From 2b68369a2b883714cea05357aa378b3a3e8ef2f6 Mon Sep 17 00:00:00 2001 From: torque Date: Mon, 6 Nov 2023 23:46:37 -0800 Subject: [PATCH] check in v3.8.2 source --- apps/nc/atomicio.c | 67 + apps/nc/atomicio.h | 39 + apps/nc/compat/base64.c | 307 + apps/nc/netcat.c | 1910 +++++ apps/nc/socks.c | 400 ++ apps/ocspcheck/compat/memmem.c | 183 + apps/ocspcheck/http.c | 777 ++ apps/ocspcheck/http.h | 92 + apps/ocspcheck/ocspcheck.c | 761 ++ apps/openssl/apps.c | 2186 ++++++ apps/openssl/apps.h | 324 + apps/openssl/apps_posix.c | 175 + apps/openssl/asn1pars.c | 470 ++ apps/openssl/ca.c | 3042 ++++++++ apps/openssl/certhash.c | 691 ++ apps/openssl/ciphers.c | 200 + apps/openssl/cms.c | 1961 +++++ apps/openssl/crl.c | 482 ++ apps/openssl/crl2p7.c | 331 + apps/openssl/dgst.c | 671 ++ apps/openssl/dh.c | 298 + apps/openssl/dhparam.c | 502 ++ apps/openssl/dsa.c | 365 + apps/openssl/dsaparam.c | 377 + apps/openssl/ec.c | 392 + apps/openssl/ecparam.c | 606 ++ apps/openssl/enc.c | 783 ++ apps/openssl/errstr.c | 117 + apps/openssl/gendh.c | 219 + apps/openssl/gendsa.c | 296 + apps/openssl/genpkey.c | 418 ++ apps/openssl/genrsa.c | 389 + apps/openssl/ocsp.c | 1532 ++++ apps/openssl/openssl.c | 736 ++ apps/openssl/passwd.c | 524 ++ apps/openssl/pkcs12.c | 1128 +++ apps/openssl/pkcs7.c | 291 + apps/openssl/pkcs8.c | 366 + apps/openssl/pkey.c | 309 + apps/openssl/pkeyparam.c | 185 + apps/openssl/pkeyutl.c | 571 ++ apps/openssl/prime.c | 201 + apps/openssl/progs.h | 48 + apps/openssl/rand.c | 182 + apps/openssl/req.c | 1878 +++++ apps/openssl/rsa.c | 411 ++ apps/openssl/rsautl.c | 402 ++ apps/openssl/s_apps.h | 151 + apps/openssl/s_cb.c | 932 +++ apps/openssl/s_client.c | 1836 +++++ apps/openssl/s_server.c | 2420 +++++++ apps/openssl/s_socket.c | 327 + apps/openssl/s_time.c | 465 ++ apps/openssl/sess_id.c | 293 + apps/openssl/smime.c | 1103 +++ apps/openssl/speed.c | 2136 ++++++ apps/openssl/spkac.c | 311 + apps/openssl/testdsa.h | 258 + apps/openssl/testrsa.h | 517 ++ apps/openssl/timeouts.h | 67 + apps/openssl/ts.c | 1252 ++++ apps/openssl/verify.c | 457 ++ apps/openssl/version.c | 249 + apps/openssl/x509.c | 1557 ++++ asm/arch/aarch64/arm64cpuid.S | 53 + asm/arch/arm/armv4cpuid.S | 69 + asm/bn/arch/amd64/bignum_add.S | 164 + asm/bn/arch/amd64/bignum_cmadd.S | 154 + asm/bn/arch/amd64/bignum_cmul.S | 137 + asm/bn/arch/amd64/bignum_mul.S | 166 + asm/bn/arch/amd64/bignum_mul_4_8_alt.S | 156 + asm/bn/arch/amd64/bignum_mul_8_16_alt.S | 243 + asm/bn/arch/amd64/bignum_sqr.S | 196 + asm/bn/arch/amd64/bignum_sqr_4_8_alt.S | 144 + asm/bn/arch/amd64/bignum_sqr_8_16_alt.S | 241 + asm/bn/arch/amd64/bignum_sub.S | 152 + asm/bn/arch/amd64/word_clz.S | 59 + asm/sparccpuid.S | 101 + cert.pem | 6400 +++++++++++++++++ crypto/aes/aes-elf-armv4.S | 1074 +++ crypto/aes/aes-elf-x86_64.S | 2558 +++++++ crypto/aes/aes-macosx-x86_64.S | 2544 +++++++ crypto/aes/aes-masm-x86_64.S | 2948 ++++++++ crypto/aes/aes-mingw64-x86_64.S | 2861 ++++++++ crypto/aes/aes-mips.S | 1336 ++++ crypto/aes/aes-mips64.S | 1340 ++++ crypto/aes/aes_cbc.c | 65 + crypto/aes/aes_cfb.c | 84 + crypto/aes/aes_core.c | 1374 ++++ crypto/aes/aes_ctr.c | 62 + crypto/aes/aes_ecb.c | 69 + crypto/aes/aes_ige.c | 194 + crypto/aes/aes_local.h | 83 + crypto/aes/aes_ofb.c | 61 + crypto/aes/aes_wrap.c | 133 + crypto/aes/aesni-elf-x86_64.S | 2575 +++++++ crypto/aes/aesni-macosx-x86_64.S | 2558 +++++++ crypto/aes/aesni-masm-x86_64.S | 3119 ++++++++ crypto/aes/aesni-mingw64-x86_64.S | 3028 ++++++++ crypto/aes/aesni-sha1-elf-x86_64.S | 1403 ++++ crypto/aes/aesni-sha1-macosx-x86_64.S | 1398 ++++ crypto/aes/aesni-sha1-masm-x86_64.S | 1616 +++++ crypto/aes/aesni-sha1-mingw64-x86_64.S | 1536 ++++ crypto/aes/bsaes-elf-x86_64.S | 2510 +++++++ crypto/aes/bsaes-macosx-x86_64.S | 2499 +++++++ crypto/aes/bsaes-masm-x86_64.S | 2803 ++++++++ crypto/aes/bsaes-mingw64-x86_64.S | 2725 +++++++ crypto/aes/vpaes-elf-x86_64.S | 846 +++ crypto/aes/vpaes-macosx-x86_64.S | 829 +++ crypto/aes/vpaes-masm-x86_64.S | 1213 ++++ crypto/aes/vpaes-mingw64-x86_64.S | 1125 +++ crypto/arm_arch.h | 59 + crypto/armcap.c | 84 + crypto/armv4cpuid.S | 69 + crypto/asn1/a_bitstr.c | 329 + crypto/asn1/a_enum.c | 393 + crypto/asn1/a_int.c | 857 +++ crypto/asn1/a_mbstr.c | 449 ++ crypto/asn1/a_object.c | 676 ++ crypto/asn1/a_octet.c | 119 + crypto/asn1/a_pkey.c | 186 + crypto/asn1/a_print.c | 127 + crypto/asn1/a_pubkey.c | 160 + crypto/asn1/a_strex.c | 603 ++ crypto/asn1/a_string.c | 450 ++ crypto/asn1/a_strnid.c | 463 ++ crypto/asn1/a_time.c | 138 + crypto/asn1/a_time_posix.c | 274 + crypto/asn1/a_time_tm.c | 626 ++ crypto/asn1/a_type.c | 360 + crypto/asn1/a_utf8.c | 199 + crypto/asn1/ameth_lib.c | 428 ++ crypto/asn1/asn1_err.c | 214 + crypto/asn1/asn1_gen.c | 804 +++ crypto/asn1/asn1_item.c | 689 ++ crypto/asn1/asn1_lib.c | 204 + crypto/asn1/asn1_local.h | 272 + crypto/asn1/asn1_old.c | 184 + crypto/asn1/asn1_old_lib.c | 216 + crypto/asn1/asn1_par.c | 386 + crypto/asn1/asn1_types.c | 305 + crypto/asn1/asn_mime.c | 1013 +++ crypto/asn1/asn_moid.c | 161 + crypto/asn1/bio_asn1.c | 453 ++ crypto/asn1/bio_ndef.c | 270 + crypto/asn1/charmap.h | 19 + crypto/asn1/p5_pbe.c | 186 + crypto/asn1/p5_pbev2.c | 374 + crypto/asn1/p8_pkey.c | 187 + crypto/asn1/t_crl.c | 145 + crypto/asn1/t_req.c | 262 + crypto/asn1/t_spki.c | 115 + crypto/asn1/t_x509.c | 515 ++ crypto/asn1/t_x509a.c | 119 + crypto/asn1/tasn_dec.c | 1260 ++++ crypto/asn1/tasn_enc.c | 682 ++ crypto/asn1/tasn_fre.c | 243 + crypto/asn1/tasn_new.c | 344 + crypto/asn1/tasn_prn.c | 612 ++ crypto/asn1/tasn_typ.c | 721 ++ crypto/asn1/tasn_utl.c | 299 + crypto/asn1/x_algor.c | 220 + crypto/asn1/x_attrib.c | 152 + crypto/asn1/x_bignum.c | 205 + crypto/asn1/x_crl.c | 763 ++ crypto/asn1/x_exten.c | 155 + crypto/asn1/x_info.c | 94 + crypto/asn1/x_long.c | 239 + crypto/asn1/x_name.c | 650 ++ crypto/asn1/x_pkey.c | 121 + crypto/asn1/x_pubkey.c | 741 ++ crypto/asn1/x_req.c | 245 + crypto/asn1/x_sig.c | 131 + crypto/asn1/x_spki.c | 174 + crypto/asn1/x_val.c | 110 + crypto/asn1/x_x509.c | 376 + crypto/asn1/x_x509a.c | 274 + crypto/bf/bf_cfb64.c | 124 + crypto/bf/bf_ecb.c | 89 + crypto/bf/bf_enc.c | 304 + crypto/bf/bf_local.h | 219 + crypto/bf/bf_ofb64.c | 111 + crypto/bf/bf_skey.c | 387 + crypto/bio/b_dump.c | 190 + crypto/bio/b_posix.c | 93 + crypto/bio/b_print.c | 111 + crypto/bio/b_sock.c | 261 + crypto/bio/b_win.c | 54 + crypto/bio/bf_buff.c | 523 ++ crypto/bio/bf_nbio.c | 255 + crypto/bio/bf_null.c | 199 + crypto/bio/bio_cb.c | 156 + crypto/bio/bio_err.c | 120 + crypto/bio/bio_lib.c | 904 +++ crypto/bio/bio_local.h | 123 + crypto/bio/bio_meth.c | 165 + crypto/bio/bss_acpt.c | 456 ++ crypto/bio/bss_bio.c | 640 ++ crypto/bio/bss_conn.c | 598 ++ crypto/bio/bss_dgram.c | 663 ++ crypto/bio/bss_fd.c | 273 + crypto/bio/bss_file.c | 325 + crypto/bio/bss_log.c | 216 + crypto/bio/bss_mem.c | 367 + crypto/bio/bss_null.c | 161 + crypto/bio/bss_sock.c | 244 + crypto/bn/arch/aarch64/bn_arch.h | 369 + crypto/bn/arch/alpha/bn_arch.h | 44 + crypto/bn/arch/amd64/bignum_add.S | 165 + crypto/bn/arch/amd64/bignum_cmadd.S | 155 + crypto/bn/arch/amd64/bignum_cmul.S | 138 + crypto/bn/arch/amd64/bignum_mul.S | 167 + crypto/bn/arch/amd64/bignum_mul_4_8_alt.S | 157 + crypto/bn/arch/amd64/bignum_mul_8_16_alt.S | 244 + crypto/bn/arch/amd64/bignum_sqr.S | 197 + crypto/bn/arch/amd64/bignum_sqr_4_8_alt.S | 145 + crypto/bn/arch/amd64/bignum_sqr_8_16_alt.S | 242 + crypto/bn/arch/amd64/bignum_sub.S | 153 + crypto/bn/arch/amd64/bn_arch.c | 131 + crypto/bn/arch/amd64/bn_arch.h | 95 + crypto/bn/arch/amd64/word_clz.S | 60 + crypto/bn/arch/arm/bn_arch.h | 73 + crypto/bn/arch/hppa/bn_arch.h | 24 + crypto/bn/arch/i386/bn_arch.h | 86 + crypto/bn/arch/m88k/bn_arch.h | 24 + crypto/bn/arch/mips64/bn_arch.h | 40 + crypto/bn/arch/powerpc/bn_arch.h | 39 + crypto/bn/arch/powerpc64/bn_arch.h | 44 + crypto/bn/arch/riscv64/bn_arch.h | 86 + crypto/bn/arch/sh/bn_arch.h | 24 + crypto/bn/arch/sparc64/bn_arch.h | 24 + crypto/bn/bn-mips.S | 2162 ++++++ crypto/bn/bn-mips64.S | 2161 ++++++ crypto/bn/bn_add.c | 341 + crypto/bn/bn_bpsw.c | 534 ++ crypto/bn/bn_const.c | 433 ++ crypto/bn/bn_convert.c | 773 ++ crypto/bn/bn_ctx.c | 161 + crypto/bn/bn_div.c | 457 ++ crypto/bn/bn_err.c | 108 + crypto/bn/bn_exp.c | 1338 ++++ crypto/bn/bn_gcd.c | 822 +++ crypto/bn/bn_internal.h | 568 ++ crypto/bn/bn_isqrt.c | 234 + crypto/bn/bn_kron.c | 195 + crypto/bn/bn_lib.c | 736 ++ crypto/bn/bn_local.h | 335 + crypto/bn/bn_mod.c | 369 + crypto/bn/bn_mod_sqrt.c | 723 ++ crypto/bn/bn_mont.c | 607 ++ crypto/bn/bn_mul.c | 370 + crypto/bn/bn_prime.c | 423 ++ crypto/bn/bn_prime.h | 14 + crypto/bn/bn_primitives.c | 65 + crypto/bn/bn_print.c | 190 + crypto/bn/bn_rand.c | 335 + crypto/bn/bn_recp.c | 260 + crypto/bn/bn_shift.c | 175 + crypto/bn/bn_small_primes.c | 265 + crypto/bn/bn_sqr.c | 305 + crypto/bn/bn_word.c | 245 + crypto/bn/modexp512-elf-x86_64.S | 1782 +++++ crypto/bn/modexp512-macosx-x86_64.S | 1774 +++++ crypto/bn/modexp512-masm-x86_64.S | 1859 +++++ crypto/bn/modexp512-mingw64-x86_64.S | 1785 +++++ crypto/bn/mont-elf-armv4.S | 148 + crypto/bn/mont-elf-x86_64.S | 1379 ++++ crypto/bn/mont-macosx-x86_64.S | 1375 ++++ crypto/bn/mont-masm-x86_64.S | 1496 ++++ crypto/bn/mont-mingw64-x86_64.S | 1414 ++++ crypto/bn/mont-mips.S | 287 + crypto/bn/mont-mips64.S | 285 + crypto/bn/mont5-elf-x86_64.S | 1182 +++ crypto/bn/mont5-macosx-x86_64.S | 1174 +++ crypto/bn/mont5-masm-x86_64.S | 1412 ++++ crypto/bn/mont5-mingw64-x86_64.S | 1329 ++++ crypto/bn/s2n_bignum.h | 856 +++ crypto/bn/s2n_bignum_internal.h | 30 + crypto/buffer/buf_err.c | 89 + crypto/buffer/buffer.c | 155 + crypto/bytestring/bs_ber.c | 269 + crypto/bytestring/bs_cbb.c | 483 ++ crypto/bytestring/bs_cbs.c | 615 ++ crypto/bytestring/bytestring.h | 564 ++ crypto/camellia/camellia.c | 566 ++ crypto/camellia/camellia.h | 125 + crypto/camellia/cmll-elf-x86_64.S | 1850 +++++ crypto/camellia/cmll-macosx-x86_64.S | 1839 +++++ crypto/camellia/cmll-masm-x86_64.S | 1966 +++++ crypto/camellia/cmll-mingw64-x86_64.S | 1884 +++++ crypto/camellia/cmll_cbc.c | 65 + crypto/camellia/cmll_cfb.c | 144 + crypto/camellia/cmll_ctr.c | 63 + crypto/camellia/cmll_ecb.c | 64 + crypto/camellia/cmll_local.h | 91 + crypto/camellia/cmll_misc.c | 81 + crypto/camellia/cmll_ofb.c | 122 + crypto/cast/c_cfb64.c | 124 + crypto/cast/c_ecb.c | 83 + crypto/cast/c_enc.c | 207 + crypto/cast/c_ofb64.c | 111 + crypto/cast/c_skey.c | 169 + crypto/cast/cast_local.h | 216 + crypto/cast/cast_s.h | 590 ++ crypto/chacha/chacha-merged.c | 323 + crypto/chacha/chacha.c | 112 + crypto/cmac/cm_ameth.c | 88 + crypto/cmac/cm_pmeth.c | 212 + crypto/cmac/cmac.c | 292 + crypto/cms/cms_asn1.c | 1622 +++++ crypto/cms/cms_att.c | 231 + crypto/cms/cms_dd.c | 150 + crypto/cms/cms_enc.c | 263 + crypto/cms/cms_env.c | 994 +++ crypto/cms/cms_err.c | 164 + crypto/cms/cms_ess.c | 408 ++ crypto/cms/cms_io.c | 176 + crypto/cms/cms_kari.c | 492 ++ crypto/cms/cms_lib.c | 776 ++ crypto/cms/cms_local.h | 477 ++ crypto/cms/cms_pwri.c | 435 ++ crypto/cms/cms_sd.c | 1029 +++ crypto/cms/cms_smime.c | 901 +++ crypto/compat/arc4random.c | 202 + crypto/compat/arc4random_aix.h | 81 + crypto/compat/arc4random_freebsd.h | 87 + crypto/compat/arc4random_hpux.h | 81 + crypto/compat/arc4random_linux.h | 88 + crypto/compat/arc4random_netbsd.h | 87 + crypto/compat/arc4random_osx.h | 81 + crypto/compat/arc4random_solaris.h | 81 + crypto/compat/arc4random_uniform.c | 56 + crypto/compat/arc4random_win.h | 78 + crypto/compat/chacha_private.h | 222 + crypto/compat/explicit_bzero.c | 19 + crypto/compat/getentropy_aix.c | 402 ++ crypto/compat/getentropy_freebsd.c | 60 + crypto/compat/getentropy_hpux.c | 396 + crypto/compat/getentropy_linux.c | 525 ++ crypto/compat/getentropy_netbsd.c | 62 + crypto/compat/getentropy_osx.c | 417 ++ crypto/compat/getentropy_solaris.c | 422 ++ crypto/compat/getentropy_win.c | 50 + crypto/compat/reallocarray.c | 38 + crypto/compat/recallocarray.c | 80 + crypto/compat/strcasecmp.c | 105 + crypto/compat/strlcat.c | 55 + crypto/compat/strlcpy.c | 50 + crypto/compat/strndup.c | 39 + crypto/compat/strnlen.c | 32 + crypto/compat/strsep.c | 70 + crypto/compat/strtonum.c | 65 + crypto/compat/timingsafe_bcmp.c | 29 + crypto/compat/timingsafe_memcmp.c | 46 + crypto/conf/conf_api.c | 286 + crypto/conf/conf_def.c | 698 ++ crypto/conf/conf_def.h | 166 + crypto/conf/conf_err.c | 105 + crypto/conf/conf_lib.c | 375 + crypto/conf/conf_mall.c | 82 + crypto/conf/conf_mod.c | 527 ++ crypto/conf/conf_sap.c | 154 + crypto/constant_time.h | 207 + crypto/cpt_err.c | 100 + crypto/cpuid-elf-x86_64.S | 141 + crypto/cpuid-macosx-x86_64.S | 137 + crypto/cpuid-masm-x86_64.S | 209 + crypto/cpuid-mingw64-x86_64.S | 137 + crypto/cryptlib.c | 384 + crypto/cryptlib.h | 84 + crypto/crypto_init.c | 102 + crypto/crypto_internal.h | 153 + crypto/crypto_lock.c | 96 + crypto/ct/ct_b64.c | 226 + crypto/ct/ct_err.c | 147 + crypto/ct/ct_local.h | 260 + crypto/ct/ct_log.c | 375 + crypto/ct/ct_oct.c | 464 ++ crypto/ct/ct_policy.c | 163 + crypto/ct/ct_prn.c | 211 + crypto/ct/ct_sct.c | 507 ++ crypto/ct/ct_sct_ctx.c | 323 + crypto/ct/ct_vfy.c | 195 + crypto/ct/ct_x509v3.c | 186 + crypto/curve25519/curve25519-generic.c | 34 + crypto/curve25519/curve25519.c | 4946 +++++++++++++ crypto/curve25519/curve25519_internal.h | 105 + crypto/cversion.c | 116 + crypto/des/cbc_cksm.c | 105 + crypto/des/cbc_enc.c | 61 + crypto/des/cfb64ede.c | 240 + crypto/des/cfb64enc.c | 122 + crypto/des/cfb_enc.c | 189 + crypto/des/des_enc.c | 392 + crypto/des/des_local.h | 398 + crypto/des/ecb3_enc.c | 84 + crypto/des/ecb_enc.c | 82 + crypto/des/ede_cbcm_enc.c | 189 + crypto/des/enc_read.c | 222 + crypto/des/enc_writ.c | 167 + crypto/des/fcrypt.c | 125 + crypto/des/fcrypt_b.c | 145 + crypto/des/ncbc_enc.c | 155 + crypto/des/ofb64ede.c | 112 + crypto/des/ofb64enc.c | 109 + crypto/des/ofb_enc.c | 133 + crypto/des/pcbc_enc.c | 116 + crypto/des/qud_cksm.c | 125 + crypto/des/rand_key.c | 68 + crypto/des/set_key.c | 407 ++ crypto/des/spr.h | 209 + crypto/des/str2key.c | 166 + crypto/des/xcbc_enc.c | 153 + crypto/dh/dh_ameth.c | 557 ++ crypto/dh/dh_asn1.c | 176 + crypto/dh/dh_check.c | 303 + crypto/dh/dh_err.c | 114 + crypto/dh/dh_gen.c | 197 + crypto/dh/dh_key.c | 247 + crypto/dh/dh_lib.c | 400 ++ crypto/dh/dh_local.h | 117 + crypto/dh/dh_pmeth.c | 266 + crypto/dsa/dsa_ameth.c | 737 ++ crypto/dsa/dsa_asn1.c | 476 ++ crypto/dsa/dsa_err.c | 104 + crypto/dsa/dsa_gen.c | 381 + crypto/dsa/dsa_key.c | 120 + crypto/dsa/dsa_lib.c | 510 ++ crypto/dsa/dsa_local.h | 120 + crypto/dsa/dsa_meth.c | 110 + crypto/dsa/dsa_ossl.c | 477 ++ crypto/dsa/dsa_pmeth.c | 350 + crypto/dsa/dsa_prn.c | 135 + crypto/ec/ec_ameth.c | 1071 +++ crypto/ec/ec_asn1.c | 1411 ++++ crypto/ec/ec_check.c | 112 + crypto/ec/ec_curve.c | 3193 ++++++++ crypto/ec/ec_cvt.c | 103 + crypto/ec/ec_err.c | 151 + crypto/ec/ec_key.c | 553 ++ crypto/ec/ec_kmeth.c | 353 + crypto/ec/ec_lib.c | 1331 ++++ crypto/ec/ec_local.h | 365 + crypto/ec/ec_mult.c | 450 ++ crypto/ec/ec_oct.c | 170 + crypto/ec/ec_pmeth.c | 524 ++ crypto/ec/ec_print.c | 182 + crypto/ec/eck_prn.c | 353 + crypto/ec/ecp_mont.c | 272 + crypto/ec/ecp_oct.c | 365 + crypto/ec/ecp_smpl.c | 1560 ++++ crypto/ec/ecx_methods.c | 897 +++ crypto/ecdh/ecdh.c | 281 + crypto/ecdsa/ecdsa.c | 774 ++ crypto/ecdsa/ecdsa_local.h | 81 + crypto/empty.c | 0 crypto/engine/engine_stubs.c | 125 + crypto/err/err.c | 1196 +++ crypto/err/err_all.c | 163 + crypto/err/err_prn.c | 122 + crypto/evp/bio_b64.c | 571 ++ crypto/evp/bio_enc.c | 418 ++ crypto/evp/bio_md.c | 280 + crypto/evp/c_all.c | 329 + crypto/evp/cipher_method_lib.c | 178 + crypto/evp/digest.c | 429 ++ crypto/evp/e_aes.c | 2602 +++++++ crypto/evp/e_aes_cbc_hmac_sha1.c | 604 ++ crypto/evp/e_bf.c | 247 + crypto/evp/e_camellia.c | 823 +++ crypto/evp/e_cast.c | 247 + crypto/evp/e_chacha.c | 76 + crypto/evp/e_chacha20poly1305.c | 618 ++ crypto/evp/e_des.c | 355 + crypto/evp/e_des3.c | 495 ++ crypto/evp/e_gost2814789.c | 315 + crypto/evp/e_idea.c | 266 + crypto/evp/e_null.c | 107 + crypto/evp/e_rc2.c | 411 ++ crypto/evp/e_rc4.c | 140 + crypto/evp/e_rc4_hmac_md5.c | 307 + crypto/evp/e_sm4.c | 267 + crypto/evp/e_xcbc_d.c | 137 + crypto/evp/encode.c | 414 ++ crypto/evp/evp_aead.c | 160 + crypto/evp/evp_enc.c | 725 ++ crypto/evp/evp_err.c | 166 + crypto/evp/evp_key.c | 212 + crypto/evp/evp_lib.c | 572 ++ crypto/evp/evp_local.h | 330 + crypto/evp/evp_pbe.c | 312 + crypto/evp/evp_pkey.c | 209 + crypto/evp/m_gost2814789.c | 113 + crypto/evp/m_gostr341194.c | 100 + crypto/evp/m_md4.c | 113 + crypto/evp/m_md5.c | 113 + crypto/evp/m_md5_sha1.c | 89 + crypto/evp/m_null.c | 103 + crypto/evp/m_ripemd.c | 113 + crypto/evp/m_sha1.c | 351 + crypto/evp/m_sha3.c | 173 + crypto/evp/m_sigver.c | 257 + crypto/evp/m_sm3.c | 68 + crypto/evp/m_streebog.c | 133 + crypto/evp/m_wp.c | 53 + crypto/evp/names.c | 240 + crypto/evp/p5_crpt.c | 163 + crypto/evp/p5_crpt2.c | 307 + crypto/evp/p_dec.c | 94 + crypto/evp/p_enc.c | 91 + crypto/evp/p_lib.c | 681 ++ crypto/evp/p_open.c | 128 + crypto/evp/p_seal.c | 124 + crypto/evp/p_sign.c | 104 + crypto/evp/p_verify.c | 97 + crypto/evp/pmeth_fn.c | 345 + crypto/evp/pmeth_gn.c | 288 + crypto/evp/pmeth_lib.c | 627 ++ crypto/ex_data.c | 637 ++ crypto/gost/gost2814789.c | 480 ++ crypto/gost/gost89_keywrap.c | 138 + crypto/gost/gost89_params.c | 246 + crypto/gost/gost89imit_ameth.c | 89 + crypto/gost/gost89imit_pmeth.c | 248 + crypto/gost/gost_asn1.c | 299 + crypto/gost/gost_asn1.h | 107 + crypto/gost/gost_err.c | 106 + crypto/gost/gost_local.h | 116 + crypto/gost/gostr341001.c | 403 ++ crypto/gost/gostr341001_ameth.c | 721 ++ crypto/gost/gostr341001_key.c | 334 + crypto/gost/gostr341001_params.c | 132 + crypto/gost/gostr341001_pmeth.c | 705 ++ crypto/gost/gostr341194.c | 278 + crypto/gost/streebog.c | 1487 ++++ crypto/hidden/crypto_namespace.h | 51 + crypto/hidden/openssl/asn1.h | 253 + crypto/hidden/openssl/asn1t.h | 33 + crypto/hidden/openssl/bio.h | 146 + crypto/hidden/openssl/bn.h | 143 + crypto/hidden/openssl/buffer.h | 34 + crypto/hidden/openssl/cast.h | 36 + crypto/hidden/openssl/chacha.h | 35 + crypto/hidden/openssl/cmac.h | 38 + crypto/hidden/openssl/cms.h | 148 + crypto/hidden/openssl/conf_api.h | 36 + crypto/hidden/openssl/crypto.h | 76 + crypto/hidden/openssl/ct.h | 85 + crypto/hidden/openssl/curve25519.h | 34 + crypto/hidden/openssl/dh.h | 74 + crypto/hidden/openssl/dsa.h | 94 + crypto/hidden/openssl/ec.h | 165 + crypto/hidden/openssl/err.h | 61 + crypto/hidden/openssl/gost.h | 71 + crypto/hidden/openssl/hkdf.h | 32 + crypto/hidden/openssl/hmac.h | 40 + crypto/hidden/openssl/idea.h | 36 + crypto/hidden/openssl/lhash.h | 44 + crypto/hidden/openssl/md4.h | 34 + crypto/hidden/openssl/md5.h | 34 + crypto/hidden/openssl/modes.h | 57 + crypto/hidden/openssl/objects.h | 59 + crypto/hidden/openssl/ocsp.h | 190 + crypto/hidden/openssl/pem.h | 149 + crypto/hidden/openssl/pkcs12.h | 106 + crypto/hidden/openssl/pkcs7.h | 129 + crypto/hidden/openssl/poly1305.h | 32 + crypto/hidden/openssl/rand.h | 33 + crypto/hidden/openssl/rc2.h | 36 + crypto/hidden/openssl/rsa.h | 141 + crypto/hidden/openssl/sha.h | 52 + crypto/hidden/openssl/sm3.h | 32 + crypto/hidden/openssl/sm4.h | 32 + crypto/hidden/openssl/stack.h | 50 + crypto/hidden/openssl/ts.h | 217 + crypto/hidden/openssl/txt_db.h | 35 + crypto/hidden/openssl/ui.h | 83 + crypto/hidden/openssl/x509.h | 283 + crypto/hidden/openssl/x509_vfy.h | 156 + crypto/hidden/openssl/x509v3.h | 265 + crypto/hkdf/hkdf.c | 123 + crypto/hmac/hm_ameth.c | 171 + crypto/hmac/hm_pmeth.c | 254 + crypto/hmac/hmac.c | 293 + crypto/hmac/hmac_local.h | 83 + crypto/idea/i_cbc.c | 176 + crypto/idea/i_cfb64.c | 124 + crypto/idea/i_ecb.c | 80 + crypto/idea/i_ofb64.c | 111 + crypto/idea/i_skey.c | 169 + crypto/idea/idea_local.h | 149 + crypto/kdf/hkdf_evp.c | 276 + crypto/kdf/kdf_err.c | 89 + crypto/lhash/lh_stats.c | 263 + crypto/lhash/lhash.c | 443 ++ crypto/malloc-wrapper.c | 205 + crypto/md32_common.h | 309 + crypto/md4/md4.c | 264 + crypto/md5/md5-elf-x86_64.S | 673 ++ crypto/md5/md5-macosx-x86_64.S | 669 ++ crypto/md5/md5-masm-x86_64.S | 753 ++ crypto/md5/md5-mingw64-x86_64.S | 679 ++ crypto/md5/md5.c | 362 + crypto/mem_clr.c | 11 + crypto/mem_dbg.c | 209 + crypto/modes/cbc128.c | 214 + crypto/modes/ccm128.c | 498 ++ crypto/modes/cfb128.c | 251 + crypto/modes/ctr128.c | 267 + crypto/modes/gcm128.c | 1355 ++++ crypto/modes/ghash-elf-armv4.S | 412 ++ crypto/modes/ghash-elf-x86_64.S | 1033 +++ crypto/modes/ghash-macosx-x86_64.S | 1027 +++ crypto/modes/ghash-masm-x86_64.S | 1256 ++++ crypto/modes/ghash-mingw64-x86_64.S | 1175 +++ crypto/modes/modes_local.h | 123 + crypto/modes/ofb128.c | 124 + crypto/modes/xts128.c | 197 + crypto/o_fips.c | 76 + crypto/o_init.c | 10 + crypto/o_str.c | 21 + crypto/objects/o_names.c | 363 + crypto/objects/obj_dat.c | 698 ++ crypto/objects/obj_dat.h | 5835 +++++++++++++++ crypto/objects/obj_err.c | 91 + crypto/objects/obj_lib.c | 135 + crypto/objects/obj_xref.c | 312 + crypto/ocsp/ocsp_asn.c | 1051 +++ crypto/ocsp/ocsp_cl.c | 469 ++ crypto/ocsp/ocsp_err.c | 119 + crypto/ocsp/ocsp_ext.c | 612 ++ crypto/ocsp/ocsp_ht.c | 469 ++ crypto/ocsp/ocsp_lib.c | 249 + crypto/ocsp/ocsp_local.h | 291 + crypto/ocsp/ocsp_prn.c | 319 + crypto/ocsp/ocsp_srv.c | 285 + crypto/ocsp/ocsp_vfy.c | 475 ++ crypto/pem/pem_all.c | 704 ++ crypto/pem/pem_err.c | 117 + crypto/pem/pem_info.c | 387 + crypto/pem/pem_lib.c | 873 +++ crypto/pem/pem_oth.c | 88 + crypto/pem/pem_pk8.c | 324 + crypto/pem/pem_pkey.c | 267 + crypto/pem/pem_sign.c | 108 + crypto/pem/pem_x509.c | 98 + crypto/pem/pem_xaux.c | 98 + crypto/pem/pvkfmt.c | 944 +++ crypto/pkcs12/p12_add.c | 220 + crypto/pkcs12/p12_asn.c | 491 ++ crypto/pkcs12/p12_attr.c | 164 + crypto/pkcs12/p12_crpt.c | 123 + crypto/pkcs12/p12_crt.c | 357 + crypto/pkcs12/p12_decr.c | 189 + crypto/pkcs12/p12_init.c | 101 + crypto/pkcs12/p12_key.c | 197 + crypto/pkcs12/p12_kiss.c | 299 + crypto/pkcs12/p12_mutl.c | 263 + crypto/pkcs12/p12_npas.c | 249 + crypto/pkcs12/p12_p8d.c | 71 + crypto/pkcs12/p12_p8e.c | 103 + crypto/pkcs12/p12_sbag.c | 240 + crypto/pkcs12/p12_utl.c | 157 + crypto/pkcs12/pk12err.c | 111 + crypto/pkcs12/pkcs12_local.h | 101 + crypto/pkcs7/pk7_asn1.c | 1041 +++ crypto/pkcs7/pk7_attr.c | 178 + crypto/pkcs7/pk7_doit.c | 1264 ++++ crypto/pkcs7/pk7_lib.c | 674 ++ crypto/pkcs7/pk7_mime.c | 107 + crypto/pkcs7/pk7_smime.c | 599 ++ crypto/pkcs7/pkcs7err.c | 143 + crypto/poly1305/poly1305-donna.c | 321 + crypto/poly1305/poly1305.c | 41 + crypto/rand/rand_err.c | 94 + crypto/rand/rand_lib.c | 104 + crypto/rand/randfile.c | 143 + crypto/rc2/rc2_cbc.c | 236 + crypto/rc2/rc2_ecb.c | 91 + crypto/rc2/rc2_local.h | 155 + crypto/rc2/rc2_skey.c | 142 + crypto/rc2/rc2cfb64.c | 124 + crypto/rc2/rc2ofb64.c | 111 + crypto/rc4/rc4-elf-x86_64.S | 598 ++ crypto/rc4/rc4-macosx-x86_64.S | 592 ++ crypto/rc4/rc4-masm-x86_64.S | 691 ++ crypto/rc4/rc4-md5-elf-x86_64.S | 1264 ++++ crypto/rc4/rc4-md5-macosx-x86_64.S | 1260 ++++ crypto/rc4/rc4-md5-masm-x86_64.S | 1347 ++++ crypto/rc4/rc4-md5-mingw64-x86_64.S | 1273 ++++ crypto/rc4/rc4-mingw64-x86_64.S | 615 ++ crypto/rc4/rc4_enc.c | 254 + crypto/rc4/rc4_local.h | 5 + crypto/rc4/rc4_skey.c | 99 + crypto/ripemd/ripemd.c | 442 ++ crypto/rsa/rsa_ameth.c | 1143 +++ crypto/rsa/rsa_asn1.c | 422 ++ crypto/rsa/rsa_blinding.c | 361 + crypto/rsa/rsa_chk.c | 223 + crypto/rsa/rsa_eay.c | 902 +++ crypto/rsa/rsa_err.c | 158 + crypto/rsa/rsa_gen.c | 257 + crypto/rsa/rsa_lib.c | 460 ++ crypto/rsa/rsa_local.h | 165 + crypto/rsa/rsa_meth.c | 309 + crypto/rsa/rsa_none.c | 98 + crypto/rsa/rsa_oaep.c | 363 + crypto/rsa/rsa_pk1.c | 217 + crypto/rsa/rsa_pmeth.c | 879 +++ crypto/rsa/rsa_prn.c | 99 + crypto/rsa/rsa_pss.c | 288 + crypto/rsa/rsa_saos.c | 143 + crypto/rsa/rsa_sign.c | 280 + crypto/rsa/rsa_x931.c | 164 + crypto/sha/sha1-elf-armv4.S | 455 ++ crypto/sha/sha1-elf-x86_64.S | 2494 +++++++ crypto/sha/sha1-macosx-x86_64.S | 2488 +++++++ crypto/sha/sha1-masm-x86_64.S | 2746 +++++++ crypto/sha/sha1-mingw64-x86_64.S | 2664 +++++++ crypto/sha/sha1-mips.S | 1663 +++++ crypto/sha/sha1-mips64.S | 1663 +++++ crypto/sha/sha1.c | 476 ++ crypto/sha/sha256-elf-armv4.S | 1520 ++++ crypto/sha/sha256-elf-x86_64.S | 1785 +++++ crypto/sha/sha256-macosx-x86_64.S | 1779 +++++ crypto/sha/sha256-masm-x86_64.S | 1864 +++++ crypto/sha/sha256-mingw64-x86_64.S | 1790 +++++ crypto/sha/sha256-mips.S | 1997 +++++ crypto/sha/sha256-mips64.S | 1998 +++++ crypto/sha/sha256.c | 499 ++ crypto/sha/sha3.c | 193 + crypto/sha/sha3_internal.h | 81 + crypto/sha/sha512-elf-armv4.S | 1786 +++++ crypto/sha/sha512-elf-x86_64.S | 1809 +++++ crypto/sha/sha512-macosx-x86_64.S | 1803 +++++ crypto/sha/sha512-masm-x86_64.S | 1888 +++++ crypto/sha/sha512-mingw64-x86_64.S | 1814 +++++ crypto/sha/sha512-mips.S | 2165 ++++++ crypto/sha/sha512-mips64.S | 2166 ++++++ crypto/sha/sha512.c | 580 ++ crypto/sha/sha_internal.h | 36 + crypto/sm3/sm3.c | 277 + crypto/sm4/sm4.c | 266 + crypto/stack/stack.c | 372 + crypto/ts/ts_asn1.c | 1077 +++ crypto/ts/ts_conf.c | 548 ++ crypto/ts/ts_err.c | 124 + crypto/ts/ts_lib.c | 158 + crypto/ts/ts_local.h | 316 + crypto/ts/ts_req_print.c | 105 + crypto/ts/ts_req_utils.c | 281 + crypto/ts/ts_rsp_print.c | 306 + crypto/ts/ts_rsp_sign.c | 1058 +++ crypto/ts/ts_rsp_utils.c | 503 ++ crypto/ts/ts_rsp_verify.c | 847 +++ crypto/ts/ts_verify_ctx.c | 236 + crypto/txt_db/txt_db.c | 378 + crypto/ui/ui_err.c | 96 + crypto/ui/ui_lib.c | 907 +++ crypto/ui/ui_local.h | 152 + crypto/ui/ui_null.c | 18 + crypto/ui/ui_openssl.c | 398 + crypto/ui/ui_openssl_win.c | 337 + crypto/ui/ui_util.c | 98 + crypto/whrlpool/wp-elf-x86_64.S | 864 +++ crypto/whrlpool/wp-macosx-x86_64.S | 859 +++ crypto/whrlpool/wp-masm-x86_64.S | 943 +++ crypto/whrlpool/wp-mingw64-x86_64.S | 869 +++ crypto/whrlpool/wp_block.c | 629 ++ crypto/whrlpool/wp_dgst.c | 268 + crypto/whrlpool/wp_local.h | 11 + crypto/x509/by_dir.c | 413 ++ crypto/x509/by_file.c | 273 + crypto/x509/by_mem.c | 141 + crypto/x509/x509_addr.c | 2061 ++++++ crypto/x509/x509_akey.c | 237 + crypto/x509/x509_akeya.c | 128 + crypto/x509/x509_alt.c | 782 ++ crypto/x509/x509_asid.c | 1203 ++++ crypto/x509/x509_att.c | 413 ++ crypto/x509/x509_bcons.c | 203 + crypto/x509/x509_bitst.c | 220 + crypto/x509/x509_cmp.c | 425 ++ crypto/x509/x509_conf.c | 591 ++ crypto/x509/x509_constraints.c | 1294 ++++ crypto/x509/x509_cpols.c | 764 ++ crypto/x509/x509_crld.c | 828 +++ crypto/x509/x509_d2.c | 131 + crypto/x509/x509_def.c | 104 + crypto/x509/x509_err.c | 213 + crypto/x509/x509_ext.c | 262 + crypto/x509/x509_extku.c | 221 + crypto/x509/x509_genn.c | 537 ++ crypto/x509/x509_ia5.c | 238 + crypto/x509/x509_info.c | 317 + crypto/x509/x509_int.c | 110 + crypto/x509/x509_internal.h | 141 + crypto/x509/x509_issuer_cache.c | 193 + crypto/x509/x509_issuer_cache.h | 48 + crypto/x509/x509_lib.c | 436 ++ crypto/x509/x509_local.h | 388 + crypto/x509/x509_lu.c | 880 +++ crypto/x509/x509_ncons.c | 561 ++ crypto/x509/x509_obj.c | 182 + crypto/x509/x509_ocsp.c | 382 + crypto/x509/x509_pcons.c | 196 + crypto/x509/x509_pku.c | 158 + crypto/x509/x509_pmaps.c | 237 + crypto/x509/x509_policy.c | 1019 +++ crypto/x509/x509_prn.c | 231 + crypto/x509/x509_purp.c | 1077 +++ crypto/x509/x509_r2x.c | 117 + crypto/x509/x509_req.c | 356 + crypto/x509/x509_set.c | 262 + crypto/x509/x509_skey.c | 165 + crypto/x509/x509_trs.c | 398 + crypto/x509/x509_txt.c | 196 + crypto/x509/x509_utl.c | 1486 ++++ crypto/x509/x509_v3.c | 315 + crypto/x509/x509_verify.c | 1282 ++++ crypto/x509/x509_verify.h | 43 + crypto/x509/x509_vfy.c | 2719 +++++++ crypto/x509/x509_vpm.c | 729 ++ crypto/x509/x509cset.c | 233 + crypto/x509/x509name.c | 452 ++ crypto/x509/x509rset.c | 110 + crypto/x509/x509spki.c | 136 + crypto/x509/x509type.c | 130 + crypto/x509/x_all.c | 541 ++ crypto/x86_arch.h | 90 + include/arch/aarch64/opensslconf.h | 154 + include/arch/alpha/opensslconf.h | 152 + include/arch/amd64/opensslconf.h | 149 + include/arch/arm/opensslconf.h | 154 + include/arch/hppa/opensslconf.h | 154 + include/arch/i386/opensslconf.h | 154 + include/arch/m88k/opensslconf.h | 154 + include/arch/mips64/opensslconf.h | 154 + include/arch/powerpc/opensslconf.h | 154 + include/arch/powerpc64/opensslconf.h | 149 + include/arch/riscv64/opensslconf.h | 154 + include/arch/sh/opensslconf.h | 154 + include/arch/sparc64/opensslconf.h | 154 + include/openssl/aes.h | 124 + include/openssl/asn1.h | 1175 +++ include/openssl/asn1t.h | 907 +++ include/openssl/bio.h | 747 ++ include/openssl/blowfish.h | 110 + include/openssl/bn.h | 534 ++ include/openssl/buffer.h | 102 + include/openssl/camellia.h | 125 + include/openssl/cast.h | 103 + include/openssl/chacha.h | 58 + include/openssl/cmac.h | 82 + include/openssl/cms.h | 535 ++ include/openssl/comp.h | 7 + include/openssl/conf.h | 246 + include/openssl/conf_api.h | 88 + include/openssl/crypto.h | 548 ++ include/openssl/ct.h | 567 ++ include/openssl/curve25519.h | 104 + include/openssl/des.h | 215 + include/openssl/dh.h | 249 + include/openssl/dsa.h | 282 + include/openssl/dtls1.h | 107 + include/openssl/ec.h | 722 ++ include/openssl/ecdh.h | 6 + include/openssl/ecdsa.h | 6 + include/openssl/engine.h | 817 +++ include/openssl/err.h | 411 ++ include/openssl/evp.h | 1515 ++++ include/openssl/gost.h | 262 + include/openssl/hkdf.h | 65 + include/openssl/hmac.h | 98 + include/openssl/idea.h | 99 + include/openssl/kdf.h | 111 + include/openssl/lhash.h | 235 + include/openssl/md4.h | 102 + include/openssl/md5.h | 107 + include/openssl/modes.h | 118 + include/openssl/obj_mac.h | 4630 ++++++++++++ include/openssl/objects.h | 163 + include/openssl/ocsp.h | 484 ++ include/openssl/opensslfeatures.h | 133 + include/openssl/opensslv.h | 18 + include/openssl/ossl_typ.h | 204 + include/openssl/pem.h | 596 ++ include/openssl/pem2.h | 71 + include/openssl/pkcs12.h | 344 + include/openssl/pkcs7.h | 524 ++ include/openssl/poly1305.h | 49 + include/openssl/rand.h | 123 + include/openssl/rc2.h | 100 + include/openssl/rc4.h | 88 + include/openssl/ripemd.h | 104 + include/openssl/rsa.h | 609 ++ include/openssl/safestack.h | 1971 +++++ include/openssl/sha.h | 189 + include/openssl/sm3.h | 53 + include/openssl/sm4.h | 51 + include/openssl/srtp.h | 146 + include/openssl/ssl.h | 2362 ++++++ include/openssl/ssl2.h | 153 + include/openssl/ssl23.h | 82 + include/openssl/ssl3.h | 455 ++ include/openssl/stack.h | 107 + include/openssl/tls1.h | 780 ++ include/openssl/ts.h | 665 ++ include/openssl/txt_db.h | 112 + include/openssl/ui.h | 403 ++ include/openssl/ui_compat.h | 65 + include/openssl/whrlpool.h | 41 + include/openssl/x509.h | 1203 ++++ include/openssl/x509_vfy.h | 477 ++ include/openssl/x509v3.h | 1119 +++ include/pqueue.h | 93 + include/tls.h | 230 + ssl/bio_ssl.c | 596 ++ ssl/bs_ber.c | 269 + ssl/bs_cbb.c | 483 ++ ssl/bs_cbs.c | 615 ++ ssl/bytestring.h | 564 ++ ssl/d1_both.c | 1198 +++ ssl/d1_lib.c | 435 ++ ssl/d1_pkt.c | 1116 +++ ssl/d1_srtp.c | 266 + ssl/dtls_local.h | 232 + ssl/empty.c | 0 ssl/hidden/openssl/srtp.h | 33 + ssl/hidden/openssl/ssl.h | 384 + ssl/hidden/openssl/tls1.h | 32 + ssl/hidden/ssl_namespace.h | 43 + ssl/pqueue.c | 201 + ssl/s3_cbc.c | 628 ++ ssl/s3_lib.c | 2827 ++++++++ ssl/srtp.h | 146 + ssl/ssl_algs.c | 125 + ssl/ssl_asn1.c | 420 ++ ssl/ssl_both.c | 580 ++ ssl/ssl_cert.c | 741 ++ ssl/ssl_ciph.c | 1768 +++++ ssl/ssl_ciphers.c | 286 + ssl/ssl_clnt.c | 2678 +++++++ ssl/ssl_err.c | 673 ++ ssl/ssl_init.c | 52 + ssl/ssl_kex.c | 422 ++ ssl/ssl_lib.c | 3695 ++++++++++ ssl/ssl_local.h | 1531 ++++ ssl/ssl_methods.c | 569 ++ ssl/ssl_packet.c | 292 + ssl/ssl_pkt.c | 1313 ++++ ssl/ssl_rsa.c | 769 ++ ssl/ssl_seclevel.c | 473 ++ ssl/ssl_sess.c | 1388 ++++ ssl/ssl_sigalgs.c | 388 + ssl/ssl_sigalgs.h | 79 + ssl/ssl_srvr.c | 2629 +++++++ ssl/ssl_stat.c | 797 ++ ssl/ssl_tlsext.c | 2519 +++++++ ssl/ssl_tlsext.h | 48 + ssl/ssl_transcript.c | 197 + ssl/ssl_txt.c | 201 + ssl/ssl_versions.c | 373 + ssl/t1_enc.c | 415 ++ ssl/t1_lib.c | 1132 +++ ssl/tls12_internal.h | 29 + ssl/tls12_key_schedule.c | 295 + ssl/tls12_lib.c | 118 + ssl/tls12_record_layer.c | 1342 ++++ ssl/tls13_client.c | 1060 +++ ssl/tls13_error.c | 99 + ssl/tls13_handshake.c | 721 ++ ssl/tls13_handshake.h | 54 + ssl/tls13_handshake_msg.c | 188 + ssl/tls13_internal.h | 443 ++ ssl/tls13_key_schedule.c | 458 ++ ssl/tls13_legacy.c | 556 ++ ssl/tls13_lib.c | 701 ++ ssl/tls13_quic.c | 181 + ssl/tls13_record.c | 186 + ssl/tls13_record.h | 66 + ssl/tls13_record_layer.c | 1222 ++++ ssl/tls13_server.c | 1095 +++ ssl/tls_buffer.c | 257 + ssl/tls_content.c | 164 + ssl/tls_content.h | 50 + ssl/tls_internal.h | 101 + ssl/tls_key_share.c | 484 ++ ssl/tls_lib.c | 68 + tests/aeadtest.c | 591 ++ tests/aeadtests.txt | 86 + tests/aes_128_gcm_tests.txt | 532 ++ tests/aes_192_gcm_tests.txt | 44 + tests/aes_256_gcm_tests.txt | 467 ++ tests/aes_test.c | 979 +++ tests/aes_wrap.c | 187 + tests/apitest.c | 374 + tests/arc4randomforktest.c | 171 + tests/asn1_string_to_utf8.c | 134 + tests/asn1api.c | 415 ++ tests/asn1basic.c | 1137 +++ tests/asn1complex.c | 324 + tests/asn1evp.c | 150 + tests/asn1object.c | 495 ++ tests/asn1oct.c | 280 + tests/asn1string_copy.c | 119 + tests/asn1test.c | 478 ++ tests/asn1time.c | 611 ++ tests/asn1x509.c | 842 +++ tests/base64test.c | 486 ++ tests/bf_test.c | 1368 ++++ tests/bio_asn1.c | 232 + tests/bio_chain.c | 515 ++ tests/bio_host.c | 154 + tests/bio_mem.c | 345 + tests/bn_add_sub.c | 249 + tests/bn_cmp.c | 360 + tests/bn_convert.c | 628 ++ tests/bn_gcd.c | 3670 ++++++++++ tests/bn_general.c | 182 + tests/bn_isqrt.c | 330 + tests/bn_mod_exp.c | 575 ++ tests/bn_mod_inverse.c | 387 + tests/bn_mod_sqrt.c | 4533 ++++++++++++ tests/bn_mont.c | 83 + tests/bn_mul_div.c | 500 ++ tests/bn_primes.c | 148 + tests/bn_print.c | 305 + tests/bn_shift.c | 659 ++ tests/bn_test.c | 1916 +++++ tests/bn_to_string.c | 252 + tests/bn_unit.c | 307 + tests/bn_word.c | 617 ++ tests/buffertest.c | 364 + tests/bytestringtest.c | 968 +++ tests/ca-int-ecdsa.crl | 8 + tests/ca-int-ecdsa.pem | 13 + tests/ca-int-rsa.crl | 11 + tests/ca-int-rsa.pem | 22 + tests/ca-root-ecdsa.pem | 13 + tests/ca-root-rsa.pem | 22 + tests/ca.pem | 45 + tests/callback.c | 428 ++ tests/callbackfailures.c | 298 + tests/casttest.c | 197 + tests/chacha20_poly1305_tests.txt | 576 ++ tests/chachatest.c | 509 ++ tests/cipher_list.c | 231 + tests/cipherstest.c | 531 ++ tests/client.c | 285 + tests/client.pem | 51 + tests/client1-ecdsa-chain.pem | 27 + tests/client1-ecdsa.pem | 19 + tests/client1-rsa-chain.pem | 44 + tests/client1-rsa.pem | 50 + tests/client2-ecdsa-chain.pem | 26 + tests/client2-ecdsa.pem | 18 + tests/client2-rsa-chain.pem | 44 + tests/client2-rsa.pem | 50 + tests/client3-ecdsa-chain.pem | 26 + tests/client3-ecdsa.pem | 18 + tests/client3-rsa-chain.pem | 44 + tests/client3-rsa.pem | 50 + tests/clienttest.c | 754 ++ tests/cmstest.c | 326 + tests/compat/memmem.c | 183 + tests/configtest.c | 173 + tests/constraints.c | 584 ++ tests/ctlog.conf | 5 + tests/cttest.c | 491 ++ tests/destest.c | 884 +++ tests/dhtest.c | 170 + tests/dsatest.c | 235 + tests/dtlstest.c | 1077 +++ tests/ec_asn1_test.c | 206 + tests/ec_point_conversion.c | 545 ++ tests/ecc_cdh.c | 2506 +++++++ tests/ecdhtest.c | 418 ++ tests/ecdsatest.c | 348 + tests/ectest.c | 781 ++ tests/ed25519test.c | 474 ++ tests/empty.c | 0 tests/enginetest.c | 253 + tests/evp_ecx_test.c | 831 +++ tests/evp_pkey_check.c | 397 + tests/evp_pkey_cleanup.c | 83 + tests/evp_test.c | 419 ++ tests/evptest.c | 470 ++ tests/evptests.txt | 384 + tests/expirecallback.c | 321 + tests/explicit_bzero.c | 225 + tests/exportertest.c | 664 ++ tests/freenull.c | 239 + tests/freenull.c.body | 182 + tests/gcm128test.c | 926 +++ tests/gost2814789t.c | 1491 ++++ tests/handshake_table.c | 550 ++ tests/hkdf_test.c | 300 + tests/hmactest.c | 335 + tests/ideatest.c | 221 + tests/igetest.c | 370 + tests/init_pledge.c | 34 + tests/key_schedule.c | 317 + tests/keypairtest.c | 211 + tests/letsencrypt-r3.crt | 30 + tests/libressl.org.crt | 39 + tests/md_test.c | 301 + tests/objectstest.c | 588 ++ tests/ocsp_test.c | 159 + tests/pbkdf2.c | 214 + tests/pkcs7test.c | 301 + tests/policy.c | 667 ++ tests/policy_intermediate.pem | 11 + tests/policy_intermediate_any.pem | 11 + tests/policy_intermediate_duplicate.pem | 12 + tests/policy_intermediate_invalid.pem | 11 + tests/policy_intermediate_mapped.pem | 17 + tests/policy_intermediate_mapped_any.pem | 15 + tests/policy_intermediate_mapped_oid3.pem | 15 + tests/policy_intermediate_require.pem | 12 + tests/policy_intermediate_require1.pem | 12 + tests/policy_intermediate_require2.pem | 12 + .../policy_intermediate_require_duplicate.pem | 12 + ...olicy_intermediate_require_no_policies.pem | 11 + tests/policy_leaf.pem | 11 + tests/policy_leaf_any.pem | 11 + tests/policy_leaf_duplicate.pem | 12 + tests/policy_leaf_invalid.pem | 11 + tests/policy_leaf_none.pem | 10 + tests/policy_leaf_oid1.pem | 11 + tests/policy_leaf_oid2.pem | 11 + tests/policy_leaf_oid3.pem | 11 + tests/policy_leaf_oid4.pem | 11 + tests/policy_leaf_oid5.pem | 11 + tests/policy_leaf_require.pem | 12 + tests/policy_leaf_require1.pem | 12 + tests/policy_root.pem | 10 + tests/policy_root2.pem | 10 + tests/policy_root_cross_inhibit_mapping.pem | 11 + tests/poly1305test.c | 169 + tests/pq_expected.txt | 3 + tests/pq_test.c | 118 + tests/quictest.c | 339 + tests/randtest.c | 204 + tests/rc2_test.c | 917 +++ tests/rc4_test.c | 479 ++ tests/record_layer_test.c | 306 + tests/recordtest.c | 555 ++ tests/rfc3779.c | 1965 +++++ tests/rfc5280time.c | 390 + tests/rmd_test.c | 201 + tests/rsa_test.c | 472 ++ tests/server.c | 321 + tests/server.pem | 51 + tests/server1-ecdsa-chain.pem | 26 + tests/server1-ecdsa.pem | 18 + tests/server1-rsa-chain.pem | 44 + tests/server1-rsa.pem | 50 + tests/server2-ecdsa-chain.pem | 26 + tests/server2-ecdsa.pem | 18 + tests/server2-rsa-chain.pem | 44 + tests/server2-rsa.pem | 50 + tests/server3-ecdsa-chain.pem | 26 + tests/server3-ecdsa.pem | 18 + tests/server3-rsa-chain.pem | 44 + tests/server3-rsa.pem | 50 + tests/servertest.c | 209 + tests/sha_test.c | 936 +++ tests/signertest.c | 471 ++ tests/sm2crypttest.c | 191 + tests/sm2evptest.c | 256 + tests/sm2sigtest.c | 170 + tests/sm3test.c | 99 + tests/sm4test.c | 108 + tests/ssl_get_shared_ciphers.c | 482 ++ tests/ssl_methods.c | 267 + tests/ssl_set_alpn_protos.c | 204 + tests/ssl_verify_param.c | 99 + tests/ssl_versions.c | 922 +++ tests/ssltest.c | 1535 ++++ tests/string_table.c | 128 + tests/tests.h | 44 + tests/testssl | 162 + tests/timingsafe.c | 68 + tests/tls_ext_alpn.c | 442 ++ tests/tls_prf.c | 251 + tests/tlsexttest.c | 4613 ++++++++++++ tests/tlslegacytest.c | 625 ++ tests/tlstest.c | 555 ++ tests/utf8test.c | 319 + tests/util.c | 145 + tests/valid_handshakes_terminate.c | 54 + tests/verify.c | 373 + tests/verifytest.c | 526 ++ tests/wycheproof-primes.c | 61 + tests/x25519test.c | 141 + tests/x509_asn1.c | 601 ++ tests/x509_info.c | 184 + tests/x509attribute.c | 105 + tests/x509name.c | 62 + tests/x509req_ext.c | 161 + tests/xchacha20_poly1305_tests.txt | 366 + tls/empty.c | 0 tls/tls.c | 931 +++ tls/tls_bio_cb.c | 171 + tls/tls_client.c | 485 ++ tls/tls_config.c | 930 +++ tls/tls_conninfo.c | 344 + tls/tls_internal.h | 326 + tls/tls_keypair.c | 169 + tls/tls_ocsp.c | 463 ++ tls/tls_peer.c | 99 + tls/tls_server.c | 468 ++ tls/tls_signer.c | 451 ++ tls/tls_util.c | 226 + tls/tls_verify.c | 331 + 1216 files changed, 563118 insertions(+) create mode 100644 apps/nc/atomicio.c create mode 100644 apps/nc/atomicio.h create mode 100644 apps/nc/compat/base64.c create mode 100644 apps/nc/netcat.c create mode 100644 apps/nc/socks.c create mode 100644 apps/ocspcheck/compat/memmem.c create mode 100644 apps/ocspcheck/http.c create mode 100644 apps/ocspcheck/http.h create mode 100644 apps/ocspcheck/ocspcheck.c create mode 100644 apps/openssl/apps.c create mode 100644 apps/openssl/apps.h create mode 100644 apps/openssl/apps_posix.c create mode 100644 apps/openssl/asn1pars.c create mode 100644 apps/openssl/ca.c create mode 100644 apps/openssl/certhash.c create mode 100644 apps/openssl/ciphers.c create mode 100644 apps/openssl/cms.c create mode 100644 apps/openssl/crl.c create mode 100644 apps/openssl/crl2p7.c create mode 100644 apps/openssl/dgst.c create mode 100644 apps/openssl/dh.c create mode 100644 apps/openssl/dhparam.c create mode 100644 apps/openssl/dsa.c create mode 100644 apps/openssl/dsaparam.c create mode 100644 apps/openssl/ec.c create mode 100644 apps/openssl/ecparam.c create mode 100644 apps/openssl/enc.c create mode 100644 apps/openssl/errstr.c create mode 100644 apps/openssl/gendh.c create mode 100644 apps/openssl/gendsa.c create mode 100644 apps/openssl/genpkey.c create mode 100644 apps/openssl/genrsa.c create mode 100644 apps/openssl/ocsp.c create mode 100644 apps/openssl/openssl.c create mode 100644 apps/openssl/passwd.c create mode 100644 apps/openssl/pkcs12.c create mode 100644 apps/openssl/pkcs7.c create mode 100644 apps/openssl/pkcs8.c create mode 100644 apps/openssl/pkey.c create mode 100644 apps/openssl/pkeyparam.c create mode 100644 apps/openssl/pkeyutl.c create mode 100644 apps/openssl/prime.c create mode 100644 apps/openssl/progs.h create mode 100644 apps/openssl/rand.c create mode 100644 apps/openssl/req.c create mode 100644 apps/openssl/rsa.c create mode 100644 apps/openssl/rsautl.c create mode 100644 apps/openssl/s_apps.h create mode 100644 apps/openssl/s_cb.c create mode 100644 apps/openssl/s_client.c create mode 100644 apps/openssl/s_server.c create mode 100644 apps/openssl/s_socket.c create mode 100644 apps/openssl/s_time.c create mode 100644 apps/openssl/sess_id.c create mode 100644 apps/openssl/smime.c create mode 100644 apps/openssl/speed.c create mode 100644 apps/openssl/spkac.c create mode 100644 apps/openssl/testdsa.h create mode 100644 apps/openssl/testrsa.h create mode 100644 apps/openssl/timeouts.h create mode 100644 apps/openssl/ts.c create mode 100644 apps/openssl/verify.c create mode 100644 apps/openssl/version.c create mode 100644 apps/openssl/x509.c create mode 100644 asm/arch/aarch64/arm64cpuid.S create mode 100644 asm/arch/arm/armv4cpuid.S create mode 100644 asm/bn/arch/amd64/bignum_add.S create mode 100644 asm/bn/arch/amd64/bignum_cmadd.S create mode 100644 asm/bn/arch/amd64/bignum_cmul.S create mode 100644 asm/bn/arch/amd64/bignum_mul.S create mode 100644 asm/bn/arch/amd64/bignum_mul_4_8_alt.S create mode 100644 asm/bn/arch/amd64/bignum_mul_8_16_alt.S create mode 100644 asm/bn/arch/amd64/bignum_sqr.S create mode 100644 asm/bn/arch/amd64/bignum_sqr_4_8_alt.S create mode 100644 asm/bn/arch/amd64/bignum_sqr_8_16_alt.S create mode 100644 asm/bn/arch/amd64/bignum_sub.S create mode 100644 asm/bn/arch/amd64/word_clz.S create mode 100644 asm/sparccpuid.S create mode 100644 cert.pem create mode 100644 crypto/aes/aes-elf-armv4.S create mode 100644 crypto/aes/aes-elf-x86_64.S create mode 100644 crypto/aes/aes-macosx-x86_64.S create mode 100644 crypto/aes/aes-masm-x86_64.S create mode 100644 crypto/aes/aes-mingw64-x86_64.S create mode 100644 crypto/aes/aes-mips.S create mode 100644 crypto/aes/aes-mips64.S create mode 100644 crypto/aes/aes_cbc.c create mode 100644 crypto/aes/aes_cfb.c create mode 100644 crypto/aes/aes_core.c create mode 100644 crypto/aes/aes_ctr.c create mode 100644 crypto/aes/aes_ecb.c create mode 100644 crypto/aes/aes_ige.c create mode 100644 crypto/aes/aes_local.h create mode 100644 crypto/aes/aes_ofb.c create mode 100644 crypto/aes/aes_wrap.c create mode 100644 crypto/aes/aesni-elf-x86_64.S create mode 100644 crypto/aes/aesni-macosx-x86_64.S create mode 100644 crypto/aes/aesni-masm-x86_64.S create mode 100644 crypto/aes/aesni-mingw64-x86_64.S create mode 100644 crypto/aes/aesni-sha1-elf-x86_64.S create mode 100644 crypto/aes/aesni-sha1-macosx-x86_64.S create mode 100644 crypto/aes/aesni-sha1-masm-x86_64.S create mode 100644 crypto/aes/aesni-sha1-mingw64-x86_64.S create mode 100644 crypto/aes/bsaes-elf-x86_64.S create mode 100644 crypto/aes/bsaes-macosx-x86_64.S create mode 100644 crypto/aes/bsaes-masm-x86_64.S create mode 100644 crypto/aes/bsaes-mingw64-x86_64.S create mode 100644 crypto/aes/vpaes-elf-x86_64.S create mode 100644 crypto/aes/vpaes-macosx-x86_64.S create mode 100644 crypto/aes/vpaes-masm-x86_64.S create mode 100644 crypto/aes/vpaes-mingw64-x86_64.S create mode 100644 crypto/arm_arch.h create mode 100644 crypto/armcap.c create mode 100644 crypto/armv4cpuid.S create mode 100644 crypto/asn1/a_bitstr.c create mode 100644 crypto/asn1/a_enum.c create mode 100644 crypto/asn1/a_int.c create mode 100644 crypto/asn1/a_mbstr.c create mode 100644 crypto/asn1/a_object.c create mode 100644 crypto/asn1/a_octet.c create mode 100644 crypto/asn1/a_pkey.c create mode 100644 crypto/asn1/a_print.c create mode 100644 crypto/asn1/a_pubkey.c create mode 100644 crypto/asn1/a_strex.c create mode 100644 crypto/asn1/a_string.c create mode 100644 crypto/asn1/a_strnid.c create mode 100644 crypto/asn1/a_time.c create mode 100644 crypto/asn1/a_time_posix.c create mode 100644 crypto/asn1/a_time_tm.c create mode 100644 crypto/asn1/a_type.c create mode 100644 crypto/asn1/a_utf8.c create mode 100644 crypto/asn1/ameth_lib.c create mode 100644 crypto/asn1/asn1_err.c create mode 100644 crypto/asn1/asn1_gen.c create mode 100644 crypto/asn1/asn1_item.c create mode 100644 crypto/asn1/asn1_lib.c create mode 100644 crypto/asn1/asn1_local.h create mode 100644 crypto/asn1/asn1_old.c create mode 100644 crypto/asn1/asn1_old_lib.c create mode 100644 crypto/asn1/asn1_par.c create mode 100644 crypto/asn1/asn1_types.c create mode 100644 crypto/asn1/asn_mime.c create mode 100644 crypto/asn1/asn_moid.c create mode 100644 crypto/asn1/bio_asn1.c create mode 100644 crypto/asn1/bio_ndef.c create mode 100644 crypto/asn1/charmap.h create mode 100644 crypto/asn1/p5_pbe.c create mode 100644 crypto/asn1/p5_pbev2.c create mode 100644 crypto/asn1/p8_pkey.c create mode 100644 crypto/asn1/t_crl.c create mode 100644 crypto/asn1/t_req.c create mode 100644 crypto/asn1/t_spki.c create mode 100644 crypto/asn1/t_x509.c create mode 100644 crypto/asn1/t_x509a.c create mode 100644 crypto/asn1/tasn_dec.c create mode 100644 crypto/asn1/tasn_enc.c create mode 100644 crypto/asn1/tasn_fre.c create mode 100644 crypto/asn1/tasn_new.c create mode 100644 crypto/asn1/tasn_prn.c create mode 100644 crypto/asn1/tasn_typ.c create mode 100644 crypto/asn1/tasn_utl.c create mode 100644 crypto/asn1/x_algor.c create mode 100644 crypto/asn1/x_attrib.c create mode 100644 crypto/asn1/x_bignum.c create mode 100644 crypto/asn1/x_crl.c create mode 100644 crypto/asn1/x_exten.c create mode 100644 crypto/asn1/x_info.c create mode 100644 crypto/asn1/x_long.c create mode 100644 crypto/asn1/x_name.c create mode 100644 crypto/asn1/x_pkey.c create mode 100644 crypto/asn1/x_pubkey.c create mode 100644 crypto/asn1/x_req.c create mode 100644 crypto/asn1/x_sig.c create mode 100644 crypto/asn1/x_spki.c create mode 100644 crypto/asn1/x_val.c create mode 100644 crypto/asn1/x_x509.c create mode 100644 crypto/asn1/x_x509a.c create mode 100644 crypto/bf/bf_cfb64.c create mode 100644 crypto/bf/bf_ecb.c create mode 100644 crypto/bf/bf_enc.c create mode 100644 crypto/bf/bf_local.h create mode 100644 crypto/bf/bf_ofb64.c create mode 100644 crypto/bf/bf_skey.c create mode 100644 crypto/bio/b_dump.c create mode 100644 crypto/bio/b_posix.c create mode 100644 crypto/bio/b_print.c create mode 100644 crypto/bio/b_sock.c create mode 100644 crypto/bio/b_win.c create mode 100644 crypto/bio/bf_buff.c create mode 100644 crypto/bio/bf_nbio.c create mode 100644 crypto/bio/bf_null.c create mode 100644 crypto/bio/bio_cb.c create mode 100644 crypto/bio/bio_err.c create mode 100644 crypto/bio/bio_lib.c create mode 100644 crypto/bio/bio_local.h create mode 100644 crypto/bio/bio_meth.c create mode 100644 crypto/bio/bss_acpt.c create mode 100644 crypto/bio/bss_bio.c create mode 100644 crypto/bio/bss_conn.c create mode 100644 crypto/bio/bss_dgram.c create mode 100644 crypto/bio/bss_fd.c create mode 100644 crypto/bio/bss_file.c create mode 100644 crypto/bio/bss_log.c create mode 100644 crypto/bio/bss_mem.c create mode 100644 crypto/bio/bss_null.c create mode 100644 crypto/bio/bss_sock.c create mode 100644 crypto/bn/arch/aarch64/bn_arch.h create mode 100644 crypto/bn/arch/alpha/bn_arch.h create mode 100644 crypto/bn/arch/amd64/bignum_add.S create mode 100644 crypto/bn/arch/amd64/bignum_cmadd.S create mode 100644 crypto/bn/arch/amd64/bignum_cmul.S create mode 100644 crypto/bn/arch/amd64/bignum_mul.S create mode 100644 crypto/bn/arch/amd64/bignum_mul_4_8_alt.S create mode 100644 crypto/bn/arch/amd64/bignum_mul_8_16_alt.S create mode 100644 crypto/bn/arch/amd64/bignum_sqr.S create mode 100644 crypto/bn/arch/amd64/bignum_sqr_4_8_alt.S create mode 100644 crypto/bn/arch/amd64/bignum_sqr_8_16_alt.S create mode 100644 crypto/bn/arch/amd64/bignum_sub.S create mode 100644 crypto/bn/arch/amd64/bn_arch.c create mode 100644 crypto/bn/arch/amd64/bn_arch.h create mode 100644 crypto/bn/arch/amd64/word_clz.S create mode 100644 crypto/bn/arch/arm/bn_arch.h create mode 100644 crypto/bn/arch/hppa/bn_arch.h create mode 100644 crypto/bn/arch/i386/bn_arch.h create mode 100644 crypto/bn/arch/m88k/bn_arch.h create mode 100644 crypto/bn/arch/mips64/bn_arch.h create mode 100644 crypto/bn/arch/powerpc/bn_arch.h create mode 100644 crypto/bn/arch/powerpc64/bn_arch.h create mode 100644 crypto/bn/arch/riscv64/bn_arch.h create mode 100644 crypto/bn/arch/sh/bn_arch.h create mode 100644 crypto/bn/arch/sparc64/bn_arch.h create mode 100644 crypto/bn/bn-mips.S create mode 100644 crypto/bn/bn-mips64.S create mode 100644 crypto/bn/bn_add.c create mode 100644 crypto/bn/bn_bpsw.c create mode 100644 crypto/bn/bn_const.c create mode 100644 crypto/bn/bn_convert.c create mode 100644 crypto/bn/bn_ctx.c create mode 100644 crypto/bn/bn_div.c create mode 100644 crypto/bn/bn_err.c create mode 100644 crypto/bn/bn_exp.c create mode 100644 crypto/bn/bn_gcd.c create mode 100644 crypto/bn/bn_internal.h create mode 100644 crypto/bn/bn_isqrt.c create mode 100644 crypto/bn/bn_kron.c create mode 100644 crypto/bn/bn_lib.c create mode 100644 crypto/bn/bn_local.h create mode 100644 crypto/bn/bn_mod.c create mode 100644 crypto/bn/bn_mod_sqrt.c create mode 100644 crypto/bn/bn_mont.c create mode 100644 crypto/bn/bn_mul.c create mode 100644 crypto/bn/bn_prime.c create mode 100644 crypto/bn/bn_prime.h create mode 100644 crypto/bn/bn_primitives.c create mode 100644 crypto/bn/bn_print.c create mode 100644 crypto/bn/bn_rand.c create mode 100644 crypto/bn/bn_recp.c create mode 100644 crypto/bn/bn_shift.c create mode 100644 crypto/bn/bn_small_primes.c create mode 100644 crypto/bn/bn_sqr.c create mode 100644 crypto/bn/bn_word.c create mode 100644 crypto/bn/modexp512-elf-x86_64.S create mode 100644 crypto/bn/modexp512-macosx-x86_64.S create mode 100644 crypto/bn/modexp512-masm-x86_64.S create mode 100644 crypto/bn/modexp512-mingw64-x86_64.S create mode 100644 crypto/bn/mont-elf-armv4.S create mode 100644 crypto/bn/mont-elf-x86_64.S create mode 100644 crypto/bn/mont-macosx-x86_64.S create mode 100644 crypto/bn/mont-masm-x86_64.S create mode 100644 crypto/bn/mont-mingw64-x86_64.S create mode 100644 crypto/bn/mont-mips.S create mode 100644 crypto/bn/mont-mips64.S create mode 100644 crypto/bn/mont5-elf-x86_64.S create mode 100644 crypto/bn/mont5-macosx-x86_64.S create mode 100644 crypto/bn/mont5-masm-x86_64.S create mode 100644 crypto/bn/mont5-mingw64-x86_64.S create mode 100644 crypto/bn/s2n_bignum.h create mode 100644 crypto/bn/s2n_bignum_internal.h create mode 100644 crypto/buffer/buf_err.c create mode 100644 crypto/buffer/buffer.c create mode 100644 crypto/bytestring/bs_ber.c create mode 100644 crypto/bytestring/bs_cbb.c create mode 100644 crypto/bytestring/bs_cbs.c create mode 100644 crypto/bytestring/bytestring.h create mode 100644 crypto/camellia/camellia.c create mode 100644 crypto/camellia/camellia.h create mode 100644 crypto/camellia/cmll-elf-x86_64.S create mode 100644 crypto/camellia/cmll-macosx-x86_64.S create mode 100644 crypto/camellia/cmll-masm-x86_64.S create mode 100644 crypto/camellia/cmll-mingw64-x86_64.S create mode 100644 crypto/camellia/cmll_cbc.c create mode 100644 crypto/camellia/cmll_cfb.c create mode 100644 crypto/camellia/cmll_ctr.c create mode 100644 crypto/camellia/cmll_ecb.c create mode 100644 crypto/camellia/cmll_local.h create mode 100644 crypto/camellia/cmll_misc.c create mode 100644 crypto/camellia/cmll_ofb.c create mode 100644 crypto/cast/c_cfb64.c create mode 100644 crypto/cast/c_ecb.c create mode 100644 crypto/cast/c_enc.c create mode 100644 crypto/cast/c_ofb64.c create mode 100644 crypto/cast/c_skey.c create mode 100644 crypto/cast/cast_local.h create mode 100644 crypto/cast/cast_s.h create mode 100644 crypto/chacha/chacha-merged.c create mode 100644 crypto/chacha/chacha.c create mode 100644 crypto/cmac/cm_ameth.c create mode 100644 crypto/cmac/cm_pmeth.c create mode 100644 crypto/cmac/cmac.c create mode 100644 crypto/cms/cms_asn1.c create mode 100644 crypto/cms/cms_att.c create mode 100644 crypto/cms/cms_dd.c create mode 100644 crypto/cms/cms_enc.c create mode 100644 crypto/cms/cms_env.c create mode 100644 crypto/cms/cms_err.c create mode 100644 crypto/cms/cms_ess.c create mode 100644 crypto/cms/cms_io.c create mode 100644 crypto/cms/cms_kari.c create mode 100644 crypto/cms/cms_lib.c create mode 100644 crypto/cms/cms_local.h create mode 100644 crypto/cms/cms_pwri.c create mode 100644 crypto/cms/cms_sd.c create mode 100644 crypto/cms/cms_smime.c create mode 100644 crypto/compat/arc4random.c create mode 100644 crypto/compat/arc4random_aix.h create mode 100644 crypto/compat/arc4random_freebsd.h create mode 100644 crypto/compat/arc4random_hpux.h create mode 100644 crypto/compat/arc4random_linux.h create mode 100644 crypto/compat/arc4random_netbsd.h create mode 100644 crypto/compat/arc4random_osx.h create mode 100644 crypto/compat/arc4random_solaris.h create mode 100644 crypto/compat/arc4random_uniform.c create mode 100644 crypto/compat/arc4random_win.h create mode 100644 crypto/compat/chacha_private.h create mode 100644 crypto/compat/explicit_bzero.c create mode 100644 crypto/compat/getentropy_aix.c create mode 100644 crypto/compat/getentropy_freebsd.c create mode 100644 crypto/compat/getentropy_hpux.c create mode 100644 crypto/compat/getentropy_linux.c create mode 100644 crypto/compat/getentropy_netbsd.c create mode 100644 crypto/compat/getentropy_osx.c create mode 100644 crypto/compat/getentropy_solaris.c create mode 100644 crypto/compat/getentropy_win.c create mode 100644 crypto/compat/reallocarray.c create mode 100644 crypto/compat/recallocarray.c create mode 100644 crypto/compat/strcasecmp.c create mode 100644 crypto/compat/strlcat.c create mode 100644 crypto/compat/strlcpy.c create mode 100644 crypto/compat/strndup.c create mode 100644 crypto/compat/strnlen.c create mode 100644 crypto/compat/strsep.c create mode 100644 crypto/compat/strtonum.c create mode 100644 crypto/compat/timingsafe_bcmp.c create mode 100644 crypto/compat/timingsafe_memcmp.c create mode 100644 crypto/conf/conf_api.c create mode 100644 crypto/conf/conf_def.c create mode 100644 crypto/conf/conf_def.h create mode 100644 crypto/conf/conf_err.c create mode 100644 crypto/conf/conf_lib.c create mode 100644 crypto/conf/conf_mall.c create mode 100644 crypto/conf/conf_mod.c create mode 100644 crypto/conf/conf_sap.c create mode 100644 crypto/constant_time.h create mode 100644 crypto/cpt_err.c create mode 100644 crypto/cpuid-elf-x86_64.S create mode 100644 crypto/cpuid-macosx-x86_64.S create mode 100644 crypto/cpuid-masm-x86_64.S create mode 100644 crypto/cpuid-mingw64-x86_64.S create mode 100644 crypto/cryptlib.c create mode 100644 crypto/cryptlib.h create mode 100644 crypto/crypto_init.c create mode 100644 crypto/crypto_internal.h create mode 100644 crypto/crypto_lock.c create mode 100644 crypto/ct/ct_b64.c create mode 100644 crypto/ct/ct_err.c create mode 100644 crypto/ct/ct_local.h create mode 100644 crypto/ct/ct_log.c create mode 100644 crypto/ct/ct_oct.c create mode 100644 crypto/ct/ct_policy.c create mode 100644 crypto/ct/ct_prn.c create mode 100644 crypto/ct/ct_sct.c create mode 100644 crypto/ct/ct_sct_ctx.c create mode 100644 crypto/ct/ct_vfy.c create mode 100644 crypto/ct/ct_x509v3.c create mode 100644 crypto/curve25519/curve25519-generic.c create mode 100644 crypto/curve25519/curve25519.c create mode 100644 crypto/curve25519/curve25519_internal.h create mode 100644 crypto/cversion.c create mode 100644 crypto/des/cbc_cksm.c create mode 100644 crypto/des/cbc_enc.c create mode 100644 crypto/des/cfb64ede.c create mode 100644 crypto/des/cfb64enc.c create mode 100644 crypto/des/cfb_enc.c create mode 100644 crypto/des/des_enc.c create mode 100644 crypto/des/des_local.h create mode 100644 crypto/des/ecb3_enc.c create mode 100644 crypto/des/ecb_enc.c create mode 100644 crypto/des/ede_cbcm_enc.c create mode 100644 crypto/des/enc_read.c create mode 100644 crypto/des/enc_writ.c create mode 100644 crypto/des/fcrypt.c create mode 100644 crypto/des/fcrypt_b.c create mode 100644 crypto/des/ncbc_enc.c create mode 100644 crypto/des/ofb64ede.c create mode 100644 crypto/des/ofb64enc.c create mode 100644 crypto/des/ofb_enc.c create mode 100644 crypto/des/pcbc_enc.c create mode 100644 crypto/des/qud_cksm.c create mode 100644 crypto/des/rand_key.c create mode 100644 crypto/des/set_key.c create mode 100644 crypto/des/spr.h create mode 100644 crypto/des/str2key.c create mode 100644 crypto/des/xcbc_enc.c create mode 100644 crypto/dh/dh_ameth.c create mode 100644 crypto/dh/dh_asn1.c create mode 100644 crypto/dh/dh_check.c create mode 100644 crypto/dh/dh_err.c create mode 100644 crypto/dh/dh_gen.c create mode 100644 crypto/dh/dh_key.c create mode 100644 crypto/dh/dh_lib.c create mode 100644 crypto/dh/dh_local.h create mode 100644 crypto/dh/dh_pmeth.c create mode 100644 crypto/dsa/dsa_ameth.c create mode 100644 crypto/dsa/dsa_asn1.c create mode 100644 crypto/dsa/dsa_err.c create mode 100644 crypto/dsa/dsa_gen.c create mode 100644 crypto/dsa/dsa_key.c create mode 100644 crypto/dsa/dsa_lib.c create mode 100644 crypto/dsa/dsa_local.h create mode 100644 crypto/dsa/dsa_meth.c create mode 100644 crypto/dsa/dsa_ossl.c create mode 100644 crypto/dsa/dsa_pmeth.c create mode 100644 crypto/dsa/dsa_prn.c create mode 100644 crypto/ec/ec_ameth.c create mode 100644 crypto/ec/ec_asn1.c create mode 100644 crypto/ec/ec_check.c create mode 100644 crypto/ec/ec_curve.c create mode 100644 crypto/ec/ec_cvt.c create mode 100644 crypto/ec/ec_err.c create mode 100644 crypto/ec/ec_key.c create mode 100644 crypto/ec/ec_kmeth.c create mode 100644 crypto/ec/ec_lib.c create mode 100644 crypto/ec/ec_local.h create mode 100644 crypto/ec/ec_mult.c create mode 100644 crypto/ec/ec_oct.c create mode 100644 crypto/ec/ec_pmeth.c create mode 100644 crypto/ec/ec_print.c create mode 100644 crypto/ec/eck_prn.c create mode 100644 crypto/ec/ecp_mont.c create mode 100644 crypto/ec/ecp_oct.c create mode 100644 crypto/ec/ecp_smpl.c create mode 100644 crypto/ec/ecx_methods.c create mode 100644 crypto/ecdh/ecdh.c create mode 100644 crypto/ecdsa/ecdsa.c create mode 100644 crypto/ecdsa/ecdsa_local.h create mode 100644 crypto/empty.c create mode 100644 crypto/engine/engine_stubs.c create mode 100644 crypto/err/err.c create mode 100644 crypto/err/err_all.c create mode 100644 crypto/err/err_prn.c create mode 100644 crypto/evp/bio_b64.c create mode 100644 crypto/evp/bio_enc.c create mode 100644 crypto/evp/bio_md.c create mode 100644 crypto/evp/c_all.c create mode 100644 crypto/evp/cipher_method_lib.c create mode 100644 crypto/evp/digest.c create mode 100644 crypto/evp/e_aes.c create mode 100644 crypto/evp/e_aes_cbc_hmac_sha1.c create mode 100644 crypto/evp/e_bf.c create mode 100644 crypto/evp/e_camellia.c create mode 100644 crypto/evp/e_cast.c create mode 100644 crypto/evp/e_chacha.c create mode 100644 crypto/evp/e_chacha20poly1305.c create mode 100644 crypto/evp/e_des.c create mode 100644 crypto/evp/e_des3.c create mode 100644 crypto/evp/e_gost2814789.c create mode 100644 crypto/evp/e_idea.c create mode 100644 crypto/evp/e_null.c create mode 100644 crypto/evp/e_rc2.c create mode 100644 crypto/evp/e_rc4.c create mode 100644 crypto/evp/e_rc4_hmac_md5.c create mode 100644 crypto/evp/e_sm4.c create mode 100644 crypto/evp/e_xcbc_d.c create mode 100644 crypto/evp/encode.c create mode 100644 crypto/evp/evp_aead.c create mode 100644 crypto/evp/evp_enc.c create mode 100644 crypto/evp/evp_err.c create mode 100644 crypto/evp/evp_key.c create mode 100644 crypto/evp/evp_lib.c create mode 100644 crypto/evp/evp_local.h create mode 100644 crypto/evp/evp_pbe.c create mode 100644 crypto/evp/evp_pkey.c create mode 100644 crypto/evp/m_gost2814789.c create mode 100644 crypto/evp/m_gostr341194.c create mode 100644 crypto/evp/m_md4.c create mode 100644 crypto/evp/m_md5.c create mode 100644 crypto/evp/m_md5_sha1.c create mode 100644 crypto/evp/m_null.c create mode 100644 crypto/evp/m_ripemd.c create mode 100644 crypto/evp/m_sha1.c create mode 100644 crypto/evp/m_sha3.c create mode 100644 crypto/evp/m_sigver.c create mode 100644 crypto/evp/m_sm3.c create mode 100644 crypto/evp/m_streebog.c create mode 100644 crypto/evp/m_wp.c create mode 100644 crypto/evp/names.c create mode 100644 crypto/evp/p5_crpt.c create mode 100644 crypto/evp/p5_crpt2.c create mode 100644 crypto/evp/p_dec.c create mode 100644 crypto/evp/p_enc.c create mode 100644 crypto/evp/p_lib.c create mode 100644 crypto/evp/p_open.c create mode 100644 crypto/evp/p_seal.c create mode 100644 crypto/evp/p_sign.c create mode 100644 crypto/evp/p_verify.c create mode 100644 crypto/evp/pmeth_fn.c create mode 100644 crypto/evp/pmeth_gn.c create mode 100644 crypto/evp/pmeth_lib.c create mode 100644 crypto/ex_data.c create mode 100644 crypto/gost/gost2814789.c create mode 100644 crypto/gost/gost89_keywrap.c create mode 100644 crypto/gost/gost89_params.c create mode 100644 crypto/gost/gost89imit_ameth.c create mode 100644 crypto/gost/gost89imit_pmeth.c create mode 100644 crypto/gost/gost_asn1.c create mode 100644 crypto/gost/gost_asn1.h create mode 100644 crypto/gost/gost_err.c create mode 100644 crypto/gost/gost_local.h create mode 100644 crypto/gost/gostr341001.c create mode 100644 crypto/gost/gostr341001_ameth.c create mode 100644 crypto/gost/gostr341001_key.c create mode 100644 crypto/gost/gostr341001_params.c create mode 100644 crypto/gost/gostr341001_pmeth.c create mode 100644 crypto/gost/gostr341194.c create mode 100644 crypto/gost/streebog.c create mode 100644 crypto/hidden/crypto_namespace.h create mode 100644 crypto/hidden/openssl/asn1.h create mode 100644 crypto/hidden/openssl/asn1t.h create mode 100644 crypto/hidden/openssl/bio.h create mode 100644 crypto/hidden/openssl/bn.h create mode 100644 crypto/hidden/openssl/buffer.h create mode 100644 crypto/hidden/openssl/cast.h create mode 100644 crypto/hidden/openssl/chacha.h create mode 100644 crypto/hidden/openssl/cmac.h create mode 100644 crypto/hidden/openssl/cms.h create mode 100644 crypto/hidden/openssl/conf_api.h create mode 100644 crypto/hidden/openssl/crypto.h create mode 100644 crypto/hidden/openssl/ct.h create mode 100644 crypto/hidden/openssl/curve25519.h create mode 100644 crypto/hidden/openssl/dh.h create mode 100644 crypto/hidden/openssl/dsa.h create mode 100644 crypto/hidden/openssl/ec.h create mode 100644 crypto/hidden/openssl/err.h create mode 100644 crypto/hidden/openssl/gost.h create mode 100644 crypto/hidden/openssl/hkdf.h create mode 100644 crypto/hidden/openssl/hmac.h create mode 100644 crypto/hidden/openssl/idea.h create mode 100644 crypto/hidden/openssl/lhash.h create mode 100644 crypto/hidden/openssl/md4.h create mode 100644 crypto/hidden/openssl/md5.h create mode 100644 crypto/hidden/openssl/modes.h create mode 100644 crypto/hidden/openssl/objects.h create mode 100644 crypto/hidden/openssl/ocsp.h create mode 100644 crypto/hidden/openssl/pem.h create mode 100644 crypto/hidden/openssl/pkcs12.h create mode 100644 crypto/hidden/openssl/pkcs7.h create mode 100644 crypto/hidden/openssl/poly1305.h create mode 100644 crypto/hidden/openssl/rand.h create mode 100644 crypto/hidden/openssl/rc2.h create mode 100644 crypto/hidden/openssl/rsa.h create mode 100644 crypto/hidden/openssl/sha.h create mode 100644 crypto/hidden/openssl/sm3.h create mode 100644 crypto/hidden/openssl/sm4.h create mode 100644 crypto/hidden/openssl/stack.h create mode 100644 crypto/hidden/openssl/ts.h create mode 100644 crypto/hidden/openssl/txt_db.h create mode 100644 crypto/hidden/openssl/ui.h create mode 100644 crypto/hidden/openssl/x509.h create mode 100644 crypto/hidden/openssl/x509_vfy.h create mode 100644 crypto/hidden/openssl/x509v3.h create mode 100644 crypto/hkdf/hkdf.c create mode 100644 crypto/hmac/hm_ameth.c create mode 100644 crypto/hmac/hm_pmeth.c create mode 100644 crypto/hmac/hmac.c create mode 100644 crypto/hmac/hmac_local.h create mode 100644 crypto/idea/i_cbc.c create mode 100644 crypto/idea/i_cfb64.c create mode 100644 crypto/idea/i_ecb.c create mode 100644 crypto/idea/i_ofb64.c create mode 100644 crypto/idea/i_skey.c create mode 100644 crypto/idea/idea_local.h create mode 100644 crypto/kdf/hkdf_evp.c create mode 100644 crypto/kdf/kdf_err.c create mode 100644 crypto/lhash/lh_stats.c create mode 100644 crypto/lhash/lhash.c create mode 100644 crypto/malloc-wrapper.c create mode 100644 crypto/md32_common.h create mode 100644 crypto/md4/md4.c create mode 100644 crypto/md5/md5-elf-x86_64.S create mode 100644 crypto/md5/md5-macosx-x86_64.S create mode 100644 crypto/md5/md5-masm-x86_64.S create mode 100644 crypto/md5/md5-mingw64-x86_64.S create mode 100644 crypto/md5/md5.c create mode 100644 crypto/mem_clr.c create mode 100644 crypto/mem_dbg.c create mode 100644 crypto/modes/cbc128.c create mode 100644 crypto/modes/ccm128.c create mode 100644 crypto/modes/cfb128.c create mode 100644 crypto/modes/ctr128.c create mode 100644 crypto/modes/gcm128.c create mode 100644 crypto/modes/ghash-elf-armv4.S create mode 100644 crypto/modes/ghash-elf-x86_64.S create mode 100644 crypto/modes/ghash-macosx-x86_64.S create mode 100644 crypto/modes/ghash-masm-x86_64.S create mode 100644 crypto/modes/ghash-mingw64-x86_64.S create mode 100644 crypto/modes/modes_local.h create mode 100644 crypto/modes/ofb128.c create mode 100644 crypto/modes/xts128.c create mode 100644 crypto/o_fips.c create mode 100644 crypto/o_init.c create mode 100644 crypto/o_str.c create mode 100644 crypto/objects/o_names.c create mode 100644 crypto/objects/obj_dat.c create mode 100644 crypto/objects/obj_dat.h create mode 100644 crypto/objects/obj_err.c create mode 100644 crypto/objects/obj_lib.c create mode 100644 crypto/objects/obj_xref.c create mode 100644 crypto/ocsp/ocsp_asn.c create mode 100644 crypto/ocsp/ocsp_cl.c create mode 100644 crypto/ocsp/ocsp_err.c create mode 100644 crypto/ocsp/ocsp_ext.c create mode 100644 crypto/ocsp/ocsp_ht.c create mode 100644 crypto/ocsp/ocsp_lib.c create mode 100644 crypto/ocsp/ocsp_local.h create mode 100644 crypto/ocsp/ocsp_prn.c create mode 100644 crypto/ocsp/ocsp_srv.c create mode 100644 crypto/ocsp/ocsp_vfy.c create mode 100644 crypto/pem/pem_all.c create mode 100644 crypto/pem/pem_err.c create mode 100644 crypto/pem/pem_info.c create mode 100644 crypto/pem/pem_lib.c create mode 100644 crypto/pem/pem_oth.c create mode 100644 crypto/pem/pem_pk8.c create mode 100644 crypto/pem/pem_pkey.c create mode 100644 crypto/pem/pem_sign.c create mode 100644 crypto/pem/pem_x509.c create mode 100644 crypto/pem/pem_xaux.c create mode 100644 crypto/pem/pvkfmt.c create mode 100644 crypto/pkcs12/p12_add.c create mode 100644 crypto/pkcs12/p12_asn.c create mode 100644 crypto/pkcs12/p12_attr.c create mode 100644 crypto/pkcs12/p12_crpt.c create mode 100644 crypto/pkcs12/p12_crt.c create mode 100644 crypto/pkcs12/p12_decr.c create mode 100644 crypto/pkcs12/p12_init.c create mode 100644 crypto/pkcs12/p12_key.c create mode 100644 crypto/pkcs12/p12_kiss.c create mode 100644 crypto/pkcs12/p12_mutl.c create mode 100644 crypto/pkcs12/p12_npas.c create mode 100644 crypto/pkcs12/p12_p8d.c create mode 100644 crypto/pkcs12/p12_p8e.c create mode 100644 crypto/pkcs12/p12_sbag.c create mode 100644 crypto/pkcs12/p12_utl.c create mode 100644 crypto/pkcs12/pk12err.c create mode 100644 crypto/pkcs12/pkcs12_local.h create mode 100644 crypto/pkcs7/pk7_asn1.c create mode 100644 crypto/pkcs7/pk7_attr.c create mode 100644 crypto/pkcs7/pk7_doit.c create mode 100644 crypto/pkcs7/pk7_lib.c create mode 100644 crypto/pkcs7/pk7_mime.c create mode 100644 crypto/pkcs7/pk7_smime.c create mode 100644 crypto/pkcs7/pkcs7err.c create mode 100644 crypto/poly1305/poly1305-donna.c create mode 100644 crypto/poly1305/poly1305.c create mode 100644 crypto/rand/rand_err.c create mode 100644 crypto/rand/rand_lib.c create mode 100644 crypto/rand/randfile.c create mode 100644 crypto/rc2/rc2_cbc.c create mode 100644 crypto/rc2/rc2_ecb.c create mode 100644 crypto/rc2/rc2_local.h create mode 100644 crypto/rc2/rc2_skey.c create mode 100644 crypto/rc2/rc2cfb64.c create mode 100644 crypto/rc2/rc2ofb64.c create mode 100644 crypto/rc4/rc4-elf-x86_64.S create mode 100644 crypto/rc4/rc4-macosx-x86_64.S create mode 100644 crypto/rc4/rc4-masm-x86_64.S create mode 100644 crypto/rc4/rc4-md5-elf-x86_64.S create mode 100644 crypto/rc4/rc4-md5-macosx-x86_64.S create mode 100644 crypto/rc4/rc4-md5-masm-x86_64.S create mode 100644 crypto/rc4/rc4-md5-mingw64-x86_64.S create mode 100644 crypto/rc4/rc4-mingw64-x86_64.S create mode 100644 crypto/rc4/rc4_enc.c create mode 100644 crypto/rc4/rc4_local.h create mode 100644 crypto/rc4/rc4_skey.c create mode 100644 crypto/ripemd/ripemd.c create mode 100644 crypto/rsa/rsa_ameth.c create mode 100644 crypto/rsa/rsa_asn1.c create mode 100644 crypto/rsa/rsa_blinding.c create mode 100644 crypto/rsa/rsa_chk.c create mode 100644 crypto/rsa/rsa_eay.c create mode 100644 crypto/rsa/rsa_err.c create mode 100644 crypto/rsa/rsa_gen.c create mode 100644 crypto/rsa/rsa_lib.c create mode 100644 crypto/rsa/rsa_local.h create mode 100644 crypto/rsa/rsa_meth.c create mode 100644 crypto/rsa/rsa_none.c create mode 100644 crypto/rsa/rsa_oaep.c create mode 100644 crypto/rsa/rsa_pk1.c create mode 100644 crypto/rsa/rsa_pmeth.c create mode 100644 crypto/rsa/rsa_prn.c create mode 100644 crypto/rsa/rsa_pss.c create mode 100644 crypto/rsa/rsa_saos.c create mode 100644 crypto/rsa/rsa_sign.c create mode 100644 crypto/rsa/rsa_x931.c create mode 100644 crypto/sha/sha1-elf-armv4.S create mode 100644 crypto/sha/sha1-elf-x86_64.S create mode 100644 crypto/sha/sha1-macosx-x86_64.S create mode 100644 crypto/sha/sha1-masm-x86_64.S create mode 100644 crypto/sha/sha1-mingw64-x86_64.S create mode 100644 crypto/sha/sha1-mips.S create mode 100644 crypto/sha/sha1-mips64.S create mode 100644 crypto/sha/sha1.c create mode 100644 crypto/sha/sha256-elf-armv4.S create mode 100644 crypto/sha/sha256-elf-x86_64.S create mode 100644 crypto/sha/sha256-macosx-x86_64.S create mode 100644 crypto/sha/sha256-masm-x86_64.S create mode 100644 crypto/sha/sha256-mingw64-x86_64.S create mode 100644 crypto/sha/sha256-mips.S create mode 100644 crypto/sha/sha256-mips64.S create mode 100644 crypto/sha/sha256.c create mode 100644 crypto/sha/sha3.c create mode 100644 crypto/sha/sha3_internal.h create mode 100644 crypto/sha/sha512-elf-armv4.S create mode 100644 crypto/sha/sha512-elf-x86_64.S create mode 100644 crypto/sha/sha512-macosx-x86_64.S create mode 100644 crypto/sha/sha512-masm-x86_64.S create mode 100644 crypto/sha/sha512-mingw64-x86_64.S create mode 100644 crypto/sha/sha512-mips.S create mode 100644 crypto/sha/sha512-mips64.S create mode 100644 crypto/sha/sha512.c create mode 100644 crypto/sha/sha_internal.h create mode 100644 crypto/sm3/sm3.c create mode 100644 crypto/sm4/sm4.c create mode 100644 crypto/stack/stack.c create mode 100644 crypto/ts/ts_asn1.c create mode 100644 crypto/ts/ts_conf.c create mode 100644 crypto/ts/ts_err.c create mode 100644 crypto/ts/ts_lib.c create mode 100644 crypto/ts/ts_local.h create mode 100644 crypto/ts/ts_req_print.c create mode 100644 crypto/ts/ts_req_utils.c create mode 100644 crypto/ts/ts_rsp_print.c create mode 100644 crypto/ts/ts_rsp_sign.c create mode 100644 crypto/ts/ts_rsp_utils.c create mode 100644 crypto/ts/ts_rsp_verify.c create mode 100644 crypto/ts/ts_verify_ctx.c create mode 100644 crypto/txt_db/txt_db.c create mode 100644 crypto/ui/ui_err.c create mode 100644 crypto/ui/ui_lib.c create mode 100644 crypto/ui/ui_local.h create mode 100644 crypto/ui/ui_null.c create mode 100644 crypto/ui/ui_openssl.c create mode 100644 crypto/ui/ui_openssl_win.c create mode 100644 crypto/ui/ui_util.c create mode 100644 crypto/whrlpool/wp-elf-x86_64.S create mode 100644 crypto/whrlpool/wp-macosx-x86_64.S create mode 100644 crypto/whrlpool/wp-masm-x86_64.S create mode 100644 crypto/whrlpool/wp-mingw64-x86_64.S create mode 100644 crypto/whrlpool/wp_block.c create mode 100644 crypto/whrlpool/wp_dgst.c create mode 100644 crypto/whrlpool/wp_local.h create mode 100644 crypto/x509/by_dir.c create mode 100644 crypto/x509/by_file.c create mode 100644 crypto/x509/by_mem.c create mode 100644 crypto/x509/x509_addr.c create mode 100644 crypto/x509/x509_akey.c create mode 100644 crypto/x509/x509_akeya.c create mode 100644 crypto/x509/x509_alt.c create mode 100644 crypto/x509/x509_asid.c create mode 100644 crypto/x509/x509_att.c create mode 100644 crypto/x509/x509_bcons.c create mode 100644 crypto/x509/x509_bitst.c create mode 100644 crypto/x509/x509_cmp.c create mode 100644 crypto/x509/x509_conf.c create mode 100644 crypto/x509/x509_constraints.c create mode 100644 crypto/x509/x509_cpols.c create mode 100644 crypto/x509/x509_crld.c create mode 100644 crypto/x509/x509_d2.c create mode 100644 crypto/x509/x509_def.c create mode 100644 crypto/x509/x509_err.c create mode 100644 crypto/x509/x509_ext.c create mode 100644 crypto/x509/x509_extku.c create mode 100644 crypto/x509/x509_genn.c create mode 100644 crypto/x509/x509_ia5.c create mode 100644 crypto/x509/x509_info.c create mode 100644 crypto/x509/x509_int.c create mode 100644 crypto/x509/x509_internal.h create mode 100644 crypto/x509/x509_issuer_cache.c create mode 100644 crypto/x509/x509_issuer_cache.h create mode 100644 crypto/x509/x509_lib.c create mode 100644 crypto/x509/x509_local.h create mode 100644 crypto/x509/x509_lu.c create mode 100644 crypto/x509/x509_ncons.c create mode 100644 crypto/x509/x509_obj.c create mode 100644 crypto/x509/x509_ocsp.c create mode 100644 crypto/x509/x509_pcons.c create mode 100644 crypto/x509/x509_pku.c create mode 100644 crypto/x509/x509_pmaps.c create mode 100644 crypto/x509/x509_policy.c create mode 100644 crypto/x509/x509_prn.c create mode 100644 crypto/x509/x509_purp.c create mode 100644 crypto/x509/x509_r2x.c create mode 100644 crypto/x509/x509_req.c create mode 100644 crypto/x509/x509_set.c create mode 100644 crypto/x509/x509_skey.c create mode 100644 crypto/x509/x509_trs.c create mode 100644 crypto/x509/x509_txt.c create mode 100644 crypto/x509/x509_utl.c create mode 100644 crypto/x509/x509_v3.c create mode 100644 crypto/x509/x509_verify.c create mode 100644 crypto/x509/x509_verify.h create mode 100644 crypto/x509/x509_vfy.c create mode 100644 crypto/x509/x509_vpm.c create mode 100644 crypto/x509/x509cset.c create mode 100644 crypto/x509/x509name.c create mode 100644 crypto/x509/x509rset.c create mode 100644 crypto/x509/x509spki.c create mode 100644 crypto/x509/x509type.c create mode 100644 crypto/x509/x_all.c create mode 100644 crypto/x86_arch.h create mode 100644 include/arch/aarch64/opensslconf.h create mode 100644 include/arch/alpha/opensslconf.h create mode 100644 include/arch/amd64/opensslconf.h create mode 100644 include/arch/arm/opensslconf.h create mode 100644 include/arch/hppa/opensslconf.h create mode 100644 include/arch/i386/opensslconf.h create mode 100644 include/arch/m88k/opensslconf.h create mode 100644 include/arch/mips64/opensslconf.h create mode 100644 include/arch/powerpc/opensslconf.h create mode 100644 include/arch/powerpc64/opensslconf.h create mode 100644 include/arch/riscv64/opensslconf.h create mode 100644 include/arch/sh/opensslconf.h create mode 100644 include/arch/sparc64/opensslconf.h create mode 100644 include/openssl/aes.h create mode 100644 include/openssl/asn1.h create mode 100644 include/openssl/asn1t.h create mode 100644 include/openssl/bio.h create mode 100644 include/openssl/blowfish.h create mode 100644 include/openssl/bn.h create mode 100644 include/openssl/buffer.h create mode 100644 include/openssl/camellia.h create mode 100644 include/openssl/cast.h create mode 100644 include/openssl/chacha.h create mode 100644 include/openssl/cmac.h create mode 100644 include/openssl/cms.h create mode 100644 include/openssl/comp.h create mode 100644 include/openssl/conf.h create mode 100644 include/openssl/conf_api.h create mode 100644 include/openssl/crypto.h create mode 100644 include/openssl/ct.h create mode 100644 include/openssl/curve25519.h create mode 100644 include/openssl/des.h create mode 100644 include/openssl/dh.h create mode 100644 include/openssl/dsa.h create mode 100644 include/openssl/dtls1.h create mode 100644 include/openssl/ec.h create mode 100644 include/openssl/ecdh.h create mode 100644 include/openssl/ecdsa.h create mode 100644 include/openssl/engine.h create mode 100644 include/openssl/err.h create mode 100644 include/openssl/evp.h create mode 100644 include/openssl/gost.h create mode 100644 include/openssl/hkdf.h create mode 100644 include/openssl/hmac.h create mode 100644 include/openssl/idea.h create mode 100644 include/openssl/kdf.h create mode 100644 include/openssl/lhash.h create mode 100644 include/openssl/md4.h create mode 100644 include/openssl/md5.h create mode 100644 include/openssl/modes.h create mode 100644 include/openssl/obj_mac.h create mode 100644 include/openssl/objects.h create mode 100644 include/openssl/ocsp.h create mode 100644 include/openssl/opensslfeatures.h create mode 100644 include/openssl/opensslv.h create mode 100644 include/openssl/ossl_typ.h create mode 100644 include/openssl/pem.h create mode 100644 include/openssl/pem2.h create mode 100644 include/openssl/pkcs12.h create mode 100644 include/openssl/pkcs7.h create mode 100644 include/openssl/poly1305.h create mode 100644 include/openssl/rand.h create mode 100644 include/openssl/rc2.h create mode 100644 include/openssl/rc4.h create mode 100644 include/openssl/ripemd.h create mode 100644 include/openssl/rsa.h create mode 100644 include/openssl/safestack.h create mode 100644 include/openssl/sha.h create mode 100644 include/openssl/sm3.h create mode 100644 include/openssl/sm4.h create mode 100644 include/openssl/srtp.h create mode 100644 include/openssl/ssl.h create mode 100644 include/openssl/ssl2.h create mode 100644 include/openssl/ssl23.h create mode 100644 include/openssl/ssl3.h create mode 100644 include/openssl/stack.h create mode 100644 include/openssl/tls1.h create mode 100644 include/openssl/ts.h create mode 100644 include/openssl/txt_db.h create mode 100644 include/openssl/ui.h create mode 100644 include/openssl/ui_compat.h create mode 100644 include/openssl/whrlpool.h create mode 100644 include/openssl/x509.h create mode 100644 include/openssl/x509_vfy.h create mode 100644 include/openssl/x509v3.h create mode 100644 include/pqueue.h create mode 100644 include/tls.h create mode 100644 ssl/bio_ssl.c create mode 100644 ssl/bs_ber.c create mode 100644 ssl/bs_cbb.c create mode 100644 ssl/bs_cbs.c create mode 100644 ssl/bytestring.h create mode 100644 ssl/d1_both.c create mode 100644 ssl/d1_lib.c create mode 100644 ssl/d1_pkt.c create mode 100644 ssl/d1_srtp.c create mode 100644 ssl/dtls_local.h create mode 100644 ssl/empty.c create mode 100644 ssl/hidden/openssl/srtp.h create mode 100644 ssl/hidden/openssl/ssl.h create mode 100644 ssl/hidden/openssl/tls1.h create mode 100644 ssl/hidden/ssl_namespace.h create mode 100644 ssl/pqueue.c create mode 100644 ssl/s3_cbc.c create mode 100644 ssl/s3_lib.c create mode 100644 ssl/srtp.h create mode 100644 ssl/ssl_algs.c create mode 100644 ssl/ssl_asn1.c create mode 100644 ssl/ssl_both.c create mode 100644 ssl/ssl_cert.c create mode 100644 ssl/ssl_ciph.c create mode 100644 ssl/ssl_ciphers.c create mode 100644 ssl/ssl_clnt.c create mode 100644 ssl/ssl_err.c create mode 100644 ssl/ssl_init.c create mode 100644 ssl/ssl_kex.c create mode 100644 ssl/ssl_lib.c create mode 100644 ssl/ssl_local.h create mode 100644 ssl/ssl_methods.c create mode 100644 ssl/ssl_packet.c create mode 100644 ssl/ssl_pkt.c create mode 100644 ssl/ssl_rsa.c create mode 100644 ssl/ssl_seclevel.c create mode 100644 ssl/ssl_sess.c create mode 100644 ssl/ssl_sigalgs.c create mode 100644 ssl/ssl_sigalgs.h create mode 100644 ssl/ssl_srvr.c create mode 100644 ssl/ssl_stat.c create mode 100644 ssl/ssl_tlsext.c create mode 100644 ssl/ssl_tlsext.h create mode 100644 ssl/ssl_transcript.c create mode 100644 ssl/ssl_txt.c create mode 100644 ssl/ssl_versions.c create mode 100644 ssl/t1_enc.c create mode 100644 ssl/t1_lib.c create mode 100644 ssl/tls12_internal.h create mode 100644 ssl/tls12_key_schedule.c create mode 100644 ssl/tls12_lib.c create mode 100644 ssl/tls12_record_layer.c create mode 100644 ssl/tls13_client.c create mode 100644 ssl/tls13_error.c create mode 100644 ssl/tls13_handshake.c create mode 100644 ssl/tls13_handshake.h create mode 100644 ssl/tls13_handshake_msg.c create mode 100644 ssl/tls13_internal.h create mode 100644 ssl/tls13_key_schedule.c create mode 100644 ssl/tls13_legacy.c create mode 100644 ssl/tls13_lib.c create mode 100644 ssl/tls13_quic.c create mode 100644 ssl/tls13_record.c create mode 100644 ssl/tls13_record.h create mode 100644 ssl/tls13_record_layer.c create mode 100644 ssl/tls13_server.c create mode 100644 ssl/tls_buffer.c create mode 100644 ssl/tls_content.c create mode 100644 ssl/tls_content.h create mode 100644 ssl/tls_internal.h create mode 100644 ssl/tls_key_share.c create mode 100644 ssl/tls_lib.c create mode 100644 tests/aeadtest.c create mode 100644 tests/aeadtests.txt create mode 100644 tests/aes_128_gcm_tests.txt create mode 100644 tests/aes_192_gcm_tests.txt create mode 100644 tests/aes_256_gcm_tests.txt create mode 100644 tests/aes_test.c create mode 100644 tests/aes_wrap.c create mode 100644 tests/apitest.c create mode 100644 tests/arc4randomforktest.c create mode 100644 tests/asn1_string_to_utf8.c create mode 100644 tests/asn1api.c create mode 100644 tests/asn1basic.c create mode 100644 tests/asn1complex.c create mode 100644 tests/asn1evp.c create mode 100644 tests/asn1object.c create mode 100644 tests/asn1oct.c create mode 100644 tests/asn1string_copy.c create mode 100644 tests/asn1test.c create mode 100644 tests/asn1time.c create mode 100644 tests/asn1x509.c create mode 100644 tests/base64test.c create mode 100644 tests/bf_test.c create mode 100644 tests/bio_asn1.c create mode 100644 tests/bio_chain.c create mode 100644 tests/bio_host.c create mode 100644 tests/bio_mem.c create mode 100644 tests/bn_add_sub.c create mode 100644 tests/bn_cmp.c create mode 100644 tests/bn_convert.c create mode 100644 tests/bn_gcd.c create mode 100644 tests/bn_general.c create mode 100644 tests/bn_isqrt.c create mode 100644 tests/bn_mod_exp.c create mode 100644 tests/bn_mod_inverse.c create mode 100644 tests/bn_mod_sqrt.c create mode 100644 tests/bn_mont.c create mode 100644 tests/bn_mul_div.c create mode 100644 tests/bn_primes.c create mode 100644 tests/bn_print.c create mode 100644 tests/bn_shift.c create mode 100644 tests/bn_test.c create mode 100644 tests/bn_to_string.c create mode 100644 tests/bn_unit.c create mode 100644 tests/bn_word.c create mode 100644 tests/buffertest.c create mode 100644 tests/bytestringtest.c create mode 100644 tests/ca-int-ecdsa.crl create mode 100644 tests/ca-int-ecdsa.pem create mode 100644 tests/ca-int-rsa.crl create mode 100644 tests/ca-int-rsa.pem create mode 100644 tests/ca-root-ecdsa.pem create mode 100644 tests/ca-root-rsa.pem create mode 100644 tests/ca.pem create mode 100644 tests/callback.c create mode 100644 tests/callbackfailures.c create mode 100644 tests/casttest.c create mode 100644 tests/chacha20_poly1305_tests.txt create mode 100644 tests/chachatest.c create mode 100644 tests/cipher_list.c create mode 100644 tests/cipherstest.c create mode 100644 tests/client.c create mode 100644 tests/client.pem create mode 100644 tests/client1-ecdsa-chain.pem create mode 100644 tests/client1-ecdsa.pem create mode 100644 tests/client1-rsa-chain.pem create mode 100644 tests/client1-rsa.pem create mode 100644 tests/client2-ecdsa-chain.pem create mode 100644 tests/client2-ecdsa.pem create mode 100644 tests/client2-rsa-chain.pem create mode 100644 tests/client2-rsa.pem create mode 100644 tests/client3-ecdsa-chain.pem create mode 100644 tests/client3-ecdsa.pem create mode 100644 tests/client3-rsa-chain.pem create mode 100644 tests/client3-rsa.pem create mode 100644 tests/clienttest.c create mode 100644 tests/cmstest.c create mode 100644 tests/compat/memmem.c create mode 100644 tests/configtest.c create mode 100644 tests/constraints.c create mode 100644 tests/ctlog.conf create mode 100644 tests/cttest.c create mode 100644 tests/destest.c create mode 100644 tests/dhtest.c create mode 100644 tests/dsatest.c create mode 100644 tests/dtlstest.c create mode 100644 tests/ec_asn1_test.c create mode 100644 tests/ec_point_conversion.c create mode 100644 tests/ecc_cdh.c create mode 100644 tests/ecdhtest.c create mode 100644 tests/ecdsatest.c create mode 100644 tests/ectest.c create mode 100644 tests/ed25519test.c create mode 100644 tests/empty.c create mode 100644 tests/enginetest.c create mode 100644 tests/evp_ecx_test.c create mode 100644 tests/evp_pkey_check.c create mode 100644 tests/evp_pkey_cleanup.c create mode 100644 tests/evp_test.c create mode 100644 tests/evptest.c create mode 100644 tests/evptests.txt create mode 100644 tests/expirecallback.c create mode 100644 tests/explicit_bzero.c create mode 100644 tests/exportertest.c create mode 100644 tests/freenull.c create mode 100644 tests/freenull.c.body create mode 100644 tests/gcm128test.c create mode 100644 tests/gost2814789t.c create mode 100644 tests/handshake_table.c create mode 100644 tests/hkdf_test.c create mode 100644 tests/hmactest.c create mode 100644 tests/ideatest.c create mode 100644 tests/igetest.c create mode 100644 tests/init_pledge.c create mode 100644 tests/key_schedule.c create mode 100644 tests/keypairtest.c create mode 100644 tests/letsencrypt-r3.crt create mode 100644 tests/libressl.org.crt create mode 100644 tests/md_test.c create mode 100644 tests/objectstest.c create mode 100644 tests/ocsp_test.c create mode 100644 tests/pbkdf2.c create mode 100644 tests/pkcs7test.c create mode 100644 tests/policy.c create mode 100644 tests/policy_intermediate.pem create mode 100644 tests/policy_intermediate_any.pem create mode 100644 tests/policy_intermediate_duplicate.pem create mode 100644 tests/policy_intermediate_invalid.pem create mode 100644 tests/policy_intermediate_mapped.pem create mode 100644 tests/policy_intermediate_mapped_any.pem create mode 100644 tests/policy_intermediate_mapped_oid3.pem create mode 100644 tests/policy_intermediate_require.pem create mode 100644 tests/policy_intermediate_require1.pem create mode 100644 tests/policy_intermediate_require2.pem create mode 100644 tests/policy_intermediate_require_duplicate.pem create mode 100644 tests/policy_intermediate_require_no_policies.pem create mode 100644 tests/policy_leaf.pem create mode 100644 tests/policy_leaf_any.pem create mode 100644 tests/policy_leaf_duplicate.pem create mode 100644 tests/policy_leaf_invalid.pem create mode 100644 tests/policy_leaf_none.pem create mode 100644 tests/policy_leaf_oid1.pem create mode 100644 tests/policy_leaf_oid2.pem create mode 100644 tests/policy_leaf_oid3.pem create mode 100644 tests/policy_leaf_oid4.pem create mode 100644 tests/policy_leaf_oid5.pem create mode 100644 tests/policy_leaf_require.pem create mode 100644 tests/policy_leaf_require1.pem create mode 100644 tests/policy_root.pem create mode 100644 tests/policy_root2.pem create mode 100644 tests/policy_root_cross_inhibit_mapping.pem create mode 100644 tests/poly1305test.c create mode 100644 tests/pq_expected.txt create mode 100644 tests/pq_test.c create mode 100644 tests/quictest.c create mode 100644 tests/randtest.c create mode 100644 tests/rc2_test.c create mode 100644 tests/rc4_test.c create mode 100644 tests/record_layer_test.c create mode 100644 tests/recordtest.c create mode 100644 tests/rfc3779.c create mode 100644 tests/rfc5280time.c create mode 100644 tests/rmd_test.c create mode 100644 tests/rsa_test.c create mode 100644 tests/server.c create mode 100644 tests/server.pem create mode 100644 tests/server1-ecdsa-chain.pem create mode 100644 tests/server1-ecdsa.pem create mode 100644 tests/server1-rsa-chain.pem create mode 100644 tests/server1-rsa.pem create mode 100644 tests/server2-ecdsa-chain.pem create mode 100644 tests/server2-ecdsa.pem create mode 100644 tests/server2-rsa-chain.pem create mode 100644 tests/server2-rsa.pem create mode 100644 tests/server3-ecdsa-chain.pem create mode 100644 tests/server3-ecdsa.pem create mode 100644 tests/server3-rsa-chain.pem create mode 100644 tests/server3-rsa.pem create mode 100644 tests/servertest.c create mode 100644 tests/sha_test.c create mode 100644 tests/signertest.c create mode 100644 tests/sm2crypttest.c create mode 100644 tests/sm2evptest.c create mode 100644 tests/sm2sigtest.c create mode 100644 tests/sm3test.c create mode 100644 tests/sm4test.c create mode 100644 tests/ssl_get_shared_ciphers.c create mode 100644 tests/ssl_methods.c create mode 100644 tests/ssl_set_alpn_protos.c create mode 100644 tests/ssl_verify_param.c create mode 100644 tests/ssl_versions.c create mode 100644 tests/ssltest.c create mode 100644 tests/string_table.c create mode 100644 tests/tests.h create mode 100755 tests/testssl create mode 100644 tests/timingsafe.c create mode 100644 tests/tls_ext_alpn.c create mode 100644 tests/tls_prf.c create mode 100644 tests/tlsexttest.c create mode 100644 tests/tlslegacytest.c create mode 100644 tests/tlstest.c create mode 100644 tests/utf8test.c create mode 100644 tests/util.c create mode 100644 tests/valid_handshakes_terminate.c create mode 100644 tests/verify.c create mode 100644 tests/verifytest.c create mode 100644 tests/wycheproof-primes.c create mode 100644 tests/x25519test.c create mode 100644 tests/x509_asn1.c create mode 100644 tests/x509_info.c create mode 100644 tests/x509attribute.c create mode 100644 tests/x509name.c create mode 100644 tests/x509req_ext.c create mode 100644 tests/xchacha20_poly1305_tests.txt create mode 100644 tls/empty.c create mode 100644 tls/tls.c create mode 100644 tls/tls_bio_cb.c create mode 100644 tls/tls_client.c create mode 100644 tls/tls_config.c create mode 100644 tls/tls_conninfo.c create mode 100644 tls/tls_internal.h create mode 100644 tls/tls_keypair.c create mode 100644 tls/tls_ocsp.c create mode 100644 tls/tls_peer.c create mode 100644 tls/tls_server.c create mode 100644 tls/tls_signer.c create mode 100644 tls/tls_util.c create mode 100644 tls/tls_verify.c diff --git a/apps/nc/atomicio.c b/apps/nc/atomicio.c new file mode 100644 index 0000000..344ac63 --- /dev/null +++ b/apps/nc/atomicio.c @@ -0,0 +1,67 @@ +/* $OpenBSD: atomicio.c,v 1.11 2012/12/04 02:24:47 deraadt Exp $ */ +/* + * Copyright (c) 2006 Damien Miller. All rights reserved. + * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. + * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. + * 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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 +#include +#include + +#include "atomicio.h" + +/* + * ensure all of data on socket comes through. f==read || f==vwrite + */ +size_t +atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n) +{ + char *s = _s; + size_t pos = 0; + ssize_t res; + struct pollfd pfd; + + pfd.fd = fd; + pfd.events = f == read ? POLLIN : POLLOUT; + while (n > pos) { + res = (f) (fd, s + pos, n - pos); + switch (res) { + case -1: + if (errno == EINTR) + continue; + if ((errno == EAGAIN) || (errno == ENOBUFS)) { + (void)poll(&pfd, 1, -1); + continue; + } + return 0; + case 0: + errno = EPIPE; + return pos; + default: + pos += (size_t)res; + } + } + return (pos); +} diff --git a/apps/nc/atomicio.h b/apps/nc/atomicio.h new file mode 100644 index 0000000..7bf5b25 --- /dev/null +++ b/apps/nc/atomicio.h @@ -0,0 +1,39 @@ +/* $OpenBSD: atomicio.h,v 1.2 2007/09/07 14:50:44 tobias Exp $ */ + +/* + * Copyright (c) 2006 Damien Miller. All rights reserved. + * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. + * 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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 _ATOMICIO_H +#define _ATOMICIO_H + +/* + * Ensure all of data on socket comes through. f==read || f==vwrite + */ +size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t); + +#define vwrite (ssize_t (*)(int, void *, size_t))write + +#endif /* _ATOMICIO_H */ diff --git a/apps/nc/compat/base64.c b/apps/nc/compat/base64.c new file mode 100644 index 0000000..f36c11a --- /dev/null +++ b/apps/nc/compat/base64.c @@ -0,0 +1,307 @@ +/* $OpenBSD: base64.c,v 1.15 2021/10/25 14:41:09 jca Exp $ */ + +/* + * Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(unsigned char const *src, size_t srclength, char *target, + size_t targsize) +{ + size_t datalength = 0; + unsigned char input[3]; + unsigned char output[4]; + int i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(char const *src, unsigned char *target, size_t targsize) +{ + int tarindex, state, ch; + unsigned char nextbyte; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = (unsigned char)*src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + nextbyte = ((pos - Base64) & 0x0f) << 4; + if (tarindex + 1 < targsize) + target[tarindex+1] = nextbyte; + else if (nextbyte) + return (-1); + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + nextbyte = ((pos - Base64) & 0x03) << 6; + if (tarindex + 1 < targsize) + target[tarindex+1] = nextbyte; + else if (nextbyte) + return (-1); + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = (unsigned char)*src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = (unsigned char)*src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = (unsigned char)*src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = (unsigned char)*src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && tarindex < targsize && + target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/apps/nc/netcat.c b/apps/nc/netcat.c new file mode 100644 index 0000000..1254a90 --- /dev/null +++ b/apps/nc/netcat.c @@ -0,0 +1,1910 @@ +/* $OpenBSD: netcat.c,v 1.226 2023/08/14 08:07:27 tb Exp $ */ +/* + * Copyright (c) 2001 Eric Jackson + * Copyright (c) 2015 Bob Beck. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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. + */ + +/* + * Re-written nc(1) for OpenBSD. Original implementation by + * *Hobbit* . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atomicio.h" + +#define PORT_MAX 65535 +#define UNIX_DG_TMP_SOCKET_SIZE 19 + +#define POLL_STDIN 0 +#define POLL_NETOUT 1 +#define POLL_NETIN 2 +#define POLL_STDOUT 3 +#define BUFSIZE 16384 + +#define TLS_NOVERIFY (1 << 1) +#define TLS_NONAME (1 << 2) +#define TLS_CCERT (1 << 3) +#define TLS_MUSTSTAPLE (1 << 4) + +/* Command Line Options */ +int dflag; /* detached, no stdin */ +int Fflag; /* fdpass sock to stdout */ +unsigned int iflag; /* Interval Flag */ +int kflag; /* More than one connect */ +int lflag; /* Bind to local port */ +int Nflag; /* shutdown() network socket */ +int nflag; /* Don't do name look up */ +char *Pflag; /* Proxy username */ +char *pflag; /* Localport flag */ +int rflag; /* Random ports flag */ +char *sflag; /* Source Address */ +int tflag; /* Telnet Emulation */ +int uflag; /* UDP - Default to TCP */ +int vflag; /* Verbosity */ +int xflag; /* Socks proxy */ +int zflag; /* Port Scan Flag */ +int Dflag; /* sodebug */ +int Iflag; /* TCP receive buffer size */ +int Oflag; /* TCP send buffer size */ +#ifdef TCP_MD5SIG +int Sflag; /* TCP MD5 signature option */ +#endif +int Tflag = -1; /* IP Type of Service */ +#ifdef SO_RTABLE +int rtableid = -1; +#endif + +int usetls; /* use TLS */ +const char *Cflag; /* Public cert file */ +const char *Kflag; /* Private key file */ +const char *oflag; /* OCSP stapling file */ +const char *Rflag; /* Root CA file */ +int tls_cachanged; /* Using non-default CA file */ +int TLSopt; /* TLS options */ +char *tls_expectname; /* required name in peer cert */ +char *tls_expecthash; /* required hash of peer cert */ +char *tls_ciphers; /* TLS ciphers */ +char *tls_protocols; /* TLS protocols */ +FILE *Zflag; /* file to save peer cert */ + +int recvcount, recvlimit; +int timeout = -1; +int family = AF_UNSPEC; +char *portlist[PORT_MAX+1]; +char *unix_dg_tmp_socket; +int ttl = -1; +int minttl = -1; + +void atelnet(int, unsigned char *, unsigned int); +int strtoport(char *portstr, int udp); +void build_ports(char *); +void help(void) __attribute__((noreturn)); +int local_listen(const char *, const char *, struct addrinfo); +void readwrite(int, struct tls *); +void fdpass(int nfd) __attribute__((noreturn)); +int remote_connect(const char *, const char *, struct addrinfo, char *); +int timeout_tls(int, struct tls *, int (*)(struct tls *)); +int timeout_connect(int, const struct sockaddr *, socklen_t); +int socks_connect(const char *, const char *, struct addrinfo, + const char *, const char *, struct addrinfo, int, const char *); +int udptest(int); +void connection_info(const char *, const char *, const char *, const char *); +int unix_bind(char *, int); +int unix_connect(char *); +int unix_listen(char *); +void set_common_sockopts(int, int); +int process_tos_opt(char *, int *); +int process_tls_opt(char *, int *); +void save_peer_cert(struct tls *_tls_ctx, FILE *_fp); +void report_sock(const char *, const struct sockaddr *, socklen_t, char *); +void report_tls(struct tls *tls_ctx, char * host); +void usage(int); +ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *); +ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *); +void tls_setup_client(struct tls *, int, char *); +struct tls *tls_setup_server(struct tls *, int, char *); + +int +main(int argc, char *argv[]) +{ + int ch, s = -1, ret, socksv; + char *host, *uport; + char ipaddr[NI_MAXHOST]; + struct addrinfo hints; + socklen_t len; + struct sockaddr_storage cliaddr; + char *proxy = NULL, *proxyport = NULL; + const char *errstr; + struct addrinfo proxyhints; + char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE]; + struct tls_config *tls_cfg = NULL; + struct tls *tls_ctx = NULL; + uint32_t protocols; + + ret = 1; + socksv = 5; + host = NULL; + uport = NULL; + Rflag = tls_default_ca_cert_file(); + + signal(SIGPIPE, SIG_IGN); + + while ((ch = getopt(argc, argv, + "46C:cDde:FH:hI:i:K:klM:m:NnO:o:P:p:R:rSs:T:tUuV:vW:w:X:x:Z:z")) + != -1) { + switch (ch) { + case '4': + family = AF_INET; + break; + case '6': + family = AF_INET6; + break; + case 'U': + family = AF_UNIX; + break; + case 'X': + if (strcasecmp(optarg, "connect") == 0) + socksv = -1; /* HTTP proxy CONNECT */ + else if (strcmp(optarg, "4") == 0) + socksv = 4; /* SOCKS v.4 */ + else if (strcmp(optarg, "5") == 0) + socksv = 5; /* SOCKS v.5 */ + else + errx(1, "unsupported proxy protocol"); + break; + case 'C': + Cflag = optarg; + break; + case 'c': + usetls = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + tls_expectname = optarg; + break; + case 'F': + Fflag = 1; + break; + case 'H': + tls_expecthash = optarg; + break; + case 'h': + help(); + break; + case 'i': + iflag = strtonum(optarg, 0, UINT_MAX, &errstr); + if (errstr) + errx(1, "interval %s: %s", errstr, optarg); + break; + case 'K': + Kflag = optarg; + break; + case 'k': + kflag = 1; + break; + case 'l': + lflag = 1; + break; + case 'M': + ttl = strtonum(optarg, 0, 255, &errstr); + if (errstr) + errx(1, "ttl is %s", errstr); + break; + case 'm': + minttl = strtonum(optarg, 0, 255, &errstr); + if (errstr) + errx(1, "minttl is %s", errstr); + break; + case 'N': + Nflag = 1; + break; + case 'n': + nflag = 1; + break; + case 'P': + Pflag = optarg; + break; + case 'p': + pflag = optarg; + break; + case 'R': + tls_cachanged = 1; + Rflag = optarg; + break; + case 'r': + rflag = 1; + break; + case 's': + sflag = optarg; + break; + case 't': + tflag = 1; + break; + case 'u': + uflag = 1; + break; +#ifdef SO_RTABLE + case 'V': + rtableid = (int)strtonum(optarg, 0, + RT_TABLEID_MAX, &errstr); + if (errstr) + errx(1, "rtable %s: %s", errstr, optarg); + break; +#endif + case 'v': + vflag = 1; + break; + case 'W': + recvlimit = strtonum(optarg, 1, INT_MAX, &errstr); + if (errstr) + errx(1, "receive limit %s: %s", errstr, optarg); + break; + case 'w': + timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr); + if (errstr) + errx(1, "timeout %s: %s", errstr, optarg); + timeout *= 1000; + break; + case 'x': + xflag = 1; + if ((proxy = strdup(optarg)) == NULL) + err(1, NULL); + break; + case 'Z': + if (strcmp(optarg, "-") == 0) + Zflag = stderr; + else if ((Zflag = fopen(optarg, "w")) == NULL) + err(1, "can't open %s", optarg); + break; + case 'z': + zflag = 1; + break; + case 'D': + Dflag = 1; + break; + case 'I': + Iflag = strtonum(optarg, 1, 65536 << 14, &errstr); + if (errstr != NULL) + errx(1, "TCP receive window %s: %s", + errstr, optarg); + break; + case 'O': + Oflag = strtonum(optarg, 1, 65536 << 14, &errstr); + if (errstr != NULL) + errx(1, "TCP send window %s: %s", + errstr, optarg); + break; + case 'o': + oflag = optarg; + break; +#ifdef TCP_MD5SIG + case 'S': + Sflag = 1; + break; +#endif + case 'T': + errstr = NULL; + errno = 0; + if (process_tls_opt(optarg, &TLSopt)) + break; + if (process_tos_opt(optarg, &Tflag)) + break; + if (strlen(optarg) > 1 && optarg[0] == '0' && + optarg[1] == 'x') + Tflag = (int)strtol(optarg, NULL, 16); + else + Tflag = (int)strtonum(optarg, 0, 255, + &errstr); + if (Tflag < 0 || Tflag > 255 || errstr || errno) + errx(1, "illegal tos/tls value %s", optarg); + break; + default: + usage(1); + } + } + argc -= optind; + argv += optind; + +#ifdef SO_RTABLE + if (rtableid >= 0) + if (setrtable(rtableid) == -1) + err(1, "setrtable"); +#endif + + /* Cruft to make sure options are clean, and used properly. */ + if (argc == 1 && family == AF_UNIX) { + host = argv[0]; + } else if (argc == 1 && lflag) { + uport = argv[0]; + } else if (argc == 2) { + host = argv[0]; + uport = argv[1]; + } else + usage(1); + + if (usetls) { + if (Cflag && unveil(Cflag, "r") == -1) + err(1, "unveil %s", Cflag); + if (unveil(Rflag, "r") == -1) + err(1, "unveil %s", Rflag); + if (Kflag && unveil(Kflag, "r") == -1) + err(1, "unveil %s", Kflag); + if (oflag && unveil(oflag, "r") == -1) + err(1, "unveil %s", oflag); + } else if (family == AF_UNIX && uflag && lflag && !kflag) { + /* + * After recvfrom(2) from client, the server connects + * to the client socket. As the client path is determined + * during runtime, we cannot unveil(2). + */ + } else { + if (family == AF_UNIX) { + if (unveil(host, "rwc") == -1) + err(1, "unveil %s", host); + if (uflag && !kflag) { + if (sflag) { + if (unveil(sflag, "rwc") == -1) + err(1, "unveil %s", sflag); + } else { + if (unveil("/tmp", "rwc") == -1) + err(1, "unveil /tmp"); + } + } + } else { + /* no filesystem visibility */ + if (unveil("/", "") == -1) + err(1, "unveil /"); + } + } + + if (family == AF_UNIX) { + if (pledge("stdio rpath wpath cpath tmppath unix", NULL) == -1) + err(1, "pledge"); + } else if (Fflag && Pflag) { + if (pledge("stdio inet dns sendfd tty", NULL) == -1) + err(1, "pledge"); + } else if (Fflag) { + if (pledge("stdio inet dns sendfd", NULL) == -1) + err(1, "pledge"); + } else if (Pflag && usetls) { + if (pledge("stdio rpath inet dns tty", NULL) == -1) + err(1, "pledge"); + } else if (Pflag) { + if (pledge("stdio inet dns tty", NULL) == -1) + err(1, "pledge"); + } else if (usetls) { + if (pledge("stdio rpath inet dns", NULL) == -1) + err(1, "pledge"); + } else if (pledge("stdio inet dns", NULL) == -1) + err(1, "pledge"); + + if (lflag && sflag) + errx(1, "cannot use -s and -l"); + if (lflag && pflag) + errx(1, "cannot use -p and -l"); + if (lflag && zflag) + errx(1, "cannot use -z and -l"); + if (!lflag && kflag) + errx(1, "must use -l with -k"); + if (uflag && usetls) + errx(1, "cannot use -c and -u"); + if ((family == AF_UNIX) && usetls) + errx(1, "cannot use -c and -U"); + if ((family == AF_UNIX) && Fflag) + errx(1, "cannot use -F and -U"); + if (Fflag && usetls) + errx(1, "cannot use -c and -F"); + if (TLSopt && !usetls) + errx(1, "you must specify -c to use TLS options"); + if (Cflag && !usetls) + errx(1, "you must specify -c to use -C"); + if (Kflag && !usetls) + errx(1, "you must specify -c to use -K"); + if (Zflag && !usetls) + errx(1, "you must specify -c to use -Z"); + if (oflag && !Cflag) + errx(1, "you must specify -C to use -o"); + if (tls_cachanged && !usetls) + errx(1, "you must specify -c to use -R"); + if (tls_expecthash && !usetls) + errx(1, "you must specify -c to use -H"); + if (tls_expectname && !usetls) + errx(1, "you must specify -c to use -e"); + + /* Get name of temporary socket for unix datagram client */ + if ((family == AF_UNIX) && uflag && !lflag) { + if (sflag) { + unix_dg_tmp_socket = sflag; + } else { + strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX", + UNIX_DG_TMP_SOCKET_SIZE); + if (mktemp(unix_dg_tmp_socket_buf) == NULL) + err(1, "mktemp"); + unix_dg_tmp_socket = unix_dg_tmp_socket_buf; + } + } + + /* Initialize addrinfo structure. */ + if (family != AF_UNIX) { + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = family; + hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; + if (nflag) + hints.ai_flags |= AI_NUMERICHOST; + } + + if (xflag) { + if (uflag) + errx(1, "no proxy support for UDP mode"); + + if (lflag) + errx(1, "no proxy support for listen"); + + if (family == AF_UNIX) + errx(1, "no proxy support for unix sockets"); + + if (sflag) + errx(1, "no proxy support for local source address"); + + if (*proxy == '[') { + ++proxy; + proxyport = strchr(proxy, ']'); + if (proxyport == NULL) + errx(1, "missing closing bracket in proxy"); + *proxyport++ = '\0'; + if (*proxyport == '\0') + /* Use default proxy port. */ + proxyport = NULL; + else { + if (*proxyport == ':') + ++proxyport; + else + errx(1, "garbage proxy port delimiter"); + } + } else { + proxyport = strrchr(proxy, ':'); + if (proxyport != NULL) + *proxyport++ = '\0'; + } + + memset(&proxyhints, 0, sizeof(struct addrinfo)); + proxyhints.ai_family = family; + proxyhints.ai_socktype = SOCK_STREAM; + proxyhints.ai_protocol = IPPROTO_TCP; + if (nflag) + proxyhints.ai_flags |= AI_NUMERICHOST; + } + + if (usetls) { + if ((tls_cfg = tls_config_new()) == NULL) + errx(1, "unable to allocate TLS config"); + if (Rflag && tls_config_set_ca_file(tls_cfg, Rflag) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (Cflag && tls_config_set_cert_file(tls_cfg, Cflag) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (Kflag && tls_config_set_key_file(tls_cfg, Kflag) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (oflag && tls_config_set_ocsp_staple_file(tls_cfg, oflag) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (tls_config_parse_protocols(&protocols, tls_protocols) == -1) + errx(1, "invalid TLS protocols `%s'", tls_protocols); + if (tls_config_set_protocols(tls_cfg, protocols) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (tls_config_set_ciphers(tls_cfg, tls_ciphers) == -1) + errx(1, "%s", tls_config_error(tls_cfg)); + if (!lflag && (TLSopt & TLS_CCERT)) + errx(1, "clientcert is only valid with -l"); + if (TLSopt & TLS_NONAME) + tls_config_insecure_noverifyname(tls_cfg); + if (TLSopt & TLS_NOVERIFY) { + if (tls_expecthash != NULL) + errx(1, "-H and -T noverify may not be used " + "together"); + tls_config_insecure_noverifycert(tls_cfg); + } + if (TLSopt & TLS_MUSTSTAPLE) + tls_config_ocsp_require_stapling(tls_cfg); + + if (Pflag) { + if (pledge("stdio inet dns tty", NULL) == -1) + err(1, "pledge"); + } else if (pledge("stdio inet dns", NULL) == -1) + err(1, "pledge"); + } + if (lflag) { + ret = 0; + + if (family == AF_UNIX) { + if (uflag) + s = unix_bind(host, 0); + else + s = unix_listen(host); + } + + if (usetls) { + tls_config_verify_client_optional(tls_cfg); + if ((tls_ctx = tls_server()) == NULL) + errx(1, "tls server creation failed"); + if (tls_configure(tls_ctx, tls_cfg) == -1) + errx(1, "tls configuration failed (%s)", + tls_error(tls_ctx)); + } + /* Allow only one connection at a time, but stay alive. */ + for (;;) { + if (family != AF_UNIX) { + if (s != -1) + close(s); + s = local_listen(host, uport, hints); + } + if (s == -1) + err(1, NULL); + if (uflag && kflag) { + if (family == AF_UNIX) { + if (pledge("stdio unix", NULL) == -1) + err(1, "pledge"); + } + /* + * For UDP and -k, don't connect the socket, + * let it receive datagrams from multiple + * socket pairs. + */ + readwrite(s, NULL); + } else if (uflag && !kflag) { + /* + * For UDP and not -k, we will use recvfrom() + * initially to wait for a caller, then use + * the regular functions to talk to the caller. + */ + int rv; + char buf[2048]; + struct sockaddr_storage z; + + len = sizeof(z); + rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, + (struct sockaddr *)&z, &len); + if (rv == -1) + err(1, "recvfrom"); + + rv = connect(s, (struct sockaddr *)&z, len); + if (rv == -1) + err(1, "connect"); + + if (family == AF_UNIX) { + if (pledge("stdio unix", NULL) == -1) + err(1, "pledge"); + } + if (vflag) + report_sock("Connection received", + (struct sockaddr *)&z, len, + family == AF_UNIX ? host : NULL); + + readwrite(s, NULL); + } else { + struct tls *tls_cctx = NULL; + int connfd; + + len = sizeof(cliaddr); + connfd = accept4(s, (struct sockaddr *)&cliaddr, + &len, SOCK_NONBLOCK); + if (connfd == -1) { + /* For now, all errnos are fatal */ + err(1, "accept"); + } + if (vflag) + report_sock("Connection received", + (struct sockaddr *)&cliaddr, len, + family == AF_UNIX ? host : NULL); + if ((usetls) && + (tls_cctx = tls_setup_server(tls_ctx, connfd, host))) + readwrite(connfd, tls_cctx); + if (!usetls) + readwrite(connfd, NULL); + if (tls_cctx) + timeout_tls(s, tls_cctx, tls_close); + close(connfd); + tls_free(tls_cctx); + } + if (family == AF_UNIX && uflag) { + if (connect(s, NULL, 0) == -1) + err(1, "connect"); + } + + if (!kflag) + break; + } + } else if (family == AF_UNIX) { + ret = 0; + + if ((s = unix_connect(host)) > 0) { + if (!zflag) + readwrite(s, NULL); + close(s); + } else { + warn("%s", host); + ret = 1; + } + + if (uflag) + unlink(unix_dg_tmp_socket); + return ret; + } else { + int i = 0; + + /* Construct the portlist[] array. */ + build_ports(uport); + + /* Cycle through portlist, connecting to each port. */ + for (s = -1, i = 0; portlist[i] != NULL; i++) { + if (s != -1) + close(s); + tls_free(tls_ctx); + tls_ctx = NULL; + + if (usetls) { + if ((tls_ctx = tls_client()) == NULL) + errx(1, "tls client creation failed"); + if (tls_configure(tls_ctx, tls_cfg) == -1) + errx(1, "tls configuration failed (%s)", + tls_error(tls_ctx)); + } + if (xflag) + s = socks_connect(host, portlist[i], hints, + proxy, proxyport, proxyhints, socksv, + Pflag); + else + s = remote_connect(host, portlist[i], hints, + ipaddr); + + if (s == -1) + continue; + + ret = 0; + if (vflag || zflag) { + int print_info = 1; + + /* For UDP, make sure we are connected. */ + if (uflag) { + /* No info on failed or skipped test. */ + if ((print_info = udptest(s)) == -1) { + ret = 1; + continue; + } + } + if (print_info == 1) + connection_info(host, portlist[i], + uflag ? "udp" : "tcp", ipaddr); + } + if (Fflag) + fdpass(s); + else { + if (usetls) + tls_setup_client(tls_ctx, s, host); + if (!zflag) + readwrite(s, tls_ctx); + if (tls_ctx) + timeout_tls(s, tls_ctx, tls_close); + } + } + } + + if (s != -1) + close(s); + tls_free(tls_ctx); + tls_config_free(tls_cfg); + + return ret; +} + +/* + * unix_bind() + * Returns a unix socket bound to the given path + */ +int +unix_bind(char *path, int flags) +{ + struct sockaddr_un s_un; + int s, save_errno; + + /* Create unix domain socket. */ + if ((s = socket(AF_UNIX, flags | (uflag ? SOCK_DGRAM : SOCK_STREAM), + 0)) == -1) + return -1; + + memset(&s_un, 0, sizeof(struct sockaddr_un)); + s_un.sun_family = AF_UNIX; + + if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >= + sizeof(s_un.sun_path)) { + close(s); + errno = ENAMETOOLONG; + return -1; + } + + if (bind(s, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) { + save_errno = errno; + close(s); + errno = save_errno; + return -1; + } + if (vflag) + report_sock("Bound", NULL, 0, path); + + return s; +} + +int +timeout_tls(int s, struct tls *tls_ctx, int (*func)(struct tls *)) +{ + struct pollfd pfd; + int ret; + + while ((ret = (*func)(tls_ctx)) != 0) { + if (ret == TLS_WANT_POLLIN) + pfd.events = POLLIN; + else if (ret == TLS_WANT_POLLOUT) + pfd.events = POLLOUT; + else + break; + pfd.fd = s; + if ((ret = poll(&pfd, 1, timeout)) == 1) + continue; + else if (ret == 0) { + errno = ETIMEDOUT; + ret = -1; + break; + } else + err(1, "poll failed"); + } + + return ret; +} + +void +tls_setup_client(struct tls *tls_ctx, int s, char *host) +{ + const char *errstr; + + if (tls_connect_socket(tls_ctx, s, + tls_expectname ? tls_expectname : host) == -1) { + errx(1, "tls connection failed (%s)", + tls_error(tls_ctx)); + } + if (timeout_tls(s, tls_ctx, tls_handshake) == -1) { + if ((errstr = tls_error(tls_ctx)) == NULL) + errstr = strerror(errno); + errx(1, "tls handshake failed (%s)", errstr); + } + if (vflag) + report_tls(tls_ctx, host); + if (tls_expecthash && (tls_peer_cert_hash(tls_ctx) == NULL || + strcmp(tls_expecthash, tls_peer_cert_hash(tls_ctx)) != 0)) + errx(1, "peer certificate is not %s", tls_expecthash); + if (Zflag) { + save_peer_cert(tls_ctx, Zflag); + if (Zflag != stderr && (fclose(Zflag) != 0)) + err(1, "fclose failed saving peer cert"); + } +} + +struct tls * +tls_setup_server(struct tls *tls_ctx, int connfd, char *host) +{ + struct tls *tls_cctx; + const char *errstr; + + if (tls_accept_socket(tls_ctx, &tls_cctx, connfd) == -1) { + warnx("tls accept failed (%s)", tls_error(tls_ctx)); + } else if (timeout_tls(connfd, tls_cctx, tls_handshake) == -1) { + if ((errstr = tls_error(tls_cctx)) == NULL) + errstr = strerror(errno); + warnx("tls handshake failed (%s)", errstr); + } else { + int gotcert = tls_peer_cert_provided(tls_cctx); + + if (vflag && gotcert) + report_tls(tls_cctx, host); + if ((TLSopt & TLS_CCERT) && !gotcert) + warnx("No client certificate provided"); + else if (gotcert && tls_expecthash && + (tls_peer_cert_hash(tls_cctx) == NULL || + strcmp(tls_expecthash, tls_peer_cert_hash(tls_cctx)) != 0)) + warnx("peer certificate is not %s", tls_expecthash); + else if (gotcert && tls_expectname && + (!tls_peer_cert_contains_name(tls_cctx, tls_expectname))) + warnx("name (%s) not found in client cert", + tls_expectname); + else { + return tls_cctx; + } + } + return NULL; +} + +/* + * unix_connect() + * Returns a socket connected to a local unix socket. Returns -1 on failure. + */ +int +unix_connect(char *path) +{ + struct sockaddr_un s_un; + int s, save_errno; + + if (uflag) { + if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) == -1) + return -1; + } else { + if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) + return -1; + } + + memset(&s_un, 0, sizeof(struct sockaddr_un)); + s_un.sun_family = AF_UNIX; + + if (strlcpy(s_un.sun_path, path, sizeof(s_un.sun_path)) >= + sizeof(s_un.sun_path)) { + close(s); + errno = ENAMETOOLONG; + return -1; + } + if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) { + save_errno = errno; + close(s); + errno = save_errno; + return -1; + } + return s; +} + +/* + * unix_listen() + * Create a unix domain socket, and listen on it. + */ +int +unix_listen(char *path) +{ + int s; + + if ((s = unix_bind(path, 0)) == -1) + return -1; + if (listen(s, 5) == -1) { + close(s); + return -1; + } + if (vflag) + report_sock("Listening", NULL, 0, path); + + return s; +} + +/* + * remote_connect() + * Returns a socket connected to a remote host. Properly binds to a local + * port or source address if needed. Returns -1 on failure. + */ +int +remote_connect(const char *host, const char *port, struct addrinfo hints, + char *ipaddr) +{ + struct addrinfo *res, *res0; + int s = -1, error, herr, save_errno; +#ifdef SO_BINDANY + int on = 1; +#endif + + if ((error = getaddrinfo(host, port, &hints, &res0))) + errx(1, "getaddrinfo for host \"%s\" port %s: %s", host, + port, gai_strerror(error)); + + for (res = res0; res; res = res->ai_next) { + if ((s = socket(res->ai_family, res->ai_socktype | + SOCK_NONBLOCK, res->ai_protocol)) == -1) + continue; + + /* Bind to a local port or source address if specified. */ + if (sflag || pflag) { + struct addrinfo ahints, *ares; + +#ifdef SO_BINDANY + /* try SO_BINDANY, but don't insist */ + setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)); +#endif + memset(&ahints, 0, sizeof(struct addrinfo)); + ahints.ai_family = res->ai_family; + ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM; + ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP; + ahints.ai_flags = AI_PASSIVE; + if ((error = getaddrinfo(sflag, pflag, &ahints, &ares))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); + + if (bind(s, (struct sockaddr *)ares->ai_addr, + ares->ai_addrlen) == -1) + err(1, "bind failed"); + freeaddrinfo(ares); + } + + set_common_sockopts(s, res->ai_family); + + if (ipaddr != NULL) { + herr = getnameinfo(res->ai_addr, res->ai_addrlen, + ipaddr, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + switch (herr) { + case 0: + break; + case EAI_SYSTEM: + err(1, "getnameinfo"); + default: + errx(1, "getnameinfo: %s", gai_strerror(herr)); + } + } + + if (timeout_connect(s, res->ai_addr, res->ai_addrlen) == 0) + break; + + if (vflag) { + /* only print IP if there is something to report */ + if (nflag || ipaddr == NULL || + (strncmp(host, ipaddr, NI_MAXHOST) == 0)) + warn("connect to %s port %s (%s) failed", host, + port, uflag ? "udp" : "tcp"); + else + warn("connect to %s (%s) port %s (%s) failed", + host, ipaddr, port, uflag ? "udp" : "tcp"); + } + + save_errno = errno; + close(s); + errno = save_errno; + s = -1; + } + + freeaddrinfo(res0); + + return s; +} + +int +timeout_connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + struct pollfd pfd; + socklen_t optlen; + int optval; + int ret; + + if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) { + pfd.fd = s; + pfd.events = POLLOUT; + if ((ret = poll(&pfd, 1, timeout)) == 1) { + optlen = sizeof(optval); + if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR, + &optval, &optlen)) == 0) { + errno = optval; + ret = optval == 0 ? 0 : -1; + } + } else if (ret == 0) { + errno = ETIMEDOUT; + ret = -1; + } else + err(1, "poll failed"); + } + + return ret; +} + +/* + * local_listen() + * Returns a socket listening on a local port, binds to specified source + * address. Returns -1 on failure. + */ +int +local_listen(const char *host, const char *port, struct addrinfo hints) +{ + struct addrinfo *res, *res0; + int s = -1, save_errno; +#ifdef SO_REUSEPORT + int ret, x = 1; +#endif + int error; + + /* Allow nodename to be null. */ + hints.ai_flags |= AI_PASSIVE; + + /* + * In the case of binding to a wildcard address + * default to binding to an ipv4 address. + */ + if (host == NULL && hints.ai_family == AF_UNSPEC) + hints.ai_family = AF_INET; + + if ((error = getaddrinfo(host, port, &hints, &res0))) + errx(1, "getaddrinfo: %s", gai_strerror(error)); + + for (res = res0; res; res = res->ai_next) { + if ((s = socket(res->ai_family, res->ai_socktype, + res->ai_protocol)) == -1) + continue; + +#ifdef SO_REUSEPORT + ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x)); + if (ret == -1) + err(1, NULL); +#endif + + set_common_sockopts(s, res->ai_family); + + if (bind(s, (struct sockaddr *)res->ai_addr, + res->ai_addrlen) == 0) + break; + + save_errno = errno; + close(s); + errno = save_errno; + s = -1; + } + + if (!uflag && s != -1) { + if (listen(s, 1) == -1) + err(1, "listen"); + } + if (vflag && s != -1) { + struct sockaddr_storage ss; + socklen_t len; + + len = sizeof(ss); + if (getsockname(s, (struct sockaddr *)&ss, &len) == -1) + err(1, "getsockname"); + report_sock(uflag ? "Bound" : "Listening", + (struct sockaddr *)&ss, len, NULL); + } + + freeaddrinfo(res0); + + return s; +} + +/* + * readwrite() + * Loop that polls on the network file descriptor and stdin. + */ +void +readwrite(int net_fd, struct tls *tls_ctx) +{ + struct pollfd pfd[4]; + int stdin_fd = STDIN_FILENO; + int stdout_fd = STDOUT_FILENO; + unsigned char netinbuf[BUFSIZE]; + size_t netinbufpos = 0; + unsigned char stdinbuf[BUFSIZE]; + size_t stdinbufpos = 0; + int n, num_fds; + ssize_t ret; + + /* don't read from stdin if requested */ + if (dflag) + stdin_fd = -1; + + /* stdin */ + pfd[POLL_STDIN].fd = stdin_fd; + pfd[POLL_STDIN].events = POLLIN; + + /* network out */ + pfd[POLL_NETOUT].fd = net_fd; + pfd[POLL_NETOUT].events = 0; + + /* network in */ + pfd[POLL_NETIN].fd = net_fd; + pfd[POLL_NETIN].events = POLLIN; + + /* stdout */ + pfd[POLL_STDOUT].fd = stdout_fd; + pfd[POLL_STDOUT].events = 0; + + while (1) { + /* both inputs are gone, buffers are empty, we are done */ + if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1 && + stdinbufpos == 0 && netinbufpos == 0) + return; + /* both outputs are gone, we can't continue */ + if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) + return; + /* listen and net in gone, queues empty, done */ + if (lflag && pfd[POLL_NETIN].fd == -1 && + stdinbufpos == 0 && netinbufpos == 0) + return; + + /* help says -i is for "wait between lines sent". We read and + * write arbitrary amounts of data, and we don't want to start + * scanning for newlines, so this is as good as it gets */ + if (iflag) + sleep(iflag); + + /* poll */ + num_fds = poll(pfd, 4, timeout); + + /* treat poll errors */ + if (num_fds == -1) + err(1, "polling error"); + + /* timeout happened */ + if (num_fds == 0) + return; + + /* treat socket error conditions */ + for (n = 0; n < 4; n++) { + if (pfd[n].revents & (POLLERR|POLLNVAL)) { + pfd[n].fd = -1; + } + } + /* reading is possible after HUP */ + if (pfd[POLL_STDIN].events & POLLIN && + pfd[POLL_STDIN].revents & POLLHUP && + !(pfd[POLL_STDIN].revents & POLLIN)) + pfd[POLL_STDIN].fd = -1; + + if (pfd[POLL_NETIN].events & POLLIN && + pfd[POLL_NETIN].revents & POLLHUP && + !(pfd[POLL_NETIN].revents & POLLIN)) + pfd[POLL_NETIN].fd = -1; + + if (pfd[POLL_NETOUT].revents & POLLHUP) { + if (pfd[POLL_NETOUT].fd != -1 && Nflag) + shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); + pfd[POLL_NETOUT].fd = -1; + } + /* if HUP, stop watching stdout */ + if (pfd[POLL_STDOUT].revents & POLLHUP) + pfd[POLL_STDOUT].fd = -1; + /* if no net out, stop watching stdin */ + if (pfd[POLL_NETOUT].fd == -1) + pfd[POLL_STDIN].fd = -1; + /* if no stdout, stop watching net in */ + if (pfd[POLL_STDOUT].fd == -1) { + if (pfd[POLL_NETIN].fd != -1) + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } + + /* try to read from stdin */ + if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) { + ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf, + &stdinbufpos, NULL); + if (ret == TLS_WANT_POLLIN) + pfd[POLL_STDIN].events = POLLIN; + else if (ret == TLS_WANT_POLLOUT) + pfd[POLL_STDIN].events = POLLOUT; + else if (ret == 0 || ret == -1) + pfd[POLL_STDIN].fd = -1; + /* read something - poll net out */ + if (stdinbufpos > 0) + pfd[POLL_NETOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (stdinbufpos == BUFSIZE) + pfd[POLL_STDIN].events = 0; + } + /* try to write to network */ + if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) { + ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf, + &stdinbufpos, tls_ctx); + if (ret == TLS_WANT_POLLIN) + pfd[POLL_NETOUT].events = POLLIN; + else if (ret == TLS_WANT_POLLOUT) + pfd[POLL_NETOUT].events = POLLOUT; + else if (ret == -1) + pfd[POLL_NETOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (stdinbufpos == 0) + pfd[POLL_NETOUT].events = 0; + /* buffer no longer full - poll stdin again */ + if (stdinbufpos < BUFSIZE) + pfd[POLL_STDIN].events = POLLIN; + } + /* try to read from network */ + if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) { + ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf, + &netinbufpos, tls_ctx); + if (ret == TLS_WANT_POLLIN) + pfd[POLL_NETIN].events = POLLIN; + else if (ret == TLS_WANT_POLLOUT) + pfd[POLL_NETIN].events = POLLOUT; + else if (ret == -1) + pfd[POLL_NETIN].fd = -1; + /* eof on net in - remove from pfd */ + if (ret == 0) { + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + } + if (recvlimit > 0 && ++recvcount >= recvlimit) { + if (pfd[POLL_NETIN].fd != -1) + shutdown(pfd[POLL_NETIN].fd, SHUT_RD); + pfd[POLL_NETIN].fd = -1; + pfd[POLL_STDIN].fd = -1; + } + /* read something - poll stdout */ + if (netinbufpos > 0) + pfd[POLL_STDOUT].events = POLLOUT; + /* filled buffer - remove self from polling */ + if (netinbufpos == BUFSIZE) + pfd[POLL_NETIN].events = 0; + /* handle telnet */ + if (pfd[POLL_NETIN].fd != -1 && tflag) + atelnet(pfd[POLL_NETIN].fd, netinbuf, + netinbufpos); + } + /* try to write to stdout */ + if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) { + ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf, + &netinbufpos, NULL); + if (ret == TLS_WANT_POLLIN) + pfd[POLL_STDOUT].events = POLLIN; + else if (ret == TLS_WANT_POLLOUT) + pfd[POLL_STDOUT].events = POLLOUT; + else if (ret == -1) + pfd[POLL_STDOUT].fd = -1; + /* buffer empty - remove self from polling */ + if (netinbufpos == 0) + pfd[POLL_STDOUT].events = 0; + /* buffer no longer full - poll net in again */ + if (netinbufpos < BUFSIZE) + pfd[POLL_NETIN].events = POLLIN; + } + + /* stdin gone and queue empty? */ + if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) { + if (pfd[POLL_NETOUT].fd != -1 && Nflag) + shutdown(pfd[POLL_NETOUT].fd, SHUT_WR); + pfd[POLL_NETOUT].fd = -1; + } + /* net in gone and queue empty? */ + if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) { + pfd[POLL_STDOUT].fd = -1; + } + } +} + +ssize_t +drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) +{ + ssize_t n; + ssize_t adjust; + + if (fd == -1) + return -1; + + if (tls) { + n = tls_write(tls, buf, *bufpos); + if (n == -1) + errx(1, "tls write failed (%s)", tls_error(tls)); + } else { + n = write(fd, buf, *bufpos); + /* don't treat EAGAIN, EINTR as error */ + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = TLS_WANT_POLLOUT; + } + if (n <= 0) + return n; + /* adjust buffer */ + adjust = *bufpos - n; + if (adjust > 0) + memmove(buf, buf + n, adjust); + *bufpos -= n; + return n; +} + +ssize_t +fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) +{ + size_t num = BUFSIZE - *bufpos; + ssize_t n; + + if (fd == -1) + return -1; + + if (tls) { + n = tls_read(tls, buf + *bufpos, num); + if (n == -1) + errx(1, "tls read failed (%s)", tls_error(tls)); + } else { + n = read(fd, buf + *bufpos, num); + /* don't treat EAGAIN, EINTR as error */ + if (n == -1 && (errno == EAGAIN || errno == EINTR)) + n = TLS_WANT_POLLIN; + } + if (n <= 0) + return n; + *bufpos += n; + return n; +} + +/* + * fdpass() + * Pass the connected file descriptor to stdout and exit. + */ +void +fdpass(int nfd) +{ + struct msghdr mh; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(int))]; + } cmsgbuf; + struct cmsghdr *cmsg; + struct iovec iov; + char c = '\0'; + ssize_t r; + struct pollfd pfd; + + /* Avoid obvious stupidity */ + if (isatty(STDOUT_FILENO)) + errx(1, "Cannot pass file descriptor to tty"); + + memset(&mh, 0, sizeof(mh)); + memset(&cmsgbuf, 0, sizeof(cmsgbuf)); + memset(&iov, 0, sizeof(iov)); + + mh.msg_control = (caddr_t)&cmsgbuf.buf; + mh.msg_controllen = sizeof(cmsgbuf.buf); + cmsg = CMSG_FIRSTHDR(&mh); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = nfd; + + iov.iov_base = &c; + iov.iov_len = 1; + mh.msg_iov = &iov; + mh.msg_iovlen = 1; + + memset(&pfd, 0, sizeof(pfd)); + pfd.fd = STDOUT_FILENO; + pfd.events = POLLOUT; + for (;;) { + r = sendmsg(STDOUT_FILENO, &mh, 0); + if (r == -1) { + if (errno == EAGAIN || errno == EINTR) { + if (poll(&pfd, 1, -1) == -1) + err(1, "poll"); + continue; + } + err(1, "sendmsg"); + } else if (r != 1) + errx(1, "sendmsg: unexpected return value %zd", r); + else + break; + } + exit(0); +} + +/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ +void +atelnet(int nfd, unsigned char *buf, unsigned int size) +{ + unsigned char *p, *end; + unsigned char obuf[4]; + + if (size < 3) + return; + end = buf + size - 2; + + for (p = buf; p < end; p++) { + if (*p != IAC) + continue; + + obuf[0] = IAC; + p++; + if ((*p == WILL) || (*p == WONT)) + obuf[1] = DONT; + else if ((*p == DO) || (*p == DONT)) + obuf[1] = WONT; + else + continue; + + p++; + obuf[2] = *p; + if (atomicio(vwrite, nfd, obuf, 3) != 3) + warn("Write Error!"); + } +} + +int +strtoport(char *portstr, int udp) +{ + struct servent *entry; + const char *errstr; + char *proto; + int port = -1; + + proto = udp ? "udp" : "tcp"; + + port = strtonum(portstr, 1, PORT_MAX, &errstr); + if (errstr == NULL) + return port; + if (errno != EINVAL) + errx(1, "port number %s: %s", errstr, portstr); + if ((entry = getservbyname(portstr, proto)) == NULL) + errx(1, "service \"%s\" unknown", portstr); + return ntohs(entry->s_port); +} + +/* + * build_ports() + * Build an array of ports in portlist[], listing each port + * that we should try to connect to. + */ +void +build_ports(char *p) +{ + char *n; + int hi, lo, cp; + int x = 0; + + if (isdigit((unsigned char)*p) && (n = strchr(p, '-')) != NULL) { + *n = '\0'; + n++; + + /* Make sure the ports are in order: lowest->highest. */ + hi = strtoport(n, uflag); + lo = strtoport(p, uflag); + if (lo > hi) { + cp = hi; + hi = lo; + lo = cp; + } + + /* + * Initialize portlist with a random permutation. Based on + * Knuth, as in ip_randomid() in sys/netinet/ip_id.c. + */ + if (rflag) { + for (x = 0; x <= hi - lo; x++) { + cp = arc4random_uniform(x + 1); + portlist[x] = portlist[cp]; + if (asprintf(&portlist[cp], "%d", x + lo) == -1) + err(1, "asprintf"); + } + } else { /* Load ports sequentially. */ + for (cp = lo; cp <= hi; cp++) { + if (asprintf(&portlist[x], "%d", cp) == -1) + err(1, "asprintf"); + x++; + } + } + } else { + char *tmp; + + hi = strtoport(p, uflag); + if (asprintf(&tmp, "%d", hi) != -1) + portlist[0] = tmp; + else + err(1, NULL); + } +} + +/* + * udptest() + * Do a few writes to see if the UDP port is there. + * Fails once PF state table is full. + */ +int +udptest(int s) +{ + int i, ret; + + /* Only write to the socket in scan mode or interactive mode. */ + if (!zflag && !isatty(STDIN_FILENO)) + return 0; + + for (i = 0; i <= 3; i++) { + if (write(s, "X", 1) == 1) + ret = 1; + else + ret = -1; + } + return ret; +} + +void +connection_info(const char *host, const char *port, const char *proto, + const char *ipaddr) +{ + struct servent *sv; + char *service = "*"; + + /* Look up service name unless -n. */ + if (!nflag) { + sv = getservbyport(ntohs(atoi(port)), proto); + if (sv != NULL) + service = sv->s_name; + } + + fprintf(stderr, "Connection to %s", host); + + /* + * if we aren't connecting thru a proxy and + * there is something to report, print IP + */ + if (!nflag && !xflag && strcmp(host, ipaddr) != 0) + fprintf(stderr, " (%s)", ipaddr); + + fprintf(stderr, " %s port [%s/%s] succeeded!\n", port, proto, service); +} + +void +set_common_sockopts(int s, int af) +{ + int x = 1; + +#ifdef TCP_MD5SIG + if (Sflag) { + if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG, + &x, sizeof(x)) == -1) + err(1, NULL); + } +#endif + if (Dflag) { + if (setsockopt(s, SOL_SOCKET, SO_DEBUG, + &x, sizeof(x)) == -1) + err(1, NULL); + } + if (Tflag != -1) { + if (af == AF_INET && setsockopt(s, IPPROTO_IP, + IP_TOS, &Tflag, sizeof(Tflag)) == -1) + err(1, "set IP ToS"); + +#ifdef IPV6_TCLASS + else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6, + IPV6_TCLASS, &Tflag, sizeof(Tflag)) == -1) + err(1, "set IPv6 traffic class"); +#else + else if (af == AF_INET6) { + errno = ENOPROTOOPT; + err(1, "set IPv6 traffic class not supported"); + } +#endif + } + if (Iflag) { + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, + &Iflag, sizeof(Iflag)) == -1) + err(1, "set TCP receive buffer size"); + } + if (Oflag) { + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, + &Oflag, sizeof(Oflag)) == -1) + err(1, "set TCP send buffer size"); + } + + if (ttl != -1) { + if (af == AF_INET && setsockopt(s, IPPROTO_IP, + IP_TTL, &ttl, sizeof(ttl))) + err(1, "set IP TTL"); + + else if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6, + IPV6_UNICAST_HOPS, &ttl, sizeof(ttl))) + err(1, "set IPv6 unicast hops"); + } + + if (minttl != -1) { +#ifdef IP_MINTTL + if (af == AF_INET && setsockopt(s, IPPROTO_IP, + IP_MINTTL, &minttl, sizeof(minttl))) + err(1, "set IP min TTL"); +#endif + +#ifdef IPV6_MINHOPCOUNT + if (af == AF_INET6 && setsockopt(s, IPPROTO_IPV6, + IPV6_MINHOPCOUNT, &minttl, sizeof(minttl))) + err(1, "set IPv6 min hop count"); +#endif + } +} + +int +process_tos_opt(char *s, int *val) +{ + /* DiffServ Codepoints and other TOS mappings */ + const struct toskeywords { + const char *keyword; + int val; + } *t, toskeywords[] = { + { "af11", IPTOS_DSCP_AF11 }, + { "af12", IPTOS_DSCP_AF12 }, + { "af13", IPTOS_DSCP_AF13 }, + { "af21", IPTOS_DSCP_AF21 }, + { "af22", IPTOS_DSCP_AF22 }, + { "af23", IPTOS_DSCP_AF23 }, + { "af31", IPTOS_DSCP_AF31 }, + { "af32", IPTOS_DSCP_AF32 }, + { "af33", IPTOS_DSCP_AF33 }, + { "af41", IPTOS_DSCP_AF41 }, + { "af42", IPTOS_DSCP_AF42 }, + { "af43", IPTOS_DSCP_AF43 }, + { "critical", IPTOS_PREC_CRITIC_ECP }, + { "cs0", IPTOS_DSCP_CS0 }, + { "cs1", IPTOS_DSCP_CS1 }, + { "cs2", IPTOS_DSCP_CS2 }, + { "cs3", IPTOS_DSCP_CS3 }, + { "cs4", IPTOS_DSCP_CS4 }, + { "cs5", IPTOS_DSCP_CS5 }, + { "cs6", IPTOS_DSCP_CS6 }, + { "cs7", IPTOS_DSCP_CS7 }, + { "ef", IPTOS_DSCP_EF }, + { "inetcontrol", IPTOS_PREC_INTERNETCONTROL }, + { "lowdelay", IPTOS_LOWDELAY }, + { "netcontrol", IPTOS_PREC_NETCONTROL }, + { "reliability", IPTOS_RELIABILITY }, + { "throughput", IPTOS_THROUGHPUT }, + { NULL, -1 }, + }; + + for (t = toskeywords; t->keyword != NULL; t++) { + if (strcmp(s, t->keyword) == 0) { + *val = t->val; + return 1; + } + } + + return 0; +} + +int +process_tls_opt(char *s, int *flags) +{ + size_t len; + char *v; + + const struct tlskeywords { + const char *keyword; + int flag; + char **value; + } *t, tlskeywords[] = { + { "ciphers", -1, &tls_ciphers }, + { "clientcert", TLS_CCERT, NULL }, + { "muststaple", TLS_MUSTSTAPLE, NULL }, + { "noverify", TLS_NOVERIFY, NULL }, + { "noname", TLS_NONAME, NULL }, + { "protocols", -1, &tls_protocols }, + { NULL, -1, NULL }, + }; + + len = strlen(s); + if ((v = strchr(s, '=')) != NULL) { + len = v - s; + v++; + } + + for (t = tlskeywords; t->keyword != NULL; t++) { + if (strlen(t->keyword) == len && + strncmp(s, t->keyword, len) == 0) { + if (t->value != NULL) { + if (v == NULL) + errx(1, "invalid tls value `%s'", s); + *t->value = v; + } else { + *flags |= t->flag; + } + return 1; + } + } + return 0; +} + +void +save_peer_cert(struct tls *tls_ctx, FILE *fp) +{ + const char *pem; + size_t plen; + + if ((pem = tls_peer_cert_chain_pem(tls_ctx, &plen)) == NULL) + errx(1, "Can't get peer certificate"); + if (fprintf(fp, "%.*s", (int)plen, pem) < 0) + err(1, "unable to save peer cert"); + if (fflush(fp) != 0) + err(1, "unable to flush peer cert"); +} + +void +report_tls(struct tls *tls_ctx, char *host) +{ + time_t t; + const char *ocsp_url; + + fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", + tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); + fprintf(stderr, "Peer name: %s\n", + tls_expectname ? tls_expectname : host); + if (tls_peer_cert_subject(tls_ctx)) + fprintf(stderr, "Subject: %s\n", + tls_peer_cert_subject(tls_ctx)); + if (tls_peer_cert_issuer(tls_ctx)) + fprintf(stderr, "Issuer: %s\n", + tls_peer_cert_issuer(tls_ctx)); + if ((t = tls_peer_cert_notbefore(tls_ctx)) != -1) + fprintf(stderr, "Valid From: %s", ctime(&t)); + if ((t = tls_peer_cert_notafter(tls_ctx)) != -1) + fprintf(stderr, "Valid Until: %s", ctime(&t)); + if (tls_peer_cert_hash(tls_ctx)) + fprintf(stderr, "Cert Hash: %s\n", + tls_peer_cert_hash(tls_ctx)); + ocsp_url = tls_peer_ocsp_url(tls_ctx); + if (ocsp_url != NULL) + fprintf(stderr, "OCSP URL: %s\n", ocsp_url); + switch (tls_peer_ocsp_response_status(tls_ctx)) { + case TLS_OCSP_RESPONSE_SUCCESSFUL: + fprintf(stderr, "OCSP Stapling: %s\n", + tls_peer_ocsp_result(tls_ctx) == NULL ? "" : + tls_peer_ocsp_result(tls_ctx)); + fprintf(stderr, + " response_status=%d cert_status=%d crl_reason=%d\n", + tls_peer_ocsp_response_status(tls_ctx), + tls_peer_ocsp_cert_status(tls_ctx), + tls_peer_ocsp_crl_reason(tls_ctx)); + t = tls_peer_ocsp_this_update(tls_ctx); + fprintf(stderr, " this update: %s", + t != -1 ? ctime(&t) : "\n"); + t = tls_peer_ocsp_next_update(tls_ctx); + fprintf(stderr, " next update: %s", + t != -1 ? ctime(&t) : "\n"); + t = tls_peer_ocsp_revocation_time(tls_ctx); + fprintf(stderr, " revocation: %s", + t != -1 ? ctime(&t) : "\n"); + break; + case -1: + break; + default: + fprintf(stderr, + "OCSP Stapling: failure - response_status %d (%s)\n", + tls_peer_ocsp_response_status(tls_ctx), + tls_peer_ocsp_result(tls_ctx) == NULL ? "" : + tls_peer_ocsp_result(tls_ctx)); + break; + } +} + +void +report_sock(const char *msg, const struct sockaddr *sa, socklen_t salen, + char *path) +{ + char host[NI_MAXHOST], port[NI_MAXSERV]; + int herr; + int flags = NI_NUMERICSERV; + + if (path != NULL) { + fprintf(stderr, "%s on %s\n", msg, path); + return; + } + + if (nflag) + flags |= NI_NUMERICHOST; + + herr = getnameinfo(sa, salen, host, sizeof(host), port, sizeof(port), + flags); + switch (herr) { + case 0: + break; + case EAI_SYSTEM: + err(1, "getnameinfo"); + default: + errx(1, "getnameinfo: %s", gai_strerror(herr)); + } + + fprintf(stderr, "%s on %s %s\n", msg, host, port); +} + +void +help(void) +{ + usage(0); + fprintf(stderr, "\tCommand Summary:\n\ + \t-4 Use IPv4\n\ + \t-6 Use IPv6\n\ + \t-C certfile Public key file\n\ + \t-c Use TLS\n\ + \t-D Enable the debug socket option\n\ + \t-d Detach from stdin\n\ + \t-e name\t Required name in peer certificate\n\ + \t-F Pass socket fd\n\ + \t-H hash\t Hash string of peer certificate\n\ + \t-h This help text\n\ + \t-I length TCP receive buffer length\n\ + \t-i interval Delay interval for lines sent, ports scanned\n\ + \t-K keyfile Private key file\n\ + \t-k Keep inbound sockets open for multiple connects\n\ + \t-l Listen mode, for inbound connects\n\ + \t-M ttl Outgoing TTL / Hop Limit\n\ + \t-m minttl Minimum incoming TTL / Hop Limit\n\ + \t-N Shutdown the network socket after EOF on stdin\n\ + \t-n Suppress name/port resolutions\n\ + \t-O length TCP send buffer length\n\ + \t-o staplefile Staple file\n\ + \t-P proxyuser\tUsername for proxy authentication\n\ + \t-p port\t Specify local port for remote connects\n\ + \t-R CAfile CA bundle\n\ + \t-r Randomize remote ports\n" +#ifdef TCP_MD5SIG + "\t-S Enable the TCP MD5 signature option\n" +#endif + "\t-s sourceaddr Local source address\n\ + \t-T keyword TOS value or TLS options\n\ + \t-t Answer TELNET negotiation\n\ + \t-U Use UNIX domain socket\n\ + \t-u UDP mode\n" +#ifdef SO_RTABLE + "\t-V rtable Specify alternate routing table\n" +#endif + "\t-v Verbose\n\ + \t-W recvlimit Terminate after receiving a number of packets\n\ + \t-w timeout Timeout for connects and final net reads\n\ + \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\ + \t-x addr[:port]\tSpecify proxy address and port\n\ + \t-Z Peer certificate file\n\ + \t-z Zero-I/O mode [used for scanning]\n\ + Port numbers can be individual or ranges: lo-hi [inclusive]\n"); + exit(1); +} + +void +usage(int ret) +{ + fprintf(stderr, + "usage: nc [-46cDdFhklNnrStUuvz] [-C certfile] [-e name] " + "[-H hash] [-I length]\n" + "\t [-i interval] [-K keyfile] [-M ttl] [-m minttl] [-O length]\n" + "\t [-o staplefile] [-P proxy_username] [-p source_port] " + "[-R CAfile]\n" + "\t [-s sourceaddr] [-T keyword] [-V rtable] [-W recvlimit] " + "[-w timeout]\n" + "\t [-X proxy_protocol] [-x proxy_address[:port]] " + "[-Z peercertfile]\n" + "\t [destination] [port]\n"); + if (ret) + exit(1); +} diff --git a/apps/nc/socks.c b/apps/nc/socks.c new file mode 100644 index 0000000..7c7448c --- /dev/null +++ b/apps/nc/socks.c @@ -0,0 +1,400 @@ +/* $OpenBSD: socks.c,v 1.31 2022/06/08 20:20:26 djm Exp $ */ + +/* + * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. + * Copyright (c) 2004, 2005 Damien Miller. 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "atomicio.h" + +#define SOCKS_PORT "1080" +#define HTTP_PROXY_PORT "3128" +#define HTTP_MAXHDRS 64 +#define SOCKS_V5 5 +#define SOCKS_V4 4 +#define SOCKS_NOAUTH 0 +#define SOCKS_NOMETHOD 0xff +#define SOCKS_CONNECT 1 +#define SOCKS_IPV4 1 +#define SOCKS_DOMAIN 3 +#define SOCKS_IPV6 4 + +int remote_connect(const char *, const char *, struct addrinfo, char *); +int socks_connect(const char *, const char *, struct addrinfo, + const char *, const char *, struct addrinfo, int, + const char *); + +static int +decode_addrport(const char *h, const char *p, struct sockaddr *addr, + socklen_t addrlen, int v4only, int numeric) +{ + int r; + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = v4only ? PF_INET : PF_UNSPEC; + hints.ai_flags = numeric ? AI_NUMERICHOST : 0; + hints.ai_socktype = SOCK_STREAM; + r = getaddrinfo(h, p, &hints, &res); + /* Don't fatal when attempting to convert a numeric address */ + if (r != 0) { + if (!numeric) { + errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p, + gai_strerror(r)); + } + return (-1); + } + if (addrlen < res->ai_addrlen) { + freeaddrinfo(res); + errx(1, "internal error: addrlen < res->ai_addrlen"); + } + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return (0); +} + +static int +proxy_read_line(int fd, char *buf, size_t bufsz) +{ + size_t off; + + for(off = 0;;) { + if (off >= bufsz) + errx(1, "proxy read too long"); + if (atomicio(read, fd, buf + off, 1) != 1) + err(1, "proxy read"); + /* Skip CR */ + if (buf[off] == '\r') + continue; + if (buf[off] == '\n') { + buf[off] = '\0'; + break; + } + off++; + } + return (off); +} + +static void +getproxypass(const char *proxyuser, const char *proxyhost, + char *pw, size_t pwlen) +{ + char prompt[512]; + + snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ", + proxyuser, proxyhost); + if (readpassphrase(prompt, pw, pwlen, RPP_REQUIRE_TTY) == NULL) + errx(1, "Unable to read proxy passphrase"); +} + +/* + * Error strings adapted from the generally accepted SOCKSv4 spec: + * + * http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol + */ +static const char * +socks4_strerror(int e) +{ + switch (e) { + case 90: + return "Succeeded"; + case 91: + return "Request rejected or failed"; + case 92: + return "SOCKS server cannot connect to identd on the client"; + case 93: + return "Client program and identd report different user-ids"; + default: + return "Unknown error"; + } +} + +/* + * Error strings taken almost directly from RFC 1928. + */ +static const char * +socks5_strerror(int e) +{ + switch (e) { + case 0: + return "Succeeded"; + case 1: + return "General SOCKS server failure"; + case 2: + return "Connection not allowed by ruleset"; + case 3: + return "Network unreachable"; + case 4: + return "Host unreachable"; + case 5: + return "Connection refused"; + case 6: + return "TTL expired"; + case 7: + return "Command not supported"; + case 8: + return "Address type not supported"; + default: + return "Unknown error"; + } +} + +int +socks_connect(const char *host, const char *port, + struct addrinfo hints __attribute__ ((__unused__)), + const char *proxyhost, const char *proxyport, struct addrinfo proxyhints, + int socksv, const char *proxyuser) +{ + int proxyfd, r, authretry = 0; + size_t hlen, wlen; + unsigned char buf[1024]; + size_t cnt; + struct sockaddr_storage addr; + struct sockaddr_in *in4 = (struct sockaddr_in *)&addr; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr; + in_port_t serverport; + + if (proxyport == NULL) + proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT; + + /* Abuse API to lookup port */ + if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr, + sizeof(addr), 1, 1) == -1) + errx(1, "unknown port \"%.64s\"", port); + serverport = in4->sin_port; + + again: + if (authretry++ > 3) + errx(1, "Too many authentication failures"); + + proxyfd = remote_connect(proxyhost, proxyport, proxyhints, NULL); + + if (proxyfd < 0) + return (-1); + + if (socksv == 5) { + if (decode_addrport(host, port, (struct sockaddr *)&addr, + sizeof(addr), 0, 1) == -1) + addr.ss_family = 0; /* used in switch below */ + + /* Version 5, one method: no authentication */ + buf[0] = SOCKS_V5; + buf[1] = 1; + buf[2] = SOCKS_NOAUTH; + cnt = atomicio(vwrite, proxyfd, buf, 3); + if (cnt != 3) + err(1, "write failed (%zu/3)", cnt); + + cnt = atomicio(read, proxyfd, buf, 2); + if (cnt != 2) + err(1, "read failed (%zu/3)", cnt); + + if (buf[1] == SOCKS_NOMETHOD) + errx(1, "authentication method negotiation failed"); + + switch (addr.ss_family) { + case 0: + /* Version 5, connect: domain name */ + + /* Max domain name length is 255 bytes */ + hlen = strlen(host); + if (hlen > 255) + errx(1, "host name too long for SOCKS5"); + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_DOMAIN; + buf[4] = hlen; + memcpy(buf + 5, host, hlen); + memcpy(buf + 5 + hlen, &serverport, sizeof serverport); + wlen = 7 + hlen; + break; + case AF_INET: + /* Version 5, connect: IPv4 address */ + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_IPV4; + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port); + wlen = 10; + break; + case AF_INET6: + /* Version 5, connect: IPv6 address */ + buf[0] = SOCKS_V5; + buf[1] = SOCKS_CONNECT; + buf[2] = 0; + buf[3] = SOCKS_IPV6; + memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr); + memcpy(buf + 20, &in6->sin6_port, + sizeof in6->sin6_port); + wlen = 22; + break; + default: + errx(1, "internal error: silly AF"); + } + + cnt = atomicio(vwrite, proxyfd, buf, wlen); + if (cnt != wlen) + err(1, "write failed (%zu/%zu)", cnt, wlen); + + cnt = atomicio(read, proxyfd, buf, 4); + if (cnt != 4) + err(1, "read failed (%zu/4)", cnt); + if (buf[1] != 0) { + errx(1, "connection failed, SOCKSv5 error: %s", + socks5_strerror(buf[1])); + } + switch (buf[3]) { + case SOCKS_IPV4: + cnt = atomicio(read, proxyfd, buf + 4, 6); + if (cnt != 6) + err(1, "read failed (%zu/6)", cnt); + break; + case SOCKS_IPV6: + cnt = atomicio(read, proxyfd, buf + 4, 18); + if (cnt != 18) + err(1, "read failed (%zu/18)", cnt); + break; + default: + errx(1, "connection failed, unsupported address type"); + } + } else if (socksv == 4) { + /* This will exit on lookup failure */ + decode_addrport(host, port, (struct sockaddr *)&addr, + sizeof(addr), 1, 0); + + /* Version 4 */ + buf[0] = SOCKS_V4; + buf[1] = SOCKS_CONNECT; /* connect */ + memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + buf[8] = 0; /* empty username */ + wlen = 9; + + cnt = atomicio(vwrite, proxyfd, buf, wlen); + if (cnt != wlen) + err(1, "write failed (%zu/%zu)", cnt, wlen); + + cnt = atomicio(read, proxyfd, buf, 8); + if (cnt != 8) + err(1, "read failed (%zu/8)", cnt); + if (buf[1] != 90) { + errx(1, "connection failed, SOCKSv4 error: %s", + socks4_strerror(buf[1])); + } + } else if (socksv == -1) { + /* HTTP proxy CONNECT */ + + /* Disallow bad chars in hostname */ + if (strcspn(host, "\r\n\t []") != strlen(host)) + errx(1, "Invalid hostname"); + + /* Try to be sane about numeric IPv6 addresses */ + if (strchr(host, ':') != NULL) { + r = snprintf(buf, sizeof(buf), + "CONNECT [%s]:%d HTTP/1.0\r\n", + host, ntohs(serverport)); + } else { + r = snprintf(buf, sizeof(buf), + "CONNECT %s:%d HTTP/1.0\r\n", + host, ntohs(serverport)); + } + if (r < 0 || (size_t)r >= sizeof(buf)) + errx(1, "hostname too long"); + r = strlen(buf); + + cnt = atomicio(vwrite, proxyfd, buf, r); + if (cnt != r) + err(1, "write failed (%zu/%d)", cnt, r); + + if (authretry > 1) { + char proxypass[256]; + char resp[1024]; + + getproxypass(proxyuser, proxyhost, + proxypass, sizeof proxypass); + r = snprintf(buf, sizeof(buf), "%s:%s", + proxyuser, proxypass); + explicit_bzero(proxypass, sizeof proxypass); + if (r == -1 || (size_t)r >= sizeof(buf) || + b64_ntop(buf, strlen(buf), resp, + sizeof(resp)) == -1) + errx(1, "Proxy username/password too long"); + r = snprintf(buf, sizeof(buf), "Proxy-Authorization: " + "Basic %s\r\n", resp); + if (r < 0 || (size_t)r >= sizeof(buf)) + errx(1, "Proxy auth response too long"); + r = strlen(buf); + if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != r) + err(1, "write failed (%zu/%d)", cnt, r); + explicit_bzero(proxypass, sizeof proxypass); + explicit_bzero(buf, sizeof buf); + } + + /* Terminate headers */ + if ((cnt = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2) + err(1, "write failed (%zu/2)", cnt); + + /* Read status reply */ + proxy_read_line(proxyfd, buf, sizeof(buf)); + if (proxyuser != NULL && + (strncmp(buf, "HTTP/1.0 407 ", 12) == 0 || + strncmp(buf, "HTTP/1.1 407 ", 12) == 0)) { + if (authretry > 1) { + fprintf(stderr, "Proxy authentication " + "failed\n"); + } + close(proxyfd); + goto again; + } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 && + strncmp(buf, "HTTP/1.1 200 ", 12) != 0) + errx(1, "Proxy error: \"%s\"", buf); + + /* Headers continue until we hit an empty line */ + for (r = 0; r < HTTP_MAXHDRS; r++) { + proxy_read_line(proxyfd, buf, sizeof(buf)); + if (*buf == '\0') + break; + } + if (*buf != '\0') + errx(1, "Too many proxy headers received"); + } else + errx(1, "Unknown proxy protocol %d", socksv); + + return (proxyfd); +} diff --git a/apps/ocspcheck/compat/memmem.c b/apps/ocspcheck/compat/memmem.c new file mode 100644 index 0000000..9b11960 --- /dev/null +++ b/apps/ocspcheck/compat/memmem.c @@ -0,0 +1,183 @@ +/* $OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */ + +/* + * Copyright (c) 2005-2020 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +static char * +twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; + for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-2; + return hw == nw ? (char *)h-2 : 0; +} + +static char * +threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; + for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) + if (hw == nw) return (char *)h-3; + return hw == nw ? (char *)h-3 : 0; +} + +static char * +fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; + for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-4; + return hw == nw ? (char *)h-4 : 0; +} + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BITOP(a,b,op) \ + ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) + +/* + * Maxime Crochemore and Dominique Perrin, Two-way string-matching, + * Journal of the ACM, 38(3):651-675, July 1991. + */ +static char * +twoway_memmem(const unsigned char *h, const unsigned char *z, + const unsigned char *n, size_t l) +{ + size_t i, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (i=0; i n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (memcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Search loop */ + for (;;) { + /* If remainder of haystack is shorter than needle, done */ + if (z-h < l) return 0; + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l-1], &)) { + k = l-shift[h[l-1]]; + if (k) { + if (k < mem) k = mem; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); + if (k <= mem) return (char *)h; + h += p; + mem = mem0; + } +} + +void * +memmem(const void *h0, size_t k, const void *n0, size_t l) +{ + const unsigned char *h = h0, *n = n0; + + /* Return immediately on empty needle */ + if (!l) return (void *)h; + + /* Return immediately when needle is longer than haystack */ + if (k + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "http.h" + +/* + * A buffer for transferring HTTP/S data. + */ +struct httpxfer { + char *hbuf; /* header transfer buffer */ + size_t hbufsz; /* header buffer size */ + int headok; /* header has been parsed */ + char *bbuf; /* body transfer buffer */ + size_t bbufsz; /* body buffer size */ + int bodyok; /* body has been parsed */ + char *headbuf; /* lookaside buffer for headers */ + struct httphead *head; /* parsed headers */ + size_t headsz; /* number of headers */ +}; + +/* + * An HTTP/S connection object. + */ +struct http { + int fd; /* connected socket */ + short port; /* port number */ + struct source src; /* endpoint (raw) host */ + char *path; /* path to request */ + char *host; /* name of endpoint host */ + struct tls *ctx; /* if TLS */ + writefp writer; /* write function */ + readfp reader; /* read function */ +}; + +struct tls_config *tlscfg; + +static ssize_t +dosysread(char *buf, size_t sz, const struct http *http) +{ + ssize_t rc; + + rc = read(http->fd, buf, sz); + if (rc == -1) + warn("%s: read", http->src.ip); + return rc; +} + +static ssize_t +dosyswrite(const void *buf, size_t sz, const struct http *http) +{ + ssize_t rc; + + rc = write(http->fd, buf, sz); + if (rc == -1) + warn("%s: write", http->src.ip); + return rc; +} + +static ssize_t +dotlsread(char *buf, size_t sz, const struct http *http) +{ + ssize_t rc; + + do { + rc = tls_read(http->ctx, buf, sz); + } while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT); + + if (rc == -1) + warnx("%s: tls_read: %s", http->src.ip, + tls_error(http->ctx)); + return rc; +} + +static ssize_t +dotlswrite(const void *buf, size_t sz, const struct http *http) +{ + ssize_t rc; + + do { + rc = tls_write(http->ctx, buf, sz); + } while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT); + + if (rc == -1) + warnx("%s: tls_write: %s", http->src.ip, + tls_error(http->ctx)); + return rc; +} + +int +http_init(void) +{ + if (tlscfg != NULL) + return 0; + + tlscfg = tls_config_new(); + if (tlscfg == NULL) { + warn("tls_config_new"); + goto err; + } + + if (tls_config_set_ca_file(tlscfg, tls_default_ca_cert_file()) == -1) { + warn("tls_config_set_ca_file: %s", tls_config_error(tlscfg)); + goto err; + } + + return 0; + + err: + tls_config_free(tlscfg); + tlscfg = NULL; + + return -1; +} + +static ssize_t +http_read(char *buf, size_t sz, const struct http *http) +{ + ssize_t ssz, xfer; + + xfer = 0; + do { + if ((ssz = http->reader(buf, sz, http)) < 0) + return -1; + if (ssz == 0) + break; + xfer += ssz; + sz -= ssz; + buf += ssz; + } while (ssz > 0 && sz > 0); + + return xfer; +} + +static int +http_write(const char *buf, size_t sz, const struct http *http) +{ + ssize_t ssz, xfer; + + xfer = sz; + while (sz > 0) { + if ((ssz = http->writer(buf, sz, http)) < 0) + return -1; + sz -= ssz; + buf += (size_t)ssz; + } + return xfer; +} + +void +http_disconnect(struct http *http) +{ + int rc; + + if (http->ctx != NULL) { + /* TLS connection. */ + do { + rc = tls_close(http->ctx); + } while (rc == TLS_WANT_POLLIN || rc == TLS_WANT_POLLOUT); + + if (rc < 0) + warnx("%s: tls_close: %s", http->src.ip, + tls_error(http->ctx)); + + tls_free(http->ctx); + } + if (http->fd != -1) { + if (close(http->fd) == -1) + warn("%s: close", http->src.ip); + } + + http->fd = -1; + http->ctx = NULL; +} + +void +http_free(struct http *http) +{ + + if (http == NULL) + return; + http_disconnect(http); + free(http->host); + free(http->path); + free(http->src.ip); + free(http); +} + +struct http * +http_alloc(const struct source *addrs, size_t addrsz, + const char *host, short port, const char *path) +{ + struct sockaddr_storage ss; + int family, fd, c; + socklen_t len; + size_t cur, i = 0; + struct http *http; + + /* Do this while we still have addresses to connect. */ +again: + if (i == addrsz) + return NULL; + cur = i++; + + /* Convert to PF_INET or PF_INET6 address from string. */ + + memset(&ss, 0, sizeof(struct sockaddr_storage)); + + if (addrs[cur].family == 4) { + family = PF_INET; + ((struct sockaddr_in *)&ss)->sin_family = AF_INET; + ((struct sockaddr_in *)&ss)->sin_port = htons(port); + c = inet_pton(AF_INET, addrs[cur].ip, + &((struct sockaddr_in *)&ss)->sin_addr); + len = sizeof(struct sockaddr_in); + } else if (addrs[cur].family == 6) { + family = PF_INET6; + ((struct sockaddr_in6 *)&ss)->sin6_family = AF_INET6; + ((struct sockaddr_in6 *)&ss)->sin6_port = htons(port); + c = inet_pton(AF_INET6, addrs[cur].ip, + &((struct sockaddr_in6 *)&ss)->sin6_addr); + len = sizeof(struct sockaddr_in6); + } else { + warnx("%s: unknown family", addrs[cur].ip); + goto again; + } + + if (c < 0) { + warn("%s: inet_ntop", addrs[cur].ip); + goto again; + } else if (c == 0) { + warnx("%s: inet_ntop", addrs[cur].ip); + goto again; + } + + /* Create socket and connect. */ + + fd = socket(family, SOCK_STREAM, 0); + if (fd == -1) { + warn("%s: socket", addrs[cur].ip); + goto again; + } else if (connect(fd, (struct sockaddr *)&ss, len) == -1) { + warn("%s: connect", addrs[cur].ip); + close(fd); + goto again; + } + + /* Allocate the communicator. */ + + http = calloc(1, sizeof(struct http)); + if (http == NULL) { + warn("calloc"); + close(fd); + return NULL; + } + http->fd = fd; + http->port = port; + http->src.family = addrs[cur].family; + http->src.ip = strdup(addrs[cur].ip); + http->host = strdup(host); + http->path = strdup(path); + if (http->src.ip == NULL || http->host == NULL || http->path == NULL) { + warn("strdup"); + goto err; + } + + /* If necessary, do our TLS setup. */ + + if (port != 443) { + http->writer = dosyswrite; + http->reader = dosysread; + return http; + } + + http->writer = dotlswrite; + http->reader = dotlsread; + + if ((http->ctx = tls_client()) == NULL) { + warn("tls_client"); + goto err; + } else if (tls_configure(http->ctx, tlscfg) == -1) { + warnx("%s: tls_configure: %s", + http->src.ip, tls_error(http->ctx)); + goto err; + } + + if (tls_connect_socket(http->ctx, http->fd, http->host) != 0) { + warnx("%s: tls_connect_socket: %s, %s", http->src.ip, + http->host, tls_error(http->ctx)); + goto err; + } + + return http; +err: + http_free(http); + return NULL; +} + +struct httpxfer * +http_open(const struct http *http, const void *p, size_t psz) +{ + char *req; + int c; + struct httpxfer *trans; + + if (p == NULL) { + c = asprintf(&req, + "GET %s HTTP/1.0\r\n" + "Host: %s\r\n" + "\r\n", + http->path, http->host); + } else { + c = asprintf(&req, + "POST %s HTTP/1.0\r\n" + "Host: %s\r\n" + "Content-Type: application/ocsp-request\r\n" + "Content-Length: %zu\r\n" + "\r\n", + http->path, http->host, psz); + } + if (c == -1) { + warn("asprintf"); + return NULL; + } else if (!http_write(req, c, http)) { + free(req); + return NULL; + } else if (p != NULL && !http_write(p, psz, http)) { + free(req); + return NULL; + } + + free(req); + + trans = calloc(1, sizeof(struct httpxfer)); + if (trans == NULL) + warn("calloc"); + return trans; +} + +void +http_close(struct httpxfer *x) +{ + + if (x == NULL) + return; + free(x->hbuf); + free(x->bbuf); + free(x->headbuf); + free(x->head); + free(x); +} + +/* + * Read the HTTP body from the wire. + * If invoked multiple times, this will return the same pointer with the + * same data (or NULL, if the original invocation returned NULL). + * Returns NULL if read or allocation errors occur. + * You must not free the returned pointer. + */ +char * +http_body_read(const struct http *http, struct httpxfer *trans, size_t *sz) +{ + char buf[BUFSIZ]; + ssize_t ssz; + void *pp; + size_t szp; + + if (sz == NULL) + sz = &szp; + + /* Have we already parsed this? */ + + if (trans->bodyok > 0) { + *sz = trans->bbufsz; + return trans->bbuf; + } else if (trans->bodyok < 0) + return NULL; + + *sz = 0; + trans->bodyok = -1; + + do { + /* If less than sizeof(buf), at EOF. */ + if ((ssz = http_read(buf, sizeof(buf), http)) < 0) + return NULL; + else if (ssz == 0) + break; + + pp = recallocarray(trans->bbuf, + trans->bbufsz, trans->bbufsz + ssz, 1); + if (pp == NULL) { + warn("recallocarray"); + return NULL; + } + trans->bbuf = pp; + memcpy(trans->bbuf + trans->bbufsz, buf, ssz); + trans->bbufsz += ssz; + } while (ssz == sizeof(buf)); + + trans->bodyok = 1; + *sz = trans->bbufsz; + return trans->bbuf; +} + +struct httphead * +http_head_get(const char *v, struct httphead *h, size_t hsz) +{ + size_t i; + + for (i = 0; i < hsz; i++) { + if (strcmp(h[i].key, v)) + continue; + return &h[i]; + } + return NULL; +} + +/* + * Look through the headers and determine our HTTP code. + * This will return -1 on failure, otherwise the code. + */ +int +http_head_status(const struct http *http, struct httphead *h, size_t sz) +{ + int rc; + unsigned int code; + struct httphead *st; + + if ((st = http_head_get("Status", h, sz)) == NULL) { + warnx("%s: no status header", http->src.ip); + return -1; + } + + rc = sscanf(st->val, "%*s %u %*s", &code); + if (rc < 0) { + warn("sscanf"); + return -1; + } else if (rc != 1) { + warnx("%s: cannot convert status header", http->src.ip); + return -1; + } + return code; +} + +/* + * Parse headers from the transfer. + * Malformed headers are skipped. + * A special "Status" header is added for the HTTP status line. + * This can only happen once http_head_read has been called with + * success. + * This can be invoked multiple times: it will only parse the headers + * once and after that it will just return the cache. + * You must not free the returned pointer. + * If the original header parse failed, or if memory allocation fails + * internally, this returns NULL. + */ +struct httphead * +http_head_parse(const struct http *http, struct httpxfer *trans, size_t *sz) +{ + size_t hsz, szp; + struct httphead *h; + char *cp, *ep, *ccp, *buf; + + if (sz == NULL) + sz = &szp; + + /* + * If we've already parsed the headers, return the + * previously-parsed buffer now. + * If we have errors on the stream, return NULL now. + */ + + if (trans->head != NULL) { + *sz = trans->headsz; + return trans->head; + } else if (trans->headok <= 0) + return NULL; + + if ((buf = strdup(trans->hbuf)) == NULL) { + warn("strdup"); + return NULL; + } + hsz = 0; + cp = buf; + + do { + if ((cp = strstr(cp, "\r\n")) != NULL) + cp += 2; + hsz++; + } while (cp != NULL); + + /* + * Allocate headers, then step through the data buffer, parsing + * out headers as we have them. + * We know at this point that the buffer is NUL-terminated in + * the usual way. + */ + + h = calloc(hsz, sizeof(struct httphead)); + if (h == NULL) { + warn("calloc"); + free(buf); + return NULL; + } + + *sz = hsz; + hsz = 0; + cp = buf; + + do { + if ((ep = strstr(cp, "\r\n")) != NULL) { + *ep = '\0'; + ep += 2; + } + if (hsz == 0) { + h[hsz].key = "Status"; + h[hsz++].val = cp; + continue; + } + + /* Skip bad headers. */ + if ((ccp = strchr(cp, ':')) == NULL) { + warnx("%s: header without separator", http->src.ip); + continue; + } + + *ccp++ = '\0'; + while (isspace((unsigned char)*ccp)) + ccp++; + h[hsz].key = cp; + h[hsz++].val = ccp; + } while ((cp = ep) != NULL); + + trans->headbuf = buf; + trans->head = h; + trans->headsz = hsz; + return h; +} + +/* + * Read the HTTP headers from the wire. + * If invoked multiple times, this will return the same pointer with the + * same data (or NULL, if the original invocation returned NULL). + * Returns NULL if read or allocation errors occur. + * You must not free the returned pointer. + */ +char * +http_head_read(const struct http *http, struct httpxfer *trans, size_t *sz) +{ + char buf[BUFSIZ]; + ssize_t ssz; + char *ep; + void *pp; + size_t szp; + + if (sz == NULL) + sz = &szp; + + /* Have we already parsed this? */ + + if (trans->headok > 0) { + *sz = trans->hbufsz; + return trans->hbuf; + } else if (trans->headok < 0) + return NULL; + + *sz = 0; + ep = NULL; + trans->headok = -1; + + /* + * Begin by reading by BUFSIZ blocks until we reach the header + * termination marker (two CRLFs). + * We might read into our body, but that's ok: we'll copy out + * the body parts into our body buffer afterward. + */ + + do { + /* If less than sizeof(buf), at EOF. */ + if ((ssz = http_read(buf, sizeof(buf), http)) < 0) + return NULL; + else if (ssz == 0) + break; + pp = realloc(trans->hbuf, trans->hbufsz + ssz); + if (pp == NULL) { + warn("realloc"); + return NULL; + } + trans->hbuf = pp; + memcpy(trans->hbuf + trans->hbufsz, buf, ssz); + trans->hbufsz += ssz; + /* Search for end of headers marker. */ + ep = memmem(trans->hbuf, trans->hbufsz, "\r\n\r\n", 4); + } while (ep == NULL && ssz == sizeof(buf)); + + if (ep == NULL) { + warnx("%s: partial transfer", http->src.ip); + return NULL; + } + *ep = '\0'; + + /* + * The header data is invalid if it has any binary characters in + * it: check that now. + * This is important because we want to guarantee that all + * header keys and pairs are properly NUL-terminated. + */ + + if (strlen(trans->hbuf) != (uintptr_t)(ep - trans->hbuf)) { + warnx("%s: binary data in header", http->src.ip); + return NULL; + } + + /* + * Copy remaining buffer into body buffer. + */ + + ep += 4; + trans->bbufsz = (trans->hbuf + trans->hbufsz) - ep; + trans->bbuf = malloc(trans->bbufsz); + if (trans->bbuf == NULL) { + warn("malloc"); + return NULL; + } + memcpy(trans->bbuf, ep, trans->bbufsz); + + trans->headok = 1; + *sz = trans->hbufsz; + return trans->hbuf; +} + +void +http_get_free(struct httpget *g) +{ + + if (g == NULL) + return; + http_close(g->xfer); + http_free(g->http); + free(g); +} + +struct httpget * +http_get(const struct source *addrs, size_t addrsz, const char *domain, + short port, const char *path, const void *post, size_t postsz) +{ + struct http *h; + struct httpxfer *x; + struct httpget *g; + struct httphead *head; + size_t headsz, bodsz, headrsz; + int code; + char *bod, *headr; + + h = http_alloc(addrs, addrsz, domain, port, path); + if (h == NULL) + return NULL; + + if ((x = http_open(h, post, postsz)) == NULL) { + http_free(h); + return NULL; + } else if ((headr = http_head_read(h, x, &headrsz)) == NULL) { + http_close(x); + http_free(h); + return NULL; + } else if ((bod = http_body_read(h, x, &bodsz)) == NULL) { + http_close(x); + http_free(h); + return NULL; + } + + http_disconnect(h); + + if ((head = http_head_parse(h, x, &headsz)) == NULL) { + http_close(x); + http_free(h); + return NULL; + } else if ((code = http_head_status(h, head, headsz)) < 0) { + http_close(x); + http_free(h); + return NULL; + } + + if ((g = calloc(1, sizeof(struct httpget))) == NULL) { + warn("calloc"); + http_close(x); + http_free(h); + return NULL; + } + + g->headpart = headr; + g->headpartsz = headrsz; + g->bodypart = bod; + g->bodypartsz = bodsz; + g->head = head; + g->headsz = headsz; + g->code = code; + g->xfer = x; + g->http = h; + return g; +} + +#if 0 +int +main(void) +{ + struct httpget *g; + struct httphead *httph; + size_t i, httphsz; + struct source addrs[2]; + size_t addrsz; + +#if 0 + addrs[0].ip = "127.0.0.1"; + addrs[0].family = 4; + addrsz = 1; +#else + addrs[0].ip = "2a00:1450:400a:806::2004"; + addrs[0].family = 6; + addrs[1].ip = "193.135.3.123"; + addrs[1].family = 4; + addrsz = 2; +#endif + + if (http_init() == -1) + errx(EXIT_FAILURE, "http_init"); + +#if 0 + g = http_get(addrs, addrsz, "localhost", 80, "/index.html"); +#else + g = http_get(addrs, addrsz, "www.google.ch", 80, "/index.html", + NULL, 0); +#endif + + if (g == NULL) + errx(EXIT_FAILURE, "http_get"); + + httph = http_head_parse(g->http, g->xfer, &httphsz); + warnx("code: %d", g->code); + + for (i = 0; i < httphsz; i++) + warnx("head: [%s]=[%s]", httph[i].key, httph[i].val); + + http_get_free(g); + return (EXIT_SUCCESS); +} +#endif diff --git a/apps/ocspcheck/http.h b/apps/ocspcheck/http.h new file mode 100644 index 0000000..17541b4 --- /dev/null +++ b/apps/ocspcheck/http.h @@ -0,0 +1,92 @@ +/* $Id: http.h,v 1.3 2017/01/25 13:52:53 inoguchi Exp $ */ +/* + * Copyright (c) 2016 Kristaps Dzonsons + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef HTTP_H +#define HTTP_H + +struct source { + int family; /* 4 (PF_INET) or 6 (PF_INET6) */ + char *ip; /* IPV4 or IPV6 address */ +}; + +struct http; + +/* + * Write and read callbacks to allow HTTP and HTTPS. + * Both of these return the number of bytes read (or written) or -1 on + * failure. + * 0 bytes read means that the connection has closed. + */ +typedef ssize_t (*writefp)(const void *, size_t, const struct http *); +typedef ssize_t (*readfp)(char *, size_t, const struct http *); + +/* + * HTTP/S header pair. + * There's also a cooked-up pair, "Status", with the status code. + * Both strings are NUL-terminated. + */ +struct httphead { + const char *key; + const char *val; +}; + +/* + * Grab all information from a transfer. + * DO NOT free any parts of this, and editing the parts (e.g., changing + * the underlying strings) will persist; so in short, don't. + * All of these values will be set upon http_get() success. + */ +struct httpget { + struct httpxfer *xfer; /* underlying transfer */ + struct http *http; /* underlying connection */ + int code; /* return code */ + struct httphead *head; /* headers */ + size_t headsz; /* number of headers */ + char *headpart; /* header buffer */ + size_t headpartsz; /* size of headpart */ + char *bodypart; /* body buffer */ + size_t bodypartsz; /* size of bodypart */ +}; + +int http_init(void); + +/* Convenience functions. */ +struct httpget *http_get(const struct source *, size_t, + const char *, short, const char *, + const void *, size_t); +void http_get_free(struct httpget *); + +/* Allocation and release. */ +struct http *http_alloc(const struct source *, size_t, + const char *, short, const char *); +void http_free(struct http *); +struct httpxfer *http_open(const struct http *, const void *, size_t); +void http_close(struct httpxfer *); +void http_disconnect(struct http *); + +/* Access. */ +char *http_head_read(const struct http *, + struct httpxfer *, size_t *); +struct httphead *http_head_parse(const struct http *, + struct httpxfer *, size_t *); +char *http_body_read(const struct http *, + struct httpxfer *, size_t *); +int http_head_status(const struct http *, + struct httphead *, size_t); +struct httphead *http_head_get(const char *, + struct httphead *, size_t); + +#endif /* HTTP_H */ diff --git a/apps/ocspcheck/ocspcheck.c b/apps/ocspcheck/ocspcheck.c new file mode 100644 index 0000000..516642b --- /dev/null +++ b/apps/ocspcheck/ocspcheck.c @@ -0,0 +1,761 @@ +/* $OpenBSD: ocspcheck.c,v 1.31 2022/12/28 21:30:17 jmc Exp $ */ + +/* + * Copyright (c) 2017,2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "http.h" + +#define MAXAGE_SEC (14*24*60*60) +#define JITTER_SEC (60) +#define OCSP_MAX_RESPONSE_SIZE (20480) + +typedef struct ocsp_request { + STACK_OF(X509) *fullchain; + OCSP_REQUEST *req; + char *url; + unsigned char *data; + size_t size; + int nonce; +} ocsp_request; + +int verbose; +#define vspew(fmt, ...) \ + do { if (verbose >= 1) fprintf(stderr, fmt, __VA_ARGS__); } while (0) +#define dspew(fmt, ...) \ + do { if (verbose >= 2) fprintf(stderr, fmt, __VA_ARGS__); } while (0) + +#define MAX_SERVERS_DNS 8 + +struct addr { + int family; /* 4 for PF_INET, 6 for PF_INET6 */ + char ip[INET6_ADDRSTRLEN]; +}; + +static ssize_t +host_dns(const char *s, struct addr vec[MAX_SERVERS_DNS]) +{ + struct addrinfo hints, *res0, *res; + int error; + ssize_t vecsz; + struct sockaddr *sa; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /* DUMMY */ + + error = getaddrinfo(s, NULL, &hints, &res0); + + if (error == EAI_AGAIN || +#ifdef EAI_NODATA + error == EAI_NODATA || +#endif + error == EAI_NONAME) + return 0; + + if (error) { + warnx("%s: parse error: %s", s, gai_strerror(error)); + return -1; + } + + for (vecsz = 0, res = res0; + res != NULL && vecsz < MAX_SERVERS_DNS; + res = res->ai_next) { + if (res->ai_family != AF_INET && + res->ai_family != AF_INET6) + continue; + + sa = res->ai_addr; + + if (res->ai_family == AF_INET) { + vec[vecsz].family = 4; + inet_ntop(AF_INET, + &(((struct sockaddr_in *)sa)->sin_addr), + vec[vecsz].ip, INET6_ADDRSTRLEN); + } else { + vec[vecsz].family = 6; + inet_ntop(AF_INET6, + &(((struct sockaddr_in6 *)sa)->sin6_addr), + vec[vecsz].ip, INET6_ADDRSTRLEN); + } + + dspew("DNS returns %s for %s\n", vec[vecsz].ip, s); + vecsz++; + } + + freeaddrinfo(res0); + return vecsz; +} + +/* + * Extract the domain and port from a URL. + * The url must be formatted as schema://address[/stuff]. + * This returns NULL on failure. + */ +static char * +url2host(const char *host, short *port, char **path) +{ + char *url, *ep; + + /* We only understand HTTP and HTTPS. */ + + if (strncmp(host, "https://", 8) == 0) { + *port = 443; + if ((url = strdup(host + 8)) == NULL) { + warn("strdup"); + return (NULL); + } + } else if (strncmp(host, "http://", 7) == 0) { + *port = 80; + if ((url = strdup(host + 7)) == NULL) { + warn("strdup"); + return (NULL); + } + } else { + warnx("%s: unknown schema", host); + return (NULL); + } + + /* Terminate path part. */ + + if ((ep = strchr(url, '/')) != NULL) { + *path = strdup(ep); + *ep = '\0'; + } else + *path = strdup("/"); + + if (*path == NULL) { + warn("strdup"); + free(url); + return (NULL); + } + + /* Check to see if there is a port in the url */ + if ((ep = strchr(url, ':')) != NULL) { + const char *errstr; + short pp; + pp = strtonum(ep + 1, 1, SHRT_MAX, &errstr); + if (errstr != NULL) { + warnx("error parsing port from '%s': %s", url, errstr); + free(url); + free(*path); + return NULL; + } + *port = pp; + *ep = '\0'; + } + + return (url); +} + +static time_t +parse_ocsp_time(ASN1_GENERALIZEDTIME *gt) +{ + struct tm tm; + time_t rv = -1; + + if (gt == NULL) + return -1; + /* RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME */ + if (ASN1_time_parse(gt->data, gt->length, &tm, + V_ASN1_GENERALIZEDTIME) == -1) + return -1; + if ((rv = timegm(&tm)) == -1) + return -1; + return rv; +} + +static X509_STORE * +read_cacerts(const char *file, const char *dir) +{ + X509_STORE *store = NULL; + X509_LOOKUP *lookup; + + if (file == NULL && dir == NULL) { + warnx("No CA certs to load"); + goto end; + } + if ((store = X509_STORE_new()) == NULL) { + warnx("Malloc failed"); + goto end; + } + if (file != NULL) { + if ((lookup = X509_STORE_add_lookup(store, + X509_LOOKUP_file())) == NULL) { + warnx("Unable to load CA cert file"); + goto end; + } + if (!X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM)) { + warnx("Unable to load CA certs from file %s", file); + goto end; + } + } + if (dir != NULL) { + if ((lookup = X509_STORE_add_lookup(store, + X509_LOOKUP_hash_dir())) == NULL) { + warnx("Unable to load CA cert directory"); + goto end; + } + if (!X509_LOOKUP_add_dir(lookup, dir, X509_FILETYPE_PEM)) { + warnx("Unable to load CA certs from directory %s", dir); + goto end; + } + } + return store; + + end: + X509_STORE_free(store); + return NULL; +} + +static STACK_OF(X509) * +read_fullchain(const char *file, int *count) +{ + int i; + BIO *bio; + STACK_OF(X509_INFO) *xis = NULL; + X509_INFO *xi; + STACK_OF(X509) *rv = NULL; + + *count = 0; + + if ((bio = BIO_new_file(file, "r")) == NULL) { + warn("Unable to read a certificate from %s", file); + goto end; + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL)) == NULL) { + warnx("Unable to read PEM format from %s", file); + goto end; + } + if (sk_X509_INFO_num(xis) <= 0) { + warnx("No certificates in file %s", file); + goto end; + } + if ((rv = sk_X509_new_null()) == NULL) { + warnx("malloc failed"); + goto end; + } + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + xi = sk_X509_INFO_value(xis, i); + if (xi->x509 == NULL) + continue; + if (!sk_X509_push(rv, xi->x509)) { + warnx("unable to build x509 chain"); + sk_X509_pop_free(rv, X509_free); + rv = NULL; + goto end; + } + xi->x509 = NULL; + (*count)++; + } + end: + BIO_free(bio); + sk_X509_INFO_pop_free(xis, X509_INFO_free); + return rv; +} + +static inline X509 * +cert_from_chain(STACK_OF(X509) *fullchain) +{ + return sk_X509_value(fullchain, 0); +} + +static const X509 * +issuer_from_chain(STACK_OF(X509) *fullchain) +{ + const X509 *cert; + X509_NAME *issuer_name; + + cert = cert_from_chain(fullchain); + if ((issuer_name = X509_get_issuer_name(cert)) == NULL) + return NULL; + + return X509_find_by_subject(fullchain, issuer_name); +} + +static ocsp_request * +ocsp_request_new_from_cert(const char *cadir, char *file, int nonce) +{ + X509 *cert; + int count = 0; + OCSP_CERTID *id = NULL; + ocsp_request *request = NULL; + const EVP_MD *cert_id_md = NULL; + const X509 *issuer; + STACK_OF(OPENSSL_STRING) *urls = NULL; + + if ((request = calloc(1, sizeof(ocsp_request))) == NULL) { + warn("malloc"); + goto err; + } + + if ((request->req = OCSP_REQUEST_new()) == NULL) + goto err; + + request->fullchain = read_fullchain(file, &count); + if (cadir == NULL) { + /* Drop rpath from pledge, we don't need to read anymore */ + if (pledge("stdio inet dns", NULL) == -1) + err(1, "pledge"); + } + if (request->fullchain == NULL) { + warnx("Unable to read cert chain from file %s", file); + goto err; + } + if (count <= 1) { + warnx("File %s does not contain a cert chain", file); + goto err; + } + if ((cert = cert_from_chain(request->fullchain)) == NULL) { + warnx("No certificate found in %s", file); + goto err; + } + if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { + warnx("Unable to find issuer for cert in %s", file); + goto err; + } + + urls = X509_get1_ocsp(cert); + if (urls == NULL || sk_OPENSSL_STRING_num(urls) <= 0) { + warnx("Certificate in %s contains no OCSP url", file); + goto err; + } + if ((request->url = strdup(sk_OPENSSL_STRING_value(urls, 0))) == NULL) + goto err; + X509_email_free(urls); + urls = NULL; + + cert_id_md = EVP_sha1(); /* XXX. This sucks but OCSP is poopy */ + if ((id = OCSP_cert_to_id(cert_id_md, cert, issuer)) == NULL) { + warnx("Unable to get certificate id from cert in %s", file); + goto err; + } + if (OCSP_request_add0_id(request->req, id) == NULL) { + warnx("Unable to add certificate id to request"); + goto err; + } + id = NULL; + + request->nonce = nonce; + if (request->nonce) + OCSP_request_add1_nonce(request->req, NULL, -1); + + if ((request->size = i2d_OCSP_REQUEST(request->req, + &request->data)) <= 0) { + warnx("Unable to encode ocsp request"); + goto err; + } + if (request->data == NULL) { + warnx("Unable to allocate memory"); + goto err; + } + return request; + + err: + if (request != NULL) { + sk_X509_pop_free(request->fullchain, X509_free); + free(request->url); + OCSP_REQUEST_free(request->req); + free(request->data); + } + X509_email_free(urls); + OCSP_CERTID_free(id); + free(request); + return NULL; +} + + +int +validate_response(char *buf, size_t size, ocsp_request *request, + X509_STORE *store, char *host, char *file) +{ + ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL; + const unsigned char **p = (const unsigned char **)&buf; + int status, cert_status = 0, crl_reason = 0; + time_t now, rev_t = -1, this_t, next_t; + OCSP_RESPONSE *resp = NULL; + OCSP_BASICRESP *bresp = NULL; + OCSP_CERTID *cid = NULL; + const X509 *cert, *issuer; + int ret = 0; + + if ((cert = cert_from_chain(request->fullchain)) == NULL) { + warnx("No certificate found in %s", file); + goto err; + } + if ((issuer = issuer_from_chain(request->fullchain)) == NULL) { + warnx("Unable to find certificate issuer for cert in %s", file); + goto err; + } + if ((cid = OCSP_cert_to_id(NULL, cert, issuer)) == NULL) { + warnx("Unable to get issuer cert/CID in %s", file); + goto err; + } + + if ((resp = d2i_OCSP_RESPONSE(NULL, p, size)) == NULL) { + warnx("OCSP response unserializable from host %s", host); + goto err; + } + + if ((bresp = OCSP_response_get1_basic(resp)) == NULL) { + warnx("Failed to load OCSP response from %s", host); + goto err; + } + + if (OCSP_basic_verify(bresp, request->fullchain, store, + OCSP_TRUSTOTHER) != 1) { + warnx("OCSP verify failed from %s", host); + goto err; + } + dspew("OCSP response signature validated from %s\n", host); + + status = OCSP_response_status(resp); + if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + warnx("OCSP Failure: code %d (%s) from host %s", + status, OCSP_response_status_str(status), host); + goto err; + } + dspew("OCSP response status %d from host %s\n", status, host); + + /* Check the nonce if we sent one */ + + if (request->nonce) { + if (OCSP_check_nonce(request->req, bresp) <= 0) { + warnx("No OCSP nonce, or mismatch, from host %s", host); + goto err; + } + } + + if (OCSP_resp_find_status(bresp, cid, &cert_status, &crl_reason, + &revtime, &thisupd, &nextupd) != 1) { + warnx("OCSP verify failed: no result for cert"); + goto err; + } + + if (revtime && (rev_t = parse_ocsp_time(revtime)) == -1) { + warnx("Unable to parse revocation time in OCSP reply"); + goto err; + } + /* + * Belt and suspenders, Treat it as revoked if there is either + * a revocation time, or status revoked. + */ + if (rev_t != -1 || cert_status == V_OCSP_CERTSTATUS_REVOKED) { + warnx("Invalid OCSP reply: certificate is revoked"); + if (rev_t != -1) + warnx("Certificate revoked at: %s", ctime(&rev_t)); + goto err; + } + if ((this_t = parse_ocsp_time(thisupd)) == -1) { + warnx("unable to parse this update time in OCSP reply"); + goto err; + } + if ((next_t = parse_ocsp_time(nextupd)) == -1) { + warnx("unable to parse next update time in OCSP reply"); + goto err; + } + + /* Don't allow this update to precede next update */ + if (this_t >= next_t) { + warnx("Invalid OCSP reply: this update >= next update"); + goto err; + } + + now = time(NULL); + /* + * Check that this update is not more than JITTER seconds + * in the future. + */ + if (this_t > now + JITTER_SEC) { + warnx("Invalid OCSP reply: this update is in the future at %s", + ctime(&this_t)); + goto err; + } + + /* + * Check that this update is not more than MAXSEC + * in the past. + */ + if (this_t < now - MAXAGE_SEC) { + warnx("Invalid OCSP reply: this update is too old %s", + ctime(&this_t)); + goto err; + } + + /* + * Check that next update is still valid + */ + if (next_t < now - JITTER_SEC) { + warnx("Invalid OCSP reply: reply has expired at %s", + ctime(&next_t)); + goto err; + } + + vspew("OCSP response validated from %s\n", host); + vspew(" This Update: %s", ctime(&this_t)); + vspew(" Next Update: %s", ctime(&next_t)); + ret = 1; + err: + OCSP_RESPONSE_free(resp); + OCSP_BASICRESP_free(bresp); + OCSP_CERTID_free(cid); + return ret; +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: ocspcheck [-Nv] [-C CAfile] [-i staplefile] " + "[-o staplefile] file\n"); + exit(1); +} + +int +main(int argc, char **argv) +{ + const char *cafile = NULL, *cadir = NULL; + char *host = NULL, *path = NULL, *certfile = NULL, *outfile = NULL, + *instaple = NULL, *infile = NULL; + struct addr addrs[MAX_SERVERS_DNS] = {{0}}; + struct source sources[MAX_SERVERS_DNS]; + int i, ch, staplefd = -1, infd = -1, nonce = 1; + ocsp_request *request = NULL; + size_t rescount, httphsz = 0, instaplesz = 0; + struct httphead *httph = NULL; + struct httpget *hget; + X509_STORE *castore; + ssize_t written, w; + short port; + + while ((ch = getopt(argc, argv, "C:i:No:v")) != -1) { + switch (ch) { + case 'C': + cafile = optarg; + break; + case 'N': + nonce = 0; + break; + case 'o': + outfile = optarg; + break; + case 'i': + infile = optarg; + break; + case 'v': + verbose++; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc != 1 || (certfile = argv[0]) == NULL) + usage(); + + if (outfile != NULL) { + if (strcmp(outfile, "-") == 0) + staplefd = STDOUT_FILENO; + else + staplefd = open(outfile, O_WRONLY|O_CREAT, + S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); + if (staplefd < 0) + err(1, "Unable to open output file %s", outfile); + } + + if (infile != NULL) { + if (strcmp(infile, "-") == 0) + infd = STDIN_FILENO; + else + infd = open(infile, O_RDONLY); + if (infd < 0) + err(1, "Unable to open input file %s", infile); + nonce = 0; /* Can't validate a nonce on a saved reply */ + } + + if (cafile == NULL) { + if (access(X509_get_default_cert_file(), R_OK) == 0) + cafile = X509_get_default_cert_file(); + if (access(X509_get_default_cert_dir(), F_OK) == 0) + cadir = X509_get_default_cert_dir(); + } + + if (cafile != NULL) { + if (unveil(cafile, "r") == -1) + err(1, "unveil %s", cafile); + } + if (cadir != NULL) { + if (unveil(cadir, "r") == -1) + err(1, "unveil %s", cadir); + } + if (unveil(certfile, "r") == -1) + err(1, "unveil %s", certfile); + + if (pledge("stdio inet rpath dns", NULL) == -1) + err(1, "pledge"); + + /* + * Load our certificate and keystore, and build up an + * OCSP request based on the full certificate chain + * we have been given to check. + */ + if ((castore = read_cacerts(cafile, cadir)) == NULL) + exit(1); + if ((request = ocsp_request_new_from_cert(cadir, certfile, nonce)) + == NULL) + exit(1); + + dspew("Built an %zu byte ocsp request\n", request->size); + + if ((host = url2host(request->url, &port, &path)) == NULL) + errx(1, "Invalid OCSP url %s from %s", request->url, + certfile); + + if (infd == -1) { + /* Get a new OCSP response from the indicated server */ + + vspew("Using %s to host %s, port %d, path %s\n", + port == 443 ? "https" : "http", host, port, path); + + rescount = host_dns(host, addrs); + for (i = 0; i < rescount; i++) { + sources[i].ip = addrs[i].ip; + sources[i].family = addrs[i].family; + } + + /* + * Do an HTTP post to send our request to the OCSP + * server, and hopefully get an answer back + */ + hget = http_get(sources, rescount, host, port, path, + request->data, request->size); + if (hget == NULL) + errx(1, "http_get"); + /* + * Pledge minimally before fiddling with libcrypto init + * routines and parsing untrusted input from someone's OCSP + * server. + */ + if (cadir == NULL) { + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); + } + + dspew("Server at %s returns:\n", host); + for (i = 0; i < httphsz; i++) + dspew(" [%s]=[%s]\n", httph[i].key, httph[i].val); + dspew(" [Body]=[%zu bytes]\n", hget->bodypartsz); + if (hget->bodypartsz <= 0) + errx(1, "No body in reply from %s", host); + + if (hget->code != 200) + errx(1, "http reply code %d from %s", hget->code, host); + + /* + * Validate the OCSP response we got back + */ + OPENSSL_add_all_algorithms_noconf(); + if (!validate_response(hget->bodypart, hget->bodypartsz, + request, castore, host, certfile)) + exit(1); + instaple = hget->bodypart; + instaplesz = hget->bodypartsz; + } else { + size_t nr = 0; + instaplesz = 0; + + /* + * Pledge minimally before fiddling with libcrypto init + */ + if (cadir == NULL) { + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); + } + + dspew("Using ocsp response saved in %s:\n", infile); + + /* Use the existing OCSP response saved in infd */ + instaple = calloc(OCSP_MAX_RESPONSE_SIZE, 1); + if (instaple) { + while ((nr = read(infd, instaple + instaplesz, + OCSP_MAX_RESPONSE_SIZE - instaplesz)) != -1 && + nr != 0) + instaplesz += nr; + } + if (instaplesz == 0) + exit(1); + /* + * Validate the OCSP staple we read in. + */ + OPENSSL_add_all_algorithms_noconf(); + if (!validate_response(instaple, instaplesz, + request, castore, host, certfile)) + exit(1); + } + + /* + * If we have been given a place to save a staple, + * write out the DER format response to the staplefd + */ + if (staplefd >= 0) { + while (ftruncate(staplefd, 0) < 0) { + if (errno == EINVAL) + break; + if (errno != EINTR && errno != EAGAIN) + err(1, "Write of OCSP response failed"); + } + written = 0; + while (written < instaplesz) { + w = write(staplefd, instaple + written, + instaplesz - written); + if (w == -1) { + if (errno != EINTR && errno != EAGAIN) + err(1, "Write of OCSP response failed"); + } else + written += w; + } + close(staplefd); + } + exit(0); +} diff --git a/apps/openssl/apps.c b/apps/openssl/apps.c new file mode 100644 index 0000000..70857e0 --- /dev/null +++ b/apps/openssl/apps.c @@ -0,0 +1,2186 @@ +/* $OpenBSD: apps.c,v 1.66 2023/07/23 11:39:29 tb Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + const char *name; + unsigned long flag; + unsigned long mask; +} NAME_EX_TBL; + +UI_METHOD *ui_method = NULL; + +static int set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL *in_tbl); +static int set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL *in_tbl); + +int +str2fmt(char *s) +{ + if (s == NULL) + return FORMAT_UNDEF; + if ((*s == 'D') || (*s == 'd')) + return (FORMAT_ASN1); + else if ((*s == 'T') || (*s == 't')) + return (FORMAT_TEXT); + else if ((*s == 'S') || (*s == 's')) + return (FORMAT_SMIME); + else if ((*s == 'M') || (*s == 'm')) + return (FORMAT_MSBLOB); + else if ((*s == '1') || + (strcmp(s, "PKCS12") == 0) || (strcmp(s, "pkcs12") == 0) || + (strcmp(s, "P12") == 0) || (strcmp(s, "p12") == 0)) + return (FORMAT_PKCS12); + else if ((*s == 'P') || (*s == 'p')) { + if (s[1] == 'V' || s[1] == 'v') + return FORMAT_PVK; + else + return (FORMAT_PEM); + } else + return (FORMAT_UNDEF); +} + +void +program_name(char *in, char *out, int size) +{ + char *p; + + p = strrchr(in, '/'); + if (p != NULL) + p++; + else + p = in; + strlcpy(out, p, size); +} + +int +dump_cert_text(BIO *out, X509 *x) +{ + char *p; + + p = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0); + BIO_puts(out, "subject="); + BIO_puts(out, p); + free(p); + + p = X509_NAME_oneline(X509_get_issuer_name(x), NULL, 0); + BIO_puts(out, "\nissuer="); + BIO_puts(out, p); + BIO_puts(out, "\n"); + free(p); + + return 0; +} + +int +ui_open(UI *ui) +{ + return UI_method_get_opener(UI_OpenSSL()) (ui); +} + +int +ui_read(UI *ui, UI_STRING *uis) +{ + const char *password; + int string_type; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && + UI_get0_user_data(ui)) { + string_type = UI_get_string_type(uis); + if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) { + password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') { + UI_set_result(ui, uis, password); + return 1; + } + } + } + return UI_method_get_reader(UI_OpenSSL()) (ui, uis); +} + +int +ui_write(UI *ui, UI_STRING *uis) +{ + const char *password; + int string_type; + + if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && + UI_get0_user_data(ui)) { + string_type = UI_get_string_type(uis); + if (string_type == UIT_PROMPT || string_type == UIT_VERIFY) { + password = + ((PW_CB_DATA *)UI_get0_user_data(ui))->password; + if (password && password[0] != '\0') + return 1; + } + } + return UI_method_get_writer(UI_OpenSSL()) (ui, uis); +} + +int +ui_close(UI *ui) +{ + return UI_method_get_closer(UI_OpenSSL()) (ui); +} + +int +password_callback(char *buf, int bufsiz, int verify, void *arg) +{ + PW_CB_DATA *cb_tmp = arg; + UI *ui = NULL; + int res = 0; + const char *prompt_info = NULL; + const char *password = NULL; + PW_CB_DATA *cb_data = (PW_CB_DATA *) cb_tmp; + + if (cb_data) { + if (cb_data->password) + password = cb_data->password; + if (cb_data->prompt_info) + prompt_info = cb_data->prompt_info; + } + if (password) { + res = strlen(password); + if (res > bufsiz) + res = bufsiz; + memcpy(buf, password, res); + return res; + } + ui = UI_new_method(ui_method); + if (ui) { + int ok = 0; + char *buff = NULL; + int ui_flags = 0; + char *prompt = NULL; + + prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); + + ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD; + UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); + + if (ok >= 0) + ok = UI_add_input_string(ui, prompt, ui_flags, buf, + PW_MIN_LENGTH, bufsiz - 1); + if (ok >= 0 && verify) { + buff = malloc(bufsiz); + ok = UI_add_verify_string(ui, prompt, ui_flags, buff, + PW_MIN_LENGTH, bufsiz - 1, buf); + } + if (ok >= 0) + do { + ok = UI_process(ui); + } while (ok < 0 && + UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); + + freezero(buff, (unsigned int) bufsiz); + if (ok >= 0) + res = strlen(buf); + if (ok == -1) { + BIO_printf(bio_err, "User interface error\n"); + ERR_print_errors(bio_err); + explicit_bzero(buf, (unsigned int) bufsiz); + res = 0; + } + if (ok == -2) { + BIO_printf(bio_err, "aborted!\n"); + explicit_bzero(buf, (unsigned int) bufsiz); + res = 0; + } + UI_free(ui); + free(prompt); + } + return res; +} + +static char *app_get_pass(BIO *err, char *arg, int keepbio); + +int +app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) +{ + int same; + + if (!arg2 || !arg1 || strcmp(arg1, arg2)) + same = 0; + else + same = 1; + if (arg1) { + *pass1 = app_get_pass(err, arg1, same); + if (!*pass1) + return 0; + } else if (pass1) + *pass1 = NULL; + if (arg2) { + *pass2 = app_get_pass(err, arg2, same ? 2 : 0); + if (!*pass2) + return 0; + } else if (pass2) + *pass2 = NULL; + return 1; +} + +static char * +app_get_pass(BIO *err, char *arg, int keepbio) +{ + char *tmp, tpass[APP_PASS_LEN]; + static BIO *pwdbio = NULL; + const char *errstr = NULL; + int i; + + if (!strncmp(arg, "pass:", 5)) + return strdup(arg + 5); + if (!strncmp(arg, "env:", 4)) { + tmp = getenv(arg + 4); + if (!tmp) { + BIO_printf(err, "Can't read environment variable %s\n", + arg + 4); + return NULL; + } + return strdup(tmp); + } + if (!keepbio || !pwdbio) { + if (!strncmp(arg, "file:", 5)) { + pwdbio = BIO_new_file(arg + 5, "r"); + if (!pwdbio) { + BIO_printf(err, "Can't open file %s\n", + arg + 5); + return NULL; + } + } else if (!strncmp(arg, "fd:", 3)) { + BIO *btmp; + i = strtonum(arg + 3, 0, INT_MAX, &errstr); + if (errstr) { + BIO_printf(err, + "Invalid file descriptor %s: %s\n", + arg, errstr); + return NULL; + } + pwdbio = BIO_new_fd(i, BIO_NOCLOSE); + if (!pwdbio) { + BIO_printf(err, + "Can't access file descriptor %s\n", + arg + 3); + return NULL; + } + /* + * Can't do BIO_gets on an fd BIO so add a buffering + * BIO + */ + btmp = BIO_new(BIO_f_buffer()); + pwdbio = BIO_push(btmp, pwdbio); + } else if (!strcmp(arg, "stdin")) { + pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); + if (!pwdbio) { + BIO_printf(err, "Can't open BIO for stdin\n"); + return NULL; + } + } else { + BIO_printf(err, "Invalid password argument \"%s\"\n", + arg); + return NULL; + } + } + i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); + if (keepbio != 1) { + BIO_free_all(pwdbio); + pwdbio = NULL; + } + if (i <= 0) { + BIO_printf(err, "Error reading password from BIO\n"); + return NULL; + } + tmp = strchr(tpass, '\n'); + if (tmp) + *tmp = 0; + return strdup(tpass); +} + +int +add_oid_section(BIO *err, CONF *conf) +{ + char *p; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *cnf; + int i; + + if (!(p = NCONF_get_string(conf, NULL, "oid_section"))) { + ERR_clear_error(); + return 1; + } + if (!(sktmp = NCONF_get_section(conf, p))) { + BIO_printf(err, "problem loading oid section %s\n", p); + return 0; + } + for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { + cnf = sk_CONF_VALUE_value(sktmp, i); + if (OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { + BIO_printf(err, "problem creating object %s=%s\n", + cnf->name, cnf->value); + return 0; + } + } + return 1; +} + +static int +load_pkcs12(BIO *err, BIO *in, const char *desc, pem_password_cb *pem_cb, + void *cb_data, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) +{ + const char *pass; + char tpass[PEM_BUFSIZE]; + int len, ret = 0; + PKCS12 *p12; + + p12 = d2i_PKCS12_bio(in, NULL); + if (p12 == NULL) { + BIO_printf(err, "Error loading PKCS12 file for %s\n", desc); + goto die; + } + /* See if an empty password will do */ + if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) + pass = ""; + else { + if (!pem_cb) + pem_cb = password_callback; + len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data); + if (len < 0) { + BIO_printf(err, "Passpharse callback error for %s\n", + desc); + goto die; + } + if (len < PEM_BUFSIZE) + tpass[len] = 0; + if (!PKCS12_verify_mac(p12, tpass, len)) { + BIO_printf(err, + "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc); + goto die; + } + pass = tpass; + } + ret = PKCS12_parse(p12, pass, pkey, cert, ca); + + die: + PKCS12_free(p12); + return ret; +} + +X509 * +load_cert(BIO *err, const char *file, int format, const char *pass, + const char *cert_descrip) +{ + X509 *x = NULL; + BIO *cert; + + if ((cert = BIO_new(BIO_s_file())) == NULL) { + ERR_print_errors(err); + goto end; + } + if (file == NULL) { + setvbuf(stdin, NULL, _IONBF, 0); + BIO_set_fp(cert, stdin, BIO_NOCLOSE); + } else { + if (BIO_read_filename(cert, file) <= 0) { + BIO_printf(err, "Error opening %s %s\n", + cert_descrip, file); + ERR_print_errors(err); + goto end; + } + } + + if (format == FORMAT_ASN1) + x = d2i_X509_bio(cert, NULL); + else if (format == FORMAT_PEM) + x = PEM_read_bio_X509_AUX(cert, NULL, password_callback, NULL); + else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(err, cert, cert_descrip, NULL, NULL, + NULL, &x, NULL)) + goto end; + } else { + BIO_printf(err, "bad input format specified for %s\n", + cert_descrip); + goto end; + } + + end: + if (x == NULL) { + BIO_printf(err, "unable to load certificate\n"); + ERR_print_errors(err); + } + BIO_free(cert); + return (x); +} + +EVP_PKEY * +load_key(BIO *err, const char *file, int format, int maybe_stdin, + const char *pass, const char *key_descrip) +{ + BIO *key = NULL; + EVP_PKEY *pkey = NULL; + PW_CB_DATA cb_data; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (file == NULL && (!maybe_stdin)) { + BIO_printf(err, "no keyfile specified\n"); + goto end; + } + key = BIO_new(BIO_s_file()); + if (key == NULL) { + ERR_print_errors(err); + goto end; + } + if (file == NULL && maybe_stdin) { + setvbuf(stdin, NULL, _IONBF, 0); + BIO_set_fp(key, stdin, BIO_NOCLOSE); + } else if (BIO_read_filename(key, file) <= 0) { + BIO_printf(err, "Error opening %s %s\n", + key_descrip, file); + ERR_print_errors(err); + goto end; + } + if (format == FORMAT_ASN1) { + pkey = d2i_PrivateKey_bio(key, NULL); + } else if (format == FORMAT_PEM) { + pkey = PEM_read_bio_PrivateKey(key, NULL, password_callback, &cb_data); + } + else if (format == FORMAT_PKCS12) { + if (!load_pkcs12(err, key, key_descrip, password_callback, &cb_data, + &pkey, NULL, NULL)) + goto end; + } +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4) + else if (format == FORMAT_MSBLOB) + pkey = b2i_PrivateKey_bio(key); + else if (format == FORMAT_PVK) + pkey = b2i_PVK_bio(key, password_callback, + &cb_data); +#endif + else { + BIO_printf(err, "bad input format specified for key file\n"); + goto end; + } + end: + BIO_free(key); + if (pkey == NULL) { + BIO_printf(err, "unable to load %s\n", key_descrip); + ERR_print_errors(err); + } + return (pkey); +} + +EVP_PKEY * +load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, + const char *pass, const char *key_descrip) +{ + BIO *key = NULL; + EVP_PKEY *pkey = NULL; + PW_CB_DATA cb_data; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (file == NULL && !maybe_stdin) { + BIO_printf(err, "no keyfile specified\n"); + goto end; + } + key = BIO_new(BIO_s_file()); + if (key == NULL) { + ERR_print_errors(err); + goto end; + } + if (file == NULL && maybe_stdin) { + setvbuf(stdin, NULL, _IONBF, 0); + BIO_set_fp(key, stdin, BIO_NOCLOSE); + } else if (BIO_read_filename(key, file) <= 0) { + BIO_printf(err, "Error opening %s %s\n", key_descrip, file); + ERR_print_errors(err); + goto end; + } + if (format == FORMAT_ASN1) { + pkey = d2i_PUBKEY_bio(key, NULL); + } + else if (format == FORMAT_ASN1RSA) { + RSA *rsa; + rsa = d2i_RSAPublicKey_bio(key, NULL); + if (rsa) { + pkey = EVP_PKEY_new(); + if (pkey) + EVP_PKEY_set1_RSA(pkey, rsa); + RSA_free(rsa); + } else + pkey = NULL; + } else if (format == FORMAT_PEMRSA) { + RSA *rsa; + rsa = PEM_read_bio_RSAPublicKey(key, NULL, password_callback, &cb_data); + if (rsa) { + pkey = EVP_PKEY_new(); + if (pkey) + EVP_PKEY_set1_RSA(pkey, rsa); + RSA_free(rsa); + } else + pkey = NULL; + } + else if (format == FORMAT_PEM) { + pkey = PEM_read_bio_PUBKEY(key, NULL, password_callback, &cb_data); + } +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) + else if (format == FORMAT_MSBLOB) + pkey = b2i_PublicKey_bio(key); +#endif + else { + BIO_printf(err, "bad input format specified for key file\n"); + goto end; + } + + end: + BIO_free(key); + if (pkey == NULL) + BIO_printf(err, "unable to load %s\n", key_descrip); + return (pkey); +} + +static int +load_certs_crls(BIO *err, const char *file, int format, const char *pass, + const char *desc, STACK_OF(X509) **pcerts, + STACK_OF(X509_CRL) **pcrls) +{ + int i; + BIO *bio; + STACK_OF(X509_INFO) *xis = NULL; + X509_INFO *xi; + PW_CB_DATA cb_data; + int rv = 0; + + cb_data.password = pass; + cb_data.prompt_info = file; + + if (format != FORMAT_PEM) { + BIO_printf(err, "bad input format specified for %s\n", desc); + return 0; + } + if (file == NULL) + bio = BIO_new_fp(stdin, BIO_NOCLOSE); + else + bio = BIO_new_file(file, "r"); + + if (bio == NULL) { + BIO_printf(err, "Error opening %s %s\n", + desc, file ? file : "stdin"); + ERR_print_errors(err); + return 0; + } + xis = PEM_X509_INFO_read_bio(bio, NULL, password_callback, &cb_data); + + BIO_free(bio); + + if (pcerts) { + *pcerts = sk_X509_new_null(); + if (!*pcerts) + goto end; + } + if (pcrls) { + *pcrls = sk_X509_CRL_new_null(); + if (!*pcrls) + goto end; + } + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + xi = sk_X509_INFO_value(xis, i); + if (xi->x509 && pcerts) { + if (!sk_X509_push(*pcerts, xi->x509)) + goto end; + xi->x509 = NULL; + } + if (xi->crl && pcrls) { + if (!sk_X509_CRL_push(*pcrls, xi->crl)) + goto end; + xi->crl = NULL; + } + } + + if (pcerts && sk_X509_num(*pcerts) > 0) + rv = 1; + + if (pcrls && sk_X509_CRL_num(*pcrls) > 0) + rv = 1; + + end: + sk_X509_INFO_pop_free(xis, X509_INFO_free); + + if (rv == 0) { + if (pcerts) { + sk_X509_pop_free(*pcerts, X509_free); + *pcerts = NULL; + } + if (pcrls) { + sk_X509_CRL_pop_free(*pcrls, X509_CRL_free); + *pcrls = NULL; + } + BIO_printf(err, "unable to load %s\n", + pcerts ? "certificates" : "CRLs"); + ERR_print_errors(err); + } + return rv; +} + +STACK_OF(X509) * +load_certs(BIO *err, const char *file, int format, const char *pass, + const char *desc) +{ + STACK_OF(X509) *certs; + + if (!load_certs_crls(err, file, format, pass, desc, &certs, NULL)) + return NULL; + return certs; +} + +STACK_OF(X509_CRL) * +load_crls(BIO *err, const char *file, int format, const char *pass, + const char *desc) +{ + STACK_OF(X509_CRL) *crls; + + if (!load_certs_crls(err, file, format, pass, desc, NULL, &crls)) + return NULL; + return crls; +} + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +#define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \ + X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION) + +int +set_cert_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL cert_tbl[] = { + {"compatible", X509_FLAG_COMPAT, 0xffffffffl}, + {"ca_default", X509_FLAG_CA, 0xffffffffl}, + {"no_header", X509_FLAG_NO_HEADER, 0}, + {"no_version", X509_FLAG_NO_VERSION, 0}, + {"no_serial", X509_FLAG_NO_SERIAL, 0}, + {"no_signame", X509_FLAG_NO_SIGNAME, 0}, + {"no_validity", X509_FLAG_NO_VALIDITY, 0}, + {"no_subject", X509_FLAG_NO_SUBJECT, 0}, + {"no_issuer", X509_FLAG_NO_ISSUER, 0}, + {"no_pubkey", X509_FLAG_NO_PUBKEY, 0}, + {"no_extensions", X509_FLAG_NO_EXTENSIONS, 0}, + {"no_sigdump", X509_FLAG_NO_SIGDUMP, 0}, + {"no_aux", X509_FLAG_NO_AUX, 0}, + {"no_attributes", X509_FLAG_NO_ATTRIBUTES, 0}, + {"ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK}, + {"ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {"ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK}, + {NULL, 0, 0} + }; + return set_multi_opts(flags, arg, cert_tbl); +} + +int +set_name_ex(unsigned long *flags, const char *arg) +{ + static const NAME_EX_TBL ex_tbl[] = { + {"esc_2253", ASN1_STRFLGS_ESC_2253, 0}, + {"esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0}, + {"esc_msb", ASN1_STRFLGS_ESC_MSB, 0}, + {"use_quote", ASN1_STRFLGS_ESC_QUOTE, 0}, + {"utf8", ASN1_STRFLGS_UTF8_CONVERT, 0}, + {"ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0}, + {"show_type", ASN1_STRFLGS_SHOW_TYPE, 0}, + {"dump_all", ASN1_STRFLGS_DUMP_ALL, 0}, + {"dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0}, + {"dump_der", ASN1_STRFLGS_DUMP_DER, 0}, + {"compat", XN_FLAG_COMPAT, 0xffffffffL}, + {"sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK}, + {"sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK}, + {"sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK}, + {"dn_rev", XN_FLAG_DN_REV, 0}, + {"nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK}, + {"sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK}, + {"lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK}, + {"align", XN_FLAG_FN_ALIGN, 0}, + {"oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK}, + {"space_eq", XN_FLAG_SPC_EQ, 0}, + {"dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0}, + {"RFC2253", XN_FLAG_RFC2253, 0xffffffffL}, + {"oneline", XN_FLAG_ONELINE, 0xffffffffL}, + {"multiline", XN_FLAG_MULTILINE, 0xffffffffL}, + {"ca_default", XN_FLAG_MULTILINE, 0xffffffffL}, + {NULL, 0, 0} + }; + if (!set_multi_opts(flags, arg, ex_tbl)) + return 0; + if (*flags != XN_FLAG_COMPAT && (*flags & XN_FLAG_SEP_MASK) == 0) + *flags |= XN_FLAG_SEP_CPLUS_SPC; + return 1; +} + +int +set_ext_copy(int *copy_type, const char *arg) +{ + if (!strcasecmp(arg, "none")) + *copy_type = EXT_COPY_NONE; + else if (!strcasecmp(arg, "copy")) + *copy_type = EXT_COPY_ADD; + else if (!strcasecmp(arg, "copyall")) + *copy_type = EXT_COPY_ALL; + else + return 0; + return 1; +} + +int +copy_extensions(X509 *x, X509_REQ *req, int copy_type) +{ + STACK_OF(X509_EXTENSION) *exts = NULL; + X509_EXTENSION *ext, *tmpext; + ASN1_OBJECT *obj; + int i, idx, ret = 0; + + if (!x || !req || (copy_type == EXT_COPY_NONE)) + return 1; + exts = X509_REQ_get_extensions(req); + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ext = sk_X509_EXTENSION_value(exts, i); + obj = X509_EXTENSION_get_object(ext); + idx = X509_get_ext_by_OBJ(x, obj, -1); + /* Does extension exist? */ + if (idx != -1) { + /* If normal copy don't override existing extension */ + if (copy_type == EXT_COPY_ADD) + continue; + /* Delete all extensions of same type */ + do { + tmpext = X509_get_ext(x, idx); + X509_delete_ext(x, idx); + X509_EXTENSION_free(tmpext); + idx = X509_get_ext_by_OBJ(x, obj, -1); + } while (idx != -1); + } + if (!X509_add_ext(x, ext, -1)) + goto end; + } + + ret = 1; + + end: + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + + return ret; +} + +static int +set_multi_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL *in_tbl) +{ + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *val; + int i, ret = 1; + + if (!arg) + return 0; + vals = X509V3_parse_list(arg); + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + val = sk_CONF_VALUE_value(vals, i); + if (!set_table_opts(flags, val->name, in_tbl)) + ret = 0; + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return ret; +} + +static int +set_table_opts(unsigned long *flags, const char *arg, + const NAME_EX_TBL *in_tbl) +{ + char c; + const NAME_EX_TBL *ptbl; + + c = arg[0]; + if (c == '-') { + c = 0; + arg++; + } else if (c == '+') { + c = 1; + arg++; + } else + c = 1; + + for (ptbl = in_tbl; ptbl->name; ptbl++) { + if (!strcasecmp(arg, ptbl->name)) { + *flags &= ~ptbl->mask; + if (c) + *flags |= ptbl->flag; + else + *flags &= ~ptbl->flag; + return 1; + } + } + return 0; +} + +void +print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags) +{ + char *buf; + char mline = 0; + int indent = 0; + + if (title) + BIO_puts(out, title); + if ((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { + mline = 1; + indent = 4; + } + if (lflags == XN_FLAG_COMPAT) { + buf = X509_NAME_oneline(nm, 0, 0); + BIO_puts(out, buf); + BIO_puts(out, "\n"); + free(buf); + } else { + if (mline) + BIO_puts(out, "\n"); + X509_NAME_print_ex(out, nm, indent, lflags); + BIO_puts(out, "\n"); + } +} + +X509_STORE * +setup_verify(BIO *bp, char *CAfile, char *CApath) +{ + X509_STORE *store; + X509_LOOKUP *lookup; + + if (!(store = X509_STORE_new())) + goto end; + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + goto end; + if (CAfile) { + if (!X509_LOOKUP_load_file(lookup, CAfile, X509_FILETYPE_PEM)) { + BIO_printf(bp, "Error loading file %s\n", CAfile); + goto end; + } + } else + X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT); + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + goto end; + if (CApath) { + if (!X509_LOOKUP_add_dir(lookup, CApath, X509_FILETYPE_PEM)) { + BIO_printf(bp, "Error loading directory %s\n", CApath); + goto end; + } + } else + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + ERR_clear_error(); + return store; + + end: + X509_STORE_free(store); + return NULL; +} + +int +load_config(BIO *err, CONF *cnf) +{ + static int load_config_called = 0; + + if (load_config_called) + return 1; + load_config_called = 1; + if (cnf == NULL) + cnf = config; + if (cnf == NULL) + return 1; + + OPENSSL_load_builtin_modules(); + + if (CONF_modules_load(cnf, NULL, 0) <= 0) { + BIO_printf(err, "Error configuring OpenSSL\n"); + ERR_print_errors(err); + return 0; + } + return 1; +} + +char * +make_config_name(void) +{ + const char *t = X509_get_default_cert_area(); + char *p; + + if (asprintf(&p, "%s/openssl.cnf", t) == -1) + return NULL; + return p; +} + +static unsigned long +index_serial_hash(const OPENSSL_CSTRING *a) +{ + const char *n; + + n = a[DB_serial]; + while (*n == '0') + n++; + return (lh_strhash(n)); +} + +static int +index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) +{ + const char *aa, *bb; + + for (aa = a[DB_serial]; *aa == '0'; aa++) + ; + for (bb = b[DB_serial]; *bb == '0'; bb++) + ; + return (strcmp(aa, bb)); +} + +static int +index_name_qual(char **a) +{ + return (a[0][0] == 'V'); +} + +static unsigned long +index_name_hash(const OPENSSL_CSTRING *a) +{ + return (lh_strhash(a[DB_name])); +} + +int +index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b) +{ + return (strcmp(a[DB_name], b[DB_name])); +} + +static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) +static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) + +BIGNUM * +load_serial(char *serialfile, int create, ASN1_INTEGER **retai) +{ + BIO *in = NULL; + BIGNUM *ret = NULL; + char buf[1024]; + ASN1_INTEGER *ai = NULL; + + ai = ASN1_INTEGER_new(); + if (ai == NULL) + goto err; + + if ((in = BIO_new(BIO_s_file())) == NULL) { + ERR_print_errors(bio_err); + goto err; + } + if (BIO_read_filename(in, serialfile) <= 0) { + if (!create) { + perror(serialfile); + goto err; + } else { + ret = BN_new(); + if (ret == NULL || !rand_serial(ret, ai)) + BIO_printf(bio_err, "Out of memory\n"); + } + } else { + if (!a2i_ASN1_INTEGER(in, ai, buf, sizeof buf)) { + BIO_printf(bio_err, "unable to load number from %s\n", + serialfile); + goto err; + } + ret = ASN1_INTEGER_to_BN(ai, NULL); + if (ret == NULL) { + BIO_printf(bio_err, + "error converting number from bin to BIGNUM\n"); + goto err; + } + } + + if (ret && retai) { + *retai = ai; + ai = NULL; + } + + err: + BIO_free(in); + ASN1_INTEGER_free(ai); + return (ret); +} + +int +save_serial(char *serialfile, char *suffix, BIGNUM *serial, + ASN1_INTEGER **retai) +{ + char serialpath[PATH_MAX]; + BIO *out = NULL; + int ret = 0, n; + ASN1_INTEGER *ai = NULL; + + if (suffix == NULL) + n = strlcpy(serialpath, serialfile, sizeof serialpath); + else + n = snprintf(serialpath, sizeof serialpath, "%s.%s", + serialfile, suffix); + if (n < 0 || n >= sizeof(serialpath)) { + BIO_printf(bio_err, "serial too long\n"); + goto err; + } + out = BIO_new(BIO_s_file()); + if (out == NULL) { + ERR_print_errors(bio_err); + goto err; + } + if (BIO_write_filename(out, serialpath) <= 0) { + perror(serialfile); + goto err; + } + if ((ai = BN_to_ASN1_INTEGER(serial, NULL)) == NULL) { + BIO_printf(bio_err, + "error converting serial to ASN.1 format\n"); + goto err; + } + i2a_ASN1_INTEGER(out, ai); + BIO_puts(out, "\n"); + ret = 1; + if (retai) { + *retai = ai; + ai = NULL; + } + + err: + BIO_free_all(out); + ASN1_INTEGER_free(ai); + return (ret); +} + +int +rotate_serial(char *serialfile, char *new_suffix, char *old_suffix) +{ + char opath[PATH_MAX], npath[PATH_MAX]; + + if (snprintf(npath, sizeof npath, "%s.%s", serialfile, + new_suffix) >= sizeof npath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + + if (snprintf(opath, sizeof opath, "%s.%s", serialfile, + old_suffix) >= sizeof opath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + + if (rename(serialfile, opath) == -1 && + errno != ENOENT && errno != ENOTDIR) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + serialfile, opath); + perror("reason"); + goto err; + } + + + if (rename(npath, serialfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + npath, serialfile); + perror("reason"); + if (rename(opath, serialfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + opath, serialfile); + perror("reason"); + } + goto err; + } + return 1; + + err: + return 0; +} + +int +rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + + if (b) + btmp = b; + else + btmp = BN_new(); + + if (!btmp) + return 0; + + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + + error: + if (b != btmp) + BN_free(btmp); + + return ret; +} + +CA_DB * +load_index(char *dbfile, DB_ATTR *db_attr) +{ + CA_DB *retdb = NULL; + TXT_DB *tmpdb = NULL; + BIO *in = BIO_new(BIO_s_file()); + CONF *dbattr_conf = NULL; + char attrpath[PATH_MAX]; + long errorline = -1; + + if (in == NULL) { + ERR_print_errors(bio_err); + goto err; + } + if (BIO_read_filename(in, dbfile) <= 0) { + perror(dbfile); + BIO_printf(bio_err, "unable to open '%s'\n", dbfile); + goto err; + } + if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL) + goto err; + + if (snprintf(attrpath, sizeof attrpath, "%s.attr", dbfile) + >= sizeof attrpath) { + BIO_printf(bio_err, "attr filename too long\n"); + goto err; + } + + dbattr_conf = NCONF_new(NULL); + if (NCONF_load(dbattr_conf, attrpath, &errorline) <= 0) { + if (errorline > 0) { + BIO_printf(bio_err, + "error on line %ld of db attribute file '%s'\n", + errorline, attrpath); + goto err; + } else { + NCONF_free(dbattr_conf); + dbattr_conf = NULL; + } + } + if ((retdb = malloc(sizeof(CA_DB))) == NULL) { + fprintf(stderr, "Out of memory\n"); + goto err; + } + retdb->db = tmpdb; + tmpdb = NULL; + if (db_attr) + retdb->attributes = *db_attr; + else { + retdb->attributes.unique_subject = 1; + } + + if (dbattr_conf) { + char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject"); + if (p) { + retdb->attributes.unique_subject = parse_yesno(p, 1); + } + } + + err: + NCONF_free(dbattr_conf); + TXT_DB_free(tmpdb); + BIO_free_all(in); + return retdb; +} + +int +index_index(CA_DB *db) +{ + if (!TXT_DB_create_index(db->db, DB_serial, NULL, + LHASH_HASH_FN(index_serial), LHASH_COMP_FN(index_serial))) { + BIO_printf(bio_err, + "error creating serial number index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + return 0; + } + if (db->attributes.unique_subject && + !TXT_DB_create_index(db->db, DB_name, index_name_qual, + LHASH_HASH_FN(index_name), LHASH_COMP_FN(index_name))) { + BIO_printf(bio_err, "error creating name index:(%ld,%ld,%ld)\n", + db->db->error, db->db->arg1, db->db->arg2); + return 0; + } + return 1; +} + +int +save_index(const char *file, const char *suffix, CA_DB *db) +{ + char attrpath[PATH_MAX], dbfile[PATH_MAX]; + BIO *out = BIO_new(BIO_s_file()); + int j; + + if (out == NULL) { + ERR_print_errors(bio_err); + goto err; + } + if (snprintf(attrpath, sizeof attrpath, "%s.attr.%s", + file, suffix) >= sizeof attrpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (snprintf(dbfile, sizeof dbfile, "%s.%s", + file, suffix) >= sizeof dbfile) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + + if (BIO_write_filename(out, dbfile) <= 0) { + perror(dbfile); + BIO_printf(bio_err, "unable to open '%s'\n", dbfile); + goto err; + } + j = TXT_DB_write(out, db->db); + if (j <= 0) + goto err; + + BIO_free(out); + + out = BIO_new(BIO_s_file()); + + if (BIO_write_filename(out, attrpath) <= 0) { + perror(attrpath); + BIO_printf(bio_err, "unable to open '%s'\n", attrpath); + goto err; + } + BIO_printf(out, "unique_subject = %s\n", + db->attributes.unique_subject ? "yes" : "no"); + BIO_free(out); + + return 1; + + err: + return 0; +} + +int +rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix) +{ + char attrpath[PATH_MAX], nattrpath[PATH_MAX], oattrpath[PATH_MAX]; + char dbpath[PATH_MAX], odbpath[PATH_MAX]; + + if (snprintf(attrpath, sizeof attrpath, "%s.attr", + dbfile) >= sizeof attrpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (snprintf(nattrpath, sizeof nattrpath, "%s.attr.%s", + dbfile, new_suffix) >= sizeof nattrpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (snprintf(oattrpath, sizeof oattrpath, "%s.attr.%s", + dbfile, old_suffix) >= sizeof oattrpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (snprintf(dbpath, sizeof dbpath, "%s.%s", + dbfile, new_suffix) >= sizeof dbpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + if (snprintf(odbpath, sizeof odbpath, "%s.%s", + dbfile, old_suffix) >= sizeof odbpath) { + BIO_printf(bio_err, "file name too long\n"); + goto err; + } + + if (rename(dbfile, odbpath) == -1 && errno != ENOENT && errno != ENOTDIR) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + dbfile, odbpath); + perror("reason"); + goto err; + } + + if (rename(dbpath, dbfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + dbpath, dbfile); + perror("reason"); + if (rename(odbpath, dbfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + odbpath, dbfile); + perror("reason"); + } + goto err; + } + + if (rename(attrpath, oattrpath) == -1 && errno != ENOENT && errno != ENOTDIR) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + attrpath, oattrpath); + perror("reason"); + if (rename(dbfile, dbpath) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + dbfile, dbpath); + perror("reason"); + } + if (rename(odbpath, dbfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + odbpath, dbfile); + perror("reason"); + } + goto err; + } + + if (rename(nattrpath, attrpath) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + nattrpath, attrpath); + perror("reason"); + if (rename(oattrpath, attrpath) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + oattrpath, attrpath); + perror("reason"); + } + if (rename(dbfile, dbpath) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + dbfile, dbpath); + perror("reason"); + } + if (rename(odbpath, dbfile) == -1) { + BIO_printf(bio_err, "unable to rename %s to %s\n", + odbpath, dbfile); + perror("reason"); + } + goto err; + } + return 1; + + err: + return 0; +} + +void +free_index(CA_DB *db) +{ + if (db) { + TXT_DB_free(db->db); + free(db); + } +} + +int +parse_yesno(const char *str, int def) +{ + int ret = def; + + if (str) { + switch (*str) { + case 'f': /* false */ + case 'F': /* FALSE */ + case 'n': /* no */ + case 'N': /* NO */ + case '0': /* 0 */ + ret = 0; + break; + case 't': /* true */ + case 'T': /* TRUE */ + case 'y': /* yes */ + case 'Y': /* YES */ + case '1': /* 1 */ + ret = 1; + break; + default: + ret = def; + break; + } + } + return ret; +} + +/* + * subject is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ +X509_NAME * +parse_name(char *subject, long chtype, int multirdn) +{ + X509_NAME *name = NULL; + size_t buflen, max_ne; + char **ne_types, **ne_values; + char *buf, *bp, *sp; + int i, nid, ne_num = 0; + int *mval; + + /* + * Buffer to copy the types and values into. Due to escaping the + * copy can only become shorter. + */ + buflen = strlen(subject) + 1; + buf = malloc(buflen); + + /* Maximum number of name elements. */ + max_ne = buflen / 2 + 1; + ne_types = reallocarray(NULL, max_ne, sizeof(char *)); + ne_values = reallocarray(NULL, max_ne, sizeof(char *)); + mval = reallocarray(NULL, max_ne, sizeof(int)); + + if (buf == NULL || ne_types == NULL || ne_values == NULL || + mval == NULL) { + BIO_printf(bio_err, "malloc error\n"); + goto error; + } + + bp = buf; + sp = subject; + + if (*subject != '/') { + BIO_printf(bio_err, "Subject does not start with '/'.\n"); + goto error; + } + + /* Skip leading '/'. */ + sp++; + + /* No multivalued RDN by default. */ + mval[ne_num] = 0; + + while (*sp) { + /* Collect type. */ + ne_types[ne_num] = bp; + while (*sp) { + /* is there anything to escape in the type...? */ + if (*sp == '\\') { + if (*++sp) + *bp++ = *sp++; + else { + BIO_printf(bio_err, "escape character " + "at end of string\n"); + goto error; + } + } else if (*sp == '=') { + sp++; + *bp++ = '\0'; + break; + } else + *bp++ = *sp++; + } + if (!*sp) { + BIO_printf(bio_err, "end of string encountered while " + "processing type of subject name element #%d\n", + ne_num); + goto error; + } + ne_values[ne_num] = bp; + while (*sp) { + if (*sp == '\\') { + if (*++sp) + *bp++ = *sp++; + else { + BIO_printf(bio_err, "escape character " + "at end of string\n"); + goto error; + } + } else if (*sp == '/') { + sp++; + /* no multivalued RDN by default */ + mval[ne_num + 1] = 0; + break; + } else if (*sp == '+' && multirdn) { + /* a not escaped + signals a multivalued RDN */ + sp++; + mval[ne_num + 1] = -1; + break; + } else + *bp++ = *sp++; + } + *bp++ = '\0'; + ne_num++; + } + + if ((name = X509_NAME_new()) == NULL) + goto error; + + for (i = 0; i < ne_num; i++) { + if ((nid = OBJ_txt2nid(ne_types[i])) == NID_undef) { + BIO_printf(bio_err, + "Subject Attribute %s has no known NID, skipped\n", + ne_types[i]); + continue; + } + if (!*ne_values[i]) { + BIO_printf(bio_err, "No value provided for Subject " + "Attribute %s, skipped\n", ne_types[i]); + continue; + } + if (!X509_NAME_add_entry_by_NID(name, nid, chtype, + (unsigned char *) ne_values[i], -1, -1, mval[i])) + goto error; + } + goto done; + + error: + X509_NAME_free(name); + name = NULL; + + done: + free(ne_values); + free(ne_types); + free(mval); + free(buf); + + return name; +} + +int +args_verify(char ***pargs, int *pargc, int *badarg, BIO *err, + X509_VERIFY_PARAM **pm) +{ + ASN1_OBJECT *otmp = NULL; + unsigned long flags = 0; + int i; + int purpose = 0, depth = -1; + char **oldargs = *pargs; + char *arg = **pargs, *argn = (*pargs)[1]; + time_t at_time = 0; + const char *errstr = NULL; + + if (!strcmp(arg, "-policy")) { + if (!argn) + *badarg = 1; + else { + otmp = OBJ_txt2obj(argn, 0); + if (!otmp) { + BIO_printf(err, "Invalid Policy \"%s\"\n", + argn); + *badarg = 1; + } + } + (*pargs)++; + } else if (strcmp(arg, "-purpose") == 0) { + X509_PURPOSE *xptmp; + if (!argn) + *badarg = 1; + else { + i = X509_PURPOSE_get_by_sname(argn); + if (i < 0) { + BIO_printf(err, "unrecognized purpose\n"); + *badarg = 1; + } else { + xptmp = X509_PURPOSE_get0(i); + purpose = X509_PURPOSE_get_id(xptmp); + } + } + (*pargs)++; + } else if (strcmp(arg, "-verify_depth") == 0) { + if (!argn) + *badarg = 1; + else { + depth = strtonum(argn, 1, INT_MAX, &errstr); + if (errstr) { + BIO_printf(err, "invalid depth %s: %s\n", + argn, errstr); + *badarg = 1; + } + } + (*pargs)++; + } else if (strcmp(arg, "-attime") == 0) { + if (!argn) + *badarg = 1; + else { + long long timestamp; + /* + * interpret the -attime argument as seconds since + * Epoch + */ + if (sscanf(argn, "%lli", ×tamp) != 1) { + BIO_printf(bio_err, + "Error parsing timestamp %s\n", + argn); + *badarg = 1; + } + /* XXX 2038 truncation */ + at_time = (time_t) timestamp; + } + (*pargs)++; + } else if (!strcmp(arg, "-ignore_critical")) + flags |= X509_V_FLAG_IGNORE_CRITICAL; + else if (!strcmp(arg, "-issuer_checks")) + flags |= X509_V_FLAG_CB_ISSUER_CHECK; + else if (!strcmp(arg, "-crl_check")) + flags |= X509_V_FLAG_CRL_CHECK; + else if (!strcmp(arg, "-crl_check_all")) + flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; + else if (!strcmp(arg, "-policy_check")) + flags |= X509_V_FLAG_POLICY_CHECK; + else if (!strcmp(arg, "-explicit_policy")) + flags |= X509_V_FLAG_EXPLICIT_POLICY; + else if (!strcmp(arg, "-legacy_verify")) + flags |= X509_V_FLAG_LEGACY_VERIFY; + else if (!strcmp(arg, "-inhibit_any")) + flags |= X509_V_FLAG_INHIBIT_ANY; + else if (!strcmp(arg, "-inhibit_map")) + flags |= X509_V_FLAG_INHIBIT_MAP; + else if (!strcmp(arg, "-x509_strict")) + flags |= X509_V_FLAG_X509_STRICT; + else if (!strcmp(arg, "-extended_crl")) + flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT; + else if (!strcmp(arg, "-use_deltas")) + flags |= X509_V_FLAG_USE_DELTAS; + else if (!strcmp(arg, "-policy_print")) + flags |= X509_V_FLAG_NOTIFY_POLICY; + else if (!strcmp(arg, "-check_ss_sig")) + flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; + else + return 0; + + if (*badarg) { + X509_VERIFY_PARAM_free(*pm); + *pm = NULL; + goto end; + } + if (!*pm && !(*pm = X509_VERIFY_PARAM_new())) { + *badarg = 1; + goto end; + } + if (otmp) { + X509_VERIFY_PARAM_add0_policy(*pm, otmp); + otmp = NULL; + } + if (flags) + X509_VERIFY_PARAM_set_flags(*pm, flags); + + if (purpose) + X509_VERIFY_PARAM_set_purpose(*pm, purpose); + + if (depth >= 0) + X509_VERIFY_PARAM_set_depth(*pm, depth); + + if (at_time) + X509_VERIFY_PARAM_set_time(*pm, at_time); + + end: + (*pargs)++; + + if (pargc) + *pargc -= *pargs - oldargs; + + ASN1_OBJECT_free(otmp); + return 1; +} + +/* Read whole contents of a BIO into an allocated memory buffer and + * return it. + */ + +int +bio_to_mem(unsigned char **out, int maxlen, BIO *in) +{ + BIO *mem; + int len, ret; + unsigned char tbuf[1024]; + + mem = BIO_new(BIO_s_mem()); + if (!mem) + return -1; + for (;;) { + if ((maxlen != -1) && maxlen < 1024) + len = maxlen; + else + len = 1024; + len = BIO_read(in, tbuf, len); + if (len <= 0) + break; + if (BIO_write(mem, tbuf, len) != len) { + BIO_free(mem); + return -1; + } + maxlen -= len; + + if (maxlen == 0) + break; + } + ret = BIO_get_mem_data(mem, (char **) out); + BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY); + BIO_free(mem); + return ret; +} + +int +pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value) +{ + int rv; + char *stmp, *vtmp = NULL; + + if (value == NULL) + return -1; + stmp = strdup(value); + if (!stmp) + return -1; + vtmp = strchr(stmp, ':'); + if (vtmp) { + *vtmp = 0; + vtmp++; + } + rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp); + free(stmp); + + return rv; +} + +/* + * next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL termianted string like "abc,def,ghi" + * + * returns: a malloced buffer or NULL on failure. + */ +unsigned char * +next_protos_parse(unsigned short *outlen, const char *in) +{ + size_t len; + unsigned char *out; + size_t i, start = 0; + + len = strlen(in); + if (len >= 65535) + return NULL; + + out = malloc(strlen(in) + 1); + if (!out) + return NULL; + + for (i = 0; i <= len; ++i) { + if (i == len || in[i] == ',') { + if (i - start > 255) { + free(out); + return NULL; + } + out[start] = i - start; + start = i + 1; + } else + out[i + 1] = in[i]; + } + + *outlen = len + 1; + return out; +} + +int +app_isdir(const char *name) +{ + struct stat st; + + if (stat(name, &st) == 0) + return S_ISDIR(st.st_mode); + return -1; +} + +#define OPTION_WIDTH 18 + +void +options_usage(const struct option *opts) +{ + const char *p, *q; + char optstr[32]; + int i; + + for (i = 0; opts[i].name != NULL; i++) { + if (opts[i].desc == NULL) + continue; + + snprintf(optstr, sizeof(optstr), "-%s %s", opts[i].name, + (opts[i].argname != NULL) ? opts[i].argname : ""); + fprintf(stderr, " %-*s", OPTION_WIDTH, optstr); + if (strlen(optstr) > OPTION_WIDTH) + fprintf(stderr, "\n %-*s", OPTION_WIDTH, ""); + + p = opts[i].desc; + while ((q = strchr(p, '\n')) != NULL) { + fprintf(stderr, " %.*s", (int)(q - p), p); + fprintf(stderr, "\n %-*s", OPTION_WIDTH, ""); + p = q + 1; + } + fprintf(stderr, " %s\n", p); + } +} + +int +options_parse(int argc, char **argv, const struct option *opts, char **unnamed, + int *argsused) +{ + const char *errstr; + const struct option *opt; + long long val; + char *arg, *p; + int fmt, used; + int ord = 0; + int i, j; + + if (unnamed != NULL) + *unnamed = NULL; + + for (i = 1; i < argc; i++) { + p = arg = argv[i]; + + /* Single unnamed argument (without leading hyphen). */ + if (*p++ != '-') { + if (argsused != NULL) + goto done; + if (unnamed == NULL) + goto unknown; + if (*unnamed != NULL) + goto toomany; + *unnamed = arg; + continue; + } + + /* End of named options (single hyphen). */ + if (*p == '\0') { + if (++i >= argc) + goto done; + if (argsused != NULL) + goto done; + if (unnamed != NULL && i == argc - 1) { + if (*unnamed != NULL) + goto toomany; + *unnamed = argv[i]; + continue; + } + goto unknown; + } + + /* See if there is a matching option... */ + for (j = 0; opts[j].name != NULL; j++) { + if (strcmp(p, opts[j].name) == 0) + break; + } + opt = &opts[j]; + if (opt->name == NULL && opt->type == 0) + goto unknown; + + if (opt->type == OPTION_ARG || + opt->type == OPTION_ARG_FORMAT || + opt->type == OPTION_ARG_FUNC || + opt->type == OPTION_ARG_INT || + opt->type == OPTION_ARG_LONG || + opt->type == OPTION_ARG_TIME) { + if (++i >= argc) { + fprintf(stderr, "missing %s argument for -%s\n", + opt->argname, opt->name); + return (1); + } + } + + switch (opt->type) { + case OPTION_ARG: + *opt->opt.arg = argv[i]; + break; + + case OPTION_ARGV_FUNC: + if (opt->opt.argvfunc(argc - i, &argv[i], &used) != 0) + return (1); + i += used - 1; + break; + + case OPTION_ARG_FORMAT: + fmt = str2fmt(argv[i]); + if (fmt == FORMAT_UNDEF) { + fprintf(stderr, "unknown %s '%s' for -%s\n", + opt->argname, argv[i], opt->name); + return (1); + } + *opt->opt.value = fmt; + break; + + case OPTION_ARG_FUNC: + if (opt->opt.argfunc(argv[i]) != 0) + return (1); + break; + + case OPTION_ARG_INT: + val = strtonum(argv[i], 0, INT_MAX, &errstr); + if (errstr != NULL) { + fprintf(stderr, "%s %s argument for -%s\n", + errstr, opt->argname, opt->name); + return (1); + } + *opt->opt.value = (int)val; + break; + + case OPTION_ARG_LONG: + val = strtonum(argv[i], 0, LONG_MAX, &errstr); + if (errstr != NULL) { + fprintf(stderr, "%s %s argument for -%s\n", + errstr, opt->argname, opt->name); + return (1); + } + *opt->opt.lvalue = (long)val; + break; + + case OPTION_ARG_TIME: + val = strtonum(argv[i], 0, LLONG_MAX, &errstr); + if (errstr != NULL) { + fprintf(stderr, "%s %s argument for -%s\n", + errstr, opt->argname, opt->name); + return (1); + } + *opt->opt.tvalue = val; + break; + + case OPTION_DISCARD: + break; + + case OPTION_FUNC: + if (opt->opt.func() != 0) + return (1); + break; + + case OPTION_FLAG: + *opt->opt.flag = 1; + break; + + case OPTION_FLAG_ORD: + *opt->opt.flag = ++ord; + break; + + case OPTION_VALUE: + *opt->opt.value = opt->value; + break; + + case OPTION_VALUE_AND: + *opt->opt.value &= opt->value; + break; + + case OPTION_VALUE_OR: + *opt->opt.value |= opt->value; + break; + + case OPTION_UL_VALUE_OR: + *opt->opt.ulvalue |= opt->ulvalue; + break; + + case OPTION_ORDER: + *opt->opt.order = ++(*opt->order); + break; + + default: + fprintf(stderr, "option %s - unknown type %i\n", + opt->name, opt->type); + return (1); + } + } + + done: + if (argsused != NULL) + *argsused = i; + + return (0); + + toomany: + fprintf(stderr, "too many arguments\n"); + return (1); + + unknown: + fprintf(stderr, "unknown option '%s'\n", arg); + return (1); +} + +void +show_cipher(const OBJ_NAME *name, void *arg) +{ + int *n = arg; + + if (!islower((unsigned char)*name->name)) + return; + + fprintf(stderr, " -%-24s%s", name->name, (++*n % 3 != 0 ? "" : "\n")); +} + +int +pkey_check(BIO *out, EVP_PKEY *pkey, int (check_fn)(EVP_PKEY_CTX *), + const char *desc) +{ + EVP_PKEY_CTX *ctx; + + if ((ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + ERR_print_errors(bio_err); + return 0; + } + + if (check_fn(ctx) == 1) { + BIO_printf(out, "%s valid\n", desc); + } else { + unsigned long err; + + BIO_printf(out, "%s invalid\n", desc); + + while ((err = ERR_get_error()) != 0) + BIO_printf(out, "Detailed error: %s\n", + ERR_reason_error_string(err)); + } + + EVP_PKEY_CTX_free(ctx); + + return 1; +} diff --git a/apps/openssl/apps.h b/apps/openssl/apps.h new file mode 100644 index 0000000..8556dc1 --- /dev/null +++ b/apps/openssl/apps.h @@ -0,0 +1,324 @@ +/* $OpenBSD: apps.h,v 1.34 2023/06/11 13:02:10 jsg Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_APPS_H +#define HEADER_APPS_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_OCSP +#include +#endif + +#include +extern int single_execution; + +extern CONF *config; +extern char *default_config_file; +extern BIO *bio_err; + +#define PW_MIN_LENGTH 4 +typedef struct pw_cb_data { + const void *password; + const char *prompt_info; +} PW_CB_DATA; + +int password_callback(char *buf, int bufsiz, int verify, void *cb_data); + +int setup_ui(void); +void destroy_ui(void); + +extern UI_METHOD *ui_method; +int ui_open(UI *ui); +int ui_read(UI *ui, UI_STRING *uis); +int ui_write(UI *ui, UI_STRING *uis); +int ui_close(UI *ui); + +int should_retry(int i); +int args_from_file(char *file, int *argc, char **argv[]); +int str2fmt(char *s); +void program_name(char *in, char *out, int size); +#ifdef HEADER_X509_H +int dump_cert_text(BIO *out, X509 *x); +void print_name(BIO *out, const char *title, X509_NAME *nm, + unsigned long lflags); +#endif +int set_cert_ex(unsigned long *flags, const char *arg); +int set_name_ex(unsigned long *flags, const char *arg); +int set_ext_copy(int *copy_type, const char *arg); +int copy_extensions(X509 *x, X509_REQ *req, int copy_type); +int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2); +int add_oid_section(BIO *err, CONF *conf); +X509 *load_cert(BIO *err, const char *file, int format, + const char *pass, const char *cert_descrip); +EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin, + const char *pass, const char *key_descrip); +EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin, + const char *pass, const char *key_descrip); +STACK_OF(X509) *load_certs(BIO *err, const char *file, int format, + const char *pass, const char *cert_descrip); +STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format, + const char *pass, const char *cert_descrip); +X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath); + +#ifndef OPENSSL_NO_OCSP +OCSP_RESPONSE *process_responder(BIO *err, OCSP_REQUEST *req, + char *host, char *path, char *port, int use_ssl, + STACK_OF(CONF_VALUE) *headers, int req_timeout); +#endif + +int load_config(BIO *err, CONF *cnf); +char *make_config_name(void); + +/* Functions defined in ca.c and also used in ocsp.c */ +int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, const char *str); + +#define DB_type 0 +#define DB_exp_date 1 +#define DB_rev_date 2 +#define DB_serial 3 /* index - unique */ +#define DB_file 4 +#define DB_name 5 /* index - unique when active and not disabled */ +#define DB_NUMBER 6 + +#define DB_TYPE_REV 'R' +#define DB_TYPE_EXP 'E' +#define DB_TYPE_VAL 'V' +#define DB_TYPE_SUSP 'S' + +typedef struct db_attr_st { + int unique_subject; +} DB_ATTR; +typedef struct ca_db_st { + DB_ATTR attributes; + TXT_DB *db; +} CA_DB; + +BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai); +int save_serial(char *serialfile, char *suffix, BIGNUM *serial, + ASN1_INTEGER **retai); +int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix); +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); +CA_DB *load_index(char *dbfile, DB_ATTR *dbattr); +int index_index(CA_DB *db); +int save_index(const char *dbfile, const char *suffix, CA_DB *db); +int rotate_index(const char *dbfile, const char *new_suffix, + const char *old_suffix); +void free_index(CA_DB *db); +#define index_name_cmp_noconst(a, b) \ + index_name_cmp((const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, a), \ + (const OPENSSL_CSTRING *)CHECKED_PTR_OF(OPENSSL_STRING, b)) +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b); +int parse_yesno(const char *str, int def); + +X509_NAME *parse_name(char *str, long chtype, int multirdn); +int args_verify(char ***pargs, int *pargc, int *badarg, BIO *err, + X509_VERIFY_PARAM **pm); +int bio_to_mem(unsigned char **out, int maxlen, BIO *in); +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value); +int init_gen_str(BIO *err, EVP_PKEY_CTX **pctx, const char *algname, + int do_param); +int do_X509_sign(BIO *err, X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_REQ_sign(BIO *err, X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); +int do_X509_CRL_sign(BIO *err, X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + STACK_OF(OPENSSL_STRING) *sigopts); + +unsigned char *next_protos_parse(unsigned short *outlen, const char *in); + +#define FORMAT_UNDEF 0 +#define FORMAT_ASN1 1 +#define FORMAT_TEXT 2 +#define FORMAT_PEM 3 + +#define FORMAT_PKCS12 5 +#define FORMAT_SMIME 6 + +#define FORMAT_PEMRSA 9 /* PEM RSAPublicKey format */ +#define FORMAT_ASN1RSA 10 /* DER RSAPublicKey format */ +#define FORMAT_MSBLOB 11 /* MS Key blob format */ +#define FORMAT_PVK 12 /* MS PVK file format */ + +#define EXT_COPY_NONE 0 +#define EXT_COPY_ADD 1 +#define EXT_COPY_ALL 2 + +#define APP_PASS_LEN 1024 + +#define SERIAL_RAND_BITS 64 + +int app_isdir(const char *); + +#define TM_RESET 0 +#define TM_GET 1 +double app_timer_real(int); +double app_timer_user(int); + +#define OPENSSL_NO_SSL_INTERN + +struct option { + const char *name; + const char *argname; + const char *desc; + enum { + OPTION_ARG, + OPTION_ARGV_FUNC, + OPTION_ARG_FORMAT, + OPTION_ARG_FUNC, + OPTION_ARG_INT, + OPTION_ARG_LONG, + OPTION_ARG_TIME, + OPTION_DISCARD, + OPTION_FUNC, + OPTION_FLAG, + OPTION_FLAG_ORD, + OPTION_VALUE, + OPTION_VALUE_AND, + OPTION_VALUE_OR, + OPTION_UL_VALUE_OR, + OPTION_ORDER, + } type; + union { + char **arg; + int (*argfunc)(char *arg); + int (*argvfunc)(int argc, char **argv, int *argsused); + int *flag; + int (*func)(void); + long *lvalue; + int *value; + unsigned long *ulvalue; + time_t *tvalue; + int *order; + } opt; + const int value; + const unsigned long ulvalue; + int *order; +}; + +void options_usage(const struct option *opts); +int options_parse(int argc, char **argv, const struct option *opts, + char **unnamed, int *argsused); + +void show_cipher(const OBJ_NAME *name, void *arg); + +int pkey_check(BIO *out, EVP_PKEY *pkey, int (check_fn)(EVP_PKEY_CTX *), + const char *desc); +#endif diff --git a/apps/openssl/apps_posix.c b/apps/openssl/apps_posix.c new file mode 100644 index 0000000..cdcf821 --- /dev/null +++ b/apps/openssl/apps_posix.c @@ -0,0 +1,175 @@ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * Functions that need to be overridden by non-POSIX operating systems. + */ + +#include +#include + +#include + +#include "apps.h" + +double +app_timer_real(int get) +{ + static struct timespec start; + struct timespec elapsed, now; + + clock_gettime(CLOCK_MONOTONIC, &now); + if (get) { + timespecsub(&now, &start, &elapsed); + return elapsed.tv_sec + elapsed.tv_nsec / 1000000000.0; + } + start = now; + return 0.0; +} + +double +app_timer_user(int get) +{ + static struct timeval start; + struct timeval elapsed; + struct rusage now; + + getrusage(RUSAGE_SELF, &now); + if (get) { + timersub(&now.ru_utime, &start, &elapsed); + return elapsed.tv_sec + elapsed.tv_usec / 1000000.0; + } + start = now.ru_utime; + return 0.0; +} + +int +setup_ui(void) +{ + ui_method = UI_create_method("OpenSSL application user interface"); + UI_method_set_opener(ui_method, ui_open); + UI_method_set_reader(ui_method, ui_read); + UI_method_set_writer(ui_method, ui_write); + UI_method_set_closer(ui_method, ui_close); + return 0; +} + +void +destroy_ui(void) +{ + if (ui_method) { + UI_destroy_method(ui_method); + ui_method = NULL; + } +} diff --git a/apps/openssl/asn1pars.c b/apps/openssl/asn1pars.c new file mode 100644 index 0000000..6b99842 --- /dev/null +++ b/apps/openssl/asn1pars.c @@ -0,0 +1,470 @@ +/* $OpenBSD: asn1pars.c,v 1.16 2023/07/23 11:39:29 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* A nice addition from Dr Stephen Henson to + * add the -strparse option which parses nested binary structures + */ + +#include +#include +#include +#include + +#include "apps.h" +#include "progs.h" + +#include +#include +#include +#include + +static struct { + char *derfile; + int dump; + char *genconf; + char *genstr; + int indent; + char *infile; + int informat; + unsigned int length; + int noout; + int offset; + char *oidfile; + STACK_OF(OPENSSL_STRING) *osk; +} cfg; + +static int +asn1pars_opt_dlimit(char *arg) +{ + const char *errstr; + + cfg.dump = strtonum(arg, 1, INT_MAX, &errstr); + if (errstr) { + fprintf(stderr, "-dlimit must be from 1 to INT_MAX: %s\n", + errstr); + return (-1); + } + return (0); +} + +static int +asn1pars_opt_length(char *arg) +{ + const char *errstr; + + cfg.length = strtonum(arg, 1, UINT_MAX, &errstr); + if (errstr) { + fprintf(stderr, "-length must be from 1 to UINT_MAX: %s\n", + errstr); + return (-1); + } + return (0); +} + +static int +asn1pars_opt_strparse(char *arg) +{ + if (sk_OPENSSL_STRING_push(cfg.osk, arg) == 0) { + fprintf(stderr, "-strparse cannot add argument\n"); + return (-1); + } + return (0); +} + +static const struct option asn1pars_options[] = { + { + .name = "dump", + .desc = "Dump unknown data in hex form", + .type = OPTION_VALUE, + .value = -1, + .opt.value = &cfg.dump, + }, + { + .name = "dlimit", + .argname = "num", + .desc = "Dump the first num bytes of unknown data in hex form", + .type = OPTION_ARG_FUNC, + .opt.argfunc = asn1pars_opt_dlimit, + }, + { + .name = "genconf", + .argname = "file", + .desc = "File to generate ASN.1 structure from", + .type = OPTION_ARG, + .opt.arg = &cfg.genconf, + }, + { + .name = "genstr", + .argname = "string", + .desc = "String to generate ASN.1 structure from", + .type = OPTION_ARG, + .opt.arg = &cfg.genstr, + }, + { + .name = "i", + .desc = "Indent output according to depth of structures", + .type = OPTION_FLAG, + .opt.flag = &cfg.indent, + }, + { + .name = "in", + .argname = "file", + .desc = "The input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "fmt", + .desc = "Input format (DER, TXT or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "length", + .argname = "num", + .desc = "Number of bytes to parse (default until EOF)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = asn1pars_opt_length, + }, + { + .name = "noout", + .desc = "Do not produce any output", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "offset", + .argname = "num", + .desc = "Offset to begin parsing", + .type = OPTION_ARG_INT, + .opt.value = &cfg.offset, + }, + { + .name = "oid", + .argname = "file", + .desc = "File containing additional object identifiers (OIDs)", + .type = OPTION_ARG, + .opt.arg = &cfg.oidfile, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file in DER format", + .type = OPTION_ARG, + .opt.arg = &cfg.derfile, + }, + { + .name = "strparse", + .argname = "offset", + .desc = "Parse the content octets of ASN.1 object starting at" + " offset", + .type = OPTION_ARG_FUNC, + .opt.argfunc = asn1pars_opt_strparse, + }, + { NULL }, +}; + +static void +asn1pars_usage(void) +{ + fprintf(stderr, + "usage: asn1parse [-i] [-dlimit num] [-dump] [-genconf file] " + "[-genstr string]\n" + " [-in file] [-inform fmt] [-length num] [-noout] [-offset num] " + "[-oid file]\n" + " [-out file] [-strparse offset]\n\n"); + options_usage(asn1pars_options); +} + +static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf); + +int +asn1parse_main(int argc, char **argv) +{ + int i, j, ret = 1; + long num, tmplen; + BIO *in = NULL, *out = NULL, *b64 = NULL, *derout = NULL; + char *str = NULL; + const char *errstr = NULL; + unsigned char *tmpbuf; + const unsigned char *ctmpbuf; + BUF_MEM *buf = NULL; + ASN1_TYPE *at = NULL; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + if ((cfg.osk = sk_OPENSSL_STRING_new_null()) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + + if (options_parse(argc, argv, asn1pars_options, NULL, NULL) != 0) { + asn1pars_usage(); + return (1); + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); + + if (cfg.oidfile != NULL) { + if (BIO_read_filename(in, cfg.oidfile) <= 0) { + BIO_printf(bio_err, "problems opening %s\n", + cfg.oidfile); + ERR_print_errors(bio_err); + goto end; + } + OBJ_create_objects(in); + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + if (cfg.derfile != NULL) { + if ((derout = BIO_new_file(cfg.derfile, "wb")) == NULL) { + BIO_printf(bio_err, "problems opening %s\n", + cfg.derfile); + ERR_print_errors(bio_err); + goto end; + } + } + if ((buf = BUF_MEM_new()) == NULL) + goto end; + if (!BUF_MEM_grow(buf, BUFSIZ * 8)) + goto end; + + if (cfg.genstr != NULL || cfg.genconf) { + num = do_generate(bio_err, cfg.genstr, cfg.genconf, buf); + if (num < 0) { + ERR_print_errors(bio_err); + goto end; + } + } else { + if (cfg.informat == FORMAT_PEM) { + BIO *tmp; + + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + BIO_push(b64, in); + tmp = in; + in = b64; + b64 = tmp; + } + num = 0; + for (;;) { + if (!BUF_MEM_grow(buf, (int) num + BUFSIZ)) + goto end; + i = BIO_read(in, &(buf->data[num]), BUFSIZ); + if (i <= 0) + break; + num += i; + } + } + str = buf->data; + + /* If any structs to parse go through in sequence */ + + if (sk_OPENSSL_STRING_num(cfg.osk) > 0) { + tmpbuf = (unsigned char *) str; + tmplen = num; + for (i = 0; i < sk_OPENSSL_STRING_num(cfg.osk); i++) { + ASN1_TYPE *atmp; + int typ; + j = strtonum(sk_OPENSSL_STRING_value(cfg.osk, i), + 1, INT_MAX, &errstr); + if (errstr) { + BIO_printf(bio_err, + "'%s' is an invalid number: %s\n", + sk_OPENSSL_STRING_value(cfg.osk, i), errstr); + continue; + } + tmpbuf += j; + tmplen -= j; + atmp = at; + ctmpbuf = tmpbuf; + at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen); + ASN1_TYPE_free(atmp); + if (!at) { + BIO_printf(bio_err, "Error parsing structure\n"); + ERR_print_errors(bio_err); + goto end; + } + typ = ASN1_TYPE_get(at); + if (typ == V_ASN1_BOOLEAN || typ == V_ASN1_NULL || + typ == V_ASN1_OBJECT) { + BIO_printf(bio_err, "Can't parse %s type\n", + ASN1_tag2str(typ)); + ERR_print_errors(bio_err); + goto end; + } + /* hmm... this is a little evil but it works */ + tmpbuf = at->value.asn1_string->data; + tmplen = at->value.asn1_string->length; + } + str = (char *) tmpbuf; + num = tmplen; + } + if (cfg.offset >= num) { + BIO_printf(bio_err, "Error: offset too large\n"); + goto end; + } + num -= cfg.offset; + + if (cfg.length == 0 || (long)cfg.length > num) + cfg.length = (unsigned int) num; + if (derout != NULL) { + if (BIO_write(derout, str + cfg.offset, + cfg.length) != (int)cfg.length) { + BIO_printf(bio_err, "Error writing output\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (!cfg.noout && !ASN1_parse_dump(out, + (unsigned char *)&str[cfg.offset], cfg.length, cfg.indent, cfg.dump)) { + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + BIO_free(derout); + BIO_free(in); + BIO_free_all(out); + BIO_free(b64); + if (ret != 0) + ERR_print_errors(bio_err); + BUF_MEM_free(buf); + ASN1_TYPE_free(at); + sk_OPENSSL_STRING_free(cfg.osk); + OBJ_cleanup(); + + return (ret); +} + +static int +do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) +{ + CONF *cnf = NULL; + int len; + long errline; + unsigned char *p; + ASN1_TYPE *atyp = NULL; + + if (genconf) { + cnf = NCONF_new(NULL); + if (!NCONF_load(cnf, genconf, &errline)) + goto conferr; + if (!genstr) + genstr = NCONF_get_string(cnf, "default", "asn1"); + if (!genstr) { + BIO_printf(bio, "Can't find 'asn1' in '%s'\n", genconf); + goto err; + } + } + atyp = ASN1_generate_nconf(genstr, cnf); + NCONF_free(cnf); + cnf = NULL; + + if (!atyp) + return -1; + + len = i2d_ASN1_TYPE(atyp, NULL); + if (len <= 0) + goto err; + + if (!BUF_MEM_grow(buf, len)) + goto err; + + p = (unsigned char *) buf->data; + + i2d_ASN1_TYPE(atyp, &p); + + ASN1_TYPE_free(atyp); + return len; + + conferr: + + if (errline > 0) + BIO_printf(bio, "Error on line %ld of config file '%s'\n", + errline, genconf); + else + BIO_printf(bio, "Error loading config file '%s'\n", genconf); + + err: + NCONF_free(cnf); + ASN1_TYPE_free(atyp); + + return -1; + +} diff --git a/apps/openssl/ca.c b/apps/openssl/ca.c new file mode 100644 index 0000000..a93be88 --- /dev/null +++ b/apps/openssl/ca.c @@ -0,0 +1,3042 @@ +/* $OpenBSD: ca.c,v 1.56 2023/07/02 07:08:57 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* The PPKI stuff has been donated by Jeff Barber */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BASE_SECTION "ca" + +#define ENV_DEFAULT_CA "default_ca" + +#define STRING_MASK "string_mask" +#define UTF8_IN "utf8" + +#define ENV_NEW_CERTS_DIR "new_certs_dir" +#define ENV_CERTIFICATE "certificate" +#define ENV_SERIAL "serial" +#define ENV_CRLNUMBER "crlnumber" +#define ENV_PRIVATE_KEY "private_key" +#define ENV_DEFAULT_DAYS "default_days" +#define ENV_DEFAULT_STARTDATE "default_startdate" +#define ENV_DEFAULT_ENDDATE "default_enddate" +#define ENV_DEFAULT_CRL_DAYS "default_crl_days" +#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" +#define ENV_DEFAULT_MD "default_md" +#define ENV_DEFAULT_EMAIL_DN "email_in_dn" +#define ENV_PRESERVE "preserve" +#define ENV_POLICY "policy" +#define ENV_EXTENSIONS "x509_extensions" +#define ENV_CRLEXT "crl_extensions" +#define ENV_MSIE_HACK "msie_hack" +#define ENV_NAMEOPT "name_opt" +#define ENV_CERTOPT "cert_opt" +#define ENV_EXTCOPY "copy_extensions" +#define ENV_UNIQUE_SUBJECT "unique_subject" + +#define ENV_DATABASE "database" + +/* Additional revocation information types */ + +#define REV_NONE 0 /* No addditional information */ +#define REV_CRL_REASON 1 /* Value is CRL reason code */ +#define REV_HOLD 2 /* Value is hold instruction */ +#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ +#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ + +static void lookup_fail(const char *name, const char *tag); +static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, int batch, char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign); +static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, + X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, int batch, char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, unsigned long nameopt, int default_op, + int ext_copy); +static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, + X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, char *ext_sect, CONF *conf, int verbose, + unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); +static int write_new_certificate(BIO *bp, X509 *x, int output_der, + int notext); +static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, int batch, int verbose, X509_REQ *req, + char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, + int default_op, int ext_copy, int selfsign); +static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); +static int get_certificate_status(const char *serial, CA_DB *db); +static int do_updatedb(CA_DB *db); +static int check_time_format(const char *str); +static char *bin2hex(unsigned char *, size_t); +char *make_revocation_str(int rev_type, char *rev_arg); +int make_revoked(X509_REVOKED *rev, const char *str); +int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); + +static CONF *conf = NULL; +static CONF *extconf = NULL; + +static struct { + int batch; + char *certfile; + unsigned long chtype; + char *configfile; + int create_serial; + char *crl_ext; + long crldays; + long crlhours; + long crlsec; + long days; + int dorevoke; + int doupdatedb; + int email_dn; + char *enddate; + char *extensions; + char *extfile; + int gencrl; + char *infile; + char **infiles; + int infiles_num; + char *key; + char *keyfile; + int keyform; + char *md; + int multirdn; + int msie_hack; + int notext; + char *outdir; + char *outfile; + char *passargin; + char *policy; + int preserve; + int req; + char *rev_arg; + int rev_type; + char *serial_status; + char *section; + int selfsign; + STACK_OF(OPENSSL_STRING) *sigopts; + char *spkac_file; + char *ss_cert_file; + char *startdate; + char *subj; + int verbose; +} cfg; + +static int +ca_opt_chtype_utf8(void) +{ + cfg.chtype = MBSTRING_UTF8; + return (0); +} + +static int +ca_opt_crl_ca_compromise(char *arg) +{ + cfg.rev_arg = arg; + cfg.rev_type = REV_CA_COMPROMISE; + return (0); +} + +static int +ca_opt_crl_compromise(char *arg) +{ + cfg.rev_arg = arg; + cfg.rev_type = REV_KEY_COMPROMISE; + return (0); +} + +static int +ca_opt_crl_hold(char *arg) +{ + cfg.rev_arg = arg; + cfg.rev_type = REV_HOLD; + return (0); +} + +static int +ca_opt_crl_reason(char *arg) +{ + cfg.rev_arg = arg; + cfg.rev_type = REV_CRL_REASON; + return (0); +} + +static int +ca_opt_in(char *arg) +{ + cfg.infile = arg; + cfg.req = 1; + return (0); +} + +static int +ca_opt_infiles(int argc, char **argv, int *argsused) +{ + cfg.infiles_num = argc - 1; + if (cfg.infiles_num < 1) + return (1); + cfg.infiles = argv + 1; + cfg.req = 1; + *argsused = argc; + return (0); +} + +static int +ca_opt_revoke(char *arg) +{ + cfg.infile = arg; + cfg.dorevoke = 1; + return (0); +} + +static int +ca_opt_sigopt(char *arg) +{ + if (cfg.sigopts == NULL) + cfg.sigopts = sk_OPENSSL_STRING_new_null(); + if (cfg.sigopts == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg)) + return (1); + return (0); +} + +static int +ca_opt_spkac(char *arg) +{ + cfg.spkac_file = arg; + cfg.req = 1; + return (0); +} + +static int +ca_opt_ss_cert(char *arg) +{ + cfg.ss_cert_file = arg; + cfg.req = 1; + return (0); +} + +static const struct option ca_options[] = { + { + .name = "batch", + .desc = "Operate in batch mode", + .type = OPTION_FLAG, + .opt.flag = &cfg.batch, + }, + { + .name = "cert", + .argname = "file", + .desc = "File containing the CA certificate", + .type = OPTION_ARG, + .opt.arg = &cfg.certfile, + }, + { + .name = "config", + .argname = "file", + .desc = "Specify an alternative configuration file", + .type = OPTION_ARG, + .opt.arg = &cfg.configfile, + }, + { + .name = "create_serial", + .desc = "If reading serial fails, create a new random serial", + .type = OPTION_FLAG, + .opt.flag = &cfg.create_serial, + }, + { + .name = "crl_CA_compromise", + .argname = "time", + .desc = "Set the compromise time and the revocation reason to\n" + "CACompromise", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_crl_ca_compromise, + }, + { + .name = "crl_compromise", + .argname = "time", + .desc = "Set the compromise time and the revocation reason to\n" + "keyCompromise", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_crl_compromise, + }, + { + .name = "crl_hold", + .argname = "instruction", + .desc = "Set the hold instruction and the revocation reason to\n" + "certificateHold", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_crl_hold, + }, + { + .name = "crl_reason", + .argname = "reason", + .desc = "Revocation reason", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_crl_reason, + }, + { + .name = "crldays", + .argname = "days", + .desc = "Number of days before the next CRL is due", + .type = OPTION_ARG_LONG, + .opt.lvalue = &cfg.crldays, + }, + { + .name = "crlexts", + .argname = "section", + .desc = "CRL extension section (override value in config file)", + .type = OPTION_ARG, + .opt.arg = &cfg.crl_ext, + }, + { + .name = "crlhours", + .argname = "hours", + .desc = "Number of hours before the next CRL is due", + .type = OPTION_ARG_LONG, + .opt.lvalue = &cfg.crlhours, + }, + { + .name = "crlsec", + .argname = "seconds", + .desc = "Number of seconds before the next CRL is due", + .type = OPTION_ARG_LONG, + .opt.lvalue = &cfg.crlsec, + }, + { + .name = "days", + .argname = "arg", + .desc = "Number of days to certify the certificate for", + .type = OPTION_ARG_LONG, + .opt.lvalue = &cfg.days, + }, + { + .name = "enddate", + .argname = "YYMMDDHHMMSSZ", + .desc = "Certificate validity notAfter (overrides -days)", + .type = OPTION_ARG, + .opt.arg = &cfg.enddate, + }, + { + .name = "extensions", + .argname = "section", + .desc = "Extension section (override value in config file)", + .type = OPTION_ARG, + .opt.arg = &cfg.extensions, + }, + { + .name = "extfile", + .argname = "file", + .desc = "Configuration file with X509v3 extentions to add", + .type = OPTION_ARG, + .opt.arg = &cfg.extfile, + }, + { + .name = "gencrl", + .desc = "Generate a new CRL", + .type = OPTION_FLAG, + .opt.flag = &cfg.gencrl, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file containing a single certificate request", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_in, + }, + { + .name = "infiles", + .argname = "...", + .desc = "The last argument, certificate requests to process", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = ca_opt_infiles, + }, + { + .name = "key", + .argname = "password", + .desc = "Key to decode the private key if it is encrypted", + .type = OPTION_ARG, + .opt.arg = &cfg.key, + }, + { + .name = "keyfile", + .argname = "file", + .desc = "Private key file", + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Private key file format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "md", + .argname = "alg", + .desc = "Message digest to use", + .type = OPTION_ARG, + .opt.arg = &cfg.md, + }, + { + .name = "msie_hack", + .type = OPTION_FLAG, + .opt.flag = &cfg.msie_hack, + }, + { + .name = "multivalue-rdn", + .desc = "Enable support for multivalued RDNs", + .type = OPTION_FLAG, + .opt.flag = &cfg.multirdn, + }, + { + .name = "name", + .argname = "section", + .desc = "Specifies the configuration file section to use", + .type = OPTION_ARG, + .opt.arg = &cfg.section, + }, + { + .name = "noemailDN", + .desc = "Do not add the EMAIL field to the DN", + .type = OPTION_VALUE, + .opt.value = &cfg.email_dn, + .value = 0, + }, + { + .name = "notext", + .desc = "Do not print the generated certificate", + .type = OPTION_FLAG, + .opt.flag = &cfg.notext, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outdir", + .argname = "directory", + .desc = " Directory to output certificates to", + .type = OPTION_ARG, + .opt.arg = &cfg.outdir, + }, + { + .name = "passin", + .argname = "src", + .desc = "Private key input password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "policy", + .argname = "name", + .desc = "The CA 'policy' to support", + .type = OPTION_ARG, + .opt.arg = &cfg.policy, + }, + { + .name = "preserveDN", + .desc = "Do not re-order the DN", + .type = OPTION_FLAG, + .opt.flag = &cfg.preserve, + }, + { + .name = "revoke", + .argname = "file", + .desc = "Revoke a certificate (given in file)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_revoke, + }, + { + .name = "selfsign", + .desc = "Sign a certificate using the key associated with it", + .type = OPTION_FLAG, + .opt.flag = &cfg.selfsign, + }, + { + .name = "sigopt", + .argname = "nm:v", + .desc = "Signature parameter in nm:v form", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_sigopt, + }, + { + .name = "spkac", + .argname = "file", + .desc = "File contains DN and signed public key and challenge", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_spkac, + }, + { + .name = "ss_cert", + .argname = "file", + .desc = "File contains a self signed certificate to sign", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ca_opt_ss_cert, + }, + { + .name = "startdate", + .argname = "YYMMDDHHMMSSZ", + .desc = "Certificate validity notBefore", + .type = OPTION_ARG, + .opt.arg = &cfg.startdate, + }, + { + .name = "status", + .argname = "serial", + .desc = "Shows certificate status given the serial number", + .type = OPTION_ARG, + .opt.arg = &cfg.serial_status, + }, + { + .name = "subj", + .argname = "arg", + .desc = "Use arg instead of request's subject", + .type = OPTION_ARG, + .opt.arg = &cfg.subj, + }, + { + .name = "updatedb", + .desc = "Updates db for expired certificates", + .type = OPTION_FLAG, + .opt.flag = &cfg.doupdatedb, + }, + { + .name = "utf8", + .desc = "Input characters are in UTF-8 (default ASCII)", + .type = OPTION_FUNC, + .opt.func = ca_opt_chtype_utf8, + }, + { + .name = "verbose", + .desc = "Verbose output during processing", + .type = OPTION_FLAG, + .opt.flag = &cfg.verbose, + }, + { NULL }, +}; + +/* + * Set a certificate time based on user provided input. Make sure + * what we put in the certificate is legit for RFC 5280. Returns + * 0 on success, -1 on an invalid time string. Strings must be + * YYYYMMDDHHMMSSZ for post 2050 dates. YYYYMMDDHHMMSSZ or + * YYMMDDHHMMSSZ is accepted for pre 2050 dates, and fixed up to + * be the correct format in the certificate. + */ +static int +setCertificateTime(ASN1_TIME *x509time, char *timestring) +{ + struct tm tm1; + + if (ASN1_time_parse(timestring, strlen(timestring), &tm1, 0) == -1) + return (-1); + if (!ASN1_TIME_set_tm(x509time, &tm1)) + return (-1); + return 0; +} + +static void +ca_usage(void) +{ + fprintf(stderr, + "usage: ca [-batch] [-cert file] [-config file] [-create_serial]\n" + " [-crl_CA_compromise time] [-crl_compromise time]\n" + " [-crl_hold instruction] [-crl_reason reason] [-crldays days]\n" + " [-crlexts section] [-crlhours hours] [-crlsec seconds]\n" + " [-days arg] [-enddate date] [-extensions section]\n" + " [-extfile file] [-gencrl] [-in file] [-infiles]\n" + " [-key password] [-keyfile file] [-keyform pem | der]\n" + " [-md alg] [-multivalue-rdn] [-name section]\n" + " [-noemailDN] [-notext] [-out file] [-outdir directory]\n" + " [-passin arg] [-policy name] [-preserveDN] [-revoke file]\n" + " [-selfsign] [-sigopt nm:v] [-spkac file] [-ss_cert file]\n" + " [-startdate date] [-status serial] [-subj arg] [-updatedb]\n" + " [-utf8] [-verbose]\n\n"); + options_usage(ca_options); + fprintf(stderr, "\n"); +} + +int +ca_main(int argc, char **argv) +{ + int free_key = 0; + int total = 0; + int total_done = 0; + long errorline = -1; + EVP_PKEY *pkey = NULL; + int output_der = 0; + char *serialfile = NULL; + char *crlnumberfile = NULL; + char *tmp_email_dn = NULL; + BIGNUM *serial = NULL; + BIGNUM *crlnumber = NULL; + unsigned long nameopt = 0, certopt = 0; + int default_op = 1; + int ext_copy = EXT_COPY_NONE; + X509 *x509 = NULL, *x509p = NULL; + X509 *x = NULL; + BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; + char *dbfile = NULL; + CA_DB *db = NULL; + X509_CRL *crl = NULL; + X509_REVOKED *r = NULL; + ASN1_TIME *tmptm = NULL; + ASN1_INTEGER *tmpserial; + char *f; + const char *p; + char *const *pp; + int i, j; + const EVP_MD *dgst = NULL; + STACK_OF(CONF_VALUE) *attribs = NULL; + STACK_OF(X509) *cert_sk = NULL; + char *tofree = NULL; + DB_ATTR db_attr; + int default_nid, rv; + int ret = 1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.email_dn = 1; + cfg.keyform = FORMAT_PEM; + cfg.chtype = MBSTRING_ASC; + cfg.rev_type = REV_NONE; + + conf = NULL; + + if (options_parse(argc, argv, ca_options, NULL, NULL) != 0) { + ca_usage(); + goto err; + } + + /*****************************************************************/ + tofree = NULL; + if (cfg.configfile == NULL) + cfg.configfile = getenv("OPENSSL_CONF"); + if (cfg.configfile == NULL) { + if ((tofree = make_config_name()) == NULL) { + BIO_printf(bio_err, "error making config file name\n"); + goto err; + } + cfg.configfile = tofree; + } + BIO_printf(bio_err, "Using configuration from %s\n", + cfg.configfile); + conf = NCONF_new(NULL); + if (NCONF_load(conf, cfg.configfile, &errorline) <= 0) { + if (errorline <= 0) + BIO_printf(bio_err, + "error loading the config file '%s'\n", + cfg.configfile); + else + BIO_printf(bio_err, + "error on line %ld of config file '%s'\n", + errorline, cfg.configfile); + goto err; + } + free(tofree); + tofree = NULL; + + /* Lets get the config section we are using */ + if (cfg.section == NULL) { + cfg.section = NCONF_get_string(conf, BASE_SECTION, + ENV_DEFAULT_CA); + if (cfg.section == NULL) { + lookup_fail(BASE_SECTION, ENV_DEFAULT_CA); + goto err; + } + } + if (conf != NULL) { + p = NCONF_get_string(conf, NULL, "oid_file"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + BIO *oid_bio; + + oid_bio = BIO_new_file(p, "r"); + if (oid_bio == NULL) { + /* + BIO_printf(bio_err, + "problems opening %s for extra oid's\n", p); + ERR_print_errors(bio_err); + */ + ERR_clear_error(); + } else { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); + } + } + if (!add_oid_section(bio_err, conf)) { + ERR_print_errors(bio_err); + goto err; + } + } + f = NCONF_get_string(conf, cfg.section, STRING_MASK); + if (f == NULL) + ERR_clear_error(); + + if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) { + BIO_printf(bio_err, + "Invalid global string mask setting %s\n", f); + goto err; + } + if (cfg.chtype != MBSTRING_UTF8) { + f = NCONF_get_string(conf, cfg.section, UTF8_IN); + if (f == NULL) + ERR_clear_error(); + else if (strcmp(f, "yes") == 0) + cfg.chtype = MBSTRING_UTF8; + } + db_attr.unique_subject = 1; + p = NCONF_get_string(conf, cfg.section, ENV_UNIQUE_SUBJECT); + if (p != NULL) { + db_attr.unique_subject = parse_yesno(p, 1); + } else + ERR_clear_error(); + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + Sout = BIO_new(BIO_s_file()); + Cout = BIO_new(BIO_s_file()); + if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) { + ERR_print_errors(bio_err); + goto err; + } + /*****************************************************************/ + /* report status of cert with serial number given on command line */ + if (cfg.serial_status) { + if ((dbfile = NCONF_get_string(conf, cfg.section, + ENV_DATABASE)) == NULL) { + lookup_fail(cfg.section, ENV_DATABASE); + goto err; + } + db = load_index(dbfile, &db_attr); + if (db == NULL) + goto err; + + if (!index_index(db)) + goto err; + + if (get_certificate_status(cfg.serial_status, db) != 1) + BIO_printf(bio_err, "Error verifying serial %s!\n", + cfg.serial_status); + goto err; + } + /*****************************************************************/ + /* we definitely need a private key, so let's get it */ + + if ((cfg.keyfile == NULL) && + ((cfg.keyfile = NCONF_get_string(conf, cfg.section, + ENV_PRIVATE_KEY)) == NULL)) { + lookup_fail(cfg.section, ENV_PRIVATE_KEY); + goto err; + } + if (cfg.key == NULL) { + free_key = 1; + if (!app_passwd(bio_err, cfg.passargin, NULL, + &cfg.key, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto err; + } + } + pkey = load_key(bio_err, cfg.keyfile, cfg.keyform, 0, + cfg.key, "CA private key"); + if (cfg.key != NULL) + explicit_bzero(cfg.key, strlen(cfg.key)); + if (pkey == NULL) { + /* load_key() has already printed an appropriate message */ + goto err; + } + /*****************************************************************/ + /* we need a certificate */ + if (!cfg.selfsign || cfg.spkac_file != NULL || + cfg.ss_cert_file != NULL || cfg.gencrl) { + if ((cfg.certfile == NULL) && + ((cfg.certfile = NCONF_get_string(conf, + cfg.section, ENV_CERTIFICATE)) == NULL)) { + lookup_fail(cfg.section, ENV_CERTIFICATE); + goto err; + } + x509 = load_cert(bio_err, cfg.certfile, FORMAT_PEM, NULL, + "CA certificate"); + if (x509 == NULL) + goto err; + + if (!X509_check_private_key(x509, pkey)) { + BIO_printf(bio_err, + "CA certificate and CA private key do not match\n"); + goto err; + } + } + if (!cfg.selfsign) + x509p = x509; + + f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE); + if (f == NULL) + ERR_clear_error(); + if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + cfg.preserve = 1; + f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK); + if (f == NULL) + ERR_clear_error(); + if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) + cfg.msie_hack = 1; + + f = NCONF_get_string(conf, cfg.section, ENV_NAMEOPT); + + if (f != NULL) { + if (!set_name_ex(&nameopt, f)) { + BIO_printf(bio_err, + "Invalid name options: \"%s\"\n", f); + goto err; + } + default_op = 0; + } else + ERR_clear_error(); + + f = NCONF_get_string(conf, cfg.section, ENV_CERTOPT); + + if (f != NULL) { + if (!set_cert_ex(&certopt, f)) { + BIO_printf(bio_err, + "Invalid certificate options: \"%s\"\n", f); + goto err; + } + default_op = 0; + } else + ERR_clear_error(); + + f = NCONF_get_string(conf, cfg.section, ENV_EXTCOPY); + + if (f != NULL) { + if (!set_ext_copy(&ext_copy, f)) { + BIO_printf(bio_err, + "Invalid extension copy option: \"%s\"\n", f); + goto err; + } + } else + ERR_clear_error(); + + /*****************************************************************/ + /* lookup where to write new certificates */ + if (cfg.outdir == NULL && cfg.req) { + if ((cfg.outdir = NCONF_get_string(conf, + cfg.section, ENV_NEW_CERTS_DIR)) == NULL) { + BIO_printf(bio_err, "output directory %s not defined\n", + ENV_NEW_CERTS_DIR); + goto err; + } + } + /*****************************************************************/ + /* we need to load the database file */ + if ((dbfile = NCONF_get_string(conf, cfg.section, + ENV_DATABASE)) == NULL) { + lookup_fail(cfg.section, ENV_DATABASE); + goto err; + } + db = load_index(dbfile, &db_attr); + if (db == NULL) + goto err; + + /* Lets check some fields */ + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + if ((pp[DB_type][0] != DB_TYPE_REV) && + (pp[DB_rev_date][0] != '\0')) { + BIO_printf(bio_err, + "entry %d: not revoked yet, but has a revocation date\n", + i + 1); + goto err; + } + if ((pp[DB_type][0] == DB_TYPE_REV) && + !make_revoked(NULL, pp[DB_rev_date])) { + BIO_printf(bio_err, " in entry %d\n", i + 1); + goto err; + } + if (!check_time_format((char *) pp[DB_exp_date])) { + BIO_printf(bio_err, "entry %d: invalid expiry date\n", + i + 1); + goto err; + } + p = pp[DB_serial]; + j = strlen(p); + if (*p == '-') { + p++; + j--; + } + if ((j & 1) || (j < 2)) { + BIO_printf(bio_err, + "entry %d: bad serial number length (%d)\n", + i + 1, j); + goto err; + } + while (*p) { + if (!(((*p >= '0') && (*p <= '9')) || + ((*p >= 'A') && (*p <= 'F')) || + ((*p >= 'a') && (*p <= 'f')))) { + BIO_printf(bio_err, + "entry %d: bad serial number characters, char pos %ld, char is '%c'\n", + i + 1, (long) (p - pp[DB_serial]), *p); + goto err; + } + p++; + } + } + if (cfg.verbose) { + BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); + TXT_DB_write(out, db->db); + BIO_printf(bio_err, "%d entries loaded from the database\n", + sk_OPENSSL_PSTRING_num(db->db->data)); + BIO_printf(bio_err, "generating index\n"); + } + if (!index_index(db)) + goto err; + + /*****************************************************************/ + /* Update the db file for expired certificates */ + if (cfg.doupdatedb) { + if (cfg.verbose) + BIO_printf(bio_err, "Updating %s ...\n", dbfile); + + i = do_updatedb(db); + if (i == -1) { + BIO_printf(bio_err, "Malloc failure\n"); + goto err; + } else if (i == 0) { + if (cfg.verbose) + BIO_printf(bio_err, + "No entries found to mark expired\n"); + } else { + if (!save_index(dbfile, "new", db)) + goto err; + + if (!rotate_index(dbfile, "new", "old")) + goto err; + + if (cfg.verbose) + BIO_printf(bio_err, + "Done. %d entries marked as expired\n", i); + } + } + /*****************************************************************/ + /* Read extentions config file */ + if (cfg.extfile != NULL) { + extconf = NCONF_new(NULL); + if (NCONF_load(extconf, cfg.extfile, &errorline) <= 0) { + if (errorline <= 0) + BIO_printf(bio_err, + "ERROR: loading the config file '%s'\n", + cfg.extfile); + else + BIO_printf(bio_err, + "ERROR: on line %ld of config file '%s'\n", + errorline, cfg.extfile); + ret = 1; + goto err; + } + if (cfg.verbose) + BIO_printf(bio_err, + "Successfully loaded extensions file %s\n", + cfg.extfile); + + /* We can have sections in the ext file */ + if (cfg.extensions == NULL && + (cfg.extensions = NCONF_get_string(extconf, "default", + "extensions")) == NULL) + cfg.extensions = "default"; + } + /*****************************************************************/ + if (cfg.req || cfg.gencrl) { + if (cfg.outfile != NULL) { + if (BIO_write_filename(Sout, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto err; + } + } else { + BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT); + } + } + + rv = EVP_PKEY_get_default_digest_nid(pkey, &default_nid); + if (rv == 2 && default_nid == NID_undef) { + /* The digest is required to be EVP_md_null() (EdDSA). */ + dgst = EVP_md_null(); + } else { + /* Ignore rv unless we need a valid default_nid. */ + if (cfg.md == NULL) + cfg.md = NCONF_get_string(conf, cfg.section, + ENV_DEFAULT_MD); + if (cfg.md == NULL) { + lookup_fail(cfg.section, ENV_DEFAULT_MD); + goto err; + } + if (strcmp(cfg.md, "default") == 0) { + if (rv <= 0) { + BIO_puts(bio_err, "no default digest\n"); + goto err; + } + cfg.md = (char *)OBJ_nid2sn(default_nid); + } + if (cfg.md == NULL) + goto err; + if ((dgst = EVP_get_digestbyname(cfg.md)) == NULL) { + BIO_printf(bio_err, "%s is an unsupported " + "message digest type\n", cfg.md); + goto err; + } + } + if (cfg.req) { + if ((cfg.email_dn == 1) && + ((tmp_email_dn = NCONF_get_string(conf, cfg.section, + ENV_DEFAULT_EMAIL_DN)) != NULL)) { + if (strcmp(tmp_email_dn, "no") == 0) + cfg.email_dn = 0; + } + if (cfg.verbose) + BIO_printf(bio_err, "message digest is %s\n", + OBJ_nid2ln(EVP_MD_type(dgst))); + if ((cfg.policy == NULL) && + ((cfg.policy = NCONF_get_string(conf, + cfg.section, ENV_POLICY)) == NULL)) { + lookup_fail(cfg.section, ENV_POLICY); + goto err; + } + if (cfg.verbose) + BIO_printf(bio_err, "policy is %s\n", cfg.policy); + + if ((serialfile = NCONF_get_string(conf, cfg.section, + ENV_SERIAL)) == NULL) { + lookup_fail(cfg.section, ENV_SERIAL); + goto err; + } + if (extconf == NULL) { + /* + * no '-extfile' option, so we look for extensions in + * the main configuration file + */ + if (cfg.extensions == NULL) { + cfg.extensions = NCONF_get_string(conf, + cfg.section, ENV_EXTENSIONS); + if (cfg.extensions == NULL) + ERR_clear_error(); + } + if (cfg.extensions != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx, + cfg.extensions, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", + cfg.extensions); + ret = 1; + goto err; + } + } + } + if (cfg.startdate == NULL) { + cfg.startdate = NCONF_get_string(conf, + cfg.section, ENV_DEFAULT_STARTDATE); + if (cfg.startdate == NULL) + ERR_clear_error(); + } + if (cfg.startdate == NULL) + cfg.startdate = "today"; + + if (cfg.enddate == NULL) { + cfg.enddate = NCONF_get_string(conf, + cfg.section, ENV_DEFAULT_ENDDATE); + if (cfg.enddate == NULL) + ERR_clear_error(); + } + if (cfg.days == 0 && cfg.enddate == NULL) { + if (!NCONF_get_number(conf, cfg.section, + ENV_DEFAULT_DAYS, &cfg.days)) + cfg.days = 0; + } + if (cfg.enddate == NULL && cfg.days == 0) { + BIO_printf(bio_err, + "cannot lookup how many days to certify for\n"); + goto err; + } + if ((serial = load_serial(serialfile, cfg.create_serial, + NULL)) == NULL) { + BIO_printf(bio_err, + "error while loading serial number\n"); + goto err; + } + if (cfg.verbose) { + if (BN_is_zero(serial)) + BIO_printf(bio_err, + "next serial number is 00\n"); + else { + if ((f = BN_bn2hex(serial)) == NULL) + goto err; + BIO_printf(bio_err, + "next serial number is %s\n", f); + free(f); + } + } + if ((attribs = NCONF_get_section(conf, cfg.policy)) == + NULL) { + BIO_printf(bio_err, "unable to find 'section' for %s\n", + cfg.policy); + goto err; + } + if ((cert_sk = sk_X509_new_null()) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + if (cfg.spkac_file != NULL) { + total++; + j = certify_spkac(&x, cfg.spkac_file, pkey, x509, + dgst, cfg.sigopts, attribs, db, serial, + cfg.subj, cfg.chtype, + cfg.multirdn, cfg.email_dn, + cfg.startdate, cfg.enddate, + cfg.days, cfg.extensions, conf, + cfg.verbose, certopt, nameopt, default_op, + ext_copy); + if (j < 0) + goto err; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto err; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, + "Memory allocation failure\n"); + goto err; + } + if (cfg.outfile != NULL) { + output_der = 1; + cfg.batch = 1; + } + } + } + if (cfg.ss_cert_file != NULL) { + total++; + j = certify_cert(&x, cfg.ss_cert_file, pkey, x509, + dgst, cfg.sigopts, attribs, db, serial, + cfg.subj, cfg.chtype, + cfg.multirdn, cfg.email_dn, + cfg.startdate, cfg.enddate, + cfg.days, cfg.batch, + cfg.extensions, conf, cfg.verbose, + certopt, nameopt, default_op, ext_copy); + if (j < 0) + goto err; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto err; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, + "Memory allocation failure\n"); + goto err; + } + } + } + if (cfg.infile != NULL) { + total++; + j = certify(&x, cfg.infile, pkey, x509p, dgst, + cfg.sigopts, attribs, db, serial, + cfg.subj, cfg.chtype, + cfg.multirdn, cfg.email_dn, + cfg.startdate, cfg.enddate, + cfg.days, cfg.batch, + cfg.extensions, conf, cfg.verbose, + certopt, nameopt, default_op, ext_copy, + cfg.selfsign); + if (j < 0) + goto err; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto err; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, + "Memory allocation failure\n"); + goto err; + } + } + } + for (i = 0; i < cfg.infiles_num; i++) { + total++; + j = certify(&x, cfg.infiles[i], pkey, x509p, dgst, + cfg.sigopts, attribs, db, serial, + cfg.subj, cfg.chtype, + cfg.multirdn, cfg.email_dn, + cfg.startdate, cfg.enddate, + cfg.days, cfg.batch, + cfg.extensions, conf, cfg.verbose, + certopt, nameopt, default_op, ext_copy, + cfg.selfsign); + if (j < 0) + goto err; + if (j > 0) { + total_done++; + BIO_printf(bio_err, "\n"); + if (!BN_add_word(serial, 1)) + goto err; + if (!sk_X509_push(cert_sk, x)) { + BIO_printf(bio_err, + "Memory allocation failure\n"); + goto err; + } + } + } + /* + * we have a stack of newly certified certificates and a data + * base and serial number that need updating + */ + + if (sk_X509_num(cert_sk) > 0) { + if (!cfg.batch) { + char answer[10]; + + BIO_printf(bio_err, + "\n%d out of %d certificate requests certified, commit? [y/n]", + total_done, total); + (void) BIO_flush(bio_err); + if (fgets(answer, sizeof answer - 1, stdin) == + NULL) { + BIO_printf(bio_err, + "CERTIFICATION CANCELED: I/O error\n"); + ret = 0; + goto err; + } + if ((answer[0] != 'y') && (answer[0] != 'Y')) { + BIO_printf(bio_err, + "CERTIFICATION CANCELED\n"); + ret = 0; + goto err; + } + } + BIO_printf(bio_err, + "Write out database with %d new entries\n", + sk_X509_num(cert_sk)); + + if (!save_serial(serialfile, "new", serial, NULL)) + goto err; + + if (!save_index(dbfile, "new", db)) + goto err; + } + if (cfg.verbose) + BIO_printf(bio_err, "writing new certificates\n"); + for (i = 0; i < sk_X509_num(cert_sk); i++) { + ASN1_INTEGER *serialNumber; + int k; + char *serialstr; + unsigned char *data; + char pempath[PATH_MAX]; + + x = sk_X509_value(cert_sk, i); + + serialNumber = X509_get_serialNumber(x); + j = ASN1_STRING_length(serialNumber); + data = ASN1_STRING_data(serialNumber); + + if (j > 0) + serialstr = bin2hex(data, j); + else + serialstr = strdup("00"); + if (serialstr != NULL) { + k = snprintf(pempath, sizeof(pempath), + "%s/%s.pem", cfg.outdir, serialstr); + free(serialstr); + if (k < 0 || k >= sizeof(pempath)) { + BIO_printf(bio_err, + "certificate file name too long\n"); + goto err; + } + } else { + BIO_printf(bio_err, + "memory allocation failed\n"); + goto err; + } + if (cfg.verbose) + BIO_printf(bio_err, "writing %s\n", pempath); + + if (BIO_write_filename(Cout, pempath) <= 0) { + perror(pempath); + goto err; + } + if (!write_new_certificate(Cout, x, 0, + cfg.notext)) + goto err; + if (!write_new_certificate(Sout, x, output_der, + cfg.notext)) + goto err; + } + + if (sk_X509_num(cert_sk)) { + /* Rename the database and the serial file */ + if (!rotate_serial(serialfile, "new", "old")) + goto err; + + if (!rotate_index(dbfile, "new", "old")) + goto err; + + BIO_printf(bio_err, "Data Base Updated\n"); + } + } + /*****************************************************************/ + if (cfg.gencrl) { + int crl_v2 = 0; + if (cfg.crl_ext == NULL) { + cfg.crl_ext = NCONF_get_string(conf, + cfg.section, ENV_CRLEXT); + if (cfg.crl_ext == NULL) + ERR_clear_error(); + } + if (cfg.crl_ext != NULL) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, conf); + if (!X509V3_EXT_add_nconf(conf, &ctx, cfg.crl_ext, + NULL)) { + BIO_printf(bio_err, + "Error Loading CRL extension section %s\n", + cfg.crl_ext); + ret = 1; + goto err; + } + } + if ((crlnumberfile = NCONF_get_string(conf, cfg.section, + ENV_CRLNUMBER)) != NULL) + if ((crlnumber = load_serial(crlnumberfile, 0, + NULL)) == NULL) { + BIO_printf(bio_err, + "error while loading CRL number\n"); + goto err; + } + if (!cfg.crldays && !cfg.crlhours && + !cfg.crlsec) { + if (!NCONF_get_number(conf, cfg.section, + ENV_DEFAULT_CRL_DAYS, &cfg.crldays)) + cfg.crldays = 0; + if (!NCONF_get_number(conf, cfg.section, + ENV_DEFAULT_CRL_HOURS, &cfg.crlhours)) + cfg.crlhours = 0; + ERR_clear_error(); + } + if ((cfg.crldays == 0) && (cfg.crlhours == 0) && + (cfg.crlsec == 0)) { + BIO_printf(bio_err, + "cannot lookup how long until the next CRL is issued\n"); + goto err; + } + if (cfg.verbose) + BIO_printf(bio_err, "making CRL\n"); + if ((crl = X509_CRL_new()) == NULL) + goto err; + if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) + goto err; + + if ((tmptm = X509_gmtime_adj(NULL, 0)) == NULL) + goto err; + if (!X509_CRL_set_lastUpdate(crl, tmptm)) + goto err; + if (X509_time_adj_ex(tmptm, cfg.crldays, + cfg.crlhours * 60 * 60 + cfg.crlsec, NULL) == + NULL) { + BIO_puts(bio_err, "error setting CRL nextUpdate\n"); + goto err; + } + if (!X509_CRL_set_nextUpdate(crl, tmptm)) + goto err; + ASN1_TIME_free(tmptm); + tmptm = NULL; + + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + pp = sk_OPENSSL_PSTRING_value(db->db->data, i); + if (pp[DB_type][0] == DB_TYPE_REV) { + if ((r = X509_REVOKED_new()) == NULL) + goto err; + j = make_revoked(r, pp[DB_rev_date]); + if (!j) + goto err; + if (j == 2) + crl_v2 = 1; + if (!BN_hex2bn(&serial, pp[DB_serial])) + goto err; + tmpserial = BN_to_ASN1_INTEGER(serial, NULL); + BN_free(serial); + serial = NULL; + if (tmpserial == NULL) + goto err; + if (!X509_REVOKED_set_serialNumber(r, tmpserial)) { + ASN1_INTEGER_free(tmpserial); + goto err; + } + ASN1_INTEGER_free(tmpserial); + if (!X509_CRL_add0_revoked(crl, r)) + goto err; + r = NULL; + } + } + + /* + * sort the data so it will be written in serial number order + */ + X509_CRL_sort(crl); + + /* we now have a CRL */ + if (cfg.verbose) + BIO_printf(bio_err, "signing CRL\n"); + + /* Add any extensions asked for */ + + if (cfg.crl_ext != NULL || crlnumberfile != NULL) { + X509V3_CTX crlctx; + X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); + X509V3_set_nconf(&crlctx, conf); + + if (cfg.crl_ext != NULL) + if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, + cfg.crl_ext, crl)) + goto err; + if (crlnumberfile != NULL) { + tmpserial = BN_to_ASN1_INTEGER(crlnumber, NULL); + if (tmpserial == NULL) + goto err; + if (!X509_CRL_add1_ext_i2d(crl, NID_crl_number, + tmpserial, 0, 0)) { + ASN1_INTEGER_free(tmpserial); + goto err; + } + ASN1_INTEGER_free(tmpserial); + crl_v2 = 1; + if (!BN_add_word(crlnumber, 1)) + goto err; + } + } + if (cfg.crl_ext != NULL || crl_v2) { + if (!X509_CRL_set_version(crl, 1)) + goto err; /* version 2 CRL */ + } + if (crlnumberfile != NULL) /* we have a CRL number that + * need updating */ + if (!save_serial(crlnumberfile, "new", crlnumber, NULL)) + goto err; + + BN_free(crlnumber); + crlnumber = NULL; + + if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, + cfg.sigopts)) + goto err; + + if (!PEM_write_bio_X509_CRL(Sout, crl)) + goto err; + + if (crlnumberfile != NULL) /* Rename the crlnumber file */ + if (!rotate_serial(crlnumberfile, "new", "old")) + goto err; + + } + /*****************************************************************/ + if (cfg.dorevoke) { + if (cfg.infile == NULL) { + BIO_printf(bio_err, "no input files\n"); + goto err; + } else { + X509 *revcert; + revcert = load_cert(bio_err, cfg.infile, + FORMAT_PEM, NULL, cfg.infile); + if (revcert == NULL) + goto err; + j = do_revoke(revcert, db, cfg.rev_type, + cfg.rev_arg); + if (j <= 0) + goto err; + X509_free(revcert); + + if (!save_index(dbfile, "new", db)) + goto err; + + if (!rotate_index(dbfile, "new", "old")) + goto err; + + BIO_printf(bio_err, "Data Base Updated\n"); + } + } + /*****************************************************************/ + ret = 0; + + err: + free(tofree); + + BIO_free_all(Cout); + BIO_free_all(Sout); + BIO_free_all(out); + BIO_free_all(in); + + sk_X509_pop_free(cert_sk, X509_free); + + if (ret) + ERR_print_errors(bio_err); + if (free_key) + free(cfg.key); + BN_free(serial); + BN_free(crlnumber); + free_index(db); + sk_OPENSSL_STRING_free(cfg.sigopts); + EVP_PKEY_free(pkey); + X509_free(x509); + X509_CRL_free(crl); + X509_REVOKED_free(r); + ASN1_TIME_free(tmptm); + NCONF_free(conf); + NCONF_free(extconf); + OBJ_cleanup(); + + return (ret); +} + +static void +lookup_fail(const char *name, const char *tag) +{ + BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag); +} + +static int +certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, int batch, char *ext_sect, CONF *lconf, + int verbose, unsigned long certopt, unsigned long nameopt, int default_op, + int ext_copy, int selfsign) +{ + X509_REQ *req = NULL; + BIO *in = NULL; + EVP_PKEY *pktmp = NULL; + int ok = -1, i; + + in = BIO_new(BIO_s_file()); + + if (BIO_read_filename(in, infile) <= 0) { + perror(infile); + goto err; + } + if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) { + BIO_printf(bio_err, "Error reading certificate request in %s\n", + infile); + goto err; + } + if (verbose) { + if (!X509_REQ_print(bio_err, req)) + goto err; + } + + BIO_printf(bio_err, "Check that the request matches the signature\n"); + + if (selfsign && !X509_REQ_check_private_key(req, pkey)) { + BIO_printf(bio_err, + "Certificate request and CA private key do not match\n"); + ok = 0; + goto err; + } + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "error unpacking public key\n"); + goto err; + } + i = X509_REQ_verify(req, pktmp); + if (i < 0) { + ok = 0; + BIO_printf(bio_err, "Signature verification problems....\n"); + goto err; + } + if (i == 0) { + ok = 0; + BIO_printf(bio_err, + "Signature did not match the certificate request\n"); + goto err; + } else + BIO_printf(bio_err, "Signature ok\n"); + + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, + subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, + verbose, req, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, selfsign); + + err: + X509_REQ_free(req); + BIO_free(in); + + return (ok); +} + +static int +certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, int batch, char *ext_sect, CONF *lconf, + int verbose, unsigned long certopt, unsigned long nameopt, int default_op, + int ext_copy) +{ + X509 *req = NULL; + X509_REQ *rreq = NULL; + EVP_PKEY *pktmp = NULL; + int ok = -1, i; + + if ((req = load_cert(bio_err, infile, FORMAT_PEM, NULL, + infile)) == NULL) + goto err; + if (verbose) { + if (!X509_print(bio_err, req)) + goto err; + } + + BIO_printf(bio_err, "Check that the request matches the signature\n"); + + if ((pktmp = X509_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "error unpacking public key\n"); + goto err; + } + i = X509_verify(req, pktmp); + if (i < 0) { + ok = 0; + BIO_printf(bio_err, "Signature verification problems....\n"); + goto err; + } + if (i == 0) { + ok = 0; + BIO_printf(bio_err, + "Signature did not match the certificate\n"); + goto err; + } else + BIO_printf(bio_err, "Signature ok\n"); + + if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL) + goto err; + + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, + subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, + verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, 0); + + err: + X509_REQ_free(rreq); + X509_free(req); + + return (ok); +} + +static int +do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, + STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, + CA_DB *db, BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, + int email_dn, char *startdate, char *enddate, long days, int batch, + int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, + unsigned long certopt, unsigned long nameopt, int default_op, + int ext_copy, int selfsign) +{ + X509_NAME *name = NULL, *CAname = NULL; + X509_NAME *subject = NULL, *dn_subject = NULL; + ASN1_UTCTIME *tm; + ASN1_STRING *str, *str2; + ASN1_OBJECT *obj; + X509 *ret = NULL; + X509_NAME_ENTRY *ne; + X509_NAME_ENTRY *tne, *push; + EVP_PKEY *pktmp; + int ok = -1, i, j, last, nid; + const char *p; + CONF_VALUE *cv; + OPENSSL_STRING row[DB_NUMBER]; + OPENSSL_STRING *irow = NULL; + OPENSSL_STRING *rrow = NULL; + const STACK_OF(X509_EXTENSION) *exts; + + *xret = NULL; + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + + if (subj != NULL) { + X509_NAME *n = parse_name(subj, chtype, multirdn); + + if (n == NULL) { + ERR_print_errors(bio_err); + goto err; + } + if (!X509_REQ_set_subject_name(req, n)) { + X509_NAME_free(n); + goto err; + } + X509_NAME_free(n); + } + if (default_op) + BIO_printf(bio_err, + "The Subject's Distinguished Name is as follows\n"); + + name = X509_REQ_get_subject_name(req); + for (i = 0; i < X509_NAME_entry_count(name); i++) { + ne = X509_NAME_get_entry(name, i); + if (ne == NULL) + goto err; + str = X509_NAME_ENTRY_get_data(ne); + if (str == NULL) + goto err; + obj = X509_NAME_ENTRY_get_object(ne); + if (obj == NULL) + goto err; + + if (cfg.msie_hack) { + /* assume all type should be strings */ + nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); + if (nid == NID_undef) + goto err; + + if (str->type == V_ASN1_UNIVERSALSTRING) + ASN1_UNIVERSALSTRING_to_string(str); + + if ((str->type == V_ASN1_IA5STRING) && + (nid != NID_pkcs9_emailAddress)) + str->type = V_ASN1_T61STRING; + + if ((nid == NID_pkcs9_emailAddress) && + (str->type == V_ASN1_PRINTABLESTRING)) + str->type = V_ASN1_IA5STRING; + } + /* If no EMAIL is wanted in the subject */ + if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) + continue; + + /* check some things */ + if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && + (str->type != V_ASN1_IA5STRING)) { + BIO_printf(bio_err, + "\nemailAddress type needs to be of type IA5STRING\n"); + goto err; + } + if ((str->type != V_ASN1_BMPSTRING) && + (str->type != V_ASN1_UTF8STRING)) { + j = ASN1_PRINTABLE_type(str->data, str->length); + if (((j == V_ASN1_T61STRING) && + (str->type != V_ASN1_T61STRING)) || + ((j == V_ASN1_IA5STRING) && + (str->type == V_ASN1_PRINTABLESTRING))) { + BIO_printf(bio_err, + "\nThe string contains characters that are illegal for the ASN.1 type\n"); + goto err; + } + } + if (default_op) + old_entry_print(bio_err, obj, str); + } + + /* Ok, now we check the 'policy' stuff. */ + if ((subject = X509_NAME_new()) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + /* take a copy of the issuer name before we mess with it. */ + if (selfsign) + CAname = X509_NAME_dup(name); + else + CAname = X509_NAME_dup(X509_get_subject_name(x509)); + if (CAname == NULL) + goto err; + str = str2 = NULL; + + for (i = 0; i < sk_CONF_VALUE_num(policy); i++) { + cv = sk_CONF_VALUE_value(policy, i); /* get the object id */ + if ((j = OBJ_txt2nid(cv->name)) == NID_undef) { + BIO_printf(bio_err, + "%s:unknown object type in 'policy' configuration\n", + cv->name); + goto err; + } + obj = OBJ_nid2obj(j); + if (obj == NULL) + goto err; + + last = -1; + for (;;) { + /* lookup the object in the supplied name list */ + j = X509_NAME_get_index_by_OBJ(name, obj, last); + if (j < 0) { + if (last != -1) + break; + tne = NULL; + } else { + tne = X509_NAME_get_entry(name, j); + if (tne == NULL) + goto err; + } + last = j; + + /* depending on the 'policy', decide what to do. */ + push = NULL; + if (strcmp(cv->value, "optional") == 0) { + if (tne != NULL) + push = tne; + } else if (strcmp(cv->value, "supplied") == 0) { + if (tne == NULL) { + BIO_printf(bio_err, + "The %s field needed to be supplied and was missing\n", + cv->name); + goto err; + } else + push = tne; + } else if (strcmp(cv->value, "match") == 0) { + int last2; + + if (tne == NULL) { + BIO_printf(bio_err, + "The mandatory %s field was missing\n", + cv->name); + goto err; + } + last2 = -1; + + again2: + j = X509_NAME_get_index_by_OBJ(CAname, obj, + last2); + if ((j < 0) && (last2 == -1)) { + BIO_printf(bio_err, + "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n", + cv->name); + goto err; + } + if (j >= 0) { + push = X509_NAME_get_entry(CAname, j); + if (push == NULL) + goto err; + str = X509_NAME_ENTRY_get_data(tne); + if (str == NULL) + goto err; + str2 = X509_NAME_ENTRY_get_data(push); + if (str2 == NULL) + goto err; + last2 = j; + if (ASN1_STRING_cmp(str, str2) != 0) + goto again2; + } + if (j < 0) { + BIO_printf(bio_err, + "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n", + cv->name, ((str2 == NULL) ? + "NULL" : (char *) str2->data), + ((str == NULL) ? + "NULL" : (char *) str->data)); + goto err; + } + } else { + BIO_printf(bio_err, + "%s:invalid type in 'policy' configuration\n", + cv->value); + goto err; + } + + if (push != NULL) { + if (!X509_NAME_add_entry(subject, push, + -1, 0)) { + X509_NAME_ENTRY_free(push); + BIO_printf(bio_err, + "Memory allocation failure\n"); + goto err; + } + } + if (j < 0) + break; + } + } + + if (cfg.preserve) { + X509_NAME_free(subject); + /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ + subject = X509_NAME_dup(name); + if (subject == NULL) + goto err; + } + + /* We are now totally happy, lets make and sign the certificate */ + if (verbose) + BIO_printf(bio_err, + "Everything appears to be ok, creating and signing the certificate\n"); + + if ((ret = X509_new()) == NULL) + goto err; + +#ifdef X509_V3 + /* Make it an X509 v3 certificate. */ + if (!X509_set_version(ret, 2)) + goto err; +#endif + if (X509_get_serialNumber(ret) == NULL) + goto err; + if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) + goto err; + if (selfsign) { + if (!X509_set_issuer_name(ret, subject)) + goto err; + } else { + if (!X509_set_issuer_name(ret, X509_get_subject_name(x509))) + goto err; + } + + if (strcmp(startdate, "today") == 0) { + if (X509_gmtime_adj(X509_get_notBefore(ret), 0) == NULL) + goto err; + } else if (setCertificateTime(X509_get_notBefore(ret), startdate) == -1) { + BIO_printf(bio_err, "Invalid start date %s\n", startdate); + goto err; + } + + if (enddate == NULL) { + if (X509_time_adj_ex(X509_get_notAfter(ret), days, 0, + NULL) == NULL) + goto err; + } else if (setCertificateTime(X509_get_notAfter(ret), enddate) == -1) { + BIO_printf(bio_err, "Invalid end date %s\n", enddate); + goto err; + } + + if (!X509_set_subject_name(ret, subject)) + goto err; + + if ((pktmp = X509_REQ_get0_pubkey(req)) == NULL) + goto err; + + if (!X509_set_pubkey(ret, pktmp)) + goto err; + + /* Lets add the extensions, if there are any */ + if (ext_sect != NULL) { + X509V3_CTX ctx; + + /* Initialize the context structure */ + if (selfsign) + X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); + else + X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); + + if (extconf != NULL) { + if (verbose) + BIO_printf(bio_err, + "Extra configuration file found\n"); + + /* Use the extconf configuration db LHASH */ + X509V3_set_nconf(&ctx, extconf); + + /* Test the structure (needed?) */ + /* X509V3_set_ctx_test(&ctx); */ + + /* Adds exts contained in the configuration file */ + if (!X509V3_EXT_add_nconf(extconf, &ctx, + ext_sect, ret)) { + BIO_printf(bio_err, + "ERROR: adding extensions in section %s\n", + ext_sect); + ERR_print_errors(bio_err); + goto err; + } + if (verbose) + BIO_printf(bio_err, + "Successfully added extensions from file.\n"); + } else if (ext_sect != NULL) { + /* We found extensions to be set from config file */ + X509V3_set_nconf(&ctx, lconf); + + if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) { + BIO_printf(bio_err, + "ERROR: adding extensions in section %s\n", + ext_sect); + ERR_print_errors(bio_err); + goto err; + } + if (verbose) + BIO_printf(bio_err, + "Successfully added extensions from config\n"); + } + } + + /* Copy extensions from request (if any) */ + if (!copy_extensions(ret, req, ext_copy)) { + BIO_printf(bio_err, "ERROR: adding extensions from request\n"); + ERR_print_errors(bio_err); + goto err; + } + + exts = X509_get0_extensions(ret); + if (exts != NULL && sk_X509_EXTENSION_num(exts) > 0) { + /* Make it an X509 v3 certificate. */ + if (!X509_set_version(ret, 2)) + goto err; + } + + if (verbose) + BIO_printf(bio_err, + "The subject name appears to be ok, checking data base for clashes\n"); + + /* Build the correct Subject if no email is wanted in the subject */ + if (!email_dn) { + X509_NAME_ENTRY *tmpne; + /* + * Its best to dup the subject DN and then delete any email + * addresses because this retains its structure. + */ + if ((dn_subject = X509_NAME_dup(subject)) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + while ((i = X509_NAME_get_index_by_NID(dn_subject, + NID_pkcs9_emailAddress, -1)) >= 0) { + tmpne = X509_NAME_get_entry(dn_subject, i); + if (tmpne == NULL) + goto err; + if (X509_NAME_delete_entry(dn_subject, i) == NULL) { + X509_NAME_ENTRY_free(tmpne); + goto err; + } + X509_NAME_ENTRY_free(tmpne); + } + + if (!X509_set_subject_name(ret, dn_subject)) + goto err; + + X509_NAME_free(dn_subject); + dn_subject = NULL; + } + + row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0); + if (row[DB_name] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + + if (BN_is_zero(serial)) + row[DB_serial] = strdup("00"); + else + row[DB_serial] = BN_bn2hex(serial); + if (row[DB_serial] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + + if (row[DB_name][0] == '\0') { + /* + * An empty subject! We'll use the serial number instead. If + * unique_subject is in use then we don't want different + * entries with empty subjects matching each other. + */ + free(row[DB_name]); + row[DB_name] = strdup(row[DB_serial]); + if (row[DB_name] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + } + + if (db->attributes.unique_subject) { + OPENSSL_STRING *crow = row; + + rrow = TXT_DB_get_by_index(db->db, DB_name, crow); + if (rrow != NULL) { + BIO_printf(bio_err, + "ERROR:There is already a certificate for %s\n", + row[DB_name]); + } + } + if (rrow == NULL) { + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow != NULL) { + BIO_printf(bio_err, + "ERROR:Serial number %s has already been issued,\n", + row[DB_serial]); + BIO_printf(bio_err, + " check the database/serial_file for corruption\n"); + } + } + if (rrow != NULL) { + BIO_printf(bio_err, + "The matching entry has the following details\n"); + if (rrow[DB_type][0] == DB_TYPE_EXP) + p = "Expired"; + else if (rrow[DB_type][0] == DB_TYPE_REV) + p = "Revoked"; + else if (rrow[DB_type][0] == DB_TYPE_VAL) + p = "Valid"; + else + p = "\ninvalid type, Data base error\n"; + BIO_printf(bio_err, "Type :%s\n", p); + if (rrow[DB_type][0] == DB_TYPE_REV) { + p = rrow[DB_exp_date]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Was revoked on:%s\n", p); + } + p = rrow[DB_exp_date]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Expires on :%s\n", p); + p = rrow[DB_serial]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Serial Number :%s\n", p); + p = rrow[DB_file]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "File name :%s\n", p); + p = rrow[DB_name]; + if (p == NULL) + p = "undef"; + BIO_printf(bio_err, "Subject Name :%s\n", p); + ok = -1; /* This is now a 'bad' error. */ + goto err; + } + + if (!default_op) { + BIO_printf(bio_err, "Certificate Details:\n"); + /* + * Never print signature details because signature not + * present + */ + certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; + if (!X509_print_ex(bio_err, ret, nameopt, certopt)) + goto err; + } + BIO_printf(bio_err, "Certificate is to be certified until "); + ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); + if (days) + BIO_printf(bio_err, " (%ld days)", days); + BIO_printf(bio_err, "\n"); + + if (!batch) { + char answer[25]; + + BIO_printf(bio_err, "Sign the certificate? [y/n]:"); + (void) BIO_flush(bio_err); + if (!fgets(answer, sizeof(answer) - 1, stdin)) { + BIO_printf(bio_err, + "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); + ok = 0; + goto err; + } + if (!((answer[0] == 'y') || (answer[0] == 'Y'))) { + BIO_printf(bio_err, + "CERTIFICATE WILL NOT BE CERTIFIED\n"); + ok = 0; + goto err; + } + } + + if ((pktmp = X509_get0_pubkey(ret)) == NULL) + goto err; + + if (EVP_PKEY_missing_parameters(pktmp) && + !EVP_PKEY_missing_parameters(pkey)) { + if (!EVP_PKEY_copy_parameters(pktmp, pkey)) { + goto err; + } + } + + if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts)) + goto err; + + /* We now just add it to the database */ + row[DB_type] = malloc(2); + + if ((tm = X509_get_notAfter(ret)) == NULL) + goto err; + row[DB_exp_date] = strndup(tm->data, tm->length); + if (row[DB_type] == NULL || row[DB_exp_date] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + + row[DB_rev_date] = NULL; + + /* row[DB_serial] done already */ + row[DB_file] = malloc(8); + + if ((row[DB_type] == NULL) || (row[DB_file] == NULL) || + (row[DB_name] == NULL)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + (void) strlcpy(row[DB_file], "unknown", 8); + row[DB_type][0] = DB_TYPE_VAL; + row[DB_type][1] = '\0'; + + if ((irow = reallocarray(NULL, DB_NUMBER + 1, sizeof(char *))) == + NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + for (i = 0; i < DB_NUMBER; i++) { + irow[i] = row[i]; + row[i] = NULL; + } + irow[DB_NUMBER] = NULL; + + if (!TXT_DB_insert(db->db, irow)) { + BIO_printf(bio_err, "failed to update database\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); + goto err; + } + + *xret = ret; + ret = NULL; + ok = 1; + + err: + for (i = 0; i < DB_NUMBER; i++) + free(row[i]); + + X509_NAME_free(CAname); + X509_NAME_free(subject); + X509_NAME_free(dn_subject); + X509_free(ret); + + return (ok); +} + +static int +write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) +{ + if (output_der) { + if (!i2d_X509_bio(bp, x)) + return (0); + } + if (!notext) { + if (!X509_print(bp, x)) + return (0); + } + + return PEM_write_bio_X509(bp, x); +} + +static int +certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, + unsigned long chtype, int multirdn, int email_dn, char *startdate, + char *enddate, long days, char *ext_sect, CONF *lconf, int verbose, + unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) +{ + STACK_OF(CONF_VALUE) *sk = NULL; + LHASH_OF(CONF_VALUE) *parms = NULL; + X509_REQ *req = NULL; + CONF_VALUE *cv = NULL; + NETSCAPE_SPKI *spki = NULL; + char *type, *buf; + EVP_PKEY *pktmp = NULL; + X509_NAME *n = NULL; + int ok = -1, i, j; + long errline; + int nid; + + /* + * Load input file into a hash table. (This is just an easy + * way to read and parse the file, then put it into a convenient + * STACK format). + */ + parms = CONF_load(NULL, infile, &errline); + if (parms == NULL) { + BIO_printf(bio_err, "error on line %ld of %s\n", + errline, infile); + ERR_print_errors(bio_err); + goto err; + } + sk = CONF_get_section(parms, "default"); + if (sk_CONF_VALUE_num(sk) == 0) { + BIO_printf(bio_err, "no name/value pairs found in %s\n", + infile); + CONF_free(parms); + goto err; + } + /* + * Now create a dummy X509 request structure. We don't actually + * have an X509 request, but we have many of the components + * (a public key, various DN components). The idea is that we + * put these components into the right X509 request structure + * and we can use the same code as if you had a real X509 request. + */ + req = X509_REQ_new(); + if (req == NULL) { + ERR_print_errors(bio_err); + goto err; + } + /* + * Build up the subject name set. + */ + n = X509_REQ_get_subject_name(req); + + for (i = 0;; i++) { + if (sk_CONF_VALUE_num(sk) <= i) + break; + + cv = sk_CONF_VALUE_value(sk, i); + type = cv->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple + * instances + */ + for (buf = cv->name; *buf; buf++) { + if ((*buf == ':') || (*buf == ',') || (*buf == '.')) { + buf++; + if (*buf) + type = buf; + break; + } + } + + buf = cv->value; + if ((nid = OBJ_txt2nid(type)) == NID_undef) { + if (strcmp(type, "SPKAC") == 0) { + spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); + if (spki == NULL) { + BIO_printf(bio_err, + "unable to load Netscape SPKAC structure\n"); + ERR_print_errors(bio_err); + goto err; + } + } + continue; + } + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + (unsigned char *)buf, -1, -1, 0)) + goto err; + } + if (spki == NULL) { + BIO_printf(bio_err, + "Netscape SPKAC structure not found in %s\n", infile); + goto err; + } + /* + * Now extract the key from the SPKI structure. + */ + + BIO_printf(bio_err, + "Check that the SPKAC request matches the signature\n"); + + if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) { + BIO_printf(bio_err, "error unpacking SPKAC public key\n"); + goto err; + } + j = NETSCAPE_SPKI_verify(spki, pktmp); + if (j <= 0) { + BIO_printf(bio_err, + "signature verification failed on SPKAC public key\n"); + goto err; + } + BIO_printf(bio_err, "Signature ok\n"); + + if (!X509_REQ_set_pubkey(req, pktmp)) { + EVP_PKEY_free(pktmp); + goto err; + } + EVP_PKEY_free(pktmp); + ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, + subj, chtype, multirdn, email_dn, startdate, enddate, days, 1, + verbose, req, ext_sect, lconf, certopt, nameopt, default_op, + ext_copy, 0); + + err: + X509_REQ_free(req); + CONF_free(parms); + NETSCAPE_SPKI_free(spki); + + return (ok); +} + +static int +check_time_format(const char *str) +{ + return ASN1_TIME_set_string(NULL, str); +} + +static int +do_revoke(X509 *x509, CA_DB *db, int type, char *value) +{ + ASN1_UTCTIME *tm = NULL; + char *row[DB_NUMBER], **rrow, **irow; + char *rev_str = NULL; + BIGNUM *bn = NULL; + int ok = -1, i; + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0); + bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL); + if (bn == NULL) + goto err; + if (BN_is_zero(bn)) + row[DB_serial] = strdup("00"); + else + row[DB_serial] = BN_bn2hex(bn); + BN_free(bn); + + if (row[DB_name] != NULL && row[DB_name][0] == '\0') { + /* + * Entries with empty Subjects actually use the serial number + * instead + */ + free(row[DB_name]); + row[DB_name] = strdup(row[DB_serial]); + if (row[DB_name] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + } + + if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + /* + * We have to lookup by serial number because name lookup skips + * revoked certs + */ + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow == NULL) { + BIO_printf(bio_err, + "Adding Entry with serial number %s to DB for %s\n", + row[DB_serial], row[DB_name]); + + /* We now just add it to the database */ + row[DB_type] = malloc(2); + + if ((tm = X509_get_notAfter(x509)) == NULL) + goto err; + row[DB_exp_date] = strndup(tm->data, tm->length); + if (row[DB_type] == NULL || row[DB_exp_date] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + + row[DB_rev_date] = NULL; + + /* row[DB_serial] done already */ + row[DB_file] = malloc(8); + + /* row[DB_name] done already */ + + if ((row[DB_type] == NULL) || (row[DB_file] == NULL)) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + (void) strlcpy(row[DB_file], "unknown", 8); + row[DB_type][0] = DB_TYPE_VAL; + row[DB_type][1] = '\0'; + + if ((irow = reallocarray(NULL, sizeof(char *), + (DB_NUMBER + 1))) == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto err; + } + for (i = 0; i < DB_NUMBER; i++) { + irow[i] = row[i]; + row[i] = NULL; + } + irow[DB_NUMBER] = NULL; + + if (!TXT_DB_insert(db->db, irow)) { + BIO_printf(bio_err, "failed to update database\n"); + BIO_printf(bio_err, "TXT_DB error number %ld\n", + db->db->error); + goto err; + } + /* Revoke Certificate */ + ok = do_revoke(x509, db, type, value); + + goto err; + + } else if (index_name_cmp_noconst(row, rrow)) { + BIO_printf(bio_err, "ERROR:name does not match %s\n", + row[DB_name]); + goto err; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { + BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", + row[DB_serial]); + goto err; + } else { + BIO_printf(bio_err, "Revoking Certificate %s.\n", + rrow[DB_serial]); + rev_str = make_revocation_str(type, value); + if (rev_str == NULL) { + BIO_printf(bio_err, "Error in revocation arguments\n"); + goto err; + } + rrow[DB_type][0] = DB_TYPE_REV; + rrow[DB_type][1] = '\0'; + rrow[DB_rev_date] = rev_str; + } + ok = 1; + + err: + for (i = 0; i < DB_NUMBER; i++) + free(row[i]); + + return (ok); +} + +static int +get_certificate_status(const char *serial, CA_DB *db) +{ + char *row[DB_NUMBER], **rrow; + int ok = -1, i; + + /* Free Resources */ + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + + /* Malloc needed char spaces */ + row[DB_serial] = malloc(strlen(serial) + 2); + if (row[DB_serial] == NULL) { + BIO_printf(bio_err, "Malloc failure\n"); + goto err; + } + if (strlen(serial) % 2) { + /* Set the first char to 0 */ ; + row[DB_serial][0] = '0'; + + /* Copy String from serial to row[DB_serial] */ + memcpy(row[DB_serial] + 1, serial, strlen(serial)); + row[DB_serial][strlen(serial) + 1] = '\0'; + } else { + /* Copy String from serial to row[DB_serial] */ + memcpy(row[DB_serial], serial, strlen(serial)); + row[DB_serial][strlen(serial)] = '\0'; + } + + /* Make it Upper Case */ + for (i = 0; row[DB_serial][i] != '\0'; i++) + row[DB_serial][i] = toupper((unsigned char) row[DB_serial][i]); + + + ok = 1; + + /* Search for the certificate */ + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + if (rrow == NULL) { + BIO_printf(bio_err, "Serial %s not present in db.\n", + row[DB_serial]); + ok = -1; + goto err; + } else if (rrow[DB_type][0] == DB_TYPE_VAL) { + BIO_printf(bio_err, "%s=Valid (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto err; + } else if (rrow[DB_type][0] == DB_TYPE_REV) { + BIO_printf(bio_err, "%s=Revoked (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto err; + } else if (rrow[DB_type][0] == DB_TYPE_EXP) { + BIO_printf(bio_err, "%s=Expired (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto err; + } else if (rrow[DB_type][0] == DB_TYPE_SUSP) { + BIO_printf(bio_err, "%s=Suspended (%c)\n", + row[DB_serial], rrow[DB_type][0]); + goto err; + } else { + BIO_printf(bio_err, "%s=Unknown (%c).\n", + row[DB_serial], rrow[DB_type][0]); + ok = -1; + } + + err: + for (i = 0; i < DB_NUMBER; i++) + free(row[i]); + + return (ok); +} + +static int +do_updatedb(CA_DB *db) +{ + ASN1_UTCTIME *a_tm = NULL; + int i, cnt = 0; + int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ + char **rrow, *a_tm_s = NULL; + + a_tm = ASN1_UTCTIME_new(); + if (a_tm == NULL) { + cnt = -1; + goto err; + } + + /* get actual time and make a string */ + a_tm = X509_gmtime_adj(a_tm, 0); + if (a_tm == NULL) { + cnt = -1; + goto err; + } + a_tm_s = strndup(a_tm->data, a_tm->length); + if (a_tm_s == NULL) { + cnt = -1; + goto err; + } + + if (strncmp(a_tm_s, "49", 2) <= 0) + a_y2k = 1; + else + a_y2k = 0; + + for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { + rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); + + if (rrow[DB_type][0] == DB_TYPE_VAL) { + /* ignore entries that are not valid */ + if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) + db_y2k = 1; + else + db_y2k = 0; + + if (db_y2k == a_y2k) { + /* all on the same y2k side */ + if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { + rrow[DB_type][0] = DB_TYPE_EXP; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", + rrow[DB_serial]); + } + } else if (db_y2k < a_y2k) { + rrow[DB_type][0] = DB_TYPE_EXP; + rrow[DB_type][1] = '\0'; + cnt++; + + BIO_printf(bio_err, "%s=Expired\n", + rrow[DB_serial]); + } + } + } + + err: + ASN1_UTCTIME_free(a_tm); + free(a_tm_s); + + return (cnt); +} + +static const char *crl_reasons[] = { + /* CRL reason strings */ + "unspecified", + "keyCompromise", + "CACompromise", + "affiliationChanged", + "superseded", + "cessationOfOperation", + "certificateHold", + "removeFromCRL", + /* Additional pseudo reasons */ + "holdInstruction", + "keyTime", + "CAkeyTime" +}; + +#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) + +/* Given revocation information convert to a DB string. + * The format of the string is: + * revtime[,reason,extra]. Where 'revtime' is the + * revocation time (the current time). 'reason' is the + * optional CRL reason and 'extra' is any additional + * argument + */ + +char * +make_revocation_str(int rev_type, char *rev_arg) +{ + char *other = NULL, *str; + const char *reason = NULL; + ASN1_OBJECT *otmp; + ASN1_UTCTIME *revtm = NULL; + int i; + switch (rev_type) { + case REV_NONE: + break; + + case REV_CRL_REASON: + for (i = 0; i < 8; i++) { + if (strcasecmp(rev_arg, crl_reasons[i]) == 0) { + reason = crl_reasons[i]; + break; + } + } + if (reason == NULL) { + BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); + return NULL; + } + break; + + case REV_HOLD: + /* Argument is an OID */ + otmp = OBJ_txt2obj(rev_arg, 0); + ASN1_OBJECT_free(otmp); + + if (otmp == NULL) { + BIO_printf(bio_err, + "Invalid object identifier %s\n", rev_arg); + return NULL; + } + reason = "holdInstruction"; + other = rev_arg; + break; + + case REV_KEY_COMPROMISE: + case REV_CA_COMPROMISE: + /* Argument is the key compromise time */ + if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { + BIO_printf(bio_err, + "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", + rev_arg); + return NULL; + } + other = rev_arg; + if (rev_type == REV_KEY_COMPROMISE) + reason = "keyTime"; + else + reason = "CAkeyTime"; + + break; + } + + revtm = X509_gmtime_adj(NULL, 0); + if (revtm == NULL) + return NULL; + + if (asprintf(&str, "%s%s%s%s%s", revtm->data, + reason ? "," : "", reason ? reason : "", + other ? "," : "", other ? other : "") == -1) + str = NULL; + + ASN1_UTCTIME_free(revtm); + + return str; +} + +/* Convert revocation field to X509_REVOKED entry + * return code: + * 0 error + * 1 OK + * 2 OK and some extensions added (i.e. V2 CRL) + */ + +int +make_revoked(X509_REVOKED *rev, const char *str) +{ + char *tmp = NULL; + int reason_code = -1; + int i, ret = 0; + ASN1_OBJECT *hold = NULL; + ASN1_GENERALIZEDTIME *comp_time = NULL; + ASN1_ENUMERATED *rtmp = NULL; + + ASN1_TIME *revDate = NULL; + + i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); + + if (i == 0) + goto err; + + if (rev != NULL && !X509_REVOKED_set_revocationDate(rev, revDate)) + goto err; + + if (rev != NULL && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) { + rtmp = ASN1_ENUMERATED_new(); + if (rtmp == NULL || !ASN1_ENUMERATED_set(rtmp, reason_code)) + goto err; + if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) + goto err; + } + if (rev != NULL && comp_time != NULL) { + if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, + comp_time, 0, 0)) + goto err; + } + if (rev != NULL && hold != NULL) { + if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, + hold, 0, 0)) + goto err; + } + if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) + ret = 2; + else + ret = 1; + + err: + free(tmp); + + ASN1_OBJECT_free(hold); + ASN1_GENERALIZEDTIME_free(comp_time); + ASN1_ENUMERATED_free(rtmp); + ASN1_TIME_free(revDate); + + return ret; +} + +int +old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) +{ + char buf[25], *pbuf, *p; + int j; + + j = i2a_ASN1_OBJECT(bp, obj); + pbuf = buf; + for (j = 22 - j; j > 0; j--) + *(pbuf++) = ' '; + *(pbuf++) = ':'; + *(pbuf++) = '\0'; + BIO_puts(bp, buf); + + if (str->type == V_ASN1_PRINTABLESTRING) + BIO_printf(bp, "PRINTABLE:'"); + else if (str->type == V_ASN1_T61STRING) + BIO_printf(bp, "T61STRING:'"); + else if (str->type == V_ASN1_IA5STRING) + BIO_printf(bp, "IA5STRING:'"); + else if (str->type == V_ASN1_UNIVERSALSTRING) + BIO_printf(bp, "UNIVERSALSTRING:'"); + else + BIO_printf(bp, "ASN.1 %2d:'", str->type); + + p = (char *) str->data; + for (j = str->length; j > 0; j--) { + if ((*p >= ' ') && (*p <= '~')) + BIO_printf(bp, "%c", *p); + else if (*p & 0x80) + BIO_printf(bp, "\\0x%02X", *p); + else if ((unsigned char) *p == 0xf7) + BIO_printf(bp, "^?"); + else + BIO_printf(bp, "^%c", *p + '@'); + p++; + } + BIO_printf(bp, "'\n"); + return 1; +} + +int +unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, + ASN1_GENERALIZEDTIME **pinvtm, const char *str) +{ + char *tmp = NULL; + char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; + int reason_code = -1; + int ret = 0; + unsigned int i; + ASN1_OBJECT *hold = NULL; + ASN1_GENERALIZEDTIME *comp_time = NULL; + + if ((tmp = strdup(str)) == NULL) { + BIO_printf(bio_err, "malloc failed\n"); + goto err; + } + p = strchr(tmp, ','); + rtime_str = tmp; + + if (p != NULL) { + *p = '\0'; + p++; + reason_str = p; + p = strchr(p, ','); + if (p != NULL) { + *p = '\0'; + arg_str = p + 1; + } + } + if (prevtm != NULL) { + *prevtm = ASN1_UTCTIME_new(); + if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) { + BIO_printf(bio_err, "invalid revocation date %s\n", + rtime_str); + goto err; + } + } + if (reason_str != NULL) { + for (i = 0; i < NUM_REASONS; i++) { + if (strcasecmp(reason_str, crl_reasons[i]) == 0) { + reason_code = i; + break; + } + } + if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) { + BIO_printf(bio_err, "invalid reason code %s\n", + reason_str); + goto err; + } + if (reason_code == 7) + reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; + else if (reason_code == 8) { /* Hold instruction */ + if (arg_str == NULL) { + BIO_printf(bio_err, + "missing hold instruction\n"); + goto err; + } + reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; + hold = OBJ_txt2obj(arg_str, 0); + + if (hold == NULL) { + BIO_printf(bio_err, + "invalid object identifier %s\n", arg_str); + goto err; + } + if (phold != NULL) + *phold = hold; + } else if ((reason_code == 9) || (reason_code == 10)) { + if (arg_str == NULL) { + BIO_printf(bio_err, + "missing compromised time\n"); + goto err; + } + comp_time = ASN1_GENERALIZEDTIME_new(); + if (!ASN1_GENERALIZEDTIME_set_string(comp_time, + arg_str)) { + BIO_printf(bio_err, + "invalid compromised time %s\n", arg_str); + goto err; + } + if (reason_code == 9) + reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; + else + reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; + } + } + if (preason != NULL) + *preason = reason_code; + if (pinvtm != NULL) + *pinvtm = comp_time; + else + ASN1_GENERALIZEDTIME_free(comp_time); + + ret = 1; + + err: + free(tmp); + + if (phold == NULL) + ASN1_OBJECT_free(hold); + if (pinvtm == NULL) + ASN1_GENERALIZEDTIME_free(comp_time); + + return ret; +} + +static char * +bin2hex(unsigned char *data, size_t len) +{ + char *ret = NULL; + char hex[] = "0123456789ABCDEF"; + int i; + + if ((ret = malloc(len * 2 + 1)) != NULL) { + for (i = 0; i < len; i++) { + ret[i * 2 + 0] = hex[data[i] >> 4]; + ret[i * 2 + 1] = hex[data[i] & 0x0F]; + } + ret[len * 2] = '\0'; + } + return ret; +} diff --git a/apps/openssl/certhash.c b/apps/openssl/certhash.c new file mode 100644 index 0000000..5ee29b8 --- /dev/null +++ b/apps/openssl/certhash.c @@ -0,0 +1,691 @@ +/* $OpenBSD: certhash.c,v 1.21 2023/03/06 14:32:05 tb Exp $ */ +/* + * Copyright (c) 2014, 2015 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "apps.h" + +static struct { + int dryrun; + int verbose; +} cfg; + +static const struct option certhash_options[] = { + { + .name = "n", + .desc = "Perform a dry-run - do not make any changes", + .type = OPTION_FLAG, + .opt.flag = &cfg.dryrun, + }, + { + .name = "v", + .desc = "Verbose", + .type = OPTION_FLAG, + .opt.flag = &cfg.verbose, + }, + { NULL }, +}; + +struct hashinfo { + char *filename; + char *target; + unsigned long hash; + unsigned int index; + unsigned char fingerprint[EVP_MAX_MD_SIZE]; + int is_crl; + int is_dup; + int exists; + int changed; + struct hashinfo *reference; + struct hashinfo *next; +}; + +static struct hashinfo * +hashinfo(const char *filename, unsigned long hash, unsigned char *fingerprint) +{ + struct hashinfo *hi; + + if ((hi = calloc(1, sizeof(*hi))) == NULL) + return (NULL); + if (filename != NULL) { + if ((hi->filename = strdup(filename)) == NULL) { + free(hi); + return (NULL); + } + } + hi->hash = hash; + if (fingerprint != NULL) + memcpy(hi->fingerprint, fingerprint, sizeof(hi->fingerprint)); + + return (hi); +} + +static void +hashinfo_free(struct hashinfo *hi) +{ + if (hi == NULL) + return; + + free(hi->filename); + free(hi->target); + free(hi); +} + +#ifdef DEBUG +static void +hashinfo_print(struct hashinfo *hi) +{ + int i; + + printf("hashinfo %s %08lx %u %i\n", hi->filename, hi->hash, + hi->index, hi->is_crl); + for (i = 0; i < (int)EVP_MAX_MD_SIZE; i++) { + printf("%02X%c", hi->fingerprint[i], + (i + 1 == (int)EVP_MAX_MD_SIZE) ? '\n' : ':'); + } +} +#endif + +static int +hashinfo_compare(const void *a, const void *b) +{ + struct hashinfo *hia = *(struct hashinfo **)a; + struct hashinfo *hib = *(struct hashinfo **)b; + int rv; + + rv = hia->hash < hib->hash ? -1 : hia->hash > hib->hash; + if (rv != 0) + return (rv); + rv = memcmp(hia->fingerprint, hib->fingerprint, + sizeof(hia->fingerprint)); + if (rv != 0) + return (rv); + return strcmp(hia->filename, hib->filename); +} + +static struct hashinfo * +hashinfo_chain(struct hashinfo *head, struct hashinfo *entry) +{ + struct hashinfo *hi = head; + + if (hi == NULL) + return (entry); + while (hi->next != NULL) + hi = hi->next; + hi->next = entry; + + return (head); +} + +static void +hashinfo_chain_free(struct hashinfo *hi) +{ + struct hashinfo *next; + + while (hi != NULL) { + next = hi->next; + hashinfo_free(hi); + hi = next; + } +} + +static size_t +hashinfo_chain_length(struct hashinfo *hi) +{ + int len = 0; + + while (hi != NULL) { + len++; + hi = hi->next; + } + return (len); +} + +static int +hashinfo_chain_sort(struct hashinfo **head) +{ + struct hashinfo **list, *entry; + size_t len; + int i; + + if (*head == NULL) + return (0); + + len = hashinfo_chain_length(*head); + if ((list = reallocarray(NULL, len, sizeof(struct hashinfo *))) == NULL) + return (-1); + + for (entry = *head, i = 0; entry != NULL; entry = entry->next, i++) + list[i] = entry; + qsort(list, len, sizeof(struct hashinfo *), hashinfo_compare); + + *head = entry = list[0]; + for (i = 1; i < len; i++) { + entry->next = list[i]; + entry = list[i]; + } + entry->next = NULL; + + free(list); + return (0); +} + +static char * +hashinfo_linkname(struct hashinfo *hi) +{ + char *filename; + + if (asprintf(&filename, "%08lx.%s%u", hi->hash, + (hi->is_crl ? "r" : ""), hi->index) == -1) + return (NULL); + + return (filename); +} + +static int +filename_is_hash(const char *filename) +{ + const char *p = filename; + + while ((*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f')) + p++; + if (*p++ != '.') + return (0); + if (*p == 'r') /* CRL format. */ + p++; + while (*p >= '0' && *p <= '9') + p++; + if (*p != '\0') + return (0); + + return (1); +} + +static int +filename_is_pem(const char *filename) +{ + const char *q, *p = filename; + + if ((q = strchr(p, '\0')) == NULL) + return (0); + if ((q - p) < 4) + return (0); + if (strncmp((q - 4), ".pem", 4) != 0) + return (0); + + return (1); +} + +static struct hashinfo * +hashinfo_from_linkname(const char *linkname, const char *target) +{ + struct hashinfo *hi = NULL; + const char *errstr; + char *l, *p, *ep; + long long val; + + if ((l = strdup(linkname)) == NULL) + goto err; + if ((p = strchr(l, '.')) == NULL) + goto err; + *p++ = '\0'; + + if ((hi = hashinfo(linkname, 0, NULL)) == NULL) + goto err; + if ((hi->target = strdup(target)) == NULL) + goto err; + + errno = 0; + val = strtoll(l, &ep, 16); + if (l[0] == '\0' || *ep != '\0') + goto err; + if (errno == ERANGE && (val == LLONG_MAX || val == LLONG_MIN)) + goto err; + if (val < 0 || val > ULONG_MAX) + goto err; + hi->hash = (unsigned long)val; + + if (*p == 'r') { + hi->is_crl = 1; + p++; + } + + val = strtonum(p, 0, 0xffffffff, &errstr); + if (errstr != NULL) + goto err; + + hi->index = (unsigned int)val; + + goto done; + + err: + hashinfo_free(hi); + hi = NULL; + + done: + free(l); + + return (hi); +} + +static struct hashinfo * +certhash_cert(BIO *bio, const char *filename) +{ + unsigned char fingerprint[EVP_MAX_MD_SIZE]; + struct hashinfo *hi = NULL; + const EVP_MD *digest; + X509 *cert = NULL; + unsigned long hash; + unsigned int len; + + if ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) + goto err; + + hash = X509_subject_name_hash(cert); + + digest = EVP_sha256(); + if (X509_digest(cert, digest, fingerprint, &len) != 1) { + fprintf(stderr, "out of memory\n"); + goto err; + } + + hi = hashinfo(filename, hash, fingerprint); + + err: + X509_free(cert); + + return (hi); +} + +static struct hashinfo * +certhash_crl(BIO *bio, const char *filename) +{ + unsigned char fingerprint[EVP_MAX_MD_SIZE]; + struct hashinfo *hi = NULL; + const EVP_MD *digest; + X509_CRL *crl = NULL; + unsigned long hash; + unsigned int len; + + if ((crl = PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL)) == NULL) + return (NULL); + + hash = X509_NAME_hash(X509_CRL_get_issuer(crl)); + + digest = EVP_sha256(); + if (X509_CRL_digest(crl, digest, fingerprint, &len) != 1) { + fprintf(stderr, "out of memory\n"); + goto err; + } + + hi = hashinfo(filename, hash, fingerprint); + + err: + X509_CRL_free(crl); + + return (hi); +} + +static int +certhash_addlink(struct hashinfo **links, struct hashinfo *hi) +{ + struct hashinfo *link = NULL; + + if ((link = hashinfo(NULL, hi->hash, hi->fingerprint)) == NULL) + goto err; + + if ((link->filename = hashinfo_linkname(hi)) == NULL) + goto err; + + link->reference = hi; + link->changed = 1; + *links = hashinfo_chain(*links, link); + hi->reference = link; + + return (0); + + err: + hashinfo_free(link); + return (-1); +} + +static void +certhash_findlink(struct hashinfo *links, struct hashinfo *hi) +{ + struct hashinfo *link; + + for (link = links; link != NULL; link = link->next) { + if (link->is_crl == hi->is_crl && + link->hash == hi->hash && + link->index == hi->index && + link->reference == NULL) { + link->reference = hi; + if (link->target == NULL || + strcmp(link->target, hi->filename) != 0) + link->changed = 1; + hi->reference = link; + break; + } + } +} + +static void +certhash_index(struct hashinfo *head, const char *name) +{ + struct hashinfo *last, *entry; + int index = 0; + + last = NULL; + for (entry = head; entry != NULL; entry = entry->next) { + if (last != NULL) { + if (entry->hash == last->hash) { + if (memcmp(entry->fingerprint, + last->fingerprint, + sizeof(entry->fingerprint)) == 0) { + fprintf(stderr, "WARNING: duplicate %s " + "in %s (using %s), ignoring...\n", + name, entry->filename, + last->filename); + entry->is_dup = 1; + continue; + } + index++; + } else { + index = 0; + } + } + entry->index = index; + last = entry; + } +} + +static int +certhash_merge(struct hashinfo **links, struct hashinfo **certs, + struct hashinfo **crls) +{ + struct hashinfo *cert, *crl; + + /* Pass 1 - sort and index entries. */ + if (hashinfo_chain_sort(certs) == -1) + return (-1); + if (hashinfo_chain_sort(crls) == -1) + return (-1); + certhash_index(*certs, "certificate"); + certhash_index(*crls, "CRL"); + + /* Pass 2 - map to existing links. */ + for (cert = *certs; cert != NULL; cert = cert->next) { + if (cert->is_dup == 1) + continue; + certhash_findlink(*links, cert); + } + for (crl = *crls; crl != NULL; crl = crl->next) { + if (crl->is_dup == 1) + continue; + certhash_findlink(*links, crl); + } + + /* Pass 3 - determine missing links. */ + for (cert = *certs; cert != NULL; cert = cert->next) { + if (cert->is_dup == 1 || cert->reference != NULL) + continue; + if (certhash_addlink(links, cert) == -1) + return (-1); + } + for (crl = *crls; crl != NULL; crl = crl->next) { + if (crl->is_dup == 1 || crl->reference != NULL) + continue; + if (certhash_addlink(links, crl) == -1) + return (-1); + } + + return (0); +} + +static int +certhash_link(struct dirent *dep, struct hashinfo **links) +{ + struct hashinfo *hi = NULL; + char target[PATH_MAX]; + struct stat sb; + int n; + + if (lstat(dep->d_name, &sb) == -1) { + fprintf(stderr, "failed to stat %s\n", dep->d_name); + return (-1); + } + if (!S_ISLNK(sb.st_mode)) + return (0); + + n = readlink(dep->d_name, target, sizeof(target) - 1); + if (n == -1) { + fprintf(stderr, "failed to readlink %s\n", dep->d_name); + return (-1); + } + if (n >= sizeof(target) - 1) { + fprintf(stderr, "symbolic link is too long %s\n", dep->d_name); + return (-1); + } + target[n] = '\0'; + + hi = hashinfo_from_linkname(dep->d_name, target); + if (hi == NULL) { + fprintf(stderr, "failed to get hash info %s\n", dep->d_name); + return (-1); + } + hi->exists = 1; + *links = hashinfo_chain(*links, hi); + + return (0); +} + +static int +certhash_file(struct dirent *dep, struct hashinfo **certs, + struct hashinfo **crls) +{ + struct hashinfo *hi = NULL; + int has_cert, has_crl; + int ret = -1; + BIO *bio = NULL; + FILE *f; + + has_cert = has_crl = 0; + + if ((f = fopen(dep->d_name, "r")) == NULL) { + fprintf(stderr, "failed to fopen %s\n", dep->d_name); + goto err; + } + if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) { + fprintf(stderr, "failed to create bio\n"); + fclose(f); + goto err; + } + + if ((hi = certhash_cert(bio, dep->d_name)) != NULL) { + has_cert = 1; + *certs = hashinfo_chain(*certs, hi); + } + + if (BIO_reset(bio) != 0) { + fprintf(stderr, "BIO_reset failed\n"); + goto err; + } + + if ((hi = certhash_crl(bio, dep->d_name)) != NULL) { + has_crl = hi->is_crl = 1; + *crls = hashinfo_chain(*crls, hi); + } + + if (!has_cert && !has_crl) + fprintf(stderr, "PEM file %s does not contain a certificate " + "or CRL, ignoring...\n", dep->d_name); + + ret = 0; + + err: + BIO_free(bio); + + return (ret); +} + +static int +certhash_directory(const char *path) +{ + struct hashinfo *links = NULL, *certs = NULL, *crls = NULL, *link; + int ret = 0; + struct dirent *dep; + DIR *dip = NULL; + + if ((dip = opendir(".")) == NULL) { + fprintf(stderr, "failed to open directory %s\n", path); + goto err; + } + + if (cfg.verbose) + fprintf(stdout, "scanning directory %s\n", path); + + /* Create lists of existing hash links, certs and CRLs. */ + while ((dep = readdir(dip)) != NULL) { + if (filename_is_hash(dep->d_name)) { + if (certhash_link(dep, &links) == -1) + goto err; + } + if (filename_is_pem(dep->d_name)) { + if (certhash_file(dep, &certs, &crls) == -1) + goto err; + } + } + + if (certhash_merge(&links, &certs, &crls) == -1) { + fprintf(stderr, "certhash merge failed\n"); + goto err; + } + + /* Remove spurious links. */ + for (link = links; link != NULL; link = link->next) { + if (link->exists == 0 || + (link->reference != NULL && link->changed == 0)) + continue; + if (cfg.verbose) + fprintf(stdout, "%s link %s -> %s\n", + (cfg.dryrun ? "would remove" : + "removing"), link->filename, link->target); + if (cfg.dryrun) + continue; + if (unlink(link->filename) == -1) { + fprintf(stderr, "failed to remove link %s\n", + link->filename); + goto err; + } + } + + /* Create missing links. */ + for (link = links; link != NULL; link = link->next) { + if (link->exists == 1 && link->changed == 0) + continue; + if (cfg.verbose) + fprintf(stdout, "%s link %s -> %s\n", + (cfg.dryrun ? "would create" : + "creating"), link->filename, + link->reference->filename); + if (cfg.dryrun) + continue; + if (symlink(link->reference->filename, link->filename) == -1) { + fprintf(stderr, "failed to create link %s -> %s\n", + link->filename, link->reference->filename); + goto err; + } + } + + goto done; + + err: + ret = 1; + + done: + hashinfo_chain_free(certs); + hashinfo_chain_free(crls); + hashinfo_chain_free(links); + + if (dip != NULL) + closedir(dip); + return (ret); +} + +static void +certhash_usage(void) +{ + fprintf(stderr, "usage: certhash [-nv] dir ...\n"); + options_usage(certhash_options); +} + +int +certhash_main(int argc, char **argv) +{ + int argsused; + int i, cwdfd, ret = 0; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, certhash_options, NULL, &argsused) != 0) { + certhash_usage(); + return (1); + } + + if ((cwdfd = open(".", O_RDONLY)) == -1) { + perror("failed to open current directory"); + return (1); + } + + for (i = argsused; i < argc; i++) { + if (chdir(argv[i]) == -1) { + fprintf(stderr, + "failed to change to directory %s: %s\n", + argv[i], strerror(errno)); + ret = 1; + continue; + } + ret |= certhash_directory(argv[i]); + if (fchdir(cwdfd) == -1) { + perror("failed to restore current directory"); + ret = 1; + break; /* can't continue safely */ + } + } + close(cwdfd); + + return (ret); +} diff --git a/apps/openssl/ciphers.c b/apps/openssl/ciphers.c new file mode 100644 index 0000000..247929b --- /dev/null +++ b/apps/openssl/ciphers.c @@ -0,0 +1,200 @@ +/* $OpenBSD: ciphers.c,v 1.18 2023/03/06 14:32:05 tb Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +#include "apps.h" +#include "progs.h" + +static struct { + int usage; + int use_supported; + int verbose; + int version; +} cfg; + +static const struct option ciphers_options[] = { + { + .name = "h", + .type = OPTION_FLAG, + .opt.flag = &cfg.usage, + }, + { + .name = "?", + .type = OPTION_FLAG, + .opt.flag = &cfg.usage, + }, + { + .name = "s", + .desc = "Only list ciphers that are supported by the TLS method", + .type = OPTION_FLAG, + .opt.flag = &cfg.use_supported, + }, + { + .name = "tls1", + .desc = "Use TLS protocol version 1", + .type = OPTION_VALUE, + .opt.value = &cfg.version, + .value = TLS1_VERSION, + }, + { + .name = "tls1_1", + .desc = "Use TLS protocol version 1.1", + .type = OPTION_VALUE, + .opt.value = &cfg.version, + .value = TLS1_1_VERSION, + }, + { + .name = "tls1_2", + .desc = "Use TLS protocol version 1.2", + .type = OPTION_VALUE, + .opt.value = &cfg.version, + .value = TLS1_2_VERSION, + }, + { + .name = "tls1_3", + .desc = "Use TLS protocol version 1.3", + .type = OPTION_VALUE, + .opt.value = &cfg.version, + .value = TLS1_3_VERSION, + }, + { + .name = "v", + .desc = "Provide cipher listing", + .type = OPTION_VALUE, + .opt.value = &cfg.verbose, + .value = 1, + }, + { + .name = "V", + .desc = "Provide cipher listing with cipher suite values", + .type = OPTION_VALUE, + .opt.value = &cfg.verbose, + .value = 2, + }, + { NULL }, +}; + +static void +ciphers_usage(void) +{ + fprintf(stderr, "usage: ciphers [-hsVv] [-tls1] [-tls1_1] [-tls1_2] " + "[-tls1_3] [cipherlist]\n"); + options_usage(ciphers_options); +} + +int +ciphers_main(int argc, char **argv) +{ + char *cipherlist = NULL; + STACK_OF(SSL_CIPHER) *ciphers; + STACK_OF(SSL_CIPHER) *supported_ciphers = NULL; + const SSL_CIPHER *cipher; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + uint16_t value; + int i, rv = 0; + char *desc; + + if (pledge("stdio rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, ciphers_options, &cipherlist, + NULL) != 0) { + ciphers_usage(); + return (1); + } + + if (cfg.usage) { + ciphers_usage(); + return (1); + } + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + goto err; + + if (cfg.version != 0) { + if (!SSL_CTX_set_min_proto_version(ssl_ctx, + cfg.version)) + goto err; + if (!SSL_CTX_set_max_proto_version(ssl_ctx, + cfg.version)) + goto err; + } + + if (cipherlist != NULL) { + if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0) + goto err; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + goto err; + + if (cfg.use_supported) { + if ((supported_ciphers = + SSL_get1_supported_ciphers(ssl)) == NULL) + goto err; + ciphers = supported_ciphers; + } else { + if ((ciphers = SSL_get_ciphers(ssl)) == NULL) + goto err; + } + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + cipher = sk_SSL_CIPHER_value(ciphers, i); + if (cfg.verbose == 0) { + fprintf(stdout, "%s%s", (i ? ":" : ""), + SSL_CIPHER_get_name(cipher)); + continue; + } + if (cfg.verbose > 1) { + value = SSL_CIPHER_get_value(cipher); + fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "", + ((value >> 8) & 0xff), (value & 0xff)); + } + desc = SSL_CIPHER_description(cipher, NULL, 0); + if (strcmp(desc, "OPENSSL_malloc Error") == 0) { + fprintf(stderr, "out of memory\n"); + goto err; + } + fprintf(stdout, "%s", desc); + free(desc); + } + if (cfg.verbose == 0) + fprintf(stdout, "\n"); + + goto done; + + err: + ERR_print_errors_fp(stderr); + rv = 1; + + done: + sk_SSL_CIPHER_free(supported_ciphers); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (rv); +} diff --git a/apps/openssl/cms.c b/apps/openssl/cms.c new file mode 100644 index 0000000..121a413 --- /dev/null +++ b/apps/openssl/cms.c @@ -0,0 +1,1961 @@ +/* $OpenBSD: cms.c,v 1.34 2023/04/14 15:27:13 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +/* CMS utility function */ + +#include +#include + +#include "apps.h" + +#ifndef OPENSSL_NO_CMS + +#include +#include +#include +#include +#include + +#include + +static int save_certs(char *signerfile, STACK_OF(X509) *signers); +static void receipt_request_print(BIO *out, CMS_ContentInfo *cms); +static CMS_ReceiptRequest *make_receipt_request( + STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from); +static int cms_set_pkey_param(EVP_PKEY_CTX *pctx, + STACK_OF(OPENSSL_STRING) *param); + +#define SMIME_OP 0x10 +#define SMIME_IP 0x20 +#define SMIME_SIGNERS 0x40 +#define SMIME_ENCRYPT (1 | SMIME_OP) +#define SMIME_DECRYPT (2 | SMIME_IP) +#define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS) +#define SMIME_VERIFY (4 | SMIME_IP) +#define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP) +#define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS) +#define SMIME_DATAOUT (7 | SMIME_IP) +#define SMIME_DATA_CREATE (8 | SMIME_OP) +#define SMIME_DIGEST_VERIFY (9 | SMIME_IP) +#define SMIME_DIGEST_CREATE (10 | SMIME_OP) +#define SMIME_UNCOMPRESS (11 | SMIME_IP) +#define SMIME_COMPRESS (12 | SMIME_OP) +#define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP) +#define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP) +#define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP) +#define SMIME_VERIFY_RECEIPT (16 | SMIME_IP) + +int verify_err = 0; + +struct cms_key_param { + int idx; + STACK_OF(OPENSSL_STRING) *param; + struct cms_key_param *next; +}; + +static struct { + char *CAfile; + char *CApath; + X509 *cert; + char *certfile; + char *certsoutfile; + const EVP_CIPHER *cipher; + char *contfile; + ASN1_OBJECT *econtent_type; + STACK_OF(X509) *encerts; + int flags; + char *from; + char *infile; + int informat; + struct cms_key_param *key_first; + struct cms_key_param *key_param; + char *keyfile; + int keyform; + int noout; + int operation; + char *outfile; + int outformat; + char *passargin; + int print; + unsigned char *pwri_pass; + int rr_allorfirst; + STACK_OF(OPENSSL_STRING) *rr_from; + int rr_print; + STACK_OF(OPENSSL_STRING) *rr_to; + char *rctfile; + int rctformat; + char *recipfile; + unsigned char *secret_key; + unsigned char *secret_keyid; + size_t secret_keyidlen; + size_t secret_keylen; + const EVP_MD *sign_md; + char *signerfile; + STACK_OF(OPENSSL_STRING) *skkeys; + STACK_OF(OPENSSL_STRING) *sksigners; + char *subject; + char *to; + int verify_retcode; + X509_VERIFY_PARAM *vpm; +} cfg; + +static const EVP_CIPHER * +get_cipher_by_name(char *name) +{ + if (name == NULL || strcmp(name, "") == 0) + return (NULL); +#ifndef OPENSSL_NO_AES + else if (strcmp(name, "aes128") == 0) + return EVP_aes_128_cbc(); + else if (strcmp(name, "aes192") == 0) + return EVP_aes_192_cbc(); + else if (strcmp(name, "aes256") == 0) + return EVP_aes_256_cbc(); +#endif +#ifndef OPENSSL_NO_CAMELLIA + else if (strcmp(name, "camellia128") == 0) + return EVP_camellia_128_cbc(); + else if (strcmp(name, "camellia192") == 0) + return EVP_camellia_192_cbc(); + else if (strcmp(name, "camellia256") == 0) + return EVP_camellia_256_cbc(); +#endif +#ifndef OPENSSL_NO_DES + else if (strcmp(name, "des") == 0) + return EVP_des_cbc(); + else if (strcmp(name, "des3") == 0) + return EVP_des_ede3_cbc(); +#endif +#ifndef OPENSSL_NO_RC2 + else if (!strcmp(name, "rc2-40")) + return EVP_rc2_40_cbc(); + else if (!strcmp(name, "rc2-64")) + return EVP_rc2_64_cbc(); + else if (!strcmp(name, "rc2-128")) + return EVP_rc2_cbc(); +#endif + else + return (NULL); +} + +static int +cms_opt_cipher(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.cipher = get_cipher_by_name(name)) == NULL) + if ((cfg.cipher = EVP_get_cipherbyname(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static int +cms_opt_econtent_type(char *arg) +{ + ASN1_OBJECT_free(cfg.econtent_type); + + if ((cfg.econtent_type = OBJ_txt2obj(arg, 0)) == NULL) { + BIO_printf(bio_err, "Invalid OID %s\n", arg); + return (1); + } + return (0); +} + +static int +cms_opt_inkey(char *arg) +{ + if (cfg.keyfile == NULL) { + cfg.keyfile = arg; + return (0); + } + + if (cfg.signerfile == NULL) { + BIO_puts(bio_err, "Illegal -inkey without -signer\n"); + return (1); + } + + if (cfg.sksigners == NULL) + cfg.sksigners = sk_OPENSSL_STRING_new_null(); + if (cfg.sksigners == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile)) + return (1); + + cfg.signerfile = NULL; + + if (cfg.skkeys == NULL) + cfg.skkeys = sk_OPENSSL_STRING_new_null(); + if (cfg.skkeys == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile)) + return (1); + + cfg.keyfile = arg; + return (0); +} + +static int +cms_opt_keyopt(char *arg) +{ + int keyidx = -1; + + if (cfg.operation == SMIME_ENCRYPT) { + if (cfg.encerts != NULL) + keyidx += sk_X509_num(cfg.encerts); + } else { + if (cfg.keyfile != NULL || cfg.signerfile != NULL) + keyidx++; + if (cfg.skkeys != NULL) + keyidx += sk_OPENSSL_STRING_num(cfg.skkeys); + } + + if (keyidx < 0) { + BIO_printf(bio_err, "No key specified\n"); + return (1); + } + + if (cfg.key_param == NULL || + cfg.key_param->idx != keyidx) { + struct cms_key_param *nparam; + + if ((nparam = calloc(1, sizeof(struct cms_key_param))) == NULL) + return (1); + + nparam->idx = keyidx; + if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL) { + free(nparam); + return (1); + } + + nparam->next = NULL; + if (cfg.key_first == NULL) + cfg.key_first = nparam; + else + cfg.key_param->next = nparam; + + cfg.key_param = nparam; + } + + if (!sk_OPENSSL_STRING_push(cfg.key_param->param, arg)) + return (1); + + return (0); +} + +static int +cms_opt_md(char *arg) +{ + if ((cfg.sign_md = EVP_get_digestbyname(arg)) == NULL) { + BIO_printf(bio_err, "Unknown digest %s\n", arg); + return (1); + } + return (0); +} + +static int +cms_opt_print(void) +{ + cfg.noout = 1; + cfg.print = 1; + return (0); +} + +static int +cms_opt_pwri_pass(char *arg) +{ + cfg.pwri_pass = (unsigned char *)arg; + return (0); +} + +static int +cms_opt_recip(char *arg) +{ + if (cfg.operation == SMIME_ENCRYPT) { + if (cfg.encerts == NULL) { + if ((cfg.encerts = sk_X509_new_null()) == NULL) + return (1); + } + + cfg.cert = load_cert(bio_err, arg, FORMAT_PEM, + NULL, "recipient certificate file"); + if (cfg.cert == NULL) + return (1); + + if (!sk_X509_push(cfg.encerts, cfg.cert)) + return (1); + + cfg.cert = NULL; + } else { + cfg.recipfile = arg; + } + return (0); +} + +static int +cms_opt_receipt_request_from(char *arg) +{ + if (cfg.rr_from == NULL) + cfg.rr_from = sk_OPENSSL_STRING_new_null(); + if (cfg.rr_from == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.rr_from, arg)) + return (1); + + return (0); +} + +static int +cms_opt_receipt_request_to(char *arg) +{ + if (cfg.rr_to == NULL) + cfg.rr_to = sk_OPENSSL_STRING_new_null(); + if (cfg.rr_to == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.rr_to, arg)) + return (1); + + return (0); +} + +static int +cms_opt_secretkey(char *arg) +{ + long ltmp; + + free(cfg.secret_key); + + if ((cfg.secret_key = string_to_hex(arg, <mp)) == NULL) { + BIO_printf(bio_err, "Invalid key %s\n", arg); + return (1); + } + cfg.secret_keylen = (size_t)ltmp; + return (0); +} + +static int +cms_opt_secretkeyid(char *arg) +{ + long ltmp; + + free(cfg.secret_keyid); + + if ((cfg.secret_keyid = string_to_hex(arg, <mp)) == NULL) { + BIO_printf(bio_err, "Invalid id %s\n", arg); + return (1); + } + cfg.secret_keyidlen = (size_t)ltmp; + return (0); +} + +static int +cms_opt_signer(char *arg) +{ + if (cfg.signerfile == NULL) { + cfg.signerfile = arg; + return (0); + } + + if (cfg.sksigners == NULL) + cfg.sksigners = sk_OPENSSL_STRING_new_null(); + if (cfg.sksigners == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.sksigners, cfg.signerfile)) + return (1); + + if (cfg.keyfile == NULL) + cfg.keyfile = cfg.signerfile; + + if (cfg.skkeys == NULL) + cfg.skkeys = sk_OPENSSL_STRING_new_null(); + if (cfg.skkeys == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile)) + return (1); + + cfg.keyfile = NULL; + + cfg.signerfile = arg; + return (0); +} + +static int +cms_opt_verify_param(int argc, char **argv, int *argsused) +{ + int oargc = argc; + int badarg = 0; + + if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm)) + return (1); + if (badarg) + return (1); + + *argsused = oargc - argc; + + return (0); +} + +static int +cms_opt_verify_receipt(char *arg) +{ + cfg.operation = SMIME_VERIFY_RECEIPT; + cfg.rctfile = arg; + return (0); +} + +static const struct option cms_options[] = { +#ifndef OPENSSL_NO_AES + { + .name = "aes128", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "aes192", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "aes256", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { + .name = "camellia128", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "camellia192", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "camellia256", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, +#endif +#ifndef OPENSSL_NO_DES + { + .name = "des", + .desc = "Encrypt with DES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "des3", + .desc = "Encrypt with triple DES (default)", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, +#endif +#ifndef OPENSSL_NO_RC2 + { + .name = "rc2-40", + .desc = "Encrypt with RC2-40", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "rc2-64", + .desc = "Encrypt with RC2-64", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { + .name = "rc2-128", + .desc = "Encrypt with RC2-128", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, +#endif + { + .name = "CAfile", + .argname = "file", + .desc = "Certificate Authority file", + .type = OPTION_ARG, + .opt.arg = &cfg.CAfile, + }, + { + .name = "CApath", + .argname = "path", + .desc = "Certificate Authority path", + .type = OPTION_ARG, + .opt.arg = &cfg.CApath, + }, + { + .name = "binary", + .desc = "Do not translate message to text", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_BINARY, + }, + { + .name = "certfile", + .argname = "file", + .desc = "Other certificates file", + .type = OPTION_ARG, + .opt.arg = &cfg.certfile, + }, + { + .name = "certsout", + .argname = "file", + .desc = "Certificate output file", + .type = OPTION_ARG, + .opt.arg = &cfg.certsoutfile, + }, + { + .name = "cmsout", + .desc = "Output CMS structure", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_CMSOUT, + }, + { + .name = "compress", + .desc = "Create CMS CompressedData type", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_COMPRESS, + }, + { + .name = "content", + .argname = "file", + .desc = "Supply or override content for detached signature", + .type = OPTION_ARG, + .opt.arg = &cfg.contfile, + }, + { + .name = "crlfeol", + .desc = "Use CRLF as EOL termination instead of CR only", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_CRLFEOL, + }, + { + .name = "data_create", + .desc = "Create CMS Data type", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_DATA_CREATE, + }, + { + .name = "data_out", + .desc = "Output content from the input CMS Data type", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_DATAOUT, + }, + { + .name = "debug_decrypt", + .desc = "Set the CMS_DEBUG_DECRYPT flag when decrypting", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_DEBUG_DECRYPT, + }, + { + .name = "decrypt", + .desc = "Decrypt encrypted message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_DECRYPT, + }, + { + .name = "digest_create", + .desc = "Create CMS DigestedData type", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_DIGEST_CREATE, + }, + { + .name = "digest_verify", + .desc = "Verify CMS DigestedData type and output the content", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_DIGEST_VERIFY, + }, + { + .name = "econtent_type", + .argname = "type", + .desc = "Set the encapsulated content type", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_econtent_type, + }, + { + .name = "encrypt", + .desc = "Encrypt message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_ENCRYPT, + }, + { + .name = "EncryptedData_decrypt", + .desc = "Decrypt CMS EncryptedData", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_ENCRYPTED_DECRYPT, + }, + { + .name = "EncryptedData_encrypt", + .desc = "Encrypt content using supplied symmetric key and algorithm", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_ENCRYPTED_ENCRYPT, + }, + { + .name = "from", + .argname = "addr", + .desc = "From address", + .type = OPTION_ARG, + .opt.arg = &cfg.from, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "indef", + .desc = "Same as -stream", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_STREAM, + }, + { + .name = "inform", + .argname = "fmt", + .desc = "Input format (DER, PEM or SMIME (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "inkey", + .argname = "file", + .desc = "Input key file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_inkey, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Input key format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "keyid", + .desc = "Use subject key identifier", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_USE_KEYID, + }, + { + .name = "keyopt", + .argname = "nm:v", + .desc = "Set public key parameters", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_keyopt, + }, + { + .name = "md", + .argname = "digest", + .desc = "Digest to use when signing or resigning", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_md, + }, + { + .name = "no_attr_verify", + .desc = "Do not verify the signer's attribute of a signature", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NO_ATTR_VERIFY, + }, + { + .name = "no_content_verify", + .desc = "Do not verify the content of a signed message", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NO_CONTENT_VERIFY, + }, + { + .name = "no_signer_cert_verify", + .desc = "Do not verify the signer's certificate", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NO_SIGNER_CERT_VERIFY, + }, + { + .name = "noattr", + .desc = "Do not include any signed attributes", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOATTR, + }, + { + .name = "nocerts", + .desc = "Do not include signer's certificate when signing", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOCERTS, + }, + { + .name = "nodetach", + .desc = "Use opaque signing", + .type = OPTION_VALUE_AND, + .opt.value = &cfg.flags, + .value = ~CMS_DETACHED, + }, + { + .name = "noindef", + .desc = "Disable CMS streaming", + .type = OPTION_VALUE_AND, + .opt.value = &cfg.flags, + .value = ~CMS_STREAM, + }, + { + .name = "nointern", + .desc = "Do not search certificates in message for signer", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOINTERN, + }, + { + .name = "nooldmime", + .desc = "Output old S/MIME content type", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOOLDMIMETYPE, + }, + { + .name = "noout", + .desc = "Do not output the parsed CMS structure", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "nosigs", + .desc = "Do not verify message signature", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOSIGS, + }, + { + .name = "nosmimecap", + .desc = "Omit the SMIMECapabilities attribute", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NOSMIMECAP, + }, + { + .name = "noverify", + .desc = "Do not verify signer's certificate", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_NO_SIGNER_CERT_VERIFY, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "fmt", + .desc = "Output format (DER, PEM or SMIME (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "src", + .desc = "Private key password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "print", + .desc = "Print out all fields of the CMS structure for the -cmsout", + .type = OPTION_FUNC, + .opt.func = cms_opt_print, + }, + { + .name = "pwri_password", + .argname = "arg", + .desc = "Specify PasswordRecipientInfo (PWRI) password to use", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_pwri_pass, + }, + { + .name = "rctform", + .argname = "fmt", + .desc = "Receipt file format (DER, PEM or SMIME (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.rctformat, + }, + { + .name = "receipt_request_all", + .desc = "Indicate requests should be provided by all recipients", + .type = OPTION_VALUE, + .opt.value = &cfg.rr_allorfirst, + .value = 0, + }, + { + .name = "receipt_request_first", + .desc = "Indicate requests should be provided by first tier recipient", + .type = OPTION_VALUE, + .opt.value = &cfg.rr_allorfirst, + .value = 1, + }, + { + .name = "receipt_request_from", + .argname = "addr", + .desc = "Add explicit email address where receipts should be supplied", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_receipt_request_from, + }, + { + .name = "receipt_request_print", + .desc = "Print out the contents of any signed receipt requests", + .type = OPTION_FLAG, + .opt.flag = &cfg.rr_print, + }, + { + .name = "receipt_request_to", + .argname = "addr", + .desc = "Add explicit email address where receipts should be sent to", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_receipt_request_to, + }, + { + .name = "recip", + .argname = "file", + .desc = "Recipient certificate file for decryption", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_recip, + }, + { + .name = "resign", + .desc = "Resign a signed message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_RESIGN, + }, + { + .name = "secretkey", + .argname = "key", + .desc = "Specify symmetric key to use", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_secretkey, + }, + { + .name = "secretkeyid", + .argname = "id", + .desc = "The key identifier for the supplied symmetric key", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_secretkeyid, + }, + { + .name = "sign", + .desc = "Sign message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_SIGN, + }, + { + .name = "sign_receipt", + .desc = "Generate a signed receipt for the message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_SIGN_RECEIPT, + }, + { + .name = "signer", + .argname = "file", + .desc = "Signer certificate file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_signer, + }, + { + .name = "stream", + .desc = "Enable CMS streaming", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_STREAM, + }, + { + .name = "subject", + .argname = "s", + .desc = "Subject", + .type = OPTION_ARG, + .opt.arg = &cfg.subject, + }, + { + .name = "text", + .desc = "Include or delete text MIME headers", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.flags, + .value = CMS_TEXT, + }, + { + .name = "to", + .argname = "addr", + .desc = "To address", + .type = OPTION_ARG, + .opt.arg = &cfg.to, + }, + { + .name = "uncompress", + .desc = "Uncompress CMS CompressedData type", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_UNCOMPRESS, + }, + { + .name = "verify", + .desc = "Verify signed message", + .type = OPTION_VALUE, + .opt.value = &cfg.operation, + .value = SMIME_VERIFY, + }, + { + .name = "verify_receipt", + .argname = "file", + .desc = "Verify a signed receipt in file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = cms_opt_verify_receipt, + }, + { + .name = "verify_retcode", + .desc = "Set verification error code to exit code", + .type = OPTION_FLAG, + .opt.flag = &cfg.verify_retcode, + }, + { + .name = "check_ss_sig", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "crl_check", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "crl_check_all", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "extended_crl", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "ignore_critical", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "issuer_checks", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "policy", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "policy_check", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "purpose", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = "x509_strict", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_verify_param, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = cms_opt_cipher, + }, + { NULL }, +}; + +static const struct option verify_shared_options[] = { + { + .name = "check_ss_sig", + .desc = "Check the root CA self-signed certificate signature", + }, + { + .name = "crl_check", + .desc = "Enable CRL checking for the leaf certificate", + }, + { + .name = "crl_check_all", + .desc = "Enable CRL checking for the entire certificate chain", + }, + { + .name = "extended_crl", + .desc = "Enable extended CRL support", + }, + { + .name = "ignore_critical", + .desc = "Disable critical extension checking", + }, + { + .name = "issuer_checks", + .desc = "Enable debugging of certificate issuer checks", + }, + { + .name = "policy", + .argname = "name", + .desc = "Add given policy to the acceptable set", + }, + { + .name = "policy_check", + .desc = "Enable certificate policy checking", + }, + { + .name = "purpose", + .argname = "name", + .desc = "Verify for the given purpose", + }, + { + .name = "x509_strict", + .desc = "Use strict X.509 rules (disables workarounds)", + }, + { NULL }, +}; + +static void +cms_usage(void) +{ + int i; + + fprintf(stderr, "usage: cms " + "[-aes128 | -aes192 | -aes256 | -camellia128 |\n" + " -camellia192 | -camellia256 | -des | -des3 |\n" + " -rc2-40 | -rc2-64 | -rc2-128] [-CAfile file]\n" + " [-CApath directory] [-binary] [-certfile file]\n" + " [-certsout file] [-cmsout] [-compress] [-content file]\n" + " [-crlfeol] [-data_create] [-data_out] [-debug_decrypt]\n" + " [-decrypt] [-digest_create] [-digest_verify]\n" + " [-econtent_type type] [-encrypt] [-EncryptedData_decrypt]\n" + " [-EncryptedData_encrypt] [-from addr] [-in file]\n" + " [-inform der | pem | smime] [-inkey file]\n" + " [-keyform der | pem] [-keyid] [-keyopt nm:v] [-md digest]\n" + " [-no_attr_verify] [-no_content_verify]\n" + " [-no_signer_cert_verify] [-noattr] [-nocerts] [-nodetach]\n" + " [-nointern] [-nooldmime] [-noout] [-nosigs] [-nosmimecap]\n" + " [-noverify] [-out file] [-outform der | pem | smime]\n" + " [-passin src] [-print] [-pwri_password arg]\n" + " [-rctform der | pem | smime]\n" + " [-receipt_request_all | -receipt_request_first]\n" + " [-receipt_request_from addr] [-receipt_request_print]\n" + " [-receipt_request_to addr] [-recip file] [-resign]\n" + " [-secretkey key] [-secretkeyid id] [-sign] [-sign_receipt]\n" + " [-signer file] [-stream | -indef | -noindef] [-subject s]\n" + " [-text] [-to addr] [-uncompress] [-verify]\n" + " [-verify_receipt file] [-verify_retcode] [cert.pem ...]\n\n"); + + options_usage(cms_options); + + fprintf(stderr, "\nVerification options:\n\n"); + options_usage(verify_shared_options); + + fprintf(stderr, "\nValid purposes:\n\n"); + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + X509_PURPOSE *ptmp = X509_PURPOSE_get0(i); + fprintf(stderr, " %-18s%s\n", X509_PURPOSE_get0_sname(ptmp), + X509_PURPOSE_get0_name(ptmp)); + } +} + +int +cms_main(int argc, char **argv) +{ + int ret = 0; + char **args; + int argsused = 0; + const char *inmode = "r", *outmode = "w"; + CMS_ContentInfo *cms = NULL, *rcms = NULL; + X509_STORE *store = NULL; + X509 *recip = NULL, *signer = NULL; + EVP_PKEY *key = NULL; + STACK_OF(X509) *other = NULL; + BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL; + int badarg = 0; + CMS_ReceiptRequest *rr = NULL; + char *passin = NULL; + unsigned char *pwri_tmp = NULL; + + if (pledge("stdio rpath wpath cpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.flags = CMS_DETACHED; + cfg.rr_allorfirst = -1; + cfg.informat = FORMAT_SMIME; + cfg.outformat = FORMAT_SMIME; + cfg.rctformat = FORMAT_SMIME; + cfg.keyform = FORMAT_PEM; + if (options_parse(argc, argv, cms_options, NULL, &argsused) != 0) { + goto argerr; + } + args = argv + argsused; + ret = 1; + + if (((cfg.rr_allorfirst != -1) || cfg.rr_from != NULL) && + cfg.rr_to == NULL) { + BIO_puts(bio_err, "No Signed Receipts Recipients\n"); + goto argerr; + } + if (!(cfg.operation & SMIME_SIGNERS) && + (cfg.rr_to != NULL || cfg.rr_from != NULL)) { + BIO_puts(bio_err, "Signed receipts only allowed with -sign\n"); + goto argerr; + } + if (!(cfg.operation & SMIME_SIGNERS) && + (cfg.skkeys != NULL || cfg.sksigners != NULL)) { + BIO_puts(bio_err, "Multiple signers or keys not allowed\n"); + goto argerr; + } + if (cfg.operation & SMIME_SIGNERS) { + if (cfg.keyfile != NULL && + cfg.signerfile == NULL) { + BIO_puts(bio_err, "Illegal -inkey without -signer\n"); + goto argerr; + } + /* Check to see if any final signer needs to be appended */ + if (cfg.signerfile != NULL) { + if (cfg.sksigners == NULL && + (cfg.sksigners = + sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (!sk_OPENSSL_STRING_push(cfg.sksigners, + cfg.signerfile)) + goto end; + if (cfg.skkeys == NULL && + (cfg.skkeys = + sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + if (cfg.keyfile == NULL) + cfg.keyfile = cfg.signerfile; + if (!sk_OPENSSL_STRING_push(cfg.skkeys, + cfg.keyfile)) + goto end; + } + if (cfg.sksigners == NULL) { + BIO_printf(bio_err, + "No signer certificate specified\n"); + badarg = 1; + } + cfg.signerfile = NULL; + cfg.keyfile = NULL; + } else if (cfg.operation == SMIME_DECRYPT) { + if (cfg.recipfile == NULL && + cfg.keyfile == NULL && + cfg.secret_key == NULL && + cfg.pwri_pass == NULL) { + BIO_printf(bio_err, + "No recipient certificate or key specified\n"); + badarg = 1; + } + } else if (cfg.operation == SMIME_ENCRYPT) { + if (*args == NULL && cfg.secret_key == NULL && + cfg.pwri_pass == NULL && + cfg.encerts == NULL) { + BIO_printf(bio_err, + "No recipient(s) certificate(s) specified\n"); + badarg = 1; + } + } else if (!cfg.operation) { + badarg = 1; + } + + if (badarg) { + argerr: + cms_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + ret = 2; + + if (!(cfg.operation & SMIME_SIGNERS)) + cfg.flags &= ~CMS_DETACHED; + + if (cfg.operation & SMIME_OP) { + if (cfg.outformat == FORMAT_ASN1) + outmode = "wb"; + } else { + if (cfg.flags & CMS_BINARY) + outmode = "wb"; + } + + if (cfg.operation & SMIME_IP) { + if (cfg.informat == FORMAT_ASN1) + inmode = "rb"; + } else { + if (cfg.flags & CMS_BINARY) + inmode = "rb"; + } + + if (cfg.operation == SMIME_ENCRYPT) { + if (cfg.cipher == NULL) { +#ifndef OPENSSL_NO_DES + cfg.cipher = EVP_des_ede3_cbc(); +#else + BIO_printf(bio_err, "No cipher selected\n"); + goto end; +#endif + } + if (cfg.secret_key != NULL && + cfg.secret_keyid == NULL) { + BIO_printf(bio_err, "No secret key id\n"); + goto end; + } + if (*args != NULL && cfg.encerts == NULL) + if ((cfg.encerts = sk_X509_new_null()) == NULL) + goto end; + while (*args) { + if ((cfg.cert = load_cert(bio_err, *args, + FORMAT_PEM, NULL, + "recipient certificate file")) == NULL) + goto end; + if (!sk_X509_push(cfg.encerts, cfg.cert)) + goto end; + cfg.cert = NULL; + args++; + } + } + if (cfg.certfile != NULL) { + if ((other = load_certs(bio_err, cfg.certfile, + FORMAT_PEM, NULL, "certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.recipfile != NULL && + (cfg.operation == SMIME_DECRYPT)) { + if ((recip = load_cert(bio_err, cfg.recipfile, + FORMAT_PEM, NULL, "recipient certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.operation == SMIME_SIGN_RECEIPT) { + if ((signer = load_cert(bio_err, cfg.signerfile, + FORMAT_PEM, NULL, + "receipt signer certificate file")) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.operation == SMIME_DECRYPT) { + if (cfg.keyfile == NULL) + cfg.keyfile = cfg.recipfile; + } else if ((cfg.operation == SMIME_SIGN) || + (cfg.operation == SMIME_SIGN_RECEIPT)) { + if (cfg.keyfile == NULL) + cfg.keyfile = cfg.signerfile; + } else { + cfg.keyfile = NULL; + } + + if (cfg.keyfile != NULL) { + key = load_key(bio_err, cfg.keyfile, cfg.keyform, + 0, passin, "signing key file"); + if (key == NULL) + goto end; + } + if (cfg.infile != NULL) { + if ((in = BIO_new_file(cfg.infile, inmode)) == NULL) { + BIO_printf(bio_err, + "Can't open input file %s\n", cfg.infile); + goto end; + } + } else { + if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL) + goto end; + } + + if (cfg.operation & SMIME_IP) { + if (cfg.informat == FORMAT_SMIME) + cms = SMIME_read_CMS(in, &indata); + else if (cfg.informat == FORMAT_PEM) + cms = PEM_read_bio_CMS(in, NULL, NULL, NULL); + else if (cfg.informat == FORMAT_ASN1) + cms = d2i_CMS_bio(in, NULL); + else { + BIO_printf(bio_err, "Bad input format for CMS file\n"); + goto end; + } + + if (cms == NULL) { + BIO_printf(bio_err, "Error reading S/MIME message\n"); + goto end; + } + if (cfg.contfile != NULL) { + BIO_free(indata); + if ((indata = BIO_new_file(cfg.contfile, + "rb")) == NULL) { + BIO_printf(bio_err, + "Can't read content file %s\n", + cfg.contfile); + goto end; + } + } + if (cfg.certsoutfile != NULL) { + STACK_OF(X509) *allcerts; + if ((allcerts = CMS_get1_certs(cms)) == NULL) + goto end; + if (!save_certs(cfg.certsoutfile, allcerts)) { + BIO_printf(bio_err, + "Error writing certs to %s\n", + cfg.certsoutfile); + sk_X509_pop_free(allcerts, X509_free); + ret = 5; + goto end; + } + sk_X509_pop_free(allcerts, X509_free); + } + } + if (cfg.rctfile != NULL) { + char *rctmode = (cfg.rctformat == FORMAT_ASN1) ? + "rb" : "r"; + if ((rctin = BIO_new_file(cfg.rctfile, rctmode)) == NULL) { + BIO_printf(bio_err, + "Can't open receipt file %s\n", cfg.rctfile); + goto end; + } + if (cfg.rctformat == FORMAT_SMIME) + rcms = SMIME_read_CMS(rctin, NULL); + else if (cfg.rctformat == FORMAT_PEM) + rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL); + else if (cfg.rctformat == FORMAT_ASN1) + rcms = d2i_CMS_bio(rctin, NULL); + else { + BIO_printf(bio_err, "Bad input format for receipt\n"); + goto end; + } + + if (rcms == NULL) { + BIO_printf(bio_err, "Error reading receipt\n"); + goto end; + } + } + if (cfg.outfile != NULL) { + if ((out = BIO_new_file(cfg.outfile, outmode)) == NULL) { + BIO_printf(bio_err, + "Can't open output file %s\n", cfg.outfile); + goto end; + } + } else { + if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) + goto end; + } + + if ((cfg.operation == SMIME_VERIFY) || + (cfg.operation == SMIME_VERIFY_RECEIPT)) { + if ((store = setup_verify(bio_err, cfg.CAfile, + cfg.CApath)) == NULL) + goto end; + if (cfg.vpm != NULL) { + if (!X509_STORE_set1_param(store, cfg.vpm)) + goto end; + } + } + ret = 3; + + if (cfg.operation == SMIME_DATA_CREATE) { + cms = CMS_data_create(in, cfg.flags); + } else if (cfg.operation == SMIME_DIGEST_CREATE) { + cms = CMS_digest_create(in, cfg.sign_md, + cfg.flags); + } else if (cfg.operation == SMIME_COMPRESS) { + cms = CMS_compress(in, -1, cfg.flags); + } else if (cfg.operation == SMIME_ENCRYPT) { + int i; + cfg.flags |= CMS_PARTIAL; + cms = CMS_encrypt(NULL, in, cfg.cipher, + cfg.flags); + if (cms == NULL) + goto end; + for (i = 0; i < sk_X509_num(cfg.encerts); i++) { + CMS_RecipientInfo *ri; + struct cms_key_param *kparam; + int tflags = cfg.flags; + X509 *x; + + if ((x = sk_X509_value(cfg.encerts, i)) == NULL) + goto end; + for (kparam = cfg.key_first; kparam != NULL; + kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + ri = CMS_add1_recipient_cert(cms, x, tflags); + if (ri == NULL) + goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + if ((pctx = CMS_RecipientInfo_get0_pkey_ctx( + ri)) == NULL) + goto end; + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } + } + + if (cfg.secret_key != NULL) { + if (CMS_add0_recipient_key(cms, NID_undef, + cfg.secret_key, cfg.secret_keylen, + cfg.secret_keyid, cfg.secret_keyidlen, + NULL, NULL, NULL) == NULL) + goto end; + /* NULL these because call absorbs them */ + cfg.secret_key = NULL; + cfg.secret_keyid = NULL; + } + if (cfg.pwri_pass != NULL) { + pwri_tmp = strdup(cfg.pwri_pass); + if (pwri_tmp == NULL) + goto end; + if (CMS_add0_recipient_password(cms, -1, NID_undef, + NID_undef, pwri_tmp, -1, NULL) == NULL) + goto end; + pwri_tmp = NULL; + } + if (!(cfg.flags & CMS_STREAM)) { + if (!CMS_final(cms, in, NULL, cfg.flags)) + goto end; + } + } else if (cfg.operation == SMIME_ENCRYPTED_ENCRYPT) { + cms = CMS_EncryptedData_encrypt(in, cfg.cipher, + cfg.secret_key, cfg.secret_keylen, + cfg.flags); + + } else if (cfg.operation == SMIME_SIGN_RECEIPT) { + CMS_ContentInfo *srcms = NULL; + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + sis = CMS_get0_SignerInfos(cms); + if (sis == NULL) + goto end; + si = sk_CMS_SignerInfo_value(sis, 0); + if (si == NULL) + goto end; + srcms = CMS_sign_receipt(si, signer, key, other, + cfg.flags); + if (srcms == NULL) + goto end; + CMS_ContentInfo_free(cms); + cms = srcms; + } else if (cfg.operation & SMIME_SIGNERS) { + int i; + /* + * If detached data content we enable streaming if S/MIME + * output format. + */ + if (cfg.operation == SMIME_SIGN) { + + if (cfg.flags & CMS_DETACHED) { + if (cfg.outformat == FORMAT_SMIME) + cfg.flags |= CMS_STREAM; + } + cfg.flags |= CMS_PARTIAL; + cms = CMS_sign(NULL, NULL, other, in, cfg.flags); + if (cms == NULL) + goto end; + if (cfg.econtent_type != NULL) + if (!CMS_set1_eContentType(cms, + cfg.econtent_type)) + goto end; + + if (cfg.rr_to != NULL) { + rr = make_receipt_request(cfg.rr_to, + cfg.rr_allorfirst, + cfg.rr_from); + if (rr == NULL) { + BIO_puts(bio_err, + "Signed Receipt Request Creation Error\n"); + goto end; + } + } + } else { + cfg.flags |= CMS_REUSE_DIGEST; + } + + for (i = 0; i < sk_OPENSSL_STRING_num(cfg.sksigners); i++) { + CMS_SignerInfo *si; + struct cms_key_param *kparam; + int tflags = cfg.flags; + + cfg.signerfile = sk_OPENSSL_STRING_value( + cfg.sksigners, i); + cfg.keyfile = sk_OPENSSL_STRING_value( + cfg.skkeys, i); + + signer = load_cert(bio_err, cfg.signerfile, + FORMAT_PEM, NULL, "signer certificate"); + if (signer == NULL) + goto end; + key = load_key(bio_err, cfg.keyfile, + cfg.keyform, 0, passin, "signing key file"); + if (key == NULL) + goto end; + for (kparam = cfg.key_first; kparam != NULL; + kparam = kparam->next) { + if (kparam->idx == i) { + tflags |= CMS_KEY_PARAM; + break; + } + } + si = CMS_add1_signer(cms, signer, key, + cfg.sign_md, tflags); + if (si == NULL) + goto end; + if (kparam != NULL) { + EVP_PKEY_CTX *pctx; + if ((pctx = CMS_SignerInfo_get0_pkey_ctx( + si)) == NULL) + goto end; + if (!cms_set_pkey_param(pctx, kparam->param)) + goto end; + } + if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr)) + goto end; + X509_free(signer); + signer = NULL; + EVP_PKEY_free(key); + key = NULL; + } + /* If not streaming or resigning finalize structure */ + if ((cfg.operation == SMIME_SIGN) && + !(cfg.flags & CMS_STREAM)) { + if (!CMS_final(cms, in, NULL, cfg.flags)) + goto end; + } + } + if (cms == NULL) { + BIO_printf(bio_err, "Error creating CMS structure\n"); + goto end; + } + ret = 4; + if (cfg.operation == SMIME_DECRYPT) { + if (cfg.flags & CMS_DEBUG_DECRYPT) + CMS_decrypt(cms, NULL, NULL, NULL, NULL, + cfg.flags); + + if (cfg.secret_key != NULL) { + if (!CMS_decrypt_set1_key(cms, cfg.secret_key, + cfg.secret_keylen, cfg.secret_keyid, + cfg.secret_keyidlen)) { + BIO_puts(bio_err, + "Error decrypting CMS using secret key\n"); + goto end; + } + } + if (key != NULL) { + if (!CMS_decrypt_set1_pkey(cms, key, recip)) { + BIO_puts(bio_err, + "Error decrypting CMS using private key\n"); + goto end; + } + } + if (cfg.pwri_pass != NULL) { + if (!CMS_decrypt_set1_password(cms, + cfg.pwri_pass, -1)) { + BIO_puts(bio_err, + "Error decrypting CMS using password\n"); + goto end; + } + } + if (!CMS_decrypt(cms, NULL, NULL, indata, out, + cfg.flags)) { + BIO_printf(bio_err, "Error decrypting CMS structure\n"); + goto end; + } + } else if (cfg.operation == SMIME_DATAOUT) { + if (!CMS_data(cms, out, cfg.flags)) + goto end; + } else if (cfg.operation == SMIME_UNCOMPRESS) { + if (!CMS_uncompress(cms, indata, out, cfg.flags)) + goto end; + } else if (cfg.operation == SMIME_DIGEST_VERIFY) { + if (CMS_digest_verify(cms, indata, out, cfg.flags) > 0) + BIO_printf(bio_err, "Verification successful\n"); + else { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } + } else if (cfg.operation == SMIME_ENCRYPTED_DECRYPT) { + if (!CMS_EncryptedData_decrypt(cms, cfg.secret_key, + cfg.secret_keylen, indata, out, cfg.flags)) + goto end; + } else if (cfg.operation == SMIME_VERIFY) { + if (CMS_verify(cms, other, store, indata, out, + cfg.flags) > 0) { + BIO_printf(bio_err, "Verification successful\n"); + } else { + BIO_printf(bio_err, "Verification failure\n"); + if (cfg.verify_retcode) + ret = verify_err + 32; + goto end; + } + if (cfg.signerfile != NULL) { + STACK_OF(X509) *signers; + if ((signers = CMS_get0_signers(cms)) == NULL) + goto end; + if (!save_certs(cfg.signerfile, signers)) { + BIO_printf(bio_err, + "Error writing signers to %s\n", + cfg.signerfile); + sk_X509_free(signers); + ret = 5; + goto end; + } + sk_X509_free(signers); + } + if (cfg.rr_print) + receipt_request_print(bio_err, cms); + + } else if (cfg.operation == SMIME_VERIFY_RECEIPT) { + if (CMS_verify_receipt(rcms, cms, other, store, + cfg.flags) > 0) { + BIO_printf(bio_err, "Verification successful\n"); + } else { + BIO_printf(bio_err, "Verification failure\n"); + goto end; + } + } else { + if (cfg.noout) { + if (cfg.print && + !CMS_ContentInfo_print_ctx(out, cms, 0, NULL)) + goto end; + } else if (cfg.outformat == FORMAT_SMIME) { + if (cfg.to != NULL) + BIO_printf(out, "To: %s\n", cfg.to); + if (cfg.from != NULL) + BIO_printf(out, "From: %s\n", cfg.from); + if (cfg.subject != NULL) + BIO_printf(out, "Subject: %s\n", + cfg.subject); + if (cfg.operation == SMIME_RESIGN) + ret = SMIME_write_CMS(out, cms, indata, + cfg.flags); + else + ret = SMIME_write_CMS(out, cms, in, + cfg.flags); + } else if (cfg.outformat == FORMAT_PEM) { + ret = PEM_write_bio_CMS_stream(out, cms, in, + cfg.flags); + } else if (cfg.outformat == FORMAT_ASN1) { + ret = i2d_CMS_bio_stream(out, cms, in, cfg.flags); + } else { + BIO_printf(bio_err, "Bad output format for CMS file\n"); + goto end; + } + if (ret <= 0) { + ret = 6; + goto end; + } + } + ret = 0; + + end: + if (ret) + ERR_print_errors(bio_err); + + sk_X509_pop_free(cfg.encerts, X509_free); + sk_X509_pop_free(other, X509_free); + X509_VERIFY_PARAM_free(cfg.vpm); + sk_OPENSSL_STRING_free(cfg.sksigners); + sk_OPENSSL_STRING_free(cfg.skkeys); + free(cfg.secret_key); + free(cfg.secret_keyid); + free(pwri_tmp); + ASN1_OBJECT_free(cfg.econtent_type); + CMS_ReceiptRequest_free(rr); + sk_OPENSSL_STRING_free(cfg.rr_to); + sk_OPENSSL_STRING_free(cfg.rr_from); + for (cfg.key_param = cfg.key_first; cfg.key_param;) { + struct cms_key_param *tparam; + sk_OPENSSL_STRING_free(cfg.key_param->param); + tparam = cfg.key_param->next; + free(cfg.key_param); + cfg.key_param = tparam; + } + X509_STORE_free(store); + X509_free(cfg.cert); + X509_free(recip); + X509_free(signer); + EVP_PKEY_free(key); + CMS_ContentInfo_free(cms); + CMS_ContentInfo_free(rcms); + BIO_free(rctin); + BIO_free(in); + BIO_free(indata); + BIO_free_all(out); + free(passin); + + return (ret); +} + +static int +save_certs(char *signerfile, STACK_OF(X509) *signers) +{ + int i; + BIO *tmp; + + if (signerfile == NULL) + return 1; + tmp = BIO_new_file(signerfile, "w"); + if (tmp == NULL) + return 0; + for (i = 0; i < sk_X509_num(signers); i++) + PEM_write_bio_X509(tmp, sk_X509_value(signers, i)); + BIO_free(tmp); + return 1; +} + +static void +gnames_stack_print(BIO *out, STACK_OF(GENERAL_NAMES) *gns) +{ + STACK_OF(GENERAL_NAME) *gens; + GENERAL_NAME *gen; + int i, j; + + for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) { + gens = sk_GENERAL_NAMES_value(gns, i); + for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) { + gen = sk_GENERAL_NAME_value(gens, j); + BIO_puts(out, " "); + GENERAL_NAME_print(out, gen); + BIO_puts(out, "\n"); + } + } + return; +} + +static void +receipt_request_print(BIO *out, CMS_ContentInfo *cms) +{ + STACK_OF(CMS_SignerInfo) *sis; + CMS_SignerInfo *si; + CMS_ReceiptRequest *rr; + int allorfirst; + STACK_OF(GENERAL_NAMES) *rto, *rlist; + ASN1_STRING *scid; + int i, rv; + + if ((sis = CMS_get0_SignerInfos(cms)) == NULL) + return; + for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) { + if ((si = sk_CMS_SignerInfo_value(sis, i)) == NULL) + return; + rv = CMS_get1_ReceiptRequest(si, &rr); + BIO_printf(bio_err, "Signer %d:\n", i + 1); + if (rv == 0) { + BIO_puts(bio_err, " No Receipt Request\n"); + } else if (rv < 0) { + BIO_puts(bio_err, " Receipt Request Parse Error\n"); + ERR_print_errors(bio_err); + } else { + char *id; + int idlen; + + CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst, + &rlist, &rto); + BIO_puts(out, " Signed Content ID:\n"); + idlen = ASN1_STRING_length(scid); + id = (char *) ASN1_STRING_data(scid); + BIO_dump_indent(out, id, idlen, 4); + BIO_puts(out, " Receipts From"); + if (rlist != NULL) { + BIO_puts(out, " List:\n"); + gnames_stack_print(out, rlist); + } else if (allorfirst == 1) { + BIO_puts(out, ": First Tier\n"); + } else if (allorfirst == 0) { + BIO_puts(out, ": All\n"); + } else { + BIO_printf(out, " Unknown (%d)\n", allorfirst); + } + BIO_puts(out, " Receipts To:\n"); + gnames_stack_print(out, rto); + } + CMS_ReceiptRequest_free(rr); + } +} + +static STACK_OF(GENERAL_NAMES) * +make_names_stack(STACK_OF(OPENSSL_STRING) *ns) +{ + int i; + STACK_OF(GENERAL_NAMES) *ret; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + + if ((ret = sk_GENERAL_NAMES_new_null()) == NULL) + goto err; + for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) { + char *str = sk_OPENSSL_STRING_value(ns, i); + gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0); + if (gen == NULL) + goto err; + gens = GENERAL_NAMES_new(); + if (gens == NULL) + goto err; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto err; + gen = NULL; + if (!sk_GENERAL_NAMES_push(ret, gens)) + goto err; + gens = NULL; + } + + return ret; + + err: + sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free); + GENERAL_NAMES_free(gens); + GENERAL_NAME_free(gen); + + return NULL; +} + + +static CMS_ReceiptRequest * +make_receipt_request(STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst, + STACK_OF(OPENSSL_STRING) *rr_from) +{ + STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL; + CMS_ReceiptRequest *rr; + + rct_to = make_names_stack(rr_to); + if (rct_to == NULL) + goto err; + if (rr_from != NULL) { + rct_from = make_names_stack(rr_from); + if (rct_from == NULL) + goto err; + } else { + rct_from = NULL; + } + + if ((rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from, + rct_to)) == NULL) + goto err; + + return rr; + + err: + sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free); + sk_GENERAL_NAMES_pop_free(rct_from, GENERAL_NAMES_free); + return NULL; +} + +static int +cms_set_pkey_param(EVP_PKEY_CTX *pctx, STACK_OF(OPENSSL_STRING) *param) +{ + char *keyopt; + int i; + + if (sk_OPENSSL_STRING_num(param) <= 0) + return 1; + for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) { + keyopt = sk_OPENSSL_STRING_value(param, i); + if (pkey_ctrl_string(pctx, keyopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt); + ERR_print_errors(bio_err); + return 0; + } + } + return 1; +} + +#endif diff --git a/apps/openssl/crl.c b/apps/openssl/crl.c new file mode 100644 index 0000000..e64038d --- /dev/null +++ b/apps/openssl/crl.c @@ -0,0 +1,482 @@ +/* $OpenBSD: crl.c,v 1.17 2023/03/06 14:32:05 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include + +static struct { + char *cafile; + char *capath; + int crlnumber; + int fingerprint; + int hash; + int hash_old; + char *infile; + int informat; + int issuer; + int lastupdate; + char *nameopt; + int nextupdate; + int noout; + char *outfile; + int outformat; + int text; + int verify; +} cfg; + +static const struct option crl_options[] = { + { + .name = "CAfile", + .argname = "file", + .desc = "Verify the CRL using certificates in the given file", + .type = OPTION_ARG, + .opt.arg = &cfg.cafile, + }, + { + .name = "CApath", + .argname = "path", + .desc = "Verify the CRL using certificates in the given path", + .type = OPTION_ARG, + .opt.arg = &cfg.capath, + }, + { + .name = "crlnumber", + .desc = "Print the CRL number", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.crlnumber, + }, + { + .name = "fingerprint", + .desc = "Print the CRL fingerprint", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.fingerprint, + }, + { + .name = "hash", + .desc = "Print the hash of the issuer name", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.hash, + }, + { + .name = "hash_old", + .desc = "Print an old-style (MD5) hash of the issuer name", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.hash_old, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file to read from (stdin if unspecified)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "issuer", + .desc = "Print the issuer name", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.issuer, + }, + { + .name = "lastupdate", + .desc = "Print the lastUpdate field", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.lastupdate, + }, + { + .name = "nameopt", + .argname = "options", + .desc = "Specify certificate name options", + .type = OPTION_ARG, + .opt.arg = &cfg.nameopt, + }, + { + .name = "nextupdate", + .desc = "Print the nextUpdate field", + .type = OPTION_FLAG_ORD, + .opt.flag = &cfg.nextupdate, + }, + { + .name = "noout", + .desc = "Do not output the encoded version of the CRL", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file to write to (stdout if unspecified)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "text", + .desc = "Print out the CRL in text form", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = "verify", + .desc = "Verify the signature on the CRL", + .type = OPTION_FLAG, + .opt.flag = &cfg.verify, + }, + {NULL}, +}; + +static void +crl_usage(void) +{ + fprintf(stderr, + "usage: crl [-CAfile file] [-CApath dir] [-fingerprint] [-hash]\n" + " [-in file] [-inform DER | PEM] [-issuer] [-lastupdate]\n" + " [-nextupdate] [-noout] [-out file] [-outform DER | PEM]\n" + " [-text]\n\n"); + options_usage(crl_options); +} + +static X509_CRL *load_crl(char *file, int format); +static BIO *bio_out = NULL; + +int +crl_main(int argc, char **argv) +{ + unsigned long nmflag = 0; + X509_CRL *x = NULL; + int ret = 1, i; + BIO *out = NULL; + X509_STORE *store = NULL; + X509_STORE_CTX *ctx = NULL; + X509_LOOKUP *lookup = NULL; + X509_OBJECT *xobj = NULL; + EVP_PKEY *pkey; + const EVP_MD *digest; + char *digest_name = NULL; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + if (bio_out == NULL) { + if ((bio_out = BIO_new(BIO_s_file())) != NULL) { + BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); + } + } + + digest = EVP_sha256(); + + memset(&cfg, 0, sizeof(cfg)); + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, crl_options, &digest_name, NULL) != 0) { + crl_usage(); + goto end; + } + + if (cfg.cafile != NULL || cfg.capath != NULL) + cfg.verify = 1; + + if (cfg.nameopt != NULL) { + if (set_name_ex(&nmflag, cfg.nameopt) != 1) { + fprintf(stderr, + "Invalid -nameopt argument '%s'\n", + cfg.nameopt); + goto end; + } + } + + if (digest_name != NULL) { + if ((digest = EVP_get_digestbyname(digest_name)) == NULL) { + fprintf(stderr, + "Unknown message digest algorithm '%s'\n", + digest_name); + goto end; + } + } + + x = load_crl(cfg.infile, cfg.informat); + if (x == NULL) + goto end; + + if (cfg.verify) { + store = X509_STORE_new(); + if (store == NULL) + goto end; + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + goto end; + if (!X509_LOOKUP_load_file(lookup, cfg.cafile, + X509_FILETYPE_PEM)) + X509_LOOKUP_load_file(lookup, NULL, + X509_FILETYPE_DEFAULT); + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + goto end; + if (!X509_LOOKUP_add_dir(lookup, cfg.capath, + X509_FILETYPE_PEM)) + X509_LOOKUP_add_dir(lookup, NULL, + X509_FILETYPE_DEFAULT); + ERR_clear_error(); + + if ((ctx = X509_STORE_CTX_new()) == NULL) + goto end; + if ((xobj = X509_OBJECT_new()) == NULL) + goto end; + + if (!X509_STORE_CTX_init(ctx, store, NULL, NULL)) { + BIO_printf(bio_err, + "Error initialising X509 store\n"); + goto end; + } + i = X509_STORE_get_by_subject(ctx, X509_LU_X509, + X509_CRL_get_issuer(x), xobj); + if (i <= 0) { + BIO_printf(bio_err, + "Error getting CRL issuer certificate\n"); + goto end; + } + pkey = X509_get_pubkey(X509_OBJECT_get0_X509(xobj)); + X509_OBJECT_free(xobj); + xobj = NULL; + if (!pkey) { + BIO_printf(bio_err, + "Error getting CRL issuer public key\n"); + goto end; + } + i = X509_CRL_verify(x, pkey); + EVP_PKEY_free(pkey); + if (i < 0) + goto end; + if (i == 0) + BIO_printf(bio_err, "verify failure\n"); + else + BIO_printf(bio_err, "verify OK\n"); + } + + /* Print requested information the order that the flags were given. */ + for (i = 1; i <= argc; i++) { + if (cfg.issuer == i) { + print_name(bio_out, "issuer=", + X509_CRL_get_issuer(x), nmflag); + } + if (cfg.crlnumber == i) { + ASN1_INTEGER *crlnum; + crlnum = X509_CRL_get_ext_d2i(x, + NID_crl_number, NULL, NULL); + BIO_printf(bio_out, "crlNumber="); + if (crlnum) { + i2a_ASN1_INTEGER(bio_out, crlnum); + ASN1_INTEGER_free(crlnum); + } else + BIO_puts(bio_out, ""); + BIO_printf(bio_out, "\n"); + } + if (cfg.hash == i) { + BIO_printf(bio_out, "%08lx\n", + X509_NAME_hash(X509_CRL_get_issuer(x))); + } +#ifndef OPENSSL_NO_MD5 + if (cfg.hash_old == i) { + BIO_printf(bio_out, "%08lx\n", + X509_NAME_hash_old(X509_CRL_get_issuer(x))); + } +#endif + if (cfg.lastupdate == i) { + BIO_printf(bio_out, "lastUpdate="); + ASN1_TIME_print(bio_out, + X509_CRL_get_lastUpdate(x)); + BIO_printf(bio_out, "\n"); + } + if (cfg.nextupdate == i) { + BIO_printf(bio_out, "nextUpdate="); + if (X509_CRL_get_nextUpdate(x)) + ASN1_TIME_print(bio_out, + X509_CRL_get_nextUpdate(x)); + else + BIO_printf(bio_out, "NONE"); + BIO_printf(bio_out, "\n"); + } + if (cfg.fingerprint == i) { + int j; + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + + if (!X509_CRL_digest(x, digest, md, &n)) { + BIO_printf(bio_err, "out of memory\n"); + goto end; + } + BIO_printf(bio_out, "%s Fingerprint=", + OBJ_nid2sn(EVP_MD_type(digest))); + for (j = 0; j < (int) n; j++) { + BIO_printf(bio_out, "%02X%c", md[j], + (j + 1 == (int)n) ? '\n' : ':'); + } + } + } + + out = BIO_new(BIO_s_file()); + if (out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.text) + X509_CRL_print(out, x); + + if (cfg.noout) { + ret = 0; + goto end; + } + if (cfg.outformat == FORMAT_ASN1) + i = (int) i2d_X509_CRL_bio(out, x); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_X509_CRL(out, x); + else { + BIO_printf(bio_err, + "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write CRL\n"); + goto end; + } + ret = 0; + + end: + BIO_free_all(out); + BIO_free_all(bio_out); + bio_out = NULL; + X509_CRL_free(x); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + X509_OBJECT_free(xobj); + + return (ret); +} + +static X509_CRL * +load_crl(char *infile, int format) +{ + X509_CRL *x = NULL; + BIO *in = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, infile) <= 0) { + perror(infile); + goto end; + } + } + if (format == FORMAT_ASN1) + x = d2i_X509_CRL_bio(in, NULL); + else if (format == FORMAT_PEM) + x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, + "bad input format specified for input crl\n"); + goto end; + } + if (x == NULL) { + BIO_printf(bio_err, "unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + + end: + BIO_free(in); + return (x); +} diff --git a/apps/openssl/crl2p7.c b/apps/openssl/crl2p7.c new file mode 100644 index 0000000..dfbc896 --- /dev/null +++ b/apps/openssl/crl2p7.c @@ -0,0 +1,331 @@ +/* $OpenBSD: crl2p7.c,v 1.11 2023/03/06 14:32:05 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* This was written by Gordon Chaffee + * and donated 'to the cause' along with lots and lots of other fixes to + * the library. */ + +#include + +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static int add_certs_from_file(STACK_OF(X509) * stack, char *certfile); + +static struct { + STACK_OF(OPENSSL_STRING) *certflst; + char *infile; + int informat; + int nocrl; + char *outfile; + int outformat; +} cfg; + +static int +crl2p7_opt_certfile(char *arg) +{ + if (cfg.certflst == NULL) + cfg.certflst = sk_OPENSSL_STRING_new_null(); + if (cfg.certflst == NULL) { + fprintf(stderr, "out of memory\n"); + return (1); + } + if (!sk_OPENSSL_STRING_push(cfg.certflst, arg)) { + fprintf(stderr, "out of memory\n"); + return (1); + } + + return (0); +} + +static const struct option crl2p7_options[] = { + { + .name = "certfile", + .argname = "file", + .desc = "Chain of PEM certificates to a trusted CA", + .type = OPTION_ARG_FUNC, + .opt.argfunc = crl2p7_opt_certfile, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "nocrl", + .desc = "Do not read CRL from input or include CRL in output", + .type = OPTION_FLAG, + .opt.flag = &cfg.nocrl, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { NULL }, +}; + +static void +crl2p7_usage(void) +{ + fprintf(stderr, + "usage: crl2p7 [-certfile file] [-in file] [-inform DER | PEM]\n" + " [-nocrl] [-out file] [-outform DER | PEM]\n\n"); + options_usage(crl2p7_options); +} + +int +crl2pkcs7_main(int argc, char **argv) +{ + int i; + BIO *in = NULL, *out = NULL; + char *certfile; + PKCS7 *p7 = NULL; + PKCS7_SIGNED *p7s = NULL; + X509_CRL *crl = NULL; + STACK_OF(X509_CRL) *crl_stack = NULL; + STACK_OF(X509) *cert_stack = NULL; + int ret = 1; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, crl2p7_options, NULL, NULL) != 0) { + crl2p7_usage(); + goto end; + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (!cfg.nocrl) { + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + if (cfg.informat == FORMAT_ASN1) + crl = d2i_X509_CRL_bio(in, NULL); + else if (cfg.informat == FORMAT_PEM) + crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, + "bad input format specified for input crl\n"); + goto end; + } + if (crl == NULL) { + BIO_printf(bio_err, "unable to load CRL\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if ((p7 = PKCS7_new()) == NULL) + goto end; + if ((p7s = PKCS7_SIGNED_new()) == NULL) + goto end; + p7->type = OBJ_nid2obj(NID_pkcs7_signed); + p7->d.sign = p7s; + p7s->contents->type = OBJ_nid2obj(NID_pkcs7_data); + + if (!ASN1_INTEGER_set(p7s->version, 1)) + goto end; + if ((crl_stack = sk_X509_CRL_new_null()) == NULL) + goto end; + p7s->crl = crl_stack; + if (crl != NULL) { + sk_X509_CRL_push(crl_stack, crl); + crl = NULL; /* now part of p7 for freeing */ + } + if ((cert_stack = sk_X509_new_null()) == NULL) + goto end; + p7s->cert = cert_stack; + + if (cfg.certflst) { + for (i = 0; i < sk_OPENSSL_STRING_num(cfg.certflst); i++) { + certfile = sk_OPENSSL_STRING_value(cfg.certflst, i); + if (add_certs_from_file(cert_stack, certfile) < 0) { + BIO_printf(bio_err, + "error loading certificates\n"); + ERR_print_errors(bio_err); + goto end; + } + } + } + + sk_OPENSSL_STRING_free(cfg.certflst); + + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.outformat == FORMAT_ASN1) + i = i2d_PKCS7_bio(out, p7); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_PKCS7(out, p7); + else { + BIO_printf(bio_err, + "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write pkcs7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + + end: + if (in != NULL) + BIO_free(in); + if (out != NULL) + BIO_free_all(out); + if (p7 != NULL) + PKCS7_free(p7); + if (crl != NULL) + X509_CRL_free(crl); + + return (ret); +} + +static int +add_certs_from_file(STACK_OF(X509) *stack, char *certfile) +{ + BIO *in = NULL; + int count = 0; + int ret = -1; + STACK_OF(X509_INFO) *sk = NULL; + X509_INFO *xi; + + in = BIO_new(BIO_s_file()); + if (in == NULL || BIO_read_filename(in, certfile) <= 0) { + BIO_printf(bio_err, "error opening the file, %s\n", certfile); + goto end; + } + /* This loads from a file, a stack of x509/crl/pkey sets */ + sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL); + if (sk == NULL) { + BIO_printf(bio_err, "error reading the file, %s\n", certfile); + goto end; + } + /* scan over it and pull out the CRL's */ + while (sk_X509_INFO_num(sk)) { + xi = sk_X509_INFO_shift(sk); + if (xi->x509 != NULL) { + sk_X509_push(stack, xi->x509); + xi->x509 = NULL; + count++; + } + X509_INFO_free(xi); + } + + ret = count; + + end: + /* never need to free x */ + if (in != NULL) + BIO_free(in); + if (sk != NULL) + sk_X509_INFO_free(sk); + return (ret); +} diff --git a/apps/openssl/dgst.c b/apps/openssl/dgst.c new file mode 100644 index 0000000..3979966 --- /dev/null +++ b/apps/openssl/dgst.c @@ -0,0 +1,671 @@ +/* $OpenBSD: dgst.c,v 1.21 2023/03/06 14:32:05 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 1024*8 + +int +do_fp(BIO * out, unsigned char *buf, BIO * bp, int sep, int binout, + EVP_PKEY * key, unsigned char *sigin, int siglen, + const char *sig_name, const char *md_name, + const char *file, BIO * bmd); + +static struct { + int argsused; + int debug; + int do_verify; + char *hmac_key; + char *keyfile; + int keyform; + const EVP_MD *m; + char *mac_name; + STACK_OF(OPENSSL_STRING) *macopts; + const EVP_MD *md; + int out_bin; + char *outfile; + char *passargin; + int separator; + char *sigfile; + STACK_OF(OPENSSL_STRING) *sigopts; + int want_pub; +} cfg; + +static int +dgst_opt_macopt(char *arg) +{ + if (arg == NULL) + return (1); + + if (cfg.macopts == NULL && + (cfg.macopts = sk_OPENSSL_STRING_new_null()) == NULL) + return (1); + + if (!sk_OPENSSL_STRING_push(cfg.macopts, arg)) + return (1); + + return (0); +} + +static int +dgst_opt_md(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.m = EVP_get_digestbyname(name)) == NULL) + return (1); + + cfg.md = cfg.m; + + *argsused = 1; + return (0); +} + +static int +dgst_opt_prverify(char *arg) +{ + if (arg == NULL) + return (1); + + cfg.keyfile = arg; + cfg.do_verify = 1; + return (0); +} + +static int +dgst_opt_sigopt(char *arg) +{ + if (arg == NULL) + return (1); + + if (cfg.sigopts == NULL && + (cfg.sigopts = sk_OPENSSL_STRING_new_null()) == NULL) + return (1); + + if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg)) + return (1); + + return (0); +} + +static int +dgst_opt_verify(char *arg) +{ + if (arg == NULL) + return (1); + + cfg.keyfile = arg; + cfg.want_pub = 1; + cfg.do_verify = 1; + return (0); +} + +static const struct option dgst_options[] = { + { + .name = "binary", + .desc = "Output the digest or signature in binary form", + .type = OPTION_VALUE, + .opt.value = &cfg.out_bin, + .value = 1, + }, + { + .name = "c", + .desc = "Print the digest in two-digit groups separated by colons", + .type = OPTION_VALUE, + .opt.value = &cfg.separator, + .value = 1, + }, + { + .name = "d", + .desc = "Print BIO debugging information", + .type = OPTION_FLAG, + .opt.flag = &cfg.debug, + }, + { + .name = "hex", + .desc = "Output as hex dump", + .type = OPTION_VALUE, + .opt.value = &cfg.out_bin, + .value = 0, + }, + { + .name = "hmac", + .argname = "key", + .desc = "Create hashed MAC with key", + .type = OPTION_ARG, + .opt.arg = &cfg.hmac_key, + }, + { + .name = "keyform", + .argname = "format", + .desc = "Key file format (PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "mac", + .argname = "algorithm", + .desc = "Create MAC (not necessarily HMAC)", + .type = OPTION_ARG, + .opt.arg = &cfg.mac_name, + }, + { + .name = "macopt", + .argname = "nm:v", + .desc = "MAC algorithm parameters or key", + .type = OPTION_ARG_FUNC, + .opt.argfunc = dgst_opt_macopt, + }, + { + .name = "out", + .argname = "file", + .desc = "Output to file rather than stdout", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passin", + .argname = "arg", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "prverify", + .argname = "file", + .desc = "Verify a signature using private key in file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = dgst_opt_prverify, + }, + { + .name = "r", + .desc = "Output the digest in coreutils format", + .type = OPTION_VALUE, + .opt.value = &cfg.separator, + .value = 2, + }, + { + .name = "sign", + .argname = "file", + .desc = "Sign digest using private key in file", + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "signature", + .argname = "file", + .desc = "Signature to verify", + .type = OPTION_ARG, + .opt.arg = &cfg.sigfile, + }, + { + .name = "sigopt", + .argname = "nm:v", + .desc = "Signature parameter", + .type = OPTION_ARG_FUNC, + .opt.argfunc = dgst_opt_sigopt, + }, + { + .name = "verify", + .argname = "file", + .desc = "Verify a signature using public key in file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = dgst_opt_verify, + }, + { + .name = NULL, + .desc = "", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = dgst_opt_md, + }, + { NULL }, +}; + +static void +list_md_fn(const EVP_MD * m, const char *from, const char *to, void *arg) +{ + const char *mname; + /* Skip aliases */ + if (!m) + return; + mname = OBJ_nid2ln(EVP_MD_type(m)); + /* Skip shortnames */ + if (strcmp(from, mname)) + return; + if (strchr(mname, ' ')) + mname = EVP_MD_name(m); + BIO_printf(arg, " -%-17s To use the %s message digest algorithm\n", + mname, mname); +} + +static void +dgst_usage(void) +{ + fprintf(stderr, "usage: dgst [-cdr] [-binary] [-digest] [-hex]"); + fprintf(stderr, " [-hmac key] [-keyform fmt]\n"); + fprintf(stderr, " [-mac algorithm] [-macopt nm:v] [-out file]"); + fprintf(stderr, " [-passin arg]\n"); + fprintf(stderr, " [-prverify file] [-sign file]"); + fprintf(stderr, " [-signature file]\n"); + fprintf(stderr, " [-sigopt nm:v] [-verify file] [file ...]\n\n"); + options_usage(dgst_options); + EVP_MD_do_all_sorted(list_md_fn, bio_err); + fprintf(stderr, "\n"); +} + +int +dgst_main(int argc, char **argv) +{ + unsigned char *buf = NULL; + int i, err = 1; + BIO *in = NULL, *inp; + BIO *bmd = NULL; + BIO *out = NULL; +#define PROG_NAME_SIZE 39 + char pname[PROG_NAME_SIZE + 1]; + EVP_PKEY *sigkey = NULL; + unsigned char *sigbuf = NULL; + int siglen = 0; + char *passin = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + if ((buf = malloc(BUFSIZE)) == NULL) { + BIO_printf(bio_err, "out of memory\n"); + goto end; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.keyform = FORMAT_PEM; + cfg.out_bin = -1; + + /* first check the program name */ + program_name(argv[0], pname, sizeof pname); + + cfg.md = EVP_get_digestbyname(pname); + + if (options_parse(argc, argv, dgst_options, NULL, + &cfg.argsused) != 0) { + dgst_usage(); + goto end; + } + argc -= cfg.argsused; + argv += cfg.argsused; + + if (cfg.do_verify && !cfg.sigfile) { + BIO_printf(bio_err, + "No signature to verify: use the -signature option\n"); + goto end; + } + + in = BIO_new(BIO_s_file()); + bmd = BIO_new(BIO_f_md()); + if (in == NULL || bmd == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if (cfg.debug) { + BIO_set_callback(in, BIO_debug_callback); + /* needed for windows 3.1 */ + BIO_set_callback_arg(in, (char *) bio_err); + } + if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + if (cfg.out_bin == -1) { + if (cfg.keyfile) + cfg.out_bin = 1; + else + cfg.out_bin = 0; + } + + if (cfg.outfile) { + if (cfg.out_bin) + out = BIO_new_file(cfg.outfile, "wb"); + else + out = BIO_new_file(cfg.outfile, "w"); + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + if (!out) { + BIO_printf(bio_err, "Error opening output file %s\n", + cfg.outfile ? cfg.outfile : "(stdout)"); + ERR_print_errors(bio_err); + goto end; + } + if ((!!cfg.mac_name + !!cfg.keyfile + + !!cfg.hmac_key) > 1) { + BIO_printf(bio_err, + "MAC and Signing key cannot both be specified\n"); + goto end; + } + if (cfg.keyfile) { + if (cfg.want_pub) + sigkey = load_pubkey(bio_err, cfg.keyfile, + cfg.keyform, 0, NULL, "key file"); + else + sigkey = load_key(bio_err, cfg.keyfile, + cfg.keyform, 0, passin, "key file"); + if (!sigkey) { + /* + * load_[pub]key() has already printed an appropriate + * message + */ + goto end; + } + } + if (cfg.mac_name) { + EVP_PKEY_CTX *mac_ctx = NULL; + int r = 0; + if (!init_gen_str(bio_err, &mac_ctx, cfg.mac_name, 0)) + goto mac_end; + if (cfg.macopts) { + char *macopt; + for (i = 0; i < sk_OPENSSL_STRING_num( + cfg.macopts); i++) { + macopt = sk_OPENSSL_STRING_value( + cfg.macopts, i); + if (pkey_ctrl_string(mac_ctx, macopt) <= 0) { + BIO_printf(bio_err, + "MAC parameter error \"%s\"\n", + macopt); + ERR_print_errors(bio_err); + goto mac_end; + } + } + } + if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) { + BIO_puts(bio_err, "Error generating key\n"); + ERR_print_errors(bio_err); + goto mac_end; + } + r = 1; + mac_end: + EVP_PKEY_CTX_free(mac_ctx); + if (r == 0) + goto end; + } + if (cfg.hmac_key) { + sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + (unsigned char *) cfg.hmac_key, -1); + if (!sigkey) + goto end; + } + if (sigkey) { + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + int r; + if (!BIO_get_md_ctx(bmd, &mctx)) { + BIO_printf(bio_err, "Error getting context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.do_verify) + r = EVP_DigestVerifyInit(mctx, &pctx, cfg.md, + NULL, sigkey); + else + r = EVP_DigestSignInit(mctx, &pctx, cfg.md, + NULL, sigkey); + if (!r) { + BIO_printf(bio_err, "Error setting context\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.sigopts) { + char *sigopt; + for (i = 0; i < sk_OPENSSL_STRING_num( + cfg.sigopts); i++) { + sigopt = sk_OPENSSL_STRING_value( + cfg.sigopts, i); + if (pkey_ctrl_string(pctx, sigopt) <= 0) { + BIO_printf(bio_err, + "parameter error \"%s\"\n", + sigopt); + ERR_print_errors(bio_err); + goto end; + } + } + } + } + /* we use md as a filter, reading from 'in' */ + else { + if (cfg.md == NULL) + cfg.md = EVP_sha256(); + if (!BIO_set_md(bmd, cfg.md)) { + BIO_printf(bio_err, "Error setting digest %s\n", pname); + ERR_print_errors(bio_err); + goto end; + } + } + + if (cfg.sigfile && sigkey) { + BIO *sigbio; + siglen = EVP_PKEY_size(sigkey); + sigbuf = malloc(siglen); + if (sigbuf == NULL) { + BIO_printf(bio_err, "out of memory\n"); + ERR_print_errors(bio_err); + goto end; + } + sigbio = BIO_new_file(cfg.sigfile, "rb"); + if (!sigbio) { + BIO_printf(bio_err, "Error opening signature file %s\n", + cfg.sigfile); + ERR_print_errors(bio_err); + goto end; + } + siglen = BIO_read(sigbio, sigbuf, siglen); + BIO_free(sigbio); + if (siglen <= 0) { + BIO_printf(bio_err, "Error reading signature file %s\n", + cfg.sigfile); + ERR_print_errors(bio_err); + goto end; + } + } + inp = BIO_push(bmd, in); + + if (cfg.md == NULL) { + EVP_MD_CTX *tctx; + BIO_get_md_ctx(bmd, &tctx); + cfg.md = EVP_MD_CTX_md(tctx); + } + if (argc == 0) { + BIO_set_fp(in, stdin, BIO_NOCLOSE); + err = do_fp(out, buf, inp, cfg.separator, + cfg.out_bin, sigkey, sigbuf, siglen, NULL, NULL, + "stdin", bmd); + } else { + const char *md_name = NULL, *sig_name = NULL; + if (!cfg.out_bin) { + if (sigkey) { + const EVP_PKEY_ASN1_METHOD *ameth; + ameth = EVP_PKEY_get0_asn1(sigkey); + if (ameth) + EVP_PKEY_asn1_get0_info(NULL, NULL, + NULL, NULL, &sig_name, ameth); + } + md_name = EVP_MD_name(cfg.md); + } + err = 0; + for (i = 0; i < argc; i++) { + int r; + if (BIO_read_filename(in, argv[i]) <= 0) { + perror(argv[i]); + err++; + continue; + } else { + r = do_fp(out, buf, inp, cfg.separator, + cfg.out_bin, sigkey, sigbuf, siglen, + sig_name, md_name, argv[i], bmd); + } + if (r) + err = r; + (void) BIO_reset(bmd); + } + } + + end: + freezero(buf, BUFSIZE); + BIO_free(in); + free(passin); + BIO_free_all(out); + EVP_PKEY_free(sigkey); + sk_OPENSSL_STRING_free(cfg.sigopts); + sk_OPENSSL_STRING_free(cfg.macopts); + free(sigbuf); + BIO_free(bmd); + + return (err); +} + +int +do_fp(BIO * out, unsigned char *buf, BIO * bp, int sep, int binout, + EVP_PKEY * key, unsigned char *sigin, int siglen, + const char *sig_name, const char *md_name, + const char *file, BIO * bmd) +{ + size_t len; + int i; + + for (;;) { + i = BIO_read(bp, (char *) buf, BUFSIZE); + if (i < 0) { + BIO_printf(bio_err, "Read Error in %s\n", file); + ERR_print_errors(bio_err); + return 1; + } + if (i == 0) + break; + } + if (sigin) { + EVP_MD_CTX *ctx; + BIO_get_md_ctx(bp, &ctx); + i = EVP_DigestVerifyFinal(ctx, sigin, (unsigned int) siglen); + if (i > 0) + BIO_printf(out, "Verified OK\n"); + else if (i == 0) { + BIO_printf(out, "Verification Failure\n"); + return 1; + } else { + BIO_printf(bio_err, "Error Verifying Data\n"); + ERR_print_errors(bio_err); + return 1; + } + return 0; + } + if (key) { + EVP_MD_CTX *ctx; + BIO_get_md_ctx(bp, &ctx); + len = BUFSIZE; + if (!EVP_DigestSignFinal(ctx, buf, &len)) { + BIO_printf(bio_err, "Error Signing Data\n"); + ERR_print_errors(bio_err); + return 1; + } + } else { + len = BIO_gets(bp, (char *) buf, BUFSIZE); + if ((int) len < 0) { + ERR_print_errors(bio_err); + return 1; + } + } + + if (binout) + BIO_write(out, buf, len); + else if (sep == 2) { + for (i = 0; i < (int) len; i++) + BIO_printf(out, "%02x", buf[i]); + BIO_printf(out, " *%s\n", file); + } else { + if (sig_name) + BIO_printf(out, "%s-%s(%s)= ", sig_name, md_name, file); + else if (md_name) + BIO_printf(out, "%s(%s)= ", md_name, file); + else + BIO_printf(out, "(%s)= ", file); + for (i = 0; i < (int) len; i++) { + if (sep && (i != 0)) + BIO_printf(out, ":"); + BIO_printf(out, "%02x", buf[i]); + } + BIO_printf(out, "\n"); + } + return 0; +} diff --git a/apps/openssl/dh.c b/apps/openssl/dh.c new file mode 100644 index 0000000..a4c0223 --- /dev/null +++ b/apps/openssl/dh.c @@ -0,0 +1,298 @@ +/* $OpenBSD: dh.c,v 1.15 2023/03/06 14:32:05 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include /* for OPENSSL_NO_DH */ + +#ifndef OPENSSL_NO_DH + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static struct { + int C; + int check; + char *infile; + int informat; + int noout; + char *outfile; + int outformat; + int text; +} cfg; + +static const struct option dh_options[] = { + { + .name = "C", + .desc = "Convert DH parameters into C code", + .type = OPTION_FLAG, + .opt.flag = &cfg.C, + }, + { + .name = "check", + .desc = "Check the DH parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "No output", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "text", + .desc = "Print a text form of the DH parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { NULL }, +}; + +static void +dh_usage(void) +{ + fprintf(stderr, + "usage: dh [-C] [-check] [-in file] [-inform format]\n" + " [-noout] [-out file] [-outform format] [-text]\n\n"); + options_usage(dh_options); +} + +int +dh_main(int argc, char **argv) +{ + DH *dh = NULL; + int i; + BIO *in = NULL, *out = NULL; + int ret = 1; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, dh_options, NULL, NULL) != 0) { + dh_usage(); + goto end; + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.informat == FORMAT_ASN1) + dh = d2i_DHparams_bio(in, NULL); + else if (cfg.informat == FORMAT_PEM) + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, "bad input format specified\n"); + goto end; + } + if (dh == NULL) { + BIO_printf(bio_err, "unable to load DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.text) { + DHparams_print(out, dh); + } + if (cfg.check) { + if (!DH_check(dh, &i)) { + ERR_print_errors(bio_err); + goto end; + } + if (i & DH_CHECK_P_NOT_PRIME) + printf("p value is not prime\n"); + if (i & DH_CHECK_P_NOT_SAFE_PRIME) + printf("p value is not a safe prime\n"); + if (i & DH_UNABLE_TO_CHECK_GENERATOR) + printf("unable to check the generator value\n"); + if (i & DH_NOT_SUITABLE_GENERATOR) + printf("the g value is not a generator\n"); + if (i == 0) + printf("DH parameters appear to be ok.\n"); + } + if (cfg.C) { + unsigned char *data; + int len, l, bits; + + len = BN_num_bytes(DH_get0_p(dh)); + bits = BN_num_bits(DH_get0_p(dh)); + data = malloc(len); + if (data == NULL) { + perror("malloc"); + goto end; + } + l = BN_bn2bin(DH_get0_p(dh), data); + printf("static unsigned char dh%d_p[] = {", bits); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t};\n"); + + l = BN_bn2bin(DH_get0_g(dh), data); + printf("static unsigned char dh%d_g[] = {", bits); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t};\n\n"); + + printf("DH *get_dh%d()\n\t{\n", bits); + printf("\tDH *dh;\n"); + printf("\tBIGNUM *p = NULL, *g = NULL;\n\n"); + printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n"); + printf("\tp = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n", + bits, bits); + printf("\tg = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n", + bits, bits); + printf("\tif (p == NULL || g == NULL)\n"); + printf("\t\t{ BN_free(p); BN_free(q); DH_free(dh); return(NULL); }\n"); + printf("\tDH_set0_pqg(dh, p, NULL, g);\n"); + printf("\treturn(dh);\n\t}\n"); + free(data); + } + if (!cfg.noout) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_DHparams_bio(out, dh); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_DHparams(out, dh); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + ret = 0; + + end: + BIO_free(in); + BIO_free_all(out); + DH_free(dh); + + return (ret); +} +#endif diff --git a/apps/openssl/dhparam.c b/apps/openssl/dhparam.c new file mode 100644 index 0000000..00bf697 --- /dev/null +++ b/apps/openssl/dhparam.c @@ -0,0 +1,502 @@ +/* $OpenBSD: dhparam.c,v 1.18 2023/07/23 11:39:29 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include /* for OPENSSL_NO_DH */ + +#ifndef OPENSSL_NO_DH + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +#include + +#define DEFBITS 2048 + +static struct { + int C; + int check; + int dsaparam; + int g; + char *infile; + int informat; + int noout; + char *outfile; + int outformat; + int text; +} cfg; + +static const struct option dhparam_options[] = { + { + .name = "2", + .desc = "Generate DH parameters with a generator value of 2 " + "(default)", + .type = OPTION_VALUE, + .opt.value = &cfg.g, + .value = 2, + }, + { + .name = "5", + .desc = "Generate DH parameters with a generator value of 5", + .type = OPTION_VALUE, + .opt.value = &cfg.g, + .value = 5, + }, + { + .name = "C", + .desc = "Convert DH parameters into C code", + .type = OPTION_FLAG, + .opt.flag = &cfg.C, + }, + { + .name = "check", + .desc = "Check the DH parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "dsaparam", + .desc = "Read or generate DSA parameters and convert to DH", + .type = OPTION_FLAG, + .opt.flag = &cfg.dsaparam, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "Do not output encoded version of DH parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "text", + .desc = "Print DH parameters in plain text", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { NULL }, +}; + +static void +dhparam_usage(void) +{ + fprintf(stderr, + "usage: dhparam [-2 | -5] [-C] [-check] [-dsaparam]\n" + " [-in file] [-inform DER | PEM] [-noout] [-out file]\n" + " [-outform DER | PEM] [-text] [numbits]\n\n"); + options_usage(dhparam_options); +} + +static int dh_cb(int p, int n, BN_GENCB *cb); + +int +dhparam_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + BN_GENCB *cb = NULL; + char *num_bits = NULL; + DH *dh = NULL; + int num = 0; + int ret = 1; + int i; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, dhparam_options, &num_bits, NULL) != 0) { + dhparam_usage(); + return (1); + } + + if (num_bits != NULL) { + if(sscanf(num_bits, "%d", &num) == 0 || num <= 0) { + BIO_printf(bio_err, "invalid number of bits: %s\n", + num_bits); + return (1); + } + } + + if (cfg.g && !num) + num = DEFBITS; + + if (cfg.dsaparam) { + if (cfg.g) { + BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); + goto end; + } + } else { + /* DH parameters */ + if (num && !cfg.g) + cfg.g = 2; + } + + if (num) { + if ((cb = BN_GENCB_new()) == NULL) { + BIO_printf(bio_err, + "Error allocating BN_GENCB object\n"); + goto end; + } + + BN_GENCB_set(cb, dh_cb, bio_err); + if (cfg.dsaparam) { + DSA *dsa = DSA_new(); + + BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); + if (!dsa || !DSA_generate_parameters_ex(dsa, num, + NULL, 0, NULL, NULL, cb)) { + DSA_free(dsa); + ERR_print_errors(bio_err); + goto end; + } + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } else { + dh = DH_new(); + BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, cfg.g); + BIO_printf(bio_err, "This is going to take a long time\n"); + if (!dh || !DH_generate_parameters_ex(dh, num, cfg.g, cb)) { + ERR_print_errors(bio_err); + goto end; + } + } + } else { + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + if (cfg.informat != FORMAT_ASN1 && + cfg.informat != FORMAT_PEM) { + BIO_printf(bio_err, "bad input format specified\n"); + goto end; + } + if (cfg.dsaparam) { + DSA *dsa; + + if (cfg.informat == FORMAT_ASN1) + dsa = d2i_DSAparams_bio(in, NULL); + else /* informat == FORMAT_PEM */ + dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); + + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + dh = DSA_dup_DH(dsa); + DSA_free(dsa); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; + } + } else + { + if (cfg.informat == FORMAT_ASN1) + dh = d2i_DHparams_bio(in, NULL); + else /* informat == FORMAT_PEM */ + dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); + + if (dh == NULL) { + BIO_printf(bio_err, "unable to load DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + /* dh != NULL */ + } + + out = BIO_new(BIO_s_file()); + if (out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + + if (cfg.text) { + DHparams_print(out, dh); + } + if (cfg.check) { + if (!DH_check(dh, &i)) { + ERR_print_errors(bio_err); + goto end; + } + if (i & DH_CHECK_P_NOT_PRIME) + printf("p value is not prime\n"); + if (i & DH_CHECK_P_NOT_SAFE_PRIME) + printf("p value is not a safe prime\n"); + if (i & DH_UNABLE_TO_CHECK_GENERATOR) + printf("unable to check the generator value\n"); + if (i & DH_NOT_SUITABLE_GENERATOR) + printf("the g value is not a generator\n"); + if (i == 0) + printf("DH parameters appear to be ok.\n"); + } + if (cfg.C) { + unsigned char *data; + int len, l, bits; + + len = BN_num_bytes(DH_get0_p(dh)); + bits = BN_num_bits(DH_get0_p(dh)); + data = malloc(len); + if (data == NULL) { + perror("malloc"); + goto end; + } + printf("#ifndef HEADER_DH_H\n" + "#include \n" + "#endif\n"); + printf("DH *get_dh%d()\n\t{\n", bits); + + l = BN_bn2bin(DH_get0_p(dh), data); + printf("\tstatic unsigned char dh%d_p[] = {", bits); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t\t};\n"); + + l = BN_bn2bin(DH_get0_g(dh), data); + printf("\tstatic unsigned char dh%d_g[] = {", bits); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t\t};\n"); + + printf("\tDH *dh;\n"); + printf("\tBIGNUM *p = NULL, *g = NULL;\n\n"); + printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n"); + printf("\tp = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n", + bits, bits); + printf("\tg = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n", + bits, bits); + printf("\tif (p == NULL || g == NULL)\n"); + printf("\t\t{ BN_free(p); BN_free(g); DH_free(dh); return(NULL); }\n"); + printf("\tDH_set0_pqg(dh, p, NULL, g);\n"); + if (DH_get_length(dh) > 0) + printf("\tDH_set_length(dh, %ld);\n", DH_get_length(dh)); + printf("\treturn(dh);\n\t}\n"); + free(data); + } + if (!cfg.noout) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_DHparams_bio(out, dh); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_DHparams(out, dh); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write DH parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + ret = 0; + + end: + BIO_free(in); + BIO_free_all(out); + BN_GENCB_free(cb); + DH_free(dh); + + return (ret); +} + +/* dh_cb is identical to dsa_cb in apps/dsaparam.c */ +static int +dh_cb(int p, int n, BN_GENCB *cb) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void) BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} + +#endif diff --git a/apps/openssl/dsa.c b/apps/openssl/dsa.c new file mode 100644 index 0000000..f1de78c --- /dev/null +++ b/apps/openssl/dsa.c @@ -0,0 +1,365 @@ +/* $OpenBSD: dsa.c,v 1.18 2023/03/06 14:32:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include /* for OPENSSL_NO_DSA */ + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include + +static struct { + const EVP_CIPHER *enc; + char *infile; + int informat; + int modulus; + int noout; + char *outfile; + int outformat; + char *passargin; + char *passargout; + int pubin; + int pubout; + int pvk_encr; + int text; +} cfg; + +static int +dsa_opt_enc(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.enc = EVP_get_cipherbyname(name)) != NULL) { + *argsused = 1; + return (0); + } + + return (1); +} + +static const struct option dsa_options[] = { + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (PEM (default) or any other supported" + " format)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "modulus", + .desc = "Print the DSA public value", + .type = OPTION_FLAG, + .opt.flag = &cfg.modulus, + }, + { + .name = "noout", + .desc = "No output", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER, MSBLOB, PEM (default) or PVK)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "source", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "source", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "pubin", + .desc = "Read a public key from the input file instead of" + " private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubin, + }, + { + .name = "pubout", + .desc = "Output a public key instead of private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubout, + }, + { + .name = "pvk-none", + .desc = "PVK encryption level", + .type = OPTION_VALUE, + .value = 0, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "pvk-strong", + .desc = "PVK encryption level (default)", + .type = OPTION_VALUE, + .value = 2, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "pvk-weak", + .desc = "PVK encryption level", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "text", + .desc = "Print the key in text form", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = dsa_opt_enc, + }, + { NULL }, +}; + +static void +dsa_usage(void) +{ + int n = 0; + + fprintf(stderr, + "usage: dsa [-in file] [-inform format] [-modulus] [-noout]\n" + " [-out file] [-outform format] [-passin src] [-passout src]\n" + " [-pubin] [-pubout] [-pvk-none | -pvk-strong | -pvk-weak]\n" + " [-text] [-ciphername]\n\n"); + options_usage(dsa_options); + fprintf(stderr, "\n"); + + fprintf(stderr, "Valid ciphername values:\n\n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, &n); + fprintf(stderr, "\n"); +} + +int +dsa_main(int argc, char **argv) +{ + int ret = 1; + DSA *dsa = NULL; + int i; + BIO *in = NULL, *out = NULL; + char *passin = NULL, *passout = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.pvk_encr = 2; + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, dsa_options, NULL, NULL) != 0) { + dsa_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, + &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + BIO_printf(bio_err, "read DSA key\n"); + + { + EVP_PKEY *pkey; + + if (cfg.pubin) + pkey = load_pubkey(bio_err, cfg.infile, + cfg.informat, 1, passin, "Public Key"); + else + pkey = load_key(bio_err, cfg.infile, + cfg.informat, 1, passin, "Private Key"); + + if (pkey) { + dsa = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + } + } + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load Key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.text) { + if (!DSA_print(out, dsa, 0)) { + perror(cfg.outfile); + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.modulus) { + fprintf(stdout, "Public Key="); + BN_print(out, DSA_get0_pub_key(dsa)); + fprintf(stdout, "\n"); + } + if (cfg.noout) + goto end; + BIO_printf(bio_err, "writing DSA key\n"); + if (cfg.outformat == FORMAT_ASN1) { + if (cfg.pubin || cfg.pubout) + i = i2d_DSA_PUBKEY_bio(out, dsa); + else + i = i2d_DSAPrivateKey_bio(out, dsa); + } else if (cfg.outformat == FORMAT_PEM) { + if (cfg.pubin || cfg.pubout) + i = PEM_write_bio_DSA_PUBKEY(out, dsa); + else + i = PEM_write_bio_DSAPrivateKey(out, dsa, cfg.enc, + NULL, 0, NULL, passout); +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_RC4) + } else if (cfg.outformat == FORMAT_MSBLOB || + cfg.outformat == FORMAT_PVK) { + EVP_PKEY *pk; + pk = EVP_PKEY_new(); + EVP_PKEY_set1_DSA(pk, dsa); + if (cfg.outformat == FORMAT_PVK) + i = i2b_PVK_bio(out, pk, cfg.pvk_encr, 0, + passout); + else if (cfg.pubin || cfg.pubout) + i = i2b_PublicKey_bio(out, pk); + else + i = i2b_PrivateKey_bio(out, pk); + EVP_PKEY_free(pk); +#endif + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (i <= 0) { + BIO_printf(bio_err, "unable to write private key\n"); + ERR_print_errors(bio_err); + } else + ret = 0; + end: + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); + free(passin); + free(passout); + + return (ret); +} diff --git a/apps/openssl/dsaparam.c b/apps/openssl/dsaparam.c new file mode 100644 index 0000000..bc9ccd1 --- /dev/null +++ b/apps/openssl/dsaparam.c @@ -0,0 +1,377 @@ +/* $OpenBSD: dsaparam.c,v 1.15 2023/03/06 14:32:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include /* for OPENSSL_NO_DSA */ + +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static struct { + int C; + int genkey; + char *infile; + int informat; + int noout; + char *outfile; + int outformat; + int text; +} cfg; + +static const struct option dsaparam_options[] = { + { + .name = "C", + .desc = "Convert DSA parameters into C code", + .type = OPTION_FLAG, + .opt.flag = &cfg.C, + }, + { + .name = "genkey", + .desc = "Generate a DSA key", + .type = OPTION_FLAG, + .opt.flag = &cfg.genkey, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "No output", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "text", + .desc = "Print as text", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { NULL }, +}; + +static void +dsaparam_usage(void) +{ + fprintf(stderr, + "usage: dsaparam [-C] [-genkey] [-in file]\n" + " [-inform format] [-noout] [-out file] [-outform format]\n" + " [-text] [numbits]\n\n"); + options_usage(dsaparam_options); +} + +static int dsa_cb(int p, int n, BN_GENCB *cb); + +int +dsaparam_main(int argc, char **argv) +{ + DSA *dsa = NULL; + int i; + BIO *in = NULL, *out = NULL; + BN_GENCB *cb = NULL; + int ret = 1; + int numbits = -1; + char *strbits = NULL; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, dsaparam_options, &strbits, NULL) != 0) { + dsaparam_usage(); + goto end; + } + + if (strbits != NULL) { + const char *errstr; + numbits = strtonum(strbits, 0, INT_MAX, &errstr); + if (errstr) { + fprintf(stderr, "Invalid number of bits: %s", errstr); + goto end; + } + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (numbits > 0) { + if ((cb = BN_GENCB_new()) == NULL) { + BIO_printf(bio_err, + "Error allocating BN_GENCB object\n"); + goto end; + } + + BN_GENCB_set(cb, dsa_cb, bio_err); + + dsa = DSA_new(); + if (!dsa) { + BIO_printf(bio_err, "Error allocating DSA object\n"); + goto end; + } + BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", numbits); + BIO_printf(bio_err, "This could take some time\n"); + if (!DSA_generate_parameters_ex(dsa, numbits, NULL, 0, NULL, NULL, cb)) { + ERR_print_errors(bio_err); + BIO_printf(bio_err, "Error, DSA key generation failed\n"); + goto end; + } + } else if (cfg.informat == FORMAT_ASN1) + dsa = d2i_DSAparams_bio(in, NULL); + else if (cfg.informat == FORMAT_PEM) + dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, "bad input format specified\n"); + goto end; + } + if (dsa == NULL) { + BIO_printf(bio_err, "unable to load DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.text) { + DSAparams_print(out, dsa); + } + if (cfg.C) { + unsigned char *data; + int l, len, bits_p; + + len = BN_num_bytes(DSA_get0_p(dsa)); + bits_p = BN_num_bits(DSA_get0_p(dsa)); + data = malloc(len + 20); + if (data == NULL) { + perror("malloc"); + goto end; + } + l = BN_bn2bin(DSA_get0_p(dsa), data); + printf("static unsigned char dsa%d_p[] = {", bits_p); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t};\n"); + + l = BN_bn2bin(DSA_get0_q(dsa), data); + printf("static unsigned char dsa%d_q[] = {", bits_p); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t"); + printf("0x%02X, ", data[i]); + } + printf("\n\t};\n"); + + l = BN_bn2bin(DSA_get0_g(dsa), data); + printf("static unsigned char dsa%d_g[] = {", bits_p); + for (i = 0; i < l; i++) { + if ((i % 12) == 0) + printf("\n\t"); + printf("0x%02X, ", data[i]); + } + free(data); + printf("\n\t};\n\n"); + + printf("DSA *get_dsa%d()\n\t{\n", bits_p); + printf("\tBIGNUM *p = NULL, *q = NULL, *g = NULL;\n"); + printf("\tDSA *dsa;\n\n"); + printf("\tif ((dsa = DSA_new()) == NULL) return(NULL);\n"); + printf("\tp = BN_bin2bn(dsa%d_p, sizeof(dsa%d_p), NULL);\n", + bits_p, bits_p); + printf("\tq = BN_bin2bn(dsa%d_q, sizeof(dsa%d_q), NULL);\n", + bits_p, bits_p); + printf("\tg = BN_bin2bn(dsa%d_g, sizeof(dsa%d_g), NULL);\n", + bits_p, bits_p); + printf("\tif (p == NULL || q == NULL || g == NULL)\n"); + printf("\t\t{ BN_free(p); BN_free(q); BN_free(g); DSA_free(dsa); return(NULL); }\n"); + printf("\tDSA_set0_pqg(dsa, p, q, g);\n"); + printf("\treturn(dsa);\n\t}\n"); + } + if (!cfg.noout) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_DSAparams_bio(out, dsa); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_DSAparams(out, dsa); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write DSA parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.genkey) { + DSA *dsakey; + + if ((dsakey = DSAparams_dup(dsa)) == NULL) + goto end; + if (!DSA_generate_key(dsakey)) { + ERR_print_errors(bio_err); + DSA_free(dsakey); + goto end; + } + if (cfg.outformat == FORMAT_ASN1) + i = i2d_DSAPrivateKey_bio(out, dsakey); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_DSAPrivateKey(out, dsakey, NULL, NULL, 0, NULL, NULL); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + DSA_free(dsakey); + goto end; + } + DSA_free(dsakey); + } + ret = 0; + + end: + BIO_free(in); + BIO_free_all(out); + BN_GENCB_free(cb); + DSA_free(dsa); + + return (ret); +} + +static int +dsa_cb(int p, int n, BN_GENCB *cb) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void) BIO_flush(BN_GENCB_get_arg(cb)); +#ifdef GENCB_TEST + if (stop_keygen_flag) + return 0; +#endif + return 1; +} diff --git a/apps/openssl/ec.c b/apps/openssl/ec.c new file mode 100644 index 0000000..c6af126 --- /dev/null +++ b/apps/openssl/ec.c @@ -0,0 +1,392 @@ +/* $OpenBSD: ec.c,v 1.16 2023/03/06 14:32:06 tb Exp $ */ +/* + * Written by Nils Larsch for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#ifndef OPENSSL_NO_EC + +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include + +static struct { + int asn1_flag; + const EVP_CIPHER *enc; + point_conversion_form_t form; + char *infile; + int informat; + char *outfile; + int outformat; + int new_asn1_flag; + int new_form; + int noout; + int param_out; + char *passargin; + char *passargout; + int pubin; + int pubout; + int text; +} cfg; + +static int +ec_opt_enc(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.enc = EVP_get_cipherbyname(name)) != NULL) { + *argsused = 1; + return (0); + } + + return (1); +} + +static int +ec_opt_form(char *arg) +{ + if (strcmp(arg, "compressed") == 0) + cfg.form = POINT_CONVERSION_COMPRESSED; + else if (strcmp(arg, "uncompressed") == 0) + cfg.form = POINT_CONVERSION_UNCOMPRESSED; + else if (strcmp(arg, "hybrid") == 0) + cfg.form = POINT_CONVERSION_HYBRID; + else { + fprintf(stderr, "Invalid point conversion: %s\n", arg); + return (1); + } + + cfg.new_form = 1; + return (0); +} + +static int +ec_opt_named(char *arg) +{ + if (strcmp(arg, "named_curve") == 0) + cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; + else if (strcmp(arg, "explicit") == 0) + cfg.asn1_flag = 0; + else { + fprintf(stderr, "Invalid curve type: %s\n", arg); + return (1); + } + + cfg.new_asn1_flag = 1; + return (0); +} + +static const struct option ec_options[] = { + { + .name = "conv_form", + .argname = "form", + .desc = "Specify the point conversion form (default" + " \"named_curve\")", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ec_opt_form, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "No output", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "param_enc", + .argname = "type", + .desc = "Specify the way the ec parameters are encoded" + " (default \"uncompressed\")", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ec_opt_named, + }, + { + .name = "param_out", + .desc = "Print the elliptic curve parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.param_out, + }, + { + .name = "passin", + .argname = "source", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "source", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "pubin", + .desc = "Read public key instead of private key from input", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubin, + }, + { + .name = "pubout", + .desc = "Output public key instead of private key in output", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubout, + }, + { + .name = "text", + .desc = "Print the public/private key components and parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = NULL, + .desc = "Cipher to encrypt the output if using PEM format", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = ec_opt_enc, + }, + { NULL }, +}; + +static void +ec_usage(void) +{ + int n = 0; + + fprintf(stderr, + "usage: ec [-conv_form form] [-in file]\n" + " [-inform format] [-noout] [-out file] [-outform format]\n" + " [-param_enc type] [-param_out] [-passin file]\n" + " [-passout file] [-pubin] [-pubout] [-text] [-ciphername]\n\n"); + options_usage(ec_options); + + fprintf(stderr, "\n"); + + fprintf(stderr, "Valid ciphername values:\n\n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, &n); + fprintf(stderr, "\n"); +} + +int +ec_main(int argc, char **argv) +{ + int ret = 1; + EC_KEY *eckey = NULL; + const EC_GROUP *group; + int i; + BIO *in = NULL, *out = NULL; + char *passin = NULL, *passout = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; + cfg.form = POINT_CONVERSION_UNCOMPRESSED; + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, ec_options, NULL, NULL) != 0) { + ec_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, + &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + BIO_printf(bio_err, "read EC key\n"); + if (cfg.informat == FORMAT_ASN1) { + if (cfg.pubin) + eckey = d2i_EC_PUBKEY_bio(in, NULL); + else + eckey = d2i_ECPrivateKey_bio(in, NULL); + } else if (cfg.informat == FORMAT_PEM) { + if (cfg.pubin) + eckey = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, + NULL); + else + eckey = PEM_read_bio_ECPrivateKey(in, NULL, NULL, + passin); + } else { + BIO_printf(bio_err, "bad input format specified for key\n"); + goto end; + } + if (eckey == NULL) { + BIO_printf(bio_err, "unable to load Key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + group = EC_KEY_get0_group(eckey); + + if (cfg.new_form) + EC_KEY_set_conv_form(eckey, cfg.form); + + if (cfg.new_asn1_flag) + EC_KEY_set_asn1_flag(eckey, cfg.asn1_flag); + + if (cfg.text) + if (!EC_KEY_print(out, eckey, 0)) { + perror(cfg.outfile); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.noout) { + ret = 0; + goto end; + } + BIO_printf(bio_err, "writing EC key\n"); + if (cfg.outformat == FORMAT_ASN1) { + if (cfg.param_out) + i = i2d_ECPKParameters_bio(out, group); + else if (cfg.pubin || cfg.pubout) + i = i2d_EC_PUBKEY_bio(out, eckey); + else + i = i2d_ECPrivateKey_bio(out, eckey); + } else if (cfg.outformat == FORMAT_PEM) { + if (cfg.param_out) + i = PEM_write_bio_ECPKParameters(out, group); + else if (cfg.pubin || cfg.pubout) + i = PEM_write_bio_EC_PUBKEY(out, eckey); + else + i = PEM_write_bio_ECPrivateKey(out, eckey, + cfg.enc, NULL, 0, NULL, passout); + } else { + BIO_printf(bio_err, "bad output format specified for " + "outfile\n"); + goto end; + } + + if (!i) { + BIO_printf(bio_err, "unable to write private key\n"); + ERR_print_errors(bio_err); + } else + ret = 0; + end: + BIO_free(in); + BIO_free_all(out); + EC_KEY_free(eckey); + free(passin); + free(passout); + + return (ret); +} +#endif diff --git a/apps/openssl/ecparam.c b/apps/openssl/ecparam.c new file mode 100644 index 0000000..933cd3e --- /dev/null +++ b/apps/openssl/ecparam.c @@ -0,0 +1,606 @@ +/* $OpenBSD: ecparam.c,v 1.23 2023/03/06 14:32:06 tb Exp $ */ +/* + * Written by Nils Larsch for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#include + +#ifndef OPENSSL_NO_EC + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static int ecparam_print_var(BIO *, BIGNUM *, const char *, int, + unsigned char *); + +static struct { + int C; + int asn1_flag; + int check; + char *curve_name; + point_conversion_form_t form; + int genkey; + char *infile; + int informat; + int list_curves; + int new_asn1_flag; + int new_form; + int no_seed; + int noout; + char *outfile; + int outformat; + int text; +} cfg; + +static int +ecparam_opt_form(char *arg) +{ + if (strcmp(arg, "compressed") == 0) + cfg.form = POINT_CONVERSION_COMPRESSED; + else if (strcmp(arg, "uncompressed") == 0) + cfg.form = POINT_CONVERSION_UNCOMPRESSED; + else if (strcmp(arg, "hybrid") == 0) + cfg.form = POINT_CONVERSION_HYBRID; + else + return (1); + + cfg.new_form = 1; + return (0); +} + +static int +ecparam_opt_enctype(char *arg) +{ + if (strcmp(arg, "explicit") == 0) + cfg.asn1_flag = 0; + else if (strcmp(arg, "named_curve") == 0) + cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; + else + return (1); + + cfg.new_asn1_flag = 1; + return (0); +} + +static const struct option ecparam_options[] = { + { + .name = "C", + .desc = "Convert the EC parameters into C code", + .type = OPTION_FLAG, + .opt.flag = &cfg.C, + }, + { + .name = "check", + .desc = "Validate the elliptic curve parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "conv_form", + .argname = "form", + .desc = "Specify point conversion form:\n" + " compressed, uncompressed (default), hybrid", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ecparam_opt_form, + }, + { + .name = "genkey", + .desc = "Generate an EC private key using the specified " + "parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.genkey, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file to read parameters from (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "list_curves", + .desc = "Print list of all currently implemented EC " + "parameter names", + .type = OPTION_FLAG, + .opt.flag = &cfg.list_curves, + }, + { + .name = "name", + .argname = "curve", + .desc = "Use the EC parameters with the specified name", + .type = OPTION_ARG, + .opt.arg = &cfg.curve_name, + }, + { + .name = "no_seed", + .desc = "Do not output seed with explicit parameter encoding", + .type = OPTION_FLAG, + .opt.flag = &cfg.no_seed, + }, + { + .name = "noout", + .desc = "Do not output encoded version of EC parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file to write parameters to (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "param_enc", + .argname = "type", + .desc = "Specify EC parameter ASN.1 encoding type:\n" + " explicit, named_curve (default)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ecparam_opt_enctype, + }, + { + .name = "text", + .desc = "Print out the EC parameters in human readable form", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + {NULL}, +}; + +static void +ecparam_usage(void) +{ + fprintf(stderr, "usage: ecparam [-C] [-check] [-conv_form arg] " + " [-genkey]\n" + " [-in file] [-inform DER | PEM] [-list_curves] [-name arg]\n" + " [-no_seed] [-noout] [-out file] [-outform DER | PEM]\n" + " [-param_enc arg] [-text]\n\n"); + options_usage(ecparam_options); +} + +int +ecparam_main(int argc, char **argv) +{ + BIGNUM *ec_p = NULL, *ec_a = NULL, *ec_b = NULL, *ec_gen = NULL; + BIGNUM *ec_order = NULL, *ec_cofactor = NULL; + EC_GROUP *group = NULL; + unsigned char *buffer = NULL; + BIO *in = NULL, *out = NULL; + int i, ret = 1; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.asn1_flag = OPENSSL_EC_NAMED_CURVE; + cfg.form = POINT_CONVERSION_UNCOMPRESSED; + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, ecparam_options, NULL, NULL) != 0) { + ecparam_usage(); + goto end; + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if ((in == NULL) || (out == NULL)) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.list_curves) { + EC_builtin_curve *curves = NULL; + size_t crv_len = 0; + size_t n = 0; + + crv_len = EC_get_builtin_curves(NULL, 0); + + curves = reallocarray(NULL, crv_len, sizeof(EC_builtin_curve)); + if (curves == NULL) + goto end; + + if (!EC_get_builtin_curves(curves, crv_len)) { + free(curves); + goto end; + } + for (n = 0; n < crv_len; n++) { + const char *comment; + const char *sname; + comment = curves[n].comment; + sname = OBJ_nid2sn(curves[n].nid); + if (comment == NULL) + comment = "CURVE DESCRIPTION NOT AVAILABLE"; + if (sname == NULL) + sname = ""; + + BIO_printf(out, " %-10s: ", sname); + BIO_printf(out, "%s\n", comment); + } + + free(curves); + ret = 0; + goto end; + } + if (cfg.curve_name != NULL) { + int nid; + + /* + * workaround for the SECG curve names secp192r1 and + * secp256r1 (which are the same as the curves prime192v1 and + * prime256v1 defined in X9.62) + */ + if (!strcmp(cfg.curve_name, "secp192r1")) { + BIO_printf(bio_err, "using curve name prime192v1 " + "instead of secp192r1\n"); + nid = NID_X9_62_prime192v1; + } else if (!strcmp(cfg.curve_name, "secp256r1")) { + BIO_printf(bio_err, "using curve name prime256v1 " + "instead of secp256r1\n"); + nid = NID_X9_62_prime256v1; + } else + nid = OBJ_sn2nid(cfg.curve_name); + + if (nid == 0) + nid = EC_curve_nist2nid(cfg.curve_name); + + if (nid == 0) { + BIO_printf(bio_err, "unknown curve name (%s)\n", + cfg.curve_name); + goto end; + } + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) { + BIO_printf(bio_err, "unable to create curve (%s)\n", + cfg.curve_name); + goto end; + } + EC_GROUP_set_asn1_flag(group, cfg.asn1_flag); + EC_GROUP_set_point_conversion_form(group, cfg.form); + } else if (cfg.informat == FORMAT_ASN1) { + group = d2i_ECPKParameters_bio(in, NULL); + } else if (cfg.informat == FORMAT_PEM) { + group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL); + } else { + BIO_printf(bio_err, "bad input format specified\n"); + goto end; + } + + if (group == NULL) { + BIO_printf(bio_err, + "unable to load elliptic curve parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.new_form) + EC_GROUP_set_point_conversion_form(group, cfg.form); + + if (cfg.new_asn1_flag) + EC_GROUP_set_asn1_flag(group, cfg.asn1_flag); + + if (cfg.no_seed) + EC_GROUP_set_seed(group, NULL, 0); + + if (cfg.text) { + if (!ECPKParameters_print(out, group, 0)) + goto end; + } + if (cfg.check) { + BIO_printf(bio_err, "checking elliptic curve parameters: "); + if (!EC_GROUP_check(group, NULL)) { + BIO_printf(bio_err, "failed\n"); + ERR_print_errors(bio_err); + } else + BIO_printf(bio_err, "ok\n"); + + } + if (cfg.C) { + size_t buf_len = 0, tmp_len = 0; + const EC_POINT *point; + int is_prime, len = 0; + const EC_METHOD *meth = EC_GROUP_method_of(group); + + if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL || + (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL || + (ec_order = BN_new()) == NULL || + (ec_cofactor = BN_new()) == NULL) { + perror("malloc"); + goto end; + } + is_prime = (EC_METHOD_get_field_type(meth) == + NID_X9_62_prime_field); + + if (!EC_GROUP_get_curve(group, ec_p, ec_a, ec_b, NULL)) + goto end; + + if ((point = EC_GROUP_get0_generator(group)) == NULL) + goto end; + if (!EC_POINT_point2bn(group, point, + EC_GROUP_get_point_conversion_form(group), ec_gen, + NULL)) + goto end; + if (!EC_GROUP_get_order(group, ec_order, NULL)) + goto end; + if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL)) + goto end; + + len = BN_num_bits(ec_order); + + if ((tmp_len = (size_t) BN_num_bytes(ec_p)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t) BN_num_bytes(ec_a)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t) BN_num_bytes(ec_b)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t) BN_num_bytes(ec_gen)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t) BN_num_bytes(ec_order)) > buf_len) + buf_len = tmp_len; + if ((tmp_len = (size_t) BN_num_bytes(ec_cofactor)) > buf_len) + buf_len = tmp_len; + + buffer = malloc(buf_len); + + if (buffer == NULL) { + perror("malloc"); + goto end; + } + ecparam_print_var(out, ec_p, "ec_p", len, buffer); + ecparam_print_var(out, ec_a, "ec_a", len, buffer); + ecparam_print_var(out, ec_b, "ec_b", len, buffer); + ecparam_print_var(out, ec_gen, "ec_gen", len, buffer); + ecparam_print_var(out, ec_order, "ec_order", len, buffer); + ecparam_print_var(out, ec_cofactor, "ec_cofactor", len, + buffer); + + BIO_printf(out, "\n\n"); + + BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n\t{\n", len); + BIO_printf(out, "\tint ok=0;\n"); + BIO_printf(out, "\tEC_GROUP *group = NULL;\n"); + BIO_printf(out, "\tEC_POINT *point = NULL;\n"); + BIO_printf(out, "\tBIGNUM *tmp_1 = NULL, *tmp_2 = NULL, " + "*tmp_3 = NULL;\n\n"); + BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_p_%d, " + "sizeof(ec_p_%d), NULL)) == NULL)\n\t\t" + "goto err;\n", len, len); + BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_a_%d, " + "sizeof(ec_a_%d), NULL)) == NULL)\n\t\t" + "goto err;\n", len, len); + BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_b_%d, " + "sizeof(ec_b_%d), NULL)) == NULL)\n\t\t" + "goto err;\n", len, len); + if (is_prime) { + BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_" + "GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)" + "\n\t\tgoto err;\n\n"); + } else { + BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_" + "GF2m(tmp_1, tmp_2, tmp_3, NULL)) == NULL)" + "\n\t\tgoto err;\n\n"); + } + BIO_printf(out, "\t/* build generator */\n"); + BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_gen_%d, " + "sizeof(ec_gen_%d), tmp_1)) == NULL)" + "\n\t\tgoto err;\n", len, len); + BIO_printf(out, "\tpoint = EC_POINT_bn2point(group, tmp_1, " + "NULL, NULL);\n"); + BIO_printf(out, "\tif (point == NULL)\n\t\tgoto err;\n"); + BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_order_%d, " + "sizeof(ec_order_%d), tmp_2)) == NULL)" + "\n\t\tgoto err;\n", len, len); + BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_cofactor_%d, " + "sizeof(ec_cofactor_%d), tmp_3)) == NULL)" + "\n\t\tgoto err;\n", len, len); + BIO_printf(out, "\tif (!EC_GROUP_set_generator(group, point," + " tmp_2, tmp_3))\n\t\tgoto err;\n"); + BIO_printf(out, "\n\tok=1;\n"); + BIO_printf(out, "err:\n"); + BIO_printf(out, "\tif (tmp_1)\n\t\tBN_free(tmp_1);\n"); + BIO_printf(out, "\tif (tmp_2)\n\t\tBN_free(tmp_2);\n"); + BIO_printf(out, "\tif (tmp_3)\n\t\tBN_free(tmp_3);\n"); + BIO_printf(out, "\tif (point)\n\t\tEC_POINT_free(point);\n"); + BIO_printf(out, "\tif (!ok)\n"); + BIO_printf(out, "\t\t{\n"); + BIO_printf(out, "\t\tEC_GROUP_free(group);\n"); + BIO_printf(out, "\t\tgroup = NULL;\n"); + BIO_printf(out, "\t\t}\n"); + BIO_printf(out, "\treturn(group);\n\t}\n"); + } + if (!cfg.noout) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_ECPKParameters_bio(out, group); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_ECPKParameters(out, group); + else { + BIO_printf(bio_err, "bad output format specified for" + " outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write elliptic " + "curve parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.genkey) { + EC_KEY *eckey = EC_KEY_new(); + + if (eckey == NULL) + goto end; + + if (EC_KEY_set_group(eckey, group) == 0) { + EC_KEY_free(eckey); + goto end; + } + + if (!EC_KEY_generate_key(eckey)) { + EC_KEY_free(eckey); + goto end; + } + if (cfg.outformat == FORMAT_ASN1) + i = i2d_ECPrivateKey_bio(out, eckey); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_ECPrivateKey(out, eckey, NULL, + NULL, 0, NULL, NULL); + else { + BIO_printf(bio_err, "bad output format specified " + "for outfile\n"); + EC_KEY_free(eckey); + goto end; + } + EC_KEY_free(eckey); + } + ret = 0; + + end: + BN_free(ec_p); + BN_free(ec_a); + BN_free(ec_b); + BN_free(ec_gen); + BN_free(ec_order); + BN_free(ec_cofactor); + + free(buffer); + + BIO_free(in); + BIO_free_all(out); + EC_GROUP_free(group); + + return (ret); +} + +static int +ecparam_print_var(BIO * out, BIGNUM * in, const char *var, + int len, unsigned char *buffer) +{ + BIO_printf(out, "static unsigned char %s_%d[] = {", var, len); + if (BN_is_zero(in)) + BIO_printf(out, "\n\t0x00"); + else { + int i, l; + + l = BN_bn2bin(in, buffer); + for (i = 0; i < l - 1; i++) { + if ((i % 12) == 0) + BIO_printf(out, "\n\t"); + BIO_printf(out, "0x%02X,", buffer[i]); + } + if ((i % 12) == 0) + BIO_printf(out, "\n\t"); + BIO_printf(out, "0x%02X", buffer[i]); + } + BIO_printf(out, "\n\t};\n\n"); + return 1; +} +#endif diff --git a/apps/openssl/enc.c b/apps/openssl/enc.c new file mode 100644 index 0000000..41732fd --- /dev/null +++ b/apps/openssl/enc.c @@ -0,0 +1,783 @@ +/* $OpenBSD: enc.c,v 1.31 2023/07/29 17:15:45 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include + +int set_hex(char *in, unsigned char *out, int size); + +#define SIZE (512) +#define BSIZE (8*1024) + +static struct { + int base64; + char *bufsize; + const EVP_CIPHER *cipher; + int debug; + int enc; + char *hiv; + char *hkey; + char *hsalt; + char *inf; + int iter; + char *keyfile; + char *keystr; + char *md; + int nopad; + int nosalt; + int olb64; + char *outf; + char *passarg; + int pbkdf2; + int printkey; + int verbose; +} cfg; + +static int +enc_opt_cipher(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if (strcmp(name, "none") == 0) { + cfg.cipher = NULL; + *argsused = 1; + return (0); + } + + if ((cfg.cipher = EVP_get_cipherbyname(name)) != NULL) { + *argsused = 1; + return (0); + } + + return (1); +} + +static const struct option enc_options[] = { + { + .name = "A", + .desc = "Process base64 data on one line (requires -a)", + .type = OPTION_FLAG, + .opt.flag = &cfg.olb64, + }, + { + .name = "a", + .desc = "Perform base64 encoding/decoding (alias -base64)", + .type = OPTION_FLAG, + .opt.flag = &cfg.base64, + }, + { + .name = "base64", + .type = OPTION_FLAG, + .opt.flag = &cfg.base64, + }, + { + .name = "bufsize", + .argname = "size", + .desc = "Specify the buffer size to use for I/O", + .type = OPTION_ARG, + .opt.arg = &cfg.bufsize, + }, + { + .name = "d", + .desc = "Decrypt the input data", + .type = OPTION_VALUE, + .opt.value = &cfg.enc, + .value = 0, + }, + { + .name = "debug", + .desc = "Print debugging information", + .type = OPTION_FLAG, + .opt.flag = &cfg.debug, + }, + { + .name = "e", + .desc = "Encrypt the input data (default)", + .type = OPTION_VALUE, + .opt.value = &cfg.enc, + .value = 1, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file to read from (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.inf, + }, + { + .name = "iter", + .argname = "iterations", + .desc = "Specify iteration count and force use of PBKDF2", + .type = OPTION_ARG_INT, + .opt.value = &cfg.iter, + }, + { + .name = "iv", + .argname = "IV", + .desc = "IV to use, specified as a hexadecimal string", + .type = OPTION_ARG, + .opt.arg = &cfg.hiv, + }, + { + .name = "K", + .argname = "key", + .desc = "Key to use, specified as a hexadecimal string", + .type = OPTION_ARG, + .opt.arg = &cfg.hkey, + }, + { + .name = "k", /* Superseded by -pass. */ + .type = OPTION_ARG, + .opt.arg = &cfg.keystr, + }, + { + .name = "kfile", /* Superseded by -pass. */ + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "md", + .argname = "digest", + .desc = "Digest to use to create a key from the passphrase", + .type = OPTION_ARG, + .opt.arg = &cfg.md, + }, + { + .name = "none", + .desc = "Use NULL cipher (no encryption or decryption)", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = enc_opt_cipher, + }, + { + .name = "nopad", + .desc = "Disable standard block padding", + .type = OPTION_FLAG, + .opt.flag = &cfg.nopad, + }, + { + .name = "nosalt", + .type = OPTION_VALUE, + .opt.value = &cfg.nosalt, + .value = 1, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file to write to (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outf, + }, + { + .name = "P", + .desc = "Print out the salt, key and IV used, then exit\n" + " (no encryption or decryption is performed)", + .type = OPTION_VALUE, + .opt.value = &cfg.printkey, + .value = 2, + }, + { + .name = "p", + .desc = "Print out the salt, key and IV used", + .type = OPTION_VALUE, + .opt.value = &cfg.printkey, + .value = 1, + }, + { + .name = "pass", + .argname = "source", + .desc = "Password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passarg, + }, + { + .name = "pbkdf2", + .desc = "Use the pbkdf2 key derivation function", + .type = OPTION_FLAG, + .opt.flag = &cfg.pbkdf2, + }, + { + .name = "S", + .argname = "salt", + .desc = "Salt to use, specified as a hexadecimal string", + .type = OPTION_ARG, + .opt.arg = &cfg.hsalt, + }, + { + .name = "salt", + .desc = "Use a salt in the key derivation routines (default)", + .type = OPTION_VALUE, + .opt.value = &cfg.nosalt, + .value = 0, + }, + { + .name = "v", + .desc = "Verbose", + .type = OPTION_FLAG, + .opt.flag = &cfg.verbose, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = enc_opt_cipher, + }, + { NULL }, +}; + +static void +skip_aead_and_xts(const OBJ_NAME *name, void *arg) +{ + const EVP_CIPHER *cipher; + + if ((cipher = EVP_get_cipherbyname(name->name)) == NULL) + return; + + if ((EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) + return; + if (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE) + return; + + show_cipher(name, arg); +} + +static void +enc_usage(void) +{ + int n = 0; + + fprintf(stderr, "usage: enc -ciphername [-AadePp] [-base64] " + "[-bufsize number] [-debug]\n" + " [-in file] [-iter iterations] [-iv IV] [-K key] " + "[-k password]\n" + " [-kfile file] [-md digest] [-none] [-nopad] [-nosalt]\n" + " [-out file] [-pass source] [-pbkdf2] [-S salt] [-salt]\n\n"); + options_usage(enc_options); + fprintf(stderr, "\n"); + + fprintf(stderr, "Valid ciphername values:\n\n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, skip_aead_and_xts, &n); + fprintf(stderr, "\n"); +} + +int +enc_main(int argc, char **argv) +{ + static const char magic[] = "Salted__"; + char mbuf[sizeof magic - 1]; + char *strbuf = NULL, *pass = NULL; + unsigned char *buff = NULL; + int bsize = BSIZE; + int ret = 1, inl; + unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; + unsigned char salt[PKCS5_SALT_LEN]; + EVP_CIPHER_CTX *ctx = NULL; + const EVP_MD *dgst = NULL; + BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL; + BIO *rbio = NULL, *wbio = NULL; +#define PROG_NAME_SIZE 39 + char pname[PROG_NAME_SIZE + 1]; + int i; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.enc = 1; + + /* first check the program name */ + program_name(argv[0], pname, sizeof(pname)); + + if (strcmp(pname, "base64") == 0) + cfg.base64 = 1; + + cfg.cipher = EVP_get_cipherbyname(pname); + + if (!cfg.base64 && cfg.cipher == NULL && strcmp(pname, "enc") != 0) { + BIO_printf(bio_err, "%s is an unknown cipher\n", pname); + goto end; + } + + if (options_parse(argc, argv, enc_options, NULL, NULL) != 0) { + enc_usage(); + goto end; + } + + if (cfg.keyfile != NULL) { + static char buf[128]; + FILE *infile; + + infile = fopen(cfg.keyfile, "r"); + if (infile == NULL) { + BIO_printf(bio_err, "unable to read key from '%s'\n", + cfg.keyfile); + goto end; + } + buf[0] = '\0'; + if (!fgets(buf, sizeof buf, infile)) { + BIO_printf(bio_err, "unable to read key from '%s'\n", + cfg.keyfile); + fclose(infile); + goto end; + } + fclose(infile); + i = strlen(buf); + if (i > 0 && (buf[i - 1] == '\n' || buf[i - 1] == '\r')) + buf[--i] = '\0'; + if (i > 0 && (buf[i - 1] == '\n' || buf[i - 1] == '\r')) + buf[--i] = '\0'; + if (i < 1) { + BIO_printf(bio_err, "zero length password\n"); + goto end; + } + cfg.keystr = buf; + } + + if (cfg.cipher != NULL && + (EVP_CIPHER_flags(cfg.cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { + BIO_printf(bio_err, "enc does not support AEAD ciphers\n"); + goto end; + } + + if (cfg.cipher != NULL && + EVP_CIPHER_mode(cfg.cipher) == EVP_CIPH_XTS_MODE) { + BIO_printf(bio_err, "enc does not support XTS mode\n"); + goto end; + } + + if (cfg.md != NULL && + (dgst = EVP_get_digestbyname(cfg.md)) == NULL) { + BIO_printf(bio_err, + "%s is an unsupported message digest type\n", + cfg.md); + goto end; + } + if (dgst == NULL) + dgst = EVP_sha256(); + + if (cfg.bufsize != NULL) { + char *p = cfg.bufsize; + unsigned long n; + + /* XXX - provide an OPTION_ARG_DISKUNIT. */ + for (n = 0; *p != '\0'; p++) { + i = *p; + if ((i <= '9') && (i >= '0')) + n = n * 10 + i - '0'; + else if (i == 'k') { + n *= 1024; + p++; + break; + } + } + if (*p != '\0') { + BIO_printf(bio_err, "invalid 'bufsize' specified.\n"); + goto end; + } + /* It must be large enough for a base64 encoded line. */ + if (cfg.base64 && n < 80) + n = 80; + + bsize = (int)n; + if (cfg.verbose) + BIO_printf(bio_err, "bufsize=%d\n", bsize); + } + strbuf = malloc(SIZE); + buff = malloc(EVP_ENCODE_LENGTH(bsize)); + if (buff == NULL || strbuf == NULL) { + BIO_printf(bio_err, "malloc failure %ld\n", (long) EVP_ENCODE_LENGTH(bsize)); + goto end; + } + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if (in == NULL || out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.debug) { + BIO_set_callback(in, BIO_debug_callback); + BIO_set_callback(out, BIO_debug_callback); + BIO_set_callback_arg(in, (char *) bio_err); + BIO_set_callback_arg(out, (char *) bio_err); + } + if (cfg.inf == NULL) { + if (cfg.bufsize != NULL) + setvbuf(stdin, (char *) NULL, _IONBF, 0); + BIO_set_fp(in, stdin, BIO_NOCLOSE); + } else { + if (BIO_read_filename(in, cfg.inf) <= 0) { + perror(cfg.inf); + goto end; + } + } + + if (!cfg.keystr && cfg.passarg) { + if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + cfg.keystr = pass; + } + if (cfg.keystr == NULL && cfg.cipher != NULL && cfg.hkey == NULL) { + for (;;) { + char buf[200]; + int retval; + + retval = snprintf(buf, sizeof buf, + "enter %s %s password:", + OBJ_nid2ln(EVP_CIPHER_nid(cfg.cipher)), + cfg.enc ? "encryption" : "decryption"); + if ((size_t)retval >= sizeof buf) { + BIO_printf(bio_err, + "Password prompt too long\n"); + goto end; + } + strbuf[0] = '\0'; + i = EVP_read_pw_string((char *)strbuf, SIZE, buf, + cfg.enc); + if (i == 0) { + if (strbuf[0] == '\0') { + ret = 1; + goto end; + } + cfg.keystr = strbuf; + break; + } + if (i < 0) { + BIO_printf(bio_err, "bad password read\n"); + goto end; + } + } + } + if (cfg.outf == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + if (cfg.bufsize != NULL) + setvbuf(stdout, (char *)NULL, _IONBF, 0); + } else { + if (BIO_write_filename(out, cfg.outf) <= 0) { + perror(cfg.outf); + goto end; + } + } + + rbio = in; + wbio = out; + + if (cfg.base64) { + if ((b64 = BIO_new(BIO_f_base64())) == NULL) + goto end; + if (cfg.debug) { + BIO_set_callback(b64, BIO_debug_callback); + BIO_set_callback_arg(b64, (char *) bio_err); + } + if (cfg.olb64) + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + if (cfg.enc) + wbio = BIO_push(b64, wbio); + else + rbio = BIO_push(b64, rbio); + } + if (cfg.cipher != NULL) { + /* + * Note that keystr is NULL if a key was passed on the command + * line, so we get no salt in that case. Is this a bug? + */ + if (cfg.keystr != NULL) { + /* + * Salt handling: if encrypting generate a salt and + * write to output BIO. If decrypting read salt from + * input BIO. + */ + unsigned char *sptr; + if (cfg.nosalt) + sptr = NULL; + else { + if (cfg.enc) { + if (cfg.hsalt) { + if (!set_hex(cfg.hsalt, salt, sizeof salt)) { + BIO_printf(bio_err, + "invalid hex salt value\n"); + goto end; + } + } else + arc4random_buf(salt, + sizeof(salt)); + /* + * If -P option then don't bother + * writing + */ + if ((cfg.printkey != 2) + && (BIO_write(wbio, magic, + sizeof magic - 1) != sizeof magic - 1 + || BIO_write(wbio, + (char *) salt, + sizeof salt) != sizeof salt)) { + BIO_printf(bio_err, "error writing output file\n"); + goto end; + } + } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf + || BIO_read(rbio, + (unsigned char *) salt, + sizeof salt) != sizeof salt) { + BIO_printf(bio_err, "error reading input file\n"); + goto end; + } else if (memcmp(mbuf, magic, sizeof magic - 1)) { + BIO_printf(bio_err, "bad magic number\n"); + goto end; + } + sptr = salt; + } + if (cfg.pbkdf2 == 1 || cfg.iter > 0) { + /* + * derive key and default iv + * concatenated into a temporary buffer + */ + unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH]; + int iklen = EVP_CIPHER_key_length(cfg.cipher); + int ivlen = EVP_CIPHER_iv_length(cfg.cipher); + /* not needed if HASH_UPDATE() is fixed : */ + int islen = (sptr != NULL ? sizeof(salt) : 0); + + if (cfg.iter == 0) + cfg.iter = 10000; + + if (!PKCS5_PBKDF2_HMAC(cfg.keystr, + strlen(cfg.keystr), sptr, islen, + cfg.iter, dgst, iklen+ivlen, tmpkeyiv)) { + BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n"); + goto end; + } + /* split and move data back to global buffer */ + memcpy(key, tmpkeyiv, iklen); + memcpy(iv, tmpkeyiv + iklen, ivlen); + explicit_bzero(tmpkeyiv, sizeof tmpkeyiv); + } else { + EVP_BytesToKey(cfg.cipher, dgst, sptr, + (unsigned char *)cfg.keystr, + strlen(cfg.keystr), 1, key, iv); + } + + /* + * zero the complete buffer or the string passed from + * the command line bug picked up by Larry J. Hughes + * Jr. + */ + if (cfg.keystr == strbuf) + explicit_bzero(cfg.keystr, SIZE); + else + explicit_bzero(cfg.keystr, + strlen(cfg.keystr)); + } + if (cfg.hiv != NULL && !set_hex(cfg.hiv, iv, sizeof iv)) { + BIO_printf(bio_err, "invalid hex iv value\n"); + goto end; + } + if (cfg.hiv == NULL && cfg.keystr == NULL && + EVP_CIPHER_iv_length(cfg.cipher) != 0) { + /* + * No IV was explicitly set and no IV was generated + * during EVP_BytesToKey. Hence the IV is undefined, + * making correct decryption impossible. + */ + BIO_printf(bio_err, "iv undefined\n"); + goto end; + } + if (cfg.hkey != NULL && !set_hex(cfg.hkey, key, sizeof key)) { + BIO_printf(bio_err, "invalid hex key value\n"); + goto end; + } + if ((benc = BIO_new(BIO_f_cipher())) == NULL) + goto end; + + /* + * Since we may be changing parameters work on the encryption + * context rather than calling BIO_set_cipher(). + */ + + BIO_get_cipher_ctx(benc, &ctx); + + if (!EVP_CipherInit_ex(ctx, cfg.cipher, NULL, NULL, + NULL, cfg.enc)) { + BIO_printf(bio_err, "Error setting cipher %s\n", + EVP_CIPHER_name(cfg.cipher)); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.nopad) + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, cfg.enc)) { + BIO_printf(bio_err, "Error setting cipher %s\n", + EVP_CIPHER_name(cfg.cipher)); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.debug) { + BIO_set_callback(benc, BIO_debug_callback); + BIO_set_callback_arg(benc, (char *) bio_err); + } + if (cfg.printkey) { + int key_len, iv_len; + + if (!cfg.nosalt) { + printf("salt="); + for (i = 0; i < (int) sizeof(salt); i++) + printf("%02X", salt[i]); + printf("\n"); + } + key_len = EVP_CIPHER_key_length(cfg.cipher); + if (key_len > 0) { + printf("key="); + for (i = 0; i < key_len; i++) + printf("%02X", key[i]); + printf("\n"); + } + iv_len = EVP_CIPHER_iv_length(cfg.cipher); + if (iv_len > 0) { + printf("iv ="); + for (i = 0; i < iv_len; i++) + printf("%02X", iv[i]); + printf("\n"); + } + if (cfg.printkey == 2) { + ret = 0; + goto end; + } + } + } + /* Only encrypt/decrypt as we write the file */ + if (benc != NULL) + wbio = BIO_push(benc, wbio); + + for (;;) { + inl = BIO_read(rbio, (char *) buff, bsize); + if (inl <= 0) + break; + if (BIO_write(wbio, (char *) buff, inl) != inl) { + BIO_printf(bio_err, "error writing output file\n"); + goto end; + } + } + if (!BIO_flush(wbio)) { + BIO_printf(bio_err, "bad decrypt\n"); + goto end; + } + ret = 0; + if (cfg.verbose) { + BIO_printf(bio_err, "bytes read :%8ld\n", BIO_number_read(in)); + BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out)); + } + end: + ERR_print_errors(bio_err); + free(strbuf); + free(buff); + BIO_free(in); + BIO_free_all(out); + BIO_free(benc); + BIO_free(b64); + free(pass); + + return (ret); +} + +int +set_hex(char *in, unsigned char *out, int size) +{ + int i, n; + unsigned char j; + + n = strlen(in); + if (n > (size * 2)) { + BIO_printf(bio_err, "hex string is too long\n"); + return (0); + } + memset(out, 0, size); + for (i = 0; i < n; i++) { + j = (unsigned char) *in; + *(in++) = '\0'; + if (j == 0) + break; + if (j >= '0' && j <= '9') + j -= '0'; + else if (j >= 'A' && j <= 'F') + j = j - 'A' + 10; + else if (j >= 'a' && j <= 'f') + j = j - 'a' + 10; + else { + BIO_printf(bio_err, "non-hex digit\n"); + return (0); + } + if (i & 1) + out[i / 2] |= j; + else + out[i / 2] = (j << 4); + } + return (1); +} diff --git a/apps/openssl/errstr.c b/apps/openssl/errstr.c new file mode 100644 index 0000000..d4ffd70 --- /dev/null +++ b/apps/openssl/errstr.c @@ -0,0 +1,117 @@ +/* $OpenBSD: errstr.c,v 1.11 2023/07/23 11:20:11 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include + +static const struct option errstr_options[] = { + { NULL }, +}; + +static void +errstr_usage(void) +{ + fprintf(stderr, "usage: errstr errno ...\n"); +} + +int +errstr_main(int argc, char **argv) +{ + unsigned long ulval; + char *ularg, *ep; + int argsused, i; + char buf[256]; + int ret = 0; + + if (pledge("stdio rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + if (options_parse(argc, argv, errstr_options, NULL, &argsused) != 0) { + errstr_usage(); + return (1); + } + + for (i = argsused; i < argc; i++) { + errno = 0; + ularg = argv[i]; + ulval = strtoul(ularg, &ep, 16); + if (strchr(ularg, '-') != NULL || + (ularg[0] == '\0' || *ep != '\0') || + (errno == ERANGE && ulval == ULONG_MAX)) { + printf("%s: bad error code\n", ularg); + ret++; + continue; + } + + ERR_error_string_n(ulval, buf, sizeof(buf)); + printf("%s\n", buf); + } + + return (ret); +} diff --git a/apps/openssl/gendh.c b/apps/openssl/gendh.c new file mode 100644 index 0000000..b9dde3c --- /dev/null +++ b/apps/openssl/gendh.c @@ -0,0 +1,219 @@ +/* $OpenBSD: gendh.c,v 1.14 2023/03/06 14:32:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + +#ifndef OPENSSL_NO_DH + +#include +#include + +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +#define DEFBITS 512 + +static int dh_cb(int p, int n, BN_GENCB *cb); + +static struct { + int g; + char *outfile; +} cfg; + +static const struct option gendh_options[] = { + { + .name = "2", + .desc = "Generate DH parameters with a generator value of 2 " + "(default)", + .type = OPTION_VALUE, + .value = 2, + .opt.value = &cfg.g, + }, + { + .name = "5", + .desc = "Generate DH parameters with a generator value of 5", + .type = OPTION_VALUE, + .value = 5, + .opt.value = &cfg.g, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { NULL }, +}; + +static void +gendh_usage(void) +{ + fprintf(stderr, + "usage: gendh [-2 | -5] [-out file] [numbits]\n\n"); + options_usage(gendh_options); +} + +int +gendh_main(int argc, char **argv) +{ + BN_GENCB *cb = NULL; + DH *dh = NULL; + int ret = 1, numbits = DEFBITS; + BIO *out = NULL; + char *strbits = NULL; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + if ((cb = BN_GENCB_new()) == NULL) { + BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); + goto end; + } + + BN_GENCB_set(cb, dh_cb, bio_err); + + memset(&cfg, 0, sizeof(cfg)); + + cfg.g = 2; + + if (options_parse(argc, argv, gendh_options, &strbits, NULL) != 0) { + gendh_usage(); + goto end; + } + + if (strbits != NULL) { + const char *errstr; + numbits = strtonum(strbits, 0, INT_MAX, &errstr); + if (errstr) { + fprintf(stderr, "Invalid number of bits: %s\n", errstr); + goto end; + } + } + + out = BIO_new(BIO_s_file()); + if (out == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime," + " generator %d\n", numbits, cfg.g); + BIO_printf(bio_err, "This is going to take a long time\n"); + + if (((dh = DH_new()) == NULL) || + !DH_generate_parameters_ex(dh, numbits, cfg.g, cb)) + goto end; + + if (!PEM_write_bio_DHparams(out, dh)) + goto end; + ret = 0; + end: + if (ret != 0) + ERR_print_errors(bio_err); + BIO_free_all(out); + BN_GENCB_free(cb); + DH_free(dh); + + return (ret); +} + +static int +dh_cb(int p, int n, BN_GENCB *cb) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void) BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} +#endif diff --git a/apps/openssl/gendsa.c b/apps/openssl/gendsa.c new file mode 100644 index 0000000..00635c4 --- /dev/null +++ b/apps/openssl/gendsa.c @@ -0,0 +1,296 @@ +/* $OpenBSD: gendsa.c,v 1.17 2023/03/06 14:32:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include /* for OPENSSL_NO_DSA */ + + +#include +#include + +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static struct { + const EVP_CIPHER *enc; + char *outfile; + char *passargout; +} cfg; + +static const EVP_CIPHER *get_cipher_by_name(char *name) +{ + if (name == NULL || strcmp(name, "") == 0) + return (NULL); +#ifndef OPENSSL_NO_AES + else if (strcmp(name, "aes128") == 0) + return EVP_aes_128_cbc(); + else if (strcmp(name, "aes192") == 0) + return EVP_aes_192_cbc(); + else if (strcmp(name, "aes256") == 0) + return EVP_aes_256_cbc(); +#endif +#ifndef OPENSSL_NO_CAMELLIA + else if (strcmp(name, "camellia128") == 0) + return EVP_camellia_128_cbc(); + else if (strcmp(name, "camellia192") == 0) + return EVP_camellia_192_cbc(); + else if (strcmp(name, "camellia256") == 0) + return EVP_camellia_256_cbc(); +#endif +#ifndef OPENSSL_NO_DES + else if (strcmp(name, "des") == 0) + return EVP_des_cbc(); + else if (strcmp(name, "des3") == 0) + return EVP_des_ede3_cbc(); +#endif +#ifndef OPENSSL_NO_IDEA + else if (strcmp(name, "idea") == 0) + return EVP_idea_cbc(); +#endif + else + return (NULL); +} + +static int +set_enc(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.enc = get_cipher_by_name(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static const struct option gendsa_options[] = { +#ifndef OPENSSL_NO_AES + { + .name = "aes128", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "aes192", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "aes256", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { + .name = "camellia128", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "camellia192", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "camellia256", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_DES + { + .name = "des", + .desc = "Encrypt the generated key with DES in CBC mode", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "des3", + .desc = "Encrypt the generated key with DES in EDE CBC mode (168 bit key)", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_IDEA + { + .name = "idea", + .desc = "Encrypt the generated key with IDEA in CBC mode", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif + { + .name = "out", + .argname = "file", + .desc = "Output the key to 'file'", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passout", + .argname = "src", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { NULL }, +}; + +static void +gendsa_usage(void) +{ + fprintf(stderr, "usage: gendsa [-aes128 | -aes192 | -aes256 |\n"); + fprintf(stderr, " -camellia128 | -camellia192 | -camellia256 |\n"); + fprintf(stderr, " -des | -des3 | -idea] [-out file] [-passout src]"); + fprintf(stderr, " paramfile\n\n"); + options_usage(gendsa_options); + fprintf(stderr, "\n"); +} + +int +gendsa_main(int argc, char **argv) +{ + DSA *dsa = NULL; + int ret = 1; + char *dsaparams = NULL; + char *passout = NULL; + BIO *out = NULL, *in = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, gendsa_options, &dsaparams, NULL) != 0) { + gendsa_usage(); + goto end; + } + + if (dsaparams == NULL) { + gendsa_usage(); + goto end; + } + if (!app_passwd(bio_err, NULL, cfg.passargout, NULL, + &passout)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + in = BIO_new(BIO_s_file()); + if (!(BIO_read_filename(in, dsaparams))) { + perror(dsaparams); + goto end; + } + if ((dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL)) == NULL) { + BIO_printf(bio_err, "unable to load DSA parameter file\n"); + goto end; + } + BIO_free(in); + in = NULL; + + out = BIO_new(BIO_s_file()); + if (out == NULL) + goto end; + + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + BIO_printf(bio_err, "Generating DSA key, %d bits\n", + BN_num_bits(DSA_get0_p(dsa))); + if (!DSA_generate_key(dsa)) + goto end; + + if (!PEM_write_bio_DSAPrivateKey(out, dsa, cfg.enc, NULL, 0, + NULL, passout)) + goto end; + ret = 0; + end: + if (ret != 0) + ERR_print_errors(bio_err); + BIO_free(in); + BIO_free_all(out); + DSA_free(dsa); + free(passout); + + return (ret); +} diff --git a/apps/openssl/genpkey.c b/apps/openssl/genpkey.c new file mode 100644 index 0000000..10c5b0f --- /dev/null +++ b/apps/openssl/genpkey.c @@ -0,0 +1,418 @@ +/* $OpenBSD: genpkey.c,v 1.17 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006 + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "apps.h" + +#include +#include +#include + +static int init_keygen_file(BIO * err, EVP_PKEY_CTX **pctx, const char *file); +static int genpkey_cb(EVP_PKEY_CTX * ctx); + +static struct { + const EVP_CIPHER *cipher; + EVP_PKEY_CTX **ctx; + int do_param; + char *outfile; + int outformat; + char *passarg; + int text; +} cfg; + +static int +genpkey_opt_algorithm(char *arg) +{ + if (!init_gen_str(bio_err, cfg.ctx, arg, + cfg.do_param)) + return (1); + + return (0); +} + +static int +genpkey_opt_cipher(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if (cfg.do_param == 1) + return (1); + + if (strcmp(name, "none") == 0) { + cfg.cipher = NULL; + *argsused = 1; + return (0); + } + + if ((cfg.cipher = EVP_get_cipherbyname(name)) != NULL) { + *argsused = 1; + return (0); + } + + return (1); +} + +static int +genpkey_opt_paramfile(char *arg) +{ + if (cfg.do_param == 1) + return (1); + if (!init_keygen_file(bio_err, cfg.ctx, arg)) + return (1); + + return (0); +} + +static int +genpkey_opt_pkeyopt(char *arg) +{ + if (*cfg.ctx == NULL) { + BIO_puts(bio_err, "No keytype specified\n"); + return (1); + } + + if (pkey_ctrl_string(*cfg.ctx, arg) <= 0) { + BIO_puts(bio_err, "parameter setting error\n"); + ERR_print_errors(bio_err); + return (1); + } + + return (0); +} + +static const struct option genpkey_options[] = { + { + .name = "algorithm", + .argname = "name", + .desc = "Public key algorithm to use (must precede -pkeyopt)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = genpkey_opt_algorithm, + }, + { + .name = "genparam", + .desc = "Generate a set of parameters instead of a private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.do_param, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file to write to (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "paramfile", + .argname = "file", + .desc = "File to load public key algorithm parameters from\n" + "(must precede -pkeyopt)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = genpkey_opt_paramfile, + }, + { + .name = "pass", + .argname = "arg", + .desc = "Output file password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passarg, + }, + { + .name = "pkeyopt", + .argname = "opt:value", + .desc = "Set public key algorithm option to the given value", + .type = OPTION_ARG_FUNC, + .opt.argfunc = genpkey_opt_pkeyopt, + }, + { + .name = "text", + .desc = "Print the private/public key in human readable form", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = genpkey_opt_cipher, + }, + {NULL}, +}; + +static void +genpkey_usage(void) +{ + fprintf(stderr, + "usage: genpkey [-algorithm alg] [cipher] [-genparam] [-out file]\n" + " [-outform der | pem] [-paramfile file] [-pass arg]\n" + " [-pkeyopt opt:value] [-text]\n\n"); + options_usage(genpkey_options); +} + +int +genpkey_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + char *pass = NULL; + int ret = 1, rv; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.ctx = &ctx; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, genpkey_options, NULL, NULL) != 0) { + genpkey_usage(); + goto end; + } + + if (ctx == NULL) { + genpkey_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) { + BIO_puts(bio_err, "Error getting password\n"); + goto end; + } + if (cfg.outfile != NULL) { + if ((out = BIO_new_file(cfg.outfile, "wb")) == + NULL) { + BIO_printf(bio_err, "Can't open output file %s\n", + cfg.outfile); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + EVP_PKEY_CTX_set_cb(ctx, genpkey_cb); + EVP_PKEY_CTX_set_app_data(ctx, bio_err); + + if (cfg.do_param) { + if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error generating parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + } else { + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error generating key\n"); + ERR_print_errors(bio_err); + goto end; + } + } + + if (cfg.do_param) + rv = PEM_write_bio_Parameters(out, pkey); + else if (cfg.outformat == FORMAT_PEM) + rv = PEM_write_bio_PrivateKey(out, pkey, cfg.cipher, + NULL, 0, NULL, pass); + else if (cfg.outformat == FORMAT_ASN1) + rv = i2d_PrivateKey_bio(out, pkey); + else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + + if (rv <= 0) { + BIO_puts(bio_err, "Error writing key\n"); + ERR_print_errors(bio_err); + } + if (cfg.text) { + if (cfg.do_param) + rv = EVP_PKEY_print_params(out, pkey, 0, NULL); + else + rv = EVP_PKEY_print_private(out, pkey, 0, NULL); + + if (rv <= 0) { + BIO_puts(bio_err, "Error printing key\n"); + ERR_print_errors(bio_err); + } + } + ret = 0; + + end: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + BIO_free_all(out); + BIO_free(in); + free(pass); + + return ret; +} + +static int +init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file) +{ + BIO *pbio; + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + if (*pctx) { + BIO_puts(err, "Parameters already set!\n"); + return 0; + } + pbio = BIO_new_file(file, "r"); + if (!pbio) { + BIO_printf(err, "Can't open parameter file %s\n", file); + return 0; + } + pkey = PEM_read_bio_Parameters(pbio, NULL); + BIO_free(pbio); + + if (!pkey) { + BIO_printf(bio_err, "Error reading parameter file %s\n", file); + return 0; + } + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ctx) + goto err; + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto err; + EVP_PKEY_free(pkey); + *pctx = ctx; + return 1; + + err: + BIO_puts(err, "Error initializing context\n"); + ERR_print_errors(err); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return 0; + +} + +int +init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx, const char *algname, int do_param) +{ + const EVP_PKEY_ASN1_METHOD *ameth; + EVP_PKEY_CTX *ctx = NULL; + int pkey_id; + + if (*pctx) { + BIO_puts(err, "Algorithm already set!\n"); + return 0; + } + ameth = EVP_PKEY_asn1_find_str(NULL, algname, -1); + + if (!ameth) { + BIO_printf(bio_err, "Algorithm %s not found\n", algname); + return 0; + } + ERR_clear_error(); + + EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); + ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL); + + if (!ctx) + goto err; + if (do_param) { + if (EVP_PKEY_paramgen_init(ctx) <= 0) + goto err; + } else { + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto err; + } + + *pctx = ctx; + return 1; + + err: + BIO_printf(err, "Error initializing %s context\n", algname); + ERR_print_errors(err); + EVP_PKEY_CTX_free(ctx); + return 0; + +} + +static int +genpkey_cb(EVP_PKEY_CTX * ctx) +{ + char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p; + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(b, &c, 1); + (void) BIO_flush(b); + return 1; +} diff --git a/apps/openssl/genrsa.c b/apps/openssl/genrsa.c new file mode 100644 index 0000000..0b5323f --- /dev/null +++ b/apps/openssl/genrsa.c @@ -0,0 +1,389 @@ +/* $OpenBSD: genrsa.c,v 1.22 2023/03/06 14:32:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + + +#include +#include + +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include + +#define DEFBITS 2048 + +static int genrsa_cb(int p, int n, BN_GENCB *cb); + +static struct { + const EVP_CIPHER *enc; + unsigned long f4; + char *outfile; + char *passargout; +} cfg; + +static int +set_public_exponent(int argc, char **argv, int *argsused) +{ + char *option = argv[0]; + + if (strcmp(option, "-3") == 0) + cfg.f4 = 3; + else if (strcmp(option, "-f4") == 0 || strcmp(option, "-F4") == 0) + cfg.f4 = RSA_F4; + else + return (1); + + *argsused = 1; + return (0); +} + +static const EVP_CIPHER *get_cipher_by_name(char *name) +{ + if (name == NULL || strcmp(name, "") == 0) + return (NULL); +#ifndef OPENSSL_NO_AES + else if (strcmp(name, "aes128") == 0) + return EVP_aes_128_cbc(); + else if (strcmp(name, "aes192") == 0) + return EVP_aes_192_cbc(); + else if (strcmp(name, "aes256") == 0) + return EVP_aes_256_cbc(); +#endif +#ifndef OPENSSL_NO_CAMELLIA + else if (strcmp(name, "camellia128") == 0) + return EVP_camellia_128_cbc(); + else if (strcmp(name, "camellia192") == 0) + return EVP_camellia_192_cbc(); + else if (strcmp(name, "camellia256") == 0) + return EVP_camellia_256_cbc(); +#endif +#ifndef OPENSSL_NO_DES + else if (strcmp(name, "des") == 0) + return EVP_des_cbc(); + else if (strcmp(name, "des3") == 0) + return EVP_des_ede3_cbc(); +#endif +#ifndef OPENSSL_NO_IDEA + else if (strcmp(name, "idea") == 0) + return EVP_idea_cbc(); +#endif + else + return (NULL); +} + +static int +set_enc(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.enc = get_cipher_by_name(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static const struct option genrsa_options[] = { + { + .name = "3", + .desc = "Use 3 for the E value", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_public_exponent, + }, + { + .name = "f4", + .desc = "Use F4 (0x10001) for the E value", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_public_exponent, + }, + { + .name = "F4", + .desc = "Use F4 (0x10001) for the E value", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_public_exponent, + }, +#ifndef OPENSSL_NO_AES + { + .name = "aes128", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "aes192", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "aes256", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { + .name = "camellia128", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "camellia192", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "camellia256", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_DES + { + .name = "des", + .desc = "Encrypt the generated key with DES in CBC mode", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, + { + .name = "des3", + .desc = "Encrypt the generated key with DES in EDE CBC mode (168 bit key)", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif +#ifndef OPENSSL_NO_IDEA + { + .name = "idea", + .desc = "Encrypt the generated key with IDEA in CBC mode", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = set_enc, + }, +#endif + { + .name = "out", + .argname = "file", + .desc = "Output the key to 'file'", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passout", + .argname = "arg", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { NULL }, +}; + +static void +genrsa_usage(void) +{ + fprintf(stderr, "usage: genrsa [-3 | -f4] [-aes128 | -aes192 |"); + fprintf(stderr, " -aes256 |\n"); + fprintf(stderr, " -camellia128 | -camellia192 | -camellia256 |"); + fprintf(stderr, " -des | -des3 | -idea]\n"); + fprintf(stderr, " [-out file] [-passout arg] [numbits]\n\n"); + options_usage(genrsa_options); + fprintf(stderr, "\n"); +} + +int +genrsa_main(int argc, char **argv) +{ + BN_GENCB *cb = NULL; + int ret = 1; + int num = DEFBITS; + char *numbits = NULL; + char *passout = NULL; + BIO *out = NULL; + BIGNUM *bn = NULL; + RSA *rsa = NULL; + char *rsa_e_hex = NULL, *rsa_e_dec = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + if ((bn = BN_new()) == NULL) + goto err; + + if ((cb = BN_GENCB_new()) == NULL) { + BIO_printf(bio_err, "Error allocating BN_GENCB object\n"); + goto err; + } + + BN_GENCB_set(cb, genrsa_cb, bio_err); + + if ((out = BIO_new(BIO_s_file())) == NULL) { + BIO_printf(bio_err, "unable to create BIO for output\n"); + goto err; + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.f4 = RSA_F4; + + if (options_parse(argc, argv, genrsa_options, &numbits, NULL) != 0) { + genrsa_usage(); + goto err; + } + + if ((numbits != NULL) && + ((sscanf(numbits, "%d", &num) == 0) || (num < 0))) { + genrsa_usage(); + goto err; + } + + if (!app_passwd(bio_err, NULL, cfg.passargout, NULL, + &passout)) { + BIO_printf(bio_err, "Error getting password\n"); + goto err; + } + + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto err; + } + } + + BIO_printf(bio_err, "Generating RSA private key, %d bit long modulus\n", + num); + rsa = RSA_new(); + if (!rsa) + goto err; + + if (!BN_set_word(bn, cfg.f4) || + !RSA_generate_key_ex(rsa, num, bn, cb)) + goto err; + + if ((rsa_e_hex = BN_bn2hex(RSA_get0_e(rsa))) == NULL) + goto err; + if ((rsa_e_dec = BN_bn2dec(RSA_get0_e(rsa))) == NULL) + goto err; + + BIO_printf(bio_err, "e is %s (0x%s)\n", rsa_e_dec, rsa_e_hex); + { + PW_CB_DATA cb_data; + cb_data.password = passout; + cb_data.prompt_info = cfg.outfile; + if (!PEM_write_bio_RSAPrivateKey(out, rsa, cfg.enc, + NULL, 0, password_callback, &cb_data)) + goto err; + } + + ret = 0; + err: + BN_free(bn); + BN_GENCB_free(cb); + RSA_free(rsa); + BIO_free_all(out); + free(rsa_e_dec); + free(rsa_e_hex); + free(passout); + + if (ret != 0) + ERR_print_errors(bio_err); + + return (ret); +} + +static int +genrsa_cb(int p, int n, BN_GENCB *cb) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(cb), &c, 1); + (void) BIO_flush(BN_GENCB_get_arg(cb)); + return 1; +} diff --git a/apps/openssl/ocsp.c b/apps/openssl/ocsp.c new file mode 100644 index 0000000..cc942a4 --- /dev/null +++ b/apps/openssl/ocsp.c @@ -0,0 +1,1532 @@ +/* $OpenBSD: ocsp.c,v 1.23 2023/03/06 14:32:06 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef OPENSSL_NO_OCSP + +#include + +#include +#include +#include +#include +#include +#include + +/* Needs to be included before the openssl headers! */ +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +/* Maximum leeway in validity period: default 5 minutes */ +#define MAX_VALIDITY_PERIOD (5 * 60) + +static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, + const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID) *ids); +static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, + const EVP_MD *cert_id_md, X509 *issuer, STACK_OF(OCSP_CERTID) *ids); +static int print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, + STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, + long maxage); + +static int make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, + CA_DB *db, X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509) *rother, + unsigned long flags, int nmin, int ndays); + +static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser); +static BIO *init_responder(char *port); +static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, + char *port); +static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp); +static OCSP_RESPONSE *query_responder(BIO *err, BIO *cbio, char *path, + STACK_OF(CONF_VALUE) *headers, const char *host, OCSP_REQUEST *req, + int req_timeout); + +static struct { + int accept_count; + int add_nonce; + char *CAfile; + char *CApath; + X509 *cert; + const EVP_MD *cert_id_md; + STACK_OF(CONF_VALUE) *headers; + char *host; + STACK_OF(OCSP_CERTID) *ids; + int ignore_err; + X509 *issuer; + char *keyfile; + long maxage; + int ndays; + int nmin; + int no_usage; + int noverify; + long nsec; + char *outfile; + char *path; + char *port; + char *rca_filename; + char *rcertfile; + OCSP_REQUEST *req; + int req_text; + int req_timeout; + char *reqin; + STACK_OF(OPENSSL_STRING) *reqnames; + char *reqout; + int resp_text; + char *respin; + char *respout; + unsigned long rflags; + char *ridx_filename; + char *rkeyfile; + char *rsignfile; + char *sign_certfile; + unsigned long sign_flags; + char *signfile; + int use_ssl; + char *verify_certfile; + unsigned long verify_flags; +} cfg; + +static int +ocsp_opt_cert(char *arg) +{ + X509_free(cfg.cert); + cfg.cert = load_cert(bio_err, arg, FORMAT_PEM, NULL, + "certificate"); + if (cfg.cert == NULL) { + cfg.no_usage = 1; + return (1); + } + if (cfg.cert_id_md == NULL) + cfg.cert_id_md = EVP_sha1(); + if (!add_ocsp_cert(&cfg.req, cfg.cert, + cfg.cert_id_md, cfg.issuer, cfg.ids)) { + cfg.no_usage = 1; + return (1); + } + if (!sk_OPENSSL_STRING_push(cfg.reqnames, arg)) { + cfg.no_usage = 1; + return (1); + } + return (0); +} + +static int +ocsp_opt_cert_id_md(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.cert_id_md = EVP_get_digestbyname(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static int +ocsp_opt_header(int argc, char **argv, int *argsused) +{ + if (argc < 3 || argv[1] == NULL || argv[2] == NULL) + return (1); + + if (!X509V3_add_value(argv[1], argv[2], &cfg.headers)) { + cfg.no_usage = 1; + return (1); + } + + *argsused = 3; + return (0); +} + +static int +ocsp_opt_host(char *arg) +{ + if (cfg.use_ssl != -1) + return (1); + + cfg.host = arg; + return (0); +} + +static int +ocsp_opt_issuer(char *arg) +{ + X509_free(cfg.issuer); + cfg.issuer = load_cert(bio_err, arg, FORMAT_PEM, NULL, + "issuer certificate"); + if (cfg.issuer == NULL) { + cfg.no_usage = 1; + return (1); + } + return (0); +} + +static int +ocsp_opt_ndays(char *arg) +{ + const char *errstr = NULL; + + cfg.ndays = strtonum(arg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal update period %s: %s\n", + arg, errstr); + return (1); + } + return (0); +} + +static int +ocsp_opt_nmin(char *arg) +{ + const char *errstr = NULL; + + cfg.nmin = strtonum(arg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal update period %s: %s\n", + arg, errstr); + return (1); + } + + if (cfg.ndays != -1) + return (1); + + cfg.ndays = 0; + return (0); +} + +static int +ocsp_opt_nrequest(char *arg) +{ + const char *errstr = NULL; + + cfg.accept_count = strtonum(arg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal accept count %s: %s\n", + arg, errstr); + return (1); + } + return (0); +} + +static int +ocsp_opt_port(char *arg) +{ + if (cfg.use_ssl != -1) + return (1); + + cfg.port = arg; + return (0); +} + +static int +ocsp_opt_serial(char *arg) +{ + if (cfg.cert_id_md == NULL) + cfg.cert_id_md = EVP_sha1(); + if (!add_ocsp_serial(&cfg.req, arg, cfg.cert_id_md, + cfg.issuer, cfg.ids)) { + cfg.no_usage = 1; + return (1); + } + if (!sk_OPENSSL_STRING_push(cfg.reqnames, arg)) { + cfg.no_usage = 1; + return (1); + } + return (0); +} + +static int +ocsp_opt_status_age(char *arg) +{ + const char *errstr = NULL; + + cfg.maxage = strtonum(arg, 0, LONG_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal validity age %s: %s\n", + arg, errstr); + return (1); + } + return (0); +} + +static int +ocsp_opt_text(void) +{ + cfg.req_text = 1; + cfg.resp_text = 1; + return (0); +} + +static int +ocsp_opt_timeout(char *arg) +{ + const char *errstr = NULL; + + cfg.req_timeout = strtonum(arg, 0, INT_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal timeout value %s: %s\n", + arg, errstr); + return (1); + } + return (0); +} + +static int +ocsp_opt_url(char *arg) +{ + if (cfg.host == NULL && cfg.port == NULL && + cfg.path == NULL) { + if (!OCSP_parse_url(arg, &cfg.host, &cfg.port, + &cfg.path, &cfg.use_ssl)) { + BIO_printf(bio_err, "Error parsing URL\n"); + return (1); + } + } + return (0); +} + +static int +ocsp_opt_vafile(char *arg) +{ + cfg.verify_certfile = arg; + cfg.verify_flags |= OCSP_TRUSTOTHER; + return (0); +} + +static int +ocsp_opt_validity_period(char *arg) +{ + const char *errstr = NULL; + + cfg.nsec = strtonum(arg, 0, LONG_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "Illegal validity period %s: %s\n", + arg, errstr); + return (1); + } + return (0); +} + +static const struct option ocsp_options[] = { + { + .name = "CA", + .argname = "file", + .desc = "CA certificate corresponding to the revocation information", + .type = OPTION_ARG, + .opt.arg = &cfg.rca_filename, + }, + { + .name = "CAfile", + .argname = "file", + .desc = "Trusted certificates file", + .type = OPTION_ARG, + .opt.arg = &cfg.CAfile, + }, + { + .name = "CApath", + .argname = "directory", + .desc = "Trusted certificates directory", + .type = OPTION_ARG, + .opt.arg = &cfg.CApath, + }, + { + .name = "cert", + .argname = "file", + .desc = "Certificate to check", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_cert, + }, + { + .name = "header", + .argname = "name value", + .desc = "Add the header name with the value to the request", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = ocsp_opt_header, + }, + { + .name = "host", + .argname = "hostname:port", + .desc = "Send OCSP request to host on port", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_host, + }, + { + .name = "ignore_err", + .desc = "Ignore the invalid response", + .type = OPTION_FLAG, + .opt.flag = &cfg.ignore_err, + }, + { + .name = "index", + .argname = "indexfile", + .desc = "Certificate status index file", + .type = OPTION_ARG, + .opt.arg = &cfg.ridx_filename, + }, + { + .name = "issuer", + .argname = "file", + .desc = "Issuer certificate", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_issuer, + }, + { + .name = "ndays", + .argname = "days", + .desc = "Number of days before next update", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_ndays, + }, + { + .name = "nmin", + .argname = "minutes", + .desc = "Number of minutes before next update", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_nmin, + }, + { + .name = "no_cert_checks", + .desc = "Don't do additional checks on signing certificate", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOCHECKS, + }, + { + .name = "no_cert_verify", + .desc = "Don't check signing certificate", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOVERIFY, + }, + { + .name = "no_certs", + .desc = "Don't include any certificates in signed request", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.sign_flags, + .ulvalue = OCSP_NOCERTS, + }, + { + .name = "no_chain", + .desc = "Don't use certificates in the response", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOCHAIN, + }, + { + .name = "no_explicit", + .desc = "Don't check the explicit trust for OCSP signing", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOEXPLICIT, + }, + { + .name = "no_intern", + .desc = "Don't search certificates contained in response for signer", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOINTERN, + }, + { + .name = "no_nonce", + .desc = "Don't add OCSP nonce to request", + .type = OPTION_VALUE, + .opt.value = &cfg.add_nonce, + .value = 0, + }, + { + .name = "no_signature_verify", + .desc = "Don't check signature on response", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_NOSIGS, + }, + { + .name = "nonce", + .desc = "Add OCSP nonce to request", + .type = OPTION_VALUE, + .opt.value = &cfg.add_nonce, + .value = 2, + }, + { + .name = "noverify", + .desc = "Don't verify response at all", + .type = OPTION_FLAG, + .opt.flag = &cfg.noverify, + }, + { + .name = "nrequest", + .argname = "number", + .desc = "Number of requests to accept (default unlimited)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_nrequest, + }, + { + .name = "out", + .argname = "file", + .desc = "Output filename", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "path", + .argname = "path", + .desc = "Path to use in OCSP request", + .type = OPTION_ARG, + .opt.arg = &cfg.path, + }, + { + .name = "port", + .argname = "portnum", + .desc = "Port to run responder on", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_port, + }, + { + .name = "req_text", + .desc = "Print text form of request", + .type = OPTION_FLAG, + .opt.flag = &cfg.req_text, + }, + { + .name = "reqin", + .argname = "file", + .desc = "Read DER encoded OCSP request from \"file\"", + .type = OPTION_ARG, + .opt.arg = &cfg.reqin, + }, + { + .name = "reqout", + .argname = "file", + .desc = "Write DER encoded OCSP request to \"file\"", + .type = OPTION_ARG, + .opt.arg = &cfg.reqout, + }, + { + .name = "resp_key_id", + .desc = "Identify response by signing certificate key ID", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.rflags, + .ulvalue = OCSP_RESPID_KEY, + }, + { + .name = "resp_no_certs", + .desc = "Don't include any certificates in response", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.rflags, + .ulvalue = OCSP_NOCERTS, + }, + { + .name = "resp_text", + .desc = "Print text form of response", + .type = OPTION_FLAG, + .opt.flag = &cfg.resp_text, + }, + { + .name = "respin", + .argname = "file", + .desc = "Read DER encoded OCSP response from \"file\"", + .type = OPTION_ARG, + .opt.arg = &cfg.respin, + }, + { + .name = "respout", + .argname = "file", + .desc = "Write DER encoded OCSP response to \"file\"", + .type = OPTION_ARG, + .opt.arg = &cfg.respout, + }, + { + .name = "rkey", + .argname = "file", + .desc = "Responder key to sign responses with", + .type = OPTION_ARG, + .opt.arg = &cfg.rkeyfile, + }, + { + .name = "rother", + .argname = "file", + .desc = "Other certificates to include in response", + .type = OPTION_ARG, + .opt.arg = &cfg.rcertfile, + }, + { + .name = "rsigner", + .argname = "file", + .desc = "Responder certificate to sign responses with", + .type = OPTION_ARG, + .opt.arg = &cfg.rsignfile, + }, + { + .name = "serial", + .argname = "num", + .desc = "Serial number to check", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_serial, + }, + { + .name = "sign_other", + .argname = "file", + .desc = "Additional certificates to include in signed request", + .type = OPTION_ARG, + .opt.arg = &cfg.sign_certfile, + }, + { + .name = "signer", + .argname = "file", + .desc = "Certificate to sign OCSP request with", + .type = OPTION_ARG, + .opt.arg = &cfg.signfile, + }, + { + .name = "signkey", + .argname = "file", + .desc = "Private key to sign OCSP request with", + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "status_age", + .argname = "age", + .desc = "Maximum status age in seconds", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_status_age, + }, + { + .name = "text", + .desc = "Print text form of request and response", + .type = OPTION_FUNC, + .opt.func = ocsp_opt_text, + }, + { + .name = "timeout", + .argname = "seconds", + .desc = "Connection timeout to the OCSP responder in seconds", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_timeout, + }, + { + .name = "trust_other", + .desc = "Don't verify additional certificates", + .type = OPTION_UL_VALUE_OR, + .opt.ulvalue = &cfg.verify_flags, + .ulvalue = OCSP_TRUSTOTHER, + }, + { + .name = "url", + .argname = "responder_url", + .desc = "OCSP responder URL", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_url, + }, + { + .name = "VAfile", + .argname = "file", + .desc = "Explicitly trusted responder certificates", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_vafile, + }, + { + .name = "validity_period", + .argname = "n", + .desc = "Maximum validity discrepancy in seconds", + .type = OPTION_ARG_FUNC, + .opt.argfunc = ocsp_opt_validity_period, + }, + { + .name = "verify_other", + .argname = "file", + .desc = "Additional certificates to search for signer", + .type = OPTION_ARG, + .opt.arg = &cfg.verify_certfile, + }, + { + .name = NULL, + .desc = "", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = ocsp_opt_cert_id_md, + }, + { NULL }, +}; + +static void +ocsp_usage(void) +{ + fprintf(stderr, "usage: ocsp " + "[-CA file] [-CAfile file] [-CApath directory] [-cert file]\n" + " [-dgst alg] [-header name value] [-host hostname:port]\n" + " [-ignore_err] [-index indexfile] [-issuer file]\n" + " [-ndays days] [-nmin minutes] [-no_cert_checks]\n" + " [-no_cert_verify] [-no_certs] [-no_chain] [-no_explicit]\n" + " [-no_intern] [-no_nonce] [-no_signature_verify] [-nonce]\n" + " [-noverify] [-nrequest number] [-out file] [-path path]\n" + " [-port portnum] [-req_text] [-reqin file] [-reqout file]\n" + " [-resp_key_id] [-resp_no_certs] [-resp_text] [-respin file]\n" + " [-respout file] [-rkey file] [-rother file] [-rsigner file]\n" + " [-serial num] [-sign_other file] [-signer file]\n" + " [-signkey file] [-status_age age] [-text]\n" + " [-timeout seconds] [-trust_other] [-url responder_url]\n" + " [-VAfile file] [-validity_period nsec] [-verify_other file]\n"); + fprintf(stderr, "\n"); + options_usage(ocsp_options); + fprintf(stderr, "\n"); +} + +int +ocsp_main(int argc, char **argv) +{ + OCSP_RESPONSE *resp = NULL; + OCSP_BASICRESP *bs = NULL; + X509 *signer = NULL, *rsigner = NULL; + EVP_PKEY *key = NULL, *rkey = NULL; + BIO *acbio = NULL, *cbio = NULL; + BIO *derbio = NULL; + BIO *out = NULL; + X509_STORE *store = NULL; + STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL; + int ret = 1; + int badarg = 0; + int i; + X509 *rca_cert = NULL; + CA_DB *rdb = NULL; + + if (pledge("stdio cpath wpath rpath inet dns tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.accept_count = -1; + cfg.add_nonce = 1; + if ((cfg.ids = sk_OCSP_CERTID_new_null()) == NULL) + goto end; + cfg.maxage = -1; + cfg.ndays = -1; + cfg.nsec = MAX_VALIDITY_PERIOD; + cfg.req_timeout = -1; + if ((cfg.reqnames = sk_OPENSSL_STRING_new_null()) == NULL) + goto end; + cfg.use_ssl = -1; + + if (options_parse(argc, argv, ocsp_options, NULL, NULL) != 0) { + if (cfg.no_usage) + goto end; + else + badarg = 1; + } + + /* Have we anything to do? */ + if (!cfg.req && !cfg.reqin && !cfg.respin && + !(cfg.port && cfg.ridx_filename)) + badarg = 1; + + if (badarg) { + ocsp_usage(); + goto end; + } + if (cfg.outfile) + out = BIO_new_file(cfg.outfile, "w"); + else + out = BIO_new_fp(stdout, BIO_NOCLOSE); + + if (!out) { + BIO_printf(bio_err, "Error opening output file\n"); + goto end; + } + if (!cfg.req && (cfg.add_nonce != 2)) + cfg.add_nonce = 0; + + if (!cfg.req && cfg.reqin) { + derbio = BIO_new_file(cfg.reqin, "rb"); + if (!derbio) { + BIO_printf(bio_err, + "Error Opening OCSP request file\n"); + goto end; + } + cfg.req = d2i_OCSP_REQUEST_bio(derbio, NULL); + BIO_free(derbio); + if (!cfg.req) { + BIO_printf(bio_err, "Error reading OCSP request\n"); + goto end; + } + } + if (!cfg.req && cfg.port) { + acbio = init_responder(cfg.port); + if (!acbio) + goto end; + } + if (cfg.rsignfile && !rdb) { + if (!cfg.rkeyfile) + cfg.rkeyfile = cfg.rsignfile; + rsigner = load_cert(bio_err, cfg.rsignfile, FORMAT_PEM, + NULL, "responder certificate"); + if (!rsigner) { + BIO_printf(bio_err, + "Error loading responder certificate\n"); + goto end; + } + rca_cert = load_cert(bio_err, cfg.rca_filename, + FORMAT_PEM, NULL, "CA certificate"); + if (cfg.rcertfile) { + rother = load_certs(bio_err, cfg.rcertfile, + FORMAT_PEM, NULL, "responder other certificates"); + if (!rother) + goto end; + } + rkey = load_key(bio_err, cfg.rkeyfile, FORMAT_PEM, 0, + NULL, "responder private key"); + if (!rkey) + goto end; + } + if (acbio) + BIO_printf(bio_err, "Waiting for OCSP client connections...\n"); + + redo_accept: + + if (acbio) { + if (!do_responder(&cfg.req, &cbio, acbio, + cfg.port)) + goto end; + if (!cfg.req) { + resp = OCSP_response_create( + OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); + send_ocsp_response(cbio, resp); + goto done_resp; + } + } + if (!cfg.req && + (cfg.signfile || cfg.reqout || cfg.host || + cfg.add_nonce || cfg.ridx_filename)) { + BIO_printf(bio_err, + "Need an OCSP request for this operation!\n"); + goto end; + } + if (cfg.req && cfg.add_nonce) + OCSP_request_add1_nonce(cfg.req, NULL, -1); + + if (cfg.signfile) { + if (!cfg.keyfile) + cfg.keyfile = cfg.signfile; + signer = load_cert(bio_err, cfg.signfile, FORMAT_PEM, + NULL, "signer certificate"); + if (!signer) { + BIO_printf(bio_err, + "Error loading signer certificate\n"); + goto end; + } + if (cfg.sign_certfile) { + sign_other = load_certs(bio_err, + cfg.sign_certfile, FORMAT_PEM, NULL, + "signer certificates"); + if (!sign_other) + goto end; + } + key = load_key(bio_err, cfg.keyfile, FORMAT_PEM, 0, + NULL, "signer private key"); + if (!key) + goto end; + + if (!OCSP_request_sign(cfg.req, signer, key, NULL, + sign_other, cfg.sign_flags)) { + BIO_printf(bio_err, "Error signing OCSP request\n"); + goto end; + } + } + if (cfg.req_text && cfg.req) + OCSP_REQUEST_print(out, cfg.req, 0); + + if (cfg.reqout) { + derbio = BIO_new_file(cfg.reqout, "wb"); + if (!derbio) { + BIO_printf(bio_err, "Error opening file %s\n", + cfg.reqout); + goto end; + } + i2d_OCSP_REQUEST_bio(derbio, cfg.req); + BIO_free(derbio); + } + if (cfg.ridx_filename && (!rkey || !rsigner || !rca_cert)) { + BIO_printf(bio_err, + "Need a responder certificate, key and CA for this operation!\n"); + goto end; + } + if (cfg.ridx_filename && !rdb) { + rdb = load_index(cfg.ridx_filename, NULL); + if (!rdb) + goto end; + if (!index_index(rdb)) + goto end; + } + if (rdb) { + i = make_ocsp_response(&resp, cfg.req, rdb, rca_cert, + rsigner, rkey, rother, cfg.rflags, + cfg.nmin, cfg.ndays); + if (cbio) + send_ocsp_response(cbio, resp); + } else if (cfg.host) { + resp = process_responder(bio_err, cfg.req, + cfg.host, + cfg.path ? cfg.path : "/", + cfg.port, cfg.use_ssl, cfg.headers, + cfg.req_timeout); + if (!resp) + goto end; + } else if (cfg.respin) { + derbio = BIO_new_file(cfg.respin, "rb"); + if (!derbio) { + BIO_printf(bio_err, + "Error Opening OCSP response file\n"); + goto end; + } + resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); + BIO_free(derbio); + if (!resp) { + BIO_printf(bio_err, "Error reading OCSP response\n"); + goto end; + } + } else { + ret = 0; + goto end; + } + + done_resp: + + if (cfg.respout) { + derbio = BIO_new_file(cfg.respout, "wb"); + if (!derbio) { + BIO_printf(bio_err, "Error opening file %s\n", + cfg.respout); + goto end; + } + i2d_OCSP_RESPONSE_bio(derbio, resp); + BIO_free(derbio); + } + i = OCSP_response_status(resp); + + if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + BIO_printf(bio_err, "Responder Error: %s (%d)\n", + OCSP_response_status_str(i), i); + if (cfg.ignore_err) + goto redo_accept; + ret = 1; + goto end; + } + if (cfg.resp_text) + OCSP_RESPONSE_print(out, resp, 0); + + /* If running as responder don't verify our own response */ + if (cbio) { + if (cfg.accept_count > 0) + cfg.accept_count--; + /* Redo if more connections needed */ + if (cfg.accept_count) { + BIO_free_all(cbio); + cbio = NULL; + OCSP_REQUEST_free(cfg.req); + cfg.req = NULL; + OCSP_RESPONSE_free(resp); + resp = NULL; + goto redo_accept; + } + goto end; + } + if (!store) + store = setup_verify(bio_err, cfg.CAfile, + cfg.CApath); + if (!store) + goto end; + if (cfg.verify_certfile) { + verify_other = load_certs(bio_err, cfg.verify_certfile, + FORMAT_PEM, NULL, "validator certificate"); + if (!verify_other) + goto end; + } + bs = OCSP_response_get1_basic(resp); + + if (!bs) { + BIO_printf(bio_err, "Error parsing response\n"); + goto end; + } + if (!cfg.noverify) { + if (cfg.req && + ((i = OCSP_check_nonce(cfg.req, bs)) <= 0)) { + if (i == -1) { + BIO_printf(bio_err, + "WARNING: no nonce in response\n"); + } else { + BIO_printf(bio_err, "Nonce Verify error\n"); + goto end; + } + } + i = OCSP_basic_verify(bs, verify_other, store, + cfg.verify_flags); + if (i < 0) + i = OCSP_basic_verify(bs, NULL, store, 0); + + if (i <= 0) { + BIO_printf(bio_err, "Response Verify Failure\n"); + ERR_print_errors(bio_err); + } else { + BIO_printf(bio_err, "Response verify OK\n"); + } + } + if (!print_ocsp_summary(out, bs, cfg.req, cfg.reqnames, + cfg.ids, cfg.nsec, cfg.maxage)) + goto end; + + ret = 0; + + end: + ERR_print_errors(bio_err); + X509_free(signer); + X509_STORE_free(store); + EVP_PKEY_free(key); + EVP_PKEY_free(rkey); + X509_free(cfg.issuer); + X509_free(cfg.cert); + X509_free(rsigner); + X509_free(rca_cert); + free_index(rdb); + BIO_free_all(cbio); + BIO_free_all(acbio); + BIO_free(out); + OCSP_REQUEST_free(cfg.req); + OCSP_RESPONSE_free(resp); + OCSP_BASICRESP_free(bs); + sk_OPENSSL_STRING_free(cfg.reqnames); + sk_OCSP_CERTID_free(cfg.ids); + sk_X509_pop_free(sign_other, X509_free); + sk_X509_pop_free(verify_other, X509_free); + sk_CONF_VALUE_pop_free(cfg.headers, X509V3_conf_free); + + if (cfg.use_ssl != -1) { + free(cfg.host); + free(cfg.port); + free(cfg.path); + } + return (ret); +} + +static int +add_ocsp_cert(OCSP_REQUEST **req, X509 *cert, const EVP_MD *cert_id_md, + X509 *issuer, STACK_OF(OCSP_CERTID) *ids) +{ + OCSP_CERTID *id; + + if (!issuer) { + BIO_printf(bio_err, "No issuer certificate specified\n"); + return 0; + } + if (!*req) + *req = OCSP_REQUEST_new(); + if (!*req) + goto err; + id = OCSP_cert_to_id(cert_id_md, cert, issuer); + if (!id || !sk_OCSP_CERTID_push(ids, id)) + goto err; + if (!OCSP_request_add0_id(*req, id)) + goto err; + return 1; + + err: + BIO_printf(bio_err, "Error Creating OCSP request\n"); + return 0; +} + +static int +add_ocsp_serial(OCSP_REQUEST **req, char *serial, const EVP_MD *cert_id_md, + X509 *issuer, STACK_OF(OCSP_CERTID) *ids) +{ + OCSP_CERTID *id; + X509_NAME *iname; + ASN1_BIT_STRING *ikey; + ASN1_INTEGER *sno; + + if (!issuer) { + BIO_printf(bio_err, "No issuer certificate specified\n"); + return 0; + } + if (!*req) + *req = OCSP_REQUEST_new(); + if (!*req) + goto err; + iname = X509_get_subject_name(issuer); + ikey = X509_get0_pubkey_bitstr(issuer); + sno = s2i_ASN1_INTEGER(NULL, serial); + if (!sno) { + BIO_printf(bio_err, "Error converting serial number %s\n", + serial); + return 0; + } + id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno); + ASN1_INTEGER_free(sno); + if (!id || !sk_OCSP_CERTID_push(ids, id)) + goto err; + if (!OCSP_request_add0_id(*req, id)) + goto err; + return 1; + + err: + BIO_printf(bio_err, "Error Creating OCSP request\n"); + return 0; +} + +static int +print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req, + STACK_OF(OPENSSL_STRING) *names, STACK_OF(OCSP_CERTID) *ids, long nsec, + long maxage) +{ + OCSP_CERTID *id; + char *name; + int i; + int status, reason; + + ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; + + if (!bs || !req || !sk_OPENSSL_STRING_num(names) || + !sk_OCSP_CERTID_num(ids)) + return 1; + + for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) { + id = sk_OCSP_CERTID_value(ids, i); + name = sk_OPENSSL_STRING_value(names, i); + BIO_printf(out, "%s: ", name); + + if (!OCSP_resp_find_status(bs, id, &status, &reason, + &rev, &thisupd, &nextupd)) { + BIO_puts(out, "ERROR: No Status found.\n"); + continue; + } + /* + * Check validity: if invalid write to output BIO so we know + * which response this refers to. + */ + if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) { + BIO_puts(out, "WARNING: Status times invalid.\n"); + ERR_print_errors(out); + } + BIO_printf(out, "%s\n", OCSP_cert_status_str(status)); + + BIO_puts(out, "\tThis Update: "); + ASN1_GENERALIZEDTIME_print(out, thisupd); + BIO_puts(out, "\n"); + + if (nextupd) { + BIO_puts(out, "\tNext Update: "); + ASN1_GENERALIZEDTIME_print(out, nextupd); + BIO_puts(out, "\n"); + } + if (status != V_OCSP_CERTSTATUS_REVOKED) + continue; + + if (reason != -1) + BIO_printf(out, "\tReason: %s\n", + OCSP_crl_reason_str(reason)); + + BIO_puts(out, "\tRevocation Time: "); + ASN1_GENERALIZEDTIME_print(out, rev); + BIO_puts(out, "\n"); + } + + return 1; +} + + +static int +make_ocsp_response(OCSP_RESPONSE **resp, OCSP_REQUEST *req, CA_DB *db, + X509 *ca, X509 *rcert, EVP_PKEY *rkey, STACK_OF(X509) *rother, + unsigned long flags, int nmin, int ndays) +{ + ASN1_TIME *thisupd = NULL, *nextupd = NULL; + OCSP_CERTID *cid, *ca_id = NULL; + OCSP_BASICRESP *bs = NULL; + int i, id_count, ret = 1; + + id_count = OCSP_request_onereq_count(req); + + if (id_count <= 0) { + *resp = OCSP_response_create( + OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL); + goto end; + } + bs = OCSP_BASICRESP_new(); + thisupd = X509_gmtime_adj(NULL, 0); + if (ndays != -1) + nextupd = X509_gmtime_adj(NULL, nmin * 60 + ndays * 3600 * 24); + + /* Examine each certificate id in the request */ + for (i = 0; i < id_count; i++) { + OCSP_ONEREQ *one; + ASN1_INTEGER *serial; + char **inf; + ASN1_OBJECT *cert_id_md_oid; + const EVP_MD *cert_id_md; + one = OCSP_request_onereq_get0(req, i); + cid = OCSP_onereq_get0_id(one); + + OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid); + + cert_id_md = EVP_get_digestbyobj(cert_id_md_oid); + if (!cert_id_md) { + *resp = OCSP_response_create( + OCSP_RESPONSE_STATUS_INTERNALERROR, NULL); + goto end; + } + OCSP_CERTID_free(ca_id); + ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca); + + /* Is this request about our CA? */ + if (OCSP_id_issuer_cmp(ca_id, cid)) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, + thisupd, nextupd); + continue; + } + OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid); + inf = lookup_serial(db, serial); + if (!inf) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_UNKNOWN, 0, NULL, + thisupd, nextupd); + } else if (inf[DB_type][0] == DB_TYPE_VAL) { + OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_GOOD, 0, NULL, + thisupd, nextupd); + } else if (inf[DB_type][0] == DB_TYPE_REV) { + ASN1_OBJECT *inst = NULL; + ASN1_TIME *revtm = NULL; + ASN1_GENERALIZEDTIME *invtm = NULL; + OCSP_SINGLERESP *single; + int reason = -1; + + unpack_revinfo(&revtm, &reason, &inst, &invtm, + inf[DB_rev_date]); + single = OCSP_basic_add1_status(bs, cid, + V_OCSP_CERTSTATUS_REVOKED, + reason, revtm, + thisupd, nextupd); + if (invtm) + OCSP_SINGLERESP_add1_ext_i2d(single, + NID_invalidity_date, invtm, 0, 0); + else if (inst) + OCSP_SINGLERESP_add1_ext_i2d(single, + NID_hold_instruction_code, inst, 0, 0); + ASN1_OBJECT_free(inst); + ASN1_TIME_free(revtm); + ASN1_GENERALIZEDTIME_free(invtm); + } + } + + OCSP_copy_nonce(bs, req); + + OCSP_basic_sign(bs, rcert, rkey, NULL, rother, flags); + + *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs); + + end: + ASN1_TIME_free(thisupd); + ASN1_TIME_free(nextupd); + OCSP_CERTID_free(ca_id); + OCSP_BASICRESP_free(bs); + return ret; +} + +static char ** +lookup_serial(CA_DB *db, ASN1_INTEGER *ser) +{ + int i; + BIGNUM *bn = NULL; + char *itmp, *row[DB_NUMBER], **rrow; + + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + bn = ASN1_INTEGER_to_BN(ser, NULL); + OPENSSL_assert(bn); /* FIXME: should report an error at this + * point and abort */ + if (BN_is_zero(bn)) + itmp = strdup("00"); + else + itmp = BN_bn2hex(bn); + row[DB_serial] = itmp; + BN_free(bn); + rrow = TXT_DB_get_by_index(db->db, DB_serial, row); + free(itmp); + return rrow; +} + +/* Quick and dirty OCSP server: read in and parse input request */ + +static BIO * +init_responder(char *port) +{ + BIO *acbio = NULL, *bufbio = NULL; + + bufbio = BIO_new(BIO_f_buffer()); + if (!bufbio) + goto err; + acbio = BIO_new_accept(port); + if (!acbio) + goto err; + BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR); + BIO_set_accept_bios(acbio, bufbio); + bufbio = NULL; + + if (BIO_do_accept(acbio) <= 0) { + BIO_printf(bio_err, "Error setting up accept BIO\n"); + ERR_print_errors(bio_err); + goto err; + } + return acbio; + + err: + BIO_free_all(acbio); + BIO_free(bufbio); + return NULL; +} + +static int +do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, char *port) +{ + int have_post = 0, len; + OCSP_REQUEST *req = NULL; + char inbuf[1024]; + BIO *cbio = NULL; + + if (BIO_do_accept(acbio) <= 0) { + BIO_printf(bio_err, "Error accepting connection\n"); + ERR_print_errors(bio_err); + return 0; + } + cbio = BIO_pop(acbio); + *pcbio = cbio; + + for (;;) { + len = BIO_gets(cbio, inbuf, sizeof inbuf); + if (len <= 0) + return 1; + /* Look for "POST" signalling start of query */ + if (!have_post) { + if (strncmp(inbuf, "POST", 4)) { + BIO_printf(bio_err, "Invalid request\n"); + return 1; + } + have_post = 1; + } + /* Look for end of headers */ + if ((inbuf[0] == '\r') || (inbuf[0] == '\n')) + break; + } + + /* Try to read OCSP request */ + + req = d2i_OCSP_REQUEST_bio(cbio, NULL); + + if (!req) { + BIO_printf(bio_err, "Error parsing OCSP request\n"); + ERR_print_errors(bio_err); + } + *preq = req; + + return 1; +} + +static int +send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp) +{ + static const char http_resp[] = + "HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n" + "Content-Length: %d\r\n\r\n"; + + if (!cbio) + return 0; + BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL)); + i2d_OCSP_RESPONSE_bio(cbio, resp); + (void) BIO_flush(cbio); + return 1; +} + +static OCSP_RESPONSE * +query_responder(BIO *err, BIO *cbio, char *path, STACK_OF(CONF_VALUE) *headers, + const char *host, OCSP_REQUEST *req, int req_timeout) +{ + int fd; + int rv; + int i; + int have_host = 0; + OCSP_REQ_CTX *ctx = NULL; + OCSP_RESPONSE *rsp = NULL; + struct pollfd pfd[1]; + + if (req_timeout != -1) + BIO_set_nbio(cbio, 1); + + rv = BIO_do_connect(cbio); + + if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) { + BIO_puts(err, "Error connecting BIO\n"); + return NULL; + } + if (BIO_get_fd(cbio, &fd) < 0) { + BIO_puts(err, "Can't get connection fd\n"); + goto err; + } + if (req_timeout != -1 && rv <= 0) { + pfd[0].fd = fd; + pfd[0].events = POLLOUT; + rv = poll(pfd, 1, req_timeout * 1000); + if (rv == 0) { + BIO_puts(err, "Timeout on connect\n"); + return NULL; + } + if (rv == -1) { + BIO_puts(err, "Poll error\n"); + return NULL; + } + } + ctx = OCSP_sendreq_new(cbio, path, NULL, -1); + if (!ctx) + return NULL; + + for (i = 0; i < sk_CONF_VALUE_num(headers); i++) { + CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i); + if (strcasecmp("host", hdr->name) == 0) + have_host = 1; + if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value)) + goto err; + } + + if (!have_host) { + if (!OCSP_REQ_CTX_add1_header(ctx, "Host", host)) + goto err; + } + + if (!OCSP_REQ_CTX_set1_req(ctx, req)) + goto err; + + for (;;) { + rv = OCSP_sendreq_nbio(&rsp, ctx); + if (rv != -1) + break; + if (req_timeout == -1) + continue; + pfd[0].fd = fd; + if (BIO_should_read(cbio)) { + pfd[0].events = POLLIN; + } else if (BIO_should_write(cbio)) { + pfd[0].events = POLLOUT; + } else { + BIO_puts(err, "Unexpected retry condition\n"); + goto err; + } + rv = poll(pfd, 1, req_timeout * 1000); + if (rv == 0) { + BIO_puts(err, "Timeout on request\n"); + break; + } + if (rv == -1 || (pfd[0].revents & (POLLERR|POLLNVAL))) { + BIO_puts(err, "Poll error\n"); + break; + } + } + + err: + OCSP_REQ_CTX_free(ctx); + return rsp; +} + +OCSP_RESPONSE * +process_responder(BIO *err, OCSP_REQUEST *req, char *host, char *path, + char *port, int use_ssl, STACK_OF(CONF_VALUE) *headers, int req_timeout) +{ + BIO *cbio = NULL; + SSL_CTX *ctx = NULL; + OCSP_RESPONSE *resp = NULL; + + cbio = BIO_new_connect(host); + if (!cbio) { + BIO_printf(err, "Error creating connect BIO\n"); + goto end; + } + if (port) + BIO_set_conn_port(cbio, port); + if (use_ssl == 1) { + BIO *sbio; + ctx = SSL_CTX_new(TLS_client_method()); + if (ctx == NULL) { + BIO_printf(err, "Error creating SSL context.\n"); + goto end; + } + SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); + sbio = BIO_new_ssl(ctx, 1); + cbio = BIO_push(sbio, cbio); + } + resp = query_responder(err, cbio, path, headers, host, req, req_timeout); + if (!resp) + BIO_printf(bio_err, "Error querying OCSP responder\n"); + + end: + BIO_free_all(cbio); + SSL_CTX_free(ctx); + return resp; +} +#endif diff --git a/apps/openssl/openssl.c b/apps/openssl/openssl.c new file mode 100644 index 0000000..15888c7 --- /dev/null +++ b/apps/openssl/openssl.c @@ -0,0 +1,736 @@ +/* $OpenBSD: openssl.c,v 1.35 2023/06/11 13:02:10 jsg Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "progs.h" +#include "s_apps.h" + +#define FUNC_TYPE_GENERAL 1 +#define FUNC_TYPE_MD 2 +#define FUNC_TYPE_CIPHER 3 +#define FUNC_TYPE_PKEY 4 +#define FUNC_TYPE_MD_ALG 5 +#define FUNC_TYPE_CIPHER_ALG 6 + +typedef struct { + int type; + const char *name; + int (*func)(int argc, char **argv); +} FUNCTION; + +DECLARE_LHASH_OF(FUNCTION); + +FUNCTION functions[] = { + + /* General functions. */ + { FUNC_TYPE_GENERAL, "asn1parse", asn1parse_main }, + { FUNC_TYPE_GENERAL, "ca", ca_main }, + { FUNC_TYPE_GENERAL, "certhash", certhash_main }, + { FUNC_TYPE_GENERAL, "ciphers", ciphers_main }, +#ifndef OPENSSL_NO_CMS + { FUNC_TYPE_GENERAL, "cms", cms_main }, +#endif + { FUNC_TYPE_GENERAL, "crl2pkcs7", crl2pkcs7_main }, + { FUNC_TYPE_GENERAL, "crl", crl_main }, + { FUNC_TYPE_GENERAL, "dgst", dgst_main }, + { FUNC_TYPE_GENERAL, "enc", enc_main }, + { FUNC_TYPE_GENERAL, "errstr", errstr_main }, + { FUNC_TYPE_GENERAL, "genpkey", genpkey_main }, +#ifndef OPENSSL_NO_OCSP + { FUNC_TYPE_GENERAL, "ocsp", ocsp_main }, +#endif + { FUNC_TYPE_GENERAL, "passwd", passwd_main }, + { FUNC_TYPE_GENERAL, "pkcs7", pkcs7_main }, + { FUNC_TYPE_GENERAL, "pkcs8", pkcs8_main }, +#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) + { FUNC_TYPE_GENERAL, "pkcs12", pkcs12_main }, +#endif + { FUNC_TYPE_GENERAL, "pkey", pkey_main }, + { FUNC_TYPE_GENERAL, "pkeyparam", pkeyparam_main }, + { FUNC_TYPE_GENERAL, "pkeyutl", pkeyutl_main }, + { FUNC_TYPE_GENERAL, "prime", prime_main }, + { FUNC_TYPE_GENERAL, "rand", rand_main }, + { FUNC_TYPE_GENERAL, "req", req_main }, + { FUNC_TYPE_GENERAL, "s_client", s_client_main }, + { FUNC_TYPE_GENERAL, "s_server", s_server_main }, + { FUNC_TYPE_GENERAL, "s_time", s_time_main }, + { FUNC_TYPE_GENERAL, "sess_id", sess_id_main }, + { FUNC_TYPE_GENERAL, "smime", smime_main }, +#ifndef OPENSSL_NO_SPEED + { FUNC_TYPE_GENERAL, "speed", speed_main }, +#endif + { FUNC_TYPE_GENERAL, "spkac", spkac_main }, + { FUNC_TYPE_GENERAL, "ts", ts_main }, + { FUNC_TYPE_GENERAL, "verify", verify_main }, + { FUNC_TYPE_GENERAL, "version", version_main }, + { FUNC_TYPE_GENERAL, "x509", x509_main }, + +#ifndef OPENSSL_NO_DH + { FUNC_TYPE_GENERAL, "dh", dh_main }, + { FUNC_TYPE_GENERAL, "dhparam", dhparam_main }, + { FUNC_TYPE_GENERAL, "gendh", gendh_main }, +#endif +#ifndef OPENSSL_NO_DSA + { FUNC_TYPE_GENERAL, "dsa", dsa_main }, + { FUNC_TYPE_GENERAL, "dsaparam", dsaparam_main }, + { FUNC_TYPE_GENERAL, "gendsa", gendsa_main }, +#endif +#ifndef OPENSSL_NO_EC + { FUNC_TYPE_GENERAL, "ec", ec_main }, + { FUNC_TYPE_GENERAL, "ecparam", ecparam_main }, +#endif +#ifndef OPENSSL_NO_RSA + { FUNC_TYPE_GENERAL, "genrsa", genrsa_main }, + { FUNC_TYPE_GENERAL, "rsa", rsa_main }, + { FUNC_TYPE_GENERAL, "rsautl", rsautl_main }, +#endif + + /* Message Digests. */ +#ifndef OPENSSL_NO_GOST + { FUNC_TYPE_MD, "gost-mac", dgst_main }, + { FUNC_TYPE_MD, "md_gost94", dgst_main }, + { FUNC_TYPE_MD, "streebog256", dgst_main }, + { FUNC_TYPE_MD, "streebog512", dgst_main }, +#endif +#ifndef OPENSSL_NO_MD4 + { FUNC_TYPE_MD, "md4", dgst_main }, +#endif +#ifndef OPENSSL_NO_MD5 + { FUNC_TYPE_MD, "md5", dgst_main }, +#endif +#ifndef OPENSSL_NO_RIPEMD160 + { FUNC_TYPE_MD, "ripemd160", dgst_main }, +#endif +#ifndef OPENSSL_NO_SHA1 + { FUNC_TYPE_MD, "sha1", dgst_main }, +#endif +#ifndef OPENSSL_NO_SHA224 + { FUNC_TYPE_MD, "sha224", dgst_main }, +#endif +#ifndef OPENSSL_NO_SHA256 + { FUNC_TYPE_MD, "sha256", dgst_main }, +#endif +#ifndef OPENSSL_NO_SHA384 + { FUNC_TYPE_MD, "sha384", dgst_main }, +#endif +#ifndef OPENSSL_NO_SHA512 + { FUNC_TYPE_MD, "sha512", dgst_main }, +#endif +#ifndef OPENSSL_NO_SM3 + { FUNC_TYPE_MD, "sm3", dgst_main }, + { FUNC_TYPE_MD, "sm3WithRSAEncryption", dgst_main }, +#endif +#ifndef OPENSSL_NO_WHIRLPOOL + { FUNC_TYPE_MD, "whirlpool", dgst_main }, +#endif + + /* Ciphers. */ + { FUNC_TYPE_CIPHER, "base64", enc_main }, +#ifndef OPENSSL_NO_AES + { FUNC_TYPE_CIPHER, "aes-128-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "aes-128-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "aes-192-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "aes-192-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "aes-256-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "aes-256-ecb", enc_main }, +#endif +#ifndef OPENSSL_NO_BF + { FUNC_TYPE_CIPHER, "bf", enc_main }, + { FUNC_TYPE_CIPHER, "bf-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "bf-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "bf-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "bf-ofb", enc_main }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { FUNC_TYPE_CIPHER, "camellia-128-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "camellia-128-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "camellia-192-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "camellia-192-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "camellia-256-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "camellia-256-ecb", enc_main }, +#endif +#ifndef OPENSSL_NO_CAST + { FUNC_TYPE_CIPHER, "cast", enc_main }, + { FUNC_TYPE_CIPHER, "cast5-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "cast5-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "cast5-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "cast5-ofb", enc_main }, + { FUNC_TYPE_CIPHER, "cast-cbc", enc_main }, +#endif +#ifndef OPENSSL_NO_CHACHA + { FUNC_TYPE_CIPHER, "chacha", enc_main }, +#endif +#ifndef OPENSSL_NO_DES + { FUNC_TYPE_CIPHER, "des", enc_main }, + { FUNC_TYPE_CIPHER, "des3", enc_main }, + { FUNC_TYPE_CIPHER, "desx", enc_main }, + { FUNC_TYPE_CIPHER, "des-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede3", enc_main }, + { FUNC_TYPE_CIPHER, "des-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede3-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "des-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede3-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ofb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede-ofb", enc_main }, + { FUNC_TYPE_CIPHER, "des-ede3-ofb", enc_main }, +#endif +#ifndef OPENSSL_NO_IDEA + { FUNC_TYPE_CIPHER, "idea", enc_main }, + { FUNC_TYPE_CIPHER, "idea-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "idea-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "idea-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "idea-ofb", enc_main }, +#endif +#ifndef OPENSSL_NO_RC2 + { FUNC_TYPE_CIPHER, "rc2", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-cfb", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-ofb", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-64-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "rc2-40-cbc", enc_main }, +#endif +#ifndef OPENSSL_NO_RC4 + { FUNC_TYPE_CIPHER, "rc4", enc_main }, + { FUNC_TYPE_CIPHER, "rc4-40", enc_main }, +#endif +#ifndef OPENSSL_NO_SM4 + { FUNC_TYPE_CIPHER, "sm4", enc_main }, + { FUNC_TYPE_CIPHER, "sm4-ecb", enc_main }, + { FUNC_TYPE_CIPHER, "sm4-cbc", enc_main }, + { FUNC_TYPE_CIPHER, "sm4-ofb", enc_main }, + { FUNC_TYPE_CIPHER, "sm4-cfb", enc_main }, +#endif + { 0, NULL, NULL } +}; + +static void openssl_startup(void); +static void openssl_shutdown(void); + +/* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the + * base prototypes (we cast each variable inside the function to the required + * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper + * functions. */ + +static LHASH_OF(FUNCTION) *prog_init(void); +static int do_cmd(LHASH_OF(FUNCTION) *prog, int argc, char *argv[]); +static void print_help(void); +static void list_pkey(BIO * out); +static void list_cipher(BIO * out); +static void list_md(BIO * out); +char *default_config_file = NULL; + +CONF *config = NULL; +BIO *bio_err = NULL; + +static void +openssl_startup(void) +{ +#ifndef _WIN32 + signal(SIGPIPE, SIG_IGN); +#endif + + OpenSSL_add_all_algorithms(); + SSL_library_init(); + SSL_load_error_strings(); + + setup_ui(); +} + +static void +openssl_shutdown(void) +{ + CONF_modules_unload(1); + destroy_ui(); + OBJ_cleanup(); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_thread_state(NULL); + ERR_free_strings(); +} + +int +main(int argc, char **argv) +{ + char *to_free = NULL; + int i, ret = 0; + char *p; + LHASH_OF(FUNCTION) * prog = NULL; + long errline; + + if (pledge("stdio cpath wpath rpath inet dns proc flock tty", NULL) == -1) { + fprintf(stderr, "openssl: pledge: %s\n", strerror(errno)); + exit(1); + } + + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + if (bio_err == NULL) { + fprintf(stderr, "openssl: failed to initialise bio_err\n"); + exit(1); + } + + if (BIO_sock_init() != 1) { + BIO_printf(bio_err, "BIO_sock_init failed\n"); + exit(1); + } + + openssl_startup(); + + /* Lets load up our environment a little */ + p = getenv("OPENSSL_CONF"); + if (p == NULL) { + p = to_free = make_config_name(); + if (p == NULL) { + BIO_printf(bio_err, "error making config file name\n"); + goto end; + } + } + + default_config_file = p; + + config = NCONF_new(NULL); + i = NCONF_load(config, p, &errline); + if (i == 0) { + if (ERR_GET_REASON(ERR_peek_last_error()) == + CONF_R_NO_SUCH_FILE) { + BIO_printf(bio_err, + "WARNING: can't open config file: %s\n", p); + ERR_clear_error(); + NCONF_free(config); + config = NULL; + } else { + ERR_print_errors(bio_err); + NCONF_free(config); + exit(1); + } + } + + if (!load_config(bio_err, NULL)) { + BIO_printf(bio_err, "failed to load configuration\n"); + goto end; + } + + prog = prog_init(); + + /* + * ok, now check that there are not arguments, if there are, run with + * them, shifting the executable name off the front + */ + argc--; + argv++; + + if (argc < 1) { + print_help(); + goto end; + } + + ret = do_cmd(prog, argc, argv); + if (ret < 0) + ret = 0; + + end: + free(to_free); + + if (config != NULL) { + NCONF_free(config); + config = NULL; + } + if (prog != NULL) + lh_FUNCTION_free(prog); + + openssl_shutdown(); + + if (bio_err != NULL) { + BIO_free(bio_err); + bio_err = NULL; + } + return (ret); +} + +#define LIST_STANDARD_COMMANDS "list-standard-commands" +#define LIST_MESSAGE_DIGEST_COMMANDS "list-message-digest-commands" +#define LIST_MESSAGE_DIGEST_ALGORITHMS "list-message-digest-algorithms" +#define LIST_CIPHER_COMMANDS "list-cipher-commands" +#define LIST_CIPHER_ALGORITHMS "list-cipher-algorithms" +#define LIST_PUBLIC_KEY_ALGORITHMS "list-public-key-algorithms" + + +static int +do_cmd(LHASH_OF(FUNCTION) * prog, int argc, char *argv[]) +{ + FUNCTION f, *fp; + int ret = 1; + + if (argc <= 0 || argv[0] == NULL) + return 0; + + f.name = argv[0]; + fp = lh_FUNCTION_retrieve(prog, &f); + if (fp == NULL) { + if (EVP_get_digestbyname(argv[0])) { + f.type = FUNC_TYPE_MD; + f.func = dgst_main; + fp = &f; + } else if (EVP_get_cipherbyname(argv[0])) { + f.type = FUNC_TYPE_CIPHER; + f.func = enc_main; + fp = &f; + } + } + + if (fp != NULL) + return fp->func(argc, argv); + + if (strcmp(argv[0], "help") == 0) { + print_help(); + return 0; + } + + if ((strncmp(argv[0], "no-", 3)) == 0) { + BIO *bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); + f.name = argv[0] + 3; + ret = (lh_FUNCTION_retrieve(prog, &f) != NULL); + if (!ret) + BIO_printf(bio_stdout, "%s\n", argv[0]); + else + BIO_printf(bio_stdout, "%s\n", argv[0] + 3); + BIO_free_all(bio_stdout); + return ret; + } + + if ((strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) || + (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) || + (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) || + (strcmp(argv[0], LIST_CIPHER_COMMANDS) == 0) || + (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) || + (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0)) { + int list_type; + BIO *bio_stdout; + + if (strcmp(argv[0], LIST_STANDARD_COMMANDS) == 0) + list_type = FUNC_TYPE_GENERAL; + else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_COMMANDS) == 0) + list_type = FUNC_TYPE_MD; + else if (strcmp(argv[0], LIST_MESSAGE_DIGEST_ALGORITHMS) == 0) + list_type = FUNC_TYPE_MD_ALG; + else if (strcmp(argv[0], LIST_PUBLIC_KEY_ALGORITHMS) == 0) + list_type = FUNC_TYPE_PKEY; + else if (strcmp(argv[0], LIST_CIPHER_ALGORITHMS) == 0) + list_type = FUNC_TYPE_CIPHER_ALG; + else /* strcmp(argv[0],LIST_CIPHER_COMMANDS) == 0 */ + list_type = FUNC_TYPE_CIPHER; + bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); + + if (list_type == FUNC_TYPE_PKEY) + list_pkey(bio_stdout); + if (list_type == FUNC_TYPE_MD_ALG) + list_md(bio_stdout); + if (list_type == FUNC_TYPE_CIPHER_ALG) + list_cipher(bio_stdout); + else { + for (fp = functions; fp->name != NULL; fp++) + if (fp->type == list_type) + BIO_printf(bio_stdout, "%s\n", + fp->name); + } + BIO_free_all(bio_stdout); + return 0; + } + + BIO_printf(bio_err, + "openssl:Error: '%s' is an invalid command.\n", + argv[0]); + print_help(); + + return 1; +} + +static void +print_help(void) +{ + FUNCTION *fp; + int i = 0; + int tp = 0; + int nl; + + BIO_printf(bio_err, "\nStandard commands"); + for (fp = functions; fp->name != NULL; fp++) { + nl = 0; +#ifdef OPENSSL_NO_CAMELLIA + if (((i++) % 5) == 0) +#else + if (((i++) % 4) == 0) +#endif + { + BIO_printf(bio_err, "\n"); + nl = 1; + } + if (fp->type != tp) { + tp = fp->type; + if (!nl) + BIO_printf(bio_err, "\n"); + if (tp == FUNC_TYPE_MD) { + i = 1; + BIO_printf(bio_err, + "\nMessage Digest commands (see the `dgst' command for more details)\n"); + } else if (tp == FUNC_TYPE_CIPHER) { + i = 1; + BIO_printf(bio_err, "\nCipher commands (see the `enc' command for more details)\n"); + } + } +#ifdef OPENSSL_NO_CAMELLIA + BIO_printf(bio_err, "%-15s", fp->name); +#else + BIO_printf(bio_err, "%-18s", fp->name); +#endif + } + + BIO_printf(bio_err, "\n\n"); +} + +static int +SortFnByName(const void *_f1, const void *_f2) +{ + const FUNCTION *f1 = _f1; + const FUNCTION *f2 = _f2; + + if (f1->type != f2->type) + return f1->type - f2->type; + return strcmp(f1->name, f2->name); +} + +static void +list_pkey(BIO * out) +{ + int i; + + for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) { + const EVP_PKEY_ASN1_METHOD *ameth; + int pkey_id, pkey_base_id, pkey_flags; + const char *pinfo, *pem_str; + ameth = EVP_PKEY_asn1_get0(i); + EVP_PKEY_asn1_get0_info(&pkey_id, &pkey_base_id, &pkey_flags, + &pinfo, &pem_str, ameth); + if (pkey_flags & ASN1_PKEY_ALIAS) { + BIO_printf(out, "Name: %s\n", + OBJ_nid2ln(pkey_id)); + BIO_printf(out, "\tType: Alias to %s\n", + OBJ_nid2ln(pkey_base_id)); + } else { + BIO_printf(out, "Name: %s\n", pinfo); + BIO_printf(out, "\tType: %s Algorithm\n", + pkey_flags & ASN1_PKEY_DYNAMIC ? + "External" : "Builtin"); + BIO_printf(out, "\tOID: %s\n", OBJ_nid2ln(pkey_id)); + if (pem_str == NULL) + pem_str = "(none)"; + BIO_printf(out, "\tPEM string: %s\n", pem_str); + } + + } +} + +static void +list_cipher_fn(const EVP_CIPHER * c, const char *from, const char *to, + void *arg) +{ + if (c) + BIO_printf(arg, "%s\n", EVP_CIPHER_name(c)); + else { + if (!from) + from = ""; + if (!to) + to = ""; + BIO_printf(arg, "%s => %s\n", from, to); + } +} + +static void +list_cipher(BIO * out) +{ + EVP_CIPHER_do_all_sorted(list_cipher_fn, out); +} + +static void +list_md_fn(const EVP_MD * m, const char *from, const char *to, void *arg) +{ + if (m) + BIO_printf(arg, "%s\n", EVP_MD_name(m)); + else { + if (!from) + from = ""; + if (!to) + to = ""; + BIO_printf(arg, "%s => %s\n", from, to); + } +} + +static void +list_md(BIO * out) +{ + EVP_MD_do_all_sorted(list_md_fn, out); +} + +static int +function_cmp(const FUNCTION * a, const FUNCTION * b) +{ + return strncmp(a->name, b->name, 8); +} + +static IMPLEMENT_LHASH_COMP_FN(function, FUNCTION) + +static unsigned long +function_hash(const FUNCTION * a) +{ + return lh_strhash(a->name); +} + +static IMPLEMENT_LHASH_HASH_FN(function, FUNCTION) + +static LHASH_OF(FUNCTION) * +prog_init(void) +{ + LHASH_OF(FUNCTION) * ret; + FUNCTION *f; + size_t i; + + /* Purely so it looks nice when the user hits ? */ + for (i = 0, f = functions; f->name != NULL; ++f, ++i) + ; + qsort(functions, i, sizeof *functions, SortFnByName); + + if ((ret = lh_FUNCTION_new()) == NULL) + return (NULL); + + for (f = functions; f->name != NULL; f++) + (void) lh_FUNCTION_insert(ret, f); + return (ret); +} diff --git a/apps/openssl/passwd.c b/apps/openssl/passwd.c new file mode 100644 index 0000000..a8dfa27 --- /dev/null +++ b/apps/openssl/passwd.c @@ -0,0 +1,524 @@ +/* $OpenBSD: passwd.c,v 1.14 2023/03/06 14:32:06 tb Exp $ */ + +#if defined OPENSSL_NO_MD5 +#define NO_MD5CRYPT_1 +#endif + +#if !defined(OPENSSL_NO_DES) || !defined(NO_MD5CRYPT_1) + +#include +#include + +#include "apps.h" + +#include +#include +#include + +#ifndef OPENSSL_NO_DES +#include +#endif + +#ifndef NO_MD5CRYPT_1 +#include +#endif + +static unsigned const char cov_2char[64] = { + /* from crypto/des/fcrypt.c */ + 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, + 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, + 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, + 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A +}; + +static int +do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, + char *passwd, BIO * out, int quiet, int table, int reverse, + size_t pw_maxlen, int usecrypt, int use1, int useapr1); + +static struct { + char *infile; + int in_stdin; + int noverify; + int quiet; + int reverse; + char *salt; + int table; + int use1; + int useapr1; + int usecrypt; +} cfg; + +static const struct option passwd_options[] = { +#ifndef NO_MD5CRYPT_1 + { + .name = "1", + .desc = "Use MD5 based BSD password algorithm 1", + .type = OPTION_FLAG, + .opt.flag = &cfg.use1, + }, + { + .name = "apr1", + .desc = "Use apr1 algorithm (Apache variant of BSD algorithm)", + .type = OPTION_FLAG, + .opt.flag = &cfg.useapr1, + }, +#endif +#ifndef OPENSSL_NO_DES + { + .name = "crypt", + .desc = "Use crypt algorithm (default)", + .type = OPTION_FLAG, + .opt.flag = &cfg.usecrypt, + }, +#endif + { + .name = "in", + .argname = "file", + .desc = "Read passwords from specified file", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "noverify", + .desc = "Do not verify password", + .type = OPTION_FLAG, + .opt.flag = &cfg.noverify, + }, + { + .name = "quiet", + .desc = "Do not output warnings", + .type = OPTION_FLAG, + .opt.flag = &cfg.quiet, + }, + { + .name = "reverse", + .desc = "Reverse table columns (requires -table)", + .type = OPTION_FLAG, + .opt.flag = &cfg.reverse, + }, + { + .name = "salt", + .argname = "string", + .desc = "Use specified salt", + .type = OPTION_ARG, + .opt.arg = &cfg.salt, + }, + { + .name = "stdin", + .desc = "Read passwords from stdin", + .type = OPTION_FLAG, + .opt.flag = &cfg.in_stdin, + }, + { + .name = "table", + .desc = "Output cleartext and hashed passwords (tab separated)", + .type = OPTION_FLAG, + .opt.flag = &cfg.table, + }, + { NULL }, +}; + +static void +passwd_usage(void) +{ + fprintf(stderr, "usage: passwd [-1 | -apr1 | -crypt] [-in file] " + "[-noverify] [-quiet]\n" + " [-reverse] [-salt string] [-stdin] [-table] [password]\n\n"); + options_usage(passwd_options); +} + +int +passwd_main(int argc, char **argv) +{ + char *passwd = NULL, **passwds = NULL; + char *salt_malloc = NULL, *passwd_malloc = NULL; + size_t passwd_malloc_size = 0; + BIO *in = NULL, *out = NULL; + int badopt = 0; + int passed_salt = 0; + size_t pw_maxlen = 0; + int argsused; + int ret = 1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, passwd_options, NULL, &argsused) != 0) { + passwd_usage(); + goto err; + } + + if (argsused < argc) + passwds = &argv[argsused]; + if (cfg.salt != NULL) + passed_salt = 1; + + if (!cfg.usecrypt && !cfg.use1 && + !cfg.useapr1) + cfg.usecrypt = 1; /* use default */ + if (cfg.usecrypt + cfg.use1 + + cfg.useapr1 > 1) + badopt = 1; /* conflicting options */ + + /* Reject unsupported algorithms */ +#ifdef OPENSSL_NO_DES + if (cfg.usecrypt) + badopt = 1; +#endif +#ifdef NO_MD5CRYPT_1 + if (cfg.use1 || cfg.useapr1) + badopt = 1; +#endif + + if (badopt) { + passwd_usage(); + goto err; + } + + if ((out = BIO_new(BIO_s_file())) == NULL) + goto err; + BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); + + if (cfg.infile != NULL || cfg.in_stdin) { + if ((in = BIO_new(BIO_s_file())) == NULL) + goto err; + if (cfg.infile != NULL) { + assert(cfg.in_stdin == 0); + if (BIO_read_filename(in, cfg.infile) <= 0) + goto err; + } else { + assert(cfg.in_stdin); + BIO_set_fp(in, stdin, BIO_NOCLOSE); + } + } + if (cfg.usecrypt) + pw_maxlen = 8; + else if (cfg.use1 || cfg.useapr1) + pw_maxlen = 256;/* arbitrary limit, should be enough for most + * passwords */ + + if (passwds == NULL) { + /* no passwords on the command line */ + + passwd_malloc_size = pw_maxlen + 2; + /* longer than necessary so that we can warn about truncation */ + passwd = passwd_malloc = malloc(passwd_malloc_size); + if (passwd_malloc == NULL) + goto err; + } + if (in == NULL && passwds == NULL) { + /* build a null-terminated list */ + static char *passwds_static[2] = {NULL, NULL}; + + passwds = passwds_static; + if (in == NULL) + if (EVP_read_pw_string(passwd_malloc, + passwd_malloc_size, "Password: ", + !(passed_salt || cfg.noverify)) != 0) + goto err; + passwds[0] = passwd_malloc; + } + if (in == NULL) { + assert(passwds != NULL); + assert(*passwds != NULL); + + do { /* loop over list of passwords */ + passwd = *passwds++; + if (!do_passwd(passed_salt, &cfg.salt, + &salt_malloc, passwd, out, cfg.quiet, + cfg.table, cfg.reverse, + pw_maxlen, cfg.usecrypt, + cfg.use1, cfg.useapr1)) + goto err; + } while (*passwds != NULL); + } else { + int done; + + assert(passwd != NULL); + do { + int r = BIO_gets(in, passwd, pw_maxlen + 1); + if (r > 0) { + char *c = (strchr(passwd, '\n')); + if (c != NULL) + *c = 0; /* truncate at newline */ + else { + /* ignore rest of line */ + char trash[BUFSIZ]; + do + r = BIO_gets(in, trash, sizeof trash); + while ((r > 0) && (!strchr(trash, '\n'))); + } + + if (!do_passwd(passed_salt, &cfg.salt, + &salt_malloc, passwd, out, + cfg.quiet, cfg.table, + cfg.reverse, pw_maxlen, + cfg.usecrypt, cfg.use1, + cfg.useapr1)) + goto err; + } + done = (r <= 0); + } while (!done); + } + ret = 0; + + err: + ERR_print_errors(bio_err); + + free(salt_malloc); + free(passwd_malloc); + + BIO_free(in); + BIO_free_all(out); + + return (ret); +} + + +#ifndef NO_MD5CRYPT_1 +/* MD5-based password algorithm (should probably be available as a library + * function; then the static buffer would not be acceptable). + * For magic string "1", this should be compatible to the MD5-based BSD + * password algorithm. + * For 'magic' string "apr1", this is compatible to the MD5-based Apache + * password algorithm. + * (Apparently, the Apache password algorithm is identical except that the + * 'magic' string was changed -- the laziest application of the NIH principle + * I've ever encountered.) + */ +static char * +md5crypt(const char *passwd, const char *magic, const char *salt) +{ + static char out_buf[6 + 9 + 24 + 2]; /* "$apr1$..salt..$.......md5h + * ash..........\0" */ + unsigned char buf[MD5_DIGEST_LENGTH]; + char *salt_out; + int n; + unsigned int i; + EVP_MD_CTX *md = NULL, *md2 = NULL; + size_t passwd_len, salt_len; + + passwd_len = strlen(passwd); + out_buf[0] = '$'; + out_buf[1] = 0; + assert(strlen(magic) <= 4); /* "1" or "apr1" */ + strlcat(out_buf, magic, sizeof(out_buf)); + strlcat(out_buf, "$", sizeof(out_buf)); + strlcat(out_buf, salt, sizeof(out_buf)); + assert(strlen(out_buf) <= 6 + 8); /* "$apr1$..salt.." */ + salt_out = out_buf + 2 + strlen(magic); + salt_len = strlen(salt_out); + assert(salt_len <= 8); + + if ((md = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestInit_ex(md, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(md, passwd, passwd_len)) + goto err; + if (!EVP_DigestUpdate(md, "$", 1)) + goto err; + if (!EVP_DigestUpdate(md, magic, strlen(magic))) + goto err; + if (!EVP_DigestUpdate(md, "$", 1)) + goto err; + if (!EVP_DigestUpdate(md, salt_out, salt_len)) + goto err; + + if ((md2 = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + if (!EVP_DigestUpdate(md2, salt_out, salt_len)) + goto err; + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + + for (i = passwd_len; i > sizeof buf; i -= sizeof buf) { + if (!EVP_DigestUpdate(md, buf, sizeof buf)) + goto err; + } + if (!EVP_DigestUpdate(md, buf, i)) + goto err; + + n = passwd_len; + while (n) { + if (!EVP_DigestUpdate(md, (n & 1) ? "\0" : passwd, 1)) + goto err; + n >>= 1; + } + if (!EVP_DigestFinal_ex(md, buf, NULL)) + goto err; + + for (i = 0; i < 1000; i++) { + if (!EVP_DigestInit_ex(md2, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(md2, + (i & 1) ? (unsigned const char *) passwd : buf, + (i & 1) ? passwd_len : sizeof buf)) + goto err; + if (i % 3) { + if (!EVP_DigestUpdate(md2, salt_out, salt_len)) + goto err; + } + if (i % 7) { + if (!EVP_DigestUpdate(md2, passwd, passwd_len)) + goto err; + } + if (!EVP_DigestUpdate(md2, + (i & 1) ? buf : (unsigned const char *) passwd, + (i & 1) ? sizeof buf : passwd_len)) + goto err; + if (!EVP_DigestFinal_ex(md2, buf, NULL)) + goto err; + } + EVP_MD_CTX_free(md2); + md2 = NULL; + + { + /* transform buf into output string */ + + unsigned char buf_perm[sizeof buf]; + int dest, source; + char *output; + + /* silly output permutation */ + for (dest = 0, source = 0; dest < 14; dest++, source = (source + 6) % 17) + buf_perm[dest] = buf[source]; + buf_perm[14] = buf[5]; + buf_perm[15] = buf[11]; + assert(16 == sizeof buf_perm); + + output = salt_out + salt_len; + assert(output == out_buf + strlen(out_buf)); + + *output++ = '$'; + + for (i = 0; i < 15; i += 3) { + *output++ = cov_2char[buf_perm[i + 2] & 0x3f]; + *output++ = cov_2char[((buf_perm[i + 1] & 0xf) << 2) | + (buf_perm[i + 2] >> 6)]; + *output++ = cov_2char[((buf_perm[i] & 3) << 4) | + (buf_perm[i + 1] >> 4)]; + *output++ = cov_2char[buf_perm[i] >> 2]; + } + assert(i == 15); + *output++ = cov_2char[buf_perm[i] & 0x3f]; + *output++ = cov_2char[buf_perm[i] >> 6]; + *output = 0; + assert(strlen(out_buf) < sizeof(out_buf)); + } + EVP_MD_CTX_free(md); + + return out_buf; + err: + EVP_MD_CTX_free(md); + EVP_MD_CTX_free(md2); + + return NULL; +} +#endif + + +static int +do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p, + char *passwd, BIO * out, int quiet, int table, int reverse, + size_t pw_maxlen, int usecrypt, int use1, int useapr1) +{ + char *hash = NULL; + + assert(salt_p != NULL); + assert(salt_malloc_p != NULL); + + /* first make sure we have a salt */ + if (!passed_salt) { +#ifndef OPENSSL_NO_DES + if (usecrypt) { + if (*salt_malloc_p == NULL) { + *salt_p = *salt_malloc_p = malloc(3); + if (*salt_malloc_p == NULL) + goto err; + } + arc4random_buf(*salt_p, 2); + (*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */ + (*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */ + (*salt_p)[2] = 0; + } +#endif /* !OPENSSL_NO_DES */ + +#ifndef NO_MD5CRYPT_1 + if (use1 || useapr1) { + int i; + + if (*salt_malloc_p == NULL) { + *salt_p = *salt_malloc_p = malloc(9); + if (*salt_malloc_p == NULL) + goto err; + } + arc4random_buf(*salt_p, 8); + + for (i = 0; i < 8; i++) + (*salt_p)[i] = cov_2char[(*salt_p)[i] & 0x3f]; /* 6 bits */ + (*salt_p)[8] = 0; + } +#endif /* !NO_MD5CRYPT_1 */ + } + assert(*salt_p != NULL); + + /* truncate password if necessary */ + if ((strlen(passwd) > pw_maxlen)) { + if (!quiet) + BIO_printf(bio_err, + "Warning: truncating password to %zu characters\n", + pw_maxlen); + passwd[pw_maxlen] = 0; + } + assert(strlen(passwd) <= pw_maxlen); + + /* now compute password hash */ +#ifndef OPENSSL_NO_DES + if (usecrypt) + hash = DES_crypt(passwd, *salt_p); +#endif +#ifndef NO_MD5CRYPT_1 + if (use1 || useapr1) + if ((hash = md5crypt(passwd, (use1 ? "1" : "apr1"), *salt_p)) == NULL) + goto err; +#endif + assert(hash != NULL); + + if (table && !reverse) + BIO_printf(out, "%s\t%s\n", passwd, hash); + else if (table && reverse) + BIO_printf(out, "%s\t%s\n", hash, passwd); + else + BIO_printf(out, "%s\n", hash); + return 1; + + err: + free(*salt_malloc_p); + *salt_malloc_p = NULL; + return 0; +} +#else + +int +passwd_main(int argc, char **argv) +{ + fputs("Program not available.\n", stderr) + return (1); +} +#endif diff --git a/apps/openssl/pkcs12.c b/apps/openssl/pkcs12.c new file mode 100644 index 0000000..aedae64 --- /dev/null +++ b/apps/openssl/pkcs12.c @@ -0,0 +1,1128 @@ +/* $OpenBSD: pkcs12.c,v 1.25 2023/03/06 14:32:06 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) + +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include + +#define NOKEYS 0x1 +#define NOCERTS 0x2 +#define INFO 0x4 +#define CLCERTS 0x8 +#define CACERTS 0x10 + +static int get_cert_chain(X509 *cert, X509_STORE *store, + STACK_OF(X509) **chain); +static int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, + int options, char *pempass); +static int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + char *pass, int passlen, int options, char *pempass); +static int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, + int passlen, int options, char *pempass); +static int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, + const char *name); +static void hex_prin(BIO *out, unsigned char *buf, int len); +static int alg_print(BIO *x, const X509_ALGOR *alg); +static int set_pbe(BIO *err, int *ppbe, const char *str); + +static struct { + int add_lmk; + char *CAfile; + STACK_OF(OPENSSL_STRING) *canames; + char *CApath; + int cert_pbe; + char *certfile; + int chain; + char *csp_name; + const EVP_CIPHER *enc; + int export_cert; + int key_pbe; + char *keyname; + int keytype; + char *infile; + int iter; + char *macalg; + int maciter; + int macver; + char *name; + int noprompt; + int options; + char *outfile; + char *passarg; + char *passargin; + char *passargout; + int twopass; +} cfg; + +static int +pkcs12_opt_canames(char *arg) +{ + if (cfg.canames == NULL && + (cfg.canames = sk_OPENSSL_STRING_new_null()) == NULL) + return (1); + + if (!sk_OPENSSL_STRING_push(cfg.canames, arg)) + return (1); + + return (0); +} + +static int +pkcs12_opt_cert_pbe(char *arg) +{ + return (!set_pbe(bio_err, &cfg.cert_pbe, arg)); +} + +static int +pkcs12_opt_key_pbe(char *arg) +{ + return (!set_pbe(bio_err, &cfg.key_pbe, arg)); +} + +static int +pkcs12_opt_passarg(char *arg) +{ + cfg.passarg = arg; + cfg.noprompt = 1; + return (0); +} + +static const EVP_CIPHER *get_cipher_by_name(char *name) +{ + if (name == NULL || strcmp(name, "") == 0) + return (NULL); +#ifndef OPENSSL_NO_AES + else if (strcmp(name, "aes128") == 0) + return EVP_aes_128_cbc(); + else if (strcmp(name, "aes192") == 0) + return EVP_aes_192_cbc(); + else if (strcmp(name, "aes256") == 0) + return EVP_aes_256_cbc(); +#endif +#ifndef OPENSSL_NO_CAMELLIA + else if (strcmp(name, "camellia128") == 0) + return EVP_camellia_128_cbc(); + else if (strcmp(name, "camellia192") == 0) + return EVP_camellia_192_cbc(); + else if (strcmp(name, "camellia256") == 0) + return EVP_camellia_256_cbc(); +#endif +#ifndef OPENSSL_NO_DES + else if (strcmp(name, "des") == 0) + return EVP_des_cbc(); + else if (strcmp(name, "des3") == 0) + return EVP_des_ede3_cbc(); +#endif +#ifndef OPENSSL_NO_IDEA + else if (strcmp(name, "idea") == 0) + return EVP_idea_cbc(); +#endif + else + return (NULL); +} + +static int +pkcs12_opt_enc(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if (strcmp(name, "nodes") == 0) + cfg.enc = NULL; + else if ((cfg.enc = get_cipher_by_name(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static const struct option pkcs12_options[] = { +#ifndef OPENSSL_NO_AES + { + .name = "aes128", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "aes192", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "aes256", + .desc = "Encrypt PEM output with CBC AES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, +#endif +#ifndef OPENSSL_NO_CAMELLIA + { + .name = "camellia128", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "camellia192", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "camellia256", + .desc = "Encrypt PEM output with CBC Camellia", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, +#endif + { + .name = "des", + .desc = "Encrypt private keys with DES", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "des3", + .desc = "Encrypt private keys with triple DES (default)", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, +#ifndef OPENSSL_NO_IDEA + { + .name = "idea", + .desc = "Encrypt private keys with IDEA", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, +#endif + { + .name = "cacerts", + .desc = "Only output CA certificates", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = CACERTS, + }, + { + .name = "CAfile", + .argname = "file", + .desc = "PEM format file of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CAfile, + }, + { + .name = "caname", + .argname = "name", + .desc = "Use name as CA friendly name (can be used more than once)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs12_opt_canames, + }, + { + .name = "CApath", + .argname = "directory", + .desc = "PEM format directory of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CApath, + }, + { + .name = "certfile", + .argname = "file", + .desc = "Add all certs in file", + .type = OPTION_ARG, + .opt.arg = &cfg.certfile, + }, + { + .name = "certpbe", + .argname = "alg", + .desc = "Specify certificate PBE algorithm (default RC2-40)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs12_opt_cert_pbe, + }, + { + .name = "chain", + .desc = "Add certificate chain", + .type = OPTION_FLAG, + .opt.flag = &cfg.chain, + }, + { + .name = "clcerts", + .desc = "Only output client certificates", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = CLCERTS, + }, + { + .name = "CSP", + .argname = "name", + .desc = "Microsoft CSP name", + .type = OPTION_ARG, + .opt.arg = &cfg.csp_name, + }, + { + .name = "descert", + .desc = "Encrypt PKCS#12 certificates with triple DES (default RC2-40)", + .type = OPTION_VALUE, + .opt.value = &cfg.cert_pbe, + .value = NID_pbe_WithSHA1And3_Key_TripleDES_CBC, + }, + { + .name = "export", + .desc = "Output PKCS#12 file", + .type = OPTION_FLAG, + .opt.flag = &cfg.export_cert, + }, + { + .name = "in", + .argname = "file", + .desc = "Input filename", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "info", + .desc = "Give info about PKCS#12 structure", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = INFO, + }, + { + .name = "inkey", + .argname = "file", + .desc = "Private key if not infile", + .type = OPTION_ARG, + .opt.arg = &cfg.keyname, + }, + { + .name = "keyex", + .desc = "Set MS key exchange type", + .type = OPTION_VALUE, + .opt.value = &cfg.keytype, + .value = KEY_EX, + }, + { + .name = "keypbe", + .argname = "alg", + .desc = "Specify private key PBE algorithm (default 3DES)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs12_opt_key_pbe, + }, + { + .name = "keysig", + .desc = "Set MS key signature type", + .type = OPTION_VALUE, + .opt.value = &cfg.keytype, + .value = KEY_SIG, + }, + { + .name = "LMK", + .desc = "Add local machine keyset attribute to private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.add_lmk, + }, + { + .name = "macalg", + .argname = "alg", + .desc = "Digest algorithm used in MAC (default SHA1)", + .type = OPTION_ARG, + .opt.arg = &cfg.macalg, + }, + { + .name = "maciter", + .desc = "Use MAC iteration", + .type = OPTION_VALUE, + .opt.value = &cfg.maciter, + .value = PKCS12_DEFAULT_ITER, + }, + { + .name = "name", + .argname = "name", + .desc = "Use name as friendly name", + .type = OPTION_ARG, + .opt.arg = &cfg.name, + }, + { + .name = "nocerts", + .desc = "Don't output certificates", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = NOCERTS, + }, + { + .name = "nodes", + .desc = "Don't encrypt private keys", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkcs12_opt_enc, + }, + { + .name = "noiter", + .desc = "Don't use encryption iteration", + .type = OPTION_VALUE, + .opt.value = &cfg.iter, + .value = 1, + }, + { + .name = "nokeys", + .desc = "Don't output private keys", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = NOKEYS, + }, + { + .name = "nomac", + .desc = "Don't generate MAC", + .type = OPTION_VALUE, + .opt.value = &cfg.maciter, + .value = -1, + }, + { + .name = "nomaciter", + .desc = "Don't use MAC iteration", + .type = OPTION_VALUE, + .opt.value = &cfg.maciter, + .value = 1, + }, + { + .name = "nomacver", + .desc = "Don't verify MAC", + .type = OPTION_VALUE, + .opt.value = &cfg.macver, + .value = 0, + }, + { + .name = "noout", + .desc = "Don't output anything, just verify", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.options, + .value = (NOKEYS | NOCERTS), + }, + { + .name = "out", + .argname = "file", + .desc = "Output filename", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passin", + .argname = "arg", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "arg", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "password", + .argname = "arg", + .desc = "Set import/export password source", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs12_opt_passarg, + }, + { + .name = "twopass", + .desc = "Separate MAC, encryption passwords", + .type = OPTION_FLAG, + .opt.flag = &cfg.twopass, + }, + { NULL }, +}; + +static void +pkcs12_usage(void) +{ + fprintf(stderr, "usage: pkcs12 [-aes128 | -aes192 | -aes256 |"); + fprintf(stderr, " -camellia128 |\n"); + fprintf(stderr, " -camellia192 | -camellia256 | -des | -des3 |"); + fprintf(stderr, " -idea]\n"); + fprintf(stderr, " [-cacerts] [-CAfile file] [-caname name]\n"); + fprintf(stderr, " [-CApath directory] [-certfile file]"); + fprintf(stderr, " [-certpbe alg]\n"); + fprintf(stderr, " [-chain] [-clcerts] [-CSP name] [-descert]"); + fprintf(stderr, " [-export]\n"); + fprintf(stderr, " [-in file] [-info] [-inkey file] [-keyex]"); + fprintf(stderr, " [-keypbe alg]\n"); + fprintf(stderr, " [-keysig] [-LMK] [-macalg alg] [-maciter]"); + fprintf(stderr, " [-name name]\n"); + fprintf(stderr, " [-nocerts] [-nodes] [-noiter] [-nokeys]"); + fprintf(stderr, " [-nomac]\n"); + fprintf(stderr, " [-nomaciter] [-nomacver] [-noout] [-out file]\n"); + fprintf(stderr, " [-passin arg] [-passout arg] [-password arg]"); + fprintf(stderr, " [-twopass]\n\n"); + options_usage(pkcs12_options); + fprintf(stderr, "\n"); +} + +int +pkcs12_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + PKCS12 *p12 = NULL; + char pass[50], macpass[50]; + int ret = 1; + char *cpass = NULL, *mpass = NULL; + char *passin = NULL, *passout = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; + cfg.enc = EVP_des_ede3_cbc(); + cfg.iter = PKCS12_DEFAULT_ITER; + cfg.key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; + cfg.maciter = PKCS12_DEFAULT_ITER; + cfg.macver = 1; + + if (options_parse(argc, argv, pkcs12_options, NULL, NULL) != 0) { + pkcs12_usage(); + goto end; + } + + if (cfg.passarg != NULL) { + if (cfg.export_cert) + cfg.passargout = cfg.passarg; + else + cfg.passargin = cfg.passarg; + } + if (!app_passwd(bio_err, cfg.passargin, + cfg.passargout, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if (cpass == NULL) { + if (cfg.export_cert) + cpass = passout; + else + cpass = passin; + } + if (cpass != NULL) { + mpass = cpass; + cfg.noprompt = 1; + } else { + cpass = pass; + mpass = macpass; + } + + if (cfg.infile == NULL) + in = BIO_new_fp(stdin, BIO_NOCLOSE); + else + in = BIO_new_file(cfg.infile, "rb"); + if (in == NULL) { + BIO_printf(bio_err, "Error opening input file %s\n", + cfg.infile ? cfg.infile : ""); + perror(cfg.infile); + goto end; + } + + if (cfg.outfile == NULL) { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } else + out = BIO_new_file(cfg.outfile, "wb"); + if (out == NULL) { + BIO_printf(bio_err, "Error opening output file %s\n", + cfg.outfile ? cfg.outfile : ""); + perror(cfg.outfile); + goto end; + } + if (cfg.twopass) { + if (EVP_read_pw_string(macpass, sizeof macpass, + "Enter MAC Password:", cfg.export_cert)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + } + if (cfg.export_cert) { + EVP_PKEY *key = NULL; + X509 *ucert = NULL, *x = NULL; + STACK_OF(X509) *certs = NULL; + const EVP_MD *macmd = NULL; + unsigned char *catmp = NULL; + int i; + + if ((cfg.options & (NOCERTS | NOKEYS)) == + (NOCERTS | NOKEYS)) { + BIO_printf(bio_err, "Nothing to do!\n"); + goto export_end; + } + if (cfg.options & NOCERTS) + cfg.chain = 0; + + if (!(cfg.options & NOKEYS)) { + key = load_key(bio_err, cfg.keyname ? + cfg.keyname : cfg.infile, + FORMAT_PEM, 1, passin, "private key"); + if (!key) + goto export_end; + } + + /* Load in all certs in input file */ + if (!(cfg.options & NOCERTS)) { + certs = load_certs(bio_err, cfg.infile, + FORMAT_PEM, NULL, "certificates"); + if (certs == NULL) + goto export_end; + + if (key != NULL) { + /* Look for matching private key */ + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (X509_check_private_key(x, key)) { + ucert = x; + /* Zero keyid and alias */ + X509_keyid_set1(ucert, NULL, 0); + X509_alias_set1(ucert, NULL, 0); + /* Remove from list */ + (void) sk_X509_delete(certs, i); + break; + } + } + if (ucert == NULL) { + BIO_printf(bio_err, + "No certificate matches private key\n"); + goto export_end; + } + } + } + + /* Add any more certificates asked for */ + if (cfg.certfile != NULL) { + STACK_OF(X509) *morecerts = NULL; + if ((morecerts = load_certs(bio_err, + cfg.certfile, FORMAT_PEM, NULL, + "certificates from certfile")) == NULL) + goto export_end; + while (sk_X509_num(morecerts) > 0) + sk_X509_push(certs, sk_X509_shift(morecerts)); + sk_X509_free(morecerts); + } + + + /* If chaining get chain from user cert */ + if (cfg.chain) { + int vret; + STACK_OF(X509) *chain2; + X509_STORE *store = X509_STORE_new(); + if (store == NULL) { + BIO_printf(bio_err, + "Memory allocation error\n"); + goto export_end; + } + if (!X509_STORE_load_locations(store, + cfg.CAfile, cfg.CApath)) + X509_STORE_set_default_paths(store); + + vret = get_cert_chain(ucert, store, &chain2); + X509_STORE_free(store); + + if (vret == X509_V_OK) { + /* Exclude verified certificate */ + for (i = 1; i < sk_X509_num(chain2); i++) + sk_X509_push(certs, sk_X509_value( + chain2, i)); + /* Free first certificate */ + X509_free(sk_X509_value(chain2, 0)); + sk_X509_free(chain2); + } else { + if (vret != X509_V_ERR_UNSPECIFIED) + BIO_printf(bio_err, + "Error %s getting chain.\n", + X509_verify_cert_error_string( + vret)); + else + ERR_print_errors(bio_err); + goto export_end; + } + } + /* Add any CA names */ + + for (i = 0; i < sk_OPENSSL_STRING_num(cfg.canames); + i++) { + catmp = (unsigned char *) sk_OPENSSL_STRING_value( + cfg.canames, i); + X509_alias_set1(sk_X509_value(certs, i), catmp, -1); + } + + if (cfg.csp_name != NULL && key != NULL) + EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, + MBSTRING_ASC, + (unsigned char *) cfg.csp_name, -1); + + if (cfg.add_lmk && key != NULL) + EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, + -1); + + if (!cfg.noprompt && + EVP_read_pw_string(pass, sizeof pass, + "Enter Export Password:", 1)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto export_end; + } + if (!cfg.twopass) + strlcpy(macpass, pass, sizeof macpass); + + + p12 = PKCS12_create(cpass, cfg.name, key, ucert, + certs, cfg.key_pbe, cfg.cert_pbe, + cfg.iter, -1, cfg.keytype); + + if (p12 == NULL) { + ERR_print_errors(bio_err); + goto export_end; + } + if (cfg.macalg != NULL) { + macmd = EVP_get_digestbyname(cfg.macalg); + if (macmd == NULL) { + BIO_printf(bio_err, + "Unknown digest algorithm %s\n", + cfg.macalg); + } + } + if (cfg.maciter != -1) + PKCS12_set_mac(p12, mpass, -1, NULL, 0, + cfg.maciter, macmd); + + i2d_PKCS12_bio(out, p12); + + ret = 0; + + export_end: + EVP_PKEY_free(key); + sk_X509_pop_free(certs, X509_free); + X509_free(ucert); + + goto end; + + } + if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (!cfg.noprompt && EVP_read_pw_string(pass, sizeof pass, + "Enter Import Password:", 0)) { + BIO_printf(bio_err, "Can't read Password\n"); + goto end; + } + + if (!cfg.twopass) + strlcpy(macpass, pass, sizeof macpass); + + if ((cfg.options & INFO) != 0 && PKCS12_mac_present(p12)) { + const ASN1_INTEGER *iter; + + PKCS12_get0_mac(NULL, NULL, NULL, &iter, p12); + BIO_printf(bio_err, "MAC Iteration %ld\n", + iter != NULL ? ASN1_INTEGER_get(iter) : 1); + } + if (cfg.macver) { + /* If we enter empty password try no password first */ + if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { + /* If mac and crypto pass the same set it to NULL too */ + if (!cfg.twopass) + cpass = NULL; + } else if (!PKCS12_verify_mac(p12, mpass, -1)) { + BIO_printf(bio_err, + "Mac verify error: invalid password?\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "MAC verified OK\n"); + } + if (!dump_certs_keys_p12(out, p12, cpass, -1, cfg.options, + passout)) { + BIO_printf(bio_err, "Error outputting keys and certificates\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + end: + PKCS12_free(p12); + BIO_free(in); + BIO_free_all(out); + sk_OPENSSL_STRING_free(cfg.canames); + free(passin); + free(passout); + + return (ret); +} + +static int +dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, + char *pempass) +{ + STACK_OF(PKCS7) *asafes = NULL; + STACK_OF(PKCS12_SAFEBAG) *bags; + int i, bagnid; + int ret = 0; + PKCS7 *p7; + + if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) + return 0; + for (i = 0; i < sk_PKCS7_num(asafes); i++) { + p7 = sk_PKCS7_value(asafes, i); + bagnid = OBJ_obj2nid(p7->type); + if (bagnid == NID_pkcs7_data) { + bags = PKCS12_unpack_p7data(p7); + if (options & INFO) + BIO_printf(bio_err, "PKCS7 Data\n"); + } else if (bagnid == NID_pkcs7_encrypted) { + if (options & INFO) { + BIO_printf(bio_err, "PKCS7 Encrypted data: "); + alg_print(bio_err, + p7->d.encrypted->enc_data->algorithm); + } + bags = PKCS12_unpack_p7encdata(p7, pass, passlen); + } else + continue; + if (bags == NULL) + goto err; + if (!dump_certs_pkeys_bags(out, bags, pass, passlen, + options, pempass)) { + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + goto err; + } + sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); + bags = NULL; + } + ret = 1; + + err: + sk_PKCS7_pop_free(asafes, PKCS7_free); + return ret; +} + +static int +dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, + char *pass, int passlen, int options, char *pempass) +{ + int i; + + for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { + if (!dump_certs_pkeys_bag(out, + sk_PKCS12_SAFEBAG_value(bags, i), + pass, passlen, + options, pempass)) + return 0; + } + return 1; +} + +static int +dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, int passlen, + int options, char *pempass) +{ + EVP_PKEY *pkey; + const STACK_OF(X509_ATTRIBUTE) *attrs; + X509 *x509; + + attrs = PKCS12_SAFEBAG_get0_attrs(bag); + + switch (PKCS12_SAFEBAG_get_nid(bag)) { + case NID_keyBag: + { + const PKCS8_PRIV_KEY_INFO *p8; + + if (options & INFO) + BIO_printf(bio_err, "Key bag\n"); + if (options & NOKEYS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + if ((p8 = PKCS12_SAFEBAG_get0_p8inf(bag)) == NULL) + return 0; + if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) + return 0; + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); + PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0, + NULL, pempass); + EVP_PKEY_free(pkey); + break; + } + + case NID_pkcs8ShroudedKeyBag: + { + PKCS8_PRIV_KEY_INFO *p8; + + if (options & INFO) { + const X509_SIG *tp8; + const X509_ALGOR *tp8alg; + + BIO_printf(bio_err, "Shrouded Keybag: "); + if ((tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag)) == NULL) + return 0; + X509_SIG_get0(tp8, &tp8alg, NULL); + alg_print(bio_err, tp8alg); + } + if (options & NOKEYS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + return 0; + if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) { + PKCS8_PRIV_KEY_INFO_free(p8); + return 0; + } + print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); + PKCS8_PRIV_KEY_INFO_free(p8); + PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0, + NULL, pempass); + EVP_PKEY_free(pkey); + break; + } + + case NID_certBag: + if (options & INFO) + BIO_printf(bio_err, "Certificate bag\n"); + if (options & NOCERTS) + return 1; + if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID) != NULL) { + if (options & CACERTS) + return 1; + } else if (options & CLCERTS) + return 1; + print_attribs(out, attrs, "Bag Attributes"); + if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) + return 1; + if ((x509 = PKCS12_certbag2x509(bag)) == NULL) + return 0; + dump_cert_text(out, x509); + PEM_write_bio_X509(out, x509); + X509_free(x509); + break; + + case NID_safeContentsBag: + if (options & INFO) + BIO_printf(bio_err, "Safe Contents bag\n"); + print_attribs(out, attrs, "Bag Attributes"); + return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag), + pass, passlen, options, pempass); + + default: + BIO_printf(bio_err, "Warning unsupported bag type: "); + i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag)); + BIO_printf(bio_err, "\n"); + return 1; + break; + } + return 1; +} + +/* Given a single certificate return a verified chain or NULL if error */ +static int +get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **out_chain) +{ + X509_STORE_CTX *store_ctx = NULL; + STACK_OF(X509) *chain = NULL; + int ret = X509_V_ERR_UNSPECIFIED; + + if ((store_ctx = X509_STORE_CTX_new()) == NULL) + goto err; + if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) + goto err; + + if (X509_verify_cert(store_ctx) > 0) { + if ((chain = X509_STORE_CTX_get1_chain(store_ctx)) == NULL) + goto err; + } + ret = X509_STORE_CTX_get_error(store_ctx); + + err: + X509_STORE_CTX_free(store_ctx); + *out_chain = chain; + + return ret; +} + +static int +alg_print(BIO *x, const X509_ALGOR *alg) +{ + PBEPARAM *pbe; + const unsigned char *p; + + p = alg->parameter->value.sequence->data; + pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); + if (pbe == NULL) + return 1; + BIO_printf(bio_err, "%s, Iteration %ld\n", + OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)), + ASN1_INTEGER_get(pbe->iter)); + PBEPARAM_free(pbe); + return 1; +} + +/* Generalised attribute print: handle PKCS#8 and bag attributes */ +static void +print_attribute(BIO *out, const ASN1_TYPE *av) +{ + char *value; + + switch (av->type) { + case V_ASN1_BMPSTRING: + value = OPENSSL_uni2asc( + av->value.bmpstring->data, + av->value.bmpstring->length); + BIO_printf(out, "%s\n", value); + free(value); + break; + + case V_ASN1_OCTET_STRING: + hex_prin(out, av->value.octet_string->data, + av->value.octet_string->length); + BIO_printf(out, "\n"); + break; + + case V_ASN1_BIT_STRING: + hex_prin(out, av->value.bit_string->data, + av->value.bit_string->length); + BIO_printf(out, "\n"); + break; + + default: + BIO_printf(out, "\n", + av->type); + break; + } +} + +static int +print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, + const char *name) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *av; + int i, j, attr_nid; + + if (attrlst == NULL) { + BIO_printf(out, "%s: \n", name); + return 1; + } + if (!sk_X509_ATTRIBUTE_num(attrlst)) { + BIO_printf(out, "%s: \n", name); + return 1; + } + BIO_printf(out, "%s\n", name); + for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { + ASN1_OBJECT *obj; + + attr = sk_X509_ATTRIBUTE_value(attrlst, i); + obj = X509_ATTRIBUTE_get0_object(attr); + attr_nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)); + BIO_printf(out, " "); + if (attr_nid == NID_undef) { + i2a_ASN1_OBJECT(out, obj); + BIO_printf(out, ": "); + } else + BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); + + if (X509_ATTRIBUTE_count(attr)) { + for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) { + av = X509_ATTRIBUTE_get0_type(attr, j); + print_attribute(out, av); + } + } else + BIO_printf(out, "\n"); + } + return 1; +} + +static void +hex_prin(BIO *out, unsigned char *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) + BIO_printf(out, "%02X ", buf[i]); +} + +static int +set_pbe(BIO *err, int *ppbe, const char *str) +{ + if (str == NULL) + return 0; + if (strcmp(str, "NONE") == 0) { + *ppbe = -1; + return 1; + } + *ppbe = OBJ_txt2nid(str); + if (*ppbe == NID_undef) { + BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str); + return 0; + } + return 1; +} + +#endif diff --git a/apps/openssl/pkcs7.c b/apps/openssl/pkcs7.c new file mode 100644 index 0000000..da30e23 --- /dev/null +++ b/apps/openssl/pkcs7.c @@ -0,0 +1,291 @@ +/* $OpenBSD: pkcs7.c,v 1.15 2023/07/23 11:39:29 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +static struct { + char *infile; + int informat; + int noout; + char *outfile; + int outformat; + int p7_print; + int print_certs; + int text; +} cfg; + +static const struct option pkcs7_options[] = { + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "Do not output encoded version of PKCS#7 structure", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "print", + .desc = "Output ASN.1 representation of PKCS#7 structure", + .type = OPTION_FLAG, + .opt.flag = &cfg.p7_print, + }, + { + .name = "print_certs", + .desc = "Print out any certificates or CRLs contained in file", + .type = OPTION_FLAG, + .opt.flag = &cfg.print_certs, + }, + { + .name = "text", + .desc = "Print out full certificate details", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { NULL }, +}; + +static void +pkcs7_usage(void) +{ + fprintf(stderr, "usage: pkcs7 [-in file] " + "[-inform DER | PEM] [-noout]\n" + " [-out file] [-outform DER | PEM] [-print_certs] [-text]\n\n"); + options_usage(pkcs7_options); +} + +int +pkcs7_main(int argc, char **argv) +{ + PKCS7 *p7 = NULL; + BIO *in = NULL, *out = NULL; + int ret = 1; + int i; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, pkcs7_options, NULL, NULL) != 0) { + pkcs7_usage(); + goto end; + } + + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if ((in == NULL) || (out == NULL)) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + if (cfg.informat == FORMAT_ASN1) + p7 = d2i_PKCS7_bio(in, NULL); + else if (cfg.informat == FORMAT_PEM) + p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, "bad input format specified for pkcs7 object\n"); + goto end; + } + if (p7 == NULL) { + BIO_printf(bio_err, "unable to load PKCS7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.p7_print) + PKCS7_print_ctx(out, p7, 0, NULL); + + if (cfg.print_certs) { + STACK_OF(X509) * certs = NULL; + STACK_OF(X509_CRL) * crls = NULL; + + i = OBJ_obj2nid(p7->type); + switch (i) { + case NID_pkcs7_signed: + if (p7->d.sign != NULL) { + certs = p7->d.sign->cert; + crls = p7->d.sign->crl; + } + break; + case NID_pkcs7_signedAndEnveloped: + if (p7->d.signed_and_enveloped != NULL) { + certs = p7->d.signed_and_enveloped->cert; + crls = p7->d.signed_and_enveloped->crl; + } + break; + default: + break; + } + + if (certs != NULL) { + X509 *x; + + for (i = 0; i < sk_X509_num(certs); i++) { + x = sk_X509_value(certs, i); + if (cfg.text) + X509_print(out, x); + else + dump_cert_text(out, x); + + if (!cfg.noout) + PEM_write_bio_X509(out, x); + BIO_puts(out, "\n"); + } + } + if (crls != NULL) { + X509_CRL *crl; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + + X509_CRL_print(out, crl); + + if (!cfg.noout) + PEM_write_bio_X509_CRL(out, crl); + BIO_puts(out, "\n"); + } + } + ret = 0; + goto end; + } + if (!cfg.noout) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_PKCS7_bio(out, p7); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_PKCS7(out, p7); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + + if (!i) { + BIO_printf(bio_err, "unable to write pkcs7 object\n"); + ERR_print_errors(bio_err); + goto end; + } + } + ret = 0; + end: + if (p7 != NULL) + PKCS7_free(p7); + if (in != NULL) + BIO_free(in); + if (out != NULL) + BIO_free_all(out); + + return (ret); +} diff --git a/apps/openssl/pkcs8.c b/apps/openssl/pkcs8.c new file mode 100644 index 0000000..9776b91 --- /dev/null +++ b/apps/openssl/pkcs8.c @@ -0,0 +1,366 @@ +/* $OpenBSD: pkcs8.c,v 1.17 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999-2004. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "apps.h" +#include "progs.h" + +#include +#include +#include +#include + +static struct { + const EVP_CIPHER *cipher; + char *infile; + int informat; + int iter; + int nocrypt; + char *outfile; + int outformat; + char *passargin; + char *passargout; + int pbe_nid; + int topk8; +} cfg; + +static int +pkcs8_opt_v1(char *arg) +{ + if ((cfg.pbe_nid = OBJ_txt2nid(arg)) == NID_undef) { + fprintf(stderr, "Unknown PBE algorithm '%s'\n", arg); + return (1); + } + + return (0); +} + +static int +pkcs8_opt_v2(char *arg) +{ + if ((cfg.cipher = EVP_get_cipherbyname(arg)) == NULL) { + fprintf(stderr, "Unknown cipher '%s'\n", arg); + return (1); + } + + return (0); +} + +static const struct option pkcs8_options[] = { + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "der | pem", + .desc = "Input format (default PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "nocrypt", + .desc = "Use or expect unencrypted private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.nocrypt, + }, + { + .name = "noiter", + .desc = "Use 1 as iteration count", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.iter, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "der | pem", + .desc = "Output format (default PEM)", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "source", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "source", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "topk8", + .desc = "Read traditional format key and write PKCS#8 format" + " key", + .type = OPTION_FLAG, + .opt.flag = &cfg.topk8, + }, + { + .name = "v1", + .argname = "algorithm", + .desc = "Use PKCS#5 v1.5 or PKCS#12 with given algorithm", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs8_opt_v1, + }, + { + .name = "v2", + .argname = "cipher", + .desc = "Use PKCS#5 v2.0 with given cipher", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkcs8_opt_v2, + }, + { NULL }, +}; + +static void +pkcs8_usage(void) +{ + fprintf(stderr, "usage: pkcs8 [-in file] [inform der | pem] " + "[-nocrypt] [-noiter]\n" + " [-out file] [-outform der | pem] [-passin arg]\n" + " [-passout arg] [-topk8] [-v1 alg] [-v2 alg]\n\n"); + options_usage(pkcs8_options); +} + +int +pkcs8_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + X509_SIG *p8 = NULL; + PKCS8_PRIV_KEY_INFO *p8inf = NULL; + EVP_PKEY *pkey = NULL; + char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL; + int ret = 1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.iter = PKCS12_DEFAULT_ITER; + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + cfg.pbe_nid = -1; + + if (options_parse(argc, argv, pkcs8_options, NULL, NULL) != 0) { + pkcs8_usage(); + return (1); + } + + if (!app_passwd(bio_err, cfg.passargin, + cfg.passargout, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if ((cfg.pbe_nid == -1) && !cfg.cipher) + cfg.pbe_nid = NID_pbeWithMD5AndDES_CBC; + + if (cfg.infile) { + if (!(in = BIO_new_file(cfg.infile, "rb"))) { + BIO_printf(bio_err, + "Can't open input file '%s'\n", + cfg.infile); + goto end; + } + } else + in = BIO_new_fp(stdin, BIO_NOCLOSE); + + if (cfg.outfile) { + if (!(out = BIO_new_file(cfg.outfile, "wb"))) { + BIO_printf(bio_err, "Can't open output file '%s'\n", + cfg.outfile); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + if (cfg.topk8) { + pkey = load_key(bio_err, cfg.infile, + cfg.informat, 1, passin, "key"); + if (!pkey) + goto end; + if (!(p8inf = EVP_PKEY2PKCS8(pkey))) { + BIO_printf(bio_err, "Error converting key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.nocrypt) { + if (cfg.outformat == FORMAT_PEM) + PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf); + else if (cfg.outformat == FORMAT_ASN1) + i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf); + else { + BIO_printf(bio_err, + "Bad format specified for key\n"); + goto end; + } + } else { + if (passout) + p8pass = passout; + else { + p8pass = pass; + if (EVP_read_pw_string(pass, sizeof pass, + "Enter Encryption Password:", 1)) + goto end; + } + if (!(p8 = PKCS8_encrypt(cfg.pbe_nid, + cfg.cipher, p8pass, strlen(p8pass), + NULL, 0, cfg.iter, p8inf))) { + BIO_printf(bio_err, "Error encrypting key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outformat == FORMAT_PEM) + PEM_write_bio_PKCS8(out, p8); + else if (cfg.outformat == FORMAT_ASN1) + i2d_PKCS8_bio(out, p8); + else { + BIO_printf(bio_err, + "Bad format specified for key\n"); + goto end; + } + } + + ret = 0; + goto end; + } + if (cfg.nocrypt) { + if (cfg.informat == FORMAT_PEM) + p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, + NULL, NULL); + else if (cfg.informat == FORMAT_ASN1) + p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL); + else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + } else { + if (cfg.informat == FORMAT_PEM) + p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL); + else if (cfg.informat == FORMAT_ASN1) + p8 = d2i_PKCS8_bio(in, NULL); + else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + + if (!p8) { + BIO_printf(bio_err, "Error reading key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (passin) + p8pass = passin; + else { + p8pass = pass; + EVP_read_pw_string(pass, sizeof pass, + "Enter Password:", 0); + } + p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass)); + } + + if (!p8inf) { + BIO_printf(bio_err, "Error decrypting key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (!(pkey = EVP_PKCS82PKEY(p8inf))) { + BIO_printf(bio_err, "Error converting key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outformat == FORMAT_PEM) + PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, + passout); + else if (cfg.outformat == FORMAT_ASN1) + i2d_PrivateKey_bio(out, pkey); + else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + ret = 0; + + end: + X509_SIG_free(p8); + PKCS8_PRIV_KEY_INFO_free(p8inf); + EVP_PKEY_free(pkey); + BIO_free_all(out); + BIO_free(in); + free(passin); + free(passout); + + return ret; +} diff --git a/apps/openssl/pkey.c b/apps/openssl/pkey.c new file mode 100644 index 0000000..47fa2dd --- /dev/null +++ b/apps/openssl/pkey.c @@ -0,0 +1,309 @@ +/* $OpenBSD: pkey.c,v 1.20 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006 + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "apps.h" + +#include +#include +#include + +static struct { + int check; + const EVP_CIPHER *cipher; + char *infile; + int informat; + int noout; + char *outfile; + int outformat; + char *passargin; + char *passargout; + int pubcheck; + int pubin; + int pubout; + int pubtext; + int text; +} cfg; + +static int +pkey_opt_cipher(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.cipher = EVP_get_cipherbyname(name)) == NULL) { + BIO_printf(bio_err, "Unknown cipher %s\n", name); + return (1); + } + + *argsused = 1; + return (0); +} + +static const struct option pkey_options[] = { + { + .name = "check", + .desc = "Check validity of key", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "noout", + .desc = "Do not print encoded version of the key", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "src", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "src", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "pubcheck", + .desc = "Check validity of public key", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubcheck, + }, + { + .name = "pubin", + .desc = "Expect a public key (default private key)", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pubin, + }, + { + .name = "pubout", + .desc = "Output a public key (default private key)", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pubout, + }, + { + .name = "text", + .desc = "Print the public/private key in plain text", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = "text_pub", + .desc = "Print out only public key in plain text", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubtext, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = pkey_opt_cipher, + }, + { NULL } +}; + +static void +pkey_usage(void) +{ + int n = 0; + + fprintf(stderr, + "usage: pkey [-check] [-ciphername] [-in file] [-inform fmt] " + "[-noout] [-out file]\n" + " [-outform fmt] [-passin src] [-passout src] [-pubcheck] " + "[-pubin] [-pubout]\n" + " [-text] [-text_pub]\n\n"); + options_usage(pkey_options); + fprintf(stderr, "\n"); + + fprintf(stderr, "Valid ciphername values:\n\n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, &n); + fprintf(stderr, "\n"); +} + +int +pkey_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + EVP_PKEY *pkey = NULL; + char *passin = NULL, *passout = NULL; + int ret = 1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, pkey_options, NULL, NULL) != 0) { + pkey_usage(); + goto end; + } + + if (cfg.pubtext) + cfg.text = 1; + if (cfg.pubin) + cfg.pubout = cfg.pubtext = 1; + + if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, + &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if (cfg.outfile) { + if (!(out = BIO_new_file(cfg.outfile, "wb"))) { + BIO_printf(bio_err, + "Can't open output file %s\n", cfg.outfile); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + if (cfg.pubin) + pkey = load_pubkey(bio_err, cfg.infile, + cfg.informat, 1, passin, "Public Key"); + else + pkey = load_key(bio_err, cfg.infile, + cfg.informat, 1, passin, "key"); + if (!pkey) + goto end; + + if (cfg.check) { + if (!pkey_check(out, pkey, EVP_PKEY_check, "Key pair")) + goto end; + } else if (cfg.pubcheck) { + if (!pkey_check(out, pkey, EVP_PKEY_public_check, "Public key")) + goto end; + } + + if (!cfg.noout) { + if (cfg.outformat == FORMAT_PEM) { + if (cfg.pubout) + PEM_write_bio_PUBKEY(out, pkey); + else + PEM_write_bio_PrivateKey(out, pkey, + cfg.cipher, NULL, 0, NULL, passout); + } else if (cfg.outformat == FORMAT_ASN1) { + if (cfg.pubout) + i2d_PUBKEY_bio(out, pkey); + else + i2d_PrivateKey_bio(out, pkey); + } else { + BIO_printf(bio_err, "Bad format specified for key\n"); + goto end; + } + + } + if (cfg.text) { + if (cfg.pubtext) + EVP_PKEY_print_public(out, pkey, 0, NULL); + else + EVP_PKEY_print_private(out, pkey, 0, NULL); + } + ret = 0; + + end: + EVP_PKEY_free(pkey); + BIO_free_all(out); + BIO_free(in); + free(passin); + free(passout); + + return ret; +} diff --git a/apps/openssl/pkeyparam.c b/apps/openssl/pkeyparam.c new file mode 100644 index 0000000..543715e --- /dev/null +++ b/apps/openssl/pkeyparam.c @@ -0,0 +1,185 @@ +/* $OpenBSD: pkeyparam.c,v 1.18 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006 + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "apps.h" + +#include +#include +#include + +static struct { + int check; + char *infile; + int noout; + char *outfile; + int text; +} cfg; + +static const struct option pkeyparam_options[] = { + { + .name = "check", + .desc = "Check validity of key parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "noout", + .desc = "Do not print encoded version of the parameters", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "text", + .desc = "Print out the parameters in plain text", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { NULL }, +}; + +static void +pkeyparam_usage(void) +{ + fprintf(stderr, + "usage: pkeyparam [-check] [-in file] [-noout] [-out file] " + "[-text]\n"); + options_usage(pkeyparam_options); +} + +int +pkeyparam_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + EVP_PKEY *pkey = NULL; + int ret = 1; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, pkeyparam_options, NULL, NULL) != 0) { + pkeyparam_usage(); + return (1); + } + + if (cfg.infile) { + if (!(in = BIO_new_file(cfg.infile, "r"))) { + BIO_printf(bio_err, "Can't open input file %s\n", + cfg.infile); + goto end; + } + } else + in = BIO_new_fp(stdin, BIO_NOCLOSE); + + if (cfg.outfile) { + if (!(out = BIO_new_file(cfg.outfile, "w"))) { + BIO_printf(bio_err, "Can't open output file %s\n", + cfg.outfile); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + pkey = PEM_read_bio_Parameters(in, NULL); + if (!pkey) { + BIO_printf(bio_err, "Error reading parameters\n"); + ERR_print_errors(bio_err); + goto end; + } + + if (cfg.check) { + if (!pkey_check(out, pkey, EVP_PKEY_param_check, "Parameters")) + goto end; + } + + if (!cfg.noout) + PEM_write_bio_Parameters(out, pkey); + + if (cfg.text) + EVP_PKEY_print_params(out, pkey, 0, NULL); + + ret = 0; + + end: + EVP_PKEY_free(pkey); + BIO_free_all(out); + BIO_free(in); + + return ret; +} diff --git a/apps/openssl/pkeyutl.c b/apps/openssl/pkeyutl.c new file mode 100644 index 0000000..eebd148 --- /dev/null +++ b/apps/openssl/pkeyutl.c @@ -0,0 +1,571 @@ +/* $OpenBSD: pkeyutl.c,v 1.20 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2006. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include "apps.h" + +#include +#include +#include + +#define KEY_PRIVKEY 1 +#define KEY_PUBKEY 2 +#define KEY_CERT 3 + +static struct { + int asn1parse; + EVP_PKEY_CTX *ctx; + int hexdump; + char *infile; + int key_type; + int keyform; + int keysize; + char *outfile; + char *passargin; + int peerform; + int pkey_op; + int rev; + char *sigfile; +} cfg; + +static void pkeyutl_usage(void); + +static int init_ctx(char *keyfile); + +static int setup_peer(char *file); + +static int pkeyutl_pkeyopt(char *pkeyopt); + +static int do_keyop(EVP_PKEY_CTX * ctx, int pkey_op, + unsigned char *out, size_t * poutlen, + unsigned char *in, size_t inlen); + +static const struct option pkeyutl_options[] = { + { + .name = "asn1parse", + .desc = "ASN.1 parse the output data", + .type = OPTION_FLAG, + .opt.flag = &cfg.asn1parse, + }, + { + .name = "certin", + .desc = "Input is a certificate containing a public key", + .type = OPTION_VALUE, + .value = KEY_CERT, + .opt.value = &cfg.key_type, + }, + { + .name = "decrypt", + .desc = "Decrypt the input data using a private key", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_DECRYPT, + .opt.value = &cfg.pkey_op, + }, + { + .name = "derive", + .desc = "Derive a shared secret using the peer key", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_DERIVE, + .opt.value = &cfg.pkey_op, + }, + { + .name = "encrypt", + .desc = "Encrypt the input data using a public key", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_ENCRYPT, + .opt.value = &cfg.pkey_op, + }, + { + .name = "hexdump", + .desc = "Hex dump the output data", + .type = OPTION_FLAG, + .opt.flag = &cfg.hexdump, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inkey", + .argname = "file", + .desc = "Input key file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = init_ctx, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Input key format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passin", + .argname = "arg", + .desc = "Key password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "peerform", + .argname = "fmt", + .desc = "Input key format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.peerform, + }, + { + .name = "peerkey", + .argname = "file", + .desc = "Peer key file", + .type = OPTION_ARG_FUNC, + .opt.argfunc = setup_peer, + }, + { + .name = "pkeyopt", + .argname = "opt:value", + .desc = "Public key options", + .type = OPTION_ARG_FUNC, + .opt.argfunc = pkeyutl_pkeyopt, + }, + { + .name = "pubin", + .desc = "Input is a public key", + .type = OPTION_VALUE, + .value = KEY_PUBKEY, + .opt.value = &cfg.key_type, + }, + { + .name = "rev", + .desc = "Reverse the input data", + .type = OPTION_FLAG, + .opt.flag = &cfg.rev, + }, + { + .name = "sigfile", + .argname = "file", + .desc = "Signature file (verify operation only)", + .type = OPTION_ARG, + .opt.arg = &cfg.sigfile, + }, + { + .name = "sign", + .desc = "Sign the input data using private key", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_SIGN, + .opt.value = &cfg.pkey_op, + }, + { + .name = "verify", + .desc = "Verify the input data using public key", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_VERIFY, + .opt.value = &cfg.pkey_op, + }, + { + .name = "verifyrecover", + .desc = "Verify with public key, recover original data", + .type = OPTION_VALUE, + .value = EVP_PKEY_OP_VERIFYRECOVER, + .opt.value = &cfg.pkey_op, + }, + + {NULL}, +}; + +static void +pkeyutl_usage(void) +{ + fprintf(stderr, + "usage: pkeyutl [-asn1parse] [-certin] [-decrypt] [-derive] " + "[-encrypt]\n" + " [-hexdump] [-in file] [-inkey file] [-keyform fmt]\n" + " [-out file] [-passin arg] [-peerform fmt]\n" + " [-peerkey file] [-pkeyopt opt:value] [-pubin] [-rev]\n" + " [-sigfile file] [-sign] [-verify] [-verifyrecover]\n\n"); + options_usage(pkeyutl_options); + fprintf(stderr, "\n"); +} + +int +pkeyutl_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; + size_t buf_outlen = 0; + int buf_inlen = 0, siglen = -1; + + int ret = 1, rv = -1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.pkey_op = EVP_PKEY_OP_SIGN; + cfg.key_type = KEY_PRIVKEY; + cfg.keyform = FORMAT_PEM; + cfg.peerform = FORMAT_PEM; + cfg.keysize = -1; + + if (options_parse(argc, argv, pkeyutl_options, NULL, NULL) != 0) { + pkeyutl_usage(); + goto end; + } + + if (!cfg.ctx) { + pkeyutl_usage(); + goto end; + } + if (cfg.sigfile && + (cfg.pkey_op != EVP_PKEY_OP_VERIFY)) { + BIO_puts(bio_err, "Signature file specified for non verify\n"); + goto end; + } + if (!cfg.sigfile && + (cfg.pkey_op == EVP_PKEY_OP_VERIFY)) { + BIO_puts(bio_err, "No signature file specified for verify\n"); + goto end; + } + + if (cfg.pkey_op != EVP_PKEY_OP_DERIVE) { + if (cfg.infile) { + if (!(in = BIO_new_file(cfg.infile, "rb"))) { + BIO_puts(bio_err, + "Error Opening Input File\n"); + ERR_print_errors(bio_err); + goto end; + } + } else + in = BIO_new_fp(stdin, BIO_NOCLOSE); + } + if (cfg.outfile) { + if (!(out = BIO_new_file(cfg.outfile, "wb"))) { + BIO_printf(bio_err, "Error Creating Output File\n"); + ERR_print_errors(bio_err); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + if (cfg.sigfile) { + BIO *sigbio = BIO_new_file(cfg.sigfile, "rb"); + if (!sigbio) { + BIO_printf(bio_err, "Can't open signature file %s\n", + cfg.sigfile); + goto end; + } + siglen = bio_to_mem(&sig, cfg.keysize * 10, sigbio); + BIO_free(sigbio); + if (siglen <= 0) { + BIO_printf(bio_err, "Error reading signature data\n"); + goto end; + } + } + if (in) { + /* Read the input data */ + buf_inlen = bio_to_mem(&buf_in, cfg.keysize * 10, in); + if (buf_inlen <= 0) { + BIO_printf(bio_err, "Error reading input Data\n"); + exit(1); + } + if (cfg.rev) { + size_t i; + unsigned char ctmp; + size_t l = (size_t) buf_inlen; + for (i = 0; i < l / 2; i++) { + ctmp = buf_in[i]; + buf_in[i] = buf_in[l - 1 - i]; + buf_in[l - 1 - i] = ctmp; + } + } + } + if (cfg.pkey_op == EVP_PKEY_OP_VERIFY) { + rv = EVP_PKEY_verify(cfg.ctx, sig, (size_t) siglen, + buf_in, (size_t) buf_inlen); + if (rv == 1) { + BIO_puts(out, "Signature Verified Successfully\n"); + ret = 0; + } else + BIO_puts(out, "Signature Verification Failure\n"); + if (rv >= 0) + goto end; + } else { + rv = do_keyop(cfg.ctx, cfg.pkey_op, NULL, + (size_t *)&buf_outlen, buf_in, (size_t) buf_inlen); + if (rv > 0) { + buf_out = malloc(buf_outlen); + if (!buf_out) + rv = -1; + else + rv = do_keyop(cfg.ctx, + cfg.pkey_op, + buf_out, (size_t *) & buf_outlen, + buf_in, (size_t) buf_inlen); + } + } + + if (rv <= 0) { + BIO_printf(bio_err, "Public Key operation error\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + if (cfg.asn1parse) { + if (!ASN1_parse_dump(out, buf_out, buf_outlen, 1, -1)) + ERR_print_errors(bio_err); + } else if (cfg.hexdump) + BIO_dump(out, (char *) buf_out, buf_outlen); + else + BIO_write(out, buf_out, buf_outlen); + + end: + EVP_PKEY_CTX_free(cfg.ctx); + BIO_free(in); + BIO_free_all(out); + free(buf_in); + free(buf_out); + free(sig); + + return ret; +} + +static int +init_ctx(char *keyfile) +{ + EVP_PKEY *pkey = NULL; + char *passin = NULL; + int rv = -1; + X509 *x; + + if (((cfg.pkey_op == EVP_PKEY_OP_SIGN) + || (cfg.pkey_op == EVP_PKEY_OP_DECRYPT) + || (cfg.pkey_op == EVP_PKEY_OP_DERIVE)) + && (cfg.key_type != KEY_PRIVKEY)) { + BIO_printf(bio_err, + "A private key is needed for this operation\n"); + goto end; + } + if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, + NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + switch (cfg.key_type) { + case KEY_PRIVKEY: + pkey = load_key(bio_err, keyfile, cfg.keyform, 0, + passin, "Private Key"); + break; + + case KEY_PUBKEY: + pkey = load_pubkey(bio_err, keyfile, cfg.keyform, 0, + NULL, "Public Key"); + break; + + case KEY_CERT: + x = load_cert(bio_err, keyfile, cfg.keyform, + NULL, "Certificate"); + if (x) { + pkey = X509_get_pubkey(x); + X509_free(x); + } + break; + } + + cfg.keysize = EVP_PKEY_size(pkey); + + if (!pkey) + goto end; + + cfg.ctx = EVP_PKEY_CTX_new(pkey, NULL); + + EVP_PKEY_free(pkey); + + if (!cfg.ctx) + goto end; + + switch (cfg.pkey_op) { + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign_init(cfg.ctx); + break; + + case EVP_PKEY_OP_VERIFY: + rv = EVP_PKEY_verify_init(cfg.ctx); + break; + + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover_init(cfg.ctx); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt_init(cfg.ctx); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt_init(cfg.ctx); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive_init(cfg.ctx); + break; + } + + if (rv <= 0) { + EVP_PKEY_CTX_free(cfg.ctx); + cfg.ctx = NULL; + } + + end: + free(passin); + + if (!cfg.ctx) { + BIO_puts(bio_err, "Error initializing context\n"); + ERR_print_errors(bio_err); + return (1); + } + + return (0); +} + +static int +setup_peer(char *file) +{ + EVP_PKEY *peer = NULL; + int ret; + + if (!cfg.ctx) { + BIO_puts(bio_err, "-peerkey command before -inkey\n"); + return (1); + } + peer = load_pubkey(bio_err, file, cfg.peerform, 0, NULL, + "Peer Key"); + + if (!peer) { + BIO_printf(bio_err, "Error reading peer key %s\n", file); + ERR_print_errors(bio_err); + return (1); + } + ret = EVP_PKEY_derive_set_peer(cfg.ctx, peer); + + EVP_PKEY_free(peer); + if (ret <= 0) { + ERR_print_errors(bio_err); + return (1); + } + + return (0); +} + +static int +pkeyutl_pkeyopt(char *pkeyopt) +{ + if (!cfg.ctx) { + BIO_puts(bio_err, "-pkeyopt command before -inkey\n"); + return (1); + } else if (pkey_ctrl_string(cfg.ctx, pkeyopt) <= 0) { + BIO_puts(bio_err, "parameter setting error\n"); + ERR_print_errors(bio_err); + return (1); + } + + return (0); +} + +static int +do_keyop(EVP_PKEY_CTX * ctx, int pkey_op, + unsigned char *out, size_t * poutlen, + unsigned char *in, size_t inlen) +{ + int rv = 0; + switch (pkey_op) { + case EVP_PKEY_OP_VERIFYRECOVER: + rv = EVP_PKEY_verify_recover(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_SIGN: + rv = EVP_PKEY_sign(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_ENCRYPT: + rv = EVP_PKEY_encrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DECRYPT: + rv = EVP_PKEY_decrypt(ctx, out, poutlen, in, inlen); + break; + + case EVP_PKEY_OP_DERIVE: + rv = EVP_PKEY_derive(ctx, out, poutlen); + break; + + } + return rv; +} diff --git a/apps/openssl/prime.c b/apps/openssl/prime.c new file mode 100644 index 0000000..36703c5 --- /dev/null +++ b/apps/openssl/prime.c @@ -0,0 +1,201 @@ +/* $OpenBSD: prime.c,v 1.18 2023/07/23 11:39:29 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include + +#include "apps.h" + +#include +#include + +static struct { + int bits; + int checks; + int generate; + int hex; + int safe; +} cfg; + +static const struct option prime_options[] = { + { + .name = "bits", + .argname = "n", + .desc = "Number of bits in the generated prime number", + .type = OPTION_ARG_INT, + .opt.value = &cfg.bits, + }, + { + .name = "checks", + .argname = "n", + .desc = "Miller-Rabin probabilistic primality test iterations", + .type = OPTION_ARG_INT, + .opt.value = &cfg.checks, + }, + { + .name = "generate", + .desc = "Generate a pseudo-random prime number", + .type = OPTION_FLAG, + .opt.flag = &cfg.generate, + }, + { + .name = "hex", + .desc = "Hexadecimal prime numbers", + .type = OPTION_FLAG, + .opt.flag = &cfg.hex, + }, + { + .name = "safe", + .desc = "Generate only \"safe\" prime numbers", + .type = OPTION_FLAG, + .opt.flag = &cfg.safe, + }, + {NULL}, +}; + +static void +prime_usage(void) +{ + fprintf(stderr, + "usage: prime [-bits n] [-checks n] [-generate] [-hex] [-safe] " + "p\n"); + options_usage(prime_options); +} + +int +prime_main(int argc, char **argv) +{ + BIGNUM *bn = NULL; + char *prime = NULL; + BIO *bio_out; + char *s; + int is_prime, ret = 1; + + if (pledge("stdio rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + /* Default iterations for Miller-Rabin probabilistic primality test. */ + cfg.checks = 20; + + if (options_parse(argc, argv, prime_options, &prime, NULL) != 0) { + prime_usage(); + return (1); + } + + if (prime == NULL && cfg.generate == 0) { + BIO_printf(bio_err, "No prime specified.\n"); + prime_usage(); + return (1); + } + + if ((bio_out = BIO_new(BIO_s_file())) == NULL) { + ERR_print_errors(bio_err); + return (1); + } + BIO_set_fp(bio_out, stdout, BIO_NOCLOSE); + + if (cfg.generate != 0) { + if (cfg.bits == 0) { + BIO_printf(bio_err, "Specify the number of bits.\n"); + goto end; + } + bn = BN_new(); + if (!bn) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } + if (!BN_generate_prime_ex(bn, cfg.bits, + cfg.safe, NULL, NULL, NULL)) { + BIO_printf(bio_err, "Prime generation error.\n"); + goto end; + } + s = cfg.hex ? BN_bn2hex(bn) : BN_bn2dec(bn); + if (s == NULL) { + BIO_printf(bio_err, "Out of memory.\n"); + goto end; + } + BIO_printf(bio_out, "%s\n", s); + free(s); + } else { + if (cfg.hex) { + if (!BN_hex2bn(&bn, prime)) { + BIO_printf(bio_err, "%s is an invalid hex " + "value.\n", prime); + goto end; + } + } else { + if (!BN_dec2bn(&bn, prime)) { + BIO_printf(bio_err, "%s is an invalid decimal " + "value.\n", prime); + goto end; + } + } + + is_prime = BN_is_prime_ex(bn, cfg.checks, NULL, NULL); + if (is_prime < 0) { + BIO_printf(bio_err, "BN_is_prime_ex failed.\n"); + goto end; + } + BIO_printf(bio_out, "%s is %sprime\n", prime, + is_prime == 1 ? "" : "not "); + } + + ret = 0; + + end: + BN_free(bn); + BIO_free_all(bio_out); + + return (ret); +} diff --git a/apps/openssl/progs.h b/apps/openssl/progs.h new file mode 100644 index 0000000..8ccf812 --- /dev/null +++ b/apps/openssl/progs.h @@ -0,0 +1,48 @@ +/* $OpenBSD: progs.h,v 1.9 2019/11/04 15:25:54 jsing Exp $ */ +/* Public domain */ + +int asn1parse_main(int argc, char **argv); +int ca_main(int argc, char **argv); +int certhash_main(int argc, char **argv); +int ciphers_main(int argc, char **argv); +int cms_main(int argc, char **argv); +int crl2pkcs7_main(int argc, char **argv); +int crl_main(int argc, char **argv); +int dgst_main(int argc, char **argv); +int dh_main(int argc, char **argv); +int dhparam_main(int argc, char **argv); +int dsa_main(int argc, char **argv); +int dsaparam_main(int argc, char **argv); +int ec_main(int argc, char **argv); +int ecparam_main(int argc, char **argv); +int enc_main(int argc, char **argv); +int errstr_main(int argc, char **argv); +int gendh_main(int argc, char **argv); +int gendsa_main(int argc, char **argv); +int genpkey_main(int argc, char **argv); +int genrsa_main(int argc, char **argv); +int nseq_main(int argc, char **argv); +int ocsp_main(int argc, char **argv); +int passwd_main(int argc, char **argv); +int pkcs7_main(int argc, char **argv); +int pkcs8_main(int argc, char **argv); +int pkcs12_main(int argc, char **argv); +int pkey_main(int argc, char **argv); +int pkeyparam_main(int argc, char **argv); +int pkeyutl_main(int argc, char **argv); +int prime_main(int argc, char **argv); +int rand_main(int argc, char **argv); +int req_main(int argc, char **argv); +int rsa_main(int argc, char **argv); +int rsautl_main(int argc, char **argv); +int s_client_main(int argc, char **argv); +int s_server_main(int argc, char **argv); +int s_time_main(int argc, char **argv); +int sess_id_main(int argc, char **argv); +int smime_main(int argc, char **argv); +int speed_main(int argc, char **argv); +int spkac_main(int argc, char **argv); +int ts_main(int argc, char **argv); +int verify_main(int argc, char **argv); +int version_main(int argc, char **argv); +int x509_main(int argc, char **argv); diff --git a/apps/openssl/rand.c b/apps/openssl/rand.c new file mode 100644 index 0000000..2600322 --- /dev/null +++ b/apps/openssl/rand.c @@ -0,0 +1,182 @@ +/* $OpenBSD: rand.c,v 1.18 2023/07/23 11:39:29 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include + +#include "apps.h" + +#include +#include + +static struct { + int base64; + int hex; + char *outfile; +} cfg; + +static const struct option rand_options[] = { + { + .name = "base64", + .desc = "Perform base64 encoding on output", + .type = OPTION_FLAG, + .opt.flag = &cfg.base64, + }, + { + .name = "hex", + .desc = "Hexadecimal output", + .type = OPTION_FLAG, + .opt.flag = &cfg.hex, + }, + { + .name = "out", + .argname = "file", + .desc = "Write to the given file instead of standard output", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + {NULL}, +}; + +static void +rand_usage(void) +{ + fprintf(stderr, + "usage: rand [-base64 | -hex] [-out file] num\n"); + options_usage(rand_options); +} + +int +rand_main(int argc, char **argv) +{ + char *num_bytes = NULL; + int ret = 1; + int badopt = 0; + int num = -1; + int i, r; + BIO *out = NULL; + + if (pledge("stdio cpath wpath rpath", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + if (options_parse(argc, argv, rand_options, &num_bytes, NULL) != 0) { + rand_usage(); + return (1); + } + + if (num_bytes != NULL) { + r = sscanf(num_bytes, "%d", &num); + if (r == 0 || num < 0) + badopt = 1; + } else + badopt = 1; + + if (cfg.hex && cfg.base64) + badopt = 1; + + if (badopt) { + rand_usage(); + goto err; + } + + out = BIO_new(BIO_s_file()); + if (out == NULL) + goto err; + if (cfg.outfile != NULL) + r = BIO_write_filename(out, cfg.outfile); + else + r = BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); + if (r <= 0) + goto err; + if (cfg.base64) { + BIO *b64 = BIO_new(BIO_f_base64()); + if (b64 == NULL) + goto err; + out = BIO_push(b64, out); + } + + while (num > 0) { + unsigned char buf[4096]; + int chunk; + + chunk = num; + if (chunk > (int) sizeof(buf)) + chunk = sizeof(buf); + arc4random_buf(buf, chunk); + if (cfg.hex) { + for (i = 0; i < chunk; i++) + BIO_printf(out, "%02x", buf[i]); + } else + BIO_write(out, buf, chunk); + num -= chunk; + } + + if (cfg.hex) + BIO_puts(out, "\n"); + (void) BIO_flush(out); + + ret = 0; + + err: + ERR_print_errors(bio_err); + BIO_free_all(out); + + return (ret); +} diff --git a/apps/openssl/req.c b/apps/openssl/req.c new file mode 100644 index 0000000..b75ba92 --- /dev/null +++ b/apps/openssl/req.c @@ -0,0 +1,1878 @@ +/* $OpenBSD: req.c,v 1.28 2023/07/02 07:05:14 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define SECTION "req" + +#define BITS "default_bits" +#define KEYFILE "default_keyfile" +#define PROMPT "prompt" +#define DISTINGUISHED_NAME "distinguished_name" +#define ATTRIBUTES "attributes" +#define V3_EXTENSIONS "x509_extensions" +#define REQ_EXTENSIONS "req_extensions" +#define STRING_MASK "string_mask" +#define UTF8_IN "utf8" + +#define DEFAULT_KEY_LENGTH 2048 +#define MIN_KEY_LENGTH 384 + +static int make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *dn, int multirdn, + int attribs, unsigned long chtype); +static int build_subject(X509_REQ * req, char *subj, unsigned long chtype, + int multirdn); +static int prompt_info(X509_REQ * req, + STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect, + STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs, + unsigned long chtype); +static int auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * sk, + STACK_OF(CONF_VALUE) * attr, int attribs, + unsigned long chtype); +static int add_attribute_object(X509_REQ * req, char *text, const char *def, + char *value, int nid, int n_min, + int n_max, unsigned long chtype); +static int add_DN_object(X509_NAME * n, char *text, const char *def, char *value, + int nid, int n_min, int n_max, unsigned long chtype, int mval); +static int genpkey_cb(EVP_PKEY_CTX * ctx); +static int req_check_len(int len, int n_min, int n_max); +static int check_end(const char *str, const char *end); +static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type, + long *pkeylen, char **palgnam); +static unsigned long ext_name_hash(const OPENSSL_STRING *a); +static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b); +static void exts_cleanup(OPENSSL_STRING *x); +static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv); +static CONF *req_conf = NULL; +static CONF *addext_conf = NULL; + +static struct { + LHASH_OF(OPENSSL_STRING) *addexts; + BIO *addext_bio; + int batch; + unsigned long chtype; + int days; + const EVP_MD *digest; + char *extensions; + char *infile; + int informat; + char *keyalg; + char *keyfile; + int keyform; + char *keyout; + int modulus; + int multirdn; + int newhdr; + long newkey; + int newreq; + unsigned long nmflag; + int nodes; + int noout; + char *outfile; + int outformat; + char *passargin; + char *passargout; + STACK_OF(OPENSSL_STRING) *pkeyopts; + int pubkey; + char *req_exts; + unsigned long reqflag; + ASN1_INTEGER *serial; + STACK_OF(OPENSSL_STRING) *sigopts; + char *subj; + int subject; + char *template; + int text; + int verbose; + int verify; + int x509; +} cfg; + +static int +req_opt_addext(char *arg) +{ + int i; + + if (cfg.addexts == NULL) { + cfg.addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new( + (LHASH_HASH_FN_TYPE)ext_name_hash, + (LHASH_COMP_FN_TYPE)ext_name_cmp); + cfg.addext_bio = BIO_new(BIO_s_mem()); + if (cfg.addexts == NULL || + cfg.addext_bio == NULL) + return (1); + } + i = duplicated(cfg.addexts, arg); + if (i == 1) + return (1); + if (i < 0 || BIO_printf(cfg.addext_bio, "%s\n", arg) < 0) + return (1); + + return (0); +} + +static int +req_opt_days(char *arg) +{ + const char *errstr; + + cfg.days = strtonum(arg, 1, INT_MAX, &errstr); + if (errstr != NULL) { + BIO_printf(bio_err, "bad -days %s, using 0: %s\n", + arg, errstr); + cfg.days = 30; + } + return (0); +} + +static int +req_opt_digest(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.digest = EVP_get_digestbyname(name)) == NULL) + return (1); + + *argsused = 1; + return (0); +} + +static int +req_opt_newkey(char *arg) +{ + cfg.keyalg = arg; + cfg.newreq = 1; + return (0); +} + +static int +req_opt_nameopt(char *arg) +{ + if (!set_name_ex(&cfg.nmflag, arg)) + return (1); + return (0); +} + +static int +req_opt_pkeyopt(char *arg) +{ + if (cfg.pkeyopts == NULL) + cfg.pkeyopts = sk_OPENSSL_STRING_new_null(); + if (cfg.pkeyopts == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.pkeyopts, arg)) + return (1); + return (0); +} + +static int +req_opt_reqopt(char *arg) +{ + if (!set_cert_ex(&cfg.reqflag, arg)) + return (1); + return (0); +} + +static int +req_opt_set_serial(char *arg) +{ + cfg.serial = s2i_ASN1_INTEGER(NULL, arg); + if (cfg.serial == NULL) + return (1); + return (0); +} + +static int +req_opt_sigopt(char *arg) +{ + if (cfg.sigopts == NULL) + cfg.sigopts = sk_OPENSSL_STRING_new_null(); + if (cfg.sigopts == NULL) + return (1); + if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg)) + return (1); + return (0); +} + +static int +req_opt_utf8(void) +{ + cfg.chtype = MBSTRING_UTF8; + return (0); +} + +static const struct option req_options[] = { + { + .name = "addext", + .argname = "key=value", + .desc = "Additional certificate extension (may be repeated)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_addext, + }, + { + .name = "batch", + .desc = "Operate in batch mode", + .type = OPTION_FLAG, + .opt.flag = &cfg.batch, + }, + { + .name = "config", + .argname = "file", + .desc = "Configuration file to use as request template", + .type = OPTION_ARG, + .opt.arg = &cfg.template, + }, + { + .name = "days", + .argname = "number", + .desc = "Number of days generated certificate is valid for", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_days, + }, + { + .name = "extensions", + .argname = "section", + .desc = "Config section to use for certificate extensions", + .type = OPTION_ARG, + .opt.arg = &cfg.extensions, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "key", + .argname = "file", + .desc = "Private key file", + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "keyform", + .argname = "format", + .desc = "Private key format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "keyout", + .argname = "file", + .desc = "Private key output file", + .type = OPTION_ARG, + .opt.arg = &cfg.keyout, + }, + { + .name = "modulus", + .desc = "Print RSA modulus", + .type = OPTION_FLAG, + .opt.flag = &cfg.modulus, + }, + { + .name = "multivalue-rdn", + .desc = "Enable support for multivalued RDNs", + .type = OPTION_FLAG, + .opt.flag = &cfg.multirdn, + }, + { + .name = "nameopt", + .argname = "arg", + .desc = "Certificate name options", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_nameopt, + }, + { + .name = "new", + .desc = "New request", + .type = OPTION_FLAG, + .opt.flag = &cfg.newreq, + }, + { + .name = "newhdr", + .desc = "Include 'NEW' in header lines", + .type = OPTION_FLAG, + .opt.flag = &cfg.newhdr, + }, + { + .name = "newkey", + .argname = "param", + .desc = "Generate a new key using given parameters", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_newkey, + }, + { + .name = "nodes", + .desc = "Do not encrypt output private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.nodes, + }, + { + .name = "noout", + .desc = "Do not output request", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "source", + .desc = "Private key input password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "source", + .desc = "Private key output password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "pkeyopt", + .argname = "opt:val", + .desc = "Set the public key algorithm option opt to val", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_pkeyopt, + }, + { + .name = "pubkey", + .desc = "Output the public key", + .type = OPTION_FLAG, + .opt.flag = &cfg.pubkey, + }, + { + .name = "reqexts", + .argname = "section", + .desc = "Config section to use for request extensions", + .type = OPTION_ARG, + .opt.arg = &cfg.req_exts, + }, + { + .name = "reqopt", + .argname = "option", + .desc = "Request text options", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_reqopt, + }, + { + .name = "set_serial", + .argname = "serial", + .desc = "Serial number to use for generated certificate", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_set_serial, + }, + { + .name = "sigopt", + .argname = "name:val", + .desc = "Signature options", + .type = OPTION_ARG_FUNC, + .opt.argfunc = req_opt_sigopt, + }, + { + .name = "subj", + .argname = "name", + .desc = "Set or modify the request subject", + .type = OPTION_ARG, + .opt.arg = &cfg.subj, + }, + { + .name = "subject", + .desc = "Output the subject of the request", + .type = OPTION_FLAG, + .opt.flag = &cfg.subject, + }, + { + .name = "text", + .desc = "Print request in text form", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = "utf8", + .desc = "Input characters are in UTF-8 (default ASCII)", + .type = OPTION_FUNC, + .opt.func = req_opt_utf8, + }, + { + .name = "verbose", + .desc = "Verbose", + .type = OPTION_FLAG, + .opt.flag = &cfg.verbose, + }, + { + .name = "verify", + .desc = "Verify signature on request", + .type = OPTION_FLAG, + .opt.flag = &cfg.verify, + }, + { + .name = "x509", + .desc = "Output an X.509 structure instead of a certificate request", + .type = OPTION_FLAG, + .opt.flag = &cfg.x509, + }, + { + .name = NULL, + .desc = "", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = req_opt_digest, + }, + { NULL }, +}; + +static void +req_usage(void) +{ + fprintf(stderr, + "usage: req [-addext ext] [-batch] [-config file]\n" + " [-days n] [-extensions section] [-in file]\n" + " [-inform der | pem] [-key keyfile] [-keyform der | pem]\n" + " [-keyout file] [-md4 | -md5 | -sha1] [-modulus]\n" + " [-multivalue-rdn] [-nameopt option] [-new] [-newhdr]\n" + " [-newkey arg] [-nodes] [-noout]\n" + " [-out file] [-outform der | pem] [-passin arg]\n" + " [-passout arg] [-pkeyopt opt:value] [-pubkey]\n" + " [-reqexts section] [-reqopt option] [-set_serial n]\n" + " [-sigopt nm:v] [-subj arg] [-subject] [-text] [-utf8]\n" + " [-verbose] [-verify] [-x509]\n\n"); + + options_usage(req_options); + fprintf(stderr, "\n"); +} + +int +req_main(int argc, char **argv) +{ + int ex = 1; + X509 *x509ss = NULL; + X509_REQ *req = NULL; + EVP_PKEY_CTX *genctx = NULL; + char *keyalgstr = NULL; + const EVP_CIPHER *cipher = NULL; + EVP_PKEY *pkey = NULL; + int i = 0, pkey_type = -1; + BIO *in = NULL, *out = NULL; + char *passin = NULL, *passout = NULL; + const EVP_MD *md_alg = NULL; + char *p; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + + cfg.chtype = MBSTRING_ASC; + cfg.days = 30; + cfg.digest = EVP_sha256(); + cfg.newkey = -1; + cfg.informat = FORMAT_PEM; + cfg.keyform = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, req_options, NULL, NULL) != 0) { + req_usage(); + return (1); + } + + req_conf = NULL; + cipher = EVP_aes_256_cbc(); + + if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if (cfg.template != NULL) { + long errline = -1; + + if (cfg.verbose) + BIO_printf(bio_err, "Using configuration from %s\n", cfg.template); + if ((req_conf = NCONF_new(NULL)) == NULL) + goto end; + if(!NCONF_load(req_conf, cfg.template, &errline)) { + BIO_printf(bio_err, "error on line %ld of %s\n", errline, cfg.template); + goto end; + } + } else { + req_conf = config; + + if (req_conf == NULL) { + BIO_printf(bio_err, "Unable to load config info from %s\n", default_config_file); + if (cfg.newreq) + goto end; + } else if (cfg.verbose) + BIO_printf(bio_err, "Using configuration from %s\n", + default_config_file); + } + + if (cfg.addext_bio != NULL) { + long errline = -1; + if (cfg.verbose) + BIO_printf(bio_err, + "Using additional configuration from command line\n"); + if ((addext_conf = NCONF_new(NULL)) == NULL) + goto end; + if (!NCONF_load_bio(addext_conf, cfg.addext_bio, &errline)) { + BIO_printf(bio_err, + "req: Error on line %ld of config input\n", + errline); + goto end; + } + } + + if (req_conf != NULL) { + if (!load_config(bio_err, req_conf)) + goto end; + p = NCONF_get_string(req_conf, NULL, "oid_file"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + BIO *oid_bio; + + oid_bio = BIO_new_file(p, "r"); + if (oid_bio == NULL) { + /* + BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); + ERR_print_errors(bio_err); + */ + } else { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); + } + } + } + if (!add_oid_section(bio_err, req_conf)) + goto end; + + if (md_alg == NULL) { + p = NCONF_get_string(req_conf, SECTION, "default_md"); + if (p == NULL) + ERR_clear_error(); + if (p != NULL) { + if ((md_alg = EVP_get_digestbyname(p)) != NULL) + cfg.digest = md_alg; + } + } + if (!cfg.extensions) { + cfg.extensions = NCONF_get_string(req_conf, SECTION, V3_EXTENSIONS); + if (!cfg.extensions) + ERR_clear_error(); + } + if (cfg.extensions) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, req_conf); + if (!X509V3_EXT_add_nconf(req_conf, &ctx, cfg.extensions, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", cfg.extensions); + goto end; + } + } + if (addext_conf != NULL) { + /* Check syntax of command line extensions */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, addext_conf); + if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { + BIO_printf(bio_err, + "Error Loading command line extensions\n"); + goto end; + } + } + if (!passin) { + passin = NCONF_get_string(req_conf, SECTION, "input_password"); + if (!passin) + ERR_clear_error(); + } + if (!passout) { + passout = NCONF_get_string(req_conf, SECTION, "output_password"); + if (!passout) + ERR_clear_error(); + } + p = NCONF_get_string(req_conf, SECTION, STRING_MASK); + if (!p) + ERR_clear_error(); + + if (p && !ASN1_STRING_set_default_mask_asc(p)) { + BIO_printf(bio_err, "Invalid global string mask setting %s\n", p); + goto end; + } + if (cfg.chtype != MBSTRING_UTF8) { + p = NCONF_get_string(req_conf, SECTION, UTF8_IN); + if (!p) + ERR_clear_error(); + else if (!strcmp(p, "yes")) + cfg.chtype = MBSTRING_UTF8; + } + if (!cfg.req_exts) { + cfg.req_exts = NCONF_get_string(req_conf, SECTION, REQ_EXTENSIONS); + if (!cfg.req_exts) + ERR_clear_error(); + } + if (cfg.req_exts) { + /* Check syntax of file */ + X509V3_CTX ctx; + X509V3_set_ctx_test(&ctx); + X509V3_set_nconf(&ctx, req_conf); + if (!X509V3_EXT_add_nconf(req_conf, &ctx, cfg.req_exts, NULL)) { + BIO_printf(bio_err, + "Error Loading request extension section %s\n", + cfg.req_exts); + goto end; + } + } + in = BIO_new(BIO_s_file()); + out = BIO_new(BIO_s_file()); + if ((in == NULL) || (out == NULL)) + goto end; + + if (cfg.keyfile != NULL) { + pkey = load_key(bio_err, cfg.keyfile, cfg.keyform, 0, passin, + "Private Key"); + if (!pkey) { + /* + * load_key() has already printed an appropriate + * message + */ + goto end; + } + } + if (cfg.newreq && (pkey == NULL)) { + if (!NCONF_get_number(req_conf, SECTION, BITS, &cfg.newkey)) { + cfg.newkey = DEFAULT_KEY_LENGTH; + } + if (cfg.keyalg) { + genctx = set_keygen_ctx(bio_err, cfg.keyalg, &pkey_type, &cfg.newkey, + &keyalgstr); + if (!genctx) + goto end; + } + if (cfg.newkey < MIN_KEY_LENGTH && (pkey_type == EVP_PKEY_RSA || pkey_type == EVP_PKEY_DSA)) { + BIO_printf(bio_err, "private key length is too short,\n"); + BIO_printf(bio_err, "it needs to be at least %d bits, not %ld\n", MIN_KEY_LENGTH, cfg.newkey); + goto end; + } + if (!genctx) { + genctx = set_keygen_ctx(bio_err, NULL, &pkey_type, &cfg.newkey, + &keyalgstr); + if (!genctx) + goto end; + } + if (cfg.pkeyopts) { + char *genopt; + for (i = 0; i < sk_OPENSSL_STRING_num(cfg.pkeyopts); i++) { + genopt = sk_OPENSSL_STRING_value(cfg.pkeyopts, i); + if (pkey_ctrl_string(genctx, genopt) <= 0) { + BIO_printf(bio_err, + "parameter error \"%s\"\n", + genopt); + ERR_print_errors(bio_err); + goto end; + } + } + } + BIO_printf(bio_err, "Generating a %ld bit %s private key\n", + cfg.newkey, keyalgstr); + + EVP_PKEY_CTX_set_cb(genctx, genpkey_cb); + EVP_PKEY_CTX_set_app_data(genctx, bio_err); + + if (EVP_PKEY_keygen(genctx, &pkey) <= 0) { + BIO_puts(bio_err, "Error Generating Key\n"); + goto end; + } + EVP_PKEY_CTX_free(genctx); + genctx = NULL; + + if (cfg.keyout == NULL) { + cfg.keyout = NCONF_get_string(req_conf, SECTION, KEYFILE); + if (cfg.keyout == NULL) + ERR_clear_error(); + } + if (cfg.keyout == NULL) { + BIO_printf(bio_err, "writing new private key to stdout\n"); + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + BIO_printf(bio_err, "writing new private key to '%s'\n", cfg.keyout); + if (BIO_write_filename(out, cfg.keyout) <= 0) { + perror(cfg.keyout); + goto end; + } + } + + p = NCONF_get_string(req_conf, SECTION, "encrypt_rsa_key"); + if (p == NULL) { + ERR_clear_error(); + p = NCONF_get_string(req_conf, SECTION, "encrypt_key"); + if (p == NULL) + ERR_clear_error(); + } + if ((p != NULL) && (strcmp(p, "no") == 0)) + cipher = NULL; + if (cfg.nodes) + cipher = NULL; + + i = 0; + loop: + if (!PEM_write_bio_PrivateKey(out, pkey, cipher, + NULL, 0, NULL, passout)) { + if ((ERR_GET_REASON(ERR_peek_error()) == + PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3)) { + ERR_clear_error(); + i++; + goto loop; + } + goto end; + } + BIO_printf(bio_err, "-----\n"); + } + if (!cfg.newreq) { + if (cfg.infile == NULL) + BIO_set_fp(in, stdin, BIO_NOCLOSE); + else { + if (BIO_read_filename(in, cfg.infile) <= 0) { + perror(cfg.infile); + goto end; + } + } + + if (cfg.informat == FORMAT_ASN1) + req = d2i_X509_REQ_bio(in, NULL); + else if (cfg.informat == FORMAT_PEM) + req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL); + else { + BIO_printf(bio_err, "bad input format specified for X509 request\n"); + goto end; + } + if (req == NULL) { + BIO_printf(bio_err, "unable to load X509 request\n"); + goto end; + } + } + if (cfg.newreq || cfg.x509) { + if (pkey == NULL) { + BIO_printf(bio_err, "you need to specify a private key\n"); + goto end; + } + if (req == NULL) { + req = X509_REQ_new(); + if (req == NULL) { + goto end; + } + i = make_REQ(req, pkey, cfg.subj, cfg.multirdn, !cfg.x509, cfg.chtype); + cfg.subj = NULL; /* done processing '-subj' option */ + if (!i) { + BIO_printf(bio_err, "problems making Certificate Request\n"); + goto end; + } + } + if (cfg.x509) { + EVP_PKEY *tmppkey; + + X509V3_CTX ext_ctx; + if ((x509ss = X509_new()) == NULL) + goto end; + + /* Set version to V3 */ + if ((cfg.extensions != NULL || addext_conf != NULL) && + !X509_set_version(x509ss, 2)) + goto end; + if (cfg.serial) { + if (!X509_set_serialNumber(x509ss, cfg.serial)) + goto end; + } else { + if (!rand_serial(NULL, + X509_get_serialNumber(x509ss))) + goto end; + } + + if (!X509_set_issuer_name(x509ss, X509_REQ_get_subject_name(req))) + goto end; + if (!X509_gmtime_adj(X509_get_notBefore(x509ss), 0)) + goto end; + if (!X509_time_adj_ex(X509_get_notAfter(x509ss), cfg.days, 0, NULL)) + goto end; + if (!X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req))) + goto end; + if ((tmppkey = X509_REQ_get0_pubkey(req)) == NULL) + goto end; + if (!X509_set_pubkey(x509ss, tmppkey)) + goto end; + + /* Set up V3 context struct */ + + X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); + X509V3_set_nconf(&ext_ctx, req_conf); + + /* Add extensions */ + if (cfg.extensions && !X509V3_EXT_add_nconf(req_conf, + &ext_ctx, cfg.extensions, x509ss)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", + cfg.extensions); + goto end; + } + if (addext_conf != NULL && + !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, + "default", x509ss)) { + BIO_printf(bio_err, + "Error Loading command line extensions\n"); + goto end; + } + i = do_X509_sign(bio_err, x509ss, pkey, cfg.digest, cfg.sigopts); + if (!i) { + ERR_print_errors(bio_err); + goto end; + } + } else { + X509V3_CTX ext_ctx; + + /* Set up V3 context struct */ + + X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0); + X509V3_set_nconf(&ext_ctx, req_conf); + + /* Add extensions */ + if (cfg.req_exts && !X509V3_EXT_REQ_add_nconf(req_conf, + &ext_ctx, cfg.req_exts, req)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", + cfg.req_exts); + goto end; + } + if (addext_conf != NULL && + !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, + "default", req)) { + BIO_printf(bio_err, + "Error Loading command line extensions\n"); + goto end; + } + i = do_X509_REQ_sign(bio_err, req, pkey, cfg.digest, cfg.sigopts); + if (!i) { + ERR_print_errors(bio_err); + goto end; + } + } + } + if (cfg.subj && cfg.x509) { + BIO_printf(bio_err, "Cannot modify certificate subject\n"); + goto end; + } + if (cfg.subj && !cfg.x509) { + if (cfg.verbose) { + BIO_printf(bio_err, "Modifying Request's Subject\n"); + print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), cfg.nmflag); + } + if (build_subject(req, cfg.subj, cfg.chtype, cfg.multirdn) == 0) { + BIO_printf(bio_err, "ERROR: cannot modify subject\n"); + ex = 1; + goto end; + } + + if (cfg.verbose) { + print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), cfg.nmflag); + } + } + if (cfg.verify && !cfg.x509) { + EVP_PKEY *pubkey = pkey; + + if (pubkey == NULL) + pubkey = X509_REQ_get0_pubkey(req); + if (pubkey == NULL) + goto end; + i = X509_REQ_verify(req, pubkey); + if (i < 0) { + goto end; + } else if (i == 0) { + BIO_printf(bio_err, "verify failure\n"); + ERR_print_errors(bio_err); + } else /* if (i > 0) */ + BIO_printf(bio_err, "verify OK\n"); + } + if (cfg.noout && !cfg.text && !cfg.modulus && !cfg.subject && !cfg.pubkey) { + ex = 0; + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if ((cfg.keyout != NULL) && (strcmp(cfg.outfile, cfg.keyout) == 0)) + i = (int) BIO_append_filename(out, cfg.outfile); + else + i = (int) BIO_write_filename(out, cfg.outfile); + if (!i) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.pubkey) { + EVP_PKEY *tpubkey; + + if ((tpubkey = X509_REQ_get0_pubkey(req)) == NULL) { + BIO_printf(bio_err, "Error getting public key\n"); + ERR_print_errors(bio_err); + goto end; + } + PEM_write_bio_PUBKEY(out, tpubkey); + } + if (cfg.text) { + if (cfg.x509) + X509_print_ex(out, x509ss, cfg.nmflag, cfg.reqflag); + else + X509_REQ_print_ex(out, req, cfg.nmflag, cfg.reqflag); + } + if (cfg.subject) { + if (cfg.x509) + print_name(out, "subject=", X509_get_subject_name(x509ss), cfg.nmflag); + else + print_name(out, "subject=", X509_REQ_get_subject_name(req), cfg.nmflag); + } + if (cfg.modulus) { + EVP_PKEY *tpubkey; + + if (cfg.x509) + tpubkey = X509_get0_pubkey(x509ss); + else + tpubkey = X509_REQ_get0_pubkey(req); + if (tpubkey == NULL) { + fprintf(stdout, "Modulus=unavailable\n"); + goto end; + } + fprintf(stdout, "Modulus="); + if (EVP_PKEY_base_id(tpubkey) == EVP_PKEY_RSA) { + const BIGNUM *n = NULL; + + RSA_get0_key(EVP_PKEY_get0_RSA(tpubkey), &n, NULL, NULL); + + BN_print(out, n); + } else + fprintf(stdout, "Wrong Algorithm type"); + fprintf(stdout, "\n"); + } + if (!cfg.noout && !cfg.x509) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_X509_REQ_bio(out, req); + else if (cfg.outformat == FORMAT_PEM) { + if (cfg.newhdr) + i = PEM_write_bio_X509_REQ_NEW(out, req); + else + i = PEM_write_bio_X509_REQ(out, req); + } else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write X509 request\n"); + goto end; + } + } + if (!cfg.noout && cfg.x509 && (x509ss != NULL)) { + if (cfg.outformat == FORMAT_ASN1) + i = i2d_X509_bio(out, x509ss); + else if (cfg.outformat == FORMAT_PEM) + i = PEM_write_bio_X509(out, x509ss); + else { + BIO_printf(bio_err, "bad output format specified for outfile\n"); + goto end; + } + if (!i) { + BIO_printf(bio_err, "unable to write X509 certificate\n"); + goto end; + } + } + ex = 0; + end: + if (ex) { + ERR_print_errors(bio_err); + } + if ((req_conf != NULL) && (req_conf != config)) + NCONF_free(req_conf); + NCONF_free(addext_conf); + BIO_free(cfg.addext_bio); + BIO_free(in); + BIO_free_all(out); + EVP_PKEY_free(pkey); + if (genctx) + EVP_PKEY_CTX_free(genctx); + if (cfg.pkeyopts) + sk_OPENSSL_STRING_free(cfg.pkeyopts); + if (cfg.sigopts) + sk_OPENSSL_STRING_free(cfg.sigopts); + lh_OPENSSL_STRING_doall(cfg.addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup); + lh_OPENSSL_STRING_free(cfg.addexts); + free(keyalgstr); + X509_REQ_free(req); + X509_free(x509ss); + ASN1_INTEGER_free(cfg.serial); + if (cfg.passargin && passin) + free(passin); + if (cfg.passargout && passout) + free(passout); + OBJ_cleanup(); + + return (ex); +} + +static int +make_REQ(X509_REQ * req, EVP_PKEY * pkey, char *subj, int multirdn, + int attribs, unsigned long chtype) +{ + int ret = 0, i; + char no_prompt = 0; + STACK_OF(CONF_VALUE) * dn_sk, *attr_sk = NULL; + char *tmp, *dn_sect, *attr_sect; + + tmp = NCONF_get_string(req_conf, SECTION, PROMPT); + if (tmp == NULL) + ERR_clear_error(); + if ((tmp != NULL) && !strcmp(tmp, "no")) + no_prompt = 1; + + dn_sect = NCONF_get_string(req_conf, SECTION, DISTINGUISHED_NAME); + if (dn_sect == NULL) { + BIO_printf(bio_err, "unable to find '%s' in config\n", + DISTINGUISHED_NAME); + goto err; + } + dn_sk = NCONF_get_section(req_conf, dn_sect); + if (dn_sk == NULL) { + BIO_printf(bio_err, "unable to get '%s' section\n", dn_sect); + goto err; + } + attr_sect = NCONF_get_string(req_conf, SECTION, ATTRIBUTES); + if (attr_sect == NULL) { + ERR_clear_error(); + attr_sk = NULL; + } else { + attr_sk = NCONF_get_section(req_conf, attr_sect); + if (attr_sk == NULL) { + BIO_printf(bio_err, "unable to get '%s' section\n", attr_sect); + goto err; + } + } + + /* setup version number */ + if (!X509_REQ_set_version(req, 0L)) + goto err; /* version 1 */ + + if (no_prompt) + i = auto_info(req, dn_sk, attr_sk, attribs, chtype); + else { + if (subj) + i = build_subject(req, subj, chtype, multirdn); + else + i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype); + } + if (!i) + goto err; + + if (!X509_REQ_set_pubkey(req, pkey)) + goto err; + + ret = 1; + err: + return (ret); +} + +/* + * subject is expected to be in the format /type0=value0/type1=value1/type2=... + * where characters may be escaped by \ + */ +static int +build_subject(X509_REQ * req, char *subject, unsigned long chtype, int multirdn) +{ + X509_NAME *n; + + if (!(n = parse_name(subject, chtype, multirdn))) + return 0; + + if (!X509_REQ_set_subject_name(req, n)) { + X509_NAME_free(n); + return 0; + } + X509_NAME_free(n); + return 1; +} + + +static int +prompt_info(X509_REQ * req, + STACK_OF(CONF_VALUE) * dn_sk, char *dn_sect, + STACK_OF(CONF_VALUE) * attr_sk, char *attr_sect, int attribs, + unsigned long chtype) +{ + int i; + char *p, *q; + char buf[100]; + int nid, mval; + long n_min, n_max; + char *type, *value; + const char *def; + CONF_VALUE *v; + X509_NAME *subj; + subj = X509_REQ_get_subject_name(req); + + if (!cfg.batch) { + BIO_printf(bio_err, "You are about to be asked to enter information that will be incorporated\n"); + BIO_printf(bio_err, "into your certificate request.\n"); + BIO_printf(bio_err, "What you are about to enter is what is called a Distinguished Name or a DN.\n"); + BIO_printf(bio_err, "There are quite a few fields but you can leave some blank\n"); + BIO_printf(bio_err, "For some fields there will be a default value,\n"); + BIO_printf(bio_err, "If you enter '.', the field will be left blank.\n"); + BIO_printf(bio_err, "-----\n"); + } + if (sk_CONF_VALUE_num(dn_sk)) { + i = -1; + start: for (;;) { + int ret; + i++; + if (sk_CONF_VALUE_num(dn_sk) <= i) + break; + + v = sk_CONF_VALUE_value(dn_sk, i); + p = q = NULL; + type = v->name; + if (!check_end(type, "_min") || !check_end(type, "_max") || + !check_end(type, "_default") || + !check_end(type, "_value")) + continue; + /* + * Skip past any leading X. X: X, etc to allow for + * multiple instances + */ + for (p = v->name; *p; p++) + if ((*p == ':') || (*p == ',') || + (*p == '.')) { + p++; + if (*p) + type = p; + break; + } + if (*type == '+') { + mval = -1; + type++; + } else + mval = 0; + /* If OBJ not recognised ignore it */ + if ((nid = OBJ_txt2nid(type)) == NID_undef) + goto start; + ret = snprintf(buf, sizeof buf, "%s_default", v->name); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for default\n", + v->name); + return 0; + } + if ((def = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { + ERR_clear_error(); + def = ""; + } + ret = snprintf(buf, sizeof buf, "%s_value", v->name); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for value\n", + v->name); + return 0; + } + if ((value = NCONF_get_string(req_conf, dn_sect, buf)) == NULL) { + ERR_clear_error(); + value = NULL; + } + ret = snprintf(buf, sizeof buf, "%s_min", v->name); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for min\n", + v->name); + return 0; + } + if (!NCONF_get_number(req_conf, dn_sect, buf, &n_min)) { + ERR_clear_error(); + n_min = -1; + } + ret = snprintf(buf, sizeof buf, "%s_max", v->name); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for max\n", + v->name); + return 0; + } + if (!NCONF_get_number(req_conf, dn_sect, buf, &n_max)) { + ERR_clear_error(); + n_max = -1; + } + if (!add_DN_object(subj, v->value, def, value, nid, + n_min, n_max, chtype, mval)) + return 0; + } + if (X509_NAME_entry_count(subj) == 0) { + BIO_printf(bio_err, "error, no objects specified in config file\n"); + return 0; + } + if (attribs) { + if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && + (!cfg.batch)) { + BIO_printf(bio_err, + "\nPlease enter the following 'extra' attributes\n"); + BIO_printf(bio_err, + "to be sent with your certificate request\n"); + } + i = -1; +start2: for (;;) { + int ret; + i++; + if ((attr_sk == NULL) || + (sk_CONF_VALUE_num(attr_sk) <= i)) + break; + + v = sk_CONF_VALUE_value(attr_sk, i); + type = v->name; + if ((nid = OBJ_txt2nid(type)) == NID_undef) + goto start2; + ret = snprintf(buf, sizeof buf, "%s_default", type); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for default\n", + v->name); + return 0; + } + if ((def = NCONF_get_string(req_conf, attr_sect, buf)) + == NULL) { + ERR_clear_error(); + def = ""; + } + ret = snprintf(buf, sizeof buf, "%s_value", type); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for value\n", + v->name); + return 0; + } + if ((value = NCONF_get_string(req_conf, attr_sect, buf)) + == NULL) { + ERR_clear_error(); + value = NULL; + } + ret = snprintf(buf, sizeof buf, "%s_min", type); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for min\n", + v->name); + return 0; + } + if (!NCONF_get_number(req_conf, attr_sect, buf, &n_min)) { + ERR_clear_error(); + n_min = -1; + } + ret = snprintf(buf, sizeof buf, "%s_max", type); + if (ret < 0 || ret >= sizeof(buf)) { + BIO_printf(bio_err, "Name '%s' too long for max\n", + v->name); + return 0; + } + if (!NCONF_get_number(req_conf, attr_sect, buf, &n_max)) { + ERR_clear_error(); + n_max = -1; + } + if (!add_attribute_object(req, + v->value, def, value, nid, n_min, n_max, chtype)) + return 0; + } + } + } else { + BIO_printf(bio_err, "No template, please set one up.\n"); + return 0; + } + + return 1; + +} + +static int +auto_info(X509_REQ * req, STACK_OF(CONF_VALUE) * dn_sk, + STACK_OF(CONF_VALUE) * attr_sk, int attribs, unsigned long chtype) +{ + int i; + char *p, *q; + char *type; + CONF_VALUE *v; + X509_NAME *subj; + + subj = X509_REQ_get_subject_name(req); + + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + int mval; + v = sk_CONF_VALUE_value(dn_sk, i); + p = q = NULL; + type = v->name; + /* + * Skip past any leading X. X: X, etc to allow for multiple + * instances + */ + for (p = v->name; *p; p++) + if ((*p == ':') || (*p == ',') || (*p == '.')) { + p++; + if (*p) + type = p; + break; + } + if (*p == '+') { + p++; + mval = -1; + } else + mval = 0; + if (!X509_NAME_add_entry_by_txt(subj, type, chtype, + (unsigned char *) v->value, -1, -1, mval)) + return 0; + + } + + if (!X509_NAME_entry_count(subj)) { + BIO_printf(bio_err, "error, no objects specified in config file\n"); + return 0; + } + if (attribs) { + for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) { + v = sk_CONF_VALUE_value(attr_sk, i); + if (!X509_REQ_add1_attr_by_txt(req, v->name, chtype, + (unsigned char *) v->value, -1)) + return 0; + } + } + return 1; +} + + +static int +add_DN_object(X509_NAME * n, char *text, const char *def, char *value, + int nid, int n_min, int n_max, unsigned long chtype, int mval) +{ + int i, ret = 0; + char buf[1024]; + start: + if (!cfg.batch) + BIO_printf(bio_err, "%s [%s]:", text, def); + (void) BIO_flush(bio_err); + if (value != NULL) { + strlcpy(buf, value, sizeof buf); + strlcat(buf, "\n", sizeof buf); + BIO_printf(bio_err, "%s\n", value); + } else { + buf[0] = '\0'; + if (!cfg.batch) { + if (!fgets(buf, sizeof buf, stdin)) + return 0; + } else { + buf[0] = '\n'; + buf[1] = '\0'; + } + } + + if (buf[0] == '\0') + return (0); + else if (buf[0] == '\n') { + if ((def == NULL) || (def[0] == '\0')) + return (1); + strlcpy(buf, def, sizeof buf); + strlcat(buf, "\n", sizeof buf); + } else if ((buf[0] == '.') && (buf[1] == '\n')) + return (1); + + i = strlen(buf); + if (buf[i - 1] != '\n') { + BIO_printf(bio_err, "weird input :-(\n"); + return (0); + } + buf[--i] = '\0'; + if (!req_check_len(i, n_min, n_max)) + goto start; + if (!X509_NAME_add_entry_by_NID(n, nid, chtype, + (unsigned char *) buf, -1, -1, mval)) + goto err; + ret = 1; + err: + return (ret); +} + +static int +add_attribute_object(X509_REQ * req, char *text, const char *def, + char *value, int nid, int n_min, + int n_max, unsigned long chtype) +{ + int i; + static char buf[1024]; + + start: + if (!cfg.batch) + BIO_printf(bio_err, "%s [%s]:", text, def); + (void) BIO_flush(bio_err); + if (value != NULL) { + strlcpy(buf, value, sizeof buf); + strlcat(buf, "\n", sizeof buf); + BIO_printf(bio_err, "%s\n", value); + } else { + buf[0] = '\0'; + if (!cfg.batch) { + if (!fgets(buf, sizeof buf, stdin)) + return 0; + } else { + buf[0] = '\n'; + buf[1] = '\0'; + } + } + + if (buf[0] == '\0') + return (0); + else if (buf[0] == '\n') { + if ((def == NULL) || (def[0] == '\0')) + return (1); + strlcpy(buf, def, sizeof buf); + strlcat(buf, "\n", sizeof buf); + } else if ((buf[0] == '.') && (buf[1] == '\n')) + return (1); + + i = strlen(buf); + if (buf[i - 1] != '\n') { + BIO_printf(bio_err, "weird input :-(\n"); + return (0); + } + buf[--i] = '\0'; + if (!req_check_len(i, n_min, n_max)) + goto start; + + if (!X509_REQ_add1_attr_by_NID(req, nid, chtype, + (unsigned char *) buf, -1)) { + BIO_printf(bio_err, "Error adding attribute\n"); + ERR_print_errors(bio_err); + goto err; + } + return (1); + err: + return (0); +} + +static int +req_check_len(int len, int n_min, int n_max) +{ + if ((n_min > 0) && (len < n_min)) { + BIO_printf(bio_err, "string is too short, it needs to be at least %d bytes long\n", n_min); + return (0); + } + if ((n_max >= 0) && (len > n_max)) { + BIO_printf(bio_err, "string is too long, it needs to be less than %d bytes long\n", n_max); + return (0); + } + return (1); +} + +/* Check if the end of a string matches 'end' */ +static int +check_end(const char *str, const char *end) +{ + int elen, slen; + const char *tmp; + elen = strlen(end); + slen = strlen(str); + if (elen > slen) + return 1; + tmp = str + slen - elen; + return strcmp(tmp, end); +} + +static EVP_PKEY_CTX * +set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type, + long *pkeylen, char **palgnam) +{ + EVP_PKEY_CTX *gctx = NULL; + EVP_PKEY *param = NULL; + long keylen = -1; + BIO *pbio = NULL; + const char *paramfile = NULL; + const char *errstr; + + if (gstr == NULL) { + *pkey_type = EVP_PKEY_RSA; + keylen = *pkeylen; + } else if (gstr[0] >= '0' && gstr[0] <= '9') { + *pkey_type = EVP_PKEY_RSA; + keylen = strtonum(gstr, 0, LONG_MAX, &errstr); + if (errstr) { + BIO_printf(err, "bad algorithm %s: %s\n", gstr, errstr); + return NULL; + } + *pkeylen = keylen; + } else if (!strncmp(gstr, "param:", 6)) + paramfile = gstr + 6; + else { + const char *p = strchr(gstr, ':'); + int len; + const EVP_PKEY_ASN1_METHOD *ameth; + + if (p) + len = p - gstr; + else + len = strlen(gstr); + + ameth = EVP_PKEY_asn1_find_str(NULL, gstr, len); + + if (!ameth) { + BIO_printf(err, "Unknown algorithm %.*s\n", len, gstr); + return NULL; + } + EVP_PKEY_asn1_get0_info(NULL, pkey_type, NULL, NULL, NULL, + ameth); + if (*pkey_type == EVP_PKEY_RSA) { + if (p) { + keylen = strtonum(p + 1, 0, LONG_MAX, &errstr); + if (errstr) { + BIO_printf(err, "bad algorithm %s: %s\n", + p + 1, errstr); + return NULL; + } + *pkeylen = keylen; + } else + keylen = *pkeylen; + } else if (p) + paramfile = p + 1; + } + + if (paramfile) { + pbio = BIO_new_file(paramfile, "r"); + if (!pbio) { + BIO_printf(err, "Can't open parameter file %s\n", + paramfile); + return NULL; + } + param = PEM_read_bio_Parameters(pbio, NULL); + + if (!param) { + X509 *x; + (void) BIO_reset(pbio); + x = PEM_read_bio_X509(pbio, NULL, NULL, NULL); + if (x) { + param = X509_get_pubkey(x); + X509_free(x); + } + } + BIO_free(pbio); + + if (!param) { + BIO_printf(err, "Error reading parameter file %s\n", + paramfile); + return NULL; + } + if (*pkey_type == -1) + *pkey_type = EVP_PKEY_id(param); + else if (*pkey_type != EVP_PKEY_base_id(param)) { + BIO_printf(err, "Key Type does not match parameters\n"); + EVP_PKEY_free(param); + return NULL; + } + } + if (palgnam) { + const EVP_PKEY_ASN1_METHOD *ameth; + const char *anam; + ameth = EVP_PKEY_asn1_find(NULL, *pkey_type); + if (!ameth) { + BIO_puts(err, "Internal error: can't find key algorithm\n"); + return NULL; + } + EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &anam, ameth); + *palgnam = strdup(anam); + } + if (param) { + gctx = EVP_PKEY_CTX_new(param, NULL); + *pkeylen = EVP_PKEY_bits(param); + EVP_PKEY_free(param); + } else + gctx = EVP_PKEY_CTX_new_id(*pkey_type, NULL); + + if (!gctx) { + BIO_puts(err, "Error allocating keygen context\n"); + ERR_print_errors(err); + return NULL; + } + if (EVP_PKEY_keygen_init(gctx) <= 0) { + BIO_puts(err, "Error initializing keygen context\n"); + ERR_print_errors(err); + return NULL; + } + if ((*pkey_type == EVP_PKEY_RSA) && (keylen != -1)) { + if (EVP_PKEY_CTX_set_rsa_keygen_bits(gctx, keylen) <= 0) { + BIO_puts(err, "Error setting RSA keysize\n"); + ERR_print_errors(err); + EVP_PKEY_CTX_free(gctx); + return NULL; + } + } + + return gctx; +} + +static int +genpkey_cb(EVP_PKEY_CTX * ctx) +{ + char c = '*'; + BIO *b = EVP_PKEY_CTX_get_app_data(ctx); + int p; + p = EVP_PKEY_CTX_get_keygen_info(ctx, 0); + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + BIO_write(b, &c, 1); + (void) BIO_flush(b); + return 1; +} + +static int +do_sign_init(BIO * err, EVP_MD_CTX * ctx, EVP_PKEY * pkey, + const EVP_MD * md, STACK_OF(OPENSSL_STRING) * sigopts) +{ + EVP_PKEY_CTX *pkctx = NULL; + int default_nid; + int i; + + if (EVP_PKEY_get_default_digest_nid(pkey, &default_nid) == 2 && + default_nid == NID_undef) { + /* The digest is required to be EVP_md_null() (EdDSA). */ + md = EVP_md_null(); + } + + if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) + return 0; + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); + return 0; + } + } + return 1; +} + +int +do_X509_sign(BIO * err, X509 * x, EVP_PKEY * pkey, const EVP_MD * md, + STACK_OF(OPENSSL_STRING) * sigopts) +{ + EVP_MD_CTX *mctx; + int rv; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + return 0; + + rv = do_sign_init(err, mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_sign_ctx(x, mctx); + + EVP_MD_CTX_free(mctx); + + return rv > 0; +} + + +int +do_X509_REQ_sign(BIO * err, X509_REQ * x, EVP_PKEY * pkey, const EVP_MD * md, + STACK_OF(OPENSSL_STRING) * sigopts) +{ + EVP_MD_CTX *mctx; + int rv; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + return 0; + + rv = do_sign_init(err, mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_REQ_sign_ctx(x, mctx); + + EVP_MD_CTX_free(mctx); + + return rv > 0; +} + + + +int +do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md, + STACK_OF(OPENSSL_STRING) * sigopts) +{ + int rv; + EVP_MD_CTX *mctx; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + return 0; + + rv = do_sign_init(err, mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_CRL_sign_ctx(x, mctx); + + EVP_MD_CTX_free(mctx); + + return rv > 0; +} + +static unsigned long +ext_name_hash(const OPENSSL_STRING *a) +{ + return lh_strhash((const char *)a); +} + +static int +ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) +{ + return strcmp((const char *)a, (const char *)b); +} + +static void +exts_cleanup(OPENSSL_STRING *x) +{ + free((char *)x); +} + +/* + * Is the |kv| key already duplicated ? This is remarkably tricky to get right. + * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error. + */ +static int +duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) +{ + char *p; + size_t off; + + /* Check syntax. */ + /* Skip leading whitespace, make a copy. */ + while (*kv && isspace(*kv)) + if (*++kv == '\0') + return 1; + if ((p = strchr(kv, '=')) == NULL) + return 1; + off = p - kv; + if ((kv = strdup(kv)) == NULL) + return -1; + + /* Skip trailing space before the equal sign. */ + for (p = kv + off; p > kv; --p) + if (!isspace(p[-1])) + break; + if (p == kv) { + free(kv); + return 1; + } + *p = '\0'; + + /* See if "key" is there by attempting to add it. */ + if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) + != NULL || lh_OPENSSL_STRING_error(addexts)) { + free(p != NULL ? p : kv); + return -1; + } + + return 0; +} diff --git a/apps/openssl/rsa.c b/apps/openssl/rsa.c new file mode 100644 index 0000000..5492cd6 --- /dev/null +++ b/apps/openssl/rsa.c @@ -0,0 +1,411 @@ +/* $OpenBSD: rsa.c,v 1.19 2023/07/23 11:39:29 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include + +#include "apps.h" +#include "progs.h" + +#include +#include +#include +#include +#include +#include +#include + +static struct { + int check; + const EVP_CIPHER *enc; + char *infile; + int informat; + int modulus; + int noout; + char *outfile; + int outformat; + char *passargin; + char *passargout; + int pubin; + int pubout; + int pvk_encr; + int text; +} cfg; + +static int +rsa_opt_cipher(int argc, char **argv, int *argsused) +{ + char *name = argv[0]; + + if (*name++ != '-') + return (1); + + if ((cfg.enc = EVP_get_cipherbyname(name)) == NULL) { + fprintf(stderr, "Invalid cipher '%s'\n", name); + return (1); + } + + *argsused = 1; + return (0); +} + +static const struct option rsa_options[] = { + { + .name = "check", + .desc = "Check consistency of RSA private key", + .type = OPTION_FLAG, + .opt.flag = &cfg.check, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inform", + .argname = "format", + .desc = "Input format (DER, NET or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.informat, + }, + { + .name = "modulus", + .desc = "Print the RSA key modulus", + .type = OPTION_FLAG, + .opt.flag = &cfg.modulus, + }, + { + .name = "noout", + .desc = "Do not print encoded version of the key", + .type = OPTION_FLAG, + .opt.flag = &cfg.noout, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "outform", + .argname = "format", + .desc = "Output format (DER, NET or PEM (default PEM))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.outformat, + }, + { + .name = "passin", + .argname = "src", + .desc = "Input file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "passout", + .argname = "src", + .desc = "Output file passphrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargout, + }, + { + .name = "pubin", + .desc = "Expect a public key (default private key)", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pubin, + }, + { + .name = "pubout", + .desc = "Output a public key (default private key)", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pubout, + }, + { + .name = "pvk-none", + .type = OPTION_VALUE, + .value = 0, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "pvk-strong", + .type = OPTION_VALUE, + .value = 2, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "pvk-weak", + .type = OPTION_VALUE, + .value = 1, + .opt.value = &cfg.pvk_encr, + }, + { + .name = "RSAPublicKey_in", + .type = OPTION_VALUE, + .value = 2, + .opt.value = &cfg.pubin, + }, + { + .name = "RSAPublicKey_out", + .type = OPTION_VALUE, + .value = 2, + .opt.value = &cfg.pubout, + }, + { + .name = "text", + .desc = "Print in plain text in addition to encoded", + .type = OPTION_FLAG, + .opt.flag = &cfg.text, + }, + { + .name = NULL, + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = rsa_opt_cipher, + }, + { NULL } +}; + +static void +rsa_usage(void) +{ + int n = 0; + + fprintf(stderr, + "usage: rsa [-ciphername] [-check] [-in file] " + "[-inform fmt]\n" + " [-modulus] [-noout] [-out file] [-outform fmt] " + "[-passin src]\n" + " [-passout src] [-pubin] [-pubout] [-text]\n\n"); + options_usage(rsa_options); + fprintf(stderr, "\n"); + + fprintf(stderr, "Valid ciphername values:\n\n"); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, &n); + fprintf(stderr, "\n"); +} + +int +rsa_main(int argc, char **argv) +{ + int ret = 1; + RSA *rsa = NULL; + int i; + BIO *out = NULL; + char *passin = NULL, *passout = NULL; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.pvk_encr = 2; + cfg.informat = FORMAT_PEM; + cfg.outformat = FORMAT_PEM; + + if (options_parse(argc, argv, rsa_options, NULL, NULL) != 0) { + rsa_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passargin, cfg.passargout, + &passin, &passout)) { + BIO_printf(bio_err, "Error getting passwords\n"); + goto end; + } + if (cfg.check && cfg.pubin) { + BIO_printf(bio_err, "Only private keys can be checked\n"); + goto end; + } + out = BIO_new(BIO_s_file()); + + { + EVP_PKEY *pkey; + + if (cfg.pubin) { + int tmpformat = -1; + if (cfg.pubin == 2) { + if (cfg.informat == FORMAT_PEM) + tmpformat = FORMAT_PEMRSA; + else if (cfg.informat == FORMAT_ASN1) + tmpformat = FORMAT_ASN1RSA; + } else + tmpformat = cfg.informat; + + pkey = load_pubkey(bio_err, cfg.infile, + tmpformat, 1, passin, "Public Key"); + } else + pkey = load_key(bio_err, cfg.infile, + cfg.informat, 1, passin, "Private Key"); + + if (pkey != NULL) + rsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + } + + if (rsa == NULL) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (BIO_write_filename(out, cfg.outfile) <= 0) { + perror(cfg.outfile); + goto end; + } + } + + if (cfg.text) + if (!RSA_print(out, rsa, 0)) { + perror(cfg.outfile); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.modulus) { + BIO_printf(out, "Modulus="); + BN_print(out, RSA_get0_n(rsa)); + BIO_printf(out, "\n"); + } + if (cfg.check) { + int r = RSA_check_key(rsa); + + if (r == 1) + BIO_printf(out, "RSA key ok\n"); + else if (r == 0) { + unsigned long err; + + while ((err = ERR_peek_error()) != 0 && + ERR_GET_LIB(err) == ERR_LIB_RSA && + ERR_GET_FUNC(err) == RSA_F_RSA_CHECK_KEY && + ERR_GET_REASON(err) != ERR_R_MALLOC_FAILURE) { + BIO_printf(out, "RSA key error: %s\n", + ERR_reason_error_string(err)); + ERR_get_error(); /* remove e from error + * stack */ + } + } + if (r == -1 || ERR_peek_error() != 0) { /* should happen only if + * r == -1 */ + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.noout) { + ret = 0; + goto end; + } + BIO_printf(bio_err, "writing RSA key\n"); + if (cfg.outformat == FORMAT_ASN1) { + if (cfg.pubout || cfg.pubin) { + if (cfg.pubout == 2) + i = i2d_RSAPublicKey_bio(out, rsa); + else + i = i2d_RSA_PUBKEY_bio(out, rsa); + } else + i = i2d_RSAPrivateKey_bio(out, rsa); + } else if (cfg.outformat == FORMAT_PEM) { + if (cfg.pubout || cfg.pubin) { + if (cfg.pubout == 2) + i = PEM_write_bio_RSAPublicKey(out, rsa); + else + i = PEM_write_bio_RSA_PUBKEY(out, rsa); + } else + i = PEM_write_bio_RSAPrivateKey(out, rsa, + cfg.enc, NULL, 0, NULL, passout); +#if !defined(OPENSSL_NO_DSA) && !defined(OPENSSL_NO_RC4) + } else if (cfg.outformat == FORMAT_MSBLOB || + cfg.outformat == FORMAT_PVK) { + EVP_PKEY *pk; + pk = EVP_PKEY_new(); + EVP_PKEY_set1_RSA(pk, rsa); + if (cfg.outformat == FORMAT_PVK) + i = i2b_PVK_bio(out, pk, cfg.pvk_encr, 0, + passout); + else if (cfg.pubin || cfg.pubout) + i = i2b_PublicKey_bio(out, pk); + else + i = i2b_PrivateKey_bio(out, pk); + EVP_PKEY_free(pk); +#endif + } else { + BIO_printf(bio_err, + "bad output format specified for outfile\n"); + goto end; + } + if (i <= 0) { + BIO_printf(bio_err, "unable to write key\n"); + ERR_print_errors(bio_err); + } else + ret = 0; + + end: + BIO_free_all(out); + RSA_free(rsa); + free(passin); + free(passout); + + return (ret); +} diff --git a/apps/openssl/rsautl.c b/apps/openssl/rsautl.c new file mode 100644 index 0000000..6d8069c --- /dev/null +++ b/apps/openssl/rsautl.c @@ -0,0 +1,402 @@ +/* $OpenBSD: rsautl.c,v 1.24 2023/07/23 11:39:29 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include + +#include "apps.h" + +#include +#include +#include + +#define RSA_SIGN 1 +#define RSA_VERIFY 2 +#define RSA_ENCRYPT 3 +#define RSA_DECRYPT 4 + +#define KEY_PRIVKEY 1 +#define KEY_PUBKEY 2 +#define KEY_CERT 3 + +static struct { + int asn1parse; + int hexdump; + char *infile; + char *keyfile; + int keyform; + int key_type; + char *outfile; + int pad; + char *passargin; + int rev; + int rsa_mode; +} cfg; + +static const struct option rsautl_options[] = { + { + .name = "asn1parse", + .desc = "ASN.1 parse the output data", + .type = OPTION_FLAG, + .opt.flag = &cfg.asn1parse, + }, + { + .name = "certin", + .desc = "Input is a certificate containing an RSA public key", + .type = OPTION_VALUE, + .value = KEY_CERT, + .opt.value = &cfg.key_type, + }, + { + .name = "decrypt", + .desc = "Decrypt the input data using RSA private key", + .type = OPTION_VALUE, + .value = RSA_DECRYPT, + .opt.value = &cfg.rsa_mode, + }, + { + .name = "encrypt", + .desc = "Encrypt the input data using RSA public key", + .type = OPTION_VALUE, + .value = RSA_ENCRYPT, + .opt.value = &cfg.rsa_mode, + }, + { + .name = "hexdump", + .desc = "Hex dump the output data", + .type = OPTION_FLAG, + .opt.flag = &cfg.hexdump, + }, + { + .name = "in", + .argname = "file", + .desc = "Input file (default stdin)", + .type = OPTION_ARG, + .opt.arg = &cfg.infile, + }, + { + .name = "inkey", + .argname = "file", + .desc = "Input key file", + .type = OPTION_ARG, + .opt.arg = &cfg.keyfile, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Input key format (DER, TXT or PEM (default))", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.keyform, + }, + { + .name = "oaep", + .desc = "Use PKCS#1 OAEP padding", + .type = OPTION_VALUE, + .value = RSA_PKCS1_OAEP_PADDING, + .opt.value = &cfg.pad, + }, + { + .name = "out", + .argname = "file", + .desc = "Output file (default stdout)", + .type = OPTION_ARG, + .opt.arg = &cfg.outfile, + }, + { + .name = "passin", + .argname = "arg", + .desc = "Key password source", + .type = OPTION_ARG, + .opt.arg = &cfg.passargin, + }, + { + .name = "pkcs", + .desc = "Use PKCS#1 v1.5 padding (default)", + .type = OPTION_VALUE, + .value = RSA_PKCS1_PADDING, + .opt.value = &cfg.pad, + }, + { + .name = "pubin", + .desc = "Input is an RSA public key", + .type = OPTION_VALUE, + .value = KEY_PUBKEY, + .opt.value = &cfg.key_type, + }, + { + .name = "raw", + .desc = "Use no padding", + .type = OPTION_VALUE, + .value = RSA_NO_PADDING, + .opt.value = &cfg.pad, + }, + { + .name = "rev", + .desc = "Reverse the input data", + .type = OPTION_FLAG, + .opt.flag = &cfg.rev, + }, + { + .name = "sign", + .desc = "Sign the input data using RSA private key", + .type = OPTION_VALUE, + .value = RSA_SIGN, + .opt.value = &cfg.rsa_mode, + }, + { + .name = "verify", + .desc = "Verify the input data using RSA public key", + .type = OPTION_VALUE, + .value = RSA_VERIFY, + .opt.value = &cfg.rsa_mode, + }, + { + .name = "x931", + .desc = "Use ANSI X9.31 padding", + .type = OPTION_VALUE, + .value = RSA_X931_PADDING, + .opt.value = &cfg.pad, + }, + + {NULL}, +}; + +static void +rsautl_usage(void) +{ + fprintf(stderr, + "usage: rsautl [-asn1parse] [-certin] [-decrypt] [-encrypt] " + "[-hexdump]\n" + " [-in file] [-inkey file] [-keyform der | pem]\n" + " [-oaep | -pkcs | -raw | -x931] [-out file] [-passin arg]\n" + " [-pubin] [-rev] [-sign] [-verify]\n\n"); + + options_usage(rsautl_options); +} + +int +rsautl_main(int argc, char **argv) +{ + BIO *in = NULL, *out = NULL; + X509 *x; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; + unsigned char *rsa_in = NULL, *rsa_out = NULL; + char *passin = NULL; + int rsa_inlen, rsa_outlen = 0; + int need_priv = 0; + int keysize; + int ret = 1; + + if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.keyform = FORMAT_PEM; + cfg.key_type = KEY_PRIVKEY; + cfg.pad = RSA_PKCS1_PADDING; + cfg.rsa_mode = RSA_VERIFY; + + if (options_parse(argc, argv, rsautl_options, NULL, NULL) != 0) { + rsautl_usage(); + return (1); + } + + if (cfg.rsa_mode == RSA_SIGN || + cfg.rsa_mode == RSA_DECRYPT) + need_priv = 1; + + if (need_priv && cfg.key_type != KEY_PRIVKEY) { + BIO_printf(bio_err, "A private key is needed for this operation\n"); + goto end; + } + if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + + switch (cfg.key_type) { + case KEY_PRIVKEY: + pkey = load_key(bio_err, cfg.keyfile, + cfg.keyform, 0, passin, "Private Key"); + break; + + case KEY_PUBKEY: + pkey = load_pubkey(bio_err, cfg.keyfile, + cfg.keyform, 0, NULL, "Public Key"); + break; + + case KEY_CERT: + x = load_cert(bio_err, cfg.keyfile, + cfg.keyform, NULL, "Certificate"); + if (x) { + pkey = X509_get_pubkey(x); + X509_free(x); + } + break; + } + + if (!pkey) + goto end; + + rsa = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + + if (!rsa) { + BIO_printf(bio_err, "Error getting RSA key\n"); + ERR_print_errors(bio_err); + goto end; + } + if (cfg.infile) { + if (!(in = BIO_new_file(cfg.infile, "rb"))) { + BIO_printf(bio_err, "Error Reading Input File\n"); + ERR_print_errors(bio_err); + goto end; + } + } else + in = BIO_new_fp(stdin, BIO_NOCLOSE); + + if (cfg.outfile) { + if (!(out = BIO_new_file(cfg.outfile, "wb"))) { + BIO_printf(bio_err, "Error Reading Output File\n"); + ERR_print_errors(bio_err); + goto end; + } + } else { + out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + + keysize = RSA_size(rsa); + + rsa_in = reallocarray(NULL, keysize, 2); + if (rsa_in == NULL) { + BIO_printf(bio_err, "Error allocating memory for input data\n"); + exit(1); + } + rsa_out = malloc(keysize); + if (rsa_out == NULL) { + BIO_printf(bio_err, "Error allocating memory for output data\n"); + exit(1); + } + + /* Read the input data */ + rsa_inlen = BIO_read(in, rsa_in, keysize * 2); + if (rsa_inlen <= 0) { + BIO_printf(bio_err, "Error reading input Data\n"); + exit(1); + } + if (cfg.rev) { + int i; + unsigned char ctmp; + for (i = 0; i < rsa_inlen / 2; i++) { + ctmp = rsa_in[i]; + rsa_in[i] = rsa_in[rsa_inlen - 1 - i]; + rsa_in[rsa_inlen - 1 - i] = ctmp; + } + } + + switch (cfg.rsa_mode) { + case RSA_VERIFY: + rsa_outlen = RSA_public_decrypt(rsa_inlen, rsa_in, rsa_out, + rsa, cfg.pad); + break; + + case RSA_SIGN: + rsa_outlen = RSA_private_encrypt(rsa_inlen, rsa_in, rsa_out, + rsa, cfg.pad); + break; + + case RSA_ENCRYPT: + rsa_outlen = RSA_public_encrypt(rsa_inlen, rsa_in, rsa_out, + rsa, cfg.pad); + break; + + case RSA_DECRYPT: + rsa_outlen = RSA_private_decrypt(rsa_inlen, rsa_in, rsa_out, + rsa, cfg.pad); + break; + } + + if (rsa_outlen <= 0) { + BIO_printf(bio_err, "RSA operation error\n"); + ERR_print_errors(bio_err); + goto end; + } + ret = 0; + if (cfg.asn1parse) { + if (!ASN1_parse_dump(out, rsa_out, rsa_outlen, 1, -1)) { + ERR_print_errors(bio_err); + } + } else if (cfg.hexdump) + BIO_dump(out, (char *) rsa_out, rsa_outlen); + else + BIO_write(out, rsa_out, rsa_outlen); + + end: + RSA_free(rsa); + BIO_free(in); + BIO_free_all(out); + free(rsa_in); + free(rsa_out); + free(passin); + + return ret; +} diff --git a/apps/openssl/s_apps.h b/apps/openssl/s_apps.h new file mode 100644 index 0000000..a73c2eb --- /dev/null +++ b/apps/openssl/s_apps.h @@ -0,0 +1,151 @@ +/* $OpenBSD: s_apps.h,v 1.7 2021/12/06 11:06:58 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#include +#include + +#define PORT 4433 +#define PORT_STR "4433" +#define PROTOCOL "tcp" + +extern int verify_depth; +extern int verify_return_error; + +int do_server(int port, int type, int *ret, + int (*cb)(int s, unsigned char *context), + unsigned char *context, int naccept); +#ifdef HEADER_X509_H +int verify_callback(int ok, X509_STORE_CTX *ctx); +#endif +#ifdef HEADER_SSL_H +int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file); +int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key); +#endif +int ssl_print_tmp_key(BIO *out, SSL *s); +int init_client(int *sock, char *server, char *port, int type, int af); +int should_retry(int i); +int extract_port(char *str, short *port_ptr); +int extract_host_port(char *str, char **host_ptr, unsigned char *ip, char **p); + +long bio_dump_callback(BIO *bio, int cmd, const char *argp, int argi, + long argl, long ret); + +#ifdef HEADER_SSL_H +void apps_ssl_info_callback(const SSL *s, int where, int ret); +void msg_cb(int write_p, int version, int content_type, const void *buf, + size_t len, SSL *ssl, void *arg); +void tlsext_cb(SSL *s, int client_server, int type, unsigned char *data, + int len, void *arg); +#endif + +int generate_cookie_callback(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); +int verify_cookie_callback(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); diff --git a/apps/openssl/s_cb.c b/apps/openssl/s_cb.c new file mode 100644 index 0000000..d503b8c --- /dev/null +++ b/apps/openssl/s_cb.c @@ -0,0 +1,932 @@ +/* $OpenBSD: s_cb.c,v 1.21 2023/04/14 15:27:13 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include + +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include + +#include "s_apps.h" + +#define COOKIE_SECRET_LENGTH 16 + +int verify_depth = 0; +int verify_return_error = 0; +unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; +int cookie_initialized = 0; + +int +verify_callback(int ok, X509_STORE_CTX * ctx) +{ + X509 *err_cert; + int err, depth; + + err_cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + depth = X509_STORE_CTX_get_error_depth(ctx); + + BIO_printf(bio_err, "depth=%d ", depth); + if (err_cert) { + X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert), + 0, XN_FLAG_ONELINE); + BIO_puts(bio_err, "\n"); + } else + BIO_puts(bio_err, "\n"); + if (!ok) { + BIO_printf(bio_err, "verify error:num=%d:%s\n", err, + X509_verify_cert_error_string(err)); + if (verify_depth >= depth) { + if (!verify_return_error) + ok = 1; + } else { + ok = 0; + } + } + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + BIO_puts(bio_err, "issuer= "); + if (err_cert == NULL) + BIO_puts(bio_err, ""); + else + X509_NAME_print_ex(bio_err, + X509_get_issuer_name(err_cert), 0, XN_FLAG_ONELINE); + BIO_puts(bio_err, "\n"); + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + BIO_printf(bio_err, "notBefore="); + if (err_cert == NULL) + BIO_printf(bio_err, " "); + else + ASN1_TIME_print(bio_err, X509_get_notBefore(err_cert)); + BIO_printf(bio_err, "\n"); + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + BIO_printf(bio_err, "notAfter="); + if (err_cert == NULL) + BIO_printf(bio_err, " "); + else + ASN1_TIME_print(bio_err, X509_get_notAfter(err_cert)); + BIO_printf(bio_err, "\n"); + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + break; + } + + BIO_printf(bio_err, "verify return:%d\n", ok); + return (ok); +} + +int +set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file) +{ + if (cert_file == NULL) + return 1; + + if (key_file == NULL) + key_file = cert_file; + + if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, + "unable to get certificate from '%s'\n", cert_file); + ERR_print_errors(bio_err); + return 0; + } + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { + BIO_printf(bio_err, "unable to get private key from '%s'\n", + key_file); + ERR_print_errors(bio_err); + return 0; + } + + /* Now we know that a key and cert have been set against the context. */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + + return 1; +} + +int +set_cert_key_stuff(SSL_CTX * ctx, X509 * cert, EVP_PKEY * key) +{ + if (cert == NULL) + return 1; + if (SSL_CTX_use_certificate(ctx, cert) <= 0) { + BIO_printf(bio_err, "error setting certificate\n"); + ERR_print_errors(bio_err); + return 0; + } + if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) { + BIO_printf(bio_err, "error setting private key\n"); + ERR_print_errors(bio_err); + return 0; + } + /* + * Now we know that a key and cert have been set against the SSL + * context + */ + if (!SSL_CTX_check_private_key(ctx)) { + BIO_printf(bio_err, + "Private key does not match the certificate public key\n"); + return 0; + } + return 1; +} + +int +ssl_print_tmp_key(BIO *out, SSL *s) +{ + const char *cname; + EVP_PKEY *pkey; + EC_KEY *ec; + const EC_GROUP *group; + int nid; + + if (!SSL_get_server_tmp_key(s, &pkey)) + return 0; + + BIO_puts(out, "Server Temp Key: "); + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_DH: + BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(pkey)); + break; + + case EVP_PKEY_EC: + if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) + goto err; + if ((group = EC_KEY_get0_group(ec)) == NULL) + goto err; + + nid = EC_GROUP_get_curve_name(group); + + if ((cname = EC_curve_nid2nist(nid)) == NULL) + cname = OBJ_nid2sn(nid); + + BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(pkey)); + break; + + default: + BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(pkey)), + EVP_PKEY_bits(pkey)); + } + + err: + EVP_PKEY_free(pkey); + return 1; +} + +long +bio_dump_callback(BIO * bio, int cmd, const char *argp, + int argi, long argl, long ret) +{ + BIO *out; + + out = (BIO *) BIO_get_callback_arg(bio); + if (out == NULL) + return (ret); + + if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { + BIO_printf(out, + "read from %p [%p] (%lu bytes => %ld (0x%lX))\n", + (void *) bio, argp, (unsigned long) argi, ret, ret); + BIO_dump(out, argp, (int) ret); + return (ret); + } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { + BIO_printf(out, + "write to %p [%p] (%lu bytes => %ld (0x%lX))\n", + (void *) bio, argp, (unsigned long) argi, ret, ret); + BIO_dump(out, argp, (int) ret); + } + return (ret); +} + +void +apps_ssl_info_callback(const SSL * s, int where, int ret) +{ + const char *str; + int w; + + w = where & ~SSL_ST_MASK; + + if (w & SSL_ST_CONNECT) + str = "SSL_connect"; + else if (w & SSL_ST_ACCEPT) + str = "SSL_accept"; + else + str = "undefined"; + + if (where & SSL_CB_LOOP) { + BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s)); + } else if (where & SSL_CB_ALERT) { + str = (where & SSL_CB_READ) ? "read" : "write"; + BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n", str, + SSL_alert_type_string_long(ret), + SSL_alert_desc_string_long(ret)); + } else if (where & SSL_CB_EXIT) { + if (ret == 0) + BIO_printf(bio_err, "%s:failed in %s\n", + str, SSL_state_string_long(s)); + else if (ret < 0) { + BIO_printf(bio_err, "%s:error in %s\n", + str, SSL_state_string_long(s)); + } + } +} + + +void +msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL * ssl, void *arg) +{ + BIO *bio = arg; + const char *str_write_p, *str_version, *str_content_type = "", + *str_details1 = "", *str_details2 = ""; + + str_write_p = write_p ? ">>>" : "<<<"; + + /* XXX convert to using ssl_get_version */ + switch (version) { + case SSL2_VERSION: + str_version = "SSL 2.0"; + break; + case SSL3_VERSION: + str_version = "SSL 3.0 "; + break; + case TLS1_VERSION: + str_version = "TLS 1.0 "; + break; + case TLS1_1_VERSION: + str_version = "TLS 1.1 "; + break; + case TLS1_2_VERSION: + str_version = "TLS 1.2 "; + break; + case TLS1_3_VERSION: + str_version = "TLS 1.3 "; + break; + case DTLS1_VERSION: + str_version = "DTLS 1.0 "; + break; + case DTLS1_2_VERSION: + str_version = "DTLS 1.2 "; + break; + default: + str_version = "???"; + } + + if (version == SSL2_VERSION) { + str_details1 = "???"; + + if (len > 0) { + /* XXX magic numbers */ + switch (((const unsigned char *) buf)[0]) { + case 0: + str_details1 = ", ERROR:"; + str_details2 = " ???"; + if (len >= 3) { + unsigned err = (((const unsigned char *) buf)[1] << 8) + ((const unsigned char *) buf)[2]; + + switch (err) { + case 0x0001: + str_details2 = " NO-CIPHER-ERROR"; + break; + case 0x0002: + str_details2 = " NO-CERTIFICATE-ERROR"; + break; + case 0x0004: + str_details2 = " BAD-CERTIFICATE-ERROR"; + break; + case 0x0006: + str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR"; + break; + } + } + break; + case 1: + str_details1 = ", CLIENT-HELLO"; + break; + case 2: + str_details1 = ", CLIENT-MASTER-KEY"; + break; + case 3: + str_details1 = ", CLIENT-FINISHED"; + break; + case 4: + str_details1 = ", SERVER-HELLO"; + break; + case 5: + str_details1 = ", SERVER-VERIFY"; + break; + case 6: + str_details1 = ", SERVER-FINISHED"; + break; + case 7: + str_details1 = ", REQUEST-CERTIFICATE"; + break; + case 8: + str_details1 = ", CLIENT-CERTIFICATE"; + break; + } + } + } + if (version == SSL3_VERSION || version == TLS1_VERSION || + version == TLS1_1_VERSION || version == TLS1_2_VERSION || + version == TLS1_3_VERSION || version == DTLS1_VERSION || + version == DTLS1_2_VERSION) { + /* XXX magic numbers are in ssl3.h */ + switch (content_type) { + case 20: + str_content_type = "ChangeCipherSpec"; + break; + case 21: + str_content_type = "Alert"; + break; + case 22: + str_content_type = "Handshake"; + break; + } + + if (content_type == 21) { /* Alert */ + str_details1 = ", ???"; + + if (len == 2) { + switch (((const unsigned char *) buf)[0]) { + case 1: + str_details1 = ", warning"; + break; + case 2: + str_details1 = ", fatal"; + break; + } + + str_details2 = " ???"; + switch (((const unsigned char *) buf)[1]) { + case 0: + str_details2 = " close_notify"; + break; + case 10: + str_details2 = " unexpected_message"; + break; + case 20: + str_details2 = " bad_record_mac"; + break; + case 21: + str_details2 = " decryption_failed"; + break; + case 22: + str_details2 = " record_overflow"; + break; + case 30: + str_details2 = " decompression_failure"; + break; + case 40: + str_details2 = " handshake_failure"; + break; + case 42: + str_details2 = " bad_certificate"; + break; + case 43: + str_details2 = " unsupported_certificate"; + break; + case 44: + str_details2 = " certificate_revoked"; + break; + case 45: + str_details2 = " certificate_expired"; + break; + case 46: + str_details2 = " certificate_unknown"; + break; + case 47: + str_details2 = " illegal_parameter"; + break; + case 48: + str_details2 = " unknown_ca"; + break; + case 49: + str_details2 = " access_denied"; + break; + case 50: + str_details2 = " decode_error"; + break; + case 51: + str_details2 = " decrypt_error"; + break; + case 60: + str_details2 = " export_restriction"; + break; + case 70: + str_details2 = " protocol_version"; + break; + case 71: + str_details2 = " insufficient_security"; + break; + case 80: + str_details2 = " internal_error"; + break; + case 90: + str_details2 = " user_canceled"; + break; + case 100: + str_details2 = " no_renegotiation"; + break; + case 110: + str_details2 = " unsupported_extension"; + break; + case 111: + str_details2 = " certificate_unobtainable"; + break; + case 112: + str_details2 = " unrecognized_name"; + break; + case 113: + str_details2 = " bad_certificate_status_response"; + break; + case 114: + str_details2 = " bad_certificate_hash_value"; + break; + case 115: + str_details2 = " unknown_psk_identity"; + break; + } + } + } + if (content_type == 22) { /* Handshake */ + str_details1 = "???"; + + if (len > 0) { + switch (((const unsigned char *) buf)[0]) { + case 0: + str_details1 = ", HelloRequest"; + break; + case 1: + str_details1 = ", ClientHello"; + break; + case 2: + str_details1 = ", ServerHello"; + break; + case 3: + str_details1 = ", HelloVerifyRequest"; + break; + case 4: + str_details1 = ", NewSessionTicket"; + break; + case 5: + str_details1 = ", EndOfEarlyData"; + break; + case 8: + str_details1 = ", EncryptedExtensions"; + break; + case 11: + str_details1 = ", Certificate"; + break; + case 12: + str_details1 = ", ServerKeyExchange"; + break; + case 13: + str_details1 = ", CertificateRequest"; + break; + case 14: + str_details1 = ", ServerHelloDone"; + break; + case 15: + str_details1 = ", CertificateVerify"; + break; + case 16: + str_details1 = ", ClientKeyExchange"; + break; + case 20: + str_details1 = ", Finished"; + break; + case 24: + str_details1 = ", KeyUpdate"; + break; + } + } + } + } + BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, + str_version, str_content_type, (unsigned long) len, + str_details1, str_details2); + + if (len > 0) { + size_t num, i; + + BIO_printf(bio, " "); + num = len; + + for (i = 0; i < num; i++) { + if (i % 16 == 0 && i > 0) + BIO_printf(bio, "\n "); + BIO_printf(bio, " %02x", + ((const unsigned char *) buf)[i]); + } + if (i < len) + BIO_printf(bio, " ..."); + BIO_printf(bio, "\n"); + } + (void) BIO_flush(bio); +} + +void +tlsext_cb(SSL * s, int client_server, int type, unsigned char *data, int len, + void *arg) +{ + BIO *bio = arg; + char *extname; + + switch (type) { + case TLSEXT_TYPE_server_name: + extname = "server name"; + break; + + case TLSEXT_TYPE_max_fragment_length: + extname = "max fragment length"; + break; + + case TLSEXT_TYPE_client_certificate_url: + extname = "client certificate URL"; + break; + + case TLSEXT_TYPE_trusted_ca_keys: + extname = "trusted CA keys"; + break; + + case TLSEXT_TYPE_truncated_hmac: + extname = "truncated HMAC"; + break; + + case TLSEXT_TYPE_status_request: + extname = "status request"; + break; + + case TLSEXT_TYPE_user_mapping: + extname = "user mapping"; + break; + + case TLSEXT_TYPE_client_authz: + extname = "client authz"; + break; + + case TLSEXT_TYPE_server_authz: + extname = "server authz"; + break; + + case TLSEXT_TYPE_cert_type: + extname = "cert type"; + break; + + case TLSEXT_TYPE_supported_groups: + extname = "supported groups"; + break; + + case TLSEXT_TYPE_ec_point_formats: + extname = "EC point formats"; + break; + + case TLSEXT_TYPE_srp: + extname = "SRP"; + break; + + case TLSEXT_TYPE_signature_algorithms: + extname = "signature algorithms"; + break; + + case TLSEXT_TYPE_use_srtp: + extname = "use SRTP"; + break; + + case TLSEXT_TYPE_heartbeat: + extname = "heartbeat"; + break; + + case TLSEXT_TYPE_application_layer_protocol_negotiation: + extname = "application layer protocol negotiation"; + break; + + case TLSEXT_TYPE_padding: + extname = "TLS padding"; + break; + + case TLSEXT_TYPE_session_ticket: + extname = "session ticket"; + break; + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) + case TLSEXT_TYPE_pre_shared_key: + extname = "pre shared key"; + break; + + case TLSEXT_TYPE_early_data: + extname = "early data"; + break; + + case TLSEXT_TYPE_supported_versions: + extname = "supported versions"; + break; + + case TLSEXT_TYPE_cookie: + extname = "cookie"; + break; + + case TLSEXT_TYPE_psk_key_exchange_modes: + extname = "PSK key exchange modes"; + break; + + case TLSEXT_TYPE_certificate_authorities: + extname = "certificate authorities"; + break; + + case TLSEXT_TYPE_oid_filters: + extname = "OID filters"; + break; + + case TLSEXT_TYPE_post_handshake_auth: + extname = "post handshake auth"; + break; + + case TLSEXT_TYPE_signature_algorithms_cert: + extname = "signature algorithms cert"; + break; + + case TLSEXT_TYPE_key_share: + extname = "key share"; + break; +#endif + + case TLSEXT_TYPE_renegotiate: + extname = "renegotiation info"; + break; + + default: + extname = "unknown"; + break; + + } + + BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n", + client_server ? "server" : "client", extname, type, len); + BIO_dump(bio, (char *) data, len); + (void) BIO_flush(bio); +} + +int +generate_cookie_callback(SSL * ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length, resultlength; + union { + struct sockaddr sa; + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } peer; + + /* Initialize a random secret */ + if (!cookie_initialized) { + arc4random_buf(cookie_secret, COOKIE_SECRET_LENGTH); + cookie_initialized = 1; + } + /* Read peer information */ + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + /* Create buffer with peer's address and port */ + length = 0; + switch (peer.sa.sa_family) { + case AF_INET: + length += sizeof(struct in_addr); + length += sizeof(peer.s4.sin_port); + break; + case AF_INET6: + length += sizeof(struct in6_addr); + length += sizeof(peer.s6.sin6_port); + break; + default: + OPENSSL_assert(0); + break; + } + buffer = malloc(length); + + if (buffer == NULL) { + BIO_printf(bio_err, "out of memory\n"); + return 0; + } + switch (peer.sa.sa_family) { + case AF_INET: + memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); + memcpy(buffer + sizeof(peer.s4.sin_port), + &peer.s4.sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); + memcpy(buffer + sizeof(peer.s6.sin6_port), + &peer.s6.sin6_addr, sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + /* Calculate HMAC of buffer using the secret */ + HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, + buffer, length, result, &resultlength); + free(buffer); + + memcpy(cookie, result, resultlength); + *cookie_len = resultlength; + + return 1; +} + +int +verify_cookie_callback(SSL * ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + unsigned char *buffer, result[EVP_MAX_MD_SIZE]; + unsigned int length, resultlength; + union { + struct sockaddr sa; + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } peer; + + /* If secret isn't initialized yet, the cookie can't be valid */ + if (!cookie_initialized) + return 0; + + /* Read peer information */ + (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer); + + /* Create buffer with peer's address and port */ + length = 0; + switch (peer.sa.sa_family) { + case AF_INET: + length += sizeof(struct in_addr); + length += sizeof(peer.s4.sin_port); + break; + case AF_INET6: + length += sizeof(struct in6_addr); + length += sizeof(peer.s6.sin6_port); + break; + default: + OPENSSL_assert(0); + break; + } + buffer = malloc(length); + + if (buffer == NULL) { + BIO_printf(bio_err, "out of memory\n"); + return 0; + } + switch (peer.sa.sa_family) { + case AF_INET: + memcpy(buffer, &peer.s4.sin_port, sizeof(peer.s4.sin_port)); + memcpy(buffer + sizeof(peer.s4.sin_port), + &peer.s4.sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + memcpy(buffer, &peer.s6.sin6_port, sizeof(peer.s6.sin6_port)); + memcpy(buffer + sizeof(peer.s6.sin6_port), + &peer.s6.sin6_addr, sizeof(struct in6_addr)); + break; + default: + OPENSSL_assert(0); + break; + } + + /* Calculate HMAC of buffer using the secret */ + if (HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH, + buffer, length, result, &resultlength) == NULL) { + free(buffer); + return 0; + } + + free(buffer); + + if (cookie_len == resultlength && + memcmp(result, cookie, resultlength) == 0) + return 1; + + return 0; +} diff --git a/apps/openssl/s_client.c b/apps/openssl/s_client.c new file mode 100644 index 0000000..e5a6b00 --- /dev/null +++ b/apps/openssl/s_client.c @@ -0,0 +1,1836 @@ +/* $OpenBSD: s_client.c,v 1.62 2023/07/03 08:03:56 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include + +#include "s_apps.h" +#include "timeouts.h" + +/*#define SSL_HOST_NAME "www.netscape.com" */ +/*#define SSL_HOST_NAME "193.118.187.102" */ +#define SSL_HOST_NAME "localhost" + + /*#define TEST_CERT "client.pem" *//* no default cert. */ + +#define BUFSIZZ 1024*8 + +static void sc_usage(void); +static void print_stuff(BIO *berr, SSL *con, int full); +static int ocsp_resp_cb(SSL *s, void *arg); +static int ssl_servername_cb(SSL *s, int *ad, void *arg); + +enum { + PROTO_OFF = 0, + PROTO_SMTP, + PROTO_LMTP, + PROTO_POP3, + PROTO_IMAP, + PROTO_FTP, + PROTO_XMPP, +}; + +/* This is a context that we pass to callbacks */ +typedef struct tlsextctx_st { + BIO *biodebug; + int ack; +} tlsextctx; + +static struct { + int af; + char *alpn_in; + int bugs; + char *CAfile; + char *CApath; + char *cert_file; + int cert_format; + char *cipher; + unsigned int clr; + char *connect; + int crlf; + int debug; + int enable_timeouts; + const char *errstr; + char *groups_in; + char *host; + int ign_eof; + char *key_file; + int key_format; + char *keymatexportlabel; + int keymatexportlen; + uint16_t max_version; + uint16_t min_version; + const SSL_METHOD *meth; + int msg; + int nbio; + int nbio_test; + int no_servername; + char *npn_in; + unsigned int off; + char *passarg; + int pause; + int peekaboo; + char *port; + int prexit; + char *proxy; + int quiet; + int reconnect; + char *servername; + char *sess_in; + char *sess_out; + int showcerts; + int socket_type; + long socket_mtu; +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles; +#endif + int starttls_proto; + int state; + int status_req; + int tlsextdebug; + int verify; + X509_VERIFY_PARAM *vpm; + char *xmpphost; +} cfg; + +static int +s_client_opt_keymatexportlen(char *arg) +{ + cfg.keymatexportlen = strtonum(arg, 1, INT_MAX, + &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + return (0); +} + +#ifndef OPENSSL_NO_DTLS +static int +s_client_opt_mtu(char *arg) +{ + cfg.socket_mtu = strtonum(arg, 0, LONG_MAX, + &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + return (0); +} +#endif + +static int +s_client_opt_port(char *arg) +{ + if (*arg == '\0') + return (1); + + cfg.port = arg; + return (0); +} + +#ifndef OPENSSL_NO_DTLS +static int +s_client_opt_protocol_version_dtls(void) +{ + cfg.meth = DTLS_client_method(); + cfg.socket_type = SOCK_DGRAM; + return (0); +} +#endif + +#ifndef OPENSSL_NO_DTLS1_2 +static int +s_client_opt_protocol_version_dtls1_2(void) +{ + cfg.meth = DTLS_client_method(); + cfg.min_version = DTLS1_2_VERSION; + cfg.max_version = DTLS1_2_VERSION; + cfg.socket_type = SOCK_DGRAM; + return (0); +} +#endif + +static int +s_client_opt_protocol_version_tls1_2(void) +{ + cfg.min_version = TLS1_2_VERSION; + cfg.max_version = TLS1_2_VERSION; + return (0); +} + +static int +s_client_opt_protocol_version_tls1_3(void) +{ + cfg.min_version = TLS1_3_VERSION; + cfg.max_version = TLS1_3_VERSION; + return (0); +} + +static int +s_client_opt_quiet(void) +{ + cfg.quiet = 1; + cfg.ign_eof = 1; + return (0); +} + +static int +s_client_opt_starttls(char *arg) +{ + if (strcmp(arg, "smtp") == 0) + cfg.starttls_proto = PROTO_SMTP; + else if (strcmp(arg, "lmtp") == 0) + cfg.starttls_proto = PROTO_LMTP; + else if (strcmp(arg, "pop3") == 0) + cfg.starttls_proto = PROTO_POP3; + else if (strcmp(arg, "imap") == 0) + cfg.starttls_proto = PROTO_IMAP; + else if (strcmp(arg, "ftp") == 0) + cfg.starttls_proto = PROTO_FTP; + else if (strcmp(arg, "xmpp") == 0) + cfg.starttls_proto = PROTO_XMPP; + else + return (1); + return (0); +} + +static int +s_client_opt_verify(char *arg) +{ + cfg.verify = SSL_VERIFY_PEER; + + verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + BIO_printf(bio_err, "verify depth is %d\n", verify_depth); + return (0); +} + +static int +s_client_opt_verify_param(int argc, char **argv, int *argsused) +{ + char **pargs = argv; + int pargc = argc; + int badarg = 0; + + if (!args_verify(&pargs, &pargc, &badarg, bio_err, + &cfg.vpm)) { + BIO_printf(bio_err, "unknown option %s\n", *argv); + return (1); + } + if (badarg) + return (1); + + *argsused = argc - pargc; + return (0); +} + +static const struct option s_client_options[] = { + { + .name = "4", + .desc = "Use IPv4 only", + .type = OPTION_VALUE, + .opt.value = &cfg.af, + .value = AF_INET, + }, + { + .name = "6", + .desc = "Use IPv6 only", + .type = OPTION_VALUE, + .opt.value = &cfg.af, + .value = AF_INET6, + }, + { + .name = "alpn", + .argname = "protocols", + .desc = "Set the advertised protocols for ALPN" + " (comma-separated list)", + .type = OPTION_ARG, + .opt.arg = &cfg.alpn_in, + }, + { + .name = "bugs", + .desc = "Enable various workarounds for buggy implementations", + .type = OPTION_FLAG, + .opt.flag = &cfg.bugs, + }, + { + .name = "CAfile", + .argname = "file", + .desc = "PEM format file of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CAfile, + }, + { + .name = "CApath", + .argname = "directory", + .desc = "PEM format directory of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CApath, + }, + { + .name = "cert", + .argname = "file", + .desc = "Certificate file to use, PEM format assumed", + .type = OPTION_ARG, + .opt.arg = &cfg.cert_file, + }, + { + .name = "certform", + .argname = "fmt", + .desc = "Certificate format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.cert_format, + }, + { + .name = "cipher", + .argname = "cipherlist", + .desc = "Preferred cipher to use (see 'openssl ciphers')", + .type = OPTION_ARG, + .opt.arg = &cfg.cipher, + }, + { + .name = "connect", + .argname = "host:port", + .desc = "Who to connect to (default is localhost:4433)", + .type = OPTION_ARG, + .opt.arg = &cfg.connect, + }, + { + .name = "crlf", + .desc = "Convert LF from terminal into CRLF", + .type = OPTION_FLAG, + .opt.flag = &cfg.crlf, + }, + { + .name = "debug", + .desc = "Print extensive debugging information", + .type = OPTION_FLAG, + .opt.flag = &cfg.debug, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "dtls", + .desc = "Use any version of DTLS", + .type = OPTION_FUNC, + .opt.func = s_client_opt_protocol_version_dtls, + }, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + { + .name = "dtls1_2", + .desc = "Just use DTLSv1.2", + .type = OPTION_FUNC, + .opt.func = s_client_opt_protocol_version_dtls1_2, + }, +#endif + { + .name = "groups", + .argname = "list", + .desc = "Specify EC groups (colon-separated list)", + .type = OPTION_ARG, + .opt.arg = &cfg.groups_in, + }, + { + .name = "host", + .argname = "host", + .desc = "Use -connect instead", + .type = OPTION_ARG, + .opt.arg = &cfg.host, + }, + { + .name = "ign_eof", + .desc = "Ignore input EOF (default when -quiet)", + .type = OPTION_VALUE, + .opt.value = &cfg.ign_eof, + .value = 1, + }, + { + .name = "key", + .argname = "file", + .desc = "Private key file to use, if not, -cert file is used", + .type = OPTION_ARG, + .opt.arg = &cfg.key_file, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Key format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.key_format, + }, + { + .name = "keymatexport", + .argname = "label", + .desc = "Export keying material using label", + .type = OPTION_ARG, + .opt.arg = &cfg.keymatexportlabel, + }, + { + .name = "keymatexportlen", + .argname = "len", + .desc = "Export len bytes of keying material (default 20)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_client_opt_keymatexportlen, + }, + { + .name = "legacy_renegotiation", + .type = OPTION_DISCARD, + }, + { + .name = "legacy_server_connect", + .desc = "Allow initial connection to servers that don't support RI", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_LEGACY_SERVER_CONNECT, + }, + { + .name = "msg", + .desc = "Show all protocol messages with hex dump", + .type = OPTION_FLAG, + .opt.flag = &cfg.msg, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "mtu", + .argname = "mtu", + .desc = "Set the link layer MTU on DTLS connections", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_client_opt_mtu, + }, +#endif + { + .name = "nbio", + .desc = "Turn on non-blocking I/O", + .type = OPTION_FLAG, + .opt.flag = &cfg.nbio, + }, + { + .name = "nbio_test", + .desc = "Test non-blocking I/O", + .type = OPTION_FLAG, + .opt.flag = &cfg.nbio_test, + }, + { + .name = "nextprotoneg", + .argname = "protocols", + .type = OPTION_ARG, + .opt.arg = &cfg.npn_in, /* Ignored. */ + }, + { + .name = "no_comp", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_COMPRESSION, + }, + { + .name = "no_ign_eof", + .desc = "Don't ignore input EOF", + .type = OPTION_VALUE, + .opt.value = &cfg.ign_eof, + .value = 0, + }, + { + .name = "no_legacy_server_connect", + .desc = "Disallow initial connection to servers that don't support RI", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.clr, + .value = SSL_OP_LEGACY_SERVER_CONNECT, + }, + { + .name = "no_servername", + .desc = "Do not send a Server Name Indication (SNI) extension", + .type = OPTION_FLAG, + .opt.value = &cfg.no_servername, + }, + { + .name = "no_ssl2", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_SSLv2, + }, + { + .name = "no_ssl3", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_SSLv3, + }, + { + .name = "no_ticket", + .desc = "Disable use of RFC4507 session ticket support", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TICKET, + }, + { + .name = "no_tls1", + .type = OPTION_DISCARD, + }, + { + .name = "no_tls1_1", + .type = OPTION_DISCARD, + }, + { + .name = "no_tls1_2", + .desc = "Disable the use of TLSv1.2", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TLSv1_2, + }, + { + .name = "no_tls1_3", + .desc = "Disable the use of TLSv1.3", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TLSv1_3, + }, + { + .name = "noservername", + .type = OPTION_FLAG, + .opt.value = &cfg.no_servername, + }, + { + .name = "pass", + .argname = "arg", + .desc = "Private key file pass phrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passarg, + }, + { + .name = "pause", + .desc = "Pause 1 second between each read and write call", + .type = OPTION_FLAG, + .opt.flag = &cfg.pause, + }, + { + .name = "peekaboo", + .type = OPTION_FLAG, + .opt.flag = &cfg.peekaboo, + }, + { + .name = "port", + .argname = "port", + .desc = "Use -connect instead", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_client_opt_port, + }, + { + .name = "prexit", + .desc = "Print session information when the program exits", + .type = OPTION_FLAG, + .opt.flag = &cfg.prexit, + }, + { + .name = "proxy", + .argname = "host:port", + .desc = "Connect to http proxy", + .type = OPTION_ARG, + .opt.arg = &cfg.proxy, + }, + { + .name = "quiet", + .desc = "Inhibit printing of session and certificate info", + .type = OPTION_FUNC, + .opt.func = s_client_opt_quiet, + }, + { + .name = "reconnect", + .desc = "Drop and re-make the connection with the same Session-ID", + .type = OPTION_VALUE, + .opt.value = &cfg.reconnect, + .value = 5, + }, + { + .name = "servername", + .argname = "name", + .desc = "Set TLS extension servername in ClientHello (SNI)", + .type = OPTION_ARG, + .opt.arg = &cfg.servername, + }, + { + .name = "serverpref", + .desc = "Use server's cipher preferences", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_CIPHER_SERVER_PREFERENCE, + }, + { + .name = "sess_in", + .argname = "file", + .desc = "File to read TLS session from", + .type = OPTION_ARG, + .opt.arg = &cfg.sess_in, + }, + { + .name = "sess_out", + .argname = "file", + .desc = "File to write TLS session to", + .type = OPTION_ARG, + .opt.arg = &cfg.sess_out, + }, + { + .name = "showcerts", + .desc = "Show all server certificates in the chain", + .type = OPTION_FLAG, + .opt.flag = &cfg.showcerts, + }, + { + .name = "starttls", + .argname = "protocol", + .desc = "Use the STARTTLS command before starting TLS,\n" + "smtp, lmtp, pop3, imap, ftp and xmpp are supported.", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_client_opt_starttls, + }, + { + .name = "state", + .desc = "Print the TLS session states", + .type = OPTION_FLAG, + .opt.flag = &cfg.state, + }, + { + .name = "status", + .desc = "Send a certificate status request to the server (OCSP)", + .type = OPTION_FLAG, + .opt.flag = &cfg.status_req, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "timeout", + .desc = "Enable send/receive timeout on DTLS connections", + .type = OPTION_FLAG, + .opt.flag = &cfg.enable_timeouts, + }, +#endif + { + .name = "tls1_2", + .desc = "Just use TLSv1.2", + .type = OPTION_FUNC, + .opt.func = s_client_opt_protocol_version_tls1_2, + }, + { + .name = "tls1_3", + .desc = "Just use TLSv1.3", + .type = OPTION_FUNC, + .opt.func = s_client_opt_protocol_version_tls1_3, + }, + { + .name = "tlsextdebug", + .desc = "Hex dump of all TLS extensions received", + .type = OPTION_FLAG, + .opt.flag = &cfg.tlsextdebug, + }, +#ifndef OPENSSL_NO_SRTP + { + .name = "use_srtp", + .argname = "profiles", + .desc = "Offer SRTP key management with a colon-separated profiles", + .type = OPTION_ARG, + .opt.arg = &cfg.srtp_profiles, + }, +#endif + { + .name = "verify", + .argname = "depth", + .desc = "Turn on peer certificate verification, with a max of depth", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_client_opt_verify, + }, + { + .name = "verify_return_error", + .desc = "Return verification error", + .type = OPTION_FLAG, + .opt.flag = &verify_return_error, + }, + { + .name = "xmpphost", + .argname = "host", + .desc = "Connect to this virtual host on the xmpp server", + .type = OPTION_ARG, + .opt.arg = &cfg.xmpphost, + }, + { + .name = NULL, + .desc = "", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = s_client_opt_verify_param, + }, + { NULL }, +}; + +static void +sc_usage(void) +{ + fprintf(stderr, "usage: s_client " + "[-4 | -6] [-alpn protocols] [-bugs] [-CAfile file]\n" + " [-CApath directory] [-cert file] [-certform der | pem] [-check_ss_sig]\n" + " [-cipher cipherlist] [-connect host[:port]] [-crl_check]\n" + " [-crl_check_all] [-crlf] [-debug] [-dtls] [-dtls1_2] [-extended_crl]\n" + " [-groups list] [-host host] [-ign_eof] [-ignore_critical]\n" + " [-issuer_checks] [-key keyfile] [-keyform der | pem]\n" + " [-keymatexport label] [-keymatexportlen len] [-legacy_server_connect]\n" + " [-msg] [-mtu mtu] [-nbio] [-nbio_test] [-no_comp] [-no_ign_eof]\n" + " [-no_legacy_server_connect] [-no_ticket] \n" + " [-no_tls1_2] [-no_tls1_3] [-pass arg] [-pause] [-policy_check]\n" + " [-port port] [-prexit] [-proxy host:port] [-quiet] [-reconnect]\n" + " [-servername name] [-serverpref] [-sess_in file] [-sess_out file]\n" + " [-showcerts] [-starttls protocol] [-state] [-status] [-timeout]\n" + " [-tls1_2] [-tls1_3] [-tlsextdebug]\n" + " [-use_srtp profiles] [-verify depth] [-verify_return_error]\n" + " [-x509_strict] [-xmpphost host]\n"); + fprintf(stderr, "\n"); + options_usage(s_client_options); + fprintf(stderr, "\n"); +} + +int +s_client_main(int argc, char **argv) +{ + SSL *con = NULL; + int s, k, p = 0, pending = 0; + char *cbuf = NULL, *sbuf = NULL, *mbuf = NULL, *pbuf = NULL; + int cbuf_len, cbuf_off; + int sbuf_len, sbuf_off; + int full_log = 1; + const char *servername; + char *pass = NULL; + X509 *cert = NULL; + EVP_PKEY *key = NULL; + int badop = 0; + int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending; + SSL_CTX *ctx = NULL; + int ret = 1, in_init = 1, i; + BIO *bio_c_out = NULL; + BIO *sbio; + int mbuf_len = 0; + struct timeval timeout; + tlsextctx tlsextcbp = {NULL, 0}; + struct sockaddr_storage peer; + int peerlen = sizeof(peer); + + if (pledge("stdio cpath wpath rpath inet dns tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.af = AF_UNSPEC; + cfg.cert_format = FORMAT_PEM; + cfg.host = SSL_HOST_NAME; + cfg.key_format = FORMAT_PEM; + cfg.keymatexportlen = 20; + cfg.meth = TLS_client_method(); + cfg.port = PORT_STR; + cfg.socket_type = SOCK_STREAM; + cfg.starttls_proto = PROTO_OFF; + cfg.verify = SSL_VERIFY_NONE; + + if (((cbuf = malloc(BUFSIZZ)) == NULL) || + ((sbuf = malloc(BUFSIZZ)) == NULL) || + ((pbuf = malloc(BUFSIZZ)) == NULL) || + ((mbuf = malloc(BUFSIZZ + 1)) == NULL)) { /* NUL byte */ + BIO_printf(bio_err, "out of memory\n"); + goto end; + } + verify_depth = 0; + + if (options_parse(argc, argv, s_client_options, NULL, NULL) != 0) { + badop = 1; + goto bad; + } + if (cfg.proxy != NULL) { + if (!extract_host_port(cfg.proxy, + &cfg.host, NULL, &cfg.port)) + goto bad; + if (cfg.connect == NULL) + cfg.connect = SSL_HOST_NAME; + } else if (cfg.connect != NULL) { + if (!extract_host_port(cfg.connect, + &cfg.host, NULL, &cfg.port)) + goto bad; + } + if (badop) { + bad: + if (cfg.errstr == NULL) + sc_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passarg, NULL, &pass, NULL)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + if (cfg.key_file == NULL) + cfg.key_file = cfg.cert_file; + + + if (cfg.key_file) { + + key = load_key(bio_err, cfg.key_file, + cfg.key_format, 0, pass, + "client certificate private key file"); + if (!key) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.cert_file) { + cert = load_cert(bio_err, cfg.cert_file, + cfg.cert_format, + NULL, "client certificate file"); + + if (!cert) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.quiet && !cfg.debug && + !cfg.msg) { + if ((bio_c_out = BIO_new(BIO_s_null())) == NULL) + goto end; + } else { + if ((bio_c_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) + goto end; + } + + ctx = SSL_CTX_new(cfg.meth); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (cfg.vpm) + SSL_CTX_set1_param(ctx, cfg.vpm); + + if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version)) + goto end; + if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version)) + goto end; + +#ifndef OPENSSL_NO_SRTP + if (cfg.srtp_profiles != NULL) + SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles); +#endif + if (cfg.bugs) + SSL_CTX_set_options(ctx, SSL_OP_ALL | cfg.off); + else + SSL_CTX_set_options(ctx, cfg.off); + + if (cfg.clr) + SSL_CTX_clear_options(ctx, cfg.clr); + + if (cfg.alpn_in) { + unsigned short alpn_len; + unsigned char *alpn; + + alpn = next_protos_parse(&alpn_len, cfg.alpn_in); + if (alpn == NULL) { + BIO_printf(bio_err, "Error parsing -alpn argument\n"); + goto end; + } + SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len); + free(alpn); + } + if (cfg.groups_in != NULL) { + if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) { + BIO_printf(bio_err, "Failed to set groups '%s'\n", + cfg.groups_in); + goto end; + } + } + + if (cfg.state) + SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); + if (cfg.cipher != NULL) + if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) { + BIO_printf(bio_err, "error setting cipher list\n"); + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_set_verify(ctx, cfg.verify, verify_callback); + if (!set_cert_key_stuff(ctx, cert, key)) + goto end; + + if ((cfg.CAfile || cfg.CApath) + && !SSL_CTX_load_verify_locations(ctx, cfg.CAfile, + cfg.CApath)) + ERR_print_errors(bio_err); + + if (!SSL_CTX_set_default_verify_paths(ctx)) + ERR_print_errors(bio_err); + + con = SSL_new(ctx); + if (cfg.sess_in) { + SSL_SESSION *sess; + BIO *stmp = BIO_new_file(cfg.sess_in, "r"); + if (!stmp) { + BIO_printf(bio_err, "Can't open session file %s\n", + cfg.sess_in); + ERR_print_errors(bio_err); + goto end; + } + sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL); + BIO_free(stmp); + if (!sess) { + BIO_printf(bio_err, "Can't open session file %s\n", + cfg.sess_in); + ERR_print_errors(bio_err); + goto end; + } + SSL_set_session(con, sess); + SSL_SESSION_free(sess); + } + + /* Attempt to opportunistically use the host name for SNI. */ + servername = cfg.servername; + if (servername == NULL) + servername = cfg.host; + + if (!cfg.no_servername && servername != NULL && + !SSL_set_tlsext_host_name(con, servername)) { + long ssl_err = ERR_peek_error(); + + if (cfg.servername != NULL || + ERR_GET_LIB(ssl_err) != ERR_LIB_SSL || + ERR_GET_REASON(ssl_err) != SSL_R_SSL3_EXT_INVALID_SERVERNAME) { + BIO_printf(bio_err, + "Unable to set TLS servername extension.\n"); + ERR_print_errors(bio_err); + goto end; + } + servername = NULL; + ERR_clear_error(); + } + if (!cfg.no_servername && servername != NULL) { + tlsextcbp.biodebug = bio_err; + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp); + } + + re_start: + + if (init_client(&s, cfg.host, cfg.port, + cfg.socket_type, cfg.af) == 0) { + BIO_printf(bio_err, "connect:errno=%d\n", errno); + goto end; + } + BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s); + + if (cfg.nbio) { + if (!cfg.quiet) + BIO_printf(bio_c_out, "turning on non blocking io\n"); + if (!BIO_socket_nbio(s, 1)) { + ERR_print_errors(bio_err); + goto end; + } + } + if (cfg.pause & 0x01) + SSL_set_debug(con, 1); + + if (SSL_is_dtls(con)) { + sbio = BIO_new_dgram(s, BIO_NOCLOSE); + if (getsockname(s, (struct sockaddr *)&peer, + (void *)&peerlen) == -1) { + BIO_printf(bio_err, "getsockname:errno=%d\n", + errno); + shutdown(s, SHUT_RD); + close(s); + goto end; + } + (void) BIO_ctrl_set_connected(sbio, 1, &peer); + + if (cfg.enable_timeouts) { + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_RCV_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, + &timeout); + + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_SND_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, + &timeout); + } + if (cfg.socket_mtu > 28) { + SSL_set_options(con, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(con, cfg.socket_mtu - 28); + } else + /* want to do MTU discovery */ + BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); + } else + sbio = BIO_new_socket(s, BIO_NOCLOSE); + + if (cfg.nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + if (cfg.debug) { + SSL_set_debug(con, 1); + BIO_set_callback(sbio, bio_dump_callback); + BIO_set_callback_arg(sbio, (char *) bio_c_out); + } + if (cfg.msg) { + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_c_out); + } + if (cfg.tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_c_out); + } + if (cfg.status_req) { + SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp); + SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb); + SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out); + } + + SSL_set_bio(con, sbio, sbio); + SSL_set_connect_state(con); + + /* ok, lets connect */ + read_tty = 1; + write_tty = 0; + tty_on = 0; + read_ssl = 1; + write_ssl = 1; + + cbuf_len = 0; + cbuf_off = 0; + sbuf_len = 0; + sbuf_off = 0; + + /* This is an ugly hack that does a lot of assumptions */ + /* + * We do have to handle multi-line responses which may come in a + * single packet or not. We therefore have to use BIO_gets() which + * does need a buffering BIO. So during the initial chitchat we do + * push a buffering BIO into the chain that is removed again later on + * to not disturb the rest of the s_client operation. + */ + if (cfg.starttls_proto == PROTO_SMTP || + cfg.starttls_proto == PROTO_LMTP) { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); + /* wait for multi-line response to end from SMTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } + while (mbuf_len > 3 && mbuf[3] == '-'); + /* STARTTLS command requires EHLO... */ + BIO_printf(fbio, "%cHLO openssl.client.net\r\n", + cfg.starttls_proto == PROTO_SMTP ? 'E' : 'L'); + (void) BIO_flush(fbio); + /* wait for multi-line response to end EHLO SMTP response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } + while (mbuf_len > 3 && mbuf[3] == '-'); + (void) BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "didn't find starttls in server response," + " try anyway...\n"); + BIO_printf(sbio, "STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } else if (cfg.starttls_proto == PROTO_POP3) { + mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ); + if (mbuf_len == -1) { + BIO_printf(bio_err, "BIO_read failed\n"); + goto end; + } + BIO_printf(sbio, "STLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } else if (cfg.starttls_proto == PROTO_IMAP) { + int foundit = 0; + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); + BIO_gets(fbio, mbuf, BUFSIZZ); + /* STARTTLS command requires CAPABILITY... */ + BIO_printf(fbio, ". CAPABILITY\r\n"); + (void) BIO_flush(fbio); + /* wait for multi-line CAPABILITY response */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + if (strstr(mbuf, "STARTTLS")) + foundit = 1; + } + while (mbuf_len > 3 && mbuf[0] != '.'); + (void) BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + if (!foundit) + BIO_printf(bio_err, + "didn't find STARTTLS in server response," + " try anyway...\n"); + BIO_printf(sbio, ". STARTTLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } else if (cfg.starttls_proto == PROTO_FTP) { + BIO *fbio = BIO_new(BIO_f_buffer()); + BIO_push(fbio, sbio); + /* wait for multi-line response to end from FTP */ + do { + mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ); + } + while (mbuf_len > 3 && mbuf[3] == '-'); + (void) BIO_flush(fbio); + BIO_pop(fbio); + BIO_free(fbio); + BIO_printf(sbio, "AUTH TLS\r\n"); + BIO_read(sbio, sbuf, BUFSIZZ); + } else if (cfg.starttls_proto == PROTO_XMPP) { + int seen = 0; + BIO_printf(sbio, "", + cfg.xmpphost ? + cfg.xmpphost : cfg.host); + seen = BIO_read(sbio, mbuf, BUFSIZZ); + + if (seen <= 0) + goto shut; + + mbuf[seen] = 0; + while (!strstr(mbuf, ""); + seen = BIO_read(sbio, sbuf, BUFSIZZ); + sbuf[seen] = 0; + if (!strstr(sbuf, " 0) + full_log--; + + if (cfg.starttls_proto) { + BIO_write(bio_err, mbuf, mbuf_len); + /* We don't need to know any more */ + cfg.starttls_proto = PROTO_OFF; + } + if (cfg.reconnect) { + cfg.reconnect--; + BIO_printf(bio_c_out, + "drop connection and then reconnect\n"); + SSL_shutdown(con); + SSL_set_connect_state(con); + shutdown(SSL_get_fd(con), SHUT_RD); + close(SSL_get_fd(con)); + goto re_start; + } + } + } + + ssl_pending = read_ssl && SSL_pending(con); + + pfd[0].fd = -1; + pfd[1].fd = -1; + if (!ssl_pending) { + if (tty_on) { + if (read_tty) { + pfd[0].fd = fileno(stdin); + pfd[0].events = POLLIN; + } + if (write_tty) { + pfd[1].fd = fileno(stdout); + pfd[1].events = POLLOUT; + } + } + + pfd[2].fd = SSL_get_fd(con); + pfd[2].events = 0; + if (read_ssl) + pfd[2].events |= POLLIN; + if (write_ssl) + pfd[2].events |= POLLOUT; + +/* printf("mode tty(%d %d%d) ssl(%d%d)\n", + tty_on,read_tty,write_tty,read_ssl,write_ssl);*/ + + i = poll(pfd, 3, ptimeout); + if (i == -1) { + BIO_printf(bio_err, "bad select %d\n", + errno); + goto shut; + /* goto end; */ + } + } + if (SSL_is_dtls(con) && + DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occured\n"); + if (!ssl_pending && + (pfd[2].revents & (POLLOUT|POLLERR|POLLNVAL))) { + if (pfd[2].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } + k = SSL_write(con, &(cbuf[cbuf_off]), + (unsigned int) cbuf_len); + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + cbuf_off += k; + cbuf_len -= k; + if (k <= 0) + goto end; + /* we have done a write(con,NULL,0); */ + if (cbuf_len <= 0) { + read_tty = 1; + write_ssl = 0; + } else { /* if (cbuf_len > 0) */ + read_tty = 0; + write_ssl = 1; + } + break; + case SSL_ERROR_WANT_WRITE: + BIO_printf(bio_c_out, "write W BLOCK\n"); + write_ssl = 1; + read_tty = 0; + break; + case SSL_ERROR_WANT_READ: + BIO_printf(bio_c_out, "write R BLOCK\n"); + write_tty = 0; + read_ssl = 1; + write_ssl = 0; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_c_out, "write X BLOCK\n"); + break; + case SSL_ERROR_ZERO_RETURN: + if (cbuf_len != 0) { + BIO_printf(bio_c_out, "shutdown\n"); + ret = 0; + goto shut; + } else { + read_tty = 1; + write_ssl = 0; + break; + } + + case SSL_ERROR_SYSCALL: + if ((k != 0) || (cbuf_len != 0)) { + BIO_printf(bio_err, "write:errno=%d\n", + errno); + goto shut; + } else { + read_tty = 1; + write_ssl = 0; + } + break; + case SSL_ERROR_SSL: + ERR_print_errors(bio_err); + goto shut; + } + } else if (!ssl_pending && + (pfd[1].revents & (POLLOUT|POLLERR|POLLNVAL))) { + if (pfd[1].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } + i = write(fileno(stdout), &(sbuf[sbuf_off]), sbuf_len); + + if (i <= 0) { + BIO_printf(bio_c_out, "DONE\n"); + ret = 0; + goto shut; + /* goto end; */ + } + sbuf_len -= i; + sbuf_off += i; + if (sbuf_len <= 0) { + read_ssl = 1; + write_tty = 0; + } + } else if (ssl_pending || (pfd[2].revents & (POLLIN|POLLHUP))) { +#ifdef RENEG + { + static int iiii; + if (++iiii == 52) { + SSL_renegotiate(con); + iiii = 0; + } + } +#endif + if (cfg.peekaboo) { + k = p = SSL_peek(con, pbuf, 1024 /* BUFSIZZ */ ); + pending = SSL_pending(con); + if (SSL_get_error(con, p) == SSL_ERROR_NONE) { + if (p <= 0) + goto end; + + k = SSL_read(con, sbuf, p); + } + } else { + k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ ); + } + + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + if (k <= 0) + goto end; + sbuf_off = 0; + sbuf_len = k; + if (cfg.peekaboo) { + if (p != pending) { + ret = -1; + BIO_printf(bio_err, + "peeked %d but pending %d!\n", + p, pending); + goto shut; + } + if (k < p) { + ret = -1; + BIO_printf(bio_err, + "read less than peek!\n"); + goto shut; + } + if (p > 0 && + (memcmp(sbuf, pbuf, p) != 0)) { + ret = -1; + BIO_printf(bio_err, + "peek of %d different from read of %d!\n", + p, k); + goto shut; + } + } + read_ssl = 0; + write_tty = 1; + break; + case SSL_ERROR_WANT_WRITE: + BIO_printf(bio_c_out, "read W BLOCK\n"); + write_ssl = 1; + read_tty = 0; + break; + case SSL_ERROR_WANT_READ: + BIO_printf(bio_c_out, "read R BLOCK\n"); + write_tty = 0; + read_ssl = 1; + if ((read_tty == 0) && (write_ssl == 0)) + write_ssl = 1; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_c_out, "read X BLOCK\n"); + break; + case SSL_ERROR_SYSCALL: + ret = errno; + BIO_printf(bio_err, "read:errno=%d\n", ret); + goto shut; + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_c_out, "closed\n"); + ret = 0; + goto shut; + case SSL_ERROR_SSL: + ERR_print_errors(bio_err); + goto shut; + /* break; */ + } + } else if (pfd[0].revents) { + if (pfd[0].revents & (POLLERR|POLLNVAL)) { + BIO_printf(bio_err, "poll error"); + goto shut; + } + if (cfg.crlf) { + int j, lf_num; + + i = read(fileno(stdin), cbuf, BUFSIZZ / 2); + lf_num = 0; + /* both loops are skipped when i <= 0 */ + for (j = 0; j < i; j++) + if (cbuf[j] == '\n') + lf_num++; + for (j = i - 1; j >= 0; j--) { + cbuf[j + lf_num] = cbuf[j]; + if (cbuf[j] == '\n') { + lf_num--; + i++; + cbuf[j + lf_num] = '\r'; + } + } + assert(lf_num == 0); + } else + i = read(fileno(stdin), cbuf, BUFSIZZ); + + if ((!cfg.ign_eof) && + ((i <= 0) || (cbuf[0] == 'Q'))) { + BIO_printf(bio_err, "DONE\n"); + ret = 0; + goto shut; + } + if ((!cfg.ign_eof) && (cbuf[0] == 'R')) { + BIO_printf(bio_err, "RENEGOTIATING\n"); + SSL_renegotiate(con); + cbuf_len = 0; + } else { + cbuf_len = i; + cbuf_off = 0; + } + + write_ssl = 1; + read_tty = 0; + } + } + + ret = 0; + shut: + if (in_init) + print_stuff(bio_c_out, con, full_log); + SSL_shutdown(con); + shutdown(SSL_get_fd(con), SHUT_RD); + close(SSL_get_fd(con)); + end: + if (con != NULL) { + if (cfg.prexit != 0) + print_stuff(bio_c_out, con, 1); + SSL_free(con); + } + SSL_CTX_free(ctx); + X509_free(cert); + EVP_PKEY_free(key); + free(pass); + X509_VERIFY_PARAM_free(cfg.vpm); + freezero(cbuf, BUFSIZZ); + freezero(sbuf, BUFSIZZ); + freezero(pbuf, BUFSIZZ); + freezero(mbuf, BUFSIZZ); + BIO_free(bio_c_out); + + return (ret); +} + +static void +print_stuff(BIO *bio, SSL *s, int full) +{ + X509 *peer = NULL; + char *p; + static const char *space = " "; + char buf[BUFSIZ]; + STACK_OF(X509) *sk; + STACK_OF(X509_NAME) *sk2; + const SSL_CIPHER *c; + X509_NAME *xn; + int j, i; + unsigned char *exportedkeymat; + + if (full) { + int got_a_chain = 0; + + sk = SSL_get_peer_cert_chain(s); + if (sk != NULL) { + got_a_chain = 1; /* we don't have it for SSL2 + * (yet) */ + + BIO_printf(bio, "---\nCertificate chain\n"); + for (i = 0; i < sk_X509_num(sk); i++) { + X509_NAME_oneline(X509_get_subject_name( + sk_X509_value(sk, i)), buf, sizeof buf); + BIO_printf(bio, "%2d s:%s\n", i, buf); + X509_NAME_oneline(X509_get_issuer_name( + sk_X509_value(sk, i)), buf, sizeof buf); + BIO_printf(bio, " i:%s\n", buf); + if (cfg.showcerts) + PEM_write_bio_X509(bio, + sk_X509_value(sk, i)); + } + } + BIO_printf(bio, "---\n"); + peer = SSL_get_peer_certificate(s); + if (peer != NULL) { + BIO_printf(bio, "Server certificate\n"); + if (!(cfg.showcerts && got_a_chain)) { + /* Redundant if we showed the whole chain */ + PEM_write_bio_X509(bio, peer); + } + X509_NAME_oneline(X509_get_subject_name(peer), + buf, sizeof buf); + BIO_printf(bio, "subject=%s\n", buf); + X509_NAME_oneline(X509_get_issuer_name(peer), + buf, sizeof buf); + BIO_printf(bio, "issuer=%s\n", buf); + } else + BIO_printf(bio, "no peer certificate available\n"); + + sk2 = SSL_get_client_CA_list(s); + if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) { + BIO_printf(bio, + "---\nAcceptable client certificate CA names\n"); + for (i = 0; i < sk_X509_NAME_num(sk2); i++) { + xn = sk_X509_NAME_value(sk2, i); + X509_NAME_oneline(xn, buf, sizeof(buf)); + BIO_write(bio, buf, strlen(buf)); + BIO_write(bio, "\n", 1); + } + } else { + BIO_printf(bio, + "---\nNo client certificate CA names sent\n"); + } + p = SSL_get_shared_ciphers(s, buf, sizeof buf); + if (p != NULL) { + /* + * This works only for SSL 2. In later protocol + * versions, the client does not know what other + * ciphers (in addition to the one to be used in the + * current connection) the server supports. + */ + + BIO_printf(bio, + "---\nCiphers common between both SSL endpoints:\n"); + j = i = 0; + while (*p) { + if (*p == ':') { + BIO_write(bio, space, 15 - j % 25); + i++; + j = 0; + BIO_write(bio, + ((i % 3) ? " " : "\n"), 1); + } else { + BIO_write(bio, p, 1); + j++; + } + p++; + } + BIO_write(bio, "\n", 1); + } + + ssl_print_tmp_key(bio, s); + + BIO_printf(bio, + "---\nSSL handshake has read %ld bytes and written %ld bytes\n", + BIO_number_read(SSL_get_rbio(s)), + BIO_number_written(SSL_get_wbio(s))); + } + BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, ")); + c = SSL_get_current_cipher(s); + BIO_printf(bio, "%s, Cipher is %s\n", + SSL_CIPHER_get_version(c), + SSL_CIPHER_get_name(c)); + if (peer != NULL) { + EVP_PKEY *pktmp; + + pktmp = X509_get0_pubkey(peer); + BIO_printf(bio, "Server public key is %d bit\n", + EVP_PKEY_bits(pktmp)); + } + BIO_printf(bio, "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(s) ? "" : " NOT"); + + /* Compression is not supported and will always be none. */ + BIO_printf(bio, "Compression: NONE\n"); + BIO_printf(bio, "Expansion: NONE\n"); + +#ifdef SSL_DEBUG + { + /* Print out local port of connection: useful for debugging */ + int sock; + struct sockaddr_in ladd; + socklen_t ladd_size = sizeof(ladd); + sock = SSL_get_fd(s); + getsockname(sock, (struct sockaddr *) & ladd, &ladd_size); + BIO_printf(bio, "LOCAL PORT is %u\n", + ntohs(ladd.sin_port)); + } +#endif + + { + const unsigned char *proto; + unsigned int proto_len; + SSL_get0_alpn_selected(s, &proto, &proto_len); + if (proto_len > 0) { + BIO_printf(bio, "ALPN protocol: "); + BIO_write(bio, proto, proto_len); + BIO_write(bio, "\n", 1); + } else + BIO_printf(bio, "No ALPN negotiated\n"); + } + +#ifndef OPENSSL_NO_SRTP + { + SRTP_PROTECTION_PROFILE *srtp_profile; + + srtp_profile = SSL_get_selected_srtp_profile(s); + if (srtp_profile) + BIO_printf(bio, + "SRTP Extension negotiated, profile=%s\n", + srtp_profile->name); + } +#endif + + SSL_SESSION_print(bio, SSL_get_session(s)); + if (cfg.keymatexportlabel != NULL) { + BIO_printf(bio, "Keying material exporter:\n"); + BIO_printf(bio, " Label: '%s'\n", + cfg.keymatexportlabel); + BIO_printf(bio, " Length: %i bytes\n", + cfg.keymatexportlen); + exportedkeymat = malloc(cfg.keymatexportlen); + if (exportedkeymat != NULL) { + if (!SSL_export_keying_material(s, exportedkeymat, + cfg.keymatexportlen, + cfg.keymatexportlabel, + strlen(cfg.keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio, " Error\n"); + } else { + BIO_printf(bio, " Keying material: "); + for (i = 0; i < cfg.keymatexportlen; i++) + BIO_printf(bio, "%02X", + exportedkeymat[i]); + BIO_printf(bio, "\n"); + } + free(exportedkeymat); + } + } + BIO_printf(bio, "---\n"); + X509_free(peer); + /* flush, or debugging output gets mixed with http response */ + (void) BIO_flush(bio); +} + +static int +ocsp_resp_cb(SSL *s, void *arg) +{ + const unsigned char *p; + int len; + OCSP_RESPONSE *rsp; + len = SSL_get_tlsext_status_ocsp_resp(s, &p); + BIO_puts(arg, "OCSP response: "); + if (!p) { + BIO_puts(arg, "no response sent\n"); + return 1; + } + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if (!rsp) { + BIO_puts(arg, "response parse error\n"); + BIO_dump_indent(arg, (char *) p, len, 4); + return 0; + } + BIO_puts(arg, "\n======================================\n"); + OCSP_RESPONSE_print(arg, rsp, 0); + BIO_puts(arg, "======================================\n"); + OCSP_RESPONSE_free(rsp); + return 1; +} + +static int +ssl_servername_cb(SSL *s, int *ad, void *arg) +{ + tlsextctx *p = (tlsextctx *) arg; + const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); + if (SSL_get_servername_type(s) != -1) + p->ack = !SSL_session_reused(s) && hn != NULL; + else + BIO_printf(bio_err, "Can't use SSL_get_servername\n"); + + return SSL_TLSEXT_ERR_OK; +} + diff --git a/apps/openssl/s_server.c b/apps/openssl/s_server.c new file mode 100644 index 0000000..95fe633 --- /dev/null +++ b/apps/openssl/s_server.c @@ -0,0 +1,2420 @@ +/* $OpenBSD: s_server.c,v 1.58 2023/07/03 08:03:56 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "apps.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_DH +#include +#endif + +#include + +#include "s_apps.h" +#include "timeouts.h" + +static void s_server_init(void); +static void sv_usage(void); +static void print_stats(BIO *bp, SSL_CTX *ctx); +static int sv_body(int s, unsigned char *context); +static void close_accept_socket(void); +static int init_ssl_connection(SSL *s); +#ifndef OPENSSL_NO_DH +static DH *load_dh_param(const char *dhfile); +#endif +static int www_body(int s, unsigned char *context); +static int generate_session_id(const SSL *ssl, unsigned char *id, + unsigned int *id_len); +static int ssl_servername_cb(SSL *s, int *ad, void *arg); +static int cert_status_cb(SSL * s, void *arg); +static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg); +/* static int load_CA(SSL_CTX *ctx, char *file);*/ + +#define BUFSIZZ 16*1024 +static int bufsize = BUFSIZZ; +static int accept_socket = -1; + +#define TEST_CERT "server.pem" +#define TEST_CERT2 "server2.pem" + +static int s_server_session_id_context = 1; /* anything will do */ +static SSL_CTX *ctx = NULL; +static SSL_CTX *ctx2 = NULL; +static BIO *bio_s_out = NULL; + +static int local_argc = 0; +static char **local_argv; + +/* This is a context that we pass to callbacks */ +typedef struct tlsextctx_st { + char *servername; + BIO *biodebug; + int extension_error; +} tlsextctx; + +/* Structure passed to cert status callback */ +typedef struct tlsextstatusctx_st { + /* Default responder to use */ + char *host, *path, *port; + int use_ssl; + int timeout; + BIO *err; + int verbose; +} tlsextstatusctx; + +/* This the context that we pass to alpn_cb */ +typedef struct tlsextalpnctx_st { + unsigned char *data; + unsigned short len; +} tlsextalpnctx; + +static struct { + char *alpn_in; + char *npn_in; /* Ignored. */ + int bugs; + char *CAfile; + char *CApath; +#ifndef OPENSSL_NO_DTLS + int cert_chain; +#endif + char *cert_file; + char *cert_file2; + int cert_format; + char *cipher; + unsigned char *context; + int crlf; + char *dcert_file; + int dcert_format; + int debug; + char *dhfile; + char *dkey_file; + int dkey_format; + char *dpassarg; + int enable_timeouts; + const char *errstr; + char *groups_in; + char *key_file; + char *key_file2; + int key_format; + char *keymatexportlabel; + int keymatexportlen; + uint16_t max_version; + uint16_t min_version; + const SSL_METHOD *meth; + int msg; + int naccept; + char *named_curve; + int nbio; + int nbio_test; + int no_cache; + int nocert; + int no_dhe; + int no_ecdhe; + int no_tmp_rsa; /* No-op. */ + int off; + char *passarg; + short port; + int quiet; + int server_verify; + char *session_id_prefix; + long socket_mtu; + int socket_type; +#ifndef OPENSSL_NO_SRTP + char *srtp_profiles; +#endif + int state; + tlsextstatusctx tlscstatp; + tlsextctx tlsextcbp; + int tlsextdebug; + int tlsextstatus; + X509_VERIFY_PARAM *vpm; + int www; +} cfg; + +static int +s_server_opt_context(char *arg) +{ + cfg.context = (unsigned char *) arg; + return (0); +} + +static int +s_server_opt_keymatexportlen(char *arg) +{ + cfg.keymatexportlen = strtonum(arg, 1, INT_MAX, + &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + return (0); +} + +#ifndef OPENSSL_NO_DTLS +static int +s_server_opt_mtu(char *arg) +{ + cfg.socket_mtu = strtonum(arg, 0, LONG_MAX, + &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + return (0); +} +#endif + +#ifndef OPENSSL_NO_DTLS +static int +s_server_opt_protocol_version_dtls(void) +{ + cfg.meth = DTLS_server_method(); + cfg.socket_type = SOCK_DGRAM; + return (0); +} +#endif + +#ifndef OPENSSL_NO_DTLS1_2 +static int +s_server_opt_protocol_version_dtls1_2(void) +{ + cfg.meth = DTLS_server_method(); + cfg.min_version = DTLS1_2_VERSION; + cfg.max_version = DTLS1_2_VERSION; + cfg.socket_type = SOCK_DGRAM; + return (0); +} +#endif + +static int +s_server_opt_protocol_version_tls1_2(void) +{ + cfg.min_version = TLS1_2_VERSION; + cfg.max_version = TLS1_2_VERSION; + return (0); +} + +static int +s_server_opt_protocol_version_tls1_3(void) +{ + cfg.min_version = TLS1_3_VERSION; + cfg.max_version = TLS1_3_VERSION; + return (0); +} + +static int +s_server_opt_nbio_test(void) +{ + cfg.nbio = 1; + cfg.nbio_test = 1; + return (0); +} + +static int +s_server_opt_port(char *arg) +{ + if (!extract_port(arg, &cfg.port)) + return (1); + return (0); +} + +static int +s_server_opt_status_timeout(char *arg) +{ + cfg.tlsextstatus = 1; + cfg.tlscstatp.timeout = strtonum(arg, 0, INT_MAX, + &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + return (0); +} + +static int +s_server_opt_status_url(char *arg) +{ + cfg.tlsextstatus = 1; + if (!OCSP_parse_url(arg, &cfg.tlscstatp.host, + &cfg.tlscstatp.port, &cfg.tlscstatp.path, + &cfg.tlscstatp.use_ssl)) { + BIO_printf(bio_err, "Error parsing URL\n"); + return (1); + } + return (0); +} + +static int +s_server_opt_status_verbose(void) +{ + cfg.tlsextstatus = 1; + cfg.tlscstatp.verbose = 1; + return (0); +} + +static int +s_server_opt_verify(char *arg) +{ + cfg.server_verify = SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE; + verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + BIO_printf(bio_err, "verify depth is %d\n", verify_depth); + return (0); +} + +static int +s_server_opt_verify_fail(char *arg) +{ + cfg.server_verify = SSL_VERIFY_PEER | + SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; + verify_depth = strtonum(arg, 0, INT_MAX, &cfg.errstr); + if (cfg.errstr != NULL) { + BIO_printf(bio_err, "invalid argument %s: %s\n", + arg, cfg.errstr); + return (1); + } + BIO_printf(bio_err, "verify depth is %d, must return a certificate\n", + verify_depth); + return (0); +} + +static int +s_server_opt_verify_param(int argc, char **argv, int *argsused) +{ + char **pargs = argv; + int pargc = argc; + int badarg = 0; + + if (!args_verify(&pargs, &pargc, &badarg, bio_err, + &cfg.vpm)) { + BIO_printf(bio_err, "unknown option %s\n", *argv); + return (1); + } + if (badarg) + return (1); + + *argsused = argc - pargc; + return (0); +} + +static const struct option s_server_options[] = { + { + .name = "4", + .type = OPTION_DISCARD, + }, + { + .name = "6", + .type = OPTION_DISCARD, + }, + { + .name = "accept", + .argname = "port", + .desc = "Port to accept on (default is 4433)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_port, + }, + { + .name = "alpn", + .argname = "protocols", + .desc = "Set the advertised protocols for the ALPN extension" + " (comma-separated list)", + .type = OPTION_ARG, + .opt.arg = &cfg.alpn_in, + }, + { + .name = "bugs", + .desc = "Turn on SSL bug compatibility", + .type = OPTION_FLAG, + .opt.flag = &cfg.bugs, + }, + { + .name = "CAfile", + .argname = "file", + .desc = "PEM format file of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CAfile, + }, + { + .name = "CApath", + .argname = "directory", + .desc = "PEM format directory of CA certificates", + .type = OPTION_ARG, + .opt.arg = &cfg.CApath, + }, + { + .name = "cert", + .argname = "file", + .desc = "Certificate file to use\n" + "(default is " TEST_CERT ")", + .type = OPTION_ARG, + .opt.arg = &cfg.cert_file, + }, + { + .name = "cert2", + .argname = "file", + .desc = "Certificate file to use for servername\n" + "(default is " TEST_CERT2 ")", + .type = OPTION_ARG, + .opt.arg = &cfg.cert_file2, + }, + { + .name = "certform", + .argname = "fmt", + .desc = "Certificate format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.cert_format, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "chain", + .type = OPTION_FLAG, + .opt.flag = &cfg.cert_chain, + }, +#endif + { + .name = "cipher", + .argname = "list", + .desc = "List of ciphers to enable (see `openssl ciphers`)", + .type = OPTION_ARG, + .opt.arg = &cfg.cipher, + }, + { + .name = "context", + .argname = "id", + .desc = "Set session ID context", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_context, + }, + { + .name = "crlf", + .desc = "Convert LF from terminal into CRLF", + .type = OPTION_FLAG, + .opt.flag = &cfg.crlf, + }, + { + .name = "dcert", + .argname = "file", + .desc = "Second certificate file to use (usually for DSA)", + .type = OPTION_ARG, + .opt.arg = &cfg.dcert_file, + }, + { + .name = "dcertform", + .argname = "fmt", + .desc = "Second certificate format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.dcert_format, + }, + { + .name = "debug", + .desc = "Print more output", + .type = OPTION_FLAG, + .opt.flag = &cfg.debug, + }, + { + .name = "dhparam", + .argname = "file", + .desc = "DH parameter file to use, in cert file if not specified", + .type = OPTION_ARG, + .opt.arg = &cfg.dhfile, + }, + { + .name = "dkey", + .argname = "file", + .desc = "Second private key file to use (usually for DSA)", + .type = OPTION_ARG, + .opt.arg = &cfg.dkey_file, + }, + { + .name = "dkeyform", + .argname = "fmt", + .desc = "Second key format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.dkey_format, + }, + { + .name = "dpass", + .argname = "arg", + .desc = "Second private key file pass phrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.dpassarg, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "dtls", + .desc = "Use any version of DTLS", + .type = OPTION_FUNC, + .opt.func = s_server_opt_protocol_version_dtls, + }, +#endif +#ifndef OPENSSL_NO_DTLS1_2 + { + .name = "dtls1_2", + .desc = "Just use DTLSv1.2", + .type = OPTION_FUNC, + .opt.func = s_server_opt_protocol_version_dtls1_2, + }, +#endif + { + .name = "groups", + .argname = "list", + .desc = "Specify EC groups (colon-separated list)", + .type = OPTION_ARG, + .opt.arg = &cfg.groups_in, + }, + { + .name = "HTTP", + .desc = "Respond to a 'GET / HTTP/1.0' with file ./", + .type = OPTION_VALUE, + .opt.value = &cfg.www, + .value = 3, + }, + { + .name = "id_prefix", + .argname = "arg", + .desc = "Generate SSL/TLS session IDs prefixed by 'arg'", + .type = OPTION_ARG, + .opt.arg = &cfg.session_id_prefix, + }, + { + .name = "key", + .argname = "file", + .desc = "Private Key file to use, in cert file if\n" + "not specified (default is " TEST_CERT ")", + .type = OPTION_ARG, + .opt.arg = &cfg.key_file, + }, + { + .name = "key2", + .argname = "file", + .desc = "Private Key file to use for servername, in cert file if\n" + "not specified (default is " TEST_CERT2 ")", + .type = OPTION_ARG, + .opt.arg = &cfg.key_file2, + }, + { + .name = "keyform", + .argname = "fmt", + .desc = "Key format (PEM or DER) PEM default", + .type = OPTION_ARG_FORMAT, + .opt.value = &cfg.key_format, + }, + { + .name = "keymatexport", + .argname = "label", + .desc = "Export keying material using label", + .type = OPTION_ARG, + .opt.arg = &cfg.keymatexportlabel, + }, + { + .name = "keymatexportlen", + .argname = "len", + .desc = "Export len bytes of keying material (default 20)", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_keymatexportlen, + }, + { + .name = "legacy_renegotiation", + .type = OPTION_DISCARD, + }, + { + .name = "msg", + .desc = "Show protocol messages", + .type = OPTION_FLAG, + .opt.flag = &cfg.msg, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "mtu", + .argname = "mtu", + .desc = "Set link layer MTU", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_mtu, + }, +#endif + { + .name = "naccept", + .argname = "num", + .desc = "Terminate after num connections", + .type = OPTION_ARG_INT, + .opt.value = &cfg.naccept + }, + { + .name = "named_curve", + .argname = "arg", + .type = OPTION_ARG, + .opt.arg = &cfg.named_curve, + }, + { + .name = "nbio", + .desc = "Run with non-blocking I/O", + .type = OPTION_FLAG, + .opt.flag = &cfg.nbio, + }, + { + .name = "nbio_test", + .desc = "Test with the non-blocking test bio", + .type = OPTION_FUNC, + .opt.func = s_server_opt_nbio_test, + }, + { + .name = "nextprotoneg", + .argname = "arg", + .type = OPTION_ARG, + .opt.arg = &cfg.npn_in, /* Ignored. */ + }, + { + .name = "no_cache", + .desc = "Disable session cache", + .type = OPTION_FLAG, + .opt.flag = &cfg.no_cache, + }, + { + .name = "no_comp", + .desc = "Disable SSL/TLS compression", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_COMPRESSION, + }, + { + .name = "no_dhe", + .desc = "Disable ephemeral DH", + .type = OPTION_FLAG, + .opt.flag = &cfg.no_dhe, + }, + { + .name = "no_ecdhe", + .desc = "Disable ephemeral ECDH", + .type = OPTION_FLAG, + .opt.flag = &cfg.no_ecdhe, + }, + { + .name = "no_ticket", + .desc = "Disable use of RFC4507bis session tickets", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TICKET, + }, + { + .name = "no_ssl2", + .type = OPTION_DISCARD, + }, + { + .name = "no_ssl3", + .type = OPTION_DISCARD, + }, + { + .name = "no_tls1", + .type = OPTION_DISCARD, + }, + { + .name = "no_tls1_1", + .type = OPTION_DISCARD, + }, + { + .name = "no_tls1_2", + .desc = "Just disable TLSv1.2", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TLSv1_2, + }, + { + .name = "no_tls1_3", + .desc = "Just disable TLSv1.3", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_NO_TLSv1_3, + }, + { + .name = "no_tmp_rsa", + .type = OPTION_DISCARD, + }, + { + .name = "nocert", + .desc = "Don't use any certificates (Anon-DH)", + .type = OPTION_FLAG, + .opt.flag = &cfg.nocert, + }, + { + .name = "pass", + .argname = "arg", + .desc = "Private key file pass phrase source", + .type = OPTION_ARG, + .opt.arg = &cfg.passarg, + }, + { + .name = "port", + .argname = "port", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_port, + }, + { + .name = "quiet", + .desc = "Inhibit printing of session and certificate information", + .type = OPTION_FLAG, + .opt.flag = &cfg.quiet, + }, + { + .name = "servername", + .argname = "name", + .desc = "Servername for HostName TLS extension", + .type = OPTION_ARG, + .opt.arg = &cfg.tlsextcbp.servername, + }, + { + .name = "servername_fatal", + .desc = "On mismatch send fatal alert (default warning alert)", + .type = OPTION_VALUE, + .opt.value = &cfg.tlsextcbp.extension_error, + .value = SSL_TLSEXT_ERR_ALERT_FATAL, + }, + { + .name = "serverpref", + .desc = "Use server's cipher preferences", + .type = OPTION_VALUE_OR, + .opt.value = &cfg.off, + .value = SSL_OP_CIPHER_SERVER_PREFERENCE, + }, + { + .name = "state", + .desc = "Print the SSL states", + .type = OPTION_FLAG, + .opt.flag = &cfg.state, + }, + { + .name = "status", + .desc = "Respond to certificate status requests", + .type = OPTION_FLAG, + .opt.flag = &cfg.tlsextstatus, + }, + { + .name = "status_timeout", + .argname = "nsec", + .desc = "Status request responder timeout", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_status_timeout, + }, + { + .name = "status_url", + .argname = "url", + .desc = "Status request fallback URL", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_status_url, + }, + { + .name = "status_verbose", + .desc = "Enable status request verbose printout", + .type = OPTION_FUNC, + .opt.func = s_server_opt_status_verbose, + }, +#ifndef OPENSSL_NO_DTLS + { + .name = "timeout", + .desc = "Enable timeouts", + .type = OPTION_FLAG, + .opt.flag = &cfg.enable_timeouts, + }, +#endif + { + .name = "tls1_2", + .desc = "Just talk TLSv1.2", + .type = OPTION_FUNC, + .opt.func = s_server_opt_protocol_version_tls1_2, + }, + { + .name = "tls1_3", + .desc = "Just talk TLSv1.3", + .type = OPTION_FUNC, + .opt.func = s_server_opt_protocol_version_tls1_3, + }, + { + .name = "tlsextdebug", + .desc = "Hex dump of all TLS extensions received", + .type = OPTION_FLAG, + .opt.flag = &cfg.tlsextdebug, + }, +#ifndef OPENSSL_NO_SRTP + { + .name = "use_srtp", + .argname = "profiles", + .desc = "Offer SRTP key management with a colon-separated profile list", + .type = OPTION_ARG, + .opt.arg = &cfg.srtp_profiles, + }, +#endif + { + .name = "Verify", + .argname = "depth", + .desc = "Turn on peer certificate verification, must have a cert", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_verify_fail, + }, + { + .name = "verify", + .argname = "depth", + .desc = "Turn on peer certificate verification", + .type = OPTION_ARG_FUNC, + .opt.argfunc = s_server_opt_verify, + }, + { + .name = "verify_return_error", + .desc = "Return verification error", + .type = OPTION_FLAG, + .opt.flag = &verify_return_error, + }, + { + .name = "WWW", + .desc = "Respond to a 'GET / HTTP/1.0' with file ./", + .type = OPTION_VALUE, + .opt.value = &cfg.www, + .value = 2, + }, + { + .name = "www", + .desc = "Respond to a 'GET /' with a status page", + .type = OPTION_VALUE, + .opt.value = &cfg.www, + .value = 1, + }, + { + .name = NULL, + .desc = "", + .type = OPTION_ARGV_FUNC, + .opt.argvfunc = s_server_opt_verify_param, + }, + { NULL }, +}; + +static void +s_server_init(void) +{ + accept_socket = -1; + cfg.cipher = NULL; + cfg.server_verify = SSL_VERIFY_NONE; + cfg.dcert_file = NULL; + cfg.dkey_file = NULL; + cfg.cert_file = TEST_CERT; + cfg.key_file = NULL; + cfg.cert_file2 = TEST_CERT2; + cfg.key_file2 = NULL; + ctx2 = NULL; + cfg.nbio = 0; + cfg.nbio_test = 0; + ctx = NULL; + cfg.www = 0; + + bio_s_out = NULL; + cfg.debug = 0; + cfg.msg = 0; + cfg.quiet = 0; +} + +static void +sv_usage(void) +{ + fprintf(stderr, "usage: s_server " + "[-accept port] [-alpn protocols] [-bugs] [-CAfile file]\n" + " [-CApath directory] [-cert file] [-cert2 file]\n" + " [-certform der | pem] [-cipher cipherlist]\n" + " [-context id] [-crl_check] [-crl_check_all] [-crlf]\n" + " [-dcert file] [-dcertform der | pem] [-debug]\n" + " [-dhparam file] [-dkey file] [-dkeyform der | pem]\n" + " [-dpass arg] [-dtls] [-dtls1_2] [-groups list] [-HTTP]\n" + " [-id_prefix arg] [-key keyfile] [-key2 keyfile]\n" + " [-keyform der | pem] [-keymatexport label]\n" + " [-keymatexportlen len] [-msg] [-mtu mtu] [-naccept num]\n" + " [-named_curve arg] [-nbio] [-nbio_test] [-no_cache]\n" + " [-no_dhe] [-no_ecdhe] [-no_ticket] \n" + " [-no_tls1_2] [-no_tls1_3] [-no_tmp_rsa]\n" + " [-nocert] [-pass arg] [-quiet] [-servername name]\n" + " [-servername_fatal] [-serverpref] [-state] [-status]\n" + " [-status_timeout nsec] [-status_url url]\n" + " [-status_verbose] [-timeout] \n" + " [-tls1_2] [-tls1_3] [-tlsextdebug] [-use_srtp profiles]\n" + " [-Verify depth] [-verify depth] [-verify_return_error]\n" + " [-WWW] [-www]\n"); + fprintf(stderr, "\n"); + options_usage(s_server_options); + fprintf(stderr, "\n"); +} + +int +s_server_main(int argc, char *argv[]) +{ + int ret = 1; + char *pass = NULL; + char *dpass = NULL; + X509 *s_cert = NULL, *s_dcert = NULL; + EVP_PKEY *s_key = NULL, *s_dkey = NULL; + EVP_PKEY *s_key2 = NULL; + X509 *s_cert2 = NULL; + tlsextalpnctx alpn_ctx = { NULL, 0 }; + + if (pledge("stdio rpath inet dns tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + memset(&cfg, 0, sizeof(cfg)); + cfg.keymatexportlen = 20; + cfg.meth = TLS_server_method(); + cfg.naccept = -1; + cfg.port = PORT; + cfg.cert_file = TEST_CERT; + cfg.cert_file2 = TEST_CERT2; + cfg.cert_format = FORMAT_PEM; + cfg.dcert_format = FORMAT_PEM; + cfg.dkey_format = FORMAT_PEM; + cfg.key_format = FORMAT_PEM; + cfg.server_verify = SSL_VERIFY_NONE; + cfg.socket_type = SOCK_STREAM; + cfg.tlscstatp.timeout = -1; + cfg.tlsextcbp.extension_error = + SSL_TLSEXT_ERR_ALERT_WARNING; + + local_argc = argc; + local_argv = argv; + + s_server_init(); + + verify_depth = 0; + + if (options_parse(argc, argv, s_server_options, NULL, NULL) != 0) { + if (cfg.errstr == NULL) + sv_usage(); + goto end; + } + + if (!app_passwd(bio_err, cfg.passarg, + cfg.dpassarg, &pass, &dpass)) { + BIO_printf(bio_err, "Error getting password\n"); + goto end; + } + if (cfg.key_file == NULL) + cfg.key_file = cfg.cert_file; + if (cfg.key_file2 == NULL) + cfg.key_file2 = cfg.cert_file2; + + if (cfg.nocert == 0) { + s_key = load_key(bio_err, cfg.key_file, + cfg.key_format, 0, pass, + "server certificate private key file"); + if (!s_key) { + ERR_print_errors(bio_err); + goto end; + } + s_cert = load_cert(bio_err, cfg.cert_file, + cfg.cert_format, + NULL, "server certificate file"); + + if (!s_cert) { + ERR_print_errors(bio_err); + goto end; + } + if (cfg.tlsextcbp.servername) { + s_key2 = load_key(bio_err, cfg.key_file2, + cfg.key_format, 0, pass, + "second server certificate private key file"); + if (!s_key2) { + ERR_print_errors(bio_err); + goto end; + } + s_cert2 = load_cert(bio_err, cfg.cert_file2, + cfg.cert_format, + NULL, "second server certificate file"); + + if (!s_cert2) { + ERR_print_errors(bio_err); + goto end; + } + } + } + alpn_ctx.data = NULL; + if (cfg.alpn_in) { + unsigned short len; + alpn_ctx.data = next_protos_parse(&len, + cfg.alpn_in); + if (alpn_ctx.data == NULL) + goto end; + alpn_ctx.len = len; + } + + if (cfg.dcert_file) { + + if (cfg.dkey_file == NULL) + cfg.dkey_file = cfg.dcert_file; + + s_dkey = load_key(bio_err, cfg.dkey_file, + cfg.dkey_format, + 0, dpass, "second certificate private key file"); + if (!s_dkey) { + ERR_print_errors(bio_err); + goto end; + } + s_dcert = load_cert(bio_err, cfg.dcert_file, + cfg.dcert_format, + NULL, "second server certificate file"); + + if (!s_dcert) { + ERR_print_errors(bio_err); + goto end; + } + } + if (bio_s_out == NULL) { + if (cfg.quiet && !cfg.debug && + !cfg.msg) { + bio_s_out = BIO_new(BIO_s_null()); + } else { + if (bio_s_out == NULL) + bio_s_out = BIO_new_fp(stdout, BIO_NOCLOSE); + } + } + if (cfg.nocert) { + cfg.cert_file = NULL; + cfg.key_file = NULL; + cfg.dcert_file = NULL; + cfg.dkey_file = NULL; + cfg.cert_file2 = NULL; + cfg.key_file2 = NULL; + } + ctx = SSL_CTX_new(cfg.meth); + if (ctx == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY); + + if (!SSL_CTX_set_min_proto_version(ctx, cfg.min_version)) + goto end; + if (!SSL_CTX_set_max_proto_version(ctx, cfg.max_version)) + goto end; + + if (cfg.session_id_prefix) { + if (strlen(cfg.session_id_prefix) >= 32) + BIO_printf(bio_err, + "warning: id_prefix is too long, only one new session will be possible\n"); + else if (strlen(cfg.session_id_prefix) >= 16) + BIO_printf(bio_err, + "warning: id_prefix is too long if you use SSLv2\n"); + if (!SSL_CTX_set_generate_session_id(ctx, generate_session_id)) { + BIO_printf(bio_err, "error setting 'id_prefix'\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "id_prefix '%s' set.\n", + cfg.session_id_prefix); + } + SSL_CTX_set_quiet_shutdown(ctx, 1); + if (cfg.bugs) + SSL_CTX_set_options(ctx, SSL_OP_ALL); + SSL_CTX_set_options(ctx, cfg.off); + + if (cfg.state) + SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback); + if (cfg.no_cache) + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + else + SSL_CTX_sess_set_cache_size(ctx, 128); + +#ifndef OPENSSL_NO_SRTP + if (cfg.srtp_profiles != NULL) + SSL_CTX_set_tlsext_use_srtp(ctx, cfg.srtp_profiles); +#endif + + if ((!SSL_CTX_load_verify_locations(ctx, cfg.CAfile, + cfg.CApath)) || + (!SSL_CTX_set_default_verify_paths(ctx))) { + /* BIO_printf(bio_err,"X509_load_verify_locations\n"); */ + ERR_print_errors(bio_err); + /* goto end; */ + } + if (cfg.vpm) + SSL_CTX_set1_param(ctx, cfg.vpm); + + if (s_cert2) { + ctx2 = SSL_CTX_new(cfg.meth); + if (ctx2 == NULL) { + ERR_print_errors(bio_err); + goto end; + } + + if (!SSL_CTX_set_min_proto_version(ctx2, + cfg.min_version)) + goto end; + if (!SSL_CTX_set_max_proto_version(ctx2, + cfg.max_version)) + goto end; + SSL_CTX_clear_mode(ctx2, SSL_MODE_AUTO_RETRY); + } + if (ctx2) { + BIO_printf(bio_s_out, "Setting secondary ctx parameters\n"); + + if (cfg.session_id_prefix) { + if (strlen(cfg.session_id_prefix) >= 32) + BIO_printf(bio_err, + "warning: id_prefix is too long, only one new session will be possible\n"); + else if (strlen(cfg.session_id_prefix) >= 16) + BIO_printf(bio_err, + "warning: id_prefix is too long if you use SSLv2\n"); + if (!SSL_CTX_set_generate_session_id(ctx2, + generate_session_id)) { + BIO_printf(bio_err, + "error setting 'id_prefix'\n"); + ERR_print_errors(bio_err); + goto end; + } + BIO_printf(bio_err, "id_prefix '%s' set.\n", + cfg.session_id_prefix); + } + SSL_CTX_set_quiet_shutdown(ctx2, 1); + if (cfg.bugs) + SSL_CTX_set_options(ctx2, SSL_OP_ALL); + SSL_CTX_set_options(ctx2, cfg.off); + + if (cfg.state) + SSL_CTX_set_info_callback(ctx2, apps_ssl_info_callback); + + if (cfg.no_cache) + SSL_CTX_set_session_cache_mode(ctx2, SSL_SESS_CACHE_OFF); + else + SSL_CTX_sess_set_cache_size(ctx2, 128); + + if ((!SSL_CTX_load_verify_locations(ctx2, + cfg.CAfile, cfg.CApath)) || + (!SSL_CTX_set_default_verify_paths(ctx2))) { + ERR_print_errors(bio_err); + } + if (cfg.vpm) + SSL_CTX_set1_param(ctx2, cfg.vpm); + } + if (alpn_ctx.data) + SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx); + + if (cfg.groups_in != NULL) { + if (SSL_CTX_set1_groups_list(ctx, cfg.groups_in) != 1) { + BIO_printf(bio_err, "Failed to set groups '%s'\n", + cfg.groups_in); + goto end; + } + } + +#ifndef OPENSSL_NO_DH + if (!cfg.no_dhe) { + DH *dh = NULL; + + if (cfg.dhfile) + dh = load_dh_param(cfg.dhfile); + else if (cfg.cert_file) + dh = load_dh_param(cfg.cert_file); + + if (dh != NULL) + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); + else + BIO_printf(bio_s_out, "Using auto DH parameters\n"); + (void) BIO_flush(bio_s_out); + + if (dh == NULL) + SSL_CTX_set_dh_auto(ctx, 1); + else if (!SSL_CTX_set_tmp_dh(ctx, dh)) { + BIO_printf(bio_err, + "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } + + if (ctx2) { + if (!cfg.dhfile) { + DH *dh2 = NULL; + + if (cfg.cert_file2 != NULL) + dh2 = load_dh_param( + cfg.cert_file2); + if (dh2 != NULL) { + BIO_printf(bio_s_out, + "Setting temp DH parameters\n"); + (void) BIO_flush(bio_s_out); + + DH_free(dh); + dh = dh2; + } + } + if (dh == NULL) + SSL_CTX_set_dh_auto(ctx2, 1); + else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) { + BIO_printf(bio_err, + "Error setting temp DH parameters\n"); + ERR_print_errors(bio_err); + DH_free(dh); + goto end; + } + } + DH_free(dh); + } +#endif + + if (!cfg.no_ecdhe && cfg.named_curve != NULL) { + EC_KEY *ecdh = NULL; + int nid; + + if ((nid = OBJ_sn2nid(cfg.named_curve)) == 0) { + BIO_printf(bio_err, "unknown curve name (%s)\n", + cfg.named_curve); + goto end; + } + if ((ecdh = EC_KEY_new_by_curve_name(nid)) == NULL) { + BIO_printf(bio_err, "unable to create curve (%s)\n", + cfg.named_curve); + goto end; + } + BIO_printf(bio_s_out, "Setting temp ECDH parameters\n"); + (void) BIO_flush(bio_s_out); + + SSL_CTX_set_tmp_ecdh(ctx, ecdh); + if (ctx2) + SSL_CTX_set_tmp_ecdh(ctx2, ecdh); + EC_KEY_free(ecdh); + } + + if (!set_cert_key_stuff(ctx, s_cert, s_key)) + goto end; + if (ctx2 && !set_cert_key_stuff(ctx2, s_cert2, s_key2)) + goto end; + if (s_dcert != NULL) { + if (!set_cert_key_stuff(ctx, s_dcert, s_dkey)) + goto end; + } + + if (cfg.cipher != NULL) { + if (!SSL_CTX_set_cipher_list(ctx, cfg.cipher)) { + BIO_printf(bio_err, "error setting cipher list\n"); + ERR_print_errors(bio_err); + goto end; + } + if (ctx2 && !SSL_CTX_set_cipher_list(ctx2, + cfg.cipher)) { + BIO_printf(bio_err, "error setting cipher list\n"); + ERR_print_errors(bio_err); + goto end; + } + } + SSL_CTX_set_verify(ctx, cfg.server_verify, verify_callback); + SSL_CTX_set_session_id_context(ctx, + (void *) &s_server_session_id_context, + sizeof s_server_session_id_context); + + /* Set DTLS cookie generation and verification callbacks */ + SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback); + SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback); + + if (ctx2) { + SSL_CTX_set_verify(ctx2, cfg.server_verify, + verify_callback); + SSL_CTX_set_session_id_context(ctx2, + (void *) &s_server_session_id_context, + sizeof s_server_session_id_context); + + cfg.tlsextcbp.biodebug = bio_s_out; + SSL_CTX_set_tlsext_servername_callback(ctx2, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx2, + &cfg.tlsextcbp); + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); + SSL_CTX_set_tlsext_servername_arg(ctx, + &cfg.tlsextcbp); + } + + if (cfg.CAfile != NULL) { + SSL_CTX_set_client_CA_list(ctx, + SSL_load_client_CA_file(cfg.CAfile)); + if (ctx2) + SSL_CTX_set_client_CA_list(ctx2, + SSL_load_client_CA_file(cfg.CAfile)); + } + BIO_printf(bio_s_out, "ACCEPT\n"); + (void) BIO_flush(bio_s_out); + if (cfg.www) + do_server(cfg.port, cfg.socket_type, + &accept_socket, www_body, cfg.context, + cfg.naccept); + else + do_server(cfg.port, cfg.socket_type, + &accept_socket, sv_body, cfg.context, + cfg.naccept); + print_stats(bio_s_out, ctx); + ret = 0; + end: + SSL_CTX_free(ctx); + X509_free(s_cert); + X509_free(s_dcert); + EVP_PKEY_free(s_key); + EVP_PKEY_free(s_dkey); + free(pass); + free(dpass); + X509_VERIFY_PARAM_free(cfg.vpm); + free(cfg.tlscstatp.host); + free(cfg.tlscstatp.port); + free(cfg.tlscstatp.path); + SSL_CTX_free(ctx2); + X509_free(s_cert2); + EVP_PKEY_free(s_key2); + free(alpn_ctx.data); + if (bio_s_out != NULL) { + BIO_free(bio_s_out); + bio_s_out = NULL; + } + + return (ret); +} + +static void +print_stats(BIO *bio, SSL_CTX *ssl_ctx) +{ + BIO_printf(bio, "%4ld items in the session cache\n", + SSL_CTX_sess_number(ssl_ctx)); + BIO_printf(bio, "%4ld client connects (SSL_connect())\n", + SSL_CTX_sess_connect(ssl_ctx)); + BIO_printf(bio, "%4ld client renegotiates (SSL_connect())\n", + SSL_CTX_sess_connect_renegotiate(ssl_ctx)); + BIO_printf(bio, "%4ld client connects that finished\n", + SSL_CTX_sess_connect_good(ssl_ctx)); + BIO_printf(bio, "%4ld server accepts (SSL_accept())\n", + SSL_CTX_sess_accept(ssl_ctx)); + BIO_printf(bio, "%4ld server renegotiates (SSL_accept())\n", + SSL_CTX_sess_accept_renegotiate(ssl_ctx)); + BIO_printf(bio, "%4ld server accepts that finished\n", + SSL_CTX_sess_accept_good(ssl_ctx)); + BIO_printf(bio, "%4ld session cache hits\n", + SSL_CTX_sess_hits(ssl_ctx)); + BIO_printf(bio, "%4ld session cache misses\n", + SSL_CTX_sess_misses(ssl_ctx)); + BIO_printf(bio, "%4ld session cache timeouts\n", + SSL_CTX_sess_timeouts(ssl_ctx)); + BIO_printf(bio, "%4ld callback cache hits\n", + SSL_CTX_sess_cb_hits(ssl_ctx)); + BIO_printf(bio, "%4ld cache full overflows (%ld allowed)\n", + SSL_CTX_sess_cache_full(ssl_ctx), + SSL_CTX_sess_get_cache_size(ssl_ctx)); +} + +static int +sv_body(int s, unsigned char *context) +{ + char *buf = NULL; + int ret = 1; + int k, i; + unsigned long l; + SSL *con = NULL; + BIO *sbio; + struct timeval timeout; + + if ((buf = malloc(bufsize)) == NULL) { + BIO_printf(bio_err, "out of memory\n"); + goto err; + } + if (cfg.nbio) { + if (!cfg.quiet) + BIO_printf(bio_err, "turning on non blocking io\n"); + if (!BIO_socket_nbio(s, 1)) + ERR_print_errors(bio_err); + } + + if (con == NULL) { + con = SSL_new(ctx); + if (cfg.tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + if (cfg.tlsextstatus) { + SSL_CTX_set_tlsext_status_cb(ctx, cert_status_cb); + cfg.tlscstatp.err = bio_err; + SSL_CTX_set_tlsext_status_arg(ctx, + &cfg.tlscstatp); + } + if (context) + SSL_set_session_id_context(con, context, + strlen((char *) context)); + } + SSL_clear(con); + + if (SSL_is_dtls(con)) { + sbio = BIO_new_dgram(s, BIO_NOCLOSE); + + if (cfg.enable_timeouts) { + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_RCV_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, + &timeout); + + timeout.tv_sec = 0; + timeout.tv_usec = DGRAM_SND_TIMEOUT; + BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, + &timeout); + } + if (cfg.socket_mtu > 28) { + SSL_set_options(con, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(con, cfg.socket_mtu - 28); + } else + /* want to do MTU discovery */ + BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL); + + /* turn on cookie exchange */ + SSL_set_options(con, SSL_OP_COOKIE_EXCHANGE); + } else + sbio = BIO_new_socket(s, BIO_NOCLOSE); + + if (cfg.nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + /* SSL_set_fd(con,s); */ + + if (cfg.debug) { + SSL_set_debug(con, 1); + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out); + } + if (cfg.msg) { + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_out); + } + if (cfg.tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + + for (;;) { + int read_from_terminal; + int read_from_sslcon; + struct pollfd pfd[2]; + int ptimeout; + + read_from_terminal = 0; + read_from_sslcon = SSL_pending(con); + + if (!read_from_sslcon) { + pfd[0].fd = fileno(stdin); + pfd[0].events = POLLIN; + pfd[1].fd = s; + pfd[1].events = POLLIN; + + if (SSL_is_dtls(con) && + DTLSv1_get_timeout(con, &timeout)) + ptimeout = timeout.tv_sec * 1000 + + timeout.tv_usec / 1000; + else + ptimeout = -1; + + i = poll(pfd, 2, ptimeout); + + if (SSL_is_dtls(con) && + DTLSv1_handle_timeout(con) > 0) + BIO_printf(bio_err, "TIMEOUT occured\n"); + if (i <= 0) + continue; + if (pfd[0].revents) { + if ((pfd[0].revents & (POLLERR|POLLNVAL))) + continue; + read_from_terminal = 1; + } + if (pfd[1].revents) { + if ((pfd[1].revents & (POLLERR|POLLNVAL))) + continue; + read_from_sslcon = 1; + } + } + if (read_from_terminal) { + if (cfg.crlf) { + int j, lf_num; + + i = read(fileno(stdin), buf, bufsize / 2); + lf_num = 0; + /* both loops are skipped when i <= 0 */ + for (j = 0; j < i; j++) + if (buf[j] == '\n') + lf_num++; + for (j = i - 1; j >= 0; j--) { + buf[j + lf_num] = buf[j]; + if (buf[j] == '\n') { + lf_num--; + i++; + buf[j + lf_num] = '\r'; + } + } + assert(lf_num == 0); + } else + i = read(fileno(stdin), buf, bufsize); + if (!cfg.quiet) { + if ((i <= 0) || (buf[0] == 'Q')) { + BIO_printf(bio_s_out, "DONE\n"); + shutdown(s, SHUT_RD); + close(s); + close_accept_socket(); + ret = -11; + goto err; + } + if ((i <= 0) || (buf[0] == 'q')) { + BIO_printf(bio_s_out, "DONE\n"); + if (!SSL_is_dtls(con)) { + shutdown(s, SHUT_RD); + close(s); + } + /* + * close_accept_socket(); ret= -11; + */ + goto err; + } + if ((buf[0] == 'r') && + ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_renegotiate(con); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; /* 13; */ + continue; + /* + * RE-NEGOTIATE\n"); + */ + } + if ((buf[0] == 'R') && + ((buf[1] == '\n') || (buf[1] == '\r'))) { + SSL_set_verify(con, + SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE, + NULL); + SSL_renegotiate(con); + i = SSL_do_handshake(con); + printf("SSL_do_handshake -> %d\n", i); + i = 0; /* 13; */ + continue; + /* + * RE-NEGOTIATE asking for client + * cert\n"); + */ + } + if (buf[0] == 'P') { + static const char *str = + "Lets print some clear text\n"; + BIO_write(SSL_get_wbio(con), str, + strlen(str)); + } + if (buf[0] == 'S') { + print_stats(bio_s_out, + SSL_get_SSL_CTX(con)); + } + } + l = k = 0; + for (;;) { + /* should do a select for the write */ +#ifdef RENEG + { + static count = 0; + if (++count == 100) { + count = 0; + SSL_renegotiate(con); + } + } +#endif + k = SSL_write(con, &(buf[l]), (unsigned int) i); + switch (SSL_get_error(con, k)) { + case SSL_ERROR_NONE: + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_printf(bio_s_out, "Write BLOCK\n"); + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + BIO_printf(bio_s_out, "ERROR\n"); + ERR_print_errors(bio_err); + ret = 1; + goto err; + /* break; */ + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_s_out, "DONE\n"); + ret = 1; + goto err; + } + if (k <= 0) + continue; + l += k; + i -= k; + if (i <= 0) + break; + } + } + if (read_from_sslcon) { + if (!SSL_is_init_finished(con)) { + i = init_ssl_connection(con); + + if (i < 0) { + ret = 0; + goto err; + } else if (i == 0) { + ret = 1; + goto err; + } + } else { + again: + i = SSL_read(con, (char *) buf, bufsize); + switch (SSL_get_error(con, i)) { + case SSL_ERROR_NONE: { + int len, n; + for (len = 0; len < i;) { + do { + n = write(fileno(stdout), buf + len, i - len); + } while (n == -1 && errno == EINTR); + + if (n == -1) { + BIO_printf(bio_s_out, "ERROR\n"); + goto err; + } + len += n; + } + } + if (SSL_pending(con)) + goto again; + break; + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + BIO_printf(bio_s_out, "Read BLOCK\n"); + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + BIO_printf(bio_s_out, "ERROR\n"); + ERR_print_errors(bio_err); + ret = 1; + goto err; + case SSL_ERROR_ZERO_RETURN: + BIO_printf(bio_s_out, "DONE\n"); + ret = 1; + goto err; + } + } + } + } + err: + if (con != NULL) { + BIO_printf(bio_s_out, "shutting down SSL\n"); + SSL_set_shutdown(con, + SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN); + SSL_free(con); + } + BIO_printf(bio_s_out, "CONNECTION CLOSED\n"); + freezero(buf, bufsize); + if (ret >= 0) + BIO_printf(bio_s_out, "ACCEPT\n"); + return (ret); +} + +static void +close_accept_socket(void) +{ + BIO_printf(bio_err, "shutdown accept socket\n"); + if (accept_socket >= 0) { + shutdown(accept_socket, SHUT_RDWR); + close(accept_socket); + } +} + +static int +init_ssl_connection(SSL *con) +{ + int i; + const char *str; + X509 *peer; + long verify_error; + char buf[BUFSIZ]; + unsigned char *exportedkeymat; + + i = SSL_accept(con); + if (i <= 0) { + if (BIO_sock_should_retry(i)) { + BIO_printf(bio_s_out, "DELAY\n"); + return (1); + } + BIO_printf(bio_err, "ERROR\n"); + verify_error = SSL_get_verify_result(con); + if (verify_error != X509_V_OK) { + BIO_printf(bio_err, "verify error:%s\n", + X509_verify_cert_error_string(verify_error)); + } else + ERR_print_errors(bio_err); + return (0); + } + PEM_write_bio_SSL_SESSION(bio_s_out, SSL_get_session(con)); + + peer = SSL_get_peer_certificate(con); + if (peer != NULL) { + BIO_printf(bio_s_out, "Client certificate\n"); + PEM_write_bio_X509(bio_s_out, peer); + X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof buf); + BIO_printf(bio_s_out, "subject=%s\n", buf); + X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof buf); + BIO_printf(bio_s_out, "issuer=%s\n", buf); + X509_free(peer); + } + if (SSL_get_shared_ciphers(con, buf, sizeof buf) != NULL) + BIO_printf(bio_s_out, "Shared ciphers:%s\n", buf); + str = SSL_CIPHER_get_name(SSL_get_current_cipher(con)); + BIO_printf(bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)"); + +#ifndef OPENSSL_NO_SRTP + { + SRTP_PROTECTION_PROFILE *srtp_profile + = SSL_get_selected_srtp_profile(con); + + if (srtp_profile) + BIO_printf(bio_s_out, + "SRTP Extension negotiated, profile=%s\n", + srtp_profile->name); + } +#endif + if (SSL_cache_hit(con)) + BIO_printf(bio_s_out, "Reused session-id\n"); + BIO_printf(bio_s_out, "Secure Renegotiation IS%s supported\n", + SSL_get_secure_renegotiation_support(con) ? "" : " NOT"); + if (cfg.keymatexportlabel != NULL) { + BIO_printf(bio_s_out, "Keying material exporter:\n"); + BIO_printf(bio_s_out, " Label: '%s'\n", + cfg.keymatexportlabel); + BIO_printf(bio_s_out, " Length: %i bytes\n", + cfg.keymatexportlen); + exportedkeymat = malloc(cfg.keymatexportlen); + if (exportedkeymat != NULL) { + if (!SSL_export_keying_material(con, exportedkeymat, + cfg.keymatexportlen, + cfg.keymatexportlabel, + strlen(cfg.keymatexportlabel), + NULL, 0, 0)) { + BIO_printf(bio_s_out, " Error\n"); + } else { + BIO_printf(bio_s_out, " Keying material: "); + for (i = 0; i < cfg.keymatexportlen; i++) + BIO_printf(bio_s_out, "%02X", + exportedkeymat[i]); + BIO_printf(bio_s_out, "\n"); + } + free(exportedkeymat); + } + } + return (1); +} + +#ifndef OPENSSL_NO_DH +static DH * +load_dh_param(const char *dhfile) +{ + DH *ret = NULL; + BIO *bio; + + if ((bio = BIO_new_file(dhfile, "r")) == NULL) + goto err; + ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + err: + BIO_free(bio); + return (ret); +} +#endif + +static int +www_body(int s, unsigned char *context) +{ + char *buf = NULL; + int ret = 1; + int i, j, k, dot; + SSL *con; + const SSL_CIPHER *c; + BIO *io, *ssl_bio, *sbio; + + buf = malloc(bufsize); + if (buf == NULL) + return (0); + io = BIO_new(BIO_f_buffer()); + ssl_bio = BIO_new(BIO_f_ssl()); + if ((io == NULL) || (ssl_bio == NULL)) + goto err; + + if (cfg.nbio) { + if (!cfg.quiet) + BIO_printf(bio_err, "turning on non blocking io\n"); + if (!BIO_socket_nbio(s, 1)) + ERR_print_errors(bio_err); + } + + /* lets make the output buffer a reasonable size */ + if (!BIO_set_write_buffer_size(io, bufsize)) + goto err; + + if ((con = SSL_new(ctx)) == NULL) + goto err; + if (cfg.tlsextdebug) { + SSL_set_tlsext_debug_callback(con, tlsext_cb); + SSL_set_tlsext_debug_arg(con, bio_s_out); + } + if (context) + SSL_set_session_id_context(con, context, + strlen((char *) context)); + + sbio = BIO_new_socket(s, BIO_NOCLOSE); + if (cfg.nbio_test) { + BIO *test; + + test = BIO_new(BIO_f_nbio_test()); + sbio = BIO_push(test, sbio); + } + SSL_set_bio(con, sbio, sbio); + SSL_set_accept_state(con); + + /* SSL_set_fd(con,s); */ + BIO_set_ssl(ssl_bio, con, BIO_CLOSE); + BIO_push(io, ssl_bio); + + if (cfg.debug) { + SSL_set_debug(con, 1); + BIO_set_callback(SSL_get_rbio(con), bio_dump_callback); + BIO_set_callback_arg(SSL_get_rbio(con), (char *) bio_s_out); + } + if (cfg.msg) { + SSL_set_msg_callback(con, msg_cb); + SSL_set_msg_callback_arg(con, bio_s_out); + } + for (;;) { + i = BIO_gets(io, buf, bufsize - 1); + if (i < 0) { /* error */ + if (!BIO_should_retry(io)) { + if (!cfg.quiet) + ERR_print_errors(bio_err); + goto err; + } else { + if (cfg.debug) { + BIO_printf(bio_s_out, "read R BLOCK\n"); + sleep(1); + } + continue; + } + } else if (i == 0) { /* end of input */ + ret = 1; + goto end; + } + /* else we have data */ + if (((cfg.www == 1) && + (strncmp("GET ", buf, 4) == 0)) || + ((cfg.www == 2) && + (strncmp("GET /stats ", buf, 11) == 0))) { + char *p; + X509 *peer; + STACK_OF(SSL_CIPHER) *sk; + static const char *space = " "; + + BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n"); + BIO_puts(io, "\n"); + BIO_puts(io, "
\n");
+/*			BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
+			BIO_puts(io, "\n");
+			for (i = 0; i < local_argc; i++) {
+				BIO_puts(io, local_argv[i]);
+				BIO_write(io, " ", 1);
+			}
+			BIO_puts(io, "\n");
+
+			BIO_printf(io,
+			    "Secure Renegotiation IS%s supported\n",
+			    SSL_get_secure_renegotiation_support(con) ?
+			    "" : " NOT");
+
+			/*
+			 * The following is evil and should not really be
+			 * done
+			 */
+			BIO_printf(io,
+			    "Ciphers supported in s_server binary\n");
+			sk = SSL_get_ciphers(con);
+			j = sk_SSL_CIPHER_num(sk);
+			for (i = 0; i < j; i++) {
+				c = sk_SSL_CIPHER_value(sk, i);
+				BIO_printf(io, "%-11s:%-25s",
+				    SSL_CIPHER_get_version(c),
+				    SSL_CIPHER_get_name(c));
+				if ((((i + 1) % 2) == 0) && (i + 1 != j))
+					BIO_puts(io, "\n");
+			}
+			BIO_puts(io, "\n");
+			p = SSL_get_shared_ciphers(con, buf, bufsize);
+			if (p != NULL) {
+				BIO_printf(io,
+				    "---\nCiphers common between both SSL end points:\n");
+				j = i = 0;
+				while (*p) {
+					if (*p == ':') {
+						BIO_write(io, space, 26 - j);
+						i++;
+						j = 0;
+						BIO_write(io,
+						    ((i % 3) ?  " " : "\n"), 1);
+					} else {
+						BIO_write(io, p, 1);
+						j++;
+					}
+					p++;
+				}
+				BIO_puts(io, "\n");
+			}
+			BIO_printf(io, (SSL_cache_hit(con)
+				? "---\nReused, "
+				: "---\nNew, "));
+			c = SSL_get_current_cipher(con);
+			BIO_printf(io, "%s, Cipher is %s\n",
+			    SSL_CIPHER_get_version(c),
+			    SSL_CIPHER_get_name(c));
+			SSL_SESSION_print(io, SSL_get_session(con));
+			BIO_printf(io, "---\n");
+			print_stats(io, SSL_get_SSL_CTX(con));
+			BIO_printf(io, "---\n");
+			peer = SSL_get_peer_certificate(con);
+			if (peer != NULL) {
+				BIO_printf(io, "Client certificate\n");
+				X509_print(io, peer);
+				PEM_write_bio_X509(io, peer);
+			} else
+				BIO_puts(io,
+				    "no client certificate available\n");
+			BIO_puts(io, "\r\n\r\n");
+			break;
+		} else if ((cfg.www == 2 ||
+		    cfg.www == 3) &&
+		    (strncmp("GET /", buf, 5) == 0)) {
+			BIO *file;
+			char *p, *e;
+			static const char *text = "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n";
+
+			/* skip the '/' */
+			p = &(buf[5]);
+
+			dot = 1;
+			for (e = p; *e != '\0'; e++) {
+				if (e[0] == ' ')
+					break;
+
+				switch (dot) {
+				case 1:
+					dot = (e[0] == '.') ? 2 : 0;
+					break;
+				case 2:
+					dot = (e[0] == '.') ? 3 : 0;
+					break;
+				case 3:
+					dot = (e[0] == '/' || e[0] == '\\') ?
+					    -1 : 0;
+					break;
+				}
+				if (dot == 0)
+					dot = (e[0] == '/' || e[0] == '\\') ?
+					    1 : 0;
+			}
+			dot = (dot == 3) || (dot == -1);  /* filename contains
+							   * ".." component */
+
+			if (*e == '\0') {
+				BIO_puts(io, text);
+				BIO_printf(io,
+				    "'%s' is an invalid file name\r\n", p);
+				break;
+			}
+			*e = '\0';
+
+			if (dot) {
+				BIO_puts(io, text);
+				BIO_printf(io,
+				    "'%s' contains '..' reference\r\n", p);
+				break;
+			}
+			if (*p == '/') {
+				BIO_puts(io, text);
+				BIO_printf(io,
+				    "'%s' is an invalid path\r\n", p);
+				break;
+			}
+			/* if a directory, do the index thang */
+			if (app_isdir(p) > 0) {
+				BIO_puts(io, text);
+				BIO_printf(io, "'%s' is a directory\r\n", p);
+				break;
+			}
+			if ((file = BIO_new_file(p, "r")) == NULL) {
+				BIO_puts(io, text);
+				BIO_printf(io, "Error opening '%s'\r\n", p);
+				ERR_print_errors(io);
+				break;
+			}
+			if (!cfg.quiet)
+				BIO_printf(bio_err, "FILE:%s\n", p);
+
+			if (cfg.www == 2) {
+				i = strlen(p);
+				if (((i > 5) && (strcmp(&(p[i - 5]), ".html") == 0)) ||
+				    ((i > 4) && (strcmp(&(p[i - 4]), ".php") == 0)) ||
+				    ((i > 4) && (strcmp(&(p[i - 4]), ".htm") == 0)))
+					BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
+				else
+					BIO_puts(io, "HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
+			}
+			/* send the file */
+			for (;;) {
+				i = BIO_read(file, buf, bufsize);
+				if (i <= 0)
+					break;
+
+#ifdef RENEG
+				total_bytes += i;
+				fprintf(stderr, "%d\n", i);
+				if (total_bytes > 3 * 1024) {
+					total_bytes = 0;
+					fprintf(stderr, "RENEGOTIATE\n");
+					SSL_renegotiate(con);
+				}
+#endif
+
+				for (j = 0; j < i;) {
+#ifdef RENEG
+					{
+						static count = 0;
+						if (++count == 13) {
+							SSL_renegotiate(con);
+						}
+					}
+#endif
+					k = BIO_write(io, &(buf[j]), i - j);
+					if (k <= 0) {
+						if (!BIO_should_retry(io))
+							goto write_error;
+						else {
+							BIO_printf(bio_s_out,
+							    "rwrite W BLOCK\n");
+						}
+					} else {
+						j += k;
+					}
+				}
+			}
+	write_error:
+			BIO_free(file);
+			break;
+		}
+	}
+
+	for (;;) {
+		i = (int) BIO_flush(io);
+		if (i <= 0) {
+			if (!BIO_should_retry(io))
+				break;
+		} else
+			break;
+	}
+ end:
+	/* make sure we re-use sessions */
+	SSL_set_shutdown(con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+
+ err:
+
+	if (ret >= 0)
+		BIO_printf(bio_s_out, "ACCEPT\n");
+
+	free(buf);
+	BIO_free_all(io);
+/*	if (ssl_bio != NULL) BIO_free(ssl_bio);*/
+	return (ret);
+}
+
+#define MAX_SESSION_ID_ATTEMPTS 10
+static int
+generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len)
+{
+	unsigned int count = 0;
+	do {
+		arc4random_buf(id, *id_len);
+		/*
+		 * Prefix the session_id with the required prefix. NB: If our
+		 * prefix is too long, clip it - but there will be worse
+		 * effects anyway, eg. the server could only possibly create
+		 * 1 session ID (ie. the prefix!) so all future session
+		 * negotiations will fail due to conflicts.
+		 */
+		memcpy(id, cfg.session_id_prefix,
+		    (strlen(cfg.session_id_prefix) < *id_len) ?
+		    strlen(cfg.session_id_prefix) : *id_len);
+	}
+	while (SSL_has_matching_session_id(ssl, id, *id_len) &&
+	    (++count < MAX_SESSION_ID_ATTEMPTS));
+	if (count >= MAX_SESSION_ID_ATTEMPTS)
+		return 0;
+	return 1;
+}
+
+static int
+ssl_servername_cb(SSL *s, int *ad, void *arg)
+{
+	tlsextctx *p = (tlsextctx *) arg;
+	const char *servername = SSL_get_servername(s,
+	    TLSEXT_NAMETYPE_host_name);
+
+	if (servername && p->biodebug)
+		BIO_printf(p->biodebug, "Hostname in TLS extension: \"%s\"\n",
+		    servername);
+
+	if (!p->servername)
+		return SSL_TLSEXT_ERR_NOACK;
+
+	if (servername) {
+		if (strcmp(servername, p->servername))
+			return p->extension_error;
+		if (ctx2) {
+			BIO_printf(p->biodebug, "Switching server context.\n");
+			SSL_set_SSL_CTX(s, ctx2);
+		}
+	}
+	return SSL_TLSEXT_ERR_OK;
+}
+
+/* Certificate Status callback. This is called when a client includes a
+ * certificate status request extension.
+ *
+ * This is a simplified version. It examines certificates each time and
+ * makes one OCSP responder query for each request.
+ *
+ * A full version would store details such as the OCSP certificate IDs and
+ * minimise the number of OCSP responses by caching them until they were
+ * considered "expired".
+ */
+
+static int
+cert_status_cb(SSL *s, void *arg)
+{
+	tlsextstatusctx *srctx = arg;
+	BIO *err = srctx->err;
+	char *host = NULL, *port = NULL, *path = NULL;
+	int use_ssl;
+	unsigned char *rspder = NULL;
+	int rspderlen;
+	STACK_OF(OPENSSL_STRING) *aia = NULL;
+	X509 *x = NULL;
+	X509_STORE_CTX *inctx = NULL;
+	X509_OBJECT *obj = NULL;
+	OCSP_REQUEST *req = NULL;
+	OCSP_RESPONSE *resp = NULL;
+	OCSP_CERTID *id = NULL;
+	STACK_OF(X509_EXTENSION) *exts;
+	int ret = SSL_TLSEXT_ERR_NOACK;
+	int i;
+
+	if (srctx->verbose)
+		BIO_puts(err, "cert_status: callback called\n");
+	/* Build up OCSP query from server certificate */
+	x = SSL_get_certificate(s);
+	aia = X509_get1_ocsp(x);
+	if (aia) {
+		if (!OCSP_parse_url(sk_OPENSSL_STRING_value(aia, 0),
+		    &host, &port, &path, &use_ssl)) {
+			BIO_puts(err, "cert_status: can't parse AIA URL\n");
+			goto err;
+		}
+		if (srctx->verbose)
+			BIO_printf(err, "cert_status: AIA URL: %s\n",
+			    sk_OPENSSL_STRING_value(aia, 0));
+	} else {
+		if (!srctx->host) {
+			BIO_puts(srctx->err,
+			    "cert_status: no AIA and no default responder URL\n");
+			goto done;
+		}
+		host = srctx->host;
+		path = srctx->path;
+		port = srctx->port;
+		use_ssl = srctx->use_ssl;
+	}
+
+	if ((inctx = X509_STORE_CTX_new()) == NULL)
+		goto err;
+
+	if (!X509_STORE_CTX_init(inctx,
+	    SSL_CTX_get_cert_store(SSL_get_SSL_CTX(s)),
+		NULL, NULL))
+		goto err;
+	if ((obj = X509_OBJECT_new()) == NULL)
+		goto done;
+	if (X509_STORE_get_by_subject(inctx, X509_LU_X509,
+	    X509_get_issuer_name(x), obj) <= 0) {
+		BIO_puts(err,
+		    "cert_status: Can't retrieve issuer certificate.\n");
+		X509_STORE_CTX_cleanup(inctx);
+		goto done;
+	}
+	req = OCSP_REQUEST_new();
+	if (!req)
+		goto err;
+	id = OCSP_cert_to_id(NULL, x, X509_OBJECT_get0_X509(obj));
+	X509_OBJECT_free(obj);
+	obj = NULL;
+	X509_STORE_CTX_free(inctx);
+	inctx = NULL;
+	if (!id)
+		goto err;
+	if (!OCSP_request_add0_id(req, id))
+		goto err;
+	id = NULL;
+	/* Add any extensions to the request */
+	SSL_get_tlsext_status_exts(s, &exts);
+	for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+		X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+		if (!OCSP_REQUEST_add_ext(req, ext, -1))
+			goto err;
+	}
+	resp = process_responder(err, req, host, path, port, use_ssl, NULL,
+	    srctx->timeout);
+	if (!resp) {
+		BIO_puts(err, "cert_status: error querying responder\n");
+		goto done;
+	}
+	rspderlen = i2d_OCSP_RESPONSE(resp, &rspder);
+	if (rspderlen <= 0)
+		goto err;
+	SSL_set_tlsext_status_ocsp_resp(s, rspder, rspderlen);
+	if (srctx->verbose) {
+		BIO_puts(err, "cert_status: ocsp response sent:\n");
+		OCSP_RESPONSE_print(err, resp, 2);
+	}
+	ret = SSL_TLSEXT_ERR_OK;
+ done:
+	X509_STORE_CTX_free(inctx);
+	X509_OBJECT_free(obj);
+	if (ret != SSL_TLSEXT_ERR_OK)
+		ERR_print_errors(err);
+	if (aia) {
+		free(host);
+		free(path);
+		free(port);
+		X509_email_free(aia);
+	}
+	if (id)
+		OCSP_CERTID_free(id);
+	if (req)
+		OCSP_REQUEST_free(req);
+	if (resp)
+		OCSP_RESPONSE_free(resp);
+	return ret;
+ err:
+	ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+	goto done;
+}
+
+static int
+alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
+    const unsigned char *in, unsigned int inlen, void *arg)
+{
+	tlsextalpnctx *alpn_ctx = arg;
+
+	if (!cfg.quiet) {
+		/* We can assume that in is syntactically valid. */
+		unsigned i;
+
+		BIO_printf(bio_s_out,
+		    "ALPN protocols advertised by the client: ");
+		for (i = 0; i < inlen; ) {
+			if (i)
+				BIO_write(bio_s_out, ", ", 2);
+			BIO_write(bio_s_out, &in[i + 1], in[i]);
+			i += in[i] + 1;
+		}
+		BIO_write(bio_s_out, "\n", 1);
+	}
+
+	if (SSL_select_next_proto((unsigned char**)out, outlen, alpn_ctx->data,
+	    alpn_ctx->len, in, inlen) != OPENSSL_NPN_NEGOTIATED)
+		return (SSL_TLSEXT_ERR_NOACK);
+
+	if (!cfg.quiet) {
+		BIO_printf(bio_s_out, "ALPN protocols selected: ");
+		BIO_write(bio_s_out, *out, *outlen);
+		BIO_write(bio_s_out, "\n", 1);
+	}
+
+	return (SSL_TLSEXT_ERR_OK);
+}
diff --git a/apps/openssl/s_socket.c b/apps/openssl/s_socket.c
new file mode 100644
index 0000000..db125c1
--- /dev/null
+++ b/apps/openssl/s_socket.c
@@ -0,0 +1,327 @@
+/* $OpenBSD: s_socket.c,v 1.13 2021/12/06 11:06:58 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+
+#include "s_apps.h"
+
+static int init_server(int *sock, int port, int type);
+static int init_server_long(int *sock, int port, char *ip, int type);
+static int do_accept(int acc_sock, int *sock);
+
+int
+init_client(int *sock, char *host, char *port, int type, int af)
+{
+	struct addrinfo hints, *ai_top, *ai;
+	int i, s = -1;
+
+	memset(&hints, '\0', sizeof(hints));
+	hints.ai_family = af;
+	hints.ai_socktype = type;
+
+	if ((i = getaddrinfo(host, port, &hints, &ai_top)) != 0) {
+		BIO_printf(bio_err, "getaddrinfo: %s\n", gai_strerror(i));
+		return (0);
+	}
+	if (ai_top == NULL || ai_top->ai_addr == NULL) {
+		BIO_printf(bio_err, "getaddrinfo returned no addresses\n");
+		if (ai_top != NULL) {
+			freeaddrinfo(ai_top);
+		}
+		return (0);
+	}
+	for (ai = ai_top; ai != NULL; ai = ai->ai_next) {
+		s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+		if (s == -1) {
+			continue;
+		}
+		if (type == SOCK_STREAM) {
+			i = 0;
+			i = setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
+			    (char *) &i, sizeof(i));
+			if (i == -1) {
+				perror("keepalive");
+				goto out;
+			}
+		}
+		if ((i = connect(s, ai->ai_addr, ai->ai_addrlen)) == 0) {
+			*sock = s;
+			freeaddrinfo(ai_top);
+			return (1);
+		}
+		close(s);
+		s = -1;
+	}
+
+	perror("connect");
+ out:
+	if (s != -1)
+		close(s);
+	freeaddrinfo(ai_top);
+	return (0);
+}
+
+int
+do_server(int port, int type, int *ret,
+    int (*cb)(int s, unsigned char *context),
+    unsigned char *context, int naccept)
+{
+	int sock;
+	int accept_socket = 0;
+	int i;
+
+	if (!init_server(&accept_socket, port, type))
+		return (0);
+
+	if (ret != NULL) {
+		*ret = accept_socket;
+		/* return(1); */
+	}
+	for (;;) {
+		if (type == SOCK_STREAM) {
+			if (do_accept(accept_socket, &sock) == 0) {
+				shutdown(accept_socket, SHUT_RD);
+				close(accept_socket);
+				return (0);
+			}
+		} else
+			sock = accept_socket;
+		i = cb(sock, context);
+		if (type == SOCK_STREAM) {
+			shutdown(sock, SHUT_RDWR);
+			close(sock);
+		}
+		if (naccept != -1)
+			naccept--;
+		if (i < 0 || naccept == 0) {
+			shutdown(accept_socket, SHUT_RDWR);
+			close(accept_socket);
+			return (i);
+		}
+	}
+}
+
+static int
+init_server_long(int *sock, int port, char *ip, int type)
+{
+	int ret = 0;
+	struct sockaddr_in server;
+	int s = -1;
+
+	memset((char *) &server, 0, sizeof(server));
+	server.sin_family = AF_INET;
+	server.sin_port = htons((unsigned short) port);
+	if (ip == NULL)
+		server.sin_addr.s_addr = INADDR_ANY;
+	else
+		memcpy(&server.sin_addr.s_addr, ip, 4);
+
+	if (type == SOCK_STREAM)
+		s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	else			/* type == SOCK_DGRAM */
+		s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+	if (s == -1)
+		goto err;
+#if defined SOL_SOCKET && defined SO_REUSEADDR
+	{
+		int j = 1;
+		if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
+		    (void *) &j, sizeof j) == -1) {
+			perror("setsockopt");
+			goto err;
+		}
+	}
+#endif
+	if (bind(s, (struct sockaddr *) & server, sizeof(server)) == -1) {
+		perror("bind");
+		goto err;
+	}
+	/* Make it 128 for linux */
+	if (type == SOCK_STREAM && listen(s, 128) == -1)
+		goto err;
+	*sock = s;
+	ret = 1;
+ err:
+	if ((ret == 0) && (s != -1)) {
+		shutdown(s, SHUT_RD);
+		close(s);
+	}
+	return (ret);
+}
+
+static int
+init_server(int *sock, int port, int type)
+{
+	return (init_server_long(sock, port, NULL, type));
+}
+
+static int
+do_accept(int acc_sock, int *sock)
+{
+	struct hostent *h1, *h2;
+	static struct sockaddr_in from;
+	socklen_t len;
+	char *host = NULL;
+	int ret;
+
+ redoit:
+
+	memset((char *) &from, 0, sizeof(from));
+	len = sizeof(from);
+	ret = accept(acc_sock, (struct sockaddr *) & from, &len);
+	if (ret == -1) {
+		if (errno == EINTR) {
+			/* check_timeout(); */
+			goto redoit;
+		}
+		fprintf(stderr, "errno=%d ", errno);
+		perror("accept");
+		return (0);
+	}
+
+	h1 = gethostbyaddr((char *) &from.sin_addr.s_addr,
+	    sizeof(from.sin_addr.s_addr), AF_INET);
+	if (h1 == NULL) {
+		BIO_printf(bio_err, "bad gethostbyaddr\n");
+	} else {
+		if ((host = strdup(h1->h_name)) == NULL) {
+			perror("strdup");
+			close(ret);
+			return (0);
+		}
+
+		h2 = gethostbyname(host);
+		if (h2 == NULL) {
+			BIO_printf(bio_err, "gethostbyname failure\n");
+			close(ret);
+			free(host);
+			return (0);
+		}
+		if (h2->h_addrtype != AF_INET) {
+			BIO_printf(bio_err, "gethostbyname addr is not AF_INET\n");
+			close(ret);
+			free(host);
+			return (0);
+		}
+	}
+
+	free(host);
+	*sock = ret;
+	return (1);
+}
+
+int
+extract_host_port(char *str, char **host_ptr, unsigned char *ip,
+    char **port_ptr)
+{
+	char *h, *p;
+
+	h = str;
+	p = strrchr(str, '/');	/* IPv6 host/port */
+	if (p == NULL) {
+		p = strrchr(str, ':');
+	}
+	if (p == NULL) {
+		BIO_printf(bio_err, "no port defined\n");
+		return (0);
+	}
+	*(p++) = '\0';
+
+	if (host_ptr != NULL)
+		*host_ptr = h;
+
+	if (port_ptr != NULL && p != NULL && *p != '\0')
+		*port_ptr = p;
+
+	return (1);
+}
+
+int
+extract_port(char *str, short *port_ptr)
+{
+	int i;
+	const char *errstr;
+	struct servent *s;
+
+	i = strtonum(str, 1, 65535, &errstr);
+	if (!errstr) {
+		*port_ptr = (unsigned short) i;
+	} else {
+		s = getservbyname(str, "tcp");
+		if (s == NULL) {
+			BIO_printf(bio_err, "getservbyname failure for %s\n", str);
+			return (0);
+		}
+		*port_ptr = ntohs((unsigned short) s->s_port);
+	}
+	return (1);
+}
diff --git a/apps/openssl/s_time.c b/apps/openssl/s_time.c
new file mode 100644
index 0000000..7eed6d4
--- /dev/null
+++ b/apps/openssl/s_time.c
@@ -0,0 +1,465 @@
+/* $OpenBSD: s_time.c,v 1.38 2023/03/06 14:32:06 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*-----------------------------------------
+   s_time - SSL client connection timer program
+   Written and donated by Larry Streepy 
+  -----------------------------------------*/
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+
+#include "s_apps.h"
+
+#define SSL_CONNECT_NAME	"localhost:4433"
+
+#define BUFSIZZ 1024*10
+
+#define MYBUFSIZ 1024*8
+
+#define SECONDS	30
+extern int verify_depth;
+
+static void s_time_usage(void);
+static int run_test(SSL *);
+static int benchmark(int);
+static void print_tally_mark(SSL *);
+
+static SSL_CTX *tm_ctx = NULL;
+static const SSL_METHOD *s_time_meth = NULL;
+static long bytes_read = 0;
+
+static struct {
+	int bugs;
+	char *CAfile;
+	char *CApath;
+	char *certfile;
+	char *cipher;
+	char *host;
+	char *keyfile;
+	time_t maxtime;
+	int nbio;
+	int no_shutdown;
+	int perform;
+	int verify;
+	int verify_depth;
+	char *www_path;
+} cfg;
+
+static const struct option s_time_options[] = {
+	{
+		.name = "bugs",
+		.desc = "Enable workarounds for known SSL/TLS bugs",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.bugs,
+	},
+	{
+		.name = "CAfile",
+		.argname = "file",
+		.desc = "File containing trusted certificates in PEM format",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CAfile,
+	},
+	{
+		.name = "CApath",
+		.argname = "path",
+		.desc = "Directory containing trusted certificates",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CApath,
+	},
+	{
+		.name = "cert",
+		.argname = "file",
+		.desc = "Client certificate to use, if one is requested",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.certfile,
+	},
+	{
+		.name = "cipher",
+		.argname = "list",
+		.desc = "List of cipher suites to send to the server",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.cipher,
+	},
+	{
+		.name = "connect",
+		.argname = "host:port",
+		.desc = "Host and port to connect to (default "
+		    SSL_CONNECT_NAME ")",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.host,
+	},
+	{
+		.name = "key",
+		.argname = "file",
+		.desc = "Client private key to use, if one is required",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.keyfile,
+	},
+	{
+		.name = "nbio",
+		.desc = "Use non-blocking I/O",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.nbio,
+	},
+	{
+		.name = "new",
+		.desc = "Use a new session ID for each connection",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.perform,
+		.value = 1,
+	},
+	{
+		.name = "no_shutdown",
+		.desc = "Shut down the connection without notifying the server",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.no_shutdown,
+	},
+	{
+		.name = "reuse",
+		.desc = "Reuse the same session ID for each connection",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.perform,
+		.value = 2,
+	},
+	{
+		.name = "time",
+		.argname = "seconds",
+		.desc = "Duration to perform timing tests for (default 30)",
+		.type = OPTION_ARG_TIME,
+		.opt.tvalue = &cfg.maxtime,
+	},
+	{
+		.name = "verify",
+		.argname = "depth",
+		.desc = "Enable peer certificate verification with given depth",
+		.type = OPTION_ARG_INT,
+		.opt.value = &cfg.verify_depth,
+	},
+	{
+		.name = "www",
+		.argname = "page",
+		.desc = "Page to GET from the server (default none)",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.www_path,
+	},
+	{ NULL },
+};
+
+static void
+s_time_usage(void)
+{
+	fprintf(stderr,
+	    "usage: s_time "
+	    "[-bugs] [-CAfile file] [-CApath directory] [-cert file]\n"
+	    "    [-cipher cipherlist] [-connect host:port] [-key keyfile]\n"
+	    "    [-nbio] [-new] [-no_shutdown] [-reuse] [-time seconds]\n"
+	    "    [-verify depth] [-www page]\n\n");
+	options_usage(s_time_options);
+}
+
+/***********************************************************************
+ * MAIN - main processing area for client
+ *			real name depends on MONOLITH
+ */
+int
+s_time_main(int argc, char **argv)
+{
+	int ret = 1;
+
+	if (pledge("stdio rpath inet dns", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	s_time_meth = TLS_client_method();
+
+	verify_depth = 0;
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.host = SSL_CONNECT_NAME;
+	cfg.maxtime = SECONDS;
+	cfg.perform = 3;
+	cfg.verify = SSL_VERIFY_NONE;
+	cfg.verify_depth = -1;
+
+	if (options_parse(argc, argv, s_time_options, NULL, NULL) != 0) {
+		s_time_usage();
+		goto end;
+	}
+
+	if (cfg.verify_depth >= 0) {
+		cfg.verify = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+		verify_depth = cfg.verify_depth;
+		BIO_printf(bio_err, "verify depth is %d\n", verify_depth);
+	}
+
+	if (cfg.www_path != NULL &&
+	    strlen(cfg.www_path) > MYBUFSIZ - 100) {
+		BIO_printf(bio_err, "-www option too long\n");
+		goto end;
+	}
+
+	if ((tm_ctx = SSL_CTX_new(s_time_meth)) == NULL)
+		return (1);
+
+	SSL_CTX_set_quiet_shutdown(tm_ctx, 1);
+
+	if (cfg.bugs)
+		SSL_CTX_set_options(tm_ctx, SSL_OP_ALL);
+
+	if (cfg.cipher != NULL) {
+		if (!SSL_CTX_set_cipher_list(tm_ctx, cfg.cipher)) {
+			BIO_printf(bio_err, "error setting cipher list\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+
+	SSL_CTX_set_verify(tm_ctx, cfg.verify, NULL);
+
+	if (!set_cert_stuff(tm_ctx, cfg.certfile,
+	    cfg.keyfile))
+		goto end;
+
+	if ((!SSL_CTX_load_verify_locations(tm_ctx, cfg.CAfile,
+	    cfg.CApath)) ||
+	    (!SSL_CTX_set_default_verify_paths(tm_ctx))) {
+		/*
+		 * BIO_printf(bio_err,"error setting default verify
+		 * locations\n");
+		 */
+		ERR_print_errors(bio_err);
+		/* goto end; */
+	}
+
+	/* Loop and time how long it takes to make connections */
+	if (cfg.perform & 1) {
+		printf("Collecting connection statistics for %lld seconds\n",
+		    (long long)cfg.maxtime);
+		if (benchmark(0))
+			goto end;
+	}
+	/*
+	 * Now loop and time connections using the same session id over and
+	 * over
+	 */
+	if (cfg.perform & 2) {
+		printf("\n\nNow timing with session id reuse.\n");
+		if (benchmark(1))
+			goto end;
+	}
+	ret = 0;
+ end:
+	if (tm_ctx != NULL) {
+		SSL_CTX_free(tm_ctx);
+		tm_ctx = NULL;
+	}
+
+	return (ret);
+}
+
+/***********************************************************************
+ * run_test - make a connection, get a file, and shut down the connection
+ *	
+ * Args:
+ *		scon	= SSL connection
+ * Returns:
+ *		1 on success, 0 on error
+ */
+static int
+run_test(SSL *scon)
+{
+	char buf[1024 * 8];
+	struct pollfd pfd[1];
+	BIO *conn;
+	long verify_error;
+	int i, retval;
+
+	if ((conn = BIO_new(BIO_s_connect())) == NULL)
+		return 0;
+	BIO_set_conn_hostname(conn, cfg.host);
+	SSL_set_connect_state(scon);
+	SSL_set_bio(scon, conn, conn);
+	for (;;) {
+		i = SSL_connect(scon);
+		if (BIO_sock_should_retry(i)) {
+			BIO_printf(bio_err, "DELAY\n");
+			pfd[0].fd = SSL_get_fd(scon);
+			pfd[0].events = POLLIN;
+			poll(pfd, 1, -1);
+			continue;
+		}
+		break;
+	}
+	if (i <= 0) {
+		BIO_printf(bio_err, "ERROR\n");
+		verify_error = SSL_get_verify_result(scon);
+		if (verify_error != X509_V_OK)
+			BIO_printf(bio_err, "verify error:%s\n",
+			    X509_verify_cert_error_string(verify_error));
+		else
+			ERR_print_errors(bio_err);
+		return 0;
+	}
+	if (cfg.www_path != NULL) {
+		retval = snprintf(buf, sizeof buf,
+		    "GET %s HTTP/1.0\r\n\r\n", cfg.www_path);
+		if (retval < 0 || retval >= sizeof buf) {
+			fprintf(stderr, "URL too long\n");
+			return 0;
+		}
+		if (SSL_write(scon, buf, retval) != retval)
+			return 0;
+		while ((i = SSL_read(scon, buf, sizeof(buf))) > 0)
+			bytes_read += i;
+	}
+	if (cfg.no_shutdown)
+		SSL_set_shutdown(scon, SSL_SENT_SHUTDOWN |
+		    SSL_RECEIVED_SHUTDOWN);
+	else
+		SSL_shutdown(scon);
+	return 1;
+}
+
+static void
+print_tally_mark(SSL *scon)
+{
+	int ver;
+
+	if (SSL_session_reused(scon))
+		ver = 'r';
+	else {
+		ver = SSL_version(scon);
+		if (ver == TLS1_VERSION)
+			ver = 't';
+		else
+			ver = '*';
+	}
+	fputc(ver, stdout);
+	fflush(stdout);
+}
+
+static int
+benchmark(int reuse_session)
+{
+	double elapsed, totalTime;
+	int nConn = 0;
+	SSL *scon = NULL;
+	int ret = 1;
+
+	if (reuse_session) {
+		/* Get an SSL object so we can reuse the session id */
+		if ((scon = SSL_new(tm_ctx)) == NULL)
+			goto end;
+		if (!run_test(scon)) {
+			fprintf(stderr, "Unable to get connection\n");
+			goto end;
+		}
+		printf("starting\n");
+	}
+
+	nConn = 0;
+	bytes_read = 0;
+
+	app_timer_real(TM_RESET);
+	app_timer_user(TM_RESET);
+	for (;;) {
+		elapsed = app_timer_real(TM_GET);
+		if (elapsed > cfg.maxtime)
+			break;
+		if (scon == NULL) {
+			if ((scon = SSL_new(tm_ctx)) == NULL)
+				goto end;
+		}
+		if (!run_test(scon))
+			goto end;
+		nConn += 1;
+		print_tally_mark(scon);
+		if (!reuse_session) {
+			SSL_free(scon);
+			scon = NULL;
+		}
+	}
+	totalTime = app_timer_user(TM_GET);
+
+	printf("\n\n%d connections in %.2fs; %.2f connections/user sec, bytes read %ld\n",
+	    nConn, totalTime, ((double) nConn / totalTime), bytes_read);
+	printf("%d connections in %.0f real seconds, %ld bytes read per connection\n",
+	    nConn, elapsed, nConn > 0 ? bytes_read / nConn : 0);
+
+	ret = 0;
+ end:
+	SSL_free(scon);
+	return ret;
+}
diff --git a/apps/openssl/sess_id.c b/apps/openssl/sess_id.c
new file mode 100644
index 0000000..c46da54
--- /dev/null
+++ b/apps/openssl/sess_id.c
@@ -0,0 +1,293 @@
+/* $OpenBSD: sess_id.c,v 1.12 2023/03/06 14:32:06 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include "apps.h"
+#include "progs.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct {
+	int cert;
+	char *context;
+	char *infile;
+	int informat;
+	int noout;
+	char *outfile;
+	int outformat;
+	int text;
+} cfg;
+
+static const struct option sess_id_options[] = {
+	{
+		.name = "cert",
+		.desc = "Output certificate if present in session",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.cert,
+	},
+	{
+		.name = "context",
+		.argname = "id",
+		.desc = "Set the session ID context for output",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.context,
+	},
+	{
+		.name = "in",
+		.argname = "file",
+		.desc = "Input file (default stdin)",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.infile,
+	},
+	{
+		.name = "inform",
+		.argname = "format",
+		.desc = "Input format (DER or PEM (default))",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.informat,
+	},
+	{
+		.name = "noout",
+		.desc = "Do not output the encoded session info",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.noout,
+	},
+	{
+		.name = "out",
+		.argname = "file",
+		.desc = "Output file (default stdout)",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.outfile,
+	},
+	{
+		.name = "outform",
+		.argname = "format",
+		.desc = "Output format (DER or PEM (default))",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.outformat,
+	},
+	{
+		.name = "text",
+		.desc = "Print various public or private key components in"
+		    " plain text",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.text,
+	},
+	{ NULL }
+};
+
+static void
+sess_id_usage(void)
+{
+	fprintf(stderr,
+	    "usage: sess_id [-cert] [-context id] [-in file] [-inform fmt] "
+	    "[-noout]\n"
+	    "    [-out file] [-outform fmt] [-text]\n\n");
+	options_usage(sess_id_options);
+}
+
+static SSL_SESSION *load_sess_id(char *file, int format);
+
+int
+sess_id_main(int argc, char **argv)
+{
+	SSL_SESSION *x = NULL;
+	X509 *peer = NULL;
+	int ret = 1, i;
+	BIO *out = NULL;
+
+	if (pledge("stdio cpath wpath rpath", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	cfg.informat = FORMAT_PEM;
+	cfg.outformat = FORMAT_PEM;
+
+	if (options_parse(argc, argv, sess_id_options, NULL, NULL) != 0) {
+		sess_id_usage();
+		return (1);
+	}
+
+	x = load_sess_id(cfg.infile, cfg.informat);
+	if (x == NULL) {
+		goto end;
+	}
+	peer = SSL_SESSION_get0_peer(x);
+
+	if (cfg.context) {
+		size_t ctx_len = strlen(cfg.context);
+		if (ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+			BIO_printf(bio_err, "Context too long\n");
+			goto end;
+		}
+		SSL_SESSION_set1_id_context(x,
+		    (unsigned char *)cfg.context, ctx_len);
+	}
+
+	if (!cfg.noout || cfg.text) {
+		out = BIO_new(BIO_s_file());
+		if (out == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		if (cfg.outfile == NULL) {
+			BIO_set_fp(out, stdout, BIO_NOCLOSE);
+		} else {
+			if (BIO_write_filename(out, cfg.outfile)
+			    <= 0) {
+				perror(cfg.outfile);
+				goto end;
+			}
+		}
+	}
+	if (cfg.text) {
+		SSL_SESSION_print(out, x);
+
+		if (cfg.cert) {
+			if (peer == NULL)
+				BIO_puts(out, "No certificate present\n");
+			else
+				X509_print(out, peer);
+		}
+	}
+	if (!cfg.noout && !cfg.cert) {
+		if (cfg.outformat == FORMAT_ASN1)
+			i = i2d_SSL_SESSION_bio(out, x);
+		else if (cfg.outformat == FORMAT_PEM)
+			i = PEM_write_bio_SSL_SESSION(out, x);
+		else {
+			BIO_printf(bio_err,
+			    "bad output format specified for outfile\n");
+			goto end;
+		}
+		if (!i) {
+			BIO_printf(bio_err, "unable to write SSL_SESSION\n");
+			goto end;
+		}
+	} else if (!cfg.noout && (peer != NULL)) {
+		/* just print the certificate */
+		if (cfg.outformat == FORMAT_ASN1)
+			i = (int) i2d_X509_bio(out, peer);
+		else if (cfg.outformat == FORMAT_PEM)
+			i = PEM_write_bio_X509(out, peer);
+		else {
+			BIO_printf(bio_err,
+			    "bad output format specified for outfile\n");
+			goto end;
+		}
+		if (!i) {
+			BIO_printf(bio_err, "unable to write X509\n");
+			goto end;
+		}
+	}
+	ret = 0;
+
+ end:
+	BIO_free_all(out);
+	SSL_SESSION_free(x);
+
+	return (ret);
+}
+
+static SSL_SESSION *
+load_sess_id(char *infile, int format)
+{
+	SSL_SESSION *x = NULL;
+	BIO *in = NULL;
+
+	in = BIO_new(BIO_s_file());
+	if (in == NULL) {
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	if (infile == NULL)
+		BIO_set_fp(in, stdin, BIO_NOCLOSE);
+	else {
+		if (BIO_read_filename(in, infile) <= 0) {
+			perror(infile);
+			goto end;
+		}
+	}
+	if (format == FORMAT_ASN1)
+		x = d2i_SSL_SESSION_bio(in, NULL);
+	else if (format == FORMAT_PEM)
+		x = PEM_read_bio_SSL_SESSION(in, NULL, NULL, NULL);
+	else {
+		BIO_printf(bio_err,
+		    "bad input format specified for input crl\n");
+		goto end;
+	}
+	if (x == NULL) {
+		BIO_printf(bio_err, "unable to load SSL_SESSION\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+ end:
+	BIO_free(in);
+	return (x);
+}
diff --git a/apps/openssl/smime.c b/apps/openssl/smime.c
new file mode 100644
index 0000000..46bfa08
--- /dev/null
+++ b/apps/openssl/smime.c
@@ -0,0 +1,1103 @@
+/* $OpenBSD: smime.c,v 1.20 2023/04/14 15:27:13 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* S/MIME utility function */
+
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int save_certs(char *signerfile, STACK_OF(X509) *signers);
+
+#define SMIME_OP	0x10
+#define SMIME_IP	0x20
+#define SMIME_SIGNERS	0x40
+#define SMIME_ENCRYPT	(1 | SMIME_OP)
+#define SMIME_DECRYPT	(2 | SMIME_IP)
+#define SMIME_SIGN	(3 | SMIME_OP | SMIME_SIGNERS)
+#define SMIME_VERIFY	(4 | SMIME_IP)
+#define SMIME_PK7OUT	(5 | SMIME_IP | SMIME_OP)
+#define SMIME_RESIGN	(6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
+
+static struct {
+	char *CAfile;
+	char *CApath;
+	char *certfile;
+	const EVP_CIPHER *cipher;
+	char *contfile;
+	int flags;
+	char *from;
+	int indef;
+	char *infile;
+	int informat;
+	char *keyfile;
+	int keyform;
+	int operation;
+	char *outfile;
+	int outformat;
+	char *passargin;
+	char *recipfile;
+	const EVP_MD *sign_md;
+	char *signerfile;
+	STACK_OF(OPENSSL_STRING) *skkeys;
+	STACK_OF(OPENSSL_STRING) *sksigners;
+	char *subject;
+	char *to;
+	X509_VERIFY_PARAM *vpm;
+} cfg;
+
+static const EVP_CIPHER *
+get_cipher_by_name(char *name)
+{
+	if (name == NULL || strcmp(name, "") == 0)
+		return (NULL);
+#ifndef OPENSSL_NO_AES
+	else if (strcmp(name, "aes128") == 0)
+		return EVP_aes_128_cbc();
+	else if (strcmp(name, "aes192") == 0)
+		return EVP_aes_192_cbc();
+	else if (strcmp(name, "aes256") == 0)
+		return EVP_aes_256_cbc();
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	else if (strcmp(name, "camellia128") == 0)
+		return EVP_camellia_128_cbc();
+	else if (strcmp(name, "camellia192") == 0)
+		return EVP_camellia_192_cbc();
+	else if (strcmp(name, "camellia256") == 0)
+		return EVP_camellia_256_cbc();
+#endif
+#ifndef OPENSSL_NO_DES
+	else if (strcmp(name, "des") == 0)
+		return EVP_des_cbc();
+	else if (strcmp(name, "des3") == 0)
+		return EVP_des_ede3_cbc();
+#endif
+#ifndef OPENSSL_NO_RC2
+	else if (!strcmp(name, "rc2-40"))
+		return EVP_rc2_40_cbc();
+	else if (!strcmp(name, "rc2-64"))
+		return EVP_rc2_64_cbc();
+	else if (!strcmp(name, "rc2-128"))
+		return EVP_rc2_cbc();
+#endif
+	else
+		return NULL;
+}
+
+static int
+smime_opt_cipher(int argc, char **argv, int *argsused)
+{
+	char *name = argv[0];
+
+	if (*name++ != '-')
+		return (1);
+
+	if ((cfg.cipher = get_cipher_by_name(name)) == NULL)
+		if ((cfg.cipher = EVP_get_cipherbyname(name)) == NULL)
+			return (1);
+
+	*argsused = 1;
+	return (0);
+}
+
+static int
+smime_opt_inkey(char *arg)
+{
+	if (cfg.keyfile == NULL) {
+		cfg.keyfile = arg;
+		return (0);
+	}
+
+	if (cfg.signerfile == NULL) {
+		BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+		return (1);
+	}
+
+	if (cfg.sksigners == NULL) {
+		if ((cfg.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+			return (1);
+	}
+	if (!sk_OPENSSL_STRING_push(cfg.sksigners,
+	    cfg.signerfile))
+		return (1);
+
+	cfg.signerfile = NULL;
+
+	if (cfg.skkeys == NULL) {
+		if ((cfg.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+			return (1);
+	}
+	if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
+		return (1);
+
+	cfg.keyfile = arg;
+	return (0);
+}
+
+static int
+smime_opt_md(char *arg)
+{
+	if ((cfg.sign_md = EVP_get_digestbyname(arg)) == NULL) {
+		BIO_printf(bio_err, "Unknown digest %s\n", arg);
+		return (1);
+	}
+	return (0);
+}
+
+static int
+smime_opt_signer(char *arg)
+{
+	if (cfg.signerfile == NULL) {
+		cfg.signerfile = arg;
+		return (0);
+	}
+
+	if (cfg.sksigners == NULL) {
+		if ((cfg.sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
+			return (1);
+	}
+	if (!sk_OPENSSL_STRING_push(cfg.sksigners,
+	    cfg.signerfile))
+		return (1);
+
+	if (cfg.keyfile == NULL)
+		cfg.keyfile = cfg.signerfile;
+
+	if (cfg.skkeys == NULL) {
+		if ((cfg.skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
+			return (1);
+	}
+	if (!sk_OPENSSL_STRING_push(cfg.skkeys, cfg.keyfile))
+		return (1);
+
+	cfg.keyfile = NULL;
+
+	cfg.signerfile = arg;
+	return (0);
+}
+
+static int
+smime_opt_verify_param(int argc, char **argv, int *argsused)
+{
+	int oargc = argc;
+	int badarg = 0;
+
+	if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm))
+		return (1);
+	if (badarg)
+		return (1);
+
+	*argsused = oargc - argc;
+
+	return (0);
+}
+
+static const struct option smime_options[] = {
+#ifndef OPENSSL_NO_AES
+	{
+		.name = "aes128",
+		.desc = "Encrypt PEM output with CBC AES",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "aes192",
+		.desc = "Encrypt PEM output with CBC AES",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "aes256",
+		.desc = "Encrypt PEM output with CBC AES",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	{
+		.name = "camellia128",
+		.desc = "Encrypt PEM output with CBC Camellia",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "camellia192",
+		.desc = "Encrypt PEM output with CBC Camellia",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "camellia256",
+		.desc = "Encrypt PEM output with CBC Camellia",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+#endif
+#ifndef OPENSSL_NO_DES
+	{
+		.name = "des",
+		.desc = "Encrypt with DES",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "des3",
+		.desc = "Encrypt with triple DES",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+#endif
+#ifndef OPENSSL_NO_RC2
+	{
+		.name = "rc2-40",
+		.desc = "Encrypt with RC2-40 (default)",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "rc2-64",
+		.desc = "Encrypt with RC2-64",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{
+		.name = "rc2-128",
+		.desc = "Encrypt with RC2-128",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+#endif
+	{
+		.name = "CAfile",
+		.argname = "file",
+		.desc = "Certificate Authority file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CAfile,
+	},
+	{
+		.name = "CApath",
+		.argname = "path",
+		.desc = "Certificate Authority path",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CApath,
+	},
+	{
+		.name = "binary",
+		.desc = "Do not translate message to text",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_BINARY,
+	},
+	{
+		.name = "certfile",
+		.argname = "file",
+		.desc = "Other certificates file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.certfile,
+	},
+	{
+		.name = "content",
+		.argname = "file",
+		.desc = "Supply or override content for detached signature",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.contfile,
+	},
+	{
+		.name = "crlfeol",
+		.desc = "Use CRLF as EOL termination instead of CR only",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_CRLFEOL,
+	},
+	{
+		.name = "decrypt",
+		.desc = "Decrypt encrypted message",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_DECRYPT,
+	},
+	{
+		.name = "encrypt",
+		.desc = "Encrypt message",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_ENCRYPT,
+	},
+	{
+		.name = "from",
+		.argname = "addr",
+		.desc = "From address",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.from,
+	},
+	{
+		.name = "in",
+		.argname = "file",
+		.desc = "Input file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.infile,
+	},
+	{
+		.name = "indef",
+		.desc = "Same as -stream",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.indef,
+		.value = 1,
+	},
+	{
+		.name = "inform",
+		.argname = "fmt",
+		.desc = "Input format (DER, PEM or SMIME (default))",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.informat,
+	},
+	{
+		.name = "inkey",
+		.argname = "file",
+		.desc = "Input key file",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = smime_opt_inkey,
+	},
+	{
+		.name = "keyform",
+		.argname = "fmt",
+		.desc = "Input key format (DER or PEM (default))",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.keyform,
+	},
+	{
+		.name = "md",
+		.argname = "digest",
+		.desc = "Digest to use when signing or resigning",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = smime_opt_md,
+	},
+	{
+		.name = "noattr",
+		.desc = "Do not include any signed attributes",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOATTR,
+	},
+	{
+		.name = "nocerts",
+		.desc = "Do not include signer's certificate when signing",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOCERTS,
+	},
+	{
+		.name = "nochain",
+		.desc = "Do not chain verification of signer's certificates",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOCHAIN,
+	},
+	{
+		.name = "nodetach",
+		.desc = "Use opaque signing",
+		.type = OPTION_VALUE_AND,
+		.opt.value = &cfg.flags,
+		.value = ~PKCS7_DETACHED,
+	},
+	{
+		.name = "noindef",
+		.desc = "Disable streaming I/O",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.indef,
+		.value = 0,
+	},
+	{
+		.name = "nointern",
+		.desc = "Do not search certificates in message for signer",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOINTERN,
+	},
+	{
+		.name = "nooldmime",
+		.desc = "Output old S/MIME content type",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOOLDMIMETYPE,
+	},
+	{
+		.name = "nosigs",
+		.desc = "Do not verify message signature",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOSIGS,
+	},
+	{
+		.name = "nosmimecap",
+		.desc = "Omit the SMIMECapabilities attribute",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOSMIMECAP,
+	},
+	{
+		.name = "noverify",
+		.desc = "Do not verify signer's certificate",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_NOVERIFY,
+	},
+	{
+		.name = "out",
+		.argname = "file",
+		.desc = "Output file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.outfile,
+	},
+	{
+		.name = "outform",
+		.argname = "fmt",
+		.desc = "Output format (DER, PEM or SMIME (default))",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.outformat,
+	},
+	{
+		.name = "passin",
+		.argname = "src",
+		.desc = "Private key password source",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.passargin,
+	},
+	{
+		.name = "pk7out",
+		.desc = "Output PKCS#7 structure",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_PK7OUT,
+	},
+	{
+		.name = "recip",
+		.argname = "file",
+		.desc = "Recipient certificate file for decryption",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.recipfile,
+	},
+	{
+		.name = "resign",
+		.desc = "Resign a signed message",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_RESIGN,
+	},
+	{
+		.name = "sign",
+		.desc = "Sign message",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_SIGN,
+	},
+	{
+		.name = "signer",
+		.argname = "file",
+		.desc = "Signer certificate file",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = smime_opt_signer,
+	},
+	{
+		.name = "stream",
+		.desc = "Enable streaming I/O",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.indef,
+		.value = 1,
+	},
+	{
+		.name = "subject",
+		.argname = "s",
+		.desc = "Subject",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.subject,
+	},
+	{
+		.name = "text",
+		.desc = "Include or delete text MIME headers",
+		.type = OPTION_VALUE_OR,
+		.opt.value = &cfg.flags,
+		.value = PKCS7_TEXT,
+	},
+	{
+		.name = "to",
+		.argname = "addr",
+		.desc = "To address",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.to,
+	},
+	{
+		.name = "verify",
+		.desc = "Verify signed message",
+		.type = OPTION_VALUE,
+		.opt.value = &cfg.operation,
+		.value = SMIME_VERIFY,
+	},
+	{
+		.name = "check_ss_sig",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "crl_check",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "crl_check_all",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "extended_crl",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "ignore_critical",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "issuer_checks",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "policy_check",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = "x509_strict",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_verify_param,
+	},
+	{
+		.name = NULL,
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = smime_opt_cipher,
+	},
+	{ NULL },
+};
+
+static const struct option verify_shared_options[] = {
+	{
+		.name = "check_ss_sig",
+		.desc = "Check the root CA self-signed certificate signature",
+	},
+	{
+		.name = "crl_check",
+		.desc = "Enable CRL checking for the leaf certificate",
+	},
+	{
+		.name = "crl_check_all",
+		.desc = "Enable CRL checking for the entire certificate chain",
+	},
+	{
+		.name = "extended_crl",
+		.desc = "Enable extended CRL support",
+	},
+	{
+		.name = "ignore_critical",
+		.desc = "Disable critical extension checking",
+	},
+	{
+		.name = "issuer_checks",
+		.desc = "Enable debugging of certificate issuer checks",
+	},
+	{
+		.name = "policy_check",
+		.desc = "Enable certificate policy checking",
+	},
+	{
+		.name = "x509_strict",
+		.desc = "Use strict X.509 rules (disables workarounds)",
+	},
+	{ NULL },
+};
+
+static void
+smime_usage(void)
+{
+	fprintf(stderr, "usage: smime "
+	    "[-aes128 | -aes192 | -aes256 | -des |\n"
+	    "    -des3 | -rc2-40 | -rc2-64 | -rc2-128] [-binary]\n"
+	    "    [-CAfile file] [-CApath directory] [-certfile file]\n"
+	    "    [-content file]\n"
+	    "    [-decrypt] [-encrypt]\n"
+	    "    [-from addr] [-in file] [-indef]\n"
+	    "    [-inform der | pem | smime] [-inkey file]\n"
+	    "    [-keyform der | pem] [-md digest] [-noattr] [-nocerts]\n"
+	    "    [-nochain] [-nodetach] [-noindef] [-nointern] [-nosigs]\n"
+	    "    [-nosmimecap] [-noverify] [-out file]\n"
+	    "    [-outform der | pem | smime] [-passin arg] [-pk7out]\n"
+	    "    [-recip file] [-resign] [-sign]\n"
+	    "    [-signer file] [-stream] [-subject s] [-text] [-to addr]\n"
+	    "    [-verify] [cert.pem ...]\n\n");
+
+	options_usage(smime_options);
+
+	fprintf(stderr, "\nVerification options:\n\n");
+	options_usage(verify_shared_options);
+}
+
+int
+smime_main(int argc, char **argv)
+{
+	int ret = 0;
+	char **args;
+	int argsused = 0;
+	const char *inmode = "r", *outmode = "w";
+	PKCS7 *p7 = NULL;
+	X509_STORE *store = NULL;
+	X509 *cert = NULL, *recip = NULL, *signer = NULL;
+	EVP_PKEY *key = NULL;
+	STACK_OF(X509) *encerts = NULL, *other = NULL;
+	BIO *in = NULL, *out = NULL, *indata = NULL;
+	int badarg = 0;
+	char *passin = NULL;
+
+	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.flags = PKCS7_DETACHED;
+	cfg.informat = FORMAT_SMIME;
+	cfg.outformat = FORMAT_SMIME;
+	cfg.keyform = FORMAT_PEM;
+	if (options_parse(argc, argv, smime_options, NULL, &argsused) != 0) {
+		goto argerr;
+	}
+	args = argv + argsused;
+	ret = 1;
+
+	if (!(cfg.operation & SMIME_SIGNERS) &&
+	    (cfg.skkeys != NULL || cfg.sksigners != NULL)) {
+		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
+		goto argerr;
+	}
+	if (cfg.operation & SMIME_SIGNERS) {
+		/* Check to see if any final signer needs to be appended */
+		if (cfg.keyfile != NULL &&
+		    cfg.signerfile == NULL) {
+			BIO_puts(bio_err, "Illegal -inkey without -signer\n");
+			goto argerr;
+		}
+		if (cfg.signerfile != NULL) {
+			if (cfg.sksigners == NULL) {
+				if ((cfg.sksigners =
+				    sk_OPENSSL_STRING_new_null()) == NULL)
+					goto end;
+			}
+			if (!sk_OPENSSL_STRING_push(cfg.sksigners,
+			    cfg.signerfile))
+				goto end;
+			if (cfg.skkeys == NULL) {
+				if ((cfg.skkeys =
+				    sk_OPENSSL_STRING_new_null()) == NULL)
+					goto end;
+			}
+			if (cfg.keyfile == NULL)
+				cfg.keyfile = cfg.signerfile;
+			if (!sk_OPENSSL_STRING_push(cfg.skkeys,
+			    cfg.keyfile))
+				goto end;
+		}
+		if (cfg.sksigners == NULL) {
+			BIO_printf(bio_err,
+			    "No signer certificate specified\n");
+			badarg = 1;
+		}
+		cfg.signerfile = NULL;
+		cfg.keyfile = NULL;
+	} else if (cfg.operation == SMIME_DECRYPT) {
+		if (cfg.recipfile == NULL &&
+		    cfg.keyfile == NULL) {
+			BIO_printf(bio_err,
+			    "No recipient certificate or key specified\n");
+			badarg = 1;
+		}
+	} else if (cfg.operation == SMIME_ENCRYPT) {
+		if (*args == NULL) {
+			BIO_printf(bio_err,
+			    "No recipient(s) certificate(s) specified\n");
+			badarg = 1;
+		}
+	} else if (!cfg.operation) {
+		badarg = 1;
+	}
+
+	if (badarg) {
+ argerr:
+		smime_usage();
+		goto end;
+	}
+
+	if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+	}
+	ret = 2;
+
+	if (!(cfg.operation & SMIME_SIGNERS))
+		cfg.flags &= ~PKCS7_DETACHED;
+
+	if (cfg.operation & SMIME_OP) {
+		if (cfg.outformat == FORMAT_ASN1)
+			outmode = "wb";
+	} else {
+		if (cfg.flags & PKCS7_BINARY)
+			outmode = "wb";
+	}
+
+	if (cfg.operation & SMIME_IP) {
+		if (cfg.informat == FORMAT_ASN1)
+			inmode = "rb";
+	} else {
+		if (cfg.flags & PKCS7_BINARY)
+			inmode = "rb";
+	}
+
+	if (cfg.operation == SMIME_ENCRYPT) {
+		if (cfg.cipher == NULL) {
+#ifndef OPENSSL_NO_RC2
+			cfg.cipher = EVP_rc2_40_cbc();
+#else
+			BIO_printf(bio_err, "No cipher selected\n");
+			goto end;
+#endif
+		}
+		if ((encerts = sk_X509_new_null()) == NULL)
+			goto end;
+		while (*args != NULL) {
+			if ((cert = load_cert(bio_err, *args, FORMAT_PEM,
+			    NULL, "recipient certificate file")) == NULL) {
+				goto end;
+			}
+			if (!sk_X509_push(encerts, cert))
+				goto end;
+			cert = NULL;
+			args++;
+		}
+	}
+	if (cfg.certfile != NULL) {
+		if ((other = load_certs(bio_err, cfg.certfile,
+		    FORMAT_PEM, NULL, "certificate file")) == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+	if (cfg.recipfile != NULL &&
+	    (cfg.operation == SMIME_DECRYPT)) {
+		if ((recip = load_cert(bio_err, cfg.recipfile,
+		    FORMAT_PEM, NULL, "recipient certificate file")) == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+	if (cfg.operation == SMIME_DECRYPT) {
+		if (cfg.keyfile == NULL)
+			cfg.keyfile = cfg.recipfile;
+	} else if (cfg.operation == SMIME_SIGN) {
+		if (cfg.keyfile == NULL)
+			cfg.keyfile = cfg.signerfile;
+	} else {
+		cfg.keyfile = NULL;
+	}
+
+	if (cfg.keyfile != NULL) {
+		key = load_key(bio_err, cfg.keyfile,
+		    cfg.keyform, 0, passin, "signing key file");
+		if (key == NULL)
+			goto end;
+	}
+	if (cfg.infile != NULL) {
+		if ((in = BIO_new_file(cfg.infile, inmode)) == NULL) {
+			BIO_printf(bio_err,
+			    "Can't open input file %s\n", cfg.infile);
+			goto end;
+		}
+	} else {
+		if ((in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL)
+			goto end;
+	}
+
+	if (cfg.operation & SMIME_IP) {
+		if (cfg.informat == FORMAT_SMIME)
+			p7 = SMIME_read_PKCS7(in, &indata);
+		else if (cfg.informat == FORMAT_PEM)
+			p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+		else if (cfg.informat == FORMAT_ASN1)
+			p7 = d2i_PKCS7_bio(in, NULL);
+		else {
+			BIO_printf(bio_err,
+			    "Bad input format for PKCS#7 file\n");
+			goto end;
+		}
+
+		if (p7 == NULL) {
+			BIO_printf(bio_err, "Error reading S/MIME message\n");
+			goto end;
+		}
+		if (cfg.contfile != NULL) {
+			BIO_free(indata);
+			if ((indata = BIO_new_file(cfg.contfile,
+			    "rb")) == NULL) {
+				BIO_printf(bio_err,
+				    "Can't read content file %s\n",
+				    cfg.contfile);
+				goto end;
+			}
+		}
+	}
+	if (cfg.outfile != NULL) {
+		if ((out = BIO_new_file(cfg.outfile, outmode)) == NULL) {
+			BIO_printf(bio_err,
+			    "Can't open output file %s\n",
+			    cfg.outfile);
+			goto end;
+		}
+	} else {
+		if ((out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
+			goto end;
+	}
+
+	if (cfg.operation == SMIME_VERIFY) {
+		if ((store = setup_verify(bio_err, cfg.CAfile,
+		    cfg.CApath)) == NULL)
+			goto end;
+		if (cfg.vpm != NULL) {
+			if (!X509_STORE_set1_param(store, cfg.vpm))
+				goto end;
+		}
+	}
+	ret = 3;
+
+	if (cfg.operation == SMIME_ENCRYPT) {
+		if (cfg.indef)
+			cfg.flags |= PKCS7_STREAM;
+		p7 = PKCS7_encrypt(encerts, in, cfg.cipher,
+		    cfg.flags);
+	} else if (cfg.operation & SMIME_SIGNERS) {
+		int i;
+		/*
+		 * If detached data content we only enable streaming if
+		 * S/MIME output format.
+		 */
+		if (cfg.operation == SMIME_SIGN) {
+			if (cfg.flags & PKCS7_DETACHED) {
+				if (cfg.outformat == FORMAT_SMIME)
+					cfg.flags |= PKCS7_STREAM;
+			} else if (cfg.indef) {
+				cfg.flags |= PKCS7_STREAM;
+			}
+			cfg.flags |= PKCS7_PARTIAL;
+			p7 = PKCS7_sign(NULL, NULL, other, in,
+			    cfg.flags);
+			if (p7 == NULL)
+				goto end;
+		} else {
+			cfg.flags |= PKCS7_REUSE_DIGEST;
+		}
+		for (i = 0; i < sk_OPENSSL_STRING_num(cfg.sksigners); i++) {
+			cfg.signerfile =
+			    sk_OPENSSL_STRING_value(cfg.sksigners, i);
+			cfg.keyfile =
+			    sk_OPENSSL_STRING_value(cfg.skkeys, i);
+			signer = load_cert(bio_err, cfg.signerfile,
+			    FORMAT_PEM, NULL, "signer certificate");
+			if (signer == NULL)
+				goto end;
+			key = load_key(bio_err, cfg.keyfile,
+			    cfg.keyform, 0, passin,
+			    "signing key file");
+			if (key == NULL)
+				goto end;
+			if (PKCS7_sign_add_signer(p7, signer, key,
+			    cfg.sign_md, cfg.flags) == NULL)
+				goto end;
+			X509_free(signer);
+			signer = NULL;
+			EVP_PKEY_free(key);
+			key = NULL;
+		}
+		/* If not streaming or resigning finalize structure */
+		if ((cfg.operation == SMIME_SIGN) &&
+		    !(cfg.flags & PKCS7_STREAM)) {
+			if (!PKCS7_final(p7, in, cfg.flags))
+				goto end;
+		}
+	}
+	if (p7 == NULL) {
+		BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
+		goto end;
+	}
+	ret = 4;
+
+	if (cfg.operation == SMIME_DECRYPT) {
+		if (!PKCS7_decrypt(p7, key, recip, out, cfg.flags)) {
+			BIO_printf(bio_err,
+			    "Error decrypting PKCS#7 structure\n");
+			goto end;
+		}
+	} else if (cfg.operation == SMIME_VERIFY) {
+		STACK_OF(X509) *signers;
+		if (PKCS7_verify(p7, other, store, indata, out,
+		    cfg.flags)) {
+			BIO_printf(bio_err, "Verification successful\n");
+		} else {
+			BIO_printf(bio_err, "Verification failure\n");
+			goto end;
+		}
+		if ((signers = PKCS7_get0_signers(p7, other,
+		    cfg.flags)) == NULL)
+			goto end;
+		if (!save_certs(cfg.signerfile, signers)) {
+			BIO_printf(bio_err, "Error writing signers to %s\n",
+			    cfg.signerfile);
+			sk_X509_free(signers);
+			ret = 5;
+			goto end;
+		}
+		sk_X509_free(signers);
+	} else if (cfg.operation == SMIME_PK7OUT) {
+		PEM_write_bio_PKCS7(out, p7);
+	} else {
+		if (cfg.to != NULL)
+			BIO_printf(out, "To: %s\n", cfg.to);
+		if (cfg.from != NULL)
+			BIO_printf(out, "From: %s\n", cfg.from);
+		if (cfg.subject != NULL)
+			BIO_printf(out, "Subject: %s\n", cfg.subject);
+		if (cfg.outformat == FORMAT_SMIME) {
+			if (cfg.operation == SMIME_RESIGN) {
+				if (!SMIME_write_PKCS7(out, p7, indata,
+				    cfg.flags))
+					goto end;
+			} else {
+				if (!SMIME_write_PKCS7(out, p7, in,
+				    cfg.flags))
+					goto end;
+			}
+		} else if (cfg.outformat == FORMAT_PEM) {
+			if (!PEM_write_bio_PKCS7_stream(out, p7, in,
+			    cfg.flags))
+				goto end;
+		} else if (cfg.outformat == FORMAT_ASN1) {
+			if (!i2d_PKCS7_bio_stream(out, p7, in,
+			    cfg.flags))
+				goto end;
+		} else {
+			BIO_printf(bio_err,
+			    "Bad output format for PKCS#7 file\n");
+			goto end;
+		}
+	}
+
+	ret = 0;
+
+ end:
+	if (ret)
+		ERR_print_errors(bio_err);
+	sk_X509_pop_free(encerts, X509_free);
+	sk_X509_pop_free(other, X509_free);
+	X509_VERIFY_PARAM_free(cfg.vpm);
+	sk_OPENSSL_STRING_free(cfg.sksigners);
+	sk_OPENSSL_STRING_free(cfg.skkeys);
+	X509_STORE_free(store);
+	X509_free(cert);
+	X509_free(recip);
+	X509_free(signer);
+	EVP_PKEY_free(key);
+	PKCS7_free(p7);
+	BIO_free(in);
+	BIO_free(indata);
+	BIO_free_all(out);
+	free(passin);
+
+	return (ret);
+}
+
+static int
+save_certs(char *signerfile, STACK_OF(X509) *signers)
+{
+	int i;
+	BIO *tmp;
+
+	if (signerfile == NULL)
+		return 1;
+	tmp = BIO_new_file(signerfile, "w");
+	if (tmp == NULL)
+		return 0;
+	for (i = 0; i < sk_X509_num(signers); i++)
+		PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
+	BIO_free(tmp);
+
+	return 1;
+}
diff --git a/apps/openssl/speed.c b/apps/openssl/speed.c
new file mode 100644
index 0000000..4877f17
--- /dev/null
+++ b/apps/openssl/speed.c
@@ -0,0 +1,2136 @@
+/* $OpenBSD: speed.c,v 1.34 2023/07/27 07:01:50 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The ECDH and ECDSA speed test software is originally written by
+ * Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+
+/* most of this code has been pilfered from my libdes speed.c program */
+
+#ifndef OPENSSL_NO_SPEED
+
+#define SECONDS		3
+#define RSA_SECONDS	10
+#define DSA_SECONDS	10
+#define ECDSA_SECONDS   10
+#define ECDH_SECONDS    10
+
+#define MAX_UNALIGN	16
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_AES
+#include 
+#endif
+#ifndef OPENSSL_NO_BF
+#include 
+#endif
+#ifndef OPENSSL_NO_CAST
+#include 
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+#include 
+#endif
+#ifndef OPENSSL_NO_DES
+#include 
+#endif
+#include 
+#include 
+#include 
+#ifndef OPENSSL_NO_HMAC
+#include 
+#endif
+#ifndef OPENSSL_NO_IDEA
+#include 
+#endif
+#ifndef OPENSSL_NO_MD4
+#include 
+#endif
+#ifndef OPENSSL_NO_MD5
+#include 
+#endif
+#ifndef OPENSSL_NO_RC2
+#include 
+#endif
+#ifndef OPENSSL_NO_RC4
+#include 
+#endif
+#include 
+#ifndef OPENSSL_NO_RIPEMD
+#include 
+#endif
+#ifndef OPENSSL_NO_SHA
+#include 
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+#include 
+#endif
+
+#include "./testdsa.h"
+#include "./testrsa.h"
+
+#define BUFSIZE	(1024*8+64)
+int run = 0;
+
+static int mr = 0;
+static int usertime = 1;
+
+static double Time_F(int s);
+static void print_message(const char *s, long num, int length);
+static void
+pkey_print_message(const char *str, const char *str2,
+    long num, int bits, int sec);
+static void print_result(int alg, int run_no, int count, double time_used);
+#ifndef _WIN32
+static int do_multi(int multi);
+#else
+void speed_signal(int sigcatch, void (*func)(int sigraised));
+unsigned int speed_alarm(unsigned int seconds);
+void speed_alarm_free(int run);
+#define SIGALRM		14
+#define signal(sigcatch, func)	speed_signal((sigcatch), (func))
+#define alarm(seconds)		speed_alarm((seconds))
+#endif
+
+#define ALGOR_NUM	32
+#define SIZE_NUM	5
+#define RSA_NUM		4
+#define DSA_NUM		3
+
+#define EC_NUM       6
+#define MAX_ECDH_SIZE 256
+
+static const char *names[ALGOR_NUM] = {
+	"md2", "md4", "md5", "hmac(md5)", "sha1", "rmd160",
+	"rc4", "des cbc", "des ede3", "idea cbc", "seed cbc",
+	"rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
+	"aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
+	"camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
+	"evp", "sha256", "sha512", "whirlpool",
+	"aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
+	"aes-128 gcm", "aes-256 gcm", "chacha20 poly1305",
+};
+static double results[ALGOR_NUM][SIZE_NUM];
+static int lengths[SIZE_NUM] = {16, 64, 256, 1024, 8 * 1024};
+static double rsa_results[RSA_NUM][2];
+static double dsa_results[DSA_NUM][2];
+static double ecdsa_results[EC_NUM][2];
+static double ecdh_results[EC_NUM][1];
+
+static void sig_done(int sig);
+
+static void
+sig_done(int sig)
+{
+	signal(SIGALRM, sig_done);
+	run = 0;
+}
+
+#define START	TM_RESET
+#define STOP	TM_GET
+
+
+static double
+Time_F(int s)
+{
+	if (usertime)
+		return app_timer_user(s);
+	else
+		return app_timer_real(s);
+}
+
+
+static const int KDF1_SHA1_len = 20;
+static void *
+KDF1_SHA1(const void *in, size_t inlen, void *out, size_t * outlen)
+{
+#ifndef OPENSSL_NO_SHA
+	if (*outlen < SHA_DIGEST_LENGTH)
+		return NULL;
+	else
+		*outlen = SHA_DIGEST_LENGTH;
+	return SHA1(in, inlen, out);
+#else
+	return NULL;
+#endif				/* OPENSSL_NO_SHA */
+}
+
+int
+speed_main(int argc, char **argv)
+{
+	unsigned char *real_buf = NULL, *real_buf2 = NULL;
+	unsigned char *buf = NULL, *buf2 = NULL;
+	size_t unaligned = 0;
+	int mret = 1;
+	long count = 0, save_count = 0;
+	int i, j, k;
+	long rsa_count;
+	unsigned rsa_num;
+	unsigned char md[EVP_MAX_MD_SIZE];
+#ifndef OPENSSL_NO_MD4
+	unsigned char md4[MD4_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_MD5
+	unsigned char md5[MD5_DIGEST_LENGTH];
+	unsigned char hmac[MD5_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_SHA
+	unsigned char sha[SHA_DIGEST_LENGTH];
+#ifndef OPENSSL_NO_SHA256
+	unsigned char sha256[SHA256_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_SHA512
+	unsigned char sha512[SHA512_DIGEST_LENGTH];
+#endif
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+	unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+	unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
+#endif
+#ifndef OPENSSL_NO_RC4
+	RC4_KEY rc4_ks;
+#endif
+#ifndef OPENSSL_NO_RC2
+	RC2_KEY rc2_ks;
+#endif
+#ifndef OPENSSL_NO_IDEA
+	IDEA_KEY_SCHEDULE idea_ks;
+#endif
+#ifndef OPENSSL_NO_BF
+	BF_KEY bf_ks;
+#endif
+#ifndef OPENSSL_NO_CAST
+	CAST_KEY cast_ks;
+#endif
+	static const unsigned char key16[16] =
+	{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+	0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12};
+#ifndef OPENSSL_NO_AES
+	static const unsigned char key24[24] =
+	{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+		0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+	0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34};
+	static const unsigned char key32[32] =
+	{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+		0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+		0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
+	0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56};
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	static const unsigned char ckey24[24] =
+	{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+		0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+	0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34};
+	static const unsigned char ckey32[32] =
+	{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
+		0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
+		0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
+	0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56};
+#endif
+#ifndef OPENSSL_NO_AES
+#define MAX_BLOCK_SIZE 128
+#else
+#define MAX_BLOCK_SIZE 64
+#endif
+	unsigned char DES_iv[8];
+	unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
+#ifndef OPENSSL_NO_DES
+	static DES_cblock key = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0};
+	static DES_cblock key2 = {0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12};
+	static DES_cblock key3 = {0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34};
+	DES_key_schedule sch;
+	DES_key_schedule sch2;
+	DES_key_schedule sch3;
+#endif
+#ifndef OPENSSL_NO_AES
+	AES_KEY aes_ks1, aes_ks2, aes_ks3;
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
+#endif
+#define	D_MD2		0
+#define	D_MD4		1
+#define	D_MD5		2
+#define	D_HMAC		3
+#define	D_SHA1		4
+#define D_RMD160	5
+#define	D_RC4		6
+#define	D_CBC_DES	7
+#define	D_EDE3_DES	8
+#define	D_CBC_IDEA	9
+#define	D_CBC_SEED	10
+#define	D_CBC_RC2	11
+#define	D_CBC_RC5	12
+#define	D_CBC_BF	13
+#define	D_CBC_CAST	14
+#define D_CBC_128_AES	15
+#define D_CBC_192_AES	16
+#define D_CBC_256_AES	17
+#define D_CBC_128_CML   18
+#define D_CBC_192_CML   19
+#define D_CBC_256_CML   20
+#define D_EVP		21
+#define D_SHA256	22
+#define D_SHA512	23
+#define D_WHIRLPOOL	24
+#define D_IGE_128_AES   25
+#define D_IGE_192_AES   26
+#define D_IGE_256_AES   27
+#define D_GHASH		28
+#define D_AES_128_GCM	29
+#define D_AES_256_GCM	30
+#define D_CHACHA20_POLY1305	31
+	double d = 0.0;
+	long c[ALGOR_NUM][SIZE_NUM];
+#define	R_DSA_512	0
+#define	R_DSA_1024	1
+#define	R_DSA_2048	2
+#define	R_RSA_512	0
+#define	R_RSA_1024	1
+#define	R_RSA_2048	2
+#define	R_RSA_4096	3
+
+#define R_EC_P160    0
+#define R_EC_P192    1
+#define R_EC_P224    2
+#define R_EC_P256    3
+#define R_EC_P384    4
+#define R_EC_P521    5
+
+	RSA *rsa_key[RSA_NUM];
+	long rsa_c[RSA_NUM][2];
+	static unsigned int rsa_bits[RSA_NUM] = {512, 1024, 2048, 4096};
+	static unsigned char *rsa_data[RSA_NUM] =
+	{test512, test1024, test2048, test4096};
+	static int rsa_data_length[RSA_NUM] = {
+		sizeof(test512), sizeof(test1024),
+	sizeof(test2048), sizeof(test4096)};
+	DSA *dsa_key[DSA_NUM];
+	long dsa_c[DSA_NUM][2];
+	static unsigned int dsa_bits[DSA_NUM] = {512, 1024, 2048};
+#ifndef OPENSSL_NO_EC
+	/*
+	 * We only test over the following curves as they are representative,
+	 * To add tests over more curves, simply add the curve NID and curve
+	 * name to the following arrays and increase the EC_NUM value
+	 * accordingly.
+	 */
+	static unsigned int test_curves[EC_NUM] = {
+		NID_secp160r1,
+		NID_X9_62_prime192v1,
+		NID_secp224r1,
+		NID_X9_62_prime256v1,
+		NID_secp384r1,
+		NID_secp521r1,
+	};
+	static const char *test_curves_names[EC_NUM] = {
+		"secp160r1",
+		"nistp192",
+		"nistp224",
+		"nistp256",
+		"nistp384",
+		"nistp521",
+	};
+	static int test_curves_bits[EC_NUM] = {
+		160, 192, 224, 256, 384, 521,
+	};
+
+#endif
+
+	unsigned char ecdsasig[256];
+	unsigned int ecdsasiglen;
+	EC_KEY *ecdsa[EC_NUM];
+	long ecdsa_c[EC_NUM][2];
+
+	EC_KEY *ecdh_a[EC_NUM], *ecdh_b[EC_NUM];
+	unsigned char secret_a[MAX_ECDH_SIZE], secret_b[MAX_ECDH_SIZE];
+	int secret_size_a, secret_size_b;
+	int ecdh_checks = 0;
+	int secret_idx = 0;
+	long ecdh_c[EC_NUM][2];
+
+	int rsa_doit[RSA_NUM];
+	int dsa_doit[DSA_NUM];
+	int ecdsa_doit[EC_NUM];
+	int ecdh_doit[EC_NUM];
+	int doit[ALGOR_NUM];
+	int pr_header = 0;
+	const EVP_CIPHER *evp_cipher = NULL;
+	const EVP_MD *evp_md = NULL;
+	int decrypt = 0;
+#ifndef _WIN32
+	int multi = 0;
+#endif
+	const char *errstr = NULL;
+
+	if (pledge("stdio proc", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	usertime = -1;
+
+	memset(results, 0, sizeof(results));
+	memset(dsa_key, 0, sizeof(dsa_key));
+	for (i = 0; i < EC_NUM; i++)
+		ecdsa[i] = NULL;
+	for (i = 0; i < EC_NUM; i++) {
+		ecdh_a[i] = NULL;
+		ecdh_b[i] = NULL;
+	}
+
+	memset(rsa_key, 0, sizeof(rsa_key));
+	for (i = 0; i < RSA_NUM; i++)
+		rsa_key[i] = NULL;
+
+	if ((buf = real_buf = malloc(BUFSIZE + MAX_UNALIGN)) == NULL) {
+		BIO_printf(bio_err, "out of memory\n");
+		goto end;
+	}
+	if ((buf2 = real_buf2 = malloc(BUFSIZE + MAX_UNALIGN)) == NULL) {
+		BIO_printf(bio_err, "out of memory\n");
+		goto end;
+	}
+	memset(c, 0, sizeof(c));
+	memset(DES_iv, 0, sizeof(DES_iv));
+	memset(iv, 0, sizeof(iv));
+
+	for (i = 0; i < ALGOR_NUM; i++)
+		doit[i] = 0;
+	for (i = 0; i < RSA_NUM; i++)
+		rsa_doit[i] = 0;
+	for (i = 0; i < DSA_NUM; i++)
+		dsa_doit[i] = 0;
+	for (i = 0; i < EC_NUM; i++)
+		ecdsa_doit[i] = 0;
+	for (i = 0; i < EC_NUM; i++)
+		ecdh_doit[i] = 0;
+
+
+	j = 0;
+	argc--;
+	argv++;
+	while (argc) {
+		if (argc > 0 && strcmp(*argv, "-elapsed") == 0) {
+			usertime = 0;
+			j--;	/* Otherwise, -elapsed gets confused with an
+				 * algorithm. */
+		} else if (argc > 0 && strcmp(*argv, "-evp") == 0) {
+			argc--;
+			argv++;
+			if (argc == 0) {
+				BIO_printf(bio_err, "no EVP given\n");
+				goto end;
+			}
+			evp_cipher = EVP_get_cipherbyname(*argv);
+			if (!evp_cipher) {
+				evp_md = EVP_get_digestbyname(*argv);
+			}
+			if (!evp_cipher && !evp_md) {
+				BIO_printf(bio_err, "%s is an unknown cipher or digest\n", *argv);
+				goto end;
+			}
+			doit[D_EVP] = 1;
+		} else if (argc > 0 && strcmp(*argv, "-decrypt") == 0) {
+			decrypt = 1;
+			j--;	/* Otherwise, -decrypt gets confused with an
+				 * algorithm. */
+#ifndef _WIN32
+		} else if (argc > 0 && strcmp(*argv, "-multi") == 0) {
+			argc--;
+			argv++;
+			if (argc == 0) {
+				BIO_printf(bio_err, "no multi count given\n");
+				goto end;
+			}
+			multi = strtonum(argv[0], 1, INT_MAX, &errstr);
+			if (errstr) {
+				BIO_printf(bio_err, "bad multi count: %s", errstr);
+				goto end;
+			}
+			j--;	/* Otherwise, -multi gets confused with an
+				 * algorithm. */
+#endif
+		} else if (argc > 0 && strcmp(*argv, "-unaligned") == 0) {
+			argc--;
+			argv++;
+			if (argc == 0) {
+				BIO_printf(bio_err, "no alignment offset given\n");
+				goto end;
+			}
+			unaligned = strtonum(argv[0], 0, MAX_UNALIGN, &errstr);
+			if (errstr) {
+				BIO_printf(bio_err, "bad alignment offset: %s",
+				    errstr);
+				goto end;
+			}
+			buf = real_buf + unaligned;
+			buf2 = real_buf2 + unaligned;
+			j--;	/* Otherwise, -unaligned gets confused with an
+				 * algorithm. */
+		} else if (argc > 0 && strcmp(*argv, "-mr") == 0) {
+			mr = 1;
+			j--;	/* Otherwise, -mr gets confused with an
+				 * algorithm. */
+		} else
+#ifndef OPENSSL_NO_MD4
+		if (strcmp(*argv, "md4") == 0)
+			doit[D_MD4] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_MD5
+		if (strcmp(*argv, "md5") == 0)
+			doit[D_MD5] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_MD5
+		if (strcmp(*argv, "hmac") == 0)
+			doit[D_HMAC] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_SHA
+		if (strcmp(*argv, "sha1") == 0)
+			doit[D_SHA1] = 1;
+		else if (strcmp(*argv, "sha") == 0)
+			doit[D_SHA1] = 1,
+			    doit[D_SHA256] = 1,
+			    doit[D_SHA512] = 1;
+		else
+#ifndef OPENSSL_NO_SHA256
+		if (strcmp(*argv, "sha256") == 0)
+			doit[D_SHA256] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_SHA512
+		if (strcmp(*argv, "sha512") == 0)
+			doit[D_SHA512] = 1;
+		else
+#endif
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+		if (strcmp(*argv, "whirlpool") == 0)
+			doit[D_WHIRLPOOL] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+		if (strcmp(*argv, "ripemd") == 0)
+			doit[D_RMD160] = 1;
+		else if (strcmp(*argv, "rmd160") == 0)
+			doit[D_RMD160] = 1;
+		else if (strcmp(*argv, "ripemd160") == 0)
+			doit[D_RMD160] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_RC4
+		if (strcmp(*argv, "rc4") == 0)
+			doit[D_RC4] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_DES
+		if (strcmp(*argv, "des-cbc") == 0)
+			doit[D_CBC_DES] = 1;
+		else if (strcmp(*argv, "des-ede3") == 0)
+			doit[D_EDE3_DES] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_AES
+		if (strcmp(*argv, "aes-128-cbc") == 0)
+			doit[D_CBC_128_AES] = 1;
+		else if (strcmp(*argv, "aes-192-cbc") == 0)
+			doit[D_CBC_192_AES] = 1;
+		else if (strcmp(*argv, "aes-256-cbc") == 0)
+			doit[D_CBC_256_AES] = 1;
+		else if (strcmp(*argv, "aes-128-ige") == 0)
+			doit[D_IGE_128_AES] = 1;
+		else if (strcmp(*argv, "aes-192-ige") == 0)
+			doit[D_IGE_192_AES] = 1;
+		else if (strcmp(*argv, "aes-256-ige") == 0)
+			doit[D_IGE_256_AES] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+		if (strcmp(*argv, "camellia-128-cbc") == 0)
+			doit[D_CBC_128_CML] = 1;
+		else if (strcmp(*argv, "camellia-192-cbc") == 0)
+			doit[D_CBC_192_CML] = 1;
+		else if (strcmp(*argv, "camellia-256-cbc") == 0)
+			doit[D_CBC_256_CML] = 1;
+		else
+#endif
+#ifndef RSA_NULL
+		if (strcmp(*argv, "openssl") == 0) {
+			RSA_set_default_method(RSA_PKCS1_SSLeay());
+			j--;
+		} else
+#endif
+		if (strcmp(*argv, "dsa512") == 0)
+			dsa_doit[R_DSA_512] = 2;
+		else if (strcmp(*argv, "dsa1024") == 0)
+			dsa_doit[R_DSA_1024] = 2;
+		else if (strcmp(*argv, "dsa2048") == 0)
+			dsa_doit[R_DSA_2048] = 2;
+		else if (strcmp(*argv, "rsa512") == 0)
+			rsa_doit[R_RSA_512] = 2;
+		else if (strcmp(*argv, "rsa1024") == 0)
+			rsa_doit[R_RSA_1024] = 2;
+		else if (strcmp(*argv, "rsa2048") == 0)
+			rsa_doit[R_RSA_2048] = 2;
+		else if (strcmp(*argv, "rsa4096") == 0)
+			rsa_doit[R_RSA_4096] = 2;
+		else
+#ifndef OPENSSL_NO_RC2
+		if (strcmp(*argv, "rc2-cbc") == 0)
+			doit[D_CBC_RC2] = 1;
+		else if (strcmp(*argv, "rc2") == 0)
+			doit[D_CBC_RC2] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_IDEA
+		if (strcmp(*argv, "idea-cbc") == 0)
+			doit[D_CBC_IDEA] = 1;
+		else if (strcmp(*argv, "idea") == 0)
+			doit[D_CBC_IDEA] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_BF
+		if (strcmp(*argv, "bf-cbc") == 0)
+			doit[D_CBC_BF] = 1;
+		else if (strcmp(*argv, "blowfish") == 0)
+			doit[D_CBC_BF] = 1;
+		else if (strcmp(*argv, "bf") == 0)
+			doit[D_CBC_BF] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_CAST
+		if (strcmp(*argv, "cast-cbc") == 0)
+			doit[D_CBC_CAST] = 1;
+		else if (strcmp(*argv, "cast") == 0)
+			doit[D_CBC_CAST] = 1;
+		else if (strcmp(*argv, "cast5") == 0)
+			doit[D_CBC_CAST] = 1;
+		else
+#endif
+#ifndef OPENSSL_NO_DES
+		if (strcmp(*argv, "des") == 0) {
+			doit[D_CBC_DES] = 1;
+			doit[D_EDE3_DES] = 1;
+		} else
+#endif
+#ifndef OPENSSL_NO_AES
+		if (strcmp(*argv, "aes") == 0) {
+			doit[D_CBC_128_AES] = 1;
+			doit[D_CBC_192_AES] = 1;
+			doit[D_CBC_256_AES] = 1;
+		} else if (strcmp(*argv, "ghash") == 0)
+			doit[D_GHASH] = 1;
+		else if (strcmp(*argv,"aes-128-gcm") == 0)
+			doit[D_AES_128_GCM]=1;
+		else if (strcmp(*argv,"aes-256-gcm") == 0)
+			doit[D_AES_256_GCM]=1;
+		else
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+		if (strcmp(*argv, "camellia") == 0) {
+			doit[D_CBC_128_CML] = 1;
+			doit[D_CBC_192_CML] = 1;
+			doit[D_CBC_256_CML] = 1;
+		} else
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+		if (strcmp(*argv,"chacha20-poly1305") == 0)
+			doit[D_CHACHA20_POLY1305]=1;
+		else
+#endif
+		if (strcmp(*argv, "rsa") == 0) {
+			rsa_doit[R_RSA_512] = 1;
+			rsa_doit[R_RSA_1024] = 1;
+			rsa_doit[R_RSA_2048] = 1;
+			rsa_doit[R_RSA_4096] = 1;
+		} else
+		if (strcmp(*argv, "dsa") == 0) {
+			dsa_doit[R_DSA_512] = 1;
+			dsa_doit[R_DSA_1024] = 1;
+			dsa_doit[R_DSA_2048] = 1;
+		} else
+		if (strcmp(*argv, "ecdsap160") == 0)
+			ecdsa_doit[R_EC_P160] = 2;
+		else if (strcmp(*argv, "ecdsap192") == 0)
+			ecdsa_doit[R_EC_P192] = 2;
+		else if (strcmp(*argv, "ecdsap224") == 0)
+			ecdsa_doit[R_EC_P224] = 2;
+		else if (strcmp(*argv, "ecdsap256") == 0)
+			ecdsa_doit[R_EC_P256] = 2;
+		else if (strcmp(*argv, "ecdsap384") == 0)
+			ecdsa_doit[R_EC_P384] = 2;
+		else if (strcmp(*argv, "ecdsap521") == 0)
+			ecdsa_doit[R_EC_P521] = 2;
+		else if (strcmp(*argv, "ecdsa") == 0) {
+			for (i = 0; i < EC_NUM; i++)
+				ecdsa_doit[i] = 1;
+		} else
+		if (strcmp(*argv, "ecdhp160") == 0)
+			ecdh_doit[R_EC_P160] = 2;
+		else if (strcmp(*argv, "ecdhp192") == 0)
+			ecdh_doit[R_EC_P192] = 2;
+		else if (strcmp(*argv, "ecdhp224") == 0)
+			ecdh_doit[R_EC_P224] = 2;
+		else if (strcmp(*argv, "ecdhp256") == 0)
+			ecdh_doit[R_EC_P256] = 2;
+		else if (strcmp(*argv, "ecdhp384") == 0)
+			ecdh_doit[R_EC_P384] = 2;
+		else if (strcmp(*argv, "ecdhp521") == 0)
+			ecdh_doit[R_EC_P521] = 2;
+		else if (strcmp(*argv, "ecdh") == 0) {
+			for (i = 0; i < EC_NUM; i++)
+				ecdh_doit[i] = 1;
+		} else
+		{
+			BIO_printf(bio_err, "Error: bad option or value\n");
+			BIO_printf(bio_err, "\n");
+			BIO_printf(bio_err, "Available values:\n");
+#ifndef OPENSSL_NO_MD4
+			BIO_printf(bio_err, "md4      ");
+#endif
+#ifndef OPENSSL_NO_MD5
+			BIO_printf(bio_err, "md5      ");
+#ifndef OPENSSL_NO_HMAC
+			BIO_printf(bio_err, "hmac     ");
+#endif
+#endif
+#ifndef OPENSSL_NO_SHA1
+			BIO_printf(bio_err, "sha1     ");
+#endif
+#ifndef OPENSSL_NO_SHA256
+			BIO_printf(bio_err, "sha256   ");
+#endif
+#ifndef OPENSSL_NO_SHA512
+			BIO_printf(bio_err, "sha512   ");
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+			BIO_printf(bio_err, "whirlpool");
+#endif
+#ifndef OPENSSL_NO_RIPEMD160
+			BIO_printf(bio_err, "rmd160");
+#endif
+#if !defined(OPENSSL_NO_MD2) || \
+    !defined(OPENSSL_NO_MD4) || !defined(OPENSSL_NO_MD5) || \
+    !defined(OPENSSL_NO_SHA1) || !defined(OPENSSL_NO_RIPEMD160) || \
+    !defined(OPENSSL_NO_WHIRLPOOL)
+			BIO_printf(bio_err, "\n");
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+			BIO_printf(bio_err, "idea-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC2
+			BIO_printf(bio_err, "rc2-cbc  ");
+#endif
+#ifndef OPENSSL_NO_BF
+			BIO_printf(bio_err, "bf-cbc   ");
+#endif
+#ifndef OPENSSL_NO_DES
+			BIO_printf(bio_err, "des-cbc  des-ede3\n");
+#endif
+#ifndef OPENSSL_NO_AES
+			BIO_printf(bio_err, "aes-128-cbc aes-192-cbc aes-256-cbc ");
+			BIO_printf(bio_err, "aes-128-ige aes-192-ige aes-256-ige\n");
+			BIO_printf(bio_err, "aes-128-gcm aes-256-gcm ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			BIO_printf(bio_err, "\n");
+			BIO_printf(bio_err, "camellia-128-cbc camellia-192-cbc camellia-256-cbc ");
+#endif
+#ifndef OPENSSL_NO_RC4
+			BIO_printf(bio_err, "rc4");
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+			BIO_printf(bio_err," chacha20-poly1305");
+#endif
+			BIO_printf(bio_err, "\n");
+
+			BIO_printf(bio_err, "rsa512   rsa1024  rsa2048  rsa4096\n");
+
+			BIO_printf(bio_err, "dsa512   dsa1024  dsa2048\n");
+			BIO_printf(bio_err, "ecdsap160 ecdsap192 ecdsap224 ecdsap256 ecdsap384 ecdsap521\n");
+			BIO_printf(bio_err, "ecdhp160  ecdhp192  ecdhp224  ecdhp256  ecdhp384  ecdhp521\n");
+
+#ifndef OPENSSL_NO_IDEA
+			BIO_printf(bio_err, "idea     ");
+#endif
+#ifndef OPENSSL_NO_RC2
+			BIO_printf(bio_err, "rc2      ");
+#endif
+#ifndef OPENSSL_NO_DES
+			BIO_printf(bio_err, "des      ");
+#endif
+#ifndef OPENSSL_NO_AES
+			BIO_printf(bio_err, "aes      ");
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+			BIO_printf(bio_err, "camellia ");
+#endif
+			BIO_printf(bio_err, "rsa      ");
+#ifndef OPENSSL_NO_BF
+			BIO_printf(bio_err, "blowfish");
+#endif
+#if !defined(OPENSSL_NO_IDEA) || !defined(OPENSSL_NO_SEED) || \
+    !defined(OPENSSL_NO_RC2) || !defined(OPENSSL_NO_DES) || \
+    !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_BF) || \
+    !defined(OPENSSL_NO_AES) || !defined(OPENSSL_NO_CAMELLIA)
+			BIO_printf(bio_err, "\n");
+#endif
+
+			BIO_printf(bio_err, "\n");
+			BIO_printf(bio_err, "Available options:\n");
+			BIO_printf(bio_err, "-elapsed        measure time in real time instead of CPU user time.\n");
+			BIO_printf(bio_err, "-evp e          use EVP e.\n");
+			BIO_printf(bio_err, "-decrypt        time decryption instead of encryption (only EVP).\n");
+			BIO_printf(bio_err, "-mr             produce machine readable output.\n");
+#ifndef _WIN32
+			BIO_printf(bio_err, "-multi n        run n benchmarks in parallel.\n");
+#endif
+			BIO_printf(bio_err, "-unaligned n    use buffers with offset n from proper alignment.\n");
+			goto end;
+		}
+		argc--;
+		argv++;
+		j++;
+	}
+
+#ifndef _WIN32
+	if (multi && do_multi(multi))
+		goto show_res;
+#endif
+
+	if (j == 0) {
+		for (i = 0; i < ALGOR_NUM; i++) {
+			if (i != D_EVP)
+				doit[i] = 1;
+		}
+		for (i = 0; i < RSA_NUM; i++)
+			rsa_doit[i] = 1;
+		for (i = 0; i < DSA_NUM; i++)
+			dsa_doit[i] = 1;
+		for (i = 0; i < EC_NUM; i++)
+			ecdsa_doit[i] = 1;
+		for (i = 0; i < EC_NUM; i++)
+			ecdh_doit[i] = 1;
+	}
+	for (i = 0; i < ALGOR_NUM; i++)
+		if (doit[i])
+			pr_header++;
+
+	if (usertime == 0 && !mr)
+		BIO_printf(bio_err, "You have chosen to measure elapsed time instead of user CPU time.\n");
+
+	for (i = 0; i < RSA_NUM; i++) {
+		const unsigned char *p;
+
+		p = rsa_data[i];
+		rsa_key[i] = d2i_RSAPrivateKey(NULL, &p, rsa_data_length[i]);
+		if (rsa_key[i] == NULL) {
+			BIO_printf(bio_err, "internal error loading RSA key number %d\n", i);
+			goto end;
+		}
+	}
+
+	dsa_key[0] = get_dsa512();
+	dsa_key[1] = get_dsa1024();
+	dsa_key[2] = get_dsa2048();
+
+#ifndef OPENSSL_NO_DES
+	DES_set_key_unchecked(&key, &sch);
+	DES_set_key_unchecked(&key2, &sch2);
+	DES_set_key_unchecked(&key3, &sch3);
+#endif
+#ifndef OPENSSL_NO_AES
+	AES_set_encrypt_key(key16, 128, &aes_ks1);
+	AES_set_encrypt_key(key24, 192, &aes_ks2);
+	AES_set_encrypt_key(key32, 256, &aes_ks3);
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	Camellia_set_key(key16, 128, &camellia_ks1);
+	Camellia_set_key(ckey24, 192, &camellia_ks2);
+	Camellia_set_key(ckey32, 256, &camellia_ks3);
+#endif
+#ifndef OPENSSL_NO_IDEA
+	idea_set_encrypt_key(key16, &idea_ks);
+#endif
+#ifndef OPENSSL_NO_RC4
+	RC4_set_key(&rc4_ks, 16, key16);
+#endif
+#ifndef OPENSSL_NO_RC2
+	RC2_set_key(&rc2_ks, 16, key16, 128);
+#endif
+#ifndef OPENSSL_NO_BF
+	BF_set_key(&bf_ks, 16, key16);
+#endif
+#ifndef OPENSSL_NO_CAST
+	CAST_set_key(&cast_ks, 16, key16);
+#endif
+	memset(rsa_c, 0, sizeof(rsa_c));
+#define COND(c)	(run && count<0x7fffffff)
+#define COUNT(d) (count)
+	signal(SIGALRM, sig_done);
+
+#ifndef OPENSSL_NO_MD4
+	if (doit[D_MD4]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_MD4], c[D_MD4][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_MD4][j]); count++)
+				EVP_Digest(&(buf[0]), (unsigned long) lengths[j], &(md4[0]), NULL, EVP_md4(), NULL);
+			d = Time_F(STOP);
+			print_result(D_MD4, j, count, d);
+		}
+	}
+#endif
+
+#ifndef OPENSSL_NO_MD5
+	if (doit[D_MD5]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_MD5], c[D_MD5][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_MD5][j]); count++)
+				EVP_Digest(&(buf[0]), (unsigned long) lengths[j], &(md5[0]), NULL, EVP_get_digestbyname("md5"), NULL);
+			d = Time_F(STOP);
+			print_result(D_MD5, j, count, d);
+		}
+	}
+#endif
+
+#if !defined(OPENSSL_NO_MD5) && !defined(OPENSSL_NO_HMAC)
+	if (doit[D_HMAC]) {
+		HMAC_CTX *hctx;
+
+		if ((hctx = HMAC_CTX_new()) == NULL) {
+			BIO_printf(bio_err, "Failed to allocate HMAC context.\n");
+			goto end;
+		}
+
+		HMAC_Init_ex(hctx, (unsigned char *) "This is a key...",
+		    16, EVP_md5(), NULL);
+
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_HMAC], c[D_HMAC][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_HMAC][j]); count++) {
+				if (!HMAC_Init_ex(hctx, NULL, 0, NULL, NULL)) {
+					HMAC_CTX_free(hctx);
+					goto end;
+				}
+				if (!HMAC_Update(hctx, buf, lengths[j])) {
+					HMAC_CTX_free(hctx);
+					goto end;
+				}
+				if (!HMAC_Final(hctx, &(hmac[0]), NULL)) {
+					HMAC_CTX_free(hctx);
+					goto end;
+				}
+			}
+			d = Time_F(STOP);
+			print_result(D_HMAC, j, count, d);
+		}
+		HMAC_CTX_free(hctx);
+	}
+#endif
+#ifndef OPENSSL_NO_SHA
+	if (doit[D_SHA1]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_SHA1], c[D_SHA1][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_SHA1][j]); count++)
+				EVP_Digest(buf, (unsigned long) lengths[j], &(sha[0]), NULL, EVP_sha1(), NULL);
+			d = Time_F(STOP);
+			print_result(D_SHA1, j, count, d);
+		}
+	}
+#ifndef OPENSSL_NO_SHA256
+	if (doit[D_SHA256]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_SHA256], c[D_SHA256][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_SHA256][j]); count++)
+				SHA256(buf, lengths[j], sha256);
+			d = Time_F(STOP);
+			print_result(D_SHA256, j, count, d);
+		}
+	}
+#endif
+
+#ifndef OPENSSL_NO_SHA512
+	if (doit[D_SHA512]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_SHA512], c[D_SHA512][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_SHA512][j]); count++)
+				SHA512(buf, lengths[j], sha512);
+			d = Time_F(STOP);
+			print_result(D_SHA512, j, count, d);
+		}
+	}
+#endif
+#endif
+
+#ifndef OPENSSL_NO_WHIRLPOOL
+	if (doit[D_WHIRLPOOL]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_WHIRLPOOL][j]); count++)
+				WHIRLPOOL(buf, lengths[j], whirlpool);
+			d = Time_F(STOP);
+			print_result(D_WHIRLPOOL, j, count, d);
+		}
+	}
+#endif
+
+#ifndef OPENSSL_NO_RIPEMD
+	if (doit[D_RMD160]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_RMD160], c[D_RMD160][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_RMD160][j]); count++)
+				EVP_Digest(buf, (unsigned long) lengths[j], &(rmd160[0]), NULL, EVP_ripemd160(), NULL);
+			d = Time_F(STOP);
+			print_result(D_RMD160, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_RC4
+	if (doit[D_RC4]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_RC4], c[D_RC4][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_RC4][j]); count++)
+				RC4(&rc4_ks, (unsigned int) lengths[j],
+				    buf, buf);
+			d = Time_F(STOP);
+			print_result(D_RC4, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_DES
+	if (doit[D_CBC_DES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_DES], c[D_CBC_DES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_DES][j]); count++)
+				DES_ncbc_encrypt(buf, buf, lengths[j], &sch,
+				    &DES_iv, DES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_DES, j, count, d);
+		}
+	}
+	if (doit[D_EDE3_DES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_EDE3_DES], c[D_EDE3_DES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_EDE3_DES][j]); count++)
+				DES_ede3_cbc_encrypt(buf, buf, lengths[j],
+				    &sch, &sch2, &sch3,
+				    &DES_iv, DES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_EDE3_DES, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_AES
+	if (doit[D_CBC_128_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_128_AES][j]); count++)
+				AES_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &aes_ks1,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_128_AES, j, count, d);
+		}
+	}
+	if (doit[D_CBC_192_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_192_AES][j]); count++)
+				AES_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &aes_ks2,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_192_AES, j, count, d);
+		}
+	}
+	if (doit[D_CBC_256_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_256_AES][j]); count++)
+				AES_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &aes_ks3,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_256_AES, j, count, d);
+		}
+	}
+	if (doit[D_IGE_128_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_IGE_128_AES][j]); count++)
+				AES_ige_encrypt(buf, buf2,
+				    (unsigned long) lengths[j], &aes_ks1,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_IGE_128_AES, j, count, d);
+		}
+	}
+	if (doit[D_IGE_192_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_IGE_192_AES][j]); count++)
+				AES_ige_encrypt(buf, buf2,
+				    (unsigned long) lengths[j], &aes_ks2,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_IGE_192_AES, j, count, d);
+		}
+	}
+	if (doit[D_IGE_256_AES]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_IGE_256_AES][j]); count++)
+				AES_ige_encrypt(buf, buf2,
+				    (unsigned long) lengths[j], &aes_ks3,
+				    iv, AES_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_IGE_256_AES, j, count, d);
+		}
+	}
+	if (doit[D_GHASH]) {
+		GCM128_CONTEXT *ctx = CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
+		CRYPTO_gcm128_setiv(ctx, (unsigned char *) "0123456789ab", 12);
+
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_GHASH], c[D_GHASH][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_GHASH][j]); count++)
+				CRYPTO_gcm128_aad(ctx, buf, lengths[j]);
+			d = Time_F(STOP);
+			print_result(D_GHASH, j, count, d);
+		}
+		CRYPTO_gcm128_release(ctx);
+	}
+	if (doit[D_AES_128_GCM]) {
+		const EVP_AEAD *aead = EVP_aead_aes_128_gcm();
+		static const unsigned char nonce[32] = {0};
+		size_t buf_len, nonce_len;
+		EVP_AEAD_CTX *ctx;
+
+		if ((ctx = EVP_AEAD_CTX_new()) == NULL) {
+			BIO_printf(bio_err,
+			    "Failed to allocate aead context.\n");
+			goto end;
+		}
+
+		EVP_AEAD_CTX_init(ctx, aead, key32, EVP_AEAD_key_length(aead),
+		    EVP_AEAD_DEFAULT_TAG_LENGTH, NULL);
+		nonce_len = EVP_AEAD_nonce_length(aead);
+
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_AES_128_GCM],c[D_AES_128_GCM][j],lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_AES_128_GCM][j]); count++)
+				EVP_AEAD_CTX_seal(ctx, buf, &buf_len, BUFSIZE, nonce,
+				    nonce_len, buf, lengths[j], NULL, 0);
+			d=Time_F(STOP);
+			print_result(D_AES_128_GCM,j,count,d);
+		}
+		EVP_AEAD_CTX_free(ctx);
+	}
+
+	if (doit[D_AES_256_GCM]) {
+		const EVP_AEAD *aead = EVP_aead_aes_256_gcm();
+		static const unsigned char nonce[32] = {0};
+		size_t buf_len, nonce_len;
+		EVP_AEAD_CTX *ctx;
+
+		if ((ctx = EVP_AEAD_CTX_new()) == NULL) {
+			BIO_printf(bio_err,
+			    "Failed to allocate aead context.\n");
+			goto end;
+		}
+
+		EVP_AEAD_CTX_init(ctx, aead, key32, EVP_AEAD_key_length(aead),
+		EVP_AEAD_DEFAULT_TAG_LENGTH, NULL);
+		nonce_len = EVP_AEAD_nonce_length(aead);
+
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_AES_256_GCM],c[D_AES_256_GCM][j],lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_AES_256_GCM][j]); count++)
+				EVP_AEAD_CTX_seal(ctx, buf, &buf_len, BUFSIZE, nonce,
+				    nonce_len, buf, lengths[j], NULL, 0);
+			d=Time_F(STOP);
+			print_result(D_AES_256_GCM, j, count, d);
+		}
+		EVP_AEAD_CTX_free(ctx);
+	}
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+	if (doit[D_CHACHA20_POLY1305]) {
+		const EVP_AEAD *aead = EVP_aead_chacha20_poly1305();
+		static const unsigned char nonce[32] = {0};
+		size_t buf_len, nonce_len;
+		EVP_AEAD_CTX *ctx;
+
+		if ((ctx = EVP_AEAD_CTX_new()) == NULL) {
+			BIO_printf(bio_err,
+			    "Failed to allocate aead context.\n");
+			goto end;
+		}
+
+		EVP_AEAD_CTX_init(ctx, aead, key32, EVP_AEAD_key_length(aead),
+		    EVP_AEAD_DEFAULT_TAG_LENGTH, NULL);
+		nonce_len = EVP_AEAD_nonce_length(aead);
+
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CHACHA20_POLY1305],
+			    c[D_CHACHA20_POLY1305][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CHACHA20_POLY1305][j]); count++)
+				EVP_AEAD_CTX_seal(ctx, buf, &buf_len, BUFSIZE, nonce,
+				    nonce_len, buf, lengths[j], NULL, 0);
+			d=Time_F(STOP);
+			print_result(D_CHACHA20_POLY1305, j, count, d);
+		}
+		EVP_AEAD_CTX_free(ctx);
+	}
+#endif
+#ifndef OPENSSL_NO_CAMELLIA
+	if (doit[D_CBC_128_CML]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_128_CML][j]); count++)
+				Camellia_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &camellia_ks1,
+				    iv, CAMELLIA_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_128_CML, j, count, d);
+		}
+	}
+	if (doit[D_CBC_192_CML]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_192_CML][j]); count++)
+				Camellia_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &camellia_ks2,
+				    iv, CAMELLIA_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_192_CML, j, count, d);
+		}
+	}
+	if (doit[D_CBC_256_CML]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_256_CML][j]); count++)
+				Camellia_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &camellia_ks3,
+				    iv, CAMELLIA_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_256_CML, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_IDEA
+	if (doit[D_CBC_IDEA]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_IDEA][j]); count++)
+				idea_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &idea_ks,
+				    iv, IDEA_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_IDEA, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_RC2
+	if (doit[D_CBC_RC2]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_RC2], c[D_CBC_RC2][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_RC2][j]); count++)
+				RC2_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &rc2_ks,
+				    iv, RC2_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_RC2, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_BF
+	if (doit[D_CBC_BF]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_BF], c[D_CBC_BF][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_BF][j]); count++)
+				BF_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &bf_ks,
+				    iv, BF_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_BF, j, count, d);
+		}
+	}
+#endif
+#ifndef OPENSSL_NO_CAST
+	if (doit[D_CBC_CAST]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			print_message(names[D_CBC_CAST], c[D_CBC_CAST][j], lengths[j]);
+			Time_F(START);
+			for (count = 0, run = 1; COND(c[D_CBC_CAST][j]); count++)
+				CAST_cbc_encrypt(buf, buf,
+				    (unsigned long) lengths[j], &cast_ks,
+				    iv, CAST_ENCRYPT);
+			d = Time_F(STOP);
+			print_result(D_CBC_CAST, j, count, d);
+		}
+	}
+#endif
+
+	if (doit[D_EVP]) {
+		for (j = 0; j < SIZE_NUM; j++) {
+			if (evp_cipher) {
+				EVP_CIPHER_CTX *ctx;
+				int outl;
+
+				names[D_EVP] =
+				    OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
+				/*
+				 * -O3 -fschedule-insns messes up an
+				 * optimization here!  names[D_EVP] somehow
+				 * becomes NULL
+				 */
+				print_message(names[D_EVP], save_count,
+				    lengths[j]);
+
+				if ((ctx = EVP_CIPHER_CTX_new()) == NULL) {
+					BIO_printf(bio_err, "Failed to "
+					    "allocate cipher context.\n");
+					goto end;
+				}
+				if (decrypt)
+					EVP_DecryptInit_ex(ctx, evp_cipher, NULL, key16, iv);
+				else
+					EVP_EncryptInit_ex(ctx, evp_cipher, NULL, key16, iv);
+				EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+				Time_F(START);
+				if (decrypt)
+					for (count = 0, run = 1; COND(save_count * 4 * lengths[0] / lengths[j]); count++)
+						EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[j]);
+				else
+					for (count = 0, run = 1; COND(save_count * 4 * lengths[0] / lengths[j]); count++)
+						EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[j]);
+				if (decrypt)
+					EVP_DecryptFinal_ex(ctx, buf, &outl);
+				else
+					EVP_EncryptFinal_ex(ctx, buf, &outl);
+				d = Time_F(STOP);
+				EVP_CIPHER_CTX_free(ctx);
+			}
+			if (evp_md) {
+				names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
+				print_message(names[D_EVP], save_count,
+				    lengths[j]);
+
+				Time_F(START);
+				for (count = 0, run = 1; COND(save_count * 4 * lengths[0] / lengths[j]); count++)
+					EVP_Digest(buf, lengths[j], &(md[0]), NULL, evp_md, NULL);
+
+				d = Time_F(STOP);
+			}
+			print_result(D_EVP, j, count, d);
+		}
+	}
+	arc4random_buf(buf, 36);
+	for (j = 0; j < RSA_NUM; j++) {
+		int ret;
+		if (!rsa_doit[j])
+			continue;
+		ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, &rsa_num, rsa_key[j]);
+		if (ret == 0) {
+			BIO_printf(bio_err, "RSA sign failure.  No RSA sign will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_count = 1;
+		} else {
+			pkey_print_message("private", "rsa",
+			    rsa_c[j][0], rsa_bits[j],
+			    RSA_SECONDS);
+/*			RSA_blinding_on(rsa_key[j],NULL); */
+			Time_F(START);
+			for (count = 0, run = 1; COND(rsa_c[j][0]); count++) {
+				ret = RSA_sign(NID_md5_sha1, buf, 36, buf2,
+				    &rsa_num, rsa_key[j]);
+				if (ret == 0) {
+					BIO_printf(bio_err,
+					    "RSA sign failure\n");
+					ERR_print_errors(bio_err);
+					count = 1;
+					break;
+				}
+			}
+			d = Time_F(STOP);
+			BIO_printf(bio_err, mr ? "+R1:%ld:%d:%.2f\n"
+			    : "%ld %d bit private RSA in %.2fs\n",
+			    count, rsa_bits[j], d);
+			rsa_results[j][0] = d / (double) count;
+			rsa_count = count;
+		}
+
+		ret = RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[j]);
+		if (ret <= 0) {
+			BIO_printf(bio_err, "RSA verify failure.  No RSA verify will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_doit[j] = 0;
+		} else {
+			pkey_print_message("public", "rsa",
+			    rsa_c[j][1], rsa_bits[j],
+			    RSA_SECONDS);
+			Time_F(START);
+			for (count = 0, run = 1; COND(rsa_c[j][1]); count++) {
+				ret = RSA_verify(NID_md5_sha1, buf, 36, buf2,
+				    rsa_num, rsa_key[j]);
+				if (ret <= 0) {
+					BIO_printf(bio_err,
+					    "RSA verify failure\n");
+					ERR_print_errors(bio_err);
+					count = 1;
+					break;
+				}
+			}
+			d = Time_F(STOP);
+			BIO_printf(bio_err, mr ? "+R2:%ld:%d:%.2f\n"
+			    : "%ld %d bit public RSA in %.2fs\n",
+			    count, rsa_bits[j], d);
+			rsa_results[j][1] = d / (double) count;
+		}
+
+		if (rsa_count <= 1) {
+			/* if longer than 10s, don't do any more */
+			for (j++; j < RSA_NUM; j++)
+				rsa_doit[j] = 0;
+		}
+	}
+
+	arc4random_buf(buf, 20);
+	for (j = 0; j < DSA_NUM; j++) {
+		unsigned int kk;
+		int ret;
+
+		if (!dsa_doit[j])
+			continue;
+/*		DSA_generate_key(dsa_key[j]); */
+/*		DSA_sign_setup(dsa_key[j],NULL); */
+		ret = DSA_sign(EVP_PKEY_DSA, buf, 20, buf2,
+		    &kk, dsa_key[j]);
+		if (ret == 0) {
+			BIO_printf(bio_err, "DSA sign failure.  No DSA sign will be done.\n");
+			ERR_print_errors(bio_err);
+			rsa_count = 1;
+		} else {
+			pkey_print_message("sign", "dsa",
+			    dsa_c[j][0], dsa_bits[j],
+			    DSA_SECONDS);
+			Time_F(START);
+			for (count = 0, run = 1; COND(dsa_c[j][0]); count++) {
+				ret = DSA_sign(EVP_PKEY_DSA, buf, 20, buf2,
+				    &kk, dsa_key[j]);
+				if (ret == 0) {
+					BIO_printf(bio_err,
+					    "DSA sign failure\n");
+					ERR_print_errors(bio_err);
+					count = 1;
+					break;
+				}
+			}
+			d = Time_F(STOP);
+			BIO_printf(bio_err, mr ? "+R3:%ld:%d:%.2f\n"
+			    : "%ld %d bit DSA signs in %.2fs\n",
+			    count, dsa_bits[j], d);
+			dsa_results[j][0] = d / (double) count;
+			rsa_count = count;
+		}
+
+		ret = DSA_verify(EVP_PKEY_DSA, buf, 20, buf2,
+		    kk, dsa_key[j]);
+		if (ret <= 0) {
+			BIO_printf(bio_err, "DSA verify failure.  No DSA verify will be done.\n");
+			ERR_print_errors(bio_err);
+			dsa_doit[j] = 0;
+		} else {
+			pkey_print_message("verify", "dsa",
+			    dsa_c[j][1], dsa_bits[j],
+			    DSA_SECONDS);
+			Time_F(START);
+			for (count = 0, run = 1; COND(dsa_c[j][1]); count++) {
+				ret = DSA_verify(EVP_PKEY_DSA, buf, 20, buf2,
+				    kk, dsa_key[j]);
+				if (ret <= 0) {
+					BIO_printf(bio_err,
+					    "DSA verify failure\n");
+					ERR_print_errors(bio_err);
+					count = 1;
+					break;
+				}
+			}
+			d = Time_F(STOP);
+			BIO_printf(bio_err, mr ? "+R4:%ld:%d:%.2f\n"
+			    : "%ld %d bit DSA verify in %.2fs\n",
+			    count, dsa_bits[j], d);
+			dsa_results[j][1] = d / (double) count;
+		}
+
+		if (rsa_count <= 1) {
+			/* if longer than 10s, don't do any more */
+			for (j++; j < DSA_NUM; j++)
+				dsa_doit[j] = 0;
+		}
+	}
+
+	for (j = 0; j < EC_NUM; j++) {
+		int ret;
+
+		if (!ecdsa_doit[j])
+			continue;	/* Ignore Curve */
+		ecdsa[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		if (ecdsa[j] == NULL) {
+			BIO_printf(bio_err, "ECDSA failure.\n");
+			ERR_print_errors(bio_err);
+			rsa_count = 1;
+		} else {
+			EC_KEY_precompute_mult(ecdsa[j], NULL);
+
+			/* Perform ECDSA signature test */
+			EC_KEY_generate_key(ecdsa[j]);
+			ret = ECDSA_sign(0, buf, 20, ecdsasig,
+			    &ecdsasiglen, ecdsa[j]);
+			if (ret == 0) {
+				BIO_printf(bio_err, "ECDSA sign failure.  No ECDSA sign will be done.\n");
+				ERR_print_errors(bio_err);
+				rsa_count = 1;
+			} else {
+				pkey_print_message("sign", "ecdsa",
+				    ecdsa_c[j][0],
+				    test_curves_bits[j],
+				    ECDSA_SECONDS);
+
+				Time_F(START);
+				for (count = 0, run = 1; COND(ecdsa_c[j][0]);
+				    count++) {
+					ret = ECDSA_sign(0, buf, 20,
+					    ecdsasig, &ecdsasiglen,
+					    ecdsa[j]);
+					if (ret == 0) {
+						BIO_printf(bio_err, "ECDSA sign failure\n");
+						ERR_print_errors(bio_err);
+						count = 1;
+						break;
+					}
+				}
+				d = Time_F(STOP);
+
+				BIO_printf(bio_err, mr ? "+R5:%ld:%d:%.2f\n" :
+				    "%ld %d bit ECDSA signs in %.2fs \n",
+				    count, test_curves_bits[j], d);
+				ecdsa_results[j][0] = d / (double) count;
+				rsa_count = count;
+			}
+
+			/* Perform ECDSA verification test */
+			ret = ECDSA_verify(0, buf, 20, ecdsasig,
+			    ecdsasiglen, ecdsa[j]);
+			if (ret != 1) {
+				BIO_printf(bio_err, "ECDSA verify failure.  No ECDSA verify will be done.\n");
+				ERR_print_errors(bio_err);
+				ecdsa_doit[j] = 0;
+			} else {
+				pkey_print_message("verify", "ecdsa",
+				    ecdsa_c[j][1],
+				    test_curves_bits[j],
+				    ECDSA_SECONDS);
+				Time_F(START);
+				for (count = 0, run = 1; COND(ecdsa_c[j][1]); count++) {
+					ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[j]);
+					if (ret != 1) {
+						BIO_printf(bio_err, "ECDSA verify failure\n");
+						ERR_print_errors(bio_err);
+						count = 1;
+						break;
+					}
+				}
+				d = Time_F(STOP);
+				BIO_printf(bio_err, mr ? "+R6:%ld:%d:%.2f\n"
+				    : "%ld %d bit ECDSA verify in %.2fs\n",
+				    count, test_curves_bits[j], d);
+				ecdsa_results[j][1] = d / (double) count;
+			}
+
+			if (rsa_count <= 1) {
+				/* if longer than 10s, don't do any more */
+				for (j++; j < EC_NUM; j++)
+					ecdsa_doit[j] = 0;
+			}
+		}
+	}
+
+	for (j = 0; j < EC_NUM; j++) {
+		if (!ecdh_doit[j])
+			continue;
+		ecdh_a[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		ecdh_b[j] = EC_KEY_new_by_curve_name(test_curves[j]);
+		if ((ecdh_a[j] == NULL) || (ecdh_b[j] == NULL)) {
+			BIO_printf(bio_err, "ECDH failure.\n");
+			ERR_print_errors(bio_err);
+			rsa_count = 1;
+		} else {
+			/* generate two ECDH key pairs */
+			if (!EC_KEY_generate_key(ecdh_a[j]) ||
+			    !EC_KEY_generate_key(ecdh_b[j])) {
+				BIO_printf(bio_err, "ECDH key generation failure.\n");
+				ERR_print_errors(bio_err);
+				rsa_count = 1;
+			} else {
+				/*
+				 * If field size is not more than 24 octets,
+				 * then use SHA-1 hash of result; otherwise,
+				 * use result (see section 4.8 of
+				 * draft-ietf-tls-ecc-03.txt).
+				 */
+				int field_size, outlen;
+				void *(*kdf) (const void *in, size_t inlen, void *out, size_t * xoutlen);
+				field_size = EC_GROUP_get_degree(EC_KEY_get0_group(ecdh_a[j]));
+				if (field_size <= 24 * 8) {
+					outlen = KDF1_SHA1_len;
+					kdf = KDF1_SHA1;
+				} else {
+					outlen = (field_size + 7) / 8;
+					kdf = NULL;
+				}
+				secret_size_a = ECDH_compute_key(secret_a, outlen,
+				    EC_KEY_get0_public_key(ecdh_b[j]),
+				    ecdh_a[j], kdf);
+				secret_size_b = ECDH_compute_key(secret_b, outlen,
+				    EC_KEY_get0_public_key(ecdh_a[j]),
+				    ecdh_b[j], kdf);
+				if (secret_size_a != secret_size_b)
+					ecdh_checks = 0;
+				else
+					ecdh_checks = 1;
+
+				for (secret_idx = 0;
+				    (secret_idx < secret_size_a)
+				    && (ecdh_checks == 1);
+				    secret_idx++) {
+					if (secret_a[secret_idx] != secret_b[secret_idx])
+						ecdh_checks = 0;
+				}
+
+				if (ecdh_checks == 0) {
+					BIO_printf(bio_err,
+					    "ECDH computations don't match.\n");
+					ERR_print_errors(bio_err);
+					rsa_count = 1;
+				} else {
+					pkey_print_message("", "ecdh",
+					    ecdh_c[j][0],
+					    test_curves_bits[j],
+					    ECDH_SECONDS);
+					Time_F(START);
+					for (count = 0, run = 1;
+					     COND(ecdh_c[j][0]); count++) {
+						ECDH_compute_key(secret_a,
+						    outlen,
+						    EC_KEY_get0_public_key(ecdh_b[j]),
+						    ecdh_a[j], kdf);
+					}
+					d = Time_F(STOP);
+					BIO_printf(bio_err, mr
+					    ? "+R7:%ld:%d:%.2f\n"
+					    : "%ld %d-bit ECDH ops in %.2fs\n",
+					    count, test_curves_bits[j], d);
+					ecdh_results[j][0] = d / (double) count;
+					rsa_count = count;
+				}
+			}
+		}
+
+
+		if (rsa_count <= 1) {
+			/* if longer than 10s, don't do any more */
+			for (j++; j < EC_NUM; j++)
+				ecdh_doit[j] = 0;
+		}
+	}
+#ifndef _WIN32
+show_res:
+#endif
+	if (!mr) {
+		fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_VERSION));
+		fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_BUILT_ON));
+		fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_CFLAGS));
+	}
+	if (pr_header) {
+		if (mr)
+			fprintf(stdout, "+H");
+		else {
+			fprintf(stdout, "The 'numbers' are in 1000s of bytes per second processed.\n");
+			fprintf(stdout, "type        ");
+		}
+		for (j = 0; j < SIZE_NUM; j++)
+			fprintf(stdout, mr ? ":%d" : "%7d bytes", lengths[j]);
+		fprintf(stdout, "\n");
+	}
+	for (k = 0; k < ALGOR_NUM; k++) {
+		if (!doit[k])
+			continue;
+		if (mr)
+			fprintf(stdout, "+F:%d:%s", k, names[k]);
+		else
+			fprintf(stdout, "%-13s", names[k]);
+		for (j = 0; j < SIZE_NUM; j++) {
+			if (results[k][j] > 10000 && !mr)
+				fprintf(stdout, " %11.2fk", results[k][j] / 1e3);
+			else
+				fprintf(stdout, mr ? ":%.2f" : " %11.2f ", results[k][j]);
+		}
+		fprintf(stdout, "\n");
+	}
+	j = 1;
+	for (k = 0; k < RSA_NUM; k++) {
+		if (!rsa_doit[k])
+			continue;
+		if (j && !mr) {
+			printf("%18ssign    verify    sign/s verify/s\n", " ");
+			j = 0;
+		}
+		if (mr)
+			fprintf(stdout, "+F2:%u:%u:%f:%f\n",
+			    k, rsa_bits[k], rsa_results[k][0],
+			    rsa_results[k][1]);
+		else
+			fprintf(stdout, "rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+			    rsa_bits[k], rsa_results[k][0], rsa_results[k][1],
+			    1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1]);
+	}
+	j = 1;
+	for (k = 0; k < DSA_NUM; k++) {
+		if (!dsa_doit[k])
+			continue;
+		if (j && !mr) {
+			printf("%18ssign    verify    sign/s verify/s\n", " ");
+			j = 0;
+		}
+		if (mr)
+			fprintf(stdout, "+F3:%u:%u:%f:%f\n",
+			    k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]);
+		else
+			fprintf(stdout, "dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
+			    dsa_bits[k], dsa_results[k][0], dsa_results[k][1],
+			    1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1]);
+	}
+	j = 1;
+	for (k = 0; k < EC_NUM; k++) {
+		if (!ecdsa_doit[k])
+			continue;
+		if (j && !mr) {
+			printf("%30ssign    verify    sign/s verify/s\n", " ");
+			j = 0;
+		}
+		if (mr)
+			fprintf(stdout, "+F4:%u:%u:%f:%f\n",
+			    k, test_curves_bits[k],
+			    ecdsa_results[k][0], ecdsa_results[k][1]);
+		else
+			fprintf(stdout,
+			    "%4u bit ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
+			    test_curves_bits[k],
+			    test_curves_names[k],
+			    ecdsa_results[k][0], ecdsa_results[k][1],
+			    1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1]);
+	}
+
+
+	j = 1;
+	for (k = 0; k < EC_NUM; k++) {
+		if (!ecdh_doit[k])
+			continue;
+		if (j && !mr) {
+			printf("%30sop      op/s\n", " ");
+			j = 0;
+		}
+		if (mr)
+			fprintf(stdout, "+F5:%u:%u:%f:%f\n",
+			    k, test_curves_bits[k],
+			    ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
+
+		else
+			fprintf(stdout, "%4u bit ecdh (%s) %8.4fs %8.1f\n",
+			    test_curves_bits[k],
+			    test_curves_names[k],
+			    ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
+	}
+
+	mret = 0;
+
+ end:
+	ERR_print_errors(bio_err);
+	free(real_buf);
+	free(real_buf2);
+	for (i = 0; i < RSA_NUM; i++)
+		if (rsa_key[i] != NULL)
+			RSA_free(rsa_key[i]);
+	for (i = 0; i < DSA_NUM; i++)
+		if (dsa_key[i] != NULL)
+			DSA_free(dsa_key[i]);
+
+	for (i = 0; i < EC_NUM; i++)
+		if (ecdsa[i] != NULL)
+			EC_KEY_free(ecdsa[i]);
+	for (i = 0; i < EC_NUM; i++) {
+		if (ecdh_a[i] != NULL)
+			EC_KEY_free(ecdh_a[i]);
+		if (ecdh_b[i] != NULL)
+			EC_KEY_free(ecdh_b[i]);
+	}
+
+
+	return (mret);
+}
+
+static void
+print_message(const char *s, long num, int length)
+{
+	BIO_printf(bio_err, mr ? "+DT:%s:%d:%d\n"
+	    : "Doing %s for %ds on %d size blocks: ", s, SECONDS, length);
+	(void) BIO_flush(bio_err);
+	alarm(SECONDS);
+}
+
+static void
+pkey_print_message(const char *str, const char *str2, long num,
+    int bits, int tm)
+{
+	BIO_printf(bio_err, mr ? "+DTP:%d:%s:%s:%d\n"
+	    : "Doing %d bit %s %s for %ds: ", bits, str, str2, tm);
+	(void) BIO_flush(bio_err);
+	alarm(tm);
+}
+
+static void
+print_result(int alg, int run_no, int count, double time_used)
+{
+#ifdef _WIN32
+	speed_alarm_free(run);
+#endif
+	BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n"
+	    : "%d %s in %.2fs\n", count, names[alg], time_used);
+	results[alg][run_no] = ((double) count) / time_used * lengths[run_no];
+}
+
+#ifndef _WIN32
+static char *
+sstrsep(char **string, const char *delim)
+{
+	char isdelim[256];
+	char *token = *string;
+
+	if (**string == 0)
+		return NULL;
+
+	memset(isdelim, 0, sizeof isdelim);
+	isdelim[0] = 1;
+
+	while (*delim) {
+		isdelim[(unsigned char) (*delim)] = 1;
+		delim++;
+	}
+
+	while (!isdelim[(unsigned char) (**string)]) {
+		(*string)++;
+	}
+
+	if (**string) {
+		**string = 0;
+		(*string)++;
+	}
+	return token;
+}
+
+static int
+do_multi(int multi)
+{
+	int n;
+	int fd[2];
+	int *fds;
+	static char sep[] = ":";
+	const char *errstr = NULL;
+
+	fds = reallocarray(NULL, multi, sizeof *fds);
+	if (fds == NULL) {
+		fprintf(stderr, "reallocarray failure\n");
+		exit(1);
+	}
+	for (n = 0; n < multi; ++n) {
+		if (pipe(fd) == -1) {
+			fprintf(stderr, "pipe failure\n");
+			exit(1);
+		}
+		fflush(stdout);
+		fflush(stderr);
+		if (fork()) {
+			close(fd[1]);
+			fds[n] = fd[0];
+		} else {
+			close(fd[0]);
+			close(1);
+			if (dup(fd[1]) == -1) {
+				fprintf(stderr, "dup failed\n");
+				exit(1);
+			}
+			close(fd[1]);
+			mr = 1;
+			usertime = 0;
+			free(fds);
+			return 0;
+		}
+		printf("Forked child %d\n", n);
+	}
+
+	/* for now, assume the pipe is long enough to take all the output */
+	for (n = 0; n < multi; ++n) {
+		FILE *f;
+		char buf[1024];
+		char *p;
+
+		f = fdopen(fds[n], "r");
+		while (fgets(buf, sizeof buf, f)) {
+			p = strchr(buf, '\n');
+			if (p)
+				*p = '\0';
+			if (buf[0] != '+') {
+				fprintf(stderr, "Don't understand line '%s' from child %d\n",
+				    buf, n);
+				continue;
+			}
+			printf("Got: %s from %d\n", buf, n);
+			if (!strncmp(buf, "+F:", 3)) {
+				int alg;
+				int j;
+
+				p = buf + 3;
+				alg = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+				for (j = 0; j < SIZE_NUM; ++j)
+					results[alg][j] += atof(sstrsep(&p, sep));
+			} else if (!strncmp(buf, "+F2:", 4)) {
+				int k;
+				double d;
+
+				p = buf + 4;
+				k = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					rsa_results[k][0] = 1 / (1 / rsa_results[k][0] + 1 / d);
+				else
+					rsa_results[k][0] = d;
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					rsa_results[k][1] = 1 / (1 / rsa_results[k][1] + 1 / d);
+				else
+					rsa_results[k][1] = d;
+			} else if (!strncmp(buf, "+F2:", 4)) {
+				int k;
+				double d;
+
+				p = buf + 4;
+				k = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					rsa_results[k][0] = 1 / (1 / rsa_results[k][0] + 1 / d);
+				else
+					rsa_results[k][0] = d;
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					rsa_results[k][1] = 1 / (1 / rsa_results[k][1] + 1 / d);
+				else
+					rsa_results[k][1] = d;
+			}
+			else if (!strncmp(buf, "+F3:", 4)) {
+				int k;
+				double d;
+
+				p = buf + 4;
+				k = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					dsa_results[k][0] = 1 / (1 / dsa_results[k][0] + 1 / d);
+				else
+					dsa_results[k][0] = d;
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					dsa_results[k][1] = 1 / (1 / dsa_results[k][1] + 1 / d);
+				else
+					dsa_results[k][1] = d;
+			}
+			else if (!strncmp(buf, "+F4:", 4)) {
+				int k;
+				double d;
+
+				p = buf + 4;
+				k = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					ecdsa_results[k][0] = 1 / (1 / ecdsa_results[k][0] + 1 / d);
+				else
+					ecdsa_results[k][0] = d;
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					ecdsa_results[k][1] = 1 / (1 / ecdsa_results[k][1] + 1 / d);
+				else
+					ecdsa_results[k][1] = d;
+			}
+
+			else if (!strncmp(buf, "+F5:", 4)) {
+				int k;
+				double d;
+
+				p = buf + 4;
+				k = strtonum(sstrsep(&p, sep),
+				    0, ALGOR_NUM - 1, &errstr);
+				sstrsep(&p, sep);
+
+				d = atof(sstrsep(&p, sep));
+				if (n)
+					ecdh_results[k][0] = 1 / (1 / ecdh_results[k][0] + 1 / d);
+				else
+					ecdh_results[k][0] = d;
+
+			}
+
+			else if (!strncmp(buf, "+H:", 3)) {
+			} else
+				fprintf(stderr, "Unknown type '%s' from child %d\n", buf, n);
+		}
+
+		fclose(f);
+	}
+	free(fds);
+	return 1;
+}
+#endif
+#endif
diff --git a/apps/openssl/spkac.c b/apps/openssl/spkac.c
new file mode 100644
index 0000000..12d530e
--- /dev/null
+++ b/apps/openssl/spkac.c
@@ -0,0 +1,311 @@
+/* $OpenBSD: spkac.c,v 1.13 2023/03/06 14:32:06 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999. Based on an original idea by Massimiliano Pala
+ * (madwolf@openca.org).
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "apps.h"
+#include "progs.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct {
+	char *challenge;
+	char *infile;
+	char *keyfile;
+	int noout;
+	char *outfile;
+	char *passargin;
+	int pubkey;
+	char *spkac;
+	char *spksect;
+	int verify;
+} cfg;
+
+static const struct option spkac_options[] = {
+	{
+		.name = "challenge",
+		.argname = "string",
+		.desc = "Specify challenge string if SPKAC is generated",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.challenge,
+	},
+	{
+		.name = "in",
+		.argname = "file",
+		.desc = "Input file (default stdin)",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.infile,
+	},
+	{
+		.name = "key",
+		.argname = "file",
+		.desc = "Create SPKAC using private key file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.keyfile,
+	},
+	{
+		.name = "noout",
+		.desc = "Do not print text version of SPKAC",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.noout,
+	},
+	{
+		.name = "out",
+		.argname = "file",
+		.desc = "Output file (default stdout)",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.outfile,
+	},
+	{
+		.name = "passin",
+		.argname = "src",
+		.desc = "Input file passphrase source",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.passargin,
+	},
+	{
+		.name = "pubkey",
+		.desc = "Output public key of an SPKAC (not used if creating)",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.pubkey,
+	},
+	{
+		.name = "spkac",
+		.argname = "name",
+		.desc = "SPKAC name (default \"SPKAC\")",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.spkac,
+	},
+	{
+		.name = "spksect",
+		.argname = "name",
+		.desc = "Name of the section containing SPKAC (default"
+		" \"default\")",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.spksect,
+	},
+	{
+		.name = "verify",
+		.desc = "Verify digital signature on supplied SPKAC",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.verify,
+	},
+	{ NULL }
+};
+
+static void
+spkac_usage(void)
+{
+	fprintf(stderr,
+	    "usage: spkac [-challenge string] [-in file] "
+	    "[-key file] [-noout]\n"
+	    "    [-out file] [-passin src] [-pubkey] [-spkac name] "
+	    "[-spksect section]\n"
+	    "    [-verify]\n\n");
+	options_usage(spkac_options);
+}
+
+int
+spkac_main(int argc, char **argv)
+{
+	int i, ret = 1;
+	BIO *in = NULL, *out = NULL;
+	char *passin = NULL;
+	char *spkstr = NULL;
+	CONF *conf = NULL;
+	NETSCAPE_SPKI *spki = NULL;
+	EVP_PKEY *pkey = NULL;
+
+	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.spkac = "SPKAC";
+	cfg.spksect = "default";
+
+	if (options_parse(argc, argv, spkac_options, NULL, NULL) != 0) {
+		spkac_usage();
+		return (1);
+	}
+
+	if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+	}
+
+	if (cfg.keyfile) {
+		pkey = load_key(bio_err,
+		    strcmp(cfg.keyfile, "-") ? cfg.keyfile
+		    : NULL, FORMAT_PEM, 1, passin, "private key");
+		if (!pkey) {
+			goto end;
+		}
+		spki = NETSCAPE_SPKI_new();
+		if (cfg.challenge)
+			ASN1_STRING_set(spki->spkac->challenge,
+			    cfg.challenge,
+			    (int) strlen(cfg.challenge));
+		NETSCAPE_SPKI_set_pubkey(spki, pkey);
+		NETSCAPE_SPKI_sign(spki, pkey, EVP_md5());
+		spkstr = NETSCAPE_SPKI_b64_encode(spki);
+		if (spkstr == NULL) {
+			BIO_printf(bio_err, "Error encoding SPKAC\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+
+		if (cfg.outfile)
+			out = BIO_new_file(cfg.outfile, "w");
+		else
+			out = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+		if (!out) {
+			BIO_printf(bio_err, "Error opening output file\n");
+			ERR_print_errors(bio_err);
+		} else {
+			BIO_printf(out, "SPKAC=%s\n", spkstr);
+			ret = 0;
+		}
+		free(spkstr);
+		goto end;
+	}
+	if (cfg.infile)
+		in = BIO_new_file(cfg.infile, "r");
+	else
+		in = BIO_new_fp(stdin, BIO_NOCLOSE);
+
+	if (!in) {
+		BIO_printf(bio_err, "Error opening input file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	conf = NCONF_new(NULL);
+	i = NCONF_load_bio(conf, in, NULL);
+
+	if (!i) {
+		BIO_printf(bio_err, "Error parsing config file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	spkstr = NCONF_get_string(conf, cfg.spksect,
+	    cfg.spkac);
+
+	if (!spkstr) {
+		BIO_printf(bio_err, "Can't find SPKAC called \"%s\"\n",
+		    cfg.spkac);
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	spki = NETSCAPE_SPKI_b64_decode(spkstr, -1);
+
+	if (!spki) {
+		BIO_printf(bio_err, "Error loading SPKAC\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	if (cfg.outfile)
+		out = BIO_new_file(cfg.outfile, "w");
+	else {
+		out = BIO_new_fp(stdout, BIO_NOCLOSE);
+	}
+
+	if (!out) {
+		BIO_printf(bio_err, "Error opening output file\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	if (!cfg.noout)
+		NETSCAPE_SPKI_print(out, spki);
+	pkey = NETSCAPE_SPKI_get_pubkey(spki);
+	if (cfg.verify) {
+		i = NETSCAPE_SPKI_verify(spki, pkey);
+		if (i > 0)
+			BIO_printf(bio_err, "Signature OK\n");
+		else {
+			BIO_printf(bio_err, "Signature Failure\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+	if (cfg.pubkey)
+		PEM_write_bio_PUBKEY(out, pkey);
+
+	ret = 0;
+
+ end:
+	NCONF_free(conf);
+	NETSCAPE_SPKI_free(spki);
+	BIO_free(in);
+	BIO_free_all(out);
+	EVP_PKEY_free(pkey);
+	free(passin);
+
+	return (ret);
+}
diff --git a/apps/openssl/testdsa.h b/apps/openssl/testdsa.h
new file mode 100644
index 0000000..973e51f
--- /dev/null
+++ b/apps/openssl/testdsa.h
@@ -0,0 +1,258 @@
+/* $OpenBSD: testdsa.h,v 1.5 2022/01/10 19:22:26 tb Exp $ */
+
+DSA *get_dsa512(void);
+DSA *get_dsa1024(void);
+DSA *get_dsa2048(void);
+
+DSA *get_dsa(const unsigned char *priv, size_t priv_size,
+    const unsigned char *pub, size_t pub_size,
+    const unsigned char *p, size_t p_size,
+    const unsigned char *q, size_t q_size,
+    const unsigned char *g, size_t g_size);
+
+static const unsigned char dsa512_priv[] = {
+	0x65, 0xe5, 0xc7, 0x38, 0x60, 0x24, 0xb5, 0x89, 0xd4, 0x9c, 0xeb, 0x4c,
+	0x9c, 0x1d, 0x7a, 0x22, 0xbd, 0xd1, 0xc2, 0xd2,
+};
+
+static const unsigned char dsa512_pub[] = {
+	0x00, 0x95, 0xa7, 0x0d, 0xec, 0x93, 0x68, 0xba, 0x5f, 0xf7, 0x5f, 0x07,
+	0xf2, 0x3b, 0xad, 0x6b, 0x01, 0xdc, 0xbe, 0xec, 0xde, 0x04, 0x7a, 0x3a,
+	0x27, 0xb3, 0xec, 0x49, 0xfd, 0x08, 0x43, 0x3d, 0x7e, 0xa8, 0x2c, 0x5e,
+	0x7b, 0xbb, 0xfc, 0xf4, 0x6e, 0xeb, 0x6c, 0xb0, 0x6e, 0xf8, 0x02, 0x12,
+	0x8c, 0x38, 0x5d, 0x83, 0x56, 0x7d, 0xee, 0x53, 0x05, 0x3e, 0x24, 0x84,
+	0xbe, 0xba, 0x0a, 0x6b, 0xc8,
+};
+
+static const unsigned char dsa512_p[] = {
+	0x9D, 0x1B, 0x69, 0x8E, 0x26, 0xDB, 0xF2, 0x2B, 0x11, 0x70, 0x19, 0x86,
+	0xF6, 0x19, 0xC8, 0xF8, 0x19, 0xF2, 0x18, 0x53, 0x94, 0x46, 0x06, 0xD0,
+	0x62, 0x50, 0x33, 0x4B, 0x02, 0x3C, 0x52, 0x30, 0x03, 0x8B, 0x3B, 0xF9,
+	0x5F, 0xD1, 0x24, 0x06, 0x4F, 0x7B, 0x4C, 0xBA, 0xAA, 0x40, 0x9B, 0xFD,
+	0x96, 0xE4, 0x37, 0x33, 0xBB, 0x2D, 0x5A, 0xD7, 0x5A, 0x11, 0x40, 0x66,
+	0xA2, 0x76, 0x7D, 0x31,
+};
+
+static const unsigned char dsa512_q[] = {
+	0xFB, 0x53, 0xEF, 0x50, 0xB4, 0x40, 0x92, 0x31, 0x56, 0x86, 0x53, 0x7A,
+	0xE8, 0x8B, 0x22, 0x9A, 0x49, 0xFB, 0x71, 0x8F,
+};
+
+static const unsigned char dsa512_g[] = {
+	0x83, 0x3E, 0x88, 0xE5, 0xC5, 0x89, 0x73, 0xCE, 0x3B, 0x6C, 0x01, 0x49,
+	0xBF, 0xB3, 0xC7, 0x9F, 0x0A, 0xEA, 0x44, 0x91, 0xE5, 0x30, 0xAA, 0xD9,
+	0xBE, 0x5B, 0x5F, 0xB7, 0x10, 0xD7, 0x89, 0xB7, 0x8E, 0x74, 0xFB, 0xCF,
+	0x29, 0x1E, 0xEB, 0xA8, 0x2C, 0x54, 0x51, 0xB8, 0x10, 0xDE, 0xA0, 0xCE,
+	0x2F, 0xCC, 0x24, 0x6B, 0x90, 0x77, 0xDE, 0xA2, 0x68, 0xA6, 0x52, 0x12,
+	0xA2, 0x03, 0x9D, 0x20,
+};
+
+DSA *
+get_dsa512(void)
+{
+	return get_dsa(dsa512_priv, sizeof(dsa512_priv),
+	    dsa512_pub, sizeof(dsa512_pub), dsa512_p, sizeof(dsa512_p),
+	    dsa512_q, sizeof(dsa512_q), dsa512_g, sizeof(dsa512_g));
+}
+
+static const unsigned char dsa1024_priv[] = {
+	0x7d, 0x21, 0xda, 0xbb, 0x62, 0x15, 0x47, 0x36, 0x07, 0x67, 0x12, 0xe8,
+	0x8c, 0xaa, 0x1c, 0xcd, 0x38, 0x12, 0x61, 0x18,
+};
+
+static const unsigned char dsa1024_pub[] = {
+	0x3c, 0x4e, 0x9c, 0x2a, 0x7f, 0x16, 0xc1, 0x25, 0xeb, 0xac, 0x78, 0x63,
+	0x90, 0x14, 0x8c, 0x8b, 0xf4, 0x68, 0x43, 0x3c, 0x2d, 0xee, 0x65, 0x50,
+	0x7d, 0x9c, 0x8f, 0x8c, 0x8a, 0x51, 0xd6, 0x11, 0x2b, 0x99, 0xaf, 0x1e,
+	0x90, 0x97, 0xb5, 0xd3, 0xa6, 0x20, 0x25, 0xd6, 0xfe, 0x43, 0x02, 0xd5,
+	0x91, 0x7d, 0xa7, 0x8c, 0xdb, 0xc9, 0x85, 0xa3, 0x36, 0x48, 0xf7, 0x68,
+	0xaa, 0x60, 0xb1, 0xf7, 0x05, 0x68, 0x3a, 0xa3, 0x3f, 0xd3, 0x19, 0x82,
+	0xd8, 0x82, 0x7a, 0x77, 0xfb, 0xef, 0xf4, 0x15, 0x0a, 0xeb, 0x06, 0x04,
+	0x7f, 0x53, 0x07, 0x0c, 0xbc, 0xcb, 0x2d, 0x83, 0xdb, 0x3e, 0xd1, 0x28,
+	0xa5, 0xa1, 0x31, 0xe0, 0x67, 0xfa, 0x50, 0xde, 0x9b, 0x07, 0x83, 0x7e,
+	0x2c, 0x0b, 0xc3, 0x13, 0x50, 0x61, 0xe5, 0xad, 0xbd, 0x36, 0xb8, 0x97,
+	0x4e, 0x40, 0x7d, 0xe8, 0x83, 0x0d, 0xbc, 0x4b
+};
+
+static const unsigned char dsa1024_p[] = {
+	0xA7, 0x3F, 0x6E, 0x85, 0xBF, 0x41, 0x6A, 0x29, 0x7D, 0xF0, 0x9F, 0x47,
+	0x19, 0x30, 0x90, 0x9A, 0x09, 0x1D, 0xDA, 0x6A, 0x33, 0x1E, 0xC5, 0x3D,
+	0x86, 0x96, 0xB3, 0x15, 0xE0, 0x53, 0x2E, 0x8F, 0xE0, 0x59, 0x82, 0x73,
+	0x90, 0x3E, 0x75, 0x31, 0x99, 0x47, 0x7A, 0x52, 0xFB, 0x85, 0xE4, 0xD9,
+	0xA6, 0x7B, 0x38, 0x9B, 0x68, 0x8A, 0x84, 0x9B, 0x87, 0xC6, 0x1E, 0xB5,
+	0x7E, 0x86, 0x4B, 0x53, 0x5B, 0x59, 0xCF, 0x71, 0x65, 0x19, 0x88, 0x6E,
+	0xCE, 0x66, 0xAE, 0x6B, 0x88, 0x36, 0xFB, 0xEC, 0x28, 0xDC, 0xC2, 0xD7,
+	0xA5, 0xBB, 0xE5, 0x2C, 0x39, 0x26, 0x4B, 0xDA, 0x9A, 0x70, 0x18, 0x95,
+	0x37, 0x95, 0x10, 0x56, 0x23, 0xF6, 0x15, 0xED, 0xBA, 0x04, 0x5E, 0xDE,
+	0x39, 0x4F, 0xFD, 0xB7, 0x43, 0x1F, 0xB5, 0xA4, 0x65, 0x6F, 0xCD, 0x80,
+	0x11, 0xE4, 0x70, 0x95, 0x5B, 0x50, 0xCD, 0x49,
+};
+
+static const unsigned char dsa1024_q[] = {
+	0xF7, 0x07, 0x31, 0xED, 0xFA, 0x6C, 0x06, 0x03, 0xD5, 0x85, 0x8A, 0x1C,
+	0xAC, 0x9C, 0x65, 0xE7, 0x50, 0x66, 0x65, 0x6F,
+};
+
+static const unsigned char dsa1024_g[] = {
+	0x4D, 0xDF, 0x4C, 0x03, 0xA6, 0x91, 0x8A, 0xF5, 0x19, 0x6F, 0x50, 0x46,
+	0x25, 0x99, 0xE5, 0x68, 0x6F, 0x30, 0xE3, 0x69, 0xE1, 0xE5, 0xB3, 0x5D,
+	0x98, 0xBB, 0x28, 0x86, 0x48, 0xFC, 0xDE, 0x99, 0x04, 0x3F, 0x5F, 0x88,
+	0x0C, 0x9C, 0x73, 0x24, 0x0D, 0x20, 0x5D, 0xB9, 0x2A, 0x9A, 0x3F, 0x18,
+	0x96, 0x27, 0xE4, 0x62, 0x87, 0xC1, 0x7B, 0x74, 0x62, 0x53, 0xFC, 0x61,
+	0x27, 0xA8, 0x7A, 0x91, 0x09, 0x9D, 0xB6, 0xF1, 0x4D, 0x9C, 0x54, 0x0F,
+	0x58, 0x06, 0xEE, 0x49, 0x74, 0x07, 0xCE, 0x55, 0x7E, 0x23, 0xCE, 0x16,
+	0xF6, 0xCA, 0xDC, 0x5A, 0x61, 0x01, 0x7E, 0xC9, 0x71, 0xB5, 0x4D, 0xF6,
+	0xDC, 0x34, 0x29, 0x87, 0x68, 0xF6, 0x5E, 0x20, 0x93, 0xB3, 0xDB, 0xF5,
+	0xE4, 0x09, 0x6C, 0x41, 0x17, 0x95, 0x92, 0xEB, 0x01, 0xB5, 0x73, 0xA5,
+	0x6A, 0x7E, 0xD8, 0x32, 0xED, 0x0E, 0x02, 0xB8,
+};
+
+DSA *
+get_dsa1024(void)
+{
+	return get_dsa(dsa1024_priv, sizeof(dsa1024_priv),
+	    dsa1024_pub, sizeof(dsa1024_pub), dsa1024_p, sizeof(dsa1024_p),
+	    dsa1024_q, sizeof(dsa1024_q), dsa1024_g, sizeof(dsa1024_g));
+}
+
+static const unsigned char dsa2048_priv[] = {
+	0x32, 0x67, 0x92, 0xf6, 0xc4, 0xe2, 0xe2, 0xe8, 0xa0, 0x8b, 0x6b, 0x45,
+	0x0c, 0x8a, 0x76, 0xb0, 0xee, 0xcf, 0x91, 0xa7,
+};
+
+static const unsigned char dsa2048_pub[] = {
+	0x17, 0x8f, 0xa8, 0x11, 0x84, 0x92, 0xec, 0x83, 0x47, 0xc7, 0x6a, 0xb0,
+	0x92, 0xaf, 0x5a, 0x20, 0x37, 0xa3, 0x64, 0x79, 0xd2, 0xd0, 0x3d, 0xcd,
+	0xe0, 0x61, 0x88, 0x88, 0x21, 0xcc, 0x74, 0x5d, 0xce, 0x4c, 0x51, 0x47,
+	0xf0, 0xc5, 0x5c, 0x4c, 0x82, 0x7a, 0xaf, 0x72, 0xad, 0xb9, 0xe0, 0x53,
+	0xf2, 0x78, 0xb7, 0xf0, 0xb5, 0x48, 0x7f, 0x8a, 0x3a, 0x18, 0xd1, 0x9f,
+	0x8b, 0x7d, 0xa5, 0x47, 0xb7, 0x95, 0xab, 0x98, 0xf8, 0x7b, 0x74, 0x50,
+	0x56, 0x8e, 0x57, 0xf0, 0xee, 0xf5, 0xb7, 0xba, 0xab, 0x85, 0x86, 0xf9,
+	0x2b, 0xef, 0x41, 0x56, 0xa0, 0xa4, 0x9f, 0xb7, 0x38, 0x00, 0x46, 0x0a,
+	0xa6, 0xf1, 0xfc, 0x1f, 0xd8, 0x4e, 0x85, 0x44, 0x92, 0x43, 0x21, 0x5d,
+	0x6e, 0xcc, 0xc2, 0xcb, 0x26, 0x31, 0x0d, 0x21, 0xc4, 0xbd, 0x8d, 0x24,
+	0xbc, 0xd9, 0x18, 0x19, 0xd7, 0xdc, 0xf1, 0xe7, 0x93, 0x50, 0x48, 0x03,
+	0x2c, 0xae, 0x2e, 0xe7, 0x49, 0x88, 0x5f, 0x93, 0x57, 0x27, 0x99, 0x36,
+	0xb4, 0x20, 0xab, 0xfc, 0xa7, 0x2b, 0xf2, 0xd9, 0x98, 0xd7, 0xd4, 0x34,
+	0x9d, 0x96, 0x50, 0x58, 0x9a, 0xea, 0x54, 0xf3, 0xee, 0xf5, 0x63, 0x14,
+	0xee, 0x85, 0x83, 0x74, 0x76, 0xe1, 0x52, 0x95, 0xc3, 0xf7, 0xeb, 0x04,
+	0x04, 0x7b, 0xa7, 0x28, 0x1b, 0xcc, 0xea, 0x4a, 0x4e, 0x84, 0xda, 0xd8,
+	0x9c, 0x79, 0xd8, 0x9b, 0x66, 0x89, 0x2f, 0xcf, 0xac, 0xd7, 0x79, 0xf9,
+	0xa9, 0xd8, 0x45, 0x13, 0x78, 0xb9, 0x00, 0x14, 0xc9, 0x7e, 0x22, 0x51,
+	0x86, 0x67, 0xb0, 0x9f, 0x26, 0x11, 0x23, 0xc8, 0x38, 0xd7, 0x70, 0x1d,
+	0x15, 0x8e, 0x4d, 0x4f, 0x95, 0x97, 0x40, 0xa1, 0xc2, 0x7e, 0x01, 0x18,
+	0x72, 0xf4, 0x10, 0xe6, 0x8d, 0x52, 0x16, 0x7f, 0xf2, 0xc9, 0xf8, 0x33,
+	0x8b, 0x33, 0xb7, 0xce,
+};
+
+static const unsigned char dsa2048_p[] = {
+	0xA0, 0x25, 0xFA, 0xAD, 0xF4, 0x8E, 0xB9, 0xE5, 0x99, 0xF3, 0x5D, 0x6F,
+	0x4F, 0x83, 0x34, 0xE2, 0x7E, 0xCF, 0x6F, 0xBF, 0x30, 0xAF, 0x6F, 0x81,
+	0xEB, 0xF8, 0xC4, 0x13, 0xD9, 0xA0, 0x5D, 0x8B, 0x5C, 0x8E, 0xDC, 0xC2,
+	0x1D, 0x0B, 0x41, 0x32, 0xB0, 0x1F, 0xFE, 0xEF, 0x0C, 0xC2, 0xA2, 0x7E,
+	0x68, 0x5C, 0x28, 0x21, 0xE9, 0xF5, 0xB1, 0x58, 0x12, 0x63, 0x4C, 0x19,
+	0x4E, 0xFF, 0x02, 0x4B, 0x92, 0xED, 0xD2, 0x07, 0x11, 0x4D, 0x8C, 0x58,
+	0x16, 0x5C, 0x55, 0x8E, 0xAD, 0xA3, 0x67, 0x7D, 0xB9, 0x86, 0x6E, 0x0B,
+	0xE6, 0x54, 0x6F, 0x40, 0xAE, 0x0E, 0x67, 0x4C, 0xF9, 0x12, 0x5B, 0x3C,
+	0x08, 0x7A, 0xF7, 0xFC, 0x67, 0x86, 0x69, 0xE7, 0x0A, 0x94, 0x40, 0xBF,
+	0x8B, 0x76, 0xFE, 0x26, 0xD1, 0xF2, 0xA1, 0x1A, 0x84, 0xA1, 0x43, 0x56,
+	0x28, 0xBC, 0x9A, 0x5F, 0xD7, 0x3B, 0x69, 0x89, 0x8A, 0x36, 0x2C, 0x51,
+	0xDF, 0x12, 0x77, 0x2F, 0x57, 0x7B, 0xA0, 0xAA, 0xDD, 0x7F, 0xA1, 0x62,
+	0x3B, 0x40, 0x7B, 0x68, 0x1A, 0x8F, 0x0D, 0x38, 0xBB, 0x21, 0x5D, 0x18,
+	0xFC, 0x0F, 0x46, 0xF7, 0xA3, 0xB0, 0x1D, 0x23, 0xC3, 0xD2, 0xC7, 0x72,
+	0x51, 0x18, 0xDF, 0x46, 0x95, 0x79, 0xD9, 0xBD, 0xB5, 0x19, 0x02, 0x2C,
+	0x87, 0xDC, 0xE7, 0x57, 0x82, 0x7E, 0xF1, 0x8B, 0x06, 0x3D, 0x00, 0xA5,
+	0x7B, 0x6B, 0x26, 0x27, 0x91, 0x0F, 0x6A, 0x77, 0xE4, 0xD5, 0x04, 0xE4,
+	0x12, 0x2C, 0x42, 0xFF, 0xD2, 0x88, 0xBB, 0xD3, 0x92, 0xA0, 0xF9, 0xC8,
+	0x51, 0x64, 0x14, 0x5C, 0xD8, 0xF9, 0x6C, 0x47, 0x82, 0xB4, 0x1C, 0x7F,
+	0x09, 0xB8, 0xF0, 0x25, 0x83, 0x1D, 0x3F, 0x3F, 0x05, 0xB3, 0x21, 0x0A,
+	0x5D, 0xA7, 0xD8, 0x54, 0xC3, 0x65, 0x7D, 0xC3, 0xB0, 0x1D, 0xBF, 0xAE,
+	0xF8, 0x68, 0xCF, 0x9B,
+};
+
+static const unsigned char dsa2048_q[] = {
+	0x97, 0xE7, 0x33, 0x4D, 0xD3, 0x94, 0x3E, 0x0B, 0xDB, 0x62, 0x74, 0xC6,
+	0xA1, 0x08, 0xDD, 0x19, 0xA3, 0x75, 0x17, 0x1B,
+};
+
+static const unsigned char dsa2048_g[] = {
+	0x2C, 0x78, 0x16, 0x59, 0x34, 0x63, 0xF4, 0xF3, 0x92, 0xFC, 0xB5, 0xA5,
+	0x4F, 0x13, 0xDE, 0x2F, 0x1C, 0xA4, 0x3C, 0xAE, 0xAD, 0x38, 0x3F, 0x7E,
+	0x90, 0xBF, 0x96, 0xA6, 0xAE, 0x25, 0x90, 0x72, 0xF5, 0x8E, 0x80, 0x0C,
+	0x39, 0x1C, 0xD9, 0xEC, 0xBA, 0x90, 0x5B, 0x3A, 0xE8, 0x58, 0x6C, 0x9E,
+	0x30, 0x42, 0x37, 0x02, 0x31, 0x82, 0xBC, 0x6A, 0xDF, 0x6A, 0x09, 0x29,
+	0xE3, 0xC0, 0x46, 0xD1, 0xCB, 0x85, 0xEC, 0x0C, 0x30, 0x5E, 0xEA, 0xC8,
+	0x39, 0x8E, 0x22, 0x9F, 0x22, 0x10, 0xD2, 0x34, 0x61, 0x68, 0x37, 0x3D,
+	0x2E, 0x4A, 0x5B, 0x9A, 0xF5, 0xC1, 0x48, 0xC6, 0xF6, 0xDC, 0x63, 0x1A,
+	0xD3, 0x96, 0x64, 0xBA, 0x34, 0xC9, 0xD1, 0xA0, 0xD1, 0xAE, 0x6C, 0x2F,
+	0x48, 0x17, 0x93, 0x14, 0x43, 0xED, 0xF0, 0x21, 0x30, 0x19, 0xC3, 0x1B,
+	0x5F, 0xDE, 0xA3, 0xF0, 0x70, 0x78, 0x18, 0xE1, 0xA8, 0xE4, 0xEE, 0x2E,
+	0x00, 0xA5, 0xE4, 0xB3, 0x17, 0xC8, 0x0C, 0x7D, 0x6E, 0x42, 0xDC, 0xB7,
+	0x46, 0x00, 0x36, 0x4D, 0xD4, 0x46, 0xAA, 0x3D, 0x3C, 0x46, 0x89, 0x40,
+	0xBF, 0x1D, 0x84, 0x77, 0x0A, 0x75, 0xF3, 0x87, 0x1D, 0x08, 0x4C, 0xA6,
+	0xD1, 0xA9, 0x1C, 0x1E, 0x12, 0x1E, 0xE1, 0xC7, 0x30, 0x28, 0x76, 0xA5,
+	0x7F, 0x6C, 0x85, 0x96, 0x2B, 0x6F, 0xDB, 0x80, 0x66, 0x26, 0xAE, 0xF5,
+	0x93, 0xC7, 0x8E, 0xAE, 0x9A, 0xED, 0xE4, 0xCA, 0x04, 0xEA, 0x3B, 0x72,
+	0xEF, 0xDC, 0x87, 0xED, 0x0D, 0xA5, 0x4C, 0x4A, 0xDD, 0x71, 0x22, 0x64,
+	0x59, 0x69, 0x4E, 0x8E, 0xBF, 0x43, 0xDC, 0xAB, 0x8E, 0x66, 0xBB, 0x01,
+	0xB6, 0xF4, 0xE7, 0xFD, 0xD2, 0xAD, 0x9F, 0x36, 0xC1, 0xA0, 0x29, 0x99,
+	0xD1, 0x96, 0x70, 0x59, 0x06, 0x78, 0x35, 0xBD, 0x65, 0x55, 0x52, 0x9E,
+	0xF8, 0xB2, 0xE5, 0x38,
+};
+
+DSA *
+get_dsa2048(void)
+{
+	return get_dsa(dsa2048_priv, sizeof(dsa2048_priv),
+	    dsa2048_pub, sizeof(dsa2048_pub), dsa2048_p, sizeof(dsa2048_p),
+	    dsa2048_q, sizeof(dsa2048_q), dsa2048_g, sizeof(dsa2048_g));
+}
+
+DSA *
+get_dsa(const unsigned char *priv, size_t priv_size,
+    const unsigned char *pub, size_t pub_size,
+    const unsigned char *p_char, size_t p_size,
+    const unsigned char *q_char, size_t q_size,
+    const unsigned char *g_char, size_t g_size)
+{
+	DSA *dsa;
+	BIGNUM *priv_key = NULL, *pub_key = NULL;
+	BIGNUM *p = NULL, *q = NULL, *g = NULL;
+
+	if ((dsa = DSA_new()) == NULL)
+		return (NULL);
+
+	priv_key = BN_bin2bn(priv, priv_size, NULL);
+	pub_key = BN_bin2bn(pub, pub_size, NULL);
+	if (priv_key == NULL || pub_key == NULL)
+		goto err;
+
+	if (!DSA_set0_key(dsa, pub_key, priv_key))
+		goto err;
+	pub_key = NULL;
+	priv_key = NULL;
+
+	p = BN_bin2bn(p_char, p_size, NULL);
+	q = BN_bin2bn(q_char, q_size, NULL);
+	g = BN_bin2bn(g_char, g_size, NULL);
+	if (p == NULL || q == NULL || g == NULL)
+		goto err;
+
+	if (!DSA_set0_pqg(dsa, p, q, g))
+		goto err;
+	p = NULL;
+	q = NULL;
+	g = NULL;
+
+	return dsa;
+
+ err:
+	DSA_free(dsa);
+	BN_free(priv_key);
+	BN_free(pub_key);
+	BN_free(p);
+	BN_free(q);
+	BN_free(g);
+
+	return NULL;
+}
diff --git a/apps/openssl/testrsa.h b/apps/openssl/testrsa.h
new file mode 100644
index 0000000..789afa9
--- /dev/null
+++ b/apps/openssl/testrsa.h
@@ -0,0 +1,517 @@
+/* $OpenBSD: testrsa.h,v 1.1 2014/08/26 17:47:25 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+static unsigned char test512[] = {
+	0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00,
+	0xd6, 0x33, 0xb9, 0xc8, 0xfb, 0x4f, 0x3c, 0x7d, 0xc0, 0x01,
+	0x86, 0xd0, 0xe7, 0xa0, 0x55, 0xf2, 0x95, 0x93, 0xcc, 0x4f,
+	0xb7, 0x5b, 0x67, 0x5b, 0x94, 0x68, 0xc9, 0x34, 0x15, 0xde,
+	0xa5, 0x2e, 0x1c, 0x33, 0xc2, 0x6e, 0xfc, 0x34, 0x5e, 0x71,
+	0x13, 0xb7, 0xd6, 0xee, 0xd8, 0xa5, 0x65, 0x05, 0x72, 0x87,
+	0xa8, 0xb0, 0x77, 0xfe, 0x57, 0xf5, 0xfc, 0x5f, 0x55, 0x83,
+	0x87, 0xdd, 0x57, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+	0x41, 0x00, 0xa7, 0xf7, 0x91, 0xc5, 0x0f, 0x84, 0x57, 0xdc,
+	0x07, 0xf7, 0x6a, 0x7f, 0x60, 0x52, 0xb3, 0x72, 0xf1, 0x66,
+	0x1f, 0x7d, 0x97, 0x3b, 0x9e, 0xb6, 0x0a, 0x8f, 0x8c, 0xcf,
+	0x42, 0x23, 0x00, 0x04, 0xd4, 0x28, 0x0e, 0x1c, 0x90, 0xc4,
+	0x11, 0x25, 0x25, 0xa5, 0x93, 0xa5, 0x2f, 0x70, 0x02, 0xdf,
+	0x81, 0x9c, 0x49, 0x03, 0xa0, 0xf8, 0x6d, 0x54, 0x2e, 0x26,
+	0xde, 0xaa, 0x85, 0x59, 0xa8, 0x31, 0x02, 0x21, 0x00, 0xeb,
+	0x47, 0xd7, 0x3b, 0xf6, 0xc3, 0xdd, 0x5a, 0x46, 0xc5, 0xb9,
+	0x2b, 0x9a, 0xa0, 0x09, 0x8f, 0xa6, 0xfb, 0xf3, 0x78, 0x7a,
+	0x33, 0x70, 0x9d, 0x0f, 0x42, 0x6b, 0x13, 0x68, 0x24, 0xd3,
+	0x15, 0x02, 0x21, 0x00, 0xe9, 0x10, 0xb0, 0xb3, 0x0d, 0xe2,
+	0x82, 0x68, 0x77, 0x8a, 0x6e, 0x7c, 0xda, 0xbc, 0x3e, 0x53,
+	0x83, 0xfb, 0xd6, 0x22, 0xe7, 0xb5, 0xae, 0x6e, 0x80, 0xda,
+	0x00, 0x55, 0x97, 0xc1, 0xd0, 0x65, 0x02, 0x20, 0x4c, 0xf8,
+	0x73, 0xb1, 0x6a, 0x49, 0x29, 0x61, 0x1f, 0x46, 0x10, 0x0d,
+	0xf3, 0xc7, 0xe7, 0x58, 0xd7, 0x88, 0x15, 0x5e, 0x94, 0x9b,
+	0xbf, 0x7b, 0xa2, 0x42, 0x58, 0x45, 0x41, 0x0c, 0xcb, 0x01,
+	0x02, 0x20, 0x12, 0x11, 0xba, 0x31, 0x57, 0x9d, 0x3d, 0x11,
+	0x0e, 0x5b, 0x8c, 0x2f, 0x5f, 0xe2, 0x02, 0x4f, 0x05, 0x47,
+	0x8c, 0x15, 0x8e, 0xb3, 0x56, 0x3f, 0xb8, 0xfb, 0xad, 0xd4,
+	0xf4, 0xfc, 0x10, 0xc5, 0x02, 0x20, 0x18, 0xa1, 0x29, 0x99,
+	0x5b, 0xd9, 0xc8, 0xd4, 0xfc, 0x49, 0x7a, 0x2a, 0x21, 0x2c,
+	0x49, 0xe4, 0x4f, 0xeb, 0xef, 0x51, 0xf1, 0xab, 0x6d, 0xfb,
+	0x4b, 0x14, 0xe9, 0x4b, 0x52, 0xb5, 0x82, 0x2c,
+};
+
+static unsigned char test1024[] = {
+	0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+	0x00, 0xdc, 0x98, 0x43, 0xe8, 0x3d, 0x43, 0x5b, 0xe4, 0x05,
+	0xcd, 0xd0, 0xa9, 0x3e, 0xcb, 0x83, 0x75, 0xf6, 0xb5, 0xa5,
+	0x9f, 0x6b, 0xe9, 0x34, 0x41, 0x29, 0x18, 0xfa, 0x6a, 0x55,
+	0x4d, 0x70, 0xfc, 0xec, 0xae, 0x87, 0x38, 0x0a, 0x20, 0xa9,
+	0xc0, 0x45, 0x77, 0x6e, 0x57, 0x60, 0x57, 0xf4, 0xed, 0x96,
+	0x22, 0xcb, 0x8f, 0xe1, 0x33, 0x3a, 0x17, 0x1f, 0xed, 0x37,
+	0xa5, 0x6f, 0xeb, 0xa6, 0xbc, 0x12, 0x80, 0x1d, 0x53, 0xbd,
+	0x70, 0xeb, 0x21, 0x76, 0x3e, 0xc9, 0x2f, 0x1a, 0x45, 0x24,
+	0x82, 0xff, 0xcd, 0x59, 0x32, 0x06, 0x2e, 0x12, 0x3b, 0x23,
+	0x78, 0xed, 0x12, 0x3d, 0xe0, 0x8d, 0xf9, 0x67, 0x4f, 0x37,
+	0x4e, 0x47, 0x02, 0x4c, 0x2d, 0xc0, 0x4f, 0x1f, 0xb3, 0x94,
+	0xe1, 0x41, 0x2e, 0x2d, 0x90, 0x10, 0xfc, 0x82, 0x91, 0x8b,
+	0x0f, 0x22, 0xd4, 0xf2, 0xfc, 0x2c, 0xab, 0x53, 0x55, 0x02,
+	0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x2b, 0xcc, 0x3f,
+	0x8f, 0x58, 0xba, 0x8b, 0x00, 0x16, 0xf6, 0xea, 0x3a, 0xf0,
+	0x30, 0xd0, 0x05, 0x17, 0xda, 0xb0, 0xeb, 0x9a, 0x2d, 0x4f,
+	0x26, 0xb0, 0xd6, 0x38, 0xc1, 0xeb, 0xf5, 0xd8, 0x3d, 0x1f,
+	0x70, 0xf7, 0x7f, 0xf4, 0xe2, 0xcf, 0x51, 0x51, 0x79, 0x88,
+	0xfa, 0xe8, 0x32, 0x0e, 0x7b, 0x2d, 0x97, 0xf2, 0xfa, 0xba,
+	0x27, 0xc5, 0x9c, 0xd9, 0xc5, 0xeb, 0x8a, 0x79, 0x52, 0x3c,
+	0x64, 0x34, 0x7d, 0xc2, 0xcf, 0x28, 0xc7, 0x4e, 0xd5, 0x43,
+	0x0b, 0xd1, 0xa6, 0xca, 0x6d, 0x03, 0x2d, 0x72, 0x23, 0xbc,
+	0x6d, 0x05, 0xfa, 0x16, 0x09, 0x2f, 0x2e, 0x5c, 0xb6, 0xee,
+	0x74, 0xdd, 0xd2, 0x48, 0x8e, 0x36, 0x0c, 0x06, 0x3d, 0x4d,
+	0xe5, 0x10, 0x82, 0xeb, 0x6a, 0xf3, 0x4b, 0x9f, 0xd6, 0xed,
+	0x11, 0xb1, 0x6e, 0xec, 0xf4, 0xfe, 0x8e, 0x75, 0x94, 0x20,
+	0x2f, 0xcb, 0xac, 0x46, 0xf1, 0x02, 0x41, 0x00, 0xf9, 0x8c,
+	0xa3, 0x85, 0xb1, 0xdd, 0x29, 0xaf, 0x65, 0xc1, 0x33, 0xf3,
+	0x95, 0xc5, 0x52, 0x68, 0x0b, 0xd4, 0xf1, 0xe5, 0x0e, 0x02,
+	0x9f, 0x4f, 0xfa, 0x77, 0xdc, 0x46, 0x9e, 0xc7, 0xa6, 0xe4,
+	0x16, 0x29, 0xda, 0xb0, 0x07, 0xcf, 0x5b, 0xa9, 0x12, 0x8a,
+	0xdd, 0x63, 0x0a, 0xde, 0x2e, 0x8c, 0x66, 0x8b, 0x8c, 0xdc,
+	0x19, 0xa3, 0x7e, 0xf4, 0x3b, 0xd0, 0x1a, 0x8c, 0xa4, 0xc2,
+	0xe1, 0xd3, 0x02, 0x41, 0x00, 0xe2, 0x4c, 0x05, 0xf2, 0x04,
+	0x86, 0x4e, 0x61, 0x43, 0xdb, 0xb0, 0xb9, 0x96, 0x86, 0x52,
+	0x2c, 0xca, 0x8d, 0x7b, 0xab, 0x0b, 0x13, 0x0d, 0x7e, 0x38,
+	0x5b, 0xe2, 0x2e, 0x7b, 0x0e, 0xe7, 0x19, 0x99, 0x38, 0xe7,
+	0xf2, 0x21, 0xbd, 0x85, 0x85, 0xe3, 0xfd, 0x28, 0x77, 0x20,
+	0x31, 0x71, 0x2c, 0xd0, 0xff, 0xfb, 0x2e, 0xaf, 0x85, 0xb4,
+	0x86, 0xca, 0xf3, 0xbb, 0xca, 0xaa, 0x0f, 0x95, 0x37, 0x02,
+	0x40, 0x0e, 0x41, 0x9a, 0x95, 0xe8, 0xb3, 0x59, 0xce, 0x4b,
+	0x61, 0xde, 0x35, 0xec, 0x38, 0x79, 0x9c, 0xb8, 0x10, 0x52,
+	0x41, 0x63, 0xab, 0x82, 0xae, 0x6f, 0x00, 0xa9, 0xf4, 0xde,
+	0xdd, 0x49, 0x0b, 0x7e, 0xb8, 0xa5, 0x65, 0xa9, 0x0c, 0x8f,
+	0x8f, 0xf9, 0x1f, 0x35, 0xc6, 0x92, 0xb8, 0x5e, 0xb0, 0x66,
+	0xab, 0x52, 0x40, 0xc0, 0xb6, 0x36, 0x6a, 0x7d, 0x80, 0x46,
+	0x04, 0x02, 0xe5, 0x9f, 0x41, 0x02, 0x41, 0x00, 0xc0, 0xad,
+	0xcc, 0x4e, 0x21, 0xee, 0x1d, 0x24, 0x91, 0xfb, 0xa7, 0x80,
+	0x8d, 0x9a, 0xb6, 0xb3, 0x2e, 0x8f, 0xc2, 0xe1, 0x82, 0xdf,
+	0x69, 0x18, 0xb4, 0x71, 0xff, 0xa6, 0x65, 0xde, 0xed, 0x84,
+	0x8d, 0x42, 0xb7, 0xb3, 0x21, 0x69, 0x56, 0x1c, 0x07, 0x60,
+	0x51, 0x29, 0x04, 0xff, 0x34, 0x06, 0xdd, 0xb9, 0x67, 0x2c,
+	0x7c, 0x04, 0x93, 0x0e, 0x46, 0x15, 0xbb, 0x2a, 0xb7, 0x1b,
+	0xe7, 0x87, 0x02, 0x40, 0x78, 0xda, 0x5d, 0x07, 0x51, 0x0c,
+	0x16, 0x7a, 0x9f, 0x29, 0x20, 0x84, 0x0d, 0x42, 0xfa, 0xd7,
+	0x00, 0xd8, 0x77, 0x7e, 0xb0, 0xb0, 0x6b, 0xd6, 0x5b, 0x53,
+	0xb8, 0x9b, 0x7a, 0xcd, 0xc7, 0x2b, 0xb8, 0x6a, 0x63, 0xa9,
+	0xfb, 0x6f, 0xa4, 0x72, 0xbf, 0x4c, 0x5d, 0x00, 0x14, 0xba,
+	0xfa, 0x59, 0x88, 0xed, 0xe4, 0xe0, 0x8c, 0xa2, 0xec, 0x14,
+	0x7e, 0x2d, 0xe2, 0xf0, 0x46, 0x49, 0x95, 0x45,
+};
+
+static unsigned char test2048[] = {
+	0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
+	0x01, 0x00, 0xc0, 0xc0, 0xce, 0x3e, 0x3c, 0x53, 0x67, 0x3f,
+	0x4f, 0xc5, 0x2f, 0xa4, 0xc2, 0x5a, 0x2f, 0x58, 0xfd, 0x27,
+	0x52, 0x6a, 0xe8, 0xcf, 0x4a, 0x73, 0x47, 0x8d, 0x25, 0x0f,
+	0x5f, 0x03, 0x26, 0x78, 0xef, 0xf0, 0x22, 0x12, 0xd3, 0xde,
+	0x47, 0xb2, 0x1c, 0x0b, 0x38, 0x63, 0x1a, 0x6c, 0x85, 0x7a,
+	0x80, 0xc6, 0x8f, 0xa0, 0x41, 0xaf, 0x62, 0xc4, 0x67, 0x32,
+	0x88, 0xf8, 0xa6, 0x9c, 0xf5, 0x23, 0x1d, 0xe4, 0xac, 0x3f,
+	0x29, 0xf9, 0xec, 0xe1, 0x8b, 0x26, 0x03, 0x2c, 0xb2, 0xab,
+	0xf3, 0x7d, 0xb5, 0xca, 0x49, 0xc0, 0x8f, 0x1c, 0xdf, 0x33,
+	0x3a, 0x60, 0xda, 0x3c, 0xb0, 0x16, 0xf8, 0xa9, 0x12, 0x8f,
+	0x64, 0xac, 0x23, 0x0c, 0x69, 0x64, 0x97, 0x5d, 0x99, 0xd4,
+	0x09, 0x83, 0x9b, 0x61, 0xd3, 0xac, 0xf0, 0xde, 0xdd, 0x5e,
+	0x9f, 0x44, 0x94, 0xdb, 0x3a, 0x4d, 0x97, 0xe8, 0x52, 0x29,
+	0xf7, 0xdb, 0x94, 0x07, 0x45, 0x90, 0x78, 0x1e, 0x31, 0x0b,
+	0x80, 0xf7, 0x57, 0xad, 0x1c, 0x79, 0xc5, 0xcb, 0x32, 0xb0,
+	0xce, 0xcd, 0x74, 0xb3, 0xe2, 0x94, 0xc5, 0x78, 0x2f, 0x34,
+	0x1a, 0x45, 0xf7, 0x8c, 0x52, 0xa5, 0xbc, 0x8d, 0xec, 0xd1,
+	0x2f, 0x31, 0x3b, 0xf0, 0x49, 0x59, 0x5e, 0x88, 0x9d, 0x15,
+	0x92, 0x35, 0x32, 0xc1, 0xe7, 0x61, 0xec, 0x50, 0x48, 0x7c,
+	0xba, 0x05, 0xf9, 0xf8, 0xf8, 0xa7, 0x8c, 0x83, 0xe8, 0x66,
+	0x5b, 0xeb, 0xfe, 0xd8, 0x4f, 0xdd, 0x6d, 0x36, 0xc0, 0xb2,
+	0x90, 0x0f, 0xb8, 0x52, 0xf9, 0x04, 0x9b, 0x40, 0x2c, 0x27,
+	0xd6, 0x36, 0x8e, 0xc2, 0x1b, 0x44, 0xf3, 0x92, 0xd5, 0x15,
+	0x9e, 0x9a, 0xbc, 0xf3, 0x7d, 0x03, 0xd7, 0x02, 0x14, 0x20,
+	0xe9, 0x10, 0x92, 0xfd, 0xf9, 0xfc, 0x8f, 0xe5, 0x18, 0xe1,
+	0x95, 0xcc, 0x9e, 0x60, 0xa6, 0xfa, 0x38, 0x4d, 0x02, 0x03,
+	0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x00, 0xc3, 0xc3,
+	0x0d, 0xb4, 0x27, 0x90, 0x8d, 0x4b, 0xbf, 0xb8, 0x84, 0xaa,
+	0xd0, 0xb8, 0xc7, 0x5d, 0x99, 0xbe, 0x55, 0xf6, 0x3e, 0x7c,
+	0x49, 0x20, 0xcb, 0x8a, 0x8e, 0x19, 0x0e, 0x66, 0x24, 0xac,
+	0xaf, 0x03, 0x33, 0x97, 0xeb, 0x95, 0xd5, 0x3b, 0x0f, 0x40,
+	0x56, 0x04, 0x50, 0xd1, 0xe6, 0xbe, 0x84, 0x0b, 0x25, 0xd3,
+	0x9c, 0xe2, 0x83, 0x6c, 0xf5, 0x62, 0x5d, 0xba, 0x2b, 0x7d,
+	0x3d, 0x7a, 0x6c, 0xe1, 0xd2, 0x0e, 0x54, 0x93, 0x80, 0x01,
+	0x91, 0x51, 0x09, 0xe8, 0x5b, 0x8e, 0x47, 0xbd, 0x64, 0xe4,
+	0x0e, 0x03, 0x83, 0x55, 0xcf, 0x5a, 0x37, 0xf0, 0x25, 0xb5,
+	0x7d, 0x21, 0xd7, 0x69, 0xdf, 0x6f, 0xc2, 0xcf, 0x10, 0xc9,
+	0x8a, 0x40, 0x9f, 0x7a, 0x70, 0xc0, 0xe8, 0xe8, 0xc0, 0xe6,
+	0x9a, 0x15, 0x0a, 0x8d, 0x4e, 0x46, 0xcb, 0x7a, 0xdb, 0xb3,
+	0xcb, 0x83, 0x02, 0xc4, 0xf0, 0xab, 0xeb, 0x02, 0x01, 0x0e,
+	0x23, 0xfc, 0x1d, 0xc4, 0xbd, 0xd4, 0xaa, 0x5d, 0x31, 0x46,
+	0x99, 0xce, 0x9e, 0xf8, 0x04, 0x75, 0x10, 0x67, 0xc4, 0x53,
+	0x47, 0x44, 0xfa, 0xc2, 0x25, 0x73, 0x7e, 0xd0, 0x8e, 0x59,
+	0xd1, 0xb2, 0x5a, 0xf4, 0xc7, 0x18, 0x92, 0x2f, 0x39, 0xab,
+	0xcd, 0xa3, 0xb5, 0xc2, 0xb9, 0xc7, 0xb9, 0x1b, 0x9f, 0x48,
+	0xfa, 0x13, 0xc6, 0x98, 0x4d, 0xca, 0x84, 0x9c, 0x06, 0xca,
+	0xe7, 0x89, 0x01, 0x04, 0xc4, 0x6c, 0xfd, 0x29, 0x59, 0x35,
+	0xe7, 0xf3, 0xdd, 0xce, 0x64, 0x59, 0xbf, 0x21, 0x13, 0xa9,
+	0x9f, 0x0e, 0xc5, 0xff, 0xbd, 0x33, 0x00, 0xec, 0xac, 0x6b,
+	0x11, 0xef, 0x51, 0x5e, 0xad, 0x07, 0x15, 0xde, 0xb8, 0x5f,
+	0xc6, 0xb9, 0xa3, 0x22, 0x65, 0x46, 0x83, 0x14, 0xdf, 0xd0,
+	0xf1, 0x44, 0x8a, 0xe1, 0x9c, 0x23, 0x33, 0xb4, 0x97, 0x33,
+	0xe6, 0x6b, 0x81, 0x02, 0x81, 0x81, 0x00, 0xec, 0x12, 0xa7,
+	0x59, 0x74, 0x6a, 0xde, 0x3e, 0xad, 0xd8, 0x36, 0x80, 0x50,
+	0xa2, 0xd5, 0x21, 0x81, 0x07, 0xf1, 0xd0, 0x91, 0xf2, 0x6c,
+	0x12, 0x2f, 0x9d, 0x1a, 0x26, 0xf8, 0x30, 0x65, 0xdf, 0xe8,
+	0xc0, 0x9b, 0x6a, 0x30, 0x98, 0x82, 0x87, 0xec, 0xa2, 0x56,
+	0x87, 0x62, 0x6f, 0xe7, 0x9f, 0xf6, 0x56, 0xe6, 0x71, 0x8f,
+	0x49, 0x86, 0x93, 0x5a, 0x4d, 0x34, 0x58, 0xfe, 0xd9, 0x04,
+	0x13, 0xaf, 0x79, 0xb7, 0xad, 0x11, 0xd1, 0x30, 0x9a, 0x14,
+	0x06, 0xa0, 0xfa, 0xb7, 0x55, 0xdc, 0x6c, 0x5a, 0x4c, 0x2c,
+	0x59, 0x56, 0xf6, 0xe8, 0x9d, 0xaf, 0x0a, 0x78, 0x99, 0x06,
+	0x06, 0x9e, 0xe7, 0x9c, 0x51, 0x55, 0x43, 0xfc, 0x3b, 0x6c,
+	0x0b, 0xbf, 0x2d, 0x41, 0xa7, 0xaf, 0xb7, 0xe0, 0xe8, 0x28,
+	0x18, 0xb4, 0x13, 0xd1, 0xe6, 0x97, 0xd0, 0x9f, 0x6a, 0x80,
+	0xca, 0xdd, 0x1a, 0x7e, 0x15, 0x02, 0x81, 0x81, 0x00, 0xd1,
+	0x06, 0x0c, 0x1f, 0xe3, 0xd0, 0xab, 0xd6, 0xca, 0x7c, 0xbc,
+	0x7d, 0x13, 0x35, 0xce, 0x27, 0xcd, 0xd8, 0x49, 0x51, 0x63,
+	0x64, 0x0f, 0xca, 0x06, 0x12, 0xfc, 0x07, 0x3e, 0xaf, 0x61,
+	0x6d, 0xe2, 0x53, 0x39, 0x27, 0xae, 0xc3, 0x11, 0x9e, 0x94,
+	0x01, 0x4f, 0xe3, 0xf3, 0x67, 0xf9, 0x77, 0xf9, 0xe7, 0x95,
+	0x3a, 0x6f, 0xe2, 0x20, 0x73, 0x3e, 0xa4, 0x7a, 0x28, 0xd4,
+	0x61, 0x97, 0xf6, 0x17, 0xa0, 0x23, 0x10, 0x2b, 0xce, 0x84,
+	0x57, 0x7e, 0x25, 0x1f, 0xf4, 0xa8, 0x54, 0xd2, 0x65, 0x94,
+	0xcc, 0x95, 0x0a, 0xab, 0x30, 0xc1, 0x59, 0x1f, 0x61, 0x8e,
+	0xb9, 0x6b, 0xd7, 0x4e, 0xb9, 0x83, 0x43, 0x79, 0x85, 0x11,
+	0xbc, 0x0f, 0xae, 0x25, 0x20, 0x05, 0xbc, 0xd2, 0x48, 0xa1,
+	0x68, 0x09, 0x84, 0xf6, 0x12, 0x9a, 0x66, 0xb9, 0x2b, 0xbb,
+	0x76, 0x03, 0x17, 0x46, 0x4e, 0x97, 0x59, 0x02, 0x81, 0x80,
+	0x09, 0x4c, 0xfa, 0xd6, 0xe5, 0x65, 0x48, 0x78, 0x43, 0xb5,
+	0x1f, 0x00, 0x93, 0x2c, 0xb7, 0x24, 0xe8, 0xc6, 0x7d, 0x5a,
+	0x70, 0x45, 0x92, 0xc8, 0x6c, 0xa3, 0xcd, 0xe1, 0xf7, 0x29,
+	0x40, 0xfa, 0x3f, 0x5b, 0x47, 0x44, 0x39, 0xc1, 0xe8, 0x72,
+	0x9e, 0x7a, 0x0e, 0xda, 0xaa, 0xa0, 0x2a, 0x09, 0xfd, 0x54,
+	0x93, 0x23, 0xaa, 0x37, 0x85, 0x5b, 0xcc, 0xd4, 0xf9, 0xd8,
+	0xff, 0xc1, 0x61, 0x0d, 0xbd, 0x7e, 0x18, 0x24, 0x73, 0x6d,
+	0x40, 0x72, 0xf1, 0x93, 0x09, 0x48, 0x97, 0x6c, 0x84, 0x90,
+	0xa8, 0x46, 0x14, 0x01, 0x39, 0x11, 0xe5, 0x3c, 0x41, 0x27,
+	0x32, 0x75, 0x24, 0xed, 0xa1, 0xd9, 0x12, 0x29, 0x8a, 0x28,
+	0x71, 0x89, 0x8d, 0xca, 0x30, 0xb0, 0x01, 0xc4, 0x2f, 0x82,
+	0x19, 0x14, 0x4c, 0x70, 0x1c, 0xb8, 0x23, 0x2e, 0xe8, 0x90,
+	0x49, 0x97, 0x92, 0x97, 0x6b, 0x7a, 0x9d, 0xb9, 0x02, 0x81,
+	0x80, 0x0f, 0x0e, 0xa1, 0x76, 0xf6, 0xa1, 0x44, 0x8f, 0xaf,
+	0x7c, 0x76, 0xd3, 0x87, 0xbb, 0xbb, 0x83, 0x10, 0x88, 0x01,
+	0x18, 0x14, 0xd1, 0xd3, 0x75, 0x59, 0x24, 0xaa, 0xf5, 0x16,
+	0xa5, 0xe9, 0x9d, 0xd1, 0xcc, 0xee, 0xf4, 0x15, 0xd9, 0xc5,
+	0x7e, 0x27, 0xe9, 0x44, 0x49, 0x06, 0x72, 0xb9, 0xfc, 0xd3,
+	0x8a, 0xc4, 0x2c, 0x36, 0x7d, 0x12, 0x9b, 0x5a, 0xaa, 0xdc,
+	0x85, 0xee, 0x6e, 0xad, 0x54, 0xb3, 0xf4, 0xfc, 0x31, 0xa1,
+	0x06, 0x3a, 0x70, 0x57, 0x0c, 0xf3, 0x95, 0x5b, 0x3e, 0xe8,
+	0xfd, 0x1a, 0x4f, 0xf6, 0x78, 0x93, 0x46, 0x6a, 0xd7, 0x31,
+	0xb4, 0x84, 0x64, 0x85, 0x09, 0x38, 0x89, 0x92, 0x94, 0x1c,
+	0xbf, 0xe2, 0x3c, 0x2a, 0xe0, 0xff, 0x99, 0xa3, 0xf0, 0x2b,
+	0x31, 0xc2, 0x36, 0xcd, 0x60, 0xbf, 0x9d, 0x2d, 0x74, 0x32,
+	0xe8, 0x9c, 0x93, 0x6e, 0xbb, 0x91, 0x7b, 0xfd, 0xd9, 0x02,
+	0x81, 0x81, 0x00, 0xa2, 0x71, 0x25, 0x38, 0xeb, 0x2a, 0xe9,
+	0x37, 0xcd, 0xfe, 0x44, 0xce, 0x90, 0x3f, 0x52, 0x87, 0x84,
+	0x52, 0x1b, 0xae, 0x8d, 0x22, 0x94, 0xce, 0x38, 0xe6, 0x04,
+	0x88, 0x76, 0x85, 0x9a, 0xd3, 0x14, 0x09, 0xe5, 0x69, 0x9a,
+	0xff, 0x58, 0x92, 0x02, 0x6a, 0x7d, 0x7c, 0x1e, 0x2c, 0xfd,
+	0xa8, 0xca, 0x32, 0x14, 0x4f, 0x0d, 0x84, 0x0d, 0x37, 0x43,
+	0xbf, 0xe4, 0x5d, 0x12, 0xc8, 0x24, 0x91, 0x27, 0x8d, 0x46,
+	0xd9, 0x54, 0x53, 0xe7, 0x62, 0x71, 0xa8, 0x2b, 0x71, 0x41,
+	0x8d, 0x75, 0xf8, 0x3a, 0xa0, 0x61, 0x29, 0x46, 0xa6, 0xe5,
+	0x82, 0xfa, 0x3a, 0xd9, 0x08, 0xfa, 0xfc, 0x63, 0xfd, 0x6b,
+	0x30, 0xbc, 0xf4, 0x4e, 0x9e, 0x8c, 0x25, 0x0c, 0xb6, 0x55,
+	0xe7, 0x3c, 0xd4, 0x4e, 0x0b, 0xfd, 0x8b, 0xc3, 0x0e, 0x1d,
+	0x9c, 0x44, 0x57, 0x8f, 0x1f, 0x86, 0xf7, 0xd5, 0x1b, 0xe4,
+	0x95,
+};
+
+static unsigned char test4096[] = {
+	0x30, 0x82, 0x09, 0x29, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02,
+	0x01, 0x00, 0xc0, 0x71, 0xac, 0x1a, 0x13, 0x88, 0x82, 0x43,
+	0x3b, 0x51, 0x57, 0x71, 0x8d, 0xb6, 0x2b, 0x82, 0x65, 0x21,
+	0x53, 0x5f, 0x28, 0x29, 0x4f, 0x8d, 0x7c, 0x8a, 0xb9, 0x44,
+	0xb3, 0x28, 0x41, 0x4f, 0xd3, 0xfa, 0x6a, 0xf8, 0xb9, 0x28,
+	0x50, 0x39, 0x67, 0x53, 0x2c, 0x3c, 0xd7, 0xcb, 0x96, 0x41,
+	0x40, 0x32, 0xbb, 0xeb, 0x70, 0xae, 0x1f, 0xb0, 0x65, 0xf7,
+	0x3a, 0xd9, 0x22, 0xfd, 0x10, 0xae, 0xbd, 0x02, 0xe2, 0xdd,
+	0xf3, 0xc2, 0x79, 0x3c, 0xc6, 0xfc, 0x75, 0xbb, 0xaf, 0x4e,
+	0x3a, 0x36, 0xc2, 0x4f, 0xea, 0x25, 0xdf, 0x13, 0x16, 0x4b,
+	0x20, 0xfe, 0x4b, 0x69, 0x16, 0xc4, 0x7f, 0x1a, 0x43, 0xa6,
+	0x17, 0x1b, 0xb9, 0x0a, 0xf3, 0x09, 0x86, 0x28, 0x89, 0xcf,
+	0x2c, 0xd0, 0xd4, 0x81, 0xaf, 0xc6, 0x6d, 0xe6, 0x21, 0x8d,
+	0xee, 0xef, 0xea, 0xdc, 0xb7, 0xc6, 0x3b, 0x63, 0x9f, 0x0e,
+	0xad, 0x89, 0x78, 0x23, 0x18, 0xbf, 0x70, 0x7e, 0x84, 0xe0,
+	0x37, 0xec, 0xdb, 0x8e, 0x9c, 0x3e, 0x6a, 0x19, 0xcc, 0x99,
+	0x72, 0xe6, 0xb5, 0x7d, 0x6d, 0xfa, 0xe5, 0xd3, 0xe4, 0x90,
+	0xb5, 0xb2, 0xb2, 0x12, 0x70, 0x4e, 0xca, 0xf8, 0x10, 0xf8,
+	0xa3, 0x14, 0xc2, 0x48, 0x19, 0xeb, 0x60, 0x99, 0xbb, 0x2a,
+	0x1f, 0xb1, 0x7a, 0xb1, 0x3d, 0x24, 0xfb, 0xa0, 0x29, 0xda,
+	0xbd, 0x1b, 0xd7, 0xa4, 0xbf, 0xef, 0x60, 0x2d, 0x22, 0xca,
+	0x65, 0x98, 0xf1, 0xc4, 0xe1, 0xc9, 0x02, 0x6b, 0x16, 0x28,
+	0x2f, 0xa1, 0xaa, 0x79, 0x00, 0xda, 0xdc, 0x7c, 0x43, 0xf7,
+	0x42, 0x3c, 0xa0, 0xef, 0x68, 0xf7, 0xdf, 0xb9, 0x69, 0xfb,
+	0x8e, 0x01, 0xed, 0x01, 0x42, 0xb5, 0x4e, 0x57, 0xa6, 0x26,
+	0xb8, 0xd0, 0x7b, 0x56, 0x6d, 0x03, 0xc6, 0x40, 0x8c, 0x8c,
+	0x2a, 0x55, 0xd7, 0x9c, 0x35, 0x00, 0x94, 0x93, 0xec, 0x03,
+	0xeb, 0x22, 0xef, 0x77, 0xbb, 0x79, 0x13, 0x3f, 0x15, 0xa1,
+	0x8f, 0xca, 0xdf, 0xfd, 0xd3, 0xb8, 0xe1, 0xd4, 0xcc, 0x09,
+	0x3f, 0x3c, 0x2c, 0xdb, 0xd1, 0x49, 0x7f, 0x38, 0x07, 0x83,
+	0x6d, 0xeb, 0x08, 0x66, 0xe9, 0x06, 0x44, 0x12, 0xac, 0x95,
+	0x22, 0x90, 0x23, 0x67, 0xd4, 0x08, 0xcc, 0xf4, 0xb7, 0xdc,
+	0xcc, 0x87, 0xd4, 0xac, 0x69, 0x35, 0x4c, 0xb5, 0x39, 0x36,
+	0xcd, 0xa4, 0xd2, 0x95, 0xca, 0x0d, 0xc5, 0xda, 0xc2, 0xc5,
+	0x22, 0x32, 0x28, 0x08, 0xe3, 0xd2, 0x8b, 0x38, 0x30, 0xdc,
+	0x8c, 0x75, 0x4f, 0x6a, 0xec, 0x7a, 0xac, 0x16, 0x3e, 0xa8,
+	0xd4, 0x6a, 0x45, 0xe1, 0xa8, 0x4f, 0x2e, 0x80, 0x34, 0xaa,
+	0x54, 0x1b, 0x02, 0x95, 0x7d, 0x8a, 0x6d, 0xcc, 0x79, 0xca,
+	0xf2, 0xa4, 0x2e, 0x8d, 0xfb, 0xfe, 0x15, 0x51, 0x10, 0x0e,
+	0x4d, 0x88, 0xb1, 0xc7, 0xf4, 0x79, 0xdb, 0xf0, 0xb4, 0x56,
+	0x44, 0x37, 0xca, 0x5a, 0xc1, 0x8c, 0x48, 0xac, 0xae, 0x48,
+	0x80, 0x83, 0x01, 0x3f, 0xde, 0xd9, 0xd3, 0x2c, 0x51, 0x46,
+	0xb1, 0x41, 0xb6, 0xc6, 0x91, 0x72, 0xf9, 0x83, 0x55, 0x1b,
+	0x8c, 0xba, 0xf3, 0x73, 0xe5, 0x2c, 0x74, 0x50, 0x3a, 0xbe,
+	0xc5, 0x2f, 0xa7, 0xb2, 0x6d, 0x8c, 0x9e, 0x13, 0x77, 0xa3,
+	0x13, 0xcd, 0x6d, 0x8c, 0x45, 0xe1, 0xfc, 0x0b, 0xb7, 0x69,
+	0xe9, 0x27, 0xbc, 0x65, 0xc3, 0xfa, 0x9b, 0xd0, 0xef, 0xfe,
+	0xe8, 0x1f, 0xb3, 0x5e, 0x34, 0xf4, 0x8c, 0xea, 0xfc, 0xd3,
+	0x81, 0xbf, 0x3d, 0x30, 0xb2, 0xb4, 0x01, 0xe8, 0x43, 0x0f,
+	0xba, 0x02, 0x23, 0x42, 0x76, 0x82, 0x31, 0x73, 0x91, 0xed,
+	0x07, 0x46, 0x61, 0x0d, 0x39, 0x83, 0x40, 0xce, 0x7a, 0xd4,
+	0xdb, 0x80, 0x2c, 0x1f, 0x0d, 0xd1, 0x34, 0xd4, 0x92, 0xe3,
+	0xd4, 0xf1, 0xc2, 0x01, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
+	0x82, 0x02, 0x01, 0x00, 0x97, 0x6c, 0xda, 0x6e, 0xea, 0x4f,
+	0xcf, 0xaf, 0xf7, 0x4c, 0xd9, 0xf1, 0x90, 0x00, 0x77, 0xdb,
+	0xf2, 0x97, 0x76, 0x72, 0xb9, 0xb7, 0x47, 0xd1, 0x9c, 0xdd,
+	0xcb, 0x4a, 0x33, 0x6e, 0xc9, 0x75, 0x76, 0xe6, 0xe4, 0xa5,
+	0x31, 0x8c, 0x77, 0x13, 0xb4, 0x29, 0xcd, 0xf5, 0x52, 0x17,
+	0xef, 0xf3, 0x08, 0x00, 0xe3, 0xbd, 0x2e, 0xbc, 0xd4, 0x52,
+	0x88, 0xe9, 0x30, 0x75, 0x0b, 0x02, 0xf5, 0xcd, 0x89, 0x0c,
+	0x6c, 0x57, 0x19, 0x27, 0x3d, 0x1e, 0x85, 0xb4, 0xc1, 0x2f,
+	0x1d, 0x92, 0x00, 0x5c, 0x76, 0x29, 0x4b, 0xa4, 0xe1, 0x12,
+	0xb3, 0xc8, 0x09, 0xfe, 0x0e, 0x78, 0x72, 0x61, 0xcb, 0x61,
+	0x6f, 0x39, 0x91, 0x95, 0x4e, 0xd5, 0x3e, 0xc7, 0x8f, 0xb8,
+	0xf6, 0x36, 0xfe, 0x9c, 0x93, 0x9a, 0x38, 0x25, 0x7a, 0xf4,
+	0x4a, 0x12, 0xd4, 0xa0, 0x13, 0xbd, 0xf9, 0x1d, 0x12, 0x3e,
+	0x21, 0x39, 0xfb, 0x72, 0xe0, 0x05, 0x3d, 0xc3, 0xe5, 0x50,
+	0xa8, 0x5d, 0x85, 0xa3, 0xea, 0x5f, 0x1c, 0xb2, 0x3f, 0xea,
+	0x6d, 0x03, 0x91, 0x55, 0xd8, 0x19, 0x0a, 0x21, 0x12, 0x16,
+	0xd9, 0x12, 0xc4, 0xe6, 0x07, 0x18, 0x5b, 0x26, 0xa4, 0xae,
+	0xed, 0x2b, 0xb7, 0xa6, 0xed, 0xf8, 0xad, 0xec, 0x77, 0xe6,
+	0x7f, 0x4f, 0x76, 0x00, 0xc0, 0xfa, 0x15, 0x92, 0xb4, 0x2c,
+	0x22, 0xc2, 0xeb, 0x6a, 0xad, 0x14, 0x05, 0xb2, 0xe5, 0x8a,
+	0x9e, 0x85, 0x83, 0xcc, 0x04, 0xf1, 0x56, 0x78, 0x44, 0x5e,
+	0xde, 0xe0, 0x60, 0x1a, 0x65, 0x79, 0x31, 0x23, 0x05, 0xbb,
+	0x01, 0xff, 0xdd, 0x2e, 0xb7, 0xb3, 0xaa, 0x74, 0xe0, 0xa5,
+	0x94, 0xaf, 0x4b, 0xde, 0x58, 0x0f, 0x55, 0xde, 0x33, 0xf6,
+	0xe3, 0xd6, 0x34, 0x36, 0x57, 0xd6, 0x79, 0x91, 0x2e, 0xbe,
+	0x3b, 0xd9, 0x4e, 0xb6, 0x9d, 0x21, 0x5c, 0xd3, 0x48, 0x14,
+	0x7f, 0x4a, 0xc4, 0x60, 0xa9, 0x29, 0xf8, 0x53, 0x7f, 0x88,
+	0x11, 0x2d, 0xb5, 0xc5, 0x2d, 0x6f, 0xee, 0x85, 0x0b, 0xf7,
+	0x8d, 0x9a, 0xbe, 0xb0, 0x42, 0xf2, 0x2e, 0x71, 0xaf, 0x19,
+	0x31, 0x6d, 0xec, 0xcd, 0x6f, 0x2b, 0x23, 0xdf, 0xb4, 0x40,
+	0xaf, 0x2c, 0x0a, 0xc3, 0x1b, 0x7d, 0x7d, 0x03, 0x1d, 0x4b,
+	0xf3, 0xb5, 0xe0, 0x85, 0xd8, 0xdf, 0x91, 0x6b, 0x0a, 0x69,
+	0xf7, 0xf2, 0x69, 0x66, 0x5b, 0xf1, 0xcf, 0x46, 0x7d, 0xe9,
+	0x70, 0xfa, 0x6d, 0x7e, 0x75, 0x4e, 0xa9, 0x77, 0xe6, 0x8c,
+	0x02, 0xf7, 0x14, 0x4d, 0xa5, 0x41, 0x8f, 0x3f, 0xc1, 0x62,
+	0x1e, 0x71, 0x5e, 0x38, 0xb4, 0xd6, 0xe6, 0xe1, 0x4b, 0xc2,
+	0x2c, 0x30, 0x83, 0x81, 0x6f, 0x49, 0x2e, 0x96, 0xe6, 0xc9,
+	0x9a, 0xf7, 0x5d, 0x09, 0xa0, 0x55, 0x02, 0xa5, 0x3a, 0x25,
+	0x23, 0xd0, 0x92, 0xc3, 0xa3, 0xe3, 0x0e, 0x12, 0x2f, 0x4d,
+	0xef, 0xf3, 0x55, 0x5a, 0xbe, 0xe6, 0x19, 0x86, 0x31, 0xab,
+	0x75, 0x9a, 0xd3, 0xf0, 0x2c, 0xc5, 0x41, 0x92, 0xd9, 0x1f,
+	0x5f, 0x11, 0x8c, 0x75, 0x1c, 0x63, 0xd0, 0x02, 0x80, 0x2c,
+	0x68, 0xcb, 0x93, 0xfb, 0x51, 0x73, 0x49, 0xb4, 0x60, 0xda,
+	0xe2, 0x26, 0xaf, 0xa9, 0x46, 0x12, 0xb8, 0xec, 0x50, 0xdd,
+	0x12, 0x06, 0x5f, 0xce, 0x59, 0xe6, 0xf6, 0x1c, 0xe0, 0x54,
+	0x10, 0xad, 0xf6, 0xcd, 0x98, 0xcc, 0x0f, 0xfb, 0xcb, 0x41,
+	0x14, 0x9d, 0xed, 0xe4, 0xb4, 0x74, 0x5f, 0x09, 0x60, 0xc7,
+	0x12, 0xf6, 0x7b, 0x3c, 0x8f, 0xa7, 0x20, 0xbc, 0xe4, 0xb1,
+	0xef, 0xeb, 0xa4, 0x93, 0xc5, 0x06, 0xca, 0x9a, 0x27, 0x9d,
+	0x87, 0xf3, 0xde, 0xca, 0xe5, 0xe7, 0xf6, 0x1c, 0x01, 0x65,
+	0x5b, 0xfb, 0x19, 0x79, 0x6e, 0x08, 0x26, 0xc5, 0xc8, 0x28,
+	0x0e, 0xb6, 0x3b, 0x07, 0x08, 0xc1, 0x02, 0x82, 0x01, 0x01,
+	0x00, 0xe8, 0x1c, 0x73, 0xa6, 0xb8, 0xe0, 0x0e, 0x6d, 0x8d,
+	0x1b, 0xb9, 0x53, 0xed, 0x58, 0x94, 0xe6, 0x1d, 0x60, 0x14,
+	0x5c, 0x76, 0x43, 0xc4, 0x58, 0x19, 0xc4, 0x24, 0xe8, 0xbc,
+	0x1b, 0x3b, 0x0b, 0x13, 0x24, 0x45, 0x54, 0x0e, 0xcc, 0x37,
+	0xf0, 0xe0, 0x63, 0x7d, 0xc3, 0xf7, 0xfb, 0x81, 0x74, 0x81,
+	0xc4, 0x0f, 0x1a, 0x21, 0x48, 0xaf, 0xce, 0xc1, 0xc4, 0x94,
+	0x18, 0x06, 0x44, 0x8d, 0xd3, 0xd2, 0x22, 0x2d, 0x2d, 0x3e,
+	0x5a, 0x31, 0xdc, 0x95, 0x8e, 0xf4, 0x41, 0xfc, 0x58, 0xc9,
+	0x40, 0x92, 0x17, 0x5f, 0xe3, 0xda, 0xac, 0x9e, 0x3f, 0x1c,
+	0x2a, 0x6b, 0x58, 0x5f, 0x48, 0x78, 0x20, 0xb1, 0xaf, 0x24,
+	0x9b, 0x3c, 0x20, 0x8b, 0x93, 0x25, 0x9e, 0xe6, 0x6b, 0xbc,
+	0x13, 0x42, 0x14, 0x6c, 0x36, 0x31, 0xff, 0x7a, 0xd1, 0xc1,
+	0x1a, 0x26, 0x14, 0x7f, 0xa9, 0x76, 0xa7, 0x0c, 0xf8, 0xcc,
+	0xed, 0x07, 0x6a, 0xd2, 0xdf, 0x62, 0xee, 0x0a, 0x7c, 0x84,
+	0xcb, 0x49, 0x90, 0xb2, 0x03, 0x0d, 0xa2, 0x82, 0x06, 0x77,
+	0xf1, 0xcd, 0x67, 0xf2, 0x47, 0x21, 0x02, 0x3f, 0x43, 0x21,
+	0xf0, 0x46, 0x30, 0x62, 0x51, 0x72, 0xb1, 0xe7, 0x48, 0xc6,
+	0x67, 0x12, 0xcd, 0x9e, 0xd6, 0x15, 0xe5, 0x21, 0xed, 0xfa,
+	0x8f, 0x30, 0xa6, 0x41, 0xfe, 0xb6, 0xfa, 0x8f, 0x34, 0x14,
+	0x19, 0xe8, 0x11, 0xf7, 0xa5, 0x77, 0x3e, 0xb7, 0xf9, 0x39,
+	0x07, 0x8c, 0x67, 0x2a, 0xab, 0x7b, 0x08, 0xf8, 0xb0, 0x06,
+	0xa8, 0xea, 0x2f, 0x8f, 0xfa, 0xcc, 0xcc, 0x40, 0xce, 0xf3,
+	0x70, 0x4f, 0x3f, 0x7f, 0xe2, 0x0c, 0xea, 0x76, 0x4a, 0x35,
+	0x4e, 0x47, 0xad, 0x2b, 0xa7, 0x97, 0x5d, 0x74, 0x43, 0x97,
+	0x90, 0xd2, 0xfb, 0xd9, 0xf9, 0x96, 0x01, 0x33, 0x05, 0xed,
+	0x7b, 0x03, 0x05, 0xad, 0xf8, 0x49, 0x03, 0x02, 0x82, 0x01,
+	0x01, 0x00, 0xd4, 0x40, 0x17, 0x66, 0x10, 0x92, 0x95, 0xc8,
+	0xec, 0x62, 0xa9, 0x7a, 0xcb, 0x93, 0x8e, 0xe6, 0x53, 0xd4,
+	0x80, 0x48, 0x27, 0x4b, 0x41, 0xce, 0x61, 0xdf, 0xbf, 0x94,
+	0xa4, 0x3d, 0x71, 0x03, 0x0b, 0xed, 0x25, 0x71, 0x98, 0xa4,
+	0xd6, 0xd5, 0x4a, 0x57, 0xf5, 0x6c, 0x1b, 0xda, 0x21, 0x7d,
+	0x35, 0x45, 0xb3, 0xf3, 0x6a, 0xd9, 0xd3, 0x43, 0xe8, 0x5c,
+	0x54, 0x1c, 0x83, 0x1b, 0xb4, 0x5f, 0xf2, 0x97, 0x24, 0x2e,
+	0xdc, 0x40, 0xde, 0x92, 0x23, 0x59, 0x8e, 0xbc, 0xd2, 0xa1,
+	0xf2, 0xe0, 0x4c, 0xdd, 0x0b, 0xd1, 0xe7, 0xae, 0x65, 0xbc,
+	0xb5, 0xf5, 0x5b, 0x98, 0xe9, 0xd7, 0xc2, 0xb7, 0x0e, 0x55,
+	0x71, 0x0e, 0x3c, 0x0a, 0x24, 0x6b, 0xa6, 0xe6, 0x14, 0x61,
+	0x11, 0xfd, 0x33, 0x42, 0x99, 0x2b, 0x84, 0x77, 0x74, 0x92,
+	0x91, 0xf5, 0x79, 0x79, 0xcf, 0xad, 0x8e, 0x04, 0xef, 0x80,
+	0x1e, 0x57, 0xf4, 0x14, 0xf5, 0x35, 0x09, 0x74, 0xb2, 0x13,
+	0x71, 0x58, 0x6b, 0xea, 0x32, 0x5d, 0xf3, 0xd3, 0x76, 0x48,
+	0x39, 0x10, 0x23, 0x84, 0x9d, 0xbe, 0x92, 0x77, 0x4a, 0xed,
+	0x70, 0x3e, 0x1a, 0xa2, 0x6c, 0xb3, 0x81, 0x00, 0xc3, 0xc9,
+	0xe4, 0x52, 0xc8, 0x24, 0x88, 0x0c, 0x41, 0xad, 0x87, 0x5a,
+	0xea, 0xa3, 0x7a, 0x85, 0x1c, 0x5e, 0x31, 0x7f, 0xc3, 0x35,
+	0xc6, 0xfa, 0x10, 0xc8, 0x75, 0x10, 0xc4, 0x96, 0x99, 0xe7,
+	0xfe, 0x01, 0xb4, 0x74, 0xdb, 0xb4, 0x11, 0xc3, 0xc8, 0x8c,
+	0xf6, 0xf7, 0x3b, 0x66, 0x50, 0xfc, 0xdb, 0xeb, 0xca, 0x47,
+	0x85, 0x89, 0xe1, 0x65, 0xd9, 0x62, 0x34, 0x3c, 0x70, 0xd8,
+	0x2e, 0xb4, 0x2f, 0x65, 0x3c, 0x4a, 0xa6, 0x2a, 0xe7, 0xc7,
+	0xd8, 0x41, 0x8f, 0x8a, 0x43, 0xbf, 0x42, 0xf2, 0x4d, 0xbc,
+	0xfc, 0x9e, 0x27, 0x95, 0xfb, 0x75, 0xff, 0xab, 0x02, 0x82,
+	0x01, 0x00, 0x41, 0x2f, 0x44, 0x57, 0x6d, 0x12, 0x17, 0x5b,
+	0x32, 0xc6, 0xb7, 0x6c, 0x57, 0x7a, 0x8a, 0x0e, 0x79, 0xef,
+	0x72, 0xa8, 0x68, 0xda, 0x2d, 0x38, 0xe4, 0xbb, 0x8d, 0xf6,
+	0x02, 0x65, 0xcf, 0x56, 0x13, 0xe1, 0x1a, 0xcb, 0x39, 0x80,
+	0xa6, 0xb1, 0x32, 0x03, 0x1e, 0xdd, 0xbb, 0x35, 0xd9, 0xac,
+	0x43, 0x89, 0x31, 0x08, 0x90, 0x92, 0x5e, 0x35, 0x3d, 0x7b,
+	0x9c, 0x6f, 0x86, 0xcb, 0x17, 0xdd, 0x85, 0xe4, 0xed, 0x35,
+	0x08, 0x8e, 0xc1, 0xf4, 0x05, 0xd8, 0x68, 0xc6, 0x63, 0x3c,
+	0xf7, 0xff, 0xf7, 0x47, 0x33, 0x39, 0xc5, 0x3e, 0xb7, 0x0e,
+	0x58, 0x35, 0x9d, 0x81, 0xea, 0xf8, 0x6a, 0x2c, 0x1c, 0x5a,
+	0x68, 0x78, 0x64, 0x11, 0x6b, 0xc1, 0x3e, 0x4e, 0x7a, 0xbd,
+	0x84, 0xcb, 0x0f, 0xc2, 0xb6, 0x85, 0x1d, 0xd3, 0x76, 0xc5,
+	0x93, 0x6a, 0x69, 0x89, 0x56, 0x34, 0xdc, 0x4a, 0x9b, 0xbc,
+	0xff, 0xa8, 0x0d, 0x6e, 0x35, 0x9c, 0x60, 0xa7, 0x23, 0x30,
+	0xc7, 0x06, 0x64, 0x39, 0x8b, 0x94, 0x89, 0xee, 0xba, 0x7f,
+	0x60, 0x8d, 0xfa, 0xb6, 0x97, 0x76, 0xdc, 0x51, 0x4a, 0x3c,
+	0xeb, 0x3a, 0x14, 0x2c, 0x20, 0x60, 0x69, 0x4a, 0x86, 0xfe,
+	0x8c, 0x21, 0x84, 0x49, 0x54, 0xb3, 0x20, 0xe1, 0x01, 0x7f,
+	0x58, 0xdf, 0x7f, 0xb5, 0x21, 0x51, 0x8c, 0x47, 0x9f, 0x91,
+	0xeb, 0x97, 0x3e, 0xf2, 0x54, 0xcf, 0x16, 0x46, 0xf9, 0xd9,
+	0xb6, 0xe7, 0x64, 0xc9, 0xd0, 0x54, 0xea, 0x2f, 0xa1, 0xcf,
+	0xa5, 0x7f, 0x28, 0x8d, 0x84, 0xec, 0xd5, 0x39, 0x03, 0x76,
+	0x5b, 0x2d, 0x8e, 0x43, 0xf2, 0x01, 0x24, 0xc9, 0x6f, 0xc0,
+	0xf5, 0x69, 0x6f, 0x7d, 0xb5, 0x85, 0xd2, 0x5f, 0x7f, 0x78,
+	0x40, 0x07, 0x7f, 0x09, 0x15, 0xb5, 0x1f, 0x28, 0x65, 0x10,
+	0xe4, 0x19, 0xa8, 0xc6, 0x9e, 0x8d, 0xdc, 0xcb, 0x02, 0x82,
+	0x01, 0x00, 0x13, 0x01, 0xee, 0x56, 0x80, 0x93, 0x70, 0x00,
+	0x7f, 0x52, 0xd2, 0x94, 0xa1, 0x98, 0x84, 0x4a, 0x92, 0x25,
+	0x4c, 0x9b, 0xa9, 0x91, 0x2e, 0xc2, 0x79, 0xb7, 0x5c, 0xe3,
+	0xc5, 0xd5, 0x8e, 0xc2, 0x54, 0x16, 0x17, 0xad, 0x55, 0x9b,
+	0x25, 0x76, 0x12, 0x63, 0x50, 0x22, 0x2f, 0x58, 0x58, 0x79,
+	0x6b, 0x04, 0xe3, 0xf9, 0x9f, 0x8f, 0x04, 0x41, 0x67, 0x94,
+	0xa5, 0x1f, 0xac, 0x8a, 0x15, 0x9c, 0x26, 0x10, 0x6c, 0xf8,
+	0x19, 0x57, 0x61, 0xd7, 0x3a, 0x7d, 0x31, 0xb0, 0x2d, 0x38,
+	0xbd, 0x94, 0x62, 0xad, 0xc4, 0xfa, 0x36, 0x42, 0x42, 0xf0,
+	0x24, 0x67, 0x65, 0x9d, 0x8b, 0x0b, 0x7c, 0x6f, 0x82, 0x44,
+	0x1a, 0x8c, 0xc8, 0xc9, 0xab, 0xbb, 0x4c, 0x45, 0xfc, 0x7b,
+	0x38, 0xee, 0x30, 0xe1, 0xfc, 0xef, 0x8d, 0xbc, 0x58, 0xdf,
+	0x2b, 0x5d, 0x0d, 0x54, 0xe0, 0x49, 0x4d, 0x97, 0x99, 0x8f,
+	0x22, 0xa8, 0x83, 0xbe, 0x40, 0xbb, 0x50, 0x2e, 0x78, 0x28,
+	0x0f, 0x95, 0x78, 0x8c, 0x8f, 0x98, 0x24, 0x56, 0xc2, 0x97,
+	0xf3, 0x2c, 0x43, 0xd2, 0x03, 0x82, 0x66, 0x81, 0x72, 0x5f,
+	0x53, 0x16, 0xec, 0xb1, 0xb1, 0x04, 0x5e, 0x40, 0x20, 0x48,
+	0x7b, 0x3f, 0x02, 0x97, 0x6a, 0xeb, 0x96, 0x12, 0x21, 0x35,
+	0xfe, 0x1f, 0x47, 0xc0, 0x95, 0xea, 0xc5, 0x8a, 0x08, 0x84,
+	0x4f, 0x5e, 0x63, 0x94, 0x60, 0x0f, 0x71, 0x5b, 0x7f, 0x4a,
+	0xec, 0x4f, 0x60, 0xc6, 0xba, 0x4a, 0x24, 0xf1, 0x20, 0x8b,
+	0xa7, 0x2e, 0x3a, 0xce, 0x8d, 0xe0, 0x27, 0x1d, 0xb5, 0x8e,
+	0xb4, 0x21, 0xc5, 0xe2, 0xa6, 0x16, 0x0a, 0x51, 0x83, 0x55,
+	0x88, 0xd1, 0x30, 0x11, 0x63, 0xd5, 0xd7, 0x8d, 0xae, 0x16,
+	0x12, 0x82, 0xc4, 0x85, 0x00, 0x4e, 0x27, 0x83, 0xa5, 0x7c,
+	0x90, 0x2e, 0xe5, 0xa2, 0xa3, 0xd3, 0x4c, 0x63, 0x02, 0x82,
+	0x01, 0x01, 0x00, 0x86, 0x08, 0x98, 0x98, 0xa5, 0x00, 0x05,
+	0x39, 0x77, 0xd9, 0x66, 0xb3, 0xcf, 0xca, 0xa0, 0x71, 0xb3,
+	0x50, 0xce, 0x3d, 0xb1, 0x93, 0x95, 0x35, 0xc4, 0xd4, 0x2e,
+	0x90, 0xdf, 0x0f, 0xfc, 0x60, 0xc1, 0x94, 0x68, 0x61, 0x43,
+	0xca, 0x9a, 0x23, 0x4a, 0x1e, 0x45, 0x72, 0x99, 0xb5, 0x1e,
+	0x61, 0x8d, 0x77, 0x0f, 0xa0, 0xbb, 0xd7, 0x77, 0xb4, 0x2a,
+	0x15, 0x11, 0x88, 0x2d, 0xb3, 0x56, 0x61, 0x5e, 0x6a, 0xed,
+	0xa4, 0x46, 0x4a, 0x3f, 0x50, 0x11, 0xd6, 0xba, 0xb6, 0xd7,
+	0x95, 0x65, 0x53, 0xc3, 0xa1, 0x8f, 0xe0, 0xa3, 0xf5, 0x1c,
+	0xfd, 0xaf, 0x6e, 0x43, 0xd7, 0x17, 0xa7, 0xd3, 0x81, 0x1b,
+	0xa4, 0xdf, 0xe0, 0x97, 0x8a, 0x46, 0x03, 0xd3, 0x46, 0x0e,
+	0x83, 0x48, 0x4e, 0xd2, 0x02, 0xcb, 0xc0, 0xad, 0x79, 0x95,
+	0x8c, 0x96, 0xba, 0x40, 0x34, 0x11, 0x71, 0x5e, 0xe9, 0x11,
+	0xf9, 0xc5, 0x4a, 0x5e, 0x91, 0x9d, 0xf5, 0x92, 0x4f, 0xeb,
+	0xc6, 0x70, 0x02, 0x2d, 0x3d, 0x04, 0xaa, 0xe9, 0x3a, 0x8e,
+	0xd5, 0xa8, 0xad, 0xf7, 0xce, 0x0d, 0x16, 0xb2, 0xec, 0x0a,
+	0x9c, 0xf5, 0x94, 0x39, 0xb9, 0x8a, 0xfc, 0x1e, 0xf9, 0xcc,
+	0xf2, 0x5f, 0x21, 0x31, 0x74, 0x72, 0x6b, 0x64, 0xae, 0x35,
+	0x61, 0x8d, 0x0d, 0xcb, 0xe7, 0xda, 0x39, 0xca, 0xf3, 0x21,
+	0x66, 0x0b, 0x95, 0xd7, 0x0a, 0x7c, 0xca, 0xa1, 0xa9, 0x5a,
+	0xe8, 0xac, 0xe0, 0x71, 0x54, 0xaf, 0x28, 0xcf, 0xd5, 0x70,
+	0x89, 0xe0, 0xf3, 0x9e, 0x43, 0x6c, 0x8d, 0x7b, 0x99, 0x01,
+	0x68, 0x4d, 0xa1, 0x45, 0x46, 0x0c, 0x43, 0xbc, 0xcc, 0x2c,
+	0xdd, 0xc5, 0x46, 0xc8, 0x4e, 0x0e, 0xbe, 0xed, 0xb9, 0x26,
+	0xab, 0x2e, 0xdb, 0xeb, 0x8f, 0xff, 0xdb, 0xb0, 0xc6, 0x55,
+	0xaf, 0xf8, 0x2a, 0x91, 0x9d, 0x50, 0x44, 0x21, 0x17,
+};
diff --git a/apps/openssl/timeouts.h b/apps/openssl/timeouts.h
new file mode 100644
index 0000000..dd2f850
--- /dev/null
+++ b/apps/openssl/timeouts.h
@@ -0,0 +1,67 @@
+/* $OpenBSD: timeouts.h,v 1.1 2014/08/26 17:47:25 jsing Exp $ */
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef INCLUDED_TIMEOUTS_H
+#define INCLUDED_TIMEOUTS_H
+
+/* numbers in us */
+#define DGRAM_RCV_TIMEOUT         250000
+#define DGRAM_SND_TIMEOUT         250000
+
+#endif /* ! INCLUDED_TIMEOUTS_H */
diff --git a/apps/openssl/ts.c b/apps/openssl/ts.c
new file mode 100644
index 0000000..8400818
--- /dev/null
+++ b/apps/openssl/ts.c
@@ -0,0 +1,1252 @@
+/* $OpenBSD: ts.c,v 1.26 2023/03/06 14:32:06 tb Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Length of the nonce of the request in bits (must be a multiple of 8). */
+#define	NONCE_LENGTH		64
+
+/* Macro definitions for the configuration file. */
+#define	ENV_OID_FILE		"oid_file"
+
+/* Local function declarations. */
+
+static ASN1_OBJECT *txt2obj(const char *oid);
+static CONF *load_config_file(const char *configfile);
+
+/* Query related functions. */
+static int query_command(const char *data, char *digest, const EVP_MD *md,
+    const char *policy, int no_nonce, int cert, const char *in, const char *out,
+    int text);
+static BIO *BIO_open_with_default(const char *file, const char *mode,
+    FILE *default_fp);
+static TS_REQ *create_query(BIO *data_bio, char *digest, const EVP_MD *md,
+    const char *policy, int no_nonce, int cert);
+static int create_digest(BIO *input, char *digest, const EVP_MD *md,
+    unsigned char **md_value);
+static ASN1_INTEGER *create_nonce(int bits);
+
+/* Reply related functions. */
+static int reply_command(CONF *conf, char *section, char *queryfile,
+    char *passin, char *inkey, char *signer, char *chain, const char *policy,
+    char *in, int token_in, char *out, int token_out, int text);
+static TS_RESP *read_PKCS7(BIO *in_bio);
+static TS_RESP *create_response(CONF *conf, const char *section,
+    char *queryfile, char *passin, char *inkey, char *signer, char *chain,
+    const char *policy);
+static ASN1_INTEGER *serial_cb(TS_RESP_CTX *ctx, void *data);
+static ASN1_INTEGER *next_serial(const char *serialfile);
+static int save_ts_serial(const char *serialfile, ASN1_INTEGER *serial);
+
+/* Verify related functions. */
+static int verify_command(char *data, char *digest, char *queryfile, char *in,
+    int token_in, char *ca_path, char *ca_file, char *untrusted);
+static TS_VERIFY_CTX *create_verify_ctx(char *data, char *digest,
+    char *queryfile, char *ca_path, char *ca_file, char *untrusted);
+static X509_STORE *create_cert_store(char *ca_path, char *ca_file);
+static int verify_cb(int ok, X509_STORE_CTX *ctx);
+
+enum mode {
+	CMD_NONE, CMD_QUERY, CMD_REPLY, CMD_VERIFY
+};
+
+static struct {
+	char *ca_file;
+	char *ca_path;
+	int cert;
+	char *chain;
+	char *configfile;
+	char *data;
+	char *digest;
+	char *in;
+	char *inkey;
+	const EVP_MD *md;
+	int mode;
+	int no_nonce;
+	char *out;
+	char *passin;
+	char *policy;
+	char *queryfile;
+	char *section;
+	char *signer;
+	int text;
+	int token_in;
+	int token_out;
+	char *untrusted;
+} cfg;
+
+static int
+ts_opt_md(int argc, char **argv, int *argsused)
+{
+	char *name = argv[0];
+
+	if (*name++ != '-')
+		return (1);
+
+	if ((cfg.md = EVP_get_digestbyname(name)) == NULL)
+		return (1);
+
+	*argsused = 1;
+	return (0);
+}
+
+static int
+ts_opt_query(void)
+{
+	if (cfg.mode != CMD_NONE)
+		return (1);
+	cfg.mode = CMD_QUERY;
+	return (0);
+}
+
+static int
+ts_opt_reply(void)
+{
+	if (cfg.mode != CMD_NONE)
+		return (1);
+	cfg.mode = CMD_REPLY;
+	return (0);
+}
+
+static int
+ts_opt_verify(void)
+{
+	if (cfg.mode != CMD_NONE)
+		return (1);
+	cfg.mode = CMD_VERIFY;
+	return (0);
+}
+
+static const struct option ts_options[] = {
+	{
+		.name = "CAfile",
+		.argname = "file",
+		.desc = "Certificate Authority file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.ca_file,
+	},
+	{
+		.name = "CApath",
+		.argname = "path",
+		.desc = "Certificate Authority path",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.ca_path,
+	},
+	{
+		.name = "cert",
+		.desc = "Include signing certificate in the response",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.cert,
+	},
+	{
+		.name = "chain",
+		.argname = "file",
+		.desc = "PEM certificates that will be included in the response",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.chain,
+	},
+	{
+		.name = "config",
+		.argname = "file",
+		.desc = "Specify an alternative configuration file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.configfile,
+	},
+	{
+		.name = "data",
+		.argname = "file",
+		.desc = "Data file for which the time stamp request needs to be created",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.data,
+	},
+	{
+		.name = "digest",
+		.argname = "arg",
+		.desc = "Specify the message imprint explicitly without the data file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.digest,
+	},
+	{
+		.name = "in",
+		.argname = "file",
+		.desc = "Input file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.in,
+	},
+	{
+		.name = "inkey",
+		.argname = "file",
+		.desc = "Input key file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.inkey,
+	},
+	{
+		.name = "no_nonce",
+		.desc = "Specify no nonce in the request",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.no_nonce,
+	},
+	{
+		.name = "out",
+		.argname = "file",
+		.desc = "Output file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.out,
+	},
+	{
+		.name = "passin",
+		.argname = "src",
+		.desc = "Private key password source",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.passin,
+	},
+	{
+		.name = "policy",
+		.argname = "object_id",
+		.desc = "Policy for the TSA to use when creating the time stamp token",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.policy,
+	},
+	{
+		.name = "query",
+		.desc = "Create and print a time stamp request",
+		.type = OPTION_FUNC,
+		.opt.func = ts_opt_query,
+	},
+	{
+		.name = "queryfile",
+		.argname = "file",
+		.desc = "File containing a DER-encoded time stamp request",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.queryfile,
+	},
+	{
+		.name = "reply",
+		.desc = "Create a time stamp response",
+		.type = OPTION_FUNC,
+		.opt.func = ts_opt_reply,
+	},
+	{
+		.name = "section",
+		.argname = "arg",
+		.desc = "TSA section containing the settings for response generation",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.section,
+	},
+	{
+		.name = "signer",
+		.argname = "file",
+		.desc = "Signer certificate file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.signer,
+	},
+	{
+		.name = "text",
+		.desc = "Output in human-readable text format",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.text,
+	},
+	{
+		.name = "token_in",
+		.desc = "Input is a DER-encoded time stamp token",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.token_in,
+	},
+	{
+		.name = "token_out",
+		.desc = "Output is a DER-encoded time stamp token",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.token_out,
+	},
+	{
+		.name = "untrusted",
+		.argname = "file",
+		.desc = "File containing untrusted certificates",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.untrusted,
+	},
+	{
+		.name = "verify",
+		.desc = "Verify a time stamp response",
+		.type = OPTION_FUNC,
+		.opt.func = ts_opt_verify,
+	},
+	{
+		.name = NULL,
+		.desc = "",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = ts_opt_md,
+	},
+	{ NULL },
+};
+
+static void
+ts_usage(void)
+{
+	fprintf(stderr, "usage:\n"
+	    "ts -query [-md4 | -md5 | -ripemd160 | -sha1] [-cert]\n"
+	    "    [-config configfile] [-data file_to_hash]\n"
+	    "    [-digest digest_bytes] [-in request.tsq] [-no_nonce]\n"
+	    "    [-out request.tsq] [-policy object_id] [-text]\n");
+	fprintf(stderr, "\n"
+	    "ts -reply [-chain certs_file.pem] [-config configfile]\n"
+	    "    [-in response.tsr] [-inkey private.pem] [-out response.tsr]\n"
+	    "    [-passin arg] [-policy object_id] [-queryfile request.tsq]\n"
+	    "    [-section tsa_section] [-signer tsa_cert.pem] [-text]\n"
+	    "    [-token_in] [-token_out]\n");
+	fprintf(stderr, "\n"
+	    "ts -verify [-CAfile trusted_certs.pem]\n"
+	    "    [-CApath trusted_cert_path] [-data file_to_hash]\n"
+	    "    [-digest digest_bytes] [-in response.tsr]\n"
+	    "    [-queryfile request.tsq] [-token_in]\n"
+	    "    [-untrusted cert_file.pem]\n");
+	fprintf(stderr, "\n");
+	options_usage(ts_options);
+	fprintf(stderr, "\n");
+}
+
+int
+ts_main(int argc, char **argv)
+{
+	int ret = 1;
+	CONF *conf = NULL;
+	char *password = NULL;	/* Password itself. */
+
+	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.mode = CMD_NONE;
+
+	if (options_parse(argc, argv, ts_options, NULL, NULL) != 0)
+		goto usage;
+
+	/* Get the password if required. */
+	if (cfg.mode == CMD_REPLY && cfg.passin != NULL &&
+	    !app_passwd(bio_err, cfg.passin, NULL, &password, NULL)) {
+		BIO_printf(bio_err, "Error getting password.\n");
+		goto cleanup;
+	}
+	/*
+	 * Check consistency of parameters and execute the appropriate
+	 * function.
+	 */
+	switch (cfg.mode) {
+	case CMD_NONE:
+		goto usage;
+	case CMD_QUERY:
+		/*
+		 * Data file and message imprint cannot be specified at the
+		 * same time.
+		 */
+		ret = cfg.data != NULL && cfg.digest != NULL;
+		if (ret)
+			goto usage;
+		/* Load the config file for possible policy OIDs. */
+		conf = load_config_file(cfg.configfile);
+		ret = !query_command(cfg.data, cfg.digest,
+		    cfg.md, cfg.policy, cfg.no_nonce,
+		    cfg.cert, cfg.in, cfg.out,
+		    cfg.text);
+		break;
+	case CMD_REPLY:
+		conf = load_config_file(cfg.configfile);
+		if (cfg.in == NULL) {
+			ret = !(cfg.queryfile != NULL && conf != NULL &&
+			    !cfg.token_in);
+			if (ret)
+				goto usage;
+		} else {
+			/* 'in' and 'queryfile' are exclusive. */
+			ret = !(cfg.queryfile == NULL);
+			if (ret)
+				goto usage;
+		}
+
+		ret = !reply_command(conf, cfg.section,
+		    cfg.queryfile, password, cfg.inkey,
+		    cfg.signer, cfg.chain, cfg.policy,
+		    cfg.in, cfg.token_in, cfg.out,
+		    cfg.token_out, cfg.text);
+		break;
+	case CMD_VERIFY:
+		ret = !(((cfg.queryfile != NULL && cfg.data == NULL &&
+		    cfg.digest == NULL) ||
+		    (cfg.queryfile == NULL && cfg.data != NULL &&
+		    cfg.digest == NULL) ||
+		    (cfg.queryfile == NULL && cfg.data == NULL &&
+		    cfg.digest != NULL)) &&
+		    cfg.in != NULL);
+		if (ret)
+			goto usage;
+
+		ret = !verify_command(cfg.data, cfg.digest,
+		    cfg.queryfile, cfg.in, cfg.token_in,
+		    cfg.ca_path, cfg.ca_file, cfg.untrusted);
+	}
+
+	goto cleanup;
+
+ usage:
+	ts_usage();
+
+ cleanup:
+	/* Clean up. */
+	NCONF_free(conf);
+	free(password);
+	OBJ_cleanup();
+
+	return (ret);
+}
+
+/*
+ * Configuration file-related function definitions.
+ */
+
+static ASN1_OBJECT *
+txt2obj(const char *oid)
+{
+	ASN1_OBJECT *oid_obj = NULL;
+
+	if ((oid_obj = OBJ_txt2obj(oid, 0)) == NULL)
+		BIO_printf(bio_err, "cannot convert %s to OID\n", oid);
+
+	return oid_obj;
+}
+
+static CONF *
+load_config_file(const char *configfile)
+{
+	CONF *conf = NULL;
+	long errorline = -1;
+
+	if (configfile == NULL)
+		configfile = getenv("OPENSSL_CONF");
+
+	if (configfile != NULL &&
+	    ((conf = NCONF_new(NULL)) == NULL ||
+	    NCONF_load(conf, configfile, &errorline) <= 0)) {
+		if (errorline <= 0)
+			BIO_printf(bio_err, "error loading the config file "
+			    "'%s'\n", configfile);
+		else
+			BIO_printf(bio_err, "error on line %ld of config file "
+			    "'%s'\n", errorline, configfile);
+	}
+	if (conf != NULL) {
+		const char *p;
+
+		BIO_printf(bio_err, "Using configuration from %s\n",
+		    configfile);
+		p = NCONF_get_string(conf, NULL, ENV_OID_FILE);
+		if (p != NULL) {
+			BIO *oid_bio = BIO_new_file(p, "r");
+			if (oid_bio == NULL)
+				ERR_print_errors(bio_err);
+			else {
+				OBJ_create_objects(oid_bio);
+				BIO_free_all(oid_bio);
+			}
+		} else
+			ERR_clear_error();
+		if (!add_oid_section(bio_err, conf))
+			ERR_print_errors(bio_err);
+	}
+	return conf;
+}
+
+/*
+ * Query-related method definitions.
+ */
+
+static int
+query_command(const char *data, char *digest, const EVP_MD *md,
+    const char *policy, int no_nonce, int cert, const char *in, const char *out,
+    int text)
+{
+	int ret = 0;
+	TS_REQ *query = NULL;
+	BIO *in_bio = NULL;
+	BIO *data_bio = NULL;
+	BIO *out_bio = NULL;
+
+	/* Build query object either from file or from scratch. */
+	if (in != NULL) {
+		if ((in_bio = BIO_new_file(in, "rb")) == NULL)
+			goto end;
+		query = d2i_TS_REQ_bio(in_bio, NULL);
+	} else {
+		/* Open the file if no explicit digest bytes were specified. */
+		if (digest == NULL &&
+		    (data_bio = BIO_open_with_default(data, "rb", stdin)) == NULL)
+			goto end;
+		/* Creating the query object. */
+		query = create_query(data_bio, digest, md,
+		    policy, no_nonce, cert);
+		/* Saving the random number generator state. */
+	}
+	if (query == NULL)
+		goto end;
+
+	/* Write query either in ASN.1 or in text format. */
+	if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL)
+		goto end;
+	if (text) {
+		/* Text output. */
+		if (!TS_REQ_print_bio(out_bio, query))
+			goto end;
+	} else {
+		/* ASN.1 output. */
+		if (!i2d_TS_REQ_bio(out_bio, query))
+			goto end;
+	}
+
+	ret = 1;
+
+ end:
+	ERR_print_errors(bio_err);
+
+	/* Clean up. */
+	BIO_free_all(in_bio);
+	BIO_free_all(data_bio);
+	BIO_free_all(out_bio);
+	TS_REQ_free(query);
+
+	return ret;
+}
+
+static BIO *
+BIO_open_with_default(const char *file, const char *mode, FILE *default_fp)
+{
+	return file == NULL ? BIO_new_fp(default_fp, BIO_NOCLOSE) :
+	    BIO_new_file(file, mode);
+}
+
+static TS_REQ *
+create_query(BIO *data_bio, char *digest, const EVP_MD *md, const char *policy,
+    int no_nonce, int cert)
+{
+	int ret = 0;
+	TS_REQ *ts_req = NULL;
+	int len;
+	TS_MSG_IMPRINT *msg_imprint = NULL;
+	X509_ALGOR *algo = NULL;
+	unsigned char *data = NULL;
+	ASN1_OBJECT *policy_obj = NULL;
+	ASN1_INTEGER *nonce_asn1 = NULL;
+
+	/* Setting default message digest. */
+	if (md == NULL && (md = EVP_get_digestbyname("sha1")) == NULL)
+		goto err;
+
+	/* Creating request object. */
+	if ((ts_req = TS_REQ_new()) == NULL)
+		goto err;
+
+	/* Setting version. */
+	if (!TS_REQ_set_version(ts_req, 1))
+		goto err;
+
+	/* Creating and adding MSG_IMPRINT object. */
+	if ((msg_imprint = TS_MSG_IMPRINT_new()) == NULL)
+		goto err;
+
+	/* Adding algorithm. */
+	if ((algo = X509_ALGOR_new()) == NULL)
+		goto err;
+	if ((algo->algorithm = OBJ_nid2obj(EVP_MD_type(md))) == NULL)
+		goto err;
+	if ((algo->parameter = ASN1_TYPE_new()) == NULL)
+		goto err;
+	algo->parameter->type = V_ASN1_NULL;
+	if (!TS_MSG_IMPRINT_set_algo(msg_imprint, algo))
+		goto err;
+
+	/* Adding message digest. */
+	if ((len = create_digest(data_bio, digest, md, &data)) == 0)
+		goto err;
+	if (!TS_MSG_IMPRINT_set_msg(msg_imprint, data, len))
+		goto err;
+
+	if (!TS_REQ_set_msg_imprint(ts_req, msg_imprint))
+		goto err;
+
+	/* Setting policy if requested. */
+	if (policy != NULL && (policy_obj = txt2obj(policy)) == NULL)
+		goto err;
+	if (policy_obj != NULL && !TS_REQ_set_policy_id(ts_req, policy_obj))
+		goto err;
+
+	/* Setting nonce if requested. */
+	if (!no_nonce && (nonce_asn1 = create_nonce(NONCE_LENGTH)) == NULL)
+		goto err;
+	if (nonce_asn1 != NULL && !TS_REQ_set_nonce(ts_req, nonce_asn1))
+		goto err;
+
+	/* Setting certificate request flag if requested. */
+	if (!TS_REQ_set_cert_req(ts_req, cert))
+		goto err;
+
+	ret = 1;
+
+ err:
+	if (!ret) {
+		TS_REQ_free(ts_req);
+		ts_req = NULL;
+		BIO_printf(bio_err, "could not create query\n");
+	}
+	TS_MSG_IMPRINT_free(msg_imprint);
+	X509_ALGOR_free(algo);
+	free(data);
+	ASN1_OBJECT_free(policy_obj);
+	ASN1_INTEGER_free(nonce_asn1);
+
+	return ts_req;
+}
+
+static int
+create_digest(BIO *input, char *digest, const EVP_MD *md,
+    unsigned char **md_value)
+{
+	int md_value_len;
+	EVP_MD_CTX *md_ctx = NULL;
+
+	md_value_len = EVP_MD_size(md);
+	if (md_value_len < 0)
+		goto err;
+
+	if (input != NULL) {
+		/* Digest must be computed from an input file. */
+		unsigned char buffer[4096];
+		int length;
+
+		*md_value = malloc(md_value_len);
+		if (*md_value == NULL)
+			goto err;
+
+		if ((md_ctx = EVP_MD_CTX_new()) == NULL)
+			goto err;
+
+		if (!EVP_DigestInit(md_ctx, md))
+			goto err;
+
+		while ((length = BIO_read(input, buffer, sizeof(buffer))) > 0) {
+			if (!EVP_DigestUpdate(md_ctx, buffer, length))
+				goto err;
+		}
+
+		if (!EVP_DigestFinal(md_ctx, *md_value, NULL))
+			goto err;
+
+		EVP_MD_CTX_free(md_ctx);
+		md_ctx = NULL;
+
+	} else {
+		/* Digest bytes are specified with digest. */
+		long digest_len;
+
+		*md_value = string_to_hex(digest, &digest_len);
+		if (*md_value == NULL || md_value_len != digest_len) {
+			free(*md_value);
+			*md_value = NULL;
+			BIO_printf(bio_err, "bad digest, %d bytes "
+			    "must be specified\n", md_value_len);
+			goto err;
+		}
+	}
+
+	return md_value_len;
+
+ err:
+	EVP_MD_CTX_free(md_ctx);
+	return 0;
+}
+
+static ASN1_INTEGER *
+create_nonce(int bits)
+{
+	unsigned char buf[20];
+	ASN1_INTEGER *nonce = NULL;
+	int len = (bits - 1) / 8 + 1;
+	int i;
+
+	/* Generating random byte sequence. */
+	if (len > (int) sizeof(buf))
+		goto err;
+	arc4random_buf(buf, len);
+
+	/* Find the first non-zero byte and creating ASN1_INTEGER object. */
+	for (i = 0; i < len && !buf[i]; ++i)
+		;
+	if ((nonce = ASN1_INTEGER_new()) == NULL)
+		goto err;
+	free(nonce->data);
+	/* Allocate at least one byte. */
+	nonce->length = len - i;
+	if ((nonce->data = malloc(nonce->length + 1)) == NULL)
+		goto err;
+	memcpy(nonce->data, buf + i, nonce->length);
+
+	return nonce;
+
+ err:
+	BIO_printf(bio_err, "could not create nonce\n");
+	ASN1_INTEGER_free(nonce);
+	return NULL;
+}
+
+/*
+ * Reply-related method definitions.
+ */
+
+static int
+reply_command(CONF *conf, char *section, char *queryfile, char *passin,
+    char *inkey, char *signer, char *chain, const char *policy, char *in,
+    int token_in, char *out, int token_out, int text)
+{
+	int ret = 0;
+	TS_RESP *response = NULL;
+	BIO *in_bio = NULL;
+	BIO *query_bio = NULL;
+	BIO *inkey_bio = NULL;
+	BIO *signer_bio = NULL;
+	BIO *out_bio = NULL;
+
+	/* Build response object either from response or query. */
+	if (in != NULL) {
+		if ((in_bio = BIO_new_file(in, "rb")) == NULL)
+			goto end;
+		if (token_in) {
+			/*
+			 * We have a ContentInfo (PKCS7) object, add
+			 * 'granted' status info around it.
+			 */
+			response = read_PKCS7(in_bio);
+		} else {
+			/* We have a ready-made TS_RESP object. */
+			response = d2i_TS_RESP_bio(in_bio, NULL);
+		}
+	} else {
+		response = create_response(conf, section, queryfile, passin,
+				inkey, signer, chain, policy);
+		if (response != NULL)
+			BIO_printf(bio_err, "Response has been generated.\n");
+		else
+			BIO_printf(bio_err, "Response is not generated.\n");
+	}
+	if (response == NULL)
+		goto end;
+
+	/* Write response either in ASN.1 or text format. */
+	if ((out_bio = BIO_open_with_default(out, "wb", stdout)) == NULL)
+		goto end;
+	if (text) {
+		/* Text output. */
+		if (token_out) {
+			TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
+			if (!TS_TST_INFO_print_bio(out_bio, tst_info))
+				goto end;
+		} else {
+			if (!TS_RESP_print_bio(out_bio, response))
+				goto end;
+		}
+	} else {
+		/* ASN.1 DER output. */
+		if (token_out) {
+			PKCS7 *token = TS_RESP_get_token(response);
+			if (!i2d_PKCS7_bio(out_bio, token))
+				goto end;
+		} else {
+			if (!i2d_TS_RESP_bio(out_bio, response))
+				goto end;
+		}
+	}
+
+	ret = 1;
+
+ end:
+	ERR_print_errors(bio_err);
+
+	/* Clean up. */
+	BIO_free_all(in_bio);
+	BIO_free_all(query_bio);
+	BIO_free_all(inkey_bio);
+	BIO_free_all(signer_bio);
+	BIO_free_all(out_bio);
+	TS_RESP_free(response);
+
+	return ret;
+}
+
+/* Reads a PKCS7 token and adds default 'granted' status info to it. */
+static TS_RESP *
+read_PKCS7(BIO *in_bio)
+{
+	int ret = 0;
+	PKCS7 *token = NULL;
+	TS_TST_INFO *tst_info = NULL;
+	TS_RESP *resp = NULL;
+	TS_STATUS_INFO *si = NULL;
+
+	/* Read PKCS7 object and extract the signed time stamp info. */
+	if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
+		goto end;
+	if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL)
+		goto end;
+
+	/* Creating response object. */
+	if ((resp = TS_RESP_new()) == NULL)
+		goto end;
+
+	/* Create granted status info. */
+	if ((si = TS_STATUS_INFO_new()) == NULL)
+		goto end;
+	if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED))
+		goto end;
+	if (!TS_RESP_set_status_info(resp, si))
+		goto end;
+
+	/* Setting encapsulated token. */
+	TS_RESP_set_tst_info(resp, token, tst_info);
+	token = NULL;		/* Ownership is lost. */
+	tst_info = NULL;	/* Ownership is lost. */
+
+	ret = 1;
+ end:
+	PKCS7_free(token);
+	TS_TST_INFO_free(tst_info);
+	if (!ret) {
+		TS_RESP_free(resp);
+		resp = NULL;
+	}
+	TS_STATUS_INFO_free(si);
+	return resp;
+}
+
+static TS_RESP *
+create_response(CONF *conf, const char *section, char *queryfile, char *passin,
+    char *inkey, char *signer, char *chain, const char *policy)
+{
+	int ret = 0;
+	TS_RESP *response = NULL;
+	BIO *query_bio = NULL;
+	TS_RESP_CTX *resp_ctx = NULL;
+
+	if ((query_bio = BIO_new_file(queryfile, "rb")) == NULL)
+		goto end;
+
+	/* Getting TSA configuration section. */
+	if ((section = TS_CONF_get_tsa_section(conf, section)) == NULL)
+		goto end;
+
+	/* Setting up response generation context. */
+	if ((resp_ctx = TS_RESP_CTX_new()) == NULL)
+		goto end;
+
+	/* Setting serial number provider callback. */
+	if (!TS_CONF_set_serial(conf, section, serial_cb, resp_ctx))
+		goto end;
+
+	/* Setting TSA signer certificate. */
+	if (!TS_CONF_set_signer_cert(conf, section, signer, resp_ctx))
+		goto end;
+
+	/* Setting TSA signer certificate chain. */
+	if (!TS_CONF_set_certs(conf, section, chain, resp_ctx))
+		goto end;
+
+	/* Setting TSA signer private key. */
+	if (!TS_CONF_set_signer_key(conf, section, inkey, passin, resp_ctx))
+		goto end;
+
+	/* Setting default policy OID. */
+	if (!TS_CONF_set_def_policy(conf, section, policy, resp_ctx))
+		goto end;
+
+	/* Setting acceptable policy OIDs. */
+	if (!TS_CONF_set_policies(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting the acceptable one-way hash algorithms. */
+	if (!TS_CONF_set_digests(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting guaranteed time stamp accuracy. */
+	if (!TS_CONF_set_accuracy(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting the precision of the time. */
+	if (!TS_CONF_set_clock_precision_digits(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting the ordering flaf if requested. */
+	if (!TS_CONF_set_ordering(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting the TSA name required flag if requested. */
+	if (!TS_CONF_set_tsa_name(conf, section, resp_ctx))
+		goto end;
+
+	/* Setting the ESS cert id chain flag if requested. */
+	if (!TS_CONF_set_ess_cert_id_chain(conf, section, resp_ctx))
+		goto end;
+
+	/* Creating the response. */
+	if ((response = TS_RESP_create_response(resp_ctx, query_bio)) == NULL)
+		goto end;
+
+	ret = 1;
+ end:
+	if (!ret) {
+		TS_RESP_free(response);
+		response = NULL;
+	}
+	TS_RESP_CTX_free(resp_ctx);
+	BIO_free_all(query_bio);
+
+	return response;
+}
+
+static ASN1_INTEGER *
+serial_cb(TS_RESP_CTX *ctx, void *data)
+{
+	const char *serial_file = (const char *) data;
+	ASN1_INTEGER *serial = next_serial(serial_file);
+
+	if (serial == NULL) {
+		TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+		    "Error during serial number "
+		    "generation.");
+		TS_RESP_CTX_add_failure_info(ctx,
+		    TS_INFO_ADD_INFO_NOT_AVAILABLE);
+	} else
+		save_ts_serial(serial_file, serial);
+
+	return serial;
+}
+
+static ASN1_INTEGER *
+next_serial(const char *serialfile)
+{
+	int ret = 0;
+	BIO *in = NULL;
+	ASN1_INTEGER *serial = NULL;
+	BIGNUM *bn = NULL;
+
+	if ((serial = ASN1_INTEGER_new()) == NULL)
+		goto err;
+
+	if ((in = BIO_new_file(serialfile, "r")) == NULL) {
+		ERR_clear_error();
+		BIO_printf(bio_err, "Warning: could not open file %s for "
+		    "reading, using serial number: 1\n", serialfile);
+		if (!ASN1_INTEGER_set(serial, 1))
+			goto err;
+	} else {
+		char buf[1024];
+		if (!a2i_ASN1_INTEGER(in, serial, buf, sizeof(buf))) {
+			BIO_printf(bio_err, "unable to load number from %s\n",
+			    serialfile);
+			goto err;
+		}
+		if ((bn = ASN1_INTEGER_to_BN(serial, NULL)) == NULL)
+			goto err;
+		ASN1_INTEGER_free(serial);
+		serial = NULL;
+		if (!BN_add_word(bn, 1))
+			goto err;
+		if ((serial = BN_to_ASN1_INTEGER(bn, NULL)) == NULL)
+			goto err;
+	}
+	ret = 1;
+ err:
+	if (!ret) {
+		ASN1_INTEGER_free(serial);
+		serial = NULL;
+	}
+	BIO_free_all(in);
+	BN_free(bn);
+	return serial;
+}
+
+static int
+save_ts_serial(const char *serialfile, ASN1_INTEGER *serial)
+{
+	int ret = 0;
+	BIO *out = NULL;
+
+	if ((out = BIO_new_file(serialfile, "w")) == NULL)
+		goto err;
+	if (i2a_ASN1_INTEGER(out, serial) <= 0)
+		goto err;
+	if (BIO_puts(out, "\n") <= 0)
+		goto err;
+	ret = 1;
+ err:
+	if (!ret)
+		BIO_printf(bio_err, "could not save serial number to %s\n",
+		    serialfile);
+	BIO_free_all(out);
+	return ret;
+}
+
+/*
+ * Verify-related method definitions.
+ */
+
+static int
+verify_command(char *data, char *digest, char *queryfile, char *in,
+    int token_in, char *ca_path, char *ca_file, char *untrusted)
+{
+	BIO *in_bio = NULL;
+	PKCS7 *token = NULL;
+	TS_RESP *response = NULL;
+	TS_VERIFY_CTX *verify_ctx = NULL;
+	int ret = 0;
+
+	/* Decode the token (PKCS7) or response (TS_RESP) files. */
+	if ((in_bio = BIO_new_file(in, "rb")) == NULL)
+		goto end;
+	if (token_in) {
+		if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
+			goto end;
+	} else {
+		if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL)
+			goto end;
+	}
+
+	if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
+	    ca_path, ca_file, untrusted)) == NULL)
+		goto end;
+
+	/* Checking the token or response against the request. */
+	ret = token_in ?
+	    TS_RESP_verify_token(verify_ctx, token) :
+	    TS_RESP_verify_response(verify_ctx, response);
+
+ end:
+	printf("Verification: ");
+	if (ret)
+		printf("OK\n");
+	else {
+		printf("FAILED\n");
+		/* Print errors, if there are any. */
+		ERR_print_errors(bio_err);
+	}
+
+	/* Clean up. */
+	BIO_free_all(in_bio);
+	PKCS7_free(token);
+	TS_RESP_free(response);
+	TS_VERIFY_CTX_free(verify_ctx);
+	return ret;
+}
+
+static TS_VERIFY_CTX *
+create_verify_ctx(char *data, char *digest, char *queryfile, char *ca_path,
+    char *ca_file, char *untrusted)
+{
+	TS_VERIFY_CTX *ctx = NULL;
+	BIO *input = NULL;
+	TS_REQ *request = NULL;
+	X509_STORE *store;
+	STACK_OF(X509) *certs;
+	int ret = 0;
+
+	if (data != NULL || digest != NULL) {
+		if ((ctx = TS_VERIFY_CTX_new()) == NULL)
+			goto err;
+		TS_VERIFY_CTX_set_flags(ctx, TS_VFY_VERSION | TS_VFY_SIGNER);
+		if (data != NULL) {
+			BIO *data_bio;
+
+			TS_VERIFY_CTX_add_flags(ctx, TS_VFY_DATA);
+			if ((data_bio = BIO_new_file(data, "rb")) == NULL)
+				goto err;
+			TS_VERIFY_CTX_set_data(ctx, data_bio);
+		} else if (digest != NULL) {
+			unsigned char *imprint;
+			long imprint_len;
+
+			TS_VERIFY_CTX_add_flags(ctx, TS_VFY_IMPRINT);
+			if ((imprint = string_to_hex(digest,
+			    &imprint_len)) == NULL) {
+				BIO_printf(bio_err, "invalid digest string\n");
+				goto err;
+			}
+			TS_VERIFY_CTX_set_imprint(ctx, imprint, imprint_len);
+		}
+	} else if (queryfile != NULL) {
+		/*
+		 * The request has just to be read, decoded and converted to
+		 * a verify context object.
+		 */
+		if ((input = BIO_new_file(queryfile, "rb")) == NULL)
+			goto err;
+		if ((request = d2i_TS_REQ_bio(input, NULL)) == NULL)
+			goto err;
+		if ((ctx = TS_REQ_to_TS_VERIFY_CTX(request, NULL)) == NULL)
+			goto err;
+	} else
+		return NULL;
+
+	/* Add the signature verification flag and arguments. */
+	TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
+
+	/* Initialising the X509_STORE object. */
+	if ((store = create_cert_store(ca_path, ca_file)) == NULL)
+		goto err;
+	TS_VERIFY_CTX_set_store(ctx, store);
+
+	/* Loading untrusted certificates. */
+	if (untrusted != NULL) {
+		if ((certs = TS_CONF_load_certs(untrusted)) == NULL)
+			goto err;
+		TS_VERIFY_CTX_set_certs(ctx, certs);
+	}
+
+	ret = 1;
+ err:
+	if (!ret) {
+		TS_VERIFY_CTX_free(ctx);
+		ctx = NULL;
+	}
+	BIO_free_all(input);
+	TS_REQ_free(request);
+	return ctx;
+}
+
+static X509_STORE *
+create_cert_store(char *ca_path, char *ca_file)
+{
+	X509_STORE *cert_ctx = NULL;
+	X509_LOOKUP *lookup = NULL;
+	int i;
+
+	/* Creating the X509_STORE object. */
+	if ((cert_ctx = X509_STORE_new()) == NULL)
+		goto err;
+
+	/* Setting the callback for certificate chain verification. */
+	X509_STORE_set_verify_cb(cert_ctx, verify_cb);
+
+	/* Adding a trusted certificate directory source. */
+	if (ca_path != NULL) {
+		lookup = X509_STORE_add_lookup(cert_ctx,
+		    X509_LOOKUP_hash_dir());
+		if (lookup == NULL) {
+			BIO_printf(bio_err, "memory allocation failure\n");
+			goto err;
+		}
+		i = X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM);
+		if (!i) {
+			BIO_printf(bio_err, "Error loading directory %s\n",
+			    ca_path);
+			goto err;
+		}
+	}
+	/* Adding a trusted certificate file source. */
+	if (ca_file != NULL) {
+		lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+		if (lookup == NULL) {
+			BIO_printf(bio_err, "memory allocation failure\n");
+			goto err;
+		}
+		i = X509_LOOKUP_load_file(lookup, ca_file, X509_FILETYPE_PEM);
+		if (!i) {
+			BIO_printf(bio_err, "Error loading file %s\n", ca_file);
+			goto err;
+		}
+	}
+	return cert_ctx;
+ err:
+	X509_STORE_free(cert_ctx);
+	return NULL;
+}
+
+static int
+verify_cb(int ok, X509_STORE_CTX *ctx)
+{
+	/*
+	char buf[256];
+
+	if (!ok)
+		{
+		X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
+				  buf, sizeof(buf));
+		printf("%s\n", buf);
+		printf("error %d at %d depth lookup: %s\n",
+		       ctx->error, ctx->error_depth,
+			X509_verify_cert_error_string(ctx->error));
+		}
+	*/
+
+	return ok;
+}
diff --git a/apps/openssl/verify.c b/apps/openssl/verify.c
new file mode 100644
index 0000000..b4e0f33
--- /dev/null
+++ b/apps/openssl/verify.c
@@ -0,0 +1,457 @@
+/* $OpenBSD: verify.c,v 1.17 2023/04/14 15:27:13 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int cb(int ok, X509_STORE_CTX *ctx);
+static int check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain,
+    STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls);
+static int vflags = 0;
+
+static struct {
+	char *CAfile;
+	char *CApath;
+	char *crlfile;
+	char *trustfile;
+	char *untfile;
+	int verbose;
+	X509_VERIFY_PARAM *vpm;
+} cfg;
+
+static int
+verify_opt_args(int argc, char **argv, int *argsused)
+{
+	int oargc = argc;
+	int badarg = 0;
+
+	if (!args_verify(&argv, &argc, &badarg, bio_err, &cfg.vpm))
+		return (1);
+	if (badarg)
+		return (1);
+
+	*argsused = oargc - argc;
+
+	return (0);
+}
+
+static const struct option verify_options[] = {
+	{
+		.name = "CAfile",
+		.argname = "file",
+		.desc = "Certificate Authority file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CAfile,
+	},
+	{
+		.name = "CApath",
+		.argname = "path",
+		.desc = "Certificate Authority path",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CApath,
+	},
+	{
+		.name = "CRLfile",
+		.argname = "file",
+		.desc = "Certificate Revocation List file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.crlfile,
+	},
+	{
+		.name = "trusted",
+		.argname = "file",
+		.desc = "Trusted certificates file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.trustfile,
+	},
+	{
+		.name = "untrusted",
+		.argname = "file",
+		.desc = "Untrusted certificates file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.untfile,
+	},
+	{
+		.name = "verbose",
+		.desc = "Verbose",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.verbose,
+	},
+	{
+		.name = NULL,
+		.desc = "",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = verify_opt_args,
+	},
+	{ NULL },
+};
+
+static const struct option verify_shared_options[] = {
+	{
+		.name = "attime",
+		.argname = "epoch",
+		.desc = "Use epoch as the verification time",
+	},
+	{
+		.name = "check_ss_sig",
+		.desc = "Check the root CA self-signed certificate signature",
+	},
+	{
+		.name = "crl_check",
+		.desc = "Enable CRL checking for the leaf certificate",
+	},
+	{
+		.name = "crl_check_all",
+		.desc = "Enable CRL checking for the entire certificate chain",
+	},
+	{
+		.name = "explicit_policy",
+		.desc = "Require explicit policy (per RFC 3280)",
+	},
+	{
+		.name = "extended_crl",
+		.desc = "Enable extended CRL support",
+	},
+	{
+		.name = "ignore_critical",
+		.desc = "Disable critical extension checking",
+	},
+	{
+		.name = "inhibit_any",
+		.desc = "Inhibit any policy (per RFC 3280)",
+	},
+	{
+		.name = "inhibit_map",
+		.desc = "Inhibit policy mapping (per RFC 3280)",
+	},
+	{
+		.name = "issuer_checks",
+		.desc = "Enable debugging of certificate issuer checks",
+	},
+	{
+		.name = "legacy_verify",
+		.desc = "Use legacy certificate chain verification",
+	},
+	{
+		.name = "policy",
+		.argname = "name",
+		.desc = "Add given policy to the acceptable set",
+	},
+	{
+		.name = "policy_check",
+		.desc = "Enable certificate policy checking",
+	},
+	{
+		.name = "policy_print",
+		.desc = "Print policy",
+	},
+	{
+		.name = "purpose",
+		.argname = "name",
+		.desc = "Verify for the given purpose",
+	},
+	{
+		.name = "use_deltas",
+		.desc = "Use delta CRLS (if present)",
+	},
+	{
+		.name = "verify_depth",
+		.argname = "num",
+		.desc = "Limit verification to the given depth",
+	},
+	{
+		.name = "x509_strict",
+		.desc = "Use strict X.509 rules (disables workarounds)",
+	},
+	{ NULL },
+};
+
+static void
+verify_usage(void)
+{
+	int i;
+
+	fprintf(stderr,
+	    "usage: verify [-CAfile file] [-CApath directory] [-check_ss_sig]\n"
+	    "    [-CRLfile file] [-crl_check] [-crl_check_all]\n"
+	    "    [-explicit_policy] [-extended_crl]\n"
+	    "    [-ignore_critical] [-inhibit_any] [-inhibit_map]\n"
+	    "    [-issuer_checks] [-policy_check] [-purpose purpose]\n"
+	    "    [-trusted file] [-untrusted file] [-verbose]\n"
+	    "    [-x509_strict] [certificates]\n\n");
+
+	options_usage(verify_options);
+
+	fprintf(stderr, "\nVerification options:\n\n");
+	options_usage(verify_shared_options);
+
+	fprintf(stderr, "\nValid purposes:\n\n");
+	for (i = 0; i < X509_PURPOSE_get_count(); i++) {
+		X509_PURPOSE *ptmp = X509_PURPOSE_get0(i);
+		fprintf(stderr, "  %-18s%s\n", X509_PURPOSE_get0_sname(ptmp),
+		    X509_PURPOSE_get0_name(ptmp));
+	}
+}
+
+int
+verify_main(int argc, char **argv)
+{
+	STACK_OF(X509) *untrusted = NULL, *trusted = NULL;
+	STACK_OF(X509_CRL) *crls = NULL;
+	X509_STORE *cert_ctx = NULL;
+	X509_LOOKUP *lookup = NULL;
+	char **cert_files = NULL;
+	int argsused;
+	int ret = 1;
+
+	if (pledge("stdio rpath", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	if (options_parse(argc, argv, verify_options, NULL, &argsused) != 0) {
+		verify_usage();
+		goto end;
+	}
+
+	if (argsused < argc)
+		cert_files = &argv[argsused];
+
+	cert_ctx = X509_STORE_new();
+	if (cert_ctx == NULL)
+		goto end;
+	X509_STORE_set_verify_cb(cert_ctx, cb);
+
+	if (cfg.vpm)
+		X509_STORE_set1_param(cert_ctx, cfg.vpm);
+
+	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_file());
+	if (lookup == NULL)
+		abort(); /* XXX */
+	if (cfg.CAfile) {
+		if (!X509_LOOKUP_load_file(lookup, cfg.CAfile,
+		    X509_FILETYPE_PEM)) {
+			BIO_printf(bio_err, "Error loading file %s\n",
+			    cfg.CAfile);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	} else
+		X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
+
+	lookup = X509_STORE_add_lookup(cert_ctx, X509_LOOKUP_hash_dir());
+	if (lookup == NULL)
+		abort(); /* XXX */
+	if (cfg.CApath) {
+		if (!X509_LOOKUP_add_dir(lookup, cfg.CApath,
+		    X509_FILETYPE_PEM)) {
+			BIO_printf(bio_err, "Error loading directory %s\n",
+			    cfg.CApath);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	} else
+		X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
+
+	ERR_clear_error();
+
+	if (cfg.untfile) {
+		untrusted = load_certs(bio_err, cfg.untfile,
+		    FORMAT_PEM, NULL, "untrusted certificates");
+		if (!untrusted)
+			goto end;
+	}
+	if (cfg.trustfile) {
+		trusted = load_certs(bio_err, cfg.trustfile,
+		    FORMAT_PEM, NULL, "trusted certificates");
+		if (!trusted)
+			goto end;
+	}
+	if (cfg.crlfile) {
+		crls = load_crls(bio_err, cfg.crlfile, FORMAT_PEM,
+		    NULL, "other CRLs");
+		if (!crls)
+			goto end;
+	}
+	ret = 0;
+	if (cert_files == NULL) {
+		if (1 != check(cert_ctx, NULL, untrusted, trusted, crls))
+			ret = -1;
+	} else {
+		do {
+			if (1 != check(cert_ctx, *cert_files++, untrusted,
+			    trusted, crls))
+				ret = -1;
+		} while (*cert_files != NULL);
+	}
+
+ end:
+	if (cfg.vpm)
+		X509_VERIFY_PARAM_free(cfg.vpm);
+	if (cert_ctx != NULL)
+		X509_STORE_free(cert_ctx);
+	sk_X509_pop_free(untrusted, X509_free);
+	sk_X509_pop_free(trusted, X509_free);
+	sk_X509_CRL_pop_free(crls, X509_CRL_free);
+
+	return (ret < 0 ? 2 : ret);
+}
+
+static int
+check(X509_STORE *ctx, char *file, STACK_OF(X509) *uchain,
+    STACK_OF(X509) *tchain, STACK_OF(X509_CRL) *crls)
+{
+	X509 *x = NULL;
+	X509_STORE_CTX *csc = NULL;
+	const char *certfile = (file == NULL) ? "stdin" : file;
+	int verify_err;
+	int i = 0, ret = 0;
+
+	x = load_cert(bio_err, file, FORMAT_PEM, NULL, "certificate file");
+	if (x == NULL)
+		goto end;
+
+	if ((csc = X509_STORE_CTX_new()) == NULL)
+		goto end;
+	X509_STORE_set_flags(ctx, vflags);
+	if (!X509_STORE_CTX_init(csc, ctx, x, uchain))
+		goto end;
+	if (tchain)
+		X509_STORE_CTX_trusted_stack(csc, tchain);
+	if (crls)
+		X509_STORE_CTX_set0_crls(csc, crls);
+
+	i = X509_verify_cert(csc);
+	verify_err = X509_STORE_CTX_get_error(csc);
+
+	if (i > 0 && verify_err == X509_V_OK) {
+		fprintf(stdout, "%s: OK\n", certfile);
+		ret = 1;
+	} else {
+		fprintf(stdout, "%s: verification failed: %d (%s)\n", certfile,
+		    verify_err, X509_verify_cert_error_string(verify_err));
+	}
+
+ end:
+	if (i <= 0)
+		ERR_print_errors(bio_err);
+	X509_free(x);
+	X509_STORE_CTX_free(csc);
+
+	return (ret);
+}
+
+static int
+cb(int ok, X509_STORE_CTX *ctx)
+{
+	int cert_error = X509_STORE_CTX_get_error(ctx);
+	X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
+
+	if (!ok) {
+		if (current_cert) {
+			X509_NAME_print_ex_fp(stdout,
+			    X509_get_subject_name(current_cert),
+			    0, XN_FLAG_ONELINE);
+			printf("\n");
+		}
+		printf("%serror %d at %d depth lookup:%s\n",
+		    X509_STORE_CTX_get0_parent_ctx(ctx) ? "[CRL path]" : "",
+		    cert_error,
+		    X509_STORE_CTX_get_error_depth(ctx),
+		    X509_verify_cert_error_string(cert_error));
+		switch (cert_error) {
+		case X509_V_ERR_NO_EXPLICIT_POLICY:
+		case X509_V_ERR_CERT_HAS_EXPIRED:
+
+			/*
+			 * since we are just checking the certificates, it is
+			 * ok if they are self signed. But we should still
+			 * warn the user.
+			 */
+
+		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+			/* Continue after extension errors too */
+		case X509_V_ERR_INVALID_CA:
+		case X509_V_ERR_INVALID_NON_CA:
+		case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+		case X509_V_ERR_INVALID_PURPOSE:
+		case X509_V_ERR_CRL_HAS_EXPIRED:
+		case X509_V_ERR_CRL_NOT_YET_VALID:
+		case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+			ok = 1;
+
+		}
+
+		return ok;
+
+	}
+	if (!cfg.verbose)
+		ERR_clear_error();
+	return (ok);
+}
diff --git a/apps/openssl/version.c b/apps/openssl/version.c
new file mode 100644
index 0000000..991e213
--- /dev/null
+++ b/apps/openssl/version.c
@@ -0,0 +1,249 @@
+/* $OpenBSD: version.c,v 1.12 2023/07/27 07:01:50 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_BF
+#include 
+#endif
+
+#ifndef OPENSSL_NO_DES
+#include 
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+#include 
+#endif
+
+#ifndef OPENSSL_NO_RC4
+#include 
+#endif
+
+static struct {
+	int cflags;
+	int date;
+	int dir;
+	int options;
+	int platform;
+	int version;
+} cfg;
+
+static int
+version_all_opts(void)
+{
+	cfg.cflags = 1;
+	cfg.date = 1;
+	cfg.dir= 1;
+	cfg.options = 1;
+	cfg.platform = 1;
+	cfg.version = 1;
+
+	return (0);
+}
+
+static const struct option version_options[] = {
+	{
+		.name = "a",
+		.desc = "All information (same as setting all other flags)",
+		.type = OPTION_FUNC,
+		.opt.func = version_all_opts,
+	},
+	{
+		.name = "b",
+		.desc = "Date the current version of OpenSSL was built",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.date,
+	},
+	{
+		.name = "d",
+		.desc = "OPENSSLDIR value",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.dir,
+	},
+	{
+		.name = "f",
+		.desc = "Compilation flags",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.cflags,
+	},
+	{
+		.name = "o",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.options,
+	},
+	{
+		.name = "p",
+		.desc = "Platform settings",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.platform,
+	},
+	{
+		.name = "v",
+		.desc = "Current OpenSSL version",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.version,
+	},
+	{NULL},
+};
+
+static void
+version_usage(void)
+{
+	fprintf(stderr, "usage: version [-abdfpv]\n");
+	options_usage(version_options);
+}
+
+int
+version_main(int argc, char **argv)
+{
+	if (pledge("stdio", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+
+	if (options_parse(argc, argv, version_options, NULL, NULL) != 0) {
+		version_usage();
+		return (1);
+	}
+
+	if (argc == 1)
+		cfg.version = 1;
+
+	if (cfg.version) {
+		if (SSLeay() == SSLEAY_VERSION_NUMBER) {
+			printf("%s\n", SSLeay_version(SSLEAY_VERSION));
+		} else {
+			printf("%s (Library: %s)\n",
+			    OPENSSL_VERSION_TEXT,
+			    SSLeay_version(SSLEAY_VERSION));
+		}
+	}
+	if (cfg.date)
+		printf("%s\n", SSLeay_version(SSLEAY_BUILT_ON));
+	if (cfg.platform)
+		printf("%s\n", SSLeay_version(SSLEAY_PLATFORM));
+	if (cfg.cflags)
+		printf("%s\n", SSLeay_version(SSLEAY_CFLAGS));
+	if (cfg.dir)
+		printf("%s\n", SSLeay_version(SSLEAY_DIR));
+
+	return (0);
+}
diff --git a/apps/openssl/x509.c b/apps/openssl/x509.c
new file mode 100644
index 0000000..7c8f34f
--- /dev/null
+++ b/apps/openssl/x509.c
@@ -0,0 +1,1557 @@
+/* $OpenBSD: x509.c,v 1.33 2023/04/14 06:47:07 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "apps.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define	POSTFIX	".srl"
+#define DEF_DAYS	30
+
+static int callb(int ok, X509_STORE_CTX *ctx);
+static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
+    const EVP_MD *digest, CONF *conf, char *section);
+static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
+    X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
+    char *serial, int create, int days, int clrext, CONF *conf, char *section,
+    ASN1_INTEGER *sno);
+static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt);
+
+static struct {
+	char *alias;
+	int aliasout;
+	int badops;
+	int C;
+	int CA_createserial;
+	int CA_flag;
+	char *CAfile;
+	int CAformat;
+	char *CAkeyfile;
+	int CAkeyformat;
+	char *CAserial;
+	unsigned long certflag;
+	int checkend;
+	int checkoffset;
+	int clrext;
+	int clrreject;
+	int clrtrust;
+	int days;
+	const EVP_MD *digest;
+	int email;
+	int enddate;
+	char *extfile;
+	char *extsect;
+	int fingerprint;
+	char *infile;
+	int informat;
+	int issuer;
+	int issuer_hash;
+#ifndef OPENSSL_NO_MD5
+	int issuer_hash_old;
+#endif
+	char *keyfile;
+	int keyformat;
+	const EVP_MD *md_alg;
+	int modulus;
+	int next_serial;
+	unsigned long nmflag;
+	int noout;
+	int num;
+	int ocspid;
+	ASN1_OBJECT *objtmp;
+	int ocsp_uri;
+	char *outfile;
+	int outformat;
+	char *passargin;
+	int pprint;
+	int pubkey;
+	STACK_OF(ASN1_OBJECT) *reject;
+	int reqfile;
+	int serial;
+	int sign_flag;
+	STACK_OF(OPENSSL_STRING) *sigopts;
+	ASN1_INTEGER *sno;
+	int startdate;
+	int subject;
+	int subject_hash;
+#ifndef OPENSSL_NO_MD5
+	int subject_hash_old;
+#endif
+	int text;
+	STACK_OF(ASN1_OBJECT) *trust;
+	int trustout;
+	int x509req;
+} cfg;
+
+static int
+x509_opt_addreject(char *arg)
+{
+	if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
+		BIO_printf(bio_err, "Invalid reject object value %s\n", arg);
+		return (1);
+	}
+
+	if (cfg.reject == NULL &&
+	    (cfg.reject = sk_ASN1_OBJECT_new_null()) == NULL)
+		return (1);
+
+	if (!sk_ASN1_OBJECT_push(cfg.reject, cfg.objtmp))
+		return (1);
+
+	cfg.trustout = 1;
+	return (0);
+}
+
+static int
+x509_opt_addtrust(char *arg)
+{
+	if ((cfg.objtmp = OBJ_txt2obj(arg, 0)) == NULL) {
+		BIO_printf(bio_err, "Invalid trust object value %s\n", arg);
+		return (1);
+	}
+
+	if (cfg.trust == NULL &&
+	    (cfg.trust = sk_ASN1_OBJECT_new_null()) == NULL)
+		return (1);
+
+	if (!sk_ASN1_OBJECT_push(cfg.trust, cfg.objtmp))
+		return (1);
+
+	cfg.trustout = 1;
+	return (0);
+}
+
+static int
+x509_opt_ca(char *arg)
+{
+	cfg.CAfile = arg;
+	cfg.CA_flag = ++cfg.num;
+	return (0);
+}
+
+static int
+x509_opt_certopt(char *arg)
+{
+	if (!set_cert_ex(&cfg.certflag, arg))
+		return (1);
+
+	return (0);
+}
+
+static int
+x509_opt_checkend(char *arg)
+{
+	const char *errstr;
+
+	cfg.checkoffset = strtonum(arg, 0, INT_MAX, &errstr);
+	if (errstr != NULL) {
+		BIO_printf(bio_err, "checkend unusable: %s\n", errstr);
+		return (1);
+	}
+	cfg.checkend = 1;
+	return (0);
+}
+
+static int
+x509_opt_dates(void)
+{
+	cfg.startdate = ++cfg.num;
+	cfg.enddate = ++cfg.num;
+	return (0);
+}
+
+static int
+x509_opt_days(char *arg)
+{
+	const char *errstr;
+
+	cfg.days = strtonum(arg, 1, INT_MAX, &errstr);
+	if (errstr != NULL) {
+		BIO_printf(bio_err, "bad number of days: %s\n", errstr);
+		return (1);
+	}
+	return (0);
+}
+
+static int
+x509_opt_digest(int argc, char **argv, int *argsused)
+{
+	char *name = argv[0];
+
+	if (*name++ != '-')
+		return (1);
+
+	if ((cfg.md_alg = EVP_get_digestbyname(name)) != NULL) {
+		cfg.digest = cfg.md_alg;
+	} else {
+		BIO_printf(bio_err, "unknown option %s\n", *argv);
+		cfg.badops = 1;
+		return (1);
+	}
+
+	*argsused = 1;
+	return (0);
+}
+
+static int
+x509_opt_nameopt(char *arg)
+{
+	if (!set_name_ex(&cfg.nmflag, arg))
+		return (1);
+
+	return (0);
+}
+
+static int
+x509_opt_set_serial(char *arg)
+{
+	ASN1_INTEGER_free(cfg.sno);
+	if ((cfg.sno = s2i_ASN1_INTEGER(NULL, arg)) == NULL)
+		return (1);
+
+	return (0);
+}
+
+static int
+x509_opt_setalias(char *arg)
+{
+	cfg.alias = arg;
+	cfg.trustout = 1;
+	return (0);
+}
+
+static int
+x509_opt_signkey(char *arg)
+{
+	cfg.keyfile = arg;
+	cfg.sign_flag = ++cfg.num;
+	return (0);
+}
+
+static int
+x509_opt_sigopt(char *arg)
+{
+	if (cfg.sigopts == NULL &&
+	    (cfg.sigopts = sk_OPENSSL_STRING_new_null()) == NULL)
+		return (1);
+
+	if (!sk_OPENSSL_STRING_push(cfg.sigopts, arg))
+		return (1);
+
+	return (0);
+}
+
+static const struct option x509_options[] = {
+	{
+		.name = "C",
+		.desc = "Convert the certificate into C code",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.C,
+		.order = &cfg.num,
+	},
+	{
+		.name = "addreject",
+		.argname = "arg",
+		.desc = "Reject certificate for a given purpose",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_addreject,
+	},
+	{
+		.name = "addtrust",
+		.argname = "arg",
+		.desc = "Trust certificate for a given purpose",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_addtrust,
+	},
+	{
+		.name = "alias",
+		.desc = "Output certificate alias",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.aliasout,
+		.order = &cfg.num,
+	},
+	{
+		.name = "CA",
+		.argname = "file",
+		.desc = "CA certificate in PEM format unless -CAform is specified",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_ca,
+	},
+	{
+		.name = "CAcreateserial",
+		.desc = "Create serial number file if it does not exist",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.CA_createserial,
+		.order = &cfg.num,
+	},
+	{
+		.name = "CAform",
+		.argname = "fmt",
+		.desc = "CA format - default PEM",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.CAformat,
+	},
+	{
+		.name = "CAkey",
+		.argname = "file",
+		.desc = "CA key in PEM format unless -CAkeyform is specified\n"
+			"if omitted, the key is assumed to be in the CA file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CAkeyfile,
+	},
+	{
+		.name = "CAkeyform",
+		.argname = "fmt",
+		.desc = "CA key format - default PEM",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.CAkeyformat,
+	},
+	{
+		.name = "CAserial",
+		.argname = "file",
+		.desc = "Serial file",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.CAserial,
+	},
+	{
+		.name = "certopt",
+		.argname = "option",
+		.desc = "Various certificate text options",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_certopt,
+	},
+	{
+		.name = "checkend",
+		.argname = "arg",
+		.desc = "Check whether the cert expires in the next arg seconds\n"
+			"exit 1 if so, 0 if not",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_checkend,
+	},
+	{
+		.name = "clrext",
+		.desc = "Clear all extensions",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.clrext,
+	},
+	{
+		.name = "clrreject",
+		.desc = "Clear all rejected purposes",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.clrreject,
+		.order = &cfg.num,
+	},
+	{
+		.name = "clrtrust",
+		.desc = "Clear all trusted purposes",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.clrtrust,
+		.order = &cfg.num,
+	},
+	{
+		.name = "dates",
+		.desc = "Both Before and After dates",
+		.type = OPTION_FUNC,
+		.opt.func = x509_opt_dates,
+	},
+	{
+		.name = "days",
+		.argname = "arg",
+		.desc = "How long till expiry of a signed certificate - def 30 days",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_days,
+	},
+	{
+		.name = "email",
+		.desc = "Print email address(es)",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.email,
+		.order = &cfg.num,
+	},
+	{
+		.name = "enddate",
+		.desc = "Print notAfter field",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.enddate,
+		.order = &cfg.num,
+	},
+	{
+		.name = "extensions",
+		.argname = "section",
+		.desc = "Section from config file with X509V3 extensions to add",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.extsect,
+	},
+	{
+		.name = "extfile",
+		.argname = "file",
+		.desc = "Configuration file with X509V3 extensions to add",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.extfile,
+	},
+	{
+		.name = "fingerprint",
+		.desc = "Print the certificate fingerprint",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.fingerprint,
+		.order = &cfg.num,
+	},
+	{
+		.name = "hash",
+		.desc = "Synonym for -subject_hash",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.subject_hash,
+		.order = &cfg.num,
+	},
+	{
+		.name = "in",
+		.argname = "file",
+		.desc = "Input file - default stdin",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.infile,
+	},
+	{
+		.name = "inform",
+		.argname = "fmt",
+		.desc = "Input format - default PEM (one of DER, NET or PEM)",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.informat,
+	},
+	{
+		.name = "issuer",
+		.desc = "Print issuer name",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.issuer,
+		.order = &cfg.num,
+	},
+	{
+		.name = "issuer_hash",
+		.desc = "Print issuer hash value",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.issuer_hash,
+		.order = &cfg.num,
+	},
+#ifndef OPENSSL_NO_MD5
+	{
+		.name = "issuer_hash_old",
+		.desc = "Print old-style (MD5) issuer hash value",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.issuer_hash_old,
+		.order = &cfg.num,
+	},
+#endif
+	{
+		.name = "keyform",
+		.argname = "fmt",
+		.desc = "Private key format - default PEM",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.keyformat,
+	},
+	{
+		.name = "modulus",
+		.desc = "Print the RSA key modulus",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.modulus,
+		.order = &cfg.num,
+	},
+	{
+		.name = "nameopt",
+		.argname = "option",
+		.desc = "Various certificate name options",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_nameopt,
+	},
+	{
+		.name = "next_serial",
+		.desc = "Print the next serial number",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.next_serial,
+		.order = &cfg.num,
+	},
+	{
+		.name = "noout",
+		.desc = "No certificate output",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.noout,
+		.order = &cfg.num,
+	},
+	{
+		.name = "ocsp_uri",
+		.desc = "Print OCSP Responder URL(s)",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.ocsp_uri,
+		.order = &cfg.num,
+	},
+	{
+		.name = "ocspid",
+		.desc = "Print OCSP hash values for the subject name and public key",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.ocspid,
+		.order = &cfg.num,
+	},
+	{
+		.name = "out",
+		.argname = "file",
+		.desc = "Output file - default stdout",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.outfile,
+	},
+	{
+		.name = "outform",
+		.argname = "fmt",
+		.desc = "Output format - default PEM (one of DER, NET or PEM)",
+		.type = OPTION_ARG_FORMAT,
+		.opt.value = &cfg.outformat,
+	},
+	{
+		.name = "passin",
+		.argname = "src",
+		.desc = "Private key password source",
+		.type = OPTION_ARG,
+		.opt.arg = &cfg.passargin,
+	},
+	{
+		.name = "pubkey",
+		.desc = "Output the public key",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.pubkey,
+		.order = &cfg.num,
+	},
+	{
+		.name = "purpose",
+		.desc = "Print out certificate purposes",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.pprint,
+		.order = &cfg.num,
+	},
+	{
+		.name = "req",
+		.desc = "Input is a certificate request, sign and output",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.reqfile,
+	},
+	{
+		.name = "serial",
+		.desc = "Print serial number value",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.serial,
+		.order = &cfg.num,
+	},
+	{
+		.name = "set_serial",
+		.argname = "n",
+		.desc = "Serial number to use",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_set_serial,
+	},
+	{
+		.name = "setalias",
+		.argname = "arg",
+		.desc = "Set certificate alias",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_setalias,
+	},
+	{
+		.name = "signkey",
+		.argname = "file",
+		.desc = "Self sign cert with arg",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_signkey,
+	},
+	{
+		.name = "sigopt",
+		.argname = "nm:v",
+		.desc = "Various signature algorithm options",
+		.type = OPTION_ARG_FUNC,
+		.opt.argfunc = x509_opt_sigopt,
+	},
+	{
+		.name = "startdate",
+		.desc = "Print notBefore field",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.startdate,
+		.order = &cfg.num,
+	},
+	{
+		.name = "subject",
+		.desc = "Print subject name",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.subject,
+		.order = &cfg.num,
+	},
+	{
+		.name = "subject_hash",
+		.desc = "Print subject hash value",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.subject_hash,
+		.order = &cfg.num,
+	},
+#ifndef OPENSSL_NO_MD5
+	{
+		.name = "subject_hash_old",
+		.desc = "Print old-style (MD5) subject hash value",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.subject_hash_old,
+		.order = &cfg.num,
+	},
+#endif
+	{
+		.name = "text",
+		.desc = "Print the certificate in text form",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.text,
+		.order = &cfg.num,
+	},
+	{
+		.name = "trustout",
+		.desc = "Output a trusted certificate",
+		.type = OPTION_FLAG,
+		.opt.flag = &cfg.trustout,
+	},
+	{
+		.name = "x509toreq",
+		.desc = "Output a certification request object",
+		.type = OPTION_ORDER,
+		.opt.order = &cfg.x509req,
+		.order = &cfg.num,
+	},
+	{
+		.name = NULL,
+		.desc = "",
+		.type = OPTION_ARGV_FUNC,
+		.opt.argvfunc = x509_opt_digest,
+	},
+	{ NULL },
+};
+
+static void
+x509_usage(void)
+{
+	fprintf(stderr, "usage: x509 "
+	    "[-C] [-addreject arg] [-addtrust arg] [-alias] [-CA file]\n"
+	    "    [-CAcreateserial] [-CAform der | pem] [-CAkey file]\n"
+	    "    [-CAkeyform der | pem] [-CAserial file] [-certopt option]\n"
+	    "    [-checkend arg] [-clrext] [-clrreject] [-clrtrust] [-dates]\n"
+	    "    [-days arg] [-email] [-enddate] [-extensions section]\n"
+	    "    [-extfile file] [-fingerprint] [-hash] [-in file]\n"
+	    "    [-inform der | net | pem] [-issuer] [-issuer_hash]\n"
+	    "    [-issuer_hash_old] [-keyform der | pem] [-md5 | -sha1]\n"
+	    "    [-modulus] [-nameopt option] [-next_serial] [-noout]\n"
+	    "    [-ocsp_uri] [-ocspid] [-out file]\n"
+	    "    [-outform der | net | pem] [-passin arg] [-pubkey]\n"
+	    "    [-purpose] [-req] [-serial] [-set_serial n] [-setalias arg]\n"
+	    "    [-signkey file] [-sigopt nm:v] [-startdate] [-subject]\n"
+	    "    [-subject_hash] [-subject_hash_old] [-text] [-trustout]\n"
+	    "    [-x509toreq]\n");
+	fprintf(stderr, "\n");
+	options_usage(x509_options);
+	fprintf(stderr, "\n");
+}
+
+int
+x509_main(int argc, char **argv)
+{
+	int ret = 1;
+	X509_REQ *req = NULL;
+	X509 *x = NULL, *xca = NULL;
+	EVP_PKEY *Upkey = NULL, *CApkey = NULL;
+	int i;
+	BIO *out = NULL;
+	BIO *STDout = NULL;
+	X509_STORE *ctx = NULL;
+	X509_REQ *rq = NULL;
+	char buf[256];
+	CONF *extconf = NULL;
+	char *passin = NULL;
+
+	if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
+		perror("pledge");
+		exit(1);
+	}
+
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.days = DEF_DAYS;
+	cfg.informat = FORMAT_PEM;
+	cfg.outformat = FORMAT_PEM;
+	cfg.keyformat = FORMAT_PEM;
+	cfg.CAformat = FORMAT_PEM;
+	cfg.CAkeyformat = FORMAT_PEM;
+
+	STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
+
+	ctx = X509_STORE_new();
+	if (ctx == NULL)
+		goto end;
+	X509_STORE_set_verify_cb(ctx, callb);
+
+	if (options_parse(argc, argv, x509_options, NULL, NULL) != 0)
+		goto bad;
+
+	if (cfg.badops) {
+ bad:
+		x509_usage();
+		goto end;
+	}
+
+	if (!app_passwd(bio_err, cfg.passargin, NULL, &passin, NULL)) {
+		BIO_printf(bio_err, "Error getting password\n");
+		goto end;
+	}
+	if (!X509_STORE_set_default_paths(ctx)) {
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	if (cfg.CAkeyfile == NULL && cfg.CA_flag && cfg.CAformat == FORMAT_PEM) {
+		cfg.CAkeyfile = cfg.CAfile;
+	} else if (cfg.CA_flag && cfg.CAkeyfile == NULL) {
+		BIO_printf(bio_err,
+		    "need to specify a CAkey if using the CA command\n");
+		goto end;
+	}
+	if (cfg.extfile != NULL) {
+		long errorline = -1;
+		X509V3_CTX ctx2;
+		extconf = NCONF_new(NULL);
+		if (!NCONF_load(extconf, cfg.extfile, &errorline)) {
+			if (errorline <= 0)
+				BIO_printf(bio_err,
+				    "error loading the config file '%s'\n",
+				    cfg.extfile);
+			else
+				BIO_printf(bio_err,
+				    "error on line %ld of config file '%s'\n",
+				    errorline, cfg.extfile);
+			goto end;
+		}
+		if (cfg.extsect == NULL) {
+			cfg.extsect = NCONF_get_string(extconf, "default",
+			    "extensions");
+			if (cfg.extsect == NULL) {
+				ERR_clear_error();
+				cfg.extsect = "default";
+			}
+		}
+		X509V3_set_ctx_test(&ctx2);
+		X509V3_set_nconf(&ctx2, extconf);
+		if (!X509V3_EXT_add_nconf(extconf, &ctx2, cfg.extsect, NULL)) {
+			BIO_printf(bio_err,
+			    "Error Loading extension section %s\n", cfg.extsect);
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+	}
+	if (cfg.reqfile) {
+		EVP_PKEY *pkey;
+		BIO *in;
+
+		if (!cfg.sign_flag && !cfg.CA_flag) {
+			BIO_printf(bio_err,
+			    "We need a private key to sign with\n");
+			goto end;
+		}
+		in = BIO_new(BIO_s_file());
+		if (in == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		if (cfg.infile == NULL)
+			BIO_set_fp(in, stdin, BIO_NOCLOSE | BIO_FP_TEXT);
+		else {
+			if (BIO_read_filename(in, cfg.infile) <= 0) {
+				perror(cfg.infile);
+				BIO_free(in);
+				goto end;
+			}
+		}
+		req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
+		BIO_free(in);
+
+		if (req == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
+			BIO_printf(bio_err, "error unpacking public key\n");
+			goto end;
+		}
+		i = X509_REQ_verify(req, pkey);
+		if (i < 0) {
+			BIO_printf(bio_err, "Signature verification error\n");
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		if (i == 0) {
+			BIO_printf(bio_err,
+			    "Signature did not match the certificate request\n");
+			goto end;
+		} else
+			BIO_printf(bio_err, "Signature ok\n");
+
+		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
+		    cfg.nmflag);
+
+		if ((x = X509_new()) == NULL)
+			goto end;
+
+		if (cfg.sno == NULL) {
+			cfg.sno = ASN1_INTEGER_new();
+			if (cfg.sno == NULL || !rand_serial(NULL, cfg.sno))
+				goto end;
+			if (!X509_set_serialNumber(x, cfg.sno))
+				goto end;
+			ASN1_INTEGER_free(cfg.sno);
+			cfg.sno = NULL;
+		} else if (!X509_set_serialNumber(x, cfg.sno))
+			goto end;
+
+		if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
+			goto end;
+		if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
+			goto end;
+
+		if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
+			goto end;
+		if (X509_time_adj_ex(X509_get_notAfter(x), cfg.days, 0,
+		    NULL) == NULL)
+			goto end;
+
+		if ((pkey = X509_REQ_get0_pubkey(req)) == NULL)
+			goto end;
+		if (!X509_set_pubkey(x, pkey))
+			goto end;
+	} else {
+		x = load_cert(bio_err, cfg.infile, cfg.informat, NULL,
+		    "Certificate");
+	}
+	if (x == NULL)
+		goto end;
+
+	if (cfg.CA_flag) {
+		xca = load_cert(bio_err, cfg.CAfile, cfg.CAformat, NULL,
+		    "CA Certificate");
+		if (xca == NULL)
+			goto end;
+	}
+	if (!cfg.noout || cfg.text || cfg.next_serial) {
+		OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");
+
+		out = BIO_new(BIO_s_file());
+		if (out == NULL) {
+			ERR_print_errors(bio_err);
+			goto end;
+		}
+		if (cfg.outfile == NULL) {
+			BIO_set_fp(out, stdout, BIO_NOCLOSE);
+		} else {
+			if (BIO_write_filename(out, cfg.outfile) <= 0) {
+				perror(cfg.outfile);
+				goto end;
+			}
+		}
+	}
+	if (cfg.alias != NULL) {
+		if (!X509_alias_set1(x, (unsigned char *)cfg.alias, -1))
+			goto end;
+	}
+
+	if (cfg.clrtrust)
+		X509_trust_clear(x);
+	if (cfg.clrreject)
+		X509_reject_clear(x);
+
+	if (cfg.trust != NULL) {
+		for (i = 0; i < sk_ASN1_OBJECT_num(cfg.trust); i++) {
+			cfg.objtmp = sk_ASN1_OBJECT_value(cfg.trust, i);
+			if (!X509_add1_trust_object(x, cfg.objtmp))
+				goto end;
+		}
+	}
+	if (cfg.reject != NULL) {
+		for (i = 0; i < sk_ASN1_OBJECT_num(cfg.reject); i++) {
+			cfg.objtmp = sk_ASN1_OBJECT_value(cfg.reject, i);
+			if (!X509_add1_reject_object(x, cfg.objtmp))
+				goto end;
+		}
+	}
+	if (cfg.num) {
+		for (i = 1; i <= cfg.num; i++) {
+			if (cfg.issuer == i) {
+				print_name(STDout, "issuer= ",
+				    X509_get_issuer_name(x), cfg.nmflag);
+			} else if (cfg.subject == i) {
+				print_name(STDout, "subject= ",
+				    X509_get_subject_name(x), cfg.nmflag);
+			} else if (cfg.serial == i) {
+				BIO_printf(STDout, "serial=");
+				i2a_ASN1_INTEGER(STDout,
+				    X509_get_serialNumber(x));
+				BIO_printf(STDout, "\n");
+			} else if (cfg.next_serial == i) {
+				BIGNUM *bnser;
+				ASN1_INTEGER *ser;
+
+				ser = X509_get_serialNumber(x);
+				if (ser == NULL)
+					goto end;
+				bnser = ASN1_INTEGER_to_BN(ser, NULL);
+				if (bnser == NULL)
+					goto end;
+				if (!BN_add_word(bnser, 1)) {
+					BN_free(bnser);
+					goto end;
+				}
+				ser = BN_to_ASN1_INTEGER(bnser, NULL);
+				if (ser == NULL) {
+					BN_free(bnser);
+					goto end;
+				}
+				BN_free(bnser);
+				i2a_ASN1_INTEGER(out, ser);
+				ASN1_INTEGER_free(ser);
+				BIO_puts(out, "\n");
+			} else if (cfg.email == i || cfg.ocsp_uri == i) {
+				STACK_OF(OPENSSL_STRING) *emlst;
+				int j;
+
+				if (cfg.email == i)
+					emlst = X509_get1_email(x);
+				else
+					emlst = X509_get1_ocsp(x);
+				for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
+					BIO_printf(STDout, "%s\n",
+					    sk_OPENSSL_STRING_value(emlst, j));
+				X509_email_free(emlst);
+			} else if (cfg.aliasout == i) {
+				unsigned char *albuf;
+				int buflen;
+				albuf = X509_alias_get0(x, &buflen);
+				if (albuf != NULL)
+					BIO_printf(STDout, "%.*s\n",
+					    buflen, albuf);
+				else
+					BIO_puts(STDout, "\n");
+			} else if (cfg.subject_hash == i) {
+				BIO_printf(STDout, "%08lx\n",
+				    X509_subject_name_hash(x));
+			}
+#ifndef OPENSSL_NO_MD5
+			else if (cfg.subject_hash_old == i) {
+				BIO_printf(STDout, "%08lx\n",
+				    X509_subject_name_hash_old(x));
+			}
+#endif
+			else if (cfg.issuer_hash == i) {
+				BIO_printf(STDout, "%08lx\n",
+				    X509_issuer_name_hash(x));
+			}
+#ifndef OPENSSL_NO_MD5
+			else if (cfg.issuer_hash_old == i) {
+				BIO_printf(STDout, "%08lx\n",
+				    X509_issuer_name_hash_old(x));
+			}
+#endif
+			else if (cfg.pprint == i) {
+				X509_PURPOSE *ptmp;
+				int j;
+
+				BIO_printf(STDout, "Certificate purposes:\n");
+				for (j = 0; j < X509_PURPOSE_get_count(); j++) {
+					ptmp = X509_PURPOSE_get0(j);
+					purpose_print(STDout, x, ptmp);
+				}
+			} else if (cfg.modulus == i) {
+				EVP_PKEY *pkey;
+
+				pkey = X509_get0_pubkey(x);
+				if (pkey == NULL) {
+					BIO_printf(bio_err,
+					    "Modulus=unavailable\n");
+					ERR_print_errors(bio_err);
+					goto end;
+				}
+				BIO_printf(STDout, "Modulus=");
+				if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+					RSA *rsa = EVP_PKEY_get0_RSA(pkey);
+					const BIGNUM *n = NULL;
+
+					RSA_get0_key(rsa, &n, NULL, NULL);
+					BN_print(STDout, n);
+				} else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
+					DSA *dsa = EVP_PKEY_get0_DSA(pkey);
+					const BIGNUM *pub_key = NULL;
+
+					DSA_get0_key(dsa, &pub_key, NULL);
+
+					BN_print(STDout, pub_key);
+				} else
+					BIO_printf(STDout,
+					    "Wrong Algorithm type");
+				BIO_printf(STDout, "\n");
+			} else if (cfg.pubkey == i) {
+				EVP_PKEY *pkey;
+
+				pkey = X509_get0_pubkey(x);
+				if (pkey == NULL) {
+					BIO_printf(bio_err,
+					    "Error getting public key\n");
+					ERR_print_errors(bio_err);
+					goto end;
+				}
+				PEM_write_bio_PUBKEY(STDout, pkey);
+			} else if (cfg.C == i) {
+				unsigned char *d;
+				char *m;
+				int y, z;
+
+				m = X509_NAME_oneline(X509_get_subject_name(x),
+				    buf, sizeof buf);
+				if (m == NULL)
+					goto end;
+				BIO_printf(STDout, "/* subject:%s */\n", buf);
+				m = X509_NAME_oneline(X509_get_issuer_name(x),
+				    buf, sizeof buf);
+				if (m == NULL)
+					goto end;
+				BIO_printf(STDout, "/* issuer :%s */\n", buf);
+
+				z = i2d_X509(x, NULL);
+				if (z < 0)
+					goto end;
+
+				m = malloc(z);
+				if (m == NULL) {
+					BIO_printf(bio_err, "out of mem\n");
+					goto end;
+				}
+
+				d = (unsigned char *) m;
+				z = i2d_X509_NAME(X509_get_subject_name(x), &d);
+				if (z < 0) {
+					free(m);
+					goto end;
+				}
+				BIO_printf(STDout,
+				    "unsigned char XXX_subject_name[%d]={\n", z);
+				d = (unsigned char *) m;
+				for (y = 0; y < z; y++) {
+					BIO_printf(STDout, "0x%02X,", d[y]);
+					if ((y & 0x0f) == 0x0f)
+						BIO_printf(STDout, "\n");
+				}
+				if (y % 16 != 0)
+					BIO_printf(STDout, "\n");
+				BIO_printf(STDout, "};\n");
+
+				z = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
+				if (z < 0) {
+					free(m);
+					goto end;
+				}
+				BIO_printf(STDout,
+				    "unsigned char XXX_public_key[%d]={\n", z);
+				d = (unsigned char *) m;
+				for (y = 0; y < z; y++) {
+					BIO_printf(STDout, "0x%02X,", d[y]);
+					if ((y & 0x0f) == 0x0f)
+						BIO_printf(STDout, "\n");
+				}
+				if (y % 16 != 0)
+					BIO_printf(STDout, "\n");
+				BIO_printf(STDout, "};\n");
+
+				z = i2d_X509(x, &d);
+				if (z < 0) {
+					free(m);
+					goto end;
+				}
+				BIO_printf(STDout,
+				    "unsigned char XXX_certificate[%d]={\n", z);
+				d = (unsigned char *) m;
+				for (y = 0; y < z; y++) {
+					BIO_printf(STDout, "0x%02X,", d[y]);
+					if ((y & 0x0f) == 0x0f)
+						BIO_printf(STDout, "\n");
+				}
+				if (y % 16 != 0)
+					BIO_printf(STDout, "\n");
+				BIO_printf(STDout, "};\n");
+
+				free(m);
+			} else if (cfg.text == i) {
+				if(!X509_print_ex(STDout, x, cfg.nmflag,
+				    cfg.certflag))
+					goto end;
+			} else if (cfg.startdate == i) {
+				ASN1_TIME *nB = X509_get_notBefore(x);
+
+				BIO_puts(STDout, "notBefore=");
+				if (ASN1_time_parse(nB->data, nB->length, NULL,
+				    0) == -1)
+					BIO_puts(STDout,
+					    "INVALID RFC5280 TIME");
+				else
+					ASN1_TIME_print(STDout, nB);
+				BIO_puts(STDout, "\n");
+			} else if (cfg.enddate == i) {
+				ASN1_TIME *nA = X509_get_notAfter(x);
+
+				BIO_puts(STDout, "notAfter=");
+				if (ASN1_time_parse(nA->data, nA->length, NULL,
+				    0) == -1)
+					BIO_puts(STDout,
+					    "INVALID RFC5280 TIME");
+				else
+					ASN1_TIME_print(STDout, nA);
+				BIO_puts(STDout, "\n");
+			} else if (cfg.fingerprint == i) {
+				int j;
+				unsigned int n;
+				unsigned char md[EVP_MAX_MD_SIZE];
+				const EVP_MD *fdig = cfg.digest;
+
+				if (fdig == NULL)
+					fdig = EVP_sha256();
+
+				if (!X509_digest(x, fdig, md, &n)) {
+					BIO_printf(bio_err, "out of memory\n");
+					goto end;
+				}
+				BIO_printf(STDout, "%s Fingerprint=",
+				    OBJ_nid2sn(EVP_MD_type(fdig)));
+				for (j = 0; j < (int) n; j++) {
+					BIO_printf(STDout, "%02X%c", md[j],
+					    (j + 1 == (int)n) ? '\n' : ':');
+				}
+
+			/* should be in the library */
+			} else if (cfg.sign_flag == i && cfg.x509req == 0) {
+				BIO_printf(bio_err, "Getting Private key\n");
+				if (Upkey == NULL) {
+					Upkey = load_key(bio_err, cfg.keyfile,
+					    cfg.keyformat, 0, passin,
+					    "Private key");
+					if (Upkey == NULL)
+						goto end;
+				}
+				if (!sign(x, Upkey, cfg.days,
+				    cfg.clrext, cfg.digest,
+				    extconf, cfg.extsect))
+					goto end;
+			} else if (cfg.CA_flag == i) {
+				BIO_printf(bio_err, "Getting CA Private Key\n");
+				if (cfg.CAkeyfile != NULL) {
+					CApkey = load_key(bio_err, cfg.CAkeyfile,
+					    cfg.CAkeyformat, 0, passin,
+					    "CA Private Key");
+					if (CApkey == NULL)
+						goto end;
+				}
+				if (!x509_certify(ctx, cfg.CAfile, cfg.digest,
+				    x, xca, CApkey, cfg.sigopts, cfg.CAserial,
+				    cfg.CA_createserial, cfg.days, cfg.clrext,
+				    extconf, cfg.extsect, cfg.sno))
+					goto end;
+			} else if (cfg.x509req == i) {
+				EVP_PKEY *pk;
+
+				BIO_printf(bio_err,
+				    "Getting request Private Key\n");
+				if (cfg.keyfile == NULL) {
+					BIO_printf(bio_err,
+					    "no request key file specified\n");
+					goto end;
+				} else {
+					pk = load_key(bio_err, cfg.keyfile,
+					    cfg.keyformat, 0, passin,
+					    "request key");
+					if (pk == NULL)
+						goto end;
+				}
+
+				BIO_printf(bio_err,
+				    "Generating certificate request\n");
+
+				rq = X509_to_X509_REQ(x, pk, cfg.digest);
+				EVP_PKEY_free(pk);
+				if (rq == NULL) {
+					ERR_print_errors(bio_err);
+					goto end;
+				}
+				if (!cfg.noout) {
+					if (!X509_REQ_print(out, rq))
+						goto end;
+					if (!PEM_write_bio_X509_REQ(out, rq))
+						goto end;
+				}
+				cfg.noout = 1;
+			} else if (cfg.ocspid == i) {
+				if (!X509_ocspid_print(out, x))
+					goto end;
+			}
+		}
+	}
+	if (cfg.checkend) {
+		time_t tcheck = time(NULL) + cfg.checkoffset;
+		int timecheck = X509_cmp_time(X509_get_notAfter(x), &tcheck);
+		if (timecheck == 0) {
+			BIO_printf(out, "Certificate expiry time is invalid\n");
+			ret = 1;
+		} else if (timecheck < 0) {
+			BIO_printf(out, "Certificate will expire\n");
+			ret = 1;
+		} else {
+			BIO_printf(out, "Certificate will not expire\n");
+			ret = 0;
+		}
+		goto end;
+	}
+	if (cfg.noout) {
+		ret = 0;
+		goto end;
+	}
+	if (cfg.outformat == FORMAT_ASN1)
+		i = i2d_X509_bio(out, x);
+	else if (cfg.outformat == FORMAT_PEM) {
+		if (cfg.trustout)
+			i = PEM_write_bio_X509_AUX(out, x);
+		else
+			i = PEM_write_bio_X509(out, x);
+	} else {
+		BIO_printf(bio_err,
+		    "bad output format specified for outfile\n");
+		goto end;
+	}
+	if (!i) {
+		BIO_printf(bio_err, "unable to write certificate\n");
+		ERR_print_errors(bio_err);
+		goto end;
+	}
+	ret = 0;
+
+ end:
+	OBJ_cleanup();
+	NCONF_free(extconf);
+	BIO_free_all(out);
+	BIO_free_all(STDout);
+	X509_STORE_free(ctx);
+	X509_REQ_free(req);
+	X509_free(x);
+	X509_free(xca);
+	EVP_PKEY_free(Upkey);
+	EVP_PKEY_free(CApkey);
+	sk_OPENSSL_STRING_free(cfg.sigopts);
+	X509_REQ_free(rq);
+	ASN1_INTEGER_free(cfg.sno);
+	sk_ASN1_OBJECT_pop_free(cfg.trust, ASN1_OBJECT_free);
+	sk_ASN1_OBJECT_pop_free(cfg.reject, ASN1_OBJECT_free);
+	free(passin);
+
+	return (ret);
+}
+
+static ASN1_INTEGER *
+x509_load_serial(char *CAfile, char *serialfile, int create)
+{
+	char *buf = NULL, *p;
+	ASN1_INTEGER *bs = NULL;
+	BIGNUM *serial = NULL;
+	size_t len;
+
+	len = ((serialfile == NULL) ? (strlen(CAfile) + strlen(POSTFIX) + 1) :
+	    (strlen(serialfile))) + 1;
+	buf = malloc(len);
+	if (buf == NULL) {
+		BIO_printf(bio_err, "out of mem\n");
+		goto end;
+	}
+	if (serialfile == NULL) {
+		strlcpy(buf, CAfile, len);
+		for (p = buf; *p; p++)
+			if (*p == '.') {
+				*p = '\0';
+				break;
+			}
+		strlcat(buf, POSTFIX, len);
+	} else
+		strlcpy(buf, serialfile, len);
+
+	serial = load_serial(buf, create, NULL);
+	if (serial == NULL)
+		goto end;
+
+	if (!BN_add_word(serial, 1)) {
+		BIO_printf(bio_err, "add_word failure\n");
+		goto end;
+	}
+	if (!save_serial(buf, NULL, serial, &bs))
+		goto end;
+
+ end:
+	free(buf);
+	BN_free(serial);
+
+	return bs;
+}
+
+static int
+x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x,
+    X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts,
+    char *serialfile, int create, int days, int clrext, CONF *conf,
+    char *section, ASN1_INTEGER *sno)
+{
+	int ret = 0;
+	ASN1_INTEGER *bs = NULL;
+	X509_STORE_CTX *xsc = NULL;
+	EVP_PKEY *upkey;
+
+	upkey = X509_get0_pubkey(xca);
+	if (upkey == NULL)
+		goto end;
+	EVP_PKEY_copy_parameters(upkey, pkey);
+
+	if ((xsc = X509_STORE_CTX_new()) == NULL)
+		goto end;
+	if (!X509_STORE_CTX_init(xsc, ctx, x, NULL)) {
+		BIO_printf(bio_err, "Error initialising X509 store\n");
+		goto end;
+	}
+	if (sno != NULL)
+		bs = sno;
+	else if ((bs = x509_load_serial(CAfile, serialfile, create)) == NULL)
+		goto end;
+
+/*	if (!X509_STORE_add_cert(ctx,x)) goto end;*/
+
+	/*
+	 * NOTE: this certificate can/should be self signed, unless it was a
+	 * certificate request in which case it is not.
+	 */
+	X509_STORE_CTX_set_cert(xsc, x);
+	X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE);
+	if (!cfg.reqfile && X509_verify_cert(xsc) <= 0)
+		goto end;
+
+	if (!X509_check_private_key(xca, pkey)) {
+		BIO_printf(bio_err,
+		    "CA certificate and CA private key do not match\n");
+		goto end;
+	}
+	if (!X509_set_issuer_name(x, X509_get_subject_name(xca)))
+		goto end;
+	if (!X509_set_serialNumber(x, bs))
+		goto end;
+
+	if (X509_gmtime_adj(X509_get_notBefore(x), 0L) == NULL)
+		goto end;
+
+	/* hardwired expired */
+	if (X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL) == NULL)
+		goto end;
+
+	if (clrext) {
+		while (X509_get_ext_count(x) > 0) {
+			if (X509_delete_ext(x, 0) == NULL)
+				goto end;
+		}
+	}
+	if (conf != NULL) {
+		X509V3_CTX ctx2;
+		if (!X509_set_version(x, 2))	/* version 3 certificate */
+			goto end;
+		X509V3_set_ctx(&ctx2, xca, x, NULL, NULL, 0);
+		X509V3_set_nconf(&ctx2, conf);
+		if (!X509V3_EXT_add_nconf(conf, &ctx2, section, x))
+			goto end;
+	}
+	if (!do_X509_sign(bio_err, x, pkey, digest, sigopts))
+		goto end;
+
+	ret = 1;
+ end:
+	X509_STORE_CTX_free(xsc);
+	if (!ret)
+		ERR_print_errors(bio_err);
+	if (sno == NULL)
+		ASN1_INTEGER_free(bs);
+	return ret;
+}
+
+static int
+callb(int ok, X509_STORE_CTX *ctx)
+{
+	int err;
+	X509 *err_cert;
+
+	/*
+	 * it is ok to use a self signed certificate This case will catch
+	 * both the initial ok == 0 and the final ok == 1 calls to this
+	 * function
+	 */
+	err = X509_STORE_CTX_get_error(ctx);
+	if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
+		return 1;
+
+	/*
+	 * BAD we should have gotten an error.  Normally if everything worked
+	 * X509_STORE_CTX_get_error(ctx) will still be set to
+	 * DEPTH_ZERO_SELF_....
+	 */
+	if (ok) {
+		BIO_printf(bio_err,
+		    "error with certificate to be certified - should be self signed\n");
+		return 0;
+	} else {
+		err_cert = X509_STORE_CTX_get_current_cert(ctx);
+		print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0);
+		BIO_printf(bio_err,
+		    "error with certificate - error %d at depth %d\n%s\n",
+		    err, X509_STORE_CTX_get_error_depth(ctx),
+		    X509_verify_cert_error_string(err));
+		return 1;
+	}
+}
+
+/* self sign */
+static int
+sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest,
+    CONF *conf, char *section)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = X509_get0_pubkey(x);
+	if (pktmp == NULL)
+		goto err;
+	EVP_PKEY_copy_parameters(pktmp, pkey);
+	EVP_PKEY_save_parameters(pktmp, 1);
+
+	if (!X509_set_issuer_name(x, X509_get_subject_name(x)))
+		goto err;
+	if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL)
+		goto err;
+
+	/* Lets just make it 12:00am GMT, Jan 1 1970 */
+	/* memcpy(x->cert_info->validity->notBefore,"700101120000Z",13); */
+	/* 28 days to be certified */
+
+	if (X509_gmtime_adj(X509_get_notAfter(x),
+	    (long) 60 * 60 * 24 * days) == NULL)
+		goto err;
+
+	if (!X509_set_pubkey(x, pkey))
+		goto err;
+	if (clrext) {
+		while (X509_get_ext_count(x) > 0) {
+			if (X509_delete_ext(x, 0) == NULL)
+				goto err;
+		}
+	}
+	if (conf != NULL) {
+		X509V3_CTX ctx;
+		if (!X509_set_version(x, 2))	/* version 3 certificate */
+			goto err;
+		X509V3_set_ctx(&ctx, x, x, NULL, NULL, 0);
+		X509V3_set_nconf(&ctx, conf);
+		if (!X509V3_EXT_add_nconf(conf, &ctx, section, x))
+			goto err;
+	}
+	if (!X509_sign(x, pkey, digest))
+		goto err;
+
+	return 1;
+
+ err:
+	ERR_print_errors(bio_err);
+	return 0;
+}
+
+static int
+purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt)
+{
+	int id, i, idret;
+	char *pname;
+
+	id = X509_PURPOSE_get_id(pt);
+	pname = X509_PURPOSE_get0_name(pt);
+	for (i = 0; i < 2; i++) {
+		idret = X509_check_purpose(cert, id, i);
+		BIO_printf(bio, "%s%s : ", pname, i ? " CA" : "");
+		if (idret == 1)
+			BIO_printf(bio, "Yes\n");
+		else if (idret == 0)
+			BIO_printf(bio, "No\n");
+		else
+			BIO_printf(bio, "Yes (WARNING code=%d)\n", idret);
+	}
+	return 1;
+}
diff --git a/asm/arch/aarch64/arm64cpuid.S b/asm/arch/aarch64/arm64cpuid.S
new file mode 100644
index 0000000..96a9c76
--- /dev/null
+++ b/asm/arch/aarch64/arm64cpuid.S
@@ -0,0 +1,53 @@
+#include "arm64_arch.h"
+
+.text
+.arch	armv8-a+crypto+sha3
+
+.align	5
+.globl	_armv7_neon_probe
+.type	_armv7_neon_probe,%function
+_armv7_neon_probe:
+	bti	c
+	orr	v15.16b, v15.16b, v15.16b
+	ret
+.size	_armv7_neon_probe,.-_armv7_neon_probe
+
+.globl	_armv8_aes_probe
+.type	_armv8_aes_probe,%function
+_armv8_aes_probe:
+	bti	c
+	aese	v0.16b, v0.16b
+	ret
+.size	_armv8_aes_probe,.-_armv8_aes_probe
+
+.globl	_armv8_sha1_probe
+.type	_armv8_sha1_probe,%function
+_armv8_sha1_probe:
+	bti	c
+	sha1h	s0, s0
+	ret
+.size	_armv8_sha1_probe,.-_armv8_sha1_probe
+
+.globl	_armv8_sha256_probe
+.type	_armv8_sha256_probe,%function
+_armv8_sha256_probe:
+	bti	c
+	sha256su0	v0.4s, v0.4s
+	ret
+.size	_armv8_sha256_probe,.-_armv8_sha256_probe
+
+.globl	_armv8_pmull_probe
+.type	_armv8_pmull_probe,%function
+_armv8_pmull_probe:
+	bti	c
+	pmull	v0.1q, v0.1d, v0.1d
+	ret
+.size	_armv8_pmull_probe,.-_armv8_pmull_probe
+
+.globl	_armv8_sha512_probe
+.type	_armv8_sha512_probe,%function
+_armv8_sha512_probe:
+	bti	c
+	sha512su0	v0.2d,v0.2d
+	ret
+.size	_armv8_sha512_probe,.-_armv8_sha512_probe
diff --git a/asm/arch/arm/armv4cpuid.S b/asm/arch/arm/armv4cpuid.S
new file mode 100644
index 0000000..db0b54e
--- /dev/null
+++ b/asm/arch/arm/armv4cpuid.S
@@ -0,0 +1,69 @@
+#include "arm_arch.h"
+
+.text
+#if defined(__thumb2__) && !defined(__APPLE__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#undef	__thumb2__
+#endif
+
+#if __ARM_ARCH__>=7
+.arch	armv7-a
+.fpu	neon
+
+.align	5
+.globl	_armv7_neon_probe
+.type	_armv7_neon_probe,%function
+_armv7_neon_probe:
+	vorr	q0,q0,q0
+	bx	lr
+.size	_armv7_neon_probe,.-_armv7_neon_probe
+
+.globl	_armv8_aes_probe
+.type	_armv8_aes_probe,%function
+_armv8_aes_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0xb0,0xff,0x00,0x03	@ aese.8	q0,q0
+#else
+.byte	0x00,0x03,0xb0,0xf3	@ aese.8	q0,q0
+#endif
+	bx	lr
+.size	_armv8_aes_probe,.-_armv8_aes_probe
+
+.globl	_armv8_sha1_probe
+.type	_armv8_sha1_probe,%function
+_armv8_sha1_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0x00,0xef,0x40,0x0c	@ sha1c.32	q0,q0,q0
+#else
+.byte	0x40,0x0c,0x00,0xf2	@ sha1c.32	q0,q0,q0
+#endif
+	bx	lr
+.size	_armv8_sha1_probe,.-_armv8_sha1_probe
+
+.globl	_armv8_sha256_probe
+.type	_armv8_sha256_probe,%function
+_armv8_sha256_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0x00,0xff,0x40,0x0c	@ sha256h.32	q0,q0,q0
+#else
+.byte	0x40,0x0c,0x00,0xf3	@ sha256h.32	q0,q0,q0
+#endif
+	bx	lr
+.size	_armv8_sha256_probe,.-_armv8_sha256_probe
+.globl	_armv8_pmull_probe
+.type	_armv8_pmull_probe,%function
+_armv8_pmull_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0xa0,0xef,0x00,0x0e	@ vmull.p64	q0,d0,d0
+#else
+.byte	0x00,0x0e,0xa0,0xf2	@ vmull.p64	q0,d0,d0
+#endif
+	bx	lr
+.size	_armv8_pmull_probe,.-_armv8_pmull_probe
+#endif
+
+.comm	OPENSSL_armcap_P,4,4
+.hidden	OPENSSL_armcap_P
diff --git a/asm/bn/arch/amd64/bignum_add.S b/asm/bn/arch/amd64/bignum_add.S
new file mode 100644
index 0000000..d56fa5e
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_add.S
@@ -0,0 +1,164 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Add, z := x + y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+//
+//    extern uint64_t bignum_add
+//     (uint64_t p, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the z := x + y operation, truncating modulo p words in general and
+// returning a top carry (0 or 1) in the p'th place, only adding the input
+// words below p (as well as m and n respectively) to get the sum and carry.
+//
+// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
+// Microsoft x64 ABI:   RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_add)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_add)
+        .text
+
+#define p rdi
+#define z rsi
+#define m rdx
+#define x rcx
+#define n r8
+#define y r9
+#define i r10
+#define a rax
+
+#define ashort eax
+
+
+
+S2N_BN_SYMBOL(bignum_add):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// Zero the main index counter for both branches
+
+        xor     i, i
+
+// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
+// we'll never need words past the p'th. Can now assume m <= p and n <= p.
+// Then compare the modified m and n and branch accordingly
+
+        cmp     p, m
+        cmovc   m, p
+        cmp     p, n
+        cmovc   n, p
+        cmp     m, n
+        jc      ylonger
+
+// The case where x is longer or of the same size (p >= m >= n)
+
+        sub     p, m
+        sub     m, n
+        inc     m
+        test    n, n
+        jz      xtest
+xmainloop:
+        mov     a, [x+8*i]
+        adc     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     xmainloop
+        jmp     xtest
+xtoploop:
+        mov     a, [x+8*i]
+        adc     a, 0
+        mov     [z+8*i],a
+        inc     i
+xtest:
+        dec     m
+        jnz     xtoploop
+        mov     ashort, 0
+        adc     a, 0
+        test    p, p
+        jnz     tails
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// The case where y is longer (p >= n > m)
+
+ylonger:
+
+        sub     p, n
+        sub     n, m
+        test    m, m
+        jz      ytoploop
+ymainloop:
+        mov     a, [x+8*i]
+        adc     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     m
+        jnz     ymainloop
+ytoploop:
+        mov     a, [y+8*i]
+        adc     a, 0
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     ytoploop
+        mov     ashort, 0
+        adc     a, 0
+        test    p, p
+        jnz     tails
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// Adding a non-trivial tail, when p > max(m,n)
+
+tails:
+        mov     [z+8*i],a
+        xor     a, a
+        jmp     tail
+tailloop:
+        mov     [z+8*i],a
+tail:
+        inc     i
+        dec     p
+        jnz     tailloop
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_cmadd.S b/asm/bn/arch/amd64/bignum_cmadd.S
new file mode 100644
index 0000000..1dc1e58
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_cmadd.S
@@ -0,0 +1,154 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply-add with single-word multiplier, z := z + c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+//
+//    extern uint64_t bignum_cmadd
+//     (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+//
+// Does the "z := z + c * y" operation where y is n digits, result z is p.
+// Truncates the result in general.
+//
+// The return value is a high/carry word that is meaningful when p = n + 1, or
+// more generally when n <= p and the result fits in p + 1 digits. In these
+// cases it gives the top digit of the (p + 1)-digit result.
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmadd)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmadd)
+        .text
+
+#define p rdi
+#define z rsi
+#define c r9
+#define n rcx
+#define x r8
+
+#define i r10
+#define h r11
+
+#define r rbx
+
+#define hshort r11d
+#define ishort r10d
+
+
+
+S2N_BN_SYMBOL(bignum_cmadd):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+#endif
+
+// Seems hard to avoid one more register
+
+        push    rbx
+
+// First clamp the input size n := min(p,n) since we can never need to read
+// past the p'th term of the input to generate p-digit output.
+// Subtract p := p - min(n,p) so it holds the size of the extra tail needed
+
+        cmp     p, n
+        cmovc   n, p
+        sub     p, n
+
+// Initialize high part h = 0; if n = 0 do nothing but return that zero
+
+        xor     h, h
+        test    n, n
+        jz      end
+
+// Move c into a safer register as multiplies overwrite rdx
+
+        mov     c, rdx
+
+// Initialization of the loop: 2^64 * CF + [h,z_0'] = z_0 + c * x_0
+
+        mov     rax, [x]
+        mul     c
+        add     [z], rax
+        mov     h, rdx
+        mov     ishort, 1
+        dec     n
+        jz      hightail
+
+// Main loop, where we always have CF + previous high part h to add in
+
+loop:
+        adc     h, [z+8*i]
+        sbb     r, r
+        mov     rax, [x+8*i]
+        mul     c
+        sub     rdx, r
+        add     rax, h
+        mov     [z+8*i], rax
+        mov     h, rdx
+        inc     i
+        dec     n
+        jnz     loop
+
+hightail:
+        adc     h, 0
+
+// Propagate the carry all the way to the end with h as extra carry word
+
+tail:
+        test    p, p
+        jz      end
+
+        add     [z+8*i], h
+        mov     hshort, 0
+        inc     i
+        dec     p
+        jz      highend
+
+tloop:
+        adc     [z+8*i], h
+        inc     i
+        dec     p
+        jnz     tloop
+
+highend:
+
+        adc     h, 0
+
+// Return the high/carry word
+
+end:
+        mov     rax, h
+
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_cmul.S b/asm/bn/arch/amd64/bignum_cmul.S
new file mode 100644
index 0000000..c1a23cc
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_cmul.S
@@ -0,0 +1,137 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply by a single word, z := c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+//
+//    extern uint64_t bignum_cmul
+//     (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+//
+// Does the "z := c * y" operation where y is n digits, result z is p.
+// Truncates the result in general unless p >= n + 1.
+//
+// The return value is a high/carry word that is meaningful when p >= n as
+// giving the high part of the result. Since this is always zero if p > n,
+// it is mainly of interest in the special case p = n, i.e. where the source
+// and destination have the same nominal size, when it gives the extra word
+// of the full result.
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmul)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmul)
+        .text
+
+#define p rdi
+#define z rsi
+#define c r9
+#define n rcx
+#define x r8
+
+#define i r10
+#define h r11
+
+
+
+S2N_BN_SYMBOL(bignum_cmul):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+#endif
+
+// First clamp the input size n := min(p,n) since we can never need to read
+// past the p'th term of the input to generate p-digit output. Now we can
+// assume that n <= p
+
+        cmp     p, n
+        cmovc   n, p
+
+// Initialize current input/output pointer offset i and high part h.
+// But then if n = 0 skip the multiplication and go to the tail part
+
+        xor     h, h
+        xor     i, i
+        test    n, n
+        jz      tail
+
+// Move c into a safer register as multiplies overwrite rdx
+
+        mov     c, rdx
+
+// Initialization of the loop: [h,l] = c * x_0
+
+        mov     rax, [x]
+        mul     c
+        mov     [z], rax
+        mov     h, rdx
+        inc     i
+        cmp     i, n
+        jz      tail
+
+// Main loop doing the multiplications
+
+loop:
+        mov     rax, [x+8*i]
+        mul     c
+        add     rax, h
+        adc     rdx, 0
+        mov     [z+8*i], rax
+        mov     h, rdx
+        inc     i
+        cmp     i, n
+        jc      loop
+
+// Add a tail when the destination is longer
+
+tail:
+        cmp     i, p
+        jnc     end
+        mov     [z+8*i], h
+        xor     h, h
+        inc     i
+        cmp     i, p
+        jnc     end
+
+tloop:
+        mov     [z+8*i], h
+        inc     i
+        cmp     i, p
+        jc      tloop
+
+// Return the high/carry word
+
+end:
+        mov     rax, h
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_mul.S b/asm/bn/arch/amd64/bignum_mul.S
new file mode 100644
index 0000000..42ac988
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_mul.S
@@ -0,0 +1,166 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[m], y[n]; output z[k]
+//
+//    extern void bignum_mul
+//     (uint64_t k, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the "z := x * y" operation where x is m digits, y is n, result z is k.
+// Truncates the result in general unless k >= m + n
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul)
+        .text
+
+// These are actually right
+
+#define p rdi
+#define z rsi
+#define n r8
+
+// These are not
+
+#define c r15
+#define h r14
+#define l r13
+#define x r12
+#define y r11
+#define i rbx
+#define k r10
+#define m rbp
+
+// These are always local scratch since multiplier result is in these
+
+#define a rax
+#define d rdx
+
+
+
+S2N_BN_SYMBOL(bignum_mul):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// We use too many registers, and also we need rax:rdx for multiplications
+
+        push    rbx
+        push    rbp
+        push    r12
+        push    r13
+        push    r14
+        push    r15
+        mov     m, rdx
+
+// If the result size is zero, do nothing
+// Note that even if either or both inputs has size zero, we can't
+// just give up because we at least need to zero the output array
+// If we did a multiply-add variant, however, then we could
+
+        test    p, p
+        jz      end
+
+// Set initial 2-part sum to zero (we zero c inside the body)
+
+        xor     h,h
+        xor     l,l
+
+// Otherwise do outer loop k = 0 ... k = p - 1
+
+        xor     k, k
+
+outerloop:
+
+// Zero our carry term first; we eventually want it and a zero is useful now
+// Set a =  max 0 (k + 1 - n), i = min (k + 1) m
+// This defines the range a <= j < i for the inner summation
+// Note that since k < p < 2^64 we can assume k + 1 doesn't overflow
+// And since we want to increment it anyway, we might as well do it now
+
+        xor     c, c            // c = 0
+        inc     k               // k = k + 1
+
+        mov     a, k            // a = k + 1
+        sub     a, n            // a = k + 1 - n
+        cmovc   a, c            // a = max 0 (k + 1 - n)
+
+        mov     i, m            // i = m
+        cmp     k, m            // CF <=> k + 1 < m
+        cmovc   i, k            // i = min (k + 1) m
+
+// Turn i into a loop count, and skip things if it's <= 0
+// Otherwise set up initial pointers x -> x0[a] and y -> y0[k - a]
+// and then launch into the main inner loop, postdecrementing i
+
+        mov     d, k
+        sub     d, i
+        sub     i, a
+        jbe     innerend
+        lea     x,[rcx+8*a]
+        lea     y,[r9+8*d-8]
+
+innerloop:
+        mov     rax, [y+8*i]
+        mul     QWORD PTR  [x]
+        add     x, 8
+        add     l, rax
+        adc     h, rdx
+        adc     c, 0
+        dec     i
+        jnz     innerloop
+
+innerend:
+
+        mov     [z], l
+        mov     l, h
+        mov     h, c
+        add     z, 8
+
+        cmp     k, p
+        jc      outerloop
+
+end:
+        pop     r15
+        pop     r14
+        pop     r13
+        pop     r12
+        pop     rbp
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_mul_4_8_alt.S b/asm/bn/arch/amd64/bignum_mul_4_8_alt.S
new file mode 100644
index 0000000..3b7848b
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_mul_4_8_alt.S
@@ -0,0 +1,156 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[4], y[4]; output z[8]
+//
+//    extern void bignum_mul_4_8_alt
+//      (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
+// Microsoft x64 ABI:   RCX = z, RDX = x, R8 = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_4_8_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_4_8_alt)
+        .text
+
+// These are actually right
+
+#define z rdi
+#define x rsi
+
+// This is moved from rdx to free it for muls
+
+#define y rcx
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A minutely shorter form for when c = 0 initially
+
+#define combadz(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, c
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa,numb)                  \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx
+
+S2N_BN_SYMBOL(bignum_mul_4_8_alt):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+#endif
+
+// Copy y into a safe register to start with
+
+        mov     y, rdx
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     QWORD PTR [y]
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combads(t1,t0,[x],[y+8])
+        combadz(t2,t1,t0,[x+8],[y])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+16])
+        combadd(t0,t2,t1,[x+8],[y+8])
+        combadd(t0,t2,t1,[x+16],[y])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+24])
+        combadd(t1,t0,t2,[x+8],[y+16])
+        combadd(t1,t0,t2,[x+16],[y+8])
+        combadd(t1,t0,t2,[x+24],[y])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+8],[y+24])
+        combadd(t2,t1,t0,[x+16],[y+16])
+        combadd(t2,t1,t0,[x+24],[y+8])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+16],[y+24])
+        combadd(t0,t2,t1,[x+24],[y+16])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combads(t0,t2,[x+24],[y+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        mov     [z+56], t0
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_mul_8_16_alt.S b/asm/bn/arch/amd64/bignum_mul_8_16_alt.S
new file mode 100644
index 0000000..1be3784
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_mul_8_16_alt.S
@@ -0,0 +1,243 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[8], y[8]; output z[16]
+//
+//    extern void bignum_mul_8_16_alt
+//     (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
+// Microsoft x64 ABI:   RCX = z, RDX = x, R8 = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_8_16_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_8_16_alt)
+        .text
+
+// These are actually right
+
+#define z rdi
+#define x rsi
+
+// This is moved from rdx to free it for muls
+
+#define y rcx
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A minutely shorter form for when c = 0 initially
+
+#define combadz(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, c
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa,numb)                  \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx
+
+S2N_BN_SYMBOL(bignum_mul_8_16_alt):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+#endif
+
+// Copy y into a safe register to start with
+
+        mov     y, rdx
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     QWORD PTR [y]
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combads(t1,t0,[x],[y+8])
+        combadz(t2,t1,t0,[x+8],[y])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+16])
+        combadd(t0,t2,t1,[x+8],[y+8])
+        combadd(t0,t2,t1,[x+16],[y])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+24])
+        combadd(t1,t0,t2,[x+8],[y+16])
+        combadd(t1,t0,t2,[x+16],[y+8])
+        combadd(t1,t0,t2,[x+24],[y])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x],[y+32])
+        combadd(t2,t1,t0,[x+8],[y+24])
+        combadd(t2,t1,t0,[x+16],[y+16])
+        combadd(t2,t1,t0,[x+24],[y+8])
+        combadd(t2,t1,t0,[x+32],[y])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+40])
+        combadd(t0,t2,t1,[x+8],[y+32])
+        combadd(t0,t2,t1,[x+16],[y+24])
+        combadd(t0,t2,t1,[x+24],[y+16])
+        combadd(t0,t2,t1,[x+32],[y+8])
+        combadd(t0,t2,t1,[x+40],[y])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+48])
+        combadd(t1,t0,t2,[x+8],[y+40])
+        combadd(t1,t0,t2,[x+16],[y+32])
+        combadd(t1,t0,t2,[x+24],[y+24])
+        combadd(t1,t0,t2,[x+32],[y+16])
+        combadd(t1,t0,t2,[x+40],[y+8])
+        combadd(t1,t0,t2,[x+48],[y])
+        mov     [z+48], t2
+
+// Result term 7
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x],[y+56])
+        combadd(t2,t1,t0,[x+8],[y+48])
+        combadd(t2,t1,t0,[x+16],[y+40])
+        combadd(t2,t1,t0,[x+24],[y+32])
+        combadd(t2,t1,t0,[x+32],[y+24])
+        combadd(t2,t1,t0,[x+40],[y+16])
+        combadd(t2,t1,t0,[x+48],[y+8])
+        combadd(t2,t1,t0,[x+56],[y])
+        mov     [z+56], t0
+
+// Result term 8
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+8],[y+56])
+        combadd(t0,t2,t1,[x+16],[y+48])
+        combadd(t0,t2,t1,[x+24],[y+40])
+        combadd(t0,t2,t1,[x+32],[y+32])
+        combadd(t0,t2,t1,[x+40],[y+24])
+        combadd(t0,t2,t1,[x+48],[y+16])
+        combadd(t0,t2,t1,[x+56],[y+8])
+        mov     [z+64], t1
+
+// Result term 9
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x+16],[y+56])
+        combadd(t1,t0,t2,[x+24],[y+48])
+        combadd(t1,t0,t2,[x+32],[y+40])
+        combadd(t1,t0,t2,[x+40],[y+32])
+        combadd(t1,t0,t2,[x+48],[y+24])
+        combadd(t1,t0,t2,[x+56],[y+16])
+        mov     [z+72], t2
+
+// Result term 10
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+24],[y+56])
+        combadd(t2,t1,t0,[x+32],[y+48])
+        combadd(t2,t1,t0,[x+40],[y+40])
+        combadd(t2,t1,t0,[x+48],[y+32])
+        combadd(t2,t1,t0,[x+56],[y+24])
+        mov     [z+80], t0
+
+// Result term 11
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+32],[y+56])
+        combadd(t0,t2,t1,[x+40],[y+48])
+        combadd(t0,t2,t1,[x+48],[y+40])
+        combadd(t0,t2,t1,[x+56],[y+32])
+        mov     [z+88], t1
+
+// Result term 12
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x+40],[y+56])
+        combadd(t1,t0,t2,[x+48],[y+48])
+        combadd(t1,t0,t2,[x+56],[y+40])
+        mov     [z+96], t2
+
+// Result term 13
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+48],[y+56])
+        combadd(t2,t1,t0,[x+56],[y+48])
+        mov     [z+104], t0
+
+// Result term 14
+
+        combads(t2,t1,[x+56],[y+56])
+        mov     [z+112], t1
+
+// Result term 11
+
+        mov     [z+120], t2
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_sqr.S b/asm/bn/arch/amd64/bignum_sqr.S
new file mode 100644
index 0000000..2e05b9c
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_sqr.S
@@ -0,0 +1,196 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square z := x^2
+// Input x[n]; output z[k]
+//
+//    extern void bignum_sqr
+//     (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
+//
+// Does the "z := x^2" operation where x is n digits and result z is k.
+// Truncates the result in general unless k >= 2 * n
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = n, RCX = x
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = n, R9 = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr)
+        .text
+
+// First three are where arguments come in, but n is moved.
+
+#define p rdi
+#define z rsi
+#define x rcx
+#define n r8
+
+// These are always local scratch since multiplier result is in these
+
+#define a rax
+#define d rdx
+
+// Other variables
+
+#define i rbx
+#define ll rbp
+#define hh r9
+#define k r10
+#define y r11
+#define htop r12
+#define l r13
+#define h r14
+#define c r15
+
+// Short versions
+
+#define llshort ebp
+
+S2N_BN_SYMBOL(bignum_sqr):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+#endif
+
+// We use too many registers, and also we need rax:rdx for multiplications
+
+        push    rbx
+        push    rbp
+        push    r12
+        push    r13
+        push    r14
+        push    r15
+        mov     n, rdx
+
+// If p = 0 the result is trivial and nothing needs doing
+
+        test    p, p
+        jz      end
+
+// initialize (hh,ll) = 0
+
+        xor     llshort, llshort
+        xor     hh, hh
+
+// Iterate outer loop from k = 0 ... k = p - 1 producing result digits
+
+        xor     k, k
+
+outerloop:
+
+// First let bot = MAX 0 (k + 1 - n) and top = MIN (k + 1) n
+// We want to accumulate all x[i] * x[k - i] for bot <= i < top
+// For the optimization of squaring we avoid duplication and do
+// 2 * x[i] * x[k - i] for i < htop, where htop = MIN ((k+1)/2) n
+// Initialize i = bot; in fact just compute bot as i directly.
+
+        xor     c, c
+        lea     i, [k+1]
+        mov     htop, i
+        shr     htop, 1
+        sub     i, n
+        cmovc   i, c
+        cmp     htop, n
+        cmovnc  htop, n
+
+// Initialize the three-part local sum (c,h,l); c was already done above
+
+        xor     l, l
+        xor     h, h
+
+// If htop <= bot then main doubled part of the sum is empty
+
+        cmp     i, htop
+        jnc     nosumming
+
+// Use a moving pointer for [y] = x[k-i] for the cofactor
+
+        mov     a, k
+        sub     a, i
+        lea     y, [x+8*a]
+
+// Do the main part of the sum x[i] * x[k - i] for 2 * i < k
+
+innerloop:
+        mov     a, [x+8*i]
+        mul     QWORD PTR [y]
+        add     l, a
+        adc     h, d
+        adc     c, 0
+        sub     y, 8
+        inc     i
+        cmp     i, htop
+        jc      innerloop
+
+// Now double it
+
+        add     l, l
+        adc     h, h
+        adc     c, c
+
+// If k is even (which means 2 * i = k) and i < n add the extra x[i]^2 term
+
+nosumming:
+        test    k, 1
+        jnz     innerend
+        cmp     i, n
+        jnc     innerend
+
+        mov     a, [x+8*i]
+        mul     a
+        add     l, a
+        adc     h, d
+        adc     c, 0
+
+// Now add the local sum into the global sum, store and shift
+
+innerend:
+        add     l, ll
+        mov     [z+8*k], l
+        adc     h, hh
+        mov     ll, h
+        adc     c, 0
+        mov     hh, c
+
+        inc     k
+        cmp     k, p
+        jc      outerloop
+
+// Restore registers and return
+
+end:
+        pop     r15
+        pop     r14
+        pop     r13
+        pop     r12
+        pop     rbp
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_sqr_4_8_alt.S b/asm/bn/arch/amd64/bignum_sqr_4_8_alt.S
new file mode 100644
index 0000000..a635177
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_sqr_4_8_alt.S
@@ -0,0 +1,144 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square, z := x^2
+// Input x[4]; output z[8]
+//
+//    extern void bignum_sqr_4_8_alt
+//      (uint64_t z[static 8], uint64_t x[static 4]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x
+// Microsoft x64 ABI:   RCX = z, RDX = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_4_8_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_4_8_alt)
+        .text
+
+// Input arguments
+
+#define z rdi
+#define x rsi
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 rcx
+#define t1 r8
+#define t2 r9
+
+// Macro for the key "multiply and add to (c,h,l)" step, for square term
+
+#define combadd1(c,h,l,numa)                    \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa)                       \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx
+
+// A version doubling before adding, for non-square terms
+
+#define combadd2(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     rax, rax;                       \
+        adc     rdx, rdx;                       \
+        adc     c, 0;                           \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+S2N_BN_SYMBOL(bignum_sqr_4_8_alt):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+#endif
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     rax
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+       xor     t2, t2
+       combadd2(t2,t1,t0,[x],[x+8])
+       mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadd1(t0,t2,t1,[x+8])
+        combadd2(t0,t2,t1,[x],[x+16])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadd2(t1,t0,t2,[x],[x+24])
+        combadd2(t1,t0,t2,[x+8],[x+16])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x+8],[x+24])
+        combadd1(t2,t1,t0,[x+16])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadd2(t0,t2,t1,[x+16],[x+24])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combads(t0,t2,[x+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        mov     [z+56], t0
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_sqr_8_16_alt.S b/asm/bn/arch/amd64/bignum_sqr_8_16_alt.S
new file mode 100644
index 0000000..f698202
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_sqr_8_16_alt.S
@@ -0,0 +1,241 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square, z := x^2
+// Input x[8]; output z[16]
+//
+//    extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x
+// Microsoft x64 ABI:   RCX = z, RDX = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_8_16_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_8_16_alt)
+        .text
+
+// Input arguments
+
+#define z rdi
+#define x rsi
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Additional temporaries for local windows to share doublings
+
+#define u0 rcx
+#define u1 r11
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// Set up initial window (c,h,l) = numa * numb
+
+#define combaddz(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        xor     c, c;                           \
+        mov     l, rax;                         \
+        mov     h, rdx
+
+// Doubling step (c,h,l) = 2 * (c,hh,ll) + (0,h,l)
+
+#define doubladd(c,h,l,hh,ll)                   \
+        add     ll, ll;                         \
+        adc     hh, hh;                         \
+        adc     c, c;                           \
+        add     l, ll;                          \
+        adc     h, hh;                          \
+        adc     c, 0
+
+// Square term incorporation (c,h,l) += numba^2
+
+#define combadd1(c,h,l,numa)                    \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa)                       \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx
+
+// A version doubling directly before adding, for single non-square terms
+
+#define combadd2(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     rax, rax;                       \
+        adc     rdx, rdx;                       \
+        adc     c, 0;                           \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+S2N_BN_SYMBOL(bignum_sqr_8_16_alt):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+#endif
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     rax
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x],[x+8])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadd1(t0,t2,t1,[x+8])
+        combadd2(t0,t2,t1,[x],[x+16])
+        mov     [z+16], t1
+
+// Result term 3
+
+        combaddz(t1,u1,u0,[x],[x+24])
+        combadd(t1,u1,u0,[x+8],[x+16])
+        doubladd(t1,t0,t2,u1,u0)
+        mov     [z+24], t2
+
+// Result term 4
+
+        combaddz(t2,u1,u0,[x],[x+32])
+        combadd(t2,u1,u0,[x+8],[x+24])
+        doubladd(t2,t1,t0,u1,u0)
+        combadd1(t2,t1,t0,[x+16])
+        mov     [z+32], t0
+
+// Result term 5
+
+        combaddz(t0,u1,u0,[x],[x+40])
+        combadd(t0,u1,u0,[x+8],[x+32])
+        combadd(t0,u1,u0,[x+16],[x+24])
+        doubladd(t0,t2,t1,u1,u0)
+        mov     [z+40], t1
+
+// Result term 6
+
+        combaddz(t1,u1,u0,[x],[x+48])
+        combadd(t1,u1,u0,[x+8],[x+40])
+        combadd(t1,u1,u0,[x+16],[x+32])
+        doubladd(t1,t0,t2,u1,u0)
+        combadd1(t1,t0,t2,[x+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        combaddz(t2,u1,u0,[x],[x+56])
+        combadd(t2,u1,u0,[x+8],[x+48])
+        combadd(t2,u1,u0,[x+16],[x+40])
+        combadd(t2,u1,u0,[x+24],[x+32])
+        doubladd(t2,t1,t0,u1,u0)
+        mov     [z+56], t0
+
+// Result term 8
+
+        combaddz(t0,u1,u0,[x+8],[x+56])
+        combadd(t0,u1,u0,[x+16],[x+48])
+        combadd(t0,u1,u0,[x+24],[x+40])
+        doubladd(t0,t2,t1,u1,u0)
+        combadd1(t0,t2,t1,[x+32])
+        mov     [z+64], t1
+
+// Result term 9
+
+        combaddz(t1,u1,u0,[x+16],[x+56])
+        combadd(t1,u1,u0,[x+24],[x+48])
+        combadd(t1,u1,u0,[x+32],[x+40])
+        doubladd(t1,t0,t2,u1,u0)
+        mov     [z+72], t2
+
+// Result term 10
+
+        combaddz(t2,u1,u0,[x+24],[x+56])
+        combadd(t2,u1,u0,[x+32],[x+48])
+        doubladd(t2,t1,t0,u1,u0)
+        combadd1(t2,t1,t0,[x+40])
+        mov     [z+80], t0
+
+// Result term 11
+
+        combaddz(t0,u1,u0,[x+32],[x+56])
+        combadd(t0,u1,u0,[x+40],[x+48])
+        doubladd(t0,t2,t1,u1,u0)
+        mov     [z+88], t1
+
+// Result term 12
+
+        xor     t1, t1
+        combadd2(t1,t0,t2,[x+40],[x+56])
+        combadd1(t1,t0,t2,[x+48])
+        mov     [z+96], t2
+
+// Result term 13
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x+48],[x+56])
+        mov     [z+104], t0
+
+// Result term 14
+
+        combads(t2,t1,[x+56])
+        mov     [z+112], t1
+
+// Result term 15
+
+        mov     [z+120], t2
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/bignum_sub.S b/asm/bn/arch/amd64/bignum_sub.S
new file mode 100644
index 0000000..f8e1fe3
--- /dev/null
+++ b/asm/bn/arch/amd64/bignum_sub.S
@@ -0,0 +1,152 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Subtract, z := x - y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+//
+//    extern uint64_t bignum_sub
+//     (uint64_t p, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the z := x - y operation, truncating modulo p words in general and
+// returning a top borrow (0 or 1) in the p'th place, only subtracting input
+// words below p (as well as m and n respectively) to get the diff and borrow.
+//
+// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
+// Microsoft x64 ABI:   RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sub)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sub)
+        .text
+
+#define p rdi
+#define z rsi
+#define m rdx
+#define x rcx
+#define n r8
+#define y r9
+#define i r10
+#define a rax
+
+#define ashort eax
+
+
+
+S2N_BN_SYMBOL(bignum_sub):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// Zero the main index counter for both branches
+
+        xor     i, i
+
+// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
+// we'll never need words past the p'th. Can now assume m <= p and n <= p.
+// Then compare the modified m and n and branch accordingly
+
+        cmp     p, m
+        cmovc   m, p
+        cmp     p, n
+        cmovc   n, p
+        cmp     m, n
+        jc      ylonger
+
+// The case where x is longer or of the same size (p >= m >= n)
+
+        sub     p, m
+        sub     m, n
+        inc     m
+        test    n, n
+        jz      xtest
+xmainloop:
+        mov     a, [x+8*i]
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     xmainloop
+        jmp     xtest
+xtoploop:
+        mov     a, [x+8*i]
+        sbb     a, 0
+        mov     [z+8*i],a
+        inc     i
+xtest:
+        dec     m
+        jnz     xtoploop
+        sbb     a, a
+        test    p, p
+        jz      tailskip
+tailloop:
+        mov     [z+8*i],a
+        inc     i
+        dec     p
+        jnz     tailloop
+tailskip:
+        neg     a
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// The case where y is longer (p >= n > m)
+
+ylonger:
+
+        sub     p, n
+        sub     n, m
+        test    m, m
+        jz      ytoploop
+ymainloop:
+        mov     a, [x+8*i]
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     m
+        jnz     ymainloop
+ytoploop:
+        mov     ashort, 0
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     ytoploop
+        sbb     a, a
+        test    p, p
+        jnz     tailloop
+        neg     a
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/bn/arch/amd64/word_clz.S b/asm/bn/arch/amd64/word_clz.S
new file mode 100644
index 0000000..025e98f
--- /dev/null
+++ b/asm/bn/arch/amd64/word_clz.S
@@ -0,0 +1,59 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Count leading zero bits in a single word
+// Input a; output function return
+//
+//    extern uint64_t word_clz (uint64_t a);
+//
+// Standard x86-64 ABI: RDI = a, returns RAX
+// Microsoft x64 ABI:   RCX = a, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(word_clz)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(word_clz)
+        .text
+
+S2N_BN_SYMBOL(word_clz):
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+#endif
+
+// First do rax = 63 - bsr(a), which is right except (maybe) for zero inputs
+
+        bsr     rax, rdi
+        xor     rax, 63
+
+// Force return of 64 in the zero-input case
+
+        mov     edx, 64
+        test    rdi, rdi
+        cmove   rax, rdx
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/asm/sparccpuid.S b/asm/sparccpuid.S
new file mode 100644
index 0000000..5d314d5
--- /dev/null
+++ b/asm/sparccpuid.S
@@ -0,0 +1,101 @@
+#if defined(__SUNPRO_C) && defined(__sparcv9)
+# define ABI64  /* They've said -xarch=v9 at command line */
+#elif defined(__GNUC__) && defined(__arch64__)
+# define ABI64  /* They've said -m64 at command line */
+#endif
+
+#ifdef ABI64
+  .register	%g2,#scratch
+  .register	%g3,#scratch
+# define	FRAME	-192
+# define	BIAS	2047
+#else
+# define	FRAME	-96
+# define	BIAS	0
+#endif
+
+.global	_sparcv9_vis1_probe
+.align	8
+_sparcv9_vis1_probe:
+	add	%sp,BIAS+2,%o1
+	.word	0xc19a5a40	!ldda	[%o1]ASI_FP16_P,%f0
+	retl
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+.type	_sparcv9_vis1_probe,#function
+.size	_sparcv9_vis1_probe,.-_sparcv9_vis1_probe
+
+! Probe and instrument VIS1 instruction. Output is number of cycles it
+! takes to execute rdtick and pair of VIS1 instructions. US-Tx VIS unit
+! is slow (documented to be 6 cycles on T2) and the core is in-order
+! single-issue, it should be possible to distinguish Tx reliably...
+! Observed return values are:
+!
+!	UltraSPARC IIe		7
+!	UltraSPARC III		7
+!	UltraSPARC T1		24
+!
+! Numbers for T2 and SPARC64 V-VII are more than welcomed.
+!
+! It would be possible to detect specifically US-T1 by instrumenting
+! fmul8ulx16, which is emulated on T1 and as such accounts for quite
+! a lot of %tick-s, couple of thousand on Linux...
+.global	_sparcv9_vis1_instrument
+.align	8
+_sparcv9_vis1_instrument:
+	.word	0x91410000	!rd	%tick,%o0
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+	.word	0x85b08d82	!fxor	%f2,%f2,%f2
+	.word	0x93410000	!rd	%tick,%o1
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+	.word	0x85b08d82	!fxor	%f2,%f2,%f2
+	.word	0x95410000	!rd	%tick,%o2
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+	.word	0x85b08d82	!fxor	%f2,%f2,%f2
+	.word	0x97410000	!rd	%tick,%o3
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+	.word	0x85b08d82	!fxor	%f2,%f2,%f2
+	.word	0x99410000	!rd	%tick,%o4
+
+	! calculate intervals
+	sub	%o1,%o0,%o0
+	sub	%o2,%o1,%o1
+	sub	%o3,%o2,%o2
+	sub	%o4,%o3,%o3
+
+	! find minimum value
+	cmp	%o0,%o1
+	.word	0x38680002	!bgu,a	%xcc,.+8
+	mov	%o1,%o0
+	cmp	%o0,%o2
+	.word	0x38680002	!bgu,a	%xcc,.+8
+	mov	%o2,%o0
+	cmp	%o0,%o3
+	.word	0x38680002	!bgu,a	%xcc,.+8
+	mov	%o3,%o0
+
+	retl
+	nop
+.type	_sparcv9_vis1_instrument,#function
+.size	_sparcv9_vis1_instrument,.-_sparcv9_vis1_instrument
+
+.global	_sparcv9_vis2_probe
+.align	8
+_sparcv9_vis2_probe:
+	retl
+	.word	0x81b00980	!bshuffle	%f0,%f0,%f0
+.type	_sparcv9_vis2_probe,#function
+.size	_sparcv9_vis2_probe,.-_sparcv9_vis2_probe
+
+.global	_sparcv9_fmadd_probe
+.align	8
+_sparcv9_fmadd_probe:
+	.word	0x81b00d80	!fxor	%f0,%f0,%f0
+	.word	0x85b08d82	!fxor	%f2,%f2,%f2
+	retl
+	.word	0x81b80440	!fmaddd	%f0,%f0,%f2,%f0
+.type	_sparcv9_fmadd_probe,#function
+.size	_sparcv9_fmadd_probe,.-_sparcv9_fmadd_probe
+
+.section	".init",#alloc,#execinstr
+	call	OPENSSL_cpuid_setup
+	nop
diff --git a/cert.pem b/cert.pem
new file mode 100644
index 0000000..e5215f3
--- /dev/null
+++ b/cert.pem
@@ -0,0 +1,6400 @@
+# $OpenBSD: cert.pem,v 1.26 2023/05/06 17:55:38 tb Exp $
+### /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+
+=== /C=ES/CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1977337328857672817 (0x1b70e9d2ffae6c71)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep 23 15:22:07 2014 GMT
+            Not After : May  5 15:22:07 2036 GMT
+        Subject: C=ES, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                65:CD:EB:AB:35:1E:00:3E:7E:D5:74:C0:1C:B4:73:47:0E:1A:64:2F
+            X509v3 Basic Constraints: critical
+                CA:TRUE, pathlen:1
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: http://www.firmaprofesional.com/cps
+                  User Notice:
+                    Explicit Text: 
+
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=0B:BE:C2:27:22:49:CB:39:AA:DB:35:5C:53:E3:8C:AE:78:FF:B6:FE
+SHA256 Fingerprint=57:DE:05:83:EF:D2:B2:6E:03:61:DA:99:DA:9D:F4:64:8D:EF:7E:E8:44:1C:3B:72:8A:FA:9B:CD:E0:F9:B2:6A
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1
+MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1UdDgQWBBRlzeurNR4APn7VdMAc
+tHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4wgZswgZgGBFUd
+IAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABC
+AG8AbgBhAG4AbwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAw
+ADEANzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9m
+iWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL4QjbEwj4KKE1soCzC1HA01aajTNF
+Sa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDbLIpgD7dvlAceHabJ
+hfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1ilI45P
+Vf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZE
+EAEeiGaPcjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV
+1aUsIC+nmCjuRfzxuIgALI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2t
+CsvMo2ebKHTEm9caPARYpoKdrcd7b/+Alun4jWq9GJAd/0kakFI3ky88Al2CdgtR
+5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH9IBk9W6VULgRfhVwOEqw
+f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9
+ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK
+GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+### ACCV
+
+=== /CN=ACCVRAIZ1/OU=PKIACCV/O=ACCV/C=ES
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6828503384748696800 (0x5ec3b7a6437fa4e0)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: May  5 09:37:37 2011 GMT
+            Not After : Dec 31 09:37:37 2030 GMT
+        Subject: CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES
+        X509v3 extensions:
+            Authority Information Access: 
+                CA Issuers - URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt
+                OCSP - URI:http://ocsp.accv.es
+
+            X509v3 Subject Key Identifier: 
+                D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  User Notice:
+                    Explicit Text: 
+                  CPS: http://www.accv.es/legislacion_c.htm
+
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl
+
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Alternative Name: 
+                email:accv@accv.es
+SHA1 Fingerprint=93:05:7A:88:15:C6:4F:CE:88:2F:FA:91:16:52:28:78:BC:53:64:17
+SHA256 Fingerprint=9A:6E:C0:12:E1:A7:DA:9D:BE:34:19:4D:47:8A:D7:C0:DB:18:22:FB:07:1D:F1:29:81:49:6E:D1:04:38:41:13
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+### Actalis S.p.A./03358520967
+
+=== /C=IT/L=Milan/O=Actalis S.p.A./03358520967/CN=Actalis Authentication Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6271844772424770508 (0x570a119742c4e3cc)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep 22 11:22:02 2011 GMT
+            Not After : Sep 22 11:22:02 2030 GMT
+        Subject: C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication Root CA
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=F3:73:B3:87:06:5A:28:84:8A:F2:F3:4A:CE:19:2B:DD:C7:8E:9C:AC
+SHA256 Fingerprint=55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+### AffirmTrust
+
+=== /C=US/O=AffirmTrust/CN=AffirmTrust Commercial
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8608355977964138876 (0x7777062726a9b17c)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 29 14:06:06 2010 GMT
+            Not After : Dec 31 14:06:06 2030 GMT
+        Subject: C=US, O=AffirmTrust, CN=AffirmTrust Commercial
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                9D:93:C6:53:8B:5E:CA:AF:3F:9F:1E:0F:E5:99:95:BC:24:F6:94:8F
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=F9:B5:B6:32:45:5F:9C:BE:EC:57:5F:80:DC:E9:6E:2C:C7:B2:78:B7
+SHA256 Fingerprint=03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+=== /C=US/O=AffirmTrust/CN=AffirmTrust Networking
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8957382827206547757 (0x7c4f04391cd4992d)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jan 29 14:08:24 2010 GMT
+            Not After : Dec 31 14:08:24 2030 GMT
+        Subject: C=US, O=AffirmTrust, CN=AffirmTrust Networking
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                07:1F:D2:E7:9C:DA:C2:6E:A2:40:B4:B0:7A:50:10:50:74:C4:C8:BD
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=29:36:21:02:8B:20:ED:02:F5:66:C5:32:D1:D6:ED:90:9F:45:00:2F
+SHA256 Fingerprint=0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+=== /C=US/O=AffirmTrust/CN=AffirmTrust Premium
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee)
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jan 29 14:10:36 2010 GMT
+            Not After : Dec 31 14:10:36 2040 GMT
+        Subject: C=US, O=AffirmTrust, CN=AffirmTrust Premium
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                9D:C0:67:A6:0C:22:D9:26:F5:45:AB:A6:65:52:11:27:D8:45:AC:63
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=D8:A6:33:2C:E0:03:6F:B1:85:F6:63:4F:7D:6A:06:65:26:32:28:27
+SHA256 Fingerprint=70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+=== /C=US/O=AffirmTrust/CN=AffirmTrust Premium ECC
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8401224907861490260 (0x7497258ac73f7a54)
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jan 29 14:20:24 2010 GMT
+            Not After : Dec 31 14:20:24 2040 GMT
+        Subject: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                9A:AF:29:7A:C0:11:35:35:26:51:30:00:C3:6A:FE:40:D5:AE:D6:3C
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=B8:23:6B:00:2F:1D:16:86:53:01:55:6C:11:A4:37:CA:EB:FF:C3:BB
+SHA256 Fingerprint=BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+### Agence Nationale de Certification Electronique
+
+=== /C=TN/O=Agence Nationale de Certification Electronique/CN=TunTrust Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            13:02:d5:e2:40:4c:92:46:86:16:67:5d:b4:bb:bb:b2:6b:3e:fc:13
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Apr 26 08:57:56 2019 GMT
+            Not After : Apr 26 08:57:56 2044 GMT
+        Subject: C=TN, O=Agence Nationale de Certification Electronique, CN=TunTrust Root CA
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                06:9A:9B:1F:53:7D:F1:F5:A4:C8:D3:86:3E:A1:73:59:B4:F7:44:21
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:06:9A:9B:1F:53:7D:F1:F5:A4:C8:D3:86:3E:A1:73:59:B4:F7:44:21
+
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=CF:E9:70:84:0F:E0:73:0F:9D:F6:0C:7F:2C:4B:EE:20:46:34:9C:BB
+SHA256 Fingerprint=2E:44:10:2A:B5:8C:B8:54:19:45:1C:8E:19:D9:AC:F3:66:2C:AF:BC:61:4B:6A:53:96:0A:30:F7:D0:E2:EB:41
+-----BEGIN CERTIFICATE-----
+MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL
+BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg
+Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv
+b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG
+EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u
+IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ
+n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd
+2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF
+VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ
+GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF
+li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU
+r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2
+eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb
+MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg
+jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB
+7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW
+5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE
+ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0
+90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z
+xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu
+QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4
+FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH
+22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP
+xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn
+dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5
+Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b
+nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ
+CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH
+u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj
+d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o=
+-----END CERTIFICATE-----
+
+### Amazon
+
+=== /C=US/O=Amazon/CN=Amazon Root CA 1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:6c:9f:cf:99:bf:8c:0a:39:e2:f0:78:8a:43:e6:96:36:5b:ca
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: May 26 00:00:00 2015 GMT
+            Not After : Jan 17 00:00:00 2038 GMT
+        Subject: C=US, O=Amazon, CN=Amazon Root CA 1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                84:18:CC:85:34:EC:BC:0C:94:94:2E:08:59:9C:C7:B2:10:4E:0A:08
+SHA1 Fingerprint=8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16
+SHA256 Fingerprint=8E:CD:E6:88:4F:3D:87:B1:12:5B:A3:1A:C3:FC:B1:3D:70:16:DE:7F:57:CC:90:4F:E1:CB:97:C6:AE:98:19:6E
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+=== /C=US/O=Amazon/CN=Amazon Root CA 2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:6c:9f:d2:96:35:86:9f:0a:0f:e5:86:78:f8:5b:26:bb:8a:37
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: May 26 00:00:00 2015 GMT
+            Not After : May 26 00:00:00 2040 GMT
+        Subject: C=US, O=Amazon, CN=Amazon Root CA 2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                B0:0C:F0:4C:30:F4:05:58:02:48:FD:33:E5:52:AF:4B:84:E3:66:52
+SHA1 Fingerprint=5A:8C:EF:45:D7:A6:98:59:76:7A:8C:8B:44:96:B5:78:CF:47:4B:1A
+SHA256 Fingerprint=1B:A5:B2:AA:8C:65:40:1A:82:96:01:18:F8:0B:EC:4F:62:30:4D:83:CE:C4:71:3A:19:C3:9C:01:1E:A4:6D:B4
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+=== /C=US/O=Amazon/CN=Amazon Root CA 3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:6c:9f:d5:74:97:36:66:3f:3b:0b:9a:d9:e8:9e:76:03:f2:4a
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: May 26 00:00:00 2015 GMT
+            Not After : May 26 00:00:00 2040 GMT
+        Subject: C=US, O=Amazon, CN=Amazon Root CA 3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                AB:B6:DB:D7:06:9E:37:AC:30:86:07:91:70:C7:9C:C4:19:B1:78:C0
+SHA1 Fingerprint=0D:44:DD:8C:3C:8C:1A:1A:58:75:64:81:E9:0F:2E:2A:FF:B3:D2:6E
+SHA256 Fingerprint=18:CE:6C:FE:7B:F1:4E:60:B2:E3:47:B8:DF:E8:68:CB:31:D0:2E:BB:3A:DA:27:15:69:F5:03:43:B4:6D:B3:A4
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+=== /C=US/O=Amazon/CN=Amazon Root CA 4
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:6c:9f:d7:c1:bb:10:4c:29:43:e5:71:7b:7b:2c:c8:1a:c1:0e
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: May 26 00:00:00 2015 GMT
+            Not After : May 26 00:00:00 2040 GMT
+        Subject: C=US, O=Amazon, CN=Amazon Root CA 4
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                D3:EC:C7:3A:65:6E:CC:E1:DA:76:9A:56:FB:9C:F3:86:6D:57:E5:81
+SHA1 Fingerprint=F6:10:84:07:D6:F8:BB:67:98:0C:C2:E2:44:C2:EB:AE:1C:EF:63:BE
+SHA256 Fingerprint=E3:5D:28:41:9E:D0:20:25:CF:A6:90:38:CD:62:39:62:45:8D:A5:C6:95:FB:DE:A3:C2:2B:0B:FB:25:89:70:92
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+### ANF Autoridad de Certificacion
+
+=== /serialNumber=G63287510/C=ES/O=ANF Autoridad de Certificacion/OU=ANF CA Raiz/CN=ANF Secure Server Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 996390341000653745 (0xdd3e3bc6cf96bb1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep  4 10:00:38 2019 GMT
+            Not After : Aug 30 10:00:38 2039 GMT
+        Subject: serialNumber=G63287510, C=ES, O=ANF Autoridad de Certificacion, OU=ANF CA Raiz, CN=ANF Secure Server Root CA
+        X509v3 extensions:
+            X509v3 Authority Key Identifier: 
+                keyid:9C:5F:D0:6C:63:A3:5F:93:CA:93:98:08:AD:8C:87:A5:2C:5C:C1:37
+
+            X509v3 Subject Key Identifier: 
+                9C:5F:D0:6C:63:A3:5F:93:CA:93:98:08:AD:8C:87:A5:2C:5C:C1:37
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=5B:6E:68:D0:CC:15:B6:A0:5F:1E:C1:5F:AE:02:FC:6B:2F:5D:6F:74
+SHA256 Fingerprint=FB:8F:EC:75:91:69:B9:10:6B:1E:51:16:44:C6:18:C5:13:04:37:3F:6C:06:43:08:8D:8B:EF:FD:1B:99:75:99
+-----BEGIN CERTIFICATE-----
+MIIF7zCCA9egAwIBAgIIDdPjvGz5a7EwDQYJKoZIhvcNAQELBQAwgYQxEjAQBgNV
+BAUTCUc2MzI4NzUxMDELMAkGA1UEBhMCRVMxJzAlBgNVBAoTHkFORiBBdXRvcmlk
+YWQgZGUgQ2VydGlmaWNhY2lvbjEUMBIGA1UECxMLQU5GIENBIFJhaXoxIjAgBgNV
+BAMTGUFORiBTZWN1cmUgU2VydmVyIFJvb3QgQ0EwHhcNMTkwOTA0MTAwMDM4WhcN
+MzkwODMwMTAwMDM4WjCBhDESMBAGA1UEBRMJRzYzMjg3NTEwMQswCQYDVQQGEwJF
+UzEnMCUGA1UEChMeQU5GIEF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uMRQwEgYD
+VQQLEwtBTkYgQ0EgUmFpejEiMCAGA1UEAxMZQU5GIFNlY3VyZSBTZXJ2ZXIgUm9v
+dCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANvrayvmZFSVgpCj
+cqQZAZ2cC4Ffc0m6p6zzBE57lgvsEeBbphzOG9INgxwruJ4dfkUyYA8H6XdYfp9q
+yGFOtibBTI3/TO80sh9l2Ll49a2pcbnvT1gdpd50IJeh7WhM3pIXS7yr/2WanvtH
+2Vdy8wmhrnZEE26cLUQ5vPnHO6RYPUG9tMJJo8gN0pcvB2VSAKduyK9o7PQUlrZX
+H1bDOZ8rbeTzPvY1ZNoMHKGESy9LS+IsJJ1tk0DrtSOOMspvRdOoiXsezx76W0OL
+zc2oD2rKDF65nkeP8Nm2CgtYZRczuSPkdxl9y0oukntPLxB3sY0vaJxizOBQ+OyR
+p1RMVwnVdmPF6GUe7m1qzwmd+nxPrWAI/VaZDxUse6mAq4xhj0oHdkLePfTdsiQz
+W7i1o0TJrH93PB0j7IKppuLIBkwC/qxcmZkLLxCKpvR/1Yd0DVlJRfbwcVw5Kda/
+SiOL9V8BY9KHcyi1Swr1+KuCLH5zJTIdC2MKF4EA/7Z2Xue0sUDKIbvVgFHlSFJn
+LNJhiQcND85Cd8BEc5xEUKDbEAotlRyBr+Qc5RQe8TZBAQIvfXOn3kLMTOmJDVb3
+n5HUA8ZsyY/b2BzgQJhdZpmYgG4t/wHFzstGH6wCxkPmrqKEPMVOHj1tyRRM4y5B
+u8o5vzY8KhmqQYdOpc5LMnndkEl/AgMBAAGjYzBhMB8GA1UdIwQYMBaAFJxf0Gxj
+o1+TypOYCK2Mh6UsXME3MB0GA1UdDgQWBBScX9BsY6Nfk8qTmAitjIelLFzBNzAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
+AgEATh65isagmD9uw2nAalxJUqzLK114OMHVVISfk/CHGT0sZonrDUL8zPB1hT+L
+9IBdeeUXZ701guLyPI59WzbLWoAAKfLOKyzxj6ptBZNscsdW699QIyjlRRA96Gej
+rw5VD5AJYu9LWaL2U/HANeQvwSS9eS9OICI7/RogsKQOLHDtdD+4E5UGUcjohybK
+pFtqFiGS3XNgnhAY3jyB6ugYw3yJ8otQPr0R4hUDqDZ9MwFsSBXXiJCZBMXM5gf0
+vPSQ7RPi6ovDj6MzD8EpTBNO2hVWcXNyglD2mjN8orGoGjR0ZVzO0eurU+AagNjq
+OknkJjCb5RyKqKkVMoaZkgoQI1YS4PbOTOK7vtuNknMBZi9iPrJyJ0U27U1W45eZ
+/zo1PqVUSlJZS2Db7v54EX9K3BR5YLZrZAPbFYPhor72I5dQ8AkzNqdxliXzuUJ9
+2zg/LFis6ELhDtjTO0wugumDLmsx2d1Hhk9tl5EuT+IocTUW0fJz/iUrB0ckYyfI
++PbZa/wSMVYIwFNCr5zQM378BvAxRAMU8Vjq8moNqRGyg77FGr8H6lnco4g175x2
+MjxNBiLOFeXdntiP2t7SxDnlF4HPOEfrf4htWRvfn0IUrn7PqLBmZdo3r5+qPeoo
+tt7VMVgWglvquxl1AnMaykgaIZOQCo6ThKd9OyMYkomgjaw=
+-----END CERTIFICATE-----
+
+### Asseco Data Systems S.A.
+
+=== /C=PL/O=Asseco Data Systems S.A./OU=Certum Certification Authority/CN=Certum EC-384 CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            78:8f:27:5c:81:12:52:20:a5:04:d0:2d:dd:ba:73:f4
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Mar 26 07:24:54 2018 GMT
+            Not After : Mar 26 07:24:54 2043 GMT
+        Subject: C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum EC-384 CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                8D:06:66:74:24:76:3A:F3:89:F7:BC:D6:BD:47:7D:2F:BC:10:5F:4B
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=F3:3E:78:3C:AC:DF:F4:A2:CC:AC:67:55:69:56:D7:E5:16:3C:E1:ED
+SHA256 Fingerprint=6B:32:80:85:62:53:18:AA:50:D1:73:C9:8D:8B:DA:09:D5:7E:27:41:3D:11:4C:F7:87:A0:F5:D0:6C:03:0C:F6
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw
+CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw
+JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT
+EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0
+WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT
+LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX
+BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE
+KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm
+Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8
+EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J
+UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn
+nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k=
+-----END CERTIFICATE-----
+=== /C=PL/O=Asseco Data Systems S.A./OU=Certum Certification Authority/CN=Certum Trusted Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            1e:bf:59:50:b8:c9:80:37:4c:06:f7:eb:55:4f:b5:ed
+    Signature Algorithm: sha512WithRSAEncryption
+        Validity
+            Not Before: Mar 16 12:10:13 2018 GMT
+            Not After : Mar 16 12:10:13 2043 GMT
+        Subject: C=PL, O=Asseco Data Systems S.A., OU=Certum Certification Authority, CN=Certum Trusted Root CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                8C:FB:1C:75:BC:02:D3:9F:4E:2E:48:D9:F9:60:54:AA:C4:B3:4F:FA
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=C8:83:44:C0:18:AE:9F:CC:F1:87:B7:8F:22:D1:C5:D7:45:84:BA:E5
+SHA256 Fingerprint=FE:76:96:57:38:55:77:3E:37:A9:5E:7A:D4:D9:CC:96:C3:01:57:C1:5D:31:76:5B:A9:B1:57:04:E1:AE:78:FD
+-----BEGIN CERTIFICATE-----
+MIIFwDCCA6igAwIBAgIQHr9ZULjJgDdMBvfrVU+17TANBgkqhkiG9w0BAQ0FADB6
+MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEu
+MScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxHzAdBgNV
+BAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwHhcNMTgwMzE2MTIxMDEzWhcNNDMw
+MzE2MTIxMDEzWjB6MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEg
+U3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkxHzAdBgNVBAMTFkNlcnR1bSBUcnVzdGVkIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDRLY67tzbqbTeRn06TpwXkKQMlzhyC93yZ
+n0EGze2jusDbCSzBfN8pfktlL5On1AFrAygYo9idBcEq2EXxkd7fO9CAAozPOA/q
+p1x4EaTByIVcJdPTsuclzxFUl6s1wB52HO8AU5853BSlLCIls3Jy/I2z5T4IHhQq
+NwuIPMqw9MjCoa68wb4pZ1Xi/K1ZXP69VyywkI3C7Te2fJmItdUDmj0VDT06qKhF
+8JVOJVkdzZhpu9PMMsmN74H+rX2Ju7pgE8pllWeg8xn2A1bUatMn4qGtg/BKEiJ3
+HAVz4hlxQsDsdUaakFjgao4rpUYwBI4Zshfjvqm6f1bxJAPXsiEodg42MEx51UGa
+mqi4NboMOvJEGyCI98Ul1z3G4z5D3Yf+xOr1Uz5MZf87Sst4WmsXXw3Hw09Omiqi
+7VdNIuJGmj8PkTQkfVXjjJU30xrwCSss0smNtA0Aq2cpKNgB9RkEth2+dv5yXMSF
+ytKAQd8FqKPVhJBPC/PgP5sZ0jeJP/J7UhyM9uH3PAeXjA6iWYEMspA90+NZRu0P
+qafegGtaqge2Gcu8V/OXIXoMsSt0Puvap2ctTMSYnjYJdmZm/Bo/6khUHL4wvYBQ
+v3y1zgD2DGHZ5yQD4OMBgQ692IU0iL2yNqh7XAjlRICMb/gv1SHKHRzQ+8S1h9E6
+Tsd2tTVItQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSM+xx1
+vALTn04uSNn5YFSqxLNP+jAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQENBQAD
+ggIBAEii1QALLtA/vBzVtVRJHlpr9OTy4EA34MwUe7nJ+jW1dReTagVphZzNTxl4
+WxmB82M+w85bj/UvXgF2Ez8sALnNllI5SW0ETsXpD4YN4fqzX4IS8TrOZgYkNCvo
+zMrnadyHncI013nR03e4qllY/p0m+jiGPp2Kh2RX5Rc64vmNueMzeMGQ2Ljdt4NR
+5MTMI9UGfOZR0800McD2RrsLrfw9EAUqO0qRJe6M1ISHgCq8CYyqOhNf6DR5UMEQ
+GfnTKB7U0VEwKbOukGfWHwpjscWpxkIxYxeU72nLL/qMFH3EQxiJ2fAyQOaA4kZf
+5ePBAFmo+eggvIksDkc0C+pXwlM2/KfUrzHN/gLldfq5Jwn58/U7yn2fqSLLiMmq
+0Uc9NneoWWRrJ8/vJ8HjJLWG965+Mk2weWjROeiQWMODvA8s1pfrzgzhIMfatz7D
+P78v3DSk+yshzWePS/Tj6tQ/50+6uaWTRRxmHyH6ZF5v4HaUMst19W7l9o/HuKTM
+qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP
+0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf
+E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
+-----END CERTIFICATE-----
+
+### Atos
+
+=== /CN=Atos TrustedRoot 2011/O=Atos/C=DE
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6643877497813316402 (0x5c33cb622c5fb332)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jul  7 14:58:30 2011 GMT
+            Not After : Dec 31 23:59:59 2030 GMT
+        Subject: CN=Atos TrustedRoot 2011, O=Atos, C=DE
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+
+            X509v3 Certificate Policies: 
+                Policy: 1.3.6.1.4.1.6189.3.4.1.1
+
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=2B:B1:F5:3E:55:0C:1D:C5:F1:D4:E6:B7:6A:46:4B:55:06:02:AC:21
+SHA256 Fingerprint=F3:56:BE:A2:44:B7:A9:1E:B3:5D:53:CA:9A:D7:86:4A:CE:01:8E:2D:35:D5:F8:F9:6D:DF:68:A6:F4:1A:A4:74
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+### Baltimore
+
+=== /C=IE/O=Baltimore/OU=CyberTrust/CN=Baltimore CyberTrust Root
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 33554617 (0x20000b9)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: May 12 18:46:00 2000 GMT
+            Not After : May 12 23:59:00 2025 GMT
+        Subject: C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                E5:9D:59:30:82:47:58:CC:AC:FA:08:54:36:86:7B:3A:B5:04:4D:F0
+            X509v3 Basic Constraints: critical
+                CA:TRUE, pathlen:3
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=D4:DE:20:D0:5E:66:FC:53:FE:1A:50:88:2C:78:DB:28:52:CA:E4:74
+SHA256 Fingerprint=16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+### Buypass AS-983163327
+
+=== /C=NO/O=Buypass AS-983163327/CN=Buypass Class 2 Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct 26 08:38:03 2010 GMT
+            Not After : Oct 26 08:38:03 2040 GMT
+        Subject: C=NO, O=Buypass AS-983163327, CN=Buypass Class 2 Root CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                C9:80:77:E0:62:92:82:F5:46:9C:F3:BA:F7:4C:C3:DE:B8:A3:AD:39
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99
+SHA256 Fingerprint=9A:11:40:25:19:7C:5B:B9:5D:94:E6:3D:55:CD:43:79:08:47:B6:46:B2:3C:DF:11:AD:A4:A0:0E:FF:15:FB:48
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+=== /C=NO/O=Buypass AS-983163327/CN=Buypass Class 3 Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct 26 08:28:58 2010 GMT
+            Not After : Oct 26 08:28:58 2040 GMT
+        Subject: C=NO, O=Buypass AS-983163327, CN=Buypass Class 3 Root CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                47:B8:CD:FF:E5:6F:EE:F8:B2:EC:2F:4E:0E:F9:25:B0:8E:3C:6B:C3
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57
+SHA256 Fingerprint=ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+### Certainly
+
+=== /C=US/O=Certainly/CN=Certainly Root E1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            06:25:33:b1:47:03:33:27:5c:f9:8d:9a:b9:bf:cc:f8
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Apr  1 00:00:00 2021 GMT
+            Not After : Apr  1 00:00:00 2046 GMT
+        Subject: C=US, O=Certainly, CN=Certainly Root E1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                F3:28:18:CB:64:75:EE:29:2A:EB:ED:AE:23:58:38:85:EB:C8:22:07
+SHA1 Fingerprint=F9:E1:6D:DC:01:89:CF:D5:82:45:63:3E:C5:37:7D:C2:EB:93:6F:2B
+SHA256 Fingerprint=B4:58:5F:22:E4:AC:75:6A:4E:86:12:A1:36:1C:5D:9D:03:1A:93:FD:84:FE:BB:77:8F:A3:06:8B:0F:C4:2D:C2
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQsw
+CQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlu
+bHkgUm9vdCBFMTAeFw0yMTA0MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJ
+BgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlubHkxGjAYBgNVBAMTEUNlcnRhaW5s
+eSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4fxzf7flHh4axpMCK
++IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9YBk2
+QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4
+hevIIgcwCgYIKoZIzj0EAwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozm
+ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG
+BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+=== /C=US/O=Certainly/CN=Certainly Root R1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8e:0f:f9:4b:90:71:68:65:33:54:f4:d4:44:39:b7:e0
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Apr  1 00:00:00 2021 GMT
+            Not After : Apr  1 00:00:00 2046 GMT
+        Subject: C=US, O=Certainly, CN=Certainly Root R1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                E0:AA:3F:25:8D:9F:44:5C:C1:3A:E8:2E:AE:77:4C:84:3E:67:0C:F4
+SHA1 Fingerprint=A0:50:EE:0F:28:71:F4:27:B2:12:6D:6F:50:96:25:BA:CC:86:42:AF
+SHA256 Fingerprint=77:B8:2C:D8:64:4C:43:05:F7:AC:C5:CB:15:6B:45:67:50:04:03:3D:51:C6:0C:62:02:A8:E0:C3:34:67:D3:A0
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAw
+PTELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2Vy
+dGFpbmx5IFJvb3QgUjEwHhcNMjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0
+YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANA2
+1B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O5MQT
+vqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbed
+aFySpvXl8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b0
+1C7jcvk2xusVtyWMOvwlDbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5
+r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGIXsXwClTNSaa/ApzSRKft43jvRl5tcdF5
+cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkNKPl6I7ENPT2a/Z2B7yyQ
+wHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQAjeZjOVJ
+6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA
+2CnbrlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyH
+Wyf5QBGenDPBt+U1VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMR
+eiFPCyEQtkA6qyI6BJyLm4SGcprSp6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB
+/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTgqj8ljZ9EXME66C6u
+d0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAszHQNTVfSVcOQr
+PbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi
+1wrykXprOQ4vMMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrd
+rRT90+7iIgXr0PK3aBLXWopBGsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9di
+taY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+gjwN/KUD+nsa2UUeYNrEjvn8K8l7
+lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgHJBu6haEaBQmAupVj
+yTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7fpYn
+Kx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLy
+yCwzk5Iwx06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5n
+wXARPbv0+Em34yaXOp/SX3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6
+OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+### certSIGN
+
+=== /C=RO/O=certSIGN/OU=certSIGN ROOT CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 35210227249154 (0x200605167002)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jul  4 17:20:04 2006 GMT
+            Not After : Jul  4 17:20:04 2031 GMT
+        Subject: C=RO, O=certSIGN, OU=certSIGN ROOT CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                E0:8C:9B:DB:25:49:B3:F1:7C:86:D6:B2:42:87:0B:D0:6B:A0:D9:E4
+SHA1 Fingerprint=FA:B7:EE:36:97:26:62:FB:2D:B0:2A:F6:BF:03:FD:E8:7C:4B:2F:9B
+SHA256 Fingerprint=EA:A9:62:C4:FA:4A:6B:AF:EB:E4:15:19:6D:35:1C:CD:88:8D:4F:53:F3:FA:8A:E6:D7:C4:66:A9:4E:60:42:BB
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+### CERTSIGN SA
+
+=== /C=RO/O=CERTSIGN SA/OU=certSIGN ROOT CA G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            11:00:34:b6:4e:c6:36:2d:36
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb  6 09:27:35 2017 GMT
+            Not After : Feb  6 09:27:35 2042 GMT
+        Subject: C=RO, O=CERTSIGN SA, OU=certSIGN ROOT CA G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                82:21:2D:66:C6:D7:A0:E0:15:EB:CE:4C:09:77:C4:60:9E:54:6E:03
+SHA1 Fingerprint=26:F9:93:B4:ED:3D:28:27:B0:B9:4B:A7:E9:15:1D:A3:8D:92:E5:32
+SHA256 Fingerprint=65:7C:FE:2F:A7:3F:AA:38:46:25:71:F3:32:A2:36:3A:46:FC:E7:02:09:51:71:07:02:CD:FB:B6:EE:DA:33:05
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV
+BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g
+Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ
+BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ
+R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF
+dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw
+vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ
+uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp
+n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs
+cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW
+xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P
+rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF
+DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx
+DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy
+LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C
+eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ
+d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq
+kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl
+qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0
+OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c
+NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk
+ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO
+pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj
+03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk
+PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE
+1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX
+QRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
+
+### China Financial Certification Authority
+
+=== /C=CN/O=China Financial Certification Authority/CN=CFCA EV ROOT
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 407555286 (0x184accd6)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Aug  8 03:07:01 2012 GMT
+            Not After : Dec 31 03:07:01 2029 GMT
+        Subject: C=CN, O=China Financial Certification Authority, CN=CFCA EV ROOT
+        X509v3 extensions:
+            X509v3 Authority Key Identifier: 
+                keyid:E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F
+
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F
+SHA1 Fingerprint=E2:B8:29:4B:55:84:AB:6B:58:C2:90:46:6C:AC:3F:B8:39:8F:84:83
+SHA256 Fingerprint=5C:C3:D7:8E:4E:1D:5E:45:54:7A:04:E6:87:3E:64:F9:0C:F9:53:6D:1C:CC:2E:F8:00:F3:55:C4:C5:FD:70:FD
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+### Chunghwa Telecom Co., Ltd.
+
+=== /C=TW/O=Chunghwa Telecom Co., Ltd./CN=HiPKI Root CA - G1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            2d:dd:ac:ce:62:97:94:a1:43:e8:b0:cd:76:6a:5e:60
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 22 09:46:04 2019 GMT
+            Not After : Dec 31 15:59:59 2037 GMT
+        Subject: C=TW, O=Chunghwa Telecom Co., Ltd., CN=HiPKI Root CA - G1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                F2:77:17:FA:5E:A8:FE:F6:3D:71:D5:68:BA:C9:46:0C:38:D8:AF:B0
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=6A:92:E4:A8:EE:1B:EC:96:45:37:E3:29:57:49:CD:96:E3:E5:D2:60
+SHA256 Fingerprint=F0:15:CE:3C:C2:39:BF:EF:06:4B:E9:F1:D2:C4:17:E1:A0:26:4A:0A:94:BE:1F:0C:8D:12:18:64:EB:69:49:CC
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBP
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xGzAZBgNVBAMMEkhpUEtJIFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRa
+Fw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3
+YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kgUm9vdCBDQSAtIEcx
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0o9Qw
+qNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twv
+Vcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6
+lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnz
+Qs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRtU6M9/Aes1MU3guvklQgZ
+KILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfdhSi8MEyr48KxRURHH+CK
+FgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj1jOXTyFj
+HluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDr
+y+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ
+/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgM
+a/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6
+fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQDAgGGMA0GCSqG
+SIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqc
+SE5XCV0vrPSltJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6Fza
+ZsT0pPBWGTMpWmWSBUdGSquEwx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9Tc
+XzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07QJNBAsNB1CI69aO4I1258EHBGG3zg
+iLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv5wiZqAxeJoBF1Pho
+L5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+GpzjLrF
+Ne85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wr
+kkVbbiVghUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+
+vhV4nYWBSipX3tUZQ9rbyltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQU
+YDksswBVLuT1sw5XxJFBAJw/6KXf6vb/yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+=== /C=TW/O=Chunghwa Telecom Co., Ltd./OU=ePKI Root Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Dec 20 02:31:27 2004 GMT
+            Not After : Dec 20 02:31:27 2034 GMT
+        Subject: C=TW, O=Chunghwa Telecom Co., Ltd., OU=ePKI Root Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                1E:0C:F7:B6:67:F2:E1:92:26:09:45:C0:55:39:2E:77:3F:42:4A:A2
+            X509v3 Basic Constraints: 
+                CA:TRUE
+            setCext-hashedRoot: 
+                0/0-...0...+......0...g*.....E...
+V|.[x....S.....
+SHA1 Fingerprint=67:65:0D:F1:7E:8E:7E:5B:82:40:A4:F4:56:4B:CF:E2:3D:69:C6:F0
+SHA256 Fingerprint=C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+### Comodo CA Limited
+
+=== /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jan  1 00:00:00 2004 GMT
+            Not After : Dec 31 23:59:59 2028 GMT
+        Subject: C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Services
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.comodoca.com/AAACertificateServices.crl
+
+                Full Name:
+                  URI:http://crl.comodo.net/AAACertificateServices.crl
+
+SHA1 Fingerprint=D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
+SHA256 Fingerprint=D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+### COMODO CA Limited
+
+=== /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            4e:81:2d:8a:82:65:e0:0b:02:ee:3e:35:02:46:e5:3d
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Dec  1 00:00:00 2006 GMT
+            Not After : Dec 31 23:59:59 2029 GMT
+        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                0B:58:E5:8B:C6:4C:15:37:A4:40:A9:30:A9:21:BE:47:36:5A:56:FF
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.comodoca.com/COMODOCertificationAuthority.crl
+
+SHA1 Fingerprint=66:31:BF:9E:F7:4F:9E:B6:C9:D5:A6:0C:BA:6A:BE:D1:F7:BD:EF:7B
+SHA256 Fingerprint=0C:2C:D6:3D:F7:80:6F:A3:99:ED:E8:09:11:6B:57:5B:F8:79:89:F0:65:18:F9:80:8C:86:05:03:17:8B:AF:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+=== /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            1f:47:af:aa:62:00:70:50:54:4c:01:9e:9b:63:99:2a
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Mar  6 00:00:00 2008 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO ECC Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                75:71:A7:19:48:19:BC:9D:9D:EA:41:47:DF:94:C4:48:77:99:D3:79
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=9F:74:4E:9F:2B:4D:BA:EC:0F:31:2C:50:B6:56:3B:8E:2D:93:C3:11
+SHA256 Fingerprint=17:93:92:7A:06:14:54:97:89:AD:CE:2F:8F:34:F7:F0:B6:6D:0F:3A:E3:A3:B8:4D:21:EC:15:DB:BA:4F:AD:C7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+=== /C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jan 19 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4
+SHA256 Fingerprint=52:F0:E1:C4:E5:8E:C6:29:29:1B:60:31:7F:07:46:71:B8:5D:7E:A8:0D:5B:07:27:34:63:53:4B:32:B4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+### D-Trust GmbH
+
+=== /C=DE/O=D-Trust GmbH/CN=D-TRUST BR Root CA 1 2020
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            7c:c9:8f:2b:84:d7:df:ea:0f:c9:65:9a:d3:4b:4d:96
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb 11 09:45:00 2020 GMT
+            Not After : Feb 11 09:44:59 2035 GMT
+        Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST BR Root CA 1 2020
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                73:91:10:AB:FF:55:B3:5A:7C:09:25:D5:B2:BA:08:A0:6B:AB:1F:6D
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.d-trust.net/crl/d-trust_br_root_ca_1_2020.crl
+
+                Full Name:
+                  URI:ldap://directory.d-trust.net/CN=D-TRUST%20BR%20Root%20CA%201%202020,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+SHA1 Fingerprint=1F:5B:98:F0:E3:B5:F7:74:3C:ED:E6:B0:36:7D:32:CD:F4:09:41:67
+SHA256 Fingerprint=E5:9A:AA:81:60:09:C2:2B:FF:5B:25:BA:D3:7D:F3:06:F0:49:79:7C:1F:81:D8:5A:B0:89:E6:57:BD:8F:00:44
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEJSIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5
+NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7dPYS
+zuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0
+QVK5buXuQqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/
+VbNafAkl1bK6CKBrqx9tMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2JyX3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFW
+wKrY7RjEsK70PvomAjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHV
+dWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+=== /C=DE/O=D-Trust GmbH/CN=D-TRUST EV Root CA 1 2020
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5f:02:41:d7:7a:87:7c:4c:03:a3:ac:96:8d:fb:ff:d0
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb 11 10:00:00 2020 GMT
+            Not After : Feb 11 09:59:59 2035 GMT
+        Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST EV Root CA 1 2020
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                7F:10:01:16:37:3A:A4:28:E4:50:F8:A4:F7:EC:6B:32:B6:FE:E9:8B
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.d-trust.net/crl/d-trust_ev_root_ca_1_2020.crl
+
+                Full Name:
+                  URI:ldap://directory.d-trust.net/CN=D-TRUST%20EV%20Root%20CA%201%202020,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+SHA1 Fingerprint=61:DB:8C:21:59:69:03:90:D8:7C:9C:12:86:54:CF:9D:3D:F4:DD:07
+SHA256 Fingerprint=08:17:0D:1A:A3:64:53:90:1A:2F:95:92:45:E3:47:DB:0C:8D:37:AB:AA:BC:56:B8:1A:A1:00:DC:95:89:70:DB
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQsw
+CQYDVQQGEwJERTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRS
+VVNUIEVWIFJvb3QgQ0EgMSAyMDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5
+NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNVBAoTDEQtVHJ1c3QgR21iSDEiMCAG
+A1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8ZRCC
+/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rD
+wpdhQntJraOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3
+OqQo5FD4pPfsazK2/umLMA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6g
+PKA6hjhodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X2V2X3Jvb3Rf
+Y2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVjdG9yeS5kLXRydXN0Lm5l
+dC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxPPUQtVHJ1
+c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjO
+PQQDAwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CA
+y/m0sRtW9XLS/BnRAjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJb
+gfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+=== /C=DE/O=D-Trust GmbH/CN=D-TRUST Root Class 3 CA 2 2009
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 623603 (0x983f3)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Nov  5 08:35:58 2009 GMT
+            Not After : Nov  5 08:35:58 2029 GMT
+        Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 2009
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                FD:DA:14:C4:9F:30:DE:21:BD:1E:42:39:FC:AB:63:23:49:E0:F1:84
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+                Full Name:
+                  URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_2009.crl
+
+SHA1 Fingerprint=58:E8:AB:B0:36:15:33:FB:80:F7:9B:1B:6D:29:D3:FF:8D:5F:00:F0
+SHA256 Fingerprint=49:E7:A4:42:AC:F0:EA:62:87:05:00:54:B5:25:64:B6:50:E4:F4:9E:42:E3:48:D6:AA:38:E0:39:E9:57:B1:C1
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+=== /C=DE/O=D-Trust GmbH/CN=D-TRUST Root Class 3 CA 2 EV 2009
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 623604 (0x983f4)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Nov  5 08:50:46 2009 GMT
+            Not After : Nov  5 08:50:46 2029 GMT
+        Subject: C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 EV 2009
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                D3:94:8A:4C:62:13:2A:19:2E:CC:AF:72:8A:7D:36:D7:9A:1C:DC:67
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%20EV%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+                Full Name:
+                  URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_ev_2009.crl
+
+SHA1 Fingerprint=96:C9:1B:0B:95:B4:10:98:42:FA:D0:D8:22:79:FE:60:FA:B9:16:83
+SHA256 Fingerprint=EE:C5:49:6B:98:8C:E9:86:25:B9:34:09:2E:EC:29:08:BE:D0:B0:F3:16:C2:D4:73:0C:84:EA:F1:F3:D3:48:81
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+### Dhimyotis
+
+=== /C=FR/O=Dhimyotis/CN=Certigna
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            fe:dc:e3:01:0f:c9:48:ff
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jun 29 15:13:05 2007 GMT
+            Not After : Jun 29 15:13:05 2027 GMT
+        Subject: C=FR, O=Dhimyotis, CN=Certigna
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11
+            X509v3 Authority Key Identifier: 
+                keyid:1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11
+                DirName:/C=FR/O=Dhimyotis/CN=Certigna
+                serial:FE:DC:E3:01:0F:C9:48:FF
+
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            Netscape Cert Type: 
+                SSL CA, S/MIME CA, Object Signing CA
+SHA1 Fingerprint=B1:2E:13:63:45:86:A4:6F:1A:B2:60:68:37:58:2D:C4:AC:FD:94:97
+SHA256 Fingerprint=E3:B6:A2:DB:2E:D7:CE:48:84:2F:7A:C5:32:41:C7:B7:1D:54:14:4B:FB:40:C1:1F:3F:1D:0B:42:F5:EE:A1:2D
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+=== /C=FR/O=Dhimyotis/OU=0002 48146308100036/CN=Certigna Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            ca:e9:1b:89:f1:55:03:0d:a3:e6:41:6d:c4:e3:a6:e1
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct  1 08:32:27 2013 GMT
+            Not After : Oct  1 08:32:27 2033 GMT
+        Subject: C=FR, O=Dhimyotis, OU=0002 48146308100036, CN=Certigna Root CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                18:87:56:E0:6E:77:EE:24:35:3C:4E:73:9A:1F:D6:E1:E2:79:7E:2B
+            X509v3 Authority Key Identifier: 
+                keyid:18:87:56:E0:6E:77:EE:24:35:3C:4E:73:9A:1F:D6:E1:E2:79:7E:2B
+
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: https://wwww.certigna.fr/autorites/
+
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.certigna.fr/certignarootca.crl
+
+                Full Name:
+                  URI:http://crl.dhimyotis.com/certignarootca.crl
+
+SHA1 Fingerprint=2D:0D:52:14:FF:9E:AD:99:24:01:74:20:47:6E:6C:85:27:27:F5:43
+SHA256 Fingerprint=D4:8D:3D:23:EE:DB:50:A4:59:E5:51:97:60:1C:27:77:4B:9D:7B:18:C9:4D:5A:05:95:11:A1:02:50:B9:31:68
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw
+WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw
+MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x
+MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD
+VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX
+BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO
+ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M
+CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu
+I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm
+TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh
+C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf
+ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz
+IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT
+Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k
+JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5
+hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB
+GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov
+L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo
+dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr
+aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq
+hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L
+6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG
+HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6
+0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB
+lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi
+o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1
+gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v
+faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63
+Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh
+jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
+3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
+
+### DigiCert Inc
+
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Assured ID Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 10 00:00:00 2006 GMT
+            Not After : Nov 10 00:00:00 2031 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F
+            X509v3 Authority Key Identifier: 
+                keyid:45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F
+
+SHA1 Fingerprint=05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43
+SHA256 Fingerprint=3E:90:99:B5:01:5E:8F:48:6C:00:BC:EA:9D:11:1E:E7:21:FA:BA:35:5A:89:BC:F1:DF:69:56:1E:3D:C6:32:5C
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Assured ID Root G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0b:93:1c:3a:d6:39:67:ea:67:23:bf:c3:af:9a:f4:4b
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Aug  1 12:00:00 2013 GMT
+            Not After : Jan 15 12:00:00 2038 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                CE:C3:4A:B9:99:55:F2:B8:DB:60:BF:A9:7E:BD:56:B5:97:36:A7:D6
+SHA1 Fingerprint=A1:4B:48:D9:43:EE:0A:0E:40:90:4F:3C:E0:A4:C0:91:93:51:5D:3F
+SHA256 Fingerprint=7D:05:EB:B6:82:33:9F:8C:94:51:EE:09:4E:EB:FE:FA:79:53:A1:14:ED:B2:F4:49:49:45:2F:AB:7D:2F:C1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Assured ID Root G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0b:a1:5a:fa:1d:df:a0:b5:49:44:af:cd:24:a0:6c:ec
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Aug  1 12:00:00 2013 GMT
+            Not After : Jan 15 12:00:00 2038 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                CB:D0:BD:A9:E1:98:05:51:A1:4D:37:A2:83:79:CE:8D:1D:2A:E4:84
+SHA1 Fingerprint=F5:17:A2:4F:9A:48:C6:C9:F8:A2:00:26:9F:DC:0F:48:2C:AB:30:89
+SHA256 Fingerprint=7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 10 00:00:00 2006 GMT
+            Not After : Nov 10 00:00:00 2031 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+            X509v3 Authority Key Identifier: 
+                keyid:03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+
+SHA1 Fingerprint=A8:98:5D:3A:65:E5:E5:C4:B2:D7:D6:6D:40:C6:DD:2F:B1:9C:54:36
+SHA256 Fingerprint=43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            03:3a:f1:e6:a7:11:a9:a0:bb:28:64:b1:1d:09:fa:e5
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Aug  1 12:00:00 2013 GMT
+            Not After : Jan 15 12:00:00 2038 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                4E:22:54:20:18:95:E6:E3:6E:E6:0F:FA:FA:B9:12:ED:06:17:8F:39
+SHA1 Fingerprint=DF:3C:24:F9:BF:D6:66:76:1B:26:80:73:FE:06:D1:CC:8D:4F:82:A4
+SHA256 Fingerprint=CB:3C:CB:B7:60:31:E5:E0:13:8F:8D:D3:9A:23:F9:DE:47:FF:C3:5E:43:C1:14:4C:EA:27:D4:6A:5A:B1:CB:5F
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            05:55:56:bc:f2:5e:a4:35:35:c3:a4:0f:d5:ab:45:72
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Aug  1 12:00:00 2013 GMT
+            Not After : Jan 15 12:00:00 2038 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                B3:DB:48:A4:F9:A1:C5:D8:AE:36:41:CC:11:63:69:62:29:BC:4B:C6
+SHA1 Fingerprint=7E:04:DE:89:6A:3E:66:6D:00:E6:87:D3:3F:FA:D9:3B:E8:3D:34:9E
+SHA256 Fingerprint=31:AD:66:48:F8:10:41:38:C7:38:F3:9E:A4:32:01:33:39:3E:3A:18:CC:02:29:6E:F9:7C:2A:C9:EF:67:31:D0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert High Assurance EV Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:ac:5c:26:6a:0b:40:9b:8f:0b:79:f2:ae:46:25:77
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 10 00:00:00 2006 GMT
+            Not After : Nov 10 00:00:00 2031 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV Root CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
+            X509v3 Authority Key Identifier: 
+                keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
+
+SHA1 Fingerprint=5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25
+SHA256 Fingerprint=74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Trusted Root G4
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            05:9b:1b:57:9e:8e:21:32:e2:39:07:bd:a7:77:75:5c
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Aug  1 12:00:00 2013 GMT
+            Not After : Jan 15 12:00:00 2038 GMT
+        Subject: C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                EC:D7:E3:82:D2:71:5D:64:4C:DF:2E:67:3F:E7:BA:98:AE:1C:0F:4F
+SHA1 Fingerprint=DD:FB:16:CD:49:31:C9:73:A2:03:7D:3F:C8:3A:4D:7D:77:5D:05:E4
+SHA256 Fingerprint=55:2F:7B:DC:F1:A7:AF:9E:6C:E6:72:01:7F:4F:12:AB:F7:72:40:C7:8E:76:1A:C2:03:D1:D9:D2:0A:C8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+### DigiCert, Inc.
+
+=== /C=US/O=DigiCert, Inc./CN=DigiCert TLS ECC P384 Root G5
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            09:e0:93:65:ac:f7:d9:c8:b9:3e:1c:0b:04:2a:2e:f3
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jan 15 00:00:00 2021 GMT
+            Not After : Jan 14 23:59:59 2046 GMT
+        Subject: C=US, O=DigiCert, Inc., CN=DigiCert TLS ECC P384 Root G5
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                C1:51:45:50:59:AB:3E:E7:2C:5A:FA:20:22:12:07:80:88:7C:11:6A
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=17:F3:DE:5E:9F:0F:19:E9:8E:F6:1F:32:26:6E:20:C4:07:AE:30:EE
+SHA256 Fingerprint=01:8E:13:F0:77:25:32:CF:80:9B:D1:B1:72:81:86:72:83:FC:48:C6:E1:3B:E9:C6:98:12:85:4A:49:0C:1B:05
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURp
+Z2lDZXJ0IFRMUyBFQ0MgUDM4NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2
+MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
+bmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQgUm9vdCBHNTB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1TzvdlHJS
+7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp
+0zVozptjn4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICIS
+B4CIfBFqMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49
+BAMDA2gAMGUCMQCJao1H5+z8blUD2WdsJk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQ
+LgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIxAJSdYsiJvRmEFOml+wG4
+DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+=== /C=US/O=DigiCert, Inc./CN=DigiCert TLS RSA4096 Root G5
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            08:f9:b4:78:a8:fa:7e:da:6a:33:37:89:de:7c:cf:8a
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jan 15 00:00:00 2021 GMT
+            Not After : Jan 14 23:59:59 2046 GMT
+        Subject: C=US, O=DigiCert, Inc., CN=DigiCert TLS RSA4096 Root G5
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                51:33:1C:ED:36:40:AF:17:D3:25:CD:69:68:F2:AF:4E:23:3E:B3:41
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=A7:88:49:DC:5D:7C:75:8C:8C:DE:39:98:56:B3:AA:D0:B2:A5:71:35
+SHA256 Fingerprint=37:1A:00:DC:05:33:B3:72:1A:7E:EB:40:E8:41:9E:70:79:9D:2B:0A:0F:2C:1D:80:69:31:65:F7:CE:C4:AD:75
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBN
+MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMT
+HERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcN
+NDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
+IEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2IFJvb3QgRzUwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS87IE+
+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG0
+2C+JFvuUAT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgp
+wgscONyfMXdcvyej/Cestyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZM
+pG2T6T867jp8nVid9E6P/DsjyG244gXazOvswzH016cpVIDPRFtMbzCe88zdH5RD
+nU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnVDdXifBBiqmvwPXbzP6Po
+sMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9qTXeXAaDx
+Zre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cd
+Lvvyz6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvX
+KyY//SovcfXWJL5/MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNe
+XoVPzthwiHvOAbWWl9fNff2C+MIkwcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPL
+tgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4EFgQUUTMc7TZArxfTJc1paPKv
+TiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN
+AQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7H
+PNtQOa27PShNlnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLF
+O4uJ+DQtpBflF+aZfTCIITfNMBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQ
+REtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/u4cnYiWB39yhL/btp/96j1EuMPik
+AdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9GOUrYU9DzLjtxpdRv
+/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh47a+
+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilw
+MUc/dNAUFvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WF
+qUITVuwhd4GTWgzqltlJyqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCK
+ovfepEWFJqgejF0pW8hL2JpqA15w8oVPbEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+### Disig a.s.
+
+=== /C=SK/L=Bratislava/O=Disig a.s./CN=CA Disig Root R2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            92:b8:88:db:b0:8a:c1:63
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jul 19 09:15:30 2012 GMT
+            Not After : Jul 19 09:15:30 2042 GMT
+        Subject: C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                B5:99:F8:AF:B0:94:F5:E3:20:D6:0A:AD:CE:4E:56:A4:2E:6E:42:ED
+SHA1 Fingerprint=B5:61:EB:EA:A4:DE:E4:25:4B:69:1A:98:A5:57:47:C2:34:C7:D9:71
+SHA256 Fingerprint=E2:3D:4A:03:6D:7B:70:E9:F5:95:B1:42:20:79:D2:B9:1E:DF:BB:1F:B6:51:A0:63:3E:AA:8A:9D:C5:F8:07:03
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+### e-commerce monitoring GmbH
+
+=== /C=AT/O=e-commerce monitoring GmbH/CN=GLOBALTRUST 2020
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5a:4b:bd:5a:fb:4f:8a:5b:fa:65:e5
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 10 00:00:00 2020 GMT
+            Not After : Jun 10 00:00:00 2040 GMT
+        Subject: C=AT, O=e-commerce monitoring GmbH, CN=GLOBALTRUST 2020
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                DC:2E:1F:D1:61:37:79:E4:AB:D5:D5:B3:12:71:68:3D:6A:68:9C:22
+            X509v3 Authority Key Identifier: 
+                keyid:DC:2E:1F:D1:61:37:79:E4:AB:D5:D5:B3:12:71:68:3D:6A:68:9C:22
+
+SHA1 Fingerprint=D0:67:C1:13:51:01:0C:AA:D0:C7:6A:65:37:31:16:26:4F:53:71:A2
+SHA256 Fingerprint=9A:29:6A:51:82:D1:D4:51:A2:E3:7F:43:9B:74:DA:AF:A2:67:52:33:29:F9:0F:9A:0D:20:07:C3:34:E2:3C:9A
+-----BEGIN CERTIFICATE-----
+MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG
+A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw
+FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx
+MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u
+aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b
+RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z
+YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3
+QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw
+yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+
+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ
+SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH
+r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0
+4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me
+dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw
+q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2
+nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu
+H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
+VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC
+XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd
+6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf
++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi
+kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7
+wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB
+TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C
+MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn
+4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I
+aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy
+qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
+-----END CERTIFICATE-----
+
+### E-Tugra EBG A.S.
+
+=== /C=TR/L=Ankara/O=E-Tugra EBG A.S./OU=E-Tugra Trust Center/CN=E-Tugra Global Root CA ECC v3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            26:46:19:77:31:e1:4f:6f:28:36:de:39:51:86:e6:d4:97:88:22:c1
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Mar 18 09:46:58 2020 GMT
+            Not After : Mar 12 09:46:58 2045 GMT
+        Subject: C=TR, L=Ankara, O=E-Tugra EBG A.S., OU=E-Tugra Trust Center, CN=E-Tugra Global Root CA ECC v3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:FF:82:31:72:3E:F9:C4:66:6C:AD:38:9E:D1:B0:51:88:A5:90:CC:F5
+
+            X509v3 Subject Key Identifier: 
+                FF:82:31:72:3E:F9:C4:66:6C:AD:38:9E:D1:B0:51:88:A5:90:CC:F5
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=8A:2F:AF:57:53:B1:B0:E6:A1:04:EC:5B:6A:69:71:6D:F6:1C:E2:84
+SHA256 Fingerprint=87:3F:46:85:FA:7F:56:36:25:25:2E:6D:36:BC:D7:F1:6F:C2:49:51:F2:64:E4:7E:1B:95:4F:49:08:CD:CA:13
+-----BEGIN CERTIFICATE-----
+MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw
+gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn
+cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD
+VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2
+NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r
+YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh
+IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF
+Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ
+KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK
+fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB
+Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C
+MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp
+ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6
+7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx
+vmjkI6TZraE3
+-----END CERTIFICATE-----
+=== /C=TR/L=Ankara/O=E-Tugra EBG A.S./OU=E-Tugra Trust Center/CN=E-Tugra Global Root CA RSA v3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0d:4d:c5:cd:16:22:95:96:08:7e:b8:0b:7f:15:06:34:fb:79:10:34
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Mar 18 09:07:17 2020 GMT
+            Not After : Mar 12 09:07:17 2045 GMT
+        Subject: C=TR, L=Ankara, O=E-Tugra EBG A.S., OU=E-Tugra Trust Center, CN=E-Tugra Global Root CA RSA v3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:B2:B4:AE:E6:2D:F7:26:D5:AA:75:2D:76:4B:C0:1B:53:21:D0:48:EF
+
+            X509v3 Subject Key Identifier: 
+                B2:B4:AE:E6:2D:F7:26:D5:AA:75:2D:76:4B:C0:1B:53:21:D0:48:EF
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=E9:A8:5D:22:14:52:1C:5B:AA:0A:B4:BE:24:6A:23:8A:C9:BA:E2:A9
+SHA256 Fingerprint=EF:66:B0:B1:0A:3C:DB:9F:2E:36:48:C7:6B:D2:AF:18:EA:D2:BF:E6:F1:17:65:5E:28:C4:06:0D:A1:A3:F4:C2
+-----BEGIN CERTIFICATE-----
+MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQEL
+BQAwgYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUt
+VHVncmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYw
+JAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIFJTQSB2MzAeFw0yMDAzMTgw
+OTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMG
+QW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1
+Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBD
+QSBSU0EgdjMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J7
+7gnJY9LTQ91ew6aEOErxjYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscx
+uj7X/iWpKo429NEvx7epXTPcMHD4QGxLsqYxYdE0PD0xesevxKenhOGXpOhL9hd8
+7jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF/YP9f4RtNGx/ardLAQO/
+rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8qQedmCeFL
+l+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bG
+wzrwbMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4
+znKS4iicvObpCdg604nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBO
+M/J+JjKsBY04pOZ2PJ8QaQ5tndLBeSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK
+5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiMbIedBi3x7+PmBvrFZhNb/FAH
+nnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbgh3cXTJ2w2Amo
+DVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSy
+tK7mLfcm1ap1LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEL
+BQADggIBAImocn+M684uGMQQgC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ
+6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN438o2Fi+CiJ+8EUdPdk3ILY7r3y18
+Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/qln0F7psTpURs+APQ
+3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3sSdPk
+vmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn9
+9t2HVhjYsCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQ
+mhty3QUBjYZgv6Rn7rWlDdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YA
+VSgU7NbHEqIbZULpkejLPoeJVF3Zr52XnGnnCv8PWniLYypMfUeUP95L6VPQMPHF
+9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFHIK+WEj5jlB0E5y67hscM
+moi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiXYY60MGo8
+bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ
+-----END CERTIFICATE-----
+
+### eMudhra Inc
+
+=== /C=US/OU=emSign PKI/O=eMudhra Inc/CN=emSign ECC Root CA - C3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            7b:71:b6:82:56:b8:12:7c:9c:a8
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb 18 18:30:00 2018 GMT
+            Not After : Feb 18 18:30:00 2043 GMT
+        Subject: C=US, OU=emSign PKI, O=eMudhra Inc, CN=emSign ECC Root CA - C3
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                FB:5A:48:D0:80:20:40:F2:A8:E9:00:07:69:19:77:A7:E6:C3:F4:CF
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=B6:AF:43:C2:9B:81:53:7D:F6:EF:6B:C3:1F:1F:60:15:0C:EE:48:66
+SHA256 Fingerprint=BC:4D:80:9B:15:18:9D:78:DB:3E:1D:8C:F4:F9:72:6A:79:5D:A1:64:3C:A5:F1:35:8E:1D:DB:0E:DC:0D:7E:B3
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG
+EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx
+IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND
+IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci
+MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti
+sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O
+BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c
+3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J
+0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
+=== /C=US/OU=emSign PKI/O=eMudhra Inc/CN=emSign Root CA - C1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            ae:cf:00:ba:c4:cf:32:f8:43:b2
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 18 18:30:00 2018 GMT
+            Not After : Feb 18 18:30:00 2043 GMT
+        Subject: C=US, OU=emSign PKI, O=eMudhra Inc, CN=emSign Root CA - C1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                FE:A1:E0:70:1E:2A:03:39:52:5A:42:BE:5C:91:85:7A:18:AA:4D:B5
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=E7:2E:F1:DF:FC:B2:09:28:CF:5D:D4:D5:67:37:B1:51:CB:86:4F:01
+SHA256 Fingerprint=12:56:09:AA:30:1D:A0:A2:49:B9:7A:82:39:CB:6A:34:21:6F:44:DC:AC:9F:39:54:B1:42:92:F2:E8:C8:60:8F
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG
+A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg
+SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v
+dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ
+BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ
+HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH
+3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH
+GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c
+xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1
+aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq
+TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87
+/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4
+kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG
+YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT
++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo
+WXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
+
+### eMudhra Technologies Limited
+
+=== /C=IN/OU=emSign PKI/O=eMudhra Technologies Limited/CN=emSign ECC Root CA - G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            3c:f6:07:a9:68:70:0e:da:8b:84
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb 18 18:30:00 2018 GMT
+            Not After : Feb 18 18:30:00 2043 GMT
+        Subject: C=IN, OU=emSign PKI, O=eMudhra Technologies Limited, CN=emSign ECC Root CA - G3
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                7C:5D:02:84:13:D4:CC:8A:9B:81:CE:17:1C:2E:29:1E:9C:48:63:42
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=30:43:FA:4F:F2:57:DC:A0:C3:80:EE:2E:58:EA:78:B2:3F:E6:BB:C1
+SHA256 Fingerprint=86:A1:EC:BA:08:9C:4A:8D:3B:BE:27:34:C6:12:BA:34:1D:81:3E:04:3C:F9:E8:A8:62:CD:5C:57:A3:6B:BE:6B
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG
+EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo
+bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ
+TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s
+b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0
+WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS
+fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB
+zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq
+hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB
+CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD
++JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
+=== /C=IN/OU=emSign PKI/O=eMudhra Technologies Limited/CN=emSign Root CA - G1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            31:f5:e4:62:0c:6c:58:ed:d6:d8
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 18 18:30:00 2018 GMT
+            Not After : Feb 18 18:30:00 2043 GMT
+        Subject: C=IN, OU=emSign PKI, O=eMudhra Technologies Limited, CN=emSign Root CA - G1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                FB:EF:0D:86:9E:B0:E3:DD:A9:B9:F1:21:17:7F:3E:FC:F0:77:2B:1A
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=8A:C7:AD:8F:73:AC:4E:C1:B5:75:4D:A5:40:F4:FC:CF:7C:B5:8E:8C
+SHA256 Fingerprint=40:F6:AF:03:46:A9:9A:A1:CD:1D:55:5A:4E:9C:CE:62:C7:F9:63:46:03:EE:40:66:15:83:3D:C8:C8:D0:03:67
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD
+VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU
+ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH
+MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO
+MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv
+Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz
+f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO
+8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq
+d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM
+tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt
+Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB
+o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x
+PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM
+wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d
+GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH
+6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby
+RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
+
+### Entrust, Inc.
+
+=== /C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2009 Entrust, Inc. - for authorized use only/CN=Entrust Root Certification Authority - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1246989352 (0x4a538c28)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jul  7 17:25:54 2009 GMT
+            Not After : Dec  7 17:55:54 2030 GMT
+        Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2009 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G2
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                6A:72:26:7A:D0:1E:EF:7D:E7:3B:69:51:D4:6C:8D:9F:90:12:66:AB
+SHA1 Fingerprint=8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4
+SHA256 Fingerprint=43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+=== /C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2012 Entrust, Inc. - for authorized use only/CN=Entrust Root Certification Authority - EC1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            a6:8b:79:29:00:00:00:00:50:d0:91:f9
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Dec 18 15:25:36 2012 GMT
+            Not After : Dec 18 15:55:36 2037 GMT
+        Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                B7:63:E7:1A:DD:8D:E9:08:A6:55:83:A4:E0:6A:50:41:65:11:42:49
+SHA1 Fingerprint=20:D8:06:40:DF:9B:25:F5:12:25:3A:11:EA:F7:59:8A:EB:14:B5:47
+SHA256 Fingerprint=02:ED:0E:B2:8C:14:DA:45:16:5C:56:67:91:70:0D:64:51:D7:FB:56:F0:B2:AB:1D:3B:8E:B0:70:E5:6E:DF:F5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+=== /C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2015 Entrust, Inc. - for authorized use only/CN=Entrust Root Certification Authority - G4
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            d9:b5:43:7f:af:a9:39:0f:00:00:00:00:55:65:ad:58
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: May 27 11:11:16 2015 GMT
+            Not After : Dec 27 11:41:16 2037 GMT
+        Subject: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2015 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G4
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                9F:38:C4:56:23:C3:39:E8:A0:71:6C:E8:54:4C:E4:E8:3A:B1:BF:67
+SHA1 Fingerprint=14:88:4E:86:26:37:B0:26:AF:59:62:5C:40:77:EC:35:29:BA:96:01
+SHA256 Fingerprint=DB:35:17:D1:F6:73:2A:2D:5A:B9:7C:53:3E:C7:07:79:EE:32:70:A6:2F:B4:AC:42:38:37:24:60:E6:F0:1E:88
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw
+gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL
+Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg
+MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw
+BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0
+MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1
+c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ
+bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ
+2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E
+T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j
+5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM
+C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T
+DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX
+wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A
+2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm
+nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
+dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl
+N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj
+c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS
+5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS
+Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr
+hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/
+B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI
+AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw
+H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+
+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk
+2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol
+IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk
+5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY
+n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw==
+-----END CERTIFICATE-----
+=== /C=US/O=Entrust, Inc./OU=www.entrust.net/CPS is incorporated by reference/OU=(c) 2006 Entrust, Inc./CN=Entrust Root Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1164660820 (0x456b5054)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 27 20:23:42 2006 GMT
+            Not After : Nov 27 20:53:42 2026 GMT
+        Subject: C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification Authority
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Private Key Usage Period: 
+                Not Before: Nov 27 20:23:42 2006 GMT, Not After: Nov 27 20:53:42 2026 GMT
+            X509v3 Authority Key Identifier: 
+                keyid:68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D
+
+            X509v3 Subject Key Identifier: 
+                68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D
+            1.2.840.113533.7.65.0: 
+                0...V7.1:4.0....
+SHA1 Fingerprint=B3:1E:B1:B7:40:E3:6C:84:02:DA:DC:37:D4:4D:F5:D4:67:49:52:F9
+SHA256 Fingerprint=73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+### Entrust.net
+
+=== /O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 946069240 (0x3863def8)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Dec 24 17:50:51 1999 GMT
+            Not After : Jul 24 14:15:12 2029 GMT
+        Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
+SHA1 Fingerprint=50:30:06:09:1D:97:D4:F5:AE:39:F7:CB:E7:92:7D:7D:65:2D:34:31
+SHA256 Fingerprint=6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+### FNMT-RCM
+
+=== /C=ES/O=FNMT-RCM/OU=AC RAIZ FNMT-RCM
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5d:93:8d:30:67:36:c8:06:1d:1a:c7:54:84:69:07
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct 29 15:59:56 2008 GMT
+            Not After : Jan  1 00:00:00 2030 GMT
+        Subject: C=ES, O=FNMT-RCM, OU=AC RAIZ FNMT-RCM
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                F7:7D:C5:FD:C4:E8:9A:1B:77:64:A7:F5:1D:A0:CC:BF:87:60:9A:6D
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: http://www.cert.fnmt.es/dpcs/
+
+SHA1 Fingerprint=EC:50:35:07:B2:15:C4:95:62:19:E2:A8:9A:5B:42:99:2C:4C:2C:20
+SHA256 Fingerprint=EB:C5:57:0C:29:01:8C:4D:67:B1:AA:12:7B:AF:12:F7:03:B4:61:1E:BC:17:B7:DA:B5:57:38:94:17:9B:93:FA
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+=== /C=ES/O=FNMT-RCM/OU=Ceres/2.5.4.97=VATES-Q2826004J/CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            62:f6:32:6c:e5:c4:e3:68:5c:1b:62:dd:9c:2e:9d:95
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Dec 20 09:37:33 2018 GMT
+            Not After : Dec 20 09:37:33 2043 GMT
+        Subject: C=ES, O=FNMT-RCM, OU=Ceres/2.5.4.97=VATES-Q2826004J, CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                01:B9:2F:EF:BF:11:86:60:F2:4F:D0:41:6E:AB:73:1F:E7:D2:6E:49
+SHA1 Fingerprint=62:FF:D9:9E:C0:65:0D:03:CE:75:93:D2:ED:3F:2D:32:C9:E3:E5:4A
+SHA256 Fingerprint=55:41:53:B1:3D:2C:F9:DD:B7:53:BF:BE:1A:4E:0A:E0:8D:0A:A4:18:70:58:FE:60:A2:B8:62:B2:E4:B8:7B:CB
+-----BEGIN CERTIFICATE-----
+MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw
+CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw
+FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S
+Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5
+MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL
+DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS
+QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH
+sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK
+Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu
+SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC
+MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy
+v+c=
+-----END CERTIFICATE-----
+
+### GlobalSign
+
+=== /OU=GlobalSign ECC Root CA - R4/O=GlobalSign/CN=GlobalSign
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:03:e5:7e:f5:3f:93:fd:a5:09:21:b2:a6
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Nov 13 00:00:00 2012 GMT
+            Not After : Jan 19 03:14:07 2038 GMT
+        Subject: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                54:B0:7B:AD:45:B8:E2:40:7F:FB:0A:6E:FB:BE:33:C9:3C:A3:84:D5
+SHA1 Fingerprint=6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28
+SHA256 Fingerprint=B0:85:D7:0B:96:4F:19:1A:73:E4:AF:0D:54:AE:7A:0E:07:AA:FD:AF:9B:71:DD:08:62:13:8A:B7:32:5A:24:A2
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
+VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
+MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
+UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
+BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
+uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
+HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
++wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
+bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+=== /OU=GlobalSign ECC Root CA - R5/O=GlobalSign/CN=GlobalSign
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            60:59:49:e0:26:2e:bb:55:f9:0a:77:8a:71:f9:4a:d8:6c
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Nov 13 00:00:00 2012 GMT
+            Not After : Jan 19 03:14:07 2038 GMT
+        Subject: OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                3D:E6:29:48:9B:EA:07:CA:21:44:4A:26:DE:6E:DE:D2:83:D0:9F:59
+SHA1 Fingerprint=1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA
+SHA256 Fingerprint=17:9F:BC:14:8A:3D:D0:0F:D2:4E:A1:34:58:CC:43:BF:A7:F5:9C:81:82:D7:83:A5:13:F6:EB:EC:10:0C:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+=== /OU=GlobalSign Root CA - R3/O=GlobalSign/CN=GlobalSign
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            04:00:00:00:00:01:21:58:53:08:a2
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Mar 18 10:00:00 2009 GMT
+            Not After : Mar 18 10:00:00 2029 GMT
+        Subject: OU=GlobalSign Root CA - R3, O=GlobalSign, CN=GlobalSign
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                8F:F0:4B:7F:A8:2E:45:24:AE:4D:50:FA:63:9A:8B:DE:E2:DD:1B:BC
+SHA1 Fingerprint=D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD
+SHA256 Fingerprint=CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+=== /OU=GlobalSign Root CA - R6/O=GlobalSign/CN=GlobalSign
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            45:e6:bb:03:83:33:c3:85:65:48:e6:ff:45:51
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Dec 10 00:00:00 2014 GMT
+            Not After : Dec 10 00:00:00 2034 GMT
+        Subject: OU=GlobalSign Root CA - R6, O=GlobalSign, CN=GlobalSign
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                AE:6C:05:A3:93:13:E2:A2:E7:E2:D7:1C:D6:C7:F0:7F:C8:67:53:A0
+            X509v3 Authority Key Identifier: 
+                keyid:AE:6C:05:A3:93:13:E2:A2:E7:E2:D7:1C:D6:C7:F0:7F:C8:67:53:A0
+
+SHA1 Fingerprint=80:94:64:0E:B5:A7:A1:CA:11:9C:1F:DD:D5:9F:81:02:63:A7:FB:D1
+SHA256 Fingerprint=2C:AB:EA:FE:37:D0:6C:A2:2A:BA:73:91:C0:03:3D:25:98:29:52:C4:53:64:73:49:76:3A:3A:B5:AD:6C:CF:69
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
+
+### GlobalSign nv-sa
+
+=== /C=BE/O=GlobalSign nv-sa/CN=GlobalSign Root E46
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            11:d2:bb:ba:33:6e:d4:bc:e6:24:68:c5:0d:84:1d:98:e8:43
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Mar 20 00:00:00 2019 GMT
+            Not After : Mar 20 00:00:00 2046 GMT
+        Subject: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Root E46
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                31:0A:90:8F:B6:C6:9D:D2:44:4B:80:B5:A2:E6:1F:B1:12:4F:1B:95
+SHA1 Fingerprint=39:B4:6C:D5:FE:80:06:EB:E2:2F:4A:BB:08:33:A0:AF:DB:B9:DD:84
+SHA256 Fingerprint=CB:B9:C4:4D:84:B8:04:3E:10:50:EA:31:A6:9F:51:49:55:D7:BF:D2:E2:C6:B4:93:01:01:9A:D6:1D:9F:50:58
+-----BEGIN CERTIFICATE-----
+MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx
+CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD
+ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw
+MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex
+HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq
+R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd
+yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ
+7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8
++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A=
+-----END CERTIFICATE-----
+=== /C=BE/O=GlobalSign nv-sa/CN=GlobalSign Root R46
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            11:d2:bb:b9:d7:23:18:9e:40:5f:0a:9d:2d:d0:df:25:67:d1
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Mar 20 00:00:00 2019 GMT
+            Not After : Mar 20 00:00:00 2046 GMT
+        Subject: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Root R46
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                03:5C:AB:73:81:87:A8:CC:B0:A6:D5:94:E2:36:96:49:FF:05:99:2C
+SHA1 Fingerprint=53:A2:B0:4B:CA:6B:D6:45:E6:39:8A:8E:C4:0D:D2:BF:77:C3:A2:90
+SHA256 Fingerprint=4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA
+MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD
+VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy
+MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt
+c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ
+OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG
+vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud
+316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo
+0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE
+y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF
+zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE
++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN
+I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs
+x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa
+ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC
+4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4
+7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg
+JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti
+2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk
+pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF
+FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt
+rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk
+ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5
+u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP
+4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6
+N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3
+vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6
+-----END CERTIFICATE-----
+=== /C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            04:00:00:00:00:01:15:4b:5a:c3:94
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Sep  1 12:00:00 1998 GMT
+            Not After : Jan 28 12:00:00 2028 GMT
+        Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
+SHA1 Fingerprint=B1:BC:96:8B:D4:F4:9D:62:2A:A8:9A:81:F2:15:01:52:A4:1D:82:9C
+SHA256 Fingerprint=EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+### GoDaddy.com, Inc.
+
+=== /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep  1 00:00:00 2009 GMT
+            Not After : Dec 31 23:59:59 2037 GMT
+        Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                3A:9A:85:07:10:67:28:B6:EF:F6:BD:05:41:6E:20:C1:94:DA:0F:DE
+SHA1 Fingerprint=47:BE:AB:C9:22:EA:E8:0E:78:78:34:62:A7:9F:45:C2:54:FD:E6:8B
+SHA256 Fingerprint=45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+### Google Trust Services LLC
+
+=== /C=US/O=Google Trust Services LLC/CN=GTS Root R1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:03:e5:93:6f:31:b0:13:49:88:6b:a2:17
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jun 22 00:00:00 2016 GMT
+            Not After : Jun 22 00:00:00 2036 GMT
+        Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E
+SHA1 Fingerprint=E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A
+SHA256 Fingerprint=D9:47:43:2A:BD:E7:B7:FA:90:FC:2E:6B:59:10:1B:12:80:E0:E1:C7:E4:E4:0F:A3:C6:88:7F:FF:57:A7:F4:CF
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
+-----END CERTIFICATE-----
+=== /C=US/O=Google Trust Services LLC/CN=GTS Root R2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:03:e5:ae:c5:8d:04:25:1a:ab:11:25:aa
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jun 22 00:00:00 2016 GMT
+            Not After : Jun 22 00:00:00 2036 GMT
+        Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R2
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                BB:FF:CA:8E:23:9F:4F:99:CA:DB:E2:68:A6:A5:15:27:17:1E:D9:0E
+SHA1 Fingerprint=9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94
+SHA256 Fingerprint=8D:25:CD:97:22:9D:BF:70:35:6B:DA:4E:B3:CC:73:40:31:E2:4C:F0:0F:AF:CF:D3:2D:C7:6E:B5:84:1C:7E:A8
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt
+nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY
+6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu
+MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k
+RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg
+f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV
++3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo
+dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
+Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa
+G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq
+gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID
+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H
+vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC
+B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u
+NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg
+yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev
+HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6
+xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR
+TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg
+JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV
+7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl
+6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL
+-----END CERTIFICATE-----
+=== /C=US/O=Google Trust Services LLC/CN=GTS Root R3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:03:e5:b8:82:eb:20:f8:25:27:6d:3d:66
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jun 22 00:00:00 2016 GMT
+            Not After : Jun 22 00:00:00 2036 GMT
+        Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R3
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                C1:F1:26:BA:A0:2D:AE:85:81:CF:D3:F1:2A:12:BD:B8:0A:67:FD:BC
+SHA1 Fingerprint=ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46
+SHA256 Fingerprint=34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G
+jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2
+4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7
+VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm
+ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+=== /C=US/O=Google Trust Services LLC/CN=GTS Root R4
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            02:03:e5:c0:68:ef:63:1a:9c:72:90:50:52
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jun 22 00:00:00 2016 GMT
+            Not After : Jun 22 00:00:00 2036 GMT
+        Subject: C=US, O=Google Trust Services LLC, CN=GTS Root R4
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C
+SHA1 Fingerprint=77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47
+SHA256 Fingerprint=34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
+VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
+A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
+WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
+IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
+QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
+HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
+9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
+p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+### GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.
+
+=== /C=CN/O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD./CN=GDCA TrustAUTH R5 ROOT
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 9009899650740120186 (0x7d0997fef047ea7a)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Nov 26 05:13:15 2014 GMT
+            Not After : Dec 31 15:59:59 2040 GMT
+        Subject: C=CN, O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD., CN=GDCA TrustAUTH R5 ROOT
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                E2:C9:40:9F:4D:CE:E8:9A:A1:7C:CF:0E:3F:65:C5:29:88:6A:19:51
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=0F:36:38:5B:81:1A:25:C3:9B:31:4E:83:CA:E9:34:66:70:CC:74:B4
+SHA256 Fingerprint=BF:FF:8F:D0:44:33:48:7D:6A:8A:A6:0C:1A:29:76:7A:9F:C2:BB:B0:5E:42:0F:71:3A:13:B9:92:89:1D:38:93
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+### Hellenic Academic and Research Institutions CA
+
+=== /C=GR/O=Hellenic Academic and Research Institutions CA/CN=HARICA TLS ECC Root CA 2021
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            67:74:9d:8d:77:d8:3b:6a:db:22:f4:ff:59:e2:bf:ce
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb 19 11:01:10 2021 GMT
+            Not After : Feb 13 11:01:09 2045 GMT
+        Subject: C=GR, O=Hellenic Academic and Research Institutions CA, CN=HARICA TLS ECC Root CA 2021
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                C9:1B:53:81:12:FE:04:D5:16:D1:AA:BC:9A:6F:B7:A0:95:19:6E:CA
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=BC:B0:C1:9D:E9:98:92:70:19:38:57:E9:8D:A7:B4:5D:6E:EE:01:48
+SHA256 Fingerprint=3F:99:CC:47:4A:CF:CE:4D:FE:D5:87:94:66:5E:47:8D:15:47:73:9F:2E:78:0F:1B:B4:CA:9B:13:30:97:D4:01
+-----BEGIN CERTIFICATE-----
+MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw
+CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh
+cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v
+dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG
+A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
+aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg
+Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7
+KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y
+STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD
+AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw
+SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN
+nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
+-----END CERTIFICATE-----
+=== /C=GR/O=Hellenic Academic and Research Institutions CA/CN=HARICA TLS RSA Root CA 2021
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            39:ca:93:1c:ef:43:f3:c6:8e:93:c7:f4:64:89:38:7e
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 19 10:55:38 2021 GMT
+            Not After : Feb 13 10:55:37 2045 GMT
+        Subject: C=GR, O=Hellenic Academic and Research Institutions CA, CN=HARICA TLS RSA Root CA 2021
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                0A:48:23:A6:60:A4:92:0A:33:EA:93:5B:C5:57:EA:25:4D:BD:12:EE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=02:2D:05:82:FA:88:CE:14:0C:06:79:DE:7F:14:10:E9:45:D7:A5:6D
+SHA256 Fingerprint=D9:5D:0E:8E:DA:79:52:5B:F9:BE:B1:1B:14:D2:10:0D:32:94:98:5F:0C:62:D9:FA:BD:9C:D9:99:EC:CB:7B:1D
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs
+MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg
+Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL
+MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
+YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv
+b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l
+mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE
+4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv
+a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M
+pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw
+Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b
+LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY
+AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB
+AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq
+E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr
+W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ
+CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU
+X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3
+f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja
+H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP
+JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P
+zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt
+jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0
+/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT
+BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79
+aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW
+xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU
+63ZTGI0RmLo=
+-----END CERTIFICATE-----
+
+### Hellenic Academic and Research Institutions Cert. Authority
+
+=== /C=GR/L=Athens/O=Hellenic Academic and Research Institutions Cert. Authority/CN=Hellenic Academic and Research Institutions ECC RootCA 2015
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Jul  7 10:37:12 2015 GMT
+            Not After : Jun 30 10:37:12 2040 GMT
+        Subject: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions ECC RootCA 2015
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                B4:22:0B:82:99:24:01:0E:9C:BB:E4:0E:FD:BF:FB:97:20:93:99:2A
+SHA1 Fingerprint=9F:F1:71:8D:92:D5:9A:F3:7D:74:97:B4:BC:6F:84:68:0B:BA:B6:66
+SHA256 Fingerprint=44:B5:45:AA:8A:25:E6:5A:73:CA:15:DC:27:FC:36:D2:4C:1C:B9:95:3A:06:65:39:B1:15:82:DC:48:7B:48:33
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+=== /C=GR/L=Athens/O=Hellenic Academic and Research Institutions Cert. Authority/CN=Hellenic Academic and Research Institutions RootCA 2015
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jul  7 10:11:21 2015 GMT
+            Not After : Jun 30 10:11:21 2040 GMT
+        Subject: C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. Authority, CN=Hellenic Academic and Research Institutions RootCA 2015
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                71:15:67:C8:C8:C9:BD:75:5D:72:D0:38:18:6A:9D:F3:71:24:54:0B
+SHA1 Fingerprint=01:0C:06:95:A6:98:19:14:FF:BF:5F:C6:B0:B6:95:EA:29:E9:12:A6
+SHA256 Fingerprint=A0:40:92:9A:02:CE:53:B4:AC:F4:F2:FF:C6:98:1C:E4:49:6F:75:5E:6D:45:FE:0B:2A:69:2B:CD:52:52:3F:36
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+### Hongkong Post
+
+=== /C=HK/O=Hongkong Post/CN=Hongkong Post Root CA 1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1000 (0x3e8)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: May 15 05:13:14 2003 GMT
+            Not After : May 15 04:52:29 2023 GMT
+        Subject: C=HK, O=Hongkong Post, CN=Hongkong Post Root CA 1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE, pathlen:3
+            X509v3 Key Usage: critical
+                Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
+SHA1 Fingerprint=D6:DA:A8:20:8D:09:D2:15:4D:24:B5:2F:CB:34:6E:B2:58:B2:8A:58
+SHA256 Fingerprint=F9:E6:7D:33:6C:51:00:2A:C0:54:C6:32:02:2D:66:DD:A2:E7:E3:FF:F1:0A:D0:61:ED:31:D8:BB:B4:10:CF:B2
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
+FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
+Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
+A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
+b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
+jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
+PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
+ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
+nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
+q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
+MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
+mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
+7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
+oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
+EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
+fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
+AmvZWg==
+-----END CERTIFICATE-----
+=== /C=HK/ST=Hong Kong/L=Hong Kong/O=Hongkong Post/CN=Hongkong Post Root CA 3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jun  3 02:29:46 2017 GMT
+            Not After : Jun  3 02:29:46 2042 GMT
+        Subject: C=HK, ST=Hong Kong, L=Hong Kong, O=Hongkong Post, CN=Hongkong Post Root CA 3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Authority Key Identifier: 
+                keyid:17:9D:CD:1E:8B:D6:39:2B:70:D3:5C:D4:A0:B8:1F:B0:00:FC:C5:61
+
+            X509v3 Subject Key Identifier: 
+                17:9D:CD:1E:8B:D6:39:2B:70:D3:5C:D4:A0:B8:1F:B0:00:FC:C5:61
+SHA1 Fingerprint=58:A2:D0:EC:20:52:81:5B:C1:F3:F8:64:02:24:4E:C2:8E:02:4B:02
+SHA256 Fingerprint=5A:2F:C0:3F:0C:83:B0:90:BB:FA:40:60:4B:09:88:44:6C:76:36:18:3D:F9:84:6E:17:10:1A:44:7F:B8:EF:D6
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL
+BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ
+SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n
+a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5
+NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT
+CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u
+Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO
+dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI
+VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV
+9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY
+2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY
+vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt
+bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb
+x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+
+l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK
+TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj
+Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw
+DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG
+7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk
+MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr
+gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk
+GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS
+3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm
+Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+
+l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c
+JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP
+L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
+LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
+mpv0
+-----END CERTIFICATE-----
+
+### IdenTrust
+
+=== /C=US/O=IdenTrust/CN=IdenTrust Commercial Root CA 1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 16 18:12:23 2014 GMT
+            Not After : Jan 16 18:12:23 2034 GMT
+        Subject: C=US, O=IdenTrust, CN=IdenTrust Commercial Root CA 1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                ED:44:19:C0:D3:F0:06:8B:EE:A4:7B:BE:42:E7:26:54:C8:8E:36:76
+SHA1 Fingerprint=DF:71:7E:AA:4A:D9:4E:C9:55:84:99:60:2D:48:DE:5F:BC:F0:3A:25
+SHA256 Fingerprint=5D:56:49:9B:E4:D2:E0:8B:CF:CA:D0:8A:3E:38:72:3D:50:50:3B:DE:70:69:48:E4:2F:55:60:30:19:E5:28:AE
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+=== /C=US/O=IdenTrust/CN=IdenTrust Public Sector Root CA 1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 16 17:53:32 2014 GMT
+            Not After : Jan 16 17:53:32 2034 GMT
+        Subject: C=US, O=IdenTrust, CN=IdenTrust Public Sector Root CA 1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                E3:71:E0:9E:D8:A7:42:D9:DB:71:91:6B:94:93:EB:C3:A3:D1:14:A3
+SHA1 Fingerprint=BA:29:41:60:77:98:3F:F4:F3:EF:F2:31:05:3B:2E:EA:6D:4D:45:FD
+SHA256 Fingerprint=30:D0:89:5A:9A:44:8A:26:20:91:63:55:22:D1:F5:20:10:B5:86:7A:CA:E1:2C:78:EF:95:8F:D4:F4:38:9F:2F
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+### Internet Security Research Group
+
+=== /C=US/O=Internet Security Research Group/CN=ISRG Root X1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            82:10:cf:b0:d2:40:e3:59:44:63:e0:bb:63:82:8b:00
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jun  4 11:04:38 2015 GMT
+            Not After : Jun  4 11:04:38 2035 GMT
+        Subject: C=US, O=Internet Security Research Group, CN=ISRG Root X1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                79:B4:59:E6:7B:B6:E5:E4:01:73:80:08:88:C8:1A:58:F6:E9:9B:6E
+SHA1 Fingerprint=CA:BD:2A:79:A1:07:6A:31:F2:1D:25:36:35:CB:03:9D:43:29:A5:E8
+SHA256 Fingerprint=96:BC:EC:06:26:49:76:F3:74:60:77:9A:CF:28:C5:A7:CF:E8:A3:C0:AA:E1:1A:8F:FC:EE:05:C0:BD:DF:08:C6
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+=== /C=US/O=Internet Security Research Group/CN=ISRG Root X2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            41:d2:9d:d1:72:ea:ee:a7:80:c1:2c:6c:e9:2f:87:52
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Sep  4 00:00:00 2020 GMT
+            Not After : Sep 17 16:00:00 2040 GMT
+        Subject: C=US, O=Internet Security Research Group, CN=ISRG Root X2
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                7C:42:96:AE:DE:4B:48:3B:FA:92:F8:9E:8C:CF:6D:8B:A9:72:37:95
+SHA1 Fingerprint=BD:B1:B9:3C:D5:97:8D:45:C6:26:14:55:F8:DB:95:C7:5A:D1:53:AF
+SHA256 Fingerprint=69:72:9B:8E:15:A8:6E:FC:17:7A:57:AF:B7:17:1D:FC:64:AD:D2:8C:2F:CA:8C:F1:50:7E:34:45:3C:CB:14:70
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw
+CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg
+R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00
+MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT
+ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW
++1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9
+ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI
+zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW
+tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1
+/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+### iTrusChina Co.,Ltd.
+
+=== /C=CN/O=iTrusChina Co.,Ltd./CN=vTrus ECC Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            6e:6a:bc:59:aa:53:be:98:39:67:a2:d2:6b:a4:3b:e6:6d:1c:d6:da
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jul 31 07:26:44 2018 GMT
+            Not After : Jul 31 07:26:44 2043 GMT
+        Subject: C=CN, O=iTrusChina Co.,Ltd., CN=vTrus ECC Root CA
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                98:39:CD:BE:D8:B2:8C:F7:B2:AB:E1:AD:24:AF:7B:7C:A1:DB:1F:CF
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=F6:9C:DB:B0:FC:F6:02:13:B6:52:32:A6:A3:91:3F:16:70:DA:C3:E1
+SHA256 Fingerprint=30:FB:BA:2C:32:23:8E:2A:98:54:7A:F9:79:31:E5:50:42:8B:9B:3F:1C:8E:EB:66:33:DC:FA:86:C5:B2:7D:D3
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMw
+RzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAY
+BgNVBAMTEXZUcnVzIEVDQyBSb290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDcz
+MTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28u
+LEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+cToL0
+v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUd
+e4BdS49nTPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIw
+V53dVvHH4+m4SVBrm2nDb+zDfSXkV5UTQJtS0zvzQBm8JsctBp61ezaf9SXUY2sA
+AjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQLYgmRWAD5Tfs0aNoJrSEG
+GJTO
+-----END CERTIFICATE-----
+=== /C=CN/O=iTrusChina Co.,Ltd./CN=vTrus Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            43:e3:71:13:d8:b3:59:14:5d:b7:ce:8c:fd:35:fd:6f:bc:05:8d:45
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jul 31 07:24:05 2018 GMT
+            Not After : Jul 31 07:24:05 2043 GMT
+        Subject: C=CN, O=iTrusChina Co.,Ltd., CN=vTrus Root CA
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                54:62:70:63:F1:75:84:43:58:8E:D1:16:20:B1:C6:AC:1A:BC:F6:89
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=84:1A:69:FB:F5:CD:1A:25:34:13:3D:E3:F8:FC:B8:99:D0:C9:14:B7
+SHA256 Fingerprint=8A:71:DE:65:59:33:6F:42:6C:26:E5:38:80:D0:0D:88:A1:8D:A4:C6:A9:1F:0D:CB:61:94:E2:06:C5:C9:63:87
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQEL
+BQAwQzELMAkGA1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4x
+FjAUBgNVBAMTDXZUcnVzIFJvb3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMx
+MDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoGA1UEChMTaVRydXNDaGluYSBDby4s
+THRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZotsSKYc
+IrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykU
+AyyNJJrIZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+
+GrPSbcKvdmaVayqwlHeFXgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z9
+8Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KAYPxMvDVTAWqXcoKv8R1w6Jz1717CbMdH
+flqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70kLJrxLT5ZOrpGgrIDajt
+J8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2AXPKBlim
+0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZN
+pGvu/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQ
+UqqzApVg+QxMaPnu1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHW
+OXSuTEGC2/KmSNGzm/MzqvOmwMVO9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMB
+AAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYgscasGrz2iTAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAKbqSSaet
+8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1j
+bhd47F18iMjrjld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvM
+Kar5CKXiNxTKsbhm7xqC5PD48acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIiv
+TDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJnxDHO2zTlJQNgJXtxmOTAGytfdELS
+S8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554WgicEFOwE30z9J4nfr
+I8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4sEb9
+b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNB
+UvupLnKWnyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1P
+Ti07NEPhmg4NpGaXutIcSkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929ven
+sBxXVsFy6K2ir40zSbofitzmdHxghm+Hl3s=
+-----END CERTIFICATE-----
+
+### IZENPE S.A.
+
+=== /C=ES/O=IZENPE S.A./CN=Izenpe.com
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            b0:b7:5a:16:48:5f:bf:e1:cb:f5:8b:d7:19:e6:7d
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Dec 13 13:08:28 2007 GMT
+            Not After : Dec 13 08:27:25 2037 GMT
+        Subject: C=ES, O=IZENPE S.A., CN=Izenpe.com
+        X509v3 extensions:
+            X509v3 Subject Alternative Name: 
+                email:info@izenpe.com, DirName:/O=IZENPE S.A. - CIF A01337260-RMerc.Vitoria-Gasteiz T1055 F62 S8/street=Avda del Mediterraneo Etorbidea 14 - 01010 Vitoria-Gasteiz
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                1D:1C:65:0E:A8:F2:25:7B:B4:91:CF:E4:B1:B1:E6:BD:55:74:6C:05
+SHA1 Fingerprint=2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19
+SHA256 Fingerprint=25:30:CC:8E:98:32:15:02:BA:D9:6F:9B:1F:BA:1B:09:9E:2D:29:9E:0F:45:48:BB:91:4F:36:3B:C0:D4:53:1F
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+### Japan Certification Services, Inc.
+
+=== /C=JP/O=Japan Certification Services, Inc./CN=SecureSign RootCA11
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Apr  8 04:56:47 2009 GMT
+            Not After : Apr  8 04:56:47 2029 GMT
+        Subject: C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA11
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                5B:F8:4D:4F:B2:A5:86:D4:3A:D2:F1:63:9A:A0:BE:09:F6:57:B7:DE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=3B:C4:9F:48:F8:F3:73:A0:9C:1E:BD:F8:5B:B1:C3:65:C7:D8:11:B3
+SHA256 Fingerprint=BF:0F:EE:FB:9E:3A:58:1A:D5:F9:E9:DB:75:89:98:57:43:D2:61:08:5C:4D:31:4F:6F:5D:72:59:AA:42:16:12
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
+QSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+### Krajowa Izba Rozliczeniowa S.A.
+
+=== /C=PL/O=Krajowa Izba Rozliczeniowa S.A./CN=SZAFIR ROOT CA2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            3e:8a:5d:07:ec:55:d2:32:d5:b7:e3:b6:5f:01:eb:2d:dc:e4:d6:e4
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct 19 07:43:30 2015 GMT
+            Not After : Oct 19 07:43:30 2035 GMT
+        Subject: C=PL, O=Krajowa Izba Rozliczeniowa S.A., CN=SZAFIR ROOT CA2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                2E:16:A9:4A:18:B5:CB:CC:F5:6F:50:F3:23:5F:F8:5D:E7:AC:F0:C8
+SHA1 Fingerprint=E2:52:FA:95:3F:ED:DB:24:60:BD:6E:28:F3:9C:CC:CF:5E:B3:3F:DE
+SHA256 Fingerprint=A1:33:9D:33:28:1A:0B:56:E5:57:D3:D3:2B:1C:E7:F9:36:7E:B0:94:BD:5F:A7:2A:7E:50:04:C8:DE:D7:CA:FE
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+### Microsec Ltd.
+
+=== /C=HU/L=Budapest/O=Microsec Ltd./2.5.4.97=VATHU-23584497/CN=e-Szigno Root CA 2017
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            01:54:48:ef:21:fd:97:59:0d:f5:04:0a
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Aug 22 12:07:06 2017 GMT
+            Not After : Aug 22 12:07:06 2042 GMT
+        Subject: C=HU, L=Budapest, O=Microsec Ltd./2.5.4.97=VATHU-23584497, CN=e-Szigno Root CA 2017
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                87:11:15:08:D1:AA:C1:78:0C:B1:AF:CE:C6:C9:90:EF:BF:30:04:C0
+            X509v3 Authority Key Identifier: 
+                keyid:87:11:15:08:D1:AA:C1:78:0C:B1:AF:CE:C6:C9:90:EF:BF:30:04:C0
+
+SHA1 Fingerprint=89:D4:83:03:4F:9E:9A:48:80:5F:72:37:D4:A9:A6:EF:CB:7C:1F:D1
+SHA256 Fingerprint=BE:B0:0B:30:83:9B:9B:C3:2C:32:E4:44:79:05:95:06:41:F2:64:21:B1:5E:D0:89:19:8B:51:8A:E2:EA:1B:99
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV
+BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk
+LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv
+b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg
+THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v
+IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv
+xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H
+Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB
+eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo
+jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ
++efcMQ==
+-----END CERTIFICATE-----
+=== /C=HU/L=Budapest/O=Microsec Ltd./CN=Microsec e-Szigno Root CA 2009/emailAddress=info@e-szigno.hu
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            c2:7e:43:04:4e:47:3f:19
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jun 16 11:30:18 2009 GMT
+            Not After : Dec 30 11:30:18 2029 GMT
+        Subject: C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA 2009/emailAddress=info@e-szigno.hu
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68
+            X509v3 Authority Key Identifier: 
+                keyid:CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68
+
+            X509v3 Subject Alternative Name: 
+                email:info@e-szigno.hu
+SHA1 Fingerprint=89:DF:74:FE:5C:F4:0F:4A:80:F9:E3:37:7D:54:DA:91:E1:01:31:8E
+SHA256 Fingerprint=3C:5F:81:FE:A5:FA:B8:2C:64:BF:A2:EA:EC:AF:CD:E8:E0:77:FC:86:20:A7:CA:E5:37:16:3D:F3:6E:DB:F3:78
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+### Microsoft Corporation
+
+=== /C=US/O=Microsoft Corporation/CN=Microsoft ECC Root Certificate Authority 2017
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            66:f2:3d:af:87:de:8b:b1:4a:ea:0c:57:31:01:c2:ec
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Dec 18 23:06:45 2019 GMT
+            Not After : Jul 18 23:16:04 2042 GMT
+        Subject: C=US, O=Microsoft Corporation, CN=Microsoft ECC Root Certificate Authority 2017
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                C8:CB:99:72:70:52:0C:F8:E6:BE:B2:04:57:29:2A:CF:42:10:ED:35
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=99:9A:64:C3:7F:F4:7D:9F:AB:95:F1:47:69:89:14:60:EE:C4:C3:C5
+SHA256 Fingerprint=35:8D:F3:9D:76:4A:F9:E1:B7:66:E9:C9:72:DF:35:2E:E1:5C:FA:C2:27:AF:6A:D1:D7:0E:8E:4A:6E:DC:BA:02
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD
+VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
+MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy
+b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR
+ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb
+hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3
+FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV
+L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB
+iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
+=== /C=US/O=Microsoft Corporation/CN=Microsoft RSA Root Certificate Authority 2017
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            1e:d3:97:09:5f:d8:b4:b3:47:70:1e:aa:be:7f:45:b3
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Dec 18 22:51:22 2019 GMT
+            Not After : Jul 18 23:00:23 2042 GMT
+        Subject: C=US, O=Microsoft Corporation, CN=Microsoft RSA Root Certificate Authority 2017
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                09:CB:59:7F:86:B2:70:8F:1A:C3:39:E3:C0:D9:E9:BF:BB:4D:B2:23
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=73:A5:E6:4A:3B:FF:83:16:FF:0E:DC:CC:61:8A:90:6E:4E:AE:4D:74
+SHA256 Fingerprint=C7:41:F7:0F:4B:2A:8D:88:BF:2E:71:C1:41:22:EF:53:EF:10:EB:A0:CF:A5:E6:4C:FA:20:F4:18:85:30:73:E0
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl
+MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N
+aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ
+Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0
+ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1
+HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm
+gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ
+jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc
+aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG
+YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6
+W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K
+UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH
++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q
+W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC
+LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC
+gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6
+tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh
+SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2
+TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3
+pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR
+xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp
+GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9
+dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN
+AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB
+RA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
+
+### NAVER BUSINESS PLATFORM Corp.
+
+=== /C=KR/O=NAVER BUSINESS PLATFORM Corp./CN=NAVER Global Root Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            01:94:30:1e:a2:0b:dd:f5:c5:33:2a:b1:43:44:71:f8:d6:50:4d:0d
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Aug 18 08:58:42 2017 GMT
+            Not After : Aug 18 23:59:59 2037 GMT
+        Subject: C=KR, O=NAVER BUSINESS PLATFORM Corp., CN=NAVER Global Root Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                D2:9F:88:DF:A1:CD:2C:BD:EC:F5:3B:01:01:93:33:27:B2:EB:60:4B
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=8F:6B:F2:A9:27:4A:DA:14:A0:C4:F4:8E:61:27:F9:C0:1E:78:5D:D1
+SHA256 Fingerprint=88:F4:38:DC:F8:FF:D1:FA:8F:42:91:15:FF:E5:F8:2A:E1:E0:6E:0C:70:C3:75:FA:AD:71:7B:34:A4:9E:72:65
+-----BEGIN CERTIFICATE-----
+MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM
+BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG
+T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx
+CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD
+b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA
+iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH
+38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE
+HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz
+kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP
+szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq
+vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf
+nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG
+YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo
+0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a
+CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K
+AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I
+36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB
+Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN
+qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj
+cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm
++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL
+hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe
+lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7
+p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8
+piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR
+LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX
+5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO
+dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul
+9XXeifdy
+-----END CERTIFICATE-----
+
+### NetLock Kft.
+
+=== /C=HU/L=Budapest/O=NetLock Kft./OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification Services)/CN=NetLock Arany (Class Gold) F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 80544274841616 (0x49412ce40010)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Dec 11 15:08:21 2008 GMT
+            Not After : Dec  6 15:08:21 2028 GMT
+        Subject: C=HU, L=Budapest, O=NetLock Kft., OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification Services), CN=NetLock Arany (Class Gold) F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE, pathlen:4
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                CC:FA:67:93:F0:B6:B8:D0:A5:C0:1E:F3:53:FD:8C:53:DF:83:D7:96
+SHA1 Fingerprint=06:08:3F:59:3F:15:A1:04:A0:69:A4:6B:A9:03:D0:06:B7:97:09:91
+SHA256 Fingerprint=6C:61:DA:C3:A2:DE:F0:31:50:6B:E0:36:D2:A6:FE:40:19:94:FB:D1:3D:F9:C8:D4:66:59:92:74:C4:46:EC:98
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+### QuoVadis Limited
+
+=== /C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 1 G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            78:58:5f:2e:ad:2c:19:4b:e3:37:07:35:34:13:28:b5:96:d4:65:93
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 12 17:27:44 2012 GMT
+            Not After : Jan 12 17:27:44 2042 GMT
+        Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 1 G3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                A3:97:D6:F3:5E:A2:10:E1:AB:45:9F:3C:17:64:3C:EE:01:70:9C:CC
+SHA1 Fingerprint=1B:8E:EA:57:96:29:1A:C9:39:EA:B8:0A:81:1A:73:73:C0:93:79:67
+SHA256 Fingerprint=8A:86:6F:D1:B2:76:B5:7E:57:8E:92:1C:65:82:8A:2B:ED:58:E9:F2:F2:88:05:41:34:B7:F1:F4:BF:C9:CC:74
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+=== /C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1289 (0x509)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 24 18:27:00 2006 GMT
+            Not After : Nov 24 18:23:33 2031 GMT
+        Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: 
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B
+            X509v3 Authority Key Identifier: 
+                keyid:1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B
+                DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 2
+                serial:05:09
+
+SHA1 Fingerprint=CA:3A:FB:CF:12:40:36:4B:44:B2:16:20:88:80:48:39:19:93:7C:F7
+SHA256 Fingerprint=85:A0:DD:7D:D7:20:AD:B7:FF:05:F8:3D:54:2B:20:9D:C7:FF:45:28:F7:D6:77:B1:83:89:FE:A5:E5:C4:9E:86
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+=== /C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 2 G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            44:57:34:24:5b:81:89:9b:35:f2:ce:b8:2b:3b:5b:a7:26:f0:75:28
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 12 18:59:32 2012 GMT
+            Not After : Jan 12 18:59:32 2042 GMT
+        Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 G3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                ED:E7:6F:76:5A:BF:60:EC:49:5B:C6:A5:77:BB:72:16:71:9B:C4:3D
+SHA1 Fingerprint=09:3C:61:F3:8B:8B:DC:7D:55:DF:75:38:02:05:00:E1:25:F5:C8:36
+SHA256 Fingerprint=8F:E4:FB:0A:F9:3A:4D:0D:67:DB:0B:EB:B2:3E:37:C7:1B:F3:25:DC:BC:DD:24:0E:A0:4D:AF:58:B4:7E:18:40
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+=== /C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1478 (0x5c6)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov 24 19:11:23 2006 GMT
+            Not After : Nov 24 19:06:44 2031 GMT
+        Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Certificate Policies: 
+                Policy: 1.3.6.1.4.1.8024.0.3
+                  User Notice:
+                    Explicit Text: Any use of this Certificate constitutes acceptance of the QuoVadis Root CA 3 Certificate Policy / Certification Practice Statement.
+                  CPS: http://www.quovadisglobal.com/cps
+
+            X509v3 Key Usage: 
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0
+            X509v3 Authority Key Identifier: 
+                keyid:F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0
+                DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 3
+                serial:05:C6
+
+SHA1 Fingerprint=1F:49:14:F7:D8:74:95:1D:DD:AE:02:C0:BE:FD:3A:2D:82:75:51:85
+SHA256 Fingerprint=18:F1:FC:7F:20:5D:F8:AD:DD:EB:7F:E0:07:DD:57:E3:AF:37:5A:9C:4D:8D:73:54:6B:F4:F1:FE:D1:E1:8D:35
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+=== /C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 3 G3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            2e:f5:9b:02:28:a7:db:7a:ff:d5:a3:a9:ee:bd:03:a0:cf:12:6a:1d
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jan 12 20:26:32 2012 GMT
+            Not After : Jan 12 20:26:32 2042 GMT
+        Subject: C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 G3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                C6:17:D0:BC:A8:EA:02:43:F2:1B:06:99:5D:2B:90:20:B9:D7:9C:E4
+SHA1 Fingerprint=48:12:BD:92:3C:A8:C4:39:06:E7:30:6D:27:96:E6:A4:CF:22:2E:7D
+SHA256 Fingerprint=88:EF:81:DE:20:2E:B0:18:45:2E:43:F8:64:72:5C:EA:5F:BD:1F:C2:D9:D2:05:73:07:09:C5:D8:B8:69:0F:46
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+### SECOM Trust Systems CO.,LTD.
+
+=== /C=JP/O=SECOM Trust Systems CO.,LTD./CN=Security Communication ECC RootCA1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            d6:5d:9b:b3:78:81:2e:eb
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Jun 16 05:15:28 2016 GMT
+            Not After : Jan 18 05:15:28 2038 GMT
+        Subject: C=JP, O=SECOM Trust Systems CO.,LTD., CN=Security Communication ECC RootCA1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                86:1C:E7:FE:2D:A5:4A:8B:08:FE:28:11:FA:BE:A3:66:F8:60:59:2F
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=B8:0E:26:A9:BF:D2:B2:3B:C0:EF:46:C9:BA:C7:BB:F6:1D:0D:41:41
+SHA256 Fingerprint=E7:4F:BD:A5:5B:D5:64:C4:73:A3:6B:44:1A:A7:99:C8:A6:8E:07:74:40:E8:28:8B:9F:A1:E5:0E:4B:BA:CA:11
+-----BEGIN CERTIFICATE-----
+MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYT
+AkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYD
+VQQDEyJTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYx
+NjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTELMAkGA1UEBhMCSlAxJTAjBgNVBAoT
+HFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNVBAMTIlNlY3VyaXR5
+IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+Cnnfdl
+dB9sELLo5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpK
+ULGjQjBAMB0GA1UdDgQWBBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu
+9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O
+be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k=
+-----END CERTIFICATE-----
+=== /C=JP/O=SECOM Trust Systems CO.,LTD./CN=Security Communication RootCA3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            e1:7c:37:40:fd:1b:fe:67
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Jun 16 06:17:16 2016 GMT
+            Not After : Jan 18 06:17:16 2038 GMT
+        Subject: C=JP, O=SECOM Trust Systems CO.,LTD., CN=Security Communication RootCA3
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                64:14:7C:FC:58:72:16:A6:0A:29:34:15:6F:2A:CB:BC:FC:AF:A8:AB
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=C3:03:C8:22:74:92:E5:61:A2:9C:5F:79:91:2B:1E:44:13:91:30:3A
+SHA256 Fingerprint=24:A5:5C:2A:B0:51:44:2D:06:17:76:65:41:23:9A:4A:D0:32:D7:C5:51:75:AA:34:FF:DE:2F:BC:4F:5C:52:94
+-----BEGIN CERTIFICATE-----
+MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNV
+BAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScw
+JQYDVQQDEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2
+MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UEAxMeU2VjdXJpdHkg
+Q29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4r
+CmDvu20rhvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzA
+lrenfna84xtSGc4RHwsENPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MG
+TfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF7
+9+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGmnpjKIG58u4iFW/vAEGK7
+8vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtYXLVqAvO4
+g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3we
+GVPKp7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst
++3A7caoreyYn8xrC3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M
+0V9hvqG8OmpI6iZVIhZdXw3/JzOfGAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQ
+T9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0VcwCBEF/VfR2ccCAwEAAaNCMEAw
+HQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS
+YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PA
+FNr0Y/Dq9HHuTofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd
+9XbXv8S2gVj/yP9kaWJ5rW4OH3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQI
+UYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASxYfQAW0q3nHE3GYV5v4GwxxMOdnE+
+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZXSEIx2C/pHF7uNke
+gr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml+LLf
+iAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUV
+nuiZIesnKwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD
+2NCcnWXL0CsnMQMeNuE9dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//
+1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm6Vwdp6POXiUyK+OVrCoHzrQoeIY8Laad
+TdJ0MN1kURXbg4NR16/9M51NZg==
+-----END CERTIFICATE-----
+=== /C=JP/O=SECOM Trust Systems CO.,LTD./OU=Security Communication RootCA2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: May 29 05:00:39 2009 GMT
+            Not After : May 29 05:00:39 2029 GMT
+        Subject: C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication RootCA2
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                0A:85:A9:77:65:05:98:7C:40:81:F8:0F:97:2C:38:F1:0A:EC:3C:CF
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=5F:3B:8C:F2:F8:10:B3:7D:78:B4:CE:EC:19:19:C3:73:34:B9:C7:74
+SHA256 Fingerprint=51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+### SECOM Trust.net
+
+=== /C=JP/O=SECOM Trust.net/OU=Security Communication RootCA1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Sep 30 04:20:49 2003 GMT
+            Not After : Sep 30 04:20:49 2023 GMT
+        Subject: C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                A0:73:49:99:68:DC:85:5B:65:E3:9B:28:2F:57:9F:BD:33:BC:07:48
+            X509v3 Key Usage: 
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=36:B1:2B:49:F9:81:9E:D7:4C:9E:BC:38:0F:C6:56:8F:5D:AC:B2:F7
+SHA256 Fingerprint=E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
+-----END CERTIFICATE-----
+
+### SecureTrust Corporation
+
+=== /C=US/O=SecureTrust Corporation/CN=Secure Global CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            07:56:22:a4:e8:d4:8a:89:4d:f4:13:c8:f0:f8:ea:a5
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov  7 19:42:28 2006 GMT
+            Not After : Dec 31 19:52:06 2029 GMT
+        Subject: C=US, O=SecureTrust Corporation, CN=Secure Global CA
+        X509v3 extensions:
+            1.3.6.1.4.1.311.20.2: 
+                ...C.A
+            X509v3 Key Usage: 
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                AF:44:04:C2:41:7E:48:83:DB:4E:39:02:EC:EC:84:7A:E6:CE:C9:A4
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.securetrust.com/SGCA.crl
+
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=3A:44:73:5A:E5:81:90:1F:24:86:61:46:1E:3B:9C:C4:5F:F5:3A:1B
+SHA256 Fingerprint=42:00:F5:04:3A:C8:59:0E:BB:52:7D:20:9E:D1:50:30:29:FB:CB:D4:1C:A1:B5:06:EC:27:F1:5A:DE:7D:AC:69
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+=== /C=US/O=SecureTrust Corporation/CN=SecureTrust CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov  7 19:31:18 2006 GMT
+            Not After : Dec 31 19:40:55 2029 GMT
+        Subject: C=US, O=SecureTrust Corporation, CN=SecureTrust CA
+        X509v3 extensions:
+            1.3.6.1.4.1.311.20.2: 
+                ...C.A
+            X509v3 Key Usage: 
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                42:32:B6:16:FA:04:FD:FE:5D:4B:7A:C3:FD:F7:4C:40:1D:5A:43:AF
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.securetrust.com/STCA.crl
+
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=87:82:C6:C3:04:35:3B:CF:D2:96:92:D2:59:3E:7D:44:D9:34:FF:11
+SHA256 Fingerprint=F1:C1:B5:0A:E5:A2:0D:D8:03:0E:C9:F6:BC:24:82:3D:D3:67:B5:25:57:59:B4:E7:1B:61:FC:E9:F7:37:5D:73
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+### SSL Corporation
+
+=== /C=US/ST=Texas/L=Houston/O=SSL Corporation/CN=SSL.com EV Root Certification Authority ECC
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3182246526754555285 (0x2c299c5b16ed0595)
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Feb 12 18:15:23 2016 GMT
+            Not After : Feb 12 18:15:23 2041 GMT
+        Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority ECC
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F
+
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=4C:DD:51:A3:D1:F5:20:32:14:B0:C6:C5:32:23:03:91:C7:46:42:6D
+SHA256 Fingerprint=22:A2:C1:F7:BD:ED:70:4C:C1:E7:01:B5:F4:08:C3:10:88:0F:E9:56:B5:DE:2A:4A:44:F9:9C:87:3A:25:A7:C8
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
+=== /C=US/ST=Texas/L=Houston/O=SSL Corporation/CN=SSL.com EV Root Certification Authority RSA R2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6248227494352943350 (0x56b629cd34bc78f6)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: May 31 18:14:37 2017 GMT
+            Not After : May 30 18:14:37 2042 GMT
+        Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com EV Root Certification Authority RSA R2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E
+
+            X509v3 Subject Key Identifier: 
+                F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=74:3A:F0:52:9B:D0:32:A0:F4:4A:83:CD:D4:BA:A9:7B:7C:2E:C4:9A
+SHA256 Fingerprint=2E:7B:F1:6C:C2:24:85:A7:BB:E2:AA:86:96:75:07:61:B0:AE:39:BE:3B:2F:E9:D0:CC:6D:4E:F7:34:91:42:5C
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+=== /C=US/ST=Texas/L=Houston/O=SSL Corporation/CN=SSL.com Root Certification Authority ECC
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8495723813297216424 (0x75e6dfcbc1685ba8)
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Feb 12 18:14:03 2016 GMT
+            Not After : Feb 12 18:14:03 2041 GMT
+        Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority ECC
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD
+
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=C3:19:7C:39:24:E6:54:AF:1B:C4:AB:20:95:7A:E2:C3:0E:13:02:6A
+SHA256 Fingerprint=34:17:BB:06:CC:60:07:DA:1B:96:1C:92:0B:8A:B4:CE:3F:AD:82:0E:4A:A3:0B:9A:CB:C4:A7:4E:BD:CE:BC:65
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+=== /C=US/ST=Texas/L=Houston/O=SSL Corporation/CN=SSL.com Root Certification Authority RSA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8875640296558310041 (0x7b2c9bd316803299)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Feb 12 17:39:39 2016 GMT
+            Not After : Feb 12 17:39:39 2041 GMT
+        Subject: C=US, ST=Texas, L=Houston, O=SSL Corporation, CN=SSL.com Root Certification Authority RSA
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Authority Key Identifier: 
+                keyid:DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59
+
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=B7:AB:33:08:D1:EA:44:77:BA:14:80:12:5A:6F:BD:A9:36:49:0C:BB
+SHA256 Fingerprint=85:66:6A:56:2E:E0:BE:5C:E9:25:C1:D8:89:0A:6F:76:A8:7E:C1:6D:4D:7D:5F:29:EA:74:19:CF:20:12:3B:69
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+### Starfield Technologies, Inc.
+
+=== /C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jun 29 17:39:16 2004 GMT
+            Not After : Jun 29 17:39:16 2034 GMT
+        Subject: C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
+            X509v3 Authority Key Identifier: 
+                keyid:BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
+                DirName:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
+                serial:00
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+SHA1 Fingerprint=AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A
+SHA256 Fingerprint=14:65:FA:20:53:97:B8:76:FA:A6:F0:A9:95:8E:55:90:E4:0F:CC:7F:AA:4F:B7:C2:C8:67:75:21:FB:5F:B6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+=== /C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Root Certificate Authority - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep  1 00:00:00 2009 GMT
+            Not After : Dec 31 23:59:59 2037 GMT
+        Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Root Certificate Authority - G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                7C:0C:32:1F:A7:D9:30:7F:C4:7D:68:A3:62:A8:A1:CE:AB:07:5B:27
+SHA1 Fingerprint=B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E
+SHA256 Fingerprint=2C:E1:CB:0B:F9:D2:F9:E1:02:99:3F:BE:21:51:52:C3:B2:DD:0C:AB:DE:1C:68:E5:31:9B:83:91:54:DB:B7:F5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+=== /C=US/ST=Arizona/L=Scottsdale/O=Starfield Technologies, Inc./CN=Starfield Services Root Certificate Authority - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Sep  1 00:00:00 2009 GMT
+            Not After : Dec 31 23:59:59 2037 GMT
+        Subject: C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., CN=Starfield Services Root Certificate Authority - G2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                9C:5F:00:DF:AA:01:D7:30:2B:38:88:A2:B8:6D:4A:9C:F2:11:91:83
+SHA1 Fingerprint=92:5A:8F:8D:2C:6D:04:E0:66:5F:59:6A:FF:22:D8:63:E8:25:6F:3F
+SHA256 Fingerprint=56:8D:69:05:A2:C8:87:08:A4:B3:02:51:90:ED:CF:ED:B1:97:4A:60:6A:13:C6:E5:29:0F:CB:2A:E6:3E:DA:B5
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+### SwissSign AG
+
+=== /C=CH/O=SwissSign AG/CN=SwissSign Gold CA - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            bb:40:1c:43:f5:5e:4f:b0
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Oct 25 08:30:35 2006 GMT
+            Not After : Oct 25 08:30:35 2036 GMT
+        Subject: C=CH, O=SwissSign AG, CN=SwissSign Gold CA - G2
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE
+            X509v3 Authority Key Identifier: 
+                keyid:5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE
+
+            X509v3 Certificate Policies: 
+                Policy: 2.16.756.1.89.1.2.1.1
+                  CPS: http://repository.swisssign.com/
+
+SHA1 Fingerprint=D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61
+SHA256 Fingerprint=62:DD:0B:E9:B9:F5:0A:16:3E:A0:F8:E7:5C:05:3B:1E:CA:57:EA:55:C8:68:8F:64:7C:68:81:F2:C8:35:7B:95
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+=== /C=CH/O=SwissSign AG/CN=SwissSign Silver CA - G2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 5700383053117599563 (0x4f1bd42f54bb2f4b)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Oct 25 08:32:46 2006 GMT
+            Not After : Oct 25 08:32:46 2036 GMT
+        Subject: C=CH, O=SwissSign AG, CN=SwissSign Silver CA - G2
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58
+            X509v3 Authority Key Identifier: 
+                keyid:17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58
+
+            X509v3 Certificate Policies: 
+                Policy: 2.16.756.1.89.1.3.1.1
+                  CPS: http://repository.swisssign.com/
+
+SHA1 Fingerprint=9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB
+SHA256 Fingerprint=BE:6C:4D:A2:BB:B9:BA:59:B6:F3:93:97:68:37:42:46:C3:C0:05:99:3F:A9:8F:02:0D:1D:ED:BE:D4:8A:81:D5
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
+IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
+RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
+U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
+Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
+YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
+nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
+6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
+eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
+c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
+MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
+HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
+jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
+5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
+rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
+wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
+AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
+WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
+xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
+2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
+IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
+aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
+em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
+dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
+OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
+tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+### T-Systems Enterprise Services GmbH
+
+=== /C=DE/O=T-Systems Enterprise Services GmbH/OU=T-Systems Trust Center/CN=T-TeleSec GlobalRoot Class 2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct  1 10:40:14 2008 GMT
+            Not After : Oct  1 23:59:59 2033 GMT
+        Subject: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 2
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                BF:59:20:36:00:79:A0:A0:22:6B:8C:D5:F2:61:D2:B8:2C:CB:82:4A
+SHA1 Fingerprint=59:0D:2D:7D:88:4F:40:2E:61:7E:A5:62:32:17:65:CF:17:D8:94:E9
+SHA256 Fingerprint=91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
+=== /C=DE/O=T-Systems Enterprise Services GmbH/OU=T-Systems Trust Center/CN=T-TeleSec GlobalRoot Class 3
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Oct  1 10:29:56 2008 GMT
+            Not After : Oct  1 23:59:59 2033 GMT
+        Subject: C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, CN=T-TeleSec GlobalRoot Class 3
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                B5:03:F7:76:3B:61:82:6A:12:AA:18:53:EB:03:21:94:BF:FE:CE:CA
+SHA1 Fingerprint=55:A6:72:3E:CB:F2:EC:CD:C3:23:74:70:19:9D:2A:BE:11:E3:81:D1
+SHA256 Fingerprint=FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+### TAIWAN-CA
+
+=== /C=TW/O=TAIWAN-CA/OU=Root CA/CN=TWCA Global Root CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3262 (0xcbe)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Jun 27 06:28:33 2012 GMT
+            Not After : Dec 31 15:59:59 2030 GMT
+        Subject: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=9C:BB:48:53:F6:A4:F6:D3:52:A4:E8:32:52:55:60:13:F5:AD:AF:65
+SHA256 Fingerprint=59:76:90:07:F7:68:5D:0F:CD:50:87:2F:9F:95:D5:75:5A:5B:2B:45:7D:81:F3:69:2B:61:0A:98:67:2F:0E:1B
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+=== /C=TW/O=TAIWAN-CA/OU=Root CA/CN=TWCA Root Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Aug 28 07:24:33 2008 GMT
+            Not After : Dec 31 15:59:59 2030 GMT
+        Subject: C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Root Certification Authority
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                6A:38:5B:26:8D:DE:8B:5A:F2:4F:7A:54:83:19:18:E3:08:35:A6:BA
+SHA1 Fingerprint=CF:9E:87:6D:D3:EB:FC:42:26:97:A3:B5:A3:7A:A0:76:A9:06:23:48
+SHA256 Fingerprint=BF:D8:8F:E1:10:1C:41:AE:3E:80:1B:F8:BE:56:35:0E:E9:BA:D1:A6:B9:BD:51:5E:DC:5C:6D:5B:87:11:AC:44
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+### Telia Finland Oyj
+
+=== /C=FI/O=Telia Finland Oyj/CN=Telia Root CA v2
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            01:67:5f:27:d6:fe:7a:e3:e4:ac:be:09:5b:05:9e
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Nov 29 11:55:54 2018 GMT
+            Not After : Nov 29 11:55:54 2043 GMT
+        Subject: C=FI, O=Telia Finland Oyj, CN=Telia Root CA v2
+        X509v3 extensions:
+            X509v3 Authority Key Identifier: 
+                keyid:72:AC:E4:33:79:AA:45:87:F6:FD:AC:1D:9E:D6:C7:2F:86:D8:24:39
+
+            X509v3 Subject Key Identifier: 
+                72:AC:E4:33:79:AA:45:87:F6:FD:AC:1D:9E:D6:C7:2F:86:D8:24:39
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=B9:99:CD:D1:73:50:8A:C4:47:05:08:9C:8C:88:FB:BE:A0:2B:40:CD
+SHA256 Fingerprint=24:2B:69:74:2F:CB:1E:5B:2A:BF:98:89:8B:94:57:21:87:54:4E:5B:4D:99:11:78:65:73:62:1F:6A:74:B8:2C
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQx
+CzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UE
+AwwQVGVsaWEgUm9vdCBDQSB2MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1
+NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZ
+MBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ76zBq
+AMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9
+vVYiQJ3q9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9
+lRdU2HhE8Qx3FZLgmEKnpNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTOD
+n3WhUidhOPFZPY5Q4L15POdslv5e2QJltI5c0BE0312/UqeBAMN/mUWZFdUXyApT
+7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW5olWK8jjfN7j/4nlNW4o
+6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNrRBH0pUPC
+TEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6
+WT0EBXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63R
+DolUK5X6wK0dmBR4M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZI
+pEYslOqodmJHixBTB0hXbOKSTbauBcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGj
+YzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7Wxy+G2CQ5MB0GA1UdDgQWBBRy
+rOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi
+0f6X+J8wfBj5tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMM
+A8iZGok1GTzTyVR8qPAs5m4HeW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBS
+SRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+Cy748fdHif64W1lZYudogsYMVoe+K
+TTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygCQMez2P2ccGrGKMOF
+6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15h2Er
+3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMt
+Ty3EHD70sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pT
+VmBds9hCG1xLEooc6+t9xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAW
+ysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQraVplI/owd8k+BsHMYeB2F326CjYSlKA
+rBPuUBQemMc=
+-----END CERTIFICATE-----
+
+### TeliaSonera
+
+=== /O=TeliaSonera/CN=TeliaSonera Root CA v1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Oct 18 12:00:50 2007 GMT
+            Not After : Oct 18 12:00:50 2032 GMT
+        Subject: O=TeliaSonera, CN=TeliaSonera Root CA v1
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: 
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                F0:8F:59:38:00:B3:F5:8F:9A:96:0C:D5:EB:FA:7B:AA:17:E8:13:12
+SHA1 Fingerprint=43:13:BB:96:F1:D5:86:9B:C1:4E:6A:92:F6:CF:F6:34:69:87:82:37
+SHA256 Fingerprint=DD:69:36:FE:21:F8:F0:77:C1:23:A1:A5:21:C1:22:24:F7:22:55:B7:3E:03:A7:26:06:93:E8:A2:4B:0F:A3:89
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+### The Go Daddy Group, Inc.
+
+=== /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 0 (0x0)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Jun 29 17:06:20 2004 GMT
+            Not After : Jun 29 17:06:20 2034 GMT
+        Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
+            X509v3 Authority Key Identifier: 
+                keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
+                DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
+                serial:00
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+SHA1 Fingerprint=27:96:BA:E6:3F:18:01:E2:77:26:1B:A0:D7:77:70:02:8F:20:EE:E4
+SHA256 Fingerprint=C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+### The USERTRUST Network
+
+=== /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust ECC Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Feb  1 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust ECC Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                3A:E1:09:86:D4:CF:19:C2:96:76:74:49:76:DC:E0:35:C6:63:63:9A
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0
+SHA256 Fingerprint=4F:F4:60:D5:4B:9C:86:DA:BF:BC:FC:57:12:E0:40:0D:2B:ED:3F:BC:4D:4F:BD:AA:86:E0:6A:DC:D2:A9:AD:7A
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+=== /C=US/ST=New Jersey/L=Jersey City/O=The USERTRUST Network/CN=USERTrust RSA Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            01:fd:6d:30:fc:a3:ca:51:a8:1b:bc:64:0e:35:03:2d
+    Signature Algorithm: sha384WithRSAEncryption
+        Validity
+            Not Before: Feb  1 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
+SHA256 Fingerprint=E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+### Trustwave Holdings, Inc.
+
+=== /C=US/ST=Illinois/L=Chicago/O=Trustwave Holdings, Inc./CN=Trustwave Global Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            05:f7:0e:86:da:49:f3:46:35:2e:ba:b2
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Aug 23 19:34:12 2017 GMT
+            Not After : Aug 23 19:34:12 2042 GMT
+        Subject: C=US, ST=Illinois, L=Chicago, O=Trustwave Holdings, Inc., CN=Trustwave Global Certification Authority
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                99:E0:19:67:0D:62:DB:76:B3:DA:3D:B8:5B:E8:FD:42:D2:31:0E:87
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=2F:8F:36:4F:E1:58:97:44:21:59:87:A5:2A:9A:D0:69:95:26:7F:B5
+SHA256 Fingerprint=97:55:20:15:F5:DD:FC:3C:87:88:C0:06:94:45:55:40:88:94:45:00:84:F1:00:86:70:86:BC:1A:2B:B5:8D:C8
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw
+CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x
+ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1
+c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx
+OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
+SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn
+swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu
+7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8
+1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW
+80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP
+JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l
+RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw
+hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10
+coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc
+BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n
+twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud
+DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W
+0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe
+uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q
+lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB
+aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE
+sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT
+MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe
+qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh
+VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8
+h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9
+EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK
+yeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
+=== /C=US/ST=Illinois/L=Chicago/O=Trustwave Holdings, Inc./CN=Trustwave Global ECC P256 Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            0d:6a:5f:08:3f:28:5c:3e:51:95:df:5d
+    Signature Algorithm: ecdsa-with-SHA256
+        Validity
+            Not Before: Aug 23 19:35:10 2017 GMT
+            Not After : Aug 23 19:35:10 2042 GMT
+        Subject: C=US, ST=Illinois, L=Chicago, O=Trustwave Holdings, Inc., CN=Trustwave Global ECC P256 Certification Authority
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                A3:41:06:AC:90:6D:D1:4A:EB:75:A5:4A:10:99:B3:B1:A1:8B:4A:F7
+SHA1 Fingerprint=B4:90:82:DD:45:0C:BE:8B:5B:B1:66:D3:E2:A4:08:26:CD:ED:42:CF
+SHA256 Fingerprint=94:5B:BC:82:5E:A5:54:F4:89:D1:FD:51:A7:3D:DF:2E:A6:24:AC:70:19:A0:52:05:22:5C:22:A7:8C:CF:A8:B4
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN
+FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw
+CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh
+DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
+=== /C=US/ST=Illinois/L=Chicago/O=Trustwave Holdings, Inc./CN=Trustwave Global ECC P384 Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            08:bd:85:97:6c:99:27:a4:80:68:47:3b
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: Aug 23 19:36:43 2017 GMT
+            Not After : Aug 23 19:36:43 2042 GMT
+        Subject: C=US, ST=Illinois, L=Chicago, O=Trustwave Holdings, Inc., CN=Trustwave Global ECC P384 Certification Authority
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Subject Key Identifier: 
+                55:A9:84:89:D2:C1:32:BD:18:CB:6C:A6:07:4E:C8:E7:9D:BE:82:90
+SHA1 Fingerprint=E7:F3:A3:C8:CF:6F:C3:04:2E:6D:0E:67:32:C5:9E:68:95:0D:5E:D2
+SHA256 Fingerprint=55:90:38:59:C8:C0:C3:EB:B8:75:9E:CE:4E:25:57:22:5F:F5:75:8B:BD:38:EB:D4:82:76:60:1E:1B:D5:80:97
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ
+j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF
+1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G
+A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3
+AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC
+MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu
+Sw==
+-----END CERTIFICATE-----
+
+### Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK
+
+=== /C=TR/L=Gebze - Kocaeli/O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK/OU=Kamu Sertifikasyon Merkezi - Kamu SM/CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Nov 25 08:25:55 2013 GMT
+            Not After : Oct 25 08:25:55 2043 GMT
+        Subject: C=TR, L=Gebze - Kocaeli, O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK, OU=Kamu Sertifikasyon Merkezi - Kamu SM, CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                65:3F:C7:8A:86:C6:3C:DD:3C:54:5C:35:F8:3A:ED:52:0C:47:57:C8
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+SHA1 Fingerprint=31:43:64:9B:EC:CE:27:EC:ED:3A:3F:0B:8F:0D:E4:E8:91:DD:EE:CA
+SHA256 Fingerprint=46:ED:C3:68:90:46:D5:3A:45:3F:B3:10:4A:B8:0D:CA:EC:65:8B:26:60:EA:16:29:DD:7E:86:79:90:64:87:16
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+### UniTrust
+
+=== /C=CN/O=UniTrust/CN=UCA Extended Validation Root
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            4f:d2:2b:8f:f5:64:c8:33:9e:4f:34:58:66:23:70:60
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Mar 13 00:00:00 2015 GMT
+            Not After : Dec 31 00:00:00 2038 GMT
+        Subject: C=CN, O=UniTrust, CN=UCA Extended Validation Root
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                D9:74:3A:E4:30:3D:0D:F7:12:DC:7E:5A:05:9F:1E:34:9A:F7:E1:14
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Key Usage: critical
+                Digital Signature, Certificate Sign, CRL Sign
+SHA1 Fingerprint=A3:A1:B0:6F:24:61:23:4A:E3:36:A5:C2:37:FC:A6:FF:DD:F0:D7:3A
+SHA256 Fingerprint=D4:3A:F9:B3:54:73:75:5C:96:84:FC:06:D7:D8:CB:70:EE:5C:28:E7:73:FB:29:4E:B4:1E:E7:17:22:92:4D:24
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF
+eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx
+MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV
+BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog
+D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS
+sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop
+O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk
+sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi
+c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj
+VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz
+KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/
+TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G
+sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs
+1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD
+fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN
+l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ
+VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5
+c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp
+4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s
+t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj
+2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO
+vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C
+xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx
+cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM
+fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax
+-----END CERTIFICATE-----
+=== /C=CN/O=UniTrust/CN=UCA Global G2 Root
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5d:df:b1:da:5a:a3:ed:5d:be:5a:65:20:65:03:90:ef
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Mar 11 00:00:00 2016 GMT
+            Not After : Dec 31 00:00:00 2040 GMT
+        Subject: C=CN, O=UniTrust, CN=UCA Global G2 Root
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                81:C4:8C:CC:F5:E4:30:FF:A5:0C:08:5F:8C:15:67:21:74:01:DF:DF
+SHA1 Fingerprint=28:F9:78:16:19:7A:FF:18:25:18:AA:44:FE:C1:A0:CE:5C:B6:4C:8A
+SHA256 Fingerprint=9B:EA:11:C9:76:FE:01:47:64:C1:BE:56:A6:F9:14:B5:A5:60:31:7A:BD:99:88:39:33:82:E5:16:1A:A0:49:3C
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH
+bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x
+CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds
+b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr
+b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9
+kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm
+VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R
+VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc
+C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj
+tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY
+D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv
+j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl
+NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6
+iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP
+O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV
+ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj
+L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl
+1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU
+b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV
+PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj
+y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb
+EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg
+DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI
++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy
+YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX
+UB+K+wb1whnw0A==
+-----END CERTIFICATE-----
+
+### Unizeto Technologies S.A.
+
+=== /C=PL/O=Unizeto Technologies S.A./OU=Certum Certification Authority/CN=Certum Trusted Network CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 279744 (0x444c0)
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Oct 22 12:07:37 2008 GMT
+            Not After : Dec 31 12:07:37 2029 GMT
+        Subject: C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, CN=Certum Trusted Network CA
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                08:76:CD:CB:07:FF:24:F6:C5:CD:ED:BB:90:BC:E2:84:37:46:75:F7
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+SHA1 Fingerprint=07:E0:32:E0:20:B7:2C:3F:19:2F:06:28:A2:59:3A:19:A7:0F:06:9E
+SHA256 Fingerprint=5C:58:46:8D:55:F5:8E:49:7E:74:39:82:D2:B5:00:10:B6:D1:65:37:4A:CF:83:A7:D4:A3:2D:B7:68:C4:40:8E
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+### WISeKey
+
+=== /C=CH/O=WISeKey/OU=OISTE Foundation Endorsed/CN=OISTE WISeKey Global Root GB CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            76:b1:20:52:74:f0:85:87:46:b3:f8:23:1a:f6:c2:c0
+    Signature Algorithm: sha256WithRSAEncryption
+        Validity
+            Not Before: Dec  1 15:00:32 2014 GMT
+            Not After : Dec  1 15:10:31 2039 GMT
+        Subject: C=CH, O=WISeKey, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GB CA
+        X509v3 extensions:
+            X509v3 Key Usage: 
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                35:0F:C8:36:63:5E:E2:A3:EC:F9:3B:66:15:CE:51:52:E3:91:9A:3D
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=0F:F9:40:76:18:D3:D7:6A:4B:98:F0:A8:35:9E:0C:FD:27:AC:CC:ED
+SHA256 Fingerprint=6B:9C:08:E8:6E:B0:F7:67:CF:AD:65:CD:98:B6:21:49:E5:49:4A:67:F5:84:5E:7B:D1:ED:01:9F:27:B8:6B:D6
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+=== /C=CH/O=WISeKey/OU=OISTE Foundation Endorsed/CN=OISTE WISeKey Global Root GC CA
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            21:2a:56:0c:ae:da:0c:ab:40:45:bf:2b:a2:2d:3a:ea
+    Signature Algorithm: ecdsa-with-SHA384
+        Validity
+            Not Before: May  9 09:48:34 2017 GMT
+            Not After : May  9 09:58:33 2042 GMT
+        Subject: C=CH, O=WISeKey, OU=OISTE Foundation Endorsed, CN=OISTE WISeKey Global Root GC CA
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                48:87:14:AC:E3:C3:9E:90:60:3A:D7:CA:89:EE:D3:AD:8C:B4:50:66
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=E0:11:84:5E:34:DE:BE:88:81:B9:9C:F6:16:26:D1:96:1F:C3:B9:31
+SHA256 Fingerprint=85:60:F9:1C:36:24:DA:BA:95:70:B5:FE:A0:DB:E3:6F:F1:1A:83:23:BE:94:86:85:4F:B3:F3:4A:55:71:19:8D
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw
+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91
+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg
+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ
+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu
+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS
+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni
+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W
+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T
+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
+
+### XRamp Security Services Inc
+
+=== /C=US/OU=www.xrampsecurity.com/O=XRamp Security Services Inc/CN=XRamp Global Certification Authority
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad
+    Signature Algorithm: sha1WithRSAEncryption
+        Validity
+            Not Before: Nov  1 17:14:04 2004 GMT
+            Not After : Jan  1 05:37:19 2035 GMT
+        Subject: C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp Global Certification Authority
+        X509v3 extensions:
+            1.3.6.1.4.1.311.20.2: 
+                ...C.A
+            X509v3 Key Usage: 
+                Digital Signature, Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                C6:4F:A2:3D:06:63:84:09:9C:CE:62:E4:04:AC:8D:5C:B5:E9:B6:1B
+            X509v3 CRL Distribution Points: 
+
+                Full Name:
+                  URI:http://crl.xrampsecurity.com/XGCA.crl
+
+            1.3.6.1.4.1.311.21.1: 
+                ...
+SHA1 Fingerprint=B8:01:86:D1:EB:9C:86:A5:41:04:CF:30:54:F3:4C:52:B7:E5:58:C6
+SHA256 Fingerprint=CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
diff --git a/crypto/aes/aes-elf-armv4.S b/crypto/aes/aes-elf-armv4.S
new file mode 100644
index 0000000..8164b53
--- /dev/null
+++ b/crypto/aes/aes-elf-armv4.S
@@ -0,0 +1,1074 @@
+#include "arm_arch.h"
+.text
+.code	32
+
+.type	AES_Te,%object
+.align	5
+AES_Te:
+.word	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d
+.word	0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554
+.word	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d
+.word	0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a
+.word	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87
+.word	0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b
+.word	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea
+.word	0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b
+.word	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a
+.word	0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f
+.word	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108
+.word	0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f
+.word	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e
+.word	0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5
+.word	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d
+.word	0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f
+.word	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e
+.word	0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb
+.word	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce
+.word	0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497
+.word	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c
+.word	0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed
+.word	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b
+.word	0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a
+.word	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16
+.word	0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594
+.word	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81
+.word	0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3
+.word	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a
+.word	0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504
+.word	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163
+.word	0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d
+.word	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f
+.word	0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739
+.word	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47
+.word	0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395
+.word	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f
+.word	0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883
+.word	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c
+.word	0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76
+.word	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e
+.word	0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4
+.word	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6
+.word	0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b
+.word	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7
+.word	0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0
+.word	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25
+.word	0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818
+.word	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72
+.word	0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651
+.word	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21
+.word	0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85
+.word	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa
+.word	0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12
+.word	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0
+.word	0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9
+.word	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133
+.word	0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7
+.word	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920
+.word	0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a
+.word	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17
+.word	0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8
+.word	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11
+.word	0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
+@ Te4[256]
+.byte	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
+.byte	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
+.byte	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
+.byte	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
+.byte	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
+.byte	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
+.byte	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
+.byte	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
+.byte	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
+.byte	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
+.byte	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
+.byte	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
+.byte	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
+.byte	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
+.byte	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
+.byte	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
+.byte	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+@ rcon[]
+.word	0x01000000, 0x02000000, 0x04000000, 0x08000000
+.word	0x10000000, 0x20000000, 0x40000000, 0x80000000
+.word	0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0
+.size	AES_Te,.-AES_Te
+
+@ void AES_encrypt(const unsigned char *in, unsigned char *out,
+@ 		 const AES_KEY *key) {
+.global AES_encrypt
+.type   AES_encrypt,%function
+.align	5
+AES_encrypt:
+	sub	r3,pc,#8		@ AES_encrypt
+	stmdb   sp!,{r1,r4-r12,lr}
+	mov	r12,r0		@ inp
+	mov	r11,r2
+	sub	r10,r3,#AES_encrypt-AES_Te	@ Te
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_encrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	AES_encrypt,.-AES_encrypt
+
+.type   _armv4_AES_encrypt,%function
+.align	2
+_armv4_AES_encrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4-r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0,lsr#16
+	mov	r0,r0,lsr#24
+.Lenc_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Te3[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Te2[s0>>8]
+	and	r8,lr,r1
+	ldr	r6,[r10,r9,lsl#2]	@ Te1[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Te0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Te1[s1>>16]
+	ldr	r8,[r10,r8,lsl#2]	@ Te3[s1>>0]
+	ldr	r9,[r10,r9,lsl#2]	@ Te2[s1>>8]
+	eor	r0,r0,r7,ror#8
+	ldr	r1,[r10,r1,lsl#2]	@ Te0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,ror#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r6,r9,ror#8
+	and	r9,lr,r2
+	ldr	r7,[r10,r7,lsl#2]	@ Te2[s2>>8]
+	eor	r1,r1,r4,ror#24
+	ldr	r8,[r10,r8,lsl#2]	@ Te1[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te3[s2>>0]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Te0[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,ror#8
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r6,r9,ror#16
+	and	r9,lr,r3,lsr#16	@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Te3[s3>>0]
+	eor	r2,r2,r5,ror#16
+	ldr	r8,[r10,r8,lsl#2]	@ Te2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Te1[s3>>16]
+	eor	r0,r0,r7,ror#24
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Te0[s3>>24]
+	eor	r2,r2,r9,ror#8
+	ldr	r4,[r11,#-12]
+	eor	r3,r3,r6,ror#8
+
+	ldr	r5,[r11,#-8]
+	eor	r0,r0,r7
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0,lsr#16
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	.Lenc_loop
+
+	add	r10,r10,#2
+
+	ldrb	r4,[r10,r7,lsl#2]	@ Te4[s0>>0]
+	and	r7,lr,r1,lsr#16	@ i0
+	ldrb	r5,[r10,r8,lsl#2]	@ Te4[s0>>8]
+	and	r8,lr,r1
+	ldrb	r6,[r10,r9,lsl#2]	@ Te4[s0>>16]
+	and	r9,lr,r1,lsr#8
+	ldrb	r0,[r10,r0,lsl#2]	@ Te4[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s1>>16]
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s1>>0]
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s1>>8]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r1,[r10,r1,lsl#2]	@ Te4[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,lsl#8
+	and	r8,lr,r2,lsr#16	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s2>>8]
+	eor	r1,r4,r1,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s2>>16]
+	mov	r2,r2,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s2>>0]
+	eor	r0,r7,r0,lsl#8
+	ldrb	r2,[r10,r2,lsl#2]	@ Te4[s2>>24]
+	and	r7,lr,r3		@ i0
+	eor	r1,r1,r8,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,lsl#8
+	and	r9,lr,r3,lsr#16	@ i2
+	ldrb	r7,[r10,r7,lsl#2]	@ Te4[s3>>0]
+	eor	r2,r5,r2,lsl#24
+	ldrb	r8,[r10,r8,lsl#2]	@ Te4[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldrb	r9,[r10,r9,lsl#2]	@ Te4[s3>>16]
+	eor	r0,r7,r0,lsl#8
+	ldr	r7,[r11,#0]
+	ldrb	r3,[r10,r3,lsl#2]	@ Te4[s3>>24]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r2,r9,lsl#16
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#2
+	ldr	pc,[sp],#4		@ pop and return
+.size	_armv4_AES_encrypt,.-_armv4_AES_encrypt
+
+.global AES_set_encrypt_key
+.type   AES_set_encrypt_key,%function
+.align	5
+AES_set_encrypt_key:
+_armv4_AES_set_encrypt_key:
+	sub	r3,pc,#8		@ AES_set_encrypt_key
+	teq	r0,#0
+	moveq	r0,#-1
+	beq	.Labrt
+	teq	r2,#0
+	moveq	r0,#-1
+	beq	.Labrt
+
+	teq	r1,#128
+	beq	.Lok
+	teq	r1,#192
+	beq	.Lok
+	teq	r1,#256
+	movne	r0,#-1
+	bne	.Labrt
+
+.Lok:	stmdb   sp!,{r4-r12,lr}
+	sub	r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024	@ Te4
+
+	mov	r12,r0		@ inp
+	mov	lr,r1			@ bits
+	mov	r11,r2			@ key
+
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	str	r0,[r11],#16
+	orr	r3,r3,r5,lsl#16
+	str	r1,[r11,#-12]
+	orr	r3,r3,r6,lsl#24
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r11],#16
+	str	r1,[r11,#-12]
+	str	r2,[r11,#-8]
+	str	r3,[r11,#-4]
+#endif
+
+	teq	lr,#128
+	bne	.Lnot128
+	mov	r12,#10
+	str	r12,[r11,#240-16]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+
+.L128_loop:
+	and	r5,lr,r3,lsr#24
+	and	r7,lr,r3,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r5,r5,r4
+	eor	r0,r0,r5			@ rk[4]=rk[0]^...
+	eor	r1,r1,r0			@ rk[5]=rk[1]^rk[4]
+	str	r0,[r11],#16
+	eor	r2,r2,r1			@ rk[6]=rk[2]^rk[5]
+	str	r1,[r11,#-12]
+	eor	r3,r3,r2			@ rk[7]=rk[3]^rk[6]
+	str	r2,[r11,#-8]
+	subs	r12,r12,#1
+	str	r3,[r11,#-4]
+	bne	.L128_loop
+	sub	r2,r11,#176
+	b	.Ldone
+
+.Lnot128:
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r8,[r12,#19]
+	ldrb	r4,[r12,#18]
+	ldrb	r5,[r12,#17]
+	ldrb	r6,[r12,#16]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#23]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#22]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#21]
+	ldrb	r6,[r12,#20]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#16]
+	ldr	r9,[r12,#20]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	teq	lr,#192
+	bne	.Lnot192
+	mov	r12,#12
+	str	r12,[r11,#240-24]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#8
+
+.L192_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[6]=rk[0]^...
+	eor	r1,r1,r0			@ rk[7]=rk[1]^rk[6]
+	str	r0,[r11],#24
+	eor	r2,r2,r1			@ rk[8]=rk[2]^rk[7]
+	str	r1,[r11,#-20]
+	eor	r3,r3,r2			@ rk[9]=rk[3]^rk[8]
+	str	r2,[r11,#-16]
+	subs	r12,r12,#1
+	str	r3,[r11,#-12]
+	subeq	r2,r11,#216
+	beq	.Ldone
+
+	ldr	r7,[r11,#-32]
+	ldr	r8,[r11,#-28]
+	eor	r7,r7,r3			@ rk[10]=rk[4]^rk[9]
+	eor	r9,r8,r7			@ rk[11]=rk[5]^rk[10]
+	str	r7,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	.L192_loop
+
+.Lnot192:
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r8,[r12,#27]
+	ldrb	r4,[r12,#26]
+	ldrb	r5,[r12,#25]
+	ldrb	r6,[r12,#24]
+	orr	r8,r8,r4,lsl#8
+	ldrb	r9,[r12,#31]
+	orr	r8,r8,r5,lsl#16
+	ldrb	r4,[r12,#30]
+	orr	r8,r8,r6,lsl#24
+	ldrb	r5,[r12,#29]
+	ldrb	r6,[r12,#28]
+	orr	r9,r9,r4,lsl#8
+	orr	r9,r9,r5,lsl#16
+	str	r8,[r11],#8
+	orr	r9,r9,r6,lsl#24
+	str	r9,[r11,#-4]
+#else
+	ldr	r8,[r12,#24]
+	ldr	r9,[r12,#28]
+#ifdef __ARMEL__
+	rev	r8,r8
+	rev	r9,r9
+#endif
+	str	r8,[r11],#8
+	str	r9,[r11,#-4]
+#endif
+
+	mov	r12,#14
+	str	r12,[r11,#240-32]
+	add	r6,r10,#256			@ rcon
+	mov	lr,#255
+	mov	r12,#7
+
+.L256_loop:
+	and	r5,lr,r9,lsr#24
+	and	r7,lr,r9,lsr#16
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r9,lsr#8
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r9
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#24
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r6],#4			@ rcon[i++]
+	orr	r5,r5,r9,lsl#8
+	eor	r9,r5,r4
+	eor	r0,r0,r9			@ rk[8]=rk[0]^...
+	eor	r1,r1,r0			@ rk[9]=rk[1]^rk[8]
+	str	r0,[r11],#32
+	eor	r2,r2,r1			@ rk[10]=rk[2]^rk[9]
+	str	r1,[r11,#-28]
+	eor	r3,r3,r2			@ rk[11]=rk[3]^rk[10]
+	str	r2,[r11,#-24]
+	subs	r12,r12,#1
+	str	r3,[r11,#-20]
+	subeq	r2,r11,#256
+	beq	.Ldone
+
+	and	r5,lr,r3
+	and	r7,lr,r3,lsr#8
+	ldrb	r5,[r10,r5]
+	and	r8,lr,r3,lsr#16
+	ldrb	r7,[r10,r7]
+	and	r9,lr,r3,lsr#24
+	ldrb	r8,[r10,r8]
+	orr	r5,r5,r7,lsl#8
+	ldrb	r9,[r10,r9]
+	orr	r5,r5,r8,lsl#16
+	ldr	r4,[r11,#-48]
+	orr	r5,r5,r9,lsl#24
+
+	ldr	r7,[r11,#-44]
+	ldr	r8,[r11,#-40]
+	eor	r4,r4,r5			@ rk[12]=rk[4]^...
+	ldr	r9,[r11,#-36]
+	eor	r7,r7,r4			@ rk[13]=rk[5]^rk[12]
+	str	r4,[r11,#-16]
+	eor	r8,r8,r7			@ rk[14]=rk[6]^rk[13]
+	str	r7,[r11,#-12]
+	eor	r9,r9,r8			@ rk[15]=rk[7]^rk[14]
+	str	r8,[r11,#-8]
+	str	r9,[r11,#-4]
+	b	.L256_loop
+
+.Ldone:	mov	r0,#0
+	ldmia   sp!,{r4-r12,lr}
+.Labrt:	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+.size	AES_set_encrypt_key,.-AES_set_encrypt_key
+
+.global AES_set_decrypt_key
+.type   AES_set_decrypt_key,%function
+.align	5
+AES_set_decrypt_key:
+	str	lr,[sp,#-4]!            @ push lr
+	bl	_armv4_AES_set_encrypt_key
+	teq	r0,#0
+	ldrne	lr,[sp],#4              @ pop lr
+	bne	.Labrt
+
+	stmdb   sp!,{r4-r12}
+
+	ldr	r12,[r2,#240]	@ AES_set_encrypt_key preserves r2,
+	mov	r11,r2			@ which is AES_KEY *key
+	mov	r7,r2
+	add	r8,r2,r12,lsl#4
+
+.Linv:	ldr	r0,[r7]
+	ldr	r1,[r7,#4]
+	ldr	r2,[r7,#8]
+	ldr	r3,[r7,#12]
+	ldr	r4,[r8]
+	ldr	r5,[r8,#4]
+	ldr	r6,[r8,#8]
+	ldr	r9,[r8,#12]
+	str	r0,[r8],#-16
+	str	r1,[r8,#16+4]
+	str	r2,[r8,#16+8]
+	str	r3,[r8,#16+12]
+	str	r4,[r7],#16
+	str	r5,[r7,#-12]
+	str	r6,[r7,#-8]
+	str	r9,[r7,#-4]
+	teq	r7,r8
+	bne	.Linv
+	ldr	r0,[r11,#16]!		@ prefetch tp1
+	mov	r7,#0x80
+	mov	r8,#0x1b
+	orr	r7,r7,#0x8000
+	orr	r8,r8,#0x1b00
+	orr	r7,r7,r7,lsl#16
+	orr	r8,r8,r8,lsl#16
+	sub	r12,r12,#1
+	mvn	r9,r7
+	mov	r12,r12,lsl#2	@ (rounds-1)*4
+
+.Lmix:	and	r4,r0,r7
+	and	r1,r0,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r1,r4,r1,lsl#1	@ tp2
+
+	and	r4,r1,r7
+	and	r2,r1,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r2,r4,r2,lsl#1	@ tp4
+
+	and	r4,r2,r7
+	and	r3,r2,r9
+	sub	r4,r4,r4,lsr#7
+	and	r4,r4,r8
+	eor	r3,r4,r3,lsl#1	@ tp8
+
+	eor	r4,r1,r2
+	eor	r5,r0,r3		@ tp9
+	eor	r4,r4,r3		@ tpe
+	eor	r4,r4,r1,ror#24
+	eor	r4,r4,r5,ror#24	@ ^= ROTATE(tpb=tp9^tp2,8)
+	eor	r4,r4,r2,ror#16
+	eor	r4,r4,r5,ror#16	@ ^= ROTATE(tpd=tp9^tp4,16)
+	eor	r4,r4,r5,ror#8	@ ^= ROTATE(tp9,24)
+
+	ldr	r0,[r11,#4]		@ prefetch tp1
+	str	r4,[r11],#4
+	subs	r12,r12,#1
+	bne	.Lmix
+
+	mov	r0,#0
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	AES_set_decrypt_key,.-AES_set_decrypt_key
+
+.type	AES_Td,%object
+.align	5
+AES_Td:
+.word	0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96
+.word	0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393
+.word	0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25
+.word	0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f
+.word	0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1
+.word	0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6
+.word	0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da
+.word	0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844
+.word	0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd
+.word	0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4
+.word	0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45
+.word	0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94
+.word	0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7
+.word	0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a
+.word	0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5
+.word	0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c
+.word	0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1
+.word	0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a
+.word	0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75
+.word	0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051
+.word	0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46
+.word	0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff
+.word	0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77
+.word	0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb
+.word	0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000
+.word	0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e
+.word	0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927
+.word	0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a
+.word	0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e
+.word	0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16
+.word	0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d
+.word	0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8
+.word	0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd
+.word	0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34
+.word	0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163
+.word	0xd731dcca, 0x42638510, 0x13972240, 0x84c61120
+.word	0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d
+.word	0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0
+.word	0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422
+.word	0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef
+.word	0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36
+.word	0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4
+.word	0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662
+.word	0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5
+.word	0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3
+.word	0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b
+.word	0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8
+.word	0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6
+.word	0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6
+.word	0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0
+.word	0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815
+.word	0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f
+.word	0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df
+.word	0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f
+.word	0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e
+.word	0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713
+.word	0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89
+.word	0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c
+.word	0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf
+.word	0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86
+.word	0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f
+.word	0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541
+.word	0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190
+.word	0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
+@ Td4[256]
+.byte	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38
+.byte	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+.byte	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+.byte	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+.byte	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+.byte	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+.byte	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+.byte	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+.byte	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+.byte	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+.byte	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+.byte	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+.byte	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+.byte	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+.byte	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+.byte	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+.byte	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+.size	AES_Td,.-AES_Td
+
+@ void AES_decrypt(const unsigned char *in, unsigned char *out,
+@ 		 const AES_KEY *key) {
+.global AES_decrypt
+.type   AES_decrypt,%function
+.align	5
+AES_decrypt:
+	sub	r3,pc,#8		@ AES_decrypt
+	stmdb   sp!,{r1,r4-r12,lr}
+	mov	r12,r0		@ inp
+	mov	r11,r2
+	sub	r10,r3,#AES_decrypt-AES_Td		@ Td
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r0,[r12,#3]	@ load input data in endian-neutral
+	ldrb	r4,[r12,#2]	@ manner...
+	ldrb	r5,[r12,#1]
+	ldrb	r6,[r12,#0]
+	orr	r0,r0,r4,lsl#8
+	ldrb	r1,[r12,#7]
+	orr	r0,r0,r5,lsl#16
+	ldrb	r4,[r12,#6]
+	orr	r0,r0,r6,lsl#24
+	ldrb	r5,[r12,#5]
+	ldrb	r6,[r12,#4]
+	orr	r1,r1,r4,lsl#8
+	ldrb	r2,[r12,#11]
+	orr	r1,r1,r5,lsl#16
+	ldrb	r4,[r12,#10]
+	orr	r1,r1,r6,lsl#24
+	ldrb	r5,[r12,#9]
+	ldrb	r6,[r12,#8]
+	orr	r2,r2,r4,lsl#8
+	ldrb	r3,[r12,#15]
+	orr	r2,r2,r5,lsl#16
+	ldrb	r4,[r12,#14]
+	orr	r2,r2,r6,lsl#24
+	ldrb	r5,[r12,#13]
+	ldrb	r6,[r12,#12]
+	orr	r3,r3,r4,lsl#8
+	orr	r3,r3,r5,lsl#16
+	orr	r3,r3,r6,lsl#24
+#else
+	ldr	r0,[r12,#0]
+	ldr	r1,[r12,#4]
+	ldr	r2,[r12,#8]
+	ldr	r3,[r12,#12]
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+#endif
+	bl	_armv4_AES_decrypt
+
+	ldr	r12,[sp],#4		@ pop out
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+#ifdef __ARMEL__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+#endif
+	str	r0,[r12,#0]
+	str	r1,[r12,#4]
+	str	r2,[r12,#8]
+	str	r3,[r12,#12]
+#else
+	mov	r4,r0,lsr#24		@ write output in endian-neutral
+	mov	r5,r0,lsr#16		@ manner...
+	mov	r6,r0,lsr#8
+	strb	r4,[r12,#0]
+	strb	r5,[r12,#1]
+	mov	r4,r1,lsr#24
+	strb	r6,[r12,#2]
+	mov	r5,r1,lsr#16
+	strb	r0,[r12,#3]
+	mov	r6,r1,lsr#8
+	strb	r4,[r12,#4]
+	strb	r5,[r12,#5]
+	mov	r4,r2,lsr#24
+	strb	r6,[r12,#6]
+	mov	r5,r2,lsr#16
+	strb	r1,[r12,#7]
+	mov	r6,r2,lsr#8
+	strb	r4,[r12,#8]
+	strb	r5,[r12,#9]
+	mov	r4,r3,lsr#24
+	strb	r6,[r12,#10]
+	mov	r5,r3,lsr#16
+	strb	r2,[r12,#11]
+	mov	r6,r3,lsr#8
+	strb	r4,[r12,#12]
+	strb	r5,[r12,#13]
+	strb	r6,[r12,#14]
+	strb	r3,[r12,#15]
+#endif
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	AES_decrypt,.-AES_decrypt
+
+.type   _armv4_AES_decrypt,%function
+.align	2
+_armv4_AES_decrypt:
+	str	lr,[sp,#-4]!		@ push lr
+	ldmia	r11!,{r4-r7}
+	eor	r0,r0,r4
+	ldr	r12,[r11,#240-16]
+	eor	r1,r1,r5
+	eor	r2,r2,r6
+	eor	r3,r3,r7
+	sub	r12,r12,#1
+	mov	lr,#255
+
+	and	r7,lr,r0,lsr#16
+	and	r8,lr,r0,lsr#8
+	and	r9,lr,r0
+	mov	r0,r0,lsr#24
+.Ldec_loop:
+	ldr	r4,[r10,r7,lsl#2]	@ Td1[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldr	r5,[r10,r8,lsl#2]	@ Td2[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldr	r6,[r10,r9,lsl#2]	@ Td3[s0>>0]
+	and	r9,lr,r1,lsr#8
+	ldr	r0,[r10,r0,lsl#2]	@ Td0[s0>>24]
+	mov	r1,r1,lsr#24
+
+	ldr	r7,[r10,r7,lsl#2]	@ Td3[s1>>0]
+	ldr	r8,[r10,r8,lsl#2]	@ Td1[s1>>16]
+	ldr	r9,[r10,r9,lsl#2]	@ Td2[s1>>8]
+	eor	r0,r0,r7,ror#24
+	ldr	r1,[r10,r1,lsl#2]	@ Td0[s1>>24]
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r8,r5,ror#8
+	and	r8,lr,r2		@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r2,lsr#16
+	ldr	r7,[r10,r7,lsl#2]	@ Td2[s2>>8]
+	eor	r1,r1,r4,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td3[s2>>0]
+	mov	r2,r2,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td1[s2>>16]
+	eor	r0,r0,r7,ror#16
+	ldr	r2,[r10,r2,lsl#2]	@ Td0[s2>>24]
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r1,r1,r8,ror#24
+	and	r8,lr,r3,lsr#8	@ i1
+	eor	r6,r9,r6,ror#8
+	and	r9,lr,r3		@ i2
+	ldr	r7,[r10,r7,lsl#2]	@ Td1[s3>>16]
+	eor	r2,r2,r5,ror#8
+	ldr	r8,[r10,r8,lsl#2]	@ Td2[s3>>8]
+	mov	r3,r3,lsr#24
+
+	ldr	r9,[r10,r9,lsl#2]	@ Td3[s3>>0]
+	eor	r0,r0,r7,ror#8
+	ldr	r7,[r11],#16
+	eor	r1,r1,r8,ror#16
+	ldr	r3,[r10,r3,lsl#2]	@ Td0[s3>>24]
+	eor	r2,r2,r9,ror#24
+
+	ldr	r4,[r11,#-12]
+	eor	r0,r0,r7
+	ldr	r5,[r11,#-8]
+	eor	r3,r3,r6,ror#8
+	ldr	r6,[r11,#-4]
+	and	r7,lr,r0,lsr#16
+	eor	r1,r1,r4
+	and	r8,lr,r0,lsr#8
+	eor	r2,r2,r5
+	and	r9,lr,r0
+	eor	r3,r3,r6
+	mov	r0,r0,lsr#24
+
+	subs	r12,r12,#1
+	bne	.Ldec_loop
+
+	add	r10,r10,#1024
+
+	ldr	r5,[r10,#0]		@ prefetch Td4
+	ldr	r6,[r10,#32]
+	ldr	r4,[r10,#64]
+	ldr	r5,[r10,#96]
+	ldr	r6,[r10,#128]
+	ldr	r4,[r10,#160]
+	ldr	r5,[r10,#192]
+	ldr	r6,[r10,#224]
+
+	ldrb	r0,[r10,r0]		@ Td4[s0>>24]
+	ldrb	r4,[r10,r7]		@ Td4[s0>>16]
+	and	r7,lr,r1		@ i0
+	ldrb	r5,[r10,r8]		@ Td4[s0>>8]
+	and	r8,lr,r1,lsr#16
+	ldrb	r6,[r10,r9]		@ Td4[s0>>0]
+	and	r9,lr,r1,lsr#8
+
+	ldrb	r7,[r10,r7]		@ Td4[s1>>0]
+	ldrb	r1,[r10,r1,lsr#24]	@ Td4[s1>>24]
+	ldrb	r8,[r10,r8]		@ Td4[s1>>16]
+	eor	r0,r7,r0,lsl#24
+	ldrb	r9,[r10,r9]		@ Td4[s1>>8]
+	eor	r1,r4,r1,lsl#8
+	and	r7,lr,r2,lsr#8	@ i0
+	eor	r5,r5,r8,lsl#8
+	and	r8,lr,r2		@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s2>>8]
+	eor	r6,r6,r9,lsl#8
+	ldrb	r8,[r10,r8]		@ Td4[s2>>0]
+	and	r9,lr,r2,lsr#16
+
+	ldrb	r2,[r10,r2,lsr#24]	@ Td4[s2>>24]
+	eor	r0,r0,r7,lsl#8
+	ldrb	r9,[r10,r9]		@ Td4[s2>>16]
+	eor	r1,r8,r1,lsl#16
+	and	r7,lr,r3,lsr#16	@ i0
+	eor	r2,r5,r2,lsl#16
+	and	r8,lr,r3,lsr#8	@ i1
+	ldrb	r7,[r10,r7]		@ Td4[s3>>16]
+	eor	r6,r6,r9,lsl#16
+	ldrb	r8,[r10,r8]		@ Td4[s3>>8]
+	and	r9,lr,r3		@ i2
+
+	ldrb	r9,[r10,r9]		@ Td4[s3>>0]
+	ldrb	r3,[r10,r3,lsr#24]	@ Td4[s3>>24]
+	eor	r0,r0,r7,lsl#16
+	ldr	r7,[r11,#0]
+	eor	r1,r1,r8,lsl#8
+	ldr	r4,[r11,#4]
+	eor	r2,r9,r2,lsl#8
+	ldr	r5,[r11,#8]
+	eor	r3,r6,r3,lsl#24
+	ldr	r6,[r11,#12]
+
+	eor	r0,r0,r7
+	eor	r1,r1,r4
+	eor	r2,r2,r5
+	eor	r3,r3,r6
+
+	sub	r10,r10,#1024
+	ldr	pc,[sp],#4		@ pop and return
+.size	_armv4_AES_decrypt,.-_armv4_AES_decrypt
+.asciz	"AES for ARMv4, CRYPTOGAMS by "
+.align	2
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aes-elf-x86_64.S b/crypto/aes/aes-elf-x86_64.S
new file mode 100644
index 0000000..1f51a47
--- /dev/null
+++ b/crypto/aes/aes-elf-x86_64.S
@@ -0,0 +1,2558 @@
+#include "x86_arch.h"
+
+.text	
+.type	_x86_64_AES_encrypt,@function
+.align	16
+_x86_64_AES_encrypt:
+	endbr64
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	.Lenc_loop
+.align	16
+.Lenc_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	shrl	$16,%ecx
+	movzbl	%ah,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movl	12(%r15),%edx
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rdi,8),%r12d
+	xorl	1(%r14,%rbp,8),%r8d
+
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	.Lenc_loop
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	2(%r14,%rsi,8),%r10d
+	movzbl	2(%r14,%rdi,8),%r11d
+	movzbl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	2(%r14,%rsi,8),%r8d
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$65280,%edi
+	andl	$65280,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%ecx
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	shrl	$16,%edx
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+
+	andl	$65280,%esi
+	andl	$65280,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$16711680,%edi
+	andl	$16711680,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	2(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$4278190080,%edi
+	andl	$4278190080,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movl	16+12(%r15),%edx
+	movl	2(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	16+0(%r15),%eax
+
+	andl	$4278190080,%esi
+	andl	$4278190080,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+.size	_x86_64_AES_encrypt,.-_x86_64_AES_encrypt
+.type	_x86_64_AES_encrypt_compact,@function
+.align	16
+_x86_64_AES_encrypt_compact:
+	endbr64
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	.Lenc_loop_compact
+.align	16
+.Lenc_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%dh,%ebp
+	movzbl	%ah,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%dh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ah,%edi
+	shrl	$8,%ecx
+	shrl	$8,%ebx
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rcx,1),%edx
+	movzbl	(%r14,%rbx,1),%ecx
+	shll	$16,%r9d
+	shll	$16,%r13d
+	shll	$16,%ebp
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%edi
+	shll	$24,%edx
+	xorl	%esi,%r10d
+	shll	$24,%ecx
+	xorl	%edi,%r11d
+	movl	%r10d,%eax
+	movl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	.Lenc_compact_done
+	movl	%eax,%esi
+	movl	%ebx,%edi
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	movl	%esi,%r10d
+	movl	%edi,%r11d
+	shrl	$7,%r10d
+	leal	(%rax,%rax,1),%r8d
+	shrl	$7,%r11d
+	leal	(%rbx,%rbx,1),%r9d
+	subl	%r10d,%esi
+	subl	%r11d,%edi
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%ecx,%esi
+	movl	%edx,%edi
+	roll	$24,%eax
+	roll	$24,%ebx
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%esi,%r12d
+	movl	%edi,%ebp
+	rorl	$16,%r10d
+	rorl	$16,%r11d
+	shrl	$7,%r12d
+	leal	(%rcx,%rcx,1),%r8d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	shrl	$7,%ebp
+	leal	(%rdx,%rdx,1),%r9d
+	rorl	$8,%r10d
+	rorl	$8,%r11d
+	subl	%r12d,%esi
+	subl	%ebp,%edi
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%ecx,%r12d
+	movl	%edx,%ebp
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	roll	$24,%ecx
+	roll	$24,%edx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	movl	0(%r14),%esi
+	rorl	$16,%r12d
+	rorl	$16,%ebp
+	movl	64(%r14),%edi
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	movl	128(%r14),%r8d
+	rorl	$8,%r12d
+	rorl	$8,%ebp
+	movl	192(%r14),%r9d
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	jmp	.Lenc_loop_compact
+.align	16
+.Lenc_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+.size	_x86_64_AES_encrypt_compact,.-_x86_64_AES_encrypt_compact
+.globl	AES_encrypt
+.type	AES_encrypt,@function
+.align	16
+.globl	asm_AES_encrypt
+.hidden	asm_AES_encrypt
+asm_AES_encrypt:
+AES_encrypt:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+.Lenc_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	.LAES_Te+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lenc_epilogue:
+	retq
+.size	AES_encrypt,.-AES_encrypt
+.type	_x86_64_AES_decrypt,@function
+.align	16
+_x86_64_AES_decrypt:
+	endbr64
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	.Ldec_loop
+.align	16
+.Ldec_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%bh,%esi
+	shrl	$16,%eax
+	movzbl	%ch,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	movl	12(%r15),%edx
+	movzbl	%ah,%ebp
+	xorl	1(%r14,%rsi,8),%r12d
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rbp,8),%r8d
+
+	xorl	%r10d,%eax
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r12d,%ecx
+	xorl	%r11d,%ebx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	.Ldec_loop
+	leaq	2048(%r14),%r14
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	(%r14,%rsi,1),%r10d
+	movzbl	(%r14,%rdi,1),%r11d
+	movzbl	(%r14,%rbp,1),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movzbl	(%r14,%rsi,1),%r8d
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$8,%edi
+	shll	$8,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%edx
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	shrl	$16,%eax
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+
+	shll	$8,%esi
+	shll	$8,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$16,%edi
+	shll	$16,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$24,%edi
+	shll	$24,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movl	16+12(%r15),%edx
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movl	16+0(%r15),%eax
+
+	shll	$24,%esi
+	shll	$24,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	leaq	-2048(%r14),%r14
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+.size	_x86_64_AES_decrypt,.-_x86_64_AES_decrypt
+.type	_x86_64_AES_decrypt_compact,@function
+.align	16
+_x86_64_AES_decrypt_compact:
+	endbr64
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	.Ldec_loop_compact
+
+.align	16
+.Ldec_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%bh,%ebp
+	movzbl	%ch,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%bh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ch,%edi
+	shll	$16,%r9d
+	shll	$16,%r13d
+	movzbl	(%r14,%rdi,1),%ebx
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+
+	movzbl	%dh,%edi
+	shrl	$8,%eax
+	shll	$16,%ebp
+	movzbl	(%r14,%rdi,1),%ecx
+	movzbl	(%r14,%rax,1),%edx
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%ebx
+	shll	$24,%ecx
+	xorl	%esi,%r10d
+	shll	$24,%edx
+	xorl	%r11d,%ebx
+	movl	%r10d,%eax
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	.Ldec_compact_done
+
+	movq	256+0(%r14),%rsi
+	shlq	$32,%rbx
+	shlq	$32,%rdx
+	movq	256+8(%r14),%rdi
+	orq	%rbx,%rax
+	orq	%rdx,%rcx
+	movq	256+16(%r14),%rbp
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	0(%r14),%rsi
+	shrq	$32,%r8
+	shrq	$32,%r11
+	movq	64(%r14),%rdi
+	roll	$16,%r9d
+	roll	$16,%r12d
+	movq	128(%r14),%rbp
+	roll	$16,%r8d
+	roll	$16,%r11d
+	movq	192(%r14),%r10
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+	movq	256(%r14),%r13
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	jmp	.Ldec_loop_compact
+.align	16
+.Ldec_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+.size	_x86_64_AES_decrypt_compact,.-_x86_64_AES_decrypt_compact
+.globl	AES_decrypt
+.type	AES_decrypt,@function
+.align	16
+.globl	asm_AES_decrypt
+.hidden	asm_AES_decrypt
+asm_AES_decrypt:
+AES_decrypt:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+.Ldec_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	.LAES_Td+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+	shrq	$3,%rbp
+	addq	%rbp,%r14
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Ldec_epilogue:
+	retq
+.size	AES_decrypt,.-AES_decrypt
+.globl	AES_set_encrypt_key
+.type	AES_set_encrypt_key,@function
+.align	16
+AES_set_encrypt_key:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$8,%rsp
+.Lenc_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+.Lenc_key_epilogue:
+	retq
+.size	AES_set_encrypt_key,.-AES_set_encrypt_key
+
+.type	_x86_64_AES_set_encrypt_key,@function
+.align	16
+_x86_64_AES_set_encrypt_key:
+	endbr64
+	movl	%esi,%ecx
+	movq	%rdi,%rsi
+	movq	%rdx,%rdi
+
+	testq	$-1,%rsi
+	jz	.Lbadpointer
+	testq	$-1,%rdi
+	jz	.Lbadpointer
+
+	leaq	.LAES_Te(%rip),%rbp
+	leaq	2048+128(%rbp),%rbp
+
+
+	movl	0-128(%rbp),%eax
+	movl	32-128(%rbp),%ebx
+	movl	64-128(%rbp),%r8d
+	movl	96-128(%rbp),%edx
+	movl	128-128(%rbp),%eax
+	movl	160-128(%rbp),%ebx
+	movl	192-128(%rbp),%r8d
+	movl	224-128(%rbp),%edx
+
+	cmpl	$128,%ecx
+	je	.L10rounds
+	cmpl	$192,%ecx
+	je	.L12rounds
+	cmpl	$256,%ecx
+	je	.L14rounds
+	movq	$-2,%rax
+	jmp	.Lexit
+
+.L10rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rdx,8(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L10shortcut
+.align	4
+.L10loop:
+	movl	0(%rdi),%eax
+	movl	12(%rdi),%edx
+.L10shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,16(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,20(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,24(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,28(%rdi)
+	addl	$1,%ecx
+	leaq	16(%rdi),%rdi
+	cmpl	$10,%ecx
+	jl	.L10loop
+
+	movl	$10,80(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.L12rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rdx,16(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L12shortcut
+.align	4
+.L12loop:
+	movl	0(%rdi),%eax
+	movl	20(%rdi),%edx
+.L12shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,24(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,28(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,32(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,36(%rdi)
+
+	cmpl	$7,%ecx
+	je	.L12break
+	addl	$1,%ecx
+
+	xorl	16(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	leaq	24(%rdi),%rdi
+	jmp	.L12loop
+.L12break:
+	movl	$12,72(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.L14rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rcx
+	movq	24(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L14shortcut
+.align	4
+.L14loop:
+	movl	0(%rdi),%eax
+	movl	28(%rdi),%edx
+.L14shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,32(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,36(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	cmpl	$6,%ecx
+	je	.L14break
+	addl	$1,%ecx
+
+	movl	%eax,%edx
+	movl	16(%rdi),%eax
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	shll	$8,%ebx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movl	%eax,48(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,52(%rdi)
+	xorl	24(%rdi),%eax
+	movl	%eax,56(%rdi)
+	xorl	28(%rdi),%eax
+	movl	%eax,60(%rdi)
+
+	leaq	32(%rdi),%rdi
+	jmp	.L14loop
+.L14break:
+	movl	$14,48(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.Lbadpointer:
+	movq	$-1,%rax
+.Lexit:
+	retq
+.size	_x86_64_AES_set_encrypt_key,.-_x86_64_AES_set_encrypt_key
+.globl	AES_set_decrypt_key
+.type	AES_set_decrypt_key,@function
+.align	16
+AES_set_decrypt_key:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushq	%rdx
+.Ldec_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+	movq	(%rsp),%r8
+	cmpl	$0,%eax
+	jne	.Labort
+
+	movl	240(%r8),%r14d
+	xorq	%rdi,%rdi
+	leaq	(%rdi,%r14,4),%rcx
+	movq	%r8,%rsi
+	leaq	(%r8,%rcx,4),%rdi
+.align	4
+.Linvert:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	0(%rdi),%rcx
+	movq	8(%rdi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,0(%rsi)
+	movq	%rdx,8(%rsi)
+	leaq	16(%rsi),%rsi
+	leaq	-16(%rdi),%rdi
+	cmpq	%rsi,%rdi
+	jne	.Linvert
+
+	leaq	.LAES_Te+2048+1024(%rip),%rax
+
+	movq	40(%rax),%rsi
+	movq	48(%rax),%rdi
+	movq	56(%rax),%rbp
+
+	movq	%r8,%r15
+	subl	$1,%r14d
+.align	4
+.Lpermute:
+	leaq	16(%r15),%r15
+	movq	0(%r15),%rax
+	movq	8(%r15),%rcx
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+
+	shrq	$32,%r8
+	shrq	$32,%r11
+
+	roll	$16,%r9d
+	roll	$16,%r12d
+
+	roll	$16,%r8d
+	roll	$16,%r11d
+
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	movl	%eax,0(%r15)
+	movl	%ebx,4(%r15)
+	movl	%ecx,8(%r15)
+	movl	%edx,12(%r15)
+	subl	$1,%r14d
+	jnz	.Lpermute
+
+	xorq	%rax,%rax
+.Labort:
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+.Ldec_key_epilogue:
+	retq
+.size	AES_set_decrypt_key,.-AES_set_decrypt_key
+.globl	AES_cbc_encrypt
+.type	AES_cbc_encrypt,@function
+.align	16
+
+.hidden	OPENSSL_ia32cap_P
+.globl	asm_AES_cbc_encrypt
+.hidden	asm_AES_cbc_encrypt
+asm_AES_cbc_encrypt:
+AES_cbc_encrypt:
+	endbr64
+	cmpq	$0,%rdx
+	je	.Lcbc_epilogue
+	pushfq
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lcbc_prologue:
+
+	cld
+	movl	%r9d,%r9d
+
+	leaq	.LAES_Te(%rip),%r14
+	cmpq	$0,%r9
+	jne	.Lcbc_picked_te
+	leaq	.LAES_Td(%rip),%r14
+.Lcbc_picked_te:
+
+	movl	OPENSSL_ia32cap_P(%rip),%r10d
+	cmpq	$512,%rdx
+	jb	.Lcbc_slow_prologue
+	testq	$15,%rdx
+	jnz	.Lcbc_slow_prologue
+	btl	$IA32CAP_BIT0_HT,%r10d
+	jc	.Lcbc_slow_prologue
+
+
+	leaq	-88-248(%rsp),%r15
+	andq	$-64,%r15
+
+
+	movq	%r14,%r10
+	leaq	2304(%r14),%r11
+	movq	%r15,%r12
+	andq	$4095,%r10
+	andq	$4095,%r11
+	andq	$4095,%r12
+
+	cmpq	%r11,%r12
+	jb	.Lcbc_te_break_out
+	subq	%r11,%r12
+	subq	%r12,%r15
+	jmp	.Lcbc_te_ok
+.Lcbc_te_break_out:
+	subq	%r10,%r12
+	andq	$4095,%r12
+	addq	$320,%r12
+	subq	%r12,%r15
+.align	4
+.Lcbc_te_ok:
+
+	xchgq	%rsp,%r15
+
+	movq	%r15,16(%rsp)
+.Lcbc_fast_body:
+	movq	%rdi,24(%rsp)
+	movq	%rsi,32(%rsp)
+	movq	%rdx,40(%rsp)
+	movq	%rcx,48(%rsp)
+	movq	%r8,56(%rsp)
+	movl	$0,80+240(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+
+	movl	240(%r15),%eax
+
+	movq	%r15,%r10
+	subq	%r14,%r10
+	andq	$4095,%r10
+	cmpq	$2304,%r10
+	jb	.Lcbc_do_ecopy
+	cmpq	$4096-248,%r10
+	jb	.Lcbc_skip_ecopy
+.align	4
+.Lcbc_do_ecopy:
+	movq	%r15,%rsi
+	leaq	80(%rsp),%rdi
+	leaq	80(%rsp),%r15
+	movl	$30,%ecx
+.long	0x90A548F3	
+	movl	%eax,(%rdi)
+.Lcbc_skip_ecopy:
+	movq	%r15,0(%rsp)
+
+	movl	$18,%ecx
+.align	4
+.Lcbc_prefetch_te:
+	movq	0(%r14),%r10
+	movq	32(%r14),%r11
+	movq	64(%r14),%r12
+	movq	96(%r14),%r13
+	leaq	128(%r14),%r14
+	subl	$1,%ecx
+	jnz	.Lcbc_prefetch_te
+	leaq	-2304(%r14),%r14
+
+	cmpq	$0,%rbx
+	je	.LFAST_DECRYPT
+
+
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+.align	4
+.Lcbc_fast_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_encrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	movq	%r10,40(%rsp)
+	jnz	.Lcbc_fast_enc_loop
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	.Lcbc_fast_cleanup
+
+
+.align	16
+.LFAST_DECRYPT:
+	cmpq	%r8,%r9
+	je	.Lcbc_fast_dec_in_place
+
+	movq	%rbp,64(%rsp)
+.align	4
+.Lcbc_fast_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	64(%rsp),%rbp
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0(%rbp),%eax
+	xorl	4(%rbp),%ebx
+	xorl	8(%rbp),%ecx
+	xorl	12(%rbp),%edx
+	movq	%r8,%rbp
+
+	subq	$16,%r10
+	movq	%r10,40(%rsp)
+	movq	%rbp,64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jnz	.Lcbc_fast_dec_loop
+	movq	56(%rsp),%r12
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0(%r12)
+	movq	%r11,8(%r12)
+	jmp	.Lcbc_fast_cleanup
+
+.align	16
+.Lcbc_fast_dec_in_place:
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0+64(%rsp)
+	movq	%r11,8+64(%rsp)
+.align	4
+.Lcbc_fast_dec_in_place_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jz	.Lcbc_fast_dec_in_place_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	movq	%r10,40(%rsp)
+	jmp	.Lcbc_fast_dec_in_place_loop
+.Lcbc_fast_dec_in_place_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+.align	4
+.Lcbc_fast_cleanup:
+	cmpl	$0,80+240(%rsp)
+	leaq	80(%rsp),%rdi
+	je	.Lcbc_exit
+	movl	$30,%ecx
+	xorq	%rax,%rax
+.long	0x90AB48F3	
+
+	jmp	.Lcbc_exit
+
+
+.align	16
+.Lcbc_slow_prologue:
+
+	leaq	-88(%rsp),%rbp
+	andq	$-64,%rbp
+
+	leaq	-88-63(%rcx),%r10
+	subq	%rbp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rbp
+
+	xchgq	%rsp,%rbp
+
+	movq	%rbp,16(%rsp)
+.Lcbc_slow_body:
+
+
+
+
+	movq	%r8,56(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+	movq	%rdx,%r10
+
+	movl	240(%r15),%eax
+	movq	%r15,0(%rsp)
+	shll	$4,%eax
+	leaq	(%r15,%rax,1),%rax
+	movq	%rax,8(%rsp)
+
+
+	leaq	2048(%r14),%r14
+	leaq	768-8(%rsp),%rax
+	subq	%r14,%rax
+	andq	$768,%rax
+	leaq	(%r14,%rax,1),%r14
+
+	cmpq	$0,%rbx
+	je	.LSLOW_DECRYPT
+
+
+	testq	$-16,%r10
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+	jz	.Lcbc_slow_enc_tail	
+
+.align	4
+.Lcbc_slow_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	jnz	.Lcbc_slow_enc_loop
+	testq	$15,%r10
+	jnz	.Lcbc_slow_enc_tail
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	.Lcbc_exit
+
+.align	4
+.Lcbc_slow_enc_tail:
+	movq	%rax,%r11
+	movq	%rcx,%r12
+	movq	%r10,%rcx
+	movq	%r8,%rsi
+	movq	%r9,%rdi
+.long	0x9066A4F3		
+	movq	$16,%rcx
+	subq	%r10,%rcx
+	xorq	%rax,%rax
+.long	0x9066AAF3		
+	movq	%r9,%r8
+	movq	$16,%r10
+	movq	%r11,%rax
+	movq	%r12,%rcx
+	jmp	.Lcbc_slow_enc_loop	
+
+.align	16
+.LSLOW_DECRYPT:
+	shrq	$3,%rax
+	addq	%rax,%r14
+
+	movq	0(%rbp),%r11
+	movq	8(%rbp),%r12
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+.align	4
+.Lcbc_slow_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jc	.Lcbc_slow_dec_partial
+	jz	.Lcbc_slow_dec_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jmp	.Lcbc_slow_dec_loop
+.Lcbc_slow_dec_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	jmp	.Lcbc_exit
+
+.align	4
+.Lcbc_slow_dec_partial:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0+64(%rsp)
+	movl	%ebx,4+64(%rsp)
+	movl	%ecx,8+64(%rsp)
+	movl	%edx,12+64(%rsp)
+
+	movq	%r9,%rdi
+	leaq	64(%rsp),%rsi
+	leaq	16(%r10),%rcx
+.long	0x9066A4F3	
+	jmp	.Lcbc_exit
+
+.align	16
+.Lcbc_exit:
+	movq	16(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lcbc_popfq:
+	popfq
+.Lcbc_epilogue:
+	retq
+.size	AES_cbc_encrypt,.-AES_cbc_encrypt
+.section	.rodata
+.align	64
+.LAES_Te:
+.long	0xa56363c6,0xa56363c6
+.long	0x847c7cf8,0x847c7cf8
+.long	0x997777ee,0x997777ee
+.long	0x8d7b7bf6,0x8d7b7bf6
+.long	0x0df2f2ff,0x0df2f2ff
+.long	0xbd6b6bd6,0xbd6b6bd6
+.long	0xb16f6fde,0xb16f6fde
+.long	0x54c5c591,0x54c5c591
+.long	0x50303060,0x50303060
+.long	0x03010102,0x03010102
+.long	0xa96767ce,0xa96767ce
+.long	0x7d2b2b56,0x7d2b2b56
+.long	0x19fefee7,0x19fefee7
+.long	0x62d7d7b5,0x62d7d7b5
+.long	0xe6abab4d,0xe6abab4d
+.long	0x9a7676ec,0x9a7676ec
+.long	0x45caca8f,0x45caca8f
+.long	0x9d82821f,0x9d82821f
+.long	0x40c9c989,0x40c9c989
+.long	0x877d7dfa,0x877d7dfa
+.long	0x15fafaef,0x15fafaef
+.long	0xeb5959b2,0xeb5959b2
+.long	0xc947478e,0xc947478e
+.long	0x0bf0f0fb,0x0bf0f0fb
+.long	0xecadad41,0xecadad41
+.long	0x67d4d4b3,0x67d4d4b3
+.long	0xfda2a25f,0xfda2a25f
+.long	0xeaafaf45,0xeaafaf45
+.long	0xbf9c9c23,0xbf9c9c23
+.long	0xf7a4a453,0xf7a4a453
+.long	0x967272e4,0x967272e4
+.long	0x5bc0c09b,0x5bc0c09b
+.long	0xc2b7b775,0xc2b7b775
+.long	0x1cfdfde1,0x1cfdfde1
+.long	0xae93933d,0xae93933d
+.long	0x6a26264c,0x6a26264c
+.long	0x5a36366c,0x5a36366c
+.long	0x413f3f7e,0x413f3f7e
+.long	0x02f7f7f5,0x02f7f7f5
+.long	0x4fcccc83,0x4fcccc83
+.long	0x5c343468,0x5c343468
+.long	0xf4a5a551,0xf4a5a551
+.long	0x34e5e5d1,0x34e5e5d1
+.long	0x08f1f1f9,0x08f1f1f9
+.long	0x937171e2,0x937171e2
+.long	0x73d8d8ab,0x73d8d8ab
+.long	0x53313162,0x53313162
+.long	0x3f15152a,0x3f15152a
+.long	0x0c040408,0x0c040408
+.long	0x52c7c795,0x52c7c795
+.long	0x65232346,0x65232346
+.long	0x5ec3c39d,0x5ec3c39d
+.long	0x28181830,0x28181830
+.long	0xa1969637,0xa1969637
+.long	0x0f05050a,0x0f05050a
+.long	0xb59a9a2f,0xb59a9a2f
+.long	0x0907070e,0x0907070e
+.long	0x36121224,0x36121224
+.long	0x9b80801b,0x9b80801b
+.long	0x3de2e2df,0x3de2e2df
+.long	0x26ebebcd,0x26ebebcd
+.long	0x6927274e,0x6927274e
+.long	0xcdb2b27f,0xcdb2b27f
+.long	0x9f7575ea,0x9f7575ea
+.long	0x1b090912,0x1b090912
+.long	0x9e83831d,0x9e83831d
+.long	0x742c2c58,0x742c2c58
+.long	0x2e1a1a34,0x2e1a1a34
+.long	0x2d1b1b36,0x2d1b1b36
+.long	0xb26e6edc,0xb26e6edc
+.long	0xee5a5ab4,0xee5a5ab4
+.long	0xfba0a05b,0xfba0a05b
+.long	0xf65252a4,0xf65252a4
+.long	0x4d3b3b76,0x4d3b3b76
+.long	0x61d6d6b7,0x61d6d6b7
+.long	0xceb3b37d,0xceb3b37d
+.long	0x7b292952,0x7b292952
+.long	0x3ee3e3dd,0x3ee3e3dd
+.long	0x712f2f5e,0x712f2f5e
+.long	0x97848413,0x97848413
+.long	0xf55353a6,0xf55353a6
+.long	0x68d1d1b9,0x68d1d1b9
+.long	0x00000000,0x00000000
+.long	0x2cededc1,0x2cededc1
+.long	0x60202040,0x60202040
+.long	0x1ffcfce3,0x1ffcfce3
+.long	0xc8b1b179,0xc8b1b179
+.long	0xed5b5bb6,0xed5b5bb6
+.long	0xbe6a6ad4,0xbe6a6ad4
+.long	0x46cbcb8d,0x46cbcb8d
+.long	0xd9bebe67,0xd9bebe67
+.long	0x4b393972,0x4b393972
+.long	0xde4a4a94,0xde4a4a94
+.long	0xd44c4c98,0xd44c4c98
+.long	0xe85858b0,0xe85858b0
+.long	0x4acfcf85,0x4acfcf85
+.long	0x6bd0d0bb,0x6bd0d0bb
+.long	0x2aefefc5,0x2aefefc5
+.long	0xe5aaaa4f,0xe5aaaa4f
+.long	0x16fbfbed,0x16fbfbed
+.long	0xc5434386,0xc5434386
+.long	0xd74d4d9a,0xd74d4d9a
+.long	0x55333366,0x55333366
+.long	0x94858511,0x94858511
+.long	0xcf45458a,0xcf45458a
+.long	0x10f9f9e9,0x10f9f9e9
+.long	0x06020204,0x06020204
+.long	0x817f7ffe,0x817f7ffe
+.long	0xf05050a0,0xf05050a0
+.long	0x443c3c78,0x443c3c78
+.long	0xba9f9f25,0xba9f9f25
+.long	0xe3a8a84b,0xe3a8a84b
+.long	0xf35151a2,0xf35151a2
+.long	0xfea3a35d,0xfea3a35d
+.long	0xc0404080,0xc0404080
+.long	0x8a8f8f05,0x8a8f8f05
+.long	0xad92923f,0xad92923f
+.long	0xbc9d9d21,0xbc9d9d21
+.long	0x48383870,0x48383870
+.long	0x04f5f5f1,0x04f5f5f1
+.long	0xdfbcbc63,0xdfbcbc63
+.long	0xc1b6b677,0xc1b6b677
+.long	0x75dadaaf,0x75dadaaf
+.long	0x63212142,0x63212142
+.long	0x30101020,0x30101020
+.long	0x1affffe5,0x1affffe5
+.long	0x0ef3f3fd,0x0ef3f3fd
+.long	0x6dd2d2bf,0x6dd2d2bf
+.long	0x4ccdcd81,0x4ccdcd81
+.long	0x140c0c18,0x140c0c18
+.long	0x35131326,0x35131326
+.long	0x2fececc3,0x2fececc3
+.long	0xe15f5fbe,0xe15f5fbe
+.long	0xa2979735,0xa2979735
+.long	0xcc444488,0xcc444488
+.long	0x3917172e,0x3917172e
+.long	0x57c4c493,0x57c4c493
+.long	0xf2a7a755,0xf2a7a755
+.long	0x827e7efc,0x827e7efc
+.long	0x473d3d7a,0x473d3d7a
+.long	0xac6464c8,0xac6464c8
+.long	0xe75d5dba,0xe75d5dba
+.long	0x2b191932,0x2b191932
+.long	0x957373e6,0x957373e6
+.long	0xa06060c0,0xa06060c0
+.long	0x98818119,0x98818119
+.long	0xd14f4f9e,0xd14f4f9e
+.long	0x7fdcdca3,0x7fdcdca3
+.long	0x66222244,0x66222244
+.long	0x7e2a2a54,0x7e2a2a54
+.long	0xab90903b,0xab90903b
+.long	0x8388880b,0x8388880b
+.long	0xca46468c,0xca46468c
+.long	0x29eeeec7,0x29eeeec7
+.long	0xd3b8b86b,0xd3b8b86b
+.long	0x3c141428,0x3c141428
+.long	0x79dedea7,0x79dedea7
+.long	0xe25e5ebc,0xe25e5ebc
+.long	0x1d0b0b16,0x1d0b0b16
+.long	0x76dbdbad,0x76dbdbad
+.long	0x3be0e0db,0x3be0e0db
+.long	0x56323264,0x56323264
+.long	0x4e3a3a74,0x4e3a3a74
+.long	0x1e0a0a14,0x1e0a0a14
+.long	0xdb494992,0xdb494992
+.long	0x0a06060c,0x0a06060c
+.long	0x6c242448,0x6c242448
+.long	0xe45c5cb8,0xe45c5cb8
+.long	0x5dc2c29f,0x5dc2c29f
+.long	0x6ed3d3bd,0x6ed3d3bd
+.long	0xefacac43,0xefacac43
+.long	0xa66262c4,0xa66262c4
+.long	0xa8919139,0xa8919139
+.long	0xa4959531,0xa4959531
+.long	0x37e4e4d3,0x37e4e4d3
+.long	0x8b7979f2,0x8b7979f2
+.long	0x32e7e7d5,0x32e7e7d5
+.long	0x43c8c88b,0x43c8c88b
+.long	0x5937376e,0x5937376e
+.long	0xb76d6dda,0xb76d6dda
+.long	0x8c8d8d01,0x8c8d8d01
+.long	0x64d5d5b1,0x64d5d5b1
+.long	0xd24e4e9c,0xd24e4e9c
+.long	0xe0a9a949,0xe0a9a949
+.long	0xb46c6cd8,0xb46c6cd8
+.long	0xfa5656ac,0xfa5656ac
+.long	0x07f4f4f3,0x07f4f4f3
+.long	0x25eaeacf,0x25eaeacf
+.long	0xaf6565ca,0xaf6565ca
+.long	0x8e7a7af4,0x8e7a7af4
+.long	0xe9aeae47,0xe9aeae47
+.long	0x18080810,0x18080810
+.long	0xd5baba6f,0xd5baba6f
+.long	0x887878f0,0x887878f0
+.long	0x6f25254a,0x6f25254a
+.long	0x722e2e5c,0x722e2e5c
+.long	0x241c1c38,0x241c1c38
+.long	0xf1a6a657,0xf1a6a657
+.long	0xc7b4b473,0xc7b4b473
+.long	0x51c6c697,0x51c6c697
+.long	0x23e8e8cb,0x23e8e8cb
+.long	0x7cdddda1,0x7cdddda1
+.long	0x9c7474e8,0x9c7474e8
+.long	0x211f1f3e,0x211f1f3e
+.long	0xdd4b4b96,0xdd4b4b96
+.long	0xdcbdbd61,0xdcbdbd61
+.long	0x868b8b0d,0x868b8b0d
+.long	0x858a8a0f,0x858a8a0f
+.long	0x907070e0,0x907070e0
+.long	0x423e3e7c,0x423e3e7c
+.long	0xc4b5b571,0xc4b5b571
+.long	0xaa6666cc,0xaa6666cc
+.long	0xd8484890,0xd8484890
+.long	0x05030306,0x05030306
+.long	0x01f6f6f7,0x01f6f6f7
+.long	0x120e0e1c,0x120e0e1c
+.long	0xa36161c2,0xa36161c2
+.long	0x5f35356a,0x5f35356a
+.long	0xf95757ae,0xf95757ae
+.long	0xd0b9b969,0xd0b9b969
+.long	0x91868617,0x91868617
+.long	0x58c1c199,0x58c1c199
+.long	0x271d1d3a,0x271d1d3a
+.long	0xb99e9e27,0xb99e9e27
+.long	0x38e1e1d9,0x38e1e1d9
+.long	0x13f8f8eb,0x13f8f8eb
+.long	0xb398982b,0xb398982b
+.long	0x33111122,0x33111122
+.long	0xbb6969d2,0xbb6969d2
+.long	0x70d9d9a9,0x70d9d9a9
+.long	0x898e8e07,0x898e8e07
+.long	0xa7949433,0xa7949433
+.long	0xb69b9b2d,0xb69b9b2d
+.long	0x221e1e3c,0x221e1e3c
+.long	0x92878715,0x92878715
+.long	0x20e9e9c9,0x20e9e9c9
+.long	0x49cece87,0x49cece87
+.long	0xff5555aa,0xff5555aa
+.long	0x78282850,0x78282850
+.long	0x7adfdfa5,0x7adfdfa5
+.long	0x8f8c8c03,0x8f8c8c03
+.long	0xf8a1a159,0xf8a1a159
+.long	0x80898909,0x80898909
+.long	0x170d0d1a,0x170d0d1a
+.long	0xdabfbf65,0xdabfbf65
+.long	0x31e6e6d7,0x31e6e6d7
+.long	0xc6424284,0xc6424284
+.long	0xb86868d0,0xb86868d0
+.long	0xc3414182,0xc3414182
+.long	0xb0999929,0xb0999929
+.long	0x772d2d5a,0x772d2d5a
+.long	0x110f0f1e,0x110f0f1e
+.long	0xcbb0b07b,0xcbb0b07b
+.long	0xfc5454a8,0xfc5454a8
+.long	0xd6bbbb6d,0xd6bbbb6d
+.long	0x3a16162c,0x3a16162c
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.long	0x00000001, 0x00000002, 0x00000004, 0x00000008
+.long	0x00000010, 0x00000020, 0x00000040, 0x00000080
+.long	0x0000001b, 0x00000036, 0x80808080, 0x80808080
+.long	0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b
+.align	64
+.LAES_Td:
+.long	0x50a7f451,0x50a7f451
+.long	0x5365417e,0x5365417e
+.long	0xc3a4171a,0xc3a4171a
+.long	0x965e273a,0x965e273a
+.long	0xcb6bab3b,0xcb6bab3b
+.long	0xf1459d1f,0xf1459d1f
+.long	0xab58faac,0xab58faac
+.long	0x9303e34b,0x9303e34b
+.long	0x55fa3020,0x55fa3020
+.long	0xf66d76ad,0xf66d76ad
+.long	0x9176cc88,0x9176cc88
+.long	0x254c02f5,0x254c02f5
+.long	0xfcd7e54f,0xfcd7e54f
+.long	0xd7cb2ac5,0xd7cb2ac5
+.long	0x80443526,0x80443526
+.long	0x8fa362b5,0x8fa362b5
+.long	0x495ab1de,0x495ab1de
+.long	0x671bba25,0x671bba25
+.long	0x980eea45,0x980eea45
+.long	0xe1c0fe5d,0xe1c0fe5d
+.long	0x02752fc3,0x02752fc3
+.long	0x12f04c81,0x12f04c81
+.long	0xa397468d,0xa397468d
+.long	0xc6f9d36b,0xc6f9d36b
+.long	0xe75f8f03,0xe75f8f03
+.long	0x959c9215,0x959c9215
+.long	0xeb7a6dbf,0xeb7a6dbf
+.long	0xda595295,0xda595295
+.long	0x2d83bed4,0x2d83bed4
+.long	0xd3217458,0xd3217458
+.long	0x2969e049,0x2969e049
+.long	0x44c8c98e,0x44c8c98e
+.long	0x6a89c275,0x6a89c275
+.long	0x78798ef4,0x78798ef4
+.long	0x6b3e5899,0x6b3e5899
+.long	0xdd71b927,0xdd71b927
+.long	0xb64fe1be,0xb64fe1be
+.long	0x17ad88f0,0x17ad88f0
+.long	0x66ac20c9,0x66ac20c9
+.long	0xb43ace7d,0xb43ace7d
+.long	0x184adf63,0x184adf63
+.long	0x82311ae5,0x82311ae5
+.long	0x60335197,0x60335197
+.long	0x457f5362,0x457f5362
+.long	0xe07764b1,0xe07764b1
+.long	0x84ae6bbb,0x84ae6bbb
+.long	0x1ca081fe,0x1ca081fe
+.long	0x942b08f9,0x942b08f9
+.long	0x58684870,0x58684870
+.long	0x19fd458f,0x19fd458f
+.long	0x876cde94,0x876cde94
+.long	0xb7f87b52,0xb7f87b52
+.long	0x23d373ab,0x23d373ab
+.long	0xe2024b72,0xe2024b72
+.long	0x578f1fe3,0x578f1fe3
+.long	0x2aab5566,0x2aab5566
+.long	0x0728ebb2,0x0728ebb2
+.long	0x03c2b52f,0x03c2b52f
+.long	0x9a7bc586,0x9a7bc586
+.long	0xa50837d3,0xa50837d3
+.long	0xf2872830,0xf2872830
+.long	0xb2a5bf23,0xb2a5bf23
+.long	0xba6a0302,0xba6a0302
+.long	0x5c8216ed,0x5c8216ed
+.long	0x2b1ccf8a,0x2b1ccf8a
+.long	0x92b479a7,0x92b479a7
+.long	0xf0f207f3,0xf0f207f3
+.long	0xa1e2694e,0xa1e2694e
+.long	0xcdf4da65,0xcdf4da65
+.long	0xd5be0506,0xd5be0506
+.long	0x1f6234d1,0x1f6234d1
+.long	0x8afea6c4,0x8afea6c4
+.long	0x9d532e34,0x9d532e34
+.long	0xa055f3a2,0xa055f3a2
+.long	0x32e18a05,0x32e18a05
+.long	0x75ebf6a4,0x75ebf6a4
+.long	0x39ec830b,0x39ec830b
+.long	0xaaef6040,0xaaef6040
+.long	0x069f715e,0x069f715e
+.long	0x51106ebd,0x51106ebd
+.long	0xf98a213e,0xf98a213e
+.long	0x3d06dd96,0x3d06dd96
+.long	0xae053edd,0xae053edd
+.long	0x46bde64d,0x46bde64d
+.long	0xb58d5491,0xb58d5491
+.long	0x055dc471,0x055dc471
+.long	0x6fd40604,0x6fd40604
+.long	0xff155060,0xff155060
+.long	0x24fb9819,0x24fb9819
+.long	0x97e9bdd6,0x97e9bdd6
+.long	0xcc434089,0xcc434089
+.long	0x779ed967,0x779ed967
+.long	0xbd42e8b0,0xbd42e8b0
+.long	0x888b8907,0x888b8907
+.long	0x385b19e7,0x385b19e7
+.long	0xdbeec879,0xdbeec879
+.long	0x470a7ca1,0x470a7ca1
+.long	0xe90f427c,0xe90f427c
+.long	0xc91e84f8,0xc91e84f8
+.long	0x00000000,0x00000000
+.long	0x83868009,0x83868009
+.long	0x48ed2b32,0x48ed2b32
+.long	0xac70111e,0xac70111e
+.long	0x4e725a6c,0x4e725a6c
+.long	0xfbff0efd,0xfbff0efd
+.long	0x5638850f,0x5638850f
+.long	0x1ed5ae3d,0x1ed5ae3d
+.long	0x27392d36,0x27392d36
+.long	0x64d90f0a,0x64d90f0a
+.long	0x21a65c68,0x21a65c68
+.long	0xd1545b9b,0xd1545b9b
+.long	0x3a2e3624,0x3a2e3624
+.long	0xb1670a0c,0xb1670a0c
+.long	0x0fe75793,0x0fe75793
+.long	0xd296eeb4,0xd296eeb4
+.long	0x9e919b1b,0x9e919b1b
+.long	0x4fc5c080,0x4fc5c080
+.long	0xa220dc61,0xa220dc61
+.long	0x694b775a,0x694b775a
+.long	0x161a121c,0x161a121c
+.long	0x0aba93e2,0x0aba93e2
+.long	0xe52aa0c0,0xe52aa0c0
+.long	0x43e0223c,0x43e0223c
+.long	0x1d171b12,0x1d171b12
+.long	0x0b0d090e,0x0b0d090e
+.long	0xadc78bf2,0xadc78bf2
+.long	0xb9a8b62d,0xb9a8b62d
+.long	0xc8a91e14,0xc8a91e14
+.long	0x8519f157,0x8519f157
+.long	0x4c0775af,0x4c0775af
+.long	0xbbdd99ee,0xbbdd99ee
+.long	0xfd607fa3,0xfd607fa3
+.long	0x9f2601f7,0x9f2601f7
+.long	0xbcf5725c,0xbcf5725c
+.long	0xc53b6644,0xc53b6644
+.long	0x347efb5b,0x347efb5b
+.long	0x7629438b,0x7629438b
+.long	0xdcc623cb,0xdcc623cb
+.long	0x68fcedb6,0x68fcedb6
+.long	0x63f1e4b8,0x63f1e4b8
+.long	0xcadc31d7,0xcadc31d7
+.long	0x10856342,0x10856342
+.long	0x40229713,0x40229713
+.long	0x2011c684,0x2011c684
+.long	0x7d244a85,0x7d244a85
+.long	0xf83dbbd2,0xf83dbbd2
+.long	0x1132f9ae,0x1132f9ae
+.long	0x6da129c7,0x6da129c7
+.long	0x4b2f9e1d,0x4b2f9e1d
+.long	0xf330b2dc,0xf330b2dc
+.long	0xec52860d,0xec52860d
+.long	0xd0e3c177,0xd0e3c177
+.long	0x6c16b32b,0x6c16b32b
+.long	0x99b970a9,0x99b970a9
+.long	0xfa489411,0xfa489411
+.long	0x2264e947,0x2264e947
+.long	0xc48cfca8,0xc48cfca8
+.long	0x1a3ff0a0,0x1a3ff0a0
+.long	0xd82c7d56,0xd82c7d56
+.long	0xef903322,0xef903322
+.long	0xc74e4987,0xc74e4987
+.long	0xc1d138d9,0xc1d138d9
+.long	0xfea2ca8c,0xfea2ca8c
+.long	0x360bd498,0x360bd498
+.long	0xcf81f5a6,0xcf81f5a6
+.long	0x28de7aa5,0x28de7aa5
+.long	0x268eb7da,0x268eb7da
+.long	0xa4bfad3f,0xa4bfad3f
+.long	0xe49d3a2c,0xe49d3a2c
+.long	0x0d927850,0x0d927850
+.long	0x9bcc5f6a,0x9bcc5f6a
+.long	0x62467e54,0x62467e54
+.long	0xc2138df6,0xc2138df6
+.long	0xe8b8d890,0xe8b8d890
+.long	0x5ef7392e,0x5ef7392e
+.long	0xf5afc382,0xf5afc382
+.long	0xbe805d9f,0xbe805d9f
+.long	0x7c93d069,0x7c93d069
+.long	0xa92dd56f,0xa92dd56f
+.long	0xb31225cf,0xb31225cf
+.long	0x3b99acc8,0x3b99acc8
+.long	0xa77d1810,0xa77d1810
+.long	0x6e639ce8,0x6e639ce8
+.long	0x7bbb3bdb,0x7bbb3bdb
+.long	0x097826cd,0x097826cd
+.long	0xf418596e,0xf418596e
+.long	0x01b79aec,0x01b79aec
+.long	0xa89a4f83,0xa89a4f83
+.long	0x656e95e6,0x656e95e6
+.long	0x7ee6ffaa,0x7ee6ffaa
+.long	0x08cfbc21,0x08cfbc21
+.long	0xe6e815ef,0xe6e815ef
+.long	0xd99be7ba,0xd99be7ba
+.long	0xce366f4a,0xce366f4a
+.long	0xd4099fea,0xd4099fea
+.long	0xd67cb029,0xd67cb029
+.long	0xafb2a431,0xafb2a431
+.long	0x31233f2a,0x31233f2a
+.long	0x3094a5c6,0x3094a5c6
+.long	0xc066a235,0xc066a235
+.long	0x37bc4e74,0x37bc4e74
+.long	0xa6ca82fc,0xa6ca82fc
+.long	0xb0d090e0,0xb0d090e0
+.long	0x15d8a733,0x15d8a733
+.long	0x4a9804f1,0x4a9804f1
+.long	0xf7daec41,0xf7daec41
+.long	0x0e50cd7f,0x0e50cd7f
+.long	0x2ff69117,0x2ff69117
+.long	0x8dd64d76,0x8dd64d76
+.long	0x4db0ef43,0x4db0ef43
+.long	0x544daacc,0x544daacc
+.long	0xdf0496e4,0xdf0496e4
+.long	0xe3b5d19e,0xe3b5d19e
+.long	0x1b886a4c,0x1b886a4c
+.long	0xb81f2cc1,0xb81f2cc1
+.long	0x7f516546,0x7f516546
+.long	0x04ea5e9d,0x04ea5e9d
+.long	0x5d358c01,0x5d358c01
+.long	0x737487fa,0x737487fa
+.long	0x2e410bfb,0x2e410bfb
+.long	0x5a1d67b3,0x5a1d67b3
+.long	0x52d2db92,0x52d2db92
+.long	0x335610e9,0x335610e9
+.long	0x1347d66d,0x1347d66d
+.long	0x8c61d79a,0x8c61d79a
+.long	0x7a0ca137,0x7a0ca137
+.long	0x8e14f859,0x8e14f859
+.long	0x893c13eb,0x893c13eb
+.long	0xee27a9ce,0xee27a9ce
+.long	0x35c961b7,0x35c961b7
+.long	0xede51ce1,0xede51ce1
+.long	0x3cb1477a,0x3cb1477a
+.long	0x59dfd29c,0x59dfd29c
+.long	0x3f73f255,0x3f73f255
+.long	0x79ce1418,0x79ce1418
+.long	0xbf37c773,0xbf37c773
+.long	0xeacdf753,0xeacdf753
+.long	0x5baafd5f,0x5baafd5f
+.long	0x146f3ddf,0x146f3ddf
+.long	0x86db4478,0x86db4478
+.long	0x81f3afca,0x81f3afca
+.long	0x3ec468b9,0x3ec468b9
+.long	0x2c342438,0x2c342438
+.long	0x5f40a3c2,0x5f40a3c2
+.long	0x72c31d16,0x72c31d16
+.long	0x0c25e2bc,0x0c25e2bc
+.long	0x8b493c28,0x8b493c28
+.long	0x41950dff,0x41950dff
+.long	0x7101a839,0x7101a839
+.long	0xdeb30c08,0xdeb30c08
+.long	0x9ce4b4d8,0x9ce4b4d8
+.long	0x90c15664,0x90c15664
+.long	0x6184cb7b,0x6184cb7b
+.long	0x70b632d5,0x70b632d5
+.long	0x745c6c48,0x745c6c48
+.long	0x4257b8d0,0x4257b8d0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.align	64
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aes-macosx-x86_64.S b/crypto/aes/aes-macosx-x86_64.S
new file mode 100644
index 0000000..8a9c36e
--- /dev/null
+++ b/crypto/aes/aes-macosx-x86_64.S
@@ -0,0 +1,2544 @@
+#include "x86_arch.h"
+
+.text	
+
+.p2align	4
+_x86_64_AES_encrypt:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	L$enc_loop
+.p2align	4
+L$enc_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	shrl	$16,%ecx
+	movzbl	%ah,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movl	12(%r15),%edx
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rdi,8),%r12d
+	xorl	1(%r14,%rbp,8),%r8d
+
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	L$enc_loop
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	2(%r14,%rsi,8),%r10d
+	movzbl	2(%r14,%rdi,8),%r11d
+	movzbl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	2(%r14,%rsi,8),%r8d
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$65280,%edi
+	andl	$65280,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%ecx
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	shrl	$16,%edx
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+
+	andl	$65280,%esi
+	andl	$65280,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$16711680,%edi
+	andl	$16711680,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	2(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$4278190080,%edi
+	andl	$4278190080,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movl	16+12(%r15),%edx
+	movl	2(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	16+0(%r15),%eax
+
+	andl	$4278190080,%esi
+	andl	$4278190080,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+
+
+.p2align	4
+_x86_64_AES_encrypt_compact:
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	L$enc_loop_compact
+.p2align	4
+L$enc_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%dh,%ebp
+	movzbl	%ah,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%dh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ah,%edi
+	shrl	$8,%ecx
+	shrl	$8,%ebx
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rcx,1),%edx
+	movzbl	(%r14,%rbx,1),%ecx
+	shll	$16,%r9d
+	shll	$16,%r13d
+	shll	$16,%ebp
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%edi
+	shll	$24,%edx
+	xorl	%esi,%r10d
+	shll	$24,%ecx
+	xorl	%edi,%r11d
+	movl	%r10d,%eax
+	movl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	L$enc_compact_done
+	movl	%eax,%esi
+	movl	%ebx,%edi
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	movl	%esi,%r10d
+	movl	%edi,%r11d
+	shrl	$7,%r10d
+	leal	(%rax,%rax,1),%r8d
+	shrl	$7,%r11d
+	leal	(%rbx,%rbx,1),%r9d
+	subl	%r10d,%esi
+	subl	%r11d,%edi
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%ecx,%esi
+	movl	%edx,%edi
+	roll	$24,%eax
+	roll	$24,%ebx
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%esi,%r12d
+	movl	%edi,%ebp
+	rorl	$16,%r10d
+	rorl	$16,%r11d
+	shrl	$7,%r12d
+	leal	(%rcx,%rcx,1),%r8d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	shrl	$7,%ebp
+	leal	(%rdx,%rdx,1),%r9d
+	rorl	$8,%r10d
+	rorl	$8,%r11d
+	subl	%r12d,%esi
+	subl	%ebp,%edi
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%ecx,%r12d
+	movl	%edx,%ebp
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	roll	$24,%ecx
+	roll	$24,%edx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	movl	0(%r14),%esi
+	rorl	$16,%r12d
+	rorl	$16,%ebp
+	movl	64(%r14),%edi
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	movl	128(%r14),%r8d
+	rorl	$8,%r12d
+	rorl	$8,%ebp
+	movl	192(%r14),%r9d
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	jmp	L$enc_loop_compact
+.p2align	4
+L$enc_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+
+.globl	_AES_encrypt
+
+.p2align	4
+.globl	_asm_AES_encrypt
+.private_extern	_asm_AES_encrypt
+_asm_AES_encrypt:
+_AES_encrypt:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+L$enc_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	L$AES_Te+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$enc_epilogue:
+	retq
+
+
+.p2align	4
+_x86_64_AES_decrypt:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	L$dec_loop
+.p2align	4
+L$dec_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%bh,%esi
+	shrl	$16,%eax
+	movzbl	%ch,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	movl	12(%r15),%edx
+	movzbl	%ah,%ebp
+	xorl	1(%r14,%rsi,8),%r12d
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rbp,8),%r8d
+
+	xorl	%r10d,%eax
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r12d,%ecx
+	xorl	%r11d,%ebx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	L$dec_loop
+	leaq	2048(%r14),%r14
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	(%r14,%rsi,1),%r10d
+	movzbl	(%r14,%rdi,1),%r11d
+	movzbl	(%r14,%rbp,1),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movzbl	(%r14,%rsi,1),%r8d
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$8,%edi
+	shll	$8,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%edx
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	shrl	$16,%eax
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+
+	shll	$8,%esi
+	shll	$8,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$16,%edi
+	shll	$16,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$24,%edi
+	shll	$24,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movl	16+12(%r15),%edx
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movl	16+0(%r15),%eax
+
+	shll	$24,%esi
+	shll	$24,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	leaq	-2048(%r14),%r14
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+
+
+.p2align	4
+_x86_64_AES_decrypt_compact:
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	L$dec_loop_compact
+
+.p2align	4
+L$dec_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%bh,%ebp
+	movzbl	%ch,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%bh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ch,%edi
+	shll	$16,%r9d
+	shll	$16,%r13d
+	movzbl	(%r14,%rdi,1),%ebx
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+
+	movzbl	%dh,%edi
+	shrl	$8,%eax
+	shll	$16,%ebp
+	movzbl	(%r14,%rdi,1),%ecx
+	movzbl	(%r14,%rax,1),%edx
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%ebx
+	shll	$24,%ecx
+	xorl	%esi,%r10d
+	shll	$24,%edx
+	xorl	%r11d,%ebx
+	movl	%r10d,%eax
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	L$dec_compact_done
+
+	movq	256+0(%r14),%rsi
+	shlq	$32,%rbx
+	shlq	$32,%rdx
+	movq	256+8(%r14),%rdi
+	orq	%rbx,%rax
+	orq	%rdx,%rcx
+	movq	256+16(%r14),%rbp
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	0(%r14),%rsi
+	shrq	$32,%r8
+	shrq	$32,%r11
+	movq	64(%r14),%rdi
+	roll	$16,%r9d
+	roll	$16,%r12d
+	movq	128(%r14),%rbp
+	roll	$16,%r8d
+	roll	$16,%r11d
+	movq	192(%r14),%r10
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+	movq	256(%r14),%r13
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	jmp	L$dec_loop_compact
+.p2align	4
+L$dec_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+
+.globl	_AES_decrypt
+
+.p2align	4
+.globl	_asm_AES_decrypt
+.private_extern	_asm_AES_decrypt
+_asm_AES_decrypt:
+_AES_decrypt:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+L$dec_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	L$AES_Td+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+	shrq	$3,%rbp
+	addq	%rbp,%r14
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$dec_epilogue:
+	retq
+
+.globl	_AES_set_encrypt_key
+
+.p2align	4
+_AES_set_encrypt_key:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$8,%rsp
+L$enc_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+L$enc_key_epilogue:
+	retq
+
+
+
+.p2align	4
+_x86_64_AES_set_encrypt_key:
+	movl	%esi,%ecx
+	movq	%rdi,%rsi
+	movq	%rdx,%rdi
+
+	testq	$-1,%rsi
+	jz	L$badpointer
+	testq	$-1,%rdi
+	jz	L$badpointer
+
+	leaq	L$AES_Te(%rip),%rbp
+	leaq	2048+128(%rbp),%rbp
+
+
+	movl	0-128(%rbp),%eax
+	movl	32-128(%rbp),%ebx
+	movl	64-128(%rbp),%r8d
+	movl	96-128(%rbp),%edx
+	movl	128-128(%rbp),%eax
+	movl	160-128(%rbp),%ebx
+	movl	192-128(%rbp),%r8d
+	movl	224-128(%rbp),%edx
+
+	cmpl	$128,%ecx
+	je	L$10rounds
+	cmpl	$192,%ecx
+	je	L$12rounds
+	cmpl	$256,%ecx
+	je	L$14rounds
+	movq	$-2,%rax
+	jmp	L$exit
+
+L$10rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rdx,8(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	L$10shortcut
+.p2align	2
+L$10loop:
+	movl	0(%rdi),%eax
+	movl	12(%rdi),%edx
+L$10shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,16(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,20(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,24(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,28(%rdi)
+	addl	$1,%ecx
+	leaq	16(%rdi),%rdi
+	cmpl	$10,%ecx
+	jl	L$10loop
+
+	movl	$10,80(%rdi)
+	xorq	%rax,%rax
+	jmp	L$exit
+
+L$12rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rdx,16(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	L$12shortcut
+.p2align	2
+L$12loop:
+	movl	0(%rdi),%eax
+	movl	20(%rdi),%edx
+L$12shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,24(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,28(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,32(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,36(%rdi)
+
+	cmpl	$7,%ecx
+	je	L$12break
+	addl	$1,%ecx
+
+	xorl	16(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	leaq	24(%rdi),%rdi
+	jmp	L$12loop
+L$12break:
+	movl	$12,72(%rdi)
+	xorq	%rax,%rax
+	jmp	L$exit
+
+L$14rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rcx
+	movq	24(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	L$14shortcut
+.p2align	2
+L$14loop:
+	movl	0(%rdi),%eax
+	movl	28(%rdi),%edx
+L$14shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,32(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,36(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	cmpl	$6,%ecx
+	je	L$14break
+	addl	$1,%ecx
+
+	movl	%eax,%edx
+	movl	16(%rdi),%eax
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	shll	$8,%ebx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movl	%eax,48(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,52(%rdi)
+	xorl	24(%rdi),%eax
+	movl	%eax,56(%rdi)
+	xorl	28(%rdi),%eax
+	movl	%eax,60(%rdi)
+
+	leaq	32(%rdi),%rdi
+	jmp	L$14loop
+L$14break:
+	movl	$14,48(%rdi)
+	xorq	%rax,%rax
+	jmp	L$exit
+
+L$badpointer:
+	movq	$-1,%rax
+L$exit:
+	retq
+
+.globl	_AES_set_decrypt_key
+
+.p2align	4
+_AES_set_decrypt_key:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushq	%rdx
+L$dec_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+	movq	(%rsp),%r8
+	cmpl	$0,%eax
+	jne	L$abort
+
+	movl	240(%r8),%r14d
+	xorq	%rdi,%rdi
+	leaq	(%rdi,%r14,4),%rcx
+	movq	%r8,%rsi
+	leaq	(%r8,%rcx,4),%rdi
+.p2align	2
+L$invert:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	0(%rdi),%rcx
+	movq	8(%rdi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,0(%rsi)
+	movq	%rdx,8(%rsi)
+	leaq	16(%rsi),%rsi
+	leaq	-16(%rdi),%rdi
+	cmpq	%rsi,%rdi
+	jne	L$invert
+
+	leaq	L$AES_Te+2048+1024(%rip),%rax
+
+	movq	40(%rax),%rsi
+	movq	48(%rax),%rdi
+	movq	56(%rax),%rbp
+
+	movq	%r8,%r15
+	subl	$1,%r14d
+.p2align	2
+L$permute:
+	leaq	16(%r15),%r15
+	movq	0(%r15),%rax
+	movq	8(%r15),%rcx
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+
+	shrq	$32,%r8
+	shrq	$32,%r11
+
+	roll	$16,%r9d
+	roll	$16,%r12d
+
+	roll	$16,%r8d
+	roll	$16,%r11d
+
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	movl	%eax,0(%r15)
+	movl	%ebx,4(%r15)
+	movl	%ecx,8(%r15)
+	movl	%edx,12(%r15)
+	subl	$1,%r14d
+	jnz	L$permute
+
+	xorq	%rax,%rax
+L$abort:
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+L$dec_key_epilogue:
+	retq
+
+.globl	_AES_cbc_encrypt
+
+.p2align	4
+
+.private_extern	_OPENSSL_ia32cap_P
+.globl	_asm_AES_cbc_encrypt
+.private_extern	_asm_AES_cbc_encrypt
+_asm_AES_cbc_encrypt:
+_AES_cbc_encrypt:
+	cmpq	$0,%rdx
+	je	L$cbc_epilogue
+	pushfq
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+L$cbc_prologue:
+
+	cld
+	movl	%r9d,%r9d
+
+	leaq	L$AES_Te(%rip),%r14
+	cmpq	$0,%r9
+	jne	L$cbc_picked_te
+	leaq	L$AES_Td(%rip),%r14
+L$cbc_picked_te:
+
+	movl	_OPENSSL_ia32cap_P(%rip),%r10d
+	cmpq	$512,%rdx
+	jb	L$cbc_slow_prologue
+	testq	$15,%rdx
+	jnz	L$cbc_slow_prologue
+	btl	$IA32CAP_BIT0_HT,%r10d
+	jc	L$cbc_slow_prologue
+
+
+	leaq	-88-248(%rsp),%r15
+	andq	$-64,%r15
+
+
+	movq	%r14,%r10
+	leaq	2304(%r14),%r11
+	movq	%r15,%r12
+	andq	$4095,%r10
+	andq	$4095,%r11
+	andq	$4095,%r12
+
+	cmpq	%r11,%r12
+	jb	L$cbc_te_break_out
+	subq	%r11,%r12
+	subq	%r12,%r15
+	jmp	L$cbc_te_ok
+L$cbc_te_break_out:
+	subq	%r10,%r12
+	andq	$4095,%r12
+	addq	$320,%r12
+	subq	%r12,%r15
+.p2align	2
+L$cbc_te_ok:
+
+	xchgq	%rsp,%r15
+
+	movq	%r15,16(%rsp)
+L$cbc_fast_body:
+	movq	%rdi,24(%rsp)
+	movq	%rsi,32(%rsp)
+	movq	%rdx,40(%rsp)
+	movq	%rcx,48(%rsp)
+	movq	%r8,56(%rsp)
+	movl	$0,80+240(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+
+	movl	240(%r15),%eax
+
+	movq	%r15,%r10
+	subq	%r14,%r10
+	andq	$4095,%r10
+	cmpq	$2304,%r10
+	jb	L$cbc_do_ecopy
+	cmpq	$4096-248,%r10
+	jb	L$cbc_skip_ecopy
+.p2align	2
+L$cbc_do_ecopy:
+	movq	%r15,%rsi
+	leaq	80(%rsp),%rdi
+	leaq	80(%rsp),%r15
+	movl	$30,%ecx
+.long	0x90A548F3	
+	movl	%eax,(%rdi)
+L$cbc_skip_ecopy:
+	movq	%r15,0(%rsp)
+
+	movl	$18,%ecx
+.p2align	2
+L$cbc_prefetch_te:
+	movq	0(%r14),%r10
+	movq	32(%r14),%r11
+	movq	64(%r14),%r12
+	movq	96(%r14),%r13
+	leaq	128(%r14),%r14
+	subl	$1,%ecx
+	jnz	L$cbc_prefetch_te
+	leaq	-2304(%r14),%r14
+
+	cmpq	$0,%rbx
+	je	L$FAST_DECRYPT
+
+
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+.p2align	2
+L$cbc_fast_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_encrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	movq	%r10,40(%rsp)
+	jnz	L$cbc_fast_enc_loop
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	L$cbc_fast_cleanup
+
+
+.p2align	4
+L$FAST_DECRYPT:
+	cmpq	%r8,%r9
+	je	L$cbc_fast_dec_in_place
+
+	movq	%rbp,64(%rsp)
+.p2align	2
+L$cbc_fast_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	64(%rsp),%rbp
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0(%rbp),%eax
+	xorl	4(%rbp),%ebx
+	xorl	8(%rbp),%ecx
+	xorl	12(%rbp),%edx
+	movq	%r8,%rbp
+
+	subq	$16,%r10
+	movq	%r10,40(%rsp)
+	movq	%rbp,64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jnz	L$cbc_fast_dec_loop
+	movq	56(%rsp),%r12
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0(%r12)
+	movq	%r11,8(%r12)
+	jmp	L$cbc_fast_cleanup
+
+.p2align	4
+L$cbc_fast_dec_in_place:
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0+64(%rsp)
+	movq	%r11,8+64(%rsp)
+.p2align	2
+L$cbc_fast_dec_in_place_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jz	L$cbc_fast_dec_in_place_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	movq	%r10,40(%rsp)
+	jmp	L$cbc_fast_dec_in_place_loop
+L$cbc_fast_dec_in_place_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+.p2align	2
+L$cbc_fast_cleanup:
+	cmpl	$0,80+240(%rsp)
+	leaq	80(%rsp),%rdi
+	je	L$cbc_exit
+	movl	$30,%ecx
+	xorq	%rax,%rax
+.long	0x90AB48F3	
+
+	jmp	L$cbc_exit
+
+
+.p2align	4
+L$cbc_slow_prologue:
+
+	leaq	-88(%rsp),%rbp
+	andq	$-64,%rbp
+
+	leaq	-88-63(%rcx),%r10
+	subq	%rbp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rbp
+
+	xchgq	%rsp,%rbp
+
+	movq	%rbp,16(%rsp)
+L$cbc_slow_body:
+
+
+
+
+	movq	%r8,56(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+	movq	%rdx,%r10
+
+	movl	240(%r15),%eax
+	movq	%r15,0(%rsp)
+	shll	$4,%eax
+	leaq	(%r15,%rax,1),%rax
+	movq	%rax,8(%rsp)
+
+
+	leaq	2048(%r14),%r14
+	leaq	768-8(%rsp),%rax
+	subq	%r14,%rax
+	andq	$768,%rax
+	leaq	(%r14,%rax,1),%r14
+
+	cmpq	$0,%rbx
+	je	L$SLOW_DECRYPT
+
+
+	testq	$-16,%r10
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+	jz	L$cbc_slow_enc_tail	
+
+.p2align	2
+L$cbc_slow_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	jnz	L$cbc_slow_enc_loop
+	testq	$15,%r10
+	jnz	L$cbc_slow_enc_tail
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	L$cbc_exit
+
+.p2align	2
+L$cbc_slow_enc_tail:
+	movq	%rax,%r11
+	movq	%rcx,%r12
+	movq	%r10,%rcx
+	movq	%r8,%rsi
+	movq	%r9,%rdi
+.long	0x9066A4F3		
+	movq	$16,%rcx
+	subq	%r10,%rcx
+	xorq	%rax,%rax
+.long	0x9066AAF3		
+	movq	%r9,%r8
+	movq	$16,%r10
+	movq	%r11,%rax
+	movq	%r12,%rcx
+	jmp	L$cbc_slow_enc_loop	
+
+.p2align	4
+L$SLOW_DECRYPT:
+	shrq	$3,%rax
+	addq	%rax,%r14
+
+	movq	0(%rbp),%r11
+	movq	8(%rbp),%r12
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+.p2align	2
+L$cbc_slow_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jc	L$cbc_slow_dec_partial
+	jz	L$cbc_slow_dec_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jmp	L$cbc_slow_dec_loop
+L$cbc_slow_dec_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	jmp	L$cbc_exit
+
+.p2align	2
+L$cbc_slow_dec_partial:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0+64(%rsp)
+	movl	%ebx,4+64(%rsp)
+	movl	%ecx,8+64(%rsp)
+	movl	%edx,12+64(%rsp)
+
+	movq	%r9,%rdi
+	leaq	64(%rsp),%rsi
+	leaq	16(%r10),%rcx
+.long	0x9066A4F3	
+	jmp	L$cbc_exit
+
+.p2align	4
+L$cbc_exit:
+	movq	16(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$cbc_popfq:
+	popfq
+L$cbc_epilogue:
+	retq
+
+.p2align	6
+L$AES_Te:
+.long	0xa56363c6,0xa56363c6
+.long	0x847c7cf8,0x847c7cf8
+.long	0x997777ee,0x997777ee
+.long	0x8d7b7bf6,0x8d7b7bf6
+.long	0x0df2f2ff,0x0df2f2ff
+.long	0xbd6b6bd6,0xbd6b6bd6
+.long	0xb16f6fde,0xb16f6fde
+.long	0x54c5c591,0x54c5c591
+.long	0x50303060,0x50303060
+.long	0x03010102,0x03010102
+.long	0xa96767ce,0xa96767ce
+.long	0x7d2b2b56,0x7d2b2b56
+.long	0x19fefee7,0x19fefee7
+.long	0x62d7d7b5,0x62d7d7b5
+.long	0xe6abab4d,0xe6abab4d
+.long	0x9a7676ec,0x9a7676ec
+.long	0x45caca8f,0x45caca8f
+.long	0x9d82821f,0x9d82821f
+.long	0x40c9c989,0x40c9c989
+.long	0x877d7dfa,0x877d7dfa
+.long	0x15fafaef,0x15fafaef
+.long	0xeb5959b2,0xeb5959b2
+.long	0xc947478e,0xc947478e
+.long	0x0bf0f0fb,0x0bf0f0fb
+.long	0xecadad41,0xecadad41
+.long	0x67d4d4b3,0x67d4d4b3
+.long	0xfda2a25f,0xfda2a25f
+.long	0xeaafaf45,0xeaafaf45
+.long	0xbf9c9c23,0xbf9c9c23
+.long	0xf7a4a453,0xf7a4a453
+.long	0x967272e4,0x967272e4
+.long	0x5bc0c09b,0x5bc0c09b
+.long	0xc2b7b775,0xc2b7b775
+.long	0x1cfdfde1,0x1cfdfde1
+.long	0xae93933d,0xae93933d
+.long	0x6a26264c,0x6a26264c
+.long	0x5a36366c,0x5a36366c
+.long	0x413f3f7e,0x413f3f7e
+.long	0x02f7f7f5,0x02f7f7f5
+.long	0x4fcccc83,0x4fcccc83
+.long	0x5c343468,0x5c343468
+.long	0xf4a5a551,0xf4a5a551
+.long	0x34e5e5d1,0x34e5e5d1
+.long	0x08f1f1f9,0x08f1f1f9
+.long	0x937171e2,0x937171e2
+.long	0x73d8d8ab,0x73d8d8ab
+.long	0x53313162,0x53313162
+.long	0x3f15152a,0x3f15152a
+.long	0x0c040408,0x0c040408
+.long	0x52c7c795,0x52c7c795
+.long	0x65232346,0x65232346
+.long	0x5ec3c39d,0x5ec3c39d
+.long	0x28181830,0x28181830
+.long	0xa1969637,0xa1969637
+.long	0x0f05050a,0x0f05050a
+.long	0xb59a9a2f,0xb59a9a2f
+.long	0x0907070e,0x0907070e
+.long	0x36121224,0x36121224
+.long	0x9b80801b,0x9b80801b
+.long	0x3de2e2df,0x3de2e2df
+.long	0x26ebebcd,0x26ebebcd
+.long	0x6927274e,0x6927274e
+.long	0xcdb2b27f,0xcdb2b27f
+.long	0x9f7575ea,0x9f7575ea
+.long	0x1b090912,0x1b090912
+.long	0x9e83831d,0x9e83831d
+.long	0x742c2c58,0x742c2c58
+.long	0x2e1a1a34,0x2e1a1a34
+.long	0x2d1b1b36,0x2d1b1b36
+.long	0xb26e6edc,0xb26e6edc
+.long	0xee5a5ab4,0xee5a5ab4
+.long	0xfba0a05b,0xfba0a05b
+.long	0xf65252a4,0xf65252a4
+.long	0x4d3b3b76,0x4d3b3b76
+.long	0x61d6d6b7,0x61d6d6b7
+.long	0xceb3b37d,0xceb3b37d
+.long	0x7b292952,0x7b292952
+.long	0x3ee3e3dd,0x3ee3e3dd
+.long	0x712f2f5e,0x712f2f5e
+.long	0x97848413,0x97848413
+.long	0xf55353a6,0xf55353a6
+.long	0x68d1d1b9,0x68d1d1b9
+.long	0x00000000,0x00000000
+.long	0x2cededc1,0x2cededc1
+.long	0x60202040,0x60202040
+.long	0x1ffcfce3,0x1ffcfce3
+.long	0xc8b1b179,0xc8b1b179
+.long	0xed5b5bb6,0xed5b5bb6
+.long	0xbe6a6ad4,0xbe6a6ad4
+.long	0x46cbcb8d,0x46cbcb8d
+.long	0xd9bebe67,0xd9bebe67
+.long	0x4b393972,0x4b393972
+.long	0xde4a4a94,0xde4a4a94
+.long	0xd44c4c98,0xd44c4c98
+.long	0xe85858b0,0xe85858b0
+.long	0x4acfcf85,0x4acfcf85
+.long	0x6bd0d0bb,0x6bd0d0bb
+.long	0x2aefefc5,0x2aefefc5
+.long	0xe5aaaa4f,0xe5aaaa4f
+.long	0x16fbfbed,0x16fbfbed
+.long	0xc5434386,0xc5434386
+.long	0xd74d4d9a,0xd74d4d9a
+.long	0x55333366,0x55333366
+.long	0x94858511,0x94858511
+.long	0xcf45458a,0xcf45458a
+.long	0x10f9f9e9,0x10f9f9e9
+.long	0x06020204,0x06020204
+.long	0x817f7ffe,0x817f7ffe
+.long	0xf05050a0,0xf05050a0
+.long	0x443c3c78,0x443c3c78
+.long	0xba9f9f25,0xba9f9f25
+.long	0xe3a8a84b,0xe3a8a84b
+.long	0xf35151a2,0xf35151a2
+.long	0xfea3a35d,0xfea3a35d
+.long	0xc0404080,0xc0404080
+.long	0x8a8f8f05,0x8a8f8f05
+.long	0xad92923f,0xad92923f
+.long	0xbc9d9d21,0xbc9d9d21
+.long	0x48383870,0x48383870
+.long	0x04f5f5f1,0x04f5f5f1
+.long	0xdfbcbc63,0xdfbcbc63
+.long	0xc1b6b677,0xc1b6b677
+.long	0x75dadaaf,0x75dadaaf
+.long	0x63212142,0x63212142
+.long	0x30101020,0x30101020
+.long	0x1affffe5,0x1affffe5
+.long	0x0ef3f3fd,0x0ef3f3fd
+.long	0x6dd2d2bf,0x6dd2d2bf
+.long	0x4ccdcd81,0x4ccdcd81
+.long	0x140c0c18,0x140c0c18
+.long	0x35131326,0x35131326
+.long	0x2fececc3,0x2fececc3
+.long	0xe15f5fbe,0xe15f5fbe
+.long	0xa2979735,0xa2979735
+.long	0xcc444488,0xcc444488
+.long	0x3917172e,0x3917172e
+.long	0x57c4c493,0x57c4c493
+.long	0xf2a7a755,0xf2a7a755
+.long	0x827e7efc,0x827e7efc
+.long	0x473d3d7a,0x473d3d7a
+.long	0xac6464c8,0xac6464c8
+.long	0xe75d5dba,0xe75d5dba
+.long	0x2b191932,0x2b191932
+.long	0x957373e6,0x957373e6
+.long	0xa06060c0,0xa06060c0
+.long	0x98818119,0x98818119
+.long	0xd14f4f9e,0xd14f4f9e
+.long	0x7fdcdca3,0x7fdcdca3
+.long	0x66222244,0x66222244
+.long	0x7e2a2a54,0x7e2a2a54
+.long	0xab90903b,0xab90903b
+.long	0x8388880b,0x8388880b
+.long	0xca46468c,0xca46468c
+.long	0x29eeeec7,0x29eeeec7
+.long	0xd3b8b86b,0xd3b8b86b
+.long	0x3c141428,0x3c141428
+.long	0x79dedea7,0x79dedea7
+.long	0xe25e5ebc,0xe25e5ebc
+.long	0x1d0b0b16,0x1d0b0b16
+.long	0x76dbdbad,0x76dbdbad
+.long	0x3be0e0db,0x3be0e0db
+.long	0x56323264,0x56323264
+.long	0x4e3a3a74,0x4e3a3a74
+.long	0x1e0a0a14,0x1e0a0a14
+.long	0xdb494992,0xdb494992
+.long	0x0a06060c,0x0a06060c
+.long	0x6c242448,0x6c242448
+.long	0xe45c5cb8,0xe45c5cb8
+.long	0x5dc2c29f,0x5dc2c29f
+.long	0x6ed3d3bd,0x6ed3d3bd
+.long	0xefacac43,0xefacac43
+.long	0xa66262c4,0xa66262c4
+.long	0xa8919139,0xa8919139
+.long	0xa4959531,0xa4959531
+.long	0x37e4e4d3,0x37e4e4d3
+.long	0x8b7979f2,0x8b7979f2
+.long	0x32e7e7d5,0x32e7e7d5
+.long	0x43c8c88b,0x43c8c88b
+.long	0x5937376e,0x5937376e
+.long	0xb76d6dda,0xb76d6dda
+.long	0x8c8d8d01,0x8c8d8d01
+.long	0x64d5d5b1,0x64d5d5b1
+.long	0xd24e4e9c,0xd24e4e9c
+.long	0xe0a9a949,0xe0a9a949
+.long	0xb46c6cd8,0xb46c6cd8
+.long	0xfa5656ac,0xfa5656ac
+.long	0x07f4f4f3,0x07f4f4f3
+.long	0x25eaeacf,0x25eaeacf
+.long	0xaf6565ca,0xaf6565ca
+.long	0x8e7a7af4,0x8e7a7af4
+.long	0xe9aeae47,0xe9aeae47
+.long	0x18080810,0x18080810
+.long	0xd5baba6f,0xd5baba6f
+.long	0x887878f0,0x887878f0
+.long	0x6f25254a,0x6f25254a
+.long	0x722e2e5c,0x722e2e5c
+.long	0x241c1c38,0x241c1c38
+.long	0xf1a6a657,0xf1a6a657
+.long	0xc7b4b473,0xc7b4b473
+.long	0x51c6c697,0x51c6c697
+.long	0x23e8e8cb,0x23e8e8cb
+.long	0x7cdddda1,0x7cdddda1
+.long	0x9c7474e8,0x9c7474e8
+.long	0x211f1f3e,0x211f1f3e
+.long	0xdd4b4b96,0xdd4b4b96
+.long	0xdcbdbd61,0xdcbdbd61
+.long	0x868b8b0d,0x868b8b0d
+.long	0x858a8a0f,0x858a8a0f
+.long	0x907070e0,0x907070e0
+.long	0x423e3e7c,0x423e3e7c
+.long	0xc4b5b571,0xc4b5b571
+.long	0xaa6666cc,0xaa6666cc
+.long	0xd8484890,0xd8484890
+.long	0x05030306,0x05030306
+.long	0x01f6f6f7,0x01f6f6f7
+.long	0x120e0e1c,0x120e0e1c
+.long	0xa36161c2,0xa36161c2
+.long	0x5f35356a,0x5f35356a
+.long	0xf95757ae,0xf95757ae
+.long	0xd0b9b969,0xd0b9b969
+.long	0x91868617,0x91868617
+.long	0x58c1c199,0x58c1c199
+.long	0x271d1d3a,0x271d1d3a
+.long	0xb99e9e27,0xb99e9e27
+.long	0x38e1e1d9,0x38e1e1d9
+.long	0x13f8f8eb,0x13f8f8eb
+.long	0xb398982b,0xb398982b
+.long	0x33111122,0x33111122
+.long	0xbb6969d2,0xbb6969d2
+.long	0x70d9d9a9,0x70d9d9a9
+.long	0x898e8e07,0x898e8e07
+.long	0xa7949433,0xa7949433
+.long	0xb69b9b2d,0xb69b9b2d
+.long	0x221e1e3c,0x221e1e3c
+.long	0x92878715,0x92878715
+.long	0x20e9e9c9,0x20e9e9c9
+.long	0x49cece87,0x49cece87
+.long	0xff5555aa,0xff5555aa
+.long	0x78282850,0x78282850
+.long	0x7adfdfa5,0x7adfdfa5
+.long	0x8f8c8c03,0x8f8c8c03
+.long	0xf8a1a159,0xf8a1a159
+.long	0x80898909,0x80898909
+.long	0x170d0d1a,0x170d0d1a
+.long	0xdabfbf65,0xdabfbf65
+.long	0x31e6e6d7,0x31e6e6d7
+.long	0xc6424284,0xc6424284
+.long	0xb86868d0,0xb86868d0
+.long	0xc3414182,0xc3414182
+.long	0xb0999929,0xb0999929
+.long	0x772d2d5a,0x772d2d5a
+.long	0x110f0f1e,0x110f0f1e
+.long	0xcbb0b07b,0xcbb0b07b
+.long	0xfc5454a8,0xfc5454a8
+.long	0xd6bbbb6d,0xd6bbbb6d
+.long	0x3a16162c,0x3a16162c
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.long	0x00000001, 0x00000002, 0x00000004, 0x00000008
+.long	0x00000010, 0x00000020, 0x00000040, 0x00000080
+.long	0x0000001b, 0x00000036, 0x80808080, 0x80808080
+.long	0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b
+.p2align	6
+L$AES_Td:
+.long	0x50a7f451,0x50a7f451
+.long	0x5365417e,0x5365417e
+.long	0xc3a4171a,0xc3a4171a
+.long	0x965e273a,0x965e273a
+.long	0xcb6bab3b,0xcb6bab3b
+.long	0xf1459d1f,0xf1459d1f
+.long	0xab58faac,0xab58faac
+.long	0x9303e34b,0x9303e34b
+.long	0x55fa3020,0x55fa3020
+.long	0xf66d76ad,0xf66d76ad
+.long	0x9176cc88,0x9176cc88
+.long	0x254c02f5,0x254c02f5
+.long	0xfcd7e54f,0xfcd7e54f
+.long	0xd7cb2ac5,0xd7cb2ac5
+.long	0x80443526,0x80443526
+.long	0x8fa362b5,0x8fa362b5
+.long	0x495ab1de,0x495ab1de
+.long	0x671bba25,0x671bba25
+.long	0x980eea45,0x980eea45
+.long	0xe1c0fe5d,0xe1c0fe5d
+.long	0x02752fc3,0x02752fc3
+.long	0x12f04c81,0x12f04c81
+.long	0xa397468d,0xa397468d
+.long	0xc6f9d36b,0xc6f9d36b
+.long	0xe75f8f03,0xe75f8f03
+.long	0x959c9215,0x959c9215
+.long	0xeb7a6dbf,0xeb7a6dbf
+.long	0xda595295,0xda595295
+.long	0x2d83bed4,0x2d83bed4
+.long	0xd3217458,0xd3217458
+.long	0x2969e049,0x2969e049
+.long	0x44c8c98e,0x44c8c98e
+.long	0x6a89c275,0x6a89c275
+.long	0x78798ef4,0x78798ef4
+.long	0x6b3e5899,0x6b3e5899
+.long	0xdd71b927,0xdd71b927
+.long	0xb64fe1be,0xb64fe1be
+.long	0x17ad88f0,0x17ad88f0
+.long	0x66ac20c9,0x66ac20c9
+.long	0xb43ace7d,0xb43ace7d
+.long	0x184adf63,0x184adf63
+.long	0x82311ae5,0x82311ae5
+.long	0x60335197,0x60335197
+.long	0x457f5362,0x457f5362
+.long	0xe07764b1,0xe07764b1
+.long	0x84ae6bbb,0x84ae6bbb
+.long	0x1ca081fe,0x1ca081fe
+.long	0x942b08f9,0x942b08f9
+.long	0x58684870,0x58684870
+.long	0x19fd458f,0x19fd458f
+.long	0x876cde94,0x876cde94
+.long	0xb7f87b52,0xb7f87b52
+.long	0x23d373ab,0x23d373ab
+.long	0xe2024b72,0xe2024b72
+.long	0x578f1fe3,0x578f1fe3
+.long	0x2aab5566,0x2aab5566
+.long	0x0728ebb2,0x0728ebb2
+.long	0x03c2b52f,0x03c2b52f
+.long	0x9a7bc586,0x9a7bc586
+.long	0xa50837d3,0xa50837d3
+.long	0xf2872830,0xf2872830
+.long	0xb2a5bf23,0xb2a5bf23
+.long	0xba6a0302,0xba6a0302
+.long	0x5c8216ed,0x5c8216ed
+.long	0x2b1ccf8a,0x2b1ccf8a
+.long	0x92b479a7,0x92b479a7
+.long	0xf0f207f3,0xf0f207f3
+.long	0xa1e2694e,0xa1e2694e
+.long	0xcdf4da65,0xcdf4da65
+.long	0xd5be0506,0xd5be0506
+.long	0x1f6234d1,0x1f6234d1
+.long	0x8afea6c4,0x8afea6c4
+.long	0x9d532e34,0x9d532e34
+.long	0xa055f3a2,0xa055f3a2
+.long	0x32e18a05,0x32e18a05
+.long	0x75ebf6a4,0x75ebf6a4
+.long	0x39ec830b,0x39ec830b
+.long	0xaaef6040,0xaaef6040
+.long	0x069f715e,0x069f715e
+.long	0x51106ebd,0x51106ebd
+.long	0xf98a213e,0xf98a213e
+.long	0x3d06dd96,0x3d06dd96
+.long	0xae053edd,0xae053edd
+.long	0x46bde64d,0x46bde64d
+.long	0xb58d5491,0xb58d5491
+.long	0x055dc471,0x055dc471
+.long	0x6fd40604,0x6fd40604
+.long	0xff155060,0xff155060
+.long	0x24fb9819,0x24fb9819
+.long	0x97e9bdd6,0x97e9bdd6
+.long	0xcc434089,0xcc434089
+.long	0x779ed967,0x779ed967
+.long	0xbd42e8b0,0xbd42e8b0
+.long	0x888b8907,0x888b8907
+.long	0x385b19e7,0x385b19e7
+.long	0xdbeec879,0xdbeec879
+.long	0x470a7ca1,0x470a7ca1
+.long	0xe90f427c,0xe90f427c
+.long	0xc91e84f8,0xc91e84f8
+.long	0x00000000,0x00000000
+.long	0x83868009,0x83868009
+.long	0x48ed2b32,0x48ed2b32
+.long	0xac70111e,0xac70111e
+.long	0x4e725a6c,0x4e725a6c
+.long	0xfbff0efd,0xfbff0efd
+.long	0x5638850f,0x5638850f
+.long	0x1ed5ae3d,0x1ed5ae3d
+.long	0x27392d36,0x27392d36
+.long	0x64d90f0a,0x64d90f0a
+.long	0x21a65c68,0x21a65c68
+.long	0xd1545b9b,0xd1545b9b
+.long	0x3a2e3624,0x3a2e3624
+.long	0xb1670a0c,0xb1670a0c
+.long	0x0fe75793,0x0fe75793
+.long	0xd296eeb4,0xd296eeb4
+.long	0x9e919b1b,0x9e919b1b
+.long	0x4fc5c080,0x4fc5c080
+.long	0xa220dc61,0xa220dc61
+.long	0x694b775a,0x694b775a
+.long	0x161a121c,0x161a121c
+.long	0x0aba93e2,0x0aba93e2
+.long	0xe52aa0c0,0xe52aa0c0
+.long	0x43e0223c,0x43e0223c
+.long	0x1d171b12,0x1d171b12
+.long	0x0b0d090e,0x0b0d090e
+.long	0xadc78bf2,0xadc78bf2
+.long	0xb9a8b62d,0xb9a8b62d
+.long	0xc8a91e14,0xc8a91e14
+.long	0x8519f157,0x8519f157
+.long	0x4c0775af,0x4c0775af
+.long	0xbbdd99ee,0xbbdd99ee
+.long	0xfd607fa3,0xfd607fa3
+.long	0x9f2601f7,0x9f2601f7
+.long	0xbcf5725c,0xbcf5725c
+.long	0xc53b6644,0xc53b6644
+.long	0x347efb5b,0x347efb5b
+.long	0x7629438b,0x7629438b
+.long	0xdcc623cb,0xdcc623cb
+.long	0x68fcedb6,0x68fcedb6
+.long	0x63f1e4b8,0x63f1e4b8
+.long	0xcadc31d7,0xcadc31d7
+.long	0x10856342,0x10856342
+.long	0x40229713,0x40229713
+.long	0x2011c684,0x2011c684
+.long	0x7d244a85,0x7d244a85
+.long	0xf83dbbd2,0xf83dbbd2
+.long	0x1132f9ae,0x1132f9ae
+.long	0x6da129c7,0x6da129c7
+.long	0x4b2f9e1d,0x4b2f9e1d
+.long	0xf330b2dc,0xf330b2dc
+.long	0xec52860d,0xec52860d
+.long	0xd0e3c177,0xd0e3c177
+.long	0x6c16b32b,0x6c16b32b
+.long	0x99b970a9,0x99b970a9
+.long	0xfa489411,0xfa489411
+.long	0x2264e947,0x2264e947
+.long	0xc48cfca8,0xc48cfca8
+.long	0x1a3ff0a0,0x1a3ff0a0
+.long	0xd82c7d56,0xd82c7d56
+.long	0xef903322,0xef903322
+.long	0xc74e4987,0xc74e4987
+.long	0xc1d138d9,0xc1d138d9
+.long	0xfea2ca8c,0xfea2ca8c
+.long	0x360bd498,0x360bd498
+.long	0xcf81f5a6,0xcf81f5a6
+.long	0x28de7aa5,0x28de7aa5
+.long	0x268eb7da,0x268eb7da
+.long	0xa4bfad3f,0xa4bfad3f
+.long	0xe49d3a2c,0xe49d3a2c
+.long	0x0d927850,0x0d927850
+.long	0x9bcc5f6a,0x9bcc5f6a
+.long	0x62467e54,0x62467e54
+.long	0xc2138df6,0xc2138df6
+.long	0xe8b8d890,0xe8b8d890
+.long	0x5ef7392e,0x5ef7392e
+.long	0xf5afc382,0xf5afc382
+.long	0xbe805d9f,0xbe805d9f
+.long	0x7c93d069,0x7c93d069
+.long	0xa92dd56f,0xa92dd56f
+.long	0xb31225cf,0xb31225cf
+.long	0x3b99acc8,0x3b99acc8
+.long	0xa77d1810,0xa77d1810
+.long	0x6e639ce8,0x6e639ce8
+.long	0x7bbb3bdb,0x7bbb3bdb
+.long	0x097826cd,0x097826cd
+.long	0xf418596e,0xf418596e
+.long	0x01b79aec,0x01b79aec
+.long	0xa89a4f83,0xa89a4f83
+.long	0x656e95e6,0x656e95e6
+.long	0x7ee6ffaa,0x7ee6ffaa
+.long	0x08cfbc21,0x08cfbc21
+.long	0xe6e815ef,0xe6e815ef
+.long	0xd99be7ba,0xd99be7ba
+.long	0xce366f4a,0xce366f4a
+.long	0xd4099fea,0xd4099fea
+.long	0xd67cb029,0xd67cb029
+.long	0xafb2a431,0xafb2a431
+.long	0x31233f2a,0x31233f2a
+.long	0x3094a5c6,0x3094a5c6
+.long	0xc066a235,0xc066a235
+.long	0x37bc4e74,0x37bc4e74
+.long	0xa6ca82fc,0xa6ca82fc
+.long	0xb0d090e0,0xb0d090e0
+.long	0x15d8a733,0x15d8a733
+.long	0x4a9804f1,0x4a9804f1
+.long	0xf7daec41,0xf7daec41
+.long	0x0e50cd7f,0x0e50cd7f
+.long	0x2ff69117,0x2ff69117
+.long	0x8dd64d76,0x8dd64d76
+.long	0x4db0ef43,0x4db0ef43
+.long	0x544daacc,0x544daacc
+.long	0xdf0496e4,0xdf0496e4
+.long	0xe3b5d19e,0xe3b5d19e
+.long	0x1b886a4c,0x1b886a4c
+.long	0xb81f2cc1,0xb81f2cc1
+.long	0x7f516546,0x7f516546
+.long	0x04ea5e9d,0x04ea5e9d
+.long	0x5d358c01,0x5d358c01
+.long	0x737487fa,0x737487fa
+.long	0x2e410bfb,0x2e410bfb
+.long	0x5a1d67b3,0x5a1d67b3
+.long	0x52d2db92,0x52d2db92
+.long	0x335610e9,0x335610e9
+.long	0x1347d66d,0x1347d66d
+.long	0x8c61d79a,0x8c61d79a
+.long	0x7a0ca137,0x7a0ca137
+.long	0x8e14f859,0x8e14f859
+.long	0x893c13eb,0x893c13eb
+.long	0xee27a9ce,0xee27a9ce
+.long	0x35c961b7,0x35c961b7
+.long	0xede51ce1,0xede51ce1
+.long	0x3cb1477a,0x3cb1477a
+.long	0x59dfd29c,0x59dfd29c
+.long	0x3f73f255,0x3f73f255
+.long	0x79ce1418,0x79ce1418
+.long	0xbf37c773,0xbf37c773
+.long	0xeacdf753,0xeacdf753
+.long	0x5baafd5f,0x5baafd5f
+.long	0x146f3ddf,0x146f3ddf
+.long	0x86db4478,0x86db4478
+.long	0x81f3afca,0x81f3afca
+.long	0x3ec468b9,0x3ec468b9
+.long	0x2c342438,0x2c342438
+.long	0x5f40a3c2,0x5f40a3c2
+.long	0x72c31d16,0x72c31d16
+.long	0x0c25e2bc,0x0c25e2bc
+.long	0x8b493c28,0x8b493c28
+.long	0x41950dff,0x41950dff
+.long	0x7101a839,0x7101a839
+.long	0xdeb30c08,0xdeb30c08
+.long	0x9ce4b4d8,0x9ce4b4d8
+.long	0x90c15664,0x90c15664
+.long	0x6184cb7b,0x6184cb7b
+.long	0x70b632d5,0x70b632d5
+.long	0x745c6c48,0x745c6c48
+.long	0x4257b8d0,0x4257b8d0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	65,69,83,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
diff --git a/crypto/aes/aes-masm-x86_64.S b/crypto/aes/aes-masm-x86_64.S
new file mode 100644
index 0000000..a5e519b
--- /dev/null
+++ b/crypto/aes/aes-masm-x86_64.S
@@ -0,0 +1,2948 @@
+; 1 "crypto/aes/aes-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/aes/aes-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/aes/aes-masm-x86_64.S.tmp" 2
+
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+ALIGN	16
+_x86_64_AES_encrypt	PROC PRIVATE
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+
+	mov	r13d,DWORD PTR[240+r15]
+	sub	r13d,1
+	jmp	$L$enc_loop
+ALIGN	16
+$L$enc_loop::
+
+	movzx	esi,al
+	movzx	edi,bl
+	movzx	ebp,cl
+	mov	r10d,DWORD PTR[rsi*8+r14]
+	mov	r11d,DWORD PTR[rdi*8+r14]
+	mov	r12d,DWORD PTR[rbp*8+r14]
+
+	movzx	esi,bh
+	movzx	edi,ch
+	movzx	ebp,dl
+	xor	r10d,DWORD PTR[3+rsi*8+r14]
+	xor	r11d,DWORD PTR[3+rdi*8+r14]
+	mov	r8d,DWORD PTR[rbp*8+r14]
+
+	movzx	esi,dh
+	shr	ecx,16
+	movzx	ebp,ah
+	xor	r12d,DWORD PTR[3+rsi*8+r14]
+	shr	edx,16
+	xor	r8d,DWORD PTR[3+rbp*8+r14]
+
+	shr	ebx,16
+	lea	r15,QWORD PTR[16+r15]
+	shr	eax,16
+
+	movzx	esi,cl
+	movzx	edi,dl
+	movzx	ebp,al
+	xor	r10d,DWORD PTR[2+rsi*8+r14]
+	xor	r11d,DWORD PTR[2+rdi*8+r14]
+	xor	r12d,DWORD PTR[2+rbp*8+r14]
+
+	movzx	esi,dh
+	movzx	edi,ah
+	movzx	ebp,bl
+	xor	r10d,DWORD PTR[1+rsi*8+r14]
+	xor	r11d,DWORD PTR[1+rdi*8+r14]
+	xor	r8d,DWORD PTR[2+rbp*8+r14]
+
+	mov	edx,DWORD PTR[12+r15]
+	movzx	edi,bh
+	movzx	ebp,ch
+	mov	eax,DWORD PTR[r15]
+	xor	r12d,DWORD PTR[1+rdi*8+r14]
+	xor	r8d,DWORD PTR[1+rbp*8+r14]
+
+	mov	ebx,DWORD PTR[4+r15]
+	mov	ecx,DWORD PTR[8+r15]
+	xor	eax,r10d
+	xor	ebx,r11d
+	xor	ecx,r12d
+	xor	edx,r8d
+	sub	r13d,1
+	jnz	$L$enc_loop
+	movzx	esi,al
+	movzx	edi,bl
+	movzx	ebp,cl
+	movzx	r10d,BYTE PTR[2+rsi*8+r14]
+	movzx	r11d,BYTE PTR[2+rdi*8+r14]
+	movzx	r12d,BYTE PTR[2+rbp*8+r14]
+
+	movzx	esi,dl
+	movzx	edi,bh
+	movzx	ebp,ch
+	movzx	r8d,BYTE PTR[2+rsi*8+r14]
+	mov	edi,DWORD PTR[rdi*8+r14]
+	mov	ebp,DWORD PTR[rbp*8+r14]
+
+	and	edi,00000ff00h
+	and	ebp,00000ff00h
+
+	xor	r10d,edi
+	xor	r11d,ebp
+	shr	ecx,16
+
+	movzx	esi,dh
+	movzx	edi,ah
+	shr	edx,16
+	mov	esi,DWORD PTR[rsi*8+r14]
+	mov	edi,DWORD PTR[rdi*8+r14]
+
+	and	esi,00000ff00h
+	and	edi,00000ff00h
+	shr	ebx,16
+	xor	r12d,esi
+	xor	r8d,edi
+	shr	eax,16
+
+	movzx	esi,cl
+	movzx	edi,dl
+	movzx	ebp,al
+	mov	esi,DWORD PTR[rsi*8+r14]
+	mov	edi,DWORD PTR[rdi*8+r14]
+	mov	ebp,DWORD PTR[rbp*8+r14]
+
+	and	esi,000ff0000h
+	and	edi,000ff0000h
+	and	ebp,000ff0000h
+
+	xor	r10d,esi
+	xor	r11d,edi
+	xor	r12d,ebp
+
+	movzx	esi,bl
+	movzx	edi,dh
+	movzx	ebp,ah
+	mov	esi,DWORD PTR[rsi*8+r14]
+	mov	edi,DWORD PTR[2+rdi*8+r14]
+	mov	ebp,DWORD PTR[2+rbp*8+r14]
+
+	and	esi,000ff0000h
+	and	edi,0ff000000h
+	and	ebp,0ff000000h
+
+	xor	r8d,esi
+	xor	r10d,edi
+	xor	r11d,ebp
+
+	movzx	esi,bh
+	movzx	edi,ch
+	mov	edx,DWORD PTR[((16+12))+r15]
+	mov	esi,DWORD PTR[2+rsi*8+r14]
+	mov	edi,DWORD PTR[2+rdi*8+r14]
+	mov	eax,DWORD PTR[((16+0))+r15]
+
+	and	esi,0ff000000h
+	and	edi,0ff000000h
+
+	xor	r12d,esi
+	xor	r8d,edi
+
+	mov	ebx,DWORD PTR[((16+4))+r15]
+	mov	ecx,DWORD PTR[((16+8))+r15]
+	xor	eax,r10d
+	xor	ebx,r11d
+	xor	ecx,r12d
+	xor	edx,r8d
+	DB	0F3h,0C3h		;repret
+_x86_64_AES_encrypt	ENDP
+
+ALIGN	16
+_x86_64_AES_encrypt_compact	PROC PRIVATE
+	lea	r8,QWORD PTR[128+r14]
+	mov	edi,DWORD PTR[((0-128))+r8]
+	mov	ebp,DWORD PTR[((32-128))+r8]
+	mov	r10d,DWORD PTR[((64-128))+r8]
+	mov	r11d,DWORD PTR[((96-128))+r8]
+	mov	edi,DWORD PTR[((128-128))+r8]
+	mov	ebp,DWORD PTR[((160-128))+r8]
+	mov	r10d,DWORD PTR[((192-128))+r8]
+	mov	r11d,DWORD PTR[((224-128))+r8]
+	jmp	$L$enc_loop_compact
+ALIGN	16
+$L$enc_loop_compact::
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+	lea	r15,QWORD PTR[16+r15]
+	movzx	r10d,al
+	movzx	r11d,bl
+	movzx	r12d,cl
+	movzx	r10d,BYTE PTR[r10*1+r14]
+	movzx	r11d,BYTE PTR[r11*1+r14]
+	movzx	r12d,BYTE PTR[r12*1+r14]
+
+	movzx	r8d,dl
+	movzx	esi,bh
+	movzx	edi,ch
+	movzx	r8d,BYTE PTR[r8*1+r14]
+	movzx	r9d,BYTE PTR[rsi*1+r14]
+	movzx	r13d,BYTE PTR[rdi*1+r14]
+
+	movzx	ebp,dh
+	movzx	esi,ah
+	shr	ecx,16
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	shr	edx,16
+
+	movzx	edi,cl
+	shl	r9d,8
+	shl	r13d,8
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	xor	r10d,r9d
+	xor	r11d,r13d
+
+	movzx	r9d,dl
+	shr	eax,16
+	shr	ebx,16
+	movzx	r13d,al
+	shl	ebp,8
+	shl	esi,8
+	movzx	r9d,BYTE PTR[r9*1+r14]
+	movzx	r13d,BYTE PTR[r13*1+r14]
+	xor	r12d,ebp
+	xor	r8d,esi
+
+	movzx	ebp,bl
+	movzx	esi,dh
+	shl	edi,16
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	xor	r10d,edi
+
+	movzx	edi,ah
+	shr	ecx,8
+	shr	ebx,8
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	movzx	edx,BYTE PTR[rcx*1+r14]
+	movzx	ecx,BYTE PTR[rbx*1+r14]
+	shl	r9d,16
+	shl	r13d,16
+	shl	ebp,16
+	xor	r11d,r9d
+	xor	r12d,r13d
+	xor	r8d,ebp
+
+	shl	esi,24
+	shl	edi,24
+	shl	edx,24
+	xor	r10d,esi
+	shl	ecx,24
+	xor	r11d,edi
+	mov	eax,r10d
+	mov	ebx,r11d
+	xor	ecx,r12d
+	xor	edx,r8d
+	cmp	r15,QWORD PTR[16+rsp]
+	je	$L$enc_compact_done
+	mov	esi,eax
+	mov	edi,ebx
+	and	esi,080808080h
+	and	edi,080808080h
+	mov	r10d,esi
+	mov	r11d,edi
+	shr	r10d,7
+	lea	r8d,DWORD PTR[rax*1+rax]
+	shr	r11d,7
+	lea	r9d,DWORD PTR[rbx*1+rbx]
+	sub	esi,r10d
+	sub	edi,r11d
+	and	r8d,0fefefefeh
+	and	r9d,0fefefefeh
+	and	esi,01b1b1b1bh
+	and	edi,01b1b1b1bh
+	mov	r10d,eax
+	mov	r11d,ebx
+	xor	r8d,esi
+	xor	r9d,edi
+
+	xor	eax,r8d
+	xor	ebx,r9d
+	mov	esi,ecx
+	mov	edi,edx
+	rol	eax,24
+	rol	ebx,24
+	and	esi,080808080h
+	and	edi,080808080h
+	xor	eax,r8d
+	xor	ebx,r9d
+	mov	r12d,esi
+	mov	ebp,edi
+	ror	r10d,16
+	ror	r11d,16
+	shr	r12d,7
+	lea	r8d,DWORD PTR[rcx*1+rcx]
+	xor	eax,r10d
+	xor	ebx,r11d
+	shr	ebp,7
+	lea	r9d,DWORD PTR[rdx*1+rdx]
+	ror	r10d,8
+	ror	r11d,8
+	sub	esi,r12d
+	sub	edi,ebp
+	xor	eax,r10d
+	xor	ebx,r11d
+
+	and	r8d,0fefefefeh
+	and	r9d,0fefefefeh
+	and	esi,01b1b1b1bh
+	and	edi,01b1b1b1bh
+	mov	r12d,ecx
+	mov	ebp,edx
+	xor	r8d,esi
+	xor	r9d,edi
+
+	xor	ecx,r8d
+	xor	edx,r9d
+	rol	ecx,24
+	rol	edx,24
+	xor	ecx,r8d
+	xor	edx,r9d
+	mov	esi,DWORD PTR[r14]
+	ror	r12d,16
+	ror	ebp,16
+	mov	edi,DWORD PTR[64+r14]
+	xor	ecx,r12d
+	xor	edx,ebp
+	mov	r8d,DWORD PTR[128+r14]
+	ror	r12d,8
+	ror	ebp,8
+	mov	r9d,DWORD PTR[192+r14]
+	xor	ecx,r12d
+	xor	edx,ebp
+	jmp	$L$enc_loop_compact
+ALIGN	16
+$L$enc_compact_done::
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+	DB	0F3h,0C3h		;repret
+_x86_64_AES_encrypt_compact	ENDP
+PUBLIC	AES_encrypt
+
+ALIGN	16
+PUBLIC	asm_AES_encrypt
+
+asm_AES_encrypt::
+AES_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_AES_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+
+	mov	r10,rsp
+	lea	rcx,QWORD PTR[((-63))+rdx]
+	and	rsp,-64
+	sub	rcx,rsp
+	neg	rcx
+	and	rcx,03c0h
+	sub	rsp,rcx
+	sub	rsp,32
+
+	mov	QWORD PTR[16+rsp],rsi
+	mov	QWORD PTR[24+rsp],r10
+$L$enc_prologue::
+
+	mov	r15,rdx
+	mov	r13d,DWORD PTR[240+r15]
+
+	mov	eax,DWORD PTR[rdi]
+	mov	ebx,DWORD PTR[4+rdi]
+	mov	ecx,DWORD PTR[8+rdi]
+	mov	edx,DWORD PTR[12+rdi]
+
+	shl	r13d,4
+	lea	rbp,QWORD PTR[r13*1+r15]
+	mov	QWORD PTR[rsp],r15
+	mov	QWORD PTR[8+rsp],rbp
+
+
+	lea	r14,QWORD PTR[(($L$AES_Te+2048))]
+	lea	rbp,QWORD PTR[768+rsp]
+	sub	rbp,r14
+	and	rbp,0300h
+	lea	r14,QWORD PTR[rbp*1+r14]
+
+	call	_x86_64_AES_encrypt_compact
+
+	mov	r9,QWORD PTR[16+rsp]
+	mov	rsi,QWORD PTR[24+rsp]
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$enc_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_AES_encrypt::
+AES_encrypt	ENDP
+
+ALIGN	16
+_x86_64_AES_decrypt	PROC PRIVATE
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+
+	mov	r13d,DWORD PTR[240+r15]
+	sub	r13d,1
+	jmp	$L$dec_loop
+ALIGN	16
+$L$dec_loop::
+
+	movzx	esi,al
+	movzx	edi,bl
+	movzx	ebp,cl
+	mov	r10d,DWORD PTR[rsi*8+r14]
+	mov	r11d,DWORD PTR[rdi*8+r14]
+	mov	r12d,DWORD PTR[rbp*8+r14]
+
+	movzx	esi,dh
+	movzx	edi,ah
+	movzx	ebp,dl
+	xor	r10d,DWORD PTR[3+rsi*8+r14]
+	xor	r11d,DWORD PTR[3+rdi*8+r14]
+	mov	r8d,DWORD PTR[rbp*8+r14]
+
+	movzx	esi,bh
+	shr	eax,16
+	movzx	ebp,ch
+	xor	r12d,DWORD PTR[3+rsi*8+r14]
+	shr	edx,16
+	xor	r8d,DWORD PTR[3+rbp*8+r14]
+
+	shr	ebx,16
+	lea	r15,QWORD PTR[16+r15]
+	shr	ecx,16
+
+	movzx	esi,cl
+	movzx	edi,dl
+	movzx	ebp,al
+	xor	r10d,DWORD PTR[2+rsi*8+r14]
+	xor	r11d,DWORD PTR[2+rdi*8+r14]
+	xor	r12d,DWORD PTR[2+rbp*8+r14]
+
+	movzx	esi,bh
+	movzx	edi,ch
+	movzx	ebp,bl
+	xor	r10d,DWORD PTR[1+rsi*8+r14]
+	xor	r11d,DWORD PTR[1+rdi*8+r14]
+	xor	r8d,DWORD PTR[2+rbp*8+r14]
+
+	movzx	esi,dh
+	mov	edx,DWORD PTR[12+r15]
+	movzx	ebp,ah
+	xor	r12d,DWORD PTR[1+rsi*8+r14]
+	mov	eax,DWORD PTR[r15]
+	xor	r8d,DWORD PTR[1+rbp*8+r14]
+
+	xor	eax,r10d
+	mov	ebx,DWORD PTR[4+r15]
+	mov	ecx,DWORD PTR[8+r15]
+	xor	ecx,r12d
+	xor	ebx,r11d
+	xor	edx,r8d
+	sub	r13d,1
+	jnz	$L$dec_loop
+	lea	r14,QWORD PTR[2048+r14]
+	movzx	esi,al
+	movzx	edi,bl
+	movzx	ebp,cl
+	movzx	r10d,BYTE PTR[rsi*1+r14]
+	movzx	r11d,BYTE PTR[rdi*1+r14]
+	movzx	r12d,BYTE PTR[rbp*1+r14]
+
+	movzx	esi,dl
+	movzx	edi,dh
+	movzx	ebp,ah
+	movzx	r8d,BYTE PTR[rsi*1+r14]
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+
+	shl	edi,8
+	shl	ebp,8
+
+	xor	r10d,edi
+	xor	r11d,ebp
+	shr	edx,16
+
+	movzx	esi,bh
+	movzx	edi,ch
+	shr	eax,16
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	movzx	edi,BYTE PTR[rdi*1+r14]
+
+	shl	esi,8
+	shl	edi,8
+	shr	ebx,16
+	xor	r12d,esi
+	xor	r8d,edi
+	shr	ecx,16
+
+	movzx	esi,cl
+	movzx	edi,dl
+	movzx	ebp,al
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+
+	shl	esi,16
+	shl	edi,16
+	shl	ebp,16
+
+	xor	r10d,esi
+	xor	r11d,edi
+	xor	r12d,ebp
+
+	movzx	esi,bl
+	movzx	edi,bh
+	movzx	ebp,ch
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+
+	shl	esi,16
+	shl	edi,24
+	shl	ebp,24
+
+	xor	r8d,esi
+	xor	r10d,edi
+	xor	r11d,ebp
+
+	movzx	esi,dh
+	movzx	edi,ah
+	mov	edx,DWORD PTR[((16+12))+r15]
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	mov	eax,DWORD PTR[((16+0))+r15]
+
+	shl	esi,24
+	shl	edi,24
+
+	xor	r12d,esi
+	xor	r8d,edi
+
+	mov	ebx,DWORD PTR[((16+4))+r15]
+	mov	ecx,DWORD PTR[((16+8))+r15]
+	lea	r14,QWORD PTR[((-2048))+r14]
+	xor	eax,r10d
+	xor	ebx,r11d
+	xor	ecx,r12d
+	xor	edx,r8d
+	DB	0F3h,0C3h		;repret
+_x86_64_AES_decrypt	ENDP
+
+ALIGN	16
+_x86_64_AES_decrypt_compact	PROC PRIVATE
+	lea	r8,QWORD PTR[128+r14]
+	mov	edi,DWORD PTR[((0-128))+r8]
+	mov	ebp,DWORD PTR[((32-128))+r8]
+	mov	r10d,DWORD PTR[((64-128))+r8]
+	mov	r11d,DWORD PTR[((96-128))+r8]
+	mov	edi,DWORD PTR[((128-128))+r8]
+	mov	ebp,DWORD PTR[((160-128))+r8]
+	mov	r10d,DWORD PTR[((192-128))+r8]
+	mov	r11d,DWORD PTR[((224-128))+r8]
+	jmp	$L$dec_loop_compact
+
+ALIGN	16
+$L$dec_loop_compact::
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+	lea	r15,QWORD PTR[16+r15]
+	movzx	r10d,al
+	movzx	r11d,bl
+	movzx	r12d,cl
+	movzx	r10d,BYTE PTR[r10*1+r14]
+	movzx	r11d,BYTE PTR[r11*1+r14]
+	movzx	r12d,BYTE PTR[r12*1+r14]
+
+	movzx	r8d,dl
+	movzx	esi,dh
+	movzx	edi,ah
+	movzx	r8d,BYTE PTR[r8*1+r14]
+	movzx	r9d,BYTE PTR[rsi*1+r14]
+	movzx	r13d,BYTE PTR[rdi*1+r14]
+
+	movzx	ebp,bh
+	movzx	esi,ch
+	shr	ecx,16
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	shr	edx,16
+
+	movzx	edi,cl
+	shl	r9d,8
+	shl	r13d,8
+	movzx	edi,BYTE PTR[rdi*1+r14]
+	xor	r10d,r9d
+	xor	r11d,r13d
+
+	movzx	r9d,dl
+	shr	eax,16
+	shr	ebx,16
+	movzx	r13d,al
+	shl	ebp,8
+	shl	esi,8
+	movzx	r9d,BYTE PTR[r9*1+r14]
+	movzx	r13d,BYTE PTR[r13*1+r14]
+	xor	r12d,ebp
+	xor	r8d,esi
+
+	movzx	ebp,bl
+	movzx	esi,bh
+	shl	edi,16
+	movzx	ebp,BYTE PTR[rbp*1+r14]
+	movzx	esi,BYTE PTR[rsi*1+r14]
+	xor	r10d,edi
+
+	movzx	edi,ch
+	shl	r9d,16
+	shl	r13d,16
+	movzx	ebx,BYTE PTR[rdi*1+r14]
+	xor	r11d,r9d
+	xor	r12d,r13d
+
+	movzx	edi,dh
+	shr	eax,8
+	shl	ebp,16
+	movzx	ecx,BYTE PTR[rdi*1+r14]
+	movzx	edx,BYTE PTR[rax*1+r14]
+	xor	r8d,ebp
+
+	shl	esi,24
+	shl	ebx,24
+	shl	ecx,24
+	xor	r10d,esi
+	shl	edx,24
+	xor	ebx,r11d
+	mov	eax,r10d
+	xor	ecx,r12d
+	xor	edx,r8d
+	cmp	r15,QWORD PTR[16+rsp]
+	je	$L$dec_compact_done
+
+	mov	rsi,QWORD PTR[((256+0))+r14]
+	shl	rbx,32
+	shl	rdx,32
+	mov	rdi,QWORD PTR[((256+8))+r14]
+	or	rax,rbx
+	or	rcx,rdx
+	mov	rbp,QWORD PTR[((256+16))+r14]
+	mov	rbx,rax
+	mov	rdx,rcx
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r9,rbx
+	mov	r12,rdx
+	shr	r9,7
+	lea	r8,QWORD PTR[rax*1+rax]
+	shr	r12,7
+	lea	r11,QWORD PTR[rcx*1+rcx]
+	sub	rbx,r9
+	sub	rdx,r12
+	and	r8,rdi
+	and	r11,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	rbx,r8
+	xor	rdx,r11
+	mov	r8,rbx
+	mov	r11,rdx
+
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r10,rbx
+	mov	r13,rdx
+	shr	r10,7
+	lea	r9,QWORD PTR[r8*1+r8]
+	shr	r13,7
+	lea	r12,QWORD PTR[r11*1+r11]
+	sub	rbx,r10
+	sub	rdx,r13
+	and	r9,rdi
+	and	r12,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	rbx,r9
+	xor	rdx,r12
+	mov	r9,rbx
+	mov	r12,rdx
+
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r10,rbx
+	mov	r13,rdx
+	shr	r10,7
+	xor	r8,rax
+	shr	r13,7
+	xor	r11,rcx
+	sub	rbx,r10
+	sub	rdx,r13
+	lea	r10,QWORD PTR[r9*1+r9]
+	lea	r13,QWORD PTR[r12*1+r12]
+	xor	r9,rax
+	xor	r12,rcx
+	and	r10,rdi
+	and	r13,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	r10,rbx
+	xor	r13,rdx
+
+	xor	rax,r10
+	xor	rcx,r13
+	xor	r8,r10
+	xor	r11,r13
+	mov	rbx,rax
+	mov	rdx,rcx
+	xor	r9,r10
+	xor	r12,r13
+	shr	rbx,32
+	shr	rdx,32
+	xor	r10,r8
+	xor	r13,r11
+	rol	eax,8
+	rol	ecx,8
+	xor	r10,r9
+	xor	r13,r12
+
+	rol	ebx,8
+	rol	edx,8
+	xor	eax,r10d
+	xor	ecx,r13d
+	shr	r10,32
+	shr	r13,32
+	xor	ebx,r10d
+	xor	edx,r13d
+
+	mov	r10,r8
+	mov	r13,r11
+	shr	r10,32
+	shr	r13,32
+	rol	r8d,24
+	rol	r11d,24
+	rol	r10d,24
+	rol	r13d,24
+	xor	eax,r8d
+	xor	ecx,r11d
+	mov	r8,r9
+	mov	r11,r12
+	xor	ebx,r10d
+	xor	edx,r13d
+
+	mov	rsi,QWORD PTR[r14]
+	shr	r8,32
+	shr	r11,32
+	mov	rdi,QWORD PTR[64+r14]
+	rol	r9d,16
+	rol	r12d,16
+	mov	rbp,QWORD PTR[128+r14]
+	rol	r8d,16
+	rol	r11d,16
+	mov	r10,QWORD PTR[192+r14]
+	xor	eax,r9d
+	xor	ecx,r12d
+	mov	r13,QWORD PTR[256+r14]
+	xor	ebx,r8d
+	xor	edx,r11d
+	jmp	$L$dec_loop_compact
+ALIGN	16
+$L$dec_compact_done::
+	xor	eax,DWORD PTR[r15]
+	xor	ebx,DWORD PTR[4+r15]
+	xor	ecx,DWORD PTR[8+r15]
+	xor	edx,DWORD PTR[12+r15]
+	DB	0F3h,0C3h		;repret
+_x86_64_AES_decrypt_compact	ENDP
+PUBLIC	AES_decrypt
+
+ALIGN	16
+PUBLIC	asm_AES_decrypt
+
+asm_AES_decrypt::
+AES_decrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_AES_decrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+
+	mov	r10,rsp
+	lea	rcx,QWORD PTR[((-63))+rdx]
+	and	rsp,-64
+	sub	rcx,rsp
+	neg	rcx
+	and	rcx,03c0h
+	sub	rsp,rcx
+	sub	rsp,32
+
+	mov	QWORD PTR[16+rsp],rsi
+	mov	QWORD PTR[24+rsp],r10
+$L$dec_prologue::
+
+	mov	r15,rdx
+	mov	r13d,DWORD PTR[240+r15]
+
+	mov	eax,DWORD PTR[rdi]
+	mov	ebx,DWORD PTR[4+rdi]
+	mov	ecx,DWORD PTR[8+rdi]
+	mov	edx,DWORD PTR[12+rdi]
+
+	shl	r13d,4
+	lea	rbp,QWORD PTR[r13*1+r15]
+	mov	QWORD PTR[rsp],r15
+	mov	QWORD PTR[8+rsp],rbp
+
+
+	lea	r14,QWORD PTR[(($L$AES_Td+2048))]
+	lea	rbp,QWORD PTR[768+rsp]
+	sub	rbp,r14
+	and	rbp,0300h
+	lea	r14,QWORD PTR[rbp*1+r14]
+	shr	rbp,3
+	add	r14,rbp
+
+	call	_x86_64_AES_decrypt_compact
+
+	mov	r9,QWORD PTR[16+rsp]
+	mov	rsi,QWORD PTR[24+rsp]
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$dec_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_AES_decrypt::
+AES_decrypt	ENDP
+PUBLIC	AES_set_encrypt_key
+
+ALIGN	16
+AES_set_encrypt_key	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_AES_set_encrypt_key::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	sub	rsp,8
+$L$enc_key_prologue::
+
+	call	_x86_64_AES_set_encrypt_key
+
+	mov	r15,QWORD PTR[8+rsp]
+	mov	r14,QWORD PTR[16+rsp]
+	mov	r13,QWORD PTR[24+rsp]
+	mov	r12,QWORD PTR[32+rsp]
+	mov	rbp,QWORD PTR[40+rsp]
+	mov	rbx,QWORD PTR[48+rsp]
+	add	rsp,56
+$L$enc_key_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_AES_set_encrypt_key::
+AES_set_encrypt_key	ENDP
+
+
+ALIGN	16
+_x86_64_AES_set_encrypt_key	PROC PRIVATE
+	mov	ecx,esi
+	mov	rsi,rdi
+	mov	rdi,rdx
+
+	test	rsi,-1
+	jz	$L$badpointer
+	test	rdi,-1
+	jz	$L$badpointer
+
+	lea	rbp,QWORD PTR[$L$AES_Te]
+	lea	rbp,QWORD PTR[((2048+128))+rbp]
+
+
+	mov	eax,DWORD PTR[((0-128))+rbp]
+	mov	ebx,DWORD PTR[((32-128))+rbp]
+	mov	r8d,DWORD PTR[((64-128))+rbp]
+	mov	edx,DWORD PTR[((96-128))+rbp]
+	mov	eax,DWORD PTR[((128-128))+rbp]
+	mov	ebx,DWORD PTR[((160-128))+rbp]
+	mov	r8d,DWORD PTR[((192-128))+rbp]
+	mov	edx,DWORD PTR[((224-128))+rbp]
+
+	cmp	ecx,128
+	je	$L$10rounds
+	cmp	ecx,192
+	je	$L$12rounds
+	cmp	ecx,256
+	je	$L$14rounds
+	mov	rax,-2
+	jmp	$L$exit
+
+$L$10rounds::
+	mov	rax,QWORD PTR[rsi]
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	QWORD PTR[rdi],rax
+	mov	QWORD PTR[8+rdi],rdx
+
+	shr	rdx,32
+	xor	ecx,ecx
+	jmp	$L$10shortcut
+ALIGN	4
+$L$10loop::
+	mov	eax,DWORD PTR[rdi]
+	mov	edx,DWORD PTR[12+rdi]
+$L$10shortcut::
+	movzx	esi,dl
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,24
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shr	edx,16
+	movzx	esi,dl
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,8
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shl	ebx,16
+	xor	eax,ebx
+
+	xor	eax,DWORD PTR[((1024-128))+rcx*4+rbp]
+	mov	DWORD PTR[16+rdi],eax
+	xor	eax,DWORD PTR[4+rdi]
+	mov	DWORD PTR[20+rdi],eax
+	xor	eax,DWORD PTR[8+rdi]
+	mov	DWORD PTR[24+rdi],eax
+	xor	eax,DWORD PTR[12+rdi]
+	mov	DWORD PTR[28+rdi],eax
+	add	ecx,1
+	lea	rdi,QWORD PTR[16+rdi]
+	cmp	ecx,10
+	jl	$L$10loop
+
+	mov	DWORD PTR[80+rdi],10
+	xor	rax,rax
+	jmp	$L$exit
+
+$L$12rounds::
+	mov	rax,QWORD PTR[rsi]
+	mov	rbx,QWORD PTR[8+rsi]
+	mov	rdx,QWORD PTR[16+rsi]
+	mov	QWORD PTR[rdi],rax
+	mov	QWORD PTR[8+rdi],rbx
+	mov	QWORD PTR[16+rdi],rdx
+
+	shr	rdx,32
+	xor	ecx,ecx
+	jmp	$L$12shortcut
+ALIGN	4
+$L$12loop::
+	mov	eax,DWORD PTR[rdi]
+	mov	edx,DWORD PTR[20+rdi]
+$L$12shortcut::
+	movzx	esi,dl
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,24
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shr	edx,16
+	movzx	esi,dl
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,8
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shl	ebx,16
+	xor	eax,ebx
+
+	xor	eax,DWORD PTR[((1024-128))+rcx*4+rbp]
+	mov	DWORD PTR[24+rdi],eax
+	xor	eax,DWORD PTR[4+rdi]
+	mov	DWORD PTR[28+rdi],eax
+	xor	eax,DWORD PTR[8+rdi]
+	mov	DWORD PTR[32+rdi],eax
+	xor	eax,DWORD PTR[12+rdi]
+	mov	DWORD PTR[36+rdi],eax
+
+	cmp	ecx,7
+	je	$L$12break
+	add	ecx,1
+
+	xor	eax,DWORD PTR[16+rdi]
+	mov	DWORD PTR[40+rdi],eax
+	xor	eax,DWORD PTR[20+rdi]
+	mov	DWORD PTR[44+rdi],eax
+
+	lea	rdi,QWORD PTR[24+rdi]
+	jmp	$L$12loop
+$L$12break::
+	mov	DWORD PTR[72+rdi],12
+	xor	rax,rax
+	jmp	$L$exit
+
+$L$14rounds::
+	mov	rax,QWORD PTR[rsi]
+	mov	rbx,QWORD PTR[8+rsi]
+	mov	rcx,QWORD PTR[16+rsi]
+	mov	rdx,QWORD PTR[24+rsi]
+	mov	QWORD PTR[rdi],rax
+	mov	QWORD PTR[8+rdi],rbx
+	mov	QWORD PTR[16+rdi],rcx
+	mov	QWORD PTR[24+rdi],rdx
+
+	shr	rdx,32
+	xor	ecx,ecx
+	jmp	$L$14shortcut
+ALIGN	4
+$L$14loop::
+	mov	eax,DWORD PTR[rdi]
+	mov	edx,DWORD PTR[28+rdi]
+$L$14shortcut::
+	movzx	esi,dl
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,24
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shr	edx,16
+	movzx	esi,dl
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,8
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shl	ebx,16
+	xor	eax,ebx
+
+	xor	eax,DWORD PTR[((1024-128))+rcx*4+rbp]
+	mov	DWORD PTR[32+rdi],eax
+	xor	eax,DWORD PTR[4+rdi]
+	mov	DWORD PTR[36+rdi],eax
+	xor	eax,DWORD PTR[8+rdi]
+	mov	DWORD PTR[40+rdi],eax
+	xor	eax,DWORD PTR[12+rdi]
+	mov	DWORD PTR[44+rdi],eax
+
+	cmp	ecx,6
+	je	$L$14break
+	add	ecx,1
+
+	mov	edx,eax
+	mov	eax,DWORD PTR[16+rdi]
+	movzx	esi,dl
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shr	edx,16
+	shl	ebx,8
+	movzx	esi,dl
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	movzx	esi,dh
+	shl	ebx,16
+	xor	eax,ebx
+
+	movzx	ebx,BYTE PTR[((-128))+rsi*1+rbp]
+	shl	ebx,24
+	xor	eax,ebx
+
+	mov	DWORD PTR[48+rdi],eax
+	xor	eax,DWORD PTR[20+rdi]
+	mov	DWORD PTR[52+rdi],eax
+	xor	eax,DWORD PTR[24+rdi]
+	mov	DWORD PTR[56+rdi],eax
+	xor	eax,DWORD PTR[28+rdi]
+	mov	DWORD PTR[60+rdi],eax
+
+	lea	rdi,QWORD PTR[32+rdi]
+	jmp	$L$14loop
+$L$14break::
+	mov	DWORD PTR[48+rdi],14
+	xor	rax,rax
+	jmp	$L$exit
+
+$L$badpointer::
+	mov	rax,-1
+$L$exit::
+	DB	0F3h,0C3h		;repret
+_x86_64_AES_set_encrypt_key	ENDP
+PUBLIC	AES_set_decrypt_key
+
+ALIGN	16
+AES_set_decrypt_key	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_AES_set_decrypt_key::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	push	rdx
+$L$dec_key_prologue::
+
+	call	_x86_64_AES_set_encrypt_key
+	mov	r8,QWORD PTR[rsp]
+	cmp	eax,0
+	jne	$L$abort
+
+	mov	r14d,DWORD PTR[240+r8]
+	xor	rdi,rdi
+	lea	rcx,QWORD PTR[r14*4+rdi]
+	mov	rsi,r8
+	lea	rdi,QWORD PTR[rcx*4+r8]
+ALIGN	4
+$L$invert::
+	mov	rax,QWORD PTR[rsi]
+	mov	rbx,QWORD PTR[8+rsi]
+	mov	rcx,QWORD PTR[rdi]
+	mov	rdx,QWORD PTR[8+rdi]
+	mov	QWORD PTR[rdi],rax
+	mov	QWORD PTR[8+rdi],rbx
+	mov	QWORD PTR[rsi],rcx
+	mov	QWORD PTR[8+rsi],rdx
+	lea	rsi,QWORD PTR[16+rsi]
+	lea	rdi,QWORD PTR[((-16))+rdi]
+	cmp	rdi,rsi
+	jne	$L$invert
+
+	lea	rax,QWORD PTR[(($L$AES_Te+2048+1024))]
+
+	mov	rsi,QWORD PTR[40+rax]
+	mov	rdi,QWORD PTR[48+rax]
+	mov	rbp,QWORD PTR[56+rax]
+
+	mov	r15,r8
+	sub	r14d,1
+ALIGN	4
+$L$permute::
+	lea	r15,QWORD PTR[16+r15]
+	mov	rax,QWORD PTR[r15]
+	mov	rcx,QWORD PTR[8+r15]
+	mov	rbx,rax
+	mov	rdx,rcx
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r9,rbx
+	mov	r12,rdx
+	shr	r9,7
+	lea	r8,QWORD PTR[rax*1+rax]
+	shr	r12,7
+	lea	r11,QWORD PTR[rcx*1+rcx]
+	sub	rbx,r9
+	sub	rdx,r12
+	and	r8,rdi
+	and	r11,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	rbx,r8
+	xor	rdx,r11
+	mov	r8,rbx
+	mov	r11,rdx
+
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r10,rbx
+	mov	r13,rdx
+	shr	r10,7
+	lea	r9,QWORD PTR[r8*1+r8]
+	shr	r13,7
+	lea	r12,QWORD PTR[r11*1+r11]
+	sub	rbx,r10
+	sub	rdx,r13
+	and	r9,rdi
+	and	r12,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	rbx,r9
+	xor	rdx,r12
+	mov	r9,rbx
+	mov	r12,rdx
+
+	and	rbx,rsi
+	and	rdx,rsi
+	mov	r10,rbx
+	mov	r13,rdx
+	shr	r10,7
+	xor	r8,rax
+	shr	r13,7
+	xor	r11,rcx
+	sub	rbx,r10
+	sub	rdx,r13
+	lea	r10,QWORD PTR[r9*1+r9]
+	lea	r13,QWORD PTR[r12*1+r12]
+	xor	r9,rax
+	xor	r12,rcx
+	and	r10,rdi
+	and	r13,rdi
+	and	rbx,rbp
+	and	rdx,rbp
+	xor	r10,rbx
+	xor	r13,rdx
+
+	xor	rax,r10
+	xor	rcx,r13
+	xor	r8,r10
+	xor	r11,r13
+	mov	rbx,rax
+	mov	rdx,rcx
+	xor	r9,r10
+	xor	r12,r13
+	shr	rbx,32
+	shr	rdx,32
+	xor	r10,r8
+	xor	r13,r11
+	rol	eax,8
+	rol	ecx,8
+	xor	r10,r9
+	xor	r13,r12
+
+	rol	ebx,8
+	rol	edx,8
+	xor	eax,r10d
+	xor	ecx,r13d
+	shr	r10,32
+	shr	r13,32
+	xor	ebx,r10d
+	xor	edx,r13d
+
+	mov	r10,r8
+	mov	r13,r11
+	shr	r10,32
+	shr	r13,32
+	rol	r8d,24
+	rol	r11d,24
+	rol	r10d,24
+	rol	r13d,24
+	xor	eax,r8d
+	xor	ecx,r11d
+	mov	r8,r9
+	mov	r11,r12
+	xor	ebx,r10d
+	xor	edx,r13d
+
+
+	shr	r8,32
+	shr	r11,32
+
+	rol	r9d,16
+	rol	r12d,16
+
+	rol	r8d,16
+	rol	r11d,16
+
+	xor	eax,r9d
+	xor	ecx,r12d
+
+	xor	ebx,r8d
+	xor	edx,r11d
+	mov	DWORD PTR[r15],eax
+	mov	DWORD PTR[4+r15],ebx
+	mov	DWORD PTR[8+r15],ecx
+	mov	DWORD PTR[12+r15],edx
+	sub	r14d,1
+	jnz	$L$permute
+
+	xor	rax,rax
+$L$abort::
+	mov	r15,QWORD PTR[8+rsp]
+	mov	r14,QWORD PTR[16+rsp]
+	mov	r13,QWORD PTR[24+rsp]
+	mov	r12,QWORD PTR[32+rsp]
+	mov	rbp,QWORD PTR[40+rsp]
+	mov	rbx,QWORD PTR[48+rsp]
+	add	rsp,56
+$L$dec_key_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_AES_set_decrypt_key::
+AES_set_decrypt_key	ENDP
+PUBLIC	AES_cbc_encrypt
+
+ALIGN	16
+EXTERN	OPENSSL_ia32cap_P:NEAR
+
+PUBLIC	asm_AES_cbc_encrypt
+
+asm_AES_cbc_encrypt::
+AES_cbc_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_AES_cbc_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	cmp	rdx,0
+	je	$L$cbc_epilogue
+	pushfq
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+$L$cbc_prologue::
+
+	cld
+	mov	r9d,r9d
+
+	lea	r14,QWORD PTR[$L$AES_Te]
+	cmp	r9,0
+	jne	$L$cbc_picked_te
+	lea	r14,QWORD PTR[$L$AES_Td]
+$L$cbc_picked_te::
+
+	mov	r10d,DWORD PTR[OPENSSL_ia32cap_P]
+	cmp	rdx,512
+	jb	$L$cbc_slow_prologue
+	test	rdx,15
+	jnz	$L$cbc_slow_prologue
+	bt	r10d,28
+	jc	$L$cbc_slow_prologue
+
+
+	lea	r15,QWORD PTR[((-88-248))+rsp]
+	and	r15,-64
+
+
+	mov	r10,r14
+	lea	r11,QWORD PTR[2304+r14]
+	mov	r12,r15
+	and	r10,0FFFh
+	and	r11,0FFFh
+	and	r12,0FFFh
+
+	cmp	r12,r11
+	jb	$L$cbc_te_break_out
+	sub	r12,r11
+	sub	r15,r12
+	jmp	$L$cbc_te_ok
+$L$cbc_te_break_out::
+	sub	r12,r10
+	and	r12,0FFFh
+	add	r12,320
+	sub	r15,r12
+ALIGN	4
+$L$cbc_te_ok::
+
+	xchg	r15,rsp
+
+	mov	QWORD PTR[16+rsp],r15
+$L$cbc_fast_body::
+	mov	QWORD PTR[24+rsp],rdi
+	mov	QWORD PTR[32+rsp],rsi
+	mov	QWORD PTR[40+rsp],rdx
+	mov	QWORD PTR[48+rsp],rcx
+	mov	QWORD PTR[56+rsp],r8
+	mov	DWORD PTR[((80+240))+rsp],0
+	mov	rbp,r8
+	mov	rbx,r9
+	mov	r9,rsi
+	mov	r8,rdi
+	mov	r15,rcx
+
+	mov	eax,DWORD PTR[240+r15]
+
+	mov	r10,r15
+	sub	r10,r14
+	and	r10,0fffh
+	cmp	r10,2304
+	jb	$L$cbc_do_ecopy
+	cmp	r10,4096-248
+	jb	$L$cbc_skip_ecopy
+ALIGN	4
+$L$cbc_do_ecopy::
+	mov	rsi,r15
+	lea	rdi,QWORD PTR[80+rsp]
+	lea	r15,QWORD PTR[80+rsp]
+	mov	ecx,240/8
+	DD	090A548F3h	
+	mov	DWORD PTR[rdi],eax
+$L$cbc_skip_ecopy::
+	mov	QWORD PTR[rsp],r15
+
+	mov	ecx,18
+ALIGN	4
+$L$cbc_prefetch_te::
+	mov	r10,QWORD PTR[r14]
+	mov	r11,QWORD PTR[32+r14]
+	mov	r12,QWORD PTR[64+r14]
+	mov	r13,QWORD PTR[96+r14]
+	lea	r14,QWORD PTR[128+r14]
+	sub	ecx,1
+	jnz	$L$cbc_prefetch_te
+	lea	r14,QWORD PTR[((-2304))+r14]
+
+	cmp	rbx,0
+	je	$L$FAST_DECRYPT
+
+
+	mov	eax,DWORD PTR[rbp]
+	mov	ebx,DWORD PTR[4+rbp]
+	mov	ecx,DWORD PTR[8+rbp]
+	mov	edx,DWORD PTR[12+rbp]
+
+ALIGN	4
+$L$cbc_fast_enc_loop::
+	xor	eax,DWORD PTR[r8]
+	xor	ebx,DWORD PTR[4+r8]
+	xor	ecx,DWORD PTR[8+r8]
+	xor	edx,DWORD PTR[12+r8]
+	mov	r15,QWORD PTR[rsp]
+	mov	QWORD PTR[24+rsp],r8
+
+	call	_x86_64_AES_encrypt
+
+	mov	r8,QWORD PTR[24+rsp]
+	mov	r10,QWORD PTR[40+rsp]
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	lea	r8,QWORD PTR[16+r8]
+	lea	r9,QWORD PTR[16+r9]
+	sub	r10,16
+	test	r10,-16
+	mov	QWORD PTR[40+rsp],r10
+	jnz	$L$cbc_fast_enc_loop
+	mov	rbp,QWORD PTR[56+rsp]
+	mov	DWORD PTR[rbp],eax
+	mov	DWORD PTR[4+rbp],ebx
+	mov	DWORD PTR[8+rbp],ecx
+	mov	DWORD PTR[12+rbp],edx
+
+	jmp	$L$cbc_fast_cleanup
+
+
+ALIGN	16
+$L$FAST_DECRYPT::
+	cmp	r9,r8
+	je	$L$cbc_fast_dec_in_place
+
+	mov	QWORD PTR[64+rsp],rbp
+ALIGN	4
+$L$cbc_fast_dec_loop::
+	mov	eax,DWORD PTR[r8]
+	mov	ebx,DWORD PTR[4+r8]
+	mov	ecx,DWORD PTR[8+r8]
+	mov	edx,DWORD PTR[12+r8]
+	mov	r15,QWORD PTR[rsp]
+	mov	QWORD PTR[24+rsp],r8
+
+	call	_x86_64_AES_decrypt
+
+	mov	rbp,QWORD PTR[64+rsp]
+	mov	r8,QWORD PTR[24+rsp]
+	mov	r10,QWORD PTR[40+rsp]
+	xor	eax,DWORD PTR[rbp]
+	xor	ebx,DWORD PTR[4+rbp]
+	xor	ecx,DWORD PTR[8+rbp]
+	xor	edx,DWORD PTR[12+rbp]
+	mov	rbp,r8
+
+	sub	r10,16
+	mov	QWORD PTR[40+rsp],r10
+	mov	QWORD PTR[64+rsp],rbp
+
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	lea	r8,QWORD PTR[16+r8]
+	lea	r9,QWORD PTR[16+r9]
+	jnz	$L$cbc_fast_dec_loop
+	mov	r12,QWORD PTR[56+rsp]
+	mov	r10,QWORD PTR[rbp]
+	mov	r11,QWORD PTR[8+rbp]
+	mov	QWORD PTR[r12],r10
+	mov	QWORD PTR[8+r12],r11
+	jmp	$L$cbc_fast_cleanup
+
+ALIGN	16
+$L$cbc_fast_dec_in_place::
+	mov	r10,QWORD PTR[rbp]
+	mov	r11,QWORD PTR[8+rbp]
+	mov	QWORD PTR[((0+64))+rsp],r10
+	mov	QWORD PTR[((8+64))+rsp],r11
+ALIGN	4
+$L$cbc_fast_dec_in_place_loop::
+	mov	eax,DWORD PTR[r8]
+	mov	ebx,DWORD PTR[4+r8]
+	mov	ecx,DWORD PTR[8+r8]
+	mov	edx,DWORD PTR[12+r8]
+	mov	r15,QWORD PTR[rsp]
+	mov	QWORD PTR[24+rsp],r8
+
+	call	_x86_64_AES_decrypt
+
+	mov	r8,QWORD PTR[24+rsp]
+	mov	r10,QWORD PTR[40+rsp]
+	xor	eax,DWORD PTR[((0+64))+rsp]
+	xor	ebx,DWORD PTR[((4+64))+rsp]
+	xor	ecx,DWORD PTR[((8+64))+rsp]
+	xor	edx,DWORD PTR[((12+64))+rsp]
+
+	mov	r11,QWORD PTR[r8]
+	mov	r12,QWORD PTR[8+r8]
+	sub	r10,16
+	jz	$L$cbc_fast_dec_in_place_done
+
+	mov	QWORD PTR[((0+64))+rsp],r11
+	mov	QWORD PTR[((8+64))+rsp],r12
+
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	lea	r8,QWORD PTR[16+r8]
+	lea	r9,QWORD PTR[16+r9]
+	mov	QWORD PTR[40+rsp],r10
+	jmp	$L$cbc_fast_dec_in_place_loop
+$L$cbc_fast_dec_in_place_done::
+	mov	rdi,QWORD PTR[56+rsp]
+	mov	QWORD PTR[rdi],r11
+	mov	QWORD PTR[8+rdi],r12
+
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+ALIGN	4
+$L$cbc_fast_cleanup::
+	cmp	DWORD PTR[((80+240))+rsp],0
+	lea	rdi,QWORD PTR[80+rsp]
+	je	$L$cbc_exit
+	mov	ecx,240/8
+	xor	rax,rax
+	DD	090AB48F3h	
+
+	jmp	$L$cbc_exit
+
+
+ALIGN	16
+$L$cbc_slow_prologue::
+
+	lea	rbp,QWORD PTR[((-88))+rsp]
+	and	rbp,-64
+
+	lea	r10,QWORD PTR[((-88-63))+rcx]
+	sub	r10,rbp
+	neg	r10
+	and	r10,03c0h
+	sub	rbp,r10
+
+	xchg	rbp,rsp
+
+	mov	QWORD PTR[16+rsp],rbp
+$L$cbc_slow_body::
+
+
+
+
+	mov	QWORD PTR[56+rsp],r8
+	mov	rbp,r8
+	mov	rbx,r9
+	mov	r9,rsi
+	mov	r8,rdi
+	mov	r15,rcx
+	mov	r10,rdx
+
+	mov	eax,DWORD PTR[240+r15]
+	mov	QWORD PTR[rsp],r15
+	shl	eax,4
+	lea	rax,QWORD PTR[rax*1+r15]
+	mov	QWORD PTR[8+rsp],rax
+
+
+	lea	r14,QWORD PTR[2048+r14]
+	lea	rax,QWORD PTR[((768-8))+rsp]
+	sub	rax,r14
+	and	rax,0300h
+	lea	r14,QWORD PTR[rax*1+r14]
+
+	cmp	rbx,0
+	je	$L$SLOW_DECRYPT
+
+
+	test	r10,-16
+	mov	eax,DWORD PTR[rbp]
+	mov	ebx,DWORD PTR[4+rbp]
+	mov	ecx,DWORD PTR[8+rbp]
+	mov	edx,DWORD PTR[12+rbp]
+	jz	$L$cbc_slow_enc_tail	
+
+ALIGN	4
+$L$cbc_slow_enc_loop::
+	xor	eax,DWORD PTR[r8]
+	xor	ebx,DWORD PTR[4+r8]
+	xor	ecx,DWORD PTR[8+r8]
+	xor	edx,DWORD PTR[12+r8]
+	mov	r15,QWORD PTR[rsp]
+	mov	QWORD PTR[24+rsp],r8
+	mov	QWORD PTR[32+rsp],r9
+	mov	QWORD PTR[40+rsp],r10
+
+	call	_x86_64_AES_encrypt_compact
+
+	mov	r8,QWORD PTR[24+rsp]
+	mov	r9,QWORD PTR[32+rsp]
+	mov	r10,QWORD PTR[40+rsp]
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	lea	r8,QWORD PTR[16+r8]
+	lea	r9,QWORD PTR[16+r9]
+	sub	r10,16
+	test	r10,-16
+	jnz	$L$cbc_slow_enc_loop
+	test	r10,15
+	jnz	$L$cbc_slow_enc_tail
+	mov	rbp,QWORD PTR[56+rsp]
+	mov	DWORD PTR[rbp],eax
+	mov	DWORD PTR[4+rbp],ebx
+	mov	DWORD PTR[8+rbp],ecx
+	mov	DWORD PTR[12+rbp],edx
+
+	jmp	$L$cbc_exit
+
+ALIGN	4
+$L$cbc_slow_enc_tail::
+	mov	r11,rax
+	mov	r12,rcx
+	mov	rcx,r10
+	mov	rsi,r8
+	mov	rdi,r9
+	DD	09066A4F3h		
+	mov	rcx,16
+	sub	rcx,r10
+	xor	rax,rax
+	DD	09066AAF3h		
+	mov	r8,r9
+	mov	r10,16
+	mov	rax,r11
+	mov	rcx,r12
+	jmp	$L$cbc_slow_enc_loop	
+
+ALIGN	16
+$L$SLOW_DECRYPT::
+	shr	rax,3
+	add	r14,rax
+
+	mov	r11,QWORD PTR[rbp]
+	mov	r12,QWORD PTR[8+rbp]
+	mov	QWORD PTR[((0+64))+rsp],r11
+	mov	QWORD PTR[((8+64))+rsp],r12
+
+ALIGN	4
+$L$cbc_slow_dec_loop::
+	mov	eax,DWORD PTR[r8]
+	mov	ebx,DWORD PTR[4+r8]
+	mov	ecx,DWORD PTR[8+r8]
+	mov	edx,DWORD PTR[12+r8]
+	mov	r15,QWORD PTR[rsp]
+	mov	QWORD PTR[24+rsp],r8
+	mov	QWORD PTR[32+rsp],r9
+	mov	QWORD PTR[40+rsp],r10
+
+	call	_x86_64_AES_decrypt_compact
+
+	mov	r8,QWORD PTR[24+rsp]
+	mov	r9,QWORD PTR[32+rsp]
+	mov	r10,QWORD PTR[40+rsp]
+	xor	eax,DWORD PTR[((0+64))+rsp]
+	xor	ebx,DWORD PTR[((4+64))+rsp]
+	xor	ecx,DWORD PTR[((8+64))+rsp]
+	xor	edx,DWORD PTR[((12+64))+rsp]
+
+	mov	r11,QWORD PTR[r8]
+	mov	r12,QWORD PTR[8+r8]
+	sub	r10,16
+	jc	$L$cbc_slow_dec_partial
+	jz	$L$cbc_slow_dec_done
+
+	mov	QWORD PTR[((0+64))+rsp],r11
+	mov	QWORD PTR[((8+64))+rsp],r12
+
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	lea	r8,QWORD PTR[16+r8]
+	lea	r9,QWORD PTR[16+r9]
+	jmp	$L$cbc_slow_dec_loop
+$L$cbc_slow_dec_done::
+	mov	rdi,QWORD PTR[56+rsp]
+	mov	QWORD PTR[rdi],r11
+	mov	QWORD PTR[8+rdi],r12
+
+	mov	DWORD PTR[r9],eax
+	mov	DWORD PTR[4+r9],ebx
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+
+	jmp	$L$cbc_exit
+
+ALIGN	4
+$L$cbc_slow_dec_partial::
+	mov	rdi,QWORD PTR[56+rsp]
+	mov	QWORD PTR[rdi],r11
+	mov	QWORD PTR[8+rdi],r12
+
+	mov	DWORD PTR[((0+64))+rsp],eax
+	mov	DWORD PTR[((4+64))+rsp],ebx
+	mov	DWORD PTR[((8+64))+rsp],ecx
+	mov	DWORD PTR[((12+64))+rsp],edx
+
+	mov	rdi,r9
+	lea	rsi,QWORD PTR[64+rsp]
+	lea	rcx,QWORD PTR[16+r10]
+	DD	09066A4F3h	
+	jmp	$L$cbc_exit
+
+ALIGN	16
+$L$cbc_exit::
+	mov	rsi,QWORD PTR[16+rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$cbc_popfq::
+	popfq
+$L$cbc_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_AES_cbc_encrypt::
+AES_cbc_encrypt	ENDP
+ALIGN	64
+$L$AES_Te::
+	DD	0a56363c6h,0a56363c6h
+	DD	0847c7cf8h,0847c7cf8h
+	DD	0997777eeh,0997777eeh
+	DD	08d7b7bf6h,08d7b7bf6h
+	DD	00df2f2ffh,00df2f2ffh
+	DD	0bd6b6bd6h,0bd6b6bd6h
+	DD	0b16f6fdeh,0b16f6fdeh
+	DD	054c5c591h,054c5c591h
+	DD	050303060h,050303060h
+	DD	003010102h,003010102h
+	DD	0a96767ceh,0a96767ceh
+	DD	07d2b2b56h,07d2b2b56h
+	DD	019fefee7h,019fefee7h
+	DD	062d7d7b5h,062d7d7b5h
+	DD	0e6abab4dh,0e6abab4dh
+	DD	09a7676ech,09a7676ech
+	DD	045caca8fh,045caca8fh
+	DD	09d82821fh,09d82821fh
+	DD	040c9c989h,040c9c989h
+	DD	0877d7dfah,0877d7dfah
+	DD	015fafaefh,015fafaefh
+	DD	0eb5959b2h,0eb5959b2h
+	DD	0c947478eh,0c947478eh
+	DD	00bf0f0fbh,00bf0f0fbh
+	DD	0ecadad41h,0ecadad41h
+	DD	067d4d4b3h,067d4d4b3h
+	DD	0fda2a25fh,0fda2a25fh
+	DD	0eaafaf45h,0eaafaf45h
+	DD	0bf9c9c23h,0bf9c9c23h
+	DD	0f7a4a453h,0f7a4a453h
+	DD	0967272e4h,0967272e4h
+	DD	05bc0c09bh,05bc0c09bh
+	DD	0c2b7b775h,0c2b7b775h
+	DD	01cfdfde1h,01cfdfde1h
+	DD	0ae93933dh,0ae93933dh
+	DD	06a26264ch,06a26264ch
+	DD	05a36366ch,05a36366ch
+	DD	0413f3f7eh,0413f3f7eh
+	DD	002f7f7f5h,002f7f7f5h
+	DD	04fcccc83h,04fcccc83h
+	DD	05c343468h,05c343468h
+	DD	0f4a5a551h,0f4a5a551h
+	DD	034e5e5d1h,034e5e5d1h
+	DD	008f1f1f9h,008f1f1f9h
+	DD	0937171e2h,0937171e2h
+	DD	073d8d8abh,073d8d8abh
+	DD	053313162h,053313162h
+	DD	03f15152ah,03f15152ah
+	DD	00c040408h,00c040408h
+	DD	052c7c795h,052c7c795h
+	DD	065232346h,065232346h
+	DD	05ec3c39dh,05ec3c39dh
+	DD	028181830h,028181830h
+	DD	0a1969637h,0a1969637h
+	DD	00f05050ah,00f05050ah
+	DD	0b59a9a2fh,0b59a9a2fh
+	DD	00907070eh,00907070eh
+	DD	036121224h,036121224h
+	DD	09b80801bh,09b80801bh
+	DD	03de2e2dfh,03de2e2dfh
+	DD	026ebebcdh,026ebebcdh
+	DD	06927274eh,06927274eh
+	DD	0cdb2b27fh,0cdb2b27fh
+	DD	09f7575eah,09f7575eah
+	DD	01b090912h,01b090912h
+	DD	09e83831dh,09e83831dh
+	DD	0742c2c58h,0742c2c58h
+	DD	02e1a1a34h,02e1a1a34h
+	DD	02d1b1b36h,02d1b1b36h
+	DD	0b26e6edch,0b26e6edch
+	DD	0ee5a5ab4h,0ee5a5ab4h
+	DD	0fba0a05bh,0fba0a05bh
+	DD	0f65252a4h,0f65252a4h
+	DD	04d3b3b76h,04d3b3b76h
+	DD	061d6d6b7h,061d6d6b7h
+	DD	0ceb3b37dh,0ceb3b37dh
+	DD	07b292952h,07b292952h
+	DD	03ee3e3ddh,03ee3e3ddh
+	DD	0712f2f5eh,0712f2f5eh
+	DD	097848413h,097848413h
+	DD	0f55353a6h,0f55353a6h
+	DD	068d1d1b9h,068d1d1b9h
+	DD	000000000h,000000000h
+	DD	02cededc1h,02cededc1h
+	DD	060202040h,060202040h
+	DD	01ffcfce3h,01ffcfce3h
+	DD	0c8b1b179h,0c8b1b179h
+	DD	0ed5b5bb6h,0ed5b5bb6h
+	DD	0be6a6ad4h,0be6a6ad4h
+	DD	046cbcb8dh,046cbcb8dh
+	DD	0d9bebe67h,0d9bebe67h
+	DD	04b393972h,04b393972h
+	DD	0de4a4a94h,0de4a4a94h
+	DD	0d44c4c98h,0d44c4c98h
+	DD	0e85858b0h,0e85858b0h
+	DD	04acfcf85h,04acfcf85h
+	DD	06bd0d0bbh,06bd0d0bbh
+	DD	02aefefc5h,02aefefc5h
+	DD	0e5aaaa4fh,0e5aaaa4fh
+	DD	016fbfbedh,016fbfbedh
+	DD	0c5434386h,0c5434386h
+	DD	0d74d4d9ah,0d74d4d9ah
+	DD	055333366h,055333366h
+	DD	094858511h,094858511h
+	DD	0cf45458ah,0cf45458ah
+	DD	010f9f9e9h,010f9f9e9h
+	DD	006020204h,006020204h
+	DD	0817f7ffeh,0817f7ffeh
+	DD	0f05050a0h,0f05050a0h
+	DD	0443c3c78h,0443c3c78h
+	DD	0ba9f9f25h,0ba9f9f25h
+	DD	0e3a8a84bh,0e3a8a84bh
+	DD	0f35151a2h,0f35151a2h
+	DD	0fea3a35dh,0fea3a35dh
+	DD	0c0404080h,0c0404080h
+	DD	08a8f8f05h,08a8f8f05h
+	DD	0ad92923fh,0ad92923fh
+	DD	0bc9d9d21h,0bc9d9d21h
+	DD	048383870h,048383870h
+	DD	004f5f5f1h,004f5f5f1h
+	DD	0dfbcbc63h,0dfbcbc63h
+	DD	0c1b6b677h,0c1b6b677h
+	DD	075dadaafh,075dadaafh
+	DD	063212142h,063212142h
+	DD	030101020h,030101020h
+	DD	01affffe5h,01affffe5h
+	DD	00ef3f3fdh,00ef3f3fdh
+	DD	06dd2d2bfh,06dd2d2bfh
+	DD	04ccdcd81h,04ccdcd81h
+	DD	0140c0c18h,0140c0c18h
+	DD	035131326h,035131326h
+	DD	02fececc3h,02fececc3h
+	DD	0e15f5fbeh,0e15f5fbeh
+	DD	0a2979735h,0a2979735h
+	DD	0cc444488h,0cc444488h
+	DD	03917172eh,03917172eh
+	DD	057c4c493h,057c4c493h
+	DD	0f2a7a755h,0f2a7a755h
+	DD	0827e7efch,0827e7efch
+	DD	0473d3d7ah,0473d3d7ah
+	DD	0ac6464c8h,0ac6464c8h
+	DD	0e75d5dbah,0e75d5dbah
+	DD	02b191932h,02b191932h
+	DD	0957373e6h,0957373e6h
+	DD	0a06060c0h,0a06060c0h
+	DD	098818119h,098818119h
+	DD	0d14f4f9eh,0d14f4f9eh
+	DD	07fdcdca3h,07fdcdca3h
+	DD	066222244h,066222244h
+	DD	07e2a2a54h,07e2a2a54h
+	DD	0ab90903bh,0ab90903bh
+	DD	08388880bh,08388880bh
+	DD	0ca46468ch,0ca46468ch
+	DD	029eeeec7h,029eeeec7h
+	DD	0d3b8b86bh,0d3b8b86bh
+	DD	03c141428h,03c141428h
+	DD	079dedea7h,079dedea7h
+	DD	0e25e5ebch,0e25e5ebch
+	DD	01d0b0b16h,01d0b0b16h
+	DD	076dbdbadh,076dbdbadh
+	DD	03be0e0dbh,03be0e0dbh
+	DD	056323264h,056323264h
+	DD	04e3a3a74h,04e3a3a74h
+	DD	01e0a0a14h,01e0a0a14h
+	DD	0db494992h,0db494992h
+	DD	00a06060ch,00a06060ch
+	DD	06c242448h,06c242448h
+	DD	0e45c5cb8h,0e45c5cb8h
+	DD	05dc2c29fh,05dc2c29fh
+	DD	06ed3d3bdh,06ed3d3bdh
+	DD	0efacac43h,0efacac43h
+	DD	0a66262c4h,0a66262c4h
+	DD	0a8919139h,0a8919139h
+	DD	0a4959531h,0a4959531h
+	DD	037e4e4d3h,037e4e4d3h
+	DD	08b7979f2h,08b7979f2h
+	DD	032e7e7d5h,032e7e7d5h
+	DD	043c8c88bh,043c8c88bh
+	DD	05937376eh,05937376eh
+	DD	0b76d6ddah,0b76d6ddah
+	DD	08c8d8d01h,08c8d8d01h
+	DD	064d5d5b1h,064d5d5b1h
+	DD	0d24e4e9ch,0d24e4e9ch
+	DD	0e0a9a949h,0e0a9a949h
+	DD	0b46c6cd8h,0b46c6cd8h
+	DD	0fa5656ach,0fa5656ach
+	DD	007f4f4f3h,007f4f4f3h
+	DD	025eaeacfh,025eaeacfh
+	DD	0af6565cah,0af6565cah
+	DD	08e7a7af4h,08e7a7af4h
+	DD	0e9aeae47h,0e9aeae47h
+	DD	018080810h,018080810h
+	DD	0d5baba6fh,0d5baba6fh
+	DD	0887878f0h,0887878f0h
+	DD	06f25254ah,06f25254ah
+	DD	0722e2e5ch,0722e2e5ch
+	DD	0241c1c38h,0241c1c38h
+	DD	0f1a6a657h,0f1a6a657h
+	DD	0c7b4b473h,0c7b4b473h
+	DD	051c6c697h,051c6c697h
+	DD	023e8e8cbh,023e8e8cbh
+	DD	07cdddda1h,07cdddda1h
+	DD	09c7474e8h,09c7474e8h
+	DD	0211f1f3eh,0211f1f3eh
+	DD	0dd4b4b96h,0dd4b4b96h
+	DD	0dcbdbd61h,0dcbdbd61h
+	DD	0868b8b0dh,0868b8b0dh
+	DD	0858a8a0fh,0858a8a0fh
+	DD	0907070e0h,0907070e0h
+	DD	0423e3e7ch,0423e3e7ch
+	DD	0c4b5b571h,0c4b5b571h
+	DD	0aa6666cch,0aa6666cch
+	DD	0d8484890h,0d8484890h
+	DD	005030306h,005030306h
+	DD	001f6f6f7h,001f6f6f7h
+	DD	0120e0e1ch,0120e0e1ch
+	DD	0a36161c2h,0a36161c2h
+	DD	05f35356ah,05f35356ah
+	DD	0f95757aeh,0f95757aeh
+	DD	0d0b9b969h,0d0b9b969h
+	DD	091868617h,091868617h
+	DD	058c1c199h,058c1c199h
+	DD	0271d1d3ah,0271d1d3ah
+	DD	0b99e9e27h,0b99e9e27h
+	DD	038e1e1d9h,038e1e1d9h
+	DD	013f8f8ebh,013f8f8ebh
+	DD	0b398982bh,0b398982bh
+	DD	033111122h,033111122h
+	DD	0bb6969d2h,0bb6969d2h
+	DD	070d9d9a9h,070d9d9a9h
+	DD	0898e8e07h,0898e8e07h
+	DD	0a7949433h,0a7949433h
+	DD	0b69b9b2dh,0b69b9b2dh
+	DD	0221e1e3ch,0221e1e3ch
+	DD	092878715h,092878715h
+	DD	020e9e9c9h,020e9e9c9h
+	DD	049cece87h,049cece87h
+	DD	0ff5555aah,0ff5555aah
+	DD	078282850h,078282850h
+	DD	07adfdfa5h,07adfdfa5h
+	DD	08f8c8c03h,08f8c8c03h
+	DD	0f8a1a159h,0f8a1a159h
+	DD	080898909h,080898909h
+	DD	0170d0d1ah,0170d0d1ah
+	DD	0dabfbf65h,0dabfbf65h
+	DD	031e6e6d7h,031e6e6d7h
+	DD	0c6424284h,0c6424284h
+	DD	0b86868d0h,0b86868d0h
+	DD	0c3414182h,0c3414182h
+	DD	0b0999929h,0b0999929h
+	DD	0772d2d5ah,0772d2d5ah
+	DD	0110f0f1eh,0110f0f1eh
+	DD	0cbb0b07bh,0cbb0b07bh
+	DD	0fc5454a8h,0fc5454a8h
+	DD	0d6bbbb6dh,0d6bbbb6dh
+	DD	03a16162ch,03a16162ch
+DB	063h,07ch,077h,07bh,0f2h,06bh,06fh,0c5h
+DB	030h,001h,067h,02bh,0feh,0d7h,0abh,076h
+DB	0cah,082h,0c9h,07dh,0fah,059h,047h,0f0h
+DB	0adh,0d4h,0a2h,0afh,09ch,0a4h,072h,0c0h
+DB	0b7h,0fdh,093h,026h,036h,03fh,0f7h,0cch
+DB	034h,0a5h,0e5h,0f1h,071h,0d8h,031h,015h
+DB	004h,0c7h,023h,0c3h,018h,096h,005h,09ah
+DB	007h,012h,080h,0e2h,0ebh,027h,0b2h,075h
+DB	009h,083h,02ch,01ah,01bh,06eh,05ah,0a0h
+DB	052h,03bh,0d6h,0b3h,029h,0e3h,02fh,084h
+DB	053h,0d1h,000h,0edh,020h,0fch,0b1h,05bh
+DB	06ah,0cbh,0beh,039h,04ah,04ch,058h,0cfh
+DB	0d0h,0efh,0aah,0fbh,043h,04dh,033h,085h
+DB	045h,0f9h,002h,07fh,050h,03ch,09fh,0a8h
+DB	051h,0a3h,040h,08fh,092h,09dh,038h,0f5h
+DB	0bch,0b6h,0dah,021h,010h,0ffh,0f3h,0d2h
+DB	0cdh,00ch,013h,0ech,05fh,097h,044h,017h
+DB	0c4h,0a7h,07eh,03dh,064h,05dh,019h,073h
+DB	060h,081h,04fh,0dch,022h,02ah,090h,088h
+DB	046h,0eeh,0b8h,014h,0deh,05eh,00bh,0dbh
+DB	0e0h,032h,03ah,00ah,049h,006h,024h,05ch
+DB	0c2h,0d3h,0ach,062h,091h,095h,0e4h,079h
+DB	0e7h,0c8h,037h,06dh,08dh,0d5h,04eh,0a9h
+DB	06ch,056h,0f4h,0eah,065h,07ah,0aeh,008h
+DB	0bah,078h,025h,02eh,01ch,0a6h,0b4h,0c6h
+DB	0e8h,0ddh,074h,01fh,04bh,0bdh,08bh,08ah
+DB	070h,03eh,0b5h,066h,048h,003h,0f6h,00eh
+DB	061h,035h,057h,0b9h,086h,0c1h,01dh,09eh
+DB	0e1h,0f8h,098h,011h,069h,0d9h,08eh,094h
+DB	09bh,01eh,087h,0e9h,0ceh,055h,028h,0dfh
+DB	08ch,0a1h,089h,00dh,0bfh,0e6h,042h,068h
+DB	041h,099h,02dh,00fh,0b0h,054h,0bbh,016h
+DB	063h,07ch,077h,07bh,0f2h,06bh,06fh,0c5h
+DB	030h,001h,067h,02bh,0feh,0d7h,0abh,076h
+DB	0cah,082h,0c9h,07dh,0fah,059h,047h,0f0h
+DB	0adh,0d4h,0a2h,0afh,09ch,0a4h,072h,0c0h
+DB	0b7h,0fdh,093h,026h,036h,03fh,0f7h,0cch
+DB	034h,0a5h,0e5h,0f1h,071h,0d8h,031h,015h
+DB	004h,0c7h,023h,0c3h,018h,096h,005h,09ah
+DB	007h,012h,080h,0e2h,0ebh,027h,0b2h,075h
+DB	009h,083h,02ch,01ah,01bh,06eh,05ah,0a0h
+DB	052h,03bh,0d6h,0b3h,029h,0e3h,02fh,084h
+DB	053h,0d1h,000h,0edh,020h,0fch,0b1h,05bh
+DB	06ah,0cbh,0beh,039h,04ah,04ch,058h,0cfh
+DB	0d0h,0efh,0aah,0fbh,043h,04dh,033h,085h
+DB	045h,0f9h,002h,07fh,050h,03ch,09fh,0a8h
+DB	051h,0a3h,040h,08fh,092h,09dh,038h,0f5h
+DB	0bch,0b6h,0dah,021h,010h,0ffh,0f3h,0d2h
+DB	0cdh,00ch,013h,0ech,05fh,097h,044h,017h
+DB	0c4h,0a7h,07eh,03dh,064h,05dh,019h,073h
+DB	060h,081h,04fh,0dch,022h,02ah,090h,088h
+DB	046h,0eeh,0b8h,014h,0deh,05eh,00bh,0dbh
+DB	0e0h,032h,03ah,00ah,049h,006h,024h,05ch
+DB	0c2h,0d3h,0ach,062h,091h,095h,0e4h,079h
+DB	0e7h,0c8h,037h,06dh,08dh,0d5h,04eh,0a9h
+DB	06ch,056h,0f4h,0eah,065h,07ah,0aeh,008h
+DB	0bah,078h,025h,02eh,01ch,0a6h,0b4h,0c6h
+DB	0e8h,0ddh,074h,01fh,04bh,0bdh,08bh,08ah
+DB	070h,03eh,0b5h,066h,048h,003h,0f6h,00eh
+DB	061h,035h,057h,0b9h,086h,0c1h,01dh,09eh
+DB	0e1h,0f8h,098h,011h,069h,0d9h,08eh,094h
+DB	09bh,01eh,087h,0e9h,0ceh,055h,028h,0dfh
+DB	08ch,0a1h,089h,00dh,0bfh,0e6h,042h,068h
+DB	041h,099h,02dh,00fh,0b0h,054h,0bbh,016h
+DB	063h,07ch,077h,07bh,0f2h,06bh,06fh,0c5h
+DB	030h,001h,067h,02bh,0feh,0d7h,0abh,076h
+DB	0cah,082h,0c9h,07dh,0fah,059h,047h,0f0h
+DB	0adh,0d4h,0a2h,0afh,09ch,0a4h,072h,0c0h
+DB	0b7h,0fdh,093h,026h,036h,03fh,0f7h,0cch
+DB	034h,0a5h,0e5h,0f1h,071h,0d8h,031h,015h
+DB	004h,0c7h,023h,0c3h,018h,096h,005h,09ah
+DB	007h,012h,080h,0e2h,0ebh,027h,0b2h,075h
+DB	009h,083h,02ch,01ah,01bh,06eh,05ah,0a0h
+DB	052h,03bh,0d6h,0b3h,029h,0e3h,02fh,084h
+DB	053h,0d1h,000h,0edh,020h,0fch,0b1h,05bh
+DB	06ah,0cbh,0beh,039h,04ah,04ch,058h,0cfh
+DB	0d0h,0efh,0aah,0fbh,043h,04dh,033h,085h
+DB	045h,0f9h,002h,07fh,050h,03ch,09fh,0a8h
+DB	051h,0a3h,040h,08fh,092h,09dh,038h,0f5h
+DB	0bch,0b6h,0dah,021h,010h,0ffh,0f3h,0d2h
+DB	0cdh,00ch,013h,0ech,05fh,097h,044h,017h
+DB	0c4h,0a7h,07eh,03dh,064h,05dh,019h,073h
+DB	060h,081h,04fh,0dch,022h,02ah,090h,088h
+DB	046h,0eeh,0b8h,014h,0deh,05eh,00bh,0dbh
+DB	0e0h,032h,03ah,00ah,049h,006h,024h,05ch
+DB	0c2h,0d3h,0ach,062h,091h,095h,0e4h,079h
+DB	0e7h,0c8h,037h,06dh,08dh,0d5h,04eh,0a9h
+DB	06ch,056h,0f4h,0eah,065h,07ah,0aeh,008h
+DB	0bah,078h,025h,02eh,01ch,0a6h,0b4h,0c6h
+DB	0e8h,0ddh,074h,01fh,04bh,0bdh,08bh,08ah
+DB	070h,03eh,0b5h,066h,048h,003h,0f6h,00eh
+DB	061h,035h,057h,0b9h,086h,0c1h,01dh,09eh
+DB	0e1h,0f8h,098h,011h,069h,0d9h,08eh,094h
+DB	09bh,01eh,087h,0e9h,0ceh,055h,028h,0dfh
+DB	08ch,0a1h,089h,00dh,0bfh,0e6h,042h,068h
+DB	041h,099h,02dh,00fh,0b0h,054h,0bbh,016h
+DB	063h,07ch,077h,07bh,0f2h,06bh,06fh,0c5h
+DB	030h,001h,067h,02bh,0feh,0d7h,0abh,076h
+DB	0cah,082h,0c9h,07dh,0fah,059h,047h,0f0h
+DB	0adh,0d4h,0a2h,0afh,09ch,0a4h,072h,0c0h
+DB	0b7h,0fdh,093h,026h,036h,03fh,0f7h,0cch
+DB	034h,0a5h,0e5h,0f1h,071h,0d8h,031h,015h
+DB	004h,0c7h,023h,0c3h,018h,096h,005h,09ah
+DB	007h,012h,080h,0e2h,0ebh,027h,0b2h,075h
+DB	009h,083h,02ch,01ah,01bh,06eh,05ah,0a0h
+DB	052h,03bh,0d6h,0b3h,029h,0e3h,02fh,084h
+DB	053h,0d1h,000h,0edh,020h,0fch,0b1h,05bh
+DB	06ah,0cbh,0beh,039h,04ah,04ch,058h,0cfh
+DB	0d0h,0efh,0aah,0fbh,043h,04dh,033h,085h
+DB	045h,0f9h,002h,07fh,050h,03ch,09fh,0a8h
+DB	051h,0a3h,040h,08fh,092h,09dh,038h,0f5h
+DB	0bch,0b6h,0dah,021h,010h,0ffh,0f3h,0d2h
+DB	0cdh,00ch,013h,0ech,05fh,097h,044h,017h
+DB	0c4h,0a7h,07eh,03dh,064h,05dh,019h,073h
+DB	060h,081h,04fh,0dch,022h,02ah,090h,088h
+DB	046h,0eeh,0b8h,014h,0deh,05eh,00bh,0dbh
+DB	0e0h,032h,03ah,00ah,049h,006h,024h,05ch
+DB	0c2h,0d3h,0ach,062h,091h,095h,0e4h,079h
+DB	0e7h,0c8h,037h,06dh,08dh,0d5h,04eh,0a9h
+DB	06ch,056h,0f4h,0eah,065h,07ah,0aeh,008h
+DB	0bah,078h,025h,02eh,01ch,0a6h,0b4h,0c6h
+DB	0e8h,0ddh,074h,01fh,04bh,0bdh,08bh,08ah
+DB	070h,03eh,0b5h,066h,048h,003h,0f6h,00eh
+DB	061h,035h,057h,0b9h,086h,0c1h,01dh,09eh
+DB	0e1h,0f8h,098h,011h,069h,0d9h,08eh,094h
+DB	09bh,01eh,087h,0e9h,0ceh,055h,028h,0dfh
+DB	08ch,0a1h,089h,00dh,0bfh,0e6h,042h,068h
+DB	041h,099h,02dh,00fh,0b0h,054h,0bbh,016h
+	DD	000000001h,000000002h,000000004h,000000008h
+	DD	000000010h,000000020h,000000040h,000000080h
+	DD	00000001bh,000000036h,080808080h,080808080h
+	DD	0fefefefeh,0fefefefeh,01b1b1b1bh,01b1b1b1bh
+ALIGN	64
+$L$AES_Td::
+	DD	050a7f451h,050a7f451h
+	DD	05365417eh,05365417eh
+	DD	0c3a4171ah,0c3a4171ah
+	DD	0965e273ah,0965e273ah
+	DD	0cb6bab3bh,0cb6bab3bh
+	DD	0f1459d1fh,0f1459d1fh
+	DD	0ab58faach,0ab58faach
+	DD	09303e34bh,09303e34bh
+	DD	055fa3020h,055fa3020h
+	DD	0f66d76adh,0f66d76adh
+	DD	09176cc88h,09176cc88h
+	DD	0254c02f5h,0254c02f5h
+	DD	0fcd7e54fh,0fcd7e54fh
+	DD	0d7cb2ac5h,0d7cb2ac5h
+	DD	080443526h,080443526h
+	DD	08fa362b5h,08fa362b5h
+	DD	0495ab1deh,0495ab1deh
+	DD	0671bba25h,0671bba25h
+	DD	0980eea45h,0980eea45h
+	DD	0e1c0fe5dh,0e1c0fe5dh
+	DD	002752fc3h,002752fc3h
+	DD	012f04c81h,012f04c81h
+	DD	0a397468dh,0a397468dh
+	DD	0c6f9d36bh,0c6f9d36bh
+	DD	0e75f8f03h,0e75f8f03h
+	DD	0959c9215h,0959c9215h
+	DD	0eb7a6dbfh,0eb7a6dbfh
+	DD	0da595295h,0da595295h
+	DD	02d83bed4h,02d83bed4h
+	DD	0d3217458h,0d3217458h
+	DD	02969e049h,02969e049h
+	DD	044c8c98eh,044c8c98eh
+	DD	06a89c275h,06a89c275h
+	DD	078798ef4h,078798ef4h
+	DD	06b3e5899h,06b3e5899h
+	DD	0dd71b927h,0dd71b927h
+	DD	0b64fe1beh,0b64fe1beh
+	DD	017ad88f0h,017ad88f0h
+	DD	066ac20c9h,066ac20c9h
+	DD	0b43ace7dh,0b43ace7dh
+	DD	0184adf63h,0184adf63h
+	DD	082311ae5h,082311ae5h
+	DD	060335197h,060335197h
+	DD	0457f5362h,0457f5362h
+	DD	0e07764b1h,0e07764b1h
+	DD	084ae6bbbh,084ae6bbbh
+	DD	01ca081feh,01ca081feh
+	DD	0942b08f9h,0942b08f9h
+	DD	058684870h,058684870h
+	DD	019fd458fh,019fd458fh
+	DD	0876cde94h,0876cde94h
+	DD	0b7f87b52h,0b7f87b52h
+	DD	023d373abh,023d373abh
+	DD	0e2024b72h,0e2024b72h
+	DD	0578f1fe3h,0578f1fe3h
+	DD	02aab5566h,02aab5566h
+	DD	00728ebb2h,00728ebb2h
+	DD	003c2b52fh,003c2b52fh
+	DD	09a7bc586h,09a7bc586h
+	DD	0a50837d3h,0a50837d3h
+	DD	0f2872830h,0f2872830h
+	DD	0b2a5bf23h,0b2a5bf23h
+	DD	0ba6a0302h,0ba6a0302h
+	DD	05c8216edh,05c8216edh
+	DD	02b1ccf8ah,02b1ccf8ah
+	DD	092b479a7h,092b479a7h
+	DD	0f0f207f3h,0f0f207f3h
+	DD	0a1e2694eh,0a1e2694eh
+	DD	0cdf4da65h,0cdf4da65h
+	DD	0d5be0506h,0d5be0506h
+	DD	01f6234d1h,01f6234d1h
+	DD	08afea6c4h,08afea6c4h
+	DD	09d532e34h,09d532e34h
+	DD	0a055f3a2h,0a055f3a2h
+	DD	032e18a05h,032e18a05h
+	DD	075ebf6a4h,075ebf6a4h
+	DD	039ec830bh,039ec830bh
+	DD	0aaef6040h,0aaef6040h
+	DD	0069f715eh,0069f715eh
+	DD	051106ebdh,051106ebdh
+	DD	0f98a213eh,0f98a213eh
+	DD	03d06dd96h,03d06dd96h
+	DD	0ae053eddh,0ae053eddh
+	DD	046bde64dh,046bde64dh
+	DD	0b58d5491h,0b58d5491h
+	DD	0055dc471h,0055dc471h
+	DD	06fd40604h,06fd40604h
+	DD	0ff155060h,0ff155060h
+	DD	024fb9819h,024fb9819h
+	DD	097e9bdd6h,097e9bdd6h
+	DD	0cc434089h,0cc434089h
+	DD	0779ed967h,0779ed967h
+	DD	0bd42e8b0h,0bd42e8b0h
+	DD	0888b8907h,0888b8907h
+	DD	0385b19e7h,0385b19e7h
+	DD	0dbeec879h,0dbeec879h
+	DD	0470a7ca1h,0470a7ca1h
+	DD	0e90f427ch,0e90f427ch
+	DD	0c91e84f8h,0c91e84f8h
+	DD	000000000h,000000000h
+	DD	083868009h,083868009h
+	DD	048ed2b32h,048ed2b32h
+	DD	0ac70111eh,0ac70111eh
+	DD	04e725a6ch,04e725a6ch
+	DD	0fbff0efdh,0fbff0efdh
+	DD	05638850fh,05638850fh
+	DD	01ed5ae3dh,01ed5ae3dh
+	DD	027392d36h,027392d36h
+	DD	064d90f0ah,064d90f0ah
+	DD	021a65c68h,021a65c68h
+	DD	0d1545b9bh,0d1545b9bh
+	DD	03a2e3624h,03a2e3624h
+	DD	0b1670a0ch,0b1670a0ch
+	DD	00fe75793h,00fe75793h
+	DD	0d296eeb4h,0d296eeb4h
+	DD	09e919b1bh,09e919b1bh
+	DD	04fc5c080h,04fc5c080h
+	DD	0a220dc61h,0a220dc61h
+	DD	0694b775ah,0694b775ah
+	DD	0161a121ch,0161a121ch
+	DD	00aba93e2h,00aba93e2h
+	DD	0e52aa0c0h,0e52aa0c0h
+	DD	043e0223ch,043e0223ch
+	DD	01d171b12h,01d171b12h
+	DD	00b0d090eh,00b0d090eh
+	DD	0adc78bf2h,0adc78bf2h
+	DD	0b9a8b62dh,0b9a8b62dh
+	DD	0c8a91e14h,0c8a91e14h
+	DD	08519f157h,08519f157h
+	DD	04c0775afh,04c0775afh
+	DD	0bbdd99eeh,0bbdd99eeh
+	DD	0fd607fa3h,0fd607fa3h
+	DD	09f2601f7h,09f2601f7h
+	DD	0bcf5725ch,0bcf5725ch
+	DD	0c53b6644h,0c53b6644h
+	DD	0347efb5bh,0347efb5bh
+	DD	07629438bh,07629438bh
+	DD	0dcc623cbh,0dcc623cbh
+	DD	068fcedb6h,068fcedb6h
+	DD	063f1e4b8h,063f1e4b8h
+	DD	0cadc31d7h,0cadc31d7h
+	DD	010856342h,010856342h
+	DD	040229713h,040229713h
+	DD	02011c684h,02011c684h
+	DD	07d244a85h,07d244a85h
+	DD	0f83dbbd2h,0f83dbbd2h
+	DD	01132f9aeh,01132f9aeh
+	DD	06da129c7h,06da129c7h
+	DD	04b2f9e1dh,04b2f9e1dh
+	DD	0f330b2dch,0f330b2dch
+	DD	0ec52860dh,0ec52860dh
+	DD	0d0e3c177h,0d0e3c177h
+	DD	06c16b32bh,06c16b32bh
+	DD	099b970a9h,099b970a9h
+	DD	0fa489411h,0fa489411h
+	DD	02264e947h,02264e947h
+	DD	0c48cfca8h,0c48cfca8h
+	DD	01a3ff0a0h,01a3ff0a0h
+	DD	0d82c7d56h,0d82c7d56h
+	DD	0ef903322h,0ef903322h
+	DD	0c74e4987h,0c74e4987h
+	DD	0c1d138d9h,0c1d138d9h
+	DD	0fea2ca8ch,0fea2ca8ch
+	DD	0360bd498h,0360bd498h
+	DD	0cf81f5a6h,0cf81f5a6h
+	DD	028de7aa5h,028de7aa5h
+	DD	0268eb7dah,0268eb7dah
+	DD	0a4bfad3fh,0a4bfad3fh
+	DD	0e49d3a2ch,0e49d3a2ch
+	DD	00d927850h,00d927850h
+	DD	09bcc5f6ah,09bcc5f6ah
+	DD	062467e54h,062467e54h
+	DD	0c2138df6h,0c2138df6h
+	DD	0e8b8d890h,0e8b8d890h
+	DD	05ef7392eh,05ef7392eh
+	DD	0f5afc382h,0f5afc382h
+	DD	0be805d9fh,0be805d9fh
+	DD	07c93d069h,07c93d069h
+	DD	0a92dd56fh,0a92dd56fh
+	DD	0b31225cfh,0b31225cfh
+	DD	03b99acc8h,03b99acc8h
+	DD	0a77d1810h,0a77d1810h
+	DD	06e639ce8h,06e639ce8h
+	DD	07bbb3bdbh,07bbb3bdbh
+	DD	0097826cdh,0097826cdh
+	DD	0f418596eh,0f418596eh
+	DD	001b79aech,001b79aech
+	DD	0a89a4f83h,0a89a4f83h
+	DD	0656e95e6h,0656e95e6h
+	DD	07ee6ffaah,07ee6ffaah
+	DD	008cfbc21h,008cfbc21h
+	DD	0e6e815efh,0e6e815efh
+	DD	0d99be7bah,0d99be7bah
+	DD	0ce366f4ah,0ce366f4ah
+	DD	0d4099feah,0d4099feah
+	DD	0d67cb029h,0d67cb029h
+	DD	0afb2a431h,0afb2a431h
+	DD	031233f2ah,031233f2ah
+	DD	03094a5c6h,03094a5c6h
+	DD	0c066a235h,0c066a235h
+	DD	037bc4e74h,037bc4e74h
+	DD	0a6ca82fch,0a6ca82fch
+	DD	0b0d090e0h,0b0d090e0h
+	DD	015d8a733h,015d8a733h
+	DD	04a9804f1h,04a9804f1h
+	DD	0f7daec41h,0f7daec41h
+	DD	00e50cd7fh,00e50cd7fh
+	DD	02ff69117h,02ff69117h
+	DD	08dd64d76h,08dd64d76h
+	DD	04db0ef43h,04db0ef43h
+	DD	0544daacch,0544daacch
+	DD	0df0496e4h,0df0496e4h
+	DD	0e3b5d19eh,0e3b5d19eh
+	DD	01b886a4ch,01b886a4ch
+	DD	0b81f2cc1h,0b81f2cc1h
+	DD	07f516546h,07f516546h
+	DD	004ea5e9dh,004ea5e9dh
+	DD	05d358c01h,05d358c01h
+	DD	0737487fah,0737487fah
+	DD	02e410bfbh,02e410bfbh
+	DD	05a1d67b3h,05a1d67b3h
+	DD	052d2db92h,052d2db92h
+	DD	0335610e9h,0335610e9h
+	DD	01347d66dh,01347d66dh
+	DD	08c61d79ah,08c61d79ah
+	DD	07a0ca137h,07a0ca137h
+	DD	08e14f859h,08e14f859h
+	DD	0893c13ebh,0893c13ebh
+	DD	0ee27a9ceh,0ee27a9ceh
+	DD	035c961b7h,035c961b7h
+	DD	0ede51ce1h,0ede51ce1h
+	DD	03cb1477ah,03cb1477ah
+	DD	059dfd29ch,059dfd29ch
+	DD	03f73f255h,03f73f255h
+	DD	079ce1418h,079ce1418h
+	DD	0bf37c773h,0bf37c773h
+	DD	0eacdf753h,0eacdf753h
+	DD	05baafd5fh,05baafd5fh
+	DD	0146f3ddfh,0146f3ddfh
+	DD	086db4478h,086db4478h
+	DD	081f3afcah,081f3afcah
+	DD	03ec468b9h,03ec468b9h
+	DD	02c342438h,02c342438h
+	DD	05f40a3c2h,05f40a3c2h
+	DD	072c31d16h,072c31d16h
+	DD	00c25e2bch,00c25e2bch
+	DD	08b493c28h,08b493c28h
+	DD	041950dffh,041950dffh
+	DD	07101a839h,07101a839h
+	DD	0deb30c08h,0deb30c08h
+	DD	09ce4b4d8h,09ce4b4d8h
+	DD	090c15664h,090c15664h
+	DD	06184cb7bh,06184cb7bh
+	DD	070b632d5h,070b632d5h
+	DD	0745c6c48h,0745c6c48h
+	DD	04257b8d0h,04257b8d0h
+DB	052h,009h,06ah,0d5h,030h,036h,0a5h,038h
+DB	0bfh,040h,0a3h,09eh,081h,0f3h,0d7h,0fbh
+DB	07ch,0e3h,039h,082h,09bh,02fh,0ffh,087h
+DB	034h,08eh,043h,044h,0c4h,0deh,0e9h,0cbh
+DB	054h,07bh,094h,032h,0a6h,0c2h,023h,03dh
+DB	0eeh,04ch,095h,00bh,042h,0fah,0c3h,04eh
+DB	008h,02eh,0a1h,066h,028h,0d9h,024h,0b2h
+DB	076h,05bh,0a2h,049h,06dh,08bh,0d1h,025h
+DB	072h,0f8h,0f6h,064h,086h,068h,098h,016h
+DB	0d4h,0a4h,05ch,0cch,05dh,065h,0b6h,092h
+DB	06ch,070h,048h,050h,0fdh,0edh,0b9h,0dah
+DB	05eh,015h,046h,057h,0a7h,08dh,09dh,084h
+DB	090h,0d8h,0abh,000h,08ch,0bch,0d3h,00ah
+DB	0f7h,0e4h,058h,005h,0b8h,0b3h,045h,006h
+DB	0d0h,02ch,01eh,08fh,0cah,03fh,00fh,002h
+DB	0c1h,0afh,0bdh,003h,001h,013h,08ah,06bh
+DB	03ah,091h,011h,041h,04fh,067h,0dch,0eah
+DB	097h,0f2h,0cfh,0ceh,0f0h,0b4h,0e6h,073h
+DB	096h,0ach,074h,022h,0e7h,0adh,035h,085h
+DB	0e2h,0f9h,037h,0e8h,01ch,075h,0dfh,06eh
+DB	047h,0f1h,01ah,071h,01dh,029h,0c5h,089h
+DB	06fh,0b7h,062h,00eh,0aah,018h,0beh,01bh
+DB	0fch,056h,03eh,04bh,0c6h,0d2h,079h,020h
+DB	09ah,0dbh,0c0h,0feh,078h,0cdh,05ah,0f4h
+DB	01fh,0ddh,0a8h,033h,088h,007h,0c7h,031h
+DB	0b1h,012h,010h,059h,027h,080h,0ech,05fh
+DB	060h,051h,07fh,0a9h,019h,0b5h,04ah,00dh
+DB	02dh,0e5h,07ah,09fh,093h,0c9h,09ch,0efh
+DB	0a0h,0e0h,03bh,04dh,0aeh,02ah,0f5h,0b0h
+DB	0c8h,0ebh,0bbh,03ch,083h,053h,099h,061h
+DB	017h,02bh,004h,07eh,0bah,077h,0d6h,026h
+DB	0e1h,069h,014h,063h,055h,021h,00ch,07dh
+	DD	080808080h,080808080h,0fefefefeh,0fefefefeh
+	DD	01b1b1b1bh,01b1b1b1bh,0,0
+DB	052h,009h,06ah,0d5h,030h,036h,0a5h,038h
+DB	0bfh,040h,0a3h,09eh,081h,0f3h,0d7h,0fbh
+DB	07ch,0e3h,039h,082h,09bh,02fh,0ffh,087h
+DB	034h,08eh,043h,044h,0c4h,0deh,0e9h,0cbh
+DB	054h,07bh,094h,032h,0a6h,0c2h,023h,03dh
+DB	0eeh,04ch,095h,00bh,042h,0fah,0c3h,04eh
+DB	008h,02eh,0a1h,066h,028h,0d9h,024h,0b2h
+DB	076h,05bh,0a2h,049h,06dh,08bh,0d1h,025h
+DB	072h,0f8h,0f6h,064h,086h,068h,098h,016h
+DB	0d4h,0a4h,05ch,0cch,05dh,065h,0b6h,092h
+DB	06ch,070h,048h,050h,0fdh,0edh,0b9h,0dah
+DB	05eh,015h,046h,057h,0a7h,08dh,09dh,084h
+DB	090h,0d8h,0abh,000h,08ch,0bch,0d3h,00ah
+DB	0f7h,0e4h,058h,005h,0b8h,0b3h,045h,006h
+DB	0d0h,02ch,01eh,08fh,0cah,03fh,00fh,002h
+DB	0c1h,0afh,0bdh,003h,001h,013h,08ah,06bh
+DB	03ah,091h,011h,041h,04fh,067h,0dch,0eah
+DB	097h,0f2h,0cfh,0ceh,0f0h,0b4h,0e6h,073h
+DB	096h,0ach,074h,022h,0e7h,0adh,035h,085h
+DB	0e2h,0f9h,037h,0e8h,01ch,075h,0dfh,06eh
+DB	047h,0f1h,01ah,071h,01dh,029h,0c5h,089h
+DB	06fh,0b7h,062h,00eh,0aah,018h,0beh,01bh
+DB	0fch,056h,03eh,04bh,0c6h,0d2h,079h,020h
+DB	09ah,0dbh,0c0h,0feh,078h,0cdh,05ah,0f4h
+DB	01fh,0ddh,0a8h,033h,088h,007h,0c7h,031h
+DB	0b1h,012h,010h,059h,027h,080h,0ech,05fh
+DB	060h,051h,07fh,0a9h,019h,0b5h,04ah,00dh
+DB	02dh,0e5h,07ah,09fh,093h,0c9h,09ch,0efh
+DB	0a0h,0e0h,03bh,04dh,0aeh,02ah,0f5h,0b0h
+DB	0c8h,0ebh,0bbh,03ch,083h,053h,099h,061h
+DB	017h,02bh,004h,07eh,0bah,077h,0d6h,026h
+DB	0e1h,069h,014h,063h,055h,021h,00ch,07dh
+	DD	080808080h,080808080h,0fefefefeh,0fefefefeh
+	DD	01b1b1b1bh,01b1b1b1bh,0,0
+DB	052h,009h,06ah,0d5h,030h,036h,0a5h,038h
+DB	0bfh,040h,0a3h,09eh,081h,0f3h,0d7h,0fbh
+DB	07ch,0e3h,039h,082h,09bh,02fh,0ffh,087h
+DB	034h,08eh,043h,044h,0c4h,0deh,0e9h,0cbh
+DB	054h,07bh,094h,032h,0a6h,0c2h,023h,03dh
+DB	0eeh,04ch,095h,00bh,042h,0fah,0c3h,04eh
+DB	008h,02eh,0a1h,066h,028h,0d9h,024h,0b2h
+DB	076h,05bh,0a2h,049h,06dh,08bh,0d1h,025h
+DB	072h,0f8h,0f6h,064h,086h,068h,098h,016h
+DB	0d4h,0a4h,05ch,0cch,05dh,065h,0b6h,092h
+DB	06ch,070h,048h,050h,0fdh,0edh,0b9h,0dah
+DB	05eh,015h,046h,057h,0a7h,08dh,09dh,084h
+DB	090h,0d8h,0abh,000h,08ch,0bch,0d3h,00ah
+DB	0f7h,0e4h,058h,005h,0b8h,0b3h,045h,006h
+DB	0d0h,02ch,01eh,08fh,0cah,03fh,00fh,002h
+DB	0c1h,0afh,0bdh,003h,001h,013h,08ah,06bh
+DB	03ah,091h,011h,041h,04fh,067h,0dch,0eah
+DB	097h,0f2h,0cfh,0ceh,0f0h,0b4h,0e6h,073h
+DB	096h,0ach,074h,022h,0e7h,0adh,035h,085h
+DB	0e2h,0f9h,037h,0e8h,01ch,075h,0dfh,06eh
+DB	047h,0f1h,01ah,071h,01dh,029h,0c5h,089h
+DB	06fh,0b7h,062h,00eh,0aah,018h,0beh,01bh
+DB	0fch,056h,03eh,04bh,0c6h,0d2h,079h,020h
+DB	09ah,0dbh,0c0h,0feh,078h,0cdh,05ah,0f4h
+DB	01fh,0ddh,0a8h,033h,088h,007h,0c7h,031h
+DB	0b1h,012h,010h,059h,027h,080h,0ech,05fh
+DB	060h,051h,07fh,0a9h,019h,0b5h,04ah,00dh
+DB	02dh,0e5h,07ah,09fh,093h,0c9h,09ch,0efh
+DB	0a0h,0e0h,03bh,04dh,0aeh,02ah,0f5h,0b0h
+DB	0c8h,0ebh,0bbh,03ch,083h,053h,099h,061h
+DB	017h,02bh,004h,07eh,0bah,077h,0d6h,026h
+DB	0e1h,069h,014h,063h,055h,021h,00ch,07dh
+	DD	080808080h,080808080h,0fefefefeh,0fefefefeh
+	DD	01b1b1b1bh,01b1b1b1bh,0,0
+DB	052h,009h,06ah,0d5h,030h,036h,0a5h,038h
+DB	0bfh,040h,0a3h,09eh,081h,0f3h,0d7h,0fbh
+DB	07ch,0e3h,039h,082h,09bh,02fh,0ffh,087h
+DB	034h,08eh,043h,044h,0c4h,0deh,0e9h,0cbh
+DB	054h,07bh,094h,032h,0a6h,0c2h,023h,03dh
+DB	0eeh,04ch,095h,00bh,042h,0fah,0c3h,04eh
+DB	008h,02eh,0a1h,066h,028h,0d9h,024h,0b2h
+DB	076h,05bh,0a2h,049h,06dh,08bh,0d1h,025h
+DB	072h,0f8h,0f6h,064h,086h,068h,098h,016h
+DB	0d4h,0a4h,05ch,0cch,05dh,065h,0b6h,092h
+DB	06ch,070h,048h,050h,0fdh,0edh,0b9h,0dah
+DB	05eh,015h,046h,057h,0a7h,08dh,09dh,084h
+DB	090h,0d8h,0abh,000h,08ch,0bch,0d3h,00ah
+DB	0f7h,0e4h,058h,005h,0b8h,0b3h,045h,006h
+DB	0d0h,02ch,01eh,08fh,0cah,03fh,00fh,002h
+DB	0c1h,0afh,0bdh,003h,001h,013h,08ah,06bh
+DB	03ah,091h,011h,041h,04fh,067h,0dch,0eah
+DB	097h,0f2h,0cfh,0ceh,0f0h,0b4h,0e6h,073h
+DB	096h,0ach,074h,022h,0e7h,0adh,035h,085h
+DB	0e2h,0f9h,037h,0e8h,01ch,075h,0dfh,06eh
+DB	047h,0f1h,01ah,071h,01dh,029h,0c5h,089h
+DB	06fh,0b7h,062h,00eh,0aah,018h,0beh,01bh
+DB	0fch,056h,03eh,04bh,0c6h,0d2h,079h,020h
+DB	09ah,0dbh,0c0h,0feh,078h,0cdh,05ah,0f4h
+DB	01fh,0ddh,0a8h,033h,088h,007h,0c7h,031h
+DB	0b1h,012h,010h,059h,027h,080h,0ech,05fh
+DB	060h,051h,07fh,0a9h,019h,0b5h,04ah,00dh
+DB	02dh,0e5h,07ah,09fh,093h,0c9h,09ch,0efh
+DB	0a0h,0e0h,03bh,04dh,0aeh,02ah,0f5h,0b0h
+DB	0c8h,0ebh,0bbh,03ch,083h,053h,099h,061h
+DB	017h,02bh,004h,07eh,0bah,077h,0d6h,026h
+DB	0e1h,069h,014h,063h,055h,021h,00ch,07dh
+	DD	080808080h,080808080h,0fefefefeh,0fefefefeh
+	DD	01b1b1b1bh,01b1b1b1bh,0,0
+DB	65,69,83,32,102,111,114,32,120,56,54,95,54,52,44,32
+DB	67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
+DB	112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
+DB	62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+block_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$in_block_prologue
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$in_block_prologue
+
+	mov	rax,QWORD PTR[24+rax]
+	lea	rax,QWORD PTR[48+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	r13,QWORD PTR[((-32))+rax]
+	mov	r14,QWORD PTR[((-40))+rax]
+	mov	r15,QWORD PTR[((-48))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$in_block_prologue::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	jmp	$L$common_seh_exit
+block_se_handler	ENDP
+
+
+ALIGN	16
+key_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$in_key_prologue
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$in_key_prologue
+
+	lea	rax,QWORD PTR[56+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	r13,QWORD PTR[((-32))+rax]
+	mov	r14,QWORD PTR[((-40))+rax]
+	mov	r15,QWORD PTR[((-48))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$in_key_prologue::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	jmp	$L$common_seh_exit
+key_se_handler	ENDP
+
+
+ALIGN	16
+cbc_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	lea	r10,QWORD PTR[$L$cbc_prologue]
+	cmp	rbx,r10
+	jb	$L$in_cbc_prologue
+
+	lea	r10,QWORD PTR[$L$cbc_fast_body]
+	cmp	rbx,r10
+	jb	$L$in_cbc_frame_setup
+
+	lea	r10,QWORD PTR[$L$cbc_slow_prologue]
+	cmp	rbx,r10
+	jb	$L$in_cbc_body
+
+	lea	r10,QWORD PTR[$L$cbc_slow_body]
+	cmp	rbx,r10
+	jb	$L$in_cbc_frame_setup
+
+$L$in_cbc_body::
+	mov	rax,QWORD PTR[152+r8]
+
+	lea	r10,QWORD PTR[$L$cbc_epilogue]
+	cmp	rbx,r10
+	jae	$L$in_cbc_prologue
+
+	lea	rax,QWORD PTR[8+rax]
+
+	lea	r10,QWORD PTR[$L$cbc_popfq]
+	cmp	rbx,r10
+	jae	$L$in_cbc_prologue
+
+	mov	rax,QWORD PTR[8+rax]
+	lea	rax,QWORD PTR[56+rax]
+
+$L$in_cbc_frame_setup::
+	mov	rbx,QWORD PTR[((-16))+rax]
+	mov	rbp,QWORD PTR[((-24))+rax]
+	mov	r12,QWORD PTR[((-32))+rax]
+	mov	r13,QWORD PTR[((-40))+rax]
+	mov	r14,QWORD PTR[((-48))+rax]
+	mov	r15,QWORD PTR[((-56))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$in_cbc_prologue::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+$L$common_seh_exit::
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+cbc_se_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_AES_encrypt
+	DD	imagerel $L$SEH_end_AES_encrypt
+	DD	imagerel $L$SEH_info_AES_encrypt
+
+	DD	imagerel $L$SEH_begin_AES_decrypt
+	DD	imagerel $L$SEH_end_AES_decrypt
+	DD	imagerel $L$SEH_info_AES_decrypt
+
+	DD	imagerel $L$SEH_begin_AES_set_encrypt_key
+	DD	imagerel $L$SEH_end_AES_set_encrypt_key
+	DD	imagerel $L$SEH_info_AES_set_encrypt_key
+
+	DD	imagerel $L$SEH_begin_AES_set_decrypt_key
+	DD	imagerel $L$SEH_end_AES_set_decrypt_key
+	DD	imagerel $L$SEH_info_AES_set_decrypt_key
+
+	DD	imagerel $L$SEH_begin_AES_cbc_encrypt
+	DD	imagerel $L$SEH_end_AES_cbc_encrypt
+	DD	imagerel $L$SEH_info_AES_cbc_encrypt
+
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_AES_encrypt::
+DB	9,0,0,0
+	DD	imagerel block_se_handler
+	DD	imagerel $L$enc_prologue,imagerel $L$enc_epilogue	
+$L$SEH_info_AES_decrypt::
+DB	9,0,0,0
+	DD	imagerel block_se_handler
+	DD	imagerel $L$dec_prologue,imagerel $L$dec_epilogue	
+$L$SEH_info_AES_set_encrypt_key::
+DB	9,0,0,0
+	DD	imagerel key_se_handler
+	DD	imagerel $L$enc_key_prologue,imagerel $L$enc_key_epilogue	
+$L$SEH_info_AES_set_decrypt_key::
+DB	9,0,0,0
+	DD	imagerel key_se_handler
+	DD	imagerel $L$dec_key_prologue,imagerel $L$dec_key_epilogue	
+$L$SEH_info_AES_cbc_encrypt::
+DB	9,0,0,0
+	DD	imagerel cbc_se_handler
+
+.xdata	ENDS
+END
+
diff --git a/crypto/aes/aes-mingw64-x86_64.S b/crypto/aes/aes-mingw64-x86_64.S
new file mode 100644
index 0000000..ca2d60f
--- /dev/null
+++ b/crypto/aes/aes-mingw64-x86_64.S
@@ -0,0 +1,2861 @@
+#include "x86_arch.h"
+
+.text	
+.def	_x86_64_AES_encrypt;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_AES_encrypt:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	.Lenc_loop
+.p2align	4
+.Lenc_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	shrl	$16,%ecx
+	movzbl	%ah,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movl	12(%r15),%edx
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rdi,8),%r12d
+	xorl	1(%r14,%rbp,8),%r8d
+
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	.Lenc_loop
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	2(%r14,%rsi,8),%r10d
+	movzbl	2(%r14,%rdi,8),%r11d
+	movzbl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	2(%r14,%rsi,8),%r8d
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$65280,%edi
+	andl	$65280,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%ecx
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	shrl	$16,%edx
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+
+	andl	$65280,%esi
+	andl	$65280,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%eax
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	0(%r14,%rdi,8),%edi
+	movl	0(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$16711680,%edi
+	andl	$16711680,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movl	0(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	2(%r14,%rbp,8),%ebp
+
+	andl	$16711680,%esi
+	andl	$4278190080,%edi
+	andl	$4278190080,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movl	16+12(%r15),%edx
+	movl	2(%r14,%rsi,8),%esi
+	movl	2(%r14,%rdi,8),%edi
+	movl	16+0(%r15),%eax
+
+	andl	$4278190080,%esi
+	andl	$4278190080,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+
+.def	_x86_64_AES_encrypt_compact;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_AES_encrypt_compact:
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	.Lenc_loop_compact
+.p2align	4
+.Lenc_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%dh,%ebp
+	movzbl	%ah,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%dh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ah,%edi
+	shrl	$8,%ecx
+	shrl	$8,%ebx
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rcx,1),%edx
+	movzbl	(%r14,%rbx,1),%ecx
+	shll	$16,%r9d
+	shll	$16,%r13d
+	shll	$16,%ebp
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%edi
+	shll	$24,%edx
+	xorl	%esi,%r10d
+	shll	$24,%ecx
+	xorl	%edi,%r11d
+	movl	%r10d,%eax
+	movl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	.Lenc_compact_done
+	movl	%eax,%esi
+	movl	%ebx,%edi
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	movl	%esi,%r10d
+	movl	%edi,%r11d
+	shrl	$7,%r10d
+	leal	(%rax,%rax,1),%r8d
+	shrl	$7,%r11d
+	leal	(%rbx,%rbx,1),%r9d
+	subl	%r10d,%esi
+	subl	%r11d,%edi
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%ecx,%esi
+	movl	%edx,%edi
+	roll	$24,%eax
+	roll	$24,%ebx
+	andl	$2155905152,%esi
+	andl	$2155905152,%edi
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movl	%esi,%r12d
+	movl	%edi,%ebp
+	rorl	$16,%r10d
+	rorl	$16,%r11d
+	shrl	$7,%r12d
+	leal	(%rcx,%rcx,1),%r8d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	shrl	$7,%ebp
+	leal	(%rdx,%rdx,1),%r9d
+	rorl	$8,%r10d
+	rorl	$8,%r11d
+	subl	%r12d,%esi
+	subl	%ebp,%edi
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+
+	andl	$4278124286,%r8d
+	andl	$4278124286,%r9d
+	andl	$454761243,%esi
+	andl	$454761243,%edi
+	movl	%ecx,%r12d
+	movl	%edx,%ebp
+	xorl	%esi,%r8d
+	xorl	%edi,%r9d
+
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	roll	$24,%ecx
+	roll	$24,%edx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+	movl	0(%r14),%esi
+	rorl	$16,%r12d
+	rorl	$16,%ebp
+	movl	64(%r14),%edi
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	movl	128(%r14),%r8d
+	rorl	$8,%r12d
+	rorl	$8,%ebp
+	movl	192(%r14),%r9d
+	xorl	%r12d,%ecx
+	xorl	%ebp,%edx
+	jmp	.Lenc_loop_compact
+.p2align	4
+.Lenc_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+
+.globl	AES_encrypt
+.def	AES_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+.globl	asm_AES_encrypt
+
+asm_AES_encrypt:
+AES_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_AES_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+.Lenc_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	.LAES_Te+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lenc_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_AES_encrypt:
+.def	_x86_64_AES_decrypt;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_AES_decrypt:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+
+	movl	240(%r15),%r13d
+	subl	$1,%r13d
+	jmp	.Ldec_loop
+.p2align	4
+.Ldec_loop:
+
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movl	0(%r14,%rsi,8),%r10d
+	movl	0(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r12d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	%dl,%ebp
+	xorl	3(%r14,%rsi,8),%r10d
+	xorl	3(%r14,%rdi,8),%r11d
+	movl	0(%r14,%rbp,8),%r8d
+
+	movzbl	%bh,%esi
+	shrl	$16,%eax
+	movzbl	%ch,%ebp
+	xorl	3(%r14,%rsi,8),%r12d
+	shrl	$16,%edx
+	xorl	3(%r14,%rbp,8),%r8d
+
+	shrl	$16,%ebx
+	leaq	16(%r15),%r15
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	xorl	2(%r14,%rsi,8),%r10d
+	xorl	2(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r12d
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	movzbl	%bl,%ebp
+	xorl	1(%r14,%rsi,8),%r10d
+	xorl	1(%r14,%rdi,8),%r11d
+	xorl	2(%r14,%rbp,8),%r8d
+
+	movzbl	%dh,%esi
+	movl	12(%r15),%edx
+	movzbl	%ah,%ebp
+	xorl	1(%r14,%rsi,8),%r12d
+	movl	0(%r15),%eax
+	xorl	1(%r14,%rbp,8),%r8d
+
+	xorl	%r10d,%eax
+	movl	4(%r15),%ebx
+	movl	8(%r15),%ecx
+	xorl	%r12d,%ecx
+	xorl	%r11d,%ebx
+	xorl	%r8d,%edx
+	subl	$1,%r13d
+	jnz	.Ldec_loop
+	leaq	2048(%r14),%r14
+	movzbl	%al,%esi
+	movzbl	%bl,%edi
+	movzbl	%cl,%ebp
+	movzbl	(%r14,%rsi,1),%r10d
+	movzbl	(%r14,%rdi,1),%r11d
+	movzbl	(%r14,%rbp,1),%r12d
+
+	movzbl	%dl,%esi
+	movzbl	%dh,%edi
+	movzbl	%ah,%ebp
+	movzbl	(%r14,%rsi,1),%r8d
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$8,%edi
+	shll	$8,%ebp
+
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+	shrl	$16,%edx
+
+	movzbl	%bh,%esi
+	movzbl	%ch,%edi
+	shrl	$16,%eax
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+
+	shll	$8,%esi
+	shll	$8,%edi
+	shrl	$16,%ebx
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+	shrl	$16,%ecx
+
+	movzbl	%cl,%esi
+	movzbl	%dl,%edi
+	movzbl	%al,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$16,%edi
+	shll	$16,%ebp
+
+	xorl	%esi,%r10d
+	xorl	%edi,%r11d
+	xorl	%ebp,%r12d
+
+	movzbl	%bl,%esi
+	movzbl	%bh,%edi
+	movzbl	%ch,%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movzbl	(%r14,%rbp,1),%ebp
+
+	shll	$16,%esi
+	shll	$24,%edi
+	shll	$24,%ebp
+
+	xorl	%esi,%r8d
+	xorl	%edi,%r10d
+	xorl	%ebp,%r11d
+
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movl	16+12(%r15),%edx
+	movzbl	(%r14,%rsi,1),%esi
+	movzbl	(%r14,%rdi,1),%edi
+	movl	16+0(%r15),%eax
+
+	shll	$24,%esi
+	shll	$24,%edi
+
+	xorl	%esi,%r12d
+	xorl	%edi,%r8d
+
+	movl	16+4(%r15),%ebx
+	movl	16+8(%r15),%ecx
+	leaq	-2048(%r14),%r14
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	retq
+
+.def	_x86_64_AES_decrypt_compact;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_AES_decrypt_compact:
+	leaq	128(%r14),%r8
+	movl	0-128(%r8),%edi
+	movl	32-128(%r8),%ebp
+	movl	64-128(%r8),%r10d
+	movl	96-128(%r8),%r11d
+	movl	128-128(%r8),%edi
+	movl	160-128(%r8),%ebp
+	movl	192-128(%r8),%r10d
+	movl	224-128(%r8),%r11d
+	jmp	.Ldec_loop_compact
+
+.p2align	4
+.Ldec_loop_compact:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	leaq	16(%r15),%r15
+	movzbl	%al,%r10d
+	movzbl	%bl,%r11d
+	movzbl	%cl,%r12d
+	movzbl	(%r14,%r10,1),%r10d
+	movzbl	(%r14,%r11,1),%r11d
+	movzbl	(%r14,%r12,1),%r12d
+
+	movzbl	%dl,%r8d
+	movzbl	%dh,%esi
+	movzbl	%ah,%edi
+	movzbl	(%r14,%r8,1),%r8d
+	movzbl	(%r14,%rsi,1),%r9d
+	movzbl	(%r14,%rdi,1),%r13d
+
+	movzbl	%bh,%ebp
+	movzbl	%ch,%esi
+	shrl	$16,%ecx
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	shrl	$16,%edx
+
+	movzbl	%cl,%edi
+	shll	$8,%r9d
+	shll	$8,%r13d
+	movzbl	(%r14,%rdi,1),%edi
+	xorl	%r9d,%r10d
+	xorl	%r13d,%r11d
+
+	movzbl	%dl,%r9d
+	shrl	$16,%eax
+	shrl	$16,%ebx
+	movzbl	%al,%r13d
+	shll	$8,%ebp
+	shll	$8,%esi
+	movzbl	(%r14,%r9,1),%r9d
+	movzbl	(%r14,%r13,1),%r13d
+	xorl	%ebp,%r12d
+	xorl	%esi,%r8d
+
+	movzbl	%bl,%ebp
+	movzbl	%bh,%esi
+	shll	$16,%edi
+	movzbl	(%r14,%rbp,1),%ebp
+	movzbl	(%r14,%rsi,1),%esi
+	xorl	%edi,%r10d
+
+	movzbl	%ch,%edi
+	shll	$16,%r9d
+	shll	$16,%r13d
+	movzbl	(%r14,%rdi,1),%ebx
+	xorl	%r9d,%r11d
+	xorl	%r13d,%r12d
+
+	movzbl	%dh,%edi
+	shrl	$8,%eax
+	shll	$16,%ebp
+	movzbl	(%r14,%rdi,1),%ecx
+	movzbl	(%r14,%rax,1),%edx
+	xorl	%ebp,%r8d
+
+	shll	$24,%esi
+	shll	$24,%ebx
+	shll	$24,%ecx
+	xorl	%esi,%r10d
+	shll	$24,%edx
+	xorl	%r11d,%ebx
+	movl	%r10d,%eax
+	xorl	%r12d,%ecx
+	xorl	%r8d,%edx
+	cmpq	16(%rsp),%r15
+	je	.Ldec_compact_done
+
+	movq	256+0(%r14),%rsi
+	shlq	$32,%rbx
+	shlq	$32,%rdx
+	movq	256+8(%r14),%rdi
+	orq	%rbx,%rax
+	orq	%rdx,%rcx
+	movq	256+16(%r14),%rbp
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	0(%r14),%rsi
+	shrq	$32,%r8
+	shrq	$32,%r11
+	movq	64(%r14),%rdi
+	roll	$16,%r9d
+	roll	$16,%r12d
+	movq	128(%r14),%rbp
+	roll	$16,%r8d
+	roll	$16,%r11d
+	movq	192(%r14),%r10
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+	movq	256(%r14),%r13
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	jmp	.Ldec_loop_compact
+.p2align	4
+.Ldec_compact_done:
+	xorl	0(%r15),%eax
+	xorl	4(%r15),%ebx
+	xorl	8(%r15),%ecx
+	xorl	12(%r15),%edx
+	retq
+
+.globl	AES_decrypt
+.def	AES_decrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+.globl	asm_AES_decrypt
+
+asm_AES_decrypt:
+AES_decrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_AES_decrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r10
+	leaq	-63(%rdx),%rcx
+	andq	$-64,%rsp
+	subq	%rsp,%rcx
+	negq	%rcx
+	andq	$960,%rcx
+	subq	%rcx,%rsp
+	subq	$32,%rsp
+
+	movq	%rsi,16(%rsp)
+	movq	%r10,24(%rsp)
+.Ldec_prologue:
+
+	movq	%rdx,%r15
+	movl	240(%r15),%r13d
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+
+	shll	$4,%r13d
+	leaq	(%r15,%r13,1),%rbp
+	movq	%r15,(%rsp)
+	movq	%rbp,8(%rsp)
+
+
+	leaq	.LAES_Td+2048(%rip),%r14
+	leaq	768(%rsp),%rbp
+	subq	%r14,%rbp
+	andq	$768,%rbp
+	leaq	(%r14,%rbp,1),%r14
+	shrq	$3,%rbp
+	addq	%rbp,%r14
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	16(%rsp),%r9
+	movq	24(%rsp),%rsi
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Ldec_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_AES_decrypt:
+.globl	AES_set_encrypt_key
+.def	AES_set_encrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+AES_set_encrypt_key:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_AES_set_encrypt_key:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$8,%rsp
+.Lenc_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+.Lenc_key_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_AES_set_encrypt_key:
+
+.def	_x86_64_AES_set_encrypt_key;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_AES_set_encrypt_key:
+	movl	%esi,%ecx
+	movq	%rdi,%rsi
+	movq	%rdx,%rdi
+
+	testq	$-1,%rsi
+	jz	.Lbadpointer
+	testq	$-1,%rdi
+	jz	.Lbadpointer
+
+	leaq	.LAES_Te(%rip),%rbp
+	leaq	2048+128(%rbp),%rbp
+
+
+	movl	0-128(%rbp),%eax
+	movl	32-128(%rbp),%ebx
+	movl	64-128(%rbp),%r8d
+	movl	96-128(%rbp),%edx
+	movl	128-128(%rbp),%eax
+	movl	160-128(%rbp),%ebx
+	movl	192-128(%rbp),%r8d
+	movl	224-128(%rbp),%edx
+
+	cmpl	$128,%ecx
+	je	.L10rounds
+	cmpl	$192,%ecx
+	je	.L12rounds
+	cmpl	$256,%ecx
+	je	.L14rounds
+	movq	$-2,%rax
+	jmp	.Lexit
+
+.L10rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rdx,8(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L10shortcut
+.p2align	2
+.L10loop:
+	movl	0(%rdi),%eax
+	movl	12(%rdi),%edx
+.L10shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,16(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,20(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,24(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,28(%rdi)
+	addl	$1,%ecx
+	leaq	16(%rdi),%rdi
+	cmpl	$10,%ecx
+	jl	.L10loop
+
+	movl	$10,80(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.L12rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rdx,16(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L12shortcut
+.p2align	2
+.L12loop:
+	movl	0(%rdi),%eax
+	movl	20(%rdi),%edx
+.L12shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,24(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,28(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,32(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,36(%rdi)
+
+	cmpl	$7,%ecx
+	je	.L12break
+	addl	$1,%ecx
+
+	xorl	16(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	leaq	24(%rdi),%rdi
+	jmp	.L12loop
+.L12break:
+	movl	$12,72(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.L14rounds:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rcx
+	movq	24(%rsi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+
+	shrq	$32,%rdx
+	xorl	%ecx,%ecx
+	jmp	.L14shortcut
+.p2align	2
+.L14loop:
+	movl	0(%rdi),%eax
+	movl	28(%rdi),%edx
+.L14shortcut:
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$8,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	xorl	1024-128(%rbp,%rcx,4),%eax
+	movl	%eax,32(%rdi)
+	xorl	4(%rdi),%eax
+	movl	%eax,36(%rdi)
+	xorl	8(%rdi),%eax
+	movl	%eax,40(%rdi)
+	xorl	12(%rdi),%eax
+	movl	%eax,44(%rdi)
+
+	cmpl	$6,%ecx
+	je	.L14break
+	addl	$1,%ecx
+
+	movl	%eax,%edx
+	movl	16(%rdi),%eax
+	movzbl	%dl,%esi
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shrl	$16,%edx
+	shll	$8,%ebx
+	movzbl	%dl,%esi
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	movzbl	%dh,%esi
+	shll	$16,%ebx
+	xorl	%ebx,%eax
+
+	movzbl	-128(%rbp,%rsi,1),%ebx
+	shll	$24,%ebx
+	xorl	%ebx,%eax
+
+	movl	%eax,48(%rdi)
+	xorl	20(%rdi),%eax
+	movl	%eax,52(%rdi)
+	xorl	24(%rdi),%eax
+	movl	%eax,56(%rdi)
+	xorl	28(%rdi),%eax
+	movl	%eax,60(%rdi)
+
+	leaq	32(%rdi),%rdi
+	jmp	.L14loop
+.L14break:
+	movl	$14,48(%rdi)
+	xorq	%rax,%rax
+	jmp	.Lexit
+
+.Lbadpointer:
+	movq	$-1,%rax
+.Lexit:
+	retq
+
+.globl	AES_set_decrypt_key
+.def	AES_set_decrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+AES_set_decrypt_key:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_AES_set_decrypt_key:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushq	%rdx
+.Ldec_key_prologue:
+
+	call	_x86_64_AES_set_encrypt_key
+	movq	(%rsp),%r8
+	cmpl	$0,%eax
+	jne	.Labort
+
+	movl	240(%r8),%r14d
+	xorq	%rdi,%rdi
+	leaq	(%rdi,%r14,4),%rcx
+	movq	%r8,%rsi
+	leaq	(%r8,%rcx,4),%rdi
+.p2align	2
+.Linvert:
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	0(%rdi),%rcx
+	movq	8(%rdi),%rdx
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,0(%rsi)
+	movq	%rdx,8(%rsi)
+	leaq	16(%rsi),%rsi
+	leaq	-16(%rdi),%rdi
+	cmpq	%rsi,%rdi
+	jne	.Linvert
+
+	leaq	.LAES_Te+2048+1024(%rip),%rax
+
+	movq	40(%rax),%rsi
+	movq	48(%rax),%rdi
+	movq	56(%rax),%rbp
+
+	movq	%r8,%r15
+	subl	$1,%r14d
+.p2align	2
+.Lpermute:
+	leaq	16(%r15),%r15
+	movq	0(%r15),%rax
+	movq	8(%r15),%rcx
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+	shrq	$7,%r9
+	leaq	(%rax,%rax,1),%r8
+	shrq	$7,%r12
+	leaq	(%rcx,%rcx,1),%r11
+	subq	%r9,%rbx
+	subq	%r12,%rdx
+	andq	%rdi,%r8
+	andq	%rdi,%r11
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r8,%rbx
+	xorq	%r11,%rdx
+	movq	%rbx,%r8
+	movq	%rdx,%r11
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	leaq	(%r8,%r8,1),%r9
+	shrq	$7,%r13
+	leaq	(%r11,%r11,1),%r12
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	andq	%rdi,%r9
+	andq	%rdi,%r12
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%r9,%rbx
+	xorq	%r12,%rdx
+	movq	%rbx,%r9
+	movq	%rdx,%r12
+
+	andq	%rsi,%rbx
+	andq	%rsi,%rdx
+	movq	%rbx,%r10
+	movq	%rdx,%r13
+	shrq	$7,%r10
+	xorq	%rax,%r8
+	shrq	$7,%r13
+	xorq	%rcx,%r11
+	subq	%r10,%rbx
+	subq	%r13,%rdx
+	leaq	(%r9,%r9,1),%r10
+	leaq	(%r12,%r12,1),%r13
+	xorq	%rax,%r9
+	xorq	%rcx,%r12
+	andq	%rdi,%r10
+	andq	%rdi,%r13
+	andq	%rbp,%rbx
+	andq	%rbp,%rdx
+	xorq	%rbx,%r10
+	xorq	%rdx,%r13
+
+	xorq	%r10,%rax
+	xorq	%r13,%rcx
+	xorq	%r10,%r8
+	xorq	%r13,%r11
+	movq	%rax,%rbx
+	movq	%rcx,%rdx
+	xorq	%r10,%r9
+	xorq	%r13,%r12
+	shrq	$32,%rbx
+	shrq	$32,%rdx
+	xorq	%r8,%r10
+	xorq	%r11,%r13
+	roll	$8,%eax
+	roll	$8,%ecx
+	xorq	%r9,%r10
+	xorq	%r12,%r13
+
+	roll	$8,%ebx
+	roll	$8,%edx
+	xorl	%r10d,%eax
+	xorl	%r13d,%ecx
+	shrq	$32,%r10
+	shrq	$32,%r13
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+	movq	%r8,%r10
+	movq	%r11,%r13
+	shrq	$32,%r10
+	shrq	$32,%r13
+	roll	$24,%r8d
+	roll	$24,%r11d
+	roll	$24,%r10d
+	roll	$24,%r13d
+	xorl	%r8d,%eax
+	xorl	%r11d,%ecx
+	movq	%r9,%r8
+	movq	%r12,%r11
+	xorl	%r10d,%ebx
+	xorl	%r13d,%edx
+
+
+	shrq	$32,%r8
+	shrq	$32,%r11
+
+	roll	$16,%r9d
+	roll	$16,%r12d
+
+	roll	$16,%r8d
+	roll	$16,%r11d
+
+	xorl	%r9d,%eax
+	xorl	%r12d,%ecx
+
+	xorl	%r8d,%ebx
+	xorl	%r11d,%edx
+	movl	%eax,0(%r15)
+	movl	%ebx,4(%r15)
+	movl	%ecx,8(%r15)
+	movl	%edx,12(%r15)
+	subl	$1,%r14d
+	jnz	.Lpermute
+
+	xorq	%rax,%rax
+.Labort:
+	movq	8(%rsp),%r15
+	movq	16(%rsp),%r14
+	movq	24(%rsp),%r13
+	movq	32(%rsp),%r12
+	movq	40(%rsp),%rbp
+	movq	48(%rsp),%rbx
+	addq	$56,%rsp
+.Ldec_key_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_AES_set_decrypt_key:
+.globl	AES_cbc_encrypt
+.def	AES_cbc_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+
+
+.globl	asm_AES_cbc_encrypt
+
+asm_AES_cbc_encrypt:
+AES_cbc_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_AES_cbc_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	cmpq	$0,%rdx
+	je	.Lcbc_epilogue
+	pushfq
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lcbc_prologue:
+
+	cld
+	movl	%r9d,%r9d
+
+	leaq	.LAES_Te(%rip),%r14
+	cmpq	$0,%r9
+	jne	.Lcbc_picked_te
+	leaq	.LAES_Td(%rip),%r14
+.Lcbc_picked_te:
+
+	movl	OPENSSL_ia32cap_P(%rip),%r10d
+	cmpq	$512,%rdx
+	jb	.Lcbc_slow_prologue
+	testq	$15,%rdx
+	jnz	.Lcbc_slow_prologue
+	btl	$IA32CAP_BIT0_HT,%r10d
+	jc	.Lcbc_slow_prologue
+
+
+	leaq	-88-248(%rsp),%r15
+	andq	$-64,%r15
+
+
+	movq	%r14,%r10
+	leaq	2304(%r14),%r11
+	movq	%r15,%r12
+	andq	$4095,%r10
+	andq	$4095,%r11
+	andq	$4095,%r12
+
+	cmpq	%r11,%r12
+	jb	.Lcbc_te_break_out
+	subq	%r11,%r12
+	subq	%r12,%r15
+	jmp	.Lcbc_te_ok
+.Lcbc_te_break_out:
+	subq	%r10,%r12
+	andq	$4095,%r12
+	addq	$320,%r12
+	subq	%r12,%r15
+.p2align	2
+.Lcbc_te_ok:
+
+	xchgq	%rsp,%r15
+
+	movq	%r15,16(%rsp)
+.Lcbc_fast_body:
+	movq	%rdi,24(%rsp)
+	movq	%rsi,32(%rsp)
+	movq	%rdx,40(%rsp)
+	movq	%rcx,48(%rsp)
+	movq	%r8,56(%rsp)
+	movl	$0,80+240(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+
+	movl	240(%r15),%eax
+
+	movq	%r15,%r10
+	subq	%r14,%r10
+	andq	$4095,%r10
+	cmpq	$2304,%r10
+	jb	.Lcbc_do_ecopy
+	cmpq	$4096-248,%r10
+	jb	.Lcbc_skip_ecopy
+.p2align	2
+.Lcbc_do_ecopy:
+	movq	%r15,%rsi
+	leaq	80(%rsp),%rdi
+	leaq	80(%rsp),%r15
+	movl	$30,%ecx
+.long	0x90A548F3	
+	movl	%eax,(%rdi)
+.Lcbc_skip_ecopy:
+	movq	%r15,0(%rsp)
+
+	movl	$18,%ecx
+.p2align	2
+.Lcbc_prefetch_te:
+	movq	0(%r14),%r10
+	movq	32(%r14),%r11
+	movq	64(%r14),%r12
+	movq	96(%r14),%r13
+	leaq	128(%r14),%r14
+	subl	$1,%ecx
+	jnz	.Lcbc_prefetch_te
+	leaq	-2304(%r14),%r14
+
+	cmpq	$0,%rbx
+	je	.LFAST_DECRYPT
+
+
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+.p2align	2
+.Lcbc_fast_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_encrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	movq	%r10,40(%rsp)
+	jnz	.Lcbc_fast_enc_loop
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	.Lcbc_fast_cleanup
+
+
+.p2align	4
+.LFAST_DECRYPT:
+	cmpq	%r8,%r9
+	je	.Lcbc_fast_dec_in_place
+
+	movq	%rbp,64(%rsp)
+.p2align	2
+.Lcbc_fast_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	64(%rsp),%rbp
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0(%rbp),%eax
+	xorl	4(%rbp),%ebx
+	xorl	8(%rbp),%ecx
+	xorl	12(%rbp),%edx
+	movq	%r8,%rbp
+
+	subq	$16,%r10
+	movq	%r10,40(%rsp)
+	movq	%rbp,64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jnz	.Lcbc_fast_dec_loop
+	movq	56(%rsp),%r12
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0(%r12)
+	movq	%r11,8(%r12)
+	jmp	.Lcbc_fast_cleanup
+
+.p2align	4
+.Lcbc_fast_dec_in_place:
+	movq	0(%rbp),%r10
+	movq	8(%rbp),%r11
+	movq	%r10,0+64(%rsp)
+	movq	%r11,8+64(%rsp)
+.p2align	2
+.Lcbc_fast_dec_in_place_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+
+	call	_x86_64_AES_decrypt
+
+	movq	24(%rsp),%r8
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jz	.Lcbc_fast_dec_in_place_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	movq	%r10,40(%rsp)
+	jmp	.Lcbc_fast_dec_in_place_loop
+.Lcbc_fast_dec_in_place_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+.p2align	2
+.Lcbc_fast_cleanup:
+	cmpl	$0,80+240(%rsp)
+	leaq	80(%rsp),%rdi
+	je	.Lcbc_exit
+	movl	$30,%ecx
+	xorq	%rax,%rax
+.long	0x90AB48F3	
+
+	jmp	.Lcbc_exit
+
+
+.p2align	4
+.Lcbc_slow_prologue:
+
+	leaq	-88(%rsp),%rbp
+	andq	$-64,%rbp
+
+	leaq	-88-63(%rcx),%r10
+	subq	%rbp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rbp
+
+	xchgq	%rsp,%rbp
+
+	movq	%rbp,16(%rsp)
+.Lcbc_slow_body:
+
+
+
+
+	movq	%r8,56(%rsp)
+	movq	%r8,%rbp
+	movq	%r9,%rbx
+	movq	%rsi,%r9
+	movq	%rdi,%r8
+	movq	%rcx,%r15
+	movq	%rdx,%r10
+
+	movl	240(%r15),%eax
+	movq	%r15,0(%rsp)
+	shll	$4,%eax
+	leaq	(%r15,%rax,1),%rax
+	movq	%rax,8(%rsp)
+
+
+	leaq	2048(%r14),%r14
+	leaq	768-8(%rsp),%rax
+	subq	%r14,%rax
+	andq	$768,%rax
+	leaq	(%r14,%rax,1),%r14
+
+	cmpq	$0,%rbx
+	je	.LSLOW_DECRYPT
+
+
+	testq	$-16,%r10
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+	jz	.Lcbc_slow_enc_tail	
+
+.p2align	2
+.Lcbc_slow_enc_loop:
+	xorl	0(%r8),%eax
+	xorl	4(%r8),%ebx
+	xorl	8(%r8),%ecx
+	xorl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_encrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	subq	$16,%r10
+	testq	$-16,%r10
+	jnz	.Lcbc_slow_enc_loop
+	testq	$15,%r10
+	jnz	.Lcbc_slow_enc_tail
+	movq	56(%rsp),%rbp
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	jmp	.Lcbc_exit
+
+.p2align	2
+.Lcbc_slow_enc_tail:
+	movq	%rax,%r11
+	movq	%rcx,%r12
+	movq	%r10,%rcx
+	movq	%r8,%rsi
+	movq	%r9,%rdi
+.long	0x9066A4F3		
+	movq	$16,%rcx
+	subq	%r10,%rcx
+	xorq	%rax,%rax
+.long	0x9066AAF3		
+	movq	%r9,%r8
+	movq	$16,%r10
+	movq	%r11,%rax
+	movq	%r12,%rcx
+	jmp	.Lcbc_slow_enc_loop	
+
+.p2align	4
+.LSLOW_DECRYPT:
+	shrq	$3,%rax
+	addq	%rax,%r14
+
+	movq	0(%rbp),%r11
+	movq	8(%rbp),%r12
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+.p2align	2
+.Lcbc_slow_dec_loop:
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movq	0(%rsp),%r15
+	movq	%r8,24(%rsp)
+	movq	%r9,32(%rsp)
+	movq	%r10,40(%rsp)
+
+	call	_x86_64_AES_decrypt_compact
+
+	movq	24(%rsp),%r8
+	movq	32(%rsp),%r9
+	movq	40(%rsp),%r10
+	xorl	0+64(%rsp),%eax
+	xorl	4+64(%rsp),%ebx
+	xorl	8+64(%rsp),%ecx
+	xorl	12+64(%rsp),%edx
+
+	movq	0(%r8),%r11
+	movq	8(%r8),%r12
+	subq	$16,%r10
+	jc	.Lcbc_slow_dec_partial
+	jz	.Lcbc_slow_dec_done
+
+	movq	%r11,0+64(%rsp)
+	movq	%r12,8+64(%rsp)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	leaq	16(%r8),%r8
+	leaq	16(%r9),%r9
+	jmp	.Lcbc_slow_dec_loop
+.Lcbc_slow_dec_done:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0(%r9)
+	movl	%ebx,4(%r9)
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+
+	jmp	.Lcbc_exit
+
+.p2align	2
+.Lcbc_slow_dec_partial:
+	movq	56(%rsp),%rdi
+	movq	%r11,0(%rdi)
+	movq	%r12,8(%rdi)
+
+	movl	%eax,0+64(%rsp)
+	movl	%ebx,4+64(%rsp)
+	movl	%ecx,8+64(%rsp)
+	movl	%edx,12+64(%rsp)
+
+	movq	%r9,%rdi
+	leaq	64(%rsp),%rsi
+	leaq	16(%r10),%rcx
+.long	0x9066A4F3	
+	jmp	.Lcbc_exit
+
+.p2align	4
+.Lcbc_exit:
+	movq	16(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lcbc_popfq:
+	popfq
+.Lcbc_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_AES_cbc_encrypt:
+.p2align	6
+.LAES_Te:
+.long	0xa56363c6,0xa56363c6
+.long	0x847c7cf8,0x847c7cf8
+.long	0x997777ee,0x997777ee
+.long	0x8d7b7bf6,0x8d7b7bf6
+.long	0x0df2f2ff,0x0df2f2ff
+.long	0xbd6b6bd6,0xbd6b6bd6
+.long	0xb16f6fde,0xb16f6fde
+.long	0x54c5c591,0x54c5c591
+.long	0x50303060,0x50303060
+.long	0x03010102,0x03010102
+.long	0xa96767ce,0xa96767ce
+.long	0x7d2b2b56,0x7d2b2b56
+.long	0x19fefee7,0x19fefee7
+.long	0x62d7d7b5,0x62d7d7b5
+.long	0xe6abab4d,0xe6abab4d
+.long	0x9a7676ec,0x9a7676ec
+.long	0x45caca8f,0x45caca8f
+.long	0x9d82821f,0x9d82821f
+.long	0x40c9c989,0x40c9c989
+.long	0x877d7dfa,0x877d7dfa
+.long	0x15fafaef,0x15fafaef
+.long	0xeb5959b2,0xeb5959b2
+.long	0xc947478e,0xc947478e
+.long	0x0bf0f0fb,0x0bf0f0fb
+.long	0xecadad41,0xecadad41
+.long	0x67d4d4b3,0x67d4d4b3
+.long	0xfda2a25f,0xfda2a25f
+.long	0xeaafaf45,0xeaafaf45
+.long	0xbf9c9c23,0xbf9c9c23
+.long	0xf7a4a453,0xf7a4a453
+.long	0x967272e4,0x967272e4
+.long	0x5bc0c09b,0x5bc0c09b
+.long	0xc2b7b775,0xc2b7b775
+.long	0x1cfdfde1,0x1cfdfde1
+.long	0xae93933d,0xae93933d
+.long	0x6a26264c,0x6a26264c
+.long	0x5a36366c,0x5a36366c
+.long	0x413f3f7e,0x413f3f7e
+.long	0x02f7f7f5,0x02f7f7f5
+.long	0x4fcccc83,0x4fcccc83
+.long	0x5c343468,0x5c343468
+.long	0xf4a5a551,0xf4a5a551
+.long	0x34e5e5d1,0x34e5e5d1
+.long	0x08f1f1f9,0x08f1f1f9
+.long	0x937171e2,0x937171e2
+.long	0x73d8d8ab,0x73d8d8ab
+.long	0x53313162,0x53313162
+.long	0x3f15152a,0x3f15152a
+.long	0x0c040408,0x0c040408
+.long	0x52c7c795,0x52c7c795
+.long	0x65232346,0x65232346
+.long	0x5ec3c39d,0x5ec3c39d
+.long	0x28181830,0x28181830
+.long	0xa1969637,0xa1969637
+.long	0x0f05050a,0x0f05050a
+.long	0xb59a9a2f,0xb59a9a2f
+.long	0x0907070e,0x0907070e
+.long	0x36121224,0x36121224
+.long	0x9b80801b,0x9b80801b
+.long	0x3de2e2df,0x3de2e2df
+.long	0x26ebebcd,0x26ebebcd
+.long	0x6927274e,0x6927274e
+.long	0xcdb2b27f,0xcdb2b27f
+.long	0x9f7575ea,0x9f7575ea
+.long	0x1b090912,0x1b090912
+.long	0x9e83831d,0x9e83831d
+.long	0x742c2c58,0x742c2c58
+.long	0x2e1a1a34,0x2e1a1a34
+.long	0x2d1b1b36,0x2d1b1b36
+.long	0xb26e6edc,0xb26e6edc
+.long	0xee5a5ab4,0xee5a5ab4
+.long	0xfba0a05b,0xfba0a05b
+.long	0xf65252a4,0xf65252a4
+.long	0x4d3b3b76,0x4d3b3b76
+.long	0x61d6d6b7,0x61d6d6b7
+.long	0xceb3b37d,0xceb3b37d
+.long	0x7b292952,0x7b292952
+.long	0x3ee3e3dd,0x3ee3e3dd
+.long	0x712f2f5e,0x712f2f5e
+.long	0x97848413,0x97848413
+.long	0xf55353a6,0xf55353a6
+.long	0x68d1d1b9,0x68d1d1b9
+.long	0x00000000,0x00000000
+.long	0x2cededc1,0x2cededc1
+.long	0x60202040,0x60202040
+.long	0x1ffcfce3,0x1ffcfce3
+.long	0xc8b1b179,0xc8b1b179
+.long	0xed5b5bb6,0xed5b5bb6
+.long	0xbe6a6ad4,0xbe6a6ad4
+.long	0x46cbcb8d,0x46cbcb8d
+.long	0xd9bebe67,0xd9bebe67
+.long	0x4b393972,0x4b393972
+.long	0xde4a4a94,0xde4a4a94
+.long	0xd44c4c98,0xd44c4c98
+.long	0xe85858b0,0xe85858b0
+.long	0x4acfcf85,0x4acfcf85
+.long	0x6bd0d0bb,0x6bd0d0bb
+.long	0x2aefefc5,0x2aefefc5
+.long	0xe5aaaa4f,0xe5aaaa4f
+.long	0x16fbfbed,0x16fbfbed
+.long	0xc5434386,0xc5434386
+.long	0xd74d4d9a,0xd74d4d9a
+.long	0x55333366,0x55333366
+.long	0x94858511,0x94858511
+.long	0xcf45458a,0xcf45458a
+.long	0x10f9f9e9,0x10f9f9e9
+.long	0x06020204,0x06020204
+.long	0x817f7ffe,0x817f7ffe
+.long	0xf05050a0,0xf05050a0
+.long	0x443c3c78,0x443c3c78
+.long	0xba9f9f25,0xba9f9f25
+.long	0xe3a8a84b,0xe3a8a84b
+.long	0xf35151a2,0xf35151a2
+.long	0xfea3a35d,0xfea3a35d
+.long	0xc0404080,0xc0404080
+.long	0x8a8f8f05,0x8a8f8f05
+.long	0xad92923f,0xad92923f
+.long	0xbc9d9d21,0xbc9d9d21
+.long	0x48383870,0x48383870
+.long	0x04f5f5f1,0x04f5f5f1
+.long	0xdfbcbc63,0xdfbcbc63
+.long	0xc1b6b677,0xc1b6b677
+.long	0x75dadaaf,0x75dadaaf
+.long	0x63212142,0x63212142
+.long	0x30101020,0x30101020
+.long	0x1affffe5,0x1affffe5
+.long	0x0ef3f3fd,0x0ef3f3fd
+.long	0x6dd2d2bf,0x6dd2d2bf
+.long	0x4ccdcd81,0x4ccdcd81
+.long	0x140c0c18,0x140c0c18
+.long	0x35131326,0x35131326
+.long	0x2fececc3,0x2fececc3
+.long	0xe15f5fbe,0xe15f5fbe
+.long	0xa2979735,0xa2979735
+.long	0xcc444488,0xcc444488
+.long	0x3917172e,0x3917172e
+.long	0x57c4c493,0x57c4c493
+.long	0xf2a7a755,0xf2a7a755
+.long	0x827e7efc,0x827e7efc
+.long	0x473d3d7a,0x473d3d7a
+.long	0xac6464c8,0xac6464c8
+.long	0xe75d5dba,0xe75d5dba
+.long	0x2b191932,0x2b191932
+.long	0x957373e6,0x957373e6
+.long	0xa06060c0,0xa06060c0
+.long	0x98818119,0x98818119
+.long	0xd14f4f9e,0xd14f4f9e
+.long	0x7fdcdca3,0x7fdcdca3
+.long	0x66222244,0x66222244
+.long	0x7e2a2a54,0x7e2a2a54
+.long	0xab90903b,0xab90903b
+.long	0x8388880b,0x8388880b
+.long	0xca46468c,0xca46468c
+.long	0x29eeeec7,0x29eeeec7
+.long	0xd3b8b86b,0xd3b8b86b
+.long	0x3c141428,0x3c141428
+.long	0x79dedea7,0x79dedea7
+.long	0xe25e5ebc,0xe25e5ebc
+.long	0x1d0b0b16,0x1d0b0b16
+.long	0x76dbdbad,0x76dbdbad
+.long	0x3be0e0db,0x3be0e0db
+.long	0x56323264,0x56323264
+.long	0x4e3a3a74,0x4e3a3a74
+.long	0x1e0a0a14,0x1e0a0a14
+.long	0xdb494992,0xdb494992
+.long	0x0a06060c,0x0a06060c
+.long	0x6c242448,0x6c242448
+.long	0xe45c5cb8,0xe45c5cb8
+.long	0x5dc2c29f,0x5dc2c29f
+.long	0x6ed3d3bd,0x6ed3d3bd
+.long	0xefacac43,0xefacac43
+.long	0xa66262c4,0xa66262c4
+.long	0xa8919139,0xa8919139
+.long	0xa4959531,0xa4959531
+.long	0x37e4e4d3,0x37e4e4d3
+.long	0x8b7979f2,0x8b7979f2
+.long	0x32e7e7d5,0x32e7e7d5
+.long	0x43c8c88b,0x43c8c88b
+.long	0x5937376e,0x5937376e
+.long	0xb76d6dda,0xb76d6dda
+.long	0x8c8d8d01,0x8c8d8d01
+.long	0x64d5d5b1,0x64d5d5b1
+.long	0xd24e4e9c,0xd24e4e9c
+.long	0xe0a9a949,0xe0a9a949
+.long	0xb46c6cd8,0xb46c6cd8
+.long	0xfa5656ac,0xfa5656ac
+.long	0x07f4f4f3,0x07f4f4f3
+.long	0x25eaeacf,0x25eaeacf
+.long	0xaf6565ca,0xaf6565ca
+.long	0x8e7a7af4,0x8e7a7af4
+.long	0xe9aeae47,0xe9aeae47
+.long	0x18080810,0x18080810
+.long	0xd5baba6f,0xd5baba6f
+.long	0x887878f0,0x887878f0
+.long	0x6f25254a,0x6f25254a
+.long	0x722e2e5c,0x722e2e5c
+.long	0x241c1c38,0x241c1c38
+.long	0xf1a6a657,0xf1a6a657
+.long	0xc7b4b473,0xc7b4b473
+.long	0x51c6c697,0x51c6c697
+.long	0x23e8e8cb,0x23e8e8cb
+.long	0x7cdddda1,0x7cdddda1
+.long	0x9c7474e8,0x9c7474e8
+.long	0x211f1f3e,0x211f1f3e
+.long	0xdd4b4b96,0xdd4b4b96
+.long	0xdcbdbd61,0xdcbdbd61
+.long	0x868b8b0d,0x868b8b0d
+.long	0x858a8a0f,0x858a8a0f
+.long	0x907070e0,0x907070e0
+.long	0x423e3e7c,0x423e3e7c
+.long	0xc4b5b571,0xc4b5b571
+.long	0xaa6666cc,0xaa6666cc
+.long	0xd8484890,0xd8484890
+.long	0x05030306,0x05030306
+.long	0x01f6f6f7,0x01f6f6f7
+.long	0x120e0e1c,0x120e0e1c
+.long	0xa36161c2,0xa36161c2
+.long	0x5f35356a,0x5f35356a
+.long	0xf95757ae,0xf95757ae
+.long	0xd0b9b969,0xd0b9b969
+.long	0x91868617,0x91868617
+.long	0x58c1c199,0x58c1c199
+.long	0x271d1d3a,0x271d1d3a
+.long	0xb99e9e27,0xb99e9e27
+.long	0x38e1e1d9,0x38e1e1d9
+.long	0x13f8f8eb,0x13f8f8eb
+.long	0xb398982b,0xb398982b
+.long	0x33111122,0x33111122
+.long	0xbb6969d2,0xbb6969d2
+.long	0x70d9d9a9,0x70d9d9a9
+.long	0x898e8e07,0x898e8e07
+.long	0xa7949433,0xa7949433
+.long	0xb69b9b2d,0xb69b9b2d
+.long	0x221e1e3c,0x221e1e3c
+.long	0x92878715,0x92878715
+.long	0x20e9e9c9,0x20e9e9c9
+.long	0x49cece87,0x49cece87
+.long	0xff5555aa,0xff5555aa
+.long	0x78282850,0x78282850
+.long	0x7adfdfa5,0x7adfdfa5
+.long	0x8f8c8c03,0x8f8c8c03
+.long	0xf8a1a159,0xf8a1a159
+.long	0x80898909,0x80898909
+.long	0x170d0d1a,0x170d0d1a
+.long	0xdabfbf65,0xdabfbf65
+.long	0x31e6e6d7,0x31e6e6d7
+.long	0xc6424284,0xc6424284
+.long	0xb86868d0,0xb86868d0
+.long	0xc3414182,0xc3414182
+.long	0xb0999929,0xb0999929
+.long	0x772d2d5a,0x772d2d5a
+.long	0x110f0f1e,0x110f0f1e
+.long	0xcbb0b07b,0xcbb0b07b
+.long	0xfc5454a8,0xfc5454a8
+.long	0xd6bbbb6d,0xd6bbbb6d
+.long	0x3a16162c,0x3a16162c
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.byte	0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5
+.byte	0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76
+.byte	0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0
+.byte	0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0
+.byte	0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc
+.byte	0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15
+.byte	0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a
+.byte	0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75
+.byte	0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0
+.byte	0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84
+.byte	0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b
+.byte	0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf
+.byte	0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85
+.byte	0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8
+.byte	0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5
+.byte	0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2
+.byte	0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17
+.byte	0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73
+.byte	0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88
+.byte	0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb
+.byte	0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c
+.byte	0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79
+.byte	0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9
+.byte	0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08
+.byte	0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6
+.byte	0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a
+.byte	0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e
+.byte	0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e
+.byte	0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94
+.byte	0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf
+.byte	0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68
+.byte	0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
+.long	0x00000001, 0x00000002, 0x00000004, 0x00000008
+.long	0x00000010, 0x00000020, 0x00000040, 0x00000080
+.long	0x0000001b, 0x00000036, 0x80808080, 0x80808080
+.long	0xfefefefe, 0xfefefefe, 0x1b1b1b1b, 0x1b1b1b1b
+.p2align	6
+.LAES_Td:
+.long	0x50a7f451,0x50a7f451
+.long	0x5365417e,0x5365417e
+.long	0xc3a4171a,0xc3a4171a
+.long	0x965e273a,0x965e273a
+.long	0xcb6bab3b,0xcb6bab3b
+.long	0xf1459d1f,0xf1459d1f
+.long	0xab58faac,0xab58faac
+.long	0x9303e34b,0x9303e34b
+.long	0x55fa3020,0x55fa3020
+.long	0xf66d76ad,0xf66d76ad
+.long	0x9176cc88,0x9176cc88
+.long	0x254c02f5,0x254c02f5
+.long	0xfcd7e54f,0xfcd7e54f
+.long	0xd7cb2ac5,0xd7cb2ac5
+.long	0x80443526,0x80443526
+.long	0x8fa362b5,0x8fa362b5
+.long	0x495ab1de,0x495ab1de
+.long	0x671bba25,0x671bba25
+.long	0x980eea45,0x980eea45
+.long	0xe1c0fe5d,0xe1c0fe5d
+.long	0x02752fc3,0x02752fc3
+.long	0x12f04c81,0x12f04c81
+.long	0xa397468d,0xa397468d
+.long	0xc6f9d36b,0xc6f9d36b
+.long	0xe75f8f03,0xe75f8f03
+.long	0x959c9215,0x959c9215
+.long	0xeb7a6dbf,0xeb7a6dbf
+.long	0xda595295,0xda595295
+.long	0x2d83bed4,0x2d83bed4
+.long	0xd3217458,0xd3217458
+.long	0x2969e049,0x2969e049
+.long	0x44c8c98e,0x44c8c98e
+.long	0x6a89c275,0x6a89c275
+.long	0x78798ef4,0x78798ef4
+.long	0x6b3e5899,0x6b3e5899
+.long	0xdd71b927,0xdd71b927
+.long	0xb64fe1be,0xb64fe1be
+.long	0x17ad88f0,0x17ad88f0
+.long	0x66ac20c9,0x66ac20c9
+.long	0xb43ace7d,0xb43ace7d
+.long	0x184adf63,0x184adf63
+.long	0x82311ae5,0x82311ae5
+.long	0x60335197,0x60335197
+.long	0x457f5362,0x457f5362
+.long	0xe07764b1,0xe07764b1
+.long	0x84ae6bbb,0x84ae6bbb
+.long	0x1ca081fe,0x1ca081fe
+.long	0x942b08f9,0x942b08f9
+.long	0x58684870,0x58684870
+.long	0x19fd458f,0x19fd458f
+.long	0x876cde94,0x876cde94
+.long	0xb7f87b52,0xb7f87b52
+.long	0x23d373ab,0x23d373ab
+.long	0xe2024b72,0xe2024b72
+.long	0x578f1fe3,0x578f1fe3
+.long	0x2aab5566,0x2aab5566
+.long	0x0728ebb2,0x0728ebb2
+.long	0x03c2b52f,0x03c2b52f
+.long	0x9a7bc586,0x9a7bc586
+.long	0xa50837d3,0xa50837d3
+.long	0xf2872830,0xf2872830
+.long	0xb2a5bf23,0xb2a5bf23
+.long	0xba6a0302,0xba6a0302
+.long	0x5c8216ed,0x5c8216ed
+.long	0x2b1ccf8a,0x2b1ccf8a
+.long	0x92b479a7,0x92b479a7
+.long	0xf0f207f3,0xf0f207f3
+.long	0xa1e2694e,0xa1e2694e
+.long	0xcdf4da65,0xcdf4da65
+.long	0xd5be0506,0xd5be0506
+.long	0x1f6234d1,0x1f6234d1
+.long	0x8afea6c4,0x8afea6c4
+.long	0x9d532e34,0x9d532e34
+.long	0xa055f3a2,0xa055f3a2
+.long	0x32e18a05,0x32e18a05
+.long	0x75ebf6a4,0x75ebf6a4
+.long	0x39ec830b,0x39ec830b
+.long	0xaaef6040,0xaaef6040
+.long	0x069f715e,0x069f715e
+.long	0x51106ebd,0x51106ebd
+.long	0xf98a213e,0xf98a213e
+.long	0x3d06dd96,0x3d06dd96
+.long	0xae053edd,0xae053edd
+.long	0x46bde64d,0x46bde64d
+.long	0xb58d5491,0xb58d5491
+.long	0x055dc471,0x055dc471
+.long	0x6fd40604,0x6fd40604
+.long	0xff155060,0xff155060
+.long	0x24fb9819,0x24fb9819
+.long	0x97e9bdd6,0x97e9bdd6
+.long	0xcc434089,0xcc434089
+.long	0x779ed967,0x779ed967
+.long	0xbd42e8b0,0xbd42e8b0
+.long	0x888b8907,0x888b8907
+.long	0x385b19e7,0x385b19e7
+.long	0xdbeec879,0xdbeec879
+.long	0x470a7ca1,0x470a7ca1
+.long	0xe90f427c,0xe90f427c
+.long	0xc91e84f8,0xc91e84f8
+.long	0x00000000,0x00000000
+.long	0x83868009,0x83868009
+.long	0x48ed2b32,0x48ed2b32
+.long	0xac70111e,0xac70111e
+.long	0x4e725a6c,0x4e725a6c
+.long	0xfbff0efd,0xfbff0efd
+.long	0x5638850f,0x5638850f
+.long	0x1ed5ae3d,0x1ed5ae3d
+.long	0x27392d36,0x27392d36
+.long	0x64d90f0a,0x64d90f0a
+.long	0x21a65c68,0x21a65c68
+.long	0xd1545b9b,0xd1545b9b
+.long	0x3a2e3624,0x3a2e3624
+.long	0xb1670a0c,0xb1670a0c
+.long	0x0fe75793,0x0fe75793
+.long	0xd296eeb4,0xd296eeb4
+.long	0x9e919b1b,0x9e919b1b
+.long	0x4fc5c080,0x4fc5c080
+.long	0xa220dc61,0xa220dc61
+.long	0x694b775a,0x694b775a
+.long	0x161a121c,0x161a121c
+.long	0x0aba93e2,0x0aba93e2
+.long	0xe52aa0c0,0xe52aa0c0
+.long	0x43e0223c,0x43e0223c
+.long	0x1d171b12,0x1d171b12
+.long	0x0b0d090e,0x0b0d090e
+.long	0xadc78bf2,0xadc78bf2
+.long	0xb9a8b62d,0xb9a8b62d
+.long	0xc8a91e14,0xc8a91e14
+.long	0x8519f157,0x8519f157
+.long	0x4c0775af,0x4c0775af
+.long	0xbbdd99ee,0xbbdd99ee
+.long	0xfd607fa3,0xfd607fa3
+.long	0x9f2601f7,0x9f2601f7
+.long	0xbcf5725c,0xbcf5725c
+.long	0xc53b6644,0xc53b6644
+.long	0x347efb5b,0x347efb5b
+.long	0x7629438b,0x7629438b
+.long	0xdcc623cb,0xdcc623cb
+.long	0x68fcedb6,0x68fcedb6
+.long	0x63f1e4b8,0x63f1e4b8
+.long	0xcadc31d7,0xcadc31d7
+.long	0x10856342,0x10856342
+.long	0x40229713,0x40229713
+.long	0x2011c684,0x2011c684
+.long	0x7d244a85,0x7d244a85
+.long	0xf83dbbd2,0xf83dbbd2
+.long	0x1132f9ae,0x1132f9ae
+.long	0x6da129c7,0x6da129c7
+.long	0x4b2f9e1d,0x4b2f9e1d
+.long	0xf330b2dc,0xf330b2dc
+.long	0xec52860d,0xec52860d
+.long	0xd0e3c177,0xd0e3c177
+.long	0x6c16b32b,0x6c16b32b
+.long	0x99b970a9,0x99b970a9
+.long	0xfa489411,0xfa489411
+.long	0x2264e947,0x2264e947
+.long	0xc48cfca8,0xc48cfca8
+.long	0x1a3ff0a0,0x1a3ff0a0
+.long	0xd82c7d56,0xd82c7d56
+.long	0xef903322,0xef903322
+.long	0xc74e4987,0xc74e4987
+.long	0xc1d138d9,0xc1d138d9
+.long	0xfea2ca8c,0xfea2ca8c
+.long	0x360bd498,0x360bd498
+.long	0xcf81f5a6,0xcf81f5a6
+.long	0x28de7aa5,0x28de7aa5
+.long	0x268eb7da,0x268eb7da
+.long	0xa4bfad3f,0xa4bfad3f
+.long	0xe49d3a2c,0xe49d3a2c
+.long	0x0d927850,0x0d927850
+.long	0x9bcc5f6a,0x9bcc5f6a
+.long	0x62467e54,0x62467e54
+.long	0xc2138df6,0xc2138df6
+.long	0xe8b8d890,0xe8b8d890
+.long	0x5ef7392e,0x5ef7392e
+.long	0xf5afc382,0xf5afc382
+.long	0xbe805d9f,0xbe805d9f
+.long	0x7c93d069,0x7c93d069
+.long	0xa92dd56f,0xa92dd56f
+.long	0xb31225cf,0xb31225cf
+.long	0x3b99acc8,0x3b99acc8
+.long	0xa77d1810,0xa77d1810
+.long	0x6e639ce8,0x6e639ce8
+.long	0x7bbb3bdb,0x7bbb3bdb
+.long	0x097826cd,0x097826cd
+.long	0xf418596e,0xf418596e
+.long	0x01b79aec,0x01b79aec
+.long	0xa89a4f83,0xa89a4f83
+.long	0x656e95e6,0x656e95e6
+.long	0x7ee6ffaa,0x7ee6ffaa
+.long	0x08cfbc21,0x08cfbc21
+.long	0xe6e815ef,0xe6e815ef
+.long	0xd99be7ba,0xd99be7ba
+.long	0xce366f4a,0xce366f4a
+.long	0xd4099fea,0xd4099fea
+.long	0xd67cb029,0xd67cb029
+.long	0xafb2a431,0xafb2a431
+.long	0x31233f2a,0x31233f2a
+.long	0x3094a5c6,0x3094a5c6
+.long	0xc066a235,0xc066a235
+.long	0x37bc4e74,0x37bc4e74
+.long	0xa6ca82fc,0xa6ca82fc
+.long	0xb0d090e0,0xb0d090e0
+.long	0x15d8a733,0x15d8a733
+.long	0x4a9804f1,0x4a9804f1
+.long	0xf7daec41,0xf7daec41
+.long	0x0e50cd7f,0x0e50cd7f
+.long	0x2ff69117,0x2ff69117
+.long	0x8dd64d76,0x8dd64d76
+.long	0x4db0ef43,0x4db0ef43
+.long	0x544daacc,0x544daacc
+.long	0xdf0496e4,0xdf0496e4
+.long	0xe3b5d19e,0xe3b5d19e
+.long	0x1b886a4c,0x1b886a4c
+.long	0xb81f2cc1,0xb81f2cc1
+.long	0x7f516546,0x7f516546
+.long	0x04ea5e9d,0x04ea5e9d
+.long	0x5d358c01,0x5d358c01
+.long	0x737487fa,0x737487fa
+.long	0x2e410bfb,0x2e410bfb
+.long	0x5a1d67b3,0x5a1d67b3
+.long	0x52d2db92,0x52d2db92
+.long	0x335610e9,0x335610e9
+.long	0x1347d66d,0x1347d66d
+.long	0x8c61d79a,0x8c61d79a
+.long	0x7a0ca137,0x7a0ca137
+.long	0x8e14f859,0x8e14f859
+.long	0x893c13eb,0x893c13eb
+.long	0xee27a9ce,0xee27a9ce
+.long	0x35c961b7,0x35c961b7
+.long	0xede51ce1,0xede51ce1
+.long	0x3cb1477a,0x3cb1477a
+.long	0x59dfd29c,0x59dfd29c
+.long	0x3f73f255,0x3f73f255
+.long	0x79ce1418,0x79ce1418
+.long	0xbf37c773,0xbf37c773
+.long	0xeacdf753,0xeacdf753
+.long	0x5baafd5f,0x5baafd5f
+.long	0x146f3ddf,0x146f3ddf
+.long	0x86db4478,0x86db4478
+.long	0x81f3afca,0x81f3afca
+.long	0x3ec468b9,0x3ec468b9
+.long	0x2c342438,0x2c342438
+.long	0x5f40a3c2,0x5f40a3c2
+.long	0x72c31d16,0x72c31d16
+.long	0x0c25e2bc,0x0c25e2bc
+.long	0x8b493c28,0x8b493c28
+.long	0x41950dff,0x41950dff
+.long	0x7101a839,0x7101a839
+.long	0xdeb30c08,0xdeb30c08
+.long	0x9ce4b4d8,0x9ce4b4d8
+.long	0x90c15664,0x90c15664
+.long	0x6184cb7b,0x6184cb7b
+.long	0x70b632d5,0x70b632d5
+.long	0x745c6c48,0x745c6c48
+.long	0x4257b8d0,0x4257b8d0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38
+.byte	0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb
+.byte	0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87
+.byte	0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb
+.byte	0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d
+.byte	0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e
+.byte	0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2
+.byte	0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25
+.byte	0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16
+.byte	0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92
+.byte	0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda
+.byte	0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84
+.byte	0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a
+.byte	0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06
+.byte	0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02
+.byte	0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b
+.byte	0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea
+.byte	0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73
+.byte	0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85
+.byte	0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e
+.byte	0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89
+.byte	0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b
+.byte	0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20
+.byte	0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4
+.byte	0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31
+.byte	0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f
+.byte	0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d
+.byte	0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef
+.byte	0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0
+.byte	0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61
+.byte	0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26
+.byte	0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
+.long	0x80808080, 0x80808080, 0xfefefefe, 0xfefefefe
+.long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
+.byte	65,69,83,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
+
+.def	block_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+block_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_block_prologue
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_block_prologue
+
+	movq	24(%rax),%rax
+	leaq	48(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	-32(%rax),%r13
+	movq	-40(%rax),%r14
+	movq	-48(%rax),%r15
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lin_block_prologue:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	jmp	.Lcommon_seh_exit
+
+
+.def	key_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+key_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_key_prologue
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_key_prologue
+
+	leaq	56(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	-32(%rax),%r13
+	movq	-40(%rax),%r14
+	movq	-48(%rax),%r15
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lin_key_prologue:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	jmp	.Lcommon_seh_exit
+
+
+.def	cbc_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+cbc_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	leaq	.Lcbc_prologue(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_cbc_prologue
+
+	leaq	.Lcbc_fast_body(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_cbc_frame_setup
+
+	leaq	.Lcbc_slow_prologue(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_cbc_body
+
+	leaq	.Lcbc_slow_body(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_cbc_frame_setup
+
+.Lin_cbc_body:
+	movq	152(%r8),%rax
+
+	leaq	.Lcbc_epilogue(%rip),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_cbc_prologue
+
+	leaq	8(%rax),%rax
+
+	leaq	.Lcbc_popfq(%rip),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_cbc_prologue
+
+	movq	8(%rax),%rax
+	leaq	56(%rax),%rax
+
+.Lin_cbc_frame_setup:
+	movq	-16(%rax),%rbx
+	movq	-24(%rax),%rbp
+	movq	-32(%rax),%r12
+	movq	-40(%rax),%r13
+	movq	-48(%rax),%r14
+	movq	-56(%rax),%r15
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lin_cbc_prologue:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+.Lcommon_seh_exit:
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.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
+.p2align	3
+.LSEH_info_AES_encrypt:
+.byte	9,0,0,0
+.rva	block_se_handler
+.rva	.Lenc_prologue,.Lenc_epilogue	
+.LSEH_info_AES_decrypt:
+.byte	9,0,0,0
+.rva	block_se_handler
+.rva	.Ldec_prologue,.Ldec_epilogue	
+.LSEH_info_AES_set_encrypt_key:
+.byte	9,0,0,0
+.rva	key_se_handler
+.rva	.Lenc_key_prologue,.Lenc_key_epilogue	
+.LSEH_info_AES_set_decrypt_key:
+.byte	9,0,0,0
+.rva	key_se_handler
+.rva	.Ldec_key_prologue,.Ldec_key_epilogue	
+.LSEH_info_AES_cbc_encrypt:
+.byte	9,0,0,0
+.rva	cbc_se_handler
diff --git a/crypto/aes/aes-mips.S b/crypto/aes/aes-mips.S
new file mode 100644
index 0000000..2a8e3e4
--- /dev/null
+++ b/crypto/aes/aes-mips.S
@@ -0,0 +1,1336 @@
+.text
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+.set	noat
+.align	5
+.ent	_mips_AES_encrypt
+_mips_AES_encrypt:
+	.frame	$29,0,$31
+	.set	reorder
+	lw	$12,0($6)
+	lw	$13,4($6)
+	lw	$14,8($6)
+	lw	$15,12($6)
+	lw	$30,240($6)
+	add $3,$6,16
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	sub	$30,1
+	srl	$1,$9,6
+.Loop_enc:
+	srl	$2,$10,6
+	srl	$24,$11,6
+	srl	$25,$8,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$12,2($1)		# Te1[s1>>16]
+	lwl	$13,2($2)		# Te1[s2>>16]
+	lwl	$14,2($24)		# Te1[s3>>16]
+	lwl	$15,2($25)		# Te1[s0>>16]
+	lwr	$12,3($1)		# Te1[s1>>16]
+	lwr	$13,3($2)		# Te1[s2>>16]
+	lwr	$14,3($24)		# Te1[s3>>16]
+	lwr	$15,3($25)		# Te1[s0>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$16,1($1)		# Te2[s2>>8]
+	lwl	$17,1($2)		# Te2[s3>>8]
+	lwl	$18,1($24)		# Te2[s0>>8]
+	lwl	$19,1($25)		# Te2[s1>>8]
+	lwr	$16,2($1)		# Te2[s2>>8]
+	lwr	$17,2($2)		# Te2[s3>>8]
+	lwr	$18,2($24)		# Te2[s0>>8]
+	lwr	$19,2($25)		# Te2[s1>>8]
+
+	srl	$1,$11,22
+	srl	$2,$8,22
+	srl	$24,$9,22
+	srl	$25,$10,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$20,0($1)		# Te3[s3]
+	lwl	$21,0($2)		# Te3[s0]
+	lwl	$22,0($24)		# Te3[s1]
+	lwl	$23,0($25)		# Te3[s2]
+	lwr	$20,1($1)		# Te3[s3]
+	lwr	$21,1($2)		# Te3[s0]
+	lwr	$22,1($24)		# Te3[s1]
+	lwr	$23,1($25)		# Te3[s2]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+	lw	$16,0($1)		# Te0[s0>>24]
+	lw	$17,0($2)		# Te0[s1>>24]
+	lw	$18,0($24)		# Te0[s2>>24]
+	lw	$19,0($25)		# Te0[s3>>24]
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	sub	$30,1
+	add $3,16
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+	.set	noreorder
+	bnez	$30,.Loop_enc
+	srl	$1,$9,6
+
+	.set	reorder
+	srl	$2,$10,6
+	srl	$24,$11,6
+	srl	$25,$8,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$12,2($1)		# Te4[s1>>16]
+	lbu	$13,2($2)		# Te4[s2>>16]
+	lbu	$14,2($24)		# Te4[s3>>16]
+	lbu	$15,2($25)		# Te4[s0>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$16,2($1)		# Te4[s2>>8]
+	lbu	$17,2($2)		# Te4[s3>>8]
+	lbu	$18,2($24)		# Te4[s0>>8]
+	lbu	$19,2($25)		# Te4[s1>>8]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$20,2($1)		# Te4[s0>>24]
+	lbu	$21,2($2)		# Te4[s1>>24]
+	lbu	$22,2($24)		# Te4[s2>>24]
+	lbu	$23,2($25)		# Te4[s3>>24]
+
+	srl	$1,$11,22
+	srl	$2,$8,22
+	srl	$24,$9,22
+	srl	$25,$10,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+
+	sll	$12,$12,8
+	sll	$13,$13,8
+	sll	$14,$14,8
+	sll	$15,$15,8
+
+	sll	$16,$16,16
+	sll	$17,$17,16
+	sll	$18,$18,16
+	sll	$19,$19,16
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$16,2($1)		# Te4[s3]
+	lbu	$17,2($2)		# Te4[s0]
+	lbu	$18,2($24)		# Te4[s1]
+	lbu	$19,2($25)		# Te4[s2]
+
+	#sll	$20,$20,0
+	#sll	$21,$21,0
+	#sll	$22,$22,0
+	#sll	$23,$23,0
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	sll	$16,$16,24
+	sll	$17,$17,24
+	sll	$18,$18,24
+	sll	$19,$19,24
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	jr	$31
+.end	_mips_AES_encrypt
+
+.align	5
+.globl	AES_encrypt
+.ent	AES_encrypt
+AES_encrypt:
+	.frame	$29,64,$31
+	.mask	3237937152,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,64
+	sw	$31,64-1*4($29)
+	sw	$30,64-2*4($29)
+	sw	$23,64-3*4($29)
+	sw	$22,64-4*4($29)
+	sw	$21,64-5*4($29)
+	sw	$20,64-6*4($29)
+	sw	$19,64-7*4($29)
+	sw	$18,64-8*4($29)
+	sw	$17,64-9*4($29)
+	sw	$16,64-10*4($29)
+	.set	reorder
+	la	$7,AES_Te		# PIC-ified 'load address'
+
+	lwl	$8,0+3($4)
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+
+	bal	_mips_AES_encrypt
+
+	swr	$8,0+0($5)
+	swr	$9,4+0($5)
+	swr	$10,8+0($5)
+	swr	$11,12+0($5)
+	swl	$8,0+3($5)
+	swl	$9,4+3($5)
+	swl	$10,8+3($5)
+	swl	$11,12+3($5)
+
+	.set	noreorder
+	lw	$31,64-1*4($29)
+	lw	$30,64-2*4($29)
+	lw	$23,64-3*4($29)
+	lw	$22,64-4*4($29)
+	lw	$21,64-5*4($29)
+	lw	$20,64-6*4($29)
+	lw	$19,64-7*4($29)
+	lw	$18,64-8*4($29)
+	lw	$17,64-9*4($29)
+	lw	$16,64-10*4($29)
+	jr	$31
+	add $29,64
+.end	AES_encrypt
+.align	5
+.ent	_mips_AES_decrypt
+_mips_AES_decrypt:
+	.frame	$29,0,$31
+	.set	reorder
+	lw	$12,0($6)
+	lw	$13,4($6)
+	lw	$14,8($6)
+	lw	$15,12($6)
+	lw	$30,240($6)
+	add $3,$6,16
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	sub	$30,1
+	srl	$1,$11,6
+.Loop_dec:
+	srl	$2,$8,6
+	srl	$24,$9,6
+	srl	$25,$10,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$12,2($1)		# Td1[s3>>16]
+	lwl	$13,2($2)		# Td1[s0>>16]
+	lwl	$14,2($24)		# Td1[s1>>16]
+	lwl	$15,2($25)		# Td1[s2>>16]
+	lwr	$12,3($1)		# Td1[s3>>16]
+	lwr	$13,3($2)		# Td1[s0>>16]
+	lwr	$14,3($24)		# Td1[s1>>16]
+	lwr	$15,3($25)		# Td1[s2>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$16,1($1)		# Td2[s2>>8]
+	lwl	$17,1($2)		# Td2[s3>>8]
+	lwl	$18,1($24)		# Td2[s0>>8]
+	lwl	$19,1($25)		# Td2[s1>>8]
+	lwr	$16,2($1)		# Td2[s2>>8]
+	lwr	$17,2($2)		# Td2[s3>>8]
+	lwr	$18,2($24)		# Td2[s0>>8]
+	lwr	$19,2($25)		# Td2[s1>>8]
+
+	srl	$1,$9,22
+	srl	$2,$10,22
+	srl	$24,$11,22
+	srl	$25,$8,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lwl	$20,0($1)		# Td3[s1]
+	lwl	$21,0($2)		# Td3[s2]
+	lwl	$22,0($24)		# Td3[s3]
+	lwl	$23,0($25)		# Td3[s0]
+	lwr	$20,1($1)		# Td3[s1]
+	lwr	$21,1($2)		# Td3[s2]
+	lwr	$22,1($24)		# Td3[s3]
+	lwr	$23,1($25)		# Td3[s0]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+
+	lw	$16,0($1)		# Td0[s0>>24]
+	lw	$17,0($2)		# Td0[s1>>24]
+	lw	$18,0($24)		# Td0[s2>>24]
+	lw	$19,0($25)		# Td0[s3>>24]
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	sub	$30,1
+	add $3,16
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+	.set	noreorder
+	bnez	$30,.Loop_dec
+	srl	$1,$11,6
+
+	.set	reorder
+	lw	$16,1024($7)		# prefetch Td4
+	lw	$17,1024+32($7)
+	lw	$18,1024+64($7)
+	lw	$19,1024+96($7)
+	lw	$20,1024+128($7)
+	lw	$21,1024+160($7)
+	lw	$22,1024+192($7)
+	lw	$23,1024+224($7)
+
+	srl	$1,$11,8
+	srl	$2,$8,8
+	srl	$24,$9,8
+	srl	$25,$10,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,0xff
+	and	$25,0xff
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$12,1024($1)		# Td4[s3>>16]
+	lbu	$13,1024($2)		# Td4[s0>>16]
+	lbu	$14,1024($24)		# Td4[s1>>16]
+	lbu	$15,1024($25)		# Td4[s2>>16]
+
+	srl	$1,$10,16
+	srl	$2,$11,16
+	srl	$24,$8,16
+	srl	$25,$9,16
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,0xff
+	and	$25,0xff
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$16,1024($1)		# Td4[s2>>8]
+	lbu	$17,1024($2)		# Td4[s3>>8]
+	lbu	$18,1024($24)		# Td4[s0>>8]
+	lbu	$19,1024($25)		# Td4[s1>>8]
+
+	and	$1,$8,0xff
+	and	$2,$9,0xff
+	and	$24,$10,0xff
+	and	$25,$11,0xff
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$20,1024($1)		# Td4[s0>>24]
+	lbu	$21,1024($2)		# Td4[s1>>24]
+	lbu	$22,1024($24)		# Td4[s2>>24]
+	lbu	$23,1024($25)		# Td4[s3>>24]
+
+	srl	$1,$9,24
+	srl	$2,$10,24
+	srl	$24,$11,24
+	srl	$25,$8,24
+
+	sll	$12,$12,8
+	sll	$13,$13,8
+	sll	$14,$14,8
+	sll	$15,$15,8
+
+	sll	$16,$16,16
+	sll	$17,$17,16
+	sll	$18,$18,16
+	sll	$19,$19,16
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$16,1024($1)		# Td4[s1]
+	lbu	$17,1024($2)		# Td4[s2]
+	lbu	$18,1024($24)		# Td4[s3]
+	lbu	$19,1024($25)		# Td4[s0]
+
+	#sll	$20,$20,0
+	#sll	$21,$21,0
+	#sll	$22,$22,0
+	#sll	$23,$23,0
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	sll	$16,$16,24
+	sll	$17,$17,24
+	sll	$18,$18,24
+	sll	$19,$19,24
+
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	jr	$31
+.end	_mips_AES_decrypt
+
+.align	5
+.globl	AES_decrypt
+.ent	AES_decrypt
+AES_decrypt:
+	.frame	$29,64,$31
+	.mask	3237937152,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,64
+	sw	$31,64-1*4($29)
+	sw	$30,64-2*4($29)
+	sw	$23,64-3*4($29)
+	sw	$22,64-4*4($29)
+	sw	$21,64-5*4($29)
+	sw	$20,64-6*4($29)
+	sw	$19,64-7*4($29)
+	sw	$18,64-8*4($29)
+	sw	$17,64-9*4($29)
+	sw	$16,64-10*4($29)
+	.set	reorder
+	la	$7,AES_Td		# PIC-ified 'load address'
+
+	lwl	$8,0+3($4)
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+
+	bal	_mips_AES_decrypt
+
+	swr	$8,0+0($5)
+	swr	$9,4+0($5)
+	swr	$10,8+0($5)
+	swr	$11,12+0($5)
+	swl	$8,0+3($5)
+	swl	$9,4+3($5)
+	swl	$10,8+3($5)
+	swl	$11,12+3($5)
+
+	.set	noreorder
+	lw	$31,64-1*4($29)
+	lw	$30,64-2*4($29)
+	lw	$23,64-3*4($29)
+	lw	$22,64-4*4($29)
+	lw	$21,64-5*4($29)
+	lw	$20,64-6*4($29)
+	lw	$19,64-7*4($29)
+	lw	$18,64-8*4($29)
+	lw	$17,64-9*4($29)
+	lw	$16,64-10*4($29)
+	jr	$31
+	add $29,64
+.end	AES_decrypt
+.align	5
+.ent	_mips_AES_set_encrypt_key
+_mips_AES_set_encrypt_key:
+	.frame	$29,0,$31
+	.set	noreorder
+	beqz	$4,.Lekey_done
+	li	$2,-1
+	beqz	$6,.Lekey_done
+	add $3,$7,1024+256
+
+	.set	reorder
+	lwl	$8,0+3($4)	# load 128 bits
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	li	$1,128
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+	.set	noreorder
+	beq	$5,$1,.L128bits
+	li	$30,10
+
+	.set	reorder
+	lwl	$12,16+3($4)	# load 192 bits
+	lwl	$13,20+3($4)
+	li	$1,192
+	lwr	$12,16+0($4)
+	lwr	$13,20+0($4)
+	.set	noreorder
+	beq	$5,$1,.L192bits
+	li	$30,8
+
+	.set	reorder
+	lwl	$14,24+3($4)	# load 256 bits
+	lwl	$15,28+3($4)
+	li	$1,256
+	lwr	$14,24+0($4)
+	lwr	$15,28+0($4)
+	.set	noreorder
+	beq	$5,$1,.L256bits
+	li	$30,7
+
+	b	.Lekey_done
+	li	$2,-2
+
+.align	4
+.L128bits:
+	.set	reorder
+	srl	$1,$11,16
+	srl	$2,$11,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$11,0xff
+	srl	$25,$11,24
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sub	$30,1
+	add $6,16
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+
+	.set	noreorder
+	bnez	$30,.L128bits
+	add $3,4
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	li	$30,10
+	sw	$11,12($6)
+	li	$2,0
+	sw	$30,80($6)
+	b	.Lekey_done
+	sub $6,10*16
+
+.align	4
+.L192bits:
+	.set	reorder
+	srl	$1,$13,16
+	srl	$2,$13,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$13,0xff
+	srl	$25,$13,24
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sw	$12,16($6)
+	sw	$13,20($6)
+	sub	$30,1
+	add $6,24
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+	xor	$12,$11
+	xor	$13,$12
+
+	.set	noreorder
+	bnez	$30,.L192bits
+	add $3,4
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	li	$30,12
+	sw	$11,12($6)
+	li	$2,0
+	sw	$30,48($6)
+	b	.Lekey_done
+	sub $6,12*16
+
+.align	4
+.L256bits:
+	.set	reorder
+	srl	$1,$15,16
+	srl	$2,$15,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$15,0xff
+	srl	$25,$15,24
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sw	$12,16($6)
+	sw	$13,20($6)
+	sw	$14,24($6)
+	sw	$15,28($6)
+	sub	$30,1
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+	beqz	$30,.L256bits_done
+
+	srl	$1,$11,24
+	srl	$2,$11,16
+	srl	$24,$11,8
+	and	$25,$11,0xff
+	and	$2,0xff
+	and	$24,0xff
+	add $1,$7
+	add $2,$7
+	add $24,$7
+	add $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+	sll	$1,24
+	sll	$2,16
+	sll	$24,8
+
+	xor	$12,$1
+	xor	$12,$2
+	xor	$12,$24
+	xor	$12,$25
+
+	xor	$13,$12
+	xor	$14,$13
+	xor	$15,$14
+
+	add $6,32
+	.set	noreorder
+	b	.L256bits
+	add $3,4
+
+.L256bits_done:
+	sw	$8,32($6)
+	sw	$9,36($6)
+	sw	$10,40($6)
+	li	$30,14
+	sw	$11,44($6)
+	li	$2,0
+	sw	$30,48($6)
+	sub $6,12*16
+
+.Lekey_done:
+	jr	$31
+	nop
+.end	_mips_AES_set_encrypt_key
+
+.globl	AES_set_encrypt_key
+.ent	AES_set_encrypt_key
+AES_set_encrypt_key:
+	.frame	$29,32,$31
+	.mask	3221225472,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,32
+	sw	$31,32-1*4($29)
+	sw	$30,32-2*4($29)
+	.set	reorder
+	la	$7,AES_Te		# PIC-ified 'load address'
+
+	bal	_mips_AES_set_encrypt_key
+
+	.set	noreorder
+	move	$4,$2
+	lw	$31,32-1*4($29)
+	lw	$30,32-2*4($29)
+	jr	$31
+	add $29,32
+.end	AES_set_encrypt_key
+.align	5
+.globl	AES_set_decrypt_key
+.ent	AES_set_decrypt_key
+AES_set_decrypt_key:
+	.frame	$29,32,$31
+	.mask	3221225472,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,32
+	sw	$31,32-1*4($29)
+	sw	$30,32-2*4($29)
+	.set	reorder
+	la	$7,AES_Te		# PIC-ified 'load address'
+
+	bal	_mips_AES_set_encrypt_key
+
+	bltz	$2,.Ldkey_done
+
+	sll	$1,$30,4
+	add $4,$6,0
+	add $5,$6,$1
+.align	4
+.Lswap:
+	lw	$8,0($4)
+	lw	$9,4($4)
+	lw	$10,8($4)
+	lw	$11,12($4)
+	lw	$12,0($5)
+	lw	$13,4($5)
+	lw	$14,8($5)
+	lw	$15,12($5)
+	sw	$8,0($5)
+	sw	$9,4($5)
+	sw	$10,8($5)
+	sw	$11,12($5)
+	add $4,16
+	sub $5,16
+	sw	$12,-16($4)
+	sw	$13,-12($4)
+	sw	$14,-8($4)
+	sw	$15,-4($4)
+	bne	$4,$5,.Lswap
+
+	lw	$8,16($6)		# modulo-scheduled
+	lui	$2,0x8080
+	sub	$30,1
+	or	$2,0x8080
+	sll	$30,2
+	add $6,16
+	lui	$25,0x1b1b
+	nor	$24,$0,$2
+	or	$25,0x1b1b
+.align	4
+.Lmix:
+	and	$1,$8,$2
+	and	$9,$8,$24
+	srl	$10,$1,7
+	addu	$9,$9		# tp2<<1
+	subu	$1,$10
+	and	$1,$25
+	xor	$9,$1
+
+	and	$1,$9,$2
+	and	$10,$9,$24
+	srl	$11,$1,7
+	addu	$10,$10		# tp4<<1
+	subu	$1,$11
+	and	$1,$25
+	xor	$10,$1
+
+	and	$1,$10,$2
+	and	$11,$10,$24
+	srl	$12,$1,7
+	addu	$11,$11		# tp8<<1
+	subu	$1,$12
+	and	$1,$25
+	xor	$11,$1
+
+	xor	$12,$11,$8
+	xor	$15,$11,$10
+	xor	$13,$12,$9
+	xor	$14,$12,$10
+
+	sll	$8,$14,16
+	 xor	$15,$9
+	srl	$9,$14,16
+	xor	$15,$8
+	sll	$8,$12,8
+	xor	$15,$9
+	srl	$9,$12,24
+	xor	$15,$8
+	sll	$8,$13,24
+	xor	$15,$9
+	srl	$9,$13,8
+	xor	$15,$8
+	lw	$8,4($6)		# modulo-scheduled
+	xor	$15,$9
+	sub	$30,1
+	sw	$15,0($6)
+	add $6,4
+	bnez	$30,.Lmix
+
+	li	$2,0
+.Ldkey_done:
+	.set	noreorder
+	move	$4,$2
+	lw	$31,32-1*4($29)
+	lw	$30,32-2*4($29)
+	jr	$31
+	add $29,32
+.end	AES_set_decrypt_key
+.rdata
+.align	6
+AES_Te:
+.byte	0xc6,0x63,0x63,0xa5,	0xf8,0x7c,0x7c,0x84	# Te0
+.byte	0xee,0x77,0x77,0x99,	0xf6,0x7b,0x7b,0x8d
+.byte	0xff,0xf2,0xf2,0x0d,	0xd6,0x6b,0x6b,0xbd
+.byte	0xde,0x6f,0x6f,0xb1,	0x91,0xc5,0xc5,0x54
+.byte	0x60,0x30,0x30,0x50,	0x02,0x01,0x01,0x03
+.byte	0xce,0x67,0x67,0xa9,	0x56,0x2b,0x2b,0x7d
+.byte	0xe7,0xfe,0xfe,0x19,	0xb5,0xd7,0xd7,0x62
+.byte	0x4d,0xab,0xab,0xe6,	0xec,0x76,0x76,0x9a
+.byte	0x8f,0xca,0xca,0x45,	0x1f,0x82,0x82,0x9d
+.byte	0x89,0xc9,0xc9,0x40,	0xfa,0x7d,0x7d,0x87
+.byte	0xef,0xfa,0xfa,0x15,	0xb2,0x59,0x59,0xeb
+.byte	0x8e,0x47,0x47,0xc9,	0xfb,0xf0,0xf0,0x0b
+.byte	0x41,0xad,0xad,0xec,	0xb3,0xd4,0xd4,0x67
+.byte	0x5f,0xa2,0xa2,0xfd,	0x45,0xaf,0xaf,0xea
+.byte	0x23,0x9c,0x9c,0xbf,	0x53,0xa4,0xa4,0xf7
+.byte	0xe4,0x72,0x72,0x96,	0x9b,0xc0,0xc0,0x5b
+.byte	0x75,0xb7,0xb7,0xc2,	0xe1,0xfd,0xfd,0x1c
+.byte	0x3d,0x93,0x93,0xae,	0x4c,0x26,0x26,0x6a
+.byte	0x6c,0x36,0x36,0x5a,	0x7e,0x3f,0x3f,0x41
+.byte	0xf5,0xf7,0xf7,0x02,	0x83,0xcc,0xcc,0x4f
+.byte	0x68,0x34,0x34,0x5c,	0x51,0xa5,0xa5,0xf4
+.byte	0xd1,0xe5,0xe5,0x34,	0xf9,0xf1,0xf1,0x08
+.byte	0xe2,0x71,0x71,0x93,	0xab,0xd8,0xd8,0x73
+.byte	0x62,0x31,0x31,0x53,	0x2a,0x15,0x15,0x3f
+.byte	0x08,0x04,0x04,0x0c,	0x95,0xc7,0xc7,0x52
+.byte	0x46,0x23,0x23,0x65,	0x9d,0xc3,0xc3,0x5e
+.byte	0x30,0x18,0x18,0x28,	0x37,0x96,0x96,0xa1
+.byte	0x0a,0x05,0x05,0x0f,	0x2f,0x9a,0x9a,0xb5
+.byte	0x0e,0x07,0x07,0x09,	0x24,0x12,0x12,0x36
+.byte	0x1b,0x80,0x80,0x9b,	0xdf,0xe2,0xe2,0x3d
+.byte	0xcd,0xeb,0xeb,0x26,	0x4e,0x27,0x27,0x69
+.byte	0x7f,0xb2,0xb2,0xcd,	0xea,0x75,0x75,0x9f
+.byte	0x12,0x09,0x09,0x1b,	0x1d,0x83,0x83,0x9e
+.byte	0x58,0x2c,0x2c,0x74,	0x34,0x1a,0x1a,0x2e
+.byte	0x36,0x1b,0x1b,0x2d,	0xdc,0x6e,0x6e,0xb2
+.byte	0xb4,0x5a,0x5a,0xee,	0x5b,0xa0,0xa0,0xfb
+.byte	0xa4,0x52,0x52,0xf6,	0x76,0x3b,0x3b,0x4d
+.byte	0xb7,0xd6,0xd6,0x61,	0x7d,0xb3,0xb3,0xce
+.byte	0x52,0x29,0x29,0x7b,	0xdd,0xe3,0xe3,0x3e
+.byte	0x5e,0x2f,0x2f,0x71,	0x13,0x84,0x84,0x97
+.byte	0xa6,0x53,0x53,0xf5,	0xb9,0xd1,0xd1,0x68
+.byte	0x00,0x00,0x00,0x00,	0xc1,0xed,0xed,0x2c
+.byte	0x40,0x20,0x20,0x60,	0xe3,0xfc,0xfc,0x1f
+.byte	0x79,0xb1,0xb1,0xc8,	0xb6,0x5b,0x5b,0xed
+.byte	0xd4,0x6a,0x6a,0xbe,	0x8d,0xcb,0xcb,0x46
+.byte	0x67,0xbe,0xbe,0xd9,	0x72,0x39,0x39,0x4b
+.byte	0x94,0x4a,0x4a,0xde,	0x98,0x4c,0x4c,0xd4
+.byte	0xb0,0x58,0x58,0xe8,	0x85,0xcf,0xcf,0x4a
+.byte	0xbb,0xd0,0xd0,0x6b,	0xc5,0xef,0xef,0x2a
+.byte	0x4f,0xaa,0xaa,0xe5,	0xed,0xfb,0xfb,0x16
+.byte	0x86,0x43,0x43,0xc5,	0x9a,0x4d,0x4d,0xd7
+.byte	0x66,0x33,0x33,0x55,	0x11,0x85,0x85,0x94
+.byte	0x8a,0x45,0x45,0xcf,	0xe9,0xf9,0xf9,0x10
+.byte	0x04,0x02,0x02,0x06,	0xfe,0x7f,0x7f,0x81
+.byte	0xa0,0x50,0x50,0xf0,	0x78,0x3c,0x3c,0x44
+.byte	0x25,0x9f,0x9f,0xba,	0x4b,0xa8,0xa8,0xe3
+.byte	0xa2,0x51,0x51,0xf3,	0x5d,0xa3,0xa3,0xfe
+.byte	0x80,0x40,0x40,0xc0,	0x05,0x8f,0x8f,0x8a
+.byte	0x3f,0x92,0x92,0xad,	0x21,0x9d,0x9d,0xbc
+.byte	0x70,0x38,0x38,0x48,	0xf1,0xf5,0xf5,0x04
+.byte	0x63,0xbc,0xbc,0xdf,	0x77,0xb6,0xb6,0xc1
+.byte	0xaf,0xda,0xda,0x75,	0x42,0x21,0x21,0x63
+.byte	0x20,0x10,0x10,0x30,	0xe5,0xff,0xff,0x1a
+.byte	0xfd,0xf3,0xf3,0x0e,	0xbf,0xd2,0xd2,0x6d
+.byte	0x81,0xcd,0xcd,0x4c,	0x18,0x0c,0x0c,0x14
+.byte	0x26,0x13,0x13,0x35,	0xc3,0xec,0xec,0x2f
+.byte	0xbe,0x5f,0x5f,0xe1,	0x35,0x97,0x97,0xa2
+.byte	0x88,0x44,0x44,0xcc,	0x2e,0x17,0x17,0x39
+.byte	0x93,0xc4,0xc4,0x57,	0x55,0xa7,0xa7,0xf2
+.byte	0xfc,0x7e,0x7e,0x82,	0x7a,0x3d,0x3d,0x47
+.byte	0xc8,0x64,0x64,0xac,	0xba,0x5d,0x5d,0xe7
+.byte	0x32,0x19,0x19,0x2b,	0xe6,0x73,0x73,0x95
+.byte	0xc0,0x60,0x60,0xa0,	0x19,0x81,0x81,0x98
+.byte	0x9e,0x4f,0x4f,0xd1,	0xa3,0xdc,0xdc,0x7f
+.byte	0x44,0x22,0x22,0x66,	0x54,0x2a,0x2a,0x7e
+.byte	0x3b,0x90,0x90,0xab,	0x0b,0x88,0x88,0x83
+.byte	0x8c,0x46,0x46,0xca,	0xc7,0xee,0xee,0x29
+.byte	0x6b,0xb8,0xb8,0xd3,	0x28,0x14,0x14,0x3c
+.byte	0xa7,0xde,0xde,0x79,	0xbc,0x5e,0x5e,0xe2
+.byte	0x16,0x0b,0x0b,0x1d,	0xad,0xdb,0xdb,0x76
+.byte	0xdb,0xe0,0xe0,0x3b,	0x64,0x32,0x32,0x56
+.byte	0x74,0x3a,0x3a,0x4e,	0x14,0x0a,0x0a,0x1e
+.byte	0x92,0x49,0x49,0xdb,	0x0c,0x06,0x06,0x0a
+.byte	0x48,0x24,0x24,0x6c,	0xb8,0x5c,0x5c,0xe4
+.byte	0x9f,0xc2,0xc2,0x5d,	0xbd,0xd3,0xd3,0x6e
+.byte	0x43,0xac,0xac,0xef,	0xc4,0x62,0x62,0xa6
+.byte	0x39,0x91,0x91,0xa8,	0x31,0x95,0x95,0xa4
+.byte	0xd3,0xe4,0xe4,0x37,	0xf2,0x79,0x79,0x8b
+.byte	0xd5,0xe7,0xe7,0x32,	0x8b,0xc8,0xc8,0x43
+.byte	0x6e,0x37,0x37,0x59,	0xda,0x6d,0x6d,0xb7
+.byte	0x01,0x8d,0x8d,0x8c,	0xb1,0xd5,0xd5,0x64
+.byte	0x9c,0x4e,0x4e,0xd2,	0x49,0xa9,0xa9,0xe0
+.byte	0xd8,0x6c,0x6c,0xb4,	0xac,0x56,0x56,0xfa
+.byte	0xf3,0xf4,0xf4,0x07,	0xcf,0xea,0xea,0x25
+.byte	0xca,0x65,0x65,0xaf,	0xf4,0x7a,0x7a,0x8e
+.byte	0x47,0xae,0xae,0xe9,	0x10,0x08,0x08,0x18
+.byte	0x6f,0xba,0xba,0xd5,	0xf0,0x78,0x78,0x88
+.byte	0x4a,0x25,0x25,0x6f,	0x5c,0x2e,0x2e,0x72
+.byte	0x38,0x1c,0x1c,0x24,	0x57,0xa6,0xa6,0xf1
+.byte	0x73,0xb4,0xb4,0xc7,	0x97,0xc6,0xc6,0x51
+.byte	0xcb,0xe8,0xe8,0x23,	0xa1,0xdd,0xdd,0x7c
+.byte	0xe8,0x74,0x74,0x9c,	0x3e,0x1f,0x1f,0x21
+.byte	0x96,0x4b,0x4b,0xdd,	0x61,0xbd,0xbd,0xdc
+.byte	0x0d,0x8b,0x8b,0x86,	0x0f,0x8a,0x8a,0x85
+.byte	0xe0,0x70,0x70,0x90,	0x7c,0x3e,0x3e,0x42
+.byte	0x71,0xb5,0xb5,0xc4,	0xcc,0x66,0x66,0xaa
+.byte	0x90,0x48,0x48,0xd8,	0x06,0x03,0x03,0x05
+.byte	0xf7,0xf6,0xf6,0x01,	0x1c,0x0e,0x0e,0x12
+.byte	0xc2,0x61,0x61,0xa3,	0x6a,0x35,0x35,0x5f
+.byte	0xae,0x57,0x57,0xf9,	0x69,0xb9,0xb9,0xd0
+.byte	0x17,0x86,0x86,0x91,	0x99,0xc1,0xc1,0x58
+.byte	0x3a,0x1d,0x1d,0x27,	0x27,0x9e,0x9e,0xb9
+.byte	0xd9,0xe1,0xe1,0x38,	0xeb,0xf8,0xf8,0x13
+.byte	0x2b,0x98,0x98,0xb3,	0x22,0x11,0x11,0x33
+.byte	0xd2,0x69,0x69,0xbb,	0xa9,0xd9,0xd9,0x70
+.byte	0x07,0x8e,0x8e,0x89,	0x33,0x94,0x94,0xa7
+.byte	0x2d,0x9b,0x9b,0xb6,	0x3c,0x1e,0x1e,0x22
+.byte	0x15,0x87,0x87,0x92,	0xc9,0xe9,0xe9,0x20
+.byte	0x87,0xce,0xce,0x49,	0xaa,0x55,0x55,0xff
+.byte	0x50,0x28,0x28,0x78,	0xa5,0xdf,0xdf,0x7a
+.byte	0x03,0x8c,0x8c,0x8f,	0x59,0xa1,0xa1,0xf8
+.byte	0x09,0x89,0x89,0x80,	0x1a,0x0d,0x0d,0x17
+.byte	0x65,0xbf,0xbf,0xda,	0xd7,0xe6,0xe6,0x31
+.byte	0x84,0x42,0x42,0xc6,	0xd0,0x68,0x68,0xb8
+.byte	0x82,0x41,0x41,0xc3,	0x29,0x99,0x99,0xb0
+.byte	0x5a,0x2d,0x2d,0x77,	0x1e,0x0f,0x0f,0x11
+.byte	0x7b,0xb0,0xb0,0xcb,	0xa8,0x54,0x54,0xfc
+.byte	0x6d,0xbb,0xbb,0xd6,	0x2c,0x16,0x16,0x3a
+
+.byte	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5	# Te4
+.byte	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
+.byte	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
+.byte	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
+.byte	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
+.byte	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
+.byte	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
+.byte	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
+.byte	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
+.byte	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
+.byte	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
+.byte	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
+.byte	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
+.byte	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
+.byte	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
+.byte	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
+.byte	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+
+.byte	0x01,0x00,0x00,0x00,	0x02,0x00,0x00,0x00	# rcon
+.byte	0x04,0x00,0x00,0x00,	0x08,0x00,0x00,0x00
+.byte	0x10,0x00,0x00,0x00,	0x20,0x00,0x00,0x00
+.byte	0x40,0x00,0x00,0x00,	0x80,0x00,0x00,0x00
+.byte	0x1B,0x00,0x00,0x00,	0x36,0x00,0x00,0x00
+
+.align	6
+AES_Td:
+.byte	0x51,0xf4,0xa7,0x50,	0x7e,0x41,0x65,0x53	# Td0
+.byte	0x1a,0x17,0xa4,0xc3,	0x3a,0x27,0x5e,0x96
+.byte	0x3b,0xab,0x6b,0xcb,	0x1f,0x9d,0x45,0xf1
+.byte	0xac,0xfa,0x58,0xab,	0x4b,0xe3,0x03,0x93
+.byte	0x20,0x30,0xfa,0x55,	0xad,0x76,0x6d,0xf6
+.byte	0x88,0xcc,0x76,0x91,	0xf5,0x02,0x4c,0x25
+.byte	0x4f,0xe5,0xd7,0xfc,	0xc5,0x2a,0xcb,0xd7
+.byte	0x26,0x35,0x44,0x80,	0xb5,0x62,0xa3,0x8f
+.byte	0xde,0xb1,0x5a,0x49,	0x25,0xba,0x1b,0x67
+.byte	0x45,0xea,0x0e,0x98,	0x5d,0xfe,0xc0,0xe1
+.byte	0xc3,0x2f,0x75,0x02,	0x81,0x4c,0xf0,0x12
+.byte	0x8d,0x46,0x97,0xa3,	0x6b,0xd3,0xf9,0xc6
+.byte	0x03,0x8f,0x5f,0xe7,	0x15,0x92,0x9c,0x95
+.byte	0xbf,0x6d,0x7a,0xeb,	0x95,0x52,0x59,0xda
+.byte	0xd4,0xbe,0x83,0x2d,	0x58,0x74,0x21,0xd3
+.byte	0x49,0xe0,0x69,0x29,	0x8e,0xc9,0xc8,0x44
+.byte	0x75,0xc2,0x89,0x6a,	0xf4,0x8e,0x79,0x78
+.byte	0x99,0x58,0x3e,0x6b,	0x27,0xb9,0x71,0xdd
+.byte	0xbe,0xe1,0x4f,0xb6,	0xf0,0x88,0xad,0x17
+.byte	0xc9,0x20,0xac,0x66,	0x7d,0xce,0x3a,0xb4
+.byte	0x63,0xdf,0x4a,0x18,	0xe5,0x1a,0x31,0x82
+.byte	0x97,0x51,0x33,0x60,	0x62,0x53,0x7f,0x45
+.byte	0xb1,0x64,0x77,0xe0,	0xbb,0x6b,0xae,0x84
+.byte	0xfe,0x81,0xa0,0x1c,	0xf9,0x08,0x2b,0x94
+.byte	0x70,0x48,0x68,0x58,	0x8f,0x45,0xfd,0x19
+.byte	0x94,0xde,0x6c,0x87,	0x52,0x7b,0xf8,0xb7
+.byte	0xab,0x73,0xd3,0x23,	0x72,0x4b,0x02,0xe2
+.byte	0xe3,0x1f,0x8f,0x57,	0x66,0x55,0xab,0x2a
+.byte	0xb2,0xeb,0x28,0x07,	0x2f,0xb5,0xc2,0x03
+.byte	0x86,0xc5,0x7b,0x9a,	0xd3,0x37,0x08,0xa5
+.byte	0x30,0x28,0x87,0xf2,	0x23,0xbf,0xa5,0xb2
+.byte	0x02,0x03,0x6a,0xba,	0xed,0x16,0x82,0x5c
+.byte	0x8a,0xcf,0x1c,0x2b,	0xa7,0x79,0xb4,0x92
+.byte	0xf3,0x07,0xf2,0xf0,	0x4e,0x69,0xe2,0xa1
+.byte	0x65,0xda,0xf4,0xcd,	0x06,0x05,0xbe,0xd5
+.byte	0xd1,0x34,0x62,0x1f,	0xc4,0xa6,0xfe,0x8a
+.byte	0x34,0x2e,0x53,0x9d,	0xa2,0xf3,0x55,0xa0
+.byte	0x05,0x8a,0xe1,0x32,	0xa4,0xf6,0xeb,0x75
+.byte	0x0b,0x83,0xec,0x39,	0x40,0x60,0xef,0xaa
+.byte	0x5e,0x71,0x9f,0x06,	0xbd,0x6e,0x10,0x51
+.byte	0x3e,0x21,0x8a,0xf9,	0x96,0xdd,0x06,0x3d
+.byte	0xdd,0x3e,0x05,0xae,	0x4d,0xe6,0xbd,0x46
+.byte	0x91,0x54,0x8d,0xb5,	0x71,0xc4,0x5d,0x05
+.byte	0x04,0x06,0xd4,0x6f,	0x60,0x50,0x15,0xff
+.byte	0x19,0x98,0xfb,0x24,	0xd6,0xbd,0xe9,0x97
+.byte	0x89,0x40,0x43,0xcc,	0x67,0xd9,0x9e,0x77
+.byte	0xb0,0xe8,0x42,0xbd,	0x07,0x89,0x8b,0x88
+.byte	0xe7,0x19,0x5b,0x38,	0x79,0xc8,0xee,0xdb
+.byte	0xa1,0x7c,0x0a,0x47,	0x7c,0x42,0x0f,0xe9
+.byte	0xf8,0x84,0x1e,0xc9,	0x00,0x00,0x00,0x00
+.byte	0x09,0x80,0x86,0x83,	0x32,0x2b,0xed,0x48
+.byte	0x1e,0x11,0x70,0xac,	0x6c,0x5a,0x72,0x4e
+.byte	0xfd,0x0e,0xff,0xfb,	0x0f,0x85,0x38,0x56
+.byte	0x3d,0xae,0xd5,0x1e,	0x36,0x2d,0x39,0x27
+.byte	0x0a,0x0f,0xd9,0x64,	0x68,0x5c,0xa6,0x21
+.byte	0x9b,0x5b,0x54,0xd1,	0x24,0x36,0x2e,0x3a
+.byte	0x0c,0x0a,0x67,0xb1,	0x93,0x57,0xe7,0x0f
+.byte	0xb4,0xee,0x96,0xd2,	0x1b,0x9b,0x91,0x9e
+.byte	0x80,0xc0,0xc5,0x4f,	0x61,0xdc,0x20,0xa2
+.byte	0x5a,0x77,0x4b,0x69,	0x1c,0x12,0x1a,0x16
+.byte	0xe2,0x93,0xba,0x0a,	0xc0,0xa0,0x2a,0xe5
+.byte	0x3c,0x22,0xe0,0x43,	0x12,0x1b,0x17,0x1d
+.byte	0x0e,0x09,0x0d,0x0b,	0xf2,0x8b,0xc7,0xad
+.byte	0x2d,0xb6,0xa8,0xb9,	0x14,0x1e,0xa9,0xc8
+.byte	0x57,0xf1,0x19,0x85,	0xaf,0x75,0x07,0x4c
+.byte	0xee,0x99,0xdd,0xbb,	0xa3,0x7f,0x60,0xfd
+.byte	0xf7,0x01,0x26,0x9f,	0x5c,0x72,0xf5,0xbc
+.byte	0x44,0x66,0x3b,0xc5,	0x5b,0xfb,0x7e,0x34
+.byte	0x8b,0x43,0x29,0x76,	0xcb,0x23,0xc6,0xdc
+.byte	0xb6,0xed,0xfc,0x68,	0xb8,0xe4,0xf1,0x63
+.byte	0xd7,0x31,0xdc,0xca,	0x42,0x63,0x85,0x10
+.byte	0x13,0x97,0x22,0x40,	0x84,0xc6,0x11,0x20
+.byte	0x85,0x4a,0x24,0x7d,	0xd2,0xbb,0x3d,0xf8
+.byte	0xae,0xf9,0x32,0x11,	0xc7,0x29,0xa1,0x6d
+.byte	0x1d,0x9e,0x2f,0x4b,	0xdc,0xb2,0x30,0xf3
+.byte	0x0d,0x86,0x52,0xec,	0x77,0xc1,0xe3,0xd0
+.byte	0x2b,0xb3,0x16,0x6c,	0xa9,0x70,0xb9,0x99
+.byte	0x11,0x94,0x48,0xfa,	0x47,0xe9,0x64,0x22
+.byte	0xa8,0xfc,0x8c,0xc4,	0xa0,0xf0,0x3f,0x1a
+.byte	0x56,0x7d,0x2c,0xd8,	0x22,0x33,0x90,0xef
+.byte	0x87,0x49,0x4e,0xc7,	0xd9,0x38,0xd1,0xc1
+.byte	0x8c,0xca,0xa2,0xfe,	0x98,0xd4,0x0b,0x36
+.byte	0xa6,0xf5,0x81,0xcf,	0xa5,0x7a,0xde,0x28
+.byte	0xda,0xb7,0x8e,0x26,	0x3f,0xad,0xbf,0xa4
+.byte	0x2c,0x3a,0x9d,0xe4,	0x50,0x78,0x92,0x0d
+.byte	0x6a,0x5f,0xcc,0x9b,	0x54,0x7e,0x46,0x62
+.byte	0xf6,0x8d,0x13,0xc2,	0x90,0xd8,0xb8,0xe8
+.byte	0x2e,0x39,0xf7,0x5e,	0x82,0xc3,0xaf,0xf5
+.byte	0x9f,0x5d,0x80,0xbe,	0x69,0xd0,0x93,0x7c
+.byte	0x6f,0xd5,0x2d,0xa9,	0xcf,0x25,0x12,0xb3
+.byte	0xc8,0xac,0x99,0x3b,	0x10,0x18,0x7d,0xa7
+.byte	0xe8,0x9c,0x63,0x6e,	0xdb,0x3b,0xbb,0x7b
+.byte	0xcd,0x26,0x78,0x09,	0x6e,0x59,0x18,0xf4
+.byte	0xec,0x9a,0xb7,0x01,	0x83,0x4f,0x9a,0xa8
+.byte	0xe6,0x95,0x6e,0x65,	0xaa,0xff,0xe6,0x7e
+.byte	0x21,0xbc,0xcf,0x08,	0xef,0x15,0xe8,0xe6
+.byte	0xba,0xe7,0x9b,0xd9,	0x4a,0x6f,0x36,0xce
+.byte	0xea,0x9f,0x09,0xd4,	0x29,0xb0,0x7c,0xd6
+.byte	0x31,0xa4,0xb2,0xaf,	0x2a,0x3f,0x23,0x31
+.byte	0xc6,0xa5,0x94,0x30,	0x35,0xa2,0x66,0xc0
+.byte	0x74,0x4e,0xbc,0x37,	0xfc,0x82,0xca,0xa6
+.byte	0xe0,0x90,0xd0,0xb0,	0x33,0xa7,0xd8,0x15
+.byte	0xf1,0x04,0x98,0x4a,	0x41,0xec,0xda,0xf7
+.byte	0x7f,0xcd,0x50,0x0e,	0x17,0x91,0xf6,0x2f
+.byte	0x76,0x4d,0xd6,0x8d,	0x43,0xef,0xb0,0x4d
+.byte	0xcc,0xaa,0x4d,0x54,	0xe4,0x96,0x04,0xdf
+.byte	0x9e,0xd1,0xb5,0xe3,	0x4c,0x6a,0x88,0x1b
+.byte	0xc1,0x2c,0x1f,0xb8,	0x46,0x65,0x51,0x7f
+.byte	0x9d,0x5e,0xea,0x04,	0x01,0x8c,0x35,0x5d
+.byte	0xfa,0x87,0x74,0x73,	0xfb,0x0b,0x41,0x2e
+.byte	0xb3,0x67,0x1d,0x5a,	0x92,0xdb,0xd2,0x52
+.byte	0xe9,0x10,0x56,0x33,	0x6d,0xd6,0x47,0x13
+.byte	0x9a,0xd7,0x61,0x8c,	0x37,0xa1,0x0c,0x7a
+.byte	0x59,0xf8,0x14,0x8e,	0xeb,0x13,0x3c,0x89
+.byte	0xce,0xa9,0x27,0xee,	0xb7,0x61,0xc9,0x35
+.byte	0xe1,0x1c,0xe5,0xed,	0x7a,0x47,0xb1,0x3c
+.byte	0x9c,0xd2,0xdf,0x59,	0x55,0xf2,0x73,0x3f
+.byte	0x18,0x14,0xce,0x79,	0x73,0xc7,0x37,0xbf
+.byte	0x53,0xf7,0xcd,0xea,	0x5f,0xfd,0xaa,0x5b
+.byte	0xdf,0x3d,0x6f,0x14,	0x78,0x44,0xdb,0x86
+.byte	0xca,0xaf,0xf3,0x81,	0xb9,0x68,0xc4,0x3e
+.byte	0x38,0x24,0x34,0x2c,	0xc2,0xa3,0x40,0x5f
+.byte	0x16,0x1d,0xc3,0x72,	0xbc,0xe2,0x25,0x0c
+.byte	0x28,0x3c,0x49,0x8b,	0xff,0x0d,0x95,0x41
+.byte	0x39,0xa8,0x01,0x71,	0x08,0x0c,0xb3,0xde
+.byte	0xd8,0xb4,0xe4,0x9c,	0x64,0x56,0xc1,0x90
+.byte	0x7b,0xcb,0x84,0x61,	0xd5,0x32,0xb6,0x70
+.byte	0x48,0x6c,0x5c,0x74,	0xd0,0xb8,0x57,0x42
+
+.byte	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38	# Td4
+.byte	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+.byte	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+.byte	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+.byte	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+.byte	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+.byte	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+.byte	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+.byte	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+.byte	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+.byte	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+.byte	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+.byte	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+.byte	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+.byte	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+.byte	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+.byte	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aes-mips64.S b/crypto/aes/aes-mips64.S
new file mode 100644
index 0000000..de57787
--- /dev/null
+++ b/crypto/aes/aes-mips64.S
@@ -0,0 +1,1340 @@
+.text
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+.set	noat
+.align	5
+.ent	_mips_AES_encrypt
+_mips_AES_encrypt:
+	.frame	$29,0,$31
+	.set	reorder
+	lw	$12,0($6)
+	lw	$13,4($6)
+	lw	$14,8($6)
+	lw	$15,12($6)
+	lw	$30,240($6)
+	dadd $3,$6,16
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	sub	$30,1
+	srl	$1,$9,6
+.Loop_enc:
+	srl	$2,$10,6
+	srl	$24,$11,6
+	srl	$25,$8,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$12,2($1)		# Te1[s1>>16]
+	lwl	$13,2($2)		# Te1[s2>>16]
+	lwl	$14,2($24)		# Te1[s3>>16]
+	lwl	$15,2($25)		# Te1[s0>>16]
+	lwr	$12,3($1)		# Te1[s1>>16]
+	lwr	$13,3($2)		# Te1[s2>>16]
+	lwr	$14,3($24)		# Te1[s3>>16]
+	lwr	$15,3($25)		# Te1[s0>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$16,1($1)		# Te2[s2>>8]
+	lwl	$17,1($2)		# Te2[s3>>8]
+	lwl	$18,1($24)		# Te2[s0>>8]
+	lwl	$19,1($25)		# Te2[s1>>8]
+	lwr	$16,2($1)		# Te2[s2>>8]
+	lwr	$17,2($2)		# Te2[s3>>8]
+	lwr	$18,2($24)		# Te2[s0>>8]
+	lwr	$19,2($25)		# Te2[s1>>8]
+
+	srl	$1,$11,22
+	srl	$2,$8,22
+	srl	$24,$9,22
+	srl	$25,$10,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$20,0($1)		# Te3[s3]
+	lwl	$21,0($2)		# Te3[s0]
+	lwl	$22,0($24)		# Te3[s1]
+	lwl	$23,0($25)		# Te3[s2]
+	lwr	$20,1($1)		# Te3[s3]
+	lwr	$21,1($2)		# Te3[s0]
+	lwr	$22,1($24)		# Te3[s1]
+	lwr	$23,1($25)		# Te3[s2]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+	lw	$16,0($1)		# Te0[s0>>24]
+	lw	$17,0($2)		# Te0[s1>>24]
+	lw	$18,0($24)		# Te0[s2>>24]
+	lw	$19,0($25)		# Te0[s3>>24]
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	sub	$30,1
+	dadd $3,16
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+	.set	noreorder
+	bnez	$30,.Loop_enc
+	srl	$1,$9,6
+
+	.set	reorder
+	srl	$2,$10,6
+	srl	$24,$11,6
+	srl	$25,$8,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$12,2($1)		# Te4[s1>>16]
+	lbu	$13,2($2)		# Te4[s2>>16]
+	lbu	$14,2($24)		# Te4[s3>>16]
+	lbu	$15,2($25)		# Te4[s0>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$16,2($1)		# Te4[s2>>8]
+	lbu	$17,2($2)		# Te4[s3>>8]
+	lbu	$18,2($24)		# Te4[s0>>8]
+	lbu	$19,2($25)		# Te4[s1>>8]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$20,2($1)		# Te4[s0>>24]
+	lbu	$21,2($2)		# Te4[s1>>24]
+	lbu	$22,2($24)		# Te4[s2>>24]
+	lbu	$23,2($25)		# Te4[s3>>24]
+
+	srl	$1,$11,22
+	srl	$2,$8,22
+	srl	$24,$9,22
+	srl	$25,$10,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+
+	sll	$12,$12,8
+	sll	$13,$13,8
+	sll	$14,$14,8
+	sll	$15,$15,8
+
+	sll	$16,$16,16
+	sll	$17,$17,16
+	sll	$18,$18,16
+	sll	$19,$19,16
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$16,2($1)		# Te4[s3]
+	lbu	$17,2($2)		# Te4[s0]
+	lbu	$18,2($24)		# Te4[s1]
+	lbu	$19,2($25)		# Te4[s2]
+
+	#sll	$20,$20,0
+	#sll	$21,$21,0
+	#sll	$22,$22,0
+	#sll	$23,$23,0
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	sll	$16,$16,24
+	sll	$17,$17,24
+	sll	$18,$18,24
+	sll	$19,$19,24
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	jr	$31
+.end	_mips_AES_encrypt
+
+.align	5
+.globl	AES_encrypt
+.ent	AES_encrypt
+AES_encrypt:
+	.frame	$29,128,$31
+	.mask	3237937152,-8
+	.set	noreorder
+	dsub $29,128
+	sd	$31,128-1*8($29)
+	sd	$30,128-2*8($29)
+	sd	$23,128-3*8($29)
+	sd	$22,128-4*8($29)
+	sd	$21,128-5*8($29)
+	sd	$20,128-6*8($29)
+	sd	$19,128-7*8($29)
+	sd	$18,128-8*8($29)
+	sd	$17,128-9*8($29)
+	sd	$16,128-10*8($29)
+	.cplocal	$7
+	.cpsetup	$25,$0,AES_encrypt
+	.set	reorder
+	dla	$7,AES_Te		# PIC-ified 'load address'
+
+	lwl	$8,0+3($4)
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+
+	bal	_mips_AES_encrypt
+
+	swr	$8,0+0($5)
+	swr	$9,4+0($5)
+	swr	$10,8+0($5)
+	swr	$11,12+0($5)
+	swl	$8,0+3($5)
+	swl	$9,4+3($5)
+	swl	$10,8+3($5)
+	swl	$11,12+3($5)
+
+	.set	noreorder
+	ld	$31,128-1*8($29)
+	ld	$30,128-2*8($29)
+	ld	$23,128-3*8($29)
+	ld	$22,128-4*8($29)
+	ld	$21,128-5*8($29)
+	ld	$20,128-6*8($29)
+	ld	$19,128-7*8($29)
+	ld	$18,128-8*8($29)
+	ld	$17,128-9*8($29)
+	ld	$16,128-10*8($29)
+	jr	$31
+	dadd $29,128
+.end	AES_encrypt
+.align	5
+.ent	_mips_AES_decrypt
+_mips_AES_decrypt:
+	.frame	$29,0,$31
+	.set	reorder
+	lw	$12,0($6)
+	lw	$13,4($6)
+	lw	$14,8($6)
+	lw	$15,12($6)
+	lw	$30,240($6)
+	dadd $3,$6,16
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	sub	$30,1
+	srl	$1,$11,6
+.Loop_dec:
+	srl	$2,$8,6
+	srl	$24,$9,6
+	srl	$25,$10,6
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$12,2($1)		# Td1[s3>>16]
+	lwl	$13,2($2)		# Td1[s0>>16]
+	lwl	$14,2($24)		# Td1[s1>>16]
+	lwl	$15,2($25)		# Td1[s2>>16]
+	lwr	$12,3($1)		# Td1[s3>>16]
+	lwr	$13,3($2)		# Td1[s0>>16]
+	lwr	$14,3($24)		# Td1[s1>>16]
+	lwr	$15,3($25)		# Td1[s2>>16]
+
+	srl	$1,$10,14
+	srl	$2,$11,14
+	srl	$24,$8,14
+	srl	$25,$9,14
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$16,1($1)		# Td2[s2>>8]
+	lwl	$17,1($2)		# Td2[s3>>8]
+	lwl	$18,1($24)		# Td2[s0>>8]
+	lwl	$19,1($25)		# Td2[s1>>8]
+	lwr	$16,2($1)		# Td2[s2>>8]
+	lwr	$17,2($2)		# Td2[s3>>8]
+	lwr	$18,2($24)		# Td2[s0>>8]
+	lwr	$19,2($25)		# Td2[s1>>8]
+
+	srl	$1,$9,22
+	srl	$2,$10,22
+	srl	$24,$11,22
+	srl	$25,$8,22
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lwl	$20,0($1)		# Td3[s1]
+	lwl	$21,0($2)		# Td3[s2]
+	lwl	$22,0($24)		# Td3[s3]
+	lwl	$23,0($25)		# Td3[s0]
+	lwr	$20,1($1)		# Td3[s1]
+	lwr	$21,1($2)		# Td3[s2]
+	lwr	$22,1($24)		# Td3[s3]
+	lwr	$23,1($25)		# Td3[s0]
+
+	sll	$1,$8,2
+	sll	$2,$9,2
+	sll	$24,$10,2
+	sll	$25,$11,2
+	and	$1,0x3fc
+	and	$2,0x3fc
+	and	$24,0x3fc
+	and	$25,0x3fc
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+
+	lw	$16,0($1)		# Td0[s0>>24]
+	lw	$17,0($2)		# Td0[s1>>24]
+	lw	$18,0($24)		# Td0[s2>>24]
+	lw	$19,0($25)		# Td0[s3>>24]
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	sub	$30,1
+	dadd $3,16
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+	.set	noreorder
+	bnez	$30,.Loop_dec
+	srl	$1,$11,6
+
+	.set	reorder
+	lw	$16,1024($7)		# prefetch Td4
+	lw	$17,1024+32($7)
+	lw	$18,1024+64($7)
+	lw	$19,1024+96($7)
+	lw	$20,1024+128($7)
+	lw	$21,1024+160($7)
+	lw	$22,1024+192($7)
+	lw	$23,1024+224($7)
+
+	srl	$1,$11,8
+	srl	$2,$8,8
+	srl	$24,$9,8
+	srl	$25,$10,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,0xff
+	and	$25,0xff
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$12,1024($1)		# Td4[s3>>16]
+	lbu	$13,1024($2)		# Td4[s0>>16]
+	lbu	$14,1024($24)		# Td4[s1>>16]
+	lbu	$15,1024($25)		# Td4[s2>>16]
+
+	srl	$1,$10,16
+	srl	$2,$11,16
+	srl	$24,$8,16
+	srl	$25,$9,16
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,0xff
+	and	$25,0xff
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$16,1024($1)		# Td4[s2>>8]
+	lbu	$17,1024($2)		# Td4[s3>>8]
+	lbu	$18,1024($24)		# Td4[s0>>8]
+	lbu	$19,1024($25)		# Td4[s1>>8]
+
+	and	$1,$8,0xff
+	and	$2,$9,0xff
+	and	$24,$10,0xff
+	and	$25,$11,0xff
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$20,1024($1)		# Td4[s0>>24]
+	lbu	$21,1024($2)		# Td4[s1>>24]
+	lbu	$22,1024($24)		# Td4[s2>>24]
+	lbu	$23,1024($25)		# Td4[s3>>24]
+
+	srl	$1,$9,24
+	srl	$2,$10,24
+	srl	$24,$11,24
+	srl	$25,$8,24
+
+	sll	$12,$12,8
+	sll	$13,$13,8
+	sll	$14,$14,8
+	sll	$15,$15,8
+
+	sll	$16,$16,16
+	sll	$17,$17,16
+	sll	$18,$18,16
+	sll	$19,$19,16
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$16,1024($1)		# Td4[s1]
+	lbu	$17,1024($2)		# Td4[s2]
+	lbu	$18,1024($24)		# Td4[s3]
+	lbu	$19,1024($25)		# Td4[s0]
+
+	#sll	$20,$20,0
+	#sll	$21,$21,0
+	#sll	$22,$22,0
+	#sll	$23,$23,0
+
+	lw	$8,0($3)
+	lw	$9,4($3)
+	lw	$10,8($3)
+	lw	$11,12($3)
+
+	sll	$16,$16,24
+	sll	$17,$17,24
+	sll	$18,$18,24
+	sll	$19,$19,24
+
+
+	xor	$12,$20
+	xor	$13,$21
+	xor	$14,$22
+	xor	$15,$23
+
+	xor	$12,$16
+	xor	$13,$17
+	xor	$14,$18
+	xor	$15,$19
+
+	xor	$8,$12
+	xor	$9,$13
+	xor	$10,$14
+	xor	$11,$15
+
+	jr	$31
+.end	_mips_AES_decrypt
+
+.align	5
+.globl	AES_decrypt
+.ent	AES_decrypt
+AES_decrypt:
+	.frame	$29,128,$31
+	.mask	3237937152,-8
+	.set	noreorder
+	dsub $29,128
+	sd	$31,128-1*8($29)
+	sd	$30,128-2*8($29)
+	sd	$23,128-3*8($29)
+	sd	$22,128-4*8($29)
+	sd	$21,128-5*8($29)
+	sd	$20,128-6*8($29)
+	sd	$19,128-7*8($29)
+	sd	$18,128-8*8($29)
+	sd	$17,128-9*8($29)
+	sd	$16,128-10*8($29)
+	.cplocal	$7
+	.cpsetup	$25,$0,AES_decrypt
+	.set	reorder
+	dla	$7,AES_Td		# PIC-ified 'load address'
+
+	lwl	$8,0+3($4)
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+
+	bal	_mips_AES_decrypt
+
+	swr	$8,0+0($5)
+	swr	$9,4+0($5)
+	swr	$10,8+0($5)
+	swr	$11,12+0($5)
+	swl	$8,0+3($5)
+	swl	$9,4+3($5)
+	swl	$10,8+3($5)
+	swl	$11,12+3($5)
+
+	.set	noreorder
+	ld	$31,128-1*8($29)
+	ld	$30,128-2*8($29)
+	ld	$23,128-3*8($29)
+	ld	$22,128-4*8($29)
+	ld	$21,128-5*8($29)
+	ld	$20,128-6*8($29)
+	ld	$19,128-7*8($29)
+	ld	$18,128-8*8($29)
+	ld	$17,128-9*8($29)
+	ld	$16,128-10*8($29)
+	jr	$31
+	dadd $29,128
+.end	AES_decrypt
+.align	5
+.ent	_mips_AES_set_encrypt_key
+_mips_AES_set_encrypt_key:
+	.frame	$29,0,$31
+	.set	noreorder
+	beqz	$4,.Lekey_done
+	li	$2,-1
+	beqz	$6,.Lekey_done
+	dadd $3,$7,1024+256
+
+	.set	reorder
+	lwl	$8,0+3($4)	# load 128 bits
+	lwl	$9,4+3($4)
+	lwl	$10,8+3($4)
+	lwl	$11,12+3($4)
+	li	$1,128
+	lwr	$8,0+0($4)
+	lwr	$9,4+0($4)
+	lwr	$10,8+0($4)
+	lwr	$11,12+0($4)
+	.set	noreorder
+	beq	$5,$1,.L128bits
+	li	$30,10
+
+	.set	reorder
+	lwl	$12,16+3($4)	# load 192 bits
+	lwl	$13,20+3($4)
+	li	$1,192
+	lwr	$12,16+0($4)
+	lwr	$13,20+0($4)
+	.set	noreorder
+	beq	$5,$1,.L192bits
+	li	$30,8
+
+	.set	reorder
+	lwl	$14,24+3($4)	# load 256 bits
+	lwl	$15,28+3($4)
+	li	$1,256
+	lwr	$14,24+0($4)
+	lwr	$15,28+0($4)
+	.set	noreorder
+	beq	$5,$1,.L256bits
+	li	$30,7
+
+	b	.Lekey_done
+	li	$2,-2
+
+.align	4
+.L128bits:
+	.set	reorder
+	srl	$1,$11,16
+	srl	$2,$11,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$11,0xff
+	srl	$25,$11,24
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sub	$30,1
+	dadd $6,16
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+
+	.set	noreorder
+	bnez	$30,.L128bits
+	dadd $3,4
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	li	$30,10
+	sw	$11,12($6)
+	li	$2,0
+	sw	$30,80($6)
+	b	.Lekey_done
+	dsub $6,10*16
+
+.align	4
+.L192bits:
+	.set	reorder
+	srl	$1,$13,16
+	srl	$2,$13,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$13,0xff
+	srl	$25,$13,24
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sw	$12,16($6)
+	sw	$13,20($6)
+	sub	$30,1
+	dadd $6,24
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+	xor	$12,$11
+	xor	$13,$12
+
+	.set	noreorder
+	bnez	$30,.L192bits
+	dadd $3,4
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	li	$30,12
+	sw	$11,12($6)
+	li	$2,0
+	sw	$30,48($6)
+	b	.Lekey_done
+	dsub $6,12*16
+
+.align	4
+.L256bits:
+	.set	reorder
+	srl	$1,$15,16
+	srl	$2,$15,8
+	and	$1,0xff
+	and	$2,0xff
+	and	$24,$15,0xff
+	srl	$25,$15,24
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+
+	sw	$8,0($6)
+	sw	$9,4($6)
+	sw	$10,8($6)
+	sw	$11,12($6)
+	sw	$12,16($6)
+	sw	$13,20($6)
+	sw	$14,24($6)
+	sw	$15,28($6)
+	sub	$30,1
+
+	sll	$1,$1,8
+	#sll	$2,$2,0
+	sll	$24,$24,24
+	sll	$25,$25,16
+
+	xor	$8,$1
+	lw	$1,0($3)
+	xor	$8,$2
+	xor	$8,$24
+	xor	$8,$25
+	xor	$8,$1
+
+	xor	$9,$8
+	xor	$10,$9
+	xor	$11,$10
+	beqz	$30,.L256bits_done
+
+	srl	$1,$11,24
+	srl	$2,$11,16
+	srl	$24,$11,8
+	and	$25,$11,0xff
+	and	$2,0xff
+	and	$24,0xff
+	dadd $1,$7
+	dadd $2,$7
+	dadd $24,$7
+	dadd $25,$7
+	lbu	$1,1024($1)
+	lbu	$2,1024($2)
+	lbu	$24,1024($24)
+	lbu	$25,1024($25)
+	sll	$1,24
+	sll	$2,16
+	sll	$24,8
+
+	xor	$12,$1
+	xor	$12,$2
+	xor	$12,$24
+	xor	$12,$25
+
+	xor	$13,$12
+	xor	$14,$13
+	xor	$15,$14
+
+	dadd $6,32
+	.set	noreorder
+	b	.L256bits
+	dadd $3,4
+
+.L256bits_done:
+	sw	$8,32($6)
+	sw	$9,36($6)
+	sw	$10,40($6)
+	li	$30,14
+	sw	$11,44($6)
+	li	$2,0
+	sw	$30,48($6)
+	dsub $6,12*16
+
+.Lekey_done:
+	jr	$31
+	nop
+.end	_mips_AES_set_encrypt_key
+
+.globl	AES_set_encrypt_key
+.ent	AES_set_encrypt_key
+AES_set_encrypt_key:
+	.frame	$29,64,$31
+	.mask	3221225472,-8
+	.set	noreorder
+	dsub $29,64
+	sd	$31,64-1*8($29)
+	sd	$30,64-2*8($29)
+	.cplocal	$7
+	.cpsetup	$25,$0,AES_set_encrypt_key
+	.set	reorder
+	dla	$7,AES_Te		# PIC-ified 'load address'
+
+	bal	_mips_AES_set_encrypt_key
+
+	.set	noreorder
+	move	$4,$2
+	ld	$31,64-1*8($29)
+	ld	$30,64-2*8($29)
+	jr	$31
+	dadd $29,64
+.end	AES_set_encrypt_key
+.align	5
+.globl	AES_set_decrypt_key
+.ent	AES_set_decrypt_key
+AES_set_decrypt_key:
+	.frame	$29,64,$31
+	.mask	3221225472,-8
+	.set	noreorder
+	dsub $29,64
+	sd	$31,64-1*8($29)
+	sd	$30,64-2*8($29)
+	.cplocal	$7
+	.cpsetup	$25,$0,AES_set_decrypt_key
+	.set	reorder
+	dla	$7,AES_Te		# PIC-ified 'load address'
+
+	bal	_mips_AES_set_encrypt_key
+
+	bltz	$2,.Ldkey_done
+
+	sll	$1,$30,4
+	dadd $4,$6,0
+	dadd $5,$6,$1
+.align	4
+.Lswap:
+	lw	$8,0($4)
+	lw	$9,4($4)
+	lw	$10,8($4)
+	lw	$11,12($4)
+	lw	$12,0($5)
+	lw	$13,4($5)
+	lw	$14,8($5)
+	lw	$15,12($5)
+	sw	$8,0($5)
+	sw	$9,4($5)
+	sw	$10,8($5)
+	sw	$11,12($5)
+	dadd $4,16
+	dsub $5,16
+	sw	$12,-16($4)
+	sw	$13,-12($4)
+	sw	$14,-8($4)
+	sw	$15,-4($4)
+	bne	$4,$5,.Lswap
+
+	lw	$8,16($6)		# modulo-scheduled
+	lui	$2,0x8080
+	sub	$30,1
+	or	$2,0x8080
+	sll	$30,2
+	dadd $6,16
+	lui	$25,0x1b1b
+	nor	$24,$0,$2
+	or	$25,0x1b1b
+.align	4
+.Lmix:
+	and	$1,$8,$2
+	and	$9,$8,$24
+	srl	$10,$1,7
+	addu	$9,$9		# tp2<<1
+	subu	$1,$10
+	and	$1,$25
+	xor	$9,$1
+
+	and	$1,$9,$2
+	and	$10,$9,$24
+	srl	$11,$1,7
+	addu	$10,$10		# tp4<<1
+	subu	$1,$11
+	and	$1,$25
+	xor	$10,$1
+
+	and	$1,$10,$2
+	and	$11,$10,$24
+	srl	$12,$1,7
+	addu	$11,$11		# tp8<<1
+	subu	$1,$12
+	and	$1,$25
+	xor	$11,$1
+
+	xor	$12,$11,$8
+	xor	$15,$11,$10
+	xor	$13,$12,$9
+	xor	$14,$12,$10
+
+	sll	$8,$14,16
+	 xor	$15,$9
+	srl	$9,$14,16
+	xor	$15,$8
+	sll	$8,$12,8
+	xor	$15,$9
+	srl	$9,$12,24
+	xor	$15,$8
+	sll	$8,$13,24
+	xor	$15,$9
+	srl	$9,$13,8
+	xor	$15,$8
+	lw	$8,4($6)		# modulo-scheduled
+	xor	$15,$9
+	sub	$30,1
+	sw	$15,0($6)
+	dadd $6,4
+	bnez	$30,.Lmix
+
+	li	$2,0
+.Ldkey_done:
+	.set	noreorder
+	move	$4,$2
+	ld	$31,64-1*8($29)
+	ld	$30,64-2*8($29)
+	jr	$31
+	dadd $29,64
+.end	AES_set_decrypt_key
+.rdata
+.align	6
+AES_Te:
+.byte	0xc6,0x63,0x63,0xa5,	0xf8,0x7c,0x7c,0x84	# Te0
+.byte	0xee,0x77,0x77,0x99,	0xf6,0x7b,0x7b,0x8d
+.byte	0xff,0xf2,0xf2,0x0d,	0xd6,0x6b,0x6b,0xbd
+.byte	0xde,0x6f,0x6f,0xb1,	0x91,0xc5,0xc5,0x54
+.byte	0x60,0x30,0x30,0x50,	0x02,0x01,0x01,0x03
+.byte	0xce,0x67,0x67,0xa9,	0x56,0x2b,0x2b,0x7d
+.byte	0xe7,0xfe,0xfe,0x19,	0xb5,0xd7,0xd7,0x62
+.byte	0x4d,0xab,0xab,0xe6,	0xec,0x76,0x76,0x9a
+.byte	0x8f,0xca,0xca,0x45,	0x1f,0x82,0x82,0x9d
+.byte	0x89,0xc9,0xc9,0x40,	0xfa,0x7d,0x7d,0x87
+.byte	0xef,0xfa,0xfa,0x15,	0xb2,0x59,0x59,0xeb
+.byte	0x8e,0x47,0x47,0xc9,	0xfb,0xf0,0xf0,0x0b
+.byte	0x41,0xad,0xad,0xec,	0xb3,0xd4,0xd4,0x67
+.byte	0x5f,0xa2,0xa2,0xfd,	0x45,0xaf,0xaf,0xea
+.byte	0x23,0x9c,0x9c,0xbf,	0x53,0xa4,0xa4,0xf7
+.byte	0xe4,0x72,0x72,0x96,	0x9b,0xc0,0xc0,0x5b
+.byte	0x75,0xb7,0xb7,0xc2,	0xe1,0xfd,0xfd,0x1c
+.byte	0x3d,0x93,0x93,0xae,	0x4c,0x26,0x26,0x6a
+.byte	0x6c,0x36,0x36,0x5a,	0x7e,0x3f,0x3f,0x41
+.byte	0xf5,0xf7,0xf7,0x02,	0x83,0xcc,0xcc,0x4f
+.byte	0x68,0x34,0x34,0x5c,	0x51,0xa5,0xa5,0xf4
+.byte	0xd1,0xe5,0xe5,0x34,	0xf9,0xf1,0xf1,0x08
+.byte	0xe2,0x71,0x71,0x93,	0xab,0xd8,0xd8,0x73
+.byte	0x62,0x31,0x31,0x53,	0x2a,0x15,0x15,0x3f
+.byte	0x08,0x04,0x04,0x0c,	0x95,0xc7,0xc7,0x52
+.byte	0x46,0x23,0x23,0x65,	0x9d,0xc3,0xc3,0x5e
+.byte	0x30,0x18,0x18,0x28,	0x37,0x96,0x96,0xa1
+.byte	0x0a,0x05,0x05,0x0f,	0x2f,0x9a,0x9a,0xb5
+.byte	0x0e,0x07,0x07,0x09,	0x24,0x12,0x12,0x36
+.byte	0x1b,0x80,0x80,0x9b,	0xdf,0xe2,0xe2,0x3d
+.byte	0xcd,0xeb,0xeb,0x26,	0x4e,0x27,0x27,0x69
+.byte	0x7f,0xb2,0xb2,0xcd,	0xea,0x75,0x75,0x9f
+.byte	0x12,0x09,0x09,0x1b,	0x1d,0x83,0x83,0x9e
+.byte	0x58,0x2c,0x2c,0x74,	0x34,0x1a,0x1a,0x2e
+.byte	0x36,0x1b,0x1b,0x2d,	0xdc,0x6e,0x6e,0xb2
+.byte	0xb4,0x5a,0x5a,0xee,	0x5b,0xa0,0xa0,0xfb
+.byte	0xa4,0x52,0x52,0xf6,	0x76,0x3b,0x3b,0x4d
+.byte	0xb7,0xd6,0xd6,0x61,	0x7d,0xb3,0xb3,0xce
+.byte	0x52,0x29,0x29,0x7b,	0xdd,0xe3,0xe3,0x3e
+.byte	0x5e,0x2f,0x2f,0x71,	0x13,0x84,0x84,0x97
+.byte	0xa6,0x53,0x53,0xf5,	0xb9,0xd1,0xd1,0x68
+.byte	0x00,0x00,0x00,0x00,	0xc1,0xed,0xed,0x2c
+.byte	0x40,0x20,0x20,0x60,	0xe3,0xfc,0xfc,0x1f
+.byte	0x79,0xb1,0xb1,0xc8,	0xb6,0x5b,0x5b,0xed
+.byte	0xd4,0x6a,0x6a,0xbe,	0x8d,0xcb,0xcb,0x46
+.byte	0x67,0xbe,0xbe,0xd9,	0x72,0x39,0x39,0x4b
+.byte	0x94,0x4a,0x4a,0xde,	0x98,0x4c,0x4c,0xd4
+.byte	0xb0,0x58,0x58,0xe8,	0x85,0xcf,0xcf,0x4a
+.byte	0xbb,0xd0,0xd0,0x6b,	0xc5,0xef,0xef,0x2a
+.byte	0x4f,0xaa,0xaa,0xe5,	0xed,0xfb,0xfb,0x16
+.byte	0x86,0x43,0x43,0xc5,	0x9a,0x4d,0x4d,0xd7
+.byte	0x66,0x33,0x33,0x55,	0x11,0x85,0x85,0x94
+.byte	0x8a,0x45,0x45,0xcf,	0xe9,0xf9,0xf9,0x10
+.byte	0x04,0x02,0x02,0x06,	0xfe,0x7f,0x7f,0x81
+.byte	0xa0,0x50,0x50,0xf0,	0x78,0x3c,0x3c,0x44
+.byte	0x25,0x9f,0x9f,0xba,	0x4b,0xa8,0xa8,0xe3
+.byte	0xa2,0x51,0x51,0xf3,	0x5d,0xa3,0xa3,0xfe
+.byte	0x80,0x40,0x40,0xc0,	0x05,0x8f,0x8f,0x8a
+.byte	0x3f,0x92,0x92,0xad,	0x21,0x9d,0x9d,0xbc
+.byte	0x70,0x38,0x38,0x48,	0xf1,0xf5,0xf5,0x04
+.byte	0x63,0xbc,0xbc,0xdf,	0x77,0xb6,0xb6,0xc1
+.byte	0xaf,0xda,0xda,0x75,	0x42,0x21,0x21,0x63
+.byte	0x20,0x10,0x10,0x30,	0xe5,0xff,0xff,0x1a
+.byte	0xfd,0xf3,0xf3,0x0e,	0xbf,0xd2,0xd2,0x6d
+.byte	0x81,0xcd,0xcd,0x4c,	0x18,0x0c,0x0c,0x14
+.byte	0x26,0x13,0x13,0x35,	0xc3,0xec,0xec,0x2f
+.byte	0xbe,0x5f,0x5f,0xe1,	0x35,0x97,0x97,0xa2
+.byte	0x88,0x44,0x44,0xcc,	0x2e,0x17,0x17,0x39
+.byte	0x93,0xc4,0xc4,0x57,	0x55,0xa7,0xa7,0xf2
+.byte	0xfc,0x7e,0x7e,0x82,	0x7a,0x3d,0x3d,0x47
+.byte	0xc8,0x64,0x64,0xac,	0xba,0x5d,0x5d,0xe7
+.byte	0x32,0x19,0x19,0x2b,	0xe6,0x73,0x73,0x95
+.byte	0xc0,0x60,0x60,0xa0,	0x19,0x81,0x81,0x98
+.byte	0x9e,0x4f,0x4f,0xd1,	0xa3,0xdc,0xdc,0x7f
+.byte	0x44,0x22,0x22,0x66,	0x54,0x2a,0x2a,0x7e
+.byte	0x3b,0x90,0x90,0xab,	0x0b,0x88,0x88,0x83
+.byte	0x8c,0x46,0x46,0xca,	0xc7,0xee,0xee,0x29
+.byte	0x6b,0xb8,0xb8,0xd3,	0x28,0x14,0x14,0x3c
+.byte	0xa7,0xde,0xde,0x79,	0xbc,0x5e,0x5e,0xe2
+.byte	0x16,0x0b,0x0b,0x1d,	0xad,0xdb,0xdb,0x76
+.byte	0xdb,0xe0,0xe0,0x3b,	0x64,0x32,0x32,0x56
+.byte	0x74,0x3a,0x3a,0x4e,	0x14,0x0a,0x0a,0x1e
+.byte	0x92,0x49,0x49,0xdb,	0x0c,0x06,0x06,0x0a
+.byte	0x48,0x24,0x24,0x6c,	0xb8,0x5c,0x5c,0xe4
+.byte	0x9f,0xc2,0xc2,0x5d,	0xbd,0xd3,0xd3,0x6e
+.byte	0x43,0xac,0xac,0xef,	0xc4,0x62,0x62,0xa6
+.byte	0x39,0x91,0x91,0xa8,	0x31,0x95,0x95,0xa4
+.byte	0xd3,0xe4,0xe4,0x37,	0xf2,0x79,0x79,0x8b
+.byte	0xd5,0xe7,0xe7,0x32,	0x8b,0xc8,0xc8,0x43
+.byte	0x6e,0x37,0x37,0x59,	0xda,0x6d,0x6d,0xb7
+.byte	0x01,0x8d,0x8d,0x8c,	0xb1,0xd5,0xd5,0x64
+.byte	0x9c,0x4e,0x4e,0xd2,	0x49,0xa9,0xa9,0xe0
+.byte	0xd8,0x6c,0x6c,0xb4,	0xac,0x56,0x56,0xfa
+.byte	0xf3,0xf4,0xf4,0x07,	0xcf,0xea,0xea,0x25
+.byte	0xca,0x65,0x65,0xaf,	0xf4,0x7a,0x7a,0x8e
+.byte	0x47,0xae,0xae,0xe9,	0x10,0x08,0x08,0x18
+.byte	0x6f,0xba,0xba,0xd5,	0xf0,0x78,0x78,0x88
+.byte	0x4a,0x25,0x25,0x6f,	0x5c,0x2e,0x2e,0x72
+.byte	0x38,0x1c,0x1c,0x24,	0x57,0xa6,0xa6,0xf1
+.byte	0x73,0xb4,0xb4,0xc7,	0x97,0xc6,0xc6,0x51
+.byte	0xcb,0xe8,0xe8,0x23,	0xa1,0xdd,0xdd,0x7c
+.byte	0xe8,0x74,0x74,0x9c,	0x3e,0x1f,0x1f,0x21
+.byte	0x96,0x4b,0x4b,0xdd,	0x61,0xbd,0xbd,0xdc
+.byte	0x0d,0x8b,0x8b,0x86,	0x0f,0x8a,0x8a,0x85
+.byte	0xe0,0x70,0x70,0x90,	0x7c,0x3e,0x3e,0x42
+.byte	0x71,0xb5,0xb5,0xc4,	0xcc,0x66,0x66,0xaa
+.byte	0x90,0x48,0x48,0xd8,	0x06,0x03,0x03,0x05
+.byte	0xf7,0xf6,0xf6,0x01,	0x1c,0x0e,0x0e,0x12
+.byte	0xc2,0x61,0x61,0xa3,	0x6a,0x35,0x35,0x5f
+.byte	0xae,0x57,0x57,0xf9,	0x69,0xb9,0xb9,0xd0
+.byte	0x17,0x86,0x86,0x91,	0x99,0xc1,0xc1,0x58
+.byte	0x3a,0x1d,0x1d,0x27,	0x27,0x9e,0x9e,0xb9
+.byte	0xd9,0xe1,0xe1,0x38,	0xeb,0xf8,0xf8,0x13
+.byte	0x2b,0x98,0x98,0xb3,	0x22,0x11,0x11,0x33
+.byte	0xd2,0x69,0x69,0xbb,	0xa9,0xd9,0xd9,0x70
+.byte	0x07,0x8e,0x8e,0x89,	0x33,0x94,0x94,0xa7
+.byte	0x2d,0x9b,0x9b,0xb6,	0x3c,0x1e,0x1e,0x22
+.byte	0x15,0x87,0x87,0x92,	0xc9,0xe9,0xe9,0x20
+.byte	0x87,0xce,0xce,0x49,	0xaa,0x55,0x55,0xff
+.byte	0x50,0x28,0x28,0x78,	0xa5,0xdf,0xdf,0x7a
+.byte	0x03,0x8c,0x8c,0x8f,	0x59,0xa1,0xa1,0xf8
+.byte	0x09,0x89,0x89,0x80,	0x1a,0x0d,0x0d,0x17
+.byte	0x65,0xbf,0xbf,0xda,	0xd7,0xe6,0xe6,0x31
+.byte	0x84,0x42,0x42,0xc6,	0xd0,0x68,0x68,0xb8
+.byte	0x82,0x41,0x41,0xc3,	0x29,0x99,0x99,0xb0
+.byte	0x5a,0x2d,0x2d,0x77,	0x1e,0x0f,0x0f,0x11
+.byte	0x7b,0xb0,0xb0,0xcb,	0xa8,0x54,0x54,0xfc
+.byte	0x6d,0xbb,0xbb,0xd6,	0x2c,0x16,0x16,0x3a
+
+.byte	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5	# Te4
+.byte	0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76
+.byte	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0
+.byte	0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0
+.byte	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc
+.byte	0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15
+.byte	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a
+.byte	0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75
+.byte	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0
+.byte	0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84
+.byte	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b
+.byte	0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf
+.byte	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85
+.byte	0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8
+.byte	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5
+.byte	0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2
+.byte	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17
+.byte	0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73
+.byte	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88
+.byte	0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb
+.byte	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c
+.byte	0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79
+.byte	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9
+.byte	0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08
+.byte	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6
+.byte	0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a
+.byte	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e
+.byte	0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e
+.byte	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94
+.byte	0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf
+.byte	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68
+.byte	0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+
+.byte	0x01,0x00,0x00,0x00,	0x02,0x00,0x00,0x00	# rcon
+.byte	0x04,0x00,0x00,0x00,	0x08,0x00,0x00,0x00
+.byte	0x10,0x00,0x00,0x00,	0x20,0x00,0x00,0x00
+.byte	0x40,0x00,0x00,0x00,	0x80,0x00,0x00,0x00
+.byte	0x1B,0x00,0x00,0x00,	0x36,0x00,0x00,0x00
+
+.align	6
+AES_Td:
+.byte	0x51,0xf4,0xa7,0x50,	0x7e,0x41,0x65,0x53	# Td0
+.byte	0x1a,0x17,0xa4,0xc3,	0x3a,0x27,0x5e,0x96
+.byte	0x3b,0xab,0x6b,0xcb,	0x1f,0x9d,0x45,0xf1
+.byte	0xac,0xfa,0x58,0xab,	0x4b,0xe3,0x03,0x93
+.byte	0x20,0x30,0xfa,0x55,	0xad,0x76,0x6d,0xf6
+.byte	0x88,0xcc,0x76,0x91,	0xf5,0x02,0x4c,0x25
+.byte	0x4f,0xe5,0xd7,0xfc,	0xc5,0x2a,0xcb,0xd7
+.byte	0x26,0x35,0x44,0x80,	0xb5,0x62,0xa3,0x8f
+.byte	0xde,0xb1,0x5a,0x49,	0x25,0xba,0x1b,0x67
+.byte	0x45,0xea,0x0e,0x98,	0x5d,0xfe,0xc0,0xe1
+.byte	0xc3,0x2f,0x75,0x02,	0x81,0x4c,0xf0,0x12
+.byte	0x8d,0x46,0x97,0xa3,	0x6b,0xd3,0xf9,0xc6
+.byte	0x03,0x8f,0x5f,0xe7,	0x15,0x92,0x9c,0x95
+.byte	0xbf,0x6d,0x7a,0xeb,	0x95,0x52,0x59,0xda
+.byte	0xd4,0xbe,0x83,0x2d,	0x58,0x74,0x21,0xd3
+.byte	0x49,0xe0,0x69,0x29,	0x8e,0xc9,0xc8,0x44
+.byte	0x75,0xc2,0x89,0x6a,	0xf4,0x8e,0x79,0x78
+.byte	0x99,0x58,0x3e,0x6b,	0x27,0xb9,0x71,0xdd
+.byte	0xbe,0xe1,0x4f,0xb6,	0xf0,0x88,0xad,0x17
+.byte	0xc9,0x20,0xac,0x66,	0x7d,0xce,0x3a,0xb4
+.byte	0x63,0xdf,0x4a,0x18,	0xe5,0x1a,0x31,0x82
+.byte	0x97,0x51,0x33,0x60,	0x62,0x53,0x7f,0x45
+.byte	0xb1,0x64,0x77,0xe0,	0xbb,0x6b,0xae,0x84
+.byte	0xfe,0x81,0xa0,0x1c,	0xf9,0x08,0x2b,0x94
+.byte	0x70,0x48,0x68,0x58,	0x8f,0x45,0xfd,0x19
+.byte	0x94,0xde,0x6c,0x87,	0x52,0x7b,0xf8,0xb7
+.byte	0xab,0x73,0xd3,0x23,	0x72,0x4b,0x02,0xe2
+.byte	0xe3,0x1f,0x8f,0x57,	0x66,0x55,0xab,0x2a
+.byte	0xb2,0xeb,0x28,0x07,	0x2f,0xb5,0xc2,0x03
+.byte	0x86,0xc5,0x7b,0x9a,	0xd3,0x37,0x08,0xa5
+.byte	0x30,0x28,0x87,0xf2,	0x23,0xbf,0xa5,0xb2
+.byte	0x02,0x03,0x6a,0xba,	0xed,0x16,0x82,0x5c
+.byte	0x8a,0xcf,0x1c,0x2b,	0xa7,0x79,0xb4,0x92
+.byte	0xf3,0x07,0xf2,0xf0,	0x4e,0x69,0xe2,0xa1
+.byte	0x65,0xda,0xf4,0xcd,	0x06,0x05,0xbe,0xd5
+.byte	0xd1,0x34,0x62,0x1f,	0xc4,0xa6,0xfe,0x8a
+.byte	0x34,0x2e,0x53,0x9d,	0xa2,0xf3,0x55,0xa0
+.byte	0x05,0x8a,0xe1,0x32,	0xa4,0xf6,0xeb,0x75
+.byte	0x0b,0x83,0xec,0x39,	0x40,0x60,0xef,0xaa
+.byte	0x5e,0x71,0x9f,0x06,	0xbd,0x6e,0x10,0x51
+.byte	0x3e,0x21,0x8a,0xf9,	0x96,0xdd,0x06,0x3d
+.byte	0xdd,0x3e,0x05,0xae,	0x4d,0xe6,0xbd,0x46
+.byte	0x91,0x54,0x8d,0xb5,	0x71,0xc4,0x5d,0x05
+.byte	0x04,0x06,0xd4,0x6f,	0x60,0x50,0x15,0xff
+.byte	0x19,0x98,0xfb,0x24,	0xd6,0xbd,0xe9,0x97
+.byte	0x89,0x40,0x43,0xcc,	0x67,0xd9,0x9e,0x77
+.byte	0xb0,0xe8,0x42,0xbd,	0x07,0x89,0x8b,0x88
+.byte	0xe7,0x19,0x5b,0x38,	0x79,0xc8,0xee,0xdb
+.byte	0xa1,0x7c,0x0a,0x47,	0x7c,0x42,0x0f,0xe9
+.byte	0xf8,0x84,0x1e,0xc9,	0x00,0x00,0x00,0x00
+.byte	0x09,0x80,0x86,0x83,	0x32,0x2b,0xed,0x48
+.byte	0x1e,0x11,0x70,0xac,	0x6c,0x5a,0x72,0x4e
+.byte	0xfd,0x0e,0xff,0xfb,	0x0f,0x85,0x38,0x56
+.byte	0x3d,0xae,0xd5,0x1e,	0x36,0x2d,0x39,0x27
+.byte	0x0a,0x0f,0xd9,0x64,	0x68,0x5c,0xa6,0x21
+.byte	0x9b,0x5b,0x54,0xd1,	0x24,0x36,0x2e,0x3a
+.byte	0x0c,0x0a,0x67,0xb1,	0x93,0x57,0xe7,0x0f
+.byte	0xb4,0xee,0x96,0xd2,	0x1b,0x9b,0x91,0x9e
+.byte	0x80,0xc0,0xc5,0x4f,	0x61,0xdc,0x20,0xa2
+.byte	0x5a,0x77,0x4b,0x69,	0x1c,0x12,0x1a,0x16
+.byte	0xe2,0x93,0xba,0x0a,	0xc0,0xa0,0x2a,0xe5
+.byte	0x3c,0x22,0xe0,0x43,	0x12,0x1b,0x17,0x1d
+.byte	0x0e,0x09,0x0d,0x0b,	0xf2,0x8b,0xc7,0xad
+.byte	0x2d,0xb6,0xa8,0xb9,	0x14,0x1e,0xa9,0xc8
+.byte	0x57,0xf1,0x19,0x85,	0xaf,0x75,0x07,0x4c
+.byte	0xee,0x99,0xdd,0xbb,	0xa3,0x7f,0x60,0xfd
+.byte	0xf7,0x01,0x26,0x9f,	0x5c,0x72,0xf5,0xbc
+.byte	0x44,0x66,0x3b,0xc5,	0x5b,0xfb,0x7e,0x34
+.byte	0x8b,0x43,0x29,0x76,	0xcb,0x23,0xc6,0xdc
+.byte	0xb6,0xed,0xfc,0x68,	0xb8,0xe4,0xf1,0x63
+.byte	0xd7,0x31,0xdc,0xca,	0x42,0x63,0x85,0x10
+.byte	0x13,0x97,0x22,0x40,	0x84,0xc6,0x11,0x20
+.byte	0x85,0x4a,0x24,0x7d,	0xd2,0xbb,0x3d,0xf8
+.byte	0xae,0xf9,0x32,0x11,	0xc7,0x29,0xa1,0x6d
+.byte	0x1d,0x9e,0x2f,0x4b,	0xdc,0xb2,0x30,0xf3
+.byte	0x0d,0x86,0x52,0xec,	0x77,0xc1,0xe3,0xd0
+.byte	0x2b,0xb3,0x16,0x6c,	0xa9,0x70,0xb9,0x99
+.byte	0x11,0x94,0x48,0xfa,	0x47,0xe9,0x64,0x22
+.byte	0xa8,0xfc,0x8c,0xc4,	0xa0,0xf0,0x3f,0x1a
+.byte	0x56,0x7d,0x2c,0xd8,	0x22,0x33,0x90,0xef
+.byte	0x87,0x49,0x4e,0xc7,	0xd9,0x38,0xd1,0xc1
+.byte	0x8c,0xca,0xa2,0xfe,	0x98,0xd4,0x0b,0x36
+.byte	0xa6,0xf5,0x81,0xcf,	0xa5,0x7a,0xde,0x28
+.byte	0xda,0xb7,0x8e,0x26,	0x3f,0xad,0xbf,0xa4
+.byte	0x2c,0x3a,0x9d,0xe4,	0x50,0x78,0x92,0x0d
+.byte	0x6a,0x5f,0xcc,0x9b,	0x54,0x7e,0x46,0x62
+.byte	0xf6,0x8d,0x13,0xc2,	0x90,0xd8,0xb8,0xe8
+.byte	0x2e,0x39,0xf7,0x5e,	0x82,0xc3,0xaf,0xf5
+.byte	0x9f,0x5d,0x80,0xbe,	0x69,0xd0,0x93,0x7c
+.byte	0x6f,0xd5,0x2d,0xa9,	0xcf,0x25,0x12,0xb3
+.byte	0xc8,0xac,0x99,0x3b,	0x10,0x18,0x7d,0xa7
+.byte	0xe8,0x9c,0x63,0x6e,	0xdb,0x3b,0xbb,0x7b
+.byte	0xcd,0x26,0x78,0x09,	0x6e,0x59,0x18,0xf4
+.byte	0xec,0x9a,0xb7,0x01,	0x83,0x4f,0x9a,0xa8
+.byte	0xe6,0x95,0x6e,0x65,	0xaa,0xff,0xe6,0x7e
+.byte	0x21,0xbc,0xcf,0x08,	0xef,0x15,0xe8,0xe6
+.byte	0xba,0xe7,0x9b,0xd9,	0x4a,0x6f,0x36,0xce
+.byte	0xea,0x9f,0x09,0xd4,	0x29,0xb0,0x7c,0xd6
+.byte	0x31,0xa4,0xb2,0xaf,	0x2a,0x3f,0x23,0x31
+.byte	0xc6,0xa5,0x94,0x30,	0x35,0xa2,0x66,0xc0
+.byte	0x74,0x4e,0xbc,0x37,	0xfc,0x82,0xca,0xa6
+.byte	0xe0,0x90,0xd0,0xb0,	0x33,0xa7,0xd8,0x15
+.byte	0xf1,0x04,0x98,0x4a,	0x41,0xec,0xda,0xf7
+.byte	0x7f,0xcd,0x50,0x0e,	0x17,0x91,0xf6,0x2f
+.byte	0x76,0x4d,0xd6,0x8d,	0x43,0xef,0xb0,0x4d
+.byte	0xcc,0xaa,0x4d,0x54,	0xe4,0x96,0x04,0xdf
+.byte	0x9e,0xd1,0xb5,0xe3,	0x4c,0x6a,0x88,0x1b
+.byte	0xc1,0x2c,0x1f,0xb8,	0x46,0x65,0x51,0x7f
+.byte	0x9d,0x5e,0xea,0x04,	0x01,0x8c,0x35,0x5d
+.byte	0xfa,0x87,0x74,0x73,	0xfb,0x0b,0x41,0x2e
+.byte	0xb3,0x67,0x1d,0x5a,	0x92,0xdb,0xd2,0x52
+.byte	0xe9,0x10,0x56,0x33,	0x6d,0xd6,0x47,0x13
+.byte	0x9a,0xd7,0x61,0x8c,	0x37,0xa1,0x0c,0x7a
+.byte	0x59,0xf8,0x14,0x8e,	0xeb,0x13,0x3c,0x89
+.byte	0xce,0xa9,0x27,0xee,	0xb7,0x61,0xc9,0x35
+.byte	0xe1,0x1c,0xe5,0xed,	0x7a,0x47,0xb1,0x3c
+.byte	0x9c,0xd2,0xdf,0x59,	0x55,0xf2,0x73,0x3f
+.byte	0x18,0x14,0xce,0x79,	0x73,0xc7,0x37,0xbf
+.byte	0x53,0xf7,0xcd,0xea,	0x5f,0xfd,0xaa,0x5b
+.byte	0xdf,0x3d,0x6f,0x14,	0x78,0x44,0xdb,0x86
+.byte	0xca,0xaf,0xf3,0x81,	0xb9,0x68,0xc4,0x3e
+.byte	0x38,0x24,0x34,0x2c,	0xc2,0xa3,0x40,0x5f
+.byte	0x16,0x1d,0xc3,0x72,	0xbc,0xe2,0x25,0x0c
+.byte	0x28,0x3c,0x49,0x8b,	0xff,0x0d,0x95,0x41
+.byte	0x39,0xa8,0x01,0x71,	0x08,0x0c,0xb3,0xde
+.byte	0xd8,0xb4,0xe4,0x9c,	0x64,0x56,0xc1,0x90
+.byte	0x7b,0xcb,0x84,0x61,	0xd5,0x32,0xb6,0x70
+.byte	0x48,0x6c,0x5c,0x74,	0xd0,0xb8,0x57,0x42
+
+.byte	0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38	# Td4
+.byte	0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
+.byte	0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87
+.byte	0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
+.byte	0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d
+.byte	0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
+.byte	0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2
+.byte	0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
+.byte	0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16
+.byte	0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
+.byte	0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda
+.byte	0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
+.byte	0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a
+.byte	0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
+.byte	0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02
+.byte	0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
+.byte	0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea
+.byte	0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
+.byte	0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85
+.byte	0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
+.byte	0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89
+.byte	0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
+.byte	0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20
+.byte	0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
+.byte	0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31
+.byte	0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
+.byte	0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d
+.byte	0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
+.byte	0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0
+.byte	0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
+.byte	0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26
+.byte	0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aes_cbc.c b/crypto/aes/aes_cbc.c
new file mode 100644
index 0000000..5e76f6e
--- /dev/null
+++ b/crypto/aes/aes_cbc.c
@@ -0,0 +1,65 @@
+/* $OpenBSD: aes_cbc.c,v 1.12 2014/06/12 15:49:27 deraadt Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+void
+AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const AES_KEY *key, unsigned char *ivec, const int enc)
+{
+	if (enc)
+		CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
+		    (block128_f)AES_encrypt);
+	else
+		CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
+		    (block128_f)AES_decrypt);
+}
diff --git a/crypto/aes/aes_cfb.c b/crypto/aes/aes_cfb.c
new file mode 100644
index 0000000..a6384f9
--- /dev/null
+++ b/crypto/aes/aes_cfb.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: aes_cfb.c,v 1.8 2014/06/12 15:49:27 deraadt Exp $ */
+/* ====================================================================
+ * Copyright (c) 2002-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+/* The input and output encrypted as though 128bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num;
+ */
+
+void
+AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const AES_KEY *key, unsigned char *ivec, int *num, const int enc)
+{
+	CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)AES_encrypt);
+}
+
+/* N.B. This expects the input to be packed, MS bit first */
+void
+AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const AES_KEY *key, unsigned char *ivec, int *num, const int enc)
+{
+	CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)AES_encrypt);
+}
+
+void
+AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const AES_KEY *key, unsigned char *ivec, int *num, const int enc)
+{
+	CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)AES_encrypt);
+}
+
diff --git a/crypto/aes/aes_core.c b/crypto/aes/aes_core.c
new file mode 100644
index 0000000..e3fdb4f
--- /dev/null
+++ b/crypto/aes/aes_core.c
@@ -0,0 +1,1374 @@
+/* $OpenBSD: aes_core.c,v 1.14 2022/11/26 16:08:50 tb Exp $ */
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen 
+ * @author Antoon Bosselaers 
+ * @author Paulo Barreto 
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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.
+ */
+
+/* Note: rewritten a little bit to provide error control and an OpenSSL-
+   compatible API */
+
+#ifndef AES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+#include 
+#include 
+#include "aes_local.h"
+
+#ifndef AES_ASM
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01];
+*/
+
+static const u32 Te0[256] = {
+	0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+	0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+	0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+	0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+	0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+	0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+	0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+	0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+	0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+	0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+	0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+	0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+	0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+	0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+	0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+	0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+	0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+	0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+	0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+	0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+	0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+	0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+	0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+	0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+	0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+	0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+	0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+	0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+	0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+	0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+	0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+	0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+	0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+	0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+	0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+	0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+	0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+	0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+	0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+	0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+	0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+	0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+	0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+	0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+	0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+	0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+	0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+	0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+	0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+	0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+	0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+	0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+	0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+	0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+	0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+	0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+	0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+	0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+	0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+	0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+	0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+	0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+	0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+	0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+	0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+	0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+	0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+	0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+	0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+	0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+	0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+	0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+	0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+	0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+	0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+	0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+	0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+	0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+	0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+	0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+	0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+	0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+	0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+	0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+	0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+	0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+	0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+	0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+	0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+	0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+	0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+	0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+	0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+	0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+	0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+	0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+	0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+	0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+	0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+	0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+	0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+	0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+	0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+	0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+	0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+	0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+	0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+	0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+	0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+	0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+	0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+	0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+	0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+	0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+	0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+	0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+	0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+	0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+	0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+	0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+	0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+	0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+	0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+	0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+	0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+	0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+	0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+	0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+	0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+	0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+	0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+	0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+	0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+	0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+	0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+	0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+	0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+	0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+	0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+	0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+	0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+	0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+	0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+	0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+	0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+	0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+	0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+	0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+	0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+	0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+	0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+	0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+	0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+	0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+	0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+	0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+	0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+	0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+	0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+	0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+	0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+	0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+	0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+	0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+	0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+	0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+	0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+	0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+	0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+	0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+	0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+	0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+	0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+	0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+	0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+	0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+	0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+	0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+	0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+	0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+	0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+	0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+	0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+	0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+	0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+	0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+	0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+	0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+	0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+	0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+	0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+	0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+	0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+	0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+	0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+	0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+	0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+	0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+	0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+	0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+	0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+	0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+	0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+	0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+	0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+	0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+	0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+	0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+	0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+	0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+	0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+	0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+	0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+	0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+	0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+	0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+	0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+	0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+	0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+	0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+	0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+	0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+	0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+	0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+	0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+	0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+	0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+	0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+	0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+	0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+	0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+	0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+	0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+	0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+	0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+	0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+	0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+	0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+	0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+	0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+	0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+	0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+	0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+	0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+	0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+	0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+	0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+	0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+	0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+	0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+	0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+	0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+	0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+	0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+	0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+	0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+static const u32 Td0[256] = {
+	0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+	0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+	0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+	0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+	0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+	0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+	0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+	0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+	0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+	0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+	0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+	0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+	0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+	0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+	0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+	0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+	0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+	0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+	0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+	0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+	0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+	0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+	0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+	0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+	0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+	0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+	0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+	0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+	0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+	0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+	0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+	0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+	0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+	0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+	0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+	0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+	0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+	0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+	0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+	0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+	0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+	0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+	0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+	0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+	0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+	0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+	0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+	0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+	0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+	0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+	0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+	0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+	0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+	0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+	0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+	0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+	0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+	0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+	0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+	0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+	0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+	0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+	0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+	0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+	0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+	0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+	0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+	0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+	0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+	0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+	0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+	0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+	0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+	0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+	0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+	0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+	0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+	0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+	0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+	0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+	0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+	0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+	0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+	0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+	0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+	0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+	0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+	0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+	0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+	0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+	0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+	0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+	0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+	0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+	0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+	0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+	0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+	0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+	0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+	0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+	0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+	0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+	0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+	0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+	0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+	0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+	0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+	0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+	0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+	0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+	0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+	0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+	0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+	0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+	0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+	0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+	0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+	0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+	0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+	0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+	0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+	0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+	0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+	0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+	0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+	0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+	0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+	0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+	0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+	0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+	0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+	0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+	0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+	0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+	0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+	0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+	0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+	0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+	0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+	0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+	0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+	0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+	0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+	0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+	0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+	0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+	0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+	0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+	0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+	0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+	0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+	0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+	0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+	0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+	0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+	0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+	0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+	0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+	0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+	0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+	0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+	0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+	0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+	0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+	0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+	0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+	0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+	0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+	0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+	0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+	0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+	0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+	0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+	0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+	0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+	0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+	0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+	0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+	0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+	0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+	0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+	0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+	0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+	0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+	0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+	0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+	0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+	0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+	0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+	0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+	0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+	0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+	0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+	0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+	0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+	0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+	0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+	0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+	0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+	0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+	0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+	0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+	0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+	0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+	0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+	0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+	0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+	0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+	0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+	0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+	0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+	0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+	0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+	0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+	0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+	0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+	0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+	0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+	0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+	0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+	0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+	0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+	0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+	0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+	0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+	0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+	0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+	0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+	0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+	0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+	0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+	0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+	0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+	0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+	0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+	0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+	0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+	0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+	0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+	0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+	0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+	0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+	0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+	0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+	0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+	0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+	0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+	0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+	0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+	0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+	0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+	0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+	0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+	0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+	0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+	0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u8 Td4[256] = {
+	0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+	0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+	0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+	0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+	0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+	0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+	0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+	0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+	0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+	0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+	0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+	0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+	0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+	0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+	0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+	0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+	0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+	0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+	0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+	0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+	0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+	0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+	0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+	0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+	0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+	0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+	0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+	0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+	0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+	0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+	0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+	0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+static const u32 rcon[] = {
+	0x01000000, 0x02000000, 0x04000000, 0x08000000,
+	0x10000000, 0x20000000, 0x40000000, 0x80000000,
+	0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ */
+int
+AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
+{
+	u32 *rk;
+	int i = 0;
+	u32 temp;
+
+	if (!userKey || !key)
+		return -1;
+	if (bits != 128 && bits != 192 && bits != 256)
+		return -2;
+
+	rk = key->rd_key;
+
+	if (bits == 128)
+		key->rounds = 10;
+	else if (bits == 192)
+		key->rounds = 12;
+	else
+		key->rounds = 14;
+
+	rk[0] = GETU32(userKey);
+	rk[1] = GETU32(userKey + 4);
+	rk[2] = GETU32(userKey + 8);
+	rk[3] = GETU32(userKey + 12);
+	if (bits == 128) {
+		while (1) {
+			temp = rk[3];
+			rk[4] = rk[0] ^
+			    (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+			    (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+			    (Te0[(temp) & 0xff] & 0x0000ff00) ^
+			    (Te1[(temp >> 24)] & 0x000000ff) ^
+			    rcon[i];
+			rk[5] = rk[1] ^ rk[4];
+			rk[6] = rk[2] ^ rk[5];
+			rk[7] = rk[3] ^ rk[6];
+			if (++i == 10) {
+				return 0;
+			}
+			rk += 4;
+		}
+	}
+	rk[4] = GETU32(userKey + 16);
+	rk[5] = GETU32(userKey + 20);
+	if (bits == 192) {
+		while (1) {
+			temp = rk[5];
+			rk[6] = rk[ 0] ^
+			    (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+			    (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+			    (Te0[(temp) & 0xff] & 0x0000ff00) ^
+			    (Te1[(temp >> 24)] & 0x000000ff) ^
+			    rcon[i];
+			rk[7] = rk[1] ^ rk[6];
+			rk[8] = rk[2] ^ rk[7];
+			rk[9] = rk[3] ^ rk[8];
+			if (++i == 8) {
+				return 0;
+			}
+			rk[10] = rk[4] ^ rk[9];
+			rk[11] = rk[5] ^ rk[10];
+			rk += 6;
+		}
+	}
+	rk[6] = GETU32(userKey + 24);
+	rk[7] = GETU32(userKey + 28);
+	if (bits == 256) {
+		while (1) {
+			temp = rk[7];
+			rk[8] = rk[0] ^
+			    (Te2[(temp >> 16) & 0xff] & 0xff000000) ^
+			    (Te3[(temp >> 8) & 0xff] & 0x00ff0000) ^
+			    (Te0[(temp) & 0xff] & 0x0000ff00) ^
+			    (Te1[(temp >> 24)] & 0x000000ff) ^
+			    rcon[i];
+			rk[9] = rk[1] ^ rk[8];
+			rk[10] = rk[2] ^ rk[9];
+			rk[11] = rk[3] ^ rk[10];
+			if (++i == 7) {
+				return 0;
+			}
+			temp = rk[11];
+			rk[12] = rk[4] ^
+			    (Te2[(temp >> 24)] & 0xff000000) ^
+			    (Te3[(temp >> 16) & 0xff] & 0x00ff0000) ^
+			    (Te0[(temp >> 8) & 0xff] & 0x0000ff00) ^
+			    (Te1[(temp) & 0xff] & 0x000000ff);
+			rk[13] = rk[5] ^ rk[12];
+			rk[14] = rk[6] ^ rk[13];
+			rk[15] = rk[7] ^ rk[14];
+
+			rk += 8;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ */
+int
+AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
+{
+	u32 *rk;
+	int i, j, status;
+	u32 temp;
+
+	/* first, start with an encryption schedule */
+	status = AES_set_encrypt_key(userKey, bits, key);
+	if (status < 0)
+		return status;
+
+	rk = key->rd_key;
+
+	/* invert the order of the round keys: */
+	for (i = 0, j = 4 * (key->rounds); i < j; i += 4, j -= 4) {
+		temp = rk[i];
+		rk[i] = rk[j];
+		rk[j] = temp;
+		temp = rk[i + 1];
+		rk[i + 1] = rk[j + 1];
+		rk[j + 1] = temp;
+		temp = rk[i + 2];
+		rk[i + 2] = rk[j + 2];
+		rk[j + 2] = temp;
+		temp = rk[i + 3];
+		rk[i + 3] = rk[j + 3];
+		rk[j + 3] = temp;
+	}
+	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
+	for (i = 1; i < (key->rounds); i++) {
+		rk += 4;
+		rk[0] =
+		    Td0[Te1[(rk[0] >> 24)] & 0xff] ^
+		    Td1[Te1[(rk[0] >> 16) & 0xff] & 0xff] ^
+		    Td2[Te1[(rk[0] >> 8) & 0xff] & 0xff] ^
+		    Td3[Te1[(rk[0]) & 0xff] & 0xff];
+		rk[1] =
+		    Td0[Te1[(rk[1] >> 24)] & 0xff] ^
+		    Td1[Te1[(rk[1] >> 16) & 0xff] & 0xff] ^
+		    Td2[Te1[(rk[1] >> 8) & 0xff] & 0xff] ^
+		    Td3[Te1[(rk[1]) & 0xff] & 0xff];
+		rk[2] =
+		    Td0[Te1[(rk[2] >> 24)] & 0xff] ^
+		    Td1[Te1[(rk[2] >> 16) & 0xff] & 0xff] ^
+		    Td2[Te1[(rk[2] >> 8) & 0xff] & 0xff] ^
+		    Td3[Te1[(rk[2]) & 0xff] & 0xff];
+		rk[3] =
+		    Td0[Te1[(rk[3] >> 24)] & 0xff] ^
+		    Td1[Te1[(rk[3] >> 16) & 0xff] & 0xff] ^
+		    Td2[Te1[(rk[3] >> 8) & 0xff] & 0xff] ^
+		    Td3[Te1[(rk[3]) & 0xff] & 0xff];
+	}
+	return 0;
+}
+
+/*
+ * Encrypt a single block
+ * in and out can overlap
+ */
+void
+AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
+{
+	const u32 *rk;
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+	int r;
+#endif /* ?FULL_UNROLL */
+
+	rk = key->rd_key;
+
+	/*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(in     ) ^ rk[0];
+	s1 = GETU32(in +  4) ^ rk[1];
+	s2 = GETU32(in +  8) ^ rk[2];
+	s3 = GETU32(in + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+	/* round 1: */
+	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+	/* round 2: */
+	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+	/* round 3: */
+	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+	/* round 4: */
+	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+	/* round 5: */
+	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+	/* round 6: */
+	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+	/* round 7: */
+	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+	/* round 8: */
+	s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+	s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+	s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+	s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+	/* round 9: */
+	t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+	t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+	t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+	t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+	if (key->rounds > 10) {
+		/* round 10: */
+		s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+		s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+		s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+		s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+		/* round 11: */
+		t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+		t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+		t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+		t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+		if (key->rounds > 12) {
+			/* round 12: */
+			s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+			s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+			s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+			s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+			/* round 13: */
+			t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+			t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+			t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+			t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+		}
+	}
+	rk += key->rounds << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+	r = key->rounds >> 1;
+	for (;;) {
+		t0 =
+		    Te0[(s0 >> 24)] ^
+		    Te1[(s1 >> 16) & 0xff] ^
+		    Te2[(s2 >> 8) & 0xff] ^
+		    Te3[(s3) & 0xff] ^
+		    rk[4];
+		t1 =
+		    Te0[(s1 >> 24)] ^
+		    Te1[(s2 >> 16) & 0xff] ^
+		    Te2[(s3 >> 8) & 0xff] ^
+		    Te3[(s0) & 0xff] ^
+		    rk[5];
+		t2 =
+		    Te0[(s2 >> 24)] ^
+		    Te1[(s3 >> 16) & 0xff] ^
+		    Te2[(s0 >> 8) & 0xff] ^
+		    Te3[(s1) & 0xff] ^
+		    rk[6];
+		t3 =
+		    Te0[(s3 >> 24)] ^
+		    Te1[(s0 >> 16) & 0xff] ^
+		    Te2[(s1 >> 8) & 0xff] ^
+		    Te3[(s2) & 0xff] ^
+		    rk[7];
+
+		rk += 8;
+		if (--r == 0) {
+			break;
+		}
+
+		s0 =
+		    Te0[(t0 >> 24)] ^
+		    Te1[(t1 >> 16) & 0xff] ^
+		    Te2[(t2 >> 8) & 0xff] ^
+		    Te3[(t3) & 0xff] ^
+		    rk[0];
+		s1 =
+		    Te0[(t1 >> 24)] ^
+		    Te1[(t2 >> 16) & 0xff] ^
+		    Te2[(t3 >> 8) & 0xff] ^
+		    Te3[(t0) & 0xff] ^
+		    rk[1];
+		s2 =
+		    Te0[(t2 >> 24)] ^
+		    Te1[(t3 >> 16) & 0xff] ^
+		    Te2[(t0 >> 8) & 0xff] ^
+		    Te3[(t1) & 0xff] ^
+		    rk[2];
+		s3 =
+		    Te0[(t3 >> 24)] ^
+		    Te1[(t0 >> 16) & 0xff] ^
+		    Te2[(t1 >> 8) & 0xff] ^
+		    Te3[(t2) & 0xff] ^
+		    rk[3];
+	}
+#endif /* ?FULL_UNROLL */
+	/*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 =
+	    (Te2[(t0 >> 24)] & 0xff000000) ^
+	    (Te3[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+	    (Te0[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+	    (Te1[(t3) & 0xff] & 0x000000ff) ^
+	    rk[0];
+	PUTU32(out, s0);
+	s1 =
+	    (Te2[(t1 >> 24)] & 0xff000000) ^
+	    (Te3[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+	    (Te0[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+	    (Te1[(t0) & 0xff] & 0x000000ff) ^
+	    rk[1];
+	PUTU32(out +  4, s1);
+	s2 =
+	    (Te2[(t2 >> 24)] & 0xff000000) ^
+	    (Te3[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+	    (Te0[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+	    (Te1[(t1) & 0xff] & 0x000000ff) ^
+	    rk[2];
+	PUTU32(out +  8, s2);
+	s3 =
+	    (Te2[(t3 >> 24)] & 0xff000000) ^
+	    (Te3[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+	    (Te0[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+	    (Te1[(t2) & 0xff] & 0x000000ff) ^
+	    rk[3];
+	PUTU32(out + 12, s3);
+}
+
+/*
+ * Decrypt a single block
+ * in and out can overlap
+ */
+void
+AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
+{
+	const u32 *rk;
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+	int r;
+#endif /* ?FULL_UNROLL */
+
+	rk = key->rd_key;
+
+	/*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(in) ^ rk[0];
+	s1 = GETU32(in + 4) ^ rk[1];
+	s2 = GETU32(in + 8) ^ rk[2];
+	s3 = GETU32(in + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+	/* round 1: */
+	t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+	t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+	t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+	t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+	/* round 2: */
+	s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+	s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+	s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+	s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+	/* round 3: */
+	t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+	t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+	t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+	t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+	/* round 4: */
+	s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+	s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+	s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+	s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+	/* round 5: */
+	t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+	t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+	t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+	t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+	/* round 6: */
+	s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+	s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+	s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+	s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+	/* round 7: */
+	t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+	t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+	t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+	t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+	/* round 8: */
+	s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+	s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+	s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+	s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+	/* round 9: */
+	t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+	t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+	t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+	t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+	if (key->rounds > 10) {
+		/* round 10: */
+		s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+		s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+		s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+		s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+		/* round 11: */
+		t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+		t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+		t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+		t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+		if (key->rounds > 12) {
+			/* round 12: */
+			s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+			s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+			s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+			s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+			/* round 13: */
+			t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+			t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+			t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+			t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+		}
+	}
+	rk += key->rounds << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+	r = key->rounds >> 1;
+	for (;;) {
+		t0 =
+		    Td0[(s0 >> 24)] ^
+		    Td1[(s3 >> 16) & 0xff] ^
+		    Td2[(s2 >> 8) & 0xff] ^
+		    Td3[(s1) & 0xff] ^
+		    rk[4];
+		t1 =
+		    Td0[(s1 >> 24)] ^
+		    Td1[(s0 >> 16) & 0xff] ^
+		    Td2[(s3 >> 8) & 0xff] ^
+		    Td3[(s2) & 0xff] ^
+		    rk[5];
+		t2 =
+		    Td0[(s2 >> 24)] ^
+		    Td1[(s1 >> 16) & 0xff] ^
+		    Td2[(s0 >> 8) & 0xff] ^
+		    Td3[(s3) & 0xff] ^
+		    rk[6];
+		t3 =
+		    Td0[(s3 >> 24)] ^
+		    Td1[(s2 >> 16) & 0xff] ^
+		    Td2[(s1 >> 8) & 0xff] ^
+		    Td3[(s0) & 0xff] ^
+		    rk[7];
+
+		rk += 8;
+		if (--r == 0) {
+			break;
+		}
+
+		s0 =
+		    Td0[(t0 >> 24)] ^
+		    Td1[(t3 >> 16) & 0xff] ^
+		    Td2[(t2 >> 8) & 0xff] ^
+		    Td3[(t1) & 0xff] ^
+		    rk[0];
+		s1 =
+		    Td0[(t1 >> 24)] ^
+		    Td1[(t0 >> 16) & 0xff] ^
+		    Td2[(t3 >> 8) & 0xff] ^
+		    Td3[(t2) & 0xff] ^
+		    rk[1];
+		s2 =
+		    Td0[(t2 >> 24)] ^
+		    Td1[(t1 >> 16) & 0xff] ^
+		    Td2[(t0 >> 8) & 0xff] ^
+		    Td3[(t3) & 0xff] ^
+		    rk[2];
+		s3 =
+		    Td0[(t3 >> 24)] ^
+		    Td1[(t2 >> 16) & 0xff] ^
+		    Td2[(t1 >> 8) & 0xff] ^
+		    Td3[(t0) & 0xff] ^
+		    rk[3];
+	}
+#endif /* ?FULL_UNROLL */
+    /*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 =
+	    (((uint32_t)Td4[(t0 >> 24)]) << 24) ^
+	    (Td4[(t3 >> 16) & 0xff] << 16) ^
+	    (Td4[(t2 >> 8) & 0xff] <<  8) ^
+	    (Td4[(t1) & 0xff]) ^
+	    rk[0];
+	PUTU32(out, s0);
+	s1 =
+	    (((uint32_t)Td4[(t1 >> 24)]) << 24) ^
+	    (Td4[(t0 >> 16) & 0xff] << 16) ^
+	    (Td4[(t3 >> 8) & 0xff] <<  8) ^
+	    (Td4[(t2) & 0xff]) ^
+	    rk[1];
+	PUTU32(out + 4, s1);
+	s2 =
+	    (((uint32_t)Td4[(t2 >> 24)]) << 24) ^
+	    (Td4[(t1 >> 16) & 0xff] << 16) ^
+	    (Td4[(t0 >> 8) & 0xff] <<  8) ^
+	    (Td4[(t3) & 0xff]) ^
+	    rk[2];
+	PUTU32(out + 8, s2);
+	s3 =
+	    (((uint32_t)Td4[(t3 >> 24)]) << 24) ^
+	    (Td4[(t2 >> 16) & 0xff] << 16) ^
+	    (Td4[(t1 >> 8) & 0xff] <<  8) ^
+	    (Td4[(t0) & 0xff]) ^
+	    rk[3];
+	PUTU32(out + 12, s3);
+}
+
+#else /* AES_ASM */
+
+static const u8 Te4[256] = {
+	0x63U, 0x7cU, 0x77U, 0x7bU, 0xf2U, 0x6bU, 0x6fU, 0xc5U,
+	0x30U, 0x01U, 0x67U, 0x2bU, 0xfeU, 0xd7U, 0xabU, 0x76U,
+	0xcaU, 0x82U, 0xc9U, 0x7dU, 0xfaU, 0x59U, 0x47U, 0xf0U,
+	0xadU, 0xd4U, 0xa2U, 0xafU, 0x9cU, 0xa4U, 0x72U, 0xc0U,
+	0xb7U, 0xfdU, 0x93U, 0x26U, 0x36U, 0x3fU, 0xf7U, 0xccU,
+	0x34U, 0xa5U, 0xe5U, 0xf1U, 0x71U, 0xd8U, 0x31U, 0x15U,
+	0x04U, 0xc7U, 0x23U, 0xc3U, 0x18U, 0x96U, 0x05U, 0x9aU,
+	0x07U, 0x12U, 0x80U, 0xe2U, 0xebU, 0x27U, 0xb2U, 0x75U,
+	0x09U, 0x83U, 0x2cU, 0x1aU, 0x1bU, 0x6eU, 0x5aU, 0xa0U,
+	0x52U, 0x3bU, 0xd6U, 0xb3U, 0x29U, 0xe3U, 0x2fU, 0x84U,
+	0x53U, 0xd1U, 0x00U, 0xedU, 0x20U, 0xfcU, 0xb1U, 0x5bU,
+	0x6aU, 0xcbU, 0xbeU, 0x39U, 0x4aU, 0x4cU, 0x58U, 0xcfU,
+	0xd0U, 0xefU, 0xaaU, 0xfbU, 0x43U, 0x4dU, 0x33U, 0x85U,
+	0x45U, 0xf9U, 0x02U, 0x7fU, 0x50U, 0x3cU, 0x9fU, 0xa8U,
+	0x51U, 0xa3U, 0x40U, 0x8fU, 0x92U, 0x9dU, 0x38U, 0xf5U,
+	0xbcU, 0xb6U, 0xdaU, 0x21U, 0x10U, 0xffU, 0xf3U, 0xd2U,
+	0xcdU, 0x0cU, 0x13U, 0xecU, 0x5fU, 0x97U, 0x44U, 0x17U,
+	0xc4U, 0xa7U, 0x7eU, 0x3dU, 0x64U, 0x5dU, 0x19U, 0x73U,
+	0x60U, 0x81U, 0x4fU, 0xdcU, 0x22U, 0x2aU, 0x90U, 0x88U,
+	0x46U, 0xeeU, 0xb8U, 0x14U, 0xdeU, 0x5eU, 0x0bU, 0xdbU,
+	0xe0U, 0x32U, 0x3aU, 0x0aU, 0x49U, 0x06U, 0x24U, 0x5cU,
+	0xc2U, 0xd3U, 0xacU, 0x62U, 0x91U, 0x95U, 0xe4U, 0x79U,
+	0xe7U, 0xc8U, 0x37U, 0x6dU, 0x8dU, 0xd5U, 0x4eU, 0xa9U,
+	0x6cU, 0x56U, 0xf4U, 0xeaU, 0x65U, 0x7aU, 0xaeU, 0x08U,
+	0xbaU, 0x78U, 0x25U, 0x2eU, 0x1cU, 0xa6U, 0xb4U, 0xc6U,
+	0xe8U, 0xddU, 0x74U, 0x1fU, 0x4bU, 0xbdU, 0x8bU, 0x8aU,
+	0x70U, 0x3eU, 0xb5U, 0x66U, 0x48U, 0x03U, 0xf6U, 0x0eU,
+	0x61U, 0x35U, 0x57U, 0xb9U, 0x86U, 0xc1U, 0x1dU, 0x9eU,
+	0xe1U, 0xf8U, 0x98U, 0x11U, 0x69U, 0xd9U, 0x8eU, 0x94U,
+	0x9bU, 0x1eU, 0x87U, 0xe9U, 0xceU, 0x55U, 0x28U, 0xdfU,
+	0x8cU, 0xa1U, 0x89U, 0x0dU, 0xbfU, 0xe6U, 0x42U, 0x68U,
+	0x41U, 0x99U, 0x2dU, 0x0fU, 0xb0U, 0x54U, 0xbbU, 0x16U
+};
+static const u32 rcon[] = {
+	0x01000000, 0x02000000, 0x04000000, 0x08000000,
+	0x10000000, 0x20000000, 0x40000000, 0x80000000,
+	0x1B000000, 0x36000000,
+	/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ */
+int
+AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key)
+{
+	u32 *rk;
+	int i = 0;
+	u32 temp;
+
+	if (!userKey || !key)
+		return -1;
+	if (bits != 128 && bits != 192 && bits != 256)
+		return -2;
+
+	rk = key->rd_key;
+
+	if (bits == 128)
+		key->rounds = 10;
+	else if (bits == 192)
+		key->rounds = 12;
+	else
+		key->rounds = 14;
+
+	rk[0] = GETU32(userKey);
+	rk[1] = GETU32(userKey +  4);
+	rk[2] = GETU32(userKey +  8);
+	rk[3] = GETU32(userKey + 12);
+	if (bits == 128) {
+		while (1) {
+			temp = rk[3];
+			rk[4] = rk[0] ^
+			    (Te4[(temp >> 16) & 0xff] << 24) ^
+			    (Te4[(temp >> 8) & 0xff] << 16) ^
+			    (Te4[(temp) & 0xff] << 8) ^
+			    (Te4[(temp >> 24)]) ^
+			    rcon[i];
+			rk[5] = rk[1] ^ rk[4];
+			rk[6] = rk[2] ^ rk[5];
+			rk[7] = rk[3] ^ rk[6];
+			if (++i == 10) {
+				return 0;
+			}
+			rk += 4;
+		}
+	}
+	rk[4] = GETU32(userKey + 16);
+	rk[5] = GETU32(userKey + 20);
+	if (bits == 192) {
+		while (1) {
+			temp = rk[5];
+			rk[6] = rk[0] ^
+			    (Te4[(temp >> 16) & 0xff] << 24) ^
+			    (Te4[(temp >> 8) & 0xff] << 16) ^
+			    (Te4[(temp) & 0xff] << 8) ^
+			    (Te4[(temp >> 24)]) ^
+			    rcon[i];
+			rk[7] = rk[1] ^ rk[6];
+			rk[8] = rk[2] ^ rk[7];
+			rk[9] = rk[3] ^ rk[8];
+			if (++i == 8) {
+				return 0;
+			}
+			rk[10] = rk[4] ^ rk[9];
+			rk[11] = rk[5] ^ rk[10];
+			rk += 6;
+		}
+	}
+	rk[6] = GETU32(userKey + 24);
+	rk[7] = GETU32(userKey + 28);
+	if (bits == 256) {
+		while (1) {
+			temp = rk[7];
+			rk[8] = rk[0] ^
+			    (Te4[(temp >> 16) & 0xff] << 24) ^
+			    (Te4[(temp >> 8) & 0xff] << 16) ^
+			    (Te4[(temp) & 0xff] << 8) ^
+			    (Te4[(temp >> 24)]) ^
+			    rcon[i];
+			rk[9] = rk[1] ^ rk[8];
+			rk[10] = rk[2] ^ rk[9];
+			rk[11] = rk[3] ^ rk[10];
+			if (++i == 7) {
+				return 0;
+			}
+			temp = rk[11];
+			rk[12] = rk[4] ^
+			    (Te4[(temp >> 24)] << 24) ^
+			    (Te4[(temp >> 16) & 0xff] << 16) ^
+			    (Te4[(temp >> 8) & 0xff] << 8) ^
+			    (Te4[(temp) & 0xff]);
+			rk[13] = rk[5] ^ rk[12];
+			rk[14] = rk[6] ^ rk[13];
+			rk[15] = rk[7] ^ rk[14];
+
+			rk += 8;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ */
+int
+AES_set_decrypt_key(const unsigned char *userKey, const int bits,
+    AES_KEY *key)
+{
+	u32 *rk;
+	int i, j, status;
+	u32 temp;
+
+	/* first, start with an encryption schedule */
+	status = AES_set_encrypt_key(userKey, bits, key);
+	if (status < 0)
+		return status;
+
+	rk = key->rd_key;
+
+	/* invert the order of the round keys: */
+	for (i = 0, j = 4*(key->rounds); i < j; i += 4, j -= 4) {
+		temp = rk[i];
+		rk[i] = rk[j];
+		rk[j] = temp;
+		temp = rk[i + 1];
+		rk[i + 1] = rk[j + 1];
+		rk[j + 1] = temp;
+		temp = rk[i + 2];
+		rk[i + 2] = rk[j + 2];
+		rk[j + 2] = temp;
+		temp = rk[i + 3];
+		rk[i + 3] = rk[j + 3];
+		rk[j + 3] = temp;
+	}
+	/* apply the inverse MixColumn transform to all round keys but the first and the last: */
+	for (i = 1; i < (key->rounds); i++) {
+		rk += 4;
+		for (j = 0; j < 4; j++) {
+			u32 tp1, tp2, tp4, tp8, tp9, tpb, tpd, tpe, m;
+
+			tp1 = rk[j];
+			m = tp1 & 0x80808080;
+			tp2 = ((tp1 & 0x7f7f7f7f) << 1) ^
+			    ((m - (m >> 7)) & 0x1b1b1b1b);
+			m = tp2 & 0x80808080;
+			tp4 = ((tp2 & 0x7f7f7f7f) << 1) ^
+			    ((m - (m >> 7)) & 0x1b1b1b1b);
+			m = tp4 & 0x80808080;
+			tp8 = ((tp4 & 0x7f7f7f7f) << 1) ^
+			    ((m - (m >> 7)) & 0x1b1b1b1b);
+			tp9 = tp8 ^ tp1;
+			tpb = tp9 ^ tp2;
+			tpd = tp9 ^ tp4;
+			tpe = tp8 ^ tp4 ^ tp2;
+#if defined(ROTATE)
+			rk[j] = tpe ^ ROTATE(tpd, 16) ^
+			    ROTATE(tp9, 24) ^ ROTATE(tpb, 8);
+#else
+			rk[j] = tpe ^ (tpd >> 16) ^ (tpd << 16) ^
+			    (tp9 >> 8) ^ (tp9 << 24) ^
+			    (tpb >> 24) ^ (tpb << 8);
+#endif
+		}
+	}
+	return 0;
+}
+
+#endif /* AES_ASM */
diff --git a/crypto/aes/aes_ctr.c b/crypto/aes/aes_ctr.c
new file mode 100644
index 0000000..6079145
--- /dev/null
+++ b/crypto/aes/aes_ctr.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: aes_ctr.c,v 1.9 2014/06/12 15:49:27 deraadt Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+void
+AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const AES_KEY *key, unsigned char ivec[AES_BLOCK_SIZE],
+    unsigned char ecount_buf[AES_BLOCK_SIZE], unsigned int *num)
+{
+	CRYPTO_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num,
+	    (block128_f)AES_encrypt);
+}
diff --git a/crypto/aes/aes_ecb.c b/crypto/aes/aes_ecb.c
new file mode 100644
index 0000000..e3bb40b
--- /dev/null
+++ b/crypto/aes/aes_ecb.c
@@ -0,0 +1,69 @@
+/* $OpenBSD: aes_ecb.c,v 1.7 2022/11/26 16:08:50 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef AES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+#include 
+#include "aes_local.h"
+
+void
+AES_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    const AES_KEY *key, const int enc)
+{
+	if (AES_ENCRYPT == enc)
+		AES_encrypt(in, out, key);
+	else
+		AES_decrypt(in, out, key);
+}
diff --git a/crypto/aes/aes_ige.c b/crypto/aes/aes_ige.c
new file mode 100644
index 0000000..ef7d766
--- /dev/null
+++ b/crypto/aes/aes_ige.c
@@ -0,0 +1,194 @@
+/* $OpenBSD: aes_ige.c,v 1.9 2022/11/26 16:08:50 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+#include "aes_local.h"
+
+#define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
+typedef struct {
+	unsigned long data[N_WORDS];
+} aes_block_t;
+
+/* XXX: probably some better way to do this */
+#if defined(__i386__) || defined(__x86_64__)
+#define UNALIGNED_MEMOPS_ARE_FAST 1
+#else
+#define UNALIGNED_MEMOPS_ARE_FAST 0
+#endif
+
+#if UNALIGNED_MEMOPS_ARE_FAST
+#define load_block(d, s)        (d) = *(const aes_block_t *)(s)
+#define store_block(d, s)       *(aes_block_t *)(d) = (s)
+#else
+#define load_block(d, s)        memcpy((d).data, (s), AES_BLOCK_SIZE)
+#define store_block(d, s)       memcpy((d), (s).data, AES_BLOCK_SIZE)
+#endif
+
+/* N.B. The IV for this mode is _twice_ the block size */
+
+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;
+
+	OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
+
+	len = length / AES_BLOCK_SIZE;
+
+	if (AES_ENCRYPT == enc) {
+		if (in != out && (UNALIGNED_MEMOPS_ARE_FAST ||
+		    ((size_t)in|(size_t)out|(size_t)ivec) %
+		    sizeof(long) == 0)) {
+			aes_block_t *ivp = (aes_block_t *)ivec;
+			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
+
+			while (len) {
+				aes_block_t *inp = (aes_block_t *)in;
+				aes_block_t *outp = (aes_block_t *)out;
+
+				for (n = 0; n < N_WORDS; ++n)
+					outp->data[n] = inp->data[n] ^ ivp->data[n];
+				AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key);
+				for (n = 0; n < N_WORDS; ++n)
+					outp->data[n] ^= iv2p->data[n];
+				ivp = outp;
+				iv2p = inp;
+				--len;
+				in += AES_BLOCK_SIZE;
+				out += AES_BLOCK_SIZE;
+			}
+			memmove(ivec, ivp->data, AES_BLOCK_SIZE);
+			memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
+		} else {
+			aes_block_t tmp, tmp2;
+			aes_block_t iv;
+			aes_block_t iv2;
+
+			load_block(iv, ivec);
+			load_block(iv2, ivec + AES_BLOCK_SIZE);
+
+			while (len) {
+				load_block(tmp, in);
+				for (n = 0; n < N_WORDS; ++n)
+					tmp2.data[n] = tmp.data[n] ^ iv.data[n];
+				AES_encrypt((unsigned char *)tmp2.data,
+				    (unsigned char *)tmp2.data, key);
+				for (n = 0; n < N_WORDS; ++n)
+					tmp2.data[n] ^= iv2.data[n];
+				store_block(out, tmp2);
+				iv = tmp2;
+				iv2 = tmp;
+				--len;
+				in += AES_BLOCK_SIZE;
+				out += AES_BLOCK_SIZE;
+			}
+			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
+			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
+		}
+	} else {
+		if (in != out && (UNALIGNED_MEMOPS_ARE_FAST ||
+		    ((size_t)in|(size_t)out|(size_t)ivec) %
+		    sizeof(long) == 0)) {
+			aes_block_t *ivp = (aes_block_t *)ivec;
+			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);
+
+			while (len) {
+				aes_block_t tmp;
+				aes_block_t *inp = (aes_block_t *)in;
+				aes_block_t *outp = (aes_block_t *)out;
+
+				for (n = 0; n < N_WORDS; ++n)
+					tmp.data[n] = inp->data[n] ^ iv2p->data[n];
+				AES_decrypt((unsigned char *)tmp.data,
+				    (unsigned char *)outp->data, key);
+				for (n = 0; n < N_WORDS; ++n)
+					outp->data[n] ^= ivp->data[n];
+				ivp = inp;
+				iv2p = outp;
+				--len;
+				in += AES_BLOCK_SIZE;
+				out += AES_BLOCK_SIZE;
+			}
+			memmove(ivec, ivp->data, AES_BLOCK_SIZE);
+			memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
+		} else {
+			aes_block_t tmp, tmp2;
+			aes_block_t iv;
+			aes_block_t iv2;
+
+			load_block(iv, ivec);
+			load_block(iv2, ivec + AES_BLOCK_SIZE);
+
+			while (len) {
+				load_block(tmp, in);
+				tmp2 = tmp;
+				for (n = 0; n < N_WORDS; ++n)
+					tmp.data[n] ^= iv2.data[n];
+				AES_decrypt((unsigned char *)tmp.data,
+				    (unsigned char *)tmp.data, key);
+				for (n = 0; n < N_WORDS; ++n)
+					tmp.data[n] ^= iv.data[n];
+				store_block(out, tmp);
+				iv = tmp2;
+				iv2 = tmp;
+				--len;
+				in += AES_BLOCK_SIZE;
+				out += AES_BLOCK_SIZE;
+			}
+			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
+			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
+		}
+	}
+}
diff --git a/crypto/aes/aes_local.h b/crypto/aes/aes_local.h
new file mode 100644
index 0000000..ef74e71
--- /dev/null
+++ b/crypto/aes/aes_local.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: aes_local.h,v 1.2 2022/11/26 17:23:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef HEADER_AES_LOCAL_H
+#define HEADER_AES_LOCAL_H
+
+#include 
+
+#ifdef OPENSSL_NO_AES
+#error AES is disabled.
+#endif
+
+#include 
+#include 
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+
+typedef unsigned int u32;
+typedef unsigned short u16;
+typedef unsigned char u8;
+
+#define MAXKC   (256/32)
+#define MAXKB   (256/8)
+#define MAXNR   14
+
+/* This controls loop-unrolling in aes_core.c */
+#undef FULL_UNROLL
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_AES_LOCAL_H */
diff --git a/crypto/aes/aes_ofb.c b/crypto/aes/aes_ofb.c
new file mode 100644
index 0000000..f8dc03a
--- /dev/null
+++ b/crypto/aes/aes_ofb.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: aes_ofb.c,v 1.6 2014/06/12 15:49:27 deraadt Exp $ */
+/* ====================================================================
+ * Copyright (c) 2002-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+void
+AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const AES_KEY *key, unsigned char *ivec, int *num)
+{
+	CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+	    (block128_f)AES_encrypt);
+}
diff --git a/crypto/aes/aes_wrap.c b/crypto/aes/aes_wrap.c
new file mode 100644
index 0000000..b30630f
--- /dev/null
+++ b/crypto/aes/aes_wrap.c
@@ -0,0 +1,133 @@
+/* $OpenBSD: aes_wrap.c,v 1.12 2018/11/07 18:31:16 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+#include 
+
+static const unsigned char default_iv[] = {
+	0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
+};
+
+int
+AES_wrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out,
+    const unsigned char *in, unsigned int inlen)
+{
+	unsigned char *A, B[16], *R;
+	unsigned int i, j, t;
+
+	if ((inlen & 0x7) || (inlen < 16))
+		return -1;
+	A = B;
+	t = 1;
+	memmove(out + 8, in, inlen);
+	if (!iv)
+		iv = default_iv;
+
+	memcpy(A, iv, 8);
+
+	for (j = 0; j < 6; j++) {
+		R = out + 8;
+		for (i = 0; i < inlen; i += 8, t++, R += 8) {
+			memcpy(B + 8, R, 8);
+			AES_encrypt(B, B, key);
+			A[7] ^= (unsigned char)(t & 0xff);
+			if (t > 0xff) {
+				A[6] ^= (unsigned char)((t >> 8) & 0xff);
+				A[5] ^= (unsigned char)((t >> 16) & 0xff);
+				A[4] ^= (unsigned char)((t >> 24) & 0xff);
+			}
+			memcpy(R, B + 8, 8);
+		}
+	}
+	memcpy(out, A, 8);
+	return inlen + 8;
+}
+
+int
+AES_unwrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out,
+    const unsigned char *in, unsigned int inlen)
+{
+	unsigned char *A, B[16], *R;
+	unsigned int i, j, t;
+
+	if ((inlen & 0x7) || (inlen < 24))
+		return -1;
+	inlen -= 8;
+	A = B;
+	t = 6 * (inlen >> 3);
+	memcpy(A, in, 8);
+	memmove(out, in + 8, inlen);
+	for (j = 0; j < 6; j++) {
+		R = out + inlen - 8;
+		for (i = 0; i < inlen; i += 8, t--, R -= 8) {
+			A[7] ^= (unsigned char)(t & 0xff);
+			if (t > 0xff) {
+				A[6] ^= (unsigned char)((t >> 8) & 0xff);
+				A[5] ^= (unsigned char)((t >> 16) & 0xff);
+				A[4] ^= (unsigned char)((t >> 24) & 0xff);
+			}
+			memcpy(B + 8, R, 8);
+			AES_decrypt(B, B, key);
+			memcpy(R, B + 8, 8);
+		}
+	}
+	if (!iv)
+		iv = default_iv;
+	if (memcmp(A, iv, 8)) {
+		explicit_bzero(out, inlen);
+		return 0;
+	}
+	return inlen;
+}
diff --git a/crypto/aes/aesni-elf-x86_64.S b/crypto/aes/aesni-elf-x86_64.S
new file mode 100644
index 0000000..ee26d2f
--- /dev/null
+++ b/crypto/aes/aesni-elf-x86_64.S
@@ -0,0 +1,2575 @@
+#include "x86_arch.h"
+.text	
+.globl	aesni_encrypt
+.type	aesni_encrypt,@function
+.align	16
+aesni_encrypt:
+	endbr64
+	movups	(%rdi),%xmm2
+	movl	240(%rdx),%eax
+	movups	(%rdx),%xmm0
+	movups	16(%rdx),%xmm1
+	leaq	32(%rdx),%rdx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_1:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rdx),%xmm1
+	leaq	16(%rdx),%rdx
+	jnz	.Loop_enc1_1	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	retq
+.size	aesni_encrypt,.-aesni_encrypt
+
+.globl	aesni_decrypt
+.type	aesni_decrypt,@function
+.align	16
+aesni_decrypt:
+	endbr64
+	movups	(%rdi),%xmm2
+	movl	240(%rdx),%eax
+	movups	(%rdx),%xmm0
+	movups	16(%rdx),%xmm1
+	leaq	32(%rdx),%rdx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_2:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rdx),%xmm1
+	leaq	16(%rdx),%rdx
+	jnz	.Loop_dec1_2	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	retq
+.size	aesni_decrypt, .-aesni_decrypt
+.type	_aesni_encrypt3,@function
+.align	16
+_aesni_encrypt3:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+.Lenc_loop3:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop3
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	retq
+.size	_aesni_encrypt3,.-_aesni_encrypt3
+.type	_aesni_decrypt3,@function
+.align	16
+_aesni_decrypt3:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+.Ldec_loop3:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop3
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	retq
+.size	_aesni_decrypt3,.-_aesni_decrypt3
+.type	_aesni_encrypt4,@function
+.align	16
+_aesni_encrypt4:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+.Lenc_loop4:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop4
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	retq
+.size	_aesni_encrypt4,.-_aesni_encrypt4
+.type	_aesni_decrypt4,@function
+.align	16
+_aesni_decrypt4:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+.Ldec_loop4:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop4
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	retq
+.size	_aesni_decrypt4,.-_aesni_decrypt4
+.type	_aesni_encrypt6,@function
+.align	16
+_aesni_encrypt6:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm7
+	jmp	.Lenc_loop6_enter
+.align	16
+.Lenc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lenc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop6
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	retq
+.size	_aesni_encrypt6,.-_aesni_encrypt6
+.type	_aesni_decrypt6,@function
+.align	16
+_aesni_decrypt6:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm7
+	jmp	.Ldec_loop6_enter
+.align	16
+.Ldec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+.Ldec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop6
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	retq
+.size	_aesni_decrypt6,.-_aesni_decrypt6
+.type	_aesni_encrypt8,@function
+.align	16
+_aesni_encrypt8:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	.Lenc_loop8_enter
+.align	16
+.Lenc_loop8:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+.Lenc_loop8_enter:
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop8
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	aesenclast	%xmm0,%xmm8
+	aesenclast	%xmm0,%xmm9
+	retq
+.size	_aesni_encrypt8,.-_aesni_encrypt8
+.type	_aesni_decrypt8,@function
+.align	16
+_aesni_decrypt8:
+	endbr64
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	.Ldec_loop8_enter
+.align	16
+.Ldec_loop8:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+.Ldec_loop8_enter:
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop8
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	aesdeclast	%xmm0,%xmm8
+	aesdeclast	%xmm0,%xmm9
+	retq
+.size	_aesni_decrypt8,.-_aesni_decrypt8
+.globl	aesni_ecb_encrypt
+.type	aesni_ecb_encrypt,@function
+.align	16
+aesni_ecb_encrypt:
+	endbr64
+	andq	$-16,%rdx
+	jz	.Lecb_ret
+
+	movl	240(%rcx),%eax
+	movups	(%rcx),%xmm0
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	testl	%r8d,%r8d
+	jz	.Lecb_decrypt
+
+	cmpq	$128,%rdx
+	jb	.Lecb_enc_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	.Lecb_enc_loop8_enter
+.align	16
+.Lecb_enc_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+.Lecb_enc_loop8_enter:
+
+	call	_aesni_encrypt8
+
+	subq	$128,%rdx
+	jnc	.Lecb_enc_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	.Lecb_ret
+
+.Lecb_enc_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	.Lecb_enc_one
+	movups	16(%rdi),%xmm3
+	je	.Lecb_enc_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	.Lecb_enc_three
+	movups	48(%rdi),%xmm5
+	je	.Lecb_enc_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	.Lecb_enc_five
+	movups	80(%rdi),%xmm7
+	je	.Lecb_enc_six
+	movdqu	96(%rdi),%xmm8
+	call	_aesni_encrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_3:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_3	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_three:
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_four:
+	call	_aesni_encrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_enc_six:
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	jmp	.Lecb_ret
+
+.align	16
+.Lecb_decrypt:
+	cmpq	$128,%rdx
+	jb	.Lecb_dec_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	.Lecb_dec_loop8_enter
+.align	16
+.Lecb_dec_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+.Lecb_dec_loop8_enter:
+
+	call	_aesni_decrypt8
+
+	movups	(%r11),%xmm0
+	subq	$128,%rdx
+	jnc	.Lecb_dec_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	.Lecb_ret
+
+.Lecb_dec_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	.Lecb_dec_one
+	movups	16(%rdi),%xmm3
+	je	.Lecb_dec_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	.Lecb_dec_three
+	movups	48(%rdi),%xmm5
+	je	.Lecb_dec_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	.Lecb_dec_five
+	movups	80(%rdi),%xmm7
+	je	.Lecb_dec_six
+	movups	96(%rdi),%xmm8
+	movups	(%rcx),%xmm0
+	call	_aesni_decrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_4:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_4	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_three:
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_four:
+	call	_aesni_decrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	.Lecb_ret
+.align	16
+.Lecb_dec_six:
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+
+.Lecb_ret:
+	retq
+.size	aesni_ecb_encrypt,.-aesni_ecb_encrypt
+.globl	aesni_ccm64_encrypt_blocks
+.type	aesni_ccm64_encrypt_blocks,@function
+.align	16
+aesni_ccm64_encrypt_blocks:
+	endbr64
+	movl	240(%rcx),%eax
+	movdqu	(%r8),%xmm9
+	movdqa	.Lincrement64(%rip),%xmm6
+	movdqa	.Lbswap_mask(%rip),%xmm7
+
+	shrl	$1,%eax
+	leaq	0(%rcx),%r11
+	movdqu	(%r9),%xmm3
+	movdqa	%xmm9,%xmm2
+	movl	%eax,%r10d
+.byte	102,68,15,56,0,207
+	jmp	.Lccm64_enc_outer
+.align	16
+.Lccm64_enc_outer:
+	movups	(%r11),%xmm0
+	movl	%r10d,%eax
+	movups	(%rdi),%xmm8
+
+	xorps	%xmm0,%xmm2
+	movups	16(%r11),%xmm1
+	xorps	%xmm8,%xmm0
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm3
+	movups	(%rcx),%xmm0
+
+.Lccm64_enc2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	.Lccm64_enc2_loop
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	paddq	%xmm6,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+
+	decq	%rdx
+	leaq	16(%rdi),%rdi
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+	jnz	.Lccm64_enc_outer
+
+	movups	%xmm3,(%r9)
+	retq
+.size	aesni_ccm64_encrypt_blocks,.-aesni_ccm64_encrypt_blocks
+.globl	aesni_ccm64_decrypt_blocks
+.type	aesni_ccm64_decrypt_blocks,@function
+.align	16
+aesni_ccm64_decrypt_blocks:
+	movl	240(%rcx),%eax
+	movups	(%r8),%xmm9
+	movdqu	(%r9),%xmm3
+	movdqa	.Lincrement64(%rip),%xmm6
+	movdqa	.Lbswap_mask(%rip),%xmm7
+
+	movaps	%xmm9,%xmm2
+	movl	%eax,%r10d
+	movq	%rcx,%r11
+.byte	102,68,15,56,0,207
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_5:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_5	
+	aesenclast	%xmm1,%xmm2
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	leaq	16(%rdi),%rdi
+	jmp	.Lccm64_dec_outer
+.align	16
+.Lccm64_dec_outer:
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movl	%r10d,%eax
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+
+	subq	$1,%rdx
+	jz	.Lccm64_dec_break
+
+	movups	(%r11),%xmm0
+	shrl	$1,%eax
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	(%rcx),%xmm0
+
+.Lccm64_dec2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	.Lccm64_dec2_loop
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	leaq	16(%rdi),%rdi
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	jmp	.Lccm64_dec_outer
+
+.align	16
+.Lccm64_dec_break:
+
+	movups	(%r11),%xmm0
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%r11
+	xorps	%xmm8,%xmm3
+.Loop_enc1_6:
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	movups	(%r11),%xmm1
+	leaq	16(%r11),%r11
+	jnz	.Loop_enc1_6	
+	aesenclast	%xmm1,%xmm3
+	movups	%xmm3,(%r9)
+	retq
+.size	aesni_ccm64_decrypt_blocks,.-aesni_ccm64_decrypt_blocks
+.globl	aesni_ctr32_encrypt_blocks
+.type	aesni_ctr32_encrypt_blocks,@function
+.align	16
+aesni_ctr32_encrypt_blocks:
+	endbr64
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$32,%rsp
+	leaq	-8(%rax),%rbp
+	cmpq	$1,%rdx
+	je	.Lctr32_one_shortcut
+
+	movdqu	(%r8),%xmm14
+	movdqa	.Lbswap_mask(%rip),%xmm15
+	xorl	%eax,%eax
+.byte	102,69,15,58,22,242,3
+.byte	102,68,15,58,34,240,3
+
+	movl	240(%rcx),%eax
+	bswapl	%r10d
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+.byte	102,69,15,58,34,226,0
+	leaq	3(%r10),%r11
+.byte	102,69,15,58,34,235,0
+	incl	%r10d
+.byte	102,69,15,58,34,226,1
+	incq	%r11
+.byte	102,69,15,58,34,235,1
+	incl	%r10d
+.byte	102,69,15,58,34,226,2
+	incq	%r11
+.byte	102,69,15,58,34,235,2
+	movdqa	%xmm12,0(%rsp)
+.byte	102,69,15,56,0,231
+	movdqa	%xmm13,16(%rsp)
+.byte	102,69,15,56,0,239
+
+	pshufd	$192,%xmm12,%xmm2
+	pshufd	$128,%xmm12,%xmm3
+	pshufd	$64,%xmm12,%xmm4
+	cmpq	$6,%rdx
+	jb	.Lctr32_tail
+	shrl	$1,%eax
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	subq	$6,%rdx
+	jmp	.Lctr32_loop6
+
+.align	16
+.Lctr32_loop6:
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm2
+	movups	(%r11),%xmm0
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm3
+	movups	16(%r11),%xmm1
+	pshufd	$64,%xmm13,%xmm7
+	por	%xmm14,%xmm4
+	por	%xmm14,%xmm5
+	xorps	%xmm0,%xmm2
+	por	%xmm14,%xmm6
+	por	%xmm14,%xmm7
+
+
+
+
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	movdqa	.Lincrement32(%rip),%xmm13
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	movdqa	(%rsp),%xmm12
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	jmp	.Lctr32_enc_loop6_enter
+.align	16
+.Lctr32_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lctr32_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lctr32_enc_loop6
+
+	aesenc	%xmm1,%xmm2
+	paddd	%xmm13,%xmm12
+	aesenc	%xmm1,%xmm3
+	paddd	16(%rsp),%xmm13
+	aesenc	%xmm1,%xmm4
+	movdqa	%xmm12,0(%rsp)
+	aesenc	%xmm1,%xmm5
+	movdqa	%xmm13,16(%rsp)
+	aesenc	%xmm1,%xmm6
+.byte	102,69,15,56,0,231
+	aesenc	%xmm1,%xmm7
+.byte	102,69,15,56,0,239
+
+	aesenclast	%xmm0,%xmm2
+	movups	(%rdi),%xmm8
+	aesenclast	%xmm0,%xmm3
+	movups	16(%rdi),%xmm9
+	aesenclast	%xmm0,%xmm4
+	movups	32(%rdi),%xmm10
+	aesenclast	%xmm0,%xmm5
+	movups	48(%rdi),%xmm11
+	aesenclast	%xmm0,%xmm6
+	movups	64(%rdi),%xmm1
+	aesenclast	%xmm0,%xmm7
+	movups	80(%rdi),%xmm0
+	leaq	96(%rdi),%rdi
+
+	xorps	%xmm2,%xmm8
+	pshufd	$192,%xmm12,%xmm2
+	xorps	%xmm3,%xmm9
+	pshufd	$128,%xmm12,%xmm3
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	pshufd	$64,%xmm12,%xmm4
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	xorps	%xmm7,%xmm0
+	movups	%xmm1,64(%rsi)
+	movups	%xmm0,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movl	%r10d,%eax
+	subq	$6,%rdx
+	jnc	.Lctr32_loop6
+
+	addq	$6,%rdx
+	jz	.Lctr32_done
+	movq	%r11,%rcx
+	leal	1(%rax,%rax,1),%eax
+
+.Lctr32_tail:
+	por	%xmm14,%xmm2
+	movups	(%rdi),%xmm8
+	cmpq	$2,%rdx
+	jb	.Lctr32_one
+
+	por	%xmm14,%xmm3
+	movups	16(%rdi),%xmm9
+	je	.Lctr32_two
+
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm4
+	movups	32(%rdi),%xmm10
+	cmpq	$4,%rdx
+	jb	.Lctr32_three
+
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm5
+	movups	48(%rdi),%xmm11
+	je	.Lctr32_four
+
+	por	%xmm14,%xmm6
+	xorps	%xmm7,%xmm7
+
+	call	_aesni_encrypt6
+
+	movups	64(%rdi),%xmm1
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	movups	%xmm1,64(%rsi)
+	jmp	.Lctr32_done
+
+.align	16
+.Lctr32_one_shortcut:
+	movups	(%r8),%xmm2
+	movups	(%rdi),%xmm8
+	movl	240(%rcx),%eax
+.Lctr32_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_7:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_7	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm2,%xmm8
+	movups	%xmm8,(%rsi)
+	jmp	.Lctr32_done
+
+.align	16
+.Lctr32_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	movups	%xmm9,16(%rsi)
+	jmp	.Lctr32_done
+
+.align	16
+.Lctr32_three:
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	movups	%xmm10,32(%rsi)
+	jmp	.Lctr32_done
+
+.align	16
+.Lctr32_four:
+	call	_aesni_encrypt4
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	movups	%xmm11,48(%rsi)
+
+.Lctr32_done:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lctr32_ret:
+	retq
+.size	aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
+.globl	aesni_xts_encrypt
+.type	aesni_xts_encrypt,@function
+.align	16
+aesni_xts_encrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$96,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+.Loop_enc1_8:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_enc1_8	
+	aesenclast	%xmm1,%xmm15
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	.Lxts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	.Lxts_enc_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	.Lxts_enc_grandloop
+
+.align	16
+.Lxts_enc_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesenc	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	.Lxts_enc_loop6_enter
+
+.align	16
+.Lxts_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lxts_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lxts_enc_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesenclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	.Lxts_enc_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+.Lxts_enc_short:
+	addq	$96,%rdx
+	jz	.Lxts_enc_done
+
+	cmpq	$32,%rdx
+	jb	.Lxts_enc_one
+	je	.Lxts_enc_two
+
+	cmpq	$64,%rdx
+	jb	.Lxts_enc_three
+	je	.Lxts_enc_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_encrypt6
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	movdqu	%xmm5,48(%rsi)
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.align	16
+.Lxts_enc_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_9:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_9	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	leaq	16(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.align	16
+.Lxts_enc_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.align	16
+.Lxts_enc_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.align	16
+.Lxts_enc_four:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_encrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.align	16
+.Lxts_enc_done:
+	andq	$15,%r9
+	jz	.Lxts_enc_ret
+	movq	%r9,%rdx
+
+.Lxts_enc_steal:
+	movzbl	(%rdi),%eax
+	movzbl	-16(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,-16(%rsi)
+	movb	%cl,0(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	.Lxts_enc_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	-16(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_10:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_10	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,-16(%rsi)
+
+.Lxts_enc_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lxts_enc_epilogue:
+	retq
+.size	aesni_xts_encrypt,.-aesni_xts_encrypt
+.globl	aesni_xts_decrypt
+.type	aesni_xts_decrypt,@function
+.align	16
+aesni_xts_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$96,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+.Loop_enc1_11:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_enc1_11	
+	aesenclast	%xmm1,%xmm15
+	xorl	%eax,%eax
+	testq	$15,%rdx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%rdx
+
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	.Lxts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	.Lxts_dec_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	.Lxts_dec_grandloop
+
+.align	16
+.Lxts_dec_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesdec	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesdec	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	.Lxts_dec_loop6_enter
+
+.align	16
+.Lxts_dec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+.Lxts_dec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lxts_dec_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesdeclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdeclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdeclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	.Lxts_dec_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+.Lxts_dec_short:
+	addq	$96,%rdx
+	jz	.Lxts_dec_done
+
+	cmpq	$32,%rdx
+	jb	.Lxts_dec_one
+	je	.Lxts_dec_two
+
+	cmpq	$64,%rdx
+	jb	.Lxts_dec_three
+	je	.Lxts_dec_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_decrypt6
+
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	pxor	%xmm14,%xmm14
+	movdqu	%xmm5,48(%rsi)
+	pcmpgtd	%xmm15,%xmm14
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	pshufd	$19,%xmm14,%xmm11
+	andq	$15,%r9
+	jz	.Lxts_dec_ret
+
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm11
+	pxor	%xmm15,%xmm11
+	jmp	.Lxts_dec_done2
+
+.align	16
+.Lxts_dec_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_12:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_12	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	movdqa	%xmm12,%xmm11
+	leaq	16(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.align	16
+.Lxts_dec_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm13,%xmm11
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.align	16
+.Lxts_dec_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.align	16
+.Lxts_dec_four:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movups	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movups	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_decrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm14,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.align	16
+.Lxts_dec_done:
+	andq	$15,%r9
+	jz	.Lxts_dec_ret
+.Lxts_dec_done2:
+	movq	%r9,%rdx
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rdi),%xmm2
+	xorps	%xmm11,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_13:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_13	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm11,%xmm2
+	movups	%xmm2,(%rsi)
+
+.Lxts_dec_steal:
+	movzbl	16(%rdi),%eax
+	movzbl	(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,(%rsi)
+	movb	%cl,16(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	.Lxts_dec_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_14:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_14	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,(%rsi)
+
+.Lxts_dec_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lxts_dec_epilogue:
+	retq
+.size	aesni_xts_decrypt,.-aesni_xts_decrypt
+.globl	aesni_cbc_encrypt
+.type	aesni_cbc_encrypt,@function
+.align	16
+aesni_cbc_encrypt:
+	testq	%rdx,%rdx
+	jz	.Lcbc_ret
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	testl	%r9d,%r9d
+	jz	.Lcbc_decrypt
+
+	movups	(%r8),%xmm2
+	movl	%r10d,%eax
+	cmpq	$16,%rdx
+	jb	.Lcbc_enc_tail
+	subq	$16,%rdx
+	jmp	.Lcbc_enc_loop
+.align	16
+.Lcbc_enc_loop:
+	movups	(%rdi),%xmm3
+	leaq	16(%rdi),%rdi
+
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	xorps	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	xorps	%xmm3,%xmm2
+.Loop_enc1_15:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_15	
+	aesenclast	%xmm1,%xmm2
+	movl	%r10d,%eax
+	movq	%r11,%rcx
+	movups	%xmm2,0(%rsi)
+	leaq	16(%rsi),%rsi
+	subq	$16,%rdx
+	jnc	.Lcbc_enc_loop
+	addq	$16,%rdx
+	jnz	.Lcbc_enc_tail
+	movups	%xmm2,(%r8)
+	jmp	.Lcbc_ret
+
+.Lcbc_enc_tail:
+	movq	%rdx,%rcx
+	xchgq	%rdi,%rsi
+.long	0x9066A4F3	
+	movl	$16,%ecx
+	subq	%rdx,%rcx
+	xorl	%eax,%eax
+.long	0x9066AAF3	
+	leaq	-16(%rdi),%rdi
+	movl	%r10d,%eax
+	movq	%rdi,%rsi
+	movq	%r11,%rcx
+	xorq	%rdx,%rdx
+	jmp	.Lcbc_enc_loop	
+
+.align	16
+.Lcbc_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$16,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r8),%xmm9
+	movl	%r10d,%eax
+	cmpq	$112,%rdx
+	jbe	.Lcbc_dec_tail
+	shrl	$1,%r10d
+	subq	$112,%rdx
+	movl	%r10d,%eax
+	movaps	%xmm9,(%rsp)
+	jmp	.Lcbc_dec_loop8_enter
+.align	16
+.Lcbc_dec_loop8:
+	movaps	%xmm0,(%rsp)
+	movups	%xmm9,(%rsi)
+	leaq	16(%rsi),%rsi
+.Lcbc_dec_loop8_enter:
+	movups	(%rcx),%xmm0
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	16(%rcx),%xmm1
+
+	leaq	32(%rcx),%rcx
+	movdqu	32(%rdi),%xmm4
+	xorps	%xmm0,%xmm2
+	movdqu	48(%rdi),%xmm5
+	xorps	%xmm0,%xmm3
+	movdqu	64(%rdi),%xmm6
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	movdqu	80(%rdi),%xmm7
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqu	96(%rdi),%xmm8
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqu	112(%rdi),%xmm9
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+
+	call	.Ldec_loop8_enter
+
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm1
+	xorps	%xmm0,%xmm8
+	movups	112(%rdi),%xmm0
+	xorps	%xmm1,%xmm9
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm7,80(%rsi)
+	leaq	128(%rdi),%rdi
+	movups	%xmm8,96(%rsi)
+	leaq	112(%rsi),%rsi
+	subq	$128,%rdx
+	ja	.Lcbc_dec_loop8
+
+	movaps	%xmm9,%xmm2
+	movaps	%xmm0,%xmm9
+	addq	$112,%rdx
+	jle	.Lcbc_dec_tail_collected
+	movups	%xmm2,(%rsi)
+	leal	1(%r10,%r10,1),%eax
+	leaq	16(%rsi),%rsi
+.Lcbc_dec_tail:
+	movups	(%rdi),%xmm2
+	movaps	%xmm2,%xmm8
+	cmpq	$16,%rdx
+	jbe	.Lcbc_dec_one
+
+	movups	16(%rdi),%xmm3
+	movaps	%xmm3,%xmm7
+	cmpq	$32,%rdx
+	jbe	.Lcbc_dec_two
+
+	movups	32(%rdi),%xmm4
+	movaps	%xmm4,%xmm6
+	cmpq	$48,%rdx
+	jbe	.Lcbc_dec_three
+
+	movups	48(%rdi),%xmm5
+	cmpq	$64,%rdx
+	jbe	.Lcbc_dec_four
+
+	movups	64(%rdi),%xmm6
+	cmpq	$80,%rdx
+	jbe	.Lcbc_dec_five
+
+	movups	80(%rdi),%xmm7
+	cmpq	$96,%rdx
+	jbe	.Lcbc_dec_six
+
+	movups	96(%rdi),%xmm8
+	movaps	%xmm9,(%rsp)
+	call	_aesni_decrypt8
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm9
+	xorps	%xmm0,%xmm8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movaps	%xmm8,%xmm2
+	subq	$112,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_16:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_16	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm9,%xmm2
+	movaps	%xmm8,%xmm9
+	subq	$16,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	movaps	%xmm7,%xmm9
+	movaps	%xmm3,%xmm2
+	leaq	16(%rsi),%rsi
+	subq	$32,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_three:
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	movaps	%xmm6,%xmm9
+	movaps	%xmm4,%xmm2
+	leaq	32(%rsi),%rsi
+	subq	$48,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_four:
+	call	_aesni_decrypt4
+	xorps	%xmm9,%xmm2
+	movups	48(%rdi),%xmm9
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm6,%xmm5
+	movups	%xmm4,32(%rsi)
+	movaps	%xmm5,%xmm2
+	leaq	48(%rsi),%rsi
+	subq	$64,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm9
+	xorps	%xmm1,%xmm6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	movaps	%xmm6,%xmm2
+	subq	$80,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_six:
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm0
+	xorps	%xmm1,%xmm6
+	movups	80(%rdi),%xmm9
+	xorps	%xmm0,%xmm7
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	movaps	%xmm7,%xmm2
+	subq	$96,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.align	16
+.Lcbc_dec_tail_collected:
+	andq	$15,%rdx
+	movups	%xmm9,(%r8)
+	jnz	.Lcbc_dec_tail_partial
+	movups	%xmm2,(%rsi)
+	jmp	.Lcbc_dec_ret
+.align	16
+.Lcbc_dec_tail_partial:
+	movaps	%xmm2,(%rsp)
+	movq	$16,%rcx
+	movq	%rsi,%rdi
+	subq	%rdx,%rcx
+	leaq	(%rsp),%rsi
+.long	0x9066A4F3	
+
+.Lcbc_dec_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lcbc_ret:
+	retq
+.size	aesni_cbc_encrypt,.-aesni_cbc_encrypt
+.globl	aesni_set_decrypt_key
+.type	aesni_set_decrypt_key,@function
+.align	16
+aesni_set_decrypt_key:
+	endbr64
+	subq	$8,%rsp
+	call	__aesni_set_encrypt_key
+	shll	$4,%esi
+	testl	%eax,%eax
+	jnz	.Ldec_key_ret
+	leaq	16(%rdx,%rsi,1),%rdi
+
+	movups	(%rdx),%xmm0
+	movups	(%rdi),%xmm1
+	movups	%xmm0,(%rdi)
+	movups	%xmm1,(%rdx)
+	leaq	16(%rdx),%rdx
+	leaq	-16(%rdi),%rdi
+
+.Ldec_key_inverse:
+	movups	(%rdx),%xmm0
+	movups	(%rdi),%xmm1
+	aesimc	%xmm0,%xmm0
+	aesimc	%xmm1,%xmm1
+	leaq	16(%rdx),%rdx
+	leaq	-16(%rdi),%rdi
+	movups	%xmm0,16(%rdi)
+	movups	%xmm1,-16(%rdx)
+	cmpq	%rdx,%rdi
+	ja	.Ldec_key_inverse
+
+	movups	(%rdx),%xmm0
+	aesimc	%xmm0,%xmm0
+	movups	%xmm0,(%rdi)
+.Ldec_key_ret:
+	addq	$8,%rsp
+	retq
+.LSEH_end_set_decrypt_key:
+.size	aesni_set_decrypt_key,.-aesni_set_decrypt_key
+.globl	aesni_set_encrypt_key
+.type	aesni_set_encrypt_key,@function
+.align	16
+aesni_set_encrypt_key:
+	endbr64
+__aesni_set_encrypt_key:
+	subq	$8,%rsp
+	movq	$-1,%rax
+	testq	%rdi,%rdi
+	jz	.Lenc_key_ret
+	testq	%rdx,%rdx
+	jz	.Lenc_key_ret
+
+	movups	(%rdi),%xmm0
+	xorps	%xmm4,%xmm4
+	leaq	16(%rdx),%rax
+	cmpl	$256,%esi
+	je	.L14rounds
+	cmpl	$192,%esi
+	je	.L12rounds
+	cmpl	$128,%esi
+	jne	.Lbad_keybits
+
+.L10rounds:
+	movl	$9,%esi
+	movups	%xmm0,(%rdx)
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	.Lkey_expansion_128_cold
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$64,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$128,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$27,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$54,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	movups	%xmm0,(%rax)
+	movl	%esi,80(%rax)
+	xorl	%eax,%eax
+	jmp	.Lenc_key_ret
+
+.align	16
+.L12rounds:
+	movq	16(%rdi),%xmm2
+	movl	$11,%esi
+	movups	%xmm0,(%rdx)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	.Lkey_expansion_192a_cold
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$128,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	movups	%xmm0,(%rax)
+	movl	%esi,48(%rax)
+	xorq	%rax,%rax
+	jmp	.Lenc_key_ret
+
+.align	16
+.L14rounds:
+	movups	16(%rdi),%xmm2
+	movl	$13,%esi
+	leaq	16(%rax),%rax
+	movups	%xmm0,(%rdx)
+	movups	%xmm2,16(%rdx)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	.Lkey_expansion_256a_cold
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	movups	%xmm0,(%rax)
+	movl	%esi,16(%rax)
+	xorq	%rax,%rax
+	jmp	.Lenc_key_ret
+
+.align	16
+.Lbad_keybits:
+	movq	$-2,%rax
+.Lenc_key_ret:
+	addq	$8,%rsp
+	retq
+.LSEH_end_set_encrypt_key:
+
+.align	16
+.Lkey_expansion_128:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_128_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.align	16
+.Lkey_expansion_192a:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_192a_cold:
+	movaps	%xmm2,%xmm5
+.Lkey_expansion_192b_warm:
+	shufps	$16,%xmm0,%xmm4
+	movdqa	%xmm2,%xmm3
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	pslldq	$4,%xmm3
+	xorps	%xmm4,%xmm0
+	pshufd	$85,%xmm1,%xmm1
+	pxor	%xmm3,%xmm2
+	pxor	%xmm1,%xmm0
+	pshufd	$255,%xmm0,%xmm3
+	pxor	%xmm3,%xmm2
+	retq
+
+.align	16
+.Lkey_expansion_192b:
+	movaps	%xmm0,%xmm3
+	shufps	$68,%xmm0,%xmm5
+	movups	%xmm5,(%rax)
+	shufps	$78,%xmm2,%xmm3
+	movups	%xmm3,16(%rax)
+	leaq	32(%rax),%rax
+	jmp	.Lkey_expansion_192b_warm
+
+.align	16
+.Lkey_expansion_256a:
+	movups	%xmm2,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_256a_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.align	16
+.Lkey_expansion_256b:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+
+	shufps	$16,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$140,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$170,%xmm1,%xmm1
+	xorps	%xmm1,%xmm2
+	retq
+.size	aesni_set_encrypt_key,.-aesni_set_encrypt_key
+.size	__aesni_set_encrypt_key,.-__aesni_set_encrypt_key
+.section	.rodata
+.align	64
+.Lbswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.Lincrement32:
+.long	6,6,6,0
+.Lincrement64:
+.long	1,0,0,0
+.Lxts_magic:
+.long	0x87,0,1,0
+.align	64
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aesni-macosx-x86_64.S b/crypto/aes/aesni-macosx-x86_64.S
new file mode 100644
index 0000000..3327fc1
--- /dev/null
+++ b/crypto/aes/aesni-macosx-x86_64.S
@@ -0,0 +1,2558 @@
+#include "x86_arch.h"
+.text	
+.globl	_aesni_encrypt
+
+.p2align	4
+_aesni_encrypt:
+	movups	(%rdi),%xmm2
+	movl	240(%rdx),%eax
+	movups	(%rdx),%xmm0
+	movups	16(%rdx),%xmm1
+	leaq	32(%rdx),%rdx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_1:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rdx),%xmm1
+	leaq	16(%rdx),%rdx
+	jnz	L$oop_enc1_1	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	retq
+
+
+.globl	_aesni_decrypt
+
+.p2align	4
+_aesni_decrypt:
+	movups	(%rdi),%xmm2
+	movl	240(%rdx),%eax
+	movups	(%rdx),%xmm0
+	movups	16(%rdx),%xmm1
+	leaq	32(%rdx),%rdx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_2:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rdx),%xmm1
+	leaq	16(%rdx),%rdx
+	jnz	L$oop_dec1_2	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	retq
+
+
+.p2align	4
+_aesni_encrypt3:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+L$enc_loop3:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	L$enc_loop3
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	retq
+
+
+.p2align	4
+_aesni_decrypt3:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+L$dec_loop3:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	L$dec_loop3
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	retq
+
+
+.p2align	4
+_aesni_encrypt4:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+L$enc_loop4:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	L$enc_loop4
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	retq
+
+
+.p2align	4
+_aesni_decrypt4:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+L$dec_loop4:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	L$dec_loop4
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	retq
+
+
+.p2align	4
+_aesni_encrypt6:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm7
+	jmp	L$enc_loop6_enter
+.p2align	4
+L$enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+L$enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	L$enc_loop6
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	retq
+
+
+.p2align	4
+_aesni_decrypt6:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm7
+	jmp	L$dec_loop6_enter
+.p2align	4
+L$dec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+L$dec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	L$dec_loop6
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	retq
+
+
+.p2align	4
+_aesni_encrypt8:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	L$enc_loop8_enter
+.p2align	4
+L$enc_loop8:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+L$enc_loop8_enter:
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	L$enc_loop8
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	aesenclast	%xmm0,%xmm8
+	aesenclast	%xmm0,%xmm9
+	retq
+
+
+.p2align	4
+_aesni_decrypt8:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	L$dec_loop8_enter
+.p2align	4
+L$dec_loop8:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+L$dec_loop8_enter:
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	L$dec_loop8
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	aesdeclast	%xmm0,%xmm8
+	aesdeclast	%xmm0,%xmm9
+	retq
+
+.globl	_aesni_ecb_encrypt
+
+.p2align	4
+_aesni_ecb_encrypt:
+	andq	$-16,%rdx
+	jz	L$ecb_ret
+
+	movl	240(%rcx),%eax
+	movups	(%rcx),%xmm0
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	testl	%r8d,%r8d
+	jz	L$ecb_decrypt
+
+	cmpq	$128,%rdx
+	jb	L$ecb_enc_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	L$ecb_enc_loop8_enter
+.p2align	4
+L$ecb_enc_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+L$ecb_enc_loop8_enter:
+
+	call	_aesni_encrypt8
+
+	subq	$128,%rdx
+	jnc	L$ecb_enc_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	L$ecb_ret
+
+L$ecb_enc_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	L$ecb_enc_one
+	movups	16(%rdi),%xmm3
+	je	L$ecb_enc_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	L$ecb_enc_three
+	movups	48(%rdi),%xmm5
+	je	L$ecb_enc_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	L$ecb_enc_five
+	movups	80(%rdi),%xmm7
+	je	L$ecb_enc_six
+	movdqu	96(%rdi),%xmm8
+	call	_aesni_encrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_3:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_3	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_three:
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_four:
+	call	_aesni_encrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_enc_six:
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	jmp	L$ecb_ret
+
+.p2align	4
+L$ecb_decrypt:
+	cmpq	$128,%rdx
+	jb	L$ecb_dec_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	L$ecb_dec_loop8_enter
+.p2align	4
+L$ecb_dec_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+L$ecb_dec_loop8_enter:
+
+	call	_aesni_decrypt8
+
+	movups	(%r11),%xmm0
+	subq	$128,%rdx
+	jnc	L$ecb_dec_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	L$ecb_ret
+
+L$ecb_dec_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	L$ecb_dec_one
+	movups	16(%rdi),%xmm3
+	je	L$ecb_dec_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	L$ecb_dec_three
+	movups	48(%rdi),%xmm5
+	je	L$ecb_dec_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	L$ecb_dec_five
+	movups	80(%rdi),%xmm7
+	je	L$ecb_dec_six
+	movups	96(%rdi),%xmm8
+	movups	(%rcx),%xmm0
+	call	_aesni_decrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_4:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_dec1_4	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_three:
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_four:
+	call	_aesni_decrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	L$ecb_ret
+.p2align	4
+L$ecb_dec_six:
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+
+L$ecb_ret:
+	retq
+
+.globl	_aesni_ccm64_encrypt_blocks
+
+.p2align	4
+_aesni_ccm64_encrypt_blocks:
+	movl	240(%rcx),%eax
+	movdqu	(%r8),%xmm9
+	movdqa	L$increment64(%rip),%xmm6
+	movdqa	L$bswap_mask(%rip),%xmm7
+
+	shrl	$1,%eax
+	leaq	0(%rcx),%r11
+	movdqu	(%r9),%xmm3
+	movdqa	%xmm9,%xmm2
+	movl	%eax,%r10d
+.byte	102,68,15,56,0,207
+	jmp	L$ccm64_enc_outer
+.p2align	4
+L$ccm64_enc_outer:
+	movups	(%r11),%xmm0
+	movl	%r10d,%eax
+	movups	(%rdi),%xmm8
+
+	xorps	%xmm0,%xmm2
+	movups	16(%r11),%xmm1
+	xorps	%xmm8,%xmm0
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm3
+	movups	(%rcx),%xmm0
+
+L$ccm64_enc2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	L$ccm64_enc2_loop
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	paddq	%xmm6,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+
+	decq	%rdx
+	leaq	16(%rdi),%rdi
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+	jnz	L$ccm64_enc_outer
+
+	movups	%xmm3,(%r9)
+	retq
+
+.globl	_aesni_ccm64_decrypt_blocks
+
+.p2align	4
+_aesni_ccm64_decrypt_blocks:
+	movl	240(%rcx),%eax
+	movups	(%r8),%xmm9
+	movdqu	(%r9),%xmm3
+	movdqa	L$increment64(%rip),%xmm6
+	movdqa	L$bswap_mask(%rip),%xmm7
+
+	movaps	%xmm9,%xmm2
+	movl	%eax,%r10d
+	movq	%rcx,%r11
+.byte	102,68,15,56,0,207
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_5:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_5	
+	aesenclast	%xmm1,%xmm2
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	leaq	16(%rdi),%rdi
+	jmp	L$ccm64_dec_outer
+.p2align	4
+L$ccm64_dec_outer:
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movl	%r10d,%eax
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+
+	subq	$1,%rdx
+	jz	L$ccm64_dec_break
+
+	movups	(%r11),%xmm0
+	shrl	$1,%eax
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	(%rcx),%xmm0
+
+L$ccm64_dec2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	L$ccm64_dec2_loop
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	leaq	16(%rdi),%rdi
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	jmp	L$ccm64_dec_outer
+
+.p2align	4
+L$ccm64_dec_break:
+
+	movups	(%r11),%xmm0
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%r11
+	xorps	%xmm8,%xmm3
+L$oop_enc1_6:
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	movups	(%r11),%xmm1
+	leaq	16(%r11),%r11
+	jnz	L$oop_enc1_6	
+	aesenclast	%xmm1,%xmm3
+	movups	%xmm3,(%r9)
+	retq
+
+.globl	_aesni_ctr32_encrypt_blocks
+
+.p2align	4
+_aesni_ctr32_encrypt_blocks:
+	endbr64
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$32,%rsp
+	leaq	-8(%rax),%rbp
+	cmpq	$1,%rdx
+	je	L$ctr32_one_shortcut
+
+	movdqu	(%r8),%xmm14
+	movdqa	L$bswap_mask(%rip),%xmm15
+	xorl	%eax,%eax
+.byte	102,69,15,58,22,242,3
+.byte	102,68,15,58,34,240,3
+
+	movl	240(%rcx),%eax
+	bswapl	%r10d
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+.byte	102,69,15,58,34,226,0
+	leaq	3(%r10),%r11
+.byte	102,69,15,58,34,235,0
+	incl	%r10d
+.byte	102,69,15,58,34,226,1
+	incq	%r11
+.byte	102,69,15,58,34,235,1
+	incl	%r10d
+.byte	102,69,15,58,34,226,2
+	incq	%r11
+.byte	102,69,15,58,34,235,2
+	movdqa	%xmm12,0(%rsp)
+.byte	102,69,15,56,0,231
+	movdqa	%xmm13,16(%rsp)
+.byte	102,69,15,56,0,239
+
+	pshufd	$192,%xmm12,%xmm2
+	pshufd	$128,%xmm12,%xmm3
+	pshufd	$64,%xmm12,%xmm4
+	cmpq	$6,%rdx
+	jb	L$ctr32_tail
+	shrl	$1,%eax
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	subq	$6,%rdx
+	jmp	L$ctr32_loop6
+
+.p2align	4
+L$ctr32_loop6:
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm2
+	movups	(%r11),%xmm0
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm3
+	movups	16(%r11),%xmm1
+	pshufd	$64,%xmm13,%xmm7
+	por	%xmm14,%xmm4
+	por	%xmm14,%xmm5
+	xorps	%xmm0,%xmm2
+	por	%xmm14,%xmm6
+	por	%xmm14,%xmm7
+
+
+
+
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	movdqa	L$increment32(%rip),%xmm13
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	movdqa	(%rsp),%xmm12
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	jmp	L$ctr32_enc_loop6_enter
+.p2align	4
+L$ctr32_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+L$ctr32_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	L$ctr32_enc_loop6
+
+	aesenc	%xmm1,%xmm2
+	paddd	%xmm13,%xmm12
+	aesenc	%xmm1,%xmm3
+	paddd	16(%rsp),%xmm13
+	aesenc	%xmm1,%xmm4
+	movdqa	%xmm12,0(%rsp)
+	aesenc	%xmm1,%xmm5
+	movdqa	%xmm13,16(%rsp)
+	aesenc	%xmm1,%xmm6
+.byte	102,69,15,56,0,231
+	aesenc	%xmm1,%xmm7
+.byte	102,69,15,56,0,239
+
+	aesenclast	%xmm0,%xmm2
+	movups	(%rdi),%xmm8
+	aesenclast	%xmm0,%xmm3
+	movups	16(%rdi),%xmm9
+	aesenclast	%xmm0,%xmm4
+	movups	32(%rdi),%xmm10
+	aesenclast	%xmm0,%xmm5
+	movups	48(%rdi),%xmm11
+	aesenclast	%xmm0,%xmm6
+	movups	64(%rdi),%xmm1
+	aesenclast	%xmm0,%xmm7
+	movups	80(%rdi),%xmm0
+	leaq	96(%rdi),%rdi
+
+	xorps	%xmm2,%xmm8
+	pshufd	$192,%xmm12,%xmm2
+	xorps	%xmm3,%xmm9
+	pshufd	$128,%xmm12,%xmm3
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	pshufd	$64,%xmm12,%xmm4
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	xorps	%xmm7,%xmm0
+	movups	%xmm1,64(%rsi)
+	movups	%xmm0,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movl	%r10d,%eax
+	subq	$6,%rdx
+	jnc	L$ctr32_loop6
+
+	addq	$6,%rdx
+	jz	L$ctr32_done
+	movq	%r11,%rcx
+	leal	1(%rax,%rax,1),%eax
+
+L$ctr32_tail:
+	por	%xmm14,%xmm2
+	movups	(%rdi),%xmm8
+	cmpq	$2,%rdx
+	jb	L$ctr32_one
+
+	por	%xmm14,%xmm3
+	movups	16(%rdi),%xmm9
+	je	L$ctr32_two
+
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm4
+	movups	32(%rdi),%xmm10
+	cmpq	$4,%rdx
+	jb	L$ctr32_three
+
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm5
+	movups	48(%rdi),%xmm11
+	je	L$ctr32_four
+
+	por	%xmm14,%xmm6
+	xorps	%xmm7,%xmm7
+
+	call	_aesni_encrypt6
+
+	movups	64(%rdi),%xmm1
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	movups	%xmm1,64(%rsi)
+	jmp	L$ctr32_done
+
+.p2align	4
+L$ctr32_one_shortcut:
+	movups	(%r8),%xmm2
+	movups	(%rdi),%xmm8
+	movl	240(%rcx),%eax
+L$ctr32_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_7:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_7	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm2,%xmm8
+	movups	%xmm8,(%rsi)
+	jmp	L$ctr32_done
+
+.p2align	4
+L$ctr32_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	movups	%xmm9,16(%rsi)
+	jmp	L$ctr32_done
+
+.p2align	4
+L$ctr32_three:
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	movups	%xmm10,32(%rsi)
+	jmp	L$ctr32_done
+
+.p2align	4
+L$ctr32_four:
+	call	_aesni_encrypt4
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	movups	%xmm11,48(%rsi)
+
+L$ctr32_done:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+L$ctr32_ret:
+	retq
+
+.globl	_aesni_xts_encrypt
+
+.p2align	4
+_aesni_xts_encrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$96,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+L$oop_enc1_8:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	L$oop_enc1_8	
+	aesenclast	%xmm1,%xmm15
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	L$xts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	L$xts_enc_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	L$xts_enc_grandloop
+
+.p2align	4
+L$xts_enc_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesenc	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	L$xts_enc_loop6_enter
+
+.p2align	4
+L$xts_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+L$xts_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	L$xts_enc_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesenclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	L$xts_enc_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+L$xts_enc_short:
+	addq	$96,%rdx
+	jz	L$xts_enc_done
+
+	cmpq	$32,%rdx
+	jb	L$xts_enc_one
+	je	L$xts_enc_two
+
+	cmpq	$64,%rdx
+	jb	L$xts_enc_three
+	je	L$xts_enc_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_encrypt6
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	movdqu	%xmm5,48(%rsi)
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	jmp	L$xts_enc_done
+
+.p2align	4
+L$xts_enc_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_9:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_9	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	leaq	16(%rsi),%rsi
+	jmp	L$xts_enc_done
+
+.p2align	4
+L$xts_enc_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	L$xts_enc_done
+
+.p2align	4
+L$xts_enc_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	L$xts_enc_done
+
+.p2align	4
+L$xts_enc_four:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_encrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	L$xts_enc_done
+
+.p2align	4
+L$xts_enc_done:
+	andq	$15,%r9
+	jz	L$xts_enc_ret
+	movq	%r9,%rdx
+
+L$xts_enc_steal:
+	movzbl	(%rdi),%eax
+	movzbl	-16(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,-16(%rsi)
+	movb	%cl,0(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	L$xts_enc_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	-16(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_enc1_10:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_10	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,-16(%rsi)
+
+L$xts_enc_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+L$xts_enc_epilogue:
+	retq
+
+.globl	_aesni_xts_decrypt
+
+.p2align	4
+_aesni_xts_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$96,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+L$oop_enc1_11:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	L$oop_enc1_11	
+	aesenclast	%xmm1,%xmm15
+	xorl	%eax,%eax
+	testq	$15,%rdx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%rdx
+
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	L$xts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	L$xts_dec_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	L$xts_dec_grandloop
+
+.p2align	4
+L$xts_dec_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesdec	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesdec	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	L$xts_dec_loop6_enter
+
+.p2align	4
+L$xts_dec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+L$xts_dec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	L$xts_dec_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesdeclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdeclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdeclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	L$xts_dec_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+L$xts_dec_short:
+	addq	$96,%rdx
+	jz	L$xts_dec_done
+
+	cmpq	$32,%rdx
+	jb	L$xts_dec_one
+	je	L$xts_dec_two
+
+	cmpq	$64,%rdx
+	jb	L$xts_dec_three
+	je	L$xts_dec_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_decrypt6
+
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	pxor	%xmm14,%xmm14
+	movdqu	%xmm5,48(%rsi)
+	pcmpgtd	%xmm15,%xmm14
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	pshufd	$19,%xmm14,%xmm11
+	andq	$15,%r9
+	jz	L$xts_dec_ret
+
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm11
+	pxor	%xmm15,%xmm11
+	jmp	L$xts_dec_done2
+
+.p2align	4
+L$xts_dec_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_12:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_dec1_12	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	movdqa	%xmm12,%xmm11
+	leaq	16(%rsi),%rsi
+	jmp	L$xts_dec_done
+
+.p2align	4
+L$xts_dec_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm13,%xmm11
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	L$xts_dec_done
+
+.p2align	4
+L$xts_dec_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	L$xts_dec_done
+
+.p2align	4
+L$xts_dec_four:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movups	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movups	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_decrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm14,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	L$xts_dec_done
+
+.p2align	4
+L$xts_dec_done:
+	andq	$15,%r9
+	jz	L$xts_dec_ret
+L$xts_dec_done2:
+	movq	%r9,%rdx
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rdi),%xmm2
+	xorps	%xmm11,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_13:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_dec1_13	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm11,%xmm2
+	movups	%xmm2,(%rsi)
+
+L$xts_dec_steal:
+	movzbl	16(%rdi),%eax
+	movzbl	(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,(%rsi)
+	movb	%cl,16(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	L$xts_dec_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_14:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_dec1_14	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,(%rsi)
+
+L$xts_dec_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+L$xts_dec_epilogue:
+	retq
+
+.globl	_aesni_cbc_encrypt
+
+.p2align	4
+_aesni_cbc_encrypt:
+	testq	%rdx,%rdx
+	jz	L$cbc_ret
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	testl	%r9d,%r9d
+	jz	L$cbc_decrypt
+
+	movups	(%r8),%xmm2
+	movl	%r10d,%eax
+	cmpq	$16,%rdx
+	jb	L$cbc_enc_tail
+	subq	$16,%rdx
+	jmp	L$cbc_enc_loop
+.p2align	4
+L$cbc_enc_loop:
+	movups	(%rdi),%xmm3
+	leaq	16(%rdi),%rdi
+
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	xorps	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	xorps	%xmm3,%xmm2
+L$oop_enc1_15:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_enc1_15	
+	aesenclast	%xmm1,%xmm2
+	movl	%r10d,%eax
+	movq	%r11,%rcx
+	movups	%xmm2,0(%rsi)
+	leaq	16(%rsi),%rsi
+	subq	$16,%rdx
+	jnc	L$cbc_enc_loop
+	addq	$16,%rdx
+	jnz	L$cbc_enc_tail
+	movups	%xmm2,(%r8)
+	jmp	L$cbc_ret
+
+L$cbc_enc_tail:
+	movq	%rdx,%rcx
+	xchgq	%rdi,%rsi
+.long	0x9066A4F3	
+	movl	$16,%ecx
+	subq	%rdx,%rcx
+	xorl	%eax,%eax
+.long	0x9066AAF3	
+	leaq	-16(%rdi),%rdi
+	movl	%r10d,%eax
+	movq	%rdi,%rsi
+	movq	%r11,%rcx
+	xorq	%rdx,%rdx
+	jmp	L$cbc_enc_loop	
+
+.p2align	4
+L$cbc_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$16,%rsp
+	leaq	-8(%rax),%rbp
+	movups	(%r8),%xmm9
+	movl	%r10d,%eax
+	cmpq	$112,%rdx
+	jbe	L$cbc_dec_tail
+	shrl	$1,%r10d
+	subq	$112,%rdx
+	movl	%r10d,%eax
+	movaps	%xmm9,(%rsp)
+	jmp	L$cbc_dec_loop8_enter
+.p2align	4
+L$cbc_dec_loop8:
+	movaps	%xmm0,(%rsp)
+	movups	%xmm9,(%rsi)
+	leaq	16(%rsi),%rsi
+L$cbc_dec_loop8_enter:
+	movups	(%rcx),%xmm0
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	16(%rcx),%xmm1
+
+	leaq	32(%rcx),%rcx
+	movdqu	32(%rdi),%xmm4
+	xorps	%xmm0,%xmm2
+	movdqu	48(%rdi),%xmm5
+	xorps	%xmm0,%xmm3
+	movdqu	64(%rdi),%xmm6
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	movdqu	80(%rdi),%xmm7
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqu	96(%rdi),%xmm8
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqu	112(%rdi),%xmm9
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+
+	call	L$dec_loop8_enter
+
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm1
+	xorps	%xmm0,%xmm8
+	movups	112(%rdi),%xmm0
+	xorps	%xmm1,%xmm9
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm7,80(%rsi)
+	leaq	128(%rdi),%rdi
+	movups	%xmm8,96(%rsi)
+	leaq	112(%rsi),%rsi
+	subq	$128,%rdx
+	ja	L$cbc_dec_loop8
+
+	movaps	%xmm9,%xmm2
+	movaps	%xmm0,%xmm9
+	addq	$112,%rdx
+	jle	L$cbc_dec_tail_collected
+	movups	%xmm2,(%rsi)
+	leal	1(%r10,%r10,1),%eax
+	leaq	16(%rsi),%rsi
+L$cbc_dec_tail:
+	movups	(%rdi),%xmm2
+	movaps	%xmm2,%xmm8
+	cmpq	$16,%rdx
+	jbe	L$cbc_dec_one
+
+	movups	16(%rdi),%xmm3
+	movaps	%xmm3,%xmm7
+	cmpq	$32,%rdx
+	jbe	L$cbc_dec_two
+
+	movups	32(%rdi),%xmm4
+	movaps	%xmm4,%xmm6
+	cmpq	$48,%rdx
+	jbe	L$cbc_dec_three
+
+	movups	48(%rdi),%xmm5
+	cmpq	$64,%rdx
+	jbe	L$cbc_dec_four
+
+	movups	64(%rdi),%xmm6
+	cmpq	$80,%rdx
+	jbe	L$cbc_dec_five
+
+	movups	80(%rdi),%xmm7
+	cmpq	$96,%rdx
+	jbe	L$cbc_dec_six
+
+	movups	96(%rdi),%xmm8
+	movaps	%xmm9,(%rsp)
+	call	_aesni_decrypt8
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm9
+	xorps	%xmm0,%xmm8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movaps	%xmm8,%xmm2
+	subq	$112,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+L$oop_dec1_16:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	L$oop_dec1_16	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm9,%xmm2
+	movaps	%xmm8,%xmm9
+	subq	$16,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	movaps	%xmm7,%xmm9
+	movaps	%xmm3,%xmm2
+	leaq	16(%rsi),%rsi
+	subq	$32,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_three:
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	movaps	%xmm6,%xmm9
+	movaps	%xmm4,%xmm2
+	leaq	32(%rsi),%rsi
+	subq	$48,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_four:
+	call	_aesni_decrypt4
+	xorps	%xmm9,%xmm2
+	movups	48(%rdi),%xmm9
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm6,%xmm5
+	movups	%xmm4,32(%rsi)
+	movaps	%xmm5,%xmm2
+	leaq	48(%rsi),%rsi
+	subq	$64,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm9
+	xorps	%xmm1,%xmm6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	movaps	%xmm6,%xmm2
+	subq	$80,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_six:
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm0
+	xorps	%xmm1,%xmm6
+	movups	80(%rdi),%xmm9
+	xorps	%xmm0,%xmm7
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	movaps	%xmm7,%xmm2
+	subq	$96,%rdx
+	jmp	L$cbc_dec_tail_collected
+.p2align	4
+L$cbc_dec_tail_collected:
+	andq	$15,%rdx
+	movups	%xmm9,(%r8)
+	jnz	L$cbc_dec_tail_partial
+	movups	%xmm2,(%rsi)
+	jmp	L$cbc_dec_ret
+.p2align	4
+L$cbc_dec_tail_partial:
+	movaps	%xmm2,(%rsp)
+	movq	$16,%rcx
+	movq	%rsi,%rdi
+	subq	%rdx,%rcx
+	leaq	(%rsp),%rsi
+.long	0x9066A4F3	
+
+L$cbc_dec_ret:
+	leaq	(%rbp),%rsp
+	popq	%rbp
+L$cbc_ret:
+	retq
+
+.globl	_aesni_set_decrypt_key
+
+.p2align	4
+_aesni_set_decrypt_key:
+	subq	$8,%rsp
+	call	__aesni_set_encrypt_key
+	shll	$4,%esi
+	testl	%eax,%eax
+	jnz	L$dec_key_ret
+	leaq	16(%rdx,%rsi,1),%rdi
+
+	movups	(%rdx),%xmm0
+	movups	(%rdi),%xmm1
+	movups	%xmm0,(%rdi)
+	movups	%xmm1,(%rdx)
+	leaq	16(%rdx),%rdx
+	leaq	-16(%rdi),%rdi
+
+L$dec_key_inverse:
+	movups	(%rdx),%xmm0
+	movups	(%rdi),%xmm1
+	aesimc	%xmm0,%xmm0
+	aesimc	%xmm1,%xmm1
+	leaq	16(%rdx),%rdx
+	leaq	-16(%rdi),%rdi
+	movups	%xmm0,16(%rdi)
+	movups	%xmm1,-16(%rdx)
+	cmpq	%rdx,%rdi
+	ja	L$dec_key_inverse
+
+	movups	(%rdx),%xmm0
+	aesimc	%xmm0,%xmm0
+	movups	%xmm0,(%rdi)
+L$dec_key_ret:
+	addq	$8,%rsp
+	retq
+L$SEH_end_set_decrypt_key:
+
+.globl	_aesni_set_encrypt_key
+
+.p2align	4
+_aesni_set_encrypt_key:
+__aesni_set_encrypt_key:
+	subq	$8,%rsp
+	movq	$-1,%rax
+	testq	%rdi,%rdi
+	jz	L$enc_key_ret
+	testq	%rdx,%rdx
+	jz	L$enc_key_ret
+
+	movups	(%rdi),%xmm0
+	xorps	%xmm4,%xmm4
+	leaq	16(%rdx),%rax
+	cmpl	$256,%esi
+	je	L$14rounds
+	cmpl	$192,%esi
+	je	L$12rounds
+	cmpl	$128,%esi
+	jne	L$bad_keybits
+
+L$10rounds:
+	movl	$9,%esi
+	movups	%xmm0,(%rdx)
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	L$key_expansion_128_cold
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$64,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$128,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$27,%xmm0,%xmm1
+	call	L$key_expansion_128
+	aeskeygenassist	$54,%xmm0,%xmm1
+	call	L$key_expansion_128
+	movups	%xmm0,(%rax)
+	movl	%esi,80(%rax)
+	xorl	%eax,%eax
+	jmp	L$enc_key_ret
+
+.p2align	4
+L$12rounds:
+	movq	16(%rdi),%xmm2
+	movl	$11,%esi
+	movups	%xmm0,(%rdx)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	L$key_expansion_192a_cold
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	L$key_expansion_192b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	L$key_expansion_192a
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	L$key_expansion_192b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	L$key_expansion_192a
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	L$key_expansion_192b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	L$key_expansion_192a
+	aeskeygenassist	$128,%xmm2,%xmm1
+	call	L$key_expansion_192b
+	movups	%xmm0,(%rax)
+	movl	%esi,48(%rax)
+	xorq	%rax,%rax
+	jmp	L$enc_key_ret
+
+.p2align	4
+L$14rounds:
+	movups	16(%rdi),%xmm2
+	movl	$13,%esi
+	leaq	16(%rax),%rax
+	movups	%xmm0,(%rdx)
+	movups	%xmm2,16(%rdx)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	L$key_expansion_256a_cold
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	L$key_expansion_256b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	L$key_expansion_256a
+	movups	%xmm0,(%rax)
+	movl	%esi,16(%rax)
+	xorq	%rax,%rax
+	jmp	L$enc_key_ret
+
+.p2align	4
+L$bad_keybits:
+	movq	$-2,%rax
+L$enc_key_ret:
+	addq	$8,%rsp
+	retq
+L$SEH_end_set_encrypt_key:
+
+.p2align	4
+L$key_expansion_128:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+L$key_expansion_128_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.p2align	4
+L$key_expansion_192a:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+L$key_expansion_192a_cold:
+	movaps	%xmm2,%xmm5
+L$key_expansion_192b_warm:
+	shufps	$16,%xmm0,%xmm4
+	movdqa	%xmm2,%xmm3
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	pslldq	$4,%xmm3
+	xorps	%xmm4,%xmm0
+	pshufd	$85,%xmm1,%xmm1
+	pxor	%xmm3,%xmm2
+	pxor	%xmm1,%xmm0
+	pshufd	$255,%xmm0,%xmm3
+	pxor	%xmm3,%xmm2
+	retq
+
+.p2align	4
+L$key_expansion_192b:
+	movaps	%xmm0,%xmm3
+	shufps	$68,%xmm0,%xmm5
+	movups	%xmm5,(%rax)
+	shufps	$78,%xmm2,%xmm3
+	movups	%xmm3,16(%rax)
+	leaq	32(%rax),%rax
+	jmp	L$key_expansion_192b_warm
+
+.p2align	4
+L$key_expansion_256a:
+	movups	%xmm2,(%rax)
+	leaq	16(%rax),%rax
+L$key_expansion_256a_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.p2align	4
+L$key_expansion_256b:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+
+	shufps	$16,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$140,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$170,%xmm1,%xmm1
+	xorps	%xmm1,%xmm2
+	retq
+
+
+.p2align	6
+L$bswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+L$increment32:
+.long	6,6,6,0
+L$increment64:
+.long	1,0,0,0
+L$xts_magic:
+.long	0x87,0,1,0
+
+.byte	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
diff --git a/crypto/aes/aesni-masm-x86_64.S b/crypto/aes/aesni-masm-x86_64.S
new file mode 100644
index 0000000..5a685fc
--- /dev/null
+++ b/crypto/aes/aesni-masm-x86_64.S
@@ -0,0 +1,3119 @@
+; 1 "crypto/aes/aesni-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/aes/aesni-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/aes/aesni-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+PUBLIC	aesni_encrypt
+
+ALIGN	16
+aesni_encrypt	PROC PUBLIC
+	movups	xmm2,XMMWORD PTR[rcx]
+	mov	eax,DWORD PTR[240+r8]
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[16+r8]
+	lea	r8,QWORD PTR[32+r8]
+	xorps	xmm2,xmm0
+$L$oop_enc1_1::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[r8]
+	lea	r8,QWORD PTR[16+r8]
+	jnz	$L$oop_enc1_1	
+	aesenclast	xmm2,xmm1
+	movups	XMMWORD PTR[rdx],xmm2
+	DB	0F3h,0C3h		;repret
+aesni_encrypt	ENDP
+
+PUBLIC	aesni_decrypt
+
+ALIGN	16
+aesni_decrypt	PROC PUBLIC
+	movups	xmm2,XMMWORD PTR[rcx]
+	mov	eax,DWORD PTR[240+r8]
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[16+r8]
+	lea	r8,QWORD PTR[32+r8]
+	xorps	xmm2,xmm0
+$L$oop_dec1_2::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[r8]
+	lea	r8,QWORD PTR[16+r8]
+	jnz	$L$oop_dec1_2	
+	aesdeclast	xmm2,xmm1
+	movups	XMMWORD PTR[rdx],xmm2
+	DB	0F3h,0C3h		;repret
+aesni_decrypt	ENDP
+
+ALIGN	16
+_aesni_encrypt3	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	xorps	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$enc_loop3::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$enc_loop3
+
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_encrypt3	ENDP
+
+ALIGN	16
+_aesni_decrypt3	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	xorps	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$dec_loop3::
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	dec	eax
+	aesdec	xmm4,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesdec	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$dec_loop3
+
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_decrypt3	ENDP
+
+ALIGN	16
+_aesni_encrypt4	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	xorps	xmm4,xmm0
+	xorps	xmm5,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$enc_loop4::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$enc_loop4
+
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_encrypt4	ENDP
+
+ALIGN	16
+_aesni_decrypt4	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	xorps	xmm4,xmm0
+	xorps	xmm5,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$dec_loop4::
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	dec	eax
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$dec_loop4
+
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_decrypt4	ENDP
+
+ALIGN	16
+_aesni_encrypt6	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	pxor	xmm3,xmm0
+	aesenc	xmm2,xmm1
+	pxor	xmm4,xmm0
+	aesenc	xmm3,xmm1
+	pxor	xmm5,xmm0
+	aesenc	xmm4,xmm1
+	pxor	xmm6,xmm0
+	aesenc	xmm5,xmm1
+	pxor	xmm7,xmm0
+	dec	eax
+	aesenc	xmm6,xmm1
+	movups	xmm0,XMMWORD PTR[rcx]
+	aesenc	xmm7,xmm1
+	jmp	$L$enc_loop6_enter
+ALIGN	16
+$L$enc_loop6::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+$L$enc_loop6_enter::
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$enc_loop6
+
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
+	aesenclast	xmm6,xmm0
+	aesenclast	xmm7,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_encrypt6	ENDP
+
+ALIGN	16
+_aesni_decrypt6	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	pxor	xmm3,xmm0
+	aesdec	xmm2,xmm1
+	pxor	xmm4,xmm0
+	aesdec	xmm3,xmm1
+	pxor	xmm5,xmm0
+	aesdec	xmm4,xmm1
+	pxor	xmm6,xmm0
+	aesdec	xmm5,xmm1
+	pxor	xmm7,xmm0
+	dec	eax
+	aesdec	xmm6,xmm1
+	movups	xmm0,XMMWORD PTR[rcx]
+	aesdec	xmm7,xmm1
+	jmp	$L$dec_loop6_enter
+ALIGN	16
+$L$dec_loop6::
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	dec	eax
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+$L$dec_loop6_enter::
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$dec_loop6
+
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
+	aesdeclast	xmm6,xmm0
+	aesdeclast	xmm7,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_decrypt6	ENDP
+
+ALIGN	16
+_aesni_encrypt8	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	aesenc	xmm2,xmm1
+	pxor	xmm4,xmm0
+	aesenc	xmm3,xmm1
+	pxor	xmm5,xmm0
+	aesenc	xmm4,xmm1
+	pxor	xmm6,xmm0
+	aesenc	xmm5,xmm1
+	pxor	xmm7,xmm0
+	dec	eax
+	aesenc	xmm6,xmm1
+	pxor	xmm8,xmm0
+	aesenc	xmm7,xmm1
+	pxor	xmm9,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	jmp	$L$enc_loop8_enter
+ALIGN	16
+$L$enc_loop8::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+$L$enc_loop8_enter::
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	aesenc	xmm8,xmm0
+	aesenc	xmm9,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$enc_loop8
+
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	aesenc	xmm8,xmm1
+	aesenc	xmm9,xmm1
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	aesenclast	xmm4,xmm0
+	aesenclast	xmm5,xmm0
+	aesenclast	xmm6,xmm0
+	aesenclast	xmm7,xmm0
+	aesenclast	xmm8,xmm0
+	aesenclast	xmm9,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_encrypt8	ENDP
+
+ALIGN	16
+_aesni_decrypt8	PROC PRIVATE
+	movups	xmm0,XMMWORD PTR[rcx]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm0
+	aesdec	xmm2,xmm1
+	pxor	xmm4,xmm0
+	aesdec	xmm3,xmm1
+	pxor	xmm5,xmm0
+	aesdec	xmm4,xmm1
+	pxor	xmm6,xmm0
+	aesdec	xmm5,xmm1
+	pxor	xmm7,xmm0
+	dec	eax
+	aesdec	xmm6,xmm1
+	pxor	xmm8,xmm0
+	aesdec	xmm7,xmm1
+	pxor	xmm9,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	jmp	$L$dec_loop8_enter
+ALIGN	16
+$L$dec_loop8::
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	dec	eax
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+$L$dec_loop8_enter::
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	aesdec	xmm8,xmm0
+	aesdec	xmm9,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$dec_loop8
+
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
+	aesdeclast	xmm2,xmm0
+	aesdeclast	xmm3,xmm0
+	aesdeclast	xmm4,xmm0
+	aesdeclast	xmm5,xmm0
+	aesdeclast	xmm6,xmm0
+	aesdeclast	xmm7,xmm0
+	aesdeclast	xmm8,xmm0
+	aesdeclast	xmm9,xmm0
+	DB	0F3h,0C3h		;repret
+_aesni_decrypt8	ENDP
+PUBLIC	aesni_ecb_encrypt
+
+ALIGN	16
+aesni_ecb_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ecb_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+
+
+	and	rdx,-16
+	jz	$L$ecb_ret
+
+	mov	eax,DWORD PTR[240+rcx]
+	movups	xmm0,XMMWORD PTR[rcx]
+	mov	r11,rcx
+	mov	r10d,eax
+	test	r8d,r8d
+	jz	$L$ecb_decrypt
+
+	cmp	rdx,080h
+	jb	$L$ecb_enc_tail
+
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	movdqu	xmm9,XMMWORD PTR[112+rdi]
+	lea	rdi,QWORD PTR[128+rdi]
+	sub	rdx,080h
+	jmp	$L$ecb_enc_loop8_enter
+ALIGN	16
+$L$ecb_enc_loop8::
+	movups	XMMWORD PTR[rsi],xmm2
+	mov	rcx,r11
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	mov	eax,r10d
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	movups	XMMWORD PTR[96+rsi],xmm8
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	movups	XMMWORD PTR[112+rsi],xmm9
+	lea	rsi,QWORD PTR[128+rsi]
+	movdqu	xmm9,XMMWORD PTR[112+rdi]
+	lea	rdi,QWORD PTR[128+rdi]
+$L$ecb_enc_loop8_enter::
+
+	call	_aesni_encrypt8
+
+	sub	rdx,080h
+	jnc	$L$ecb_enc_loop8
+
+	movups	XMMWORD PTR[rsi],xmm2
+	mov	rcx,r11
+	movups	XMMWORD PTR[16+rsi],xmm3
+	mov	eax,r10d
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movups	XMMWORD PTR[96+rsi],xmm8
+	movups	XMMWORD PTR[112+rsi],xmm9
+	lea	rsi,QWORD PTR[128+rsi]
+	add	rdx,080h
+	jz	$L$ecb_ret
+
+$L$ecb_enc_tail::
+	movups	xmm2,XMMWORD PTR[rdi]
+	cmp	rdx,020h
+	jb	$L$ecb_enc_one
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	je	$L$ecb_enc_two
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	cmp	rdx,040h
+	jb	$L$ecb_enc_three
+	movups	xmm5,XMMWORD PTR[48+rdi]
+	je	$L$ecb_enc_four
+	movups	xmm6,XMMWORD PTR[64+rdi]
+	cmp	rdx,060h
+	jb	$L$ecb_enc_five
+	movups	xmm7,XMMWORD PTR[80+rdi]
+	je	$L$ecb_enc_six
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	call	_aesni_encrypt8
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movups	XMMWORD PTR[96+rsi],xmm8
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_one::
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_enc1_3::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_3	
+	aesenclast	xmm2,xmm1
+	movups	XMMWORD PTR[rsi],xmm2
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_two::
+	xorps	xmm4,xmm4
+	call	_aesni_encrypt3
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_three::
+	call	_aesni_encrypt3
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_four::
+	call	_aesni_encrypt4
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_five::
+	xorps	xmm7,xmm7
+	call	_aesni_encrypt6
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_enc_six::
+	call	_aesni_encrypt6
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	jmp	$L$ecb_ret
+
+ALIGN	16
+$L$ecb_decrypt::
+	cmp	rdx,080h
+	jb	$L$ecb_dec_tail
+
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	movdqu	xmm9,XMMWORD PTR[112+rdi]
+	lea	rdi,QWORD PTR[128+rdi]
+	sub	rdx,080h
+	jmp	$L$ecb_dec_loop8_enter
+ALIGN	16
+$L$ecb_dec_loop8::
+	movups	XMMWORD PTR[rsi],xmm2
+	mov	rcx,r11
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	mov	eax,r10d
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	movups	XMMWORD PTR[96+rsi],xmm8
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	movups	XMMWORD PTR[112+rsi],xmm9
+	lea	rsi,QWORD PTR[128+rsi]
+	movdqu	xmm9,XMMWORD PTR[112+rdi]
+	lea	rdi,QWORD PTR[128+rdi]
+$L$ecb_dec_loop8_enter::
+
+	call	_aesni_decrypt8
+
+	movups	xmm0,XMMWORD PTR[r11]
+	sub	rdx,080h
+	jnc	$L$ecb_dec_loop8
+
+	movups	XMMWORD PTR[rsi],xmm2
+	mov	rcx,r11
+	movups	XMMWORD PTR[16+rsi],xmm3
+	mov	eax,r10d
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movups	XMMWORD PTR[96+rsi],xmm8
+	movups	XMMWORD PTR[112+rsi],xmm9
+	lea	rsi,QWORD PTR[128+rsi]
+	add	rdx,080h
+	jz	$L$ecb_ret
+
+$L$ecb_dec_tail::
+	movups	xmm2,XMMWORD PTR[rdi]
+	cmp	rdx,020h
+	jb	$L$ecb_dec_one
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	je	$L$ecb_dec_two
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	cmp	rdx,040h
+	jb	$L$ecb_dec_three
+	movups	xmm5,XMMWORD PTR[48+rdi]
+	je	$L$ecb_dec_four
+	movups	xmm6,XMMWORD PTR[64+rdi]
+	cmp	rdx,060h
+	jb	$L$ecb_dec_five
+	movups	xmm7,XMMWORD PTR[80+rdi]
+	je	$L$ecb_dec_six
+	movups	xmm8,XMMWORD PTR[96+rdi]
+	movups	xmm0,XMMWORD PTR[rcx]
+	call	_aesni_decrypt8
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	movups	XMMWORD PTR[96+rsi],xmm8
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_one::
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_dec1_4::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_dec1_4	
+	aesdeclast	xmm2,xmm1
+	movups	XMMWORD PTR[rsi],xmm2
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_two::
+	xorps	xmm4,xmm4
+	call	_aesni_decrypt3
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_three::
+	call	_aesni_decrypt3
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_four::
+	call	_aesni_decrypt4
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_five::
+	xorps	xmm7,xmm7
+	call	_aesni_decrypt6
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	jmp	$L$ecb_ret
+ALIGN	16
+$L$ecb_dec_six::
+	call	_aesni_decrypt6
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+
+$L$ecb_ret::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ecb_encrypt::
+aesni_ecb_encrypt	ENDP
+PUBLIC	aesni_ccm64_encrypt_blocks
+
+ALIGN	16
+aesni_ccm64_encrypt_blocks	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ccm64_encrypt_blocks::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	lea	rsp,QWORD PTR[((-88))+rsp]
+	movaps	XMMWORD PTR[rsp],xmm6
+	movaps	XMMWORD PTR[16+rsp],xmm7
+	movaps	XMMWORD PTR[32+rsp],xmm8
+	movaps	XMMWORD PTR[48+rsp],xmm9
+$L$ccm64_enc_body::
+	mov	eax,DWORD PTR[240+rcx]
+	movdqu	xmm9,XMMWORD PTR[r8]
+	movdqa	xmm6,XMMWORD PTR[$L$increment64]
+	movdqa	xmm7,XMMWORD PTR[$L$bswap_mask]
+
+	shr	eax,1
+	lea	r11,QWORD PTR[rcx]
+	movdqu	xmm3,XMMWORD PTR[r9]
+	movdqa	xmm2,xmm9
+	mov	r10d,eax
+DB	102,68,15,56,0,207
+	jmp	$L$ccm64_enc_outer
+ALIGN	16
+$L$ccm64_enc_outer::
+	movups	xmm0,XMMWORD PTR[r11]
+	mov	eax,r10d
+	movups	xmm8,XMMWORD PTR[rdi]
+
+	xorps	xmm2,xmm0
+	movups	xmm1,XMMWORD PTR[16+r11]
+	xorps	xmm0,xmm8
+	lea	rcx,QWORD PTR[32+r11]
+	xorps	xmm3,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$ccm64_enc2_loop::
+	aesenc	xmm2,xmm1
+	dec	eax
+	aesenc	xmm3,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm3,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$ccm64_enc2_loop
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	paddq	xmm9,xmm6
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+
+	dec	rdx
+	lea	rdi,QWORD PTR[16+rdi]
+	xorps	xmm8,xmm2
+	movdqa	xmm2,xmm9
+	movups	XMMWORD PTR[rsi],xmm8
+	lea	rsi,QWORD PTR[16+rsi]
+DB	102,15,56,0,215
+	jnz	$L$ccm64_enc_outer
+
+	movups	XMMWORD PTR[r9],xmm3
+	movaps	xmm6,XMMWORD PTR[rsp]
+	movaps	xmm7,XMMWORD PTR[16+rsp]
+	movaps	xmm8,XMMWORD PTR[32+rsp]
+	movaps	xmm9,XMMWORD PTR[48+rsp]
+	lea	rsp,QWORD PTR[88+rsp]
+$L$ccm64_enc_ret::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ccm64_encrypt_blocks::
+aesni_ccm64_encrypt_blocks	ENDP
+PUBLIC	aesni_ccm64_decrypt_blocks
+
+ALIGN	16
+aesni_ccm64_decrypt_blocks	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ccm64_decrypt_blocks::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	lea	rsp,QWORD PTR[((-88))+rsp]
+	movaps	XMMWORD PTR[rsp],xmm6
+	movaps	XMMWORD PTR[16+rsp],xmm7
+	movaps	XMMWORD PTR[32+rsp],xmm8
+	movaps	XMMWORD PTR[48+rsp],xmm9
+$L$ccm64_dec_body::
+	mov	eax,DWORD PTR[240+rcx]
+	movups	xmm9,XMMWORD PTR[r8]
+	movdqu	xmm3,XMMWORD PTR[r9]
+	movdqa	xmm6,XMMWORD PTR[$L$increment64]
+	movdqa	xmm7,XMMWORD PTR[$L$bswap_mask]
+
+	movaps	xmm2,xmm9
+	mov	r10d,eax
+	mov	r11,rcx
+DB	102,68,15,56,0,207
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_enc1_5::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_5	
+	aesenclast	xmm2,xmm1
+	movups	xmm8,XMMWORD PTR[rdi]
+	paddq	xmm9,xmm6
+	lea	rdi,QWORD PTR[16+rdi]
+	jmp	$L$ccm64_dec_outer
+ALIGN	16
+$L$ccm64_dec_outer::
+	xorps	xmm8,xmm2
+	movdqa	xmm2,xmm9
+	mov	eax,r10d
+	movups	XMMWORD PTR[rsi],xmm8
+	lea	rsi,QWORD PTR[16+rsi]
+DB	102,15,56,0,215
+
+	sub	rdx,1
+	jz	$L$ccm64_dec_break
+
+	movups	xmm0,XMMWORD PTR[r11]
+	shr	eax,1
+	movups	xmm1,XMMWORD PTR[16+r11]
+	xorps	xmm8,xmm0
+	lea	rcx,QWORD PTR[32+r11]
+	xorps	xmm2,xmm0
+	xorps	xmm3,xmm8
+	movups	xmm0,XMMWORD PTR[rcx]
+
+$L$ccm64_dec2_loop::
+	aesenc	xmm2,xmm1
+	dec	eax
+	aesenc	xmm3,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm3,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$ccm64_dec2_loop
+	movups	xmm8,XMMWORD PTR[rdi]
+	paddq	xmm9,xmm6
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	lea	rdi,QWORD PTR[16+rdi]
+	aesenclast	xmm2,xmm0
+	aesenclast	xmm3,xmm0
+	jmp	$L$ccm64_dec_outer
+
+ALIGN	16
+$L$ccm64_dec_break::
+
+	movups	xmm0,XMMWORD PTR[r11]
+	movups	xmm1,XMMWORD PTR[16+r11]
+	xorps	xmm8,xmm0
+	lea	r11,QWORD PTR[32+r11]
+	xorps	xmm3,xmm8
+$L$oop_enc1_6::
+	aesenc	xmm3,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[r11]
+	lea	r11,QWORD PTR[16+r11]
+	jnz	$L$oop_enc1_6	
+	aesenclast	xmm3,xmm1
+	movups	XMMWORD PTR[r9],xmm3
+	movaps	xmm6,XMMWORD PTR[rsp]
+	movaps	xmm7,XMMWORD PTR[16+rsp]
+	movaps	xmm8,XMMWORD PTR[32+rsp]
+	movaps	xmm9,XMMWORD PTR[48+rsp]
+	lea	rsp,QWORD PTR[88+rsp]
+$L$ccm64_dec_ret::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ccm64_decrypt_blocks::
+aesni_ccm64_decrypt_blocks	ENDP
+PUBLIC	aesni_ctr32_encrypt_blocks
+
+ALIGN	16
+aesni_ctr32_encrypt_blocks	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ctr32_encrypt_blocks::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+
+
+	endbr64
+	lea	rax,QWORD PTR[rsp]
+	push	rbp
+	sub	rsp,192
+	movaps	XMMWORD PTR[32+rsp],xmm6
+	movaps	XMMWORD PTR[48+rsp],xmm7
+	movaps	XMMWORD PTR[64+rsp],xmm8
+	movaps	XMMWORD PTR[80+rsp],xmm9
+	movaps	XMMWORD PTR[96+rsp],xmm10
+	movaps	XMMWORD PTR[112+rsp],xmm11
+	movaps	XMMWORD PTR[128+rsp],xmm12
+	movaps	XMMWORD PTR[144+rsp],xmm13
+	movaps	XMMWORD PTR[160+rsp],xmm14
+	movaps	XMMWORD PTR[176+rsp],xmm15
+$L$ctr32_body::
+	lea	rbp,QWORD PTR[((-8))+rax]
+	cmp	rdx,1
+	je	$L$ctr32_one_shortcut
+
+	movdqu	xmm14,XMMWORD PTR[r8]
+	movdqa	xmm15,XMMWORD PTR[$L$bswap_mask]
+	xor	eax,eax
+DB	102,69,15,58,22,242,3
+DB	102,68,15,58,34,240,3
+
+	mov	eax,DWORD PTR[240+rcx]
+	bswap	r10d
+	pxor	xmm12,xmm12
+	pxor	xmm13,xmm13
+DB	102,69,15,58,34,226,0
+	lea	r11,QWORD PTR[3+r10]
+DB	102,69,15,58,34,235,0
+	inc	r10d
+DB	102,69,15,58,34,226,1
+	inc	r11
+DB	102,69,15,58,34,235,1
+	inc	r10d
+DB	102,69,15,58,34,226,2
+	inc	r11
+DB	102,69,15,58,34,235,2
+	movdqa	XMMWORD PTR[rsp],xmm12
+DB	102,69,15,56,0,231
+	movdqa	XMMWORD PTR[16+rsp],xmm13
+DB	102,69,15,56,0,239
+
+	pshufd	xmm2,xmm12,192
+	pshufd	xmm3,xmm12,128
+	pshufd	xmm4,xmm12,64
+	cmp	rdx,6
+	jb	$L$ctr32_tail
+	shr	eax,1
+	mov	r11,rcx
+	mov	r10d,eax
+	sub	rdx,6
+	jmp	$L$ctr32_loop6
+
+ALIGN	16
+$L$ctr32_loop6::
+	pshufd	xmm5,xmm13,192
+	por	xmm2,xmm14
+	movups	xmm0,XMMWORD PTR[r11]
+	pshufd	xmm6,xmm13,128
+	por	xmm3,xmm14
+	movups	xmm1,XMMWORD PTR[16+r11]
+	pshufd	xmm7,xmm13,64
+	por	xmm4,xmm14
+	por	xmm5,xmm14
+	xorps	xmm2,xmm0
+	por	xmm6,xmm14
+	por	xmm7,xmm14
+
+
+
+
+	pxor	xmm3,xmm0
+	aesenc	xmm2,xmm1
+	lea	rcx,QWORD PTR[32+r11]
+	pxor	xmm4,xmm0
+	aesenc	xmm3,xmm1
+	movdqa	xmm13,XMMWORD PTR[$L$increment32]
+	pxor	xmm5,xmm0
+	aesenc	xmm4,xmm1
+	movdqa	xmm12,XMMWORD PTR[rsp]
+	pxor	xmm6,xmm0
+	aesenc	xmm5,xmm1
+	pxor	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	dec	eax
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	jmp	$L$ctr32_enc_loop6_enter
+ALIGN	16
+$L$ctr32_enc_loop6::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+$L$ctr32_enc_loop6_enter::
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$ctr32_enc_loop6
+
+	aesenc	xmm2,xmm1
+	paddd	xmm12,xmm13
+	aesenc	xmm3,xmm1
+	paddd	xmm13,XMMWORD PTR[16+rsp]
+	aesenc	xmm4,xmm1
+	movdqa	XMMWORD PTR[rsp],xmm12
+	aesenc	xmm5,xmm1
+	movdqa	XMMWORD PTR[16+rsp],xmm13
+	aesenc	xmm6,xmm1
+DB	102,69,15,56,0,231
+	aesenc	xmm7,xmm1
+DB	102,69,15,56,0,239
+
+	aesenclast	xmm2,xmm0
+	movups	xmm8,XMMWORD PTR[rdi]
+	aesenclast	xmm3,xmm0
+	movups	xmm9,XMMWORD PTR[16+rdi]
+	aesenclast	xmm4,xmm0
+	movups	xmm10,XMMWORD PTR[32+rdi]
+	aesenclast	xmm5,xmm0
+	movups	xmm11,XMMWORD PTR[48+rdi]
+	aesenclast	xmm6,xmm0
+	movups	xmm1,XMMWORD PTR[64+rdi]
+	aesenclast	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[80+rdi]
+	lea	rdi,QWORD PTR[96+rdi]
+
+	xorps	xmm8,xmm2
+	pshufd	xmm2,xmm12,192
+	xorps	xmm9,xmm3
+	pshufd	xmm3,xmm12,128
+	movups	XMMWORD PTR[rsi],xmm8
+	xorps	xmm10,xmm4
+	pshufd	xmm4,xmm12,64
+	movups	XMMWORD PTR[16+rsi],xmm9
+	xorps	xmm11,xmm5
+	movups	XMMWORD PTR[32+rsi],xmm10
+	xorps	xmm1,xmm6
+	movups	XMMWORD PTR[48+rsi],xmm11
+	xorps	xmm0,xmm7
+	movups	XMMWORD PTR[64+rsi],xmm1
+	movups	XMMWORD PTR[80+rsi],xmm0
+	lea	rsi,QWORD PTR[96+rsi]
+	mov	eax,r10d
+	sub	rdx,6
+	jnc	$L$ctr32_loop6
+
+	add	rdx,6
+	jz	$L$ctr32_done
+	mov	rcx,r11
+	lea	eax,DWORD PTR[1+rax*1+rax]
+
+$L$ctr32_tail::
+	por	xmm2,xmm14
+	movups	xmm8,XMMWORD PTR[rdi]
+	cmp	rdx,2
+	jb	$L$ctr32_one
+
+	por	xmm3,xmm14
+	movups	xmm9,XMMWORD PTR[16+rdi]
+	je	$L$ctr32_two
+
+	pshufd	xmm5,xmm13,192
+	por	xmm4,xmm14
+	movups	xmm10,XMMWORD PTR[32+rdi]
+	cmp	rdx,4
+	jb	$L$ctr32_three
+
+	pshufd	xmm6,xmm13,128
+	por	xmm5,xmm14
+	movups	xmm11,XMMWORD PTR[48+rdi]
+	je	$L$ctr32_four
+
+	por	xmm6,xmm14
+	xorps	xmm7,xmm7
+
+	call	_aesni_encrypt6
+
+	movups	xmm1,XMMWORD PTR[64+rdi]
+	xorps	xmm8,xmm2
+	xorps	xmm9,xmm3
+	movups	XMMWORD PTR[rsi],xmm8
+	xorps	xmm10,xmm4
+	movups	XMMWORD PTR[16+rsi],xmm9
+	xorps	xmm11,xmm5
+	movups	XMMWORD PTR[32+rsi],xmm10
+	xorps	xmm1,xmm6
+	movups	XMMWORD PTR[48+rsi],xmm11
+	movups	XMMWORD PTR[64+rsi],xmm1
+	jmp	$L$ctr32_done
+
+ALIGN	16
+$L$ctr32_one_shortcut::
+	movups	xmm2,XMMWORD PTR[r8]
+	movups	xmm8,XMMWORD PTR[rdi]
+	mov	eax,DWORD PTR[240+rcx]
+$L$ctr32_one::
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_enc1_7::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_7	
+	aesenclast	xmm2,xmm1
+	xorps	xmm8,xmm2
+	movups	XMMWORD PTR[rsi],xmm8
+	jmp	$L$ctr32_done
+
+ALIGN	16
+$L$ctr32_two::
+	xorps	xmm4,xmm4
+	call	_aesni_encrypt3
+	xorps	xmm8,xmm2
+	xorps	xmm9,xmm3
+	movups	XMMWORD PTR[rsi],xmm8
+	movups	XMMWORD PTR[16+rsi],xmm9
+	jmp	$L$ctr32_done
+
+ALIGN	16
+$L$ctr32_three::
+	call	_aesni_encrypt3
+	xorps	xmm8,xmm2
+	xorps	xmm9,xmm3
+	movups	XMMWORD PTR[rsi],xmm8
+	xorps	xmm10,xmm4
+	movups	XMMWORD PTR[16+rsi],xmm9
+	movups	XMMWORD PTR[32+rsi],xmm10
+	jmp	$L$ctr32_done
+
+ALIGN	16
+$L$ctr32_four::
+	call	_aesni_encrypt4
+	xorps	xmm8,xmm2
+	xorps	xmm9,xmm3
+	movups	XMMWORD PTR[rsi],xmm8
+	xorps	xmm10,xmm4
+	movups	XMMWORD PTR[16+rsi],xmm9
+	xorps	xmm11,xmm5
+	movups	XMMWORD PTR[32+rsi],xmm10
+	movups	XMMWORD PTR[48+rsi],xmm11
+
+$L$ctr32_done::
+	movaps	xmm6,XMMWORD PTR[32+rsp]
+	movaps	xmm7,XMMWORD PTR[48+rsp]
+	movaps	xmm8,XMMWORD PTR[64+rsp]
+	movaps	xmm9,XMMWORD PTR[80+rsp]
+	movaps	xmm10,XMMWORD PTR[96+rsp]
+	movaps	xmm11,XMMWORD PTR[112+rsp]
+	movaps	xmm12,XMMWORD PTR[128+rsp]
+	movaps	xmm13,XMMWORD PTR[144+rsp]
+	movaps	xmm14,XMMWORD PTR[160+rsp]
+	movaps	xmm15,XMMWORD PTR[176+rsp]
+	lea	rsp,QWORD PTR[rbp]
+	pop	rbp
+$L$ctr32_ret::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ctr32_encrypt_blocks::
+aesni_ctr32_encrypt_blocks	ENDP
+PUBLIC	aesni_xts_encrypt
+
+ALIGN	16
+aesni_xts_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_xts_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	lea	rax,QWORD PTR[rsp]
+	push	rbp
+	sub	rsp,256
+	movaps	XMMWORD PTR[96+rsp],xmm6
+	movaps	XMMWORD PTR[112+rsp],xmm7
+	movaps	XMMWORD PTR[128+rsp],xmm8
+	movaps	XMMWORD PTR[144+rsp],xmm9
+	movaps	XMMWORD PTR[160+rsp],xmm10
+	movaps	XMMWORD PTR[176+rsp],xmm11
+	movaps	XMMWORD PTR[192+rsp],xmm12
+	movaps	XMMWORD PTR[208+rsp],xmm13
+	movaps	XMMWORD PTR[224+rsp],xmm14
+	movaps	XMMWORD PTR[240+rsp],xmm15
+$L$xts_enc_body::
+	lea	rbp,QWORD PTR[((-8))+rax]
+	movups	xmm15,XMMWORD PTR[r9]
+	mov	eax,DWORD PTR[240+r8]
+	mov	r10d,DWORD PTR[240+rcx]
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[16+r8]
+	lea	r8,QWORD PTR[32+r8]
+	xorps	xmm15,xmm0
+$L$oop_enc1_8::
+	aesenc	xmm15,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[r8]
+	lea	r8,QWORD PTR[16+r8]
+	jnz	$L$oop_enc1_8	
+	aesenclast	xmm15,xmm1
+	mov	r11,rcx
+	mov	eax,r10d
+	mov	r9,rdx
+	and	rdx,-16
+
+	movdqa	xmm8,XMMWORD PTR[$L$xts_magic]
+	pxor	xmm14,xmm14
+	pcmpgtd	xmm14,xmm15
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm10,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm11,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm12,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm13,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	sub	rdx,16*6
+	jc	$L$xts_enc_short
+
+	shr	eax,1
+	sub	eax,1
+	mov	r10d,eax
+	jmp	$L$xts_enc_grandloop
+
+ALIGN	16
+$L$xts_enc_grandloop::
+	pshufd	xmm9,xmm14,013h
+	movdqa	xmm14,xmm15
+	paddq	xmm15,xmm15
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	pand	xmm9,xmm8
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	pxor	xmm15,xmm9
+
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	pxor	xmm2,xmm10
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	pxor	xmm3,xmm11
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	pxor	xmm4,xmm12
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	lea	rdi,QWORD PTR[96+rdi]
+	pxor	xmm5,xmm13
+	movups	xmm0,XMMWORD PTR[r11]
+	pxor	xmm6,xmm14
+	pxor	xmm7,xmm15
+
+
+
+	movups	xmm1,XMMWORD PTR[16+r11]
+	pxor	xmm2,xmm0
+	pxor	xmm3,xmm0
+	movdqa	XMMWORD PTR[rsp],xmm10
+	aesenc	xmm2,xmm1
+	lea	rcx,QWORD PTR[32+r11]
+	pxor	xmm4,xmm0
+	movdqa	XMMWORD PTR[16+rsp],xmm11
+	aesenc	xmm3,xmm1
+	pxor	xmm5,xmm0
+	movdqa	XMMWORD PTR[32+rsp],xmm12
+	aesenc	xmm4,xmm1
+	pxor	xmm6,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm13
+	aesenc	xmm5,xmm1
+	pxor	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	dec	eax
+	movdqa	XMMWORD PTR[64+rsp],xmm14
+	aesenc	xmm6,xmm1
+	movdqa	XMMWORD PTR[80+rsp],xmm15
+	aesenc	xmm7,xmm1
+	pxor	xmm14,xmm14
+	pcmpgtd	xmm14,xmm15
+	jmp	$L$xts_enc_loop6_enter
+
+ALIGN	16
+$L$xts_enc_loop6::
+	aesenc	xmm2,xmm1
+	aesenc	xmm3,xmm1
+	dec	eax
+	aesenc	xmm4,xmm1
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+$L$xts_enc_loop6_enter::
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesenc	xmm2,xmm0
+	aesenc	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesenc	xmm4,xmm0
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$xts_enc_loop6
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	paddq	xmm15,xmm15
+	aesenc	xmm2,xmm1
+	pand	xmm9,xmm8
+	aesenc	xmm3,xmm1
+	pcmpgtd	xmm14,xmm15
+	aesenc	xmm4,xmm1
+	pxor	xmm15,xmm9
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm10,xmm15
+	paddq	xmm15,xmm15
+	aesenc	xmm2,xmm0
+	pand	xmm9,xmm8
+	aesenc	xmm3,xmm0
+	pcmpgtd	xmm14,xmm15
+	aesenc	xmm4,xmm0
+	pxor	xmm15,xmm9
+	aesenc	xmm5,xmm0
+	aesenc	xmm6,xmm0
+	aesenc	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[32+rcx]
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm11,xmm15
+	paddq	xmm15,xmm15
+	aesenc	xmm2,xmm1
+	pand	xmm9,xmm8
+	aesenc	xmm3,xmm1
+	pcmpgtd	xmm14,xmm15
+	aesenc	xmm4,xmm1
+	pxor	xmm15,xmm9
+	aesenc	xmm5,xmm1
+	aesenc	xmm6,xmm1
+	aesenc	xmm7,xmm1
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm12,xmm15
+	paddq	xmm15,xmm15
+	aesenclast	xmm2,xmm0
+	pand	xmm9,xmm8
+	aesenclast	xmm3,xmm0
+	pcmpgtd	xmm14,xmm15
+	aesenclast	xmm4,xmm0
+	pxor	xmm15,xmm9
+	aesenclast	xmm5,xmm0
+	aesenclast	xmm6,xmm0
+	aesenclast	xmm7,xmm0
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm13,xmm15
+	paddq	xmm15,xmm15
+	xorps	xmm2,XMMWORD PTR[rsp]
+	pand	xmm9,xmm8
+	xorps	xmm3,XMMWORD PTR[16+rsp]
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+
+	xorps	xmm4,XMMWORD PTR[32+rsp]
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,XMMWORD PTR[48+rsp]
+	movups	XMMWORD PTR[16+rsi],xmm3
+	xorps	xmm6,XMMWORD PTR[64+rsp]
+	movups	XMMWORD PTR[32+rsi],xmm4
+	xorps	xmm7,XMMWORD PTR[80+rsp]
+	movups	XMMWORD PTR[48+rsi],xmm5
+	mov	eax,r10d
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	lea	rsi,QWORD PTR[96+rsi]
+	sub	rdx,16*6
+	jnc	$L$xts_enc_grandloop
+
+	lea	eax,DWORD PTR[3+rax*1+rax]
+	mov	rcx,r11
+	mov	r10d,eax
+
+$L$xts_enc_short::
+	add	rdx,16*6
+	jz	$L$xts_enc_done
+
+	cmp	rdx,020h
+	jb	$L$xts_enc_one
+	je	$L$xts_enc_two
+
+	cmp	rdx,040h
+	jb	$L$xts_enc_three
+	je	$L$xts_enc_four
+
+	pshufd	xmm9,xmm14,013h
+	movdqa	xmm14,xmm15
+	paddq	xmm15,xmm15
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	pand	xmm9,xmm8
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	pxor	xmm15,xmm9
+
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	pxor	xmm2,xmm10
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	pxor	xmm3,xmm11
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	lea	rdi,QWORD PTR[80+rdi]
+	pxor	xmm4,xmm12
+	pxor	xmm5,xmm13
+	pxor	xmm6,xmm14
+
+	call	_aesni_encrypt6
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm15
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	movdqu	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,xmm13
+	movdqu	XMMWORD PTR[16+rsi],xmm3
+	xorps	xmm6,xmm14
+	movdqu	XMMWORD PTR[32+rsi],xmm4
+	movdqu	XMMWORD PTR[48+rsi],xmm5
+	movdqu	XMMWORD PTR[64+rsi],xmm6
+	lea	rsi,QWORD PTR[80+rsi]
+	jmp	$L$xts_enc_done
+
+ALIGN	16
+$L$xts_enc_one::
+	movups	xmm2,XMMWORD PTR[rdi]
+	lea	rdi,QWORD PTR[16+rdi]
+	xorps	xmm2,xmm10
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_enc1_9::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_9	
+	aesenclast	xmm2,xmm1
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm11
+	movups	XMMWORD PTR[rsi],xmm2
+	lea	rsi,QWORD PTR[16+rsi]
+	jmp	$L$xts_enc_done
+
+ALIGN	16
+$L$xts_enc_two::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	lea	rdi,QWORD PTR[32+rdi]
+	xorps	xmm2,xmm10
+	xorps	xmm3,xmm11
+
+	call	_aesni_encrypt3
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm12
+	xorps	xmm3,xmm11
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	lea	rsi,QWORD PTR[32+rsi]
+	jmp	$L$xts_enc_done
+
+ALIGN	16
+$L$xts_enc_three::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	lea	rdi,QWORD PTR[48+rdi]
+	xorps	xmm2,xmm10
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+
+	call	_aesni_encrypt3
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm13
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	lea	rsi,QWORD PTR[48+rsi]
+	jmp	$L$xts_enc_done
+
+ALIGN	16
+$L$xts_enc_four::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	xorps	xmm2,xmm10
+	movups	xmm5,XMMWORD PTR[48+rdi]
+	lea	rdi,QWORD PTR[64+rdi]
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	xorps	xmm5,xmm13
+
+	call	_aesni_encrypt4
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm15
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,xmm13
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	lea	rsi,QWORD PTR[64+rsi]
+	jmp	$L$xts_enc_done
+
+ALIGN	16
+$L$xts_enc_done::
+	and	r9,15
+	jz	$L$xts_enc_ret
+	mov	rdx,r9
+
+$L$xts_enc_steal::
+	movzx	eax,BYTE PTR[rdi]
+	movzx	ecx,BYTE PTR[((-16))+rsi]
+	lea	rdi,QWORD PTR[1+rdi]
+	mov	BYTE PTR[((-16))+rsi],al
+	mov	BYTE PTR[rsi],cl
+	lea	rsi,QWORD PTR[1+rsi]
+	sub	rdx,1
+	jnz	$L$xts_enc_steal
+
+	sub	rsi,r9
+	mov	rcx,r11
+	mov	eax,r10d
+
+	movups	xmm2,XMMWORD PTR[((-16))+rsi]
+	xorps	xmm2,xmm10
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_enc1_10::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_10	
+	aesenclast	xmm2,xmm1
+	xorps	xmm2,xmm10
+	movups	XMMWORD PTR[(-16)+rsi],xmm2
+
+$L$xts_enc_ret::
+	movaps	xmm6,XMMWORD PTR[96+rsp]
+	movaps	xmm7,XMMWORD PTR[112+rsp]
+	movaps	xmm8,XMMWORD PTR[128+rsp]
+	movaps	xmm9,XMMWORD PTR[144+rsp]
+	movaps	xmm10,XMMWORD PTR[160+rsp]
+	movaps	xmm11,XMMWORD PTR[176+rsp]
+	movaps	xmm12,XMMWORD PTR[192+rsp]
+	movaps	xmm13,XMMWORD PTR[208+rsp]
+	movaps	xmm14,XMMWORD PTR[224+rsp]
+	movaps	xmm15,XMMWORD PTR[240+rsp]
+	lea	rsp,QWORD PTR[rbp]
+	pop	rbp
+$L$xts_enc_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_xts_encrypt::
+aesni_xts_encrypt	ENDP
+PUBLIC	aesni_xts_decrypt
+
+ALIGN	16
+aesni_xts_decrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_xts_decrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	lea	rax,QWORD PTR[rsp]
+	push	rbp
+	sub	rsp,256
+	movaps	XMMWORD PTR[96+rsp],xmm6
+	movaps	XMMWORD PTR[112+rsp],xmm7
+	movaps	XMMWORD PTR[128+rsp],xmm8
+	movaps	XMMWORD PTR[144+rsp],xmm9
+	movaps	XMMWORD PTR[160+rsp],xmm10
+	movaps	XMMWORD PTR[176+rsp],xmm11
+	movaps	XMMWORD PTR[192+rsp],xmm12
+	movaps	XMMWORD PTR[208+rsp],xmm13
+	movaps	XMMWORD PTR[224+rsp],xmm14
+	movaps	XMMWORD PTR[240+rsp],xmm15
+$L$xts_dec_body::
+	lea	rbp,QWORD PTR[((-8))+rax]
+	movups	xmm15,XMMWORD PTR[r9]
+	mov	eax,DWORD PTR[240+r8]
+	mov	r10d,DWORD PTR[240+rcx]
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[16+r8]
+	lea	r8,QWORD PTR[32+r8]
+	xorps	xmm15,xmm0
+$L$oop_enc1_11::
+	aesenc	xmm15,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[r8]
+	lea	r8,QWORD PTR[16+r8]
+	jnz	$L$oop_enc1_11	
+	aesenclast	xmm15,xmm1
+	xor	eax,eax
+	test	rdx,15
+	setnz	al
+	shl	rax,4
+	sub	rdx,rax
+
+	mov	r11,rcx
+	mov	eax,r10d
+	mov	r9,rdx
+	and	rdx,-16
+
+	movdqa	xmm8,XMMWORD PTR[$L$xts_magic]
+	pxor	xmm14,xmm14
+	pcmpgtd	xmm14,xmm15
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm10,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm11,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm12,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm13,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm9,xmm8
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+	sub	rdx,16*6
+	jc	$L$xts_dec_short
+
+	shr	eax,1
+	sub	eax,1
+	mov	r10d,eax
+	jmp	$L$xts_dec_grandloop
+
+ALIGN	16
+$L$xts_dec_grandloop::
+	pshufd	xmm9,xmm14,013h
+	movdqa	xmm14,xmm15
+	paddq	xmm15,xmm15
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	pand	xmm9,xmm8
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	pxor	xmm15,xmm9
+
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	pxor	xmm2,xmm10
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	pxor	xmm3,xmm11
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	pxor	xmm4,xmm12
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	lea	rdi,QWORD PTR[96+rdi]
+	pxor	xmm5,xmm13
+	movups	xmm0,XMMWORD PTR[r11]
+	pxor	xmm6,xmm14
+	pxor	xmm7,xmm15
+
+
+
+	movups	xmm1,XMMWORD PTR[16+r11]
+	pxor	xmm2,xmm0
+	pxor	xmm3,xmm0
+	movdqa	XMMWORD PTR[rsp],xmm10
+	aesdec	xmm2,xmm1
+	lea	rcx,QWORD PTR[32+r11]
+	pxor	xmm4,xmm0
+	movdqa	XMMWORD PTR[16+rsp],xmm11
+	aesdec	xmm3,xmm1
+	pxor	xmm5,xmm0
+	movdqa	XMMWORD PTR[32+rsp],xmm12
+	aesdec	xmm4,xmm1
+	pxor	xmm6,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm13
+	aesdec	xmm5,xmm1
+	pxor	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	dec	eax
+	movdqa	XMMWORD PTR[64+rsp],xmm14
+	aesdec	xmm6,xmm1
+	movdqa	XMMWORD PTR[80+rsp],xmm15
+	aesdec	xmm7,xmm1
+	pxor	xmm14,xmm14
+	pcmpgtd	xmm14,xmm15
+	jmp	$L$xts_dec_loop6_enter
+
+ALIGN	16
+$L$xts_dec_loop6::
+	aesdec	xmm2,xmm1
+	aesdec	xmm3,xmm1
+	dec	eax
+	aesdec	xmm4,xmm1
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+$L$xts_dec_loop6_enter::
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	aesdec	xmm2,xmm0
+	aesdec	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	aesdec	xmm4,xmm0
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	jnz	$L$xts_dec_loop6
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	paddq	xmm15,xmm15
+	aesdec	xmm2,xmm1
+	pand	xmm9,xmm8
+	aesdec	xmm3,xmm1
+	pcmpgtd	xmm14,xmm15
+	aesdec	xmm4,xmm1
+	pxor	xmm15,xmm9
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm10,xmm15
+	paddq	xmm15,xmm15
+	aesdec	xmm2,xmm0
+	pand	xmm9,xmm8
+	aesdec	xmm3,xmm0
+	pcmpgtd	xmm14,xmm15
+	aesdec	xmm4,xmm0
+	pxor	xmm15,xmm9
+	aesdec	xmm5,xmm0
+	aesdec	xmm6,xmm0
+	aesdec	xmm7,xmm0
+	movups	xmm0,XMMWORD PTR[32+rcx]
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm11,xmm15
+	paddq	xmm15,xmm15
+	aesdec	xmm2,xmm1
+	pand	xmm9,xmm8
+	aesdec	xmm3,xmm1
+	pcmpgtd	xmm14,xmm15
+	aesdec	xmm4,xmm1
+	pxor	xmm15,xmm9
+	aesdec	xmm5,xmm1
+	aesdec	xmm6,xmm1
+	aesdec	xmm7,xmm1
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm12,xmm15
+	paddq	xmm15,xmm15
+	aesdeclast	xmm2,xmm0
+	pand	xmm9,xmm8
+	aesdeclast	xmm3,xmm0
+	pcmpgtd	xmm14,xmm15
+	aesdeclast	xmm4,xmm0
+	pxor	xmm15,xmm9
+	aesdeclast	xmm5,xmm0
+	aesdeclast	xmm6,xmm0
+	aesdeclast	xmm7,xmm0
+
+	pshufd	xmm9,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm13,xmm15
+	paddq	xmm15,xmm15
+	xorps	xmm2,XMMWORD PTR[rsp]
+	pand	xmm9,xmm8
+	xorps	xmm3,XMMWORD PTR[16+rsp]
+	pcmpgtd	xmm14,xmm15
+	pxor	xmm15,xmm9
+
+	xorps	xmm4,XMMWORD PTR[32+rsp]
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,XMMWORD PTR[48+rsp]
+	movups	XMMWORD PTR[16+rsi],xmm3
+	xorps	xmm6,XMMWORD PTR[64+rsp]
+	movups	XMMWORD PTR[32+rsi],xmm4
+	xorps	xmm7,XMMWORD PTR[80+rsp]
+	movups	XMMWORD PTR[48+rsi],xmm5
+	mov	eax,r10d
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	lea	rsi,QWORD PTR[96+rsi]
+	sub	rdx,16*6
+	jnc	$L$xts_dec_grandloop
+
+	lea	eax,DWORD PTR[3+rax*1+rax]
+	mov	rcx,r11
+	mov	r10d,eax
+
+$L$xts_dec_short::
+	add	rdx,16*6
+	jz	$L$xts_dec_done
+
+	cmp	rdx,020h
+	jb	$L$xts_dec_one
+	je	$L$xts_dec_two
+
+	cmp	rdx,040h
+	jb	$L$xts_dec_three
+	je	$L$xts_dec_four
+
+	pshufd	xmm9,xmm14,013h
+	movdqa	xmm14,xmm15
+	paddq	xmm15,xmm15
+	movdqu	xmm2,XMMWORD PTR[rdi]
+	pand	xmm9,xmm8
+	movdqu	xmm3,XMMWORD PTR[16+rdi]
+	pxor	xmm15,xmm9
+
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	pxor	xmm2,xmm10
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	pxor	xmm3,xmm11
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	lea	rdi,QWORD PTR[80+rdi]
+	pxor	xmm4,xmm12
+	pxor	xmm5,xmm13
+	pxor	xmm6,xmm14
+
+	call	_aesni_decrypt6
+
+	xorps	xmm2,xmm10
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	movdqu	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,xmm13
+	movdqu	XMMWORD PTR[16+rsi],xmm3
+	xorps	xmm6,xmm14
+	movdqu	XMMWORD PTR[32+rsi],xmm4
+	pxor	xmm14,xmm14
+	movdqu	XMMWORD PTR[48+rsi],xmm5
+	pcmpgtd	xmm14,xmm15
+	movdqu	XMMWORD PTR[64+rsi],xmm6
+	lea	rsi,QWORD PTR[80+rsi]
+	pshufd	xmm11,xmm14,013h
+	and	r9,15
+	jz	$L$xts_dec_ret
+
+	movdqa	xmm10,xmm15
+	paddq	xmm15,xmm15
+	pand	xmm11,xmm8
+	pxor	xmm11,xmm15
+	jmp	$L$xts_dec_done2
+
+ALIGN	16
+$L$xts_dec_one::
+	movups	xmm2,XMMWORD PTR[rdi]
+	lea	rdi,QWORD PTR[16+rdi]
+	xorps	xmm2,xmm10
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_dec1_12::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_dec1_12	
+	aesdeclast	xmm2,xmm1
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm11
+	movups	XMMWORD PTR[rsi],xmm2
+	movdqa	xmm11,xmm12
+	lea	rsi,QWORD PTR[16+rsi]
+	jmp	$L$xts_dec_done
+
+ALIGN	16
+$L$xts_dec_two::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	lea	rdi,QWORD PTR[32+rdi]
+	xorps	xmm2,xmm10
+	xorps	xmm3,xmm11
+
+	call	_aesni_decrypt3
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm12
+	xorps	xmm3,xmm11
+	movdqa	xmm11,xmm13
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	lea	rsi,QWORD PTR[32+rsi]
+	jmp	$L$xts_dec_done
+
+ALIGN	16
+$L$xts_dec_three::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	lea	rdi,QWORD PTR[48+rdi]
+	xorps	xmm2,xmm10
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+
+	call	_aesni_decrypt3
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm13
+	xorps	xmm3,xmm11
+	movdqa	xmm11,xmm15
+	xorps	xmm4,xmm12
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	lea	rsi,QWORD PTR[48+rsi]
+	jmp	$L$xts_dec_done
+
+ALIGN	16
+$L$xts_dec_four::
+	pshufd	xmm9,xmm14,013h
+	movdqa	xmm14,xmm15
+	paddq	xmm15,xmm15
+	movups	xmm2,XMMWORD PTR[rdi]
+	pand	xmm9,xmm8
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	pxor	xmm15,xmm9
+
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	xorps	xmm2,xmm10
+	movups	xmm5,XMMWORD PTR[48+rdi]
+	lea	rdi,QWORD PTR[64+rdi]
+	xorps	xmm3,xmm11
+	xorps	xmm4,xmm12
+	xorps	xmm5,xmm13
+
+	call	_aesni_decrypt4
+
+	xorps	xmm2,xmm10
+	movdqa	xmm10,xmm14
+	xorps	xmm3,xmm11
+	movdqa	xmm11,xmm15
+	xorps	xmm4,xmm12
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm5,xmm13
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	lea	rsi,QWORD PTR[64+rsi]
+	jmp	$L$xts_dec_done
+
+ALIGN	16
+$L$xts_dec_done::
+	and	r9,15
+	jz	$L$xts_dec_ret
+$L$xts_dec_done2::
+	mov	rdx,r9
+	mov	rcx,r11
+	mov	eax,r10d
+
+	movups	xmm2,XMMWORD PTR[rdi]
+	xorps	xmm2,xmm11
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_dec1_13::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_dec1_13	
+	aesdeclast	xmm2,xmm1
+	xorps	xmm2,xmm11
+	movups	XMMWORD PTR[rsi],xmm2
+
+$L$xts_dec_steal::
+	movzx	eax,BYTE PTR[16+rdi]
+	movzx	ecx,BYTE PTR[rsi]
+	lea	rdi,QWORD PTR[1+rdi]
+	mov	BYTE PTR[rsi],al
+	mov	BYTE PTR[16+rsi],cl
+	lea	rsi,QWORD PTR[1+rsi]
+	sub	rdx,1
+	jnz	$L$xts_dec_steal
+
+	sub	rsi,r9
+	mov	rcx,r11
+	mov	eax,r10d
+
+	movups	xmm2,XMMWORD PTR[rsi]
+	xorps	xmm2,xmm10
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_dec1_14::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_dec1_14	
+	aesdeclast	xmm2,xmm1
+	xorps	xmm2,xmm10
+	movups	XMMWORD PTR[rsi],xmm2
+
+$L$xts_dec_ret::
+	movaps	xmm6,XMMWORD PTR[96+rsp]
+	movaps	xmm7,XMMWORD PTR[112+rsp]
+	movaps	xmm8,XMMWORD PTR[128+rsp]
+	movaps	xmm9,XMMWORD PTR[144+rsp]
+	movaps	xmm10,XMMWORD PTR[160+rsp]
+	movaps	xmm11,XMMWORD PTR[176+rsp]
+	movaps	xmm12,XMMWORD PTR[192+rsp]
+	movaps	xmm13,XMMWORD PTR[208+rsp]
+	movaps	xmm14,XMMWORD PTR[224+rsp]
+	movaps	xmm15,XMMWORD PTR[240+rsp]
+	lea	rsp,QWORD PTR[rbp]
+	pop	rbp
+$L$xts_dec_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_xts_decrypt::
+aesni_xts_decrypt	ENDP
+PUBLIC	aesni_cbc_encrypt
+
+ALIGN	16
+aesni_cbc_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_cbc_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	test	rdx,rdx
+	jz	$L$cbc_ret
+
+	mov	r10d,DWORD PTR[240+rcx]
+	mov	r11,rcx
+	test	r9d,r9d
+	jz	$L$cbc_decrypt
+
+	movups	xmm2,XMMWORD PTR[r8]
+	mov	eax,r10d
+	cmp	rdx,16
+	jb	$L$cbc_enc_tail
+	sub	rdx,16
+	jmp	$L$cbc_enc_loop
+ALIGN	16
+$L$cbc_enc_loop::
+	movups	xmm3,XMMWORD PTR[rdi]
+	lea	rdi,QWORD PTR[16+rdi]
+
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	xorps	xmm3,xmm0
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm3
+$L$oop_enc1_15::
+	aesenc	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_enc1_15	
+	aesenclast	xmm2,xmm1
+	mov	eax,r10d
+	mov	rcx,r11
+	movups	XMMWORD PTR[rsi],xmm2
+	lea	rsi,QWORD PTR[16+rsi]
+	sub	rdx,16
+	jnc	$L$cbc_enc_loop
+	add	rdx,16
+	jnz	$L$cbc_enc_tail
+	movups	XMMWORD PTR[r8],xmm2
+	jmp	$L$cbc_ret
+
+$L$cbc_enc_tail::
+	mov	rcx,rdx
+	xchg	rsi,rdi
+	DD	09066A4F3h	
+	mov	ecx,16
+	sub	rcx,rdx
+	xor	eax,eax
+	DD	09066AAF3h	
+	lea	rdi,QWORD PTR[((-16))+rdi]
+	mov	eax,r10d
+	mov	rsi,rdi
+	mov	rcx,r11
+	xor	rdx,rdx
+	jmp	$L$cbc_enc_loop	
+
+ALIGN	16
+$L$cbc_decrypt::
+	lea	rax,QWORD PTR[rsp]
+	push	rbp
+	sub	rsp,80
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+$L$cbc_decrypt_body::
+	lea	rbp,QWORD PTR[((-8))+rax]
+	movups	xmm9,XMMWORD PTR[r8]
+	mov	eax,r10d
+	cmp	rdx,070h
+	jbe	$L$cbc_dec_tail
+	shr	r10d,1
+	sub	rdx,070h
+	mov	eax,r10d
+	movaps	XMMWORD PTR[rsp],xmm9
+	jmp	$L$cbc_dec_loop8_enter
+ALIGN	16
+$L$cbc_dec_loop8::
+	movaps	XMMWORD PTR[rsp],xmm0
+	movups	XMMWORD PTR[rsi],xmm9
+	lea	rsi,QWORD PTR[16+rsi]
+$L$cbc_dec_loop8_enter::
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm2,XMMWORD PTR[rdi]
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+
+	lea	rcx,QWORD PTR[32+rcx]
+	movdqu	xmm4,XMMWORD PTR[32+rdi]
+	xorps	xmm2,xmm0
+	movdqu	xmm5,XMMWORD PTR[48+rdi]
+	xorps	xmm3,xmm0
+	movdqu	xmm6,XMMWORD PTR[64+rdi]
+	aesdec	xmm2,xmm1
+	pxor	xmm4,xmm0
+	movdqu	xmm7,XMMWORD PTR[80+rdi]
+	aesdec	xmm3,xmm1
+	pxor	xmm5,xmm0
+	movdqu	xmm8,XMMWORD PTR[96+rdi]
+	aesdec	xmm4,xmm1
+	pxor	xmm6,xmm0
+	movdqu	xmm9,XMMWORD PTR[112+rdi]
+	aesdec	xmm5,xmm1
+	pxor	xmm7,xmm0
+	dec	eax
+	aesdec	xmm6,xmm1
+	pxor	xmm8,xmm0
+	aesdec	xmm7,xmm1
+	pxor	xmm9,xmm0
+	movups	xmm0,XMMWORD PTR[rcx]
+	aesdec	xmm8,xmm1
+	aesdec	xmm9,xmm1
+	movups	xmm1,XMMWORD PTR[16+rcx]
+
+	call	$L$dec_loop8_enter
+
+	movups	xmm1,XMMWORD PTR[rdi]
+	movups	xmm0,XMMWORD PTR[16+rdi]
+	xorps	xmm2,XMMWORD PTR[rsp]
+	xorps	xmm3,xmm1
+	movups	xmm1,XMMWORD PTR[32+rdi]
+	xorps	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[48+rdi]
+	xorps	xmm5,xmm1
+	movups	xmm1,XMMWORD PTR[64+rdi]
+	xorps	xmm6,xmm0
+	movups	xmm0,XMMWORD PTR[80+rdi]
+	xorps	xmm7,xmm1
+	movups	xmm1,XMMWORD PTR[96+rdi]
+	xorps	xmm8,xmm0
+	movups	xmm0,XMMWORD PTR[112+rdi]
+	xorps	xmm9,xmm1
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	mov	eax,r10d
+	movups	XMMWORD PTR[64+rsi],xmm6
+	mov	rcx,r11
+	movups	XMMWORD PTR[80+rsi],xmm7
+	lea	rdi,QWORD PTR[128+rdi]
+	movups	XMMWORD PTR[96+rsi],xmm8
+	lea	rsi,QWORD PTR[112+rsi]
+	sub	rdx,080h
+	ja	$L$cbc_dec_loop8
+
+	movaps	xmm2,xmm9
+	movaps	xmm9,xmm0
+	add	rdx,070h
+	jle	$L$cbc_dec_tail_collected
+	movups	XMMWORD PTR[rsi],xmm2
+	lea	eax,DWORD PTR[1+r10*1+r10]
+	lea	rsi,QWORD PTR[16+rsi]
+$L$cbc_dec_tail::
+	movups	xmm2,XMMWORD PTR[rdi]
+	movaps	xmm8,xmm2
+	cmp	rdx,010h
+	jbe	$L$cbc_dec_one
+
+	movups	xmm3,XMMWORD PTR[16+rdi]
+	movaps	xmm7,xmm3
+	cmp	rdx,020h
+	jbe	$L$cbc_dec_two
+
+	movups	xmm4,XMMWORD PTR[32+rdi]
+	movaps	xmm6,xmm4
+	cmp	rdx,030h
+	jbe	$L$cbc_dec_three
+
+	movups	xmm5,XMMWORD PTR[48+rdi]
+	cmp	rdx,040h
+	jbe	$L$cbc_dec_four
+
+	movups	xmm6,XMMWORD PTR[64+rdi]
+	cmp	rdx,050h
+	jbe	$L$cbc_dec_five
+
+	movups	xmm7,XMMWORD PTR[80+rdi]
+	cmp	rdx,060h
+	jbe	$L$cbc_dec_six
+
+	movups	xmm8,XMMWORD PTR[96+rdi]
+	movaps	XMMWORD PTR[rsp],xmm9
+	call	_aesni_decrypt8
+	movups	xmm1,XMMWORD PTR[rdi]
+	movups	xmm0,XMMWORD PTR[16+rdi]
+	xorps	xmm2,XMMWORD PTR[rsp]
+	xorps	xmm3,xmm1
+	movups	xmm1,XMMWORD PTR[32+rdi]
+	xorps	xmm4,xmm0
+	movups	xmm0,XMMWORD PTR[48+rdi]
+	xorps	xmm5,xmm1
+	movups	xmm1,XMMWORD PTR[64+rdi]
+	xorps	xmm6,xmm0
+	movups	xmm0,XMMWORD PTR[80+rdi]
+	xorps	xmm7,xmm1
+	movups	xmm9,XMMWORD PTR[96+rdi]
+	xorps	xmm8,xmm0
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	movups	XMMWORD PTR[80+rsi],xmm7
+	lea	rsi,QWORD PTR[96+rsi]
+	movaps	xmm2,xmm8
+	sub	rdx,070h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_one::
+	movups	xmm0,XMMWORD PTR[rcx]
+	movups	xmm1,XMMWORD PTR[16+rcx]
+	lea	rcx,QWORD PTR[32+rcx]
+	xorps	xmm2,xmm0
+$L$oop_dec1_16::
+	aesdec	xmm2,xmm1
+	dec	eax
+	movups	xmm1,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	jnz	$L$oop_dec1_16	
+	aesdeclast	xmm2,xmm1
+	xorps	xmm2,xmm9
+	movaps	xmm9,xmm8
+	sub	rdx,010h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_two::
+	xorps	xmm4,xmm4
+	call	_aesni_decrypt3
+	xorps	xmm2,xmm9
+	xorps	xmm3,xmm8
+	movups	XMMWORD PTR[rsi],xmm2
+	movaps	xmm9,xmm7
+	movaps	xmm2,xmm3
+	lea	rsi,QWORD PTR[16+rsi]
+	sub	rdx,020h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_three::
+	call	_aesni_decrypt3
+	xorps	xmm2,xmm9
+	xorps	xmm3,xmm8
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm4,xmm7
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movaps	xmm9,xmm6
+	movaps	xmm2,xmm4
+	lea	rsi,QWORD PTR[32+rsi]
+	sub	rdx,030h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_four::
+	call	_aesni_decrypt4
+	xorps	xmm2,xmm9
+	movups	xmm9,XMMWORD PTR[48+rdi]
+	xorps	xmm3,xmm8
+	movups	XMMWORD PTR[rsi],xmm2
+	xorps	xmm4,xmm7
+	movups	XMMWORD PTR[16+rsi],xmm3
+	xorps	xmm5,xmm6
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movaps	xmm2,xmm5
+	lea	rsi,QWORD PTR[48+rsi]
+	sub	rdx,040h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_five::
+	xorps	xmm7,xmm7
+	call	_aesni_decrypt6
+	movups	xmm1,XMMWORD PTR[16+rdi]
+	movups	xmm0,XMMWORD PTR[32+rdi]
+	xorps	xmm2,xmm9
+	xorps	xmm3,xmm8
+	xorps	xmm4,xmm1
+	movups	xmm1,XMMWORD PTR[48+rdi]
+	xorps	xmm5,xmm0
+	movups	xmm9,XMMWORD PTR[64+rdi]
+	xorps	xmm6,xmm1
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	lea	rsi,QWORD PTR[64+rsi]
+	movaps	xmm2,xmm6
+	sub	rdx,050h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_six::
+	call	_aesni_decrypt6
+	movups	xmm1,XMMWORD PTR[16+rdi]
+	movups	xmm0,XMMWORD PTR[32+rdi]
+	xorps	xmm2,xmm9
+	xorps	xmm3,xmm8
+	xorps	xmm4,xmm1
+	movups	xmm1,XMMWORD PTR[48+rdi]
+	xorps	xmm5,xmm0
+	movups	xmm0,XMMWORD PTR[64+rdi]
+	xorps	xmm6,xmm1
+	movups	xmm9,XMMWORD PTR[80+rdi]
+	xorps	xmm7,xmm0
+	movups	XMMWORD PTR[rsi],xmm2
+	movups	XMMWORD PTR[16+rsi],xmm3
+	movups	XMMWORD PTR[32+rsi],xmm4
+	movups	XMMWORD PTR[48+rsi],xmm5
+	movups	XMMWORD PTR[64+rsi],xmm6
+	lea	rsi,QWORD PTR[80+rsi]
+	movaps	xmm2,xmm7
+	sub	rdx,060h
+	jmp	$L$cbc_dec_tail_collected
+ALIGN	16
+$L$cbc_dec_tail_collected::
+	and	rdx,15
+	movups	XMMWORD PTR[r8],xmm9
+	jnz	$L$cbc_dec_tail_partial
+	movups	XMMWORD PTR[rsi],xmm2
+	jmp	$L$cbc_dec_ret
+ALIGN	16
+$L$cbc_dec_tail_partial::
+	movaps	XMMWORD PTR[rsp],xmm2
+	mov	rcx,16
+	mov	rdi,rsi
+	sub	rcx,rdx
+	lea	rsi,QWORD PTR[rsp]
+	DD	09066A4F3h	
+
+$L$cbc_dec_ret::
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	lea	rsp,QWORD PTR[rbp]
+	pop	rbp
+$L$cbc_ret::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_cbc_encrypt::
+aesni_cbc_encrypt	ENDP
+PUBLIC	aesni_set_decrypt_key
+
+ALIGN	16
+aesni_set_decrypt_key	PROC PUBLIC
+	sub	rsp,8
+	call	__aesni_set_encrypt_key
+	shl	edx,4
+	test	eax,eax
+	jnz	$L$dec_key_ret
+	lea	rcx,QWORD PTR[16+rdx*1+r8]
+
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[rcx]
+	movups	XMMWORD PTR[rcx],xmm0
+	movups	XMMWORD PTR[r8],xmm1
+	lea	r8,QWORD PTR[16+r8]
+	lea	rcx,QWORD PTR[((-16))+rcx]
+
+$L$dec_key_inverse::
+	movups	xmm0,XMMWORD PTR[r8]
+	movups	xmm1,XMMWORD PTR[rcx]
+	aesimc	xmm0,xmm0
+	aesimc	xmm1,xmm1
+	lea	r8,QWORD PTR[16+r8]
+	lea	rcx,QWORD PTR[((-16))+rcx]
+	movups	XMMWORD PTR[16+rcx],xmm0
+	movups	XMMWORD PTR[(-16)+r8],xmm1
+	cmp	rcx,r8
+	ja	$L$dec_key_inverse
+
+	movups	xmm0,XMMWORD PTR[r8]
+	aesimc	xmm0,xmm0
+	movups	XMMWORD PTR[rcx],xmm0
+$L$dec_key_ret::
+	add	rsp,8
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_set_decrypt_key::
+aesni_set_decrypt_key	ENDP
+PUBLIC	aesni_set_encrypt_key
+
+ALIGN	16
+aesni_set_encrypt_key	PROC PUBLIC
+__aesni_set_encrypt_key::
+	sub	rsp,8
+	mov	rax,-1
+	test	rcx,rcx
+	jz	$L$enc_key_ret
+	test	r8,r8
+	jz	$L$enc_key_ret
+
+	movups	xmm0,XMMWORD PTR[rcx]
+	xorps	xmm4,xmm4
+	lea	rax,QWORD PTR[16+r8]
+	cmp	edx,256
+	je	$L$14rounds
+	cmp	edx,192
+	je	$L$12rounds
+	cmp	edx,128
+	jne	$L$bad_keybits
+
+$L$10rounds::
+	mov	edx,9
+	movups	XMMWORD PTR[r8],xmm0
+	aeskeygenassist	xmm1,xmm0,01h
+	call	$L$key_expansion_128_cold
+	aeskeygenassist	xmm1,xmm0,02h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,04h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,08h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,010h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,020h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,040h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,080h
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,01bh
+	call	$L$key_expansion_128
+	aeskeygenassist	xmm1,xmm0,036h
+	call	$L$key_expansion_128
+	movups	XMMWORD PTR[rax],xmm0
+	mov	DWORD PTR[80+rax],edx
+	xor	eax,eax
+	jmp	$L$enc_key_ret
+
+ALIGN	16
+$L$12rounds::
+	movq	xmm2,QWORD PTR[16+rcx]
+	mov	edx,11
+	movups	XMMWORD PTR[r8],xmm0
+	aeskeygenassist	xmm1,xmm2,01h
+	call	$L$key_expansion_192a_cold
+	aeskeygenassist	xmm1,xmm2,02h
+	call	$L$key_expansion_192b
+	aeskeygenassist	xmm1,xmm2,04h
+	call	$L$key_expansion_192a
+	aeskeygenassist	xmm1,xmm2,08h
+	call	$L$key_expansion_192b
+	aeskeygenassist	xmm1,xmm2,010h
+	call	$L$key_expansion_192a
+	aeskeygenassist	xmm1,xmm2,020h
+	call	$L$key_expansion_192b
+	aeskeygenassist	xmm1,xmm2,040h
+	call	$L$key_expansion_192a
+	aeskeygenassist	xmm1,xmm2,080h
+	call	$L$key_expansion_192b
+	movups	XMMWORD PTR[rax],xmm0
+	mov	DWORD PTR[48+rax],edx
+	xor	rax,rax
+	jmp	$L$enc_key_ret
+
+ALIGN	16
+$L$14rounds::
+	movups	xmm2,XMMWORD PTR[16+rcx]
+	mov	edx,13
+	lea	rax,QWORD PTR[16+rax]
+	movups	XMMWORD PTR[r8],xmm0
+	movups	XMMWORD PTR[16+r8],xmm2
+	aeskeygenassist	xmm1,xmm2,01h
+	call	$L$key_expansion_256a_cold
+	aeskeygenassist	xmm1,xmm0,01h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,02h
+	call	$L$key_expansion_256a
+	aeskeygenassist	xmm1,xmm0,02h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,04h
+	call	$L$key_expansion_256a
+	aeskeygenassist	xmm1,xmm0,04h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,08h
+	call	$L$key_expansion_256a
+	aeskeygenassist	xmm1,xmm0,08h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,010h
+	call	$L$key_expansion_256a
+	aeskeygenassist	xmm1,xmm0,010h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,020h
+	call	$L$key_expansion_256a
+	aeskeygenassist	xmm1,xmm0,020h
+	call	$L$key_expansion_256b
+	aeskeygenassist	xmm1,xmm2,040h
+	call	$L$key_expansion_256a
+	movups	XMMWORD PTR[rax],xmm0
+	mov	DWORD PTR[16+rax],edx
+	xor	rax,rax
+	jmp	$L$enc_key_ret
+
+ALIGN	16
+$L$bad_keybits::
+	mov	rax,-2
+$L$enc_key_ret::
+	add	rsp,8
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_set_encrypt_key::
+
+ALIGN	16
+$L$key_expansion_128::
+	movups	XMMWORD PTR[rax],xmm0
+	lea	rax,QWORD PTR[16+rax]
+$L$key_expansion_128_cold::
+	shufps	xmm4,xmm0,16
+	xorps	xmm0,xmm4
+	shufps	xmm4,xmm0,140
+	xorps	xmm0,xmm4
+	shufps	xmm1,xmm1,255
+	xorps	xmm0,xmm1
+	DB	0F3h,0C3h		;repret
+
+ALIGN	16
+$L$key_expansion_192a::
+	movups	XMMWORD PTR[rax],xmm0
+	lea	rax,QWORD PTR[16+rax]
+$L$key_expansion_192a_cold::
+	movaps	xmm5,xmm2
+$L$key_expansion_192b_warm::
+	shufps	xmm4,xmm0,16
+	movdqa	xmm3,xmm2
+	xorps	xmm0,xmm4
+	shufps	xmm4,xmm0,140
+	pslldq	xmm3,4
+	xorps	xmm0,xmm4
+	pshufd	xmm1,xmm1,85
+	pxor	xmm2,xmm3
+	pxor	xmm0,xmm1
+	pshufd	xmm3,xmm0,255
+	pxor	xmm2,xmm3
+	DB	0F3h,0C3h		;repret
+
+ALIGN	16
+$L$key_expansion_192b::
+	movaps	xmm3,xmm0
+	shufps	xmm5,xmm0,68
+	movups	XMMWORD PTR[rax],xmm5
+	shufps	xmm3,xmm2,78
+	movups	XMMWORD PTR[16+rax],xmm3
+	lea	rax,QWORD PTR[32+rax]
+	jmp	$L$key_expansion_192b_warm
+
+ALIGN	16
+$L$key_expansion_256a::
+	movups	XMMWORD PTR[rax],xmm2
+	lea	rax,QWORD PTR[16+rax]
+$L$key_expansion_256a_cold::
+	shufps	xmm4,xmm0,16
+	xorps	xmm0,xmm4
+	shufps	xmm4,xmm0,140
+	xorps	xmm0,xmm4
+	shufps	xmm1,xmm1,255
+	xorps	xmm0,xmm1
+	DB	0F3h,0C3h		;repret
+
+ALIGN	16
+$L$key_expansion_256b::
+	movups	XMMWORD PTR[rax],xmm0
+	lea	rax,QWORD PTR[16+rax]
+
+	shufps	xmm4,xmm2,16
+	xorps	xmm2,xmm4
+	shufps	xmm4,xmm2,140
+	xorps	xmm2,xmm4
+	shufps	xmm1,xmm1,170
+	xorps	xmm2,xmm1
+	DB	0F3h,0C3h		;repret
+aesni_set_encrypt_key	ENDP
+
+ALIGN	64
+$L$bswap_mask::
+DB	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+$L$increment32::
+	DD	6,6,6,0
+$L$increment64::
+	DD	1,0,0,0
+$L$xts_magic::
+	DD	087h,0,1,0
+
+DB	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69
+DB	83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83
+DB	32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
+DB	115,108,46,111,114,103,62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+ecb_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[152+r8]
+
+	jmp	$L$common_seh_tail
+ecb_se_handler	ENDP
+
+
+ALIGN	16
+ccm64_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,8
+	DD	0a548f3fch		
+	lea	rax,QWORD PTR[88+rax]
+
+	jmp	$L$common_seh_tail
+ccm64_se_handler	ENDP
+
+
+ALIGN	16
+ctr32_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	lea	r10,QWORD PTR[$L$ctr32_body]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	lea	r10,QWORD PTR[$L$ctr32_ret]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[32+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,20
+	DD	0a548f3fch		
+
+	jmp	$L$common_rbp_tail
+ctr32_se_handler	ENDP
+
+
+ALIGN	16
+xts_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[96+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,20
+	DD	0a548f3fch		
+
+	jmp	$L$common_rbp_tail
+xts_se_handler	ENDP
+
+ALIGN	16
+cbc_se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[152+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	lea	r10,QWORD PTR[$L$cbc_decrypt]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	lea	r10,QWORD PTR[$L$cbc_decrypt_body]
+	cmp	rbx,r10
+	jb	$L$restore_cbc_rax
+
+	lea	r10,QWORD PTR[$L$cbc_ret]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[16+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,8
+	DD	0a548f3fch		
+
+$L$common_rbp_tail::
+	mov	rax,QWORD PTR[160+r8]
+	mov	rbp,QWORD PTR[rax]
+	lea	rax,QWORD PTR[8+rax]
+	mov	QWORD PTR[160+r8],rbp
+	jmp	$L$common_seh_tail
+
+$L$restore_cbc_rax::
+	mov	rax,QWORD PTR[120+r8]
+
+$L$common_seh_tail::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+cbc_se_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_aesni_ecb_encrypt
+	DD	imagerel $L$SEH_end_aesni_ecb_encrypt
+	DD	imagerel $L$SEH_info_ecb
+
+	DD	imagerel $L$SEH_begin_aesni_ccm64_encrypt_blocks
+	DD	imagerel $L$SEH_end_aesni_ccm64_encrypt_blocks
+	DD	imagerel $L$SEH_info_ccm64_enc
+
+	DD	imagerel $L$SEH_begin_aesni_ccm64_decrypt_blocks
+	DD	imagerel $L$SEH_end_aesni_ccm64_decrypt_blocks
+	DD	imagerel $L$SEH_info_ccm64_dec
+
+	DD	imagerel $L$SEH_begin_aesni_ctr32_encrypt_blocks
+	DD	imagerel $L$SEH_end_aesni_ctr32_encrypt_blocks
+	DD	imagerel $L$SEH_info_ctr32
+
+	DD	imagerel $L$SEH_begin_aesni_xts_encrypt
+	DD	imagerel $L$SEH_end_aesni_xts_encrypt
+	DD	imagerel $L$SEH_info_xts_enc
+
+	DD	imagerel $L$SEH_begin_aesni_xts_decrypt
+	DD	imagerel $L$SEH_end_aesni_xts_decrypt
+	DD	imagerel $L$SEH_info_xts_dec
+	DD	imagerel $L$SEH_begin_aesni_cbc_encrypt
+	DD	imagerel $L$SEH_end_aesni_cbc_encrypt
+	DD	imagerel $L$SEH_info_cbc
+
+	DD	imagerel aesni_set_decrypt_key
+	DD	imagerel $L$SEH_end_set_decrypt_key
+	DD	imagerel $L$SEH_info_key
+
+	DD	imagerel aesni_set_encrypt_key
+	DD	imagerel $L$SEH_end_set_encrypt_key
+	DD	imagerel $L$SEH_info_key
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_ecb::
+DB	9,0,0,0
+	DD	imagerel ecb_se_handler
+$L$SEH_info_ccm64_enc::
+DB	9,0,0,0
+	DD	imagerel ccm64_se_handler
+	DD	imagerel $L$ccm64_enc_body,imagerel $L$ccm64_enc_ret	
+$L$SEH_info_ccm64_dec::
+DB	9,0,0,0
+	DD	imagerel ccm64_se_handler
+	DD	imagerel $L$ccm64_dec_body,imagerel $L$ccm64_dec_ret	
+$L$SEH_info_ctr32::
+DB	9,0,0,0
+	DD	imagerel ctr32_se_handler
+$L$SEH_info_xts_enc::
+DB	9,0,0,0
+	DD	imagerel xts_se_handler
+	DD	imagerel $L$xts_enc_body,imagerel $L$xts_enc_epilogue	
+$L$SEH_info_xts_dec::
+DB	9,0,0,0
+	DD	imagerel xts_se_handler
+	DD	imagerel $L$xts_dec_body,imagerel $L$xts_dec_epilogue	
+$L$SEH_info_cbc::
+DB	9,0,0,0
+	DD	imagerel cbc_se_handler
+$L$SEH_info_key::
+DB	001h,004h,001h,000h
+DB	004h,002h,000h,000h	
+
+.xdata	ENDS
+END
+
diff --git a/crypto/aes/aesni-mingw64-x86_64.S b/crypto/aes/aesni-mingw64-x86_64.S
new file mode 100644
index 0000000..762bd25
--- /dev/null
+++ b/crypto/aes/aesni-mingw64-x86_64.S
@@ -0,0 +1,3028 @@
+#include "x86_arch.h"
+.text	
+.globl	aesni_encrypt
+.def	aesni_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_encrypt:
+	movups	(%rcx),%xmm2
+	movl	240(%r8),%eax
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm2
+.Loop_enc1_1:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_enc1_1	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rdx)
+	retq
+
+
+.globl	aesni_decrypt
+.def	aesni_decrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_decrypt:
+	movups	(%rcx),%xmm2
+	movl	240(%r8),%eax
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm2
+.Loop_dec1_2:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_dec1_2	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rdx)
+	retq
+
+.def	_aesni_encrypt3;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_encrypt3:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+.Lenc_loop3:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop3
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	retq
+
+.def	_aesni_decrypt3;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_decrypt3:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+
+.Ldec_loop3:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop3
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	retq
+
+.def	_aesni_encrypt4;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_encrypt4:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+.Lenc_loop4:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop4
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	retq
+
+.def	_aesni_decrypt4;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_decrypt4:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	xorps	%xmm0,%xmm4
+	xorps	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+
+.Ldec_loop4:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop4
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	retq
+
+.def	_aesni_encrypt6;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_encrypt6:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm7
+	jmp	.Lenc_loop6_enter
+.p2align	4
+.Lenc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lenc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop6
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	retq
+
+.def	_aesni_decrypt6;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_decrypt6:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm7
+	jmp	.Ldec_loop6_enter
+.p2align	4
+.Ldec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+.Ldec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop6
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	retq
+
+.def	_aesni_encrypt8;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_encrypt8:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	.Lenc_loop8_enter
+.p2align	4
+.Lenc_loop8:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+.Lenc_loop8_enter:
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	aesenc	%xmm0,%xmm8
+	aesenc	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	.Lenc_loop8
+
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	aesenc	%xmm1,%xmm8
+	aesenc	%xmm1,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	aesenclast	%xmm0,%xmm4
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+	aesenclast	%xmm0,%xmm8
+	aesenclast	%xmm0,%xmm9
+	retq
+
+.def	_aesni_decrypt8;	.scl 3;	.type 32;	.endef
+.p2align	4
+_aesni_decrypt8:
+	movups	(%rcx),%xmm0
+	shrl	$1,%eax
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm0,%xmm3
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+	jmp	.Ldec_loop8_enter
+.p2align	4
+.Ldec_loop8:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+.Ldec_loop8_enter:
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	aesdec	%xmm0,%xmm8
+	aesdec	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	jnz	.Ldec_loop8
+
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	aesdeclast	%xmm0,%xmm2
+	aesdeclast	%xmm0,%xmm3
+	aesdeclast	%xmm0,%xmm4
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+	aesdeclast	%xmm0,%xmm8
+	aesdeclast	%xmm0,%xmm9
+	retq
+
+.globl	aesni_ecb_encrypt
+.def	aesni_ecb_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_ecb_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_ecb_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+
+	andq	$-16,%rdx
+	jz	.Lecb_ret
+
+	movl	240(%rcx),%eax
+	movups	(%rcx),%xmm0
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	testl	%r8d,%r8d
+	jz	.Lecb_decrypt
+
+	cmpq	$128,%rdx
+	jb	.Lecb_enc_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	.Lecb_enc_loop8_enter
+.p2align	4
+.Lecb_enc_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+.Lecb_enc_loop8_enter:
+
+	call	_aesni_encrypt8
+
+	subq	$128,%rdx
+	jnc	.Lecb_enc_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	.Lecb_ret
+
+.Lecb_enc_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	.Lecb_enc_one
+	movups	16(%rdi),%xmm3
+	je	.Lecb_enc_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	.Lecb_enc_three
+	movups	48(%rdi),%xmm5
+	je	.Lecb_enc_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	.Lecb_enc_five
+	movups	80(%rdi),%xmm7
+	je	.Lecb_enc_six
+	movdqu	96(%rdi),%xmm8
+	call	_aesni_encrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_3:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_3	
+	aesenclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_three:
+	call	_aesni_encrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_four:
+	call	_aesni_encrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_enc_six:
+	call	_aesni_encrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	jmp	.Lecb_ret
+
+.p2align	4
+.Lecb_decrypt:
+	cmpq	$128,%rdx
+	jb	.Lecb_dec_tail
+
+	movdqu	(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	movdqu	96(%rdi),%xmm8
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	jmp	.Lecb_dec_loop8_enter
+.p2align	4
+.Lecb_dec_loop8:
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movdqu	(%rdi),%xmm2
+	movl	%r10d,%eax
+	movups	%xmm3,16(%rsi)
+	movdqu	16(%rdi),%xmm3
+	movups	%xmm4,32(%rsi)
+	movdqu	32(%rdi),%xmm4
+	movups	%xmm5,48(%rsi)
+	movdqu	48(%rdi),%xmm5
+	movups	%xmm6,64(%rsi)
+	movdqu	64(%rdi),%xmm6
+	movups	%xmm7,80(%rsi)
+	movdqu	80(%rdi),%xmm7
+	movups	%xmm8,96(%rsi)
+	movdqu	96(%rdi),%xmm8
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	movdqu	112(%rdi),%xmm9
+	leaq	128(%rdi),%rdi
+.Lecb_dec_loop8_enter:
+
+	call	_aesni_decrypt8
+
+	movups	(%r11),%xmm0
+	subq	$128,%rdx
+	jnc	.Lecb_dec_loop8
+
+	movups	%xmm2,(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm3,16(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	movups	%xmm9,112(%rsi)
+	leaq	128(%rsi),%rsi
+	addq	$128,%rdx
+	jz	.Lecb_ret
+
+.Lecb_dec_tail:
+	movups	(%rdi),%xmm2
+	cmpq	$32,%rdx
+	jb	.Lecb_dec_one
+	movups	16(%rdi),%xmm3
+	je	.Lecb_dec_two
+	movups	32(%rdi),%xmm4
+	cmpq	$64,%rdx
+	jb	.Lecb_dec_three
+	movups	48(%rdi),%xmm5
+	je	.Lecb_dec_four
+	movups	64(%rdi),%xmm6
+	cmpq	$96,%rdx
+	jb	.Lecb_dec_five
+	movups	80(%rdi),%xmm7
+	je	.Lecb_dec_six
+	movups	96(%rdi),%xmm8
+	movups	(%rcx),%xmm0
+	call	_aesni_decrypt8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	movups	%xmm8,96(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_4:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_4	
+	aesdeclast	%xmm1,%xmm2
+	movups	%xmm2,(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_three:
+	call	_aesni_decrypt3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_four:
+	call	_aesni_decrypt4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	jmp	.Lecb_ret
+.p2align	4
+.Lecb_dec_six:
+	call	_aesni_decrypt6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+
+.Lecb_ret:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_ecb_encrypt:
+.globl	aesni_ccm64_encrypt_blocks
+.def	aesni_ccm64_encrypt_blocks;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_ccm64_encrypt_blocks:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_ccm64_encrypt_blocks:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	leaq	-88(%rsp),%rsp
+	movaps	%xmm6,(%rsp)
+	movaps	%xmm7,16(%rsp)
+	movaps	%xmm8,32(%rsp)
+	movaps	%xmm9,48(%rsp)
+.Lccm64_enc_body:
+	movl	240(%rcx),%eax
+	movdqu	(%r8),%xmm9
+	movdqa	.Lincrement64(%rip),%xmm6
+	movdqa	.Lbswap_mask(%rip),%xmm7
+
+	shrl	$1,%eax
+	leaq	0(%rcx),%r11
+	movdqu	(%r9),%xmm3
+	movdqa	%xmm9,%xmm2
+	movl	%eax,%r10d
+.byte	102,68,15,56,0,207
+	jmp	.Lccm64_enc_outer
+.p2align	4
+.Lccm64_enc_outer:
+	movups	(%r11),%xmm0
+	movl	%r10d,%eax
+	movups	(%rdi),%xmm8
+
+	xorps	%xmm0,%xmm2
+	movups	16(%r11),%xmm1
+	xorps	%xmm8,%xmm0
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm3
+	movups	(%rcx),%xmm0
+
+.Lccm64_enc2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	.Lccm64_enc2_loop
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	paddq	%xmm6,%xmm9
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+
+	decq	%rdx
+	leaq	16(%rdi),%rdi
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+	jnz	.Lccm64_enc_outer
+
+	movups	%xmm3,(%r9)
+	movaps	(%rsp),%xmm6
+	movaps	16(%rsp),%xmm7
+	movaps	32(%rsp),%xmm8
+	movaps	48(%rsp),%xmm9
+	leaq	88(%rsp),%rsp
+.Lccm64_enc_ret:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_ccm64_encrypt_blocks:
+.globl	aesni_ccm64_decrypt_blocks
+.def	aesni_ccm64_decrypt_blocks;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_ccm64_decrypt_blocks:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_ccm64_decrypt_blocks:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	leaq	-88(%rsp),%rsp
+	movaps	%xmm6,(%rsp)
+	movaps	%xmm7,16(%rsp)
+	movaps	%xmm8,32(%rsp)
+	movaps	%xmm9,48(%rsp)
+.Lccm64_dec_body:
+	movl	240(%rcx),%eax
+	movups	(%r8),%xmm9
+	movdqu	(%r9),%xmm3
+	movdqa	.Lincrement64(%rip),%xmm6
+	movdqa	.Lbswap_mask(%rip),%xmm7
+
+	movaps	%xmm9,%xmm2
+	movl	%eax,%r10d
+	movq	%rcx,%r11
+.byte	102,68,15,56,0,207
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_5:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_5	
+	aesenclast	%xmm1,%xmm2
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	leaq	16(%rdi),%rdi
+	jmp	.Lccm64_dec_outer
+.p2align	4
+.Lccm64_dec_outer:
+	xorps	%xmm2,%xmm8
+	movdqa	%xmm9,%xmm2
+	movl	%r10d,%eax
+	movups	%xmm8,(%rsi)
+	leaq	16(%rsi),%rsi
+.byte	102,15,56,0,215
+
+	subq	$1,%rdx
+	jz	.Lccm64_dec_break
+
+	movups	(%r11),%xmm0
+	shrl	$1,%eax
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%rcx
+	xorps	%xmm0,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	(%rcx),%xmm0
+
+.Lccm64_dec2_loop:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	aesenc	%xmm1,%xmm3
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm3
+	movups	0(%rcx),%xmm0
+	jnz	.Lccm64_dec2_loop
+	movups	(%rdi),%xmm8
+	paddq	%xmm6,%xmm9
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	leaq	16(%rdi),%rdi
+	aesenclast	%xmm0,%xmm2
+	aesenclast	%xmm0,%xmm3
+	jmp	.Lccm64_dec_outer
+
+.p2align	4
+.Lccm64_dec_break:
+
+	movups	(%r11),%xmm0
+	movups	16(%r11),%xmm1
+	xorps	%xmm0,%xmm8
+	leaq	32(%r11),%r11
+	xorps	%xmm8,%xmm3
+.Loop_enc1_6:
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	movups	(%r11),%xmm1
+	leaq	16(%r11),%r11
+	jnz	.Loop_enc1_6	
+	aesenclast	%xmm1,%xmm3
+	movups	%xmm3,(%r9)
+	movaps	(%rsp),%xmm6
+	movaps	16(%rsp),%xmm7
+	movaps	32(%rsp),%xmm8
+	movaps	48(%rsp),%xmm9
+	leaq	88(%rsp),%rsp
+.Lccm64_dec_ret:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_ccm64_decrypt_blocks:
+.globl	aesni_ctr32_encrypt_blocks
+.def	aesni_ctr32_encrypt_blocks;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_ctr32_encrypt_blocks:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_ctr32_encrypt_blocks:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+
+	endbr64
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$192,%rsp
+	movaps	%xmm6,32(%rsp)
+	movaps	%xmm7,48(%rsp)
+	movaps	%xmm8,64(%rsp)
+	movaps	%xmm9,80(%rsp)
+	movaps	%xmm10,96(%rsp)
+	movaps	%xmm11,112(%rsp)
+	movaps	%xmm12,128(%rsp)
+	movaps	%xmm13,144(%rsp)
+	movaps	%xmm14,160(%rsp)
+	movaps	%xmm15,176(%rsp)
+.Lctr32_body:
+	leaq	-8(%rax),%rbp
+	cmpq	$1,%rdx
+	je	.Lctr32_one_shortcut
+
+	movdqu	(%r8),%xmm14
+	movdqa	.Lbswap_mask(%rip),%xmm15
+	xorl	%eax,%eax
+.byte	102,69,15,58,22,242,3
+.byte	102,68,15,58,34,240,3
+
+	movl	240(%rcx),%eax
+	bswapl	%r10d
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+.byte	102,69,15,58,34,226,0
+	leaq	3(%r10),%r11
+.byte	102,69,15,58,34,235,0
+	incl	%r10d
+.byte	102,69,15,58,34,226,1
+	incq	%r11
+.byte	102,69,15,58,34,235,1
+	incl	%r10d
+.byte	102,69,15,58,34,226,2
+	incq	%r11
+.byte	102,69,15,58,34,235,2
+	movdqa	%xmm12,0(%rsp)
+.byte	102,69,15,56,0,231
+	movdqa	%xmm13,16(%rsp)
+.byte	102,69,15,56,0,239
+
+	pshufd	$192,%xmm12,%xmm2
+	pshufd	$128,%xmm12,%xmm3
+	pshufd	$64,%xmm12,%xmm4
+	cmpq	$6,%rdx
+	jb	.Lctr32_tail
+	shrl	$1,%eax
+	movq	%rcx,%r11
+	movl	%eax,%r10d
+	subq	$6,%rdx
+	jmp	.Lctr32_loop6
+
+.p2align	4
+.Lctr32_loop6:
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm2
+	movups	(%r11),%xmm0
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm3
+	movups	16(%r11),%xmm1
+	pshufd	$64,%xmm13,%xmm7
+	por	%xmm14,%xmm4
+	por	%xmm14,%xmm5
+	xorps	%xmm0,%xmm2
+	por	%xmm14,%xmm6
+	por	%xmm14,%xmm7
+
+
+
+
+	pxor	%xmm0,%xmm3
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	aesenc	%xmm1,%xmm3
+	movdqa	.Lincrement32(%rip),%xmm13
+	pxor	%xmm0,%xmm5
+	aesenc	%xmm1,%xmm4
+	movdqa	(%rsp),%xmm12
+	pxor	%xmm0,%xmm6
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	jmp	.Lctr32_enc_loop6_enter
+.p2align	4
+.Lctr32_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lctr32_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lctr32_enc_loop6
+
+	aesenc	%xmm1,%xmm2
+	paddd	%xmm13,%xmm12
+	aesenc	%xmm1,%xmm3
+	paddd	16(%rsp),%xmm13
+	aesenc	%xmm1,%xmm4
+	movdqa	%xmm12,0(%rsp)
+	aesenc	%xmm1,%xmm5
+	movdqa	%xmm13,16(%rsp)
+	aesenc	%xmm1,%xmm6
+.byte	102,69,15,56,0,231
+	aesenc	%xmm1,%xmm7
+.byte	102,69,15,56,0,239
+
+	aesenclast	%xmm0,%xmm2
+	movups	(%rdi),%xmm8
+	aesenclast	%xmm0,%xmm3
+	movups	16(%rdi),%xmm9
+	aesenclast	%xmm0,%xmm4
+	movups	32(%rdi),%xmm10
+	aesenclast	%xmm0,%xmm5
+	movups	48(%rdi),%xmm11
+	aesenclast	%xmm0,%xmm6
+	movups	64(%rdi),%xmm1
+	aesenclast	%xmm0,%xmm7
+	movups	80(%rdi),%xmm0
+	leaq	96(%rdi),%rdi
+
+	xorps	%xmm2,%xmm8
+	pshufd	$192,%xmm12,%xmm2
+	xorps	%xmm3,%xmm9
+	pshufd	$128,%xmm12,%xmm3
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	pshufd	$64,%xmm12,%xmm4
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	xorps	%xmm7,%xmm0
+	movups	%xmm1,64(%rsi)
+	movups	%xmm0,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movl	%r10d,%eax
+	subq	$6,%rdx
+	jnc	.Lctr32_loop6
+
+	addq	$6,%rdx
+	jz	.Lctr32_done
+	movq	%r11,%rcx
+	leal	1(%rax,%rax,1),%eax
+
+.Lctr32_tail:
+	por	%xmm14,%xmm2
+	movups	(%rdi),%xmm8
+	cmpq	$2,%rdx
+	jb	.Lctr32_one
+
+	por	%xmm14,%xmm3
+	movups	16(%rdi),%xmm9
+	je	.Lctr32_two
+
+	pshufd	$192,%xmm13,%xmm5
+	por	%xmm14,%xmm4
+	movups	32(%rdi),%xmm10
+	cmpq	$4,%rdx
+	jb	.Lctr32_three
+
+	pshufd	$128,%xmm13,%xmm6
+	por	%xmm14,%xmm5
+	movups	48(%rdi),%xmm11
+	je	.Lctr32_four
+
+	por	%xmm14,%xmm6
+	xorps	%xmm7,%xmm7
+
+	call	_aesni_encrypt6
+
+	movups	64(%rdi),%xmm1
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	xorps	%xmm6,%xmm1
+	movups	%xmm11,48(%rsi)
+	movups	%xmm1,64(%rsi)
+	jmp	.Lctr32_done
+
+.p2align	4
+.Lctr32_one_shortcut:
+	movups	(%r8),%xmm2
+	movups	(%rdi),%xmm8
+	movl	240(%rcx),%eax
+.Lctr32_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_7:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_7	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm2,%xmm8
+	movups	%xmm8,(%rsi)
+	jmp	.Lctr32_done
+
+.p2align	4
+.Lctr32_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	movups	%xmm9,16(%rsi)
+	jmp	.Lctr32_done
+
+.p2align	4
+.Lctr32_three:
+	call	_aesni_encrypt3
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	movups	%xmm10,32(%rsi)
+	jmp	.Lctr32_done
+
+.p2align	4
+.Lctr32_four:
+	call	_aesni_encrypt4
+	xorps	%xmm2,%xmm8
+	xorps	%xmm3,%xmm9
+	movups	%xmm8,(%rsi)
+	xorps	%xmm4,%xmm10
+	movups	%xmm9,16(%rsi)
+	xorps	%xmm5,%xmm11
+	movups	%xmm10,32(%rsi)
+	movups	%xmm11,48(%rsi)
+
+.Lctr32_done:
+	movaps	32(%rsp),%xmm6
+	movaps	48(%rsp),%xmm7
+	movaps	64(%rsp),%xmm8
+	movaps	80(%rsp),%xmm9
+	movaps	96(%rsp),%xmm10
+	movaps	112(%rsp),%xmm11
+	movaps	128(%rsp),%xmm12
+	movaps	144(%rsp),%xmm13
+	movaps	160(%rsp),%xmm14
+	movaps	176(%rsp),%xmm15
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lctr32_ret:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_ctr32_encrypt_blocks:
+.globl	aesni_xts_encrypt
+.def	aesni_xts_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_xts_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_xts_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$256,%rsp
+	movaps	%xmm6,96(%rsp)
+	movaps	%xmm7,112(%rsp)
+	movaps	%xmm8,128(%rsp)
+	movaps	%xmm9,144(%rsp)
+	movaps	%xmm10,160(%rsp)
+	movaps	%xmm11,176(%rsp)
+	movaps	%xmm12,192(%rsp)
+	movaps	%xmm13,208(%rsp)
+	movaps	%xmm14,224(%rsp)
+	movaps	%xmm15,240(%rsp)
+.Lxts_enc_body:
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+.Loop_enc1_8:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_enc1_8	
+	aesenclast	%xmm1,%xmm15
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	.Lxts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	.Lxts_enc_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	.Lxts_enc_grandloop
+
+.p2align	4
+.Lxts_enc_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesenc	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesenc	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesenc	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesenc	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesenc	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	.Lxts_enc_loop6_enter
+
+.p2align	4
+.Lxts_enc_loop6:
+	aesenc	%xmm1,%xmm2
+	aesenc	%xmm1,%xmm3
+	decl	%eax
+	aesenc	%xmm1,%xmm4
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+.Lxts_enc_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesenc	%xmm0,%xmm2
+	aesenc	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesenc	%xmm0,%xmm4
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lxts_enc_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm0,%xmm5
+	aesenc	%xmm0,%xmm6
+	aesenc	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesenc	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesenc	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenc	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenc	%xmm1,%xmm5
+	aesenc	%xmm1,%xmm6
+	aesenc	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesenclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesenclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesenclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesenclast	%xmm0,%xmm5
+	aesenclast	%xmm0,%xmm6
+	aesenclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	.Lxts_enc_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+.Lxts_enc_short:
+	addq	$96,%rdx
+	jz	.Lxts_enc_done
+
+	cmpq	$32,%rdx
+	jb	.Lxts_enc_one
+	je	.Lxts_enc_two
+
+	cmpq	$64,%rdx
+	jb	.Lxts_enc_three
+	je	.Lxts_enc_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_encrypt6
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	movdqu	%xmm5,48(%rsi)
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.p2align	4
+.Lxts_enc_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_9:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_9	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	leaq	16(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.p2align	4
+.Lxts_enc_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.p2align	4
+.Lxts_enc_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_encrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.p2align	4
+.Lxts_enc_four:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_encrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm15,%xmm10
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	.Lxts_enc_done
+
+.p2align	4
+.Lxts_enc_done:
+	andq	$15,%r9
+	jz	.Lxts_enc_ret
+	movq	%r9,%rdx
+
+.Lxts_enc_steal:
+	movzbl	(%rdi),%eax
+	movzbl	-16(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,-16(%rsi)
+	movb	%cl,0(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	.Lxts_enc_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	-16(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_enc1_10:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_10	
+	aesenclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,-16(%rsi)
+
+.Lxts_enc_ret:
+	movaps	96(%rsp),%xmm6
+	movaps	112(%rsp),%xmm7
+	movaps	128(%rsp),%xmm8
+	movaps	144(%rsp),%xmm9
+	movaps	160(%rsp),%xmm10
+	movaps	176(%rsp),%xmm11
+	movaps	192(%rsp),%xmm12
+	movaps	208(%rsp),%xmm13
+	movaps	224(%rsp),%xmm14
+	movaps	240(%rsp),%xmm15
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lxts_enc_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_xts_encrypt:
+.globl	aesni_xts_decrypt
+.def	aesni_xts_decrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_xts_decrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_xts_decrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$256,%rsp
+	movaps	%xmm6,96(%rsp)
+	movaps	%xmm7,112(%rsp)
+	movaps	%xmm8,128(%rsp)
+	movaps	%xmm9,144(%rsp)
+	movaps	%xmm10,160(%rsp)
+	movaps	%xmm11,176(%rsp)
+	movaps	%xmm12,192(%rsp)
+	movaps	%xmm13,208(%rsp)
+	movaps	%xmm14,224(%rsp)
+	movaps	%xmm15,240(%rsp)
+.Lxts_dec_body:
+	leaq	-8(%rax),%rbp
+	movups	(%r9),%xmm15
+	movl	240(%r8),%eax
+	movl	240(%rcx),%r10d
+	movups	(%r8),%xmm0
+	movups	16(%r8),%xmm1
+	leaq	32(%r8),%r8
+	xorps	%xmm0,%xmm15
+.Loop_enc1_11:
+	aesenc	%xmm1,%xmm15
+	decl	%eax
+	movups	(%r8),%xmm1
+	leaq	16(%r8),%r8
+	jnz	.Loop_enc1_11	
+	aesenclast	%xmm1,%xmm15
+	xorl	%eax,%eax
+	testq	$15,%rdx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%rdx
+
+	movq	%rcx,%r11
+	movl	%r10d,%eax
+	movq	%rdx,%r9
+	andq	$-16,%rdx
+
+	movdqa	.Lxts_magic(%rip),%xmm8
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm9
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+	subq	$96,%rdx
+	jc	.Lxts_dec_short
+
+	shrl	$1,%eax
+	subl	$1,%eax
+	movl	%eax,%r10d
+	jmp	.Lxts_dec_grandloop
+
+.p2align	4
+.Lxts_dec_grandloop:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	0(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm12,%xmm4
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+	pxor	%xmm13,%xmm5
+	movups	(%r11),%xmm0
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+
+
+
+	movups	16(%r11),%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm0,%xmm3
+	movdqa	%xmm10,0(%rsp)
+	aesdec	%xmm1,%xmm2
+	leaq	32(%r11),%rcx
+	pxor	%xmm0,%xmm4
+	movdqa	%xmm11,16(%rsp)
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqa	%xmm12,32(%rsp)
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm13,48(%rsp)
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	decl	%eax
+	movdqa	%xmm14,64(%rsp)
+	aesdec	%xmm1,%xmm6
+	movdqa	%xmm15,80(%rsp)
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm14,%xmm14
+	pcmpgtd	%xmm15,%xmm14
+	jmp	.Lxts_dec_loop6_enter
+
+.p2align	4
+.Lxts_dec_loop6:
+	aesdec	%xmm1,%xmm2
+	aesdec	%xmm1,%xmm3
+	decl	%eax
+	aesdec	%xmm1,%xmm4
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+.Lxts_dec_loop6_enter:
+	movups	16(%rcx),%xmm1
+	aesdec	%xmm0,%xmm2
+	aesdec	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	aesdec	%xmm0,%xmm4
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	(%rcx),%xmm0
+	jnz	.Lxts_dec_loop6
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+	movups	16(%rcx),%xmm1
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm0,%xmm5
+	aesdec	%xmm0,%xmm6
+	aesdec	%xmm0,%xmm7
+	movups	32(%rcx),%xmm0
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm11
+	paddq	%xmm15,%xmm15
+	aesdec	%xmm1,%xmm2
+	pand	%xmm8,%xmm9
+	aesdec	%xmm1,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdec	%xmm1,%xmm5
+	aesdec	%xmm1,%xmm6
+	aesdec	%xmm1,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm12
+	paddq	%xmm15,%xmm15
+	aesdeclast	%xmm0,%xmm2
+	pand	%xmm8,%xmm9
+	aesdeclast	%xmm0,%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	aesdeclast	%xmm0,%xmm4
+	pxor	%xmm9,%xmm15
+	aesdeclast	%xmm0,%xmm5
+	aesdeclast	%xmm0,%xmm6
+	aesdeclast	%xmm0,%xmm7
+
+	pshufd	$19,%xmm14,%xmm9
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm15,%xmm13
+	paddq	%xmm15,%xmm15
+	xorps	0(%rsp),%xmm2
+	pand	%xmm8,%xmm9
+	xorps	16(%rsp),%xmm3
+	pcmpgtd	%xmm15,%xmm14
+	pxor	%xmm9,%xmm15
+
+	xorps	32(%rsp),%xmm4
+	movups	%xmm2,0(%rsi)
+	xorps	48(%rsp),%xmm5
+	movups	%xmm3,16(%rsi)
+	xorps	64(%rsp),%xmm6
+	movups	%xmm4,32(%rsi)
+	xorps	80(%rsp),%xmm7
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$96,%rdx
+	jnc	.Lxts_dec_grandloop
+
+	leal	3(%rax,%rax,1),%eax
+	movq	%r11,%rcx
+	movl	%eax,%r10d
+
+.Lxts_dec_short:
+	addq	$96,%rdx
+	jz	.Lxts_dec_done
+
+	cmpq	$32,%rdx
+	jb	.Lxts_dec_one
+	je	.Lxts_dec_two
+
+	cmpq	$64,%rdx
+	jb	.Lxts_dec_three
+	je	.Lxts_dec_four
+
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movdqu	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movdqu	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movdqu	32(%rdi),%xmm4
+	pxor	%xmm10,%xmm2
+	movdqu	48(%rdi),%xmm5
+	pxor	%xmm11,%xmm3
+	movdqu	64(%rdi),%xmm6
+	leaq	80(%rdi),%rdi
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm6
+
+	call	_aesni_decrypt6
+
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	movdqu	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movdqu	%xmm3,16(%rsi)
+	xorps	%xmm14,%xmm6
+	movdqu	%xmm4,32(%rsi)
+	pxor	%xmm14,%xmm14
+	movdqu	%xmm5,48(%rsi)
+	pcmpgtd	%xmm15,%xmm14
+	movdqu	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	pshufd	$19,%xmm14,%xmm11
+	andq	$15,%r9
+	jz	.Lxts_dec_ret
+
+	movdqa	%xmm15,%xmm10
+	paddq	%xmm15,%xmm15
+	pand	%xmm8,%xmm11
+	pxor	%xmm15,%xmm11
+	jmp	.Lxts_dec_done2
+
+.p2align	4
+.Lxts_dec_one:
+	movups	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_12:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_12	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm11,%xmm10
+	movups	%xmm2,(%rsi)
+	movdqa	%xmm12,%xmm11
+	leaq	16(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.p2align	4
+.Lxts_dec_two:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	leaq	32(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm12,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm13,%xmm11
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	leaq	32(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.p2align	4
+.Lxts_dec_three:
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	32(%rdi),%xmm4
+	leaq	48(%rdi),%rdi
+	xorps	%xmm10,%xmm2
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+
+	call	_aesni_decrypt3
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm13,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	leaq	48(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.p2align	4
+.Lxts_dec_four:
+	pshufd	$19,%xmm14,%xmm9
+	movdqa	%xmm15,%xmm14
+	paddq	%xmm15,%xmm15
+	movups	(%rdi),%xmm2
+	pand	%xmm8,%xmm9
+	movups	16(%rdi),%xmm3
+	pxor	%xmm9,%xmm15
+
+	movups	32(%rdi),%xmm4
+	xorps	%xmm10,%xmm2
+	movups	48(%rdi),%xmm5
+	leaq	64(%rdi),%rdi
+	xorps	%xmm11,%xmm3
+	xorps	%xmm12,%xmm4
+	xorps	%xmm13,%xmm5
+
+	call	_aesni_decrypt4
+
+	xorps	%xmm10,%xmm2
+	movdqa	%xmm14,%xmm10
+	xorps	%xmm11,%xmm3
+	movdqa	%xmm15,%xmm11
+	xorps	%xmm12,%xmm4
+	movups	%xmm2,(%rsi)
+	xorps	%xmm13,%xmm5
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	jmp	.Lxts_dec_done
+
+.p2align	4
+.Lxts_dec_done:
+	andq	$15,%r9
+	jz	.Lxts_dec_ret
+.Lxts_dec_done2:
+	movq	%r9,%rdx
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rdi),%xmm2
+	xorps	%xmm11,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_13:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_13	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm11,%xmm2
+	movups	%xmm2,(%rsi)
+
+.Lxts_dec_steal:
+	movzbl	16(%rdi),%eax
+	movzbl	(%rsi),%ecx
+	leaq	1(%rdi),%rdi
+	movb	%al,(%rsi)
+	movb	%cl,16(%rsi)
+	leaq	1(%rsi),%rsi
+	subq	$1,%rdx
+	jnz	.Lxts_dec_steal
+
+	subq	%r9,%rsi
+	movq	%r11,%rcx
+	movl	%r10d,%eax
+
+	movups	(%rsi),%xmm2
+	xorps	%xmm10,%xmm2
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_14:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_14	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm10,%xmm2
+	movups	%xmm2,(%rsi)
+
+.Lxts_dec_ret:
+	movaps	96(%rsp),%xmm6
+	movaps	112(%rsp),%xmm7
+	movaps	128(%rsp),%xmm8
+	movaps	144(%rsp),%xmm9
+	movaps	160(%rsp),%xmm10
+	movaps	176(%rsp),%xmm11
+	movaps	192(%rsp),%xmm12
+	movaps	208(%rsp),%xmm13
+	movaps	224(%rsp),%xmm14
+	movaps	240(%rsp),%xmm15
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lxts_dec_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_xts_decrypt:
+.globl	aesni_cbc_encrypt
+.def	aesni_cbc_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_cbc_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_cbc_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	testq	%rdx,%rdx
+	jz	.Lcbc_ret
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	testl	%r9d,%r9d
+	jz	.Lcbc_decrypt
+
+	movups	(%r8),%xmm2
+	movl	%r10d,%eax
+	cmpq	$16,%rdx
+	jb	.Lcbc_enc_tail
+	subq	$16,%rdx
+	jmp	.Lcbc_enc_loop
+.p2align	4
+.Lcbc_enc_loop:
+	movups	(%rdi),%xmm3
+	leaq	16(%rdi),%rdi
+
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	xorps	%xmm0,%xmm3
+	leaq	32(%rcx),%rcx
+	xorps	%xmm3,%xmm2
+.Loop_enc1_15:
+	aesenc	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_enc1_15	
+	aesenclast	%xmm1,%xmm2
+	movl	%r10d,%eax
+	movq	%r11,%rcx
+	movups	%xmm2,0(%rsi)
+	leaq	16(%rsi),%rsi
+	subq	$16,%rdx
+	jnc	.Lcbc_enc_loop
+	addq	$16,%rdx
+	jnz	.Lcbc_enc_tail
+	movups	%xmm2,(%r8)
+	jmp	.Lcbc_ret
+
+.Lcbc_enc_tail:
+	movq	%rdx,%rcx
+	xchgq	%rdi,%rsi
+.long	0x9066A4F3	
+	movl	$16,%ecx
+	subq	%rdx,%rcx
+	xorl	%eax,%eax
+.long	0x9066AAF3	
+	leaq	-16(%rdi),%rdi
+	movl	%r10d,%eax
+	movq	%rdi,%rsi
+	movq	%r11,%rcx
+	xorq	%rdx,%rdx
+	jmp	.Lcbc_enc_loop	
+
+.p2align	4
+.Lcbc_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbp
+	subq	$80,%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+.Lcbc_decrypt_body:
+	leaq	-8(%rax),%rbp
+	movups	(%r8),%xmm9
+	movl	%r10d,%eax
+	cmpq	$112,%rdx
+	jbe	.Lcbc_dec_tail
+	shrl	$1,%r10d
+	subq	$112,%rdx
+	movl	%r10d,%eax
+	movaps	%xmm9,(%rsp)
+	jmp	.Lcbc_dec_loop8_enter
+.p2align	4
+.Lcbc_dec_loop8:
+	movaps	%xmm0,(%rsp)
+	movups	%xmm9,(%rsi)
+	leaq	16(%rsi),%rsi
+.Lcbc_dec_loop8_enter:
+	movups	(%rcx),%xmm0
+	movups	(%rdi),%xmm2
+	movups	16(%rdi),%xmm3
+	movups	16(%rcx),%xmm1
+
+	leaq	32(%rcx),%rcx
+	movdqu	32(%rdi),%xmm4
+	xorps	%xmm0,%xmm2
+	movdqu	48(%rdi),%xmm5
+	xorps	%xmm0,%xmm3
+	movdqu	64(%rdi),%xmm6
+	aesdec	%xmm1,%xmm2
+	pxor	%xmm0,%xmm4
+	movdqu	80(%rdi),%xmm7
+	aesdec	%xmm1,%xmm3
+	pxor	%xmm0,%xmm5
+	movdqu	96(%rdi),%xmm8
+	aesdec	%xmm1,%xmm4
+	pxor	%xmm0,%xmm6
+	movdqu	112(%rdi),%xmm9
+	aesdec	%xmm1,%xmm5
+	pxor	%xmm0,%xmm7
+	decl	%eax
+	aesdec	%xmm1,%xmm6
+	pxor	%xmm0,%xmm8
+	aesdec	%xmm1,%xmm7
+	pxor	%xmm0,%xmm9
+	movups	(%rcx),%xmm0
+	aesdec	%xmm1,%xmm8
+	aesdec	%xmm1,%xmm9
+	movups	16(%rcx),%xmm1
+
+	call	.Ldec_loop8_enter
+
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm1
+	xorps	%xmm0,%xmm8
+	movups	112(%rdi),%xmm0
+	xorps	%xmm1,%xmm9
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movl	%r10d,%eax
+	movups	%xmm6,64(%rsi)
+	movq	%r11,%rcx
+	movups	%xmm7,80(%rsi)
+	leaq	128(%rdi),%rdi
+	movups	%xmm8,96(%rsi)
+	leaq	112(%rsi),%rsi
+	subq	$128,%rdx
+	ja	.Lcbc_dec_loop8
+
+	movaps	%xmm9,%xmm2
+	movaps	%xmm0,%xmm9
+	addq	$112,%rdx
+	jle	.Lcbc_dec_tail_collected
+	movups	%xmm2,(%rsi)
+	leal	1(%r10,%r10,1),%eax
+	leaq	16(%rsi),%rsi
+.Lcbc_dec_tail:
+	movups	(%rdi),%xmm2
+	movaps	%xmm2,%xmm8
+	cmpq	$16,%rdx
+	jbe	.Lcbc_dec_one
+
+	movups	16(%rdi),%xmm3
+	movaps	%xmm3,%xmm7
+	cmpq	$32,%rdx
+	jbe	.Lcbc_dec_two
+
+	movups	32(%rdi),%xmm4
+	movaps	%xmm4,%xmm6
+	cmpq	$48,%rdx
+	jbe	.Lcbc_dec_three
+
+	movups	48(%rdi),%xmm5
+	cmpq	$64,%rdx
+	jbe	.Lcbc_dec_four
+
+	movups	64(%rdi),%xmm6
+	cmpq	$80,%rdx
+	jbe	.Lcbc_dec_five
+
+	movups	80(%rdi),%xmm7
+	cmpq	$96,%rdx
+	jbe	.Lcbc_dec_six
+
+	movups	96(%rdi),%xmm8
+	movaps	%xmm9,(%rsp)
+	call	_aesni_decrypt8
+	movups	(%rdi),%xmm1
+	movups	16(%rdi),%xmm0
+	xorps	(%rsp),%xmm2
+	xorps	%xmm1,%xmm3
+	movups	32(%rdi),%xmm1
+	xorps	%xmm0,%xmm4
+	movups	48(%rdi),%xmm0
+	xorps	%xmm1,%xmm5
+	movups	64(%rdi),%xmm1
+	xorps	%xmm0,%xmm6
+	movups	80(%rdi),%xmm0
+	xorps	%xmm1,%xmm7
+	movups	96(%rdi),%xmm9
+	xorps	%xmm0,%xmm8
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	movaps	%xmm8,%xmm2
+	subq	$112,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_one:
+	movups	(%rcx),%xmm0
+	movups	16(%rcx),%xmm1
+	leaq	32(%rcx),%rcx
+	xorps	%xmm0,%xmm2
+.Loop_dec1_16:
+	aesdec	%xmm1,%xmm2
+	decl	%eax
+	movups	(%rcx),%xmm1
+	leaq	16(%rcx),%rcx
+	jnz	.Loop_dec1_16	
+	aesdeclast	%xmm1,%xmm2
+	xorps	%xmm9,%xmm2
+	movaps	%xmm8,%xmm9
+	subq	$16,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_two:
+	xorps	%xmm4,%xmm4
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	movaps	%xmm7,%xmm9
+	movaps	%xmm3,%xmm2
+	leaq	16(%rsi),%rsi
+	subq	$32,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_three:
+	call	_aesni_decrypt3
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	movaps	%xmm6,%xmm9
+	movaps	%xmm4,%xmm2
+	leaq	32(%rsi),%rsi
+	subq	$48,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_four:
+	call	_aesni_decrypt4
+	xorps	%xmm9,%xmm2
+	movups	48(%rdi),%xmm9
+	xorps	%xmm8,%xmm3
+	movups	%xmm2,(%rsi)
+	xorps	%xmm7,%xmm4
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm6,%xmm5
+	movups	%xmm4,32(%rsi)
+	movaps	%xmm5,%xmm2
+	leaq	48(%rsi),%rsi
+	subq	$64,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_five:
+	xorps	%xmm7,%xmm7
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm9
+	xorps	%xmm1,%xmm6
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	leaq	64(%rsi),%rsi
+	movaps	%xmm6,%xmm2
+	subq	$80,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_six:
+	call	_aesni_decrypt6
+	movups	16(%rdi),%xmm1
+	movups	32(%rdi),%xmm0
+	xorps	%xmm9,%xmm2
+	xorps	%xmm8,%xmm3
+	xorps	%xmm1,%xmm4
+	movups	48(%rdi),%xmm1
+	xorps	%xmm0,%xmm5
+	movups	64(%rdi),%xmm0
+	xorps	%xmm1,%xmm6
+	movups	80(%rdi),%xmm9
+	xorps	%xmm0,%xmm7
+	movups	%xmm2,(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	leaq	80(%rsi),%rsi
+	movaps	%xmm7,%xmm2
+	subq	$96,%rdx
+	jmp	.Lcbc_dec_tail_collected
+.p2align	4
+.Lcbc_dec_tail_collected:
+	andq	$15,%rdx
+	movups	%xmm9,(%r8)
+	jnz	.Lcbc_dec_tail_partial
+	movups	%xmm2,(%rsi)
+	jmp	.Lcbc_dec_ret
+.p2align	4
+.Lcbc_dec_tail_partial:
+	movaps	%xmm2,(%rsp)
+	movq	$16,%rcx
+	movq	%rsi,%rdi
+	subq	%rdx,%rcx
+	leaq	(%rsp),%rsi
+.long	0x9066A4F3	
+
+.Lcbc_dec_ret:
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	leaq	(%rbp),%rsp
+	popq	%rbp
+.Lcbc_ret:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_cbc_encrypt:
+.globl	aesni_set_decrypt_key
+.def	aesni_set_decrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_set_decrypt_key:
+	subq	$8,%rsp
+	call	__aesni_set_encrypt_key
+	shll	$4,%edx
+	testl	%eax,%eax
+	jnz	.Ldec_key_ret
+	leaq	16(%r8,%rdx,1),%rcx
+
+	movups	(%r8),%xmm0
+	movups	(%rcx),%xmm1
+	movups	%xmm0,(%rcx)
+	movups	%xmm1,(%r8)
+	leaq	16(%r8),%r8
+	leaq	-16(%rcx),%rcx
+
+.Ldec_key_inverse:
+	movups	(%r8),%xmm0
+	movups	(%rcx),%xmm1
+	aesimc	%xmm0,%xmm0
+	aesimc	%xmm1,%xmm1
+	leaq	16(%r8),%r8
+	leaq	-16(%rcx),%rcx
+	movups	%xmm0,16(%rcx)
+	movups	%xmm1,-16(%r8)
+	cmpq	%r8,%rcx
+	ja	.Ldec_key_inverse
+
+	movups	(%r8),%xmm0
+	aesimc	%xmm0,%xmm0
+	movups	%xmm0,(%rcx)
+.Ldec_key_ret:
+	addq	$8,%rsp
+	retq
+.LSEH_end_set_decrypt_key:
+
+.globl	aesni_set_encrypt_key
+.def	aesni_set_encrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_set_encrypt_key:
+__aesni_set_encrypt_key:
+	subq	$8,%rsp
+	movq	$-1,%rax
+	testq	%rcx,%rcx
+	jz	.Lenc_key_ret
+	testq	%r8,%r8
+	jz	.Lenc_key_ret
+
+	movups	(%rcx),%xmm0
+	xorps	%xmm4,%xmm4
+	leaq	16(%r8),%rax
+	cmpl	$256,%edx
+	je	.L14rounds
+	cmpl	$192,%edx
+	je	.L12rounds
+	cmpl	$128,%edx
+	jne	.Lbad_keybits
+
+.L10rounds:
+	movl	$9,%edx
+	movups	%xmm0,(%r8)
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	.Lkey_expansion_128_cold
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$64,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$128,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$27,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	aeskeygenassist	$54,%xmm0,%xmm1
+	call	.Lkey_expansion_128
+	movups	%xmm0,(%rax)
+	movl	%edx,80(%rax)
+	xorl	%eax,%eax
+	jmp	.Lenc_key_ret
+
+.p2align	4
+.L12rounds:
+	movq	16(%rcx),%xmm2
+	movl	$11,%edx
+	movups	%xmm0,(%r8)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	.Lkey_expansion_192a_cold
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	.Lkey_expansion_192a
+	aeskeygenassist	$128,%xmm2,%xmm1
+	call	.Lkey_expansion_192b
+	movups	%xmm0,(%rax)
+	movl	%edx,48(%rax)
+	xorq	%rax,%rax
+	jmp	.Lenc_key_ret
+
+.p2align	4
+.L14rounds:
+	movups	16(%rcx),%xmm2
+	movl	$13,%edx
+	leaq	16(%rax),%rax
+	movups	%xmm0,(%r8)
+	movups	%xmm2,16(%r8)
+	aeskeygenassist	$1,%xmm2,%xmm1
+	call	.Lkey_expansion_256a_cold
+	aeskeygenassist	$1,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$2,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$2,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$4,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$4,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$8,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$8,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$16,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$16,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$32,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	aeskeygenassist	$32,%xmm0,%xmm1
+	call	.Lkey_expansion_256b
+	aeskeygenassist	$64,%xmm2,%xmm1
+	call	.Lkey_expansion_256a
+	movups	%xmm0,(%rax)
+	movl	%edx,16(%rax)
+	xorq	%rax,%rax
+	jmp	.Lenc_key_ret
+
+.p2align	4
+.Lbad_keybits:
+	movq	$-2,%rax
+.Lenc_key_ret:
+	addq	$8,%rsp
+	retq
+.LSEH_end_set_encrypt_key:
+
+.p2align	4
+.Lkey_expansion_128:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_128_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.p2align	4
+.Lkey_expansion_192a:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_192a_cold:
+	movaps	%xmm2,%xmm5
+.Lkey_expansion_192b_warm:
+	shufps	$16,%xmm0,%xmm4
+	movdqa	%xmm2,%xmm3
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	pslldq	$4,%xmm3
+	xorps	%xmm4,%xmm0
+	pshufd	$85,%xmm1,%xmm1
+	pxor	%xmm3,%xmm2
+	pxor	%xmm1,%xmm0
+	pshufd	$255,%xmm0,%xmm3
+	pxor	%xmm3,%xmm2
+	retq
+
+.p2align	4
+.Lkey_expansion_192b:
+	movaps	%xmm0,%xmm3
+	shufps	$68,%xmm0,%xmm5
+	movups	%xmm5,(%rax)
+	shufps	$78,%xmm2,%xmm3
+	movups	%xmm3,16(%rax)
+	leaq	32(%rax),%rax
+	jmp	.Lkey_expansion_192b_warm
+
+.p2align	4
+.Lkey_expansion_256a:
+	movups	%xmm2,(%rax)
+	leaq	16(%rax),%rax
+.Lkey_expansion_256a_cold:
+	shufps	$16,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$140,%xmm0,%xmm4
+	xorps	%xmm4,%xmm0
+	shufps	$255,%xmm1,%xmm1
+	xorps	%xmm1,%xmm0
+	retq
+
+.p2align	4
+.Lkey_expansion_256b:
+	movups	%xmm0,(%rax)
+	leaq	16(%rax),%rax
+
+	shufps	$16,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$140,%xmm2,%xmm4
+	xorps	%xmm4,%xmm2
+	shufps	$170,%xmm1,%xmm1
+	xorps	%xmm1,%xmm2
+	retq
+
+
+.p2align	6
+.Lbswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.Lincrement32:
+.long	6,6,6,0
+.Lincrement64:
+.long	1,0,0,0
+.Lxts_magic:
+.long	0x87,0,1,0
+
+.byte	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
+
+.def	ecb_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+ecb_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	152(%r8),%rax
+
+	jmp	.Lcommon_seh_tail
+
+
+.def	ccm64_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+ccm64_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	0(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$8,%ecx
+.long	0xa548f3fc		
+	leaq	88(%rax),%rax
+
+	jmp	.Lcommon_seh_tail
+
+
+.def	ctr32_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+ctr32_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	leaq	.Lctr32_body(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	leaq	.Lctr32_ret(%rip),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	32(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$20,%ecx
+.long	0xa548f3fc		
+
+	jmp	.Lcommon_rbp_tail
+
+
+.def	xts_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+xts_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	96(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$20,%ecx
+.long	0xa548f3fc		
+
+	jmp	.Lcommon_rbp_tail
+
+.def	cbc_se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+cbc_se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	152(%r8),%rax
+	movq	248(%r8),%rbx
+
+	leaq	.Lcbc_decrypt(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	leaq	.Lcbc_decrypt_body(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lrestore_cbc_rax
+
+	leaq	.Lcbc_ret(%rip),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	16(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$8,%ecx
+.long	0xa548f3fc		
+
+.Lcommon_rbp_tail:
+	movq	160(%r8),%rax
+	movq	(%rax),%rbp
+	leaq	8(%rax),%rax
+	movq	%rbp,160(%r8)
+	jmp	.Lcommon_seh_tail
+
+.Lrestore_cbc_rax:
+	movq	120(%r8),%rax
+
+.Lcommon_seh_tail:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_aesni_ecb_encrypt
+.rva	.LSEH_end_aesni_ecb_encrypt
+.rva	.LSEH_info_ecb
+
+.rva	.LSEH_begin_aesni_ccm64_encrypt_blocks
+.rva	.LSEH_end_aesni_ccm64_encrypt_blocks
+.rva	.LSEH_info_ccm64_enc
+
+.rva	.LSEH_begin_aesni_ccm64_decrypt_blocks
+.rva	.LSEH_end_aesni_ccm64_decrypt_blocks
+.rva	.LSEH_info_ccm64_dec
+
+.rva	.LSEH_begin_aesni_ctr32_encrypt_blocks
+.rva	.LSEH_end_aesni_ctr32_encrypt_blocks
+.rva	.LSEH_info_ctr32
+
+.rva	.LSEH_begin_aesni_xts_encrypt
+.rva	.LSEH_end_aesni_xts_encrypt
+.rva	.LSEH_info_xts_enc
+
+.rva	.LSEH_begin_aesni_xts_decrypt
+.rva	.LSEH_end_aesni_xts_decrypt
+.rva	.LSEH_info_xts_dec
+.rva	.LSEH_begin_aesni_cbc_encrypt
+.rva	.LSEH_end_aesni_cbc_encrypt
+.rva	.LSEH_info_cbc
+
+.rva	aesni_set_decrypt_key
+.rva	.LSEH_end_set_decrypt_key
+.rva	.LSEH_info_key
+
+.rva	aesni_set_encrypt_key
+.rva	.LSEH_end_set_encrypt_key
+.rva	.LSEH_info_key
+.section	.xdata
+.p2align	3
+.LSEH_info_ecb:
+.byte	9,0,0,0
+.rva	ecb_se_handler
+.LSEH_info_ccm64_enc:
+.byte	9,0,0,0
+.rva	ccm64_se_handler
+.rva	.Lccm64_enc_body,.Lccm64_enc_ret	
+.LSEH_info_ccm64_dec:
+.byte	9,0,0,0
+.rva	ccm64_se_handler
+.rva	.Lccm64_dec_body,.Lccm64_dec_ret	
+.LSEH_info_ctr32:
+.byte	9,0,0,0
+.rva	ctr32_se_handler
+.LSEH_info_xts_enc:
+.byte	9,0,0,0
+.rva	xts_se_handler
+.rva	.Lxts_enc_body,.Lxts_enc_epilogue	
+.LSEH_info_xts_dec:
+.byte	9,0,0,0
+.rva	xts_se_handler
+.rva	.Lxts_dec_body,.Lxts_dec_epilogue	
+.LSEH_info_cbc:
+.byte	9,0,0,0
+.rva	cbc_se_handler
+.LSEH_info_key:
+.byte	0x01,0x04,0x01,0x00
+.byte	0x04,0x02,0x00,0x00	
diff --git a/crypto/aes/aesni-sha1-elf-x86_64.S b/crypto/aes/aesni-sha1-elf-x86_64.S
new file mode 100644
index 0000000..0d7e94a
--- /dev/null
+++ b/crypto/aes/aesni-sha1-elf-x86_64.S
@@ -0,0 +1,1403 @@
+#include "x86_arch.h"
+.text	
+
+.hidden	OPENSSL_ia32cap_P
+
+.globl	aesni_cbc_sha1_enc
+.type	aesni_cbc_sha1_enc,@function
+.align	16
+aesni_cbc_sha1_enc:
+	endbr64
+
+	movl	OPENSSL_ia32cap_P+0(%rip),%r10d
+	movl	OPENSSL_ia32cap_P+4(%rip),%r11d
+	jmp	aesni_cbc_sha1_enc_ssse3
+	retq
+.size	aesni_cbc_sha1_enc,.-aesni_cbc_sha1_enc
+.type	aesni_cbc_sha1_enc_ssse3,@function
+.align	16
+aesni_cbc_sha1_enc_ssse3:
+	endbr64
+	movq	8(%rsp),%r10
+
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-104(%rsp),%rsp
+
+
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movdqu	(%r8),%xmm11
+	movq	%r8,88(%rsp)
+	shlq	$6,%r14
+	subq	%r12,%r13
+	movl	240(%r15),%r8d
+	addq	%r10,%r14
+
+	leaq	K_XX_XX(%rip),%r11
+	movl	0(%r9),%eax
+	movl	4(%r9),%ebx
+	movl	8(%r9),%ecx
+	movl	12(%r9),%edx
+	movl	%ebx,%esi
+	movl	16(%r9),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	movups	(%r15),%xmm13
+	movups	16(%r15),%xmm14
+	jmp	.Loop_ssse3
+.align	16
+.Loop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	movups	0(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	cmpl	$11,%r8d
+	jb	.Laesenclast1
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast1
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast1:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	movups	16(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,0(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast2
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast2
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast2:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	movups	32(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,16(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	cmpl	$11,%r8d
+	jb	.Laesenclast3
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast3
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast3:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	movups	48(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,32(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r14,%r10
+	je	.Ldone_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast4
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast4
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast4:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	leaq	64(%r12),%r12
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	addl	12(%r9),%edx
+	movl	%eax,0(%r9)
+	addl	16(%r9),%ebp
+	movl	%esi,4(%r9)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	jmp	.Loop_ssse3
+
+.align	16
+.Ldone_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast5
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast5
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast5:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	movq	88(%rsp),%r8
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	movl	%eax,0(%r9)
+	addl	12(%r9),%edx
+	movl	%esi,4(%r9)
+	addl	16(%r9),%ebp
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	movups	%xmm11,(%r8)
+	leaq	104(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue_ssse3:
+	retq
+.size	aesni_cbc_sha1_enc_ssse3,.-aesni_cbc_sha1_enc_ssse3
+.section	.rodata
+.align	64
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+.align	64
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/aesni-sha1-macosx-x86_64.S b/crypto/aes/aesni-sha1-macosx-x86_64.S
new file mode 100644
index 0000000..3e88b1a
--- /dev/null
+++ b/crypto/aes/aesni-sha1-macosx-x86_64.S
@@ -0,0 +1,1398 @@
+#include "x86_arch.h"
+.text	
+
+.private_extern	_OPENSSL_ia32cap_P
+
+.globl	_aesni_cbc_sha1_enc
+
+.p2align	4
+_aesni_cbc_sha1_enc:
+
+	movl	_OPENSSL_ia32cap_P+0(%rip),%r10d
+	movl	_OPENSSL_ia32cap_P+4(%rip),%r11d
+	jmp	aesni_cbc_sha1_enc_ssse3
+	retq
+
+
+.p2align	4
+aesni_cbc_sha1_enc_ssse3:
+	movq	8(%rsp),%r10
+
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-104(%rsp),%rsp
+
+
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movdqu	(%r8),%xmm11
+	movq	%r8,88(%rsp)
+	shlq	$6,%r14
+	subq	%r12,%r13
+	movl	240(%r15),%r8d
+	addq	%r10,%r14
+
+	leaq	K_XX_XX(%rip),%r11
+	movl	0(%r9),%eax
+	movl	4(%r9),%ebx
+	movl	8(%r9),%ecx
+	movl	12(%r9),%edx
+	movl	%ebx,%esi
+	movl	16(%r9),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	movups	(%r15),%xmm13
+	movups	16(%r15),%xmm14
+	jmp	L$oop_ssse3
+.p2align	4
+L$oop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	movups	0(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	cmpl	$11,%r8d
+	jb	L$aesenclast1
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	L$aesenclast1
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+L$aesenclast1:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	movups	16(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,0(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	L$aesenclast2
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	L$aesenclast2
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+L$aesenclast2:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	movups	32(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,16(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	cmpl	$11,%r8d
+	jb	L$aesenclast3
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	L$aesenclast3
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+L$aesenclast3:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	movups	48(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,32(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r14,%r10
+	je	L$done_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	L$aesenclast4
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	L$aesenclast4
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+L$aesenclast4:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	leaq	64(%r12),%r12
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	addl	12(%r9),%edx
+	movl	%eax,0(%r9)
+	addl	16(%r9),%ebp
+	movl	%esi,4(%r9)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	jmp	L$oop_ssse3
+
+.p2align	4
+L$done_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	L$aesenclast5
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	L$aesenclast5
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+L$aesenclast5:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	movq	88(%rsp),%r8
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	movl	%eax,0(%r9)
+	addl	12(%r9),%edx
+	movl	%esi,4(%r9)
+	addl	16(%r9),%ebp
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	movups	%xmm11,(%r8)
+	leaq	104(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$epilogue_ssse3:
+	retq
+
+.p2align	6
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+
+.byte	65,69,83,78,73,45,67,66,67,43,83,72,65,49,32,115,116,105,116,99,104,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
diff --git a/crypto/aes/aesni-sha1-masm-x86_64.S b/crypto/aes/aesni-sha1-masm-x86_64.S
new file mode 100644
index 0000000..90327a5
--- /dev/null
+++ b/crypto/aes/aesni-sha1-masm-x86_64.S
@@ -0,0 +1,1616 @@
+; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/aes/aesni-sha1-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+EXTERN	OPENSSL_ia32cap_P:NEAR
+
+
+PUBLIC	aesni_cbc_sha1_enc
+
+ALIGN	16
+aesni_cbc_sha1_enc	PROC PUBLIC
+
+	mov	r10d,DWORD PTR[((OPENSSL_ia32cap_P+0))]
+	mov	r11d,DWORD PTR[((OPENSSL_ia32cap_P+4))]
+	jmp	aesni_cbc_sha1_enc_ssse3
+	DB	0F3h,0C3h		;repret
+aesni_cbc_sha1_enc	ENDP
+
+ALIGN	16
+aesni_cbc_sha1_enc_ssse3	PROC PRIVATE
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_cbc_sha1_enc_ssse3::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	mov	r10,QWORD PTR[56+rsp]
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,QWORD PTR[((-264))+rsp]
+
+
+	movaps	XMMWORD PTR[(96+0)+rsp],xmm6
+	movaps	XMMWORD PTR[(96+16)+rsp],xmm7
+	movaps	XMMWORD PTR[(96+32)+rsp],xmm8
+	movaps	XMMWORD PTR[(96+48)+rsp],xmm9
+	movaps	XMMWORD PTR[(96+64)+rsp],xmm10
+	movaps	XMMWORD PTR[(96+80)+rsp],xmm11
+	movaps	XMMWORD PTR[(96+96)+rsp],xmm12
+	movaps	XMMWORD PTR[(96+112)+rsp],xmm13
+	movaps	XMMWORD PTR[(96+128)+rsp],xmm14
+	movaps	XMMWORD PTR[(96+144)+rsp],xmm15
+$L$prologue_ssse3::
+	mov	r12,rdi
+	mov	r13,rsi
+	mov	r14,rdx
+	mov	r15,rcx
+	movdqu	xmm11,XMMWORD PTR[r8]
+	mov	QWORD PTR[88+rsp],r8
+	shl	r14,6
+	sub	r13,r12
+	mov	r8d,DWORD PTR[240+r15]
+	add	r14,r10
+
+	lea	r11,QWORD PTR[K_XX_XX]
+	mov	eax,DWORD PTR[r9]
+	mov	ebx,DWORD PTR[4+r9]
+	mov	ecx,DWORD PTR[8+r9]
+	mov	edx,DWORD PTR[12+r9]
+	mov	esi,ebx
+	mov	ebp,DWORD PTR[16+r9]
+
+	movdqa	xmm6,XMMWORD PTR[64+r11]
+	movdqa	xmm9,XMMWORD PTR[r11]
+	movdqu	xmm0,XMMWORD PTR[r10]
+	movdqu	xmm1,XMMWORD PTR[16+r10]
+	movdqu	xmm2,XMMWORD PTR[32+r10]
+	movdqu	xmm3,XMMWORD PTR[48+r10]
+DB	102,15,56,0,198
+	add	r10,64
+DB	102,15,56,0,206
+DB	102,15,56,0,214
+DB	102,15,56,0,222
+	paddd	xmm0,xmm9
+	paddd	xmm1,xmm9
+	paddd	xmm2,xmm9
+	movdqa	XMMWORD PTR[rsp],xmm0
+	psubd	xmm0,xmm9
+	movdqa	XMMWORD PTR[16+rsp],xmm1
+	psubd	xmm1,xmm9
+	movdqa	XMMWORD PTR[32+rsp],xmm2
+	psubd	xmm2,xmm9
+	movups	xmm13,XMMWORD PTR[r15]
+	movups	xmm14,XMMWORD PTR[16+r15]
+	jmp	$L$oop_ssse3
+ALIGN	16
+$L$oop_ssse3::
+	movdqa	xmm4,xmm1
+	add	ebp,DWORD PTR[rsp]
+	movups	xmm12,XMMWORD PTR[r12]
+	xorps	xmm12,xmm13
+	xorps	xmm11,xmm12
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[32+r15]
+	xor	ecx,edx
+	movdqa	xmm8,xmm3
+DB	102,15,58,15,224,8
+	mov	edi,eax
+	rol	eax,5
+	paddd	xmm9,xmm3
+	and	esi,ecx
+	xor	ecx,edx
+	psrldq	xmm8,4
+	xor	esi,edx
+	add	ebp,eax
+	pxor	xmm4,xmm0
+	ror	ebx,2
+	add	ebp,esi
+	pxor	xmm8,xmm2
+	add	edx,DWORD PTR[4+rsp]
+	xor	ebx,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	pxor	xmm4,xmm8
+	and	edi,ebx
+	xor	ebx,ecx
+	movdqa	XMMWORD PTR[48+rsp],xmm9
+	xor	edi,ecx
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[48+r15]
+	add	edx,ebp
+	movdqa	xmm10,xmm4
+	movdqa	xmm8,xmm4
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[8+rsp]
+	xor	eax,ebx
+	pslldq	xmm10,12
+	paddd	xmm4,xmm4
+	mov	edi,edx
+	rol	edx,5
+	and	esi,eax
+	xor	eax,ebx
+	psrld	xmm8,31
+	xor	esi,ebx
+	add	ecx,edx
+	movdqa	xmm9,xmm10
+	ror	ebp,7
+	add	ecx,esi
+	psrld	xmm10,30
+	por	xmm4,xmm8
+	add	ebx,DWORD PTR[12+rsp]
+	xor	ebp,eax
+	mov	esi,ecx
+	rol	ecx,5
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[64+r15]
+	pslld	xmm9,2
+	pxor	xmm4,xmm10
+	and	edi,ebp
+	xor	ebp,eax
+	movdqa	xmm10,XMMWORD PTR[r11]
+	xor	edi,eax
+	add	ebx,ecx
+	pxor	xmm4,xmm9
+	ror	edx,7
+	add	ebx,edi
+	movdqa	xmm5,xmm2
+	add	eax,DWORD PTR[16+rsp]
+	xor	edx,ebp
+	movdqa	xmm9,xmm4
+DB	102,15,58,15,233,8
+	mov	edi,ebx
+	rol	ebx,5
+	paddd	xmm10,xmm4
+	and	esi,edx
+	xor	edx,ebp
+	psrldq	xmm9,4
+	xor	esi,ebp
+	add	eax,ebx
+	pxor	xmm5,xmm1
+	ror	ecx,7
+	add	eax,esi
+	pxor	xmm9,xmm3
+	add	ebp,DWORD PTR[20+rsp]
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[80+r15]
+	xor	ecx,edx
+	mov	esi,eax
+	rol	eax,5
+	pxor	xmm5,xmm9
+	and	edi,ecx
+	xor	ecx,edx
+	movdqa	XMMWORD PTR[rsp],xmm10
+	xor	edi,edx
+	add	ebp,eax
+	movdqa	xmm8,xmm5
+	movdqa	xmm9,xmm5
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[24+rsp]
+	xor	ebx,ecx
+	pslldq	xmm8,12
+	paddd	xmm5,xmm5
+	mov	edi,ebp
+	rol	ebp,5
+	and	esi,ebx
+	xor	ebx,ecx
+	psrld	xmm9,31
+	xor	esi,ecx
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[96+r15]
+	add	edx,ebp
+	movdqa	xmm10,xmm8
+	ror	eax,7
+	add	edx,esi
+	psrld	xmm8,30
+	por	xmm5,xmm9
+	add	ecx,DWORD PTR[28+rsp]
+	xor	eax,ebx
+	mov	esi,edx
+	rol	edx,5
+	pslld	xmm10,2
+	pxor	xmm5,xmm8
+	and	edi,eax
+	xor	eax,ebx
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	xor	edi,ebx
+	add	ecx,edx
+	pxor	xmm5,xmm10
+	ror	ebp,7
+	add	ecx,edi
+	movdqa	xmm6,xmm3
+	add	ebx,DWORD PTR[32+rsp]
+	xor	ebp,eax
+	movdqa	xmm10,xmm5
+DB	102,15,58,15,242,8
+	mov	edi,ecx
+	rol	ecx,5
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[112+r15]
+	paddd	xmm8,xmm5
+	and	esi,ebp
+	xor	ebp,eax
+	psrldq	xmm10,4
+	xor	esi,eax
+	add	ebx,ecx
+	pxor	xmm6,xmm2
+	ror	edx,7
+	add	ebx,esi
+	pxor	xmm10,xmm4
+	add	eax,DWORD PTR[36+rsp]
+	xor	edx,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	pxor	xmm6,xmm10
+	and	edi,edx
+	xor	edx,ebp
+	movdqa	XMMWORD PTR[16+rsp],xmm8
+	xor	edi,ebp
+	add	eax,ebx
+	movdqa	xmm9,xmm6
+	movdqa	xmm10,xmm6
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[40+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[128+r15]
+	xor	ecx,edx
+	pslldq	xmm9,12
+	paddd	xmm6,xmm6
+	mov	edi,eax
+	rol	eax,5
+	and	esi,ecx
+	xor	ecx,edx
+	psrld	xmm10,31
+	xor	esi,edx
+	add	ebp,eax
+	movdqa	xmm8,xmm9
+	ror	ebx,7
+	add	ebp,esi
+	psrld	xmm9,30
+	por	xmm6,xmm10
+	add	edx,DWORD PTR[44+rsp]
+	xor	ebx,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	pslld	xmm8,2
+	pxor	xmm6,xmm9
+	and	edi,ebx
+	xor	ebx,ecx
+	movdqa	xmm9,XMMWORD PTR[16+r11]
+	xor	edi,ecx
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[144+r15]
+	add	edx,ebp
+	pxor	xmm6,xmm8
+	ror	eax,7
+	add	edx,edi
+	movdqa	xmm7,xmm4
+	add	ecx,DWORD PTR[48+rsp]
+	xor	eax,ebx
+	movdqa	xmm8,xmm6
+DB	102,15,58,15,251,8
+	mov	edi,edx
+	rol	edx,5
+	paddd	xmm9,xmm6
+	and	esi,eax
+	xor	eax,ebx
+	psrldq	xmm8,4
+	xor	esi,ebx
+	add	ecx,edx
+	pxor	xmm7,xmm3
+	ror	ebp,7
+	add	ecx,esi
+	pxor	xmm8,xmm5
+	add	ebx,DWORD PTR[52+rsp]
+	xor	ebp,eax
+	mov	esi,ecx
+	rol	ecx,5
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[160+r15]
+	pxor	xmm7,xmm8
+	and	edi,ebp
+	xor	ebp,eax
+	movdqa	XMMWORD PTR[32+rsp],xmm9
+	xor	edi,eax
+	add	ebx,ecx
+	movdqa	xmm10,xmm7
+	movdqa	xmm8,xmm7
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[56+rsp]
+	xor	edx,ebp
+	pslldq	xmm10,12
+	paddd	xmm7,xmm7
+	mov	edi,ebx
+	rol	ebx,5
+	and	esi,edx
+	xor	edx,ebp
+	psrld	xmm8,31
+	xor	esi,ebp
+	add	eax,ebx
+	movdqa	xmm9,xmm10
+	ror	ecx,7
+	add	eax,esi
+	psrld	xmm10,30
+	por	xmm7,xmm8
+	add	ebp,DWORD PTR[60+rsp]
+	cmp	r8d,11
+	jb	$L$aesenclast1
+	movups	xmm14,XMMWORD PTR[176+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[192+r15]
+	aesenc	xmm11,xmm14
+	je	$L$aesenclast1
+	movups	xmm14,XMMWORD PTR[208+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[224+r15]
+	aesenc	xmm11,xmm14
+$L$aesenclast1::
+	aesenclast	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[16+r15]
+	xor	ecx,edx
+	mov	esi,eax
+	rol	eax,5
+	pslld	xmm9,2
+	pxor	xmm7,xmm10
+	and	edi,ecx
+	xor	ecx,edx
+	movdqa	xmm10,XMMWORD PTR[16+r11]
+	xor	edi,edx
+	add	ebp,eax
+	pxor	xmm7,xmm9
+	ror	ebx,7
+	add	ebp,edi
+	movdqa	xmm9,xmm7
+	add	edx,DWORD PTR[rsp]
+	pxor	xmm0,xmm4
+DB	102,68,15,58,15,206,8
+	xor	ebx,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	pxor	xmm0,xmm1
+	and	esi,ebx
+	xor	ebx,ecx
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm7
+	xor	esi,ecx
+	movups	xmm12,XMMWORD PTR[16+r12]
+	xorps	xmm12,xmm13
+	movups	XMMWORD PTR[r12*1+r13],xmm11
+	xorps	xmm11,xmm12
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[32+r15]
+	add	edx,ebp
+	pxor	xmm0,xmm9
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[4+rsp]
+	xor	eax,ebx
+	movdqa	xmm9,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm10
+	mov	esi,edx
+	rol	edx,5
+	and	edi,eax
+	xor	eax,ebx
+	pslld	xmm0,2
+	xor	edi,ebx
+	add	ecx,edx
+	psrld	xmm9,30
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[8+rsp]
+	xor	ebp,eax
+	mov	edi,ecx
+	rol	ecx,5
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[48+r15]
+	por	xmm0,xmm9
+	and	esi,ebp
+	xor	ebp,eax
+	movdqa	xmm10,xmm0
+	xor	esi,eax
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[12+rsp]
+	xor	edx,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	and	edi,edx
+	xor	edx,ebp
+	xor	edi,ebp
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[16+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[64+r15]
+	pxor	xmm1,xmm5
+DB	102,68,15,58,15,215,8
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	pxor	xmm1,xmm2
+	xor	esi,ecx
+	add	ebp,eax
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm0
+	ror	ebx,7
+	add	ebp,esi
+	pxor	xmm1,xmm10
+	add	edx,DWORD PTR[20+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	movdqa	xmm10,xmm1
+	movdqa	XMMWORD PTR[rsp],xmm8
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	pslld	xmm1,2
+	add	ecx,DWORD PTR[24+rsp]
+	xor	esi,ebx
+	psrld	xmm10,30
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[80+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	por	xmm1,xmm10
+	add	ebx,DWORD PTR[28+rsp]
+	xor	edi,eax
+	movdqa	xmm8,xmm1
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[32+rsp]
+	pxor	xmm2,xmm6
+DB	102,68,15,58,15,192,8
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	pxor	xmm2,xmm3
+	xor	esi,edx
+	add	eax,ebx
+	movdqa	xmm10,XMMWORD PTR[32+r11]
+	paddd	xmm9,xmm1
+	ror	ecx,7
+	add	eax,esi
+	pxor	xmm2,xmm8
+	add	ebp,DWORD PTR[36+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[96+r15]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	movdqa	xmm8,xmm2
+	movdqa	XMMWORD PTR[16+rsp],xmm9
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	pslld	xmm2,2
+	add	edx,DWORD PTR[40+rsp]
+	xor	esi,ecx
+	psrld	xmm8,30
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	por	xmm2,xmm8
+	add	ecx,DWORD PTR[44+rsp]
+	xor	edi,ebx
+	movdqa	xmm9,xmm2
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[112+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[48+rsp]
+	pxor	xmm3,xmm7
+DB	102,68,15,58,15,201,8
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	pxor	xmm3,xmm4
+	xor	esi,ebp
+	add	ebx,ecx
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm2
+	ror	edx,7
+	add	ebx,esi
+	pxor	xmm3,xmm9
+	add	eax,DWORD PTR[52+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	movdqa	xmm9,xmm3
+	movdqa	XMMWORD PTR[32+rsp],xmm10
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	pslld	xmm3,2
+	add	ebp,DWORD PTR[56+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[128+r15]
+	xor	esi,edx
+	psrld	xmm9,30
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	por	xmm3,xmm9
+	add	edx,DWORD PTR[60+rsp]
+	xor	edi,ecx
+	movdqa	xmm10,xmm3
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[rsp]
+	pxor	xmm4,xmm0
+DB	102,68,15,58,15,210,8
+	xor	esi,ebx
+	mov	edi,edx
+	rol	edx,5
+	pxor	xmm4,xmm5
+	xor	esi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[144+r15]
+	add	ecx,edx
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm3
+	ror	ebp,7
+	add	ecx,esi
+	pxor	xmm4,xmm10
+	add	ebx,DWORD PTR[4+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	movdqa	xmm10,xmm4
+	movdqa	XMMWORD PTR[48+rsp],xmm8
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	pslld	xmm4,2
+	add	eax,DWORD PTR[8+rsp]
+	xor	esi,ebp
+	psrld	xmm10,30
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	por	xmm4,xmm10
+	add	ebp,DWORD PTR[12+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[160+r15]
+	xor	edi,edx
+	movdqa	xmm8,xmm4
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[16+rsp]
+	pxor	xmm5,xmm1
+DB	102,68,15,58,15,195,8
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	pxor	xmm5,xmm6
+	xor	esi,ebx
+	add	edx,ebp
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm4
+	ror	eax,7
+	add	edx,esi
+	pxor	xmm5,xmm8
+	add	ecx,DWORD PTR[20+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	movdqa	xmm8,xmm5
+	movdqa	XMMWORD PTR[rsp],xmm9
+	xor	edi,eax
+	cmp	r8d,11
+	jb	$L$aesenclast2
+	movups	xmm14,XMMWORD PTR[176+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[192+r15]
+	aesenc	xmm11,xmm14
+	je	$L$aesenclast2
+	movups	xmm14,XMMWORD PTR[208+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[224+r15]
+	aesenc	xmm11,xmm14
+$L$aesenclast2::
+	aesenclast	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[16+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	pslld	xmm5,2
+	add	ebx,DWORD PTR[24+rsp]
+	xor	esi,eax
+	psrld	xmm8,30
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	por	xmm5,xmm8
+	add	eax,DWORD PTR[28+rsp]
+	xor	edi,ebp
+	movdqa	xmm9,xmm5
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	mov	edi,ecx
+	movups	xmm12,XMMWORD PTR[32+r12]
+	xorps	xmm12,xmm13
+	movups	XMMWORD PTR[16+r12*1+r13],xmm11
+	xorps	xmm11,xmm12
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[32+r15]
+	pxor	xmm6,xmm2
+DB	102,68,15,58,15,204,8
+	xor	ecx,edx
+	add	ebp,DWORD PTR[32+rsp]
+	and	edi,edx
+	pxor	xmm6,xmm7
+	and	esi,ecx
+	ror	ebx,7
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm5
+	add	ebp,edi
+	mov	edi,eax
+	pxor	xmm6,xmm9
+	rol	eax,5
+	add	ebp,esi
+	xor	ecx,edx
+	add	ebp,eax
+	movdqa	xmm9,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm10
+	mov	esi,ebx
+	xor	ebx,ecx
+	add	edx,DWORD PTR[36+rsp]
+	and	esi,ecx
+	pslld	xmm6,2
+	and	edi,ebx
+	ror	eax,7
+	psrld	xmm9,30
+	add	edx,esi
+	mov	esi,ebp
+	rol	ebp,5
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[48+r15]
+	add	edx,edi
+	xor	ebx,ecx
+	add	edx,ebp
+	por	xmm6,xmm9
+	mov	edi,eax
+	xor	eax,ebx
+	movdqa	xmm10,xmm6
+	add	ecx,DWORD PTR[40+rsp]
+	and	edi,ebx
+	and	esi,eax
+	ror	ebp,7
+	add	ecx,edi
+	mov	edi,edx
+	rol	edx,5
+	add	ecx,esi
+	xor	eax,ebx
+	add	ecx,edx
+	mov	esi,ebp
+	xor	ebp,eax
+	add	ebx,DWORD PTR[44+rsp]
+	and	esi,eax
+	and	edi,ebp
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[64+r15]
+	ror	edx,7
+	add	ebx,esi
+	mov	esi,ecx
+	rol	ecx,5
+	add	ebx,edi
+	xor	ebp,eax
+	add	ebx,ecx
+	mov	edi,edx
+	pxor	xmm7,xmm3
+DB	102,68,15,58,15,213,8
+	xor	edx,ebp
+	add	eax,DWORD PTR[48+rsp]
+	and	edi,ebp
+	pxor	xmm7,xmm0
+	and	esi,edx
+	ror	ecx,7
+	movdqa	xmm9,XMMWORD PTR[48+r11]
+	paddd	xmm8,xmm6
+	add	eax,edi
+	mov	edi,ebx
+	pxor	xmm7,xmm10
+	rol	ebx,5
+	add	eax,esi
+	xor	edx,ebp
+	add	eax,ebx
+	movdqa	xmm10,xmm7
+	movdqa	XMMWORD PTR[32+rsp],xmm8
+	mov	esi,ecx
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[80+r15]
+	xor	ecx,edx
+	add	ebp,DWORD PTR[52+rsp]
+	and	esi,edx
+	pslld	xmm7,2
+	and	edi,ecx
+	ror	ebx,7
+	psrld	xmm10,30
+	add	ebp,esi
+	mov	esi,eax
+	rol	eax,5
+	add	ebp,edi
+	xor	ecx,edx
+	add	ebp,eax
+	por	xmm7,xmm10
+	mov	edi,ebx
+	xor	ebx,ecx
+	movdqa	xmm8,xmm7
+	add	edx,DWORD PTR[56+rsp]
+	and	edi,ecx
+	and	esi,ebx
+	ror	eax,7
+	add	edx,edi
+	mov	edi,ebp
+	rol	ebp,5
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[96+r15]
+	add	edx,esi
+	xor	ebx,ecx
+	add	edx,ebp
+	mov	esi,eax
+	xor	eax,ebx
+	add	ecx,DWORD PTR[60+rsp]
+	and	esi,ebx
+	and	edi,eax
+	ror	ebp,7
+	add	ecx,esi
+	mov	esi,edx
+	rol	edx,5
+	add	ecx,edi
+	xor	eax,ebx
+	add	ecx,edx
+	mov	edi,ebp
+	pxor	xmm0,xmm4
+DB	102,68,15,58,15,198,8
+	xor	ebp,eax
+	add	ebx,DWORD PTR[rsp]
+	and	edi,eax
+	pxor	xmm0,xmm1
+	and	esi,ebp
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[112+r15]
+	ror	edx,7
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm7
+	add	ebx,edi
+	mov	edi,ecx
+	pxor	xmm0,xmm8
+	rol	ecx,5
+	add	ebx,esi
+	xor	ebp,eax
+	add	ebx,ecx
+	movdqa	xmm8,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm9
+	mov	esi,edx
+	xor	edx,ebp
+	add	eax,DWORD PTR[4+rsp]
+	and	esi,ebp
+	pslld	xmm0,2
+	and	edi,edx
+	ror	ecx,7
+	psrld	xmm8,30
+	add	eax,esi
+	mov	esi,ebx
+	rol	ebx,5
+	add	eax,edi
+	xor	edx,ebp
+	add	eax,ebx
+	por	xmm0,xmm8
+	mov	edi,ecx
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[128+r15]
+	xor	ecx,edx
+	movdqa	xmm9,xmm0
+	add	ebp,DWORD PTR[8+rsp]
+	and	edi,edx
+	and	esi,ecx
+	ror	ebx,7
+	add	ebp,edi
+	mov	edi,eax
+	rol	eax,5
+	add	ebp,esi
+	xor	ecx,edx
+	add	ebp,eax
+	mov	esi,ebx
+	xor	ebx,ecx
+	add	edx,DWORD PTR[12+rsp]
+	and	esi,ecx
+	and	edi,ebx
+	ror	eax,7
+	add	edx,esi
+	mov	esi,ebp
+	rol	ebp,5
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[144+r15]
+	add	edx,edi
+	xor	ebx,ecx
+	add	edx,ebp
+	mov	edi,eax
+	pxor	xmm1,xmm5
+DB	102,68,15,58,15,207,8
+	xor	eax,ebx
+	add	ecx,DWORD PTR[16+rsp]
+	and	edi,ebx
+	pxor	xmm1,xmm2
+	and	esi,eax
+	ror	ebp,7
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm0
+	add	ecx,edi
+	mov	edi,edx
+	pxor	xmm1,xmm9
+	rol	edx,5
+	add	ecx,esi
+	xor	eax,ebx
+	add	ecx,edx
+	movdqa	xmm9,xmm1
+	movdqa	XMMWORD PTR[rsp],xmm10
+	mov	esi,ebp
+	xor	ebp,eax
+	add	ebx,DWORD PTR[20+rsp]
+	and	esi,eax
+	pslld	xmm1,2
+	and	edi,ebp
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[160+r15]
+	ror	edx,7
+	psrld	xmm9,30
+	add	ebx,esi
+	mov	esi,ecx
+	rol	ecx,5
+	add	ebx,edi
+	xor	ebp,eax
+	add	ebx,ecx
+	por	xmm1,xmm9
+	mov	edi,edx
+	xor	edx,ebp
+	movdqa	xmm10,xmm1
+	add	eax,DWORD PTR[24+rsp]
+	and	edi,ebp
+	and	esi,edx
+	ror	ecx,7
+	add	eax,edi
+	mov	edi,ebx
+	rol	ebx,5
+	add	eax,esi
+	xor	edx,ebp
+	add	eax,ebx
+	mov	esi,ecx
+	cmp	r8d,11
+	jb	$L$aesenclast3
+	movups	xmm14,XMMWORD PTR[176+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[192+r15]
+	aesenc	xmm11,xmm14
+	je	$L$aesenclast3
+	movups	xmm14,XMMWORD PTR[208+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[224+r15]
+	aesenc	xmm11,xmm14
+$L$aesenclast3::
+	aesenclast	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[16+r15]
+	xor	ecx,edx
+	add	ebp,DWORD PTR[28+rsp]
+	and	esi,edx
+	and	edi,ecx
+	ror	ebx,7
+	add	ebp,esi
+	mov	esi,eax
+	rol	eax,5
+	add	ebp,edi
+	xor	ecx,edx
+	add	ebp,eax
+	mov	edi,ebx
+	pxor	xmm2,xmm6
+DB	102,68,15,58,15,208,8
+	xor	ebx,ecx
+	add	edx,DWORD PTR[32+rsp]
+	and	edi,ecx
+	pxor	xmm2,xmm3
+	and	esi,ebx
+	ror	eax,7
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm1
+	add	edx,edi
+	mov	edi,ebp
+	pxor	xmm2,xmm10
+	rol	ebp,5
+	movups	xmm12,XMMWORD PTR[48+r12]
+	xorps	xmm12,xmm13
+	movups	XMMWORD PTR[32+r12*1+r13],xmm11
+	xorps	xmm11,xmm12
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[32+r15]
+	add	edx,esi
+	xor	ebx,ecx
+	add	edx,ebp
+	movdqa	xmm10,xmm2
+	movdqa	XMMWORD PTR[16+rsp],xmm8
+	mov	esi,eax
+	xor	eax,ebx
+	add	ecx,DWORD PTR[36+rsp]
+	and	esi,ebx
+	pslld	xmm2,2
+	and	edi,eax
+	ror	ebp,7
+	psrld	xmm10,30
+	add	ecx,esi
+	mov	esi,edx
+	rol	edx,5
+	add	ecx,edi
+	xor	eax,ebx
+	add	ecx,edx
+	por	xmm2,xmm10
+	mov	edi,ebp
+	xor	ebp,eax
+	movdqa	xmm8,xmm2
+	add	ebx,DWORD PTR[40+rsp]
+	and	edi,eax
+	and	esi,ebp
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[48+r15]
+	ror	edx,7
+	add	ebx,edi
+	mov	edi,ecx
+	rol	ecx,5
+	add	ebx,esi
+	xor	ebp,eax
+	add	ebx,ecx
+	mov	esi,edx
+	xor	edx,ebp
+	add	eax,DWORD PTR[44+rsp]
+	and	esi,ebp
+	and	edi,edx
+	ror	ecx,7
+	add	eax,esi
+	mov	esi,ebx
+	rol	ebx,5
+	add	eax,edi
+	xor	edx,ebp
+	add	eax,ebx
+	add	ebp,DWORD PTR[48+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[64+r15]
+	pxor	xmm3,xmm7
+DB	102,68,15,58,15,193,8
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	pxor	xmm3,xmm4
+	xor	esi,ecx
+	add	ebp,eax
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm2
+	ror	ebx,7
+	add	ebp,esi
+	pxor	xmm3,xmm8
+	add	edx,DWORD PTR[52+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	movdqa	xmm8,xmm3
+	movdqa	XMMWORD PTR[32+rsp],xmm9
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	pslld	xmm3,2
+	add	ecx,DWORD PTR[56+rsp]
+	xor	esi,ebx
+	psrld	xmm8,30
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[80+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	por	xmm3,xmm8
+	add	ebx,DWORD PTR[60+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[rsp]
+	paddd	xmm10,xmm3
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	movdqa	XMMWORD PTR[48+rsp],xmm10
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[4+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[96+r15]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[8+rsp]
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[12+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[112+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	cmp	r10,r14
+	je	$L$done_ssse3
+	movdqa	xmm6,XMMWORD PTR[64+r11]
+	movdqa	xmm9,XMMWORD PTR[r11]
+	movdqu	xmm0,XMMWORD PTR[r10]
+	movdqu	xmm1,XMMWORD PTR[16+r10]
+	movdqu	xmm2,XMMWORD PTR[32+r10]
+	movdqu	xmm3,XMMWORD PTR[48+r10]
+DB	102,15,56,0,198
+	add	r10,64
+	add	ebx,DWORD PTR[16+rsp]
+	xor	esi,eax
+DB	102,15,56,0,206
+	mov	edi,ecx
+	rol	ecx,5
+	paddd	xmm0,xmm9
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	movdqa	XMMWORD PTR[rsp],xmm0
+	add	eax,DWORD PTR[20+rsp]
+	xor	edi,ebp
+	psubd	xmm0,xmm9
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[24+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[128+r15]
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	add	edx,DWORD PTR[28+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[32+rsp]
+	xor	esi,ebx
+DB	102,15,56,0,214
+	mov	edi,edx
+	rol	edx,5
+	paddd	xmm1,xmm9
+	xor	esi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[144+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	movdqa	XMMWORD PTR[16+rsp],xmm1
+	add	ebx,DWORD PTR[36+rsp]
+	xor	edi,eax
+	psubd	xmm1,xmm9
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[40+rsp]
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[44+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[160+r15]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[48+rsp]
+	xor	esi,ecx
+DB	102,15,56,0,222
+	mov	edi,ebp
+	rol	ebp,5
+	paddd	xmm2,xmm9
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	movdqa	XMMWORD PTR[32+rsp],xmm2
+	add	ecx,DWORD PTR[52+rsp]
+	xor	edi,ebx
+	psubd	xmm2,xmm9
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	cmp	r8d,11
+	jb	$L$aesenclast4
+	movups	xmm14,XMMWORD PTR[176+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[192+r15]
+	aesenc	xmm11,xmm14
+	je	$L$aesenclast4
+	movups	xmm14,XMMWORD PTR[208+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[224+r15]
+	aesenc	xmm11,xmm14
+$L$aesenclast4::
+	aesenclast	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[16+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[56+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[60+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	movups	XMMWORD PTR[48+r12*1+r13],xmm11
+	lea	r12,QWORD PTR[64+r12]
+
+	add	eax,DWORD PTR[r9]
+	add	esi,DWORD PTR[4+r9]
+	add	ecx,DWORD PTR[8+r9]
+	add	edx,DWORD PTR[12+r9]
+	mov	DWORD PTR[r9],eax
+	add	ebp,DWORD PTR[16+r9]
+	mov	DWORD PTR[4+r9],esi
+	mov	ebx,esi
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+	mov	DWORD PTR[16+r9],ebp
+	jmp	$L$oop_ssse3
+
+ALIGN	16
+$L$done_ssse3::
+	add	ebx,DWORD PTR[16+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[20+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[24+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[128+r15]
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	add	edx,DWORD PTR[28+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[32+rsp]
+	xor	esi,ebx
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	aesenc	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[144+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	add	ebx,DWORD PTR[36+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[40+rsp]
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[44+rsp]
+	aesenc	xmm11,xmm14
+	movups	xmm15,XMMWORD PTR[160+r15]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[48+rsp]
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[52+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	cmp	r8d,11
+	jb	$L$aesenclast5
+	movups	xmm14,XMMWORD PTR[176+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[192+r15]
+	aesenc	xmm11,xmm14
+	je	$L$aesenclast5
+	movups	xmm14,XMMWORD PTR[208+r15]
+	aesenc	xmm11,xmm15
+	movups	xmm15,XMMWORD PTR[224+r15]
+	aesenc	xmm11,xmm14
+$L$aesenclast5::
+	aesenclast	xmm11,xmm15
+	movups	xmm14,XMMWORD PTR[16+r15]
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[56+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[60+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	movups	XMMWORD PTR[48+r12*1+r13],xmm11
+	mov	r8,QWORD PTR[88+rsp]
+
+	add	eax,DWORD PTR[r9]
+	add	esi,DWORD PTR[4+r9]
+	add	ecx,DWORD PTR[8+r9]
+	mov	DWORD PTR[r9],eax
+	add	edx,DWORD PTR[12+r9]
+	mov	DWORD PTR[4+r9],esi
+	add	ebp,DWORD PTR[16+r9]
+	mov	DWORD PTR[8+r9],ecx
+	mov	DWORD PTR[12+r9],edx
+	mov	DWORD PTR[16+r9],ebp
+	movups	XMMWORD PTR[r8],xmm11
+	movaps	xmm6,XMMWORD PTR[((96+0))+rsp]
+	movaps	xmm7,XMMWORD PTR[((96+16))+rsp]
+	movaps	xmm8,XMMWORD PTR[((96+32))+rsp]
+	movaps	xmm9,XMMWORD PTR[((96+48))+rsp]
+	movaps	xmm10,XMMWORD PTR[((96+64))+rsp]
+	movaps	xmm11,XMMWORD PTR[((96+80))+rsp]
+	movaps	xmm12,XMMWORD PTR[((96+96))+rsp]
+	movaps	xmm13,XMMWORD PTR[((96+112))+rsp]
+	movaps	xmm14,XMMWORD PTR[((96+128))+rsp]
+	movaps	xmm15,XMMWORD PTR[((96+144))+rsp]
+	lea	rsi,QWORD PTR[264+rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$epilogue_ssse3::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_cbc_sha1_enc_ssse3::
+aesni_cbc_sha1_enc_ssse3	ENDP
+ALIGN	64
+K_XX_XX::
+	DD	05a827999h,05a827999h,05a827999h,05a827999h	
+	DD	06ed9eba1h,06ed9eba1h,06ed9eba1h,06ed9eba1h	
+	DD	08f1bbcdch,08f1bbcdch,08f1bbcdch,08f1bbcdch	
+	DD	0ca62c1d6h,0ca62c1d6h,0ca62c1d6h,0ca62c1d6h	
+	DD	000010203h,004050607h,008090a0bh,00c0d0e0fh	
+
+DB	65,69,83,78,73,45,67,66,67,43,83,72,65,49,32,115
+DB	116,105,116,99,104,32,102,111,114,32,120,56,54,95,54,52
+DB	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
+DB	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
+DB	114,103,62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+ssse3_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[96+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,20
+	DD	0a548f3fch		
+	lea	rax,QWORD PTR[264+rax]
+
+	mov	r15,QWORD PTR[rax]
+	mov	r14,QWORD PTR[8+rax]
+	mov	r13,QWORD PTR[16+rax]
+	mov	r12,QWORD PTR[24+rax]
+	mov	rbp,QWORD PTR[32+rax]
+	mov	rbx,QWORD PTR[40+rax]
+	lea	rax,QWORD PTR[48+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$common_seh_tail::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+ssse3_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_aesni_cbc_sha1_enc_ssse3
+	DD	imagerel $L$SEH_end_aesni_cbc_sha1_enc_ssse3
+	DD	imagerel $L$SEH_info_aesni_cbc_sha1_enc_ssse3
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_aesni_cbc_sha1_enc_ssse3::
+DB	9,0,0,0
+	DD	imagerel ssse3_handler
+	DD	imagerel $L$prologue_ssse3,imagerel $L$epilogue_ssse3	
+
+.xdata	ENDS
+END
+
diff --git a/crypto/aes/aesni-sha1-mingw64-x86_64.S b/crypto/aes/aesni-sha1-mingw64-x86_64.S
new file mode 100644
index 0000000..c7a2d5c
--- /dev/null
+++ b/crypto/aes/aesni-sha1-mingw64-x86_64.S
@@ -0,0 +1,1536 @@
+#include "x86_arch.h"
+.text	
+
+
+
+.globl	aesni_cbc_sha1_enc
+.def	aesni_cbc_sha1_enc;	.scl 2;	.type 32;	.endef
+.p2align	4
+aesni_cbc_sha1_enc:
+
+	movl	OPENSSL_ia32cap_P+0(%rip),%r10d
+	movl	OPENSSL_ia32cap_P+4(%rip),%r11d
+	jmp	aesni_cbc_sha1_enc_ssse3
+	retq
+
+.def	aesni_cbc_sha1_enc_ssse3;	.scl 3;	.type 32;	.endef
+.p2align	4
+aesni_cbc_sha1_enc_ssse3:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_aesni_cbc_sha1_enc_ssse3:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	movq	56(%rsp),%r10
+
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-264(%rsp),%rsp
+
+
+	movaps	%xmm6,96+0(%rsp)
+	movaps	%xmm7,96+16(%rsp)
+	movaps	%xmm8,96+32(%rsp)
+	movaps	%xmm9,96+48(%rsp)
+	movaps	%xmm10,96+64(%rsp)
+	movaps	%xmm11,96+80(%rsp)
+	movaps	%xmm12,96+96(%rsp)
+	movaps	%xmm13,96+112(%rsp)
+	movaps	%xmm14,96+128(%rsp)
+	movaps	%xmm15,96+144(%rsp)
+.Lprologue_ssse3:
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movdqu	(%r8),%xmm11
+	movq	%r8,88(%rsp)
+	shlq	$6,%r14
+	subq	%r12,%r13
+	movl	240(%r15),%r8d
+	addq	%r10,%r14
+
+	leaq	K_XX_XX(%rip),%r11
+	movl	0(%r9),%eax
+	movl	4(%r9),%ebx
+	movl	8(%r9),%ecx
+	movl	12(%r9),%edx
+	movl	%ebx,%esi
+	movl	16(%r9),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	movups	(%r15),%xmm13
+	movups	16(%r15),%xmm14
+	jmp	.Loop_ssse3
+.p2align	4
+.Loop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	movups	0(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	cmpl	$11,%r8d
+	jb	.Laesenclast1
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast1
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast1:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	movups	16(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,0(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast2
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast2
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast2:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	movups	32(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,16(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	cmpl	$11,%r8d
+	jb	.Laesenclast3
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast3
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast3:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	movups	48(%r12),%xmm12
+	xorps	%xmm13,%xmm12
+	movups	%xmm11,32(%r13,%r12,1)
+	xorps	%xmm12,%xmm11
+	aesenc	%xmm14,%xmm11
+	movups	32(%r15),%xmm15
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	aesenc	%xmm15,%xmm11
+	movups	48(%r15),%xmm14
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	64(%r15),%xmm15
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	80(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	96(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	aesenc	%xmm15,%xmm11
+	movups	112(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r14,%r10
+	je	.Ldone_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r10),%xmm0
+	movdqu	16(%r10),%xmm1
+	movdqu	32(%r10),%xmm2
+	movdqu	48(%r10),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r10
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast4
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast4
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast4:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	leaq	64(%r12),%r12
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	addl	12(%r9),%edx
+	movl	%eax,0(%r9)
+	addl	16(%r9),%ebp
+	movl	%esi,4(%r9)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	jmp	.Loop_ssse3
+
+.p2align	4
+.Ldone_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	128(%r15),%xmm15
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	aesenc	%xmm15,%xmm11
+	movups	144(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	aesenc	%xmm14,%xmm11
+	movups	160(%r15),%xmm15
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	cmpl	$11,%r8d
+	jb	.Laesenclast5
+	movups	176(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	192(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+	je	.Laesenclast5
+	movups	208(%r15),%xmm14
+	aesenc	%xmm15,%xmm11
+	movups	224(%r15),%xmm15
+	aesenc	%xmm14,%xmm11
+.Laesenclast5:
+	aesenclast	%xmm15,%xmm11
+	movups	16(%r15),%xmm14
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movups	%xmm11,48(%r13,%r12,1)
+	movq	88(%rsp),%r8
+
+	addl	0(%r9),%eax
+	addl	4(%r9),%esi
+	addl	8(%r9),%ecx
+	movl	%eax,0(%r9)
+	addl	12(%r9),%edx
+	movl	%esi,4(%r9)
+	addl	16(%r9),%ebp
+	movl	%ecx,8(%r9)
+	movl	%edx,12(%r9)
+	movl	%ebp,16(%r9)
+	movups	%xmm11,(%r8)
+	movaps	96+0(%rsp),%xmm6
+	movaps	96+16(%rsp),%xmm7
+	movaps	96+32(%rsp),%xmm8
+	movaps	96+48(%rsp),%xmm9
+	movaps	96+64(%rsp),%xmm10
+	movaps	96+80(%rsp),%xmm11
+	movaps	96+96(%rsp),%xmm12
+	movaps	96+112(%rsp),%xmm13
+	movaps	96+128(%rsp),%xmm14
+	movaps	96+144(%rsp),%xmm15
+	leaq	264(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue_ssse3:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_aesni_cbc_sha1_enc_ssse3:
+.p2align	6
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+
+.byte	65,69,83,78,73,45,67,66,67,43,83,72,65,49,32,115,116,105,116,99,104,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
+
+.def	ssse3_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+ssse3_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	96(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$20,%ecx
+.long	0xa548f3fc		
+	leaq	264(%rax),%rax
+
+	movq	0(%rax),%r15
+	movq	8(%rax),%r14
+	movq	16(%rax),%r13
+	movq	24(%rax),%r12
+	movq	32(%rax),%rbp
+	movq	40(%rax),%rbx
+	leaq	48(%rax),%rax
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lcommon_seh_tail:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_aesni_cbc_sha1_enc_ssse3
+.rva	.LSEH_end_aesni_cbc_sha1_enc_ssse3
+.rva	.LSEH_info_aesni_cbc_sha1_enc_ssse3
+.section	.xdata
+.p2align	3
+.LSEH_info_aesni_cbc_sha1_enc_ssse3:
+.byte	9,0,0,0
+.rva	ssse3_handler
+.rva	.Lprologue_ssse3,.Lepilogue_ssse3	
diff --git a/crypto/aes/bsaes-elf-x86_64.S b/crypto/aes/bsaes-elf-x86_64.S
new file mode 100644
index 0000000..602afd0
--- /dev/null
+++ b/crypto/aes/bsaes-elf-x86_64.S
@@ -0,0 +1,2510 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+.type	_bsaes_encrypt8,@function
+.align	64
+_bsaes_encrypt8:
+	endbr64
+	leaq	.LBS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	80(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+_bsaes_encrypt8_bitslice:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	.Lenc_sbox
+.align	16
+.Lenc_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+.Lenc_sbox:
+	pxor	%xmm5,%xmm4
+	pxor	%xmm0,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm1,%xmm5
+	pxor	%xmm15,%xmm4
+
+	pxor	%xmm2,%xmm5
+	pxor	%xmm6,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm3,%xmm2
+	pxor	%xmm4,%xmm3
+	pxor	%xmm0,%xmm2
+
+	pxor	%xmm6,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm6,%xmm10
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm4,%xmm8
+	movdqa	%xmm1,%xmm12
+	movdqa	%xmm5,%xmm11
+
+	pxor	%xmm3,%xmm10
+	pxor	%xmm1,%xmm9
+	pxor	%xmm2,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm3,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm15,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm2,%xmm11
+	pxor	%xmm15,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm6,%xmm12
+	movdqa	%xmm4,%xmm11
+	pxor	%xmm0,%xmm12
+	pxor	%xmm5,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm1,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm3,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm0,%xmm13
+	pand	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm14
+	pand	%xmm15,%xmm12
+	pand	%xmm4,%xmm13
+	por	%xmm5,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm5,%xmm11
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm5,%xmm9
+	pxor	%xmm4,%xmm5
+	pand	%xmm14,%xmm4
+	pand	%xmm13,%xmm5
+	pxor	%xmm4,%xmm5
+	pxor	%xmm9,%xmm4
+	pxor	%xmm15,%xmm11
+	pxor	%xmm2,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm2,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm2
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm2,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm2
+	pxor	%xmm11,%xmm5
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm2
+
+	movdqa	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm7
+	pxor	%xmm3,%xmm11
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm3,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm1,%xmm3
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm1
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm3
+	pxor	%xmm11,%xmm7
+	pxor	%xmm1,%xmm3
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm1
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm6,%xmm10
+	pxor	%xmm0,%xmm6
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm6
+	pxor	%xmm0,%xmm6
+	pxor	%xmm10,%xmm0
+	pxor	%xmm11,%xmm6
+	pxor	%xmm11,%xmm3
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm1
+	pxor	%xmm15,%xmm6
+	pxor	%xmm5,%xmm0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm15,%xmm5
+	pxor	%xmm0,%xmm15
+
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	pxor	%xmm2,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm4,%xmm3
+
+	pxor	%xmm2,%xmm5
+	decl	%r10d
+	jl	.Lenc_done
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm3,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm5,%xmm10
+	pxor	%xmm9,%xmm3
+	pshufd	$147,%xmm2,%xmm11
+	pxor	%xmm10,%xmm5
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm2
+	pshufd	$147,%xmm1,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm1
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm2,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm5,%xmm11
+	pshufd	$78,%xmm2,%xmm7
+	pxor	%xmm1,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm3,%xmm10
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm1,%xmm5
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm12,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm14,%xmm6
+	pxor	%xmm13,%xmm5
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm1
+	movdqa	%xmm8,%xmm4
+	movdqa	48(%r11),%xmm7
+	jnz	.Lenc_loop
+	movdqa	64(%r11),%xmm7
+	jmp	.Lenc_loop
+.align	16
+.Lenc_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm2,%xmm10
+	psrlq	$1,%xmm2
+	pxor	%xmm4,%xmm1
+	pxor	%xmm6,%xmm2
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm2
+	pxor	%xmm1,%xmm4
+	psllq	$1,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$1,%xmm2
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm3,%xmm9
+	psrlq	$1,%xmm3
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm5,%xmm3
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm15
+	pxor	%xmm3,%xmm5
+	psllq	$1,%xmm3
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm2,%xmm10
+	psrlq	$2,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm1,%xmm2
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm2
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm2,%xmm1
+	psllq	$2,%xmm2
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm5,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm5
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm5,%xmm9
+	psrlq	$4,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$4,%xmm3
+	pxor	%xmm4,%xmm5
+	pxor	%xmm1,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm4
+	psllq	$4,%xmm5
+	pxor	%xmm3,%xmm1
+	psllq	$4,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm2,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm2
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+.size	_bsaes_encrypt8,.-_bsaes_encrypt8
+
+.type	_bsaes_decrypt8,@function
+.align	64
+_bsaes_decrypt8:
+	endbr64
+	leaq	.LBS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	-48(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	.Ldec_sbox
+.align	16
+.Ldec_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+.Ldec_sbox:
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm6,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm3,%xmm5
+	pxor	%xmm5,%xmm6
+	pxor	%xmm6,%xmm0
+
+	pxor	%xmm0,%xmm15
+	pxor	%xmm4,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm15,%xmm4
+	pxor	%xmm2,%xmm0
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm3,%xmm12
+	movdqa	%xmm4,%xmm11
+
+	pxor	%xmm15,%xmm10
+	pxor	%xmm3,%xmm9
+	pxor	%xmm5,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm15,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm1,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm5,%xmm11
+	pxor	%xmm1,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm2,%xmm12
+	movdqa	%xmm0,%xmm11
+	pxor	%xmm6,%xmm12
+	pxor	%xmm4,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm3,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm15,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm6,%xmm13
+	pand	%xmm5,%xmm11
+	movdqa	%xmm2,%xmm14
+	pand	%xmm1,%xmm12
+	pand	%xmm0,%xmm13
+	por	%xmm4,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm4,%xmm11
+	movdqa	%xmm0,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm4,%xmm9
+	pxor	%xmm0,%xmm4
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm4
+	pxor	%xmm0,%xmm4
+	pxor	%xmm9,%xmm0
+	pxor	%xmm1,%xmm11
+	pxor	%xmm5,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm1,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm5,%xmm1
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm5
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm1
+	pxor	%xmm11,%xmm7
+	pxor	%xmm5,%xmm1
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm5
+	pxor	%xmm11,%xmm4
+	pxor	%xmm11,%xmm1
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm5
+
+	movdqa	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm7
+	pxor	%xmm15,%xmm11
+	pxor	%xmm3,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm3,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm3
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm3,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm3
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm2,%xmm10
+	pxor	%xmm6,%xmm2
+	pand	%xmm14,%xmm6
+	pand	%xmm13,%xmm2
+	pxor	%xmm6,%xmm2
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm4,%xmm5
+
+	pxor	%xmm0,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm6,%xmm4
+	pxor	%xmm1,%xmm3
+	pxor	%xmm15,%xmm6
+	pxor	%xmm4,%xmm3
+	pxor	%xmm5,%xmm2
+	pxor	%xmm0,%xmm5
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm15,%xmm3
+	pxor	%xmm2,%xmm6
+	decl	%r10d
+	jl	.Ldec_done
+
+	pshufd	$78,%xmm15,%xmm7
+	pshufd	$78,%xmm2,%xmm13
+	pxor	%xmm15,%xmm7
+	pshufd	$78,%xmm4,%xmm14
+	pxor	%xmm2,%xmm13
+	pshufd	$78,%xmm0,%xmm8
+	pxor	%xmm4,%xmm14
+	pshufd	$78,%xmm5,%xmm9
+	pxor	%xmm0,%xmm8
+	pshufd	$78,%xmm3,%xmm10
+	pxor	%xmm5,%xmm9
+	pxor	%xmm13,%xmm15
+	pxor	%xmm13,%xmm0
+	pshufd	$78,%xmm1,%xmm11
+	pxor	%xmm3,%xmm10
+	pxor	%xmm7,%xmm5
+	pxor	%xmm8,%xmm3
+	pshufd	$78,%xmm6,%xmm12
+	pxor	%xmm1,%xmm11
+	pxor	%xmm14,%xmm0
+	pxor	%xmm9,%xmm1
+	pxor	%xmm6,%xmm12
+
+	pxor	%xmm14,%xmm5
+	pxor	%xmm13,%xmm3
+	pxor	%xmm13,%xmm1
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm14,%xmm1
+	pxor	%xmm14,%xmm6
+	pxor	%xmm12,%xmm4
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm5,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm3,%xmm10
+	pxor	%xmm9,%xmm5
+	pshufd	$147,%xmm1,%xmm11
+	pxor	%xmm10,%xmm3
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm1
+	pshufd	$147,%xmm2,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm2
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm1,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm3,%xmm11
+	pshufd	$78,%xmm1,%xmm7
+	pxor	%xmm2,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm5,%xmm10
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm2,%xmm3
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm12,%xmm8
+	pxor	%xmm1,%xmm10
+	pxor	%xmm14,%xmm6
+	pxor	%xmm3,%xmm13
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm2
+	movdqa	%xmm13,%xmm5
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm2,%xmm1
+	movdqa	%xmm10,%xmm2
+	movdqa	-16(%r11),%xmm7
+	jnz	.Ldec_loop
+	movdqa	-32(%r11),%xmm7
+	jmp	.Ldec_loop
+.align	16
+.Ldec_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm2,%xmm9
+	psrlq	$1,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$1,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm6,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm4
+	psllq	$1,%xmm2
+	pxor	%xmm1,%xmm6
+	psllq	$1,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm3,%xmm5
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm15
+	pxor	%xmm5,%xmm3
+	psllq	$1,%xmm5
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm1,%xmm10
+	psrlq	$2,%xmm1
+	pxor	%xmm4,%xmm6
+	pxor	%xmm2,%xmm1
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm1
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm1,%xmm2
+	psllq	$2,%xmm1
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm5,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm3
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm5
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm3,%xmm9
+	psrlq	$4,%xmm3
+	movdqa	%xmm5,%xmm10
+	psrlq	$4,%xmm5
+	pxor	%xmm4,%xmm3
+	pxor	%xmm2,%xmm5
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$4,%xmm3
+	pxor	%xmm5,%xmm2
+	psllq	$4,%xmm5
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm5
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+.size	_bsaes_decrypt8,.-_bsaes_decrypt8
+.type	_bsaes_key_convert,@function
+.align	16
+_bsaes_key_convert:
+	endbr64
+	leaq	.Lmasks(%rip),%r11
+	movdqu	(%rcx),%xmm7
+	leaq	16(%rcx),%rcx
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	movdqa	48(%r11),%xmm3
+	movdqa	64(%r11),%xmm4
+	pcmpeqd	%xmm5,%xmm5
+
+	movdqu	(%rcx),%xmm6
+	movdqa	%xmm7,(%rax)
+	leaq	16(%rax),%rax
+	decl	%r10d
+	jmp	.Lkey_loop
+.align	16
+.Lkey_loop:
+.byte	102,15,56,0,244
+
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm1,%xmm9
+
+	pand	%xmm6,%xmm8
+	pand	%xmm6,%xmm9
+	movdqa	%xmm2,%xmm10
+	pcmpeqb	%xmm0,%xmm8
+	psllq	$4,%xmm0
+	movdqa	%xmm3,%xmm11
+	pcmpeqb	%xmm1,%xmm9
+	psllq	$4,%xmm1
+
+	pand	%xmm6,%xmm10
+	pand	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm12
+	pcmpeqb	%xmm2,%xmm10
+	psllq	$4,%xmm2
+	movdqa	%xmm1,%xmm13
+	pcmpeqb	%xmm3,%xmm11
+	psllq	$4,%xmm3
+
+	movdqa	%xmm2,%xmm14
+	movdqa	%xmm3,%xmm15
+	pxor	%xmm5,%xmm8
+	pxor	%xmm5,%xmm9
+
+	pand	%xmm6,%xmm12
+	pand	%xmm6,%xmm13
+	movdqa	%xmm8,0(%rax)
+	pcmpeqb	%xmm0,%xmm12
+	psrlq	$4,%xmm0
+	movdqa	%xmm9,16(%rax)
+	pcmpeqb	%xmm1,%xmm13
+	psrlq	$4,%xmm1
+	leaq	16(%rcx),%rcx
+
+	pand	%xmm6,%xmm14
+	pand	%xmm6,%xmm15
+	movdqa	%xmm10,32(%rax)
+	pcmpeqb	%xmm2,%xmm14
+	psrlq	$4,%xmm2
+	movdqa	%xmm11,48(%rax)
+	pcmpeqb	%xmm3,%xmm15
+	psrlq	$4,%xmm3
+	movdqu	(%rcx),%xmm6
+
+	pxor	%xmm5,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm12,64(%rax)
+	movdqa	%xmm13,80(%rax)
+	movdqa	%xmm14,96(%rax)
+	movdqa	%xmm15,112(%rax)
+	leaq	128(%rax),%rax
+	decl	%r10d
+	jnz	.Lkey_loop
+
+	movdqa	80(%r11),%xmm7
+
+	retq
+.size	_bsaes_key_convert,.-_bsaes_key_convert
+
+.globl	bsaes_cbc_encrypt
+.type	bsaes_cbc_encrypt,@function
+.align	16
+bsaes_cbc_encrypt:
+	endbr64
+	cmpl	$0,%r9d
+	jne	asm_AES_cbc_encrypt
+	cmpq	$128,%rdx
+	jb	asm_AES_cbc_encrypt
+
+	movq	%rsp,%rax
+.Lcbc_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movl	240(%rcx),%eax
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movq	%r8,%rbx
+	shrq	$4,%r14
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	movdqu	(%rbx),%xmm14
+	subq	$8,%r14
+.Lcbc_dec_loop:
+	movdqu	0(%r12),%xmm15
+	movdqu	16(%r12),%xmm0
+	movdqu	32(%r12),%xmm1
+	movdqu	48(%r12),%xmm2
+	movdqu	64(%r12),%xmm3
+	movdqu	80(%r12),%xmm4
+	movq	%rsp,%rax
+	movdqu	96(%r12),%xmm5
+	movl	%edx,%r10d
+	movdqu	112(%r12),%xmm6
+	movdqa	%xmm14,32(%rbp)
+
+	call	_bsaes_decrypt8
+
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm2
+	movdqu	112(%r12),%xmm14
+	pxor	%xmm13,%xmm4
+	movdqu	%xmm15,0(%r13)
+	leaq	128(%r12),%r12
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	subq	$8,%r14
+	jnc	.Lcbc_dec_loop
+
+	addq	$8,%r14
+	jz	.Lcbc_dec_done
+
+	movdqu	0(%r12),%xmm15
+	movq	%rsp,%rax
+	movl	%edx,%r10d
+	cmpq	$2,%r14
+	jb	.Lcbc_dec_one
+	movdqu	16(%r12),%xmm0
+	je	.Lcbc_dec_two
+	movdqu	32(%r12),%xmm1
+	cmpq	$4,%r14
+	jb	.Lcbc_dec_three
+	movdqu	48(%r12),%xmm2
+	je	.Lcbc_dec_four
+	movdqu	64(%r12),%xmm3
+	cmpq	$6,%r14
+	jb	.Lcbc_dec_five
+	movdqu	80(%r12),%xmm4
+	je	.Lcbc_dec_six
+	movdqu	96(%r12),%xmm5
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm14
+	pxor	%xmm12,%xmm2
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_six:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm14
+	pxor	%xmm11,%xmm6
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_five:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm14
+	pxor	%xmm10,%xmm1
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_four:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm14
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_three:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm14
+	pxor	%xmm8,%xmm5
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_two:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm14
+	pxor	%xmm7,%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	jmp	.Lcbc_dec_done
+.align	16
+.Lcbc_dec_one:
+	leaq	(%r12),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm14
+	movdqu	%xmm14,(%r13)
+	movdqa	%xmm15,%xmm14
+
+.Lcbc_dec_done:
+	movdqu	%xmm14,(%rbx)
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lcbc_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lcbc_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lcbc_dec_epilogue:
+	retq
+.size	bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
+
+.globl	bsaes_ctr32_encrypt_blocks
+.type	bsaes_ctr32_encrypt_blocks,@function
+.align	16
+bsaes_ctr32_encrypt_blocks:
+	endbr64
+	movq	%rsp,%rax
+.Lctr_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movdqu	(%r8),%xmm0
+	movl	240(%rcx),%eax
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movdqa	%xmm0,32(%rbp)
+	cmpq	$8,%rdx
+	jb	.Lctr_enc_short
+
+	movl	%eax,%ebx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%ebx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	movdqa	(%rsp),%xmm8
+	leaq	.LADD1(%rip),%r11
+	movdqa	32(%rbp),%xmm15
+	movdqa	-32(%r11),%xmm7
+.byte	102,68,15,56,0,199
+.byte	102,68,15,56,0,255
+	movdqa	%xmm8,(%rsp)
+	jmp	.Lctr_enc_loop
+.align	16
+.Lctr_enc_loop:
+	movdqa	%xmm15,32(%rbp)
+	movdqa	%xmm15,%xmm0
+	movdqa	%xmm15,%xmm1
+	paddd	0(%r11),%xmm0
+	movdqa	%xmm15,%xmm2
+	paddd	16(%r11),%xmm1
+	movdqa	%xmm15,%xmm3
+	paddd	32(%r11),%xmm2
+	movdqa	%xmm15,%xmm4
+	paddd	48(%r11),%xmm3
+	movdqa	%xmm15,%xmm5
+	paddd	64(%r11),%xmm4
+	movdqa	%xmm15,%xmm6
+	paddd	80(%r11),%xmm5
+	paddd	96(%r11),%xmm6
+
+
+
+	movdqa	(%rsp),%xmm8
+	leaq	16(%rsp),%rax
+	movdqa	-16(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+	leaq	.LBS0(%rip),%r11
+.byte	102,15,56,0,247
+	movl	%ebx,%r10d
+
+	call	_bsaes_encrypt8_bitslice
+
+	subq	$8,%r14
+	jc	.Lctr_enc_loop_done
+
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	movdqu	32(%r12),%xmm9
+	movdqu	48(%r12),%xmm10
+	movdqu	64(%r12),%xmm11
+	movdqu	80(%r12),%xmm12
+	movdqu	96(%r12),%xmm13
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	pxor	%xmm15,%xmm7
+	movdqa	32(%rbp),%xmm15
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm7,0(%r13)
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	%xmm14,%xmm4
+	movdqu	%xmm1,96(%r13)
+	leaq	.LADD1(%rip),%r11
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	paddd	112(%r11),%xmm15
+	jnz	.Lctr_enc_loop
+
+	jmp	.Lctr_enc_done
+.align	16
+.Lctr_enc_loop_done:
+	addq	$8,%r14
+	movdqu	0(%r12),%xmm7
+	pxor	%xmm7,%xmm15
+	movdqu	%xmm15,0(%r13)
+	cmpq	$2,%r14
+	jb	.Lctr_enc_done
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm0,16(%r13)
+	je	.Lctr_enc_done
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm3,32(%r13)
+	cmpq	$4,%r14
+	jb	.Lctr_enc_done
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm5,48(%r13)
+	je	.Lctr_enc_done
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm2,64(%r13)
+	cmpq	$6,%r14
+	jb	.Lctr_enc_done
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm6,80(%r13)
+	je	.Lctr_enc_done
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm1,96(%r13)
+	jmp	.Lctr_enc_done
+
+.align	16
+.Lctr_enc_short:
+	leaq	32(%rbp),%rdi
+	leaq	48(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	asm_AES_encrypt
+	movdqu	(%r12),%xmm0
+	leaq	16(%r12),%r12
+	movl	44(%rbp),%eax
+	bswapl	%eax
+	pxor	48(%rbp),%xmm0
+	incl	%eax
+	movdqu	%xmm0,(%r13)
+	bswapl	%eax
+	leaq	16(%r13),%r13
+	movl	%eax,44(%rsp)
+	decq	%r14
+	jnz	.Lctr_enc_short
+
+.Lctr_enc_done:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lctr_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lctr_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lctr_enc_epilogue:
+	retq
+.size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
+.globl	bsaes_xts_encrypt
+.type	bsaes_xts_encrypt,@function
+.align	16
+bsaes_xts_encrypt:
+	endbr64
+	movq	%rsp,%rax
+.Lxts_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+
+	leaq	(%r9),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r8),%rdx
+	call	asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	andq	$-16,%r14
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	.Lxts_enc_short
+	jmp	.Lxts_enc_loop
+
+.align	16
+.Lxts_enc_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm1,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	.Lxts_enc_loop
+
+.Lxts_enc_short:
+	addq	$128,%r14
+	jz	.Lxts_enc_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	.Lxts_enc_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	.Lxts_enc_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	.Lxts_enc_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	.Lxts_enc_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	.Lxts_enc_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	.Lxts_enc_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm1,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	movdqu	%xmm2,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	movdqu	%xmm5,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm3,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.align	16
+.Lxts_enc_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	asm_AES_encrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+.Lxts_enc_done:
+	andl	$15,%ebx
+	jz	.Lxts_enc_ret
+	movq	%r13,%rdx
+
+.Lxts_enc_steal:
+	movzbl	(%r12),%eax
+	movzbl	-16(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,-16(%rdx)
+	movb	%cl,0(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	.Lxts_enc_steal
+
+	movdqu	-16(%r13),%xmm15
+	leaq	32(%rbp),%rdi
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	asm_AES_encrypt		
+	pxor	32(%rbp),%xmm6
+	movdqu	%xmm6,-16(%r13)
+
+.Lxts_enc_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lxts_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lxts_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lxts_enc_epilogue:
+	retq
+.size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
+
+.globl	bsaes_xts_decrypt
+.type	bsaes_xts_decrypt,@function
+.align	16
+bsaes_xts_decrypt:
+	endbr64
+	movq	%rsp,%rax
+.Lxts_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+
+	leaq	(%r9),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r8),%rdx
+	call	asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	xorl	%eax,%eax
+	andq	$-16,%r14
+	testl	$15,%ebx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%r14
+
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	.Lxts_dec_short
+	jmp	.Lxts_dec_loop
+
+.align	16
+.Lxts_dec_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	.Lxts_dec_loop
+
+.Lxts_dec_short:
+	addq	$128,%r14
+	jz	.Lxts_dec_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	.Lxts_dec_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	.Lxts_dec_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	.Lxts_dec_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	.Lxts_dec_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	.Lxts_dec_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	.Lxts_dec_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.align	16
+.Lxts_dec_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+.Lxts_dec_done:
+	andl	$15,%ebx
+	jz	.Lxts_dec_ret
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	movdqa	%xmm6,%xmm5
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	movdqu	(%r12),%xmm15
+	pxor	%xmm13,%xmm6
+
+	leaq	32(%rbp),%rdi
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm6
+	movq	%r13,%rdx
+	movdqu	%xmm6,(%r13)
+
+.Lxts_dec_steal:
+	movzbl	16(%r12),%eax
+	movzbl	(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,(%rdx)
+	movb	%cl,16(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	.Lxts_dec_steal
+
+	movdqu	(%r13),%xmm15
+	leaq	32(%rbp),%rdi
+	pxor	%xmm5,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm5
+	movdqu	%xmm5,(%r13)
+
+.Lxts_dec_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lxts_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lxts_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lxts_dec_epilogue:
+	retq
+.size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
+.section	.rodata
+.type	_bsaes_const,@object
+.align	64
+_bsaes_const:
+.LM0ISR:
+.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISRM0:
+.quad	0x01040b0e0205080f, 0x0306090c00070a0d
+.LISR:
+.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
+.LBS0:
+.quad	0x5555555555555555, 0x5555555555555555
+.LBS1:
+.quad	0x3333333333333333, 0x3333333333333333
+.LBS2:
+.quad	0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+.LSR:
+.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+.quad	0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0SR:
+.quad	0x0a0e02060f03070b, 0x0004080c05090d01
+.LSWPUP:
+.quad	0x0706050403020100, 0x0c0d0e0f0b0a0908
+.LSWPUPM0SR:
+.quad	0x0a0d02060c03070b, 0x0004080f05090e01
+.LADD1:
+.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
+.align	64
+.size	_bsaes_const,.-_bsaes_const
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/bsaes-macosx-x86_64.S b/crypto/aes/bsaes-macosx-x86_64.S
new file mode 100644
index 0000000..5f780f0
--- /dev/null
+++ b/crypto/aes/bsaes-macosx-x86_64.S
@@ -0,0 +1,2499 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+
+.p2align	6
+_bsaes_encrypt8:
+	leaq	L$BS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	80(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+_bsaes_encrypt8_bitslice:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	L$enc_sbox
+.p2align	4
+L$enc_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+L$enc_sbox:
+	pxor	%xmm5,%xmm4
+	pxor	%xmm0,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm1,%xmm5
+	pxor	%xmm15,%xmm4
+
+	pxor	%xmm2,%xmm5
+	pxor	%xmm6,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm3,%xmm2
+	pxor	%xmm4,%xmm3
+	pxor	%xmm0,%xmm2
+
+	pxor	%xmm6,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm6,%xmm10
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm4,%xmm8
+	movdqa	%xmm1,%xmm12
+	movdqa	%xmm5,%xmm11
+
+	pxor	%xmm3,%xmm10
+	pxor	%xmm1,%xmm9
+	pxor	%xmm2,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm3,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm15,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm2,%xmm11
+	pxor	%xmm15,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm6,%xmm12
+	movdqa	%xmm4,%xmm11
+	pxor	%xmm0,%xmm12
+	pxor	%xmm5,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm1,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm3,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm0,%xmm13
+	pand	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm14
+	pand	%xmm15,%xmm12
+	pand	%xmm4,%xmm13
+	por	%xmm5,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm5,%xmm11
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm5,%xmm9
+	pxor	%xmm4,%xmm5
+	pand	%xmm14,%xmm4
+	pand	%xmm13,%xmm5
+	pxor	%xmm4,%xmm5
+	pxor	%xmm9,%xmm4
+	pxor	%xmm15,%xmm11
+	pxor	%xmm2,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm2,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm2
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm2,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm2
+	pxor	%xmm11,%xmm5
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm2
+
+	movdqa	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm7
+	pxor	%xmm3,%xmm11
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm3,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm1,%xmm3
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm1
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm3
+	pxor	%xmm11,%xmm7
+	pxor	%xmm1,%xmm3
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm1
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm6,%xmm10
+	pxor	%xmm0,%xmm6
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm6
+	pxor	%xmm0,%xmm6
+	pxor	%xmm10,%xmm0
+	pxor	%xmm11,%xmm6
+	pxor	%xmm11,%xmm3
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm1
+	pxor	%xmm15,%xmm6
+	pxor	%xmm5,%xmm0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm15,%xmm5
+	pxor	%xmm0,%xmm15
+
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	pxor	%xmm2,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm4,%xmm3
+
+	pxor	%xmm2,%xmm5
+	decl	%r10d
+	jl	L$enc_done
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm3,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm5,%xmm10
+	pxor	%xmm9,%xmm3
+	pshufd	$147,%xmm2,%xmm11
+	pxor	%xmm10,%xmm5
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm2
+	pshufd	$147,%xmm1,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm1
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm2,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm5,%xmm11
+	pshufd	$78,%xmm2,%xmm7
+	pxor	%xmm1,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm3,%xmm10
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm1,%xmm5
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm12,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm14,%xmm6
+	pxor	%xmm13,%xmm5
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm1
+	movdqa	%xmm8,%xmm4
+	movdqa	48(%r11),%xmm7
+	jnz	L$enc_loop
+	movdqa	64(%r11),%xmm7
+	jmp	L$enc_loop
+.p2align	4
+L$enc_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm2,%xmm10
+	psrlq	$1,%xmm2
+	pxor	%xmm4,%xmm1
+	pxor	%xmm6,%xmm2
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm2
+	pxor	%xmm1,%xmm4
+	psllq	$1,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$1,%xmm2
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm3,%xmm9
+	psrlq	$1,%xmm3
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm5,%xmm3
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm15
+	pxor	%xmm3,%xmm5
+	psllq	$1,%xmm3
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm2,%xmm10
+	psrlq	$2,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm1,%xmm2
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm2
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm2,%xmm1
+	psllq	$2,%xmm2
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm5,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm5
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm5,%xmm9
+	psrlq	$4,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$4,%xmm3
+	pxor	%xmm4,%xmm5
+	pxor	%xmm1,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm4
+	psllq	$4,%xmm5
+	pxor	%xmm3,%xmm1
+	psllq	$4,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm2,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm2
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+
+
+
+.p2align	6
+_bsaes_decrypt8:
+	leaq	L$BS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	-48(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	L$dec_sbox
+.p2align	4
+L$dec_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+L$dec_sbox:
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm6,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm3,%xmm5
+	pxor	%xmm5,%xmm6
+	pxor	%xmm6,%xmm0
+
+	pxor	%xmm0,%xmm15
+	pxor	%xmm4,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm15,%xmm4
+	pxor	%xmm2,%xmm0
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm3,%xmm12
+	movdqa	%xmm4,%xmm11
+
+	pxor	%xmm15,%xmm10
+	pxor	%xmm3,%xmm9
+	pxor	%xmm5,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm15,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm1,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm5,%xmm11
+	pxor	%xmm1,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm2,%xmm12
+	movdqa	%xmm0,%xmm11
+	pxor	%xmm6,%xmm12
+	pxor	%xmm4,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm3,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm15,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm6,%xmm13
+	pand	%xmm5,%xmm11
+	movdqa	%xmm2,%xmm14
+	pand	%xmm1,%xmm12
+	pand	%xmm0,%xmm13
+	por	%xmm4,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm4,%xmm11
+	movdqa	%xmm0,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm4,%xmm9
+	pxor	%xmm0,%xmm4
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm4
+	pxor	%xmm0,%xmm4
+	pxor	%xmm9,%xmm0
+	pxor	%xmm1,%xmm11
+	pxor	%xmm5,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm1,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm5,%xmm1
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm5
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm1
+	pxor	%xmm11,%xmm7
+	pxor	%xmm5,%xmm1
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm5
+	pxor	%xmm11,%xmm4
+	pxor	%xmm11,%xmm1
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm5
+
+	movdqa	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm7
+	pxor	%xmm15,%xmm11
+	pxor	%xmm3,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm3,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm3
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm3,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm3
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm2,%xmm10
+	pxor	%xmm6,%xmm2
+	pand	%xmm14,%xmm6
+	pand	%xmm13,%xmm2
+	pxor	%xmm6,%xmm2
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm4,%xmm5
+
+	pxor	%xmm0,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm6,%xmm4
+	pxor	%xmm1,%xmm3
+	pxor	%xmm15,%xmm6
+	pxor	%xmm4,%xmm3
+	pxor	%xmm5,%xmm2
+	pxor	%xmm0,%xmm5
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm15,%xmm3
+	pxor	%xmm2,%xmm6
+	decl	%r10d
+	jl	L$dec_done
+
+	pshufd	$78,%xmm15,%xmm7
+	pshufd	$78,%xmm2,%xmm13
+	pxor	%xmm15,%xmm7
+	pshufd	$78,%xmm4,%xmm14
+	pxor	%xmm2,%xmm13
+	pshufd	$78,%xmm0,%xmm8
+	pxor	%xmm4,%xmm14
+	pshufd	$78,%xmm5,%xmm9
+	pxor	%xmm0,%xmm8
+	pshufd	$78,%xmm3,%xmm10
+	pxor	%xmm5,%xmm9
+	pxor	%xmm13,%xmm15
+	pxor	%xmm13,%xmm0
+	pshufd	$78,%xmm1,%xmm11
+	pxor	%xmm3,%xmm10
+	pxor	%xmm7,%xmm5
+	pxor	%xmm8,%xmm3
+	pshufd	$78,%xmm6,%xmm12
+	pxor	%xmm1,%xmm11
+	pxor	%xmm14,%xmm0
+	pxor	%xmm9,%xmm1
+	pxor	%xmm6,%xmm12
+
+	pxor	%xmm14,%xmm5
+	pxor	%xmm13,%xmm3
+	pxor	%xmm13,%xmm1
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm14,%xmm1
+	pxor	%xmm14,%xmm6
+	pxor	%xmm12,%xmm4
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm5,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm3,%xmm10
+	pxor	%xmm9,%xmm5
+	pshufd	$147,%xmm1,%xmm11
+	pxor	%xmm10,%xmm3
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm1
+	pshufd	$147,%xmm2,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm2
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm1,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm3,%xmm11
+	pshufd	$78,%xmm1,%xmm7
+	pxor	%xmm2,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm5,%xmm10
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm2,%xmm3
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm12,%xmm8
+	pxor	%xmm1,%xmm10
+	pxor	%xmm14,%xmm6
+	pxor	%xmm3,%xmm13
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm2
+	movdqa	%xmm13,%xmm5
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm2,%xmm1
+	movdqa	%xmm10,%xmm2
+	movdqa	-16(%r11),%xmm7
+	jnz	L$dec_loop
+	movdqa	-32(%r11),%xmm7
+	jmp	L$dec_loop
+.p2align	4
+L$dec_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm2,%xmm9
+	psrlq	$1,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$1,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm6,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm4
+	psllq	$1,%xmm2
+	pxor	%xmm1,%xmm6
+	psllq	$1,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm3,%xmm5
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm15
+	pxor	%xmm5,%xmm3
+	psllq	$1,%xmm5
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm1,%xmm10
+	psrlq	$2,%xmm1
+	pxor	%xmm4,%xmm6
+	pxor	%xmm2,%xmm1
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm1
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm1,%xmm2
+	psllq	$2,%xmm1
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm5,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm3
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm5
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm3,%xmm9
+	psrlq	$4,%xmm3
+	movdqa	%xmm5,%xmm10
+	psrlq	$4,%xmm5
+	pxor	%xmm4,%xmm3
+	pxor	%xmm2,%xmm5
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$4,%xmm3
+	pxor	%xmm5,%xmm2
+	psllq	$4,%xmm5
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm5
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+
+
+.p2align	4
+_bsaes_key_convert:
+	leaq	L$masks(%rip),%r11
+	movdqu	(%rcx),%xmm7
+	leaq	16(%rcx),%rcx
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	movdqa	48(%r11),%xmm3
+	movdqa	64(%r11),%xmm4
+	pcmpeqd	%xmm5,%xmm5
+
+	movdqu	(%rcx),%xmm6
+	movdqa	%xmm7,(%rax)
+	leaq	16(%rax),%rax
+	decl	%r10d
+	jmp	L$key_loop
+.p2align	4
+L$key_loop:
+.byte	102,15,56,0,244
+
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm1,%xmm9
+
+	pand	%xmm6,%xmm8
+	pand	%xmm6,%xmm9
+	movdqa	%xmm2,%xmm10
+	pcmpeqb	%xmm0,%xmm8
+	psllq	$4,%xmm0
+	movdqa	%xmm3,%xmm11
+	pcmpeqb	%xmm1,%xmm9
+	psllq	$4,%xmm1
+
+	pand	%xmm6,%xmm10
+	pand	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm12
+	pcmpeqb	%xmm2,%xmm10
+	psllq	$4,%xmm2
+	movdqa	%xmm1,%xmm13
+	pcmpeqb	%xmm3,%xmm11
+	psllq	$4,%xmm3
+
+	movdqa	%xmm2,%xmm14
+	movdqa	%xmm3,%xmm15
+	pxor	%xmm5,%xmm8
+	pxor	%xmm5,%xmm9
+
+	pand	%xmm6,%xmm12
+	pand	%xmm6,%xmm13
+	movdqa	%xmm8,0(%rax)
+	pcmpeqb	%xmm0,%xmm12
+	psrlq	$4,%xmm0
+	movdqa	%xmm9,16(%rax)
+	pcmpeqb	%xmm1,%xmm13
+	psrlq	$4,%xmm1
+	leaq	16(%rcx),%rcx
+
+	pand	%xmm6,%xmm14
+	pand	%xmm6,%xmm15
+	movdqa	%xmm10,32(%rax)
+	pcmpeqb	%xmm2,%xmm14
+	psrlq	$4,%xmm2
+	movdqa	%xmm11,48(%rax)
+	pcmpeqb	%xmm3,%xmm15
+	psrlq	$4,%xmm3
+	movdqu	(%rcx),%xmm6
+
+	pxor	%xmm5,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm12,64(%rax)
+	movdqa	%xmm13,80(%rax)
+	movdqa	%xmm14,96(%rax)
+	movdqa	%xmm15,112(%rax)
+	leaq	128(%rax),%rax
+	decl	%r10d
+	jnz	L$key_loop
+
+	movdqa	80(%r11),%xmm7
+
+	retq
+
+
+.globl	_bsaes_cbc_encrypt
+
+.p2align	4
+_bsaes_cbc_encrypt:
+	cmpl	$0,%r9d
+	jne	_asm_AES_cbc_encrypt
+	cmpq	$128,%rdx
+	jb	_asm_AES_cbc_encrypt
+
+	movq	%rsp,%rax
+L$cbc_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movl	240(%rcx),%eax
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movq	%r8,%rbx
+	shrq	$4,%r14
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	movdqu	(%rbx),%xmm14
+	subq	$8,%r14
+L$cbc_dec_loop:
+	movdqu	0(%r12),%xmm15
+	movdqu	16(%r12),%xmm0
+	movdqu	32(%r12),%xmm1
+	movdqu	48(%r12),%xmm2
+	movdqu	64(%r12),%xmm3
+	movdqu	80(%r12),%xmm4
+	movq	%rsp,%rax
+	movdqu	96(%r12),%xmm5
+	movl	%edx,%r10d
+	movdqu	112(%r12),%xmm6
+	movdqa	%xmm14,32(%rbp)
+
+	call	_bsaes_decrypt8
+
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm2
+	movdqu	112(%r12),%xmm14
+	pxor	%xmm13,%xmm4
+	movdqu	%xmm15,0(%r13)
+	leaq	128(%r12),%r12
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	subq	$8,%r14
+	jnc	L$cbc_dec_loop
+
+	addq	$8,%r14
+	jz	L$cbc_dec_done
+
+	movdqu	0(%r12),%xmm15
+	movq	%rsp,%rax
+	movl	%edx,%r10d
+	cmpq	$2,%r14
+	jb	L$cbc_dec_one
+	movdqu	16(%r12),%xmm0
+	je	L$cbc_dec_two
+	movdqu	32(%r12),%xmm1
+	cmpq	$4,%r14
+	jb	L$cbc_dec_three
+	movdqu	48(%r12),%xmm2
+	je	L$cbc_dec_four
+	movdqu	64(%r12),%xmm3
+	cmpq	$6,%r14
+	jb	L$cbc_dec_five
+	movdqu	80(%r12),%xmm4
+	je	L$cbc_dec_six
+	movdqu	96(%r12),%xmm5
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm14
+	pxor	%xmm12,%xmm2
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_six:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm14
+	pxor	%xmm11,%xmm6
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_five:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm14
+	pxor	%xmm10,%xmm1
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_four:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm14
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_three:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm14
+	pxor	%xmm8,%xmm5
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_two:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm14
+	pxor	%xmm7,%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	jmp	L$cbc_dec_done
+.p2align	4
+L$cbc_dec_one:
+	leaq	(%r12),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	_asm_AES_decrypt		
+	pxor	32(%rbp),%xmm14
+	movdqu	%xmm14,(%r13)
+	movdqa	%xmm15,%xmm14
+
+L$cbc_dec_done:
+	movdqu	%xmm14,(%rbx)
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+L$cbc_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	L$cbc_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+L$cbc_dec_epilogue:
+	retq
+
+
+.globl	_bsaes_ctr32_encrypt_blocks
+
+.p2align	4
+_bsaes_ctr32_encrypt_blocks:
+	movq	%rsp,%rax
+L$ctr_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movdqu	(%r8),%xmm0
+	movl	240(%rcx),%eax
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	movdqa	%xmm0,32(%rbp)
+	cmpq	$8,%rdx
+	jb	L$ctr_enc_short
+
+	movl	%eax,%ebx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%ebx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	movdqa	(%rsp),%xmm8
+	leaq	L$ADD1(%rip),%r11
+	movdqa	32(%rbp),%xmm15
+	movdqa	-32(%r11),%xmm7
+.byte	102,68,15,56,0,199
+.byte	102,68,15,56,0,255
+	movdqa	%xmm8,(%rsp)
+	jmp	L$ctr_enc_loop
+.p2align	4
+L$ctr_enc_loop:
+	movdqa	%xmm15,32(%rbp)
+	movdqa	%xmm15,%xmm0
+	movdqa	%xmm15,%xmm1
+	paddd	0(%r11),%xmm0
+	movdqa	%xmm15,%xmm2
+	paddd	16(%r11),%xmm1
+	movdqa	%xmm15,%xmm3
+	paddd	32(%r11),%xmm2
+	movdqa	%xmm15,%xmm4
+	paddd	48(%r11),%xmm3
+	movdqa	%xmm15,%xmm5
+	paddd	64(%r11),%xmm4
+	movdqa	%xmm15,%xmm6
+	paddd	80(%r11),%xmm5
+	paddd	96(%r11),%xmm6
+
+
+
+	movdqa	(%rsp),%xmm8
+	leaq	16(%rsp),%rax
+	movdqa	-16(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+	leaq	L$BS0(%rip),%r11
+.byte	102,15,56,0,247
+	movl	%ebx,%r10d
+
+	call	_bsaes_encrypt8_bitslice
+
+	subq	$8,%r14
+	jc	L$ctr_enc_loop_done
+
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	movdqu	32(%r12),%xmm9
+	movdqu	48(%r12),%xmm10
+	movdqu	64(%r12),%xmm11
+	movdqu	80(%r12),%xmm12
+	movdqu	96(%r12),%xmm13
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	pxor	%xmm15,%xmm7
+	movdqa	32(%rbp),%xmm15
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm7,0(%r13)
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	%xmm14,%xmm4
+	movdqu	%xmm1,96(%r13)
+	leaq	L$ADD1(%rip),%r11
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	paddd	112(%r11),%xmm15
+	jnz	L$ctr_enc_loop
+
+	jmp	L$ctr_enc_done
+.p2align	4
+L$ctr_enc_loop_done:
+	addq	$8,%r14
+	movdqu	0(%r12),%xmm7
+	pxor	%xmm7,%xmm15
+	movdqu	%xmm15,0(%r13)
+	cmpq	$2,%r14
+	jb	L$ctr_enc_done
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm0,16(%r13)
+	je	L$ctr_enc_done
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm3,32(%r13)
+	cmpq	$4,%r14
+	jb	L$ctr_enc_done
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm5,48(%r13)
+	je	L$ctr_enc_done
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm2,64(%r13)
+	cmpq	$6,%r14
+	jb	L$ctr_enc_done
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm6,80(%r13)
+	je	L$ctr_enc_done
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm1,96(%r13)
+	jmp	L$ctr_enc_done
+
+.p2align	4
+L$ctr_enc_short:
+	leaq	32(%rbp),%rdi
+	leaq	48(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	_asm_AES_encrypt
+	movdqu	(%r12),%xmm0
+	leaq	16(%r12),%r12
+	movl	44(%rbp),%eax
+	bswapl	%eax
+	pxor	48(%rbp),%xmm0
+	incl	%eax
+	movdqu	%xmm0,(%r13)
+	bswapl	%eax
+	leaq	16(%r13),%r13
+	movl	%eax,44(%rsp)
+	decq	%r14
+	jnz	L$ctr_enc_short
+
+L$ctr_enc_done:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+L$ctr_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	L$ctr_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+L$ctr_enc_epilogue:
+	retq
+
+.globl	_bsaes_xts_encrypt
+
+.p2align	4
+_bsaes_xts_encrypt:
+	movq	%rsp,%rax
+L$xts_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+
+	leaq	(%r9),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r8),%rdx
+	call	_asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	andq	$-16,%r14
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	L$xts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	L$xts_enc_short
+	jmp	L$xts_enc_loop
+
+.p2align	4
+L$xts_enc_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm1,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	L$xts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	L$xts_enc_loop
+
+L$xts_enc_short:
+	addq	$128,%r14
+	jz	L$xts_enc_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	L$xts_enc_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	L$xts_enc_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	L$xts_enc_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	L$xts_enc_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	L$xts_enc_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	L$xts_enc_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm1,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	movdqu	%xmm2,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	movdqu	%xmm5,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm3,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	L$xts_enc_done
+.p2align	4
+L$xts_enc_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	_asm_AES_encrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+L$xts_enc_done:
+	andl	$15,%ebx
+	jz	L$xts_enc_ret
+	movq	%r13,%rdx
+
+L$xts_enc_steal:
+	movzbl	(%r12),%eax
+	movzbl	-16(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,-16(%rdx)
+	movb	%cl,0(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	L$xts_enc_steal
+
+	movdqu	-16(%r13),%xmm15
+	leaq	32(%rbp),%rdi
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	_asm_AES_encrypt		
+	pxor	32(%rbp),%xmm6
+	movdqu	%xmm6,-16(%r13)
+
+L$xts_enc_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+L$xts_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	L$xts_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+L$xts_enc_epilogue:
+	retq
+
+
+.globl	_bsaes_xts_decrypt
+
+.p2align	4
+_bsaes_xts_decrypt:
+	movq	%rsp,%rax
+L$xts_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	%rsp,%rbp
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+
+	leaq	(%r9),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r8),%rdx
+	call	_asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	xorl	%eax,%eax
+	andq	$-16,%r14
+	testl	$15,%ebx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%r14
+
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	L$xts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	L$xts_dec_short
+	jmp	L$xts_dec_loop
+
+.p2align	4
+L$xts_dec_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	L$xts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	L$xts_dec_loop
+
+L$xts_dec_short:
+	addq	$128,%r14
+	jz	L$xts_dec_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	L$xts_dec_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	L$xts_dec_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	L$xts_dec_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	L$xts_dec_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	L$xts_dec_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	L$xts_dec_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	L$xts_dec_done
+.p2align	4
+L$xts_dec_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rdi
+	leaq	32(%rbp),%rsi
+	leaq	(%r15),%rdx
+	call	_asm_AES_decrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+L$xts_dec_done:
+	andl	$15,%ebx
+	jz	L$xts_dec_ret
+
+	pxor	%xmm14,%xmm14
+	movdqa	L$xts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	movdqa	%xmm6,%xmm5
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	movdqu	(%r12),%xmm15
+	pxor	%xmm13,%xmm6
+
+	leaq	32(%rbp),%rdi
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	_asm_AES_decrypt		
+	pxor	32(%rbp),%xmm6
+	movq	%r13,%rdx
+	movdqu	%xmm6,(%r13)
+
+L$xts_dec_steal:
+	movzbl	16(%r12),%eax
+	movzbl	(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,(%rdx)
+	movb	%cl,16(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	L$xts_dec_steal
+
+	movdqu	(%r13),%xmm15
+	leaq	32(%rbp),%rdi
+	pxor	%xmm5,%xmm15
+	leaq	32(%rbp),%rsi
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%rdx
+	call	_asm_AES_decrypt		
+	pxor	32(%rbp),%xmm5
+	movdqu	%xmm5,(%r13)
+
+L$xts_dec_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+L$xts_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	L$xts_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+L$xts_dec_epilogue:
+	retq
+
+
+.p2align	6
+_bsaes_const:
+L$M0ISR:
+.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
+L$ISRM0:
+.quad	0x01040b0e0205080f, 0x0306090c00070a0d
+L$ISR:
+.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
+L$BS0:
+.quad	0x5555555555555555, 0x5555555555555555
+L$BS1:
+.quad	0x3333333333333333, 0x3333333333333333
+L$BS2:
+.quad	0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+L$SR:
+.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
+L$SRM0:
+.quad	0x0304090e00050a0f, 0x01060b0c0207080d
+L$M0SR:
+.quad	0x0a0e02060f03070b, 0x0004080c05090d01
+L$SWPUP:
+.quad	0x0706050403020100, 0x0c0d0e0f0b0a0908
+L$SWPUPM0SR:
+.quad	0x0a0d02060c03070b, 0x0004080f05090e01
+L$ADD1:
+.quad	0x0000000000000000, 0x0000000100000000
+L$ADD2:
+.quad	0x0000000000000000, 0x0000000200000000
+L$ADD3:
+.quad	0x0000000000000000, 0x0000000300000000
+L$ADD4:
+.quad	0x0000000000000000, 0x0000000400000000
+L$ADD5:
+.quad	0x0000000000000000, 0x0000000500000000
+L$ADD6:
+.quad	0x0000000000000000, 0x0000000600000000
+L$ADD7:
+.quad	0x0000000000000000, 0x0000000700000000
+L$ADD8:
+.quad	0x0000000000000000, 0x0000000800000000
+L$xts_magic:
+.long	0x87,0,1,0
+L$masks:
+.quad	0x0101010101010101, 0x0101010101010101
+.quad	0x0202020202020202, 0x0202020202020202
+.quad	0x0404040404040404, 0x0404040404040404
+.quad	0x0808080808080808, 0x0808080808080808
+L$M0:
+.quad	0x02060a0e03070b0f, 0x0004080c0105090d
+L$63:
+.quad	0x6363636363636363, 0x6363636363636363
+.byte	66,105,116,45,115,108,105,99,101,100,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,69,109,105,108,105,97,32,75,195,164,115,112,101,114,44,32,80,101,116,101,114,32,83,99,104,119,97,98,101,44,32,65,110,100,121,32,80,111,108,121,97,107,111,118,0
+.p2align	6
+
diff --git a/crypto/aes/bsaes-masm-x86_64.S b/crypto/aes/bsaes-masm-x86_64.S
new file mode 100644
index 0000000..211959e
--- /dev/null
+++ b/crypto/aes/bsaes-masm-x86_64.S
@@ -0,0 +1,2803 @@
+; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/aes/bsaes-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/aes/bsaes-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+EXTERN	asm_AES_encrypt:NEAR
+EXTERN	asm_AES_decrypt:NEAR
+
+
+ALIGN	64
+_bsaes_encrypt8	PROC PRIVATE
+	lea	r11,QWORD PTR[$L$BS0]
+
+	movdqa	xmm8,XMMWORD PTR[rax]
+	lea	rax,QWORD PTR[16+rax]
+	movdqa	xmm7,XMMWORD PTR[80+r11]
+	pxor	xmm15,xmm8
+	pxor	xmm0,xmm8
+DB	102,68,15,56,0,255
+	pxor	xmm1,xmm8
+DB	102,15,56,0,199
+	pxor	xmm2,xmm8
+DB	102,15,56,0,207
+	pxor	xmm3,xmm8
+DB	102,15,56,0,215
+	pxor	xmm4,xmm8
+DB	102,15,56,0,223
+	pxor	xmm5,xmm8
+DB	102,15,56,0,231
+	pxor	xmm6,xmm8
+DB	102,15,56,0,239
+DB	102,15,56,0,247
+_bsaes_encrypt8_bitslice::
+	movdqa	xmm7,XMMWORD PTR[r11]
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	movdqa	xmm9,xmm5
+	psrlq	xmm5,1
+	movdqa	xmm10,xmm3
+	psrlq	xmm3,1
+	pxor	xmm5,xmm6
+	pxor	xmm3,xmm4
+	pand	xmm5,xmm7
+	pand	xmm3,xmm7
+	pxor	xmm6,xmm5
+	psllq	xmm5,1
+	pxor	xmm4,xmm3
+	psllq	xmm3,1
+	pxor	xmm5,xmm9
+	pxor	xmm3,xmm10
+	movdqa	xmm9,xmm1
+	psrlq	xmm1,1
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,1
+	pxor	xmm1,xmm2
+	pxor	xmm15,xmm0
+	pand	xmm1,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm2,xmm1
+	psllq	xmm1,1
+	pxor	xmm0,xmm15
+	psllq	xmm15,1
+	pxor	xmm1,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[32+r11]
+	movdqa	xmm9,xmm4
+	psrlq	xmm4,2
+	movdqa	xmm10,xmm3
+	psrlq	xmm3,2
+	pxor	xmm4,xmm6
+	pxor	xmm3,xmm5
+	pand	xmm4,xmm8
+	pand	xmm3,xmm8
+	pxor	xmm6,xmm4
+	psllq	xmm4,2
+	pxor	xmm5,xmm3
+	psllq	xmm3,2
+	pxor	xmm4,xmm9
+	pxor	xmm3,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,2
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,2
+	pxor	xmm0,xmm2
+	pxor	xmm15,xmm1
+	pand	xmm0,xmm8
+	pand	xmm15,xmm8
+	pxor	xmm2,xmm0
+	psllq	xmm0,2
+	pxor	xmm1,xmm15
+	psllq	xmm15,2
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm9,xmm2
+	psrlq	xmm2,4
+	movdqa	xmm10,xmm1
+	psrlq	xmm1,4
+	pxor	xmm2,xmm6
+	pxor	xmm1,xmm5
+	pand	xmm2,xmm7
+	pand	xmm1,xmm7
+	pxor	xmm6,xmm2
+	psllq	xmm2,4
+	pxor	xmm5,xmm1
+	psllq	xmm1,4
+	pxor	xmm2,xmm9
+	pxor	xmm1,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,4
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,4
+	pxor	xmm0,xmm4
+	pxor	xmm15,xmm3
+	pand	xmm0,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm4,xmm0
+	psllq	xmm0,4
+	pxor	xmm3,xmm15
+	psllq	xmm15,4
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	dec	r10d
+	jmp	$L$enc_sbox
+ALIGN	16
+$L$enc_loop::
+	pxor	xmm15,XMMWORD PTR[rax]
+	pxor	xmm0,XMMWORD PTR[16+rax]
+DB	102,68,15,56,0,255
+	pxor	xmm1,XMMWORD PTR[32+rax]
+DB	102,15,56,0,199
+	pxor	xmm2,XMMWORD PTR[48+rax]
+DB	102,15,56,0,207
+	pxor	xmm3,XMMWORD PTR[64+rax]
+DB	102,15,56,0,215
+	pxor	xmm4,XMMWORD PTR[80+rax]
+DB	102,15,56,0,223
+	pxor	xmm5,XMMWORD PTR[96+rax]
+DB	102,15,56,0,231
+	pxor	xmm6,XMMWORD PTR[112+rax]
+DB	102,15,56,0,239
+	lea	rax,QWORD PTR[128+rax]
+DB	102,15,56,0,247
+$L$enc_sbox::
+	pxor	xmm4,xmm5
+	pxor	xmm1,xmm0
+	pxor	xmm2,xmm15
+	pxor	xmm5,xmm1
+	pxor	xmm4,xmm15
+
+	pxor	xmm5,xmm2
+	pxor	xmm2,xmm6
+	pxor	xmm6,xmm4
+	pxor	xmm2,xmm3
+	pxor	xmm3,xmm4
+	pxor	xmm2,xmm0
+
+	pxor	xmm1,xmm6
+	pxor	xmm0,xmm4
+	movdqa	xmm10,xmm6
+	movdqa	xmm9,xmm0
+	movdqa	xmm8,xmm4
+	movdqa	xmm12,xmm1
+	movdqa	xmm11,xmm5
+
+	pxor	xmm10,xmm3
+	pxor	xmm9,xmm1
+	pxor	xmm8,xmm2
+	movdqa	xmm13,xmm10
+	pxor	xmm12,xmm3
+	movdqa	xmm7,xmm9
+	pxor	xmm11,xmm15
+	movdqa	xmm14,xmm10
+
+	por	xmm9,xmm8
+	por	xmm10,xmm11
+	pxor	xmm14,xmm7
+	pand	xmm13,xmm11
+	pxor	xmm11,xmm8
+	pand	xmm7,xmm8
+	pand	xmm14,xmm11
+	movdqa	xmm11,xmm2
+	pxor	xmm11,xmm15
+	pand	xmm12,xmm11
+	pxor	xmm10,xmm12
+	pxor	xmm9,xmm12
+	movdqa	xmm12,xmm6
+	movdqa	xmm11,xmm4
+	pxor	xmm12,xmm0
+	pxor	xmm11,xmm5
+	movdqa	xmm8,xmm12
+	pand	xmm12,xmm11
+	por	xmm8,xmm11
+	pxor	xmm7,xmm12
+	pxor	xmm10,xmm14
+	pxor	xmm9,xmm13
+	pxor	xmm8,xmm14
+	movdqa	xmm11,xmm1
+	pxor	xmm7,xmm13
+	movdqa	xmm12,xmm3
+	pxor	xmm8,xmm13
+	movdqa	xmm13,xmm0
+	pand	xmm11,xmm2
+	movdqa	xmm14,xmm6
+	pand	xmm12,xmm15
+	pand	xmm13,xmm4
+	por	xmm14,xmm5
+	pxor	xmm10,xmm11
+	pxor	xmm9,xmm12
+	pxor	xmm8,xmm13
+	pxor	xmm7,xmm14
+
+
+
+
+
+	movdqa	xmm11,xmm10
+	pand	xmm10,xmm8
+	pxor	xmm11,xmm9
+
+	movdqa	xmm13,xmm7
+	movdqa	xmm14,xmm11
+	pxor	xmm13,xmm10
+	pand	xmm14,xmm13
+
+	movdqa	xmm12,xmm8
+	pxor	xmm14,xmm9
+	pxor	xmm12,xmm7
+
+	pxor	xmm10,xmm9
+
+	pand	xmm12,xmm10
+
+	movdqa	xmm9,xmm13
+	pxor	xmm12,xmm7
+
+	pxor	xmm9,xmm12
+	pxor	xmm8,xmm12
+
+	pand	xmm9,xmm7
+
+	pxor	xmm13,xmm9
+	pxor	xmm8,xmm9
+
+	pand	xmm13,xmm14
+
+	pxor	xmm13,xmm11
+	movdqa	xmm11,xmm5
+	movdqa	xmm7,xmm4
+	movdqa	xmm9,xmm14
+	pxor	xmm9,xmm13
+	pand	xmm9,xmm5
+	pxor	xmm5,xmm4
+	pand	xmm4,xmm14
+	pand	xmm5,xmm13
+	pxor	xmm5,xmm4
+	pxor	xmm4,xmm9
+	pxor	xmm11,xmm15
+	pxor	xmm7,xmm2
+	pxor	xmm14,xmm12
+	pxor	xmm13,xmm8
+	movdqa	xmm10,xmm14
+	movdqa	xmm9,xmm12
+	pxor	xmm10,xmm13
+	pxor	xmm9,xmm8
+	pand	xmm10,xmm11
+	pand	xmm9,xmm15
+	pxor	xmm11,xmm7
+	pxor	xmm15,xmm2
+	pand	xmm7,xmm14
+	pand	xmm2,xmm12
+	pand	xmm11,xmm13
+	pand	xmm15,xmm8
+	pxor	xmm7,xmm11
+	pxor	xmm15,xmm2
+	pxor	xmm11,xmm10
+	pxor	xmm2,xmm9
+	pxor	xmm5,xmm11
+	pxor	xmm15,xmm11
+	pxor	xmm4,xmm7
+	pxor	xmm2,xmm7
+
+	movdqa	xmm11,xmm6
+	movdqa	xmm7,xmm0
+	pxor	xmm11,xmm3
+	pxor	xmm7,xmm1
+	movdqa	xmm10,xmm14
+	movdqa	xmm9,xmm12
+	pxor	xmm10,xmm13
+	pxor	xmm9,xmm8
+	pand	xmm10,xmm11
+	pand	xmm9,xmm3
+	pxor	xmm11,xmm7
+	pxor	xmm3,xmm1
+	pand	xmm7,xmm14
+	pand	xmm1,xmm12
+	pand	xmm11,xmm13
+	pand	xmm3,xmm8
+	pxor	xmm7,xmm11
+	pxor	xmm3,xmm1
+	pxor	xmm11,xmm10
+	pxor	xmm1,xmm9
+	pxor	xmm14,xmm12
+	pxor	xmm13,xmm8
+	movdqa	xmm10,xmm14
+	pxor	xmm10,xmm13
+	pand	xmm10,xmm6
+	pxor	xmm6,xmm0
+	pand	xmm0,xmm14
+	pand	xmm6,xmm13
+	pxor	xmm6,xmm0
+	pxor	xmm0,xmm10
+	pxor	xmm6,xmm11
+	pxor	xmm3,xmm11
+	pxor	xmm0,xmm7
+	pxor	xmm1,xmm7
+	pxor	xmm6,xmm15
+	pxor	xmm0,xmm5
+	pxor	xmm3,xmm6
+	pxor	xmm5,xmm15
+	pxor	xmm15,xmm0
+
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	pxor	xmm1,xmm2
+	pxor	xmm2,xmm4
+	pxor	xmm3,xmm4
+
+	pxor	xmm5,xmm2
+	dec	r10d
+	jl	$L$enc_done
+	pshufd	xmm7,xmm15,093h
+	pshufd	xmm8,xmm0,093h
+	pxor	xmm15,xmm7
+	pshufd	xmm9,xmm3,093h
+	pxor	xmm0,xmm8
+	pshufd	xmm10,xmm5,093h
+	pxor	xmm3,xmm9
+	pshufd	xmm11,xmm2,093h
+	pxor	xmm5,xmm10
+	pshufd	xmm12,xmm6,093h
+	pxor	xmm2,xmm11
+	pshufd	xmm13,xmm1,093h
+	pxor	xmm6,xmm12
+	pshufd	xmm14,xmm4,093h
+	pxor	xmm1,xmm13
+	pxor	xmm4,xmm14
+
+	pxor	xmm8,xmm15
+	pxor	xmm7,xmm4
+	pxor	xmm8,xmm4
+	pshufd	xmm15,xmm15,04Eh
+	pxor	xmm9,xmm0
+	pshufd	xmm0,xmm0,04Eh
+	pxor	xmm12,xmm2
+	pxor	xmm15,xmm7
+	pxor	xmm13,xmm6
+	pxor	xmm0,xmm8
+	pxor	xmm11,xmm5
+	pshufd	xmm7,xmm2,04Eh
+	pxor	xmm14,xmm1
+	pshufd	xmm8,xmm6,04Eh
+	pxor	xmm10,xmm3
+	pshufd	xmm2,xmm5,04Eh
+	pxor	xmm10,xmm4
+	pshufd	xmm6,xmm4,04Eh
+	pxor	xmm11,xmm4
+	pshufd	xmm5,xmm1,04Eh
+	pxor	xmm7,xmm11
+	pshufd	xmm1,xmm3,04Eh
+	pxor	xmm8,xmm12
+	pxor	xmm2,xmm10
+	pxor	xmm6,xmm14
+	pxor	xmm5,xmm13
+	movdqa	xmm3,xmm7
+	pxor	xmm1,xmm9
+	movdqa	xmm4,xmm8
+	movdqa	xmm7,XMMWORD PTR[48+r11]
+	jnz	$L$enc_loop
+	movdqa	xmm7,XMMWORD PTR[64+r11]
+	jmp	$L$enc_loop
+ALIGN	16
+$L$enc_done::
+	movdqa	xmm7,XMMWORD PTR[r11]
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	movdqa	xmm9,xmm1
+	psrlq	xmm1,1
+	movdqa	xmm10,xmm2
+	psrlq	xmm2,1
+	pxor	xmm1,xmm4
+	pxor	xmm2,xmm6
+	pand	xmm1,xmm7
+	pand	xmm2,xmm7
+	pxor	xmm4,xmm1
+	psllq	xmm1,1
+	pxor	xmm6,xmm2
+	psllq	xmm2,1
+	pxor	xmm1,xmm9
+	pxor	xmm2,xmm10
+	movdqa	xmm9,xmm3
+	psrlq	xmm3,1
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,1
+	pxor	xmm3,xmm5
+	pxor	xmm15,xmm0
+	pand	xmm3,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm5,xmm3
+	psllq	xmm3,1
+	pxor	xmm0,xmm15
+	psllq	xmm15,1
+	pxor	xmm3,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[32+r11]
+	movdqa	xmm9,xmm6
+	psrlq	xmm6,2
+	movdqa	xmm10,xmm2
+	psrlq	xmm2,2
+	pxor	xmm6,xmm4
+	pxor	xmm2,xmm1
+	pand	xmm6,xmm8
+	pand	xmm2,xmm8
+	pxor	xmm4,xmm6
+	psllq	xmm6,2
+	pxor	xmm1,xmm2
+	psllq	xmm2,2
+	pxor	xmm6,xmm9
+	pxor	xmm2,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,2
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,2
+	pxor	xmm0,xmm5
+	pxor	xmm15,xmm3
+	pand	xmm0,xmm8
+	pand	xmm15,xmm8
+	pxor	xmm5,xmm0
+	psllq	xmm0,2
+	pxor	xmm3,xmm15
+	psllq	xmm15,2
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm9,xmm5
+	psrlq	xmm5,4
+	movdqa	xmm10,xmm3
+	psrlq	xmm3,4
+	pxor	xmm5,xmm4
+	pxor	xmm3,xmm1
+	pand	xmm5,xmm7
+	pand	xmm3,xmm7
+	pxor	xmm4,xmm5
+	psllq	xmm5,4
+	pxor	xmm1,xmm3
+	psllq	xmm3,4
+	pxor	xmm5,xmm9
+	pxor	xmm3,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,4
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,4
+	pxor	xmm0,xmm6
+	pxor	xmm15,xmm2
+	pand	xmm0,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm6,xmm0
+	psllq	xmm0,4
+	pxor	xmm2,xmm15
+	psllq	xmm15,4
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[rax]
+	pxor	xmm3,xmm7
+	pxor	xmm5,xmm7
+	pxor	xmm2,xmm7
+	pxor	xmm6,xmm7
+	pxor	xmm1,xmm7
+	pxor	xmm4,xmm7
+	pxor	xmm15,xmm7
+	pxor	xmm0,xmm7
+	DB	0F3h,0C3h		;repret
+_bsaes_encrypt8	ENDP
+
+
+ALIGN	64
+_bsaes_decrypt8	PROC PRIVATE
+	lea	r11,QWORD PTR[$L$BS0]
+
+	movdqa	xmm8,XMMWORD PTR[rax]
+	lea	rax,QWORD PTR[16+rax]
+	movdqa	xmm7,XMMWORD PTR[((-48))+r11]
+	pxor	xmm15,xmm8
+	pxor	xmm0,xmm8
+DB	102,68,15,56,0,255
+	pxor	xmm1,xmm8
+DB	102,15,56,0,199
+	pxor	xmm2,xmm8
+DB	102,15,56,0,207
+	pxor	xmm3,xmm8
+DB	102,15,56,0,215
+	pxor	xmm4,xmm8
+DB	102,15,56,0,223
+	pxor	xmm5,xmm8
+DB	102,15,56,0,231
+	pxor	xmm6,xmm8
+DB	102,15,56,0,239
+DB	102,15,56,0,247
+	movdqa	xmm7,XMMWORD PTR[r11]
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	movdqa	xmm9,xmm5
+	psrlq	xmm5,1
+	movdqa	xmm10,xmm3
+	psrlq	xmm3,1
+	pxor	xmm5,xmm6
+	pxor	xmm3,xmm4
+	pand	xmm5,xmm7
+	pand	xmm3,xmm7
+	pxor	xmm6,xmm5
+	psllq	xmm5,1
+	pxor	xmm4,xmm3
+	psllq	xmm3,1
+	pxor	xmm5,xmm9
+	pxor	xmm3,xmm10
+	movdqa	xmm9,xmm1
+	psrlq	xmm1,1
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,1
+	pxor	xmm1,xmm2
+	pxor	xmm15,xmm0
+	pand	xmm1,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm2,xmm1
+	psllq	xmm1,1
+	pxor	xmm0,xmm15
+	psllq	xmm15,1
+	pxor	xmm1,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[32+r11]
+	movdqa	xmm9,xmm4
+	psrlq	xmm4,2
+	movdqa	xmm10,xmm3
+	psrlq	xmm3,2
+	pxor	xmm4,xmm6
+	pxor	xmm3,xmm5
+	pand	xmm4,xmm8
+	pand	xmm3,xmm8
+	pxor	xmm6,xmm4
+	psllq	xmm4,2
+	pxor	xmm5,xmm3
+	psllq	xmm3,2
+	pxor	xmm4,xmm9
+	pxor	xmm3,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,2
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,2
+	pxor	xmm0,xmm2
+	pxor	xmm15,xmm1
+	pand	xmm0,xmm8
+	pand	xmm15,xmm8
+	pxor	xmm2,xmm0
+	psllq	xmm0,2
+	pxor	xmm1,xmm15
+	psllq	xmm15,2
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm9,xmm2
+	psrlq	xmm2,4
+	movdqa	xmm10,xmm1
+	psrlq	xmm1,4
+	pxor	xmm2,xmm6
+	pxor	xmm1,xmm5
+	pand	xmm2,xmm7
+	pand	xmm1,xmm7
+	pxor	xmm6,xmm2
+	psllq	xmm2,4
+	pxor	xmm5,xmm1
+	psllq	xmm1,4
+	pxor	xmm2,xmm9
+	pxor	xmm1,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,4
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,4
+	pxor	xmm0,xmm4
+	pxor	xmm15,xmm3
+	pand	xmm0,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm4,xmm0
+	psllq	xmm0,4
+	pxor	xmm3,xmm15
+	psllq	xmm15,4
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	dec	r10d
+	jmp	$L$dec_sbox
+ALIGN	16
+$L$dec_loop::
+	pxor	xmm15,XMMWORD PTR[rax]
+	pxor	xmm0,XMMWORD PTR[16+rax]
+DB	102,68,15,56,0,255
+	pxor	xmm1,XMMWORD PTR[32+rax]
+DB	102,15,56,0,199
+	pxor	xmm2,XMMWORD PTR[48+rax]
+DB	102,15,56,0,207
+	pxor	xmm3,XMMWORD PTR[64+rax]
+DB	102,15,56,0,215
+	pxor	xmm4,XMMWORD PTR[80+rax]
+DB	102,15,56,0,223
+	pxor	xmm5,XMMWORD PTR[96+rax]
+DB	102,15,56,0,231
+	pxor	xmm6,XMMWORD PTR[112+rax]
+DB	102,15,56,0,239
+	lea	rax,QWORD PTR[128+rax]
+DB	102,15,56,0,247
+$L$dec_sbox::
+	pxor	xmm2,xmm3
+
+	pxor	xmm3,xmm6
+	pxor	xmm1,xmm6
+	pxor	xmm5,xmm3
+	pxor	xmm6,xmm5
+	pxor	xmm0,xmm6
+
+	pxor	xmm15,xmm0
+	pxor	xmm1,xmm4
+	pxor	xmm2,xmm15
+	pxor	xmm4,xmm15
+	pxor	xmm0,xmm2
+	movdqa	xmm10,xmm2
+	movdqa	xmm9,xmm6
+	movdqa	xmm8,xmm0
+	movdqa	xmm12,xmm3
+	movdqa	xmm11,xmm4
+
+	pxor	xmm10,xmm15
+	pxor	xmm9,xmm3
+	pxor	xmm8,xmm5
+	movdqa	xmm13,xmm10
+	pxor	xmm12,xmm15
+	movdqa	xmm7,xmm9
+	pxor	xmm11,xmm1
+	movdqa	xmm14,xmm10
+
+	por	xmm9,xmm8
+	por	xmm10,xmm11
+	pxor	xmm14,xmm7
+	pand	xmm13,xmm11
+	pxor	xmm11,xmm8
+	pand	xmm7,xmm8
+	pand	xmm14,xmm11
+	movdqa	xmm11,xmm5
+	pxor	xmm11,xmm1
+	pand	xmm12,xmm11
+	pxor	xmm10,xmm12
+	pxor	xmm9,xmm12
+	movdqa	xmm12,xmm2
+	movdqa	xmm11,xmm0
+	pxor	xmm12,xmm6
+	pxor	xmm11,xmm4
+	movdqa	xmm8,xmm12
+	pand	xmm12,xmm11
+	por	xmm8,xmm11
+	pxor	xmm7,xmm12
+	pxor	xmm10,xmm14
+	pxor	xmm9,xmm13
+	pxor	xmm8,xmm14
+	movdqa	xmm11,xmm3
+	pxor	xmm7,xmm13
+	movdqa	xmm12,xmm15
+	pxor	xmm8,xmm13
+	movdqa	xmm13,xmm6
+	pand	xmm11,xmm5
+	movdqa	xmm14,xmm2
+	pand	xmm12,xmm1
+	pand	xmm13,xmm0
+	por	xmm14,xmm4
+	pxor	xmm10,xmm11
+	pxor	xmm9,xmm12
+	pxor	xmm8,xmm13
+	pxor	xmm7,xmm14
+
+
+
+
+
+	movdqa	xmm11,xmm10
+	pand	xmm10,xmm8
+	pxor	xmm11,xmm9
+
+	movdqa	xmm13,xmm7
+	movdqa	xmm14,xmm11
+	pxor	xmm13,xmm10
+	pand	xmm14,xmm13
+
+	movdqa	xmm12,xmm8
+	pxor	xmm14,xmm9
+	pxor	xmm12,xmm7
+
+	pxor	xmm10,xmm9
+
+	pand	xmm12,xmm10
+
+	movdqa	xmm9,xmm13
+	pxor	xmm12,xmm7
+
+	pxor	xmm9,xmm12
+	pxor	xmm8,xmm12
+
+	pand	xmm9,xmm7
+
+	pxor	xmm13,xmm9
+	pxor	xmm8,xmm9
+
+	pand	xmm13,xmm14
+
+	pxor	xmm13,xmm11
+	movdqa	xmm11,xmm4
+	movdqa	xmm7,xmm0
+	movdqa	xmm9,xmm14
+	pxor	xmm9,xmm13
+	pand	xmm9,xmm4
+	pxor	xmm4,xmm0
+	pand	xmm0,xmm14
+	pand	xmm4,xmm13
+	pxor	xmm4,xmm0
+	pxor	xmm0,xmm9
+	pxor	xmm11,xmm1
+	pxor	xmm7,xmm5
+	pxor	xmm14,xmm12
+	pxor	xmm13,xmm8
+	movdqa	xmm10,xmm14
+	movdqa	xmm9,xmm12
+	pxor	xmm10,xmm13
+	pxor	xmm9,xmm8
+	pand	xmm10,xmm11
+	pand	xmm9,xmm1
+	pxor	xmm11,xmm7
+	pxor	xmm1,xmm5
+	pand	xmm7,xmm14
+	pand	xmm5,xmm12
+	pand	xmm11,xmm13
+	pand	xmm1,xmm8
+	pxor	xmm7,xmm11
+	pxor	xmm1,xmm5
+	pxor	xmm11,xmm10
+	pxor	xmm5,xmm9
+	pxor	xmm4,xmm11
+	pxor	xmm1,xmm11
+	pxor	xmm0,xmm7
+	pxor	xmm5,xmm7
+
+	movdqa	xmm11,xmm2
+	movdqa	xmm7,xmm6
+	pxor	xmm11,xmm15
+	pxor	xmm7,xmm3
+	movdqa	xmm10,xmm14
+	movdqa	xmm9,xmm12
+	pxor	xmm10,xmm13
+	pxor	xmm9,xmm8
+	pand	xmm10,xmm11
+	pand	xmm9,xmm15
+	pxor	xmm11,xmm7
+	pxor	xmm15,xmm3
+	pand	xmm7,xmm14
+	pand	xmm3,xmm12
+	pand	xmm11,xmm13
+	pand	xmm15,xmm8
+	pxor	xmm7,xmm11
+	pxor	xmm15,xmm3
+	pxor	xmm11,xmm10
+	pxor	xmm3,xmm9
+	pxor	xmm14,xmm12
+	pxor	xmm13,xmm8
+	movdqa	xmm10,xmm14
+	pxor	xmm10,xmm13
+	pand	xmm10,xmm2
+	pxor	xmm2,xmm6
+	pand	xmm6,xmm14
+	pand	xmm2,xmm13
+	pxor	xmm2,xmm6
+	pxor	xmm6,xmm10
+	pxor	xmm2,xmm11
+	pxor	xmm15,xmm11
+	pxor	xmm6,xmm7
+	pxor	xmm3,xmm7
+	pxor	xmm0,xmm6
+	pxor	xmm5,xmm4
+
+	pxor	xmm3,xmm0
+	pxor	xmm1,xmm6
+	pxor	xmm4,xmm6
+	pxor	xmm3,xmm1
+	pxor	xmm6,xmm15
+	pxor	xmm3,xmm4
+	pxor	xmm2,xmm5
+	pxor	xmm5,xmm0
+	pxor	xmm2,xmm3
+
+	pxor	xmm3,xmm15
+	pxor	xmm6,xmm2
+	dec	r10d
+	jl	$L$dec_done
+
+	pshufd	xmm7,xmm15,04Eh
+	pshufd	xmm13,xmm2,04Eh
+	pxor	xmm7,xmm15
+	pshufd	xmm14,xmm4,04Eh
+	pxor	xmm13,xmm2
+	pshufd	xmm8,xmm0,04Eh
+	pxor	xmm14,xmm4
+	pshufd	xmm9,xmm5,04Eh
+	pxor	xmm8,xmm0
+	pshufd	xmm10,xmm3,04Eh
+	pxor	xmm9,xmm5
+	pxor	xmm15,xmm13
+	pxor	xmm0,xmm13
+	pshufd	xmm11,xmm1,04Eh
+	pxor	xmm10,xmm3
+	pxor	xmm5,xmm7
+	pxor	xmm3,xmm8
+	pshufd	xmm12,xmm6,04Eh
+	pxor	xmm11,xmm1
+	pxor	xmm0,xmm14
+	pxor	xmm1,xmm9
+	pxor	xmm12,xmm6
+
+	pxor	xmm5,xmm14
+	pxor	xmm3,xmm13
+	pxor	xmm1,xmm13
+	pxor	xmm6,xmm10
+	pxor	xmm2,xmm11
+	pxor	xmm1,xmm14
+	pxor	xmm6,xmm14
+	pxor	xmm4,xmm12
+	pshufd	xmm7,xmm15,093h
+	pshufd	xmm8,xmm0,093h
+	pxor	xmm15,xmm7
+	pshufd	xmm9,xmm5,093h
+	pxor	xmm0,xmm8
+	pshufd	xmm10,xmm3,093h
+	pxor	xmm5,xmm9
+	pshufd	xmm11,xmm1,093h
+	pxor	xmm3,xmm10
+	pshufd	xmm12,xmm6,093h
+	pxor	xmm1,xmm11
+	pshufd	xmm13,xmm2,093h
+	pxor	xmm6,xmm12
+	pshufd	xmm14,xmm4,093h
+	pxor	xmm2,xmm13
+	pxor	xmm4,xmm14
+
+	pxor	xmm8,xmm15
+	pxor	xmm7,xmm4
+	pxor	xmm8,xmm4
+	pshufd	xmm15,xmm15,04Eh
+	pxor	xmm9,xmm0
+	pshufd	xmm0,xmm0,04Eh
+	pxor	xmm12,xmm1
+	pxor	xmm15,xmm7
+	pxor	xmm13,xmm6
+	pxor	xmm0,xmm8
+	pxor	xmm11,xmm3
+	pshufd	xmm7,xmm1,04Eh
+	pxor	xmm14,xmm2
+	pshufd	xmm8,xmm6,04Eh
+	pxor	xmm10,xmm5
+	pshufd	xmm1,xmm3,04Eh
+	pxor	xmm10,xmm4
+	pshufd	xmm6,xmm4,04Eh
+	pxor	xmm11,xmm4
+	pshufd	xmm3,xmm2,04Eh
+	pxor	xmm7,xmm11
+	pshufd	xmm2,xmm5,04Eh
+	pxor	xmm8,xmm12
+	pxor	xmm10,xmm1
+	pxor	xmm6,xmm14
+	pxor	xmm13,xmm3
+	movdqa	xmm3,xmm7
+	pxor	xmm2,xmm9
+	movdqa	xmm5,xmm13
+	movdqa	xmm4,xmm8
+	movdqa	xmm1,xmm2
+	movdqa	xmm2,xmm10
+	movdqa	xmm7,XMMWORD PTR[((-16))+r11]
+	jnz	$L$dec_loop
+	movdqa	xmm7,XMMWORD PTR[((-32))+r11]
+	jmp	$L$dec_loop
+ALIGN	16
+$L$dec_done::
+	movdqa	xmm7,XMMWORD PTR[r11]
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	movdqa	xmm9,xmm2
+	psrlq	xmm2,1
+	movdqa	xmm10,xmm1
+	psrlq	xmm1,1
+	pxor	xmm2,xmm4
+	pxor	xmm1,xmm6
+	pand	xmm2,xmm7
+	pand	xmm1,xmm7
+	pxor	xmm4,xmm2
+	psllq	xmm2,1
+	pxor	xmm6,xmm1
+	psllq	xmm1,1
+	pxor	xmm2,xmm9
+	pxor	xmm1,xmm10
+	movdqa	xmm9,xmm5
+	psrlq	xmm5,1
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,1
+	pxor	xmm5,xmm3
+	pxor	xmm15,xmm0
+	pand	xmm5,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm3,xmm5
+	psllq	xmm5,1
+	pxor	xmm0,xmm15
+	psllq	xmm15,1
+	pxor	xmm5,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[32+r11]
+	movdqa	xmm9,xmm6
+	psrlq	xmm6,2
+	movdqa	xmm10,xmm1
+	psrlq	xmm1,2
+	pxor	xmm6,xmm4
+	pxor	xmm1,xmm2
+	pand	xmm6,xmm8
+	pand	xmm1,xmm8
+	pxor	xmm4,xmm6
+	psllq	xmm6,2
+	pxor	xmm2,xmm1
+	psllq	xmm1,2
+	pxor	xmm6,xmm9
+	pxor	xmm1,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,2
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,2
+	pxor	xmm0,xmm3
+	pxor	xmm15,xmm5
+	pand	xmm0,xmm8
+	pand	xmm15,xmm8
+	pxor	xmm3,xmm0
+	psllq	xmm0,2
+	pxor	xmm5,xmm15
+	psllq	xmm15,2
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm9,xmm3
+	psrlq	xmm3,4
+	movdqa	xmm10,xmm5
+	psrlq	xmm5,4
+	pxor	xmm3,xmm4
+	pxor	xmm5,xmm2
+	pand	xmm3,xmm7
+	pand	xmm5,xmm7
+	pxor	xmm4,xmm3
+	psllq	xmm3,4
+	pxor	xmm2,xmm5
+	psllq	xmm5,4
+	pxor	xmm3,xmm9
+	pxor	xmm5,xmm10
+	movdqa	xmm9,xmm0
+	psrlq	xmm0,4
+	movdqa	xmm10,xmm15
+	psrlq	xmm15,4
+	pxor	xmm0,xmm6
+	pxor	xmm15,xmm1
+	pand	xmm0,xmm7
+	pand	xmm15,xmm7
+	pxor	xmm6,xmm0
+	psllq	xmm0,4
+	pxor	xmm1,xmm15
+	psllq	xmm15,4
+	pxor	xmm0,xmm9
+	pxor	xmm15,xmm10
+	movdqa	xmm7,XMMWORD PTR[rax]
+	pxor	xmm5,xmm7
+	pxor	xmm3,xmm7
+	pxor	xmm1,xmm7
+	pxor	xmm6,xmm7
+	pxor	xmm2,xmm7
+	pxor	xmm4,xmm7
+	pxor	xmm15,xmm7
+	pxor	xmm0,xmm7
+	DB	0F3h,0C3h		;repret
+_bsaes_decrypt8	ENDP
+
+ALIGN	16
+_bsaes_key_convert	PROC PRIVATE
+	lea	r11,QWORD PTR[$L$masks]
+	movdqu	xmm7,XMMWORD PTR[rcx]
+	lea	rcx,QWORD PTR[16+rcx]
+	movdqa	xmm0,XMMWORD PTR[r11]
+	movdqa	xmm1,XMMWORD PTR[16+r11]
+	movdqa	xmm2,XMMWORD PTR[32+r11]
+	movdqa	xmm3,XMMWORD PTR[48+r11]
+	movdqa	xmm4,XMMWORD PTR[64+r11]
+	pcmpeqd	xmm5,xmm5
+
+	movdqu	xmm6,XMMWORD PTR[rcx]
+	movdqa	XMMWORD PTR[rax],xmm7
+	lea	rax,QWORD PTR[16+rax]
+	dec	r10d
+	jmp	$L$key_loop
+ALIGN	16
+$L$key_loop::
+DB	102,15,56,0,244
+
+	movdqa	xmm8,xmm0
+	movdqa	xmm9,xmm1
+
+	pand	xmm8,xmm6
+	pand	xmm9,xmm6
+	movdqa	xmm10,xmm2
+	pcmpeqb	xmm8,xmm0
+	psllq	xmm0,4
+	movdqa	xmm11,xmm3
+	pcmpeqb	xmm9,xmm1
+	psllq	xmm1,4
+
+	pand	xmm10,xmm6
+	pand	xmm11,xmm6
+	movdqa	xmm12,xmm0
+	pcmpeqb	xmm10,xmm2
+	psllq	xmm2,4
+	movdqa	xmm13,xmm1
+	pcmpeqb	xmm11,xmm3
+	psllq	xmm3,4
+
+	movdqa	xmm14,xmm2
+	movdqa	xmm15,xmm3
+	pxor	xmm8,xmm5
+	pxor	xmm9,xmm5
+
+	pand	xmm12,xmm6
+	pand	xmm13,xmm6
+	movdqa	XMMWORD PTR[rax],xmm8
+	pcmpeqb	xmm12,xmm0
+	psrlq	xmm0,4
+	movdqa	XMMWORD PTR[16+rax],xmm9
+	pcmpeqb	xmm13,xmm1
+	psrlq	xmm1,4
+	lea	rcx,QWORD PTR[16+rcx]
+
+	pand	xmm14,xmm6
+	pand	xmm15,xmm6
+	movdqa	XMMWORD PTR[32+rax],xmm10
+	pcmpeqb	xmm14,xmm2
+	psrlq	xmm2,4
+	movdqa	XMMWORD PTR[48+rax],xmm11
+	pcmpeqb	xmm15,xmm3
+	psrlq	xmm3,4
+	movdqu	xmm6,XMMWORD PTR[rcx]
+
+	pxor	xmm13,xmm5
+	pxor	xmm14,xmm5
+	movdqa	XMMWORD PTR[64+rax],xmm12
+	movdqa	XMMWORD PTR[80+rax],xmm13
+	movdqa	XMMWORD PTR[96+rax],xmm14
+	movdqa	XMMWORD PTR[112+rax],xmm15
+	lea	rax,QWORD PTR[128+rax]
+	dec	r10d
+	jnz	$L$key_loop
+
+	movdqa	xmm7,XMMWORD PTR[80+r11]
+
+	DB	0F3h,0C3h		;repret
+_bsaes_key_convert	ENDP
+EXTERN	asm_AES_cbc_encrypt:NEAR
+PUBLIC	bsaes_cbc_encrypt
+
+ALIGN	16
+bsaes_cbc_encrypt	PROC PUBLIC
+	mov	r11d,DWORD PTR[48+rsp]
+	cmp	r11d,0
+	jne	asm_AES_cbc_encrypt
+	cmp	r8,128
+	jb	asm_AES_cbc_encrypt
+
+	mov	rax,rsp
+$L$cbc_dec_prologue::
+	push	rbp
+	push	rbx
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,QWORD PTR[((-72))+rsp]
+	mov	r10,QWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[((-160))+rsp]
+	movaps	XMMWORD PTR[64+rsp],xmm6
+	movaps	XMMWORD PTR[80+rsp],xmm7
+	movaps	XMMWORD PTR[96+rsp],xmm8
+	movaps	XMMWORD PTR[112+rsp],xmm9
+	movaps	XMMWORD PTR[128+rsp],xmm10
+	movaps	XMMWORD PTR[144+rsp],xmm11
+	movaps	XMMWORD PTR[160+rsp],xmm12
+	movaps	XMMWORD PTR[176+rsp],xmm13
+	movaps	XMMWORD PTR[192+rsp],xmm14
+	movaps	XMMWORD PTR[208+rsp],xmm15
+$L$cbc_dec_body::
+	mov	rbp,rsp
+	mov	eax,DWORD PTR[240+r9]
+	mov	r12,rcx
+	mov	r13,rdx
+	mov	r14,r8
+	mov	r15,r9
+	mov	rbx,r10
+	shr	r14,4
+
+	mov	edx,eax
+	shl	rax,7
+	sub	rax,96
+	sub	rsp,rax
+
+	mov	rax,rsp
+	mov	rcx,r15
+	mov	r10d,edx
+	call	_bsaes_key_convert
+	pxor	xmm7,XMMWORD PTR[rsp]
+	movdqa	XMMWORD PTR[rax],xmm6
+	movdqa	XMMWORD PTR[rsp],xmm7
+
+	movdqu	xmm14,XMMWORD PTR[rbx]
+	sub	r14,8
+$L$cbc_dec_loop::
+	movdqu	xmm15,XMMWORD PTR[r12]
+	movdqu	xmm0,XMMWORD PTR[16+r12]
+	movdqu	xmm1,XMMWORD PTR[32+r12]
+	movdqu	xmm2,XMMWORD PTR[48+r12]
+	movdqu	xmm3,XMMWORD PTR[64+r12]
+	movdqu	xmm4,XMMWORD PTR[80+r12]
+	mov	rax,rsp
+	movdqu	xmm5,XMMWORD PTR[96+r12]
+	mov	r10d,edx
+	movdqu	xmm6,XMMWORD PTR[112+r12]
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm3,xmm9
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm1,xmm10
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	pxor	xmm6,xmm11
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm2,xmm12
+	movdqu	xmm14,XMMWORD PTR[112+r12]
+	pxor	xmm4,xmm13
+	movdqu	XMMWORD PTR[r13],xmm15
+	lea	r12,QWORD PTR[128+r12]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	movdqu	XMMWORD PTR[96+r13],xmm2
+	movdqu	XMMWORD PTR[112+r13],xmm4
+	lea	r13,QWORD PTR[128+r13]
+	sub	r14,8
+	jnc	$L$cbc_dec_loop
+
+	add	r14,8
+	jz	$L$cbc_dec_done
+
+	movdqu	xmm15,XMMWORD PTR[r12]
+	mov	rax,rsp
+	mov	r10d,edx
+	cmp	r14,2
+	jb	$L$cbc_dec_one
+	movdqu	xmm0,XMMWORD PTR[16+r12]
+	je	$L$cbc_dec_two
+	movdqu	xmm1,XMMWORD PTR[32+r12]
+	cmp	r14,4
+	jb	$L$cbc_dec_three
+	movdqu	xmm2,XMMWORD PTR[48+r12]
+	je	$L$cbc_dec_four
+	movdqu	xmm3,XMMWORD PTR[64+r12]
+	cmp	r14,6
+	jb	$L$cbc_dec_five
+	movdqu	xmm4,XMMWORD PTR[80+r12]
+	je	$L$cbc_dec_six
+	movdqu	xmm5,XMMWORD PTR[96+r12]
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm3,xmm9
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm1,xmm10
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	pxor	xmm6,xmm11
+	movdqu	xmm14,XMMWORD PTR[96+r12]
+	pxor	xmm2,xmm12
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	movdqu	XMMWORD PTR[96+r13],xmm2
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_six::
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm3,xmm9
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm1,xmm10
+	movdqu	xmm14,XMMWORD PTR[80+r12]
+	pxor	xmm6,xmm11
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_five::
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm3,xmm9
+	movdqu	xmm14,XMMWORD PTR[64+r12]
+	pxor	xmm1,xmm10
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_four::
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	xmm14,XMMWORD PTR[48+r12]
+	pxor	xmm3,xmm9
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_three::
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	xmm14,XMMWORD PTR[32+r12]
+	pxor	xmm5,xmm8
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_two::
+	movdqa	XMMWORD PTR[32+rbp],xmm14
+	call	_bsaes_decrypt8
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm14,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm7
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	jmp	$L$cbc_dec_done
+ALIGN	16
+$L$cbc_dec_one::
+	lea	rcx,QWORD PTR[r12]
+	lea	rdx,QWORD PTR[32+rbp]
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_decrypt		
+	pxor	xmm14,XMMWORD PTR[32+rbp]
+	movdqu	XMMWORD PTR[r13],xmm14
+	movdqa	xmm14,xmm15
+
+$L$cbc_dec_done::
+	movdqu	XMMWORD PTR[rbx],xmm14
+	lea	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+$L$cbc_dec_bzero::
+	movdqa	XMMWORD PTR[rax],xmm0
+	movdqa	XMMWORD PTR[16+rax],xmm0
+	lea	rax,QWORD PTR[32+rax]
+	cmp	rbp,rax
+	ja	$L$cbc_dec_bzero
+
+	lea	rsp,QWORD PTR[rbp]
+	movaps	xmm6,XMMWORD PTR[64+rbp]
+	movaps	xmm7,XMMWORD PTR[80+rbp]
+	movaps	xmm8,XMMWORD PTR[96+rbp]
+	movaps	xmm9,XMMWORD PTR[112+rbp]
+	movaps	xmm10,XMMWORD PTR[128+rbp]
+	movaps	xmm11,XMMWORD PTR[144+rbp]
+	movaps	xmm12,XMMWORD PTR[160+rbp]
+	movaps	xmm13,XMMWORD PTR[176+rbp]
+	movaps	xmm14,XMMWORD PTR[192+rbp]
+	movaps	xmm15,XMMWORD PTR[208+rbp]
+	lea	rsp,QWORD PTR[160+rbp]
+	mov	r15,QWORD PTR[72+rsp]
+	mov	r14,QWORD PTR[80+rsp]
+	mov	r13,QWORD PTR[88+rsp]
+	mov	r12,QWORD PTR[96+rsp]
+	mov	rbx,QWORD PTR[104+rsp]
+	mov	rax,QWORD PTR[112+rsp]
+	lea	rsp,QWORD PTR[120+rsp]
+	mov	rbp,rax
+$L$cbc_dec_epilogue::
+	DB	0F3h,0C3h		;repret
+bsaes_cbc_encrypt	ENDP
+
+PUBLIC	bsaes_ctr32_encrypt_blocks
+
+ALIGN	16
+bsaes_ctr32_encrypt_blocks	PROC PUBLIC
+	mov	rax,rsp
+$L$ctr_enc_prologue::
+	push	rbp
+	push	rbx
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,QWORD PTR[((-72))+rsp]
+	mov	r10,QWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[((-160))+rsp]
+	movaps	XMMWORD PTR[64+rsp],xmm6
+	movaps	XMMWORD PTR[80+rsp],xmm7
+	movaps	XMMWORD PTR[96+rsp],xmm8
+	movaps	XMMWORD PTR[112+rsp],xmm9
+	movaps	XMMWORD PTR[128+rsp],xmm10
+	movaps	XMMWORD PTR[144+rsp],xmm11
+	movaps	XMMWORD PTR[160+rsp],xmm12
+	movaps	XMMWORD PTR[176+rsp],xmm13
+	movaps	XMMWORD PTR[192+rsp],xmm14
+	movaps	XMMWORD PTR[208+rsp],xmm15
+$L$ctr_enc_body::
+	mov	rbp,rsp
+	movdqu	xmm0,XMMWORD PTR[r10]
+	mov	eax,DWORD PTR[240+r9]
+	mov	r12,rcx
+	mov	r13,rdx
+	mov	r14,r8
+	mov	r15,r9
+	movdqa	XMMWORD PTR[32+rbp],xmm0
+	cmp	r8,8
+	jb	$L$ctr_enc_short
+
+	mov	ebx,eax
+	shl	rax,7
+	sub	rax,96
+	sub	rsp,rax
+
+	mov	rax,rsp
+	mov	rcx,r15
+	mov	r10d,ebx
+	call	_bsaes_key_convert
+	pxor	xmm7,xmm6
+	movdqa	XMMWORD PTR[rax],xmm7
+
+	movdqa	xmm8,XMMWORD PTR[rsp]
+	lea	r11,QWORD PTR[$L$ADD1]
+	movdqa	xmm15,XMMWORD PTR[32+rbp]
+	movdqa	xmm7,XMMWORD PTR[((-32))+r11]
+DB	102,68,15,56,0,199
+DB	102,68,15,56,0,255
+	movdqa	XMMWORD PTR[rsp],xmm8
+	jmp	$L$ctr_enc_loop
+ALIGN	16
+$L$ctr_enc_loop::
+	movdqa	XMMWORD PTR[32+rbp],xmm15
+	movdqa	xmm0,xmm15
+	movdqa	xmm1,xmm15
+	paddd	xmm0,XMMWORD PTR[r11]
+	movdqa	xmm2,xmm15
+	paddd	xmm1,XMMWORD PTR[16+r11]
+	movdqa	xmm3,xmm15
+	paddd	xmm2,XMMWORD PTR[32+r11]
+	movdqa	xmm4,xmm15
+	paddd	xmm3,XMMWORD PTR[48+r11]
+	movdqa	xmm5,xmm15
+	paddd	xmm4,XMMWORD PTR[64+r11]
+	movdqa	xmm6,xmm15
+	paddd	xmm5,XMMWORD PTR[80+r11]
+	paddd	xmm6,XMMWORD PTR[96+r11]
+
+
+
+	movdqa	xmm8,XMMWORD PTR[rsp]
+	lea	rax,QWORD PTR[16+rsp]
+	movdqa	xmm7,XMMWORD PTR[((-16))+r11]
+	pxor	xmm15,xmm8
+	pxor	xmm0,xmm8
+DB	102,68,15,56,0,255
+	pxor	xmm1,xmm8
+DB	102,15,56,0,199
+	pxor	xmm2,xmm8
+DB	102,15,56,0,207
+	pxor	xmm3,xmm8
+DB	102,15,56,0,215
+	pxor	xmm4,xmm8
+DB	102,15,56,0,223
+	pxor	xmm5,xmm8
+DB	102,15,56,0,231
+	pxor	xmm6,xmm8
+DB	102,15,56,0,239
+	lea	r11,QWORD PTR[$L$BS0]
+DB	102,15,56,0,247
+	mov	r10d,ebx
+
+	call	_bsaes_encrypt8_bitslice
+
+	sub	r14,8
+	jc	$L$ctr_enc_loop_done
+
+	movdqu	xmm7,XMMWORD PTR[r12]
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	movdqu	xmm14,XMMWORD PTR[112+r12]
+	lea	r12,QWORD PTR[128+r12]
+	pxor	xmm7,xmm15
+	movdqa	xmm15,XMMWORD PTR[32+rbp]
+	pxor	xmm0,xmm8
+	movdqu	XMMWORD PTR[r13],xmm7
+	pxor	xmm3,xmm9
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,xmm10
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	pxor	xmm2,xmm11
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	pxor	xmm6,xmm12
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	pxor	xmm1,xmm13
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	pxor	xmm4,xmm14
+	movdqu	XMMWORD PTR[96+r13],xmm1
+	lea	r11,QWORD PTR[$L$ADD1]
+	movdqu	XMMWORD PTR[112+r13],xmm4
+	lea	r13,QWORD PTR[128+r13]
+	paddd	xmm15,XMMWORD PTR[112+r11]
+	jnz	$L$ctr_enc_loop
+
+	jmp	$L$ctr_enc_done
+ALIGN	16
+$L$ctr_enc_loop_done::
+	add	r14,8
+	movdqu	xmm7,XMMWORD PTR[r12]
+	pxor	xmm15,xmm7
+	movdqu	XMMWORD PTR[r13],xmm15
+	cmp	r14,2
+	jb	$L$ctr_enc_done
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm0,xmm8
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	je	$L$ctr_enc_done
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm3,xmm9
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	cmp	r14,4
+	jb	$L$ctr_enc_done
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm5,xmm10
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	je	$L$ctr_enc_done
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm2,xmm11
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	cmp	r14,6
+	jb	$L$ctr_enc_done
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	pxor	xmm6,xmm12
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	je	$L$ctr_enc_done
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm1,xmm13
+	movdqu	XMMWORD PTR[96+r13],xmm1
+	jmp	$L$ctr_enc_done
+
+ALIGN	16
+$L$ctr_enc_short::
+	lea	rcx,QWORD PTR[32+rbp]
+	lea	rdx,QWORD PTR[48+rbp]
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_encrypt
+	movdqu	xmm0,XMMWORD PTR[r12]
+	lea	r12,QWORD PTR[16+r12]
+	mov	eax,DWORD PTR[44+rbp]
+	bswap	eax
+	pxor	xmm0,XMMWORD PTR[48+rbp]
+	inc	eax
+	movdqu	XMMWORD PTR[r13],xmm0
+	bswap	eax
+	lea	r13,QWORD PTR[16+r13]
+	mov	DWORD PTR[44+rsp],eax
+	dec	r14
+	jnz	$L$ctr_enc_short
+
+$L$ctr_enc_done::
+	lea	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+$L$ctr_enc_bzero::
+	movdqa	XMMWORD PTR[rax],xmm0
+	movdqa	XMMWORD PTR[16+rax],xmm0
+	lea	rax,QWORD PTR[32+rax]
+	cmp	rbp,rax
+	ja	$L$ctr_enc_bzero
+
+	lea	rsp,QWORD PTR[rbp]
+	movaps	xmm6,XMMWORD PTR[64+rbp]
+	movaps	xmm7,XMMWORD PTR[80+rbp]
+	movaps	xmm8,XMMWORD PTR[96+rbp]
+	movaps	xmm9,XMMWORD PTR[112+rbp]
+	movaps	xmm10,XMMWORD PTR[128+rbp]
+	movaps	xmm11,XMMWORD PTR[144+rbp]
+	movaps	xmm12,XMMWORD PTR[160+rbp]
+	movaps	xmm13,XMMWORD PTR[176+rbp]
+	movaps	xmm14,XMMWORD PTR[192+rbp]
+	movaps	xmm15,XMMWORD PTR[208+rbp]
+	lea	rsp,QWORD PTR[160+rbp]
+	mov	r15,QWORD PTR[72+rsp]
+	mov	r14,QWORD PTR[80+rsp]
+	mov	r13,QWORD PTR[88+rsp]
+	mov	r12,QWORD PTR[96+rsp]
+	mov	rbx,QWORD PTR[104+rsp]
+	mov	rax,QWORD PTR[112+rsp]
+	lea	rsp,QWORD PTR[120+rsp]
+	mov	rbp,rax
+$L$ctr_enc_epilogue::
+	DB	0F3h,0C3h		;repret
+bsaes_ctr32_encrypt_blocks	ENDP
+PUBLIC	bsaes_xts_encrypt
+
+ALIGN	16
+bsaes_xts_encrypt	PROC PUBLIC
+	mov	rax,rsp
+$L$xts_enc_prologue::
+	push	rbp
+	push	rbx
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,QWORD PTR[((-72))+rsp]
+	mov	r10,QWORD PTR[160+rsp]
+	mov	r11,QWORD PTR[168+rsp]
+	lea	rsp,QWORD PTR[((-160))+rsp]
+	movaps	XMMWORD PTR[64+rsp],xmm6
+	movaps	XMMWORD PTR[80+rsp],xmm7
+	movaps	XMMWORD PTR[96+rsp],xmm8
+	movaps	XMMWORD PTR[112+rsp],xmm9
+	movaps	XMMWORD PTR[128+rsp],xmm10
+	movaps	XMMWORD PTR[144+rsp],xmm11
+	movaps	XMMWORD PTR[160+rsp],xmm12
+	movaps	XMMWORD PTR[176+rsp],xmm13
+	movaps	XMMWORD PTR[192+rsp],xmm14
+	movaps	XMMWORD PTR[208+rsp],xmm15
+$L$xts_enc_body::
+	mov	rbp,rsp
+	mov	r12,rcx
+	mov	r13,rdx
+	mov	r14,r8
+	mov	r15,r9
+
+	lea	rcx,QWORD PTR[r11]
+	lea	rdx,QWORD PTR[32+rbp]
+	lea	r8,QWORD PTR[r10]
+	call	asm_AES_encrypt		
+
+	mov	eax,DWORD PTR[240+r15]
+	mov	rbx,r14
+
+	mov	edx,eax
+	shl	rax,7
+	sub	rax,96
+	sub	rsp,rax
+
+	mov	rax,rsp
+	mov	rcx,r15
+	mov	r10d,edx
+	call	_bsaes_key_convert
+	pxor	xmm7,xmm6
+	movdqa	XMMWORD PTR[rax],xmm7
+
+	and	r14,-16
+	sub	rsp,080h
+	movdqa	xmm6,XMMWORD PTR[32+rbp]
+
+	pxor	xmm14,xmm14
+	movdqa	xmm12,XMMWORD PTR[$L$xts_magic]
+	pcmpgtd	xmm14,xmm6
+
+	sub	r14,080h
+	jc	$L$xts_enc_short
+	jmp	$L$xts_enc_loop
+
+ALIGN	16
+$L$xts_enc_loop::
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm15,xmm6
+	movdqa	XMMWORD PTR[rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm0,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm7,XMMWORD PTR[r12]
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm1,xmm6
+	movdqa	XMMWORD PTR[32+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm15,xmm7
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm2,xmm6
+	movdqa	XMMWORD PTR[48+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm0,xmm8
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm3,xmm6
+	movdqa	XMMWORD PTR[64+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm1,xmm9
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm4,xmm6
+	movdqa	XMMWORD PTR[80+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm2,xmm10
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm5,xmm6
+	movdqa	XMMWORD PTR[96+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	pxor	xmm3,xmm11
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	movdqu	xmm14,XMMWORD PTR[112+r12]
+	lea	r12,QWORD PTR[128+r12]
+	movdqa	XMMWORD PTR[112+rsp],xmm6
+	pxor	xmm5,xmm13
+	lea	rax,QWORD PTR[128+rsp]
+	pxor	xmm6,xmm14
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	pxor	xmm2,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	pxor	xmm1,XMMWORD PTR[96+rsp]
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	pxor	xmm4,XMMWORD PTR[112+rsp]
+	movdqu	XMMWORD PTR[96+r13],xmm1
+	movdqu	XMMWORD PTR[112+r13],xmm4
+	lea	r13,QWORD PTR[128+r13]
+
+	movdqa	xmm6,XMMWORD PTR[112+rsp]
+	pxor	xmm14,xmm14
+	movdqa	xmm12,XMMWORD PTR[$L$xts_magic]
+	pcmpgtd	xmm14,xmm6
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+
+	sub	r14,080h
+	jnc	$L$xts_enc_loop
+
+$L$xts_enc_short::
+	add	r14,080h
+	jz	$L$xts_enc_done
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm15,xmm6
+	movdqa	XMMWORD PTR[rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm0,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm7,XMMWORD PTR[r12]
+	cmp	r14,16
+	je	$L$xts_enc_1
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm1,xmm6
+	movdqa	XMMWORD PTR[32+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	cmp	r14,32
+	je	$L$xts_enc_2
+	pxor	xmm15,xmm7
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm2,xmm6
+	movdqa	XMMWORD PTR[48+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	cmp	r14,48
+	je	$L$xts_enc_3
+	pxor	xmm0,xmm8
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm3,xmm6
+	movdqa	XMMWORD PTR[64+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	cmp	r14,64
+	je	$L$xts_enc_4
+	pxor	xmm1,xmm9
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm4,xmm6
+	movdqa	XMMWORD PTR[80+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	cmp	r14,80
+	je	$L$xts_enc_5
+	pxor	xmm2,xmm10
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm5,xmm6
+	movdqa	XMMWORD PTR[96+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	cmp	r14,96
+	je	$L$xts_enc_6
+	pxor	xmm3,xmm11
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	movdqa	XMMWORD PTR[112+rsp],xmm6
+	lea	r12,QWORD PTR[112+r12]
+	pxor	xmm5,xmm13
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	pxor	xmm2,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	pxor	xmm1,XMMWORD PTR[96+rsp]
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	movdqu	XMMWORD PTR[96+r13],xmm1
+	lea	r13,QWORD PTR[112+r13]
+
+	movdqa	xmm6,XMMWORD PTR[112+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_6::
+	pxor	xmm3,xmm11
+	lea	r12,QWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	pxor	xmm2,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	lea	r13,QWORD PTR[96+r13]
+
+	movdqa	xmm6,XMMWORD PTR[96+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_5::
+	pxor	xmm2,xmm10
+	lea	r12,QWORD PTR[80+r12]
+	pxor	xmm3,xmm11
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	pxor	xmm2,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	movdqu	XMMWORD PTR[64+r13],xmm2
+	lea	r13,QWORD PTR[80+r13]
+
+	movdqa	xmm6,XMMWORD PTR[80+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_4::
+	pxor	xmm1,xmm9
+	lea	r12,QWORD PTR[64+r12]
+	pxor	xmm2,xmm10
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm5,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	movdqu	XMMWORD PTR[48+r13],xmm5
+	lea	r13,QWORD PTR[64+r13]
+
+	movdqa	xmm6,XMMWORD PTR[64+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_3::
+	pxor	xmm0,xmm8
+	lea	r12,QWORD PTR[48+r12]
+	pxor	xmm1,xmm9
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm3,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm3
+	lea	r13,QWORD PTR[48+r13]
+
+	movdqa	xmm6,XMMWORD PTR[48+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_2::
+	pxor	xmm15,xmm7
+	lea	r12,QWORD PTR[32+r12]
+	pxor	xmm0,xmm8
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_encrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	lea	r13,QWORD PTR[32+r13]
+
+	movdqa	xmm6,XMMWORD PTR[32+rsp]
+	jmp	$L$xts_enc_done
+ALIGN	16
+$L$xts_enc_1::
+	pxor	xmm7,xmm15
+	lea	r12,QWORD PTR[16+r12]
+	movdqa	XMMWORD PTR[32+rbp],xmm7
+	lea	rcx,QWORD PTR[32+rbp]
+	lea	rdx,QWORD PTR[32+rbp]
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_encrypt		
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+
+
+
+
+
+	movdqu	XMMWORD PTR[r13],xmm15
+	lea	r13,QWORD PTR[16+r13]
+
+	movdqa	xmm6,XMMWORD PTR[16+rsp]
+
+$L$xts_enc_done::
+	and	ebx,15
+	jz	$L$xts_enc_ret
+	mov	rdx,r13
+
+$L$xts_enc_steal::
+	movzx	eax,BYTE PTR[r12]
+	movzx	ecx,BYTE PTR[((-16))+rdx]
+	lea	r12,QWORD PTR[1+r12]
+	mov	BYTE PTR[((-16))+rdx],al
+	mov	BYTE PTR[rdx],cl
+	lea	rdx,QWORD PTR[1+rdx]
+	sub	ebx,1
+	jnz	$L$xts_enc_steal
+
+	movdqu	xmm15,XMMWORD PTR[((-16))+r13]
+	lea	rcx,QWORD PTR[32+rbp]
+	pxor	xmm15,xmm6
+	lea	rdx,QWORD PTR[32+rbp]
+	movdqa	XMMWORD PTR[32+rbp],xmm15
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_encrypt		
+	pxor	xmm6,XMMWORD PTR[32+rbp]
+	movdqu	XMMWORD PTR[(-16)+r13],xmm6
+
+$L$xts_enc_ret::
+	lea	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+$L$xts_enc_bzero::
+	movdqa	XMMWORD PTR[rax],xmm0
+	movdqa	XMMWORD PTR[16+rax],xmm0
+	lea	rax,QWORD PTR[32+rax]
+	cmp	rbp,rax
+	ja	$L$xts_enc_bzero
+
+	lea	rsp,QWORD PTR[rbp]
+	movaps	xmm6,XMMWORD PTR[64+rbp]
+	movaps	xmm7,XMMWORD PTR[80+rbp]
+	movaps	xmm8,XMMWORD PTR[96+rbp]
+	movaps	xmm9,XMMWORD PTR[112+rbp]
+	movaps	xmm10,XMMWORD PTR[128+rbp]
+	movaps	xmm11,XMMWORD PTR[144+rbp]
+	movaps	xmm12,XMMWORD PTR[160+rbp]
+	movaps	xmm13,XMMWORD PTR[176+rbp]
+	movaps	xmm14,XMMWORD PTR[192+rbp]
+	movaps	xmm15,XMMWORD PTR[208+rbp]
+	lea	rsp,QWORD PTR[160+rbp]
+	mov	r15,QWORD PTR[72+rsp]
+	mov	r14,QWORD PTR[80+rsp]
+	mov	r13,QWORD PTR[88+rsp]
+	mov	r12,QWORD PTR[96+rsp]
+	mov	rbx,QWORD PTR[104+rsp]
+	mov	rax,QWORD PTR[112+rsp]
+	lea	rsp,QWORD PTR[120+rsp]
+	mov	rbp,rax
+$L$xts_enc_epilogue::
+	DB	0F3h,0C3h		;repret
+bsaes_xts_encrypt	ENDP
+
+PUBLIC	bsaes_xts_decrypt
+
+ALIGN	16
+bsaes_xts_decrypt	PROC PUBLIC
+	mov	rax,rsp
+$L$xts_dec_prologue::
+	push	rbp
+	push	rbx
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,QWORD PTR[((-72))+rsp]
+	mov	r10,QWORD PTR[160+rsp]
+	mov	r11,QWORD PTR[168+rsp]
+	lea	rsp,QWORD PTR[((-160))+rsp]
+	movaps	XMMWORD PTR[64+rsp],xmm6
+	movaps	XMMWORD PTR[80+rsp],xmm7
+	movaps	XMMWORD PTR[96+rsp],xmm8
+	movaps	XMMWORD PTR[112+rsp],xmm9
+	movaps	XMMWORD PTR[128+rsp],xmm10
+	movaps	XMMWORD PTR[144+rsp],xmm11
+	movaps	XMMWORD PTR[160+rsp],xmm12
+	movaps	XMMWORD PTR[176+rsp],xmm13
+	movaps	XMMWORD PTR[192+rsp],xmm14
+	movaps	XMMWORD PTR[208+rsp],xmm15
+$L$xts_dec_body::
+	mov	rbp,rsp
+	mov	r12,rcx
+	mov	r13,rdx
+	mov	r14,r8
+	mov	r15,r9
+
+	lea	rcx,QWORD PTR[r11]
+	lea	rdx,QWORD PTR[32+rbp]
+	lea	r8,QWORD PTR[r10]
+	call	asm_AES_encrypt		
+
+	mov	eax,DWORD PTR[240+r15]
+	mov	rbx,r14
+
+	mov	edx,eax
+	shl	rax,7
+	sub	rax,96
+	sub	rsp,rax
+
+	mov	rax,rsp
+	mov	rcx,r15
+	mov	r10d,edx
+	call	_bsaes_key_convert
+	pxor	xmm7,XMMWORD PTR[rsp]
+	movdqa	XMMWORD PTR[rax],xmm6
+	movdqa	XMMWORD PTR[rsp],xmm7
+
+	xor	eax,eax
+	and	r14,-16
+	test	ebx,15
+	setnz	al
+	shl	rax,4
+	sub	r14,rax
+
+	sub	rsp,080h
+	movdqa	xmm6,XMMWORD PTR[32+rbp]
+
+	pxor	xmm14,xmm14
+	movdqa	xmm12,XMMWORD PTR[$L$xts_magic]
+	pcmpgtd	xmm14,xmm6
+
+	sub	r14,080h
+	jc	$L$xts_dec_short
+	jmp	$L$xts_dec_loop
+
+ALIGN	16
+$L$xts_dec_loop::
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm15,xmm6
+	movdqa	XMMWORD PTR[rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm0,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm7,XMMWORD PTR[r12]
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm1,xmm6
+	movdqa	XMMWORD PTR[32+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	pxor	xmm15,xmm7
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm2,xmm6
+	movdqa	XMMWORD PTR[48+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	pxor	xmm0,xmm8
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm3,xmm6
+	movdqa	XMMWORD PTR[64+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	pxor	xmm1,xmm9
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm4,xmm6
+	movdqa	XMMWORD PTR[80+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	pxor	xmm2,xmm10
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm5,xmm6
+	movdqa	XMMWORD PTR[96+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	pxor	xmm3,xmm11
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	movdqu	xmm14,XMMWORD PTR[112+r12]
+	lea	r12,QWORD PTR[128+r12]
+	movdqa	XMMWORD PTR[112+rsp],xmm6
+	pxor	xmm5,xmm13
+	lea	rax,QWORD PTR[128+rsp]
+	pxor	xmm6,xmm14
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm3,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	pxor	xmm1,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	pxor	xmm2,XMMWORD PTR[96+rsp]
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	pxor	xmm4,XMMWORD PTR[112+rsp]
+	movdqu	XMMWORD PTR[96+r13],xmm2
+	movdqu	XMMWORD PTR[112+r13],xmm4
+	lea	r13,QWORD PTR[128+r13]
+
+	movdqa	xmm6,XMMWORD PTR[112+rsp]
+	pxor	xmm14,xmm14
+	movdqa	xmm12,XMMWORD PTR[$L$xts_magic]
+	pcmpgtd	xmm14,xmm6
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+
+	sub	r14,080h
+	jnc	$L$xts_dec_loop
+
+$L$xts_dec_short::
+	add	r14,080h
+	jz	$L$xts_dec_done
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm15,xmm6
+	movdqa	XMMWORD PTR[rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm0,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm7,XMMWORD PTR[r12]
+	cmp	r14,16
+	je	$L$xts_dec_1
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm1,xmm6
+	movdqa	XMMWORD PTR[32+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm8,XMMWORD PTR[16+r12]
+	cmp	r14,32
+	je	$L$xts_dec_2
+	pxor	xmm15,xmm7
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm2,xmm6
+	movdqa	XMMWORD PTR[48+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm9,XMMWORD PTR[32+r12]
+	cmp	r14,48
+	je	$L$xts_dec_3
+	pxor	xmm0,xmm8
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm3,xmm6
+	movdqa	XMMWORD PTR[64+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm10,XMMWORD PTR[48+r12]
+	cmp	r14,64
+	je	$L$xts_dec_4
+	pxor	xmm1,xmm9
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm4,xmm6
+	movdqa	XMMWORD PTR[80+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm11,XMMWORD PTR[64+r12]
+	cmp	r14,80
+	je	$L$xts_dec_5
+	pxor	xmm2,xmm10
+	pshufd	xmm13,xmm14,013h
+	pxor	xmm14,xmm14
+	movdqa	xmm5,xmm6
+	movdqa	XMMWORD PTR[96+rsp],xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	pcmpgtd	xmm14,xmm6
+	pxor	xmm6,xmm13
+	movdqu	xmm12,XMMWORD PTR[80+r12]
+	cmp	r14,96
+	je	$L$xts_dec_6
+	pxor	xmm3,xmm11
+	movdqu	xmm13,XMMWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	movdqa	XMMWORD PTR[112+rsp],xmm6
+	lea	r12,QWORD PTR[112+r12]
+	pxor	xmm5,xmm13
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm3,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	pxor	xmm1,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	pxor	xmm2,XMMWORD PTR[96+rsp]
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	movdqu	XMMWORD PTR[96+r13],xmm2
+	lea	r13,QWORD PTR[112+r13]
+
+	movdqa	xmm6,XMMWORD PTR[112+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_6::
+	pxor	xmm3,xmm11
+	lea	r12,QWORD PTR[96+r12]
+	pxor	xmm4,xmm12
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm3,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	pxor	xmm1,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	pxor	xmm6,XMMWORD PTR[80+rsp]
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	movdqu	XMMWORD PTR[80+r13],xmm6
+	lea	r13,QWORD PTR[96+r13]
+
+	movdqa	xmm6,XMMWORD PTR[96+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_5::
+	pxor	xmm2,xmm10
+	lea	r12,QWORD PTR[80+r12]
+	pxor	xmm3,xmm11
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm3,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	pxor	xmm1,XMMWORD PTR[64+rsp]
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	movdqu	XMMWORD PTR[64+r13],xmm1
+	lea	r13,QWORD PTR[80+r13]
+
+	movdqa	xmm6,XMMWORD PTR[80+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_4::
+	pxor	xmm1,xmm9
+	lea	r12,QWORD PTR[64+r12]
+	pxor	xmm2,xmm10
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	pxor	xmm3,XMMWORD PTR[48+rsp]
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	movdqu	XMMWORD PTR[48+r13],xmm3
+	lea	r13,QWORD PTR[64+r13]
+
+	movdqa	xmm6,XMMWORD PTR[64+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_3::
+	pxor	xmm0,xmm8
+	lea	r12,QWORD PTR[48+r12]
+	pxor	xmm1,xmm9
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	pxor	xmm5,XMMWORD PTR[32+rsp]
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	movdqu	XMMWORD PTR[32+r13],xmm5
+	lea	r13,QWORD PTR[48+r13]
+
+	movdqa	xmm6,XMMWORD PTR[48+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_2::
+	pxor	xmm15,xmm7
+	lea	r12,QWORD PTR[32+r12]
+	pxor	xmm0,xmm8
+	lea	rax,QWORD PTR[128+rsp]
+	mov	r10d,edx
+
+	call	_bsaes_decrypt8
+
+	pxor	xmm15,XMMWORD PTR[rsp]
+	pxor	xmm0,XMMWORD PTR[16+rsp]
+	movdqu	XMMWORD PTR[r13],xmm15
+	movdqu	XMMWORD PTR[16+r13],xmm0
+	lea	r13,QWORD PTR[32+r13]
+
+	movdqa	xmm6,XMMWORD PTR[32+rsp]
+	jmp	$L$xts_dec_done
+ALIGN	16
+$L$xts_dec_1::
+	pxor	xmm7,xmm15
+	lea	r12,QWORD PTR[16+r12]
+	movdqa	XMMWORD PTR[32+rbp],xmm7
+	lea	rcx,QWORD PTR[32+rbp]
+	lea	rdx,QWORD PTR[32+rbp]
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_decrypt		
+	pxor	xmm15,XMMWORD PTR[32+rbp]
+
+
+
+
+
+	movdqu	XMMWORD PTR[r13],xmm15
+	lea	r13,QWORD PTR[16+r13]
+
+	movdqa	xmm6,XMMWORD PTR[16+rsp]
+
+$L$xts_dec_done::
+	and	ebx,15
+	jz	$L$xts_dec_ret
+
+	pxor	xmm14,xmm14
+	movdqa	xmm12,XMMWORD PTR[$L$xts_magic]
+	pcmpgtd	xmm14,xmm6
+	pshufd	xmm13,xmm14,013h
+	movdqa	xmm5,xmm6
+	paddq	xmm6,xmm6
+	pand	xmm13,xmm12
+	movdqu	xmm15,XMMWORD PTR[r12]
+	pxor	xmm6,xmm13
+
+	lea	rcx,QWORD PTR[32+rbp]
+	pxor	xmm15,xmm6
+	lea	rdx,QWORD PTR[32+rbp]
+	movdqa	XMMWORD PTR[32+rbp],xmm15
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_decrypt		
+	pxor	xmm6,XMMWORD PTR[32+rbp]
+	mov	rdx,r13
+	movdqu	XMMWORD PTR[r13],xmm6
+
+$L$xts_dec_steal::
+	movzx	eax,BYTE PTR[16+r12]
+	movzx	ecx,BYTE PTR[rdx]
+	lea	r12,QWORD PTR[1+r12]
+	mov	BYTE PTR[rdx],al
+	mov	BYTE PTR[16+rdx],cl
+	lea	rdx,QWORD PTR[1+rdx]
+	sub	ebx,1
+	jnz	$L$xts_dec_steal
+
+	movdqu	xmm15,XMMWORD PTR[r13]
+	lea	rcx,QWORD PTR[32+rbp]
+	pxor	xmm15,xmm5
+	lea	rdx,QWORD PTR[32+rbp]
+	movdqa	XMMWORD PTR[32+rbp],xmm15
+	lea	r8,QWORD PTR[r15]
+	call	asm_AES_decrypt		
+	pxor	xmm5,XMMWORD PTR[32+rbp]
+	movdqu	XMMWORD PTR[r13],xmm5
+
+$L$xts_dec_ret::
+	lea	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+$L$xts_dec_bzero::
+	movdqa	XMMWORD PTR[rax],xmm0
+	movdqa	XMMWORD PTR[16+rax],xmm0
+	lea	rax,QWORD PTR[32+rax]
+	cmp	rbp,rax
+	ja	$L$xts_dec_bzero
+
+	lea	rsp,QWORD PTR[rbp]
+	movaps	xmm6,XMMWORD PTR[64+rbp]
+	movaps	xmm7,XMMWORD PTR[80+rbp]
+	movaps	xmm8,XMMWORD PTR[96+rbp]
+	movaps	xmm9,XMMWORD PTR[112+rbp]
+	movaps	xmm10,XMMWORD PTR[128+rbp]
+	movaps	xmm11,XMMWORD PTR[144+rbp]
+	movaps	xmm12,XMMWORD PTR[160+rbp]
+	movaps	xmm13,XMMWORD PTR[176+rbp]
+	movaps	xmm14,XMMWORD PTR[192+rbp]
+	movaps	xmm15,XMMWORD PTR[208+rbp]
+	lea	rsp,QWORD PTR[160+rbp]
+	mov	r15,QWORD PTR[72+rsp]
+	mov	r14,QWORD PTR[80+rsp]
+	mov	r13,QWORD PTR[88+rsp]
+	mov	r12,QWORD PTR[96+rsp]
+	mov	rbx,QWORD PTR[104+rsp]
+	mov	rax,QWORD PTR[112+rsp]
+	lea	rsp,QWORD PTR[120+rsp]
+	mov	rbp,rax
+$L$xts_dec_epilogue::
+	DB	0F3h,0C3h		;repret
+bsaes_xts_decrypt	ENDP
+
+ALIGN	64
+_bsaes_const::
+$L$M0ISR::
+	DQ	00a0e0206070b0f03h,00004080c0d010509h
+$L$ISRM0::
+	DQ	001040b0e0205080fh,00306090c00070a0dh
+$L$ISR::
+	DQ	00504070602010003h,00f0e0d0c080b0a09h
+$L$BS0::
+	DQ	05555555555555555h,05555555555555555h
+$L$BS1::
+	DQ	03333333333333333h,03333333333333333h
+$L$BS2::
+	DQ	00f0f0f0f0f0f0f0fh,00f0f0f0f0f0f0f0fh
+$L$SR::
+	DQ	00504070600030201h,00f0e0d0c0a09080bh
+$L$SRM0::
+	DQ	00304090e00050a0fh,001060b0c0207080dh
+$L$M0SR::
+	DQ	00a0e02060f03070bh,00004080c05090d01h
+$L$SWPUP::
+	DQ	00706050403020100h,00c0d0e0f0b0a0908h
+$L$SWPUPM0SR::
+	DQ	00a0d02060c03070bh,00004080f05090e01h
+$L$ADD1::
+	DQ	00000000000000000h,00000000100000000h
+$L$ADD2::
+	DQ	00000000000000000h,00000000200000000h
+$L$ADD3::
+	DQ	00000000000000000h,00000000300000000h
+$L$ADD4::
+	DQ	00000000000000000h,00000000400000000h
+$L$ADD5::
+	DQ	00000000000000000h,00000000500000000h
+$L$ADD6::
+	DQ	00000000000000000h,00000000600000000h
+$L$ADD7::
+	DQ	00000000000000000h,00000000700000000h
+$L$ADD8::
+	DQ	00000000000000000h,00000000800000000h
+$L$xts_magic::
+	DD	087h,0,1,0
+$L$masks::
+	DQ	00101010101010101h,00101010101010101h
+	DQ	00202020202020202h,00202020202020202h
+	DQ	00404040404040404h,00404040404040404h
+	DQ	00808080808080808h,00808080808080808h
+$L$M0::
+	DQ	002060a0e03070b0fh,00004080c0105090dh
+$L$63::
+	DQ	06363636363636363h,06363636363636363h
+DB	66,105,116,45,115,108,105,99,101,100,32,65,69,83,32,102
+DB	111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44
+DB	32,69,109,105,108,105,97,32,75,195,164,115,112,101,114,44
+DB	32,80,101,116,101,114,32,83,99,104,119,97,98,101,44,32
+DB	65,110,100,121,32,80,111,108,121,97,107,111,118,0
+ALIGN	64
+
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$in_prologue
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$in_prologue
+
+	mov	rax,QWORD PTR[160+r8]
+
+	lea	rsi,QWORD PTR[64+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,20
+	DD	0a548f3fch		
+	lea	rax,QWORD PTR[160+rax]
+
+	mov	rbp,QWORD PTR[112+rax]
+	mov	rbx,QWORD PTR[104+rax]
+	mov	r12,QWORD PTR[96+rax]
+	mov	r13,QWORD PTR[88+rax]
+	mov	r14,QWORD PTR[80+rax]
+	mov	r15,QWORD PTR[72+rax]
+	lea	rax,QWORD PTR[120+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$in_prologue::
+	mov	QWORD PTR[152+r8],rax
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+se_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$cbc_dec_prologue
+	DD	imagerel $L$cbc_dec_epilogue
+	DD	imagerel $L$cbc_dec_info
+
+	DD	imagerel $L$ctr_enc_prologue
+	DD	imagerel $L$ctr_enc_epilogue
+	DD	imagerel $L$ctr_enc_info
+
+	DD	imagerel $L$xts_enc_prologue
+	DD	imagerel $L$xts_enc_epilogue
+	DD	imagerel $L$xts_enc_info
+
+	DD	imagerel $L$xts_dec_prologue
+	DD	imagerel $L$xts_dec_epilogue
+	DD	imagerel $L$xts_dec_info
+
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$cbc_dec_info::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$cbc_dec_body,imagerel $L$cbc_dec_epilogue	
+$L$ctr_enc_info::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$ctr_enc_body,imagerel $L$ctr_enc_epilogue	
+$L$xts_enc_info::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$xts_enc_body,imagerel $L$xts_enc_epilogue	
+$L$xts_dec_info::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$xts_dec_body,imagerel $L$xts_dec_epilogue	
+
+.xdata	ENDS
+END
+
diff --git a/crypto/aes/bsaes-mingw64-x86_64.S b/crypto/aes/bsaes-mingw64-x86_64.S
new file mode 100644
index 0000000..f0b07cb
--- /dev/null
+++ b/crypto/aes/bsaes-mingw64-x86_64.S
@@ -0,0 +1,2725 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+.def	_bsaes_encrypt8;	.scl 3;	.type 32;	.endef
+.p2align	6
+_bsaes_encrypt8:
+	leaq	.LBS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	80(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+_bsaes_encrypt8_bitslice:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	.Lenc_sbox
+.p2align	4
+.Lenc_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+.Lenc_sbox:
+	pxor	%xmm5,%xmm4
+	pxor	%xmm0,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm1,%xmm5
+	pxor	%xmm15,%xmm4
+
+	pxor	%xmm2,%xmm5
+	pxor	%xmm6,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm3,%xmm2
+	pxor	%xmm4,%xmm3
+	pxor	%xmm0,%xmm2
+
+	pxor	%xmm6,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm6,%xmm10
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm4,%xmm8
+	movdqa	%xmm1,%xmm12
+	movdqa	%xmm5,%xmm11
+
+	pxor	%xmm3,%xmm10
+	pxor	%xmm1,%xmm9
+	pxor	%xmm2,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm3,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm15,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm2,%xmm11
+	pxor	%xmm15,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm6,%xmm12
+	movdqa	%xmm4,%xmm11
+	pxor	%xmm0,%xmm12
+	pxor	%xmm5,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm1,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm3,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm0,%xmm13
+	pand	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm14
+	pand	%xmm15,%xmm12
+	pand	%xmm4,%xmm13
+	por	%xmm5,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm5,%xmm11
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm5,%xmm9
+	pxor	%xmm4,%xmm5
+	pand	%xmm14,%xmm4
+	pand	%xmm13,%xmm5
+	pxor	%xmm4,%xmm5
+	pxor	%xmm9,%xmm4
+	pxor	%xmm15,%xmm11
+	pxor	%xmm2,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm2,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm2
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm2,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm2
+	pxor	%xmm11,%xmm5
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm2
+
+	movdqa	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm7
+	pxor	%xmm3,%xmm11
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm3,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm1,%xmm3
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm1
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm3
+	pxor	%xmm11,%xmm7
+	pxor	%xmm1,%xmm3
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm1
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm6,%xmm10
+	pxor	%xmm0,%xmm6
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm6
+	pxor	%xmm0,%xmm6
+	pxor	%xmm10,%xmm0
+	pxor	%xmm11,%xmm6
+	pxor	%xmm11,%xmm3
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm1
+	pxor	%xmm15,%xmm6
+	pxor	%xmm5,%xmm0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm15,%xmm5
+	pxor	%xmm0,%xmm15
+
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	pxor	%xmm2,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm4,%xmm3
+
+	pxor	%xmm2,%xmm5
+	decl	%r10d
+	jl	.Lenc_done
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm3,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm5,%xmm10
+	pxor	%xmm9,%xmm3
+	pshufd	$147,%xmm2,%xmm11
+	pxor	%xmm10,%xmm5
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm2
+	pshufd	$147,%xmm1,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm1
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm2,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm5,%xmm11
+	pshufd	$78,%xmm2,%xmm7
+	pxor	%xmm1,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm3,%xmm10
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm1,%xmm5
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm12,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm14,%xmm6
+	pxor	%xmm13,%xmm5
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm1
+	movdqa	%xmm8,%xmm4
+	movdqa	48(%r11),%xmm7
+	jnz	.Lenc_loop
+	movdqa	64(%r11),%xmm7
+	jmp	.Lenc_loop
+.p2align	4
+.Lenc_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm2,%xmm10
+	psrlq	$1,%xmm2
+	pxor	%xmm4,%xmm1
+	pxor	%xmm6,%xmm2
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm2
+	pxor	%xmm1,%xmm4
+	psllq	$1,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$1,%xmm2
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm3,%xmm9
+	psrlq	$1,%xmm3
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm5,%xmm3
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm15
+	pxor	%xmm3,%xmm5
+	psllq	$1,%xmm3
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm2,%xmm10
+	psrlq	$2,%xmm2
+	pxor	%xmm4,%xmm6
+	pxor	%xmm1,%xmm2
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm2
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm2,%xmm1
+	psllq	$2,%xmm2
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm2
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm5,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm5
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm5,%xmm9
+	psrlq	$4,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$4,%xmm3
+	pxor	%xmm4,%xmm5
+	pxor	%xmm1,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm4
+	psllq	$4,%xmm5
+	pxor	%xmm3,%xmm1
+	psllq	$4,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm2,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm2
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+
+
+.def	_bsaes_decrypt8;	.scl 3;	.type 32;	.endef
+.p2align	6
+_bsaes_decrypt8:
+	leaq	.LBS0(%rip),%r11
+
+	movdqa	(%rax),%xmm8
+	leaq	16(%rax),%rax
+	movdqa	-48(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+.byte	102,15,56,0,247
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm3,%xmm10
+	psrlq	$1,%xmm3
+	pxor	%xmm6,%xmm5
+	pxor	%xmm4,%xmm3
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm3
+	pxor	%xmm5,%xmm6
+	psllq	$1,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$1,%xmm3
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm1,%xmm9
+	psrlq	$1,%xmm1
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm2,%xmm1
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm1
+	pand	%xmm7,%xmm15
+	pxor	%xmm1,%xmm2
+	psllq	$1,%xmm1
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm1
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm4,%xmm9
+	psrlq	$2,%xmm4
+	movdqa	%xmm3,%xmm10
+	psrlq	$2,%xmm3
+	pxor	%xmm6,%xmm4
+	pxor	%xmm5,%xmm3
+	pand	%xmm8,%xmm4
+	pand	%xmm8,%xmm3
+	pxor	%xmm4,%xmm6
+	psllq	$2,%xmm4
+	pxor	%xmm3,%xmm5
+	psllq	$2,%xmm3
+	pxor	%xmm9,%xmm4
+	pxor	%xmm10,%xmm3
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm2,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm2
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm2,%xmm9
+	psrlq	$4,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$4,%xmm1
+	pxor	%xmm6,%xmm2
+	pxor	%xmm5,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm6
+	psllq	$4,%xmm2
+	pxor	%xmm1,%xmm5
+	psllq	$4,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm4
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm3
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	decl	%r10d
+	jmp	.Ldec_sbox
+.p2align	4
+.Ldec_loop:
+	pxor	0(%rax),%xmm15
+	pxor	16(%rax),%xmm0
+.byte	102,68,15,56,0,255
+	pxor	32(%rax),%xmm1
+.byte	102,15,56,0,199
+	pxor	48(%rax),%xmm2
+.byte	102,15,56,0,207
+	pxor	64(%rax),%xmm3
+.byte	102,15,56,0,215
+	pxor	80(%rax),%xmm4
+.byte	102,15,56,0,223
+	pxor	96(%rax),%xmm5
+.byte	102,15,56,0,231
+	pxor	112(%rax),%xmm6
+.byte	102,15,56,0,239
+	leaq	128(%rax),%rax
+.byte	102,15,56,0,247
+.Ldec_sbox:
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm6,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm3,%xmm5
+	pxor	%xmm5,%xmm6
+	pxor	%xmm6,%xmm0
+
+	pxor	%xmm0,%xmm15
+	pxor	%xmm4,%xmm1
+	pxor	%xmm15,%xmm2
+	pxor	%xmm15,%xmm4
+	pxor	%xmm2,%xmm0
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm3,%xmm12
+	movdqa	%xmm4,%xmm11
+
+	pxor	%xmm15,%xmm10
+	pxor	%xmm3,%xmm9
+	pxor	%xmm5,%xmm8
+	movdqa	%xmm10,%xmm13
+	pxor	%xmm15,%xmm12
+	movdqa	%xmm9,%xmm7
+	pxor	%xmm1,%xmm11
+	movdqa	%xmm10,%xmm14
+
+	por	%xmm8,%xmm9
+	por	%xmm11,%xmm10
+	pxor	%xmm7,%xmm14
+	pand	%xmm11,%xmm13
+	pxor	%xmm8,%xmm11
+	pand	%xmm8,%xmm7
+	pand	%xmm11,%xmm14
+	movdqa	%xmm5,%xmm11
+	pxor	%xmm1,%xmm11
+	pand	%xmm11,%xmm12
+	pxor	%xmm12,%xmm10
+	pxor	%xmm12,%xmm9
+	movdqa	%xmm2,%xmm12
+	movdqa	%xmm0,%xmm11
+	pxor	%xmm6,%xmm12
+	pxor	%xmm4,%xmm11
+	movdqa	%xmm12,%xmm8
+	pand	%xmm11,%xmm12
+	por	%xmm11,%xmm8
+	pxor	%xmm12,%xmm7
+	pxor	%xmm14,%xmm10
+	pxor	%xmm13,%xmm9
+	pxor	%xmm14,%xmm8
+	movdqa	%xmm3,%xmm11
+	pxor	%xmm13,%xmm7
+	movdqa	%xmm15,%xmm12
+	pxor	%xmm13,%xmm8
+	movdqa	%xmm6,%xmm13
+	pand	%xmm5,%xmm11
+	movdqa	%xmm2,%xmm14
+	pand	%xmm1,%xmm12
+	pand	%xmm0,%xmm13
+	por	%xmm4,%xmm14
+	pxor	%xmm11,%xmm10
+	pxor	%xmm12,%xmm9
+	pxor	%xmm13,%xmm8
+	pxor	%xmm14,%xmm7
+
+
+
+
+
+	movdqa	%xmm10,%xmm11
+	pand	%xmm8,%xmm10
+	pxor	%xmm9,%xmm11
+
+	movdqa	%xmm7,%xmm13
+	movdqa	%xmm11,%xmm14
+	pxor	%xmm10,%xmm13
+	pand	%xmm13,%xmm14
+
+	movdqa	%xmm8,%xmm12
+	pxor	%xmm9,%xmm14
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm9,%xmm10
+
+	pand	%xmm10,%xmm12
+
+	movdqa	%xmm13,%xmm9
+	pxor	%xmm7,%xmm12
+
+	pxor	%xmm12,%xmm9
+	pxor	%xmm12,%xmm8
+
+	pand	%xmm7,%xmm9
+
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm8
+
+	pand	%xmm14,%xmm13
+
+	pxor	%xmm11,%xmm13
+	movdqa	%xmm4,%xmm11
+	movdqa	%xmm0,%xmm7
+	movdqa	%xmm14,%xmm9
+	pxor	%xmm13,%xmm9
+	pand	%xmm4,%xmm9
+	pxor	%xmm0,%xmm4
+	pand	%xmm14,%xmm0
+	pand	%xmm13,%xmm4
+	pxor	%xmm0,%xmm4
+	pxor	%xmm9,%xmm0
+	pxor	%xmm1,%xmm11
+	pxor	%xmm5,%xmm7
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm1,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm5,%xmm1
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm5
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm1
+	pxor	%xmm11,%xmm7
+	pxor	%xmm5,%xmm1
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm5
+	pxor	%xmm11,%xmm4
+	pxor	%xmm11,%xmm1
+	pxor	%xmm7,%xmm0
+	pxor	%xmm7,%xmm5
+
+	movdqa	%xmm2,%xmm11
+	movdqa	%xmm6,%xmm7
+	pxor	%xmm15,%xmm11
+	pxor	%xmm3,%xmm7
+	movdqa	%xmm14,%xmm10
+	movdqa	%xmm12,%xmm9
+	pxor	%xmm13,%xmm10
+	pxor	%xmm8,%xmm9
+	pand	%xmm11,%xmm10
+	pand	%xmm15,%xmm9
+	pxor	%xmm7,%xmm11
+	pxor	%xmm3,%xmm15
+	pand	%xmm14,%xmm7
+	pand	%xmm12,%xmm3
+	pand	%xmm13,%xmm11
+	pand	%xmm8,%xmm15
+	pxor	%xmm11,%xmm7
+	pxor	%xmm3,%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm9,%xmm3
+	pxor	%xmm12,%xmm14
+	pxor	%xmm8,%xmm13
+	movdqa	%xmm14,%xmm10
+	pxor	%xmm13,%xmm10
+	pand	%xmm2,%xmm10
+	pxor	%xmm6,%xmm2
+	pand	%xmm14,%xmm6
+	pand	%xmm13,%xmm2
+	pxor	%xmm6,%xmm2
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm11,%xmm15
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm4,%xmm5
+
+	pxor	%xmm0,%xmm3
+	pxor	%xmm6,%xmm1
+	pxor	%xmm6,%xmm4
+	pxor	%xmm1,%xmm3
+	pxor	%xmm15,%xmm6
+	pxor	%xmm4,%xmm3
+	pxor	%xmm5,%xmm2
+	pxor	%xmm0,%xmm5
+	pxor	%xmm3,%xmm2
+
+	pxor	%xmm15,%xmm3
+	pxor	%xmm2,%xmm6
+	decl	%r10d
+	jl	.Ldec_done
+
+	pshufd	$78,%xmm15,%xmm7
+	pshufd	$78,%xmm2,%xmm13
+	pxor	%xmm15,%xmm7
+	pshufd	$78,%xmm4,%xmm14
+	pxor	%xmm2,%xmm13
+	pshufd	$78,%xmm0,%xmm8
+	pxor	%xmm4,%xmm14
+	pshufd	$78,%xmm5,%xmm9
+	pxor	%xmm0,%xmm8
+	pshufd	$78,%xmm3,%xmm10
+	pxor	%xmm5,%xmm9
+	pxor	%xmm13,%xmm15
+	pxor	%xmm13,%xmm0
+	pshufd	$78,%xmm1,%xmm11
+	pxor	%xmm3,%xmm10
+	pxor	%xmm7,%xmm5
+	pxor	%xmm8,%xmm3
+	pshufd	$78,%xmm6,%xmm12
+	pxor	%xmm1,%xmm11
+	pxor	%xmm14,%xmm0
+	pxor	%xmm9,%xmm1
+	pxor	%xmm6,%xmm12
+
+	pxor	%xmm14,%xmm5
+	pxor	%xmm13,%xmm3
+	pxor	%xmm13,%xmm1
+	pxor	%xmm10,%xmm6
+	pxor	%xmm11,%xmm2
+	pxor	%xmm14,%xmm1
+	pxor	%xmm14,%xmm6
+	pxor	%xmm12,%xmm4
+	pshufd	$147,%xmm15,%xmm7
+	pshufd	$147,%xmm0,%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$147,%xmm5,%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$147,%xmm3,%xmm10
+	pxor	%xmm9,%xmm5
+	pshufd	$147,%xmm1,%xmm11
+	pxor	%xmm10,%xmm3
+	pshufd	$147,%xmm6,%xmm12
+	pxor	%xmm11,%xmm1
+	pshufd	$147,%xmm2,%xmm13
+	pxor	%xmm12,%xmm6
+	pshufd	$147,%xmm4,%xmm14
+	pxor	%xmm13,%xmm2
+	pxor	%xmm14,%xmm4
+
+	pxor	%xmm15,%xmm8
+	pxor	%xmm4,%xmm7
+	pxor	%xmm4,%xmm8
+	pshufd	$78,%xmm15,%xmm15
+	pxor	%xmm0,%xmm9
+	pshufd	$78,%xmm0,%xmm0
+	pxor	%xmm1,%xmm12
+	pxor	%xmm7,%xmm15
+	pxor	%xmm6,%xmm13
+	pxor	%xmm8,%xmm0
+	pxor	%xmm3,%xmm11
+	pshufd	$78,%xmm1,%xmm7
+	pxor	%xmm2,%xmm14
+	pshufd	$78,%xmm6,%xmm8
+	pxor	%xmm5,%xmm10
+	pshufd	$78,%xmm3,%xmm1
+	pxor	%xmm4,%xmm10
+	pshufd	$78,%xmm4,%xmm6
+	pxor	%xmm4,%xmm11
+	pshufd	$78,%xmm2,%xmm3
+	pxor	%xmm11,%xmm7
+	pshufd	$78,%xmm5,%xmm2
+	pxor	%xmm12,%xmm8
+	pxor	%xmm1,%xmm10
+	pxor	%xmm14,%xmm6
+	pxor	%xmm3,%xmm13
+	movdqa	%xmm7,%xmm3
+	pxor	%xmm9,%xmm2
+	movdqa	%xmm13,%xmm5
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm2,%xmm1
+	movdqa	%xmm10,%xmm2
+	movdqa	-16(%r11),%xmm7
+	jnz	.Ldec_loop
+	movdqa	-32(%r11),%xmm7
+	jmp	.Ldec_loop
+.p2align	4
+.Ldec_done:
+	movdqa	0(%r11),%xmm7
+	movdqa	16(%r11),%xmm8
+	movdqa	%xmm2,%xmm9
+	psrlq	$1,%xmm2
+	movdqa	%xmm1,%xmm10
+	psrlq	$1,%xmm1
+	pxor	%xmm4,%xmm2
+	pxor	%xmm6,%xmm1
+	pand	%xmm7,%xmm2
+	pand	%xmm7,%xmm1
+	pxor	%xmm2,%xmm4
+	psllq	$1,%xmm2
+	pxor	%xmm1,%xmm6
+	psllq	$1,%xmm1
+	pxor	%xmm9,%xmm2
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm5,%xmm9
+	psrlq	$1,%xmm5
+	movdqa	%xmm15,%xmm10
+	psrlq	$1,%xmm15
+	pxor	%xmm3,%xmm5
+	pxor	%xmm0,%xmm15
+	pand	%xmm7,%xmm5
+	pand	%xmm7,%xmm15
+	pxor	%xmm5,%xmm3
+	psllq	$1,%xmm5
+	pxor	%xmm15,%xmm0
+	psllq	$1,%xmm15
+	pxor	%xmm9,%xmm5
+	pxor	%xmm10,%xmm15
+	movdqa	32(%r11),%xmm7
+	movdqa	%xmm6,%xmm9
+	psrlq	$2,%xmm6
+	movdqa	%xmm1,%xmm10
+	psrlq	$2,%xmm1
+	pxor	%xmm4,%xmm6
+	pxor	%xmm2,%xmm1
+	pand	%xmm8,%xmm6
+	pand	%xmm8,%xmm1
+	pxor	%xmm6,%xmm4
+	psllq	$2,%xmm6
+	pxor	%xmm1,%xmm2
+	psllq	$2,%xmm1
+	pxor	%xmm9,%xmm6
+	pxor	%xmm10,%xmm1
+	movdqa	%xmm0,%xmm9
+	psrlq	$2,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$2,%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm5,%xmm15
+	pand	%xmm8,%xmm0
+	pand	%xmm8,%xmm15
+	pxor	%xmm0,%xmm3
+	psllq	$2,%xmm0
+	pxor	%xmm15,%xmm5
+	psllq	$2,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	%xmm3,%xmm9
+	psrlq	$4,%xmm3
+	movdqa	%xmm5,%xmm10
+	psrlq	$4,%xmm5
+	pxor	%xmm4,%xmm3
+	pxor	%xmm2,%xmm5
+	pand	%xmm7,%xmm3
+	pand	%xmm7,%xmm5
+	pxor	%xmm3,%xmm4
+	psllq	$4,%xmm3
+	pxor	%xmm5,%xmm2
+	psllq	$4,%xmm5
+	pxor	%xmm9,%xmm3
+	pxor	%xmm10,%xmm5
+	movdqa	%xmm0,%xmm9
+	psrlq	$4,%xmm0
+	movdqa	%xmm15,%xmm10
+	psrlq	$4,%xmm15
+	pxor	%xmm6,%xmm0
+	pxor	%xmm1,%xmm15
+	pand	%xmm7,%xmm0
+	pand	%xmm7,%xmm15
+	pxor	%xmm0,%xmm6
+	psllq	$4,%xmm0
+	pxor	%xmm15,%xmm1
+	psllq	$4,%xmm15
+	pxor	%xmm9,%xmm0
+	pxor	%xmm10,%xmm15
+	movdqa	(%rax),%xmm7
+	pxor	%xmm7,%xmm5
+	pxor	%xmm7,%xmm3
+	pxor	%xmm7,%xmm1
+	pxor	%xmm7,%xmm6
+	pxor	%xmm7,%xmm2
+	pxor	%xmm7,%xmm4
+	pxor	%xmm7,%xmm15
+	pxor	%xmm7,%xmm0
+	retq
+
+.def	_bsaes_key_convert;	.scl 3;	.type 32;	.endef
+.p2align	4
+_bsaes_key_convert:
+	leaq	.Lmasks(%rip),%r11
+	movdqu	(%rcx),%xmm7
+	leaq	16(%rcx),%rcx
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	movdqa	48(%r11),%xmm3
+	movdqa	64(%r11),%xmm4
+	pcmpeqd	%xmm5,%xmm5
+
+	movdqu	(%rcx),%xmm6
+	movdqa	%xmm7,(%rax)
+	leaq	16(%rax),%rax
+	decl	%r10d
+	jmp	.Lkey_loop
+.p2align	4
+.Lkey_loop:
+.byte	102,15,56,0,244
+
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm1,%xmm9
+
+	pand	%xmm6,%xmm8
+	pand	%xmm6,%xmm9
+	movdqa	%xmm2,%xmm10
+	pcmpeqb	%xmm0,%xmm8
+	psllq	$4,%xmm0
+	movdqa	%xmm3,%xmm11
+	pcmpeqb	%xmm1,%xmm9
+	psllq	$4,%xmm1
+
+	pand	%xmm6,%xmm10
+	pand	%xmm6,%xmm11
+	movdqa	%xmm0,%xmm12
+	pcmpeqb	%xmm2,%xmm10
+	psllq	$4,%xmm2
+	movdqa	%xmm1,%xmm13
+	pcmpeqb	%xmm3,%xmm11
+	psllq	$4,%xmm3
+
+	movdqa	%xmm2,%xmm14
+	movdqa	%xmm3,%xmm15
+	pxor	%xmm5,%xmm8
+	pxor	%xmm5,%xmm9
+
+	pand	%xmm6,%xmm12
+	pand	%xmm6,%xmm13
+	movdqa	%xmm8,0(%rax)
+	pcmpeqb	%xmm0,%xmm12
+	psrlq	$4,%xmm0
+	movdqa	%xmm9,16(%rax)
+	pcmpeqb	%xmm1,%xmm13
+	psrlq	$4,%xmm1
+	leaq	16(%rcx),%rcx
+
+	pand	%xmm6,%xmm14
+	pand	%xmm6,%xmm15
+	movdqa	%xmm10,32(%rax)
+	pcmpeqb	%xmm2,%xmm14
+	psrlq	$4,%xmm2
+	movdqa	%xmm11,48(%rax)
+	pcmpeqb	%xmm3,%xmm15
+	psrlq	$4,%xmm3
+	movdqu	(%rcx),%xmm6
+
+	pxor	%xmm5,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm12,64(%rax)
+	movdqa	%xmm13,80(%rax)
+	movdqa	%xmm14,96(%rax)
+	movdqa	%xmm15,112(%rax)
+	leaq	128(%rax),%rax
+	decl	%r10d
+	jnz	.Lkey_loop
+
+	movdqa	80(%r11),%xmm7
+
+	retq
+
+
+.globl	bsaes_cbc_encrypt
+.def	bsaes_cbc_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+bsaes_cbc_encrypt:
+	movl	48(%rsp),%r11d
+	cmpl	$0,%r11d
+	jne	asm_AES_cbc_encrypt
+	cmpq	$128,%r8
+	jb	asm_AES_cbc_encrypt
+
+	movq	%rsp,%rax
+.Lcbc_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	160(%rsp),%r10
+	leaq	-160(%rsp),%rsp
+	movaps	%xmm6,64(%rsp)
+	movaps	%xmm7,80(%rsp)
+	movaps	%xmm8,96(%rsp)
+	movaps	%xmm9,112(%rsp)
+	movaps	%xmm10,128(%rsp)
+	movaps	%xmm11,144(%rsp)
+	movaps	%xmm12,160(%rsp)
+	movaps	%xmm13,176(%rsp)
+	movaps	%xmm14,192(%rsp)
+	movaps	%xmm15,208(%rsp)
+.Lcbc_dec_body:
+	movq	%rsp,%rbp
+	movl	240(%r9),%eax
+	movq	%rcx,%r12
+	movq	%rdx,%r13
+	movq	%r8,%r14
+	movq	%r9,%r15
+	movq	%r10,%rbx
+	shrq	$4,%r14
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	movdqu	(%rbx),%xmm14
+	subq	$8,%r14
+.Lcbc_dec_loop:
+	movdqu	0(%r12),%xmm15
+	movdqu	16(%r12),%xmm0
+	movdqu	32(%r12),%xmm1
+	movdqu	48(%r12),%xmm2
+	movdqu	64(%r12),%xmm3
+	movdqu	80(%r12),%xmm4
+	movq	%rsp,%rax
+	movdqu	96(%r12),%xmm5
+	movl	%edx,%r10d
+	movdqu	112(%r12),%xmm6
+	movdqa	%xmm14,32(%rbp)
+
+	call	_bsaes_decrypt8
+
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm2
+	movdqu	112(%r12),%xmm14
+	pxor	%xmm13,%xmm4
+	movdqu	%xmm15,0(%r13)
+	leaq	128(%r12),%r12
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	subq	$8,%r14
+	jnc	.Lcbc_dec_loop
+
+	addq	$8,%r14
+	jz	.Lcbc_dec_done
+
+	movdqu	0(%r12),%xmm15
+	movq	%rsp,%rax
+	movl	%edx,%r10d
+	cmpq	$2,%r14
+	jb	.Lcbc_dec_one
+	movdqu	16(%r12),%xmm0
+	je	.Lcbc_dec_two
+	movdqu	32(%r12),%xmm1
+	cmpq	$4,%r14
+	jb	.Lcbc_dec_three
+	movdqu	48(%r12),%xmm2
+	je	.Lcbc_dec_four
+	movdqu	64(%r12),%xmm3
+	cmpq	$6,%r14
+	jb	.Lcbc_dec_five
+	movdqu	80(%r12),%xmm4
+	je	.Lcbc_dec_six
+	movdqu	96(%r12),%xmm5
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm6
+	movdqu	96(%r12),%xmm14
+	pxor	%xmm12,%xmm2
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_six:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm1
+	movdqu	80(%r12),%xmm14
+	pxor	%xmm11,%xmm6
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_five:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm3
+	movdqu	64(%r12),%xmm14
+	pxor	%xmm10,%xmm1
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_four:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm5
+	movdqu	48(%r12),%xmm14
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_three:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm0
+	movdqu	32(%r12),%xmm14
+	pxor	%xmm8,%xmm5
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_two:
+	movdqa	%xmm14,32(%rbp)
+	call	_bsaes_decrypt8
+	pxor	32(%rbp),%xmm15
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm14
+	pxor	%xmm7,%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	jmp	.Lcbc_dec_done
+.p2align	4
+.Lcbc_dec_one:
+	leaq	(%r12),%rcx
+	leaq	32(%rbp),%rdx
+	leaq	(%r15),%r8
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm14
+	movdqu	%xmm14,(%r13)
+	movdqa	%xmm15,%xmm14
+
+.Lcbc_dec_done:
+	movdqu	%xmm14,(%rbx)
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lcbc_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lcbc_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movaps	64(%rbp),%xmm6
+	movaps	80(%rbp),%xmm7
+	movaps	96(%rbp),%xmm8
+	movaps	112(%rbp),%xmm9
+	movaps	128(%rbp),%xmm10
+	movaps	144(%rbp),%xmm11
+	movaps	160(%rbp),%xmm12
+	movaps	176(%rbp),%xmm13
+	movaps	192(%rbp),%xmm14
+	movaps	208(%rbp),%xmm15
+	leaq	160(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lcbc_dec_epilogue:
+	retq
+
+
+.globl	bsaes_ctr32_encrypt_blocks
+.def	bsaes_ctr32_encrypt_blocks;	.scl 2;	.type 32;	.endef
+.p2align	4
+bsaes_ctr32_encrypt_blocks:
+	movq	%rsp,%rax
+.Lctr_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	160(%rsp),%r10
+	leaq	-160(%rsp),%rsp
+	movaps	%xmm6,64(%rsp)
+	movaps	%xmm7,80(%rsp)
+	movaps	%xmm8,96(%rsp)
+	movaps	%xmm9,112(%rsp)
+	movaps	%xmm10,128(%rsp)
+	movaps	%xmm11,144(%rsp)
+	movaps	%xmm12,160(%rsp)
+	movaps	%xmm13,176(%rsp)
+	movaps	%xmm14,192(%rsp)
+	movaps	%xmm15,208(%rsp)
+.Lctr_enc_body:
+	movq	%rsp,%rbp
+	movdqu	(%r10),%xmm0
+	movl	240(%r9),%eax
+	movq	%rcx,%r12
+	movq	%rdx,%r13
+	movq	%r8,%r14
+	movq	%r9,%r15
+	movdqa	%xmm0,32(%rbp)
+	cmpq	$8,%r8
+	jb	.Lctr_enc_short
+
+	movl	%eax,%ebx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%ebx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	movdqa	(%rsp),%xmm8
+	leaq	.LADD1(%rip),%r11
+	movdqa	32(%rbp),%xmm15
+	movdqa	-32(%r11),%xmm7
+.byte	102,68,15,56,0,199
+.byte	102,68,15,56,0,255
+	movdqa	%xmm8,(%rsp)
+	jmp	.Lctr_enc_loop
+.p2align	4
+.Lctr_enc_loop:
+	movdqa	%xmm15,32(%rbp)
+	movdqa	%xmm15,%xmm0
+	movdqa	%xmm15,%xmm1
+	paddd	0(%r11),%xmm0
+	movdqa	%xmm15,%xmm2
+	paddd	16(%r11),%xmm1
+	movdqa	%xmm15,%xmm3
+	paddd	32(%r11),%xmm2
+	movdqa	%xmm15,%xmm4
+	paddd	48(%r11),%xmm3
+	movdqa	%xmm15,%xmm5
+	paddd	64(%r11),%xmm4
+	movdqa	%xmm15,%xmm6
+	paddd	80(%r11),%xmm5
+	paddd	96(%r11),%xmm6
+
+
+
+	movdqa	(%rsp),%xmm8
+	leaq	16(%rsp),%rax
+	movdqa	-16(%r11),%xmm7
+	pxor	%xmm8,%xmm15
+	pxor	%xmm8,%xmm0
+.byte	102,68,15,56,0,255
+	pxor	%xmm8,%xmm1
+.byte	102,15,56,0,199
+	pxor	%xmm8,%xmm2
+.byte	102,15,56,0,207
+	pxor	%xmm8,%xmm3
+.byte	102,15,56,0,215
+	pxor	%xmm8,%xmm4
+.byte	102,15,56,0,223
+	pxor	%xmm8,%xmm5
+.byte	102,15,56,0,231
+	pxor	%xmm8,%xmm6
+.byte	102,15,56,0,239
+	leaq	.LBS0(%rip),%r11
+.byte	102,15,56,0,247
+	movl	%ebx,%r10d
+
+	call	_bsaes_encrypt8_bitslice
+
+	subq	$8,%r14
+	jc	.Lctr_enc_loop_done
+
+	movdqu	0(%r12),%xmm7
+	movdqu	16(%r12),%xmm8
+	movdqu	32(%r12),%xmm9
+	movdqu	48(%r12),%xmm10
+	movdqu	64(%r12),%xmm11
+	movdqu	80(%r12),%xmm12
+	movdqu	96(%r12),%xmm13
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	pxor	%xmm15,%xmm7
+	movdqa	32(%rbp),%xmm15
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm7,0(%r13)
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	%xmm14,%xmm4
+	movdqu	%xmm1,96(%r13)
+	leaq	.LADD1(%rip),%r11
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+	paddd	112(%r11),%xmm15
+	jnz	.Lctr_enc_loop
+
+	jmp	.Lctr_enc_done
+.p2align	4
+.Lctr_enc_loop_done:
+	addq	$8,%r14
+	movdqu	0(%r12),%xmm7
+	pxor	%xmm7,%xmm15
+	movdqu	%xmm15,0(%r13)
+	cmpq	$2,%r14
+	jb	.Lctr_enc_done
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm8,%xmm0
+	movdqu	%xmm0,16(%r13)
+	je	.Lctr_enc_done
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm9,%xmm3
+	movdqu	%xmm3,32(%r13)
+	cmpq	$4,%r14
+	jb	.Lctr_enc_done
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm10,%xmm5
+	movdqu	%xmm5,48(%r13)
+	je	.Lctr_enc_done
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm11,%xmm2
+	movdqu	%xmm2,64(%r13)
+	cmpq	$6,%r14
+	jb	.Lctr_enc_done
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm12,%xmm6
+	movdqu	%xmm6,80(%r13)
+	je	.Lctr_enc_done
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm13,%xmm1
+	movdqu	%xmm1,96(%r13)
+	jmp	.Lctr_enc_done
+
+.p2align	4
+.Lctr_enc_short:
+	leaq	32(%rbp),%rcx
+	leaq	48(%rbp),%rdx
+	leaq	(%r15),%r8
+	call	asm_AES_encrypt
+	movdqu	(%r12),%xmm0
+	leaq	16(%r12),%r12
+	movl	44(%rbp),%eax
+	bswapl	%eax
+	pxor	48(%rbp),%xmm0
+	incl	%eax
+	movdqu	%xmm0,(%r13)
+	bswapl	%eax
+	leaq	16(%r13),%r13
+	movl	%eax,44(%rsp)
+	decq	%r14
+	jnz	.Lctr_enc_short
+
+.Lctr_enc_done:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lctr_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lctr_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movaps	64(%rbp),%xmm6
+	movaps	80(%rbp),%xmm7
+	movaps	96(%rbp),%xmm8
+	movaps	112(%rbp),%xmm9
+	movaps	128(%rbp),%xmm10
+	movaps	144(%rbp),%xmm11
+	movaps	160(%rbp),%xmm12
+	movaps	176(%rbp),%xmm13
+	movaps	192(%rbp),%xmm14
+	movaps	208(%rbp),%xmm15
+	leaq	160(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lctr_enc_epilogue:
+	retq
+
+.globl	bsaes_xts_encrypt
+.def	bsaes_xts_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+bsaes_xts_encrypt:
+	movq	%rsp,%rax
+.Lxts_enc_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	160(%rsp),%r10
+	movq	168(%rsp),%r11
+	leaq	-160(%rsp),%rsp
+	movaps	%xmm6,64(%rsp)
+	movaps	%xmm7,80(%rsp)
+	movaps	%xmm8,96(%rsp)
+	movaps	%xmm9,112(%rsp)
+	movaps	%xmm10,128(%rsp)
+	movaps	%xmm11,144(%rsp)
+	movaps	%xmm12,160(%rsp)
+	movaps	%xmm13,176(%rsp)
+	movaps	%xmm14,192(%rsp)
+	movaps	%xmm15,208(%rsp)
+.Lxts_enc_body:
+	movq	%rsp,%rbp
+	movq	%rcx,%r12
+	movq	%rdx,%r13
+	movq	%r8,%r14
+	movq	%r9,%r15
+
+	leaq	(%r11),%rcx
+	leaq	32(%rbp),%rdx
+	leaq	(%r10),%r8
+	call	asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	%xmm6,%xmm7
+	movdqa	%xmm7,(%rax)
+
+	andq	$-16,%r14
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	.Lxts_enc_short
+	jmp	.Lxts_enc_loop
+
+.p2align	4
+.Lxts_enc_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm1,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	.Lxts_enc_loop
+
+.Lxts_enc_short:
+	addq	$128,%r14
+	jz	.Lxts_enc_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	.Lxts_enc_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	.Lxts_enc_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	.Lxts_enc_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	.Lxts_enc_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	.Lxts_enc_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	.Lxts_enc_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	pxor	96(%rsp),%xmm1
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm1,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm2,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	pxor	64(%rsp),%xmm2
+	movdqu	%xmm5,48(%r13)
+	movdqu	%xmm2,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm5
+	movdqu	%xmm3,32(%r13)
+	movdqu	%xmm5,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm3
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm3,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_encrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	.Lxts_enc_done
+.p2align	4
+.Lxts_enc_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rcx
+	leaq	32(%rbp),%rdx
+	leaq	(%r15),%r8
+	call	asm_AES_encrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+.Lxts_enc_done:
+	andl	$15,%ebx
+	jz	.Lxts_enc_ret
+	movq	%r13,%rdx
+
+.Lxts_enc_steal:
+	movzbl	(%r12),%eax
+	movzbl	-16(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,-16(%rdx)
+	movb	%cl,0(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	.Lxts_enc_steal
+
+	movdqu	-16(%r13),%xmm15
+	leaq	32(%rbp),%rcx
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rdx
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%r8
+	call	asm_AES_encrypt		
+	pxor	32(%rbp),%xmm6
+	movdqu	%xmm6,-16(%r13)
+
+.Lxts_enc_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lxts_enc_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lxts_enc_bzero
+
+	leaq	(%rbp),%rsp
+	movaps	64(%rbp),%xmm6
+	movaps	80(%rbp),%xmm7
+	movaps	96(%rbp),%xmm8
+	movaps	112(%rbp),%xmm9
+	movaps	128(%rbp),%xmm10
+	movaps	144(%rbp),%xmm11
+	movaps	160(%rbp),%xmm12
+	movaps	176(%rbp),%xmm13
+	movaps	192(%rbp),%xmm14
+	movaps	208(%rbp),%xmm15
+	leaq	160(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lxts_enc_epilogue:
+	retq
+
+
+.globl	bsaes_xts_decrypt
+.def	bsaes_xts_decrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+bsaes_xts_decrypt:
+	movq	%rsp,%rax
+.Lxts_dec_prologue:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	leaq	-72(%rsp),%rsp
+	movq	160(%rsp),%r10
+	movq	168(%rsp),%r11
+	leaq	-160(%rsp),%rsp
+	movaps	%xmm6,64(%rsp)
+	movaps	%xmm7,80(%rsp)
+	movaps	%xmm8,96(%rsp)
+	movaps	%xmm9,112(%rsp)
+	movaps	%xmm10,128(%rsp)
+	movaps	%xmm11,144(%rsp)
+	movaps	%xmm12,160(%rsp)
+	movaps	%xmm13,176(%rsp)
+	movaps	%xmm14,192(%rsp)
+	movaps	%xmm15,208(%rsp)
+.Lxts_dec_body:
+	movq	%rsp,%rbp
+	movq	%rcx,%r12
+	movq	%rdx,%r13
+	movq	%r8,%r14
+	movq	%r9,%r15
+
+	leaq	(%r11),%rcx
+	leaq	32(%rbp),%rdx
+	leaq	(%r10),%r8
+	call	asm_AES_encrypt		
+
+	movl	240(%r15),%eax
+	movq	%r14,%rbx
+
+	movl	%eax,%edx
+	shlq	$7,%rax
+	subq	$96,%rax
+	subq	%rax,%rsp
+
+	movq	%rsp,%rax
+	movq	%r15,%rcx
+	movl	%edx,%r10d
+	call	_bsaes_key_convert
+	pxor	(%rsp),%xmm7
+	movdqa	%xmm6,(%rax)
+	movdqa	%xmm7,(%rsp)
+
+	xorl	%eax,%eax
+	andq	$-16,%r14
+	testl	$15,%ebx
+	setnz	%al
+	shlq	$4,%rax
+	subq	%rax,%r14
+
+	subq	$128,%rsp
+	movdqa	32(%rbp),%xmm6
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+
+	subq	$128,%r14
+	jc	.Lxts_dec_short
+	jmp	.Lxts_dec_loop
+
+.p2align	4
+.Lxts_dec_loop:
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqu	112(%r12),%xmm14
+	leaq	128(%r12),%r12
+	movdqa	%xmm6,112(%rsp)
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	pxor	%xmm14,%xmm6
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	pxor	112(%rsp),%xmm4
+	movdqu	%xmm2,96(%r13)
+	movdqu	%xmm4,112(%r13)
+	leaq	128(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+
+	subq	$128,%r14
+	jnc	.Lxts_dec_loop
+
+.Lxts_dec_short:
+	addq	$128,%r14
+	jz	.Lxts_dec_done
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm15
+	movdqa	%xmm6,0(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm0
+	movdqa	%xmm6,16(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	0(%r12),%xmm7
+	cmpq	$16,%r14
+	je	.Lxts_dec_1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm1
+	movdqa	%xmm6,32(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	16(%r12),%xmm8
+	cmpq	$32,%r14
+	je	.Lxts_dec_2
+	pxor	%xmm7,%xmm15
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm6,48(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	32(%r12),%xmm9
+	cmpq	$48,%r14
+	je	.Lxts_dec_3
+	pxor	%xmm8,%xmm0
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm3
+	movdqa	%xmm6,64(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	48(%r12),%xmm10
+	cmpq	$64,%r14
+	je	.Lxts_dec_4
+	pxor	%xmm9,%xmm1
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm4
+	movdqa	%xmm6,80(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	64(%r12),%xmm11
+	cmpq	$80,%r14
+	je	.Lxts_dec_5
+	pxor	%xmm10,%xmm2
+	pshufd	$19,%xmm14,%xmm13
+	pxor	%xmm14,%xmm14
+	movdqa	%xmm6,%xmm5
+	movdqa	%xmm6,96(%rsp)
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	pcmpgtd	%xmm6,%xmm14
+	pxor	%xmm13,%xmm6
+	movdqu	80(%r12),%xmm12
+	cmpq	$96,%r14
+	je	.Lxts_dec_6
+	pxor	%xmm11,%xmm3
+	movdqu	96(%r12),%xmm13
+	pxor	%xmm12,%xmm4
+	movdqa	%xmm6,112(%rsp)
+	leaq	112(%r12),%r12
+	pxor	%xmm13,%xmm5
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	pxor	96(%rsp),%xmm2
+	movdqu	%xmm6,80(%r13)
+	movdqu	%xmm2,96(%r13)
+	leaq	112(%r13),%r13
+
+	movdqa	112(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_6:
+	pxor	%xmm11,%xmm3
+	leaq	96(%r12),%r12
+	pxor	%xmm12,%xmm4
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	pxor	80(%rsp),%xmm6
+	movdqu	%xmm1,64(%r13)
+	movdqu	%xmm6,80(%r13)
+	leaq	96(%r13),%r13
+
+	movdqa	96(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_5:
+	pxor	%xmm10,%xmm2
+	leaq	80(%r12),%r12
+	pxor	%xmm11,%xmm3
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	pxor	64(%rsp),%xmm1
+	movdqu	%xmm3,48(%r13)
+	movdqu	%xmm1,64(%r13)
+	leaq	80(%r13),%r13
+
+	movdqa	80(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_4:
+	pxor	%xmm9,%xmm1
+	leaq	64(%r12),%r12
+	pxor	%xmm10,%xmm2
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	pxor	48(%rsp),%xmm3
+	movdqu	%xmm5,32(%r13)
+	movdqu	%xmm3,48(%r13)
+	leaq	64(%r13),%r13
+
+	movdqa	64(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_3:
+	pxor	%xmm8,%xmm0
+	leaq	48(%r12),%r12
+	pxor	%xmm9,%xmm1
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	pxor	32(%rsp),%xmm5
+	movdqu	%xmm0,16(%r13)
+	movdqu	%xmm5,32(%r13)
+	leaq	48(%r13),%r13
+
+	movdqa	48(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_2:
+	pxor	%xmm7,%xmm15
+	leaq	32(%r12),%r12
+	pxor	%xmm8,%xmm0
+	leaq	128(%rsp),%rax
+	movl	%edx,%r10d
+
+	call	_bsaes_decrypt8
+
+	pxor	0(%rsp),%xmm15
+	pxor	16(%rsp),%xmm0
+	movdqu	%xmm15,0(%r13)
+	movdqu	%xmm0,16(%r13)
+	leaq	32(%r13),%r13
+
+	movdqa	32(%rsp),%xmm6
+	jmp	.Lxts_dec_done
+.p2align	4
+.Lxts_dec_1:
+	pxor	%xmm15,%xmm7
+	leaq	16(%r12),%r12
+	movdqa	%xmm7,32(%rbp)
+	leaq	32(%rbp),%rcx
+	leaq	32(%rbp),%rdx
+	leaq	(%r15),%r8
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm15
+
+
+
+
+
+	movdqu	%xmm15,0(%r13)
+	leaq	16(%r13),%r13
+
+	movdqa	16(%rsp),%xmm6
+
+.Lxts_dec_done:
+	andl	$15,%ebx
+	jz	.Lxts_dec_ret
+
+	pxor	%xmm14,%xmm14
+	movdqa	.Lxts_magic(%rip),%xmm12
+	pcmpgtd	%xmm6,%xmm14
+	pshufd	$19,%xmm14,%xmm13
+	movdqa	%xmm6,%xmm5
+	paddq	%xmm6,%xmm6
+	pand	%xmm12,%xmm13
+	movdqu	(%r12),%xmm15
+	pxor	%xmm13,%xmm6
+
+	leaq	32(%rbp),%rcx
+	pxor	%xmm6,%xmm15
+	leaq	32(%rbp),%rdx
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%r8
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm6
+	movq	%r13,%rdx
+	movdqu	%xmm6,(%r13)
+
+.Lxts_dec_steal:
+	movzbl	16(%r12),%eax
+	movzbl	(%rdx),%ecx
+	leaq	1(%r12),%r12
+	movb	%al,(%rdx)
+	movb	%cl,16(%rdx)
+	leaq	1(%rdx),%rdx
+	subl	$1,%ebx
+	jnz	.Lxts_dec_steal
+
+	movdqu	(%r13),%xmm15
+	leaq	32(%rbp),%rcx
+	pxor	%xmm5,%xmm15
+	leaq	32(%rbp),%rdx
+	movdqa	%xmm15,32(%rbp)
+	leaq	(%r15),%r8
+	call	asm_AES_decrypt		
+	pxor	32(%rbp),%xmm5
+	movdqu	%xmm5,(%r13)
+
+.Lxts_dec_ret:
+	leaq	(%rsp),%rax
+	pxor	%xmm0,%xmm0
+.Lxts_dec_bzero:
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm0,16(%rax)
+	leaq	32(%rax),%rax
+	cmpq	%rax,%rbp
+	ja	.Lxts_dec_bzero
+
+	leaq	(%rbp),%rsp
+	movaps	64(%rbp),%xmm6
+	movaps	80(%rbp),%xmm7
+	movaps	96(%rbp),%xmm8
+	movaps	112(%rbp),%xmm9
+	movaps	128(%rbp),%xmm10
+	movaps	144(%rbp),%xmm11
+	movaps	160(%rbp),%xmm12
+	movaps	176(%rbp),%xmm13
+	movaps	192(%rbp),%xmm14
+	movaps	208(%rbp),%xmm15
+	leaq	160(%rbp),%rsp
+	movq	72(%rsp),%r15
+	movq	80(%rsp),%r14
+	movq	88(%rsp),%r13
+	movq	96(%rsp),%r12
+	movq	104(%rsp),%rbx
+	movq	112(%rsp),%rax
+	leaq	120(%rsp),%rsp
+	movq	%rax,%rbp
+.Lxts_dec_epilogue:
+	retq
+
+
+.p2align	6
+_bsaes_const:
+.LM0ISR:
+.quad	0x0a0e0206070b0f03, 0x0004080c0d010509
+.LISRM0:
+.quad	0x01040b0e0205080f, 0x0306090c00070a0d
+.LISR:
+.quad	0x0504070602010003, 0x0f0e0d0c080b0a09
+.LBS0:
+.quad	0x5555555555555555, 0x5555555555555555
+.LBS1:
+.quad	0x3333333333333333, 0x3333333333333333
+.LBS2:
+.quad	0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+.LSR:
+.quad	0x0504070600030201, 0x0f0e0d0c0a09080b
+.LSRM0:
+.quad	0x0304090e00050a0f, 0x01060b0c0207080d
+.LM0SR:
+.quad	0x0a0e02060f03070b, 0x0004080c05090d01
+.LSWPUP:
+.quad	0x0706050403020100, 0x0c0d0e0f0b0a0908
+.LSWPUPM0SR:
+.quad	0x0a0d02060c03070b, 0x0004080f05090e01
+.LADD1:
+.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
+.byte	66,105,116,45,115,108,105,99,101,100,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,69,109,105,108,105,97,32,75,195,164,115,112,101,114,44,32,80,101,116,101,114,32,83,99,104,119,97,98,101,44,32,65,110,100,121,32,80,111,108,121,97,107,111,118,0
+.p2align	6
+
+
+.def	se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_prologue
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_prologue
+
+	movq	160(%r8),%rax
+
+	leaq	64(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$20,%ecx
+.long	0xa548f3fc		
+	leaq	160(%rax),%rax
+
+	movq	112(%rax),%rbp
+	movq	104(%rax),%rbx
+	movq	96(%rax),%r12
+	movq	88(%rax),%r13
+	movq	80(%rax),%r14
+	movq	72(%rax),%r15
+	leaq	120(%rax),%rax
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lin_prologue:
+	movq	%rax,152(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.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
+.p2align	3
+.Lcbc_dec_info:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lcbc_dec_body,.Lcbc_dec_epilogue	
+.Lctr_enc_info:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lctr_enc_body,.Lctr_enc_epilogue	
+.Lxts_enc_info:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lxts_enc_body,.Lxts_enc_epilogue	
+.Lxts_dec_info:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lxts_dec_body,.Lxts_dec_epilogue	
diff --git a/crypto/aes/vpaes-elf-x86_64.S b/crypto/aes/vpaes-elf-x86_64.S
new file mode 100644
index 0000000..67ff646
--- /dev/null
+++ b/crypto/aes/vpaes-elf-x86_64.S
@@ -0,0 +1,846 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type	_vpaes_encrypt_core,@function
+.align	16
+_vpaes_encrypt_core:
+	endbr64
+	movq	%rdx,%r9
+	movq	$16,%r11
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	.Lk_ipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movdqu	(%r9),%xmm5
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	.Lk_ipt+16(%rip),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm5,%xmm2
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	leaq	.Lk_mc_backward(%rip),%r10
+	jmp	.Lenc_entry
+
+.align	16
+.Lenc_loop:
+
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm15,%xmm5
+.byte	102,15,56,0,234
+	movdqa	-64(%r11,%r10,1),%xmm1
+	movdqa	%xmm14,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm5,%xmm2
+	movdqa	(%r11,%r10,1),%xmm4
+	movdqa	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	addq	$16,%r9
+	pxor	%xmm2,%xmm0
+.byte	102,15,56,0,220
+	addq	$16,%r11
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm3,%xmm0
+	subq	$1,%rax
+
+.Lenc_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm5
+.byte	102,15,56,0,232
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+	movdqu	(%r9),%xmm5
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	jnz	.Lenc_loop
+
+
+	movdqa	-96(%r10),%xmm4
+	movdqa	-80(%r10),%xmm0
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+.byte	102,15,56,0,195
+	movdqa	64(%r11,%r10,1),%xmm1
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,193
+	retq
+.size	_vpaes_encrypt_core,.-_vpaes_encrypt_core
+
+
+
+
+
+
+.type	_vpaes_decrypt_core,@function
+.align	16
+_vpaes_decrypt_core:
+	endbr64
+	movq	%rdx,%r9
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	.Lk_dipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movq	%rax,%r11
+	psrld	$4,%xmm1
+	movdqu	(%r9),%xmm5
+	shlq	$4,%r11
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	.Lk_dipt+16(%rip),%xmm0
+	xorq	$48,%r11
+	leaq	.Lk_dsbd(%rip),%r10
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm5,%xmm2
+	movdqa	.Lk_mc_forward+48(%rip),%xmm5
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	addq	%r10,%r11
+	jmp	.Ldec_entry
+
+.align	16
+.Ldec_loop:
+
+
+
+	movdqa	-32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	-16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	addq	$16,%r9
+
+.byte	102,15,56,0,197
+	movdqa	0(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	subq	$1,%rax
+
+.byte	102,15,56,0,197
+	movdqa	32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	48(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,56,0,197
+	movdqa	64(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	80(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,58,15,237,12
+
+.Ldec_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqu	(%r9),%xmm0
+	jnz	.Ldec_loop
+
+
+	movdqa	96(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	112(%r10),%xmm0
+	movdqa	-352(%r11),%xmm2
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,194
+	retq
+.size	_vpaes_decrypt_core,.-_vpaes_decrypt_core
+
+
+
+
+
+
+.type	_vpaes_schedule_core,@function
+.align	16
+_vpaes_schedule_core:
+	endbr64
+
+
+
+
+
+	call	_vpaes_preheat		
+	movdqa	.Lk_rcon(%rip),%xmm8
+	movdqu	(%rdi),%xmm0
+
+
+	movdqa	%xmm0,%xmm3
+	leaq	.Lk_ipt(%rip),%r11
+	call	_vpaes_schedule_transform
+	movdqa	%xmm0,%xmm7
+
+	leaq	.Lk_sr(%rip),%r10
+	testq	%rcx,%rcx
+	jnz	.Lschedule_am_decrypting
+
+
+	movdqu	%xmm0,(%rdx)
+	jmp	.Lschedule_go
+
+.Lschedule_am_decrypting:
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	movdqu	%xmm3,(%rdx)
+	xorq	$48,%r8
+
+.Lschedule_go:
+	cmpl	$192,%esi
+	ja	.Lschedule_256
+	je	.Lschedule_192
+
+
+
+
+
+
+
+
+
+
+.Lschedule_128:
+	movl	$10,%esi
+
+.Loop_schedule_128:
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	jmp	.Loop_schedule_128
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.align	16
+.Lschedule_192:
+	movdqu	8(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movdqa	%xmm0,%xmm6
+	pxor	%xmm4,%xmm4
+	movhlps	%xmm4,%xmm6
+	movl	$4,%esi
+
+.Loop_schedule_192:
+	call	_vpaes_schedule_round
+.byte	102,15,58,15,198,8
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	jmp	.Loop_schedule_192
+
+
+
+
+
+
+
+
+
+
+
+.align	16
+.Lschedule_256:
+	movdqu	16(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movl	$7,%esi
+
+.Loop_schedule_256:
+	call	_vpaes_schedule_mangle	
+	movdqa	%xmm0,%xmm6
+
+
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+
+
+	pshufd	$255,%xmm0,%xmm0
+	movdqa	%xmm7,%xmm5
+	movdqa	%xmm6,%xmm7
+	call	_vpaes_schedule_low_round
+	movdqa	%xmm5,%xmm7
+
+	jmp	.Loop_schedule_256
+
+
+
+
+
+
+
+
+
+
+
+
+.align	16
+.Lschedule_mangle_last:
+
+	leaq	.Lk_deskew(%rip),%r11
+	testq	%rcx,%rcx
+	jnz	.Lschedule_mangle_last_dec
+
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,193
+	leaq	.Lk_opt(%rip),%r11
+	addq	$32,%rdx
+
+.Lschedule_mangle_last_dec:
+	addq	$-16,%rdx
+	pxor	.Lk_s63(%rip),%xmm0
+	call	_vpaes_schedule_transform 
+	movdqu	%xmm0,(%rdx)
+
+
+	pxor	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	retq
+.size	_vpaes_schedule_core,.-_vpaes_schedule_core
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type	_vpaes_schedule_192_smear,@function
+.align	16
+_vpaes_schedule_192_smear:
+	endbr64
+	pshufd	$128,%xmm6,%xmm0
+	pxor	%xmm0,%xmm6
+	pshufd	$254,%xmm7,%xmm0
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm6,%xmm0
+	pxor	%xmm1,%xmm1
+	movhlps	%xmm1,%xmm6
+	retq
+.size	_vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type	_vpaes_schedule_round,@function
+.align	16
+_vpaes_schedule_round:
+	endbr64
+
+	pxor	%xmm1,%xmm1
+.byte	102,65,15,58,15,200,15
+.byte	102,69,15,58,15,192,15
+	pxor	%xmm1,%xmm7
+
+
+	pshufd	$255,%xmm0,%xmm0
+.byte	102,15,58,15,192,1
+
+
+
+
+_vpaes_schedule_low_round:
+
+	movdqa	%xmm7,%xmm1
+	pslldq	$4,%xmm7
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm7,%xmm1
+	pslldq	$8,%xmm7
+	pxor	%xmm1,%xmm7
+	pxor	.Lk_s63(%rip),%xmm7
+
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+
+	pxor	%xmm7,%xmm0
+	movdqa	%xmm0,%xmm7
+	retq
+.size	_vpaes_schedule_round,.-_vpaes_schedule_round
+
+
+
+
+
+
+
+
+
+
+.type	_vpaes_schedule_transform,@function
+.align	16
+_vpaes_schedule_transform:
+	endbr64
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	(%r11),%xmm2
+.byte	102,15,56,0,208
+	movdqa	16(%r11),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm2,%xmm0
+	retq
+.size	_vpaes_schedule_transform,.-_vpaes_schedule_transform
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.type	_vpaes_schedule_mangle,@function
+.align	16
+_vpaes_schedule_mangle:
+	endbr64
+	movdqa	%xmm0,%xmm4
+	movdqa	.Lk_mc_forward(%rip),%xmm5
+	testq	%rcx,%rcx
+	jnz	.Lschedule_mangle_dec
+
+
+	addq	$16,%rdx
+	pxor	.Lk_s63(%rip),%xmm4
+.byte	102,15,56,0,229
+	movdqa	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+
+	jmp	.Lschedule_mangle_both
+.align	16
+.Lschedule_mangle_dec:
+
+	leaq	.Lk_dksd(%rip),%r11
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm4,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm4
+
+	movdqa	0(%r11),%xmm2
+.byte	102,15,56,0,212
+	movdqa	16(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	32(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	48(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	64(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	80(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	96(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	112(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+
+	addq	$-16,%rdx
+
+.Lschedule_mangle_both:
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	addq	$-16,%r8
+	andq	$48,%r8
+	movdqu	%xmm3,(%rdx)
+	retq
+.size	_vpaes_schedule_mangle,.-_vpaes_schedule_mangle
+
+
+
+
+.globl	vpaes_set_encrypt_key
+.type	vpaes_set_encrypt_key,@function
+.align	16
+vpaes_set_encrypt_key:
+	endbr64
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+
+	movl	$0,%ecx
+	movl	$48,%r8d
+	call	_vpaes_schedule_core
+	xorl	%eax,%eax
+	retq
+.size	vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
+
+.globl	vpaes_set_decrypt_key
+.type	vpaes_set_decrypt_key,@function
+.align	16
+vpaes_set_decrypt_key:
+	endbr64
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+	shll	$4,%eax
+	leaq	16(%rdx,%rax,1),%rdx
+
+	movl	$1,%ecx
+	movl	%esi,%r8d
+	shrl	$1,%r8d
+	andl	$32,%r8d
+	xorl	$32,%r8d
+	call	_vpaes_schedule_core
+	xorl	%eax,%eax
+	retq
+.size	vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
+
+.globl	vpaes_encrypt
+.type	vpaes_encrypt,@function
+.align	16
+vpaes_encrypt:
+	endbr64
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_encrypt_core
+	movdqu	%xmm0,(%rsi)
+	retq
+.size	vpaes_encrypt,.-vpaes_encrypt
+
+.globl	vpaes_decrypt
+.type	vpaes_decrypt,@function
+.align	16
+vpaes_decrypt:
+	endbr64
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_decrypt_core
+	movdqu	%xmm0,(%rsi)
+	retq
+.size	vpaes_decrypt,.-vpaes_decrypt
+.globl	vpaes_cbc_encrypt
+.type	vpaes_cbc_encrypt,@function
+.align	16
+vpaes_cbc_encrypt:
+	endbr64
+	xchgq	%rcx,%rdx
+	subq	$16,%rcx
+	jc	.Lcbc_abort
+	movdqu	(%r8),%xmm6
+	subq	%rdi,%rsi
+	call	_vpaes_preheat
+	cmpl	$0,%r9d
+	je	.Lcbc_dec_loop
+	jmp	.Lcbc_enc_loop
+.align	16
+.Lcbc_enc_loop:
+	movdqu	(%rdi),%xmm0
+	pxor	%xmm6,%xmm0
+	call	_vpaes_encrypt_core
+	movdqa	%xmm0,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	.Lcbc_enc_loop
+	jmp	.Lcbc_done
+.align	16
+.Lcbc_dec_loop:
+	movdqu	(%rdi),%xmm0
+	movdqa	%xmm0,%xmm7
+	call	_vpaes_decrypt_core
+	pxor	%xmm6,%xmm0
+	movdqa	%xmm7,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	.Lcbc_dec_loop
+.Lcbc_done:
+	movdqu	%xmm6,(%r8)
+.Lcbc_abort:
+	retq
+.size	vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
+
+
+
+
+
+
+.type	_vpaes_preheat,@function
+.align	16
+_vpaes_preheat:
+	endbr64
+	leaq	.Lk_s0F(%rip),%r10
+	movdqa	-32(%r10),%xmm10
+	movdqa	-16(%r10),%xmm11
+	movdqa	0(%r10),%xmm9
+	movdqa	48(%r10),%xmm13
+	movdqa	64(%r10),%xmm12
+	movdqa	80(%r10),%xmm15
+	movdqa	96(%r10),%xmm14
+	retq
+.size	_vpaes_preheat,.-_vpaes_preheat
+
+
+
+
+
+.section	.rodata
+.type	_vpaes_consts,@object
+.align	64
+_vpaes_consts:
+.Lk_inv:
+.quad	0x0E05060F0D080180, 0x040703090A0B0C02
+.quad	0x01040A060F0B0780, 0x030D0E0C02050809
+
+.Lk_s0F:
+.quad	0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+
+.Lk_ipt:
+.quad	0xC2B2E8985A2A7000, 0xCABAE09052227808
+.quad	0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
+
+.Lk_sb1:
+.quad	0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
+.quad	0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
+.Lk_sb2:
+.quad	0xE27A93C60B712400, 0x5EB7E955BC982FCD
+.quad	0x69EB88400AE12900, 0xC2A163C8AB82234A
+.Lk_sbo:
+.quad	0xD0D26D176FBDC700, 0x15AABF7AC502A878
+.quad	0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
+
+.Lk_mc_forward:
+.quad	0x0407060500030201, 0x0C0F0E0D080B0A09
+.quad	0x080B0A0904070605, 0x000302010C0F0E0D
+.quad	0x0C0F0E0D080B0A09, 0x0407060500030201
+.quad	0x000302010C0F0E0D, 0x080B0A0904070605
+
+.Lk_mc_backward:
+.quad	0x0605040702010003, 0x0E0D0C0F0A09080B
+.quad	0x020100030E0D0C0F, 0x0A09080B06050407
+.quad	0x0E0D0C0F0A09080B, 0x0605040702010003
+.quad	0x0A09080B06050407, 0x020100030E0D0C0F
+
+.Lk_sr:
+.quad	0x0706050403020100, 0x0F0E0D0C0B0A0908
+.quad	0x030E09040F0A0500, 0x0B06010C07020D08
+.quad	0x0F060D040B020900, 0x070E050C030A0108
+.quad	0x0B0E0104070A0D00, 0x0306090C0F020508
+
+.Lk_rcon:
+.quad	0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
+
+.Lk_s63:
+.quad	0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
+
+.Lk_opt:
+.quad	0xFF9F4929D6B66000, 0xF7974121DEBE6808
+.quad	0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
+
+.Lk_deskew:
+.quad	0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
+.quad	0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
+
+
+
+
+
+.Lk_dksd:
+.quad	0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
+.quad	0x41C277F4B5368300, 0x5FDC69EAAB289D1E
+.Lk_dksb:
+.quad	0x9A4FCA1F8550D500, 0x03D653861CC94C99
+.quad	0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
+.Lk_dkse:
+.quad	0xD5031CCA1FC9D600, 0x53859A4C994F5086
+.quad	0xA23196054FDC7BE8, 0xCD5EF96A20B31487
+.Lk_dks9:
+.quad	0xB6116FC87ED9A700, 0x4AED933482255BFC
+.quad	0x4576516227143300, 0x8BB89FACE9DAFDCE
+
+
+
+
+
+.Lk_dipt:
+.quad	0x0F505B040B545F00, 0x154A411E114E451A
+.quad	0x86E383E660056500, 0x12771772F491F194
+
+.Lk_dsb9:
+.quad	0x851C03539A86D600, 0xCAD51F504F994CC9
+.quad	0xC03B1789ECD74900, 0x725E2C9EB2FBA565
+.Lk_dsbd:
+.quad	0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
+.quad	0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
+.Lk_dsbb:
+.quad	0xD022649296B44200, 0x602646F6B0F2D404
+.quad	0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
+.Lk_dsbe:
+.quad	0x46F2929626D4D000, 0x2242600464B4F6B0
+.quad	0x0C55A6CDFFAAC100, 0x9467F36B98593E32
+.Lk_dsbo:
+.quad	0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
+.quad	0x12D7560F93441D00, 0xCA4B8159D8C58E9C
+.align	64
+.size	_vpaes_consts,.-_vpaes_consts
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/aes/vpaes-macosx-x86_64.S b/crypto/aes/vpaes-macosx-x86_64.S
new file mode 100644
index 0000000..0a892a9
--- /dev/null
+++ b/crypto/aes/vpaes-macosx-x86_64.S
@@ -0,0 +1,829 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_encrypt_core:
+	movq	%rdx,%r9
+	movq	$16,%r11
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	L$k_ipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movdqu	(%r9),%xmm5
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	L$k_ipt+16(%rip),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm5,%xmm2
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	leaq	L$k_mc_backward(%rip),%r10
+	jmp	L$enc_entry
+
+.p2align	4
+L$enc_loop:
+
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm15,%xmm5
+.byte	102,15,56,0,234
+	movdqa	-64(%r11,%r10,1),%xmm1
+	movdqa	%xmm14,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm5,%xmm2
+	movdqa	(%r11,%r10,1),%xmm4
+	movdqa	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	addq	$16,%r9
+	pxor	%xmm2,%xmm0
+.byte	102,15,56,0,220
+	addq	$16,%r11
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm3,%xmm0
+	subq	$1,%rax
+
+L$enc_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm5
+.byte	102,15,56,0,232
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+	movdqu	(%r9),%xmm5
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	jnz	L$enc_loop
+
+
+	movdqa	-96(%r10),%xmm4
+	movdqa	-80(%r10),%xmm0
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+.byte	102,15,56,0,195
+	movdqa	64(%r11,%r10,1),%xmm1
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,193
+	retq
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_decrypt_core:
+	movq	%rdx,%r9
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	L$k_dipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movq	%rax,%r11
+	psrld	$4,%xmm1
+	movdqu	(%r9),%xmm5
+	shlq	$4,%r11
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	L$k_dipt+16(%rip),%xmm0
+	xorq	$48,%r11
+	leaq	L$k_dsbd(%rip),%r10
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm5,%xmm2
+	movdqa	L$k_mc_forward+48(%rip),%xmm5
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	addq	%r10,%r11
+	jmp	L$dec_entry
+
+.p2align	4
+L$dec_loop:
+
+
+
+	movdqa	-32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	-16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	addq	$16,%r9
+
+.byte	102,15,56,0,197
+	movdqa	0(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	subq	$1,%rax
+
+.byte	102,15,56,0,197
+	movdqa	32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	48(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,56,0,197
+	movdqa	64(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	80(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,58,15,237,12
+
+L$dec_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqu	(%r9),%xmm0
+	jnz	L$dec_loop
+
+
+	movdqa	96(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	112(%r10),%xmm0
+	movdqa	-352(%r11),%xmm2
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,194
+	retq
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_schedule_core:
+
+
+
+
+
+	call	_vpaes_preheat		
+	movdqa	L$k_rcon(%rip),%xmm8
+	movdqu	(%rdi),%xmm0
+
+
+	movdqa	%xmm0,%xmm3
+	leaq	L$k_ipt(%rip),%r11
+	call	_vpaes_schedule_transform
+	movdqa	%xmm0,%xmm7
+
+	leaq	L$k_sr(%rip),%r10
+	testq	%rcx,%rcx
+	jnz	L$schedule_am_decrypting
+
+
+	movdqu	%xmm0,(%rdx)
+	jmp	L$schedule_go
+
+L$schedule_am_decrypting:
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	movdqu	%xmm3,(%rdx)
+	xorq	$48,%r8
+
+L$schedule_go:
+	cmpl	$192,%esi
+	ja	L$schedule_256
+	je	L$schedule_192
+
+
+
+
+
+
+
+
+
+
+L$schedule_128:
+	movl	$10,%esi
+
+L$oop_schedule_128:
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	jmp	L$oop_schedule_128
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+L$schedule_192:
+	movdqu	8(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movdqa	%xmm0,%xmm6
+	pxor	%xmm4,%xmm4
+	movhlps	%xmm4,%xmm6
+	movl	$4,%esi
+
+L$oop_schedule_192:
+	call	_vpaes_schedule_round
+.byte	102,15,58,15,198,8
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	jmp	L$oop_schedule_192
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+L$schedule_256:
+	movdqu	16(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movl	$7,%esi
+
+L$oop_schedule_256:
+	call	_vpaes_schedule_mangle	
+	movdqa	%xmm0,%xmm6
+
+
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+
+
+	pshufd	$255,%xmm0,%xmm0
+	movdqa	%xmm7,%xmm5
+	movdqa	%xmm6,%xmm7
+	call	_vpaes_schedule_low_round
+	movdqa	%xmm5,%xmm7
+
+	jmp	L$oop_schedule_256
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+L$schedule_mangle_last:
+
+	leaq	L$k_deskew(%rip),%r11
+	testq	%rcx,%rcx
+	jnz	L$schedule_mangle_last_dec
+
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,193
+	leaq	L$k_opt(%rip),%r11
+	addq	$32,%rdx
+
+L$schedule_mangle_last_dec:
+	addq	$-16,%rdx
+	pxor	L$k_s63(%rip),%xmm0
+	call	_vpaes_schedule_transform 
+	movdqu	%xmm0,(%rdx)
+
+
+	pxor	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_schedule_192_smear:
+	pshufd	$128,%xmm6,%xmm0
+	pxor	%xmm0,%xmm6
+	pshufd	$254,%xmm7,%xmm0
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm6,%xmm0
+	pxor	%xmm1,%xmm1
+	movhlps	%xmm1,%xmm6
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_schedule_round:
+
+	pxor	%xmm1,%xmm1
+.byte	102,65,15,58,15,200,15
+.byte	102,69,15,58,15,192,15
+	pxor	%xmm1,%xmm7
+
+
+	pshufd	$255,%xmm0,%xmm0
+.byte	102,15,58,15,192,1
+
+
+
+
+_vpaes_schedule_low_round:
+
+	movdqa	%xmm7,%xmm1
+	pslldq	$4,%xmm7
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm7,%xmm1
+	pslldq	$8,%xmm7
+	pxor	%xmm1,%xmm7
+	pxor	L$k_s63(%rip),%xmm7
+
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+
+	pxor	%xmm7,%xmm0
+	movdqa	%xmm0,%xmm7
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_schedule_transform:
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	(%r11),%xmm2
+.byte	102,15,56,0,208
+	movdqa	16(%r11),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm2,%xmm0
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_schedule_mangle:
+	movdqa	%xmm0,%xmm4
+	movdqa	L$k_mc_forward(%rip),%xmm5
+	testq	%rcx,%rcx
+	jnz	L$schedule_mangle_dec
+
+
+	addq	$16,%rdx
+	pxor	L$k_s63(%rip),%xmm4
+.byte	102,15,56,0,229
+	movdqa	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+
+	jmp	L$schedule_mangle_both
+.p2align	4
+L$schedule_mangle_dec:
+
+	leaq	L$k_dksd(%rip),%r11
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm4,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm4
+
+	movdqa	0(%r11),%xmm2
+.byte	102,15,56,0,212
+	movdqa	16(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	32(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	48(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	64(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	80(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	96(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	112(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+
+	addq	$-16,%rdx
+
+L$schedule_mangle_both:
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	addq	$-16,%r8
+	andq	$48,%r8
+	movdqu	%xmm3,(%rdx)
+	retq
+
+
+
+
+
+.globl	_vpaes_set_encrypt_key
+
+.p2align	4
+_vpaes_set_encrypt_key:
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+
+	movl	$0,%ecx
+	movl	$48,%r8d
+	call	_vpaes_schedule_core
+	xorl	%eax,%eax
+	retq
+
+
+.globl	_vpaes_set_decrypt_key
+
+.p2align	4
+_vpaes_set_decrypt_key:
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+	shll	$4,%eax
+	leaq	16(%rdx,%rax,1),%rdx
+
+	movl	$1,%ecx
+	movl	%esi,%r8d
+	shrl	$1,%r8d
+	andl	$32,%r8d
+	xorl	$32,%r8d
+	call	_vpaes_schedule_core
+	xorl	%eax,%eax
+	retq
+
+
+.globl	_vpaes_encrypt
+
+.p2align	4
+_vpaes_encrypt:
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_encrypt_core
+	movdqu	%xmm0,(%rsi)
+	retq
+
+
+.globl	_vpaes_decrypt
+
+.p2align	4
+_vpaes_decrypt:
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_decrypt_core
+	movdqu	%xmm0,(%rsi)
+	retq
+
+.globl	_vpaes_cbc_encrypt
+
+.p2align	4
+_vpaes_cbc_encrypt:
+	xchgq	%rcx,%rdx
+	subq	$16,%rcx
+	jc	L$cbc_abort
+	movdqu	(%r8),%xmm6
+	subq	%rdi,%rsi
+	call	_vpaes_preheat
+	cmpl	$0,%r9d
+	je	L$cbc_dec_loop
+	jmp	L$cbc_enc_loop
+.p2align	4
+L$cbc_enc_loop:
+	movdqu	(%rdi),%xmm0
+	pxor	%xmm6,%xmm0
+	call	_vpaes_encrypt_core
+	movdqa	%xmm0,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	L$cbc_enc_loop
+	jmp	L$cbc_done
+.p2align	4
+L$cbc_dec_loop:
+	movdqu	(%rdi),%xmm0
+	movdqa	%xmm0,%xmm7
+	call	_vpaes_decrypt_core
+	pxor	%xmm6,%xmm0
+	movdqa	%xmm7,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	L$cbc_dec_loop
+L$cbc_done:
+	movdqu	%xmm6,(%r8)
+L$cbc_abort:
+	retq
+
+
+
+
+
+
+
+
+.p2align	4
+_vpaes_preheat:
+	leaq	L$k_s0F(%rip),%r10
+	movdqa	-32(%r10),%xmm10
+	movdqa	-16(%r10),%xmm11
+	movdqa	0(%r10),%xmm9
+	movdqa	48(%r10),%xmm13
+	movdqa	64(%r10),%xmm12
+	movdqa	80(%r10),%xmm15
+	movdqa	96(%r10),%xmm14
+	retq
+
+
+
+
+
+
+
+.p2align	6
+_vpaes_consts:
+L$k_inv:
+.quad	0x0E05060F0D080180, 0x040703090A0B0C02
+.quad	0x01040A060F0B0780, 0x030D0E0C02050809
+
+L$k_s0F:
+.quad	0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+
+L$k_ipt:
+.quad	0xC2B2E8985A2A7000, 0xCABAE09052227808
+.quad	0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
+
+L$k_sb1:
+.quad	0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
+.quad	0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
+L$k_sb2:
+.quad	0xE27A93C60B712400, 0x5EB7E955BC982FCD
+.quad	0x69EB88400AE12900, 0xC2A163C8AB82234A
+L$k_sbo:
+.quad	0xD0D26D176FBDC700, 0x15AABF7AC502A878
+.quad	0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
+
+L$k_mc_forward:
+.quad	0x0407060500030201, 0x0C0F0E0D080B0A09
+.quad	0x080B0A0904070605, 0x000302010C0F0E0D
+.quad	0x0C0F0E0D080B0A09, 0x0407060500030201
+.quad	0x000302010C0F0E0D, 0x080B0A0904070605
+
+L$k_mc_backward:
+.quad	0x0605040702010003, 0x0E0D0C0F0A09080B
+.quad	0x020100030E0D0C0F, 0x0A09080B06050407
+.quad	0x0E0D0C0F0A09080B, 0x0605040702010003
+.quad	0x0A09080B06050407, 0x020100030E0D0C0F
+
+L$k_sr:
+.quad	0x0706050403020100, 0x0F0E0D0C0B0A0908
+.quad	0x030E09040F0A0500, 0x0B06010C07020D08
+.quad	0x0F060D040B020900, 0x070E050C030A0108
+.quad	0x0B0E0104070A0D00, 0x0306090C0F020508
+
+L$k_rcon:
+.quad	0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
+
+L$k_s63:
+.quad	0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
+
+L$k_opt:
+.quad	0xFF9F4929D6B66000, 0xF7974121DEBE6808
+.quad	0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
+
+L$k_deskew:
+.quad	0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
+.quad	0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
+
+
+
+
+
+L$k_dksd:
+.quad	0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
+.quad	0x41C277F4B5368300, 0x5FDC69EAAB289D1E
+L$k_dksb:
+.quad	0x9A4FCA1F8550D500, 0x03D653861CC94C99
+.quad	0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
+L$k_dkse:
+.quad	0xD5031CCA1FC9D600, 0x53859A4C994F5086
+.quad	0xA23196054FDC7BE8, 0xCD5EF96A20B31487
+L$k_dks9:
+.quad	0xB6116FC87ED9A700, 0x4AED933482255BFC
+.quad	0x4576516227143300, 0x8BB89FACE9DAFDCE
+
+
+
+
+
+L$k_dipt:
+.quad	0x0F505B040B545F00, 0x154A411E114E451A
+.quad	0x86E383E660056500, 0x12771772F491F194
+
+L$k_dsb9:
+.quad	0x851C03539A86D600, 0xCAD51F504F994CC9
+.quad	0xC03B1789ECD74900, 0x725E2C9EB2FBA565
+L$k_dsbd:
+.quad	0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
+.quad	0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
+L$k_dsbb:
+.quad	0xD022649296B44200, 0x602646F6B0F2D404
+.quad	0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
+L$k_dsbe:
+.quad	0x46F2929626D4D000, 0x2242600464B4F6B0
+.quad	0x0C55A6CDFFAAC100, 0x9467F36B98593E32
+L$k_dsbo:
+.quad	0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
+.quad	0x12D7560F93441D00, 0xCA4B8159D8C58E9C
+.byte	86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
+.p2align	6
+
diff --git a/crypto/aes/vpaes-masm-x86_64.S b/crypto/aes/vpaes-masm-x86_64.S
new file mode 100644
index 0000000..81a33fd
--- /dev/null
+++ b/crypto/aes/vpaes-masm-x86_64.S
@@ -0,0 +1,1213 @@
+; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/aes/vpaes-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/aes/vpaes-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_encrypt_core	PROC PRIVATE
+	mov	r9,rdx
+	mov	r11,16
+	mov	eax,DWORD PTR[240+rdx]
+	movdqa	xmm1,xmm9
+	movdqa	xmm2,XMMWORD PTR[$L$k_ipt]
+	pandn	xmm1,xmm0
+	movdqu	xmm5,XMMWORD PTR[r9]
+	psrld	xmm1,4
+	pand	xmm0,xmm9
+DB	102,15,56,0,208
+	movdqa	xmm0,XMMWORD PTR[(($L$k_ipt+16))]
+DB	102,15,56,0,193
+	pxor	xmm2,xmm5
+	pxor	xmm0,xmm2
+	add	r9,16
+	lea	r10,QWORD PTR[$L$k_mc_backward]
+	jmp	$L$enc_entry
+
+ALIGN	16
+$L$enc_loop::
+
+	movdqa	xmm4,xmm13
+DB	102,15,56,0,226
+	pxor	xmm4,xmm5
+	movdqa	xmm0,xmm12
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+	movdqa	xmm5,xmm15
+DB	102,15,56,0,234
+	movdqa	xmm1,XMMWORD PTR[((-64))+r10*1+r11]
+	movdqa	xmm2,xmm14
+DB	102,15,56,0,211
+	pxor	xmm2,xmm5
+	movdqa	xmm4,XMMWORD PTR[r10*1+r11]
+	movdqa	xmm3,xmm0
+DB	102,15,56,0,193
+	add	r9,16
+	pxor	xmm0,xmm2
+DB	102,15,56,0,220
+	add	r11,16
+	pxor	xmm3,xmm0
+DB	102,15,56,0,193
+	and	r11,030h
+	pxor	xmm0,xmm3
+	sub	rax,1
+
+$L$enc_entry::
+
+	movdqa	xmm1,xmm9
+	pandn	xmm1,xmm0
+	psrld	xmm1,4
+	pand	xmm0,xmm9
+	movdqa	xmm5,xmm11
+DB	102,15,56,0,232
+	pxor	xmm0,xmm1
+	movdqa	xmm3,xmm10
+DB	102,15,56,0,217
+	pxor	xmm3,xmm5
+	movdqa	xmm4,xmm10
+DB	102,15,56,0,224
+	pxor	xmm4,xmm5
+	movdqa	xmm2,xmm10
+DB	102,15,56,0,211
+	pxor	xmm2,xmm0
+	movdqa	xmm3,xmm10
+	movdqu	xmm5,XMMWORD PTR[r9]
+DB	102,15,56,0,220
+	pxor	xmm3,xmm1
+	jnz	$L$enc_loop
+
+
+	movdqa	xmm4,XMMWORD PTR[((-96))+r10]
+	movdqa	xmm0,XMMWORD PTR[((-80))+r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm5
+DB	102,15,56,0,195
+	movdqa	xmm1,XMMWORD PTR[64+r10*1+r11]
+	pxor	xmm0,xmm4
+DB	102,15,56,0,193
+	DB	0F3h,0C3h		;repret
+_vpaes_encrypt_core	ENDP
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_decrypt_core	PROC PRIVATE
+	mov	r9,rdx
+	mov	eax,DWORD PTR[240+rdx]
+	movdqa	xmm1,xmm9
+	movdqa	xmm2,XMMWORD PTR[$L$k_dipt]
+	pandn	xmm1,xmm0
+	mov	r11,rax
+	psrld	xmm1,4
+	movdqu	xmm5,XMMWORD PTR[r9]
+	shl	r11,4
+	pand	xmm0,xmm9
+DB	102,15,56,0,208
+	movdqa	xmm0,XMMWORD PTR[(($L$k_dipt+16))]
+	xor	r11,030h
+	lea	r10,QWORD PTR[$L$k_dsbd]
+DB	102,15,56,0,193
+	and	r11,030h
+	pxor	xmm2,xmm5
+	movdqa	xmm5,XMMWORD PTR[(($L$k_mc_forward+48))]
+	pxor	xmm0,xmm2
+	add	r9,16
+	add	r11,r10
+	jmp	$L$dec_entry
+
+ALIGN	16
+$L$dec_loop::
+
+
+
+	movdqa	xmm4,XMMWORD PTR[((-32))+r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm0
+	movdqa	xmm0,XMMWORD PTR[((-16))+r10]
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+	add	r9,16
+
+DB	102,15,56,0,197
+	movdqa	xmm4,XMMWORD PTR[r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm0
+	movdqa	xmm0,XMMWORD PTR[16+r10]
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+	sub	rax,1
+
+DB	102,15,56,0,197
+	movdqa	xmm4,XMMWORD PTR[32+r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm0
+	movdqa	xmm0,XMMWORD PTR[48+r10]
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+
+DB	102,15,56,0,197
+	movdqa	xmm4,XMMWORD PTR[64+r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm0
+	movdqa	xmm0,XMMWORD PTR[80+r10]
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+
+DB	102,15,58,15,237,12
+
+$L$dec_entry::
+
+	movdqa	xmm1,xmm9
+	pandn	xmm1,xmm0
+	psrld	xmm1,4
+	pand	xmm0,xmm9
+	movdqa	xmm2,xmm11
+DB	102,15,56,0,208
+	pxor	xmm0,xmm1
+	movdqa	xmm3,xmm10
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+	movdqa	xmm4,xmm10
+DB	102,15,56,0,224
+	pxor	xmm4,xmm2
+	movdqa	xmm2,xmm10
+DB	102,15,56,0,211
+	pxor	xmm2,xmm0
+	movdqa	xmm3,xmm10
+DB	102,15,56,0,220
+	pxor	xmm3,xmm1
+	movdqu	xmm0,XMMWORD PTR[r9]
+	jnz	$L$dec_loop
+
+
+	movdqa	xmm4,XMMWORD PTR[96+r10]
+DB	102,15,56,0,226
+	pxor	xmm4,xmm0
+	movdqa	xmm0,XMMWORD PTR[112+r10]
+	movdqa	xmm2,XMMWORD PTR[((-352))+r11]
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+DB	102,15,56,0,194
+	DB	0F3h,0C3h		;repret
+_vpaes_decrypt_core	ENDP
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_schedule_core	PROC PRIVATE
+
+
+
+
+
+	call	_vpaes_preheat		
+	movdqa	xmm8,XMMWORD PTR[$L$k_rcon]
+	movdqu	xmm0,XMMWORD PTR[rdi]
+
+
+	movdqa	xmm3,xmm0
+	lea	r11,QWORD PTR[$L$k_ipt]
+	call	_vpaes_schedule_transform
+	movdqa	xmm7,xmm0
+
+	lea	r10,QWORD PTR[$L$k_sr]
+	test	rcx,rcx
+	jnz	$L$schedule_am_decrypting
+
+
+	movdqu	XMMWORD PTR[rdx],xmm0
+	jmp	$L$schedule_go
+
+$L$schedule_am_decrypting::
+
+	movdqa	xmm1,XMMWORD PTR[r10*1+r8]
+DB	102,15,56,0,217
+	movdqu	XMMWORD PTR[rdx],xmm3
+	xor	r8,030h
+
+$L$schedule_go::
+	cmp	esi,192
+	ja	$L$schedule_256
+	je	$L$schedule_192
+
+
+
+
+
+
+
+
+
+
+$L$schedule_128::
+	mov	esi,10
+
+$L$oop_schedule_128::
+	call	_vpaes_schedule_round
+	dec	rsi
+	jz	$L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	jmp	$L$oop_schedule_128
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+$L$schedule_192::
+	movdqu	xmm0,XMMWORD PTR[8+rdi]
+	call	_vpaes_schedule_transform	
+	movdqa	xmm6,xmm0
+	pxor	xmm4,xmm4
+	movhlps	xmm6,xmm4
+	mov	esi,4
+
+$L$oop_schedule_192::
+	call	_vpaes_schedule_round
+DB	102,15,58,15,198,8
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_round
+	dec	rsi
+	jz	$L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	jmp	$L$oop_schedule_192
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+$L$schedule_256::
+	movdqu	xmm0,XMMWORD PTR[16+rdi]
+	call	_vpaes_schedule_transform	
+	mov	esi,7
+
+$L$oop_schedule_256::
+	call	_vpaes_schedule_mangle	
+	movdqa	xmm6,xmm0
+
+
+	call	_vpaes_schedule_round
+	dec	rsi
+	jz	$L$schedule_mangle_last
+	call	_vpaes_schedule_mangle	
+
+
+	pshufd	xmm0,xmm0,0FFh
+	movdqa	xmm5,xmm7
+	movdqa	xmm7,xmm6
+	call	_vpaes_schedule_low_round
+	movdqa	xmm7,xmm5
+
+	jmp	$L$oop_schedule_256
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+$L$schedule_mangle_last::
+
+	lea	r11,QWORD PTR[$L$k_deskew]
+	test	rcx,rcx
+	jnz	$L$schedule_mangle_last_dec
+
+
+	movdqa	xmm1,XMMWORD PTR[r10*1+r8]
+DB	102,15,56,0,193
+	lea	r11,QWORD PTR[$L$k_opt]
+	add	rdx,32
+
+$L$schedule_mangle_last_dec::
+	add	rdx,-16
+	pxor	xmm0,XMMWORD PTR[$L$k_s63]
+	call	_vpaes_schedule_transform 
+	movdqu	XMMWORD PTR[rdx],xmm0
+
+
+	pxor	xmm0,xmm0
+	pxor	xmm1,xmm1
+	pxor	xmm2,xmm2
+	pxor	xmm3,xmm3
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	pxor	xmm6,xmm6
+	pxor	xmm7,xmm7
+	DB	0F3h,0C3h		;repret
+_vpaes_schedule_core	ENDP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_schedule_192_smear	PROC PRIVATE
+	pshufd	xmm0,xmm6,080h
+	pxor	xmm6,xmm0
+	pshufd	xmm0,xmm7,0FEh
+	pxor	xmm6,xmm0
+	movdqa	xmm0,xmm6
+	pxor	xmm1,xmm1
+	movhlps	xmm6,xmm1
+	DB	0F3h,0C3h		;repret
+_vpaes_schedule_192_smear	ENDP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_schedule_round	PROC PRIVATE
+
+	pxor	xmm1,xmm1
+DB	102,65,15,58,15,200,15
+DB	102,69,15,58,15,192,15
+	pxor	xmm7,xmm1
+
+
+	pshufd	xmm0,xmm0,0FFh
+DB	102,15,58,15,192,1
+
+
+
+
+_vpaes_schedule_low_round::
+
+	movdqa	xmm1,xmm7
+	pslldq	xmm7,4
+	pxor	xmm7,xmm1
+	movdqa	xmm1,xmm7
+	pslldq	xmm7,8
+	pxor	xmm7,xmm1
+	pxor	xmm7,XMMWORD PTR[$L$k_s63]
+
+
+	movdqa	xmm1,xmm9
+	pandn	xmm1,xmm0
+	psrld	xmm1,4
+	pand	xmm0,xmm9
+	movdqa	xmm2,xmm11
+DB	102,15,56,0,208
+	pxor	xmm0,xmm1
+	movdqa	xmm3,xmm10
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+	movdqa	xmm4,xmm10
+DB	102,15,56,0,224
+	pxor	xmm4,xmm2
+	movdqa	xmm2,xmm10
+DB	102,15,56,0,211
+	pxor	xmm2,xmm0
+	movdqa	xmm3,xmm10
+DB	102,15,56,0,220
+	pxor	xmm3,xmm1
+	movdqa	xmm4,xmm13
+DB	102,15,56,0,226
+	movdqa	xmm0,xmm12
+DB	102,15,56,0,195
+	pxor	xmm0,xmm4
+
+
+	pxor	xmm0,xmm7
+	movdqa	xmm7,xmm0
+	DB	0F3h,0C3h		;repret
+_vpaes_schedule_round	ENDP
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_schedule_transform	PROC PRIVATE
+	movdqa	xmm1,xmm9
+	pandn	xmm1,xmm0
+	psrld	xmm1,4
+	pand	xmm0,xmm9
+	movdqa	xmm2,XMMWORD PTR[r11]
+DB	102,15,56,0,208
+	movdqa	xmm0,XMMWORD PTR[16+r11]
+DB	102,15,56,0,193
+	pxor	xmm0,xmm2
+	DB	0F3h,0C3h		;repret
+_vpaes_schedule_transform	ENDP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_schedule_mangle	PROC PRIVATE
+	movdqa	xmm4,xmm0
+	movdqa	xmm5,XMMWORD PTR[$L$k_mc_forward]
+	test	rcx,rcx
+	jnz	$L$schedule_mangle_dec
+
+
+	add	rdx,16
+	pxor	xmm4,XMMWORD PTR[$L$k_s63]
+DB	102,15,56,0,229
+	movdqa	xmm3,xmm4
+DB	102,15,56,0,229
+	pxor	xmm3,xmm4
+DB	102,15,56,0,229
+	pxor	xmm3,xmm4
+
+	jmp	$L$schedule_mangle_both
+ALIGN	16
+$L$schedule_mangle_dec::
+
+	lea	r11,QWORD PTR[$L$k_dksd]
+	movdqa	xmm1,xmm9
+	pandn	xmm1,xmm4
+	psrld	xmm1,4
+	pand	xmm4,xmm9
+
+	movdqa	xmm2,XMMWORD PTR[r11]
+DB	102,15,56,0,212
+	movdqa	xmm3,XMMWORD PTR[16+r11]
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+DB	102,15,56,0,221
+
+	movdqa	xmm2,XMMWORD PTR[32+r11]
+DB	102,15,56,0,212
+	pxor	xmm2,xmm3
+	movdqa	xmm3,XMMWORD PTR[48+r11]
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+DB	102,15,56,0,221
+
+	movdqa	xmm2,XMMWORD PTR[64+r11]
+DB	102,15,56,0,212
+	pxor	xmm2,xmm3
+	movdqa	xmm3,XMMWORD PTR[80+r11]
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+DB	102,15,56,0,221
+
+	movdqa	xmm2,XMMWORD PTR[96+r11]
+DB	102,15,56,0,212
+	pxor	xmm2,xmm3
+	movdqa	xmm3,XMMWORD PTR[112+r11]
+DB	102,15,56,0,217
+	pxor	xmm3,xmm2
+
+	add	rdx,-16
+
+$L$schedule_mangle_both::
+	movdqa	xmm1,XMMWORD PTR[r10*1+r8]
+DB	102,15,56,0,217
+	add	r8,-16
+	and	r8,030h
+	movdqu	XMMWORD PTR[rdx],xmm3
+	DB	0F3h,0C3h		;repret
+_vpaes_schedule_mangle	ENDP
+
+
+
+
+PUBLIC	vpaes_set_encrypt_key
+
+ALIGN	16
+vpaes_set_encrypt_key	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_vpaes_set_encrypt_key::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	lea	rsp,QWORD PTR[((-184))+rsp]
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+	movaps	XMMWORD PTR[80+rsp],xmm10
+	movaps	XMMWORD PTR[96+rsp],xmm11
+	movaps	XMMWORD PTR[112+rsp],xmm12
+	movaps	XMMWORD PTR[128+rsp],xmm13
+	movaps	XMMWORD PTR[144+rsp],xmm14
+	movaps	XMMWORD PTR[160+rsp],xmm15
+$L$enc_key_body::
+	mov	eax,esi
+	shr	eax,5
+	add	eax,5
+	mov	DWORD PTR[240+rdx],eax
+
+	mov	ecx,0
+	mov	r8d,030h
+	call	_vpaes_schedule_core
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	movaps	xmm10,XMMWORD PTR[80+rsp]
+	movaps	xmm11,XMMWORD PTR[96+rsp]
+	movaps	xmm12,XMMWORD PTR[112+rsp]
+	movaps	xmm13,XMMWORD PTR[128+rsp]
+	movaps	xmm14,XMMWORD PTR[144+rsp]
+	movaps	xmm15,XMMWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[184+rsp]
+$L$enc_key_epilogue::
+	xor	eax,eax
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_vpaes_set_encrypt_key::
+vpaes_set_encrypt_key	ENDP
+
+PUBLIC	vpaes_set_decrypt_key
+
+ALIGN	16
+vpaes_set_decrypt_key	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_vpaes_set_decrypt_key::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	lea	rsp,QWORD PTR[((-184))+rsp]
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+	movaps	XMMWORD PTR[80+rsp],xmm10
+	movaps	XMMWORD PTR[96+rsp],xmm11
+	movaps	XMMWORD PTR[112+rsp],xmm12
+	movaps	XMMWORD PTR[128+rsp],xmm13
+	movaps	XMMWORD PTR[144+rsp],xmm14
+	movaps	XMMWORD PTR[160+rsp],xmm15
+$L$dec_key_body::
+	mov	eax,esi
+	shr	eax,5
+	add	eax,5
+	mov	DWORD PTR[240+rdx],eax
+	shl	eax,4
+	lea	rdx,QWORD PTR[16+rax*1+rdx]
+
+	mov	ecx,1
+	mov	r8d,esi
+	shr	r8d,1
+	and	r8d,32
+	xor	r8d,32
+	call	_vpaes_schedule_core
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	movaps	xmm10,XMMWORD PTR[80+rsp]
+	movaps	xmm11,XMMWORD PTR[96+rsp]
+	movaps	xmm12,XMMWORD PTR[112+rsp]
+	movaps	xmm13,XMMWORD PTR[128+rsp]
+	movaps	xmm14,XMMWORD PTR[144+rsp]
+	movaps	xmm15,XMMWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[184+rsp]
+$L$dec_key_epilogue::
+	xor	eax,eax
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_vpaes_set_decrypt_key::
+vpaes_set_decrypt_key	ENDP
+
+PUBLIC	vpaes_encrypt
+
+ALIGN	16
+vpaes_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_vpaes_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	lea	rsp,QWORD PTR[((-184))+rsp]
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+	movaps	XMMWORD PTR[80+rsp],xmm10
+	movaps	XMMWORD PTR[96+rsp],xmm11
+	movaps	XMMWORD PTR[112+rsp],xmm12
+	movaps	XMMWORD PTR[128+rsp],xmm13
+	movaps	XMMWORD PTR[144+rsp],xmm14
+	movaps	XMMWORD PTR[160+rsp],xmm15
+$L$enc_body::
+	movdqu	xmm0,XMMWORD PTR[rdi]
+	call	_vpaes_preheat
+	call	_vpaes_encrypt_core
+	movdqu	XMMWORD PTR[rsi],xmm0
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	movaps	xmm10,XMMWORD PTR[80+rsp]
+	movaps	xmm11,XMMWORD PTR[96+rsp]
+	movaps	xmm12,XMMWORD PTR[112+rsp]
+	movaps	xmm13,XMMWORD PTR[128+rsp]
+	movaps	xmm14,XMMWORD PTR[144+rsp]
+	movaps	xmm15,XMMWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[184+rsp]
+$L$enc_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_vpaes_encrypt::
+vpaes_encrypt	ENDP
+
+PUBLIC	vpaes_decrypt
+
+ALIGN	16
+vpaes_decrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_vpaes_decrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	lea	rsp,QWORD PTR[((-184))+rsp]
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+	movaps	XMMWORD PTR[80+rsp],xmm10
+	movaps	XMMWORD PTR[96+rsp],xmm11
+	movaps	XMMWORD PTR[112+rsp],xmm12
+	movaps	XMMWORD PTR[128+rsp],xmm13
+	movaps	XMMWORD PTR[144+rsp],xmm14
+	movaps	XMMWORD PTR[160+rsp],xmm15
+$L$dec_body::
+	movdqu	xmm0,XMMWORD PTR[rdi]
+	call	_vpaes_preheat
+	call	_vpaes_decrypt_core
+	movdqu	XMMWORD PTR[rsi],xmm0
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	movaps	xmm10,XMMWORD PTR[80+rsp]
+	movaps	xmm11,XMMWORD PTR[96+rsp]
+	movaps	xmm12,XMMWORD PTR[112+rsp]
+	movaps	xmm13,XMMWORD PTR[128+rsp]
+	movaps	xmm14,XMMWORD PTR[144+rsp]
+	movaps	xmm15,XMMWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[184+rsp]
+$L$dec_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_vpaes_decrypt::
+vpaes_decrypt	ENDP
+PUBLIC	vpaes_cbc_encrypt
+
+ALIGN	16
+vpaes_cbc_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_vpaes_cbc_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	xchg	rdx,rcx
+	sub	rcx,16
+	jc	$L$cbc_abort
+	lea	rsp,QWORD PTR[((-184))+rsp]
+	movaps	XMMWORD PTR[16+rsp],xmm6
+	movaps	XMMWORD PTR[32+rsp],xmm7
+	movaps	XMMWORD PTR[48+rsp],xmm8
+	movaps	XMMWORD PTR[64+rsp],xmm9
+	movaps	XMMWORD PTR[80+rsp],xmm10
+	movaps	XMMWORD PTR[96+rsp],xmm11
+	movaps	XMMWORD PTR[112+rsp],xmm12
+	movaps	XMMWORD PTR[128+rsp],xmm13
+	movaps	XMMWORD PTR[144+rsp],xmm14
+	movaps	XMMWORD PTR[160+rsp],xmm15
+$L$cbc_body::
+	movdqu	xmm6,XMMWORD PTR[r8]
+	sub	rsi,rdi
+	call	_vpaes_preheat
+	cmp	r9d,0
+	je	$L$cbc_dec_loop
+	jmp	$L$cbc_enc_loop
+ALIGN	16
+$L$cbc_enc_loop::
+	movdqu	xmm0,XMMWORD PTR[rdi]
+	pxor	xmm0,xmm6
+	call	_vpaes_encrypt_core
+	movdqa	xmm6,xmm0
+	movdqu	XMMWORD PTR[rdi*1+rsi],xmm0
+	lea	rdi,QWORD PTR[16+rdi]
+	sub	rcx,16
+	jnc	$L$cbc_enc_loop
+	jmp	$L$cbc_done
+ALIGN	16
+$L$cbc_dec_loop::
+	movdqu	xmm0,XMMWORD PTR[rdi]
+	movdqa	xmm7,xmm0
+	call	_vpaes_decrypt_core
+	pxor	xmm0,xmm6
+	movdqa	xmm6,xmm7
+	movdqu	XMMWORD PTR[rdi*1+rsi],xmm0
+	lea	rdi,QWORD PTR[16+rdi]
+	sub	rcx,16
+	jnc	$L$cbc_dec_loop
+$L$cbc_done::
+	movdqu	XMMWORD PTR[r8],xmm6
+	movaps	xmm6,XMMWORD PTR[16+rsp]
+	movaps	xmm7,XMMWORD PTR[32+rsp]
+	movaps	xmm8,XMMWORD PTR[48+rsp]
+	movaps	xmm9,XMMWORD PTR[64+rsp]
+	movaps	xmm10,XMMWORD PTR[80+rsp]
+	movaps	xmm11,XMMWORD PTR[96+rsp]
+	movaps	xmm12,XMMWORD PTR[112+rsp]
+	movaps	xmm13,XMMWORD PTR[128+rsp]
+	movaps	xmm14,XMMWORD PTR[144+rsp]
+	movaps	xmm15,XMMWORD PTR[160+rsp]
+	lea	rsp,QWORD PTR[184+rsp]
+$L$cbc_epilogue::
+$L$cbc_abort::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_vpaes_cbc_encrypt::
+vpaes_cbc_encrypt	ENDP
+
+
+
+
+
+
+
+ALIGN	16
+_vpaes_preheat	PROC PRIVATE
+	lea	r10,QWORD PTR[$L$k_s0F]
+	movdqa	xmm10,XMMWORD PTR[((-32))+r10]
+	movdqa	xmm11,XMMWORD PTR[((-16))+r10]
+	movdqa	xmm9,XMMWORD PTR[r10]
+	movdqa	xmm13,XMMWORD PTR[48+r10]
+	movdqa	xmm12,XMMWORD PTR[64+r10]
+	movdqa	xmm15,XMMWORD PTR[80+r10]
+	movdqa	xmm14,XMMWORD PTR[96+r10]
+	DB	0F3h,0C3h		;repret
+_vpaes_preheat	ENDP
+
+
+
+
+
+
+ALIGN	64
+_vpaes_consts::
+$L$k_inv::
+	DQ	00E05060F0D080180h,0040703090A0B0C02h
+	DQ	001040A060F0B0780h,0030D0E0C02050809h
+
+$L$k_s0F::
+	DQ	00F0F0F0F0F0F0F0Fh,00F0F0F0F0F0F0F0Fh
+
+$L$k_ipt::
+	DQ	0C2B2E8985A2A7000h,0CABAE09052227808h
+	DQ	04C01307D317C4D00h,0CD80B1FCB0FDCC81h
+
+$L$k_sb1::
+	DQ	0B19BE18FCB503E00h,0A5DF7A6E142AF544h
+	DQ	03618D415FAE22300h,03BF7CCC10D2ED9EFh
+$L$k_sb2::
+	DQ	0E27A93C60B712400h,05EB7E955BC982FCDh
+	DQ	069EB88400AE12900h,0C2A163C8AB82234Ah
+$L$k_sbo::
+	DQ	0D0D26D176FBDC700h,015AABF7AC502A878h
+	DQ	0CFE474A55FBB6A00h,08E1E90D1412B35FAh
+
+$L$k_mc_forward::
+	DQ	00407060500030201h,00C0F0E0D080B0A09h
+	DQ	0080B0A0904070605h,0000302010C0F0E0Dh
+	DQ	00C0F0E0D080B0A09h,00407060500030201h
+	DQ	0000302010C0F0E0Dh,0080B0A0904070605h
+
+$L$k_mc_backward::
+	DQ	00605040702010003h,00E0D0C0F0A09080Bh
+	DQ	0020100030E0D0C0Fh,00A09080B06050407h
+	DQ	00E0D0C0F0A09080Bh,00605040702010003h
+	DQ	00A09080B06050407h,0020100030E0D0C0Fh
+
+$L$k_sr::
+	DQ	00706050403020100h,00F0E0D0C0B0A0908h
+	DQ	0030E09040F0A0500h,00B06010C07020D08h
+	DQ	00F060D040B020900h,0070E050C030A0108h
+	DQ	00B0E0104070A0D00h,00306090C0F020508h
+
+$L$k_rcon::
+	DQ	01F8391B9AF9DEEB6h,0702A98084D7C7D81h
+
+$L$k_s63::
+	DQ	05B5B5B5B5B5B5B5Bh,05B5B5B5B5B5B5B5Bh
+
+$L$k_opt::
+	DQ	0FF9F4929D6B66000h,0F7974121DEBE6808h
+	DQ	001EDBD5150BCEC00h,0E10D5DB1B05C0CE0h
+
+$L$k_deskew::
+	DQ	007E4A34047A4E300h,01DFEB95A5DBEF91Ah
+	DQ	05F36B5DC83EA6900h,02841C2ABF49D1E77h
+
+
+
+
+
+$L$k_dksd::
+	DQ	0FEB91A5DA3E44700h,00740E3A45A1DBEF9h
+	DQ	041C277F4B5368300h,05FDC69EAAB289D1Eh
+$L$k_dksb::
+	DQ	09A4FCA1F8550D500h,003D653861CC94C99h
+	DQ	0115BEDA7B6FC4A00h,0D993256F7E3482C8h
+$L$k_dkse::
+	DQ	0D5031CCA1FC9D600h,053859A4C994F5086h
+	DQ	0A23196054FDC7BE8h,0CD5EF96A20B31487h
+$L$k_dks9::
+	DQ	0B6116FC87ED9A700h,04AED933482255BFCh
+	DQ	04576516227143300h,08BB89FACE9DAFDCEh
+
+
+
+
+
+$L$k_dipt::
+	DQ	00F505B040B545F00h,0154A411E114E451Ah
+	DQ	086E383E660056500h,012771772F491F194h
+
+$L$k_dsb9::
+	DQ	0851C03539A86D600h,0CAD51F504F994CC9h
+	DQ	0C03B1789ECD74900h,0725E2C9EB2FBA565h
+$L$k_dsbd::
+	DQ	07D57CCDFE6B1A200h,0F56E9B13882A4439h
+	DQ	03CE2FAF724C6CB00h,02931180D15DEEFD3h
+$L$k_dsbb::
+	DQ	0D022649296B44200h,0602646F6B0F2D404h
+	DQ	0C19498A6CD596700h,0F3FF0C3E3255AA6Bh
+$L$k_dsbe::
+	DQ	046F2929626D4D000h,02242600464B4F6B0h
+	DQ	00C55A6CDFFAAC100h,09467F36B98593E32h
+$L$k_dsbo::
+	DQ	01387EA537EF94000h,0C7AA6DB9D4943E2Dh
+	DQ	012D7560F93441D00h,0CA4B8159D8C58E9Ch
+DB	86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105
+DB	111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54
+DB	52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97
+DB	109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32
+DB	85,110,105,118,101,114,115,105,116,121,41,0
+ALIGN	64
+
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$in_prologue
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$in_prologue
+
+	lea	rsi,QWORD PTR[16+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,20
+	DD	0a548f3fch		
+	lea	rax,QWORD PTR[184+rax]
+
+$L$in_prologue::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+se_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_vpaes_set_encrypt_key
+	DD	imagerel $L$SEH_end_vpaes_set_encrypt_key
+	DD	imagerel $L$SEH_info_vpaes_set_encrypt_key
+
+	DD	imagerel $L$SEH_begin_vpaes_set_decrypt_key
+	DD	imagerel $L$SEH_end_vpaes_set_decrypt_key
+	DD	imagerel $L$SEH_info_vpaes_set_decrypt_key
+
+	DD	imagerel $L$SEH_begin_vpaes_encrypt
+	DD	imagerel $L$SEH_end_vpaes_encrypt
+	DD	imagerel $L$SEH_info_vpaes_encrypt
+
+	DD	imagerel $L$SEH_begin_vpaes_decrypt
+	DD	imagerel $L$SEH_end_vpaes_decrypt
+	DD	imagerel $L$SEH_info_vpaes_decrypt
+
+	DD	imagerel $L$SEH_begin_vpaes_cbc_encrypt
+	DD	imagerel $L$SEH_end_vpaes_cbc_encrypt
+	DD	imagerel $L$SEH_info_vpaes_cbc_encrypt
+
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_vpaes_set_encrypt_key::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$enc_key_body,imagerel $L$enc_key_epilogue	
+$L$SEH_info_vpaes_set_decrypt_key::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$dec_key_body,imagerel $L$dec_key_epilogue	
+$L$SEH_info_vpaes_encrypt::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$enc_body,imagerel $L$enc_epilogue		
+$L$SEH_info_vpaes_decrypt::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$dec_body,imagerel $L$dec_epilogue		
+$L$SEH_info_vpaes_cbc_encrypt::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$cbc_body,imagerel $L$cbc_epilogue		
+
+.xdata	ENDS
+END
+
diff --git a/crypto/aes/vpaes-mingw64-x86_64.S b/crypto/aes/vpaes-mingw64-x86_64.S
new file mode 100644
index 0000000..d6cb860
--- /dev/null
+++ b/crypto/aes/vpaes-mingw64-x86_64.S
@@ -0,0 +1,1125 @@
+#include "x86_arch.h"
+.text	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.def	_vpaes_encrypt_core;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_encrypt_core:
+	movq	%rdx,%r9
+	movq	$16,%r11
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	.Lk_ipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movdqu	(%r9),%xmm5
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	.Lk_ipt+16(%rip),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm5,%xmm2
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	leaq	.Lk_mc_backward(%rip),%r10
+	jmp	.Lenc_entry
+
+.p2align	4
+.Lenc_loop:
+
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	movdqa	%xmm15,%xmm5
+.byte	102,15,56,0,234
+	movdqa	-64(%r11,%r10,1),%xmm1
+	movdqa	%xmm14,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm5,%xmm2
+	movdqa	(%r11,%r10,1),%xmm4
+	movdqa	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	addq	$16,%r9
+	pxor	%xmm2,%xmm0
+.byte	102,15,56,0,220
+	addq	$16,%r11
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm3,%xmm0
+	subq	$1,%rax
+
+.Lenc_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm5
+.byte	102,15,56,0,232
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm5,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+	movdqu	(%r9),%xmm5
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	jnz	.Lenc_loop
+
+
+	movdqa	-96(%r10),%xmm4
+	movdqa	-80(%r10),%xmm0
+.byte	102,15,56,0,226
+	pxor	%xmm5,%xmm4
+.byte	102,15,56,0,195
+	movdqa	64(%r11,%r10,1),%xmm1
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,193
+	retq
+
+
+
+
+
+
+
+.def	_vpaes_decrypt_core;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_decrypt_core:
+	movq	%rdx,%r9
+	movl	240(%rdx),%eax
+	movdqa	%xmm9,%xmm1
+	movdqa	.Lk_dipt(%rip),%xmm2
+	pandn	%xmm0,%xmm1
+	movq	%rax,%r11
+	psrld	$4,%xmm1
+	movdqu	(%r9),%xmm5
+	shlq	$4,%r11
+	pand	%xmm9,%xmm0
+.byte	102,15,56,0,208
+	movdqa	.Lk_dipt+16(%rip),%xmm0
+	xorq	$48,%r11
+	leaq	.Lk_dsbd(%rip),%r10
+.byte	102,15,56,0,193
+	andq	$48,%r11
+	pxor	%xmm5,%xmm2
+	movdqa	.Lk_mc_forward+48(%rip),%xmm5
+	pxor	%xmm2,%xmm0
+	addq	$16,%r9
+	addq	%r10,%r11
+	jmp	.Ldec_entry
+
+.p2align	4
+.Ldec_loop:
+
+
+
+	movdqa	-32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	-16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	addq	$16,%r9
+
+.byte	102,15,56,0,197
+	movdqa	0(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	16(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+	subq	$1,%rax
+
+.byte	102,15,56,0,197
+	movdqa	32(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	48(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,56,0,197
+	movdqa	64(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	80(%r10),%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+.byte	102,15,58,15,237,12
+
+.Ldec_entry:
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqu	(%r9),%xmm0
+	jnz	.Ldec_loop
+
+
+	movdqa	96(%r10),%xmm4
+.byte	102,15,56,0,226
+	pxor	%xmm0,%xmm4
+	movdqa	112(%r10),%xmm0
+	movdqa	-352(%r11),%xmm2
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,194
+	retq
+
+
+
+
+
+
+
+.def	_vpaes_schedule_core;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_schedule_core:
+
+
+
+
+
+	call	_vpaes_preheat		
+	movdqa	.Lk_rcon(%rip),%xmm8
+	movdqu	(%rdi),%xmm0
+
+
+	movdqa	%xmm0,%xmm3
+	leaq	.Lk_ipt(%rip),%r11
+	call	_vpaes_schedule_transform
+	movdqa	%xmm0,%xmm7
+
+	leaq	.Lk_sr(%rip),%r10
+	testq	%rcx,%rcx
+	jnz	.Lschedule_am_decrypting
+
+
+	movdqu	%xmm0,(%rdx)
+	jmp	.Lschedule_go
+
+.Lschedule_am_decrypting:
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	movdqu	%xmm3,(%rdx)
+	xorq	$48,%r8
+
+.Lschedule_go:
+	cmpl	$192,%esi
+	ja	.Lschedule_256
+	je	.Lschedule_192
+
+
+
+
+
+
+
+
+
+
+.Lschedule_128:
+	movl	$10,%esi
+
+.Loop_schedule_128:
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	jmp	.Loop_schedule_128
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+.Lschedule_192:
+	movdqu	8(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movdqa	%xmm0,%xmm6
+	pxor	%xmm4,%xmm4
+	movhlps	%xmm4,%xmm6
+	movl	$4,%esi
+
+.Loop_schedule_192:
+	call	_vpaes_schedule_round
+.byte	102,15,58,15,198,8
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_192_smear
+	jmp	.Loop_schedule_192
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+.Lschedule_256:
+	movdqu	16(%rdi),%xmm0
+	call	_vpaes_schedule_transform	
+	movl	$7,%esi
+
+.Loop_schedule_256:
+	call	_vpaes_schedule_mangle	
+	movdqa	%xmm0,%xmm6
+
+
+	call	_vpaes_schedule_round
+	decq	%rsi
+	jz	.Lschedule_mangle_last
+	call	_vpaes_schedule_mangle	
+
+
+	pshufd	$255,%xmm0,%xmm0
+	movdqa	%xmm7,%xmm5
+	movdqa	%xmm6,%xmm7
+	call	_vpaes_schedule_low_round
+	movdqa	%xmm5,%xmm7
+
+	jmp	.Loop_schedule_256
+
+
+
+
+
+
+
+
+
+
+
+
+.p2align	4
+.Lschedule_mangle_last:
+
+	leaq	.Lk_deskew(%rip),%r11
+	testq	%rcx,%rcx
+	jnz	.Lschedule_mangle_last_dec
+
+
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,193
+	leaq	.Lk_opt(%rip),%r11
+	addq	$32,%rdx
+
+.Lschedule_mangle_last_dec:
+	addq	$-16,%rdx
+	pxor	.Lk_s63(%rip),%xmm0
+	call	_vpaes_schedule_transform 
+	movdqu	%xmm0,(%rdx)
+
+
+	pxor	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.def	_vpaes_schedule_192_smear;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_schedule_192_smear:
+	pshufd	$128,%xmm6,%xmm0
+	pxor	%xmm0,%xmm6
+	pshufd	$254,%xmm7,%xmm0
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm6,%xmm0
+	pxor	%xmm1,%xmm1
+	movhlps	%xmm1,%xmm6
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.def	_vpaes_schedule_round;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_schedule_round:
+
+	pxor	%xmm1,%xmm1
+.byte	102,65,15,58,15,200,15
+.byte	102,69,15,58,15,192,15
+	pxor	%xmm1,%xmm7
+
+
+	pshufd	$255,%xmm0,%xmm0
+.byte	102,15,58,15,192,1
+
+
+
+
+_vpaes_schedule_low_round:
+
+	movdqa	%xmm7,%xmm1
+	pslldq	$4,%xmm7
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm7,%xmm1
+	pslldq	$8,%xmm7
+	pxor	%xmm1,%xmm7
+	pxor	.Lk_s63(%rip),%xmm7
+
+
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	%xmm11,%xmm2
+.byte	102,15,56,0,208
+	pxor	%xmm1,%xmm0
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+	movdqa	%xmm10,%xmm4
+.byte	102,15,56,0,224
+	pxor	%xmm2,%xmm4
+	movdqa	%xmm10,%xmm2
+.byte	102,15,56,0,211
+	pxor	%xmm0,%xmm2
+	movdqa	%xmm10,%xmm3
+.byte	102,15,56,0,220
+	pxor	%xmm1,%xmm3
+	movdqa	%xmm13,%xmm4
+.byte	102,15,56,0,226
+	movdqa	%xmm12,%xmm0
+.byte	102,15,56,0,195
+	pxor	%xmm4,%xmm0
+
+
+	pxor	%xmm7,%xmm0
+	movdqa	%xmm0,%xmm7
+	retq
+
+
+
+
+
+
+
+
+
+
+
+.def	_vpaes_schedule_transform;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_schedule_transform:
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm0,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm0
+	movdqa	(%r11),%xmm2
+.byte	102,15,56,0,208
+	movdqa	16(%r11),%xmm0
+.byte	102,15,56,0,193
+	pxor	%xmm2,%xmm0
+	retq
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.def	_vpaes_schedule_mangle;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_schedule_mangle:
+	movdqa	%xmm0,%xmm4
+	movdqa	.Lk_mc_forward(%rip),%xmm5
+	testq	%rcx,%rcx
+	jnz	.Lschedule_mangle_dec
+
+
+	addq	$16,%rdx
+	pxor	.Lk_s63(%rip),%xmm4
+.byte	102,15,56,0,229
+	movdqa	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+.byte	102,15,56,0,229
+	pxor	%xmm4,%xmm3
+
+	jmp	.Lschedule_mangle_both
+.p2align	4
+.Lschedule_mangle_dec:
+
+	leaq	.Lk_dksd(%rip),%r11
+	movdqa	%xmm9,%xmm1
+	pandn	%xmm4,%xmm1
+	psrld	$4,%xmm1
+	pand	%xmm9,%xmm4
+
+	movdqa	0(%r11),%xmm2
+.byte	102,15,56,0,212
+	movdqa	16(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	32(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	48(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	64(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	80(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+.byte	102,15,56,0,221
+
+	movdqa	96(%r11),%xmm2
+.byte	102,15,56,0,212
+	pxor	%xmm3,%xmm2
+	movdqa	112(%r11),%xmm3
+.byte	102,15,56,0,217
+	pxor	%xmm2,%xmm3
+
+	addq	$-16,%rdx
+
+.Lschedule_mangle_both:
+	movdqa	(%r8,%r10,1),%xmm1
+.byte	102,15,56,0,217
+	addq	$-16,%r8
+	andq	$48,%r8
+	movdqu	%xmm3,(%rdx)
+	retq
+
+
+
+
+
+.globl	vpaes_set_encrypt_key
+.def	vpaes_set_encrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+vpaes_set_encrypt_key:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_vpaes_set_encrypt_key:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	leaq	-184(%rsp),%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+	movaps	%xmm10,80(%rsp)
+	movaps	%xmm11,96(%rsp)
+	movaps	%xmm12,112(%rsp)
+	movaps	%xmm13,128(%rsp)
+	movaps	%xmm14,144(%rsp)
+	movaps	%xmm15,160(%rsp)
+.Lenc_key_body:
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+
+	movl	$0,%ecx
+	movl	$48,%r8d
+	call	_vpaes_schedule_core
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	movaps	80(%rsp),%xmm10
+	movaps	96(%rsp),%xmm11
+	movaps	112(%rsp),%xmm12
+	movaps	128(%rsp),%xmm13
+	movaps	144(%rsp),%xmm14
+	movaps	160(%rsp),%xmm15
+	leaq	184(%rsp),%rsp
+.Lenc_key_epilogue:
+	xorl	%eax,%eax
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_vpaes_set_encrypt_key:
+
+.globl	vpaes_set_decrypt_key
+.def	vpaes_set_decrypt_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+vpaes_set_decrypt_key:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_vpaes_set_decrypt_key:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	leaq	-184(%rsp),%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+	movaps	%xmm10,80(%rsp)
+	movaps	%xmm11,96(%rsp)
+	movaps	%xmm12,112(%rsp)
+	movaps	%xmm13,128(%rsp)
+	movaps	%xmm14,144(%rsp)
+	movaps	%xmm15,160(%rsp)
+.Ldec_key_body:
+	movl	%esi,%eax
+	shrl	$5,%eax
+	addl	$5,%eax
+	movl	%eax,240(%rdx)
+	shll	$4,%eax
+	leaq	16(%rdx,%rax,1),%rdx
+
+	movl	$1,%ecx
+	movl	%esi,%r8d
+	shrl	$1,%r8d
+	andl	$32,%r8d
+	xorl	$32,%r8d
+	call	_vpaes_schedule_core
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	movaps	80(%rsp),%xmm10
+	movaps	96(%rsp),%xmm11
+	movaps	112(%rsp),%xmm12
+	movaps	128(%rsp),%xmm13
+	movaps	144(%rsp),%xmm14
+	movaps	160(%rsp),%xmm15
+	leaq	184(%rsp),%rsp
+.Ldec_key_epilogue:
+	xorl	%eax,%eax
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_vpaes_set_decrypt_key:
+
+.globl	vpaes_encrypt
+.def	vpaes_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+vpaes_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_vpaes_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	leaq	-184(%rsp),%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+	movaps	%xmm10,80(%rsp)
+	movaps	%xmm11,96(%rsp)
+	movaps	%xmm12,112(%rsp)
+	movaps	%xmm13,128(%rsp)
+	movaps	%xmm14,144(%rsp)
+	movaps	%xmm15,160(%rsp)
+.Lenc_body:
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_encrypt_core
+	movdqu	%xmm0,(%rsi)
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	movaps	80(%rsp),%xmm10
+	movaps	96(%rsp),%xmm11
+	movaps	112(%rsp),%xmm12
+	movaps	128(%rsp),%xmm13
+	movaps	144(%rsp),%xmm14
+	movaps	160(%rsp),%xmm15
+	leaq	184(%rsp),%rsp
+.Lenc_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_vpaes_encrypt:
+
+.globl	vpaes_decrypt
+.def	vpaes_decrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+vpaes_decrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_vpaes_decrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	leaq	-184(%rsp),%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+	movaps	%xmm10,80(%rsp)
+	movaps	%xmm11,96(%rsp)
+	movaps	%xmm12,112(%rsp)
+	movaps	%xmm13,128(%rsp)
+	movaps	%xmm14,144(%rsp)
+	movaps	%xmm15,160(%rsp)
+.Ldec_body:
+	movdqu	(%rdi),%xmm0
+	call	_vpaes_preheat
+	call	_vpaes_decrypt_core
+	movdqu	%xmm0,(%rsi)
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	movaps	80(%rsp),%xmm10
+	movaps	96(%rsp),%xmm11
+	movaps	112(%rsp),%xmm12
+	movaps	128(%rsp),%xmm13
+	movaps	144(%rsp),%xmm14
+	movaps	160(%rsp),%xmm15
+	leaq	184(%rsp),%rsp
+.Ldec_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_vpaes_decrypt:
+.globl	vpaes_cbc_encrypt
+.def	vpaes_cbc_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+vpaes_cbc_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_vpaes_cbc_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	xchgq	%rcx,%rdx
+	subq	$16,%rcx
+	jc	.Lcbc_abort
+	leaq	-184(%rsp),%rsp
+	movaps	%xmm6,16(%rsp)
+	movaps	%xmm7,32(%rsp)
+	movaps	%xmm8,48(%rsp)
+	movaps	%xmm9,64(%rsp)
+	movaps	%xmm10,80(%rsp)
+	movaps	%xmm11,96(%rsp)
+	movaps	%xmm12,112(%rsp)
+	movaps	%xmm13,128(%rsp)
+	movaps	%xmm14,144(%rsp)
+	movaps	%xmm15,160(%rsp)
+.Lcbc_body:
+	movdqu	(%r8),%xmm6
+	subq	%rdi,%rsi
+	call	_vpaes_preheat
+	cmpl	$0,%r9d
+	je	.Lcbc_dec_loop
+	jmp	.Lcbc_enc_loop
+.p2align	4
+.Lcbc_enc_loop:
+	movdqu	(%rdi),%xmm0
+	pxor	%xmm6,%xmm0
+	call	_vpaes_encrypt_core
+	movdqa	%xmm0,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	.Lcbc_enc_loop
+	jmp	.Lcbc_done
+.p2align	4
+.Lcbc_dec_loop:
+	movdqu	(%rdi),%xmm0
+	movdqa	%xmm0,%xmm7
+	call	_vpaes_decrypt_core
+	pxor	%xmm6,%xmm0
+	movdqa	%xmm7,%xmm6
+	movdqu	%xmm0,(%rsi,%rdi,1)
+	leaq	16(%rdi),%rdi
+	subq	$16,%rcx
+	jnc	.Lcbc_dec_loop
+.Lcbc_done:
+	movdqu	%xmm6,(%r8)
+	movaps	16(%rsp),%xmm6
+	movaps	32(%rsp),%xmm7
+	movaps	48(%rsp),%xmm8
+	movaps	64(%rsp),%xmm9
+	movaps	80(%rsp),%xmm10
+	movaps	96(%rsp),%xmm11
+	movaps	112(%rsp),%xmm12
+	movaps	128(%rsp),%xmm13
+	movaps	144(%rsp),%xmm14
+	movaps	160(%rsp),%xmm15
+	leaq	184(%rsp),%rsp
+.Lcbc_epilogue:
+.Lcbc_abort:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_vpaes_cbc_encrypt:
+
+
+
+
+
+
+.def	_vpaes_preheat;	.scl 3;	.type 32;	.endef
+.p2align	4
+_vpaes_preheat:
+	leaq	.Lk_s0F(%rip),%r10
+	movdqa	-32(%r10),%xmm10
+	movdqa	-16(%r10),%xmm11
+	movdqa	0(%r10),%xmm9
+	movdqa	48(%r10),%xmm13
+	movdqa	64(%r10),%xmm12
+	movdqa	80(%r10),%xmm15
+	movdqa	96(%r10),%xmm14
+	retq
+
+
+
+
+
+
+
+.p2align	6
+_vpaes_consts:
+.Lk_inv:
+.quad	0x0E05060F0D080180, 0x040703090A0B0C02
+.quad	0x01040A060F0B0780, 0x030D0E0C02050809
+
+.Lk_s0F:
+.quad	0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
+
+.Lk_ipt:
+.quad	0xC2B2E8985A2A7000, 0xCABAE09052227808
+.quad	0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
+
+.Lk_sb1:
+.quad	0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
+.quad	0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
+.Lk_sb2:
+.quad	0xE27A93C60B712400, 0x5EB7E955BC982FCD
+.quad	0x69EB88400AE12900, 0xC2A163C8AB82234A
+.Lk_sbo:
+.quad	0xD0D26D176FBDC700, 0x15AABF7AC502A878
+.quad	0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
+
+.Lk_mc_forward:
+.quad	0x0407060500030201, 0x0C0F0E0D080B0A09
+.quad	0x080B0A0904070605, 0x000302010C0F0E0D
+.quad	0x0C0F0E0D080B0A09, 0x0407060500030201
+.quad	0x000302010C0F0E0D, 0x080B0A0904070605
+
+.Lk_mc_backward:
+.quad	0x0605040702010003, 0x0E0D0C0F0A09080B
+.quad	0x020100030E0D0C0F, 0x0A09080B06050407
+.quad	0x0E0D0C0F0A09080B, 0x0605040702010003
+.quad	0x0A09080B06050407, 0x020100030E0D0C0F
+
+.Lk_sr:
+.quad	0x0706050403020100, 0x0F0E0D0C0B0A0908
+.quad	0x030E09040F0A0500, 0x0B06010C07020D08
+.quad	0x0F060D040B020900, 0x070E050C030A0108
+.quad	0x0B0E0104070A0D00, 0x0306090C0F020508
+
+.Lk_rcon:
+.quad	0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
+
+.Lk_s63:
+.quad	0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
+
+.Lk_opt:
+.quad	0xFF9F4929D6B66000, 0xF7974121DEBE6808
+.quad	0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
+
+.Lk_deskew:
+.quad	0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
+.quad	0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
+
+
+
+
+
+.Lk_dksd:
+.quad	0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
+.quad	0x41C277F4B5368300, 0x5FDC69EAAB289D1E
+.Lk_dksb:
+.quad	0x9A4FCA1F8550D500, 0x03D653861CC94C99
+.quad	0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
+.Lk_dkse:
+.quad	0xD5031CCA1FC9D600, 0x53859A4C994F5086
+.quad	0xA23196054FDC7BE8, 0xCD5EF96A20B31487
+.Lk_dks9:
+.quad	0xB6116FC87ED9A700, 0x4AED933482255BFC
+.quad	0x4576516227143300, 0x8BB89FACE9DAFDCE
+
+
+
+
+
+.Lk_dipt:
+.quad	0x0F505B040B545F00, 0x154A411E114E451A
+.quad	0x86E383E660056500, 0x12771772F491F194
+
+.Lk_dsb9:
+.quad	0x851C03539A86D600, 0xCAD51F504F994CC9
+.quad	0xC03B1789ECD74900, 0x725E2C9EB2FBA565
+.Lk_dsbd:
+.quad	0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
+.quad	0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
+.Lk_dsbb:
+.quad	0xD022649296B44200, 0x602646F6B0F2D404
+.quad	0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
+.Lk_dsbe:
+.quad	0x46F2929626D4D000, 0x2242600464B4F6B0
+.quad	0x0C55A6CDFFAAC100, 0x9467F36B98593E32
+.Lk_dsbo:
+.quad	0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
+.quad	0x12D7560F93441D00, 0xCA4B8159D8C58E9C
+.byte	86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
+.p2align	6
+
+
+.def	se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_prologue
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_prologue
+
+	leaq	16(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$20,%ecx
+.long	0xa548f3fc		
+	leaq	184(%rax),%rax
+
+.Lin_prologue:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_vpaes_set_encrypt_key
+.rva	.LSEH_end_vpaes_set_encrypt_key
+.rva	.LSEH_info_vpaes_set_encrypt_key
+
+.rva	.LSEH_begin_vpaes_set_decrypt_key
+.rva	.LSEH_end_vpaes_set_decrypt_key
+.rva	.LSEH_info_vpaes_set_decrypt_key
+
+.rva	.LSEH_begin_vpaes_encrypt
+.rva	.LSEH_end_vpaes_encrypt
+.rva	.LSEH_info_vpaes_encrypt
+
+.rva	.LSEH_begin_vpaes_decrypt
+.rva	.LSEH_end_vpaes_decrypt
+.rva	.LSEH_info_vpaes_decrypt
+
+.rva	.LSEH_begin_vpaes_cbc_encrypt
+.rva	.LSEH_end_vpaes_cbc_encrypt
+.rva	.LSEH_info_vpaes_cbc_encrypt
+
+.section	.xdata
+.p2align	3
+.LSEH_info_vpaes_set_encrypt_key:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lenc_key_body,.Lenc_key_epilogue	
+.LSEH_info_vpaes_set_decrypt_key:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Ldec_key_body,.Ldec_key_epilogue	
+.LSEH_info_vpaes_encrypt:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lenc_body,.Lenc_epilogue		
+.LSEH_info_vpaes_decrypt:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Ldec_body,.Ldec_epilogue		
+.LSEH_info_vpaes_cbc_encrypt:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lcbc_body,.Lcbc_epilogue		
diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h
new file mode 100644
index 0000000..5ac3b93
--- /dev/null
+++ b/crypto/arm_arch.h
@@ -0,0 +1,59 @@
+/* $OpenBSD: arm_arch.h,v 1.1 2022/03/23 15:13:31 tb Exp $ */
+#ifndef __ARM_ARCH_H__
+#define __ARM_ARCH_H__
+
+#if !defined(__ARM_ARCH__)
+# if defined(__CC_ARM)
+#  define __ARM_ARCH__ __TARGET_ARCH_ARM
+#  if defined(__BIG_ENDIAN)
+#   define __ARMEB__
+#  else
+#   define __ARMEL__
+#  endif
+# elif defined(__GNUC__)
+  /*
+   * Why doesn't gcc define __ARM_ARCH__? Instead it defines
+   * bunch of below macros. See all_architectures[] table in
+   * gcc/config/arm/arm.c. On a side note it defines
+   * __ARMEL__/__ARMEB__ for little-/big-endian.
+   */
+#  if	defined(__ARM_ARCH)
+#   define __ARM_ARCH__ __ARM_ARCH
+#  elif	defined(__ARM_ARCH_8A__)
+#   define __ARM_ARCH__ 8
+#  elif	defined(__ARM_ARCH_7__)	|| defined(__ARM_ARCH_7A__)	|| \
+	defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__)	|| \
+	defined(__ARM_ARCH_7EM__)
+#   define __ARM_ARCH__ 7
+#  elif	defined(__ARM_ARCH_6__)	|| defined(__ARM_ARCH_6J__)	|| \
+	defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__)	|| \
+	defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__)	|| \
+	defined(__ARM_ARCH_6T2__)
+#   define __ARM_ARCH__ 6
+#  elif	defined(__ARM_ARCH_5__)	|| defined(__ARM_ARCH_5T__)	|| \
+	defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__)	|| \
+	defined(__ARM_ARCH_5TEJ__)
+#   define __ARM_ARCH__ 5
+#  elif	defined(__ARM_ARCH_4__)	|| defined(__ARM_ARCH_4T__)
+#   define __ARM_ARCH__ 4
+#  else
+#   error "unsupported ARM architecture"
+#  endif
+# endif
+#endif
+
+#if !defined(__ASSEMBLER__)
+extern unsigned int OPENSSL_armcap_P;
+
+#define ARMV7_NEON	(1<<0)
+#define ARMV8_AES	(1<<1)
+#define ARMV8_SHA1	(1<<2)
+#define ARMV8_SHA256	(1<<3)
+#define ARMV8_PMULL	(1<<4)
+#endif
+
+#if defined(__OpenBSD__)
+#define __STRICT_ALIGNMENT
+#endif
+
+#endif
diff --git a/crypto/armcap.c b/crypto/armcap.c
new file mode 100644
index 0000000..9d93d11
--- /dev/null
+++ b/crypto/armcap.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: armcap.c,v 1.2 2023/07/26 09:57:34 jsing Exp $ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "arm_arch.h"
+
+unsigned int OPENSSL_armcap_P;
+
+#if __ARM_ARCH__ >= 7
+static sigset_t all_masked;
+
+static sigjmp_buf ill_jmp;
+	static void ill_handler (int sig) { siglongjmp(ill_jmp, sig);
+}
+
+/*
+ * Following subroutines could have been inlined, but it's not all
+ * ARM compilers support inline assembler...
+ */
+void _armv7_neon_probe(void);
+void _armv8_aes_probe(void);
+void _armv8_sha1_probe(void);
+void _armv8_sha256_probe(void);
+void _armv8_pmull_probe(void);
+#endif
+
+void
+OPENSSL_cpuid_setup(void)
+{
+#if __ARM_ARCH__ >= 7
+	struct sigaction	ill_oact, ill_act;
+	sigset_t		oset;
+#endif
+	static int trigger = 0;
+
+	if (trigger)
+		return;
+	trigger = 1;
+
+	OPENSSL_armcap_P = 0;
+
+#if __ARM_ARCH__ >= 7
+	sigfillset(&all_masked);
+	sigdelset(&all_masked, SIGILL);
+	sigdelset(&all_masked, SIGTRAP);
+	sigdelset(&all_masked, SIGFPE);
+	sigdelset(&all_masked, SIGBUS);
+	sigdelset(&all_masked, SIGSEGV);
+
+	memset(&ill_act, 0, sizeof(ill_act));
+	ill_act.sa_handler = ill_handler;
+	ill_act.sa_mask = all_masked;
+
+	sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
+	sigaction(SIGILL, &ill_act, &ill_oact);
+
+	if (sigsetjmp(ill_jmp, 1) == 0) {
+		_armv7_neon_probe();
+		OPENSSL_armcap_P |= ARMV7_NEON;
+		if (sigsetjmp(ill_jmp, 1) == 0) {
+			_armv8_pmull_probe();
+			OPENSSL_armcap_P |= ARMV8_PMULL | ARMV8_AES;
+		} else if (sigsetjmp(ill_jmp, 1) == 0) {
+			_armv8_aes_probe();
+			OPENSSL_armcap_P |= ARMV8_AES;
+		}
+		if (sigsetjmp(ill_jmp, 1) == 0) {
+			_armv8_sha1_probe();
+			OPENSSL_armcap_P |= ARMV8_SHA1;
+		}
+		if (sigsetjmp(ill_jmp, 1) == 0) {
+			_armv8_sha256_probe();
+			OPENSSL_armcap_P |= ARMV8_SHA256;
+		}
+	}
+
+	sigaction (SIGILL, &ill_oact, NULL);
+	sigprocmask(SIG_SETMASK, &oset, NULL);
+#endif
+}
diff --git a/crypto/armv4cpuid.S b/crypto/armv4cpuid.S
new file mode 100644
index 0000000..db0b54e
--- /dev/null
+++ b/crypto/armv4cpuid.S
@@ -0,0 +1,69 @@
+#include "arm_arch.h"
+
+.text
+#if defined(__thumb2__) && !defined(__APPLE__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#undef	__thumb2__
+#endif
+
+#if __ARM_ARCH__>=7
+.arch	armv7-a
+.fpu	neon
+
+.align	5
+.globl	_armv7_neon_probe
+.type	_armv7_neon_probe,%function
+_armv7_neon_probe:
+	vorr	q0,q0,q0
+	bx	lr
+.size	_armv7_neon_probe,.-_armv7_neon_probe
+
+.globl	_armv8_aes_probe
+.type	_armv8_aes_probe,%function
+_armv8_aes_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0xb0,0xff,0x00,0x03	@ aese.8	q0,q0
+#else
+.byte	0x00,0x03,0xb0,0xf3	@ aese.8	q0,q0
+#endif
+	bx	lr
+.size	_armv8_aes_probe,.-_armv8_aes_probe
+
+.globl	_armv8_sha1_probe
+.type	_armv8_sha1_probe,%function
+_armv8_sha1_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0x00,0xef,0x40,0x0c	@ sha1c.32	q0,q0,q0
+#else
+.byte	0x40,0x0c,0x00,0xf2	@ sha1c.32	q0,q0,q0
+#endif
+	bx	lr
+.size	_armv8_sha1_probe,.-_armv8_sha1_probe
+
+.globl	_armv8_sha256_probe
+.type	_armv8_sha256_probe,%function
+_armv8_sha256_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0x00,0xff,0x40,0x0c	@ sha256h.32	q0,q0,q0
+#else
+.byte	0x40,0x0c,0x00,0xf3	@ sha256h.32	q0,q0,q0
+#endif
+	bx	lr
+.size	_armv8_sha256_probe,.-_armv8_sha256_probe
+.globl	_armv8_pmull_probe
+.type	_armv8_pmull_probe,%function
+_armv8_pmull_probe:
+#if defined(__thumb2__) && !defined(__APPLE__)
+.byte	0xa0,0xef,0x00,0x0e	@ vmull.p64	q0,d0,d0
+#else
+.byte	0x00,0x0e,0xa0,0xf2	@ vmull.p64	q0,d0,d0
+#endif
+	bx	lr
+.size	_armv8_pmull_probe,.-_armv8_pmull_probe
+#endif
+
+.comm	OPENSSL_armcap_P,4,4
+.hidden	OPENSSL_armcap_P
diff --git a/crypto/asn1/a_bitstr.c b/crypto/asn1/a_bitstr.c
new file mode 100644
index 0000000..7ea3e12
--- /dev/null
+++ b/crypto/asn1/a_bitstr.c
@@ -0,0 +1,329 @@
+/* $OpenBSD: a_bitstr.c,v 1.41 2023/07/28 10:33:13 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+
+const ASN1_ITEM ASN1_BIT_STRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_BIT_STRING,
+	.sname = "ASN1_BIT_STRING",
+};
+
+ASN1_BIT_STRING *
+ASN1_BIT_STRING_new(void)
+{
+	return (ASN1_BIT_STRING *)ASN1_item_new(&ASN1_BIT_STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_BIT_STRING_new);
+
+void
+ASN1_BIT_STRING_free(ASN1_BIT_STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_BIT_STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_BIT_STRING_free);
+
+static void
+asn1_abs_clear_unused_bits(ASN1_BIT_STRING *abs)
+{
+	abs->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+}
+
+int
+asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits)
+{
+	if (unused_bits > 7)
+		return 0;
+
+	asn1_abs_clear_unused_bits(abs);
+
+	abs->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits;
+
+	return 1;
+}
+
+int
+ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
+{
+	return ASN1_STRING_set(x, d, len);
+}
+LCRYPTO_ALIAS(ASN1_BIT_STRING_set);
+
+int
+ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
+{
+	int w, v, iv;
+	unsigned char *c;
+
+	w = n/8;
+	v = 1 << (7 - (n & 0x07));
+	iv = ~v;
+	if (!value)
+		v = 0;
+
+	if (a == NULL)
+		return 0;
+
+	asn1_abs_clear_unused_bits(a);
+
+	if ((a->length < (w + 1)) || (a->data == NULL)) {
+		if (!value)
+			return(1); /* Don't need to set */
+		if ((c = recallocarray(a->data, a->length, w + 1, 1)) == NULL) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		a->data = c;
+		a->length = w + 1;
+	}
+	a->data[w] = ((a->data[w]) & iv) | v;
+	while ((a->length > 0) && (a->data[a->length - 1] == 0))
+		a->length--;
+
+	return (1);
+}
+LCRYPTO_ALIAS(ASN1_BIT_STRING_set_bit);
+
+int
+ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n)
+{
+	int w, v;
+
+	w = n / 8;
+	v = 1 << (7 - (n & 0x07));
+	if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
+		return (0);
+	return ((a->data[w] & v) != 0);
+}
+LCRYPTO_ALIAS(ASN1_BIT_STRING_get_bit);
+
+int
+i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
+{
+	int ret, j, bits, len;
+	unsigned char *p, *d;
+
+	if (a == NULL)
+		return (0);
+
+	if (a->length == INT_MAX)
+		return (0);
+
+	ret = a->length + 1;
+
+	if (pp == NULL)
+		return (ret);
+
+	len = a->length;
+
+	if (len > 0) {
+		if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
+			bits = (int)a->flags & 0x07;
+		} else {
+			j = 0;
+			for (; len > 0; len--) {
+				if (a->data[len - 1])
+					break;
+			}
+			if (len > 0)
+				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;
+
+	p= *pp;
+
+	*(p++) = (unsigned char)bits;
+	d = a->data;
+	if (len > 0) {
+		memcpy(p, d, len);
+		p += len;
+		p[-1] &= 0xff << bits;
+	}
+	*pp = p;
+	return (ret);
+}
+
+int
+c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs)
+{
+	ASN1_BIT_STRING *abs = NULL;
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	uint8_t unused_bits;
+	int ret = 0;
+
+	if (out_abs == NULL)
+		goto err;
+
+	if (*out_abs != NULL) {
+		ASN1_BIT_STRING_free(*out_abs);
+		*out_abs = NULL;
+	}
+
+	if (!CBS_get_u8(cbs, &unused_bits)) {
+		ASN1error(ASN1_R_STRING_TOO_SHORT);
+		goto err;
+	}
+
+	if (!CBS_stow(cbs, &data, &data_len))
+		goto err;
+	if (data_len > INT_MAX)
+		goto err;
+
+	if ((abs = ASN1_BIT_STRING_new()) == NULL)
+		goto err;
+
+	abs->data = data;
+	abs->length = (int)data_len;
+	data = NULL;
+
+	/*
+	 * We do this to preserve the settings. If we modify the settings,
+	 * via the _set_bit function, we will recalculate on output.
+	 */
+	if (!asn1_abs_set_unused_bits(abs, unused_bits)) {
+		ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+		goto err;
+	}
+	if (abs->length > 0)
+		abs->data[abs->length - 1] &= 0xff << unused_bits;
+
+	*out_abs = abs;
+	abs = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_BIT_STRING_free(abs);
+	freezero(data, data_len);
+
+	return ret;
+}
+
+ASN1_BIT_STRING *
+c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **out_abs, const unsigned char **pp, long len)
+{
+	ASN1_BIT_STRING *abs = NULL;
+	CBS content;
+
+	if (out_abs != NULL) {
+		ASN1_BIT_STRING_free(*out_abs);
+		*out_abs = NULL;
+	}
+
+	if (len < 0) {
+		ASN1error(ASN1_R_LENGTH_ERROR);
+		return NULL;
+	}
+
+	CBS_init(&content, *pp, len);
+
+	if (!c2i_ASN1_BIT_STRING_cbs(&abs, &content))
+		return NULL;
+
+	*pp = CBS_data(&content);
+
+	if (out_abs != NULL)
+		*out_abs = abs;
+
+	return abs;
+}
+
+int
+i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BIT_STRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_BIT_STRING);
+
+ASN1_BIT_STRING *
+d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_BIT_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_BIT_STRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_BIT_STRING);
diff --git a/crypto/asn1/a_enum.c b/crypto/asn1/a_enum.c
new file mode 100644
index 0000000..483fe1c
--- /dev/null
+++ b/crypto/asn1/a_enum.c
@@ -0,0 +1,393 @@
+/* $OpenBSD: a_enum.c,v 1.29 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bytestring.h"
+
+/*
+ * Code for ENUMERATED type: identical to INTEGER apart from a different tag.
+ * for comments on encoding see a_int.c
+ */
+
+const ASN1_ITEM ASN1_ENUMERATED_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_ENUMERATED,
+	.sname = "ASN1_ENUMERATED",
+};
+
+ASN1_ENUMERATED *
+ASN1_ENUMERATED_new(void)
+{
+	return (ASN1_ENUMERATED *)ASN1_item_new(&ASN1_ENUMERATED_it);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_new);
+
+static void
+asn1_aenum_clear(ASN1_ENUMERATED *aenum)
+{
+	freezero(aenum->data, aenum->length);
+
+	memset(aenum, 0, sizeof(*aenum));
+
+	aenum->type = V_ASN1_ENUMERATED;
+}
+
+void
+ASN1_ENUMERATED_free(ASN1_ENUMERATED *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_ENUMERATED_it);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_free);
+
+int
+ASN1_ENUMERATED_get_int64(int64_t *out_val, const ASN1_ENUMERATED *aenum)
+{
+	CBS cbs;
+
+	*out_val = 0;
+
+	if (aenum == NULL || aenum->length < 0)
+		return 0;
+
+	if (aenum->type != V_ASN1_ENUMERATED &&
+	    aenum->type != V_ASN1_NEG_ENUMERATED) {
+		ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
+		return 0;
+	}
+
+	CBS_init(&cbs, aenum->data, aenum->length);
+
+	return asn1_aint_get_int64(&cbs, (aenum->type == V_ASN1_NEG_ENUMERATED),
+	    out_val);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_get_int64);
+
+int
+ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *aenum, int64_t val)
+{
+	uint64_t uval;
+
+	asn1_aenum_clear(aenum);
+
+	uval = (uint64_t)val;
+
+	if (val < 0) {
+		aenum->type = V_ASN1_NEG_ENUMERATED;
+		uval = -uval;
+	}
+
+	return asn1_aint_set_uint64(uval, &aenum->data, &aenum->length);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_set_int64);
+
+long
+ASN1_ENUMERATED_get(const ASN1_ENUMERATED *aenum)
+{
+	int64_t val;
+
+	if (aenum == NULL)
+		return 0;
+	if (!ASN1_ENUMERATED_get_int64(&val, aenum))
+		return -1;
+	if (val < LONG_MIN || val > LONG_MAX) {
+		/* hmm... a bit ugly, return all ones */
+		return -1;
+	}
+
+	return (long)val;
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_get);
+
+int
+ASN1_ENUMERATED_set(ASN1_ENUMERATED *aenum, long val)
+{
+	return ASN1_ENUMERATED_set_int64(aenum, val);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_set);
+
+ASN1_ENUMERATED *
+BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai)
+{
+	ASN1_ENUMERATED *ret;
+	int len, j;
+
+	if (ai == NULL)
+		ret = ASN1_ENUMERATED_new();
+	else
+		ret = ai;
+	if (ret == NULL) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+	if (BN_is_negative(bn))
+		ret->type = V_ASN1_NEG_ENUMERATED;
+	else
+		ret->type = V_ASN1_ENUMERATED;
+	j = BN_num_bits(bn);
+	len = ((j == 0) ? 0 : ((j / 8) + 1));
+	if (ret->length < len + 4) {
+		unsigned char *new_data = realloc(ret->data, len + 4);
+		if (!new_data) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		ret->data = new_data;
+	}
+	ret->length = BN_bn2bin(bn, ret->data);
+
+	/* Correct zero case */
+	if (!ret->length) {
+		ret->data[0] = 0;
+		ret->length = 1;
+	}
+	return (ret);
+
+ err:
+	if (ret != ai)
+		ASN1_ENUMERATED_free(ret);
+	return (NULL);
+}
+LCRYPTO_ALIAS(BN_to_ASN1_ENUMERATED);
+
+BIGNUM *
+ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn)
+{
+	BIGNUM *ret;
+
+	if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+		ASN1error(ASN1_R_BN_LIB);
+	else if (ai->type == V_ASN1_NEG_ENUMERATED)
+		BN_set_negative(ret, 1);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_ENUMERATED_to_BN);
+
+/* Based on a_int.c: equivalent ENUMERATED functions */
+
+int
+i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a)
+{
+	int i, n = 0;
+	static const char h[] = "0123456789ABCDEF";
+	char buf[2];
+
+	if (a == NULL)
+		return (0);
+
+	if (a->length == 0) {
+		if (BIO_write(bp, "00", 2) != 2)
+			goto err;
+		n = 2;
+	} else {
+		for (i = 0; i < a->length; i++) {
+			if ((i != 0) && (i % 35 == 0)) {
+				if (BIO_write(bp, "\\\n", 2) != 2)
+					goto err;
+				n += 2;
+			}
+			buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+			buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+			if (BIO_write(bp, buf, 2) != 2)
+				goto err;
+			n += 2;
+		}
+	}
+	return (n);
+
+ err:
+	return (-1);
+}
+LCRYPTO_ALIAS(i2a_ASN1_ENUMERATED);
+
+int
+a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
+{
+	int ret = 0;
+	int i, j,k, m,n, again, bufsize;
+	unsigned char *s = NULL, *sp;
+	unsigned char *bufp;
+	int first = 1;
+	size_t num = 0, slen = 0;
+
+	bs->type = V_ASN1_ENUMERATED;
+
+	bufsize = BIO_gets(bp, buf, size);
+	for (;;) {
+		if (bufsize < 1)
+			goto err_sl;
+		i = bufsize;
+		if (buf[i-1] == '\n')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i-1] == '\r')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i - 1] == '\\') {
+			i--;
+			again = 1;
+		} else
+			again = 0;
+		buf[i] = '\0';
+		if (i < 2)
+			goto err_sl;
+
+		bufp = (unsigned char *)buf;
+		if (first) {
+			first = 0;
+			if ((bufp[0] == '0') && (buf[1] == '0')) {
+				bufp += 2;
+				i -= 2;
+			}
+		}
+		k = 0;
+		if (i % 2 != 0) {
+			ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
+			goto err;
+		}
+		i /= 2;
+		if (num + i > slen) {
+			sp = realloc(s, num + i);
+			if (sp == NULL) {
+				ASN1error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			s = sp;
+			slen = num + i;
+		}
+		for (j = 0; j < i; j++, k += 2) {
+			for (n = 0; n < 2; n++) {
+				m = bufp[k + n];
+				if ((m >= '0') && (m <= '9'))
+					m -= '0';
+				else if ((m >= 'a') && (m <= 'f'))
+					m = m - 'a' + 10;
+				else if ((m >= 'A') && (m <= 'F'))
+					m = m - 'A' + 10;
+				else {
+					ASN1error(ASN1_R_NON_HEX_CHARACTERS);
+					goto err;
+				}
+				s[num + j] <<= 4;
+				s[num + j] |= m;
+			}
+		}
+		num += i;
+		if (again)
+			bufsize = BIO_gets(bp, buf, size);
+		else
+			break;
+	}
+	bs->length = num;
+	bs->data = s;
+	return (1);
+
+ err_sl:
+	ASN1error(ASN1_R_SHORT_LINE);
+ err:
+	free(s);
+	return (ret);
+}
+LCRYPTO_ALIAS(a2i_ASN1_ENUMERATED);
+
+int
+c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs)
+{
+	ASN1_ENUMERATED *aenum = NULL;
+
+	if (out_aenum == NULL)
+		return 0;
+
+	if (*out_aenum != NULL) {
+		ASN1_INTEGER_free(*out_aenum);
+		*out_aenum = NULL;
+	}
+
+	if (!c2i_ASN1_INTEGER_cbs((ASN1_INTEGER **)&aenum, cbs))
+		return 0;
+
+	aenum->type = V_ASN1_ENUMERATED | (aenum->type & V_ASN1_NEG);
+	*out_aenum = aenum;
+
+	return 1;
+}
+
+int
+i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ENUMERATED_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_ENUMERATED);
+
+ASN1_ENUMERATED *
+d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, const unsigned char **in, long len)
+{
+	return (ASN1_ENUMERATED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_ENUMERATED_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_ENUMERATED);
diff --git a/crypto/asn1/a_int.c b/crypto/asn1/a_int.c
new file mode 100644
index 0000000..643ad2e
--- /dev/null
+++ b/crypto/asn1/a_int.c
@@ -0,0 +1,857 @@
+/* $OpenBSD: a_int.c,v 1.47 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+
+const ASN1_ITEM ASN1_INTEGER_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_INTEGER,
+	.sname = "ASN1_INTEGER",
+};
+
+ASN1_INTEGER *
+ASN1_INTEGER_new(void)
+{
+	return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_new);
+
+static void
+asn1_aint_clear(ASN1_INTEGER *aint)
+{
+	freezero(aint->data, aint->length);
+
+	memset(aint, 0, sizeof(*aint));
+
+	aint->type = V_ASN1_INTEGER;
+}
+
+void
+ASN1_INTEGER_free(ASN1_INTEGER *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_INTEGER_it);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_free);
+
+static int
+ASN1_INTEGER_valid(const ASN1_INTEGER *a)
+{
+	return (a != NULL && a->length >= 0);
+}
+
+ASN1_INTEGER *
+ASN1_INTEGER_dup(const ASN1_INTEGER *x)
+{
+	if (!ASN1_INTEGER_valid(x))
+		return NULL;
+
+	return ASN1_STRING_dup(x);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_dup);
+
+int
+ASN1_INTEGER_cmp(const ASN1_INTEGER *a, const ASN1_INTEGER *b)
+{
+	int ret = 1;
+
+	/* Compare sign, then content. */
+	if ((a->type & V_ASN1_NEG) == (b->type & V_ASN1_NEG))
+		ret = ASN1_STRING_cmp(a, b);
+
+	if ((a->type & V_ASN1_NEG) != 0)
+		return -ret;
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_cmp);
+
+int
+asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val)
+{
+	uint64_t val = 0;
+	uint8_t u8;
+
+	*out_val = 0;
+
+	while (CBS_len(cbs) > 0) {
+		if (!CBS_get_u8(cbs, &u8))
+			return 0;
+		if (val > (UINT64_MAX >> 8)) {
+			ASN1error(ASN1_R_TOO_LARGE);
+			return 0;
+		}
+		val = val << 8 | u8;
+	}
+
+	*out_val = val;
+
+	return 1;
+}
+
+int
+asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len)
+{
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	int started = 0;
+	uint8_t u8;
+	CBB cbb;
+	int i;
+	int ret = 0;
+
+	if (!CBB_init(&cbb, sizeof(long)))
+		goto err;
+
+	if (out_data == NULL || out_len == NULL)
+		goto err;
+	if (*out_data != NULL || *out_len != 0)
+		goto err;
+
+	for (i = sizeof(uint64_t) - 1; i >= 0; i--) {
+		u8 = (val >> (i * 8)) & 0xff;
+		if (!started && i != 0 && u8 == 0)
+			continue;
+		if (!CBB_add_u8(&cbb, u8))
+			goto err;
+		started = 1;
+	}
+
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+	if (data_len > INT_MAX)
+		goto err;
+
+	*out_data = data;
+	*out_len = (int)data_len;
+	data = NULL;
+
+	ret = 1;
+ err:
+	CBB_cleanup(&cbb);
+	freezero(data, data_len);
+
+	return ret;
+}
+
+int
+asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val)
+{
+	uint64_t val;
+
+	if (!asn1_aint_get_uint64(cbs, &val))
+		return 0;
+
+	if (negative) {
+		if (val > (uint64_t)INT64_MIN) {
+			ASN1error(ASN1_R_TOO_SMALL);
+			return 0;
+		}
+		*out_val = (int64_t)-val;
+	} else {
+		if (val > (uint64_t)INT64_MAX) {
+			ASN1error(ASN1_R_TOO_LARGE);
+			return 0;
+		}
+		*out_val = (int64_t)val;
+	}
+
+	return 1;
+}
+
+int
+ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint)
+{
+	uint64_t val;
+	CBS cbs;
+
+	*out_val = 0;
+
+	if (aint == NULL || aint->length < 0)
+		return 0;
+
+	if (aint->type == V_ASN1_NEG_INTEGER) {
+		ASN1error(ASN1_R_ILLEGAL_NEGATIVE_VALUE);
+		return 0;
+	}
+	if (aint->type != V_ASN1_INTEGER) {
+		ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
+		return 0;
+	}
+
+	CBS_init(&cbs, aint->data, aint->length);
+
+	if (!asn1_aint_get_uint64(&cbs, &val))
+		return 0;
+
+	*out_val = val;
+
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_get_uint64);
+
+int
+ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val)
+{
+	asn1_aint_clear(aint);
+
+	return asn1_aint_set_uint64(val, &aint->data, &aint->length);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_set_uint64);
+
+int
+ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint)
+{
+	CBS cbs;
+
+	*out_val = 0;
+
+	if (aint == NULL || aint->length < 0)
+		return 0;
+
+	if (aint->type != V_ASN1_INTEGER &&
+	    aint->type != V_ASN1_NEG_INTEGER) {
+		ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
+		return 0;
+	}
+
+	CBS_init(&cbs, aint->data, aint->length);
+
+	return asn1_aint_get_int64(&cbs, (aint->type == V_ASN1_NEG_INTEGER),
+	    out_val);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_get_int64);
+
+int
+ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val)
+{
+	uint64_t uval;
+
+	asn1_aint_clear(aint);
+
+	uval = (uint64_t)val;
+
+	if (val < 0) {
+		aint->type = V_ASN1_NEG_INTEGER;
+		uval = -uval;
+	}
+
+	return asn1_aint_set_uint64(uval, &aint->data, &aint->length);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_set_int64);
+
+long
+ASN1_INTEGER_get(const ASN1_INTEGER *aint)
+{
+	int64_t val;
+
+	if (aint == NULL)
+		return 0;
+	if (!ASN1_INTEGER_get_int64(&val, aint))
+		return -1;
+	if (val < LONG_MIN || val > LONG_MAX) {
+		/* hmm... a bit ugly, return all ones */
+		return -1;
+	}
+
+	return (long)val;
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_get);
+
+int
+ASN1_INTEGER_set(ASN1_INTEGER *aint, long val)
+{
+	return ASN1_INTEGER_set_int64(aint, val);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_set);
+
+ASN1_INTEGER *
+BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
+{
+	ASN1_INTEGER *ret;
+	int len, j;
+
+	if (ai == NULL)
+		ret = ASN1_INTEGER_new();
+	else
+		ret = ai;
+	if (ret == NULL) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+
+	if (!ASN1_INTEGER_valid(ret))
+		goto err;
+
+	if (BN_is_negative(bn))
+		ret->type = V_ASN1_NEG_INTEGER;
+	else
+		ret->type = V_ASN1_INTEGER;
+	j = BN_num_bits(bn);
+	len = ((j == 0) ? 0 : ((j / 8) + 1));
+	if (ret->length < len + 4) {
+		unsigned char *new_data = realloc(ret->data, len + 4);
+		if (!new_data) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		ret->data = new_data;
+	}
+	ret->length = BN_bn2bin(bn, ret->data);
+
+	/* Correct zero case */
+	if (!ret->length) {
+		ret->data[0] = 0;
+		ret->length = 1;
+	}
+	return (ret);
+
+ err:
+	if (ret != ai)
+		ASN1_INTEGER_free(ret);
+	return (NULL);
+}
+LCRYPTO_ALIAS(BN_to_ASN1_INTEGER);
+
+BIGNUM *
+ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
+{
+	BIGNUM *ret;
+
+	if (!ASN1_INTEGER_valid(ai))
+		return (NULL);
+
+	if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+		ASN1error(ASN1_R_BN_LIB);
+	else if (ai->type == V_ASN1_NEG_INTEGER)
+		BN_set_negative(ret, 1);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_INTEGER_to_BN);
+
+int
+i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a)
+{
+	int i, n = 0;
+	static const char h[] = "0123456789ABCDEF";
+	char buf[2];
+
+	if (a == NULL)
+		return (0);
+
+	if (a->type & V_ASN1_NEG) {
+		if (BIO_write(bp, "-", 1) != 1)
+			goto err;
+		n = 1;
+	}
+
+	if (a->length == 0) {
+		if (BIO_write(bp, "00", 2) != 2)
+			goto err;
+		n += 2;
+	} else {
+		for (i = 0; i < a->length; i++) {
+			if ((i != 0) && (i % 35 == 0)) {
+				if (BIO_write(bp, "\\\n", 2) != 2)
+					goto err;
+				n += 2;
+			}
+			buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+			buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+			if (BIO_write(bp, buf, 2) != 2)
+				goto err;
+			n += 2;
+		}
+	}
+	return (n);
+
+ err:
+	return (-1);
+}
+LCRYPTO_ALIAS(i2a_ASN1_INTEGER);
+
+int
+a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
+{
+	int ret = 0;
+	int i, j,k, m,n, again, bufsize;
+	unsigned char *s = NULL, *sp;
+	unsigned char *bufp;
+	int num = 0, slen = 0, first = 1;
+
+	bs->type = V_ASN1_INTEGER;
+
+	bufsize = BIO_gets(bp, buf, size);
+	for (;;) {
+		if (bufsize < 1)
+			goto err_sl;
+		i = bufsize;
+		if (buf[i - 1] == '\n')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i - 1] == '\r')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i - 1] == '\\') {
+			i--;
+			again = 1;
+		} else
+			again = 0;
+		buf[i] = '\0';
+		if (i < 2)
+			goto err_sl;
+
+		bufp = (unsigned char *)buf;
+		if (first) {
+			first = 0;
+			if ((bufp[0] == '0') && (buf[1] == '0')) {
+				bufp += 2;
+				i -= 2;
+			}
+		}
+		k = 0;
+		if (i % 2 != 0) {
+			ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
+			goto err;
+		}
+		i /= 2;
+		if (num + i > slen) {
+			if ((sp = recallocarray(s, slen, num + i, 1)) == NULL) {
+				ASN1error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			s = sp;
+			slen = num + i;
+		}
+		for (j = 0; j < i; j++, k += 2) {
+			for (n = 0; n < 2; n++) {
+				m = bufp[k + n];
+				if ((m >= '0') && (m <= '9'))
+					m -= '0';
+				else if ((m >= 'a') && (m <= 'f'))
+					m = m - 'a' + 10;
+				else if ((m >= 'A') && (m <= 'F'))
+					m = m - 'A' + 10;
+				else {
+					ASN1error(ASN1_R_NON_HEX_CHARACTERS);
+					goto err;
+				}
+				s[num + j] <<= 4;
+				s[num + j] |= m;
+			}
+		}
+		num += i;
+		if (again)
+			bufsize = BIO_gets(bp, buf, size);
+		else
+			break;
+	}
+	bs->length = num;
+	bs->data = s;
+	return (1);
+
+ err_sl:
+	ASN1error(ASN1_R_SHORT_LINE);
+ err:
+	free(s);
+	return (ret);
+}
+LCRYPTO_ALIAS(a2i_ASN1_INTEGER);
+
+static void
+asn1_aint_twos_complement(uint8_t *data, size_t data_len)
+{
+	uint8_t carry = 1;
+	ssize_t i;
+
+	for (i = data_len - 1; i >= 0; i--) {
+		data[i] = (data[i] ^ 0xff) + carry;
+		if (data[i] != 0)
+			carry = 0;
+	}
+}
+
+static int
+asn1_aint_keep_twos_padding(const uint8_t *data, size_t data_len)
+{
+	size_t i;
+
+	/*
+	 * If a two's complement value has a padding byte (0xff) and the rest
+	 * of the value is all zeros, the padding byte cannot be removed as when
+	 * converted from two's complement this becomes 0x01 (in the place of
+	 * the padding byte) followed by the same number of zero bytes.
+	 */
+	if (data_len <= 1 || data[0] != 0xff)
+		return 0;
+	for (i = 1; i < data_len; i++) {
+		if (data[i] != 0)
+			return 0;
+	}
+	return 1;
+}
+
+static int
+i2c_ASN1_INTEGER_cbb(ASN1_INTEGER *aint, CBB *cbb)
+{
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	uint8_t padding, val;
+	uint8_t msb;
+	CBS cbs;
+	int ret = 0;
+
+	if (aint->length < 0)
+		goto err;
+	if (aint->data == NULL && aint->length != 0)
+		goto err;
+
+	if ((aint->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED &&
+	    (aint->type & ~V_ASN1_NEG) != V_ASN1_INTEGER)
+		goto err;
+
+	CBS_init(&cbs, aint->data, aint->length);
+
+	/* Find the first non-zero byte. */
+	while (CBS_len(&cbs) > 0) {
+		if (!CBS_peek_u8(&cbs, &val))
+			goto err;
+		if (val != 0)
+			break;
+		if (!CBS_skip(&cbs, 1))
+			goto err;
+	}
+
+	/* A zero value is encoded as a single octet. */
+	if (CBS_len(&cbs) == 0) {
+		if (!CBB_add_u8(cbb, 0))
+			goto err;
+		goto done;
+	}
+
+	if (!CBS_stow(&cbs, &data, &data_len))
+		goto err;
+
+	if ((aint->type & V_ASN1_NEG) != 0)
+		asn1_aint_twos_complement(data, data_len);
+
+	/* Topmost bit indicates sign, padding is all zeros or all ones. */
+	msb = (data[0] >> 7);
+	padding = (msb - 1) & 0xff;
+
+	/* See if we need a padding octet to avoid incorrect sign. */
+	if (((aint->type & V_ASN1_NEG) == 0 && msb == 1) ||
+	    ((aint->type & V_ASN1_NEG) != 0 && msb == 0)) {
+		if (!CBB_add_u8(cbb, padding))
+			goto err;
+	}
+	if (!CBB_add_bytes(cbb, data, data_len))
+		goto err;
+
+ done:
+	ret = 1;
+
+ err:
+	freezero(data, data_len);
+
+	return ret;
+}
+
+int
+i2c_ASN1_INTEGER(ASN1_INTEGER *aint, unsigned char **pp)
+{
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	CBB cbb;
+	int ret = -3;
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+	if (!i2c_ASN1_INTEGER_cbb(aint, &cbb))
+		goto err;
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+	if (data_len > INT_MAX)
+		goto err;
+
+	if (pp != NULL) {
+		if ((uintptr_t)*pp > UINTPTR_MAX - data_len)
+			goto err;
+		memcpy(*pp, data, data_len);
+		*pp += data_len;
+	}
+
+	ret = data_len;
+
+ err:
+	freezero(data, data_len);
+	CBB_cleanup(&cbb);
+
+	return ret;
+}
+
+int
+c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs)
+{
+	ASN1_INTEGER *aint = NULL;
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	uint8_t padding, val;
+	uint8_t negative;
+	int ret = 0;
+
+	if (out_aint == NULL)
+		goto err;
+
+	if (*out_aint != NULL) {
+		ASN1_INTEGER_free(*out_aint);
+		*out_aint = NULL;
+	}
+
+	if (CBS_len(cbs) == 0) {
+		/* XXX INVALID ENCODING? */
+		ASN1error(ERR_R_ASN1_LENGTH_MISMATCH);
+		goto err;
+	}
+	if (!CBS_peek_u8(cbs, &val))
+		goto err;
+
+	/* Topmost bit indicates sign, padding is all zeros or all ones. */
+	negative = (val >> 7);
+	padding = ~(negative - 1) & 0xff;
+
+	/*
+	 * Ensure that the first 9 bits are not all zero or all one, as per
+	 * X.690 section 8.3.2. Remove the padding octet if possible.
+	 */
+	if (CBS_len(cbs) > 1 && val == padding) {
+		if (!asn1_aint_keep_twos_padding(CBS_data(cbs), CBS_len(cbs))) {
+			if (!CBS_get_u8(cbs, &padding))
+				goto err;
+			if (!CBS_peek_u8(cbs, &val))
+				goto err;
+			if ((val >> 7) == (padding >> 7)) {
+				/* XXX INVALID ENCODING? */
+				ASN1error(ERR_R_ASN1_LENGTH_MISMATCH);
+				goto err;
+			}
+		}
+	}
+
+	if (!CBS_stow(cbs, &data, &data_len))
+		goto err;
+	if (data_len > INT_MAX)
+		goto err;
+
+	if ((aint = ASN1_INTEGER_new()) == NULL)
+		goto err;
+
+	/*
+	 * Negative integers are handled as a separate type - convert from
+	 * two's complement for internal representation.
+	 */
+	if (negative) {
+		aint->type = V_ASN1_NEG_INTEGER;
+		asn1_aint_twos_complement(data, data_len);
+	}
+
+	aint->data = data;
+	aint->length = (int)data_len;
+	data = NULL;
+
+	*out_aint = aint;
+	aint = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+	freezero(data, data_len);
+
+	return ret;
+}
+
+ASN1_INTEGER *
+c2i_ASN1_INTEGER(ASN1_INTEGER **out_aint, const unsigned char **pp, long len)
+{
+	ASN1_INTEGER *aint = NULL;
+	CBS content;
+
+	if (out_aint != NULL) {
+		ASN1_INTEGER_free(*out_aint);
+		*out_aint = NULL;
+	}
+
+	if (len < 0) {
+		ASN1error(ASN1_R_LENGTH_ERROR);
+		return NULL;
+	}
+
+	CBS_init(&content, *pp, len);
+
+	if (!c2i_ASN1_INTEGER_cbs(&aint, &content))
+		return NULL;
+
+	*pp = CBS_data(&content);
+
+	if (out_aint != NULL)
+		*out_aint = aint;
+
+	return aint;
+}
+
+int
+i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_INTEGER_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_INTEGER);
+
+ASN1_INTEGER *
+d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len)
+{
+	return (ASN1_INTEGER *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_INTEGER_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_INTEGER);
+
+/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
+ * ASN1 integers: some broken software can encode a positive INTEGER
+ * with its MSB set as negative (it doesn't add a padding zero).
+ */
+
+ASN1_INTEGER *
+d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length)
+{
+	ASN1_INTEGER *ret = NULL;
+	const unsigned char *p;
+	unsigned char *s;
+	long len;
+	int inf, tag, xclass;
+	int i;
+
+	if ((a == NULL) || ((*a) == NULL)) {
+		if ((ret = ASN1_INTEGER_new()) == NULL)
+			return (NULL);
+	} else
+		ret = (*a);
+
+	if (!ASN1_INTEGER_valid(ret)) {
+		i = ERR_R_ASN1_LENGTH_MISMATCH;
+		goto err;
+	}
+
+	p = *pp;
+	inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+	if (inf & 0x80) {
+		i = ASN1_R_BAD_OBJECT_HEADER;
+		goto err;
+	}
+
+	if (tag != V_ASN1_INTEGER) {
+		i = ASN1_R_EXPECTING_AN_INTEGER;
+		goto err;
+	}
+
+	/* We must malloc stuff, even for 0 bytes otherwise it
+	 * signifies a missing NULL parameter. */
+	if (len < 0 || len > INT_MAX) {
+		i = ERR_R_ASN1_LENGTH_MISMATCH;
+		goto err;
+	}
+	s = malloc(len + 1);
+	if (s == NULL) {
+		i = ERR_R_MALLOC_FAILURE;
+		goto err;
+	}
+	ret->type = V_ASN1_INTEGER;
+	if (len) {
+		if ((*p == 0) && (len != 1)) {
+			p++;
+			len--;
+		}
+		memcpy(s, p, len);
+		p += len;
+	}
+
+	free(ret->data);
+	ret->data = s;
+	ret->length = (int)len;
+	if (a != NULL)
+		(*a) = ret;
+	*pp = p;
+	return (ret);
+
+ err:
+	ASN1error(i);
+	if (a == NULL || *a != ret)
+		ASN1_INTEGER_free(ret);
+	return (NULL);
+}
+LCRYPTO_ALIAS(d2i_ASN1_UINTEGER);
diff --git a/crypto/asn1/a_mbstr.c b/crypto/asn1/a_mbstr.c
new file mode 100644
index 0000000..f050f97
--- /dev/null
+++ b/crypto/asn1/a_mbstr.c
@@ -0,0 +1,449 @@
+/* $OpenBSD: a_mbstr.c,v 1.27 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+
+static int traverse_string(const unsigned char *p, int len, int inform,
+    int (*rfunc)(unsigned long value, void *in), void *arg);
+static int in_utf8(unsigned long value, void *arg);
+static int out_utf8(unsigned long value, void *arg);
+static int type_str(unsigned long value, void *arg);
+static int cpy_asc(unsigned long value, void *arg);
+static int cpy_bmp(unsigned long value, void *arg);
+static int cpy_univ(unsigned long value, void *arg);
+static int cpy_utf8(unsigned long value, void *arg);
+static int is_printable(unsigned long value);
+
+/* These functions take a string in UTF8, ASCII or multibyte form and
+ * a mask of permissible ASN1 string types. It then works out the minimal
+ * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
+ * and creates a string of the correct type with the supplied data.
+ * Yes this is horrible: it has to be :-(
+ * The 'ncopy' form checks minimum and maximum size limits too.
+ */
+
+int
+ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
+    int inform, unsigned long mask)
+{
+	return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
+}
+LCRYPTO_ALIAS(ASN1_mbstring_copy);
+
+int
+ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
+    int inform, unsigned long mask, long minsize, long maxsize)
+{
+	int str_type;
+	int ret;
+	char free_out;
+	int outform, outlen = 0;
+	ASN1_STRING *dest;
+	unsigned char *p;
+	int nchar;
+	int (*cpyfunc)(unsigned long, void *) = NULL;
+
+	if (len < 0)
+		len = strlen((const char *)in);
+	if (!mask)
+		mask = DIRSTRING_TYPE;
+
+	/* First do a string check and work out the number of characters */
+	switch (inform) {
+	case MBSTRING_BMP:
+		if (len & 1) {
+			ASN1error(ASN1_R_INVALID_BMPSTRING_LENGTH);
+			return -1;
+		}
+		nchar = len >> 1;
+		break;
+
+	case MBSTRING_UNIV:
+		if (len & 3) {
+			ASN1error(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+			return -1;
+		}
+		nchar = len >> 2;
+		break;
+
+	case MBSTRING_UTF8:
+		nchar = 0;
+		/* This counts the characters and does utf8 syntax checking */
+		ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
+		if (ret < 0) {
+			ASN1error(ASN1_R_INVALID_UTF8STRING);
+			return -1;
+		}
+		break;
+
+	case MBSTRING_ASC:
+		nchar = len;
+		break;
+
+	default:
+		ASN1error(ASN1_R_UNKNOWN_FORMAT);
+		return -1;
+	}
+
+	if ((minsize > 0) && (nchar < minsize)) {
+		ASN1error(ASN1_R_STRING_TOO_SHORT);
+		ERR_asprintf_error_data("minsize=%ld", minsize);
+		return -1;
+	}
+
+	if ((maxsize > 0) && (nchar > maxsize)) {
+		ASN1error(ASN1_R_STRING_TOO_LONG);
+		ERR_asprintf_error_data("maxsize=%ld", maxsize);
+		return -1;
+	}
+
+	/* Now work out minimal type (if any) */
+	if (traverse_string(in, len, inform, type_str, &mask) < 0) {
+		ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
+		return -1;
+	}
+
+
+	/* Now work out output format and string type */
+	outform = MBSTRING_ASC;
+	if (mask & B_ASN1_PRINTABLESTRING)
+		str_type = V_ASN1_PRINTABLESTRING;
+	else if (mask & B_ASN1_IA5STRING)
+		str_type = V_ASN1_IA5STRING;
+	else if (mask & B_ASN1_T61STRING)
+		str_type = V_ASN1_T61STRING;
+	else if (mask & B_ASN1_BMPSTRING) {
+		str_type = V_ASN1_BMPSTRING;
+		outform = MBSTRING_BMP;
+	} else if (mask & B_ASN1_UNIVERSALSTRING) {
+		str_type = V_ASN1_UNIVERSALSTRING;
+		outform = MBSTRING_UNIV;
+	} else {
+		str_type = V_ASN1_UTF8STRING;
+		outform = MBSTRING_UTF8;
+	}
+	if (!out)
+		return str_type;
+	if (*out) {
+		free_out = 0;
+		dest = *out;
+		if (dest->data) {
+			dest->length = 0;
+			free(dest->data);
+			dest->data = NULL;
+		}
+		dest->type = str_type;
+	} else {
+		free_out = 1;
+		dest = ASN1_STRING_type_new(str_type);
+		if (!dest) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			return -1;
+		}
+		*out = dest;
+	}
+	/* If both the same type just copy across */
+	if (inform == outform) {
+		if (!ASN1_STRING_set(dest, in, len)) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		return str_type;
+	}
+
+	/* Work out how much space the destination will need */
+	switch (outform) {
+	case MBSTRING_ASC:
+		outlen = nchar;
+		cpyfunc = cpy_asc;
+		break;
+
+	case MBSTRING_BMP:
+		outlen = nchar << 1;
+		cpyfunc = cpy_bmp;
+		break;
+
+	case MBSTRING_UNIV:
+		outlen = nchar << 2;
+		cpyfunc = cpy_univ;
+		break;
+
+	case MBSTRING_UTF8:
+		outlen = 0;
+		if (traverse_string(in, len, inform, out_utf8, &outlen) < 0) {
+			ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
+			goto err;
+		}
+		cpyfunc = cpy_utf8;
+		break;
+	}
+	if (!(p = malloc(outlen + 1))) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	dest->length = outlen;
+	dest->data = p;
+	p[outlen] = 0;
+	traverse_string(in, len, inform, cpyfunc, &p);
+	return str_type;
+
+ err:
+	if (free_out) {
+		ASN1_STRING_free(dest);
+		*out = NULL;
+	}
+	return -1;
+}
+LCRYPTO_ALIAS(ASN1_mbstring_ncopy);
+
+/* This function traverses a string and passes the value of each character
+ * to an optional function along with a void * argument.
+ */
+
+static int
+traverse_string(const unsigned char *p, int len, int inform,
+    int (*rfunc)(unsigned long value, void *in), void *arg)
+{
+	unsigned long value;
+	int ret;
+
+	while (len) {
+		switch (inform) {
+		case MBSTRING_ASC:
+			value = *p++;
+			len--;
+			break;
+		case MBSTRING_BMP:
+			value = *p++ << 8;
+			value |= *p++;
+			/* BMP is explicitly defined to not support surrogates */
+			if (UNICODE_IS_SURROGATE(value))
+				return -1;
+			len -= 2;
+			break;
+		case MBSTRING_UNIV:
+			value = (unsigned long)*p++ << 24;
+			value |= *p++ << 16;
+			value |= *p++ << 8;
+			value |= *p++;
+			if (value > UNICODE_MAX || UNICODE_IS_SURROGATE(value))
+				return -1;
+			len -= 4;
+			break;
+		default:
+			ret = UTF8_getc(p, len, &value);
+			if (ret < 0)
+				return -1;
+			len -= ret;
+			p += ret;
+			break;
+		}
+		if (rfunc) {
+			ret = rfunc(value, arg);
+			if (ret <= 0)
+				return ret;
+		}
+	}
+	return 1;
+}
+
+/* Various utility functions for traverse_string */
+
+/* Just count number of characters */
+
+static int
+in_utf8(unsigned long value, void *arg)
+{
+	int *nchar;
+
+	nchar = arg;
+	(*nchar)++;
+	return 1;
+}
+
+/* Determine size of output as a UTF8 String */
+
+static int
+out_utf8(unsigned long value, void *arg)
+{
+	int *outlen;
+	int ret;
+
+	outlen = arg;
+	ret = UTF8_putc(NULL, -1, value);
+	if (ret < 0)
+		return ret;
+	*outlen += ret;
+	return 1;
+}
+
+/* Determine the "type" of a string: check each character against a
+ * supplied "mask".
+ */
+
+static int
+type_str(unsigned long value, void *arg)
+{
+	unsigned long types;
+
+	types = *((unsigned long *)arg);
+	if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
+		types &= ~B_ASN1_PRINTABLESTRING;
+	if ((types & B_ASN1_IA5STRING) && (value > 127))
+		types &= ~B_ASN1_IA5STRING;
+	if ((types & B_ASN1_T61STRING) && (value > 0xff))
+		types &= ~B_ASN1_T61STRING;
+	if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
+		types &= ~B_ASN1_BMPSTRING;
+	if (!types)
+		return -1;
+	*((unsigned long *)arg) = types;
+	return 1;
+}
+
+/* Copy one byte per character ASCII like strings */
+
+static int
+cpy_asc(unsigned long value, void *arg)
+{
+	unsigned char **p, *q;
+
+	p = arg;
+	q = *p;
+	*q = value;
+	(*p)++;
+	return 1;
+}
+
+/* Copy two byte per character BMPStrings */
+
+static int
+cpy_bmp(unsigned long value, void *arg)
+{
+	unsigned char **p, *q;
+
+	p = arg;
+	q = *p;
+	*q++ = (value >> 8) & 0xff;
+	*q = value & 0xff;
+	*p += 2;
+	return 1;
+}
+
+/* Copy four byte per character UniversalStrings */
+
+static int
+cpy_univ(unsigned long value, void *arg)
+{
+	unsigned char **p, *q;
+
+	p = arg;
+	q = *p;
+	*q++ = (value >> 24) & 0xff;
+	*q++ = (value >> 16) & 0xff;
+	*q++ = (value >> 8) & 0xff;
+	*q = value & 0xff;
+	*p += 4;
+	return 1;
+}
+
+/* Copy to a UTF8String */
+
+static int
+cpy_utf8(unsigned long value, void *arg)
+{
+	unsigned char **p;
+
+	int ret;
+	p = arg;
+	/* We already know there is enough room so pass 0xff as the length */
+	ret = UTF8_putc(*p, 0xff, value);
+	*p += ret;
+	return 1;
+}
+
+/* Return 1 if the character is permitted in a PrintableString */
+static int
+is_printable(unsigned long value)
+{
+	int ch;
+
+	if (value > 0x7f)
+		return 0;
+	ch = (int)value;
+
+	/* Note: we can't use 'isalnum' because certain accented
+	 * characters may count as alphanumeric in some environments.
+	 */
+	if ((ch >= 'a') && (ch <= 'z'))
+		return 1;
+	if ((ch >= 'A') && (ch <= 'Z'))
+		return 1;
+	if ((ch >= '0') && (ch <= '9'))
+		return 1;
+	if ((ch == ' ') || strchr("'()+,-./:=?", ch))
+		return 1;
+	return 0;
+}
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c
new file mode 100644
index 0000000..a87e243
--- /dev/null
+++ b/crypto/asn1/a_object.c
@@ -0,0 +1,676 @@
+/* $OpenBSD: a_object.c,v 1.51 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+const ASN1_ITEM ASN1_OBJECT_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_OBJECT,
+	.sname = "ASN1_OBJECT",
+};
+
+ASN1_OBJECT *
+ASN1_OBJECT_new(void)
+{
+	ASN1_OBJECT *a;
+
+	if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	a->flags = ASN1_OBJECT_FLAG_DYNAMIC;
+
+	return a;
+}
+LCRYPTO_ALIAS(ASN1_OBJECT_new);
+
+void
+ASN1_OBJECT_free(ASN1_OBJECT *a)
+{
+	if (a == NULL)
+		return;
+	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
+		free((void *)a->sn);
+		free((void *)a->ln);
+		a->sn = a->ln = NULL;
+	}
+	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
+		freezero((void *)a->data, a->length);
+		a->data = NULL;
+		a->length = 0;
+	}
+	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
+		free(a);
+}
+LCRYPTO_ALIAS(ASN1_OBJECT_free);
+
+ASN1_OBJECT *
+ASN1_OBJECT_create(int nid, unsigned char *data, int len,
+    const char *sn, const char *ln)
+{
+	ASN1_OBJECT o;
+
+	o.sn = sn;
+	o.ln = ln;
+	o.data = data;
+	o.nid = nid;
+	o.length = len;
+	o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+	    ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+	return (OBJ_dup(&o));
+}
+LCRYPTO_ALIAS(ASN1_OBJECT_create);
+
+static int
+oid_add_arc(CBB *cbb, uint64_t arc)
+{
+	int started = 0;
+	uint8_t val;
+	int i;
+
+	for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) {
+		val = (arc >> (i * 7)) & 0x7f;
+		if (!started && i != 0 && val == 0)
+			continue;
+		if (i > 0)
+			val |= 0x80;
+		if (!CBB_add_u8(cbb, val))
+			return 0;
+		started = 1;
+	}
+
+	return 1;
+}
+
+static int
+oid_parse_arc(CBS *cbs, uint64_t *out_arc)
+{
+	uint64_t arc = 0;
+	uint8_t val;
+
+	do {
+		if (!CBS_get_u8(cbs, &val))
+			return 0;
+		if (arc == 0 && val == 0x80)
+			return 0;
+		if (out_arc != NULL && arc > (UINT64_MAX >> 7))
+			return 0;
+		arc = (arc << 7) | (val & 0x7f);
+	} while (val & 0x80);
+
+	if (out_arc != NULL)
+		*out_arc = arc;
+
+	return 1;
+}
+
+static int
+oid_add_arc_txt(CBB *cbb, uint64_t arc, int first)
+{
+	const char *fmt = ".%llu";
+	char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */
+	int n;
+
+	if (first)
+		fmt = "%llu";
+	n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc);
+	if (n < 0 || (size_t)n >= sizeof(s))
+		return 0;
+	if (!CBB_add_bytes(cbb, s, n))
+		return 0;
+
+	return 1;
+}
+
+static int
+oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first)
+{
+	uint64_t arc = 0;
+	int digits = 0;
+	uint8_t val;
+
+	if (!first) {
+		if (!CBS_get_u8(cbs, &val))
+			return 0;
+		if ((*separator == 0 && val != '.' && val != ' ') ||
+		    (*separator != 0 && val != *separator)) {
+			ASN1error(ASN1_R_INVALID_SEPARATOR);
+			return 0;
+		}
+		*separator = val;
+	}
+
+	while (CBS_len(cbs) > 0) {
+		if (!CBS_peek_u8(cbs, &val))
+			return 0;
+		if (val == '.' || val == ' ')
+			break;
+
+		if (!CBS_get_u8(cbs, &val))
+			return 0;
+		if (val < '0' || val > '9') {
+			/* For the first arc we treat this as the separator. */
+			if (first) {
+				ASN1error(ASN1_R_INVALID_SEPARATOR);
+				return 0;
+			}
+			ASN1error(ASN1_R_INVALID_DIGIT);
+			return 0;
+		}
+		val -= '0';
+
+		if (digits > 0 && arc == 0 && val == 0) {
+			ASN1error(ASN1_R_INVALID_NUMBER);
+			return 0;
+		}
+		digits++;
+
+		if (arc > UINT64_MAX / 10) {
+			ASN1error(ASN1_R_TOO_LONG);
+			return 0;
+		}
+		arc = arc * 10 + val;
+	}
+
+	if (digits < 1) {
+		ASN1error(ASN1_R_INVALID_NUMBER);
+		return 0;
+	}
+
+	*out_arc = arc;
+
+	return 1;
+}
+
+static int
+a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs)
+{
+	uint64_t arc, si1, si2;
+	char separator = 0;
+
+	if (!oid_parse_arc_txt(cbs, &si1, &separator, 1))
+		return 0;
+
+	if (CBS_len(cbs) == 0) {
+		ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
+		return 0;
+	}
+
+	if (!oid_parse_arc_txt(cbs, &si2, &separator, 0))
+		return 0;
+
+	/*
+	 * X.690 section 8.19 - the first two subidentifiers are encoded as
+	 * (x * 40) + y, with x being limited to [0,1,2]. The second
+	 * subidentifier cannot exceed 39 for x < 2.
+	 */
+	if (si1 > 2) {
+		ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
+		return 0;
+	}
+	if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) {
+		ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
+		return 0;
+	}
+	arc = si1 * 40 + si2;
+
+	if (!oid_add_arc(cbb, arc))
+		return 0;
+
+	while (CBS_len(cbs) > 0) {
+		if (!oid_parse_arc_txt(cbs, &arc, &separator, 0))
+			return 0;
+		if (!oid_add_arc(cbb, arc))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb)
+{
+	uint64_t arc, si1, si2;
+
+	/*
+	 * X.690 section 8.19 - the first two subidentifiers are encoded as
+	 * (x * 40) + y, with x being limited to [0,1,2].
+	 */
+	if (!oid_parse_arc(cbs, &arc))
+		return 0;
+	if ((si1 = arc / 40) > 2)
+		si1 = 2;
+	si2 = arc - si1 * 40;
+
+	if (!oid_add_arc_txt(cbb, si1, 1))
+		return 0;
+	if (!oid_add_arc_txt(cbb, si2, 0))
+		return 0;
+
+	while (CBS_len(cbs) > 0) {
+		if (!oid_parse_arc(cbs, &arc))
+			return 0;
+		if (!oid_add_arc_txt(cbb, arc, 0))
+			return 0;
+	}
+
+	/* NUL terminate. */
+	if (!CBB_add_u8(cbb, 0))
+		return 0;
+
+	return 1;
+}
+
+int
+a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len)
+{
+	uint8_t *data = NULL;
+	size_t data_len;
+	CBS cbs;
+	CBB cbb;
+	int ret = 0;
+
+	memset(&cbb, 0, sizeof(cbb));
+
+	if (in_len == -1)
+		in_len = strlen(in);
+	if (in_len <= 0)
+		goto err;
+
+	CBS_init(&cbs, in, in_len);
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+	if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
+		goto err;
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	if (data_len > INT_MAX)
+		goto err;
+
+	if (out != NULL) {
+		if (out_len <= 0 || (size_t)out_len < data_len) {
+			ASN1error(ASN1_R_BUFFER_TOO_SMALL);
+			goto err;
+		}
+		memcpy(out, data, data_len);
+	}
+
+	ret = (int)data_len;
+
+ err:
+	CBB_cleanup(&cbb);
+	free(data);
+
+	return ret;
+}
+LCRYPTO_ALIAS(a2d_ASN1_OBJECT);
+
+static int
+i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb)
+{
+	CBS cbs;
+
+	CBS_init(&cbs, aobj->data, aobj->length);
+
+	return c2a_ASN1_OBJECT(&cbs, cbb);
+}
+
+static int
+i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name)
+{
+	const char *name;
+	int nid;
+
+	*out_name = NULL;
+
+	if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
+		return 0;
+
+	if ((name = OBJ_nid2ln(nid)) == NULL)
+		name = OBJ_nid2sn(nid);
+	if (name == NULL)
+		return 0;
+
+	*out_name = name;
+
+	if (!CBB_add_bytes(cbb, name, strlen(name)))
+		return 0;
+
+	/* NUL terminate. */
+	if (!CBB_add_u8(cbb, 0))
+		return 0;
+
+	return 1;
+}
+
+static int
+i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name)
+{
+	const char *name;
+
+	if (!no_name) {
+		if (i2t_ASN1_OBJECT_name(aobj, cbb, &name))
+			return 1;
+		if (name != NULL)
+			return 0;
+	}
+	return i2t_ASN1_OBJECT_oid(aobj, cbb);
+}
+
+int
+i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name)
+{
+	uint8_t *data = NULL;
+	size_t data_len;
+	CBB cbb;
+	int ret = 0;
+
+	if (buf_len < 0)
+		return 0;
+	if (buf_len > 0)
+		buf[0] = '\0';
+
+	if (aobj == NULL || aobj->data == NULL)
+		return 0;
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+	if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name))
+		goto err;
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	ret = strlcpy(buf, data, buf_len);
+ err:
+	CBB_cleanup(&cbb);
+	free(data);
+
+	return ret;
+}
+
+int
+i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj)
+{
+	return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0);
+}
+LCRYPTO_ALIAS(i2t_ASN1_OBJECT);
+
+ASN1_OBJECT *
+t2i_ASN1_OBJECT_internal(const char *oid)
+{
+	ASN1_OBJECT *aobj = NULL;
+	uint8_t *data = NULL;
+	size_t data_len;
+	CBB cbb;
+	CBS cbs;
+
+	memset(&cbb, 0, sizeof(cbb));
+
+	CBS_init(&cbs, oid, strlen(oid));
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+	if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
+		goto err;
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	if (data_len > INT_MAX)
+		goto err;
+
+	if ((aobj = ASN1_OBJECT_new()) == NULL)
+		goto err;
+
+	aobj->data = data;
+	aobj->length = (int)data_len;
+	aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+	data = NULL;
+
+ err:
+	CBB_cleanup(&cbb);
+	free(data);
+
+	return aobj;
+}
+
+int
+i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj)
+{
+	uint8_t *data = NULL;
+	size_t data_len;
+	CBB cbb;
+	int ret = -1;
+
+	if (aobj == NULL || aobj->data == NULL)
+		return BIO_write(bp, "NULL", 4);
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+	if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) {
+		ret = BIO_write(bp, "", 9);
+		goto err;
+	}
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	ret = BIO_write(bp, data, strlen(data));
+
+ err:
+	CBB_cleanup(&cbb);
+	free(data);
+
+	return ret;
+}
+LCRYPTO_ALIAS(i2a_ASN1_OBJECT);
+
+int
+c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content)
+{
+	ASN1_OBJECT *aobj = NULL;
+	uint8_t *data = NULL;
+	size_t data_len;
+	CBS cbs;
+
+	if (out_aobj == NULL)
+		goto err;
+
+	if (*out_aobj != NULL) {
+		ASN1_OBJECT_free(*out_aobj);
+		*out_aobj = NULL;
+	}
+
+	/* Parse and validate OID encoding per X.690 8.19.2. */
+	CBS_dup(content, &cbs);
+	if (CBS_len(&cbs) == 0) {
+		ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
+		goto err;
+	}
+	while (CBS_len(&cbs) > 0) {
+		if (!oid_parse_arc(&cbs, NULL)) {
+			ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
+			goto err;
+		}
+	}
+
+	if (!CBS_stow(content, &data, &data_len))
+		goto err;
+
+	if (data_len > INT_MAX)
+		goto err;
+
+	if ((aobj = ASN1_OBJECT_new()) == NULL)
+		goto err;
+
+	aobj->data = data;
+	aobj->length = (int)data_len; /* XXX - change length to size_t. */
+	aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+
+	*out_aobj = aobj;
+
+	return 1;
+
+ err:
+	ASN1_OBJECT_free(aobj);
+	free(data);
+
+	return 0;
+}
+
+ASN1_OBJECT *
+c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len)
+{
+	ASN1_OBJECT *aobj = NULL;
+	CBS content;
+
+	if (out_aobj != NULL) {
+		ASN1_OBJECT_free(*out_aobj);
+		*out_aobj = NULL;
+	}
+
+	if (len < 0) {
+		ASN1error(ASN1_R_LENGTH_ERROR);
+		return NULL;
+	}
+
+	CBS_init(&content, *pp, len);
+
+	if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
+		return NULL;
+
+	*pp = CBS_data(&content);
+
+	if (out_aobj != NULL)
+		*out_aobj = aobj;
+
+	return aobj;
+}
+
+int
+i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
+{
+	unsigned char *p;
+	int objsize;
+
+	if ((a == NULL) || (a->data == NULL))
+		return (0);
+
+	objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
+	if (pp == NULL)
+		return objsize;
+
+	p = *pp;
+	ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
+	memcpy(p, a->data, a->length);
+	p += a->length;
+
+	*pp = p;
+	return (objsize);
+}
+LCRYPTO_ALIAS(i2d_ASN1_OBJECT);
+
+ASN1_OBJECT *
+d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length)
+{
+	ASN1_OBJECT *aobj = NULL;
+	uint32_t tag_number;
+	CBS cbs, content;
+
+	if (out_aobj != NULL) {
+		ASN1_OBJECT_free(*out_aobj);
+		*out_aobj = NULL;
+	}
+
+	if (length < 0) {
+		ASN1error(ASN1_R_LENGTH_ERROR);
+		return NULL;
+	}
+
+	CBS_init(&cbs, *pp, length);
+
+	if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) {
+		ASN1error(ASN1_R_BAD_OBJECT_HEADER);
+		return NULL;
+	}
+	if (tag_number != V_ASN1_OBJECT) {
+		ASN1error(ASN1_R_EXPECTING_AN_OBJECT);
+		return NULL;
+	}
+
+	if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
+		return NULL;
+
+	*pp = CBS_data(&cbs);
+
+	if (out_aobj != NULL)
+		*out_aobj = aobj;
+
+	return aobj;
+}
+LCRYPTO_ALIAS(d2i_ASN1_OBJECT);
diff --git a/crypto/asn1/a_octet.c b/crypto/asn1/a_octet.c
new file mode 100644
index 0000000..47eae5a
--- /dev/null
+++ b/crypto/asn1/a_octet.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: a_octet.c,v 1.12 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+
+const ASN1_ITEM ASN1_OCTET_STRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_OCTET_STRING,
+	.sname = "ASN1_OCTET_STRING",
+};
+
+ASN1_OCTET_STRING *
+ASN1_OCTET_STRING_new(void)
+{
+	return (ASN1_OCTET_STRING *)ASN1_item_new(&ASN1_OCTET_STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_OCTET_STRING_new);
+
+void
+ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_OCTET_STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_OCTET_STRING_free);
+
+
+ASN1_OCTET_STRING *
+ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
+{
+	return ASN1_STRING_dup(x);
+}
+LCRYPTO_ALIAS(ASN1_OCTET_STRING_dup);
+
+int
+ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
+{
+	return ASN1_STRING_cmp(a, b);
+}
+LCRYPTO_ALIAS(ASN1_OCTET_STRING_cmp);
+
+int
+ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
+{
+	return ASN1_STRING_set(x, d, len);
+}
+LCRYPTO_ALIAS(ASN1_OCTET_STRING_set);
+
+int
+i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_OCTET_STRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_OCTET_STRING);
+
+ASN1_OCTET_STRING *
+d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_OCTET_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_OCTET_STRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_OCTET_STRING);
diff --git a/crypto/asn1/a_pkey.c b/crypto/asn1/a_pkey.c
new file mode 100644
index 0000000..6e715d4
--- /dev/null
+++ b/crypto/asn1/a_pkey.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: a_pkey.c,v 1.6 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+EVP_PKEY *
+d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, long length)
+{
+	const unsigned char *p = *pp;
+	EVP_PKEY *ret;
+
+	if ((a == NULL) || (*a == NULL)) {
+		if ((ret = EVP_PKEY_new()) == NULL) {
+			ASN1error(ERR_R_EVP_LIB);
+			return (NULL);
+		}
+	} else {
+		ret = *a;
+#ifndef OPENSSL_NO_ENGINE
+		ENGINE_finish(ret->engine);
+		ret->engine = NULL;
+#endif
+	}
+
+	if (!EVP_PKEY_set_type(ret, type)) {
+		ASN1error(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+		goto err;
+	}
+
+	if (!ret->ameth->old_priv_decode ||
+	    !ret->ameth->old_priv_decode(ret, pp, length)) {
+		if (ret->ameth->priv_decode) {
+			PKCS8_PRIV_KEY_INFO *p8 = NULL;
+			*pp = p; /* XXX */
+			p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, pp, length);
+			if (!p8)
+				goto err;
+			EVP_PKEY_free(ret);
+			ret = EVP_PKCS82PKEY(p8);
+			PKCS8_PRIV_KEY_INFO_free(p8);
+		} else {
+			ASN1error(ERR_R_ASN1_LIB);
+			goto err;
+		}
+	}
+	if (a != NULL)
+		(*a) = ret;
+	return (ret);
+
+ err:
+	if (a == NULL || *a != ret)
+		EVP_PKEY_free(ret);
+	return (NULL);
+}
+
+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 = i2d_PKCS8_PRIV_KEY_INFO(p8, pp);
+		PKCS8_PRIV_KEY_INFO_free(p8);
+		return ret;
+	}
+	ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+	return (-1);
+}
+
+/* This works like d2i_PrivateKey() except it automatically works out the type */
+
+EVP_PKEY *
+d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, long length)
+{
+	STACK_OF(ASN1_TYPE) *inkey;
+	const unsigned char *p;
+	int keytype;
+
+	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 input is surrounded by an ASN1 SEQUENCE.
+	 */
+	inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length);
+	/* 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)
+		keytype = EVP_PKEY_DSA;
+	else if (sk_ASN1_TYPE_num(inkey) == 4)
+		keytype = EVP_PKEY_EC;
+	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, pp, length);
+		EVP_PKEY *ret;
+
+		sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+		if (!p8) {
+			ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+			return NULL;
+		}
+		ret = EVP_PKCS82PKEY(p8);
+		PKCS8_PRIV_KEY_INFO_free(p8);
+		if (a) {
+			*a = ret;
+		}
+		return ret;
+	} else
+		keytype = EVP_PKEY_RSA;
+	sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
+	return d2i_PrivateKey(keytype, a, pp, length);
+}
diff --git a/crypto/asn1/a_print.c b/crypto/asn1/a_print.c
new file mode 100644
index 0000000..5c03087
--- /dev/null
+++ b/crypto/asn1/a_print.c
@@ -0,0 +1,127 @@
+/* $OpenBSD: a_print.c,v 1.13 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+int
+ASN1_PRINTABLE_type(const unsigned char *s, int len)
+{
+	int c;
+	int ia5 = 0;
+	int t61 = 0;
+
+	if (len <= 0)
+		len = -1;
+	if (s == NULL)
+		return (V_ASN1_PRINTABLESTRING);
+
+	while (len-- > 0 && *s != '\0') {
+		c= *(s++);
+		if (!(((c >= 'a') && (c <= 'z')) ||
+		    ((c >= 'A') && (c <= 'Z')) ||
+		    (c == ' ') ||
+		    ((c >= '0') && (c <= '9')) ||
+		    (c == ' ') || (c == '\'') ||
+		    (c == '(') || (c == ')') ||
+		    (c == '+') || (c == ',') ||
+		    (c == '-') || (c == '.') ||
+		    (c == '/') || (c == ':') ||
+		    (c == '=') || (c == '?')))
+			ia5 = 1;
+		if (c & 0x80)
+			t61 = 1;
+	}
+	if (t61)
+		return (V_ASN1_T61STRING);
+	if (ia5)
+		return (V_ASN1_IA5STRING);
+	return (V_ASN1_PRINTABLESTRING);
+}
+LCRYPTO_ALIAS(ASN1_PRINTABLE_type);
+
+int
+ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
+{
+	int i;
+	unsigned char *p;
+
+	if (s->type != V_ASN1_UNIVERSALSTRING)
+		return (0);
+	if ((s->length % 4) != 0)
+		return (0);
+	p = s->data;
+	for (i = 0; i < s->length; i += 4) {
+		if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
+			break;
+		else
+			p += 4;
+	}
+	if (i < s->length)
+		return (0);
+	p = s->data;
+	for (i = 3; i < s->length; i += 4) {
+		*(p++) = s->data[i];
+	}
+	*(p) = '\0';
+	s->length /= 4;
+	s->type = ASN1_PRINTABLE_type(s->data, s->length);
+	return (1);
+}
+LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_to_string);
diff --git a/crypto/asn1/a_pubkey.c b/crypto/asn1/a_pubkey.c
new file mode 100644
index 0000000..5e022d3
--- /dev/null
+++ b/crypto/asn1/a_pubkey.c
@@ -0,0 +1,160 @@
+/* $OpenBSD: a_pubkey.c,v 1.6 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_EC
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+EVP_PKEY *
+d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, long length)
+{
+	EVP_PKEY *ret;
+
+	if ((a == NULL) || (*a == NULL)) {
+		if ((ret = EVP_PKEY_new()) == NULL) {
+			ASN1error(ERR_R_EVP_LIB);
+			return (NULL);
+		}
+	} else
+		ret = *a;
+
+	if (!EVP_PKEY_set_type(ret, type)) {
+		ASN1error(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	switch (EVP_PKEY_id(ret)) {
+#ifndef OPENSSL_NO_RSA
+	case EVP_PKEY_RSA:
+		if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) ==
+		    NULL) {
+			ASN1error(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_DSA
+	case EVP_PKEY_DSA:
+		if (!d2i_DSAPublicKey(&(ret->pkey.dsa), pp, length)) {
+			ASN1error(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		break;
+#endif
+#ifndef OPENSSL_NO_EC
+	case EVP_PKEY_EC:
+		if (!o2i_ECPublicKey(&(ret->pkey.ec), pp, length)) {
+			ASN1error(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		break;
+#endif
+	default:
+		ASN1error(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE);
+		goto err;
+		/* break; */
+	}
+	if (a != NULL)
+		(*a) = ret;
+	return (ret);
+
+ err:
+	if (a == NULL || *a != ret)
+		EVP_PKEY_free(ret);
+	return (NULL);
+}
+
+int
+i2d_PublicKey(EVP_PKEY *a, unsigned char **pp)
+{
+	switch (a->type) {
+#ifndef OPENSSL_NO_RSA
+	case EVP_PKEY_RSA:
+		return (i2d_RSAPublicKey(a->pkey.rsa, pp));
+#endif
+#ifndef OPENSSL_NO_DSA
+	case EVP_PKEY_DSA:
+		return (i2d_DSAPublicKey(a->pkey.dsa, pp));
+#endif
+#ifndef OPENSSL_NO_EC
+	case EVP_PKEY_EC:
+		return (i2o_ECPublicKey(a->pkey.ec, pp));
+#endif
+	default:
+		ASN1error(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+		return (-1);
+	}
+}
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
new file mode 100644
index 0000000..17213cb
--- /dev/null
+++ b/crypto/asn1/a_strex.c
@@ -0,0 +1,603 @@
+/* $OpenBSD: a_strex.c,v 1.34 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+#include "charmap.h"
+
+/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
+ * Enhanced string and name printing routines handling
+ * multibyte characters, RFC2253 and a host of other
+ * options.
+ */
+
+#define CHARTYPE_BS_ESC		(ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
+
+#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
+		  ASN1_STRFLGS_ESC_QUOTE | \
+		  ASN1_STRFLGS_ESC_CTRL | \
+		  ASN1_STRFLGS_ESC_MSB)
+
+
+/* Three IO functions for sending data to memory, a BIO and
+ * and a FILE pointer.
+ */
+static int
+send_bio_chars(void *arg, const void *buf, int len)
+{
+	if (!arg)
+		return 1;
+	if (BIO_write(arg, buf, len) != len)
+		return 0;
+	return 1;
+}
+
+static int
+send_fp_chars(void *arg, const void *buf, int len)
+{
+	if (!arg)
+		return 1;
+	if (fwrite(buf, 1, (size_t)len, arg) != (size_t)len)
+		return 0;
+	return 1;
+}
+
+typedef int char_io(void *arg, const void *buf, int len);
+
+/* This function handles display of
+ * strings, one character at a time.
+ * It is passed an unsigned long for each
+ * character because it could come from 2 or even
+ * 4 byte forms.
+ */
+
+static int
+do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
+    char_io *io_ch, void *arg)
+{
+	unsigned char chflgs, chtmp;
+	char tmphex[sizeof(long) * 2 + 3];
+
+	if (c > 0xffffffffL)
+		return -1;
+	if (c > 0xffff) {
+		snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+		if (!io_ch(arg, tmphex, 10))
+			return -1;
+		return 10;
+	}
+	if (c > 0xff) {
+		snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
+		if (!io_ch(arg, tmphex, 6))
+			return -1;
+		return 6;
+	}
+	chtmp = (unsigned char)c;
+	if (chtmp > 0x7f)
+		chflgs = flags & ASN1_STRFLGS_ESC_MSB;
+	else
+		chflgs = char_type[chtmp] & flags;
+	if (chflgs & CHARTYPE_BS_ESC) {
+		/* If we don't escape with quotes, signal we need quotes */
+		if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
+			if (do_quotes)
+				*do_quotes = 1;
+			if (!io_ch(arg, &chtmp, 1))
+				return -1;
+			return 1;
+		}
+		if (!io_ch(arg, "\\", 1))
+			return -1;
+		if (!io_ch(arg, &chtmp, 1))
+			return -1;
+		return 2;
+	}
+	if (chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
+		snprintf(tmphex, sizeof tmphex, "\\%02X", chtmp);
+		if (!io_ch(arg, tmphex, 3))
+			return -1;
+		return 3;
+	}
+	/* If we get this far and do any escaping at all must escape
+	 * the escape character itself: backslash.
+	 */
+	if (chtmp == '\\' && flags & ESC_FLAGS) {
+		if (!io_ch(arg, "\\\\", 2))
+			return -1;
+		return 2;
+	}
+	if (!io_ch(arg, &chtmp, 1))
+		return -1;
+	return 1;
+}
+
+#define BUF_TYPE_WIDTH_MASK	0x7
+#define BUF_TYPE_CONVUTF8	0x8
+
+/* This function sends each character in a buffer to
+ * do_esc_char(). It interprets the content formats
+ * and converts to or from UTF8 as appropriate.
+ */
+
+static int
+do_buf(unsigned char *buf, int buflen, int type, unsigned char flags,
+    char *quotes, char_io *io_ch, void *arg)
+{
+	int i, outlen, len;
+	unsigned char orflags, *p, *q;
+	unsigned long c;
+
+	p = buf;
+	q = buf + buflen;
+	outlen = 0;
+	while (p != q) {
+		if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
+			orflags = CHARTYPE_FIRST_ESC_2253;
+		else
+			orflags = 0;
+		switch (type & BUF_TYPE_WIDTH_MASK) {
+		case 4:
+			c = ((unsigned long)*p++) << 24;
+			c |= ((unsigned long)*p++) << 16;
+			c |= ((unsigned long)*p++) << 8;
+			c |= *p++;
+			if (c > UNICODE_MAX || UNICODE_IS_SURROGATE(c))
+				return -1;
+			break;
+
+		case 2:
+			c = ((unsigned long)*p++) << 8;
+			c |= *p++;
+			if (UNICODE_IS_SURROGATE(c))
+				return -1;
+			break;
+
+		case 1:
+			c = *p++;
+			break;
+
+		case 0:
+			i = UTF8_getc(p, q - p, &c);
+			if (i < 0)
+				return -1;	/* Invalid UTF8String */
+			p += i;
+			break;
+		default:
+			return -1;		/* invalid width */
+		}
+		if (p == q && flags & ASN1_STRFLGS_ESC_2253)
+			orflags = CHARTYPE_LAST_ESC_2253;
+		if (type & BUF_TYPE_CONVUTF8) {
+			unsigned char utfbuf[6];
+			int utflen;
+
+			utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
+			if (utflen < 0)
+				return -1;
+			for (i = 0; i < utflen; i++) {
+				/* We don't need to worry about setting orflags correctly
+				 * because if utflen==1 its value will be correct anyway
+				 * otherwise each character will be > 0x7f and so the
+				 * character will never be escaped on first and last.
+				 */
+				len = do_esc_char(utfbuf[i],
+				    (unsigned char)(flags | orflags), quotes,
+				    io_ch, arg);
+				if (len < 0)
+					return -1;
+				outlen += len;
+			}
+		} else {
+			len = do_esc_char(c, (unsigned char)(flags | orflags),
+			    quotes, io_ch, arg);
+			if (len < 0)
+				return -1;
+			outlen += len;
+		}
+	}
+	return outlen;
+}
+
+/* This function hex dumps a buffer of characters */
+
+static int
+do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
+{
+	static const char hexdig[] = "0123456789ABCDEF";
+	unsigned char *p, *q;
+	char hextmp[2];
+	if (arg) {
+		p = buf;
+		q = buf + buflen;
+		while (p != q) {
+			hextmp[0] = hexdig[*p >> 4];
+			hextmp[1] = hexdig[*p & 0xf];
+			if (!io_ch(arg, hextmp, 2))
+				return -1;
+			p++;
+		}
+	}
+	return buflen << 1;
+}
+
+/* "dump" a string. This is done when the type is unknown,
+ * or the flags request it. We can either dump the content
+ * octets or the entire DER encoding. This uses the RFC2253
+ * #01234 format.
+ */
+
+static int
+do_dump(unsigned long lflags, char_io *io_ch, void *arg, const ASN1_STRING *str)
+{
+	/* Placing the ASN1_STRING in a temp ASN1_TYPE allows
+	 * the DER encoding to readily obtained
+	 */
+	ASN1_TYPE t;
+	unsigned char *der_buf, *p;
+	int outlen, der_len;
+
+	if (!io_ch(arg, "#", 1))
+		return -1;
+	/* If we don't dump DER encoding just dump content octets */
+	if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
+		outlen = do_hex_dump(io_ch, arg, str->data, str->length);
+		if (outlen < 0)
+			return -1;
+		return outlen + 1;
+	}
+	t.type = str->type;
+	t.value.ptr = (char *)str;
+	der_len = i2d_ASN1_TYPE(&t, NULL);
+	der_buf = malloc(der_len);
+	if (!der_buf)
+		return -1;
+	p = der_buf;
+	i2d_ASN1_TYPE(&t, &p);
+	outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
+	free(der_buf);
+	if (outlen < 0)
+		return -1;
+	return outlen + 1;
+}
+
+/* This is the main function, print out an
+ * ASN1_STRING taking note of various escape
+ * and display options. Returns number of
+ * characters written or -1 if an error
+ * occurred.
+ */
+
+static int
+do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
+    const ASN1_STRING *str)
+{
+	int outlen, len;
+	int type;
+	char quotes;
+	unsigned char flags;
+
+	quotes = 0;
+	/* Keep a copy of escape flags */
+	flags = (unsigned char)(lflags & ESC_FLAGS);
+	type = str->type;
+	outlen = 0;
+
+	if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
+		const char *tagname;
+		tagname = ASN1_tag2str(type);
+		outlen += strlen(tagname);
+		if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
+			return -1;
+		outlen++;
+	}
+
+	/* Decide what to do with type, either dump content or display it */
+
+	if (lflags & ASN1_STRFLGS_DUMP_ALL) {
+		/* Dump everything. */
+		type = -1;
+	} else if (lflags & ASN1_STRFLGS_IGNORE_TYPE) {
+		/* Ignore the string type. */
+		type = 1;
+	} else {
+		/* Else determine width based on type. */
+		type = asn1_tag2charwidth(type);
+		if (type == -1 && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
+			type = 1;
+	}
+
+	if (type == -1) {
+		len = do_dump(lflags, io_ch, arg, str);
+		if (len < 0)
+			return -1;
+		outlen += len;
+		return outlen;
+	}
+
+	if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
+		/* Note: if string is UTF8 and we want
+		 * to convert to UTF8 then we just interpret
+		 * it as 1 byte per character to avoid converting
+		 * twice.
+		 */
+		if (!type)
+			type = 1;
+		else
+			type |= BUF_TYPE_CONVUTF8;
+	}
+
+	len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL);
+	if (len < 0)
+		return -1;
+	outlen += len;
+	if (quotes)
+		outlen += 2;
+	if (!arg)
+		return outlen;
+	if (quotes && !io_ch(arg, "\"", 1))
+		return -1;
+	if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
+		return -1;
+	if (quotes && !io_ch(arg, "\"", 1))
+		return -1;
+	return outlen;
+}
+
+/* Used for line indenting: print 'indent' spaces */
+
+static int
+do_indent(char_io *io_ch, void *arg, int indent)
+{
+	int i;
+	for (i = 0; i < indent; i++)
+		if (!io_ch(arg, " ", 1))
+			return 0;
+	return 1;
+}
+
+#define FN_WIDTH_LN	25
+#define FN_WIDTH_SN	10
+
+static int
+do_name_ex(char_io *io_ch, void *arg, const X509_NAME *n, int indent,
+    unsigned long flags)
+{
+	int i, prev = -1, orflags, cnt;
+	int fn_opt, fn_nid;
+	ASN1_OBJECT *fn;
+	ASN1_STRING *val;
+	X509_NAME_ENTRY *ent;
+	char objtmp[80];
+	const char *objbuf;
+	int outlen, len;
+	char *sep_dn, *sep_mv, *sep_eq;
+	int sep_dn_len, sep_mv_len, sep_eq_len;
+
+	if (indent < 0)
+		indent = 0;
+	outlen = indent;
+	if (!do_indent(io_ch, arg, indent))
+		return -1;
+
+	switch (flags & XN_FLAG_SEP_MASK) {
+	case XN_FLAG_SEP_MULTILINE:
+		sep_dn = "\n";
+		sep_dn_len = 1;
+		sep_mv = " + ";
+		sep_mv_len = 3;
+		break;
+
+	case XN_FLAG_SEP_COMMA_PLUS:
+		sep_dn = ",";
+		sep_dn_len = 1;
+		sep_mv = "+";
+		sep_mv_len = 1;
+		indent = 0;
+		break;
+
+	case XN_FLAG_SEP_CPLUS_SPC:
+		sep_dn = ", ";
+		sep_dn_len = 2;
+		sep_mv = " + ";
+		sep_mv_len = 3;
+		indent = 0;
+		break;
+
+	case XN_FLAG_SEP_SPLUS_SPC:
+		sep_dn = "; ";
+		sep_dn_len = 2;
+		sep_mv = " + ";
+		sep_mv_len = 3;
+		indent = 0;
+		break;
+
+	default:
+		return -1;
+	}
+
+	if (flags & XN_FLAG_SPC_EQ) {
+		sep_eq = " = ";
+		sep_eq_len = 3;
+	} else {
+		sep_eq = "=";
+		sep_eq_len = 1;
+	}
+
+	fn_opt = flags & XN_FLAG_FN_MASK;
+
+	cnt = X509_NAME_entry_count(n);
+	for (i = 0; i < cnt; i++) {
+		if (flags & XN_FLAG_DN_REV)
+			ent = X509_NAME_get_entry(n, cnt - i - 1);
+		else
+			ent = X509_NAME_get_entry(n, i);
+		if (prev != -1) {
+			if (prev == X509_NAME_ENTRY_set(ent)) {
+				if (!io_ch(arg, sep_mv, sep_mv_len))
+					return -1;
+				outlen += sep_mv_len;
+			} else {
+				if (!io_ch(arg, sep_dn, sep_dn_len))
+					return -1;
+				outlen += sep_dn_len;
+				if (!do_indent(io_ch, arg, indent))
+					return -1;
+				outlen += indent;
+			}
+		}
+		prev = X509_NAME_ENTRY_set(ent);
+		fn = X509_NAME_ENTRY_get_object(ent);
+		val = X509_NAME_ENTRY_get_data(ent);
+		fn_nid = OBJ_obj2nid(fn);
+		if (fn_opt != XN_FLAG_FN_NONE) {
+			int objlen, fld_len;
+			if ((fn_opt == XN_FLAG_FN_OID) ||
+			    (fn_nid == NID_undef)) {
+				OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+				fld_len = 0; /* XXX: what should this be? */
+				objbuf = objtmp;
+			} else {
+				if (fn_opt == XN_FLAG_FN_SN) {
+					fld_len = FN_WIDTH_SN;
+					objbuf = OBJ_nid2sn(fn_nid);
+				} else if (fn_opt == XN_FLAG_FN_LN) {
+					fld_len = FN_WIDTH_LN;
+					objbuf = OBJ_nid2ln(fn_nid);
+				} else {
+					fld_len = 0; /* XXX: what should this be? */
+					objbuf = "";
+				}
+			}
+			objlen = strlen(objbuf);
+			if (!io_ch(arg, objbuf, objlen))
+				return -1;
+			if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
+				if (!do_indent(io_ch, arg, fld_len - objlen))
+					return -1;
+				outlen += fld_len - objlen;
+			}
+			if (!io_ch(arg, sep_eq, sep_eq_len))
+				return -1;
+			outlen += objlen + sep_eq_len;
+		}
+		/* If the field name is unknown then fix up the DER dump
+		 * flag. We might want to limit this further so it will
+ 		 * DER dump on anything other than a few 'standard' fields.
+		 */
+		if ((fn_nid == NID_undef) &&
+		    (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
+			orflags = ASN1_STRFLGS_DUMP_ALL;
+		else
+			orflags = 0;
+
+		len = do_print_ex(io_ch, arg, flags | orflags, val);
+		if (len < 0)
+			return -1;
+		outlen += len;
+	}
+	return outlen;
+}
+
+/* Wrappers round the main functions */
+
+int
+X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent,
+    unsigned long flags)
+{
+	if (flags == XN_FLAG_COMPAT)
+		return X509_NAME_print(out, nm, indent);
+	return do_name_ex(send_bio_chars, out, nm, indent, flags);
+}
+
+int
+X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent,
+    unsigned long flags)
+{
+	if (flags == XN_FLAG_COMPAT) {
+		BIO *btmp;
+		int ret;
+		btmp = BIO_new_fp(fp, BIO_NOCLOSE);
+		if (!btmp)
+			return -1;
+		ret = X509_NAME_print(btmp, nm, indent);
+		BIO_free(btmp);
+		return ret;
+	}
+	return do_name_ex(send_fp_chars, fp, nm, indent, flags);
+}
+
+int
+ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags)
+{
+	return do_print_ex(send_bio_chars, out, flags, str);
+}
+LCRYPTO_ALIAS(ASN1_STRING_print_ex);
+
+int
+ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, unsigned long flags)
+{
+	return do_print_ex(send_fp_chars, fp, flags, str);
+}
+LCRYPTO_ALIAS(ASN1_STRING_print_ex_fp);
diff --git a/crypto/asn1/a_string.c b/crypto/asn1/a_string.c
new file mode 100644
index 0000000..ec492e7
--- /dev/null
+++ b/crypto/asn1/a_string.c
@@ -0,0 +1,450 @@
+/* $OpenBSD: a_string.c,v 1.17 2023/08/15 18:05:15 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+
+ASN1_STRING *
+ASN1_STRING_new(void)
+{
+	return ASN1_STRING_type_new(V_ASN1_OCTET_STRING);
+}
+LCRYPTO_ALIAS(ASN1_STRING_new);
+
+ASN1_STRING *
+ASN1_STRING_type_new(int type)
+{
+	ASN1_STRING *astr;
+
+	if ((astr = calloc(1, sizeof(ASN1_STRING))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	astr->type = type;
+
+	return astr;
+}
+LCRYPTO_ALIAS(ASN1_STRING_type_new);
+
+static void
+ASN1_STRING_clear(ASN1_STRING *astr)
+{
+	if (!(astr->flags & ASN1_STRING_FLAG_NDEF))
+		freezero(astr->data, astr->length);
+
+	astr->flags &= ~ASN1_STRING_FLAG_NDEF;
+	astr->data = NULL;
+	astr->length = 0;
+}
+
+void
+ASN1_STRING_free(ASN1_STRING *astr)
+{
+	if (astr == NULL)
+		return;
+
+	ASN1_STRING_clear(astr);
+
+	free(astr);
+}
+LCRYPTO_ALIAS(ASN1_STRING_free);
+
+int
+ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
+{
+	int cmp;
+
+	if (a == NULL || b == NULL)
+		return -1;
+	if ((cmp = (a->length - b->length)) != 0)
+		return cmp;
+	if (a->length != 0) {
+		if ((cmp = memcmp(a->data, b->data, a->length)) != 0)
+			return cmp;
+	}
+
+	return a->type - b->type;
+}
+LCRYPTO_ALIAS(ASN1_STRING_cmp);
+
+int
+ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *src)
+{
+	if (src == NULL)
+		return 0;
+
+	if (!ASN1_STRING_set(dst, src->data, src->length))
+		return 0;
+
+	dst->type = src->type;
+	dst->flags = src->flags & ~ASN1_STRING_FLAG_NDEF;
+
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_STRING_copy);
+
+ASN1_STRING *
+ASN1_STRING_dup(const ASN1_STRING *src)
+{
+	ASN1_STRING *astr;
+
+	if (src == NULL)
+		return NULL;
+
+	if ((astr = ASN1_STRING_new()) == NULL)
+		return NULL;
+	if (!ASN1_STRING_copy(astr, src)) {
+		ASN1_STRING_free(astr);
+		return NULL;
+	}
+	return astr;
+}
+LCRYPTO_ALIAS(ASN1_STRING_dup);
+
+int
+ASN1_STRING_set(ASN1_STRING *astr, const void *_data, int len)
+{
+	const char *data = _data;
+
+	if (len == -1) {
+		size_t slen;
+
+		if (data == NULL)
+			return 0;
+
+		if ((slen = strlen(data)) > INT_MAX)
+			return 0;
+
+		len = (int)slen;
+	}
+
+	ASN1_STRING_clear(astr);
+
+	if (len < 0 || len >= INT_MAX)
+		return 0;
+
+	if ((astr->data = calloc(1, len + 1)) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	astr->length = len;
+
+	if (data != NULL) {
+		memcpy(astr->data, data, len);
+		astr->data[len] = '\0';
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_STRING_set);
+
+void
+ASN1_STRING_set0(ASN1_STRING *astr, void *data, int len)
+{
+	ASN1_STRING_clear(astr);
+
+	astr->data = data;
+	astr->length = len;
+}
+LCRYPTO_ALIAS(ASN1_STRING_set0);
+
+int
+ASN1_STRING_length(const ASN1_STRING *astr)
+{
+	return astr->length;
+}
+LCRYPTO_ALIAS(ASN1_STRING_length);
+
+void
+ASN1_STRING_length_set(ASN1_STRING *astr, int len)
+{
+	/* This is dangerous and unfixable. */
+	astr->length = len;
+}
+LCRYPTO_ALIAS(ASN1_STRING_length_set);
+
+int
+ASN1_STRING_type(const ASN1_STRING *astr)
+{
+	return astr->type;
+}
+LCRYPTO_ALIAS(ASN1_STRING_type);
+
+unsigned char *
+ASN1_STRING_data(ASN1_STRING *astr)
+{
+	return astr->data;
+}
+LCRYPTO_ALIAS(ASN1_STRING_data);
+
+const unsigned char *
+ASN1_STRING_get0_data(const ASN1_STRING *astr)
+{
+	return astr->data;
+}
+LCRYPTO_ALIAS(ASN1_STRING_get0_data);
+
+int
+ASN1_STRING_print(BIO *bp, const ASN1_STRING *astr)
+{
+	int i, n;
+	char buf[80];
+	const char *p;
+
+	if (astr == NULL)
+		return 0;
+
+	n = 0;
+	p = (const char *)astr->data;
+	for (i = 0; i < astr->length; i++) {
+		if ((p[i] > '~') || ((p[i] < ' ') &&
+		    (p[i] != '\n') && (p[i] != '\r')))
+			buf[n] = '.';
+		else
+			buf[n] = p[i];
+		n++;
+		if (n >= 80) {
+			if (BIO_write(bp, buf, n) <= 0)
+				return 0;
+			n = 0;
+		}
+	}
+	if (n > 0) {
+		if (BIO_write(bp, buf, n) <= 0)
+			return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_STRING_print);
+
+/*
+ * Utility function: convert any string type to UTF8, returns number of bytes
+ * in output string or a negative error code
+ */
+int
+ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in)
+{
+	ASN1_STRING *astr = NULL;
+	int mbflag;
+	int ret = -1;
+
+	/*
+	 * XXX We can't fail on *out != NULL here since things like haproxy and
+	 * grpc pass in a pointer to an uninitialized pointer on the stack.
+	 */
+	if (out == NULL)
+		goto err;
+
+	if (in == NULL)
+		goto err;
+
+	if ((mbflag = asn1_tag2charwidth(in->type)) == -1)
+		goto err;
+
+	mbflag |= MBSTRING_FLAG;
+
+	if ((ret = ASN1_mbstring_copy(&astr, in->data, in->length, mbflag,
+	    B_ASN1_UTF8STRING)) < 0)
+		goto err;
+
+	*out = astr->data;
+	ret = astr->length;
+
+	astr->data = NULL;
+	astr->length = 0;
+
+ err:
+	ASN1_STRING_free(astr);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_STRING_to_UTF8);
+
+int
+i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *astr, int type)
+{
+	int i, n = 0;
+	static const char h[] = "0123456789ABCDEF";
+	char buf[2];
+
+	if (astr == NULL)
+		return 0;
+
+	if (astr->length == 0) {
+		if (BIO_write(bp, "0", 1) != 1)
+			goto err;
+		n = 1;
+	} else {
+		for (i = 0; i < astr->length; i++) {
+			if ((i != 0) && (i % 35 == 0)) {
+				if (BIO_write(bp, "\\\n", 2) != 2)
+					goto err;
+				n += 2;
+			}
+			buf[0] = h[((unsigned char)astr->data[i] >> 4) & 0x0f];
+			buf[1] = h[((unsigned char)astr->data[i]) & 0x0f];
+			if (BIO_write(bp, buf, 2) != 2)
+				goto err;
+			n += 2;
+		}
+	}
+	return n;
+
+ err:
+	return -1;
+}
+LCRYPTO_ALIAS(i2a_ASN1_STRING);
+
+int
+a2i_ASN1_STRING(BIO *bp, ASN1_STRING *astr, char *buf, int size)
+{
+	int ret = 0;
+	int i, j, k, m, n, again, bufsize;
+	unsigned char *s = NULL, *sp;
+	unsigned char *bufp;
+	int first = 1;
+	size_t num = 0, slen = 0;
+
+	bufsize = BIO_gets(bp, buf, size);
+	for (;;) {
+		if (bufsize < 1) {
+			if (first)
+				break;
+			else
+				goto err_sl;
+		}
+		first = 0;
+
+		i = bufsize;
+		if (buf[i-1] == '\n')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i-1] == '\r')
+			buf[--i] = '\0';
+		if (i == 0)
+			goto err_sl;
+		if (buf[i - 1] == '\\') {
+			i--;
+			again = 1;
+		} else
+			again = 0;
+		buf[i] = '\0';
+		if (i < 2)
+			goto err_sl;
+
+		bufp = (unsigned char *)buf;
+
+		k = 0;
+		if (i % 2 != 0) {
+			ASN1error(ASN1_R_ODD_NUMBER_OF_CHARS);
+			goto err;
+		}
+		i /= 2;
+		if (num + i > slen) {
+			sp = realloc(s, num + i);
+			if (sp == NULL) {
+				ASN1error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			s = sp;
+			slen = num + i;
+		}
+		for (j = 0; j < i; j++, k += 2) {
+			for (n = 0; n < 2; n++) {
+				m = bufp[k + n];
+				if ((m >= '0') && (m <= '9'))
+					m -= '0';
+				else if ((m >= 'a') && (m <= 'f'))
+					m = m - 'a' + 10;
+				else if ((m >= 'A') && (m <= 'F'))
+					m = m - 'A' + 10;
+				else {
+					ASN1error(ASN1_R_NON_HEX_CHARACTERS);
+					goto err;
+				}
+				s[num + j] <<= 4;
+				s[num + j] |= m;
+			}
+		}
+		num += i;
+		if (again)
+			bufsize = BIO_gets(bp, buf, size);
+		else
+			break;
+	}
+	astr->length = num;
+	astr->data = s;
+
+	return 1;
+
+ err_sl:
+	ASN1error(ASN1_R_SHORT_LINE);
+ err:
+	free(s);
+
+	return ret;
+}
+LCRYPTO_ALIAS(a2i_ASN1_STRING);
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
new file mode 100644
index 0000000..2542119
--- /dev/null
+++ b/crypto/asn1/a_strnid.c
@@ -0,0 +1,463 @@
+/* $OpenBSD: a_strnid.c,v 1.27 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
+
+static ASN1_STRING_TABLE *stable_get(int nid);
+static void st_free(ASN1_STRING_TABLE *tbl);
+static int sk_table_cmp(const ASN1_STRING_TABLE * const *a,
+    const ASN1_STRING_TABLE * const *b);
+
+
+/*
+ * This is the global mask for the mbstring functions: this is used to
+ * mask out certain types (such as BMPString and UTF8String) because
+ * certain software (e.g. Netscape) has problems with them.
+ */
+
+static unsigned long global_mask = B_ASN1_UTF8STRING;
+
+void
+ASN1_STRING_set_default_mask(unsigned long mask)
+{
+	global_mask = mask;
+}
+LCRYPTO_ALIAS(ASN1_STRING_set_default_mask);
+
+unsigned long
+ASN1_STRING_get_default_mask(void)
+{
+	return global_mask;
+}
+LCRYPTO_ALIAS(ASN1_STRING_get_default_mask);
+
+/*
+ * 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.
+ */
+
+int
+ASN1_STRING_set_default_mask_asc(const char *p)
+{
+	unsigned long mask;
+	char *end;
+	int save_errno;
+
+	if (strncmp(p, "MASK:", 5) == 0) {
+		if (p[5] == '\0')
+			return 0;
+		save_errno = errno;
+		errno = 0;
+		mask = strtoul(p + 5, &end, 0);
+		if (errno == ERANGE && mask == ULONG_MAX)
+			return 0;
+		errno = save_errno;
+		if (*end != '\0')
+			return 0;
+	} else if (strcmp(p, "nombstr") == 0)
+		mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
+	else if (strcmp(p, "pkix") == 0)
+		mask = ~((unsigned long)B_ASN1_T61STRING);
+	else if (strcmp(p, "utf8only") == 0)
+		mask = B_ASN1_UTF8STRING;
+	else if (strcmp(p, "default") == 0)
+		mask = 0xFFFFFFFFL;
+	else
+		return 0;
+	ASN1_STRING_set_default_mask(mask);
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_STRING_set_default_mask_asc);
+
+/*
+ * The following function generates an ASN1_STRING based on limits in a table.
+ * Frequently the types and length of an ASN1_STRING are restricted by a
+ * corresponding OID. For example certificates and certificate requests.
+ */
+
+ASN1_STRING *
+ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen,
+    int inform, int nid)
+{
+	ASN1_STRING_TABLE *tbl;
+	ASN1_STRING *str = NULL;
+	unsigned long mask;
+	int ret;
+
+	if (out == NULL)
+		out = &str;
+	tbl = ASN1_STRING_TABLE_get(nid);
+	if (tbl != NULL) {
+		mask = tbl->mask;
+		if ((tbl->flags & STABLE_NO_MASK) == 0)
+			mask &= global_mask;
+		ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
+		    tbl->minsize, tbl->maxsize);
+	} else
+		ret = ASN1_mbstring_copy(out, in, inlen, inform,
+		    DIRSTRING_TYPE & global_mask);
+	if (ret <= 0)
+		return NULL;
+	return *out;
+}
+LCRYPTO_ALIAS(ASN1_STRING_set_by_NID);
+
+/*
+ * Now the tables and helper functions for the string table:
+ */
+
+/* size limits: this stuff is taken straight from RFC3280 */
+
+#define ub_name				32768
+#define ub_common_name			64
+#define ub_locality_name		128
+#define ub_state_name			128
+#define ub_organization_name		64
+#define ub_organization_unit_name	64
+#define ub_title			64
+#define ub_email_address		128
+#define ub_serial_number		64
+
+
+/* This table must be kept in NID order */
+
+static const ASN1_STRING_TABLE tbl_standard[] = {
+	{
+		.nid = NID_commonName,
+		.minsize = 1,
+		.maxsize = ub_common_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_countryName,
+		.minsize = 2,
+		.maxsize = 2,
+		.mask = B_ASN1_PRINTABLESTRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_localityName,
+		.minsize = 1,
+		.maxsize = ub_locality_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_stateOrProvinceName,
+		.minsize = 1,
+		.maxsize = ub_state_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_organizationName,
+		.minsize = 1,
+		.maxsize = ub_organization_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_organizationalUnitName,
+		.minsize = 1,
+		.maxsize = ub_organization_unit_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_pkcs9_emailAddress,
+		.minsize = 1,
+		.maxsize = ub_email_address,
+		.mask = B_ASN1_IA5STRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_pkcs9_unstructuredName,
+		.minsize = 1,
+		.maxsize = -1,
+		.mask = PKCS9STRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_pkcs9_challengePassword,
+		.minsize = 1,
+		.maxsize = -1,
+		.mask = PKCS9STRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_pkcs9_unstructuredAddress,
+		.minsize = 1,
+		.maxsize = -1,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_givenName,
+		.minsize = 1,
+		.maxsize = ub_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_surname,
+		.minsize = 1,
+		.maxsize = ub_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_initials,
+		.minsize = 1,
+		.maxsize = ub_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_serialNumber,
+		.minsize = 1,
+		.maxsize = ub_serial_number,
+		.mask = B_ASN1_PRINTABLESTRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_friendlyName,
+		.minsize = -1,
+		.maxsize = -1,
+		.mask = B_ASN1_BMPSTRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_name,
+		.minsize = 1,
+		.maxsize = ub_name,
+		.mask = DIRSTRING_TYPE,
+		.flags = 0,
+	},
+	{
+		.nid = NID_dnQualifier,
+		.minsize = -1,
+		.maxsize = -1,
+		.mask = B_ASN1_PRINTABLESTRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_domainComponent,
+		.minsize = 1,
+		.maxsize = -1,
+		.mask = B_ASN1_IA5STRING,
+		.flags = STABLE_NO_MASK,
+	},
+	{
+		.nid = NID_ms_csp_name,
+		.minsize = -1,
+		.maxsize = -1,
+		.mask = B_ASN1_BMPSTRING,
+		.flags = STABLE_NO_MASK,
+	},
+};
+
+static int
+sk_table_cmp(const ASN1_STRING_TABLE * const *a,
+    const ASN1_STRING_TABLE * const *b)
+{
+	return (*a)->nid - (*b)->nid;
+}
+
+static int table_cmp_BSEARCH_CMP_FN(const void *, const void *);
+static int table_cmp(ASN1_STRING_TABLE const *, ASN1_STRING_TABLE const *);
+static ASN1_STRING_TABLE *OBJ_bsearch_table(ASN1_STRING_TABLE *key, ASN1_STRING_TABLE const *base, int num);
+
+static int
+table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b)
+{
+	return a->nid - b->nid;
+}
+
+
+static int
+table_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
+{
+	ASN1_STRING_TABLE const *a = a_;
+	ASN1_STRING_TABLE const *b = b_;
+	return table_cmp(a, b);
+}
+
+static ASN1_STRING_TABLE *
+OBJ_bsearch_table(ASN1_STRING_TABLE *key, ASN1_STRING_TABLE const *base, int num)
+{
+	return (ASN1_STRING_TABLE *)OBJ_bsearch_(key, base, num, sizeof(ASN1_STRING_TABLE),
+	    table_cmp_BSEARCH_CMP_FN);
+}
+
+ASN1_STRING_TABLE *
+ASN1_STRING_TABLE_get(int nid)
+{
+	int idx;
+	ASN1_STRING_TABLE fnd;
+
+	fnd.nid = nid;
+	if (stable != NULL) {
+		idx = sk_ASN1_STRING_TABLE_find(stable, &fnd);
+		if (idx >= 0)
+			return sk_ASN1_STRING_TABLE_value(stable, idx);
+	}
+	return OBJ_bsearch_table(&fnd, tbl_standard,
+	    sizeof(tbl_standard) / sizeof(tbl_standard[0]));
+}
+LCRYPTO_ALIAS(ASN1_STRING_TABLE_get);
+
+/*
+ * Return a string table pointer which can be modified: either directly
+ * from table or a copy of an internal value added to the table.
+ */
+
+static ASN1_STRING_TABLE *
+stable_get(int nid)
+{
+	ASN1_STRING_TABLE *tmp, *rv;
+
+	/* Always need a string table so allocate one if NULL */
+	if (stable == NULL) {
+		stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
+		if (stable == NULL)
+			return NULL;
+	}
+	tmp = ASN1_STRING_TABLE_get(nid);
+	if (tmp != NULL && (tmp->flags & STABLE_FLAGS_MALLOC) != 0)
+		return tmp;
+
+	if ((rv = calloc(1, sizeof(*rv))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	if (!sk_ASN1_STRING_TABLE_push(stable, rv)) {
+		free(rv);
+		return NULL;
+	}
+	if (tmp != NULL) {
+		rv->nid = tmp->nid;
+		rv->minsize = tmp->minsize;
+		rv->maxsize = tmp->maxsize;
+		rv->mask = tmp->mask;
+		rv->flags = tmp->flags | STABLE_FLAGS_MALLOC;
+	} else {
+		rv->nid = nid;
+		rv->minsize = -1;
+		rv->maxsize = -1;
+		rv->flags = STABLE_FLAGS_MALLOC;
+	}
+	return rv;
+}
+
+int
+ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask,
+    unsigned long flags)
+{
+	ASN1_STRING_TABLE *tmp;
+
+	if ((tmp = stable_get(nid)) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	if (minsize >= 0)
+		tmp->minsize = minsize;
+	if (maxsize >= 0)
+		tmp->maxsize = maxsize;
+	if (mask != 0)
+		tmp->mask = mask;
+	if (flags != 0)
+		tmp->flags = flags | STABLE_FLAGS_MALLOC;
+
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_STRING_TABLE_add);
+
+void
+ASN1_STRING_TABLE_cleanup(void)
+{
+	STACK_OF(ASN1_STRING_TABLE) *tmp;
+
+	tmp = stable;
+	if (tmp == NULL)
+		return;
+	stable = NULL;
+	sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
+}
+LCRYPTO_ALIAS(ASN1_STRING_TABLE_cleanup);
+
+static void
+st_free(ASN1_STRING_TABLE *tbl)
+{
+	if (tbl->flags & STABLE_FLAGS_MALLOC)
+		free(tbl);
+}
diff --git a/crypto/asn1/a_time.c b/crypto/asn1/a_time.c
new file mode 100644
index 0000000..f4ddb4d
--- /dev/null
+++ b/crypto/asn1/a_time.c
@@ -0,0 +1,138 @@
+/* $OpenBSD: a_time.c,v 1.37 2023/07/05 21:23:36 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* This is an implementation of the ASN1 Time structure which is:
+ *    Time ::= CHOICE {
+ *      utcTime        UTCTime,
+ *      generalTime    GeneralizedTime }
+ * written by Steve Henson.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+
+const ASN1_ITEM ASN1_TIME_it = {
+	.itype = ASN1_ITYPE_MSTRING,
+	.utype = B_ASN1_TIME,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = sizeof(ASN1_STRING),
+	.sname = "ASN1_TIME",
+};
+
+ASN1_TIME *
+ASN1_TIME_new(void)
+{
+	return (ASN1_TIME *)ASN1_item_new(&ASN1_TIME_it);
+}
+LCRYPTO_ALIAS(ASN1_TIME_new);
+
+void
+ASN1_TIME_free(ASN1_TIME *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_TIME_it);
+}
+LCRYPTO_ALIAS(ASN1_TIME_free);
+
+int
+ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
+{
+	time_t now;
+
+	if (s != NULL)
+		return ASN1_time_parse(s->data, s->length, tm, 0) != -1;
+
+	time(&now);
+	memset(tm, 0, sizeof(*tm));
+
+	return asn1_time_time_t_to_tm(&now, tm);
+}
+LCRYPTO_ALIAS(ASN1_TIME_to_tm);
+
+int
+ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, const ASN1_TIME *to)
+{
+	struct tm tm_from, tm_to;
+
+	if (!ASN1_TIME_to_tm(from, &tm_from))
+		return 0;
+	if (!ASN1_TIME_to_tm(to, &tm_to))
+		return 0;
+
+	return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
+}
+LCRYPTO_ALIAS(ASN1_TIME_diff);
+
+ASN1_TIME *
+d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len)
+{
+	return (ASN1_TIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_TIME_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_TIME);
+
+int
+i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_TIME_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_TIME);
diff --git a/crypto/asn1/a_time_posix.c b/crypto/asn1/a_time_posix.c
new file mode 100644
index 0000000..9327aa8
--- /dev/null
+++ b/crypto/asn1/a_time_posix.c
@@ -0,0 +1,274 @@
+/* $OpenBSD: a_time_posix.c,v 1.3 2023/01/01 16:58:23 miod Exp $ */
+/*
+ * Copyright (c) 2022, Google Inc.
+ * Copyright (c) 2022, Bob Beck 
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Time conversion to/from POSIX time_t and struct tm, with no support
+ * for time zones other than UTC
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define SECS_PER_HOUR (int64_t)(60 * 60)
+#define SECS_PER_DAY (int64_t)(24 * SECS_PER_HOUR)
+
+/*
+ * Is a year/month/day combination valid, in the range from year 0000
+ * to 9999?
+ */
+static int
+is_valid_date(int year, int month, int day)
+{
+	int days_in_month;
+	if (day < 1 || month < 1 || year < 0 || year > 9999)
+		return 0;
+	switch (month) {
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+	case 8:
+	case 10:
+	case 12:
+		days_in_month = 31;
+		break;
+	case 4:
+	case 6:
+	case 9:
+	case 11:
+		days_in_month = 30;
+		break;
+	case 2:
+		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+			days_in_month = 29;
+		else
+			days_in_month = 28;
+		break;
+	default:
+		return 0;
+	}
+	return day <= days_in_month;
+}
+
+/*
+ * Is a time valid? Leap seconds of 60 are not considered valid, as
+ * the POSIX time in seconds does not include them.
+ */
+static int
+is_valid_time(int hours, int minutes, int seconds)
+{
+	return hours >= 0 && minutes >= 0 && seconds >= 0 && hours <= 23 &&
+	    minutes <= 59 && seconds <= 59;
+}
+
+/* Is a int64 time representing a time within our expected range? */
+static int
+is_valid_epoch_time(int64_t time)
+{
+	/* 0000-01-01 00:00:00 UTC to 9999-12-31 23:59:59 UTC */
+	return (int64_t)-62167219200LL <= time &&
+	    time <= (int64_t)253402300799LL;
+}
+
+/*
+ * Inspired by algorithms presented in
+ * https://howardhinnant.github.io/date_algorithms.html
+ * (Public Domain)
+ */
+static int
+posix_time_from_utc(int year, int month, int day, int hours,  int minutes,
+    int seconds, int64_t *out_time)
+{
+	int64_t era, year_of_era, day_of_year, day_of_era, posix_days;
+
+	if (!is_valid_date(year, month, day) ||
+	    !is_valid_time(hours, minutes, seconds))
+		return 0;
+	if (month <= 2)
+		year--;  /* Start years on Mar 1, so leap days end a year. */
+
+	/* At this point year will be in the range -1 and 9999.*/
+	era = (year >= 0 ? year : year - 399) / 400;
+	year_of_era = year - era * 400;
+	day_of_year = (153 * (month > 2 ? month - 3 : month + 9) + 2) /
+	    5 + day - 1;
+	day_of_era = year_of_era * 365 + year_of_era / 4 - year_of_era /
+	    100 + day_of_year;
+	posix_days = era * 146097 + day_of_era - 719468;
+	*out_time = posix_days * SECS_PER_DAY + hours * SECS_PER_HOUR +
+	    minutes * 60 + seconds;
+
+	return 1;
+}
+
+/*
+ * Inspired by algorithms presented in
+ * https://howardhinnant.github.io/date_algorithms.html
+ * (Public Domain)
+ */
+static int
+utc_from_posix_time(int64_t time, int *out_year, int *out_month, int *out_day,
+    int *out_hours, int *out_minutes, int *out_seconds)
+{
+	int64_t days, leftover_seconds, era, day_of_era, year_of_era,
+	    day_of_year, month_of_year;
+
+	if (!is_valid_epoch_time(time))
+		return 0;
+
+	days = time / SECS_PER_DAY;
+	leftover_seconds = time % SECS_PER_DAY;
+	if (leftover_seconds < 0) {
+		days--;
+		leftover_seconds += SECS_PER_DAY;
+	}
+	days += 719468;  /*  Shift to starting epoch of Mar 1 0000. */
+
+	/* At this point, days will be in the range -61 and 3652364. */
+	era = (days > 0 ? days : days - 146096) / 146097;
+	day_of_era = days - era * 146097;
+	year_of_era = (day_of_era - day_of_era / 1460 + day_of_era / 36524 -
+	    day_of_era / 146096) /
+	    365;
+	*out_year = year_of_era + era * 400;  /* Year starts on Mar 1 */
+	day_of_year = day_of_era - (365 * year_of_era + year_of_era / 4 -
+	    year_of_era / 100);
+	month_of_year = (5 * day_of_year + 2) / 153;
+	*out_month = (month_of_year < 10 ? month_of_year + 3 :
+	    month_of_year - 9);
+	if (*out_month <= 2)
+		(*out_year)++;  /* Adjust year back to Jan 1 start of year. */
+
+	*out_day = day_of_year - (153 * month_of_year + 2) / 5 + 1;
+	*out_hours = leftover_seconds / SECS_PER_HOUR;
+	leftover_seconds %= SECS_PER_HOUR;
+	*out_minutes = leftover_seconds / 60;
+	*out_seconds = leftover_seconds % 60;
+
+	return 1;
+}
+
+static int
+asn1_time_tm_to_posix(const struct tm *tm, int64_t *out)
+{
+	/* Ensure additions below do not overflow */
+	if (tm->tm_year > 9999)
+		return 0;
+	if (tm->tm_mon > 12)
+		return 0;
+
+	return posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1,
+	    tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, out);
+}
+
+static int
+asn1_time_posix_to_tm(int64_t time, struct tm *out_tm)
+{
+	memset(out_tm, 0, sizeof(struct tm));
+	if (!utc_from_posix_time(time, &out_tm->tm_year, &out_tm->tm_mon,
+	    &out_tm->tm_mday, &out_tm->tm_hour, &out_tm->tm_min,
+	    &out_tm->tm_sec))
+		return 0;
+
+	out_tm->tm_year -= 1900;
+	out_tm->tm_mon -= 1;
+
+	return 1;
+}
+
+int
+asn1_time_tm_to_time_t(const struct tm *tm, time_t *out)
+{
+	int64_t posix_time;
+
+	if (!asn1_time_tm_to_posix(tm, &posix_time))
+		return 0;
+
+#ifdef SMALL_TIME_T
+	/* For portable. */
+	if (sizeof(time_t) == sizeof(int32_t) &&
+	    (posix_time > INT32_MAX || posix_time < INT32_MIN))
+		return 0;
+#endif
+
+	*out = posix_time;
+	return 1;
+}
+
+int
+asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm)
+{
+	int64_t posix_time = *time;
+
+	return asn1_time_posix_to_tm(posix_time, out_tm);
+}
+
+int
+OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec)
+{
+	int64_t posix_time;
+
+	/* Ensure additions below do not overflow */
+	if (tm->tm_year > 9999)
+		return 0;
+	if (tm->tm_mon > 12)
+		return 0;
+
+	if (!posix_time_from_utc(tm->tm_year + 1900, tm->tm_mon + 1,
+	    tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, &posix_time))
+		return 0;
+
+	if (!utc_from_posix_time(posix_time + off_day * SECS_PER_DAY +
+	    offset_sec, &tm->tm_year, &tm->tm_mon, &tm->tm_mday, &tm->tm_hour,
+	    &tm->tm_min, &tm->tm_sec))
+		return 0;
+
+	tm->tm_year -= 1900;
+	tm->tm_mon -= 1;
+
+	return 1;
+}
+
+int
+OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
+    const struct tm *to)
+{
+	int64_t time_to, time_from, timediff, daydiff;
+
+	if (!posix_time_from_utc(to->tm_year + 1900, to->tm_mon + 1,
+	    to->tm_mday, to->tm_hour, to->tm_min, to->tm_sec, &time_to))
+		return 0;
+
+	if (!posix_time_from_utc(from->tm_year + 1900, from->tm_mon + 1,
+	    from->tm_mday, from->tm_hour, from->tm_min,
+	    from->tm_sec, &time_from))
+		return 0;
+
+	timediff = time_to - time_from;
+	daydiff = timediff / SECS_PER_DAY;
+	timediff %= SECS_PER_DAY;
+	if (daydiff > INT_MAX || daydiff < INT_MIN)
+		return 0;
+
+	*out_secs = timediff;
+	*out_days = daydiff;
+
+	return 1;
+}
diff --git a/crypto/asn1/a_time_tm.c b/crypto/asn1/a_time_tm.c
new file mode 100644
index 0000000..ea94d2f
--- /dev/null
+++ b/crypto/asn1/a_time_tm.c
@@ -0,0 +1,626 @@
+/* $OpenBSD: a_time_tm.c,v 1.31 2023/10/01 22:14:36 tb Exp $ */
+/*
+ * Copyright (c) 2015 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bytestring.h"
+#include "asn1_local.h"
+
+#define RFC5280 0
+#define GENTIME_LENGTH 15
+#define UTCTIME_LENGTH 13
+
+int
+ASN1_time_tm_cmp(struct tm *tm1, struct tm *tm2)
+{
+	if (tm1->tm_year < tm2->tm_year)
+		return (-1);
+	if (tm1->tm_year > tm2->tm_year)
+		return (1);
+	if (tm1->tm_mon < tm2->tm_mon)
+		return (-1);
+	if (tm1->tm_mon > tm2->tm_mon)
+		return (1);
+	if (tm1->tm_mday < tm2->tm_mday)
+		return (-1);
+	if (tm1->tm_mday > tm2->tm_mday)
+		return (1);
+	if (tm1->tm_hour < tm2->tm_hour)
+		return (-1);
+	if (tm1->tm_hour > tm2->tm_hour)
+		return (1);
+	if (tm1->tm_min < tm2->tm_min)
+		return (-1);
+	if (tm1->tm_min > tm2->tm_min)
+		return (1);
+	if (tm1->tm_sec < tm2->tm_sec)
+		return (-1);
+	if (tm1->tm_sec > tm2->tm_sec)
+		return (1);
+	return 0;
+}
+LCRYPTO_ALIAS(ASN1_time_tm_cmp);
+
+int
+ASN1_time_tm_clamp_notafter(struct tm *tm)
+{
+#ifdef SMALL_TIME_T
+	struct tm broken_os_epoch_tm;
+	time_t broken_os_epoch_time = INT_MAX;
+
+	if (!asn1_time_time_t_to_tm(&broken_os_epoch_time, &broken_os_epoch_tm))
+		return 0;
+
+	if (ASN1_time_tm_cmp(tm, &broken_os_epoch_tm) == 1)
+		memcpy(tm, &broken_os_epoch_tm, sizeof(*tm));
+#endif
+	return 1;
+}
+
+/* Convert time to GeneralizedTime, X.690, 11.7. */
+ASN1_TIME *
+tm_to_gentime(struct tm *tm, ASN1_TIME *atime)
+{
+	char *time_str = NULL;
+	int year;
+
+	year = tm->tm_year + 1900;
+	if (year < 0 || year > 9999) {
+		ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
+		goto err;
+	}
+
+	if (asprintf(&time_str, "%04u%02u%02u%02u%02u%02uZ", year,
+	    tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
+	    tm->tm_sec) == -1) {
+		time_str = NULL;
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (atime == NULL)
+		atime = ASN1_TIME_new();
+	if (atime == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	free(atime->data);
+	atime->data = time_str;
+	atime->length = GENTIME_LENGTH;
+	atime->type = V_ASN1_GENERALIZEDTIME;
+
+	return (atime);
+
+ err:
+	free(time_str);
+
+	return (NULL);
+}
+
+/* Convert time to UTCTime, X.690, 11.8. */
+ASN1_TIME *
+tm_to_utctime(struct tm *tm, ASN1_TIME *atime)
+{
+	char *time_str = NULL;
+
+	if (tm->tm_year >= 150 || tm->tm_year < 50) {
+		ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
+		goto err;
+	}
+
+	if (asprintf(&time_str, "%02u%02u%02u%02u%02u%02uZ",
+	    tm->tm_year % 100,  tm->tm_mon + 1, tm->tm_mday,
+	    tm->tm_hour, tm->tm_min, tm->tm_sec) == -1) {
+		time_str = NULL;
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (atime == NULL)
+		atime = ASN1_TIME_new();
+	if (atime == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	free(atime->data);
+	atime->data = time_str;
+	atime->length = UTCTIME_LENGTH;
+	atime->type = V_ASN1_UTCTIME;
+
+	return (atime);
+
+ err:
+	free(time_str);
+
+	return (NULL);
+}
+
+ASN1_TIME *
+tm_to_rfc5280_time(struct tm *tm, ASN1_TIME *atime)
+{
+	int year;
+
+	year = tm->tm_year + 1900;
+	if (year < 1950 || year > 9999) {
+		ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
+		return (NULL);
+	}
+
+	if (year < 2050)
+		return (tm_to_utctime(tm, atime));
+
+	return (tm_to_gentime(tm, atime));
+}
+
+
+static int
+cbs_get_two_digit_value(CBS *cbs, int *out)
+{
+	uint8_t first_digit, second_digit;
+
+	if (!CBS_get_u8(cbs, &first_digit))
+		return 0;
+	if (!isdigit(first_digit))
+		return 0;
+	if (!CBS_get_u8(cbs, &second_digit))
+		return 0;
+	if (!isdigit(second_digit))
+		return 0;
+
+	*out = (first_digit - '0') * 10 + (second_digit - '0');
+
+	return 1;
+}
+
+static int
+is_valid_day(int year, int month, int day)
+{
+	if (day < 1)
+		return 0;
+	switch (month) {
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+	case 8:
+	case 10:
+	case 12:
+		return day <= 31;
+	case 4:
+	case 6:
+	case 9:
+	case 11:
+		return day <= 30;
+	case 2:
+		if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
+			return day <= 29;
+		 else
+			return day <= 28;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * asn1_time_parse_cbs returns one if |cbs| is a valid DER-encoded, ASN.1 Time
+ * body within the limitations imposed by RFC 5280, or zero otherwise. The time
+ * is expected to parse as a Generalized Time if is_gentime is true, and as a
+ * UTC Time otherwise. If |out_tm| is non-NULL, |*out_tm| will be zeroed, and
+ * then set to the corresponding time in UTC. This function does not compute
+ * |out_tm->tm_wday| or |out_tm->tm_yday|. |cbs| is not consumed.
+ */
+int
+asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm)
+{
+	int year, month, day, hour, min, sec, val;
+	CBS copy;
+	uint8_t tz;
+
+	CBS_dup(cbs, ©);
+
+	if (is_gentime) {
+		if (!cbs_get_two_digit_value(©, &val))
+			return 0;
+		year = val * 100;
+		if (!cbs_get_two_digit_value(©, &val))
+			return 0;
+		year += val;
+	} else {
+		year = 1900;
+		if (!cbs_get_two_digit_value(©, &val))
+			return 0;
+		year += val;
+		if (year < 1950)
+			year += 100;
+		if (year >= 2050)
+			return 0;  /* A Generalized time must be used. */
+	}
+
+	if (!cbs_get_two_digit_value(©, &month))
+		return 0;
+	if (month < 1 || month > 12)
+		return 0; /* Reject invalid months. */
+
+	if (!cbs_get_two_digit_value(©, &day))
+		return 0;
+	if (!is_valid_day(year, month, day))
+		return 0; /* Reject invalid days. */
+
+	if (!cbs_get_two_digit_value(©, &hour))
+		return 0;
+	if (hour > 23)
+		return 0; /* Reject invalid hours. */
+
+	if (!cbs_get_two_digit_value(©, &min))
+		return 0;
+	if (min > 59)
+		return 0; /* Reject invalid minutes. */
+
+	if (!cbs_get_two_digit_value(©, &sec))
+		return 0;
+	if (sec > 59)
+		return 0; /* Reject invalid seconds. Leap seconds are invalid. */
+
+	if (!CBS_get_u8(©, &tz))
+		return 0;
+	if (tz != 'Z')
+		return 0; /* Reject anything but Z on the end. */
+
+	if (CBS_len(©) != 0)
+		return 0;  /* Reject invalid lengths. */
+
+	if (out_tm != NULL) {
+		memset(out_tm, 0, sizeof(*out_tm));
+		/* Fill in the tm fields corresponding to what we validated. */
+		out_tm->tm_year = year - 1900;
+		out_tm->tm_mon = month - 1;
+		out_tm->tm_mday = day;
+		out_tm->tm_hour = hour;
+		out_tm->tm_min = min;
+		out_tm->tm_sec = sec;
+	}
+
+	return 1;
+}
+
+/*
+ * Parse an RFC 5280 format ASN.1 time string.
+ *
+ * mode must be:
+ * 0 if we expect to parse a time as specified in RFC 5280 for an X509 object.
+ * V_ASN1_UTCTIME if we wish to parse an RFC5280 format UTC time.
+ * V_ASN1_GENERALIZEDTIME if we wish to parse an RFC5280 format Generalized time.
+ *
+ * Returns:
+ * -1 if the string was invalid.
+ * V_ASN1_UTCTIME if the string validated as a UTC time string.
+ * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
+ *
+ * Fills in *tm with the corresponding time if tm is non NULL.
+ */
+int
+ASN1_time_parse(const char *bytes, size_t len, struct tm *tm, int mode)
+{
+	struct tm tml, *tmp = tm ? tm : &tml;
+	int type = 0;
+	CBS cbs;
+
+	if (bytes == NULL)
+		return (-1);
+
+	CBS_init(&cbs, bytes, len);
+
+	if (CBS_len(&cbs) == UTCTIME_LENGTH)
+		type = V_ASN1_UTCTIME;
+	if (CBS_len(&cbs) == GENTIME_LENGTH)
+		type = V_ASN1_GENERALIZEDTIME;
+	if (asn1_time_parse_cbs(&cbs, type == V_ASN1_GENERALIZEDTIME, tmp)) {
+		if (mode != 0 && mode != type)
+			return -1;
+		return type;
+	}
+
+	return -1;
+}
+LCRYPTO_ALIAS(ASN1_time_parse);
+
+/*
+ * ASN1_TIME generic functions.
+ */
+
+static int
+ASN1_TIME_set_string_internal(ASN1_TIME *s, const char *str, int mode)
+{
+	int type;
+	char *tmp;
+
+	if ((type = ASN1_time_parse(str, strlen(str), NULL, mode)) == -1)
+		return (0);
+	if (mode != 0 && mode != type)
+		return (0);
+
+	if (s == NULL)
+		return (1);
+
+	if ((tmp = strdup(str)) == NULL)
+		return (0);
+	free(s->data);
+	s->data = tmp;
+	s->length = strlen(tmp);
+	s->type = type;
+
+	return (1);
+}
+
+static ASN1_TIME *
+ASN1_TIME_adj_internal(ASN1_TIME *s, time_t t, int offset_day, long offset_sec,
+    int mode)
+{
+	struct tm tm;
+
+	if (!asn1_time_time_t_to_tm(&t, &tm))
+		return (NULL);
+
+	if (offset_day != 0 || offset_sec != 0) {
+		if (!OPENSSL_gmtime_adj(&tm, offset_day, offset_sec))
+			return (NULL);
+	}
+
+	switch (mode) {
+	case V_ASN1_UTCTIME:
+		return (tm_to_utctime(&tm, s));
+	case V_ASN1_GENERALIZEDTIME:
+		return (tm_to_gentime(&tm, s));
+	case RFC5280:
+		return (tm_to_rfc5280_time(&tm, s));
+	default:
+		return (NULL);
+	}
+}
+
+ASN1_TIME *
+ASN1_TIME_set(ASN1_TIME *s, time_t t)
+{
+	return (ASN1_TIME_adj(s, t, 0, 0));
+}
+LCRYPTO_ALIAS(ASN1_TIME_set);
+
+ASN1_TIME *
+ASN1_TIME_set_tm(ASN1_TIME *s, struct tm *tm)
+{
+	time_t t;
+
+	if (!asn1_time_tm_to_time_t(tm, &t))
+		return NULL;
+	return (ASN1_TIME_adj(s, t, 0, 0));
+}
+LCRYPTO_ALIAS(ASN1_TIME_set_tm);
+
+ASN1_TIME *
+ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
+{
+	return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec, RFC5280));
+}
+LCRYPTO_ALIAS(ASN1_TIME_adj);
+
+int
+ASN1_TIME_check(const ASN1_TIME *t)
+{
+	if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
+		return (0);
+	return (t->type == ASN1_time_parse(t->data, t->length, NULL, t->type));
+}
+LCRYPTO_ALIAS(ASN1_TIME_check);
+
+ASN1_GENERALIZEDTIME *
+ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
+{
+	ASN1_GENERALIZEDTIME *agt = NULL;
+	struct tm tm;
+
+	if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
+		return (NULL);
+
+	if (t->type != ASN1_time_parse(t->data, t->length, &tm, t->type))
+		return (NULL);
+
+	if (out != NULL)
+		agt = *out;
+	if ((agt = tm_to_gentime(&tm, agt)) == NULL)
+		return (NULL);
+	if (out != NULL)
+		*out = agt;
+
+	return (agt);
+}
+LCRYPTO_ALIAS(ASN1_TIME_to_generalizedtime);
+
+int
+ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
+{
+	return (ASN1_TIME_set_string_internal(s, str, 0));
+}
+LCRYPTO_ALIAS(ASN1_TIME_set_string);
+
+static int
+ASN1_TIME_cmp_time_t_internal(const ASN1_TIME *s, time_t t2, int mode)
+{
+	struct tm tm1, tm2;
+
+	/*
+	 * This function has never handled failure conditions properly
+	 * The OpenSSL version used to simply follow NULL pointers on failure.
+	 * BoringSSL and OpenSSL now make it return -2 on failure.
+	 *
+	 * The danger is that users of this function will not differentiate the
+	 * -2 failure case from s < t2. Callers must be careful. Sadly this is
+	 * one of those pervasive things from OpenSSL we must continue with.
+	 */
+
+	if (ASN1_time_parse(s->data, s->length, &tm1, mode) == -1)
+		return -2;
+
+	if (!asn1_time_time_t_to_tm(&t2, &tm2))
+		return -2;
+
+	return ASN1_time_tm_cmp(&tm1, &tm2);
+}
+
+int
+ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2)
+{
+	struct tm tm1, tm2;
+
+	if (t1->type != V_ASN1_UTCTIME && t1->type != V_ASN1_GENERALIZEDTIME)
+		return -2;
+
+	if (t2->type != V_ASN1_UTCTIME && t2->type != V_ASN1_GENERALIZEDTIME)
+		return -2;
+
+	if (ASN1_time_parse(t1->data, t1->length, &tm1, t1->type) == -1)
+		return -2;
+
+	if (ASN1_time_parse(t2->data, t2->length, &tm2, t2->type) == -1)
+		return -2;
+
+	return ASN1_time_tm_cmp(&tm1, &tm2);
+}
+LCRYPTO_ALIAS(ASN1_TIME_compare);
+
+int
+ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t)
+{
+	if (s->type == V_ASN1_UTCTIME)
+		return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
+	if (s->type == V_ASN1_GENERALIZEDTIME)
+		return ASN1_TIME_cmp_time_t_internal(s, t,
+		    V_ASN1_GENERALIZEDTIME);
+	return -2;
+}
+LCRYPTO_ALIAS(ASN1_TIME_cmp_time_t);
+
+/*
+ * ASN1_UTCTIME wrappers
+ */
+
+int
+ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
+{
+	if (d->type != V_ASN1_UTCTIME)
+		return (0);
+	return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_check);
+
+int
+ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
+{
+	if (s != NULL && s->type != V_ASN1_UTCTIME)
+		return (0);
+	return (ASN1_TIME_set_string_internal(s, str, V_ASN1_UTCTIME));
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_set_string);
+
+ASN1_UTCTIME *
+ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
+{
+	return (ASN1_UTCTIME_adj(s, t, 0, 0));
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_set);
+
+ASN1_UTCTIME *
+ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, int offset_day, long offset_sec)
+{
+	return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
+	    V_ASN1_UTCTIME));
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_adj);
+
+int
+ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
+{
+	if (s->type == V_ASN1_UTCTIME)
+		return ASN1_TIME_cmp_time_t_internal(s, t, V_ASN1_UTCTIME);
+	return -2;
+}
+
+/*
+ * ASN1_GENERALIZEDTIME wrappers
+ */
+
+int
+ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
+{
+	if (d->type != V_ASN1_GENERALIZEDTIME)
+		return (0);
+	return (d->type == ASN1_time_parse(d->data, d->length, NULL, d->type));
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_check);
+
+int
+ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
+{
+	if (s != NULL && s->type != V_ASN1_GENERALIZEDTIME)
+		return (0);
+	return (ASN1_TIME_set_string_internal(s, str, V_ASN1_GENERALIZEDTIME));
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_set_string);
+
+ASN1_GENERALIZEDTIME *
+ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, time_t t)
+{
+	return (ASN1_GENERALIZEDTIME_adj(s, t, 0, 0));
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_set);
+
+ASN1_GENERALIZEDTIME *
+ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, time_t t, int offset_day,
+    long offset_sec)
+{
+	return (ASN1_TIME_adj_internal(s, t, offset_day, offset_sec,
+	    V_ASN1_GENERALIZEDTIME));
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_adj);
+
+int
+ASN1_TIME_normalize(ASN1_TIME *t)
+{
+	struct tm tm;
+
+	if (t == NULL)
+		return 0;
+	if (!ASN1_TIME_to_tm(t, &tm))
+		return 0;
+	return tm_to_rfc5280_time(&tm, t) != NULL;
+}
+LCRYPTO_ALIAS(ASN1_TIME_normalize);
+
+int
+ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str)
+{
+	return ASN1_TIME_set_string_internal(s, str, RFC5280);
+}
+LCRYPTO_ALIAS(ASN1_TIME_set_string_X509);
diff --git a/crypto/asn1/a_type.c b/crypto/asn1/a_type.c
new file mode 100644
index 0000000..ef0a76e
--- /dev/null
+++ b/crypto/asn1/a_type.c
@@ -0,0 +1,360 @@
+/* $OpenBSD: a_type.c,v 1.27 2023/07/28 10:00:10 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+typedef struct {
+	ASN1_INTEGER *num;
+	ASN1_OCTET_STRING *value;
+} ASN1_int_octetstring;
+
+static const ASN1_TEMPLATE ASN1_INT_OCTETSTRING_seq_tt[] = {
+	{
+		.offset = offsetof(ASN1_int_octetstring, num),
+		.field_name = "num",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(ASN1_int_octetstring, value),
+		.field_name = "value",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM ASN1_INT_OCTETSTRING_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ASN1_INT_OCTETSTRING_seq_tt,
+	.tcount = sizeof(ASN1_INT_OCTETSTRING_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(ASN1_int_octetstring),
+	.sname = "ASN1_INT_OCTETSTRING",
+};
+
+ASN1_TYPE *
+ASN1_TYPE_new(void)
+{
+	return (ASN1_TYPE *)ASN1_item_new(&ASN1_ANY_it);
+}
+LCRYPTO_ALIAS(ASN1_TYPE_new);
+
+void
+ASN1_TYPE_free(ASN1_TYPE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_ANY_it);
+}
+LCRYPTO_ALIAS(ASN1_TYPE_free);
+
+int
+ASN1_TYPE_get(const ASN1_TYPE *a)
+{
+	/* Special non-pointer types. */
+	if (a->type == V_ASN1_BOOLEAN || a->type == V_ASN1_NULL)
+		return a->type;
+
+	if (a->value.ptr != NULL)
+		return a->type;
+
+	return 0;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_get);
+
+void
+ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
+{
+	if (a->value.ptr != NULL) {
+		ASN1_TYPE **tmp_a = &a;
+		ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
+	}
+	a->type = type;
+	if (type == V_ASN1_BOOLEAN)
+		a->value.boolean = value ? 0xff : 0;
+	else
+		a->value.ptr = value;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_set);
+
+int
+ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
+{
+	if (!value || (type == V_ASN1_BOOLEAN)) {
+		void *p = (void *)value;
+		ASN1_TYPE_set(a, type, p);
+	} else if (type == V_ASN1_OBJECT) {
+		ASN1_OBJECT *odup;
+		odup = OBJ_dup(value);
+		if (!odup)
+			return 0;
+		ASN1_TYPE_set(a, type, odup);
+	} else {
+		ASN1_STRING *sdup;
+		sdup = ASN1_STRING_dup(value);
+		if (!sdup)
+			return 0;
+		ASN1_TYPE_set(a, type, sdup);
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_set1);
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int
+ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
+{
+	int result = -1;
+
+	if (!a || !b || a->type != b->type)
+		return -1;
+
+	switch (a->type) {
+	case V_ASN1_OBJECT:
+		result = OBJ_cmp(a->value.object, b->value.object);
+		break;
+	case V_ASN1_BOOLEAN:
+		result = a->value.boolean - b->value.boolean;
+		break;
+	case V_ASN1_NULL:
+		result = 0;	/* They do not have content. */
+		break;
+
+	case V_ASN1_INTEGER:
+	case V_ASN1_ENUMERATED:
+	case V_ASN1_BIT_STRING:
+	case V_ASN1_OCTET_STRING:
+	case V_ASN1_SEQUENCE:
+	case V_ASN1_SET:
+	case V_ASN1_NUMERICSTRING:
+	case V_ASN1_PRINTABLESTRING:
+	case V_ASN1_T61STRING:
+	case V_ASN1_VIDEOTEXSTRING:
+	case V_ASN1_IA5STRING:
+	case V_ASN1_UTCTIME:
+	case V_ASN1_GENERALIZEDTIME:
+	case V_ASN1_GRAPHICSTRING:
+	case V_ASN1_VISIBLESTRING:
+	case V_ASN1_GENERALSTRING:
+	case V_ASN1_UNIVERSALSTRING:
+	case V_ASN1_BMPSTRING:
+	case V_ASN1_UTF8STRING:
+	case V_ASN1_OTHER:
+	default:
+		result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
+		    (ASN1_STRING *)b->value.ptr);
+		break;
+	}
+
+	return result;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_cmp);
+
+int
+ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len)
+{
+	ASN1_STRING *os;
+
+	if ((os = ASN1_OCTET_STRING_new()) == NULL)
+		return (0);
+	if (!ASN1_STRING_set(os, data, len)) {
+		ASN1_OCTET_STRING_free(os);
+		return (0);
+	}
+	ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os);
+	return (1);
+}
+LCRYPTO_ALIAS(ASN1_TYPE_set_octetstring);
+
+int
+ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len)
+{
+	int ret, num;
+	unsigned char *p;
+
+	if ((a->type != V_ASN1_OCTET_STRING) ||
+	    (a->value.octet_string == NULL)) {
+		ASN1error(ASN1_R_DATA_IS_WRONG);
+		return (-1);
+	}
+	p = ASN1_STRING_data(a->value.octet_string);
+	ret = ASN1_STRING_length(a->value.octet_string);
+	if (ret < max_len)
+		num = ret;
+	else
+		num = max_len;
+	memcpy(data, p, num);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_TYPE_get_octetstring);
+
+int
+ASN1_TYPE_set_int_octetstring(ASN1_TYPE *at, long num, const unsigned char *data,
+    int len)
+{
+	ASN1_int_octetstring *ios;
+	ASN1_STRING *sp = NULL;
+	int ret = 0;
+
+	if ((ios = (ASN1_int_octetstring *)ASN1_item_new(
+	    &ASN1_INT_OCTETSTRING_it)) == NULL)
+		goto err;
+	if (!ASN1_INTEGER_set(ios->num, num))
+		goto err;
+	if (!ASN1_OCTET_STRING_set(ios->value, data, len))
+		goto err;
+
+	if ((sp = ASN1_item_pack(ios, &ASN1_INT_OCTETSTRING_it, NULL)) == NULL)
+		goto err;
+
+	ASN1_TYPE_set(at, V_ASN1_SEQUENCE, sp);
+	sp = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
+	ASN1_STRING_free(sp);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_set_int_octetstring);
+
+int
+ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *at, long *num, unsigned char *data,
+    int max_len)
+{
+	ASN1_STRING *sp = at->value.sequence;
+	ASN1_int_octetstring *ios = NULL;
+	int ret = -1;
+	int len;
+
+	if (at->type != V_ASN1_SEQUENCE || sp == NULL)
+		goto err;
+
+	if ((ios = ASN1_item_unpack(sp, &ASN1_INT_OCTETSTRING_it)) == NULL)
+		goto err;
+
+	if (num != NULL)
+		*num = ASN1_INTEGER_get(ios->num);
+	if (data != NULL) {
+		len = ASN1_STRING_length(ios->value);
+		if (len > max_len)
+			len = max_len;
+		memcpy(data, ASN1_STRING_data(ios->value), len);
+	}
+
+	ret = ASN1_STRING_length(ios->value);
+
+ err:
+	ASN1_item_free((ASN1_VALUE *)ios, &ASN1_INT_OCTETSTRING_it);
+
+	if (ret == -1)
+		ASN1error(ASN1_R_DATA_IS_WRONG);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_TYPE_get_int_octetstring);
+
+ASN1_TYPE *
+ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t)
+{
+	ASN1_OCTET_STRING *oct;
+	ASN1_TYPE *rt;
+
+	if ((oct = ASN1_item_pack(s, it, NULL)) == NULL)
+		return NULL;
+
+	if (t != NULL && *t != NULL) {
+		rt = *t;
+	} else {
+		if ((rt = ASN1_TYPE_new()) == NULL) {
+			ASN1_OCTET_STRING_free(oct);
+			return NULL;
+		}
+		if (t != NULL)
+			*t = rt;
+	}
+	ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct);
+	return rt;
+}
+
+void *
+ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
+{
+	if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
+		return NULL;
+	return ASN1_item_unpack(t->value.sequence, it);
+}
+
+int
+i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_ANY_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_TYPE);
+
+ASN1_TYPE *
+d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len)
+{
+	return (ASN1_TYPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_ANY_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_TYPE);
diff --git a/crypto/asn1/a_utf8.c b/crypto/asn1/a_utf8.c
new file mode 100644
index 0000000..51ab1bd
--- /dev/null
+++ b/crypto/asn1/a_utf8.c
@@ -0,0 +1,199 @@
+/* $OpenBSD: a_utf8.c,v 1.9 2022/11/26 16:08:50 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include "asn1_local.h"
+
+/* UTF8 utilities */
+
+/*
+ * This parses a UTF8 string one character at a time. It is passed a pointer
+ * to the string and the length of the string. It sets 'value' to the value of
+ * the current character. It returns the number of characters read or a
+ * negative error code:
+ * -1 = string too short
+ * -2 = illegal character
+ * -3 = subsequent characters not of the form 10xxxxxx
+ * -4 = character encoded incorrectly (not minimal length).
+ */
+
+int
+UTF8_getc(const unsigned char *str, int len, unsigned long *val)
+{
+	const unsigned char *p;
+	unsigned long value;
+	int ret;
+	if (len <= 0)
+		return 0;
+	p = str;
+
+	/* Check syntax and work out the encoded value (if correct) */
+	if ((*p & 0x80) == 0) {
+		value = *p++ & 0x7f;
+		ret = 1;
+	} else if ((*p & 0xe0) == 0xc0) {
+		if (*p < 0xc2)
+			return -2;
+		if (len < 2)
+			return -1;
+		if ((p[1] & 0xc0) != 0x80)
+			return -3;
+		value = (*p++ & 0x1f) << 6;
+		value |= *p++ & 0x3f;
+		if (value < 0x80)
+			return -4;
+		ret = 2;
+	} else if ((*p & 0xf0) == 0xe0) {
+		if (len < 3)
+			return -1;
+		if (((p[1] & 0xc0) != 0x80) ||
+		    ((p[2] & 0xc0) != 0x80))
+			return -3;
+		value = (*p++ & 0xf) << 12;
+		value |= (*p++ & 0x3f) << 6;
+		value |= *p++ & 0x3f;
+		if (value < 0x800)
+			return -4;
+		/* surrogate pair code points are not valid */
+		if (value >= 0xd800 && value < 0xe000)
+			return -2;
+		ret = 3;
+	} else if ((*p & 0xf8) == 0xf0 && (*p < 0xf5)) {
+		if (len < 4)
+			return -1;
+		if (((p[1] & 0xc0) != 0x80) ||
+		    ((p[2] & 0xc0) != 0x80) ||
+		    ((p[3] & 0xc0) != 0x80))
+			return -3;
+		value = ((unsigned long)(*p++ & 0x7)) << 18;
+		value |= (*p++ & 0x3f) << 12;
+		value |= (*p++ & 0x3f) << 6;
+		value |= *p++ & 0x3f;
+		if (value < 0x10000)
+			return -4;
+		if (value > UNICODE_MAX)
+			return -2;
+		ret = 4;
+	} else
+		return -2;
+	*val = value;
+	return ret;
+}
+
+/* This takes a Unicode code point 'value' and writes its UTF-8 encoded form
+ * in 'str' where 'str' is a buffer of at least length 'len'.  If 'str'
+ * is NULL, then nothing is written and just the return code is determined.
+
+ * Returns less than zero on error:
+ *  -1 if 'str' is not NULL and 'len' is too small
+ *  -2 if 'value' is an invalid character (surrogate or out-of-range)
+ *
+ * Otherwise, returns the number of bytes in 'value's encoded form
+ * (i.e., the number of bytes written to 'str' when it's not NULL).
+ *
+ * It will need at most 4 characters.
+ */
+
+int
+UTF8_putc(unsigned char *str, int len, unsigned long value)
+{
+	if (value < 0x80) {
+		if (str != NULL) {
+			if (len < 1)
+				return -1;
+			str[0] = (unsigned char)value;
+		}
+		return 1;
+	}
+	if (value < 0x800) {
+		if (str != NULL) {
+			if (len < 2)
+				return -1;
+			str[0] = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
+			str[1] = (unsigned char)((value & 0x3f) | 0x80);
+		}
+		return 2;
+	}
+	if (value < 0x10000) {
+		if (UNICODE_IS_SURROGATE(value))
+			return -2;
+		if (str != NULL) {
+			if (len < 3)
+				return -1;
+			str[0] = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
+			str[1] = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+			str[2] = (unsigned char)((value & 0x3f) | 0x80);
+		}
+		return 3;
+	}
+	if (value <= UNICODE_MAX) {
+		if (str != NULL) {
+			if (len < 4)
+				return -1;
+			str[0] = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
+			str[1] = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+			str[2] = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+			str[3] = (unsigned char)((value & 0x3f) | 0x80);
+		}
+		return 4;
+	}
+	return -2;
+}
diff --git a/crypto/asn1/ameth_lib.c b/crypto/asn1/ameth_lib.c
new file mode 100644
index 0000000..153ad21
--- /dev/null
+++ b/crypto/asn1/ameth_lib.c
@@ -0,0 +1,428 @@
+/* $OpenBSD: ameth_lib.c,v 1.32 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
+extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
+extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
+extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
+
+static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
+	&cmac_asn1_meth,
+	&dh_asn1_meth,
+	&dsa_asn1_meths[0],
+	&dsa_asn1_meths[1],
+	&dsa_asn1_meths[2],
+	&dsa_asn1_meths[3],
+	&dsa_asn1_meths[4],
+	&eckey_asn1_meth,
+	&ed25519_asn1_meth,
+	&gostimit_asn1_meth,
+	&gostr01_asn1_meths[0],
+	&gostr01_asn1_meths[1],
+	&gostr01_asn1_meths[2],
+	&hmac_asn1_meth,
+	&rsa_asn1_meths[0],
+	&rsa_asn1_meths[1],
+	&rsa_pss_asn1_meth,
+	&x25519_asn1_meth,
+};
+
+static const size_t asn1_methods_count =
+    sizeof(asn1_methods) / sizeof(asn1_methods[0]);
+
+DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
+static STACK_OF(EVP_PKEY_ASN1_METHOD) *asn1_app_methods = NULL;
+
+int
+EVP_PKEY_asn1_get_count(void)
+{
+	int num = asn1_methods_count;
+
+	if (asn1_app_methods != NULL)
+		num += sk_EVP_PKEY_ASN1_METHOD_num(asn1_app_methods);
+
+	return num;
+}
+
+const EVP_PKEY_ASN1_METHOD *
+EVP_PKEY_asn1_get0(int idx)
+{
+	int num = asn1_methods_count;
+
+	if (idx < 0)
+		return NULL;
+	if (idx < num)
+		return asn1_methods[idx];
+
+	idx -= num;
+
+	return sk_EVP_PKEY_ASN1_METHOD_value(asn1_app_methods, idx);
+}
+
+static const EVP_PKEY_ASN1_METHOD *
+pkey_asn1_find(int pkey_id)
+{
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	int i;
+
+	for (i = EVP_PKEY_asn1_get_count() - 1; i >= 0; i--) {
+		ameth = EVP_PKEY_asn1_get0(i);
+		if (ameth->pkey_id == pkey_id)
+			return ameth;
+	}
+
+	return NULL;
+}
+
+/*
+ * Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
+ * also search through engines and set *pe to a functional reference
+ * to the engine implementing 'type' or NULL if no engine implements
+ * it.
+ */
+const EVP_PKEY_ASN1_METHOD *
+EVP_PKEY_asn1_find(ENGINE **pe, int type)
+{
+	const EVP_PKEY_ASN1_METHOD *mp;
+
+	for (;;) {
+		if ((mp = pkey_asn1_find(type)) == NULL)
+			break;
+		if ((mp->pkey_flags & ASN1_PKEY_ALIAS) == 0)
+			break;
+		type = mp->pkey_base_id;
+	}
+	if (pe) {
+#ifndef OPENSSL_NO_ENGINE
+		ENGINE *e;
+		/* type will contain the final unaliased type */
+		e = ENGINE_get_pkey_asn1_meth_engine(type);
+		if (e) {
+			*pe = e;
+			return ENGINE_get_pkey_asn1_meth(e, type);
+		}
+#endif
+		*pe = NULL;
+	}
+	return mp;
+}
+
+const EVP_PKEY_ASN1_METHOD *
+EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len)
+{
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	int i;
+
+	if (len == -1)
+		len = strlen(str);
+	if (pe) {
+#ifndef OPENSSL_NO_ENGINE
+		ENGINE *e;
+		ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
+		if (ameth) {
+			/* Convert structural into
+			 * functional reference
+			 */
+			if (!ENGINE_init(e))
+				ameth = NULL;
+			ENGINE_free(e);
+			*pe = e;
+			return ameth;
+		}
+#endif
+		*pe = NULL;
+	}
+	for (i = EVP_PKEY_asn1_get_count() - 1; i >= 0; i--) {
+		ameth = EVP_PKEY_asn1_get0(i);
+		if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
+			continue;
+		if (((int)strlen(ameth->pem_str) == len) &&
+		    !strncasecmp(ameth->pem_str, str, len))
+			return ameth;
+	}
+	return NULL;
+}
+
+int
+EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
+{
+	if (asn1_app_methods == NULL) {
+		asn1_app_methods = sk_EVP_PKEY_ASN1_METHOD_new(NULL);
+		if (asn1_app_methods == NULL)
+			return 0;
+	}
+
+	if (!sk_EVP_PKEY_ASN1_METHOD_push(asn1_app_methods, ameth))
+		return 0;
+
+	return 1;
+}
+
+int
+EVP_PKEY_asn1_add_alias(int to, int from)
+{
+	EVP_PKEY_ASN1_METHOD *ameth;
+
+	ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
+	if (ameth == NULL)
+		return 0;
+
+	ameth->pkey_base_id = to;
+	if (!EVP_PKEY_asn1_add0(ameth)) {
+		EVP_PKEY_asn1_free(ameth);
+		return 0;
+	}
+	return 1;
+}
+
+int
+EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
+    const char **pinfo, const char **ppem_str,
+    const EVP_PKEY_ASN1_METHOD *ameth)
+{
+	if (!ameth)
+		return 0;
+	if (ppkey_id)
+		*ppkey_id = ameth->pkey_id;
+	if (ppkey_base_id)
+		*ppkey_base_id = ameth->pkey_base_id;
+	if (ppkey_flags)
+		*ppkey_flags = ameth->pkey_flags;
+	if (pinfo)
+		*pinfo = ameth->info;
+	if (ppem_str)
+		*ppem_str = ameth->pem_str;
+	return 1;
+}
+
+const EVP_PKEY_ASN1_METHOD*
+EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
+{
+	return pkey->ameth;
+}
+
+EVP_PKEY_ASN1_METHOD*
+EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info)
+{
+	EVP_PKEY_ASN1_METHOD *ameth;
+
+	if ((ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD))) == NULL)
+		return NULL;
+
+	ameth->pkey_id = id;
+	ameth->pkey_base_id = id;
+	ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
+
+	if (info != NULL) {
+		if ((ameth->info = strdup(info)) == NULL)
+			goto err;
+	}
+
+	if (pem_str != NULL) {
+		if ((ameth->pem_str = strdup(pem_str)) == NULL)
+			goto err;
+	}
+
+	return ameth;
+
+ err:
+	EVP_PKEY_asn1_free(ameth);
+	return NULL;
+}
+
+void
+EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src)
+{
+	EVP_PKEY_ASN1_METHOD preserve;
+
+	preserve.pkey_id = dst->pkey_id;
+	preserve.pkey_base_id = dst->pkey_base_id;
+	preserve.pkey_flags = dst->pkey_flags;
+	preserve.pem_str = dst->pem_str;
+	preserve.info = dst->info;
+
+	*dst = *src;
+
+	dst->pkey_id = preserve.pkey_id;
+	dst->pkey_base_id = preserve.pkey_base_id;
+	dst->pkey_flags = preserve.pkey_flags;
+	dst->pem_str = preserve.pem_str;
+	dst->info = preserve.info;
+}
+
+void
+EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
+{
+	if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
+		free(ameth->pem_str);
+		free(ameth->info);
+		free(ameth);
+	}
+}
+
+void
+EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
+    int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
+    int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
+    int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	ASN1_PCTX *pctx),
+    int (*pkey_size)(const EVP_PKEY *pk),
+    int (*pkey_bits)(const EVP_PKEY *pk))
+{
+	ameth->pub_decode = pub_decode;
+	ameth->pub_encode = pub_encode;
+	ameth->pub_cmp = pub_cmp;
+	ameth->pub_print = pub_print;
+	ameth->pkey_size = pkey_size;
+	ameth->pkey_bits = pkey_bits;
+}
+
+void
+EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf),
+    int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
+    int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	ASN1_PCTX *pctx))
+{
+	ameth->priv_decode = priv_decode;
+	ameth->priv_encode = priv_encode;
+	ameth->priv_print = priv_print;
+}
+
+void
+EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen),
+    int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
+    int (*param_missing)(const EVP_PKEY *pk),
+    int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
+    int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
+    int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	ASN1_PCTX *pctx))
+{
+	ameth->param_decode = param_decode;
+	ameth->param_encode = param_encode;
+	ameth->param_missing = param_missing;
+	ameth->param_copy = param_copy;
+	ameth->param_cmp = param_cmp;
+	ameth->param_print = param_print;
+}
+
+void
+EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
+    void (*pkey_free)(EVP_PKEY *pkey))
+{
+	ameth->pkey_free = pkey_free;
+}
+
+void
+EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2))
+{
+	ameth->pkey_ctrl = pkey_ctrl;
+}
+
+void
+EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pkey_security_bits)(const EVP_PKEY *pkey))
+{
+	ameth->pkey_security_bits = pkey_security_bits;
+}
+
+void
+EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pkey_check)(const EVP_PKEY *pk))
+{
+	ameth->pkey_check = pkey_check;
+}
+
+void
+EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pkey_public_check)(const EVP_PKEY *pk))
+{
+	ameth->pkey_public_check = pkey_public_check;
+}
+
+void
+EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
+    int (*pkey_param_check)(const EVP_PKEY *pk))
+{
+	ameth->pkey_param_check = pkey_param_check;
+}
diff --git a/crypto/asn1/asn1_err.c b/crypto/asn1/asn1_err.c
new file mode 100644
index 0000000..2857038
--- /dev/null
+++ b/crypto/asn1/asn1_err.c
@@ -0,0 +1,214 @@
+/* $OpenBSD: asn1_err.c,v 1.26 2023/07/05 21:23:36 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_ASN1,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_ASN1,0,reason)
+
+static ERR_STRING_DATA ASN1_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA ASN1_str_reasons[] = {
+	{ERR_REASON(ASN1_R_ADDING_OBJECT)        , "adding object"},
+	{ERR_REASON(ASN1_R_ASN1_PARSE_ERROR)     , "asn1 parse error"},
+	{ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR) , "asn1 sig parse error"},
+	{ERR_REASON(ASN1_R_AUX_ERROR)            , "aux error"},
+	{ERR_REASON(ASN1_R_BAD_CLASS)            , "bad class"},
+	{ERR_REASON(ASN1_R_BAD_OBJECT_HEADER)    , "bad object header"},
+	{ERR_REASON(ASN1_R_BAD_PASSWORD_READ)    , "bad password read"},
+	{ERR_REASON(ASN1_R_BAD_TAG)              , "bad tag"},
+	{ERR_REASON(ASN1_R_BAD_TEMPLATE)         , "bad template"},
+	{ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH), "bmpstring is wrong length"},
+	{ERR_REASON(ASN1_R_BN_LIB)               , "bn lib"},
+	{ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "boolean is wrong length"},
+	{ERR_REASON(ASN1_R_BUFFER_TOO_SMALL)     , "buffer too small"},
+	{ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "cipher has no object identifier"},
+	{ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED), "context not initialised"},
+	{ERR_REASON(ASN1_R_DATA_IS_WRONG)        , "data is wrong"},
+	{ERR_REASON(ASN1_R_DECODE_ERROR)         , "decode error"},
+	{ERR_REASON(ASN1_R_DECODING_ERROR)       , "decoding error"},
+	{ERR_REASON(ASN1_R_DEPTH_EXCEEDED)       , "depth exceeded"},
+	{ERR_REASON(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), "digest and key type not supported"},
+	{ERR_REASON(ASN1_R_ENCODE_ERROR)         , "encode error"},
+	{ERR_REASON(ASN1_R_ERROR_GETTING_TIME)   , "error getting time"},
+	{ERR_REASON(ASN1_R_ERROR_LOADING_SECTION), "error loading section"},
+	{ERR_REASON(ASN1_R_ERROR_PARSING_SET_ELEMENT), "error parsing set element"},
+	{ERR_REASON(ASN1_R_ERROR_SETTING_CIPHER_PARAMS), "error setting cipher params"},
+	{ERR_REASON(ASN1_R_EXPECTING_AN_INTEGER) , "expecting an integer"},
+	{ERR_REASON(ASN1_R_EXPECTING_AN_OBJECT)  , "expecting an object"},
+	{ERR_REASON(ASN1_R_EXPECTING_A_BOOLEAN)  , "expecting a boolean"},
+	{ERR_REASON(ASN1_R_EXPECTING_A_TIME)     , "expecting a time"},
+	{ERR_REASON(ASN1_R_EXPLICIT_LENGTH_MISMATCH), "explicit length mismatch"},
+	{ERR_REASON(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), "explicit tag not constructed"},
+	{ERR_REASON(ASN1_R_FIELD_MISSING)        , "field missing"},
+	{ERR_REASON(ASN1_R_FIRST_NUM_TOO_LARGE)  , "first num too large"},
+	{ERR_REASON(ASN1_R_HEADER_TOO_LONG)      , "header too long"},
+	{ERR_REASON(ASN1_R_ILLEGAL_BITSTRING_FORMAT), "illegal bitstring format"},
+	{ERR_REASON(ASN1_R_ILLEGAL_BOOLEAN)      , "illegal boolean"},
+	{ERR_REASON(ASN1_R_ILLEGAL_CHARACTERS)   , "illegal characters"},
+	{ERR_REASON(ASN1_R_ILLEGAL_FORMAT)       , "illegal format"},
+	{ERR_REASON(ASN1_R_ILLEGAL_HEX)          , "illegal hex"},
+	{ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG) , "illegal implicit tag"},
+	{ERR_REASON(ASN1_R_ILLEGAL_INTEGER)      , "illegal integer"},
+	{ERR_REASON(ASN1_R_ILLEGAL_NEGATIVE_VALUE), "illegal negative value"},
+	{ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"},
+	{ERR_REASON(ASN1_R_ILLEGAL_NULL)         , "illegal null"},
+	{ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE)   , "illegal null value"},
+	{ERR_REASON(ASN1_R_ILLEGAL_OBJECT)       , "illegal object"},
+	{ERR_REASON(ASN1_R_ILLEGAL_OPTIONAL_ANY) , "illegal optional any"},
+	{ERR_REASON(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), "illegal options on item template"},
+	{ERR_REASON(ASN1_R_ILLEGAL_TAGGED_ANY)   , "illegal tagged any"},
+	{ERR_REASON(ASN1_R_ILLEGAL_TIME_VALUE)   , "illegal time value"},
+	{ERR_REASON(ASN1_R_INTEGER_NOT_ASCII_FORMAT), "integer not ascii format"},
+	{ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), "integer too large for long"},
+	{ERR_REASON(ASN1_R_INVALID_BIT_STRING_BITS_LEFT), "invalid bit string bits left"},
+	{ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH), "invalid bmpstring length"},
+	{ERR_REASON(ASN1_R_INVALID_DIGIT)        , "invalid digit"},
+	{ERR_REASON(ASN1_R_INVALID_MIME_TYPE)    , "invalid mime type"},
+	{ERR_REASON(ASN1_R_INVALID_MODIFIER)     , "invalid modifier"},
+	{ERR_REASON(ASN1_R_INVALID_NUMBER)       , "invalid number"},
+	{ERR_REASON(ASN1_R_INVALID_OBJECT_ENCODING), "invalid object encoding"},
+	{ERR_REASON(ASN1_R_INVALID_SEPARATOR)    , "invalid separator"},
+	{ERR_REASON(ASN1_R_INVALID_TIME_FORMAT)  , "invalid time format"},
+	{ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), "invalid universalstring length"},
+	{ERR_REASON(ASN1_R_INVALID_UTF8STRING)   , "invalid utf8string"},
+	{ERR_REASON(ASN1_R_IV_TOO_LARGE)         , "iv too large"},
+	{ERR_REASON(ASN1_R_LENGTH_ERROR)         , "length error"},
+	{ERR_REASON(ASN1_R_LIST_ERROR)           , "list error"},
+	{ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE) , "mime no content type"},
+	{ERR_REASON(ASN1_R_MIME_PARSE_ERROR)     , "mime parse error"},
+	{ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR) , "mime sig parse error"},
+	{ERR_REASON(ASN1_R_MISSING_EOC)          , "missing eoc"},
+	{ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER), "missing second number"},
+	{ERR_REASON(ASN1_R_MISSING_VALUE)        , "missing value"},
+	{ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"},
+	{ERR_REASON(ASN1_R_MSTRING_WRONG_TAG)    , "mstring wrong tag"},
+	{ERR_REASON(ASN1_R_NESTED_ASN1_STRING)   , "nested asn1 string"},
+	{ERR_REASON(ASN1_R_NESTED_TOO_DEEP)      , "nested too deep"},
+	{ERR_REASON(ASN1_R_NON_HEX_CHARACTERS)   , "non hex characters"},
+	{ERR_REASON(ASN1_R_NOT_ASCII_FORMAT)     , "not ascii format"},
+	{ERR_REASON(ASN1_R_NOT_ENOUGH_DATA)      , "not enough data"},
+	{ERR_REASON(ASN1_R_NO_CONTENT_TYPE)      , "no content type"},
+	{ERR_REASON(ASN1_R_NO_DEFAULT_DIGEST)    , "no default digest"},
+	{ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE), "no matching choice type"},
+	{ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE), "no multipart body failure"},
+	{ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY), "no multipart boundary"},
+	{ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE)  , "no sig content type"},
+	{ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH) , "null is wrong length"},
+	{ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT), "object not ascii format"},
+	{ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS)  , "odd number of chars"},
+	{ERR_REASON(ASN1_R_PRIVATE_KEY_HEADER_MISSING), "private key header missing"},
+	{ERR_REASON(ASN1_R_SECOND_NUMBER_TOO_LARGE), "second number too large"},
+	{ERR_REASON(ASN1_R_SEQUENCE_LENGTH_MISMATCH), "sequence length mismatch"},
+	{ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "sequence not constructed"},
+	{ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), "sequence or set needs config"},
+	{ERR_REASON(ASN1_R_SHORT_LINE)           , "short line"},
+	{ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE), "sig invalid mime type"},
+	{ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED), "streaming not supported"},
+	{ERR_REASON(ASN1_R_STRING_TOO_LONG)      , "string too long"},
+	{ERR_REASON(ASN1_R_STRING_TOO_SHORT)     , "string too short"},
+	{ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH)   , "tag value too high"},
+	{ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"},
+	{ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"},
+	{ERR_REASON(ASN1_R_TOO_LARGE)            , "too large"},
+	{ERR_REASON(ASN1_R_TOO_LONG)             , "too long"},
+	{ERR_REASON(ASN1_R_TOO_SMALL)            , "too small"},
+	{ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED) , "type not constructed"},
+	{ERR_REASON(ASN1_R_TYPE_NOT_PRIMITIVE)   , "type not primitive"},
+	{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "unable to decode rsa key"},
+	{ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "unable to decode rsa private key"},
+	{ERR_REASON(ASN1_R_UNEXPECTED_EOC)       , "unexpected eoc"},
+	{ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), "universalstring is wrong length"},
+	{ERR_REASON(ASN1_R_UNKNOWN_FORMAT)       , "unknown format"},
+	{ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), "unknown message digest algorithm"},
+	{ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE)  , "unknown object type"},
+	{ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "unknown public key type"},
+	{ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM), "unknown signature algorithm"},
+	{ERR_REASON(ASN1_R_UNKNOWN_TAG)          , "unknown tag"},
+	{ERR_REASON(ASN1_R_UNKOWN_FORMAT)        , "unknown format"},
+	{ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), "unsupported any defined by type"},
+	{ERR_REASON(ASN1_R_UNSUPPORTED_CIPHER)   , "unsupported cipher"},
+	{ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "unsupported encryption algorithm"},
+	{ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"},
+	{ERR_REASON(ASN1_R_UNSUPPORTED_TYPE)     , "unsupported type"},
+	{ERR_REASON(ASN1_R_WRONG_INTEGER_TYPE)   , "wrong integer type"},
+	{ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"},
+	{ERR_REASON(ASN1_R_WRONG_TAG)            , "wrong tag"},
+	{ERR_REASON(ASN1_R_WRONG_TYPE)           , "wrong type"},
+	{0, NULL}
+};
+#endif
+
+void
+ERR_load_ASN1_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, ASN1_str_functs);
+		ERR_load_strings(0, ASN1_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_ASN1_strings);
diff --git a/crypto/asn1/asn1_gen.c b/crypto/asn1/asn1_gen.c
new file mode 100644
index 0000000..228f236
--- /dev/null
+++ b/crypto/asn1/asn1_gen.c
@@ -0,0 +1,804 @@
+/* $OpenBSD: asn1_gen.c,v 1.21 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+#define ASN1_GEN_FLAG		0x10000
+#define ASN1_GEN_FLAG_IMP	(ASN1_GEN_FLAG|1)
+#define ASN1_GEN_FLAG_EXP	(ASN1_GEN_FLAG|2)
+#define ASN1_GEN_FLAG_TAG	(ASN1_GEN_FLAG|3)
+#define ASN1_GEN_FLAG_BITWRAP	(ASN1_GEN_FLAG|4)
+#define ASN1_GEN_FLAG_OCTWRAP	(ASN1_GEN_FLAG|5)
+#define ASN1_GEN_FLAG_SEQWRAP	(ASN1_GEN_FLAG|6)
+#define ASN1_GEN_FLAG_SETWRAP	(ASN1_GEN_FLAG|7)
+#define ASN1_GEN_FLAG_FORMAT	(ASN1_GEN_FLAG|8)
+
+#define ASN1_GEN_STR(str,val){str, sizeof(str) - 1, val}
+
+#define ASN1_FLAG_EXP_MAX	20
+
+/* Input formats */
+
+/* ASCII: default */
+#define ASN1_GEN_FORMAT_ASCII	1
+/* UTF8 */
+#define ASN1_GEN_FORMAT_UTF8	2
+/* Hex */
+#define ASN1_GEN_FORMAT_HEX	3
+/* List of bits */
+#define ASN1_GEN_FORMAT_BITLIST	4
+
+struct tag_name_st {
+	const char *strnam;
+	int len;
+	int tag;
+};
+
+typedef struct {
+	int exp_tag;
+	int exp_class;
+	int exp_constructed;
+	int exp_pad;
+	long exp_len;
+} tag_exp_type;
+
+typedef struct {
+	int imp_tag;
+	int imp_class;
+	int utype;
+	int format;
+	const char *str;
+	tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
+	int exp_count;
+} tag_exp_arg;
+
+static int bitstr_cb(const char *elem, int len, void *bitstr);
+static int asn1_cb(const char *elem, int len, void *bitstr);
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
+    int exp_constructed, int exp_pad, int imp_ok);
+static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass);
+static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
+static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
+static int asn1_str2tag(const char *tagstr, int len);
+
+ASN1_TYPE *
+ASN1_generate_nconf(const char *str, CONF *nconf)
+{
+	X509V3_CTX cnf;
+
+	if (!nconf)
+		return ASN1_generate_v3(str, NULL);
+
+	X509V3_set_nconf(&cnf, nconf);
+	return ASN1_generate_v3(str, &cnf);
+}
+LCRYPTO_ALIAS(ASN1_generate_nconf);
+
+ASN1_TYPE *
+ASN1_generate_v3(const char *str, X509V3_CTX *cnf)
+{
+	ASN1_TYPE *ret;
+	tag_exp_arg asn1_tags;
+	tag_exp_type *etmp;
+
+	int i, len;
+
+	unsigned char *orig_der = NULL, *new_der = NULL;
+	const unsigned char *cpy_start;
+	unsigned char *p;
+	const unsigned char *cp;
+	int cpy_len;
+	long hdr_len = 0;
+	int hdr_constructed = 0, hdr_tag, hdr_class;
+	int r;
+
+	asn1_tags.imp_tag = -1;
+	asn1_tags.imp_class = -1;
+	asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
+	asn1_tags.exp_count = 0;
+	if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
+		return NULL;
+
+	if ((asn1_tags.utype == V_ASN1_SEQUENCE) ||
+	    (asn1_tags.utype == V_ASN1_SET)) {
+		if (!cnf) {
+			ASN1error(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+			return NULL;
+		}
+		ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
+	} else
+		ret = asn1_str2type(asn1_tags.str, asn1_tags.format,
+		    asn1_tags.utype);
+
+	if (!ret)
+		return NULL;
+
+	/* If no tagging return base type */
+	if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
+		return ret;
+
+	/* Generate the encoding */
+	cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
+	ASN1_TYPE_free(ret);
+	ret = NULL;
+	/* Set point to start copying for modified encoding */
+	cpy_start = orig_der;
+
+	/* Do we need IMPLICIT tagging? */
+	if (asn1_tags.imp_tag != -1) {
+		/* If IMPLICIT we will replace the underlying tag */
+		/* Skip existing tag+len */
+		r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag,
+		    &hdr_class, cpy_len);
+		if (r & 0x80)
+			goto err;
+		/* Update copy length */
+		cpy_len -= cpy_start - orig_der;
+		/* For IMPLICIT tagging the length should match the
+		 * original length and constructed flag should be
+		 * consistent.
+		 */
+		if (r & 0x1) {
+			/* Indefinite length constructed */
+			hdr_constructed = 2;
+			hdr_len = 0;
+		} else
+			/* Just retain constructed flag */
+			hdr_constructed = r & V_ASN1_CONSTRUCTED;
+		/* Work out new length with IMPLICIT tag: ignore constructed
+		 * because it will mess up if indefinite length
+		 */
+		len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
+	} else
+		len = cpy_len;
+
+	/* Work out length in any EXPLICIT, starting from end */
+
+	for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
+	    i < asn1_tags.exp_count; i++, etmp--) {
+		/* Content length: number of content octets + any padding */
+		len += etmp->exp_pad;
+		etmp->exp_len = len;
+		/* Total object length: length including new header */
+		len = ASN1_object_size(0, len, etmp->exp_tag);
+	}
+
+	/* Allocate buffer for new encoding */
+
+	new_der = malloc(len);
+	if (!new_der)
+		goto err;
+
+	/* Generate tagged encoding */
+	p = new_der;
+
+	/* Output explicit tags first */
+	for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
+	    i++, etmp++) {
+		ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
+		    etmp->exp_tag, etmp->exp_class);
+		if (etmp->exp_pad)
+			*p++ = 0;
+	}
+
+	/* If IMPLICIT, output tag */
+
+	if (asn1_tags.imp_tag != -1) {
+		if (asn1_tags.imp_class == V_ASN1_UNIVERSAL &&
+		    (asn1_tags.imp_tag == V_ASN1_SEQUENCE ||
+		    asn1_tags.imp_tag == V_ASN1_SET))
+			hdr_constructed = V_ASN1_CONSTRUCTED;
+		ASN1_put_object(&p, hdr_constructed, hdr_len,
+		    asn1_tags.imp_tag, asn1_tags.imp_class);
+	}
+
+	/* Copy across original encoding */
+	memcpy(p, cpy_start, cpy_len);
+
+	cp = new_der;
+
+	/* Obtain new ASN1_TYPE structure */
+	ret = d2i_ASN1_TYPE(NULL, &cp, len);
+
+ err:
+	free(orig_der);
+	free(new_der);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_generate_v3);
+
+static int
+asn1_cb(const char *elem, int len, void *bitstr)
+{
+	tag_exp_arg *arg = bitstr;
+	int i;
+	int utype;
+	int vlen = 0;
+	const char *p, *vstart = NULL;
+
+	int tmp_tag, tmp_class;
+
+	for (i = 0, p = elem; i < len; p++, i++) {
+		/* Look for the ':' in name value pairs */
+		if (*p == ':') {
+			vstart = p + 1;
+			vlen = len - (vstart - elem);
+			len = p - elem;
+			break;
+		}
+	}
+
+	utype = asn1_str2tag(elem, len);
+
+	if (utype == -1) {
+		ASN1error(ASN1_R_UNKNOWN_TAG);
+		ERR_asprintf_error_data("tag=%s", elem);
+		return -1;
+	}
+
+	/* If this is not a modifier mark end of string and exit */
+	if (!(utype & ASN1_GEN_FLAG)) {
+		arg->utype = utype;
+		arg->str = vstart;
+		/* If no value and not end of string, error */
+		if (!vstart && elem[len]) {
+			ASN1error(ASN1_R_MISSING_VALUE);
+			return -1;
+		}
+		return 0;
+	}
+
+	switch (utype) {
+
+	case ASN1_GEN_FLAG_IMP:
+		/* Check for illegal multiple IMPLICIT tagging */
+		if (arg->imp_tag != -1) {
+			ASN1error(ASN1_R_ILLEGAL_NESTED_TAGGING);
+			return -1;
+		}
+		if (!parse_tagging(vstart, vlen, &arg->imp_tag,
+		    &arg->imp_class))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_EXP:
+		if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
+			return -1;
+		if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_SEQWRAP:
+		if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_SETWRAP:
+		if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_BITWRAP:
+		if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_OCTWRAP:
+		if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
+			return -1;
+		break;
+
+	case ASN1_GEN_FLAG_FORMAT:
+		if (vstart == NULL) {
+			ASN1error(ASN1_R_ILLEGAL_FORMAT);
+			return -1;
+		}
+		if (!strncmp(vstart, "ASCII", 5))
+			arg->format = ASN1_GEN_FORMAT_ASCII;
+		else if (!strncmp(vstart, "UTF8", 4))
+			arg->format = ASN1_GEN_FORMAT_UTF8;
+		else if (!strncmp(vstart, "HEX", 3))
+			arg->format = ASN1_GEN_FORMAT_HEX;
+		else if (!strncmp(vstart, "BITLIST", 7))
+			arg->format = ASN1_GEN_FORMAT_BITLIST;
+		else {
+			ASN1error(ASN1_R_UNKOWN_FORMAT);
+			return -1;
+		}
+		break;
+
+	}
+
+	return 1;
+}
+
+static int
+parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
+{
+	long tag_num;
+	char *eptr;
+
+	if (!vstart)
+		return 0;
+	tag_num = strtoul(vstart, &eptr, 10);
+	/* Check we haven't gone past max length: should be impossible */
+	if (eptr && *eptr && (eptr > vstart + vlen))
+		return 0;
+	if (tag_num < 0) {
+		ASN1error(ASN1_R_INVALID_NUMBER);
+		return 0;
+	}
+	*ptag = tag_num;
+	/* If we have non numeric characters, parse them */
+	if (eptr)
+		vlen -= eptr - vstart;
+	else
+		vlen = 0;
+	if (vlen) {
+		switch (*eptr) {
+
+		case 'U':
+			*pclass = V_ASN1_UNIVERSAL;
+			break;
+
+		case 'A':
+			*pclass = V_ASN1_APPLICATION;
+			break;
+
+		case 'P':
+			*pclass = V_ASN1_PRIVATE;
+			break;
+
+		case 'C':
+			*pclass = V_ASN1_CONTEXT_SPECIFIC;
+			break;
+
+		default:
+			ASN1error(ASN1_R_INVALID_MODIFIER);
+			ERR_asprintf_error_data("Char=%c", *eptr);
+			return 0;
+			break;
+
+		}
+	} else
+		*pclass = V_ASN1_CONTEXT_SPECIFIC;
+
+	return 1;
+
+}
+
+/* Handle multiple types: SET and SEQUENCE */
+
+static ASN1_TYPE *
+asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
+{
+	ASN1_TYPE *ret = NULL;
+	STACK_OF(ASN1_TYPE) *sk = NULL;
+	STACK_OF(CONF_VALUE) *sect = NULL;
+	unsigned char *der = NULL;
+	int derlen;
+	int i;
+	sk = sk_ASN1_TYPE_new_null();
+	if (!sk)
+		goto bad;
+	if (section) {
+		if (!cnf)
+			goto bad;
+		sect = X509V3_get_section(cnf, (char *)section);
+		if (!sect)
+			goto bad;
+		for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
+			ASN1_TYPE *typ = ASN1_generate_v3(
+			    sk_CONF_VALUE_value(sect, i)->value, cnf);
+			if (!typ)
+				goto bad;
+			if (!sk_ASN1_TYPE_push(sk, typ))
+				goto bad;
+		}
+	}
+
+	/* Now we has a STACK of the components, convert to the correct form */
+
+	if (utype == V_ASN1_SET)
+		derlen = i2d_ASN1_SET_ANY(sk, &der);
+	else
+		derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
+
+	if (derlen < 0)
+		goto bad;
+
+	if (!(ret = ASN1_TYPE_new()))
+		goto bad;
+
+	if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
+		goto bad;
+
+	ret->type = utype;
+
+	ret->value.asn1_string->data = der;
+	ret->value.asn1_string->length = derlen;
+
+	der = NULL;
+
+ bad:
+	free(der);
+	if (sk)
+		sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+	if (sect)
+		X509V3_section_free(cnf, sect);
+
+	return ret;
+}
+
+static int
+append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed,
+    int exp_pad, int imp_ok)
+{
+	tag_exp_type *exp_tmp;
+
+	/* Can only have IMPLICIT if permitted */
+	if ((arg->imp_tag != -1) && !imp_ok) {
+		ASN1error(ASN1_R_ILLEGAL_IMPLICIT_TAG);
+		return 0;
+	}
+
+	if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
+		ASN1error(ASN1_R_DEPTH_EXCEEDED);
+		return 0;
+	}
+
+	exp_tmp = &arg->exp_list[arg->exp_count++];
+
+	/* If IMPLICIT set tag to implicit value then
+	 * reset implicit tag since it has been used.
+	 */
+	if (arg->imp_tag != -1) {
+		exp_tmp->exp_tag = arg->imp_tag;
+		exp_tmp->exp_class = arg->imp_class;
+		arg->imp_tag = -1;
+		arg->imp_class = -1;
+	} else {
+		exp_tmp->exp_tag = exp_tag;
+		exp_tmp->exp_class = exp_class;
+	}
+	exp_tmp->exp_constructed = exp_constructed;
+	exp_tmp->exp_pad = exp_pad;
+
+	return 1;
+}
+
+static int
+asn1_str2tag(const char *tagstr, int len)
+{
+	unsigned int i;
+	static const struct tag_name_st *tntmp, tnst [] = {
+		ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
+		ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
+		ASN1_GEN_STR("NULL", V_ASN1_NULL),
+		ASN1_GEN_STR("INT", V_ASN1_INTEGER),
+		ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
+		ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
+		ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
+		ASN1_GEN_STR("OID", V_ASN1_OBJECT),
+		ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
+		ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
+		ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
+		ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
+		ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
+		ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
+		ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
+		ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
+		ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
+		ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
+		ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
+		ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
+		ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
+		ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
+		ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
+		ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
+		ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
+		ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
+		ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
+		ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
+		ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
+		ASN1_GEN_STR("T61", V_ASN1_T61STRING),
+		ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
+		ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
+		ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
+		ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
+		ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
+		ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
+
+		/* Special cases */
+		ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
+		ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
+		ASN1_GEN_STR("SET", V_ASN1_SET),
+		/* type modifiers */
+		/* Explicit tag */
+		ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
+		ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
+		/* Implicit tag */
+		ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
+		ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
+		/* OCTET STRING wrapper */
+		ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
+		/* SEQUENCE wrapper */
+		ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
+		/* SET wrapper */
+		ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
+		/* BIT STRING wrapper */
+		ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
+		ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
+		ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
+	};
+
+	if (len == -1)
+		len = strlen(tagstr);
+
+	tntmp = tnst;
+	for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st);
+	    i++, tntmp++) {
+		if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
+			return tntmp->tag;
+	}
+
+	return -1;
+}
+
+static ASN1_TYPE *
+asn1_str2type(const char *str, int format, int utype)
+{
+	ASN1_TYPE *atmp = NULL;
+	CONF_VALUE vtmp;
+	unsigned char *rdata;
+	long rdlen;
+	int no_unused = 1;
+
+	if (!(atmp = ASN1_TYPE_new())) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (!str)
+		str = "";
+
+	switch (utype) {
+
+	case V_ASN1_NULL:
+		if (str && *str) {
+			ASN1error(ASN1_R_ILLEGAL_NULL_VALUE);
+			goto bad_form;
+		}
+		break;
+
+	case V_ASN1_BOOLEAN:
+		if (format != ASN1_GEN_FORMAT_ASCII) {
+			ASN1error(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)) {
+			ASN1error(ASN1_R_ILLEGAL_BOOLEAN);
+			goto bad_str;
+		}
+		break;
+
+	case V_ASN1_INTEGER:
+	case V_ASN1_ENUMERATED:
+		if (format != ASN1_GEN_FORMAT_ASCII) {
+			ASN1error(ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+			goto bad_form;
+		}
+		if (!(atmp->value.integer =
+		    s2i_ASN1_INTEGER(NULL, (char *)str))) {
+			ASN1error(ASN1_R_ILLEGAL_INTEGER);
+			goto bad_str;
+		}
+		break;
+
+	case V_ASN1_OBJECT:
+		if (format != ASN1_GEN_FORMAT_ASCII) {
+			ASN1error(ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+			goto bad_form;
+		}
+		if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
+			ASN1error(ASN1_R_ILLEGAL_OBJECT);
+			goto bad_str;
+		}
+		break;
+
+	case V_ASN1_UTCTIME:
+	case V_ASN1_GENERALIZEDTIME:
+		if (format != ASN1_GEN_FORMAT_ASCII) {
+			ASN1error(ASN1_R_TIME_NOT_ASCII_FORMAT);
+			goto bad_form;
+		}
+		if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto bad_str;
+		}
+		if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto bad_str;
+		}
+		atmp->value.asn1_string->type = utype;
+		if (!ASN1_TIME_check(atmp->value.asn1_string)) {
+			ASN1error(ASN1_R_ILLEGAL_TIME_VALUE);
+			goto bad_str;
+		}
+		break;
+
+	case V_ASN1_BMPSTRING:
+	case V_ASN1_PRINTABLESTRING:
+	case V_ASN1_IA5STRING:
+	case V_ASN1_T61STRING:
+	case V_ASN1_UTF8STRING:
+	case V_ASN1_VISIBLESTRING:
+	case V_ASN1_UNIVERSALSTRING:
+	case V_ASN1_GENERALSTRING:
+	case V_ASN1_NUMERICSTRING:
+
+		if (format == ASN1_GEN_FORMAT_ASCII)
+			format = MBSTRING_ASC;
+		else if (format == ASN1_GEN_FORMAT_UTF8)
+			format = MBSTRING_UTF8;
+		else {
+			ASN1error(ASN1_R_ILLEGAL_FORMAT);
+			goto bad_form;
+		}
+
+		if (ASN1_mbstring_copy(&atmp->value.asn1_string,
+		    (unsigned char *)str, -1, format,
+		    ASN1_tag2bit(utype)) <= 0) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto bad_str;
+		}
+		break;
+
+	case V_ASN1_BIT_STRING:
+	case V_ASN1_OCTET_STRING:
+		if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto bad_form;
+		}
+
+		if (format == ASN1_GEN_FORMAT_HEX) {
+
+			if (!(rdata = string_to_hex((char *)str, &rdlen))) {
+				ASN1error(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) {
+			if (ASN1_STRING_set(atmp->value.asn1_string, str,
+			    -1) == 0) {
+				ASN1error(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)) {
+				ASN1error(ASN1_R_LIST_ERROR);
+				goto bad_str;
+			}
+			no_unused = 0;
+
+		} else {
+			ASN1error(ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+			goto bad_form;
+		}
+
+		if ((utype == V_ASN1_BIT_STRING) && no_unused) {
+			if (!asn1_abs_set_unused_bits(atmp->value.asn1_string,
+			    0))
+				goto bad_str;
+		}
+
+		break;
+
+	default:
+		ASN1error(ASN1_R_UNSUPPORTED_TYPE);
+		goto bad_str;
+		break;
+	}
+
+	atmp->type = utype;
+	return atmp;
+
+ bad_str:
+	ERR_asprintf_error_data("string=%s", str);
+ bad_form:
+	ASN1_TYPE_free(atmp);
+	return NULL;
+}
+
+static int
+bitstr_cb(const char *elem, int len, void *bitstr)
+{
+	long bitnum;
+	char *eptr;
+
+	if (!elem)
+		return 0;
+	bitnum = strtoul(elem, &eptr, 10);
+	if (eptr && *eptr && (eptr != elem + len))
+		return 0;
+	if (bitnum < 0) {
+		ASN1error(ASN1_R_INVALID_NUMBER);
+		return 0;
+	}
+	if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	return 1;
+}
diff --git a/crypto/asn1/asn1_item.c b/crypto/asn1/asn1_item.c
new file mode 100644
index 0000000..87f426c
--- /dev/null
+++ b/crypto/asn1/asn1_item.c
@@ -0,0 +1,689 @@
+/* $OpenBSD: asn1_item.c,v 1.17 2023/07/13 20:59:10 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+int
+ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
+    unsigned char *md, unsigned int *len)
+{
+	int i;
+	unsigned char *str = NULL;
+
+	i = ASN1_item_i2d(asn, &str, it);
+	if (!str)
+		return (0);
+
+	if (!EVP_Digest(str, i, md, len, type, NULL)) {
+		free(str);
+		return (0);
+	}
+
+	free(str);
+	return (1);
+}
+
+/*
+ * ASN1_ITEM version of ASN1_dup(): follows the same model except there's no
+ * need to allocate the buffer. At some point this could be rewritten to dup
+ * the underlying structure directly instead of doing an encode and decode.
+ */
+
+void *
+ASN1_item_dup(const ASN1_ITEM *it, void *x)
+{
+	unsigned char *b = NULL;
+	const unsigned char *p;
+	long i;
+	void *ret;
+
+	if (x == NULL)
+		return (NULL);
+
+	i = ASN1_item_i2d(x, &b, it);
+	if (b == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	p = b;
+	ret = ASN1_item_d2i(NULL, &p, i, it);
+	free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_item_dup);
+
+/* Pack an ASN1 object into an ASN1_STRING. */
+ASN1_STRING *
+ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
+{
+	ASN1_STRING *octmp;
+
+	if (!oct || !*oct) {
+		if (!(octmp = ASN1_STRING_new ())) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+	} else
+		octmp = *oct;
+
+	free(octmp->data);
+	octmp->data = NULL;
+
+	if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+		ASN1error(ASN1_R_ENCODE_ERROR);
+		goto err;
+	}
+	if (!octmp->data) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (oct)
+		*oct = octmp;
+	return octmp;
+ err:
+	if (!oct || octmp != *oct)
+		ASN1_STRING_free(octmp);
+	return NULL;
+}
+LCRYPTO_ALIAS(ASN1_item_pack);
+
+/* Extract an ASN1 object from an ASN1_STRING. */
+void *
+ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
+{
+	const unsigned char *p;
+	void *ret;
+
+	p = oct->data;
+	if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
+		ASN1error(ASN1_R_DECODE_ERROR);
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_item_unpack);
+
+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)
+{
+	EVP_MD_CTX ctx;
+	EVP_MD_CTX_init(&ctx);
+	if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
+		EVP_MD_CTX_cleanup(&ctx);
+		return 0;
+	}
+	return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+}
+
+static int
+asn1_item_set_algorithm_identifiers(EVP_MD_CTX *ctx, X509_ALGOR *algor1,
+    X509_ALGOR *algor2)
+{
+	EVP_PKEY *pkey;
+	ASN1_OBJECT *aobj;
+	const EVP_MD *md;
+	int sign_id, sign_param;
+
+	if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
+		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
+		return 0;
+	}
+
+	if ((md = EVP_MD_CTX_md(ctx)) == NULL) {
+		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
+		return 0;
+	}
+
+	if (!OBJ_find_sigid_by_algs(&sign_id, EVP_MD_nid(md),
+	    pkey->ameth->pkey_id)) {
+		ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+		return 0;
+	}
+	if ((aobj = OBJ_nid2obj(sign_id)) == NULL) {
+		ASN1error(ASN1_R_UNKNOWN_OBJECT_TYPE);
+		return 0;
+	}
+
+	sign_param = V_ASN1_UNDEF;
+	if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
+		sign_param = V_ASN1_NULL;
+
+	if (algor1 != NULL) {
+		if (!X509_ALGOR_set0(algor1, aobj, sign_param, NULL))
+			return 0;
+	}
+	if (algor2 != NULL) {
+		if (!X509_ALGOR_set0(algor2, aobj, sign_param, NULL))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+asn1_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+    ASN1_BIT_STRING *signature)
+{
+	unsigned char *in = NULL, *out = NULL;
+	size_t out_len = 0;
+	int in_len = 0;
+	int ret = 0;
+
+	if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
+		in_len = 0;
+		goto err;
+	}
+
+	if (!EVP_DigestSign(ctx, NULL, &out_len, in, in_len)) {
+		ASN1error(ERR_R_EVP_LIB);
+		goto err;
+	}
+	if ((out = calloc(1, out_len)) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!EVP_DigestSign(ctx, out, &out_len, in, in_len)) {
+		ASN1error(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	if (out_len > INT_MAX) {
+		ASN1error(ASN1_R_TOO_LONG);
+		goto err;
+	}
+
+	ASN1_STRING_set0(signature, out, out_len);
+	out = NULL;
+
+	if (!asn1_abs_set_unused_bits(signature, 0)) {
+		ASN1_STRING_set0(signature, NULL, 0);
+		ASN1error(ERR_R_ASN1_LIB);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	freezero(in, in_len);
+	freezero(out, out_len);
+
+	return ret;
+}
+
+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)
+{
+	EVP_PKEY *pkey;
+	int rv;
+	int ret = 0;
+
+	if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
+		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
+		goto err;
+	}
+	if (pkey->ameth == NULL) {
+		ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+		goto err;
+	}
+
+	/*
+	 * API insanity ahead. If the item_sign() method is absent or if it
+	 * returns 2, this means: do all the work here. If it returns 3, only
+	 * sign. If it returns 1, then there's nothing to do but to return
+	 * the signature's length. Everything else is an error.
+	 */
+
+	rv = 2;
+	if (pkey->ameth->item_sign != NULL)
+		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
+		    signature);
+	if (rv <= 0 || rv > 3)
+		goto err;
+	if (rv == 1)
+		goto done;
+	if (rv == 2) {
+		if (!asn1_item_set_algorithm_identifiers(ctx, algor1, algor2))
+			goto err;
+	}
+
+	if (!asn1_item_sign(ctx, it, asn, signature))
+		goto err;
+
+ done:
+	ret = signature->length;
+
+ err:
+	EVP_MD_CTX_cleanup(ctx);
+
+	return ret;
+}
+
+int
+ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
+    ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+{
+	EVP_MD_CTX ctx;
+	unsigned char *in = NULL;
+	int mdnid, pknid;
+	int in_len = 0;
+	int ret = -1;
+
+	if (pkey == NULL) {
+		ASN1error(ERR_R_PASSED_NULL_PARAMETER);
+		return -1;
+	}
+
+	if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
+		ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+		return -1;
+	}
+
+	EVP_MD_CTX_init(&ctx);
+
+	/* Convert signature OID into digest and public key OIDs */
+	if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
+		ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+		goto err;
+	}
+	if (mdnid == NID_undef) {
+		if (!pkey->ameth || !pkey->ameth->item_verify) {
+			ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
+			goto err;
+		}
+		ret = pkey->ameth->item_verify(&ctx, it, asn, a,
+		    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.
+		 */
+		if (ret != 2)
+			goto err;
+		ret = -1;
+	} else {
+		const EVP_MD *type;
+		type = EVP_get_digestbynid(mdnid);
+		if (type == NULL) {
+			ASN1error(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) {
+			ASN1error(ASN1_R_WRONG_PUBLIC_KEY_TYPE);
+			goto err;
+		}
+
+		if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) {
+			ASN1error(ERR_R_EVP_LIB);
+			ret = 0;
+			goto err;
+		}
+
+	}
+
+	if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		in_len = 0;
+		goto err;
+	}
+
+	if (EVP_DigestVerify(&ctx, signature->data, signature->length,
+	    in, in_len) <= 0) {
+		ASN1error(ERR_R_EVP_LIB);
+		ret = 0;
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	EVP_MD_CTX_cleanup(&ctx);
+	freezero(in, in_len);
+
+	return ret;
+}
+
+#define HEADER_SIZE   8
+#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
+int
+asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
+{
+	BUF_MEM *b;
+	unsigned char *p;
+	const unsigned char *q;
+	long slen;
+	int i, inf, tag, xclass;
+	size_t want = HEADER_SIZE;
+	int eos = 0;
+	size_t off = 0;
+	size_t len = 0;
+
+	b = BUF_MEM_new();
+	if (b == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return -1;
+	}
+
+	ERR_clear_error();
+	for (;;) {
+		if (want >= (len - off)) {
+			want -= (len - off);
+
+			if (len + want < len ||
+			    !BUF_MEM_grow_clean(b, len + want)) {
+				ASN1error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			i = BIO_read(in, &(b->data[len]), want);
+			if ((i < 0) && ((len - off) == 0)) {
+				ASN1error(ASN1_R_NOT_ENOUGH_DATA);
+				goto err;
+			}
+			if (i > 0) {
+				if (len + i < len) {
+					ASN1error(ASN1_R_TOO_LONG);
+					goto err;
+				}
+				len += i;
+			}
+		}
+		/* else data already loaded */
+
+		p = (unsigned char *) & (b->data[off]);
+		q = p;
+		inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
+		if (inf & 0x80) {
+			unsigned long e;
+
+			e = ERR_GET_REASON(ERR_peek_error());
+			if (e != ASN1_R_TOO_LONG)
+				goto err;
+			else
+				ERR_clear_error(); /* clear error */
+		}
+		i = q - p;	/* header length */
+		off += i;	/* end of data */
+
+		if (inf & 1) {
+			/* no data body so go round again */
+			eos++;
+			if (eos < 0) {
+				ASN1error(ASN1_R_HEADER_TOO_LONG);
+				goto err;
+			}
+			want = HEADER_SIZE;
+		} else if (eos && slen == 0 && tag == V_ASN1_EOC) {
+			/* eos value, so go back and read another header */
+			eos--;
+			if (eos <= 0)
+				break;
+			else
+				want = HEADER_SIZE;
+		} else {
+			/* suck in slen bytes of data */
+			want = slen;
+			if (want > (len - off)) {
+				size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
+
+				want -= (len - off);
+				if (want > INT_MAX /* BIO_read takes an int length */ ||
+				    len+want < len) {
+					ASN1error(ASN1_R_TOO_LONG);
+					goto err;
+				}
+				while (want > 0) {
+					/*
+					 * Read content in chunks of increasing size
+					 * so we can return an error for EOF without
+					 * having to allocate the entire content length
+					 * in one go.
+					 */
+					size_t chunk = want > chunk_max ? chunk_max : want;
+
+					if (!BUF_MEM_grow_clean(b, len + chunk)) {
+						ASN1error(ERR_R_MALLOC_FAILURE);
+						goto err;
+					}
+					want -= chunk;
+					while (chunk > 0) {
+						i = BIO_read(in, &(b->data[len]), chunk);
+						if (i <= 0) {
+							ASN1error(ASN1_R_NOT_ENOUGH_DATA);
+							goto err;
+						}
+						/*
+						 * This can't overflow because |len+want|
+						 * didn't overflow.
+						 */
+						len += i;
+						chunk -= i;
+					}
+					if (chunk_max < INT_MAX/2)
+						chunk_max *= 2;
+				}
+			}
+			if (off + slen < off) {
+				ASN1error(ASN1_R_TOO_LONG);
+				goto err;
+			}
+			off += slen;
+			if (eos <= 0) {
+				break;
+			} else
+				want = HEADER_SIZE;
+		}
+	}
+
+	if (off > INT_MAX) {
+		ASN1error(ASN1_R_TOO_LONG);
+		goto err;
+	}
+
+	*pb = b;
+	return off;
+
+ err:
+	if (b != NULL)
+		BUF_MEM_free(b);
+	return -1;
+}
+
+void *
+ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
+{
+	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 = (const unsigned char *)b->data;
+	ret = ASN1_item_d2i(x, &p, len, it);
+
+ err:
+	if (b != NULL)
+		BUF_MEM_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_item_d2i_bio);
+
+void *
+ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
+{
+	BIO *b;
+	char *ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ASN1error(ERR_R_BUF_LIB);
+		return (NULL);
+	}
+	BIO_set_fp(b, in, BIO_NOCLOSE);
+	ret = ASN1_item_d2i_bio(it, b, x);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_item_d2i_fp);
+
+int
+ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
+{
+	unsigned char *b = NULL;
+	int i, j = 0, n, ret = 1;
+
+	n = ASN1_item_i2d(x, &b, it);
+	if (b == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (0);
+	}
+
+	for (;;) {
+		i = BIO_write(out, &(b[j]), n);
+		if (i == n)
+			break;
+		if (i <= 0) {
+			ret = 0;
+			break;
+		}
+		j += i;
+		n -= i;
+	}
+	free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_item_i2d_bio);
+
+int
+ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ASN1error(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, out, BIO_NOCLOSE);
+	ret = ASN1_item_i2d_bio(it, b, x);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_item_i2d_fp);
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
new file mode 100644
index 0000000..ac8da0e
--- /dev/null
+++ b/crypto/asn1/asn1_lib.c
@@ -0,0 +1,204 @@
+/* $OpenBSD: asn1_lib.c,v 1.54 2022/05/05 19:18:56 jsing Exp $ */
+/*
+ * Copyright (c) 2021 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "bytestring.h"
+
+int
+asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
+    int *out_constructed, uint32_t *out_tag_number)
+{
+	uint8_t tag_class, tag_val;
+	int tag_constructed;
+	uint32_t tag_number;
+
+	/*
+	 * Decode ASN.1 identifier octets - see ITU-T X.690 section 8.1.2.
+	 */
+
+	*out_class = 0;
+	*out_constructed = 0;
+	*out_tag_number = 0;
+
+	if (!CBS_get_u8(cbs, &tag_val))
+		return 0;
+
+	/*
+	 * ASN.1 tag class, encoding (primitive or constructed) and tag number
+	 * are encoded in one or more identifier octets - the first octet
+	 * contains the 2 bit tag class, the 1 bit encoding type and 5 bits
+	 * of tag number.
+	 *
+	 * For tag numbers larger than 30 (0x1e) the 5 bit tag number in the
+	 * first octet is set to all ones (0x1f) - the tag number is then
+	 * encoded in subsequent octets - each of which have a one bit
+	 * continuation flag and 7 bits of tag number in big-endian form.
+	 * The encoding should not contain leading zeros but can for BER.
+	 */
+	tag_class = (tag_val >> 6) & 0x3;
+	tag_constructed = (tag_val >> 5) & 0x1;
+	tag_number = tag_val & 0x1f;
+
+	/* Long form. */
+	if (tag_number == 0x1f) {
+		tag_number = 0;
+		do {
+			if (!CBS_get_u8(cbs, &tag_val))
+				return 0;
+			if (der_mode && tag_number == 0 && tag_val == 0x80)
+				return 0;
+			if (tag_number > (UINT32_MAX >> 7))
+				return 0;
+			tag_number = tag_number << 7 | (tag_val & 0x7f);
+		} while ((tag_val & 0x80) != 0);
+	}
+
+	*out_class = tag_class;
+	*out_constructed = tag_constructed;
+	*out_tag_number = tag_number;
+
+	return 1;
+}
+
+int
+asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite,
+    size_t *out_length)
+{
+	uint8_t len_bytes;
+	size_t length;
+	uint8_t val;
+
+	/*
+	 * Decode ASN.1 length octets - see ITU-T X.690 section 8.1.3.
+	 */
+
+	*out_length = 0;
+	*out_indefinite = 0;
+
+	if (!CBS_get_u8(cbs, &val))
+		return 0;
+
+	/*
+	 * Short form - length is encoded in the lower 7 bits of a single byte.
+	 */
+	if (val < 0x80) {
+		*out_length = val;
+		return 1;
+	}
+
+	/*
+	 * Indefinite length - content continues until an End of Content (EOC)
+	 * marker is reached. Must be used with constructed encoding.
+	 */
+	if (val == 0x80) {
+		*out_indefinite = 1;
+		return 1;
+	}
+
+	/*
+	 * Long form - the lower 7 bits of the first byte specifies the number
+	 * of bytes used to encode the length, the following bytes specify the
+	 * length in big-endian form. The encoding should not contain leading
+	 * zeros but can for BER. A length value of 0x7f is invalid.
+	 */
+	if ((len_bytes = val & 0x7f) == 0x7f)
+		return 0;
+
+	length = 0;
+
+	while (len_bytes-- > 0) {
+		if (!CBS_get_u8(cbs, &val))
+			return 0;
+		if (der_mode && length == 0 && val == 0)
+			return 0;
+		if (length > (SIZE_MAX >> 8))
+			return 0;
+		length = (length << 8) | val;
+	}
+
+	*out_length = length;
+
+	return 1;
+}
+
+int
+asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_tag_class,
+    int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
+    size_t *out_length)
+{
+	int constructed, indefinite;
+	uint32_t tag_number;
+	uint8_t tag_class;
+	size_t length;
+
+	*out_tag_class = 0;
+	*out_constructed = 0;
+	*out_tag_number = 0;
+	*out_indefinite = 0;
+	*out_length = 0;
+
+	if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed,
+	    &tag_number))
+		return 0;
+	if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length))
+		return 0;
+
+	/* Indefinite length can only be used with constructed encoding. */
+	if (indefinite && !constructed)
+		return 0;
+
+	*out_tag_class = tag_class;
+	*out_constructed = constructed;
+	*out_tag_number = tag_number;
+	*out_indefinite = indefinite;
+	*out_length = length;
+
+	return 1;
+}
+
+int
+asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
+    CBS *out_content)
+{
+	int constructed, indefinite;
+	uint32_t tag_number;
+	uint8_t tag_class;
+	size_t length;
+
+	*out_tag_number = 0;
+
+	CBS_init(out_content, NULL, 0);
+
+	if (!asn1_get_identifier_cbs(cbs, der_mode, &tag_class, &constructed,
+	    &tag_number))
+		return 0;
+	if (!asn1_get_length_cbs(cbs, der_mode, &indefinite, &length))
+		return 0;
+
+	/* A primitive is not constructed and has a definite length. */
+	if (constructed || indefinite)
+		return 0;
+
+	if (!CBS_get_bytes(cbs, out_content, length))
+		return 0;
+
+	*out_tag_number = tag_number;
+
+	return 1;
+}
diff --git a/crypto/asn1/asn1_local.h b/crypto/asn1/asn1_local.h
new file mode 100644
index 0000000..566ace7
--- /dev/null
+++ b/crypto/asn1/asn1_local.h
@@ -0,0 +1,272 @@
+/* $OpenBSD: asn1_local.h,v 1.4 2023/07/28 10:00:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "bytestring.h"
+
+__BEGIN_HIDDEN_DECLS
+
+/* Internal ASN1 structures and functions: not for application use */
+
+ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t);
+void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t);
+
+/* These are used internally in the ASN1_OBJECT to keep track of
+ * whether the names and data need to be free()ed */
+#define ASN1_OBJECT_FLAG_DYNAMIC	 0x01	/* internal use */
+#define ASN1_OBJECT_FLAG_CRITICAL	 0x02	/* critical x509v3 object id */
+#define ASN1_OBJECT_FLAG_DYNAMIC_STRINGS 0x04	/* internal use */
+#define ASN1_OBJECT_FLAG_DYNAMIC_DATA	 0x08	/* internal use */
+struct asn1_object_st {
+	const char *sn, *ln;
+	int nid;
+	int length;
+	const unsigned char *data;	/* data remains const after init */
+	int flags;	/* Should we free this one */
+} /* ASN1_OBJECT */;
+
+/* ASN1 print context structure */
+
+struct asn1_pctx_st {
+	unsigned long flags;
+	unsigned long nm_flags;
+	unsigned long cert_flags;
+	unsigned long oid_flags;
+	unsigned long str_flags;
+} /* ASN1_PCTX */;
+
+/* ASN1 public key method structure */
+
+struct evp_pkey_asn1_method_st {
+	int pkey_id;
+	int pkey_base_id;
+	unsigned long pkey_flags;
+
+	char *pem_str;
+	char *info;
+
+	int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub);
+	int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk);
+	int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
+	int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	    ASN1_PCTX *pctx);
+
+	int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf);
+	int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
+	int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	    ASN1_PCTX *pctx);
+
+	int (*pkey_size)(const EVP_PKEY *pk);
+	int (*pkey_bits)(const EVP_PKEY *pk);
+	int (*pkey_security_bits)(const EVP_PKEY *pk);
+
+	int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder,
+	    int derlen);
+	int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder);
+	int (*param_missing)(const EVP_PKEY *pk);
+	int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
+	int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
+	int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+	    ASN1_PCTX *pctx);
+	int (*sig_print)(BIO *out, const X509_ALGOR *sigalg,
+	    const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx);
+
+	void (*pkey_free)(EVP_PKEY *pkey);
+	int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2);
+
+	/* Legacy functions for old PEM */
+
+	int (*old_priv_decode)(EVP_PKEY *pkey, const unsigned char **pder,
+	    int derlen);
+	int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
+	/* Custom ASN1 signature verification */
+	int (*item_verify)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+	    X509_ALGOR *a, ASN1_BIT_STRING *sig, EVP_PKEY *pkey);
+	int (*item_sign)(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
+	    X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig);
+
+	int (*pkey_check)(const EVP_PKEY *pk);
+	int (*pkey_public_check)(const EVP_PKEY *pk);
+	int (*pkey_param_check)(const EVP_PKEY *pk);
+
+	int (*set_priv_key)(EVP_PKEY *pk, const unsigned char *private_key,
+	    size_t len);
+	int (*set_pub_key)(EVP_PKEY *pk, const unsigned char *public_key,
+	    size_t len);
+	int (*get_priv_key)(const EVP_PKEY *pk, unsigned char *out_private_key,
+	    size_t *out_len);
+	int (*get_pub_key)(const EVP_PKEY *pk, unsigned char *out_public_key,
+	    size_t *out_len);
+} /* EVP_PKEY_ASN1_METHOD */;
+
+/* Method to handle CRL access.
+ * In general a CRL could be very large (several Mb) and can consume large
+ * amounts of resources if stored in memory by multiple processes.
+ * This method allows general CRL operations to be redirected to more
+ * efficient callbacks: for example a CRL entry database.
+ */
+
+#define X509_CRL_METHOD_DYNAMIC		1
+
+struct x509_crl_method_st {
+	int flags;
+	int (*crl_init)(X509_CRL *crl);
+	int (*crl_free)(X509_CRL *crl);
+	int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
+	    ASN1_INTEGER *ser, X509_NAME *issuer);
+	int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
+};
+
+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);
+
+ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr);
+
+int 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_cleanup(ASN1_VALUE **pval, const ASN1_ITEM *it);
+int asn1_enc_save(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it);
+int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int i2d_ASN1_BOOLEAN(int a, unsigned char **pp);
+int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length);
+
+/*
+ * Unicode codepoint constants
+ */
+#define	UNICODE_MAX		0x10FFFF
+#define	UNICODE_SURROGATE_MIN	0x00D800
+#define	UNICODE_SURROGATE_MAX	0x00DFFF
+
+#define	UNICODE_IS_SURROGATE(x) \
+	((x) >= UNICODE_SURROGATE_MIN && (x) <= UNICODE_SURROGATE_MAX)
+
+int UTF8_getc(const unsigned char *str, int len, unsigned long *val);
+int UTF8_putc(unsigned char *str, int len, unsigned long value);
+
+int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
+
+int asn1_get_identifier_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
+    int *out_constructed, uint32_t *out_tag_number);
+int asn1_get_length_cbs(CBS *cbs, int der_mode, int *out_indefinite,
+    size_t *out_length);
+int asn1_get_object_cbs(CBS *cbs, int der_mode, uint8_t *out_class,
+    int *out_constructed, uint32_t *out_tag_number, int *out_indefinite,
+    size_t *out_length);
+int asn1_get_primitive(CBS *cbs, int der_mode, uint32_t *out_tag_number,
+    CBS *out_content);
+
+int asn1_must_be_constructed(int tag);
+int asn1_must_be_primitive(int tag);
+int asn1_tag2charwidth(int tag);
+
+int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits);
+int c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs);
+
+int c2i_ASN1_ENUMERATED_cbs(ASN1_ENUMERATED **out_aenum, CBS *cbs);
+
+int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val);
+int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len);
+int asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val);
+int c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs);
+
+int c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content);
+int i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len,
+    int no_name);
+ASN1_OBJECT *t2i_ASN1_OBJECT_internal(const char *oid);
+
+int asn1_time_parse_cbs(const CBS *cbs, int is_gentime, struct tm *out_tm);
+
+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);
+int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from,
+    const struct tm *to);
+int asn1_time_time_t_to_tm(const time_t *time, struct tm *out_tm);
+int asn1_time_tm_to_time_t(const struct tm *tm, time_t *out);
+
+int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
+
+const BIO_METHOD *BIO_f_asn1(void);
+
+BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
+
+int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+    const ASN1_ITEM *it);
+int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+    const char *hdr, const ASN1_ITEM *it);
+int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags,
+    int ctype_nid, int econt_nid, STACK_OF(X509_ALGOR) *mdalgs,
+    const ASN1_ITEM *it);
+ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
+
+int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+
+__END_HIDDEN_DECLS
diff --git a/crypto/asn1/asn1_old.c b/crypto/asn1/asn1_old.c
new file mode 100644
index 0000000..a9aeeb8
--- /dev/null
+++ b/crypto/asn1/asn1_old.c
@@ -0,0 +1,184 @@
+/* $OpenBSD: asn1_old.c,v 1.5 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+#ifndef NO_OLD_ASN1
+
+void *
+ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
+{
+	unsigned char *b, *p;
+	const unsigned char *p2;
+	int i;
+	char *ret;
+
+	if (x == NULL)
+		return (NULL);
+
+	i = i2d(x, NULL);
+	b = malloc(i + 10);
+	if (b == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	p = b;
+	i = i2d(x, &p);
+	p2 = b;
+	ret = d2i(NULL, &p2, i);
+	free(b);
+	return (ret);
+}
+
+void *
+ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
+{
+	BIO *b;
+	void *ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ASN1error(ERR_R_BUF_LIB);
+		return (NULL);
+	}
+	BIO_set_fp(b, in, BIO_NOCLOSE);
+	ret = ASN1_d2i_bio(xnew, d2i, b, x);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_d2i_fp);
+
+void *
+ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
+{
+	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(x, &p, len);
+
+ err:
+	if (b != NULL)
+		BUF_MEM_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_d2i_bio);
+
+int
+ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ASN1error(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, out, BIO_NOCLOSE);
+	ret = ASN1_i2d_bio(i2d, b, x);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_i2d_fp);
+
+int
+ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x)
+{
+	char *b;
+	unsigned char *p;
+	int i, j = 0, n, ret = 1;
+
+	n = i2d(x, NULL);
+	b = malloc(n);
+	if (b == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (0);
+	}
+
+	p = (unsigned char *)b;
+	i2d(x, &p);
+
+	for (;;) {
+		i = BIO_write(out, &(b[j]), n);
+		if (i == n)
+			break;
+		if (i <= 0) {
+			ret = 0;
+			break;
+		}
+		j += i;
+		n -= i;
+	}
+	free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_i2d_bio);
+
+#endif
diff --git a/crypto/asn1/asn1_old_lib.c b/crypto/asn1/asn1_old_lib.c
new file mode 100644
index 0000000..80362ae
--- /dev/null
+++ b/crypto/asn1/asn1_old_lib.c
@@ -0,0 +1,216 @@
+/* $OpenBSD: asn1_old_lib.c,v 1.6 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+
+static void asn1_put_length(unsigned char **pp, int length);
+
+int
+ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
+    int *pclass, long omax)
+{
+	int constructed, indefinite;
+	uint32_t tag_number;
+	uint8_t tag_class;
+	size_t length;
+	CBS cbs;
+	int ret = 0;
+
+	*pclass = 0;
+	*ptag = 0;
+	*plength = 0;
+
+	CBS_init(&cbs, *pp, omax);
+
+	if (!asn1_get_object_cbs(&cbs, 0, &tag_class, &constructed, &tag_number,
+	    &indefinite, &length)) {
+		ASN1error(ASN1_R_HEADER_TOO_LONG);
+		return 0x80;
+	}
+
+	if (tag_number > INT_MAX) {
+		ASN1error(ASN1_R_HEADER_TOO_LONG);
+		return 0x80;
+	}
+
+	/*
+	 * API insanity ahead... in this case we add an error to the stack and
+	 * signal an error by setting the 8th bit in the return value... but we
+	 * still provide all of the decoded data.
+	 */
+	if (length > CBS_len(&cbs) || length > LONG_MAX) {
+		ASN1error(ASN1_R_TOO_LONG);
+		ret = 0x80;
+	}
+
+	*pclass = tag_class << 6;
+	*ptag = tag_number;
+	*plength = length;
+
+	*pp = CBS_data(&cbs);
+
+	if (constructed)
+		ret |= 1 << 5;
+	if (indefinite)
+		ret |= 1;
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_get_object);
+
+/* class 0 is constructed
+ * constructed == 2 for indefinite length constructed */
+void
+ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
+    int xclass)
+{
+	unsigned char *p = *pp;
+	int i, ttag;
+
+	i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
+	i |= (xclass & V_ASN1_PRIVATE);
+	if (tag < 31)
+		*(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
+	else {
+		*(p++) = i | V_ASN1_PRIMITIVE_TAG;
+		for(i = 0, ttag = tag; ttag > 0; i++)
+			ttag >>= 7;
+		ttag = i;
+		while (i-- > 0) {
+			p[i] = tag & 0x7f;
+			if (i != (ttag - 1))
+				p[i] |= 0x80;
+			tag >>= 7;
+		}
+		p += ttag;
+	}
+	if (constructed == 2)
+		*(p++) = 0x80;
+	else
+		asn1_put_length(&p, length);
+	*pp = p;
+}
+LCRYPTO_ALIAS(ASN1_put_object);
+
+int
+ASN1_put_eoc(unsigned char **pp)
+{
+	unsigned char *p = *pp;
+
+	*p++ = 0;
+	*p++ = 0;
+	*pp = p;
+	return 2;
+}
+LCRYPTO_ALIAS(ASN1_put_eoc);
+
+static void
+asn1_put_length(unsigned char **pp, int length)
+{
+	unsigned char *p = *pp;
+
+	int i, l;
+	if (length <= 127)
+		*(p++) = (unsigned char)length;
+	else {
+		l = length;
+		for (i = 0; l > 0; i++)
+			l >>= 8;
+		*(p++) = i | 0x80;
+		l = i;
+		while (i-- > 0) {
+			p[i] = length & 0xff;
+			length >>= 8;
+		}
+		p += l;
+	}
+	*pp = p;
+}
+
+int
+ASN1_object_size(int constructed, int length, int tag)
+{
+	int ret;
+
+	ret = length;
+	ret++;
+	if (tag >= 31) {
+		while (tag > 0) {
+			tag >>= 7;
+			ret++;
+		}
+	}
+	if (constructed == 2)
+		return ret + 3;
+	ret++;
+	if (length > 127) {
+		while (length > 0) {
+			length >>= 8;
+			ret++;
+		}
+	}
+	return (ret);
+}
+LCRYPTO_ALIAS(ASN1_object_size);
diff --git a/crypto/asn1/asn1_par.c b/crypto/asn1/asn1_par.c
new file mode 100644
index 0000000..712bb52
--- /dev/null
+++ b/crypto/asn1/asn1_par.c
@@ -0,0 +1,386 @@
+/* $OpenBSD: asn1_par.c,v 1.35 2023/07/05 21:23:36 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+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)
+{
+	char str[128];
+	const char *p;
+
+	if (constructed & V_ASN1_CONSTRUCTED)
+		p="cons: ";
+	else
+		p="prim: ";
+	if (BIO_write(bp, p, 6) < 6)
+		goto err;
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+
+	p = str;
+	if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
+		snprintf(str, sizeof str, "priv [ %d ] ", tag);
+	else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
+		snprintf(str, sizeof str, "cont [ %d ]", tag);
+	else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
+		snprintf(str, sizeof str, "appl [ %d ]", tag);
+	else if (tag > 30)
+		snprintf(str, sizeof str, "", tag);
+	else
+		p = ASN1_tag2str(tag);
+
+	if (BIO_printf(bp, "%-18s", p) <= 0)
+		goto err;
+	return (1);
+ err:
+	return (0);
+}
+
+int
+ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
+{
+	return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0));
+}
+LCRYPTO_ALIAS(ASN1_parse);
+
+int
+ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
+{
+	return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump));
+}
+LCRYPTO_ALIAS(ASN1_parse_dump);
+
+static int
+asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
+    int depth, int indent, int dump)
+{
+	const unsigned char *p, *ep, *tot, *op, *opp;
+	long len;
+	int tag, xclass, ret = 0;
+	int nl, hl, j, r;
+	ASN1_OBJECT *o = NULL;
+	ASN1_OCTET_STRING *os = NULL;
+	ASN1_INTEGER *ai = NULL;
+	ASN1_ENUMERATED *ae = NULL;
+	/* ASN1_BMPSTRING *bmp=NULL;*/
+	int dump_indent;
+
+	dump_indent = 6;	/* Because we know BIO_dump_indent() */
+	p = *pp;
+	tot = p + length;
+	op = p - 1;
+	if (depth > 128) {
+		BIO_printf(bp, "Max depth exceeded\n");
+		goto end;
+	}
+	while ((p < tot) && (op < p)) {
+		op = p;
+		j = ASN1_get_object(&p, &len, &tag, &xclass, length);
+
+		if (j & 0x80) {
+			if (BIO_write(bp, "Error in encoding\n", 18) <= 0)
+				goto end;
+			ret = 0;
+			goto end;
+		}
+		hl = (p - op);
+		length -= hl;
+		/* if j == 0x21 it is a constructed indefinite length object */
+		if (BIO_printf(bp, "%5ld:", (long)offset +
+		    (long)(op - *pp)) <= 0)
+		    goto end;
+
+		if (j != (V_ASN1_CONSTRUCTED | 1)) {
+			if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ",
+			    depth, (long)hl, len) <= 0)
+				goto end;
+		} else {
+			if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ",
+			    depth, (long)hl) <= 0)
+				goto end;
+		}
+		if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0))
+			goto end;
+		if (j & V_ASN1_CONSTRUCTED) {
+			ep = p + len;
+			if (BIO_write(bp, "\n", 1) <= 0)
+				goto end;
+			if (len > length) {
+				BIO_printf(bp, "length is greater than %ld\n",
+				    length);
+				ret = 0;
+				goto end;
+			}
+			if ((j == 0x21) && (len == 0)) {
+				for (;;) {
+					r = asn1_parse2(bp, &p, (long)(tot - p),
+					    offset + (p - *pp), depth + 1,
+					    indent, dump);
+					if (r == 0) {
+						ret = 0;
+						goto end;
+					}
+					if ((r == 2) || (p >= tot)) {
+						len = (long)(p - ep);
+						break;
+					}
+				}
+			} else {
+				while (p < ep) {
+					r = asn1_parse2(bp, &p, (long)(ep - p),
+					    offset + (p - *pp), depth + 1,
+					    indent, dump);
+					if (r == 0) {
+						ret = 0;
+						goto end;
+					}
+				}
+			}
+		} else if (xclass != 0) {
+			p += len;
+			if (BIO_write(bp, "\n", 1) <= 0)
+				goto end;
+		} else {
+			nl = 0;
+			if ((tag == V_ASN1_PRINTABLESTRING) ||
+			    (tag == V_ASN1_T61STRING) ||
+			    (tag == V_ASN1_IA5STRING) ||
+			    (tag == V_ASN1_VISIBLESTRING) ||
+			    (tag == V_ASN1_NUMERICSTRING) ||
+			    (tag == V_ASN1_UTF8STRING) ||
+			    (tag == V_ASN1_UTCTIME) ||
+			    (tag == V_ASN1_GENERALIZEDTIME)) {
+				if (BIO_write(bp, ":", 1) <= 0)
+					goto end;
+				if ((len > 0) &&
+				    BIO_write(bp, (const char *)p, (int)len) !=
+				    (int)len)
+					goto end;
+			} else if (tag == V_ASN1_OBJECT) {
+				opp = op;
+				if (d2i_ASN1_OBJECT(&o, &opp, len + hl) !=
+				    NULL) {
+					if (BIO_write(bp, ":", 1) <= 0)
+						goto end;
+					i2a_ASN1_OBJECT(bp, o);
+				} else {
+					if (BIO_write(bp, ":BAD OBJECT",
+					    11) <= 0)
+						goto end;
+				}
+			} else if (tag == V_ASN1_BOOLEAN) {
+				if (len == 1 && p < tot) {
+					BIO_printf(bp, ":%u", p[0]);
+				} else {
+					if (BIO_write(bp, "Bad boolean\n",
+					    12) <= 0)
+						goto end;
+				}
+			} else if (tag == V_ASN1_BMPSTRING) {
+				/* do the BMP thang */
+			} else if (tag == V_ASN1_OCTET_STRING) {
+				int i, printable = 1;
+
+				opp = op;
+				os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
+				if (os != NULL && os->length > 0) {
+					opp = os->data;
+					/* testing whether the octet string is
+					 * printable */
+					for (i = 0; i < os->length; i++) {
+						if (((opp[i] < ' ') &&
+						    (opp[i] != '\n') &&
+						    (opp[i] != '\r') &&
+						    (opp[i] != '\t')) ||
+						    (opp[i] > '~')) {
+							printable = 0;
+							break;
+						}
+					}
+					if (printable) {
+						/* printable string */
+						if (BIO_write(bp, ":", 1) <= 0)
+							goto end;
+						if (BIO_write(bp, (const char *)opp,
+							    os->length) <= 0)
+							goto end;
+					} else if (!dump) {
+						/* not printable => print octet string
+						 * as hex dump */
+						if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
+							goto end;
+						for (i = 0; i < os->length; i++) {
+							if (BIO_printf(bp,
+							    "%02X", opp[i]) <= 0)
+								goto end;
+						}
+					} else {
+						/* print the normal dump */
+						if (!nl) {
+							if (BIO_write(bp, "\n", 1) <= 0)
+								goto end;
+						}
+						if (BIO_dump_indent(bp,
+						    (const char *)opp,
+						    ((dump == -1 || dump >
+						    os->length) ? os->length : dump),
+						    dump_indent) <= 0)
+							goto end;
+						nl = 1;
+					}
+				}
+				ASN1_OCTET_STRING_free(os);
+				os = NULL;
+			} else if (tag == V_ASN1_INTEGER) {
+				int i;
+
+				opp = op;
+				ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
+				if (ai != NULL) {
+					if (BIO_write(bp, ":", 1) <= 0)
+						goto end;
+					if (ai->type == V_ASN1_NEG_INTEGER)
+						if (BIO_write(bp, "-", 1) <= 0)
+							goto end;
+					for (i = 0; i < ai->length; i++) {
+						if (BIO_printf(bp, "%02X",
+						    ai->data[i]) <= 0)
+							goto end;
+					}
+					if (ai->length == 0) {
+						if (BIO_write(bp, "00", 2) <= 0)
+							goto end;
+					}
+				} else {
+					if (BIO_write(bp, "BAD INTEGER", 11) <= 0)
+						goto end;
+				}
+				ASN1_INTEGER_free(ai);
+				ai = NULL;
+			} else if (tag == V_ASN1_ENUMERATED) {
+				int i;
+
+				opp = op;
+				ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
+				if (ae != NULL) {
+					if (BIO_write(bp, ":", 1) <= 0)
+						goto end;
+					if (ae->type == V_ASN1_NEG_ENUMERATED)
+						if (BIO_write(bp, "-", 1) <= 0)
+							goto end;
+					for (i = 0; i < ae->length; i++) {
+						if (BIO_printf(bp, "%02X",
+						    ae->data[i]) <= 0)
+							goto end;
+					}
+					if (ae->length == 0) {
+						if (BIO_write(bp, "00", 2) <= 0)
+							goto end;
+					}
+				} else {
+					if (BIO_write(bp, "BAD ENUMERATED", 14) <= 0)
+						goto end;
+				}
+				ASN1_ENUMERATED_free(ae);
+				ae = NULL;
+			} else if (len > 0 && dump) {
+				if (!nl) {
+					if (BIO_write(bp, "\n", 1) <= 0)
+						goto end;
+				}
+				if (BIO_dump_indent(bp, (const char *)p,
+				    ((dump == -1 || dump > len) ? len : dump),
+				    dump_indent) <= 0)
+					goto end;
+				nl = 1;
+			}
+
+			if (!nl) {
+				if (BIO_write(bp, "\n", 1) <= 0)
+					goto end;
+			}
+			p += len;
+			if ((tag == V_ASN1_EOC) && (xclass == 0)) {
+				ret = 2; /* End of sequence */
+				goto end;
+			}
+		}
+		length -= len;
+	}
+	ret = 1;
+
+ end:
+	if (o != NULL)
+		ASN1_OBJECT_free(o);
+	ASN1_OCTET_STRING_free(os);
+	ASN1_INTEGER_free(ai);
+	ASN1_ENUMERATED_free(ae);
+	*pp = p;
+	return (ret);
+}
diff --git a/crypto/asn1/asn1_types.c b/crypto/asn1/asn1_types.c
new file mode 100644
index 0000000..5f9644a
--- /dev/null
+++ b/crypto/asn1/asn1_types.c
@@ -0,0 +1,305 @@
+/* $OpenBSD: asn1_types.c,v 1.3 2023/07/05 21:23:36 beck Exp $ */
+/*
+ * Copyright (c) 2021 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#define ASN1_ENCODING_CONSTRUCTED_ONLY	1
+#define ASN1_ENCODING_PRIMITIVE_ONLY	2
+
+struct asn1_type {
+	const char *name;
+	uint32_t bit_value;
+	int char_width;
+	int encoding;
+};
+
+/*
+ * Universal class tag types - ITU X.680.
+ */
+static const struct asn1_type asn1_types[31] = {
+	[0] = {
+		/* Tag 0 (0x00) - Reserved for use by encoding rules */
+		.name = "EOC",
+		.bit_value = 0,
+		.char_width = -1,
+	},
+	[1] = {
+		/* Tag 1 (0x01) - Boolean */
+		.name = "BOOLEAN",
+		.bit_value = 0,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[2] = {
+		/* Tag 2 (0x02) - Integer */
+		.name = "INTEGER",
+		.bit_value = 0,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[3] = {
+		/* Tag 3 (0x03) - BitString */
+		.name = "BIT STRING",
+		.bit_value = B_ASN1_BIT_STRING,
+		.char_width = -1,
+	},
+	[4] = {
+		/* Tag 4 (0x04) - OctetString */
+		.name = "OCTET STRING",
+		.bit_value = B_ASN1_OCTET_STRING,
+		.char_width = -1,
+	},
+	[5] = {
+		/* Tag 5 (0x05) - Null */
+		.name = "NULL",
+		.bit_value = 0,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[6] = {
+		/* Tag 6 (0x06) - Object Identifier */
+		.name = "OBJECT",
+		.bit_value = 0,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[7] = {
+		/* Tag 7 (0x07) - Object Descriptor */
+		.name = "OBJECT DESCRIPTOR",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+	},
+	[8] = {
+		/* Tag 8 (0x08) - External */
+		.name = "EXTERNAL",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+	},
+	[9] = {
+		/* Tag 9 (0x09) - Real */
+		.name = "REAL",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[10] = {
+		/* Tag 10 (0x0a) - Enumerated */
+		.name = "ENUMERATED",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[11] = {
+		/* Tag 11 (0x0b) - Embedded PDV */
+		.name = "",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+	},
+	[12] = {
+		/* Tag 12 (0x0c) - UTF8String */
+		.name = "UTF8STRING",
+		.bit_value = B_ASN1_UTF8STRING,
+		.char_width = 0,
+	},
+	[13] = {
+		/* Tag 13 (0x0d) - Relative Object Identifier */
+		.name = "",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[14] = {
+		/* Tag 14 (0x0e) - Time */
+		.name = "",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
+	},
+	[15] = {
+		/* Tag 15 (0x0f) - Reserved */
+		.name = "",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+	},
+	[16] = {
+		/* Tag 16 (0x10)- Sequence */
+		.name = "SEQUENCE",
+		.bit_value = B_ASN1_SEQUENCE,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
+	},
+	[17] = {
+		/* Tag 17 (0x11) - Set */
+		.name = "SET",
+		.bit_value = 0,
+		.char_width = -1,
+		.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
+	},
+	[18] = {
+		/* Tag 18 (0x12) - NumericString */
+		.name = "NUMERICSTRING",
+		.bit_value = B_ASN1_NUMERICSTRING,
+		.char_width = -1,
+	},
+	[19] = {
+		/* Tag 19 (0x13) - PrintableString */
+		.name = "PRINTABLESTRING",
+		.bit_value = B_ASN1_PRINTABLESTRING,
+		.char_width = 1,
+	},
+	[20] = {
+		/* Tag 20 (0x14) - TeletexString (T61String) */
+		.name = "T61STRING",
+		.bit_value = B_ASN1_T61STRING,
+		.char_width = 1,
+	},
+	[21] = {
+		/* Tag 21 (0x15) - VideotexString */
+		.name = "VIDEOTEXSTRING",
+		.bit_value = B_ASN1_VIDEOTEXSTRING,
+		.char_width = -1,
+	},
+	[22] = {
+		/* Tag 22 (0x16) - IA5String */
+		.name = "IA5STRING",
+		.bit_value = B_ASN1_IA5STRING,
+		.char_width = 1,
+	},
+	[23] = {
+		/* Tag 23 (0x17) - UTCTime */
+		.name = "UTCTIME",
+		.bit_value = B_ASN1_UTCTIME,
+		.char_width = 1,
+	},
+	[24] = {
+		/* Tag 24 (0x18) - GeneralizedTime */
+		.name = "GENERALIZEDTIME",
+		.bit_value = B_ASN1_GENERALIZEDTIME,
+		.char_width = 1,
+	},
+	[25] = {
+		/* Tag 25 (0x19) - GraphicString */
+		.name = "GRAPHICSTRING",
+		.bit_value = B_ASN1_GRAPHICSTRING,
+		.char_width = -1,
+	},
+	[26] = {
+		/* Tag 26 (0x1a) - VisibleString (ISO646String) */
+		.name = "VISIBLESTRING",
+		.bit_value = B_ASN1_ISO64STRING,
+		.char_width = 1,
+	},
+	[27] = {
+		/* Tag 27 (0x1b) - GeneralString */
+		.name = "GENERALSTRING",
+		.bit_value = B_ASN1_GENERALSTRING,
+		.char_width = -1,
+	},
+	[28] = {
+		/* Tag 28 (0x1c) - UniversalString */
+		.name = "UNIVERSALSTRING",
+		.bit_value = B_ASN1_UNIVERSALSTRING,
+		.char_width = 4,
+	},
+	[29] = {
+		/* Tag 29 (0x1d) - Unallocated */
+		.name = "",
+		.bit_value = B_ASN1_UNKNOWN,
+		.char_width = -1,
+	},
+	[30] = {
+		/* Tag 30 (0x1e) - BMPString */
+		.name = "BMPSTRING",
+		.bit_value = B_ASN1_BMPSTRING,
+		.char_width = 2,
+	},
+};
+
+static const struct asn1_type *
+asn1_type_by_tag(int tag)
+{
+	if (tag < 0 || tag > 30)
+		return NULL;
+
+	return &asn1_types[tag];
+}
+
+int
+asn1_must_be_constructed(int tag)
+{
+	const struct asn1_type *at;
+
+	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
+		tag &= ~V_ASN1_NEG;
+	if ((at = asn1_type_by_tag(tag)) != NULL)
+		return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY;
+
+	return 0;
+}
+
+int
+asn1_must_be_primitive(int tag)
+{
+	const struct asn1_type *at;
+
+	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
+		tag &= ~V_ASN1_NEG;
+	if ((at = asn1_type_by_tag(tag)) != NULL)
+		return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY;
+
+	return 0;
+}
+
+int
+asn1_tag2charwidth(int tag)
+{
+	const struct asn1_type *at;
+
+	if ((at = asn1_type_by_tag(tag)) != NULL)
+		return at->char_width;
+
+	return -1;
+}
+
+unsigned long
+ASN1_tag2bit(int tag)
+{
+	const struct asn1_type *at;
+
+	if ((at = asn1_type_by_tag(tag)) != NULL)
+		return (unsigned long)at->bit_value;
+
+	return 0;
+}
+LCRYPTO_ALIAS(ASN1_tag2bit);
+
+const char *
+ASN1_tag2str(int tag)
+{
+	const struct asn1_type *at;
+
+	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
+		tag &= ~V_ASN1_NEG;
+
+	if ((at = asn1_type_by_tag(tag)) != NULL)
+		return at->name;
+
+	return "(unknown)";
+}
+LCRYPTO_ALIAS(ASN1_tag2str);
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
new file mode 100644
index 0000000..56a428a
--- /dev/null
+++ b/crypto/asn1/asn_mime.c
@@ -0,0 +1,1013 @@
+/* $OpenBSD: asn_mime.c,v 1.32 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+/* Generalised MIME like utilities for streaming ASN1. Although many
+ * have a PKCS7/CMS like flavour others are more general purpose.
+ */
+
+/* MIME format structures
+ * Note that all are translated to lower case apart from
+ * parameter values. Quotes are stripped off
+ */
+
+typedef struct {
+	char *param_name;		/* Param name e.g. "micalg" */
+	char *param_value;		/* Param value e.g. "sha1" */
+} MIME_PARAM;
+
+DECLARE_STACK_OF(MIME_PARAM)
+
+typedef struct {
+	char *name;			/* Name of line e.g. "content-type" */
+	char *value;			/* Value of line e.g. "text/plain" */
+	STACK_OF(MIME_PARAM) *params;	/* Zero or more parameters */
+} MIME_HEADER;
+
+DECLARE_STACK_OF(MIME_HEADER)
+
+static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+    const ASN1_ITEM *it);
+static char * strip_ends(char *name);
+static char * strip_start(char *name);
+static char * strip_end(char *name);
+static MIME_HEADER *mime_hdr_new(char *name, char *value);
+static int mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value);
+static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio);
+static int mime_hdr_cmp(const MIME_HEADER * const *a,
+    const MIME_HEADER * const *b);
+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, char *bound, int blen);
+static int multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret);
+static int strip_eol(char *linebuf, int *plen);
+static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name);
+static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, char *name);
+static void mime_hdr_free(MIME_HEADER *hdr);
+
+#define MAX_SMLEN 1024
+#define mime_debug(x) /* x */
+
+/* Output an ASN1 structure in BER format streaming if necessary */
+
+int
+i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+    const ASN1_ITEM *it)
+{
+	/* 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) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		SMIME_crlf_copy(in, bio, flags);
+		(void)BIO_flush(bio);
+		/* Free up successive BIOs until we hit the old output BIO */
+		do {
+			tbio = BIO_pop(bio);
+			BIO_free(bio);
+			bio = tbio;
+		} while (bio != out);
+	}
+	/* else just write out ASN1 structure which will have all content
+	 * stored internally
+	 */
+	else
+		ASN1_item_i2d_bio(it, out, val);
+	return 1;
+}
+
+/* Base 64 read and write of ASN1 structure */
+
+static int
+B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+    const ASN1_ITEM *it)
+{
+	BIO *b64;
+	int r;
+
+	b64 = BIO_new(BIO_f_base64());
+	if (!b64) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	/* prepend the b64 BIO so all data is base64 encoded.
+	 */
+	out = BIO_push(b64, out);
+	r = i2d_ASN1_bio_stream(out, val, in, flags, it);
+	(void)BIO_flush(out);
+	BIO_pop(out);
+	BIO_free(b64);
+	return r;
+}
+
+/* Streaming ASN1 PEM write */
+
+int
+PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags,
+    const char *hdr, const ASN1_ITEM *it)
+{
+	int r;
+
+	BIO_printf(out, "-----BEGIN %s-----\n", hdr);
+	r = B64_write_ASN1(out, val, in, flags, it);
+	BIO_printf(out, "-----END %s-----\n", hdr);
+	return r;
+}
+
+static ASN1_VALUE *
+b64_read_asn1(BIO *bio, const ASN1_ITEM *it)
+{
+	BIO *b64;
+	ASN1_VALUE *val;
+	if (!(b64 = BIO_new(BIO_f_base64()))) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	bio = BIO_push(b64, bio);
+	val = ASN1_item_d2i_bio(it, bio, NULL);
+	if (!val)
+		ASN1error(ASN1_R_DECODE_ERROR);
+	(void)BIO_flush(bio);
+	bio = BIO_pop(bio);
+	BIO_free(b64);
+	return val;
+}
+
+/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */
+
+static int
+asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs)
+{
+	const EVP_MD *md;
+	int i, have_unknown = 0, write_comma, ret = 0, md_nid;
+
+	have_unknown = 0;
+	write_comma = 0;
+	for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) {
+		if (write_comma)
+			BIO_write(out, ",", 1);
+		write_comma = 1;
+		md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm);
+		md = EVP_get_digestbynid(md_nid);
+		if (md && md->md_ctrl) {
+			int rv;
+			char *micstr;
+			rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr);
+			if (rv > 0) {
+				BIO_puts(out, micstr);
+				free(micstr);
+				continue;
+			}
+			if (rv != -2)
+				goto err;
+		}
+		switch (md_nid) {
+		case NID_sha1:
+			BIO_puts(out, "sha1");
+			break;
+
+		case NID_md5:
+			BIO_puts(out, "md5");
+			break;
+
+		case NID_sha256:
+			BIO_puts(out, "sha-256");
+			break;
+
+		case NID_sha384:
+			BIO_puts(out, "sha-384");
+			break;
+
+		case NID_sha512:
+			BIO_puts(out, "sha-512");
+			break;
+
+		case NID_id_GostR3411_94:
+			BIO_puts(out, "gostr3411-94");
+			goto err;
+			break;
+
+		default:
+			if (have_unknown)
+				write_comma = 0;
+			else {
+				BIO_puts(out, "unknown");
+				have_unknown = 1;
+			}
+			break;
+
+		}
+	}
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+/* 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)
+{
+	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
+		mime_prefix = "application/pkcs7-";
+
+	if (flags & SMIME_CRLFEOL)
+		mime_eol = "\r\n";
+	else
+		mime_eol = "\n";
+	if ((flags & SMIME_DETACHED) && data) {
+		/* We want multipart/signed */
+		/* Generate a random boundary */
+		arc4random_buf(bound, 32);
+		for (i = 0; i < 32; i++) {
+			c = bound[i] & 0xf;
+			if (c < 10)
+				c += '0';
+			else
+				c += 'A' - 10;
+			bound[i] = c;
+		}
+		bound[32] = 0;
+		BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
+		BIO_printf(bio, "Content-Type: multipart/signed;");
+		BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix);
+		BIO_puts(bio, " micalg=\"");
+		asn1_write_micalg(bio, mdalgs);
+		BIO_printf(bio, "\"; boundary=\"----%s\"%s%s",
+		    bound, mime_eol, mime_eol);
+		BIO_printf(bio, "This is an S/MIME signed message%s%s",
+		    mime_eol, mime_eol);
+		/* Now write out the first part */
+		BIO_printf(bio, "------%s%s", bound, mime_eol);
+		if (!asn1_output_data(bio, data, val, flags, it))
+			return 0;
+		BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol);
+
+		/* Headers for signature */
+
+		BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix);
+		BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol);
+		BIO_printf(bio, "Content-Transfer-Encoding: base64%s",
+		    mime_eol);
+		BIO_printf(bio, "Content-Disposition: attachment;");
+		BIO_printf(bio, " filename=\"smime.p7s\"%s%s",
+		    mime_eol, mime_eol);
+		B64_write_ASN1(bio, val, NULL, 0, it);
+		BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound,
+		    mime_eol, mime_eol);
+		return 1;
+	}
+
+	/* Determine smime-type header */
+
+	if (ctype_nid == NID_pkcs7_enveloped)
+		msg_type = "enveloped-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)
+			msg_type = "signed-data";
+		else
+			msg_type = "certs-only";
+	} else if (ctype_nid == NID_id_smime_ct_compressedData) {
+		msg_type = "compressed-data";
+		cname = "smime.p7z";
+	}
+	/* MIME headers */
+	BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol);
+	BIO_printf(bio, "Content-Disposition: attachment;");
+	BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol);
+	BIO_printf(bio, "Content-Type: %smime;", mime_prefix);
+	if (msg_type)
+		BIO_printf(bio, " smime-type=%s;", msg_type);
+	BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol);
+	BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s",
+	    mime_eol, mime_eol);
+	if (!B64_write_ASN1(bio, val, data, flags, it))
+		return 0;
+	BIO_printf(bio, "%s", mime_eol);
+	return 1;
+}
+
+/* Handle output of ASN1 data */
+
+
+static int
+asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags,
+    const ASN1_ITEM *it)
+{
+	BIO *tmpbio;
+	const ASN1_AUX *aux = it->funcs;
+	ASN1_STREAM_ARG sarg;
+	int rv = 1;
+
+	/* If data is not deteched or resigning then the output BIO is
+	 * already 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;
+	}
+
+	if (!aux || !aux->asn1_cb) {
+		ASN1error(ASN1_R_STREAMING_NOT_SUPPORTED);
+		return 0;
+	}
+
+	sarg.out = out;
+	sarg.ndef_bio = NULL;
+	sarg.boundary = NULL;
+
+	/* Let ASN1 code prepend any needed BIOs */
+
+	if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0)
+		return 0;
+
+	/* Copy data across, passing through filter BIOs for processing */
+	SMIME_crlf_copy(data, sarg.ndef_bio, flags);
+
+	/* Finalize structure */
+	if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0)
+		rv = 0;
+
+	/* Now remove any digests prepended to the BIO */
+
+	while (sarg.ndef_bio != out) {
+		tmpbio = BIO_pop(sarg.ndef_bio);
+		BIO_free(sarg.ndef_bio);
+		sarg.ndef_bio = tmpbio;
+	}
+
+	return rv;
+}
+
+/* SMIME reader: handle multipart/signed and opaque signing.
+ * in multipart case the content is placed in a memory BIO
+ * pointed to by "bcont". In opaque this is set to NULL
+ */
+
+ASN1_VALUE *
+SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it)
+{
+	BIO *asnin;
+	STACK_OF(MIME_HEADER) *headers = NULL;
+	STACK_OF(BIO) *parts = NULL;
+	MIME_HEADER *hdr;
+	MIME_PARAM *prm;
+	ASN1_VALUE *val;
+	int ret;
+
+	if (bcont)
+		*bcont = NULL;
+
+	if (!(headers = mime_parse_hdr(bio))) {
+		ASN1error(ASN1_R_MIME_PARSE_ERROR);
+		return NULL;
+	}
+
+	if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
+		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+		ASN1error(ASN1_R_NO_CONTENT_TYPE);
+		return NULL;
+	}
+
+	/* Handle multipart/signed */
+
+	if (!strcmp(hdr->value, "multipart/signed")) {
+		/* Split into two parts */
+		prm = mime_param_find(hdr, "boundary");
+		if (!prm || !prm->param_value) {
+			sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+			ASN1error(ASN1_R_NO_MULTIPART_BOUNDARY);
+			return NULL;
+		}
+		ret = multi_split(bio, prm->param_value, &parts);
+		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+		if (!ret || (sk_BIO_num(parts) != 2) ) {
+			ASN1error(ASN1_R_NO_MULTIPART_BODY_FAILURE);
+			sk_BIO_pop_free(parts, BIO_vfree);
+			return NULL;
+		}
+
+		/* Parse the signature piece */
+		asnin = sk_BIO_value(parts, 1);
+
+		if (!(headers = mime_parse_hdr(asnin))) {
+			ASN1error(ASN1_R_MIME_SIG_PARSE_ERROR);
+			sk_BIO_pop_free(parts, BIO_vfree);
+			return NULL;
+		}
+
+		/* Get content type */
+
+		if (!(hdr = mime_hdr_find(headers, "content-type")) ||
+		    !hdr->value) {
+			sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+			sk_BIO_pop_free(parts, BIO_vfree);
+			ASN1error(ASN1_R_NO_SIG_CONTENT_TYPE);
+			return NULL;
+		}
+
+		if (strcmp(hdr->value, "application/x-pkcs7-signature") &&
+		    strcmp(hdr->value, "application/pkcs7-signature")) {
+			ASN1error(ASN1_R_SIG_INVALID_MIME_TYPE);
+			ERR_asprintf_error_data("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))) {
+			ASN1error(ASN1_R_ASN1_SIG_PARSE_ERROR);
+			sk_BIO_pop_free(parts, BIO_vfree);
+			return NULL;
+		}
+
+		if (bcont) {
+			*bcont = sk_BIO_value(parts, 0);
+			BIO_free(asnin);
+			sk_BIO_free(parts);
+		} else sk_BIO_pop_free(parts, BIO_vfree);
+			return val;
+	}
+
+	/* OK, if not multipart/signed try opaque signature */
+
+	if (strcmp (hdr->value, "application/x-pkcs7-mime") &&
+	    strcmp (hdr->value, "application/pkcs7-mime")) {
+		ASN1error(ASN1_R_INVALID_MIME_TYPE);
+		ERR_asprintf_error_data("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))) {
+		ASN1error(ASN1_R_ASN1_PARSE_ERROR);
+		return NULL;
+	}
+	return val;
+}
+
+/* Copy text from one BIO to another making the output CRLF at EOL */
+int
+SMIME_crlf_copy(BIO *in, BIO *out, int flags)
+{
+	BIO *bf;
+	char eol;
+	int len;
+	char linebuf[MAX_SMLEN];
+
+	/* 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)
+		return 0;
+	out = BIO_push(bf, out);
+	if (flags & SMIME_BINARY) {
+		while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0)
+			BIO_write(out, linebuf, len);
+	} else {
+		if (flags & SMIME_TEXT)
+			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);
+			if (len)
+				BIO_write(out, linebuf, len);
+			if (eol)
+				BIO_write(out, "\r\n", 2);
+		}
+	}
+	(void)BIO_flush(out);
+	BIO_pop(out);
+	BIO_free(bf);
+	return 1;
+}
+LCRYPTO_ALIAS(SMIME_crlf_copy);
+
+/* Strip off headers if they are text/plain */
+int
+SMIME_text(BIO *in, BIO *out)
+{
+	char iobuf[4096];
+	int len;
+	STACK_OF(MIME_HEADER) *headers;
+	MIME_HEADER *hdr;
+
+	if (!(headers = mime_parse_hdr(in))) {
+		ASN1error(ASN1_R_MIME_PARSE_ERROR);
+		return 0;
+	}
+	if (!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) {
+		ASN1error(ASN1_R_MIME_NO_CONTENT_TYPE);
+		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+		return 0;
+	}
+	if (strcmp (hdr->value, "text/plain")) {
+		ASN1error(ASN1_R_INVALID_MIME_TYPE);
+		ERR_asprintf_error_data("type: %s", hdr->value);
+		sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+		return 0;
+	}
+	sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+	while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0)
+		BIO_write(out, iobuf, len);
+	if (len < 0)
+		return 0;
+	return 1;
+}
+LCRYPTO_ALIAS(SMIME_text);
+
+/*
+ * Split a multipart/XXX message body into component parts: result is
+ * canonical parts in a STACK of bios
+ */
+static int
+multi_split(BIO *bio, char *bound, STACK_OF(BIO) **ret)
+{
+	char linebuf[MAX_SMLEN];
+	int len, blen;
+	int eol = 0, next_eol = 0;
+	BIO *bpart = NULL;
+	STACK_OF(BIO) *parts;
+	char state, part, first;
+
+	blen = strlen(bound);
+	part = 0;
+	state = 0;
+	first = 1;
+	parts = sk_BIO_new_null();
+	*ret = parts;
+	if (parts == NULL)
+		return 0;
+	while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+		state = mime_bound_check(linebuf, len, bound, blen);
+		if (state == 1) {
+			first = 1;
+			part++;
+		} else if (state == 2) {
+			if (sk_BIO_push(parts, bpart) == 0)
+				return 0;
+			return 1;
+		} else if (part) {
+			/* Strip CR+LF from linebuf */
+			next_eol = strip_eol(linebuf, &len);
+			if (first) {
+				first = 0;
+				if (bpart != NULL) {
+					if (sk_BIO_push(parts, bpart) == 0)
+						return 0;
+				}
+				bpart = BIO_new(BIO_s_mem());
+				if (bpart == NULL)
+					return 0;
+				BIO_set_mem_eof_return(bpart, 0);
+			} else if (eol)
+				BIO_write(bpart, "\r\n", 2);
+			eol = next_eol;
+			if (len)
+				BIO_write(bpart, linebuf, len);
+		}
+	}
+	BIO_free(bpart);
+	return 0;
+}
+
+/* This is the big one: parse MIME header lines up to message body */
+
+#define MIME_INVALID	0
+#define MIME_START	1
+#define MIME_TYPE	2
+#define MIME_NAME	3
+#define MIME_VALUE	4
+#define MIME_QUOTE	5
+#define MIME_COMMENT	6
+
+static STACK_OF(MIME_HEADER) *
+mime_parse_hdr(BIO *bio)
+{
+	char *p, *q, c;
+	char *ntmp;
+	char linebuf[MAX_SMLEN];
+	MIME_HEADER *mhdr = NULL;
+	STACK_OF(MIME_HEADER) *headers;
+	int len, state, save_state = 0;
+
+	headers = sk_MIME_HEADER_new(mime_hdr_cmp);
+	if (!headers)
+		return NULL;
+	while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) {
+		/* If whitespace at line start then continuation line */
+		if (mhdr && isspace((unsigned char)linebuf[0]))
+			state = MIME_NAME;
+		else
+			state = MIME_START;
+		ntmp = NULL;
+
+		/* Go through all characters */
+		for (p = linebuf, q = linebuf;
+		    (c = *p) && (c != '\r') && (c != '\n'); p++) {
+
+			/* State machine to handle MIME headers
+			 * if this looks horrible that's because it *is*
+			 */
+
+			switch (state) {
+			case MIME_START:
+				if (c == ':') {
+					state = MIME_TYPE;
+					*p = 0;
+					ntmp = strip_ends(q);
+					q = p + 1;
+				}
+				break;
+
+			case MIME_TYPE:
+				if (c == ';') {
+					mime_debug("Found End Value\n");
+					*p = 0;
+					mhdr = mime_hdr_new(ntmp,
+					    strip_ends(q));
+					if (mhdr == NULL)
+						goto merr;
+					if (sk_MIME_HEADER_push(headers,
+					    mhdr) == 0)
+						goto merr;
+					ntmp = NULL;
+					q = p + 1;
+					state = MIME_NAME;
+				} else if (c == '(') {
+					save_state = state;
+					state = MIME_COMMENT;
+				}
+				break;
+
+			case MIME_COMMENT:
+				if (c == ')') {
+					state = save_state;
+				}
+				break;
+
+			case MIME_NAME:
+				if (c == '=') {
+					state = MIME_VALUE;
+					*p = 0;
+					ntmp = strip_ends(q);
+					q = p + 1;
+				}
+				break;
+
+			case MIME_VALUE:
+				if (c == ';') {
+					state = MIME_NAME;
+					*p = 0;
+					mime_hdr_addparam(mhdr, ntmp,
+					    strip_ends(q));
+					ntmp = NULL;
+					q = p + 1;
+				} else if (c == '"') {
+					mime_debug("Found Quote\n");
+					state = MIME_QUOTE;
+				} else if (c == '(') {
+					save_state = state;
+					state = MIME_COMMENT;
+				}
+				break;
+
+			case MIME_QUOTE:
+				if (c == '"') {
+					mime_debug("Found Match Quote\n");
+					state = MIME_VALUE;
+				}
+				break;
+			}
+		}
+
+		if (state == MIME_TYPE) {
+			mhdr = mime_hdr_new(ntmp, strip_ends(q));
+			if (mhdr == NULL)
+				goto merr;
+			if (sk_MIME_HEADER_push(headers, mhdr) == 0)
+				goto merr;
+		} 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;
+
+ merr:
+	if (mhdr != NULL)
+		mime_hdr_free(mhdr);
+	sk_MIME_HEADER_pop_free(headers, mime_hdr_free);
+	return NULL;
+}
+
+static char *
+strip_ends(char *name)
+{
+	return strip_end(strip_start(name));
+}
+
+/* Strip a parameter of whitespace from start of param */
+static char *
+strip_start(char *name)
+{
+	char *p, c;
+
+	/* Look for first non white space or quote */
+	for (p = name; (c = *p); p++) {
+		if (c == '"') {
+			/* Next char is start of string if non null */
+			if (p[1])
+				return p + 1;
+			/* Else null string */
+			return NULL;
+		}
+		if (!isspace((unsigned char)c))
+			return p;
+	}
+	return NULL;
+}
+
+/* As above but strip from end of string : maybe should handle brackets? */
+static char *
+strip_end(char *name)
+{
+	char *p, c;
+
+	if (!name)
+		return NULL;
+
+	/* Look for first non white space or quote */
+	for (p = name + strlen(name) - 1; p >= name; p--) {
+		c = *p;
+		if (c == '"') {
+			if (p - 1 == name)
+				return NULL;
+			*p = 0;
+			return name;
+		}
+		if (isspace((unsigned char)c))
+			*p = 0;
+		else
+			return name;
+	}
+	return NULL;
+}
+
+static MIME_HEADER *
+mime_hdr_new(char *name, char *value)
+{
+	MIME_HEADER *mhdr;
+	char *tmpname = NULL, *tmpval = NULL, *p;
+
+	if (name) {
+		if (!(tmpname = strdup(name)))
+			goto err;
+		for (p = tmpname; *p; p++)
+			*p = tolower((unsigned char)*p);
+	}
+	if (value) {
+		if (!(tmpval = strdup(value)))
+			goto err;
+		for (p = tmpval; *p; p++)
+			*p = tolower((unsigned char)*p);
+	}
+	mhdr = malloc(sizeof(MIME_HEADER));
+	if (!mhdr)
+		goto err;
+	mhdr->name = tmpname;
+	mhdr->value = tmpval;
+	if (!(mhdr->params = sk_MIME_PARAM_new(mime_param_cmp))) {
+		free(mhdr);
+		goto err;
+	}
+	return mhdr;
+ err:
+	free(tmpname);
+	free(tmpval);
+	return NULL;
+}
+
+static int
+mime_hdr_addparam(MIME_HEADER *mhdr, char *name, char *value)
+{
+	char *tmpname = NULL, *tmpval = NULL, *p;
+	MIME_PARAM *mparam;
+
+	if (name) {
+		tmpname = strdup(name);
+		if (!tmpname)
+			goto err;
+		for (p = tmpname; *p; p++)
+			*p = tolower((unsigned char)*p);
+	}
+	if (value) {
+		tmpval = strdup(value);
+		if (!tmpval)
+			goto err;
+	}
+	/* Parameter values are case sensitive so leave as is */
+	mparam = malloc(sizeof(MIME_PARAM));
+	if (!mparam)
+		goto err;
+	mparam->param_name = tmpname;
+	mparam->param_value = tmpval;
+	if (sk_MIME_PARAM_push(mhdr->params, mparam) == 0) {
+		free(mparam);
+		goto err;
+	}
+	return 1;
+ err:
+	free(tmpname);
+	free(tmpval);
+	return 0;
+}
+
+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;
+	return (strcmp((*a)->name, (*b)->name));
+}
+
+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;
+	return (strcmp((*a)->param_name, (*b)->param_name));
+}
+
+/* Find a header with a given name (if possible) */
+
+static MIME_HEADER *
+mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, char *name)
+{
+	MIME_HEADER htmp;
+	int idx;
+	htmp.name = name;
+	idx = sk_MIME_HEADER_find(hdrs, &htmp);
+	if (idx < 0)
+		return NULL;
+	return sk_MIME_HEADER_value(hdrs, idx);
+}
+
+static MIME_PARAM *
+mime_param_find(MIME_HEADER *hdr, char *name)
+{
+	MIME_PARAM param;
+	int idx;
+	param.param_name = name;
+	idx = sk_MIME_PARAM_find(hdr->params, ¶m);
+	if (idx < 0)
+		return NULL;
+	return sk_MIME_PARAM_value(hdr->params, idx);
+}
+
+static void
+mime_hdr_free(MIME_HEADER *hdr)
+{
+	free(hdr->name);
+	free(hdr->value);
+	if (hdr->params)
+		sk_MIME_PARAM_pop_free(hdr->params, mime_param_free);
+	free(hdr);
+}
+
+static void
+mime_param_free(MIME_PARAM *param)
+{
+	free(param->param_name);
+	free(param->param_value);
+	free(param);
+}
+
+/* Check for a multipart boundary. Returns:
+ * 0 : no boundary
+ * 1 : part boundary
+ * 2 : final boundary
+ */
+static int
+mime_bound_check(char *line, int linelen, char *bound, int blen)
+{
+	if (linelen == -1)
+		linelen = strlen(line);
+	if (blen == -1)
+		blen = strlen(bound);
+	/* Quickly eliminate if line length too short */
+	if (blen + 2 > linelen)
+		return 0;
+	/* Check for part boundary */
+	if (!strncmp(line, "--", 2) && !strncmp(line + 2, bound, blen)) {
+		if (!strncmp(line + blen + 2, "--", 2))
+			return 2;
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int
+strip_eol(char *linebuf, int *plen)
+{
+	int len = *plen;
+	char *p, c;
+	int is_eol = 0;
+
+	for (p = linebuf + len - 1; len > 0; len--, p--) {
+		c = *p;
+		if (c == '\n')
+			is_eol = 1;
+		else if (c != '\r')
+			break;
+	}
+	*plen = len;
+	return is_eol;
+}
diff --git a/crypto/asn1/asn_moid.c b/crypto/asn1/asn_moid.c
new file mode 100644
index 0000000..4da35c0
--- /dev/null
+++ b/crypto/asn1/asn_moid.c
@@ -0,0 +1,161 @@
+/* $OpenBSD: asn_moid.c,v 1.16 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+/* Simple ASN1 OID module: add all objects in a given section */
+
+static int do_create(char *value, char *name);
+
+static int
+oid_module_init(CONF_IMODULE *md, const CONF *cnf)
+{
+	int i;
+	const char *oid_section;
+	STACK_OF(CONF_VALUE) *sktmp;
+	CONF_VALUE *oval;
+
+	oid_section = CONF_imodule_get_value(md);
+	if (!(sktmp = NCONF_get_section(cnf, oid_section))) {
+		ASN1error(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)) {
+			ASN1error(ASN1_R_ADDING_OBJECT);
+			return 0;
+		}
+	}
+	return 1;
+}
+
+static void
+oid_module_finish(CONF_IMODULE *md)
+{
+	OBJ_cleanup();
+}
+
+void
+ASN1_add_oid_module(void)
+{
+	CONF_module_add("oid_section", oid_module_init, oid_module_finish);
+}
+LCRYPTO_ALIAS(ASN1_add_oid_module);
+
+/* Create an OID based on a name value pair. Accept two formats.
+ * shortname = 1.2.3.4
+ * shortname = some long name, 1.2.3.4
+ */
+
+static int
+do_create(char *value, char *name)
+{
+	int nid;
+	ASN1_OBJECT *oid;
+	char *ln, *ostr, *p, *lntmp;
+
+	p = strrchr(value, ',');
+	if (!p) {
+		ln = name;
+		ostr = value;
+	} else {
+		ln = NULL;
+		ostr = p + 1;
+		if (!*ostr)
+			return 0;
+		while (isspace((unsigned char)*ostr))
+			ostr++;
+	}
+
+	nid = OBJ_create(ostr, name, ln);
+
+	if (nid == NID_undef)
+		return 0;
+
+	if (p) {
+		ln = value;
+		while (isspace((unsigned char)*ln))
+			ln++;
+		p--;
+		while (isspace((unsigned char)*p)) {
+			if (p == ln)
+				return 0;
+			p--;
+		}
+		p++;
+		lntmp = malloc((p - ln) + 1);
+		if (lntmp == NULL)
+			return 0;
+		memcpy(lntmp, ln, p - ln);
+		lntmp[p - ln] = 0;
+		oid = OBJ_nid2obj(nid);
+		oid->ln = lntmp;
+	}
+
+	return 1;
+}
diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c
new file mode 100644
index 0000000..b9f54cd
--- /dev/null
+++ b/crypto/asn1/bio_asn1.c
@@ -0,0 +1,453 @@
+/* $OpenBSD: bio_asn1.c,v 1.23 2023/07/28 09:58:30 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* Experimental ASN1 BIO. When written through the data is converted
+ * to an ASN1 string type: default is OCTET STRING. Additional functions
+ * can be provided to add prefix and suffix data.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+
+#define BIO_C_SET_PREFIX			149
+#define BIO_C_SET_SUFFIX			151
+
+/* Must be large enough for biggest tag+length */
+#define DEFAULT_ASN1_BUF_SIZE 20
+
+typedef enum {
+	ASN1_STATE_START,
+	ASN1_STATE_PRE_COPY,
+	ASN1_STATE_HEADER,
+	ASN1_STATE_HEADER_COPY,
+	ASN1_STATE_DATA_COPY,
+	ASN1_STATE_POST_COPY,
+	ASN1_STATE_DONE
+} asn1_bio_state_t;
+
+typedef struct BIO_ASN1_EX_FUNCS_st {
+	asn1_ps_func	*ex_func;
+	asn1_ps_func	*ex_free_func;
+} BIO_ASN1_EX_FUNCS;
+
+typedef struct BIO_ASN1_BUF_CTX_t {
+	/* Internal state */
+	asn1_bio_state_t state;
+	/* Internal buffer */
+	unsigned char *buf;
+	/* Size of buffer */
+	int bufsize;
+	/* Current position in buffer */
+	int bufpos;
+	/* Current buffer length */
+	int buflen;
+	/* Amount of data to copy */
+	int copylen;
+	/* Class and tag to use */
+	int asn1_class, asn1_tag;
+	asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
+	/* Extra buffer for prefix and suffix data */
+	unsigned char *ex_buf;
+	int ex_len;
+	int ex_pos;
+	void *ex_arg;
+} BIO_ASN1_BUF_CTX;
+
+
+static int asn1_bio_write(BIO *h, const char *buf, int num);
+static int asn1_bio_read(BIO *h, char *buf, int size);
+static int asn1_bio_puts(BIO *h, const char *str);
+static int asn1_bio_gets(BIO *h, char *str, int size);
+static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int asn1_bio_new(BIO *h);
+static int asn1_bio_free(BIO *data);
+static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+
+static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
+    asn1_ps_func *cleanup, asn1_bio_state_t next);
+static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
+    asn1_ps_func *setup, asn1_bio_state_t ex_state,
+    asn1_bio_state_t other_state);
+
+static const BIO_METHOD methods_asn1 = {
+	.type = BIO_TYPE_ASN1,
+	.name = "asn1",
+	.bwrite = asn1_bio_write,
+	.bread = asn1_bio_read,
+	.bputs = asn1_bio_puts,
+	.bgets = asn1_bio_gets,
+	.ctrl = asn1_bio_ctrl,
+	.create = asn1_bio_new,
+	.destroy = asn1_bio_free,
+	.callback_ctrl = asn1_bio_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_asn1(void)
+{
+	return (&methods_asn1);
+}
+
+static int
+asn1_bio_new(BIO *b)
+{
+	BIO_ASN1_BUF_CTX *ctx;
+
+	if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
+		return 0;
+
+	if ((ctx->buf = malloc(DEFAULT_ASN1_BUF_SIZE)) == NULL) {
+		free(ctx);
+		return 0;
+	}
+	ctx->bufsize = DEFAULT_ASN1_BUF_SIZE;
+	ctx->asn1_class = V_ASN1_UNIVERSAL;
+	ctx->asn1_tag = V_ASN1_OCTET_STRING;
+	ctx->state = ASN1_STATE_START;
+
+	b->init = 1;
+	b->ptr = ctx;
+	b->flags = 0;
+
+	return 1;
+}
+
+static int
+asn1_bio_free(BIO *b)
+{
+	BIO_ASN1_BUF_CTX *ctx = b->ptr;
+
+	if (ctx == NULL)
+		return 0;
+
+	if (ctx->prefix_free != NULL)
+		ctx->prefix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
+	if (ctx->suffix_free != NULL)
+		ctx->suffix_free(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg);
+
+	free(ctx->buf);
+	free(ctx);
+	b->init = 0;
+	b->ptr = NULL;
+	b->flags = 0;
+	return 1;
+}
+
+static int
+asn1_bio_write(BIO *b, const char *in , int inl)
+{
+	BIO_ASN1_BUF_CTX *ctx;
+	int wrmax, wrlen, ret, buflen;
+	unsigned char *p;
+
+	if (!in || (inl < 0) || (b->next_bio == NULL))
+		return 0;
+
+	if ((ctx = b->ptr) == NULL)
+		return 0;
+
+	wrlen = 0;
+	ret = -1;
+
+	for (;;) {
+		switch (ctx->state) {
+
+			/* Setup prefix data, call it */
+		case ASN1_STATE_START:
+			if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
+				    ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
+				return 0;
+			break;
+
+			/* Copy any pre data first */
+		case ASN1_STATE_PRE_COPY:
+			ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
+			    ASN1_STATE_HEADER);
+			if (ret <= 0)
+				goto done;
+			break;
+
+		case ASN1_STATE_HEADER:
+			buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
+			if (buflen <= 0 || buflen > ctx->bufsize)
+				return -1;
+			ctx->buflen = buflen;
+			p = ctx->buf;
+			ASN1_put_object(&p, 0, inl,
+			    ctx->asn1_tag, ctx->asn1_class);
+			ctx->copylen = inl;
+			ctx->state = ASN1_STATE_HEADER_COPY;
+			break;
+
+		case ASN1_STATE_HEADER_COPY:
+			ret = BIO_write(b->next_bio,
+			    ctx->buf + ctx->bufpos, ctx->buflen);
+			if (ret <= 0)
+				goto done;
+
+			ctx->buflen -= ret;
+			if (ctx->buflen)
+				ctx->bufpos += ret;
+			else {
+				ctx->bufpos = 0;
+				ctx->state = ASN1_STATE_DATA_COPY;
+			}
+			break;
+
+		case ASN1_STATE_DATA_COPY:
+
+			if (inl > ctx->copylen)
+				wrmax = ctx->copylen;
+			else
+				wrmax = inl;
+			ret = BIO_write(b->next_bio, in, wrmax);
+			if (ret <= 0)
+				goto done;
+			wrlen += ret;
+			ctx->copylen -= ret;
+			in += ret;
+			inl -= ret;
+
+			if (ctx->copylen == 0)
+				ctx->state = ASN1_STATE_HEADER;
+			if (inl == 0)
+				goto done;
+			break;
+
+		default:
+			BIO_clear_retry_flags(b);
+			return 0;
+		}
+
+	}
+
+ done:
+	BIO_clear_retry_flags(b);
+	BIO_copy_next_retry(b);
+
+	return (wrlen > 0) ? wrlen : ret;
+}
+
+static int
+asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *cleanup,
+    asn1_bio_state_t next)
+{
+	int ret;
+
+	if (ctx->ex_len <= 0)
+		return 1;
+	for (;;) {
+		ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
+		    ctx->ex_len);
+		if (ret <= 0)
+			break;
+		ctx->ex_len -= ret;
+		if (ctx->ex_len > 0)
+			ctx->ex_pos += ret;
+		else {
+			if (cleanup)
+				cleanup(b, &ctx->ex_buf, &ctx->ex_len,
+				    &ctx->ex_arg);
+			ctx->state = next;
+			ctx->ex_pos = 0;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int
+asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, asn1_ps_func *setup,
+    asn1_bio_state_t ex_state, asn1_bio_state_t other_state)
+{
+	if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) {
+		BIO_clear_retry_flags(b);
+		return 0;
+	}
+	if (ctx->ex_len > 0)
+		ctx->state = ex_state;
+	else
+		ctx->state = other_state;
+	return 1;
+}
+
+static int
+asn1_bio_read(BIO *b, char *in , int inl)
+{
+	if (!b->next_bio)
+		return 0;
+	return BIO_read(b->next_bio, in , inl);
+}
+
+static int
+asn1_bio_puts(BIO *b, const char *str)
+{
+	return asn1_bio_write(b, str, strlen(str));
+}
+
+static int
+asn1_bio_gets(BIO *b, char *str, int size)
+{
+	if (!b->next_bio)
+		return 0;
+	return BIO_gets(b->next_bio, str , size);
+}
+
+static long
+asn1_bio_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 long
+asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
+{
+	BIO_ASN1_BUF_CTX *ctx;
+	BIO_ASN1_EX_FUNCS *ex_func;
+	long ret = 1;
+
+	if ((ctx = b->ptr) == NULL)
+		return 0;
+	switch (cmd) {
+
+	case BIO_C_SET_PREFIX:
+		ex_func = arg2;
+		ctx->prefix = ex_func->ex_func;
+		ctx->prefix_free = ex_func->ex_free_func;
+		break;
+
+	case BIO_C_SET_SUFFIX:
+		ex_func = arg2;
+		ctx->suffix = ex_func->ex_func;
+		ctx->suffix_free = ex_func->ex_free_func;
+		break;
+
+	case BIO_C_SET_EX_ARG:
+		ctx->ex_arg = arg2;
+		break;
+
+	case BIO_C_GET_EX_ARG:
+		*(void **)arg2 = ctx->ex_arg;
+		break;
+
+	case BIO_CTRL_FLUSH:
+		if (!b->next_bio)
+			return 0;
+
+		/* Call post function if possible */
+		if (ctx->state == ASN1_STATE_HEADER) {
+			if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
+			    ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
+				return 0;
+		}
+
+		if (ctx->state == ASN1_STATE_POST_COPY) {
+			ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
+			    ASN1_STATE_DONE);
+			if (ret <= 0)
+				return ret;
+		}
+
+		if (ctx->state == ASN1_STATE_DONE)
+			return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
+		else {
+			BIO_clear_retry_flags(b);
+			return 0;
+		}
+		break;
+
+
+	default:
+		if (!b->next_bio)
+			return 0;
+		return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
+
+	}
+
+	return ret;
+}
+
+static int
+asn1_bio_set_ex(BIO *b, int cmd, asn1_ps_func *ex_func, asn1_ps_func
+    *ex_free_func)
+{
+	BIO_ASN1_EX_FUNCS extmp;
+
+	extmp.ex_func = ex_func;
+	extmp.ex_free_func = ex_free_func;
+	return BIO_ctrl(b, cmd, 0, &extmp);
+}
+
+int
+BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
+{
+	return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
+}
+
+int
+BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
+{
+	return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
+}
diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c
new file mode 100644
index 0000000..98bb1cd
--- /dev/null
+++ b/crypto/asn1/bio_ndef.c
@@ -0,0 +1,270 @@
+/* $OpenBSD: bio_ndef.c,v 1.24 2023/07/28 09:58:30 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free);
+int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free);
+
+/* Experimental NDEF ASN1 BIO support routines */
+
+/* The usage is quite simple, initialize an ASN1 structure,
+ * get a BIO from it then any data written through the BIO
+ * will end up translated to approptiate format on the fly.
+ * The data is streamed out and does *not* need to be
+ * all held in memory at once.
+ *
+ * When the BIO is flushed the output is finalized and any
+ * signatures etc written out.
+ *
+ * The BIO is a 'proper' BIO and can handle non blocking I/O
+ * correctly.
+ *
+ * The usage is simple. The implementation is *not*...
+ */
+
+/* BIO support data stored in the ASN1 BIO ex_arg */
+
+typedef struct ndef_aux_st {
+	/* ASN1 structure this BIO refers to */
+	ASN1_VALUE *val;
+	const ASN1_ITEM *it;
+	/* Top of the BIO chain */
+	BIO *ndef_bio;
+	/* Output BIO */
+	BIO *out;
+	/* Boundary where content is inserted */
+	unsigned char **boundary;
+	/* DER buffer start */
+	unsigned char *derbuf;
+} NDEF_SUPPORT;
+
+static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
+
+BIO *
+BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
+{
+	NDEF_SUPPORT *ndef_aux = NULL;
+	BIO *asn_bio = NULL, *pop_bio = NULL;
+	const ASN1_AUX *aux = it->funcs;
+	ASN1_STREAM_ARG sarg;
+
+	if (aux == NULL || aux->asn1_cb == NULL) {
+		ASN1error(ASN1_R_STREAMING_NOT_SUPPORTED);
+		goto err;
+	}
+
+	if ((asn_bio = BIO_new(BIO_f_asn1())) == NULL)
+		goto err;
+
+	if (BIO_push(asn_bio, out) == NULL)
+		goto err;
+	pop_bio = asn_bio;
+
+	/*
+	 * Set up prefix and suffix handlers first. This ensures that ndef_aux
+	 * is freed as part of asn_bio once it is the asn_bio's ex_arg.
+	 */
+	if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0)
+		goto err;
+	if (BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0)
+		goto err;
+
+	/*
+	 * Allocate early to avoid the tricky cleanup after the asn1_cb().
+	 * Ownership of ndef_aux is transferred to asn_bio in BIO_ctrl().
+	 * Keep a reference to populate it after callback success.
+	 */
+	if ((ndef_aux = calloc(1, sizeof(*ndef_aux))) == NULL)
+		goto err;
+	if (BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0) {
+		free(ndef_aux);
+		goto err;
+	}
+
+	/*
+	 * The callback prepends BIOs to the chain starting at asn_bio for
+	 * digest, cipher, etc. The resulting chain starts at sarg.ndef_bio.
+	 */
+
+	sarg.out = asn_bio;
+	sarg.ndef_bio = NULL;
+	sarg.boundary = NULL;
+
+	if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
+		goto err;
+
+	ndef_aux->val = val;
+	ndef_aux->it = it;
+	ndef_aux->ndef_bio = sarg.ndef_bio;
+	ndef_aux->boundary = sarg.boundary;
+	ndef_aux->out = asn_bio;
+
+	return sarg.ndef_bio;
+
+ err:
+	BIO_pop(pop_bio);
+	BIO_free(asn_bio);
+
+	return NULL;
+}
+
+static int
+ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+{
+	NDEF_SUPPORT *ndef_aux;
+	unsigned char *p = NULL;
+	int derlen;
+
+	if (!parg)
+		return 0;
+
+	ndef_aux = *(NDEF_SUPPORT **)parg;
+
+	if ((derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it)) <= 0)
+		return 0;
+
+	ndef_aux->derbuf = p;
+	*pbuf = p;
+
+	if (*ndef_aux->boundary == NULL)
+		return 0;
+
+	*plen = *ndef_aux->boundary - *pbuf;
+
+	return 1;
+}
+
+static int
+ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+{
+	NDEF_SUPPORT **pndef_aux = parg;
+
+	if (pndef_aux == NULL || *pndef_aux == NULL)
+		return 0;
+
+	free((*pndef_aux)->derbuf);
+	(*pndef_aux)->derbuf = NULL;
+
+	*pbuf = NULL;
+	*plen = 0;
+
+	return 1;
+}
+
+static int
+ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+{
+	NDEF_SUPPORT **pndef_aux = parg;
+
+	/* Ensure ndef_prefix_free() won't fail, so we won't leak *pndef_aux. */
+	if (pndef_aux == NULL || *pndef_aux == NULL)
+		return 0;
+	if (!ndef_prefix_free(b, pbuf, plen, parg))
+		return 0;
+
+	free(*pndef_aux);
+	*pndef_aux = NULL;
+
+	return 1;
+}
+
+static int
+ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
+{
+	NDEF_SUPPORT *ndef_aux;
+	unsigned char *p = NULL;
+	int derlen;
+	const ASN1_AUX *aux;
+	ASN1_STREAM_ARG sarg;
+
+	if (!parg)
+		return 0;
+
+	ndef_aux = *(NDEF_SUPPORT **)parg;
+
+	aux = ndef_aux->it->funcs;
+
+	/* Finalize structures */
+	sarg.ndef_bio = ndef_aux->ndef_bio;
+	sarg.out = ndef_aux->out;
+	sarg.boundary = ndef_aux->boundary;
+	if (aux->asn1_cb(ASN1_OP_STREAM_POST,
+	    &ndef_aux->val, ndef_aux->it, &sarg) <= 0)
+		return 0;
+
+	if ((derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it)) <= 0)
+		return 0;
+
+	ndef_aux->derbuf = p;
+	*pbuf = p;
+
+	if (*ndef_aux->boundary == NULL)
+		return 0;
+
+	*pbuf = *ndef_aux->boundary;
+	*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
+
+	return 1;
+}
diff --git a/crypto/asn1/charmap.h b/crypto/asn1/charmap.h
new file mode 100644
index 0000000..bed5487
--- /dev/null
+++ b/crypto/asn1/charmap.h
@@ -0,0 +1,19 @@
+/* $OpenBSD: charmap.h,v 1.5 2016/12/21 15:49:29 jsing Exp $ */
+/* Auto generated with chartype.pl script.
+ * Mask of various character properties
+ */
+
+__BEGIN_HIDDEN_DECLS
+
+static const unsigned char char_type[] = {
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16,
+	0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0,
+	0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2
+};
+
+__END_HIDDEN_DECLS
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
new file mode 100644
index 0000000..204e818
--- /dev/null
+++ b/crypto/asn1/p5_pbe.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: p5_pbe.c,v 1.25 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* PKCS#5 password based encryption structure */
+
+static const ASN1_TEMPLATE PBEPARAM_seq_tt[] = {
+	{
+		.offset = offsetof(PBEPARAM, salt),
+		.field_name = "salt",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.offset = offsetof(PBEPARAM, iter),
+		.field_name = "iter",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM PBEPARAM_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PBEPARAM_seq_tt,
+	.tcount = sizeof(PBEPARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(PBEPARAM),
+	.sname = "PBEPARAM",
+};
+
+
+PBEPARAM *
+d2i_PBEPARAM(PBEPARAM **a, const unsigned char **in, long len)
+{
+	return (PBEPARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PBEPARAM_it);
+}
+
+int
+i2d_PBEPARAM(PBEPARAM *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBEPARAM_it);
+}
+
+PBEPARAM *
+PBEPARAM_new(void)
+{
+	return (PBEPARAM *)ASN1_item_new(&PBEPARAM_it);
+}
+
+void
+PBEPARAM_free(PBEPARAM *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PBEPARAM_it);
+}
+
+
+/* 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)
+{
+	PBEPARAM *pbe = NULL;
+	ASN1_STRING *pbe_str = NULL;
+	unsigned char *sstr;
+
+	pbe = PBEPARAM_new();
+	if (!pbe) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (iter <= 0)
+		iter = PKCS5_DEFAULT_ITER;
+	if (!ASN1_INTEGER_set(pbe->iter, iter)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!saltlen)
+		saltlen = PKCS5_SALT_LEN;
+	if (!ASN1_STRING_set(pbe->salt, NULL, saltlen)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	sstr = ASN1_STRING_data(pbe->salt);
+	if (salt)
+		memcpy(sstr, salt, saltlen);
+	else
+		arc4random_buf(sstr, saltlen);
+
+	if (!ASN1_item_pack(pbe, &PBEPARAM_it, &pbe_str)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	PBEPARAM_free(pbe);
+	pbe = NULL;
+
+	if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
+		return 1;
+
+ err:
+	if (pbe != NULL)
+		PBEPARAM_free(pbe);
+	ASN1_STRING_free(pbe_str);
+	return 0;
+}
+
+/* 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 *ret;
+	ret = X509_ALGOR_new();
+	if (!ret) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen))
+		return ret;
+
+	X509_ALGOR_free(ret);
+	return NULL;
+}
diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
new file mode 100644
index 0000000..8b6d192
--- /dev/null
+++ b/crypto/asn1/p5_pbev2.c
@@ -0,0 +1,374 @@
+/* $OpenBSD: p5_pbev2.c,v 1.30 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999-2004.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* PKCS#5 v2.0 password based encryption structures */
+
+static const ASN1_TEMPLATE PBE2PARAM_seq_tt[] = {
+	{
+		.offset = offsetof(PBE2PARAM, keyfunc),
+		.field_name = "keyfunc",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(PBE2PARAM, encryption),
+		.field_name = "encryption",
+		.item = &X509_ALGOR_it,
+	},
+};
+
+const ASN1_ITEM PBE2PARAM_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PBE2PARAM_seq_tt,
+	.tcount = sizeof(PBE2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(PBE2PARAM),
+	.sname = "PBE2PARAM",
+};
+
+
+PBE2PARAM *
+d2i_PBE2PARAM(PBE2PARAM **a, const unsigned char **in, long len)
+{
+	return (PBE2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PBE2PARAM_it);
+}
+
+int
+i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBE2PARAM_it);
+}
+
+PBE2PARAM *
+PBE2PARAM_new(void)
+{
+	return (PBE2PARAM *)ASN1_item_new(&PBE2PARAM_it);
+}
+
+void
+PBE2PARAM_free(PBE2PARAM *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PBE2PARAM_it);
+}
+
+static const ASN1_TEMPLATE PBKDF2PARAM_seq_tt[] = {
+	{
+		.offset = offsetof(PBKDF2PARAM, salt),
+		.field_name = "salt",
+		.item = &ASN1_ANY_it,
+	},
+	{
+		.offset = offsetof(PBKDF2PARAM, iter),
+		.field_name = "iter",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(PBKDF2PARAM, keylength),
+		.field_name = "keylength",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(PBKDF2PARAM, prf),
+		.field_name = "prf",
+		.item = &X509_ALGOR_it,
+	},
+};
+
+const ASN1_ITEM PBKDF2PARAM_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PBKDF2PARAM_seq_tt,
+	.tcount = sizeof(PBKDF2PARAM_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(PBKDF2PARAM),
+	.sname = "PBKDF2PARAM",
+};
+
+
+PBKDF2PARAM *
+d2i_PBKDF2PARAM(PBKDF2PARAM **a, const unsigned char **in, long len)
+{
+	return (PBKDF2PARAM *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PBKDF2PARAM_it);
+}
+
+int
+i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PBKDF2PARAM_it);
+}
+
+PBKDF2PARAM *
+PBKDF2PARAM_new(void)
+{
+	return (PBKDF2PARAM *)ASN1_item_new(&PBKDF2PARAM_it);
+}
+
+void
+PBKDF2PARAM_free(PBKDF2PARAM *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PBKDF2PARAM_it);
+}
+
+/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
+ * yes I know this is horrible!
+ *
+ * Extended version to allow application supplied PRF NID 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 *scheme = NULL, *kalg = NULL, *ret = NULL;
+	int alg_nid, keylen;
+	EVP_CIPHER_CTX ctx;
+	unsigned char iv[EVP_MAX_IV_LENGTH];
+	PBE2PARAM *pbe2 = NULL;
+	ASN1_OBJECT *obj;
+
+	alg_nid = EVP_CIPHER_type(cipher);
+	if (alg_nid == NID_undef) {
+		ASN1error(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+		goto err;
+	}
+	obj = OBJ_nid2obj(alg_nid);
+
+	if (!(pbe2 = PBE2PARAM_new()))
+		goto merr;
+
+	/* Setup the AlgorithmIdentifier for the encryption scheme */
+	scheme = pbe2->encryption;
+
+	scheme->algorithm = obj;
+	if (!(scheme->parameter = ASN1_TYPE_new()))
+		goto merr;
+
+	/* Create random IV */
+	if (EVP_CIPHER_iv_length(cipher)) {
+		if (aiv)
+			memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
+		else
+			arc4random_buf(iv, EVP_CIPHER_iv_length(cipher));
+	}
+
+	EVP_CIPHER_CTX_init(&ctx);
+
+	/* Dummy cipherinit to just setup the IV, and PRF */
+	if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0))
+		goto err;
+	if (EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) {
+		ASN1error(ASN1_R_ERROR_SETTING_CIPHER_PARAMS);
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		goto err;
+	}
+	/* If prf NID unspecified see if cipher has a preference.
+	 * An error is OK here: just means use default PRF.
+	 */
+	if ((prf_nid == -1) &&
+	    EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) {
+		ERR_clear_error();
+		prf_nid = NID_hmacWithSHA1;
+	}
+	EVP_CIPHER_CTX_cleanup(&ctx);
+
+	/* If its RC2 then we'd better setup the key length */
+
+	if (alg_nid == NID_rc2_cbc)
+		keylen = EVP_CIPHER_key_length(cipher);
+	else
+		keylen = -1;
+
+	/* Setup keyfunc */
+
+	X509_ALGOR_free(pbe2->keyfunc);
+
+	pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
+
+	if (!pbe2->keyfunc)
+		goto merr;
+
+	/* Now set up top level AlgorithmIdentifier */
+
+	if (!(ret = X509_ALGOR_new()))
+		goto merr;
+	if (!(ret->parameter = ASN1_TYPE_new()))
+		goto merr;
+
+	ret->algorithm = OBJ_nid2obj(NID_pbes2);
+
+	/* Encode PBE2PARAM into parameter */
+
+	if (!ASN1_item_pack(pbe2, &PBE2PARAM_it,
+		&ret->parameter->value.sequence)) goto merr;
+	ret->parameter->type = V_ASN1_SEQUENCE;
+
+	PBE2PARAM_free(pbe2);
+	pbe2 = NULL;
+
+	return ret;
+
+ merr:
+	ASN1error(ERR_R_MALLOC_FAILURE);
+
+ err:
+	PBE2PARAM_free(pbe2);
+	/* Note 'scheme' is freed as part of pbe2 */
+	X509_ALGOR_free(kalg);
+	X509_ALGOR_free(ret);
+
+	return 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);
+}
+
+X509_ALGOR *
+PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, int prf_nid,
+    int keylen)
+{
+	X509_ALGOR *keyfunc = NULL;
+	PBKDF2PARAM *kdf = NULL;
+	ASN1_OCTET_STRING *osalt = NULL;
+
+	if (!(kdf = PBKDF2PARAM_new()))
+		goto merr;
+	if (!(osalt = ASN1_OCTET_STRING_new()))
+		goto merr;
+
+	kdf->salt->value.octet_string = osalt;
+	kdf->salt->type = V_ASN1_OCTET_STRING;
+
+	if (!saltlen)
+		saltlen = PKCS5_SALT_LEN;
+	if (!(osalt->data = malloc (saltlen)))
+		goto merr;
+
+	osalt->length = saltlen;
+
+	if (salt)
+		memcpy (osalt->data, salt, saltlen);
+	else
+		arc4random_buf(osalt->data, saltlen);
+
+	if (iter <= 0)
+		iter = PKCS5_DEFAULT_ITER;
+
+	if (!ASN1_INTEGER_set(kdf->iter, iter))
+		goto merr;
+
+	/* If have a key len set it up */
+
+	if (keylen > 0) {
+		if (!(kdf->keylength = ASN1_INTEGER_new()))
+			goto merr;
+		if (!ASN1_INTEGER_set(kdf->keylength, keylen))
+			goto merr;
+	}
+
+	/* prf can stay NULL if we are using hmacWithSHA1 */
+	if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) {
+		kdf->prf = X509_ALGOR_new();
+		if (!kdf->prf)
+			goto merr;
+		X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid),
+		V_ASN1_NULL, NULL);
+	}
+
+	/* Finally setup the keyfunc structure */
+
+	keyfunc = X509_ALGOR_new();
+	if (!keyfunc)
+		goto merr;
+
+	keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2);
+
+	/* Encode PBKDF2PARAM into parameter of pbe2 */
+
+	if (!(keyfunc->parameter = ASN1_TYPE_new()))
+		goto merr;
+
+	if (!ASN1_item_pack(kdf, &PBKDF2PARAM_it,
+		&keyfunc->parameter->value.sequence))
+		goto merr;
+	keyfunc->parameter->type = V_ASN1_SEQUENCE;
+
+	PBKDF2PARAM_free(kdf);
+	return keyfunc;
+
+ merr:
+	ASN1error(ERR_R_MALLOC_FAILURE);
+	PBKDF2PARAM_free(kdf);
+	X509_ALGOR_free(keyfunc);
+	return NULL;
+}
diff --git a/crypto/asn1/p8_pkey.c b/crypto/asn1/p8_pkey.c
new file mode 100644
index 0000000..9e0cfc4
--- /dev/null
+++ b/crypto/asn1/p8_pkey.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: p8_pkey.c,v 1.23 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "x509_local.h"
+
+/* Minor tweak to operation: zero private key data */
+static int
+pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	/* Since the structure must still be valid use ASN1_OP_FREE_PRE */
+	if (operation == ASN1_OP_FREE_PRE) {
+		PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
+		if (key->pkey != NULL)
+			explicit_bzero(key->pkey->data, key->pkey->length);
+	}
+	return 1;
+}
+
+static const ASN1_AUX PKCS8_PRIV_KEY_INFO_aux = {
+	.asn1_cb = pkey_cb,
+};
+static const ASN1_TEMPLATE PKCS8_PRIV_KEY_INFO_seq_tt[] = {
+	{
+		.offset = offsetof(PKCS8_PRIV_KEY_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(PKCS8_PRIV_KEY_INFO, pkeyalg),
+		.field_name = "pkeyalg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(PKCS8_PRIV_KEY_INFO, pkey),
+		.field_name = "pkey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(PKCS8_PRIV_KEY_INFO, attributes),
+		.field_name = "attributes",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM PKCS8_PRIV_KEY_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS8_PRIV_KEY_INFO_seq_tt,
+	.tcount = sizeof(PKCS8_PRIV_KEY_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &PKCS8_PRIV_KEY_INFO_aux,
+	.size = sizeof(PKCS8_PRIV_KEY_INFO),
+	.sname = "PKCS8_PRIV_KEY_INFO",
+};
+
+
+PKCS8_PRIV_KEY_INFO *
+d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, const unsigned char **in, long len)
+{
+	return (PKCS8_PRIV_KEY_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS8_PRIV_KEY_INFO_it);
+}
+
+int
+i2d_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS8_PRIV_KEY_INFO_it);
+}
+
+PKCS8_PRIV_KEY_INFO *
+PKCS8_PRIV_KEY_INFO_new(void)
+{
+	return (PKCS8_PRIV_KEY_INFO *)ASN1_item_new(&PKCS8_PRIV_KEY_INFO_it);
+}
+
+void
+PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS8_PRIV_KEY_INFO_it);
+}
+
+int
+PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
+    int ptype, void *pval, unsigned char *penc, int penclen)
+{
+	if (version >= 0) {
+		if (!ASN1_INTEGER_set(priv->version, version))
+			return 0;
+	}
+	if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval))
+		return 0;
+	if (penc != NULL)
+		ASN1_STRING_set0(priv->pkey, penc, penclen);
+	return 1;
+}
+
+int
+PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, const unsigned char **pk,
+    int *ppklen, const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8)
+{
+	if (ppkalg != NULL)
+		*ppkalg = p8->pkeyalg->algorithm;
+	if (pk != NULL) {
+		*pk = ASN1_STRING_data(p8->pkey);
+		*ppklen = ASN1_STRING_length(p8->pkey);
+	}
+	if (pa != NULL)
+		*pa = p8->pkeyalg;
+	return 1;
+}
+
+const STACK_OF(X509_ATTRIBUTE) *
+PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8)
+{
+	return p8->attributes;
+}
+
+int
+PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type,
+    const unsigned char *bytes, int len)
+{
+	if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes,
+	    len) != NULL)
+		return 1;
+	return 0;
+}
diff --git a/crypto/asn1/t_crl.c b/crypto/asn1/t_crl.c
new file mode 100644
index 0000000..d662d99
--- /dev/null
+++ b/crypto/asn1/t_crl.c
@@ -0,0 +1,145 @@
+/* $OpenBSD: t_crl.c,v 1.23 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+int
+X509_CRL_print_fp(FILE *fp, X509_CRL *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		X509error(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = X509_CRL_print(b, x);
+	BIO_free(b);
+	return (ret);
+}
+
+int
+X509_CRL_print(BIO *out, X509_CRL *x)
+{
+	STACK_OF(X509_REVOKED) *rev;
+	X509_REVOKED *r;
+	long l;
+	int i;
+	char *p;
+
+	BIO_printf(out, "Certificate Revocation List (CRL):\n");
+	l = X509_CRL_get_version(x);
+	if (l < 0 || l == LONG_MAX)
+		goto err;
+	BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l);
+	i = OBJ_obj2nid(x->sig_alg->algorithm);
+	if (X509_signature_print(out, x->sig_alg, NULL) == 0)
+		goto err;
+	p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0);
+	if (p == NULL)
+		goto err;
+	BIO_printf(out, "%8sIssuer: %s\n", "", p);
+	free(p);
+	BIO_printf(out, "%8sLast Update: ", "");
+	ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x));
+	BIO_printf(out, "\n%8sNext Update: ", "");
+	if (X509_CRL_get_nextUpdate(x))
+		ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x));
+	else
+		BIO_printf(out, "NONE");
+	BIO_printf(out, "\n");
+
+	X509V3_extensions_print(out, "CRL extensions",
+	    x->crl->extensions, 0, 8);
+
+	rev = X509_CRL_get_REVOKED(x);
+
+	if (sk_X509_REVOKED_num(rev) > 0)
+		BIO_printf(out, "Revoked Certificates:\n");
+	else
+		BIO_printf(out, "No Revoked Certificates.\n");
+
+	for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
+		r = sk_X509_REVOKED_value(rev, i);
+		BIO_printf(out, "    Serial Number: ");
+		i2a_ASN1_INTEGER(out, r->serialNumber);
+		BIO_printf(out, "\n        Revocation Date: ");
+		ASN1_TIME_print(out, r->revocationDate);
+		BIO_printf(out, "\n");
+		X509V3_extensions_print(out, "CRL entry extensions",
+		    r->extensions, 0, 8);
+	}
+	if (X509_signature_print(out, x->sig_alg, x->signature) == 0)
+		goto err;
+
+	return 1;
+
+ err:
+	return 0;
+}
diff --git a/crypto/asn1/t_req.c b/crypto/asn1/t_req.c
new file mode 100644
index 0000000..2fd9842
--- /dev/null
+++ b/crypto/asn1/t_req.c
@@ -0,0 +1,262 @@
+/* $OpenBSD: t_req.c,v 1.26 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "x509_local.h"
+
+int
+X509_REQ_print_fp(FILE *fp, X509_REQ *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		X509error(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = X509_REQ_print(b, x);
+	BIO_free(b);
+	return (ret);
+}
+
+int
+X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags,
+    unsigned long cflag)
+{
+	unsigned long l;
+	int i;
+	const char *neg;
+	X509_REQ_INFO *ri;
+	EVP_PKEY *pkey;
+	STACK_OF(X509_ATTRIBUTE) *sk;
+	STACK_OF(X509_EXTENSION) *exts = NULL;
+	char mlch = ' ';
+	int nmindent = 0;
+
+	if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+		mlch = '\n';
+		nmindent = 12;
+	}
+
+	if (nmflags == X509_FLAG_COMPAT)
+		nmindent = 16;
+
+	ri = x->req_info;
+	if (!(cflag & X509_FLAG_NO_HEADER)) {
+		if (BIO_write(bp, "Certificate Request:\n", 21) <= 0)
+			goto err;
+		if (BIO_write(bp, "    Data:\n", 10) <= 0)
+
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_VERSION)) {
+		neg = (ri->version->type == V_ASN1_NEG_INTEGER) ? "-" : "";
+		l = 0;
+		for (i = 0; i < ri->version->length; i++) {
+			l <<= 8;
+			l += ri->version->data[i];
+		}
+		if (BIO_printf(bp, "%8sVersion: %s%lu (%s0x%lx)\n", "", neg,
+		    l, neg, l) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_SUBJECT)) {
+		if (BIO_printf(bp, "        Subject:%c", mlch) <= 0)
+			goto err;
+		if (X509_NAME_print_ex(bp, ri->subject, nmindent, nmflags) < 0)
+			goto err;
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_PUBKEY)) {
+		if (BIO_write(bp, "        Subject Public Key Info:\n",
+		    33) <= 0)
+			goto err;
+		if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
+			goto err;
+		if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0)
+			goto err;
+		if (BIO_puts(bp, "\n") <= 0)
+			goto err;
+
+		pkey = X509_REQ_get_pubkey(x);
+		if (pkey == NULL) {
+			BIO_printf(bp, "%12sUnable to load Public Key\n", "");
+			ERR_print_errors(bp);
+		} else {
+			EVP_PKEY_print_public(bp, pkey, 16, NULL);
+			EVP_PKEY_free(pkey);
+		}
+	}
+
+	if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) {
+		/* may not be */
+		if (BIO_printf(bp, "%8sAttributes:\n", "") <= 0)
+			goto err;
+
+		sk = x->req_info->attributes;
+		if (sk_X509_ATTRIBUTE_num(sk) == 0) {
+			if (BIO_printf(bp, "%12sa0:00\n", "") <= 0)
+				goto err;
+		} else {
+			for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
+				ASN1_TYPE *at;
+				X509_ATTRIBUTE *a;
+				ASN1_BIT_STRING *bs = NULL;
+				int j, type = 0, count = 1, ii = 0;
+
+				a = sk_X509_ATTRIBUTE_value(sk, i);
+				if (X509_REQ_extension_nid(
+				    OBJ_obj2nid(a->object)))
+					continue;
+				if (BIO_printf(bp, "%12s", "") <= 0)
+					goto err;
+				if ((j = i2a_ASN1_OBJECT(bp, a->object)) > 0) {
+					ii = 0;
+					count = sk_ASN1_TYPE_num(a->set);
+ get_next:
+					at = sk_ASN1_TYPE_value(a->set, ii);
+					type = at->type;
+					bs = at->value.asn1_string;
+				}
+				for (j = 25 - j; j > 0; j--)
+					if (BIO_write(bp, " ", 1) != 1)
+						goto err;
+				if (BIO_puts(bp, ":") <= 0)
+					goto err;
+				if ((type == V_ASN1_PRINTABLESTRING) ||
+				    (type == V_ASN1_T61STRING) ||
+				    (type == V_ASN1_IA5STRING)) {
+					if (BIO_write(bp, (char *)bs->data,
+					    bs->length) != bs->length)
+						goto err;
+					BIO_puts(bp, "\n");
+				} else {
+					BIO_puts(bp,
+					    "unable to print attribute\n");
+				}
+				if (++ii < count)
+					goto get_next;
+			}
+		}
+	}
+	if (!(cflag & X509_FLAG_NO_EXTENSIONS)) {
+		exts = X509_REQ_get_extensions(x);
+		if (exts) {
+			BIO_printf(bp, "%8sRequested Extensions:\n", "");
+			for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+				ASN1_OBJECT *obj;
+				X509_EXTENSION *ex;
+				int j;
+				ex = sk_X509_EXTENSION_value(exts, i);
+				if (BIO_printf(bp, "%12s", "") <= 0)
+					goto err;
+				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)
+					goto err;
+				if (!X509V3_EXT_print(bp, ex, cflag, 16)) {
+					BIO_printf(bp, "%16s", "");
+					ASN1_STRING_print(bp, ex->value);
+				}
+				if (BIO_write(bp, "\n", 1) <= 0)
+					goto err;
+			}
+			sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+			exts = NULL;
+		}
+	}
+
+	if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
+		if (!X509_signature_print(bp, x->sig_alg, x->signature))
+			goto err;
+	}
+
+	return (1);
+
+ err:
+	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+	X509error(ERR_R_BUF_LIB);
+	return (0);
+}
+
+int
+X509_REQ_print(BIO *bp, X509_REQ *x)
+{
+	return X509_REQ_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
diff --git a/crypto/asn1/t_spki.c b/crypto/asn1/t_spki.c
new file mode 100644
index 0000000..73996b6
--- /dev/null
+++ b/crypto/asn1/t_spki.c
@@ -0,0 +1,115 @@
+/* $OpenBSD: t_spki.c,v 1.16 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "x509_local.h"
+
+/* Print out an SPKI */
+
+int
+NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki)
+{
+	EVP_PKEY *pkey;
+	ASN1_IA5STRING *chal;
+	int i, n;
+	char *s;
+
+	BIO_printf(out, "Netscape SPKI:\n");
+	i = OBJ_obj2nid(spki->spkac->pubkey->algor->algorithm);
+	BIO_printf(out, "  Public Key Algorithm: %s\n",
+	    (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
+	pkey = X509_PUBKEY_get(spki->spkac->pubkey);
+	if (!pkey)
+		BIO_printf(out, "  Unable to load public key\n");
+	else {
+		EVP_PKEY_print_public(out, pkey, 4, NULL);
+		EVP_PKEY_free(pkey);
+	}
+	chal = spki->spkac->challenge;
+	if (chal->length)
+		BIO_printf(out, "  Challenge String: %.*s\n", chal->length,
+		    chal->data);
+	i = OBJ_obj2nid(spki->sig_algor->algorithm);
+	BIO_printf(out, "  Signature Algorithm: %s",
+	    (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
+
+	n = spki->signature->length;
+	s = (char *)spki->signature->data;
+	for (i = 0; i < n; i++) {
+		if ((i % 18) == 0)
+			BIO_write(out, "\n      ", 7);
+		BIO_printf(out, "%02x%s", (unsigned char)s[i],
+		    ((i + 1) == n) ? "" : ":");
+	}
+	BIO_write(out, "\n", 1);
+	return 1;
+}
diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c
new file mode 100644
index 0000000..cd98997
--- /dev/null
+++ b/crypto/asn1/t_x509.c
@@ -0,0 +1,515 @@
+/* $OpenBSD: t_x509.c,v 1.43 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_EC
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "x509_local.h"
+
+int
+X509_print_fp(FILE *fp, X509 *x)
+{
+	return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
+
+int
+X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		X509error(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = X509_print_ex(b, x, nmflag, cflag);
+	BIO_free(b);
+	return (ret);
+}
+
+int
+X509_print(BIO *bp, X509 *x)
+{
+	return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
+
+int
+X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
+{
+	long l;
+	int ret = 0, i;
+	char *m = NULL, mlch = ' ';
+	int nmindent = 0;
+	X509_CINF *ci;
+	ASN1_INTEGER *bs;
+	EVP_PKEY *pkey = NULL;
+
+	if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+		mlch = '\n';
+		nmindent = 12;
+	}
+
+	if (nmflags == X509_FLAG_COMPAT)
+		nmindent = 16;
+
+	ci = x->cert_info;
+	if (!(cflag & X509_FLAG_NO_HEADER)) {
+		if (BIO_write(bp, "Certificate:\n", 13) <= 0)
+			goto err;
+		if (BIO_write(bp, "    Data:\n", 10) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_VERSION)) {
+		l = X509_get_version(x);
+		if (l >= 0 && l <= 2) {
+			if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n",
+			    "", l + 1, l) <= 0)
+				goto err;
+		} else {
+			if (BIO_printf(bp, "%8sVersion: unknown (%ld)\n",
+			    "", l) <= 0)
+				goto err;
+		}
+	}
+	if (!(cflag & X509_FLAG_NO_SERIAL)) {
+		if (BIO_write(bp, "        Serial Number:", 22) <= 0)
+			goto err;
+
+		bs = X509_get_serialNumber(x);
+		l = -1;
+		if (bs->length <= (int)sizeof(long))
+			l = ASN1_INTEGER_get(bs);
+		if (l >= 0) {
+			if (BIO_printf(bp, " %ld (0x%lx)\n", l, l) <= 0)
+				goto err;
+		} else {
+			const char *neg = "";
+
+			if (bs->type == V_ASN1_NEG_INTEGER)
+				neg = " (Negative)";
+
+			if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
+				goto err;
+			for (i = 0; i < bs->length; i++) {
+				if (BIO_printf(bp, "%02x%c", bs->data[i],
+				    ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
+					goto err;
+			}
+		}
+
+	}
+
+	if (!(cflag & X509_FLAG_NO_SIGNAME)) {
+		if (X509_signature_print(bp, x->sig_alg, NULL) <= 0)
+			goto err;
+	}
+
+	if (!(cflag & X509_FLAG_NO_ISSUER)) {
+		if (BIO_printf(bp, "        Issuer:%c", mlch) <= 0)
+			goto err;
+		if (X509_NAME_print_ex(bp, X509_get_issuer_name(x),
+		    nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
+			goto err;
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_VALIDITY)) {
+		if (BIO_write(bp, "        Validity\n", 17) <= 0)
+			goto err;
+		if (BIO_write(bp, "            Not Before: ", 24) <= 0)
+			goto err;
+		if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
+			goto err;
+		if (BIO_write(bp, "\n            Not After : ", 25) <= 0)
+			goto err;
+		if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
+			goto err;
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_SUBJECT)) {
+		if (BIO_printf(bp, "        Subject:%c", mlch) <= 0)
+			goto err;
+		if (X509_NAME_print_ex(bp, X509_get_subject_name(x),
+		    nmindent, nmflags) < (nmflags == X509_FLAG_COMPAT ? 1 : 0))
+			goto err;
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_PUBKEY)) {
+		if (BIO_write(bp, "        Subject Public Key Info:\n",
+		    33) <= 0)
+			goto err;
+		if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
+			goto err;
+		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
+			goto err;
+		if (BIO_puts(bp, "\n") <= 0)
+			goto err;
+
+		pkey = X509_get_pubkey(x);
+		if (pkey == NULL) {
+			BIO_printf(bp, "%12sUnable to load Public Key\n", "");
+			ERR_print_errors(bp);
+		} else {
+			EVP_PKEY_print_public(bp, pkey, 16, NULL);
+			EVP_PKEY_free(pkey);
+		}
+	}
+
+	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
+		X509V3_extensions_print(bp, "X509v3 extensions",
+		    ci->extensions, cflag, 8);
+
+	if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
+		if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
+			goto err;
+	}
+	if (!(cflag & X509_FLAG_NO_AUX)) {
+		if (!X509_CERT_AUX_print(bp, x->aux, 0))
+			goto err;
+	}
+	ret = 1;
+
+ err:
+	free(m);
+	return (ret);
+}
+
+int
+X509_ocspid_print(BIO *bp, X509 *x)
+{
+	unsigned char *der = NULL;
+	unsigned char *dertmp;
+	int derlen;
+	int i;
+	unsigned char SHA1md[SHA_DIGEST_LENGTH];
+
+	/* display the hash of the subject as it would appear
+	   in OCSP requests */
+	if (BIO_printf(bp, "        Subject OCSP hash: ") <= 0)
+		goto err;
+	if ((derlen = i2d_X509_NAME(x->cert_info->subject, NULL)) <= 0)
+		goto err;
+	if ((der = dertmp = malloc(derlen)) == NULL)
+		goto err;
+	if (i2d_X509_NAME(x->cert_info->subject, &dertmp) <= 0)
+		goto err;
+
+	if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+		goto err;
+	for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+		if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
+			goto err;
+	}
+	free (der);
+	der = NULL;
+
+	/* display the hash of the public key as it would appear
+	   in OCSP requests */
+	if (BIO_printf(bp, "\n        Public key OCSP hash: ") <= 0)
+		goto err;
+
+	if (!EVP_Digest(x->cert_info->key->public_key->data,
+	    x->cert_info->key->public_key->length,
+	    SHA1md, NULL, EVP_sha1(), 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");
+
+	return (1);
+
+ err:
+	free(der);
+	return (0);
+}
+
+int
+X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent)
+{
+	const unsigned char *s;
+	int i, n;
+
+	n = sig->length;
+	s = sig->data;
+	for (i = 0; i < n; i++) {
+		if ((i % 18) == 0) {
+			if (BIO_write(bp, "\n", 1) <= 0)
+				return 0;
+			if (BIO_indent(bp, indent, indent) <= 0)
+				return 0;
+		}
+		if (BIO_printf(bp, "%02x%s", s[i],
+		    ((i + 1) == n) ? "" : ":") <= 0)
+			return 0;
+	}
+	if (BIO_write(bp, "\n", 1) != 1)
+		return 0;
+
+	return 1;
+}
+
+int
+X509_signature_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig)
+{
+	int sig_nid;
+	if (BIO_puts(bp, "    Signature Algorithm: ") <= 0)
+		return 0;
+	if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
+		return 0;
+
+	sig_nid = OBJ_obj2nid(sigalg->algorithm);
+	if (sig_nid != NID_undef) {
+		int pkey_nid, dig_nid;
+		const EVP_PKEY_ASN1_METHOD *ameth;
+		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);
+		}
+	}
+	if (sig)
+		return X509_signature_dump(bp, sig, 9);
+	else if (BIO_puts(bp, "\n") <= 0)
+		return 0;
+	return 1;
+}
+
+int
+ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
+{
+	if (tm->type == V_ASN1_UTCTIME)
+		return ASN1_UTCTIME_print(bp, tm);
+	if (tm->type == V_ASN1_GENERALIZEDTIME)
+		return ASN1_GENERALIZEDTIME_print(bp, tm);
+	BIO_write(bp, "Bad time value", 14);
+	return (0);
+}
+LCRYPTO_ALIAS(ASN1_TIME_print);
+
+static const char *mon[12] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+int
+ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
+{
+	char *v;
+	int gmt = 0;
+	int i;
+	int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+	char *f = "";
+	int f_len = 0;
+
+	i = tm->length;
+	v = (char *)tm->data;
+
+	if (i < 12)
+		goto err;
+	if (v[i-1] == 'Z')
+		gmt = 1;
+	for (i = 0; i < 12; i++)
+		if ((v[i] > '9') || (v[i] < '0'))
+			goto err;
+	y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 +
+	    (v[2] - '0') * 10 + (v[3] - '0');
+	M = (v[4] - '0') * 10 + (v[5] - '0');
+	if ((M > 12) || (M < 1))
+		goto err;
+	d = (v[6] - '0') * 10 + (v[7] - '0');
+	h = (v[8] - '0') * 10 + (v[9] - '0');
+	m = (v[10] - '0') * 10 + (v[11] - '0');
+	if (tm->length >= 14 &&
+	    (v[12] >= '0') && (v[12] <= '9') &&
+	    (v[13] >= '0') && (v[13] <= '9')) {
+		s =  (v[12] - '0') * 10 + (v[13] - '0');
+		/* Check for fractions of seconds. */
+		if (tm->length >= 15 && v[14] == '.') {
+			int l = tm->length;
+			f = &v[14];	/* The decimal point. */
+			f_len = 1;
+			while (14 + f_len < l && f[f_len] >= '0' &&
+			    f[f_len] <= '9')
+				++f_len;
+		}
+	}
+
+	if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+	    mon[M - 1], d, h, m, s, f_len, f, y, (gmt) ? " GMT" : "") <= 0)
+		return (0);
+	else
+		return (1);
+
+ err:
+	BIO_write(bp, "Bad time value", 14);
+	return (0);
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_print);
+
+int
+ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
+{
+	const char *v;
+	int gmt = 0;
+	int i;
+	int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+
+	i = tm->length;
+	v = (const char *)tm->data;
+
+	if (i < 10)
+		goto err;
+	if (v[i-1] == 'Z')
+		gmt = 1;
+	for (i = 0; i < 10; i++)
+		if ((v[i] > '9') || (v[i] < '0'))
+			goto err;
+	y = (v[0] - '0') * 10 + (v[1] - '0');
+	if (y < 50)
+		y += 100;
+	M = (v[2] - '0') * 10 + (v[3] - '0');
+	if ((M > 12) || (M < 1))
+		goto err;
+	d = (v[4] - '0') * 10 + (v[5] - '0');
+	h = (v[6] - '0') * 10 + (v[7] - '0');
+	m = (v[8] - '0') * 10 + (v[9] - '0');
+	if (tm->length >=12 &&
+	    (v[10] >= '0') && (v[10] <= '9') &&
+	    (v[11] >= '0') && (v[11] <= '9'))
+		s = (v[10] - '0') * 10 + (v[11] - '0');
+
+	if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
+	    mon[M - 1], d, h, m, s, y + 1900, (gmt) ? " GMT" : "") <= 0)
+		return (0);
+	else
+		return (1);
+
+ err:
+	BIO_write(bp, "Bad time value", 14);
+	return (0);
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_print);
+
+int
+X509_NAME_print(BIO *bp, const X509_NAME *name, int obase)
+{
+	char *s, *c, *b;
+	int i;
+	int ret = 0;
+
+	b = X509_NAME_oneline(name, NULL, 0);
+	if (b == NULL)
+		return 0;
+	if (*b == '\0') {
+		free(b);
+		return 1;
+	}
+	s = b + 1; /* skip the first slash */
+
+	c = s;
+	for (;;) {
+		if (((*s == '/') &&
+		    ((s[1] >= 'A') && (s[1] <= 'Z') &&
+		    ((s[2] == '=') || ((s[2] >= 'A') && (s[2] <= 'Z') &&
+		    (s[3] == '='))))) || (*s == '\0')) {
+			i = s - c;
+			if (BIO_write(bp, c, i) != i)
+				goto err;
+			c = s + 1;	/* skip following slash */
+			if (*s != '\0') {
+				if (BIO_write(bp, ", ", 2) != 2)
+					goto err;
+			}
+		}
+		if (*s == '\0')
+			break;
+		s++;
+	}
+
+	ret = 1;
+	if (0) {
+ err:
+		X509error(ERR_R_BUF_LIB);
+	}
+	free(b);
+	return (ret);
+}
diff --git a/crypto/asn1/t_x509a.c b/crypto/asn1/t_x509a.c
new file mode 100644
index 0000000..7dbf844
--- /dev/null
+++ b/crypto/asn1/t_x509a.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: t_x509a.c,v 1.13 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+/* X509_CERT_AUX and string set routines */
+
+int
+X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
+{
+	char oidstr[80], first;
+	int i;
+	if (!aux)
+		return 1;
+	if (aux->trust) {
+		first = 1;
+		BIO_printf(out, "%*sTrusted Uses:\n%*s",
+		    indent, "", indent + 2, "");
+		for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
+			if (!first)
+				BIO_puts(out, ", ");
+			else
+				first = 0;
+			OBJ_obj2txt(oidstr, sizeof oidstr,
+			    sk_ASN1_OBJECT_value(aux->trust, i), 0);
+			BIO_puts(out, oidstr);
+		}
+		BIO_puts(out, "\n");
+	} else
+		BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
+	if (aux->reject) {
+		first = 1;
+		BIO_printf(out, "%*sRejected Uses:\n%*s",
+		    indent, "", indent + 2, "");
+		for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
+			if (!first)
+				BIO_puts(out, ", ");
+			else
+				first = 0;
+			OBJ_obj2txt(oidstr, sizeof oidstr,
+			    sk_ASN1_OBJECT_value(aux->reject, i), 0);
+			BIO_puts(out, oidstr);
+		}
+		BIO_puts(out, "\n");
+	} else
+		BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
+	if (aux->alias)
+		BIO_printf(out, "%*sAlias: %.*s\n", indent, "",
+		    aux->alias->length, aux->alias->data);
+	if (aux->keyid) {
+		BIO_printf(out, "%*sKey Id: ", indent, "");
+		for (i = 0; i < aux->keyid->length; i++)
+			BIO_printf(out, "%s%02X", i ? ":" : "",
+			    aux->keyid->data[i]);
+		BIO_write(out, "\n", 1);
+	}
+	return 1;
+}
diff --git a/crypto/asn1/tasn_dec.c b/crypto/asn1/tasn_dec.c
new file mode 100644
index 0000000..31b9efe
--- /dev/null
+++ b/crypto/asn1/tasn_dec.c
@@ -0,0 +1,1260 @@
+/* $OpenBSD: tasn_dec.c,v 1.88 2023/07/28 10:00:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bytestring.h"
+
+/*
+ * Constructed types with a recursive definition (such as can be found in PKCS7)
+ * could eventually exceed the stack given malicious input with excessive
+ * recursion. Therefore we limit the stack depth.
+ */
+#define ASN1_MAX_CONSTRUCTED_NEST 30
+
+#ifndef ASN1_MAX_STRING_NEST
+/*
+ * This determines how many levels of recursion are permitted in ASN.1 string
+ * types. If it is not limited stack overflows can occur. If set to zero no
+ * recursion is allowed at all.
+ */
+#define ASN1_MAX_STRING_NEST 5
+#endif
+
+static int asn1_template_d2i(ASN1_VALUE **pval, CBS *cbs,
+    const ASN1_TEMPLATE *at, int optional, int depth);
+
+static int
+asn1_check_eoc(CBS *cbs)
+{
+	uint16_t eoc;
+
+	if (!CBS_peek_u16(cbs, &eoc))
+		return 0;
+	if (eoc != 0)
+		return 0;
+
+	return CBS_skip(cbs, 2);
+}
+
+static int
+asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class,
+    int *out_indefinite, int *out_constructed, int expected_tag,
+    int expected_class, int optional)
+{
+	int constructed, indefinite;
+	uint32_t tag_number;
+	uint8_t tag_class;
+	size_t length;
+
+	if (out_len != NULL)
+		*out_len = 0;
+	if (out_tag != NULL)
+		*out_tag = 0;
+	if (out_class != NULL)
+		*out_class = 0;
+	if (out_indefinite != NULL)
+		*out_indefinite = 0;
+	if (out_constructed != NULL)
+		*out_constructed = 0;
+
+	if (!asn1_get_identifier_cbs(cbs, 0, &tag_class, &constructed,
+	    &tag_number)) {
+		ASN1error(ASN1_R_BAD_OBJECT_HEADER);
+		return 0;
+	}
+	if (expected_tag >= 0) {
+		if (expected_tag != tag_number ||
+		    expected_class != tag_class << 6) {
+			/* Indicate missing type if this is OPTIONAL. */
+			if (optional)
+				return -1;
+
+			ASN1error(ASN1_R_WRONG_TAG);
+			return 0;
+		}
+	}
+	if (!asn1_get_length_cbs(cbs, 0, &indefinite, &length)) {
+		ASN1error(ASN1_R_BAD_OBJECT_HEADER);
+		return 0;
+	}
+
+	/* Indefinite length can only be used with constructed encoding. */
+	if (indefinite && !constructed) {
+		ASN1error(ASN1_R_BAD_OBJECT_HEADER);
+		return 0;
+	}
+
+	if (!indefinite && CBS_len(cbs) < length) {
+		ASN1error(ASN1_R_TOO_LONG);
+		return 0;
+	}
+
+	if (tag_number > INT_MAX) {
+		ASN1error(ASN1_R_TOO_LONG);
+		return 0;
+	}
+
+	if (indefinite)
+		length = CBS_len(cbs);
+
+	if (out_len != NULL)
+		*out_len = length;
+	if (out_tag != NULL)
+		*out_tag = tag_number;
+	if (out_class != NULL)
+		*out_class = tag_class << 6;
+	if (out_indefinite != NULL)
+		*out_indefinite = indefinite;
+	if (out_constructed != NULL)
+		*out_constructed = constructed;
+
+	return 1;
+}
+
+/* Collect the contents from a constructed ASN.1 object. */
+static int
+asn1_collect(CBB *cbb, CBS *cbs, int indefinite, int expected_tag,
+    int expected_class, int depth)
+{
+	int constructed;
+	size_t length;
+	CBS content;
+	int need_eoc;
+
+	if (depth > ASN1_MAX_STRING_NEST) {
+		ASN1error(ASN1_R_NESTED_ASN1_STRING);
+		return 0;
+	}
+
+	need_eoc = indefinite;
+
+	while (CBS_len(cbs) > 0) {
+		if (asn1_check_eoc(cbs)) {
+			if (!need_eoc) {
+				ASN1error(ASN1_R_UNEXPECTED_EOC);
+				return 0;
+			}
+			return 1;
+		}
+		if (!asn1_check_tag(cbs, &length, NULL, NULL, &indefinite,
+		    &constructed, expected_tag, expected_class, 0)) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			return 0;
+		}
+
+		if (constructed) {
+			if (!asn1_collect(cbb, cbs, indefinite, expected_tag,
+			    expected_class, depth + 1))
+				return 0;
+			continue;
+		}
+
+		if (!CBS_get_bytes(cbs, &content, length)) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			return 0;
+		}
+		if (!CBB_add_bytes(cbb, CBS_data(&content), CBS_len(&content)))
+			return 0;
+	}
+
+	if (need_eoc) {
+		ASN1error(ASN1_R_MISSING_EOC);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Find the end of an ASN.1 object. */
+static int
+asn1_find_end(CBS *cbs, size_t length, int indefinite)
+{
+	size_t eoc_count;
+
+	if (!indefinite) {
+		if (!CBS_skip(cbs, length)) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			return 0;
+		}
+		return 1;
+	}
+
+	eoc_count = 1;
+
+	while (CBS_len(cbs) > 0) {
+		if (asn1_check_eoc(cbs)) {
+			if (--eoc_count == 0)
+				break;
+			continue;
+		}
+		if (!asn1_check_tag(cbs, &length, NULL, NULL,
+		    &indefinite, NULL, -1, 0, 0)) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			return 0;
+		}
+		if (indefinite) {
+			eoc_count++;
+			continue;
+		}
+		if (!CBS_skip(cbs, length))
+			return 0;
+	}
+
+	if (eoc_count > 0) {
+		ASN1error(ASN1_R_MISSING_EOC);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+asn1_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it)
+{
+	ASN1_BOOLEAN *abool;
+	ASN1_STRING *astr;
+	uint8_t val;
+	int ret = 0;
+
+	if (it->funcs != NULL)
+		goto err;
+
+	if (CBS_len(content) > INT_MAX)
+		goto err;
+
+	switch (utype) {
+	case V_ASN1_OBJECT:
+		if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content))
+			goto err;
+		break;
+
+	case V_ASN1_NULL:
+		if (CBS_len(content) != 0) {
+			ASN1error(ASN1_R_NULL_IS_WRONG_LENGTH);
+			goto err;
+		}
+		*pval = (ASN1_VALUE *)1;
+		break;
+
+	case V_ASN1_BOOLEAN:
+		abool = (ASN1_BOOLEAN *)pval;
+		if (CBS_len(content) != 1) {
+			ASN1error(ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+			goto err;
+		}
+		if (!CBS_get_u8(content, &val))
+			goto err;
+		*abool = val;
+		break;
+
+	case V_ASN1_BIT_STRING:
+		if (!c2i_ASN1_BIT_STRING_cbs((ASN1_BIT_STRING **)pval, content))
+			goto err;
+		break;
+
+	case V_ASN1_ENUMERATED:
+		if (!c2i_ASN1_ENUMERATED_cbs((ASN1_ENUMERATED **)pval, content))
+			goto err;
+		break;
+
+	case V_ASN1_INTEGER:
+		if (!c2i_ASN1_INTEGER_cbs((ASN1_INTEGER **)pval, content))
+			goto err;
+		break;
+
+	case V_ASN1_OCTET_STRING:
+	case V_ASN1_NUMERICSTRING:
+	case V_ASN1_PRINTABLESTRING:
+	case V_ASN1_T61STRING:
+	case V_ASN1_VIDEOTEXSTRING:
+	case V_ASN1_IA5STRING:
+	case V_ASN1_UTCTIME:
+	case V_ASN1_GENERALIZEDTIME:
+	case V_ASN1_GRAPHICSTRING:
+	case V_ASN1_VISIBLESTRING:
+	case V_ASN1_GENERALSTRING:
+	case V_ASN1_UNIVERSALSTRING:
+	case V_ASN1_BMPSTRING:
+	case V_ASN1_UTF8STRING:
+	case V_ASN1_OTHER:
+	case V_ASN1_SET:
+	case V_ASN1_SEQUENCE:
+	default:
+		if (utype == V_ASN1_BMPSTRING && (CBS_len(content) & 1)) {
+			ASN1error(ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+			goto err;
+		}
+		if (utype == V_ASN1_UNIVERSALSTRING && (CBS_len(content) & 3)) {
+			ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+			goto err;
+		}
+		if (utype == V_ASN1_UTCTIME || utype == V_ASN1_GENERALIZEDTIME) {
+			if (!asn1_time_parse_cbs(content,
+			    utype == V_ASN1_GENERALIZEDTIME, NULL))  {
+				ASN1error(ASN1_R_INVALID_TIME_FORMAT);
+				goto err;
+			}
+		}
+		/* All based on ASN1_STRING and handled the same way. */
+		if (*pval != NULL) {
+			ASN1_STRING_free((ASN1_STRING *)*pval);
+			*pval = NULL;
+		}
+		if ((astr = ASN1_STRING_type_new(utype)) == NULL) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!ASN1_STRING_set(astr, CBS_data(content), CBS_len(content))) {
+			ASN1_STRING_free(astr);
+			goto err;
+		}
+		*pval = (ASN1_VALUE *)astr;
+		break;
+	}
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+static int
+asn1_c2i_any(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it)
+{
+	ASN1_TYPE *atype;
+
+	if (it->utype != V_ASN1_ANY || it->funcs != NULL)
+		return 0;
+
+	if (*pval != NULL) {
+		ASN1_TYPE_free((ASN1_TYPE *)*pval);
+		*pval = NULL;
+	}
+
+	if ((atype = ASN1_TYPE_new()) == NULL)
+		return 0;
+
+	if (!asn1_c2i_primitive(&atype->value.asn1_value, content, utype, it)) {
+		ASN1_TYPE_free(atype);
+		return 0;
+	}
+	atype->type = utype;
+
+	/* Fix up value for ASN.1 NULL. */
+	if (atype->type == V_ASN1_NULL)
+		atype->value.ptr = NULL;
+
+	*pval = (ASN1_VALUE *)atype;
+
+	return 1;
+}
+
+static int
+asn1_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it)
+{
+	if (CBS_len(content) > INT_MAX)
+		return 0;
+
+	if (it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+		char free_content = 0;
+
+		if (pf->prim_c2i == NULL)
+			return 0;
+
+		return pf->prim_c2i(pval, CBS_data(content), CBS_len(content),
+		    utype, &free_content, it);
+	}
+
+	if (it->utype == V_ASN1_ANY)
+		return asn1_c2i_any(pval, content, utype, it);
+
+	return asn1_c2i_primitive(pval, content, utype, it);
+}
+
+/*
+ * Decode ASN.1 content into a primitive type. There are three possible forms -
+ * a SEQUENCE/SET/OTHER that is stored verbatim (including the ASN.1 tag and
+ * length octets), constructed objects and non-constructed objects. In the
+ * first two cases indefinite length is permitted, which we may need to handle.
+ * When this function is called the *cbs should reference the start of the
+ * ASN.1 object (i.e. the tag/length header), while *cbs_object should
+ * reference the start of the object contents (i.e. after the tag/length
+ * header. Additionally, the *cbs_object offset should be relative to the
+ * ASN.1 object being parsed. On success the *cbs will point at the octet
+ * after the object.
+ */
+static int
+asn1_d2i_primitive_content(ASN1_VALUE **pval, CBS *cbs, CBS *cbs_object,
+    int utype, int constructed, int indefinite, size_t length,
+    const ASN1_ITEM *it)
+{
+	CBS cbs_content, cbs_initial;
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	CBB cbb;
+	int ret = 0;
+
+	memset(&cbb, 0, sizeof(cbb));
+
+	CBS_dup(cbs, &cbs_initial);
+	CBS_init(&cbs_content, NULL, 0);
+
+	if (asn1_must_be_constructed(utype) && !constructed) {
+		ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED);
+		goto err;
+	}
+	if (asn1_must_be_primitive(utype) && constructed) {
+		ASN1error(ASN1_R_TYPE_NOT_PRIMITIVE);
+		goto err;
+	}
+
+	/* SEQUENCE, SET and "OTHER" are left in encoded form. */
+	if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET ||
+	    utype == V_ASN1_OTHER) {
+		if (!asn1_find_end(cbs_object, length, indefinite))
+			goto err;
+		if (!CBS_get_bytes(&cbs_initial, &cbs_content,
+		    CBS_offset(cbs_object)))
+			goto err;
+	} else if (constructed) {
+		/*
+		 * Should really check the internal tags are correct but
+		 * some things may get this wrong. The relevant specs
+		 * say that constructed string types should be OCTET STRINGs
+		 * internally irrespective of the type. So instead just check
+		 * for UNIVERSAL class and ignore the tag.
+		 */
+		if (!CBB_init(&cbb, 0))
+			goto err;
+		if (!asn1_collect(&cbb, cbs_object, indefinite, -1,
+		    V_ASN1_UNIVERSAL, 0))
+			goto err;
+		if (!CBB_finish(&cbb, &data, &data_len))
+			goto err;
+
+		CBS_init(&cbs_content, data, data_len);
+	} else {
+		if (!CBS_get_bytes(cbs_object, &cbs_content, length))
+			goto err;
+	}
+
+	if (!asn1_c2i(pval, &cbs_content, utype, it))
+		goto err;
+
+	if (!CBS_skip(cbs, CBS_offset(cbs_object)))
+		goto err;
+
+	ret = 1;
+
+ err:
+	CBB_cleanup(&cbb);
+	freezero(data, data_len);
+
+	return ret;
+}
+
+static int
+asn1_d2i_any(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional)
+{
+	int constructed, indefinite;
+	uint8_t object_class;
+	int object_type;
+	CBS cbs_object;
+	size_t length;
+
+	CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs));
+
+	if (it->utype != V_ASN1_ANY)
+		return 0;
+
+	if (tag_number >= 0) {
+		ASN1error(ASN1_R_ILLEGAL_TAGGED_ANY);
+		return 0;
+	}
+	if (optional) {
+		ASN1error(ASN1_R_ILLEGAL_OPTIONAL_ANY);
+		return 0;
+	}
+
+	/* Determine type from ASN.1 tag. */
+	if (asn1_check_tag(&cbs_object, &length, &object_type, &object_class,
+	    &indefinite, &constructed, -1, 0, 0) != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+	if (object_class != V_ASN1_UNIVERSAL)
+		object_type = V_ASN1_OTHER;
+
+	return asn1_d2i_primitive_content(pval, cbs, &cbs_object, object_type,
+	    constructed, indefinite, length, it);
+}
+
+static int
+asn1_d2i_mstring(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional)
+{
+	int constructed, indefinite;
+	uint8_t object_class;
+	int object_tag;
+	CBS cbs_object;
+	size_t length;
+
+	CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs));
+
+	/*
+	 * It never makes sense for multi-strings to have implicit tagging, so
+	 * if tag_number != -1, then this looks like an error in the template.
+	 */
+	if (tag_number != -1) {
+		ASN1error(ASN1_R_BAD_TEMPLATE);
+		return 0;
+	}
+
+	if (asn1_check_tag(&cbs_object, &length, &object_tag, &object_class,
+	    &indefinite, &constructed, -1, 0, 1) != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+
+	/* Class must be UNIVERSAL. */
+	if (object_class != V_ASN1_UNIVERSAL) {
+		if (optional)
+			return -1;
+		ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL);
+		return 0;
+	}
+	/* Check tag matches bit map. */
+	if ((ASN1_tag2bit(object_tag) & it->utype) == 0) {
+		if (optional)
+			return -1;
+		ASN1error(ASN1_R_MSTRING_WRONG_TAG);
+		return 0;
+	}
+
+	return asn1_d2i_primitive_content(pval, cbs, &cbs_object,
+	    object_tag, constructed, indefinite, length, it);
+}
+
+static int
+asn1_d2i_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional)
+{
+	CBS cbs_object;
+	int constructed, indefinite;
+	int utype = it->utype;
+	size_t length;
+	int ret;
+
+	CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs));
+
+	if (it->itype == ASN1_ITYPE_MSTRING)
+		return 0;
+
+	if (it->utype == V_ASN1_ANY)
+		return asn1_d2i_any(pval, cbs, it, tag_number, tag_class, optional);
+
+	if (tag_number == -1) {
+		tag_number = it->utype;
+		tag_class = V_ASN1_UNIVERSAL;
+	}
+
+	ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite,
+	    &constructed, tag_number, tag_class, optional);
+	if (ret == -1)
+		return -1;
+	if (ret != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+
+	return asn1_d2i_primitive_content(pval, cbs, &cbs_object, utype,
+	    constructed, indefinite, length, it);
+}
+
+static int
+asn1_item_d2i_choice(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional, int depth)
+{
+	const ASN1_TEMPLATE *at, *errat = NULL;
+	const ASN1_AUX *aux;
+	ASN1_aux_cb *asn1_cb = NULL;
+	ASN1_VALUE *achoice = NULL;
+	ASN1_VALUE **pchptr;
+	int i, ret;
+
+	if ((aux = it->funcs) != NULL)
+		asn1_cb = aux->asn1_cb;
+
+	if (it->itype != ASN1_ITYPE_CHOICE)
+		goto err;
+
+	/*
+	 * It never makes sense for CHOICE types to have implicit tagging, so
+	 * if tag_number != -1, then this looks like an error in the template.
+	 */
+	if (tag_number != -1) {
+		ASN1error(ASN1_R_BAD_TEMPLATE);
+		goto err;
+	}
+
+	if (*pval != NULL) {
+		ASN1_item_ex_free(pval, it);
+		*pval = NULL;
+	}
+
+	if (!ASN1_item_ex_new(&achoice, it)) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+
+	if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_PRE, &achoice, it, NULL)) {
+		ASN1error(ASN1_R_AUX_ERROR);
+		goto err;
+	}
+
+	/* Try each possible CHOICE in turn. */
+	for (i = 0; i < it->tcount; i++) {
+		at = &it->templates[i];
+
+		pchptr = asn1_get_field_ptr(&achoice, at);
+
+		/* Mark field as OPTIONAL so its absence can be identified. */
+		ret = asn1_template_d2i(pchptr, cbs, at, 1, depth);
+		if (ret == -1)
+			continue;
+		if (ret != 1) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			errat = at;
+			goto err;
+		}
+
+		/* We've successfully decoded an ASN.1 object. */
+		asn1_set_choice_selector(&achoice, i, it);
+		break;
+	}
+
+	/* Did we fall off the end without reading anything? */
+	if (i == it->tcount) {
+		if (optional) {
+			ASN1_item_ex_free(&achoice, it);
+			return -1;
+		}
+		ASN1error(ASN1_R_NO_MATCHING_CHOICE_TYPE);
+		goto err;
+	}
+
+	if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_POST, &achoice, it, NULL)) {
+		ASN1error(ASN1_R_AUX_ERROR);
+		goto err;
+	}
+
+	*pval = achoice;
+	achoice = NULL;
+
+	return 1;
+
+ err:
+	ASN1_item_ex_free(&achoice, it);
+
+	if (errat != NULL)
+		ERR_asprintf_error_data("Field=%s, Type=%s", errat->field_name,
+		    it->sname);
+	else
+		ERR_asprintf_error_data("Type=%s", it->sname);
+
+	return 0;
+}
+
+static int
+asn1_item_d2i_sequence(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional, int depth)
+{
+	CBS cbs_seq, cbs_seq_content, cbs_object;
+	int constructed, indefinite, optional_field;
+	const ASN1_TEMPLATE *errat = NULL;
+	const ASN1_TEMPLATE *seqat, *at;
+	ASN1_aux_cb *asn1_cb = NULL;
+	const ASN1_AUX *aux;
+	ASN1_VALUE *aseq = NULL;
+	ASN1_VALUE **pseqval;
+	int eoc_needed, i;
+	size_t length;
+	int ret = 0;
+
+	CBS_init(&cbs_seq, CBS_data(cbs), CBS_len(cbs));
+
+	if ((aux = it->funcs) != NULL)
+		asn1_cb = aux->asn1_cb;
+
+	if (it->itype != ASN1_ITYPE_NDEF_SEQUENCE &&
+	    it->itype != ASN1_ITYPE_SEQUENCE)
+		goto err;
+
+	if (*pval != NULL) {
+		ASN1_item_ex_free(pval, it);
+		*pval = NULL;
+	}
+
+	/* If no IMPLICIT tagging use UNIVERSAL/SEQUENCE. */
+	if (tag_number == -1) {
+		tag_class = V_ASN1_UNIVERSAL;
+		tag_number = V_ASN1_SEQUENCE;
+	}
+
+	/* Read ASN.1 SEQUENCE header. */
+	ret = asn1_check_tag(&cbs_seq, &length, NULL, NULL, &indefinite,
+	    &constructed, tag_number, tag_class, optional);
+	if (ret == -1)
+		return -1;
+	if (ret != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+
+	if (!constructed) {
+		ASN1error(ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+		goto err;
+	}
+
+	if (indefinite) {
+		eoc_needed = 1;
+		CBS_init(&cbs_seq_content, CBS_data(&cbs_seq), CBS_len(&cbs_seq));
+	} else {
+		eoc_needed = 0;
+		if (!CBS_get_bytes(&cbs_seq, &cbs_seq_content, length))
+			goto err;
+	}
+
+	if (!ASN1_item_ex_new(&aseq, it)) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+
+	if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_PRE, &aseq, it, NULL)) {
+		ASN1error(ASN1_R_AUX_ERROR);
+		goto err;
+	}
+
+	for (i = 0; i < it->tcount; i++) {
+		at = &it->templates[i];
+
+		if (asn1_check_eoc(&cbs_seq_content)) {
+			if (!indefinite) {
+				ASN1error(ASN1_R_UNEXPECTED_EOC);
+				goto err;
+			}
+			eoc_needed = 0;
+			break;
+		}
+		if (CBS_len(&cbs_seq_content) == 0)
+			break;
+
+		if ((seqat = asn1_do_adb(&aseq, at, 1)) == NULL)
+			goto err;
+
+		pseqval = asn1_get_field_ptr(&aseq, seqat);
+
+		/*
+		 * This was originally implemented to "increase efficiency",
+		 * however it currently needs to remain since it papers over
+		 * the use of ASN.1 ANY with OPTIONAL in SEQUENCEs (which
+		 * asn1_d2i_primitive() currently rejects).
+		 */
+		optional_field = (seqat->flags & ASN1_TFLG_OPTIONAL) != 0;
+		if (i == it->tcount - 1)
+			optional_field = 0;
+
+		ret = asn1_template_d2i(pseqval, &cbs_seq_content,
+		    seqat, optional_field, depth);
+		if (ret == -1) {
+			/* Absent OPTIONAL component. */
+			ASN1_template_free(pseqval, seqat);
+			continue;
+		}
+		if (ret != 1) {
+			errat = seqat;
+			goto err;
+		}
+	}
+
+	if (eoc_needed && !asn1_check_eoc(&cbs_seq_content)) {
+		ASN1error(ASN1_R_MISSING_EOC);
+		goto err;
+	}
+
+	if (indefinite) {
+		if (!CBS_skip(&cbs_seq, CBS_offset(&cbs_seq_content)))
+			goto err;
+	} else if (CBS_len(&cbs_seq_content) != 0) {
+		ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+		goto err;
+	}
+
+	/*
+	 * There is no more data in the ASN.1 SEQUENCE, however we may not have
+	 * populated all fields - check that any remaining are OPTIONAL.
+	 */
+	for (; i < it->tcount; i++) {
+		at = &it->templates[i];
+
+		if ((seqat = asn1_do_adb(&aseq, at, 1)) == NULL)
+			goto err;
+
+		if ((seqat->flags & ASN1_TFLG_OPTIONAL) == 0) {
+			ASN1error(ASN1_R_FIELD_MISSING);
+			errat = seqat;
+			goto err;
+		}
+
+		/* XXX - this is probably unnecessary with earlier free. */
+		pseqval = asn1_get_field_ptr(&aseq, seqat);
+		ASN1_template_free(pseqval, seqat);
+	}
+
+	if (!CBS_get_bytes(cbs, &cbs_object, CBS_offset(&cbs_seq)))
+		goto err;
+
+	if (!asn1_enc_save(&aseq, &cbs_object, it)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (asn1_cb != NULL && !asn1_cb(ASN1_OP_D2I_POST, &aseq, it, NULL)) {
+		ASN1error(ASN1_R_AUX_ERROR);
+		goto err;
+	}
+
+	*pval = aseq;
+	aseq = NULL;
+
+	return 1;
+
+ err:
+	ASN1_item_ex_free(&aseq, it);
+
+	if (errat != NULL)
+		ERR_asprintf_error_data("Field=%s, Type=%s", errat->field_name,
+		    it->sname);
+	else
+		ERR_asprintf_error_data("Type=%s", it->sname);
+
+	return 0;
+}
+
+static int
+asn1_item_d2i_extern(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional)
+{
+	const ASN1_EXTERN_FUNCS *ef = it->funcs;
+	const unsigned char *p = NULL;
+	ASN1_TLC ctx = { 0 };
+	int ret = 0;
+
+	if (CBS_len(cbs) > LONG_MAX)
+		return 0;
+
+	p = CBS_data(cbs);
+
+	if ((ret = ef->asn1_ex_d2i(pval, &p, (long)CBS_len(cbs), it,
+	    tag_number, tag_class, optional, &ctx)) == 1) {
+		if (!CBS_skip(cbs, p - CBS_data(cbs)))
+			goto err;
+	}
+	return ret;
+
+ err:
+	ASN1_item_ex_free(pval, it);
+
+	ERR_asprintf_error_data("Type=%s", it->sname);
+
+	return 0;
+}
+
+static int
+asn1_item_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it,
+    int tag_number, int tag_class, int optional, int depth)
+{
+	if (pval == NULL)
+		return 0;
+
+	if (++depth > ASN1_MAX_CONSTRUCTED_NEST) {
+		ASN1error(ASN1_R_NESTED_TOO_DEEP);
+		goto err;
+	}
+
+	switch (it->itype) {
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates != NULL) {
+			/*
+			 * Tagging or OPTIONAL is currently illegal on an item
+			 * template because the flags can't get passed down.
+			 * In practice this isn't a problem: we include the
+			 * relevant flags from the item template in the
+			 * template itself.
+			 */
+			if (tag_number != -1 || optional) {
+				ASN1error(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+				goto err;
+			}
+			return asn1_template_d2i(pval, cbs, it->templates,
+			    optional, depth);
+		}
+		return asn1_d2i_primitive(pval, cbs, it, tag_number, tag_class,
+		    optional);
+
+	case ASN1_ITYPE_MSTRING:
+		return asn1_d2i_mstring(pval, cbs, it, tag_number, tag_class,
+		    optional);
+
+	case ASN1_ITYPE_EXTERN:
+		return asn1_item_d2i_extern(pval, cbs, it, tag_number,
+		    tag_class, optional);
+
+	case ASN1_ITYPE_CHOICE:
+		return asn1_item_d2i_choice(pval, cbs, it, tag_number,
+		    tag_class, optional, depth);
+
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+	case ASN1_ITYPE_SEQUENCE:
+		return asn1_item_d2i_sequence(pval, cbs, it, tag_number,
+		    tag_class, optional, depth);
+
+	default:
+		return 0;
+	}
+
+ err:
+	ASN1_item_ex_free(pval, it);
+
+	ERR_asprintf_error_data("Type=%s", it->sname);
+
+	return 0;
+}
+
+static void
+asn1_template_stack_of_free(STACK_OF(ASN1_VALUE) *avals,
+    const ASN1_TEMPLATE *at)
+{
+	ASN1_VALUE *aval;
+
+	if (avals == NULL)
+		return;
+
+	while (sk_ASN1_VALUE_num(avals) > 0) {
+		aval = sk_ASN1_VALUE_pop(avals);
+		ASN1_item_ex_free(&aval, at->item);
+	}
+	sk_ASN1_VALUE_free(avals);
+}
+
+static int
+asn1_template_stack_of_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *at,
+    int optional, int depth)
+{
+	CBS cbs_object, cbs_object_content;
+	STACK_OF(ASN1_VALUE) *avals = NULL;
+	ASN1_VALUE *aval = NULL;
+	int tag_number, tag_class;
+	int eoc_needed;
+	int indefinite;
+	size_t length;
+	int ret;
+
+	CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs));
+
+	if (pval == NULL)
+		return 0;
+
+	asn1_template_stack_of_free((STACK_OF(ASN1_VALUE) *)*pval, at);
+	*pval = NULL;
+
+	tag_number = at->tag;
+	tag_class = at->flags & ASN1_TFLG_TAG_CLASS;
+
+	/* Determine the inner tag value for SET OF or SEQUENCE OF. */
+	if ((at->flags & ASN1_TFLG_IMPTAG) == 0) {
+		tag_number = V_ASN1_SEQUENCE;
+		tag_class = V_ASN1_UNIVERSAL;
+		if ((at->flags & ASN1_TFLG_SET_OF) != 0)
+			tag_number = V_ASN1_SET;
+	}
+
+	ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite,
+	    NULL, tag_number, tag_class, optional);
+	if (ret == -1)
+		return -1;
+	if (ret != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+
+	if (indefinite) {
+		eoc_needed = 1;
+		CBS_init(&cbs_object_content, CBS_data(&cbs_object),
+		    CBS_len(&cbs_object));
+	} else {
+		eoc_needed = 0;
+		if (!CBS_get_bytes(&cbs_object, &cbs_object_content,
+		    length))
+			goto err;
+	}
+
+	if ((avals = sk_ASN1_VALUE_new_null()) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* Read as many items as possible. */
+	while (CBS_len(&cbs_object_content) > 0) {
+		if (asn1_check_eoc(&cbs_object_content)) {
+			if (!eoc_needed) {
+				ASN1error(ASN1_R_UNEXPECTED_EOC);
+				goto err;
+			}
+			eoc_needed = 0;
+			break;
+		}
+		if (!asn1_item_d2i(&aval, &cbs_object_content, at->item, -1, 0,
+		    0, depth)) {
+			ASN1error(ERR_R_NESTED_ASN1_ERROR);
+			goto err;
+		}
+		if (!sk_ASN1_VALUE_push(avals, aval)) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		aval = NULL;
+	}
+	if (eoc_needed) {
+		ASN1error(ASN1_R_MISSING_EOC);
+		goto err;
+	}
+
+	if (indefinite) {
+		if (!CBS_skip(&cbs_object, CBS_offset(&cbs_object_content)))
+			goto err;
+	}
+
+	if (!CBS_skip(cbs, CBS_offset(&cbs_object)))
+		goto err;
+
+	*pval = (ASN1_VALUE *)avals;
+	avals = NULL;
+
+	return 1;
+
+ err:
+	asn1_template_stack_of_free(avals, at);
+	ASN1_item_ex_free(&aval, at->item);
+
+	return 0;
+}
+
+static int
+asn1_template_noexp_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *at,
+    int optional, int depth)
+{
+	int tag_number, tag_class;
+	int ret;
+
+	if (pval == NULL)
+		return 0;
+
+	if ((at->flags & ASN1_TFLG_SK_MASK) != 0)
+		return asn1_template_stack_of_d2i(pval, cbs, at, optional, depth);
+
+	tag_number = -1;
+	tag_class = V_ASN1_UNIVERSAL;
+
+	/* See if we need to use IMPLICIT tagging. */
+	if ((at->flags & ASN1_TFLG_IMPTAG) != 0) {
+		tag_number = at->tag;
+		tag_class = at->flags & ASN1_TFLG_TAG_CLASS;
+	}
+
+	ret = asn1_item_d2i(pval, cbs, at->item, tag_number, tag_class,
+	    optional, depth);
+	if (ret == -1)
+		return -1;
+	if (ret != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		goto err;
+	}
+
+	return 1;
+
+ err:
+	/* XXX - The called function should have freed already. */
+	ASN1_template_free(pval, at);
+	return 0;
+}
+
+static int
+asn1_template_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *at,
+    int optional, int depth)
+{
+	CBS cbs_exp, cbs_exp_content;
+	int constructed, indefinite;
+	size_t length;
+	int ret;
+
+	if (pval == NULL)
+		return 0;
+
+	/* Check if EXPLICIT tag is expected. */
+	if ((at->flags & ASN1_TFLG_EXPTAG) == 0)
+		return asn1_template_noexp_d2i(pval, cbs, at, optional, depth);
+
+	CBS_init(&cbs_exp, CBS_data(cbs), CBS_len(cbs));
+
+	/* Read ASN.1 header for EXPLICIT tagged object. */
+	ret = asn1_check_tag(&cbs_exp, &length, NULL, NULL, &indefinite,
+	    &constructed, at->tag, at->flags & ASN1_TFLG_TAG_CLASS, optional);
+	if (ret == -1)
+		return -1;
+	if (ret != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+
+	if (!constructed) {
+		ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+		return 0;
+	}
+
+	if (indefinite) {
+		CBS_init(&cbs_exp_content, CBS_data(&cbs_exp), CBS_len(&cbs_exp));
+	} else {
+		if (!CBS_get_bytes(&cbs_exp, &cbs_exp_content, length))
+			goto err;
+	}
+
+	if ((ret = asn1_template_noexp_d2i(pval, &cbs_exp_content, at, 0,
+	    depth)) != 1) {
+		ASN1error(ERR_R_NESTED_ASN1_ERROR);
+		return 0;
+	}
+
+	if (indefinite) {
+		if (!asn1_check_eoc(&cbs_exp_content)) {
+			ASN1error(ASN1_R_MISSING_EOC);
+			goto err;
+		}
+		if (!CBS_skip(&cbs_exp, CBS_offset(&cbs_exp_content)))
+			goto err;
+	} else if (CBS_len(&cbs_exp_content) != 0) {
+		ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+		goto err;
+	}
+
+	if (!CBS_skip(cbs, CBS_offset(&cbs_exp)))
+		goto err;
+
+	return 1;
+
+ err:
+	ASN1_template_free(pval, at);
+	return 0;
+}
+
+ASN1_VALUE *
+ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen,
+    const ASN1_ITEM *it)
+{
+	ASN1_VALUE *ptmpval = NULL;
+
+	if (pval == NULL)
+		pval = &ptmpval;
+	if (ASN1_item_ex_d2i(pval, in, inlen, it, -1, 0, 0, NULL) <= 0)
+		return NULL;
+
+	return *pval;
+}
+LCRYPTO_ALIAS(ASN1_item_d2i);
+
+int
+ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen,
+    const ASN1_ITEM *it, int tag_number, int tag_class, char optional,
+    ASN1_TLC *ctx)
+{
+	CBS cbs;
+	int ret;
+
+	if (inlen < 0)
+		return 0;
+
+	CBS_init(&cbs, *in, inlen);
+	if ((ret = asn1_item_d2i(pval, &cbs, it, tag_number, tag_class,
+	    (int)optional, 0)) == 1)
+		*in = CBS_data(&cbs);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ASN1_item_ex_d2i);
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
new file mode 100644
index 0000000..b71993a
--- /dev/null
+++ b/crypto/asn1/tasn_enc.c
@@ -0,0 +1,682 @@
+/* $OpenBSD: tasn_enc.c,v 1.33 2023/07/28 10:00:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+static int asn1_i2d_ex_primitive(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,
+    int skcontlen, const ASN1_ITEM *item, int do_sort, int iclass);
+static int asn1_template_ex_i2d(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,
+    const ASN1_ITEM *it, int flags);
+static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+    const ASN1_ITEM *it);
+
+/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
+ * to use indefinite length constructed encoding, where appropriate
+ */
+
+int
+ASN1_item_ndef_i2d(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)
+{
+	return asn1_item_flags_i2d(val, out, it, 0);
+}
+LCRYPTO_ALIAS(ASN1_item_i2d);
+
+/* Encode an ASN1 item, this is use by the
+ * standard 'i2d' function. 'out' points to
+ * a buffer to output the data to.
+ *
+ * The new i2d has one additional feature. If the output
+ * buffer is NULL (i.e. *out == NULL) then a buffer is
+ * allocated and populated with the encoding.
+ */
+
+static int
+asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it,
+    int flags)
+{
+	unsigned char *p, *buf;
+	int len;
+
+	if (out == NULL || *out != NULL)
+		return ASN1_item_ex_i2d(&val, out, it, -1, flags);
+
+	if ((len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags)) <= 0)
+		return len;
+
+	if ((buf = calloc(1, len)) == NULL)
+		return -1;
+
+	p = buf;
+	if (ASN1_item_ex_i2d(&val, &p, it, -1, flags) != len) {
+		freezero(buf, len);
+		ASN1error(ASN1_R_LENGTH_ERROR);
+		return -1;
+	}
+
+	*out = buf;
+
+	return len;
+}
+
+/* Encode an item, taking care of IMPLICIT tagging (if any).
+ * This function performs the normal item handling: it can be
+ * used in external types.
+ */
+
+int
+ASN1_item_ex_i2d(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 = NULL;
+
+	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+		return 0;
+
+	if (aux && aux->asn1_cb)
+		asn1_cb = aux->asn1_cb;
+
+	switch (it->itype) {
+
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates)
+			return asn1_template_ex_i2d(pval, out, it->templates,
+			    tag, aclass);
+		return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
+		break;
+
+	case ASN1_ITYPE_MSTRING:
+		/*
+		 * It never makes sense for multi-strings to have implicit
+		 * tagging, so if tag != -1, then this looks like an error in
+		 * the template.
+		 */
+		if (tag != -1) {
+			ASN1error(ASN1_R_BAD_TEMPLATE);
+			return 0;
+		}
+		return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
+
+	case ASN1_ITYPE_CHOICE:
+		/*
+		 * It never makes sense for CHOICE types to have implicit
+		 * tagging, so if tag != -1, then this looks like an error in
+		 * the template.
+		 */
+		if (tag != -1) {
+			ASN1error(ASN1_R_BAD_TEMPLATE);
+			return 0;
+		}
+		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+			return 0;
+		i = asn1_get_choice_selector(pval, it);
+		if ((i >= 0) && (i < it->tcount)) {
+			ASN1_VALUE **pchval;
+			const ASN1_TEMPLATE *chtt;
+			chtt = it->templates + i;
+			pchval = asn1_get_field_ptr(pval, chtt);
+			return asn1_template_ex_i2d(pchval, out, chtt,
+			    -1, aclass);
+		}
+		/* Fixme: error condition if selector out of range */
+		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+			return 0;
+		break;
+
+	case ASN1_ITYPE_EXTERN:
+		/* If new style i2d it does all the work */
+		ef = it->funcs;
+		return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
+
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+		/* Use indefinite length constructed if requested */
+		if (aclass & ASN1_TFLG_NDEF)
+			ndef = 2;
+		/* fall through */
+
+	case ASN1_ITYPE_SEQUENCE:
+		i = asn1_enc_restore(&seqcontlen, out, pval, it);
+		/* An error occurred */
+		if (i < 0)
+			return 0;
+		/* We have a valid cached encoding... */
+		if (i > 0)
+			return seqcontlen;
+		/* Otherwise carry on */
+		seqcontlen = 0;
+		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+		if (tag == -1) {
+			tag = V_ASN1_SEQUENCE;
+			/* Retain any other flags in aclass */
+			aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) |
+			    V_ASN1_UNIVERSAL;
+		}
+		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+			return 0;
+		/* First work out sequence content length */
+		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);
+			if (!seqtt)
+				return 0;
+			pseqval = asn1_get_field_ptr(pval, seqtt);
+			/* FIXME: check for errors in enhanced version */
+			seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
+			    -1, aclass);
+		}
+
+		seqlen = ASN1_object_size(ndef, seqcontlen, tag);
+		if (!out)
+			return seqlen;
+		/* Output SEQUENCE header */
+		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);
+			if (!seqtt)
+				return 0;
+			pseqval = asn1_get_field_ptr(pval, seqtt);
+			/* FIXME: check for errors in enhanced version */
+			asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
+		}
+		if (ndef == 2)
+			ASN1_put_eoc(out);
+		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+			return 0;
+		return seqlen;
+
+	default:
+		return 0;
+
+	}
+	return 0;
+}
+LCRYPTO_ALIAS(ASN1_item_ex_i2d);
+
+static int
+asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
+    const ASN1_TEMPLATE *tt, int tag, int iclass)
+{
+	int i, ret, flags, ttag, tclass, ndef;
+	flags = tt->flags;
+	/* Work out tag and class to use: tagging may come
+	 * either from the template or the arguments, not both
+	 * because this would create ambiguity. Additionally
+	 * the iclass argument may contain some additional flags
+	 * which should be noted and passed down to other levels.
+	 */
+	if (flags & ASN1_TFLG_TAG_MASK) {
+		/* Error if argument and template tagging */
+		if (tag != -1)
+			/* FIXME: error code here */
+			return -1;
+		/* Get tagging from template */
+		ttag = tt->tag;
+		tclass = flags & ASN1_TFLG_TAG_CLASS;
+	} else if (tag != -1) {
+		/* No template tagging, get from arguments */
+		ttag = tag;
+		tclass = iclass & ASN1_TFLG_TAG_CLASS;
+	} else {
+		ttag = -1;
+		tclass = 0;
+	}
+	/*
+	 * Remove any class mask from iflag.
+	 */
+	iclass &= ~ASN1_TFLG_TAG_CLASS;
+
+	/* At this point 'ttag' contains the outer tag to use,
+	 * 'tclass' is the class and iclass is any flags passed
+	 * to this function.
+	 */
+
+	/* if template and arguments require ndef, use it */
+	if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
+		ndef = 2;
+	else
+		ndef = 1;
+
+	if (flags & ASN1_TFLG_SK_MASK) {
+		/* SET OF, SEQUENCE OF */
+		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+		int isset, sktag, skaclass;
+		int skcontlen, sklen;
+		ASN1_VALUE *skitem;
+
+		if (!*pval)
+			return 0;
+
+		if (flags & ASN1_TFLG_SET_OF) {
+			isset = 1;
+			/* 2 means we reorder */
+			if (flags & ASN1_TFLG_SEQUENCE_OF)
+				isset = 2;
+		} else
+			isset = 0;
+
+		/* Work out inner tag value: if EXPLICIT
+		 * or no tagging use underlying type.
+		 */
+		if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
+			sktag = ttag;
+			skaclass = tclass;
+		} else {
+			skaclass = V_ASN1_UNIVERSAL;
+			if (isset)
+				sktag = V_ASN1_SET;
+			else
+				sktag = V_ASN1_SEQUENCE;
+		}
+
+		/* Determine total length of items */
+		skcontlen = 0;
+		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+			skitem = sk_ASN1_VALUE_value(sk, i);
+			skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
+			    tt->item, -1, iclass);
+		}
+		sklen = ASN1_object_size(ndef, skcontlen, sktag);
+		/* If EXPLICIT need length of surrounding tag */
+		if (flags & ASN1_TFLG_EXPTAG)
+			ret = ASN1_object_size(ndef, sklen, ttag);
+		else
+			ret = sklen;
+
+		if (!out)
+			return ret;
+
+		/* Now encode this lot... */
+		/* EXPLICIT tag */
+		if (flags & ASN1_TFLG_EXPTAG)
+			ASN1_put_object(out, ndef, sklen, ttag, tclass);
+		/* SET or SEQUENCE and IMPLICIT tag */
+		ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
+		/* And the stuff itself */
+		asn1_set_seq_out(sk, out, skcontlen, tt->item,
+		    isset, iclass);
+		if (ndef == 2) {
+			ASN1_put_eoc(out);
+			if (flags & ASN1_TFLG_EXPTAG)
+				ASN1_put_eoc(out);
+		}
+
+		return ret;
+	}
+
+	if (flags & ASN1_TFLG_EXPTAG) {
+		/* EXPLICIT tagging */
+		/* Find length of tagged item */
+		i = ASN1_item_ex_i2d(pval, NULL, tt->item,
+		    -1, iclass);
+		if (!i)
+			return 0;
+		/* Find length of EXPLICIT tag */
+		ret = ASN1_object_size(ndef, i, ttag);
+		if (out) {
+			/* Output tag and item */
+			ASN1_put_object(out, ndef, i, ttag, tclass);
+			ASN1_item_ex_i2d(pval, out, tt->item,
+			    -1, iclass);
+			if (ndef == 2)
+				ASN1_put_eoc(out);
+		}
+		return ret;
+	}
+
+	/* Either normal or IMPLICIT tagging: combine class and flags */
+	return ASN1_item_ex_i2d(pval, out, tt->item,
+	    ttag, tclass | iclass);
+}
+
+/* Temporary structure used to hold DER encoding of items for SET OF */
+
+typedef	struct {
+	unsigned char *data;
+	int length;
+	ASN1_VALUE *field;
+} DER_ENC;
+
+static int
+der_cmp(const void *a, const void *b)
+{
+	const DER_ENC *d1 = a, *d2 = b;
+	int cmplen, i;
+
+	cmplen = (d1->length < d2->length) ? d1->length : d2->length;
+	i = memcmp(d1->data, d2->data, cmplen);
+	if (i)
+		return i;
+	return d1->length - d2->length;
+}
+
+/* Output the content octets of SET OF or SEQUENCE OF */
+
+static int
+asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen,
+    const ASN1_ITEM *item, int do_sort, int iclass)
+{
+	int i;
+	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)
+			do_sort = 0;
+		else {
+			derlst = reallocarray(NULL, sk_ASN1_VALUE_num(sk),
+			    sizeof(*derlst));
+			tmpdat = malloc(skcontlen);
+			if (!derlst || !tmpdat) {
+				free(derlst);
+				free(tmpdat);
+				return 0;
+			}
+		}
+	}
+	/* 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);
+			ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
+		}
+		return 1;
+	}
+	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);
+		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);
+	/* Output sorted DER encoding */
+	p = *out;
+	for (i = 0, tder = derlst; i < sk_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);
+	}
+	free(derlst);
+	free(tmpdat);
+	return 1;
+}
+
+static int
+asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
+    const ASN1_ITEM *it, int tag, int aclass)
+{
+	int olen, len;
+	int utype;
+	int usetag;
+	int ndef = 0;
+
+	utype = it->utype;
+
+	/* Get length of content octets and maybe find
+	 * out the underlying type.
+	 */
+
+	olen = len = asn1_ex_i2c(pval, NULL, &utype, it);
+
+	/* If SEQUENCE, SET or OTHER then header is
+	 * included in pseudo content octets so don't
+	 * include tag+length. We need to check here
+	 * because the call to asn1_ex_i2c() could change
+	 * utype.
+	 */
+	if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
+	    (utype == V_ASN1_OTHER))
+		usetag = 0;
+	else
+		usetag = 1;
+
+	/* -1 means omit type */
+	if (len == -1)
+		return 0;
+
+	/* -2 return is special meaning use ndef */
+	if (len == -2) {
+		ndef = 2;
+		len = 0;
+	}
+
+	/* Treat any other negative value as an error. */
+	if (len < 0)
+		return -1;
+
+	/* If not implicitly tagged get tag from underlying type */
+	if (tag == -1)
+		tag = utype;
+
+	/* Output tag+length followed by content octets */
+	if (out) {
+		if (usetag)
+			ASN1_put_object(out, ndef, len, tag, aclass);
+		if (asn1_ex_i2c(pval, *out, &utype, it) != olen)
+			return -1;
+		if (ndef)
+			ASN1_put_eoc(out);
+		else
+			*out += len;
+	}
+
+	if (usetag)
+		return ASN1_object_size(ndef, len, tag);
+	return len;
+}
+
+/* Produce content octets from a structure */
+
+static int
+asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
+    const ASN1_ITEM *it)
+{
+	ASN1_BOOLEAN *tbool = NULL;
+	ASN1_STRING *strtmp;
+	ASN1_OBJECT *otmp;
+	int utype;
+	const unsigned char *cont;
+	unsigned char c;
+	int len;
+
+	if (it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+
+		if (pf->prim_i2c == NULL)
+			return -1;
+		return pf->prim_i2c(pval, cout, putype, it);
+	}
+
+	/* Should type be omitted? */
+	if ((it->itype != ASN1_ITYPE_PRIMITIVE) ||
+	    (it->utype != V_ASN1_BOOLEAN)) {
+		if (!*pval)
+			return -1;
+	}
+
+	if (it->itype == ASN1_ITYPE_MSTRING) {
+		/* If MSTRING type set the underlying type */
+		strtmp = (ASN1_STRING *)*pval;
+		utype = strtmp->type;
+		*putype = utype;
+	} else if (it->utype == V_ASN1_ANY) {
+		/* If ANY set type and pointer to value */
+		ASN1_TYPE *typ;
+		typ = (ASN1_TYPE *)*pval;
+		utype = typ->type;
+		*putype = utype;
+		pval = &typ->value.asn1_value;
+	} else
+		utype = *putype;
+
+	switch (utype) {
+	case V_ASN1_OBJECT:
+		otmp = (ASN1_OBJECT *)*pval;
+		cont = otmp->data;
+		len = otmp->length;
+		break;
+
+	case V_ASN1_NULL:
+		cont = NULL;
+		len = 0;
+		break;
+
+	case V_ASN1_BOOLEAN:
+		tbool = (ASN1_BOOLEAN *)pval;
+		if (*tbool == -1)
+			return -1;
+		if (it->utype != V_ASN1_ANY) {
+			/* Default handling if value == size field then omit */
+			if (*tbool && (it->size > 0))
+				return -1;
+			if (!*tbool && !it->size)
+				return -1;
+		}
+		c = (unsigned char)*tbool;
+		cont = &c;
+		len = 1;
+		break;
+
+	case V_ASN1_BIT_STRING:
+		return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+		    cout ? &cout : NULL);
+		break;
+
+	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);
+		break;
+
+	case V_ASN1_OCTET_STRING:
+	case V_ASN1_NUMERICSTRING:
+	case V_ASN1_PRINTABLESTRING:
+	case V_ASN1_T61STRING:
+	case V_ASN1_VIDEOTEXSTRING:
+	case V_ASN1_IA5STRING:
+	case V_ASN1_UTCTIME:
+	case V_ASN1_GENERALIZEDTIME:
+	case V_ASN1_GRAPHICSTRING:
+	case V_ASN1_VISIBLESTRING:
+	case V_ASN1_GENERALSTRING:
+	case V_ASN1_UNIVERSALSTRING:
+	case V_ASN1_BMPSTRING:
+	case V_ASN1_UTF8STRING:
+	case V_ASN1_SEQUENCE:
+	case V_ASN1_SET:
+	default:
+		/* All based on ASN1_STRING and handled the same */
+		strtmp = (ASN1_STRING *)*pval;
+		/* Special handling for NDEF */
+		if ((it->size == ASN1_TFLG_NDEF) &&
+		    (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
+			if (cout) {
+				strtmp->data = cout;
+				strtmp->length = 0;
+			}
+			/* Special return code */
+			return -2;
+		}
+		cont = strtmp->data;
+		len = strtmp->length;
+
+		break;
+
+	}
+	if (cout && len)
+		memcpy(cout, cont, len);
+	return len;
+}
diff --git a/crypto/asn1/tasn_fre.c b/crypto/asn1/tasn_fre.c
new file mode 100644
index 0000000..83c073b
--- /dev/null
+++ b/crypto/asn1/tasn_fre.c
@@ -0,0 +1,243 @@
+/* $OpenBSD: tasn_fre.c,v 1.23 2023/07/28 10:00:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+static void asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+/* Free up an ASN1 structure */
+
+void
+ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
+{
+	asn1_item_free(&val, it);
+}
+LCRYPTO_ALIAS(ASN1_item_free);
+
+void
+ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	asn1_item_free(pval, it);
+}
+LCRYPTO_ALIAS(ASN1_item_ex_free);
+
+static void
+asn1_item_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	const ASN1_TEMPLATE *tt = NULL, *seqtt;
+	const ASN1_EXTERN_FUNCS *ef;
+	const ASN1_AUX *aux = it->funcs;
+	ASN1_aux_cb *asn1_cb = NULL;
+	int i;
+
+	if (pval == NULL)
+		return;
+	/* For primitive types *pval may be something other than C pointer. */
+	if (it->itype != ASN1_ITYPE_PRIMITIVE && *pval == NULL)
+		return;
+
+	if (aux != NULL && aux->asn1_cb != NULL)
+		asn1_cb = aux->asn1_cb;
+
+	switch (it->itype) {
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates)
+			ASN1_template_free(pval, it->templates);
+		else
+			ASN1_primitive_free(pval, it);
+		break;
+
+	case ASN1_ITYPE_MSTRING:
+		ASN1_primitive_free(pval, it);
+		break;
+
+	case ASN1_ITYPE_CHOICE:
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+			if (i == 2)
+				return;
+		}
+		i = 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);
+		}
+		if (asn1_cb)
+			asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+		free(*pval);
+		*pval = NULL;
+		break;
+
+	case ASN1_ITYPE_EXTERN:
+		ef = it->funcs;
+		if (ef && ef->asn1_ex_free)
+			ef->asn1_ex_free(pval, it);
+		break;
+
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+	case ASN1_ITYPE_SEQUENCE:
+		if (asn1_do_lock(pval, -1, it) > 0)
+			return;
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+			if (i == 2)
+				return;
+		}
+		asn1_enc_cleanup(pval, it);
+		/* If we free up as normal we will invalidate any
+		 * ANY DEFINED BY field and we wont be able to
+		 * determine the type of the field it defines. So
+		 * free up in reverse order.
+		 */
+		tt = it->templates + it->tcount - 1;
+		for (i = 0; i < it->tcount; tt--, i++) {
+			ASN1_VALUE **pseqval;
+			seqtt = asn1_do_adb(pval, tt, 0);
+			if (!seqtt)
+				continue;
+			pseqval = asn1_get_field_ptr(pval, seqtt);
+			ASN1_template_free(pseqval, seqtt);
+		}
+		if (asn1_cb)
+			asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+		free(*pval);
+		*pval = NULL;
+		break;
+	}
+}
+
+void
+ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+{
+	int i;
+	if (tt->flags & ASN1_TFLG_SK_MASK) {
+		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+			ASN1_VALUE *vtmp;
+			vtmp = sk_ASN1_VALUE_value(sk, i);
+			asn1_item_free(&vtmp, tt->item);
+		}
+		sk_ASN1_VALUE_free(sk);
+		*pval = NULL;
+	} else
+		asn1_item_free(pval, tt->item);
+}
+
+void
+ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	int utype;
+
+	if (it != NULL && it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+
+		pf->prim_free(pval, it);
+		return;
+	}
+
+	/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
+	if (!it) {
+		ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
+		utype = typ->type;
+		pval = &typ->value.asn1_value;
+		if (!*pval)
+			return;
+	} else if (it->itype == ASN1_ITYPE_MSTRING) {
+		utype = -1;
+		if (!*pval)
+			return;
+	} else {
+		utype = it->utype;
+		if ((utype != V_ASN1_BOOLEAN) && !*pval)
+			return;
+	}
+
+	switch (utype) {
+	case V_ASN1_OBJECT:
+		ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
+		break;
+
+	case V_ASN1_BOOLEAN:
+		if (it)
+			*(ASN1_BOOLEAN *)pval = it->size;
+		else
+			*(ASN1_BOOLEAN *)pval = -1;
+		return;
+
+	case V_ASN1_NULL:
+		break;
+
+	case V_ASN1_ANY:
+		ASN1_primitive_free(pval, NULL);
+		free(*pval);
+		break;
+
+	default:
+		ASN1_STRING_free((ASN1_STRING *)*pval);
+		break;
+	}
+	*pval = NULL;
+}
diff --git a/crypto/asn1/tasn_new.c b/crypto/asn1/tasn_new.c
new file mode 100644
index 0000000..10c1137
--- /dev/null
+++ b/crypto/asn1/tasn_new.c
@@ -0,0 +1,344 @@
+/* $OpenBSD: tasn_new.c,v 1.25 2023/07/28 10:00:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+static int asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
+static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+ASN1_VALUE *
+ASN1_item_new(const ASN1_ITEM *it)
+{
+	ASN1_VALUE *ret = NULL;
+	if (ASN1_item_ex_new(&ret, it) > 0)
+		return ret;
+	return NULL;
+}
+LCRYPTO_ALIAS(ASN1_item_new);
+
+/* Allocate an ASN1 structure */
+
+int
+ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	return asn1_item_ex_new(pval, it);
+}
+LCRYPTO_ALIAS(ASN1_item_ex_new);
+
+static int
+asn1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	const ASN1_TEMPLATE *tt = NULL;
+	const ASN1_EXTERN_FUNCS *ef;
+	const ASN1_AUX *aux = it->funcs;
+	ASN1_aux_cb *asn1_cb = NULL;
+	ASN1_VALUE **pseqval;
+	int i;
+
+	if (aux != NULL && aux->asn1_cb != NULL)
+		asn1_cb = aux->asn1_cb;
+
+	*pval = NULL;
+
+	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;
+		}
+		break;
+
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates) {
+			if (!ASN1_template_new(pval, it->templates))
+				goto memerr;
+		} else if (!ASN1_primitive_new(pval, it))
+			goto memerr;
+		break;
+
+	case ASN1_ITYPE_MSTRING:
+		if (!ASN1_primitive_new(pval, it))
+			goto memerr;
+		break;
+
+	case ASN1_ITYPE_CHOICE:
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+			if (!i)
+				goto auxerr;
+			if (i == 2) {
+				return 1;
+			}
+		}
+		*pval = calloc(1, it->size);
+		if (!*pval)
+			goto memerr;
+		asn1_set_choice_selector(pval, -1, it);
+		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+			goto auxerr;
+		break;
+
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+	case ASN1_ITYPE_SEQUENCE:
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+			if (!i)
+				goto auxerr;
+			if (i == 2) {
+				return 1;
+			}
+		}
+		*pval = calloc(1, it->size);
+		if (!*pval)
+			goto memerr;
+		asn1_do_lock(pval, 0, it);
+		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))
+				goto memerr;
+		}
+		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+			goto auxerr;
+		break;
+	}
+	return 1;
+
+ memerr:
+	ASN1error(ERR_R_MALLOC_FAILURE);
+	return 0;
+
+ auxerr:
+	ASN1error(ASN1_R_AUX_ERROR);
+	ASN1_item_ex_free(pval, it);
+	return 0;
+
+}
+
+static void
+asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	const ASN1_EXTERN_FUNCS *ef;
+
+	switch (it->itype) {
+	case ASN1_ITYPE_EXTERN:
+		ef = it->funcs;
+		if (ef && ef->asn1_ex_clear)
+			ef->asn1_ex_clear(pval, it);
+		else
+			*pval = NULL;
+		break;
+
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates)
+			asn1_template_clear(pval, it->templates);
+		else
+			asn1_primitive_clear(pval, it);
+		break;
+
+	case ASN1_ITYPE_MSTRING:
+		asn1_primitive_clear(pval, it);
+		break;
+
+	case ASN1_ITYPE_CHOICE:
+	case ASN1_ITYPE_SEQUENCE:
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+		*pval = NULL;
+		break;
+	}
+}
+
+int
+ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+{
+	const ASN1_ITEM *it = tt->item;
+	int ret;
+
+	if (tt->flags & ASN1_TFLG_OPTIONAL) {
+		asn1_template_clear(pval, tt);
+		return 1;
+	}
+	/* If ANY DEFINED BY nothing to do */
+
+	if (tt->flags & ASN1_TFLG_ADB_MASK) {
+		*pval = NULL;
+		return 1;
+	}
+	/* 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) {
+			ASN1error(ERR_R_MALLOC_FAILURE);
+			ret = 0;
+			goto done;
+		}
+		*pval = (ASN1_VALUE *)skval;
+		ret = 1;
+		goto done;
+	}
+	/* Otherwise pass it back to the item routine */
+	ret = asn1_item_ex_new(pval, it);
+ done:
+	return ret;
+}
+
+static void
+asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
+{
+	/* If ADB or STACK just NULL the field */
+	if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK))
+		*pval = NULL;
+	else
+		asn1_item_clear(pval, tt->item);
+}
+
+
+/* NB: could probably combine most of the real XXX_new() behaviour and junk
+ * all the old functions.
+ */
+
+int
+ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	ASN1_TYPE *typ;
+	ASN1_STRING *str;
+	int utype;
+
+	if (it != NULL && it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+
+		if (pf->prim_new == NULL)
+			return 0;
+		return pf->prim_new(pval, it);
+	}
+
+	if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+		utype = V_ASN1_UNDEF;
+	else
+		utype = it->utype;
+	switch (utype) {
+	case V_ASN1_OBJECT:
+		*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
+		return 1;
+
+	case V_ASN1_BOOLEAN:
+		*(ASN1_BOOLEAN *)pval = it->size;
+		return 1;
+
+	case V_ASN1_NULL:
+		*pval = (ASN1_VALUE *)1;
+		return 1;
+
+	case V_ASN1_ANY:
+		typ = malloc(sizeof(ASN1_TYPE));
+		if (typ != NULL) {
+			typ->value.ptr = NULL;
+			typ->type = V_ASN1_UNDEF;
+		}
+		*pval = (ASN1_VALUE *)typ;
+		break;
+
+	default:
+		str = ASN1_STRING_type_new(utype);
+		if (it != NULL && it->itype == ASN1_ITYPE_MSTRING &&
+		    str != NULL)
+			str->flags |= ASN1_STRING_FLAG_MSTRING;
+		*pval = (ASN1_VALUE *)str;
+		break;
+	}
+	if (*pval)
+		return 1;
+	return 0;
+}
+
+static void
+asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	int utype;
+
+	if (it != NULL && it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+
+		if (pf->prim_clear)
+			pf->prim_clear(pval, it);
+		else
+			*pval = NULL;
+		return;
+	}
+
+	if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+		utype = V_ASN1_UNDEF;
+	else
+		utype = it->utype;
+	if (utype == V_ASN1_BOOLEAN)
+		*(ASN1_BOOLEAN *)pval = it->size;
+	else
+		*pval = NULL;
+}
diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
new file mode 100644
index 0000000..3f61a68
--- /dev/null
+++ b/crypto/asn1/tasn_prn.c
@@ -0,0 +1,612 @@
+/* $OpenBSD: tasn_prn.c,v 1.25 2023/07/05 21:23:36 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000,2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+/* Print routines.
+ */
+
+/* ASN1_PCTX routines */
+
+static const ASN1_PCTX default_pctx = {
+	.flags = ASN1_PCTX_FLAGS_SHOW_ABSENT,
+};
+
+ASN1_PCTX *
+ASN1_PCTX_new(void)
+{
+	ASN1_PCTX *p;
+
+	if ((p = calloc(1, sizeof(ASN1_PCTX))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	return p;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_new);
+
+void
+ASN1_PCTX_free(ASN1_PCTX *p)
+{
+	free(p);
+}
+LCRYPTO_ALIAS(ASN1_PCTX_free);
+
+unsigned long
+ASN1_PCTX_get_flags(const ASN1_PCTX *p)
+{
+	return p->flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_get_flags);
+
+void
+ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
+{
+	p->flags = flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_set_flags);
+
+unsigned long
+ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p)
+{
+	return p->nm_flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_get_nm_flags);
+
+void
+ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
+{
+	p->nm_flags = flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_set_nm_flags);
+
+unsigned long
+ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p)
+{
+	return p->cert_flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_get_cert_flags);
+
+void
+ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
+{
+	p->cert_flags = flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_set_cert_flags);
+
+unsigned long
+ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p)
+{
+	return p->oid_flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_get_oid_flags);
+
+void
+ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
+{
+	p->oid_flags = flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_set_oid_flags);
+
+unsigned long
+ASN1_PCTX_get_str_flags(const ASN1_PCTX *p)
+{
+	return p->str_flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_get_str_flags);
+
+void
+ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
+{
+	p->str_flags = flags;
+}
+LCRYPTO_ALIAS(ASN1_PCTX_set_str_flags);
+
+/* Main print routines */
+
+static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+    const ASN1_ITEM *it, const char *fname, const char *sname, int nohdr,
+    const ASN1_PCTX *pctx);
+
+int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+    const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
+
+static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
+    const ASN1_ITEM *it, int indent, const char *fname, const char *sname,
+    const ASN1_PCTX *pctx);
+
+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, const ASN1_ITEM *it,
+    const ASN1_PCTX *pctx)
+{
+	const char *sname;
+
+	if (pctx == NULL)
+		pctx = &default_pctx;
+	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
+		sname = NULL;
+	else
+		sname = it->sname;
+	return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname,
+	    0, pctx);
+}
+LCRYPTO_ALIAS(ASN1_item_print);
+
+static int
+asn1_item_print_ctx(BIO *out, 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_AUX *aux = it->funcs;
+	ASN1_aux_cb *asn1_cb;
+	ASN1_PRINT_ARG parg;
+	int i;
+
+	if (aux && aux->asn1_cb) {
+		parg.out = out;
+		parg.indent = indent;
+		parg.pctx = pctx;
+		asn1_cb = aux->asn1_cb;
+	} else
+		asn1_cb = NULL;
+
+	if ((it->itype != ASN1_ITYPE_PRIMITIVE ||
+	    it->utype != V_ASN1_BOOLEAN) && *fld == NULL) {
+		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) {
+			if (!nohdr &&
+			    !asn1_print_fsname(out, indent, fname, sname, pctx))
+				return 0;
+			if (BIO_puts(out, "\n") <= 0)
+				return 0;
+		}
+		return 1;
+	}
+
+	switch (it->itype) {
+	case ASN1_ITYPE_PRIMITIVE:
+		if (it->templates) {
+			if (!asn1_template_print_ctx(out, fld, indent,
+			    it->templates, pctx))
+				return 0;
+		}
+		/* fall thru */
+	case ASN1_ITYPE_MSTRING:
+		if (!asn1_primitive_print(out, fld, it,
+		    indent, fname, sname, pctx))
+			return 0;
+		break;
+
+	case ASN1_ITYPE_EXTERN:
+		if (!nohdr &&
+		    !asn1_print_fsname(out, indent, fname, sname, pctx))
+			return 0;
+		/* Use new style print routine if possible */
+		ef = it->funcs;
+		if (ef && ef->asn1_ex_print) {
+			i = ef->asn1_ex_print(out, fld, indent, "", pctx);
+			if (!i)
+				return 0;
+			if ((i == 2) && (BIO_puts(out, "\n") <= 0))
+				return 0;
+			return 1;
+		} else if (sname &&
+		    BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
+			return 0;
+		break;
+
+	case ASN1_ITYPE_CHOICE:
+		/* CHOICE type, get selector */
+		i = asn1_get_choice_selector(fld, it);
+		/* This should never happen... */
+		if ((i < 0) || (i >= it->tcount)) {
+			if (BIO_printf(out,
+			    "ERROR: selector [%d] invalid\n", i) <= 0)
+				return 0;
+			return 1;
+		}
+		tt = it->templates + i;
+		tmpfld = asn1_get_field_ptr(fld, tt);
+		if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
+			return 0;
+		break;
+
+	case ASN1_ITYPE_SEQUENCE:
+	case ASN1_ITYPE_NDEF_SEQUENCE:
+		if (!nohdr &&
+		    !asn1_print_fsname(out, indent, fname, sname, pctx))
+			return 0;
+		if (fname || sname) {
+			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+				if (BIO_puts(out, " {\n") <= 0)
+					return 0;
+			} else {
+				if (BIO_puts(out, "\n") <= 0)
+					return 0;
+			}
+		}
+
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
+			if (i == 0)
+				return 0;
+			if (i == 2)
+				return 1;
+		}
+
+		/* 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);
+			if (seqtt == NULL)
+				return 0;
+			tmpfld = asn1_get_field_ptr(fld, seqtt);
+			if (!asn1_template_print_ctx(out, tmpfld, indent + 2,
+			    seqtt, pctx))
+				return 0;
+		}
+		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+			if (BIO_printf(out, "%*s}\n", indent, "") < 0)
+				return 0;
+		}
+
+		if (asn1_cb) {
+			i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
+			if (i == 0)
+				return 0;
+		}
+		break;
+
+	default:
+		BIO_printf(out, "Unprocessed type %d\n", it->itype);
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
+    const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
+{
+	int i, flags;
+	const char *sname, *fname;
+
+	flags = tt->flags;
+	if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
+		sname = tt->item->sname;
+	else
+		sname = NULL;
+	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
+		fname = NULL;
+	else
+		fname = tt->field_name;
+	if (flags & ASN1_TFLG_SK_MASK) {
+		char *tname;
+		ASN1_VALUE *skitem;
+		STACK_OF(ASN1_VALUE) *stack;
+
+		/* SET OF, SEQUENCE OF */
+		if (fname) {
+			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) {
+				if (flags & ASN1_TFLG_SET_OF)
+					tname = "SET";
+				else
+					tname = "SEQUENCE";
+				if (BIO_printf(out, "%*s%s OF %s {\n",
+				    indent, "", tname, tt->field_name) <= 0)
+					return 0;
+			} 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++) {
+			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
+				return 0;
+			skitem = sk_ASN1_VALUE_value(stack, i);
+			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
+			    tt->item, NULL, NULL, 1, pctx))
+				return 0;
+		}
+		if (!i && BIO_printf(out, "%*s\n", indent + 2, "") <= 0)
+			return 0;
+		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) {
+			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
+				return 0;
+		}
+		return 1;
+	}
+	return asn1_item_print_ctx(out, fld, indent, tt->item,
+	    fname, sname, 0, pctx);
+}
+
+static int
+asn1_print_fsname(BIO *out, int indent, const char *fname, const char *sname,
+    const ASN1_PCTX *pctx)
+{
+	static char spaces[] = "                    ";
+	const int nspaces = sizeof(spaces) - 1;
+
+	while (indent > nspaces) {
+		if (BIO_write(out, spaces, nspaces) != nspaces)
+			return 0;
+		indent -= nspaces;
+	}
+	if (BIO_write(out, spaces, indent) != indent)
+		return 0;
+	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
+		sname = NULL;
+	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
+		fname = NULL;
+	if (!sname && !fname)
+		return 1;
+	if (fname) {
+		if (BIO_puts(out, fname) <= 0)
+			return 0;
+	}
+	if (sname) {
+		if (fname) {
+			if (BIO_printf(out, " (%s)", sname) <= 0)
+				return 0;
+		} else {
+			if (BIO_puts(out, sname) <= 0)
+				return 0;
+		}
+	}
+	if (BIO_write(out, ": ", 2) != 2)
+		return 0;
+	return 1;
+}
+
+static int
+asn1_print_boolean_ctx(BIO *out, int boolval, const ASN1_PCTX *pctx)
+{
+	const char *str;
+	switch (boolval) {
+	case -1:
+		str = "BOOL ABSENT";
+		break;
+
+	case 0:
+		str = "FALSE";
+		break;
+
+	default:
+		str = "TRUE";
+		break;
+
+	}
+
+	if (BIO_puts(out, str) <= 0)
+		return 0;
+	return 1;
+
+}
+
+static int
+asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str, const ASN1_PCTX *pctx)
+{
+	char *s;
+	int ret = 1;
+	if ((s = i2s_ASN1_INTEGER(NULL, str)) == NULL)
+		return 0;
+	if (BIO_puts(out, s) <= 0)
+		ret = 0;
+	free(s);
+	return ret;
+}
+
+static int
+asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid, const ASN1_PCTX *pctx)
+{
+	char objbuf[80];
+	const char *ln;
+	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
+	if (!ln)
+		ln = "";
+	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
+	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
+		return 0;
+	return 1;
+}
+
+static int
+asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
+    const ASN1_PCTX *pctx)
+{
+	if (str->type == V_ASN1_BIT_STRING) {
+		if (BIO_printf(out, " (%ld unused bits)\n",
+		    str->flags & 0x7) <= 0)
+			return 0;
+	} else if (BIO_puts(out, "\n") <= 0)
+		return 0;
+	if ((str->length > 0) &&
+	    BIO_dump_indent(out, (char *)str->data, str->length,
+	    indent + 2) <= 0)
+		return 0;
+	return 1;
+}
+
+static int
+asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it,
+    int indent, const char *fname, const char *sname, const ASN1_PCTX *pctx)
+{
+	long utype;
+	ASN1_STRING *str;
+	int ret = 1, needlf = 1;
+	const char *pname;
+
+	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
+		return 0;
+
+	if (it != NULL && it->funcs != NULL) {
+		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+
+		if (pf->prim_print == NULL)
+			return 0;
+
+		return pf->prim_print(out, fld, it, indent, pctx);
+	}
+	if (it->itype == ASN1_ITYPE_MSTRING) {
+		str = (ASN1_STRING *)*fld;
+		utype = str->type & ~V_ASN1_NEG;
+	} else {
+		utype = it->utype;
+		if (utype == V_ASN1_BOOLEAN)
+			str = NULL;
+		else
+			str = (ASN1_STRING *)*fld;
+	}
+	if (utype == V_ASN1_ANY) {
+		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
+		utype = atype->type;
+		fld = &atype->value.asn1_value;
+		str = (ASN1_STRING *)*fld;
+		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
+			pname = NULL;
+		else
+			pname = ASN1_tag2str(utype);
+	} else {
+		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
+			pname = ASN1_tag2str(utype);
+		else
+			pname = NULL;
+	}
+
+	if (utype == V_ASN1_NULL) {
+		if (BIO_puts(out, "NULL\n") <= 0)
+			return 0;
+		return 1;
+	}
+
+	if (pname) {
+		if (BIO_puts(out, pname) <= 0)
+			return 0;
+		if (BIO_puts(out, ":") <= 0)
+			return 0;
+	}
+
+	switch (utype) {
+	case V_ASN1_BOOLEAN:
+		{
+			int boolval = *(int *)fld;
+			if (boolval == -1)
+				boolval = it->size;
+			ret = asn1_print_boolean_ctx(out, boolval, pctx);
+		}
+		break;
+
+	case V_ASN1_INTEGER:
+	case V_ASN1_ENUMERATED:
+		ret = asn1_print_integer_ctx(out, str, pctx);
+		break;
+
+	case V_ASN1_UTCTIME:
+		ret = ASN1_UTCTIME_print(out, str);
+		break;
+
+	case V_ASN1_GENERALIZEDTIME:
+		ret = ASN1_GENERALIZEDTIME_print(out, str);
+		break;
+
+	case V_ASN1_OBJECT:
+		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
+		break;
+
+	case V_ASN1_OCTET_STRING:
+	case V_ASN1_BIT_STRING:
+		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
+		needlf = 0;
+		break;
+
+	case V_ASN1_SEQUENCE:
+	case V_ASN1_SET:
+	case V_ASN1_OTHER:
+		if (BIO_puts(out, "\n") <= 0)
+			return 0;
+		if (ASN1_parse_dump(out, str->data, str->length,
+		    indent, 0) <= 0)
+			ret = 0;
+		needlf = 0;
+		break;
+
+	default:
+		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
+	}
+	if (!ret)
+		return 0;
+	if (needlf && BIO_puts(out, "\n") <= 0)
+		return 0;
+	return 1;
+}
diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c
new file mode 100644
index 0000000..21e3885
--- /dev/null
+++ b/crypto/asn1/tasn_typ.c
@@ -0,0 +1,721 @@
+/* $OpenBSD: tasn_typ.c,v 1.18 2023/07/05 21:23:37 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include 
+#include 
+#include 
+
+/* Declarations for string types */
+
+const ASN1_ITEM ASN1_NULL_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_NULL,
+	.sname = "ASN1_NULL",
+};
+
+ASN1_NULL *
+d2i_ASN1_NULL(ASN1_NULL **a, const unsigned char **in, long len)
+{
+	return (ASN1_NULL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_NULL_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_NULL);
+
+int
+i2d_ASN1_NULL(ASN1_NULL *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_NULL_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_NULL);
+
+ASN1_NULL *
+ASN1_NULL_new(void)
+{
+	return (ASN1_NULL *)ASN1_item_new(&ASN1_NULL_it);
+}
+LCRYPTO_ALIAS(ASN1_NULL_new);
+
+void
+ASN1_NULL_free(ASN1_NULL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_NULL_it);
+}
+LCRYPTO_ALIAS(ASN1_NULL_free);
+
+
+const ASN1_ITEM ASN1_UTF8STRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_UTF8STRING,
+	.sname = "ASN1_UTF8STRING",
+};
+
+ASN1_UTF8STRING *
+d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_UTF8STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_UTF8STRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_UTF8STRING);
+
+int
+i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UTF8STRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_UTF8STRING);
+
+ASN1_UTF8STRING *
+ASN1_UTF8STRING_new(void)
+{
+	return (ASN1_UTF8STRING *)ASN1_item_new(&ASN1_UTF8STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_UTF8STRING_new);
+
+void
+ASN1_UTF8STRING_free(ASN1_UTF8STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_UTF8STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_UTF8STRING_free);
+
+
+const ASN1_ITEM ASN1_PRINTABLESTRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_PRINTABLESTRING,
+	.sname = "ASN1_PRINTABLESTRING",
+};
+
+ASN1_PRINTABLESTRING *
+d2i_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING **a, const unsigned char **in,
+    long len)
+{
+	return (ASN1_PRINTABLESTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_PRINTABLESTRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_PRINTABLESTRING);
+
+int
+i2d_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_PRINTABLESTRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_PRINTABLESTRING);
+
+ASN1_PRINTABLESTRING *
+ASN1_PRINTABLESTRING_new(void)
+{
+	return (ASN1_PRINTABLESTRING *)ASN1_item_new(&ASN1_PRINTABLESTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_PRINTABLESTRING_new);
+
+void
+ASN1_PRINTABLESTRING_free(ASN1_PRINTABLESTRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_PRINTABLESTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_PRINTABLESTRING_free);
+
+
+const ASN1_ITEM ASN1_T61STRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_T61STRING,
+	.sname = "ASN1_T61STRING",
+};
+
+ASN1_T61STRING *
+d2i_ASN1_T61STRING(ASN1_T61STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_T61STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_T61STRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_T61STRING);
+
+int
+i2d_ASN1_T61STRING(ASN1_T61STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_T61STRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_T61STRING);
+
+ASN1_T61STRING *
+ASN1_T61STRING_new(void)
+{
+	return (ASN1_T61STRING *)ASN1_item_new(&ASN1_T61STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_T61STRING_new);
+
+void
+ASN1_T61STRING_free(ASN1_T61STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_T61STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_T61STRING_free);
+
+
+const ASN1_ITEM ASN1_IA5STRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_IA5STRING,
+	.sname = "ASN1_IA5STRING",
+};
+
+ASN1_IA5STRING *
+d2i_ASN1_IA5STRING(ASN1_IA5STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_IA5STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_IA5STRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_IA5STRING);
+
+int
+i2d_ASN1_IA5STRING(ASN1_IA5STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_IA5STRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_IA5STRING);
+
+ASN1_IA5STRING *
+ASN1_IA5STRING_new(void)
+{
+	return (ASN1_IA5STRING *)ASN1_item_new(&ASN1_IA5STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_IA5STRING_new);
+
+void
+ASN1_IA5STRING_free(ASN1_IA5STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_IA5STRING_it);
+}
+LCRYPTO_ALIAS(ASN1_IA5STRING_free);
+
+
+const ASN1_ITEM ASN1_GENERALSTRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_GENERALSTRING,
+	.sname = "ASN1_GENERALSTRING",
+};
+
+ASN1_GENERALSTRING *
+d2i_ASN1_GENERALSTRING(ASN1_GENERALSTRING **a, const unsigned char **in,
+    long len)
+{
+	return (ASN1_GENERALSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_GENERALSTRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_GENERALSTRING);
+
+int
+i2d_ASN1_GENERALSTRING(ASN1_GENERALSTRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_GENERALSTRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_GENERALSTRING);
+
+ASN1_GENERALSTRING *
+ASN1_GENERALSTRING_new(void)
+{
+	return (ASN1_GENERALSTRING *)ASN1_item_new(&ASN1_GENERALSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_GENERALSTRING_new);
+
+void
+ASN1_GENERALSTRING_free(ASN1_GENERALSTRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_GENERALSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_GENERALSTRING_free);
+
+
+const ASN1_ITEM ASN1_UTCTIME_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_UTCTIME,
+	.sname = "ASN1_UTCTIME",
+};
+
+ASN1_UTCTIME *
+d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, const unsigned char **in, long len)
+{
+	return (ASN1_UTCTIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_UTCTIME_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_UTCTIME);
+
+int
+i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UTCTIME_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_UTCTIME);
+
+ASN1_UTCTIME *
+ASN1_UTCTIME_new(void)
+{
+	return (ASN1_UTCTIME *)ASN1_item_new(&ASN1_UTCTIME_it);
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_new);
+
+void
+ASN1_UTCTIME_free(ASN1_UTCTIME *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_UTCTIME_it);
+}
+LCRYPTO_ALIAS(ASN1_UTCTIME_free);
+
+
+const ASN1_ITEM ASN1_GENERALIZEDTIME_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_GENERALIZEDTIME,
+	.sname = "ASN1_GENERALIZEDTIME",
+};
+
+ASN1_GENERALIZEDTIME *
+d2i_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME **a, const unsigned char **in,
+    long len)
+{
+	return (ASN1_GENERALIZEDTIME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_GENERALIZEDTIME_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_GENERALIZEDTIME);
+
+int
+i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_GENERALIZEDTIME_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_GENERALIZEDTIME);
+
+ASN1_GENERALIZEDTIME *
+ASN1_GENERALIZEDTIME_new(void)
+{
+	return (ASN1_GENERALIZEDTIME *)ASN1_item_new(&ASN1_GENERALIZEDTIME_it);
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_new);
+
+void
+ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_GENERALIZEDTIME_it);
+}
+LCRYPTO_ALIAS(ASN1_GENERALIZEDTIME_free);
+
+
+const ASN1_ITEM ASN1_VISIBLESTRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_VISIBLESTRING,
+	.sname = "ASN1_VISIBLESTRING",
+};
+
+ASN1_VISIBLESTRING *
+d2i_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING **a, const unsigned char **in,
+    long len)
+{
+	return (ASN1_VISIBLESTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_VISIBLESTRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_VISIBLESTRING);
+
+int
+i2d_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_VISIBLESTRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_VISIBLESTRING);
+
+ASN1_VISIBLESTRING *
+ASN1_VISIBLESTRING_new(void)
+{
+	return (ASN1_VISIBLESTRING *)ASN1_item_new(&ASN1_VISIBLESTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_VISIBLESTRING_new);
+
+void
+ASN1_VISIBLESTRING_free(ASN1_VISIBLESTRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_VISIBLESTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_VISIBLESTRING_free);
+
+
+const ASN1_ITEM ASN1_UNIVERSALSTRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_UNIVERSALSTRING,
+	.sname = "ASN1_UNIVERSALSTRING",
+};
+
+ASN1_UNIVERSALSTRING *
+d2i_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING **a, const unsigned char **in,
+    long len)
+{
+	return (ASN1_UNIVERSALSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_UNIVERSALSTRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_UNIVERSALSTRING);
+
+int
+i2d_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_UNIVERSALSTRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_UNIVERSALSTRING);
+
+ASN1_UNIVERSALSTRING *
+ASN1_UNIVERSALSTRING_new(void)
+{
+	return (ASN1_UNIVERSALSTRING *)ASN1_item_new(&ASN1_UNIVERSALSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_new);
+
+void
+ASN1_UNIVERSALSTRING_free(ASN1_UNIVERSALSTRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_UNIVERSALSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_UNIVERSALSTRING_free);
+
+
+const ASN1_ITEM ASN1_BMPSTRING_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_BMPSTRING,
+	.sname = "ASN1_BMPSTRING",
+};
+
+ASN1_BMPSTRING *
+d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_BMPSTRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_BMPSTRING_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_BMPSTRING);
+
+int
+i2d_ASN1_BMPSTRING(ASN1_BMPSTRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_BMPSTRING_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_BMPSTRING);
+
+ASN1_BMPSTRING *
+ASN1_BMPSTRING_new(void)
+{
+	return (ASN1_BMPSTRING *)ASN1_item_new(&ASN1_BMPSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_BMPSTRING_new);
+
+void
+ASN1_BMPSTRING_free(ASN1_BMPSTRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_BMPSTRING_it);
+}
+LCRYPTO_ALIAS(ASN1_BMPSTRING_free);
+
+const ASN1_ITEM ASN1_ANY_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_ANY,
+	.sname = "ASN1_ANY",
+};
+
+
+/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
+
+const ASN1_ITEM ASN1_SEQUENCE_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_SEQUENCE,
+	.sname = "ASN1_SEQUENCE",
+};
+
+
+/* Multistring types */
+
+
+const ASN1_ITEM ASN1_PRINTABLE_it = {
+	.itype = ASN1_ITYPE_MSTRING,
+	.utype = B_ASN1_PRINTABLE,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = sizeof(ASN1_STRING),
+	.sname = "ASN1_PRINTABLE",
+};
+
+ASN1_STRING *
+d2i_ASN1_PRINTABLE(ASN1_STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_PRINTABLE_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_PRINTABLE);
+
+int
+i2d_ASN1_PRINTABLE(ASN1_STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_PRINTABLE_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_PRINTABLE);
+
+ASN1_STRING *
+ASN1_PRINTABLE_new(void)
+{
+	return (ASN1_STRING *)ASN1_item_new(&ASN1_PRINTABLE_it);
+}
+LCRYPTO_ALIAS(ASN1_PRINTABLE_new);
+
+void
+ASN1_PRINTABLE_free(ASN1_STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ASN1_PRINTABLE_it);
+}
+LCRYPTO_ALIAS(ASN1_PRINTABLE_free);
+
+
+const ASN1_ITEM DISPLAYTEXT_it = {
+	.itype = ASN1_ITYPE_MSTRING,
+	.utype = B_ASN1_DISPLAYTEXT,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = sizeof(ASN1_STRING),
+	.sname = "DISPLAYTEXT",
+};
+
+ASN1_STRING *
+d2i_DISPLAYTEXT(ASN1_STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DISPLAYTEXT_it);
+}
+LCRYPTO_ALIAS(d2i_DISPLAYTEXT);
+
+int
+i2d_DISPLAYTEXT(ASN1_STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DISPLAYTEXT_it);
+}
+LCRYPTO_ALIAS(i2d_DISPLAYTEXT);
+
+ASN1_STRING *
+DISPLAYTEXT_new(void)
+{
+	return (ASN1_STRING *)ASN1_item_new(&DISPLAYTEXT_it);
+}
+LCRYPTO_ALIAS(DISPLAYTEXT_new);
+
+void
+DISPLAYTEXT_free(ASN1_STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &DISPLAYTEXT_it);
+}
+LCRYPTO_ALIAS(DISPLAYTEXT_free);
+
+
+const ASN1_ITEM DIRECTORYSTRING_it = {
+	.itype = ASN1_ITYPE_MSTRING,
+	.utype = B_ASN1_DIRECTORYSTRING,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = sizeof(ASN1_STRING),
+	.sname = "DIRECTORYSTRING",
+};
+
+ASN1_STRING *
+d2i_DIRECTORYSTRING(ASN1_STRING **a, const unsigned char **in, long len)
+{
+	return (ASN1_STRING *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DIRECTORYSTRING_it);
+}
+LCRYPTO_ALIAS(d2i_DIRECTORYSTRING);
+
+int
+i2d_DIRECTORYSTRING(ASN1_STRING *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIRECTORYSTRING_it);
+}
+LCRYPTO_ALIAS(i2d_DIRECTORYSTRING);
+
+ASN1_STRING *
+DIRECTORYSTRING_new(void)
+{
+	return (ASN1_STRING *)ASN1_item_new(&DIRECTORYSTRING_it);
+}
+LCRYPTO_ALIAS(DIRECTORYSTRING_new);
+
+void
+DIRECTORYSTRING_free(ASN1_STRING *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &DIRECTORYSTRING_it);
+}
+LCRYPTO_ALIAS(DIRECTORYSTRING_free);
+
+/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
+
+const ASN1_ITEM ASN1_BOOLEAN_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_BOOLEAN,
+	.size = -1,
+	.sname = "ASN1_BOOLEAN",
+};
+
+int
+i2d_ASN1_BOOLEAN(int a, unsigned char **out)
+{
+	return ASN1_item_ex_i2d((ASN1_VALUE **)&a, out,
+	    &ASN1_BOOLEAN_it, -1, 0);
+}
+
+int
+d2i_ASN1_BOOLEAN(int *a, const unsigned char **in, long len)
+{
+	ASN1_BOOLEAN abool;
+
+	if (ASN1_item_ex_d2i((ASN1_VALUE **)&abool, in, len, &ASN1_BOOLEAN_it,
+	    -1, 0, 0, NULL) <= 0)
+		return -1;
+
+	if (a != NULL)
+		*a = abool;
+
+	return abool;
+}
+
+const ASN1_ITEM ASN1_TBOOLEAN_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_BOOLEAN,
+	.size = 1,
+	.sname = "ASN1_TBOOLEAN",
+};
+
+const ASN1_ITEM ASN1_FBOOLEAN_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_BOOLEAN,
+	.size = 0,
+	.sname = "ASN1_FBOOLEAN",
+};
+
+/* Special, OCTET STRING with indefinite length constructed support */
+
+const ASN1_ITEM ASN1_OCTET_STRING_NDEF_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_OCTET_STRING,
+	.size = ASN1_TFLG_NDEF,
+	.sname = "ASN1_OCTET_STRING_NDEF",
+};
+
+static const ASN1_TEMPLATE ASN1_SEQUENCE_ANY_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "ASN1_SEQUENCE_ANY",
+	.item = &ASN1_ANY_it,
+};
+
+const ASN1_ITEM ASN1_SEQUENCE_ANY_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &ASN1_SEQUENCE_ANY_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "ASN1_SEQUENCE_ANY",
+};
+
+static const ASN1_TEMPLATE ASN1_SET_ANY_item_tt = {
+	.flags = ASN1_TFLG_SET_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "ASN1_SET_ANY",
+	.item = &ASN1_ANY_it,
+};
+
+const ASN1_ITEM ASN1_SET_ANY_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &ASN1_SET_ANY_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "ASN1_SET_ANY",
+};
+
+
+ASN1_SEQUENCE_ANY *
+d2i_ASN1_SEQUENCE_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len)
+{
+	return (ASN1_SEQUENCE_ANY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_SEQUENCE_ANY_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_SEQUENCE_ANY);
+
+int
+i2d_ASN1_SEQUENCE_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_SEQUENCE_ANY_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_SEQUENCE_ANY);
+
+ASN1_SEQUENCE_ANY *
+d2i_ASN1_SET_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len)
+{
+	return (ASN1_SEQUENCE_ANY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ASN1_SET_ANY_it);
+}
+LCRYPTO_ALIAS(d2i_ASN1_SET_ANY);
+
+int
+i2d_ASN1_SET_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASN1_SET_ANY_it);
+}
+LCRYPTO_ALIAS(i2d_ASN1_SET_ANY);
diff --git a/crypto/asn1/tasn_utl.c b/crypto/asn1/tasn_utl.c
new file mode 100644
index 0000000..ae546ed
--- /dev/null
+++ b/crypto/asn1/tasn_utl.c
@@ -0,0 +1,299 @@
+/* $OpenBSD: tasn_utl.c,v 1.18 2022/12/26 07:18:51 jmc Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+
+/* Utility functions for manipulating fields and offsets */
+
+/* Add 'offset' to 'addr' */
+#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
+
+/* Given an ASN1_ITEM CHOICE type return
+ * the selector value
+ */
+
+int
+asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	int *sel = offset2ptr(*pval, it->utype);
+	return *sel;
+}
+
+/* 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 *sel, ret;
+	sel = offset2ptr(*pval, it->utype);
+	ret = *sel;
+	*sel = value;
+	return ret;
+}
+
+/* Do reference counting. The value 'op' decides what to do.
+ * if it is +1 then the count is incremented. If op is 0 count is
+ * set to 1. If op is -1 count is decremented and the return value
+ * is the current reference count or 0 if no reference count exists.
+ */
+
+int
+asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
+{
+	const ASN1_AUX *aux;
+	int *lck, ret;
+
+	if ((it->itype != ASN1_ITYPE_SEQUENCE) &&
+	    (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
+		return 0;
+	aux = it->funcs;
+	if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
+		return 0;
+	lck = offset2ptr(*pval, aux->ref_offset);
+	if (op == 0) {
+		*lck = 1;
+		return 1;
+	}
+	ret = CRYPTO_add(lck, op, aux->ref_lock);
+	return ret;
+}
+
+static ASN1_ENCODING *
+asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	const ASN1_AUX *aux = it->funcs;
+
+	if (pval == NULL || *pval == NULL)
+		return NULL;
+
+	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)
+{
+	ASN1_ENCODING *aenc;
+
+	if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
+		return;
+
+	aenc->enc = NULL;
+	aenc->len = 0;
+	aenc->modified = 1;
+}
+
+static void
+asn1_enc_clear(ASN1_ENCODING *aenc)
+{
+	freezero(aenc->enc, aenc->len);
+	aenc->enc = NULL;
+	aenc->len = 0;
+	aenc->modified = 1;
+}
+
+void
+asn1_enc_cleanup(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	ASN1_ENCODING *aenc;
+
+	if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
+		return;
+
+	asn1_enc_clear(aenc);
+}
+
+int
+asn1_enc_save(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it)
+{
+	ASN1_ENCODING *aenc;
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+
+	if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
+		return 1;
+
+	asn1_enc_clear(aenc);
+
+	if (!CBS_stow(cbs, &data, &data_len))
+		return 0;
+	if (data_len > LONG_MAX) {
+		freezero(data, data_len);
+		return 0;
+	}
+
+	aenc->enc = data;
+	aenc->len = (long)data_len;
+	aenc->modified = 0;
+
+	return 1;
+}
+
+int
+asn1_enc_restore(int *out_len, unsigned char **out, ASN1_VALUE **pval,
+    const ASN1_ITEM *it)
+{
+	ASN1_ENCODING *aenc;
+
+	if ((aenc = asn1_get_enc_ptr(pval, it)) == NULL)
+		return 0;
+
+	if (aenc->modified)
+		return 0;
+
+	if (out != NULL) {
+		memcpy(*out, aenc->enc, aenc->len);
+		*out += aenc->len;
+	}
+
+	if (out_len != NULL)
+		*out_len = aenc->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 **pvaltmp;
+
+	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 *).
+	 */
+	return pvaltmp;
+}
+
+/* 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_ADB *adb;
+	const ASN1_ADB_TABLE *atbl;
+	long selector;
+	ASN1_VALUE **sfld;
+	int i;
+
+	if (!(tt->flags & ASN1_TFLG_ADB_MASK))
+		return tt;
+
+	/* Else ANY DEFINED BY ... get the table */
+	adb = (const ASN1_ADB *)tt->item;
+
+	/* Get the selector field */
+	sfld = offset2ptr(*pval, adb->offset);
+
+	/* Check if NULL */
+	if (!sfld) {
+		if (!adb->null_tt)
+			goto err;
+		return adb->null_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)
+		selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
+	else
+		selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
+
+	/* Try to find matching entry in table
+	 * Maybe should check application types first to
+	 * allow application override? Might also be useful
+	 * to have a flag which indicates table is sorted and
+	 * we can do a binary search. For now stick to a
+	 * linear search.
+	 */
+
+	for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++)
+		if (atbl->value == selector)
+			return &atbl->tt;
+
+	/* FIXME: need to search application table too */
+
+	/* No match, return default type */
+	if (!adb->default_tt)
+		goto err;
+	return adb->default_tt;
+
+ err:
+	/* FIXME: should log the value or OID of unsupported type */
+	if (nullerr)
+		ASN1error(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
+	return NULL;
+}
diff --git a/crypto/asn1/x_algor.c b/crypto/asn1/x_algor.c
new file mode 100644
index 0000000..0f1cd9c
--- /dev/null
+++ b/crypto/asn1/x_algor.c
@@ -0,0 +1,220 @@
+/* $OpenBSD: x_algor.c,v 1.25 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+static const ASN1_TEMPLATE X509_ALGOR_seq_tt[] = {
+	{
+		.offset = offsetof(X509_ALGOR, algorithm),
+		.field_name = "algorithm",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_ALGOR, parameter),
+		.field_name = "parameter",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+const ASN1_ITEM X509_ALGOR_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_ALGOR_seq_tt,
+	.tcount = sizeof(X509_ALGOR_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_ALGOR),
+	.sname = "X509_ALGOR",
+};
+
+static const ASN1_TEMPLATE X509_ALGORS_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "algorithms",
+	.item = &X509_ALGOR_it,
+};
+
+const ASN1_ITEM X509_ALGORS_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &X509_ALGORS_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "X509_ALGORS",
+};
+
+
+X509_ALGOR *
+d2i_X509_ALGOR(X509_ALGOR **a, const unsigned char **in, long len)
+{
+	return (X509_ALGOR *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_ALGOR_it);
+}
+
+int
+i2d_X509_ALGOR(X509_ALGOR *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ALGOR_it);
+}
+
+X509_ALGOR *
+X509_ALGOR_new(void)
+{
+	return (X509_ALGOR *)ASN1_item_new(&X509_ALGOR_it);
+}
+
+void
+X509_ALGOR_free(X509_ALGOR *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_ALGOR_it);
+}
+
+X509_ALGORS *
+d2i_X509_ALGORS(X509_ALGORS **a, const unsigned char **in, long len)
+{
+	return (X509_ALGORS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_ALGORS_it);
+}
+
+int
+i2d_X509_ALGORS(X509_ALGORS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ALGORS_it);
+}
+
+X509_ALGOR *
+X509_ALGOR_dup(X509_ALGOR *x)
+{
+	return ASN1_item_dup(&X509_ALGOR_it, x);
+}
+
+int
+X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval)
+{
+	if (!alg)
+		return 0;
+	if (ptype != V_ASN1_UNDEF) {
+		if (alg->parameter == NULL)
+			alg->parameter = ASN1_TYPE_new();
+		if (alg->parameter == NULL)
+			return 0;
+	}
+	if (alg) {
+		if (alg->algorithm)
+			ASN1_OBJECT_free(alg->algorithm);
+		alg->algorithm = aobj;
+	}
+	if (ptype == 0)
+		return 1;
+	if (ptype == V_ASN1_UNDEF) {
+		if (alg->parameter) {
+			ASN1_TYPE_free(alg->parameter);
+			alg->parameter = NULL;
+		}
+	} else
+		ASN1_TYPE_set(alg->parameter, ptype, pval);
+	return 1;
+}
+
+void
+X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval,
+    const X509_ALGOR *algor)
+{
+	if (paobj)
+		*paobj = algor->algorithm;
+	if (pptype) {
+		if (algor->parameter == NULL) {
+			*pptype = V_ASN1_UNDEF;
+			return;
+		} else
+			*pptype = algor->parameter->type;
+		if (ppval)
+			*ppval = algor->parameter->value.ptr;
+	}
+}
+
+/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
+
+void
+X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
+{
+	int param_type = V_ASN1_NULL;
+
+	if ((EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT) != 0)
+		param_type = V_ASN1_UNDEF;
+
+	X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+}
+
+/* Returns 0 if they are equal, != 0 otherwise. */
+int
+X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
+{
+	int rv = OBJ_cmp(a->algorithm, b->algorithm);
+	if (!rv) {
+		if (!a->parameter && !b->parameter)
+			rv = 0;
+		else
+			rv = ASN1_TYPE_cmp(a->parameter, b->parameter);
+	}
+	return(rv);
+}
diff --git a/crypto/asn1/x_attrib.c b/crypto/asn1/x_attrib.c
new file mode 100644
index 0000000..0820617
--- /dev/null
+++ b/crypto/asn1/x_attrib.c
@@ -0,0 +1,152 @@
+/* $OpenBSD: x_attrib.c,v 1.21 2023/07/28 13:30:07 jsg Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+static const ASN1_TEMPLATE X509_ATTRIBUTE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X509_ATTRIBUTE, object),
+		.field_name = "object",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(X509_ATTRIBUTE, set),
+		.field_name = "set",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+const ASN1_ITEM X509_ATTRIBUTE_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_ATTRIBUTE_seq_tt,
+	.tcount = sizeof(X509_ATTRIBUTE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(X509_ATTRIBUTE),
+	.sname = "X509_ATTRIBUTE",
+};
+
+
+X509_ATTRIBUTE *
+d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **a, const unsigned char **in, long len)
+{
+	return (X509_ATTRIBUTE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_ATTRIBUTE_it);
+}
+
+int
+i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_ATTRIBUTE_it);
+}
+
+X509_ATTRIBUTE *
+X509_ATTRIBUTE_new(void)
+{
+	return (X509_ATTRIBUTE *)ASN1_item_new(&X509_ATTRIBUTE_it);
+}
+
+void
+X509_ATTRIBUTE_free(X509_ATTRIBUTE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_ATTRIBUTE_it);
+}
+
+X509_ATTRIBUTE *
+X509_ATTRIBUTE_dup(X509_ATTRIBUTE *x)
+{
+	return ASN1_item_dup(&X509_ATTRIBUTE_it, x);
+}
+
+X509_ATTRIBUTE *
+X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
+{
+	X509_ATTRIBUTE *ret = NULL;
+	ASN1_TYPE *val = NULL;
+	ASN1_OBJECT *oid;
+
+	if ((oid = OBJ_nid2obj(nid)) == NULL)
+		return (NULL);
+	if ((ret = X509_ATTRIBUTE_new()) == NULL)
+		return (NULL);
+	ret->object = oid;
+	if ((val = ASN1_TYPE_new()) == NULL)
+		goto err;
+	if (!sk_ASN1_TYPE_push(ret->set, val))
+		goto err;
+
+	ASN1_TYPE_set(val, atrtype, value);
+	return (ret);
+
+ err:
+	if (ret != NULL)
+		X509_ATTRIBUTE_free(ret);
+	if (val != NULL)
+		ASN1_TYPE_free(val);
+	return (NULL);
+}
diff --git a/crypto/asn1/x_bignum.c b/crypto/asn1/x_bignum.c
new file mode 100644
index 0000000..bfcf941
--- /dev/null
+++ b/crypto/asn1/x_bignum.c
@@ -0,0 +1,205 @@
+/* $OpenBSD: x_bignum.c,v 1.13 2022/11/26 16:08:50 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bytestring.h"
+
+/*
+ * Custom primitive type for that reads an ASN.1 INTEGER into a BIGNUM.
+ */
+
+static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void bn_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+static int bn_i2c(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_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+    int indent, const ASN1_PCTX *pctx);
+
+static ASN1_PRIMITIVE_FUNCS bignum_pf = {
+	.app_data = NULL,
+	.flags = 0,
+	.prim_new = bn_new,
+	.prim_free = bn_free,
+	.prim_clear = bn_clear,
+	.prim_c2i = bn_c2i,
+	.prim_i2c = bn_i2c,
+	.prim_print = bn_print,
+};
+
+const ASN1_ITEM BIGNUM_it = {
+        .itype = ASN1_ITYPE_PRIMITIVE,
+        .utype = V_ASN1_INTEGER,
+        .templates = NULL,
+        .tcount = 0,
+        .funcs = &bignum_pf,
+        .size = 0,
+        .sname = "BIGNUM",
+};
+
+const ASN1_ITEM CBIGNUM_it = {
+        .itype = ASN1_ITYPE_PRIMITIVE,
+        .utype = V_ASN1_INTEGER,
+        .templates = NULL,
+        .tcount = 0,
+        .funcs = &bignum_pf,
+        .size = 0,
+        .sname = "BIGNUM",
+};
+
+static int
+bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if ((*pval = (ASN1_VALUE *)BN_new()) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static void
+bn_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	BN_free((BIGNUM *)*pval);
+	*pval = NULL;
+}
+
+static void
+bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if (*pval == NULL)
+		return;
+
+	bn_clear(pval, it);
+}
+
+static int
+bn_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype, const ASN1_ITEM *it)
+{
+	ASN1_INTEGER *aint = NULL;
+	unsigned char **pp = NULL;
+	const BIGNUM *bn;
+	int ret;
+
+	if (*pval == NULL)
+		return -1;
+
+	bn = (const BIGNUM *)*pval;
+
+	if ((aint = BN_to_ASN1_INTEGER(bn, NULL)) == NULL)
+		return -1;
+
+	if (content != NULL)
+		pp = &content;
+
+	ret = i2c_ASN1_INTEGER(aint, pp);
+
+	ASN1_INTEGER_free(aint);
+
+	return ret;
+}
+
+static int
+bn_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
+    char *free_content, const ASN1_ITEM *it)
+{
+	ASN1_INTEGER *aint = NULL;
+	BIGNUM *bn;
+	CBS cbs;
+	int ret = 0;
+
+	bn_clear(pval, it);
+
+	if (len < 0)
+		goto err;
+	CBS_init(&cbs, content, len);
+	if (!c2i_ASN1_INTEGER_cbs(&aint, &cbs))
+		goto err;
+
+	if ((bn = ASN1_INTEGER_to_BN(aint, NULL)) == NULL)
+		goto err;
+	*pval = (ASN1_VALUE *)bn;
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+
+	return ret;
+}
+
+static int
+bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent,
+    const ASN1_PCTX *pctx)
+{
+	const BIGNUM *bn = (BIGNUM *)*pval;
+
+	if (!BN_print(out, bn))
+		return 0;
+	if (BIO_printf(out, "\n") <= 0)
+		return 0;
+
+	return 1;
+}
diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c
new file mode 100644
index 0000000..b33ae6e
--- /dev/null
+++ b/crypto/asn1/x_crl.c
@@ -0,0 +1,763 @@
+/* $OpenBSD: x_crl.c,v 1.41 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "x509_local.h"
+
+static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
+    const X509_REVOKED * const *b);
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
+
+static const ASN1_TEMPLATE X509_REVOKED_seq_tt[] = {
+	{
+		.offset = offsetof(X509_REVOKED, serialNumber),
+		.field_name = "serialNumber",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(X509_REVOKED, revocationDate),
+		.field_name = "revocationDate",
+		.item = &ASN1_TIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_REVOKED, extensions),
+		.field_name = "extensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM X509_REVOKED_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_REVOKED_seq_tt,
+	.tcount = sizeof(X509_REVOKED_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_REVOKED),
+	.sname = "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);
+
+static X509_CRL_METHOD int_crl_meth = {
+	.crl_lookup = def_crl_lookup,
+	.crl_verify = def_crl_verify
+};
+
+static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
+
+/* The X509_CRL_INFO structure needs a bit of customisation.
+ * Since we cache the original encoding the signature wont be affected by
+ * reordering of the revoked field.
+ */
+static int
+crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
+
+	if (!a || !a->revoked)
+		return 1;
+	switch (operation) {
+		/* Just set cmp function here. We don't sort because that
+		 * would affect the output of X509_CRL_print().
+		 */
+	case ASN1_OP_D2I_POST:
+		(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
+		break;
+	}
+	return 1;
+}
+
+
+static const ASN1_AUX X509_CRL_INFO_aux = {
+	.flags = ASN1_AFLG_ENCODING,
+	.asn1_cb = crl_inf_cb,
+	.enc_offset = offsetof(X509_CRL_INFO, enc),
+};
+static const ASN1_TEMPLATE X509_CRL_INFO_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CRL_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(X509_CRL_INFO, sig_alg),
+		.field_name = "sig_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_CRL_INFO, issuer),
+		.field_name = "issuer",
+		.item = &X509_NAME_it,
+	},
+	{
+		.offset = offsetof(X509_CRL_INFO, lastUpdate),
+		.field_name = "lastUpdate",
+		.item = &ASN1_TIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CRL_INFO, nextUpdate),
+		.field_name = "nextUpdate",
+		.item = &ASN1_TIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CRL_INFO, revoked),
+		.field_name = "revoked",
+		.item = &X509_REVOKED_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CRL_INFO, extensions),
+		.field_name = "extensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM X509_CRL_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_CRL_INFO_seq_tt,
+	.tcount = sizeof(X509_CRL_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_CRL_INFO_aux,
+	.size = sizeof(X509_CRL_INFO),
+	.sname = "X509_CRL_INFO",
+};
+
+/* Set CRL entry issuer according to CRL certificate issuer extension.
+ * Check for unhandled critical CRL entry extensions.
+ */
+
+static int
+crl_set_issuers(X509_CRL *crl)
+{
+	int i, j;
+	GENERAL_NAMES *gens, *gtmp;
+	STACK_OF(X509_REVOKED) *revoked;
+
+	revoked = X509_CRL_get_REVOKED(crl);
+
+	gens = NULL;
+	for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
+		X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
+		STACK_OF(X509_EXTENSION) *exts;
+		ASN1_ENUMERATED *reason;
+		X509_EXTENSION *ext;
+		gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer,
+		    &j, NULL);
+		if (!gtmp && (j != -1)) {
+			crl->flags |= EXFLAG_INVALID;
+			return 1;
+		}
+
+		if (gtmp) {
+			gens = gtmp;
+			if (!crl->issuers) {
+				crl->issuers = sk_GENERAL_NAMES_new_null();
+				if (!crl->issuers)
+					return 0;
+			}
+			if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
+				return 0;
+		}
+		rev->issuer = gens;
+
+		reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
+		    &j, NULL);
+		if (!reason && (j != -1)) {
+			crl->flags |= EXFLAG_INVALID;
+			return 1;
+		}
+
+		if (reason) {
+			rev->reason = ASN1_ENUMERATED_get(reason);
+			ASN1_ENUMERATED_free(reason);
+		} else
+			rev->reason = CRL_REASON_NONE;
+
+		/* Check for critical CRL entry extensions */
+
+		exts = rev->extensions;
+
+		for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
+			ext = sk_X509_EXTENSION_value(exts, j);
+			if (ext->critical > 0) {
+				if (OBJ_obj2nid(ext->object) ==
+				    NID_certificate_issuer)
+					continue;
+				crl->flags |= EXFLAG_CRITICAL;
+				break;
+			}
+		}
+	}
+
+	return 1;
+}
+
+/* The X509_CRL structure needs a bit of customisation. Cache some extensions
+ * and hash of the whole CRL.
+ */
+static int
+crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	X509_CRL *crl = (X509_CRL *)*pval;
+	STACK_OF(X509_EXTENSION) *exts;
+	X509_EXTENSION *ext;
+	int idx;
+	int rc = 1;
+
+	switch (operation) {
+	case ASN1_OP_NEW_POST:
+		crl->idp = NULL;
+		crl->akid = NULL;
+		crl->flags = 0;
+		crl->idp_flags = 0;
+		crl->idp_reasons = CRLDP_ALL_REASONS;
+		crl->meth = default_crl_method;
+		crl->meth_data = NULL;
+		crl->issuers = NULL;
+		crl->crl_number = NULL;
+		crl->base_crl_number = NULL;
+		break;
+
+	case ASN1_OP_D2I_POST:
+		X509_CRL_digest(crl, X509_CRL_HASH_EVP, crl->hash, NULL);
+		crl->idp = X509_CRL_get_ext_d2i(crl,
+		    NID_issuing_distribution_point, NULL, NULL);
+		if (crl->idp)
+			setup_idp(crl, crl->idp);
+
+		crl->akid = X509_CRL_get_ext_d2i(crl,
+		    NID_authority_key_identifier, NULL, NULL);
+
+		crl->crl_number = X509_CRL_get_ext_d2i(crl,
+		    NID_crl_number, NULL, NULL);
+
+		crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
+		    NID_delta_crl, NULL, NULL);
+		/* Delta CRLs must have CRL number */
+		if (crl->base_crl_number && !crl->crl_number)
+			crl->flags |= EXFLAG_INVALID;
+
+		/* See if we have any unhandled critical CRL extensions and
+		 * indicate this in a flag. We only currently handle IDP,
+		 * AKID and deltas, so anything else critical sets the flag.
+		 *
+		 * This code accesses the X509_CRL structure directly:
+		 * applications shouldn't do this.
+		 */
+
+		exts = crl->crl->extensions;
+
+		for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
+			int nid;
+			ext = sk_X509_EXTENSION_value(exts, idx);
+			nid = OBJ_obj2nid(ext->object);
+			if (nid == NID_freshest_crl)
+				crl->flags |= EXFLAG_FRESHEST;
+			if (ext->critical > 0) {
+				/* We handle IDP, AKID and deltas */
+				if (nid == NID_issuing_distribution_point ||
+				    nid == NID_authority_key_identifier ||
+				    nid == NID_delta_crl)
+					break;
+				crl->flags |= EXFLAG_CRITICAL;
+				break;
+			}
+		}
+
+		if (!crl_set_issuers(crl))
+			return 0;
+
+		if (crl->meth->crl_init) {
+			if (crl->meth->crl_init(crl) == 0)
+				return 0;
+		}
+		break;
+
+	case ASN1_OP_FREE_POST:
+		if (crl->meth->crl_free) {
+			if (!crl->meth->crl_free(crl))
+				rc = 0;
+		}
+		if (crl->akid)
+			AUTHORITY_KEYID_free(crl->akid);
+		if (crl->idp)
+			ISSUING_DIST_POINT_free(crl->idp);
+		ASN1_INTEGER_free(crl->crl_number);
+		ASN1_INTEGER_free(crl->base_crl_number);
+		sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
+		break;
+	}
+	return rc;
+}
+
+/* Convert IDP into a more convenient form */
+
+static void
+setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
+{
+	int idp_only = 0;
+
+	/* Set various flags according to IDP */
+	crl->idp_flags |= IDP_PRESENT;
+	if (idp->onlyuser > 0) {
+		idp_only++;
+		crl->idp_flags |= IDP_ONLYUSER;
+	}
+	if (idp->onlyCA > 0) {
+		idp_only++;
+		crl->idp_flags |= IDP_ONLYCA;
+	}
+	if (idp->onlyattr > 0) {
+		idp_only++;
+		crl->idp_flags |= IDP_ONLYATTR;
+	}
+
+	if (idp_only > 1)
+		crl->idp_flags |= IDP_INVALID;
+
+	if (idp->indirectCRL > 0)
+		crl->idp_flags |= IDP_INDIRECT;
+
+	if (idp->onlysomereasons) {
+		crl->idp_flags |= IDP_REASONS;
+		if (idp->onlysomereasons->length > 0)
+			crl->idp_reasons = idp->onlysomereasons->data[0];
+		if (idp->onlysomereasons->length > 1)
+			crl->idp_reasons |=
+			    (idp->onlysomereasons->data[1] << 8);
+		crl->idp_reasons &= CRLDP_ALL_REASONS;
+	}
+
+	DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
+}
+
+static const ASN1_AUX X509_CRL_aux = {
+	.app_data = NULL,
+	.flags = ASN1_AFLG_REFCOUNT,
+	.ref_offset = offsetof(X509_CRL, references),
+	.ref_lock = CRYPTO_LOCK_X509_CRL,
+	.asn1_cb = crl_cb,
+};
+static const ASN1_TEMPLATE X509_CRL_seq_tt[] = {
+	{
+		.offset = offsetof(X509_CRL, crl),
+		.field_name = "crl",
+		.item = &X509_CRL_INFO_it,
+	},
+	{
+		.offset = offsetof(X509_CRL, sig_alg),
+		.field_name = "sig_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_CRL, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_CRL_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_CRL_seq_tt,
+	.tcount = sizeof(X509_CRL_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_CRL_aux,
+	.size = sizeof(X509_CRL),
+	.sname = "X509_CRL",
+};
+
+
+X509_REVOKED *
+d2i_X509_REVOKED(X509_REVOKED **a, const unsigned char **in, long len)
+{
+	return (X509_REVOKED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_REVOKED_it);
+}
+
+int
+i2d_X509_REVOKED(X509_REVOKED *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REVOKED_it);
+}
+
+X509_REVOKED *
+X509_REVOKED_new(void)
+{
+	return (X509_REVOKED *)ASN1_item_new(&X509_REVOKED_it);
+}
+
+void
+X509_REVOKED_free(X509_REVOKED *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_REVOKED_it);
+}
+
+X509_REVOKED *
+X509_REVOKED_dup(X509_REVOKED *a)
+{
+	return ASN1_item_dup(&X509_REVOKED_it, a);
+}
+
+X509_CRL_INFO *
+d2i_X509_CRL_INFO(X509_CRL_INFO **a, const unsigned char **in, long len)
+{
+	return (X509_CRL_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_CRL_INFO_it);
+}
+
+int
+i2d_X509_CRL_INFO(X509_CRL_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_INFO_it);
+}
+
+X509_CRL_INFO *
+X509_CRL_INFO_new(void)
+{
+	return (X509_CRL_INFO *)ASN1_item_new(&X509_CRL_INFO_it);
+}
+
+void
+X509_CRL_INFO_free(X509_CRL_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_INFO_it);
+}
+
+X509_CRL *
+d2i_X509_CRL(X509_CRL **a, const unsigned char **in, long len)
+{
+	return (X509_CRL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_CRL_it);
+}
+
+int
+i2d_X509_CRL(X509_CRL *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_it);
+}
+
+X509_CRL *
+X509_CRL_new(void)
+{
+	return (X509_CRL *)ASN1_item_new(&X509_CRL_it);
+}
+
+void
+X509_CRL_free(X509_CRL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_it);
+}
+
+X509_CRL *
+X509_CRL_dup(X509_CRL *x)
+{
+	return ASN1_item_dup(&X509_CRL_it, x);
+}
+
+static int
+X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
+{
+	return(ASN1_INTEGER_cmp((*a)->serialNumber, (*b)->serialNumber));
+}
+
+int
+X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
+{
+	X509_CRL_INFO *inf;
+
+	inf = crl->crl;
+	if (!inf->revoked)
+		inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
+	if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	inf->enc.modified = 1;
+	return 1;
+}
+
+int
+X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
+{
+	if (crl->meth->crl_verify)
+		return crl->meth->crl_verify(crl, r);
+	return 0;
+}
+
+int
+X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
+    ASN1_INTEGER *serial)
+{
+	if (crl->meth->crl_lookup)
+		return crl->meth->crl_lookup(crl, ret, serial, NULL);
+	return 0;
+}
+
+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_get_issuer_name(x));
+	return 0;
+}
+
+static int
+def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
+{
+	return(ASN1_item_verify(&X509_CRL_INFO_it,
+	    crl->sig_alg, crl->signature, crl->crl, r));
+}
+
+static int
+crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, X509_REVOKED *rev)
+{
+	int i;
+
+	if (!rev->issuer) {
+		if (!nm)
+			return 1;
+		if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
+			return 1;
+		return 0;
+	}
+
+	if (!nm)
+		nm = X509_CRL_get_issuer(crl);
+
+	for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
+		GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
+		if (gen->type != GEN_DIRNAME)
+			continue;
+		if (!X509_NAME_cmp(nm, gen->d.directoryName))
+			return 1;
+	}
+	return 0;
+
+}
+
+static int
+def_crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
+    X509_NAME *issuer)
+{
+	X509_REVOKED rtmp, *rev;
+	int idx;
+
+	rtmp.serialNumber = serial;
+	/* Sort revoked into serial number order if not already sorted.
+	 * Do this under a lock to avoid race condition.
+ 	 */
+	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
+		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
+		sk_X509_REVOKED_sort(crl->crl->revoked);
+		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
+	}
+	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
+	if (idx < 0)
+		return 0;
+	/* Need to look for matching name */
+	for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
+		rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
+		if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
+			return 0;
+		if (crl_revoked_issuer_match(crl, issuer, rev)) {
+			if (ret)
+				*ret = rev;
+			if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+				return 2;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void
+X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
+{
+	if (meth == NULL)
+		default_crl_method = &int_crl_meth;
+	else
+		default_crl_method = meth;
+}
+
+X509_CRL_METHOD *
+X509_CRL_METHOD_new(int (*crl_init)(X509_CRL *crl),
+    int (*crl_free)(X509_CRL *crl),
+    int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
+    ASN1_INTEGER *ser, X509_NAME *issuer),
+    int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk))
+{
+	X509_CRL_METHOD *m;
+
+	if ((m = calloc(1, sizeof(X509_CRL_METHOD))) == NULL)
+		return NULL;
+
+	m->crl_init = crl_init;
+	m->crl_free = crl_free;
+	m->crl_lookup = crl_lookup;
+	m->crl_verify = crl_verify;
+	m->flags = X509_CRL_METHOD_DYNAMIC;
+
+	return m;
+}
+
+void
+X509_CRL_METHOD_free(X509_CRL_METHOD *m)
+{
+	if (m == NULL)
+		return;
+	if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
+		return;
+	free(m);
+}
+
+void
+X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
+{
+	crl->meth_data = dat;
+}
+
+void *
+X509_CRL_get_meth_data(X509_CRL *crl)
+{
+	return crl->meth_data;
+}
+
+int
+X509_CRL_get_signature_nid(const X509_CRL *crl)
+{
+	return OBJ_obj2nid(crl->sig_alg->algorithm);
+}
+
+const STACK_OF(X509_EXTENSION) *
+X509_CRL_get0_extensions(const X509_CRL *crl)
+{
+	return crl->crl->extensions;
+}
+
+long
+X509_CRL_get_version(const X509_CRL *crl)
+{
+	return ASN1_INTEGER_get(crl->crl->version);
+}
+
+const ASN1_TIME *
+X509_CRL_get0_lastUpdate(const X509_CRL *crl)
+{
+	return crl->crl->lastUpdate;
+}
+
+ASN1_TIME *
+X509_CRL_get_lastUpdate(X509_CRL *crl)
+{
+	return crl->crl->lastUpdate;
+}
+
+const ASN1_TIME *
+X509_CRL_get0_nextUpdate(const X509_CRL *crl)
+{
+	return crl->crl->nextUpdate;
+}
+
+ASN1_TIME *
+X509_CRL_get_nextUpdate(X509_CRL *crl)
+{
+	return crl->crl->nextUpdate;
+}
+
+X509_NAME *
+X509_CRL_get_issuer(const X509_CRL *crl)
+{
+	return crl->crl->issuer;
+}
+
+STACK_OF(X509_REVOKED) *
+X509_CRL_get_REVOKED(X509_CRL *crl)
+{
+	return crl->crl->revoked;
+}
+
+void
+X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
+    const X509_ALGOR **palg)
+{
+	if (psig != NULL)
+		*psig = crl->signature;
+	if (palg != NULL)
+		*palg = crl->sig_alg;
+}
+
+const X509_ALGOR *
+X509_CRL_get0_tbs_sigalg(const X509_CRL *crl)
+{
+	return crl->crl->sig_alg;
+}
diff --git a/crypto/asn1/x_exten.c b/crypto/asn1/x_exten.c
new file mode 100644
index 0000000..6ff33d5
--- /dev/null
+++ b/crypto/asn1/x_exten.c
@@ -0,0 +1,155 @@
+/* $OpenBSD: x_exten.c,v 1.20 2023/07/07 19:37:52 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+static const ASN1_TEMPLATE X509_EXTENSION_seq_tt[] = {
+	{
+		.offset = offsetof(X509_EXTENSION, object),
+		.field_name = "object",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_EXTENSION, critical),
+		.field_name = "critical",
+		.item = &ASN1_BOOLEAN_it,
+	},
+	{
+		.offset = offsetof(X509_EXTENSION, value),
+		.field_name = "value",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_EXTENSION_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_EXTENSION_seq_tt,
+	.tcount = sizeof(X509_EXTENSION_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_EXTENSION),
+	.sname = "X509_EXTENSION",
+};
+
+static const ASN1_TEMPLATE X509_EXTENSIONS_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "Extension",
+	.item = &X509_EXTENSION_it,
+};
+
+const ASN1_ITEM X509_EXTENSIONS_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &X509_EXTENSIONS_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "X509_EXTENSIONS",
+};
+
+
+X509_EXTENSION *
+d2i_X509_EXTENSION(X509_EXTENSION **a, const unsigned char **in, long len)
+{
+	return (X509_EXTENSION *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_EXTENSION_it);
+}
+
+int
+i2d_X509_EXTENSION(X509_EXTENSION *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_EXTENSION_it);
+}
+
+X509_EXTENSION *
+X509_EXTENSION_new(void)
+{
+	return (X509_EXTENSION *)ASN1_item_new(&X509_EXTENSION_it);
+}
+
+void
+X509_EXTENSION_free(X509_EXTENSION *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_EXTENSION_it);
+}
+
+X509_EXTENSIONS *
+d2i_X509_EXTENSIONS(X509_EXTENSIONS **a, const unsigned char **in, long len)
+{
+	return (X509_EXTENSIONS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_EXTENSIONS_it);
+}
+
+int
+i2d_X509_EXTENSIONS(X509_EXTENSIONS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_EXTENSIONS_it);
+}
+
+X509_EXTENSION *
+X509_EXTENSION_dup(X509_EXTENSION *x)
+{
+	return ASN1_item_dup(&X509_EXTENSION_it, x);
+}
diff --git a/crypto/asn1/x_info.c b/crypto/asn1/x_info.c
new file mode 100644
index 0000000..3d2d5ba
--- /dev/null
+++ b/crypto/asn1/x_info.c
@@ -0,0 +1,94 @@
+/* $OpenBSD: x_info.c,v 1.20 2023/07/07 19:37:52 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+X509_INFO *
+X509_INFO_new(void)
+{
+	X509_INFO *ret;
+
+	if ((ret = calloc(1, sizeof(X509_INFO))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	ret->references = 1;
+
+	return ret;
+}
+
+void
+X509_INFO_free(X509_INFO *x)
+{
+	if (x == NULL)
+		return;
+
+	if (CRYPTO_add(&x->references, -1, CRYPTO_LOCK_X509_INFO) > 0)
+		return;
+
+	X509_free(x->x509);
+	X509_CRL_free(x->crl);
+	X509_PKEY_free(x->x_pkey);
+	free(x->enc_data);
+
+	free(x);
+}
diff --git a/crypto/asn1/x_long.c b/crypto/asn1/x_long.c
new file mode 100644
index 0000000..aafdb9c
--- /dev/null
+++ b/crypto/asn1/x_long.c
@@ -0,0 +1,239 @@
+/* $OpenBSD: x_long.c,v 1.19 2022/11/26 16:08:50 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+/*
+ * Custom primitive type for long handling. This converts between an
+ * ASN1_INTEGER and a long directly.
+ */
+
+static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
+static void long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
+
+static int long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
+    const ASN1_ITEM *it);
+static int long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len,
+    int utype, char *free_content, const ASN1_ITEM *it);
+static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
+    int indent, const ASN1_PCTX *pctx);
+
+static ASN1_PRIMITIVE_FUNCS long_pf = {
+	.app_data = NULL,
+	.flags = 0,
+	.prim_new = long_new,
+	.prim_free = long_free,
+	.prim_clear = long_clear,
+	.prim_c2i = long_c2i,
+	.prim_i2c = long_i2c,
+	.prim_print = long_print,
+};
+
+const ASN1_ITEM LONG_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_INTEGER,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &long_pf,
+	.size = ASN1_LONG_UNDEF,
+	.sname = "LONG",
+};
+
+const ASN1_ITEM ZLONG_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = V_ASN1_INTEGER,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &long_pf,
+	.size = 0,
+	.sname = "ZLONG",
+};
+
+static void
+long_get(ASN1_VALUE **pval, long *out_val)
+{
+	memcpy(out_val, pval, sizeof(long));
+}
+
+static void
+long_set(ASN1_VALUE **pval, long val)
+{
+	memcpy(pval, &val, sizeof(long));
+}
+
+static int
+long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	long_clear(pval, it);
+
+	return 1;
+}
+
+static void
+long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	long_clear(pval, it);
+}
+
+static void
+long_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	/* Zero value. */
+	long_set(pval, it->size);
+}
+
+static int
+long_i2c(ASN1_VALUE **pval, unsigned char *content, int *putype,
+    const ASN1_ITEM *it)
+{
+	ASN1_INTEGER *aint;
+	uint8_t **pp = NULL;
+	long val;
+	int ret = 0;
+
+	long_get(pval, &val);
+
+	/*
+	 * The zero value for this type (stored in the overloaded it->size
+	 * field) is considered to be invalid.
+	 */
+	if (val == it->size)
+		return -1;
+
+	if ((aint = ASN1_INTEGER_new()) == NULL)
+		goto err;
+	if (!ASN1_INTEGER_set_int64(aint, (int64_t)val))
+		goto err;
+	if (content != NULL)
+		pp = &content;
+	ret = i2c_ASN1_INTEGER(aint, pp);
+
+ err:
+	ASN1_INTEGER_free(aint);
+
+	return ret;
+}
+
+static int
+long_c2i(ASN1_VALUE **pval, const unsigned char *content, int len, int utype,
+    char *free_content, const ASN1_ITEM *it)
+{
+	ASN1_INTEGER *aint = NULL;
+	const uint8_t **pp = NULL;
+	int64_t val = 0;
+	int ret = 0;
+
+	/*
+	 * The original long_i2c() mishandled 0 values and encoded them as
+	 * content with zero length, rather than a single zero byte. Permit
+	 * zero length content here for backwards compatibility.
+	 */
+	if (len != 0) {
+		if (content != NULL)
+			pp = &content;
+		if (!c2i_ASN1_INTEGER(&aint, pp, len))
+			goto err;
+		if (!ASN1_INTEGER_get_int64(&val, aint))
+			goto err;
+	}
+
+	if (val < LONG_MIN || val > LONG_MAX) {
+		ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+		goto err;
+	}
+
+	/*
+	 * The zero value for this type (stored in the overloaded it->size
+	 * field) is considered to be invalid.
+	 */
+	if (val == (int64_t)it->size) {
+		ASN1error(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
+		goto err;
+	}
+
+	long_set(pval, (long)val);
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+
+	return ret;
+}
+
+static int
+long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent,
+    const ASN1_PCTX *pctx)
+{
+	long val;
+
+	long_get(pval, &val);
+
+	if (BIO_printf(out, "%ld\n", val) <= 0)
+		return 0;
+
+	return 1;
+}
diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c
new file mode 100644
index 0000000..dc9f217
--- /dev/null
+++ b/crypto/asn1/x_name.c
@@ -0,0 +1,650 @@
+/* $OpenBSD: x_name.c,v 1.41 2023/07/24 06:56:54 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "x509_local.h"
+
+typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
+DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
+
+static int x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in,
+    long len, 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,
+    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);
+
+static int x509_name_encode(X509_NAME *a);
+static int x509_name_canon(X509_NAME *a);
+static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
+    unsigned char **in);
+
+static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent,
+    const char *fname, const ASN1_PCTX *pctx);
+
+static const ASN1_TEMPLATE X509_NAME_ENTRY_seq_tt[] = {
+	{
+		.offset = offsetof(X509_NAME_ENTRY, object),
+		.field_name = "object",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.offset = offsetof(X509_NAME_ENTRY, value),
+		.field_name = "value",
+		.item = &ASN1_PRINTABLE_it,
+	},
+};
+
+const ASN1_ITEM X509_NAME_ENTRY_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_NAME_ENTRY_seq_tt,
+	.tcount = sizeof(X509_NAME_ENTRY_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_NAME_ENTRY),
+	.sname = "X509_NAME_ENTRY",
+};
+
+
+X509_NAME_ENTRY *
+d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a, const unsigned char **in, long len)
+{
+	return (X509_NAME_ENTRY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_NAME_ENTRY_it);
+}
+
+int
+i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_ENTRY_it);
+}
+
+X509_NAME_ENTRY *
+X509_NAME_ENTRY_new(void)
+{
+	return (X509_NAME_ENTRY *)ASN1_item_new(&X509_NAME_ENTRY_it);
+}
+
+void
+X509_NAME_ENTRY_free(X509_NAME_ENTRY *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_ENTRY_it);
+}
+
+X509_NAME_ENTRY *
+X509_NAME_ENTRY_dup(X509_NAME_ENTRY *x)
+{
+	return ASN1_item_dup(&X509_NAME_ENTRY_it, x);
+}
+
+/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
+ * so declare two template wrappers for this
+ */
+
+static const ASN1_TEMPLATE X509_NAME_ENTRIES_item_tt = {
+	.flags = ASN1_TFLG_SET_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "RDNS",
+	.item = &X509_NAME_ENTRY_it,
+};
+
+const ASN1_ITEM X509_NAME_ENTRIES_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &X509_NAME_ENTRIES_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "X509_NAME_ENTRIES",
+};
+
+static const ASN1_TEMPLATE X509_NAME_INTERNAL_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "Name",
+	.item = &X509_NAME_ENTRIES_it,
+};
+
+const ASN1_ITEM X509_NAME_INTERNAL_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &X509_NAME_INTERNAL_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "X509_NAME_INTERNAL",
+};
+
+/* Normally that's where it would end: we'd have two nested STACK structures
+ * representing the ASN1. Unfortunately X509_NAME uses a completely different
+ * form and caches encodings so we have to process the internal form and convert
+ * to the external form.
+ */
+
+const ASN1_EXTERN_FUNCS x509_name_ff = {
+	.app_data = NULL,
+	.asn1_ex_new = x509_name_ex_new,
+	.asn1_ex_free = x509_name_ex_free,
+	.asn1_ex_clear = NULL,
+	.asn1_ex_d2i = x509_name_ex_d2i,
+	.asn1_ex_i2d = x509_name_ex_i2d,
+	.asn1_ex_print = x509_name_ex_print,
+};
+
+const ASN1_ITEM X509_NAME_it = {
+	.itype = ASN1_ITYPE_EXTERN,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &x509_name_ff,
+	.size = 0,
+	.sname = "X509_NAME",
+};
+
+X509_NAME *
+d2i_X509_NAME(X509_NAME **a, const unsigned char **in, long len)
+{
+	return (X509_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_NAME_it);
+}
+
+int
+i2d_X509_NAME(X509_NAME *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_NAME_it);
+}
+
+X509_NAME *
+X509_NAME_new(void)
+{
+	return (X509_NAME *)ASN1_item_new(&X509_NAME_it);
+}
+
+void
+X509_NAME_free(X509_NAME *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_NAME_it);
+}
+
+X509_NAME *
+X509_NAME_dup(X509_NAME *x)
+{
+	return ASN1_item_dup(&X509_NAME_it, x);
+}
+
+static int
+x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
+{
+	X509_NAME *ret = NULL;
+
+	ret = malloc(sizeof(X509_NAME));
+	if (!ret)
+		goto memerr;
+	if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
+		goto memerr;
+	if ((ret->bytes = BUF_MEM_new()) == NULL)
+		goto memerr;
+	ret->canon_enc = NULL;
+	ret->canon_enclen = 0;
+	ret->modified = 1;
+	*val = (ASN1_VALUE *)ret;
+	return 1;
+
+ memerr:
+	ASN1error(ERR_R_MALLOC_FAILURE);
+	if (ret) {
+		if (ret->entries)
+			sk_X509_NAME_ENTRY_free(ret->entries);
+		free(ret);
+	}
+	return 0;
+}
+
+static void
+x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	X509_NAME *a;
+
+	if (!pval || !*pval)
+		return;
+	a = (X509_NAME *)*pval;
+
+	BUF_MEM_free(a->bytes);
+	sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
+	free(a->canon_enc);
+	free(a);
+	*pval = NULL;
+}
+
+static int
+x509_name_ex_d2i(ASN1_VALUE **val, const unsigned char **in, long len,
+    const ASN1_ITEM *it, int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+	const unsigned char *p = *in, *q;
+	union {
+		STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+		ASN1_VALUE *a;
+	} intname = {NULL};
+	union {
+		X509_NAME *x;
+		ASN1_VALUE *a;
+	} nm = {NULL};
+	int i, j, ret;
+	STACK_OF(X509_NAME_ENTRY) *entries;
+	X509_NAME_ENTRY *entry;
+	q = p;
+
+	/* Get internal representation of Name */
+	ret = ASN1_item_ex_d2i(&intname.a, &p, len,
+	    &X509_NAME_INTERNAL_it, tag, aclass, opt, ctx);
+
+	if (ret <= 0)
+		return ret;
+
+	if (*val)
+		x509_name_ex_free(val, NULL);
+	if (!x509_name_ex_new(&nm.a, NULL))
+		goto err;
+	/* We've decoded it: now cache encoding */
+	if (!BUF_MEM_grow(nm.x->bytes, p - q))
+		goto err;
+	memcpy(nm.x->bytes->data, q, p - q);
+
+	/* Convert internal representation to X509_NAME structure */
+	for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
+		entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
+		for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
+			entry = sk_X509_NAME_ENTRY_value(entries, j);
+			entry->set = i;
+			if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
+				goto err;
+		}
+		sk_X509_NAME_ENTRY_free(entries);
+	}
+	sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
+	ret = x509_name_canon(nm.x);
+	if (!ret)
+		goto err;
+	nm.x->modified = 0;
+	*val = nm.a;
+	*in = p;
+	return ret;
+
+ err:
+	if (nm.x != NULL)
+		X509_NAME_free(nm.x);
+	ASN1error(ERR_R_NESTED_ASN1_ERROR);
+	return 0;
+}
+
+static int
+x509_name_ex_i2d(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)
+			return ret;
+		ret = x509_name_canon(a);
+		if (ret < 0)
+			return ret;
+	}
+	ret = a->bytes->length;
+	if (out != NULL) {
+		memcpy(*out, a->bytes->data, ret);
+		*out += ret;
+	}
+	return ret;
+}
+
+static void
+local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+	sk_X509_NAME_ENTRY_free(ne);
+}
+
+static void
+local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
+{
+	sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+}
+
+static int
+x509_name_encode(X509_NAME *a)
+{
+	union {
+		STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+		ASN1_VALUE *a;
+	} intname = {NULL};
+	int len;
+	unsigned char *p;
+	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;
+	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+		if (entry->set != set) {
+			entries = sk_X509_NAME_ENTRY_new_null();
+			if (!entries)
+				goto memerr;
+			if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s,
+			    entries))
+				goto memerr;
+			set = entry->set;
+		}
+		if (entries == NULL /* if entry->set is bogusly -1 */ ||
+		    !sk_X509_NAME_ENTRY_push(entries, entry))
+			goto memerr;
+	}
+	len = ASN1_item_ex_i2d(&intname.a, NULL,
+	    &X509_NAME_INTERNAL_it, -1, -1);
+	if (!BUF_MEM_grow(a->bytes, len))
+		goto memerr;
+	p = (unsigned char *)a->bytes->data;
+	ASN1_item_ex_i2d(&intname.a, &p, &X509_NAME_INTERNAL_it,
+	    -1, -1);
+	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+	    local_sk_X509_NAME_ENTRY_free);
+	a->modified = 0;
+	return len;
+
+ memerr:
+	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+	    local_sk_X509_NAME_ENTRY_free);
+	ASN1error(ERR_R_MALLOC_FAILURE);
+	return -1;
+}
+
+static int
+x509_name_ex_print(BIO *out, ASN1_VALUE **pval, int indent, const char *fname,
+    const ASN1_PCTX *pctx)
+{
+	if (X509_NAME_print_ex(out, (X509_NAME *)*pval, indent,
+	    pctx->nm_flags) <= 0)
+		return 0;
+	return 2;
+}
+
+/* This function generates the canonical encoding of the Name structure.
+ * In it all strings are converted to UTF8, leading, trailing and
+ * multiple spaces collapsed, converted to lower case and the leading
+ * SEQUENCE header removed.
+ *
+ * In future we could also normalize the UTF8 too.
+ *
+ * By doing this 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().
+ */
+
+static int
+x509_name_canon(X509_NAME *a)
+{
+	unsigned char *p;
+	STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+	STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+	X509_NAME_ENTRY *entry, *tmpentry = NULL;
+	int i, len, set = -1, ret = 0;
+
+	if (a->canon_enc) {
+		free(a->canon_enc);
+		a->canon_enc = NULL;
+	}
+	/* Special case: empty X509_NAME => null encoding */
+	if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
+		a->canon_enclen = 0;
+		return 1;
+	}
+	intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+	if (!intname)
+		goto err;
+	for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+		if (entry->set != set) {
+			entries = sk_X509_NAME_ENTRY_new_null();
+			if (!entries)
+				goto err;
+			if (sk_STACK_OF_X509_NAME_ENTRY_push(intname,
+			    entries) == 0) {
+				sk_X509_NAME_ENTRY_free(entries);
+				goto err;
+			}
+			set = entry->set;
+		}
+		tmpentry = X509_NAME_ENTRY_new();
+		if (tmpentry == NULL)
+			goto err;
+		tmpentry->object = OBJ_dup(entry->object);
+		if (tmpentry->object == NULL)
+			goto err;
+		if (!asn1_string_canon(tmpentry->value, entry->value))
+			goto err;
+		if (entries == NULL /* if entry->set is bogusly -1 */ ||
+		    !sk_X509_NAME_ENTRY_push(entries, tmpentry))
+			goto err;
+		tmpentry = NULL;
+	}
+
+	/* Finally generate encoding */
+	len = i2d_name_canon(intname, NULL);
+	if (len < 0)
+		goto err;
+	p = malloc(len);
+	if (p == NULL)
+		goto err;
+	a->canon_enc = p;
+	a->canon_enclen = len;
+	i2d_name_canon(intname, &p);
+	ret = 1;
+
+ err:
+	if (tmpentry)
+		X509_NAME_ENTRY_free(tmpentry);
+	if (intname)
+		sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
+		    local_sk_X509_NAME_ENTRY_pop_free);
+	return ret;
+}
+
+/* Bitmap of all the types of string that will be canonicalized. */
+
+#define ASN1_MASK_CANON	\
+	(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
+	| B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
+	| B_ASN1_VISIBLESTRING)
+
+
+static int
+asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
+{
+	unsigned char *to, *from;
+	int len, i;
+
+	/* If type not in bitmask just copy string across */
+	if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
+		if (!ASN1_STRING_copy(out, in))
+			return 0;
+		return 1;
+	}
+
+	out->type = V_ASN1_UTF8STRING;
+	out->length = ASN1_STRING_to_UTF8(&out->data, in);
+	if (out->length == -1)
+		return 0;
+
+	to = out->data;
+	from = to;
+
+	len = out->length;
+
+	/* Convert string in place to canonical form.
+	 * Ultimately we may need to handle a wider range of characters
+	 * but for now ignore anything with MSB set and rely on the
+	 * isspace() and tolower() functions.
+	 */
+
+	/* Ignore leading spaces */
+	while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
+		from++;
+		len--;
+	}
+
+	to = from + len - 1;
+
+	/* Ignore trailing spaces */
+	while ((len > 0) && !(*to & 0x80) && isspace(*to)) {
+		to--;
+		len--;
+	}
+
+	to = out->data;
+
+	i = 0;
+	while (i < len) {
+		/* If MSB set just copy across */
+		if (*from & 0x80) {
+			*to++ = *from++;
+			i++;
+		}
+		/* Collapse multiple spaces */
+		else if (isspace(*from)) {
+			/* Copy one space across */
+			*to++ = ' ';
+			/* Ignore subsequent spaces. Note: don't need to
+			 * check len here because we know the last
+			 * character is a non-space so we can't overflow.
+			 */
+			do {
+				from++;
+				i++;
+			} while (!(*from & 0x80) && isspace(*from));
+		} else {
+			*to++ = tolower(*from);
+			from++;
+			i++;
+		}
+	}
+
+	out->length = to - out->data;
+
+	return 1;
+}
+
+static int
+i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname, unsigned char **in)
+{
+	int i, len, ltmp;
+	ASN1_VALUE *v;
+	STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
+
+	len = 0;
+	for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
+		v = sk_ASN1_VALUE_value(intname, i);
+		ltmp = ASN1_item_ex_i2d(&v, in,
+		    &X509_NAME_ENTRIES_it, -1, -1);
+		if (ltmp < 0)
+			return ltmp;
+		len += ltmp;
+	}
+	return len;
+}
+
+int
+X509_NAME_set(X509_NAME **xn, X509_NAME *name)
+{
+	if (*xn == name)
+		return *xn != NULL;
+	if ((name = X509_NAME_dup(name)) == NULL)
+		return 0;
+	X509_NAME_free(*xn);
+	*xn = name;
+	return 1;
+}
+
+int
+X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, size_t *pderlen)
+{
+	/* Make sure encoding is valid. */
+	if (i2d_X509_NAME(nm, NULL) <= 0)
+		return 0;
+	if (pder != NULL)
+		*pder = (unsigned char *)nm->bytes->data;
+	if (pderlen != NULL)
+		*pderlen = nm->bytes->length;
+	return 1;
+}
diff --git a/crypto/asn1/x_pkey.c b/crypto/asn1/x_pkey.c
new file mode 100644
index 0000000..c4964fc
--- /dev/null
+++ b/crypto/asn1/x_pkey.c
@@ -0,0 +1,121 @@
+/* $OpenBSD: x_pkey.c,v 1.23 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+X509_PKEY *
+X509_PKEY_new(void)
+{
+	X509_PKEY *ret = NULL;
+
+	if ((ret = malloc(sizeof(X509_PKEY))) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	ret->version = 0;
+	if ((ret->enc_algor = X509_ALGOR_new()) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if ((ret->enc_pkey = ASN1_OCTET_STRING_new()) == NULL) {
+		ASN1error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	ret->dec_pkey = NULL;
+	ret->key_length = 0;
+	ret->key_data = NULL;
+	ret->key_free = 0;
+	ret->cipher.cipher = NULL;
+	memset(ret->cipher.iv, 0, EVP_MAX_IV_LENGTH);
+	ret->references = 1;
+	return (ret);
+
+ err:
+	if (ret) {
+		X509_ALGOR_free(ret->enc_algor);
+		free(ret);
+	}
+	return NULL;
+}
+
+void
+X509_PKEY_free(X509_PKEY *x)
+{
+	int i;
+
+	if (x == NULL)
+		return;
+
+	i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_X509_PKEY);
+	if (i > 0)
+		return;
+
+	if (x->enc_algor != NULL)
+		X509_ALGOR_free(x->enc_algor);
+	ASN1_OCTET_STRING_free(x->enc_pkey);
+	EVP_PKEY_free(x->dec_pkey);
+	if ((x->key_data != NULL) && (x->key_free))
+		free(x->key_data);
+	free(x);
+}
diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c
new file mode 100644
index 0000000..0534edc
--- /dev/null
+++ b/crypto/asn1/x_pubkey.c
@@ -0,0 +1,741 @@
+/* $OpenBSD: x_pubkey.c,v 1.35 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+#include "x509_local.h"
+
+/* Minor tweak to operation: free up EVP_PKEY */
+static int
+pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_FREE_POST) {
+		X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
+		EVP_PKEY_free(pubkey->pkey);
+	}
+	return 1;
+}
+
+static const ASN1_AUX X509_PUBKEY_aux = {
+	.asn1_cb = pubkey_cb,
+};
+static const ASN1_TEMPLATE X509_PUBKEY_seq_tt[] = {
+	{
+		.offset = offsetof(X509_PUBKEY, algor),
+		.field_name = "algor",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_PUBKEY, public_key),
+		.field_name = "public_key",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_PUBKEY_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_PUBKEY_seq_tt,
+	.tcount = sizeof(X509_PUBKEY_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_PUBKEY_aux,
+	.size = sizeof(X509_PUBKEY),
+	.sname = "X509_PUBKEY",
+};
+
+X509_PUBKEY *
+d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len)
+{
+	return (X509_PUBKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_PUBKEY_it);
+}
+
+int
+i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_PUBKEY_it);
+}
+
+X509_PUBKEY *
+X509_PUBKEY_new(void)
+{
+	return (X509_PUBKEY *)ASN1_item_new(&X509_PUBKEY_it);
+}
+
+void
+X509_PUBKEY_free(X509_PUBKEY *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_PUBKEY_it);
+}
+
+int
+X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
+{
+	X509_PUBKEY *pk = NULL;
+
+	if (x == NULL)
+		return (0);
+	if ((pk = X509_PUBKEY_new()) == NULL)
+		goto error;
+
+	if (pkey->ameth) {
+		if (pkey->ameth->pub_encode) {
+			if (!pkey->ameth->pub_encode(pk, pkey)) {
+				X509error(X509_R_PUBLIC_KEY_ENCODE_ERROR);
+				goto error;
+			}
+		} else {
+			X509error(X509_R_METHOD_NOT_SUPPORTED);
+			goto error;
+		}
+	} else {
+		X509error(X509_R_UNSUPPORTED_ALGORITHM);
+		goto error;
+	}
+
+	if (*x != NULL)
+		X509_PUBKEY_free(*x);
+
+	*x = pk;
+
+	return 1;
+
+ error:
+	if (pk != NULL)
+		X509_PUBKEY_free(pk);
+	return 0;
+}
+
+EVP_PKEY *
+X509_PUBKEY_get0(X509_PUBKEY *key)
+{
+	EVP_PKEY *ret = NULL;
+
+	if (key == NULL)
+		goto error;
+
+	if (key->pkey != NULL)
+		return key->pkey;
+
+	if (key->public_key == NULL)
+		goto error;
+
+	if ((ret = EVP_PKEY_new()) == NULL) {
+		X509error(ERR_R_MALLOC_FAILURE);
+		goto error;
+	}
+
+	if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) {
+		X509error(X509_R_UNSUPPORTED_ALGORITHM);
+		goto error;
+	}
+
+	if (ret->ameth->pub_decode) {
+		if (!ret->ameth->pub_decode(ret, key)) {
+			X509error(X509_R_PUBLIC_KEY_DECODE_ERROR);
+			goto error;
+		}
+	} else {
+		X509error(X509_R_METHOD_NOT_SUPPORTED);
+		goto error;
+	}
+
+	/* Check to see if another thread set key->pkey first */
+	CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
+	if (key->pkey) {
+		CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+		EVP_PKEY_free(ret);
+		ret = key->pkey;
+	} else {
+		key->pkey = ret;
+		CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+	}
+
+	return ret;
+
+ error:
+	EVP_PKEY_free(ret);
+	return (NULL);
+}
+
+EVP_PKEY *
+X509_PUBKEY_get(X509_PUBKEY *key)
+{
+	EVP_PKEY *pkey;
+
+	if ((pkey = X509_PUBKEY_get0(key)) == NULL)
+		return (NULL);
+
+	CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+
+	return pkey;
+}
+
+/*
+ * Decode an X509_PUBKEY into the specified key type.
+ */
+static int
+pubkey_ex_d2i(int pkey_type, ASN1_VALUE **pval, const unsigned char **in,
+    long len, const ASN1_ITEM *it)
+{
+	const ASN1_EXTERN_FUNCS *ef = it->funcs;
+	const unsigned char *p = *in;
+	X509_PUBKEY *xpk = NULL;
+	ASN1_VALUE *key = NULL;
+	EVP_PKEY *pkey = NULL;
+	int ret = 0;
+
+	if ((xpk = d2i_X509_PUBKEY(NULL, &p, len)) == NULL)
+		goto err;
+	if ((pkey = X509_PUBKEY_get(xpk)) == NULL)
+		goto err;
+
+	switch (pkey_type) {
+	case EVP_PKEY_NONE:
+		key = (ASN1_VALUE *)pkey;
+		pkey = NULL;
+		break;
+
+	case EVP_PKEY_DSA:
+		key = (ASN1_VALUE *)EVP_PKEY_get1_DSA(pkey);
+		break;
+
+	case EVP_PKEY_RSA:
+		key = (ASN1_VALUE *)EVP_PKEY_get1_RSA(pkey);
+		break;
+
+	case EVP_PKEY_EC:
+		key = (ASN1_VALUE *)EVP_PKEY_get1_EC_KEY(pkey);
+		break;
+
+	default:
+		goto err;
+	}
+
+	if (key == NULL)
+		goto err;
+
+	ef->asn1_ex_free(pval, it);
+
+	*pval = key;
+	*in = p;
+	ret = 1;
+
+ err:
+	EVP_PKEY_free(pkey);
+	X509_PUBKEY_free(xpk);
+
+	return ret;
+}
+
+/*
+ * Encode the specified key type into an X509_PUBKEY.
+ */
+static int
+pubkey_ex_i2d(int pkey_type, ASN1_VALUE **pval, unsigned char **out,
+    const ASN1_ITEM *it)
+{
+	X509_PUBKEY *xpk = NULL;
+	EVP_PKEY *pkey, *pktmp;
+	int ret = -1;
+
+	if ((pkey = pktmp = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	switch (pkey_type) {
+	case EVP_PKEY_NONE:
+		pkey = (EVP_PKEY *)*pval;
+		break;
+
+	case EVP_PKEY_DSA:
+		if (!EVP_PKEY_set1_DSA(pkey, (DSA *)*pval))
+			goto err;
+		break;
+
+	case EVP_PKEY_RSA:
+		if (!EVP_PKEY_set1_RSA(pkey, (RSA *)*pval))
+			goto err;
+		break;
+
+	case EVP_PKEY_EC:
+		if (!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY*)*pval))
+			goto err;
+		break;
+
+	default:
+		goto err;
+	}
+
+	if (!X509_PUBKEY_set(&xpk, pkey))
+		goto err;
+
+	ret = i2d_X509_PUBKEY(xpk, out);
+
+ err:
+	EVP_PKEY_free(pktmp);
+	X509_PUBKEY_free(xpk);
+
+	return ret;
+}
+
+static int
+pkey_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if ((*pval = (ASN1_VALUE *)EVP_PKEY_new()) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static void
+pkey_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	EVP_PKEY_free((EVP_PKEY *)*pval);
+	*pval = NULL;
+}
+
+static int
+pkey_pubkey_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 pubkey_ex_d2i(EVP_PKEY_NONE, pval, in, len, it);
+}
+
+static int
+pkey_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
+    int tag, int aclass)
+{
+	return pubkey_ex_i2d(EVP_PKEY_NONE, pval, out, it);
+}
+
+const ASN1_EXTERN_FUNCS pkey_pubkey_asn1_ff = {
+	.app_data = NULL,
+	.asn1_ex_new = pkey_pubkey_ex_new,
+	.asn1_ex_free = pkey_pubkey_ex_free,
+	.asn1_ex_clear = NULL,
+	.asn1_ex_d2i = pkey_pubkey_ex_d2i,
+	.asn1_ex_i2d = pkey_pubkey_ex_i2d,
+	.asn1_ex_print = NULL,
+};
+
+const ASN1_ITEM EVP_PKEY_PUBKEY_it = {
+	.itype = ASN1_ITYPE_EXTERN,
+	.utype = 0,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &pkey_pubkey_asn1_ff,
+	.size = 0,
+	.sname = NULL,
+};
+
+EVP_PKEY *
+d2i_PUBKEY(EVP_PKEY **pkey, const unsigned char **in, long len)
+{
+	return (EVP_PKEY *)ASN1_item_d2i((ASN1_VALUE **)pkey, in, len,
+	    &EVP_PKEY_PUBKEY_it);
+}
+
+int
+i2d_PUBKEY(EVP_PKEY *pkey, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)pkey, out, &EVP_PKEY_PUBKEY_it);
+}
+
+EVP_PKEY *
+d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **pkey)
+{
+	return (EVP_PKEY *)ASN1_item_d2i_bio(&EVP_PKEY_PUBKEY_it, bp,
+	    (ASN1_VALUE **)pkey);
+}
+
+int
+i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
+{
+	return ASN1_item_i2d_bio(&EVP_PKEY_PUBKEY_it, bp, (ASN1_VALUE *)pkey);
+}
+
+EVP_PKEY *
+d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **pkey)
+{
+	return (EVP_PKEY *)ASN1_item_d2i_fp(&EVP_PKEY_PUBKEY_it, fp,
+	    (ASN1_VALUE **)pkey);
+}
+
+int
+i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
+{
+	return ASN1_item_i2d_fp(&EVP_PKEY_PUBKEY_it, fp, (ASN1_VALUE *)pkey);
+}
+
+/*
+ * The following are equivalents but which return RSA and DSA keys.
+ */
+#ifndef OPENSSL_NO_RSA
+
+static int
+rsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if ((*pval = (ASN1_VALUE *)RSA_new()) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static void
+rsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	RSA_free((RSA *)*pval);
+	*pval = NULL;
+}
+
+static int
+rsa_pubkey_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 pubkey_ex_d2i(EVP_PKEY_RSA, pval, in, len, it);
+}
+
+static int
+rsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
+    int tag, int aclass)
+{
+	return pubkey_ex_i2d(EVP_PKEY_RSA, pval, out, it);
+}
+
+const ASN1_EXTERN_FUNCS rsa_pubkey_asn1_ff = {
+	.app_data = NULL,
+	.asn1_ex_new = rsa_pubkey_ex_new,
+	.asn1_ex_free = rsa_pubkey_ex_free,
+	.asn1_ex_clear = NULL,
+	.asn1_ex_d2i = rsa_pubkey_ex_d2i,
+	.asn1_ex_i2d = rsa_pubkey_ex_i2d,
+	.asn1_ex_print = NULL,
+};
+
+const ASN1_ITEM RSA_PUBKEY_it = {
+	.itype = ASN1_ITYPE_EXTERN,
+	.utype = 0,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &rsa_pubkey_asn1_ff,
+	.size = 0,
+	.sname = NULL,
+};
+
+RSA *
+d2i_RSA_PUBKEY(RSA **rsa, const unsigned char **in, long len)
+{
+	return (RSA *)ASN1_item_d2i((ASN1_VALUE **)rsa, in, len,
+	    &RSA_PUBKEY_it);
+}
+
+int
+i2d_RSA_PUBKEY(RSA *rsa, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)rsa, out, &RSA_PUBKEY_it);
+}
+
+RSA *
+d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
+{
+	return (RSA *)ASN1_item_d2i_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE **)rsa);
+}
+
+int
+i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
+{
+	return ASN1_item_i2d_bio(&RSA_PUBKEY_it, bp, (ASN1_VALUE *)rsa);
+}
+
+RSA *
+d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
+{
+	return (RSA *)ASN1_item_d2i_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE **)rsa);
+}
+
+int
+i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
+{
+	return ASN1_item_i2d_fp(&RSA_PUBKEY_it, fp, (ASN1_VALUE *)rsa);
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+static int
+dsa_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if ((*pval = (ASN1_VALUE *)DSA_new()) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static void
+dsa_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	DSA_free((DSA *)*pval);
+	*pval = NULL;
+}
+
+static int
+dsa_pubkey_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 pubkey_ex_d2i(EVP_PKEY_DSA, pval, in, len, it);
+}
+
+static int
+dsa_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
+    int tag, int aclass)
+{
+	return pubkey_ex_i2d(EVP_PKEY_DSA, pval, out, it);
+}
+
+const ASN1_EXTERN_FUNCS dsa_pubkey_asn1_ff = {
+	.app_data = NULL,
+	.asn1_ex_new = dsa_pubkey_ex_new,
+	.asn1_ex_free = dsa_pubkey_ex_free,
+	.asn1_ex_clear = NULL,
+	.asn1_ex_d2i = dsa_pubkey_ex_d2i,
+	.asn1_ex_i2d = dsa_pubkey_ex_i2d,
+	.asn1_ex_print = NULL,
+};
+
+const ASN1_ITEM DSA_PUBKEY_it = {
+	.itype = ASN1_ITYPE_EXTERN,
+	.utype = 0,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &dsa_pubkey_asn1_ff,
+	.size = 0,
+	.sname = NULL,
+};
+
+DSA *
+d2i_DSA_PUBKEY(DSA **dsa, const unsigned char **in, long len)
+{
+	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)dsa, in, len,
+	    &DSA_PUBKEY_it);
+}
+
+int
+i2d_DSA_PUBKEY(DSA *dsa, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)dsa, out, &DSA_PUBKEY_it);
+}
+
+DSA *
+d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
+{
+	return (DSA *)ASN1_item_d2i_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE **)dsa);
+}
+
+int
+i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
+{
+	return ASN1_item_i2d_bio(&DSA_PUBKEY_it, bp, (ASN1_VALUE *)dsa);
+}
+
+DSA *
+d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
+{
+	return (DSA *)ASN1_item_d2i_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE **)dsa);
+}
+
+int
+i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
+{
+	return ASN1_item_i2d_fp(&DSA_PUBKEY_it, fp, (ASN1_VALUE *)dsa);
+}
+
+#endif
+
+#ifndef OPENSSL_NO_EC
+
+static int
+ec_pubkey_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	if ((*pval = (ASN1_VALUE *)EC_KEY_new()) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static void
+ec_pubkey_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+	EC_KEY_free((EC_KEY *)*pval);
+	*pval = NULL;
+}
+
+static int
+ec_pubkey_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 pubkey_ex_d2i(EVP_PKEY_EC, pval, in, len, it);
+}
+
+static int
+ec_pubkey_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it,
+    int tag, int aclass)
+{
+	return pubkey_ex_i2d(EVP_PKEY_EC, pval, out, it);
+}
+
+const ASN1_EXTERN_FUNCS ec_pubkey_asn1_ff = {
+	.app_data = NULL,
+	.asn1_ex_new = ec_pubkey_ex_new,
+	.asn1_ex_free = ec_pubkey_ex_free,
+	.asn1_ex_clear = NULL,
+	.asn1_ex_d2i = ec_pubkey_ex_d2i,
+	.asn1_ex_i2d = ec_pubkey_ex_i2d,
+	.asn1_ex_print = NULL,
+};
+
+const ASN1_ITEM EC_PUBKEY_it = {
+	.itype = ASN1_ITYPE_EXTERN,
+	.utype = 0,
+	.templates = NULL,
+	.tcount = 0,
+	.funcs = &ec_pubkey_asn1_ff,
+	.size = 0,
+	.sname = NULL,
+};
+
+EC_KEY *
+d2i_EC_PUBKEY(EC_KEY **ec, const unsigned char **in, long len)
+{
+	return (EC_KEY *)ASN1_item_d2i((ASN1_VALUE **)ec, in, len,
+	    &EC_PUBKEY_it);
+}
+
+int
+i2d_EC_PUBKEY(EC_KEY *ec, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)ec, out, &EC_PUBKEY_it);
+}
+
+EC_KEY *
+d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **ec)
+{
+	return (EC_KEY *)ASN1_item_d2i_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE **)ec);
+}
+
+int
+i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ec)
+{
+	return ASN1_item_i2d_bio(&EC_PUBKEY_it, bp, (ASN1_VALUE *)ec);
+}
+
+EC_KEY *
+d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **ec)
+{
+	return (EC_KEY *)ASN1_item_d2i_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE **)ec);
+}
+
+int
+i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *ec)
+{
+	return ASN1_item_i2d_fp(&EC_PUBKEY_it, fp, (ASN1_VALUE *)ec);
+}
+#endif
+
+int
+X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, int ptype,
+    void *pval, unsigned char *penc, int penclen)
+{
+	if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
+		return 0;
+
+	if (penc == NULL)
+		return 1;
+
+	ASN1_STRING_set0(pub->public_key, penc, penclen);
+
+	return asn1_abs_set_unused_bits(pub->public_key, 0);
+}
+
+int
+X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, const unsigned char **pk,
+    int *ppklen, X509_ALGOR **pa, X509_PUBKEY *pub)
+{
+	if (ppkalg)
+		*ppkalg = pub->algor->algorithm;
+	if (pk) {
+		*pk = pub->public_key->data;
+		*ppklen = pub->public_key->length;
+	}
+	if (pa)
+		*pa = pub->algor;
+	return 1;
+}
diff --git a/crypto/asn1/x_req.c b/crypto/asn1/x_req.c
new file mode 100644
index 0000000..9a6f0c7
--- /dev/null
+++ b/crypto/asn1/x_req.c
@@ -0,0 +1,245 @@
+/* $OpenBSD: x_req.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "x509_local.h"
+
+/* X509_REQ_INFO is handled in an unusual way to get round
+ * invalid encodings. Some broken certificate requests don't
+ * encode the attributes field if it is empty. This is in
+ * violation of PKCS#10 but we need to tolerate it. We do
+ * this by making the attributes field OPTIONAL then using
+ * the callback to initialise it to an empty STACK.
+ *
+ * This means that the field will be correctly encoded unless
+ * we NULL out the field.
+ *
+ * As a result we no longer need the req_kludge field because
+ * the information is now contained in the attributes field:
+ * 1. If it is NULL then it's the invalid omission.
+ * 2. If it is empty it is the correct encoding.
+ * 3. If it is not empty then some attributes are present.
+ *
+ */
+
+static int
+rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
+
+	if (operation == ASN1_OP_NEW_POST) {
+		rinf->attributes = sk_X509_ATTRIBUTE_new_null();
+		if (!rinf->attributes)
+			return 0;
+	}
+	return 1;
+}
+
+static const ASN1_AUX X509_REQ_INFO_aux = {
+	.flags = ASN1_AFLG_ENCODING,
+	.asn1_cb = rinf_cb,
+	.enc_offset = offsetof(X509_REQ_INFO, enc),
+};
+static const ASN1_TEMPLATE X509_REQ_INFO_seq_tt[] = {
+	{
+		.offset = offsetof(X509_REQ_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(X509_REQ_INFO, subject),
+		.field_name = "subject",
+		.item = &X509_NAME_it,
+	},
+	{
+		.offset = offsetof(X509_REQ_INFO, pubkey),
+		.field_name = "pubkey",
+		.item = &X509_PUBKEY_it,
+	},
+	/* This isn't really OPTIONAL but it gets round invalid
+	 * encodings
+	 */
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_REQ_INFO, attributes),
+		.field_name = "attributes",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM X509_REQ_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_REQ_INFO_seq_tt,
+	.tcount = sizeof(X509_REQ_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_REQ_INFO_aux,
+	.size = sizeof(X509_REQ_INFO),
+	.sname = "X509_REQ_INFO",
+};
+
+
+X509_REQ_INFO *
+d2i_X509_REQ_INFO(X509_REQ_INFO **a, const unsigned char **in, long len)
+{
+	return (X509_REQ_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_REQ_INFO_it);
+}
+
+int
+i2d_X509_REQ_INFO(X509_REQ_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REQ_INFO_it);
+}
+
+X509_REQ_INFO *
+X509_REQ_INFO_new(void)
+{
+	return (X509_REQ_INFO *)ASN1_item_new(&X509_REQ_INFO_it);
+}
+
+void
+X509_REQ_INFO_free(X509_REQ_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_REQ_INFO_it);
+}
+
+static const ASN1_AUX X509_REQ_aux = {
+	.app_data = NULL,
+	.flags = ASN1_AFLG_REFCOUNT,
+	.ref_offset = offsetof(X509_REQ, references),
+	.ref_lock = CRYPTO_LOCK_X509_REQ,
+};
+static const ASN1_TEMPLATE X509_REQ_seq_tt[] = {
+	{
+		.offset = offsetof(X509_REQ, req_info),
+		.field_name = "req_info",
+		.item = &X509_REQ_INFO_it,
+	},
+	{
+		.offset = offsetof(X509_REQ, sig_alg),
+		.field_name = "sig_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_REQ, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_REQ_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_REQ_seq_tt,
+	.tcount = sizeof(X509_REQ_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_REQ_aux,
+	.size = sizeof(X509_REQ),
+	.sname = "X509_REQ",
+};
+
+
+X509_REQ *
+d2i_X509_REQ(X509_REQ **a, const unsigned char **in, long len)
+{
+	return (X509_REQ *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_REQ_it);
+}
+
+int
+i2d_X509_REQ(X509_REQ *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REQ_it);
+}
+
+X509_REQ *
+X509_REQ_new(void)
+{
+	return (X509_REQ *)ASN1_item_new(&X509_REQ_it);
+}
+
+void
+X509_REQ_free(X509_REQ *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_REQ_it);
+}
+
+X509_REQ *
+X509_REQ_dup(X509_REQ *x)
+{
+	return ASN1_item_dup(&X509_REQ_it, x);
+}
+
+int
+X509_REQ_get_signature_nid(const X509_REQ *req)
+{
+	return OBJ_obj2nid(req->sig_alg->algorithm);
+}
+
+void
+X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
+    const X509_ALGOR **palg)
+{
+	if (psig != NULL)
+		*psig = req->signature;
+	if (palg != NULL)
+		*palg = req->sig_alg;
+}
diff --git a/crypto/asn1/x_sig.c b/crypto/asn1/x_sig.c
new file mode 100644
index 0000000..c55de71
--- /dev/null
+++ b/crypto/asn1/x_sig.c
@@ -0,0 +1,131 @@
+/* $OpenBSD: x_sig.c,v 1.16 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "x509_local.h"
+
+static const ASN1_TEMPLATE X509_SIG_seq_tt[] = {
+	{
+		.offset = offsetof(X509_SIG, algor),
+		.field_name = "algor",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_SIG, digest),
+		.field_name = "digest",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_SIG_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_SIG_seq_tt,
+	.tcount = sizeof(X509_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_SIG),
+	.sname = "X509_SIG",
+};
+
+
+X509_SIG *
+d2i_X509_SIG(X509_SIG **a, const unsigned char **in, long len)
+{
+	return (X509_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_SIG_it);
+}
+
+int
+i2d_X509_SIG(X509_SIG *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_SIG_it);
+}
+
+X509_SIG *
+X509_SIG_new(void)
+{
+	return (X509_SIG *)ASN1_item_new(&X509_SIG_it);
+}
+
+void
+X509_SIG_free(X509_SIG *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_SIG_it);
+}
+
+void
+X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg,
+    const ASN1_OCTET_STRING **pdigest)
+{
+	if (palg != NULL)
+		*palg = sig->algor;
+	if (pdigest != NULL)
+		*pdigest = sig->digest;
+}
+
+void
+X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, ASN1_OCTET_STRING **pdigest)
+{
+	if (palg != NULL)
+		*palg = sig->algor;
+	if (pdigest != NULL)
+		*pdigest = sig->digest;
+}
diff --git a/crypto/asn1/x_spki.c b/crypto/asn1/x_spki.c
new file mode 100644
index 0000000..ef60533
--- /dev/null
+++ b/crypto/asn1/x_spki.c
@@ -0,0 +1,174 @@
+/* $OpenBSD: x_spki.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+ /* This module was send to me my Pat Richards  who
+  * wrote it.  It is under my Copyright with his permission
+  */
+
+#include 
+
+#include 
+#include 
+
+static const ASN1_TEMPLATE NETSCAPE_SPKAC_seq_tt[] = {
+	{
+		.offset = offsetof(NETSCAPE_SPKAC, pubkey),
+		.field_name = "pubkey",
+		.item = &X509_PUBKEY_it,
+	},
+	{
+		.offset = offsetof(NETSCAPE_SPKAC, challenge),
+		.field_name = "challenge",
+		.item = &ASN1_IA5STRING_it,
+	},
+};
+
+const ASN1_ITEM NETSCAPE_SPKAC_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = NETSCAPE_SPKAC_seq_tt,
+	.tcount = sizeof(NETSCAPE_SPKAC_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(NETSCAPE_SPKAC),
+	.sname = "NETSCAPE_SPKAC",
+};
+
+
+NETSCAPE_SPKAC *
+d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **a, const unsigned char **in, long len)
+{
+	return (NETSCAPE_SPKAC *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &NETSCAPE_SPKAC_it);
+}
+
+int
+i2d_NETSCAPE_SPKAC(NETSCAPE_SPKAC *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_SPKAC_it);
+}
+
+NETSCAPE_SPKAC *
+NETSCAPE_SPKAC_new(void)
+{
+	return (NETSCAPE_SPKAC *)ASN1_item_new(&NETSCAPE_SPKAC_it);
+}
+
+void
+NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_SPKAC_it);
+}
+
+static const ASN1_TEMPLATE NETSCAPE_SPKI_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(NETSCAPE_SPKI, spkac),
+		.field_name = "spkac",
+		.item = &NETSCAPE_SPKAC_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(NETSCAPE_SPKI, sig_algor),
+		.field_name = "sig_algor",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(NETSCAPE_SPKI, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM NETSCAPE_SPKI_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = NETSCAPE_SPKI_seq_tt,
+	.tcount = sizeof(NETSCAPE_SPKI_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(NETSCAPE_SPKI),
+	.sname = "NETSCAPE_SPKI",
+};
+
+
+NETSCAPE_SPKI *
+d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **a, const unsigned char **in, long len)
+{
+	return (NETSCAPE_SPKI *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &NETSCAPE_SPKI_it);
+}
+
+int
+i2d_NETSCAPE_SPKI(NETSCAPE_SPKI *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &NETSCAPE_SPKI_it);
+}
+
+NETSCAPE_SPKI *
+NETSCAPE_SPKI_new(void)
+{
+	return (NETSCAPE_SPKI *)ASN1_item_new(&NETSCAPE_SPKI_it);
+}
+
+void
+NETSCAPE_SPKI_free(NETSCAPE_SPKI *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &NETSCAPE_SPKI_it);
+}
diff --git a/crypto/asn1/x_val.c b/crypto/asn1/x_val.c
new file mode 100644
index 0000000..a9c9c48
--- /dev/null
+++ b/crypto/asn1/x_val.c
@@ -0,0 +1,110 @@
+/* $OpenBSD: x_val.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+
+static const ASN1_TEMPLATE X509_VAL_seq_tt[] = {
+	{
+		.offset = offsetof(X509_VAL, notBefore),
+		.field_name = "notBefore",
+		.item = &ASN1_TIME_it,
+	},
+	{
+		.offset = offsetof(X509_VAL, notAfter),
+		.field_name = "notAfter",
+		.item = &ASN1_TIME_it,
+	},
+};
+
+const ASN1_ITEM X509_VAL_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_VAL_seq_tt,
+	.tcount = sizeof(X509_VAL_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_VAL),
+	.sname = "X509_VAL",
+};
+
+
+X509_VAL *
+d2i_X509_VAL(X509_VAL **a, const unsigned char **in, long len)
+{
+	return (X509_VAL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_VAL_it);
+}
+
+int
+i2d_X509_VAL(X509_VAL *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_VAL_it);
+}
+
+X509_VAL *
+X509_VAL_new(void)
+{
+	return (X509_VAL *)ASN1_item_new(&X509_VAL_it);
+}
+
+void
+X509_VAL_free(X509_VAL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_VAL_it);
+}
diff --git a/crypto/asn1/x_x509.c b/crypto/asn1/x_x509.c
new file mode 100644
index 0000000..08e4dba
--- /dev/null
+++ b/crypto/asn1/x_x509.c
@@ -0,0 +1,376 @@
+/* $OpenBSD: x_x509.c,v 1.37 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+static const ASN1_AUX X509_CINF_aux = {
+	.flags = ASN1_AFLG_ENCODING,
+	.enc_offset = offsetof(X509_CINF, enc),
+};
+static const ASN1_TEMPLATE X509_CINF_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CINF, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, serialNumber),
+		.field_name = "serialNumber",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, signature),
+		.field_name = "signature",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, issuer),
+		.field_name = "issuer",
+		.item = &X509_NAME_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, validity),
+		.field_name = "validity",
+		.item = &X509_VAL_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, subject),
+		.field_name = "subject",
+		.item = &X509_NAME_it,
+	},
+	{
+		.offset = offsetof(X509_CINF, key),
+		.field_name = "key",
+		.item = &X509_PUBKEY_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(X509_CINF, issuerUID),
+		.field_name = "issuerUID",
+		.item = &ASN1_BIT_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(X509_CINF, subjectUID),
+		.field_name = "subjectUID",
+		.item = &ASN1_BIT_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF |
+		    ASN1_TFLG_OPTIONAL,
+		.tag = 3,
+		.offset = offsetof(X509_CINF, extensions),
+		.field_name = "extensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM X509_CINF_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_CINF_seq_tt,
+	.tcount = sizeof(X509_CINF_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_CINF_aux,
+	.size = sizeof(X509_CINF),
+	.sname = "X509_CINF",
+};
+
+
+X509_CINF *
+d2i_X509_CINF(X509_CINF **a, const unsigned char **in, long len)
+{
+	return (X509_CINF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_CINF_it);
+}
+
+int
+i2d_X509_CINF(X509_CINF *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CINF_it);
+}
+
+X509_CINF *
+X509_CINF_new(void)
+{
+	return (X509_CINF *)ASN1_item_new(&X509_CINF_it);
+}
+
+void
+X509_CINF_free(X509_CINF *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_CINF_it);
+}
+/* X509 top level structure needs a bit of customisation */
+
+static int
+x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	X509 *ret = (X509 *)*pval;
+
+	switch (operation) {
+
+	case ASN1_OP_NEW_POST:
+		ret->valid = 0;
+		ret->name = NULL;
+		ret->ex_flags = 0;
+		ret->ex_pathlen = -1;
+		ret->skid = NULL;
+		ret->akid = NULL;
+		ret->aux = NULL;
+		ret->crldp = NULL;
+#ifndef OPENSSL_NO_RFC3779
+		ret->rfc3779_addr = NULL;
+		ret->rfc3779_asid = NULL;
+#endif
+		CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+		break;
+
+	case ASN1_OP_D2I_POST:
+		free(ret->name);
+		ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
+		break;
+
+	case ASN1_OP_FREE_POST:
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+		X509_CERT_AUX_free(ret->aux);
+		ASN1_OCTET_STRING_free(ret->skid);
+		AUTHORITY_KEYID_free(ret->akid);
+		CRL_DIST_POINTS_free(ret->crldp);
+		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
+		free(ret->name);
+		ret->name = NULL;
+		break;
+	}
+
+	return 1;
+}
+
+static const ASN1_AUX X509_aux = {
+	.app_data = NULL,
+	.flags = ASN1_AFLG_REFCOUNT,
+	.ref_offset = offsetof(X509, references),
+	.ref_lock = CRYPTO_LOCK_X509,
+	.asn1_cb = x509_cb,
+};
+static const ASN1_TEMPLATE X509_seq_tt[] = {
+	{
+		.offset = offsetof(X509, cert_info),
+		.field_name = "cert_info",
+		.item = &X509_CINF_it,
+	},
+	{
+		.offset = offsetof(X509, sig_alg),
+		.field_name = "sig_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.offset = offsetof(X509, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM X509_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_seq_tt,
+	.tcount = sizeof(X509_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &X509_aux,
+	.size = sizeof(X509),
+	.sname = "X509",
+};
+
+
+X509 *
+d2i_X509(X509 **a, const unsigned char **in, long len)
+{
+	return (X509 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_it);
+}
+
+int
+i2d_X509(X509 *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_it);
+}
+
+X509 *
+X509_new(void)
+{
+	return (X509 *)ASN1_item_new(&X509_it);
+}
+
+void
+X509_free(X509 *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_it);
+}
+
+X509 *
+X509_dup(X509 *x)
+{
+	return ASN1_item_dup(&X509_it, x);
+}
+
+int
+X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp,
+	    new_func, dup_func, free_func);
+}
+
+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)
+{
+	return (CRYPTO_get_ex_data(&r->ex_data, idx));
+}
+
+/* X509_AUX ASN1 routines. X509_AUX is the name given to
+ * a certificate with extra info tagged on the end. Since these
+ * functions set how a certificate is trusted they should only
+ * be used when the certificate comes from a reliable source
+ * such as local storage.
+ *
+ */
+
+X509 *
+d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
+{
+	const unsigned char *q;
+	X509 *ret;
+
+	/* Save start position */
+	q = *pp;
+	ret = d2i_X509(NULL, pp, length);
+	/* If certificate unreadable then forget it */
+	if (!ret)
+		return NULL;
+	/* update length */
+	length -= *pp - q;
+	if (length > 0) {
+		if (!d2i_X509_CERT_AUX(&ret->aux, pp, length))
+			goto err;
+	}
+	if (a != NULL) {
+		X509_free(*a);
+		*a = ret;
+	}
+	return ret;
+
+ err:
+	X509_free(ret);
+	return NULL;
+}
+
+int
+i2d_X509_AUX(X509 *a, unsigned char **pp)
+{
+	int length;
+
+	length = i2d_X509(a, pp);
+	if (a)
+		length += i2d_X509_CERT_AUX(a->aux, pp);
+	return length;
+}
+
+int
+i2d_re_X509_tbs(X509 *x, unsigned char **pp)
+{
+	x->cert_info->enc.modified = 1;
+	return i2d_X509_CINF(x->cert_info, pp);
+}
+
+void
+X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg,
+    const X509 *x)
+{
+	if (psig != NULL)
+		*psig = x->signature;
+	if (palg != NULL)
+		*palg = x->sig_alg;
+}
+
+int
+X509_get_signature_nid(const X509 *x)
+{
+	return OBJ_obj2nid(x->sig_alg->algorithm);
+}
diff --git a/crypto/asn1/x_x509a.c b/crypto/asn1/x_x509a.c
new file mode 100644
index 0000000..2b6fe7f
--- /dev/null
+++ b/crypto/asn1/x_x509a.c
@@ -0,0 +1,274 @@
+/* $OpenBSD: x_x509a.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+/* X509_CERT_AUX routines. These are used to encode additional
+ * user modifiable data about a certificate. This data is
+ * appended to the X509 encoding when the *_X509_AUX routines
+ * are used. This means that the "traditional" X509 routines
+ * will simply ignore the extra data.
+ */
+
+static X509_CERT_AUX *aux_get(X509 *x);
+
+static const ASN1_TEMPLATE X509_CERT_AUX_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CERT_AUX, trust),
+		.field_name = "trust",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF |
+		    ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(X509_CERT_AUX, reject),
+		.field_name = "reject",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CERT_AUX, alias),
+		.field_name = "alias",
+		.item = &ASN1_UTF8STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.offset = offsetof(X509_CERT_AUX, keyid),
+		.field_name = "keyid",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF |
+		    ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(X509_CERT_AUX, other),
+		.field_name = "other",
+		.item = &X509_ALGOR_it,
+	},
+};
+
+const ASN1_ITEM X509_CERT_AUX_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X509_CERT_AUX_seq_tt,
+	.tcount = sizeof(X509_CERT_AUX_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.size = sizeof(X509_CERT_AUX),
+	.sname = "X509_CERT_AUX",
+};
+
+
+X509_CERT_AUX *
+d2i_X509_CERT_AUX(X509_CERT_AUX **a, const unsigned char **in, long len)
+{
+	return (X509_CERT_AUX *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &X509_CERT_AUX_it);
+}
+
+int
+i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CERT_AUX_it);
+}
+
+X509_CERT_AUX *
+X509_CERT_AUX_new(void)
+{
+	return (X509_CERT_AUX *)ASN1_item_new(&X509_CERT_AUX_it);
+}
+
+void
+X509_CERT_AUX_free(X509_CERT_AUX *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X509_CERT_AUX_it);
+}
+
+static X509_CERT_AUX *
+aux_get(X509 *x)
+{
+	if (!x)
+		return NULL;
+	if (!x->aux && !(x->aux = X509_CERT_AUX_new()))
+		return NULL;
+	return x->aux;
+}
+
+int
+X509_alias_set1(X509 *x, const unsigned char *name, int len)
+{
+	X509_CERT_AUX *aux;
+	if (!name) {
+		if (!x || !x->aux || !x->aux->alias)
+			return 1;
+		ASN1_UTF8STRING_free(x->aux->alias);
+		x->aux->alias = NULL;
+		return 1;
+	}
+	if (!(aux = aux_get(x)))
+		return 0;
+	if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new()))
+		return 0;
+	return ASN1_STRING_set(aux->alias, name, len);
+}
+
+int
+X509_keyid_set1(X509 *x, const unsigned char *id, int len)
+{
+	X509_CERT_AUX *aux;
+	if (!id) {
+		if (!x || !x->aux || !x->aux->keyid)
+			return 1;
+		ASN1_OCTET_STRING_free(x->aux->keyid);
+		x->aux->keyid = NULL;
+		return 1;
+	}
+	if (!(aux = aux_get(x)))
+		return 0;
+	if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new()))
+		return 0;
+	return ASN1_STRING_set(aux->keyid, id, len);
+}
+
+unsigned char *
+X509_alias_get0(X509 *x, int *len)
+{
+	if (!x->aux || !x->aux->alias)
+		return NULL;
+	if (len)
+		*len = x->aux->alias->length;
+	return x->aux->alias->data;
+}
+
+unsigned char *
+X509_keyid_get0(X509 *x, int *len)
+{
+	if (!x->aux || !x->aux->keyid)
+		return NULL;
+	if (len)
+		*len = x->aux->keyid->length;
+	return x->aux->keyid->data;
+}
+
+int
+X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj)
+{
+	X509_CERT_AUX *aux;
+	ASN1_OBJECT *objtmp;
+	int rc;
+
+	if (!(objtmp = OBJ_dup(obj)))
+		return 0;
+	if (!(aux = aux_get(x)))
+		goto err;
+	if (!aux->trust && !(aux->trust = sk_ASN1_OBJECT_new_null()))
+		goto err;
+	rc = sk_ASN1_OBJECT_push(aux->trust, objtmp);
+	if (rc != 0)
+		return rc;
+
+ err:
+	ASN1_OBJECT_free(objtmp);
+	return 0;
+}
+
+int
+X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj)
+{
+	X509_CERT_AUX *aux;
+	ASN1_OBJECT *objtmp;
+	int rc;
+
+	if (!(objtmp = OBJ_dup(obj)))
+		return 0;
+	if (!(aux = aux_get(x)))
+		goto err;
+	if (!aux->reject && !(aux->reject = sk_ASN1_OBJECT_new_null()))
+		goto err;
+	rc = sk_ASN1_OBJECT_push(aux->reject, objtmp);
+	if (rc != 0)
+		return rc;
+
+ err:
+	ASN1_OBJECT_free(objtmp);
+	return 0;
+}
+
+void
+X509_trust_clear(X509 *x)
+{
+	if (x->aux && x->aux->trust) {
+		sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
+		x->aux->trust = NULL;
+	}
+}
+
+void
+X509_reject_clear(X509 *x)
+{
+	if (x->aux && x->aux->reject) {
+		sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
+		x->aux->reject = NULL;
+	}
+}
diff --git a/crypto/bf/bf_cfb64.c b/crypto/bf/bf_cfb64.c
new file mode 100644
index 0000000..87dccae
--- /dev/null
+++ b/crypto/bf/bf_cfb64.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: bf_cfb64.c,v 1.8 2022/11/26 16:08:51 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "bf_local.h"
+
+/*
+ * The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+    const BF_KEY *schedule, unsigned char *ivec, int *num, int encrypt)
+{
+	BF_LONG v0, v1, t;
+	int n= *num;
+	long l = length;
+	BF_LONG ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = (unsigned char *)ivec;
+	if (encrypt) {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				BF_encrypt((BF_LONG *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			c= *(in++)^iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1)&0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				BF_encrypt((BF_LONG *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			cc= *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c^cc;
+			n = (n + 1)&0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = t=c = cc = 0;
+	*num = n;
+}
diff --git a/crypto/bf/bf_ecb.c b/crypto/bf/bf_ecb.c
new file mode 100644
index 0000000..eda6f19
--- /dev/null
+++ b/crypto/bf/bf_ecb.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: bf_ecb.c,v 1.10 2023/07/28 10:35:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include "bf_local.h"
+
+/*
+ * Blowfish as implemented from 'Blowfish: Springer-Verlag paper'
+ * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION,
+ * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
+ */
+
+void
+BF_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    const BF_KEY *key, int encrypt)
+{
+	BF_LONG l, d[2];
+
+	n2l(in, l);
+	d[0] = l;
+	n2l(in, l);
+	d[1] = l;
+	if (encrypt)
+		BF_encrypt(d, key);
+	else
+		BF_decrypt(d, key);
+	l = d[0];
+	l2n(l, out);
+	l = d[1];
+	l2n(l, out);
+	l = d[0] = d[1] = 0;
+}
diff --git a/crypto/bf/bf_enc.c b/crypto/bf/bf_enc.c
new file mode 100644
index 0000000..bbefe7d
--- /dev/null
+++ b/crypto/bf/bf_enc.c
@@ -0,0 +1,304 @@
+/* $OpenBSD: bf_enc.c,v 1.9 2022/11/26 16:08:51 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "bf_local.h"
+
+/*
+ * Blowfish as implemented from 'Blowfish: Springer-Verlag paper'
+ * (From LECTURE NOTES IN COMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION,
+ * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
+ */
+
+#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20)
+#error If you set BF_ROUNDS to some value other than 16 or 20, you will have \
+to modify the code.
+#endif
+
+void
+BF_encrypt(BF_LONG *data, const BF_KEY *key)
+{
+#ifndef BF_PTR2
+	BF_LONG l, r;
+	const BF_LONG *p, *s;
+
+	p = key->P;
+	s = &(key->S[0]);
+	l = data[0];
+	r = data[1];
+
+	l ^= p[0];
+	BF_ENC(r, l,s, p[1]);
+	BF_ENC(l, r,s, p[2]);
+	BF_ENC(r, l,s, p[3]);
+	BF_ENC(l, r,s, p[4]);
+	BF_ENC(r, l,s, p[5]);
+	BF_ENC(l, r,s, p[6]);
+	BF_ENC(r, l,s, p[7]);
+	BF_ENC(l, r,s, p[8]);
+	BF_ENC(r, l,s, p[9]);
+	BF_ENC(l, r,s, p[10]);
+	BF_ENC(r, l,s, p[11]);
+	BF_ENC(l, r,s, p[12]);
+	BF_ENC(r, l,s, p[13]);
+	BF_ENC(l, r,s, p[14]);
+	BF_ENC(r, l,s, p[15]);
+	BF_ENC(l, r,s, p[16]);
+#if BF_ROUNDS == 20
+	BF_ENC(r, l,s, p[17]);
+	BF_ENC(l, r,s, p[18]);
+	BF_ENC(r, l,s, p[19]);
+	BF_ENC(l, r,s, p[20]);
+#endif
+	r ^= p[BF_ROUNDS + 1];
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+#else
+	BF_LONG l, r,t, *k;
+
+	l = data[0];
+	r = data[1];
+	k = (BF_LONG*)key;
+
+	l ^= k[0];
+	BF_ENC(r, l, k, 1);
+	BF_ENC(l, r, k, 2);
+	BF_ENC(r, l, k, 3);
+	BF_ENC(l, r, k, 4);
+	BF_ENC(r, l, k, 5);
+	BF_ENC(l, r, k, 6);
+	BF_ENC(r, l, k, 7);
+	BF_ENC(l, r, k, 8);
+	BF_ENC(r, l, k, 9);
+	BF_ENC(l, r,k, 10);
+	BF_ENC(r, l,k, 11);
+	BF_ENC(l, r,k, 12);
+	BF_ENC(r, l,k, 13);
+	BF_ENC(l, r,k, 14);
+	BF_ENC(r, l,k, 15);
+	BF_ENC(l, r,k, 16);
+#if BF_ROUNDS == 20
+	BF_ENC(r, l,k, 17);
+	BF_ENC(l, r,k, 18);
+	BF_ENC(r, l,k, 19);
+	BF_ENC(l, r,k, 20);
+#endif
+	r ^= k[BF_ROUNDS + 1];
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+#endif
+}
+
+#ifndef BF_DEFAULT_OPTIONS
+
+void
+BF_decrypt(BF_LONG *data, const BF_KEY *key)
+{
+#ifndef BF_PTR2
+	BF_LONG l, r;
+	const BF_LONG *p, *s;
+
+	p = key->P;
+	s = &(key->S[0]);
+	l = data[0];
+	r = data[1];
+
+	l ^= p[BF_ROUNDS + 1];
+#if BF_ROUNDS == 20
+	BF_ENC(r, l,s, p[20]);
+	BF_ENC(l, r,s, p[19]);
+	BF_ENC(r, l,s, p[18]);
+	BF_ENC(l, r,s, p[17]);
+#endif
+	BF_ENC(r, l,s, p[16]);
+	BF_ENC(l, r,s, p[15]);
+	BF_ENC(r, l,s, p[14]);
+	BF_ENC(l, r,s, p[13]);
+	BF_ENC(r, l,s, p[12]);
+	BF_ENC(l, r,s, p[11]);
+	BF_ENC(r, l,s, p[10]);
+	BF_ENC(l, r,s, p[9]);
+	BF_ENC(r, l,s, p[8]);
+	BF_ENC(l, r,s, p[7]);
+	BF_ENC(r, l,s, p[6]);
+	BF_ENC(l, r,s, p[5]);
+	BF_ENC(r, l,s, p[4]);
+	BF_ENC(l, r,s, p[3]);
+	BF_ENC(r, l,s, p[2]);
+	BF_ENC(l, r,s, p[1]);
+	r ^= p[0];
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+#else
+	BF_LONG l, r,t, *k;
+
+	l = data[0];
+	r = data[1];
+	k = (BF_LONG *)key;
+
+	l ^= k[BF_ROUNDS + 1];
+#if BF_ROUNDS == 20
+	BF_ENC(r, l,k, 20);
+	BF_ENC(l, r,k, 19);
+	BF_ENC(r, l,k, 18);
+	BF_ENC(l, r,k, 17);
+#endif
+	BF_ENC(r, l,k, 16);
+	BF_ENC(l, r,k, 15);
+	BF_ENC(r, l,k, 14);
+	BF_ENC(l, r,k, 13);
+	BF_ENC(r, l,k, 12);
+	BF_ENC(l, r,k, 11);
+	BF_ENC(r, l,k, 10);
+	BF_ENC(l, r, k, 9);
+	BF_ENC(r, l, k, 8);
+	BF_ENC(l, r, k, 7);
+	BF_ENC(r, l, k, 6);
+	BF_ENC(l, r, k, 5);
+	BF_ENC(r, l, k, 4);
+	BF_ENC(l, r, k, 3);
+	BF_ENC(r, l, k, 2);
+	BF_ENC(l, r, k, 1);
+	r ^= k[0];
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+#endif
+}
+
+void
+BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    const BF_KEY *schedule, unsigned char *ivec, int encrypt)
+{
+	BF_LONG tin0, tin1;
+	BF_LONG tout0, tout1, xor0, xor1;
+	long l = length;
+	BF_LONG tin[2];
+
+	if (encrypt) {
+		n2l(ivec, tout0);
+		n2l(ivec, tout1);
+		ivec -= 8;
+		for (l -= 8; l >= 0; l -= 8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			BF_encrypt(tin, schedule);
+			tout0 = tin[0];
+			tout1 = tin[1];
+			l2n(tout0, out);
+			l2n(tout1, out);
+		}
+		if (l != -8) {
+			n2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			BF_encrypt(tin, schedule);
+			tout0 = tin[0];
+			tout1 = tin[1];
+			l2n(tout0, out);
+			l2n(tout1, out);
+		}
+		l2n(tout0, ivec);
+		l2n(tout1, ivec);
+	} else {
+		n2l(ivec, xor0);
+		n2l(ivec, xor1);
+		ivec -= 8;
+		for (l -= 8; l >= 0; l -= 8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin[0] = tin0;
+			tin[1] = tin1;
+			BF_decrypt(tin, schedule);
+			tout0 = tin[0]^xor0;
+			tout1 = tin[1]^xor1;
+			l2n(tout0, out);
+			l2n(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin[0] = tin0;
+			tin[1] = tin1;
+			BF_decrypt(tin, schedule);
+			tout0 = tin[0]^xor0;
+			tout1 = tin[1]^xor1;
+			l2nn(tout0, tout1, out, l + 8);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		l2n(xor0, ivec);
+		l2n(xor1, ivec);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+
+#endif
diff --git a/crypto/bf/bf_local.h b/crypto/bf/bf_local.h
new file mode 100644
index 0000000..1cc2952
--- /dev/null
+++ b/crypto/bf/bf_local.h
@@ -0,0 +1,219 @@
+/* $OpenBSD: bf_local.h,v 1.1 2022/11/26 16:08:51 tb Exp $ */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BF_LOCL_H
+#define HEADER_BF_LOCL_H
+#include  /* BF_PTR, BF_PTR2 */
+
+#undef c2l
+#define c2l(c,l)	(l =((unsigned long)(*((c)++)))    , \
+			 l|=((unsigned long)(*((c)++)))<< 8L, \
+			 l|=((unsigned long)(*((c)++)))<<16L, \
+			 l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))<<24L; \
+			case 7: l2|=((unsigned long)(*(--(c))))<<16L; \
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \
+			case 5: l2|=((unsigned long)(*(--(c))));     \
+			case 4: l1 =((unsigned long)(*(--(c))))<<24L; \
+			case 3: l1|=((unsigned long)(*(--(c))))<<16L; \
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \
+			case 1: l1|=((unsigned long)(*(--(c))));     \
+				} \
+			}
+
+#undef l2c
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
+				} \
+			}
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))    ; \
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
+			case 6: l2|=((unsigned long)(*(--(c))))<<16; \
+			case 5: l2|=((unsigned long)(*(--(c))))<<24; \
+			case 4: l1 =((unsigned long)(*(--(c))))    ; \
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
+			case 2: l1|=((unsigned long)(*(--(c))))<<16; \
+			case 1: l1|=((unsigned long)(*(--(c))))<<24; \
+				} \
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+				} \
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \
+                         l|=((unsigned long)(*((c)++)))<<16L, \
+                         l|=((unsigned long)(*((c)++)))<< 8L, \
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+/* This is actually a big endian algorithm, the most significant byte
+ * is used to lookup array 0 */
+
+#if defined(BF_PTR2)
+
+/*
+ * This is basically a special Intel version. Point is that Intel
+ * doesn't have many registers, but offers a reach choice of addressing
+ * modes. So we spare some registers by directly traversing BF_KEY
+ * structure and hiring the most decorated addressing mode. The code
+ * generated by EGCS is *perfectly* competitive with assembler
+ * implementation!
+ */
+#define BF_ENC(LL,R,KEY,Pi) (\
+	LL^=KEY[Pi], \
+	t=  KEY[BF_ROUNDS+2 +   0 + ((R>>24)&0xFF)], \
+	t+= KEY[BF_ROUNDS+2 + 256 + ((R>>16)&0xFF)], \
+	t^= KEY[BF_ROUNDS+2 + 512 + ((R>>8 )&0xFF)], \
+	t+= KEY[BF_ROUNDS+2 + 768 + ((R    )&0xFF)], \
+	LL^=t \
+	)
+
+#elif defined(BF_PTR)
+
+#ifndef BF_LONG_LOG2
+#define BF_LONG_LOG2  2       /* default to BF_LONG being 32 bits */
+#endif
+#define BF_M  (0xFF<>BF_i)&BF_M gets folded into a single instruction, namely
+ * rlwinm. So let'em double-check if their compiler does it.
+ */
+
+#define BF_ENC(LL,R,S,P) ( \
+	LL^=P, \
+	LL^= (((*(BF_LONG *)((unsigned char *)&(S[  0])+((R>>BF_0)&BF_M))+ \
+		*(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \
+		*(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \
+		*(BF_LONG *)((unsigned char *)&(S[768])+((R<>24)&0xff)] + \
+		S[0x0100+((int)(R>>16)&0xff)])^ \
+		S[0x0200+((int)(R>> 8)&0xff)])+ \
+		S[0x0300+((int)(R    )&0xff)])&0xffffffffL \
+	)
+#endif
+
+#endif
diff --git a/crypto/bf/bf_ofb64.c b/crypto/bf/bf_ofb64.c
new file mode 100644
index 0000000..8fe2478
--- /dev/null
+++ b/crypto/bf/bf_ofb64.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: bf_ofb64.c,v 1.8 2022/11/26 16:08:51 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "bf_local.h"
+
+/*
+ * The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length,
+    const BF_KEY *schedule, unsigned char *ivec, int *num)
+{
+	BF_LONG v0, v1, t;
+	int n= *num;
+	long l = length;
+	unsigned char d[8];
+	char *dp;
+	BF_LONG ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = (unsigned char *)ivec;
+	n2l(iv, v0);
+	n2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = (char *)d;
+	l2n(v0, dp);
+	l2n(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			BF_encrypt((BF_LONG *)ti, schedule);
+			dp = (char *)d;
+			t = ti[0];
+			l2n(t, dp);
+			t = ti[1];
+			l2n(t, dp);
+			save++;
+		}
+		*(out++)= *(in++)^d[n];
+		n = (n + 1)&0x07;
+	}
+	if (save) {
+		v0 = ti[0];
+		v1 = ti[1];
+		iv = (unsigned char *)ivec;
+		l2n(v0, iv);
+		l2n(v1, iv);
+	}
+	t = v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
diff --git a/crypto/bf/bf_skey.c b/crypto/bf/bf_skey.c
new file mode 100644
index 0000000..cc31034
--- /dev/null
+++ b/crypto/bf/bf_skey.c
@@ -0,0 +1,387 @@
+/* $OpenBSD: bf_skey.c,v 1.17 2022/11/26 16:08:51 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bf_local.h"
+
+static const BF_KEY bf_init = {
+	.P = {
+		0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L,
+		0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L,
+		0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL,
+		0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L,
+		0x9216d5d9L, 0x8979fb1b
+	},
+	.S = {
+		0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L,
+		0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L,
+		0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L,
+		0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL,
+		0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL,
+		0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L,
+		0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL,
+		0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL,
+		0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L,
+		0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L,
+		0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL,
+		0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL,
+		0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL,
+		0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L,
+		0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L,
+		0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L,
+		0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L,
+		0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L,
+		0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL,
+		0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L,
+		0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L,
+		0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L,
+		0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L,
+		0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL,
+		0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L,
+		0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL,
+		0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL,
+		0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L,
+		0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL,
+		0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L,
+		0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL,
+		0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L,
+		0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L,
+		0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL,
+		0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L,
+		0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L,
+		0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL,
+		0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L,
+		0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL,
+		0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L,
+		0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L,
+		0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL,
+		0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L,
+		0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L,
+		0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L,
+		0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L,
+		0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L,
+		0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL,
+		0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL,
+		0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L,
+		0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L,
+		0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L,
+		0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L,
+		0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL,
+		0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L,
+		0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL,
+		0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL,
+		0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L,
+		0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L,
+		0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L,
+		0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L,
+		0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L,
+		0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L,
+		0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL,
+		0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L,
+		0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L,
+		0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L,
+		0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL,
+		0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L,
+		0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L,
+		0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL,
+		0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L,
+		0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L,
+		0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L,
+		0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL,
+		0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL,
+		0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L,
+		0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L,
+		0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L,
+		0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L,
+		0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL,
+		0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL,
+		0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL,
+		0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L,
+		0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL,
+		0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L,
+		0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L,
+		0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL,
+		0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL,
+		0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L,
+		0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL,
+		0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L,
+		0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL,
+		0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL,
+		0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L,
+		0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L,
+		0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L,
+		0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L,
+		0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L,
+		0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L,
+		0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L,
+		0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL,
+		0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L,
+		0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL,
+		0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L,
+		0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L,
+		0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L,
+		0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L,
+		0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L,
+		0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L,
+		0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L,
+		0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L,
+		0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L,
+		0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L,
+		0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L,
+		0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L,
+		0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L,
+		0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L,
+		0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L,
+		0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L,
+		0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL,
+		0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL,
+		0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L,
+		0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL,
+		0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L,
+		0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L,
+		0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L,
+		0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L,
+		0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L,
+		0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L,
+		0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL,
+		0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L,
+		0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L,
+		0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L,
+		0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL,
+		0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL,
+		0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL,
+		0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L,
+		0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L,
+		0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL,
+		0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L,
+		0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL,
+		0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L,
+		0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL,
+		0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L,
+		0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL,
+		0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L,
+		0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL,
+		0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L,
+		0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L,
+		0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL,
+		0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L,
+		0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L,
+		0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L,
+		0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L,
+		0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL,
+		0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L,
+		0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL,
+		0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L,
+		0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL,
+		0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L,
+		0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL,
+		0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL,
+		0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL,
+		0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L,
+		0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L,
+		0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL,
+		0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL,
+		0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL,
+		0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL,
+		0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL,
+		0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L,
+		0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L,
+		0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L,
+		0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L,
+		0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL,
+		0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL,
+		0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L,
+		0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L,
+		0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L,
+		0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L,
+		0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L,
+		0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L,
+		0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L,
+		0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L,
+		0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L,
+		0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L,
+		0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL,
+		0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L,
+		0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL,
+		0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L,
+		0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L,
+		0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL,
+		0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL,
+		0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL,
+		0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L,
+		0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L,
+		0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L,
+		0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L,
+		0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L,
+		0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L,
+		0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L,
+		0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L,
+		0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L,
+		0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L,
+		0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L,
+		0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L,
+		0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL,
+		0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL,
+		0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L,
+		0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL,
+		0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL,
+		0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL,
+		0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L,
+		0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL,
+		0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL,
+		0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L,
+		0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L,
+		0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L,
+		0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L,
+		0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL,
+		0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL,
+		0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L,
+		0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L,
+		0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L,
+		0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL,
+		0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L,
+		0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L,
+		0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L,
+		0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL,
+		0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L,
+		0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L,
+		0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L,
+		0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL,
+		0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL,
+		0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L,
+		0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L,
+		0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L,
+		0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L,
+		0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL,
+		0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L,
+		0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL,
+		0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL,
+		0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L,
+		0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L,
+		0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL,
+		0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L,
+		0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL,
+		0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L,
+		0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL,
+		0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L,
+		0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L,
+		0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL,
+		0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L,
+		0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL,
+		0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L,
+	}
+};
+
+void
+BF_set_key(BF_KEY *key, int len, const unsigned char *data)
+{
+	int i;
+	BF_LONG *p, ri, in[2];
+	const unsigned char *d, *end;
+
+	memcpy(key, &bf_init, sizeof(BF_KEY));
+	p = key->P;
+
+	if (len > ((BF_ROUNDS + 2)*4))
+		len = (BF_ROUNDS + 2)*4;
+
+	d = data;
+	end = &(data[len]);
+	for (i = 0; i < (BF_ROUNDS + 2); i++) {
+		ri= *(d++);
+		if (d >= end)
+			d = data;
+
+		ri <<= 8;
+		ri |= *(d++);
+		if (d >= end)
+			d = data;
+
+		ri <<= 8;
+		ri |= *(d++);
+		if (d >= end)
+			d = data;
+
+		ri <<= 8;
+		ri |= *(d++);
+		if (d >= end)
+			d = data;
+
+		p[i]^=ri;
+	}
+
+	in[0] = 0L;
+	in[1] = 0L;
+	for (i = 0; i < (BF_ROUNDS + 2); i += 2) {
+		BF_encrypt(in, key);
+		p[i  ] = in[0];
+		p[i + 1] = in[1];
+	}
+
+	p = key->S;
+	for (i = 0; i < 4*256; i += 2) {
+		BF_encrypt(in, key);
+		p[i  ] = in[0];
+		p[i + 1] = in[1];
+	}
+}
diff --git a/crypto/bio/b_dump.c b/crypto/bio/b_dump.c
new file mode 100644
index 0000000..e46424e
--- /dev/null
+++ b/crypto/bio/b_dump.c
@@ -0,0 +1,190 @@
+/* $OpenBSD: b_dump.c,v 1.26 2023/07/29 02:32:00 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * Stolen from tjh's ssl/ssl_trc.c stuff.
+ */
+
+#include 
+#include 
+
+#include 
+
+#define TRUNCATE
+#define DUMP_WIDTH	16
+#define DUMP_WIDTH_LESS_INDENT(i) (DUMP_WIDTH - ((i - (i > 6 ? 6 : i) + 3) / 4))
+
+int
+BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u),
+    void *u, const char *s, int len)
+{
+	return BIO_dump_indent_cb(cb, u, s, len, 0);
+}
+
+int
+BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u),
+    void *u, const char *s, int len, int indent)
+{
+	char buf[288 + 1], tmp[20], str[128 + 1];
+	int i, j, rows, trc, written;
+	unsigned char ch;
+	int dump_width;
+	int ret = 0;
+
+	trc = 0;
+
+#ifdef TRUNCATE
+	for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--)
+		trc++;
+#endif
+
+	if (indent < 0)
+		indent = 0;
+	if (indent > 64)
+		indent = 64;
+	memset(str, ' ', indent);
+	str[indent] = '\0';
+
+	if ((dump_width = DUMP_WIDTH_LESS_INDENT(indent)) <= 0)
+		return -1;
+	rows = (len / dump_width);
+	if ((rows * dump_width) < len)
+		rows++;
+	for (i = 0; i < rows; i++) {
+		strlcpy(buf, str, sizeof buf);
+		snprintf(tmp, sizeof tmp, "%04x - ", i*dump_width);
+		strlcat(buf, tmp, sizeof buf);
+		for (j = 0; j < dump_width; j++) {
+			if (((i*dump_width) + j) >= len) {
+				strlcat(buf, "   ", sizeof buf);
+			} else {
+				ch = ((unsigned char)*(s + i*dump_width + j)) & 0xff;
+				snprintf(tmp, sizeof tmp, "%02x%c", ch,
+				    j == 7 ? '-' : ' ');
+				strlcat(buf, tmp, sizeof buf);
+			}
+		}
+		strlcat(buf, "  ", sizeof buf);
+		for (j = 0; j < dump_width; j++) {
+			if (((i*dump_width) + j) >= len)
+				break;
+			ch = ((unsigned char)*(s + i * dump_width + j)) & 0xff;
+			snprintf(tmp, sizeof tmp, "%c",
+			    ((ch >= ' ') && (ch <= '~')) ? ch : '.');
+			strlcat(buf, tmp, sizeof buf);
+		}
+		strlcat(buf, "\n", sizeof buf);
+		/* if this is the last call then update the ddt_dump thing so
+		 * that we will move the selection point in the debug window
+		 */
+		if ((written = cb((void *)buf, strlen(buf), u)) < 0)
+			return -1;
+		ret += written;
+
+	}
+#ifdef TRUNCATE
+	if (trc > 0) {
+		snprintf(buf, sizeof buf, "%s%04x - \n",
+		    str, len + trc);
+		if ((written = cb((void *)buf, strlen(buf), u)) < 0)
+			return -1;
+		ret += written;
+	}
+#endif
+	return (ret);
+}
+
+static int
+write_fp(const void *data, size_t len, void *fp)
+{
+	return fwrite(data, 1, len, fp);
+}
+
+int
+BIO_dump_fp(FILE *fp, const char *s, int len)
+{
+	return BIO_dump_cb(write_fp, fp, s, len);
+}
+LCRYPTO_ALIAS(BIO_dump_fp);
+
+int
+BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent)
+{
+	return BIO_dump_indent_cb(write_fp, fp, s, len, indent);
+}
+LCRYPTO_ALIAS(BIO_dump_indent_fp);
+
+static int
+write_bio(const void *data, size_t len, void *bp)
+{
+	return BIO_write((BIO *)bp, (const char *)data, len);
+}
+
+int
+BIO_dump(BIO *bp, const char *s, int len)
+{
+	return BIO_dump_cb(write_bio, bp, s, len);
+}
+LCRYPTO_ALIAS(BIO_dump);
+
+int
+BIO_dump_indent(BIO *bp, const char *s, int len, int indent)
+{
+	return BIO_dump_indent_cb(write_bio, bp, s, len, indent);
+}
+LCRYPTO_ALIAS(BIO_dump_indent);
diff --git a/crypto/bio/b_posix.c b/crypto/bio/b_posix.c
new file mode 100644
index 0000000..d78f25a
--- /dev/null
+++ b/crypto/bio/b_posix.c
@@ -0,0 +1,93 @@
+/* $OpenBSD: b_posix.c,v 1.3 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * Functions that need to be overridden by non-POSIX operating systems.
+ */
+
+#include 
+#include 
+
+#include 
+
+int
+BIO_sock_init(void)
+{
+	if (!OPENSSL_init_crypto(0, NULL)) /* XXX do we need this? */
+		return (0);
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_sock_init);
+
+void
+BIO_sock_cleanup(void)
+{
+}
+LCRYPTO_ALIAS(BIO_sock_cleanup);
+
+int
+BIO_socket_nbio(int s, int mode)
+{
+	int flags = fcntl(s, F_GETFD);
+	if (mode && !(flags & O_NONBLOCK))
+		return (fcntl(s, F_SETFL, flags | O_NONBLOCK) != -1);
+	else if (!mode && (flags & O_NONBLOCK))
+		return (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) != -1);
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_socket_nbio);
diff --git a/crypto/bio/b_print.c b/crypto/bio/b_print.c
new file mode 100644
index 0000000..a750ac4
--- /dev/null
+++ b/crypto/bio/b_print.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: b_print.c,v 1.27 2023/07/05 21:23:37 beck Exp $ */
+
+/* Theo de Raadt places this file in the public domain. */
+
+#include 
+
+int
+BIO_printf(BIO *bio, const char *format, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, format);
+	ret = BIO_vprintf(bio, format, args);
+	va_end(args);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_printf);
+
+#ifdef HAVE_FUNOPEN
+static int
+_BIO_write(void *cookie, const char *buf, int nbytes)
+{
+	return BIO_write(cookie, buf, nbytes);
+}
+
+int
+BIO_vprintf(BIO *bio, const char *format, va_list args)
+{
+	int ret;
+	FILE *fp;
+
+	fp = funopen(bio, NULL, &_BIO_write, NULL, NULL);
+	if (fp == NULL) {
+		ret = -1;
+		goto fail;
+	}
+	ret = vfprintf(fp, format, args);
+	fclose(fp);
+fail:
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_vprintf);
+
+#else /* !HAVE_FUNOPEN */
+
+int
+BIO_vprintf(BIO *bio, const char *format, va_list args)
+{
+	int ret;
+	char *buf = NULL;
+
+	ret = vasprintf(&buf, format, args);
+	if (ret == -1)
+		return (ret);
+	BIO_write(bio, buf, ret);
+	free(buf);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_vprintf);
+
+#endif /* HAVE_FUNOPEN */
+
+/*
+ * BIO_snprintf and BIO_vsnprintf return -1 for overflow,
+ * due to the history of this API.  Justification:
+ *
+ * Traditional snprintf surfaced in 4.4BSD, and returned
+ * "number of bytes wanted". Solaris and Windows opted to
+ * return -1.  A draft standard was written which returned -1.
+ * Due to the large volume of code already using the first
+ * semantics, the draft was repaired before standardization to
+ * specify "number of bytes wanted" plus "-1 for character conversion
+ * style errors".  Solaris adapted to this rule, but Windows stuck
+ * with -1.
+ *
+ * Original OpenSSL comment which is full of lies:
+ *
+ * "In case of truncation, return -1 like traditional snprintf.
+ * (Current drafts for ISO/IEC 9899 say snprintf should return
+ * the number of characters that would have been written,
+ * had the buffer been large enough.)"
+ */
+int
+BIO_snprintf(char *buf, size_t n, const char *format, ...)
+{
+	va_list args;
+	int ret;
+
+	va_start(args, format);
+	ret = vsnprintf(buf, n, format, args);
+	va_end(args);
+
+	if (ret >= n || ret == -1)
+		return (-1);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_snprintf);
+
+int
+BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
+{
+	int ret;
+
+	ret = vsnprintf(buf, n, format, args);
+
+	if (ret >= n || ret == -1)
+		return (-1);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_vsnprintf);
diff --git a/crypto/bio/b_sock.c b/crypto/bio/b_sock.c
new file mode 100644
index 0000000..00bbe9c
--- /dev/null
+++ b/crypto/bio/b_sock.c
@@ -0,0 +1,261 @@
+/* $OpenBSD: b_sock.c,v 1.71 2023/07/05 21:23:37 beck Exp $ */
+/*
+ * Copyright (c) 2017 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+int
+BIO_get_host_ip(const char *str, unsigned char *ip)
+{
+	struct addrinfo *res = NULL;
+	struct addrinfo hints = {
+		.ai_family = AF_INET,
+		.ai_socktype = SOCK_STREAM,
+		.ai_flags = AI_PASSIVE,
+	};
+	uint32_t *iap = (in_addr_t *)ip;
+	int error;
+
+	if (str == NULL) {
+		BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
+		ERR_asprintf_error_data("NULL host provided");
+		return (0);
+	}
+
+	if ((error = getaddrinfo(str, NULL, &hints, &res)) != 0) {
+		BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
+		ERR_asprintf_error_data("getaddrinfo: host='%s' : %s'", str,
+		    gai_strerror(error));
+		return (0);
+	}
+	*iap = (uint32_t)(((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr);
+	freeaddrinfo(res);
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_get_host_ip);
+
+int
+BIO_get_port(const char *str, unsigned short *port_ptr)
+{
+	struct addrinfo *res = NULL;
+	struct addrinfo hints = {
+		.ai_family = AF_UNSPEC,
+		.ai_socktype = SOCK_STREAM,
+		.ai_flags = AI_PASSIVE,
+	};
+	int error;
+
+	if (str == NULL) {
+		BIOerror(BIO_R_NO_PORT_SPECIFIED);
+		return (0);
+	}
+
+	if ((error = getaddrinfo(NULL, str, &hints, &res)) != 0) {
+		BIOerror(BIO_R_INVALID_ARGUMENT);
+		ERR_asprintf_error_data("getaddrinfo: service='%s' : %s'", str,
+		    gai_strerror(error));
+		return (0);
+	}
+	*port_ptr = ntohs(((struct sockaddr_in *)(res->ai_addr))->sin_port);
+	freeaddrinfo(res);
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_get_port);
+
+int
+BIO_sock_error(int sock)
+{
+	socklen_t len;
+	int err;
+
+	len = sizeof(err);
+	if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len) != 0)
+		return (1);
+	return (err);
+}
+LCRYPTO_ALIAS(BIO_sock_error);
+
+struct hostent *
+BIO_gethostbyname(const char *name)
+{
+	return gethostbyname(name);
+}
+LCRYPTO_ALIAS(BIO_gethostbyname);
+
+int
+BIO_socket_ioctl(int fd, long type, void *arg)
+{
+	int ret;
+
+	ret = ioctl(fd, type, arg);
+	if (ret < 0)
+		SYSerror(errno);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_socket_ioctl);
+
+int
+BIO_get_accept_socket(char *host, int bind_mode)
+{
+	struct addrinfo hints = {
+		.ai_family = AF_INET,
+		.ai_socktype = SOCK_STREAM,
+		.ai_flags = AI_PASSIVE,
+	};
+	struct addrinfo *res = NULL;
+	char *h, *p, *str = NULL;
+	int error, ret = 0, s = -1;
+
+	if (host == NULL) {
+		BIOerror(BIO_R_NO_PORT_SPECIFIED);
+		return (-1);
+	}
+	if ((str = strdup(host)) == NULL) {
+		BIOerror(ERR_R_MALLOC_FAILURE);
+		return (-1);
+	}
+	p = NULL;
+	h = str;
+	if ((p = strrchr(str, ':')) == NULL) {
+		/* A string without a colon is treated as a port. */
+		p = str;
+		h = NULL;
+	} else {
+		*p++ = '\0';
+		if (*p == '\0') {
+			BIOerror(BIO_R_NO_PORT_SPECIFIED);
+			goto err;
+		}
+		if (*h == '\0' || strcmp(h, "*") == 0)
+			h = NULL;
+	}
+
+	if ((error = getaddrinfo(h, p, &hints, &res)) != 0) {
+		BIOerror(BIO_R_BAD_HOSTNAME_LOOKUP);
+		ERR_asprintf_error_data("getaddrinfo: '%s:%s': %s'", h, p,
+		    gai_strerror(error));
+		goto err;
+	}
+	if (h == NULL) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)res->ai_addr;
+		sin->sin_addr.s_addr = INADDR_ANY;
+	}
+
+	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (s == -1) {
+		SYSerror(errno);
+		ERR_asprintf_error_data("host='%s'", host);
+		BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET);
+		goto err;
+	}
+	if (bind_mode == BIO_BIND_REUSEADDR) {
+		int i = 1;
+
+		ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+		bind_mode = BIO_BIND_NORMAL;
+	}
+	if (bind(s, res->ai_addr, res->ai_addrlen) == -1) {
+		SYSerror(errno);
+		ERR_asprintf_error_data("host='%s'", host);
+		BIOerror(BIO_R_UNABLE_TO_BIND_SOCKET);
+		goto err;
+	}
+	if (listen(s, SOMAXCONN) == -1) {
+		SYSerror(errno);
+		ERR_asprintf_error_data("host='%s'", host);
+		BIOerror(BIO_R_UNABLE_TO_LISTEN_SOCKET);
+		goto err;
+	}
+	ret = 1;
+
+err:
+	free(str);
+	if (res != NULL)
+		freeaddrinfo(res);
+	if ((ret == 0) && (s != -1)) {
+		close(s);
+		s = -1;
+	}
+	return (s);
+}
+LCRYPTO_ALIAS(BIO_get_accept_socket);
+
+int
+BIO_accept(int sock, char **addr)
+{
+	char   h[NI_MAXHOST], s[NI_MAXSERV];
+	struct sockaddr_in sin;
+	socklen_t sin_len = sizeof(sin);
+	int ret = -1;
+
+	if (addr == NULL) {
+		BIOerror(BIO_R_NULL_PARAMETER);
+		goto end;
+	}
+	ret = accept(sock, (struct sockaddr *)&sin, &sin_len);
+	if (ret == -1) {
+		if (BIO_sock_should_retry(ret))
+			return -2;
+		SYSerror(errno);
+		BIOerror(BIO_R_ACCEPT_ERROR);
+		goto end;
+	}
+	/* XXX Crazy API. Can't be helped */
+	if (*addr != NULL) {
+		free(*addr);
+		*addr = NULL;
+	}
+
+	if (sin.sin_family != AF_INET)
+		goto end;
+
+	if (getnameinfo((struct sockaddr *)&sin, sin_len, h, sizeof(h),
+		s, sizeof(s), NI_NUMERICHOST|NI_NUMERICSERV) != 0)
+		goto end;
+
+	if ((asprintf(addr, "%s:%s", h, s)) == -1) {
+		BIOerror(ERR_R_MALLOC_FAILURE);
+		*addr = NULL;
+		goto end;
+	}
+end:
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_accept);
+
+int
+BIO_set_tcp_ndelay(int s, int on)
+{
+	return (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) == 0);
+}
+LCRYPTO_ALIAS(BIO_set_tcp_ndelay);
diff --git a/crypto/bio/b_win.c b/crypto/bio/b_win.c
new file mode 100644
index 0000000..e261cd2
--- /dev/null
+++ b/crypto/bio/b_win.c
@@ -0,0 +1,54 @@
+/*
+ * Public domain
+ *
+ * Dongsheng Song 
+ * Brent Cook 
+ */
+
+#include 
+
+#include 
+#include 
+
+int
+BIO_sock_init(void)
+{
+	/*
+	 * WSAStartup loads the winsock .dll and initializes the networking
+	 * stack on Windows, or simply increases the reference count.
+	 */
+	static struct WSAData wsa_state = {0};
+	WORD version_requested = MAKEWORD(2, 2);
+	static int wsa_init_done = 0;
+	if (!wsa_init_done) {
+		if (WSAStartup(version_requested, &wsa_state) != 0) {
+			int err = WSAGetLastError();
+			SYSerror(err);
+			BIOerror(BIO_R_WSASTARTUP);
+			return (-1);
+		}
+		wsa_init_done = 1;
+	}
+ 	return (1);
+}
+
+void
+BIO_sock_cleanup(void)
+{
+	/*
+	 * We could call WSACleanup here, but it is easy to get it wrong. Since
+	 * this API provides no way to even tell if it failed, there is no safe
+	 * way to expose that functionality here.
+	 *
+	 * The cost of leaving the networking DLLs loaded may have been large
+	 * during the Windows 3.1/win32s era, but it is small in modern
+	 * contexts, so don't bother.
+	 */
+}
+
+int
+BIO_socket_nbio(int s, int mode)
+{
+	u_long value = mode;
+	return ioctlsocket(s, FIONBIO, &value) != SOCKET_ERROR;
+}
diff --git a/crypto/bio/bf_buff.c b/crypto/bio/bf_buff.c
new file mode 100644
index 0000000..226c168
--- /dev/null
+++ b/crypto/bio/bf_buff.c
@@ -0,0 +1,523 @@
+/* $OpenBSD: bf_buff.c,v 1.28 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+
+static int buffer_write(BIO *h, const char *buf, int num);
+static int buffer_read(BIO *h, char *buf, int size);
+static int buffer_puts(BIO *h, const char *str);
+static int buffer_gets(BIO *h, char *str, int size);
+static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int buffer_new(BIO *h);
+static int buffer_free(BIO *data);
+static long buffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+#define DEFAULT_BUFFER_SIZE	4096
+
+static const BIO_METHOD methods_buffer = {
+	.type = BIO_TYPE_BUFFER,
+	.name = "buffer",
+	.bwrite = buffer_write,
+	.bread = buffer_read,
+	.bputs = buffer_puts,
+	.bgets = buffer_gets,
+	.ctrl = buffer_ctrl,
+	.create = buffer_new,
+	.destroy = buffer_free,
+	.callback_ctrl = buffer_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_buffer(void)
+{
+	return (&methods_buffer);
+}
+LCRYPTO_ALIAS(BIO_f_buffer);
+
+static int
+buffer_new(BIO *bi)
+{
+	BIO_F_BUFFER_CTX *ctx;
+
+	ctx = malloc(sizeof(BIO_F_BUFFER_CTX));
+	if (ctx == NULL)
+		return (0);
+	ctx->ibuf = malloc(DEFAULT_BUFFER_SIZE);
+	if (ctx->ibuf == NULL) {
+		free(ctx);
+		return (0);
+	}
+	ctx->obuf = malloc(DEFAULT_BUFFER_SIZE);
+	if (ctx->obuf == NULL) {
+		free(ctx->ibuf);
+		free(ctx);
+		return (0);
+	}
+	ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
+	ctx->obuf_size = DEFAULT_BUFFER_SIZE;
+	ctx->ibuf_len = 0;
+	ctx->ibuf_off = 0;
+	ctx->obuf_len = 0;
+	ctx->obuf_off = 0;
+
+	bi->init = 1;
+	bi->ptr = (char *)ctx;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+buffer_free(BIO *a)
+{
+	BIO_F_BUFFER_CTX *b;
+
+	if (a == NULL)
+		return (0);
+	b = (BIO_F_BUFFER_CTX *)a->ptr;
+	free(b->ibuf);
+	free(b->obuf);
+	free(a->ptr);
+	a->ptr = NULL;
+	a->init = 0;
+	a->flags = 0;
+	return (1);
+}
+
+static int
+buffer_read(BIO *b, char *out, int outl)
+{
+	int i, num = 0;
+	BIO_F_BUFFER_CTX *ctx;
+
+	if (out == NULL)
+		return (0);
+	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+
+	if ((ctx == NULL) || (b->next_bio == NULL))
+		return (0);
+	num = 0;
+	BIO_clear_retry_flags(b);
+
+start:
+	i = ctx->ibuf_len;
+	/* If there is stuff left over, grab 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;
+		if (outl == i)
+			return (num);
+		outl -= i;
+		out += i;
+	}
+
+	/* We may have done a partial read. try to do more.
+	 * We have nothing in the buffer.
+	 * If we get an error and have read some data, just return it
+	 * and let them retry to get the error again.
+	 * copy direct to parent address space */
+	if (outl > ctx->ibuf_size) {
+		for (;;) {
+			i = BIO_read(b->next_bio, out, outl);
+			if (i <= 0) {
+				BIO_copy_next_retry(b);
+				if (i < 0)
+					return ((num > 0) ? num : i);
+				if (i == 0)
+					return (num);
+			}
+			num += i;
+			if (outl == i)
+				return (num);
+			out += i;
+			outl -= i;
+		}
+	}
+	/* else */
+
+	/* we are going to be doing some buffering */
+	i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
+	if (i <= 0) {
+		BIO_copy_next_retry(b);
+		if (i < 0)
+			return ((num > 0) ? num : i);
+		if (i == 0)
+			return (num);
+	}
+	ctx->ibuf_off = 0;
+	ctx->ibuf_len = i;
+
+	/* Lets re-read using ourselves :-) */
+	goto start;
+}
+
+static int
+buffer_write(BIO *b, const char *in, int inl)
+{
+	int i, num = 0;
+	BIO_F_BUFFER_CTX *ctx;
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+	if ((ctx == NULL) || (b->next_bio == NULL))
+		return (0);
+
+	BIO_clear_retry_flags(b);
+start:
+	i = ctx->obuf_size - (ctx->obuf_len + ctx->obuf_off);
+	/* add to buffer and return */
+	if (i >= inl) {
+		memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, inl);
+		ctx->obuf_len += inl;
+		return (num + inl);
+	}
+	/* else */
+	/* stuff already in buffer, so add to it first, then flush */
+	if (ctx->obuf_len != 0) {
+		if (i > 0) /* lets fill it up if we can */
+		{
+			memcpy(&(ctx->obuf[ctx->obuf_off + ctx->obuf_len]), in, i);
+			in += i;
+			inl -= i;
+			num += i;
+			ctx->obuf_len += i;
+		}
+		/* we now have a full buffer needing flushing */
+		for (;;) {
+			i = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
+			    ctx->obuf_len);
+			if (i <= 0) {
+				BIO_copy_next_retry(b);
+
+				if (i < 0)
+					return ((num > 0) ? num : i);
+				if (i == 0)
+					return (num);
+			}
+			ctx->obuf_off += i;
+			ctx->obuf_len -= i;
+			if (ctx->obuf_len == 0)
+				break;
+		}
+	}
+	/* we only get here if the buffer has been flushed and we
+	 * still have stuff to write */
+	ctx->obuf_off = 0;
+
+	/* we now have inl bytes to write */
+	while (inl >= ctx->obuf_size) {
+		i = BIO_write(b->next_bio, in, inl);
+		if (i <= 0) {
+			BIO_copy_next_retry(b);
+			if (i < 0)
+				return ((num > 0) ? num : i);
+			if (i == 0)
+				return (num);
+		}
+		num += i;
+		in += i;
+		inl -= i;
+		if (inl == 0)
+			return (num);
+	}
+
+	/* copy the rest into the buffer since we have only a small
+	 * amount left */
+	goto start;
+}
+
+static long
+buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	BIO *dbio;
+	BIO_F_BUFFER_CTX *ctx;
+	long ret = 1;
+	char *p1, *p2;
+	int r, i, *ip;
+	int ibs, obs;
+
+	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		ctx->ibuf_off = 0;
+		ctx->ibuf_len = 0;
+		ctx->obuf_off = 0;
+		ctx->obuf_len = 0;
+		if (b->next_bio == NULL)
+			return (0);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_INFO:
+		ret = (long)ctx->obuf_len;
+		break;
+	case BIO_C_GET_BUFF_NUM_LINES:
+		ret = 0;
+		p1 = ctx->ibuf;
+		for (i = 0; i < ctx->ibuf_len; i++) {
+			if (p1[ctx->ibuf_off + i] == '\n')
+				ret++;
+		}
+		break;
+	case BIO_CTRL_WPENDING:
+		ret = (long)ctx->obuf_len;
+		if (ret == 0) {
+			if (b->next_bio == NULL)
+				return (0);
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		}
+		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_C_SET_BUFF_READ_DATA:
+		if (num > ctx->ibuf_size) {
+			p1 = malloc(num);
+			if (p1 == NULL)
+				goto malloc_error;
+			free(ctx->ibuf);
+			ctx->ibuf = p1;
+		}
+		ctx->ibuf_off = 0;
+		ctx->ibuf_len = (int)num;
+		memcpy(ctx->ibuf, ptr, num);
+		ret = 1;
+		break;
+	case BIO_C_SET_BUFF_SIZE:
+		if (ptr != NULL) {
+			ip = (int *)ptr;
+			if (*ip == 0) {
+				ibs = (int)num;
+				obs = ctx->obuf_size;
+			}
+			else /* if (*ip == 1) */
+			{
+				ibs = ctx->ibuf_size;
+				obs = (int)num;
+			}
+		} else {
+			ibs = (int)num;
+			obs = (int)num;
+		}
+		p1 = ctx->ibuf;
+		p2 = ctx->obuf;
+		if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size)) {
+			p1 = malloc(num);
+			if (p1 == NULL)
+				goto malloc_error;
+		}
+		if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size)) {
+			p2 = malloc(num);
+			if (p2 == NULL) {
+				if (p1 != ctx->ibuf)
+					free(p1);
+				goto malloc_error;
+			}
+		}
+		if (ctx->ibuf != p1) {
+			free(ctx->ibuf);
+			ctx->ibuf = p1;
+			ctx->ibuf_off = 0;
+			ctx->ibuf_len = 0;
+			ctx->ibuf_size = ibs;
+		}
+		if (ctx->obuf != p2) {
+			free(ctx->obuf);
+			ctx->obuf = p2;
+			ctx->obuf_off = 0;
+			ctx->obuf_len = 0;
+			ctx->obuf_size = obs;
+		}
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		if (b->next_bio == NULL)
+			return (0);
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+
+	case BIO_CTRL_FLUSH:
+		if (b->next_bio == NULL)
+			return (0);
+		if (ctx->obuf_len <= 0) {
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+			break;
+		}
+
+		for (;;) {
+			BIO_clear_retry_flags(b);
+			if (ctx->obuf_len > 0) {
+				r = BIO_write(b->next_bio,
+				    &(ctx->obuf[ctx->obuf_off]),
+				    ctx->obuf_len);
+				BIO_copy_next_retry(b);
+				if (r <= 0)
+					return ((long)r);
+				ctx->obuf_off += r;
+				ctx->obuf_len -= r;
+			} else {
+				ctx->obuf_len = 0;
+				ctx->obuf_off = 0;
+				break;
+			}
+		}
+		ret = BIO_ctrl(b->next_bio, cmd, num, 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))
+			ret = 0;
+		break;
+	default:
+		if (b->next_bio == NULL)
+			return (0);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	}
+	return (ret);
+malloc_error:
+	BIOerror(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);
+}
+
+static int
+buffer_gets(BIO *b, char *buf, int size)
+{
+	BIO_F_BUFFER_CTX *ctx;
+	int num = 0, i, flag;
+	char *p;
+
+	ctx = (BIO_F_BUFFER_CTX *)b->ptr;
+	size--; /* reserve space for a '\0' */
+	BIO_clear_retry_flags(b);
+
+	for (;;) {
+		if (ctx->ibuf_len > 0) {
+			p = &(ctx->ibuf[ctx->ibuf_off]);
+			flag = 0;
+			for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
+				*(buf++) = p[i];
+				if (p[i] == '\n') {
+					flag = 1;
+					i++;
+					break;
+				}
+			}
+			num += i;
+			size -= i;
+			ctx->ibuf_len -= i;
+			ctx->ibuf_off += i;
+			if (flag || size == 0) {
+				*buf = '\0';
+				return (num);
+			}
+		}
+		else	/* read another chunk */
+		{
+			i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
+			if (i <= 0) {
+				BIO_copy_next_retry(b);
+				*buf = '\0';
+				if (i < 0)
+					return ((num > 0) ? num : i);
+				if (i == 0)
+					return (num);
+			}
+			ctx->ibuf_len = i;
+			ctx->ibuf_off = 0;
+		}
+	}
+}
+
+static int
+buffer_puts(BIO *b, const char *str)
+{
+	return (buffer_write(b, str, strlen(str)));
+}
diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c
new file mode 100644
index 0000000..2aed3b8
--- /dev/null
+++ b/crypto/bio/bf_nbio.c
@@ -0,0 +1,255 @@
+/* $OpenBSD: bf_nbio.c,v 1.23 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+/* BIO_put and BIO_get both add to the digest,
+ * BIO_gets returns the digest */
+
+static int nbiof_write(BIO *h, const char *buf, int num);
+static int nbiof_read(BIO *h, char *buf, int size);
+static int nbiof_puts(BIO *h, const char *str);
+static int nbiof_gets(BIO *h, char *str, int size);
+static long nbiof_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int nbiof_new(BIO *h);
+static int nbiof_free(BIO *data);
+static long nbiof_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+
+typedef struct nbio_test_st {
+	/* only set if we sent a 'should retry' error */
+	int lrn;
+	int lwn;
+} NBIO_TEST;
+
+static const BIO_METHOD methods_nbiof = {
+	.type = BIO_TYPE_NBIO_TEST,
+	.name = "non-blocking IO test filter",
+	.bwrite = nbiof_write,
+	.bread = nbiof_read,
+	.bputs = nbiof_puts,
+	.bgets = nbiof_gets,
+	.ctrl = nbiof_ctrl,
+	.create = nbiof_new,
+	.destroy = nbiof_free,
+	.callback_ctrl = nbiof_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_nbio_test(void)
+{
+	return (&methods_nbiof);
+}
+LCRYPTO_ALIAS(BIO_f_nbio_test);
+
+static int
+nbiof_new(BIO *bi)
+{
+	NBIO_TEST *nt;
+
+	if (!(nt = malloc(sizeof(NBIO_TEST))))
+		return (0);
+	nt->lrn = -1;
+	nt->lwn = -1;
+	bi->ptr = (char *)nt;
+	bi->init = 1;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+nbiof_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	free(a->ptr);
+	a->ptr = NULL;
+	a->init = 0;
+	a->flags = 0;
+	return (1);
+}
+
+static int
+nbiof_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+	int num;
+	unsigned char n;
+
+	if (out == NULL)
+		return (0);
+	if (b->next_bio == NULL)
+		return (0);
+
+	BIO_clear_retry_flags(b);
+
+	arc4random_buf(&n, 1);
+	num = (n & 0x07);
+
+	if (outl > num)
+		outl = num;
+
+	if (num == 0) {
+		ret = -1;
+		BIO_set_retry_read(b);
+	} else {
+		ret = BIO_read(b->next_bio, out, outl);
+		if (ret < 0)
+			BIO_copy_next_retry(b);
+	}
+	return (ret);
+}
+
+static int
+nbiof_write(BIO *b, const char *in, int inl)
+{
+	NBIO_TEST *nt;
+	int ret = 0;
+	int num;
+	unsigned char n;
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+	if (b->next_bio == NULL)
+		return (0);
+	nt = (NBIO_TEST *)b->ptr;
+
+	BIO_clear_retry_flags(b);
+
+	if (nt->lwn > 0) {
+		num = nt->lwn;
+		nt->lwn = 0;
+	} else {
+		arc4random_buf(&n, 1);
+		num = (n&7);
+	}
+
+	if (inl > num)
+		inl = num;
+
+	if (num == 0) {
+		ret = -1;
+		BIO_set_retry_write(b);
+	} else {
+		ret = BIO_write(b->next_bio, in, inl);
+		if (ret < 0) {
+			BIO_copy_next_retry(b);
+			nt->lwn = inl;
+		}
+	}
+	return (ret);
+}
+
+static long
+nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret;
+
+	if (b->next_bio == NULL)
+		return (0);
+	switch (cmd) {
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+	case BIO_CTRL_DUP:
+		ret = 0L;
+		break;
+	default:
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	}
+	return (ret);
+}
+
+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);
+}
+
+static int
+nbiof_gets(BIO *bp, char *buf, int size)
+{
+	if (bp->next_bio == NULL)
+		return (0);
+	return (BIO_gets(bp->next_bio, buf, size));
+}
+
+static int
+nbiof_puts(BIO *bp, const char *str)
+{
+	if (bp->next_bio == NULL)
+		return (0);
+	return (BIO_puts(bp->next_bio, str));
+}
diff --git a/crypto/bio/bf_null.c b/crypto/bio/bf_null.c
new file mode 100644
index 0000000..055daeb
--- /dev/null
+++ b/crypto/bio/bf_null.c
@@ -0,0 +1,199 @@
+/* $OpenBSD: bf_null.c,v 1.15 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+/* BIO_put and BIO_get both add to the digest,
+ * BIO_gets returns the digest */
+
+static int nullf_write(BIO *h, const char *buf, int num);
+static int nullf_read(BIO *h, char *buf, int size);
+static int nullf_puts(BIO *h, const char *str);
+static int nullf_gets(BIO *h, char *str, int size);
+static long nullf_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int nullf_new(BIO *h);
+static int nullf_free(BIO *data);
+static long nullf_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+
+static const BIO_METHOD methods_nullf = {
+	.type = BIO_TYPE_NULL_FILTER,
+	.name = "NULL filter",
+	.bwrite = nullf_write,
+	.bread = nullf_read,
+	.bputs = nullf_puts,
+	.bgets = nullf_gets,
+	.ctrl = nullf_ctrl,
+	.create = nullf_new,
+	.destroy = nullf_free,
+	.callback_ctrl = nullf_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_null(void)
+{
+	return (&methods_nullf);
+}
+LCRYPTO_ALIAS(BIO_f_null);
+
+static int
+nullf_new(BIO *bi)
+{
+	bi->init = 1;
+	bi->ptr = NULL;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+nullf_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+/*	a->ptr=NULL;
+	a->init=0;
+	a->flags=0;*/
+	return (1);
+}
+
+static int
+nullf_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+
+	if (out == NULL)
+		return (0);
+	if (b->next_bio == NULL)
+		return (0);
+	ret = BIO_read(b->next_bio, out, outl);
+	BIO_clear_retry_flags(b);
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static int
+nullf_write(BIO *b, const char *in, int inl)
+{
+	int ret = 0;
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+	if (b->next_bio == NULL)
+		return (0);
+	ret = BIO_write(b->next_bio, in, inl);
+	BIO_clear_retry_flags(b);
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static long
+nullf_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret;
+
+	if (b->next_bio == NULL)
+		return (0);
+	switch (cmd) {
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+	case BIO_CTRL_DUP:
+		ret = 0L;
+		break;
+	default:
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+	}
+	return (ret);
+}
+
+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);
+}
+
+static int
+nullf_gets(BIO *bp, char *buf, int size)
+{
+	if (bp->next_bio == NULL)
+		return (0);
+	return (BIO_gets(bp->next_bio, buf, size));
+}
+
+static int
+nullf_puts(BIO *bp, const char *str)
+{
+	if (bp->next_bio == NULL)
+		return (0);
+	return (BIO_puts(bp->next_bio, str));
+}
diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c
new file mode 100644
index 0000000..18e9be8
--- /dev/null
+++ b/crypto/bio/bio_cb.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: bio_cb.c,v 1.19 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+
+long
+BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, long argl,
+    long ret)
+{
+	BIO *b;
+	char buf[256];
+	char *p;
+	int nbuf;
+	long r = 1;
+	size_t p_maxlen;
+
+	if (BIO_CB_RETURN & cmd)
+		r = ret;
+
+	nbuf = snprintf(buf, sizeof(buf), "BIO[%p]: ", bio);
+	if (nbuf < 0)
+		nbuf = 0;	/* Ignore error; continue printing. */
+	if (nbuf >= sizeof(buf))
+		goto out;
+
+	p = buf + nbuf;
+	p_maxlen = sizeof(buf) - nbuf;
+
+	switch (cmd) {
+	case BIO_CB_FREE:
+		snprintf(p, p_maxlen, "Free - %s\n", bio->method->name);
+		break;
+	case BIO_CB_READ:
+		if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+			snprintf(p, p_maxlen,
+			    "read(%d,%lu) - %s fd=%d\n",
+			    bio->num, (unsigned long)argi,
+			    bio->method->name, bio->num);
+		else
+			snprintf(p, p_maxlen, "read(%d,%lu) - %s\n",
+			    bio->num, (unsigned long)argi, bio->method->name);
+		break;
+	case BIO_CB_WRITE:
+		if (bio->method->type & BIO_TYPE_DESCRIPTOR)
+			snprintf(p, p_maxlen,
+			    "write(%d,%lu) - %s fd=%d\n",
+			    bio->num, (unsigned long)argi,
+			    bio->method->name, bio->num);
+		else
+			snprintf(p, p_maxlen, "write(%d,%lu) - %s\n",
+			    bio->num, (unsigned long)argi, bio->method->name);
+		break;
+	case BIO_CB_PUTS:
+		snprintf(p, p_maxlen,
+		    "puts() - %s\n", bio->method->name);
+		break;
+	case BIO_CB_GETS:
+		snprintf(p, p_maxlen, "gets(%lu) - %s\n",
+		    (unsigned long)argi, bio->method->name);
+		break;
+	case BIO_CB_CTRL:
+		snprintf(p, p_maxlen, "ctrl(%lu) - %s\n",
+		    (unsigned long)argi, bio->method->name);
+		break;
+	case BIO_CB_RETURN|BIO_CB_READ:
+		snprintf(p, p_maxlen, "read return %ld\n", ret);
+		break;
+	case BIO_CB_RETURN|BIO_CB_WRITE:
+		snprintf(p, p_maxlen, "write return %ld\n", ret);
+		break;
+	case BIO_CB_RETURN|BIO_CB_GETS:
+		snprintf(p, p_maxlen, "gets return %ld\n", ret);
+		break;
+	case BIO_CB_RETURN|BIO_CB_PUTS:
+		snprintf(p, p_maxlen, "puts return %ld\n", ret);
+		break;
+	case BIO_CB_RETURN|BIO_CB_CTRL:
+		snprintf(p, p_maxlen, "ctrl return %ld\n", ret);
+		break;
+	default:
+		snprintf(p, p_maxlen,
+		    "bio callback - unknown type (%d)\n", cmd);
+		break;
+	}
+
+ out:
+	b = (BIO *)bio->cb_arg;
+	if (b != NULL)
+		BIO_write(b, buf, strlen(buf));
+	else
+		fputs(buf, stderr);
+	return (r);
+}
+LCRYPTO_ALIAS(BIO_debug_callback);
diff --git a/crypto/bio/bio_err.c b/crypto/bio/bio_err.c
new file mode 100644
index 0000000..36fabca
--- /dev/null
+++ b/crypto/bio/bio_err.c
@@ -0,0 +1,120 @@
+/* $OpenBSD: bio_err.c,v 1.20 2023/07/05 21:23:37 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_BIO,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BIO,0,reason)
+
+static ERR_STRING_DATA BIO_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA BIO_str_reasons[] = {
+	{ERR_REASON(BIO_R_ACCEPT_ERROR)          , "accept error"},
+	{ERR_REASON(BIO_R_BAD_FOPEN_MODE)        , "bad fopen mode"},
+	{ERR_REASON(BIO_R_BAD_HOSTNAME_LOOKUP)   , "bad hostname lookup"},
+	{ERR_REASON(BIO_R_BROKEN_PIPE)           , "broken pipe"},
+	{ERR_REASON(BIO_R_CONNECT_ERROR)         , "connect error"},
+	{ERR_REASON(BIO_R_EOF_ON_MEMORY_BIO)     , "EOF on memory BIO"},
+	{ERR_REASON(BIO_R_ERROR_SETTING_NBIO)    , "error setting nbio"},
+	{ERR_REASON(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET), "error setting nbio on accepted socket"},
+	{ERR_REASON(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET), "error setting nbio on accept socket"},
+	{ERR_REASON(BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET), "gethostbyname addr is not af inet"},
+	{ERR_REASON(BIO_R_INVALID_ARGUMENT)      , "invalid argument"},
+	{ERR_REASON(BIO_R_INVALID_IP_ADDRESS)    , "invalid ip address"},
+	{ERR_REASON(BIO_R_INVALID_PORT_NUMBER)   , "invalid port number"},
+	{ERR_REASON(BIO_R_IN_USE)                , "in use"},
+	{ERR_REASON(BIO_R_KEEPALIVE)             , "keepalive"},
+	{ERR_REASON(BIO_R_LENGTH_TOO_LONG)       , "too long"},
+	{ERR_REASON(BIO_R_NBIO_CONNECT_ERROR)    , "nbio connect error"},
+	{ERR_REASON(BIO_R_NO_ACCEPT_PORT_SPECIFIED), "no accept port specified"},
+	{ERR_REASON(BIO_R_NO_HOSTNAME_SPECIFIED) , "no hostname specified"},
+	{ERR_REASON(BIO_R_NO_PORT_DEFINED)       , "no port defined"},
+	{ERR_REASON(BIO_R_NO_PORT_SPECIFIED)     , "no port specified"},
+	{ERR_REASON(BIO_R_NO_SUCH_FILE)          , "no such file"},
+	{ERR_REASON(BIO_R_NULL_PARAMETER)        , "null parameter"},
+	{ERR_REASON(BIO_R_TAG_MISMATCH)          , "tag mismatch"},
+	{ERR_REASON(BIO_R_UNABLE_TO_BIND_SOCKET) , "unable to bind socket"},
+	{ERR_REASON(BIO_R_UNABLE_TO_CREATE_SOCKET), "unable to create socket"},
+	{ERR_REASON(BIO_R_UNABLE_TO_LISTEN_SOCKET), "unable to listen socket"},
+	{ERR_REASON(BIO_R_UNINITIALIZED)         , "uninitialized"},
+	{ERR_REASON(BIO_R_UNSUPPORTED_METHOD)    , "unsupported method"},
+	{ERR_REASON(BIO_R_WRITE_TO_READ_ONLY_BIO), "write to read only BIO"},
+	{ERR_REASON(BIO_R_WSASTARTUP)            , "WSAStartup"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_BIO_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(BIO_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, BIO_str_functs);
+		ERR_load_strings(0, BIO_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_BIO_strings);
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
new file mode 100644
index 0000000..b058af0
--- /dev/null
+++ b/crypto/bio/bio_lib.c
@@ -0,0 +1,904 @@
+/* $OpenBSD: bio_lib.c,v 1.48 2023/08/07 10:58:56 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+/*
+ * Helper function to work out whether to call the new style callback or the old
+ * one, and translate between the two.
+ *
+ * This has a long return type for consistency with the old callback. Similarly
+ * 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)
+{
+	long ret;
+	int bareoper;
+
+	if (b->callback_ex != NULL)
+		return b->callback_ex(b, oper, argp, len, argi, argl, inret,
+		    processed);
+
+	/*
+	 * We have an old style callback, so we will have to do nasty casts and
+	 * check for overflows.
+	 */
+
+	bareoper = oper & ~BIO_CB_RETURN;
+
+	if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE ||
+	    bareoper == BIO_CB_GETS) {
+		/* In this case len is set and should be used instead of argi. */
+		if (len > INT_MAX)
+			return -1;
+		argi = (int)len;
+	}
+
+	if (inret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
+		if (*processed > INT_MAX)
+			return -1;
+		inret = *processed;
+	}
+
+	ret = b->callback(b, oper, argp, argi, argl, inret);
+
+	if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
+		*processed = (size_t)ret;
+		ret = 1;
+	}
+
+	return ret;
+}
+
+int
+BIO_get_new_index(void)
+{
+	static int bio_type_index = BIO_TYPE_START;
+	int index;
+
+	/* The index will collide with the BIO flag bits if it exceeds 255. */
+	index = CRYPTO_add(&bio_type_index, 1, CRYPTO_LOCK_BIO);
+	if (index > 255)
+		return -1;
+
+	return index;
+}
+LCRYPTO_ALIAS(BIO_get_new_index);
+
+BIO *
+BIO_new(const BIO_METHOD *method)
+{
+	BIO *ret = NULL;
+
+	/* XXX calloc */
+	ret = malloc(sizeof(BIO));
+	if (ret == NULL) {
+		BIOerror(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	if (!BIO_set(ret, method)) {
+		free(ret);
+		ret = NULL;
+	}
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new);
+
+int
+BIO_set(BIO *bio, const BIO_METHOD *method)
+{
+	bio->method = method;
+	bio->callback = NULL;
+	bio->callback_ex = NULL;
+	bio->cb_arg = NULL;
+	bio->init = 0;
+	bio->shutdown = 1;
+	bio->flags = 0;
+	bio->retry_reason = 0;
+	bio->num = 0;
+	bio->ptr = NULL;
+	bio->prev_bio = NULL;
+	bio->next_bio = NULL;
+	bio->references = 1;
+	bio->num_read = 0L;
+	bio->num_write = 0L;
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
+	if (method->create != NULL) {
+		if (!method->create(bio)) {
+			CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
+			    &bio->ex_data);
+			return (0);
+		}
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_set);
+
+int
+BIO_free(BIO *a)
+{
+	int ret;
+
+	if (a == NULL)
+		return (0);
+
+	if (CRYPTO_add(&a->references, -1, CRYPTO_LOCK_BIO) > 0)
+		return (1);
+
+	if (a->callback != NULL || a->callback_ex != NULL) {
+		if ((ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0,
+		    0L, 1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
+
+	if (a->method != NULL && a->method->destroy != NULL)
+		a->method->destroy(a);
+	free(a);
+	return (1);
+}
+LCRYPTO_ALIAS(BIO_free);
+
+void
+BIO_vfree(BIO *a)
+{
+	BIO_free(a);
+}
+LCRYPTO_ALIAS(BIO_vfree);
+
+int
+BIO_up_ref(BIO *bio)
+{
+	int refs = CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO);
+	return (refs > 1) ? 1 : 0;
+}
+LCRYPTO_ALIAS(BIO_up_ref);
+
+void *
+BIO_get_data(BIO *a)
+{
+	return (a->ptr);
+}
+LCRYPTO_ALIAS(BIO_get_data);
+
+void
+BIO_set_data(BIO *a, void *ptr)
+{
+	a->ptr = ptr;
+}
+LCRYPTO_ALIAS(BIO_set_data);
+
+int
+BIO_get_init(BIO *a)
+{
+	return a->init;
+}
+LCRYPTO_ALIAS(BIO_get_init);
+
+void
+BIO_set_init(BIO *a, int init)
+{
+	a->init = init;
+}
+LCRYPTO_ALIAS(BIO_set_init);
+
+int
+BIO_get_shutdown(BIO *a)
+{
+	return (a->shutdown);
+}
+LCRYPTO_ALIAS(BIO_get_shutdown);
+
+void
+BIO_set_shutdown(BIO *a, int shut)
+{
+	a->shutdown = shut;
+}
+LCRYPTO_ALIAS(BIO_set_shutdown);
+
+void
+BIO_clear_flags(BIO *b, int flags)
+{
+	b->flags &= ~flags;
+}
+LCRYPTO_ALIAS(BIO_clear_flags);
+
+int
+BIO_test_flags(const BIO *b, int flags)
+{
+	return (b->flags & flags);
+}
+LCRYPTO_ALIAS(BIO_test_flags);
+
+void
+BIO_set_flags(BIO *b, int flags)
+{
+	b->flags |= flags;
+}
+LCRYPTO_ALIAS(BIO_set_flags);
+
+BIO_callback_fn
+BIO_get_callback(const BIO *b)
+{
+	return b->callback;
+}
+LCRYPTO_ALIAS(BIO_get_callback);
+
+void
+BIO_set_callback(BIO *b, BIO_callback_fn cb)
+{
+	b->callback = cb;
+}
+LCRYPTO_ALIAS(BIO_set_callback);
+
+BIO_callback_fn_ex
+BIO_get_callback_ex(const BIO *b)
+{
+	return b->callback_ex;
+}
+LCRYPTO_ALIAS(BIO_get_callback_ex);
+
+void
+BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex cb)
+{
+	b->callback_ex = cb;
+}
+LCRYPTO_ALIAS(BIO_set_callback_ex);
+
+void
+BIO_set_callback_arg(BIO *b, char *arg)
+{
+	b->cb_arg = arg;
+}
+LCRYPTO_ALIAS(BIO_set_callback_arg);
+
+char *
+BIO_get_callback_arg(const BIO *b)
+{
+	return b->cb_arg;
+}
+LCRYPTO_ALIAS(BIO_get_callback_arg);
+
+const char *
+BIO_method_name(const BIO *b)
+{
+	return b->method->name;
+}
+LCRYPTO_ALIAS(BIO_method_name);
+
+int
+BIO_method_type(const BIO *b)
+{
+	return b->method->type;
+}
+LCRYPTO_ALIAS(BIO_method_type);
+
+int
+BIO_read(BIO *b, void *out, int outl)
+{
+	size_t readbytes = 0;
+	int ret;
+
+	if (b == NULL) {
+		BIOerror(ERR_R_PASSED_NULL_PARAMETER);
+		return (-1);
+	}
+
+	if (outl <= 0)
+		return (0);
+
+	if (out == NULL) {
+		BIOerror(ERR_R_PASSED_NULL_PARAMETER);
+		return (-1);
+	}
+
+	if (b->method == NULL || b->method->bread == NULL) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = (int)bio_call_callback(b, BIO_CB_READ, out, outl, 0,
+		    0L, 1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	if (!b->init) {
+		BIOerror(BIO_R_UNINITIALIZED);
+		return (-2);
+	}
+
+	if ((ret = b->method->bread(b, out, outl)) > 0)
+		readbytes = (size_t)ret;
+
+	b->num_read += readbytes;
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN,
+		    out, outl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
+	}
+
+	if (ret > 0) {
+		if (readbytes > INT_MAX) {
+			BIOerror(BIO_R_LENGTH_TOO_LONG);
+			ret = -1;
+		} else {
+			ret = (int)readbytes;
+		}
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_read);
+
+int
+BIO_write(BIO *b, const void *in, int inl)
+{
+	size_t writebytes = 0;
+	int ret;
+
+	/* Not an error. Things like SMIME_text() assume that this succeeds. */
+	if (b == NULL)
+		return (0);
+
+	if (inl <= 0)
+		return (0);
+
+	if (in == NULL) {
+		BIOerror(ERR_R_PASSED_NULL_PARAMETER);
+		return (-1);
+	}
+
+	if (b->method == NULL || b->method->bwrite == NULL) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, in, inl, 0,
+		    0L, 1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	if (!b->init) {
+		BIOerror(BIO_R_UNINITIALIZED);
+		return (-2);
+	}
+
+	if ((ret = b->method->bwrite(b, in, inl)) > 0)
+		writebytes = ret;
+
+	b->num_write += writebytes;
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN,
+		    in, inl, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
+	}
+
+	if (ret > 0) {
+		if (writebytes > INT_MAX) {
+			BIOerror(BIO_R_LENGTH_TOO_LONG);
+			ret = -1;
+		} else {
+			ret = (int)writebytes;
+		}
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_write);
+
+int
+BIO_puts(BIO *b, const char *in)
+{
+	size_t writebytes = 0;
+	int ret;
+
+	if (b == NULL || b->method == NULL || b->method->bputs == NULL) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = (int)bio_call_callback(b, BIO_CB_PUTS, in, 0, 0, 0L,
+		    1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	if (!b->init) {
+		BIOerror(BIO_R_UNINITIALIZED);
+		return (-2);
+	}
+
+	if ((ret = b->method->bputs(b, in)) > 0)
+		writebytes = ret;
+
+	b->num_write += writebytes;
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN,
+		    in, 0, 0, 0L, (ret > 0) ? 1 : ret, &writebytes);
+	}
+
+	if (ret > 0) {
+		if (writebytes > INT_MAX) {
+			BIOerror(BIO_R_LENGTH_TOO_LONG);
+			ret = -1;
+		} else {
+			ret = (int)writebytes;
+		}
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_puts);
+
+int
+BIO_gets(BIO *b, char *in, int inl)
+{
+	size_t readbytes = 0;
+	int ret;
+
+	if (b == NULL || b->method == NULL || b->method->bgets == NULL) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = (int)bio_call_callback(b, BIO_CB_GETS, in, inl, 0, 0L,
+		    1, NULL)) <= 0)
+			return (ret);
+	}
+
+	if (!b->init) {
+		BIOerror(BIO_R_UNINITIALIZED);
+		return (-2);
+	}
+
+	if ((ret = b->method->bgets(b, in, inl)) > 0)
+		readbytes = ret;
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, in,
+		    inl, 0, 0L, (ret > 0) ? 1 : ret, &readbytes);
+	}
+
+	if (ret > 0) {
+		if (readbytes > INT_MAX) {
+			BIOerror(BIO_R_LENGTH_TOO_LONG);
+			ret = -1;
+		} else {
+			ret = (int)readbytes;
+		}
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_gets);
+
+int
+BIO_indent(BIO *b, int indent, int max)
+{
+	if (indent > max)
+		indent = max;
+	if (indent <= 0)
+		return 1;
+	if (BIO_printf(b, "%*s", indent, "") <= 0)
+		return 0;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_indent);
+
+long
+BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
+{
+	int i;
+
+	i = iarg;
+	return (BIO_ctrl(b, cmd, larg, (char *)&i));
+}
+LCRYPTO_ALIAS(BIO_int_ctrl);
+
+char *
+BIO_ptr_ctrl(BIO *b, int cmd, long larg)
+{
+	char *p = NULL;
+
+	if (BIO_ctrl(b, cmd, larg, (char *)&p) <= 0)
+		return (NULL);
+	else
+		return (p);
+}
+LCRYPTO_ALIAS(BIO_ptr_ctrl);
+
+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) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg,
+		    1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	ret = b->method->ctrl(b, cmd, larg, parg);
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0,
+		    cmd, larg, ret, NULL);
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_ctrl);
+
+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) {
+		BIOerror(BIO_R_UNSUPPORTED_METHOD);
+		return (-2);
+	}
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		if ((ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0,
+		    cmd, 0, 1L, NULL)) <= 0)
+			return (ret);
+	}
+
+	ret = b->method->callback_ctrl(b, cmd, fp);
+
+	if (b->callback != NULL || b->callback_ex != NULL) {
+		ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN,
+		    (void *)&fp, 0, cmd, 0, ret, NULL);
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_callback_ctrl);
+
+/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
+ * do; but those macros have inappropriate return type, and for interfacing
+ * from other programming languages, C macros aren't much of a help anyway. */
+size_t
+BIO_ctrl_pending(BIO *bio)
+{
+	return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
+}
+LCRYPTO_ALIAS(BIO_ctrl_pending);
+
+size_t
+BIO_ctrl_wpending(BIO *bio)
+{
+	return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
+}
+LCRYPTO_ALIAS(BIO_ctrl_wpending);
+
+
+/*
+ * Append "bio" to the end of the chain containing "b":
+ * Two chains "b -> lb" and "oldhead -> bio"
+ * become two chains "b -> lb -> bio" and "oldhead".
+ */
+BIO *
+BIO_push(BIO *b, BIO *bio)
+{
+	BIO *lb;
+
+	if (b == NULL)
+		return (bio);
+	lb = b;
+	while (lb->next_bio != NULL)
+		lb = lb->next_bio;
+	lb->next_bio = bio;
+	if (bio != NULL) {
+		if (bio->prev_bio != NULL)
+			bio->prev_bio->next_bio = NULL;
+		bio->prev_bio = lb;
+	}
+	/* called to do internal processing */
+	BIO_ctrl(b, BIO_CTRL_PUSH, 0, lb);
+	return (b);
+}
+LCRYPTO_ALIAS(BIO_push);
+
+/* Remove the first and return the rest */
+BIO *
+BIO_pop(BIO *b)
+{
+	BIO *ret;
+
+	if (b == NULL)
+		return (NULL);
+	ret = b->next_bio;
+
+	BIO_ctrl(b, BIO_CTRL_POP, 0, b);
+
+	if (b->prev_bio != NULL)
+		b->prev_bio->next_bio = b->next_bio;
+	if (b->next_bio != NULL)
+		b->next_bio->prev_bio = b->prev_bio;
+
+	b->next_bio = NULL;
+	b->prev_bio = NULL;
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_pop);
+
+BIO *
+BIO_get_retry_BIO(BIO *bio, int *reason)
+{
+	BIO *b, *last;
+
+	b = last = bio;
+	for (;;) {
+		if (!BIO_should_retry(b))
+			break;
+		last = b;
+		b = b->next_bio;
+		if (b == NULL)
+			break;
+	}
+	if (reason != NULL)
+		*reason = last->retry_reason;
+	return (last);
+}
+LCRYPTO_ALIAS(BIO_get_retry_BIO);
+
+int
+BIO_get_retry_reason(BIO *bio)
+{
+	return (bio->retry_reason);
+}
+LCRYPTO_ALIAS(BIO_get_retry_reason);
+
+void
+BIO_set_retry_reason(BIO *bio, int reason)
+{
+	bio->retry_reason = reason;
+}
+LCRYPTO_ALIAS(BIO_set_retry_reason);
+
+BIO *
+BIO_find_type(BIO *bio, int type)
+{
+	int mt, mask;
+
+	if (!bio)
+		return NULL;
+	mask = type & 0xff;
+	do {
+		if (bio->method != NULL) {
+			mt = bio->method->type;
+			if (!mask) {
+				if (mt & type)
+					return (bio);
+			} else if (mt == type)
+				return (bio);
+		}
+		bio = bio->next_bio;
+	} while (bio != NULL);
+	return (NULL);
+}
+LCRYPTO_ALIAS(BIO_find_type);
+
+BIO *
+BIO_next(BIO *b)
+{
+	if (!b)
+		return NULL;
+	return b->next_bio;
+}
+LCRYPTO_ALIAS(BIO_next);
+
+/*
+ * Two chains "bio -> oldtail" and "oldhead -> next" become
+ * three chains "oldtail", "bio -> next", and "oldhead".
+ */
+void
+BIO_set_next(BIO *bio, BIO *next)
+{
+	/* Cut off the tail of the chain containing bio after bio. */
+	if (bio->next_bio != NULL)
+		bio->next_bio->prev_bio = NULL;
+
+	/* Cut off the head of the chain containing next before next. */
+	if (next != NULL && next->prev_bio != NULL)
+		next->prev_bio->next_bio = NULL;
+
+	/* Append the chain starting at next to the chain ending at bio. */
+	bio->next_bio = next;
+	if (next != NULL)
+		next->prev_bio = bio;
+}
+LCRYPTO_ALIAS(BIO_set_next);
+
+void
+BIO_free_all(BIO *bio)
+{
+	BIO *b;
+	int ref;
+
+	while (bio != NULL) {
+		b = bio;
+		ref = b->references;
+		bio = bio->next_bio;
+		BIO_free(b);
+		/* Since ref count > 1, don't free anyone else. */
+		if (ref > 1)
+			break;
+	}
+}
+LCRYPTO_ALIAS(BIO_free_all);
+
+BIO *
+BIO_dup_chain(BIO *in)
+{
+	BIO *new_chain = NULL, *new_bio = NULL, *tail = NULL;
+	BIO *bio;
+
+	for (bio = in; bio != NULL; bio = bio->next_bio) {
+		if ((new_bio = BIO_new(bio->method)) == NULL)
+			goto err;
+		new_bio->callback = bio->callback;
+		new_bio->callback_ex = bio->callback_ex;
+		new_bio->cb_arg = bio->cb_arg;
+		new_bio->init = bio->init;
+		new_bio->shutdown = bio->shutdown;
+		new_bio->flags = bio->flags;
+		new_bio->num = bio->num;
+
+		if (!BIO_dup_state(bio, new_bio))
+			goto err;
+
+		if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO,
+		    &new_bio->ex_data, &bio->ex_data))
+			goto err;
+
+		if (BIO_push(tail, new_bio) == NULL)
+			goto err;
+
+		tail = new_bio;
+		if (new_chain == NULL)
+			new_chain = new_bio;
+	}
+
+	return new_chain;
+
+ err:
+	BIO_free(new_bio);
+	BIO_free_all(new_chain);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(BIO_dup_chain);
+
+void
+BIO_copy_next_retry(BIO *b)
+{
+	BIO_set_flags(b, BIO_get_retry_flags(b->next_bio));
+	b->retry_reason = b->next_bio->retry_reason;
+}
+LCRYPTO_ALIAS(BIO_copy_next_retry);
+
+int
+BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
+	    new_func, dup_func, free_func);
+}
+
+int
+BIO_set_ex_data(BIO *bio, int idx, void *data)
+{
+	return (CRYPTO_set_ex_data(&(bio->ex_data), idx, data));
+}
+LCRYPTO_ALIAS(BIO_set_ex_data);
+
+void *
+BIO_get_ex_data(BIO *bio, int idx)
+{
+	return (CRYPTO_get_ex_data(&(bio->ex_data), idx));
+}
+LCRYPTO_ALIAS(BIO_get_ex_data);
+
+unsigned long
+BIO_number_read(BIO *bio)
+{
+	if (bio)
+		return bio->num_read;
+	return 0;
+}
+LCRYPTO_ALIAS(BIO_number_read);
+
+unsigned long
+BIO_number_written(BIO *bio)
+{
+	if (bio)
+		return bio->num_write;
+	return 0;
+}
+LCRYPTO_ALIAS(BIO_number_written);
diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h
new file mode 100644
index 0000000..4eecf7e
--- /dev/null
+++ b/crypto/bio/bio_local.h
@@ -0,0 +1,123 @@
+/* $OpenBSD: bio_local.h,v 1.5 2022/12/02 19:44:04 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BIO_LOCAL_H
+#define HEADER_BIO_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+struct bio_method_st {
+	int type;
+	const char *name;
+	int (*bwrite)(BIO *, const char *, int);
+	int (*bread)(BIO *, char *, int);
+	int (*bputs)(BIO *, const char *);
+	int (*bgets)(BIO *, char *, int);
+	long (*ctrl)(BIO *, int, long, void *);
+	int (*create)(BIO *);
+	int (*destroy)(BIO *);
+	long (*callback_ctrl)(BIO *, int, BIO_info_cb *);
+} /* BIO_METHOD */;
+
+struct bio_st {
+	const BIO_METHOD *method;
+	BIO_callback_fn callback;
+	BIO_callback_fn_ex callback_ex;
+	char *cb_arg; /* first argument for the callback */
+
+	int init;
+	int shutdown;
+	int flags;	/* extra storage */
+	int retry_reason;
+	int num;
+	void *ptr;
+	struct bio_st *next_bio;	/* used by filter BIOs */
+	struct bio_st *prev_bio;	/* used by filter BIOs */
+	int references;
+	unsigned long num_read;
+	unsigned long num_write;
+
+	CRYPTO_EX_DATA ex_data;
+} /* BIO */;
+
+typedef struct bio_f_buffer_ctx_struct {
+	/* Buffers are setup like this:
+	 *
+	 * <---------------------- size ----------------------->
+	 * +---------------------------------------------------+
+	 * | consumed | remaining          | free space        |
+	 * +---------------------------------------------------+
+	 * <-- off --><------- len ------->
+	 */
+
+	/* BIO *bio; */ /* this is now in the BIO struct */
+	int ibuf_size;	/* how big is the input buffer */
+	int obuf_size;	/* how big is the output buffer */
+
+	char *ibuf;	/* the char array */
+	int ibuf_len;	/* how many bytes are in it */
+	int ibuf_off;	/* write/read offset */
+
+	char *obuf;	/* the char array */
+	int obuf_len;	/* how many bytes are in it */
+	int obuf_off;	/* write/read offset */
+} BIO_F_BUFFER_CTX;
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_BIO_LOCAL_H */
diff --git a/crypto/bio/bio_meth.c b/crypto/bio/bio_meth.c
new file mode 100644
index 0000000..37f866a
--- /dev/null
+++ b/crypto/bio/bio_meth.c
@@ -0,0 +1,165 @@
+/*	$OpenBSD: bio_meth.c,v 1.9 2023/07/05 21:23:37 beck Exp $	*/
+/*
+ * Copyright (c) 2018 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+BIO_METHOD *
+BIO_meth_new(int type, const char *name)
+{
+	BIO_METHOD *biom;
+
+	if ((biom = calloc(1, sizeof(*biom))) == NULL)
+		return NULL;
+
+	biom->type = type;
+	biom->name = name;
+
+	return biom;
+}
+LCRYPTO_ALIAS(BIO_meth_new);
+
+void
+BIO_meth_free(BIO_METHOD *biom)
+{
+	free(biom);
+}
+LCRYPTO_ALIAS(BIO_meth_free);
+
+int
+(*BIO_meth_get_write(const BIO_METHOD *biom))(BIO *, const char *, int)
+{
+	return biom->bwrite;
+}
+LCRYPTO_ALIAS(BIO_meth_get_write);
+
+int
+BIO_meth_set_write(BIO_METHOD *biom, int (*write)(BIO *, const char *, int))
+{
+	biom->bwrite = write;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_write);
+
+int
+(*BIO_meth_get_read(const BIO_METHOD *biom))(BIO *, char *, int)
+{
+	return biom->bread;
+}
+LCRYPTO_ALIAS(BIO_meth_get_read);
+
+int
+BIO_meth_set_read(BIO_METHOD *biom, int (*read)(BIO *, char *, int))
+{
+	biom->bread = read;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_read);
+
+int
+(*BIO_meth_get_puts(const BIO_METHOD *biom))(BIO *, const char *)
+{
+	return biom->bputs;
+}
+LCRYPTO_ALIAS(BIO_meth_get_puts);
+
+int
+BIO_meth_set_puts(BIO_METHOD *biom, int (*puts)(BIO *, const char *))
+{
+	biom->bputs = puts;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_puts);
+
+int
+(*BIO_meth_get_gets(const BIO_METHOD *biom))(BIO *, char *, int)
+{
+	return biom->bgets;
+}
+LCRYPTO_ALIAS(BIO_meth_get_gets);
+
+int
+BIO_meth_set_gets(BIO_METHOD *biom, int (*gets)(BIO *, char *, int))
+{
+	biom->bgets = gets;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_gets);
+
+long
+(*BIO_meth_get_ctrl(const BIO_METHOD *biom))(BIO *, int, long, void *)
+{
+	return biom->ctrl;
+}
+LCRYPTO_ALIAS(BIO_meth_get_ctrl);
+
+int
+BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl)(BIO *, int, long, void *))
+{
+	biom->ctrl = ctrl;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_ctrl);
+
+int
+(*BIO_meth_get_create(const BIO_METHOD *biom))(BIO *)
+{
+	return biom->create;
+}
+LCRYPTO_ALIAS(BIO_meth_get_create);
+
+int
+BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *))
+{
+	biom->create = create;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_create);
+
+int
+(*BIO_meth_get_destroy(const BIO_METHOD *biom))(BIO *)
+{
+	return biom->destroy;
+}
+LCRYPTO_ALIAS(BIO_meth_get_destroy);
+
+int
+BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *))
+{
+	biom->destroy = destroy;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_destroy);
+
+long
+(*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *)
+{
+	return biom->callback_ctrl;
+}
+LCRYPTO_ALIAS(BIO_meth_get_callback_ctrl);
+
+int
+BIO_meth_set_callback_ctrl(BIO_METHOD *biom,
+    long (*callback_ctrl)(BIO *, int, BIO_info_cb *))
+{
+	biom->callback_ctrl = callback_ctrl;
+	return 1;
+}
+LCRYPTO_ALIAS(BIO_meth_set_callback_ctrl);
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
new file mode 100644
index 0000000..d74c710
--- /dev/null
+++ b/crypto/bio/bss_acpt.c
@@ -0,0 +1,456 @@
+/* $OpenBSD: bss_acpt.c,v 1.31 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+#define SOCKET_PROTOCOL IPPROTO_TCP
+
+typedef struct bio_accept_st {
+	int state;
+	char *param_addr;
+
+	int accept_sock;
+	int accept_nbio;
+
+	char *addr;
+	int nbio;
+	/* If 0, it means normal, if 1, do a connect on bind failure,
+	 * and if there is no-one listening, bind with SO_REUSEADDR.
+	 * If 2, always use SO_REUSEADDR. */
+	int bind_mode;
+	BIO *bio_chain;
+} BIO_ACCEPT;
+
+static int acpt_write(BIO *h, const char *buf, int num);
+static int acpt_read(BIO *h, char *buf, int size);
+static int acpt_puts(BIO *h, const char *str);
+static long acpt_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int acpt_new(BIO *h);
+static int acpt_free(BIO *data);
+static int acpt_state(BIO *b, BIO_ACCEPT *c);
+static void acpt_close_socket(BIO *data);
+static BIO_ACCEPT *BIO_ACCEPT_new(void );
+static void BIO_ACCEPT_free(BIO_ACCEPT *a);
+
+#define ACPT_S_BEFORE			1
+#define ACPT_S_GET_ACCEPT_SOCKET	2
+#define ACPT_S_OK			3
+
+static const BIO_METHOD methods_acceptp = {
+	.type = BIO_TYPE_ACCEPT,
+	.name = "socket accept",
+	.bwrite = acpt_write,
+	.bread = acpt_read,
+	.bputs = acpt_puts,
+	.ctrl = acpt_ctrl,
+	.create = acpt_new,
+	.destroy = acpt_free
+};
+
+const BIO_METHOD *
+BIO_s_accept(void)
+{
+	return (&methods_acceptp);
+}
+LCRYPTO_ALIAS(BIO_s_accept);
+
+static int
+acpt_new(BIO *bi)
+{
+	BIO_ACCEPT *ba;
+
+	bi->init = 0;
+	bi->num = -1;
+	bi->flags = 0;
+	if ((ba = BIO_ACCEPT_new()) == NULL)
+		return (0);
+	bi->ptr = (char *)ba;
+	ba->state = ACPT_S_BEFORE;
+	bi->shutdown = 1;
+	return (1);
+}
+
+static BIO_ACCEPT *
+BIO_ACCEPT_new(void)
+{
+	BIO_ACCEPT *ret;
+
+	if ((ret = calloc(1, sizeof(BIO_ACCEPT))) == NULL)
+		return (NULL);
+	ret->accept_sock = -1;
+	ret->bind_mode = BIO_BIND_NORMAL;
+	return (ret);
+}
+
+static void
+BIO_ACCEPT_free(BIO_ACCEPT *a)
+{
+	if (a == NULL)
+		return;
+
+	free(a->param_addr);
+	free(a->addr);
+	BIO_free(a->bio_chain);
+	free(a);
+}
+
+static void
+acpt_close_socket(BIO *bio)
+{
+	BIO_ACCEPT *c;
+
+	c = (BIO_ACCEPT *)bio->ptr;
+	if (c->accept_sock != -1) {
+		shutdown(c->accept_sock, SHUT_RDWR);
+		close(c->accept_sock);
+		c->accept_sock = -1;
+		bio->num = -1;
+	}
+}
+
+static int
+acpt_free(BIO *a)
+{
+	BIO_ACCEPT *data;
+
+	if (a == NULL)
+		return (0);
+	data = (BIO_ACCEPT *)a->ptr;
+
+	if (a->shutdown) {
+		acpt_close_socket(a);
+		BIO_ACCEPT_free(data);
+		a->ptr = NULL;
+		a->flags = 0;
+		a->init = 0;
+	}
+	return (1);
+}
+
+static int
+acpt_state(BIO *b, BIO_ACCEPT *c)
+{
+	BIO *bio = NULL, *dbio;
+	int s = -1;
+	int i;
+
+again:
+	switch (c->state) {
+	case ACPT_S_BEFORE:
+		if (c->param_addr == NULL) {
+			BIOerror(BIO_R_NO_ACCEPT_PORT_SPECIFIED);
+			return (-1);
+		}
+		s = BIO_get_accept_socket(c->param_addr, c->bind_mode);
+		if (s == -1)
+			return (-1);
+
+		if (c->accept_nbio) {
+			if (!BIO_socket_nbio(s, 1)) {
+				close(s);
+				BIOerror(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET);
+				return (-1);
+			}
+		}
+		c->accept_sock = s;
+		b->num = s;
+		c->state = ACPT_S_GET_ACCEPT_SOCKET;
+		return (1);
+		/* break; */
+	case ACPT_S_GET_ACCEPT_SOCKET:
+		if (b->next_bio != NULL) {
+			c->state = ACPT_S_OK;
+			goto again;
+		}
+		BIO_clear_retry_flags(b);
+		b->retry_reason = 0;
+		i = BIO_accept(c->accept_sock, &(c->addr));
+
+		/* -2 return means we should retry */
+		if (i == -2) {
+			BIO_set_retry_special(b);
+			b->retry_reason = BIO_RR_ACCEPT;
+			return -1;
+		}
+
+		if (i < 0)
+			return (i);
+
+		bio = BIO_new_socket(i, BIO_CLOSE);
+		if (bio == NULL)
+			goto err;
+
+		BIO_set_callback(bio, BIO_get_callback(b));
+		BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
+
+		if (c->nbio) {
+			if (!BIO_socket_nbio(i, 1)) {
+				BIOerror(BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET);
+				goto err;
+			}
+		}
+
+		/* If the accept BIO has an bio_chain, we dup it and
+		 * put the new socket at the end. */
+		if (c->bio_chain != NULL) {
+			if ((dbio = BIO_dup_chain(c->bio_chain)) == NULL)
+				goto err;
+			if (!BIO_push(dbio, bio)) goto err;
+				bio = dbio;
+		}
+		if (BIO_push(b, bio)
+			== NULL) goto err;
+
+		c->state = ACPT_S_OK;
+		return (1);
+
+err:
+		if (bio != NULL)
+			BIO_free(bio);
+		return (0);
+		/* break; */
+	case ACPT_S_OK:
+		if (b->next_bio == NULL) {
+			c->state = ACPT_S_GET_ACCEPT_SOCKET;
+			goto again;
+		}
+		return (1);
+		/* break; */
+	default:
+		return (0);
+		/* break; */
+	}
+}
+
+static int
+acpt_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+	BIO_ACCEPT *data;
+
+	BIO_clear_retry_flags(b);
+	data = (BIO_ACCEPT *)b->ptr;
+
+	while (b->next_bio == NULL) {
+		ret = acpt_state(b, data);
+		if (ret <= 0)
+			return (ret);
+	}
+
+	ret = BIO_read(b->next_bio, out, outl);
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static int
+acpt_write(BIO *b, const char *in, int inl)
+{
+	int ret;
+	BIO_ACCEPT *data;
+
+	BIO_clear_retry_flags(b);
+	data = (BIO_ACCEPT *)b->ptr;
+
+	while (b->next_bio == NULL) {
+		ret = acpt_state(b, data);
+		if (ret <= 0)
+			return (ret);
+	}
+
+	ret = BIO_write(b->next_bio, in, inl);
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static long
+acpt_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	int *ip;
+	long ret = 1;
+	BIO_ACCEPT *data;
+	char **pp;
+
+	data = (BIO_ACCEPT *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		ret = 0;
+		data->state = ACPT_S_BEFORE;
+		acpt_close_socket(b);
+		b->flags = 0;
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		/* use this one to start the connection */
+		ret = (long)acpt_state(b, data);
+		break;
+	case BIO_C_SET_ACCEPT:
+		if (ptr != NULL) {
+			if (num == 0) {
+				b->init = 1;
+				free(data->param_addr);
+				data->param_addr = strdup(ptr);
+			} else if (num == 1) {
+				data->accept_nbio = (ptr != NULL);
+			} else if (num == 2) {
+				BIO_free(data->bio_chain);
+				data->bio_chain = (BIO *)ptr;
+			}
+		}
+		break;
+	case BIO_C_SET_NBIO:
+		data->nbio = (int)num;
+		break;
+	case BIO_C_SET_FD:
+		b->init = 1;
+		b->num= *((int *)ptr);
+		data->accept_sock = b->num;
+		data->state = ACPT_S_GET_ACCEPT_SOCKET;
+		b->shutdown = (int)num;
+		b->init = 1;
+		break;
+	case BIO_C_GET_FD:
+		if (b->init) {
+			ip = (int *)ptr;
+			if (ip != NULL)
+				*ip = data->accept_sock;
+			ret = data->accept_sock;
+		} else
+			ret = -1;
+		break;
+	case BIO_C_GET_ACCEPT:
+		if (b->init) {
+			if (ptr != NULL) {
+				pp = (char **)ptr;
+				*pp = data->param_addr;
+			} else
+				ret = -1;
+		} else
+			ret = -1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_WPENDING:
+		ret = 0;
+		break;
+	case BIO_CTRL_FLUSH:
+		break;
+	case BIO_C_SET_BIND_MODE:
+		data->bind_mode = (int)num;
+		break;
+	case BIO_C_GET_BIND_MODE:
+		ret = (long)data->bind_mode;
+		break;
+	case BIO_CTRL_DUP:
+/*		dbio=(BIO *)ptr;
+		if (data->param_port) EAY EAY
+			BIO_set_port(dbio,data->param_port);
+		if (data->param_hostname)
+			BIO_set_hostname(dbio,data->param_hostname);
+		BIO_set_nbio(dbio,data->nbio);
+*/
+		break;
+
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+acpt_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = acpt_write(bp, str, n);
+	return (ret);
+}
+
+BIO *
+BIO_new_accept(const char *str)
+{
+	BIO *ret;
+
+	ret = BIO_new(BIO_s_accept());
+	if (ret == NULL)
+		return (NULL);
+	if (BIO_set_accept_port(ret, str))
+		return (ret);
+	else {
+		BIO_free(ret);
+		return (NULL);
+	}
+}
+LCRYPTO_ALIAS(BIO_new_accept);
diff --git a/crypto/bio/bss_bio.c b/crypto/bio/bss_bio.c
new file mode 100644
index 0000000..9a3215a
--- /dev/null
+++ b/crypto/bio/bss_bio.c
@@ -0,0 +1,640 @@
+/* $OpenBSD: bss_bio.c,v 1.28 2023/07/28 10:13:50 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* Special method for a BIO where the other endpoint is also a BIO
+ * of this kind, handled by the same thread (i.e. the "peer" is actually
+ * ourselves, wearing a different hat).
+ * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces
+ * for which no specific BIO method is available.
+ * See ssl/ssltest.c for some hints on how this can be used. */
+
+/* BIO_DEBUG implies BIO_PAIR_DEBUG */
+#ifdef BIO_DEBUG
+# ifndef BIO_PAIR_DEBUG
+#  define BIO_PAIR_DEBUG
+# endif
+#endif
+
+/* disable assert() unless BIO_PAIR_DEBUG has been defined */
+#ifndef BIO_PAIR_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+static int bio_new(BIO *bio);
+static int bio_free(BIO *bio);
+static int bio_read(BIO *bio, char *buf, int size);
+static int bio_write(BIO *bio, const char *buf, int num);
+static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);
+static int bio_puts(BIO *bio, const char *str);
+
+static int bio_make_pair(BIO *bio1, BIO *bio2);
+static void bio_destroy_pair(BIO *bio);
+
+static const BIO_METHOD methods_biop = {
+	.type = BIO_TYPE_BIO,
+	.name = "BIO pair",
+	.bwrite = bio_write,
+	.bread = bio_read,
+	.bputs = bio_puts,
+	.ctrl = bio_ctrl,
+	.create = bio_new,
+	.destroy = bio_free
+};
+
+const BIO_METHOD *
+BIO_s_bio(void)
+{
+	return &methods_biop;
+}
+LCRYPTO_ALIAS(BIO_s_bio);
+
+struct bio_bio_st {
+	BIO *peer;	/* NULL if buf == NULL.
+			 * If peer != NULL, then peer->ptr is also a bio_bio_st,
+			 * and its "peer" member points back to us.
+			 * peer != NULL iff init != 0 in the BIO. */
+
+	/* This is for what we write (i.e. reading uses peer's struct): */
+	int closed;	/* valid iff peer != NULL */
+	size_t len;	/* valid iff buf != NULL; 0 if peer == NULL */
+	size_t offset;	/* valid iff buf != NULL; 0 if len == 0 */
+	size_t size;
+	char *buf;      /* "size" elements (if != NULL) */
+
+	size_t request; /* valid iff peer != NULL; 0 if len != 0,
+			 * otherwise set by peer to number of bytes
+			 * it (unsuccessfully) tried to read,
+	                 * never more than buffer space (size-len) warrants. */
+};
+
+static int
+bio_new(BIO *bio)
+{
+	struct bio_bio_st *b;
+
+	b = malloc(sizeof *b);
+	if (b == NULL)
+		return 0;
+
+	b->peer = NULL;
+	b->size = 17 * 1024; /* enough for one TLS record (just a default) */
+	b->buf = NULL;
+
+	bio->ptr = b;
+	return 1;
+}
+
+static int
+bio_free(BIO *bio)
+{
+	struct bio_bio_st *b;
+
+	if (bio == NULL)
+		return 0;
+	b = bio->ptr;
+
+	assert(b != NULL);
+
+	if (b->peer)
+		bio_destroy_pair(bio);
+
+	free(b->buf);
+	free(b);
+	return 1;
+}
+
+
+
+static int
+bio_read(BIO *bio, char *buf, int size_)
+{
+	size_t size = size_;
+	size_t rest;
+	struct bio_bio_st *b, *peer_b;
+
+	BIO_clear_retry_flags(bio);
+
+	if (!bio->init)
+		return 0;
+
+	b = bio->ptr;
+	assert(b != NULL);
+	assert(b->peer != NULL);
+	peer_b = b->peer->ptr;
+	assert(peer_b != NULL);
+	assert(peer_b->buf != NULL);
+
+	peer_b->request = 0; /* will be set in "retry_read" situation */
+
+	if (buf == NULL || size == 0)
+		return 0;
+
+	if (peer_b->len == 0) {
+		if (peer_b->closed)
+			return 0; /* writer has closed, and no data is left */
+		else {
+			BIO_set_retry_read(bio); /* buffer is empty */
+			if (size <= peer_b->size)
+				peer_b->request = size;
+			else
+				/* don't ask for more than the peer can
+				 * deliver in one write */
+				peer_b->request = peer_b->size;
+			return -1;
+		}
+	}
+
+	/* we can read */
+	if (peer_b->len < size)
+		size = peer_b->len;
+
+	/* now read "size" bytes */
+
+	rest = size;
+
+	assert(rest > 0);
+	do /* one or two iterations */
+	{
+		size_t chunk;
+
+		assert(rest <= peer_b->len);
+		if (peer_b->offset + rest <= peer_b->size)
+			chunk = rest;
+		else
+			/* wrap around ring buffer */
+			chunk = peer_b->size - peer_b->offset;
+		assert(peer_b->offset + chunk <= peer_b->size);
+
+		memcpy(buf, peer_b->buf + peer_b->offset, chunk);
+
+		peer_b->len -= chunk;
+		if (peer_b->len) {
+			peer_b->offset += chunk;
+			assert(peer_b->offset <= peer_b->size);
+			if (peer_b->offset == peer_b->size)
+				peer_b->offset = 0;
+			buf += chunk;
+		} else {
+			/* buffer now empty, no need to advance "buf" */
+			assert(chunk == rest);
+			peer_b->offset = 0;
+		}
+		rest -= chunk;
+	} while (rest);
+
+	return size;
+}
+
+static int
+bio_write(BIO *bio, const char *buf, int num_)
+{
+	size_t num = num_;
+	size_t rest;
+	struct bio_bio_st *b;
+
+	BIO_clear_retry_flags(bio);
+
+	if (!bio->init || buf == NULL || num == 0)
+		return 0;
+
+	b = bio->ptr;
+
+	assert(b != NULL);
+	assert(b->peer != NULL);
+	assert(b->buf != NULL);
+
+	b->request = 0;
+	if (b->closed) {
+		/* we already closed */
+		BIOerror(BIO_R_BROKEN_PIPE);
+		return -1;
+	}
+
+	assert(b->len <= b->size);
+
+	if (b->len == b->size) {
+		BIO_set_retry_write(bio); /* buffer is full */
+		return -1;
+	}
+
+	/* we can write */
+	if (num > b->size - b->len)
+		num = b->size - b->len;
+
+	/* now write "num" bytes */
+
+	rest = num;
+
+	assert(rest > 0);
+	do /* one or two iterations */
+	{
+		size_t write_offset;
+		size_t chunk;
+
+		assert(b->len + rest <= b->size);
+
+		write_offset = b->offset + b->len;
+		if (write_offset >= b->size)
+			write_offset -= b->size;
+		/* b->buf[write_offset] is the first byte we can write to. */
+
+		if (write_offset + rest <= b->size)
+			chunk = rest;
+		else
+			/* wrap around ring buffer */
+			chunk = b->size - write_offset;
+
+		memcpy(b->buf + write_offset, buf, chunk);
+
+		b->len += chunk;
+
+		assert(b->len <= b->size);
+
+		rest -= chunk;
+		buf += chunk;
+	} while (rest);
+
+	return num;
+}
+
+static long
+bio_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+	long ret;
+	struct bio_bio_st *b = bio->ptr;
+
+	assert(b != NULL);
+
+	switch (cmd) {
+		/* specific CTRL codes */
+
+	case BIO_C_SET_WRITE_BUF_SIZE:
+		if (b->peer) {
+			BIOerror(BIO_R_IN_USE);
+			ret = 0;
+		} else if (num == 0) {
+			BIOerror(BIO_R_INVALID_ARGUMENT);
+			ret = 0;
+		} else {
+			size_t new_size = num;
+
+			if (b->size != new_size) {
+				free(b->buf);
+				b->buf = NULL;
+				b->size = new_size;
+			}
+			ret = 1;
+		}
+		break;
+
+	case BIO_C_GET_WRITE_BUF_SIZE:
+		ret = (long) b->size;
+		break;
+
+	case BIO_C_MAKE_BIO_PAIR:
+		{
+			BIO *other_bio = ptr;
+
+			if (bio_make_pair(bio, other_bio))
+				ret = 1;
+			else
+				ret = 0;
+		}
+		break;
+
+	case BIO_C_DESTROY_BIO_PAIR:
+		/* Affects both BIOs in the pair -- call just once!
+		 * Or let BIO_free(bio1); BIO_free(bio2); do the job. */
+		bio_destroy_pair(bio);
+		ret = 1;
+		break;
+
+	case BIO_C_GET_WRITE_GUARANTEE:
+		/* How many bytes can the caller feed to the next write
+		 * without having to keep any? */
+		if (b->peer == NULL || b->closed)
+			ret = 0;
+		else
+			ret = (long) b->size - b->len;
+		break;
+
+	case BIO_C_GET_READ_REQUEST:
+		/* If the peer unsuccessfully tried to read, how many bytes
+		 * were requested?  (As with BIO_CTRL_PENDING, that number
+		 * can usually be treated as boolean.) */
+		ret = (long) b->request;
+		break;
+
+	case BIO_C_RESET_READ_REQUEST:
+		/* Reset request.  (Can be useful after read attempts
+		 * at the other side that are meant to be non-blocking,
+		 * e.g. when probing SSL_read to see if any data is
+		 * available.) */
+		b->request = 0;
+		ret = 1;
+		break;
+
+	case BIO_C_SHUTDOWN_WR:
+		/* similar to shutdown(..., SHUT_WR) */
+		b->closed = 1;
+		ret = 1;
+		break;
+
+	/* standard CTRL codes follow */
+
+	case BIO_CTRL_RESET:
+		if (b->buf != NULL) {
+			b->len = 0;
+			b->offset = 0;
+		}
+		ret = 0;
+		break;
+
+
+	case BIO_CTRL_GET_CLOSE:
+		ret = bio->shutdown;
+		break;
+
+	case BIO_CTRL_SET_CLOSE:
+		bio->shutdown = (int) num;
+		ret = 1;
+		break;
+
+	case BIO_CTRL_PENDING:
+		if (b->peer != NULL) {
+			struct bio_bio_st *peer_b = b->peer->ptr;
+
+			ret = (long) peer_b->len;
+		} else
+			ret = 0;
+		break;
+
+	case BIO_CTRL_WPENDING:
+		if (b->buf != NULL)
+			ret = (long) b->len;
+		else
+			ret = 0;
+		break;
+
+	case BIO_CTRL_DUP:
+		/* See BIO_dup_chain for circumstances we have to expect. */
+		{
+			BIO *other_bio = ptr;
+			struct bio_bio_st *other_b;
+
+			assert(other_bio != NULL);
+			other_b = other_bio->ptr;
+			assert(other_b != NULL);
+
+			assert(other_b->buf == NULL); /* other_bio is always fresh */
+
+			other_b->size = b->size;
+		}
+
+		ret = 1;
+		break;
+
+	case BIO_CTRL_FLUSH:
+		ret = 1;
+		break;
+
+	case BIO_CTRL_EOF:
+		{
+			BIO *other_bio = ptr;
+
+			if (other_bio) {
+				struct bio_bio_st *other_b = other_bio->ptr;
+
+				assert(other_b != NULL);
+				ret = other_b->len == 0 && other_b->closed;
+			} else
+				ret = 1;
+		}
+		break;
+
+	default:
+		ret = 0;
+	}
+	return ret;
+}
+
+static int
+bio_puts(BIO *bio, const char *str)
+{
+	return bio_write(bio, str, strlen(str));
+}
+
+
+static int
+bio_make_pair(BIO *bio1, BIO *bio2)
+{
+	struct bio_bio_st *b1, *b2;
+
+	assert(bio1 != NULL);
+	assert(bio2 != NULL);
+
+	b1 = bio1->ptr;
+	b2 = bio2->ptr;
+
+	if (b1->peer != NULL || b2->peer != NULL) {
+		BIOerror(BIO_R_IN_USE);
+		return 0;
+	}
+
+	if (b1->buf == NULL) {
+		b1->buf = malloc(b1->size);
+		if (b1->buf == NULL) {
+			BIOerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		b1->len = 0;
+		b1->offset = 0;
+	}
+
+	if (b2->buf == NULL) {
+		b2->buf = malloc(b2->size);
+		if (b2->buf == NULL) {
+			BIOerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		b2->len = 0;
+		b2->offset = 0;
+	}
+
+	b1->peer = bio2;
+	b1->closed = 0;
+	b1->request = 0;
+	b2->peer = bio1;
+	b2->closed = 0;
+	b2->request = 0;
+
+	bio1->init = 1;
+	bio2->init = 1;
+
+	return 1;
+}
+
+static void
+bio_destroy_pair(BIO *bio)
+{
+	struct bio_bio_st *b = bio->ptr;
+
+	if (b != NULL) {
+		BIO *peer_bio = b->peer;
+
+		if (peer_bio != NULL) {
+			struct bio_bio_st *peer_b = peer_bio->ptr;
+
+			assert(peer_b != NULL);
+			assert(peer_b->peer == bio);
+
+			peer_b->peer = NULL;
+			peer_bio->init = 0;
+			assert(peer_b->buf != NULL);
+			peer_b->len = 0;
+			peer_b->offset = 0;
+
+			b->peer = NULL;
+			bio->init = 0;
+			assert(b->buf != NULL);
+			b->len = 0;
+			b->offset = 0;
+		}
+	}
+}
+
+
+/* Exported convenience functions */
+int
+BIO_new_bio_pair(BIO **bio1_p, size_t writebuf1, BIO **bio2_p, size_t writebuf2)
+{
+	BIO *bio1 = NULL, *bio2 = NULL;
+	long r;
+	int ret = 0;
+
+	bio1 = BIO_new(BIO_s_bio());
+	if (bio1 == NULL)
+		goto err;
+	bio2 = BIO_new(BIO_s_bio());
+	if (bio2 == NULL)
+		goto err;
+
+	if (writebuf1) {
+		r = BIO_set_write_buf_size(bio1, writebuf1);
+		if (!r)
+			goto err;
+	}
+	if (writebuf2) {
+		r = BIO_set_write_buf_size(bio2, writebuf2);
+		if (!r)
+			goto err;
+	}
+
+	r = BIO_make_bio_pair(bio1, bio2);
+	if (!r)
+		goto err;
+	ret = 1;
+
+	err:
+	if (ret == 0) {
+		if (bio1) {
+			BIO_free(bio1);
+			bio1 = NULL;
+		}
+		if (bio2) {
+			BIO_free(bio2);
+			bio2 = NULL;
+		}
+	}
+
+	*bio1_p = bio1;
+	*bio2_p = bio2;
+	return ret;
+}
+
+size_t
+BIO_ctrl_get_write_guarantee(BIO *bio)
+{
+	return BIO_ctrl(bio, BIO_C_GET_WRITE_GUARANTEE, 0, NULL);
+}
+LCRYPTO_ALIAS(BIO_ctrl_get_write_guarantee);
+
+size_t
+BIO_ctrl_get_read_request(BIO *bio)
+{
+	return BIO_ctrl(bio, BIO_C_GET_READ_REQUEST, 0, NULL);
+}
+LCRYPTO_ALIAS(BIO_ctrl_get_read_request);
+
+int
+BIO_ctrl_reset_read_request(BIO *bio)
+{
+	return (BIO_ctrl(bio, BIO_C_RESET_READ_REQUEST, 0, NULL) != 0);
+}
+LCRYPTO_ALIAS(BIO_ctrl_reset_read_request);
diff --git a/crypto/bio/bss_conn.c b/crypto/bio/bss_conn.c
new file mode 100644
index 0000000..427bd4b
--- /dev/null
+++ b/crypto/bio/bss_conn.c
@@ -0,0 +1,598 @@
+/* $OpenBSD: bss_conn.c,v 1.39 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+#define SOCKET_PROTOCOL IPPROTO_TCP
+
+typedef struct bio_connect_st {
+	int state;
+
+	char *param_hostname;
+	char *param_port;
+	int nbio;
+
+	unsigned char ip[4];
+	unsigned short port;
+
+	struct sockaddr_in them;
+
+	/* int socket; this will be kept in bio->num so that it is
+	 * compatible with the bss_sock bio */ 
+
+	/* called when the connection is initially made
+	 *  callback(BIO,state,ret);  The callback should return
+	 * 'ret'.  state is for compatibility with the ssl info_callback */
+	BIO_info_cb *info_callback;
+} BIO_CONNECT;
+
+static int conn_write(BIO *h, const char *buf, int num);
+static int conn_read(BIO *h, char *buf, int size);
+static int conn_puts(BIO *h, const char *str);
+static long conn_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int conn_new(BIO *h);
+static int conn_free(BIO *data);
+static long conn_callback_ctrl(BIO *h, int cmd, BIO_info_cb *);
+
+static int conn_state(BIO *b, BIO_CONNECT *c);
+static void conn_close_socket(BIO *data);
+BIO_CONNECT *BIO_CONNECT_new(void);
+void BIO_CONNECT_free(BIO_CONNECT *a);
+
+static const BIO_METHOD methods_connectp = {
+	.type = BIO_TYPE_CONNECT,
+	.name = "socket connect",
+	.bwrite = conn_write,
+	.bread = conn_read,
+	.bputs = conn_puts,
+	.ctrl = conn_ctrl,
+	.create = conn_new,
+	.destroy = conn_free,
+	.callback_ctrl = conn_callback_ctrl
+};
+
+static int
+conn_state(BIO *b, BIO_CONNECT *c)
+{
+	int ret = -1, i;
+	unsigned long l;
+	char *p, *q;
+	BIO_info_cb *cb = NULL;
+
+	if (c->info_callback != NULL)
+		cb = c->info_callback;
+
+	for (;;) {
+		switch (c->state) {
+		case BIO_CONN_S_BEFORE:
+			p = c->param_hostname;
+			if (p == NULL) {
+				BIOerror(BIO_R_NO_HOSTNAME_SPECIFIED);
+				goto exit_loop;
+			}
+			for (; *p != '\0'; p++) {
+				if ((*p == ':') || (*p == '/'))
+				break;
+			}
+
+			i= *p;
+			if ((i == ':') || (i == '/')) {
+				*(p++) = '\0';
+				if (i == ':') {
+					for (q = p; *q; q++)
+						if (*q == '/') {
+							*q = '\0';
+							break;
+						}
+					free(c->param_port);
+					c->param_port = strdup(p);
+				}
+			}
+
+			if (c->param_port == NULL) {
+				BIOerror(BIO_R_NO_PORT_SPECIFIED);
+				ERR_asprintf_error_data("host=%s",
+				    c->param_hostname);
+				goto exit_loop;
+			}
+			c->state = BIO_CONN_S_GET_IP;
+			break;
+
+		case BIO_CONN_S_GET_IP:
+			if (BIO_get_host_ip(c->param_hostname, &(c->ip[0])) <= 0)
+				goto exit_loop;
+			c->state = BIO_CONN_S_GET_PORT;
+			break;
+
+		case BIO_CONN_S_GET_PORT:
+			if (c->param_port == NULL) {
+				/* abort(); */
+				goto exit_loop;
+			} else if (BIO_get_port(c->param_port, &c->port) <= 0)
+				goto exit_loop;
+			c->state = BIO_CONN_S_CREATE_SOCKET;
+			break;
+
+		case BIO_CONN_S_CREATE_SOCKET:
+			/* now setup address */
+			memset((char *)&c->them, 0, sizeof(c->them));
+			c->them.sin_family = AF_INET;
+			c->them.sin_port = htons((unsigned short)c->port);
+			l = (unsigned long)
+			    ((unsigned long)c->ip[0] << 24L)|
+			    ((unsigned long)c->ip[1] << 16L)|
+			    ((unsigned long)c->ip[2] << 8L)|
+			    ((unsigned long)c->ip[3]);
+			c->them.sin_addr.s_addr = htonl(l);
+			c->state = BIO_CONN_S_CREATE_SOCKET;
+
+			ret = socket(AF_INET, SOCK_STREAM, SOCKET_PROTOCOL);
+			if (ret == -1) {
+				SYSerror(errno);
+				ERR_asprintf_error_data("host=%s:%s",
+				    c->param_hostname, c->param_port);
+				BIOerror(BIO_R_UNABLE_TO_CREATE_SOCKET);
+				goto exit_loop;
+			}
+			b->num = ret;
+			c->state = BIO_CONN_S_NBIO;
+			break;
+
+		case BIO_CONN_S_NBIO:
+			if (c->nbio) {
+				if (!BIO_socket_nbio(b->num, 1)) {
+					BIOerror(BIO_R_ERROR_SETTING_NBIO);
+					ERR_asprintf_error_data("host=%s:%s",
+					    c->param_hostname, c->param_port);
+					goto exit_loop;
+				}
+			}
+			c->state = BIO_CONN_S_CONNECT;
+
+#if defined(SO_KEEPALIVE)
+			i = 1;
+			i = setsockopt(b->num, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i));
+			if (i < 0) {
+				SYSerror(errno);
+				ERR_asprintf_error_data("host=%s:%s",
+				    c->param_hostname, c->param_port);
+				BIOerror(BIO_R_KEEPALIVE);
+				goto exit_loop;
+			}
+#endif
+			break;
+
+		case BIO_CONN_S_CONNECT:
+			BIO_clear_retry_flags(b);
+			ret = connect(b->num,
+			(struct sockaddr *)&c->them,
+			sizeof(c->them));
+			b->retry_reason = 0;
+			if (ret < 0) {
+				if (BIO_sock_should_retry(ret)) {
+					BIO_set_retry_special(b);
+					c->state = BIO_CONN_S_BLOCKED_CONNECT;
+					b->retry_reason = BIO_RR_CONNECT;
+				} else {
+					SYSerror(errno);
+					ERR_asprintf_error_data("host=%s:%s",
+					    c->param_hostname, c->param_port);
+					BIOerror(BIO_R_CONNECT_ERROR);
+				}
+				goto exit_loop;
+			} else
+				c->state = BIO_CONN_S_OK;
+			break;
+
+		case BIO_CONN_S_BLOCKED_CONNECT:
+			i = BIO_sock_error(b->num);
+			if (i) {
+				BIO_clear_retry_flags(b);
+				SYSerror(i);
+				ERR_asprintf_error_data("host=%s:%s",
+				    c->param_hostname, c->param_port);
+				BIOerror(BIO_R_NBIO_CONNECT_ERROR);
+				ret = 0;
+				goto exit_loop;
+			} else
+				c->state = BIO_CONN_S_OK;
+			break;
+
+		case BIO_CONN_S_OK:
+			ret = 1;
+			goto exit_loop;
+		default:
+			/* abort(); */
+			goto exit_loop;
+		}
+
+		if (cb != NULL) {
+			if (!(ret = cb((BIO *)b, c->state, ret)))
+				goto end;
+		}
+	}
+
+	/* Loop does not exit */
+exit_loop:
+	if (cb != NULL)
+		ret = cb((BIO *)b, c->state, ret);
+end:
+	return (ret);
+}
+
+BIO_CONNECT *
+BIO_CONNECT_new(void)
+{
+	BIO_CONNECT *ret;
+
+	if ((ret = malloc(sizeof(BIO_CONNECT))) == NULL)
+		return (NULL);
+	ret->state = BIO_CONN_S_BEFORE;
+	ret->param_hostname = NULL;
+	ret->param_port = NULL;
+	ret->info_callback = NULL;
+	ret->nbio = 0;
+	ret->ip[0] = 0;
+	ret->ip[1] = 0;
+	ret->ip[2] = 0;
+	ret->ip[3] = 0;
+	ret->port = 0;
+	memset((char *)&ret->them, 0, sizeof(ret->them));
+	return (ret);
+}
+
+void
+BIO_CONNECT_free(BIO_CONNECT *a)
+{
+	if (a == NULL)
+		return;
+
+	free(a->param_hostname);
+	free(a->param_port);
+	free(a);
+}
+
+const BIO_METHOD *
+BIO_s_connect(void)
+{
+	return (&methods_connectp);
+}
+LCRYPTO_ALIAS(BIO_s_connect);
+
+static int
+conn_new(BIO *bi)
+{
+	bi->init = 0;
+	bi->num = -1;
+	bi->flags = 0;
+	if ((bi->ptr = (char *)BIO_CONNECT_new()) == NULL)
+		return (0);
+	else
+		return (1);
+}
+
+static void
+conn_close_socket(BIO *bio)
+{
+	BIO_CONNECT *c;
+
+	c = (BIO_CONNECT *)bio->ptr;
+	if (bio->num != -1) {
+		/* Only do a shutdown if things were established */
+		if (c->state == BIO_CONN_S_OK)
+			shutdown(bio->num, SHUT_RDWR);
+		close(bio->num);
+		bio->num = -1;
+	}
+}
+
+static int
+conn_free(BIO *a)
+{
+	BIO_CONNECT *data;
+
+	if (a == NULL)
+		return (0);
+	data = (BIO_CONNECT *)a->ptr;
+
+	if (a->shutdown) {
+		conn_close_socket(a);
+		BIO_CONNECT_free(data);
+		a->ptr = NULL;
+		a->flags = 0;
+		a->init = 0;
+	}
+	return (1);
+}
+
+static int
+conn_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+	BIO_CONNECT *data;
+
+	data = (BIO_CONNECT *)b->ptr;
+	if (data->state != BIO_CONN_S_OK) {
+		ret = conn_state(b, data);
+		if (ret <= 0)
+			return (ret);
+	}
+
+	if (out != NULL) {
+		errno = 0;
+		ret = read(b->num, out, outl);
+		BIO_clear_retry_flags(b);
+		if (ret <= 0) {
+			if (BIO_sock_should_retry(ret))
+				BIO_set_retry_read(b);
+		}
+	}
+	return (ret);
+}
+
+static int
+conn_write(BIO *b, const char *in, int inl)
+{
+	int ret;
+	BIO_CONNECT *data;
+
+	data = (BIO_CONNECT *)b->ptr;
+	if (data->state != BIO_CONN_S_OK) {
+		ret = conn_state(b, data);
+		if (ret <= 0)
+			return (ret);
+	}
+
+	errno = 0;
+	ret = write(b->num, in, inl);
+	BIO_clear_retry_flags(b);
+	if (ret <= 0) {
+		if (BIO_sock_should_retry(ret))
+			BIO_set_retry_write(b);
+	}
+	return (ret);
+}
+
+static long
+conn_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	BIO *dbio;
+	int *ip;
+	const char **pptr;
+	long ret = 1;
+	BIO_CONNECT *data;
+
+	data = (BIO_CONNECT *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		ret = 0;
+		data->state = BIO_CONN_S_BEFORE;
+		conn_close_socket(b);
+		b->flags = 0;
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		/* use this one to start the connection */
+		if (data->state != BIO_CONN_S_OK)
+			ret = (long)conn_state(b, data);
+		else
+			ret = 1;
+		break;
+	case BIO_C_GET_CONNECT:
+		if (ptr != NULL) {
+			pptr = (const char **)ptr;
+			if (num == 0) {
+				*pptr = data->param_hostname;
+
+			} else if (num == 1) {
+				*pptr = data->param_port;
+			} else if (num == 2) {
+				*pptr = (char *)&(data->ip[0]);
+			} else if (num == 3) {
+				*((int *)ptr) = data->port;
+			}
+			if ((!b->init) || (ptr == NULL))
+				*pptr = "not initialized";
+			ret = 1;
+		}
+		break;
+	case BIO_C_SET_CONNECT:
+		if (ptr != NULL) {
+			b->init = 1;
+			if (num == 0) {
+				free(data->param_hostname);
+				data->param_hostname = strdup(ptr);
+			} else if (num == 1) {
+				free(data->param_port);
+				data->param_port = strdup(ptr);
+			} else if (num == 2) {
+				unsigned char *p = ptr;
+				free(data->param_hostname);
+				if (asprintf(&data->param_hostname,
+					"%u.%u.%u.%u", p[0], p[1],
+					p[2], p[3]) == -1)
+					data->param_hostname = NULL;
+				memcpy(&(data->ip[0]), ptr, 4);
+			} else if (num == 3) {
+				free(data->param_port);
+				data->port= *(int *)ptr;
+				if (asprintf(&data->param_port, "%d",
+					data->port) == -1)
+					data->param_port = NULL;
+			}
+		}
+		break;
+	case BIO_C_SET_NBIO:
+		data->nbio = (int)num;
+		break;
+	case BIO_C_GET_FD:
+		if (b->init) {
+			ip = (int *)ptr;
+			if (ip != NULL)
+				*ip = b->num;
+			ret = b->num;
+		} else
+			ret = -1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_WPENDING:
+		ret = 0;
+		break;
+	case BIO_CTRL_FLUSH:
+		break;
+	case BIO_CTRL_DUP:
+		{
+			dbio = (BIO *)ptr;
+			if (data->param_port)
+				BIO_set_conn_port(dbio, data->param_port);
+			if (data->param_hostname)
+				BIO_set_conn_hostname(dbio,
+				    data->param_hostname);
+			BIO_set_nbio(dbio, data->nbio);
+			(void)BIO_set_info_callback(dbio, data->info_callback);
+		}
+		break;
+	case BIO_CTRL_SET_CALLBACK:
+		{
+#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
+			BIOerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+			ret = -1;
+#else
+			ret = 0;
+#endif
+		}
+		break;
+	case BIO_CTRL_GET_CALLBACK:
+		{
+			BIO_info_cb **fptr = ptr;
+
+			*fptr = data->info_callback;
+		}
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static long
+conn_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+	long ret = 1;
+	BIO_CONNECT *data;
+
+	data = (BIO_CONNECT *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_SET_CALLBACK:
+		data->info_callback = (BIO_info_cb *)fp;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+conn_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = conn_write(bp, str, n);
+	return (ret);
+}
+
+BIO *
+BIO_new_connect(const char *str)
+{
+	BIO *ret;
+
+	ret = BIO_new(BIO_s_connect());
+	if (ret == NULL)
+		return (NULL);
+	if (BIO_set_conn_hostname(ret, str))
+		return (ret);
+	else {
+		BIO_free(ret);
+		return (NULL);
+	}
+}
+LCRYPTO_ALIAS(BIO_new_connect);
diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c
new file mode 100644
index 0000000..65a8f6f
--- /dev/null
+++ b/crypto/bio/bss_dgram.c
@@ -0,0 +1,663 @@
+/* $OpenBSD: bss_dgram.c,v 1.45 2023/07/05 21:23:37 beck Exp $ */
+/* 
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+#ifndef OPENSSL_NO_DGRAM
+
+
+static int dgram_write(BIO *h, const char *buf, int num);
+static int dgram_read(BIO *h, char *buf, int size);
+static int dgram_puts(BIO *h, const char *str);
+static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int dgram_new(BIO *h);
+static int dgram_free(BIO *data);
+static int dgram_clear(BIO *bio);
+
+
+static int BIO_dgram_should_retry(int s);
+
+static const BIO_METHOD methods_dgramp = {
+	.type = BIO_TYPE_DGRAM,
+	.name = "datagram socket",
+	.bwrite = dgram_write,
+	.bread = dgram_read,
+	.bputs = dgram_puts,
+	.ctrl = dgram_ctrl,
+	.create = dgram_new,
+	.destroy = dgram_free
+};
+
+
+typedef struct bio_dgram_data_st {
+	union {
+		struct sockaddr sa;
+		struct sockaddr_in sa_in;
+		struct sockaddr_in6 sa_in6;
+	} peer;
+	unsigned int connected;
+	unsigned int _errno;
+	unsigned int mtu;
+	struct timeval next_timeout;
+	struct timeval socket_timeout;
+} bio_dgram_data;
+
+
+const BIO_METHOD *
+BIO_s_datagram(void)
+{
+	return (&methods_dgramp);
+}
+LCRYPTO_ALIAS(BIO_s_datagram);
+
+BIO *
+BIO_new_dgram(int fd, int close_flag)
+{
+	BIO *ret;
+
+	ret = BIO_new(BIO_s_datagram());
+	if (ret == NULL)
+		return (NULL);
+	BIO_set_fd(ret, fd, close_flag);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new_dgram);
+
+static int
+dgram_new(BIO *bi)
+{
+	bio_dgram_data *data = NULL;
+
+	bi->init = 0;
+	bi->num = 0;
+	data = calloc(1, sizeof(bio_dgram_data));
+	if (data == NULL)
+		return 0;
+	bi->ptr = data;
+
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+dgram_free(BIO *a)
+{
+	bio_dgram_data *data;
+
+	if (a == NULL)
+		return (0);
+	if (!dgram_clear(a))
+		return 0;
+
+	data = (bio_dgram_data *)a->ptr;
+	free(data);
+
+	return (1);
+}
+
+static int
+dgram_clear(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	if (a->shutdown) {
+		if (a->init) {
+			shutdown(a->num, SHUT_RDWR);
+			close(a->num);
+		}
+		a->init = 0;
+		a->flags = 0;
+	}
+	return (1);
+}
+
+static void
+dgram_adjust_rcv_timeout(BIO *b)
+{
+#if defined(SO_RCVTIMEO)
+	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+
+	/* Is a timer active? */
+	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
+		struct timeval timenow, timeleft;
+
+		/* Read current socket timeout */
+		socklen_t sz = sizeof(data->socket_timeout);
+		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+		    &(data->socket_timeout), &sz) < 0) {
+			perror("getsockopt");
+		}
+
+		/* Get current time */
+		gettimeofday(&timenow, NULL);
+
+		/* Calculate time left until timer expires */
+		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
+		timeleft.tv_sec -= timenow.tv_sec;
+		timeleft.tv_usec -= timenow.tv_usec;
+		if (timeleft.tv_usec < 0) {
+			timeleft.tv_sec--;
+			timeleft.tv_usec += 1000000;
+		}
+
+		if (timeleft.tv_sec < 0) {
+			timeleft.tv_sec = 0;
+			timeleft.tv_usec = 1;
+		}
+
+		/* Adjust socket timeout if next handshake message timer
+		 * will expire earlier.
+		 */
+		if ((data->socket_timeout.tv_sec == 0 &&
+		    data->socket_timeout.tv_usec == 0) ||
+		    (data->socket_timeout.tv_sec > timeleft.tv_sec) ||
+		    (data->socket_timeout.tv_sec == timeleft.tv_sec &&
+		    data->socket_timeout.tv_usec >= timeleft.tv_usec)) {
+			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+			    &timeleft, sizeof(struct timeval)) < 0) {
+				perror("setsockopt");
+			}
+		}
+	}
+#endif
+}
+
+static void
+dgram_reset_rcv_timeout(BIO *b)
+{
+#if defined(SO_RCVTIMEO)
+	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+
+	/* Is a timer active? */
+	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0) {
+		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+		    &(data->socket_timeout), sizeof(struct timeval)) < 0) {
+			perror("setsockopt");
+		}
+	}
+#endif
+}
+
+static int
+dgram_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+
+	struct	{
+		socklen_t len;
+		union	{
+			struct sockaddr sa;
+			struct sockaddr_in sa_in;
+			struct sockaddr_in6 sa_in6;
+		} peer;
+	} sa;
+
+	sa.len = sizeof(sa.peer);
+
+	if (out != NULL) {
+		errno = 0;
+		memset(&sa.peer, 0, sizeof(sa.peer));
+		dgram_adjust_rcv_timeout(b);
+		ret = recvfrom(b->num, out, outl, 0, &sa.peer.sa, &sa.len);
+
+		if (! data->connected  && ret >= 0)
+			BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
+
+		BIO_clear_retry_flags(b);
+		if (ret < 0) {
+			if (BIO_dgram_should_retry(ret)) {
+				BIO_set_retry_read(b);
+				data->_errno = errno;
+			}
+		}
+
+		dgram_reset_rcv_timeout(b);
+	}
+	return (ret);
+}
+
+static int
+dgram_write(BIO *b, const char *in, int inl)
+{
+	int ret;
+	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+	errno = 0;
+
+	if (data->connected)
+		ret = write(b->num, in, inl);
+	else {
+		int peerlen = sizeof(data->peer);
+
+		if (data->peer.sa.sa_family == AF_INET)
+			peerlen = sizeof(data->peer.sa_in);
+		else if (data->peer.sa.sa_family == AF_INET6)
+			peerlen = sizeof(data->peer.sa_in6);
+		ret = sendto(b->num, in, inl, 0, &data->peer.sa, peerlen);
+	}
+
+	BIO_clear_retry_flags(b);
+	if (ret <= 0) {
+		if (BIO_dgram_should_retry(ret)) {
+			BIO_set_retry_write(b);
+
+			data->_errno = errno;
+			/*
+			 * higher layers are responsible for querying MTU,
+			 * if necessary
+			 */
+		}
+	}
+	return (ret);
+}
+
+static long
+dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret = 1;
+	int *ip;
+	struct sockaddr *to = NULL;
+	bio_dgram_data *data = NULL;
+#if (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
+	int sockopt_val = 0;
+	socklen_t sockopt_len;	/* assume that system supporting IP_MTU is
+				 * modern enough to define socklen_t */
+	socklen_t addr_len;
+	union	{
+		struct sockaddr	sa;
+		struct sockaddr_in s4;
+		struct sockaddr_in6 s6;
+	} addr;
+#endif
+
+	data = (bio_dgram_data *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		num = 0;
+	case BIO_C_FILE_SEEK:
+		ret = 0;
+		break;
+	case BIO_C_FILE_TELL:
+	case BIO_CTRL_INFO:
+		ret = 0;
+		break;
+	case BIO_C_SET_FD:
+		dgram_clear(b);
+		b->num= *((int *)ptr);
+		b->shutdown = (int)num;
+		b->init = 1;
+		break;
+	case BIO_C_GET_FD:
+		if (b->init) {
+			ip = (int *)ptr;
+			if (ip != NULL)
+				*ip = b->num;
+			ret = b->num;
+		} else
+			ret = -1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_WPENDING:
+		ret = 0;
+		break;
+	case BIO_CTRL_DUP:
+	case BIO_CTRL_FLUSH:
+		ret = 1;
+		break;
+	case BIO_CTRL_DGRAM_CONNECT:
+		to = (struct sockaddr *)ptr;
+		switch (to->sa_family) {
+		case AF_INET:
+			memcpy(&data->peer, to, sizeof(data->peer.sa_in));
+			break;
+		case AF_INET6:
+			memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
+			break;
+		default:
+			memcpy(&data->peer, to, sizeof(data->peer.sa));
+			break;
+		}
+		break;
+		/* (Linux)kernel sets DF bit on outgoing IP packets */
+	case BIO_CTRL_DGRAM_MTU_DISCOVER:
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
+		addr_len = (socklen_t)sizeof(addr);
+		memset((void *)&addr, 0, sizeof(addr));
+		if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
+			ret = 0;
+			break;
+		}
+		switch (addr.sa.sa_family) {
+		case AF_INET:
+			sockopt_val = IP_PMTUDISC_DO;
+			ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
+			    &sockopt_val, sizeof(sockopt_val));
+			if (ret < 0)
+				perror("setsockopt");
+			break;
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
+		case AF_INET6:
+			sockopt_val = IPV6_PMTUDISC_DO;
+			ret = setsockopt(b->num, IPPROTO_IPV6,
+			    IPV6_MTU_DISCOVER, &sockopt_val,
+			    sizeof(sockopt_val));
+			if (ret < 0)
+				perror("setsockopt");
+			break;
+#endif
+		default:
+			ret = -1;
+			break;
+		}
+#else
+		ret = -1;
+#endif
+		break;
+	case BIO_CTRL_DGRAM_QUERY_MTU:
+#if defined(IP_MTU)
+		addr_len = (socklen_t)sizeof(addr);
+		memset((void *)&addr, 0, sizeof(addr));
+		if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
+			ret = 0;
+			break;
+		}
+		sockopt_len = sizeof(sockopt_val);
+		switch (addr.sa.sa_family) {
+		case AF_INET:
+			ret = getsockopt(b->num, IPPROTO_IP, IP_MTU,
+			    &sockopt_val, &sockopt_len);
+			if (ret < 0 || sockopt_val < 0) {
+				ret = 0;
+			} else {
+				/* we assume that the transport protocol is UDP and no
+				 * IP options are used.
+				 */
+				data->mtu = sockopt_val - 8 - 20;
+				ret = data->mtu;
+			}
+			break;
+#if defined(IPV6_MTU)
+		case AF_INET6:
+			ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU,
+			    &sockopt_val, &sockopt_len);
+			if (ret < 0 || sockopt_val < 0) {
+				ret = 0;
+			} else {
+				/* we assume that the transport protocol is UDP and no
+				 * IPV6 options are used.
+				 */
+				data->mtu = sockopt_val - 8 - 40;
+				ret = data->mtu;
+			}
+			break;
+#endif
+default:
+			ret = 0;
+			break;
+		}
+#else
+		ret = 0;
+#endif
+		break;
+	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
+		switch (data->peer.sa.sa_family) {
+		case AF_INET:
+			ret = 576 - 20 - 8;
+			break;
+		case AF_INET6:
+#ifdef IN6_IS_ADDR_V4MAPPED
+			if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
+				ret = 576 - 20 - 8;
+			else
+#endif
+				ret = 1280 - 40 - 8;
+			break;
+		default:
+			ret = 576 - 20 - 8;
+			break;
+		}
+		break;
+	case BIO_CTRL_DGRAM_GET_MTU:
+		return data->mtu;
+		break;
+	case BIO_CTRL_DGRAM_SET_MTU:
+		data->mtu = num;
+		ret = num;
+		break;
+	case BIO_CTRL_DGRAM_SET_CONNECTED:
+		to = (struct sockaddr *)ptr;
+
+		if (to != NULL) {
+			data->connected = 1;
+			switch (to->sa_family) {
+			case AF_INET:
+				memcpy(&data->peer, to, sizeof(data->peer.sa_in));
+				break;
+			case AF_INET6:
+				memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
+				break;
+			default:
+				memcpy(&data->peer, to, sizeof(data->peer.sa));
+				break;
+			}
+		} else {
+			data->connected = 0;
+			memset(&(data->peer), 0, sizeof(data->peer));
+		}
+		break;
+	case BIO_CTRL_DGRAM_GET_PEER:
+		switch (data->peer.sa.sa_family) {
+		case AF_INET:
+			ret = sizeof(data->peer.sa_in);
+			break;
+		case AF_INET6:
+			ret = sizeof(data->peer.sa_in6);
+			break;
+		default:
+			ret = sizeof(data->peer.sa);
+			break;
+		}
+		if (num == 0 || num > ret)
+			num = ret;
+		memcpy(ptr, &data->peer, (ret = num));
+		break;
+	case BIO_CTRL_DGRAM_SET_PEER:
+		to = (struct sockaddr *) ptr;
+		switch (to->sa_family) {
+		case AF_INET:
+			memcpy(&data->peer, to, sizeof(data->peer.sa_in));
+			break;
+		case AF_INET6:
+			memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
+			break;
+		default:
+			memcpy(&data->peer, to, sizeof(data->peer.sa));
+			break;
+		}
+		break;
+	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
+		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
+		break;
+#if defined(SO_RCVTIMEO)
+	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
+		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
+		    sizeof(struct timeval)) < 0) {
+			perror("setsockopt");
+			ret = -1;
+		}
+		break;
+	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
+		{
+			socklen_t sz = sizeof(struct timeval);
+			if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+			    ptr, &sz) < 0) {
+				perror("getsockopt");
+				ret = -1;
+			} else
+				ret = sz;
+		}
+		break;
+#endif
+#if defined(SO_SNDTIMEO)
+	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
+		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
+		    sizeof(struct timeval)) < 0) {
+			perror("setsockopt");
+			ret = -1;
+		}
+		break;
+	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
+		{
+			socklen_t sz = sizeof(struct timeval);
+			if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
+			    ptr, &sz) < 0) {
+				perror("getsockopt");
+				ret = -1;
+			} else
+				ret = sz;
+		}
+		break;
+#endif
+	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
+		/* fall-through */
+	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
+		if (data->_errno == EAGAIN) {
+			ret = 1;
+			data->_errno = 0;
+		} else
+			ret = 0;
+		break;
+#ifdef EMSGSIZE
+	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
+		if (data->_errno == EMSGSIZE) {
+			ret = 1;
+			data->_errno = 0;
+		} else
+			ret = 0;
+		break;
+#endif
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+dgram_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = dgram_write(bp, str, n);
+	return (ret);
+}
+
+
+static int
+BIO_dgram_should_retry(int i)
+{
+	int err;
+
+	if ((i == 0) || (i == -1)) {
+		err = errno;
+		return (BIO_dgram_non_fatal_error(err));
+	}
+	return (0);
+}
+
+int
+BIO_dgram_non_fatal_error(int err)
+{
+	switch (err) {
+	case EINTR:
+	case EAGAIN:
+	case EINPROGRESS:
+	case EALREADY:
+		return (1);
+	default:
+		break;
+	}
+	return (0);
+}
+LCRYPTO_ALIAS(BIO_dgram_non_fatal_error);
+
+#endif
diff --git a/crypto/bio/bss_fd.c b/crypto/bio/bss_fd.c
new file mode 100644
index 0000000..63eac32
--- /dev/null
+++ b/crypto/bio/bss_fd.c
@@ -0,0 +1,273 @@
+/* $OpenBSD: bss_fd.c,v 1.21 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+static int fd_write(BIO *h, const char *buf, int num);
+static int fd_read(BIO *h, char *buf, int size);
+static int fd_puts(BIO *h, const char *str);
+static int fd_gets(BIO *h, char *buf, int size);
+static long fd_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int fd_new(BIO *h);
+static int fd_free(BIO *data);
+int BIO_fd_should_retry(int s);
+
+static const BIO_METHOD methods_fdp = {
+	.type = BIO_TYPE_FD,
+	.name = "file descriptor",
+	.bwrite = fd_write,
+	.bread = fd_read,
+	.bputs = fd_puts,
+	.bgets = fd_gets,
+	.ctrl = fd_ctrl,
+	.create = fd_new,
+	.destroy = fd_free
+};
+
+const BIO_METHOD *
+BIO_s_fd(void)
+{
+	return (&methods_fdp);
+}
+LCRYPTO_ALIAS(BIO_s_fd);
+
+BIO *
+BIO_new_fd(int fd, int close_flag)
+{
+	BIO *ret;
+	ret = BIO_new(BIO_s_fd());
+	if (ret == NULL)
+		return (NULL);
+	BIO_set_fd(ret, fd, close_flag);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new_fd);
+
+static int
+fd_new(BIO *bi)
+{
+	bi->init = 0;
+	bi->num = -1;
+	bi->ptr = NULL;
+	bi->flags=0;
+	return (1);
+}
+
+static int
+fd_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	if (a->shutdown) {
+		if (a->init) {
+			close(a->num);
+		}
+		a->init = 0;
+		a->flags = 0;
+	}
+	return (1);
+}
+
+static int
+fd_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+
+	if (out != NULL) {
+		errno = 0;
+		ret = read(b->num, out, outl);
+		BIO_clear_retry_flags(b);
+		if (ret <= 0) {
+			if (BIO_fd_should_retry(ret))
+				BIO_set_retry_read(b);
+		}
+	}
+	return (ret);
+}
+
+static int
+fd_write(BIO *b, const char *in, int inl)
+{
+	int ret;
+	errno = 0;
+	ret = write(b->num, in, inl);
+	BIO_clear_retry_flags(b);
+	if (ret <= 0) {
+		if (BIO_fd_should_retry(ret))
+			BIO_set_retry_write(b);
+	}
+	return (ret);
+}
+
+static long
+fd_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret = 1;
+	int *ip;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		num = 0;
+	case BIO_C_FILE_SEEK:
+		ret = (long)lseek(b->num, num, 0);
+		break;
+	case BIO_C_FILE_TELL:
+	case BIO_CTRL_INFO:
+		ret = (long)lseek(b->num, 0, 1);
+		break;
+	case BIO_C_SET_FD:
+		fd_free(b);
+		b->num= *((int *)ptr);
+		b->shutdown = (int)num;
+		b->init = 1;
+		break;
+	case BIO_C_GET_FD:
+		if (b->init) {
+			ip = (int *)ptr;
+			if (ip != NULL)
+				*ip = b->num;
+			ret = b->num;
+		} else
+			ret = -1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_WPENDING:
+		ret = 0;
+		break;
+	case BIO_CTRL_DUP:
+	case BIO_CTRL_FLUSH:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+fd_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = fd_write(bp, str, n);
+	return (ret);
+}
+
+static int
+fd_gets(BIO *bp, char *buf, int size)
+{
+	int ret = 0;
+	char *ptr = buf;
+	char *end = buf + size - 1;
+
+	while ((ptr < end) && (fd_read(bp, ptr, 1) > 0) && (ptr[0] != '\n'))
+		ptr++;
+
+	ptr[0] = '\0';
+
+	if (buf[0] != '\0')
+		ret = strlen(buf);
+	return (ret);
+}
+
+int
+BIO_fd_should_retry(int i)
+{
+	int err;
+
+	if ((i == 0) || (i == -1)) {
+		err = errno;
+		return (BIO_fd_non_fatal_error(err));
+	}
+	return (0);
+}
+LCRYPTO_ALIAS(BIO_fd_should_retry);
+
+int
+BIO_fd_non_fatal_error(int err)
+{
+	switch (err) {
+	case ENOTCONN:
+	case EINTR:
+	case EAGAIN:
+	case EINPROGRESS:
+	case EALREADY:
+		return (1);
+	default:
+		break;
+	}
+	return (0);
+}
+LCRYPTO_ALIAS(BIO_fd_non_fatal_error);
diff --git a/crypto/bio/bss_file.c b/crypto/bio/bss_file.c
new file mode 100644
index 0000000..9b6ca2b
--- /dev/null
+++ b/crypto/bio/bss_file.c
@@ -0,0 +1,325 @@
+/* $OpenBSD: bss_file.c,v 1.35 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/*
+ * 03-Dec-1997	rdenny@dc3.com  Fix bug preventing use of stdin/stdout
+ *		with binary data (e.g. asn1parse -inform DER < xxx) under
+ *		Windows
+ */
+
+#ifndef HEADER_BSS_FILE_C
+#define HEADER_BSS_FILE_C
+
+#if defined(__linux) || defined(__sun) || defined(__hpux)
+/* Following definition aliases fopen to fopen64 on above mentioned
+ * platforms. This makes it possible to open and sequentially access
+ * files larger than 2GB from 32-bit application. It does not allow to
+ * traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
+ * 32-bit platform permits that, not with fseek/ftell. Not to mention
+ * that breaking 2GB limit for seeking would require surgery to *our*
+ * API. But sequential access suffices for practical cases when you
+ * can run into large files, such as fingerprinting, so we can let API
+ * alone. For reference, the list of 32-bit platforms which allow for
+ * sequential access of large files without extra "magic" comprise *BSD,
+ * Darwin, IRIX...
+ */
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#endif
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+
+static int file_write(BIO *h, const char *buf, int num);
+static int file_read(BIO *h, char *buf, int size);
+static int file_puts(BIO *h, const char *str);
+static int file_gets(BIO *h, char *str, int size);
+static long file_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int file_new(BIO *h);
+static int file_free(BIO *data);
+
+static const BIO_METHOD methods_filep = {
+	.type = BIO_TYPE_FILE,
+	.name = "FILE pointer",
+	.bwrite = file_write,
+	.bread = file_read,
+	.bputs = file_puts,
+	.bgets = file_gets,
+	.ctrl = file_ctrl,
+	.create = file_new,
+	.destroy = file_free
+};
+
+BIO *
+BIO_new_file(const char *filename, const char *mode)
+{
+	BIO  *ret;
+	FILE *file = NULL;
+
+	file = fopen(filename, mode);
+
+	if (file == NULL) {
+		SYSerror(errno);
+		ERR_asprintf_error_data("fopen('%s', '%s')", filename, mode);
+		if (errno == ENOENT)
+			BIOerror(BIO_R_NO_SUCH_FILE);
+		else
+			BIOerror(ERR_R_SYS_LIB);
+		return (NULL);
+	}
+	if ((ret = BIO_new(BIO_s_file())) == NULL) {
+		fclose(file);
+		return (NULL);
+	}
+
+	BIO_set_fp(ret, file, BIO_CLOSE);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new_file);
+
+BIO *
+BIO_new_fp(FILE *stream, int close_flag)
+{
+	BIO *ret;
+
+	if ((ret = BIO_new(BIO_s_file())) == NULL)
+		return (NULL);
+
+	BIO_set_fp(ret, stream, close_flag);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new_fp);
+
+const BIO_METHOD *
+BIO_s_file(void)
+{
+	return (&methods_filep);
+}
+LCRYPTO_ALIAS(BIO_s_file);
+
+static int
+file_new(BIO *bi)
+{
+	bi->init = 0;
+	bi->num = 0;
+	bi->ptr = NULL;
+	bi->flags=0;
+	return (1);
+}
+
+static int
+file_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	if (a->shutdown) {
+		if ((a->init) && (a->ptr != NULL)) {
+			fclose (a->ptr);
+			a->ptr = NULL;
+			a->flags = 0;
+		}
+		a->init = 0;
+	}
+	return (1);
+}
+
+static int
+file_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+
+	if (b->init && out != NULL) {
+		ret = fread(out, 1, outl, (FILE *)b->ptr);
+		if (ret == 0 && ferror((FILE *)b->ptr)) {
+			SYSerror(errno);
+			BIOerror(ERR_R_SYS_LIB);
+			ret = -1;
+		}
+	}
+	return (ret);
+}
+
+static int
+file_write(BIO *b, const char *in, int inl)
+{
+	int ret = 0;
+
+	if (b->init && in != NULL)
+		ret = fwrite(in, 1, inl, (FILE *)b->ptr);
+	return (ret);
+}
+
+static long
+file_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret = 1;
+	FILE *fp = (FILE *)b->ptr;
+	FILE **fpp;
+	char p[4];
+
+	switch (cmd) {
+	case BIO_C_FILE_SEEK:
+	case BIO_CTRL_RESET:
+		ret = (long)fseek(fp, num, 0);
+		break;
+	case BIO_CTRL_EOF:
+		ret = (long)feof(fp);
+		break;
+	case BIO_C_FILE_TELL:
+	case BIO_CTRL_INFO:
+		ret = ftell(fp);
+		break;
+	case BIO_C_SET_FILE_PTR:
+		file_free(b);
+		b->shutdown = (int)num&BIO_CLOSE;
+		b->ptr = ptr;
+		b->init = 1;
+		break;
+	case BIO_C_SET_FILENAME:
+		file_free(b);
+		b->shutdown = (int)num&BIO_CLOSE;
+		if (num & BIO_FP_APPEND) {
+			if (num & BIO_FP_READ)
+				strlcpy(p, "a+", sizeof p);
+			else	strlcpy(p, "a", sizeof p);
+		} else if ((num & BIO_FP_READ) && (num & BIO_FP_WRITE))
+			strlcpy(p, "r+", sizeof p);
+		else if (num & BIO_FP_WRITE)
+			strlcpy(p, "w", sizeof p);
+		else if (num & BIO_FP_READ)
+			strlcpy(p, "r", sizeof p);
+		else {
+			BIOerror(BIO_R_BAD_FOPEN_MODE);
+			ret = 0;
+			break;
+		}
+		fp = fopen(ptr, p);
+		if (fp == NULL) {
+			SYSerror(errno);
+			ERR_asprintf_error_data("fopen('%s', '%s')", ptr, p);
+			BIOerror(ERR_R_SYS_LIB);
+			ret = 0;
+			break;
+		}
+		b->ptr = fp;
+		b->init = 1;
+		break;
+	case BIO_C_GET_FILE_PTR:
+		/* the ptr parameter is actually a FILE ** in this case. */
+		if (ptr != NULL) {
+			fpp = (FILE **)ptr;
+			*fpp = (FILE *)b->ptr;
+		}
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = (long)b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_FLUSH:
+		fflush((FILE *)b->ptr);
+		break;
+	case BIO_CTRL_DUP:
+		ret = 1;
+		break;
+
+	case BIO_CTRL_WPENDING:
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_PUSH:
+	case BIO_CTRL_POP:
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+file_gets(BIO *bp, char *buf, int size)
+{
+	int ret = 0;
+
+	buf[0] = '\0';
+	if (!fgets(buf, size,(FILE *)bp->ptr))
+		goto err;
+	if (buf[0] != '\0')
+		ret = strlen(buf);
+err:
+	return (ret);
+}
+
+static int
+file_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = file_write(bp, str, n);
+	return (ret);
+}
+
+
+#endif /* HEADER_BSS_FILE_C */
diff --git a/crypto/bio/bss_log.c b/crypto/bio/bss_log.c
new file mode 100644
index 0000000..9e2e882
--- /dev/null
+++ b/crypto/bio/bss_log.c
@@ -0,0 +1,216 @@
+/* $OpenBSD: bss_log.c,v 1.24 2023/07/05 21:23:37 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+	Why BIO_s_log?
+
+	BIO_s_log is useful for system daemons (or services under NT).
+	It is one-way BIO, it sends all stuff to syslogd (on system that
+	commonly use that), or event log (on NT), or OPCOM (on OpenVMS).
+
+*/
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+
+#ifndef NO_SYSLOG
+
+static int slg_write(BIO *h, const char *buf, int num);
+static int slg_puts(BIO *h, const char *str);
+static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int slg_new(BIO *h);
+static int slg_free(BIO *data);
+static void xopenlog(BIO* bp, char* name, int level);
+static void xsyslog(BIO* bp, int priority, const char* string);
+static void xcloselog(BIO* bp);
+
+static const BIO_METHOD methods_slg = {
+	.type = BIO_TYPE_MEM,
+	.name = "syslog",
+	.bwrite = slg_write,
+	.bputs = slg_puts,
+	.ctrl = slg_ctrl,
+	.create = slg_new,
+	.destroy = slg_free
+};
+
+const BIO_METHOD *
+BIO_s_log(void)
+{
+	return (&methods_slg);
+}
+LCRYPTO_ALIAS(BIO_s_log);
+
+static int
+slg_new(BIO *bi)
+{
+	bi->init = 1;
+	bi->num = 0;
+	bi->ptr = NULL;
+	xopenlog(bi, "application", LOG_DAEMON);
+	return (1);
+}
+
+static int
+slg_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	xcloselog(a);
+	return (1);
+}
+
+static int
+slg_write(BIO *b, const char *in, int inl)
+{
+	int ret = inl;
+	char* buf;
+	char* pp;
+	int priority, i;
+	static const struct {
+		int strl;
+		char str[10];
+		int log_level;
+	}
+	mapping[] = {
+		{ 6, "PANIC ", LOG_EMERG },
+		{ 6, "EMERG ", LOG_EMERG },
+		{ 4, "EMR ", LOG_EMERG },
+		{ 6, "ALERT ", LOG_ALERT },
+		{ 4, "ALR ", LOG_ALERT },
+		{ 5, "CRIT ", LOG_CRIT },
+		{ 4, "CRI ", LOG_CRIT },
+		{ 6, "ERROR ", LOG_ERR },
+		{ 4, "ERR ", LOG_ERR },
+		{ 8, "WARNING ", LOG_WARNING },
+		{ 5, "WARN ", LOG_WARNING },
+		{ 4, "WAR ", LOG_WARNING },
+		{ 7, "NOTICE ", LOG_NOTICE },
+		{ 5, "NOTE ", LOG_NOTICE },
+		{ 4, "NOT ", LOG_NOTICE },
+		{ 5, "INFO ", LOG_INFO },
+		{ 4, "INF ", LOG_INFO },
+		{ 6, "DEBUG ", LOG_DEBUG },
+		{ 4, "DBG ", LOG_DEBUG },
+		{ 0, "", LOG_ERR } /* The default */
+	};
+
+	if ((buf = malloc(inl + 1)) == NULL) {
+		return (0);
+	}
+	strlcpy(buf, in, inl + 1);
+	i = 0;
+	while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
+		i++;
+	priority = mapping[i].log_level;
+	pp = buf + mapping[i].strl;
+
+	xsyslog(b, priority, pp);
+
+	free(buf);
+	return (ret);
+}
+
+static long
+slg_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	switch (cmd) {
+	case BIO_CTRL_SET:
+		xcloselog(b);
+		xopenlog(b, ptr, num);
+		break;
+	default:
+		break;
+	}
+	return (0);
+}
+
+static int
+slg_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = slg_write(bp, str, n);
+	return (ret);
+}
+
+
+static void
+xopenlog(BIO* bp, char* name, int level)
+{
+	openlog(name, LOG_PID|LOG_CONS, level);
+}
+
+static void
+xsyslog(BIO *bp, int priority, const char *string)
+{
+	syslog(priority, "%s", string);
+}
+
+static void
+xcloselog(BIO* bp)
+{
+	closelog();
+}
+
+#endif /* NO_SYSLOG */
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c
new file mode 100644
index 0000000..6d0d54d
--- /dev/null
+++ b/crypto/bio/bss_mem.c
@@ -0,0 +1,367 @@
+/* $OpenBSD: bss_mem.c,v 1.22 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+struct bio_mem {
+	BUF_MEM *buf;
+	size_t read_offset;
+};
+
+static size_t
+bio_mem_pending(struct bio_mem *bm)
+{
+	if (bm->read_offset > bm->buf->length)
+		return 0;
+
+	return bm->buf->length - bm->read_offset;
+}
+
+static uint8_t *
+bio_mem_read_ptr(struct bio_mem *bm)
+{
+	return &bm->buf->data[bm->read_offset];
+}
+
+static int mem_new(BIO *bio);
+static int mem_free(BIO *bio);
+static int mem_write(BIO *bio, const char *in, int in_len);
+static int mem_read(BIO *bio, char *out, int out_len);
+static int mem_puts(BIO *bio, const char *in);
+static int mem_gets(BIO *bio, char *out, int out_len);
+static long mem_ctrl(BIO *bio, int cmd, long arg1, void *arg2);
+
+static const BIO_METHOD mem_method = {
+	.type = BIO_TYPE_MEM,
+	.name = "memory buffer",
+	.bwrite = mem_write,
+	.bread = mem_read,
+	.bputs = mem_puts,
+	.bgets = mem_gets,
+	.ctrl = mem_ctrl,
+	.create = mem_new,
+	.destroy = mem_free
+};
+
+/*
+ * bio->num is used to hold the value to return on 'empty', if it is
+ * 0, should_retry is not set.
+ */
+
+const BIO_METHOD *
+BIO_s_mem(void)
+{
+	return &mem_method;
+}
+LCRYPTO_ALIAS(BIO_s_mem);
+
+BIO *
+BIO_new_mem_buf(const void *buf, int buf_len)
+{
+	struct bio_mem *bm;
+	BIO *bio;
+
+	if (buf == NULL) {
+		BIOerror(BIO_R_NULL_PARAMETER);
+		return NULL;
+	}
+	if (buf_len == -1)
+		buf_len = strlen(buf);
+	if (buf_len < 0) {
+		BIOerror(BIO_R_INVALID_ARGUMENT);
+		return NULL;
+	}
+
+	if ((bio = BIO_new(BIO_s_mem())) == NULL)
+		return NULL;
+
+	bm = bio->ptr;
+	bm->buf->data = (void *)buf; /* Trust in the BIO_FLAGS_MEM_RDONLY flag. */
+	bm->buf->length = buf_len;
+	bm->buf->max = buf_len;
+	bio->flags |= BIO_FLAGS_MEM_RDONLY;
+	/* Since this is static data retrying will not help. */
+	bio->num = 0;
+
+	return bio;
+}
+LCRYPTO_ALIAS(BIO_new_mem_buf);
+
+static int
+mem_new(BIO *bio)
+{
+	struct bio_mem *bm;
+
+	if ((bm = calloc(1, sizeof(*bm))) == NULL)
+		return 0;
+	if ((bm->buf = BUF_MEM_new()) == NULL) {
+		free(bm);
+		return 0;
+	}
+
+	bio->shutdown = 1;
+	bio->init = 1;
+	bio->num = -1;
+	bio->ptr = bm;
+
+	return 1;
+}
+
+static int
+mem_free(BIO *bio)
+{
+	struct bio_mem *bm;
+
+	if (bio == NULL)
+		return 0;
+	if (!bio->init || bio->ptr == NULL)
+		return 1;
+
+	bm = bio->ptr;
+	if (bio->shutdown) {
+		if (bio->flags & BIO_FLAGS_MEM_RDONLY)
+			bm->buf->data = NULL;
+		BUF_MEM_free(bm->buf);
+	}
+	free(bm);
+	bio->ptr = NULL;
+
+	return 1;
+}
+
+static int
+mem_read(BIO *bio, char *out, int out_len)
+{
+	struct bio_mem *bm = bio->ptr;
+
+	BIO_clear_retry_flags(bio);
+
+	if (out == NULL || out_len <= 0)
+		return 0;
+
+	if ((size_t)out_len > bio_mem_pending(bm))
+		out_len = bio_mem_pending(bm);
+
+	if (out_len == 0) {
+		if (bio->num != 0)
+			BIO_set_retry_read(bio);
+		return bio->num;
+	}
+
+	memcpy(out, bio_mem_read_ptr(bm), out_len);
+	bm->read_offset += out_len;
+
+	return out_len;
+}
+
+static int
+mem_write(BIO *bio, const char *in, int in_len)
+{
+	struct bio_mem *bm = bio->ptr;
+	size_t buf_len;
+
+	BIO_clear_retry_flags(bio);
+
+	if (in == NULL || in_len <= 0)
+		return 0;
+
+	if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
+		BIOerror(BIO_R_WRITE_TO_READ_ONLY_BIO);
+		return -1;
+	}
+
+	if (bm->read_offset > 4096) {
+		memmove(bm->buf->data, bio_mem_read_ptr(bm),
+		    bio_mem_pending(bm));
+		bm->buf->length = bio_mem_pending(bm);
+		bm->read_offset = 0;
+	}
+
+	/*
+	 * Check for overflow and ensure we do not exceed an int, otherwise we
+	 * cannot tell if BUF_MEM_grow_clean() succeeded.
+	 */
+	buf_len = bm->buf->length + in_len;
+	if (buf_len < bm->buf->length || buf_len > INT_MAX)
+		return -1;
+
+	if (BUF_MEM_grow_clean(bm->buf, buf_len) != buf_len)
+		return -1;
+
+	memcpy(&bm->buf->data[buf_len - in_len], in, in_len);
+
+	return in_len;
+}
+
+static long
+mem_ctrl(BIO *bio, int cmd, long num, void *ptr)
+{
+	struct bio_mem *bm = bio->ptr;
+	void **pptr;
+	long ret = 1;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		if (bm->buf->data != NULL) {
+			if (!(bio->flags & BIO_FLAGS_MEM_RDONLY)) {
+				memset(bm->buf->data, 0, bm->buf->max);
+				bm->buf->length = 0;
+			}
+			bm->read_offset = 0;
+		}
+		break;
+	case BIO_CTRL_EOF:
+		ret = (long)(bio_mem_pending(bm) == 0);
+		break;
+	case BIO_C_SET_BUF_MEM_EOF_RETURN:
+		bio->num = (int)num;
+		break;
+	case BIO_CTRL_INFO:
+		if (ptr != NULL) {
+			pptr = (void **)ptr;
+			*pptr = bio_mem_read_ptr(bm);
+		}
+		ret = (long)bio_mem_pending(bm);
+		break;
+	case BIO_C_SET_BUF_MEM:
+		BUF_MEM_free(bm->buf);
+		bio->shutdown = (int)num;
+		bm->buf = ptr;
+		bm->read_offset = 0;
+		break;
+	case BIO_C_GET_BUF_MEM_PTR:
+		if (ptr != NULL) {
+			pptr = (void **)ptr;
+			*pptr = bm->buf;
+		}
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = (long)bio->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		bio->shutdown = (int)num;
+		break;
+	case BIO_CTRL_WPENDING:
+		ret = 0L;
+		break;
+	case BIO_CTRL_PENDING:
+		ret = (long)bio_mem_pending(bm);
+		break;
+	case BIO_CTRL_DUP:
+	case BIO_CTRL_FLUSH:
+		ret = 1;
+		break;
+	case BIO_CTRL_PUSH:
+	case BIO_CTRL_POP:
+	default:
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
+static int
+mem_gets(BIO *bio, char *out, int out_len)
+{
+	struct bio_mem *bm = bio->ptr;
+	int i, out_max;
+	char *p;
+	int ret = -1;
+
+	BIO_clear_retry_flags(bio);
+
+	out_max = bio_mem_pending(bm);
+	if (out_len - 1 < out_max)
+		out_max = out_len - 1;
+	if (out_max <= 0) {
+		*out = '\0';
+		return 0;
+	}
+
+	p = bio_mem_read_ptr(bm);
+	for (i = 0; i < out_max; i++) {
+		if (p[i] == '\n') {
+			i++;
+			break;
+		}
+	}
+
+	/*
+	 * i is now the max num of bytes to copy, either out_max or up to and
+	 * including the first newline
+	 */ 
+	if ((ret = mem_read(bio, out, i)) > 0)
+		out[ret] = '\0';
+
+	return ret;
+}
+
+static int
+mem_puts(BIO *bio, const char *in)
+{
+	return mem_write(bio, in, strlen(in));
+}
diff --git a/crypto/bio/bss_null.c b/crypto/bio/bss_null.c
new file mode 100644
index 0000000..5f93409
--- /dev/null
+++ b/crypto/bio/bss_null.c
@@ -0,0 +1,161 @@
+/* $OpenBSD: bss_null.c,v 1.13 2023/07/05 21:23:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+static int null_write(BIO *h, const char *buf, int num);
+static int null_read(BIO *h, char *buf, int size);
+static int null_puts(BIO *h, const char *str);
+static int null_gets(BIO *h, char *str, int size);
+static long null_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int null_new(BIO *h);
+static int null_free(BIO *data);
+
+static const BIO_METHOD null_method = {
+	.type = BIO_TYPE_NULL,
+	.name = "NULL",
+	.bwrite = null_write,
+	.bread = null_read,
+	.bputs = null_puts,
+	.bgets = null_gets,
+	.ctrl = null_ctrl,
+	.create = null_new,
+	.destroy = null_free
+};
+
+const BIO_METHOD *
+BIO_s_null(void)
+{
+	return (&null_method);
+}
+LCRYPTO_ALIAS(BIO_s_null);
+
+static int
+null_new(BIO *bi)
+{
+	bi->init = 1;
+	bi->num = 0;
+	bi->ptr = (NULL);
+	return (1);
+}
+
+static int
+null_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	return (1);
+}
+
+static int
+null_read(BIO *b, char *out, int outl)
+{
+	return (0);
+}
+
+static int
+null_write(BIO *b, const char *in, int inl)
+{
+	return (inl);
+}
+
+static long
+null_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret = 1;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+	case BIO_CTRL_EOF:
+	case BIO_CTRL_SET:
+	case BIO_CTRL_SET_CLOSE:
+	case BIO_CTRL_FLUSH:
+	case BIO_CTRL_DUP:
+		ret = 1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+	case BIO_CTRL_INFO:
+	case BIO_CTRL_GET:
+	case BIO_CTRL_PENDING:
+	case BIO_CTRL_WPENDING:
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+null_gets(BIO *bp, char *buf, int size)
+{
+	return (0);
+}
+
+static int
+null_puts(BIO *bp, const char *str)
+{
+	if (str == NULL)
+		return (0);
+	return (strlen(str));
+}
diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c
new file mode 100644
index 0000000..79194a7
--- /dev/null
+++ b/crypto/bio/bss_sock.c
@@ -0,0 +1,244 @@
+/* $OpenBSD: bss_sock.c,v 1.27 2023/08/07 10:54:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bio_local.h"
+
+static int sock_write(BIO *h, const char *buf, int num);
+static int sock_read(BIO *h, char *buf, int size);
+static int sock_puts(BIO *h, const char *str);
+static long sock_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int sock_new(BIO *h);
+static int sock_free(BIO *data);
+int BIO_sock_should_retry(int s);
+
+static const BIO_METHOD methods_sockp = {
+	.type = BIO_TYPE_SOCKET,
+	.name = "socket",
+	.bwrite = sock_write,
+	.bread = sock_read,
+	.bputs = sock_puts,
+	.ctrl = sock_ctrl,
+	.create = sock_new,
+	.destroy = sock_free
+};
+
+const BIO_METHOD *
+BIO_s_socket(void)
+{
+	return (&methods_sockp);
+}
+LCRYPTO_ALIAS(BIO_s_socket);
+
+BIO *
+BIO_new_socket(int fd, int close_flag)
+{
+	BIO *ret;
+
+	ret = BIO_new(BIO_s_socket());
+	if (ret == NULL)
+		return (NULL);
+	BIO_set_fd(ret, fd, close_flag);
+	return (ret);
+}
+LCRYPTO_ALIAS(BIO_new_socket);
+
+static int
+sock_new(BIO *bi)
+{
+	bi->init = 0;
+	bi->num = 0;
+	bi->ptr = NULL;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+sock_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	if (a->shutdown) {
+		if (a->init) {
+			shutdown(a->num, SHUT_RDWR);
+			close(a->num);
+		}
+		a->init = 0;
+		a->flags = 0;
+	}
+	return (1);
+}
+
+static int
+sock_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+
+	if (out != NULL) {
+		errno = 0;
+		ret = read(b->num, out, outl);
+		BIO_clear_retry_flags(b);
+		if (ret <= 0) {
+			if (BIO_sock_should_retry(ret))
+				BIO_set_retry_read(b);
+		}
+	}
+	return (ret);
+}
+
+static int
+sock_write(BIO *b, const char *in, int inl)
+{
+	int ret;
+
+	errno = 0;
+	ret = write(b->num, in, inl);
+	BIO_clear_retry_flags(b);
+	if (ret <= 0) {
+		if (BIO_sock_should_retry(ret))
+			BIO_set_retry_write(b);
+	}
+	return (ret);
+}
+
+static long
+sock_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	long ret = 1;
+	int *ip;
+
+	switch (cmd) {
+	case BIO_C_SET_FD:
+		sock_free(b);
+		b->num = *((int *)ptr);
+		b->shutdown = (int)num;
+		b->init = 1;
+		break;
+	case BIO_C_GET_FD:
+		if (b->init) {
+			ip = (int *)ptr;
+			if (ip != NULL)
+				*ip = b->num;
+			ret = b->num;
+		} else
+			ret = -1;
+		break;
+	case BIO_CTRL_GET_CLOSE:
+		ret = b->shutdown;
+		break;
+	case BIO_CTRL_SET_CLOSE:
+		b->shutdown = (int)num;
+		break;
+	case BIO_CTRL_DUP:
+	case BIO_CTRL_FLUSH:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	return (ret);
+}
+
+static int
+sock_puts(BIO *bp, const char *str)
+{
+	int n, ret;
+
+	n = strlen(str);
+	ret = sock_write(bp, str, n);
+	return (ret);
+}
+
+int
+BIO_sock_should_retry(int i)
+{
+	int err;
+
+	if ((i == 0) || (i == -1)) {
+		err = errno;
+		return (BIO_sock_non_fatal_error(err));
+	}
+	return (0);
+}
+LCRYPTO_ALIAS(BIO_sock_should_retry);
+
+int
+BIO_sock_non_fatal_error(int err)
+{
+	switch (err) {
+	case ENOTCONN:
+	case EINTR:
+	case EAGAIN:
+	case EINPROGRESS:
+	case EALREADY:
+		return (1);
+	default:
+		break;
+	}
+	return (0);
+}
+LCRYPTO_ALIAS(BIO_sock_non_fatal_error);
diff --git a/crypto/bn/arch/aarch64/bn_arch.h b/crypto/bn/arch/aarch64/bn_arch.h
new file mode 100644
index 0000000..fe6f8a3
--- /dev/null
+++ b/crypto/bn/arch/aarch64/bn_arch.h
@@ -0,0 +1,369 @@
+/*	$OpenBSD: bn_arch.h,v 1.13 2023/07/24 10:21:29 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#if defined(__GNUC__)
+
+#define HAVE_BN_CLZW
+
+static inline int
+bn_clzw(BN_ULONG w)
+{
+	BN_ULONG n;
+
+	__asm__ ("clz   %[n], %[w]"
+	    : [n]"=r"(n)
+	    : [w]"r"(w));
+
+	return n;
+}
+
+#define HAVE_BN_ADDW
+
+static inline void
+bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r0;
+
+	__asm__ (
+	    "adds  %[r0], %[a], %[b] \n"
+	    "cset  %[carry], cs \n"
+	    : [carry]"=r"(carry), [r0]"=r"(r0)
+	    : [a]"r"(a), [b]"r"(b)
+	    : "cc");
+
+	*out_r1 = carry;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_ADDW_ADDW
+
+static inline void
+bn_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r0;
+
+	__asm__ (
+	    "adds  %[r0], %[a], %[b] \n"
+	    "cset  %[carry], cs \n"
+	    "adds  %[r0], %[r0], %[c] \n"
+	    "cinc  %[carry], %[carry], cs \n"
+	    : [carry]"=&r"(carry), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c]"r"(c)
+	    : "cc");
+
+	*out_r1 = carry;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_QWADDQW
+
+static inline void
+bn_qwaddqw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b3,
+    BN_ULONG b2, BN_ULONG b1, BN_ULONG b0, BN_ULONG carry, BN_ULONG *out_carry,
+    BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	__asm__ (
+	    "adds  xzr, %[carry], #-1 \n"
+	    "adcs  %[r0], %[a0], %[b0] \n"
+	    "adcs  %[r1], %[a1], %[b1] \n"
+	    "adcs  %[r2], %[a2], %[b2] \n"
+	    "adcs  %[r3], %[a3], %[b3] \n"
+	    "cset  %[carry], cs \n"
+	    : [carry]"+r"(carry), [r3]"=&r"(r3), [r2]"=&r"(r2),
+		[r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a3]"r"(a3), [a2]"r"(a2), [a1]"r"(a1), [a0]"r"(a0),
+		[b3]"r"(b3), [b2]"r"(b2), [b1]"r"(b1), [b0]"r"(b0)
+	    : "cc");
+
+	*out_carry = carry;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MULW
+
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/* Unsigned multiplication using a umulh/mul pair. */
+	__asm__ (
+	    "umulh %[r1], %[a], %[b] \n"
+	    "mul   %[r0], %[a], %[b] \n"
+	    : [r1]"=&r"(r1), [r0]"=r"(r0)
+	    : [a]"r"(a), [b]"r"(b));
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MULW_ADDW
+
+static inline void
+bn_mulw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	__asm__ (
+	    "umulh  %[r1], %[a], %[b] \n"
+	    "mul    %[r0], %[a], %[b] \n"
+	    "adds   %[r0], %[r0], %[c] \n"
+	    "adc    %[r1], %[r1], xzr \n"
+	    : [r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c]"r"(c)
+	    : "cc");
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MULW_ADDW_ADDW
+
+static inline void
+bn_mulw_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG d,
+    BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	__asm__ (
+	    "umulh  %[r1], %[a], %[b] \n"
+	    "mul    %[r0], %[a], %[b] \n"
+	    "adds   %[r0], %[r0], %[c] \n"
+	    "adc    %[r1], %[r1], xzr \n"
+	    "adds   %[r0], %[r0], %[d] \n"
+	    "adc    %[r1], %[r1], xzr \n"
+	    : [r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c]"r"(c), [d]"r"(d)
+	    : "cc");
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MULW_ADDTW
+
+static inline void
+bn_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
+    BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r2, r1, r0;
+
+	__asm__ (
+	    "umulh  %[r1], %[a], %[b] \n"
+	    "mul    %[r0], %[a], %[b] \n"
+	    "adds   %[r0], %[r0], %[c0] \n"
+	    "adcs   %[r1], %[r1], %[c1] \n"
+	    "adc    %[r2], xzr, %[c2] \n"
+	    : [r2]"=&r"(r2), [r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c2]"r"(c2), [c1]"r"(c1), [c0]"r"(c0)
+	    : "cc");
+
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MUL2_MULW_ADDTW
+
+static inline void
+bn_mul2_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
+    BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r2, r1, r0, x1, x0;
+
+	__asm__ (
+	    "umulh  %[x1], %[a], %[b] \n"
+	    "mul    %[x0], %[a], %[b] \n"
+	    "adds   %[r0], %[c0], %[x0] \n"
+	    "adcs   %[r1], %[c1], %[x1] \n"
+	    "adc    %[r2], xzr, %[c2] \n"
+	    "adds   %[r0], %[r0], %[x0] \n"
+	    "adcs   %[r1], %[r1], %[x1] \n"
+	    "adc    %[r2], xzr, %[r2] \n"
+	    : [r2]"=&r"(r2), [r1]"=&r"(r1), [r0]"=&r"(r0), [x1]"=&r"(x1),
+		[x0]"=&r"(x0)
+	    : [a]"r"(a), [b]"r"(b), [c2]"r"(c2), [c1]"r"(c1), [c0]"r"(c0)
+	    : "cc");
+
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_QWMULW_ADDW
+
+static inline void
+bn_qwmulw_addw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b,
+    BN_ULONG c, BN_ULONG *out_r4, BN_ULONG *out_r3, BN_ULONG *out_r2,
+    BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r4, r3, r2, r1, r0;
+
+	__asm__ (
+	    "umulh  %[r1], %[a0], %[b] \n"
+	    "mul    %[r0], %[a0], %[b] \n"
+	    "adds   %[r0], %[r0], %[c] \n"
+	    "umulh  %[r2], %[a1], %[b] \n"
+	    "mul     %[c], %[a1], %[b] \n"
+	    "adcs   %[r1], %[r1], %[c] \n"
+	    "umulh  %[r3], %[a2], %[b] \n"
+	    "mul     %[c], %[a2], %[b] \n"
+	    "adcs   %[r2], %[r2], %[c] \n"
+	    "umulh  %[r4], %[a3], %[b] \n"
+	    "mul     %[c], %[a3], %[b] \n"
+	    "adcs   %[r3], %[r3], %[c] \n"
+	    "adc    %[r4], %[r4], xzr  \n"
+	    : [c]"+&r"(c), [r4]"=&r"(r4), [r3]"=&r"(r3), [r2]"=&r"(r2),
+		[r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a3]"r"(a3), [a2]"r"(a2), [a1]"r"(a1), [a0]"r"(a0), [b]"r"(b)
+	    : "cc");
+
+	*out_r4 = r4;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_QWMULW_ADDQW_ADDW
+
+static inline void
+bn_qwmulw_addqw_addw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0,
+    BN_ULONG b, BN_ULONG c3, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0, BN_ULONG d,
+    BN_ULONG *out_r4, BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG r4, r3, r2, r1, r0;
+
+	__asm__ (
+	    "umulh  %[r1], %[a0], %[b]  \n"
+	    "mul    %[r0], %[a0], %[b]  \n"
+	    "adds   %[r0], %[r0], %[d]  \n"
+	    "umulh  %[r2], %[a1], %[b]  \n"
+	    "mul     %[d], %[a1], %[b]  \n"
+	    "adcs   %[r1], %[r1], %[d]  \n"
+	    "umulh  %[r3], %[a2], %[b]  \n"
+	    "mul     %[d], %[a2], %[b]  \n"
+	    "adcs   %[r2], %[r2], %[d]  \n"
+	    "umulh  %[r4], %[a3], %[b]  \n"
+	    "mul     %[d], %[a3], %[b]  \n"
+	    "adcs   %[r3], %[r3], %[d]  \n"
+	    "adc    %[r4], %[r4], xzr   \n"
+	    "adds   %[r0], %[r0], %[c0] \n"
+	    "adcs   %[r1], %[r1], %[c1] \n"
+	    "adcs   %[r2], %[r2], %[c2] \n"
+	    "adcs   %[r3], %[r3], %[c3] \n"
+	    "adc    %[r4], %[r4], xzr   \n"
+	    : [d]"+&r"(d), [r4]"=&r"(r4), [r3]"=&r"(r3), [r2]"=&r"(r2),
+		[r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a3]"r"(a3), [a2]"r"(a2), [a1]"r"(a1), [a0]"r"(a0), [b]"r"(b),
+		[c3]"r"(c3), [c2]"r"(c2), [c1]"r"(c1), [c0]"r"(c0)
+	    : "cc");
+
+	*out_r4 = r4;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_SUBW
+
+static inline void
+bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	__asm__ (
+	    "subs  %[r0], %[a], %[b] \n"
+	    "cset  %[borrow], cc \n"
+	    : [borrow]"=r"(borrow), [r0]"=r"(r0)
+	    : [a]"r"(a), [b]"r"(b)
+	    : "cc");
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_SUBW_SUBW
+
+static inline void
+bn_subw_subw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_borrow,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	__asm__ (
+	    "subs  %[r0], %[a], %[b] \n"
+	    "cset  %[borrow], cc \n"
+	    "subs  %[r0], %[r0], %[c] \n"
+	    "cinc  %[borrow], %[borrow], cc \n"
+	    : [borrow]"=&r"(borrow), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c]"r"(c)
+	    : "cc");
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_QWSUBQW
+
+static inline void
+bn_qwsubqw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b3,
+    BN_ULONG b2, BN_ULONG b1, BN_ULONG b0, BN_ULONG borrow, BN_ULONG *out_borrow,
+    BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	__asm__ (
+	    "subs  xzr, xzr, %[borrow] \n"
+	    "sbcs  %[r0], %[a0], %[b0] \n"
+	    "sbcs  %[r1], %[a1], %[b1] \n"
+	    "sbcs  %[r2], %[a2], %[b2] \n"
+	    "sbcs  %[r3], %[a3], %[b3] \n"
+	    "cset  %[borrow], cc \n"
+	    : [borrow]"+r"(borrow), [r3]"=&r"(r3), [r2]"=&r"(r2),
+		[r1]"=&r"(r1), [r0]"=&r"(r0)
+	    : [a3]"r"(a3), [a2]"r"(a2), [a1]"r"(a1), [a0]"r"(a0),
+		[b3]"r"(b3), [b2]"r"(b2), [b1]"r"(b1), [b0]"r"(b0)
+	    : "cc");
+
+	*out_borrow = borrow;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#endif /* __GNUC__ */
+
+#endif
+#endif
diff --git a/crypto/bn/arch/alpha/bn_arch.h b/crypto/bn/arch/alpha/bn_arch.h
new file mode 100644
index 0000000..5bf4ba8
--- /dev/null
+++ b/crypto/bn/arch/alpha/bn_arch.h
@@ -0,0 +1,44 @@
+/*	$OpenBSD: bn_arch.h,v 1.4 2023/02/16 10:41:03 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#if 0 /* Needs testing and enabling. */
+#if defined(__GNUC__)
+#define HAVE_BN_MULW
+
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/* Unsigned multiplication using a umulh/mulq pair. */
+	__asm__ ("umulh %2, %3, %0; mulq %2, %3, %1"
+	    : "=&r"(r1), "=r"(r0)
+	    : "r"(a), "r"(b));
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif /* __GNUC__ */
+#endif
+
+#endif
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_add.S b/crypto/bn/arch/amd64/bignum_add.S
new file mode 100644
index 0000000..06298ca
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_add.S
@@ -0,0 +1,165 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Add, z := x + y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+//
+//    extern uint64_t bignum_add
+//     (uint64_t p, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the z := x + y operation, truncating modulo p words in general and
+// returning a top carry (0 or 1) in the p'th place, only adding the input
+// words below p (as well as m and n respectively) to get the sum and carry.
+//
+// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
+// Microsoft x64 ABI:   RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_add)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_add)
+        .text
+
+#define p rdi
+#define z rsi
+#define m rdx
+#define x rcx
+#define n r8
+#define y r9
+#define i r10
+#define a rax
+
+#define ashort eax
+
+
+
+S2N_BN_SYMBOL(bignum_add):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// Zero the main index counter for both branches
+
+        xor     i, i
+
+// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
+// we'll never need words past the p'th. Can now assume m <= p and n <= p.
+// Then compare the modified m and n and branch accordingly
+
+        cmp     p, m
+        cmovc   m, p
+        cmp     p, n
+        cmovc   n, p
+        cmp     m, n
+        jc      ylonger
+
+// The case where x is longer or of the same size (p >= m >= n)
+
+        sub     p, m
+        sub     m, n
+        inc     m
+        test    n, n
+        jz      xtest
+xmainloop:
+        mov     a, [x+8*i]
+        adc     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     xmainloop
+        jmp     xtest
+xtoploop:
+        mov     a, [x+8*i]
+        adc     a, 0
+        mov     [z+8*i],a
+        inc     i
+xtest:
+        dec     m
+        jnz     xtoploop
+        mov     ashort, 0
+        adc     a, 0
+        test    p, p
+        jnz     tails
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// The case where y is longer (p >= n > m)
+
+ylonger:
+
+        sub     p, n
+        sub     n, m
+        test    m, m
+        jz      ytoploop
+ymainloop:
+        mov     a, [x+8*i]
+        adc     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     m
+        jnz     ymainloop
+ytoploop:
+        mov     a, [y+8*i]
+        adc     a, 0
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     ytoploop
+        mov     ashort, 0
+        adc     a, 0
+        test    p, p
+        jnz     tails
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// Adding a non-trivial tail, when p > max(m,n)
+
+tails:
+        mov     [z+8*i],a
+        xor     a, a
+        jmp     tail
+tailloop:
+        mov     [z+8*i],a
+tail:
+        inc     i
+        dec     p
+        jnz     tailloop
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_cmadd.S b/crypto/bn/arch/amd64/bignum_cmadd.S
new file mode 100644
index 0000000..5ad7127
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_cmadd.S
@@ -0,0 +1,155 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply-add with single-word multiplier, z := z + c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+//
+//    extern uint64_t bignum_cmadd
+//     (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+//
+// Does the "z := z + c * y" operation where y is n digits, result z is p.
+// Truncates the result in general.
+//
+// The return value is a high/carry word that is meaningful when p = n + 1, or
+// more generally when n <= p and the result fits in p + 1 digits. In these
+// cases it gives the top digit of the (p + 1)-digit result.
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmadd)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmadd)
+        .text
+
+#define p rdi
+#define z rsi
+#define c r9
+#define n rcx
+#define x r8
+
+#define i r10
+#define h r11
+
+#define r rbx
+
+#define hshort r11d
+#define ishort r10d
+
+
+
+S2N_BN_SYMBOL(bignum_cmadd):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+#endif
+
+// Seems hard to avoid one more register
+
+        push    rbx
+
+// First clamp the input size n := min(p,n) since we can never need to read
+// past the p'th term of the input to generate p-digit output.
+// Subtract p := p - min(n,p) so it holds the size of the extra tail needed
+
+        cmp     p, n
+        cmovc   n, p
+        sub     p, n
+
+// Initialize high part h = 0; if n = 0 do nothing but return that zero
+
+        xor     h, h
+        test    n, n
+        jz      end
+
+// Move c into a safer register as multiplies overwrite rdx
+
+        mov     c, rdx
+
+// Initialization of the loop: 2^64 * CF + [h,z_0'] = z_0 + c * x_0
+
+        mov     rax, [x]
+        mul     c
+        add     [z], rax
+        mov     h, rdx
+        mov     ishort, 1
+        dec     n
+        jz      hightail
+
+// Main loop, where we always have CF + previous high part h to add in
+
+loop:
+        adc     h, [z+8*i]
+        sbb     r, r
+        mov     rax, [x+8*i]
+        mul     c
+        sub     rdx, r
+        add     rax, h
+        mov     [z+8*i], rax
+        mov     h, rdx
+        inc     i
+        dec     n
+        jnz     loop
+
+hightail:
+        adc     h, 0
+
+// Propagate the carry all the way to the end with h as extra carry word
+
+tail:
+        test    p, p
+        jz      end
+
+        add     [z+8*i], h
+        mov     hshort, 0
+        inc     i
+        dec     p
+        jz      highend
+
+tloop:
+        adc     [z+8*i], h
+        inc     i
+        dec     p
+        jnz     tloop
+
+highend:
+
+        adc     h, 0
+
+// Return the high/carry word
+
+end:
+        mov     rax, h
+
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_cmul.S b/crypto/bn/arch/amd64/bignum_cmul.S
new file mode 100644
index 0000000..9199c8f
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_cmul.S
@@ -0,0 +1,138 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply by a single word, z := c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+//
+//    extern uint64_t bignum_cmul
+//     (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+//
+// Does the "z := c * y" operation where y is n digits, result z is p.
+// Truncates the result in general unless p >= n + 1.
+//
+// The return value is a high/carry word that is meaningful when p >= n as
+// giving the high part of the result. Since this is always zero if p > n,
+// it is mainly of interest in the special case p = n, i.e. where the source
+// and destination have the same nominal size, when it gives the extra word
+// of the full result.
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = c, RCX = n, R8 = y, returns RAX
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = c, R9 = n, [RSP+40] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_cmul)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_cmul)
+        .text
+
+#define p rdi
+#define z rsi
+#define c r9
+#define n rcx
+#define x r8
+
+#define i r10
+#define h r11
+
+
+
+S2N_BN_SYMBOL(bignum_cmul):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+#endif
+
+// First clamp the input size n := min(p,n) since we can never need to read
+// past the p'th term of the input to generate p-digit output. Now we can
+// assume that n <= p
+
+        cmp     p, n
+        cmovc   n, p
+
+// Initialize current input/output pointer offset i and high part h.
+// But then if n = 0 skip the multiplication and go to the tail part
+
+        xor     h, h
+        xor     i, i
+        test    n, n
+        jz      tail
+
+// Move c into a safer register as multiplies overwrite rdx
+
+        mov     c, rdx
+
+// Initialization of the loop: [h,l] = c * x_0
+
+        mov     rax, [x]
+        mul     c
+        mov     [z], rax
+        mov     h, rdx
+        inc     i
+        cmp     i, n
+        jz      tail
+
+// Main loop doing the multiplications
+
+loop:
+        mov     rax, [x+8*i]
+        mul     c
+        add     rax, h
+        adc     rdx, 0
+        mov     [z+8*i], rax
+        mov     h, rdx
+        inc     i
+        cmp     i, n
+        jc      loop
+
+// Add a tail when the destination is longer
+
+tail:
+        cmp     i, p
+        jnc     end
+        mov     [z+8*i], h
+        xor     h, h
+        inc     i
+        cmp     i, p
+        jnc     end
+
+tloop:
+        mov     [z+8*i], h
+        inc     i
+        cmp     i, p
+        jc      tloop
+
+// Return the high/carry word
+
+end:
+        mov     rax, h
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_mul.S b/crypto/bn/arch/amd64/bignum_mul.S
new file mode 100644
index 0000000..2d7ed19
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_mul.S
@@ -0,0 +1,167 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[m], y[n]; output z[k]
+//
+//    extern void bignum_mul
+//     (uint64_t k, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the "z := x * y" operation where x is m digits, y is n, result z is k.
+// Truncates the result in general unless k >= m + n
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul)
+        .text
+
+// These are actually right
+
+#define p rdi
+#define z rsi
+#define n r8
+
+// These are not
+
+#define c r15
+#define h r14
+#define l r13
+#define x r12
+#define y r11
+#define i rbx
+#define k r10
+#define m rbp
+
+// These are always local scratch since multiplier result is in these
+
+#define a rax
+#define d rdx
+
+
+
+S2N_BN_SYMBOL(bignum_mul):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// We use too many registers, and also we need rax:rdx for multiplications
+
+        push    rbx
+        push    rbp
+        push    r12
+        push    r13
+        push    r14
+        push    r15
+        mov     m, rdx
+
+// If the result size is zero, do nothing
+// Note that even if either or both inputs has size zero, we can't
+// just give up because we at least need to zero the output array
+// If we did a multiply-add variant, however, then we could
+
+        test    p, p
+        jz      end
+
+// Set initial 2-part sum to zero (we zero c inside the body)
+
+        xor     h,h
+        xor     l,l
+
+// Otherwise do outer loop k = 0 ... k = p - 1
+
+        xor     k, k
+
+outerloop:
+
+// Zero our carry term first; we eventually want it and a zero is useful now
+// Set a =  max 0 (k + 1 - n), i = min (k + 1) m
+// This defines the range a <= j < i for the inner summation
+// Note that since k < p < 2^64 we can assume k + 1 doesn't overflow
+// And since we want to increment it anyway, we might as well do it now
+
+        xor     c, c            // c = 0
+        inc     k               // k = k + 1
+
+        mov     a, k            // a = k + 1
+        sub     a, n            // a = k + 1 - n
+        cmovc   a, c            // a = max 0 (k + 1 - n)
+
+        mov     i, m            // i = m
+        cmp     k, m            // CF <=> k + 1 < m
+        cmovc   i, k            // i = min (k + 1) m
+
+// Turn i into a loop count, and skip things if it's <= 0
+// Otherwise set up initial pointers x -> x0[a] and y -> y0[k - a]
+// and then launch into the main inner loop, postdecrementing i
+
+        mov     d, k
+        sub     d, i
+        sub     i, a
+        jbe     innerend
+        lea     x,[rcx+8*a]
+        lea     y,[r9+8*d-8]
+
+innerloop:
+        mov     rax, [y+8*i]
+        mul     QWORD PTR  [x]
+        add     x, 8
+        add     l, rax
+        adc     h, rdx
+        adc     c, 0
+        dec     i
+        jnz     innerloop
+
+innerend:
+
+        mov     [z], l
+        mov     l, h
+        mov     h, c
+        add     z, 8
+
+        cmp     k, p
+        jc      outerloop
+
+end:
+        pop     r15
+        pop     r14
+        pop     r13
+        pop     r12
+        pop     rbp
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_mul_4_8_alt.S b/crypto/bn/arch/amd64/bignum_mul_4_8_alt.S
new file mode 100644
index 0000000..f02b09b
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_mul_4_8_alt.S
@@ -0,0 +1,157 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[4], y[4]; output z[8]
+//
+//    extern void bignum_mul_4_8_alt
+//      (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
+// Microsoft x64 ABI:   RCX = z, RDX = x, R8 = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_4_8_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_4_8_alt)
+        .text
+
+// These are actually right
+
+#define z rdi
+#define x rsi
+
+// This is moved from rdx to free it for muls
+
+#define y rcx
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A minutely shorter form for when c = 0 initially
+
+#define combadz(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, c
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa,numb)                  \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx
+
+S2N_BN_SYMBOL(bignum_mul_4_8_alt):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+#endif
+
+// Copy y into a safe register to start with
+
+        mov     y, rdx
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     QWORD PTR [y]
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combads(t1,t0,[x],[y+8])
+        combadz(t2,t1,t0,[x+8],[y])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+16])
+        combadd(t0,t2,t1,[x+8],[y+8])
+        combadd(t0,t2,t1,[x+16],[y])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+24])
+        combadd(t1,t0,t2,[x+8],[y+16])
+        combadd(t1,t0,t2,[x+16],[y+8])
+        combadd(t1,t0,t2,[x+24],[y])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+8],[y+24])
+        combadd(t2,t1,t0,[x+16],[y+16])
+        combadd(t2,t1,t0,[x+24],[y+8])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+16],[y+24])
+        combadd(t0,t2,t1,[x+24],[y+16])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combads(t0,t2,[x+24],[y+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        mov     [z+56], t0
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_mul_8_16_alt.S b/crypto/bn/arch/amd64/bignum_mul_8_16_alt.S
new file mode 100644
index 0000000..97be83e
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_mul_8_16_alt.S
@@ -0,0 +1,244 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Multiply z := x * y
+// Inputs x[8], y[8]; output z[16]
+//
+//    extern void bignum_mul_8_16_alt
+//     (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x, RDX = y
+// Microsoft x64 ABI:   RCX = z, RDX = x, R8 = y
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_mul_8_16_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_mul_8_16_alt)
+        .text
+
+// These are actually right
+
+#define z rdi
+#define x rsi
+
+// This is moved from rdx to free it for muls
+
+#define y rcx
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A minutely shorter form for when c = 0 initially
+
+#define combadz(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, c
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa,numb)                  \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx
+
+S2N_BN_SYMBOL(bignum_mul_8_16_alt):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+#endif
+
+// Copy y into a safe register to start with
+
+        mov     y, rdx
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     QWORD PTR [y]
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combads(t1,t0,[x],[y+8])
+        combadz(t2,t1,t0,[x+8],[y])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+16])
+        combadd(t0,t2,t1,[x+8],[y+8])
+        combadd(t0,t2,t1,[x+16],[y])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+24])
+        combadd(t1,t0,t2,[x+8],[y+16])
+        combadd(t1,t0,t2,[x+16],[y+8])
+        combadd(t1,t0,t2,[x+24],[y])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x],[y+32])
+        combadd(t2,t1,t0,[x+8],[y+24])
+        combadd(t2,t1,t0,[x+16],[y+16])
+        combadd(t2,t1,t0,[x+24],[y+8])
+        combadd(t2,t1,t0,[x+32],[y])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x],[y+40])
+        combadd(t0,t2,t1,[x+8],[y+32])
+        combadd(t0,t2,t1,[x+16],[y+24])
+        combadd(t0,t2,t1,[x+24],[y+16])
+        combadd(t0,t2,t1,[x+32],[y+8])
+        combadd(t0,t2,t1,[x+40],[y])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x],[y+48])
+        combadd(t1,t0,t2,[x+8],[y+40])
+        combadd(t1,t0,t2,[x+16],[y+32])
+        combadd(t1,t0,t2,[x+24],[y+24])
+        combadd(t1,t0,t2,[x+32],[y+16])
+        combadd(t1,t0,t2,[x+40],[y+8])
+        combadd(t1,t0,t2,[x+48],[y])
+        mov     [z+48], t2
+
+// Result term 7
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x],[y+56])
+        combadd(t2,t1,t0,[x+8],[y+48])
+        combadd(t2,t1,t0,[x+16],[y+40])
+        combadd(t2,t1,t0,[x+24],[y+32])
+        combadd(t2,t1,t0,[x+32],[y+24])
+        combadd(t2,t1,t0,[x+40],[y+16])
+        combadd(t2,t1,t0,[x+48],[y+8])
+        combadd(t2,t1,t0,[x+56],[y])
+        mov     [z+56], t0
+
+// Result term 8
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+8],[y+56])
+        combadd(t0,t2,t1,[x+16],[y+48])
+        combadd(t0,t2,t1,[x+24],[y+40])
+        combadd(t0,t2,t1,[x+32],[y+32])
+        combadd(t0,t2,t1,[x+40],[y+24])
+        combadd(t0,t2,t1,[x+48],[y+16])
+        combadd(t0,t2,t1,[x+56],[y+8])
+        mov     [z+64], t1
+
+// Result term 9
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x+16],[y+56])
+        combadd(t1,t0,t2,[x+24],[y+48])
+        combadd(t1,t0,t2,[x+32],[y+40])
+        combadd(t1,t0,t2,[x+40],[y+32])
+        combadd(t1,t0,t2,[x+48],[y+24])
+        combadd(t1,t0,t2,[x+56],[y+16])
+        mov     [z+72], t2
+
+// Result term 10
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+24],[y+56])
+        combadd(t2,t1,t0,[x+32],[y+48])
+        combadd(t2,t1,t0,[x+40],[y+40])
+        combadd(t2,t1,t0,[x+48],[y+32])
+        combadd(t2,t1,t0,[x+56],[y+24])
+        mov     [z+80], t0
+
+// Result term 11
+
+        xor     t0, t0
+        combadz(t0,t2,t1,[x+32],[y+56])
+        combadd(t0,t2,t1,[x+40],[y+48])
+        combadd(t0,t2,t1,[x+48],[y+40])
+        combadd(t0,t2,t1,[x+56],[y+32])
+        mov     [z+88], t1
+
+// Result term 12
+
+        xor     t1, t1
+        combadz(t1,t0,t2,[x+40],[y+56])
+        combadd(t1,t0,t2,[x+48],[y+48])
+        combadd(t1,t0,t2,[x+56],[y+40])
+        mov     [z+96], t2
+
+// Result term 13
+
+        xor     t2, t2
+        combadz(t2,t1,t0,[x+48],[y+56])
+        combadd(t2,t1,t0,[x+56],[y+48])
+        mov     [z+104], t0
+
+// Result term 14
+
+        combads(t2,t1,[x+56],[y+56])
+        mov     [z+112], t1
+
+// Result term 11
+
+        mov     [z+120], t2
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_sqr.S b/crypto/bn/arch/amd64/bignum_sqr.S
new file mode 100644
index 0000000..c4a0cab
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_sqr.S
@@ -0,0 +1,197 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square z := x^2
+// Input x[n]; output z[k]
+//
+//    extern void bignum_sqr
+//     (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
+//
+// Does the "z := x^2" operation where x is n digits and result z is k.
+// Truncates the result in general unless k >= 2 * n
+//
+// Standard x86-64 ABI: RDI = k, RSI = z, RDX = n, RCX = x
+// Microsoft x64 ABI:   RCX = k, RDX = z, R8 = n, R9 = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr)
+        .text
+
+// First three are where arguments come in, but n is moved.
+
+#define p rdi
+#define z rsi
+#define x rcx
+#define n r8
+
+// These are always local scratch since multiplier result is in these
+
+#define a rax
+#define d rdx
+
+// Other variables
+
+#define i rbx
+#define ll rbp
+#define hh r9
+#define k r10
+#define y r11
+#define htop r12
+#define l r13
+#define h r14
+#define c r15
+
+// Short versions
+
+#define llshort ebp
+
+S2N_BN_SYMBOL(bignum_sqr):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+#endif
+
+// We use too many registers, and also we need rax:rdx for multiplications
+
+        push    rbx
+        push    rbp
+        push    r12
+        push    r13
+        push    r14
+        push    r15
+        mov     n, rdx
+
+// If p = 0 the result is trivial and nothing needs doing
+
+        test    p, p
+        jz      end
+
+// initialize (hh,ll) = 0
+
+        xor     llshort, llshort
+        xor     hh, hh
+
+// Iterate outer loop from k = 0 ... k = p - 1 producing result digits
+
+        xor     k, k
+
+outerloop:
+
+// First let bot = MAX 0 (k + 1 - n) and top = MIN (k + 1) n
+// We want to accumulate all x[i] * x[k - i] for bot <= i < top
+// For the optimization of squaring we avoid duplication and do
+// 2 * x[i] * x[k - i] for i < htop, where htop = MIN ((k+1)/2) n
+// Initialize i = bot; in fact just compute bot as i directly.
+
+        xor     c, c
+        lea     i, [k+1]
+        mov     htop, i
+        shr     htop, 1
+        sub     i, n
+        cmovc   i, c
+        cmp     htop, n
+        cmovnc  htop, n
+
+// Initialize the three-part local sum (c,h,l); c was already done above
+
+        xor     l, l
+        xor     h, h
+
+// If htop <= bot then main doubled part of the sum is empty
+
+        cmp     i, htop
+        jnc     nosumming
+
+// Use a moving pointer for [y] = x[k-i] for the cofactor
+
+        mov     a, k
+        sub     a, i
+        lea     y, [x+8*a]
+
+// Do the main part of the sum x[i] * x[k - i] for 2 * i < k
+
+innerloop:
+        mov     a, [x+8*i]
+        mul     QWORD PTR [y]
+        add     l, a
+        adc     h, d
+        adc     c, 0
+        sub     y, 8
+        inc     i
+        cmp     i, htop
+        jc      innerloop
+
+// Now double it
+
+        add     l, l
+        adc     h, h
+        adc     c, c
+
+// If k is even (which means 2 * i = k) and i < n add the extra x[i]^2 term
+
+nosumming:
+        test    k, 1
+        jnz     innerend
+        cmp     i, n
+        jnc     innerend
+
+        mov     a, [x+8*i]
+        mul     a
+        add     l, a
+        adc     h, d
+        adc     c, 0
+
+// Now add the local sum into the global sum, store and shift
+
+innerend:
+        add     l, ll
+        mov     [z+8*k], l
+        adc     h, hh
+        mov     ll, h
+        adc     c, 0
+        mov     hh, c
+
+        inc     k
+        cmp     k, p
+        jc      outerloop
+
+// Restore registers and return
+
+end:
+        pop     r15
+        pop     r14
+        pop     r13
+        pop     r12
+        pop     rbp
+        pop     rbx
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_sqr_4_8_alt.S b/crypto/bn/arch/amd64/bignum_sqr_4_8_alt.S
new file mode 100644
index 0000000..b228414
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_sqr_4_8_alt.S
@@ -0,0 +1,145 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square, z := x^2
+// Input x[4]; output z[8]
+//
+//    extern void bignum_sqr_4_8_alt
+//      (uint64_t z[static 8], uint64_t x[static 4]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x
+// Microsoft x64 ABI:   RCX = z, RDX = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_4_8_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_4_8_alt)
+        .text
+
+// Input arguments
+
+#define z rdi
+#define x rsi
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 rcx
+#define t1 r8
+#define t2 r9
+
+// Macro for the key "multiply and add to (c,h,l)" step, for square term
+
+#define combadd1(c,h,l,numa)                    \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa)                       \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx
+
+// A version doubling before adding, for non-square terms
+
+#define combadd2(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     rax, rax;                       \
+        adc     rdx, rdx;                       \
+        adc     c, 0;                           \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+S2N_BN_SYMBOL(bignum_sqr_4_8_alt):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+#endif
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     rax
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+       xor     t2, t2
+       combadd2(t2,t1,t0,[x],[x+8])
+       mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadd1(t0,t2,t1,[x+8])
+        combadd2(t0,t2,t1,[x],[x+16])
+        mov     [z+16], t1
+
+// Result term 3
+
+        xor     t1, t1
+        combadd2(t1,t0,t2,[x],[x+24])
+        combadd2(t1,t0,t2,[x+8],[x+16])
+        mov     [z+24], t2
+
+// Result term 4
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x+8],[x+24])
+        combadd1(t2,t1,t0,[x+16])
+        mov     [z+32], t0
+
+// Result term 5
+
+        xor     t0, t0
+        combadd2(t0,t2,t1,[x+16],[x+24])
+        mov     [z+40], t1
+
+// Result term 6
+
+        xor     t1, t1
+        combads(t0,t2,[x+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        mov     [z+56], t0
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_sqr_8_16_alt.S b/crypto/bn/arch/amd64/bignum_sqr_8_16_alt.S
new file mode 100644
index 0000000..04efeec
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_sqr_8_16_alt.S
@@ -0,0 +1,242 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Square, z := x^2
+// Input x[8]; output z[16]
+//
+//    extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
+//
+// Standard x86-64 ABI: RDI = z, RSI = x
+// Microsoft x64 ABI:   RCX = z, RDX = x
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sqr_8_16_alt)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sqr_8_16_alt)
+        .text
+
+// Input arguments
+
+#define z rdi
+#define x rsi
+
+// Other variables used as a rotating 3-word window to add terms to
+
+#define t0 r8
+#define t1 r9
+#define t2 r10
+
+// Additional temporaries for local windows to share doublings
+
+#define u0 rcx
+#define u1 r11
+
+// Macro for the key "multiply and add to (c,h,l)" step
+
+#define combadd(c,h,l,numa,numb)                \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// Set up initial window (c,h,l) = numa * numb
+
+#define combaddz(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        xor     c, c;                           \
+        mov     l, rax;                         \
+        mov     h, rdx
+
+// Doubling step (c,h,l) = 2 * (c,hh,ll) + (0,h,l)
+
+#define doubladd(c,h,l,hh,ll)                   \
+        add     ll, ll;                         \
+        adc     hh, hh;                         \
+        adc     c, c;                           \
+        add     l, ll;                          \
+        adc     h, hh;                          \
+        adc     c, 0
+
+// Square term incorporation (c,h,l) += numba^2
+
+#define combadd1(c,h,l,numa)                    \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+// A short form where we don't expect a top carry
+
+#define combads(h,l,numa)                       \
+        mov     rax, numa;                      \
+        mul     rax;                            \
+        add     l, rax;                         \
+        adc     h, rdx
+
+// A version doubling directly before adding, for single non-square terms
+
+#define combadd2(c,h,l,numa,numb)               \
+        mov     rax, numa;                      \
+        mul     QWORD PTR numb;                 \
+        add     rax, rax;                       \
+        adc     rdx, rdx;                       \
+        adc     c, 0;                           \
+        add     l, rax;                         \
+        adc     h, rdx;                         \
+        adc     c, 0
+
+S2N_BN_SYMBOL(bignum_sqr_8_16_alt):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+#endif
+
+// Result term 0
+
+        mov     rax, [x]
+        mul     rax
+
+        mov     [z], rax
+        mov     t0, rdx
+        xor     t1, t1
+
+// Result term 1
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x],[x+8])
+        mov     [z+8], t0
+
+// Result term 2
+
+        xor     t0, t0
+        combadd1(t0,t2,t1,[x+8])
+        combadd2(t0,t2,t1,[x],[x+16])
+        mov     [z+16], t1
+
+// Result term 3
+
+        combaddz(t1,u1,u0,[x],[x+24])
+        combadd(t1,u1,u0,[x+8],[x+16])
+        doubladd(t1,t0,t2,u1,u0)
+        mov     [z+24], t2
+
+// Result term 4
+
+        combaddz(t2,u1,u0,[x],[x+32])
+        combadd(t2,u1,u0,[x+8],[x+24])
+        doubladd(t2,t1,t0,u1,u0)
+        combadd1(t2,t1,t0,[x+16])
+        mov     [z+32], t0
+
+// Result term 5
+
+        combaddz(t0,u1,u0,[x],[x+40])
+        combadd(t0,u1,u0,[x+8],[x+32])
+        combadd(t0,u1,u0,[x+16],[x+24])
+        doubladd(t0,t2,t1,u1,u0)
+        mov     [z+40], t1
+
+// Result term 6
+
+        combaddz(t1,u1,u0,[x],[x+48])
+        combadd(t1,u1,u0,[x+8],[x+40])
+        combadd(t1,u1,u0,[x+16],[x+32])
+        doubladd(t1,t0,t2,u1,u0)
+        combadd1(t1,t0,t2,[x+24])
+        mov     [z+48], t2
+
+// Result term 7
+
+        combaddz(t2,u1,u0,[x],[x+56])
+        combadd(t2,u1,u0,[x+8],[x+48])
+        combadd(t2,u1,u0,[x+16],[x+40])
+        combadd(t2,u1,u0,[x+24],[x+32])
+        doubladd(t2,t1,t0,u1,u0)
+        mov     [z+56], t0
+
+// Result term 8
+
+        combaddz(t0,u1,u0,[x+8],[x+56])
+        combadd(t0,u1,u0,[x+16],[x+48])
+        combadd(t0,u1,u0,[x+24],[x+40])
+        doubladd(t0,t2,t1,u1,u0)
+        combadd1(t0,t2,t1,[x+32])
+        mov     [z+64], t1
+
+// Result term 9
+
+        combaddz(t1,u1,u0,[x+16],[x+56])
+        combadd(t1,u1,u0,[x+24],[x+48])
+        combadd(t1,u1,u0,[x+32],[x+40])
+        doubladd(t1,t0,t2,u1,u0)
+        mov     [z+72], t2
+
+// Result term 10
+
+        combaddz(t2,u1,u0,[x+24],[x+56])
+        combadd(t2,u1,u0,[x+32],[x+48])
+        doubladd(t2,t1,t0,u1,u0)
+        combadd1(t2,t1,t0,[x+40])
+        mov     [z+80], t0
+
+// Result term 11
+
+        combaddz(t0,u1,u0,[x+32],[x+56])
+        combadd(t0,u1,u0,[x+40],[x+48])
+        doubladd(t0,t2,t1,u1,u0)
+        mov     [z+88], t1
+
+// Result term 12
+
+        xor     t1, t1
+        combadd2(t1,t0,t2,[x+40],[x+56])
+        combadd1(t1,t0,t2,[x+48])
+        mov     [z+96], t2
+
+// Result term 13
+
+        xor     t2, t2
+        combadd2(t2,t1,t0,[x+48],[x+56])
+        mov     [z+104], t0
+
+// Result term 14
+
+        combads(t2,t1,[x+56])
+        mov     [z+112], t1
+
+// Result term 15
+
+        mov     [z+120], t2
+
+// Return
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bignum_sub.S b/crypto/bn/arch/amd64/bignum_sub.S
new file mode 100644
index 0000000..11a9bd7
--- /dev/null
+++ b/crypto/bn/arch/amd64/bignum_sub.S
@@ -0,0 +1,153 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Subtract, z := x - y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+//
+//    extern uint64_t bignum_sub
+//     (uint64_t p, uint64_t *z,
+//      uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+//
+// Does the z := x - y operation, truncating modulo p words in general and
+// returning a top borrow (0 or 1) in the p'th place, only subtracting input
+// words below p (as well as m and n respectively) to get the diff and borrow.
+//
+// Standard x86-64 ABI: RDI = p, RSI = z, RDX = m, RCX = x, R8 = n, R9 = y, returns RAX
+// Microsoft x64 ABI:   RCX = p, RDX = z, R8 = m, R9 = x, [RSP+40] = n, [RSP+48] = y, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(bignum_sub)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(bignum_sub)
+        .text
+
+#define p rdi
+#define z rsi
+#define m rdx
+#define x rcx
+#define n r8
+#define y r9
+#define i r10
+#define a rax
+
+#define ashort eax
+
+
+
+S2N_BN_SYMBOL(bignum_sub):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+        mov     rsi, rdx
+        mov     rdx, r8
+        mov     rcx, r9
+        mov     r8, [rsp+56]
+        mov     r9, [rsp+64]
+#endif
+
+// Zero the main index counter for both branches
+
+        xor     i, i
+
+// First clamp the two input sizes m := min(p,m) and n := min(p,n) since
+// we'll never need words past the p'th. Can now assume m <= p and n <= p.
+// Then compare the modified m and n and branch accordingly
+
+        cmp     p, m
+        cmovc   m, p
+        cmp     p, n
+        cmovc   n, p
+        cmp     m, n
+        jc      ylonger
+
+// The case where x is longer or of the same size (p >= m >= n)
+
+        sub     p, m
+        sub     m, n
+        inc     m
+        test    n, n
+        jz      xtest
+xmainloop:
+        mov     a, [x+8*i]
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     xmainloop
+        jmp     xtest
+xtoploop:
+        mov     a, [x+8*i]
+        sbb     a, 0
+        mov     [z+8*i],a
+        inc     i
+xtest:
+        dec     m
+        jnz     xtoploop
+        sbb     a, a
+        test    p, p
+        jz      tailskip
+tailloop:
+        mov     [z+8*i],a
+        inc     i
+        dec     p
+        jnz     tailloop
+tailskip:
+        neg     a
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+// The case where y is longer (p >= n > m)
+
+ylonger:
+
+        sub     p, n
+        sub     n, m
+        test    m, m
+        jz      ytoploop
+ymainloop:
+        mov     a, [x+8*i]
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     m
+        jnz     ymainloop
+ytoploop:
+        mov     ashort, 0
+        sbb     a, [y+8*i]
+        mov     [z+8*i],a
+        inc     i
+        dec     n
+        jnz     ytoploop
+        sbb     a, a
+        test    p, p
+        jnz     tailloop
+        neg     a
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/amd64/bn_arch.c b/crypto/bn/arch/amd64/bn_arch.c
new file mode 100644
index 0000000..a377a05
--- /dev/null
+++ b/crypto/bn/arch/amd64/bn_arch.c
@@ -0,0 +1,131 @@
+/*	$OpenBSD: bn_arch.c,v 1.7 2023/06/24 16:01:44 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bn_arch.h"
+#include "bn_local.h"
+#include "s2n_bignum.h"
+
+#ifdef HAVE_BN_ADD
+BN_ULONG
+bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
+    int b_len)
+{
+	return bignum_add(r_len, (uint64_t *)r, a_len, (uint64_t *)a,
+	    b_len, (uint64_t *)b);
+}
+#endif
+
+
+#ifdef HAVE_BN_ADD_WORDS
+BN_ULONG
+bn_add_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
+{
+	return bignum_add(n, (uint64_t *)rd, n, (uint64_t *)ad, n,
+	    (uint64_t *)bd);
+}
+#endif
+
+#ifdef HAVE_BN_SUB
+BN_ULONG
+bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
+    int b_len)
+{
+	return bignum_sub(r_len, (uint64_t *)r, a_len, (uint64_t *)a,
+	    b_len, (uint64_t *)b);
+}
+#endif
+
+#ifdef HAVE_BN_SUB_WORDS
+BN_ULONG
+bn_sub_words(BN_ULONG *rd, const BN_ULONG *ad, const BN_ULONG *bd, int n)
+{
+	return bignum_sub(n, (uint64_t *)rd, n, (uint64_t *)ad, n,
+	    (uint64_t *)bd);
+}
+#endif
+
+#ifdef HAVE_BN_MUL_ADD_WORDS
+BN_ULONG
+bn_mul_add_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
+{
+	return bignum_cmadd(num, (uint64_t *)rd, w, num, (uint64_t *)ad);
+}
+#endif
+
+#ifdef HAVE_BN_MUL_WORDS
+BN_ULONG
+bn_mul_words(BN_ULONG *rd, const BN_ULONG *ad, int num, BN_ULONG w)
+{
+	return bignum_cmul(num, (uint64_t *)rd, w, num, (uint64_t *)ad);
+}
+#endif
+
+#ifdef HAVE_BN_MUL_COMBA4
+void
+bn_mul_comba4(BN_ULONG *rd, BN_ULONG *ad, BN_ULONG *bd)
+{
+	/* XXX - consider using non-alt on CPUs that have the ADX extension. */
+	bignum_mul_4_8_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd);
+}
+#endif
+
+#ifdef HAVE_BN_MUL_COMBA8
+void
+bn_mul_comba8(BN_ULONG *rd, BN_ULONG *ad, BN_ULONG *bd)
+{
+	/* XXX - consider using non-alt on CPUs that have the ADX extension. */
+	bignum_mul_8_16_alt((uint64_t *)rd, (uint64_t *)ad, (uint64_t *)bd);
+}
+#endif
+
+#ifdef HAVE_BN_SQR
+int
+bn_sqr(BIGNUM *r, const BIGNUM *a, int r_len, BN_CTX *ctx)
+{
+	bignum_sqr(r_len, (uint64_t *)r->d, a->top, (uint64_t *)a->d);
+
+	return 1;
+}
+#endif
+
+#ifdef HAVE_BN_SQR_COMBA4
+void
+bn_sqr_comba4(BN_ULONG *rd, const BN_ULONG *ad)
+{
+	/* XXX - consider using non-alt on CPUs that have the ADX extension. */
+	bignum_sqr_4_8_alt((uint64_t *)rd, (uint64_t *)ad);
+}
+#endif
+
+#ifdef HAVE_BN_SQR_COMBA8
+void
+bn_sqr_comba8(BN_ULONG *rd, const BN_ULONG *ad)
+{
+	/* XXX - consider using non-alt on CPUs that have the ADX extension. */
+	bignum_sqr_8_16_alt((uint64_t *)rd, (uint64_t *)ad);
+}
+#endif
+
+#ifdef HAVE_BN_WORD_CLZ
+int
+bn_word_clz(BN_ULONG w)
+{
+	return word_clz(w);
+}
+#endif
diff --git a/crypto/bn/arch/amd64/bn_arch.h b/crypto/bn/arch/amd64/bn_arch.h
new file mode 100644
index 0000000..9d491e2
--- /dev/null
+++ b/crypto/bn/arch/amd64/bn_arch.h
@@ -0,0 +1,95 @@
+/*	$OpenBSD: bn_arch.h,v 1.13 2023/02/16 11:13:05 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifdef _WIN32
+#define OPENSSL_NO_ASM
+#else
+
+#ifndef OPENSSL_NO_ASM
+
+#define HAVE_BN_ADD
+#define HAVE_BN_ADD_WORDS
+
+#define HAVE_BN_DIV_WORDS
+
+#define HAVE_BN_MUL_ADD_WORDS
+#define HAVE_BN_MUL_COMBA4
+#define HAVE_BN_MUL_COMBA8
+#define HAVE_BN_MUL_WORDS
+
+#define HAVE_BN_SQR
+#define HAVE_BN_SQR_COMBA4
+#define HAVE_BN_SQR_COMBA8
+
+#define HAVE_BN_SUB
+#define HAVE_BN_SUB_WORDS
+
+#define HAVE_BN_WORD_CLZ
+
+#if defined(__GNUC__)
+#define HAVE_BN_DIV_REM_WORDS_INLINE
+
+static inline void
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+    BN_ULONG *out_r)
+{
+	BN_ULONG q, r;
+
+	/*
+	 * Unsigned division of %rdx:%rax by d with quotient being stored in
+	 * %rax and remainder in %rdx.
+	 */
+	__asm__ volatile ("divq %4"
+	    : "=a"(q), "=d"(r)
+	    : "d"(h), "a"(l), "rm"(d)
+	    : "cc");
+
+	*out_q = q;
+	*out_r = r;
+}
+#endif /* __GNUC__ */
+
+#if defined(__GNUC__)
+#define HAVE_BN_MULW
+
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/*
+	 * Unsigned multiplication of %rax, with the double word result being
+	 * stored in %rdx:%rax.
+	 */
+	__asm__ ("mulq %3"
+	    : "=d"(r1), "=a"(r0)
+	    : "a"(a), "rm"(b)
+	    : "cc");
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif /* __GNUC__ */
+#endif /* _WIN32 */
+
+#endif
+#endif
diff --git a/crypto/bn/arch/amd64/word_clz.S b/crypto/bn/arch/amd64/word_clz.S
new file mode 100644
index 0000000..464a9d9
--- /dev/null
+++ b/crypto/bn/arch/amd64/word_clz.S
@@ -0,0 +1,60 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// Count leading zero bits in a single word
+// Input a; output function return
+//
+//    extern uint64_t word_clz (uint64_t a);
+//
+// Standard x86-64 ABI: RDI = a, returns RAX
+// Microsoft x64 ABI:   RCX = a, returns RAX
+// ----------------------------------------------------------------------------
+
+#include "s2n_bignum_internal.h"
+
+        .intel_syntax noprefix
+        S2N_BN_SYM_VISIBILITY_DIRECTIVE(word_clz)
+        S2N_BN_SYM_PRIVACY_DIRECTIVE(word_clz)
+        .text
+
+S2N_BN_SYMBOL(word_clz):
+	endbr64
+
+#if WINDOWS_ABI
+        push    rdi
+        push    rsi
+        mov     rdi, rcx
+#endif
+
+// First do rax = 63 - bsr(a), which is right except (maybe) for zero inputs
+
+        bsr     rax, rdi
+        xor     rax, 63
+
+// Force return of 64 in the zero-input case
+
+        mov     edx, 64
+        test    rdi, rdi
+        cmove   rax, rdx
+
+#if WINDOWS_ABI
+        pop    rsi
+        pop    rdi
+#endif
+        ret
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/arch/arm/bn_arch.h b/crypto/bn/arch/arm/bn_arch.h
new file mode 100644
index 0000000..ef9bf7f
--- /dev/null
+++ b/crypto/bn/arch/arm/bn_arch.h
@@ -0,0 +1,73 @@
+/*	$OpenBSD: bn_arch.h,v 1.2 2023/06/24 15:51:47 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#if defined(__GNUC__)
+
+#define HAVE_BN_SUBW
+
+static inline void
+bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	__asm__ (
+	    "mov  %[borrow], #0 \n"
+	    "subs %[r0], %[a], %[b] \n"
+	    "sbc  %[borrow], %[borrow], #0 \n"
+	    "neg  %[borrow], %[borrow] \n"
+	    : [borrow]"=&r"(borrow), [r0]"=r"(r0)
+	    : [a]"r"(a), [b]"r"(b)
+	    : "cc");
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_SUBW_SUBW
+
+static inline void
+bn_subw_subw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_borrow,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	__asm__ (
+	    "mov  %[borrow], #0 \n"
+	    "subs %[r0], %[a], %[b] \n"
+	    "sbc  %[borrow], %[borrow], #0 \n"
+	    "subs %[r0], %[r0], %[c] \n"
+	    "sbc  %[borrow], %[borrow], #0 \n"
+	    "neg  %[borrow], %[borrow] \n"
+	    : [borrow]"=&r"(borrow), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b), [c]"r"(c)
+	    : "cc");
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+
+#endif /* __GNUC__ */
+
+#endif
+#endif
diff --git a/crypto/bn/arch/hppa/bn_arch.h b/crypto/bn/arch/hppa/bn_arch.h
new file mode 100644
index 0000000..136adf0
--- /dev/null
+++ b/crypto/bn/arch/hppa/bn_arch.h
@@ -0,0 +1,24 @@
+/*	$OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:33 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#endif
+#endif
diff --git a/crypto/bn/arch/i386/bn_arch.h b/crypto/bn/arch/i386/bn_arch.h
new file mode 100644
index 0000000..eef519f
--- /dev/null
+++ b/crypto/bn/arch/i386/bn_arch.h
@@ -0,0 +1,86 @@
+/*	$OpenBSD: bn_arch.h,v 1.9 2023/02/16 10:41:03 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#define HAVE_BN_ADD_WORDS
+
+#define HAVE_BN_DIV_WORDS
+
+#define HAVE_BN_MUL_ADD_WORDS
+#define HAVE_BN_MUL_COMBA4
+#define HAVE_BN_MUL_COMBA8
+#define HAVE_BN_MUL_WORDS
+
+#define HAVE_BN_SQR_COMBA4
+#define HAVE_BN_SQR_COMBA8
+#define HAVE_BN_SQR_WORDS
+
+#define HAVE_BN_SUB_WORDS
+
+#if defined(__GNUC__)
+#define HAVE_BN_DIV_REM_WORDS_INLINE
+
+static inline void
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+    BN_ULONG *out_r)
+{
+	BN_ULONG q, r;
+
+	/*
+	 * Unsigned division of %edx:%eax by d with quotient being stored in
+	 * %eax and remainder in %edx.
+	 */
+	__asm__ volatile ("divl %4"
+	    : "=a"(q), "=d"(r)
+	    : "a"(l), "d"(h), "rm"(d)
+	    : "cc");
+
+	*out_q = q;
+	*out_r = r;
+}
+#endif /* __GNUC__ */
+
+#if defined(__GNUC__)
+#define HAVE_BN_MULW
+
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/*
+	 * Unsigned multiplication of %eax, with the double word result being
+	 * stored in %edx:%eax.
+	 */
+	__asm__ ("mull %3"
+	    : "=d"(r1), "=a"(r0)
+	    : "a"(a), "rm"(b)
+	    : "cc");
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif /* __GNUC__ */
+
+#endif
+#endif
diff --git a/crypto/bn/arch/m88k/bn_arch.h b/crypto/bn/arch/m88k/bn_arch.h
new file mode 100644
index 0000000..136adf0
--- /dev/null
+++ b/crypto/bn/arch/m88k/bn_arch.h
@@ -0,0 +1,24 @@
+/*	$OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:33 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#endif
+#endif
diff --git a/crypto/bn/arch/mips64/bn_arch.h b/crypto/bn/arch/mips64/bn_arch.h
new file mode 100644
index 0000000..53771bc
--- /dev/null
+++ b/crypto/bn/arch/mips64/bn_arch.h
@@ -0,0 +1,40 @@
+/*	$OpenBSD: bn_arch.h,v 1.7 2023/01/23 12:17:58 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#define HAVE_BN_ADD_WORDS
+
+#define HAVE_BN_DIV_WORDS
+#define HAVE_BN_DIV_3_WORDS
+
+#define HAVE_BN_MUL_ADD_WORDS
+#define HAVE_BN_MUL_COMBA4
+#define HAVE_BN_MUL_COMBA8
+#define HAVE_BN_MUL_WORDS
+
+#define HAVE_BN_SQR_COMBA4
+#define HAVE_BN_SQR_COMBA8
+#define HAVE_BN_SQR_WORDS
+
+#define HAVE_BN_SUB_WORDS
+
+#endif
+#endif
diff --git a/crypto/bn/arch/powerpc/bn_arch.h b/crypto/bn/arch/powerpc/bn_arch.h
new file mode 100644
index 0000000..46e932a
--- /dev/null
+++ b/crypto/bn/arch/powerpc/bn_arch.h
@@ -0,0 +1,39 @@
+/*	$OpenBSD: bn_arch.h,v 1.6 2023/01/23 12:17:58 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#define HAVE_BN_ADD_WORDS
+
+#define HAVE_BN_DIV_WORDS
+
+#define HAVE_BN_MUL_ADD_WORDS
+#define HAVE_BN_MUL_COMBA4
+#define HAVE_BN_MUL_COMBA8
+#define HAVE_BN_MUL_WORDS
+
+#define HAVE_BN_SQR_COMBA4
+#define HAVE_BN_SQR_COMBA8
+#define HAVE_BN_SQR_WORDS
+
+#define HAVE_BN_SUB_WORDS
+
+#endif
+#endif
diff --git a/crypto/bn/arch/powerpc64/bn_arch.h b/crypto/bn/arch/powerpc64/bn_arch.h
new file mode 100644
index 0000000..18bac20
--- /dev/null
+++ b/crypto/bn/arch/powerpc64/bn_arch.h
@@ -0,0 +1,44 @@
+/*	$OpenBSD: bn_arch.h,v 1.4 2023/02/16 10:41:03 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#if 0 /* Needs testing and enabling. */
+#if defined(__GNUC__)
+#define HAVE_BN_MULW
+
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/* Unsigned multiplication using a mulhdu/mul pair. */
+	__asm__ ("mulhdu %0, %2, %3; mul %1, %2, %3"
+	    : "=&r"(r1), "=r"(r0)
+	    : "r"(a), "r"(b));
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif /* __GNUC__ */
+#endif
+
+#endif
+#endif
diff --git a/crypto/bn/arch/riscv64/bn_arch.h b/crypto/bn/arch/riscv64/bn_arch.h
new file mode 100644
index 0000000..e67de83
--- /dev/null
+++ b/crypto/bn/arch/riscv64/bn_arch.h
@@ -0,0 +1,86 @@
+/*	$OpenBSD: bn_arch.h,v 1.7 2023/07/09 10:37:32 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#if defined(__GNUC__)
+
+#define HAVE_BN_ADDW
+
+static inline void
+bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r0;
+
+	__asm__ (
+	    "add   %[r0], %[a], %[b] \n"
+	    "sltu  %[carry], %[r0], %[a] \n"
+	    : [carry]"=r"(carry), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b));
+
+	*out_r1 = carry;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_MULW
+ 
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0;
+
+	/*
+	 * Unsigned multiplication using a mulh/mul pair. Note that the order
+	 * of these instructions is important, as they can potentially be fused
+	 * into a single operation.
+	 */
+	__asm__ (
+	    "mulhu %[r1], %[a], %[b] \n"
+	    "mul   %[r0], %[a], %[b] \n"
+	    : [r1]"=&r"(r1), [r0]"=r"(r0)
+	    : [a]"r"(a), [b]"r"(b));
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+
+#define HAVE_BN_SUBW
+
+static inline void
+bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	__asm__ (
+	    "sub   %[r0], %[a], %[b] \n"
+	    "sltu  %[borrow], %[a], %[r0] \n"
+	    : [borrow]"=r"(borrow), [r0]"=&r"(r0)
+	    : [a]"r"(a), [b]"r"(b));
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+
+#endif /* __GNUC__ */
+
+#endif
+#endif
diff --git a/crypto/bn/arch/sh/bn_arch.h b/crypto/bn/arch/sh/bn_arch.h
new file mode 100644
index 0000000..4d6571f
--- /dev/null
+++ b/crypto/bn/arch/sh/bn_arch.h
@@ -0,0 +1,24 @@
+/*	$OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:34 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#endif
+#endif
diff --git a/crypto/bn/arch/sparc64/bn_arch.h b/crypto/bn/arch/sparc64/bn_arch.h
new file mode 100644
index 0000000..4d6571f
--- /dev/null
+++ b/crypto/bn/arch/sparc64/bn_arch.h
@@ -0,0 +1,24 @@
+/*	$OpenBSD: bn_arch.h,v 1.1 2023/01/20 10:04:34 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_BN_ARCH_H
+#define HEADER_BN_ARCH_H
+
+#ifndef OPENSSL_NO_ASM
+
+#endif
+#endif
diff --git a/crypto/bn/bn-mips.S b/crypto/bn/bn-mips.S
new file mode 100644
index 0000000..eb4ac9b
--- /dev/null
+++ b/crypto/bn/bn-mips.S
@@ -0,0 +1,2162 @@
+.set	mips2
+.rdata
+.asciiz	"mips3.s, Version 1.2"
+.asciiz	"MIPS II/III/IV ISA artwork by Andy Polyakov "
+
+.text
+.set	noat
+
+.align	5
+.globl	bn_mul_add_words
+.ent	bn_mul_add_words
+bn_mul_add_words:
+	.set	noreorder
+	bgtz	$6,bn_mul_add_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_mul_add_words
+
+.align	5
+.ent	bn_mul_add_words_internal
+bn_mul_add_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_mul_add_words_tail
+
+.L_bn_mul_add_words_loop:
+	lw	$12,0($5)
+	multu	$12,$7
+	lw	$13,0($4)
+	lw	$14,4($5)
+	lw	$15,4($4)
+	lw	$8,2*4($5)
+	lw	$9,2*4($4)
+	addu	$13,$2
+	sltu	$2,$13,$2	# All manuals say it "compares 32-bit
+				# values", but it seems to work fine
+				# even on 64-bit registers.
+	mflo	$1
+	mfhi	$12
+	addu	$13,$1
+	addu	$2,$12
+	 multu	$14,$7
+	sltu	$1,$13,$1
+	sw	$13,0($4)
+	addu	$2,$1
+
+	lw	$10,3*4($5)
+	lw	$11,3*4($4)
+	addu	$15,$2
+	sltu	$2,$15,$2
+	mflo	$1
+	mfhi	$14
+	addu	$15,$1
+	addu	$2,$14
+	 multu	$8,$7
+	sltu	$1,$15,$1
+	sw	$15,4($4)
+	addu	$2,$1
+
+	subu	$6,4
+	addu $4,4*4
+	addu $5,4*4
+	addu	$9,$2
+	sltu	$2,$9,$2
+	mflo	$1
+	mfhi	$8
+	addu	$9,$1
+	addu	$2,$8
+	 multu	$10,$7
+	sltu	$1,$9,$1
+	sw	$9,-2*4($4)
+	addu	$2,$1
+
+
+	and	$8,$6,$3
+	addu	$11,$2
+	sltu	$2,$11,$2
+	mflo	$1
+	mfhi	$10
+	addu	$11,$1
+	addu	$2,$10
+	sltu	$1,$11,$1
+	sw	$11,-4($4)
+	.set	noreorder
+	bgtz	$8,.L_bn_mul_add_words_loop
+	addu	$2,$1
+
+	beqz	$6,.L_bn_mul_add_words_return
+	nop
+
+.L_bn_mul_add_words_tail:
+	.set	reorder
+	lw	$12,0($5)
+	multu	$12,$7
+	lw	$13,0($4)
+	subu	$6,1
+	addu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	addu	$13,$1
+	addu	$2,$12
+	sltu	$1,$13,$1
+	sw	$13,0($4)
+	addu	$2,$1
+	beqz	$6,.L_bn_mul_add_words_return
+
+	lw	$12,4($5)
+	multu	$12,$7
+	lw	$13,4($4)
+	subu	$6,1
+	addu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	addu	$13,$1
+	addu	$2,$12
+	sltu	$1,$13,$1
+	sw	$13,4($4)
+	addu	$2,$1
+	beqz	$6,.L_bn_mul_add_words_return
+
+	lw	$12,2*4($5)
+	multu	$12,$7
+	lw	$13,2*4($4)
+	addu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	addu	$13,$1
+	addu	$2,$12
+	sltu	$1,$13,$1
+	sw	$13,2*4($4)
+	addu	$2,$1
+
+.L_bn_mul_add_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_mul_add_words_internal
+
+.align	5
+.globl	bn_mul_words
+.ent	bn_mul_words
+bn_mul_words:
+	.set	noreorder
+	bgtz	$6,bn_mul_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_mul_words
+
+.align	5
+.ent	bn_mul_words_internal
+bn_mul_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_mul_words_tail
+
+.L_bn_mul_words_loop:
+	lw	$12,0($5)
+	multu	$12,$7
+	lw	$14,4($5)
+	lw	$8,2*4($5)
+	lw	$10,3*4($5)
+	mflo	$1
+	mfhi	$12
+	addu	$2,$1
+	sltu	$13,$2,$1
+	 multu	$14,$7
+	sw	$2,0($4)
+	addu	$2,$13,$12
+
+	subu	$6,4
+	addu $4,4*4
+	addu $5,4*4
+	mflo	$1
+	mfhi	$14
+	addu	$2,$1
+	sltu	$15,$2,$1
+	 multu	$8,$7
+	sw	$2,-3*4($4)
+	addu	$2,$15,$14
+
+	mflo	$1
+	mfhi	$8
+	addu	$2,$1
+	sltu	$9,$2,$1
+	 multu	$10,$7
+	sw	$2,-2*4($4)
+	addu	$2,$9,$8
+
+	and	$8,$6,$3
+	mflo	$1
+	mfhi	$10
+	addu	$2,$1
+	sltu	$11,$2,$1
+	sw	$2,-4($4)
+	.set	noreorder
+	bgtz	$8,.L_bn_mul_words_loop
+	addu	$2,$11,$10
+
+	beqz	$6,.L_bn_mul_words_return
+	nop
+
+.L_bn_mul_words_tail:
+	.set	reorder
+	lw	$12,0($5)
+	multu	$12,$7
+	subu	$6,1
+	mflo	$1
+	mfhi	$12
+	addu	$2,$1
+	sltu	$13,$2,$1
+	sw	$2,0($4)
+	addu	$2,$13,$12
+	beqz	$6,.L_bn_mul_words_return
+
+	lw	$12,4($5)
+	multu	$12,$7
+	subu	$6,1
+	mflo	$1
+	mfhi	$12
+	addu	$2,$1
+	sltu	$13,$2,$1
+	sw	$2,4($4)
+	addu	$2,$13,$12
+	beqz	$6,.L_bn_mul_words_return
+
+	lw	$12,2*4($5)
+	multu	$12,$7
+	mflo	$1
+	mfhi	$12
+	addu	$2,$1
+	sltu	$13,$2,$1
+	sw	$2,2*4($4)
+	addu	$2,$13,$12
+
+.L_bn_mul_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_mul_words_internal
+
+.align	5
+.globl	bn_sqr_words
+.ent	bn_sqr_words
+bn_sqr_words:
+	.set	noreorder
+	bgtz	$6,bn_sqr_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_sqr_words
+
+.align	5
+.ent	bn_sqr_words_internal
+bn_sqr_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_sqr_words_tail
+
+.L_bn_sqr_words_loop:
+	lw	$12,0($5)
+	multu	$12,$12
+	lw	$14,4($5)
+	lw	$8,2*4($5)
+	lw	$10,3*4($5)
+	mflo	$13
+	mfhi	$12
+	sw	$13,0($4)
+	sw	$12,4($4)
+
+	multu	$14,$14
+	subu	$6,4
+	addu $4,8*4
+	addu $5,4*4
+	mflo	$15
+	mfhi	$14
+	sw	$15,-6*4($4)
+	sw	$14,-5*4($4)
+
+	multu	$8,$8
+	mflo	$9
+	mfhi	$8
+	sw	$9,-4*4($4)
+	sw	$8,-3*4($4)
+
+
+	multu	$10,$10
+	and	$8,$6,$3
+	mflo	$11
+	mfhi	$10
+	sw	$11,-2*4($4)
+
+	.set	noreorder
+	bgtz	$8,.L_bn_sqr_words_loop
+	sw	$10,-4($4)
+
+	beqz	$6,.L_bn_sqr_words_return
+	nop
+
+.L_bn_sqr_words_tail:
+	.set	reorder
+	lw	$12,0($5)
+	multu	$12,$12
+	subu	$6,1
+	mflo	$13
+	mfhi	$12
+	sw	$13,0($4)
+	sw	$12,4($4)
+	beqz	$6,.L_bn_sqr_words_return
+
+	lw	$12,4($5)
+	multu	$12,$12
+	subu	$6,1
+	mflo	$13
+	mfhi	$12
+	sw	$13,2*4($4)
+	sw	$12,3*4($4)
+	beqz	$6,.L_bn_sqr_words_return
+
+	lw	$12,2*4($5)
+	multu	$12,$12
+	mflo	$13
+	mfhi	$12
+	sw	$13,4*4($4)
+	sw	$12,5*4($4)
+
+.L_bn_sqr_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+
+.end	bn_sqr_words_internal
+
+.align	5
+.globl	bn_add_words
+.ent	bn_add_words
+bn_add_words:
+	.set	noreorder
+	bgtz	$7,bn_add_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_add_words
+
+.align	5
+.ent	bn_add_words_internal
+bn_add_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$1,$7,$3
+	beqz	$1,.L_bn_add_words_tail
+
+.L_bn_add_words_loop:
+	lw	$12,0($5)
+	lw	$8,0($6)
+	subu	$7,4
+	lw	$13,4($5)
+	and	$1,$7,$3
+	lw	$14,2*4($5)
+	addu $6,4*4
+	lw	$15,3*4($5)
+	addu $4,4*4
+	lw	$9,-3*4($6)
+	addu $5,4*4
+	lw	$10,-2*4($6)
+	lw	$11,-4($6)
+	addu	$8,$12
+	sltu	$24,$8,$12
+	addu	$12,$8,$2
+	sltu	$2,$12,$8
+	sw	$12,-4*4($4)
+	addu	$2,$24
+
+	addu	$9,$13
+	sltu	$25,$9,$13
+	addu	$13,$9,$2
+	sltu	$2,$13,$9
+	sw	$13,-3*4($4)
+	addu	$2,$25
+
+	addu	$10,$14
+	sltu	$24,$10,$14
+	addu	$14,$10,$2
+	sltu	$2,$14,$10
+	sw	$14,-2*4($4)
+	addu	$2,$24
+	
+	addu	$11,$15
+	sltu	$25,$11,$15
+	addu	$15,$11,$2
+	sltu	$2,$15,$11
+	sw	$15,-4($4)
+	
+	.set	noreorder
+	bgtz	$1,.L_bn_add_words_loop
+	addu	$2,$25
+
+	beqz	$7,.L_bn_add_words_return
+	nop
+
+.L_bn_add_words_tail:
+	.set	reorder
+	lw	$12,0($5)
+	lw	$8,0($6)
+	addu	$8,$12
+	subu	$7,1
+	sltu	$24,$8,$12
+	addu	$12,$8,$2
+	sltu	$2,$12,$8
+	sw	$12,0($4)
+	addu	$2,$24
+	beqz	$7,.L_bn_add_words_return
+
+	lw	$13,4($5)
+	lw	$9,4($6)
+	addu	$9,$13
+	subu	$7,1
+	sltu	$25,$9,$13
+	addu	$13,$9,$2
+	sltu	$2,$13,$9
+	sw	$13,4($4)
+	addu	$2,$25
+	beqz	$7,.L_bn_add_words_return
+
+	lw	$14,2*4($5)
+	lw	$10,2*4($6)
+	addu	$10,$14
+	sltu	$24,$10,$14
+	addu	$14,$10,$2
+	sltu	$2,$14,$10
+	sw	$14,2*4($4)
+	addu	$2,$24
+
+.L_bn_add_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+
+.end	bn_add_words_internal
+
+.align	5
+.globl	bn_sub_words
+.ent	bn_sub_words
+bn_sub_words:
+	.set	noreorder
+	bgtz	$7,bn_sub_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$0
+.end	bn_sub_words
+
+.align	5
+.ent	bn_sub_words_internal
+bn_sub_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$1,$7,$3
+	beqz	$1,.L_bn_sub_words_tail
+
+.L_bn_sub_words_loop:
+	lw	$12,0($5)
+	lw	$8,0($6)
+	subu	$7,4
+	lw	$13,4($5)
+	and	$1,$7,$3
+	lw	$14,2*4($5)
+	addu $6,4*4
+	lw	$15,3*4($5)
+	addu $4,4*4
+	lw	$9,-3*4($6)
+	addu $5,4*4
+	lw	$10,-2*4($6)
+	lw	$11,-4($6)
+	sltu	$24,$12,$8
+	subu	$8,$12,$8
+	subu	$12,$8,$2
+	sgtu	$2,$12,$8
+	sw	$12,-4*4($4)
+	addu	$2,$24
+
+	sltu	$25,$13,$9
+	subu	$9,$13,$9
+	subu	$13,$9,$2
+	sgtu	$2,$13,$9
+	sw	$13,-3*4($4)
+	addu	$2,$25
+
+
+	sltu	$24,$14,$10
+	subu	$10,$14,$10
+	subu	$14,$10,$2
+	sgtu	$2,$14,$10
+	sw	$14,-2*4($4)
+	addu	$2,$24
+
+	sltu	$25,$15,$11
+	subu	$11,$15,$11
+	subu	$15,$11,$2
+	sgtu	$2,$15,$11
+	sw	$15,-4($4)
+
+	.set	noreorder
+	bgtz	$1,.L_bn_sub_words_loop
+	addu	$2,$25
+
+	beqz	$7,.L_bn_sub_words_return
+	nop
+
+.L_bn_sub_words_tail:
+	.set	reorder
+	lw	$12,0($5)
+	lw	$8,0($6)
+	subu	$7,1
+	sltu	$24,$12,$8
+	subu	$8,$12,$8
+	subu	$12,$8,$2
+	sgtu	$2,$12,$8
+	sw	$12,0($4)
+	addu	$2,$24
+	beqz	$7,.L_bn_sub_words_return
+
+	lw	$13,4($5)
+	subu	$7,1
+	lw	$9,4($6)
+	sltu	$25,$13,$9
+	subu	$9,$13,$9
+	subu	$13,$9,$2
+	sgtu	$2,$13,$9
+	sw	$13,4($4)
+	addu	$2,$25
+	beqz	$7,.L_bn_sub_words_return
+
+	lw	$14,2*4($5)
+	lw	$10,2*4($6)
+	sltu	$24,$14,$10
+	subu	$10,$14,$10
+	subu	$14,$10,$2
+	sgtu	$2,$14,$10
+	sw	$14,2*4($4)
+	addu	$2,$24
+
+.L_bn_sub_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_sub_words_internal
+
+.align 5
+.globl	bn_div_3_words
+.ent	bn_div_3_words
+bn_div_3_words:
+	.set	noreorder
+	move	$7,$4		# we know that bn_div_words does not
+				# touch $7, $10, $11 and preserves $6
+				# so that we can save two arguments
+				# and return address in registers
+				# instead of stack:-)
+				
+	lw	$4,($7)
+	move	$10,$5
+	bne	$4,$6,bn_div_3_words_internal
+	lw	$5,-4($7)
+	li	$2,-1
+	jr	$31
+	move	$4,$2
+.end	bn_div_3_words
+
+.align	5
+.ent	bn_div_3_words_internal
+bn_div_3_words_internal:
+	.set	reorder
+	move	$11,$31
+	bal	bn_div_words_internal
+	move	$31,$11
+	multu	$10,$2
+	lw	$14,-2*4($7)
+	move	$8,$0
+	mfhi	$13
+	mflo	$12
+	sltu	$24,$13,$5
+.L_bn_div_3_words_inner_loop:
+	bnez	$24,.L_bn_div_3_words_inner_loop_done
+	sgeu	$1,$14,$12
+	seq	$25,$13,$5
+	and	$1,$25
+	sltu	$15,$12,$10
+	addu	$5,$6
+	subu	$13,$15
+	subu	$12,$10
+	sltu	$24,$13,$5
+	sltu	$8,$5,$6
+	or	$24,$8
+	.set	noreorder
+	beqz	$1,.L_bn_div_3_words_inner_loop
+	subu	$2,1
+	addu	$2,1
+	.set	reorder
+.L_bn_div_3_words_inner_loop_done:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_div_3_words_internal
+
+.align	5
+.globl	bn_div_words
+.ent	bn_div_words
+bn_div_words:
+	.set	noreorder
+	bnez	$6,bn_div_words_internal
+	li	$2,-1		# I would rather signal div-by-zero
+				# which can be done with 'break 7'
+	jr	$31
+	move	$4,$2
+.end	bn_div_words
+
+.align	5
+.ent	bn_div_words_internal
+bn_div_words_internal:
+	move	$3,$0
+	bltz	$6,.L_bn_div_words_body
+	move	$25,$3
+	sll	$6,1
+	bgtz	$6,.-4
+	addu	$25,1
+
+	.set	reorder
+	negu	$13,$25
+	li	$14,-1
+	sll	$14,$13
+	and	$14,$4
+	srl	$1,$5,$13
+	.set	noreorder
+	beqz	$14,.+12
+	nop
+	break	6		# signal overflow
+	.set	reorder
+	sll	$4,$25
+	sll	$5,$25
+	or	$4,$1
+.L_bn_div_words_body:
+	srl	$3,$6,4*4	# bits
+	sgeu	$1,$4,$6
+	.set	noreorder
+	beqz	$1,.+12
+	nop
+	subu	$4,$6
+	.set	reorder
+
+	li	$8,-1
+	srl	$9,$4,4*4	# bits
+	srl	$8,4*4	# q=0xffffffff
+	beq	$3,$9,.L_bn_div_words_skip_div1
+	divu	$0,$4,$3
+	mflo	$8
+.L_bn_div_words_skip_div1:
+	multu	$6,$8
+	sll	$15,$4,4*4	# bits
+	srl	$1,$5,4*4	# bits
+	or	$15,$1
+	mflo	$12
+	mfhi	$13
+.L_bn_div_words_inner_loop1:
+	sltu	$14,$15,$12
+	seq	$24,$9,$13
+	sltu	$1,$9,$13
+	and	$14,$24
+	sltu	$2,$12,$6
+	or	$1,$14
+	.set	noreorder
+	beqz	$1,.L_bn_div_words_inner_loop1_done
+	subu	$13,$2
+	subu	$12,$6
+	b	.L_bn_div_words_inner_loop1
+	subu	$8,1
+	.set	reorder
+.L_bn_div_words_inner_loop1_done:
+
+	sll	$5,4*4	# bits
+	subu	$4,$15,$12
+	sll	$2,$8,4*4	# bits
+
+	li	$8,-1
+	srl	$9,$4,4*4	# bits
+	srl	$8,4*4	# q=0xffffffff
+	beq	$3,$9,.L_bn_div_words_skip_div2
+	divu	$0,$4,$3
+	mflo	$8
+.L_bn_div_words_skip_div2:
+	multu	$6,$8
+	sll	$15,$4,4*4	# bits
+	srl	$1,$5,4*4	# bits
+	or	$15,$1
+	mflo	$12
+	mfhi	$13
+.L_bn_div_words_inner_loop2:
+	sltu	$14,$15,$12
+	seq	$24,$9,$13
+	sltu	$1,$9,$13
+	and	$14,$24
+	sltu	$3,$12,$6
+	or	$1,$14
+	.set	noreorder
+	beqz	$1,.L_bn_div_words_inner_loop2_done
+	subu	$13,$3
+	subu	$12,$6
+	b	.L_bn_div_words_inner_loop2
+	subu	$8,1
+	.set	reorder
+.L_bn_div_words_inner_loop2_done:
+
+	subu	$4,$15,$12
+	or	$2,$8
+	srl	$3,$4,$25	# $3 contains remainder if anybody wants it
+	srl	$6,$25		# restore $6
+
+	.set	noreorder
+	move	$5,$3
+	jr	$31
+	move	$4,$2
+.end	bn_div_words_internal
+
+.align	5
+.globl	bn_mul_comba8
+.ent	bn_mul_comba8
+bn_mul_comba8:
+	.set	noreorder
+	.frame	$29,6*4,$31
+	.mask	0x003f0000,-4
+	subu $29,6*4
+	sw	$21,5*4($29)
+	sw	$20,4*4($29)
+	sw	$19,3*4($29)
+	sw	$18,2*4($29)
+	sw	$17,1*4($29)
+	sw	$16,0*4($29)
+
+	.set	reorder
+	lw	$12,0($5)	# If compiled with -mips3 option on
+				# R5000 box assembler barks on this
+				# 1ine with "should not have mult/div
+				# as last instruction in bb (R10K
+				# bug)" warning. If anybody out there
+				# has a clue about how to circumvent
+				# this do send me a note.
+				#		
+
+	lw	$8,0($6)
+	lw	$13,4($5)
+	lw	$14,2*4($5)
+	multu	$12,$8		# mul_add_c(a[0],b[0],c1,c2,c3);
+	lw	$15,3*4($5)
+	lw	$9,4($6)
+	lw	$10,2*4($6)
+	lw	$11,3*4($6)
+	mflo	$2
+	mfhi	$3
+
+	lw	$16,4*4($5)
+	lw	$18,5*4($5)
+	multu	$12,$9		# mul_add_c(a[0],b[1],c2,c3,c1);
+	lw	$20,6*4($5)
+	lw	$5,7*4($5)
+	lw	$17,4*4($6)
+	lw	$19,5*4($6)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$13,$8		# mul_add_c(a[1],b[0],c2,c3,c1);
+	addu	$7,$25,$1
+	lw	$21,6*4($6)
+	lw	$6,7*4($6)
+	sw	$2,0($4)	# r[0]=c1;
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$8		# mul_add_c(a[2],b[0],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	sw	$3,4($4)	# r[1]=c2;
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$13,$9		# mul_add_c(a[1],b[1],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$12,$10		# mul_add_c(a[0],b[2],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$12,$11		# mul_add_c(a[0],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,2*4($4)	# r[2]=c3;
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$13,$10		# mul_add_c(a[1],b[2],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$14,$9		# mul_add_c(a[2],b[1],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$15,$8		# mul_add_c(a[3],b[0],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$16,$8		# mul_add_c(a[4],b[0],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,3*4($4)	# r[3]=c1;
+
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$15,$9		# mul_add_c(a[3],b[1],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$14,$10		# mul_add_c(a[2],b[2],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$13,$11		# mul_add_c(a[1],b[3],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$12,$17		# mul_add_c(a[0],b[4],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$12,$19		# mul_add_c(a[0],b[5],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,4*4($4)	# r[4]=c2;
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$13,$17		# mul_add_c(a[1],b[4],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$14,$11		# mul_add_c(a[2],b[3],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$15,$10		# mul_add_c(a[3],b[2],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$16,$9		# mul_add_c(a[4],b[1],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$18,$8		# mul_add_c(a[5],b[0],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$20,$8		# mul_add_c(a[6],b[0],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,5*4($4)	# r[5]=c3;
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$18,$9		# mul_add_c(a[5],b[1],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$16,$10		# mul_add_c(a[4],b[2],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$15,$11		# mul_add_c(a[3],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$14,$17		# mul_add_c(a[2],b[4],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$13,$19		# mul_add_c(a[1],b[5],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$12,$21		# mul_add_c(a[0],b[6],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$12,$6		# mul_add_c(a[0],b[7],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,6*4($4)	# r[6]=c1;
+
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$13,$21		# mul_add_c(a[1],b[6],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$14,$19		# mul_add_c(a[2],b[5],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$15,$17		# mul_add_c(a[3],b[4],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$16,$11		# mul_add_c(a[4],b[3],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$18,$10		# mul_add_c(a[5],b[2],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$20,$9		# mul_add_c(a[6],b[1],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$5,$8		# mul_add_c(a[7],b[0],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$5,$9		# mul_add_c(a[7],b[1],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,7*4($4)	# r[7]=c2;
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$20,$10		# mul_add_c(a[6],b[2],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$18,$11		# mul_add_c(a[5],b[3],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$16,$17		# mul_add_c(a[4],b[4],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$15,$19		# mul_add_c(a[3],b[5],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$14,$21		# mul_add_c(a[2],b[6],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$13,$6		# mul_add_c(a[1],b[7],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$14,$6		# mul_add_c(a[2],b[7],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,8*4($4)	# r[8]=c3;
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$15,$21		# mul_add_c(a[3],b[6],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$16,$19		# mul_add_c(a[4],b[5],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$18,$17		# mul_add_c(a[5],b[4],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$20,$11		# mul_add_c(a[6],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$5,$10		# mul_add_c(a[7],b[2],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$5,$11		# mul_add_c(a[7],b[3],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,9*4($4)	# r[9]=c1;
+
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$20,$17		# mul_add_c(a[6],b[4],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$18,$19		# mul_add_c(a[5],b[5],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$16,$21		# mul_add_c(a[4],b[6],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$15,$6		# mul_add_c(a[3],b[7],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$16,$6		# mul_add_c(a[4],b[7],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,10*4($4)	# r[10]=c2;
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$18,$21		# mul_add_c(a[5],b[6],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$20,$19		# mul_add_c(a[6],b[5],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$5,$17		# mul_add_c(a[7],b[4],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$5,$19		# mul_add_c(a[7],b[5],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,11*4($4)	# r[11]=c3;
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$20,$21		# mul_add_c(a[6],b[6],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$18,$6		# mul_add_c(a[5],b[7],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$20,$6		# mul_add_c(a[6],b[7],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,12*4($4)	# r[12]=c1;
+
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$5,$21		# mul_add_c(a[7],b[6],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$5,$6		# mul_add_c(a[7],b[7],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,13*4($4)	# r[13]=c2;
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	addu	$25,$1
+	addu	$2,$25
+	sw	$7,14*4($4)	# r[14]=c3;
+	sw	$2,15*4($4)	# r[15]=c1;
+
+	.set	noreorder
+	lw	$21,5*4($29)
+	lw	$20,4*4($29)
+	lw	$19,3*4($29)
+	lw	$18,2*4($29)
+	lw	$17,1*4($29)
+	lw	$16,0*4($29)
+	jr	$31
+	addu $29,6*4
+.end	bn_mul_comba8
+
+.align	5
+.globl	bn_mul_comba4
+.ent	bn_mul_comba4
+bn_mul_comba4:
+	.set	reorder
+	lw	$12,0($5)
+	lw	$8,0($6)
+	lw	$13,4($5)
+	lw	$14,2*4($5)
+	multu	$12,$8		# mul_add_c(a[0],b[0],c1,c2,c3);
+	lw	$15,3*4($5)
+	lw	$9,4($6)
+	lw	$10,2*4($6)
+	lw	$11,3*4($6)
+	mflo	$2
+	mfhi	$3
+	sw	$2,0($4)
+
+	multu	$12,$9		# mul_add_c(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$13,$8		# mul_add_c(a[1],b[0],c2,c3,c1);
+	addu	$7,$25,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$8		# mul_add_c(a[2],b[0],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	sw	$3,4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$13,$9		# mul_add_c(a[1],b[1],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$12,$10		# mul_add_c(a[0],b[2],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$12,$11		# mul_add_c(a[0],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,2*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$13,$10		# mul_add_c(a[1],b[2],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$14,$9		# mul_add_c(a[2],b[1],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	multu	$15,$8		# mul_add_c(a[3],b[0],c1,c2,c3);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$15,$9		# mul_add_c(a[3],b[1],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,3*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$14,$10		# mul_add_c(a[2],b[2],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	multu	$13,$11		# mul_add_c(a[1],b[3],c2,c3,c1);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$11		# mul_add_c(a[2],b[3],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,4*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	multu	$15,$10		# mul_add_c(a[3],b[2],c3,c1,c2);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$15,$11		# mul_add_c(a[3],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,5*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	addu	$25,$1
+	addu	$3,$25
+	sw	$2,6*4($4)
+	sw	$3,7*4($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_mul_comba4
+
+.align	5
+.globl	bn_sqr_comba8
+.ent	bn_sqr_comba8
+bn_sqr_comba8:
+	.set	reorder
+	lw	$12,0($5)
+	lw	$13,4($5)
+	lw	$14,2*4($5)
+	lw	$15,3*4($5)
+
+	multu	$12,$12		# mul_add_c(a[0],b[0],c1,c2,c3);
+	lw	$8,4*4($5)
+	lw	$9,5*4($5)
+	lw	$10,6*4($5)
+	lw	$11,7*4($5)
+	mflo	$2
+	mfhi	$3
+	sw	$2,0($4)
+
+	multu	$12,$13		# mul_add_c2(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	slt	$2,$25,$0
+	sll	$25,1
+	 multu	$14,$12		# mul_add_c2(a[2],b[0],c3,c1,c2);
+	slt	$6,$24,$0
+	addu	$25,$6
+	sll	$24,1
+	addu	$3,$24
+	sltu	$1,$3,$24
+	addu	$7,$25,$1
+	sw	$3,4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$13,$13			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$12,$15		# mul_add_c2(a[0],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,2*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$13,$14			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$7,$3,$1
+	addu	$3,$25
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$8,$12			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	sw	$2,3*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$15,$13			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$2,$7,$1
+	addu	$7,$25
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$14			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$1,$7,$1
+	addu	$7,$25
+	addu	$2,$1
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$12,$9		# mul_add_c2(a[0],b[5],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,4*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$13,$8			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$14,$15			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$1,$2,$1
+	addu	$2,$25
+	addu	$3,$1
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$10,$12			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$1,$2,$1
+	addu	$2,$25
+	addu	$3,$1
+	sltu	$25,$2,$25
+	addu	$3,$25
+	sw	$7,5*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$9,$13			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$7,$3,$1
+	addu	$3,$25
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$8,$14			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$15,$15			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$12,$11		# mul_add_c2(a[0],b[7],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,6*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$13,$10			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$2,$7,$1
+	addu	$7,$25
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$9			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$1,$7,$1
+	addu	$7,$25
+	addu	$2,$1
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$15,$8			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$1,$7,$1
+	addu	$7,$25
+	addu	$2,$1
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$11,$13			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$1,$7,$1
+	addu	$7,$25
+	addu	$2,$1
+	sltu	$25,$7,$25
+	addu	$2,$25
+	sw	$3,7*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$10,$14			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$9,$15			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$1,$2,$1
+	addu	$2,$25
+	addu	$3,$1
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$8,$8			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$1,$2,$1
+	addu	$2,$25
+	addu	$3,$1
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$14,$11		# mul_add_c2(a[2],b[7],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,8*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$15,$10			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$7,$3,$1
+	addu	$3,$25
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$8,$9			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$11,$15			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	sw	$2,9*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$10,$8			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$2,$7,$1
+	addu	$7,$25
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$9,$9			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$1,$7,$1
+	addu	$7,$25
+	addu	$2,$1
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$8,$11		# mul_add_c2(a[4],b[7],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,10*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$9,$10			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$11,$9			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$1,$2,$1
+	addu	$2,$25
+	addu	$3,$1
+	sltu	$25,$2,$25
+	addu	$3,$25
+	sw	$7,11*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$10,$10			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$7,$3,$1
+	addu	$3,$25
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$10,$11		# mul_add_c2(a[6],b[7],c2,c3,c1);
+	addu	$25,$1
+	addu	$3,$25
+	sltu	$1,$3,$25
+	addu	$7,$1
+	sw	$2,12*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$11,$11			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$2,$7,$1
+	addu	$7,$25
+	sltu	$25,$7,$25
+	addu	$2,$25
+	sw	$3,13*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	addu	$25,$1
+	addu	$2,$25
+	sw	$7,14*4($4)
+	sw	$2,15*4($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_sqr_comba8
+
+.align	5
+.globl	bn_sqr_comba4
+.ent	bn_sqr_comba4
+bn_sqr_comba4:
+	.set	reorder
+	lw	$12,0($5)
+	lw	$13,4($5)
+	multu	$12,$12		# mul_add_c(a[0],b[0],c1,c2,c3);
+	lw	$14,2*4($5)
+	lw	$15,3*4($5)
+	mflo	$2
+	mfhi	$3
+	sw	$2,0($4)
+
+	multu	$12,$13		# mul_add_c2(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	slt	$2,$25,$0
+	sll	$25,1
+	 multu	$14,$12		# mul_add_c2(a[2],b[0],c3,c1,c2);
+	slt	$6,$24,$0
+	addu	$25,$6
+	sll	$24,1
+	addu	$3,$24
+	sltu	$1,$3,$24
+	addu	$7,$25,$1
+	sw	$3,4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$13,$13			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$12,$15		# mul_add_c2(a[0],b[3],c1,c2,c3);
+	addu	$25,$1
+	addu	$2,$25
+	sltu	$1,$2,$25
+	addu	$3,$1
+	sw	$7,2*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$13,$14			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$7,$3,$1
+	addu	$3,$25
+	sltu	$25,$3,$25
+	addu	$7,$25
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	 multu	$15,$13			# forward multiplication
+	addu	$2,$24
+	addu	$1,$25
+	sltu	$24,$2,$24
+	addu	$3,$1
+	addu	$25,$24
+	sltu	$1,$3,$1
+	addu	$3,$25
+	addu	$7,$1
+	sltu	$25,$3,$25
+	addu	$7,$25
+	sw	$2,3*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$14			# forward multiplication
+	addu	$3,$24
+	addu	$1,$25
+	sltu	$24,$3,$24
+	addu	$7,$1
+	addu	$25,$24
+	sltu	$2,$7,$1
+	addu	$7,$25
+	sltu	$25,$7,$25
+	addu	$2,$25
+	mflo	$24
+	mfhi	$25
+	addu	$3,$24
+	sltu	$1,$3,$24
+	 multu	$14,$15		# mul_add_c2(a[2],b[3],c3,c1,c2);
+	addu	$25,$1
+	addu	$7,$25
+	sltu	$1,$7,$25
+	addu	$2,$1
+	sw	$3,4*4($4)
+	mflo	$24
+	mfhi	$25
+	addu	$7,$24
+	sltu	$1,$7,$24
+	 multu	$15,$15			# forward multiplication
+	addu	$7,$24
+	addu	$1,$25
+	sltu	$24,$7,$24
+	addu	$2,$1
+	addu	$25,$24
+	sltu	$3,$2,$1
+	addu	$2,$25
+	sltu	$25,$2,$25
+	addu	$3,$25
+	sw	$7,5*4($4)
+
+	mflo	$24
+	mfhi	$25
+	addu	$2,$24
+	sltu	$1,$2,$24
+	addu	$25,$1
+	addu	$3,$25
+	sw	$2,6*4($4)
+	sw	$3,7*4($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_sqr_comba4
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/bn-mips64.S b/crypto/bn/bn-mips64.S
new file mode 100644
index 0000000..2278f26
--- /dev/null
+++ b/crypto/bn/bn-mips64.S
@@ -0,0 +1,2161 @@
+.rdata
+.asciiz	"mips3.s, Version 1.2"
+.asciiz	"MIPS II/III/IV ISA artwork by Andy Polyakov "
+
+.text
+.set	noat
+
+.align	5
+.globl	bn_mul_add_words
+.ent	bn_mul_add_words
+bn_mul_add_words:
+	.set	noreorder
+	bgtz	$6,bn_mul_add_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_mul_add_words
+
+.align	5
+.ent	bn_mul_add_words_internal
+bn_mul_add_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_mul_add_words_tail
+
+.L_bn_mul_add_words_loop:
+	ld	$12,0($5)
+	dmultu	$12,$7
+	ld	$13,0($4)
+	ld	$14,8($5)
+	ld	$15,8($4)
+	ld	$8,2*8($5)
+	ld	$9,2*8($4)
+	daddu	$13,$2
+	sltu	$2,$13,$2	# All manuals say it "compares 32-bit
+				# values", but it seems to work fine
+				# even on 64-bit registers.
+	mflo	$1
+	mfhi	$12
+	daddu	$13,$1
+	daddu	$2,$12
+	 dmultu	$14,$7
+	sltu	$1,$13,$1
+	sd	$13,0($4)
+	daddu	$2,$1
+
+	ld	$10,3*8($5)
+	ld	$11,3*8($4)
+	daddu	$15,$2
+	sltu	$2,$15,$2
+	mflo	$1
+	mfhi	$14
+	daddu	$15,$1
+	daddu	$2,$14
+	 dmultu	$8,$7
+	sltu	$1,$15,$1
+	sd	$15,8($4)
+	daddu	$2,$1
+
+	subu	$6,4
+	daddu $4,4*8
+	daddu $5,4*8
+	daddu	$9,$2
+	sltu	$2,$9,$2
+	mflo	$1
+	mfhi	$8
+	daddu	$9,$1
+	daddu	$2,$8
+	 dmultu	$10,$7
+	sltu	$1,$9,$1
+	sd	$9,-2*8($4)
+	daddu	$2,$1
+
+
+	and	$8,$6,$3
+	daddu	$11,$2
+	sltu	$2,$11,$2
+	mflo	$1
+	mfhi	$10
+	daddu	$11,$1
+	daddu	$2,$10
+	sltu	$1,$11,$1
+	sd	$11,-8($4)
+	.set	noreorder
+	bgtz	$8,.L_bn_mul_add_words_loop
+	daddu	$2,$1
+
+	beqz	$6,.L_bn_mul_add_words_return
+	nop
+
+.L_bn_mul_add_words_tail:
+	.set	reorder
+	ld	$12,0($5)
+	dmultu	$12,$7
+	ld	$13,0($4)
+	subu	$6,1
+	daddu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	daddu	$13,$1
+	daddu	$2,$12
+	sltu	$1,$13,$1
+	sd	$13,0($4)
+	daddu	$2,$1
+	beqz	$6,.L_bn_mul_add_words_return
+
+	ld	$12,8($5)
+	dmultu	$12,$7
+	ld	$13,8($4)
+	subu	$6,1
+	daddu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	daddu	$13,$1
+	daddu	$2,$12
+	sltu	$1,$13,$1
+	sd	$13,8($4)
+	daddu	$2,$1
+	beqz	$6,.L_bn_mul_add_words_return
+
+	ld	$12,2*8($5)
+	dmultu	$12,$7
+	ld	$13,2*8($4)
+	daddu	$13,$2
+	sltu	$2,$13,$2
+	mflo	$1
+	mfhi	$12
+	daddu	$13,$1
+	daddu	$2,$12
+	sltu	$1,$13,$1
+	sd	$13,2*8($4)
+	daddu	$2,$1
+
+.L_bn_mul_add_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_mul_add_words_internal
+
+.align	5
+.globl	bn_mul_words
+.ent	bn_mul_words
+bn_mul_words:
+	.set	noreorder
+	bgtz	$6,bn_mul_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_mul_words
+
+.align	5
+.ent	bn_mul_words_internal
+bn_mul_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_mul_words_tail
+
+.L_bn_mul_words_loop:
+	ld	$12,0($5)
+	dmultu	$12,$7
+	ld	$14,8($5)
+	ld	$8,2*8($5)
+	ld	$10,3*8($5)
+	mflo	$1
+	mfhi	$12
+	daddu	$2,$1
+	sltu	$13,$2,$1
+	 dmultu	$14,$7
+	sd	$2,0($4)
+	daddu	$2,$13,$12
+
+	subu	$6,4
+	daddu $4,4*8
+	daddu $5,4*8
+	mflo	$1
+	mfhi	$14
+	daddu	$2,$1
+	sltu	$15,$2,$1
+	 dmultu	$8,$7
+	sd	$2,-3*8($4)
+	daddu	$2,$15,$14
+
+	mflo	$1
+	mfhi	$8
+	daddu	$2,$1
+	sltu	$9,$2,$1
+	 dmultu	$10,$7
+	sd	$2,-2*8($4)
+	daddu	$2,$9,$8
+
+	and	$8,$6,$3
+	mflo	$1
+	mfhi	$10
+	daddu	$2,$1
+	sltu	$11,$2,$1
+	sd	$2,-8($4)
+	.set	noreorder
+	bgtz	$8,.L_bn_mul_words_loop
+	daddu	$2,$11,$10
+
+	beqz	$6,.L_bn_mul_words_return
+	nop
+
+.L_bn_mul_words_tail:
+	.set	reorder
+	ld	$12,0($5)
+	dmultu	$12,$7
+	subu	$6,1
+	mflo	$1
+	mfhi	$12
+	daddu	$2,$1
+	sltu	$13,$2,$1
+	sd	$2,0($4)
+	daddu	$2,$13,$12
+	beqz	$6,.L_bn_mul_words_return
+
+	ld	$12,8($5)
+	dmultu	$12,$7
+	subu	$6,1
+	mflo	$1
+	mfhi	$12
+	daddu	$2,$1
+	sltu	$13,$2,$1
+	sd	$2,8($4)
+	daddu	$2,$13,$12
+	beqz	$6,.L_bn_mul_words_return
+
+	ld	$12,2*8($5)
+	dmultu	$12,$7
+	mflo	$1
+	mfhi	$12
+	daddu	$2,$1
+	sltu	$13,$2,$1
+	sd	$2,2*8($4)
+	daddu	$2,$13,$12
+
+.L_bn_mul_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_mul_words_internal
+
+.align	5
+.globl	bn_sqr_words
+.ent	bn_sqr_words
+bn_sqr_words:
+	.set	noreorder
+	bgtz	$6,bn_sqr_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_sqr_words
+
+.align	5
+.ent	bn_sqr_words_internal
+bn_sqr_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$8,$6,$3
+	beqz	$8,.L_bn_sqr_words_tail
+
+.L_bn_sqr_words_loop:
+	ld	$12,0($5)
+	dmultu	$12,$12
+	ld	$14,8($5)
+	ld	$8,2*8($5)
+	ld	$10,3*8($5)
+	mflo	$13
+	mfhi	$12
+	sd	$13,0($4)
+	sd	$12,8($4)
+
+	dmultu	$14,$14
+	subu	$6,4
+	daddu $4,8*8
+	daddu $5,4*8
+	mflo	$15
+	mfhi	$14
+	sd	$15,-6*8($4)
+	sd	$14,-5*8($4)
+
+	dmultu	$8,$8
+	mflo	$9
+	mfhi	$8
+	sd	$9,-4*8($4)
+	sd	$8,-3*8($4)
+
+
+	dmultu	$10,$10
+	and	$8,$6,$3
+	mflo	$11
+	mfhi	$10
+	sd	$11,-2*8($4)
+
+	.set	noreorder
+	bgtz	$8,.L_bn_sqr_words_loop
+	sd	$10,-8($4)
+
+	beqz	$6,.L_bn_sqr_words_return
+	nop
+
+.L_bn_sqr_words_tail:
+	.set	reorder
+	ld	$12,0($5)
+	dmultu	$12,$12
+	subu	$6,1
+	mflo	$13
+	mfhi	$12
+	sd	$13,0($4)
+	sd	$12,8($4)
+	beqz	$6,.L_bn_sqr_words_return
+
+	ld	$12,8($5)
+	dmultu	$12,$12
+	subu	$6,1
+	mflo	$13
+	mfhi	$12
+	sd	$13,2*8($4)
+	sd	$12,3*8($4)
+	beqz	$6,.L_bn_sqr_words_return
+
+	ld	$12,2*8($5)
+	dmultu	$12,$12
+	mflo	$13
+	mfhi	$12
+	sd	$13,4*8($4)
+	sd	$12,5*8($4)
+
+.L_bn_sqr_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+
+.end	bn_sqr_words_internal
+
+.align	5
+.globl	bn_add_words
+.ent	bn_add_words
+bn_add_words:
+	.set	noreorder
+	bgtz	$7,bn_add_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$2
+.end	bn_add_words
+
+.align	5
+.ent	bn_add_words_internal
+bn_add_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$1,$7,$3
+	beqz	$1,.L_bn_add_words_tail
+
+.L_bn_add_words_loop:
+	ld	$12,0($5)
+	ld	$8,0($6)
+	subu	$7,4
+	ld	$13,8($5)
+	and	$1,$7,$3
+	ld	$14,2*8($5)
+	daddu $6,4*8
+	ld	$15,3*8($5)
+	daddu $4,4*8
+	ld	$9,-3*8($6)
+	daddu $5,4*8
+	ld	$10,-2*8($6)
+	ld	$11,-8($6)
+	daddu	$8,$12
+	sltu	$24,$8,$12
+	daddu	$12,$8,$2
+	sltu	$2,$12,$8
+	sd	$12,-4*8($4)
+	daddu	$2,$24
+
+	daddu	$9,$13
+	sltu	$25,$9,$13
+	daddu	$13,$9,$2
+	sltu	$2,$13,$9
+	sd	$13,-3*8($4)
+	daddu	$2,$25
+
+	daddu	$10,$14
+	sltu	$24,$10,$14
+	daddu	$14,$10,$2
+	sltu	$2,$14,$10
+	sd	$14,-2*8($4)
+	daddu	$2,$24
+	
+	daddu	$11,$15
+	sltu	$25,$11,$15
+	daddu	$15,$11,$2
+	sltu	$2,$15,$11
+	sd	$15,-8($4)
+	
+	.set	noreorder
+	bgtz	$1,.L_bn_add_words_loop
+	daddu	$2,$25
+
+	beqz	$7,.L_bn_add_words_return
+	nop
+
+.L_bn_add_words_tail:
+	.set	reorder
+	ld	$12,0($5)
+	ld	$8,0($6)
+	daddu	$8,$12
+	subu	$7,1
+	sltu	$24,$8,$12
+	daddu	$12,$8,$2
+	sltu	$2,$12,$8
+	sd	$12,0($4)
+	daddu	$2,$24
+	beqz	$7,.L_bn_add_words_return
+
+	ld	$13,8($5)
+	ld	$9,8($6)
+	daddu	$9,$13
+	subu	$7,1
+	sltu	$25,$9,$13
+	daddu	$13,$9,$2
+	sltu	$2,$13,$9
+	sd	$13,8($4)
+	daddu	$2,$25
+	beqz	$7,.L_bn_add_words_return
+
+	ld	$14,2*8($5)
+	ld	$10,2*8($6)
+	daddu	$10,$14
+	sltu	$24,$10,$14
+	daddu	$14,$10,$2
+	sltu	$2,$14,$10
+	sd	$14,2*8($4)
+	daddu	$2,$24
+
+.L_bn_add_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+
+.end	bn_add_words_internal
+
+.align	5
+.globl	bn_sub_words
+.ent	bn_sub_words
+bn_sub_words:
+	.set	noreorder
+	bgtz	$7,bn_sub_words_internal
+	move	$2,$0
+	jr	$31
+	move	$4,$0
+.end	bn_sub_words
+
+.align	5
+.ent	bn_sub_words_internal
+bn_sub_words_internal:
+	.set	reorder
+	li	$3,-4
+	and	$1,$7,$3
+	beqz	$1,.L_bn_sub_words_tail
+
+.L_bn_sub_words_loop:
+	ld	$12,0($5)
+	ld	$8,0($6)
+	subu	$7,4
+	ld	$13,8($5)
+	and	$1,$7,$3
+	ld	$14,2*8($5)
+	daddu $6,4*8
+	ld	$15,3*8($5)
+	daddu $4,4*8
+	ld	$9,-3*8($6)
+	daddu $5,4*8
+	ld	$10,-2*8($6)
+	ld	$11,-8($6)
+	sltu	$24,$12,$8
+	dsubu	$8,$12,$8
+	dsubu	$12,$8,$2
+	sgtu	$2,$12,$8
+	sd	$12,-4*8($4)
+	daddu	$2,$24
+
+	sltu	$25,$13,$9
+	dsubu	$9,$13,$9
+	dsubu	$13,$9,$2
+	sgtu	$2,$13,$9
+	sd	$13,-3*8($4)
+	daddu	$2,$25
+
+
+	sltu	$24,$14,$10
+	dsubu	$10,$14,$10
+	dsubu	$14,$10,$2
+	sgtu	$2,$14,$10
+	sd	$14,-2*8($4)
+	daddu	$2,$24
+
+	sltu	$25,$15,$11
+	dsubu	$11,$15,$11
+	dsubu	$15,$11,$2
+	sgtu	$2,$15,$11
+	sd	$15,-8($4)
+
+	.set	noreorder
+	bgtz	$1,.L_bn_sub_words_loop
+	daddu	$2,$25
+
+	beqz	$7,.L_bn_sub_words_return
+	nop
+
+.L_bn_sub_words_tail:
+	.set	reorder
+	ld	$12,0($5)
+	ld	$8,0($6)
+	subu	$7,1
+	sltu	$24,$12,$8
+	dsubu	$8,$12,$8
+	dsubu	$12,$8,$2
+	sgtu	$2,$12,$8
+	sd	$12,0($4)
+	daddu	$2,$24
+	beqz	$7,.L_bn_sub_words_return
+
+	ld	$13,8($5)
+	subu	$7,1
+	ld	$9,8($6)
+	sltu	$25,$13,$9
+	dsubu	$9,$13,$9
+	dsubu	$13,$9,$2
+	sgtu	$2,$13,$9
+	sd	$13,8($4)
+	daddu	$2,$25
+	beqz	$7,.L_bn_sub_words_return
+
+	ld	$14,2*8($5)
+	ld	$10,2*8($6)
+	sltu	$24,$14,$10
+	dsubu	$10,$14,$10
+	dsubu	$14,$10,$2
+	sgtu	$2,$14,$10
+	sd	$14,2*8($4)
+	daddu	$2,$24
+
+.L_bn_sub_words_return:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_sub_words_internal
+
+.align 5
+.globl	bn_div_3_words
+.ent	bn_div_3_words
+bn_div_3_words:
+	.set	noreorder
+	move	$7,$4		# we know that bn_div_words does not
+				# touch $7, $10, $11 and preserves $6
+				# so that we can save two arguments
+				# and return address in registers
+				# instead of stack:-)
+				
+	ld	$4,($7)
+	move	$10,$5
+	bne	$4,$6,bn_div_3_words_internal
+	ld	$5,-8($7)
+	li	$2,-1
+	jr	$31
+	move	$4,$2
+.end	bn_div_3_words
+
+.align	5
+.ent	bn_div_3_words_internal
+bn_div_3_words_internal:
+	.set	reorder
+	move	$11,$31
+	bal	bn_div_words_internal
+	move	$31,$11
+	dmultu	$10,$2
+	ld	$14,-2*8($7)
+	move	$8,$0
+	mfhi	$13
+	mflo	$12
+	sltu	$24,$13,$5
+.L_bn_div_3_words_inner_loop:
+	bnez	$24,.L_bn_div_3_words_inner_loop_done
+	sgeu	$1,$14,$12
+	seq	$25,$13,$5
+	and	$1,$25
+	sltu	$15,$12,$10
+	daddu	$5,$6
+	dsubu	$13,$15
+	dsubu	$12,$10
+	sltu	$24,$13,$5
+	sltu	$8,$5,$6
+	or	$24,$8
+	.set	noreorder
+	beqz	$1,.L_bn_div_3_words_inner_loop
+	dsubu	$2,1
+	daddu	$2,1
+	.set	reorder
+.L_bn_div_3_words_inner_loop_done:
+	.set	noreorder
+	jr	$31
+	move	$4,$2
+.end	bn_div_3_words_internal
+
+.align	5
+.globl	bn_div_words
+.ent	bn_div_words
+bn_div_words:
+	.set	noreorder
+	bnez	$6,bn_div_words_internal
+	li	$2,-1		# I would rather signal div-by-zero
+				# which can be done with 'break 7'
+	jr	$31
+	move	$4,$2
+.end	bn_div_words
+
+.align	5
+.ent	bn_div_words_internal
+bn_div_words_internal:
+	move	$3,$0
+	bltz	$6,.L_bn_div_words_body
+	move	$25,$3
+	dsll	$6,1
+	bgtz	$6,.-4
+	addu	$25,1
+
+	.set	reorder
+	negu	$13,$25
+	li	$14,-1
+	dsll	$14,$13
+	and	$14,$4
+	dsrl	$1,$5,$13
+	.set	noreorder
+	beqz	$14,.+12
+	nop
+	break	6		# signal overflow
+	.set	reorder
+	dsll	$4,$25
+	dsll	$5,$25
+	or	$4,$1
+.L_bn_div_words_body:
+	dsrl	$3,$6,4*8	# bits
+	sgeu	$1,$4,$6
+	.set	noreorder
+	beqz	$1,.+12
+	nop
+	dsubu	$4,$6
+	.set	reorder
+
+	li	$8,-1
+	dsrl	$9,$4,4*8	# bits
+	dsrl	$8,4*8	# q=0xffffffff
+	beq	$3,$9,.L_bn_div_words_skip_div1
+	ddivu	$0,$4,$3
+	mflo	$8
+.L_bn_div_words_skip_div1:
+	dmultu	$6,$8
+	dsll	$15,$4,4*8	# bits
+	dsrl	$1,$5,4*8	# bits
+	or	$15,$1
+	mflo	$12
+	mfhi	$13
+.L_bn_div_words_inner_loop1:
+	sltu	$14,$15,$12
+	seq	$24,$9,$13
+	sltu	$1,$9,$13
+	and	$14,$24
+	sltu	$2,$12,$6
+	or	$1,$14
+	.set	noreorder
+	beqz	$1,.L_bn_div_words_inner_loop1_done
+	dsubu	$13,$2
+	dsubu	$12,$6
+	b	.L_bn_div_words_inner_loop1
+	dsubu	$8,1
+	.set	reorder
+.L_bn_div_words_inner_loop1_done:
+
+	dsll	$5,4*8	# bits
+	dsubu	$4,$15,$12
+	dsll	$2,$8,4*8	# bits
+
+	li	$8,-1
+	dsrl	$9,$4,4*8	# bits
+	dsrl	$8,4*8	# q=0xffffffff
+	beq	$3,$9,.L_bn_div_words_skip_div2
+	ddivu	$0,$4,$3
+	mflo	$8
+.L_bn_div_words_skip_div2:
+	dmultu	$6,$8
+	dsll	$15,$4,4*8	# bits
+	dsrl	$1,$5,4*8	# bits
+	or	$15,$1
+	mflo	$12
+	mfhi	$13
+.L_bn_div_words_inner_loop2:
+	sltu	$14,$15,$12
+	seq	$24,$9,$13
+	sltu	$1,$9,$13
+	and	$14,$24
+	sltu	$3,$12,$6
+	or	$1,$14
+	.set	noreorder
+	beqz	$1,.L_bn_div_words_inner_loop2_done
+	dsubu	$13,$3
+	dsubu	$12,$6
+	b	.L_bn_div_words_inner_loop2
+	dsubu	$8,1
+	.set	reorder
+.L_bn_div_words_inner_loop2_done:
+
+	dsubu	$4,$15,$12
+	or	$2,$8
+	dsrl	$3,$4,$25	# $3 contains remainder if anybody wants it
+	dsrl	$6,$25		# restore $6
+
+	.set	noreorder
+	move	$5,$3
+	jr	$31
+	move	$4,$2
+.end	bn_div_words_internal
+
+.align	5
+.globl	bn_mul_comba8
+.ent	bn_mul_comba8
+bn_mul_comba8:
+	.set	noreorder
+	.frame	$29,6*8,$31
+	.mask	0x003f0000,-8
+	dsubu $29,6*8
+	sd	$21,5*8($29)
+	sd	$20,4*8($29)
+	sd	$19,3*8($29)
+	sd	$18,2*8($29)
+	sd	$17,1*8($29)
+	sd	$16,0*8($29)
+
+	.set	reorder
+	ld	$12,0($5)	# If compiled with -mips3 option on
+				# R5000 box assembler barks on this
+				# 1ine with "should not have mult/div
+				# as last instruction in bb (R10K
+				# bug)" warning. If anybody out there
+				# has a clue about how to circumvent
+				# this do send me a note.
+				#		
+
+	ld	$8,0($6)
+	ld	$13,8($5)
+	ld	$14,2*8($5)
+	dmultu	$12,$8		# mul_add_c(a[0],b[0],c1,c2,c3);
+	ld	$15,3*8($5)
+	ld	$9,8($6)
+	ld	$10,2*8($6)
+	ld	$11,3*8($6)
+	mflo	$2
+	mfhi	$3
+
+	ld	$16,4*8($5)
+	ld	$18,5*8($5)
+	dmultu	$12,$9		# mul_add_c(a[0],b[1],c2,c3,c1);
+	ld	$20,6*8($5)
+	ld	$5,7*8($5)
+	ld	$17,4*8($6)
+	ld	$19,5*8($6)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$13,$8		# mul_add_c(a[1],b[0],c2,c3,c1);
+	daddu	$7,$25,$1
+	ld	$21,6*8($6)
+	ld	$6,7*8($6)
+	sd	$2,0($4)	# r[0]=c1;
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$8		# mul_add_c(a[2],b[0],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	sd	$3,8($4)	# r[1]=c2;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$13,$9		# mul_add_c(a[1],b[1],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$12,$10		# mul_add_c(a[0],b[2],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$12,$11		# mul_add_c(a[0],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,2*8($4)	# r[2]=c3;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$13,$10		# mul_add_c(a[1],b[2],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$14,$9		# mul_add_c(a[2],b[1],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$15,$8		# mul_add_c(a[3],b[0],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$16,$8		# mul_add_c(a[4],b[0],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,3*8($4)	# r[3]=c1;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$15,$9		# mul_add_c(a[3],b[1],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$14,$10		# mul_add_c(a[2],b[2],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$13,$11		# mul_add_c(a[1],b[3],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$12,$17		# mul_add_c(a[0],b[4],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$12,$19		# mul_add_c(a[0],b[5],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,4*8($4)	# r[4]=c2;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$13,$17		# mul_add_c(a[1],b[4],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$14,$11		# mul_add_c(a[2],b[3],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$15,$10		# mul_add_c(a[3],b[2],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$16,$9		# mul_add_c(a[4],b[1],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$18,$8		# mul_add_c(a[5],b[0],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$20,$8		# mul_add_c(a[6],b[0],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,5*8($4)	# r[5]=c3;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$18,$9		# mul_add_c(a[5],b[1],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$16,$10		# mul_add_c(a[4],b[2],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$15,$11		# mul_add_c(a[3],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$14,$17		# mul_add_c(a[2],b[4],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$13,$19		# mul_add_c(a[1],b[5],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$12,$21		# mul_add_c(a[0],b[6],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$12,$6		# mul_add_c(a[0],b[7],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,6*8($4)	# r[6]=c1;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$13,$21		# mul_add_c(a[1],b[6],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$14,$19		# mul_add_c(a[2],b[5],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$15,$17		# mul_add_c(a[3],b[4],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$16,$11		# mul_add_c(a[4],b[3],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$18,$10		# mul_add_c(a[5],b[2],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$20,$9		# mul_add_c(a[6],b[1],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$5,$8		# mul_add_c(a[7],b[0],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$5,$9		# mul_add_c(a[7],b[1],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,7*8($4)	# r[7]=c2;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$20,$10		# mul_add_c(a[6],b[2],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$18,$11		# mul_add_c(a[5],b[3],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$16,$17		# mul_add_c(a[4],b[4],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$15,$19		# mul_add_c(a[3],b[5],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$14,$21		# mul_add_c(a[2],b[6],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$13,$6		# mul_add_c(a[1],b[7],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$14,$6		# mul_add_c(a[2],b[7],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,8*8($4)	# r[8]=c3;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$15,$21		# mul_add_c(a[3],b[6],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$16,$19		# mul_add_c(a[4],b[5],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$18,$17		# mul_add_c(a[5],b[4],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$20,$11		# mul_add_c(a[6],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$5,$10		# mul_add_c(a[7],b[2],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$5,$11		# mul_add_c(a[7],b[3],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,9*8($4)	# r[9]=c1;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$20,$17		# mul_add_c(a[6],b[4],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$18,$19		# mul_add_c(a[5],b[5],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$16,$21		# mul_add_c(a[4],b[6],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$15,$6		# mul_add_c(a[3],b[7],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$16,$6		# mul_add_c(a[4],b[7],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,10*8($4)	# r[10]=c2;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$18,$21		# mul_add_c(a[5],b[6],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$20,$19		# mul_add_c(a[6],b[5],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$5,$17		# mul_add_c(a[7],b[4],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$5,$19		# mul_add_c(a[7],b[5],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,11*8($4)	# r[11]=c3;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$20,$21		# mul_add_c(a[6],b[6],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$18,$6		# mul_add_c(a[5],b[7],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$20,$6		# mul_add_c(a[6],b[7],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,12*8($4)	# r[12]=c1;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$5,$21		# mul_add_c(a[7],b[6],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$5,$6		# mul_add_c(a[7],b[7],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,13*8($4)	# r[13]=c2;
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	daddu	$25,$1
+	daddu	$2,$25
+	sd	$7,14*8($4)	# r[14]=c3;
+	sd	$2,15*8($4)	# r[15]=c1;
+
+	.set	noreorder
+	ld	$21,5*8($29)
+	ld	$20,4*8($29)
+	ld	$19,3*8($29)
+	ld	$18,2*8($29)
+	ld	$17,1*8($29)
+	ld	$16,0*8($29)
+	jr	$31
+	daddu $29,6*8
+.end	bn_mul_comba8
+
+.align	5
+.globl	bn_mul_comba4
+.ent	bn_mul_comba4
+bn_mul_comba4:
+	.set	reorder
+	ld	$12,0($5)
+	ld	$8,0($6)
+	ld	$13,8($5)
+	ld	$14,2*8($5)
+	dmultu	$12,$8		# mul_add_c(a[0],b[0],c1,c2,c3);
+	ld	$15,3*8($5)
+	ld	$9,8($6)
+	ld	$10,2*8($6)
+	ld	$11,3*8($6)
+	mflo	$2
+	mfhi	$3
+	sd	$2,0($4)
+
+	dmultu	$12,$9		# mul_add_c(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$13,$8		# mul_add_c(a[1],b[0],c2,c3,c1);
+	daddu	$7,$25,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$8		# mul_add_c(a[2],b[0],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	sd	$3,8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$13,$9		# mul_add_c(a[1],b[1],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$12,$10		# mul_add_c(a[0],b[2],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$12,$11		# mul_add_c(a[0],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,2*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$13,$10		# mul_add_c(a[1],b[2],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$7,$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$14,$9		# mul_add_c(a[2],b[1],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	dmultu	$15,$8		# mul_add_c(a[3],b[0],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$15,$9		# mul_add_c(a[3],b[1],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,3*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$14,$10		# mul_add_c(a[2],b[2],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$2,$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	dmultu	$13,$11		# mul_add_c(a[1],b[3],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$11		# mul_add_c(a[2],b[3],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,4*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	dmultu	$15,$10		# mul_add_c(a[3],b[2],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$3,$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$15,$11		# mul_add_c(a[3],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,5*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	daddu	$25,$1
+	daddu	$3,$25
+	sd	$2,6*8($4)
+	sd	$3,7*8($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_mul_comba4
+
+.align	5
+.globl	bn_sqr_comba8
+.ent	bn_sqr_comba8
+bn_sqr_comba8:
+	.set	reorder
+	ld	$12,0($5)
+	ld	$13,8($5)
+	ld	$14,2*8($5)
+	ld	$15,3*8($5)
+
+	dmultu	$12,$12		# mul_add_c(a[0],b[0],c1,c2,c3);
+	ld	$8,4*8($5)
+	ld	$9,5*8($5)
+	ld	$10,6*8($5)
+	ld	$11,7*8($5)
+	mflo	$2
+	mfhi	$3
+	sd	$2,0($4)
+
+	dmultu	$12,$13		# mul_add_c2(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	slt	$2,$25,$0
+	dsll	$25,1
+	 dmultu	$14,$12		# mul_add_c2(a[2],b[0],c3,c1,c2);
+	slt	$6,$24,$0
+	daddu	$25,$6
+	dsll	$24,1
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	daddu	$7,$25,$1
+	sd	$3,8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$13,$13			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$12,$15		# mul_add_c2(a[0],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,2*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$13,$14			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$7,$3,$1
+	daddu	$3,$25
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$8,$12			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	sd	$2,3*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$15,$13			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$2,$7,$1
+	daddu	$7,$25
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$14			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$1,$7,$1
+	daddu	$7,$25
+	daddu	$2,$1
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$12,$9		# mul_add_c2(a[0],b[5],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,4*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$13,$8			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$14,$15			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$1,$2,$1
+	daddu	$2,$25
+	daddu	$3,$1
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$10,$12			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$1,$2,$1
+	daddu	$2,$25
+	daddu	$3,$1
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	sd	$7,5*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$9,$13			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$7,$3,$1
+	daddu	$3,$25
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$8,$14			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$15,$15			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$12,$11		# mul_add_c2(a[0],b[7],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,6*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$13,$10			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$2,$7,$1
+	daddu	$7,$25
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$9			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$1,$7,$1
+	daddu	$7,$25
+	daddu	$2,$1
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$15,$8			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$1,$7,$1
+	daddu	$7,$25
+	daddu	$2,$1
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$11,$13			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$1,$7,$1
+	daddu	$7,$25
+	daddu	$2,$1
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	sd	$3,7*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$10,$14			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$9,$15			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$1,$2,$1
+	daddu	$2,$25
+	daddu	$3,$1
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$8,$8			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$1,$2,$1
+	daddu	$2,$25
+	daddu	$3,$1
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$14,$11		# mul_add_c2(a[2],b[7],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,8*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$15,$10			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$7,$3,$1
+	daddu	$3,$25
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$8,$9			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$11,$15			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	sd	$2,9*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$10,$8			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$2,$7,$1
+	daddu	$7,$25
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$9,$9			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$1,$7,$1
+	daddu	$7,$25
+	daddu	$2,$1
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$8,$11		# mul_add_c2(a[4],b[7],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,10*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$9,$10			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$11,$9			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$1,$2,$1
+	daddu	$2,$25
+	daddu	$3,$1
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	sd	$7,11*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$10,$10			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$7,$3,$1
+	daddu	$3,$25
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$10,$11		# mul_add_c2(a[6],b[7],c2,c3,c1);
+	daddu	$25,$1
+	daddu	$3,$25
+	sltu	$1,$3,$25
+	daddu	$7,$1
+	sd	$2,12*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$11,$11			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$2,$7,$1
+	daddu	$7,$25
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	sd	$3,13*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	daddu	$25,$1
+	daddu	$2,$25
+	sd	$7,14*8($4)
+	sd	$2,15*8($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_sqr_comba8
+
+.align	5
+.globl	bn_sqr_comba4
+.ent	bn_sqr_comba4
+bn_sqr_comba4:
+	.set	reorder
+	ld	$12,0($5)
+	ld	$13,8($5)
+	dmultu	$12,$12		# mul_add_c(a[0],b[0],c1,c2,c3);
+	ld	$14,2*8($5)
+	ld	$15,3*8($5)
+	mflo	$2
+	mfhi	$3
+	sd	$2,0($4)
+
+	dmultu	$12,$13		# mul_add_c2(a[0],b[1],c2,c3,c1);
+	mflo	$24
+	mfhi	$25
+	slt	$2,$25,$0
+	dsll	$25,1
+	 dmultu	$14,$12		# mul_add_c2(a[2],b[0],c3,c1,c2);
+	slt	$6,$24,$0
+	daddu	$25,$6
+	dsll	$24,1
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	daddu	$7,$25,$1
+	sd	$3,8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$13,$13			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$12,$15		# mul_add_c2(a[0],b[3],c1,c2,c3);
+	daddu	$25,$1
+	daddu	$2,$25
+	sltu	$1,$2,$25
+	daddu	$3,$1
+	sd	$7,2*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$13,$14			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$7,$3,$1
+	daddu	$3,$25
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	 dmultu	$15,$13			# forward multiplication
+	daddu	$2,$24
+	daddu	$1,$25
+	sltu	$24,$2,$24
+	daddu	$3,$1
+	daddu	$25,$24
+	sltu	$1,$3,$1
+	daddu	$3,$25
+	daddu	$7,$1
+	sltu	$25,$3,$25
+	daddu	$7,$25
+	sd	$2,3*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$14			# forward multiplication
+	daddu	$3,$24
+	daddu	$1,$25
+	sltu	$24,$3,$24
+	daddu	$7,$1
+	daddu	$25,$24
+	sltu	$2,$7,$1
+	daddu	$7,$25
+	sltu	$25,$7,$25
+	daddu	$2,$25
+	mflo	$24
+	mfhi	$25
+	daddu	$3,$24
+	sltu	$1,$3,$24
+	 dmultu	$14,$15		# mul_add_c2(a[2],b[3],c3,c1,c2);
+	daddu	$25,$1
+	daddu	$7,$25
+	sltu	$1,$7,$25
+	daddu	$2,$1
+	sd	$3,4*8($4)
+	mflo	$24
+	mfhi	$25
+	daddu	$7,$24
+	sltu	$1,$7,$24
+	 dmultu	$15,$15			# forward multiplication
+	daddu	$7,$24
+	daddu	$1,$25
+	sltu	$24,$7,$24
+	daddu	$2,$1
+	daddu	$25,$24
+	sltu	$3,$2,$1
+	daddu	$2,$25
+	sltu	$25,$2,$25
+	daddu	$3,$25
+	sd	$7,5*8($4)
+
+	mflo	$24
+	mfhi	$25
+	daddu	$2,$24
+	sltu	$1,$2,$24
+	daddu	$25,$1
+	daddu	$3,$25
+	sd	$2,6*8($4)
+	sd	$3,7*8($4)
+
+	.set	noreorder
+	jr	$31
+	nop
+.end	bn_sqr_comba4
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/bn_add.c b/crypto/bn/bn_add.c
new file mode 100644
index 0000000..86768a3
--- /dev/null
+++ b/crypto/bn/bn_add.c
@@ -0,0 +1,341 @@
+/* $OpenBSD: bn_add.c,v 1.26 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bn_arch.h"
+#include "bn_local.h"
+#include "bn_internal.h"
+
+/*
+ * bn_add_words() computes (carry:r[i]) = a[i] + b[i] + carry, where a and b
+ * are both arrays of words. Any carry resulting from the addition is returned.
+ */
+#ifndef HAVE_BN_ADD_WORDS
+BN_ULONG
+bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
+{
+	BN_ULONG carry = 0;
+
+	assert(n >= 0);
+	if (n <= 0)
+		return 0;
+
+	while (n & ~3) {
+		bn_qwaddqw(a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0],
+		    carry, &carry, &r[3], &r[2], &r[1], &r[0]);
+		a += 4;
+		b += 4;
+		r += 4;
+		n -= 4;
+	}
+	while (n) {
+		bn_addw_addw(a[0], b[0], carry, &carry, &r[0]);
+		a++;
+		b++;
+		r++;
+		n--;
+	}
+	return carry;
+}
+#endif
+
+/*
+ * bn_add() computes (carry:r[i]) = a[i] + b[i] + carry, where a and b are both
+ * arrays of words (r may be the same as a or b). The length of a and b may
+ * differ, while r must be at least max(a_len, b_len) in length. Any carry
+ * resulting from the addition is returned.
+ */
+#ifndef HAVE_BN_ADD
+BN_ULONG
+bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
+    int b_len)
+{
+	int min_len, diff_len;
+	BN_ULONG carry = 0;
+
+	if ((min_len = a_len) > b_len)
+		min_len = b_len;
+
+	diff_len = a_len - b_len;
+
+	carry = bn_add_words(r, a, b, min_len);
+
+	a += min_len;
+	b += min_len;
+	r += min_len;
+
+	/* XXX - consider doing four at a time to match bn_add_words(). */
+	while (diff_len < 0) {
+		/* Compute r[0] = 0 + b[0] + carry. */
+		bn_addw(b[0], carry, &carry, &r[0]);
+		diff_len++;
+		b++;
+		r++;
+	}
+
+	/* XXX - consider doing four at a time to match bn_add_words(). */
+	while (diff_len > 0) {
+		/* Compute r[0] = a[0] + 0 + carry. */
+		bn_addw(a[0], carry, &carry, &r[0]);
+		diff_len--;
+		a++;
+		r++;
+	}
+
+	return carry;
+}
+#endif
+
+/*
+ * bn_sub_words() computes (borrow:r[i]) = a[i] - b[i] - borrow, where a and b
+ * are both arrays of words. Any borrow resulting from the subtraction is
+ * returned.
+ */
+#ifndef HAVE_BN_SUB_WORDS
+BN_ULONG
+bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
+{
+	BN_ULONG borrow = 0;
+
+	assert(n >= 0);
+	if (n <= 0)
+		return 0;
+
+	while (n & ~3) {
+		bn_qwsubqw(a[3], a[2], a[1], a[0], b[3], b[2], b[1], b[0],
+		    borrow, &borrow, &r[3], &r[2], &r[1], &r[0]);
+		a += 4;
+		b += 4;
+		r += 4;
+		n -= 4;
+	}
+	while (n) {
+		bn_subw_subw(a[0], b[0], borrow, &borrow, &r[0]);
+		a++;
+		b++;
+		r++;
+		n--;
+	}
+	return borrow;
+}
+#endif
+
+/*
+ * bn_sub() computes (borrow:r[i]) = a[i] - b[i] - borrow, where a and b are both
+ * arrays of words (r may be the same as a or b). The length of a and b may
+ * differ, while r must be at least max(a_len, b_len) in length. Any borrow
+ * resulting from the subtraction is returned.
+ */
+#ifndef HAVE_BN_SUB
+BN_ULONG
+bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len, const BN_ULONG *b,
+    int b_len)
+{
+	int min_len, diff_len;
+	BN_ULONG borrow = 0;
+
+	if ((min_len = a_len) > b_len)
+		min_len = b_len;
+
+	diff_len = a_len - b_len;
+
+	borrow = bn_sub_words(r, a, b, min_len);
+
+	a += min_len;
+	b += min_len;
+	r += min_len;
+
+	/* XXX - consider doing four at a time to match bn_sub_words. */
+	while (diff_len < 0) {
+		/* Compute r[0] = 0 - b[0] - borrow. */
+		bn_subw(0 - b[0], borrow, &borrow, &r[0]);
+		diff_len++;
+		b++;
+		r++;
+	}
+
+	/* XXX - consider doing four at a time to match bn_sub_words. */
+	while (diff_len > 0) {
+		/* Compute r[0] = a[0] - 0 - borrow. */
+		bn_subw(a[0], borrow, &borrow, &r[0]);
+		diff_len--;
+		a++;
+		r++;
+	}
+
+	return borrow;
+}
+#endif
+
+int
+BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+	BN_ULONG carry;
+	int rn;
+
+	if ((rn = a->top) < b->top)
+		rn = b->top;
+	if (rn == INT_MAX)
+		return 0;
+	if (!bn_wexpand(r, rn + 1))
+		return 0;
+
+	carry = bn_add(r->d, rn, a->d, a->top, b->d, b->top);
+	r->d[rn] = carry;
+
+	r->top = rn + (carry & 1);
+	r->neg = 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(BN_uadd);
+
+int
+BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+	BN_ULONG borrow;
+	int rn;
+
+	if (a->top < b->top) {
+		BNerror(BN_R_ARG2_LT_ARG3);
+		return 0;
+	}
+	rn = a->top;
+
+	if (!bn_wexpand(r, rn))
+		return 0;
+
+	borrow = bn_sub(r->d, rn, a->d, a->top, b->d, b->top);
+	if (borrow > 0) {
+		BNerror(BN_R_ARG2_LT_ARG3);
+		return 0;
+	}
+
+	r->top = rn;
+	r->neg = 0;
+
+	bn_correct_top(r);
+
+	return 1;
+}
+LCRYPTO_ALIAS(BN_usub);
+
+int
+BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+	int ret, r_neg;
+
+	if (a->neg == b->neg) {
+		r_neg = a->neg;
+		ret = BN_uadd(r, a, b);
+	} else {
+		int cmp = BN_ucmp(a, b);
+
+		if (cmp > 0) {
+			r_neg = a->neg;
+			ret = BN_usub(r, a, b);
+		} else if (cmp < 0) {
+			r_neg = b->neg;
+			ret = BN_usub(r, b, a);
+		} else {
+			r_neg = 0;
+			BN_zero(r);
+			ret = 1;
+		}
+	}
+
+	BN_set_negative(r, r_neg);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_add);
+
+int
+BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+	int ret, r_neg;
+
+	if (a->neg != b->neg) {
+		r_neg = a->neg;
+		ret = BN_uadd(r, a, b);
+	} else {
+		int cmp = BN_ucmp(a, b);
+
+		if (cmp > 0) {
+			r_neg = a->neg;
+			ret = BN_usub(r, a, b);
+		} else if (cmp < 0) {
+			r_neg = !b->neg;
+			ret = BN_usub(r, b, a);
+		} else {
+			r_neg = 0;
+			BN_zero(r);
+			ret = 1;
+		}
+	}
+
+	BN_set_negative(r, r_neg);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_sub);
diff --git a/crypto/bn/bn_bpsw.c b/crypto/bn/bn_bpsw.c
new file mode 100644
index 0000000..14f2800
--- /dev/null
+++ b/crypto/bn/bn_bpsw.c
@@ -0,0 +1,534 @@
+/*	$OpenBSD: bn_bpsw.c,v 1.11 2023/08/03 18:53:55 tb Exp $ */
+/*
+ * Copyright (c) 2022 Martin Grenouilloux 
+ * Copyright (c) 2022 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bn_local.h"
+#include "bn_prime.h"
+
+/*
+ * For an odd n compute a / 2 (mod n). If a is even, we can do a plain
+ * division, otherwise calculate (a + n) / 2. Then reduce (mod n).
+ */
+
+static int
+bn_div_by_two_mod_odd_n(BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+{
+	if (!BN_is_odd(n))
+		return 0;
+
+	if (BN_is_odd(a)) {
+		if (!BN_add(a, a, n))
+			return 0;
+	}
+	if (!BN_rshift1(a, a))
+		return 0;
+	if (!BN_mod_ct(a, a, n, ctx))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * Given the next binary digit of k and the current Lucas terms U and V, this
+ * helper computes the next terms in the Lucas sequence defined as follows:
+ *
+ *   U' = U * V                  (mod n)
+ *   V' = (V^2 + D * U^2) / 2    (mod n)
+ *
+ * If digit == 0, bn_lucas_step() returns U' and V'. If digit == 1, it returns
+ *
+ *   U'' = (U' + V') / 2         (mod n)
+ *   V'' = (V' + D * U') / 2     (mod n)
+ *
+ * Compare with FIPS 186-4, Appendix C.3.3, step 6.
+ */
+
+static int
+bn_lucas_step(BIGNUM *U, BIGNUM *V, int digit, const BIGNUM *D,
+    const BIGNUM *n, BN_CTX *ctx)
+{
+	BIGNUM *tmp;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Calculate D * U^2 before computing U'. */
+	if (!BN_sqr(tmp, U, ctx))
+		goto err;
+	if (!BN_mul(tmp, D, tmp, ctx))
+		goto err;
+
+	/* U' = U * V (mod n). */
+	if (!BN_mod_mul(U, U, V, n, ctx))
+		goto err;
+
+	/* V' = (V^2 + D * U^2) / 2 (mod n). */
+	if (!BN_sqr(V, V, ctx))
+		goto err;
+	if (!BN_add(V, V, tmp))
+		goto err;
+	if (!bn_div_by_two_mod_odd_n(V, n, ctx))
+		goto err;
+
+	if (digit == 1) {
+		/* Calculate D * U' before computing U''. */
+		if (!BN_mul(tmp, D, U, ctx))
+			goto err;
+
+		/* U'' = (U' + V') / 2 (mod n). */
+		if (!BN_add(U, U, V))
+			goto err;
+		if (!bn_div_by_two_mod_odd_n(U, n, ctx))
+			goto err;
+
+		/* V'' = (V' + D * U') / 2 (mod n). */
+		if (!BN_add(V, V, tmp))
+			goto err;
+		if (!bn_div_by_two_mod_odd_n(V, n, ctx))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Compute the Lucas terms U_k, V_k, see FIPS 186-4, Appendix C.3.3, steps 4-6.
+ */
+
+static int
+bn_lucas(BIGNUM *U, BIGNUM *V, const BIGNUM *k, const BIGNUM *D,
+    const BIGNUM *n, BN_CTX *ctx)
+{
+	int digit, i;
+	int ret = 0;
+
+	if (!BN_one(U))
+		goto err;
+	if (!BN_one(V))
+		goto err;
+
+	/*
+	 * Iterate over the digits of k from MSB to LSB. Start at digit 2
+	 * since the first digit is dealt with by setting U = 1 and V = 1.
+	 */
+
+	for (i = BN_num_bits(k) - 2; i >= 0; i--) {
+		digit = BN_is_bit_set(k, i);
+
+		if (!bn_lucas_step(U, V, digit, D, n, ctx))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+/*
+ * This is a stronger variant of the Lucas test in FIPS 186-4, Appendix C.3.3.
+ * Every strong Lucas pseudoprime n is also a Lucas pseudoprime since
+ * U_{n+1} == 0 follows from U_k == 0 or V_{k * 2^r} == 0 for 0 <= r < s.
+ */
+
+static int
+bn_strong_lucas_test(int *is_pseudoprime, const BIGNUM *n, const BIGNUM *D,
+    BN_CTX *ctx)
+{
+	BIGNUM *k, *U, *V;
+	int r, s;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((U = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((V = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Factorize n + 1 = k * 2^s with odd k: shift away the s trailing ones
+	 * of n and set the lowest bit of the resulting number k.
+	 */
+
+	s = 0;
+	while (BN_is_bit_set(n, s))
+		s++;
+	if (!BN_rshift(k, n, s))
+		goto err;
+	if (!BN_set_bit(k, 0))
+		goto err;
+
+	/*
+	 * Calculate the Lucas terms U_k and V_k. If either of them is zero,
+	 * then n is a strong Lucas pseudoprime.
+	 */
+
+	if (!bn_lucas(U, V, k, D, n, ctx))
+		goto err;
+
+	if (BN_is_zero(U) || BN_is_zero(V)) {
+		*is_pseudoprime = 1;
+		goto done;
+	}
+
+	/*
+	 * Calculate the Lucas terms U_{k * 2^r}, V_{k * 2^r} for 1 <= r < s.
+	 * If any V_{k * 2^r} is zero then n is a strong Lucas pseudoprime.
+	 */
+
+	for (r = 1; r < s; r++) {
+		if (!bn_lucas_step(U, V, 0, D, n, ctx))
+			goto err;
+
+		if (BN_is_zero(V)) {
+			*is_pseudoprime = 1;
+			goto done;
+		}
+	}
+
+	/*
+	 * If we got here, n is definitely composite.
+	 */
+
+	*is_pseudoprime = 0;
+
+ done:
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Test n for primality using the strong Lucas test with Selfridge's Method A.
+ * Returns 1 if n is prime or a strong Lucas-Selfridge pseudoprime.
+ * If it returns 0 then n is definitely composite.
+ */
+
+static int
+bn_strong_lucas_selfridge(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx)
+{
+	BIGNUM *D, *two;
+	int is_perfect_square, jacobi_symbol, sign;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	/* If n is a perfect square, it is composite. */
+	if (!bn_is_perfect_square(&is_perfect_square, n, ctx))
+		goto err;
+	if (is_perfect_square) {
+		*is_pseudoprime = 0;
+		goto done;
+	}
+
+	/*
+	 * Find the first D in the Selfridge sequence 5, -7, 9, -11, 13, ...
+	 * such that the Jacobi symbol (D/n) is -1.
+	 */
+
+	if ((D = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((two = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	sign = 1;
+	if (!BN_set_word(D, 5))
+		goto err;
+	if (!BN_set_word(two, 2))
+		goto err;
+
+	while (1) {
+		/* For odd n the Kronecker symbol computes the Jacobi symbol. */
+		if ((jacobi_symbol = BN_kronecker(D, n, ctx)) == -2)
+			goto err;
+
+		/* We found the value for D. */
+		if (jacobi_symbol == -1)
+			break;
+
+		/* n and D have prime factors in common. */
+		if (jacobi_symbol == 0) {
+			*is_pseudoprime = 0;
+			goto done;
+		}
+
+		sign = -sign;
+		if (!BN_uadd(D, D, two))
+			goto err;
+		BN_set_negative(D, sign == -1);
+	}
+
+	if (!bn_strong_lucas_test(is_pseudoprime, n, D, ctx))
+		goto err;
+
+ done:
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Fermat criterion in Miller-Rabin test.
+ *
+ * Check whether 1 < base < n - 1 witnesses that n is composite. For prime n:
+ *
+ *  * Fermat's little theorem: base^(n-1) = 1 (mod n).
+ *  * The only square roots of 1 (mod n) are 1 and -1.
+ *
+ * Calculate base^((n-1)/2) by writing n - 1 = k * 2^s with odd k. Iteratively
+ * compute power = (base^k)^(2^(s-1)) by successive squaring of base^k.
+ *
+ * If power ever reaches -1, base^(n-1) is equal to 1 and n is a pseudoprime
+ * for base. If power reaches 1 before -1 during successive squaring, we have
+ * an unexpected square root of 1 and n is composite. Otherwise base^(n-1) != 1,
+ * and n is composite.
+ */
+
+static int
+bn_fermat(int *is_pseudoprime, const BIGNUM *n, const BIGNUM *n_minus_one,
+    const BIGNUM *k, int s, const BIGNUM *base, BN_CTX *ctx, BN_MONT_CTX *mctx)
+{
+	BIGNUM *power;
+	int ret = 0;
+	int i;
+
+	BN_CTX_start(ctx);
+
+	if ((power = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Sanity check: ensure that 1 < base < n - 1. */
+	if (BN_cmp(base, BN_value_one()) <= 0 || BN_cmp(base, n_minus_one) >= 0)
+		goto err;
+
+	if (!BN_mod_exp_mont_ct(power, base, k, n, ctx, mctx))
+		goto err;
+
+	if (BN_is_one(power) || BN_cmp(power, n_minus_one) == 0) {
+		*is_pseudoprime = 1;
+		goto done;
+	}
+
+	/* Loop invariant: power is neither 1 nor -1 (mod n). */
+	for (i = 1; i < s; i++) {
+		if (!BN_mod_sqr(power, power, n, ctx))
+			goto err;
+
+		/* n is a pseudoprime for base. */
+		if (BN_cmp(power, n_minus_one) == 0) {
+			*is_pseudoprime = 1;
+			goto done;
+		}
+
+		/* n is composite: there's a square root of unity != 1 or -1. */
+		if (BN_is_one(power)) {
+			*is_pseudoprime = 0;
+			goto done;
+		}
+	}
+
+	/*
+	 * If we get here, n is definitely composite: base^(n-1) != 1.
+	 */
+
+	*is_pseudoprime = 0;
+
+ done:
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Miller-Rabin primality test for base 2 and for |rounds| of random bases.
+ * On success: is_pseudoprime == 0 implies that n is composite.
+ */
+
+static int
+bn_miller_rabin(int *is_pseudoprime, const BIGNUM *n, BN_CTX *ctx,
+    size_t rounds)
+{
+	BN_MONT_CTX *mctx = NULL;
+	BIGNUM *base, *k, *n_minus_one;
+	size_t i;
+	int s;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((base = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((n_minus_one = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (BN_is_word(n, 2) || BN_is_word(n, 3)) {
+		*is_pseudoprime = 1;
+		goto done;
+	}
+
+	if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
+		*is_pseudoprime = 0;
+		goto done;
+	}
+
+	if (!BN_sub(n_minus_one, n, BN_value_one()))
+		goto err;
+
+	/*
+	 * Factorize n - 1 = k * 2^s.
+	 */
+
+	s = 0;
+	while (!BN_is_bit_set(n_minus_one, s))
+		s++;
+	if (!BN_rshift(k, n_minus_one, s))
+		goto err;
+
+	/*
+	 * Montgomery setup for n.
+	 */
+
+	if ((mctx = BN_MONT_CTX_new()) == NULL)
+		goto err;
+
+	if (!BN_MONT_CTX_set(mctx, n, ctx))
+		goto err;
+
+	/*
+	 * Perform a Miller-Rabin test for base 2 as required by BPSW.
+	 */
+
+	if (!BN_set_word(base, 2))
+		goto err;
+
+	if (!bn_fermat(is_pseudoprime, n, n_minus_one, k, s, base, ctx, mctx))
+		goto err;
+	if (!*is_pseudoprime)
+		goto done;
+
+	/*
+	 * Perform Miller-Rabin tests with random 3 <= base < n - 1 to reduce
+	 * risk of false positives in BPSW.
+	 */
+
+	for (i = 0; i < rounds; i++) {
+		if (!bn_rand_interval(base, 3, n_minus_one))
+			goto err;
+
+		if (!bn_fermat(is_pseudoprime, n, n_minus_one, k, s, base, ctx,
+		    mctx))
+			goto err;
+		if (!*is_pseudoprime)
+			goto done;
+	}
+
+	/*
+	 * If we got here, we have a Miller-Rabin pseudoprime.
+	 */
+
+	*is_pseudoprime = 1;
+
+ done:
+	ret = 1;
+
+ err:
+	BN_MONT_CTX_free(mctx);
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * The Baillie-Pomerance-Selfridge-Wagstaff algorithm combines a Miller-Rabin
+ * test for base 2 with a Strong Lucas pseudoprime test.
+ */
+
+int
+bn_is_prime_bpsw(int *is_pseudoprime, const BIGNUM *n, BN_CTX *in_ctx,
+    size_t rounds)
+{
+	BN_CTX *ctx = NULL;
+	BN_ULONG mod;
+	int i;
+	int ret = 0;
+
+	if (BN_is_word(n, 2)) {
+		*is_pseudoprime = 1;
+		goto done;
+	}
+
+	if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
+		*is_pseudoprime = 0;
+		goto done;
+	}
+
+	/* Trial divisions with the first 2048 primes. */
+	for (i = 0; i < NUMPRIMES; i++) {
+		if ((mod = BN_mod_word(n, primes[i])) == (BN_ULONG)-1)
+			goto err;
+		if (mod == 0) {
+			*is_pseudoprime = BN_is_word(n, primes[i]);
+			goto done;
+		}
+	}
+
+	if ((ctx = in_ctx) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (!bn_miller_rabin(is_pseudoprime, n, ctx, rounds))
+		goto err;
+	if (!*is_pseudoprime)
+		goto done;
+
+	if (!bn_strong_lucas_selfridge(is_pseudoprime, n, ctx))
+		goto err;
+
+ done:
+	ret = 1;
+
+ err:
+	if (ctx != in_ctx)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
diff --git a/crypto/bn/bn_const.c b/crypto/bn/bn_const.c
new file mode 100644
index 0000000..bf684c8
--- /dev/null
+++ b/crypto/bn/bn_const.c
@@ -0,0 +1,433 @@
+/* $OpenBSD: bn_const.c,v 1.8 2023/07/28 10:07:30 tb Exp $ */
+/* Insert boilerplate */
+
+#include 
+
+/*
+ * "First Oakley Default Group" from RFC2409, section 6.1.
+ *
+ * The prime is: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
+ *
+ * RFC2409 specifies a generator of 2.
+ * RFC2412 specifies a generator of of 22.
+ */
+
+static const unsigned char RFC2409_PRIME_768[] = {
+	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, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+BIGNUM *
+BN_get_rfc2409_prime_768(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC2409_PRIME_768, sizeof(RFC2409_PRIME_768), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc2409_prime_768);
+
+/*
+ * "Second Oakley Default Group" from RFC2409, section 6.2.
+ *
+ * The prime is: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+ *
+ * RFC2409 specifies a generator of 2.
+ * RFC2412 specifies a generator of 22.
+ */
+
+static const unsigned char RFC2409_PRIME_1024[] = {
+	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, 0xE6, 0x53, 0x81,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+BIGNUM *
+BN_get_rfc2409_prime_1024(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC2409_PRIME_1024, sizeof(RFC2409_PRIME_1024), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc2409_prime_1024);
+
+/*
+ * "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.
+ * RFC2312 specifies a generator of 22.
+ */
+
+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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_1536(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_1536);
+
+/*
+ * "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 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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_2048(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_2048);
+
+/*
+ * "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 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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_3072(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_3072);
+
+/*
+ * "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 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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_4096(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_4096);
+
+/*
+ * "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 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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_6144(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_6144);
+
+/*
+ * "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 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,
+};
+
+BIGNUM *
+BN_get_rfc3526_prime_8192(BIGNUM *bn)
+{
+	return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn);
+}
+LCRYPTO_ALIAS(BN_get_rfc3526_prime_8192);
diff --git a/crypto/bn/bn_convert.c b/crypto/bn/bn_convert.c
new file mode 100644
index 0000000..f09c909
--- /dev/null
+++ b/crypto/bn/bn_convert.c
@@ -0,0 +1,773 @@
+/* $OpenBSD: bn_convert.c,v 1.15 2023/07/09 18:37:58 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "bytestring.h"
+
+static int bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs);
+static int bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs);
+
+static const char hex_digits[] = "0123456789ABCDEF";
+
+typedef enum {
+	big,
+	little,
+} endianness_t;
+
+/* ignore negative */
+static int
+bn2binpad(const BIGNUM *a, unsigned char *to, int tolen, endianness_t endianness)
+{
+	int n;
+	size_t i, lasti, j, atop, mask;
+	BN_ULONG l;
+
+	/*
+	 * In case |a| is fixed-top, BN_num_bytes can return bogus length,
+	 * but it's assumed that fixed-top inputs ought to be "nominated"
+	 * even for padded output, so it works out...
+	 */
+	n = BN_num_bytes(a);
+	if (tolen == -1)
+		tolen = n;
+	else if (tolen < n) {	/* uncommon/unlike case */
+		BIGNUM temp = *a;
+
+		bn_correct_top(&temp);
+
+		n = BN_num_bytes(&temp);
+		if (tolen < n)
+			return -1;
+	}
+
+	/* Swipe through whole available data and don't give away padded zero. */
+	atop = a->dmax * BN_BYTES;
+	if (atop == 0) {
+		explicit_bzero(to, tolen);
+		return tolen;
+	}
+
+	lasti = atop - 1;
+	atop = a->top * BN_BYTES;
+
+	if (endianness == big)
+		to += tolen; /* start from the end of the buffer */
+
+	for (i = 0, j = 0; j < (size_t)tolen; j++) {
+		unsigned char val;
+
+		l = a->d[i / BN_BYTES];
+		mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
+		val = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
+
+		if (endianness == big)
+			*--to = val;
+		else
+			*to++ = val;
+
+		i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
+	}
+
+	return tolen;
+}
+
+int
+BN_bn2bin(const BIGNUM *a, unsigned char *to)
+{
+	return bn2binpad(a, to, -1, big);
+}
+LCRYPTO_ALIAS(BN_bn2bin);
+
+int
+BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
+{
+	if (tolen < 0)
+		return -1;
+	return bn2binpad(a, to, tolen, big);
+}
+LCRYPTO_ALIAS(BN_bn2binpad);
+
+BIGNUM *
+BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
+{
+	unsigned int i, m;
+	unsigned int n;
+	BN_ULONG l;
+	BIGNUM *bn = NULL;
+
+	if (len < 0)
+		return (NULL);
+	if (ret == NULL)
+		ret = bn = BN_new();
+	if (ret == NULL)
+		return (NULL);
+	l = 0;
+	n = len;
+	if (n == 0) {
+		ret->top = 0;
+		return (ret);
+	}
+	i = ((n - 1) / BN_BYTES) + 1;
+	m = ((n - 1) % (BN_BYTES));
+	if (!bn_wexpand(ret, (int)i)) {
+		BN_free(bn);
+		return NULL;
+	}
+	ret->top = i;
+	ret->neg = 0;
+	while (n--) {
+		l = (l << 8L) | *(s++);
+		if (m-- == 0) {
+			ret->d[--i] = l;
+			l = 0;
+			m = BN_BYTES - 1;
+		}
+	}
+	/* need to call this due to clear byte at top if avoiding
+	 * having the top bit set (-ve number) */
+	bn_correct_top(ret);
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_bin2bn);
+
+int
+BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
+{
+	if (tolen < 0)
+		return -1;
+
+	return bn2binpad(a, to, tolen, little);
+}
+LCRYPTO_ALIAS(BN_bn2lebinpad);
+
+BIGNUM *
+BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
+{
+	unsigned int i, m, n;
+	BN_ULONG l;
+	BIGNUM *bn = NULL;
+
+	if (ret == NULL)
+		ret = bn = BN_new();
+	if (ret == NULL)
+		return NULL;
+
+
+	s += len;
+	/* Skip trailing zeroes. */
+	for (; len > 0 && s[-1] == 0; s--, len--)
+		continue;
+
+	n = len;
+	if (n == 0) {
+		ret->top = 0;
+		return ret;
+	}
+
+	i = ((n - 1) / BN_BYTES) + 1;
+	m = (n - 1) % BN_BYTES;
+	if (!bn_wexpand(ret, (int)i)) {
+		BN_free(bn);
+		return NULL;
+	}
+
+	ret->top = i;
+	ret->neg = 0;
+	l = 0;
+	while (n-- > 0) {
+		s--;
+		l = (l << 8L) | *s;
+		if (m-- == 0) {
+			ret->d[--i] = l;
+			l = 0;
+			m = BN_BYTES - 1;
+		}
+	}
+
+	/*
+	 * need to call this due to clear byte at top if avoiding having the
+	 * top bit set (-ve number)
+	 */
+	bn_correct_top(ret);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_lebin2bn);
+
+int
+BN_asc2bn(BIGNUM **bnp, const char *s)
+{
+	CBS cbs, cbs_hex;
+	size_t s_len;
+	uint8_t v;
+	int neg;
+
+	if (bnp != NULL && *bnp != NULL)
+		BN_zero(*bnp);
+
+	if (s == NULL)
+		return 0;
+	if ((s_len = strlen(s)) == 0)
+		return 0;
+
+	CBS_init(&cbs, s, s_len);
+
+	/* Handle negative sign. */
+	if (!CBS_peek_u8(&cbs, &v))
+		return 0;
+	if ((neg = (v == '-'))) {
+		if (!CBS_skip(&cbs, 1))
+			return 0;
+	}
+
+	/* Try parsing as hexadecimal with a 0x prefix. */
+	CBS_dup(&cbs, &cbs_hex);
+	if (!CBS_get_u8(&cbs_hex, &v))
+		goto decimal;
+	if (v != '0')
+		goto decimal;
+	if (!CBS_get_u8(&cbs_hex, &v))
+		goto decimal;
+	if (v != 'X' && v != 'x')
+		goto decimal;
+	if (bn_hex2bn_cbs(bnp, &cbs_hex) == 0)
+		return 0;
+
+	goto done;
+
+ decimal:
+	if (bn_dec2bn_cbs(bnp, &cbs) == 0)
+		return 0;
+
+ done:
+	if (bnp != NULL && *bnp != NULL)
+		BN_set_negative(*bnp, neg);
+
+	return 1;
+}
+LCRYPTO_ALIAS(BN_asc2bn);
+
+char *
+BN_bn2dec(const BIGNUM *bn)
+{
+	int started = 0;
+	BIGNUM *tmp = NULL;
+	uint8_t *data = NULL;
+	size_t data_len = 0;
+	uint8_t *s = NULL;
+	size_t s_len;
+	BN_ULONG v, w;
+	uint8_t c;
+	CBB cbb;
+	CBS cbs;
+	int i;
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+
+	if ((tmp = BN_dup(bn)) == NULL)
+		goto err;
+
+	/*
+	 * Divide the BIGNUM by a large multiple of 10, then break the remainder
+	 * into decimal digits. This produces a reversed string of digits,
+	 * potentially with leading zeroes.
+	 */
+	while (!BN_is_zero(tmp)) {
+		if ((w = BN_div_word(tmp, BN_DEC_CONV)) == -1)
+			goto err;
+		for (i = 0; i < BN_DEC_NUM; i++) {
+			v = w % 10;
+			if (!CBB_add_u8(&cbb, '0' + v))
+				goto err;
+			w /= 10;
+		}
+	}
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	if (data_len > SIZE_MAX - 3)
+		goto err;
+	if (!CBB_init(&cbb, data_len + 3))
+		goto err;
+
+	if (BN_is_negative(bn)) {
+		if (!CBB_add_u8(&cbb, '-'))
+			goto err;
+	}
+
+	/* Reverse digits and trim leading zeroes. */
+	CBS_init(&cbs, data, data_len);
+	while (CBS_len(&cbs) > 0) {
+		if (!CBS_get_last_u8(&cbs, &c))
+			goto err;
+		if (!started && c == '0')
+			continue;
+		if (!CBB_add_u8(&cbb, c))
+			goto err;
+		started = 1;
+	}
+
+	if (!started) {
+		if (!CBB_add_u8(&cbb, '0'))
+			goto err;
+	}
+	if (!CBB_add_u8(&cbb, '\0'))
+		goto err;
+	if (!CBB_finish(&cbb, &s, &s_len))
+		goto err;
+
+ err:
+	BN_free(tmp);
+	CBB_cleanup(&cbb);
+	freezero(data, data_len);
+
+	return s;
+}
+LCRYPTO_ALIAS(BN_bn2dec);
+
+static int
+bn_dec2bn_cbs(BIGNUM **bnp, CBS *cbs)
+{
+	CBS cbs_digits;
+	BIGNUM *bn = NULL;
+	int d, neg, num;
+	size_t digits = 0;
+	BN_ULONG w;
+	uint8_t v;
+
+	/* Handle negative sign. */
+	if (!CBS_peek_u8(cbs, &v))
+		goto err;
+	if ((neg = (v == '-'))) {
+		if (!CBS_skip(cbs, 1))
+			goto err;
+	}
+
+	/* Scan to find last decimal digit. */
+	CBS_dup(cbs, &cbs_digits);
+	while (CBS_len(&cbs_digits) > 0) {
+		if (!CBS_get_u8(&cbs_digits, &v))
+			goto err;
+		if (!isdigit(v))
+			break;
+		digits++;
+	}
+	if (digits > INT_MAX / 4)
+		goto err;
+
+	num = digits + neg;
+
+	if (bnp == NULL)
+		return num;
+
+	if ((bn = *bnp) == NULL)
+		bn = BN_new();
+	if (bn == NULL)
+		goto err;
+	if (!bn_expand(bn, digits * 4))
+		goto err;
+
+	if ((d = digits % BN_DEC_NUM) == 0)
+		d = BN_DEC_NUM;
+
+	w = 0;
+
+	/* Work forwards from most significant digit. */
+	while (digits-- > 0) {
+		if (!CBS_get_u8(cbs, &v))
+			goto err;
+
+		if (v < '0' || v > '9')
+			goto err;
+
+		v -= '0';
+		w = w * 10 + v;
+		d--;
+
+		if (d == 0) {
+			if (!BN_mul_word(bn, BN_DEC_CONV))
+				goto err;
+			if (!BN_add_word(bn, w))
+				goto err;
+
+			d = BN_DEC_NUM;
+			w = 0;
+		}
+	}
+
+	bn_correct_top(bn);
+
+	BN_set_negative(bn, neg);
+
+	*bnp = bn;
+
+	return num;
+
+ err:
+	if (bnp != NULL && *bnp == NULL)
+		BN_free(bn);
+
+	return 0;
+}
+
+int
+BN_dec2bn(BIGNUM **bnp, const char *s)
+{
+	size_t s_len;
+	CBS cbs;
+
+	if (bnp != NULL && *bnp != NULL)
+		BN_zero(*bnp);
+
+	if (s == NULL)
+		return 0;
+	if ((s_len = strlen(s)) == 0)
+		return 0;
+
+	CBS_init(&cbs, s, s_len);
+
+	return bn_dec2bn_cbs(bnp, &cbs);
+}
+LCRYPTO_ALIAS(BN_dec2bn);
+
+static int
+bn_bn2hex_internal(const BIGNUM *bn, int include_sign, int nibbles_only,
+    char **out, size_t *out_len)
+{
+	int started = 0;
+	uint8_t *s = NULL;
+	size_t s_len = 0;
+	BN_ULONG v, w;
+	int i, j;
+	CBB cbb;
+	CBS cbs;
+	uint8_t nul;
+	int ret = 0;
+
+	*out = NULL;
+	*out_len = 0;
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+
+	if (BN_is_negative(bn) && include_sign) {
+		if (!CBB_add_u8(&cbb, '-'))
+			goto err;
+	}
+	if (BN_is_zero(bn)) {
+		if (!CBB_add_u8(&cbb, '0'))
+			goto err;
+	}
+	for (i = bn->top - 1; i >= 0; i--) {
+		w = bn->d[i];
+		for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
+			v = (w >> j) & 0xff;
+			if (!started && v == 0)
+				continue;
+			if (started || !nibbles_only || (v >> 4) != 0) {
+				if (!CBB_add_u8(&cbb, hex_digits[v >> 4]))
+					goto err;
+			}
+			if (!CBB_add_u8(&cbb, hex_digits[v & 0xf]))
+				goto err;
+			started = 1;
+		}
+	}
+	if (!CBB_add_u8(&cbb, '\0'))
+		goto err;
+	if (!CBB_finish(&cbb, &s, &s_len))
+		goto err;
+
+	/* The length of a C string does not include the terminating NUL. */
+	CBS_init(&cbs, s, s_len);
+	if (!CBS_get_last_u8(&cbs, &nul))
+		goto err;
+
+	*out = (char *)CBS_data(&cbs);
+	*out_len = CBS_len(&cbs);
+	s = NULL;
+	s_len = 0;
+
+	ret = 1;
+
+ err:
+	CBB_cleanup(&cbb);
+	freezero(s, s_len);
+
+	return ret;
+}
+
+int
+bn_bn2hex_nosign(const BIGNUM *bn, char **out, size_t *out_len)
+{
+	return bn_bn2hex_internal(bn, 0, 0, out, out_len);
+}
+
+int
+bn_bn2hex_nibbles(const BIGNUM *bn, char **out, size_t *out_len)
+{
+	return bn_bn2hex_internal(bn, 1, 1, out, out_len);
+}
+
+char *
+BN_bn2hex(const BIGNUM *bn)
+{
+	char *s;
+	size_t s_len;
+
+	if (!bn_bn2hex_internal(bn, 1, 0, &s, &s_len))
+		return NULL;
+
+	return s;
+}
+LCRYPTO_ALIAS(BN_bn2hex);
+
+static int
+bn_hex2bn_cbs(BIGNUM **bnp, CBS *cbs)
+{
+	CBS cbs_digits;
+	BIGNUM *bn = NULL;
+	int b, i, neg, num;
+	size_t digits = 0;
+	BN_ULONG w;
+	uint8_t v;
+
+	/* Handle negative sign. */
+	if (!CBS_peek_u8(cbs, &v))
+		goto err;
+	if ((neg = (v == '-'))) {
+		if (!CBS_skip(cbs, 1))
+			goto err;
+	}
+
+	/* Scan to find last hexadecimal digit. */
+	CBS_dup(cbs, &cbs_digits);
+	while (CBS_len(&cbs_digits) > 0) {
+		if (!CBS_get_u8(&cbs_digits, &v))
+			goto err;
+		if (!isxdigit(v))
+			break;
+		digits++;
+	}
+	if (digits > INT_MAX / 4)
+		goto err;
+
+	num = digits + neg;
+
+	if (bnp == NULL)
+		return num;
+
+	if ((bn = *bnp) == NULL)
+		bn = BN_new();
+	if (bn == NULL)
+		goto err;
+	if (!bn_expand(bn, digits * 4))
+		goto err;
+
+	if (!CBS_get_bytes(cbs, cbs, digits))
+		goto err;
+
+	b = BN_BITS2;
+	i = 0;
+	w = 0;
+
+	/* Work backwards from least significant digit. */
+	while (digits-- > 0) {
+		if (!CBS_get_last_u8(cbs, &v))
+			goto err;
+
+		if (v >= '0' && v <= '9')
+			v -= '0';
+		else if (v >= 'a' && v <= 'f')
+			v -= 'a' - 10;
+		else if (v >= 'A' && v <= 'F')
+			v -= 'A' - 10;
+		else
+			goto err;
+
+		w |= (BN_ULONG)v << (BN_BITS2 - b);
+		b -= 4;
+
+		if (b == 0 || digits == 0) {
+			b = BN_BITS2;
+			bn->d[i++] = w;
+			w = 0;
+		}
+	}
+
+	bn->top = i;
+	bn_correct_top(bn);
+
+	BN_set_negative(bn, neg);
+
+	*bnp = bn;
+
+	return num;
+
+ err:
+	if (bnp != NULL && *bnp == NULL)
+		BN_free(bn);
+
+	return 0;
+}
+
+int
+BN_hex2bn(BIGNUM **bnp, const char *s)
+{
+	size_t s_len;
+	CBS cbs;
+
+	if (bnp != NULL && *bnp != NULL)
+		BN_zero(*bnp);
+
+	if (s == NULL)
+		return 0;
+	if ((s_len = strlen(s)) == 0)
+		return 0;
+
+	CBS_init(&cbs, s, s_len);
+
+	return bn_hex2bn_cbs(bnp, &cbs);
+}
+LCRYPTO_ALIAS(BN_hex2bn);
+
+int
+BN_bn2mpi(const BIGNUM *a, unsigned char *d)
+{
+	int bits;
+	int num = 0;
+	int ext = 0;
+	long l;
+
+	bits = BN_num_bits(a);
+	num = (bits + 7) / 8;
+	if (bits > 0) {
+		ext = ((bits & 0x07) == 0);
+	}
+	if (d == NULL)
+		return (num + 4 + ext);
+
+	l = num + ext;
+	d[0] = (unsigned char)(l >> 24) & 0xff;
+	d[1] = (unsigned char)(l >> 16) & 0xff;
+	d[2] = (unsigned char)(l >> 8) & 0xff;
+	d[3] = (unsigned char)(l) & 0xff;
+	if (ext)
+		d[4] = 0;
+	num = BN_bn2bin(a, &(d[4 + ext]));
+	if (a->neg)
+		d[4] |= 0x80;
+	return (num + 4 + ext);
+}
+LCRYPTO_ALIAS(BN_bn2mpi);
+
+BIGNUM *
+BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain)
+{
+	BIGNUM *a = ain;
+	long len;
+	int neg = 0;
+
+	if (n < 4) {
+		BNerror(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) {
+		BNerror(BN_R_ENCODING_ERROR);
+		return (NULL);
+	}
+
+	if (a == NULL)
+		a = BN_new();
+	if (a == NULL)
+		return (NULL);
+
+	if (len == 0) {
+		a->neg = 0;
+		a->top = 0;
+		return (a);
+	}
+	d += 4;
+	if ((*d) & 0x80)
+		neg = 1;
+	if (BN_bin2bn(d, (int)len, a) == NULL) {
+		if (ain == NULL)
+			BN_free(a);
+		return (NULL);
+	}
+	BN_set_negative(a, neg);
+	if (neg) {
+		BN_clear_bit(a, BN_num_bits(a) - 1);
+	}
+	return (a);
+}
+LCRYPTO_ALIAS(BN_mpi2bn);
diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c
new file mode 100644
index 0000000..129b9c9
--- /dev/null
+++ b/crypto/bn/bn_ctx.c
@@ -0,0 +1,161 @@
+/*	$OpenBSD: bn_ctx.c,v 1.22 2023/07/08 12:21:58 beck Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bn_local.h"
+
+#define BN_CTX_INITIAL_LEN	8
+
+struct bignum_ctx {
+	BIGNUM **bignums;
+	uint8_t *groups;
+	uint8_t group;
+	size_t index;
+	size_t len;
+
+	int error;
+};
+
+static int
+bn_ctx_grow(BN_CTX *bctx)
+{
+	BIGNUM **bignums = NULL;
+	uint8_t *groups = NULL;
+	size_t len;
+
+	if ((len = bctx->len) == 0) {
+		len = BN_CTX_INITIAL_LEN;
+	} else {
+		if (SIZE_MAX - len < len)
+			return 0;
+		len *= 2;
+	}
+
+	if ((bignums = recallocarray(bctx->bignums, bctx->len, len,
+	    sizeof(bctx->bignums[0]))) == NULL)
+		return 0;
+	bctx->bignums = bignums;
+
+	if ((groups = reallocarray(bctx->groups, len,
+	    sizeof(bctx->groups[0]))) == NULL)
+		return 0;
+	bctx->groups = groups;
+
+	bctx->len = len;
+
+	return 1;
+}
+
+BN_CTX *
+BN_CTX_new(void)
+{
+	return calloc(1, sizeof(struct bignum_ctx));
+}
+LCRYPTO_ALIAS(BN_CTX_new);
+
+void
+BN_CTX_free(BN_CTX *bctx)
+{
+	size_t i;
+
+	if (bctx == NULL)
+		return;
+
+	for (i = 0; i < bctx->len; i++) {
+		BN_free(bctx->bignums[i]);
+		bctx->bignums[i] = NULL;
+	}
+
+	free(bctx->bignums);
+	free(bctx->groups);
+
+	freezero(bctx, sizeof(*bctx));
+}
+LCRYPTO_ALIAS(BN_CTX_free);
+
+void
+BN_CTX_start(BN_CTX *bctx)
+{
+	bctx->group++;
+
+	if (bctx->group == 0) {
+		BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+		bctx->error = 1;
+		return;
+	}
+}
+LCRYPTO_ALIAS(BN_CTX_start);
+
+BIGNUM *
+BN_CTX_get(BN_CTX *bctx)
+{
+	BIGNUM *bn = NULL;
+
+	if (bctx->error)
+		return NULL;
+
+	if (bctx->group == 0) {
+		BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		bctx->error = 1;
+		return NULL;
+	}
+
+	if (bctx->index == bctx->len) {
+		if (!bn_ctx_grow(bctx)) {
+			BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+			bctx->error = 1;
+			return NULL;
+		}
+	}
+
+	if ((bn = bctx->bignums[bctx->index]) == NULL) {
+		if ((bn = BN_new()) == NULL) {
+			BNerror(BN_R_TOO_MANY_TEMPORARY_VARIABLES);
+			bctx->error = 1;
+			return NULL;
+		}
+		bctx->bignums[bctx->index] = bn;
+	}
+	bctx->groups[bctx->index] = bctx->group;
+	bctx->index++;
+
+	BN_zero(bn);
+
+	return bn;
+}
+LCRYPTO_ALIAS(BN_CTX_get);
+
+void
+BN_CTX_end(BN_CTX *bctx)
+{
+	if (bctx == NULL || bctx->error || bctx->group == 0)
+		return;
+
+	while (bctx->index > 0 && bctx->groups[bctx->index - 1] == bctx->group) {
+		BN_zero(bctx->bignums[bctx->index - 1]);
+		bctx->groups[bctx->index - 1] = 0;
+		bctx->index--;
+	}
+
+	bctx->group--;
+}
+LCRYPTO_ALIAS(BN_CTX_end);
diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c
new file mode 100644
index 0000000..3225fa4
--- /dev/null
+++ b/crypto/bn/bn_div.c
@@ -0,0 +1,457 @@
+/* $OpenBSD: bn_div.c,v 1.40 2023/03/27 10:21:23 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "bn_arch.h"
+#include "bn_local.h"
+#include "bn_internal.h"
+
+BN_ULONG bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0);
+
+#ifndef HAVE_BN_DIV_WORDS
+#if defined(BN_LLONG) && defined(BN_DIV2W)
+
+BN_ULONG
+bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
+{
+	return ((BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2)|l)/(BN_ULLONG)d));
+}
+
+#else
+
+/* Divide h,l by d and return the result. */
+/* I need to test this some more :-( */
+BN_ULONG
+bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
+{
+	BN_ULONG dh, dl, q,ret = 0, th, tl, t;
+	int i, count = 2;
+
+	if (d == 0)
+		return (BN_MASK2);
+
+	i = BN_num_bits_word(d);
+	assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
+
+	i = BN_BITS2 - i;
+	if (h >= d)
+		h -= d;
+
+	if (i) {
+		d <<= i;
+		h = (h << i) | (l >> (BN_BITS2 - i));
+		l <<= i;
+	}
+	dh = (d & BN_MASK2h) >> BN_BITS4;
+	dl = (d & BN_MASK2l);
+	for (;;) {
+		if ((h >> BN_BITS4) == dh)
+			q = BN_MASK2l;
+		else
+			q = h / dh;
+
+		th = q * dh;
+		tl = dl * q;
+		for (;;) {
+			t = h - th;
+			if ((t & BN_MASK2h) ||
+			    ((tl) <= (
+			    (t << BN_BITS4) |
+			    ((l & BN_MASK2h) >> BN_BITS4))))
+				break;
+			q--;
+			th -= dh;
+			tl -= dl;
+		}
+		t = (tl >> BN_BITS4);
+		tl = (tl << BN_BITS4) & BN_MASK2h;
+		th += t;
+
+		if (l < tl)
+			th++;
+		l -= tl;
+		if (h < th) {
+			h += d;
+			q--;
+		}
+		h -= th;
+
+		if (--count == 0)
+			break;
+
+		ret = q << BN_BITS4;
+		h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
+		l = (l & BN_MASK2l) << BN_BITS4;
+	}
+	ret |= q;
+	return (ret);
+}
+#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
+#endif
+
+/*
+ * Divide a double word (h:l) by d, returning the quotient q and the remainder
+ * r, such that q * d + r is equal to the numerator.
+ */
+#ifndef HAVE_BN_DIV_REM_WORDS
+#ifndef HAVE_BN_DIV_REM_WORDS_INLINE
+static inline void
+bn_div_rem_words_inline(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+    BN_ULONG *out_r)
+{
+	BN_ULONG q, r;
+
+	q = bn_div_words(h, l, d);
+	r = (l - q * d) & BN_MASK2;
+
+	*out_q = q;
+	*out_r = r;
+}
+#endif
+
+void
+bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+    BN_ULONG *out_r)
+{
+	bn_div_rem_words_inline(h, l, d, out_q, out_r);
+}
+#endif
+
+#ifndef HAVE_BN_DIV_3_WORDS
+
+/*
+ * Interface is somewhat quirky, |m| is pointer to most significant limb,
+ * and less significant limb is referred at |m[-1]|. This means that caller
+ * is responsible for ensuring that |m[-1]| is valid. Second condition that
+ * has to be met is that |d0|'s most significant bit has to be set. Or in
+ * other words divisor has to be "bit-aligned to the left." The subroutine
+ * considers four limbs, two of which are "overlapping," hence the name...
+ */
+BN_ULONG
+bn_div_3_words(const BN_ULONG *m, BN_ULONG d1, BN_ULONG d0)
+{
+	BN_ULONG n0, n1, q, t2h, t2l;
+	BN_ULONG rem = 0;
+
+	n0 = m[0];
+	n1 = m[-1];
+
+	if (n0 == d0)
+		return BN_MASK2;
+
+	/* n0 < d0 */
+	bn_div_rem_words(n0, n1, d0, &q, &rem);
+
+	bn_mulw(d1, q, &t2h, &t2l);
+
+	for (;;) {
+		if (t2h < rem || (t2h == rem && t2l <= m[-2]))
+			break;
+		q--;
+		rem += d0;
+		if (rem < d0)
+			break; /* don't let rem overflow */
+		if (t2l < d1)
+			t2h--;
+		t2l -= d1;
+	}
+
+	return q;
+}
+#endif /* !HAVE_BN_DIV_3_WORDS */
+
+/*
+ * BN_div_internal computes quotient := numerator / divisor, rounding towards
+ * zero and setting remainder such that quotient * divisor + remainder equals
+ * the numerator. Thus:
+ *
+ *   quotient->neg  == numerator->neg ^ divisor->neg   (unless result is zero)
+ *   remainder->neg == numerator->neg           (unless the remainder is zero)
+ *
+ * If either the quotient or remainder is NULL, the respective value is not
+ * returned.
+ */
+static int
+BN_div_internal(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
+    const BIGNUM *divisor, BN_CTX *ctx, int ct)
+{
+	int norm_shift, i, loop, r_neg;
+	BIGNUM *tmp, wnum, *snum, *sdiv, *res;
+	BN_ULONG *resp, *wnump;
+	BN_ULONG d0, d1;
+	int num_n, div_n;
+	int no_branch = 0;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	/* Invalid zero-padding would have particularly bad consequences. */
+	if (numerator->top > 0 && numerator->d[numerator->top - 1] == 0) {
+		BNerror(BN_R_NOT_INITIALIZED);
+		goto err;
+	}
+
+	if (ct)
+		no_branch = 1;
+
+	if (BN_is_zero(divisor)) {
+		BNerror(BN_R_DIV_BY_ZERO);
+		goto err;
+	}
+
+	if (!no_branch) {
+		if (BN_ucmp(numerator, divisor) < 0) {
+			if (remainder != NULL) {
+				if (!bn_copy(remainder, numerator))
+					goto err;
+			}
+			if (quotient != NULL)
+				BN_zero(quotient);
+
+			goto done;
+		}
+	}
+
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((snum = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((sdiv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((res = quotient) == NULL) {
+		if ((res = BN_CTX_get(ctx)) == NULL)
+			goto err;
+	}
+
+	/* First we normalise the numbers. */
+	norm_shift = BN_BITS2 - BN_num_bits(divisor) % BN_BITS2;
+	if (!BN_lshift(sdiv, divisor, norm_shift))
+		goto err;
+	sdiv->neg = 0;
+	norm_shift += BN_BITS2;
+	if (!BN_lshift(snum, numerator, norm_shift))
+		goto err;
+	snum->neg = 0;
+
+	if (no_branch) {
+		/*
+		 * Since we don't know whether snum is larger than sdiv, we pad
+		 * snum with enough zeroes without changing its value.
+		 */
+		if (snum->top <= sdiv->top + 1) {
+			if (!bn_wexpand(snum, sdiv->top + 2))
+				goto err;
+			for (i = snum->top; i < sdiv->top + 2; i++)
+				snum->d[i] = 0;
+			snum->top = sdiv->top + 2;
+		} else {
+			if (!bn_wexpand(snum, snum->top + 1))
+				goto err;
+			snum->d[snum->top] = 0;
+			snum->top++;
+		}
+	}
+
+	div_n = sdiv->top;
+	num_n = snum->top;
+	loop = num_n - div_n;
+
+	/*
+	 * Setup a 'window' into snum - this is the part that corresponds to the
+	 * current 'area' being divided.
+	 */
+	wnum.neg = 0;
+	wnum.d = &(snum->d[loop]);
+	wnum.top = div_n;
+	/* only needed when BN_ucmp messes up the values between top and max */
+	wnum.dmax  = snum->dmax - loop; /* so we don't step out of bounds */
+	wnum.flags = snum->flags | BN_FLG_STATIC_DATA;
+
+	/* Get the top 2 words of sdiv */
+	/* div_n=sdiv->top; */
+	d0 = sdiv->d[div_n - 1];
+	d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];
+
+	/* pointer to the 'top' of snum */
+	wnump = &(snum->d[num_n - 1]);
+
+	/* Setup to 'res' */
+	if (!bn_wexpand(res, (loop + 1)))
+		goto err;
+	res->top = loop - no_branch;
+	r_neg = numerator->neg ^ divisor->neg;
+	resp = &(res->d[loop - 1]);
+
+	/* space for temp */
+	if (!bn_wexpand(tmp, (div_n + 1)))
+		goto err;
+
+	if (!no_branch) {
+		if (BN_ucmp(&wnum, sdiv) >= 0) {
+			bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
+			*resp = 1;
+		} else
+			res->top--;
+	}
+
+	/*
+	 * If res->top == 0 then clear the neg value otherwise decrease the resp
+	 * pointer.
+	 */
+	if (res->top == 0)
+		res->neg = 0;
+	else
+		resp--;
+
+	for (i = 0; i < loop - 1; i++, wnump--, resp--) {
+		BN_ULONG q, l0;
+
+		/*
+		 * The first part of the loop uses the top two words of snum and
+		 * sdiv to calculate a BN_ULONG q such that:
+		 *
+		 *  | wnum - sdiv * q | < sdiv
+		 */
+		q = bn_div_3_words(wnump, d1, d0);
+		l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
+		tmp->d[div_n] = l0;
+		wnum.d--;
+
+		/*
+		 * Ignore top values of the bignums just sub the two BN_ULONG
+		 * arrays with bn_sub_words.
+		 */
+		if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
+			/*
+			 * Note: As we have considered only the leading two
+			 * BN_ULONGs in the calculation of q, sdiv * q might be
+			 * greater than wnum (but then (q-1) * sdiv is less or
+			 * equal than wnum).
+			 */
+			q--;
+			if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) {
+				/*
+				 * We can't have an overflow here (assuming
+				 * that q != 0, but if q == 0 then tmp is
+				 * zero anyway).
+				 */
+				(*wnump)++;
+			}
+		}
+		/* store part of the result */
+		*resp = q;
+	}
+
+	bn_correct_top(snum);
+
+	if (remainder != NULL) {
+		/*
+		 * Keep a copy of the neg flag in numerator because if
+		 * remainder == numerator, BN_rshift() will overwrite it.
+		 */
+		int neg = numerator->neg;
+
+		BN_rshift(remainder, snum, norm_shift);
+		BN_set_negative(remainder, neg);
+	}
+
+	if (no_branch)
+		bn_correct_top(res);
+
+	BN_set_negative(res, r_neg);
+
+ done:
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+BN_div(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
+    const BIGNUM *divisor, BN_CTX *ctx)
+{
+	int ct;
+
+	ct = BN_get_flags(numerator, BN_FLG_CONSTTIME) != 0 ||
+	    BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0;
+
+	return BN_div_internal(quotient, remainder, numerator, divisor, ctx, ct);
+}
+
+int
+BN_div_nonct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
+    const BIGNUM *divisor, BN_CTX *ctx)
+{
+	return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 0);
+}
+
+int
+BN_div_ct(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
+    const BIGNUM *divisor, BN_CTX *ctx)
+{
+	return BN_div_internal(quotient, remainder, numerator, divisor, ctx, 1);
+}
diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c
new file mode 100644
index 0000000..6fd6030
--- /dev/null
+++ b/crypto/bn/bn_err.c
@@ -0,0 +1,108 @@
+/* $OpenBSD: bn_err.c,v 1.17 2023/07/08 12:21:58 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_BN,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BN,0,reason)
+
+static ERR_STRING_DATA BN_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA BN_str_reasons[]= {
+	{ERR_REASON(BN_R_ARG2_LT_ARG3)           , "arg2 lt arg3"},
+	{ERR_REASON(BN_R_BAD_RECIPROCAL)         , "bad reciprocal"},
+	{ERR_REASON(BN_R_BIGNUM_TOO_LONG)        , "bignum too long"},
+	{ERR_REASON(BN_R_BITS_TOO_SMALL)         , "bits too small"},
+	{ERR_REASON(BN_R_CALLED_WITH_EVEN_MODULUS), "called with even modulus"},
+	{ERR_REASON(BN_R_DIV_BY_ZERO)            , "div by zero"},
+	{ERR_REASON(BN_R_ENCODING_ERROR)         , "encoding error"},
+	{ERR_REASON(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA), "expand on static bignum data"},
+	{ERR_REASON(BN_R_INPUT_NOT_REDUCED)      , "input not reduced"},
+	{ERR_REASON(BN_R_INVALID_ARGUMENT)       , "invalid argument"},
+	{ERR_REASON(BN_R_INVALID_LENGTH)         , "invalid length"},
+	{ERR_REASON(BN_R_INVALID_RANGE)          , "invalid range"},
+	{ERR_REASON(BN_R_NOT_A_SQUARE)           , "not a square"},
+	{ERR_REASON(BN_R_NOT_INITIALIZED)        , "not initialized"},
+	{ERR_REASON(BN_R_NO_INVERSE)             , "no inverse"},
+	{ERR_REASON(BN_R_NO_SOLUTION)            , "no solution"},
+	{ERR_REASON(BN_R_P_IS_NOT_PRIME)         , "p is not prime"},
+	{ERR_REASON(BN_R_TOO_MANY_ITERATIONS)    , "too many iterations"},
+	{ERR_REASON(BN_R_TOO_MANY_TEMPORARY_VARIABLES), "too many temporary variables"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_BN_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(BN_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, BN_str_functs);
+		ERR_load_strings(0, BN_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_BN_strings);
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
new file mode 100644
index 0000000..a50fa59
--- /dev/null
+++ b/crypto/bn/bn_exp.c
@@ -0,0 +1,1338 @@
+/* $OpenBSD: bn_exp.c,v 1.47 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "bn_local.h"
+#include "constant_time.h"
+
+/* maximum precomputation table size for *variable* sliding windows */
+#define TABLE_SIZE	32
+
+/* Calculates r = a^p by successive squaring of a. Not constant time. */
+int
+BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
+{
+	BIGNUM *rr, *v;
+	int i;
+	int ret = 0;
+
+	if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
+		BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((v = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	rr = r;
+	if (r == a || r == p)
+		rr = BN_CTX_get(ctx);
+	if (rr == NULL)
+		goto err;
+
+	if (!BN_one(rr))
+		goto err;
+	if (BN_is_odd(p)) {
+		if (!bn_copy(rr, a))
+			goto err;
+	}
+
+	if (!bn_copy(v, a))
+		goto err;
+
+	for (i = 1; i < BN_num_bits(p); i++) {
+		if (!BN_sqr(v, v, ctx))
+			goto err;
+		if (!BN_is_bit_set(p, i))
+			continue;
+		if (!BN_mul(rr, rr, v, ctx))
+			goto err;
+	}
+
+	if (!bn_copy(r, rr))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_exp);
+
+/* The old fallback, simple version :-) */
+int
+BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	int i, j, bits, ret = 0, wstart, wend, window, wvalue;
+	int start = 1;
+	BIGNUM *d;
+	/* Table of variables obtained from 'ctx' */
+	BIGNUM *val[TABLE_SIZE];
+
+	if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
+		/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+	}
+
+	bits = BN_num_bits(p);
+	if (bits == 0) {
+		/* x**0 mod 1 is still zero. */
+		if (BN_abs_is_word(m, 1)) {
+			ret = 1;
+			BN_zero(r);
+		} else
+			ret = BN_one(r);
+		return ret;
+	}
+
+	BN_CTX_start(ctx);
+	if ((d = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((val[0] = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_nnmod(val[0],a,m,ctx))
+		goto err;		/* 1 */
+	if (BN_is_zero(val[0])) {
+		BN_zero(r);
+		ret = 1;
+		goto err;
+	}
+
+	window = BN_window_bits_for_exponent_size(bits);
+	if (window > 1) {
+		if (!BN_mod_mul(d, val[0], val[0], m, ctx))
+			goto err;				/* 2 */
+		j = 1 << (window - 1);
+		for (i = 1; i < j; i++) {
+			if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
+			    !BN_mod_mul(val[i], val[i - 1], d,m, ctx))
+				goto err;
+		}
+	}
+
+	start = 1;		/* This is used to avoid multiplication etc
+				 * when there is only the value '1' in the
+				 * buffer. */
+	wvalue = 0;		/* The 'value' of the window */
+	wstart = bits - 1;	/* The top bit of the window */
+	wend = 0;		/* The bottom bit of the window */
+
+	if (!BN_one(r))
+		goto err;
+
+	for (;;) {
+		if (BN_is_bit_set(p, wstart) == 0) {
+			if (!start)
+				if (!BN_mod_mul(r, r, r, m, ctx))
+					goto err;
+			if (wstart == 0)
+				break;
+			wstart--;
+			continue;
+		}
+		/* We now have wstart on a 'set' bit, we now need to work out
+		 * how bit 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++) {
+			if (wstart - i < 0)
+				break;
+			if (BN_is_bit_set(p, wstart - i)) {
+				wvalue <<= (i - wend);
+				wvalue |= 1;
+				wend = i;
+			}
+		}
+
+		/* wend is the size of the current window */
+		j = wend + 1;
+		/* add the 'bytes above' */
+		if (!start)
+			for (i = 0; i < j; i++) {
+				if (!BN_mod_mul(r, r, r, m, ctx))
+					goto err;
+			}
+
+		/* wvalue will be an odd number < 2^window */
+		if (!BN_mod_mul(r, r, val[wvalue >> 1], m, ctx))
+			goto err;
+
+		/* move the 'window' down further */
+		wstart -= wend + 1;
+		wvalue = 0;
+		start = 0;
+		if (wstart < 0)
+			break;
+	}
+	ret = 1;
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_mod_exp_simple);
+
+/* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific layout
+ * so that accessing any of these table values shows the same access pattern as far
+ * as cache lines are concerned.  The following functions are used to transfer a BIGNUM
+ * from/to that table. */
+
+static int
+MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, unsigned char *buf,
+    int idx, int window)
+{
+	int i, j;
+	int width = 1 << window;
+	BN_ULONG *table = (BN_ULONG *)buf;
+
+	if (top > b->top)
+		top = b->top; /* this works because 'buf' is explicitly zeroed */
+
+	for (i = 0, j = idx; i < top; i++, j += width) {
+		table[j] = b->d[i];
+	}
+
+	return 1;
+}
+
+static int
+MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx,
+    int window)
+{
+	int i, j;
+	int width = 1 << window;
+	volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
+
+	if (!bn_wexpand(b, top))
+		return 0;
+
+	if (window <= 3) {
+		for (i = 0; i < top; i++, table += width) {
+		    BN_ULONG acc = 0;
+
+		    for (j = 0; j < width; j++) {
+			acc |= table[j] &
+			       ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1));
+		    }
+
+		    b->d[i] = acc;
+		}
+	} else {
+		int xstride = 1 << (window - 2);
+		BN_ULONG y0, y1, y2, y3;
+
+		i = idx >> (window - 2);        /* equivalent of idx / xstride */
+		idx &= xstride - 1;             /* equivalent of idx % xstride */
+
+		y0 = (BN_ULONG)0 - (constant_time_eq_int(i,0)&1);
+		y1 = (BN_ULONG)0 - (constant_time_eq_int(i,1)&1);
+		y2 = (BN_ULONG)0 - (constant_time_eq_int(i,2)&1);
+		y3 = (BN_ULONG)0 - (constant_time_eq_int(i,3)&1);
+
+		for (i = 0; i < top; i++, table += width) {
+		    BN_ULONG acc = 0;
+
+		    for (j = 0; j < xstride; j++) {
+			acc |= ( (table[j + 0 * xstride] & y0) |
+				 (table[j + 1 * xstride] & y1) |
+				 (table[j + 2 * xstride] & y2) |
+				 (table[j + 3 * xstride] & y3) )
+			       & ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1));
+		    }
+
+		    b->d[i] = acc;
+		}
+	}
+	b->top = top;
+	bn_correct_top(b);
+	return 1;
+}
+
+/* Given a pointer value, compute the next address that is a cache line multiple. */
+#define MOD_EXP_CTIME_ALIGN(x_) \
+	((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
+
+/* This variant of BN_mod_exp_mont() uses fixed windows and the special
+ * precomputation memory layout to limit data-dependency to a minimum
+ * to protect secret exponents (cf. the hyper-threading timing attacks
+ * pointed 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,
+    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+	int i, bits, ret = 0, window, wvalue;
+	int top;
+	BN_MONT_CTX *mont = NULL;
+	int numPowers;
+	unsigned char *powerbufFree = NULL;
+	int powerbufLen = 0;
+	unsigned char *powerbuf = NULL;
+	BIGNUM tmp, am;
+
+
+	if (!BN_is_odd(m)) {
+		BNerror(BN_R_CALLED_WITH_EVEN_MODULUS);
+		return (0);
+	}
+
+	top = m->top;
+
+	bits = BN_num_bits(p);
+	if (bits == 0) {
+		/* x**0 mod 1 is still zero. */
+		if (BN_abs_is_word(m, 1)) {
+			ret = 1;
+			BN_zero(rr);
+		} else
+			ret = BN_one(rr);
+		return ret;
+	}
+
+	BN_CTX_start(ctx);
+
+	/*
+	 * Allocate a Montgomery context if it was not supplied by the caller.
+	 * If this is not done, things will break in the montgomery part.
+	 */
+	if (in_mont != NULL)
+		mont = in_mont;
+	else {
+		if ((mont = BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(mont, m, ctx))
+			goto err;
+	}
+
+	/* Get the window size to use with size of p. */
+	window = BN_window_bits_for_ctime_exponent_size(bits);
+#if defined(OPENSSL_BN_ASM_MONT5)
+	if (window == 6 && bits <= 1024)
+		window = 5;	/* ~5% improvement of 2048-bit RSA sign */
+#endif
+
+	/* Allocate a buffer large enough to hold all of the pre-computed
+	 * powers of am, am itself and tmp.
+	 */
+	numPowers = 1 << window;
+	powerbufLen = sizeof(m->d[0]) * (top * numPowers +
+	    ((2*top) > numPowers ? (2*top) : numPowers));
+	if ((powerbufFree = calloc(powerbufLen +
+	    MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH, 1)) == NULL)
+		goto err;
+	powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
+
+	/* lay down tmp and am right after powers table */
+	tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers);
+	am.d = tmp.d + top;
+	tmp.top = am.top = 0;
+	tmp.dmax = am.dmax = top;
+	tmp.neg = am.neg = 0;
+	tmp.flags = am.flags = BN_FLG_STATIC_DATA;
+
+	/* prepare a^0 in Montgomery domain */
+#if 1
+	if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx))
+		goto err;
+#else
+	tmp.d[0] = (0 - m - >d[0]) & BN_MASK2;	/* 2^(top*BN_BITS2) - m */
+	for (i = 1; i < top; i++)
+		tmp.d[i] = (~m->d[i]) & BN_MASK2;
+	tmp.top = top;
+#endif
+
+	/* prepare a^1 in Montgomery domain */
+	if (!BN_nnmod(&am, a, m, ctx))
+		goto err;
+	if (!BN_to_montgomery(&am, &am, mont, ctx))
+		goto err;
+
+#if defined(OPENSSL_BN_ASM_MONT5)
+	/* This optimization uses ideas from http://eprint.iacr.org/2011/239,
+	 * specifically optimization of cache-timing attack countermeasures
+	 * and pre-computation optimization. */
+
+	/* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
+	 * 512-bit RSA is hardly relevant, we omit it to spare size... */
+	if (window == 5 && top > 1) {
+		void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap,
+		    const void *table, const BN_ULONG *np,
+		    const BN_ULONG *n0, int num, int power);
+		void bn_scatter5(const BN_ULONG *inp, size_t num,
+		    void *table, size_t power);
+		void bn_gather5(BN_ULONG *out, size_t num,
+		    void *table, size_t power);
+
+		BN_ULONG *np = mont->N.d, *n0 = mont->n0;
+
+		/* BN_to_montgomery can contaminate words above .top
+		 * [in BN_DEBUG[_DEBUG] build]... */
+		for (i = am.top; i < top; i++)
+			am.d[i] = 0;
+		for (i = tmp.top; i < top; i++)
+			tmp.d[i] = 0;
+
+		bn_scatter5(tmp.d, top, powerbuf, 0);
+		bn_scatter5(am.d, am.top, powerbuf, 1);
+		bn_mul_mont(tmp.d, am.d, am.d, np, n0, top);
+		bn_scatter5(tmp.d, top, powerbuf, 2);
+
+#if 0
+		for (i = 3; i < 32; i++) {
+			/* Calculate a^i = a^(i-1) * a */
+			bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np,
+			    n0, top, i - 1);
+			bn_scatter5(tmp.d, top, powerbuf, i);
+		}
+#else
+		/* same as above, but uses squaring for 1/2 of operations */
+		for (i = 4; i < 32; i*=2) {
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_scatter5(tmp.d, top, powerbuf, i);
+		}
+		for (i = 3; i < 8; i += 2) {
+			int j;
+			bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np,
+			    n0, top, i - 1);
+			bn_scatter5(tmp.d, top, powerbuf, i);
+			for (j = 2 * i; j < 32; j *= 2) {
+				bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+				bn_scatter5(tmp.d, top, powerbuf, j);
+			}
+		}
+		for (; i < 16; i += 2) {
+			bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np,
+			    n0, top, i - 1);
+			bn_scatter5(tmp.d, top, powerbuf, i);
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_scatter5(tmp.d, top, powerbuf, 2*i);
+		}
+		for (; i < 32; i += 2) {
+			bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np,
+			    n0, top, i - 1);
+			bn_scatter5(tmp.d, top, powerbuf, i);
+		}
+#endif
+		bits--;
+		for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--)
+			wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+		bn_gather5(tmp.d, top, powerbuf, wvalue);
+
+		/* Scan the exponent one window at a time starting from the most
+		 * significant bits.
+		 */
+		while (bits >= 0) {
+			for (wvalue = 0, i = 0; i < 5; i++, bits--)
+				wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
+			bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
+		}
+
+		tmp.top = top;
+		bn_correct_top(&tmp);
+	} else
+#endif
+	{
+		if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0,
+		    window))
+			goto err;
+		if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am,  top, powerbuf, 1,
+		    window))
+			goto err;
+
+		/* If the window size is greater than 1, then calculate
+		 * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
+		 * (even powers could instead be computed as (a^(i/2))^2
+		 * to use the slight performance advantage of sqr over mul).
+		 */
+		if (window > 1) {
+			if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx))
+				goto err;
+			if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf,
+			    2, window))
+				goto err;
+			for (i = 3; i < numPowers; i++) {
+				/* Calculate a^i = a^(i-1) * a */
+				if (!BN_mod_mul_montgomery(&tmp, &am, &tmp,
+				    mont, ctx))
+					goto err;
+				if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top,
+				    powerbuf, i, window))
+					goto err;
+			}
+		}
+
+		bits--;
+		for (wvalue = 0, i = bits % window; i >= 0; i--, bits--)
+			wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+		if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf,
+		    wvalue, window))
+			goto err;
+
+		/* Scan the exponent one window at a time starting from the most
+		 * significant bits.
+		 */
+		while (bits >= 0) {
+			wvalue = 0; /* The 'value' of the window */
+
+			/* Scan the window, squaring the result as we go */
+			for (i = 0; i < window; i++, bits--) {
+				if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp,
+				    mont, ctx))
+					goto err;
+				wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
+			}
+
+			/* Fetch the appropriate pre-computed value from the pre-buf */
+			if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf,
+			    wvalue, window))
+				goto err;
+
+			/* Multiply the result into the intermediate result */
+			if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx))
+				goto err;
+		}
+	}
+
+	/* Convert the final result from montgomery to standard format */
+	if (!BN_from_montgomery(rr, &tmp, mont, ctx))
+		goto err;
+	ret = 1;
+
+err:
+	if ((in_mont == NULL) && (mont != NULL))
+		BN_MONT_CTX_free(mont);
+	freezero(powerbufFree, powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_mod_exp_mont_consttime);
+
+static int
+BN_mod_exp_mont_internal(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx, BN_MONT_CTX *in_mont, int ct)
+{
+	int i, j, bits, ret = 0, wstart, wend, window, wvalue;
+	int start = 1;
+	BIGNUM *d, *r;
+	const BIGNUM *aa;
+	/* Table of variables obtained from 'ctx' */
+	BIGNUM *val[TABLE_SIZE];
+	BN_MONT_CTX *mont = NULL;
+
+	if (ct) {
+		return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
+	}
+
+
+	if (!BN_is_odd(m)) {
+		BNerror(BN_R_CALLED_WITH_EVEN_MODULUS);
+		return (0);
+	}
+
+	bits = BN_num_bits(p);
+	if (bits == 0) {
+		/* x**0 mod 1 is still zero. */
+		if (BN_abs_is_word(m, 1)) {
+			ret = 1;
+			BN_zero(rr);
+		} else
+			ret = BN_one(rr);
+		return ret;
+	}
+
+	BN_CTX_start(ctx);
+	if ((d = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((val[0] = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* If this is not done, things will break in the montgomery
+	 * part */
+
+	if (in_mont != NULL)
+		mont = in_mont;
+	else {
+		if ((mont = BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(mont, m, ctx))
+			goto err;
+	}
+
+	if (!BN_nnmod(val[0], a,m, ctx))
+		goto err;
+	aa = val[0];
+	if (BN_is_zero(aa)) {
+		BN_zero(rr);
+		ret = 1;
+		goto err;
+	}
+	if (!BN_to_montgomery(val[0], aa, mont, ctx))
+		goto err; /* 1 */
+
+	window = BN_window_bits_for_exponent_size(bits);
+	if (window > 1) {
+		if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx))
+			goto err; /* 2 */
+		j = 1 << (window - 1);
+		for (i = 1; i < j; i++) {
+			if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
+			    !BN_mod_mul_montgomery(val[i], val[i - 1],
+			    d, mont, ctx))
+				goto err;
+		}
+	}
+
+	start = 1;		/* This is used to avoid multiplication etc
+				 * when there is only the value '1' in the
+				 * buffer. */
+	wvalue = 0;		/* The 'value' of the window */
+	wstart = bits - 1;	/* The top bit of the window */
+	wend = 0;		/* The bottom bit of the window */
+
+	if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
+		goto err;
+	for (;;) {
+		if (BN_is_bit_set(p, wstart) == 0) {
+			if (!start) {
+				if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
+					goto err;
+			}
+			if (wstart == 0)
+				break;
+			wstart--;
+			continue;
+		}
+		/* We now have wstart on a 'set' bit, we now need to work out
+		 * how bit 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++) {
+			if (wstart - i < 0)
+				break;
+			if (BN_is_bit_set(p, wstart - i)) {
+				wvalue <<= (i - wend);
+				wvalue |= 1;
+				wend = i;
+			}
+		}
+
+		/* wend is the size of the current window */
+		j = wend + 1;
+		/* add the 'bytes above' */
+		if (!start)
+			for (i = 0; i < j; i++) {
+				if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
+					goto err;
+			}
+
+		/* wvalue will be an odd number < 2^window */
+		if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx))
+			goto err;
+
+		/* move the 'window' down further */
+		wstart -= wend + 1;
+		wvalue = 0;
+		start = 0;
+		if (wstart < 0)
+			break;
+	}
+	if (!BN_from_montgomery(rr, r,mont, ctx))
+		goto err;
+	ret = 1;
+
+err:
+	if ((in_mont == NULL) && (mont != NULL))
+		BN_MONT_CTX_free(mont);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+int
+BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+	return BN_mod_exp_mont_internal(rr, a, p, m, ctx, in_mont,
+	    (BN_get_flags(p, BN_FLG_CONSTTIME) != 0));
+}
+
+int
+BN_mod_exp_mont_ct(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+	return BN_mod_exp_mont_internal(rr, a, p, m, ctx, in_mont, 1);
+}
+
+int
+BN_mod_exp_mont_nonct(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+	return BN_mod_exp_mont_internal(rr, a, p, m, ctx, in_mont, 0);
+}
+
+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)
+{
+	BN_MONT_CTX *mont = NULL;
+	int b, bits, ret = 0;
+	int r_is_one;
+	BN_ULONG w, next_w;
+	BIGNUM *d, *r, *t;
+	BIGNUM *swap_tmp;
+
+#define BN_MOD_MUL_WORD(r, w, m) \
+		(BN_mul_word(r, (w)) && \
+		(/* BN_ucmp(r, (m)) < 0 ? 1 :*/  \
+			(BN_mod_ct(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
+		/* BN_MOD_MUL_WORD is only used with 'w' large,
+		 * so the BN_ucmp test is probably more overhead
+		 * than always using BN_mod (which uses bn_copy if
+		 * a similar test returns true). */
+		/* We can use BN_mod and do not need BN_nnmod because our
+		 * accumulator is never negative (the result of BN_mod does
+		 * not depend on the sign of the modulus).
+		 */
+#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
+		(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
+
+	if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
+		/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+	}
+
+
+	if (!BN_is_odd(m)) {
+		BNerror(BN_R_CALLED_WITH_EVEN_MODULUS);
+		return (0);
+	}
+	if (m->top == 1)
+		a %= m->d[0]; /* make sure that 'a' is reduced */
+
+	bits = BN_num_bits(p);
+	if (bits == 0) {
+		/* x**0 mod 1 is still zero. */
+		if (BN_abs_is_word(m, 1)) {
+			ret = 1;
+			BN_zero(rr);
+		} else
+			ret = BN_one(rr);
+		return ret;
+	}
+	if (a == 0) {
+		BN_zero(rr);
+		ret = 1;
+		return ret;
+	}
+
+	BN_CTX_start(ctx);
+	if ((d = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((t = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (in_mont != NULL)
+		mont = in_mont;
+	else {
+		if ((mont = BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(mont, m, ctx))
+			goto err;
+	}
+
+	r_is_one = 1; /* except for Montgomery factor */
+
+	/* bits-1 >= 0 */
+
+	/* The result is accumulated in the product r*w. */
+	w = a; /* bit 'bits-1' of 'p' is always set */
+	for (b = bits - 2; b >= 0; b--) {
+		/* First, square r*w. */
+		next_w = w * w;
+		if ((next_w / w) != w) /* overflow */
+		{
+			if (r_is_one) {
+				if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
+					goto err;
+				r_is_one = 0;
+			} else {
+				if (!BN_MOD_MUL_WORD(r, w, m))
+					goto err;
+			}
+			next_w = 1;
+		}
+		w = next_w;
+		if (!r_is_one) {
+			if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
+				goto err;
+		}
+
+		/* Second, multiply r*w by 'a' if exponent bit is set. */
+		if (BN_is_bit_set(p, b)) {
+			next_w = w * a;
+			if ((next_w / a) != w) /* overflow */
+			{
+				if (r_is_one) {
+					if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
+						goto err;
+					r_is_one = 0;
+				} else {
+					if (!BN_MOD_MUL_WORD(r, w, m))
+						goto err;
+				}
+				next_w = a;
+			}
+			w = next_w;
+		}
+	}
+
+	/* Finally, set r:=r*w. */
+	if (w != 1) {
+		if (r_is_one) {
+			if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
+				goto err;
+			r_is_one = 0;
+		} else {
+			if (!BN_MOD_MUL_WORD(r, w, m))
+				goto err;
+		}
+	}
+
+	if (r_is_one) /* can happen only if a == 1*/
+	{
+		if (!BN_one(rr))
+			goto err;
+	} else {
+		if (!BN_from_montgomery(rr, r, mont, ctx))
+			goto err;
+	}
+	ret = 1;
+
+err:
+	if ((in_mont == NULL) && (mont != NULL))
+		BN_MONT_CTX_free(mont);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_mod_exp_mont_word);
+
+int
+BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	int i, j, bits, ret = 0, wstart, wend, window, wvalue;
+	int start = 1;
+	BIGNUM *aa;
+	/* Table of variables obtained from 'ctx' */
+	BIGNUM *val[TABLE_SIZE];
+	BN_RECP_CTX recp;
+
+	if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
+		/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
+		BNerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return -1;
+	}
+
+	bits = BN_num_bits(p);
+	if (bits == 0) {
+		/* x**0 mod 1 is still zero. */
+		if (BN_abs_is_word(m, 1)) {
+			ret = 1;
+			BN_zero(r);
+		} else
+			ret = BN_one(r);
+		return ret;
+	}
+
+	BN_RECP_CTX_init(&recp);
+
+	BN_CTX_start(ctx);
+	if ((aa = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((val[0] = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (m->neg) {
+		/* ignore sign of 'm' */
+		if (!bn_copy(aa, m))
+			goto err;
+		aa->neg = 0;
+		if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0)
+			goto err;
+	} else {
+		if (BN_RECP_CTX_set(&recp, m, ctx) <= 0)
+			goto err;
+	}
+
+	if (!BN_nnmod(val[0], a, m, ctx))
+		goto err;		/* 1 */
+	if (BN_is_zero(val[0])) {
+		BN_zero(r);
+		ret = 1;
+		goto err;
+	}
+
+	window = BN_window_bits_for_exponent_size(bits);
+	if (window > 1) {
+		if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx))
+			goto err;				/* 2 */
+		j = 1 << (window - 1);
+		for (i = 1; i < j; i++) {
+			if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
+			    !BN_mod_mul_reciprocal(val[i], val[i - 1],
+			    aa, &recp, ctx))
+				goto err;
+		}
+	}
+
+	start = 1;		/* This is used to avoid multiplication etc
+				 * when there is only the value '1' in the
+				 * buffer. */
+	wvalue = 0;		/* The 'value' of the window */
+	wstart = bits - 1;	/* The top bit of the window */
+	wend = 0;		/* The bottom bit of the window */
+
+	if (!BN_one(r))
+		goto err;
+
+	for (;;) {
+		if (BN_is_bit_set(p, wstart) == 0) {
+			if (!start)
+				if (!BN_mod_mul_reciprocal(r, r,r, &recp, ctx))
+					goto err;
+			if (wstart == 0)
+				break;
+			wstart--;
+			continue;
+		}
+		/* We now have wstart on a 'set' bit, we now need to work out
+		 * how bit 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++) {
+			if (wstart - i < 0)
+				break;
+			if (BN_is_bit_set(p, wstart - i)) {
+				wvalue <<= (i - wend);
+				wvalue |= 1;
+				wend = i;
+			}
+		}
+
+		/* wend is the size of the current window */
+		j = wend + 1;
+		/* add the 'bytes above' */
+		if (!start)
+			for (i = 0; i < j; i++) {
+				if (!BN_mod_mul_reciprocal(r, r,r, &recp, ctx))
+					goto err;
+			}
+
+		/* wvalue will be an odd number < 2^window */
+		if (!BN_mod_mul_reciprocal(r, r,val[wvalue >> 1], &recp, ctx))
+			goto err;
+
+		/* move the 'window' down further */
+		wstart -= wend + 1;
+		wvalue = 0;
+		start = 0;
+		if (wstart < 0)
+			break;
+	}
+	ret = 1;
+
+err:
+	BN_CTX_end(ctx);
+	BN_RECP_CTX_free(&recp);
+	return (ret);
+}
+
+static int
+BN_mod_exp_internal(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx, int ct)
+{
+	int ret;
+
+
+	/* For even modulus  m = 2^k*m_odd,  it might make sense to compute
+	 * a^p mod m_odd  and  a^p mod 2^k  separately (with Montgomery
+	 * exponentiation for the odd part), using appropriate exponent
+	 * reductions, and combine the results using the CRT.
+	 *
+	 * For now, we use Montgomery only if the modulus is odd; otherwise,
+	 * exponentiation using the reciprocal-based quick remaindering
+	 * algorithm is used.
+	 *
+	 * (Timing obtained with expspeed.c [computations  a^p mod m
+	 * where  a, p, m  are of the same length: 256, 512, 1024, 2048,
+	 * 4096, 8192 bits], compared to the running time of the
+	 * standard algorithm:
+	 *
+	 *   BN_mod_exp_mont   33 .. 40 %  [AMD K6-2, Linux, debug configuration]
+	 *                     55 .. 77 %  [UltraSparc processor, but
+	 *                                  debug-solaris-sparcv8-gcc conf.]
+	 *
+	 *   BN_mod_exp_recp   50 .. 70 %  [AMD K6-2, Linux, debug configuration]
+	 *                     62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
+	 *
+	 * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
+	 * at 2048 and more bits, but at 512 and 1024 bits, it was
+	 * slower even than the standard algorithm!
+	 *
+	 * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
+	 * should be obtained when the new Montgomery reduction code
+	 * has been integrated into OpenSSL.)
+	 */
+
+	if (BN_is_odd(m)) {
+		if (a->top == 1 && !a->neg && !ct) {
+			BN_ULONG A = a->d[0];
+			ret = BN_mod_exp_mont_word(r, A,p, m,ctx, NULL);
+		} else
+			ret = BN_mod_exp_mont_ct(r, a,p, m,ctx, NULL);
+	} else	{
+		ret = BN_mod_exp_recp(r, a,p, m, ctx);
+	}
+
+	return (ret);
+}
+
+int
+BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	return BN_mod_exp_internal(r, a, p, m, ctx,
+	    (BN_get_flags(p, BN_FLG_CONSTTIME) != 0));
+}
+
+int
+BN_mod_exp_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	return BN_mod_exp_internal(r, a, p, m, ctx, 1);
+}
+
+int
+BN_mod_exp_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	return BN_mod_exp_internal(r, a, p, m, ctx, 0);
+}
+
+int
+BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
+    const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, BN_CTX *ctx,
+    BN_MONT_CTX *in_mont)
+{
+	int i, j, bits, b, bits1, bits2, ret = 0, wpos1, wpos2, window1, window2, wvalue1, wvalue2;
+	int r_is_one = 1;
+	BIGNUM *d, *r;
+	const BIGNUM *a_mod_m;
+	/* Tables of variables obtained from 'ctx' */
+	BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];
+	BN_MONT_CTX *mont = NULL;
+
+
+	if (!BN_is_odd(m)) {
+		BNerror(BN_R_CALLED_WITH_EVEN_MODULUS);
+		return (0);
+	}
+	bits1 = BN_num_bits(p1);
+	bits2 = BN_num_bits(p2);
+	if ((bits1 == 0) && (bits2 == 0)) {
+		ret = BN_one(rr);
+		return ret;
+	}
+
+	bits = (bits1 > bits2) ? bits1 : bits2;
+
+	BN_CTX_start(ctx);
+	if ((d = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((val1[0] = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((val2[0] = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (in_mont != NULL)
+		mont = in_mont;
+	else {
+		if ((mont = BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(mont, m, ctx))
+			goto err;
+	}
+
+	window1 = BN_window_bits_for_exponent_size(bits1);
+	window2 = BN_window_bits_for_exponent_size(bits2);
+
+	/*
+	 * Build table for a1:   val1[i] := a1^(2*i + 1) mod m  for i = 0 .. 2^(window1-1)
+	 */
+	if (!BN_nnmod(val1[0], a1, m, ctx))
+		goto err;
+	a_mod_m = val1[0];
+	if (BN_is_zero(a_mod_m)) {
+		BN_zero(rr);
+		ret = 1;
+		goto err;
+	}
+
+	if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx))
+		goto err;
+	if (window1 > 1) {
+		if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx))
+			goto err;
+
+		j = 1 << (window1 - 1);
+		for (i = 1; i < j; i++) {
+			if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||
+			    !BN_mod_mul_montgomery(val1[i], val1[i - 1],
+			    d, mont, ctx))
+				goto err;
+		}
+	}
+
+
+	/*
+	 * Build table for a2:   val2[i] := a2^(2*i + 1) mod m  for i = 0 .. 2^(window2-1)
+	 */
+	if (!BN_nnmod(val2[0], a2, m, ctx))
+		goto err;
+	a_mod_m = val2[0];
+	if (BN_is_zero(a_mod_m)) {
+		BN_zero(rr);
+		ret = 1;
+		goto err;
+	}
+	if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx))
+		goto err;
+	if (window2 > 1) {
+		if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx))
+			goto err;
+
+		j = 1 << (window2 - 1);
+		for (i = 1; i < j; i++) {
+			if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||
+			    !BN_mod_mul_montgomery(val2[i], val2[i - 1],
+			    d, mont, ctx))
+				goto err;
+		}
+	}
+
+
+	/* Now compute the power product, using independent windows. */
+	r_is_one = 1;
+	wvalue1 = 0;  /* The 'value' of the first window */
+	wvalue2 = 0;  /* The 'value' of the second window */
+	wpos1 = 0;    /* If wvalue1 > 0, the bottom bit of the first window */
+	wpos2 = 0;    /* If wvalue2 > 0, the bottom bit of the second window */
+
+	if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
+		goto err;
+	for (b = bits - 1; b >= 0; b--) {
+		if (!r_is_one) {
+			if (!BN_mod_mul_montgomery(r, r,r, mont, ctx))
+				goto err;
+		}
+
+		if (!wvalue1)
+			if (BN_is_bit_set(p1, b)) {
+			/* consider bits b-window1+1 .. b for this window */
+			i = b - window1 + 1;
+			while (!BN_is_bit_set(p1, i)) /* works for i<0 */
+				i++;
+			wpos1 = i;
+			wvalue1 = 1;
+			for (i = b - 1; i >= wpos1; i--) {
+				wvalue1 <<= 1;
+				if (BN_is_bit_set(p1, i))
+					wvalue1++;
+			}
+		}
+
+		if (!wvalue2)
+			if (BN_is_bit_set(p2, b)) {
+			/* consider bits b-window2+1 .. b for this window */
+			i = b - window2 + 1;
+			while (!BN_is_bit_set(p2, i))
+				i++;
+			wpos2 = i;
+			wvalue2 = 1;
+			for (i = b - 1; i >= wpos2; i--) {
+				wvalue2 <<= 1;
+				if (BN_is_bit_set(p2, i))
+					wvalue2++;
+			}
+		}
+
+		if (wvalue1 && b == wpos1) {
+			/* wvalue1 is odd and < 2^window1 */
+			if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1],
+			    mont, ctx))
+				goto err;
+			wvalue1 = 0;
+			r_is_one = 0;
+		}
+
+		if (wvalue2 && b == wpos2) {
+			/* wvalue2 is odd and < 2^window2 */
+			if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1],
+			    mont, ctx))
+				goto err;
+			wvalue2 = 0;
+			r_is_one = 0;
+		}
+	}
+	if (!BN_from_montgomery(rr, r,mont, ctx))
+		goto err;
+	ret = 1;
+
+err:
+	if ((in_mont == NULL) && (mont != NULL))
+		BN_MONT_CTX_free(mont);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_mod_exp2_mont);
diff --git a/crypto/bn/bn_gcd.c b/crypto/bn/bn_gcd.c
new file mode 100644
index 0000000..6b3d8a3
--- /dev/null
+++ b/crypto/bn/bn_gcd.c
@@ -0,0 +1,822 @@
+/* $OpenBSD: bn_gcd.c,v 1.28 2023/06/02 17:15:30 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include "bn_local.h"
+
+static BIGNUM *
+euclid(BIGNUM *a, BIGNUM *b)
+{
+	BIGNUM *t;
+	int shifts = 0;
+
+	/* Loop invariant: 0 <= b <= a. */
+	while (!BN_is_zero(b)) {
+		if (BN_is_odd(a) && BN_is_odd(b)) {
+			if (!BN_sub(a, a, b))
+				goto err;
+			if (!BN_rshift1(a, a))
+				goto err;
+		} else if (BN_is_odd(a) && !BN_is_odd(b)) {
+			if (!BN_rshift1(b, b))
+				goto err;
+		} else if (!BN_is_odd(a) && BN_is_odd(b)) {
+			if (!BN_rshift1(a, a))
+				goto err;
+		} else {
+			if (!BN_rshift1(a, a))
+				goto err;
+			if (!BN_rshift1(b, b))
+				goto err;
+			shifts++;
+			continue;
+		}
+
+		if (BN_cmp(a, b) < 0) {
+			t = a;
+			a = b;
+			b = t;
+		}
+	}
+
+	if (shifts) {
+		if (!BN_lshift(a, a, shifts))
+			goto err;
+	}
+
+	return a;
+
+ err:
+	return NULL;
+}
+
+int
+BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
+{
+	BIGNUM *a, *b, *t;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!bn_copy(a, in_a))
+		goto err;
+	if (!bn_copy(b, in_b))
+		goto err;
+	a->neg = 0;
+	b->neg = 0;
+
+	if (BN_cmp(a, b) < 0) {
+		t = a;
+		a = b;
+		b = t;
+	}
+	t = euclid(a, b);
+	if (t == NULL)
+		goto err;
+
+	if (!bn_copy(r, t))
+		goto err;
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+int
+BN_gcd_nonct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
+{
+	return BN_gcd(r, in_a, in_b, ctx);
+}
+
+/*
+ * BN_gcd_no_branch is a special version of BN_mod_inverse_no_branch.
+ * that returns the GCD.
+ */
+static BIGNUM *
+BN_gcd_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
+    BN_CTX *ctx)
+{
+	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
+	BIGNUM local_A, local_B;
+	BIGNUM *pA, *pB;
+	BIGNUM *ret = NULL;
+	int sign;
+
+	if (in == NULL)
+		goto err;
+	R = in;
+
+	BN_init(&local_A);
+	BN_init(&local_B);
+
+	BN_CTX_start(ctx);
+	if ((A = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((B = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((D = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((M = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((T = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_one(X))
+		goto err;
+	BN_zero(Y);
+	if (!bn_copy(B, a))
+		goto err;
+	if (!bn_copy(A, n))
+		goto err;
+	A->neg = 0;
+
+	if (B->neg || (BN_ucmp(B, A) >= 0)) {
+		/*
+		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+		 * BN_div_no_branch will be called eventually.
+		 */
+		pB = &local_B;
+		/* BN_init() done at the top of the function. */
+		BN_with_flags(pB, B, BN_FLG_CONSTTIME);
+		if (!BN_nnmod(B, pB, A, ctx))
+			goto err;
+	}
+	sign = -1;
+	/* From  B = a mod |n|,  A = |n|  it follows that
+	 *
+	 *      0 <= B < A,
+	 *     -sign*X*a  ==  B   (mod |n|),
+	 *      sign*Y*a  ==  A   (mod |n|).
+	 */
+
+	while (!BN_is_zero(B)) {
+		BIGNUM *tmp;
+
+		/*
+		 *      0 < B < A,
+		 * (*) -sign*X*a  ==  B   (mod |n|),
+		 *      sign*Y*a  ==  A   (mod |n|)
+		 */
+
+		/*
+		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+		 * BN_div_no_branch will be called eventually.
+		 */
+		pA = &local_A;
+		/* BN_init() done at the top of the function. */
+		BN_with_flags(pA, A, BN_FLG_CONSTTIME);
+
+		/* (D, M) := (A/B, A%B) ... */
+		if (!BN_div_ct(D, M, pA, B, ctx))
+			goto err;
+
+		/* Now
+		 *      A = D*B + M;
+		 * thus we have
+		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
+		 */
+		tmp = A; /* keep the BIGNUM object, the value does not matter */
+
+		/* (A, B) := (B, A mod B) ... */
+		A = B;
+		B = M;
+		/* ... so we have  0 <= B < A  again */
+
+		/* Since the former  M  is now  B  and the former  B  is now  A,
+		 * (**) translates into
+		 *       sign*Y*a  ==  D*A + B    (mod |n|),
+		 * i.e.
+		 *       sign*Y*a - D*A  ==  B    (mod |n|).
+		 * Similarly, (*) translates into
+		 *      -sign*X*a  ==  A          (mod |n|).
+		 *
+		 * Thus,
+		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
+		 * i.e.
+		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
+		 *
+		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
+		 *      -sign*X*a  ==  B   (mod |n|),
+		 *       sign*Y*a  ==  A   (mod |n|).
+		 * Note that  X  and  Y  stay non-negative all the time.
+		 */
+
+		if (!BN_mul(tmp, D, X, ctx))
+			goto err;
+		if (!BN_add(tmp, tmp, Y))
+			goto err;
+
+		M = Y; /* keep the BIGNUM object, the value does not matter */
+		Y = X;
+		X = tmp;
+		sign = -sign;
+	}
+
+	/*
+	 * The while loop (Euclid's algorithm) ends when
+	 *      A == gcd(a,n);
+	 */
+
+	if (!bn_copy(R, A))
+		goto err;
+	ret = R;
+ err:
+	if ((ret == NULL) && (in == NULL))
+		BN_free(R);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+int
+BN_gcd_ct(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
+{
+	if (BN_gcd_no_branch(r, in_a, in_b, ctx) == NULL)
+		return 0;
+	return 1;
+}
+
+/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse.
+ * It does not contain branches that may leak sensitive information.
+ */
+static BIGNUM *
+BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n,
+    BN_CTX *ctx)
+{
+	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
+	BIGNUM local_A, local_B;
+	BIGNUM *pA, *pB;
+	BIGNUM *ret = NULL;
+	int sign;
+
+	BN_init(&local_A);
+	BN_init(&local_B);
+
+	BN_CTX_start(ctx);
+	if ((A = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((B = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((D = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((M = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((T = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (in == NULL)
+		R = BN_new();
+	else
+		R = in;
+	if (R == NULL)
+		goto err;
+
+	if (!BN_one(X))
+		goto err;
+	BN_zero(Y);
+	if (!bn_copy(B, a))
+		goto err;
+	if (!bn_copy(A, n))
+		goto err;
+	A->neg = 0;
+
+	if (B->neg || (BN_ucmp(B, A) >= 0)) {
+		/*
+		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+		 * BN_div_no_branch will be called eventually.
+		 */
+		pB = &local_B;
+		/* BN_init() done at the top of the function. */
+		BN_with_flags(pB, B, BN_FLG_CONSTTIME);
+		if (!BN_nnmod(B, pB, A, ctx))
+			goto err;
+	}
+	sign = -1;
+	/* From  B = a mod |n|,  A = |n|  it follows that
+	 *
+	 *      0 <= B < A,
+	 *     -sign*X*a  ==  B   (mod |n|),
+	 *      sign*Y*a  ==  A   (mod |n|).
+	 */
+
+	while (!BN_is_zero(B)) {
+		BIGNUM *tmp;
+
+		/*
+		 *      0 < B < A,
+		 * (*) -sign*X*a  ==  B   (mod |n|),
+		 *      sign*Y*a  ==  A   (mod |n|)
+		 */
+
+		/*
+		 * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
+		 * BN_div_no_branch will be called eventually.
+		 */
+		pA = &local_A;
+		/* BN_init() done at the top of the function. */
+		BN_with_flags(pA, A, BN_FLG_CONSTTIME);
+
+		/* (D, M) := (A/B, A%B) ... */
+		if (!BN_div_ct(D, M, pA, B, ctx))
+			goto err;
+
+		/* Now
+		 *      A = D*B + M;
+		 * thus we have
+		 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
+		 */
+		tmp = A; /* keep the BIGNUM object, the value does not matter */
+
+		/* (A, B) := (B, A mod B) ... */
+		A = B;
+		B = M;
+		/* ... so we have  0 <= B < A  again */
+
+		/* Since the former  M  is now  B  and the former  B  is now  A,
+		 * (**) translates into
+		 *       sign*Y*a  ==  D*A + B    (mod |n|),
+		 * i.e.
+		 *       sign*Y*a - D*A  ==  B    (mod |n|).
+		 * Similarly, (*) translates into
+		 *      -sign*X*a  ==  A          (mod |n|).
+		 *
+		 * Thus,
+		 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
+		 * i.e.
+		 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
+		 *
+		 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
+		 *      -sign*X*a  ==  B   (mod |n|),
+		 *       sign*Y*a  ==  A   (mod |n|).
+		 * Note that  X  and  Y  stay non-negative all the time.
+		 */
+
+		if (!BN_mul(tmp, D, X, ctx))
+			goto err;
+		if (!BN_add(tmp, tmp, Y))
+			goto err;
+
+		M = Y; /* keep the BIGNUM object, the value does not matter */
+		Y = X;
+		X = tmp;
+		sign = -sign;
+	}
+
+	/*
+	 * The while loop (Euclid's algorithm) ends when
+	 *      A == gcd(a,n);
+	 * we have
+	 *       sign*Y*a  ==  A  (mod |n|),
+	 * where  Y  is non-negative.
+	 */
+
+	if (sign < 0) {
+		if (!BN_sub(Y, n, Y))
+			goto err;
+	}
+	/* Now  Y*a  ==  A  (mod |n|).  */
+
+	if (!BN_is_one(A)) {
+		BNerror(BN_R_NO_INVERSE);
+		goto err;
+	}
+
+	if (!BN_nnmod(Y, Y, n, ctx))
+		goto err;
+	if (!bn_copy(R, Y))
+		goto err;
+
+	ret = R;
+
+ err:
+	if ((ret == NULL) && (in == NULL))
+		BN_free(R);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+/* solves ax == 1 (mod n) */
+static BIGNUM *
+BN_mod_inverse_internal(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx,
+    int ct)
+{
+	BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
+	BIGNUM *ret = NULL;
+	int sign;
+
+	if (ct)
+		return BN_mod_inverse_no_branch(in, a, n, ctx);
+
+	BN_CTX_start(ctx);
+	if ((A = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((B = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((D = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((M = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((T = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (in == NULL)
+		R = BN_new();
+	else
+		R = in;
+	if (R == NULL)
+		goto err;
+
+	if (!BN_one(X))
+		goto err;
+	BN_zero(Y);
+	if (!bn_copy(B, a))
+		goto err;
+	if (!bn_copy(A, n))
+		goto err;
+	A->neg = 0;
+	if (B->neg || (BN_ucmp(B, A) >= 0)) {
+		if (!BN_nnmod(B, B, A, ctx))
+			goto err;
+	}
+	sign = -1;
+	/* From  B = a mod |n|,  A = |n|  it follows that
+	 *
+	 *      0 <= B < A,
+	 *     -sign*X*a  ==  B   (mod |n|),
+	 *      sign*Y*a  ==  A   (mod |n|).
+	 */
+
+	if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) {
+		/* Binary inversion algorithm; requires odd modulus.
+		 * This is faster than the general algorithm if the modulus
+		 * is sufficiently small (about 400 .. 500 bits on 32-bit
+		 * systems, but much more on 64-bit systems) */
+		int shift;
+
+		while (!BN_is_zero(B)) {
+			/*
+			 *      0 < B < |n|,
+			 *      0 < A <= |n|,
+			 * (1) -sign*X*a  ==  B   (mod |n|),
+			 * (2)  sign*Y*a  ==  A   (mod |n|)
+			 */
+
+			/* Now divide  B  by the maximum possible power of two in the integers,
+			 * and divide  X  by the same value mod |n|.
+			 * When we're done, (1) still holds. */
+			shift = 0;
+			while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
+			{
+				shift++;
+
+				if (BN_is_odd(X)) {
+					if (!BN_uadd(X, X, n))
+						goto err;
+				}
+				/* now X is even, so we can easily divide it by two */
+				if (!BN_rshift1(X, X))
+					goto err;
+			}
+			if (shift > 0) {
+				if (!BN_rshift(B, B, shift))
+					goto err;
+			}
+
+			/* Same for  A  and  Y.  Afterwards, (2) still holds. */
+			shift = 0;
+			while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
+			{
+				shift++;
+
+				if (BN_is_odd(Y)) {
+					if (!BN_uadd(Y, Y, n))
+						goto err;
+				}
+				/* now Y is even */
+				if (!BN_rshift1(Y, Y))
+					goto err;
+			}
+			if (shift > 0) {
+				if (!BN_rshift(A, A, shift))
+					goto err;
+			}
+
+			/* We still have (1) and (2).
+			 * Both  A  and  B  are odd.
+			 * The following computations ensure that
+			 *
+			 *     0 <= B < |n|,
+			 *      0 < A < |n|,
+			 * (1) -sign*X*a  ==  B   (mod |n|),
+			 * (2)  sign*Y*a  ==  A   (mod |n|),
+			 *
+			 * and that either  A  or  B  is even in the next iteration.
+			 */
+			if (BN_ucmp(B, A) >= 0) {
+				/* -sign*(X + Y)*a == B - A  (mod |n|) */
+				if (!BN_uadd(X, X, Y))
+					goto err;
+				/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
+				 * actually makes the algorithm slower */
+				if (!BN_usub(B, B, A))
+					goto err;
+			} else {
+				/*  sign*(X + Y)*a == A - B  (mod |n|) */
+				if (!BN_uadd(Y, Y, X))
+					goto err;
+				/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
+				if (!BN_usub(A, A, B))
+					goto err;
+			}
+		}
+	} else {
+		/* general inversion algorithm */
+
+		while (!BN_is_zero(B)) {
+			BIGNUM *tmp;
+
+			/*
+			 *      0 < B < A,
+			 * (*) -sign*X*a  ==  B   (mod |n|),
+			 *      sign*Y*a  ==  A   (mod |n|)
+			 */
+
+			/* (D, M) := (A/B, A%B) ... */
+			if (BN_num_bits(A) == BN_num_bits(B)) {
+				if (!BN_one(D))
+					goto err;
+				if (!BN_sub(M, A, B))
+					goto err;
+			} else if (BN_num_bits(A) == BN_num_bits(B) + 1) {
+				/* A/B is 1, 2, or 3 */
+				if (!BN_lshift1(T, B))
+					goto err;
+				if (BN_ucmp(A, T) < 0) {
+					/* A < 2*B, so D=1 */
+					if (!BN_one(D))
+						goto err;
+					if (!BN_sub(M, A, B))
+						goto err;
+				} else {
+					/* A >= 2*B, so D=2 or D=3 */
+					if (!BN_sub(M, A, T))
+						goto err;
+					if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
+						if (BN_ucmp(A, D) < 0) {
+						/* A < 3*B, so D=2 */
+						if (!BN_set_word(D, 2))
+							goto err;
+						/* M (= A - 2*B) already has the correct value */
+					} else {
+						/* only D=3 remains */
+						if (!BN_set_word(D, 3))
+							goto err;
+						/* currently  M = A - 2*B,  but we need  M = A - 3*B */
+						if (!BN_sub(M, M, B))
+							goto err;
+					}
+				}
+			} else {
+				if (!BN_div_nonct(D, M, A, B, ctx))
+					goto err;
+			}
+
+			/* Now
+			 *      A = D*B + M;
+			 * thus we have
+			 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
+			 */
+			tmp = A; /* keep the BIGNUM object, the value does not matter */
+
+			/* (A, B) := (B, A mod B) ... */
+			A = B;
+			B = M;
+			/* ... so we have  0 <= B < A  again */
+
+			/* Since the former  M  is now  B  and the former  B  is now  A,
+			 * (**) translates into
+			 *       sign*Y*a  ==  D*A + B    (mod |n|),
+			 * i.e.
+			 *       sign*Y*a - D*A  ==  B    (mod |n|).
+			 * Similarly, (*) translates into
+			 *      -sign*X*a  ==  A          (mod |n|).
+			 *
+			 * Thus,
+			 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
+			 * i.e.
+			 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
+			 *
+			 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
+			 *      -sign*X*a  ==  B   (mod |n|),
+			 *       sign*Y*a  ==  A   (mod |n|).
+			 * Note that  X  and  Y  stay non-negative all the time.
+			 */
+
+			/* most of the time D is very small, so we can optimize tmp := D*X+Y */
+			if (BN_is_one(D)) {
+				if (!BN_add(tmp, X, Y))
+					goto err;
+			} else {
+				if (BN_is_word(D, 2)) {
+					if (!BN_lshift1(tmp, X))
+						goto err;
+				} else if (BN_is_word(D, 4)) {
+					if (!BN_lshift(tmp, X, 2))
+						goto err;
+				} else if (D->top == 1) {
+					if (!bn_copy(tmp, X))
+						goto err;
+					if (!BN_mul_word(tmp, D->d[0]))
+						goto err;
+				} else {
+					if (!BN_mul(tmp, D,X, ctx))
+						goto err;
+				}
+				if (!BN_add(tmp, tmp, Y))
+					goto err;
+			}
+
+			M = Y; /* keep the BIGNUM object, the value does not matter */
+			Y = X;
+			X = tmp;
+			sign = -sign;
+		}
+	}
+
+	/*
+	 * The while loop (Euclid's algorithm) ends when
+	 *      A == gcd(a,n);
+	 * we have
+	 *       sign*Y*a  ==  A  (mod |n|),
+	 * where  Y  is non-negative.
+	 */
+
+	if (sign < 0) {
+		if (!BN_sub(Y, n, Y))
+			goto err;
+	}
+	/* Now  Y*a  ==  A  (mod |n|).  */
+
+	if (!BN_is_one(A)) {
+		BNerror(BN_R_NO_INVERSE);
+		goto err;
+	}
+
+	if (!BN_nnmod(Y, Y, n, ctx))
+		goto err;
+	if (!bn_copy(R, Y))
+		goto err;
+
+	ret = R;
+
+ err:
+	if ((ret == NULL) && (in == NULL))
+		BN_free(R);
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+BIGNUM *
+BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+{
+	int ct = ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) ||
+	    (BN_get_flags(n, BN_FLG_CONSTTIME) != 0));
+	return BN_mod_inverse_internal(in, a, n, ctx, ct);
+}
+
+BIGNUM *
+BN_mod_inverse_nonct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+{
+	return BN_mod_inverse_internal(in, a, n, ctx, 0);
+}
+
+BIGNUM *
+BN_mod_inverse_ct(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+{
+	return BN_mod_inverse_internal(in, a, n, ctx, 1);
+}
diff --git a/crypto/bn/bn_internal.h b/crypto/bn/bn_internal.h
new file mode 100644
index 0000000..fd04bc9
--- /dev/null
+++ b/crypto/bn/bn_internal.h
@@ -0,0 +1,568 @@
+/*	$OpenBSD: bn_internal.h,v 1.15 2023/06/25 11:42:26 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bn_arch.h"
+
+#ifndef HEADER_BN_INTERNAL_H
+#define HEADER_BN_INTERNAL_H
+
+int bn_word_clz(BN_ULONG w);
+
+int bn_bitsize(const BIGNUM *bn);
+
+#ifndef HAVE_BN_CT_NE_ZERO
+static inline int
+bn_ct_ne_zero(BN_ULONG w)
+{
+	return (w | ~(w - 1)) >> (BN_BITS2 - 1);
+}
+#endif
+
+#ifndef HAVE_BN_CT_NE_ZERO_MASK
+static inline BN_ULONG
+bn_ct_ne_zero_mask(BN_ULONG w)
+{
+	return 0 - bn_ct_ne_zero(w);
+}
+#endif
+
+#ifndef HAVE_BN_CT_EQ_ZERO
+static inline int
+bn_ct_eq_zero(BN_ULONG w)
+{
+	return 1 - bn_ct_ne_zero(w);
+}
+#endif
+
+#ifndef HAVE_BN_CT_EQ_ZERO_MASK
+static inline BN_ULONG
+bn_ct_eq_zero_mask(BN_ULONG w)
+{
+	return 0 - bn_ct_eq_zero(w);
+}
+#endif
+
+#ifndef HAVE_BN_CLZW
+static inline int
+bn_clzw(BN_ULONG w)
+{
+	return bn_word_clz(w);
+}
+#endif
+
+/*
+ * Big number primitives are named as the operation followed by a suffix
+ * that indicates the number of words that it operates on, where 'w' means
+ * single word, 'dw' means double word, 'tw' means triple word and 'qw' means
+ * quadruple word. Unless otherwise noted, the size of the output is implied
+ * based on its inputs, for example bn_mulw() takes two single word inputs
+ * and is going to produce a double word result.
+ *
+ * Where a function implements multiple operations, these are listed in order.
+ * For example, a function that computes (r1:r0) = a * b + c is named
+ * bn_mulw_addw(), producing a double word result.
+ */
+
+/*
+ * Default implementations for BN_ULLONG architectures.
+ *
+ * On these platforms the C compiler is generally better at optimising without
+ * the use of inline assembly primitives. However, it can be difficult for the
+ * compiler to see through primitives in order to combine operations, due to
+ * type changes/narrowing. For this reason compound primitives are usually
+ * explicitly provided.
+ */
+#ifdef BN_ULLONG
+
+#ifndef HAVE_BN_ADDW
+#define HAVE_BN_ADDW
+static inline void
+bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULLONG r;
+
+	r = (BN_ULLONG)a + (BN_ULLONG)b;
+
+	*out_r1 = r >> BN_BITS2;
+	*out_r0 = r & BN_MASK2;
+}
+#endif
+
+#ifndef HAVE_BN_ADDW_ADDW
+#define HAVE_BN_ADDW_ADDW
+static inline void
+bn_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULLONG r;
+
+	r = (BN_ULLONG)a + (BN_ULLONG)b + (BN_ULLONG)c;
+
+	*out_r1 = r >> BN_BITS2;
+	*out_r0 = r & BN_MASK2;
+}
+#endif
+
+#ifndef HAVE_BN_MULW
+#define HAVE_BN_MULW
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULLONG r;
+
+	r = (BN_ULLONG)a * (BN_ULLONG)b;
+
+	*out_r1 = r >> BN_BITS2;
+	*out_r0 = r & BN_MASK2;
+}
+#endif
+
+#ifndef HAVE_BN_MULW_ADDW
+#define HAVE_BN_MULW_ADDW
+static inline void
+bn_mulw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULLONG r;
+
+	r = (BN_ULLONG)a * (BN_ULLONG)b + (BN_ULLONG)c;
+
+	*out_r1 = r >> BN_BITS2;
+	*out_r0 = r & BN_MASK2;
+}
+#endif
+
+#ifndef HAVE_BN_MULW_ADDW_ADDW
+#define HAVE_BN_MULW_ADDW_ADDW
+static inline void
+bn_mulw_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG d,
+    BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULLONG r;
+
+	r = (BN_ULLONG)a * (BN_ULLONG)b + (BN_ULLONG)c + (BN_ULLONG)d;
+
+	*out_r1 = r >> BN_BITS2;
+	*out_r0 = r & BN_MASK2;
+}
+#endif
+
+#endif /* !BN_ULLONG */
+
+/*
+ * bn_addw() computes (r1:r0) = a + b, where both inputs are single words,
+ * producing a double word result. The value of r1 is the carry from the
+ * addition.
+ */
+#ifndef HAVE_BN_ADDW
+static inline void
+bn_addw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r1, r0, c1, c2;
+
+	c1 = a | b;
+	c2 = a & b;
+	r0 = a + b;
+	r1 = ((c1 & ~r0) | c2) >> (BN_BITS2 - 1); /* carry */
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_addw_addw() computes (r1:r0) = a + b + c, where all inputs are single
+ * words, producing a double word result.
+ */
+#ifndef HAVE_BN_ADDW_ADDW
+static inline void
+bn_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r1, r0;
+
+	bn_addw(a, b, &r1, &r0);
+	bn_addw(r0, c, &carry, &r0);
+	r1 += carry;
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_qwaddqw() computes
+ * (r4:r3:r2:r1:r0) = (a3:a2:a1:a0) + (b3:b2:b1:b0) + carry, where a is a quad word,
+ * b is a quad word, and carry is a single word with value 0 or 1, producing a four
+ * word result and carry.
+ */
+#ifndef HAVE_BN_QWADDQW
+static inline void
+bn_qwaddqw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b3,
+    BN_ULONG b2, BN_ULONG b1, BN_ULONG b0, BN_ULONG carry, BN_ULONG *out_carry,
+    BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	bn_addw_addw(a0, b0, carry, &carry, &r0);
+	bn_addw_addw(a1, b1, carry, &carry, &r1);
+	bn_addw_addw(a2, b2, carry, &carry, &r2);
+	bn_addw_addw(a3, b3, carry, &carry, &r3);
+
+	*out_carry = carry;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_subw() computes r0 = a - b, where both inputs are single words,
+ * producing a single word result and borrow.
+ */
+#ifndef HAVE_BN_SUBW
+static inline void
+bn_subw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_borrow, BN_ULONG *out_r0)
+{
+	BN_ULONG borrow, r0;
+
+	r0 = a - b;
+	borrow = ((r0 | (b & ~a)) & (b | ~a)) >> (BN_BITS2 - 1);
+
+	*out_borrow = borrow;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_subw_subw() computes r0 = a - b - c, where all inputs are single words,
+ * producing a single word result and borrow.
+ */
+#ifndef HAVE_BN_SUBW_SUBW
+static inline void
+bn_subw_subw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_borrow,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG b1, b2, r0;
+
+	bn_subw(a, b, &b1, &r0);
+	bn_subw(r0, c, &b2, &r0);
+
+	*out_borrow = b1 + b2;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_qwsubqw() computes
+ * (r3:r2:r1:r0) = (a3:a2:a1:a0) - (b3:b2:b1:b0) - borrow, where a is a quad word,
+ * b is a quad word, and borrow is a single word with value 0 or 1, producing a
+ * four word result and borrow.
+ */
+#ifndef HAVE_BN_QWSUBQW
+static inline void
+bn_qwsubqw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b3,
+    BN_ULONG b2, BN_ULONG b1, BN_ULONG b0, BN_ULONG borrow, BN_ULONG *out_borrow,
+    BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	bn_subw_subw(a0, b0, borrow, &borrow, &r0);
+	bn_subw_subw(a1, b1, borrow, &borrow, &r1);
+	bn_subw_subw(a2, b2, borrow, &borrow, &r2);
+	bn_subw_subw(a3, b3, borrow, &borrow, &r3);
+
+	*out_borrow = borrow;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_mulw() computes (r1:r0) = a * b, where both inputs are single words,
+ * producing a double word result.
+ */
+#ifndef HAVE_BN_MULW
+/*
+ * Multiply two words (a * b) producing a double word result (h:l).
+ *
+ * This can be rewritten as:
+ *
+ *  a * b = (hi32(a) * 2^32 + lo32(a)) * (hi32(b) * 2^32 + lo32(b))
+ *        = hi32(a) * hi32(b) * 2^64 +
+ *          hi32(a) * lo32(b) * 2^32 +
+ *          hi32(b) * lo32(a) * 2^32 +
+ *          lo32(a) * lo32(b)
+ *
+ * The multiplication for each part of a and b can be calculated for each of
+ * these four terms without overflowing a BN_ULONG, as the maximum value of a
+ * 32 bit x 32 bit multiplication is 32 + 32 = 64 bits. Once these
+ * multiplications have been performed the result can be partitioned and summed
+ * into a double word (h:l). The same applies on a 32 bit system, substituting
+ * 16 for 32 and 32 for 64.
+ */
+#if 1
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG a1, a0, b1, b0, r1, r0;
+	BN_ULONG carry, x;
+
+	a1 = a >> BN_BITS4;
+	a0 = a & BN_MASK2l;
+	b1 = b >> BN_BITS4;
+	b0 = b & BN_MASK2l;
+
+	r1 = a1 * b1;
+	r0 = a0 * b0;
+
+	/* (a1 * b0) << BN_BITS4, partition the result across r1:r0 with carry. */
+	x = a1 * b0;
+	r1 += x >> BN_BITS4;
+	bn_addw(r0, x << BN_BITS4, &carry, &r0);
+	r1 += carry;
+
+	/* (b1 * a0) << BN_BITS4, partition the result across r1:r0 with carry. */
+	x = b1 * a0;
+	r1 += x >> BN_BITS4;
+	bn_addw(r0, x << BN_BITS4, &carry, &r0);
+	r1 += carry;
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#else
+
+/*
+ * XXX - this accumulator based version uses fewer instructions, however
+ * requires more variables/registers. It seems to be slower on at least amd64
+ * and i386, however may be faster on other architectures that have more
+ * registers available. Further testing is required and one of the two
+ * implementations should eventually be removed.
+ */
+static inline void
+bn_mulw(BN_ULONG a, BN_ULONG b, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG a1, a0, b1, b0, r1, r0, x;
+	BN_ULONG acc0, acc1, acc2, acc3;
+
+	a1 = a >> BN_BITS4;
+	b1 = b >> BN_BITS4;
+	a0 = a & BN_MASK2l;
+	b0 = b & BN_MASK2l;
+
+	r1 = a1 * b1;
+	r0 = a0 * b0;
+
+	acc0 = r0 & BN_MASK2l;
+	acc1 = r0 >> BN_BITS4;
+	acc2 = r1 & BN_MASK2l;
+	acc3 = r1 >> BN_BITS4;
+
+	/* (a1 * b0) << BN_BITS4, partition the result across r1:r0. */
+	x = a1 * b0;
+	acc1 += x & BN_MASK2l;
+	acc2 += (acc1 >> BN_BITS4) + (x >> BN_BITS4);
+	acc1 &= BN_MASK2l;
+	acc3 += acc2 >> BN_BITS4;
+	acc2 &= BN_MASK2l;
+
+	/* (b1 * a0) << BN_BITS4, partition the result across r1:r0. */
+	x = b1 * a0;
+	acc1 += x & BN_MASK2l;
+	acc2 += (acc1 >> BN_BITS4) + (x >> BN_BITS4);
+	acc1 &= BN_MASK2l;
+	acc3 += acc2 >> BN_BITS4;
+	acc2 &= BN_MASK2l;
+
+	*out_r1 = (acc3 << BN_BITS4) | acc2;
+	*out_r0 = (acc1 << BN_BITS4) | acc0;
+}
+#endif
+#endif
+
+#ifndef HAVE_BN_MULW_LO
+static inline BN_ULONG
+bn_mulw_lo(BN_ULONG a, BN_ULONG b)
+{
+	return a * b;
+}
+#endif
+
+#ifndef HAVE_BN_MULW_HI
+static inline BN_ULONG
+bn_mulw_hi(BN_ULONG a, BN_ULONG b)
+{
+	BN_ULONG h, l;
+
+	bn_mulw(a, b, &h, &l);
+
+	return h;
+}
+#endif
+
+/*
+ * bn_mulw_addw() computes (r1:r0) = a * b + c with all inputs being single
+ * words, producing a double word result.
+ */
+#ifndef HAVE_BN_MULW_ADDW
+static inline void
+bn_mulw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r1, r0;
+
+	bn_mulw(a, b, &r1, &r0);
+	bn_addw(r0, c, &carry, &r0);
+	r1 += carry;
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_mulw_addw_addw() computes (r1:r0) = a * b + c + d with all inputs being
+ * single words, producing a double word result.
+ */
+#ifndef HAVE_BN_MULW_ADDW_ADDW
+static inline void
+bn_mulw_addw_addw(BN_ULONG a, BN_ULONG b, BN_ULONG c, BN_ULONG d,
+    BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r1, r0;
+
+	bn_mulw_addw(a, b, c, &r1, &r0);
+	bn_addw(r0, d, &carry, &r0);
+	r1 += carry;
+
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_mulw_addtw() computes (r2:r1:r0) = a * b + (c2:c1:c0), where a and b are
+ * single words and (c2:c1:c0) is a triple word, producing a triple word result.
+ * The caller must ensure that the inputs provided do not result in c2
+ * overflowing.
+ */
+#ifndef HAVE_BN_MULW_ADDTW
+static inline void
+bn_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
+    BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG carry, r2, r1, r0, x1;
+
+	bn_mulw_addw(a, b, c0, &x1, &r0);
+	bn_addw(c1, x1, &carry, &r1);
+	r2 = c2 + carry;
+
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_mul2_mulw_addtw() computes (r2:r1:r0) = 2 * a * b + (c2:c1:c0), where a
+ * and b are single words and (c2:c1:c0) is a triple word, producing a triple
+ * word result. The caller must ensure that the inputs provided do not result
+ * in c2 overflowing.
+ */
+#ifndef HAVE_BN_MUL2_MULW_ADDTW
+static inline void
+bn_mul2_mulw_addtw(BN_ULONG a, BN_ULONG b, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0,
+    BN_ULONG *out_r2, BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r2, r1, r0, x1, x0;
+	BN_ULONG carry;
+
+	bn_mulw(a, b, &x1, &x0);
+	bn_addw(c0, x0, &carry, &r0);
+	bn_addw(c1, x1 + carry, &r2, &r1);
+	bn_addw(c2, r2, &carry, &r2);
+	bn_addw(r0, x0, &carry, &r0);
+	bn_addw(r1, x1 + carry, &carry, &r1);
+	r2 += carry;
+
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_qwmulw_addw() computes (r4:r3:r2:r1:r0) = (a3:a2:a1:a0) * b + c, where a
+ * is a quad word, b is a single word and c is a single word, producing a five
+ * word result.
+ */
+#ifndef HAVE_BN_QWMULW_ADDW
+static inline void
+bn_qwmulw_addw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0, BN_ULONG b,
+    BN_ULONG c, BN_ULONG *out_r4, BN_ULONG *out_r3, BN_ULONG *out_r2,
+    BN_ULONG *out_r1, BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	bn_mulw_addw(a0, b, c, &c, &r0);
+	bn_mulw_addw(a1, b, c, &c, &r1);
+	bn_mulw_addw(a2, b, c, &c, &r2);
+	bn_mulw_addw(a3, b, c, &c, &r3);
+
+	*out_r4 = c;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+/*
+ * bn_qwmulw_addqw_addw() computes
+ * (r4:r3:r2:r1:r0) = (a3:a2:a1:a0) * b + (c3:c2:c1:c0) + d, where a
+ * is a quad word, b is a single word, c is a quad word, and d is a single word,
+ * producing a five word result.
+ */
+#ifndef HAVE_BN_QWMULW_ADDQW_ADDW
+static inline void
+bn_qwmulw_addqw_addw(BN_ULONG a3, BN_ULONG a2, BN_ULONG a1, BN_ULONG a0,
+    BN_ULONG b, BN_ULONG c3, BN_ULONG c2, BN_ULONG c1, BN_ULONG c0, BN_ULONG d,
+    BN_ULONG *out_r4, BN_ULONG *out_r3, BN_ULONG *out_r2, BN_ULONG *out_r1,
+    BN_ULONG *out_r0)
+{
+	BN_ULONG r3, r2, r1, r0;
+
+	bn_mulw_addw_addw(a0, b, c0, d, &d, &r0);
+	bn_mulw_addw_addw(a1, b, c1, d, &d, &r1);
+	bn_mulw_addw_addw(a2, b, c2, d, &d, &r2);
+	bn_mulw_addw_addw(a3, b, c3, d, &d, &r3);
+
+	*out_r4 = d;
+	*out_r3 = r3;
+	*out_r2 = r2;
+	*out_r1 = r1;
+	*out_r0 = r0;
+}
+#endif
+
+#endif
diff --git a/crypto/bn/bn_isqrt.c b/crypto/bn/bn_isqrt.c
new file mode 100644
index 0000000..018d5f3
--- /dev/null
+++ b/crypto/bn/bn_isqrt.c
@@ -0,0 +1,234 @@
+/*	$OpenBSD: bn_isqrt.c,v 1.10 2023/06/04 17:28:35 tb Exp $ */
+/*
+ * Copyright (c) 2022 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bn_local.h"
+#include "crypto_internal.h"
+
+/*
+ * Calculate integer square root of |n| using a variant of Newton's method.
+ *
+ * Returns the integer square root of |n| in the caller-provided |out_sqrt|;
+ * |*out_perfect| is set to 1 if and only if |n| is a perfect square.
+ * One of |out_sqrt| and |out_perfect| can be NULL; |in_ctx| can be NULL.
+ *
+ * Returns 0 on error, 1 on success.
+ *
+ * Adapted from pure Python describing cpython's math.isqrt(), without bothering
+ * with any of the optimizations in the C code. A correctness proof is here:
+ * https://github.com/mdickinson/snippets/blob/master/proofs/isqrt/src/isqrt.lean
+ * The comments in the Python code also give a rather detailed proof.
+ */
+
+int
+bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *in_ctx)
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *a, *b;
+	int c, d, e, s;
+	int cmp, perfect;
+	int ret = 0;
+
+	if (out_perfect == NULL && out_sqrt == NULL) {
+		BNerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if (BN_is_negative(n)) {
+		BNerror(BN_R_INVALID_RANGE);
+		goto err;
+	}
+
+	if ((ctx = in_ctx) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (BN_is_zero(n)) {
+		perfect = 1;
+		BN_zero(a);
+		goto done;
+	}
+
+	if (!BN_one(a))
+		goto err;
+
+	c = (BN_num_bits(n) - 1) / 2;
+	d = 0;
+
+	/* Calculate s = floor(log(c)). */
+	if (!BN_set_word(b, c))
+		goto err;
+	s = BN_num_bits(b) - 1;
+
+	/*
+	 * By definition, the loop below is run <= floor(log(log(n))) times.
+	 * Comments in the cpython code establish the loop invariant that
+	 *
+	 *	(a - 1)^2 < n / 4^(c - d) < (a + 1)^2
+	 *
+	 * holds true in every iteration. Once this is proved via induction,
+	 * correctness of the algorithm is easy.
+	 *
+	 * Roughly speaking, A = (a << (d - e)) is used for one Newton step
+	 * "a = (A >> 1) + (m >> 1) / A" approximating m = (n >> 2 * (c - d)).
+	 */
+
+	for (; s >= 0; s--) {
+		e = d;
+		d = c >> s;
+
+		if (!BN_rshift(b, n, 2 * c - d - e + 1))
+			goto err;
+
+		if (!BN_div_ct(b, NULL, b, a, ctx))
+			goto err;
+
+		if (!BN_lshift(a, a, d - e - 1))
+			goto err;
+
+		if (!BN_add(a, a, b))
+			goto err;
+	}
+
+	/*
+	 * The loop invariant implies that either a or a - 1 is isqrt(n).
+	 * Figure out which one it is. The invariant also implies that for
+	 * a perfect square n, a must be the square root.
+	 */
+
+	if (!BN_sqr(b, a, ctx))
+		goto err;
+
+	/* If a^2 > n, we must have isqrt(n) == a - 1. */
+	if ((cmp = BN_cmp(b, n)) > 0) {
+		if (!BN_sub_word(a, 1))
+			goto err;
+	}
+
+	perfect = cmp == 0;
+
+ done:
+	if (out_perfect != NULL)
+		*out_perfect = perfect;
+
+	if (out_sqrt != NULL) {
+		if (!bn_copy(out_sqrt, a))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	if (ctx != in_ctx)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+
+/*
+ * is_square_mod_N[r % N] indicates whether r % N has a square root modulo N.
+ * The tables are generated in regress/lib/libcrypto/bn/bn_isqrt.c.
+ */
+
+const uint8_t is_square_mod_11[] = {
+	1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
+};
+CTASSERT(sizeof(is_square_mod_11) == 11);
+
+const uint8_t is_square_mod_63[] = {
+	1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
+	1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
+	0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+};
+CTASSERT(sizeof(is_square_mod_63) == 63);
+
+const uint8_t is_square_mod_64[] = {
+	1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+	1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+};
+CTASSERT(sizeof(is_square_mod_64) == 64);
+
+const uint8_t is_square_mod_65[] = {
+	1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
+	1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0,
+	0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0,
+	1,
+};
+CTASSERT(sizeof(is_square_mod_65) == 65);
+
+/*
+ * Determine whether n is a perfect square or not.
+ *
+ * Returns 1 on success and 0 on error. In case of success, |*out_perfect| is
+ * set to 1 if and only if |n| is a perfect square.
+ */
+
+int
+bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx)
+{
+	BN_ULONG r;
+
+	*out_perfect = 0;
+
+	if (BN_is_negative(n))
+		return 1;
+
+	/*
+	 * Before performing an expensive bn_isqrt() operation, weed out many
+	 * obvious non-squares. See H. Cohen, "A course in computational
+	 * algebraic number theory", Algorithm 1.7.3.
+	 *
+	 * The idea is that a square remains a square when reduced modulo any
+	 * number. The moduli are chosen in such a way that a non-square has
+	 * probability < 1% of passing the four table lookups.
+	 */
+
+	/* n % 64 */
+	r = BN_lsw(n) & 0x3f;
+
+	if (!is_square_mod_64[r % 64])
+		return 1;
+
+	if ((r = BN_mod_word(n, 11 * 63 * 65)) == (BN_ULONG)-1)
+		return 0;
+
+	if (!is_square_mod_63[r % 63] ||
+	    !is_square_mod_65[r % 65] ||
+	    !is_square_mod_11[r % 11])
+		return 1;
+
+	return bn_isqrt(NULL, out_perfect, n, ctx);
+}
diff --git a/crypto/bn/bn_kron.c b/crypto/bn/bn_kron.c
new file mode 100644
index 0000000..a170d68
--- /dev/null
+++ b/crypto/bn/bn_kron.c
@@ -0,0 +1,195 @@
+/* $OpenBSD: bn_kron.c,v 1.15 2023/07/08 12:21:58 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "bn_local.h"
+
+/*
+ * Kronecker symbol, implemented according to Henri Cohen, "A Course in
+ * Computational Algebraic Number Theory", Algorithm 1.4.10.
+ *
+ * Returns -1, 0, or 1 on success and -2 on error.
+ */
+
+int
+BN_kronecker(const BIGNUM *A, const BIGNUM *B, BN_CTX *ctx)
+{
+	/* tab[BN_lsw(n) & 7] = (-1)^((n^2 - 1)) / 8) for odd values of n. */
+	static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
+	BIGNUM *a, *b, *tmp;
+	int k, v;
+	int ret = -2;
+
+	BN_CTX_start(ctx);
+
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto end;
+
+	if (!bn_copy(a, A))
+		goto end;
+	if (!bn_copy(b, B))
+		goto end;
+
+	/*
+	 * Cohen's step 1:
+	 */
+
+	/* If b is zero, output 1 if |a| is 1, otherwise output 0. */
+	if (BN_is_zero(b)) {
+		ret = BN_abs_is_word(a, 1);
+		goto end;
+	}
+
+	/*
+	 * Cohen's step 2:
+	 */
+
+	/* If both are even, they have a factor in common, so output 0. */
+	if (!BN_is_odd(a) && !BN_is_odd(b)) {
+		ret = 0;
+		goto end;
+	}
+
+	/* Factorize b = 2^v * u with odd u and replace b with u. */
+	v = 0;
+	while (!BN_is_bit_set(b, v))
+		v++;
+	if (!BN_rshift(b, b, v))
+		goto end;
+
+	/* If v is even set k = 1, otherwise set it to (-1)^((a^2 - 1) / 8). */
+	k = 1;
+	if (v % 2 != 0)
+		k = tab[BN_lsw(a) & 7];
+
+	/*
+	 * If b is negative, replace it with -b and if a is also negative
+	 * replace k with -k.
+	 */
+	if (BN_is_negative(b)) {
+		BN_set_negative(b, 0);
+
+		if (BN_is_negative(a))
+			k = -k;
+	}
+
+	/*
+	 * Now b is positive and odd, so compute the Jacobi symbol (a/b)
+	 * and multiply it by k.
+	 */
+
+	while (1) {
+		/*
+		 * Cohen's step 3:
+		 */
+
+		/* b is positive and odd. */
+
+		/* If a is zero output k if b is one, otherwise output 0. */
+		if (BN_is_zero(a)) {
+			ret = BN_is_one(b) ? k : 0;
+			goto end;
+		}
+
+		/* Factorize a = 2^v * u with odd u and replace a with u. */
+		v = 0;
+		while (!BN_is_bit_set(a, v))
+			v++;
+		if (!BN_rshift(a, a, v))
+			goto end;
+
+		/* If v is odd, multiply k with (-1)^((b^2 - 1) / 8). */
+		if (v % 2 != 0)
+			k *= tab[BN_lsw(b) & 7];
+
+		/*
+		 * Cohen's step 4:
+		 */
+
+		/*
+		 * Apply the reciprocity law: multiply k by (-1)^((a-1)(b-1)/4).
+		 *
+		 * This expression is -1 if and only if a and b are 3 (mod 4).
+		 * In turn, this is the case if and only if their two's
+		 * complement representations have the second bit set.
+		 * a could be negative in the first iteration, b is positive.
+		 */
+		if ((BN_is_negative(a) ? ~BN_lsw(a) : BN_lsw(a)) & BN_lsw(b) & 2)
+			k = -k;
+
+		/*
+		 * (a, b) := (b mod |a|, |a|)
+		 *
+		 * Once this is done, we know that 0 < a < b at the start of the
+		 * loop. Since b is strictly decreasing, the loop terminates.
+		 */
+
+		if (!BN_nnmod(b, b, a, ctx))
+			goto end;
+
+		tmp = a;
+		a = b;
+		b = tmp;
+
+		BN_set_negative(b, 0);
+	}
+
+ end:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_kronecker);
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
new file mode 100644
index 0000000..c0c0ac8
--- /dev/null
+++ b/crypto/bn/bn_lib.c
@@ -0,0 +1,736 @@
+/* $OpenBSD: bn_lib.c,v 1.90 2023/07/28 10:35:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "bn_local.h"
+#include "bn_internal.h"
+
+BIGNUM *
+BN_new(void)
+{
+	BIGNUM *bn;
+
+	if ((bn = calloc(1, sizeof(BIGNUM))) == NULL) {
+		BNerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	bn->flags = BN_FLG_MALLOCED;
+
+	return bn;
+}
+LCRYPTO_ALIAS(BN_new);
+
+void
+BN_init(BIGNUM *a)
+{
+	memset(a, 0, sizeof(BIGNUM));
+}
+
+void
+BN_clear(BIGNUM *a)
+{
+	if (a->d != NULL)
+		explicit_bzero(a->d, a->dmax * sizeof(a->d[0]));
+	a->top = 0;
+	a->neg = 0;
+}
+LCRYPTO_ALIAS(BN_clear);
+
+void
+BN_free(BIGNUM *bn)
+{
+	if (bn == NULL)
+		return;
+
+	if (!BN_get_flags(bn, BN_FLG_STATIC_DATA))
+		freezero(bn->d, bn->dmax * sizeof(bn->d[0]));
+
+	if (!BN_get_flags(bn, BN_FLG_MALLOCED)) {
+		explicit_bzero(bn, sizeof(*bn));
+		return;
+	}
+
+	freezero(bn, sizeof(*bn));
+}
+LCRYPTO_ALIAS(BN_free);
+
+void
+BN_clear_free(BIGNUM *bn)
+{
+	BN_free(bn);
+}
+LCRYPTO_ALIAS(BN_clear_free);
+
+void
+BN_set_flags(BIGNUM *b, int n)
+{
+	b->flags |= n;
+}
+LCRYPTO_ALIAS(BN_set_flags);
+
+int
+BN_get_flags(const BIGNUM *b, int n)
+{
+	return b->flags & n;
+}
+LCRYPTO_ALIAS(BN_get_flags);
+
+void
+BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
+{
+	int dest_flags;
+
+	dest_flags = (dest->flags & BN_FLG_MALLOCED) |
+	    (b->flags & ~BN_FLG_MALLOCED) | BN_FLG_STATIC_DATA | flags;
+
+	*dest = *b;
+	dest->flags = dest_flags;
+}
+LCRYPTO_ALIAS(BN_with_flags);
+
+static const BN_ULONG bn_value_one_data = 1;
+static const BIGNUM bn_value_one = {
+	.d = (BN_ULONG *)&bn_value_one_data,
+	.top = 1,
+	.dmax = 1,
+	.neg = 0,
+	.flags = BN_FLG_STATIC_DATA,
+};
+
+const BIGNUM *
+BN_value_one(void)
+{
+	return &bn_value_one;
+}
+LCRYPTO_ALIAS(BN_value_one);
+
+int
+BN_num_bits_word(BN_ULONG w)
+{
+	return BN_BITS2 - bn_clzw(w);
+}
+LCRYPTO_ALIAS(BN_num_bits_word);
+
+int
+BN_num_bits(const BIGNUM *bn)
+{
+	return bn_bitsize(bn);
+}
+LCRYPTO_ALIAS(BN_num_bits);
+
+void
+bn_correct_top(BIGNUM *a)
+{
+	while (a->top > 0 && a->d[a->top - 1] == 0)
+		a->top--;
+}
+
+static int
+bn_expand_internal(BIGNUM *bn, int words)
+{
+	BN_ULONG *d;
+
+	if (words < 0) {
+		BNerror(BN_R_BIGNUM_TOO_LONG); // XXX
+		return 0;
+	}
+
+	if (words > INT_MAX / (4 * BN_BITS2)) {
+		BNerror(BN_R_BIGNUM_TOO_LONG);
+		return 0;
+	}
+	if (BN_get_flags(bn, BN_FLG_STATIC_DATA)) {
+		BNerror(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
+		return 0;
+	}
+
+	d = recallocarray(bn->d, bn->dmax, words, sizeof(BN_ULONG));
+	if (d == NULL) {
+		BNerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	bn->d = d;
+	bn->dmax = words;
+
+	return 1;
+}
+
+int
+bn_expand(BIGNUM *bn, int bits)
+{
+	int words;
+
+	if (bits < 0)
+		return 0;
+
+	if (bits > (INT_MAX - BN_BITS2 + 1))
+		return 0;
+
+	words = (bits + BN_BITS2 - 1) / BN_BITS2;
+
+	return bn_wexpand(bn, words);
+}
+
+int
+bn_wexpand(BIGNUM *bn, int words)
+{
+	if (words < 0)
+		return 0;
+
+	if (words <= bn->dmax)
+		return 1;
+
+	return bn_expand_internal(bn, words);
+}
+
+BIGNUM *
+BN_dup(const BIGNUM *a)
+{
+	BIGNUM *t;
+
+	if (a == NULL)
+		return NULL;
+
+	t = BN_new();
+	if (t == NULL)
+		return NULL;
+	if (!bn_copy(t, a)) {
+		BN_free(t);
+		return NULL;
+	}
+	return t;
+}
+LCRYPTO_ALIAS(BN_dup);
+
+static inline void
+bn_copy_words(BN_ULONG *ap, const BN_ULONG *bp, int n)
+{
+	while (n > 0) {
+		ap[0] = bp[0];
+		ap++;
+		bp++;
+		n--;
+	}
+}
+
+BIGNUM *
+BN_copy(BIGNUM *a, const BIGNUM *b)
+{
+	if (a == b)
+		return (a);
+
+	if (!bn_wexpand(a, b->top))
+		return (NULL);
+
+	bn_copy_words(a->d, b->d, b->top);
+
+	/* Copy constant time flag from b, but make it sticky on a. */
+	a->flags |= b->flags & BN_FLG_CONSTTIME;
+
+	a->top = b->top;
+	a->neg = b->neg;
+
+	return (a);
+}
+LCRYPTO_ALIAS(BN_copy);
+
+int
+bn_copy(BIGNUM *dst, const BIGNUM *src)
+{
+	return BN_copy(dst, src) != NULL;
+}
+
+void
+BN_swap(BIGNUM *a, BIGNUM *b)
+{
+	int flags_old_a, flags_old_b;
+	BN_ULONG *tmp_d;
+	int tmp_top, tmp_dmax, tmp_neg;
+
+
+	flags_old_a = a->flags;
+	flags_old_b = b->flags;
+
+	tmp_d = a->d;
+	tmp_top = a->top;
+	tmp_dmax = a->dmax;
+	tmp_neg = a->neg;
+
+	a->d = b->d;
+	a->top = b->top;
+	a->dmax = b->dmax;
+	a->neg = b->neg;
+
+	b->d = tmp_d;
+	b->top = tmp_top;
+	b->dmax = tmp_dmax;
+	b->neg = tmp_neg;
+
+	a->flags = (flags_old_a & BN_FLG_MALLOCED) |
+	    (flags_old_b & BN_FLG_STATIC_DATA);
+	b->flags = (flags_old_b & BN_FLG_MALLOCED) |
+	    (flags_old_a & BN_FLG_STATIC_DATA);
+}
+LCRYPTO_ALIAS(BN_swap);
+
+BN_ULONG
+BN_get_word(const BIGNUM *a)
+{
+	if (a->top > 1)
+		return BN_MASK2;
+	else if (a->top == 1)
+		return a->d[0];
+	/* a->top == 0 */
+	return 0;
+}
+LCRYPTO_ALIAS(BN_get_word);
+
+int
+BN_set_word(BIGNUM *a, BN_ULONG w)
+{
+	if (!bn_wexpand(a, 1))
+		return (0);
+	a->neg = 0;
+	a->d[0] = w;
+	a->top = (w ? 1 : 0);
+	return (1);
+}
+LCRYPTO_ALIAS(BN_set_word);
+
+int
+BN_ucmp(const BIGNUM *a, const BIGNUM *b)
+{
+	int i;
+
+	if (a->top < b->top)
+		return -1;
+	if (a->top > b->top)
+		return 1;
+
+	for (i = a->top - 1; i >= 0; i--) {
+		if (a->d[i] != b->d[i])
+			return (a->d[i] > b->d[i] ? 1 : -1);
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(BN_ucmp);
+
+int
+BN_cmp(const BIGNUM *a, const BIGNUM *b)
+{
+	if (a == NULL || b == NULL) {
+		if (a != NULL)
+			return -1;
+		if (b != NULL)
+			return 1;
+		return 0;
+	}
+
+	if (a->neg != b->neg)
+		return b->neg - a->neg;
+
+	if (a->neg)
+		return BN_ucmp(b, a);
+
+	return BN_ucmp(a, b);
+}
+LCRYPTO_ALIAS(BN_cmp);
+
+int
+BN_set_bit(BIGNUM *a, int n)
+{
+	int i, j, k;
+
+	if (n < 0)
+		return 0;
+
+	i = n / BN_BITS2;
+	j = n % BN_BITS2;
+	if (a->top <= i) {
+		if (!bn_wexpand(a, i + 1))
+			return (0);
+		for (k = a->top; k < i + 1; k++)
+			a->d[k] = 0;
+		a->top = i + 1;
+	}
+
+	a->d[i] |= (((BN_ULONG)1) << j);
+	return (1);
+}
+LCRYPTO_ALIAS(BN_set_bit);
+
+int
+BN_clear_bit(BIGNUM *a, int n)
+{
+	int i, j;
+
+	if (n < 0)
+		return 0;
+
+	i = n / BN_BITS2;
+	j = n % BN_BITS2;
+	if (a->top <= i)
+		return (0);
+
+	a->d[i] &= (~(((BN_ULONG)1) << j));
+	bn_correct_top(a);
+	return (1);
+}
+LCRYPTO_ALIAS(BN_clear_bit);
+
+int
+BN_is_bit_set(const BIGNUM *a, int n)
+{
+	int i, j;
+
+	if (n < 0)
+		return 0;
+	i = n / BN_BITS2;
+	j = n % BN_BITS2;
+	if (a->top <= i)
+		return 0;
+	return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
+}
+LCRYPTO_ALIAS(BN_is_bit_set);
+
+int
+BN_mask_bits(BIGNUM *a, int n)
+{
+	int b, w;
+
+	if (n < 0)
+		return 0;
+
+	w = n / BN_BITS2;
+	b = n % BN_BITS2;
+	if (w >= a->top)
+		return 0;
+	if (b == 0)
+		a->top = w;
+	else {
+		a->top = w + 1;
+		a->d[w] &= ~(BN_MASK2 << b);
+	}
+	bn_correct_top(a);
+	return (1);
+}
+LCRYPTO_ALIAS(BN_mask_bits);
+
+void
+BN_set_negative(BIGNUM *bn, int neg)
+{
+	bn->neg = ~BN_is_zero(bn) & bn_ct_ne_zero(neg);
+}
+LCRYPTO_ALIAS(BN_set_negative);
+
+/*
+ * Constant-time conditional swap of a and b.
+ * a and b are swapped if condition is not 0.
+ * The code assumes that at most one bit of condition is set.
+ * nwords is the number of words to swap.
+ * The code assumes that at least nwords are allocated in both a and b,
+ * and that no more than nwords are used by either a or b.
+ * a and b cannot be the same number
+ */
+void
+BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
+{
+	BN_ULONG t;
+	int i;
+
+	assert(a != b);
+	assert((condition & (condition - 1)) == 0);
+	assert(sizeof(BN_ULONG) >= sizeof(int));
+
+	condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1;
+
+	t = (a->top^b->top) & condition;
+	a->top ^= t;
+	b->top ^= t;
+
+#define BN_CONSTTIME_SWAP(ind) \
+	do { \
+		t = (a->d[ind] ^ b->d[ind]) & condition; \
+		a->d[ind] ^= t; \
+		b->d[ind] ^= t; \
+	} while (0)
+
+
+	switch (nwords) {
+	default:
+		for (i = 10; i < nwords; i++)
+			BN_CONSTTIME_SWAP(i);
+		/* Fallthrough */
+	case 10: BN_CONSTTIME_SWAP(9); /* Fallthrough */
+	case 9: BN_CONSTTIME_SWAP(8); /* Fallthrough */
+	case 8: BN_CONSTTIME_SWAP(7); /* Fallthrough */
+	case 7: BN_CONSTTIME_SWAP(6); /* Fallthrough */
+	case 6: BN_CONSTTIME_SWAP(5); /* Fallthrough */
+	case 5: BN_CONSTTIME_SWAP(4); /* Fallthrough */
+	case 4: BN_CONSTTIME_SWAP(3); /* Fallthrough */
+	case 3: BN_CONSTTIME_SWAP(2); /* Fallthrough */
+	case 2: BN_CONSTTIME_SWAP(1); /* Fallthrough */
+	case 1:
+		BN_CONSTTIME_SWAP(0);
+	}
+#undef BN_CONSTTIME_SWAP
+}
+LCRYPTO_ALIAS(BN_consttime_swap);
+
+/*
+ * Constant-time conditional swap of a and b.
+ * a and b are swapped if condition is not 0.
+ * nwords is the number of words to swap.
+ */
+int
+BN_swap_ct(BN_ULONG condition, BIGNUM *a, BIGNUM *b, size_t nwords)
+{
+	BN_ULONG t;
+	int i, words;
+
+	if (a == b)
+		return 1;
+	if (nwords > INT_MAX)
+		return 0;
+	words = (int)nwords;
+	if (!bn_wexpand(a, words) || !bn_wexpand(b, words))
+		return 0;
+	if (a->top > words || b->top > words) {
+		BNerror(BN_R_INVALID_LENGTH);
+		return 0;
+	}
+
+	/* Set condition to 0 (if it was zero) or all 1s otherwise. */
+	condition = ((~condition & (condition - 1)) >> (BN_BITS2 - 1)) - 1;
+
+	/* swap top field */
+	t = (a->top ^ b->top) & condition;
+	a->top ^= t;
+	b->top ^= t;
+
+	/* swap neg field */
+	t = (a->neg ^ b->neg) & condition;
+	a->neg ^= t;
+	b->neg ^= t;
+
+	/* swap BN_FLG_CONSTTIME from flag field */
+	t = ((a->flags ^ b->flags) & BN_FLG_CONSTTIME) & condition;
+	a->flags ^= t;
+	b->flags ^= t;
+
+	/* swap the data */
+	for (i = 0; i < words; i++) {
+		t = (a->d[i] ^ b->d[i]) & condition;
+		a->d[i] ^= t;
+		b->d[i] ^= t;
+	}
+
+	return 1;
+}
+
+void
+BN_zero(BIGNUM *a)
+{
+	a->neg = 0;
+	a->top = 0;
+}
+LCRYPTO_ALIAS(BN_zero);
+
+int
+BN_one(BIGNUM *a)
+{
+	return BN_set_word(a, 1);
+}
+LCRYPTO_ALIAS(BN_one);
+
+int
+BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
+{
+	return (a->top == 1 && a->d[0] == w) || (w == 0 && a->top == 0);
+}
+LCRYPTO_ALIAS(BN_abs_is_word);
+
+int
+BN_is_zero(const BIGNUM *bn)
+{
+	BN_ULONG bits = 0;
+	int i;
+
+	for (i = 0; i < bn->top; i++)
+		bits |= bn->d[i];
+
+	return bits == 0;
+}
+LCRYPTO_ALIAS(BN_is_zero);
+
+int
+BN_is_one(const BIGNUM *a)
+{
+	return BN_abs_is_word(a, 1) && !a->neg;
+}
+LCRYPTO_ALIAS(BN_is_one);
+
+int
+BN_is_word(const BIGNUM *a, const BN_ULONG w)
+{
+	return BN_abs_is_word(a, w) && (w == 0 || !a->neg);
+}
+LCRYPTO_ALIAS(BN_is_word);
+
+int
+BN_is_odd(const BIGNUM *a)
+{
+	return a->top > 0 && (a->d[0] & 1);
+}
+LCRYPTO_ALIAS(BN_is_odd);
+
+int
+BN_is_negative(const BIGNUM *a)
+{
+	return a->neg != 0;
+}
+LCRYPTO_ALIAS(BN_is_negative);
+
+/*
+ * Bits of security, see SP800-57, section 5.6.11, table 2.
+ */
+int
+BN_security_bits(int L, int N)
+{
+	int secbits, bits;
+
+	if (L >= 15360)
+		secbits = 256;
+	else if (L >= 7680)
+		secbits = 192;
+	else if (L >= 3072)
+		secbits = 128;
+	else if (L >= 2048)
+		secbits = 112;
+	else if (L >= 1024)
+		secbits = 80;
+	else
+		return 0;
+
+	if (N == -1)
+		return secbits;
+
+	bits = N / 2;
+	if (bits < 80)
+		return 0;
+
+	return bits >= secbits ? secbits : bits;
+}
+LCRYPTO_ALIAS(BN_security_bits);
+
+BN_GENCB *
+BN_GENCB_new(void)
+{
+	BN_GENCB *cb;
+
+	if ((cb = calloc(1, sizeof(*cb))) == NULL)
+		return NULL;
+
+	return cb;
+}
+LCRYPTO_ALIAS(BN_GENCB_new);
+
+void
+BN_GENCB_free(BN_GENCB *cb)
+{
+	if (cb == NULL)
+		return;
+	free(cb);
+}
+LCRYPTO_ALIAS(BN_GENCB_free);
+
+/* Populate a BN_GENCB structure with an "old"-style callback */
+void
+BN_GENCB_set_old(BN_GENCB *gencb, void (*cb)(int, int, void *), void *cb_arg)
+{
+	gencb->ver = 1;
+	gencb->cb.cb_1 = cb;
+	gencb->arg = cb_arg;
+}
+LCRYPTO_ALIAS(BN_GENCB_set_old);
+
+/* Populate a BN_GENCB structure with a "new"-style callback */
+void
+BN_GENCB_set(BN_GENCB *gencb, int (*cb)(int, int, BN_GENCB *), void *cb_arg)
+{
+	gencb->ver = 2;
+	gencb->cb.cb_2 = cb;
+	gencb->arg = cb_arg;
+}
+LCRYPTO_ALIAS(BN_GENCB_set);
+
+void *
+BN_GENCB_get_arg(BN_GENCB *cb)
+{
+	return cb->arg;
+}
+LCRYPTO_ALIAS(BN_GENCB_get_arg);
diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h
new file mode 100644
index 0000000..a9ce466
--- /dev/null
+++ b/crypto/bn/bn_local.h
@@ -0,0 +1,335 @@
+/* $OpenBSD: bn_local.h,v 1.38 2023/08/09 09:23:03 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_BN_LOCAL_H
+#define HEADER_BN_LOCAL_H
+
+#include 
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+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;
+};
+
+struct bn_mont_ctx_st {
+	int ri;		/* Number of bits in R */
+	BIGNUM RR;	/* Used to convert to Montgomery form */
+	BIGNUM N;	/* Modulus */
+
+	/* Least significant word(s) of Ni; R*(1/R mod N) - N*Ni = 1 */
+	BN_ULONG n0[2];
+
+	int flags;
+};
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+typedef struct bn_recp_ctx_st {
+	BIGNUM N;	/* the divisor */
+	BIGNUM Nr;	/* the reciprocal */
+	int num_bits;
+	int shift;
+	int flags;
+} BN_RECP_CTX;
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st {
+	unsigned int ver;	/* To handle binary (in)compatibility */
+	void *arg;		/* callback-specific data */
+	union {
+		/* if(ver==1) - handles old style callbacks */
+		void (*cb_1)(int, int, void *);
+		/* if(ver==2) - new callback style */
+		int (*cb_2)(int, int, BN_GENCB *);
+	} cb;
+};
+
+/*
+ * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
+ *
+ *
+ * For window size 'w' (w >= 2) and a random 'b' bits exponent,
+ * the number of multiplications is a constant plus on average
+ *
+ *    2^(w-1) + (b-w)/(w+1);
+ *
+ * here  2^(w-1)  is for precomputing the table (we actually need
+ * entries only for windows that have the lowest bit set), and
+ * (b-w)/(w+1)  is an approximation for the expected number of
+ * w-bit windows, not counting the first one.
+ *
+ * Thus we should use
+ *
+ *    w >= 6  if        b > 671
+ *     w = 5  if  671 > b > 239
+ *     w = 4  if  239 > b >  79
+ *     w = 3  if   79 > b >  23
+ *    w <= 2  if   23 > b
+ *
+ * (with draws in between).  Very small exponents are often selected
+ * with low Hamming weight, so we use  w = 1  for b <= 23.
+ */
+#define BN_window_bits_for_exponent_size(b) \
+		((b) > 671 ? 6 : \
+		 (b) > 239 ? 5 : \
+		 (b) >  79 ? 4 : \
+		 (b) >  23 ? 3 : 1)
+
+
+/* BN_mod_exp_mont_consttime is based on the assumption that the
+ * L1 data cache line width of the target processor is at least
+ * the following value.
+ */
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH	( 64 )
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK	(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
+
+/* Window sizes optimized for fixed window size modular exponentiation
+ * algorithm (BN_mod_exp_mont_consttime).
+ *
+ * To achieve the security goals of BN_mode_exp_mont_consttime, the
+ * maximum size of the window must not exceed
+ * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH).
+ *
+ * Window size thresholds are defined for cache line sizes of 32 and 64,
+ * cache line sizes where log_2(32)=5 and log_2(64)=6 respectively. A
+ * window size of 7 should only be used on processors that have a 128
+ * byte or greater cache line size.
+ */
+#if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+		((b) > 937 ? 6 : \
+		 (b) > 306 ? 5 : \
+		 (b) >  89 ? 4 : \
+		 (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE	(6)
+
+#elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+		((b) > 306 ? 5 : \
+		 (b) >  89 ? 4 : \
+		 (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE	(5)
+
+#endif
+
+
+/* Pentium pro 16,16,16,32,64 */
+/* Alpha       16,16,16,16.64 */
+#define BN_MULL_SIZE_NORMAL			(16) /* 32 */
+#define BN_MUL_RECURSIVE_SIZE_NORMAL		(16) /* 32 less than */
+#define BN_SQR_RECURSIVE_SIZE_NORMAL		(16) /* 32 */
+#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL	(32) /* 32 */
+#define BN_MONT_CTX_SET_SIZE_WORD		(64) /* 32 */
+
+/* The least significant word of a BIGNUM. */
+#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
+
+BN_ULONG bn_add(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len,
+    const BN_ULONG *b, int b_len);
+BN_ULONG bn_sub(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len,
+    const BN_ULONG *b, int b_len);
+
+void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb);
+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, const BN_ULONG *a);
+void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
+
+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(BIGNUM *a);
+int bn_expand(BIGNUM *a, int bits);
+int bn_wexpand(BIGNUM *a, int words);
+
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+    int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+    int num);
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void     bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+void bn_div_rem_words(BN_ULONG h, BN_ULONG l, BN_ULONG d, BN_ULONG *out_q,
+    BN_ULONG *out_r);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
+int bn_rand_in_range(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc);
+int bn_rand_interval(BIGNUM *rnd, BN_ULONG lower_word, const BIGNUM *upper_exc);
+
+void	BN_init(BIGNUM *);
+
+int	BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx);
+
+void	BN_RECP_CTX_init(BN_RECP_CTX *recp);
+BN_RECP_CTX *BN_RECP_CTX_new(void);
+void	BN_RECP_CTX_free(BN_RECP_CTX *recp);
+int	BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *rdiv, BN_CTX *ctx);
+int	BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+    BN_RECP_CTX *recp, BN_CTX *ctx);
+int	BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx);
+int	BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
+    BN_RECP_CTX *recp, BN_CTX *ctx);
+
+/* Explicitly const time / non-const time versions for internal use */
+int BN_mod_exp_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_exp_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_exp_mont_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_mod_exp_mont_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+int BN_div_nonct(BIGNUM *q, BIGNUM *r, const BIGNUM *n, const BIGNUM *d,
+    BN_CTX *ctx);
+int BN_div_ct(BIGNUM *q, BIGNUM *r, const BIGNUM *n, const BIGNUM *d,
+    BN_CTX *ctx);
+int BN_mod_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+int BN_mod_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+
+BIGNUM *BN_mod_inverse_ct(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,
+    BN_CTX *ctx);
+BIGNUM *BN_mod_inverse_nonct(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n,
+    BN_CTX *ctx);
+int	BN_gcd_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+int	BN_gcd_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
+
+int	BN_swap_ct(BN_ULONG swap, BIGNUM *a, BIGNUM *b, size_t nwords);
+
+int bn_copy(BIGNUM *dst, const BIGNUM *src);
+
+int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
+int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
+
+int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *ctx, size_t rounds);
+
+int bn_printf(BIO *bio, const BIGNUM *bn, int indent, const char *fmt, ...)
+    __attribute__((__format__ (printf, 4, 5)))
+    __attribute__((__nonnull__ (4)));
+
+int bn_bn2hex_nosign(const BIGNUM *bn, char **out, size_t *out_len);
+int bn_bn2hex_nibbles(const BIGNUM *bn, char **out, size_t *out_len);
+
+__END_HIDDEN_DECLS
+#endif /* !HEADER_BN_LOCAL_H */
diff --git a/crypto/bn/bn_mod.c b/crypto/bn/bn_mod.c
new file mode 100644
index 0000000..365f6fc
--- /dev/null
+++ b/crypto/bn/bn_mod.c
@@ -0,0 +1,369 @@
+/* $OpenBSD: bn_mod.c,v 1.22 2023/07/08 12:21:58 beck Exp $ */
+/* Includes code written by Lenka Fibikova 
+ * for the OpenSSL project. */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "bn_local.h"
+
+int
+BN_mod_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+	return BN_div_ct(NULL, r, a, m, ctx);
+}
+
+int
+BN_mod_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+	return BN_div_nonct(NULL, r, a, m, ctx);
+}
+
+/*
+ * BN_nnmod() is like BN_mod(), but always returns a non-negative remainder
+ * (that is 0 <= r < |m| always holds). If both a and m have the same sign then
+ * the result is already non-negative. Otherwise, -|m| < r < 0, which needs to
+ * be adjusted as r := r + |m|. This equates to r := |m| - |r|.
+ */
+int
+BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_mod_ct(r, a, m, ctx))
+		return 0;
+	if (BN_is_negative(r))
+		return BN_usub(r, m, r);
+	return 1;
+}
+LCRYPTO_ALIAS(BN_nnmod);
+
+int
+BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_add(r, a, b))
+		return 0;
+	return BN_nnmod(r, r, m, ctx);
+}
+LCRYPTO_ALIAS(BN_mod_add);
+
+/*
+ * BN_mod_add() variant that may only be used if both a and b are non-negative
+ * and have already been reduced (less than m).
+ */
+int
+BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_uadd(r, a, b))
+		return 0;
+	if (BN_ucmp(r, m) >= 0)
+		return BN_usub(r, r, m);
+	return 1;
+}
+LCRYPTO_ALIAS(BN_mod_add_quick);
+
+int
+BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_sub(r, a, b))
+		return 0;
+	return BN_nnmod(r, r, m, ctx);
+}
+LCRYPTO_ALIAS(BN_mod_sub);
+
+/*
+ * BN_mod_sub() variant that may only be used if both a and b are non-negative
+ * and have already been reduced (less than m).
+ */
+int
+BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (BN_ucmp(a, b) >= 0)
+		return BN_usub(r, a, b);
+	if (!BN_usub(r, b, a))
+		return 0;
+	return BN_usub(r, m, r);
+}
+LCRYPTO_ALIAS(BN_mod_sub_quick);
+
+int
+BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+    BN_CTX *ctx)
+{
+	BIGNUM *rr;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		goto err;
+	}
+
+	rr = r;
+	if (rr == a || rr == b)
+		rr = BN_CTX_get(ctx);
+	if (rr == NULL)
+		goto err;
+
+	if (a == b) {
+		if (!BN_sqr(rr, a, ctx))
+			goto err;
+	} else {
+		if (!BN_mul(rr, a, b, ctx))
+			goto err;
+	}
+	if (!BN_nnmod(r, rr, m, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_mod_mul);
+
+int
+BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+	return BN_mod_mul(r, a, a, m, ctx);
+}
+LCRYPTO_ALIAS(BN_mod_sqr);
+
+int
+BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_lshift1(r, a))
+		return 0;
+	return BN_nnmod(r, r, m, ctx);
+}
+LCRYPTO_ALIAS(BN_mod_lshift1);
+
+/*
+ * BN_mod_lshift1() variant that may be used if a is non-negative
+ * and has already been reduced (less than m).
+ */
+int
+BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
+{
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+	if (!BN_lshift1(r, a))
+		return 0;
+	if (BN_ucmp(r, m) >= 0)
+		return BN_usub(r, r, m);
+	return 1;
+}
+LCRYPTO_ALIAS(BN_mod_lshift1_quick);
+
+int
+BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx)
+{
+	BIGNUM *abs_m;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		goto err;
+	}
+
+	if (!BN_nnmod(r, a, m, ctx))
+		goto err;
+
+	if (BN_is_negative(m)) {
+		if ((abs_m = BN_CTX_get(ctx)) == NULL)
+			goto err;
+		if (!bn_copy(abs_m, m))
+			goto err;
+		BN_set_negative(abs_m, 0);
+		m = abs_m;
+	}
+	if (!BN_mod_lshift_quick(r, r, n, m))
+		goto err;
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_mod_lshift);
+
+/*
+ * BN_mod_lshift() variant that may be used if a is non-negative
+ * and has already been reduced (less than m).
+ */
+int
+BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
+{
+	int max_shift;
+
+	if (r == m) {
+		BNerror(BN_R_INVALID_ARGUMENT);
+		return 0;
+	}
+
+	if (!bn_copy(r, a))
+		return 0;
+
+	while (n > 0) {
+		if ((max_shift = BN_num_bits(m) - BN_num_bits(r)) < 0) {
+			BNerror(BN_R_INPUT_NOT_REDUCED);
+			return 0;
+		}
+		if (max_shift == 0)
+			max_shift = 1;
+		if (max_shift > n)
+			max_shift = n;
+
+		if (!BN_lshift(r, r, max_shift))
+			return 0;
+		n -= max_shift;
+
+		if (BN_ucmp(r, m) >= 0) {
+			if (!BN_usub(r, r, m))
+				return 0;
+		}
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(BN_mod_lshift_quick);
diff --git a/crypto/bn/bn_mod_sqrt.c b/crypto/bn/bn_mod_sqrt.c
new file mode 100644
index 0000000..280002c
--- /dev/null
+++ b/crypto/bn/bn_mod_sqrt.c
@@ -0,0 +1,723 @@
+/*	$OpenBSD: bn_mod_sqrt.c,v 1.3 2023/08/03 18:53:55 tb Exp $ */
+
+/*
+ * Copyright (c) 2022 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bn_local.h"
+
+/*
+ * Tonelli-Shanks according to H. Cohen "A Course in Computational Algebraic
+ * Number Theory", Section 1.5.1, Springer GTM volume 138, Berlin, 1996.
+ *
+ * Under the assumption that p is prime and a is a quadratic residue, we know:
+ *
+ *	a^[(p-1)/2] = 1 (mod p).					(*)
+ *
+ * To find a square root of a (mod p), we handle three cases of increasing
+ * complexity. In the first two cases, we can compute a square root using an
+ * explicit formula, thus avoiding the probabilistic nature of Tonelli-Shanks.
+ *
+ * 1. p = 3 (mod 4).
+ *
+ *    Set n = (p+1)/4. Then 2n = 1 + (p-1)/2 and (*) shows that x = a^n (mod p)
+ *    is a square root of a: x^2 = a^(2n) = a * a^[(p-1)/2] = a (mod p).
+ *
+ * 2. p = 5 (mod 8).
+ *
+ *    This uses a simplification due to Atkin. By Theorem 1.4.7 and 1.4.9, the
+ *    Kronecker symbol (2/p) evaluates to (-1)^[(p^2-1)/8]. From p = 5 (mod 8)
+ *    we get (p^2-1)/8 = 1 (mod 2), so (2/p) = -1, and thus
+ *
+ *	2^[(p-1)/2] = -1 (mod p).					(**)
+ *
+ *    Set b = (2a)^[(p-5)/8]. With (p-1)/2 = 2 + (p-5)/2, (*) and (**) show
+ *
+ *	i = 2 a b^2	is a square root of -1 (mod p).
+ *
+ *    Indeed, i^2 = 2^2 a^2 b^4 = 2^[(p-1)/2] a^[(p-1)/2] = -1 (mod p). Because
+ *    of (i-1)^2 = -2i (mod p) and i (-i) = 1 (mod p), a square root of a is
+ *
+ *	x = a b (i-1)
+ *
+ *    as x^2 = a^2 b^2 (-2i) = a (2 a b^2) (-i) = a (mod p).
+ *
+ * 3. p = 1 (mod 8).
+ *
+ *    This is the Tonelli-Shanks algorithm. For a prime p, the multiplicative
+ *    group of GF(p) is cyclic of order p - 1 = 2^s q, with odd q. Denote its
+ *    2-Sylow subgroup by S. It is cyclic of order 2^s. The squares in S have
+ *    order dividing 2^(s-1). They are the even powers of any generator z of S.
+ *    If a is a quadratic residue, 1 = a^[(p-1)/2] = (a^q)^[2^(s-1)], so b = a^q
+ *    is a square in S. Therefore there is an integer k such that b z^(2k) = 1.
+ *    Set x = a^[(q+1)/2] z^k, and find x^2 = a (mod p).
+ *
+ *    The problem is thus reduced to finding a generator z of the 2-Sylow
+ *    subgroup S of GF(p)* and finding k. An iterative constructions avoids
+ *    the need for an explicit k, a generator is found by a randomized search.
+ *
+ * While we do not actually know that p is a prime number, we can still apply
+ * the formulas in cases 1 and 2 and verify that we have indeed found a square
+ * root of p. Similarly, in case 3, we can try to find a quadratic non-residue,
+ * which will fail for example if p is a square. The iterative construction
+ * may or may not find a candidate square root which we can then validate.
+ */
+
+/*
+ * Handle the cases where p is 2, p isn't odd or p is one. Since BN_mod_sqrt()
+ * can run on untrusted data, a primality check is too expensive. Also treat
+ * the obvious cases where a is 0 or 1.
+ */
+
+static int
+bn_mod_sqrt_trivial_cases(int *done, BIGNUM *out_sqrt, const BIGNUM *a,
+    const BIGNUM *p, BN_CTX *ctx)
+{
+	*done = 1;
+
+	if (BN_abs_is_word(p, 2))
+		return BN_set_word(out_sqrt, BN_is_odd(a));
+
+	if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		return 0;
+	}
+
+	if (BN_is_zero(a) || BN_is_one(a))
+		return BN_set_word(out_sqrt, BN_is_one(a));
+
+	*done = 0;
+
+	return 1;
+}
+
+/*
+ * Case 1. We know that (a/p) = 1 and that p = 3 (mod 4).
+ */
+
+static int
+bn_mod_sqrt_p_is_3_mod_4(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
+    BN_CTX *ctx)
+{
+	BIGNUM *n;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((n = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Calculate n = (|p| + 1) / 4. */
+	if (!BN_uadd(n, p, BN_value_one()))
+		goto err;
+	if (!BN_rshift(n, n, 2))
+		goto err;
+
+	/* By case 1 above, out_sqrt = a^n is a square root of a (mod p). */
+	if (!BN_mod_exp_ct(out_sqrt, a, n, p, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Case 2. We know that (a/p) = 1 and that p = 5 (mod 8).
+ */
+
+static int
+bn_mod_sqrt_p_is_5_mod_8(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
+    BN_CTX *ctx)
+{
+	BIGNUM *b, *i, *n, *tmp;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((i = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((n = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Calculate n = (|p| - 5) / 8. Since p = 5 (mod 8), simply shift. */
+	if (!BN_rshift(n, p, 3))
+		goto err;
+	BN_set_negative(n, 0);
+
+	/* Compute tmp = 2a (mod p) for later use. */
+	if (!BN_mod_lshift1(tmp, a, p, ctx))
+		goto err;
+
+	/* Calculate b = (2a)^n (mod p). */
+	if (!BN_mod_exp_ct(b, tmp, n, p, ctx))
+		goto err;
+
+	/* Calculate i = 2 a b^2 (mod p). */
+	if (!BN_mod_sqr(i, b, p, ctx))
+		goto err;
+	if (!BN_mod_mul(i, tmp, i, p, ctx))
+		goto err;
+
+	/* A square root is out_sqrt = a b (i-1) (mod p). */
+	if (!BN_sub_word(i, 1))
+		goto err;
+	if (!BN_mod_mul(out_sqrt, a, b, p, ctx))
+		goto err;
+	if (!BN_mod_mul(out_sqrt, out_sqrt, i, p, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Case 3. We know that (a/p) = 1 and that p = 1 (mod 8).
+ */
+
+/*
+ * Simple helper. To find a generator of the 2-Sylow subgroup of GF(p)*, we
+ * need to find a quadratic non-residue of p, i.e., n such that (n/p) = -1.
+ */
+
+static int
+bn_mod_sqrt_n_is_non_residue(int *is_non_residue, const BIGNUM *n,
+    const BIGNUM *p, BN_CTX *ctx)
+{
+	switch (BN_kronecker(n, p, ctx)) {
+	case -1:
+		*is_non_residue = 1;
+		return 1;
+	case 1:
+		*is_non_residue = 0;
+		return 1;
+	case 0:
+		/* n divides p, so ... */
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		return 0;
+	default:
+		return 0;
+	}
+}
+
+/*
+ * The following is the only non-deterministic part preparing Tonelli-Shanks.
+ *
+ * If we find n such that (n/p) = -1, then n^q (mod p) is a generator of the
+ * 2-Sylow subgroup of GF(p)*. To find such n, first try some small numbers,
+ * then random ones.
+ */
+
+static int
+bn_mod_sqrt_find_sylow_generator(BIGNUM *out_generator, const BIGNUM *p,
+    const BIGNUM *q, BN_CTX *ctx)
+{
+	BIGNUM *n, *p_abs;
+	int i, is_non_residue;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((n = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((p_abs = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	for (i = 2; i < 32; i++) {
+		if (!BN_set_word(n, i))
+			goto err;
+		if (!bn_mod_sqrt_n_is_non_residue(&is_non_residue, n, p, ctx))
+			goto err;
+		if (is_non_residue)
+			goto found;
+	}
+
+	if (!bn_copy(p_abs, p))
+		goto err;
+	BN_set_negative(p_abs, 0);
+
+	for (i = 0; i < 128; i++) {
+		if (!bn_rand_interval(n, 32, p_abs))
+			goto err;
+		if (!bn_mod_sqrt_n_is_non_residue(&is_non_residue, n, p, ctx))
+			goto err;
+		if (is_non_residue)
+			goto found;
+	}
+
+	/*
+	 * The probability to get here is < 2^(-128) for prime p. For squares
+	 * it is easy: for p = 1369 = 37^2 this happens in ~3% of runs.
+	 */
+
+	BNerror(BN_R_TOO_MANY_ITERATIONS);
+	goto err;
+
+ found:
+	/*
+	 * If p is prime, n^q generates the 2-Sylow subgroup S of GF(p)*.
+	 */
+
+	if (!BN_mod_exp_ct(out_generator, n, q, p, ctx))
+		goto err;
+
+	/* Sanity: p is not necessarily prime, so we could have found 0 or 1. */
+	if (BN_is_zero(out_generator) || BN_is_one(out_generator)) {
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Initialization step for Tonelli-Shanks.
+ *
+ * In the end, b = a^q (mod p) and x = a^[(q+1)/2] (mod p). Cohen optimizes this
+ * to minimize taking powers of a. This is a bit confusing and distracting, so
+ * factor this into a separate function.
+ */
+
+static int
+bn_mod_sqrt_tonelli_shanks_initialize(BIGNUM *b, BIGNUM *x, const BIGNUM *a,
+    const BIGNUM *p, const BIGNUM *q, BN_CTX *ctx)
+{
+	BIGNUM *k;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* k = (q-1)/2. Since q is odd, we can shift. */
+	if (!BN_rshift1(k, q))
+		goto err;
+
+	/* x = a^[(q-1)/2] (mod p). */
+	if (!BN_mod_exp_ct(x, a, k, p, ctx))
+		goto err;
+
+	/* b = ax^2 = a^q (mod p). */
+	if (!BN_mod_sqr(b, x, p, ctx))
+		goto err;
+	if (!BN_mod_mul(b, a, b, p, ctx))
+		goto err;
+
+	/* x = ax = a^[(q+1)/2] (mod p). */
+	if (!BN_mod_mul(x, a, x, p, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Find smallest exponent m such that b^(2^m) = 1 (mod p). Assuming that a
+ * is a quadratic residue and p is a prime, we know that 1 <= m < r.
+ */
+
+static int
+bn_mod_sqrt_tonelli_shanks_find_exponent(int *out_exponent, const BIGNUM *b,
+    const BIGNUM *p, int r, BN_CTX *ctx)
+{
+	BIGNUM *x;
+	int m;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * If r <= 1, the Tonelli-Shanks iteration should have terminated as
+	 * r == 1 implies b == 1.
+	 */
+	if (r <= 1) {
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		goto err;
+	}
+
+	/*
+	 * Sanity check to ensure taking squares actually does something:
+	 * If b is 1, the Tonelli-Shanks iteration should have terminated.
+	 * If b is 0, something's very wrong, in particular p can't be prime.
+	 */
+	if (BN_is_zero(b) || BN_is_one(b)) {
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		goto err;
+	}
+
+	if (!bn_copy(x, b))
+		goto err;
+
+	for (m = 1; m < r; m++) {
+		if (!BN_mod_sqr(x, x, p, ctx))
+			goto err;
+		if (BN_is_one(x))
+			break;
+	}
+
+	if (m >= r) {
+		/* This means a is not a quadratic residue. As (a/p) = 1, ... */
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		goto err;
+	}
+
+	*out_exponent = m;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * The update step. With the minimal m such that b^(2^m) = 1 (mod m),
+ * set t = y^[2^(r-m-1)] (mod p) and update x = xt, y = t^2, b = by.
+ * This preserves the loop invariants a b = x^2, y^[2^(r-1)] = -1 and
+ * b^[2^(r-1)] = 1.
+ */
+
+static int
+bn_mod_sqrt_tonelli_shanks_update(BIGNUM *b, BIGNUM *x, BIGNUM *y,
+    const BIGNUM *p, int m, int r, BN_CTX *ctx)
+{
+	BIGNUM *t;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((t = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* t = y^[2^(r-m-1)] (mod p). */
+	if (!BN_set_bit(t, r - m - 1))
+		goto err;
+	if (!BN_mod_exp_ct(t, y, t, p, ctx))
+		goto err;
+
+	/* x = xt (mod p). */
+	if (!BN_mod_mul(x, x, t, p, ctx))
+		goto err;
+
+	/* y = t^2 = y^[2^(r-m)] (mod p). */
+	if (!BN_mod_sqr(y, t, p, ctx))
+		goto err;
+
+	/* b = by (mod p). */
+	if (!BN_mod_mul(b, b, y, p, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+static int
+bn_mod_sqrt_p_is_1_mod_8(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
+    BN_CTX *ctx)
+{
+	BIGNUM *b, *q, *x, *y;
+	int e, m, r;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((q = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Factor p - 1 = 2^e q with odd q. Since p = 1 (mod 8), we know e >= 3.
+	 */
+
+	e = 1;
+	while (!BN_is_bit_set(p, e))
+		e++;
+	if (!BN_rshift(q, p, e))
+		goto err;
+
+	if (!bn_mod_sqrt_find_sylow_generator(y, p, q, ctx))
+		goto err;
+
+	/*
+	 * Set b = a^q (mod p) and x = a^[(q+1)/2] (mod p).
+	 */
+	if (!bn_mod_sqrt_tonelli_shanks_initialize(b, x, a, p, q, ctx))
+		goto err;
+
+	/*
+	 * The Tonelli-Shanks iteration. Starting with r = e, the following loop
+	 * invariants hold at the start of the loop.
+	 *
+	 *	a b		= x^2	(mod p)
+	 *	y^[2^(r-1)]	= -1	(mod p)
+	 *	b^[2^(r-1)]	= 1	(mod p)
+	 *
+	 * In particular, if b = 1 (mod p), x is a square root of a.
+	 *
+	 * Since p - 1 = 2^e q, we have 2^(e-1) q = (p - 1) / 2, so in the first
+	 * iteration this follows from (a/p) = 1, (n/p) = -1, y = n^q, b = a^q.
+	 *
+	 * In subsequent iterations, t = y^[2^(r-m-1)], where m is the smallest
+	 * m such that b^(2^m) = 1. With x = xt (mod p) and b = bt^2 (mod p) the
+	 * first invariant is preserved, the second and third follow from
+	 * y = t^2 (mod p) and r = m as well as the choice of m.
+	 *
+	 * Finally, r is strictly decreasing in each iteration. If p is prime,
+	 * let S be the 2-Sylow subgroup of GF(p)*. We can prove the algorithm
+	 * stops: Let S_r be the subgroup of S consisting of elements of order
+	 * dividing 2^r. Then S_r =  and b is in S_(r-1). The S_r form a
+	 * descending filtration of S and when r = 1, then b = 1.
+	 */
+
+	for (r = e; r >= 1; r = m) {
+		/*
+		 * Termination condition. If b == 1 then x is a square root.
+		 */
+		if (BN_is_one(b))
+			goto done;
+
+		/* Find smallest exponent 1 <= m < r such that b^(2^m) == 1. */
+		if (!bn_mod_sqrt_tonelli_shanks_find_exponent(&m, b, p, r, ctx))
+			goto err;
+
+		/*
+		 * With t = y^[2^(r-m-1)], update x = xt, y = t^2, b = by.
+		 */
+		if (!bn_mod_sqrt_tonelli_shanks_update(b, x, y, p, m, r, ctx))
+			goto err;
+
+		/*
+		 * Sanity check to make sure we don't loop indefinitely.
+		 * bn_mod_sqrt_tonelli_shanks_find_exponent() ensures m < r.
+		 */
+		if (r <= m)
+			goto err;
+	}
+
+	/*
+	 * If p is prime, we should not get here.
+	 */
+
+	BNerror(BN_R_NOT_A_SQUARE);
+	goto err;
+
+ done:
+	if (!bn_copy(out_sqrt, x))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Choose the smaller of sqrt and |p| - sqrt.
+ */
+
+static int
+bn_mod_sqrt_normalize(BIGNUM *sqrt, const BIGNUM *p, BN_CTX *ctx)
+{
+	BIGNUM *x;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_lshift1(x, sqrt))
+		goto err;
+
+	if (BN_ucmp(x, p) > 0) {
+		if (!BN_usub(sqrt, p, sqrt))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+/*
+ * Verify that a = (sqrt_a)^2 (mod p). Requires that a is reduced (mod p).
+ */
+
+static int
+bn_mod_sqrt_verify(const BIGNUM *a, const BIGNUM *sqrt_a, const BIGNUM *p,
+    BN_CTX *ctx)
+{
+	BIGNUM *x;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_mod_sqr(x, sqrt_a, p, ctx))
+		goto err;
+
+	if (BN_cmp(x, a) != 0) {
+		BNerror(BN_R_NOT_A_SQUARE);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+static int
+bn_mod_sqrt_internal(BIGNUM *out_sqrt, const BIGNUM *a, const BIGNUM *p,
+    BN_CTX *ctx)
+{
+	BIGNUM *a_mod_p, *sqrt;
+	BN_ULONG lsw;
+	int done;
+	int kronecker;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((a_mod_p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((sqrt = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_nnmod(a_mod_p, a, p, ctx))
+		goto err;
+
+	if (!bn_mod_sqrt_trivial_cases(&done, sqrt, a_mod_p, p, ctx))
+		goto err;
+	if (done)
+		goto verify;
+
+	/*
+	 * Make sure that the Kronecker symbol (a/p) == 1. In case p is prime
+	 * this is equivalent to a having a square root (mod p). The cost of
+	 * BN_kronecker() is O(log^2(n)). This is small compared to the cost
+	 * O(log^4(n)) of Tonelli-Shanks.
+	 */
+
+	if ((kronecker = BN_kronecker(a_mod_p, p, ctx)) == -2)
+		goto err;
+	if (kronecker <= 0) {
+		/* This error is only accurate if p is known to be a prime. */
+		BNerror(BN_R_NOT_A_SQUARE);
+		goto err;
+	}
+
+	lsw = BN_lsw(p);
+
+	if (lsw % 4 == 3) {
+		if (!bn_mod_sqrt_p_is_3_mod_4(sqrt, a_mod_p, p, ctx))
+			goto err;
+	} else if (lsw % 8 == 5) {
+		if (!bn_mod_sqrt_p_is_5_mod_8(sqrt, a_mod_p, p, ctx))
+			goto err;
+	} else if (lsw % 8 == 1) {
+		if (!bn_mod_sqrt_p_is_1_mod_8(sqrt, a_mod_p, p, ctx))
+			goto err;
+	} else {
+		/* Impossible to hit since the trivial cases ensure p is odd. */
+		BNerror(BN_R_P_IS_NOT_PRIME);
+		goto err;
+	}
+
+	if (!bn_mod_sqrt_normalize(sqrt, p, ctx))
+		goto err;
+
+ verify:
+	if (!bn_mod_sqrt_verify(a_mod_p, sqrt, p, ctx))
+		goto err;
+
+	if (!bn_copy(out_sqrt, sqrt))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+BIGNUM *
+BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
+{
+	BIGNUM *out_sqrt;
+
+	if ((out_sqrt = in) == NULL)
+		out_sqrt = BN_new();
+	if (out_sqrt == NULL)
+		goto err;
+
+	if (!bn_mod_sqrt_internal(out_sqrt, a, p, ctx))
+		goto err;
+
+	return out_sqrt;
+
+ err:
+	if (out_sqrt != in)
+		BN_free(out_sqrt);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(BN_mod_sqrt);
diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c
new file mode 100644
index 0000000..12fea44
--- /dev/null
+++ b/crypto/bn/bn_mont.c
@@ -0,0 +1,607 @@
+/* $OpenBSD: bn_mont.c,v 1.61 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+ * Details about Montgomery multiplication algorithms can be found at
+ * http://security.ece.orst.edu/publications.html, e.g.
+ * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
+ * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
+ */
+
+#include 
+#include 
+#include 
+
+#include "bn_internal.h"
+#include "bn_local.h"
+
+BN_MONT_CTX *
+BN_MONT_CTX_new(void)
+{
+	BN_MONT_CTX *mctx;
+
+	if ((mctx = calloc(1, sizeof(BN_MONT_CTX))) == NULL)
+		return NULL;
+	mctx->flags = BN_FLG_MALLOCED;
+
+	BN_init(&mctx->RR);
+	BN_init(&mctx->N);
+
+	return mctx;
+}
+LCRYPTO_ALIAS(BN_MONT_CTX_new);
+
+void
+BN_MONT_CTX_free(BN_MONT_CTX *mctx)
+{
+	if (mctx == NULL)
+		return;
+
+	BN_free(&mctx->RR);
+	BN_free(&mctx->N);
+
+	if (mctx->flags & BN_FLG_MALLOCED)
+		free(mctx);
+}
+LCRYPTO_ALIAS(BN_MONT_CTX_free);
+
+BN_MONT_CTX *
+BN_MONT_CTX_copy(BN_MONT_CTX *dst, BN_MONT_CTX *src)
+{
+	if (dst == src)
+		return dst;
+
+	if (!bn_copy(&dst->RR, &src->RR))
+		return NULL;
+	if (!bn_copy(&dst->N, &src->N))
+		return NULL;
+
+	dst->ri = src->ri;
+	dst->n0[0] = src->n0[0];
+	dst->n0[1] = src->n0[1];
+
+	return dst;
+}
+LCRYPTO_ALIAS(BN_MONT_CTX_copy);
+
+int
+BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
+{
+	BIGNUM *N, *Ninv, *Rinv, *R;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((N = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Ninv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((R = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Rinv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Save modulus and determine length of R. */
+	if (BN_is_zero(mod))
+		goto err;
+	if (!bn_copy(&mont->N, mod))
+		 goto err;
+	mont->N.neg = 0;
+	mont->ri = ((BN_num_bits(mod) + BN_BITS2 - 1) / BN_BITS2) * BN_BITS2;
+	if (mont->ri * 2 < mont->ri)
+		goto err;
+
+	/*
+	 * Compute Ninv = (R * Rinv - 1)/N mod R, for R = 2^64. This provides
+	 * a single or double word result (dependent on BN word size), that is
+	 * later used to implement Montgomery reduction.
+	 */
+	BN_zero(R);
+	if (!BN_set_bit(R, 64))
+		goto err;
+
+	/* N = N mod R. */
+	if (!bn_wexpand(N, 2))
+		goto err;
+	if (!BN_set_word(N, mod->d[0]))
+		goto err;
+#if BN_BITS2 == 32
+	if (mod->top > 1) {
+		N->d[1] = mod->d[1];
+		N->top += bn_ct_ne_zero(N->d[1]);
+	}
+#endif
+
+	/* Rinv = R^-1 mod N */
+	if ((BN_mod_inverse_ct(Rinv, R, N, ctx)) == NULL)
+		goto err;
+
+	/* Ninv = (R * Rinv - 1) / N */
+	if (!BN_lshift(Ninv, Rinv, 64))
+		goto err;
+	if (BN_is_zero(Ninv)) {
+		/* R * Rinv == 0, set to R so that R * Rinv - 1 is mod R. */
+		if (!BN_set_bit(Ninv, 64))
+			goto err;
+	}
+	if (!BN_sub_word(Ninv, 1))
+		goto err;
+	if (!BN_div_ct(Ninv, NULL, Ninv, N, ctx))
+		goto err;
+
+	/* Store least significant word(s) of Ninv. */
+	mont->n0[0] = mont->n0[1] = 0;
+	if (Ninv->top > 0)
+		mont->n0[0] = Ninv->d[0];
+#if BN_BITS2 == 32
+	/* Some BN_BITS2 == 32 platforms (namely parisc) use two words of Ninv. */
+	if (Ninv->top > 1)
+		mont->n0[1] = Ninv->d[1];
+#endif
+
+	/* Compute RR = R * R mod N, for use when converting to Montgomery form. */
+	BN_zero(&mont->RR);
+	if (!BN_set_bit(&mont->RR, mont->ri * 2))
+		goto err;
+	if (!BN_mod_ct(&mont->RR, &mont->RR, &mont->N, ctx))
+		goto err;
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_MONT_CTX_set);
+
+BN_MONT_CTX *
+BN_MONT_CTX_set_locked(BN_MONT_CTX **pmctx, int lock, const BIGNUM *mod,
+    BN_CTX *ctx)
+{
+	BN_MONT_CTX *mctx = NULL;
+
+	CRYPTO_r_lock(lock);
+	mctx = *pmctx;
+	CRYPTO_r_unlock(lock);
+
+	if (mctx != NULL)
+		goto done;
+
+	if ((mctx = BN_MONT_CTX_new()) == NULL)
+		goto err;
+	if (!BN_MONT_CTX_set(mctx, mod, ctx))
+		goto err;
+
+	CRYPTO_w_lock(lock);
+	if (*pmctx != NULL) {
+		/* Someone else raced us... */
+		BN_MONT_CTX_free(mctx);
+		mctx = *pmctx;
+	} else {
+		*pmctx = mctx;
+	}
+	CRYPTO_w_unlock(lock);
+
+	goto done;
+ err:
+	BN_MONT_CTX_free(mctx);
+	mctx = NULL;
+ done:
+	return mctx;
+}
+LCRYPTO_ALIAS(BN_MONT_CTX_set_locked);
+
+static int bn_montgomery_reduce(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mctx);
+
+static int
+bn_mod_mul_montgomery_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+    BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	BIGNUM *tmp;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (a == b) {
+		if (!BN_sqr(tmp, a, ctx))
+			goto err;
+	} else {
+		if (!BN_mul(tmp, a, b, ctx))
+			goto err;
+	}
+
+	/* Reduce from aRR to aR. */
+	if (!bn_montgomery_reduce(r, tmp, mctx))
+		goto err;
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+static void
+bn_montgomery_multiply_word(const BN_ULONG *ap, BN_ULONG b, const BN_ULONG *np,
+    BN_ULONG *tp, BN_ULONG w, BN_ULONG *carry_a, BN_ULONG *carry_n, int n_len)
+{
+	BN_ULONG x3, x2, x1, x0;
+
+	*carry_a = *carry_n = 0;
+
+	while (n_len & ~3) {
+		bn_qwmulw_addqw_addw(ap[3], ap[2], ap[1], ap[0], b,
+		    tp[3], tp[2], tp[1], tp[0], *carry_a, carry_a,
+		    &x3, &x2, &x1, &x0);
+		bn_qwmulw_addqw_addw(np[3], np[2], np[1], np[0], w,
+		    x3, x2, x1, x0, *carry_n, carry_n,
+		    &tp[3], &tp[2], &tp[1], &tp[0]);
+		ap += 4;
+		np += 4;
+		tp += 4;
+		n_len -= 4;
+	}
+	while (n_len > 0) {
+		bn_mulw_addw_addw(ap[0], b, tp[0], *carry_a, carry_a, &x0);
+		bn_mulw_addw_addw(np[0], w, x0, *carry_n, carry_n, &tp[0]);
+		ap++;
+		np++;
+		tp++;
+		n_len--;
+	}
+}
+
+/*
+ * bn_montgomery_multiply_words() computes r = aR * bR * R^-1 = abR for the
+ * given word arrays. The caller must ensure that rp, ap, bp and np are all
+ * n_len words in length, while tp must be n_len * 2 + 2 words in length.
+ */
+void
+bn_montgomery_multiply_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+    const BN_ULONG *np, BN_ULONG *tp, BN_ULONG n0, int n_len)
+{
+	BN_ULONG a0, b, carry_a, carry_n, carry, mask, w;
+	int i;
+
+	carry = 0;
+
+	for (i = 0; i < n_len; i++)
+		tp[i] = 0;
+
+	a0 = ap[0];
+
+	for (i = 0; i < n_len; i++) {
+		b = bp[i];
+
+		/* Compute new t[0] * n0, as we need it for this iteration. */
+		w = (a0 * b + tp[0]) * n0;
+
+		bn_montgomery_multiply_word(ap, b, np, tp, w, &carry_a,
+		    &carry_n, n_len);
+		bn_addw_addw(carry_a, carry_n, carry, &carry, &tp[n_len]);
+
+		tp++;
+	}
+	tp[n_len] = carry;
+
+	/*
+	 * The output is now in the range of [0, 2N). Attempt to reduce once by
+	 * subtracting the modulus. If the reduction was necessary then the
+	 * result is already in r, otherwise copy the value prior to reduction
+	 * from tp.
+	 */
+	mask = bn_ct_ne_zero(tp[n_len]) - bn_sub_words(rp, tp, np, n_len);
+
+	for (i = 0; i < n_len; i++) {
+		*rp = (*rp & ~mask) | (*tp & mask);
+		rp++;
+		tp++;
+	}
+}
+
+/*
+ * bn_montgomery_multiply() computes r = aR * bR * R^-1 = abR for the given
+ * BIGNUMs. The caller must ensure that the modulus is two or more words in
+ * length and that a and b have the same number of words as the modulus.
+ */
+int
+bn_montgomery_multiply(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+    BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	BIGNUM *t;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
+		goto err;
+	if (!bn_wexpand(r, mctx->N.top))
+		goto err;
+
+	if ((t = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (!bn_wexpand(t, mctx->N.top * 2 + 2))
+		goto err;
+
+	bn_montgomery_multiply_words(r->d, a->d, b->d, mctx->N.d, t->d,
+	    mctx->n0[0], mctx->N.top);
+
+	r->top = mctx->N.top;
+	bn_correct_top(r);
+
+	BN_set_negative(r, a->neg ^ b->neg);
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+#ifndef OPENSSL_BN_ASM_MONT
+int
+bn_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+    BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
+		return bn_mod_mul_montgomery_simple(r, a, b, mctx, ctx);
+
+	return bn_montgomery_multiply(r, a, b, mctx, ctx);
+}
+#else
+
+int
+bn_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+    BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	if (mctx->N.top <= 1 || a->top != mctx->N.top || b->top != mctx->N.top)
+		return bn_mod_mul_montgomery_simple(r, a, b, mctx, ctx);
+
+	/*
+	 * Legacy bn_mul_mont() performs stack based allocation, without
+	 * size limitation. Allowing a large size results in the stack
+	 * being blown.
+	 */
+	if (mctx->N.top > (8 * 1024 / sizeof(BN_ULONG)))
+		return bn_montgomery_multiply(r, a, b, mctx, ctx);
+
+	if (!bn_wexpand(r, mctx->N.top))
+		return 0;
+
+	/*
+	 * Legacy bn_mul_mont() can indicate that we should "fallback" to
+	 * another implementation.
+	 */
+	if (!bn_mul_mont(r->d, a->d, b->d, mctx->N.d, mctx->n0, mctx->N.top))
+		return bn_montgomery_multiply(r, a, b, mctx, ctx);
+
+	r->top = mctx->N.top;
+	bn_correct_top(r);
+
+	BN_set_negative(r, a->neg ^ b->neg);
+
+	return (1);
+}
+#endif
+
+int
+BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+    BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	/* Compute r = aR * bR * R^-1 mod N = abR mod N */
+	return bn_mod_mul_montgomery(r, a, b, mctx, ctx);
+}
+LCRYPTO_ALIAS(BN_mod_mul_montgomery);
+
+int
+BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	/* Compute r = a * R * R * R^-1 mod N = aR mod N */
+	return bn_mod_mul_montgomery(r, a, &mctx->RR, mctx, ctx);
+}
+LCRYPTO_ALIAS(BN_to_montgomery);
+
+/*
+ * bn_montgomery_reduce() performs Montgomery reduction, reducing the input
+ * from its Montgomery form aR to a, returning the result in r. Note that the
+ * input is mutated in the process of performing the reduction, destroying its
+ * original value.
+ */
+static int
+bn_montgomery_reduce(BIGNUM *r, BIGNUM *a, BN_MONT_CTX *mctx)
+{
+	BIGNUM *n;
+	BN_ULONG *ap, *rp, n0, v, carry, mask;
+	int i, max, n_len;
+
+	n = &mctx->N;
+	n_len = mctx->N.top;
+
+	if (n_len == 0) {
+		BN_zero(r);
+		return 1;
+	}
+
+	if (!bn_wexpand(r, n_len))
+		return 0;
+
+	/*
+	 * Expand a to twice the length of the modulus, zero if necessary.
+	 * XXX - make this a requirement of the caller.
+	 */
+	if ((max = 2 * n_len) < n_len)
+		return 0;
+	if (!bn_wexpand(a, max))
+		return 0;
+	for (i = a->top; i < max; i++)
+		a->d[i] = 0;
+
+	carry = 0;
+	n0 = mctx->n0[0];
+
+	/* Add multiples of the modulus, so that it becomes divisible by R. */
+	for (i = 0; i < n_len; i++) {
+		v = bn_mul_add_words(&a->d[i], n->d, n_len, a->d[i] * n0);
+		bn_addw_addw(v, a->d[i + n_len], carry, &carry,
+		    &a->d[i + n_len]);
+	}
+
+	/* Divide by R (this is the equivalent of right shifting by n_len). */
+	ap = &a->d[n_len];
+
+	/*
+	 * The output is now in the range of [0, 2N). Attempt to reduce once by
+	 * subtracting the modulus. If the reduction was necessary then the
+	 * result is already in r, otherwise copy the value prior to reduction
+	 * from the top half of a.
+	 */
+	mask = carry - bn_sub_words(r->d, ap, n->d, n_len);
+
+	rp = r->d;
+	for (i = 0; i < n_len; i++) {
+		*rp = (*rp & ~mask) | (*ap & mask);
+		rp++;
+		ap++;
+	}
+	r->top = n_len;
+
+	bn_correct_top(r);
+
+	BN_set_negative(r, a->neg ^ n->neg);
+
+	return 1;
+}
+
+int
+BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mctx, BN_CTX *ctx)
+{
+	BIGNUM *tmp;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (!bn_copy(tmp, a))
+		goto err;
+	if (!bn_montgomery_reduce(r, tmp, mctx))
+		goto err;
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_from_montgomery);
diff --git a/crypto/bn/bn_mul.c b/crypto/bn/bn_mul.c
new file mode 100644
index 0000000..bdeb9b0
--- /dev/null
+++ b/crypto/bn/bn_mul.c
@@ -0,0 +1,370 @@
+/* $OpenBSD: bn_mul.c,v 1.39 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bn_arch.h"
+#include "bn_internal.h"
+#include "bn_local.h"
+
+/*
+ * bn_mul_comba4() computes r[] = a[] * b[] using Comba multiplication
+ * (https://everything2.com/title/Comba+multiplication), where a and b are both
+ * four word arrays, producing an eight word array result.
+ */
+#ifndef HAVE_BN_MUL_COMBA4
+void
+bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
+{
+	BN_ULONG c0, c1, c2;
+
+	bn_mulw_addtw(a[0], b[0],  0,  0,  0, &c2, &c1, &r[0]);
+
+	bn_mulw_addtw(a[0], b[1],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[0], c2, c1, c0, &c2, &c1, &r[1]);
+
+	bn_mulw_addtw(a[2], b[0],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[0], b[2], c2, c1, c0, &c2, &c1, &r[2]);
+
+	bn_mulw_addtw(a[0], b[3],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[0], c2, c1, c0, &c2, &c1, &r[3]);
+
+	bn_mulw_addtw(a[3], b[1],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[3], c2, c1, c0, &c2, &c1, &r[4]);
+
+	bn_mulw_addtw(a[2], b[3],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[2], c2, c1, c0, &c2, &c1, &r[5]);
+
+	bn_mulw_addtw(a[3], b[3],  0, c2, c1, &c2, &r[7], &r[6]);
+}
+#endif
+
+/*
+ * bn_mul_comba8() computes r[] = a[] * b[] using Comba multiplication
+ * (https://everything2.com/title/Comba+multiplication), where a and b are both
+ * eight word arrays, producing a 16 word array result.
+ */
+#ifndef HAVE_BN_MUL_COMBA8
+void
+bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
+{
+	BN_ULONG c0, c1, c2;
+
+	bn_mulw_addtw(a[0], b[0],  0,  0,  0, &c2, &c1, &r[0]);
+
+	bn_mulw_addtw(a[0], b[1],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[0], c2, c1, c0, &c2, &c1, &r[1]);
+
+	bn_mulw_addtw(a[2], b[0],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[0], b[2], c2, c1, c0, &c2, &c1, &r[2]);
+
+	bn_mulw_addtw(a[0], b[3],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[0], c2, c1, c0, &c2, &c1, &r[3]);
+
+	bn_mulw_addtw(a[4], b[0],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[0], b[4], c2, c1, c0, &c2, &c1, &r[4]);
+
+	bn_mulw_addtw(a[0], b[5],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[0], c2, c1, c0, &c2, &c1, &r[5]);
+
+	bn_mulw_addtw(a[6], b[0],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[0], b[6], c2, c1, c0, &c2, &c1, &r[6]);
+
+	bn_mulw_addtw(a[0], b[7],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[7], b[0], c2, c1, c0, &c2, &c1, &r[7]);
+
+	bn_mulw_addtw(a[7], b[1],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[2], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[1], b[7], c2, c1, c0, &c2, &c1, &r[8]);
+
+	bn_mulw_addtw(a[2], b[7],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[7], b[2], c2, c1, c0, &c2, &c1, &r[9]);
+
+	bn_mulw_addtw(a[7], b[3],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[4], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[3], b[7], c2, c1, c0, &c2, &c1, &r[10]);
+
+	bn_mulw_addtw(a[4], b[7],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[5], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[7], b[4], c2, c1, c0, &c2, &c1, &r[11]);
+
+	bn_mulw_addtw(a[7], b[5],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[6], b[6], c2, c1, c0, &c2, &c1, &c0);
+	bn_mulw_addtw(a[5], b[7], c2, c1, c0, &c2, &c1, &r[12]);
+
+	bn_mulw_addtw(a[6], b[7],  0, c2, c1, &c2, &c1, &c0);
+	bn_mulw_addtw(a[7], b[6], c2, c1, c0, &c2, &c1, &r[13]);
+
+	bn_mulw_addtw(a[7], b[7],  0, c2, c1, &c2, &r[15], &r[14]);
+}
+#endif
+
+/*
+ * bn_mul_words() computes (carry:r[i]) = a[i] * w + carry, where a is an array
+ * of words and w is a single word. This should really be called bn_mulw_words()
+ * since only one input is an array. This is used as a step in the multiplication
+ * of word arrays.
+ */
+#ifndef HAVE_BN_MUL_WORDS
+BN_ULONG
+bn_mul_words(BN_ULONG *r, const BN_ULONG *a, int num, BN_ULONG w)
+{
+	BN_ULONG carry = 0;
+
+	assert(num >= 0);
+	if (num <= 0)
+		return 0;
+
+	while (num & ~3) {
+		bn_qwmulw_addw(a[3], a[2], a[1], a[0], w, carry, &carry,
+		    &r[3], &r[2], &r[1], &r[0]);
+		a += 4;
+		r += 4;
+		num -= 4;
+	}
+	while (num) {
+		bn_mulw_addw(a[0], w, carry, &carry, &r[0]);
+		a++;
+		r++;
+		num--;
+	}
+	return carry;
+}
+#endif
+
+/*
+ * bn_mul_add_words() computes (carry:r[i]) = a[i] * w + r[i] + carry, where
+ * a is an array of words and w is a single word. This should really be called
+ * bn_mulw_add_words() since only one input is an array. This is used as a step
+ * in the multiplication of word arrays.
+ */
+#ifndef HAVE_BN_MUL_ADD_WORDS
+BN_ULONG
+bn_mul_add_words(BN_ULONG *r, const BN_ULONG *a, int num, BN_ULONG w)
+{
+	BN_ULONG carry = 0;
+
+	assert(num >= 0);
+	if (num <= 0)
+		return 0;
+
+	while (num & ~3) {
+		bn_qwmulw_addqw_addw(a[3], a[2], a[1], a[0], w,
+		    r[3], r[2], r[1], r[0], carry, &carry,
+		    &r[3], &r[2], &r[1], &r[0]);
+		a += 4;
+		r += 4;
+		num -= 4;
+	}
+	while (num) {
+		bn_mulw_addw_addw(a[0], w, r[0], carry, &carry, &r[0]);
+		a++;
+		r++;
+		num--;
+	}
+
+	return carry;
+}
+#endif
+
+void
+bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb)
+{
+	BN_ULONG *rr;
+
+
+	if (na < nb) {
+		int itmp;
+		BN_ULONG *ltmp;
+
+		itmp = na;
+		na = nb;
+		nb = itmp;
+		ltmp = a;
+		a = b;
+		b = ltmp;
+
+	}
+	rr = &(r[na]);
+	if (nb <= 0) {
+		(void)bn_mul_words(r, a, na, 0);
+		return;
+	} else
+		rr[0] = bn_mul_words(r, a, na, b[0]);
+
+	for (;;) {
+		if (--nb <= 0)
+			return;
+		rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]);
+		if (--nb <= 0)
+			return;
+		rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]);
+		if (--nb <= 0)
+			return;
+		rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]);
+		if (--nb <= 0)
+			return;
+		rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]);
+		rr += 4;
+		r += 4;
+		b += 4;
+	}
+}
+
+
+#ifndef HAVE_BN_MUL
+int
+bn_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, int rn, BN_CTX *ctx)
+{
+	bn_mul_normal(r->d, a->d, a->top, b->d, b->top);
+
+	return 1;
+}
+
+#endif /* HAVE_BN_MUL */
+
+int
+BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+{
+	BIGNUM *rr;
+	int rn;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if (BN_is_zero(a) || BN_is_zero(b)) {
+		BN_zero(r);
+		goto done;
+	}
+
+	rr = r;
+	if (rr == a || rr == b)
+		rr = BN_CTX_get(ctx);
+	if (rr == NULL)
+		goto err;
+
+	rn = a->top + b->top;
+	if (rn < a->top)
+		goto err;
+	if (!bn_wexpand(rr, rn))
+		goto err;
+
+	if (a->top == 4 && b->top == 4) {
+		bn_mul_comba4(rr->d, a->d, b->d);
+	} else if (a->top == 8 && b->top == 8) {
+		bn_mul_comba8(rr->d, a->d, b->d);
+	} else {
+		if (!bn_mul(rr, a, b, rn, ctx))
+			goto err;
+	}
+
+	rr->top = rn;
+	bn_correct_top(rr);
+
+	BN_set_negative(rr, a->neg ^ b->neg);
+
+	if (!bn_copy(r, rr))
+		goto err;
+ done:
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_mul);
diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
new file mode 100644
index 0000000..5a4aa50
--- /dev/null
+++ b/crypto/bn/bn_prime.c
@@ -0,0 +1,423 @@
+/* $OpenBSD: bn_prime.c,v 1.34 2023/07/20 06:26:27 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "bn_local.h"
+
+/* The quick sieve algorithm approach to weeding out primes is
+ * Philip Zimmermann's, as implemented in PGP.  I have had a read of
+ * his comments and implemented my own version.
+ */
+#include "bn_prime.h"
+
+static int probable_prime(BIGNUM *rnd, int bits);
+static int probable_prime_dh(BIGNUM *rnd, int bits,
+    const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
+static int probable_prime_dh_safe(BIGNUM *rnd, int bits,
+    const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
+
+int
+BN_GENCB_call(BN_GENCB *cb, int a, int b)
+{
+	/* No callback means continue */
+	if (!cb)
+		return 1;
+	switch (cb->ver) {
+	case 1:
+		/* Deprecated-style callbacks */
+		if (!cb->cb.cb_1)
+			return 1;
+		cb->cb.cb_1(a, b, cb->arg);
+		return 1;
+	case 2:
+		/* New-style callbacks */
+		return cb->cb.cb_2(a, b, cb);
+	default:
+		break;
+	}
+	/* Unrecognised callback type */
+	return 0;
+}
+LCRYPTO_ALIAS(BN_GENCB_call);
+
+int
+BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
+    const BIGNUM *rem, BN_GENCB *cb)
+{
+	BN_CTX *ctx;
+	BIGNUM *p;
+	int is_prime;
+	int loops = 0;
+	int found = 0;
+
+	if (bits < 2 || (bits == 2 && safe)) {
+		/*
+		 * There are no prime numbers smaller than 2, and the smallest
+		 * safe prime (7) spans three bits.
+		 */
+		BNerror(BN_R_BITS_TOO_SMALL);
+		return 0;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+ loop:
+	/* Make a random number and set the top and bottom bits. */
+	if (add == NULL) {
+		if (!probable_prime(ret, bits))
+			goto err;
+	} else {
+		if (safe) {
+			if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
+				goto err;
+		} else {
+			if (!probable_prime_dh(ret, bits, add, rem, ctx))
+				goto err;
+		}
+	}
+
+	if (!BN_GENCB_call(cb, 0, loops++))
+		goto err;
+
+	if (!safe) {
+		if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
+			goto err;
+		if (!is_prime)
+			goto loop;
+	} else {
+		if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
+			goto err;
+		if (!is_prime)
+			goto loop;
+
+		/*
+		 * For safe prime generation, check that p = (ret-1)/2 is prime.
+		 * Since this prime has >= 3 bits, it is odd, and we can simply
+		 * divide by 2.
+		 */
+		if (!BN_rshift1(p, ret))
+			goto err;
+
+		if (!bn_is_prime_bpsw(&is_prime, p, ctx, 1))
+			goto err;
+		if (!is_prime)
+			goto loop;
+
+		if (!BN_GENCB_call(cb, 2, loops - 1))
+			goto err;
+	}
+
+	found = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return found;
+}
+LCRYPTO_ALIAS(BN_generate_prime_ex);
+
+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);
+}
+LCRYPTO_ALIAS(BN_is_prime_ex);
+
+#define BN_PRIME_MAXIMUM_BITS (32 * 1024)
+
+int
+BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
+    int do_trial_division, BN_GENCB *cb)
+{
+	int is_prime;
+
+	if (checks < 0)
+		return -1;
+
+	/*
+	 * Prime numbers this large do not appear in everyday cryptography
+	 * and checking such numbers for primality is very expensive.
+	 */
+	if (BN_num_bits(a) > BN_PRIME_MAXIMUM_BITS) {
+		BNerror(BN_R_BIGNUM_TOO_LONG);
+		return -1;
+	}
+
+	if (checks == BN_prime_checks)
+		checks = BN_prime_checks_for_size(BN_num_bits(a));
+
+	/* XXX - tickle BN_GENCB in bn_is_prime_bpsw(). */
+	if (!bn_is_prime_bpsw(&is_prime, a, ctx_passed, checks))
+		return -1;
+
+	return is_prime;
+}
+LCRYPTO_ALIAS(BN_is_prime_fasttest_ex);
+
+static int
+probable_prime(BIGNUM *rnd, int bits)
+{
+	int i;
+	BN_ULONG mods[NUMPRIMES];
+	BN_ULONG delta, maxdelta;
+
+again:
+	if (!BN_rand(rnd, bits, 1, 1))
+		return (0);
+	/* we now have a random number 'rand' to test. */
+	for (i = 1; i < NUMPRIMES; i++) {
+		BN_ULONG mod = BN_mod_word(rnd, primes[i]);
+		if (mod == (BN_ULONG)-1)
+			return (0);
+		mods[i] = mod;
+	}
+	maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
+	delta = 0;
+loop:
+	for (i = 1; i < NUMPRIMES; i++) {
+		/* check that rnd is not a prime and also
+		 * that gcd(rnd-1,primes) == 1 (except for 2) */
+		if (((mods[i] + delta) % primes[i]) <= 1) {
+			delta += 2;
+			if (delta > maxdelta)
+				goto again;
+			goto loop;
+		}
+	}
+	if (!BN_add_word(rnd, delta))
+		return (0);
+	return (1);
+}
+
+static int
+probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem,
+    BN_CTX *ctx)
+{
+	int i, ret = 0;
+	BIGNUM *t1;
+
+	BN_CTX_start(ctx);
+	if ((t1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_rand(rnd, bits, 0, 1))
+		goto err;
+
+	/* we need ((rnd-rem) % add) == 0 */
+
+	if (!BN_mod_ct(t1, rnd, add, ctx))
+		goto err;
+	if (!BN_sub(rnd, rnd, t1))
+		goto err;
+	if (rem == NULL) {
+		if (!BN_add_word(rnd, 1))
+			goto err;
+	} else {
+		if (!BN_add(rnd, rnd, rem))
+			goto err;
+	}
+
+	/* we now have a random number 'rand' to test. */
+
+loop:
+	for (i = 1; i < NUMPRIMES; i++) {
+		/* check that rnd is a prime */
+		BN_LONG mod = BN_mod_word(rnd, primes[i]);
+		if (mod == (BN_ULONG)-1)
+			goto err;
+		if (mod <= 1) {
+			if (!BN_add(rnd, rnd, add))
+				goto err;
+			goto loop;
+		}
+	}
+	ret = 1;
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+static int
+probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
+    const BIGNUM *rem, BN_CTX *ctx)
+{
+	int i, ret = 0;
+	BIGNUM *t1, *qadd, *q;
+
+	bits--;
+	BN_CTX_start(ctx);
+	if ((t1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((q = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((qadd = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_rshift1(qadd, padd))
+		goto err;
+
+	if (!BN_rand(q, bits, 0, 1))
+		goto err;
+
+	/* we need ((rnd-rem) % add) == 0 */
+	if (!BN_mod_ct(t1, q,qadd, ctx))
+		goto err;
+	if (!BN_sub(q, q, t1))
+		goto err;
+	if (rem == NULL) {
+		if (!BN_add_word(q, 1))
+			goto err;
+	} else {
+		if (!BN_rshift1(t1, rem))
+			goto err;
+		if (!BN_add(q, q, t1))
+			goto err;
+	}
+
+	/* we now have a random number 'rand' to test. */
+	if (!BN_lshift1(p, q))
+		goto err;
+	if (!BN_add_word(p, 1))
+		goto err;
+
+loop:
+	for (i = 1; i < NUMPRIMES; i++) {
+		/* check that p and q are prime */
+		/* check that for p and q
+		 * gcd(p-1,primes) == 1 (except for 2) */
+		BN_ULONG pmod = BN_mod_word(p, primes[i]);
+		BN_ULONG qmod = BN_mod_word(q, primes[i]);
+		if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1)
+			goto err;
+		if (pmod == 0 || qmod == 0) {
+			if (!BN_add(p, p, padd))
+				goto err;
+			if (!BN_add(q, q, qadd))
+				goto err;
+			goto loop;
+		}
+	}
+	ret = 1;
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
diff --git a/crypto/bn/bn_prime.h b/crypto/bn/bn_prime.h
new file mode 100644
index 0000000..4ea2d47
--- /dev/null
+++ b/crypto/bn/bn_prime.h
@@ -0,0 +1,14 @@
+/* $OpenBSD: bn_prime.h,v 1.9 2022/11/10 10:24:50 tb Exp $ */
+/*
+ * Public domain.
+ */
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+#define NUMPRIMES 2048
+
+extern const uint16_t primes[NUMPRIMES];
+
+__END_HIDDEN_DECLS
diff --git a/crypto/bn/bn_primitives.c b/crypto/bn/bn_primitives.c
new file mode 100644
index 0000000..66427a9
--- /dev/null
+++ b/crypto/bn/bn_primitives.c
@@ -0,0 +1,65 @@
+/* $OpenBSD: bn_primitives.c,v 1.2 2023/06/21 07:48:41 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bn_arch.h"
+#include "bn_internal.h"
+#include "bn_local.h"
+
+#ifndef HAVE_BN_CLZW
+#ifndef HAVE_BN_WORD_CLZ
+int
+bn_word_clz(BN_ULONG w)
+{
+	BN_ULONG bits, mask, shift;
+
+	bits = shift = BN_BITS2;
+	mask = 0;
+
+	while ((shift >>= 1) != 0) {
+		bits += (shift & mask) - (shift & ~mask);
+		mask = bn_ct_ne_zero_mask(w >> bits);
+	}
+	bits += 1 & mask;
+
+	bits -= bn_ct_eq_zero(w);
+
+	return BN_BITS2 - bits;
+}
+#endif
+#endif
+
+#ifndef HAVE_BN_BITSIZE
+int
+bn_bitsize(const BIGNUM *bn)
+{
+	BN_ULONG n = 0, x = 0;
+	BN_ULONG mask, w;
+	int i = 0;
+
+	while (i < bn->top) {
+		w = bn->d[i];
+		mask = bn_ct_ne_zero_mask(w);
+		n = ((BN_ULONG)i & mask) | (n & ~mask);
+		x = (w & mask) | (x & ~mask);
+		i++;
+	}
+
+	return (n + 1) * BN_BITS2 - bn_clzw(x);
+}
+#endif
diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c
new file mode 100644
index 0000000..e7678f7
--- /dev/null
+++ b/crypto/bn/bn_print.c
@@ -0,0 +1,190 @@
+/*	$OpenBSD: bn_print.c,v 1.46 2023/07/22 17:14:08 tb Exp $ */
+
+/*
+ * Copyright (c) 2023 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bn_local.h"
+#include "bytestring.h"
+
+static int
+bn_print_zero(BIO *bio, const BIGNUM *bn)
+{
+	if (!BN_is_zero(bn))
+		return 0;
+	if (BIO_printf(bio, " 0\n") <= 0)
+		return 0;
+	return 1;
+}
+
+static int
+bn_print_word(BIO *bio, const BIGNUM *bn)
+{
+	unsigned long long word;
+	const char *neg = "";
+
+	if (BN_is_zero(bn) || BN_num_bytes(bn) > BN_BYTES)
+		return 0;
+
+	if (BN_is_negative(bn))
+		neg = "-";
+
+	word = BN_get_word(bn);
+	if (BIO_printf(bio, " %s%llu (%s0x%llx)\n", neg, word, neg, word) <= 0)
+		return 0;
+
+	return 1;
+}
+
+static int
+bn_print_bignum(BIO *bio, const BIGNUM *bn, int indent)
+{
+	CBS cbs;
+	char *hex = NULL;
+	size_t hex_len = 0;
+	size_t octets = 0;
+	uint8_t hi, lo;
+	const char *sep = ":";
+	int ret = 0;
+
+	if (BN_num_bytes(bn) <= BN_BYTES)
+		goto err;
+
+	/* Secondary indent is 4 spaces, capped at 128. */
+	if (indent > 124)
+		indent = 124;
+	indent += 4;
+	if (indent < 0)
+		indent = 0;
+
+	if (!bn_bn2hex_nosign(bn, &hex, &hex_len))
+		goto err;
+
+	CBS_init(&cbs, hex, hex_len);
+
+	if (BN_is_negative(bn)) {
+		if (BIO_printf(bio, " (Negative)") <= 0)
+			goto err;
+	}
+
+	while (CBS_len(&cbs) > 0) {
+		if (!CBS_get_u8(&cbs, &hi))
+			goto err;
+		if (!CBS_get_u8(&cbs, &lo))
+			goto err;
+		if (octets++ % 15 == 0) {
+			if (BIO_printf(bio, "\n%*s", indent, "") <= 0)
+				goto err;
+		}
+		/* First nibble has the high bit set. Insert leading 0 octet. */
+		if (octets == 1 && hi >= '8') {
+			if (BIO_printf(bio, "00:") <= 0)
+				goto err;
+			octets++;
+		}
+		if (CBS_len(&cbs) == 0)
+			sep = "";
+		if (BIO_printf(bio, "%c%c%s", tolower(hi), tolower(lo), sep) <= 0)
+			goto err;
+	}
+
+	if (BIO_printf(bio, "\n") <= 0)
+		goto err;
+
+	ret = 1;
+
+ err:
+	freezero(hex, hex_len);
+
+	return ret;
+}
+
+int
+bn_printf(BIO *bio, const BIGNUM *bn, int indent, const char *fmt, ...)
+{
+	va_list ap;
+	int rv;
+
+	if (bn == NULL)
+		return 1;
+
+	if (!BIO_indent(bio, indent, 128))
+		return 0;
+
+	va_start(ap, fmt);
+	rv = BIO_vprintf(bio, fmt, ap);
+	va_end(ap);
+	if (rv < 0)
+		return 0;
+
+	if (BN_is_zero(bn))
+		return bn_print_zero(bio, bn);
+
+	if (BN_num_bytes(bn) <= BN_BYTES)
+		return bn_print_word(bio, bn);
+
+	return bn_print_bignum(bio, bn, indent);
+}
+
+int
+BN_print(BIO *bio, const BIGNUM *bn)
+{
+	char *hex = NULL;
+	size_t hex_len = 0;
+	int ret = 0;
+
+	if (!bn_bn2hex_nibbles(bn, &hex, &hex_len))
+		goto err;
+	if (BIO_printf(bio, "%s", hex) <= 0)
+		goto err;
+
+	ret = 1;
+
+ err:
+	freezero(hex, hex_len);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_print);
+
+int
+BN_print_fp(FILE *fp, const BIGNUM *bn)
+{
+	char *hex = NULL;
+	size_t hex_len = 0;
+	int ret = 0;
+
+	if (!bn_bn2hex_nibbles(bn, &hex, &hex_len))
+		goto err;
+	if (fprintf(fp, "%s", hex) < 0)
+		goto err;
+
+	ret = 1;
+
+ err:
+	freezero(hex, hex_len);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_print_fp);
diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c
new file mode 100644
index 0000000..a5b163c
--- /dev/null
+++ b/crypto/bn/bn_rand.c
@@ -0,0 +1,335 @@
+/* $OpenBSD: bn_rand.c,v 1.29 2023/08/03 18:53:55 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "bn_local.h"
+
+static int
+bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
+{
+	unsigned char *buf = NULL;
+	int ret = 0, bit, bytes, mask;
+
+	if (rnd == NULL) {
+		BNerror(ERR_R_PASSED_NULL_PARAMETER);
+		return (0);
+	}
+
+	if (bits < 0 || (bits == 1 && top > 0)) {
+		BNerror(BN_R_BITS_TOO_SMALL);
+		return (0);
+	}
+
+	if (bits == 0) {
+		BN_zero(rnd);
+		return (1);
+	}
+
+	bytes = (bits + 7) / 8;
+	bit = (bits - 1) % 8;
+	mask = 0xff << (bit + 1);
+
+	buf = malloc(bytes);
+	if (buf == NULL) {
+		BNerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* make a random number and set the top and bottom bits */
+	arc4random_buf(buf, bytes);
+
+#if 1
+	if (pseudorand == 2) {
+		/* generate patterns that are more likely to trigger BN
+		   library bugs */
+		int i;
+		unsigned char c;
+
+		for (i = 0; i < bytes; i++) {
+			arc4random_buf(&c, 1);
+			if (c >= 128 && i > 0)
+				buf[i] = buf[i - 1];
+			else if (c < 42)
+				buf[i] = 0;
+			else if (c < 84)
+				buf[i] = 255;
+		}
+	}
+#endif
+
+	if (top > 0) {
+		if (bit == 0) {
+			buf[0] = 1;
+			buf[1] |= 0x80;
+		} else {
+			buf[0] |= (3 << (bit - 1));
+		}
+	}
+	if (top == 0)
+		buf[0] |= (1 << bit);
+	buf[0] &= ~mask;
+	if (bottom) /* set bottom bit if requested */
+		buf[bytes - 1] |= 1;
+	if (BN_bin2bn(buf, bytes, rnd) == NULL)
+		goto err;
+	ret = 1;
+
+err:
+	freezero(buf, bytes);
+	return (ret);
+}
+
+int
+BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
+{
+	return bnrand(0, rnd, bits, top, bottom);
+}
+LCRYPTO_ALIAS(BN_rand);
+
+int
+BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
+{
+	return bnrand(1, rnd, bits, top, bottom);
+}
+LCRYPTO_ALIAS(BN_pseudo_rand);
+
+#if 1
+int
+BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
+{
+	return bnrand(2, rnd, bits, top, bottom);
+}
+#endif
+
+
+/* random number r:  0 <= r < range */
+static int
+bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
+{
+	int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand;
+	int n;
+	int count = 100;
+
+	if (range->neg || BN_is_zero(range)) {
+		BNerror(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 if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
+		/* range = 100..._2,
+		 * so  3*range (= 11..._2)  is exactly one bit longer than  range */
+		do {
+			if (!bn_rand(r, n + 1, -1, 0))
+				return 0;
+			/* If  r < 3*range,  use  r := r MOD range
+			 * (which is either  r, r - range,  or  r - 2*range).
+			 * Otherwise, iterate once more.
+			 * Since  3*range = 11..._2, each iteration succeeds with
+			 * probability >= .75. */
+			if (BN_cmp(r, range) >= 0) {
+				if (!BN_sub(r, r, range))
+					return 0;
+				if (BN_cmp(r, range) >= 0)
+					if (!BN_sub(r, r, range))
+						return 0;
+			}
+
+			if (!--count) {
+				BNerror(BN_R_TOO_MANY_ITERATIONS);
+				return 0;
+			}
+
+		} while (BN_cmp(r, range) >= 0);
+	} else {
+		do {
+			/* range = 11..._2  or  range = 101..._2 */
+			if (!bn_rand(r, n, -1, 0))
+				return 0;
+
+			if (!--count) {
+				BNerror(BN_R_TOO_MANY_ITERATIONS);
+				return 0;
+			}
+		} while (BN_cmp(r, range) >= 0);
+	}
+
+	return 1;
+}
+
+int
+BN_rand_range(BIGNUM *r, const BIGNUM *range)
+{
+	return bn_rand_range(0, r, range);
+}
+LCRYPTO_ALIAS(BN_rand_range);
+
+int
+bn_rand_in_range(BIGNUM *rnd, const BIGNUM *lower_inc, const BIGNUM *upper_exc)
+{
+	BIGNUM *len;
+	int ret = 0;
+
+	if ((len = BN_new()) == NULL)
+		goto err;
+	if (!BN_sub(len, upper_exc, lower_inc))
+		goto err;
+	if (!BN_rand_range(rnd, len))
+		goto err;
+	if (!BN_add(rnd, rnd, lower_inc))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_free(len);
+
+	return ret;
+}
+
+int
+bn_rand_interval(BIGNUM *rnd, BN_ULONG lower_word, const BIGNUM *upper_exc)
+{
+	BIGNUM *lower_inc = NULL;
+	int ret = 0;
+
+	if ((lower_inc = BN_new()) == NULL)
+		goto err;
+	if (!BN_set_word(lower_inc, lower_word))
+		goto err;
+	if (!bn_rand_in_range(rnd, lower_inc, upper_exc))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_free(lower_inc);
+
+	return ret;
+}
+
+int
+BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
+{
+	return bn_rand_range(1, r, range);
+}
+LCRYPTO_ALIAS(BN_pseudo_rand_range);
diff --git a/crypto/bn/bn_recp.c b/crypto/bn/bn_recp.c
new file mode 100644
index 0000000..35390e3
--- /dev/null
+++ b/crypto/bn/bn_recp.c
@@ -0,0 +1,260 @@
+/* $OpenBSD: bn_recp.c,v 1.19 2023/03/27 10:25:02 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include "bn_local.h"
+
+void
+BN_RECP_CTX_init(BN_RECP_CTX *recp)
+{
+	BN_init(&(recp->N));
+	BN_init(&(recp->Nr));
+	recp->num_bits = 0;
+	recp->flags = 0;
+}
+
+BN_RECP_CTX *
+BN_RECP_CTX_new(void)
+{
+	BN_RECP_CTX *ret;
+
+	if ((ret = malloc(sizeof(BN_RECP_CTX))) == NULL)
+		return (NULL);
+
+	BN_RECP_CTX_init(ret);
+	ret->flags = BN_FLG_MALLOCED;
+	return (ret);
+}
+
+void
+BN_RECP_CTX_free(BN_RECP_CTX *recp)
+{
+	if (recp == NULL)
+		return;
+
+	BN_free(&(recp->N));
+	BN_free(&(recp->Nr));
+	if (recp->flags & BN_FLG_MALLOCED)
+		free(recp);
+}
+
+int
+BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
+{
+	if (!bn_copy(&(recp->N), d))
+		return 0;
+	BN_zero(&(recp->Nr));
+	recp->num_bits = BN_num_bits(d);
+	recp->shift = 0;
+	return (1);
+}
+
+int
+BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
+    BN_RECP_CTX *recp, BN_CTX *ctx)
+{
+	int ret = 0;
+	BIGNUM *a;
+	const BIGNUM *ca;
+
+	BN_CTX_start(ctx);
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (y != NULL) {
+		if (x == y) {
+			if (!BN_sqr(a, x, ctx))
+				goto err;
+		} else {
+			if (!BN_mul(a, x, y, ctx))
+				goto err;
+		}
+		ca = a;
+	} else
+		ca = x; /* Just do the mod */
+
+	ret = BN_div_recp(NULL, r, ca, recp, ctx);
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+int
+BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
+    BN_CTX *ctx)
+{
+	int i, j, ret = 0;
+	BIGNUM *a, *b, *d, *r;
+
+	BN_CTX_start(ctx);
+	a = BN_CTX_get(ctx);
+	b = BN_CTX_get(ctx);
+	if (dv != NULL)
+		d = dv;
+	else
+		d = BN_CTX_get(ctx);
+	if (rem != NULL)
+		r = rem;
+	else
+		r = BN_CTX_get(ctx);
+	if (a == NULL || b == NULL || d == NULL || r == NULL)
+		goto err;
+
+	if (BN_ucmp(m, &(recp->N)) < 0) {
+		BN_zero(d);
+		if (!bn_copy(r, m)) {
+			BN_CTX_end(ctx);
+			return 0;
+		}
+		BN_CTX_end(ctx);
+		return (1);
+	}
+
+	/* We want the remainder
+	 * Given input of ABCDEF / ab
+	 * we need multiply ABCDEF by 3 digests of the reciprocal of ab
+	 *
+	 */
+
+	/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
+	i = BN_num_bits(m);
+	j = recp->num_bits << 1;
+	if (j > i)
+		i = j;
+
+	/* Nr := round(2^i / N) */
+	if (i != recp->shift)
+		recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);
+
+	/* BN_reciprocal returns i, or -1 for an error */
+	if (recp->shift == -1)
+		goto err;
+
+	/* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
+	 *    = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
+	 *   <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
+	 *    = |m/N|
+	 */
+	if (!BN_rshift(a, m, recp->num_bits))
+		goto err;
+	if (!BN_mul(b, a,&(recp->Nr), ctx))
+		goto err;
+	if (!BN_rshift(d, b, i - recp->num_bits))
+		goto err;
+	d->neg = 0;
+
+	if (!BN_mul(b, &(recp->N), d, ctx))
+		goto err;
+	if (!BN_usub(r, m, b))
+		goto err;
+	r->neg = 0;
+
+#if 1
+	j = 0;
+	while (BN_ucmp(r, &(recp->N)) >= 0) {
+		if (j++ > 2) {
+			BNerror(BN_R_BAD_RECIPROCAL);
+			goto err;
+		}
+		if (!BN_usub(r, r, &(recp->N)))
+			goto err;
+		if (!BN_add_word(d, 1))
+			goto err;
+	}
+#endif
+
+	BN_set_negative(r, m->neg);
+	BN_set_negative(d, m->neg ^ recp->N.neg);
+
+	ret = 1;
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
+
+/* len is the expected size of the result
+ * We actually calculate with an extra word of precision, so
+ * we can do faster division if the remainder is not required.
+ */
+/* r := 2^len / m */
+int
+BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)
+{
+	int ret = -1;
+	BIGNUM *t;
+
+	BN_CTX_start(ctx);
+	if ((t = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_set_bit(t, len))
+		goto err;
+
+	if (!BN_div_ct(r, NULL, t,m, ctx))
+		goto err;
+
+	ret = len;
+
+err:
+	BN_CTX_end(ctx);
+	return (ret);
+}
diff --git a/crypto/bn/bn_shift.c b/crypto/bn/bn_shift.c
new file mode 100644
index 0000000..12edc7c
--- /dev/null
+++ b/crypto/bn/bn_shift.c
@@ -0,0 +1,175 @@
+/* $OpenBSD: bn_shift.c,v 1.22 2023/07/08 12:21:58 beck Exp $ */
+/*
+ * Copyright (c) 2022, 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "bn_local.h"
+
+static inline int
+bn_lshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+	size_t count, shift_bits, shift_words;
+	size_t lshift, rshift;
+	ssize_t rstride;
+	BN_ULONG *dst, *src;
+
+	if (n < 0) {
+		BNerror(BN_R_INVALID_LENGTH);
+		return 0;
+	}
+	shift_bits = n;
+
+	/*
+	 * Left bit shift, potentially across word boundaries.
+	 *
+	 * When shift is not an exact multiple of BN_BITS2, the bottom bits of
+	 * the previous word need to be right shifted and combined with the left
+	 * shifted bits using bitwise OR. If shift is an exact multiple of
+	 * BN_BITS2, the source for the left and right shifts are the same
+	 * and the shifts become zero bits (which is effectively a memmove).
+	 */
+	shift_words = shift_bits / BN_BITS2;
+	lshift = shift_bits % BN_BITS2;
+	rshift = (BN_BITS2 - lshift) % BN_BITS2;
+	rstride = 0 - (lshift + rshift) / BN_BITS2;
+
+	if (a->top < 1) {
+		BN_zero(r);
+		return 1;
+	}
+
+	count = a->top + shift_words + 1;
+
+	if (count < shift_words)
+		return 0;
+
+	if (!bn_wexpand(r, count))
+		return 0;
+
+	src = a->d + a->top - 1;
+	dst = r->d + a->top + shift_words;
+
+	/* Handle right shift for top most word. */
+	*dst = (*src >> rshift) & rstride;
+	dst--;
+
+	/* Handle left shift and right shift for remaining words. */
+	while (src > a->d) {
+		*dst = *src << lshift | src[rstride] >> rshift;
+		src--;
+		dst--;
+	}
+	*dst = *src << lshift;
+
+	/* Zero any additional words resulting from the left shift. */
+	while (dst > r->d) {
+		dst--;
+		*dst = 0;
+	}
+
+	r->top = count;
+	bn_correct_top(r);
+
+	BN_set_negative(r, a->neg);
+
+	return 1;
+}
+
+static inline int
+bn_rshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+	size_t count, shift_bits, shift_words;
+	size_t lshift, rshift;
+	ssize_t lstride;
+	BN_ULONG *dst, *src;
+	size_t i;
+
+	if (n < 0) {
+		BNerror(BN_R_INVALID_LENGTH);
+		return 0;
+	}
+	shift_bits = n;
+
+	/*
+	 * Right bit shift, potentially across word boundaries.
+	 *
+	 * When shift is not an exact multiple of BN_BITS2, the top bits of
+	 * the next word need to be left shifted and combined with the right
+	 * shifted bits using bitwise OR. If shift is an exact multiple of
+	 * BN_BITS2, the source for the left and right shifts are the same
+	 * and the shifts become zero (which is effectively a memmove).
+	 */
+	shift_words = shift_bits / BN_BITS2;
+	rshift = shift_bits % BN_BITS2;
+	lshift = (BN_BITS2 - rshift) % BN_BITS2;
+	lstride = (lshift + rshift) / BN_BITS2;
+
+	if (a->top <= shift_words) {
+		BN_zero(r);
+		return 1;
+	}
+	count = a->top - shift_words;
+
+	if (!bn_wexpand(r, count))
+		return 0;
+
+	src = a->d + shift_words;
+	dst = r->d;
+
+	for (i = 1; i < count; i++) {
+		*dst = src[lstride] << lshift | *src >> rshift;
+		src++;
+		dst++;
+	}
+	*dst = *src >> rshift;
+
+	r->top = count;
+	bn_correct_top(r);
+
+	BN_set_negative(r, a->neg);
+
+	return 1;
+}
+
+int
+BN_lshift1(BIGNUM *r, const BIGNUM *a)
+{
+	return bn_lshift(r, a, 1);
+}
+LCRYPTO_ALIAS(BN_lshift1);
+
+int
+BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+	return bn_lshift(r, a, n);
+}
+LCRYPTO_ALIAS(BN_lshift);
+
+int
+BN_rshift1(BIGNUM *r, const BIGNUM *a)
+{
+	return bn_rshift(r, a, 1);
+}
+LCRYPTO_ALIAS(BN_rshift1);
+
+int
+BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+	return bn_rshift(r, a, n);
+}
+LCRYPTO_ALIAS(BN_rshift);
diff --git a/crypto/bn/bn_small_primes.c b/crypto/bn/bn_small_primes.c
new file mode 100644
index 0000000..bfb7903
--- /dev/null
+++ b/crypto/bn/bn_small_primes.c
@@ -0,0 +1,265 @@
+/*	$OpenBSD: bn_small_primes.c,v 1.1 2022/11/09 22:52:51 tb Exp $ */
+/*
+ * Public domain, generated by bn_prime.pl.
+ */
+
+#include "bn_prime.h"
+
+const uint16_t primes[NUMPRIMES] = {
+	    2,     3,     5,     7,    11,    13,    17,    19,
+	   23,    29,    31,    37,    41,    43,    47,    53,
+	   59,    61,    67,    71,    73,    79,    83,    89,
+	   97,   101,   103,   107,   109,   113,   127,   131,
+	  137,   139,   149,   151,   157,   163,   167,   173,
+	  179,   181,   191,   193,   197,   199,   211,   223,
+	  227,   229,   233,   239,   241,   251,   257,   263,
+	  269,   271,   277,   281,   283,   293,   307,   311,
+	  313,   317,   331,   337,   347,   349,   353,   359,
+	  367,   373,   379,   383,   389,   397,   401,   409,
+	  419,   421,   431,   433,   439,   443,   449,   457,
+	  461,   463,   467,   479,   487,   491,   499,   503,
+	  509,   521,   523,   541,   547,   557,   563,   569,
+	  571,   577,   587,   593,   599,   601,   607,   613,
+	  617,   619,   631,   641,   643,   647,   653,   659,
+	  661,   673,   677,   683,   691,   701,   709,   719,
+	  727,   733,   739,   743,   751,   757,   761,   769,
+	  773,   787,   797,   809,   811,   821,   823,   827,
+	  829,   839,   853,   857,   859,   863,   877,   881,
+	  883,   887,   907,   911,   919,   929,   937,   941,
+	  947,   953,   967,   971,   977,   983,   991,   997,
+	 1009,  1013,  1019,  1021,  1031,  1033,  1039,  1049,
+	 1051,  1061,  1063,  1069,  1087,  1091,  1093,  1097,
+	 1103,  1109,  1117,  1123,  1129,  1151,  1153,  1163,
+	 1171,  1181,  1187,  1193,  1201,  1213,  1217,  1223,
+	 1229,  1231,  1237,  1249,  1259,  1277,  1279,  1283,
+	 1289,  1291,  1297,  1301,  1303,  1307,  1319,  1321,
+	 1327,  1361,  1367,  1373,  1381,  1399,  1409,  1423,
+	 1427,  1429,  1433,  1439,  1447,  1451,  1453,  1459,
+	 1471,  1481,  1483,  1487,  1489,  1493,  1499,  1511,
+	 1523,  1531,  1543,  1549,  1553,  1559,  1567,  1571,
+	 1579,  1583,  1597,  1601,  1607,  1609,  1613,  1619,
+	 1621,  1627,  1637,  1657,  1663,  1667,  1669,  1693,
+	 1697,  1699,  1709,  1721,  1723,  1733,  1741,  1747,
+	 1753,  1759,  1777,  1783,  1787,  1789,  1801,  1811,
+	 1823,  1831,  1847,  1861,  1867,  1871,  1873,  1877,
+	 1879,  1889,  1901,  1907,  1913,  1931,  1933,  1949,
+	 1951,  1973,  1979,  1987,  1993,  1997,  1999,  2003,
+	 2011,  2017,  2027,  2029,  2039,  2053,  2063,  2069,
+	 2081,  2083,  2087,  2089,  2099,  2111,  2113,  2129,
+	 2131,  2137,  2141,  2143,  2153,  2161,  2179,  2203,
+	 2207,  2213,  2221,  2237,  2239,  2243,  2251,  2267,
+	 2269,  2273,  2281,  2287,  2293,  2297,  2309,  2311,
+	 2333,  2339,  2341,  2347,  2351,  2357,  2371,  2377,
+	 2381,  2383,  2389,  2393,  2399,  2411,  2417,  2423,
+	 2437,  2441,  2447,  2459,  2467,  2473,  2477,  2503,
+	 2521,  2531,  2539,  2543,  2549,  2551,  2557,  2579,
+	 2591,  2593,  2609,  2617,  2621,  2633,  2647,  2657,
+	 2659,  2663,  2671,  2677,  2683,  2687,  2689,  2693,
+	 2699,  2707,  2711,  2713,  2719,  2729,  2731,  2741,
+	 2749,  2753,  2767,  2777,  2789,  2791,  2797,  2801,
+	 2803,  2819,  2833,  2837,  2843,  2851,  2857,  2861,
+	 2879,  2887,  2897,  2903,  2909,  2917,  2927,  2939,
+	 2953,  2957,  2963,  2969,  2971,  2999,  3001,  3011,
+	 3019,  3023,  3037,  3041,  3049,  3061,  3067,  3079,
+	 3083,  3089,  3109,  3119,  3121,  3137,  3163,  3167,
+	 3169,  3181,  3187,  3191,  3203,  3209,  3217,  3221,
+	 3229,  3251,  3253,  3257,  3259,  3271,  3299,  3301,
+	 3307,  3313,  3319,  3323,  3329,  3331,  3343,  3347,
+	 3359,  3361,  3371,  3373,  3389,  3391,  3407,  3413,
+	 3433,  3449,  3457,  3461,  3463,  3467,  3469,  3491,
+	 3499,  3511,  3517,  3527,  3529,  3533,  3539,  3541,
+	 3547,  3557,  3559,  3571,  3581,  3583,  3593,  3607,
+	 3613,  3617,  3623,  3631,  3637,  3643,  3659,  3671,
+	 3673,  3677,  3691,  3697,  3701,  3709,  3719,  3727,
+	 3733,  3739,  3761,  3767,  3769,  3779,  3793,  3797,
+	 3803,  3821,  3823,  3833,  3847,  3851,  3853,  3863,
+	 3877,  3881,  3889,  3907,  3911,  3917,  3919,  3923,
+	 3929,  3931,  3943,  3947,  3967,  3989,  4001,  4003,
+	 4007,  4013,  4019,  4021,  4027,  4049,  4051,  4057,
+	 4073,  4079,  4091,  4093,  4099,  4111,  4127,  4129,
+	 4133,  4139,  4153,  4157,  4159,  4177,  4201,  4211,
+	 4217,  4219,  4229,  4231,  4241,  4243,  4253,  4259,
+	 4261,  4271,  4273,  4283,  4289,  4297,  4327,  4337,
+	 4339,  4349,  4357,  4363,  4373,  4391,  4397,  4409,
+	 4421,  4423,  4441,  4447,  4451,  4457,  4463,  4481,
+	 4483,  4493,  4507,  4513,  4517,  4519,  4523,  4547,
+	 4549,  4561,  4567,  4583,  4591,  4597,  4603,  4621,
+	 4637,  4639,  4643,  4649,  4651,  4657,  4663,  4673,
+	 4679,  4691,  4703,  4721,  4723,  4729,  4733,  4751,
+	 4759,  4783,  4787,  4789,  4793,  4799,  4801,  4813,
+	 4817,  4831,  4861,  4871,  4877,  4889,  4903,  4909,
+	 4919,  4931,  4933,  4937,  4943,  4951,  4957,  4967,
+	 4969,  4973,  4987,  4993,  4999,  5003,  5009,  5011,
+	 5021,  5023,  5039,  5051,  5059,  5077,  5081,  5087,
+	 5099,  5101,  5107,  5113,  5119,  5147,  5153,  5167,
+	 5171,  5179,  5189,  5197,  5209,  5227,  5231,  5233,
+	 5237,  5261,  5273,  5279,  5281,  5297,  5303,  5309,
+	 5323,  5333,  5347,  5351,  5381,  5387,  5393,  5399,
+	 5407,  5413,  5417,  5419,  5431,  5437,  5441,  5443,
+	 5449,  5471,  5477,  5479,  5483,  5501,  5503,  5507,
+	 5519,  5521,  5527,  5531,  5557,  5563,  5569,  5573,
+	 5581,  5591,  5623,  5639,  5641,  5647,  5651,  5653,
+	 5657,  5659,  5669,  5683,  5689,  5693,  5701,  5711,
+	 5717,  5737,  5741,  5743,  5749,  5779,  5783,  5791,
+	 5801,  5807,  5813,  5821,  5827,  5839,  5843,  5849,
+	 5851,  5857,  5861,  5867,  5869,  5879,  5881,  5897,
+	 5903,  5923,  5927,  5939,  5953,  5981,  5987,  6007,
+	 6011,  6029,  6037,  6043,  6047,  6053,  6067,  6073,
+	 6079,  6089,  6091,  6101,  6113,  6121,  6131,  6133,
+	 6143,  6151,  6163,  6173,  6197,  6199,  6203,  6211,
+	 6217,  6221,  6229,  6247,  6257,  6263,  6269,  6271,
+	 6277,  6287,  6299,  6301,  6311,  6317,  6323,  6329,
+	 6337,  6343,  6353,  6359,  6361,  6367,  6373,  6379,
+	 6389,  6397,  6421,  6427,  6449,  6451,  6469,  6473,
+	 6481,  6491,  6521,  6529,  6547,  6551,  6553,  6563,
+	 6569,  6571,  6577,  6581,  6599,  6607,  6619,  6637,
+	 6653,  6659,  6661,  6673,  6679,  6689,  6691,  6701,
+	 6703,  6709,  6719,  6733,  6737,  6761,  6763,  6779,
+	 6781,  6791,  6793,  6803,  6823,  6827,  6829,  6833,
+	 6841,  6857,  6863,  6869,  6871,  6883,  6899,  6907,
+	 6911,  6917,  6947,  6949,  6959,  6961,  6967,  6971,
+	 6977,  6983,  6991,  6997,  7001,  7013,  7019,  7027,
+	 7039,  7043,  7057,  7069,  7079,  7103,  7109,  7121,
+	 7127,  7129,  7151,  7159,  7177,  7187,  7193,  7207,
+	 7211,  7213,  7219,  7229,  7237,  7243,  7247,  7253,
+	 7283,  7297,  7307,  7309,  7321,  7331,  7333,  7349,
+	 7351,  7369,  7393,  7411,  7417,  7433,  7451,  7457,
+	 7459,  7477,  7481,  7487,  7489,  7499,  7507,  7517,
+	 7523,  7529,  7537,  7541,  7547,  7549,  7559,  7561,
+	 7573,  7577,  7583,  7589,  7591,  7603,  7607,  7621,
+	 7639,  7643,  7649,  7669,  7673,  7681,  7687,  7691,
+	 7699,  7703,  7717,  7723,  7727,  7741,  7753,  7757,
+	 7759,  7789,  7793,  7817,  7823,  7829,  7841,  7853,
+	 7867,  7873,  7877,  7879,  7883,  7901,  7907,  7919,
+	 7927,  7933,  7937,  7949,  7951,  7963,  7993,  8009,
+	 8011,  8017,  8039,  8053,  8059,  8069,  8081,  8087,
+	 8089,  8093,  8101,  8111,  8117,  8123,  8147,  8161,
+	 8167,  8171,  8179,  8191,  8209,  8219,  8221,  8231,
+	 8233,  8237,  8243,  8263,  8269,  8273,  8287,  8291,
+	 8293,  8297,  8311,  8317,  8329,  8353,  8363,  8369,
+	 8377,  8387,  8389,  8419,  8423,  8429,  8431,  8443,
+	 8447,  8461,  8467,  8501,  8513,  8521,  8527,  8537,
+	 8539,  8543,  8563,  8573,  8581,  8597,  8599,  8609,
+	 8623,  8627,  8629,  8641,  8647,  8663,  8669,  8677,
+	 8681,  8689,  8693,  8699,  8707,  8713,  8719,  8731,
+	 8737,  8741,  8747,  8753,  8761,  8779,  8783,  8803,
+	 8807,  8819,  8821,  8831,  8837,  8839,  8849,  8861,
+	 8863,  8867,  8887,  8893,  8923,  8929,  8933,  8941,
+	 8951,  8963,  8969,  8971,  8999,  9001,  9007,  9011,
+	 9013,  9029,  9041,  9043,  9049,  9059,  9067,  9091,
+	 9103,  9109,  9127,  9133,  9137,  9151,  9157,  9161,
+	 9173,  9181,  9187,  9199,  9203,  9209,  9221,  9227,
+	 9239,  9241,  9257,  9277,  9281,  9283,  9293,  9311,
+	 9319,  9323,  9337,  9341,  9343,  9349,  9371,  9377,
+	 9391,  9397,  9403,  9413,  9419,  9421,  9431,  9433,
+	 9437,  9439,  9461,  9463,  9467,  9473,  9479,  9491,
+	 9497,  9511,  9521,  9533,  9539,  9547,  9551,  9587,
+	 9601,  9613,  9619,  9623,  9629,  9631,  9643,  9649,
+	 9661,  9677,  9679,  9689,  9697,  9719,  9721,  9733,
+	 9739,  9743,  9749,  9767,  9769,  9781,  9787,  9791,
+	 9803,  9811,  9817,  9829,  9833,  9839,  9851,  9857,
+	 9859,  9871,  9883,  9887,  9901,  9907,  9923,  9929,
+	 9931,  9941,  9949,  9967,  9973, 10007, 10009, 10037,
+	10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
+	10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163,
+	10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247,
+	10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303,
+	10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369,
+	10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
+	10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531,
+	10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627,
+	10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691,
+	10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771,
+	10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
+	10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937,
+	10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003,
+	11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087,
+	11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161,
+	11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
+	11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317,
+	11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399,
+	11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483,
+	11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551,
+	11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
+	11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731,
+	11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813,
+	11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887,
+	11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941,
+	11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
+	12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101,
+	12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161,
+	12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251,
+	12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323,
+	12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
+	12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473,
+	12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527,
+	12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589,
+	12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653,
+	12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
+	12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821,
+	12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907,
+	12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967,
+	12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033,
+	13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
+	13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177,
+	13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259,
+	13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
+	13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421,
+	13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
+	13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597,
+	13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681,
+	13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723,
+	13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799,
+	13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
+	13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933,
+	13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033,
+	14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143,
+	14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221,
+	14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
+	14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407,
+	14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461,
+	14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549,
+	14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627,
+	14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
+	14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
+	14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821,
+	14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887,
+	14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957,
+	14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
+	15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137,
+	15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217,
+	15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277,
+	15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331,
+	15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
+	15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473,
+	15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569,
+	15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643,
+	15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727,
+	15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
+	15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859,
+	15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919,
+	15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007,
+	16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087,
+	16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
+	16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249,
+	16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349,
+	16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427,
+	16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493,
+	16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
+	16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661,
+	16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747,
+	16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843,
+	16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927,
+	16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
+	17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053,
+	17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159,
+	17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231,
+	17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327,
+	17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
+	17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467,
+	17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519,
+	17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599,
+	17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683,
+	17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
+	17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863,
+};
diff --git a/crypto/bn/bn_sqr.c b/crypto/bn/bn_sqr.c
new file mode 100644
index 0000000..0dbccbf
--- /dev/null
+++ b/crypto/bn/bn_sqr.c
@@ -0,0 +1,305 @@
+/* $OpenBSD: bn_sqr.c,v 1.36 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include "bn_arch.h"
+#include "bn_local.h"
+#include "bn_internal.h"
+
+int bn_sqr(BIGNUM *r, const BIGNUM *a, int max, BN_CTX *ctx);
+
+/*
+ * bn_sqr_comba4() computes r[] = a[] * a[] using Comba multiplication
+ * (https://everything2.com/title/Comba+multiplication), where a is a
+ * four word array, producing an eight word array result.
+ */
+#ifndef HAVE_BN_SQR_COMBA4
+void
+bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
+{
+	BN_ULONG c2, c1, c0;
+
+	bn_mulw_addtw(a[0], a[0], 0, 0, 0, &c2, &c1, &r[0]);
+
+	bn_mul2_mulw_addtw(a[1], a[0], 0, c2, c1, &c2, &c1, &r[1]);
+
+	bn_mulw_addtw(a[1], a[1], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[2], a[0], c2, c1, c0, &c2, &c1, &r[2]);
+
+	bn_mul2_mulw_addtw(a[3], a[0], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[2], a[1], c2, c1, c0, &c2, &c1, &r[3]);
+
+	bn_mulw_addtw(a[2], a[2], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[3], a[1], c2, c1, c0, &c2, &c1, &r[4]);
+
+	bn_mul2_mulw_addtw(a[3], a[2], 0, c2, c1, &c2, &c1, &r[5]);
+
+	bn_mulw_addtw(a[3], a[3], 0, c2, c1, &c2, &r[7], &r[6]);
+}
+#endif
+
+/*
+ * bn_sqr_comba8() computes r[] = a[] * a[] using Comba multiplication
+ * (https://everything2.com/title/Comba+multiplication), where a is an
+ * eight word array, producing an 16 word array result.
+ */
+#ifndef HAVE_BN_SQR_COMBA8
+void
+bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
+{
+	BN_ULONG c2, c1, c0;
+
+	bn_mulw_addtw(a[0], a[0], 0, 0, 0, &c2, &c1, &r[0]);
+
+	bn_mul2_mulw_addtw(a[1], a[0], 0, c2, c1, &c2, &c1, &r[1]);
+
+	bn_mulw_addtw(a[1], a[1], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[2], a[0], c2, c1, c0, &c2, &c1, &r[2]);
+
+	bn_mul2_mulw_addtw(a[3], a[0], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[2], a[1], c2, c1, c0, &c2, &c1, &r[3]);
+
+	bn_mulw_addtw(a[2], a[2], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[3], a[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[4], a[0], c2, c1, c0, &c2, &c1, &r[4]);
+
+	bn_mul2_mulw_addtw(a[5], a[0], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[4], a[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[3], a[2], c2, c1, c0, &c2, &c1, &r[5]);
+
+	bn_mulw_addtw(a[3], a[3], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[4], a[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[5], a[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[0], c2, c1, c0, &c2, &c1, &r[6]);
+
+	bn_mul2_mulw_addtw(a[7], a[0], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[1], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[5], a[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[4], a[3], c2, c1, c0, &c2, &c1, &r[7]);
+
+	bn_mulw_addtw(a[4], a[4], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[5], a[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[2], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[7], a[1], c2, c1, c0, &c2, &c1, &r[8]);
+
+	bn_mul2_mulw_addtw(a[7], a[2], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[3], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[5], a[4], c2, c1, c0, &c2, &c1, &r[9]);
+
+	bn_mulw_addtw(a[5], a[5], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[4], c2, c1, c0, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[7], a[3], c2, c1, c0, &c2, &c1, &r[10]);
+
+	bn_mul2_mulw_addtw(a[7], a[4], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[6], a[5], c2, c1, c0, &c2, &c1, &r[11]);
+
+	bn_mulw_addtw(a[6], a[6], 0, c2, c1, &c2, &c1, &c0);
+	bn_mul2_mulw_addtw(a[7], a[5], c2, c1, c0, &c2, &c1, &r[12]);
+
+	bn_mul2_mulw_addtw(a[7], a[6], 0, c2, c1, &c2, &c1, &r[13]);
+
+	bn_mulw_addtw(a[7], a[7], 0, c2, c1, &c2, &r[15], &r[14]);
+}
+#endif
+
+#ifndef HAVE_BN_SQR
+/*
+ * bn_sqr_add_words() computes (r[i*2+1]:r[i*2]) = (r[i*2+1]:r[i*2]) + a[i] * a[i].
+ */
+static void
+bn_sqr_add_words(BN_ULONG *r, const BN_ULONG *a, int n)
+{
+	BN_ULONG x3, x2, x1, x0;
+	BN_ULONG carry = 0;
+
+	assert(n >= 0);
+	if (n <= 0)
+		return;
+
+	while (n & ~3) {
+		bn_mulw(a[0], a[0], &x1, &x0);
+		bn_mulw(a[1], a[1], &x3, &x2);
+		bn_qwaddqw(x3, x2, x1, x0, r[3], r[2], r[1], r[0], carry,
+		    &carry, &r[3], &r[2], &r[1], &r[0]);
+		bn_mulw(a[2], a[2], &x1, &x0);
+		bn_mulw(a[3], a[3], &x3, &x2);
+		bn_qwaddqw(x3, x2, x1, x0, r[7], r[6], r[5], r[4], carry,
+		    &carry, &r[7], &r[6], &r[5], &r[4]);
+
+		a += 4;
+		r += 8;
+		n -= 4;
+	}
+	while (n) {
+		bn_mulw_addw_addw(a[0], a[0], r[0], carry, &carry, &r[0]);
+		bn_addw(r[1], carry, &carry, &r[1]);
+		a++;
+		r += 2;
+		n--;
+	}
+}
+
+static void
+bn_sqr_normal(BN_ULONG *r, int r_len, const BN_ULONG *a, int a_len)
+{
+	const BN_ULONG *ap;
+	BN_ULONG *rp;
+	BN_ULONG w;
+	int n;
+
+	if (a_len <= 0)
+		return;
+
+	ap = a;
+	w = ap[0];
+	ap++;
+
+	rp = r;
+	rp[0] = rp[r_len - 1] = 0;
+	rp++;
+
+	/* Compute initial product - r[n:1] = a[n:1] * a[0] */
+	n = a_len - 1;
+	if (n > 0) {
+		rp[n] = bn_mul_words(rp, ap, n, w);
+	}
+	rp += 2;
+	n--;
+
+	/* Compute and sum remaining products. */
+	while (n > 0) {
+		w = ap[0];
+		ap++;
+
+		rp[n] = bn_mul_add_words(rp, ap, n, w);
+		rp += 2;
+		n--;
+	}
+
+	/* Double the sum of products. */
+	bn_add_words(r, r, r, r_len);
+
+	/* Add squares. */
+	bn_sqr_add_words(r, a, a_len);
+}
+
+/*
+ * bn_sqr() computes a * a, storing the result in r. The caller must ensure that
+ * r is not the same BIGNUM as a and that r has been expanded to rn = a->top * 2
+ * words.
+ */
+int
+bn_sqr(BIGNUM *r, const BIGNUM *a, int r_len, BN_CTX *ctx)
+{
+	bn_sqr_normal(r->d, r_len, a->d, a->top);
+
+	return 1;
+}
+#endif
+
+int
+BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
+{
+	BIGNUM *rr;
+	int r_len;
+	int ret = 1;
+
+	BN_CTX_start(ctx);
+
+	if (a->top < 1) {
+		BN_zero(r);
+		goto done;
+	}
+
+	if ((rr = r) == a)
+		rr = BN_CTX_get(ctx);
+	if (rr == NULL)
+		goto err;
+
+	if ((r_len = a->top * 2) < a->top)
+		goto err;
+	if (!bn_wexpand(rr, r_len))
+		goto err;
+
+	if (a->top == 4) {
+		bn_sqr_comba4(rr->d, a->d);
+	} else if (a->top == 8) {
+		bn_sqr_comba8(rr->d, a->d);
+	} else {
+		if (!bn_sqr(rr, a, r_len, ctx))
+			goto err;
+	}
+
+	rr->top = r_len;
+	bn_correct_top(rr);
+
+	rr->neg = 0;
+
+	if (!bn_copy(r, rr))
+		goto err;
+ done:
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(BN_sqr);
diff --git a/crypto/bn/bn_word.c b/crypto/bn/bn_word.c
new file mode 100644
index 0000000..a82b911
--- /dev/null
+++ b/crypto/bn/bn_word.c
@@ -0,0 +1,245 @@
+/* $OpenBSD: bn_word.c,v 1.21 2023/07/08 12:21:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "bn_local.h"
+
+BN_ULONG
+BN_mod_word(const BIGNUM *a, BN_ULONG w)
+{
+#ifndef BN_LLONG
+	BN_ULONG ret = 0;
+#else
+	BN_ULLONG ret = 0;
+#endif
+	int i;
+
+	if (w == 0)
+		return (BN_ULONG) - 1;
+
+#ifndef BN_ULLONG
+	/* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
+	* to using |BN_div_word|. */
+	if (w > ((BN_ULONG)1 << BN_BITS4)) {
+		BIGNUM *tmp = BN_dup(a);
+		if (tmp == NULL) {
+			return (BN_ULONG)-1;
+		}
+		ret = BN_div_word(tmp, w);
+		BN_free(tmp);
+		return ret;
+	}
+#endif
+
+	w &= BN_MASK2;
+	for (i = a->top - 1; i >= 0; i--) {
+#ifndef BN_LLONG
+		ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) &
+		    BN_MASK2l)) % w;
+		ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
+#else
+		ret = (BN_ULLONG)(((ret << (BN_ULLONG)BN_BITS2) |
+		    a->d[i]) % (BN_ULLONG)w);
+#endif
+	}
+	return ((BN_ULONG)ret);
+}
+LCRYPTO_ALIAS(BN_mod_word);
+
+BN_ULONG
+BN_div_word(BIGNUM *a, BN_ULONG w)
+{
+	BN_ULONG ret = 0;
+	int i, j;
+
+	w &= BN_MASK2;
+
+	if (!w)
+		/* actually this an error (division by zero) */
+		return (BN_ULONG) - 1;
+	if (a->top == 0)
+		return 0;
+
+	/* normalize input (so bn_div_words doesn't complain) */
+	j = BN_BITS2 - BN_num_bits_word(w);
+	w <<= j;
+	if (!BN_lshift(a, a, j))
+		return (BN_ULONG) - 1;
+
+	for (i = a->top - 1; i >= 0; i--) {
+		BN_ULONG l, d;
+
+		l = a->d[i];
+		bn_div_rem_words(ret, l, w, &d, &ret);
+		a->d[i] = d;
+	}
+	if ((a->top > 0) && (a->d[a->top - 1] == 0))
+		a->top--;
+	ret >>= j;
+
+	/* Set negative again, to handle -0 case. */
+	BN_set_negative(a, a->neg);
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BN_div_word);
+
+int
+BN_add_word(BIGNUM *a, BN_ULONG w)
+{
+	BN_ULONG l;
+	int i;
+
+	w &= BN_MASK2;
+
+	/* degenerate case: w is zero */
+	if (!w)
+		return 1;
+	/* degenerate case: a is zero */
+	if (BN_is_zero(a))
+		return BN_set_word(a, w);
+	/* handle 'a' when negative */
+	if (a->neg) {
+		a->neg = 0;
+		i = BN_sub_word(a, w);
+		BN_set_negative(a, !a->neg);
+		return (i);
+	}
+	for (i = 0; w != 0 && i < a->top; i++) {
+		a->d[i] = l = (a->d[i] + w) & BN_MASK2;
+		w = (w > l) ? 1 : 0;
+	}
+	if (w && i == a->top) {
+		if (!bn_wexpand(a, a->top + 1))
+			return 0;
+		a->top++;
+		a->d[i] = w;
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(BN_add_word);
+
+int
+BN_sub_word(BIGNUM *a, BN_ULONG w)
+{
+	int i;
+
+	w &= BN_MASK2;
+
+	/* degenerate case: w is zero */
+	if (!w)
+		return 1;
+	/* degenerate case: a is zero */
+	if (BN_is_zero(a)) {
+		i = BN_set_word(a, w);
+		if (i != 0)
+			BN_set_negative(a, 1);
+		return i;
+	}
+	/* handle 'a' when negative */
+	if (a->neg) {
+		a->neg = 0;
+		i = BN_add_word(a, w);
+		BN_set_negative(a, !a->neg);
+		return (i);
+	}
+
+	if ((a->top == 1) && (a->d[0] < w)) {
+		a->d[0] = w - a->d[0];
+		BN_set_negative(a, 1);
+		return (1);
+	}
+	i = 0;
+	for (;;) {
+		if (a->d[i] >= w) {
+			a->d[i] -= w;
+			break;
+		} else {
+			a->d[i] = (a->d[i] - w) & BN_MASK2;
+			i++;
+			w = 1;
+		}
+	}
+	if ((a->d[i] == 0) && (i == (a->top - 1)))
+		a->top--;
+	return (1);
+}
+LCRYPTO_ALIAS(BN_sub_word);
+
+int
+BN_mul_word(BIGNUM *a, BN_ULONG w)
+{
+	BN_ULONG ll;
+
+	w &= BN_MASK2;
+	if (a->top) {
+		if (w == 0)
+			BN_zero(a);
+		else {
+			ll = bn_mul_words(a->d, a->d, a->top, w);
+			if (ll) {
+				if (!bn_wexpand(a, a->top + 1))
+					return (0);
+				a->d[a->top++] = ll;
+			}
+		}
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(BN_mul_word);
diff --git a/crypto/bn/modexp512-elf-x86_64.S b/crypto/bn/modexp512-elf-x86_64.S
new file mode 100644
index 0000000..87fc026
--- /dev/null
+++ b/crypto/bn/modexp512-elf-x86_64.S
@@ -0,0 +1,1782 @@
+#include "x86_arch.h"
+.text	
+
+.type	MULADD_128x512,@function
+.align	16
+MULADD_128x512:
+	endbr64
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	retq
+.size	MULADD_128x512,.-MULADD_128x512
+.type	mont_reduce,@function
+.align	16
+mont_reduce:
+	endbr64
+	leaq	192(%rsp),%rdi
+	movq	32(%rsp),%rsi
+	addq	$576,%rsi
+	leaq	520(%rsp),%rcx
+
+	movq	96(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	movq	(%rcx),%r8
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	movq	8(%rcx),%r9
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	movq	16(%rcx),%r10
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	movq	24(%rcx),%r11
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	movq	32(%rcx),%r12
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	movq	40(%rcx),%r13
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	movq	48(%rcx),%r14
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	movq	56(%rcx),%r15
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	104(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	112(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,16(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	120(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,24(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	xorq	%rax,%rax
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+	adcq	80(%rcx),%r10
+	adcq	88(%rcx),%r11
+	adcq	$0,%rax
+
+
+
+
+	movq	%r8,64(%rdi)
+	movq	%r9,72(%rdi)
+	movq	%r10,%rbp
+	movq	%r11,88(%rdi)
+
+	movq	%rax,384(%rsp)
+
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+
+
+
+
+
+
+
+
+	addq	$80,%rdi
+
+	addq	$64,%rsi
+	leaq	296(%rsp),%rcx
+
+	call	MULADD_128x512			
+
+	movq	384(%rsp),%rax
+
+
+	addq	-16(%rdi),%r8
+	adcq	-8(%rdi),%r9
+	movq	%r8,64(%rcx)
+	movq	%r9,72(%rcx)
+
+	adcq	%rax,%rax
+	movq	%rax,384(%rsp)
+
+	leaq	192(%rsp),%rdi
+	addq	$64,%rsi
+
+
+
+
+
+	movq	(%rsi),%r8
+	movq	8(%rsi),%rbx
+
+	movq	(%rcx),%rax
+	mulq	%r8
+	movq	%rax,%rbp
+	movq	%rdx,%r9
+
+	movq	8(%rcx),%rax
+	mulq	%r8
+	addq	%rax,%r9
+
+	movq	(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r9
+
+	movq	%r9,8(%rdi)
+
+
+	subq	$192,%rsi
+
+	movq	(%rcx),%r8
+	movq	8(%rcx),%r9
+
+	call	MULADD_128x512			
+
+
+
+
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdi
+	movq	24(%rsi),%rdx
+
+
+	movq	384(%rsp),%rbp
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+
+
+	adcq	%rbp,%rbp
+
+
+
+	shlq	$3,%rbp
+	movq	32(%rsp),%rcx
+	addq	%rcx,%rbp
+
+
+	xorq	%rsi,%rsi
+
+	addq	0(%rbp),%r10
+	adcq	64(%rbp),%r11
+	adcq	128(%rbp),%r12
+	adcq	192(%rbp),%r13
+	adcq	256(%rbp),%r14
+	adcq	320(%rbp),%r15
+	adcq	384(%rbp),%r8
+	adcq	448(%rbp),%r9
+
+
+
+	sbbq	$0,%rsi
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+	movq	$1,%rbp
+	subq	%rax,%r10
+	sbbq	%rbx,%r11
+	sbbq	%rdi,%r12
+	sbbq	%rdx,%r13
+
+
+
+
+	sbbq	$0,%rbp
+
+
+
+	addq	$512,%rcx
+	movq	32(%rcx),%rax
+	movq	40(%rcx),%rbx
+	movq	48(%rcx),%rdi
+	movq	56(%rcx),%rdx
+
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+
+
+	subq	$1,%rbp
+
+	sbbq	%rax,%r14
+	sbbq	%rbx,%r15
+	sbbq	%rdi,%r8
+	sbbq	%rdx,%r9
+
+
+
+	movq	144(%rsp),%rsi
+	movq	%r10,0(%rsi)
+	movq	%r11,8(%rsi)
+	movq	%r12,16(%rsi)
+	movq	%r13,24(%rsi)
+	movq	%r14,32(%rsi)
+	movq	%r15,40(%rsi)
+	movq	%r8,48(%rsi)
+	movq	%r9,56(%rsi)
+
+	retq
+.size	mont_reduce,.-mont_reduce
+.type	mont_mul_a3b,@function
+.align	16
+mont_mul_a3b:
+	endbr64
+
+
+
+
+	movq	0(%rdi),%rbp
+
+	movq	%r10,%rax
+	mulq	%rbp
+	movq	%rax,520(%rsp)
+	movq	%rdx,%r10
+	movq	%r11,%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r12,%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r13,%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r14,%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r15,%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r8,%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,528(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	16(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,536(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	24(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,544(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	32(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,552(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	40(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%r14,560(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	48(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,568(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	56(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,576(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,584(%rsp)
+	movq	%r10,592(%rsp)
+	movq	%r11,600(%rsp)
+	movq	%r12,608(%rsp)
+	movq	%r13,616(%rsp)
+	movq	%r14,624(%rsp)
+	movq	%r15,632(%rsp)
+	movq	%r8,640(%rsp)
+
+
+
+
+
+	jmp	mont_reduce
+
+
+.size	mont_mul_a3b,.-mont_mul_a3b
+.type	sqr_reduce,@function
+.align	16
+sqr_reduce:
+	endbr64
+	movq	16(%rsp),%rcx
+
+
+
+	movq	%r10,%rbx
+
+	movq	%r11,%rax
+	mulq	%rbx
+	movq	%rax,528(%rsp)
+	movq	%rdx,%r10
+	movq	%r12,%rax
+	mulq	%rbx
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r13,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r14,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r15,%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rsi
+
+	movq	%r10,536(%rsp)
+
+
+
+
+
+	movq	8(%rcx),%rbx
+
+	movq	16(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,544(%rsp)
+
+	movq	%rdx,%r10
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,552(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	16(%rcx),%rbx
+
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,560(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+	movq	%r14,568(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r12
+
+
+
+
+
+	movq	24(%rcx),%rbx
+
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,576(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+	movq	%rsi,584(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+
+	movq	%rdx,%r15
+
+
+
+
+	movq	32(%rcx),%rbx
+
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,592(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,600(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	40(%rcx),%rbx
+
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,608(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r11,616(%rsp)
+
+	movq	%rdx,%r12
+
+
+
+
+	movq	%r8,%rbx
+
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,624(%rsp)
+
+	movq	%rdx,632(%rsp)
+
+
+	movq	528(%rsp),%r10
+	movq	536(%rsp),%r11
+	movq	544(%rsp),%r12
+	movq	552(%rsp),%r13
+	movq	560(%rsp),%r14
+	movq	568(%rsp),%r15
+
+	movq	24(%rcx),%rax
+	mulq	%rax
+	movq	%rax,%rdi
+	movq	%rdx,%r8
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	$0,%r8
+
+	movq	0(%rcx),%rax
+	mulq	%rax
+	movq	%rax,520(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+	movq	%r10,528(%rsp)
+	movq	%r11,536(%rsp)
+
+	movq	16(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+
+	movq	%r12,544(%rsp)
+	movq	%r13,552(%rsp)
+
+	xorq	%rbp,%rbp
+	addq	%rbx,%r14
+	adcq	%rdi,%r15
+	adcq	$0,%rbp
+
+	movq	%r14,560(%rsp)
+	movq	%r15,568(%rsp)
+
+
+
+
+	movq	576(%rsp),%r10
+	movq	584(%rsp),%r11
+	movq	592(%rsp),%r12
+	movq	600(%rsp),%r13
+	movq	608(%rsp),%r14
+	movq	616(%rsp),%r15
+	movq	624(%rsp),%rdi
+	movq	632(%rsp),%rsi
+
+	movq	%r9,%rax
+	mulq	%rax
+	movq	%rax,%r9
+	movq	%rdx,%rbx
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	%rdi,%rdi
+	adcq	%rsi,%rsi
+	adcq	$0,%rbx
+
+	addq	%rbp,%r10
+
+	movq	32(%rcx),%rax
+	mulq	%rax
+
+	addq	%r8,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r10,576(%rsp)
+	movq	%r11,584(%rsp)
+
+	movq	40(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r12,592(%rsp)
+	movq	%r13,600(%rsp)
+
+	movq	48(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r14
+	adcq	%rax,%r15
+	adcq	$0,%rdx
+
+	movq	%r14,608(%rsp)
+	movq	%r15,616(%rsp)
+
+	addq	%rdx,%rdi
+	adcq	%r9,%rsi
+	adcq	$0,%rbx
+
+	movq	%rdi,624(%rsp)
+	movq	%rsi,632(%rsp)
+	movq	%rbx,640(%rsp)
+
+	jmp	mont_reduce
+
+
+.size	sqr_reduce,.-sqr_reduce
+.globl	mod_exp_512
+.type	mod_exp_512,@function
+mod_exp_512:
+	endbr64
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r8
+	subq	$2688,%rsp
+	andq	$-64,%rsp
+
+
+	movq	%r8,0(%rsp)
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rcx,24(%rsp)
+.Lbody:
+
+
+
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rsi),%xmm0
+	movdqu	16(%rsi),%xmm1
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm3
+	movdqa	%xmm4,512(%rsp)
+	movdqa	%xmm4,528(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,544(%rsp)
+	movdqa	%xmm1,560(%rsp)
+	movdqa	%xmm2,576(%rsp)
+	movdqa	%xmm3,592(%rsp)
+
+
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+
+	leaq	384(%rsp),%rbx
+	movq	%rbx,136(%rsp)
+	call	mont_reduce
+
+
+	leaq	448(%rsp),%rcx
+	xorq	%rax,%rax
+	movq	%rax,0(%rcx)
+	movq	%rax,8(%rcx)
+	movq	%rax,24(%rcx)
+	movq	%rax,32(%rcx)
+	movq	%rax,40(%rcx)
+	movq	%rax,48(%rcx)
+	movq	%rax,56(%rcx)
+	movq	%rax,128(%rsp)
+	movq	$1,16(%rcx)
+
+	leaq	640(%rsp),%rbp
+	movq	%rcx,%rsi
+	movq	%rbp,%rdi
+	movq	$8,%rax
+loop_0:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,64(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,128(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,192(%rdi)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rdi),%rdi
+	decq	%rax
+	jnz	loop_0
+	movq	$31,%rax
+	movq	%rax,32(%rsp)
+	movq	%rbp,40(%rsp)
+
+	movq	%rsi,136(%rsp)
+	movq	0(%rsi),%r10
+	movq	8(%rsi),%r11
+	movq	16(%rsi),%r12
+	movq	24(%rsi),%r13
+	movq	32(%rsi),%r14
+	movq	40(%rsi),%r15
+	movq	48(%rsi),%r8
+	movq	56(%rsi),%r9
+init_loop:
+	leaq	384(%rsp),%rdi
+	call	mont_mul_a3b
+	leaq	448(%rsp),%rsi
+	movq	40(%rsp),%rbp
+	addq	$2,%rbp
+	movq	%rbp,40(%rsp)
+	movq	%rsi,%rcx
+	movq	$8,%rax
+loop_1:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,64(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,128(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,192(%rbp)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rbp),%rbp
+	decq	%rax
+	jnz	loop_1
+	movq	32(%rsp),%rax
+	subq	$1,%rax
+	movq	%rax,32(%rsp)
+	jne	init_loop
+
+
+
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm1,80(%rsp)
+	movdqa	%xmm2,96(%rsp)
+	movdqa	%xmm3,112(%rsp)
+
+
+
+
+
+	movl	126(%rsp),%eax
+	movq	%rax,%rdx
+	shrq	$11,%rax
+	andl	$2047,%edx
+	movl	%edx,126(%rsp)
+	leaq	640(%rsp,%rax,2),%rsi
+	movq	8(%rsp),%rdx
+	movq	$4,%rbp
+loop_2:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_2
+	movq	$505,48(%rsp)
+
+	movq	8(%rsp),%rcx
+	movq	%rcx,136(%rsp)
+	movq	0(%rcx),%r10
+	movq	8(%rcx),%r11
+	movq	16(%rcx),%r12
+	movq	24(%rcx),%r13
+	movq	32(%rcx),%r14
+	movq	40(%rcx),%r15
+	movq	48(%rcx),%r8
+	movq	56(%rcx),%r9
+	jmp	sqr_2
+
+main_loop_a3b:
+	call	sqr_reduce
+	call	sqr_reduce
+	call	sqr_reduce
+sqr_2:
+	call	sqr_reduce
+	call	sqr_reduce
+
+
+
+	movq	48(%rsp),%rcx
+	movq	%rcx,%rax
+	shrq	$4,%rax
+	movl	64(%rsp,%rax,2),%edx
+	andq	$15,%rcx
+	shrq	%cl,%rdx
+	andq	$31,%rdx
+
+	leaq	640(%rsp,%rdx,2),%rsi
+	leaq	448(%rsp),%rdx
+	movq	%rdx,%rdi
+	movq	$4,%rbp
+loop_3:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_3
+	movq	8(%rsp),%rsi
+	call	mont_mul_a3b
+
+
+
+	movq	48(%rsp),%rcx
+	subq	$5,%rcx
+	movq	%rcx,48(%rsp)
+	jge	main_loop_a3b
+
+
+
+end_main_loop_a3b:
+
+
+	movq	8(%rsp),%rdx
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+	movdqa	%xmm4,576(%rsp)
+	movdqa	%xmm4,592(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,512(%rsp)
+	movdqa	%xmm1,528(%rsp)
+	movdqa	%xmm2,544(%rsp)
+	movdqa	%xmm3,560(%rsp)
+	call	mont_reduce
+
+
+
+	movq	8(%rsp),%rax
+	movq	0(%rax),%r8
+	movq	8(%rax),%r9
+	movq	16(%rax),%r10
+	movq	24(%rax),%r11
+	movq	32(%rax),%r12
+	movq	40(%rax),%r13
+	movq	48(%rax),%r14
+	movq	56(%rax),%r15
+
+
+	movq	24(%rsp),%rbx
+	addq	$512,%rbx
+
+	subq	0(%rbx),%r8
+	sbbq	8(%rbx),%r9
+	sbbq	16(%rbx),%r10
+	sbbq	24(%rbx),%r11
+	sbbq	32(%rbx),%r12
+	sbbq	40(%rbx),%r13
+	sbbq	48(%rbx),%r14
+	sbbq	56(%rbx),%r15
+
+
+	movq	0(%rax),%rsi
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rcx
+	movq	24(%rax),%rdx
+	cmovncq	%r8,%rsi
+	cmovncq	%r9,%rdi
+	cmovncq	%r10,%rcx
+	cmovncq	%r11,%rdx
+	movq	%rsi,0(%rax)
+	movq	%rdi,8(%rax)
+	movq	%rcx,16(%rax)
+	movq	%rdx,24(%rax)
+
+	movq	32(%rax),%rsi
+	movq	40(%rax),%rdi
+	movq	48(%rax),%rcx
+	movq	56(%rax),%rdx
+	cmovncq	%r12,%rsi
+	cmovncq	%r13,%rdi
+	cmovncq	%r14,%rcx
+	cmovncq	%r15,%rdx
+	movq	%rsi,32(%rax)
+	movq	%rdi,40(%rax)
+	movq	%rcx,48(%rax)
+	movq	%rdx,56(%rax)
+
+	movq	0(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbx
+	movq	40(%rsi),%rbp
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	retq
+.size	mod_exp_512, . - mod_exp_512
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/modexp512-macosx-x86_64.S b/crypto/bn/modexp512-macosx-x86_64.S
new file mode 100644
index 0000000..4d7b0b8
--- /dev/null
+++ b/crypto/bn/modexp512-macosx-x86_64.S
@@ -0,0 +1,1774 @@
+#include "x86_arch.h"
+.text	
+
+
+.p2align	4
+MULADD_128x512:
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	retq
+
+
+.p2align	4
+mont_reduce:
+	leaq	192(%rsp),%rdi
+	movq	32(%rsp),%rsi
+	addq	$576,%rsi
+	leaq	520(%rsp),%rcx
+
+	movq	96(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	movq	(%rcx),%r8
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	movq	8(%rcx),%r9
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	movq	16(%rcx),%r10
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	movq	24(%rcx),%r11
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	movq	32(%rcx),%r12
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	movq	40(%rcx),%r13
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	movq	48(%rcx),%r14
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	movq	56(%rcx),%r15
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	104(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	112(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,16(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	120(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,24(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	xorq	%rax,%rax
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+	adcq	80(%rcx),%r10
+	adcq	88(%rcx),%r11
+	adcq	$0,%rax
+
+
+
+
+	movq	%r8,64(%rdi)
+	movq	%r9,72(%rdi)
+	movq	%r10,%rbp
+	movq	%r11,88(%rdi)
+
+	movq	%rax,384(%rsp)
+
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+
+
+
+
+
+
+
+
+	addq	$80,%rdi
+
+	addq	$64,%rsi
+	leaq	296(%rsp),%rcx
+
+	call	MULADD_128x512			
+
+	movq	384(%rsp),%rax
+
+
+	addq	-16(%rdi),%r8
+	adcq	-8(%rdi),%r9
+	movq	%r8,64(%rcx)
+	movq	%r9,72(%rcx)
+
+	adcq	%rax,%rax
+	movq	%rax,384(%rsp)
+
+	leaq	192(%rsp),%rdi
+	addq	$64,%rsi
+
+
+
+
+
+	movq	(%rsi),%r8
+	movq	8(%rsi),%rbx
+
+	movq	(%rcx),%rax
+	mulq	%r8
+	movq	%rax,%rbp
+	movq	%rdx,%r9
+
+	movq	8(%rcx),%rax
+	mulq	%r8
+	addq	%rax,%r9
+
+	movq	(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r9
+
+	movq	%r9,8(%rdi)
+
+
+	subq	$192,%rsi
+
+	movq	(%rcx),%r8
+	movq	8(%rcx),%r9
+
+	call	MULADD_128x512			
+
+
+
+
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdi
+	movq	24(%rsi),%rdx
+
+
+	movq	384(%rsp),%rbp
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+
+
+	adcq	%rbp,%rbp
+
+
+
+	shlq	$3,%rbp
+	movq	32(%rsp),%rcx
+	addq	%rcx,%rbp
+
+
+	xorq	%rsi,%rsi
+
+	addq	0(%rbp),%r10
+	adcq	64(%rbp),%r11
+	adcq	128(%rbp),%r12
+	adcq	192(%rbp),%r13
+	adcq	256(%rbp),%r14
+	adcq	320(%rbp),%r15
+	adcq	384(%rbp),%r8
+	adcq	448(%rbp),%r9
+
+
+
+	sbbq	$0,%rsi
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+	movq	$1,%rbp
+	subq	%rax,%r10
+	sbbq	%rbx,%r11
+	sbbq	%rdi,%r12
+	sbbq	%rdx,%r13
+
+
+
+
+	sbbq	$0,%rbp
+
+
+
+	addq	$512,%rcx
+	movq	32(%rcx),%rax
+	movq	40(%rcx),%rbx
+	movq	48(%rcx),%rdi
+	movq	56(%rcx),%rdx
+
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+
+
+	subq	$1,%rbp
+
+	sbbq	%rax,%r14
+	sbbq	%rbx,%r15
+	sbbq	%rdi,%r8
+	sbbq	%rdx,%r9
+
+
+
+	movq	144(%rsp),%rsi
+	movq	%r10,0(%rsi)
+	movq	%r11,8(%rsi)
+	movq	%r12,16(%rsi)
+	movq	%r13,24(%rsi)
+	movq	%r14,32(%rsi)
+	movq	%r15,40(%rsi)
+	movq	%r8,48(%rsi)
+	movq	%r9,56(%rsi)
+
+	retq
+
+
+.p2align	4
+mont_mul_a3b:
+
+
+
+
+	movq	0(%rdi),%rbp
+
+	movq	%r10,%rax
+	mulq	%rbp
+	movq	%rax,520(%rsp)
+	movq	%rdx,%r10
+	movq	%r11,%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r12,%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r13,%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r14,%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r15,%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r8,%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,528(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	16(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,536(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	24(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,544(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	32(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,552(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	40(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%r14,560(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	48(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,568(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	56(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,576(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,584(%rsp)
+	movq	%r10,592(%rsp)
+	movq	%r11,600(%rsp)
+	movq	%r12,608(%rsp)
+	movq	%r13,616(%rsp)
+	movq	%r14,624(%rsp)
+	movq	%r15,632(%rsp)
+	movq	%r8,640(%rsp)
+
+
+
+
+
+	jmp	mont_reduce
+
+
+
+
+.p2align	4
+sqr_reduce:
+	movq	16(%rsp),%rcx
+
+
+
+	movq	%r10,%rbx
+
+	movq	%r11,%rax
+	mulq	%rbx
+	movq	%rax,528(%rsp)
+	movq	%rdx,%r10
+	movq	%r12,%rax
+	mulq	%rbx
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r13,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r14,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r15,%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rsi
+
+	movq	%r10,536(%rsp)
+
+
+
+
+
+	movq	8(%rcx),%rbx
+
+	movq	16(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,544(%rsp)
+
+	movq	%rdx,%r10
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,552(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	16(%rcx),%rbx
+
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,560(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+	movq	%r14,568(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r12
+
+
+
+
+
+	movq	24(%rcx),%rbx
+
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,576(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+	movq	%rsi,584(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+
+	movq	%rdx,%r15
+
+
+
+
+	movq	32(%rcx),%rbx
+
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,592(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,600(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	40(%rcx),%rbx
+
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,608(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r11,616(%rsp)
+
+	movq	%rdx,%r12
+
+
+
+
+	movq	%r8,%rbx
+
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,624(%rsp)
+
+	movq	%rdx,632(%rsp)
+
+
+	movq	528(%rsp),%r10
+	movq	536(%rsp),%r11
+	movq	544(%rsp),%r12
+	movq	552(%rsp),%r13
+	movq	560(%rsp),%r14
+	movq	568(%rsp),%r15
+
+	movq	24(%rcx),%rax
+	mulq	%rax
+	movq	%rax,%rdi
+	movq	%rdx,%r8
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	$0,%r8
+
+	movq	0(%rcx),%rax
+	mulq	%rax
+	movq	%rax,520(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+	movq	%r10,528(%rsp)
+	movq	%r11,536(%rsp)
+
+	movq	16(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+
+	movq	%r12,544(%rsp)
+	movq	%r13,552(%rsp)
+
+	xorq	%rbp,%rbp
+	addq	%rbx,%r14
+	adcq	%rdi,%r15
+	adcq	$0,%rbp
+
+	movq	%r14,560(%rsp)
+	movq	%r15,568(%rsp)
+
+
+
+
+	movq	576(%rsp),%r10
+	movq	584(%rsp),%r11
+	movq	592(%rsp),%r12
+	movq	600(%rsp),%r13
+	movq	608(%rsp),%r14
+	movq	616(%rsp),%r15
+	movq	624(%rsp),%rdi
+	movq	632(%rsp),%rsi
+
+	movq	%r9,%rax
+	mulq	%rax
+	movq	%rax,%r9
+	movq	%rdx,%rbx
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	%rdi,%rdi
+	adcq	%rsi,%rsi
+	adcq	$0,%rbx
+
+	addq	%rbp,%r10
+
+	movq	32(%rcx),%rax
+	mulq	%rax
+
+	addq	%r8,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r10,576(%rsp)
+	movq	%r11,584(%rsp)
+
+	movq	40(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r12,592(%rsp)
+	movq	%r13,600(%rsp)
+
+	movq	48(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r14
+	adcq	%rax,%r15
+	adcq	$0,%rdx
+
+	movq	%r14,608(%rsp)
+	movq	%r15,616(%rsp)
+
+	addq	%rdx,%rdi
+	adcq	%r9,%rsi
+	adcq	$0,%rbx
+
+	movq	%rdi,624(%rsp)
+	movq	%rsi,632(%rsp)
+	movq	%rbx,640(%rsp)
+
+	jmp	mont_reduce
+
+
+
+.globl	_mod_exp_512
+
+_mod_exp_512:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r8
+	subq	$2688,%rsp
+	andq	$-64,%rsp
+
+
+	movq	%r8,0(%rsp)
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rcx,24(%rsp)
+L$body:
+
+
+
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rsi),%xmm0
+	movdqu	16(%rsi),%xmm1
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm3
+	movdqa	%xmm4,512(%rsp)
+	movdqa	%xmm4,528(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,544(%rsp)
+	movdqa	%xmm1,560(%rsp)
+	movdqa	%xmm2,576(%rsp)
+	movdqa	%xmm3,592(%rsp)
+
+
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+
+	leaq	384(%rsp),%rbx
+	movq	%rbx,136(%rsp)
+	call	mont_reduce
+
+
+	leaq	448(%rsp),%rcx
+	xorq	%rax,%rax
+	movq	%rax,0(%rcx)
+	movq	%rax,8(%rcx)
+	movq	%rax,24(%rcx)
+	movq	%rax,32(%rcx)
+	movq	%rax,40(%rcx)
+	movq	%rax,48(%rcx)
+	movq	%rax,56(%rcx)
+	movq	%rax,128(%rsp)
+	movq	$1,16(%rcx)
+
+	leaq	640(%rsp),%rbp
+	movq	%rcx,%rsi
+	movq	%rbp,%rdi
+	movq	$8,%rax
+loop_0:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,64(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,128(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,192(%rdi)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rdi),%rdi
+	decq	%rax
+	jnz	loop_0
+	movq	$31,%rax
+	movq	%rax,32(%rsp)
+	movq	%rbp,40(%rsp)
+
+	movq	%rsi,136(%rsp)
+	movq	0(%rsi),%r10
+	movq	8(%rsi),%r11
+	movq	16(%rsi),%r12
+	movq	24(%rsi),%r13
+	movq	32(%rsi),%r14
+	movq	40(%rsi),%r15
+	movq	48(%rsi),%r8
+	movq	56(%rsi),%r9
+init_loop:
+	leaq	384(%rsp),%rdi
+	call	mont_mul_a3b
+	leaq	448(%rsp),%rsi
+	movq	40(%rsp),%rbp
+	addq	$2,%rbp
+	movq	%rbp,40(%rsp)
+	movq	%rsi,%rcx
+	movq	$8,%rax
+loop_1:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,64(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,128(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,192(%rbp)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rbp),%rbp
+	decq	%rax
+	jnz	loop_1
+	movq	32(%rsp),%rax
+	subq	$1,%rax
+	movq	%rax,32(%rsp)
+	jne	init_loop
+
+
+
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm1,80(%rsp)
+	movdqa	%xmm2,96(%rsp)
+	movdqa	%xmm3,112(%rsp)
+
+
+
+
+
+	movl	126(%rsp),%eax
+	movq	%rax,%rdx
+	shrq	$11,%rax
+	andl	$2047,%edx
+	movl	%edx,126(%rsp)
+	leaq	640(%rsp,%rax,2),%rsi
+	movq	8(%rsp),%rdx
+	movq	$4,%rbp
+loop_2:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_2
+	movq	$505,48(%rsp)
+
+	movq	8(%rsp),%rcx
+	movq	%rcx,136(%rsp)
+	movq	0(%rcx),%r10
+	movq	8(%rcx),%r11
+	movq	16(%rcx),%r12
+	movq	24(%rcx),%r13
+	movq	32(%rcx),%r14
+	movq	40(%rcx),%r15
+	movq	48(%rcx),%r8
+	movq	56(%rcx),%r9
+	jmp	sqr_2
+
+main_loop_a3b:
+	call	sqr_reduce
+	call	sqr_reduce
+	call	sqr_reduce
+sqr_2:
+	call	sqr_reduce
+	call	sqr_reduce
+
+
+
+	movq	48(%rsp),%rcx
+	movq	%rcx,%rax
+	shrq	$4,%rax
+	movl	64(%rsp,%rax,2),%edx
+	andq	$15,%rcx
+	shrq	%cl,%rdx
+	andq	$31,%rdx
+
+	leaq	640(%rsp,%rdx,2),%rsi
+	leaq	448(%rsp),%rdx
+	movq	%rdx,%rdi
+	movq	$4,%rbp
+loop_3:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_3
+	movq	8(%rsp),%rsi
+	call	mont_mul_a3b
+
+
+
+	movq	48(%rsp),%rcx
+	subq	$5,%rcx
+	movq	%rcx,48(%rsp)
+	jge	main_loop_a3b
+
+
+
+end_main_loop_a3b:
+
+
+	movq	8(%rsp),%rdx
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+	movdqa	%xmm4,576(%rsp)
+	movdqa	%xmm4,592(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,512(%rsp)
+	movdqa	%xmm1,528(%rsp)
+	movdqa	%xmm2,544(%rsp)
+	movdqa	%xmm3,560(%rsp)
+	call	mont_reduce
+
+
+
+	movq	8(%rsp),%rax
+	movq	0(%rax),%r8
+	movq	8(%rax),%r9
+	movq	16(%rax),%r10
+	movq	24(%rax),%r11
+	movq	32(%rax),%r12
+	movq	40(%rax),%r13
+	movq	48(%rax),%r14
+	movq	56(%rax),%r15
+
+
+	movq	24(%rsp),%rbx
+	addq	$512,%rbx
+
+	subq	0(%rbx),%r8
+	sbbq	8(%rbx),%r9
+	sbbq	16(%rbx),%r10
+	sbbq	24(%rbx),%r11
+	sbbq	32(%rbx),%r12
+	sbbq	40(%rbx),%r13
+	sbbq	48(%rbx),%r14
+	sbbq	56(%rbx),%r15
+
+
+	movq	0(%rax),%rsi
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rcx
+	movq	24(%rax),%rdx
+	cmovncq	%r8,%rsi
+	cmovncq	%r9,%rdi
+	cmovncq	%r10,%rcx
+	cmovncq	%r11,%rdx
+	movq	%rsi,0(%rax)
+	movq	%rdi,8(%rax)
+	movq	%rcx,16(%rax)
+	movq	%rdx,24(%rax)
+
+	movq	32(%rax),%rsi
+	movq	40(%rax),%rdi
+	movq	48(%rax),%rcx
+	movq	56(%rax),%rdx
+	cmovncq	%r12,%rsi
+	cmovncq	%r13,%rdi
+	cmovncq	%r14,%rcx
+	cmovncq	%r15,%rdx
+	movq	%rsi,32(%rax)
+	movq	%rdi,40(%rax)
+	movq	%rcx,48(%rax)
+	movq	%rdx,56(%rax)
+
+	movq	0(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbx
+	movq	40(%rsi),%rbp
+	leaq	48(%rsi),%rsp
+L$epilogue:
+	retq
+
diff --git a/crypto/bn/modexp512-masm-x86_64.S b/crypto/bn/modexp512-masm-x86_64.S
new file mode 100644
index 0000000..fd6d0ab
--- /dev/null
+++ b/crypto/bn/modexp512-masm-x86_64.S
@@ -0,0 +1,1859 @@
+; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/bn/modexp512-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/bn/modexp512-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+
+ALIGN	16
+MULADD_128x512	PROC PRIVATE
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	mov	QWORD PTR[rcx],r8
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	r8,rdx
+	mov	rbp,QWORD PTR[8+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	mov	QWORD PTR[8+rcx],r9
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	r9,rdx
+	DB	0F3h,0C3h		;repret
+MULADD_128x512	ENDP
+
+ALIGN	16
+mont_reduce	PROC PRIVATE
+	lea	rdi,QWORD PTR[192+rsp]
+	mov	rsi,QWORD PTR[32+rsp]
+	add	rsi,576
+	lea	rcx,QWORD PTR[520+rsp]
+
+	mov	rbp,QWORD PTR[96+rcx]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	mov	r8,QWORD PTR[rcx]
+	add	r8,rax
+	adc	rdx,0
+	mov	QWORD PTR[rdi],r8
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	mov	r9,QWORD PTR[8+rcx]
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	mov	r10,QWORD PTR[16+rcx]
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	mov	r11,QWORD PTR[24+rcx]
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	mov	r12,QWORD PTR[32+rcx]
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	mov	r13,QWORD PTR[40+rcx]
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	mov	r14,QWORD PTR[48+rcx]
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	mov	r15,QWORD PTR[56+rcx]
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	r8,rdx
+	mov	rbp,QWORD PTR[104+rcx]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	mov	QWORD PTR[8+rdi],r9
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	r9,rdx
+	mov	rbp,QWORD PTR[112+rcx]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	mov	QWORD PTR[16+rdi],r10
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	r10,rdx
+	mov	rbp,QWORD PTR[120+rcx]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	mov	QWORD PTR[24+rdi],r11
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	r11,rdx
+	xor	rax,rax
+
+	add	r8,QWORD PTR[64+rcx]
+	adc	r9,QWORD PTR[72+rcx]
+	adc	r10,QWORD PTR[80+rcx]
+	adc	r11,QWORD PTR[88+rcx]
+	adc	rax,0
+
+
+
+
+	mov	QWORD PTR[64+rdi],r8
+	mov	QWORD PTR[72+rdi],r9
+	mov	rbp,r10
+	mov	QWORD PTR[88+rdi],r11
+
+	mov	QWORD PTR[384+rsp],rax
+
+	mov	r8,QWORD PTR[rdi]
+	mov	r9,QWORD PTR[8+rdi]
+	mov	r10,QWORD PTR[16+rdi]
+	mov	r11,QWORD PTR[24+rdi]
+
+
+
+
+
+
+
+
+	add	rdi,8*10
+
+	add	rsi,64
+	lea	rcx,QWORD PTR[296+rsp]
+
+	call	MULADD_128x512			
+
+	mov	rax,QWORD PTR[384+rsp]
+
+
+	add	r8,QWORD PTR[((-16))+rdi]
+	adc	r9,QWORD PTR[((-8))+rdi]
+	mov	QWORD PTR[64+rcx],r8
+	mov	QWORD PTR[72+rcx],r9
+
+	adc	rax,rax
+	mov	QWORD PTR[384+rsp],rax
+
+	lea	rdi,QWORD PTR[192+rsp]
+	add	rsi,64
+
+
+
+
+
+	mov	r8,QWORD PTR[rsi]
+	mov	rbx,QWORD PTR[8+rsi]
+
+	mov	rax,QWORD PTR[rcx]
+	mul	r8
+	mov	rbp,rax
+	mov	r9,rdx
+
+	mov	rax,QWORD PTR[8+rcx]
+	mul	r8
+	add	r9,rax
+
+	mov	rax,QWORD PTR[rcx]
+	mul	rbx
+	add	r9,rax
+
+	mov	QWORD PTR[8+rdi],r9
+
+
+	sub	rsi,192
+
+	mov	r8,QWORD PTR[rcx]
+	mov	r9,QWORD PTR[8+rcx]
+
+	call	MULADD_128x512			
+
+
+
+
+	mov	rax,QWORD PTR[rsi]
+	mov	rbx,QWORD PTR[8+rsi]
+	mov	rdi,QWORD PTR[16+rsi]
+	mov	rdx,QWORD PTR[24+rsi]
+
+
+	mov	rbp,QWORD PTR[384+rsp]
+
+	add	r8,QWORD PTR[64+rcx]
+	adc	r9,QWORD PTR[72+rcx]
+
+
+	adc	rbp,rbp
+
+
+
+	shl	rbp,3
+	mov	rcx,QWORD PTR[32+rsp]
+	add	rbp,rcx
+
+
+	xor	rsi,rsi
+
+	add	r10,QWORD PTR[rbp]
+	adc	r11,QWORD PTR[64+rbp]
+	adc	r12,QWORD PTR[128+rbp]
+	adc	r13,QWORD PTR[192+rbp]
+	adc	r14,QWORD PTR[256+rbp]
+	adc	r15,QWORD PTR[320+rbp]
+	adc	r8,QWORD PTR[384+rbp]
+	adc	r9,QWORD PTR[448+rbp]
+
+
+
+	sbb	rsi,0
+
+
+	and	rax,rsi
+	and	rbx,rsi
+	and	rdi,rsi
+	and	rdx,rsi
+
+	mov	rbp,1
+	sub	r10,rax
+	sbb	r11,rbx
+	sbb	r12,rdi
+	sbb	r13,rdx
+
+
+
+
+	sbb	rbp,0
+
+
+
+	add	rcx,512
+	mov	rax,QWORD PTR[32+rcx]
+	mov	rbx,QWORD PTR[40+rcx]
+	mov	rdi,QWORD PTR[48+rcx]
+	mov	rdx,QWORD PTR[56+rcx]
+
+
+
+	and	rax,rsi
+	and	rbx,rsi
+	and	rdi,rsi
+	and	rdx,rsi
+
+
+
+	sub	rbp,1
+
+	sbb	r14,rax
+	sbb	r15,rbx
+	sbb	r8,rdi
+	sbb	r9,rdx
+
+
+
+	mov	rsi,QWORD PTR[144+rsp]
+	mov	QWORD PTR[rsi],r10
+	mov	QWORD PTR[8+rsi],r11
+	mov	QWORD PTR[16+rsi],r12
+	mov	QWORD PTR[24+rsi],r13
+	mov	QWORD PTR[32+rsi],r14
+	mov	QWORD PTR[40+rsi],r15
+	mov	QWORD PTR[48+rsi],r8
+	mov	QWORD PTR[56+rsi],r9
+
+	DB	0F3h,0C3h		;repret
+mont_reduce	ENDP
+
+ALIGN	16
+mont_mul_a3b	PROC PRIVATE
+
+
+
+
+	mov	rbp,QWORD PTR[rdi]
+
+	mov	rax,r10
+	mul	rbp
+	mov	QWORD PTR[520+rsp],rax
+	mov	r10,rdx
+	mov	rax,r11
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	mov	r11,rdx
+	mov	rax,r12
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	mov	r12,rdx
+	mov	rax,r13
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	mov	r13,rdx
+	mov	rax,r14
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	mov	r14,rdx
+	mov	rax,r15
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	mov	r15,rdx
+	mov	rax,r8
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	mov	r8,rdx
+	mov	rax,r9
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	mov	r9,rdx
+	mov	rbp,QWORD PTR[8+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	mov	QWORD PTR[528+rsp],r10
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	r10,rdx
+	mov	rbp,QWORD PTR[16+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	mov	QWORD PTR[536+rsp],r11
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	r11,rdx
+	mov	rbp,QWORD PTR[24+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	mov	QWORD PTR[544+rsp],r12
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	r12,rdx
+	mov	rbp,QWORD PTR[32+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	mov	QWORD PTR[552+rsp],r13
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	r13,rdx
+	mov	rbp,QWORD PTR[40+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	mov	QWORD PTR[560+rsp],r14
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	r14,rdx
+	mov	rbp,QWORD PTR[48+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	mov	QWORD PTR[568+rsp],r15
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	add	r8,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	r15,rdx
+	mov	rbp,QWORD PTR[56+rdi]
+	mov	rax,QWORD PTR[rsi]
+	mul	rbp
+	add	r8,rax
+	adc	rdx,0
+	mov	QWORD PTR[576+rsp],r8
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rsi]
+	mul	rbp
+	add	r9,rax
+	adc	rdx,0
+	add	r9,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[16+rsi]
+	mul	rbp
+	add	r10,rax
+	adc	rdx,0
+	add	r10,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[24+rsi]
+	mul	rbp
+	add	r11,rax
+	adc	rdx,0
+	add	r11,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[32+rsi]
+	mul	rbp
+	add	r12,rax
+	adc	rdx,0
+	add	r12,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[40+rsi]
+	mul	rbp
+	add	r13,rax
+	adc	rdx,0
+	add	r13,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[48+rsi]
+	mul	rbp
+	add	r14,rax
+	adc	rdx,0
+	add	r14,rbx
+	adc	rdx,0
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[56+rsi]
+	mul	rbp
+	add	r15,rax
+	adc	rdx,0
+	add	r15,rbx
+	adc	rdx,0
+	mov	r8,rdx
+	mov	QWORD PTR[584+rsp],r9
+	mov	QWORD PTR[592+rsp],r10
+	mov	QWORD PTR[600+rsp],r11
+	mov	QWORD PTR[608+rsp],r12
+	mov	QWORD PTR[616+rsp],r13
+	mov	QWORD PTR[624+rsp],r14
+	mov	QWORD PTR[632+rsp],r15
+	mov	QWORD PTR[640+rsp],r8
+
+
+
+
+
+	jmp	mont_reduce
+
+
+mont_mul_a3b	ENDP
+
+ALIGN	16
+sqr_reduce	PROC PRIVATE
+	mov	rcx,QWORD PTR[16+rsp]
+
+
+
+	mov	rbx,r10
+
+	mov	rax,r11
+	mul	rbx
+	mov	QWORD PTR[528+rsp],rax
+	mov	r10,rdx
+	mov	rax,r12
+	mul	rbx
+	add	r10,rax
+	adc	rdx,0
+	mov	r11,rdx
+	mov	rax,r13
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	mov	r12,rdx
+	mov	rax,r14
+	mul	rbx
+	add	r12,rax
+	adc	rdx,0
+	mov	r13,rdx
+	mov	rax,r15
+	mul	rbx
+	add	r13,rax
+	adc	rdx,0
+	mov	r14,rdx
+	mov	rax,r8
+	mul	rbx
+	add	r14,rax
+	adc	rdx,0
+	mov	r15,rdx
+	mov	rax,r9
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	mov	rsi,rdx
+
+	mov	QWORD PTR[536+rsp],r10
+
+
+
+
+
+	mov	rbx,QWORD PTR[8+rcx]
+
+	mov	rax,QWORD PTR[16+rcx]
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	mov	QWORD PTR[544+rsp],r11
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[24+rcx]
+	mul	rbx
+	add	r12,rax
+	adc	rdx,0
+	add	r12,r10
+	adc	rdx,0
+	mov	QWORD PTR[552+rsp],r12
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[32+rcx]
+	mul	rbx
+	add	r13,rax
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[40+rcx]
+	mul	rbx
+	add	r14,rax
+	adc	rdx,0
+	add	r14,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,r8
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	add	r15,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,r9
+	mul	rbx
+	add	rsi,rax
+	adc	rdx,0
+	add	rsi,r10
+	adc	rdx,0
+
+	mov	r11,rdx
+
+
+
+
+	mov	rbx,QWORD PTR[16+rcx]
+
+	mov	rax,QWORD PTR[24+rcx]
+	mul	rbx
+	add	r13,rax
+	adc	rdx,0
+	mov	QWORD PTR[560+rsp],r13
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[32+rcx]
+	mul	rbx
+	add	r14,rax
+	adc	rdx,0
+	add	r14,r10
+	adc	rdx,0
+	mov	QWORD PTR[568+rsp],r14
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[40+rcx]
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	add	r15,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,r8
+	mul	rbx
+	add	rsi,rax
+	adc	rdx,0
+	add	rsi,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,r9
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	add	r11,r10
+	adc	rdx,0
+
+	mov	r12,rdx
+
+
+
+
+
+	mov	rbx,QWORD PTR[24+rcx]
+
+	mov	rax,QWORD PTR[32+rcx]
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	mov	QWORD PTR[576+rsp],r15
+
+	mov	r10,rdx
+	mov	rax,QWORD PTR[40+rcx]
+	mul	rbx
+	add	rsi,rax
+	adc	rdx,0
+	add	rsi,r10
+	adc	rdx,0
+	mov	QWORD PTR[584+rsp],rsi
+
+	mov	r10,rdx
+	mov	rax,r8
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	add	r11,r10
+	adc	rdx,0
+
+	mov	r10,rdx
+	mov	rax,r9
+	mul	rbx
+	add	r12,rax
+	adc	rdx,0
+	add	r12,r10
+	adc	rdx,0
+
+	mov	r15,rdx
+
+
+
+
+	mov	rbx,QWORD PTR[32+rcx]
+
+	mov	rax,QWORD PTR[40+rcx]
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	mov	QWORD PTR[592+rsp],r11
+
+	mov	r10,rdx
+	mov	rax,r8
+	mul	rbx
+	add	r12,rax
+	adc	rdx,0
+	add	r12,r10
+	adc	rdx,0
+	mov	QWORD PTR[600+rsp],r12
+
+	mov	r10,rdx
+	mov	rax,r9
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	add	r15,r10
+	adc	rdx,0
+
+	mov	r11,rdx
+
+
+
+
+	mov	rbx,QWORD PTR[40+rcx]
+
+	mov	rax,r8
+	mul	rbx
+	add	r15,rax
+	adc	rdx,0
+	mov	QWORD PTR[608+rsp],r15
+
+	mov	r10,rdx
+	mov	rax,r9
+	mul	rbx
+	add	r11,rax
+	adc	rdx,0
+	add	r11,r10
+	adc	rdx,0
+	mov	QWORD PTR[616+rsp],r11
+
+	mov	r12,rdx
+
+
+
+
+	mov	rbx,r8
+
+	mov	rax,r9
+	mul	rbx
+	add	r12,rax
+	adc	rdx,0
+	mov	QWORD PTR[624+rsp],r12
+
+	mov	QWORD PTR[632+rsp],rdx
+
+
+	mov	r10,QWORD PTR[528+rsp]
+	mov	r11,QWORD PTR[536+rsp]
+	mov	r12,QWORD PTR[544+rsp]
+	mov	r13,QWORD PTR[552+rsp]
+	mov	r14,QWORD PTR[560+rsp]
+	mov	r15,QWORD PTR[568+rsp]
+
+	mov	rax,QWORD PTR[24+rcx]
+	mul	rax
+	mov	rdi,rax
+	mov	r8,rdx
+
+	add	r10,r10
+	adc	r11,r11
+	adc	r12,r12
+	adc	r13,r13
+	adc	r14,r14
+	adc	r15,r15
+	adc	r8,0
+
+	mov	rax,QWORD PTR[rcx]
+	mul	rax
+	mov	QWORD PTR[520+rsp],rax
+	mov	rbx,rdx
+
+	mov	rax,QWORD PTR[8+rcx]
+	mul	rax
+
+	add	r10,rbx
+	adc	r11,rax
+	adc	rdx,0
+
+	mov	rbx,rdx
+	mov	QWORD PTR[528+rsp],r10
+	mov	QWORD PTR[536+rsp],r11
+
+	mov	rax,QWORD PTR[16+rcx]
+	mul	rax
+
+	add	r12,rbx
+	adc	r13,rax
+	adc	rdx,0
+
+	mov	rbx,rdx
+
+	mov	QWORD PTR[544+rsp],r12
+	mov	QWORD PTR[552+rsp],r13
+
+	xor	rbp,rbp
+	add	r14,rbx
+	adc	r15,rdi
+	adc	rbp,0
+
+	mov	QWORD PTR[560+rsp],r14
+	mov	QWORD PTR[568+rsp],r15
+
+
+
+
+	mov	r10,QWORD PTR[576+rsp]
+	mov	r11,QWORD PTR[584+rsp]
+	mov	r12,QWORD PTR[592+rsp]
+	mov	r13,QWORD PTR[600+rsp]
+	mov	r14,QWORD PTR[608+rsp]
+	mov	r15,QWORD PTR[616+rsp]
+	mov	rdi,QWORD PTR[624+rsp]
+	mov	rsi,QWORD PTR[632+rsp]
+
+	mov	rax,r9
+	mul	rax
+	mov	r9,rax
+	mov	rbx,rdx
+
+	add	r10,r10
+	adc	r11,r11
+	adc	r12,r12
+	adc	r13,r13
+	adc	r14,r14
+	adc	r15,r15
+	adc	rdi,rdi
+	adc	rsi,rsi
+	adc	rbx,0
+
+	add	r10,rbp
+
+	mov	rax,QWORD PTR[32+rcx]
+	mul	rax
+
+	add	r10,r8
+	adc	r11,rax
+	adc	rdx,0
+
+	mov	rbp,rdx
+
+	mov	QWORD PTR[576+rsp],r10
+	mov	QWORD PTR[584+rsp],r11
+
+	mov	rax,QWORD PTR[40+rcx]
+	mul	rax
+
+	add	r12,rbp
+	adc	r13,rax
+	adc	rdx,0
+
+	mov	rbp,rdx
+
+	mov	QWORD PTR[592+rsp],r12
+	mov	QWORD PTR[600+rsp],r13
+
+	mov	rax,QWORD PTR[48+rcx]
+	mul	rax
+
+	add	r14,rbp
+	adc	r15,rax
+	adc	rdx,0
+
+	mov	QWORD PTR[608+rsp],r14
+	mov	QWORD PTR[616+rsp],r15
+
+	add	rdi,rdx
+	adc	rsi,r9
+	adc	rbx,0
+
+	mov	QWORD PTR[624+rsp],rdi
+	mov	QWORD PTR[632+rsp],rsi
+	mov	QWORD PTR[640+rsp],rbx
+
+	jmp	mont_reduce
+
+
+sqr_reduce	ENDP
+PUBLIC	mod_exp_512
+
+mod_exp_512	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_mod_exp_512::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbp
+	push	rbx
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+
+	mov	r8,rsp
+	sub	rsp,2688
+	and	rsp,-64
+
+
+	mov	QWORD PTR[rsp],r8
+	mov	QWORD PTR[8+rsp],rdi
+	mov	QWORD PTR[16+rsp],rsi
+	mov	QWORD PTR[24+rsp],rcx
+$L$body::
+
+
+
+	pxor	xmm4,xmm4
+	movdqu	xmm0,XMMWORD PTR[rsi]
+	movdqu	xmm1,XMMWORD PTR[16+rsi]
+	movdqu	xmm2,XMMWORD PTR[32+rsi]
+	movdqu	xmm3,XMMWORD PTR[48+rsi]
+	movdqa	XMMWORD PTR[512+rsp],xmm4
+	movdqa	XMMWORD PTR[528+rsp],xmm4
+	movdqa	XMMWORD PTR[608+rsp],xmm4
+	movdqa	XMMWORD PTR[624+rsp],xmm4
+	movdqa	XMMWORD PTR[544+rsp],xmm0
+	movdqa	XMMWORD PTR[560+rsp],xmm1
+	movdqa	XMMWORD PTR[576+rsp],xmm2
+	movdqa	XMMWORD PTR[592+rsp],xmm3
+
+
+	movdqu	xmm0,XMMWORD PTR[rdx]
+	movdqu	xmm1,XMMWORD PTR[16+rdx]
+	movdqu	xmm2,XMMWORD PTR[32+rdx]
+	movdqu	xmm3,XMMWORD PTR[48+rdx]
+
+	lea	rbx,QWORD PTR[384+rsp]
+	mov	QWORD PTR[136+rsp],rbx
+	call	mont_reduce
+
+
+	lea	rcx,QWORD PTR[448+rsp]
+	xor	rax,rax
+	mov	QWORD PTR[rcx],rax
+	mov	QWORD PTR[8+rcx],rax
+	mov	QWORD PTR[24+rcx],rax
+	mov	QWORD PTR[32+rcx],rax
+	mov	QWORD PTR[40+rcx],rax
+	mov	QWORD PTR[48+rcx],rax
+	mov	QWORD PTR[56+rcx],rax
+	mov	QWORD PTR[128+rsp],rax
+	mov	QWORD PTR[16+rcx],1
+
+	lea	rbp,QWORD PTR[640+rsp]
+	mov	rsi,rcx
+	mov	rdi,rbp
+	mov	rax,8
+loop_0::
+	mov	rbx,QWORD PTR[rcx]
+	mov	WORD PTR[rdi],bx
+	shr	rbx,16
+	mov	WORD PTR[64+rdi],bx
+	shr	rbx,16
+	mov	WORD PTR[128+rdi],bx
+	shr	rbx,16
+	mov	WORD PTR[192+rdi],bx
+	lea	rcx,QWORD PTR[8+rcx]
+	lea	rdi,QWORD PTR[256+rdi]
+	dec	rax
+	jnz	loop_0
+	mov	rax,31
+	mov	QWORD PTR[32+rsp],rax
+	mov	QWORD PTR[40+rsp],rbp
+
+	mov	QWORD PTR[136+rsp],rsi
+	mov	r10,QWORD PTR[rsi]
+	mov	r11,QWORD PTR[8+rsi]
+	mov	r12,QWORD PTR[16+rsi]
+	mov	r13,QWORD PTR[24+rsi]
+	mov	r14,QWORD PTR[32+rsi]
+	mov	r15,QWORD PTR[40+rsi]
+	mov	r8,QWORD PTR[48+rsi]
+	mov	r9,QWORD PTR[56+rsi]
+init_loop::
+	lea	rdi,QWORD PTR[384+rsp]
+	call	mont_mul_a3b
+	lea	rsi,QWORD PTR[448+rsp]
+	mov	rbp,QWORD PTR[40+rsp]
+	add	rbp,2
+	mov	QWORD PTR[40+rsp],rbp
+	mov	rcx,rsi
+	mov	rax,8
+loop_1::
+	mov	rbx,QWORD PTR[rcx]
+	mov	WORD PTR[rbp],bx
+	shr	rbx,16
+	mov	WORD PTR[64+rbp],bx
+	shr	rbx,16
+	mov	WORD PTR[128+rbp],bx
+	shr	rbx,16
+	mov	WORD PTR[192+rbp],bx
+	lea	rcx,QWORD PTR[8+rcx]
+	lea	rbp,QWORD PTR[256+rbp]
+	dec	rax
+	jnz	loop_1
+	mov	rax,QWORD PTR[32+rsp]
+	sub	rax,1
+	mov	QWORD PTR[32+rsp],rax
+	jne	init_loop
+
+
+
+	movdqa	XMMWORD PTR[64+rsp],xmm0
+	movdqa	XMMWORD PTR[80+rsp],xmm1
+	movdqa	XMMWORD PTR[96+rsp],xmm2
+	movdqa	XMMWORD PTR[112+rsp],xmm3
+
+
+
+
+
+	mov	eax,DWORD PTR[126+rsp]
+	mov	rdx,rax
+	shr	rax,11
+	and	edx,007FFh
+	mov	DWORD PTR[126+rsp],edx
+	lea	rsi,QWORD PTR[640+rax*2+rsp]
+	mov	rdx,QWORD PTR[8+rsp]
+	mov	rbp,4
+loop_2::
+	movzx	rbx,WORD PTR[192+rsi]
+	movzx	rax,WORD PTR[448+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[128+rsi]
+	mov	ax,WORD PTR[384+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[64+rsi]
+	mov	ax,WORD PTR[320+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[rsi]
+	mov	ax,WORD PTR[256+rsi]
+	mov	QWORD PTR[rdx],rbx
+	mov	QWORD PTR[8+rdx],rax
+	lea	rsi,QWORD PTR[512+rsi]
+	lea	rdx,QWORD PTR[16+rdx]
+	sub	rbp,1
+	jnz	loop_2
+	mov	QWORD PTR[48+rsp],505
+
+	mov	rcx,QWORD PTR[8+rsp]
+	mov	QWORD PTR[136+rsp],rcx
+	mov	r10,QWORD PTR[rcx]
+	mov	r11,QWORD PTR[8+rcx]
+	mov	r12,QWORD PTR[16+rcx]
+	mov	r13,QWORD PTR[24+rcx]
+	mov	r14,QWORD PTR[32+rcx]
+	mov	r15,QWORD PTR[40+rcx]
+	mov	r8,QWORD PTR[48+rcx]
+	mov	r9,QWORD PTR[56+rcx]
+	jmp	sqr_2
+
+main_loop_a3b::
+	call	sqr_reduce
+	call	sqr_reduce
+	call	sqr_reduce
+sqr_2::
+	call	sqr_reduce
+	call	sqr_reduce
+
+
+
+	mov	rcx,QWORD PTR[48+rsp]
+	mov	rax,rcx
+	shr	rax,4
+	mov	edx,DWORD PTR[64+rax*2+rsp]
+	and	rcx,15
+	shr	rdx,cl
+	and	rdx,01Fh
+
+	lea	rsi,QWORD PTR[640+rdx*2+rsp]
+	lea	rdx,QWORD PTR[448+rsp]
+	mov	rdi,rdx
+	mov	rbp,4
+loop_3::
+	movzx	rbx,WORD PTR[192+rsi]
+	movzx	rax,WORD PTR[448+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[128+rsi]
+	mov	ax,WORD PTR[384+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[64+rsi]
+	mov	ax,WORD PTR[320+rsi]
+	shl	rbx,16
+	shl	rax,16
+	mov	bx,WORD PTR[rsi]
+	mov	ax,WORD PTR[256+rsi]
+	mov	QWORD PTR[rdx],rbx
+	mov	QWORD PTR[8+rdx],rax
+	lea	rsi,QWORD PTR[512+rsi]
+	lea	rdx,QWORD PTR[16+rdx]
+	sub	rbp,1
+	jnz	loop_3
+	mov	rsi,QWORD PTR[8+rsp]
+	call	mont_mul_a3b
+
+
+
+	mov	rcx,QWORD PTR[48+rsp]
+	sub	rcx,5
+	mov	QWORD PTR[48+rsp],rcx
+	jge	main_loop_a3b
+
+
+
+end_main_loop_a3b::
+
+
+	mov	rdx,QWORD PTR[8+rsp]
+	pxor	xmm4,xmm4
+	movdqu	xmm0,XMMWORD PTR[rdx]
+	movdqu	xmm1,XMMWORD PTR[16+rdx]
+	movdqu	xmm2,XMMWORD PTR[32+rdx]
+	movdqu	xmm3,XMMWORD PTR[48+rdx]
+	movdqa	XMMWORD PTR[576+rsp],xmm4
+	movdqa	XMMWORD PTR[592+rsp],xmm4
+	movdqa	XMMWORD PTR[608+rsp],xmm4
+	movdqa	XMMWORD PTR[624+rsp],xmm4
+	movdqa	XMMWORD PTR[512+rsp],xmm0
+	movdqa	XMMWORD PTR[528+rsp],xmm1
+	movdqa	XMMWORD PTR[544+rsp],xmm2
+	movdqa	XMMWORD PTR[560+rsp],xmm3
+	call	mont_reduce
+
+
+
+	mov	rax,QWORD PTR[8+rsp]
+	mov	r8,QWORD PTR[rax]
+	mov	r9,QWORD PTR[8+rax]
+	mov	r10,QWORD PTR[16+rax]
+	mov	r11,QWORD PTR[24+rax]
+	mov	r12,QWORD PTR[32+rax]
+	mov	r13,QWORD PTR[40+rax]
+	mov	r14,QWORD PTR[48+rax]
+	mov	r15,QWORD PTR[56+rax]
+
+
+	mov	rbx,QWORD PTR[24+rsp]
+	add	rbx,512
+
+	sub	r8,QWORD PTR[rbx]
+	sbb	r9,QWORD PTR[8+rbx]
+	sbb	r10,QWORD PTR[16+rbx]
+	sbb	r11,QWORD PTR[24+rbx]
+	sbb	r12,QWORD PTR[32+rbx]
+	sbb	r13,QWORD PTR[40+rbx]
+	sbb	r14,QWORD PTR[48+rbx]
+	sbb	r15,QWORD PTR[56+rbx]
+
+
+	mov	rsi,QWORD PTR[rax]
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rcx,QWORD PTR[16+rax]
+	mov	rdx,QWORD PTR[24+rax]
+	cmovnc	rsi,r8
+	cmovnc	rdi,r9
+	cmovnc	rcx,r10
+	cmovnc	rdx,r11
+	mov	QWORD PTR[rax],rsi
+	mov	QWORD PTR[8+rax],rdi
+	mov	QWORD PTR[16+rax],rcx
+	mov	QWORD PTR[24+rax],rdx
+
+	mov	rsi,QWORD PTR[32+rax]
+	mov	rdi,QWORD PTR[40+rax]
+	mov	rcx,QWORD PTR[48+rax]
+	mov	rdx,QWORD PTR[56+rax]
+	cmovnc	rsi,r12
+	cmovnc	rdi,r13
+	cmovnc	rcx,r14
+	cmovnc	rdx,r15
+	mov	QWORD PTR[32+rax],rsi
+	mov	QWORD PTR[40+rax],rdi
+	mov	QWORD PTR[48+rax],rcx
+	mov	QWORD PTR[56+rax],rdx
+
+	mov	rsi,QWORD PTR[rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbx,QWORD PTR[32+rsi]
+	mov	rbp,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_mod_exp_512::
+mod_exp_512	ENDP
+
+.text$	ENDS
+END
+
diff --git a/crypto/bn/modexp512-mingw64-x86_64.S b/crypto/bn/modexp512-mingw64-x86_64.S
new file mode 100644
index 0000000..1c4a556
--- /dev/null
+++ b/crypto/bn/modexp512-mingw64-x86_64.S
@@ -0,0 +1,1785 @@
+#include "x86_arch.h"
+.text	
+
+.def	MULADD_128x512;	.scl 3;	.type 32;	.endef
+.p2align	4
+MULADD_128x512:
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rcx)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	retq
+
+.def	mont_reduce;	.scl 3;	.type 32;	.endef
+.p2align	4
+mont_reduce:
+	leaq	192(%rsp),%rdi
+	movq	32(%rsp),%rsi
+	addq	$576,%rsi
+	leaq	520(%rsp),%rcx
+
+	movq	96(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	movq	(%rcx),%r8
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,0(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	movq	8(%rcx),%r9
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	movq	16(%rcx),%r10
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	movq	24(%rcx),%r11
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	movq	32(%rcx),%r12
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	movq	40(%rcx),%r13
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	movq	48(%rcx),%r14
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	movq	56(%rcx),%r15
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	104(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	movq	%r9,8(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	112(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,16(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	120(%rcx),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,24(%rdi)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	xorq	%rax,%rax
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+	adcq	80(%rcx),%r10
+	adcq	88(%rcx),%r11
+	adcq	$0,%rax
+
+
+
+
+	movq	%r8,64(%rdi)
+	movq	%r9,72(%rdi)
+	movq	%r10,%rbp
+	movq	%r11,88(%rdi)
+
+	movq	%rax,384(%rsp)
+
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+
+
+
+
+
+
+
+
+	addq	$80,%rdi
+
+	addq	$64,%rsi
+	leaq	296(%rsp),%rcx
+
+	call	MULADD_128x512			
+
+	movq	384(%rsp),%rax
+
+
+	addq	-16(%rdi),%r8
+	adcq	-8(%rdi),%r9
+	movq	%r8,64(%rcx)
+	movq	%r9,72(%rcx)
+
+	adcq	%rax,%rax
+	movq	%rax,384(%rsp)
+
+	leaq	192(%rsp),%rdi
+	addq	$64,%rsi
+
+
+
+
+
+	movq	(%rsi),%r8
+	movq	8(%rsi),%rbx
+
+	movq	(%rcx),%rax
+	mulq	%r8
+	movq	%rax,%rbp
+	movq	%rdx,%r9
+
+	movq	8(%rcx),%rax
+	mulq	%r8
+	addq	%rax,%r9
+
+	movq	(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r9
+
+	movq	%r9,8(%rdi)
+
+
+	subq	$192,%rsi
+
+	movq	(%rcx),%r8
+	movq	8(%rcx),%r9
+
+	call	MULADD_128x512			
+
+
+
+
+	movq	0(%rsi),%rax
+	movq	8(%rsi),%rbx
+	movq	16(%rsi),%rdi
+	movq	24(%rsi),%rdx
+
+
+	movq	384(%rsp),%rbp
+
+	addq	64(%rcx),%r8
+	adcq	72(%rcx),%r9
+
+
+	adcq	%rbp,%rbp
+
+
+
+	shlq	$3,%rbp
+	movq	32(%rsp),%rcx
+	addq	%rcx,%rbp
+
+
+	xorq	%rsi,%rsi
+
+	addq	0(%rbp),%r10
+	adcq	64(%rbp),%r11
+	adcq	128(%rbp),%r12
+	adcq	192(%rbp),%r13
+	adcq	256(%rbp),%r14
+	adcq	320(%rbp),%r15
+	adcq	384(%rbp),%r8
+	adcq	448(%rbp),%r9
+
+
+
+	sbbq	$0,%rsi
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+	movq	$1,%rbp
+	subq	%rax,%r10
+	sbbq	%rbx,%r11
+	sbbq	%rdi,%r12
+	sbbq	%rdx,%r13
+
+
+
+
+	sbbq	$0,%rbp
+
+
+
+	addq	$512,%rcx
+	movq	32(%rcx),%rax
+	movq	40(%rcx),%rbx
+	movq	48(%rcx),%rdi
+	movq	56(%rcx),%rdx
+
+
+
+	andq	%rsi,%rax
+	andq	%rsi,%rbx
+	andq	%rsi,%rdi
+	andq	%rsi,%rdx
+
+
+
+	subq	$1,%rbp
+
+	sbbq	%rax,%r14
+	sbbq	%rbx,%r15
+	sbbq	%rdi,%r8
+	sbbq	%rdx,%r9
+
+
+
+	movq	144(%rsp),%rsi
+	movq	%r10,0(%rsi)
+	movq	%r11,8(%rsi)
+	movq	%r12,16(%rsi)
+	movq	%r13,24(%rsi)
+	movq	%r14,32(%rsi)
+	movq	%r15,40(%rsi)
+	movq	%r8,48(%rsi)
+	movq	%r9,56(%rsi)
+
+	retq
+
+.def	mont_mul_a3b;	.scl 3;	.type 32;	.endef
+.p2align	4
+mont_mul_a3b:
+
+
+
+
+	movq	0(%rdi),%rbp
+
+	movq	%r10,%rax
+	mulq	%rbp
+	movq	%rax,520(%rsp)
+	movq	%rdx,%r10
+	movq	%r11,%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r12,%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r13,%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r14,%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r15,%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r8,%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%r9
+	movq	8(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%r10,528(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	16(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,536(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	24(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,544(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	32(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,552(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	40(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%r14,560(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	48(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,568(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	addq	%rbx,%r8
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	56(%rdi),%rbp
+	movq	0(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r8
+	adcq	$0,%rdx
+	movq	%r8,576(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r9
+	adcq	$0,%rdx
+	addq	%rbx,%r9
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	16(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	addq	%rbx,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	24(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%rbx,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	32(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%rbx,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	40(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%rbx,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	48(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%rbx,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%rbx
+
+	movq	56(%rsi),%rax
+	mulq	%rbp
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%rbx,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r8
+	movq	%r9,584(%rsp)
+	movq	%r10,592(%rsp)
+	movq	%r11,600(%rsp)
+	movq	%r12,608(%rsp)
+	movq	%r13,616(%rsp)
+	movq	%r14,624(%rsp)
+	movq	%r15,632(%rsp)
+	movq	%r8,640(%rsp)
+
+
+
+
+
+	jmp	mont_reduce
+
+
+
+.def	sqr_reduce;	.scl 3;	.type 32;	.endef
+.p2align	4
+sqr_reduce:
+	movq	16(%rsp),%rcx
+
+
+
+	movq	%r10,%rbx
+
+	movq	%r11,%rax
+	mulq	%rbx
+	movq	%rax,528(%rsp)
+	movq	%rdx,%r10
+	movq	%r12,%rax
+	mulq	%rbx
+	addq	%rax,%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+	movq	%r13,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r12
+	movq	%r14,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	movq	%r15,%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%rdx,%r14
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r15
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%rdx,%rsi
+
+	movq	%r10,536(%rsp)
+
+
+
+
+
+	movq	8(%rcx),%rbx
+
+	movq	16(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,544(%rsp)
+
+	movq	%rdx,%r10
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,552(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	16(%rcx),%rbx
+
+	movq	24(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r13
+	adcq	$0,%rdx
+	movq	%r13,560(%rsp)
+
+	movq	%rdx,%r10
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	addq	%r10,%r14
+	adcq	$0,%rdx
+	movq	%r14,568(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r12
+
+
+
+
+
+	movq	24(%rcx),%rbx
+
+	movq	32(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,576(%rsp)
+
+	movq	%rdx,%r10
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%rsi
+	adcq	$0,%rdx
+	addq	%r10,%rsi
+	adcq	$0,%rdx
+	movq	%rsi,584(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+
+	movq	%rdx,%r15
+
+
+
+
+	movq	32(%rcx),%rbx
+
+	movq	40(%rcx),%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	movq	%r11,592(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	addq	%r10,%r12
+	adcq	$0,%rdx
+	movq	%r12,600(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	addq	%r10,%r15
+	adcq	$0,%rdx
+
+	movq	%rdx,%r11
+
+
+
+
+	movq	40(%rcx),%rbx
+
+	movq	%r8,%rax
+	mulq	%rbx
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movq	%r15,608(%rsp)
+
+	movq	%rdx,%r10
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r11
+	adcq	$0,%rdx
+	addq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r11,616(%rsp)
+
+	movq	%rdx,%r12
+
+
+
+
+	movq	%r8,%rbx
+
+	movq	%r9,%rax
+	mulq	%rbx
+	addq	%rax,%r12
+	adcq	$0,%rdx
+	movq	%r12,624(%rsp)
+
+	movq	%rdx,632(%rsp)
+
+
+	movq	528(%rsp),%r10
+	movq	536(%rsp),%r11
+	movq	544(%rsp),%r12
+	movq	552(%rsp),%r13
+	movq	560(%rsp),%r14
+	movq	568(%rsp),%r15
+
+	movq	24(%rcx),%rax
+	mulq	%rax
+	movq	%rax,%rdi
+	movq	%rdx,%r8
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	$0,%r8
+
+	movq	0(%rcx),%rax
+	mulq	%rax
+	movq	%rax,520(%rsp)
+	movq	%rdx,%rbx
+
+	movq	8(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+	movq	%r10,528(%rsp)
+	movq	%r11,536(%rsp)
+
+	movq	16(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbx,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbx
+
+	movq	%r12,544(%rsp)
+	movq	%r13,552(%rsp)
+
+	xorq	%rbp,%rbp
+	addq	%rbx,%r14
+	adcq	%rdi,%r15
+	adcq	$0,%rbp
+
+	movq	%r14,560(%rsp)
+	movq	%r15,568(%rsp)
+
+
+
+
+	movq	576(%rsp),%r10
+	movq	584(%rsp),%r11
+	movq	592(%rsp),%r12
+	movq	600(%rsp),%r13
+	movq	608(%rsp),%r14
+	movq	616(%rsp),%r15
+	movq	624(%rsp),%rdi
+	movq	632(%rsp),%rsi
+
+	movq	%r9,%rax
+	mulq	%rax
+	movq	%rax,%r9
+	movq	%rdx,%rbx
+
+	addq	%r10,%r10
+	adcq	%r11,%r11
+	adcq	%r12,%r12
+	adcq	%r13,%r13
+	adcq	%r14,%r14
+	adcq	%r15,%r15
+	adcq	%rdi,%rdi
+	adcq	%rsi,%rsi
+	adcq	$0,%rbx
+
+	addq	%rbp,%r10
+
+	movq	32(%rcx),%rax
+	mulq	%rax
+
+	addq	%r8,%r10
+	adcq	%rax,%r11
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r10,576(%rsp)
+	movq	%r11,584(%rsp)
+
+	movq	40(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r12
+	adcq	%rax,%r13
+	adcq	$0,%rdx
+
+	movq	%rdx,%rbp
+
+	movq	%r12,592(%rsp)
+	movq	%r13,600(%rsp)
+
+	movq	48(%rcx),%rax
+	mulq	%rax
+
+	addq	%rbp,%r14
+	adcq	%rax,%r15
+	adcq	$0,%rdx
+
+	movq	%r14,608(%rsp)
+	movq	%r15,616(%rsp)
+
+	addq	%rdx,%rdi
+	adcq	%r9,%rsi
+	adcq	$0,%rbx
+
+	movq	%rdi,624(%rsp)
+	movq	%rsi,632(%rsp)
+	movq	%rbx,640(%rsp)
+
+	jmp	mont_reduce
+
+
+
+.globl	mod_exp_512
+.def	mod_exp_512;	.scl 2;	.type 32;	.endef
+mod_exp_512:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_mod_exp_512:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+
+	movq	%rsp,%r8
+	subq	$2688,%rsp
+	andq	$-64,%rsp
+
+
+	movq	%r8,0(%rsp)
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rcx,24(%rsp)
+.Lbody:
+
+
+
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rsi),%xmm0
+	movdqu	16(%rsi),%xmm1
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm3
+	movdqa	%xmm4,512(%rsp)
+	movdqa	%xmm4,528(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,544(%rsp)
+	movdqa	%xmm1,560(%rsp)
+	movdqa	%xmm2,576(%rsp)
+	movdqa	%xmm3,592(%rsp)
+
+
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+
+	leaq	384(%rsp),%rbx
+	movq	%rbx,136(%rsp)
+	call	mont_reduce
+
+
+	leaq	448(%rsp),%rcx
+	xorq	%rax,%rax
+	movq	%rax,0(%rcx)
+	movq	%rax,8(%rcx)
+	movq	%rax,24(%rcx)
+	movq	%rax,32(%rcx)
+	movq	%rax,40(%rcx)
+	movq	%rax,48(%rcx)
+	movq	%rax,56(%rcx)
+	movq	%rax,128(%rsp)
+	movq	$1,16(%rcx)
+
+	leaq	640(%rsp),%rbp
+	movq	%rcx,%rsi
+	movq	%rbp,%rdi
+	movq	$8,%rax
+loop_0:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,64(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,128(%rdi)
+	shrq	$16,%rbx
+	movw	%bx,192(%rdi)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rdi),%rdi
+	decq	%rax
+	jnz	loop_0
+	movq	$31,%rax
+	movq	%rax,32(%rsp)
+	movq	%rbp,40(%rsp)
+
+	movq	%rsi,136(%rsp)
+	movq	0(%rsi),%r10
+	movq	8(%rsi),%r11
+	movq	16(%rsi),%r12
+	movq	24(%rsi),%r13
+	movq	32(%rsi),%r14
+	movq	40(%rsi),%r15
+	movq	48(%rsi),%r8
+	movq	56(%rsi),%r9
+init_loop:
+	leaq	384(%rsp),%rdi
+	call	mont_mul_a3b
+	leaq	448(%rsp),%rsi
+	movq	40(%rsp),%rbp
+	addq	$2,%rbp
+	movq	%rbp,40(%rsp)
+	movq	%rsi,%rcx
+	movq	$8,%rax
+loop_1:
+	movq	(%rcx),%rbx
+	movw	%bx,(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,64(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,128(%rbp)
+	shrq	$16,%rbx
+	movw	%bx,192(%rbp)
+	leaq	8(%rcx),%rcx
+	leaq	256(%rbp),%rbp
+	decq	%rax
+	jnz	loop_1
+	movq	32(%rsp),%rax
+	subq	$1,%rax
+	movq	%rax,32(%rsp)
+	jne	init_loop
+
+
+
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm1,80(%rsp)
+	movdqa	%xmm2,96(%rsp)
+	movdqa	%xmm3,112(%rsp)
+
+
+
+
+
+	movl	126(%rsp),%eax
+	movq	%rax,%rdx
+	shrq	$11,%rax
+	andl	$2047,%edx
+	movl	%edx,126(%rsp)
+	leaq	640(%rsp,%rax,2),%rsi
+	movq	8(%rsp),%rdx
+	movq	$4,%rbp
+loop_2:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_2
+	movq	$505,48(%rsp)
+
+	movq	8(%rsp),%rcx
+	movq	%rcx,136(%rsp)
+	movq	0(%rcx),%r10
+	movq	8(%rcx),%r11
+	movq	16(%rcx),%r12
+	movq	24(%rcx),%r13
+	movq	32(%rcx),%r14
+	movq	40(%rcx),%r15
+	movq	48(%rcx),%r8
+	movq	56(%rcx),%r9
+	jmp	sqr_2
+
+main_loop_a3b:
+	call	sqr_reduce
+	call	sqr_reduce
+	call	sqr_reduce
+sqr_2:
+	call	sqr_reduce
+	call	sqr_reduce
+
+
+
+	movq	48(%rsp),%rcx
+	movq	%rcx,%rax
+	shrq	$4,%rax
+	movl	64(%rsp,%rax,2),%edx
+	andq	$15,%rcx
+	shrq	%cl,%rdx
+	andq	$31,%rdx
+
+	leaq	640(%rsp,%rdx,2),%rsi
+	leaq	448(%rsp),%rdx
+	movq	%rdx,%rdi
+	movq	$4,%rbp
+loop_3:
+	movzwq	192(%rsi),%rbx
+	movzwq	448(%rsi),%rax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	128(%rsi),%bx
+	movw	384(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	64(%rsi),%bx
+	movw	320(%rsi),%ax
+	shlq	$16,%rbx
+	shlq	$16,%rax
+	movw	0(%rsi),%bx
+	movw	256(%rsi),%ax
+	movq	%rbx,0(%rdx)
+	movq	%rax,8(%rdx)
+	leaq	512(%rsi),%rsi
+	leaq	16(%rdx),%rdx
+	subq	$1,%rbp
+	jnz	loop_3
+	movq	8(%rsp),%rsi
+	call	mont_mul_a3b
+
+
+
+	movq	48(%rsp),%rcx
+	subq	$5,%rcx
+	movq	%rcx,48(%rsp)
+	jge	main_loop_a3b
+
+
+
+end_main_loop_a3b:
+
+
+	movq	8(%rsp),%rdx
+	pxor	%xmm4,%xmm4
+	movdqu	0(%rdx),%xmm0
+	movdqu	16(%rdx),%xmm1
+	movdqu	32(%rdx),%xmm2
+	movdqu	48(%rdx),%xmm3
+	movdqa	%xmm4,576(%rsp)
+	movdqa	%xmm4,592(%rsp)
+	movdqa	%xmm4,608(%rsp)
+	movdqa	%xmm4,624(%rsp)
+	movdqa	%xmm0,512(%rsp)
+	movdqa	%xmm1,528(%rsp)
+	movdqa	%xmm2,544(%rsp)
+	movdqa	%xmm3,560(%rsp)
+	call	mont_reduce
+
+
+
+	movq	8(%rsp),%rax
+	movq	0(%rax),%r8
+	movq	8(%rax),%r9
+	movq	16(%rax),%r10
+	movq	24(%rax),%r11
+	movq	32(%rax),%r12
+	movq	40(%rax),%r13
+	movq	48(%rax),%r14
+	movq	56(%rax),%r15
+
+
+	movq	24(%rsp),%rbx
+	addq	$512,%rbx
+
+	subq	0(%rbx),%r8
+	sbbq	8(%rbx),%r9
+	sbbq	16(%rbx),%r10
+	sbbq	24(%rbx),%r11
+	sbbq	32(%rbx),%r12
+	sbbq	40(%rbx),%r13
+	sbbq	48(%rbx),%r14
+	sbbq	56(%rbx),%r15
+
+
+	movq	0(%rax),%rsi
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rcx
+	movq	24(%rax),%rdx
+	cmovncq	%r8,%rsi
+	cmovncq	%r9,%rdi
+	cmovncq	%r10,%rcx
+	cmovncq	%r11,%rdx
+	movq	%rsi,0(%rax)
+	movq	%rdi,8(%rax)
+	movq	%rcx,16(%rax)
+	movq	%rdx,24(%rax)
+
+	movq	32(%rax),%rsi
+	movq	40(%rax),%rdi
+	movq	48(%rax),%rcx
+	movq	56(%rax),%rdx
+	cmovncq	%r12,%rsi
+	cmovncq	%r13,%rdi
+	cmovncq	%r14,%rcx
+	cmovncq	%r15,%rdx
+	movq	%rsi,32(%rax)
+	movq	%rdi,40(%rax)
+	movq	%rcx,48(%rax)
+	movq	%rdx,56(%rax)
+
+	movq	0(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbx
+	movq	40(%rsi),%rbp
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_mod_exp_512:
diff --git a/crypto/bn/mont-elf-armv4.S b/crypto/bn/mont-elf-armv4.S
new file mode 100644
index 0000000..136da62
--- /dev/null
+++ b/crypto/bn/mont-elf-armv4.S
@@ -0,0 +1,148 @@
+.text
+
+.global	bn_mul_mont
+.type	bn_mul_mont,%function
+
+.align	2
+bn_mul_mont:
+	stmdb	sp!,{r0,r2}		@ sp points at argument block
+	ldr	r0,[sp,#3*4]		@ load num
+	cmp	r0,#2
+	movlt	r0,#0
+	addlt	sp,sp,#2*4
+	blt	.Labrt
+
+	stmdb	sp!,{r4-r12,lr}		@ save 10 registers
+
+	mov	r0,r0,lsl#2		@ rescale r0 for byte count
+	sub	sp,sp,r0		@ alloca(4*num)
+	sub	sp,sp,#4		@ +extra dword
+	sub	r0,r0,#4		@ "num=num-1"
+	add	r4,r2,r0		@ &bp[num-1]
+
+	add	r0,sp,r0		@ r0 to point at &tp[num-1]
+	ldr	r8,[r0,#14*4]		@ &n0
+	ldr	r2,[r2]		@ bp[0]
+	ldr	r5,[r1],#4		@ ap[0],ap++
+	ldr	r6,[r3],#4		@ np[0],np++
+	ldr	r8,[r8]		@ *n0
+	str	r4,[r0,#15*4]		@ save &bp[num]
+
+	umull	r10,r11,r5,r2	@ ap[0]*bp[0]
+	str	r8,[r0,#14*4]		@ save n0 value
+	mul	r8,r10,r8		@ "tp[0]"*n0
+	mov	r12,#0
+	umlal	r10,r12,r6,r8	@ np[0]*n0+"t[0]"
+	mov	r4,sp
+
+.L1st:
+	ldr	r5,[r1],#4		@ ap[j],ap++
+	mov	r10,r11
+	ldr	r6,[r3],#4		@ np[j],np++
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[j]*bp[0]
+	mov	r14,#0
+	umlal	r12,r14,r6,r8	@ np[j]*n0
+	adds	r12,r12,r10
+	str	r12,[r4],#4		@ tp[j-1]=,tp++
+	adc	r12,r14,#0
+	cmp	r4,r0
+	bne	.L1st
+
+	adds	r12,r12,r11
+	ldr	r4,[r0,#13*4]		@ restore bp
+	mov	r14,#0
+	ldr	r8,[r0,#14*4]		@ restore n0
+	adc	r14,r14,#0
+	str	r12,[r0]		@ tp[num-1]=
+	str	r14,[r0,#4]		@ tp[num]=
+
+.Louter:
+	sub	r7,r0,sp		@ "original" r0-1 value
+	sub	r1,r1,r7		@ "rewind" ap to &ap[1]
+	ldr	r2,[r4,#4]!		@ *(++bp)
+	sub	r3,r3,r7		@ "rewind" np to &np[1]
+	ldr	r5,[r1,#-4]		@ ap[0]
+	ldr	r10,[sp]		@ tp[0]
+	ldr	r6,[r3,#-4]		@ np[0]
+	ldr	r7,[sp,#4]		@ tp[1]
+
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[0]*bp[i]+tp[0]
+	str	r4,[r0,#13*4]		@ save bp
+	mul	r8,r10,r8
+	mov	r12,#0
+	umlal	r10,r12,r6,r8	@ np[0]*n0+"tp[0]"
+	mov	r4,sp
+
+.Linner:
+	ldr	r5,[r1],#4		@ ap[j],ap++
+	adds	r10,r11,r7		@ +=tp[j]
+	ldr	r6,[r3],#4		@ np[j],np++
+	mov	r11,#0
+	umlal	r10,r11,r5,r2	@ ap[j]*bp[i]
+	mov	r14,#0
+	umlal	r12,r14,r6,r8	@ np[j]*n0
+	adc	r11,r11,#0
+	ldr	r7,[r4,#8]		@ tp[j+1]
+	adds	r12,r12,r10
+	str	r12,[r4],#4		@ tp[j-1]=,tp++
+	adc	r12,r14,#0
+	cmp	r4,r0
+	bne	.Linner
+
+	adds	r12,r12,r11
+	mov	r14,#0
+	ldr	r4,[r0,#13*4]		@ restore bp
+	adc	r14,r14,#0
+	ldr	r8,[r0,#14*4]		@ restore n0
+	adds	r12,r12,r7
+	ldr	r7,[r0,#15*4]		@ restore &bp[num]
+	adc	r14,r14,#0
+	str	r12,[r0]		@ tp[num-1]=
+	str	r14,[r0,#4]		@ tp[num]=
+
+	cmp	r4,r7
+	bne	.Louter
+
+	ldr	r2,[r0,#12*4]		@ pull rp
+	add	r0,r0,#4		@ r0 to point at &tp[num]
+	sub	r5,r0,sp		@ "original" num value
+	mov	r4,sp			@ "rewind" r4
+	mov	r1,r4			@ "borrow" r1
+	sub	r3,r3,r5		@ "rewind" r3 to &np[0]
+
+	subs	r7,r7,r7		@ "clear" carry flag
+.Lsub:	ldr	r7,[r4],#4
+	ldr	r6,[r3],#4
+	sbcs	r7,r7,r6		@ tp[j]-np[j]
+	str	r7,[r2],#4		@ rp[j]=
+	teq	r4,r0		@ preserve carry
+	bne	.Lsub
+	sbcs	r14,r14,#0		@ upmost carry
+	mov	r4,sp			@ "rewind" r4
+	sub	r2,r2,r5		@ "rewind" r2
+
+	and	r1,r4,r14
+	bic	r3,r2,r14
+	orr	r1,r1,r3		@ ap=borrow?tp:rp
+
+.Lcopy:	ldr	r7,[r1],#4		@ copy or in-place refresh
+	str	sp,[r4],#4		@ zap tp
+	str	r7,[r2],#4
+	cmp	r4,r0
+	bne	.Lcopy
+
+	add	sp,r0,#4		@ skip over tp[num+1]
+	ldmia	sp!,{r4-r12,lr}		@ restore registers
+	add	sp,sp,#2*4		@ skip over {r0,r2}
+	mov	r0,#1
+.Labrt:	tst	lr,#1
+	moveq	pc,lr			@ be binary compatible with V4, yet
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+.size	bn_mul_mont,.-bn_mul_mont
+.asciz	"Montgomery multiplication for ARMv4, CRYPTOGAMS by "
+.align	2
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/mont-elf-x86_64.S b/crypto/bn/mont-elf-x86_64.S
new file mode 100644
index 0000000..7847a19
--- /dev/null
+++ b/crypto/bn/mont-elf-x86_64.S
@@ -0,0 +1,1379 @@
+#include "x86_arch.h"
+.text	
+
+.globl	bn_mul_mont
+.type	bn_mul_mont,@function
+.align	16
+bn_mul_mont:
+	endbr64
+	testl	$3,%r9d
+	jnz	.Lmul_enter
+	cmpl	$8,%r9d
+	jb	.Lmul_enter
+	cmpq	%rsi,%rdx
+	jne	.Lmul4x_enter
+	jmp	.Lsqr4x_enter
+
+.align	16
+.Lmul_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	2(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+.Lmul_body:
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.L1st_enter
+
+.align	16
+.L1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.L1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.L1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	.Louter
+.align	16
+.Louter:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.Linner_enter
+
+.align	16
+.Linner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.Linner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.Linner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	.Louter
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	.Lsub
+.align	16
+.Lsub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	.Lsub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.align	16
+.Lcopy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	.Lcopy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul_epilogue:
+	retq
+.size	bn_mul_mont,.-bn_mul_mont
+.type	bn_mul4x_mont,@function
+.align	16
+bn_mul4x_mont:
+.Lmul4x_enter:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	4(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+.Lmul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.L1st4x
+.align	16
+.L1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.L1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.align	4
+.Louter4x:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.Linner4x
+.align	16
+.Linner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.Linner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	.Louter4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	.Lsub4x
+.align	16
+.Lsub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	.Lsub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lcopy4x
+.align	16
+.Lcopy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	.Lcopy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul4x_epilogue:
+	retq
+.size	bn_mul4x_mont,.-bn_mul4x_mont
+.type	bn_sqr4x_mont,@function
+.align	16
+bn_sqr4x_mont:
+.Lsqr4x_enter:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	shll	$3,%r9d
+	xorq	%r10,%r10
+	movq	%rsp,%r11
+	subq	%r9,%r10
+	movq	(%r8),%r8
+	leaq	-72(%rsp,%r10,2),%rsp
+	andq	$-1024,%rsp
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdi,32(%rsp)
+	movq	%rcx,40(%rsp)
+	movq	%r8,48(%rsp)
+	movq	%r11,56(%rsp)
+.Lsqr4x_body:
+
+
+
+
+
+
+
+	leaq	32(%r10),%rbp
+	leaq	(%rsi,%r9,1),%rsi
+
+	movq	%r9,%rcx
+
+
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	mulq	%r14
+	movq	%rax,%r10
+	movq	%rbx,%rax
+	movq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	mulq	%r15
+	movq	%rax,%r12
+	movq	%rbx,%rax
+	movq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+	jmp	.Lsqr4x_1st
+
+.align	16
+.Lsqr4x_1st:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,16(%rdi,%rcx,1)
+
+
+	movq	24(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_1st
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	leaq	16(%rbp),%rbp
+	movq	%r12,8(%rdi)
+	jmp	.Lsqr4x_outer
+
+.align	16
+.Lsqr4x_outer:
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	movq	-24(%rdi,%rbp,1),%r10
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	addq	-16(%rdi,%rbp,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+	xorq	%r12,%r12
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	leaq	16(%rcx),%rcx
+	jmp	.Lsqr4x_inner
+
+.align	16
+.Lsqr4x_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	addq	(%rdi,%rcx,1),%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_inner
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	addq	$16,%rbp
+	jnz	.Lsqr4x_outer
+
+
+	movq	-32(%rsi),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi),%rbx
+	movq	%rax,%r15
+
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi)
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi)
+
+	movq	-8(%rsi),%rbx
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	$0,%rdx
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	movq	%rdx,%r13
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi)
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	-16(%rsi),%rax
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	mulq	%rbx
+	addq	$16,%rbp
+	xorq	%r14,%r14
+	subq	%r9,%rbp
+	xorq	%r15,%r15
+
+	addq	%r12,%rax
+	adcq	$0,%rdx
+	movq	%rax,8(%rdi)
+	movq	%rdx,16(%rdi)
+	movq	%r15,24(%rdi)
+
+	movq	-16(%rsi,%rbp,1),%rax
+	leaq	64(%rsp,%r9,2),%rdi
+	xorq	%r10,%r10
+	movq	-24(%rdi,%rbp,2),%r11
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	leaq	16(%rbp),%rbp
+	movq	%r8,-40(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	jmp	.Lsqr4x_shift_n_add
+
+.align	16
+.Lsqr4x_shift_n_add:
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+
+	leaq	(%r14,%r10,2),%r12
+	movq	%r8,-8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	24(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	8(%rsi,%rbp,1),%rax
+	movq	%r12,0(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	32(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	40(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	16(%rsi,%rbp,1),%rax
+	movq	%rbx,16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	movq	%r8,24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	addq	$32,%rbp
+	jnz	.Lsqr4x_shift_n_add
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi),%rax
+	movq	%r12,-32(%rdi)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	mulq	%rax
+	negq	%r15
+	adcq	%rax,%rbx
+	adcq	%rdx,%r8
+	movq	%rbx,-16(%rdi)
+	movq	%r8,-8(%rdi)
+	movq	40(%rsp),%rsi
+	movq	48(%rsp),%r8
+	xorq	%rcx,%rcx
+	movq	%r9,0(%rsp)
+	subq	%r9,%rcx
+	movq	64(%rsp),%r10
+	movq	%r8,%r14
+	leaq	64(%rsp,%r9,2),%rax
+	leaq	64(%rsp,%r9,1),%rdi
+	movq	%rax,8(%rsp)
+	leaq	(%rsi,%r9,1),%rsi
+	xorq	%rbp,%rbp
+
+	movq	0(%rsi,%rcx,1),%rax
+	movq	8(%rsi,%rcx,1),%r9
+	imulq	%r10,%r14
+	movq	%rax,%rbx
+	jmp	.Lsqr4x_mont_outer
+
+.align	16
+.Lsqr4x_mont_outer:
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+	movq	%r8,%r15
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+	imulq	%r11,%r15
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	jmp	.Lsqr4x_mont_inner
+
+.align	16
+.Lsqr4x_mont_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	8(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_mont_inner
+
+	subq	0(%rsp),%rcx
+	movq	%r8,%r14
+
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%r9,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi)
+
+	xorq	%r11,%r11
+	addq	(%rdi),%r10
+	adcq	$0,%r11
+	movq	0(%rsi,%rcx,1),%rbx
+	addq	%rbp,%r10
+	adcq	$0,%r11
+
+	imulq	16(%rdi,%rcx,1),%r14
+	xorq	%r12,%r12
+	movq	8(%rsi,%rcx,1),%r9
+	addq	%r10,%r13
+	movq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi)
+
+	xorq	%rbp,%rbp
+	addq	8(%rdi),%r12
+	adcq	%rbp,%rbp
+	addq	%r11,%r12
+	leaq	16(%rdi),%rdi
+	adcq	$0,%rbp
+	movq	%r12,-8(%rdi)
+	cmpq	8(%rsp),%rdi
+	jb	.Lsqr4x_mont_outer
+
+	movq	0(%rsp),%r9
+	movq	%rbp,(%rdi)
+	movq	64(%rsp,%r9,1),%rax
+	leaq	64(%rsp,%r9,1),%rbx
+	movq	40(%rsp),%rsi
+	shrq	$5,%r9
+	movq	8(%rbx),%rdx
+	xorq	%rbp,%rbp
+
+	movq	32(%rsp),%rdi
+	subq	0(%rsi),%rax
+	movq	16(%rbx),%r10
+	movq	24(%rbx),%r11
+	sbbq	8(%rsi),%rdx
+	leaq	-1(%r9),%rcx
+	jmp	.Lsqr4x_sub
+.align	16
+.Lsqr4x_sub:
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	32(%rbx,%rbp,8),%rax
+	movq	40(%rbx,%rbp,8),%rdx
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+	movq	%r11,24(%rdi,%rbp,8)
+	sbbq	32(%rsi,%rbp,8),%rax
+	movq	48(%rbx,%rbp,8),%r10
+	movq	56(%rbx,%rbp,8),%r11
+	sbbq	40(%rsi,%rbp,8),%rdx
+	leaq	4(%rbp),%rbp
+	decq	%rcx
+	jnz	.Lsqr4x_sub
+
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	32(%rbx,%rbp,8),%rax
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+
+	sbbq	$0,%rax
+	movq	%r11,24(%rdi,%rbp,8)
+	xorq	%rbp,%rbp
+	andq	%rax,%rbx
+	notq	%rax
+	movq	%rdi,%rsi
+	andq	%rax,%rsi
+	leaq	-1(%r9),%rcx
+	orq	%rsi,%rbx
+
+	pxor	%xmm0,%xmm0
+	leaq	64(%rsp,%r9,8),%rsi
+	movdqu	(%rbx),%xmm1
+	leaq	(%rsi,%r9,8),%rsi
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm0,(%rsi)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lsqr4x_copy
+.align	16
+.Lsqr4x_copy:
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqu	32(%rbx,%rbp,1),%xmm1
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,96(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqa	%xmm0,32(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movdqu	%xmm1,32(%rdi,%rbp,1)
+	leaq	32(%rbp),%rbp
+	decq	%rcx
+	jnz	.Lsqr4x_copy
+
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movq	56(%rsp),%rsi
+	movq	$1,%rax
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lsqr4x_epilogue:
+	retq
+.size	bn_sqr4x_mont,.-bn_sqr4x_mont
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/mont-macosx-x86_64.S b/crypto/bn/mont-macosx-x86_64.S
new file mode 100644
index 0000000..7de69d9
--- /dev/null
+++ b/crypto/bn/mont-macosx-x86_64.S
@@ -0,0 +1,1375 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_bn_mul_mont
+
+.p2align	4
+_bn_mul_mont:
+	testl	$3,%r9d
+	jnz	L$mul_enter
+	cmpl	$8,%r9d
+	jb	L$mul_enter
+	cmpq	%rsi,%rdx
+	jne	L$mul4x_enter
+	jmp	L$sqr4x_enter
+
+.p2align	4
+L$mul_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	2(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+L$mul_body:
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	L$1st_enter
+
+.p2align	4
+L$1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+L$1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	L$1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	L$outer
+.p2align	4
+L$outer:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	L$inner_enter
+
+.p2align	4
+L$inner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+L$inner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	L$inner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	L$outer
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	L$sub
+.p2align	4
+L$sub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	L$sub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.p2align	4
+L$copy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	L$copy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$mul_epilogue:
+	retq
+
+
+.p2align	4
+bn_mul4x_mont:
+L$mul4x_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	4(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+L$mul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	L$1st4x
+.p2align	4
+L$1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	L$1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.p2align	2
+L$outer4x:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	L$inner4x
+.p2align	4
+L$inner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	L$inner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	L$outer4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	L$sub4x
+.p2align	4
+L$sub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	L$sub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	L$copy4x
+.p2align	4
+L$copy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	L$copy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$mul4x_epilogue:
+	retq
+
+
+.p2align	4
+bn_sqr4x_mont:
+L$sqr4x_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	shll	$3,%r9d
+	xorq	%r10,%r10
+	movq	%rsp,%r11
+	subq	%r9,%r10
+	movq	(%r8),%r8
+	leaq	-72(%rsp,%r10,2),%rsp
+	andq	$-1024,%rsp
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdi,32(%rsp)
+	movq	%rcx,40(%rsp)
+	movq	%r8,48(%rsp)
+	movq	%r11,56(%rsp)
+L$sqr4x_body:
+
+
+
+
+
+
+
+	leaq	32(%r10),%rbp
+	leaq	(%rsi,%r9,1),%rsi
+
+	movq	%r9,%rcx
+
+
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	mulq	%r14
+	movq	%rax,%r10
+	movq	%rbx,%rax
+	movq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	mulq	%r15
+	movq	%rax,%r12
+	movq	%rbx,%rax
+	movq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+	jmp	L$sqr4x_1st
+
+.p2align	4
+L$sqr4x_1st:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,16(%rdi,%rcx,1)
+
+
+	movq	24(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	L$sqr4x_1st
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	leaq	16(%rbp),%rbp
+	movq	%r12,8(%rdi)
+	jmp	L$sqr4x_outer
+
+.p2align	4
+L$sqr4x_outer:
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	movq	-24(%rdi,%rbp,1),%r10
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	addq	-16(%rdi,%rbp,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+	xorq	%r12,%r12
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	leaq	16(%rcx),%rcx
+	jmp	L$sqr4x_inner
+
+.p2align	4
+L$sqr4x_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	addq	(%rdi,%rcx,1),%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	L$sqr4x_inner
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	addq	$16,%rbp
+	jnz	L$sqr4x_outer
+
+
+	movq	-32(%rsi),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi),%rbx
+	movq	%rax,%r15
+
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi)
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi)
+
+	movq	-8(%rsi),%rbx
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	$0,%rdx
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	movq	%rdx,%r13
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi)
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	-16(%rsi),%rax
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	mulq	%rbx
+	addq	$16,%rbp
+	xorq	%r14,%r14
+	subq	%r9,%rbp
+	xorq	%r15,%r15
+
+	addq	%r12,%rax
+	adcq	$0,%rdx
+	movq	%rax,8(%rdi)
+	movq	%rdx,16(%rdi)
+	movq	%r15,24(%rdi)
+
+	movq	-16(%rsi,%rbp,1),%rax
+	leaq	64(%rsp,%r9,2),%rdi
+	xorq	%r10,%r10
+	movq	-24(%rdi,%rbp,2),%r11
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	leaq	16(%rbp),%rbp
+	movq	%r8,-40(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	jmp	L$sqr4x_shift_n_add
+
+.p2align	4
+L$sqr4x_shift_n_add:
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+
+	leaq	(%r14,%r10,2),%r12
+	movq	%r8,-8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	24(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	8(%rsi,%rbp,1),%rax
+	movq	%r12,0(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	32(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	40(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	16(%rsi,%rbp,1),%rax
+	movq	%rbx,16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	movq	%r8,24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	addq	$32,%rbp
+	jnz	L$sqr4x_shift_n_add
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi),%rax
+	movq	%r12,-32(%rdi)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	mulq	%rax
+	negq	%r15
+	adcq	%rax,%rbx
+	adcq	%rdx,%r8
+	movq	%rbx,-16(%rdi)
+	movq	%r8,-8(%rdi)
+	movq	40(%rsp),%rsi
+	movq	48(%rsp),%r8
+	xorq	%rcx,%rcx
+	movq	%r9,0(%rsp)
+	subq	%r9,%rcx
+	movq	64(%rsp),%r10
+	movq	%r8,%r14
+	leaq	64(%rsp,%r9,2),%rax
+	leaq	64(%rsp,%r9,1),%rdi
+	movq	%rax,8(%rsp)
+	leaq	(%rsi,%r9,1),%rsi
+	xorq	%rbp,%rbp
+
+	movq	0(%rsi,%rcx,1),%rax
+	movq	8(%rsi,%rcx,1),%r9
+	imulq	%r10,%r14
+	movq	%rax,%rbx
+	jmp	L$sqr4x_mont_outer
+
+.p2align	4
+L$sqr4x_mont_outer:
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+	movq	%r8,%r15
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+	imulq	%r11,%r15
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	jmp	L$sqr4x_mont_inner
+
+.p2align	4
+L$sqr4x_mont_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	8(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	cmpq	$0,%rcx
+	jne	L$sqr4x_mont_inner
+
+	subq	0(%rsp),%rcx
+	movq	%r8,%r14
+
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%r9,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi)
+
+	xorq	%r11,%r11
+	addq	(%rdi),%r10
+	adcq	$0,%r11
+	movq	0(%rsi,%rcx,1),%rbx
+	addq	%rbp,%r10
+	adcq	$0,%r11
+
+	imulq	16(%rdi,%rcx,1),%r14
+	xorq	%r12,%r12
+	movq	8(%rsi,%rcx,1),%r9
+	addq	%r10,%r13
+	movq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi)
+
+	xorq	%rbp,%rbp
+	addq	8(%rdi),%r12
+	adcq	%rbp,%rbp
+	addq	%r11,%r12
+	leaq	16(%rdi),%rdi
+	adcq	$0,%rbp
+	movq	%r12,-8(%rdi)
+	cmpq	8(%rsp),%rdi
+	jb	L$sqr4x_mont_outer
+
+	movq	0(%rsp),%r9
+	movq	%rbp,(%rdi)
+	movq	64(%rsp,%r9,1),%rax
+	leaq	64(%rsp,%r9,1),%rbx
+	movq	40(%rsp),%rsi
+	shrq	$5,%r9
+	movq	8(%rbx),%rdx
+	xorq	%rbp,%rbp
+
+	movq	32(%rsp),%rdi
+	subq	0(%rsi),%rax
+	movq	16(%rbx),%r10
+	movq	24(%rbx),%r11
+	sbbq	8(%rsi),%rdx
+	leaq	-1(%r9),%rcx
+	jmp	L$sqr4x_sub
+.p2align	4
+L$sqr4x_sub:
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	32(%rbx,%rbp,8),%rax
+	movq	40(%rbx,%rbp,8),%rdx
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+	movq	%r11,24(%rdi,%rbp,8)
+	sbbq	32(%rsi,%rbp,8),%rax
+	movq	48(%rbx,%rbp,8),%r10
+	movq	56(%rbx,%rbp,8),%r11
+	sbbq	40(%rsi,%rbp,8),%rdx
+	leaq	4(%rbp),%rbp
+	decq	%rcx
+	jnz	L$sqr4x_sub
+
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	32(%rbx,%rbp,8),%rax
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+
+	sbbq	$0,%rax
+	movq	%r11,24(%rdi,%rbp,8)
+	xorq	%rbp,%rbp
+	andq	%rax,%rbx
+	notq	%rax
+	movq	%rdi,%rsi
+	andq	%rax,%rsi
+	leaq	-1(%r9),%rcx
+	orq	%rsi,%rbx
+
+	pxor	%xmm0,%xmm0
+	leaq	64(%rsp,%r9,8),%rsi
+	movdqu	(%rbx),%xmm1
+	leaq	(%rsi,%r9,8),%rsi
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm0,(%rsi)
+	movdqu	%xmm1,(%rdi)
+	jmp	L$sqr4x_copy
+.p2align	4
+L$sqr4x_copy:
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqu	32(%rbx,%rbp,1),%xmm1
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,96(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqa	%xmm0,32(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movdqu	%xmm1,32(%rdi,%rbp,1)
+	leaq	32(%rbp),%rbp
+	decq	%rcx
+	jnz	L$sqr4x_copy
+
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movq	56(%rsp),%rsi
+	movq	$1,%rax
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$sqr4x_epilogue:
+	retq
+
+.byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	4
diff --git a/crypto/bn/mont-masm-x86_64.S b/crypto/bn/mont-masm-x86_64.S
new file mode 100644
index 0000000..ea582ed
--- /dev/null
+++ b/crypto/bn/mont-masm-x86_64.S
@@ -0,0 +1,1496 @@
+; 1 "crypto/bn/mont-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/bn/mont-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/bn/mont-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	bn_mul_mont
+
+ALIGN	16
+bn_mul_mont	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_bn_mul_mont::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	test	r9d,3
+	jnz	$L$mul_enter
+	cmp	r9d,8
+	jb	$L$mul_enter
+	cmp	rdx,rsi
+	jne	$L$mul4x_enter
+	jmp	$L$sqr4x_enter
+
+ALIGN	16
+$L$mul_enter::
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+	mov	r9d,r9d
+	lea	r10,QWORD PTR[2+r9]
+	mov	r11,rsp
+	neg	r10
+	lea	rsp,QWORD PTR[r10*8+rsp]
+	and	rsp,-1024
+
+	mov	QWORD PTR[8+r9*8+rsp],r11
+$L$mul_body::
+	mov	r12,rdx
+	mov	r8,QWORD PTR[r8]
+	mov	rbx,QWORD PTR[r12]
+	mov	rax,QWORD PTR[rsi]
+
+	xor	r14,r14
+	xor	r15,r15
+
+	mov	rbp,r8
+	mul	rbx
+	mov	r10,rax
+	mov	rax,QWORD PTR[rcx]
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	r13,rdx
+
+	lea	r15,QWORD PTR[1+r15]
+	jmp	$L$1st_enter
+
+ALIGN	16
+$L$1st::
+	add	r13,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	r13,r11
+	mov	r11,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+$L$1st_enter::
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	lea	r15,QWORD PTR[1+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	cmp	r15,r9
+	jl	$L$1st
+
+	add	r13,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	r13,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+	mov	r11,r10
+
+	xor	rdx,rdx
+	add	r13,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r9*8+rsp],r13
+	mov	QWORD PTR[r9*8+rsp],rdx
+
+	lea	r14,QWORD PTR[1+r14]
+	jmp	$L$outer
+ALIGN	16
+$L$outer::
+	mov	rbx,QWORD PTR[r14*8+r12]
+	xor	r15,r15
+	mov	rbp,r8
+	mov	r10,QWORD PTR[rsp]
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[rcx]
+	adc	rdx,0
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	r10,QWORD PTR[8+rsp]
+	mov	r13,rdx
+
+	lea	r15,QWORD PTR[1+r15]
+	jmp	$L$inner_enter
+
+ALIGN	16
+$L$inner::
+	add	r13,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	mov	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+$L$inner_enter::
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	add	r10,r11
+	mov	r11,rdx
+	adc	r11,0
+	lea	r15,QWORD PTR[1+r15]
+
+	mul	rbp
+	cmp	r15,r9
+	jl	$L$inner
+
+	add	r13,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	r13,r10
+	mov	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+	xor	rdx,rdx
+	add	r13,r11
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r9*8+rsp],r13
+	mov	QWORD PTR[r9*8+rsp],rdx
+
+	lea	r14,QWORD PTR[1+r14]
+	cmp	r14,r9
+	jl	$L$outer
+
+	xor	r14,r14
+	mov	rax,QWORD PTR[rsp]
+	lea	rsi,QWORD PTR[rsp]
+	mov	r15,r9
+	jmp	$L$sub
+ALIGN	16
+$L$sub::	sbb	rax,QWORD PTR[r14*8+rcx]
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	rax,QWORD PTR[8+r14*8+rsi]
+	lea	r14,QWORD PTR[1+r14]
+	dec	r15
+	jnz	$L$sub
+
+	sbb	rax,0
+	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
+	mov	r15,r9
+	or	rsi,rcx
+ALIGN	16
+$L$copy::
+	mov	rax,QWORD PTR[r14*8+rsi]
+	mov	QWORD PTR[r14*8+rsp],r14
+	mov	QWORD PTR[r14*8+rdi],rax
+	lea	r14,QWORD PTR[1+r14]
+	sub	r15,1
+	jnz	$L$copy
+
+	mov	rsi,QWORD PTR[8+r9*8+rsp]
+	mov	rax,1
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$mul_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_mul_mont::
+bn_mul_mont	ENDP
+
+ALIGN	16
+bn_mul4x_mont	PROC PRIVATE
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_bn_mul4x_mont::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+$L$mul4x_enter::
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+	mov	r9d,r9d
+	lea	r10,QWORD PTR[4+r9]
+	mov	r11,rsp
+	neg	r10
+	lea	rsp,QWORD PTR[r10*8+rsp]
+	and	rsp,-1024
+
+	mov	QWORD PTR[8+r9*8+rsp],r11
+$L$mul4x_body::
+	mov	QWORD PTR[16+r9*8+rsp],rdi
+	mov	r12,rdx
+	mov	r8,QWORD PTR[r8]
+	mov	rbx,QWORD PTR[r12]
+	mov	rax,QWORD PTR[rsi]
+
+	xor	r14,r14
+	xor	r15,r15
+
+	mov	rbp,r8
+	mul	rbx
+	mov	r10,rax
+	mov	rax,QWORD PTR[rcx]
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[16+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	lea	r15,QWORD PTR[4+r15]
+	adc	rdx,0
+	mov	QWORD PTR[rsp],rdi
+	mov	r13,rdx
+	jmp	$L$1st4x
+ALIGN	16
+$L$1st4x::
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[8+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+r15*8+rcx]
+	adc	rdx,0
+	lea	r15,QWORD PTR[4+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-32))+r15*8+rsp],rdi
+	mov	r13,rdx
+	cmp	r15,r9
+	jl	$L$1st4x
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	xor	rdi,rdi
+	add	r13,r10
+	adc	rdi,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	QWORD PTR[r15*8+rsp],rdi
+
+	lea	r14,QWORD PTR[1+r14]
+ALIGN	4
+$L$outer4x::
+	mov	rbx,QWORD PTR[r14*8+r12]
+	xor	r15,r15
+	mov	r10,QWORD PTR[rsp]
+	mov	rbp,r8
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[rcx]
+	adc	rdx,0
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[8+rsp]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[16+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	lea	r15,QWORD PTR[4+r15]
+	adc	rdx,0
+	mov	QWORD PTR[rsp],rdi
+	mov	r13,rdx
+	jmp	$L$inner4x
+ALIGN	16
+$L$inner4x::
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[((-16))+r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[((-8))+r15*8+rsp]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[8+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[8+r15*8+rsp]
+	adc	rdx,0
+	lea	r15,QWORD PTR[4+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-32))+r15*8+rsp],rdi
+	mov	r13,rdx
+	cmp	r15,r9
+	jl	$L$inner4x
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[((-16))+r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[((-8))+r15*8+rsp]
+	adc	rdx,0
+	lea	r14,QWORD PTR[1+r14]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	xor	rdi,rdi
+	add	r13,r10
+	adc	rdi,0
+	add	r13,QWORD PTR[r9*8+rsp]
+	adc	rdi,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	QWORD PTR[r15*8+rsp],rdi
+
+	cmp	r14,r9
+	jl	$L$outer4x
+	mov	rdi,QWORD PTR[16+r9*8+rsp]
+	mov	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+	mov	rdx,QWORD PTR[8+rsp]
+	shr	r9,2
+	lea	rsi,QWORD PTR[rsp]
+	xor	r14,r14
+
+	sub	rax,QWORD PTR[rcx]
+	mov	rbx,QWORD PTR[16+rsi]
+	mov	rbp,QWORD PTR[24+rsi]
+	sbb	rdx,QWORD PTR[8+rcx]
+	lea	r15,QWORD PTR[((-1))+r9]
+	jmp	$L$sub4x
+ALIGN	16
+$L$sub4x::
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	QWORD PTR[8+r14*8+rdi],rdx
+	sbb	rbx,QWORD PTR[16+r14*8+rcx]
+	mov	rax,QWORD PTR[32+r14*8+rsi]
+	mov	rdx,QWORD PTR[40+r14*8+rsi]
+	sbb	rbp,QWORD PTR[24+r14*8+rcx]
+	mov	QWORD PTR[16+r14*8+rdi],rbx
+	mov	QWORD PTR[24+r14*8+rdi],rbp
+	sbb	rax,QWORD PTR[32+r14*8+rcx]
+	mov	rbx,QWORD PTR[48+r14*8+rsi]
+	mov	rbp,QWORD PTR[56+r14*8+rsi]
+	sbb	rdx,QWORD PTR[40+r14*8+rcx]
+	lea	r14,QWORD PTR[4+r14]
+	dec	r15
+	jnz	$L$sub4x
+
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	rax,QWORD PTR[32+r14*8+rsi]
+	sbb	rbx,QWORD PTR[16+r14*8+rcx]
+	mov	QWORD PTR[8+r14*8+rdi],rdx
+	sbb	rbp,QWORD PTR[24+r14*8+rcx]
+	mov	QWORD PTR[16+r14*8+rdi],rbx
+
+	sbb	rax,0
+	mov	QWORD PTR[24+r14*8+rdi],rbp
+	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
+	lea	r15,QWORD PTR[((-1))+r9]
+	or	rsi,rcx
+
+	movdqu	xmm1,XMMWORD PTR[rsi]
+	movdqa	XMMWORD PTR[rsp],xmm0
+	movdqu	XMMWORD PTR[rdi],xmm1
+	jmp	$L$copy4x
+ALIGN	16
+$L$copy4x::
+	movdqu	xmm2,XMMWORD PTR[16+r14*1+rsi]
+	movdqu	xmm1,XMMWORD PTR[32+r14*1+rsi]
+	movdqa	XMMWORD PTR[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[16+r14*1+rdi],xmm2
+	movdqa	XMMWORD PTR[32+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[32+r14*1+rdi],xmm1
+	lea	r14,QWORD PTR[32+r14]
+	dec	r15
+	jnz	$L$copy4x
+
+	shl	r9,2
+	movdqu	xmm2,XMMWORD PTR[16+r14*1+rsi]
+	movdqa	XMMWORD PTR[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[16+r14*1+rdi],xmm2
+	mov	rsi,QWORD PTR[8+r9*8+rsp]
+	mov	rax,1
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$mul4x_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_mul4x_mont::
+bn_mul4x_mont	ENDP
+
+ALIGN	16
+bn_sqr4x_mont	PROC PRIVATE
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_bn_sqr4x_mont::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+$L$sqr4x_enter::
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+	shl	r9d,3
+	xor	r10,r10
+	mov	r11,rsp
+	sub	r10,r9
+	mov	r8,QWORD PTR[r8]
+	lea	rsp,QWORD PTR[((-72))+r10*2+rsp]
+	and	rsp,-1024
+
+
+
+
+
+
+
+
+
+
+
+	mov	QWORD PTR[32+rsp],rdi
+	mov	QWORD PTR[40+rsp],rcx
+	mov	QWORD PTR[48+rsp],r8
+	mov	QWORD PTR[56+rsp],r11
+$L$sqr4x_body::
+
+
+
+
+
+
+
+	lea	rbp,QWORD PTR[32+r10]
+	lea	rsi,QWORD PTR[r9*1+rsi]
+
+	mov	rcx,r9
+
+
+	mov	r14,QWORD PTR[((-32))+rbp*1+rsi]
+	lea	rdi,QWORD PTR[64+r9*2+rsp]
+	mov	rax,QWORD PTR[((-24))+rbp*1+rsi]
+	lea	rdi,QWORD PTR[((-32))+rbp*1+rdi]
+	mov	rbx,QWORD PTR[((-16))+rbp*1+rsi]
+	mov	r15,rax
+
+	mul	r14
+	mov	r10,rax
+	mov	rax,rbx
+	mov	r11,rdx
+	mov	QWORD PTR[((-24))+rbp*1+rdi],r10
+
+	xor	r10,r10
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[((-16))+rbp*1+rdi],r11
+
+	lea	rcx,QWORD PTR[((-16))+rbp]
+
+
+	mov	rbx,QWORD PTR[8+rcx*1+rsi]
+	mul	r15
+	mov	r12,rax
+	mov	rax,rbx
+	mov	r13,rdx
+
+	xor	r11,r11
+	add	r10,r12
+	lea	rcx,QWORD PTR[16+rcx]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-8))+rcx*1+rdi],r10
+	jmp	$L$sqr4x_1st
+
+ALIGN	16
+$L$sqr4x_1st::
+	mov	rbx,QWORD PTR[rcx*1+rsi]
+	xor	r12,r12
+	mul	r15
+	add	r13,rax
+	mov	rax,rbx
+	adc	r12,rdx
+
+	xor	r10,r10
+	add	r11,r13
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[rcx*1+rdi],r11
+
+
+	mov	rbx,QWORD PTR[8+rcx*1+rsi]
+	xor	r13,r13
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+
+	xor	r11,r11
+	add	r10,r12
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[8+rcx*1+rdi],r10
+
+	mov	rbx,QWORD PTR[16+rcx*1+rsi]
+	xor	r12,r12
+	mul	r15
+	add	r13,rax
+	mov	rax,rbx
+	adc	r12,rdx
+
+	xor	r10,r10
+	add	r11,r13
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[16+rcx*1+rdi],r11
+
+
+	mov	rbx,QWORD PTR[24+rcx*1+rsi]
+	xor	r13,r13
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+
+	xor	r11,r11
+	add	r10,r12
+	lea	rcx,QWORD PTR[32+rcx]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-8))+rcx*1+rdi],r10
+
+	cmp	rcx,0
+	jne	$L$sqr4x_1st
+
+	xor	r12,r12
+	add	r13,r11
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	adc	r12,rdx
+
+	mov	QWORD PTR[rdi],r13
+	lea	rbp,QWORD PTR[16+rbp]
+	mov	QWORD PTR[8+rdi],r12
+	jmp	$L$sqr4x_outer
+
+ALIGN	16
+$L$sqr4x_outer::
+	mov	r14,QWORD PTR[((-32))+rbp*1+rsi]
+	lea	rdi,QWORD PTR[64+r9*2+rsp]
+	mov	rax,QWORD PTR[((-24))+rbp*1+rsi]
+	lea	rdi,QWORD PTR[((-32))+rbp*1+rdi]
+	mov	rbx,QWORD PTR[((-16))+rbp*1+rsi]
+	mov	r15,rax
+
+	mov	r10,QWORD PTR[((-24))+rbp*1+rdi]
+	xor	r11,r11
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-24))+rbp*1+rdi],r10
+
+	xor	r10,r10
+	add	r11,QWORD PTR[((-16))+rbp*1+rdi]
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[((-16))+rbp*1+rdi],r11
+
+	lea	rcx,QWORD PTR[((-16))+rbp]
+	xor	r12,r12
+
+
+	mov	rbx,QWORD PTR[8+rcx*1+rsi]
+	xor	r13,r13
+	add	r12,QWORD PTR[8+rcx*1+rdi]
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+
+	xor	r11,r11
+	add	r10,r12
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[8+rcx*1+rdi],r10
+
+	lea	rcx,QWORD PTR[16+rcx]
+	jmp	$L$sqr4x_inner
+
+ALIGN	16
+$L$sqr4x_inner::
+	mov	rbx,QWORD PTR[rcx*1+rsi]
+	xor	r12,r12
+	add	r13,QWORD PTR[rcx*1+rdi]
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,rbx
+	adc	r12,rdx
+
+	xor	r10,r10
+	add	r11,r13
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[rcx*1+rdi],r11
+
+	mov	rbx,QWORD PTR[8+rcx*1+rsi]
+	xor	r13,r13
+	add	r12,QWORD PTR[8+rcx*1+rdi]
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+
+	xor	r11,r11
+	add	r10,r12
+	lea	rcx,QWORD PTR[16+rcx]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-8))+rcx*1+rdi],r10
+
+	cmp	rcx,0
+	jne	$L$sqr4x_inner
+
+	xor	r12,r12
+	add	r13,r11
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	adc	r12,rdx
+
+	mov	QWORD PTR[rdi],r13
+	mov	QWORD PTR[8+rdi],r12
+
+	add	rbp,16
+	jnz	$L$sqr4x_outer
+
+
+	mov	r14,QWORD PTR[((-32))+rsi]
+	lea	rdi,QWORD PTR[64+r9*2+rsp]
+	mov	rax,QWORD PTR[((-24))+rsi]
+	lea	rdi,QWORD PTR[((-32))+rbp*1+rdi]
+	mov	rbx,QWORD PTR[((-16))+rsi]
+	mov	r15,rax
+
+	xor	r11,r11
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-24))+rdi],r10
+
+	xor	r10,r10
+	add	r11,r13
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	mov	QWORD PTR[((-16))+rdi],r11
+
+	mov	rbx,QWORD PTR[((-8))+rsi]
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	rdx,0
+
+	xor	r11,r11
+	add	r10,r12
+	mov	r13,rdx
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,rbx
+	adc	r11,rdx
+	mov	QWORD PTR[((-8))+rdi],r10
+
+	xor	r12,r12
+	add	r13,r11
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,QWORD PTR[((-16))+rsi]
+	adc	r12,rdx
+
+	mov	QWORD PTR[rdi],r13
+	mov	QWORD PTR[8+rdi],r12
+
+	mul	rbx
+	add	rbp,16
+	xor	r14,r14
+	sub	rbp,r9
+	xor	r15,r15
+
+	add	rax,r12
+	adc	rdx,0
+	mov	QWORD PTR[8+rdi],rax
+	mov	QWORD PTR[16+rdi],rdx
+	mov	QWORD PTR[24+rdi],r15
+
+	mov	rax,QWORD PTR[((-16))+rbp*1+rsi]
+	lea	rdi,QWORD PTR[64+r9*2+rsp]
+	xor	r10,r10
+	mov	r11,QWORD PTR[((-24))+rbp*2+rdi]
+
+	lea	r12,QWORD PTR[r10*2+r14]
+	shr	r10,63
+	lea	r13,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r13,r10
+	mov	r10,QWORD PTR[((-16))+rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[((-8))+rbp*2+rdi]
+	adc	r12,rax
+	mov	rax,QWORD PTR[((-8))+rbp*1+rsi]
+	mov	QWORD PTR[((-32))+rbp*2+rdi],r12
+	adc	r13,rdx
+
+	lea	rbx,QWORD PTR[r10*2+r14]
+	mov	QWORD PTR[((-24))+rbp*2+rdi],r13
+	sbb	r15,r15
+	shr	r10,63
+	lea	r8,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r8,r10
+	mov	r10,QWORD PTR[rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[8+rbp*2+rdi]
+	adc	rbx,rax
+	mov	rax,QWORD PTR[rbp*1+rsi]
+	mov	QWORD PTR[((-16))+rbp*2+rdi],rbx
+	adc	r8,rdx
+	lea	rbp,QWORD PTR[16+rbp]
+	mov	QWORD PTR[((-40))+rbp*2+rdi],r8
+	sbb	r15,r15
+	jmp	$L$sqr4x_shift_n_add
+
+ALIGN	16
+$L$sqr4x_shift_n_add::
+	lea	r12,QWORD PTR[r10*2+r14]
+	shr	r10,63
+	lea	r13,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r13,r10
+	mov	r10,QWORD PTR[((-16))+rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[((-8))+rbp*2+rdi]
+	adc	r12,rax
+	mov	rax,QWORD PTR[((-8))+rbp*1+rsi]
+	mov	QWORD PTR[((-32))+rbp*2+rdi],r12
+	adc	r13,rdx
+
+	lea	rbx,QWORD PTR[r10*2+r14]
+	mov	QWORD PTR[((-24))+rbp*2+rdi],r13
+	sbb	r15,r15
+	shr	r10,63
+	lea	r8,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r8,r10
+	mov	r10,QWORD PTR[rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[8+rbp*2+rdi]
+	adc	rbx,rax
+	mov	rax,QWORD PTR[rbp*1+rsi]
+	mov	QWORD PTR[((-16))+rbp*2+rdi],rbx
+	adc	r8,rdx
+
+	lea	r12,QWORD PTR[r10*2+r14]
+	mov	QWORD PTR[((-8))+rbp*2+rdi],r8
+	sbb	r15,r15
+	shr	r10,63
+	lea	r13,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r13,r10
+	mov	r10,QWORD PTR[16+rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[24+rbp*2+rdi]
+	adc	r12,rax
+	mov	rax,QWORD PTR[8+rbp*1+rsi]
+	mov	QWORD PTR[rbp*2+rdi],r12
+	adc	r13,rdx
+
+	lea	rbx,QWORD PTR[r10*2+r14]
+	mov	QWORD PTR[8+rbp*2+rdi],r13
+	sbb	r15,r15
+	shr	r10,63
+	lea	r8,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r8,r10
+	mov	r10,QWORD PTR[32+rbp*2+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[40+rbp*2+rdi]
+	adc	rbx,rax
+	mov	rax,QWORD PTR[16+rbp*1+rsi]
+	mov	QWORD PTR[16+rbp*2+rdi],rbx
+	adc	r8,rdx
+	mov	QWORD PTR[24+rbp*2+rdi],r8
+	sbb	r15,r15
+	add	rbp,32
+	jnz	$L$sqr4x_shift_n_add
+
+	lea	r12,QWORD PTR[r10*2+r14]
+	shr	r10,63
+	lea	r13,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r13,r10
+	mov	r10,QWORD PTR[((-16))+rdi]
+	mov	r14,r11
+	mul	rax
+	neg	r15
+	mov	r11,QWORD PTR[((-8))+rdi]
+	adc	r12,rax
+	mov	rax,QWORD PTR[((-8))+rsi]
+	mov	QWORD PTR[((-32))+rdi],r12
+	adc	r13,rdx
+
+	lea	rbx,QWORD PTR[r10*2+r14]
+	mov	QWORD PTR[((-24))+rdi],r13
+	sbb	r15,r15
+	shr	r10,63
+	lea	r8,QWORD PTR[r11*2+rcx]
+	shr	r11,63
+	or	r8,r10
+	mul	rax
+	neg	r15
+	adc	rbx,rax
+	adc	r8,rdx
+	mov	QWORD PTR[((-16))+rdi],rbx
+	mov	QWORD PTR[((-8))+rdi],r8
+	mov	rsi,QWORD PTR[40+rsp]
+	mov	r8,QWORD PTR[48+rsp]
+	xor	rcx,rcx
+	mov	QWORD PTR[rsp],r9
+	sub	rcx,r9
+	mov	r10,QWORD PTR[64+rsp]
+	mov	r14,r8
+	lea	rax,QWORD PTR[64+r9*2+rsp]
+	lea	rdi,QWORD PTR[64+r9*1+rsp]
+	mov	QWORD PTR[8+rsp],rax
+	lea	rsi,QWORD PTR[r9*1+rsi]
+	xor	rbp,rbp
+
+	mov	rax,QWORD PTR[rcx*1+rsi]
+	mov	r9,QWORD PTR[8+rcx*1+rsi]
+	imul	r14,r10
+	mov	rbx,rax
+	jmp	$L$sqr4x_mont_outer
+
+ALIGN	16
+$L$sqr4x_mont_outer::
+	xor	r11,r11
+	mul	r14
+	add	r10,rax
+	mov	rax,r9
+	adc	r11,rdx
+	mov	r15,r8
+
+	xor	r10,r10
+	add	r11,QWORD PTR[8+rcx*1+rdi]
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+
+	imul	r15,r11
+
+	mov	rbx,QWORD PTR[16+rcx*1+rsi]
+	xor	r13,r13
+	add	r12,r11
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+	mov	QWORD PTR[8+rcx*1+rdi],r12
+
+	xor	r11,r11
+	add	r10,QWORD PTR[16+rcx*1+rdi]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,r9
+	adc	r11,rdx
+
+	mov	r9,QWORD PTR[24+rcx*1+rsi]
+	xor	r12,r12
+	add	r13,r10
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,r9
+	adc	r12,rdx
+	mov	QWORD PTR[16+rcx*1+rdi],r13
+
+	xor	r10,r10
+	add	r11,QWORD PTR[24+rcx*1+rdi]
+	lea	rcx,QWORD PTR[32+rcx]
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	jmp	$L$sqr4x_mont_inner
+
+ALIGN	16
+$L$sqr4x_mont_inner::
+	mov	rbx,QWORD PTR[rcx*1+rsi]
+	xor	r13,r13
+	add	r12,r11
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+	mov	QWORD PTR[((-8))+rcx*1+rdi],r12
+
+	xor	r11,r11
+	add	r10,QWORD PTR[rcx*1+rdi]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,r9
+	adc	r11,rdx
+
+	mov	r9,QWORD PTR[8+rcx*1+rsi]
+	xor	r12,r12
+	add	r13,r10
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,r9
+	adc	r12,rdx
+	mov	QWORD PTR[rcx*1+rdi],r13
+
+	xor	r10,r10
+	add	r11,QWORD PTR[8+rcx*1+rdi]
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+
+
+	mov	rbx,QWORD PTR[16+rcx*1+rsi]
+	xor	r13,r13
+	add	r12,r11
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,rbx
+	adc	r13,rdx
+	mov	QWORD PTR[8+rcx*1+rdi],r12
+
+	xor	r11,r11
+	add	r10,QWORD PTR[16+rcx*1+rdi]
+	adc	r11,0
+	mul	r14
+	add	r10,rax
+	mov	rax,r9
+	adc	r11,rdx
+
+	mov	r9,QWORD PTR[24+rcx*1+rsi]
+	xor	r12,r12
+	add	r13,r10
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,r9
+	adc	r12,rdx
+	mov	QWORD PTR[16+rcx*1+rdi],r13
+
+	xor	r10,r10
+	add	r11,QWORD PTR[24+rcx*1+rdi]
+	lea	rcx,QWORD PTR[32+rcx]
+	adc	r10,0
+	mul	r14
+	add	r11,rax
+	mov	rax,rbx
+	adc	r10,rdx
+	cmp	rcx,0
+	jne	$L$sqr4x_mont_inner
+
+	sub	rcx,QWORD PTR[rsp]
+	mov	r14,r8
+
+	xor	r13,r13
+	add	r12,r11
+	adc	r13,0
+	mul	r15
+	add	r12,rax
+	mov	rax,r9
+	adc	r13,rdx
+	mov	QWORD PTR[((-8))+rdi],r12
+
+	xor	r11,r11
+	add	r10,QWORD PTR[rdi]
+	adc	r11,0
+	mov	rbx,QWORD PTR[rcx*1+rsi]
+	add	r10,rbp
+	adc	r11,0
+
+	imul	r14,QWORD PTR[16+rcx*1+rdi]
+	xor	r12,r12
+	mov	r9,QWORD PTR[8+rcx*1+rsi]
+	add	r13,r10
+	mov	r10,QWORD PTR[16+rcx*1+rdi]
+	adc	r12,0
+	mul	r15
+	add	r13,rax
+	mov	rax,rbx
+	adc	r12,rdx
+	mov	QWORD PTR[rdi],r13
+
+	xor	rbp,rbp
+	add	r12,QWORD PTR[8+rdi]
+	adc	rbp,rbp
+	add	r12,r11
+	lea	rdi,QWORD PTR[16+rdi]
+	adc	rbp,0
+	mov	QWORD PTR[((-8))+rdi],r12
+	cmp	rdi,QWORD PTR[8+rsp]
+	jb	$L$sqr4x_mont_outer
+
+	mov	r9,QWORD PTR[rsp]
+	mov	QWORD PTR[rdi],rbp
+	mov	rax,QWORD PTR[64+r9*1+rsp]
+	lea	rbx,QWORD PTR[64+r9*1+rsp]
+	mov	rsi,QWORD PTR[40+rsp]
+	shr	r9,5
+	mov	rdx,QWORD PTR[8+rbx]
+	xor	rbp,rbp
+
+	mov	rdi,QWORD PTR[32+rsp]
+	sub	rax,QWORD PTR[rsi]
+	mov	r10,QWORD PTR[16+rbx]
+	mov	r11,QWORD PTR[24+rbx]
+	sbb	rdx,QWORD PTR[8+rsi]
+	lea	rcx,QWORD PTR[((-1))+r9]
+	jmp	$L$sqr4x_sub
+ALIGN	16
+$L$sqr4x_sub::
+	mov	QWORD PTR[rbp*8+rdi],rax
+	mov	QWORD PTR[8+rbp*8+rdi],rdx
+	sbb	r10,QWORD PTR[16+rbp*8+rsi]
+	mov	rax,QWORD PTR[32+rbp*8+rbx]
+	mov	rdx,QWORD PTR[40+rbp*8+rbx]
+	sbb	r11,QWORD PTR[24+rbp*8+rsi]
+	mov	QWORD PTR[16+rbp*8+rdi],r10
+	mov	QWORD PTR[24+rbp*8+rdi],r11
+	sbb	rax,QWORD PTR[32+rbp*8+rsi]
+	mov	r10,QWORD PTR[48+rbp*8+rbx]
+	mov	r11,QWORD PTR[56+rbp*8+rbx]
+	sbb	rdx,QWORD PTR[40+rbp*8+rsi]
+	lea	rbp,QWORD PTR[4+rbp]
+	dec	rcx
+	jnz	$L$sqr4x_sub
+
+	mov	QWORD PTR[rbp*8+rdi],rax
+	mov	rax,QWORD PTR[32+rbp*8+rbx]
+	sbb	r10,QWORD PTR[16+rbp*8+rsi]
+	mov	QWORD PTR[8+rbp*8+rdi],rdx
+	sbb	r11,QWORD PTR[24+rbp*8+rsi]
+	mov	QWORD PTR[16+rbp*8+rdi],r10
+
+	sbb	rax,0
+	mov	QWORD PTR[24+rbp*8+rdi],r11
+	xor	rbp,rbp
+	and	rbx,rax
+	not	rax
+	mov	rsi,rdi
+	and	rsi,rax
+	lea	rcx,QWORD PTR[((-1))+r9]
+	or	rbx,rsi
+
+	pxor	xmm0,xmm0
+	lea	rsi,QWORD PTR[64+r9*8+rsp]
+	movdqu	xmm1,XMMWORD PTR[rbx]
+	lea	rsi,QWORD PTR[r9*8+rsi]
+	movdqa	XMMWORD PTR[64+rsp],xmm0
+	movdqa	XMMWORD PTR[rsi],xmm0
+	movdqu	XMMWORD PTR[rdi],xmm1
+	jmp	$L$sqr4x_copy
+ALIGN	16
+$L$sqr4x_copy::
+	movdqu	xmm2,XMMWORD PTR[16+rbp*1+rbx]
+	movdqu	xmm1,XMMWORD PTR[32+rbp*1+rbx]
+	movdqa	XMMWORD PTR[80+rbp*1+rsp],xmm0
+	movdqa	XMMWORD PTR[96+rbp*1+rsp],xmm0
+	movdqa	XMMWORD PTR[16+rbp*1+rsi],xmm0
+	movdqa	XMMWORD PTR[32+rbp*1+rsi],xmm0
+	movdqu	XMMWORD PTR[16+rbp*1+rdi],xmm2
+	movdqu	XMMWORD PTR[32+rbp*1+rdi],xmm1
+	lea	rbp,QWORD PTR[32+rbp]
+	dec	rcx
+	jnz	$L$sqr4x_copy
+
+	movdqu	xmm2,XMMWORD PTR[16+rbp*1+rbx]
+	movdqa	XMMWORD PTR[80+rbp*1+rsp],xmm0
+	movdqa	XMMWORD PTR[16+rbp*1+rsi],xmm0
+	movdqu	XMMWORD PTR[16+rbp*1+rdi],xmm2
+	mov	rsi,QWORD PTR[56+rsp]
+	mov	rax,1
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$sqr4x_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_sqr4x_mont::
+bn_sqr4x_mont	ENDP
+DB	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
+DB	112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56
+DB	54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83
+DB	32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
+DB	115,108,46,111,114,103,62,0
+ALIGN	16
+
+.text$	ENDS
+END
+
diff --git a/crypto/bn/mont-mingw64-x86_64.S b/crypto/bn/mont-mingw64-x86_64.S
new file mode 100644
index 0000000..0185883
--- /dev/null
+++ b/crypto/bn/mont-mingw64-x86_64.S
@@ -0,0 +1,1414 @@
+#include "x86_arch.h"
+.text	
+
+.globl	bn_mul_mont
+.def	bn_mul_mont;	.scl 2;	.type 32;	.endef
+.p2align	4
+bn_mul_mont:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_bn_mul_mont:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	testl	$3,%r9d
+	jnz	.Lmul_enter
+	cmpl	$8,%r9d
+	jb	.Lmul_enter
+	cmpq	%rsi,%rdx
+	jne	.Lmul4x_enter
+	jmp	.Lsqr4x_enter
+
+.p2align	4
+.Lmul_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	2(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+.Lmul_body:
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.L1st_enter
+
+.p2align	4
+.L1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.L1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.L1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	.Louter
+.p2align	4
+.Louter:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.Linner_enter
+
+.p2align	4
+.Linner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.Linner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.Linner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	.Louter
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	.Lsub
+.p2align	4
+.Lsub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	.Lsub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.p2align	4
+.Lcopy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	.Lcopy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_bn_mul_mont:
+.def	bn_mul4x_mont;	.scl 3;	.type 32;	.endef
+.p2align	4
+bn_mul4x_mont:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_bn_mul4x_mont:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+.Lmul4x_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movl	%r9d,%r9d
+	leaq	4(%r9),%r10
+	movq	%rsp,%r11
+	negq	%r10
+	leaq	(%rsp,%r10,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%r11,8(%rsp,%r9,8)
+.Lmul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	movq	%rdx,%r12
+	movq	(%r8),%r8
+	movq	(%r12),%rbx
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.L1st4x
+.p2align	4
+.L1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.L1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.p2align	2
+.Louter4x:
+	movq	(%r12,%r14,8),%rbx
+	xorq	%r15,%r15
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.Linner4x
+.p2align	4
+.Linner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.Linner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	.Louter4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	.Lsub4x
+.p2align	4
+.Lsub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	.Lsub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lcopy4x
+.p2align	4
+.Lcopy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	.Lcopy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul4x_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_bn_mul4x_mont:
+.def	bn_sqr4x_mont;	.scl 3;	.type 32;	.endef
+.p2align	4
+bn_sqr4x_mont:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_bn_sqr4x_mont:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+.Lsqr4x_enter:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	shll	$3,%r9d
+	xorq	%r10,%r10
+	movq	%rsp,%r11
+	subq	%r9,%r10
+	movq	(%r8),%r8
+	leaq	-72(%rsp,%r10,2),%rsp
+	andq	$-1024,%rsp
+
+
+
+
+
+
+
+
+
+
+
+	movq	%rdi,32(%rsp)
+	movq	%rcx,40(%rsp)
+	movq	%r8,48(%rsp)
+	movq	%r11,56(%rsp)
+.Lsqr4x_body:
+
+
+
+
+
+
+
+	leaq	32(%r10),%rbp
+	leaq	(%rsi,%r9,1),%rsi
+
+	movq	%r9,%rcx
+
+
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	mulq	%r14
+	movq	%rax,%r10
+	movq	%rbx,%rax
+	movq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	mulq	%r15
+	movq	%rax,%r12
+	movq	%rbx,%rax
+	movq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+	jmp	.Lsqr4x_1st
+
+.p2align	4
+.Lsqr4x_1st:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,16(%rdi,%rcx,1)
+
+
+	movq	24(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_1st
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	leaq	16(%rbp),%rbp
+	movq	%r12,8(%rdi)
+	jmp	.Lsqr4x_outer
+
+.p2align	4
+.Lsqr4x_outer:
+	movq	-32(%rsi,%rbp,1),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi,%rbp,1),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi,%rbp,1),%rbx
+	movq	%rax,%r15
+
+	movq	-24(%rdi,%rbp,1),%r10
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi,%rbp,1)
+
+	xorq	%r10,%r10
+	addq	-16(%rdi,%rbp,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi,%rbp,1)
+
+	leaq	-16(%rbp),%rcx
+	xorq	%r12,%r12
+
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,8(%rdi,%rcx,1)
+
+	leaq	16(%rcx),%rcx
+	jmp	.Lsqr4x_inner
+
+.p2align	4
+.Lsqr4x_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r12,%r12
+	addq	(%rdi,%rcx,1),%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,(%rdi,%rcx,1)
+
+	movq	8(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	8(%rdi,%rcx,1),%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	leaq	16(%rcx),%rcx
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi,%rcx,1)
+
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_inner
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	addq	$16,%rbp
+	jnz	.Lsqr4x_outer
+
+
+	movq	-32(%rsi),%r14
+	leaq	64(%rsp,%r9,2),%rdi
+	movq	-24(%rsi),%rax
+	leaq	-32(%rdi,%rbp,1),%rdi
+	movq	-16(%rsi),%rbx
+	movq	%rax,%r15
+
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-24(%rdi)
+
+	xorq	%r10,%r10
+	addq	%r13,%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	movq	%r11,-16(%rdi)
+
+	movq	-8(%rsi),%rbx
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	$0,%rdx
+
+	xorq	%r11,%r11
+	addq	%r12,%r10
+	movq	%rdx,%r13
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%rbx,%rax
+	adcq	%rdx,%r11
+	movq	%r10,-8(%rdi)
+
+	xorq	%r12,%r12
+	addq	%r11,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	-16(%rsi),%rax
+	adcq	%rdx,%r12
+
+	movq	%r13,(%rdi)
+	movq	%r12,8(%rdi)
+
+	mulq	%rbx
+	addq	$16,%rbp
+	xorq	%r14,%r14
+	subq	%r9,%rbp
+	xorq	%r15,%r15
+
+	addq	%r12,%rax
+	adcq	$0,%rdx
+	movq	%rax,8(%rdi)
+	movq	%rdx,16(%rdi)
+	movq	%r15,24(%rdi)
+
+	movq	-16(%rsi,%rbp,1),%rax
+	leaq	64(%rsp,%r9,2),%rdi
+	xorq	%r10,%r10
+	movq	-24(%rdi,%rbp,2),%r11
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	leaq	16(%rbp),%rbp
+	movq	%r8,-40(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	jmp	.Lsqr4x_shift_n_add
+
+.p2align	4
+.Lsqr4x_shift_n_add:
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi,%rbp,1),%rax
+	movq	%r12,-32(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	0(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	8(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	0(%rsi,%rbp,1),%rax
+	movq	%rbx,-16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+
+	leaq	(%r14,%r10,2),%r12
+	movq	%r8,-8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	16(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	24(%rdi,%rbp,2),%r11
+	adcq	%rax,%r12
+	movq	8(%rsi,%rbp,1),%rax
+	movq	%r12,0(%rdi,%rbp,2)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,8(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	movq	32(%rdi,%rbp,2),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	40(%rdi,%rbp,2),%r11
+	adcq	%rax,%rbx
+	movq	16(%rsi,%rbp,1),%rax
+	movq	%rbx,16(%rdi,%rbp,2)
+	adcq	%rdx,%r8
+	movq	%r8,24(%rdi,%rbp,2)
+	sbbq	%r15,%r15
+	addq	$32,%rbp
+	jnz	.Lsqr4x_shift_n_add
+
+	leaq	(%r14,%r10,2),%r12
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r13
+	shrq	$63,%r11
+	orq	%r10,%r13
+	movq	-16(%rdi),%r10
+	movq	%r11,%r14
+	mulq	%rax
+	negq	%r15
+	movq	-8(%rdi),%r11
+	adcq	%rax,%r12
+	movq	-8(%rsi),%rax
+	movq	%r12,-32(%rdi)
+	adcq	%rdx,%r13
+
+	leaq	(%r14,%r10,2),%rbx
+	movq	%r13,-24(%rdi)
+	sbbq	%r15,%r15
+	shrq	$63,%r10
+	leaq	(%rcx,%r11,2),%r8
+	shrq	$63,%r11
+	orq	%r10,%r8
+	mulq	%rax
+	negq	%r15
+	adcq	%rax,%rbx
+	adcq	%rdx,%r8
+	movq	%rbx,-16(%rdi)
+	movq	%r8,-8(%rdi)
+	movq	40(%rsp),%rsi
+	movq	48(%rsp),%r8
+	xorq	%rcx,%rcx
+	movq	%r9,0(%rsp)
+	subq	%r9,%rcx
+	movq	64(%rsp),%r10
+	movq	%r8,%r14
+	leaq	64(%rsp,%r9,2),%rax
+	leaq	64(%rsp,%r9,1),%rdi
+	movq	%rax,8(%rsp)
+	leaq	(%rsi,%r9,1),%rsi
+	xorq	%rbp,%rbp
+
+	movq	0(%rsi,%rcx,1),%rax
+	movq	8(%rsi,%rcx,1),%r9
+	imulq	%r10,%r14
+	movq	%rax,%rbx
+	jmp	.Lsqr4x_mont_outer
+
+.p2align	4
+.Lsqr4x_mont_outer:
+	xorq	%r11,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+	movq	%r8,%r15
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+	imulq	%r11,%r15
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	jmp	.Lsqr4x_mont_inner
+
+.p2align	4
+.Lsqr4x_mont_inner:
+	movq	(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	8(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	8(%rdi,%rcx,1),%r11
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+
+
+	movq	16(%rsi,%rcx,1),%rbx
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%rbx,%rax
+	adcq	%rdx,%r13
+	movq	%r12,8(%rdi,%rcx,1)
+
+	xorq	%r11,%r11
+	addq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r11
+	mulq	%r14
+	addq	%rax,%r10
+	movq	%r9,%rax
+	adcq	%rdx,%r11
+
+	movq	24(%rsi,%rcx,1),%r9
+	xorq	%r12,%r12
+	addq	%r10,%r13
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%r9,%rax
+	adcq	%rdx,%r12
+	movq	%r13,16(%rdi,%rcx,1)
+
+	xorq	%r10,%r10
+	addq	24(%rdi,%rcx,1),%r11
+	leaq	32(%rcx),%rcx
+	adcq	$0,%r10
+	mulq	%r14
+	addq	%rax,%r11
+	movq	%rbx,%rax
+	adcq	%rdx,%r10
+	cmpq	$0,%rcx
+	jne	.Lsqr4x_mont_inner
+
+	subq	0(%rsp),%rcx
+	movq	%r8,%r14
+
+	xorq	%r13,%r13
+	addq	%r11,%r12
+	adcq	$0,%r13
+	mulq	%r15
+	addq	%rax,%r12
+	movq	%r9,%rax
+	adcq	%rdx,%r13
+	movq	%r12,-8(%rdi)
+
+	xorq	%r11,%r11
+	addq	(%rdi),%r10
+	adcq	$0,%r11
+	movq	0(%rsi,%rcx,1),%rbx
+	addq	%rbp,%r10
+	adcq	$0,%r11
+
+	imulq	16(%rdi,%rcx,1),%r14
+	xorq	%r12,%r12
+	movq	8(%rsi,%rcx,1),%r9
+	addq	%r10,%r13
+	movq	16(%rdi,%rcx,1),%r10
+	adcq	$0,%r12
+	mulq	%r15
+	addq	%rax,%r13
+	movq	%rbx,%rax
+	adcq	%rdx,%r12
+	movq	%r13,(%rdi)
+
+	xorq	%rbp,%rbp
+	addq	8(%rdi),%r12
+	adcq	%rbp,%rbp
+	addq	%r11,%r12
+	leaq	16(%rdi),%rdi
+	adcq	$0,%rbp
+	movq	%r12,-8(%rdi)
+	cmpq	8(%rsp),%rdi
+	jb	.Lsqr4x_mont_outer
+
+	movq	0(%rsp),%r9
+	movq	%rbp,(%rdi)
+	movq	64(%rsp,%r9,1),%rax
+	leaq	64(%rsp,%r9,1),%rbx
+	movq	40(%rsp),%rsi
+	shrq	$5,%r9
+	movq	8(%rbx),%rdx
+	xorq	%rbp,%rbp
+
+	movq	32(%rsp),%rdi
+	subq	0(%rsi),%rax
+	movq	16(%rbx),%r10
+	movq	24(%rbx),%r11
+	sbbq	8(%rsi),%rdx
+	leaq	-1(%r9),%rcx
+	jmp	.Lsqr4x_sub
+.p2align	4
+.Lsqr4x_sub:
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	32(%rbx,%rbp,8),%rax
+	movq	40(%rbx,%rbp,8),%rdx
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+	movq	%r11,24(%rdi,%rbp,8)
+	sbbq	32(%rsi,%rbp,8),%rax
+	movq	48(%rbx,%rbp,8),%r10
+	movq	56(%rbx,%rbp,8),%r11
+	sbbq	40(%rsi,%rbp,8),%rdx
+	leaq	4(%rbp),%rbp
+	decq	%rcx
+	jnz	.Lsqr4x_sub
+
+	movq	%rax,0(%rdi,%rbp,8)
+	movq	32(%rbx,%rbp,8),%rax
+	sbbq	16(%rsi,%rbp,8),%r10
+	movq	%rdx,8(%rdi,%rbp,8)
+	sbbq	24(%rsi,%rbp,8),%r11
+	movq	%r10,16(%rdi,%rbp,8)
+
+	sbbq	$0,%rax
+	movq	%r11,24(%rdi,%rbp,8)
+	xorq	%rbp,%rbp
+	andq	%rax,%rbx
+	notq	%rax
+	movq	%rdi,%rsi
+	andq	%rax,%rsi
+	leaq	-1(%r9),%rcx
+	orq	%rsi,%rbx
+
+	pxor	%xmm0,%xmm0
+	leaq	64(%rsp,%r9,8),%rsi
+	movdqu	(%rbx),%xmm1
+	leaq	(%rsi,%r9,8),%rsi
+	movdqa	%xmm0,64(%rsp)
+	movdqa	%xmm0,(%rsi)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lsqr4x_copy
+.p2align	4
+.Lsqr4x_copy:
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqu	32(%rbx,%rbp,1),%xmm1
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,96(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqa	%xmm0,32(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movdqu	%xmm1,32(%rdi,%rbp,1)
+	leaq	32(%rbp),%rbp
+	decq	%rcx
+	jnz	.Lsqr4x_copy
+
+	movdqu	16(%rbx,%rbp,1),%xmm2
+	movdqa	%xmm0,80(%rsp,%rbp,1)
+	movdqa	%xmm0,16(%rsi,%rbp,1)
+	movdqu	%xmm2,16(%rdi,%rbp,1)
+	movq	56(%rsp),%rsi
+	movq	$1,%rax
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lsqr4x_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_bn_sqr4x_mont:
+.byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	4
diff --git a/crypto/bn/mont-mips.S b/crypto/bn/mont-mips.S
new file mode 100644
index 0000000..65f7b22
--- /dev/null
+++ b/crypto/bn/mont-mips.S
@@ -0,0 +1,287 @@
+.text
+
+.set	noat
+.set	noreorder
+
+.align	5
+.globl	bn_mul_mont
+.ent	bn_mul_mont
+bn_mul_mont:
+	lw	$8,16($29)
+	lw	$9,20($29)
+	slt	$1,$9,4
+	bnez	$1,1f
+	li	$2,0
+	slt	$1,$9,17	# on in-order CPU
+	bnez	$1,bn_mul_mont_internal
+	nop
+1:	jr	$31
+	li	$4,0
+.end	bn_mul_mont
+
+.align	5
+.ent	bn_mul_mont_internal
+bn_mul_mont_internal:
+	.frame	$30,14*4,$31
+	.mask	0x40000000|16711680,-4
+	sub $29,14*4
+	sw	$30,(14-1)*4($29)
+	sw	$23,(14-2)*4($29)
+	sw	$22,(14-3)*4($29)
+	sw	$21,(14-4)*4($29)
+	sw	$20,(14-5)*4($29)
+	sw	$19,(14-6)*4($29)
+	sw	$18,(14-7)*4($29)
+	sw	$17,(14-8)*4($29)
+	sw	$16,(14-9)*4($29)
+	move	$30,$29
+
+	.set	reorder
+	lw	$8,0($8)
+	lw	$13,0($6)	# bp[0]
+	lw	$12,0($5)	# ap[0]
+	lw	$14,0($7)	# np[0]
+
+	sub $29,2*4	# place for two extra words
+	sll	$9,2
+	li	$1,-4096
+	sub $29,$9
+	and	$29,$1
+
+	multu	$12,$13
+	lw	$16,4($5)
+	lw	$18,4($7)
+	mflo	$10
+	mfhi	$11
+	multu	$10,$8
+	mflo	$23
+
+	multu	$16,$13
+	mflo	$16
+	mfhi	$17
+
+	multu	$14,$23
+	mflo	$24
+	mfhi	$25
+	multu	$18,$23
+	addu	$24,$10
+	sltu	$1,$24,$10
+	addu	$25,$1
+	mflo	$18
+	mfhi	$19
+
+	move	$15,$29
+	li	$22,2*4
+.align	4
+.L1st:
+	.set	noreorder
+	add $12,$5,$22
+	add $14,$7,$22
+	lw	$12,($12)
+	lw	$14,($14)
+
+	multu	$12,$13
+	addu	$10,$16,$11
+	addu	$24,$18,$25
+	sltu	$1,$10,$11
+	sltu	$2,$24,$25
+	addu	$11,$17,$1
+	addu	$25,$19,$2
+	mflo	$16
+	mfhi	$17
+
+	addu	$24,$10
+	sltu	$1,$24,$10
+	multu	$14,$23
+	addu	$25,$1
+	addu	$22,4
+	sw	$24,($15)
+	sltu	$2,$22,$9
+	mflo	$18
+	mfhi	$19
+
+	bnez	$2,.L1st
+	add $15,4
+	.set	reorder
+
+	addu	$10,$16,$11
+	sltu	$1,$10,$11
+	addu	$11,$17,$1
+
+	addu	$24,$18,$25
+	sltu	$2,$24,$25
+	addu	$25,$19,$2
+	addu	$24,$10
+	sltu	$1,$24,$10
+	addu	$25,$1
+
+	sw	$24,($15)
+
+	addu	$25,$11
+	sltu	$1,$25,$11
+	sw	$25,4($15)
+	sw	$1,2*4($15)
+
+	li	$21,4
+.align	4
+.Louter:
+	add $13,$6,$21
+	lw	$13,($13)
+	lw	$12,($5)
+	lw	$16,4($5)
+	lw	$20,($29)
+
+	multu	$12,$13
+	lw	$14,($7)
+	lw	$18,4($7)
+	mflo	$10
+	mfhi	$11
+	addu	$10,$20
+	multu	$10,$8
+	sltu	$1,$10,$20
+	addu	$11,$1
+	mflo	$23
+
+	multu	$16,$13
+	mflo	$16
+	mfhi	$17
+
+	multu	$14,$23
+	mflo	$24
+	mfhi	$25
+
+	multu	$18,$23
+	addu	$24,$10
+	sltu	$1,$24,$10
+	addu	$25,$1
+	mflo	$18
+	mfhi	$19
+
+	move	$15,$29
+	li	$22,2*4
+	lw	$20,4($15)
+.align	4
+.Linner:
+	.set	noreorder
+	add $12,$5,$22
+	add $14,$7,$22
+	lw	$12,($12)
+	lw	$14,($14)
+
+	multu	$12,$13
+	addu	$10,$16,$11
+	addu	$24,$18,$25
+	sltu	$1,$10,$11
+	sltu	$2,$24,$25
+	addu	$11,$17,$1
+	addu	$25,$19,$2
+	mflo	$16
+	mfhi	$17
+
+	addu	$10,$20
+	addu	$22,4
+	multu	$14,$23
+	sltu	$1,$10,$20
+	addu	$24,$10
+	addu	$11,$1
+	sltu	$2,$24,$10
+	lw	$20,2*4($15)
+	addu	$25,$2
+	sltu	$1,$22,$9
+	mflo	$18
+	mfhi	$19
+	sw	$24,($15)
+	bnez	$1,.Linner
+	add $15,4
+	.set	reorder
+
+	addu	$10,$16,$11
+	sltu	$1,$10,$11
+	addu	$11,$17,$1
+	addu	$10,$20
+	sltu	$2,$10,$20
+	addu	$11,$2
+
+	lw	$20,2*4($15)
+	addu	$24,$18,$25
+	sltu	$1,$24,$25
+	addu	$25,$19,$1
+	addu	$24,$10
+	sltu	$2,$24,$10
+	addu	$25,$2
+	sw	$24,($15)
+
+	addu	$24,$25,$11
+	sltu	$25,$24,$11
+	addu	$24,$20
+	sltu	$1,$24,$20
+	addu	$25,$1
+	sw	$24,4($15)
+	sw	$25,2*4($15)
+
+	addu	$21,4
+	sltu	$2,$21,$9
+	bnez	$2,.Louter
+
+	.set	noreorder
+	add $20,$29,$9	# &tp[num]
+	move	$15,$29
+	move	$5,$29
+	li	$11,0		# clear borrow bit
+
+.align	4
+.Lsub:	lw	$10,($15)
+	lw	$24,($7)
+	add $15,4
+	add $7,4
+	subu	$24,$10,$24	# tp[i]-np[i]
+	sgtu	$1,$24,$10
+	subu	$10,$24,$11
+	sgtu	$11,$10,$24
+	sw	$10,($4)
+	or	$11,$1
+	sltu	$1,$15,$20
+	bnez	$1,.Lsub
+	add $4,4
+
+	subu	$11,$25,$11	# handle upmost overflow bit
+	move	$15,$29
+	sub $4,$9	# restore rp
+	not	$25,$11
+
+	and	$5,$11,$29
+	and	$6,$25,$4
+	or	$5,$5,$6	# ap=borrow?tp:rp
+
+.align	4
+.Lcopy:	lw	$12,($5)
+	add $5,4
+	sw	$0,($15)
+	add $15,4
+	sltu	$1,$15,$20
+	sw	$12,($4)
+	bnez	$1,.Lcopy
+	add $4,4
+
+	li	$4,1
+	li	$2,1
+
+	.set	noreorder
+	move	$29,$30
+	lw	$30,(14-1)*4($29)
+	lw	$23,(14-2)*4($29)
+	lw	$22,(14-3)*4($29)
+	lw	$21,(14-4)*4($29)
+	lw	$20,(14-5)*4($29)
+	lw	$19,(14-6)*4($29)
+	lw	$18,(14-7)*4($29)
+	lw	$17,(14-8)*4($29)
+	lw	$16,(14-9)*4($29)
+	jr	$31
+	add $29,14*4
+.end	bn_mul_mont_internal
+.rdata
+.asciiz	"Montgomery Multiplication for MIPS, CRYPTOGAMS by "
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/mont-mips64.S b/crypto/bn/mont-mips64.S
new file mode 100644
index 0000000..9128895
--- /dev/null
+++ b/crypto/bn/mont-mips64.S
@@ -0,0 +1,285 @@
+.text
+
+.set	noat
+.set	noreorder
+
+.align	5
+.globl	bn_mul_mont
+.ent	bn_mul_mont
+bn_mul_mont:
+	slt	$1,$9,4
+	bnez	$1,1f
+	li	$2,0
+	slt	$1,$9,17	# on in-order CPU
+	bnez	$1,bn_mul_mont_internal
+	nop
+1:	jr	$31
+	li	$4,0
+.end	bn_mul_mont
+
+.align	5
+.ent	bn_mul_mont_internal
+bn_mul_mont_internal:
+	.frame	$30,14*8,$31
+	.mask	0x40000000|16711680,-8
+	dsub $29,14*8
+	sd	$30,(14-1)*8($29)
+	sd	$23,(14-2)*8($29)
+	sd	$22,(14-3)*8($29)
+	sd	$21,(14-4)*8($29)
+	sd	$20,(14-5)*8($29)
+	sd	$19,(14-6)*8($29)
+	sd	$18,(14-7)*8($29)
+	sd	$17,(14-8)*8($29)
+	sd	$16,(14-9)*8($29)
+	move	$30,$29
+
+	.set	reorder
+	ld	$8,0($8)
+	ld	$13,0($6)	# bp[0]
+	ld	$12,0($5)	# ap[0]
+	ld	$14,0($7)	# np[0]
+
+	dsub $29,2*8	# place for two extra words
+	sll	$9,3
+	li	$1,-4096
+	dsub $29,$9
+	and	$29,$1
+
+	dmultu	$12,$13
+	ld	$16,8($5)
+	ld	$18,8($7)
+	mflo	$10
+	mfhi	$11
+	dmultu	$10,$8
+	mflo	$23
+
+	dmultu	$16,$13
+	mflo	$16
+	mfhi	$17
+
+	dmultu	$14,$23
+	mflo	$24
+	mfhi	$25
+	dmultu	$18,$23
+	daddu	$24,$10
+	sltu	$1,$24,$10
+	daddu	$25,$1
+	mflo	$18
+	mfhi	$19
+
+	move	$15,$29
+	li	$22,2*8
+.align	4
+.L1st:
+	.set	noreorder
+	dadd $12,$5,$22
+	dadd $14,$7,$22
+	ld	$12,($12)
+	ld	$14,($14)
+
+	dmultu	$12,$13
+	daddu	$10,$16,$11
+	daddu	$24,$18,$25
+	sltu	$1,$10,$11
+	sltu	$2,$24,$25
+	daddu	$11,$17,$1
+	daddu	$25,$19,$2
+	mflo	$16
+	mfhi	$17
+
+	daddu	$24,$10
+	sltu	$1,$24,$10
+	dmultu	$14,$23
+	daddu	$25,$1
+	addu	$22,8
+	sd	$24,($15)
+	sltu	$2,$22,$9
+	mflo	$18
+	mfhi	$19
+
+	bnez	$2,.L1st
+	dadd $15,8
+	.set	reorder
+
+	daddu	$10,$16,$11
+	sltu	$1,$10,$11
+	daddu	$11,$17,$1
+
+	daddu	$24,$18,$25
+	sltu	$2,$24,$25
+	daddu	$25,$19,$2
+	daddu	$24,$10
+	sltu	$1,$24,$10
+	daddu	$25,$1
+
+	sd	$24,($15)
+
+	daddu	$25,$11
+	sltu	$1,$25,$11
+	sd	$25,8($15)
+	sd	$1,2*8($15)
+
+	li	$21,8
+.align	4
+.Louter:
+	dadd $13,$6,$21
+	ld	$13,($13)
+	ld	$12,($5)
+	ld	$16,8($5)
+	ld	$20,($29)
+
+	dmultu	$12,$13
+	ld	$14,($7)
+	ld	$18,8($7)
+	mflo	$10
+	mfhi	$11
+	daddu	$10,$20
+	dmultu	$10,$8
+	sltu	$1,$10,$20
+	daddu	$11,$1
+	mflo	$23
+
+	dmultu	$16,$13
+	mflo	$16
+	mfhi	$17
+
+	dmultu	$14,$23
+	mflo	$24
+	mfhi	$25
+
+	dmultu	$18,$23
+	daddu	$24,$10
+	sltu	$1,$24,$10
+	daddu	$25,$1
+	mflo	$18
+	mfhi	$19
+
+	move	$15,$29
+	li	$22,2*8
+	ld	$20,8($15)
+.align	4
+.Linner:
+	.set	noreorder
+	dadd $12,$5,$22
+	dadd $14,$7,$22
+	ld	$12,($12)
+	ld	$14,($14)
+
+	dmultu	$12,$13
+	daddu	$10,$16,$11
+	daddu	$24,$18,$25
+	sltu	$1,$10,$11
+	sltu	$2,$24,$25
+	daddu	$11,$17,$1
+	daddu	$25,$19,$2
+	mflo	$16
+	mfhi	$17
+
+	daddu	$10,$20
+	addu	$22,8
+	dmultu	$14,$23
+	sltu	$1,$10,$20
+	daddu	$24,$10
+	daddu	$11,$1
+	sltu	$2,$24,$10
+	ld	$20,2*8($15)
+	daddu	$25,$2
+	sltu	$1,$22,$9
+	mflo	$18
+	mfhi	$19
+	sd	$24,($15)
+	bnez	$1,.Linner
+	dadd $15,8
+	.set	reorder
+
+	daddu	$10,$16,$11
+	sltu	$1,$10,$11
+	daddu	$11,$17,$1
+	daddu	$10,$20
+	sltu	$2,$10,$20
+	daddu	$11,$2
+
+	ld	$20,2*8($15)
+	daddu	$24,$18,$25
+	sltu	$1,$24,$25
+	daddu	$25,$19,$1
+	daddu	$24,$10
+	sltu	$2,$24,$10
+	daddu	$25,$2
+	sd	$24,($15)
+
+	daddu	$24,$25,$11
+	sltu	$25,$24,$11
+	daddu	$24,$20
+	sltu	$1,$24,$20
+	daddu	$25,$1
+	sd	$24,8($15)
+	sd	$25,2*8($15)
+
+	addu	$21,8
+	sltu	$2,$21,$9
+	bnez	$2,.Louter
+
+	.set	noreorder
+	dadd $20,$29,$9	# &tp[num]
+	move	$15,$29
+	move	$5,$29
+	li	$11,0		# clear borrow bit
+
+.align	4
+.Lsub:	ld	$10,($15)
+	ld	$24,($7)
+	dadd $15,8
+	dadd $7,8
+	dsubu	$24,$10,$24	# tp[i]-np[i]
+	sgtu	$1,$24,$10
+	dsubu	$10,$24,$11
+	sgtu	$11,$10,$24
+	sd	$10,($4)
+	or	$11,$1
+	sltu	$1,$15,$20
+	bnez	$1,.Lsub
+	dadd $4,8
+
+	dsubu	$11,$25,$11	# handle upmost overflow bit
+	move	$15,$29
+	dsub $4,$9	# restore rp
+	not	$25,$11
+
+	and	$5,$11,$29
+	and	$6,$25,$4
+	or	$5,$5,$6	# ap=borrow?tp:rp
+
+.align	4
+.Lcopy:	ld	$12,($5)
+	dadd $5,8
+	sd	$0,($15)
+	dadd $15,8
+	sltu	$1,$15,$20
+	sd	$12,($4)
+	bnez	$1,.Lcopy
+	dadd $4,8
+
+	li	$4,1
+	li	$2,1
+
+	.set	noreorder
+	move	$29,$30
+	ld	$30,(14-1)*8($29)
+	ld	$23,(14-2)*8($29)
+	ld	$22,(14-3)*8($29)
+	ld	$21,(14-4)*8($29)
+	ld	$20,(14-5)*8($29)
+	ld	$19,(14-6)*8($29)
+	ld	$18,(14-7)*8($29)
+	ld	$17,(14-8)*8($29)
+	ld	$16,(14-9)*8($29)
+	jr	$31
+	dadd $29,14*8
+.end	bn_mul_mont_internal
+.rdata
+.asciiz	"Montgomery Multiplication for MIPS, CRYPTOGAMS by "
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/mont5-elf-x86_64.S b/crypto/bn/mont5-elf-x86_64.S
new file mode 100644
index 0000000..a3dbbca
--- /dev/null
+++ b/crypto/bn/mont5-elf-x86_64.S
@@ -0,0 +1,1182 @@
+#include "x86_arch.h"
+.text	
+
+.globl	bn_mul_mont_gather5
+.type	bn_mul_mont_gather5,@function
+.align	64
+bn_mul_mont_gather5:
+	endbr64
+	testl	$3,%r9d
+	jnz	.Lmul_enter
+	cmpl	$8,%r9d
+	jb	.Lmul_enter
+	jmp	.Lmul4x_enter
+
+.align	16
+.Lmul_enter:
+	movl	%r9d,%r9d
+	movd	8(%rsp),%xmm5
+	leaq	.Linc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+.Lmul_alloca:
+	movq	%rsp,%rax
+	leaq	2(%r9),%r11
+	negq	%r11
+	leaq	-264(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+.Lmul_body:
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	24-112(%rsp,%r9,8),%r10
+	andq	$-16,%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.L1st_enter
+
+.align	16
+.L1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.L1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.L1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	.Louter
+.align	16
+.Louter:
+	leaq	24+128(%rsp,%r9,8),%rdx
+	andq	$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.Linner_enter
+
+.align	16
+.Linner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.Linner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.Linner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	.Louter
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	.Lsub
+.align	16
+.Lsub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	.Lsub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.align	16
+.Lcopy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	.Lcopy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul_epilogue:
+	retq
+.size	bn_mul_mont_gather5,.-bn_mul_mont_gather5
+.type	bn_mul4x_mont_gather5,@function
+.align	16
+bn_mul4x_mont_gather5:
+	endbr64
+.Lmul4x_enter:
+	movl	%r9d,%r9d
+	movd	8(%rsp),%xmm5
+	leaq	.Linc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+.Lmul4x_alloca:
+	movq	%rsp,%rax
+	leaq	4(%r9),%r11
+	negq	%r11
+	leaq	-256(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+.Lmul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	32-112(%rsp,%r9,8),%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.L1st4x
+.align	16
+.L1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.L1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.align	4
+.Louter4x:
+	leaq	32+128(%rsp,%r9,8),%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	jmp	.Linner4x
+.align	16
+.Linner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-40(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.Linner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	movq	%rdi,-16(%rsp,%r15,8)
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	.Louter4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	.Lsub4x
+.align	16
+.Lsub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	.Lsub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lcopy4x
+.align	16
+.Lcopy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	.Lcopy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul4x_epilogue:
+	retq
+.size	bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
+.globl	bn_scatter5
+.type	bn_scatter5,@function
+.align	16
+bn_scatter5:
+	endbr64
+	cmpq	$0,%rsi
+	jz	.Lscatter_epilogue
+	leaq	(%rdx,%rcx,8),%rdx
+.Lscatter:
+	movq	(%rdi),%rax
+	leaq	8(%rdi),%rdi
+	movq	%rax,(%rdx)
+	leaq	256(%rdx),%rdx
+	subq	$1,%rsi
+	jnz	.Lscatter
+.Lscatter_epilogue:
+	retq
+.size	bn_scatter5,.-bn_scatter5
+
+.globl	bn_gather5
+.type	bn_gather5,@function
+.align	16
+bn_gather5:
+	endbr64
+.LSEH_begin_bn_gather5:
+
+.byte	0x4c,0x8d,0x14,0x24			
+.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00	
+	leaq	.Linc(%rip),%rax
+	andq	$-16,%rsp
+
+	movd	%ecx,%xmm5
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	128(%rdx),%r11
+	leaq	128(%rsp),%rax
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-128(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-112(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-96(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-80(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-48(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-16(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,16(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,48(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,80(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,96(%rax)
+	movdqa	%xmm4,%xmm2
+	movdqa	%xmm3,112(%rax)
+	jmp	.Lgather
+
+.align	32
+.Lgather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r11),%xmm0
+	movdqa	-112(%r11),%xmm1
+	movdqa	-96(%r11),%xmm2
+	pand	-128(%rax),%xmm0
+	movdqa	-80(%r11),%xmm3
+	pand	-112(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r11),%xmm0
+	movdqa	-48(%r11),%xmm1
+	movdqa	-32(%r11),%xmm2
+	pand	-64(%rax),%xmm0
+	movdqa	-16(%r11),%xmm3
+	pand	-48(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	pand	0(%rax),%xmm0
+	movdqa	48(%r11),%xmm3
+	pand	16(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r11),%xmm0
+	movdqa	80(%r11),%xmm1
+	movdqa	96(%r11),%xmm2
+	pand	64(%rax),%xmm0
+	movdqa	112(%r11),%xmm3
+	pand	80(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	leaq	256(%r11),%r11
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	movq	%xmm0,(%rdi)
+	leaq	8(%rdi),%rdi
+	subq	$1,%rsi
+	jnz	.Lgather
+
+	leaq	(%r10),%rsp
+	retq
+.LSEH_end_bn_gather5:
+.size	bn_gather5,.-bn_gather5
+.section	.rodata
+.align	64
+.Linc:
+.long	0,0, 1,1
+.long	2,2, 2,2
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/bn/mont5-macosx-x86_64.S b/crypto/bn/mont5-macosx-x86_64.S
new file mode 100644
index 0000000..039229f
--- /dev/null
+++ b/crypto/bn/mont5-macosx-x86_64.S
@@ -0,0 +1,1174 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_bn_mul_mont_gather5
+
+.p2align	6
+_bn_mul_mont_gather5:
+	testl	$3,%r9d
+	jnz	L$mul_enter
+	cmpl	$8,%r9d
+	jb	L$mul_enter
+	jmp	L$mul4x_enter
+
+.p2align	4
+L$mul_enter:
+	movl	%r9d,%r9d
+	movd	8(%rsp),%xmm5
+	leaq	L$inc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+L$mul_alloca:
+	movq	%rsp,%rax
+	leaq	2(%r9),%r11
+	negq	%r11
+	leaq	-264(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+L$mul_body:
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	24-112(%rsp,%r9,8),%r10
+	andq	$-16,%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	L$1st_enter
+
+.p2align	4
+L$1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+L$1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	L$1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	L$outer
+.p2align	4
+L$outer:
+	leaq	24+128(%rsp,%r9,8),%rdx
+	andq	$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	L$inner_enter
+
+.p2align	4
+L$inner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+L$inner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	L$inner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	L$outer
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	L$sub
+.p2align	4
+L$sub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	L$sub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.p2align	4
+L$copy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	L$copy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$mul_epilogue:
+	retq
+
+
+.p2align	4
+bn_mul4x_mont_gather5:
+L$mul4x_enter:
+	movl	%r9d,%r9d
+	movd	8(%rsp),%xmm5
+	leaq	L$inc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+L$mul4x_alloca:
+	movq	%rsp,%rax
+	leaq	4(%r9),%r11
+	negq	%r11
+	leaq	-256(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+L$mul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	32-112(%rsp,%r9,8),%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	L$1st4x
+.p2align	4
+L$1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	L$1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.p2align	2
+L$outer4x:
+	leaq	32+128(%rsp,%r9,8),%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	jmp	L$inner4x
+.p2align	4
+L$inner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-40(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	L$inner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	movq	%rdi,-16(%rsp,%r15,8)
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	L$outer4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	L$sub4x
+.p2align	4
+L$sub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	L$sub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	L$copy4x
+.p2align	4
+L$copy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	L$copy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$mul4x_epilogue:
+	retq
+
+.globl	_bn_scatter5
+
+.p2align	4
+_bn_scatter5:
+	cmpq	$0,%rsi
+	jz	L$scatter_epilogue
+	leaq	(%rdx,%rcx,8),%rdx
+L$scatter:
+	movq	(%rdi),%rax
+	leaq	8(%rdi),%rdi
+	movq	%rax,(%rdx)
+	leaq	256(%rdx),%rdx
+	subq	$1,%rsi
+	jnz	L$scatter
+L$scatter_epilogue:
+	retq
+
+
+.globl	_bn_gather5
+
+.p2align	4
+_bn_gather5:
+L$SEH_begin_bn_gather5:
+
+.byte	0x4c,0x8d,0x14,0x24			
+.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00	
+	leaq	L$inc(%rip),%rax
+	andq	$-16,%rsp
+
+	movd	%ecx,%xmm5
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	128(%rdx),%r11
+	leaq	128(%rsp),%rax
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-128(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-112(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-96(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-80(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-48(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-16(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,16(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,48(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,80(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,96(%rax)
+	movdqa	%xmm4,%xmm2
+	movdqa	%xmm3,112(%rax)
+	jmp	L$gather
+
+.p2align	5
+L$gather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r11),%xmm0
+	movdqa	-112(%r11),%xmm1
+	movdqa	-96(%r11),%xmm2
+	pand	-128(%rax),%xmm0
+	movdqa	-80(%r11),%xmm3
+	pand	-112(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r11),%xmm0
+	movdqa	-48(%r11),%xmm1
+	movdqa	-32(%r11),%xmm2
+	pand	-64(%rax),%xmm0
+	movdqa	-16(%r11),%xmm3
+	pand	-48(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	pand	0(%rax),%xmm0
+	movdqa	48(%r11),%xmm3
+	pand	16(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r11),%xmm0
+	movdqa	80(%r11),%xmm1
+	movdqa	96(%r11),%xmm2
+	pand	64(%rax),%xmm0
+	movdqa	112(%r11),%xmm3
+	pand	80(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	leaq	256(%r11),%r11
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	movq	%xmm0,(%rdi)
+	leaq	8(%rdi),%rdi
+	subq	$1,%rsi
+	jnz	L$gather
+
+	leaq	(%r10),%rsp
+	retq
+L$SEH_end_bn_gather5:
+
+.p2align	6
+L$inc:
+.long	0,0, 1,1
+.long	2,2, 2,2
+.byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
diff --git a/crypto/bn/mont5-masm-x86_64.S b/crypto/bn/mont5-masm-x86_64.S
new file mode 100644
index 0000000..905e203
--- /dev/null
+++ b/crypto/bn/mont5-masm-x86_64.S
@@ -0,0 +1,1412 @@
+; 1 "crypto/bn/mont5-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/bn/mont5-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/bn/mont5-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	bn_mul_mont_gather5
+
+ALIGN	64
+bn_mul_mont_gather5	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_bn_mul_mont_gather5::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	test	r9d,3
+	jnz	$L$mul_enter
+	cmp	r9d,8
+	jb	$L$mul_enter
+	jmp	$L$mul4x_enter
+
+ALIGN	16
+$L$mul_enter::
+	mov	r9d,r9d
+	movd	xmm5,DWORD PTR[56+rsp]
+	lea	r10,QWORD PTR[$L$inc]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+$L$mul_alloca::
+	mov	rax,rsp
+	lea	r11,QWORD PTR[2+r9]
+	neg	r11
+	lea	rsp,QWORD PTR[((-264))+r11*8+rsp]
+	and	rsp,-1024
+
+	mov	QWORD PTR[8+r9*8+rsp],rax
+$L$mul_body::
+	lea	r12,QWORD PTR[128+rdx]
+	movdqa	xmm0,XMMWORD PTR[r10]
+	movdqa	xmm1,XMMWORD PTR[16+r10]
+	lea	r10,QWORD PTR[((24-112))+r9*8+rsp]
+	and	r10,-16
+
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+DB	067h
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[112+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[128+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[144+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[160+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[176+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[192+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[208+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[224+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[240+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[256+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[272+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[288+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[304+r10],xmm0
+
+	paddd	xmm3,xmm2
+DB	067h
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[320+r10],xmm1
+
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[336+r10],xmm2
+	pand	xmm0,XMMWORD PTR[64+r12]
+
+	pand	xmm1,XMMWORD PTR[80+r12]
+	pand	xmm2,XMMWORD PTR[96+r12]
+	movdqa	XMMWORD PTR[352+r10],xmm3
+	pand	xmm3,XMMWORD PTR[112+r12]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[((-128))+r12]
+	movdqa	xmm5,XMMWORD PTR[((-112))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-96))+r12]
+	pand	xmm4,XMMWORD PTR[112+r10]
+	movdqa	xmm3,XMMWORD PTR[((-80))+r12]
+	pand	xmm5,XMMWORD PTR[128+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[144+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[160+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[((-64))+r12]
+	movdqa	xmm5,XMMWORD PTR[((-48))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-32))+r12]
+	pand	xmm4,XMMWORD PTR[176+r10]
+	movdqa	xmm3,XMMWORD PTR[((-16))+r12]
+	pand	xmm5,XMMWORD PTR[192+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[208+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[224+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[r12]
+	movdqa	xmm5,XMMWORD PTR[16+r12]
+	movdqa	xmm2,XMMWORD PTR[32+r12]
+	pand	xmm4,XMMWORD PTR[240+r10]
+	movdqa	xmm3,XMMWORD PTR[48+r12]
+	pand	xmm5,XMMWORD PTR[256+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[272+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[288+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	por	xmm0,xmm1
+	pshufd	xmm1,xmm0,04eh
+	por	xmm0,xmm1
+	lea	r12,QWORD PTR[256+r12]
+	movd	rbx,xmm0
+
+	mov	r8,QWORD PTR[r8]
+	mov	rax,QWORD PTR[rsi]
+
+	xor	r14,r14
+	xor	r15,r15
+
+	mov	rbp,r8
+	mul	rbx
+	mov	r10,rax
+	mov	rax,QWORD PTR[rcx]
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	r13,rdx
+
+	lea	r15,QWORD PTR[1+r15]
+	jmp	$L$1st_enter
+
+ALIGN	16
+$L$1st::
+	add	r13,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	r13,r11
+	mov	r11,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+$L$1st_enter::
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	lea	r15,QWORD PTR[1+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	cmp	r15,r9
+	jl	$L$1st
+
+	add	r13,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	r13,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+	mov	r11,r10
+
+	xor	rdx,rdx
+	add	r13,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r9*8+rsp],r13
+	mov	QWORD PTR[r9*8+rsp],rdx
+
+	lea	r14,QWORD PTR[1+r14]
+	jmp	$L$outer
+ALIGN	16
+$L$outer::
+	lea	rdx,QWORD PTR[((24+128))+r9*8+rsp]
+	and	rdx,-16
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD PTR[((-128))+r12]
+	movdqa	xmm1,XMMWORD PTR[((-112))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-96))+r12]
+	movdqa	xmm3,XMMWORD PTR[((-80))+r12]
+	pand	xmm0,XMMWORD PTR[((-128))+rdx]
+	pand	xmm1,XMMWORD PTR[((-112))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-96))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-80))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[((-64))+r12]
+	movdqa	xmm1,XMMWORD PTR[((-48))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-32))+r12]
+	movdqa	xmm3,XMMWORD PTR[((-16))+r12]
+	pand	xmm0,XMMWORD PTR[((-64))+rdx]
+	pand	xmm1,XMMWORD PTR[((-48))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-32))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-16))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[r12]
+	movdqa	xmm1,XMMWORD PTR[16+r12]
+	movdqa	xmm2,XMMWORD PTR[32+r12]
+	movdqa	xmm3,XMMWORD PTR[48+r12]
+	pand	xmm0,XMMWORD PTR[rdx]
+	pand	xmm1,XMMWORD PTR[16+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[32+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[48+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[64+r12]
+	movdqa	xmm1,XMMWORD PTR[80+r12]
+	movdqa	xmm2,XMMWORD PTR[96+r12]
+	movdqa	xmm3,XMMWORD PTR[112+r12]
+	pand	xmm0,XMMWORD PTR[64+rdx]
+	pand	xmm1,XMMWORD PTR[80+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[96+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[112+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	pshufd	xmm0,xmm4,04eh
+	por	xmm0,xmm4
+	lea	r12,QWORD PTR[256+r12]
+	movd	rbx,xmm0
+
+	xor	r15,r15
+	mov	rbp,r8
+	mov	r10,QWORD PTR[rsp]
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[rcx]
+	adc	rdx,0
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	r10,QWORD PTR[8+rsp]
+	mov	r13,rdx
+
+	lea	r15,QWORD PTR[1+r15]
+	jmp	$L$inner_enter
+
+ALIGN	16
+$L$inner::
+	add	r13,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	mov	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+$L$inner_enter::
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	add	r10,r11
+	mov	r11,rdx
+	adc	r11,0
+	lea	r15,QWORD PTR[1+r15]
+
+	mul	rbp
+	cmp	r15,r9
+	jl	$L$inner
+
+	add	r13,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	r13,r10
+	mov	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],r13
+	mov	r13,rdx
+
+	xor	rdx,rdx
+	add	r13,r11
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r9*8+rsp],r13
+	mov	QWORD PTR[r9*8+rsp],rdx
+
+	lea	r14,QWORD PTR[1+r14]
+	cmp	r14,r9
+	jl	$L$outer
+
+	xor	r14,r14
+	mov	rax,QWORD PTR[rsp]
+	lea	rsi,QWORD PTR[rsp]
+	mov	r15,r9
+	jmp	$L$sub
+ALIGN	16
+$L$sub::	sbb	rax,QWORD PTR[r14*8+rcx]
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	rax,QWORD PTR[8+r14*8+rsi]
+	lea	r14,QWORD PTR[1+r14]
+	dec	r15
+	jnz	$L$sub
+
+	sbb	rax,0
+	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
+	mov	r15,r9
+	or	rsi,rcx
+ALIGN	16
+$L$copy::
+	mov	rax,QWORD PTR[r14*8+rsi]
+	mov	QWORD PTR[r14*8+rsp],r14
+	mov	QWORD PTR[r14*8+rdi],rax
+	lea	r14,QWORD PTR[1+r14]
+	sub	r15,1
+	jnz	$L$copy
+
+	mov	rsi,QWORD PTR[8+r9*8+rsp]
+	mov	rax,1
+
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$mul_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_mul_mont_gather5::
+bn_mul_mont_gather5	ENDP
+
+ALIGN	16
+bn_mul4x_mont_gather5	PROC PRIVATE
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_bn_mul4x_mont_gather5::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+$L$mul4x_enter::
+	mov	r9d,r9d
+	movd	xmm5,DWORD PTR[56+rsp]
+	lea	r10,QWORD PTR[$L$inc]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+$L$mul4x_alloca::
+	mov	rax,rsp
+	lea	r11,QWORD PTR[4+r9]
+	neg	r11
+	lea	rsp,QWORD PTR[((-256))+r11*8+rsp]
+	and	rsp,-1024
+
+	mov	QWORD PTR[8+r9*8+rsp],rax
+$L$mul4x_body::
+	mov	QWORD PTR[16+r9*8+rsp],rdi
+	lea	r12,QWORD PTR[128+rdx]
+	movdqa	xmm0,XMMWORD PTR[r10]
+	movdqa	xmm1,XMMWORD PTR[16+r10]
+	lea	r10,QWORD PTR[((32-112))+r9*8+rsp]
+
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+DB	067h,067h
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+DB	067h
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[112+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[128+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[144+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[160+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[176+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[192+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[208+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[224+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[240+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[256+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[272+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[288+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[304+r10],xmm0
+
+	paddd	xmm3,xmm2
+DB	067h
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[320+r10],xmm1
+
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[336+r10],xmm2
+	pand	xmm0,XMMWORD PTR[64+r12]
+
+	pand	xmm1,XMMWORD PTR[80+r12]
+	pand	xmm2,XMMWORD PTR[96+r12]
+	movdqa	XMMWORD PTR[352+r10],xmm3
+	pand	xmm3,XMMWORD PTR[112+r12]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[((-128))+r12]
+	movdqa	xmm5,XMMWORD PTR[((-112))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-96))+r12]
+	pand	xmm4,XMMWORD PTR[112+r10]
+	movdqa	xmm3,XMMWORD PTR[((-80))+r12]
+	pand	xmm5,XMMWORD PTR[128+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[144+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[160+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[((-64))+r12]
+	movdqa	xmm5,XMMWORD PTR[((-48))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-32))+r12]
+	pand	xmm4,XMMWORD PTR[176+r10]
+	movdqa	xmm3,XMMWORD PTR[((-16))+r12]
+	pand	xmm5,XMMWORD PTR[192+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[208+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[224+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD PTR[r12]
+	movdqa	xmm5,XMMWORD PTR[16+r12]
+	movdqa	xmm2,XMMWORD PTR[32+r12]
+	pand	xmm4,XMMWORD PTR[240+r10]
+	movdqa	xmm3,XMMWORD PTR[48+r12]
+	pand	xmm5,XMMWORD PTR[256+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD PTR[272+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD PTR[288+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	por	xmm0,xmm1
+	pshufd	xmm1,xmm0,04eh
+	por	xmm0,xmm1
+	lea	r12,QWORD PTR[256+r12]
+	movd	rbx,xmm0
+
+	mov	r8,QWORD PTR[r8]
+	mov	rax,QWORD PTR[rsi]
+
+	xor	r14,r14
+	xor	r15,r15
+
+	mov	rbp,r8
+	mul	rbx
+	mov	r10,rax
+	mov	rax,QWORD PTR[rcx]
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[16+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	lea	r15,QWORD PTR[4+r15]
+	adc	rdx,0
+	mov	QWORD PTR[rsp],rdi
+	mov	r13,rdx
+	jmp	$L$1st4x
+ALIGN	16
+$L$1st4x::
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[8+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+r15*8+rcx]
+	adc	rdx,0
+	lea	r15,QWORD PTR[4+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-32))+r15*8+rsp],rdi
+	mov	r13,rdx
+	cmp	r15,r9
+	jl	$L$1st4x
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	r13,rdx
+
+	xor	rdi,rdi
+	add	r13,r10
+	adc	rdi,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	QWORD PTR[r15*8+rsp],rdi
+
+	lea	r14,QWORD PTR[1+r14]
+ALIGN	4
+$L$outer4x::
+	lea	rdx,QWORD PTR[((32+128))+r9*8+rsp]
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD PTR[((-128))+r12]
+	movdqa	xmm1,XMMWORD PTR[((-112))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-96))+r12]
+	movdqa	xmm3,XMMWORD PTR[((-80))+r12]
+	pand	xmm0,XMMWORD PTR[((-128))+rdx]
+	pand	xmm1,XMMWORD PTR[((-112))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-96))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-80))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[((-64))+r12]
+	movdqa	xmm1,XMMWORD PTR[((-48))+r12]
+	movdqa	xmm2,XMMWORD PTR[((-32))+r12]
+	movdqa	xmm3,XMMWORD PTR[((-16))+r12]
+	pand	xmm0,XMMWORD PTR[((-64))+rdx]
+	pand	xmm1,XMMWORD PTR[((-48))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-32))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-16))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[r12]
+	movdqa	xmm1,XMMWORD PTR[16+r12]
+	movdqa	xmm2,XMMWORD PTR[32+r12]
+	movdqa	xmm3,XMMWORD PTR[48+r12]
+	pand	xmm0,XMMWORD PTR[rdx]
+	pand	xmm1,XMMWORD PTR[16+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[32+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[48+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[64+r12]
+	movdqa	xmm1,XMMWORD PTR[80+r12]
+	movdqa	xmm2,XMMWORD PTR[96+r12]
+	movdqa	xmm3,XMMWORD PTR[112+r12]
+	pand	xmm0,XMMWORD PTR[64+rdx]
+	pand	xmm1,XMMWORD PTR[80+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[96+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[112+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	pshufd	xmm0,xmm4,04eh
+	por	xmm0,xmm4
+	lea	r12,QWORD PTR[256+r12]
+	movd	rbx,xmm0
+
+	xor	r15,r15
+
+	mov	r10,QWORD PTR[rsp]
+	mov	rbp,r8
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[rcx]
+	adc	rdx,0
+
+	imul	rbp,r10
+	mov	r11,rdx
+
+	mul	rbp
+	add	r10,rax
+	mov	rax,QWORD PTR[8+rsi]
+	adc	rdx,0
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[8+rsp]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[16+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	lea	r15,QWORD PTR[4+r15]
+	adc	rdx,0
+	mov	r13,rdx
+	jmp	$L$inner4x
+ALIGN	16
+$L$inner4x::
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[((-16))+r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-32))+r15*8+rsp],rdi
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[((-8))+r15*8+rsp]
+	adc	rdx,0
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	r13,rdx
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[8+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[8+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[8+r15*8+rsp]
+	adc	rdx,0
+	lea	r15,QWORD PTR[4+r15]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-40))+r15*8+rsp],r13
+	mov	r13,rdx
+	cmp	r15,r9
+	jl	$L$inner4x
+
+	mul	rbx
+	add	r10,rax
+	mov	rax,QWORD PTR[((-16))+r15*8+rcx]
+	adc	rdx,0
+	add	r10,QWORD PTR[((-16))+r15*8+rsp]
+	adc	rdx,0
+	mov	r11,rdx
+
+	mul	rbp
+	add	r13,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rsi]
+	adc	rdx,0
+	add	r13,r10
+	adc	rdx,0
+	mov	QWORD PTR[((-32))+r15*8+rsp],rdi
+	mov	rdi,rdx
+
+	mul	rbx
+	add	r11,rax
+	mov	rax,QWORD PTR[((-8))+r15*8+rcx]
+	adc	rdx,0
+	add	r11,QWORD PTR[((-8))+r15*8+rsp]
+	adc	rdx,0
+	lea	r14,QWORD PTR[1+r14]
+	mov	r10,rdx
+
+	mul	rbp
+	add	rdi,rax
+	mov	rax,QWORD PTR[rsi]
+	adc	rdx,0
+	add	rdi,r11
+	adc	rdx,0
+	mov	QWORD PTR[((-24))+r15*8+rsp],r13
+	mov	r13,rdx
+
+	mov	QWORD PTR[((-16))+r15*8+rsp],rdi
+
+	xor	rdi,rdi
+	add	r13,r10
+	adc	rdi,0
+	add	r13,QWORD PTR[r9*8+rsp]
+	adc	rdi,0
+	mov	QWORD PTR[((-8))+r15*8+rsp],r13
+	mov	QWORD PTR[r15*8+rsp],rdi
+
+	cmp	r14,r9
+	jl	$L$outer4x
+	mov	rdi,QWORD PTR[16+r9*8+rsp]
+	mov	rax,QWORD PTR[rsp]
+	pxor	xmm0,xmm0
+	mov	rdx,QWORD PTR[8+rsp]
+	shr	r9,2
+	lea	rsi,QWORD PTR[rsp]
+	xor	r14,r14
+
+	sub	rax,QWORD PTR[rcx]
+	mov	rbx,QWORD PTR[16+rsi]
+	mov	rbp,QWORD PTR[24+rsi]
+	sbb	rdx,QWORD PTR[8+rcx]
+	lea	r15,QWORD PTR[((-1))+r9]
+	jmp	$L$sub4x
+ALIGN	16
+$L$sub4x::
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	QWORD PTR[8+r14*8+rdi],rdx
+	sbb	rbx,QWORD PTR[16+r14*8+rcx]
+	mov	rax,QWORD PTR[32+r14*8+rsi]
+	mov	rdx,QWORD PTR[40+r14*8+rsi]
+	sbb	rbp,QWORD PTR[24+r14*8+rcx]
+	mov	QWORD PTR[16+r14*8+rdi],rbx
+	mov	QWORD PTR[24+r14*8+rdi],rbp
+	sbb	rax,QWORD PTR[32+r14*8+rcx]
+	mov	rbx,QWORD PTR[48+r14*8+rsi]
+	mov	rbp,QWORD PTR[56+r14*8+rsi]
+	sbb	rdx,QWORD PTR[40+r14*8+rcx]
+	lea	r14,QWORD PTR[4+r14]
+	dec	r15
+	jnz	$L$sub4x
+
+	mov	QWORD PTR[r14*8+rdi],rax
+	mov	rax,QWORD PTR[32+r14*8+rsi]
+	sbb	rbx,QWORD PTR[16+r14*8+rcx]
+	mov	QWORD PTR[8+r14*8+rdi],rdx
+	sbb	rbp,QWORD PTR[24+r14*8+rcx]
+	mov	QWORD PTR[16+r14*8+rdi],rbx
+
+	sbb	rax,0
+	mov	QWORD PTR[24+r14*8+rdi],rbp
+	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
+	lea	r15,QWORD PTR[((-1))+r9]
+	or	rsi,rcx
+
+	movdqu	xmm1,XMMWORD PTR[rsi]
+	movdqa	XMMWORD PTR[rsp],xmm0
+	movdqu	XMMWORD PTR[rdi],xmm1
+	jmp	$L$copy4x
+ALIGN	16
+$L$copy4x::
+	movdqu	xmm2,XMMWORD PTR[16+r14*1+rsi]
+	movdqu	xmm1,XMMWORD PTR[32+r14*1+rsi]
+	movdqa	XMMWORD PTR[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[16+r14*1+rdi],xmm2
+	movdqa	XMMWORD PTR[32+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[32+r14*1+rdi],xmm1
+	lea	r14,QWORD PTR[32+r14]
+	dec	r15
+	jnz	$L$copy4x
+
+	shl	r9,2
+	movdqu	xmm2,XMMWORD PTR[16+r14*1+rsi]
+	movdqa	XMMWORD PTR[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD PTR[16+r14*1+rdi],xmm2
+	mov	rsi,QWORD PTR[8+r9*8+rsp]
+	mov	rax,1
+
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$mul4x_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_mul4x_mont_gather5::
+bn_mul4x_mont_gather5	ENDP
+PUBLIC	bn_scatter5
+
+ALIGN	16
+bn_scatter5	PROC PUBLIC
+	cmp	rdx,0
+	jz	$L$scatter_epilogue
+	lea	r8,QWORD PTR[r9*8+r8]
+$L$scatter::
+	mov	rax,QWORD PTR[rcx]
+	lea	rcx,QWORD PTR[8+rcx]
+	mov	QWORD PTR[r8],rax
+	lea	r8,QWORD PTR[256+r8]
+	sub	rdx,1
+	jnz	$L$scatter
+$L$scatter_epilogue::
+	DB	0F3h,0C3h		;repret
+bn_scatter5	ENDP
+
+PUBLIC	bn_gather5
+
+ALIGN	16
+bn_gather5	PROC PUBLIC
+$L$SEH_begin_bn_gather5::
+
+DB	04ch,08dh,014h,024h			
+DB	048h,081h,0ech,008h,001h,000h,000h	
+	lea	rax,QWORD PTR[$L$inc]
+	and	rsp,-16
+
+	movd	xmm5,r9d
+	movdqa	xmm0,XMMWORD PTR[rax]
+	movdqa	xmm1,XMMWORD PTR[16+rax]
+	lea	r11,QWORD PTR[128+r8]
+	lea	rax,QWORD PTR[128+rsp]
+
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[(-128)+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[(-112)+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[(-96)+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[(-80)+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[(-64)+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[(-48)+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[(-32)+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[(-16)+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[16+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[32+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD PTR[48+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD PTR[64+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD PTR[80+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD PTR[96+rax],xmm2
+	movdqa	xmm2,xmm4
+	movdqa	XMMWORD PTR[112+rax],xmm3
+	jmp	$L$gather
+
+ALIGN	32
+$L$gather::
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD PTR[((-128))+r11]
+	movdqa	xmm1,XMMWORD PTR[((-112))+r11]
+	movdqa	xmm2,XMMWORD PTR[((-96))+r11]
+	pand	xmm0,XMMWORD PTR[((-128))+rax]
+	movdqa	xmm3,XMMWORD PTR[((-80))+r11]
+	pand	xmm1,XMMWORD PTR[((-112))+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-96))+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-80))+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[((-64))+r11]
+	movdqa	xmm1,XMMWORD PTR[((-48))+r11]
+	movdqa	xmm2,XMMWORD PTR[((-32))+r11]
+	pand	xmm0,XMMWORD PTR[((-64))+rax]
+	movdqa	xmm3,XMMWORD PTR[((-16))+r11]
+	pand	xmm1,XMMWORD PTR[((-48))+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[((-32))+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[((-16))+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[r11]
+	movdqa	xmm1,XMMWORD PTR[16+r11]
+	movdqa	xmm2,XMMWORD PTR[32+r11]
+	pand	xmm0,XMMWORD PTR[rax]
+	movdqa	xmm3,XMMWORD PTR[48+r11]
+	pand	xmm1,XMMWORD PTR[16+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[32+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[48+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD PTR[64+r11]
+	movdqa	xmm1,XMMWORD PTR[80+r11]
+	movdqa	xmm2,XMMWORD PTR[96+r11]
+	pand	xmm0,XMMWORD PTR[64+rax]
+	movdqa	xmm3,XMMWORD PTR[112+r11]
+	pand	xmm1,XMMWORD PTR[80+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD PTR[96+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD PTR[112+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	lea	r11,QWORD PTR[256+r11]
+	pshufd	xmm0,xmm4,04eh
+	por	xmm0,xmm4
+	movq	QWORD PTR[rcx],xmm0
+	lea	rcx,QWORD PTR[8+rcx]
+	sub	rdx,1
+	jnz	$L$gather
+
+	lea	rsp,QWORD PTR[r10]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_bn_gather5::
+bn_gather5	ENDP
+ALIGN	64
+$L$inc::
+	DD	0,0,1,1
+	DD	2,2,2,2
+DB	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
+DB	112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115
+DB	99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111
+DB	114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79
+DB	71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111
+DB	112,101,110,115,115,108,46,111,114,103,62,0
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+mul_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	lea	rax,QWORD PTR[48+rax]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[8+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	mov	r10,QWORD PTR[192+r8]
+	mov	rax,QWORD PTR[8+r10*8+rax]
+
+	lea	rax,QWORD PTR[48+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	r13,QWORD PTR[((-32))+rax]
+	mov	r14,QWORD PTR[((-40))+rax]
+	mov	r15,QWORD PTR[((-48))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+	mov	QWORD PTR[232+r8],r14
+	mov	QWORD PTR[240+r8],r15
+
+$L$common_seh_tail::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+mul_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_bn_mul_mont_gather5
+	DD	imagerel $L$SEH_end_bn_mul_mont_gather5
+	DD	imagerel $L$SEH_info_bn_mul_mont_gather5
+
+	DD	imagerel $L$SEH_begin_bn_mul4x_mont_gather5
+	DD	imagerel $L$SEH_end_bn_mul4x_mont_gather5
+	DD	imagerel $L$SEH_info_bn_mul4x_mont_gather5
+
+	DD	imagerel $L$SEH_begin_bn_gather5
+	DD	imagerel $L$SEH_end_bn_gather5
+	DD	imagerel $L$SEH_info_bn_gather5
+
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_bn_mul_mont_gather5::
+DB	9,0,0,0
+	DD	imagerel mul_handler
+	DD	imagerel $L$mul_alloca,imagerel $L$mul_body,imagerel $L$mul_epilogue		
+ALIGN	8
+$L$SEH_info_bn_mul4x_mont_gather5::
+DB	9,0,0,0
+	DD	imagerel mul_handler
+	DD	imagerel $L$mul4x_alloca,imagerel $L$mul4x_body,imagerel $L$mul4x_epilogue	
+ALIGN	8
+$L$SEH_info_bn_gather5::
+DB	001h,00bh,003h,00ah
+DB	00bh,001h,021h,000h	
+DB	004h,0a3h,000h,000h	
+ALIGN	8
+
+.xdata	ENDS
+END
+
diff --git a/crypto/bn/mont5-mingw64-x86_64.S b/crypto/bn/mont5-mingw64-x86_64.S
new file mode 100644
index 0000000..d58e425
--- /dev/null
+++ b/crypto/bn/mont5-mingw64-x86_64.S
@@ -0,0 +1,1329 @@
+#include "x86_arch.h"
+.text	
+
+.globl	bn_mul_mont_gather5
+.def	bn_mul_mont_gather5;	.scl 2;	.type 32;	.endef
+.p2align	6
+bn_mul_mont_gather5:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_bn_mul_mont_gather5:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	testl	$3,%r9d
+	jnz	.Lmul_enter
+	cmpl	$8,%r9d
+	jb	.Lmul_enter
+	jmp	.Lmul4x_enter
+
+.p2align	4
+.Lmul_enter:
+	movl	%r9d,%r9d
+	movd	56(%rsp),%xmm5
+	leaq	.Linc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+.Lmul_alloca:
+	movq	%rsp,%rax
+	leaq	2(%r9),%r11
+	negq	%r11
+	leaq	-264(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+.Lmul_body:
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	24-112(%rsp,%r9,8),%r10
+	andq	$-16,%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.L1st_enter
+
+.p2align	4
+.L1st:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	movq	%r10,%r11
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.L1st_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	1(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.L1st
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+	movq	%r10,%r11
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	jmp	.Louter
+.p2align	4
+.Louter:
+	leaq	24+128(%rsp,%r9,8),%rdx
+	andq	$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+	movq	%r8,%rbp
+	movq	(%rsp),%r10
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	8(%rsp),%r10
+	movq	%rdx,%r13
+
+	leaq	1(%r15),%r15
+	jmp	.Linner_enter
+
+.p2align	4
+.Linner:
+	addq	%rax,%r13
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+.Linner_enter:
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%r10
+	movq	%rdx,%r11
+	adcq	$0,%r11
+	leaq	1(%r15),%r15
+
+	mulq	%rbp
+	cmpq	%r9,%r15
+	jl	.Linner
+
+	addq	%rax,%r13
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	movq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%r13,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdx,%rdx
+	addq	%r11,%r13
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r9,8)
+	movq	%rdx,(%rsp,%r9,8)
+
+	leaq	1(%r14),%r14
+	cmpq	%r9,%r14
+	jl	.Louter
+
+	xorq	%r14,%r14
+	movq	(%rsp),%rax
+	leaq	(%rsp),%rsi
+	movq	%r9,%r15
+	jmp	.Lsub
+.p2align	4
+.Lsub:	sbbq	(%rcx,%r14,8),%rax
+	movq	%rax,(%rdi,%r14,8)
+	movq	8(%rsi,%r14,8),%rax
+	leaq	1(%r14),%r14
+	decq	%r15
+	jnz	.Lsub
+
+	sbbq	$0,%rax
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	movq	%r9,%r15
+	orq	%rcx,%rsi
+.p2align	4
+.Lcopy:
+	movq	(%rsi,%r14,8),%rax
+	movq	%r14,(%rsp,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
+	leaq	1(%r14),%r14
+	subq	$1,%r15
+	jnz	.Lcopy
+
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_bn_mul_mont_gather5:
+.def	bn_mul4x_mont_gather5;	.scl 3;	.type 32;	.endef
+.p2align	4
+bn_mul4x_mont_gather5:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_bn_mul4x_mont_gather5:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+.Lmul4x_enter:
+	movl	%r9d,%r9d
+	movd	56(%rsp),%xmm5
+	leaq	.Linc(%rip),%r10
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+.Lmul4x_alloca:
+	movq	%rsp,%rax
+	leaq	4(%r9),%r11
+	negq	%r11
+	leaq	-256(%rsp,%r11,8),%rsp
+	andq	$-1024,%rsp
+
+	movq	%rax,8(%rsp,%r9,8)
+.Lmul4x_body:
+	movq	%rdi,16(%rsp,%r9,8)
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	32-112(%rsp,%r9,8),%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$78,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	movq	(%r8),%r8
+	movq	(%rsi),%rax
+
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+
+	movq	%r8,%rbp
+	mulq	%rbx
+	movq	%rax,%r10
+	movq	(%rcx),%rax
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdi,(%rsp)
+	movq	%rdx,%r13
+	jmp	.L1st4x
+.p2align	4
+.L1st4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.L1st4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	leaq	1(%r14),%r14
+.p2align	2
+.Louter4x:
+	leaq	32+128(%rsp,%r9,8),%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+	movd	%xmm0,%rbx
+
+	xorq	%r15,%r15
+
+	movq	(%rsp),%r10
+	movq	%r8,%rbp
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx),%rax
+	adcq	$0,%rdx
+
+	imulq	%r10,%rbp
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r10
+	movq	8(%rsi),%rax
+	adcq	$0,%rdx
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	16(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	leaq	4(%r15),%r15
+	adcq	$0,%rdx
+	movq	%rdx,%r13
+	jmp	.Linner4x
+.p2align	4
+.Linner4x:
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-16(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	4(%r15),%r15
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	-16(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-40(%rsp,%r15,8)
+	movq	%rdx,%r13
+	cmpq	%r9,%r15
+	jl	.Linner4x
+
+	mulq	%rbx
+	addq	%rax,%r10
+	movq	-16(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-16(%rsp,%r15,8),%r10
+	adcq	$0,%rdx
+	movq	%rdx,%r11
+
+	mulq	%rbp
+	addq	%rax,%r13
+	movq	-8(%rsi,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	%r10,%r13
+	adcq	$0,%rdx
+	movq	%rdi,-32(%rsp,%r15,8)
+	movq	%rdx,%rdi
+
+	mulq	%rbx
+	addq	%rax,%r11
+	movq	-8(%rcx,%r15,8),%rax
+	adcq	$0,%rdx
+	addq	-8(%rsp,%r15,8),%r11
+	adcq	$0,%rdx
+	leaq	1(%r14),%r14
+	movq	%rdx,%r10
+
+	mulq	%rbp
+	addq	%rax,%rdi
+	movq	(%rsi),%rax
+	adcq	$0,%rdx
+	addq	%r11,%rdi
+	adcq	$0,%rdx
+	movq	%r13,-24(%rsp,%r15,8)
+	movq	%rdx,%r13
+
+	movq	%rdi,-16(%rsp,%r15,8)
+
+	xorq	%rdi,%rdi
+	addq	%r10,%r13
+	adcq	$0,%rdi
+	addq	(%rsp,%r9,8),%r13
+	adcq	$0,%rdi
+	movq	%r13,-8(%rsp,%r15,8)
+	movq	%rdi,(%rsp,%r15,8)
+
+	cmpq	%r9,%r14
+	jl	.Louter4x
+	movq	16(%rsp,%r9,8),%rdi
+	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
+	movq	8(%rsp),%rdx
+	shrq	$2,%r9
+	leaq	(%rsp),%rsi
+	xorq	%r14,%r14
+
+	subq	0(%rcx),%rax
+	movq	16(%rsi),%rbx
+	movq	24(%rsi),%rbp
+	sbbq	8(%rcx),%rdx
+	leaq	-1(%r9),%r15
+	jmp	.Lsub4x
+.p2align	4
+.Lsub4x:
+	movq	%rax,0(%rdi,%r14,8)
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	32(%rsi,%r14,8),%rax
+	movq	40(%rsi,%r14,8),%rdx
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+	movq	%rbp,24(%rdi,%r14,8)
+	sbbq	32(%rcx,%r14,8),%rax
+	movq	48(%rsi,%r14,8),%rbx
+	movq	56(%rsi,%r14,8),%rbp
+	sbbq	40(%rcx,%r14,8),%rdx
+	leaq	4(%r14),%r14
+	decq	%r15
+	jnz	.Lsub4x
+
+	movq	%rax,0(%rdi,%r14,8)
+	movq	32(%rsi,%r14,8),%rax
+	sbbq	16(%rcx,%r14,8),%rbx
+	movq	%rdx,8(%rdi,%r14,8)
+	sbbq	24(%rcx,%r14,8),%rbp
+	movq	%rbx,16(%rdi,%r14,8)
+
+	sbbq	$0,%rax
+	movq	%rbp,24(%rdi,%r14,8)
+	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-1(%r9),%r15
+	orq	%rcx,%rsi
+
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
+	jmp	.Lcopy4x
+.p2align	4
+.Lcopy4x:
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
+	leaq	32(%r14),%r14
+	decq	%r15
+	jnz	.Lcopy4x
+
+	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movq	8(%rsp,%r9,8),%rsi
+	movq	$1,%rax
+
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lmul4x_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_bn_mul4x_mont_gather5:
+.globl	bn_scatter5
+.def	bn_scatter5;	.scl 2;	.type 32;	.endef
+.p2align	4
+bn_scatter5:
+	cmpq	$0,%rdx
+	jz	.Lscatter_epilogue
+	leaq	(%r8,%r9,8),%r8
+.Lscatter:
+	movq	(%rcx),%rax
+	leaq	8(%rcx),%rcx
+	movq	%rax,(%r8)
+	leaq	256(%r8),%r8
+	subq	$1,%rdx
+	jnz	.Lscatter
+.Lscatter_epilogue:
+	retq
+
+
+.globl	bn_gather5
+.def	bn_gather5;	.scl 2;	.type 32;	.endef
+.p2align	4
+bn_gather5:
+.LSEH_begin_bn_gather5:
+
+.byte	0x4c,0x8d,0x14,0x24			
+.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00	
+	leaq	.Linc(%rip),%rax
+	andq	$-16,%rsp
+
+	movd	%r9d,%xmm5
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	128(%r8),%r11
+	leaq	128(%rsp),%rax
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-128(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-112(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-96(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-80(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-48(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-16(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,16(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,48(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,80(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,96(%rax)
+	movdqa	%xmm4,%xmm2
+	movdqa	%xmm3,112(%rax)
+	jmp	.Lgather
+
+.p2align	5
+.Lgather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r11),%xmm0
+	movdqa	-112(%r11),%xmm1
+	movdqa	-96(%r11),%xmm2
+	pand	-128(%rax),%xmm0
+	movdqa	-80(%r11),%xmm3
+	pand	-112(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r11),%xmm0
+	movdqa	-48(%r11),%xmm1
+	movdqa	-32(%r11),%xmm2
+	pand	-64(%rax),%xmm0
+	movdqa	-16(%r11),%xmm3
+	pand	-48(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	pand	0(%rax),%xmm0
+	movdqa	48(%r11),%xmm3
+	pand	16(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r11),%xmm0
+	movdqa	80(%r11),%xmm1
+	movdqa	96(%r11),%xmm2
+	pand	64(%rax),%xmm0
+	movdqa	112(%r11),%xmm3
+	pand	80(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	leaq	256(%r11),%r11
+	pshufd	$78,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	movq	%xmm0,(%rcx)
+	leaq	8(%rcx),%rcx
+	subq	$1,%rdx
+	jnz	.Lgather
+
+	leaq	(%r10),%rsp
+	retq
+.LSEH_end_bn_gather5:
+
+.p2align	6
+.Linc:
+.long	0,0, 1,1
+.long	2,2, 2,2
+.byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+
+.def	mul_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+mul_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	leaq	48(%rax),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	movl	8(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	movq	192(%r8),%r10
+	movq	8(%rax,%r10,8),%rax
+
+	leaq	48(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	-32(%rax),%r13
+	movq	-40(%rax),%r14
+	movq	-48(%rax),%r15
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+	movq	%r14,232(%r8)
+	movq	%r15,240(%r8)
+
+.Lcommon_seh_tail:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_bn_mul_mont_gather5
+.rva	.LSEH_end_bn_mul_mont_gather5
+.rva	.LSEH_info_bn_mul_mont_gather5
+
+.rva	.LSEH_begin_bn_mul4x_mont_gather5
+.rva	.LSEH_end_bn_mul4x_mont_gather5
+.rva	.LSEH_info_bn_mul4x_mont_gather5
+
+.rva	.LSEH_begin_bn_gather5
+.rva	.LSEH_end_bn_gather5
+.rva	.LSEH_info_bn_gather5
+
+.section	.xdata
+.p2align	3
+.LSEH_info_bn_mul_mont_gather5:
+.byte	9,0,0,0
+.rva	mul_handler
+.rva	.Lmul_alloca,.Lmul_body,.Lmul_epilogue		
+.p2align	3
+.LSEH_info_bn_mul4x_mont_gather5:
+.byte	9,0,0,0
+.rva	mul_handler
+.rva	.Lmul4x_alloca,.Lmul4x_body,.Lmul4x_epilogue	
+.p2align	3
+.LSEH_info_bn_gather5:
+.byte	0x01,0x0b,0x03,0x0a
+.byte	0x0b,0x01,0x21,0x00	
+.byte	0x04,0xa3,0x00,0x00	
+.p2align	3
diff --git a/crypto/bn/s2n_bignum.h b/crypto/bn/s2n_bignum.h
new file mode 100644
index 0000000..ce6e8cd
--- /dev/null
+++ b/crypto/bn/s2n_bignum.h
@@ -0,0 +1,856 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+// ----------------------------------------------------------------------------
+// C prototypes for s2n-bignum functions, so you can use them in C programs via
+//
+//  #include "s2n-bignum.h"
+//
+// The functions are listed in alphabetical order with a brief description
+// in comments for each one. For more detailed documentation see the comment
+// banner at the top of the corresponding assembly (.S) file, and
+// for the last word in what properties it satisfies see the spec in the
+// formal proof (the .ml file in the architecture-specific directory).
+//
+// For some functions there are additional variants with names ending in
+// "_alt". These have the same core mathematical functionality as their
+// non-"alt" versions, but can be better suited to some microarchitectures:
+//
+//      - On x86, the "_alt" forms avoid BMI and ADX instruction set
+//        extensions, so will run on any x86_64 machine, even older ones
+//
+//      - On ARM, the "_alt" forms target machines with higher multiplier
+//        throughput, generally offering higher performance there.
+// ----------------------------------------------------------------------------
+
+// Add, z := x + y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+extern uint64_t bignum_add (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Add modulo p_25519, z := (x + y) mod p_25519, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_add_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Add modulo p_256, z := (x + y) mod p_256, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_add_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Add modulo p_256k1, z := (x + y) mod p_256k1, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_add_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Add modulo p_384, z := (x + y) mod p_384, assuming x and y reduced
+// Inputs x[6], y[6]; output z[6]
+extern void bignum_add_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
+
+// Add modulo p_521, z := (x + y) mod p_521, assuming x and y reduced
+// Inputs x[9], y[9]; output z[9]
+extern void bignum_add_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+
+// Compute "amontification" constant z :== 2^{128k} (congruent mod m)
+// Input m[k]; output z[k]; temporary buffer t[>=k]
+extern void bignum_amontifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
+
+// Almost-Montgomery multiply, z :== (x * y / 2^{64k}) (congruent mod m)
+// Inputs x[k], y[k], m[k]; output z[k]
+extern void bignum_amontmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
+
+// Almost-Montgomery reduce, z :== (x' / 2^{64p}) (congruent mod m)
+// Inputs x[n], m[k], p; output z[k]
+extern void bignum_amontredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
+
+// Almost-Montgomery square, z :== (x^2 / 2^{64k}) (congruent mod m)
+// Inputs x[k], m[k]; output z[k]
+extern void bignum_amontsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
+
+// Convert 4-digit (256-bit) bignum to/from big-endian form
+// Input x[4]; output z[4]
+extern void bignum_bigendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert 6-digit (384-bit) bignum to/from big-endian form
+// Input x[6]; output z[6]
+extern void bignum_bigendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Select bitfield starting at bit n with length l <= 64
+// Inputs x[k], n, l; output function return
+extern uint64_t bignum_bitfield (uint64_t k, uint64_t *x, uint64_t n, uint64_t l);
+
+// Return size of bignum in bits
+// Input x[k]; output function return
+extern uint64_t bignum_bitsize (uint64_t k, uint64_t *x);
+
+// Divide by a single (nonzero) word, z := x / m and return x mod m
+// Inputs x[n], m; outputs function return (remainder) and z[k]
+extern uint64_t bignum_cdiv (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
+
+// Divide by a single word, z := x / m when known to be exact
+// Inputs x[n], m; output z[k]
+extern void bignum_cdiv_exact (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t m);
+
+// Count leading zero digits (64-bit words)
+// Input x[k]; output function return
+extern uint64_t bignum_cld (uint64_t k, uint64_t *x);
+
+// Count leading zero bits
+// Input x[k]; output function return
+extern uint64_t bignum_clz (uint64_t k, uint64_t *x);
+
+// Multiply-add with single-word multiplier, z := z + c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_cmadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+
+// Negated multiply-add with single-word multiplier, z := z - c * y
+// Inputs c, y[n]; outputs function return (negative carry-out) and z[k]
+extern uint64_t bignum_cmnegadd (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+
+// Find modulus of bignum w.r.t. single nonzero word m, returning x mod m
+// Input x[k], m; output function return
+extern uint64_t bignum_cmod (uint64_t k, uint64_t *x, uint64_t m);
+
+// Multiply by a single word, z := c * y
+// Inputs c, y[n]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_cmul (uint64_t k, uint64_t *z, uint64_t c, uint64_t n, uint64_t *y);
+
+// Multiply by a single word modulo p_25519, z := (c * x) mod p_25519, assuming x reduced
+// Inputs c, x[4]; output z[4]
+extern void bignum_cmul_p25519 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+extern void bignum_cmul_p25519_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+
+// Multiply by a single word modulo p_256, z := (c * x) mod p_256, assuming x reduced
+// Inputs c, x[4]; output z[4]
+extern void bignum_cmul_p256 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+extern void bignum_cmul_p256_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+
+// Multiply by a single word modulo p_256k1, z := (c * x) mod p_256k1, assuming x reduced
+// Inputs c, x[4]; output z[4]
+extern void bignum_cmul_p256k1 (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+extern void bignum_cmul_p256k1_alt (uint64_t z[static 4], uint64_t c, uint64_t x[static 4]);
+
+// Multiply by a single word modulo p_384, z := (c * x) mod p_384, assuming x reduced
+// Inputs c, x[6]; output z[6]
+extern void bignum_cmul_p384 (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
+extern void bignum_cmul_p384_alt (uint64_t z[static 6], uint64_t c, uint64_t x[static 6]);
+
+// Multiply by a single word modulo p_521, z := (c * x) mod p_521, assuming x reduced
+// Inputs c, x[9]; output z[9]
+extern void bignum_cmul_p521 (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
+extern void bignum_cmul_p521_alt (uint64_t z[static 9], uint64_t c, uint64_t x[static 9]);
+
+// Test bignums for coprimality, gcd(x,y) = 1
+// Inputs x[m], y[n]; output function return; temporary buffer t[>=2*max(m,n)]
+extern uint64_t bignum_coprime (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y, uint64_t *t);
+
+// Copy bignum with zero-extension or truncation, z := x
+// Input x[n]; output z[k]
+extern void bignum_copy (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
+
+// Count trailing zero digits (64-bit words)
+// Input x[k]; output function return
+extern uint64_t bignum_ctd (uint64_t k, uint64_t *x);
+
+// Count trailing zero bits
+// Input x[k]; output function return
+extern uint64_t bignum_ctz (uint64_t k, uint64_t *x);
+
+// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256
+// Input x[4]; output z[4]
+extern void bignum_deamont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_deamont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert from almost-Montgomery form, z := (x / 2^256) mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_deamont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert from almost-Montgomery form, z := (x / 2^384) mod p_384
+// Input x[6]; output z[6]
+extern void bignum_deamont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+extern void bignum_deamont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Convert from almost-Montgomery form z := (x / 2^576) mod p_521
+// Input x[9]; output z[9]
+extern void bignum_deamont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Convert from (almost-)Montgomery form z := (x / 2^{64k}) mod m
+// Inputs x[k], m[k]; output z[k]
+extern void bignum_demont (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
+
+// Convert from Montgomery form z := (x / 2^256) mod p_256, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_demont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_demont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert from Montgomery form z := (x / 2^256) mod p_256k1, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_demont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert from Montgomery form z := (x / 2^384) mod p_384, assuming x reduced
+// Input x[6]; output z[6]
+extern void bignum_demont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+extern void bignum_demont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Convert from Montgomery form z := (x / 2^576) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_demont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Select digit x[n]
+// Inputs x[k], n; output function return
+extern uint64_t bignum_digit (uint64_t k, uint64_t *x, uint64_t n);
+
+// Return size of bignum in digits (64-bit word)
+// Input x[k]; output function return
+extern uint64_t bignum_digitsize (uint64_t k, uint64_t *x);
+
+// Divide bignum by 10: z' := z div 10, returning remainder z mod 10
+// Inputs z[k]; outputs function return (remainder) and z[k]
+extern uint64_t bignum_divmod10 (uint64_t k, uint64_t *z);
+
+// Double modulo p_25519, z := (2 * x) mod p_25519, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_double_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Double modulo p_256, z := (2 * x) mod p_256, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_double_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Double modulo p_256k1, z := (2 * x) mod p_256k1, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_double_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Double modulo p_384, z := (2 * x) mod p_384, assuming x reduced
+// Input x[6]; output z[6]
+extern void bignum_double_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Double modulo p_521, z := (2 * x) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_double_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Extended Montgomery reduce, returning results in input-output buffer
+// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
+extern uint64_t bignum_emontredc (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
+
+// Extended Montgomery reduce in 8-digit blocks, results in input-output buffer
+// Inputs z[2*k], m[k], w; outputs function return (extra result bit) and z[2*k]
+extern uint64_t bignum_emontredc_8n (uint64_t k, uint64_t *z, uint64_t *m, uint64_t w);
+
+// Test bignums for equality, x = y
+// Inputs x[m], y[n]; output function return
+extern uint64_t bignum_eq (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Test bignum for even-ness
+// Input x[k]; output function return
+extern uint64_t bignum_even (uint64_t k, uint64_t *x);
+
+// Convert 4-digit (256-bit) bignum from big-endian bytes
+// Input x[32] (bytes); output z[4]
+extern void bignum_frombebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
+
+// Convert 6-digit (384-bit) bignum from big-endian bytes
+// Input x[48] (bytes); output z[6]
+extern void bignum_frombebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
+
+// Convert 4-digit (256-bit) bignum from little-endian bytes
+// Input x[32] (bytes); output z[4]
+extern void bignum_fromlebytes_4 (uint64_t z[static 4], uint8_t x[static 32]);
+
+// Convert 6-digit (384-bit) bignum from little-endian bytes
+// Input x[48] (bytes); output z[6]
+extern void bignum_fromlebytes_6 (uint64_t z[static 6], uint8_t x[static 48]);
+
+// Convert little-endian bytes to 9-digit 528-bit bignum
+// Input x[66] (bytes); output z[9]
+extern void bignum_fromlebytes_p521 (uint64_t z[static 9],uint8_t x[static 66]);
+
+// Compare bignums, x >= y
+// Inputs x[m], y[n]; output function return
+extern uint64_t bignum_ge (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Compare bignums, x > y
+// Inputs x[m], y[n]; output function return
+extern uint64_t bignum_gt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Halve modulo p_256, z := (x / 2) mod p_256, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_half_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Halve modulo p_256k1, z := (x / 2) mod p_256k1, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_half_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Halve modulo p_384, z := (x / 2) mod p_384, assuming x reduced
+// Input x[6]; output z[6]
+extern void bignum_half_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Halve modulo p_521, z := (x / 2) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_half_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Test bignum for zero-ness, x = 0
+// Input x[k]; output function return
+extern uint64_t bignum_iszero (uint64_t k, uint64_t *x);
+
+// Multiply z := x * y
+// Inputs x[16], y[16]; output z[32]; temporary buffer t[>=32]
+extern void bignum_kmul_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t y[static 16], uint64_t t[static 32]);
+
+// Multiply z := x * y
+// Inputs x[32], y[32]; output z[64]; temporary buffer t[>=96]
+extern void bignum_kmul_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t y[static 32], uint64_t t[static 96]);
+
+// Square, z := x^2
+// Input x[16]; output z[32]; temporary buffer t[>=24]
+extern void bignum_ksqr_16_32 (uint64_t z[static 32], uint64_t x[static 16], uint64_t t[static 24]);
+
+// Square, z := x^2
+// Input x[32]; output z[64]; temporary buffer t[>=72]
+extern void bignum_ksqr_32_64 (uint64_t z[static 64], uint64_t x[static 32], uint64_t t[static 72]);
+
+// Compare bignums, x <= y
+// Inputs x[m], y[n]; output function return
+extern uint64_t bignum_le (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Convert 4-digit (256-bit) bignum to/from little-endian form
+// Input x[4]; output z[4]
+extern void bignum_littleendian_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert 6-digit (384-bit) bignum to/from little-endian form
+// Input x[6]; output z[6]
+extern void bignum_littleendian_6 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Compare bignums, x < y
+// Inputs x[m], y[n]; output function return
+extern uint64_t bignum_lt (uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Multiply-add, z := z + x * y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_madd (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Reduce modulo group order, z := x mod n_256
+// Input x[k]; output z[4]
+extern void bignum_mod_n256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
+extern void bignum_mod_n256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
+
+// Reduce modulo group order, z := x mod n_256
+// Input x[4]; output z[4]
+extern void bignum_mod_n256_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Reduce modulo group order, z := x mod n_256k1
+// Input x[4]; output z[4]
+extern void bignum_mod_n256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Reduce modulo group order, z := x mod n_384
+// Input x[k]; output z[6]
+extern void bignum_mod_n384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
+extern void bignum_mod_n384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
+
+// Reduce modulo group order, z := x mod n_384
+// Input x[6]; output z[6]
+extern void bignum_mod_n384_6 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Reduce modulo group order, z := x mod n_521
+// Input x[9]; output z[9]
+extern void bignum_mod_n521_9 (uint64_t z[static 9], uint64_t x[static 9]);
+extern void bignum_mod_n521_9_alt (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Reduce modulo field characteristic, z := x mod p_25519
+// Input x[4]; output z[4]
+extern void bignum_mod_p25519_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Reduce modulo field characteristic, z := x mod p_256
+// Input x[k]; output z[4]
+extern void bignum_mod_p256 (uint64_t z[static 4], uint64_t k, uint64_t *x);
+extern void bignum_mod_p256_alt (uint64_t z[static 4], uint64_t k, uint64_t *x);
+
+// Reduce modulo field characteristic, z := x mod p_256
+// Input x[4]; output z[4]
+extern void bignum_mod_p256_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Reduce modulo field characteristic, z := x mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_mod_p256k1_4 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Reduce modulo field characteristic, z := x mod p_384
+// Input x[k]; output z[6]
+extern void bignum_mod_p384 (uint64_t z[static 6], uint64_t k, uint64_t *x);
+extern void bignum_mod_p384_alt (uint64_t z[static 6], uint64_t k, uint64_t *x);
+
+// Reduce modulo field characteristic, z := x mod p_384
+// Input x[6]; output z[6]
+extern void bignum_mod_p384_6 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Reduce modulo field characteristic, z := x mod p_521
+// Input x[9]; output z[9]
+extern void bignum_mod_p521_9 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Add modulo m, z := (x + y) mod m, assuming x and y reduced
+// Inputs x[k], y[k], m[k]; output z[k]
+extern void bignum_modadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
+
+// Double modulo m, z := (2 * x) mod m, assuming x reduced
+// Inputs x[k], m[k]; output z[k]
+extern void bignum_moddouble (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
+
+// Compute "modification" constant z := 2^{64k} mod m
+// Input m[k]; output z[k]; temporary buffer t[>=k]
+extern void bignum_modifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
+
+// Invert modulo m, z = (1/a) mod b, assuming b is an odd number > 1, a coprime to b
+// Inputs a[k], b[k]; output z[k]; temporary buffer t[>=3*k]
+extern void bignum_modinv (uint64_t k, uint64_t *z, uint64_t *a, uint64_t *b, uint64_t *t);
+
+// Optionally negate modulo m, z := (-x) mod m (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[k], m[k]; output z[k]
+extern void bignum_modoptneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x, uint64_t *m);
+
+// Subtract modulo m, z := (x - y) mod m, assuming x and y reduced
+// Inputs x[k], y[k], m[k]; output z[k]
+extern void bignum_modsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
+
+// Compute "montification" constant z := 2^{128k} mod m
+// Input m[k]; output z[k]; temporary buffer t[>=k]
+extern void bignum_montifier (uint64_t k, uint64_t *z, uint64_t *m, uint64_t *t);
+
+// Montgomery multiply, z := (x * y / 2^{64k}) mod m
+// Inputs x[k], y[k], m[k]; output z[k]
+extern void bignum_montmul (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y, uint64_t *m);
+
+// Montgomery multiply, z := (x * y / 2^256) mod p_256
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_montmul_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+extern void bignum_montmul_p256_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Montgomery multiply, z := (x * y / 2^256) mod p_256k1
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_montmul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+extern void bignum_montmul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Montgomery multiply, z := (x * y / 2^384) mod p_384
+// Inputs x[6], y[6]; output z[6]
+extern void bignum_montmul_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
+extern void bignum_montmul_p384_alt (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
+
+// Montgomery multiply, z := (x * y / 2^576) mod p_521
+// Inputs x[9], y[9]; output z[9]
+extern void bignum_montmul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+extern void bignum_montmul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+
+// Montgomery reduce, z := (x' / 2^{64p}) MOD m
+// Inputs x[n], m[k], p; output z[k]
+extern void bignum_montredc (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t *m, uint64_t p);
+
+// Montgomery square, z := (x^2 / 2^{64k}) mod m
+// Inputs x[k], m[k]; output z[k]
+extern void bignum_montsqr (uint64_t k, uint64_t *z, uint64_t *x, uint64_t *m);
+
+// Montgomery square, z := (x^2 / 2^256) mod p_256
+// Input x[4]; output z[4]
+extern void bignum_montsqr_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_montsqr_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Montgomery square, z := (x^2 / 2^256) mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_montsqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_montsqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Montgomery square, z := (x^2 / 2^384) mod p_384
+// Input x[6]; output z[6]
+extern void bignum_montsqr_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+extern void bignum_montsqr_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Montgomery square, z := (x^2 / 2^576) mod p_521
+// Input x[9]; output z[9]
+extern void bignum_montsqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+extern void bignum_montsqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Multiply z := x * y
+// Inputs x[m], y[n]; output z[k]
+extern void bignum_mul (uint64_t k, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Multiply z := x * y
+// Inputs x[4], y[4]; output z[8]
+extern void bignum_mul_4_8 (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
+extern void bignum_mul_4_8_alt (uint64_t z[static 8], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Multiply z := x * y
+// Inputs x[6], y[6]; output z[12]
+extern void bignum_mul_6_12 (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
+extern void bignum_mul_6_12_alt (uint64_t z[static 12], uint64_t x[static 6], uint64_t y[static 6]);
+
+// Multiply z := x * y
+// Inputs x[8], y[8]; output z[16]
+extern void bignum_mul_8_16 (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
+extern void bignum_mul_8_16_alt (uint64_t z[static 16], uint64_t x[static 8], uint64_t y[static 8]);
+
+// Multiply modulo p_25519, z := (x * y) mod p_25519
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_mul_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+extern void bignum_mul_p25519_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Multiply modulo p_256k1, z := (x * y) mod p_256k1
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_mul_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+extern void bignum_mul_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Multiply modulo p_521, z := (x * y) mod p_521, assuming x and y reduced
+// Inputs x[9], y[9]; output z[9]
+extern void bignum_mul_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+extern void bignum_mul_p521_alt (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+
+// Multiply bignum by 10 and add word: z := 10 * z + d
+// Inputs z[k], d; outputs function return (carry) and z[k]
+extern uint64_t bignum_muladd10 (uint64_t k, uint64_t *z, uint64_t d);
+
+// Multiplex/select z := x (if p nonzero) or z := y (if p zero)
+// Inputs p, x[k], y[k]; output z[k]
+extern void bignum_mux (uint64_t p, uint64_t k, uint64_t *z, uint64_t *x, uint64_t *y);
+
+// 256-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
+// Inputs p, x[4], y[4]; output z[4]
+extern void bignum_mux_4 (uint64_t p, uint64_t z[static 4],uint64_t x[static 4], uint64_t y[static 4]);
+
+// 384-bit multiplex/select z := x (if p nonzero) or z := y (if p zero)
+// Inputs p, x[6], y[6]; output z[6]
+extern void bignum_mux_6 (uint64_t p, uint64_t z[static 6],uint64_t x[static 6], uint64_t y[static 6]);
+
+// Select element from 16-element table, z := xs[k*i]
+// Inputs xs[16*k], i; output z[k]
+extern void bignum_mux16 (uint64_t k, uint64_t *z, uint64_t *xs, uint64_t i);
+
+// Negate modulo p_25519, z := (-x) mod p_25519, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_neg_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Negate modulo p_256, z := (-x) mod p_256, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_neg_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Negate modulo p_256k1, z := (-x) mod p_256k1, assuming x reduced
+// Input x[4]; output z[4]
+extern void bignum_neg_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Negate modulo p_384, z := (-x) mod p_384, assuming x reduced
+// Input x[6]; output z[6]
+extern void bignum_neg_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Negate modulo p_521, z := (-x) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_neg_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Negated modular inverse, z := (-1/x) mod 2^{64k}
+// Input x[k]; output z[k]
+extern void bignum_negmodinv (uint64_t k, uint64_t *z, uint64_t *x);
+
+// Test bignum for nonzero-ness x =/= 0
+// Input x[k]; output function return
+extern uint64_t bignum_nonzero (uint64_t k, uint64_t *x);
+
+// Test 256-bit bignum for nonzero-ness x =/= 0
+// Input x[4]; output function return
+extern uint64_t bignum_nonzero_4(uint64_t x[static 4]);
+
+// Test 384-bit bignum for nonzero-ness x =/= 0
+// Input x[6]; output function return
+extern uint64_t bignum_nonzero_6(uint64_t x[static 6]);
+
+// Normalize bignum in-place by shifting left till top bit is 1
+// Input z[k]; outputs function return (bits shifted left) and z[k]
+extern uint64_t bignum_normalize (uint64_t k, uint64_t *z);
+
+// Test bignum for odd-ness
+// Input x[k]; output function return
+extern uint64_t bignum_odd (uint64_t k, uint64_t *x);
+
+// Convert single digit to bignum, z := n
+// Input n; output z[k]
+extern void bignum_of_word (uint64_t k, uint64_t *z, uint64_t n);
+
+// Optionally add, z := x + y (if p nonzero) or z := x (if p zero)
+// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_optadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
+
+// Optionally negate, z := -x (if p nonzero) or z := x (if p zero)
+// Inputs p, x[k]; outputs function return (nonzero input) and z[k]
+extern uint64_t bignum_optneg (uint64_t k, uint64_t *z, uint64_t p, uint64_t *x);
+
+// Optionally negate modulo p_25519, z := (-x) mod p_25519 (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[4]; output z[4]
+extern void bignum_optneg_p25519 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
+
+// Optionally negate modulo p_256, z := (-x) mod p_256 (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[4]; output z[4]
+extern void bignum_optneg_p256 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
+
+// Optionally negate modulo p_256k1, z := (-x) mod p_256k1 (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[4]; output z[4]
+extern void bignum_optneg_p256k1 (uint64_t z[static 4], uint64_t p, uint64_t x[static 4]);
+
+// Optionally negate modulo p_384, z := (-x) mod p_384 (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[6]; output z[6]
+extern void bignum_optneg_p384 (uint64_t z[static 6], uint64_t p, uint64_t x[static 6]);
+
+// Optionally negate modulo p_521, z := (-x) mod p_521 (if p nonzero) or z := x (if p zero), assuming x reduced
+// Inputs p, x[9]; output z[9]
+extern void bignum_optneg_p521 (uint64_t z[static 9], uint64_t p, uint64_t x[static 9]);
+
+// Optionally subtract, z := x - y (if p nonzero) or z := x (if p zero)
+// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_optsub (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
+
+// Optionally subtract or add, z := x + sgn(p) * y interpreting p as signed
+// Inputs x[k], p, y[k]; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_optsubadd (uint64_t k, uint64_t *z, uint64_t *x, uint64_t p, uint64_t *y);
+
+// Return bignum of power of 2, z := 2^n
+// Input n; output z[k]
+extern void bignum_pow2 (uint64_t k, uint64_t *z, uint64_t n);
+
+// Shift bignum left by c < 64 bits z := x * 2^c
+// Inputs x[n], c; outputs function return (carry-out) and z[k]
+extern uint64_t bignum_shl_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
+
+// Shift bignum right by c < 64 bits z := floor(x / 2^c)
+// Inputs x[n], c; outputs function return (bits shifted out) and z[k]
+extern uint64_t bignum_shr_small (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x, uint64_t c);
+
+// Square, z := x^2
+// Input x[n]; output z[k]
+extern void bignum_sqr (uint64_t k, uint64_t *z, uint64_t n, uint64_t *x);
+
+// Square, z := x^2
+// Input x[4]; output z[8]
+extern void bignum_sqr_4_8 (uint64_t z[static 8], uint64_t x[static 4]);
+extern void bignum_sqr_4_8_alt (uint64_t z[static 8], uint64_t x[static 4]);
+
+// Square, z := x^2
+// Input x[6]; output z[12]
+extern void bignum_sqr_6_12 (uint64_t z[static 12], uint64_t x[static 6]);
+extern void bignum_sqr_6_12_alt (uint64_t z[static 12], uint64_t x[static 6]);
+
+// Square, z := x^2
+// Input x[8]; output z[16]
+extern void bignum_sqr_8_16 (uint64_t z[static 16], uint64_t x[static 8]);
+extern void bignum_sqr_8_16_alt (uint64_t z[static 16], uint64_t x[static 8]);
+
+// Square modulo p_25519, z := (x^2) mod p_25519
+// Input x[4]; output z[4]
+extern void bignum_sqr_p25519 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_sqr_p25519_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Square modulo p_256k1, z := (x^2) mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_sqr_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_sqr_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Square modulo p_521, z := (x^2) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_sqr_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+extern void bignum_sqr_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Subtract, z := x - y
+// Inputs x[m], y[n]; outputs function return (carry-out) and z[p]
+extern uint64_t bignum_sub (uint64_t p, uint64_t *z, uint64_t m, uint64_t *x, uint64_t n, uint64_t *y);
+
+// Subtract modulo p_25519, z := (x - y) mod p_25519, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_sub_p25519 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Subtract modulo p_256, z := (x - y) mod p_256, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_sub_p256 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Subtract modulo p_256k1, z := (x - y) mod p_256k1, assuming x and y reduced
+// Inputs x[4], y[4]; output z[4]
+extern void bignum_sub_p256k1 (uint64_t z[static 4], uint64_t x[static 4], uint64_t y[static 4]);
+
+// Subtract modulo p_384, z := (x - y) mod p_384, assuming x and y reduced
+// Inputs x[6], y[6]; output z[6]
+extern void bignum_sub_p384 (uint64_t z[static 6], uint64_t x[static 6], uint64_t y[static 6]);
+
+// Subtract modulo p_521, z := (x - y) mod p_521, assuming x and y reduced
+// Inputs x[9], y[9]; output z[9]
+extern void bignum_sub_p521 (uint64_t z[static 9], uint64_t x[static 9], uint64_t y[static 9]);
+
+// Convert 4-digit (256-bit) bignum to big-endian bytes
+// Input x[4]; output z[32] (bytes)
+extern void bignum_tobebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
+
+// Convert 6-digit (384-bit) bignum to big-endian bytes
+// Input x[6]; output z[48] (bytes)
+extern void bignum_tobebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
+
+// Convert 4-digit (256-bit) bignum to little-endian bytes
+// Input x[4]; output z[32] (bytes)
+extern void bignum_tolebytes_4 (uint8_t z[static 32], uint64_t x[static 4]);
+
+// Convert 6-digit (384-bit) bignum to little-endian bytes
+// Input x[6]; output z[48] (bytes)
+extern void bignum_tolebytes_6 (uint8_t z[static 48], uint64_t x[static 6]);
+
+// Convert 9-digit 528-bit bignum to little-endian bytes
+// Input x[6]; output z[66] (bytes)
+extern void bignum_tolebytes_p521 (uint8_t z[static 66], uint64_t x[static 9]);
+
+// Convert to Montgomery form z := (2^256 * x) mod p_256
+// Input x[4]; output z[4]
+extern void bignum_tomont_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_tomont_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert to Montgomery form z := (2^256 * x) mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_tomont_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_tomont_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Convert to Montgomery form z := (2^384 * x) mod p_384
+// Input x[6]; output z[6]
+extern void bignum_tomont_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+extern void bignum_tomont_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Convert to Montgomery form z := (2^576 * x) mod p_521
+// Input x[9]; output z[9]
+extern void bignum_tomont_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Triple modulo p_256, z := (3 * x) mod p_256
+// Input x[4]; output z[4]
+extern void bignum_triple_p256 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_triple_p256_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Triple modulo p_256k1, z := (3 * x) mod p_256k1
+// Input x[4]; output z[4]
+extern void bignum_triple_p256k1 (uint64_t z[static 4], uint64_t x[static 4]);
+extern void bignum_triple_p256k1_alt (uint64_t z[static 4], uint64_t x[static 4]);
+
+// Triple modulo p_384, z := (3 * x) mod p_384
+// Input x[6]; output z[6]
+extern void bignum_triple_p384 (uint64_t z[static 6], uint64_t x[static 6]);
+extern void bignum_triple_p384_alt (uint64_t z[static 6], uint64_t x[static 6]);
+
+// Triple modulo p_521, z := (3 * x) mod p_521, assuming x reduced
+// Input x[9]; output z[9]
+extern void bignum_triple_p521 (uint64_t z[static 9], uint64_t x[static 9]);
+extern void bignum_triple_p521_alt (uint64_t z[static 9], uint64_t x[static 9]);
+
+// Montgomery ladder step for curve25519
+// Inputs point[8], pp[16], b; output rr[16]
+extern void curve25519_ladderstep(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
+extern void curve25519_ladderstep_alt(uint64_t rr[16],uint64_t point[8],uint64_t pp[16],uint64_t b);
+
+// Projective scalar multiplication, x coordinate only, for curve25519
+// Inputs scalar[4], point[4]; output res[8]
+extern void curve25519_pxscalarmul(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
+extern void curve25519_pxscalarmul_alt(uint64_t res[static 8],uint64_t scalar[static 4],uint64_t point[static 4]);
+
+// x25519 function for curve25519
+// Inputs scalar[4], point[4]; output res[4]
+extern void curve25519_x25519(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
+extern void curve25519_x25519_alt(uint64_t res[static 4],uint64_t scalar[static 4],uint64_t point[static 4]);
+
+// x25519 function for curve25519 on base element 9
+// Input scalar[4]; output res[4]
+extern void curve25519_x25519base(uint64_t res[static 4],uint64_t scalar[static 4]);
+extern void curve25519_x25519base_alt(uint64_t res[static 4],uint64_t scalar[static 4]);
+
+// Extended projective addition for edwards25519
+// Inputs p1[16], p2[16]; output p3[16]
+extern void edwards25519_epadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
+extern void edwards25519_epadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 16]);
+
+// Extended projective doubling for edwards25519
+// Inputs p1[12]; output p3[16]
+extern void edwards25519_epdouble(uint64_t p3[static 16],uint64_t p1[static 12]);
+extern void edwards25519_epdouble_alt(uint64_t p3[static 16],uint64_t p1[static 12]);
+
+// Projective doubling for edwards25519
+// Inputs p1[12]; output p3[12]
+extern void edwards25519_pdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
+extern void edwards25519_pdouble_alt(uint64_t p3[static 12],uint64_t p1[static 12]);
+
+// Extended projective + precomputed mixed addition for edwards25519
+// Inputs p1[16], p2[12]; output p3[16]
+extern void edwards25519_pepadd(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
+extern void edwards25519_pepadd_alt(uint64_t p3[static 16],uint64_t p1[static 16],uint64_t p2[static 12]);
+
+// Point addition on NIST curve P-256 in Montgomery-Jacobian coordinates
+// Inputs p1[12], p2[12]; output p3[12]
+extern void p256_montjadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
+
+// Point doubling on NIST curve P-256 in Montgomery-Jacobian coordinates
+// Inputs p1[12]; output p3[12]
+extern void p256_montjdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
+
+// Point mixed addition on NIST curve P-256 in Montgomery-Jacobian coordinates
+// Inputs p1[12], p2[8]; output p3[12]
+extern void p256_montjmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
+
+// Point addition on NIST curve P-384 in Montgomery-Jacobian coordinates
+// Inputs p1[18], p2[18]; output p3[18]
+extern void p384_montjadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 18]);
+
+// Point doubling on NIST curve P-384 in Montgomery-Jacobian coordinates
+// Inputs p1[18]; output p3[18]
+extern void p384_montjdouble(uint64_t p3[static 18],uint64_t p1[static 18]);
+
+// Point mixed addition on NIST curve P-384 in Montgomery-Jacobian coordinates
+// Inputs p1[18], p2[12]; output p3[18]
+extern void p384_montjmixadd(uint64_t p3[static 18],uint64_t p1[static 18],uint64_t p2[static 12]);
+
+// Point addition on NIST curve P-521 in Jacobian coordinates
+// Inputs p1[27], p2[27]; output p3[27]
+extern void p521_jadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 27]);
+
+// Point doubling on NIST curve P-521 in Jacobian coordinates
+// Input p1[27]; output p3[27]
+extern void p521_jdouble(uint64_t p3[static 27],uint64_t p1[static 27]);
+
+// Point mixed addition on NIST curve P-521 in Jacobian coordinates
+// Inputs p1[27], p2[18]; output p3[27]
+extern void p521_jmixadd(uint64_t p3[static 27],uint64_t p1[static 27],uint64_t p2[static 18]);
+
+// Point addition on SECG curve secp256k1 in Jacobian coordinates
+// Inputs p1[12], p2[12]; output p3[12]
+extern void secp256k1_jadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 12]);
+
+// Point doubling on SECG curve secp256k1 in Jacobian coordinates
+// Input p1[12]; output p3[12]
+extern void secp256k1_jdouble(uint64_t p3[static 12],uint64_t p1[static 12]);
+
+// Point mixed addition on SECG curve secp256k1 in Jacobian coordinates
+// Inputs p1[12], p2[8]; output p3[12]
+extern void secp256k1_jmixadd(uint64_t p3[static 12],uint64_t p1[static 12],uint64_t p2[static 8]);
+
+// Reverse the bytes in a single word
+// Input a; output function return
+extern uint64_t word_bytereverse (uint64_t a);
+
+// Count leading zero bits in a single word
+// Input a; output function return
+extern uint64_t word_clz (uint64_t a);
+
+// Count trailing zero bits in a single word
+// Input a; output function return
+extern uint64_t word_ctz (uint64_t a);
+
+// Return maximum of two unsigned 64-bit words
+// Inputs a, b; output function return
+extern uint64_t word_max (uint64_t a, uint64_t b);
+
+// Return minimum of two unsigned 64-bit words
+// Inputs a, b; output function return
+extern uint64_t word_min (uint64_t a, uint64_t b);
+
+// Single-word negated modular inverse (-1/a) mod 2^64
+// Input a; output function return
+extern uint64_t word_negmodinv (uint64_t a);
+
+// Single-word reciprocal, 2^64 + ret = ceil(2^128/a) - 1 if MSB of "a" is set
+// Input a; output function return
+extern uint64_t word_recip (uint64_t a);
diff --git a/crypto/bn/s2n_bignum_internal.h b/crypto/bn/s2n_bignum_internal.h
new file mode 100644
index 0000000..f413688
--- /dev/null
+++ b/crypto/bn/s2n_bignum_internal.h
@@ -0,0 +1,30 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+#ifdef __APPLE__
+#   define S2N_BN_SYMBOL(NAME) _##NAME
+#else
+#   define S2N_BN_SYMBOL(name) name
+#endif
+
+#define S2N_BN_SYM_VISIBILITY_DIRECTIVE(name) .globl S2N_BN_SYMBOL(name)
+#ifdef S2N_BN_HIDE_SYMBOLS
+#   ifdef __APPLE__
+#      define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) .private_extern S2N_BN_SYMBOL(name)
+#   else
+#      define S2N_BN_SYM_PRIVACY_DIRECTIVE(name) .hidden S2N_BN_SYMBOL(name)
+#   endif
+#else
+#   define S2N_BN_SYM_PRIVACY_DIRECTIVE(name)  /* NO-OP: S2N_BN_SYM_PRIVACY_DIRECTIVE */
+#endif
diff --git a/crypto/buffer/buf_err.c b/crypto/buffer/buf_err.c
new file mode 100644
index 0000000..3b045cf
--- /dev/null
+++ b/crypto/buffer/buf_err.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: buf_err.c,v 1.13 2023/07/08 08:26:26 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_BUF,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_BUF,0,reason)
+
+static ERR_STRING_DATA BUF_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA BUF_str_reasons[] = {
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_BUF_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(BUF_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, BUF_str_functs);
+		ERR_load_strings(0, BUF_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_BUF_strings);
diff --git a/crypto/buffer/buffer.c b/crypto/buffer/buffer.c
new file mode 100644
index 0000000..51ce90f
--- /dev/null
+++ b/crypto/buffer/buffer.c
@@ -0,0 +1,155 @@
+/* $OpenBSD: buffer.c,v 1.28 2023/07/08 08:26:26 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+/*
+ * LIMIT_BEFORE_EXPANSION is the maximum n such that (n + 3) / 3 * 4 < 2**31.
+ * That function is applied in several functions in this file and this limit
+ * ensures that the result fits in an int.
+ */
+#define LIMIT_BEFORE_EXPANSION 0x5ffffffc
+
+BUF_MEM *
+BUF_MEM_new(void)
+{
+	BUF_MEM *ret;
+
+	if ((ret = calloc(1, sizeof(BUF_MEM))) == NULL) {
+		BUFerror(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+
+	return (ret);
+}
+LCRYPTO_ALIAS(BUF_MEM_new);
+
+void
+BUF_MEM_free(BUF_MEM *a)
+{
+	if (a == NULL)
+		return;
+
+	freezero(a->data, a->max);
+	free(a);
+}
+LCRYPTO_ALIAS(BUF_MEM_free);
+
+int
+BUF_MEM_grow(BUF_MEM *str, size_t len)
+{
+	return BUF_MEM_grow_clean(str, len);
+}
+LCRYPTO_ALIAS(BUF_MEM_grow);
+
+int
+BUF_MEM_grow_clean(BUF_MEM *str, size_t len)
+{
+	char *ret;
+	size_t n;
+
+	if (str->max >= len) {
+		if (str->length >= len)
+			memset(&str->data[len], 0, str->length - len);
+		str->length = len;
+		return (len);
+	}
+
+	if (len > LIMIT_BEFORE_EXPANSION) {
+		BUFerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	n = (len + 3) / 3 * 4;
+	if ((ret = recallocarray(str->data, str->max, n, 1)) == NULL) {
+		BUFerror(ERR_R_MALLOC_FAILURE);
+		return (0);
+	}
+	str->data = ret;
+	str->max = n;
+	str->length = len;
+
+	return (len);
+}
+LCRYPTO_ALIAS(BUF_MEM_grow_clean);
+
+void
+BUF_reverse(unsigned char *out, const unsigned char *in, size_t size)
+{
+	size_t i;
+
+	if (in) {
+		out += size - 1;
+		for (i = 0; i < size; i++)
+			*out-- = *in++;
+	} else {
+		unsigned char *q;
+		char c;
+		q = out + size - 1;
+		for (i = 0; i < size / 2; i++) {
+			c = *q;
+			*q-- = *out;
+			*out++ = c;
+		}
+	}
+}
diff --git a/crypto/bytestring/bs_ber.c b/crypto/bytestring/bs_ber.c
new file mode 100644
index 0000000..c9779c8
--- /dev/null
+++ b/crypto/bytestring/bs_ber.c
@@ -0,0 +1,269 @@
+/*	$OpenBSD: bs_ber.c,v 1.2 2021/12/15 18:02:39 jsing Exp $	*/
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "bytestring.h"
+
+/*
+ * kMaxDepth is a just a sanity limit. The code should be such that the length
+ * of the input being processes always decreases. None the less, a very large
+ * input could otherwise cause the stack to overflow.
+ */
+static const unsigned int kMaxDepth = 2048;
+
+/* Non-strict version that allows a relaxed DER with indefinite form. */
+static int
+cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
+    size_t *out_header_len)
+{
+	return cbs_get_any_asn1_element_internal(cbs, out,
+	    out_tag, out_header_len, 0);
+}
+
+/*
+ * cbs_find_indefinite walks an ASN.1 structure in |orig_in| and sets
+ * |*indefinite_found| depending on whether an indefinite length element was
+ * found. The value of |orig_in| is not modified.
+ *
+ * Returns one on success (i.e. |*indefinite_found| was set) and zero on error.
+ */
+static int
+cbs_find_indefinite(const CBS *orig_in, char *indefinite_found,
+    unsigned int depth)
+{
+	CBS in;
+
+	if (depth > kMaxDepth)
+		return 0;
+
+	CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in));
+
+	while (CBS_len(&in) > 0) {
+		CBS contents;
+		unsigned int tag;
+		size_t header_len;
+
+		if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag,
+		    &header_len))
+			return 0;
+
+		/* Indefinite form not allowed by DER. */
+		if (CBS_len(&contents) == header_len && header_len > 0 &&
+		    CBS_data(&contents)[header_len - 1] == 0x80) {
+			*indefinite_found = 1;
+			return 1;
+		}
+		if (tag & CBS_ASN1_CONSTRUCTED) {
+			if (!CBS_skip(&contents, header_len) ||
+			    !cbs_find_indefinite(&contents, indefinite_found,
+			    depth + 1))
+				return 0;
+		}
+	}
+
+	*indefinite_found = 0;
+	return 1;
+}
+
+/*
+ * is_primitive_type returns true if |tag| likely a primitive type. Normally
+ * one can just test the "constructed" bit in the tag but, in BER, even
+ * primitive tags can have the constructed bit if they have indefinite
+ * length.
+ */
+static char
+is_primitive_type(unsigned int tag)
+{
+	return (tag & 0xc0) == 0 &&
+	    (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
+	    (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
+}
+
+/*
+ * is_eoc returns true if |header_len| and |contents|, as returned by
+ * |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC)
+ * value.
+ */
+static char
+is_eoc(size_t header_len, CBS *contents)
+{
+	const unsigned char eoc[] = {0x0, 0x0};
+
+	return header_len == 2 && CBS_mem_equal(contents, eoc, 2);
+}
+
+/*
+ * cbs_convert_indefinite reads data with DER encoding (but relaxed to allow
+ * indefinite form) from |in| and writes definite form DER data to |out|. If
+ * |squash_header| is set then the top-level of elements from |in| will not
+ * have their headers written. This is used when concatenating the fragments of
+ * an indefinite length, primitive value. If |looking_for_eoc| is set then any
+ * EOC elements found will cause the function to return after consuming it.
+ * It returns one on success and zero on error.
+ */
+static int
+cbs_convert_indefinite(CBS *in, CBB *out, char squash_header,
+    char looking_for_eoc, unsigned int depth)
+{
+	if (depth > kMaxDepth)
+		return 0;
+
+	while (CBS_len(in) > 0) {
+		CBS contents;
+		unsigned int tag;
+		size_t header_len;
+		CBB *out_contents, out_contents_storage;
+
+		if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag,
+		    &header_len))
+			return 0;
+
+		out_contents = out;
+
+		if (CBS_len(&contents) == header_len) {
+			if (is_eoc(header_len, &contents))
+				return looking_for_eoc;
+
+			if (header_len > 0 &&
+			    CBS_data(&contents)[header_len - 1] == 0x80) {
+				/*
+				 * This is an indefinite length element. If
+				 * it's a SEQUENCE or SET then we just need to
+				 * write the out the contents as normal, but
+				 * with a concrete length prefix.
+				 *
+				 * If it's a something else then the contents
+				 * will be a series of DER elements of the same
+				 * type which need to be concatenated.
+				 */
+				const char context_specific = (tag & 0xc0)
+				    == 0x80;
+				char squash_child_headers =
+				    is_primitive_type(tag);
+
+				/*
+				 * This is a hack, but it sufficies to handle
+				 * NSS's output. If we find an indefinite
+				 * length, context-specific tag with a definite,
+				 * primtive tag inside it, then we assume that
+				 * the context-specific tag is implicit and the
+				 * tags within are fragments of a primitive type
+				 * that need to be concatenated.
+				 */
+				if (context_specific &&
+				    (tag & CBS_ASN1_CONSTRUCTED)) {
+					CBS in_copy, inner_contents;
+					unsigned int inner_tag;
+					size_t inner_header_len;
+
+					CBS_init(&in_copy, CBS_data(in),
+					    CBS_len(in));
+					if (!cbs_nonstrict_get_any_asn1_element(
+					    &in_copy, &inner_contents,
+					    &inner_tag, &inner_header_len))
+						return 0;
+
+					if (CBS_len(&inner_contents) >
+					    inner_header_len &&
+					    is_primitive_type(inner_tag))
+						squash_child_headers = 1;
+				}
+
+				if (!squash_header) {
+					unsigned int out_tag = tag;
+
+					if (squash_child_headers)
+						out_tag &=
+						    ~CBS_ASN1_CONSTRUCTED;
+
+					if (!CBB_add_asn1(out,
+					    &out_contents_storage, out_tag))
+						return 0;
+
+					out_contents = &out_contents_storage;
+				}
+
+				if (!cbs_convert_indefinite(in, out_contents,
+				    squash_child_headers,
+				    1 /* looking for eoc */, depth + 1))
+					return 0;
+
+				if (out_contents != out && !CBB_flush(out))
+					return 0;
+
+				continue;
+			}
+		}
+
+		if (!squash_header) {
+			if (!CBB_add_asn1(out, &out_contents_storage, tag))
+				return 0;
+
+			out_contents = &out_contents_storage;
+		}
+
+		if (!CBS_skip(&contents, header_len))
+			return 0;
+
+		if (tag & CBS_ASN1_CONSTRUCTED) {
+			if (!cbs_convert_indefinite(&contents, out_contents,
+			    0 /* don't squash header */,
+			    0 /* not looking for eoc */, depth + 1))
+				return 0;
+		} else {
+			if (!CBB_add_bytes(out_contents, CBS_data(&contents),
+			    CBS_len(&contents)))
+				return 0;
+		}
+
+		if (out_contents != out && !CBB_flush(out))
+			return 0;
+	}
+
+	return looking_for_eoc == 0;
+}
+
+int
+CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len)
+{
+	CBB cbb;
+
+	/*
+	 * First, do a quick walk to find any indefinite-length elements. Most
+	 * of the time we hope that there aren't any and thus we can quickly
+	 * return.
+	 */
+	char conversion_needed;
+	if (!cbs_find_indefinite(in, &conversion_needed, 0))
+		return 0;
+
+	if (!conversion_needed) {
+		*out = NULL;
+		*out_len = 0;
+		return 1;
+	}
+
+	if (!CBB_init(&cbb, CBS_len(in)))
+		return 0;
+	if (!cbs_convert_indefinite(in, &cbb, 0, 0, 0)) {
+		CBB_cleanup(&cbb);
+		return 0;
+	}
+
+	return CBB_finish(&cbb, out, out_len);
+}
diff --git a/crypto/bytestring/bs_cbb.c b/crypto/bytestring/bs_cbb.c
new file mode 100644
index 0000000..c8b6f48
--- /dev/null
+++ b/crypto/bytestring/bs_cbb.c
@@ -0,0 +1,483 @@
+/*	$OpenBSD: bs_cbb.c,v 1.4 2022/07/07 17:16:05 tb Exp $	*/
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "bytestring.h"
+
+#define CBB_INITIAL_SIZE 64
+
+static int
+cbb_init(CBB *cbb, uint8_t *buf, size_t cap)
+{
+	struct cbb_buffer_st *base;
+
+	if ((base = calloc(1, sizeof(struct cbb_buffer_st))) == NULL)
+		return 0;
+
+	base->buf = buf;
+	base->len = 0;
+	base->cap = cap;
+	base->can_resize = 1;
+
+	cbb->base = base;
+	cbb->is_top_level = 1;
+
+	return 1;
+}
+
+int
+CBB_init(CBB *cbb, size_t initial_capacity)
+{
+	uint8_t *buf = NULL;
+
+	memset(cbb, 0, sizeof(*cbb));
+
+	if (initial_capacity == 0)
+		initial_capacity = CBB_INITIAL_SIZE;
+
+	if ((buf = calloc(1, initial_capacity)) == NULL)
+		return 0;
+
+	if (!cbb_init(cbb, buf, initial_capacity)) {
+		free(buf);
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len)
+{
+	memset(cbb, 0, sizeof(*cbb));
+
+	if (!cbb_init(cbb, buf, len))
+		return 0;
+
+	cbb->base->can_resize = 0;
+
+	return 1;
+}
+
+void
+CBB_cleanup(CBB *cbb)
+{
+	if (cbb->base) {
+		if (cbb->base->can_resize)
+			freezero(cbb->base->buf, cbb->base->cap);
+		free(cbb->base);
+	}
+	cbb->base = NULL;
+	cbb->child = NULL;
+}
+
+static int
+cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len)
+{
+	size_t newlen;
+
+	if (base == NULL)
+		return 0;
+
+	newlen = base->len + len;
+	if (newlen < base->len)
+		/* Overflow */
+		return 0;
+
+	if (newlen > base->cap) {
+		size_t newcap = base->cap * 2;
+		uint8_t *newbuf;
+
+		if (!base->can_resize)
+			return 0;
+
+		if (newcap < base->cap || newcap < newlen)
+			newcap = newlen;
+
+		newbuf = recallocarray(base->buf, base->cap, newcap, 1);
+		if (newbuf == NULL)
+			return 0;
+
+		base->buf = newbuf;
+		base->cap = newcap;
+	}
+
+	if (out)
+		*out = base->buf + base->len;
+
+	base->len = newlen;
+	return 1;
+}
+
+static int
+cbb_add_u(CBB *cbb, uint32_t v, size_t len_len)
+{
+	uint8_t *buf;
+	size_t i;
+
+	if (len_len == 0)
+		return 1;
+
+	if (len_len > 4)
+		return 0;
+
+	if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len))
+		return 0;
+
+	for (i = len_len - 1; i < len_len; i--) {
+		buf[i] = v;
+		v >>= 8;
+	}
+	return 1;
+}
+
+int
+CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len)
+{
+	if (!cbb->is_top_level)
+		return 0;
+
+	if (!CBB_flush(cbb))
+		return 0;
+
+	if (cbb->base->can_resize && (out_data == NULL || out_len == NULL))
+		/*
+		 * |out_data| and |out_len| can only be NULL if the CBB is
+		 * fixed.
+		 */
+		return 0;
+
+	if (out_data != NULL && *out_data != NULL)
+		return 0;
+
+	if (out_data != NULL)
+		*out_data = cbb->base->buf;
+
+	if (out_len != NULL)
+		*out_len = cbb->base->len;
+
+	cbb->base->buf = NULL;
+	CBB_cleanup(cbb);
+	return 1;
+}
+
+/*
+ * CBB_flush recurses and then writes out any pending length prefix. The current
+ * length of the underlying base is taken to be the length of the
+ * length-prefixed data.
+ */
+int
+CBB_flush(CBB *cbb)
+{
+	size_t child_start, i, len;
+
+	if (cbb->base == NULL)
+		return 0;
+
+	if (cbb->child == NULL || cbb->pending_len_len == 0)
+		return 1;
+
+	child_start = cbb->offset + cbb->pending_len_len;
+
+	if (!CBB_flush(cbb->child) || child_start < cbb->offset ||
+	    cbb->base->len < child_start)
+		return 0;
+
+	len = cbb->base->len - child_start;
+
+	if (cbb->pending_is_asn1) {
+		/*
+		 * For ASN.1, we assumed that we were using short form which
+		 * only requires a single byte for the length octet.
+		 *
+		 * If it turns out that we need long form, we have to move
+		 * the contents along in order to make space for more length
+		 * octets.
+		 */
+		size_t len_len = 1;  /* total number of length octets */
+		uint8_t initial_length_byte;
+
+		/* We already wrote 1 byte for the length. */
+		if (cbb->pending_len_len != 1)
+			return 0;
+
+		/* Check for long form */
+		if (len > 0xfffffffe)
+			return 0;	/* 0xffffffff is reserved */
+		else if (len > 0xffffff)
+			len_len = 5;
+		else if (len > 0xffff)
+			len_len = 4;
+		else if (len > 0xff)
+			len_len = 3;
+		else if (len > 0x7f)
+			len_len = 2;
+
+		if (len_len == 1) {
+			/* For short form, the initial byte is the length. */
+			initial_length_byte = len;
+			len = 0;
+
+		} else {
+			/*
+			 * For long form, the initial byte is the number of
+			 * subsequent length octets (plus bit 8 set).
+			 */
+			initial_length_byte = 0x80 | (len_len - 1);
+
+			/*
+			 * We need to move the contents along in order to make
+			 * space for the long form length octets.
+			 */
+			size_t extra_bytes = len_len - 1;
+			if (!cbb_buffer_add(cbb->base, NULL, extra_bytes))
+				return 0;
+
+			memmove(cbb->base->buf + child_start + extra_bytes,
+			    cbb->base->buf + child_start, len);
+		}
+		cbb->base->buf[cbb->offset++] = initial_length_byte;
+		cbb->pending_len_len = len_len - 1;
+	}
+
+	for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) {
+		cbb->base->buf[cbb->offset + i] = len;
+		len >>= 8;
+	}
+	if (len != 0)
+		return 0;
+
+	cbb->child->base = NULL;
+	cbb->child = NULL;
+	cbb->pending_len_len = 0;
+	cbb->pending_is_asn1 = 0;
+	cbb->offset = 0;
+
+	return 1;
+}
+
+void
+CBB_discard_child(CBB *cbb)
+{
+	if (cbb->child == NULL)
+		return;
+
+	cbb->base->len = cbb->offset;
+
+	cbb->child->base = NULL;
+	cbb->child = NULL;
+	cbb->pending_len_len = 0;
+	cbb->pending_is_asn1 = 0;
+	cbb->offset = 0;
+}
+
+static int
+cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len)
+{
+	uint8_t *prefix_bytes;
+
+	if (!CBB_flush(cbb))
+		return 0;
+
+	cbb->offset = cbb->base->len;
+	if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len))
+		return 0;
+
+	memset(prefix_bytes, 0, len_len);
+	memset(out_contents, 0, sizeof(CBB));
+	out_contents->base = cbb->base;
+	cbb->child = out_contents;
+	cbb->pending_len_len = len_len;
+	cbb->pending_is_asn1 = 0;
+
+	return 1;
+}
+
+int
+CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents)
+{
+	return cbb_add_length_prefixed(cbb, out_contents, 1);
+}
+
+int
+CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents)
+{
+	return cbb_add_length_prefixed(cbb, out_contents, 2);
+}
+
+int
+CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents)
+{
+	return cbb_add_length_prefixed(cbb, out_contents, 3);
+}
+
+int
+CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag)
+{
+	if (tag > UINT8_MAX)
+		return 0;
+
+	/* Long form identifier octets are not supported. */
+	if ((tag & 0x1f) == 0x1f)
+		return 0;
+
+	/* Short-form identifier octet only needs a single byte */
+	if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag))
+		return 0;
+
+	/*
+	 * Add 1 byte to cover the short-form length octet case.  If it turns
+	 * out we need long-form, it will be extended later.
+	 */
+	cbb->offset = cbb->base->len;
+	if (!CBB_add_u8(cbb, 0))
+		return 0;
+
+	memset(out_contents, 0, sizeof(CBB));
+	out_contents->base = cbb->base;
+	cbb->child = out_contents;
+	cbb->pending_len_len = 1;
+	cbb->pending_is_asn1 = 1;
+
+	return 1;
+}
+
+int
+CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len)
+{
+	uint8_t *dest;
+
+	if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len))
+		return 0;
+
+	memcpy(dest, data, len);
+	return 1;
+}
+
+int
+CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len)
+{
+	if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len))
+		return 0;
+
+	memset(*out_data, 0, len);
+	return 1;
+}
+
+int
+CBB_add_u8(CBB *cbb, size_t value)
+{
+	if (value > UINT8_MAX)
+		return 0;
+
+	return cbb_add_u(cbb, (uint32_t)value, 1);
+}
+
+int
+CBB_add_u16(CBB *cbb, size_t value)
+{
+	if (value > UINT16_MAX)
+		return 0;
+
+	return cbb_add_u(cbb, (uint32_t)value, 2);
+}
+
+int
+CBB_add_u24(CBB *cbb, size_t value)
+{
+	if (value > 0xffffffUL)
+		return 0;
+
+	return cbb_add_u(cbb, (uint32_t)value, 3);
+}
+
+int
+CBB_add_u32(CBB *cbb, size_t value)
+{
+	if (value > 0xffffffffUL)
+		return 0;
+
+	return cbb_add_u(cbb, (uint32_t)value, 4);
+}
+
+int
+CBB_add_u64(CBB *cbb, uint64_t value)
+{
+	uint32_t a, b;
+
+	a = value >> 32;
+	b = value & 0xffffffff;
+
+	if (!CBB_add_u32(cbb, a))
+		return 0;
+	return CBB_add_u32(cbb, b);
+}
+
+int
+CBB_add_asn1_uint64(CBB *cbb, uint64_t value)
+{
+	CBB child;
+	size_t i;
+	int started = 0;
+
+	if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER))
+		return 0;
+
+	for (i = 0; i < 8; i++) {
+		uint8_t byte = (value >> 8 * (7 - i)) & 0xff;
+
+		/*
+		 * ASN.1 restriction: first 9 bits cannot be all zeroes or
+		 * all ones.  Since this function only encodes unsigned
+		 * integers, the only concerns are not encoding leading
+		 * zeros and adding a padding byte if necessary.
+		 *
+		 * In practice, this means:
+		 * 1) Skip leading octets of all zero bits in the value
+		 * 2) After skipping the leading zero octets, if the next 9
+		 *    bits are all ones, add an all zero prefix octet (and
+		 *    set the high bit of the prefix octet if negative).
+		 *
+		 * Additionally, for an unsigned value, add an all zero
+		 * prefix if the high bit of the first octet would be one.
+		 */
+		if (!started) {
+			if (byte == 0)
+				/* Don't encode leading zeros. */
+				continue;
+
+			/*
+			 * If the high bit is set, add a padding byte to make it
+			 * unsigned.
+			 */
+			if ((byte & 0x80) && !CBB_add_u8(&child, 0))
+				return 0;
+
+			started = 1;
+		}
+		if (!CBB_add_u8(&child, byte))
+			return 0;
+	}
+
+	/* 0 is encoded as a single 0, not the empty string. */
+	if (!started && !CBB_add_u8(&child, 0))
+		return 0;
+
+	return CBB_flush(cbb);
+}
diff --git a/crypto/bytestring/bs_cbs.c b/crypto/bytestring/bs_cbs.c
new file mode 100644
index 0000000..e2bb54e
--- /dev/null
+++ b/crypto/bytestring/bs_cbs.c
@@ -0,0 +1,615 @@
+/*	$OpenBSD: bs_cbs.c,v 1.2 2021/12/15 18:02:39 jsing Exp $	*/
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "bytestring.h"
+
+void
+CBS_init(CBS *cbs, const uint8_t *data, size_t len)
+{
+	cbs->data = data;
+	cbs->initial_len = len;
+	cbs->len = len;
+}
+
+void
+CBS_dup(const CBS *cbs, CBS *out)
+{
+	CBS_init(out, CBS_data(cbs), CBS_len(cbs));
+	out->initial_len = cbs->initial_len;
+}
+
+static int
+cbs_get(CBS *cbs, const uint8_t **p, size_t n)
+{
+	if (cbs->len < n)
+		return 0;
+
+	*p = cbs->data;
+	cbs->data += n;
+	cbs->len -= n;
+	return 1;
+}
+
+static int
+cbs_peek(CBS *cbs, const uint8_t **p, size_t n)
+{
+	if (cbs->len < n)
+		return 0;
+
+	*p = cbs->data;
+	return 1;
+}
+
+size_t
+CBS_offset(const CBS *cbs)
+{
+	return cbs->initial_len - cbs->len;
+}
+
+int
+CBS_skip(CBS *cbs, size_t len)
+{
+	const uint8_t *dummy;
+	return cbs_get(cbs, &dummy, len);
+}
+
+const uint8_t *
+CBS_data(const CBS *cbs)
+{
+	return cbs->data;
+}
+
+size_t
+CBS_len(const CBS *cbs)
+{
+	return cbs->len;
+}
+
+int
+CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len)
+{
+	free(*out_ptr);
+	*out_ptr = NULL;
+	*out_len = 0;
+
+	if (cbs->len == 0)
+		return 1;
+
+	if ((*out_ptr = malloc(cbs->len)) == NULL)
+		return 0;
+
+	memcpy(*out_ptr, cbs->data, cbs->len);
+
+	*out_len = cbs->len;
+	return 1;
+}
+
+int
+CBS_strdup(const CBS *cbs, char **out_ptr)
+{
+	free(*out_ptr);
+	*out_ptr = NULL;
+
+	if (CBS_contains_zero_byte(cbs))
+		return 0;
+
+	*out_ptr = strndup((const char *)cbs->data, cbs->len);
+	return (*out_ptr != NULL);
+}
+
+int
+CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied)
+{
+	if (dst_len < cbs->len)
+		return 0;
+
+	memmove(dst, cbs->data, cbs->len);
+
+	if (copied != NULL)
+		*copied = cbs->len;
+
+	return 1;
+}
+
+int
+CBS_contains_zero_byte(const CBS *cbs)
+{
+	return memchr(cbs->data, 0, cbs->len) != NULL;
+}
+
+int
+CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len)
+{
+	if (len != cbs->len)
+		return 0;
+
+	return timingsafe_memcmp(cbs->data, data, len) == 0;
+}
+
+static int
+cbs_get_u(CBS *cbs, uint32_t *out, size_t len)
+{
+	uint32_t result = 0;
+	size_t i;
+	const uint8_t *data;
+
+	if (len < 1 || len > 4)
+		return 0;
+
+	if (!cbs_get(cbs, &data, len))
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		result <<= 8;
+		result |= data[i];
+	}
+	*out = result;
+	return 1;
+}
+
+int
+CBS_get_u8(CBS *cbs, uint8_t *out)
+{
+	const uint8_t *v;
+
+	if (!cbs_get(cbs, &v, 1))
+		return 0;
+
+	*out = *v;
+	return 1;
+}
+
+int
+CBS_get_u16(CBS *cbs, uint16_t *out)
+{
+	uint32_t v;
+
+	if (!cbs_get_u(cbs, &v, 2))
+		return 0;
+
+	*out = v;
+	return 1;
+}
+
+int
+CBS_get_u24(CBS *cbs, uint32_t *out)
+{
+	return cbs_get_u(cbs, out, 3);
+}
+
+int
+CBS_get_u32(CBS *cbs, uint32_t *out)
+{
+	return cbs_get_u(cbs, out, 4);
+}
+
+int
+CBS_get_u64(CBS *cbs, uint64_t *out)
+{
+	uint32_t a, b;
+
+	if (cbs->len < 8)
+		return 0;
+
+	if (!CBS_get_u32(cbs, &a))
+		return 0;
+	if (!CBS_get_u32(cbs, &b))
+		return 0;
+
+	*out = (uint64_t)a << 32 | b;
+	return 1;
+}
+
+int
+CBS_get_last_u8(CBS *cbs, uint8_t *out)
+{
+	if (cbs->len == 0)
+		return 0;
+
+	*out = cbs->data[cbs->len - 1];
+	cbs->len--;
+	return 1;
+}
+
+int
+CBS_get_bytes(CBS *cbs, CBS *out, size_t len)
+{
+	const uint8_t *v;
+
+	if (!cbs_get(cbs, &v, len))
+		return 0;
+
+	CBS_init(out, v, len);
+	return 1;
+}
+
+static int
+cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len)
+{
+	uint32_t len;
+
+	if (!cbs_get_u(cbs, &len, len_len))
+		return 0;
+
+	return CBS_get_bytes(cbs, out, len);
+}
+
+int
+CBS_get_u8_length_prefixed(CBS *cbs, CBS *out)
+{
+	return cbs_get_length_prefixed(cbs, out, 1);
+}
+
+int
+CBS_get_u16_length_prefixed(CBS *cbs, CBS *out)
+{
+	return cbs_get_length_prefixed(cbs, out, 2);
+}
+
+int
+CBS_get_u24_length_prefixed(CBS *cbs, CBS *out)
+{
+	return cbs_get_length_prefixed(cbs, out, 3);
+}
+
+static int
+cbs_peek_u(CBS *cbs, uint32_t *out, size_t len)
+{
+	uint32_t result = 0;
+	size_t i;
+	const uint8_t *data;
+
+	if (len < 1 || len > 4)
+		return 0;
+
+	if (!cbs_peek(cbs, &data, len))
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		result <<= 8;
+		result |= data[i];
+	}
+	*out = result;
+	return 1;
+}
+
+int
+CBS_peek_u8(CBS *cbs, uint8_t *out)
+{
+	const uint8_t *v;
+
+	if (!cbs_peek(cbs, &v, 1))
+		return 0;
+
+	*out = *v;
+	return 1;
+}
+
+int
+CBS_peek_u16(CBS *cbs, uint16_t *out)
+{
+	uint32_t v;
+
+	if (!cbs_peek_u(cbs, &v, 2))
+		return 0;
+
+	*out = v;
+	return 1;
+}
+
+int
+CBS_peek_u24(CBS *cbs, uint32_t *out)
+{
+	return cbs_peek_u(cbs, out, 3);
+}
+
+int
+CBS_peek_u32(CBS *cbs, uint32_t *out)
+{
+	return cbs_peek_u(cbs, out, 4);
+}
+
+int
+CBS_peek_last_u8(CBS *cbs, uint8_t *out)
+{
+	if (cbs->len == 0)
+		return 0;
+
+	*out = cbs->data[cbs->len - 1];
+	return 1;
+}
+
+int
+CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
+    size_t *out_header_len)
+{
+	return cbs_get_any_asn1_element_internal(cbs, out, out_tag,
+	    out_header_len, 1);
+}
+
+/*
+ * Review X.690 for details on ASN.1 DER encoding.
+ *
+ * If non-strict mode is enabled, then DER rules are relaxed
+ * for indefinite constructs (violates DER but a little closer to BER).
+ * Non-strict mode should only be used by bs_ber.c
+ *
+ * Sections 8, 10 and 11 for DER encoding
+ */
+int
+cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag,
+    size_t *out_header_len, int strict)
+{
+	uint8_t tag, length_byte;
+	CBS header = *cbs;
+	CBS throwaway;
+	size_t len;
+
+	if (out == NULL)
+		out = &throwaway;
+
+	/*
+	 * Get identifier octet and length octet.  Only 1 octet for each
+	 * is a CBS limitation.
+	 */
+	if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte))
+		return 0;
+
+	/* CBS limitation: long form tags are not supported. */
+	if ((tag & 0x1f) == 0x1f)
+		return 0;
+
+	if (out_tag != NULL)
+		*out_tag = tag;
+
+	if ((length_byte & 0x80) == 0) {
+		/* Short form length. */
+		len = ((size_t) length_byte) + 2;
+		if (out_header_len != NULL)
+			*out_header_len = 2;
+
+	} else {
+		/* Long form length. */
+		const size_t num_bytes = length_byte & 0x7f;
+		uint32_t len32;
+
+		/* ASN.1 reserved value for future extensions */
+		if (num_bytes == 0x7f)
+			return 0;
+
+		/* Handle indefinite form length */
+		if (num_bytes == 0) {
+			/* DER encoding doesn't allow for indefinite form. */
+			if (strict)
+				return 0;
+
+			/* Primitive cannot use indefinite in BER or DER. */
+			if ((tag & CBS_ASN1_CONSTRUCTED) == 0)
+				return 0;
+
+			/* Constructed, indefinite length allowed in BER. */
+			if (out_header_len != NULL)
+				*out_header_len = 2;
+			return CBS_get_bytes(cbs, out, 2);
+		}
+
+		/* CBS limitation. */
+		if (num_bytes > 4)
+			return 0;
+
+		if (!cbs_get_u(&header, &len32, num_bytes))
+			return 0;
+
+		/* DER has a minimum length octet requirement. */
+		if (len32 < 128)
+			/* Should have used short form instead */
+			return 0;
+
+		if ((len32 >> ((num_bytes - 1) * 8)) == 0)
+			/* Length should have been at least one byte shorter. */
+			return 0;
+
+		len = len32;
+		if (len + 2 + num_bytes < len)
+			/* Overflow. */
+			return 0;
+
+		len += 2 + num_bytes;
+		if (out_header_len != NULL)
+			*out_header_len = 2 + num_bytes;
+	}
+
+	return CBS_get_bytes(cbs, out, len);
+}
+
+static int
+cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header)
+{
+	size_t header_len;
+	unsigned int tag;
+	CBS throwaway;
+
+	if (out == NULL)
+		out = &throwaway;
+
+	if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
+	    tag != tag_value)
+		return 0;
+
+	if (skip_header && !CBS_skip(out, header_len))
+		return 0;
+
+	return 1;
+}
+
+int
+CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value)
+{
+	return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
+}
+
+int
+CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value)
+{
+	return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
+}
+
+int
+CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value)
+{
+	if (CBS_len(cbs) < 1)
+		return 0;
+
+	/*
+	 * Tag number 31 indicates the start of a long form number.
+	 * This is valid in ASN.1, but CBS only supports short form.
+	 */
+	if ((tag_value & 0x1f) == 0x1f)
+		return 0;
+
+	return CBS_data(cbs)[0] == tag_value;
+}
+
+/* Encoding details are in ASN.1: X.690 section 8.3 */
+int
+CBS_get_asn1_uint64(CBS *cbs, uint64_t *out)
+{
+	CBS bytes;
+	const uint8_t *data;
+	size_t i, len;
+
+	if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER))
+		return 0;
+
+	*out = 0;
+	data = CBS_data(&bytes);
+	len = CBS_len(&bytes);
+
+	if (len == 0)
+		/* An INTEGER is encoded with at least one content octet. */
+		return 0;
+
+	if ((data[0] & 0x80) != 0)
+		/* Negative number. */
+		return 0;
+
+	if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0)
+		/* Violates smallest encoding rule: excessive leading zeros. */
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		if ((*out >> 56) != 0)
+			/* Too large to represent as a uint64_t. */
+			return 0;
+
+		*out <<= 8;
+		*out |= data[i];
+	}
+
+	return 1;
+}
+
+int
+CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag)
+{
+	if (CBS_peek_asn1_tag(cbs, tag)) {
+		if (!CBS_get_asn1(cbs, out, tag))
+			return 0;
+
+		*out_present = 1;
+	} else {
+		*out_present = 0;
+	}
+	return 1;
+}
+
+int
+CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
+    unsigned int tag)
+{
+	CBS child;
+	int present;
+
+	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
+		return 0;
+
+	if (present) {
+		if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
+		    CBS_len(&child) != 0)
+			return 0;
+	} else {
+		CBS_init(out, NULL, 0);
+	}
+	if (out_present)
+		*out_present = present;
+
+	return 1;
+}
+
+int
+CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag,
+    uint64_t default_value)
+{
+	CBS child;
+	int present;
+
+	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
+		return 0;
+
+	if (present) {
+		if (!CBS_get_asn1_uint64(&child, out) ||
+		    CBS_len(&child) != 0)
+			return 0;
+	} else {
+		*out = default_value;
+	}
+	return 1;
+}
+
+int
+CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag,
+    int default_value)
+{
+	CBS child, child2;
+	int present;
+
+	if (!CBS_get_optional_asn1(cbs, &child, &present, tag))
+		return 0;
+
+	if (present) {
+		uint8_t boolean;
+
+		if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
+		    CBS_len(&child2) != 1 || CBS_len(&child) != 0)
+			return 0;
+
+		boolean = CBS_data(&child2)[0];
+		if (boolean == 0)
+			*out = 0;
+		else if (boolean == 0xff)
+			*out = 1;
+		else
+			return 0;
+
+	} else {
+		*out = default_value;
+	}
+	return 1;
+}
diff --git a/crypto/bytestring/bytestring.h b/crypto/bytestring/bytestring.h
new file mode 100644
index 0000000..d80e89c
--- /dev/null
+++ b/crypto/bytestring/bytestring.h
@@ -0,0 +1,564 @@
+/*	$OpenBSD: bytestring.h,v 1.4 2022/11/09 19:05:42 jsing Exp $	*/
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef OPENSSL_HEADER_BYTESTRING_H
+#define OPENSSL_HEADER_BYTESTRING_H
+
+#include 
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+/*
+ * Bytestrings are used for parsing and building TLS and ASN.1 messages.
+ *
+ * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and
+ * provides utility functions for safely parsing length-prefixed structures
+ * like TLS and ASN.1 from it.
+ *
+ * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and
+ * provides utility functions for building length-prefixed messages.
+ */
+
+/* CRYPTO ByteString */
+typedef struct cbs_st {
+	const uint8_t *data;
+	size_t initial_len;
+	size_t len;
+} CBS;
+
+/*
+ * CBS_init sets |cbs| to point to |data|. It does not take ownership of
+ * |data|.
+ */
+void CBS_init(CBS *cbs, const uint8_t *data, size_t len);
+
+/*
+ * CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero
+ * otherwise.
+ */
+int CBS_skip(CBS *cbs, size_t len);
+
+/*
+ * CBS_data returns a pointer to the contents of |cbs|.
+ */
+const uint8_t *CBS_data(const CBS *cbs);
+
+/*
+ * CBS_len returns the number of bytes remaining in |cbs|.
+ */
+size_t CBS_len(const CBS *cbs);
+
+/*
+ * CBS_offset returns the current offset into the original data of |cbs|.
+ */
+size_t CBS_offset(const CBS *cbs);
+
+/*
+ * CBS_stow copies the current contents of |cbs| into |*out_ptr| and
+ * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with
+ * free. It returns one on success and zero on allocation failure. On
+ * success, |*out_ptr| should be freed with free. If |cbs| is empty,
+ * |*out_ptr| will be NULL.
+ */
+int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len);
+
+/*
+ * CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a
+ * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed
+ * with free. It returns one on success and zero on failure. On success,
+ * |*out_ptr| should be freed with free. If |cbs| contains NUL bytes,
+ * CBS_strdup will fail.
+ */
+int CBS_strdup(const CBS *cbs, char **out_ptr);
+
+/*
+ * CBS_write_bytes writes all of the remaining data from |cbs| into |dst|
+ * if it is at most |dst_len| bytes.  If |copied| is not NULL, it will be set
+ * to the amount copied. It returns one on success and zero otherwise.
+ */
+int CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len,
+    size_t *copied);
+
+/*
+ * CBS_contains_zero_byte returns one if the current contents of |cbs| contains
+ * a NUL byte and zero otherwise.
+ */
+int CBS_contains_zero_byte(const CBS *cbs);
+
+/*
+ * CBS_mem_equal compares the current contents of |cbs| with the |len| bytes
+ * starting at |data|. If they're equal, it returns one, otherwise zero. If the
+ * lengths match, it uses a constant-time comparison.
+ */
+int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len);
+
+/*
+ * CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It
+ * returns one on success and zero on error.
+ */
+int CBS_get_u8(CBS *cbs, uint8_t *out);
+
+/*
+ * CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and
+ * advances |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_u16(CBS *cbs, uint16_t *out);
+
+/*
+ * CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and
+ * advances |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_u24(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|
+ * and advances |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_u32(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs|
+ * and advances |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_u64(CBS *cbs, uint64_t *out);
+
+/*
+ * CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens
+ * |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_last_u8(CBS *cbs, uint8_t *out);
+
+/*
+ * CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances
+ * |cbs|. It returns one on success and zero on error.
+ */
+int CBS_get_bytes(CBS *cbs, CBS *out, size_t len);
+
+/*
+ * CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit,
+ * length-prefixed value from |cbs| and advances |cbs| over it. It returns one
+ * on success and zero on error.
+ */
+int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out);
+
+/*
+ * CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit,
+ * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
+ * returns one on success and zero on error.
+ */
+int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out);
+
+/*
+ * CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit,
+ * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It
+ * returns one on success and zero on error.
+ */
+int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out);
+
+/*
+ * CBS_peek_u8 sets |*out| to the next uint8_t from |cbs|, but does not advance
+ * |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u8(CBS *cbs, uint8_t *out);
+
+/*
+ * CBS_peek_u16 sets |*out| to the next, big-endian uint16_t from |cbs|, but
+ * does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u16(CBS *cbs, uint16_t *out);
+
+/*
+ * CBS_peek_u24 sets |*out| to the next, big-endian 24-bit value from |cbs|, but
+ * does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u24(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_peek_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|,
+ * but does not advance |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_u32(CBS *cbs, uint32_t *out);
+
+/*
+ * CBS_peek_last_u8 sets |*out| to the last uint8_t from |cbs|, but does not
+ * shorten |cbs|. It returns one on success and zero on error.
+ */
+int CBS_peek_last_u8(CBS *cbs, uint8_t *out);
+
+
+/* Parsing ASN.1 */
+
+/*
+ * While an identifier can be multiple octets, this library only handles the
+ * single octet variety currently.  This limits support up to tag number 30
+ * since tag number 31 is a reserved value to indicate multiple octets.
+ */
+
+/* Bits 8 and 7: class tag type: See X.690 section 8.1.2.2. */
+#define CBS_ASN1_UNIVERSAL		0x00
+#define CBS_ASN1_APPLICATION		0x40
+#define CBS_ASN1_CONTEXT_SPECIFIC	0x80
+#define CBS_ASN1_PRIVATE		0xc0
+
+/* Bit 6: Primitive or constructed: See X.690 section 8.1.2.3. */
+#define CBS_ASN1_PRIMITIVE	0x00
+#define CBS_ASN1_CONSTRUCTED	0x20
+
+/*
+ * Bits 5 to 1 are the tag number.  See X.680 section 8.6 for tag numbers of
+ * the universal class.
+ */
+
+/*
+ * Common universal identifier octets.
+ * See X.690 section 8.1 and X.680 section 8.6 for universal tag numbers.
+ *
+ * Note: These definitions are the cause of some of the strange behavior in
+ * CBS's bs_ber.c.
+ *
+ * In BER, it is the sender's option to use primitive or constructed for
+ * bitstring (X.690 section 8.6.1) and octetstring (X.690 section 8.7.1).
+ *
+ * In DER, bitstring and octetstring are required to be primitive
+ * (X.690 section 10.2).
+ */
+#define CBS_ASN1_BOOLEAN     (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x1)
+#define CBS_ASN1_INTEGER     (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x2)
+#define CBS_ASN1_BITSTRING   (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x3)
+#define CBS_ASN1_OCTETSTRING (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x4)
+#define CBS_ASN1_OBJECT      (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x6)
+#define CBS_ASN1_ENUMERATED  (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0xa)
+#define CBS_ASN1_SEQUENCE    (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x10)
+#define CBS_ASN1_SET         (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x11)
+
+/*
+ * CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
+ * including tag and length bytes) and advances |cbs| over it. The ASN.1
+ * element must match |tag_value|. It returns one on success and zero
+ * on error.
+ *
+ * Tag numbers greater than 30 are not supported (i.e. short form only).
+ */
+int CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value);
+
+/*
+ * CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the
+ * ASN.1 header bytes too.
+ */
+int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value);
+
+/*
+ * CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one
+ * if the next ASN.1 element on |cbs| would have tag |tag_value|. If
+ * |cbs| is empty or the tag does not match, it returns zero. Note: if
+ * it returns one, CBS_get_asn1 may still fail if the rest of the
+ * element is malformed.
+ */
+int CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value);
+
+/*
+ * CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
+ * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
+ * the tag number and |*out_header_len| to the length of the ASN.1 header.
+ * Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore
+ * the value.
+ *
+ * Tag numbers greater than 30 are not supported (i.e. short form only).
+ */
+int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag,
+    size_t *out_header_len);
+
+/*
+ * CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1|
+ * and sets |*out| to its value. It returns one on success and zero on error,
+ * where error includes the integer being negative, or too large to represent
+ * in 64 bits.
+ */
+int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
+
+/*
+ * CBS_get_optional_asn1 gets an optional explicitly-tagged element
+ * from |cbs| tagged with |tag| and sets |*out| to its contents. If
+ * present, it sets |*out_present| to one, otherwise zero. It returns
+ * one on success, whether or not the element was present, and zero on
+ * decode failure.
+ */
+int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present,
+    unsigned int tag);
+
+/*
+ * CBS_get_optional_asn1_octet_string gets an optional
+ * explicitly-tagged OCTET STRING from |cbs|. If present, it sets
+ * |*out| to the string and |*out_present| to one. Otherwise, it sets
+ * |*out| to empty and |*out_present| to zero. |out_present| may be
+ * NULL. It returns one on success, whether or not the element was
+ * present, and zero on decode failure.
+ */
+int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
+    unsigned int tag);
+
+/*
+ * CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged
+ * INTEGER from |cbs|. If present, it sets |*out| to the
+ * value. Otherwise, it sets |*out| to |default_value|. It returns one
+ * on success, whether or not the element was present, and zero on
+ * decode failure.
+ */
+int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag,
+    uint64_t default_value);
+
+/*
+ * CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from
+ * |cbs|. If present, it sets |*out| to either zero or one, based on the
+ * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on
+ * success, whether or not the element was present, and zero on decode
+ * failure.
+ */
+int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag,
+    int default_value);
+
+
+/*
+ * CRYPTO ByteBuilder.
+ *
+ * |CBB| objects allow one to build length-prefixed serialisations. A |CBB|
+ * object is associated with a buffer and new buffers are created with
+ * |CBB_init|. Several |CBB| objects can point at the same buffer when a
+ * length-prefix is pending, however only a single |CBB| can be 'current' at
+ * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then
+ * the new |CBB| points at the same buffer as the original. But if the original
+ * |CBB| is used then the length prefix is written out and the new |CBB| must
+ * not be used again.
+ *
+ * If one needs to force a length prefix to be written out because a |CBB| is
+ * going out of scope, use |CBB_flush|.
+ */
+
+struct cbb_buffer_st {
+	uint8_t *buf;
+
+	/* The number of valid bytes. */
+	size_t len;
+
+	/* The size of buf. */
+	size_t cap;
+
+	/*
+	 * One iff |buf| is owned by this object. If not then |buf| cannot be
+	 * resized.
+	 */
+	char can_resize;
+};
+
+typedef struct cbb_st {
+	struct cbb_buffer_st *base;
+
+	/*
+	 * offset is the offset from the start of |base->buf| to the position of any
+	 * pending length-prefix.
+	 */
+	size_t offset;
+
+	/* child points to a child CBB if a length-prefix is pending. */
+	struct cbb_st *child;
+
+	/*
+	 * pending_len_len contains the number of bytes in a pending length-prefix,
+	 * or zero if no length-prefix is pending.
+	 */
+	uint8_t pending_len_len;
+
+	char pending_is_asn1;
+
+	/*
+	 * is_top_level is true iff this is a top-level |CBB| (as opposed to a child
+	 * |CBB|). Top-level objects are valid arguments for |CBB_finish|.
+	 */
+	char is_top_level;
+} CBB;
+
+/*
+ * CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as
+ * needed, the |initial_capacity| is just a hint. It returns one on success or
+ * zero on error.
+ */
+int CBB_init(CBB *cbb, size_t initial_capacity);
+
+/*
+ * CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since
+ * |buf| cannot grow, trying to write more than |len| bytes will cause CBB
+ * functions to fail. It returns one on success or zero on error.
+ */
+int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len);
+
+/*
+ * CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects
+ * writing to the same buffer. This should be used in an error case where a
+ * serialisation is abandoned.
+ */
+void CBB_cleanup(CBB *cbb);
+
+/*
+ * CBB_finish completes any pending length prefix and sets |*out_data| to a
+ * malloced buffer and |*out_len| to the length of that buffer. The caller
+ * takes ownership of the buffer and, unless the buffer was fixed with
+ * |CBB_init_fixed|, must call |free| when done.
+ *
+ * It can only be called on a "top level" |CBB|, i.e. one initialised with
+ * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on
+ * error.
+ */
+int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len);
+
+/*
+ * CBB_flush causes any pending length prefixes to be written out and any child
+ * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero
+ * on error.
+ */
+int CBB_flush(CBB *cbb);
+
+/*
+ * CBB_discard_child discards the current unflushed child of |cbb|. Neither the
+ * child's contents nor the length prefix will be included in the output.
+ */
+void CBB_discard_child(CBB *cbb);
+
+/*
+ * CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The
+ * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit
+ * length. It returns one on success or zero on error.
+ */
+int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents);
+
+/*
+ * CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|.
+ * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit,
+ * big-endian length. It returns one on success or zero on error.
+ */
+int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents);
+
+/*
+ * CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|.
+ * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit,
+ * big-endian length. It returns one on success or zero on error.
+ */
+int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents);
+
+/*
+ * CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an
+ * ASN.1 object can be written. The |tag| argument will be used as the tag for
+ * the object. Passing in |tag| number 31 will return in an error since only
+ * single octet identifiers are supported. It returns one on success or zero
+ * on error.
+ */
+int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag);
+
+/*
+ * CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
+ * success and zero otherwise.
+ */
+int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len);
+
+/*
+ * CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to
+ * the beginning of that space. The caller must then write |len| bytes of
+ * actual contents to |*out_data|. It returns one on success and zero
+ * otherwise.
+ */
+int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len);
+
+/*
+ * CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on
+ * success and zero otherwise.
+ */
+int CBB_add_u8(CBB *cbb, size_t value);
+
+/*
+ * CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise.
+ */
+int CBB_add_u16(CBB *cbb, size_t value);
+
+/*
+ * CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise.
+ */
+int CBB_add_u24(CBB *cbb, size_t value);
+
+/*
+ * CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise.
+ */
+int CBB_add_u32(CBB *cbb, size_t value);
+
+/*
+ * CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise.
+ */
+int CBB_add_u64(CBB *cbb, uint64_t value);
+
+/*
+ * CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1|
+ * and writes |value| in its contents. It returns one on success and zero on
+ * error.
+ */
+int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
+
+#ifdef LIBRESSL_INTERNAL
+/*
+ * CBS_dup sets |out| to point to cbs's |data| and |len|.  It results in two
+ * CBS that point to the same buffer.
+ */
+void CBS_dup(const CBS *cbs, CBS *out);
+
+/*
+ * cbs_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
+ * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
+ * the tag number and |*out_header_len| to the length of the ASN.1 header. If
+ * strict mode is disabled and the element has indefinite length then |*out|
+ * will only contain the header. Each of |out|, |out_tag|, and
+ * |out_header_len| may be NULL to ignore the value.
+ *
+ * Tag numbers greater than 30 are not supported (i.e. short form only).
+ */
+int cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag,
+    size_t *out_header_len, int strict);
+
+/*
+ * CBS_asn1_indefinite_to_definite reads an ASN.1 structure from |in|. If it
+ * finds indefinite-length elements that otherwise appear to be valid DER, it
+ * attempts to convert the DER-like data to DER and sets |*out| and
+ * |*out_length| to describe a malloced buffer containing the DER data.
+ * Additionally, |*in| will be advanced over the ASN.1 data.
+ *
+ * If it doesn't find any indefinite-length elements then it sets |*out| to
+ * NULL and |*in| is unmodified.
+ *
+ * This is NOT a conversion from BER to DER.  There are many restrictions when
+ * dealing with DER data.  This is only concerned with one: indefinite vs.
+ * definite form. However, this suffices to handle the PKCS#7 and PKCS#12 output
+ * from NSS.
+ *
+ * It returns one on success and zero otherwise.
+ */
+int CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len);
+#endif /* LIBRESSL_INTERNAL */
+
+__END_HIDDEN_DECLS 
+
+#endif  /* OPENSSL_HEADER_BYTESTRING_H */
diff --git a/crypto/camellia/camellia.c b/crypto/camellia/camellia.c
new file mode 100644
index 0000000..336074a
--- /dev/null
+++ b/crypto/camellia/camellia.c
@@ -0,0 +1,566 @@
+/* $OpenBSD: camellia.c,v 1.12 2022/11/26 16:08:51 tb Exp $ */
+/* ====================================================================
+ * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . 
+ * ALL RIGHTS RESERVED.
+ *
+ * Intellectual Property information for Camellia:
+ *     http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html
+ *
+ * News Release for Announcement of Camellia open source:
+ *     http://www.ntt.co.jp/news/news06e/0604/060413a.html
+ *
+ * The Camellia Code included herein is developed by
+ * NTT (Nippon Telegraph and Telephone Corporation), and is contributed
+ * to the OpenSSL project.
+ *
+ * The Camellia Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+/*
+ * Algorithm Specification
+ * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html
+ */
+
+/*
+ * This release balances code size and performance. In particular key
+ * schedule setup is fully unrolled, because doing so *significantly*
+ * reduces amount of instructions per setup round and code increase is
+ * justifiable. In block functions on the other hand only inner loops
+ * are unrolled, as full unroll gives only nominal performance boost,
+ * while code size grows 4 or 7 times. Also, unlike previous versions
+ * this one "encourages" compiler to keep intermediate variables in
+ * registers, which should give better "all round" results, in other
+ * words reasonable performance even with not so modern compilers.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "cmll_local.h"
+
+/* 32-bit rotations */
+#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
+# if defined(__GNUC__) && __GNUC__>=2
+#  if defined(__i386) || defined(__x86_64)
+#   define RightRotate(x,s) ({u32 ret; asm ("rorl %1,%0":"=r"(ret):"I"(s),"0"(x):"cc"); ret; })
+#   define LeftRotate(x,s)  ({u32 ret; asm ("roll %1,%0":"=r"(ret):"I"(s),"0"(x):"cc"); ret; })
+#   define GETU32(p)   ({u32 r=*(const u32 *)(p); asm("bswapl %0":"=r"(r):"0"(r)); r; })
+#   define PUTU32(p,v) ({u32 r=(v); asm("bswapl %0":"=r"(r):"0"(r)); *(u32 *)(p)=r; })
+#  elif defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
+        defined(__powerpc) || defined(__ppc__) || defined(__powerpc64__)
+#   define LeftRotate(x,s)  ({u32 ret; asm ("rlwinm %0,%1,%2,0,31":"=r"(ret):"r"(x),"I"(s)); ret; })
+#   define RightRotate(x,s) LeftRotate(x,(32-s))
+#  endif
+# endif
+#endif
+
+#if !defined(RightRotate) && !defined(LeftRotate)
+# define RightRotate(x, s) ( ((x) >> (s)) + ((x) << (32 - s)) )
+# define LeftRotate(x, s)  ( ((x) << (s)) + ((x) >> (32 - s)) )
+#endif
+
+#if !defined(GETU32) && !defined(PUTU32)
+# 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
+
+/* S-box data */
+#define SBOX1_1110 Camellia_SBOX[0]
+#define SBOX4_4404 Camellia_SBOX[1]
+#define SBOX2_0222 Camellia_SBOX[2]
+#define SBOX3_3033 Camellia_SBOX[3]
+static const u32 Camellia_SBOX[][256] = {
+{   0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
+    0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
+    0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
+    0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
+    0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
+    0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
+    0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
+    0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
+    0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
+    0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
+    0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
+    0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
+    0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
+    0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
+    0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
+    0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
+    0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
+    0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
+    0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
+    0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
+    0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
+    0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
+    0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
+    0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
+    0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
+    0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
+    0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
+    0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
+    0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
+    0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
+    0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
+    0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
+    0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
+    0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
+    0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
+    0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
+    0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
+    0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
+    0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
+    0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
+    0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
+    0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
+    0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00 },
+{   0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
+    0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
+    0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
+    0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
+    0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
+    0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
+    0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
+    0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
+    0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
+    0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
+    0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
+    0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
+    0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
+    0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
+    0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
+    0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
+    0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
+    0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
+    0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
+    0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
+    0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
+    0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
+    0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
+    0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
+    0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
+    0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
+    0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
+    0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
+    0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
+    0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
+    0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
+    0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
+    0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
+    0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
+    0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
+    0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
+    0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
+    0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
+    0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
+    0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
+    0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
+    0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
+    0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e },
+{   0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
+    0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
+    0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
+    0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
+    0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
+    0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
+    0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
+    0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
+    0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
+    0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
+    0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
+    0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
+    0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
+    0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
+    0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
+    0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
+    0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
+    0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
+    0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
+    0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
+    0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
+    0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
+    0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
+    0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
+    0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
+    0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
+    0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
+    0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
+    0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
+    0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
+    0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
+    0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
+    0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
+    0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
+    0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
+    0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
+    0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
+    0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
+    0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
+    0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
+    0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
+    0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
+    0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d },
+{   0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
+    0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
+    0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
+    0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
+    0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
+    0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
+    0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
+    0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
+    0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
+    0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
+    0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
+    0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
+    0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
+    0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
+    0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
+    0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
+    0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
+    0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
+    0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
+    0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
+    0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
+    0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
+    0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
+    0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
+    0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
+    0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
+    0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
+    0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
+    0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
+    0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
+    0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
+    0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
+    0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
+    0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
+    0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
+    0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
+    0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
+    0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
+    0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
+    0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
+    0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
+    0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
+    0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f }
+};
+
+/* Key generation constants */
+static const u32 SIGMA[] = {
+    0xa09e667f, 0x3bcc908b, 0xb67ae858, 0x4caa73b2, 0xc6ef372f, 0xe94f82be,
+    0x54ff53a5, 0xf1d36f1c, 0x10e527fa, 0xde682d1d, 0xb05688c2, 0xb3e6c1fd
+};
+
+/* The phi algorithm given in C.2.7 of the Camellia spec document. */
+/*
+ * This version does not attempt to minimize amount of temporary
+ * variables, but instead explicitly exposes algorithm's parallelism.
+ * It is therefore most appropriate for platforms with not less than
+ * ~16 registers. For platforms with fewer registers [well, x86 to be
+ * specific] assembler version should be/is provided anyway...
+ */
+#define Camellia_Feistel(_s0,_s1,_s2,_s3,_key) \
+do { \
+	u32 _t0, _t1, _t2, _t3; \
+	_t0 = _s0 ^ (_key)[0]; \
+	_t3 = SBOX4_4404[_t0 & 0xff]; \
+	_t1 = _s1 ^ (_key)[1]; \
+	_t3 ^= SBOX3_3033[(_t0 >> 8) & 0xff]; \
+	_t2 = SBOX1_1110[_t1 & 0xff]; \
+	_t3 ^= SBOX2_0222[(_t0 >> 16) & 0xff]; \
+	_t2 ^= SBOX4_4404[(_t1 >> 8) & 0xff]; \
+	_t3 ^= SBOX1_1110[(_t0 >> 24)]; \
+	_t2 ^= _t3; \
+	_t3 = RightRotate(_t3, 8); \
+	_t2 ^= SBOX3_3033[(_t1 >> 16) & 0xff]; \
+	_s3 ^= _t3; \
+	_t2 ^= SBOX2_0222[(_t1 >> 24)]; \
+	_s2 ^= _t2; \
+	_s3 ^= _t2; \
+} while(0)
+
+/*
+ * Note that n has to be less than 32. Rotations for larger amount
+ * of bits are achieved by "rotating" order of s-elements and
+ * adjusting n accordingly, e.g. RotLeft128(s1, s2, s3, s0, n - 32).
+ */
+#define RotLeft128(_s0, _s1, _s2, _s3, _n) \
+do { \
+	u32 _t0 = _s0 >> (32 - _n); \
+	_s0 = (_s0 << _n) | (_s1 >> (32 - _n)); \
+	_s1 = (_s1 << _n) | (_s2 >> (32 - _n)); \
+	_s2 = (_s2 << _n) | (_s3 >> (32 - _n)); \
+	_s3 = (_s3 << _n) | _t0; \
+} while (0)
+
+int
+Camellia_Ekeygen(int keyBitLength, const u8 *rawKey, KEY_TABLE_TYPE k)
+{
+	u32 s0, s1, s2, s3;
+
+	k[0] = s0 = GETU32(rawKey);
+	k[1] = s1 = GETU32(rawKey + 4);
+	k[2] = s2 = GETU32(rawKey + 8);
+	k[3] = s3 = GETU32(rawKey + 12);
+
+	if (keyBitLength != 128) {
+		k[8] = s0 = GETU32(rawKey + 16);
+		k[9] = s1 = GETU32(rawKey + 20);
+		if (keyBitLength == 192) {
+			k[10] = s2 = ~s0;
+			k[11] = s3 = ~s1;
+		} else {
+			k[10] = s2 = GETU32(rawKey + 24);
+			k[11] = s3 = GETU32(rawKey + 28);
+		}
+		s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3];
+	}
+
+	/* Use the Feistel routine to scramble the key material */
+	Camellia_Feistel(s0, s1, s2, s3, SIGMA + 0);
+	Camellia_Feistel(s2, s3, s0, s1, SIGMA + 2);
+
+	s0 ^= k[0], s1 ^= k[1], s2 ^= k[2], s3 ^= k[3];
+	Camellia_Feistel(s0, s1, s2, s3, SIGMA + 4);
+	Camellia_Feistel(s2, s3, s0, s1, SIGMA + 6);
+
+	/* Fill the keyTable. Requires many block rotations. */
+	if (keyBitLength == 128) {
+		k[ 4] = s0, k[ 5] = s1, k[ 6] = s2, k[ 7] = s3;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KA <<< 15 */
+		k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KA <<< 30 */
+		k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KA <<< 45 */
+		k[24] = s0, k[25] = s1;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KA <<< 60 */
+		k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3;
+		RotLeft128(s1, s2, s3, s0, 2);	/* KA <<< 94 */
+		k[40] = s1, k[41] = s2, k[42] = s3, k[43] = s0;
+		RotLeft128(s1, s2, s3, s0, 17);	/* KA <<<111 */
+		k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0;
+
+		s0 = k[ 0], s1 = k[ 1], s2 = k[ 2], s3 = k[ 3];
+		RotLeft128(s0, s1, s2, s3, 15);	/* KL <<< 15 */
+		k[ 8] = s0, k[ 9] = s1, k[10] = s2, k[11] = s3;
+		RotLeft128(s0, s1, s2, s3, 30);	/* KL <<< 45 */
+		k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KL <<< 60 */
+		k[26] = s2, k[27] = s3;
+		RotLeft128(s0, s1, s2, s3, 17);	/* KL <<< 77 */
+		k[32] = s0, k[33] = s1, k[34] = s2, k[35] = s3;
+		RotLeft128(s0, s1, s2, s3, 17);	/* KL <<< 94 */
+		k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3;
+		RotLeft128(s0, s1, s2, s3, 17);	/* KL <<<111 */
+		k[44] = s0, k[45] = s1, k[46] = s2, k[47] = s3;
+
+		return 3;	/* grand rounds */
+	} else {
+		k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
+		s0 ^= k[8], s1 ^= k[9], s2 ^=k[10], s3 ^=k[11];
+		Camellia_Feistel(s0, s1, s2, s3, (SIGMA + 8));
+		Camellia_Feistel(s2, s3, s0, s1, (SIGMA + 10));
+
+		k[ 4] = s0, k[ 5] = s1, k[ 6] = s2, k[ 7] = s3;
+		RotLeft128(s0, s1, s2, s3, 30);	/* KB <<< 30 */
+		k[20] = s0, k[21] = s1, k[22] = s2, k[23] = s3;
+		RotLeft128(s0, s1, s2, s3, 30);	/* KB <<< 60 */
+		k[40] = s0, k[41] = s1, k[42] = s2, k[43] = s3;
+		RotLeft128(s1, s2, s3, s0, 19);	/* KB <<<111 */
+		k[64] = s1, k[65] = s2, k[66] = s3, k[67] = s0;
+
+		s0 = k[ 8], s1 = k[ 9], s2 = k[10], s3 = k[11];
+		RotLeft128(s0, s1, s2, s3, 15);	/* KR <<< 15 */
+		k[ 8] = s0, k[ 9] = s1, k[10] = s2, k[11] = s3;
+		RotLeft128(s0, s1, s2, s3, 15);	/* KR <<< 30 */
+		k[16] = s0, k[17] = s1, k[18] = s2, k[19] = s3;
+		RotLeft128(s0, s1, s2, s3, 30);	/* KR <<< 60 */
+		k[36] = s0, k[37] = s1, k[38] = s2, k[39] = s3;
+		RotLeft128(s1, s2, s3, s0, 2);	/* KR <<< 94 */
+		k[52] = s1, k[53] = s2, k[54] = s3, k[55] = s0;
+
+		s0 = k[12], s1 = k[13], s2 = k[14], s3 = k[15];
+		RotLeft128(s0, s1, s2, s3, 15);	/* KA <<< 15 */
+		k[12] = s0, k[13] = s1, k[14] = s2, k[15] = s3;
+		RotLeft128(s0, s1, s2, s3, 30);	/* KA <<< 45 */
+		k[28] = s0, k[29] = s1, k[30] = s2, k[31] = s3;
+						/* KA <<< 77 */
+		k[48] = s1, k[49] = s2, k[50] = s3, k[51] = s0;
+		RotLeft128(s1, s2, s3, s0, 17);	/* KA <<< 94 */
+		k[56] = s1, k[57] = s2, k[58] = s3, k[59] = s0;
+
+		s0 = k[ 0], s1 = k[ 1], s2 = k[ 2], s3 = k[ 3];
+		RotLeft128(s1, s2, s3, s0, 13);	/* KL <<< 45 */
+		k[24] = s1, k[25] = s2, k[26] = s3, k[27] = s0;
+		RotLeft128(s1, s2, s3, s0, 15);	/* KL <<< 60 */
+		k[32] = s1, k[33] = s2, k[34] = s3, k[35] = s0;
+		RotLeft128(s1, s2, s3, s0, 17);	/* KL <<< 77 */
+		k[44] = s1, k[45] = s2, k[46] = s3, k[47] = s0;
+		RotLeft128(s2, s3, s0, s1, 2);	/* KL <<<111 */
+		k[60] = s2, k[61] = s3, k[62] = s0, k[63] = s1;
+
+		return 4;	/* grand rounds */
+	}
+	/*
+	 * It is possible to perform certain precalculations, which
+	 * would spare few cycles in block procedure. It's not done,
+	 * because it upsets the performance balance between key
+	 * setup and block procedures, negatively affecting overall
+	 * throughput in applications operating on short messages
+	 * and volatile keys.
+	 */
+}
+
+void
+Camellia_EncryptBlock_Rounds(int grandRounds, const u8 plaintext[],
+    const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
+{
+	u32 s0, s1, s2, s3;
+	const u32 *k = keyTable, *kend = keyTable + grandRounds * 16;
+
+	s0 = GETU32(plaintext) ^ k[0];
+	s1 = GETU32(plaintext + 4) ^ k[1];
+	s2 = GETU32(plaintext + 8) ^ k[2];
+	s3 = GETU32(plaintext + 12) ^ k[3];
+	k += 4;
+
+	while (1) {
+		/* Camellia makes 6 Feistel rounds */
+		Camellia_Feistel(s0, s1, s2, s3, k + 0);
+		Camellia_Feistel(s2, s3, s0, s1, k + 2);
+		Camellia_Feistel(s0, s1, s2, s3, k + 4);
+		Camellia_Feistel(s2, s3, s0, s1, k + 6);
+		Camellia_Feistel(s0, s1, s2, s3, k + 8);
+		Camellia_Feistel(s2, s3, s0, s1, k + 10);
+		k += 12;
+
+		if (k == kend)
+			break;
+
+		/* This is the same function as the diffusion function D
+		 * of the accompanying documentation. See section 3.2
+		 * for properties of the FLlayer function. */
+		s1 ^= LeftRotate(s0 & k[0], 1);
+		s2 ^= s3 | k[3];
+		s0 ^= s1 | k[1];
+		s3 ^= LeftRotate(s2 & k[2], 1);
+		k += 4;
+	}
+
+	s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3];
+
+	PUTU32(ciphertext, s2);
+	PUTU32(ciphertext + 4, s3);
+	PUTU32(ciphertext + 8, s0);
+	PUTU32(ciphertext + 12, s1);
+}
+
+void
+Camellia_EncryptBlock(int keyBitLength, const u8 plaintext[],
+    const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
+{
+	Camellia_EncryptBlock_Rounds(keyBitLength == 128 ? 3 : 4,
+	    plaintext, keyTable, ciphertext);
+}
+
+void
+Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[],
+    const KEY_TABLE_TYPE keyTable, u8 plaintext[])
+{
+	u32 s0, s1, s2, s3;
+	const u32 *k = keyTable+grandRounds * 16, *kend = keyTable+4;
+
+	s0 = GETU32(ciphertext) ^ k[0];
+	s1 = GETU32(ciphertext+4) ^ k[1];
+	s2 = GETU32(ciphertext+8) ^ k[2];
+	s3 = GETU32(ciphertext+12) ^ k[3];
+
+	while (1) {
+		/* Camellia makes 6 Feistel rounds */
+		k -= 12;
+		Camellia_Feistel(s0, s1, s2, s3, k+10);
+		Camellia_Feistel(s2, s3, s0, s1, k+8);
+		Camellia_Feistel(s0, s1, s2, s3, k+6);
+		Camellia_Feistel(s2, s3, s0, s1, k+4);
+		Camellia_Feistel(s0, s1, s2, s3, k+2);
+		Camellia_Feistel(s2, s3, s0, s1, k+0);
+
+		if (k == kend)
+			break;
+
+		/* This is the same function as the diffusion function D
+		 * of the accompanying documentation. See section 3.2
+		 * for properties of the FLlayer function. */
+		k -= 4;
+		s1 ^= LeftRotate(s0 & k[2], 1);
+		s2 ^= s3 | k[1];
+		s0 ^= s1 | k[3];
+		s3 ^= LeftRotate(s2 & k[0], 1);
+	}
+
+	k -= 4;
+	s2 ^= k[0], s3 ^= k[1], s0 ^= k[2], s1 ^= k[3];
+
+	PUTU32(plaintext, s2);
+	PUTU32(plaintext+4, s3);
+	PUTU32(plaintext+8, s0);
+	PUTU32(plaintext+12, s1);
+}
+
+void
+Camellia_DecryptBlock(int keyBitLength, const u8 plaintext[],
+    const KEY_TABLE_TYPE keyTable, u8 ciphertext[])
+{
+	Camellia_DecryptBlock_Rounds(keyBitLength == 128 ? 3 : 4,
+	    plaintext, keyTable, ciphertext);
+}
diff --git a/crypto/camellia/camellia.h b/crypto/camellia/camellia.h
new file mode 100644
index 0000000..b9b5f79
--- /dev/null
+++ b/crypto/camellia/camellia.h
@@ -0,0 +1,125 @@
+/* $OpenBSD: camellia.h,v 1.5 2014/11/13 20:01:58 miod Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#ifndef HEADER_CAMELLIA_H
+#define HEADER_CAMELLIA_H
+
+#include 
+
+#ifdef OPENSSL_NO_CAMELLIA
+#error CAMELLIA is disabled.
+#endif
+
+#include 
+
+#define CAMELLIA_ENCRYPT	1
+#define CAMELLIA_DECRYPT	0
+
+/* Because array size can't be a const in C, the following two are macros.
+   Both sizes are in bytes. */
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* This should be a hidden type, but EVP requires that the size be known */
+
+#define CAMELLIA_BLOCK_SIZE 16
+#define CAMELLIA_TABLE_BYTE_LEN 272
+#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
+
+typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match with WORD */
+
+struct camellia_key_st {
+	union {
+		double d;	/* ensures 64-bit align */
+		KEY_TABLE_TYPE rd_key;
+	} u;
+	int grand_rounds;
+};
+typedef struct camellia_key_st CAMELLIA_KEY;
+
+int Camellia_set_key(const unsigned char *userKey, const int bits,
+	CAMELLIA_KEY *key);
+
+void Camellia_encrypt(const unsigned char *in, unsigned char *out,
+	const CAMELLIA_KEY *key);
+void Camellia_decrypt(const unsigned char *in, unsigned char *out,
+	const CAMELLIA_KEY *key);
+
+void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out,
+	const CAMELLIA_KEY *key, const int enc);
+void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char *ivec, const int enc);
+void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char *ivec, int *num, const int enc);
+void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char *ivec, int *num);
+void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+	size_t length, const CAMELLIA_KEY *key,
+	unsigned char ivec[CAMELLIA_BLOCK_SIZE],
+	unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE],
+	unsigned int *num);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* !HEADER_Camellia_H */
diff --git a/crypto/camellia/cmll-elf-x86_64.S b/crypto/camellia/cmll-elf-x86_64.S
new file mode 100644
index 0000000..ab4a184
--- /dev/null
+++ b/crypto/camellia/cmll-elf-x86_64.S
@@ -0,0 +1,1850 @@
+#include "x86_arch.h"
+.text	
+
+
+.globl	Camellia_EncryptBlock
+.type	Camellia_EncryptBlock,@function
+.align	16
+Camellia_EncryptBlock:
+	endbr64
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	.Lenc_rounds
+.size	Camellia_EncryptBlock,.-Camellia_EncryptBlock
+
+.globl	Camellia_EncryptBlock_Rounds
+.type	Camellia_EncryptBlock_Rounds,@function
+.align	16
+.Lenc_rounds:
+Camellia_EncryptBlock_Rounds:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lenc_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r14
+
+	shll	$6,%edi
+	leaq	.LCamellia_SBOX(%rip),%rbp
+	leaq	(%r14,%rdi,1),%r15
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Lenc_epilogue:
+	retq
+.size	Camellia_EncryptBlock_Rounds,.-Camellia_EncryptBlock_Rounds
+
+.type	_x86_64_Camellia_encrypt,@function
+.align	16
+_x86_64_Camellia_encrypt:
+	endbr64
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.align	16
+.Leloop:
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	56(%r14),%ebx
+	movl	60(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	64(%r14),%ebx
+	movl	68(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	8(%r14),%edx
+	movl	12(%r14),%ecx
+	je	.Ledone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+	jmp	.Leloop
+
+.align	16
+.Ledone:
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r10d
+	movl	%edx,%r11d
+
+	retq
+.size	_x86_64_Camellia_encrypt,.-_x86_64_Camellia_encrypt
+
+
+.globl	Camellia_DecryptBlock
+.type	Camellia_DecryptBlock,@function
+.align	16
+Camellia_DecryptBlock:
+	endbr64
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	.Ldec_rounds
+.size	Camellia_DecryptBlock,.-Camellia_DecryptBlock
+
+.globl	Camellia_DecryptBlock_Rounds
+.type	Camellia_DecryptBlock_Rounds,@function
+.align	16
+.Ldec_rounds:
+Camellia_DecryptBlock_Rounds:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Ldec_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r15
+
+	shll	$6,%edi
+	leaq	.LCamellia_SBOX(%rip),%rbp
+	leaq	(%r15,%rdi,1),%r14
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Ldec_epilogue:
+	retq
+.size	Camellia_DecryptBlock_Rounds,.-Camellia_DecryptBlock_Rounds
+
+.type	_x86_64_Camellia_decrypt,@function
+.align	16
+_x86_64_Camellia_decrypt:
+	endbr64
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.align	16
+.Ldloop:
+	movl	-8(%r14),%ebx
+	movl	-4(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-16(%r14),%ebx
+	movl	-12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-24(%r14),%ebx
+	movl	-20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-32(%r14),%ebx
+	movl	-28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-40(%r14),%ebx
+	movl	-36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-48(%r14),%ebx
+	movl	-44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-56(%r14),%ebx
+	movl	-52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	-64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	0(%r14),%edx
+	movl	4(%r14),%ecx
+	je	.Lddone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+
+	jmp	.Ldloop
+
+.align	16
+.Lddone:
+	xorl	%r10d,%ecx
+	xorl	%r11d,%edx
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+
+	movl	%ecx,%r8d
+	movl	%edx,%r9d
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+
+	retq
+.size	_x86_64_Camellia_decrypt,.-_x86_64_Camellia_decrypt
+.globl	Camellia_Ekeygen
+.type	Camellia_Ekeygen,@function
+.align	16
+Camellia_Ekeygen:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lkey_prologue:
+
+	movq	%rdi,%r15
+	movq	%rdx,%r13
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	movl	12(%rsi),%r11d
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,0(%r13)
+	movl	%r8d,4(%r13)
+	movl	%r11d,8(%r13)
+	movl	%r10d,12(%r13)
+	cmpq	$128,%r15
+	je	.L1st128
+
+	movl	16(%rsi),%r8d
+	movl	20(%rsi),%r9d
+	cmpq	$192,%r15
+	je	.L1st192
+	movl	24(%rsi),%r10d
+	movl	28(%rsi),%r11d
+	jmp	.L1st256
+.L1st192:
+	movl	%r8d,%r10d
+	movl	%r9d,%r11d
+	notl	%r10d
+	notl	%r11d
+.L1st256:
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,32(%r13)
+	movl	%r8d,36(%r13)
+	movl	%r11d,40(%r13)
+	movl	%r10d,44(%r13)
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+
+.L1st128:
+	leaq	.LCamellia_SIGMA(%rip),%r14
+	leaq	.LCamellia_SBOX(%rip),%rbp
+
+	movl	0(%r14),%ebx
+	movl	4(%r14),%eax
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	8(%r14),%ebx
+	movl	12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	cmpq	$128,%r15
+	jne	.L2nd256
+
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	-128(%r13),%rax
+	movq	-120(%r13),%rbx
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-96(%r13)
+	movq	%rbx,-88(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-80(%r13)
+	movq	%r10,-72(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-64(%r13)
+	movq	%r10,-56(%r13)
+	movq	%rax,%r11
+	shlq	$30,%rax
+	movq	%rbx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rax
+	shlq	$30,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-48(%r13)
+	movq	%rbx,-40(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-32(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rbx,-24(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-16(%r13)
+	movq	%r10,-8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,16(%r13)
+	movq	%rbx,24(%r13)
+	movq	%r8,%r11
+	shlq	$34,%r8
+	movq	%r10,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%r8
+	shlq	$34,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r8,%r11
+	shlq	$17,%r8
+	movq	%r10,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r8
+	shlq	$17,%r10
+	orq	%r11,%r10
+	movq	%r8,64(%r13)
+	movq	%r10,72(%r13)
+	movl	$3,%eax
+	jmp	.Ldone
+.align	16
+.L2nd256:
+	movl	%r9d,48(%r13)
+	movl	%r8d,52(%r13)
+	movl	%r11d,56(%r13)
+	movl	%r10d,60(%r13)
+	xorl	32(%r13),%r9d
+	xorl	36(%r13),%r8d
+	xorl	40(%r13),%r11d
+	xorl	44(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	movq	0(%r13),%rax
+	movq	8(%r13),%rbx
+	movq	32(%r13),%rcx
+	movq	40(%r13),%rdx
+	movq	48(%r13),%r14
+	movq	56(%r13),%r15
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-96(%r13)
+	movq	%rdx,-88(%r13)
+	movq	%r14,%r11
+	shlq	$15,%r14
+	movq	%r15,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r14
+	shlq	$15,%r15
+	orq	%r11,%r15
+	movq	%r14,-80(%r13)
+	movq	%r15,-72(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-64(%r13)
+	movq	%rdx,-56(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,-48(%r13)
+	movq	%r10,-40(%r13)
+	movq	%rax,%r11
+	shlq	$45,%rax
+	movq	%rbx,%r9
+	shrq	$19,%r9
+	shrq	$19,%r11
+	orq	%r9,%rax
+	shlq	$45,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-32(%r13)
+	movq	%rbx,-24(%r13)
+	movq	%r14,%r11
+	shlq	$30,%r14
+	movq	%r15,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r14
+	shlq	$30,%r15
+	orq	%r11,%r15
+	movq	%r14,-16(%r13)
+	movq	%r15,-8(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rcx,%r11
+	shlq	$30,%rcx
+	movq	%rdx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rcx
+	shlq	$30,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,16(%r13)
+	movq	%rdx,24(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r14,%r11
+	shlq	$32,%r14
+	movq	%r15,%r9
+	shrq	$32,%r9
+	shrq	$32,%r11
+	orq	%r9,%r14
+	shlq	$32,%r15
+	orq	%r11,%r15
+	movq	%r14,64(%r13)
+	movq	%r15,72(%r13)
+	movq	%rcx,%r11
+	shlq	$34,%rcx
+	movq	%rdx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rcx
+	shlq	$34,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,80(%r13)
+	movq	%rdx,88(%r13)
+	movq	%r14,%r11
+	shlq	$17,%r14
+	movq	%r15,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r14
+	shlq	$17,%r15
+	orq	%r11,%r15
+	movq	%r14,96(%r13)
+	movq	%r15,104(%r13)
+	movq	%rax,%r11
+	shlq	$34,%rax
+	movq	%rbx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rax
+	shlq	$34,%rbx
+	orq	%r11,%rbx
+	movq	%rax,112(%r13)
+	movq	%rbx,120(%r13)
+	movq	%r8,%r11
+	shlq	$51,%r8
+	movq	%r10,%r9
+	shrq	$13,%r9
+	shrq	$13,%r11
+	orq	%r9,%r8
+	shlq	$51,%r10
+	orq	%r11,%r10
+	movq	%r8,128(%r13)
+	movq	%r10,136(%r13)
+	movl	$4,%eax
+.Ldone:
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Lkey_epilogue:
+	retq
+.size	Camellia_Ekeygen,.-Camellia_Ekeygen
+.section	.rodata
+.align	64
+.LCamellia_SIGMA:
+.long	0x3bcc908b, 0xa09e667f, 0x4caa73b2, 0xb67ae858
+.long	0xe94f82be, 0xc6ef372f, 0xf1d36f1c, 0x54ff53a5
+.long	0xde682d1d, 0x10e527fa, 0xb3e6c1fd, 0xb05688c2
+.long	0,          0,          0,          0
+.LCamellia_SBOX:
+.long	0x70707000,0x70700070
+.long	0x82828200,0x2c2c002c
+.long	0x2c2c2c00,0xb3b300b3
+.long	0xececec00,0xc0c000c0
+.long	0xb3b3b300,0xe4e400e4
+.long	0x27272700,0x57570057
+.long	0xc0c0c000,0xeaea00ea
+.long	0xe5e5e500,0xaeae00ae
+.long	0xe4e4e400,0x23230023
+.long	0x85858500,0x6b6b006b
+.long	0x57575700,0x45450045
+.long	0x35353500,0xa5a500a5
+.long	0xeaeaea00,0xeded00ed
+.long	0x0c0c0c00,0x4f4f004f
+.long	0xaeaeae00,0x1d1d001d
+.long	0x41414100,0x92920092
+.long	0x23232300,0x86860086
+.long	0xefefef00,0xafaf00af
+.long	0x6b6b6b00,0x7c7c007c
+.long	0x93939300,0x1f1f001f
+.long	0x45454500,0x3e3e003e
+.long	0x19191900,0xdcdc00dc
+.long	0xa5a5a500,0x5e5e005e
+.long	0x21212100,0x0b0b000b
+.long	0xededed00,0xa6a600a6
+.long	0x0e0e0e00,0x39390039
+.long	0x4f4f4f00,0xd5d500d5
+.long	0x4e4e4e00,0x5d5d005d
+.long	0x1d1d1d00,0xd9d900d9
+.long	0x65656500,0x5a5a005a
+.long	0x92929200,0x51510051
+.long	0xbdbdbd00,0x6c6c006c
+.long	0x86868600,0x8b8b008b
+.long	0xb8b8b800,0x9a9a009a
+.long	0xafafaf00,0xfbfb00fb
+.long	0x8f8f8f00,0xb0b000b0
+.long	0x7c7c7c00,0x74740074
+.long	0xebebeb00,0x2b2b002b
+.long	0x1f1f1f00,0xf0f000f0
+.long	0xcecece00,0x84840084
+.long	0x3e3e3e00,0xdfdf00df
+.long	0x30303000,0xcbcb00cb
+.long	0xdcdcdc00,0x34340034
+.long	0x5f5f5f00,0x76760076
+.long	0x5e5e5e00,0x6d6d006d
+.long	0xc5c5c500,0xa9a900a9
+.long	0x0b0b0b00,0xd1d100d1
+.long	0x1a1a1a00,0x04040004
+.long	0xa6a6a600,0x14140014
+.long	0xe1e1e100,0x3a3a003a
+.long	0x39393900,0xdede00de
+.long	0xcacaca00,0x11110011
+.long	0xd5d5d500,0x32320032
+.long	0x47474700,0x9c9c009c
+.long	0x5d5d5d00,0x53530053
+.long	0x3d3d3d00,0xf2f200f2
+.long	0xd9d9d900,0xfefe00fe
+.long	0x01010100,0xcfcf00cf
+.long	0x5a5a5a00,0xc3c300c3
+.long	0xd6d6d600,0x7a7a007a
+.long	0x51515100,0x24240024
+.long	0x56565600,0xe8e800e8
+.long	0x6c6c6c00,0x60600060
+.long	0x4d4d4d00,0x69690069
+.long	0x8b8b8b00,0xaaaa00aa
+.long	0x0d0d0d00,0xa0a000a0
+.long	0x9a9a9a00,0xa1a100a1
+.long	0x66666600,0x62620062
+.long	0xfbfbfb00,0x54540054
+.long	0xcccccc00,0x1e1e001e
+.long	0xb0b0b000,0xe0e000e0
+.long	0x2d2d2d00,0x64640064
+.long	0x74747400,0x10100010
+.long	0x12121200,0x00000000
+.long	0x2b2b2b00,0xa3a300a3
+.long	0x20202000,0x75750075
+.long	0xf0f0f000,0x8a8a008a
+.long	0xb1b1b100,0xe6e600e6
+.long	0x84848400,0x09090009
+.long	0x99999900,0xdddd00dd
+.long	0xdfdfdf00,0x87870087
+.long	0x4c4c4c00,0x83830083
+.long	0xcbcbcb00,0xcdcd00cd
+.long	0xc2c2c200,0x90900090
+.long	0x34343400,0x73730073
+.long	0x7e7e7e00,0xf6f600f6
+.long	0x76767600,0x9d9d009d
+.long	0x05050500,0xbfbf00bf
+.long	0x6d6d6d00,0x52520052
+.long	0xb7b7b700,0xd8d800d8
+.long	0xa9a9a900,0xc8c800c8
+.long	0x31313100,0xc6c600c6
+.long	0xd1d1d100,0x81810081
+.long	0x17171700,0x6f6f006f
+.long	0x04040400,0x13130013
+.long	0xd7d7d700,0x63630063
+.long	0x14141400,0xe9e900e9
+.long	0x58585800,0xa7a700a7
+.long	0x3a3a3a00,0x9f9f009f
+.long	0x61616100,0xbcbc00bc
+.long	0xdedede00,0x29290029
+.long	0x1b1b1b00,0xf9f900f9
+.long	0x11111100,0x2f2f002f
+.long	0x1c1c1c00,0xb4b400b4
+.long	0x32323200,0x78780078
+.long	0x0f0f0f00,0x06060006
+.long	0x9c9c9c00,0xe7e700e7
+.long	0x16161600,0x71710071
+.long	0x53535300,0xd4d400d4
+.long	0x18181800,0xabab00ab
+.long	0xf2f2f200,0x88880088
+.long	0x22222200,0x8d8d008d
+.long	0xfefefe00,0x72720072
+.long	0x44444400,0xb9b900b9
+.long	0xcfcfcf00,0xf8f800f8
+.long	0xb2b2b200,0xacac00ac
+.long	0xc3c3c300,0x36360036
+.long	0xb5b5b500,0x2a2a002a
+.long	0x7a7a7a00,0x3c3c003c
+.long	0x91919100,0xf1f100f1
+.long	0x24242400,0x40400040
+.long	0x08080800,0xd3d300d3
+.long	0xe8e8e800,0xbbbb00bb
+.long	0xa8a8a800,0x43430043
+.long	0x60606000,0x15150015
+.long	0xfcfcfc00,0xadad00ad
+.long	0x69696900,0x77770077
+.long	0x50505000,0x80800080
+.long	0xaaaaaa00,0x82820082
+.long	0xd0d0d000,0xecec00ec
+.long	0xa0a0a000,0x27270027
+.long	0x7d7d7d00,0xe5e500e5
+.long	0xa1a1a100,0x85850085
+.long	0x89898900,0x35350035
+.long	0x62626200,0x0c0c000c
+.long	0x97979700,0x41410041
+.long	0x54545400,0xefef00ef
+.long	0x5b5b5b00,0x93930093
+.long	0x1e1e1e00,0x19190019
+.long	0x95959500,0x21210021
+.long	0xe0e0e000,0x0e0e000e
+.long	0xffffff00,0x4e4e004e
+.long	0x64646400,0x65650065
+.long	0xd2d2d200,0xbdbd00bd
+.long	0x10101000,0xb8b800b8
+.long	0xc4c4c400,0x8f8f008f
+.long	0x00000000,0xebeb00eb
+.long	0x48484800,0xcece00ce
+.long	0xa3a3a300,0x30300030
+.long	0xf7f7f700,0x5f5f005f
+.long	0x75757500,0xc5c500c5
+.long	0xdbdbdb00,0x1a1a001a
+.long	0x8a8a8a00,0xe1e100e1
+.long	0x03030300,0xcaca00ca
+.long	0xe6e6e600,0x47470047
+.long	0xdadada00,0x3d3d003d
+.long	0x09090900,0x01010001
+.long	0x3f3f3f00,0xd6d600d6
+.long	0xdddddd00,0x56560056
+.long	0x94949400,0x4d4d004d
+.long	0x87878700,0x0d0d000d
+.long	0x5c5c5c00,0x66660066
+.long	0x83838300,0xcccc00cc
+.long	0x02020200,0x2d2d002d
+.long	0xcdcdcd00,0x12120012
+.long	0x4a4a4a00,0x20200020
+.long	0x90909000,0xb1b100b1
+.long	0x33333300,0x99990099
+.long	0x73737300,0x4c4c004c
+.long	0x67676700,0xc2c200c2
+.long	0xf6f6f600,0x7e7e007e
+.long	0xf3f3f300,0x05050005
+.long	0x9d9d9d00,0xb7b700b7
+.long	0x7f7f7f00,0x31310031
+.long	0xbfbfbf00,0x17170017
+.long	0xe2e2e200,0xd7d700d7
+.long	0x52525200,0x58580058
+.long	0x9b9b9b00,0x61610061
+.long	0xd8d8d800,0x1b1b001b
+.long	0x26262600,0x1c1c001c
+.long	0xc8c8c800,0x0f0f000f
+.long	0x37373700,0x16160016
+.long	0xc6c6c600,0x18180018
+.long	0x3b3b3b00,0x22220022
+.long	0x81818100,0x44440044
+.long	0x96969600,0xb2b200b2
+.long	0x6f6f6f00,0xb5b500b5
+.long	0x4b4b4b00,0x91910091
+.long	0x13131300,0x08080008
+.long	0xbebebe00,0xa8a800a8
+.long	0x63636300,0xfcfc00fc
+.long	0x2e2e2e00,0x50500050
+.long	0xe9e9e900,0xd0d000d0
+.long	0x79797900,0x7d7d007d
+.long	0xa7a7a700,0x89890089
+.long	0x8c8c8c00,0x97970097
+.long	0x9f9f9f00,0x5b5b005b
+.long	0x6e6e6e00,0x95950095
+.long	0xbcbcbc00,0xffff00ff
+.long	0x8e8e8e00,0xd2d200d2
+.long	0x29292900,0xc4c400c4
+.long	0xf5f5f500,0x48480048
+.long	0xf9f9f900,0xf7f700f7
+.long	0xb6b6b600,0xdbdb00db
+.long	0x2f2f2f00,0x03030003
+.long	0xfdfdfd00,0xdada00da
+.long	0xb4b4b400,0x3f3f003f
+.long	0x59595900,0x94940094
+.long	0x78787800,0x5c5c005c
+.long	0x98989800,0x02020002
+.long	0x06060600,0x4a4a004a
+.long	0x6a6a6a00,0x33330033
+.long	0xe7e7e700,0x67670067
+.long	0x46464600,0xf3f300f3
+.long	0x71717100,0x7f7f007f
+.long	0xbababa00,0xe2e200e2
+.long	0xd4d4d400,0x9b9b009b
+.long	0x25252500,0x26260026
+.long	0xababab00,0x37370037
+.long	0x42424200,0x3b3b003b
+.long	0x88888800,0x96960096
+.long	0xa2a2a200,0x4b4b004b
+.long	0x8d8d8d00,0xbebe00be
+.long	0xfafafa00,0x2e2e002e
+.long	0x72727200,0x79790079
+.long	0x07070700,0x8c8c008c
+.long	0xb9b9b900,0x6e6e006e
+.long	0x55555500,0x8e8e008e
+.long	0xf8f8f800,0xf5f500f5
+.long	0xeeeeee00,0xb6b600b6
+.long	0xacacac00,0xfdfd00fd
+.long	0x0a0a0a00,0x59590059
+.long	0x36363600,0x98980098
+.long	0x49494900,0x6a6a006a
+.long	0x2a2a2a00,0x46460046
+.long	0x68686800,0xbaba00ba
+.long	0x3c3c3c00,0x25250025
+.long	0x38383800,0x42420042
+.long	0xf1f1f100,0xa2a200a2
+.long	0xa4a4a400,0xfafa00fa
+.long	0x40404000,0x07070007
+.long	0x28282800,0x55550055
+.long	0xd3d3d300,0xeeee00ee
+.long	0x7b7b7b00,0x0a0a000a
+.long	0xbbbbbb00,0x49490049
+.long	0xc9c9c900,0x68680068
+.long	0x43434300,0x38380038
+.long	0xc1c1c100,0xa4a400a4
+.long	0x15151500,0x28280028
+.long	0xe3e3e300,0x7b7b007b
+.long	0xadadad00,0xc9c900c9
+.long	0xf4f4f400,0xc1c100c1
+.long	0x77777700,0xe3e300e3
+.long	0xc7c7c700,0xf4f400f4
+.long	0x80808000,0xc7c700c7
+.long	0x9e9e9e00,0x9e9e009e
+.long	0x00e0e0e0,0x38003838
+.long	0x00050505,0x41004141
+.long	0x00585858,0x16001616
+.long	0x00d9d9d9,0x76007676
+.long	0x00676767,0xd900d9d9
+.long	0x004e4e4e,0x93009393
+.long	0x00818181,0x60006060
+.long	0x00cbcbcb,0xf200f2f2
+.long	0x00c9c9c9,0x72007272
+.long	0x000b0b0b,0xc200c2c2
+.long	0x00aeaeae,0xab00abab
+.long	0x006a6a6a,0x9a009a9a
+.long	0x00d5d5d5,0x75007575
+.long	0x00181818,0x06000606
+.long	0x005d5d5d,0x57005757
+.long	0x00828282,0xa000a0a0
+.long	0x00464646,0x91009191
+.long	0x00dfdfdf,0xf700f7f7
+.long	0x00d6d6d6,0xb500b5b5
+.long	0x00272727,0xc900c9c9
+.long	0x008a8a8a,0xa200a2a2
+.long	0x00323232,0x8c008c8c
+.long	0x004b4b4b,0xd200d2d2
+.long	0x00424242,0x90009090
+.long	0x00dbdbdb,0xf600f6f6
+.long	0x001c1c1c,0x07000707
+.long	0x009e9e9e,0xa700a7a7
+.long	0x009c9c9c,0x27002727
+.long	0x003a3a3a,0x8e008e8e
+.long	0x00cacaca,0xb200b2b2
+.long	0x00252525,0x49004949
+.long	0x007b7b7b,0xde00dede
+.long	0x000d0d0d,0x43004343
+.long	0x00717171,0x5c005c5c
+.long	0x005f5f5f,0xd700d7d7
+.long	0x001f1f1f,0xc700c7c7
+.long	0x00f8f8f8,0x3e003e3e
+.long	0x00d7d7d7,0xf500f5f5
+.long	0x003e3e3e,0x8f008f8f
+.long	0x009d9d9d,0x67006767
+.long	0x007c7c7c,0x1f001f1f
+.long	0x00606060,0x18001818
+.long	0x00b9b9b9,0x6e006e6e
+.long	0x00bebebe,0xaf00afaf
+.long	0x00bcbcbc,0x2f002f2f
+.long	0x008b8b8b,0xe200e2e2
+.long	0x00161616,0x85008585
+.long	0x00343434,0x0d000d0d
+.long	0x004d4d4d,0x53005353
+.long	0x00c3c3c3,0xf000f0f0
+.long	0x00727272,0x9c009c9c
+.long	0x00959595,0x65006565
+.long	0x00ababab,0xea00eaea
+.long	0x008e8e8e,0xa300a3a3
+.long	0x00bababa,0xae00aeae
+.long	0x007a7a7a,0x9e009e9e
+.long	0x00b3b3b3,0xec00ecec
+.long	0x00020202,0x80008080
+.long	0x00b4b4b4,0x2d002d2d
+.long	0x00adadad,0x6b006b6b
+.long	0x00a2a2a2,0xa800a8a8
+.long	0x00acacac,0x2b002b2b
+.long	0x00d8d8d8,0x36003636
+.long	0x009a9a9a,0xa600a6a6
+.long	0x00171717,0xc500c5c5
+.long	0x001a1a1a,0x86008686
+.long	0x00353535,0x4d004d4d
+.long	0x00cccccc,0x33003333
+.long	0x00f7f7f7,0xfd00fdfd
+.long	0x00999999,0x66006666
+.long	0x00616161,0x58005858
+.long	0x005a5a5a,0x96009696
+.long	0x00e8e8e8,0x3a003a3a
+.long	0x00242424,0x09000909
+.long	0x00565656,0x95009595
+.long	0x00404040,0x10001010
+.long	0x00e1e1e1,0x78007878
+.long	0x00636363,0xd800d8d8
+.long	0x00090909,0x42004242
+.long	0x00333333,0xcc00cccc
+.long	0x00bfbfbf,0xef00efef
+.long	0x00989898,0x26002626
+.long	0x00979797,0xe500e5e5
+.long	0x00858585,0x61006161
+.long	0x00686868,0x1a001a1a
+.long	0x00fcfcfc,0x3f003f3f
+.long	0x00ececec,0x3b003b3b
+.long	0x000a0a0a,0x82008282
+.long	0x00dadada,0xb600b6b6
+.long	0x006f6f6f,0xdb00dbdb
+.long	0x00535353,0xd400d4d4
+.long	0x00626262,0x98009898
+.long	0x00a3a3a3,0xe800e8e8
+.long	0x002e2e2e,0x8b008b8b
+.long	0x00080808,0x02000202
+.long	0x00afafaf,0xeb00ebeb
+.long	0x00282828,0x0a000a0a
+.long	0x00b0b0b0,0x2c002c2c
+.long	0x00747474,0x1d001d1d
+.long	0x00c2c2c2,0xb000b0b0
+.long	0x00bdbdbd,0x6f006f6f
+.long	0x00363636,0x8d008d8d
+.long	0x00222222,0x88008888
+.long	0x00383838,0x0e000e0e
+.long	0x00646464,0x19001919
+.long	0x001e1e1e,0x87008787
+.long	0x00393939,0x4e004e4e
+.long	0x002c2c2c,0x0b000b0b
+.long	0x00a6a6a6,0xa900a9a9
+.long	0x00303030,0x0c000c0c
+.long	0x00e5e5e5,0x79007979
+.long	0x00444444,0x11001111
+.long	0x00fdfdfd,0x7f007f7f
+.long	0x00888888,0x22002222
+.long	0x009f9f9f,0xe700e7e7
+.long	0x00656565,0x59005959
+.long	0x00878787,0xe100e1e1
+.long	0x006b6b6b,0xda00dada
+.long	0x00f4f4f4,0x3d003d3d
+.long	0x00232323,0xc800c8c8
+.long	0x00484848,0x12001212
+.long	0x00101010,0x04000404
+.long	0x00d1d1d1,0x74007474
+.long	0x00515151,0x54005454
+.long	0x00c0c0c0,0x30003030
+.long	0x00f9f9f9,0x7e007e7e
+.long	0x00d2d2d2,0xb400b4b4
+.long	0x00a0a0a0,0x28002828
+.long	0x00555555,0x55005555
+.long	0x00a1a1a1,0x68006868
+.long	0x00414141,0x50005050
+.long	0x00fafafa,0xbe00bebe
+.long	0x00434343,0xd000d0d0
+.long	0x00131313,0xc400c4c4
+.long	0x00c4c4c4,0x31003131
+.long	0x002f2f2f,0xcb00cbcb
+.long	0x00a8a8a8,0x2a002a2a
+.long	0x00b6b6b6,0xad00adad
+.long	0x003c3c3c,0x0f000f0f
+.long	0x002b2b2b,0xca00caca
+.long	0x00c1c1c1,0x70007070
+.long	0x00ffffff,0xff00ffff
+.long	0x00c8c8c8,0x32003232
+.long	0x00a5a5a5,0x69006969
+.long	0x00202020,0x08000808
+.long	0x00898989,0x62006262
+.long	0x00000000,0x00000000
+.long	0x00909090,0x24002424
+.long	0x00474747,0xd100d1d1
+.long	0x00efefef,0xfb00fbfb
+.long	0x00eaeaea,0xba00baba
+.long	0x00b7b7b7,0xed00eded
+.long	0x00151515,0x45004545
+.long	0x00060606,0x81008181
+.long	0x00cdcdcd,0x73007373
+.long	0x00b5b5b5,0x6d006d6d
+.long	0x00121212,0x84008484
+.long	0x007e7e7e,0x9f009f9f
+.long	0x00bbbbbb,0xee00eeee
+.long	0x00292929,0x4a004a4a
+.long	0x000f0f0f,0xc300c3c3
+.long	0x00b8b8b8,0x2e002e2e
+.long	0x00070707,0xc100c1c1
+.long	0x00040404,0x01000101
+.long	0x009b9b9b,0xe600e6e6
+.long	0x00949494,0x25002525
+.long	0x00212121,0x48004848
+.long	0x00666666,0x99009999
+.long	0x00e6e6e6,0xb900b9b9
+.long	0x00cecece,0xb300b3b3
+.long	0x00ededed,0x7b007b7b
+.long	0x00e7e7e7,0xf900f9f9
+.long	0x003b3b3b,0xce00cece
+.long	0x00fefefe,0xbf00bfbf
+.long	0x007f7f7f,0xdf00dfdf
+.long	0x00c5c5c5,0x71007171
+.long	0x00a4a4a4,0x29002929
+.long	0x00373737,0xcd00cdcd
+.long	0x00b1b1b1,0x6c006c6c
+.long	0x004c4c4c,0x13001313
+.long	0x00919191,0x64006464
+.long	0x006e6e6e,0x9b009b9b
+.long	0x008d8d8d,0x63006363
+.long	0x00767676,0x9d009d9d
+.long	0x00030303,0xc000c0c0
+.long	0x002d2d2d,0x4b004b4b
+.long	0x00dedede,0xb700b7b7
+.long	0x00969696,0xa500a5a5
+.long	0x00262626,0x89008989
+.long	0x007d7d7d,0x5f005f5f
+.long	0x00c6c6c6,0xb100b1b1
+.long	0x005c5c5c,0x17001717
+.long	0x00d3d3d3,0xf400f4f4
+.long	0x00f2f2f2,0xbc00bcbc
+.long	0x004f4f4f,0xd300d3d3
+.long	0x00191919,0x46004646
+.long	0x003f3f3f,0xcf00cfcf
+.long	0x00dcdcdc,0x37003737
+.long	0x00797979,0x5e005e5e
+.long	0x001d1d1d,0x47004747
+.long	0x00525252,0x94009494
+.long	0x00ebebeb,0xfa00fafa
+.long	0x00f3f3f3,0xfc00fcfc
+.long	0x006d6d6d,0x5b005b5b
+.long	0x005e5e5e,0x97009797
+.long	0x00fbfbfb,0xfe00fefe
+.long	0x00696969,0x5a005a5a
+.long	0x00b2b2b2,0xac00acac
+.long	0x00f0f0f0,0x3c003c3c
+.long	0x00313131,0x4c004c4c
+.long	0x000c0c0c,0x03000303
+.long	0x00d4d4d4,0x35003535
+.long	0x00cfcfcf,0xf300f3f3
+.long	0x008c8c8c,0x23002323
+.long	0x00e2e2e2,0xb800b8b8
+.long	0x00757575,0x5d005d5d
+.long	0x00a9a9a9,0x6a006a6a
+.long	0x004a4a4a,0x92009292
+.long	0x00575757,0xd500d5d5
+.long	0x00848484,0x21002121
+.long	0x00111111,0x44004444
+.long	0x00454545,0x51005151
+.long	0x001b1b1b,0xc600c6c6
+.long	0x00f5f5f5,0x7d007d7d
+.long	0x00e4e4e4,0x39003939
+.long	0x000e0e0e,0x83008383
+.long	0x00737373,0xdc00dcdc
+.long	0x00aaaaaa,0xaa00aaaa
+.long	0x00f1f1f1,0x7c007c7c
+.long	0x00dddddd,0x77007777
+.long	0x00595959,0x56005656
+.long	0x00141414,0x05000505
+.long	0x006c6c6c,0x1b001b1b
+.long	0x00929292,0xa400a4a4
+.long	0x00545454,0x15001515
+.long	0x00d0d0d0,0x34003434
+.long	0x00787878,0x1e001e1e
+.long	0x00707070,0x1c001c1c
+.long	0x00e3e3e3,0xf800f8f8
+.long	0x00494949,0x52005252
+.long	0x00808080,0x20002020
+.long	0x00505050,0x14001414
+.long	0x00a7a7a7,0xe900e9e9
+.long	0x00f6f6f6,0xbd00bdbd
+.long	0x00777777,0xdd00dddd
+.long	0x00939393,0xe400e4e4
+.long	0x00868686,0xa100a1a1
+.long	0x00838383,0xe000e0e0
+.long	0x002a2a2a,0x8a008a8a
+.long	0x00c7c7c7,0xf100f1f1
+.long	0x005b5b5b,0xd600d6d6
+.long	0x00e9e9e9,0x7a007a7a
+.long	0x00eeeeee,0xbb00bbbb
+.long	0x008f8f8f,0xe300e3e3
+.long	0x00010101,0x40004040
+.long	0x003d3d3d,0x4f004f4f
+.text	
+.globl	Camellia_cbc_encrypt
+.type	Camellia_cbc_encrypt,@function
+.align	16
+Camellia_cbc_encrypt:
+	endbr64
+	cmpq	$0,%rdx
+	je	.Lcbc_abort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lcbc_prologue:
+
+	movq	%rsp,%rbp
+	subq	$64,%rsp
+	andq	$-64,%rsp
+
+
+
+	leaq	-64-63(%rcx),%r10
+	subq	%rsp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rsp
+
+
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%r8,%rbx
+	movq	%rcx,%r14
+	movl	272(%rcx),%r15d
+
+	movq	%r8,40(%rsp)
+	movq	%rbp,48(%rsp)
+
+.Lcbc_body:
+	leaq	.LCamellia_SBOX(%rip),%rbp
+
+	movl	$32,%ecx
+.align	4
+.Lcbc_prefetch_sbox:
+	movq	0(%rbp),%rax
+	movq	32(%rbp),%rsi
+	movq	64(%rbp),%rdi
+	movq	96(%rbp),%r11
+	leaq	128(%rbp),%rbp
+	loop	.Lcbc_prefetch_sbox
+	subq	$4096,%rbp
+	shlq	$6,%r15
+	movq	%rdx,%rcx
+	leaq	(%r14,%r15,1),%r15
+
+	cmpl	$0,%r9d
+	je	.LCBC_DECRYPT
+
+	andq	$-16,%rdx
+	andq	$15,%rcx
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%r14,0(%rsp)
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	cmpq	%r12,%rdx
+	movl	0(%rbx),%r8d
+	movl	4(%rbx),%r9d
+	movl	8(%rbx),%r10d
+	movl	12(%rbx),%r11d
+	je	.Lcbc_enc_tail
+	jmp	.Lcbc_eloop
+
+.align	16
+.Lcbc_eloop:
+	xorl	0(%r12),%r8d
+	xorl	4(%r12),%r9d
+	xorl	8(%r12),%r10d
+	bswapl	%r8d
+	xorl	12(%r12),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	movq	0(%rsp),%r14
+	bswapl	%r8d
+	movq	8(%rsp),%rdx
+	bswapl	%r9d
+	movq	16(%rsp),%rcx
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	leaq	16(%r12),%r12
+	movl	%r11d,12(%r13)
+	cmpq	%rdx,%r12
+	leaq	16(%r13),%r13
+	jne	.Lcbc_eloop
+
+	cmpq	$0,%rcx
+	jne	.Lcbc_enc_tail
+
+	movq	40(%rsp),%r13
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+	jmp	.Lcbc_done
+
+.align	16
+.Lcbc_enc_tail:
+	xorq	%rax,%rax
+	movq	%rax,0+24(%rsp)
+	movq	%rax,8+24(%rsp)
+	movq	%rax,16(%rsp)
+
+.Lcbc_enc_pushf:
+	pushfq
+	cld
+	movq	%r12,%rsi
+	leaq	8+24(%rsp),%rdi
+.long	0x9066A4F3		
+	popfq
+.Lcbc_enc_popf:
+
+	leaq	24(%rsp),%r12
+	leaq	16+24(%rsp),%rax
+	movq	%rax,8(%rsp)
+	jmp	.Lcbc_eloop		
+
+.align	16
+.LCBC_DECRYPT:
+	xchgq	%r14,%r15
+	addq	$15,%rdx
+	andq	$15,%rcx
+	andq	$-16,%rdx
+	movq	%r14,0(%rsp)
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	movq	(%rbx),%rax
+	movq	8(%rbx),%rbx
+	jmp	.Lcbc_dloop
+.align	16
+.Lcbc_dloop:
+	movl	0(%r12),%r8d
+	movl	4(%r12),%r9d
+	movl	8(%r12),%r10d
+	bswapl	%r8d
+	movl	12(%r12),%r11d
+	bswapl	%r9d
+	movq	%rax,0+24(%rsp)
+	bswapl	%r10d
+	movq	%rbx,8+24(%rsp)
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	movq	0(%rsp),%r14
+	movq	8(%rsp),%rdx
+	movq	16(%rsp),%rcx
+
+	bswapl	%r8d
+	movq	(%r12),%rax
+	bswapl	%r9d
+	movq	8(%r12),%rbx
+	bswapl	%r10d
+	xorl	0+24(%rsp),%r8d
+	bswapl	%r11d
+	xorl	4+24(%rsp),%r9d
+	xorl	8+24(%rsp),%r10d
+	leaq	16(%r12),%r12
+	xorl	12+24(%rsp),%r11d
+	cmpq	%rdx,%r12
+	je	.Lcbc_ddone
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	leaq	16(%r13),%r13
+	jmp	.Lcbc_dloop
+
+.align	16
+.Lcbc_ddone:
+	movq	40(%rsp),%rdx
+	cmpq	$0,%rcx
+	jne	.Lcbc_dec_tail
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	.Lcbc_done
+.align	16
+.Lcbc_dec_tail:
+	movl	%r8d,0+24(%rsp)
+	movl	%r9d,4+24(%rsp)
+	movl	%r10d,8+24(%rsp)
+	movl	%r11d,12+24(%rsp)
+
+.Lcbc_dec_pushf:
+	pushfq
+	cld
+	leaq	8+24(%rsp),%rsi
+	leaq	(%r13),%rdi
+.long	0x9066A4F3		
+	popfq
+.Lcbc_dec_popf:
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	.Lcbc_done
+
+.align	16
+.Lcbc_done:
+	movq	48(%rsp),%rcx
+	movq	0(%rcx),%r15
+	movq	8(%rcx),%r14
+	movq	16(%rcx),%r13
+	movq	24(%rcx),%r12
+	movq	32(%rcx),%rbp
+	movq	40(%rcx),%rbx
+	leaq	48(%rcx),%rsp
+.Lcbc_abort:
+	retq
+.size	Camellia_cbc_encrypt,.-Camellia_cbc_encrypt
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/camellia/cmll-macosx-x86_64.S b/crypto/camellia/cmll-macosx-x86_64.S
new file mode 100644
index 0000000..5e7a1b7
--- /dev/null
+++ b/crypto/camellia/cmll-macosx-x86_64.S
@@ -0,0 +1,1839 @@
+#include "x86_arch.h"
+.text	
+
+
+.globl	_Camellia_EncryptBlock
+
+.p2align	4
+_Camellia_EncryptBlock:
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	L$enc_rounds
+
+
+.globl	_Camellia_EncryptBlock_Rounds
+
+.p2align	4
+L$enc_rounds:
+_Camellia_EncryptBlock_Rounds:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+L$enc_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r14
+
+	shll	$6,%edi
+	leaq	L$Camellia_SBOX(%rip),%rbp
+	leaq	(%r14,%rdi,1),%r15
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+L$enc_epilogue:
+	retq
+
+
+
+.p2align	4
+_x86_64_Camellia_encrypt:
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.p2align	4
+L$eloop:
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	56(%r14),%ebx
+	movl	60(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	64(%r14),%ebx
+	movl	68(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	8(%r14),%edx
+	movl	12(%r14),%ecx
+	je	L$edone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+	jmp	L$eloop
+
+.p2align	4
+L$edone:
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r10d
+	movl	%edx,%r11d
+
+	retq
+
+
+
+.globl	_Camellia_DecryptBlock
+
+.p2align	4
+_Camellia_DecryptBlock:
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	L$dec_rounds
+
+
+.globl	_Camellia_DecryptBlock_Rounds
+
+.p2align	4
+L$dec_rounds:
+_Camellia_DecryptBlock_Rounds:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+L$dec_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r15
+
+	shll	$6,%edi
+	leaq	L$Camellia_SBOX(%rip),%rbp
+	leaq	(%r15,%rdi,1),%r14
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+L$dec_epilogue:
+	retq
+
+
+
+.p2align	4
+_x86_64_Camellia_decrypt:
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.p2align	4
+L$dloop:
+	movl	-8(%r14),%ebx
+	movl	-4(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-16(%r14),%ebx
+	movl	-12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-24(%r14),%ebx
+	movl	-20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-32(%r14),%ebx
+	movl	-28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-40(%r14),%ebx
+	movl	-36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-48(%r14),%ebx
+	movl	-44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-56(%r14),%ebx
+	movl	-52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	-64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	0(%r14),%edx
+	movl	4(%r14),%ecx
+	je	L$ddone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+
+	jmp	L$dloop
+
+.p2align	4
+L$ddone:
+	xorl	%r10d,%ecx
+	xorl	%r11d,%edx
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+
+	movl	%ecx,%r8d
+	movl	%edx,%r9d
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+
+	retq
+
+.globl	_Camellia_Ekeygen
+
+.p2align	4
+_Camellia_Ekeygen:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+L$key_prologue:
+
+	movq	%rdi,%r15
+	movq	%rdx,%r13
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	movl	12(%rsi),%r11d
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,0(%r13)
+	movl	%r8d,4(%r13)
+	movl	%r11d,8(%r13)
+	movl	%r10d,12(%r13)
+	cmpq	$128,%r15
+	je	L$1st128
+
+	movl	16(%rsi),%r8d
+	movl	20(%rsi),%r9d
+	cmpq	$192,%r15
+	je	L$1st192
+	movl	24(%rsi),%r10d
+	movl	28(%rsi),%r11d
+	jmp	L$1st256
+L$1st192:
+	movl	%r8d,%r10d
+	movl	%r9d,%r11d
+	notl	%r10d
+	notl	%r11d
+L$1st256:
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,32(%r13)
+	movl	%r8d,36(%r13)
+	movl	%r11d,40(%r13)
+	movl	%r10d,44(%r13)
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+
+L$1st128:
+	leaq	L$Camellia_SIGMA(%rip),%r14
+	leaq	L$Camellia_SBOX(%rip),%rbp
+
+	movl	0(%r14),%ebx
+	movl	4(%r14),%eax
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	8(%r14),%ebx
+	movl	12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	cmpq	$128,%r15
+	jne	L$2nd256
+
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	-128(%r13),%rax
+	movq	-120(%r13),%rbx
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-96(%r13)
+	movq	%rbx,-88(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-80(%r13)
+	movq	%r10,-72(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-64(%r13)
+	movq	%r10,-56(%r13)
+	movq	%rax,%r11
+	shlq	$30,%rax
+	movq	%rbx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rax
+	shlq	$30,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-48(%r13)
+	movq	%rbx,-40(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-32(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rbx,-24(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-16(%r13)
+	movq	%r10,-8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,16(%r13)
+	movq	%rbx,24(%r13)
+	movq	%r8,%r11
+	shlq	$34,%r8
+	movq	%r10,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%r8
+	shlq	$34,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r8,%r11
+	shlq	$17,%r8
+	movq	%r10,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r8
+	shlq	$17,%r10
+	orq	%r11,%r10
+	movq	%r8,64(%r13)
+	movq	%r10,72(%r13)
+	movl	$3,%eax
+	jmp	L$done
+.p2align	4
+L$2nd256:
+	movl	%r9d,48(%r13)
+	movl	%r8d,52(%r13)
+	movl	%r11d,56(%r13)
+	movl	%r10d,60(%r13)
+	xorl	32(%r13),%r9d
+	xorl	36(%r13),%r8d
+	xorl	40(%r13),%r11d
+	xorl	44(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	movq	0(%r13),%rax
+	movq	8(%r13),%rbx
+	movq	32(%r13),%rcx
+	movq	40(%r13),%rdx
+	movq	48(%r13),%r14
+	movq	56(%r13),%r15
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-96(%r13)
+	movq	%rdx,-88(%r13)
+	movq	%r14,%r11
+	shlq	$15,%r14
+	movq	%r15,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r14
+	shlq	$15,%r15
+	orq	%r11,%r15
+	movq	%r14,-80(%r13)
+	movq	%r15,-72(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-64(%r13)
+	movq	%rdx,-56(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,-48(%r13)
+	movq	%r10,-40(%r13)
+	movq	%rax,%r11
+	shlq	$45,%rax
+	movq	%rbx,%r9
+	shrq	$19,%r9
+	shrq	$19,%r11
+	orq	%r9,%rax
+	shlq	$45,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-32(%r13)
+	movq	%rbx,-24(%r13)
+	movq	%r14,%r11
+	shlq	$30,%r14
+	movq	%r15,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r14
+	shlq	$30,%r15
+	orq	%r11,%r15
+	movq	%r14,-16(%r13)
+	movq	%r15,-8(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rcx,%r11
+	shlq	$30,%rcx
+	movq	%rdx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rcx
+	shlq	$30,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,16(%r13)
+	movq	%rdx,24(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r14,%r11
+	shlq	$32,%r14
+	movq	%r15,%r9
+	shrq	$32,%r9
+	shrq	$32,%r11
+	orq	%r9,%r14
+	shlq	$32,%r15
+	orq	%r11,%r15
+	movq	%r14,64(%r13)
+	movq	%r15,72(%r13)
+	movq	%rcx,%r11
+	shlq	$34,%rcx
+	movq	%rdx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rcx
+	shlq	$34,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,80(%r13)
+	movq	%rdx,88(%r13)
+	movq	%r14,%r11
+	shlq	$17,%r14
+	movq	%r15,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r14
+	shlq	$17,%r15
+	orq	%r11,%r15
+	movq	%r14,96(%r13)
+	movq	%r15,104(%r13)
+	movq	%rax,%r11
+	shlq	$34,%rax
+	movq	%rbx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rax
+	shlq	$34,%rbx
+	orq	%r11,%rbx
+	movq	%rax,112(%r13)
+	movq	%rbx,120(%r13)
+	movq	%r8,%r11
+	shlq	$51,%r8
+	movq	%r10,%r9
+	shrq	$13,%r9
+	shrq	$13,%r11
+	orq	%r9,%r8
+	shlq	$51,%r10
+	orq	%r11,%r10
+	movq	%r8,128(%r13)
+	movq	%r10,136(%r13)
+	movl	$4,%eax
+L$done:
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+L$key_epilogue:
+	retq
+
+.p2align	6
+L$Camellia_SIGMA:
+.long	0x3bcc908b, 0xa09e667f, 0x4caa73b2, 0xb67ae858
+.long	0xe94f82be, 0xc6ef372f, 0xf1d36f1c, 0x54ff53a5
+.long	0xde682d1d, 0x10e527fa, 0xb3e6c1fd, 0xb05688c2
+.long	0,          0,          0,          0
+L$Camellia_SBOX:
+.long	0x70707000,0x70700070
+.long	0x82828200,0x2c2c002c
+.long	0x2c2c2c00,0xb3b300b3
+.long	0xececec00,0xc0c000c0
+.long	0xb3b3b300,0xe4e400e4
+.long	0x27272700,0x57570057
+.long	0xc0c0c000,0xeaea00ea
+.long	0xe5e5e500,0xaeae00ae
+.long	0xe4e4e400,0x23230023
+.long	0x85858500,0x6b6b006b
+.long	0x57575700,0x45450045
+.long	0x35353500,0xa5a500a5
+.long	0xeaeaea00,0xeded00ed
+.long	0x0c0c0c00,0x4f4f004f
+.long	0xaeaeae00,0x1d1d001d
+.long	0x41414100,0x92920092
+.long	0x23232300,0x86860086
+.long	0xefefef00,0xafaf00af
+.long	0x6b6b6b00,0x7c7c007c
+.long	0x93939300,0x1f1f001f
+.long	0x45454500,0x3e3e003e
+.long	0x19191900,0xdcdc00dc
+.long	0xa5a5a500,0x5e5e005e
+.long	0x21212100,0x0b0b000b
+.long	0xededed00,0xa6a600a6
+.long	0x0e0e0e00,0x39390039
+.long	0x4f4f4f00,0xd5d500d5
+.long	0x4e4e4e00,0x5d5d005d
+.long	0x1d1d1d00,0xd9d900d9
+.long	0x65656500,0x5a5a005a
+.long	0x92929200,0x51510051
+.long	0xbdbdbd00,0x6c6c006c
+.long	0x86868600,0x8b8b008b
+.long	0xb8b8b800,0x9a9a009a
+.long	0xafafaf00,0xfbfb00fb
+.long	0x8f8f8f00,0xb0b000b0
+.long	0x7c7c7c00,0x74740074
+.long	0xebebeb00,0x2b2b002b
+.long	0x1f1f1f00,0xf0f000f0
+.long	0xcecece00,0x84840084
+.long	0x3e3e3e00,0xdfdf00df
+.long	0x30303000,0xcbcb00cb
+.long	0xdcdcdc00,0x34340034
+.long	0x5f5f5f00,0x76760076
+.long	0x5e5e5e00,0x6d6d006d
+.long	0xc5c5c500,0xa9a900a9
+.long	0x0b0b0b00,0xd1d100d1
+.long	0x1a1a1a00,0x04040004
+.long	0xa6a6a600,0x14140014
+.long	0xe1e1e100,0x3a3a003a
+.long	0x39393900,0xdede00de
+.long	0xcacaca00,0x11110011
+.long	0xd5d5d500,0x32320032
+.long	0x47474700,0x9c9c009c
+.long	0x5d5d5d00,0x53530053
+.long	0x3d3d3d00,0xf2f200f2
+.long	0xd9d9d900,0xfefe00fe
+.long	0x01010100,0xcfcf00cf
+.long	0x5a5a5a00,0xc3c300c3
+.long	0xd6d6d600,0x7a7a007a
+.long	0x51515100,0x24240024
+.long	0x56565600,0xe8e800e8
+.long	0x6c6c6c00,0x60600060
+.long	0x4d4d4d00,0x69690069
+.long	0x8b8b8b00,0xaaaa00aa
+.long	0x0d0d0d00,0xa0a000a0
+.long	0x9a9a9a00,0xa1a100a1
+.long	0x66666600,0x62620062
+.long	0xfbfbfb00,0x54540054
+.long	0xcccccc00,0x1e1e001e
+.long	0xb0b0b000,0xe0e000e0
+.long	0x2d2d2d00,0x64640064
+.long	0x74747400,0x10100010
+.long	0x12121200,0x00000000
+.long	0x2b2b2b00,0xa3a300a3
+.long	0x20202000,0x75750075
+.long	0xf0f0f000,0x8a8a008a
+.long	0xb1b1b100,0xe6e600e6
+.long	0x84848400,0x09090009
+.long	0x99999900,0xdddd00dd
+.long	0xdfdfdf00,0x87870087
+.long	0x4c4c4c00,0x83830083
+.long	0xcbcbcb00,0xcdcd00cd
+.long	0xc2c2c200,0x90900090
+.long	0x34343400,0x73730073
+.long	0x7e7e7e00,0xf6f600f6
+.long	0x76767600,0x9d9d009d
+.long	0x05050500,0xbfbf00bf
+.long	0x6d6d6d00,0x52520052
+.long	0xb7b7b700,0xd8d800d8
+.long	0xa9a9a900,0xc8c800c8
+.long	0x31313100,0xc6c600c6
+.long	0xd1d1d100,0x81810081
+.long	0x17171700,0x6f6f006f
+.long	0x04040400,0x13130013
+.long	0xd7d7d700,0x63630063
+.long	0x14141400,0xe9e900e9
+.long	0x58585800,0xa7a700a7
+.long	0x3a3a3a00,0x9f9f009f
+.long	0x61616100,0xbcbc00bc
+.long	0xdedede00,0x29290029
+.long	0x1b1b1b00,0xf9f900f9
+.long	0x11111100,0x2f2f002f
+.long	0x1c1c1c00,0xb4b400b4
+.long	0x32323200,0x78780078
+.long	0x0f0f0f00,0x06060006
+.long	0x9c9c9c00,0xe7e700e7
+.long	0x16161600,0x71710071
+.long	0x53535300,0xd4d400d4
+.long	0x18181800,0xabab00ab
+.long	0xf2f2f200,0x88880088
+.long	0x22222200,0x8d8d008d
+.long	0xfefefe00,0x72720072
+.long	0x44444400,0xb9b900b9
+.long	0xcfcfcf00,0xf8f800f8
+.long	0xb2b2b200,0xacac00ac
+.long	0xc3c3c300,0x36360036
+.long	0xb5b5b500,0x2a2a002a
+.long	0x7a7a7a00,0x3c3c003c
+.long	0x91919100,0xf1f100f1
+.long	0x24242400,0x40400040
+.long	0x08080800,0xd3d300d3
+.long	0xe8e8e800,0xbbbb00bb
+.long	0xa8a8a800,0x43430043
+.long	0x60606000,0x15150015
+.long	0xfcfcfc00,0xadad00ad
+.long	0x69696900,0x77770077
+.long	0x50505000,0x80800080
+.long	0xaaaaaa00,0x82820082
+.long	0xd0d0d000,0xecec00ec
+.long	0xa0a0a000,0x27270027
+.long	0x7d7d7d00,0xe5e500e5
+.long	0xa1a1a100,0x85850085
+.long	0x89898900,0x35350035
+.long	0x62626200,0x0c0c000c
+.long	0x97979700,0x41410041
+.long	0x54545400,0xefef00ef
+.long	0x5b5b5b00,0x93930093
+.long	0x1e1e1e00,0x19190019
+.long	0x95959500,0x21210021
+.long	0xe0e0e000,0x0e0e000e
+.long	0xffffff00,0x4e4e004e
+.long	0x64646400,0x65650065
+.long	0xd2d2d200,0xbdbd00bd
+.long	0x10101000,0xb8b800b8
+.long	0xc4c4c400,0x8f8f008f
+.long	0x00000000,0xebeb00eb
+.long	0x48484800,0xcece00ce
+.long	0xa3a3a300,0x30300030
+.long	0xf7f7f700,0x5f5f005f
+.long	0x75757500,0xc5c500c5
+.long	0xdbdbdb00,0x1a1a001a
+.long	0x8a8a8a00,0xe1e100e1
+.long	0x03030300,0xcaca00ca
+.long	0xe6e6e600,0x47470047
+.long	0xdadada00,0x3d3d003d
+.long	0x09090900,0x01010001
+.long	0x3f3f3f00,0xd6d600d6
+.long	0xdddddd00,0x56560056
+.long	0x94949400,0x4d4d004d
+.long	0x87878700,0x0d0d000d
+.long	0x5c5c5c00,0x66660066
+.long	0x83838300,0xcccc00cc
+.long	0x02020200,0x2d2d002d
+.long	0xcdcdcd00,0x12120012
+.long	0x4a4a4a00,0x20200020
+.long	0x90909000,0xb1b100b1
+.long	0x33333300,0x99990099
+.long	0x73737300,0x4c4c004c
+.long	0x67676700,0xc2c200c2
+.long	0xf6f6f600,0x7e7e007e
+.long	0xf3f3f300,0x05050005
+.long	0x9d9d9d00,0xb7b700b7
+.long	0x7f7f7f00,0x31310031
+.long	0xbfbfbf00,0x17170017
+.long	0xe2e2e200,0xd7d700d7
+.long	0x52525200,0x58580058
+.long	0x9b9b9b00,0x61610061
+.long	0xd8d8d800,0x1b1b001b
+.long	0x26262600,0x1c1c001c
+.long	0xc8c8c800,0x0f0f000f
+.long	0x37373700,0x16160016
+.long	0xc6c6c600,0x18180018
+.long	0x3b3b3b00,0x22220022
+.long	0x81818100,0x44440044
+.long	0x96969600,0xb2b200b2
+.long	0x6f6f6f00,0xb5b500b5
+.long	0x4b4b4b00,0x91910091
+.long	0x13131300,0x08080008
+.long	0xbebebe00,0xa8a800a8
+.long	0x63636300,0xfcfc00fc
+.long	0x2e2e2e00,0x50500050
+.long	0xe9e9e900,0xd0d000d0
+.long	0x79797900,0x7d7d007d
+.long	0xa7a7a700,0x89890089
+.long	0x8c8c8c00,0x97970097
+.long	0x9f9f9f00,0x5b5b005b
+.long	0x6e6e6e00,0x95950095
+.long	0xbcbcbc00,0xffff00ff
+.long	0x8e8e8e00,0xd2d200d2
+.long	0x29292900,0xc4c400c4
+.long	0xf5f5f500,0x48480048
+.long	0xf9f9f900,0xf7f700f7
+.long	0xb6b6b600,0xdbdb00db
+.long	0x2f2f2f00,0x03030003
+.long	0xfdfdfd00,0xdada00da
+.long	0xb4b4b400,0x3f3f003f
+.long	0x59595900,0x94940094
+.long	0x78787800,0x5c5c005c
+.long	0x98989800,0x02020002
+.long	0x06060600,0x4a4a004a
+.long	0x6a6a6a00,0x33330033
+.long	0xe7e7e700,0x67670067
+.long	0x46464600,0xf3f300f3
+.long	0x71717100,0x7f7f007f
+.long	0xbababa00,0xe2e200e2
+.long	0xd4d4d400,0x9b9b009b
+.long	0x25252500,0x26260026
+.long	0xababab00,0x37370037
+.long	0x42424200,0x3b3b003b
+.long	0x88888800,0x96960096
+.long	0xa2a2a200,0x4b4b004b
+.long	0x8d8d8d00,0xbebe00be
+.long	0xfafafa00,0x2e2e002e
+.long	0x72727200,0x79790079
+.long	0x07070700,0x8c8c008c
+.long	0xb9b9b900,0x6e6e006e
+.long	0x55555500,0x8e8e008e
+.long	0xf8f8f800,0xf5f500f5
+.long	0xeeeeee00,0xb6b600b6
+.long	0xacacac00,0xfdfd00fd
+.long	0x0a0a0a00,0x59590059
+.long	0x36363600,0x98980098
+.long	0x49494900,0x6a6a006a
+.long	0x2a2a2a00,0x46460046
+.long	0x68686800,0xbaba00ba
+.long	0x3c3c3c00,0x25250025
+.long	0x38383800,0x42420042
+.long	0xf1f1f100,0xa2a200a2
+.long	0xa4a4a400,0xfafa00fa
+.long	0x40404000,0x07070007
+.long	0x28282800,0x55550055
+.long	0xd3d3d300,0xeeee00ee
+.long	0x7b7b7b00,0x0a0a000a
+.long	0xbbbbbb00,0x49490049
+.long	0xc9c9c900,0x68680068
+.long	0x43434300,0x38380038
+.long	0xc1c1c100,0xa4a400a4
+.long	0x15151500,0x28280028
+.long	0xe3e3e300,0x7b7b007b
+.long	0xadadad00,0xc9c900c9
+.long	0xf4f4f400,0xc1c100c1
+.long	0x77777700,0xe3e300e3
+.long	0xc7c7c700,0xf4f400f4
+.long	0x80808000,0xc7c700c7
+.long	0x9e9e9e00,0x9e9e009e
+.long	0x00e0e0e0,0x38003838
+.long	0x00050505,0x41004141
+.long	0x00585858,0x16001616
+.long	0x00d9d9d9,0x76007676
+.long	0x00676767,0xd900d9d9
+.long	0x004e4e4e,0x93009393
+.long	0x00818181,0x60006060
+.long	0x00cbcbcb,0xf200f2f2
+.long	0x00c9c9c9,0x72007272
+.long	0x000b0b0b,0xc200c2c2
+.long	0x00aeaeae,0xab00abab
+.long	0x006a6a6a,0x9a009a9a
+.long	0x00d5d5d5,0x75007575
+.long	0x00181818,0x06000606
+.long	0x005d5d5d,0x57005757
+.long	0x00828282,0xa000a0a0
+.long	0x00464646,0x91009191
+.long	0x00dfdfdf,0xf700f7f7
+.long	0x00d6d6d6,0xb500b5b5
+.long	0x00272727,0xc900c9c9
+.long	0x008a8a8a,0xa200a2a2
+.long	0x00323232,0x8c008c8c
+.long	0x004b4b4b,0xd200d2d2
+.long	0x00424242,0x90009090
+.long	0x00dbdbdb,0xf600f6f6
+.long	0x001c1c1c,0x07000707
+.long	0x009e9e9e,0xa700a7a7
+.long	0x009c9c9c,0x27002727
+.long	0x003a3a3a,0x8e008e8e
+.long	0x00cacaca,0xb200b2b2
+.long	0x00252525,0x49004949
+.long	0x007b7b7b,0xde00dede
+.long	0x000d0d0d,0x43004343
+.long	0x00717171,0x5c005c5c
+.long	0x005f5f5f,0xd700d7d7
+.long	0x001f1f1f,0xc700c7c7
+.long	0x00f8f8f8,0x3e003e3e
+.long	0x00d7d7d7,0xf500f5f5
+.long	0x003e3e3e,0x8f008f8f
+.long	0x009d9d9d,0x67006767
+.long	0x007c7c7c,0x1f001f1f
+.long	0x00606060,0x18001818
+.long	0x00b9b9b9,0x6e006e6e
+.long	0x00bebebe,0xaf00afaf
+.long	0x00bcbcbc,0x2f002f2f
+.long	0x008b8b8b,0xe200e2e2
+.long	0x00161616,0x85008585
+.long	0x00343434,0x0d000d0d
+.long	0x004d4d4d,0x53005353
+.long	0x00c3c3c3,0xf000f0f0
+.long	0x00727272,0x9c009c9c
+.long	0x00959595,0x65006565
+.long	0x00ababab,0xea00eaea
+.long	0x008e8e8e,0xa300a3a3
+.long	0x00bababa,0xae00aeae
+.long	0x007a7a7a,0x9e009e9e
+.long	0x00b3b3b3,0xec00ecec
+.long	0x00020202,0x80008080
+.long	0x00b4b4b4,0x2d002d2d
+.long	0x00adadad,0x6b006b6b
+.long	0x00a2a2a2,0xa800a8a8
+.long	0x00acacac,0x2b002b2b
+.long	0x00d8d8d8,0x36003636
+.long	0x009a9a9a,0xa600a6a6
+.long	0x00171717,0xc500c5c5
+.long	0x001a1a1a,0x86008686
+.long	0x00353535,0x4d004d4d
+.long	0x00cccccc,0x33003333
+.long	0x00f7f7f7,0xfd00fdfd
+.long	0x00999999,0x66006666
+.long	0x00616161,0x58005858
+.long	0x005a5a5a,0x96009696
+.long	0x00e8e8e8,0x3a003a3a
+.long	0x00242424,0x09000909
+.long	0x00565656,0x95009595
+.long	0x00404040,0x10001010
+.long	0x00e1e1e1,0x78007878
+.long	0x00636363,0xd800d8d8
+.long	0x00090909,0x42004242
+.long	0x00333333,0xcc00cccc
+.long	0x00bfbfbf,0xef00efef
+.long	0x00989898,0x26002626
+.long	0x00979797,0xe500e5e5
+.long	0x00858585,0x61006161
+.long	0x00686868,0x1a001a1a
+.long	0x00fcfcfc,0x3f003f3f
+.long	0x00ececec,0x3b003b3b
+.long	0x000a0a0a,0x82008282
+.long	0x00dadada,0xb600b6b6
+.long	0x006f6f6f,0xdb00dbdb
+.long	0x00535353,0xd400d4d4
+.long	0x00626262,0x98009898
+.long	0x00a3a3a3,0xe800e8e8
+.long	0x002e2e2e,0x8b008b8b
+.long	0x00080808,0x02000202
+.long	0x00afafaf,0xeb00ebeb
+.long	0x00282828,0x0a000a0a
+.long	0x00b0b0b0,0x2c002c2c
+.long	0x00747474,0x1d001d1d
+.long	0x00c2c2c2,0xb000b0b0
+.long	0x00bdbdbd,0x6f006f6f
+.long	0x00363636,0x8d008d8d
+.long	0x00222222,0x88008888
+.long	0x00383838,0x0e000e0e
+.long	0x00646464,0x19001919
+.long	0x001e1e1e,0x87008787
+.long	0x00393939,0x4e004e4e
+.long	0x002c2c2c,0x0b000b0b
+.long	0x00a6a6a6,0xa900a9a9
+.long	0x00303030,0x0c000c0c
+.long	0x00e5e5e5,0x79007979
+.long	0x00444444,0x11001111
+.long	0x00fdfdfd,0x7f007f7f
+.long	0x00888888,0x22002222
+.long	0x009f9f9f,0xe700e7e7
+.long	0x00656565,0x59005959
+.long	0x00878787,0xe100e1e1
+.long	0x006b6b6b,0xda00dada
+.long	0x00f4f4f4,0x3d003d3d
+.long	0x00232323,0xc800c8c8
+.long	0x00484848,0x12001212
+.long	0x00101010,0x04000404
+.long	0x00d1d1d1,0x74007474
+.long	0x00515151,0x54005454
+.long	0x00c0c0c0,0x30003030
+.long	0x00f9f9f9,0x7e007e7e
+.long	0x00d2d2d2,0xb400b4b4
+.long	0x00a0a0a0,0x28002828
+.long	0x00555555,0x55005555
+.long	0x00a1a1a1,0x68006868
+.long	0x00414141,0x50005050
+.long	0x00fafafa,0xbe00bebe
+.long	0x00434343,0xd000d0d0
+.long	0x00131313,0xc400c4c4
+.long	0x00c4c4c4,0x31003131
+.long	0x002f2f2f,0xcb00cbcb
+.long	0x00a8a8a8,0x2a002a2a
+.long	0x00b6b6b6,0xad00adad
+.long	0x003c3c3c,0x0f000f0f
+.long	0x002b2b2b,0xca00caca
+.long	0x00c1c1c1,0x70007070
+.long	0x00ffffff,0xff00ffff
+.long	0x00c8c8c8,0x32003232
+.long	0x00a5a5a5,0x69006969
+.long	0x00202020,0x08000808
+.long	0x00898989,0x62006262
+.long	0x00000000,0x00000000
+.long	0x00909090,0x24002424
+.long	0x00474747,0xd100d1d1
+.long	0x00efefef,0xfb00fbfb
+.long	0x00eaeaea,0xba00baba
+.long	0x00b7b7b7,0xed00eded
+.long	0x00151515,0x45004545
+.long	0x00060606,0x81008181
+.long	0x00cdcdcd,0x73007373
+.long	0x00b5b5b5,0x6d006d6d
+.long	0x00121212,0x84008484
+.long	0x007e7e7e,0x9f009f9f
+.long	0x00bbbbbb,0xee00eeee
+.long	0x00292929,0x4a004a4a
+.long	0x000f0f0f,0xc300c3c3
+.long	0x00b8b8b8,0x2e002e2e
+.long	0x00070707,0xc100c1c1
+.long	0x00040404,0x01000101
+.long	0x009b9b9b,0xe600e6e6
+.long	0x00949494,0x25002525
+.long	0x00212121,0x48004848
+.long	0x00666666,0x99009999
+.long	0x00e6e6e6,0xb900b9b9
+.long	0x00cecece,0xb300b3b3
+.long	0x00ededed,0x7b007b7b
+.long	0x00e7e7e7,0xf900f9f9
+.long	0x003b3b3b,0xce00cece
+.long	0x00fefefe,0xbf00bfbf
+.long	0x007f7f7f,0xdf00dfdf
+.long	0x00c5c5c5,0x71007171
+.long	0x00a4a4a4,0x29002929
+.long	0x00373737,0xcd00cdcd
+.long	0x00b1b1b1,0x6c006c6c
+.long	0x004c4c4c,0x13001313
+.long	0x00919191,0x64006464
+.long	0x006e6e6e,0x9b009b9b
+.long	0x008d8d8d,0x63006363
+.long	0x00767676,0x9d009d9d
+.long	0x00030303,0xc000c0c0
+.long	0x002d2d2d,0x4b004b4b
+.long	0x00dedede,0xb700b7b7
+.long	0x00969696,0xa500a5a5
+.long	0x00262626,0x89008989
+.long	0x007d7d7d,0x5f005f5f
+.long	0x00c6c6c6,0xb100b1b1
+.long	0x005c5c5c,0x17001717
+.long	0x00d3d3d3,0xf400f4f4
+.long	0x00f2f2f2,0xbc00bcbc
+.long	0x004f4f4f,0xd300d3d3
+.long	0x00191919,0x46004646
+.long	0x003f3f3f,0xcf00cfcf
+.long	0x00dcdcdc,0x37003737
+.long	0x00797979,0x5e005e5e
+.long	0x001d1d1d,0x47004747
+.long	0x00525252,0x94009494
+.long	0x00ebebeb,0xfa00fafa
+.long	0x00f3f3f3,0xfc00fcfc
+.long	0x006d6d6d,0x5b005b5b
+.long	0x005e5e5e,0x97009797
+.long	0x00fbfbfb,0xfe00fefe
+.long	0x00696969,0x5a005a5a
+.long	0x00b2b2b2,0xac00acac
+.long	0x00f0f0f0,0x3c003c3c
+.long	0x00313131,0x4c004c4c
+.long	0x000c0c0c,0x03000303
+.long	0x00d4d4d4,0x35003535
+.long	0x00cfcfcf,0xf300f3f3
+.long	0x008c8c8c,0x23002323
+.long	0x00e2e2e2,0xb800b8b8
+.long	0x00757575,0x5d005d5d
+.long	0x00a9a9a9,0x6a006a6a
+.long	0x004a4a4a,0x92009292
+.long	0x00575757,0xd500d5d5
+.long	0x00848484,0x21002121
+.long	0x00111111,0x44004444
+.long	0x00454545,0x51005151
+.long	0x001b1b1b,0xc600c6c6
+.long	0x00f5f5f5,0x7d007d7d
+.long	0x00e4e4e4,0x39003939
+.long	0x000e0e0e,0x83008383
+.long	0x00737373,0xdc00dcdc
+.long	0x00aaaaaa,0xaa00aaaa
+.long	0x00f1f1f1,0x7c007c7c
+.long	0x00dddddd,0x77007777
+.long	0x00595959,0x56005656
+.long	0x00141414,0x05000505
+.long	0x006c6c6c,0x1b001b1b
+.long	0x00929292,0xa400a4a4
+.long	0x00545454,0x15001515
+.long	0x00d0d0d0,0x34003434
+.long	0x00787878,0x1e001e1e
+.long	0x00707070,0x1c001c1c
+.long	0x00e3e3e3,0xf800f8f8
+.long	0x00494949,0x52005252
+.long	0x00808080,0x20002020
+.long	0x00505050,0x14001414
+.long	0x00a7a7a7,0xe900e9e9
+.long	0x00f6f6f6,0xbd00bdbd
+.long	0x00777777,0xdd00dddd
+.long	0x00939393,0xe400e4e4
+.long	0x00868686,0xa100a1a1
+.long	0x00838383,0xe000e0e0
+.long	0x002a2a2a,0x8a008a8a
+.long	0x00c7c7c7,0xf100f1f1
+.long	0x005b5b5b,0xd600d6d6
+.long	0x00e9e9e9,0x7a007a7a
+.long	0x00eeeeee,0xbb00bbbb
+.long	0x008f8f8f,0xe300e3e3
+.long	0x00010101,0x40004040
+.long	0x003d3d3d,0x4f004f4f
+.globl	_Camellia_cbc_encrypt
+
+.p2align	4
+_Camellia_cbc_encrypt:
+	cmpq	$0,%rdx
+	je	L$cbc_abort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+L$cbc_prologue:
+
+	movq	%rsp,%rbp
+	subq	$64,%rsp
+	andq	$-64,%rsp
+
+
+
+	leaq	-64-63(%rcx),%r10
+	subq	%rsp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rsp
+
+
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%r8,%rbx
+	movq	%rcx,%r14
+	movl	272(%rcx),%r15d
+
+	movq	%r8,40(%rsp)
+	movq	%rbp,48(%rsp)
+
+L$cbc_body:
+	leaq	L$Camellia_SBOX(%rip),%rbp
+
+	movl	$32,%ecx
+.p2align	2
+L$cbc_prefetch_sbox:
+	movq	0(%rbp),%rax
+	movq	32(%rbp),%rsi
+	movq	64(%rbp),%rdi
+	movq	96(%rbp),%r11
+	leaq	128(%rbp),%rbp
+	loop	L$cbc_prefetch_sbox
+	subq	$4096,%rbp
+	shlq	$6,%r15
+	movq	%rdx,%rcx
+	leaq	(%r14,%r15,1),%r15
+
+	cmpl	$0,%r9d
+	je	L$CBC_DECRYPT
+
+	andq	$-16,%rdx
+	andq	$15,%rcx
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%r14,0(%rsp)
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	cmpq	%r12,%rdx
+	movl	0(%rbx),%r8d
+	movl	4(%rbx),%r9d
+	movl	8(%rbx),%r10d
+	movl	12(%rbx),%r11d
+	je	L$cbc_enc_tail
+	jmp	L$cbc_eloop
+
+.p2align	4
+L$cbc_eloop:
+	xorl	0(%r12),%r8d
+	xorl	4(%r12),%r9d
+	xorl	8(%r12),%r10d
+	bswapl	%r8d
+	xorl	12(%r12),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	movq	0(%rsp),%r14
+	bswapl	%r8d
+	movq	8(%rsp),%rdx
+	bswapl	%r9d
+	movq	16(%rsp),%rcx
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	leaq	16(%r12),%r12
+	movl	%r11d,12(%r13)
+	cmpq	%rdx,%r12
+	leaq	16(%r13),%r13
+	jne	L$cbc_eloop
+
+	cmpq	$0,%rcx
+	jne	L$cbc_enc_tail
+
+	movq	40(%rsp),%r13
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+	jmp	L$cbc_done
+
+.p2align	4
+L$cbc_enc_tail:
+	xorq	%rax,%rax
+	movq	%rax,0+24(%rsp)
+	movq	%rax,8+24(%rsp)
+	movq	%rax,16(%rsp)
+
+L$cbc_enc_pushf:
+	pushfq
+	cld
+	movq	%r12,%rsi
+	leaq	8+24(%rsp),%rdi
+.long	0x9066A4F3		
+	popfq
+L$cbc_enc_popf:
+
+	leaq	24(%rsp),%r12
+	leaq	16+24(%rsp),%rax
+	movq	%rax,8(%rsp)
+	jmp	L$cbc_eloop		
+
+.p2align	4
+L$CBC_DECRYPT:
+	xchgq	%r14,%r15
+	addq	$15,%rdx
+	andq	$15,%rcx
+	andq	$-16,%rdx
+	movq	%r14,0(%rsp)
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	movq	(%rbx),%rax
+	movq	8(%rbx),%rbx
+	jmp	L$cbc_dloop
+.p2align	4
+L$cbc_dloop:
+	movl	0(%r12),%r8d
+	movl	4(%r12),%r9d
+	movl	8(%r12),%r10d
+	bswapl	%r8d
+	movl	12(%r12),%r11d
+	bswapl	%r9d
+	movq	%rax,0+24(%rsp)
+	bswapl	%r10d
+	movq	%rbx,8+24(%rsp)
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	movq	0(%rsp),%r14
+	movq	8(%rsp),%rdx
+	movq	16(%rsp),%rcx
+
+	bswapl	%r8d
+	movq	(%r12),%rax
+	bswapl	%r9d
+	movq	8(%r12),%rbx
+	bswapl	%r10d
+	xorl	0+24(%rsp),%r8d
+	bswapl	%r11d
+	xorl	4+24(%rsp),%r9d
+	xorl	8+24(%rsp),%r10d
+	leaq	16(%r12),%r12
+	xorl	12+24(%rsp),%r11d
+	cmpq	%rdx,%r12
+	je	L$cbc_ddone
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	leaq	16(%r13),%r13
+	jmp	L$cbc_dloop
+
+.p2align	4
+L$cbc_ddone:
+	movq	40(%rsp),%rdx
+	cmpq	$0,%rcx
+	jne	L$cbc_dec_tail
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	L$cbc_done
+.p2align	4
+L$cbc_dec_tail:
+	movl	%r8d,0+24(%rsp)
+	movl	%r9d,4+24(%rsp)
+	movl	%r10d,8+24(%rsp)
+	movl	%r11d,12+24(%rsp)
+
+L$cbc_dec_pushf:
+	pushfq
+	cld
+	leaq	8+24(%rsp),%rsi
+	leaq	(%r13),%rdi
+.long	0x9066A4F3		
+	popfq
+L$cbc_dec_popf:
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	L$cbc_done
+
+.p2align	4
+L$cbc_done:
+	movq	48(%rsp),%rcx
+	movq	0(%rcx),%r15
+	movq	8(%rcx),%r14
+	movq	16(%rcx),%r13
+	movq	24(%rcx),%r12
+	movq	32(%rcx),%rbp
+	movq	40(%rcx),%rbx
+	leaq	48(%rcx),%rsp
+L$cbc_abort:
+	retq
+
+
+.byte	67,97,109,101,108,108,105,97,32,102,111,114,32,120,56,54,95,54,52,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
diff --git a/crypto/camellia/cmll-masm-x86_64.S b/crypto/camellia/cmll-masm-x86_64.S
new file mode 100644
index 0000000..d39c08d
--- /dev/null
+++ b/crypto/camellia/cmll-masm-x86_64.S
@@ -0,0 +1,1966 @@
+; 1 "crypto/camellia/cmll-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/camellia/cmll-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/camellia/cmll-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+
+PUBLIC	Camellia_EncryptBlock
+
+ALIGN	16
+Camellia_EncryptBlock	PROC PUBLIC
+	mov	eax,128
+	sub	eax,edi
+	mov	edi,3
+	adc	edi,0
+	jmp	$L$enc_rounds
+Camellia_EncryptBlock	ENDP
+
+PUBLIC	Camellia_EncryptBlock_Rounds
+
+ALIGN	16
+$L$enc_rounds::
+Camellia_EncryptBlock_Rounds	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_Camellia_EncryptBlock_Rounds::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbx
+	push	rbp
+	push	r13
+	push	r14
+	push	r15
+$L$enc_prologue::
+
+
+	mov	r13,rcx
+	mov	r14,rdx
+
+	shl	edi,6
+	lea	rbp,QWORD PTR[$L$Camellia_SBOX]
+	lea	r15,QWORD PTR[rdi*1+r14]
+
+	mov	r8d,DWORD PTR[rsi]
+	mov	r9d,DWORD PTR[4+rsi]
+	mov	r10d,DWORD PTR[8+rsi]
+	bswap	r8d
+	mov	r11d,DWORD PTR[12+rsi]
+	bswap	r9d
+	bswap	r10d
+	bswap	r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	bswap	r8d
+	bswap	r9d
+	bswap	r10d
+	mov	DWORD PTR[r13],r8d
+	bswap	r11d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	mov	DWORD PTR[12+r13],r11d
+
+	mov	r15,QWORD PTR[rsp]
+	mov	r14,QWORD PTR[8+rsp]
+	mov	r13,QWORD PTR[16+rsp]
+	mov	rbp,QWORD PTR[24+rsp]
+	mov	rbx,QWORD PTR[32+rsp]
+	lea	rsp,QWORD PTR[40+rsp]
+$L$enc_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_Camellia_EncryptBlock_Rounds::
+Camellia_EncryptBlock_Rounds	ENDP
+
+
+ALIGN	16
+_x86_64_Camellia_encrypt	PROC PRIVATE
+	xor	r9d,DWORD PTR[r14]
+	xor	r8d,DWORD PTR[4+r14]
+	xor	r11d,DWORD PTR[8+r14]
+	xor	r10d,DWORD PTR[12+r14]
+ALIGN	16
+$L$eloop::
+	mov	ebx,DWORD PTR[16+r14]
+	mov	eax,DWORD PTR[20+r14]
+
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[24+r14]
+	mov	eax,DWORD PTR[28+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[32+r14]
+	mov	eax,DWORD PTR[36+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[40+r14]
+	mov	eax,DWORD PTR[44+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[48+r14]
+	mov	eax,DWORD PTR[52+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[56+r14]
+	mov	eax,DWORD PTR[60+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[64+r14]
+	mov	eax,DWORD PTR[68+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	lea	r14,QWORD PTR[64+r14]
+	cmp	r14,r15
+	mov	edx,DWORD PTR[8+r14]
+	mov	ecx,DWORD PTR[12+r14]
+	je	$L$edone
+
+	and	eax,r8d
+	or	edx,r11d
+	rol	eax,1
+	xor	r10d,edx
+	xor	r9d,eax
+	and	ecx,r10d
+	or	ebx,r9d
+	rol	ecx,1
+	xor	r8d,ebx
+	xor	r11d,ecx
+	jmp	$L$eloop
+
+ALIGN	16
+$L$edone::
+	xor	eax,r10d
+	xor	ebx,r11d
+	xor	ecx,r8d
+	xor	edx,r9d
+
+	mov	r8d,eax
+	mov	r9d,ebx
+	mov	r10d,ecx
+	mov	r11d,edx
+
+	DB	0F3h,0C3h		;repret
+_x86_64_Camellia_encrypt	ENDP
+
+
+PUBLIC	Camellia_DecryptBlock
+
+ALIGN	16
+Camellia_DecryptBlock	PROC PUBLIC
+	mov	eax,128
+	sub	eax,edi
+	mov	edi,3
+	adc	edi,0
+	jmp	$L$dec_rounds
+Camellia_DecryptBlock	ENDP
+
+PUBLIC	Camellia_DecryptBlock_Rounds
+
+ALIGN	16
+$L$dec_rounds::
+Camellia_DecryptBlock_Rounds	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_Camellia_DecryptBlock_Rounds::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbx
+	push	rbp
+	push	r13
+	push	r14
+	push	r15
+$L$dec_prologue::
+
+
+	mov	r13,rcx
+	mov	r15,rdx
+
+	shl	edi,6
+	lea	rbp,QWORD PTR[$L$Camellia_SBOX]
+	lea	r14,QWORD PTR[rdi*1+r15]
+
+	mov	r8d,DWORD PTR[rsi]
+	mov	r9d,DWORD PTR[4+rsi]
+	mov	r10d,DWORD PTR[8+rsi]
+	bswap	r8d
+	mov	r11d,DWORD PTR[12+rsi]
+	bswap	r9d
+	bswap	r10d
+	bswap	r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	bswap	r8d
+	bswap	r9d
+	bswap	r10d
+	mov	DWORD PTR[r13],r8d
+	bswap	r11d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	mov	DWORD PTR[12+r13],r11d
+
+	mov	r15,QWORD PTR[rsp]
+	mov	r14,QWORD PTR[8+rsp]
+	mov	r13,QWORD PTR[16+rsp]
+	mov	rbp,QWORD PTR[24+rsp]
+	mov	rbx,QWORD PTR[32+rsp]
+	lea	rsp,QWORD PTR[40+rsp]
+$L$dec_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_Camellia_DecryptBlock_Rounds::
+Camellia_DecryptBlock_Rounds	ENDP
+
+
+ALIGN	16
+_x86_64_Camellia_decrypt	PROC PRIVATE
+	xor	r9d,DWORD PTR[r14]
+	xor	r8d,DWORD PTR[4+r14]
+	xor	r11d,DWORD PTR[8+r14]
+	xor	r10d,DWORD PTR[12+r14]
+ALIGN	16
+$L$dloop::
+	mov	ebx,DWORD PTR[((-8))+r14]
+	mov	eax,DWORD PTR[((-4))+r14]
+
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-16))+r14]
+	mov	eax,DWORD PTR[((-12))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-24))+r14]
+	mov	eax,DWORD PTR[((-20))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-32))+r14]
+	mov	eax,DWORD PTR[((-28))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-40))+r14]
+	mov	eax,DWORD PTR[((-36))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-48))+r14]
+	mov	eax,DWORD PTR[((-44))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[((-56))+r14]
+	mov	eax,DWORD PTR[((-52))+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	lea	r14,QWORD PTR[((-64))+r14]
+	cmp	r14,r15
+	mov	edx,DWORD PTR[r14]
+	mov	ecx,DWORD PTR[4+r14]
+	je	$L$ddone
+
+	and	eax,r8d
+	or	edx,r11d
+	rol	eax,1
+	xor	r10d,edx
+	xor	r9d,eax
+	and	ecx,r10d
+	or	ebx,r9d
+	rol	ecx,1
+	xor	r8d,ebx
+	xor	r11d,ecx
+
+	jmp	$L$dloop
+
+ALIGN	16
+$L$ddone::
+	xor	ecx,r10d
+	xor	edx,r11d
+	xor	eax,r8d
+	xor	ebx,r9d
+
+	mov	r8d,ecx
+	mov	r9d,edx
+	mov	r10d,eax
+	mov	r11d,ebx
+
+	DB	0F3h,0C3h		;repret
+_x86_64_Camellia_decrypt	ENDP
+PUBLIC	Camellia_Ekeygen
+
+ALIGN	16
+Camellia_Ekeygen	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_Camellia_Ekeygen::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r13
+	push	r14
+	push	r15
+$L$key_prologue::
+
+	mov	r15,rdi
+	mov	r13,rdx
+
+	mov	r8d,DWORD PTR[rsi]
+	mov	r9d,DWORD PTR[4+rsi]
+	mov	r10d,DWORD PTR[8+rsi]
+	mov	r11d,DWORD PTR[12+rsi]
+
+	bswap	r8d
+	bswap	r9d
+	bswap	r10d
+	bswap	r11d
+	mov	DWORD PTR[r13],r9d
+	mov	DWORD PTR[4+r13],r8d
+	mov	DWORD PTR[8+r13],r11d
+	mov	DWORD PTR[12+r13],r10d
+	cmp	r15,128
+	je	$L$1st128
+
+	mov	r8d,DWORD PTR[16+rsi]
+	mov	r9d,DWORD PTR[20+rsi]
+	cmp	r15,192
+	je	$L$1st192
+	mov	r10d,DWORD PTR[24+rsi]
+	mov	r11d,DWORD PTR[28+rsi]
+	jmp	$L$1st256
+$L$1st192::
+	mov	r10d,r8d
+	mov	r11d,r9d
+	not	r10d
+	not	r11d
+$L$1st256::
+	bswap	r8d
+	bswap	r9d
+	bswap	r10d
+	bswap	r11d
+	mov	DWORD PTR[32+r13],r9d
+	mov	DWORD PTR[36+r13],r8d
+	mov	DWORD PTR[40+r13],r11d
+	mov	DWORD PTR[44+r13],r10d
+	xor	r9d,DWORD PTR[r13]
+	xor	r8d,DWORD PTR[4+r13]
+	xor	r11d,DWORD PTR[8+r13]
+	xor	r10d,DWORD PTR[12+r13]
+
+$L$1st128::
+	lea	r14,QWORD PTR[$L$Camellia_SIGMA]
+	lea	rbp,QWORD PTR[$L$Camellia_SBOX]
+
+	mov	ebx,DWORD PTR[r14]
+	mov	eax,DWORD PTR[4+r14]
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[8+r14]
+	mov	eax,DWORD PTR[12+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[16+r14]
+	mov	eax,DWORD PTR[20+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	xor	r9d,DWORD PTR[r13]
+	xor	r8d,DWORD PTR[4+r13]
+	xor	r11d,DWORD PTR[8+r13]
+	xor	r10d,DWORD PTR[12+r13]
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[24+r14]
+	mov	eax,DWORD PTR[28+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[32+r14]
+	mov	eax,DWORD PTR[36+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	cmp	r15,128
+	jne	$L$2nd256
+
+	lea	r13,QWORD PTR[128+r13]
+	shl	r8,32
+	shl	r10,32
+	or	r8,r9
+	or	r10,r11
+	mov	rax,QWORD PTR[((-128))+r13]
+	mov	rbx,QWORD PTR[((-120))+r13]
+	mov	QWORD PTR[((-112))+r13],r8
+	mov	QWORD PTR[((-104))+r13],r10
+	mov	r11,rax
+	shl	rax,15
+	mov	r9,rbx
+	shr	r9,49
+	shr	r11,49
+	or	rax,r9
+	shl	rbx,15
+	or	rbx,r11
+	mov	QWORD PTR[((-96))+r13],rax
+	mov	QWORD PTR[((-88))+r13],rbx
+	mov	r11,r8
+	shl	r8,15
+	mov	r9,r10
+	shr	r9,49
+	shr	r11,49
+	or	r8,r9
+	shl	r10,15
+	or	r10,r11
+	mov	QWORD PTR[((-80))+r13],r8
+	mov	QWORD PTR[((-72))+r13],r10
+	mov	r11,r8
+	shl	r8,15
+	mov	r9,r10
+	shr	r9,49
+	shr	r11,49
+	or	r8,r9
+	shl	r10,15
+	or	r10,r11
+	mov	QWORD PTR[((-64))+r13],r8
+	mov	QWORD PTR[((-56))+r13],r10
+	mov	r11,rax
+	shl	rax,30
+	mov	r9,rbx
+	shr	r9,34
+	shr	r11,34
+	or	rax,r9
+	shl	rbx,30
+	or	rbx,r11
+	mov	QWORD PTR[((-48))+r13],rax
+	mov	QWORD PTR[((-40))+r13],rbx
+	mov	r11,r8
+	shl	r8,15
+	mov	r9,r10
+	shr	r9,49
+	shr	r11,49
+	or	r8,r9
+	shl	r10,15
+	or	r10,r11
+	mov	QWORD PTR[((-32))+r13],r8
+	mov	r11,rax
+	shl	rax,15
+	mov	r9,rbx
+	shr	r9,49
+	shr	r11,49
+	or	rax,r9
+	shl	rbx,15
+	or	rbx,r11
+	mov	QWORD PTR[((-24))+r13],rbx
+	mov	r11,r8
+	shl	r8,15
+	mov	r9,r10
+	shr	r9,49
+	shr	r11,49
+	or	r8,r9
+	shl	r10,15
+	or	r10,r11
+	mov	QWORD PTR[((-16))+r13],r8
+	mov	QWORD PTR[((-8))+r13],r10
+	mov	r11,rax
+	shl	rax,17
+	mov	r9,rbx
+	shr	r9,47
+	shr	r11,47
+	or	rax,r9
+	shl	rbx,17
+	or	rbx,r11
+	mov	QWORD PTR[r13],rax
+	mov	QWORD PTR[8+r13],rbx
+	mov	r11,rax
+	shl	rax,17
+	mov	r9,rbx
+	shr	r9,47
+	shr	r11,47
+	or	rax,r9
+	shl	rbx,17
+	or	rbx,r11
+	mov	QWORD PTR[16+r13],rax
+	mov	QWORD PTR[24+r13],rbx
+	mov	r11,r8
+	shl	r8,34
+	mov	r9,r10
+	shr	r9,30
+	shr	r11,30
+	or	r8,r9
+	shl	r10,34
+	or	r10,r11
+	mov	QWORD PTR[32+r13],r8
+	mov	QWORD PTR[40+r13],r10
+	mov	r11,rax
+	shl	rax,17
+	mov	r9,rbx
+	shr	r9,47
+	shr	r11,47
+	or	rax,r9
+	shl	rbx,17
+	or	rbx,r11
+	mov	QWORD PTR[48+r13],rax
+	mov	QWORD PTR[56+r13],rbx
+	mov	r11,r8
+	shl	r8,17
+	mov	r9,r10
+	shr	r9,47
+	shr	r11,47
+	or	r8,r9
+	shl	r10,17
+	or	r10,r11
+	mov	QWORD PTR[64+r13],r8
+	mov	QWORD PTR[72+r13],r10
+	mov	eax,3
+	jmp	$L$done
+ALIGN	16
+$L$2nd256::
+	mov	DWORD PTR[48+r13],r9d
+	mov	DWORD PTR[52+r13],r8d
+	mov	DWORD PTR[56+r13],r11d
+	mov	DWORD PTR[60+r13],r10d
+	xor	r9d,DWORD PTR[32+r13]
+	xor	r8d,DWORD PTR[36+r13]
+	xor	r11d,DWORD PTR[40+r13]
+	xor	r10d,DWORD PTR[44+r13]
+	xor	eax,r8d
+	xor	ebx,r9d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[40+r14]
+	mov	eax,DWORD PTR[44+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r10d,ecx
+	xor	r11d,ecx
+	xor	r11d,edx
+	xor	eax,r10d
+	xor	ebx,r11d
+	movzx	esi,ah
+	movzx	edi,bl
+	mov	edx,DWORD PTR[2052+rsi*8+rbp]
+	mov	ecx,DWORD PTR[rdi*8+rbp]
+	movzx	esi,al
+	shr	eax,16
+	movzx	edi,bh
+	xor	edx,DWORD PTR[4+rsi*8+rbp]
+	shr	ebx,16
+	xor	ecx,DWORD PTR[4+rdi*8+rbp]
+	movzx	esi,ah
+	movzx	edi,bl
+	xor	edx,DWORD PTR[rsi*8+rbp]
+	xor	ecx,DWORD PTR[2052+rdi*8+rbp]
+	movzx	esi,al
+	movzx	edi,bh
+	xor	edx,DWORD PTR[2048+rsi*8+rbp]
+	xor	ecx,DWORD PTR[2048+rdi*8+rbp]
+	mov	ebx,DWORD PTR[48+r14]
+	mov	eax,DWORD PTR[52+r14]
+	xor	ecx,edx
+	ror	edx,8
+	xor	r8d,ecx
+	xor	r9d,ecx
+	xor	r9d,edx
+	mov	rax,QWORD PTR[r13]
+	mov	rbx,QWORD PTR[8+r13]
+	mov	rcx,QWORD PTR[32+r13]
+	mov	rdx,QWORD PTR[40+r13]
+	mov	r14,QWORD PTR[48+r13]
+	mov	r15,QWORD PTR[56+r13]
+	lea	r13,QWORD PTR[128+r13]
+	shl	r8,32
+	shl	r10,32
+	or	r8,r9
+	or	r10,r11
+	mov	QWORD PTR[((-112))+r13],r8
+	mov	QWORD PTR[((-104))+r13],r10
+	mov	r11,rcx
+	shl	rcx,15
+	mov	r9,rdx
+	shr	r9,49
+	shr	r11,49
+	or	rcx,r9
+	shl	rdx,15
+	or	rdx,r11
+	mov	QWORD PTR[((-96))+r13],rcx
+	mov	QWORD PTR[((-88))+r13],rdx
+	mov	r11,r14
+	shl	r14,15
+	mov	r9,r15
+	shr	r9,49
+	shr	r11,49
+	or	r14,r9
+	shl	r15,15
+	or	r15,r11
+	mov	QWORD PTR[((-80))+r13],r14
+	mov	QWORD PTR[((-72))+r13],r15
+	mov	r11,rcx
+	shl	rcx,15
+	mov	r9,rdx
+	shr	r9,49
+	shr	r11,49
+	or	rcx,r9
+	shl	rdx,15
+	or	rdx,r11
+	mov	QWORD PTR[((-64))+r13],rcx
+	mov	QWORD PTR[((-56))+r13],rdx
+	mov	r11,r8
+	shl	r8,30
+	mov	r9,r10
+	shr	r9,34
+	shr	r11,34
+	or	r8,r9
+	shl	r10,30
+	or	r10,r11
+	mov	QWORD PTR[((-48))+r13],r8
+	mov	QWORD PTR[((-40))+r13],r10
+	mov	r11,rax
+	shl	rax,45
+	mov	r9,rbx
+	shr	r9,19
+	shr	r11,19
+	or	rax,r9
+	shl	rbx,45
+	or	rbx,r11
+	mov	QWORD PTR[((-32))+r13],rax
+	mov	QWORD PTR[((-24))+r13],rbx
+	mov	r11,r14
+	shl	r14,30
+	mov	r9,r15
+	shr	r9,34
+	shr	r11,34
+	or	r14,r9
+	shl	r15,30
+	or	r15,r11
+	mov	QWORD PTR[((-16))+r13],r14
+	mov	QWORD PTR[((-8))+r13],r15
+	mov	r11,rax
+	shl	rax,15
+	mov	r9,rbx
+	shr	r9,49
+	shr	r11,49
+	or	rax,r9
+	shl	rbx,15
+	or	rbx,r11
+	mov	QWORD PTR[r13],rax
+	mov	QWORD PTR[8+r13],rbx
+	mov	r11,rcx
+	shl	rcx,30
+	mov	r9,rdx
+	shr	r9,34
+	shr	r11,34
+	or	rcx,r9
+	shl	rdx,30
+	or	rdx,r11
+	mov	QWORD PTR[16+r13],rcx
+	mov	QWORD PTR[24+r13],rdx
+	mov	r11,r8
+	shl	r8,30
+	mov	r9,r10
+	shr	r9,34
+	shr	r11,34
+	or	r8,r9
+	shl	r10,30
+	or	r10,r11
+	mov	QWORD PTR[32+r13],r8
+	mov	QWORD PTR[40+r13],r10
+	mov	r11,rax
+	shl	rax,17
+	mov	r9,rbx
+	shr	r9,47
+	shr	r11,47
+	or	rax,r9
+	shl	rbx,17
+	or	rbx,r11
+	mov	QWORD PTR[48+r13],rax
+	mov	QWORD PTR[56+r13],rbx
+	mov	r11,r14
+	shl	r14,32
+	mov	r9,r15
+	shr	r9,32
+	shr	r11,32
+	or	r14,r9
+	shl	r15,32
+	or	r15,r11
+	mov	QWORD PTR[64+r13],r14
+	mov	QWORD PTR[72+r13],r15
+	mov	r11,rcx
+	shl	rcx,34
+	mov	r9,rdx
+	shr	r9,30
+	shr	r11,30
+	or	rcx,r9
+	shl	rdx,34
+	or	rdx,r11
+	mov	QWORD PTR[80+r13],rcx
+	mov	QWORD PTR[88+r13],rdx
+	mov	r11,r14
+	shl	r14,17
+	mov	r9,r15
+	shr	r9,47
+	shr	r11,47
+	or	r14,r9
+	shl	r15,17
+	or	r15,r11
+	mov	QWORD PTR[96+r13],r14
+	mov	QWORD PTR[104+r13],r15
+	mov	r11,rax
+	shl	rax,34
+	mov	r9,rbx
+	shr	r9,30
+	shr	r11,30
+	or	rax,r9
+	shl	rbx,34
+	or	rbx,r11
+	mov	QWORD PTR[112+r13],rax
+	mov	QWORD PTR[120+r13],rbx
+	mov	r11,r8
+	shl	r8,51
+	mov	r9,r10
+	shr	r9,13
+	shr	r11,13
+	or	r8,r9
+	shl	r10,51
+	or	r10,r11
+	mov	QWORD PTR[128+r13],r8
+	mov	QWORD PTR[136+r13],r10
+	mov	eax,4
+$L$done::
+	mov	r15,QWORD PTR[rsp]
+	mov	r14,QWORD PTR[8+rsp]
+	mov	r13,QWORD PTR[16+rsp]
+	mov	rbp,QWORD PTR[24+rsp]
+	mov	rbx,QWORD PTR[32+rsp]
+	lea	rsp,QWORD PTR[40+rsp]
+$L$key_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_Camellia_Ekeygen::
+Camellia_Ekeygen	ENDP
+ALIGN	64
+$L$Camellia_SIGMA::
+	DD	03bcc908bh,0a09e667fh,04caa73b2h,0b67ae858h
+	DD	0e94f82beh,0c6ef372fh,0f1d36f1ch,054ff53a5h
+	DD	0de682d1dh,010e527fah,0b3e6c1fdh,0b05688c2h
+	DD	0,0,0,0
+$L$Camellia_SBOX::
+	DD	070707000h,070700070h
+	DD	082828200h,02c2c002ch
+	DD	02c2c2c00h,0b3b300b3h
+	DD	0ececec00h,0c0c000c0h
+	DD	0b3b3b300h,0e4e400e4h
+	DD	027272700h,057570057h
+	DD	0c0c0c000h,0eaea00eah
+	DD	0e5e5e500h,0aeae00aeh
+	DD	0e4e4e400h,023230023h
+	DD	085858500h,06b6b006bh
+	DD	057575700h,045450045h
+	DD	035353500h,0a5a500a5h
+	DD	0eaeaea00h,0eded00edh
+	DD	00c0c0c00h,04f4f004fh
+	DD	0aeaeae00h,01d1d001dh
+	DD	041414100h,092920092h
+	DD	023232300h,086860086h
+	DD	0efefef00h,0afaf00afh
+	DD	06b6b6b00h,07c7c007ch
+	DD	093939300h,01f1f001fh
+	DD	045454500h,03e3e003eh
+	DD	019191900h,0dcdc00dch
+	DD	0a5a5a500h,05e5e005eh
+	DD	021212100h,00b0b000bh
+	DD	0ededed00h,0a6a600a6h
+	DD	00e0e0e00h,039390039h
+	DD	04f4f4f00h,0d5d500d5h
+	DD	04e4e4e00h,05d5d005dh
+	DD	01d1d1d00h,0d9d900d9h
+	DD	065656500h,05a5a005ah
+	DD	092929200h,051510051h
+	DD	0bdbdbd00h,06c6c006ch
+	DD	086868600h,08b8b008bh
+	DD	0b8b8b800h,09a9a009ah
+	DD	0afafaf00h,0fbfb00fbh
+	DD	08f8f8f00h,0b0b000b0h
+	DD	07c7c7c00h,074740074h
+	DD	0ebebeb00h,02b2b002bh
+	DD	01f1f1f00h,0f0f000f0h
+	DD	0cecece00h,084840084h
+	DD	03e3e3e00h,0dfdf00dfh
+	DD	030303000h,0cbcb00cbh
+	DD	0dcdcdc00h,034340034h
+	DD	05f5f5f00h,076760076h
+	DD	05e5e5e00h,06d6d006dh
+	DD	0c5c5c500h,0a9a900a9h
+	DD	00b0b0b00h,0d1d100d1h
+	DD	01a1a1a00h,004040004h
+	DD	0a6a6a600h,014140014h
+	DD	0e1e1e100h,03a3a003ah
+	DD	039393900h,0dede00deh
+	DD	0cacaca00h,011110011h
+	DD	0d5d5d500h,032320032h
+	DD	047474700h,09c9c009ch
+	DD	05d5d5d00h,053530053h
+	DD	03d3d3d00h,0f2f200f2h
+	DD	0d9d9d900h,0fefe00feh
+	DD	001010100h,0cfcf00cfh
+	DD	05a5a5a00h,0c3c300c3h
+	DD	0d6d6d600h,07a7a007ah
+	DD	051515100h,024240024h
+	DD	056565600h,0e8e800e8h
+	DD	06c6c6c00h,060600060h
+	DD	04d4d4d00h,069690069h
+	DD	08b8b8b00h,0aaaa00aah
+	DD	00d0d0d00h,0a0a000a0h
+	DD	09a9a9a00h,0a1a100a1h
+	DD	066666600h,062620062h
+	DD	0fbfbfb00h,054540054h
+	DD	0cccccc00h,01e1e001eh
+	DD	0b0b0b000h,0e0e000e0h
+	DD	02d2d2d00h,064640064h
+	DD	074747400h,010100010h
+	DD	012121200h,000000000h
+	DD	02b2b2b00h,0a3a300a3h
+	DD	020202000h,075750075h
+	DD	0f0f0f000h,08a8a008ah
+	DD	0b1b1b100h,0e6e600e6h
+	DD	084848400h,009090009h
+	DD	099999900h,0dddd00ddh
+	DD	0dfdfdf00h,087870087h
+	DD	04c4c4c00h,083830083h
+	DD	0cbcbcb00h,0cdcd00cdh
+	DD	0c2c2c200h,090900090h
+	DD	034343400h,073730073h
+	DD	07e7e7e00h,0f6f600f6h
+	DD	076767600h,09d9d009dh
+	DD	005050500h,0bfbf00bfh
+	DD	06d6d6d00h,052520052h
+	DD	0b7b7b700h,0d8d800d8h
+	DD	0a9a9a900h,0c8c800c8h
+	DD	031313100h,0c6c600c6h
+	DD	0d1d1d100h,081810081h
+	DD	017171700h,06f6f006fh
+	DD	004040400h,013130013h
+	DD	0d7d7d700h,063630063h
+	DD	014141400h,0e9e900e9h
+	DD	058585800h,0a7a700a7h
+	DD	03a3a3a00h,09f9f009fh
+	DD	061616100h,0bcbc00bch
+	DD	0dedede00h,029290029h
+	DD	01b1b1b00h,0f9f900f9h
+	DD	011111100h,02f2f002fh
+	DD	01c1c1c00h,0b4b400b4h
+	DD	032323200h,078780078h
+	DD	00f0f0f00h,006060006h
+	DD	09c9c9c00h,0e7e700e7h
+	DD	016161600h,071710071h
+	DD	053535300h,0d4d400d4h
+	DD	018181800h,0abab00abh
+	DD	0f2f2f200h,088880088h
+	DD	022222200h,08d8d008dh
+	DD	0fefefe00h,072720072h
+	DD	044444400h,0b9b900b9h
+	DD	0cfcfcf00h,0f8f800f8h
+	DD	0b2b2b200h,0acac00ach
+	DD	0c3c3c300h,036360036h
+	DD	0b5b5b500h,02a2a002ah
+	DD	07a7a7a00h,03c3c003ch
+	DD	091919100h,0f1f100f1h
+	DD	024242400h,040400040h
+	DD	008080800h,0d3d300d3h
+	DD	0e8e8e800h,0bbbb00bbh
+	DD	0a8a8a800h,043430043h
+	DD	060606000h,015150015h
+	DD	0fcfcfc00h,0adad00adh
+	DD	069696900h,077770077h
+	DD	050505000h,080800080h
+	DD	0aaaaaa00h,082820082h
+	DD	0d0d0d000h,0ecec00ech
+	DD	0a0a0a000h,027270027h
+	DD	07d7d7d00h,0e5e500e5h
+	DD	0a1a1a100h,085850085h
+	DD	089898900h,035350035h
+	DD	062626200h,00c0c000ch
+	DD	097979700h,041410041h
+	DD	054545400h,0efef00efh
+	DD	05b5b5b00h,093930093h
+	DD	01e1e1e00h,019190019h
+	DD	095959500h,021210021h
+	DD	0e0e0e000h,00e0e000eh
+	DD	0ffffff00h,04e4e004eh
+	DD	064646400h,065650065h
+	DD	0d2d2d200h,0bdbd00bdh
+	DD	010101000h,0b8b800b8h
+	DD	0c4c4c400h,08f8f008fh
+	DD	000000000h,0ebeb00ebh
+	DD	048484800h,0cece00ceh
+	DD	0a3a3a300h,030300030h
+	DD	0f7f7f700h,05f5f005fh
+	DD	075757500h,0c5c500c5h
+	DD	0dbdbdb00h,01a1a001ah
+	DD	08a8a8a00h,0e1e100e1h
+	DD	003030300h,0caca00cah
+	DD	0e6e6e600h,047470047h
+	DD	0dadada00h,03d3d003dh
+	DD	009090900h,001010001h
+	DD	03f3f3f00h,0d6d600d6h
+	DD	0dddddd00h,056560056h
+	DD	094949400h,04d4d004dh
+	DD	087878700h,00d0d000dh
+	DD	05c5c5c00h,066660066h
+	DD	083838300h,0cccc00cch
+	DD	002020200h,02d2d002dh
+	DD	0cdcdcd00h,012120012h
+	DD	04a4a4a00h,020200020h
+	DD	090909000h,0b1b100b1h
+	DD	033333300h,099990099h
+	DD	073737300h,04c4c004ch
+	DD	067676700h,0c2c200c2h
+	DD	0f6f6f600h,07e7e007eh
+	DD	0f3f3f300h,005050005h
+	DD	09d9d9d00h,0b7b700b7h
+	DD	07f7f7f00h,031310031h
+	DD	0bfbfbf00h,017170017h
+	DD	0e2e2e200h,0d7d700d7h
+	DD	052525200h,058580058h
+	DD	09b9b9b00h,061610061h
+	DD	0d8d8d800h,01b1b001bh
+	DD	026262600h,01c1c001ch
+	DD	0c8c8c800h,00f0f000fh
+	DD	037373700h,016160016h
+	DD	0c6c6c600h,018180018h
+	DD	03b3b3b00h,022220022h
+	DD	081818100h,044440044h
+	DD	096969600h,0b2b200b2h
+	DD	06f6f6f00h,0b5b500b5h
+	DD	04b4b4b00h,091910091h
+	DD	013131300h,008080008h
+	DD	0bebebe00h,0a8a800a8h
+	DD	063636300h,0fcfc00fch
+	DD	02e2e2e00h,050500050h
+	DD	0e9e9e900h,0d0d000d0h
+	DD	079797900h,07d7d007dh
+	DD	0a7a7a700h,089890089h
+	DD	08c8c8c00h,097970097h
+	DD	09f9f9f00h,05b5b005bh
+	DD	06e6e6e00h,095950095h
+	DD	0bcbcbc00h,0ffff00ffh
+	DD	08e8e8e00h,0d2d200d2h
+	DD	029292900h,0c4c400c4h
+	DD	0f5f5f500h,048480048h
+	DD	0f9f9f900h,0f7f700f7h
+	DD	0b6b6b600h,0dbdb00dbh
+	DD	02f2f2f00h,003030003h
+	DD	0fdfdfd00h,0dada00dah
+	DD	0b4b4b400h,03f3f003fh
+	DD	059595900h,094940094h
+	DD	078787800h,05c5c005ch
+	DD	098989800h,002020002h
+	DD	006060600h,04a4a004ah
+	DD	06a6a6a00h,033330033h
+	DD	0e7e7e700h,067670067h
+	DD	046464600h,0f3f300f3h
+	DD	071717100h,07f7f007fh
+	DD	0bababa00h,0e2e200e2h
+	DD	0d4d4d400h,09b9b009bh
+	DD	025252500h,026260026h
+	DD	0ababab00h,037370037h
+	DD	042424200h,03b3b003bh
+	DD	088888800h,096960096h
+	DD	0a2a2a200h,04b4b004bh
+	DD	08d8d8d00h,0bebe00beh
+	DD	0fafafa00h,02e2e002eh
+	DD	072727200h,079790079h
+	DD	007070700h,08c8c008ch
+	DD	0b9b9b900h,06e6e006eh
+	DD	055555500h,08e8e008eh
+	DD	0f8f8f800h,0f5f500f5h
+	DD	0eeeeee00h,0b6b600b6h
+	DD	0acacac00h,0fdfd00fdh
+	DD	00a0a0a00h,059590059h
+	DD	036363600h,098980098h
+	DD	049494900h,06a6a006ah
+	DD	02a2a2a00h,046460046h
+	DD	068686800h,0baba00bah
+	DD	03c3c3c00h,025250025h
+	DD	038383800h,042420042h
+	DD	0f1f1f100h,0a2a200a2h
+	DD	0a4a4a400h,0fafa00fah
+	DD	040404000h,007070007h
+	DD	028282800h,055550055h
+	DD	0d3d3d300h,0eeee00eeh
+	DD	07b7b7b00h,00a0a000ah
+	DD	0bbbbbb00h,049490049h
+	DD	0c9c9c900h,068680068h
+	DD	043434300h,038380038h
+	DD	0c1c1c100h,0a4a400a4h
+	DD	015151500h,028280028h
+	DD	0e3e3e300h,07b7b007bh
+	DD	0adadad00h,0c9c900c9h
+	DD	0f4f4f400h,0c1c100c1h
+	DD	077777700h,0e3e300e3h
+	DD	0c7c7c700h,0f4f400f4h
+	DD	080808000h,0c7c700c7h
+	DD	09e9e9e00h,09e9e009eh
+	DD	000e0e0e0h,038003838h
+	DD	000050505h,041004141h
+	DD	000585858h,016001616h
+	DD	000d9d9d9h,076007676h
+	DD	000676767h,0d900d9d9h
+	DD	0004e4e4eh,093009393h
+	DD	000818181h,060006060h
+	DD	000cbcbcbh,0f200f2f2h
+	DD	000c9c9c9h,072007272h
+	DD	0000b0b0bh,0c200c2c2h
+	DD	000aeaeaeh,0ab00ababh
+	DD	0006a6a6ah,09a009a9ah
+	DD	000d5d5d5h,075007575h
+	DD	000181818h,006000606h
+	DD	0005d5d5dh,057005757h
+	DD	000828282h,0a000a0a0h
+	DD	000464646h,091009191h
+	DD	000dfdfdfh,0f700f7f7h
+	DD	000d6d6d6h,0b500b5b5h
+	DD	000272727h,0c900c9c9h
+	DD	0008a8a8ah,0a200a2a2h
+	DD	000323232h,08c008c8ch
+	DD	0004b4b4bh,0d200d2d2h
+	DD	000424242h,090009090h
+	DD	000dbdbdbh,0f600f6f6h
+	DD	0001c1c1ch,007000707h
+	DD	0009e9e9eh,0a700a7a7h
+	DD	0009c9c9ch,027002727h
+	DD	0003a3a3ah,08e008e8eh
+	DD	000cacacah,0b200b2b2h
+	DD	000252525h,049004949h
+	DD	0007b7b7bh,0de00dedeh
+	DD	0000d0d0dh,043004343h
+	DD	000717171h,05c005c5ch
+	DD	0005f5f5fh,0d700d7d7h
+	DD	0001f1f1fh,0c700c7c7h
+	DD	000f8f8f8h,03e003e3eh
+	DD	000d7d7d7h,0f500f5f5h
+	DD	0003e3e3eh,08f008f8fh
+	DD	0009d9d9dh,067006767h
+	DD	0007c7c7ch,01f001f1fh
+	DD	000606060h,018001818h
+	DD	000b9b9b9h,06e006e6eh
+	DD	000bebebeh,0af00afafh
+	DD	000bcbcbch,02f002f2fh
+	DD	0008b8b8bh,0e200e2e2h
+	DD	000161616h,085008585h
+	DD	000343434h,00d000d0dh
+	DD	0004d4d4dh,053005353h
+	DD	000c3c3c3h,0f000f0f0h
+	DD	000727272h,09c009c9ch
+	DD	000959595h,065006565h
+	DD	000abababh,0ea00eaeah
+	DD	0008e8e8eh,0a300a3a3h
+	DD	000bababah,0ae00aeaeh
+	DD	0007a7a7ah,09e009e9eh
+	DD	000b3b3b3h,0ec00ecech
+	DD	000020202h,080008080h
+	DD	000b4b4b4h,02d002d2dh
+	DD	000adadadh,06b006b6bh
+	DD	000a2a2a2h,0a800a8a8h
+	DD	000acacach,02b002b2bh
+	DD	000d8d8d8h,036003636h
+	DD	0009a9a9ah,0a600a6a6h
+	DD	000171717h,0c500c5c5h
+	DD	0001a1a1ah,086008686h
+	DD	000353535h,04d004d4dh
+	DD	000cccccch,033003333h
+	DD	000f7f7f7h,0fd00fdfdh
+	DD	000999999h,066006666h
+	DD	000616161h,058005858h
+	DD	0005a5a5ah,096009696h
+	DD	000e8e8e8h,03a003a3ah
+	DD	000242424h,009000909h
+	DD	000565656h,095009595h
+	DD	000404040h,010001010h
+	DD	000e1e1e1h,078007878h
+	DD	000636363h,0d800d8d8h
+	DD	000090909h,042004242h
+	DD	000333333h,0cc00cccch
+	DD	000bfbfbfh,0ef00efefh
+	DD	000989898h,026002626h
+	DD	000979797h,0e500e5e5h
+	DD	000858585h,061006161h
+	DD	000686868h,01a001a1ah
+	DD	000fcfcfch,03f003f3fh
+	DD	000ececech,03b003b3bh
+	DD	0000a0a0ah,082008282h
+	DD	000dadadah,0b600b6b6h
+	DD	0006f6f6fh,0db00dbdbh
+	DD	000535353h,0d400d4d4h
+	DD	000626262h,098009898h
+	DD	000a3a3a3h,0e800e8e8h
+	DD	0002e2e2eh,08b008b8bh
+	DD	000080808h,002000202h
+	DD	000afafafh,0eb00ebebh
+	DD	000282828h,00a000a0ah
+	DD	000b0b0b0h,02c002c2ch
+	DD	000747474h,01d001d1dh
+	DD	000c2c2c2h,0b000b0b0h
+	DD	000bdbdbdh,06f006f6fh
+	DD	000363636h,08d008d8dh
+	DD	000222222h,088008888h
+	DD	000383838h,00e000e0eh
+	DD	000646464h,019001919h
+	DD	0001e1e1eh,087008787h
+	DD	000393939h,04e004e4eh
+	DD	0002c2c2ch,00b000b0bh
+	DD	000a6a6a6h,0a900a9a9h
+	DD	000303030h,00c000c0ch
+	DD	000e5e5e5h,079007979h
+	DD	000444444h,011001111h
+	DD	000fdfdfdh,07f007f7fh
+	DD	000888888h,022002222h
+	DD	0009f9f9fh,0e700e7e7h
+	DD	000656565h,059005959h
+	DD	000878787h,0e100e1e1h
+	DD	0006b6b6bh,0da00dadah
+	DD	000f4f4f4h,03d003d3dh
+	DD	000232323h,0c800c8c8h
+	DD	000484848h,012001212h
+	DD	000101010h,004000404h
+	DD	000d1d1d1h,074007474h
+	DD	000515151h,054005454h
+	DD	000c0c0c0h,030003030h
+	DD	000f9f9f9h,07e007e7eh
+	DD	000d2d2d2h,0b400b4b4h
+	DD	000a0a0a0h,028002828h
+	DD	000555555h,055005555h
+	DD	000a1a1a1h,068006868h
+	DD	000414141h,050005050h
+	DD	000fafafah,0be00bebeh
+	DD	000434343h,0d000d0d0h
+	DD	000131313h,0c400c4c4h
+	DD	000c4c4c4h,031003131h
+	DD	0002f2f2fh,0cb00cbcbh
+	DD	000a8a8a8h,02a002a2ah
+	DD	000b6b6b6h,0ad00adadh
+	DD	0003c3c3ch,00f000f0fh
+	DD	0002b2b2bh,0ca00cacah
+	DD	000c1c1c1h,070007070h
+	DD	000ffffffh,0ff00ffffh
+	DD	000c8c8c8h,032003232h
+	DD	000a5a5a5h,069006969h
+	DD	000202020h,008000808h
+	DD	000898989h,062006262h
+	DD	000000000h,000000000h
+	DD	000909090h,024002424h
+	DD	000474747h,0d100d1d1h
+	DD	000efefefh,0fb00fbfbh
+	DD	000eaeaeah,0ba00babah
+	DD	000b7b7b7h,0ed00ededh
+	DD	000151515h,045004545h
+	DD	000060606h,081008181h
+	DD	000cdcdcdh,073007373h
+	DD	000b5b5b5h,06d006d6dh
+	DD	000121212h,084008484h
+	DD	0007e7e7eh,09f009f9fh
+	DD	000bbbbbbh,0ee00eeeeh
+	DD	000292929h,04a004a4ah
+	DD	0000f0f0fh,0c300c3c3h
+	DD	000b8b8b8h,02e002e2eh
+	DD	000070707h,0c100c1c1h
+	DD	000040404h,001000101h
+	DD	0009b9b9bh,0e600e6e6h
+	DD	000949494h,025002525h
+	DD	000212121h,048004848h
+	DD	000666666h,099009999h
+	DD	000e6e6e6h,0b900b9b9h
+	DD	000cececeh,0b300b3b3h
+	DD	000edededh,07b007b7bh
+	DD	000e7e7e7h,0f900f9f9h
+	DD	0003b3b3bh,0ce00ceceh
+	DD	000fefefeh,0bf00bfbfh
+	DD	0007f7f7fh,0df00dfdfh
+	DD	000c5c5c5h,071007171h
+	DD	000a4a4a4h,029002929h
+	DD	000373737h,0cd00cdcdh
+	DD	000b1b1b1h,06c006c6ch
+	DD	0004c4c4ch,013001313h
+	DD	000919191h,064006464h
+	DD	0006e6e6eh,09b009b9bh
+	DD	0008d8d8dh,063006363h
+	DD	000767676h,09d009d9dh
+	DD	000030303h,0c000c0c0h
+	DD	0002d2d2dh,04b004b4bh
+	DD	000dededeh,0b700b7b7h
+	DD	000969696h,0a500a5a5h
+	DD	000262626h,089008989h
+	DD	0007d7d7dh,05f005f5fh
+	DD	000c6c6c6h,0b100b1b1h
+	DD	0005c5c5ch,017001717h
+	DD	000d3d3d3h,0f400f4f4h
+	DD	000f2f2f2h,0bc00bcbch
+	DD	0004f4f4fh,0d300d3d3h
+	DD	000191919h,046004646h
+	DD	0003f3f3fh,0cf00cfcfh
+	DD	000dcdcdch,037003737h
+	DD	000797979h,05e005e5eh
+	DD	0001d1d1dh,047004747h
+	DD	000525252h,094009494h
+	DD	000ebebebh,0fa00fafah
+	DD	000f3f3f3h,0fc00fcfch
+	DD	0006d6d6dh,05b005b5bh
+	DD	0005e5e5eh,097009797h
+	DD	000fbfbfbh,0fe00fefeh
+	DD	000696969h,05a005a5ah
+	DD	000b2b2b2h,0ac00acach
+	DD	000f0f0f0h,03c003c3ch
+	DD	000313131h,04c004c4ch
+	DD	0000c0c0ch,003000303h
+	DD	000d4d4d4h,035003535h
+	DD	000cfcfcfh,0f300f3f3h
+	DD	0008c8c8ch,023002323h
+	DD	000e2e2e2h,0b800b8b8h
+	DD	000757575h,05d005d5dh
+	DD	000a9a9a9h,06a006a6ah
+	DD	0004a4a4ah,092009292h
+	DD	000575757h,0d500d5d5h
+	DD	000848484h,021002121h
+	DD	000111111h,044004444h
+	DD	000454545h,051005151h
+	DD	0001b1b1bh,0c600c6c6h
+	DD	000f5f5f5h,07d007d7dh
+	DD	000e4e4e4h,039003939h
+	DD	0000e0e0eh,083008383h
+	DD	000737373h,0dc00dcdch
+	DD	000aaaaaah,0aa00aaaah
+	DD	000f1f1f1h,07c007c7ch
+	DD	000ddddddh,077007777h
+	DD	000595959h,056005656h
+	DD	000141414h,005000505h
+	DD	0006c6c6ch,01b001b1bh
+	DD	000929292h,0a400a4a4h
+	DD	000545454h,015001515h
+	DD	000d0d0d0h,034003434h
+	DD	000787878h,01e001e1eh
+	DD	000707070h,01c001c1ch
+	DD	000e3e3e3h,0f800f8f8h
+	DD	000494949h,052005252h
+	DD	000808080h,020002020h
+	DD	000505050h,014001414h
+	DD	000a7a7a7h,0e900e9e9h
+	DD	000f6f6f6h,0bd00bdbdh
+	DD	000777777h,0dd00ddddh
+	DD	000939393h,0e400e4e4h
+	DD	000868686h,0a100a1a1h
+	DD	000838383h,0e000e0e0h
+	DD	0002a2a2ah,08a008a8ah
+	DD	000c7c7c7h,0f100f1f1h
+	DD	0005b5b5bh,0d600d6d6h
+	DD	000e9e9e9h,07a007a7ah
+	DD	000eeeeeeh,0bb00bbbbh
+	DD	0008f8f8fh,0e300e3e3h
+	DD	000010101h,040004040h
+	DD	0003d3d3dh,04f004f4fh
+PUBLIC	Camellia_cbc_encrypt
+
+ALIGN	16
+Camellia_cbc_encrypt	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_Camellia_cbc_encrypt::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	cmp	rdx,0
+	je	$L$cbc_abort
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+$L$cbc_prologue::
+
+	mov	rbp,rsp
+	sub	rsp,64
+	and	rsp,-64
+
+
+
+	lea	r10,QWORD PTR[((-64-63))+rcx]
+	sub	r10,rsp
+	neg	r10
+	and	r10,03C0h
+	sub	rsp,r10
+
+
+	mov	r12,rdi
+	mov	r13,rsi
+	mov	rbx,r8
+	mov	r14,rcx
+	mov	r15d,DWORD PTR[272+rcx]
+
+	mov	QWORD PTR[40+rsp],r8
+	mov	QWORD PTR[48+rsp],rbp
+
+$L$cbc_body::
+	lea	rbp,QWORD PTR[$L$Camellia_SBOX]
+
+	mov	ecx,32
+ALIGN	4
+$L$cbc_prefetch_sbox::
+	mov	rax,QWORD PTR[rbp]
+	mov	rsi,QWORD PTR[32+rbp]
+	mov	rdi,QWORD PTR[64+rbp]
+	mov	r11,QWORD PTR[96+rbp]
+	lea	rbp,QWORD PTR[128+rbp]
+	loop	$L$cbc_prefetch_sbox
+	sub	rbp,4096
+	shl	r15,6
+	mov	rcx,rdx
+	lea	r15,QWORD PTR[r15*1+r14]
+
+	cmp	r9d,0
+	je	$L$CBC_DECRYPT
+
+	and	rdx,-16
+	and	rcx,15
+	lea	rdx,QWORD PTR[rdx*1+r12]
+	mov	QWORD PTR[rsp],r14
+	mov	QWORD PTR[8+rsp],rdx
+	mov	QWORD PTR[16+rsp],rcx
+
+	cmp	rdx,r12
+	mov	r8d,DWORD PTR[rbx]
+	mov	r9d,DWORD PTR[4+rbx]
+	mov	r10d,DWORD PTR[8+rbx]
+	mov	r11d,DWORD PTR[12+rbx]
+	je	$L$cbc_enc_tail
+	jmp	$L$cbc_eloop
+
+ALIGN	16
+$L$cbc_eloop::
+	xor	r8d,DWORD PTR[r12]
+	xor	r9d,DWORD PTR[4+r12]
+	xor	r10d,DWORD PTR[8+r12]
+	bswap	r8d
+	xor	r11d,DWORD PTR[12+r12]
+	bswap	r9d
+	bswap	r10d
+	bswap	r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	mov	r14,QWORD PTR[rsp]
+	bswap	r8d
+	mov	rdx,QWORD PTR[8+rsp]
+	bswap	r9d
+	mov	rcx,QWORD PTR[16+rsp]
+	bswap	r10d
+	mov	DWORD PTR[r13],r8d
+	bswap	r11d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	lea	r12,QWORD PTR[16+r12]
+	mov	DWORD PTR[12+r13],r11d
+	cmp	r12,rdx
+	lea	r13,QWORD PTR[16+r13]
+	jne	$L$cbc_eloop
+
+	cmp	rcx,0
+	jne	$L$cbc_enc_tail
+
+	mov	r13,QWORD PTR[40+rsp]
+	mov	DWORD PTR[r13],r8d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	mov	DWORD PTR[12+r13],r11d
+	jmp	$L$cbc_done
+
+ALIGN	16
+$L$cbc_enc_tail::
+	xor	rax,rax
+	mov	QWORD PTR[((0+24))+rsp],rax
+	mov	QWORD PTR[((8+24))+rsp],rax
+	mov	QWORD PTR[16+rsp],rax
+
+$L$cbc_enc_pushf::
+	pushfq
+	cld
+	mov	rsi,r12
+	lea	rdi,QWORD PTR[((8+24))+rsp]
+	DD	09066A4F3h		
+	popfq
+$L$cbc_enc_popf::
+
+	lea	r12,QWORD PTR[24+rsp]
+	lea	rax,QWORD PTR[((16+24))+rsp]
+	mov	QWORD PTR[8+rsp],rax
+	jmp	$L$cbc_eloop		
+
+ALIGN	16
+$L$CBC_DECRYPT::
+	xchg	r15,r14
+	add	rdx,15
+	and	rcx,15
+	and	rdx,-16
+	mov	QWORD PTR[rsp],r14
+	lea	rdx,QWORD PTR[rdx*1+r12]
+	mov	QWORD PTR[8+rsp],rdx
+	mov	QWORD PTR[16+rsp],rcx
+
+	mov	rax,QWORD PTR[rbx]
+	mov	rbx,QWORD PTR[8+rbx]
+	jmp	$L$cbc_dloop
+ALIGN	16
+$L$cbc_dloop::
+	mov	r8d,DWORD PTR[r12]
+	mov	r9d,DWORD PTR[4+r12]
+	mov	r10d,DWORD PTR[8+r12]
+	bswap	r8d
+	mov	r11d,DWORD PTR[12+r12]
+	bswap	r9d
+	mov	QWORD PTR[((0+24))+rsp],rax
+	bswap	r10d
+	mov	QWORD PTR[((8+24))+rsp],rbx
+	bswap	r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	mov	r14,QWORD PTR[rsp]
+	mov	rdx,QWORD PTR[8+rsp]
+	mov	rcx,QWORD PTR[16+rsp]
+
+	bswap	r8d
+	mov	rax,QWORD PTR[r12]
+	bswap	r9d
+	mov	rbx,QWORD PTR[8+r12]
+	bswap	r10d
+	xor	r8d,DWORD PTR[((0+24))+rsp]
+	bswap	r11d
+	xor	r9d,DWORD PTR[((4+24))+rsp]
+	xor	r10d,DWORD PTR[((8+24))+rsp]
+	lea	r12,QWORD PTR[16+r12]
+	xor	r11d,DWORD PTR[((12+24))+rsp]
+	cmp	r12,rdx
+	je	$L$cbc_ddone
+
+	mov	DWORD PTR[r13],r8d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	mov	DWORD PTR[12+r13],r11d
+
+	lea	r13,QWORD PTR[16+r13]
+	jmp	$L$cbc_dloop
+
+ALIGN	16
+$L$cbc_ddone::
+	mov	rdx,QWORD PTR[40+rsp]
+	cmp	rcx,0
+	jne	$L$cbc_dec_tail
+
+	mov	DWORD PTR[r13],r8d
+	mov	DWORD PTR[4+r13],r9d
+	mov	DWORD PTR[8+r13],r10d
+	mov	DWORD PTR[12+r13],r11d
+
+	mov	QWORD PTR[rdx],rax
+	mov	QWORD PTR[8+rdx],rbx
+	jmp	$L$cbc_done
+ALIGN	16
+$L$cbc_dec_tail::
+	mov	DWORD PTR[((0+24))+rsp],r8d
+	mov	DWORD PTR[((4+24))+rsp],r9d
+	mov	DWORD PTR[((8+24))+rsp],r10d
+	mov	DWORD PTR[((12+24))+rsp],r11d
+
+$L$cbc_dec_pushf::
+	pushfq
+	cld
+	lea	rsi,QWORD PTR[((8+24))+rsp]
+	lea	rdi,QWORD PTR[r13]
+	DD	09066A4F3h		
+	popfq
+$L$cbc_dec_popf::
+
+	mov	QWORD PTR[rdx],rax
+	mov	QWORD PTR[8+rdx],rbx
+	jmp	$L$cbc_done
+
+ALIGN	16
+$L$cbc_done::
+	mov	rcx,QWORD PTR[48+rsp]
+	mov	r15,QWORD PTR[rcx]
+	mov	r14,QWORD PTR[8+rcx]
+	mov	r13,QWORD PTR[16+rcx]
+	mov	r12,QWORD PTR[24+rcx]
+	mov	rbp,QWORD PTR[32+rcx]
+	mov	rbx,QWORD PTR[40+rcx]
+	lea	rsp,QWORD PTR[48+rcx]
+$L$cbc_abort::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_Camellia_cbc_encrypt::
+Camellia_cbc_encrypt	ENDP
+
+DB	67,97,109,101,108,108,105,97,32,102,111,114,32,120,56,54
+DB	95,54,52,32,98,121,32,60,97,112,112,114,111,64,111,112
+DB	101,110,115,115,108,46,111,114,103,62,0
+
+.text$	ENDS
+END
+
diff --git a/crypto/camellia/cmll-mingw64-x86_64.S b/crypto/camellia/cmll-mingw64-x86_64.S
new file mode 100644
index 0000000..75966f4
--- /dev/null
+++ b/crypto/camellia/cmll-mingw64-x86_64.S
@@ -0,0 +1,1884 @@
+#include "x86_arch.h"
+.text	
+
+
+.globl	Camellia_EncryptBlock
+.def	Camellia_EncryptBlock;	.scl 2;	.type 32;	.endef
+.p2align	4
+Camellia_EncryptBlock:
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	.Lenc_rounds
+
+
+.globl	Camellia_EncryptBlock_Rounds
+.def	Camellia_EncryptBlock_Rounds;	.scl 2;	.type 32;	.endef
+.p2align	4
+.Lenc_rounds:
+Camellia_EncryptBlock_Rounds:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_Camellia_EncryptBlock_Rounds:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lenc_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r14
+
+	shll	$6,%edi
+	leaq	.LCamellia_SBOX(%rip),%rbp
+	leaq	(%r14,%rdi,1),%r15
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Lenc_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_Camellia_EncryptBlock_Rounds:
+
+.def	_x86_64_Camellia_encrypt;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_Camellia_encrypt:
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.p2align	4
+.Leloop:
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	56(%r14),%ebx
+	movl	60(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	64(%r14),%ebx
+	movl	68(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	8(%r14),%edx
+	movl	12(%r14),%ecx
+	je	.Ledone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+	jmp	.Leloop
+
+.p2align	4
+.Ledone:
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	xorl	%r8d,%ecx
+	xorl	%r9d,%edx
+
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r10d
+	movl	%edx,%r11d
+
+	retq
+
+
+
+.globl	Camellia_DecryptBlock
+.def	Camellia_DecryptBlock;	.scl 2;	.type 32;	.endef
+.p2align	4
+Camellia_DecryptBlock:
+	movl	$128,%eax
+	subl	%edi,%eax
+	movl	$3,%edi
+	adcl	$0,%edi
+	jmp	.Ldec_rounds
+
+
+.globl	Camellia_DecryptBlock_Rounds
+.def	Camellia_DecryptBlock_Rounds;	.scl 2;	.type 32;	.endef
+.p2align	4
+.Ldec_rounds:
+Camellia_DecryptBlock_Rounds:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_Camellia_DecryptBlock_Rounds:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Ldec_prologue:
+
+
+	movq	%rcx,%r13
+	movq	%rdx,%r15
+
+	shll	$6,%edi
+	leaq	.LCamellia_SBOX(%rip),%rbp
+	leaq	(%r15,%rdi,1),%r14
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	bswapl	%r8d
+	movl	12(%rsi),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Ldec_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_Camellia_DecryptBlock_Rounds:
+
+.def	_x86_64_Camellia_decrypt;	.scl 3;	.type 32;	.endef
+.p2align	4
+_x86_64_Camellia_decrypt:
+	xorl	0(%r14),%r9d
+	xorl	4(%r14),%r8d
+	xorl	8(%r14),%r11d
+	xorl	12(%r14),%r10d
+.p2align	4
+.Ldloop:
+	movl	-8(%r14),%ebx
+	movl	-4(%r14),%eax
+
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-16(%r14),%ebx
+	movl	-12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-24(%r14),%ebx
+	movl	-20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-32(%r14),%ebx
+	movl	-28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-40(%r14),%ebx
+	movl	-36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-48(%r14),%ebx
+	movl	-44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	-56(%r14),%ebx
+	movl	-52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	leaq	-64(%r14),%r14
+	cmpq	%r15,%r14
+	movl	0(%r14),%edx
+	movl	4(%r14),%ecx
+	je	.Lddone
+
+	andl	%r8d,%eax
+	orl	%r11d,%edx
+	roll	$1,%eax
+	xorl	%edx,%r10d
+	xorl	%eax,%r9d
+	andl	%r10d,%ecx
+	orl	%r9d,%ebx
+	roll	$1,%ecx
+	xorl	%ebx,%r8d
+	xorl	%ecx,%r11d
+
+	jmp	.Ldloop
+
+.p2align	4
+.Lddone:
+	xorl	%r10d,%ecx
+	xorl	%r11d,%edx
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+
+	movl	%ecx,%r8d
+	movl	%edx,%r9d
+	movl	%eax,%r10d
+	movl	%ebx,%r11d
+
+	retq
+
+.globl	Camellia_Ekeygen
+.def	Camellia_Ekeygen;	.scl 2;	.type 32;	.endef
+.p2align	4
+Camellia_Ekeygen:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_Camellia_Ekeygen:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lkey_prologue:
+
+	movq	%rdi,%r15
+	movq	%rdx,%r13
+
+	movl	0(%rsi),%r8d
+	movl	4(%rsi),%r9d
+	movl	8(%rsi),%r10d
+	movl	12(%rsi),%r11d
+
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,0(%r13)
+	movl	%r8d,4(%r13)
+	movl	%r11d,8(%r13)
+	movl	%r10d,12(%r13)
+	cmpq	$128,%r15
+	je	.L1st128
+
+	movl	16(%rsi),%r8d
+	movl	20(%rsi),%r9d
+	cmpq	$192,%r15
+	je	.L1st192
+	movl	24(%rsi),%r10d
+	movl	28(%rsi),%r11d
+	jmp	.L1st256
+.L1st192:
+	movl	%r8d,%r10d
+	movl	%r9d,%r11d
+	notl	%r10d
+	notl	%r11d
+.L1st256:
+	bswapl	%r8d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+	movl	%r9d,32(%r13)
+	movl	%r8d,36(%r13)
+	movl	%r11d,40(%r13)
+	movl	%r10d,44(%r13)
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+
+.L1st128:
+	leaq	.LCamellia_SIGMA(%rip),%r14
+	leaq	.LCamellia_SBOX(%rip),%rbp
+
+	movl	0(%r14),%ebx
+	movl	4(%r14),%eax
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	8(%r14),%ebx
+	movl	12(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	16(%r14),%ebx
+	movl	20(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	xorl	0(%r13),%r9d
+	xorl	4(%r13),%r8d
+	xorl	8(%r13),%r11d
+	xorl	12(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	24(%r14),%ebx
+	movl	28(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	32(%r14),%ebx
+	movl	36(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	cmpq	$128,%r15
+	jne	.L2nd256
+
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	-128(%r13),%rax
+	movq	-120(%r13),%rbx
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-96(%r13)
+	movq	%rbx,-88(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-80(%r13)
+	movq	%r10,-72(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-64(%r13)
+	movq	%r10,-56(%r13)
+	movq	%rax,%r11
+	shlq	$30,%rax
+	movq	%rbx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rax
+	shlq	$30,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-48(%r13)
+	movq	%rbx,-40(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-32(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rbx,-24(%r13)
+	movq	%r8,%r11
+	shlq	$15,%r8
+	movq	%r10,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r8
+	shlq	$15,%r10
+	orq	%r11,%r10
+	movq	%r8,-16(%r13)
+	movq	%r10,-8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,16(%r13)
+	movq	%rbx,24(%r13)
+	movq	%r8,%r11
+	shlq	$34,%r8
+	movq	%r10,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%r8
+	shlq	$34,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r8,%r11
+	shlq	$17,%r8
+	movq	%r10,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r8
+	shlq	$17,%r10
+	orq	%r11,%r10
+	movq	%r8,64(%r13)
+	movq	%r10,72(%r13)
+	movl	$3,%eax
+	jmp	.Ldone
+.p2align	4
+.L2nd256:
+	movl	%r9d,48(%r13)
+	movl	%r8d,52(%r13)
+	movl	%r11d,56(%r13)
+	movl	%r10d,60(%r13)
+	xorl	32(%r13),%r9d
+	xorl	36(%r13),%r8d
+	xorl	40(%r13),%r11d
+	xorl	44(%r13),%r10d
+	xorl	%r8d,%eax
+	xorl	%r9d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	40(%r14),%ebx
+	movl	44(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r10d
+	xorl	%ecx,%r11d
+	xorl	%edx,%r11d
+	xorl	%r10d,%eax
+	xorl	%r11d,%ebx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	movl	2052(%rbp,%rsi,8),%edx
+	movl	0(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	shrl	$16,%eax
+	movzbl	%bh,%edi
+	xorl	4(%rbp,%rsi,8),%edx
+	shrl	$16,%ebx
+	xorl	4(%rbp,%rdi,8),%ecx
+	movzbl	%ah,%esi
+	movzbl	%bl,%edi
+	xorl	0(%rbp,%rsi,8),%edx
+	xorl	2052(%rbp,%rdi,8),%ecx
+	movzbl	%al,%esi
+	movzbl	%bh,%edi
+	xorl	2048(%rbp,%rsi,8),%edx
+	xorl	2048(%rbp,%rdi,8),%ecx
+	movl	48(%r14),%ebx
+	movl	52(%r14),%eax
+	xorl	%edx,%ecx
+	rorl	$8,%edx
+	xorl	%ecx,%r8d
+	xorl	%ecx,%r9d
+	xorl	%edx,%r9d
+	movq	0(%r13),%rax
+	movq	8(%r13),%rbx
+	movq	32(%r13),%rcx
+	movq	40(%r13),%rdx
+	movq	48(%r13),%r14
+	movq	56(%r13),%r15
+	leaq	128(%r13),%r13
+	shlq	$32,%r8
+	shlq	$32,%r10
+	orq	%r9,%r8
+	orq	%r11,%r10
+	movq	%r8,-112(%r13)
+	movq	%r10,-104(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-96(%r13)
+	movq	%rdx,-88(%r13)
+	movq	%r14,%r11
+	shlq	$15,%r14
+	movq	%r15,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%r14
+	shlq	$15,%r15
+	orq	%r11,%r15
+	movq	%r14,-80(%r13)
+	movq	%r15,-72(%r13)
+	movq	%rcx,%r11
+	shlq	$15,%rcx
+	movq	%rdx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rcx
+	shlq	$15,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,-64(%r13)
+	movq	%rdx,-56(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,-48(%r13)
+	movq	%r10,-40(%r13)
+	movq	%rax,%r11
+	shlq	$45,%rax
+	movq	%rbx,%r9
+	shrq	$19,%r9
+	shrq	$19,%r11
+	orq	%r9,%rax
+	shlq	$45,%rbx
+	orq	%r11,%rbx
+	movq	%rax,-32(%r13)
+	movq	%rbx,-24(%r13)
+	movq	%r14,%r11
+	shlq	$30,%r14
+	movq	%r15,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r14
+	shlq	$30,%r15
+	orq	%r11,%r15
+	movq	%r14,-16(%r13)
+	movq	%r15,-8(%r13)
+	movq	%rax,%r11
+	shlq	$15,%rax
+	movq	%rbx,%r9
+	shrq	$49,%r9
+	shrq	$49,%r11
+	orq	%r9,%rax
+	shlq	$15,%rbx
+	orq	%r11,%rbx
+	movq	%rax,0(%r13)
+	movq	%rbx,8(%r13)
+	movq	%rcx,%r11
+	shlq	$30,%rcx
+	movq	%rdx,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%rcx
+	shlq	$30,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,16(%r13)
+	movq	%rdx,24(%r13)
+	movq	%r8,%r11
+	shlq	$30,%r8
+	movq	%r10,%r9
+	shrq	$34,%r9
+	shrq	$34,%r11
+	orq	%r9,%r8
+	shlq	$30,%r10
+	orq	%r11,%r10
+	movq	%r8,32(%r13)
+	movq	%r10,40(%r13)
+	movq	%rax,%r11
+	shlq	$17,%rax
+	movq	%rbx,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%rax
+	shlq	$17,%rbx
+	orq	%r11,%rbx
+	movq	%rax,48(%r13)
+	movq	%rbx,56(%r13)
+	movq	%r14,%r11
+	shlq	$32,%r14
+	movq	%r15,%r9
+	shrq	$32,%r9
+	shrq	$32,%r11
+	orq	%r9,%r14
+	shlq	$32,%r15
+	orq	%r11,%r15
+	movq	%r14,64(%r13)
+	movq	%r15,72(%r13)
+	movq	%rcx,%r11
+	shlq	$34,%rcx
+	movq	%rdx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rcx
+	shlq	$34,%rdx
+	orq	%r11,%rdx
+	movq	%rcx,80(%r13)
+	movq	%rdx,88(%r13)
+	movq	%r14,%r11
+	shlq	$17,%r14
+	movq	%r15,%r9
+	shrq	$47,%r9
+	shrq	$47,%r11
+	orq	%r9,%r14
+	shlq	$17,%r15
+	orq	%r11,%r15
+	movq	%r14,96(%r13)
+	movq	%r15,104(%r13)
+	movq	%rax,%r11
+	shlq	$34,%rax
+	movq	%rbx,%r9
+	shrq	$30,%r9
+	shrq	$30,%r11
+	orq	%r9,%rax
+	shlq	$34,%rbx
+	orq	%r11,%rbx
+	movq	%rax,112(%r13)
+	movq	%rbx,120(%r13)
+	movq	%r8,%r11
+	shlq	$51,%r8
+	movq	%r10,%r9
+	shrq	$13,%r9
+	shrq	$13,%r11
+	orq	%r9,%r8
+	shlq	$51,%r10
+	orq	%r11,%r10
+	movq	%r8,128(%r13)
+	movq	%r10,136(%r13)
+	movl	$4,%eax
+.Ldone:
+	movq	0(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r13
+	movq	24(%rsp),%rbp
+	movq	32(%rsp),%rbx
+	leaq	40(%rsp),%rsp
+.Lkey_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_Camellia_Ekeygen:
+.p2align	6
+.LCamellia_SIGMA:
+.long	0x3bcc908b, 0xa09e667f, 0x4caa73b2, 0xb67ae858
+.long	0xe94f82be, 0xc6ef372f, 0xf1d36f1c, 0x54ff53a5
+.long	0xde682d1d, 0x10e527fa, 0xb3e6c1fd, 0xb05688c2
+.long	0,          0,          0,          0
+.LCamellia_SBOX:
+.long	0x70707000,0x70700070
+.long	0x82828200,0x2c2c002c
+.long	0x2c2c2c00,0xb3b300b3
+.long	0xececec00,0xc0c000c0
+.long	0xb3b3b300,0xe4e400e4
+.long	0x27272700,0x57570057
+.long	0xc0c0c000,0xeaea00ea
+.long	0xe5e5e500,0xaeae00ae
+.long	0xe4e4e400,0x23230023
+.long	0x85858500,0x6b6b006b
+.long	0x57575700,0x45450045
+.long	0x35353500,0xa5a500a5
+.long	0xeaeaea00,0xeded00ed
+.long	0x0c0c0c00,0x4f4f004f
+.long	0xaeaeae00,0x1d1d001d
+.long	0x41414100,0x92920092
+.long	0x23232300,0x86860086
+.long	0xefefef00,0xafaf00af
+.long	0x6b6b6b00,0x7c7c007c
+.long	0x93939300,0x1f1f001f
+.long	0x45454500,0x3e3e003e
+.long	0x19191900,0xdcdc00dc
+.long	0xa5a5a500,0x5e5e005e
+.long	0x21212100,0x0b0b000b
+.long	0xededed00,0xa6a600a6
+.long	0x0e0e0e00,0x39390039
+.long	0x4f4f4f00,0xd5d500d5
+.long	0x4e4e4e00,0x5d5d005d
+.long	0x1d1d1d00,0xd9d900d9
+.long	0x65656500,0x5a5a005a
+.long	0x92929200,0x51510051
+.long	0xbdbdbd00,0x6c6c006c
+.long	0x86868600,0x8b8b008b
+.long	0xb8b8b800,0x9a9a009a
+.long	0xafafaf00,0xfbfb00fb
+.long	0x8f8f8f00,0xb0b000b0
+.long	0x7c7c7c00,0x74740074
+.long	0xebebeb00,0x2b2b002b
+.long	0x1f1f1f00,0xf0f000f0
+.long	0xcecece00,0x84840084
+.long	0x3e3e3e00,0xdfdf00df
+.long	0x30303000,0xcbcb00cb
+.long	0xdcdcdc00,0x34340034
+.long	0x5f5f5f00,0x76760076
+.long	0x5e5e5e00,0x6d6d006d
+.long	0xc5c5c500,0xa9a900a9
+.long	0x0b0b0b00,0xd1d100d1
+.long	0x1a1a1a00,0x04040004
+.long	0xa6a6a600,0x14140014
+.long	0xe1e1e100,0x3a3a003a
+.long	0x39393900,0xdede00de
+.long	0xcacaca00,0x11110011
+.long	0xd5d5d500,0x32320032
+.long	0x47474700,0x9c9c009c
+.long	0x5d5d5d00,0x53530053
+.long	0x3d3d3d00,0xf2f200f2
+.long	0xd9d9d900,0xfefe00fe
+.long	0x01010100,0xcfcf00cf
+.long	0x5a5a5a00,0xc3c300c3
+.long	0xd6d6d600,0x7a7a007a
+.long	0x51515100,0x24240024
+.long	0x56565600,0xe8e800e8
+.long	0x6c6c6c00,0x60600060
+.long	0x4d4d4d00,0x69690069
+.long	0x8b8b8b00,0xaaaa00aa
+.long	0x0d0d0d00,0xa0a000a0
+.long	0x9a9a9a00,0xa1a100a1
+.long	0x66666600,0x62620062
+.long	0xfbfbfb00,0x54540054
+.long	0xcccccc00,0x1e1e001e
+.long	0xb0b0b000,0xe0e000e0
+.long	0x2d2d2d00,0x64640064
+.long	0x74747400,0x10100010
+.long	0x12121200,0x00000000
+.long	0x2b2b2b00,0xa3a300a3
+.long	0x20202000,0x75750075
+.long	0xf0f0f000,0x8a8a008a
+.long	0xb1b1b100,0xe6e600e6
+.long	0x84848400,0x09090009
+.long	0x99999900,0xdddd00dd
+.long	0xdfdfdf00,0x87870087
+.long	0x4c4c4c00,0x83830083
+.long	0xcbcbcb00,0xcdcd00cd
+.long	0xc2c2c200,0x90900090
+.long	0x34343400,0x73730073
+.long	0x7e7e7e00,0xf6f600f6
+.long	0x76767600,0x9d9d009d
+.long	0x05050500,0xbfbf00bf
+.long	0x6d6d6d00,0x52520052
+.long	0xb7b7b700,0xd8d800d8
+.long	0xa9a9a900,0xc8c800c8
+.long	0x31313100,0xc6c600c6
+.long	0xd1d1d100,0x81810081
+.long	0x17171700,0x6f6f006f
+.long	0x04040400,0x13130013
+.long	0xd7d7d700,0x63630063
+.long	0x14141400,0xe9e900e9
+.long	0x58585800,0xa7a700a7
+.long	0x3a3a3a00,0x9f9f009f
+.long	0x61616100,0xbcbc00bc
+.long	0xdedede00,0x29290029
+.long	0x1b1b1b00,0xf9f900f9
+.long	0x11111100,0x2f2f002f
+.long	0x1c1c1c00,0xb4b400b4
+.long	0x32323200,0x78780078
+.long	0x0f0f0f00,0x06060006
+.long	0x9c9c9c00,0xe7e700e7
+.long	0x16161600,0x71710071
+.long	0x53535300,0xd4d400d4
+.long	0x18181800,0xabab00ab
+.long	0xf2f2f200,0x88880088
+.long	0x22222200,0x8d8d008d
+.long	0xfefefe00,0x72720072
+.long	0x44444400,0xb9b900b9
+.long	0xcfcfcf00,0xf8f800f8
+.long	0xb2b2b200,0xacac00ac
+.long	0xc3c3c300,0x36360036
+.long	0xb5b5b500,0x2a2a002a
+.long	0x7a7a7a00,0x3c3c003c
+.long	0x91919100,0xf1f100f1
+.long	0x24242400,0x40400040
+.long	0x08080800,0xd3d300d3
+.long	0xe8e8e800,0xbbbb00bb
+.long	0xa8a8a800,0x43430043
+.long	0x60606000,0x15150015
+.long	0xfcfcfc00,0xadad00ad
+.long	0x69696900,0x77770077
+.long	0x50505000,0x80800080
+.long	0xaaaaaa00,0x82820082
+.long	0xd0d0d000,0xecec00ec
+.long	0xa0a0a000,0x27270027
+.long	0x7d7d7d00,0xe5e500e5
+.long	0xa1a1a100,0x85850085
+.long	0x89898900,0x35350035
+.long	0x62626200,0x0c0c000c
+.long	0x97979700,0x41410041
+.long	0x54545400,0xefef00ef
+.long	0x5b5b5b00,0x93930093
+.long	0x1e1e1e00,0x19190019
+.long	0x95959500,0x21210021
+.long	0xe0e0e000,0x0e0e000e
+.long	0xffffff00,0x4e4e004e
+.long	0x64646400,0x65650065
+.long	0xd2d2d200,0xbdbd00bd
+.long	0x10101000,0xb8b800b8
+.long	0xc4c4c400,0x8f8f008f
+.long	0x00000000,0xebeb00eb
+.long	0x48484800,0xcece00ce
+.long	0xa3a3a300,0x30300030
+.long	0xf7f7f700,0x5f5f005f
+.long	0x75757500,0xc5c500c5
+.long	0xdbdbdb00,0x1a1a001a
+.long	0x8a8a8a00,0xe1e100e1
+.long	0x03030300,0xcaca00ca
+.long	0xe6e6e600,0x47470047
+.long	0xdadada00,0x3d3d003d
+.long	0x09090900,0x01010001
+.long	0x3f3f3f00,0xd6d600d6
+.long	0xdddddd00,0x56560056
+.long	0x94949400,0x4d4d004d
+.long	0x87878700,0x0d0d000d
+.long	0x5c5c5c00,0x66660066
+.long	0x83838300,0xcccc00cc
+.long	0x02020200,0x2d2d002d
+.long	0xcdcdcd00,0x12120012
+.long	0x4a4a4a00,0x20200020
+.long	0x90909000,0xb1b100b1
+.long	0x33333300,0x99990099
+.long	0x73737300,0x4c4c004c
+.long	0x67676700,0xc2c200c2
+.long	0xf6f6f600,0x7e7e007e
+.long	0xf3f3f300,0x05050005
+.long	0x9d9d9d00,0xb7b700b7
+.long	0x7f7f7f00,0x31310031
+.long	0xbfbfbf00,0x17170017
+.long	0xe2e2e200,0xd7d700d7
+.long	0x52525200,0x58580058
+.long	0x9b9b9b00,0x61610061
+.long	0xd8d8d800,0x1b1b001b
+.long	0x26262600,0x1c1c001c
+.long	0xc8c8c800,0x0f0f000f
+.long	0x37373700,0x16160016
+.long	0xc6c6c600,0x18180018
+.long	0x3b3b3b00,0x22220022
+.long	0x81818100,0x44440044
+.long	0x96969600,0xb2b200b2
+.long	0x6f6f6f00,0xb5b500b5
+.long	0x4b4b4b00,0x91910091
+.long	0x13131300,0x08080008
+.long	0xbebebe00,0xa8a800a8
+.long	0x63636300,0xfcfc00fc
+.long	0x2e2e2e00,0x50500050
+.long	0xe9e9e900,0xd0d000d0
+.long	0x79797900,0x7d7d007d
+.long	0xa7a7a700,0x89890089
+.long	0x8c8c8c00,0x97970097
+.long	0x9f9f9f00,0x5b5b005b
+.long	0x6e6e6e00,0x95950095
+.long	0xbcbcbc00,0xffff00ff
+.long	0x8e8e8e00,0xd2d200d2
+.long	0x29292900,0xc4c400c4
+.long	0xf5f5f500,0x48480048
+.long	0xf9f9f900,0xf7f700f7
+.long	0xb6b6b600,0xdbdb00db
+.long	0x2f2f2f00,0x03030003
+.long	0xfdfdfd00,0xdada00da
+.long	0xb4b4b400,0x3f3f003f
+.long	0x59595900,0x94940094
+.long	0x78787800,0x5c5c005c
+.long	0x98989800,0x02020002
+.long	0x06060600,0x4a4a004a
+.long	0x6a6a6a00,0x33330033
+.long	0xe7e7e700,0x67670067
+.long	0x46464600,0xf3f300f3
+.long	0x71717100,0x7f7f007f
+.long	0xbababa00,0xe2e200e2
+.long	0xd4d4d400,0x9b9b009b
+.long	0x25252500,0x26260026
+.long	0xababab00,0x37370037
+.long	0x42424200,0x3b3b003b
+.long	0x88888800,0x96960096
+.long	0xa2a2a200,0x4b4b004b
+.long	0x8d8d8d00,0xbebe00be
+.long	0xfafafa00,0x2e2e002e
+.long	0x72727200,0x79790079
+.long	0x07070700,0x8c8c008c
+.long	0xb9b9b900,0x6e6e006e
+.long	0x55555500,0x8e8e008e
+.long	0xf8f8f800,0xf5f500f5
+.long	0xeeeeee00,0xb6b600b6
+.long	0xacacac00,0xfdfd00fd
+.long	0x0a0a0a00,0x59590059
+.long	0x36363600,0x98980098
+.long	0x49494900,0x6a6a006a
+.long	0x2a2a2a00,0x46460046
+.long	0x68686800,0xbaba00ba
+.long	0x3c3c3c00,0x25250025
+.long	0x38383800,0x42420042
+.long	0xf1f1f100,0xa2a200a2
+.long	0xa4a4a400,0xfafa00fa
+.long	0x40404000,0x07070007
+.long	0x28282800,0x55550055
+.long	0xd3d3d300,0xeeee00ee
+.long	0x7b7b7b00,0x0a0a000a
+.long	0xbbbbbb00,0x49490049
+.long	0xc9c9c900,0x68680068
+.long	0x43434300,0x38380038
+.long	0xc1c1c100,0xa4a400a4
+.long	0x15151500,0x28280028
+.long	0xe3e3e300,0x7b7b007b
+.long	0xadadad00,0xc9c900c9
+.long	0xf4f4f400,0xc1c100c1
+.long	0x77777700,0xe3e300e3
+.long	0xc7c7c700,0xf4f400f4
+.long	0x80808000,0xc7c700c7
+.long	0x9e9e9e00,0x9e9e009e
+.long	0x00e0e0e0,0x38003838
+.long	0x00050505,0x41004141
+.long	0x00585858,0x16001616
+.long	0x00d9d9d9,0x76007676
+.long	0x00676767,0xd900d9d9
+.long	0x004e4e4e,0x93009393
+.long	0x00818181,0x60006060
+.long	0x00cbcbcb,0xf200f2f2
+.long	0x00c9c9c9,0x72007272
+.long	0x000b0b0b,0xc200c2c2
+.long	0x00aeaeae,0xab00abab
+.long	0x006a6a6a,0x9a009a9a
+.long	0x00d5d5d5,0x75007575
+.long	0x00181818,0x06000606
+.long	0x005d5d5d,0x57005757
+.long	0x00828282,0xa000a0a0
+.long	0x00464646,0x91009191
+.long	0x00dfdfdf,0xf700f7f7
+.long	0x00d6d6d6,0xb500b5b5
+.long	0x00272727,0xc900c9c9
+.long	0x008a8a8a,0xa200a2a2
+.long	0x00323232,0x8c008c8c
+.long	0x004b4b4b,0xd200d2d2
+.long	0x00424242,0x90009090
+.long	0x00dbdbdb,0xf600f6f6
+.long	0x001c1c1c,0x07000707
+.long	0x009e9e9e,0xa700a7a7
+.long	0x009c9c9c,0x27002727
+.long	0x003a3a3a,0x8e008e8e
+.long	0x00cacaca,0xb200b2b2
+.long	0x00252525,0x49004949
+.long	0x007b7b7b,0xde00dede
+.long	0x000d0d0d,0x43004343
+.long	0x00717171,0x5c005c5c
+.long	0x005f5f5f,0xd700d7d7
+.long	0x001f1f1f,0xc700c7c7
+.long	0x00f8f8f8,0x3e003e3e
+.long	0x00d7d7d7,0xf500f5f5
+.long	0x003e3e3e,0x8f008f8f
+.long	0x009d9d9d,0x67006767
+.long	0x007c7c7c,0x1f001f1f
+.long	0x00606060,0x18001818
+.long	0x00b9b9b9,0x6e006e6e
+.long	0x00bebebe,0xaf00afaf
+.long	0x00bcbcbc,0x2f002f2f
+.long	0x008b8b8b,0xe200e2e2
+.long	0x00161616,0x85008585
+.long	0x00343434,0x0d000d0d
+.long	0x004d4d4d,0x53005353
+.long	0x00c3c3c3,0xf000f0f0
+.long	0x00727272,0x9c009c9c
+.long	0x00959595,0x65006565
+.long	0x00ababab,0xea00eaea
+.long	0x008e8e8e,0xa300a3a3
+.long	0x00bababa,0xae00aeae
+.long	0x007a7a7a,0x9e009e9e
+.long	0x00b3b3b3,0xec00ecec
+.long	0x00020202,0x80008080
+.long	0x00b4b4b4,0x2d002d2d
+.long	0x00adadad,0x6b006b6b
+.long	0x00a2a2a2,0xa800a8a8
+.long	0x00acacac,0x2b002b2b
+.long	0x00d8d8d8,0x36003636
+.long	0x009a9a9a,0xa600a6a6
+.long	0x00171717,0xc500c5c5
+.long	0x001a1a1a,0x86008686
+.long	0x00353535,0x4d004d4d
+.long	0x00cccccc,0x33003333
+.long	0x00f7f7f7,0xfd00fdfd
+.long	0x00999999,0x66006666
+.long	0x00616161,0x58005858
+.long	0x005a5a5a,0x96009696
+.long	0x00e8e8e8,0x3a003a3a
+.long	0x00242424,0x09000909
+.long	0x00565656,0x95009595
+.long	0x00404040,0x10001010
+.long	0x00e1e1e1,0x78007878
+.long	0x00636363,0xd800d8d8
+.long	0x00090909,0x42004242
+.long	0x00333333,0xcc00cccc
+.long	0x00bfbfbf,0xef00efef
+.long	0x00989898,0x26002626
+.long	0x00979797,0xe500e5e5
+.long	0x00858585,0x61006161
+.long	0x00686868,0x1a001a1a
+.long	0x00fcfcfc,0x3f003f3f
+.long	0x00ececec,0x3b003b3b
+.long	0x000a0a0a,0x82008282
+.long	0x00dadada,0xb600b6b6
+.long	0x006f6f6f,0xdb00dbdb
+.long	0x00535353,0xd400d4d4
+.long	0x00626262,0x98009898
+.long	0x00a3a3a3,0xe800e8e8
+.long	0x002e2e2e,0x8b008b8b
+.long	0x00080808,0x02000202
+.long	0x00afafaf,0xeb00ebeb
+.long	0x00282828,0x0a000a0a
+.long	0x00b0b0b0,0x2c002c2c
+.long	0x00747474,0x1d001d1d
+.long	0x00c2c2c2,0xb000b0b0
+.long	0x00bdbdbd,0x6f006f6f
+.long	0x00363636,0x8d008d8d
+.long	0x00222222,0x88008888
+.long	0x00383838,0x0e000e0e
+.long	0x00646464,0x19001919
+.long	0x001e1e1e,0x87008787
+.long	0x00393939,0x4e004e4e
+.long	0x002c2c2c,0x0b000b0b
+.long	0x00a6a6a6,0xa900a9a9
+.long	0x00303030,0x0c000c0c
+.long	0x00e5e5e5,0x79007979
+.long	0x00444444,0x11001111
+.long	0x00fdfdfd,0x7f007f7f
+.long	0x00888888,0x22002222
+.long	0x009f9f9f,0xe700e7e7
+.long	0x00656565,0x59005959
+.long	0x00878787,0xe100e1e1
+.long	0x006b6b6b,0xda00dada
+.long	0x00f4f4f4,0x3d003d3d
+.long	0x00232323,0xc800c8c8
+.long	0x00484848,0x12001212
+.long	0x00101010,0x04000404
+.long	0x00d1d1d1,0x74007474
+.long	0x00515151,0x54005454
+.long	0x00c0c0c0,0x30003030
+.long	0x00f9f9f9,0x7e007e7e
+.long	0x00d2d2d2,0xb400b4b4
+.long	0x00a0a0a0,0x28002828
+.long	0x00555555,0x55005555
+.long	0x00a1a1a1,0x68006868
+.long	0x00414141,0x50005050
+.long	0x00fafafa,0xbe00bebe
+.long	0x00434343,0xd000d0d0
+.long	0x00131313,0xc400c4c4
+.long	0x00c4c4c4,0x31003131
+.long	0x002f2f2f,0xcb00cbcb
+.long	0x00a8a8a8,0x2a002a2a
+.long	0x00b6b6b6,0xad00adad
+.long	0x003c3c3c,0x0f000f0f
+.long	0x002b2b2b,0xca00caca
+.long	0x00c1c1c1,0x70007070
+.long	0x00ffffff,0xff00ffff
+.long	0x00c8c8c8,0x32003232
+.long	0x00a5a5a5,0x69006969
+.long	0x00202020,0x08000808
+.long	0x00898989,0x62006262
+.long	0x00000000,0x00000000
+.long	0x00909090,0x24002424
+.long	0x00474747,0xd100d1d1
+.long	0x00efefef,0xfb00fbfb
+.long	0x00eaeaea,0xba00baba
+.long	0x00b7b7b7,0xed00eded
+.long	0x00151515,0x45004545
+.long	0x00060606,0x81008181
+.long	0x00cdcdcd,0x73007373
+.long	0x00b5b5b5,0x6d006d6d
+.long	0x00121212,0x84008484
+.long	0x007e7e7e,0x9f009f9f
+.long	0x00bbbbbb,0xee00eeee
+.long	0x00292929,0x4a004a4a
+.long	0x000f0f0f,0xc300c3c3
+.long	0x00b8b8b8,0x2e002e2e
+.long	0x00070707,0xc100c1c1
+.long	0x00040404,0x01000101
+.long	0x009b9b9b,0xe600e6e6
+.long	0x00949494,0x25002525
+.long	0x00212121,0x48004848
+.long	0x00666666,0x99009999
+.long	0x00e6e6e6,0xb900b9b9
+.long	0x00cecece,0xb300b3b3
+.long	0x00ededed,0x7b007b7b
+.long	0x00e7e7e7,0xf900f9f9
+.long	0x003b3b3b,0xce00cece
+.long	0x00fefefe,0xbf00bfbf
+.long	0x007f7f7f,0xdf00dfdf
+.long	0x00c5c5c5,0x71007171
+.long	0x00a4a4a4,0x29002929
+.long	0x00373737,0xcd00cdcd
+.long	0x00b1b1b1,0x6c006c6c
+.long	0x004c4c4c,0x13001313
+.long	0x00919191,0x64006464
+.long	0x006e6e6e,0x9b009b9b
+.long	0x008d8d8d,0x63006363
+.long	0x00767676,0x9d009d9d
+.long	0x00030303,0xc000c0c0
+.long	0x002d2d2d,0x4b004b4b
+.long	0x00dedede,0xb700b7b7
+.long	0x00969696,0xa500a5a5
+.long	0x00262626,0x89008989
+.long	0x007d7d7d,0x5f005f5f
+.long	0x00c6c6c6,0xb100b1b1
+.long	0x005c5c5c,0x17001717
+.long	0x00d3d3d3,0xf400f4f4
+.long	0x00f2f2f2,0xbc00bcbc
+.long	0x004f4f4f,0xd300d3d3
+.long	0x00191919,0x46004646
+.long	0x003f3f3f,0xcf00cfcf
+.long	0x00dcdcdc,0x37003737
+.long	0x00797979,0x5e005e5e
+.long	0x001d1d1d,0x47004747
+.long	0x00525252,0x94009494
+.long	0x00ebebeb,0xfa00fafa
+.long	0x00f3f3f3,0xfc00fcfc
+.long	0x006d6d6d,0x5b005b5b
+.long	0x005e5e5e,0x97009797
+.long	0x00fbfbfb,0xfe00fefe
+.long	0x00696969,0x5a005a5a
+.long	0x00b2b2b2,0xac00acac
+.long	0x00f0f0f0,0x3c003c3c
+.long	0x00313131,0x4c004c4c
+.long	0x000c0c0c,0x03000303
+.long	0x00d4d4d4,0x35003535
+.long	0x00cfcfcf,0xf300f3f3
+.long	0x008c8c8c,0x23002323
+.long	0x00e2e2e2,0xb800b8b8
+.long	0x00757575,0x5d005d5d
+.long	0x00a9a9a9,0x6a006a6a
+.long	0x004a4a4a,0x92009292
+.long	0x00575757,0xd500d5d5
+.long	0x00848484,0x21002121
+.long	0x00111111,0x44004444
+.long	0x00454545,0x51005151
+.long	0x001b1b1b,0xc600c6c6
+.long	0x00f5f5f5,0x7d007d7d
+.long	0x00e4e4e4,0x39003939
+.long	0x000e0e0e,0x83008383
+.long	0x00737373,0xdc00dcdc
+.long	0x00aaaaaa,0xaa00aaaa
+.long	0x00f1f1f1,0x7c007c7c
+.long	0x00dddddd,0x77007777
+.long	0x00595959,0x56005656
+.long	0x00141414,0x05000505
+.long	0x006c6c6c,0x1b001b1b
+.long	0x00929292,0xa400a4a4
+.long	0x00545454,0x15001515
+.long	0x00d0d0d0,0x34003434
+.long	0x00787878,0x1e001e1e
+.long	0x00707070,0x1c001c1c
+.long	0x00e3e3e3,0xf800f8f8
+.long	0x00494949,0x52005252
+.long	0x00808080,0x20002020
+.long	0x00505050,0x14001414
+.long	0x00a7a7a7,0xe900e9e9
+.long	0x00f6f6f6,0xbd00bdbd
+.long	0x00777777,0xdd00dddd
+.long	0x00939393,0xe400e4e4
+.long	0x00868686,0xa100a1a1
+.long	0x00838383,0xe000e0e0
+.long	0x002a2a2a,0x8a008a8a
+.long	0x00c7c7c7,0xf100f1f1
+.long	0x005b5b5b,0xd600d6d6
+.long	0x00e9e9e9,0x7a007a7a
+.long	0x00eeeeee,0xbb00bbbb
+.long	0x008f8f8f,0xe300e3e3
+.long	0x00010101,0x40004040
+.long	0x003d3d3d,0x4f004f4f
+.globl	Camellia_cbc_encrypt
+.def	Camellia_cbc_encrypt;	.scl 2;	.type 32;	.endef
+.p2align	4
+Camellia_cbc_encrypt:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_Camellia_cbc_encrypt:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	cmpq	$0,%rdx
+	je	.Lcbc_abort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+.Lcbc_prologue:
+
+	movq	%rsp,%rbp
+	subq	$64,%rsp
+	andq	$-64,%rsp
+
+
+
+	leaq	-64-63(%rcx),%r10
+	subq	%rsp,%r10
+	negq	%r10
+	andq	$960,%r10
+	subq	%r10,%rsp
+
+
+	movq	%rdi,%r12
+	movq	%rsi,%r13
+	movq	%r8,%rbx
+	movq	%rcx,%r14
+	movl	272(%rcx),%r15d
+
+	movq	%r8,40(%rsp)
+	movq	%rbp,48(%rsp)
+
+.Lcbc_body:
+	leaq	.LCamellia_SBOX(%rip),%rbp
+
+	movl	$32,%ecx
+.p2align	2
+.Lcbc_prefetch_sbox:
+	movq	0(%rbp),%rax
+	movq	32(%rbp),%rsi
+	movq	64(%rbp),%rdi
+	movq	96(%rbp),%r11
+	leaq	128(%rbp),%rbp
+	loop	.Lcbc_prefetch_sbox
+	subq	$4096,%rbp
+	shlq	$6,%r15
+	movq	%rdx,%rcx
+	leaq	(%r14,%r15,1),%r15
+
+	cmpl	$0,%r9d
+	je	.LCBC_DECRYPT
+
+	andq	$-16,%rdx
+	andq	$15,%rcx
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%r14,0(%rsp)
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	cmpq	%r12,%rdx
+	movl	0(%rbx),%r8d
+	movl	4(%rbx),%r9d
+	movl	8(%rbx),%r10d
+	movl	12(%rbx),%r11d
+	je	.Lcbc_enc_tail
+	jmp	.Lcbc_eloop
+
+.p2align	4
+.Lcbc_eloop:
+	xorl	0(%r12),%r8d
+	xorl	4(%r12),%r9d
+	xorl	8(%r12),%r10d
+	bswapl	%r8d
+	xorl	12(%r12),%r11d
+	bswapl	%r9d
+	bswapl	%r10d
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_encrypt
+
+	movq	0(%rsp),%r14
+	bswapl	%r8d
+	movq	8(%rsp),%rdx
+	bswapl	%r9d
+	movq	16(%rsp),%rcx
+	bswapl	%r10d
+	movl	%r8d,0(%r13)
+	bswapl	%r11d
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	leaq	16(%r12),%r12
+	movl	%r11d,12(%r13)
+	cmpq	%rdx,%r12
+	leaq	16(%r13),%r13
+	jne	.Lcbc_eloop
+
+	cmpq	$0,%rcx
+	jne	.Lcbc_enc_tail
+
+	movq	40(%rsp),%r13
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+	jmp	.Lcbc_done
+
+.p2align	4
+.Lcbc_enc_tail:
+	xorq	%rax,%rax
+	movq	%rax,0+24(%rsp)
+	movq	%rax,8+24(%rsp)
+	movq	%rax,16(%rsp)
+
+.Lcbc_enc_pushf:
+	pushfq
+	cld
+	movq	%r12,%rsi
+	leaq	8+24(%rsp),%rdi
+.long	0x9066A4F3		
+	popfq
+.Lcbc_enc_popf:
+
+	leaq	24(%rsp),%r12
+	leaq	16+24(%rsp),%rax
+	movq	%rax,8(%rsp)
+	jmp	.Lcbc_eloop		
+
+.p2align	4
+.LCBC_DECRYPT:
+	xchgq	%r14,%r15
+	addq	$15,%rdx
+	andq	$15,%rcx
+	andq	$-16,%rdx
+	movq	%r14,0(%rsp)
+	leaq	(%r12,%rdx,1),%rdx
+	movq	%rdx,8(%rsp)
+	movq	%rcx,16(%rsp)
+
+	movq	(%rbx),%rax
+	movq	8(%rbx),%rbx
+	jmp	.Lcbc_dloop
+.p2align	4
+.Lcbc_dloop:
+	movl	0(%r12),%r8d
+	movl	4(%r12),%r9d
+	movl	8(%r12),%r10d
+	bswapl	%r8d
+	movl	12(%r12),%r11d
+	bswapl	%r9d
+	movq	%rax,0+24(%rsp)
+	bswapl	%r10d
+	movq	%rbx,8+24(%rsp)
+	bswapl	%r11d
+
+	call	_x86_64_Camellia_decrypt
+
+	movq	0(%rsp),%r14
+	movq	8(%rsp),%rdx
+	movq	16(%rsp),%rcx
+
+	bswapl	%r8d
+	movq	(%r12),%rax
+	bswapl	%r9d
+	movq	8(%r12),%rbx
+	bswapl	%r10d
+	xorl	0+24(%rsp),%r8d
+	bswapl	%r11d
+	xorl	4+24(%rsp),%r9d
+	xorl	8+24(%rsp),%r10d
+	leaq	16(%r12),%r12
+	xorl	12+24(%rsp),%r11d
+	cmpq	%rdx,%r12
+	je	.Lcbc_ddone
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	leaq	16(%r13),%r13
+	jmp	.Lcbc_dloop
+
+.p2align	4
+.Lcbc_ddone:
+	movq	40(%rsp),%rdx
+	cmpq	$0,%rcx
+	jne	.Lcbc_dec_tail
+
+	movl	%r8d,0(%r13)
+	movl	%r9d,4(%r13)
+	movl	%r10d,8(%r13)
+	movl	%r11d,12(%r13)
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	.Lcbc_done
+.p2align	4
+.Lcbc_dec_tail:
+	movl	%r8d,0+24(%rsp)
+	movl	%r9d,4+24(%rsp)
+	movl	%r10d,8+24(%rsp)
+	movl	%r11d,12+24(%rsp)
+
+.Lcbc_dec_pushf:
+	pushfq
+	cld
+	leaq	8+24(%rsp),%rsi
+	leaq	(%r13),%rdi
+.long	0x9066A4F3		
+	popfq
+.Lcbc_dec_popf:
+
+	movq	%rax,(%rdx)
+	movq	%rbx,8(%rdx)
+	jmp	.Lcbc_done
+
+.p2align	4
+.Lcbc_done:
+	movq	48(%rsp),%rcx
+	movq	0(%rcx),%r15
+	movq	8(%rcx),%r14
+	movq	16(%rcx),%r13
+	movq	24(%rcx),%r12
+	movq	32(%rcx),%rbp
+	movq	40(%rcx),%rbx
+	leaq	48(%rcx),%rsp
+.Lcbc_abort:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_Camellia_cbc_encrypt:
+
+.byte	67,97,109,101,108,108,105,97,32,102,111,114,32,120,56,54,95,54,52,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
diff --git a/crypto/camellia/cmll_cbc.c b/crypto/camellia/cmll_cbc.c
new file mode 100644
index 0000000..6567e5d
--- /dev/null
+++ b/crypto/camellia/cmll_cbc.c
@@ -0,0 +1,65 @@
+/* $OpenBSD: cmll_cbc.c,v 1.4 2014/11/13 20:01:58 miod Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+void
+Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+    const CAMELLIA_KEY *key, unsigned char *ivec, const int enc)
+{
+	if (enc)
+		CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
+		    (block128_f)Camellia_encrypt);
+	else
+		CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
+		   (block128_f)Camellia_decrypt);
+}
diff --git a/crypto/camellia/cmll_cfb.c b/crypto/camellia/cmll_cfb.c
new file mode 100644
index 0000000..755ab9f
--- /dev/null
+++ b/crypto/camellia/cmll_cfb.c
@@ -0,0 +1,144 @@
+/* $OpenBSD: cmll_cfb.c,v 1.4 2014/11/13 20:01:58 miod Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+
+/*
+ * The input and output encrypted as though 128bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num;
+ */
+
+void
+Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num,
+    const int enc)
+{
+	CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)Camellia_encrypt);
+}
+
+/* N.B. This expects the input to be packed, MS bit first */
+void
+Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num,
+    const int enc)
+{
+	CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)Camellia_encrypt);
+}
+
+void
+Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num,
+    const int enc)
+{
+	CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)Camellia_encrypt);
+}
diff --git a/crypto/camellia/cmll_ctr.c b/crypto/camellia/cmll_ctr.c
new file mode 100644
index 0000000..59a351e
--- /dev/null
+++ b/crypto/camellia/cmll_ctr.c
@@ -0,0 +1,63 @@
+/* $OpenBSD: cmll_ctr.c,v 1.4 2014/11/13 20:01:58 miod Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+void
+Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const CAMELLIA_KEY *key,
+    unsigned char ivec[CAMELLIA_BLOCK_SIZE],
+    unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], unsigned int *num)
+{
+	CRYPTO_ctr128_encrypt(in, out, length, key, ivec, ecount_buf, num,
+	    (block128_f)Camellia_encrypt);
+}
diff --git a/crypto/camellia/cmll_ecb.c b/crypto/camellia/cmll_ecb.c
new file mode 100644
index 0000000..0575d29
--- /dev/null
+++ b/crypto/camellia/cmll_ecb.c
@@ -0,0 +1,64 @@
+/* $OpenBSD: cmll_ecb.c,v 1.7 2023/09/04 08:43:41 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+
+#include "cmll_local.h"
+
+void
+Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    const CAMELLIA_KEY *key, const int enc)
+{
+	if (CAMELLIA_ENCRYPT == enc)
+		Camellia_encrypt(in, out, key);
+	else
+		Camellia_decrypt(in, out, key);
+}
diff --git a/crypto/camellia/cmll_local.h b/crypto/camellia/cmll_local.h
new file mode 100644
index 0000000..831625e
--- /dev/null
+++ b/crypto/camellia/cmll_local.h
@@ -0,0 +1,91 @@
+/* $OpenBSD: cmll_local.h,v 1.3 2023/09/04 08:43:41 tb Exp $ */
+/* ====================================================================
+ * Copyright 2006 NTT (Nippon Telegraph and Telephone Corporation) . 
+ * ALL RIGHTS RESERVED.
+ *
+ * Intellectual Property information for Camellia:
+ *     http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html
+ *
+ * News Release for Announcement of Camellia open source:
+ *     http://www.ntt.co.jp/news/news06e/0604/060413a.html
+ *
+ * The Camellia Code included herein is developed by
+ * NTT (Nippon Telegraph and Telephone Corporation), and is contributed
+ * to the OpenSSL project.
+ *
+ * The Camellia Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifndef HEADER_CAMELLIA_LOCAL_H
+#define HEADER_CAMELLIA_LOCAL_H
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+typedef unsigned int  u32;
+typedef unsigned char u8;
+
+int Camellia_Ekeygen(int keyBitLength, const u8 *rawKey,
+	    KEY_TABLE_TYPE keyTable);
+void Camellia_EncryptBlock_Rounds(int grandRounds, const u8 plaintext[],
+	    const KEY_TABLE_TYPE keyTable, u8 ciphertext[]);
+void Camellia_DecryptBlock_Rounds(int grandRounds, const u8 ciphertext[],
+	    const KEY_TABLE_TYPE keyTable, u8 plaintext[]);
+void Camellia_EncryptBlock(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[]);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_CAMELLIA_LOCAL_H */
diff --git a/crypto/camellia/cmll_misc.c b/crypto/camellia/cmll_misc.c
new file mode 100644
index 0000000..9fce92d
--- /dev/null
+++ b/crypto/camellia/cmll_misc.c
@@ -0,0 +1,81 @@
+/* $OpenBSD: cmll_misc.c,v 1.7 2022/11/26 16:08:51 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+#include 
+#include "cmll_local.h"
+
+int
+Camellia_set_key(const unsigned char *userKey, const int bits,
+    CAMELLIA_KEY *key)
+{
+	if (userKey == NULL || key == NULL)
+		return -1;
+	if (bits != 128 && bits != 192 && bits != 256)
+		return -2;
+	key->grand_rounds = Camellia_Ekeygen(bits, userKey, key->u.rd_key);
+	return 0;
+}
+
+void
+Camellia_encrypt(const unsigned char *in, unsigned char *out,
+    const CAMELLIA_KEY *key)
+{
+	Camellia_EncryptBlock_Rounds(key->grand_rounds, in, key->u.rd_key, out);
+}
+
+void
+Camellia_decrypt(const unsigned char *in, unsigned char *out,
+    const CAMELLIA_KEY *key)
+{
+	Camellia_DecryptBlock_Rounds(key->grand_rounds, in, key->u.rd_key, out);
+}
diff --git a/crypto/camellia/cmll_ofb.c b/crypto/camellia/cmll_ofb.c
new file mode 100644
index 0000000..cd3a65e
--- /dev/null
+++ b/crypto/camellia/cmll_ofb.c
@@ -0,0 +1,122 @@
+/* $OpenBSD: cmll_ofb.c,v 1.4 2014/11/13 20:01:58 miod Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+/*
+ * The input and output encrypted as though 128bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num;
+ */
+void
+Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num)
+{
+	CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+	    (block128_f)Camellia_encrypt);
+}
diff --git a/crypto/cast/c_cfb64.c b/crypto/cast/c_cfb64.c
new file mode 100644
index 0000000..2acf763
--- /dev/null
+++ b/crypto/cast/c_cfb64.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: c_cfb64.c,v 1.8 2023/07/08 10:43:59 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "cast_local.h"
+
+/* The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, const CAST_KEY *schedule, unsigned char *ivec,
+    int *num, int enc)
+{
+	CAST_LONG v0, v1, t;
+	int n= *num;
+	long l = length;
+	CAST_LONG ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = ivec;
+	if (enc) {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				CAST_encrypt((CAST_LONG *)ti, schedule);
+				iv = ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = ivec;
+			}
+			c= *(in++)^iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1)&0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				CAST_encrypt((CAST_LONG *)ti, schedule);
+				iv = ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = ivec;
+			}
+			cc= *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c^cc;
+			n = (n + 1)&0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = t=c = cc = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(CAST_cfb64_encrypt);
diff --git a/crypto/cast/c_ecb.c b/crypto/cast/c_ecb.c
new file mode 100644
index 0000000..89338a1
--- /dev/null
+++ b/crypto/cast/c_ecb.c
@@ -0,0 +1,83 @@
+/* $OpenBSD: c_ecb.c,v 1.10 2023/07/08 10:43:59 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "cast_local.h"
+#include 
+
+void
+CAST_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    const CAST_KEY *ks, int enc)
+{
+	CAST_LONG l, d[2];
+
+	n2l(in, l);
+	d[0] = l;
+	n2l(in, l);
+	d[1] = l;
+	if (enc)
+		CAST_encrypt(d, ks);
+	else
+		CAST_decrypt(d, ks);
+	l = d[0];
+	l2n(l, out);
+	l = d[1];
+	l2n(l, out);
+	l = d[0] = d[1] = 0;
+}
+LCRYPTO_ALIAS(CAST_ecb_encrypt);
diff --git a/crypto/cast/c_enc.c b/crypto/cast/c_enc.c
new file mode 100644
index 0000000..34fe69f
--- /dev/null
+++ b/crypto/cast/c_enc.c
@@ -0,0 +1,207 @@
+/* $OpenBSD: c_enc.c,v 1.10 2023/07/08 10:43:59 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "cast_local.h"
+
+#ifndef OPENBSD_CAST_ASM
+void
+CAST_encrypt(CAST_LONG *data, const CAST_KEY *key)
+{
+	CAST_LONG l, r, t;
+	const CAST_LONG *k;
+
+	k = &(key->data[0]);
+	l = data[0];
+	r = data[1];
+
+	E_CAST( 0, k,l, r,+,^, -);
+	E_CAST( 1, k,r, l,^, -,+);
+	E_CAST( 2, k,l, r, -,+,^);
+	E_CAST( 3, k,r, l,+,^, -);
+	E_CAST( 4, k,l, r,^, -,+);
+	E_CAST( 5, k,r, l, -,+,^);
+	E_CAST( 6, k,l, r,+,^, -);
+	E_CAST( 7, k,r, l,^, -,+);
+	E_CAST( 8, k,l, r, -,+,^);
+	E_CAST( 9, k,r, l,+,^, -);
+	E_CAST(10, k,l, r,^, -,+);
+	E_CAST(11, k,r, l, -,+,^);
+	if (!key->short_key) {
+		E_CAST(12, k,l, r,+,^, -);
+		E_CAST(13, k,r, l,^, -,+);
+		E_CAST(14, k,l, r, -,+,^);
+		E_CAST(15, k,r, l,+,^, -);
+	}
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+}
+LCRYPTO_ALIAS(CAST_encrypt);
+
+void
+CAST_decrypt(CAST_LONG *data, const CAST_KEY *key)
+{
+	CAST_LONG l, r, t;
+	const CAST_LONG *k;
+
+	k = &(key->data[0]);
+	l = data[0];
+	r = data[1];
+
+	if (!key->short_key) {
+		E_CAST(15, k,l, r,+,^, -);
+		E_CAST(14, k,r, l, -,+,^);
+		E_CAST(13, k,l, r,^, -,+);
+		E_CAST(12, k,r, l,+,^, -);
+	}
+	E_CAST(11, k,l, r, -,+,^);
+	E_CAST(10, k,r, l,^, -,+);
+	E_CAST( 9, k,l, r,+,^, -);
+	E_CAST( 8, k,r, l, -,+,^);
+	E_CAST( 7, k,l, r,^, -,+);
+	E_CAST( 6, k,r, l,+,^, -);
+	E_CAST( 5, k,l, r, -,+,^);
+	E_CAST( 4, k,r, l,^, -,+);
+	E_CAST( 3, k,l, r,+,^, -);
+	E_CAST( 2, k,r, l, -,+,^);
+	E_CAST( 1, k,l, r,^, -,+);
+	E_CAST( 0, k,r, l,+,^, -);
+
+	data[1] = l&0xffffffffL;
+	data[0] = r&0xffffffffL;
+}
+LCRYPTO_ALIAS(CAST_decrypt);
+#endif
+
+void
+CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    const CAST_KEY *ks, unsigned char *iv, int enc)
+{
+	CAST_LONG tin0, tin1;
+	CAST_LONG tout0, tout1, xor0, xor1;
+	long l = length;
+	CAST_LONG tin[2];
+
+	if (enc) {
+		n2l(iv, tout0);
+		n2l(iv, tout1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			CAST_encrypt(tin, ks);
+			tout0 = tin[0];
+			tout1 = tin[1];
+			l2n(tout0, out);
+			l2n(tout1, out);
+		}
+		if (l != -8) {
+			n2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			CAST_encrypt(tin, ks);
+			tout0 = tin[0];
+			tout1 = tin[1];
+			l2n(tout0, out);
+			l2n(tout1, out);
+		}
+		l2n(tout0, iv);
+		l2n(tout1, iv);
+	} else {
+		n2l(iv, xor0);
+		n2l(iv, xor1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin[0] = tin0;
+			tin[1] = tin1;
+			CAST_decrypt(tin, ks);
+			tout0 = tin[0]^xor0;
+			tout1 = tin[1]^xor1;
+			l2n(tout0, out);
+			l2n(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin[0] = tin0;
+			tin[1] = tin1;
+			CAST_decrypt(tin, ks);
+			tout0 = tin[0]^xor0;
+			tout1 = tin[1]^xor1;
+			l2nn(tout0, tout1, out, l + 8);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		l2n(xor0, iv);
+		l2n(xor1, iv);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+LCRYPTO_ALIAS(CAST_cbc_encrypt);
diff --git a/crypto/cast/c_ofb64.c b/crypto/cast/c_ofb64.c
new file mode 100644
index 0000000..48ebab9
--- /dev/null
+++ b/crypto/cast/c_ofb64.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: c_ofb64.c,v 1.8 2023/07/08 10:43:59 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "cast_local.h"
+
+/* The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, const CAST_KEY *schedule, unsigned char *ivec,
+    int *num)
+{
+	CAST_LONG v0, v1, t;
+	int n= *num;
+	long l = length;
+	unsigned char d[8];
+	char *dp;
+	CAST_LONG ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = ivec;
+	n2l(iv, v0);
+	n2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = (char *)d;
+	l2n(v0, dp);
+	l2n(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			CAST_encrypt((CAST_LONG *)ti, schedule);
+			dp = (char *)d;
+			t = ti[0];
+			l2n(t, dp);
+			t = ti[1];
+			l2n(t, dp);
+			save++;
+		}
+		*(out++)= *(in++)^d[n];
+		n = (n + 1)&0x07;
+	}
+	if (save) {
+		v0 = ti[0];
+		v1 = ti[1];
+		iv = ivec;
+		l2n(v0, iv);
+		l2n(v1, iv);
+	}
+	t = v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(CAST_ofb64_encrypt);
diff --git a/crypto/cast/c_skey.c b/crypto/cast/c_skey.c
new file mode 100644
index 0000000..ecce7ba
--- /dev/null
+++ b/crypto/cast/c_skey.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: c_skey.c,v 1.14 2023/07/08 10:43:59 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include "cast_local.h"
+#include "cast_s.h"
+
+#define CAST_exp(l,A,a,n) \
+	A[n/4]=l; \
+	a[n+3]=(l    )&0xff; \
+	a[n+2]=(l>> 8)&0xff; \
+	a[n+1]=(l>>16)&0xff; \
+	a[n+0]=(l>>24)&0xff;
+
+#define S4 CAST_S_table4
+#define S5 CAST_S_table5
+#define S6 CAST_S_table6
+#define S7 CAST_S_table7
+void
+CAST_set_key(CAST_KEY *key, int len, const unsigned char *data)
+{
+	CAST_LONG x[16];
+	CAST_LONG z[16];
+	CAST_LONG k[32];
+	CAST_LONG X[4], Z[4];
+	CAST_LONG l, *K;
+	int i;
+
+	for (i = 0;
+		i < 16;
+	i++) x[i] = 0;
+	if (len > 16)
+		len = 16;
+	for (i = 0; i < len; i++)
+		x[i] = data[i];
+	if (len <= 10)
+		key->short_key = 1;
+	else
+		key->short_key = 0;
+
+	K = &k[0];
+	X[0] = ((x[ 0]<<24)|(x[ 1]<<16)|(x[ 2]<<8)|x[ 3])&0xffffffffL;
+	X[1] = ((x[ 4]<<24)|(x[ 5]<<16)|(x[ 6]<<8)|x[ 7])&0xffffffffL;
+	X[2] = ((x[ 8]<<24)|(x[ 9]<<16)|(x[10]<<8)|x[11])&0xffffffffL;
+	X[3] = ((x[12]<<24)|(x[13]<<16)|(x[14]<<8)|x[15])&0xffffffffL;
+
+	for (;;) {
+		l = X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];
+		CAST_exp(l, Z, z, 0);
+		l = X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];
+		CAST_exp(l, Z, z, 4);
+		l = X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];
+		CAST_exp(l, Z, z, 8);
+		l = X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];
+		CAST_exp(l, Z,z, 12);
+
+		K[0] = S4[z[ 8]]^S5[z[ 9]]^S6[z[ 7]]^S7[z[ 6]]^S4[z[ 2]];
+		K[1] = S4[z[10]]^S5[z[11]]^S6[z[ 5]]^S7[z[ 4]]^S5[z[ 6]];
+		K[2] = S4[z[12]]^S5[z[13]]^S6[z[ 3]]^S7[z[ 2]]^S6[z[ 9]];
+		K[3] = S4[z[14]]^S5[z[15]]^S6[z[ 1]]^S7[z[ 0]]^S7[z[12]];
+
+		l = Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];
+		CAST_exp(l, X, x, 0);
+		l = Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];
+		CAST_exp(l, X, x, 4);
+		l = Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];
+		CAST_exp(l, X, x, 8);
+		l = Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];
+		CAST_exp(l, X,x, 12);
+
+		K[4] = S4[x[ 3]]^S5[x[ 2]]^S6[x[12]]^S7[x[13]]^S4[x[ 8]];
+		K[5] = S4[x[ 1]]^S5[x[ 0]]^S6[x[14]]^S7[x[15]]^S5[x[13]];
+		K[6] = S4[x[ 7]]^S5[x[ 6]]^S6[x[ 8]]^S7[x[ 9]]^S6[x[ 3]];
+		K[7] = S4[x[ 5]]^S5[x[ 4]]^S6[x[10]]^S7[x[11]]^S7[x[ 7]];
+
+		l = X[0]^S4[x[13]]^S5[x[15]]^S6[x[12]]^S7[x[14]]^S6[x[ 8]];
+		CAST_exp(l, Z, z, 0);
+		l = X[2]^S4[z[ 0]]^S5[z[ 2]]^S6[z[ 1]]^S7[z[ 3]]^S7[x[10]];
+		CAST_exp(l, Z, z, 4);
+		l = X[3]^S4[z[ 7]]^S5[z[ 6]]^S6[z[ 5]]^S7[z[ 4]]^S4[x[ 9]];
+		CAST_exp(l, Z, z, 8);
+		l = X[1]^S4[z[10]]^S5[z[ 9]]^S6[z[11]]^S7[z[ 8]]^S5[x[11]];
+		CAST_exp(l, Z,z, 12);
+
+		K[8] = S4[z[ 3]]^S5[z[ 2]]^S6[z[12]]^S7[z[13]]^S4[z[ 9]];
+		K[9] = S4[z[ 1]]^S5[z[ 0]]^S6[z[14]]^S7[z[15]]^S5[z[12]];
+		K[10] = S4[z[ 7]]^S5[z[ 6]]^S6[z[ 8]]^S7[z[ 9]]^S6[z[ 2]];
+		K[11] = S4[z[ 5]]^S5[z[ 4]]^S6[z[10]]^S7[z[11]]^S7[z[ 6]];
+
+		l = Z[2]^S4[z[ 5]]^S5[z[ 7]]^S6[z[ 4]]^S7[z[ 6]]^S6[z[ 0]];
+		CAST_exp(l, X, x, 0);
+		l = Z[0]^S4[x[ 0]]^S5[x[ 2]]^S6[x[ 1]]^S7[x[ 3]]^S7[z[ 2]];
+		CAST_exp(l, X, x, 4);
+		l = Z[1]^S4[x[ 7]]^S5[x[ 6]]^S6[x[ 5]]^S7[x[ 4]]^S4[z[ 1]];
+		CAST_exp(l, X, x, 8);
+		l = Z[3]^S4[x[10]]^S5[x[ 9]]^S6[x[11]]^S7[x[ 8]]^S5[z[ 3]];
+		CAST_exp(l, X,x, 12);
+
+		K[12] = S4[x[ 8]]^S5[x[ 9]]^S6[x[ 7]]^S7[x[ 6]]^S4[x[ 3]];
+		K[13] = S4[x[10]]^S5[x[11]]^S6[x[ 5]]^S7[x[ 4]]^S5[x[ 7]];
+		K[14] = S4[x[12]]^S5[x[13]]^S6[x[ 3]]^S7[x[ 2]]^S6[x[ 8]];
+		K[15] = S4[x[14]]^S5[x[15]]^S6[x[ 1]]^S7[x[ 0]]^S7[x[13]];
+		if (K != k)
+			break;
+		K += 16;
+	}
+
+	for (i = 0; i < 16; i++) {
+		key->data[i*2] = k[i];
+		key->data[i*2 + 1] = ((k[i + 16]) + 16)&0x1f;
+	}
+}
+LCRYPTO_ALIAS(CAST_set_key);
diff --git a/crypto/cast/cast_local.h b/crypto/cast/cast_local.h
new file mode 100644
index 0000000..5fb9911
--- /dev/null
+++ b/crypto/cast/cast_local.h
@@ -0,0 +1,216 @@
+/* $OpenBSD: cast_local.h,v 1.2 2023/07/08 07:25:43 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#undef c2l
+#define c2l(c,l)	(l =((unsigned long)(*((c)++)))    , \
+			 l|=((unsigned long)(*((c)++)))<< 8L, \
+			 l|=((unsigned long)(*((c)++)))<<16L, \
+			 l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))<<24L; \
+			case 7: l2|=((unsigned long)(*(--(c))))<<16L; \
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \
+			case 5: l2|=((unsigned long)(*(--(c))));     \
+			case 4: l1 =((unsigned long)(*(--(c))))<<24L; \
+			case 3: l1|=((unsigned long)(*(--(c))))<<16L; \
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \
+			case 1: l1|=((unsigned long)(*(--(c))));     \
+				} \
+			}
+
+#undef l2c
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff); \
+				} \
+			}
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{ \
+			c+=n; \
+			l1=l2=0; \
+			switch (n) { \
+			case 8: l2 =((unsigned long)(*(--(c))))    ; \
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
+			case 6: l2|=((unsigned long)(*(--(c))))<<16; \
+			case 5: l2|=((unsigned long)(*(--(c))))<<24; \
+			case 4: l1 =((unsigned long)(*(--(c))))    ; \
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
+			case 2: l1|=((unsigned long)(*(--(c))))<<16; \
+			case 1: l1|=((unsigned long)(*(--(c))))<<24; \
+				} \
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{ \
+			c+=n; \
+			switch (n) { \
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff); \
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff); \
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+				} \
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L, \
+                         l|=((unsigned long)(*((c)++)))<<16L, \
+                         l|=((unsigned long)(*((c)++)))<< 8L, \
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+/* only invoked with 0 <= n <= 31 */
+#define ROTL(a,n)     ((((a)<<(n))&0xffffffffL)|((a)>>((32-(n))&31)))
+
+#define C_M    0x3fc
+#define C_0    22L
+#define C_1    14L
+#define C_2     6L
+#define C_3     2L /* left shift */
+
+/* The rotate has an extra 16 added to it to help the x86 asm */
+#if defined(CAST_PTR)
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	int i; \
+	t=(key[n*2] OP1 R)&0xffffffffL; \
+	i=key[n*2+1]; \
+	t=ROTL(t,i); \
+	L^= (((((*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table0+((t>>C_2)&C_M)) OP2 \
+		*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table1+((t<>C_0)&C_M)))&0xffffffffL) OP1 \
+		*(CAST_LONG *)((unsigned char *) \
+			CAST_S_table3+((t>>C_1)&C_M)))&0xffffffffL; \
+	}
+#elif defined(CAST_PTR2)
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	int i; \
+	CAST_LONG u,v,w; \
+	w=(key[n*2] OP1 R)&0xffffffffL; \
+	i=key[n*2+1]; \
+	w=ROTL(w,i); \
+	u=w>>C_2; \
+	v=w<>C_0; \
+	t=(t OP2 *(CAST_LONG *)((unsigned char *)CAST_S_table1+v))&0xffffffffL;\
+	v=w>>C_1; \
+	u&=C_M; \
+	v&=C_M; \
+	t=(t OP3 *(CAST_LONG *)((unsigned char *)CAST_S_table2+u)&0xffffffffL);\
+	t=(t OP1 *(CAST_LONG *)((unsigned char *)CAST_S_table3+v)&0xffffffffL);\
+	L^=(t&0xffffffff); \
+	}
+#else
+#define E_CAST(n,key,L,R,OP1,OP2,OP3) \
+	{ \
+	CAST_LONG a,b,c,d; \
+	t=(key[n*2] OP1 R)&0xffffffff; \
+	t=ROTL(t,(key[n*2+1])); \
+	a=CAST_S_table0[(t>> 8)&0xff]; \
+	b=CAST_S_table1[(t    )&0xff]; \
+	c=CAST_S_table2[(t>>24)&0xff]; \
+	d=CAST_S_table3[(t>>16)&0xff]; \
+	L^=(((((a OP2 b)&0xffffffffL) OP3 c)&0xffffffffL) OP1 d)&0xffffffffL; \
+	}
+#endif
+
+extern const CAST_LONG CAST_S_table0[256];
+extern const CAST_LONG CAST_S_table1[256];
+extern const CAST_LONG CAST_S_table2[256];
+extern const CAST_LONG CAST_S_table3[256];
+extern const CAST_LONG CAST_S_table4[256];
+extern const CAST_LONG CAST_S_table5[256];
+extern const CAST_LONG CAST_S_table6[256];
+extern const CAST_LONG CAST_S_table7[256];
diff --git a/crypto/cast/cast_s.h b/crypto/cast/cast_s.h
new file mode 100644
index 0000000..dc33950
--- /dev/null
+++ b/crypto/cast/cast_s.h
@@ -0,0 +1,590 @@
+/* $OpenBSD: cast_s.h,v 1.7 2023/07/08 07:25:43 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+__BEGIN_HIDDEN_DECLS
+
+const CAST_LONG CAST_S_table0[256] = {
+	0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a,
+	0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+	0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675,
+	0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+	0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2,
+	0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+	0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f,
+	0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+	0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de,
+	0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+	0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f,
+	0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+	0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d,
+	0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+	0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165,
+	0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+	0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272,
+	0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+	0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d,
+	0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+	0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a,
+	0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+	0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f,
+	0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+	0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9,
+	0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+	0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6,
+	0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+	0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9,
+	0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+	0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e,
+	0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+	0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e,
+	0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+	0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82,
+	0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+	0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac,
+	0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+	0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f,
+	0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+	0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491,
+	0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+	0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de,
+	0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+	0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a,
+	0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+	0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79,
+	0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+	0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779,
+	0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+	0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755,
+	0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+	0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb,
+	0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+	0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0,
+	0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+	0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79,
+	0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+	0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298,
+	0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+	0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571,
+	0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+	0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d,
+	0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf,
+};
+const CAST_LONG CAST_S_table1[256] = {
+	0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380,
+	0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+	0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba,
+	0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+	0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909,
+	0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+	0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b,
+	0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+	0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4,
+	0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+	0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f,
+	0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+	0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21,
+	0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+	0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d,
+	0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+	0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f,
+	0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+	0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d,
+	0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+	0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4,
+	0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+	0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801,
+	0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+	0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755,
+	0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+	0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709,
+	0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+	0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b,
+	0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+	0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c,
+	0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+	0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9,
+	0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+	0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3,
+	0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+	0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9,
+	0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+	0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab,
+	0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+	0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4,
+	0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+	0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43,
+	0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+	0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8,
+	0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+	0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171,
+	0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+	0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89,
+	0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+	0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b,
+	0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+	0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb,
+	0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+	0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e,
+	0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+	0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea,
+	0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+	0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea,
+	0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+	0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd,
+	0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+	0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef,
+	0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1,
+};
+const CAST_LONG CAST_S_table2[256] = {
+	0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907,
+	0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+	0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae,
+	0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+	0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e,
+	0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+	0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc,
+	0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+	0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e,
+	0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+	0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f,
+	0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+	0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99,
+	0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+	0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f,
+	0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+	0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380,
+	0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+	0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8,
+	0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+	0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504,
+	0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+	0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6,
+	0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+	0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e,
+	0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+	0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d,
+	0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+	0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1,
+	0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+	0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c,
+	0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+	0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15,
+	0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+	0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4,
+	0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+	0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b,
+	0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+	0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392,
+	0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+	0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231,
+	0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+	0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889,
+	0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+	0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67,
+	0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+	0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49,
+	0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+	0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d,
+	0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+	0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d,
+	0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+	0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e,
+	0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+	0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767,
+	0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+	0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce,
+	0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+	0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24,
+	0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+	0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0,
+	0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+	0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5,
+	0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783,
+};
+const CAST_LONG CAST_S_table3[256] = {
+	0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298,
+	0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+	0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120,
+	0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+	0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220,
+	0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+	0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe,
+	0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+	0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701,
+	0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+	0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b,
+	0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+	0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93,
+	0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+	0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746,
+	0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+	0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9,
+	0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+	0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb,
+	0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+	0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c,
+	0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+	0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7,
+	0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+	0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340,
+	0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+	0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327,
+	0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+	0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec,
+	0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+	0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205,
+	0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+	0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031,
+	0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+	0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5,
+	0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+	0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c,
+	0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+	0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69,
+	0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+	0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9,
+	0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+	0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff,
+	0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+	0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3,
+	0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+	0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2,
+	0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+	0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff,
+	0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+	0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091,
+	0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+	0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df,
+	0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+	0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf,
+	0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+	0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367,
+	0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+	0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c,
+	0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+	0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43,
+	0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+	0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e,
+	0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2,
+};
+const CAST_LONG CAST_S_table4[256] = {
+	0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911,
+	0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+	0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00,
+	0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+	0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180,
+	0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+	0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2,
+	0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+	0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725,
+	0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+	0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b,
+	0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+	0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571,
+	0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+	0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec,
+	0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+	0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea,
+	0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+	0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263,
+	0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+	0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468,
+	0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+	0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b,
+	0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+	0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284,
+	0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+	0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4,
+	0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+	0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7,
+	0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+	0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce,
+	0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+	0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6,
+	0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+	0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4,
+	0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+	0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561,
+	0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+	0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6,
+	0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+	0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406,
+	0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+	0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472,
+	0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+	0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487,
+	0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+	0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288,
+	0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+	0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2,
+	0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+	0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78,
+	0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+	0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76,
+	0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+	0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0,
+	0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+	0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58,
+	0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+	0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2,
+	0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+	0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be,
+	0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+	0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55,
+	0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4,
+};
+const CAST_LONG CAST_S_table5[256] = {
+	0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c,
+	0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+	0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9,
+	0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+	0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e,
+	0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+	0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866,
+	0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+	0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c,
+	0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+	0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd,
+	0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+	0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53,
+	0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+	0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d,
+	0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+	0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf,
+	0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+	0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807,
+	0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+	0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a,
+	0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+	0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563,
+	0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+	0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0,
+	0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+	0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be,
+	0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+	0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0,
+	0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+	0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2,
+	0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+	0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853,
+	0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+	0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa,
+	0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+	0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9,
+	0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+	0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751,
+	0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+	0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358,
+	0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+	0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397,
+	0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+	0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459,
+	0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+	0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4,
+	0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+	0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f,
+	0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+	0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb,
+	0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+	0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2,
+	0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+	0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab,
+	0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+	0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b,
+	0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+	0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b,
+	0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+	0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855,
+	0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+	0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454,
+	0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f,
+};
+const CAST_LONG CAST_S_table6[256] = {
+	0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693,
+	0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+	0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82,
+	0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+	0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd,
+	0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+	0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f,
+	0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+	0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9,
+	0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+	0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e,
+	0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+	0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83,
+	0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+	0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e,
+	0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+	0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a,
+	0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+	0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f,
+	0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+	0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b,
+	0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+	0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78,
+	0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+	0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d,
+	0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+	0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802,
+	0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+	0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9,
+	0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+	0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302,
+	0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+	0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858,
+	0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+	0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a,
+	0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+	0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4,
+	0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+	0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df,
+	0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+	0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9,
+	0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+	0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c,
+	0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+	0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07,
+	0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+	0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939,
+	0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+	0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e,
+	0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+	0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378,
+	0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+	0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd,
+	0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+	0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567,
+	0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+	0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2,
+	0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+	0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf,
+	0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+	0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2,
+	0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+	0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada,
+	0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3,
+};
+const CAST_LONG CAST_S_table7[256] = {
+	0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095,
+	0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+	0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174,
+	0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+	0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940,
+	0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+	0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42,
+	0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+	0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164,
+	0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+	0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4,
+	0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+	0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0,
+	0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+	0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6,
+	0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+	0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491,
+	0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+	0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b,
+	0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+	0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8,
+	0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+	0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006,
+	0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+	0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564,
+	0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+	0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab,
+	0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+	0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc,
+	0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+	0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8,
+	0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+	0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441,
+	0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+	0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f,
+	0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+	0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504,
+	0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+	0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c,
+	0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+	0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6,
+	0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+	0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd,
+	0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+	0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4,
+	0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+	0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc,
+	0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+	0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba,
+	0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+	0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf,
+	0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+	0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603,
+	0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+	0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37,
+	0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+	0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819,
+	0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+	0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d,
+	0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+	0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347,
+	0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+	0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d,
+	0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e,
+};
+
+__END_HIDDEN_DECLS
diff --git a/crypto/chacha/chacha-merged.c b/crypto/chacha/chacha-merged.c
new file mode 100644
index 0000000..b405af8
--- /dev/null
+++ b/crypto/chacha/chacha-merged.c
@@ -0,0 +1,323 @@
+/* $OpenBSD: chacha-merged.c,v 1.11 2023/07/07 19:37:53 beck Exp $ */
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+#include 
+
+#define CHACHA_MINKEYLEN	16
+#define CHACHA_NONCELEN		8
+#define CHACHA_CTRLEN		8
+#define CHACHA_STATELEN		(CHACHA_NONCELEN+CHACHA_CTRLEN)
+#define CHACHA_BLOCKLEN		64
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+
+struct chacha_ctx {
+	u32 input[16];
+	u8 ks[CHACHA_BLOCKLEN];
+	u8 unused;
+};
+
+static inline void chacha_keysetup(struct chacha_ctx *x, const u8 *k, u32 kbits)
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
+static inline void chacha_ivsetup(struct chacha_ctx *x, const u8 *iv,
+    const u8 *ctr)
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
+    __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
+static inline void chacha_encrypt_bytes(struct chacha_ctx *x, const u8 *m,
+    u8 *c, u32 bytes)
+    __attribute__((__bounded__(__buffer__, 2, 4)))
+    __attribute__((__bounded__(__buffer__, 3, 4)));
+
+typedef struct chacha_ctx chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+  (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+  (((u32)((p)[0])) | \
+   ((u32)((p)[1]) <<  8) | \
+   ((u32)((p)[2]) << 16) | \
+   ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+  do { \
+    (p)[0] = U8V((v)); \
+    (p)[1] = U8V((v) >>  8); \
+    (p)[2] = U8V((v) >> 16); \
+    (p)[3] = U8V((v) >> 24); \
+  } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+/* Initialise with "expand 32-byte k". */
+static const char sigma[16] = {
+	0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x33,
+	0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b,
+};
+
+/* Initialise with "expand 16-byte k". */
+static const char tau[16] = {
+	0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x20, 0x31,
+	0x36, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b,
+};
+
+static inline void
+chacha_keysetup(chacha_ctx *x, const u8 *k, u32 kbits)
+{
+	const char *constants;
+
+	x->input[4] = U8TO32_LITTLE(k + 0);
+	x->input[5] = U8TO32_LITTLE(k + 4);
+	x->input[6] = U8TO32_LITTLE(k + 8);
+	x->input[7] = U8TO32_LITTLE(k + 12);
+	if (kbits == 256) { /* recommended */
+		k += 16;
+		constants = sigma;
+	} else { /* kbits == 128 */
+		constants = tau;
+	}
+	x->input[8] = U8TO32_LITTLE(k + 0);
+	x->input[9] = U8TO32_LITTLE(k + 4);
+	x->input[10] = U8TO32_LITTLE(k + 8);
+	x->input[11] = U8TO32_LITTLE(k + 12);
+	x->input[0] = U8TO32_LITTLE(constants + 0);
+	x->input[1] = U8TO32_LITTLE(constants + 4);
+	x->input[2] = U8TO32_LITTLE(constants + 8);
+	x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static inline void
+chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter)
+{
+	x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
+	x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
+	x->input[14] = U8TO32_LITTLE(iv + 0);
+	x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static inline void
+chacha_encrypt_bytes(chacha_ctx *x, const u8 *m, u8 *c, u32 bytes)
+{
+	u32 x0, x1, x2, x3, x4, x5, x6, x7;
+	u32 x8, x9, x10, x11, x12, x13, x14, x15;
+	u32 j0, j1, j2, j3, j4, j5, j6, j7;
+	u32 j8, j9, j10, j11, j12, j13, j14, j15;
+	u8 *ctarget = NULL;
+	u8 tmp[64];
+	u32 i;
+
+	if (!bytes)
+		return;
+
+	j0 = x->input[0];
+	j1 = x->input[1];
+	j2 = x->input[2];
+	j3 = x->input[3];
+	j4 = x->input[4];
+	j5 = x->input[5];
+	j6 = x->input[6];
+	j7 = x->input[7];
+	j8 = x->input[8];
+	j9 = x->input[9];
+	j10 = x->input[10];
+	j11 = x->input[11];
+	j12 = x->input[12];
+	j13 = x->input[13];
+	j14 = x->input[14];
+	j15 = x->input[15];
+
+	for (;;) {
+		if (bytes < 64) {
+			for (i = 0; i < bytes; ++i)
+				tmp[i] = m[i];
+			m = tmp;
+			ctarget = c;
+			c = tmp;
+		}
+		x0 = j0;
+		x1 = j1;
+		x2 = j2;
+		x3 = j3;
+		x4 = j4;
+		x5 = j5;
+		x6 = j6;
+		x7 = j7;
+		x8 = j8;
+		x9 = j9;
+		x10 = j10;
+		x11 = j11;
+		x12 = j12;
+		x13 = j13;
+		x14 = j14;
+		x15 = j15;
+		for (i = 20; i > 0; i -= 2) {
+			QUARTERROUND(x0, x4, x8, x12)
+			QUARTERROUND(x1, x5, x9, x13)
+			QUARTERROUND(x2, x6, x10, x14)
+			QUARTERROUND(x3, x7, x11, x15)
+			QUARTERROUND(x0, x5, x10, x15)
+			QUARTERROUND(x1, x6, x11, x12)
+			QUARTERROUND(x2, x7, x8, x13)
+			QUARTERROUND(x3, x4, x9, x14)
+		}
+		x0 = PLUS(x0, j0);
+		x1 = PLUS(x1, j1);
+		x2 = PLUS(x2, j2);
+		x3 = PLUS(x3, j3);
+		x4 = PLUS(x4, j4);
+		x5 = PLUS(x5, j5);
+		x6 = PLUS(x6, j6);
+		x7 = PLUS(x7, j7);
+		x8 = PLUS(x8, j8);
+		x9 = PLUS(x9, j9);
+		x10 = PLUS(x10, j10);
+		x11 = PLUS(x11, j11);
+		x12 = PLUS(x12, j12);
+		x13 = PLUS(x13, j13);
+		x14 = PLUS(x14, j14);
+		x15 = PLUS(x15, j15);
+
+		if (bytes < 64) {
+			U32TO8_LITTLE(x->ks + 0, x0);
+			U32TO8_LITTLE(x->ks + 4, x1);
+			U32TO8_LITTLE(x->ks + 8, x2);
+			U32TO8_LITTLE(x->ks + 12, x3);
+			U32TO8_LITTLE(x->ks + 16, x4);
+			U32TO8_LITTLE(x->ks + 20, x5);
+			U32TO8_LITTLE(x->ks + 24, x6);
+			U32TO8_LITTLE(x->ks + 28, x7);
+			U32TO8_LITTLE(x->ks + 32, x8);
+			U32TO8_LITTLE(x->ks + 36, x9);
+			U32TO8_LITTLE(x->ks + 40, x10);
+			U32TO8_LITTLE(x->ks + 44, x11);
+			U32TO8_LITTLE(x->ks + 48, x12);
+			U32TO8_LITTLE(x->ks + 52, x13);
+			U32TO8_LITTLE(x->ks + 56, x14);
+			U32TO8_LITTLE(x->ks + 60, x15);
+		}
+
+		x0 = XOR(x0, U8TO32_LITTLE(m + 0));
+		x1 = XOR(x1, U8TO32_LITTLE(m + 4));
+		x2 = XOR(x2, U8TO32_LITTLE(m + 8));
+		x3 = XOR(x3, U8TO32_LITTLE(m + 12));
+		x4 = XOR(x4, U8TO32_LITTLE(m + 16));
+		x5 = XOR(x5, U8TO32_LITTLE(m + 20));
+		x6 = XOR(x6, U8TO32_LITTLE(m + 24));
+		x7 = XOR(x7, U8TO32_LITTLE(m + 28));
+		x8 = XOR(x8, U8TO32_LITTLE(m + 32));
+		x9 = XOR(x9, U8TO32_LITTLE(m + 36));
+		x10 = XOR(x10, U8TO32_LITTLE(m + 40));
+		x11 = XOR(x11, U8TO32_LITTLE(m + 44));
+		x12 = XOR(x12, U8TO32_LITTLE(m + 48));
+		x13 = XOR(x13, U8TO32_LITTLE(m + 52));
+		x14 = XOR(x14, U8TO32_LITTLE(m + 56));
+		x15 = XOR(x15, U8TO32_LITTLE(m + 60));
+
+		j12 = PLUSONE(j12);
+		if (!j12) {
+			j13 = PLUSONE(j13);
+			/*
+			 * Stopping at 2^70 bytes per nonce is the user's
+			 * responsibility.
+			 */
+		}
+
+		U32TO8_LITTLE(c + 0, x0);
+		U32TO8_LITTLE(c + 4, x1);
+		U32TO8_LITTLE(c + 8, x2);
+		U32TO8_LITTLE(c + 12, x3);
+		U32TO8_LITTLE(c + 16, x4);
+		U32TO8_LITTLE(c + 20, x5);
+		U32TO8_LITTLE(c + 24, x6);
+		U32TO8_LITTLE(c + 28, x7);
+		U32TO8_LITTLE(c + 32, x8);
+		U32TO8_LITTLE(c + 36, x9);
+		U32TO8_LITTLE(c + 40, x10);
+		U32TO8_LITTLE(c + 44, x11);
+		U32TO8_LITTLE(c + 48, x12);
+		U32TO8_LITTLE(c + 52, x13);
+		U32TO8_LITTLE(c + 56, x14);
+		U32TO8_LITTLE(c + 60, x15);
+
+		if (bytes <= 64) {
+			if (bytes < 64) {
+				for (i = 0; i < bytes; ++i)
+					ctarget[i] = c[i];
+			}
+			x->input[12] = j12;
+			x->input[13] = j13;
+			x->unused = 64 - bytes;
+			return;
+		}
+		bytes -= 64;
+		c += 64;
+		m += 64;
+	}
+}
+
+void
+CRYPTO_hchacha_20(unsigned char subkey[32], const unsigned char key[32],
+    const unsigned char nonce[16])
+{
+	uint32_t x[16];
+	int i;
+
+	x[0] = U8TO32_LITTLE(sigma + 0);
+	x[1] = U8TO32_LITTLE(sigma + 4);
+	x[2] = U8TO32_LITTLE(sigma + 8);
+	x[3] = U8TO32_LITTLE(sigma + 12);
+	x[4] = U8TO32_LITTLE(key + 0);
+	x[5] = U8TO32_LITTLE(key + 4);
+	x[6] = U8TO32_LITTLE(key + 8);
+	x[7] = U8TO32_LITTLE(key + 12);
+	x[8] = U8TO32_LITTLE(key + 16);
+	x[9] = U8TO32_LITTLE(key + 20);
+	x[10] = U8TO32_LITTLE(key + 24);
+	x[11] = U8TO32_LITTLE(key + 28);
+	x[12] = U8TO32_LITTLE(nonce + 0);
+	x[13] = U8TO32_LITTLE(nonce + 4);
+	x[14] = U8TO32_LITTLE(nonce + 8);
+	x[15] = U8TO32_LITTLE(nonce + 12);
+
+	for (i = 20; i > 0; i -= 2) {
+		QUARTERROUND(x[0], x[4], x[8], x[12])
+		QUARTERROUND(x[1], x[5], x[9], x[13])
+		QUARTERROUND(x[2], x[6], x[10], x[14])
+		QUARTERROUND(x[3], x[7], x[11], x[15])
+		QUARTERROUND(x[0], x[5], x[10], x[15])
+		QUARTERROUND(x[1], x[6], x[11], x[12])
+		QUARTERROUND(x[2], x[7], x[8], x[13])
+		QUARTERROUND(x[3], x[4], x[9], x[14])
+	}
+
+	U32TO8_LITTLE(subkey + 0, x[0]);
+	U32TO8_LITTLE(subkey + 4, x[1]);
+	U32TO8_LITTLE(subkey + 8, x[2]);
+	U32TO8_LITTLE(subkey + 12, x[3]);
+
+	U32TO8_LITTLE(subkey + 16, x[12]);
+	U32TO8_LITTLE(subkey + 20, x[13]);
+	U32TO8_LITTLE(subkey + 24, x[14]);
+	U32TO8_LITTLE(subkey + 28, x[15]);
+}
+LCRYPTO_ALIAS(CRYPTO_hchacha_20);
diff --git a/crypto/chacha/chacha.c b/crypto/chacha/chacha.c
new file mode 100644
index 0000000..b60e3c4
--- /dev/null
+++ b/crypto/chacha/chacha.c
@@ -0,0 +1,112 @@
+/* $OpenBSD: chacha.c,v 1.10 2023/07/05 16:17:20 beck Exp $ */
+/*
+ * Copyright (c) 2014 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#include "chacha-merged.c"
+
+void
+ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, uint32_t keybits)
+{
+	chacha_keysetup((chacha_ctx *)ctx, key, keybits);
+	ctx->unused = 0;
+}
+LCRYPTO_ALIAS(ChaCha_set_key);
+
+void
+ChaCha_set_iv(ChaCha_ctx *ctx, const unsigned char *iv,
+    const unsigned char *counter)
+{
+	chacha_ivsetup((chacha_ctx *)ctx, iv, counter);
+	ctx->unused = 0;
+}
+LCRYPTO_ALIAS(ChaCha_set_iv);
+
+void
+ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, size_t len)
+{
+	unsigned char *k;
+	uint64_t n;
+	int i, l;
+
+	/* Consume remaining keystream, if any exists. */
+	if (ctx->unused > 0) {
+		k = ctx->ks + 64 - ctx->unused;
+		l = (len > ctx->unused) ? ctx->unused : len;
+		for (i = 0; i < l; i++)
+			*(out++) = *(in++) ^ *(k++);
+		ctx->unused -= l;
+		len -= l;
+	}
+
+	while (len > 0) {
+		if ((n = len) > UINT32_MAX)
+			n = UINT32_MAX;
+
+		chacha_encrypt_bytes((chacha_ctx *)ctx, in, out, (uint32_t)n);
+
+		in += n;
+		out += n;
+		len -= n;
+	}
+}
+LCRYPTO_ALIAS(ChaCha);
+
+void
+CRYPTO_chacha_20(unsigned char *out, const unsigned char *in, size_t len,
+    const unsigned char key[32], const unsigned char iv[8], uint64_t counter)
+{
+	struct chacha_ctx ctx;
+	uint64_t n;
+
+	/*
+	 * chacha_ivsetup expects the counter to be in u8. Rather than
+	 * converting size_t to u8 and then back again, pass a counter of
+	 * NULL and manually assign it afterwards.
+	 */
+	chacha_keysetup(&ctx, key, 256);
+	chacha_ivsetup(&ctx, iv, NULL);
+	if (counter != 0) {
+		ctx.input[12] = (uint32_t)counter;
+		ctx.input[13] = (uint32_t)(counter >> 32);
+	}
+
+	while (len > 0) {
+		if ((n = len) > UINT32_MAX)
+			n = UINT32_MAX;
+
+		chacha_encrypt_bytes(&ctx, in, out, (uint32_t)n);
+
+		in += n;
+		out += n;
+		len -= n;
+	}
+}
+LCRYPTO_ALIAS(CRYPTO_chacha_20);
+
+void
+CRYPTO_xchacha_20(unsigned char *out, const unsigned char *in, size_t len,
+    const unsigned char key[32], const unsigned char iv[24])
+{
+	uint8_t subkey[32];
+
+	CRYPTO_hchacha_20(subkey, key, iv);
+	CRYPTO_chacha_20(out, in, len, subkey, iv + 16, 0);
+}
+LCRYPTO_ALIAS(CRYPTO_xchacha_20);
diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c
new file mode 100644
index 0000000..04e0eb8
--- /dev/null
+++ b/crypto/cmac/cm_ameth.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: cm_ameth.c,v 1.10 2022/11/26 16:08:51 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2010.
+ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.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_free(pkey->pkey.ptr);
+}
+
+const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = {
+	.pkey_id = EVP_PKEY_CMAC,
+	.pkey_base_id = EVP_PKEY_CMAC,
+
+	.pem_str = "CMAC",
+	.info = "OpenSSL CMAC method",
+
+	.pkey_size = cmac_size,
+	.pkey_free = cmac_key_free
+};
diff --git a/crypto/cmac/cm_pmeth.c b/crypto/cmac/cm_pmeth.c
new file mode 100644
index 0000000..d47cfb7
--- /dev/null
+++ b/crypto/cmac/cm_pmeth.c
@@ -0,0 +1,212 @@
+/* $OpenBSD: cm_pmeth.c,v 1.10 2022/11/26 16:08:51 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2010.
+ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.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)
+		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)
+		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(ctx->pctx->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);
+	mctx->update = 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, 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, "key")) {
+		void *p = (void *)value;
+		return pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
+		    strlen(p), p);
+	}
+	if (!strcmp(type, "cipher")) {
+		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, "hexkey")) {
+		unsigned char *key;
+		int r;
+		long keylen;
+
+		key = string_to_hex(value, &keylen);
+		if (!key)
+			return 0;
+		r = pkey_cmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key);
+		free(key);
+		return r;
+	}
+
+	return -2;
+}
+
+const EVP_PKEY_METHOD cmac_pkey_meth = {
+	.pkey_id = EVP_PKEY_CMAC,
+	.flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+
+	.init = pkey_cmac_init,
+	.copy = pkey_cmac_copy,
+	.cleanup = pkey_cmac_cleanup,
+
+	.keygen = pkey_cmac_keygen,
+
+	.signctx_init = cmac_signctx_init,
+	.signctx = cmac_signctx,
+
+	.ctrl = pkey_cmac_ctrl,
+	.ctrl_str = pkey_cmac_ctrl_str
+};
diff --git a/crypto/cmac/cmac.c b/crypto/cmac/cmac.c
new file mode 100644
index 0000000..9c05a98
--- /dev/null
+++ b/crypto/cmac/cmac.c
@@ -0,0 +1,292 @@
+/* $OpenBSD: cmac.c,v 1.14 2023/07/08 14:27:14 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "evp_local.h"
+
+struct CMAC_CTX_st {
+	/* Cipher context to use */
+	EVP_CIPHER_CTX cctx;
+	/* Keys k1 and k2 */
+	unsigned char k1[EVP_MAX_BLOCK_LENGTH];
+	unsigned char k2[EVP_MAX_BLOCK_LENGTH];
+	/* Temporary block */
+	unsigned char tbl[EVP_MAX_BLOCK_LENGTH];
+	/* Last (possibly partial) block */
+	unsigned char last_block[EVP_MAX_BLOCK_LENGTH];
+	/* Number of bytes in last block: -1 means context not initialised */
+	int nlast_block;
+};
+
+
+/* Make temporary keys K1 and K2 */
+
+static void
+make_kn(unsigned char *k1, unsigned char *l, int bl)
+{
+	int i;
+
+	/* Shift block to left, including carry */
+	for (i = 0; i < bl; i++) {
+		k1[i] = l[i] << 1;
+		if (i < bl - 1 && l[i + 1] & 0x80)
+			k1[i] |= 1;
+	}
+	/* If MSB set fixup with R */
+	if (l[0] & 0x80)
+		k1[bl - 1] ^= bl == 16 ? 0x87 : 0x1b;
+}
+
+CMAC_CTX *
+CMAC_CTX_new(void)
+{
+	CMAC_CTX *ctx;
+
+	ctx = malloc(sizeof(CMAC_CTX));
+	if (!ctx)
+		return NULL;
+	EVP_CIPHER_CTX_init(&ctx->cctx);
+	ctx->nlast_block = -1;
+	return ctx;
+}
+LCRYPTO_ALIAS(CMAC_CTX_new);
+
+void
+CMAC_CTX_cleanup(CMAC_CTX *ctx)
+{
+	EVP_CIPHER_CTX_cleanup(&ctx->cctx);
+	explicit_bzero(ctx->tbl, EVP_MAX_BLOCK_LENGTH);
+	explicit_bzero(ctx->k1, EVP_MAX_BLOCK_LENGTH);
+	explicit_bzero(ctx->k2, EVP_MAX_BLOCK_LENGTH);
+	explicit_bzero(ctx->last_block, EVP_MAX_BLOCK_LENGTH);
+	ctx->nlast_block = -1;
+}
+LCRYPTO_ALIAS(CMAC_CTX_cleanup);
+
+EVP_CIPHER_CTX *
+CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx)
+{
+	return &ctx->cctx;
+}
+LCRYPTO_ALIAS(CMAC_CTX_get0_cipher_ctx);
+
+void
+CMAC_CTX_free(CMAC_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	CMAC_CTX_cleanup(ctx);
+	free(ctx);
+}
+LCRYPTO_ALIAS(CMAC_CTX_free);
+
+int
+CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in)
+{
+	int bl;
+
+	if (in->nlast_block == -1)
+		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);
+	memcpy(out->last_block, in->last_block, bl);
+	out->nlast_block = in->nlast_block;
+	return 1;
+}
+LCRYPTO_ALIAS(CMAC_CTX_copy);
+
+int
+CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
+    const EVP_CIPHER *cipher, ENGINE *impl)
+{
+	static unsigned char zero_iv[EVP_MAX_BLOCK_LENGTH];
+
+	/* All zeros means restart */
+	if (!key && !cipher && !impl && keylen == 0) {
+		/* Not initialised */
+		if (ctx->nlast_block == -1)
+			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));
+		ctx->nlast_block = 0;
+		return 1;
+	}
+	/* Initialise context */
+	if (cipher && !EVP_EncryptInit_ex(&ctx->cctx, cipher, impl, NULL, NULL))
+		return 0;
+	/* Non-NULL key means initialisation complete */
+	if (key) {
+		int bl;
+
+		if (!EVP_CIPHER_CTX_cipher(&ctx->cctx))
+			return 0;
+		if (!EVP_CIPHER_CTX_set_key_length(&ctx->cctx, keylen))
+			return 0;
+		if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, key, zero_iv))
+			return 0;
+		bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
+		if (!EVP_Cipher(&ctx->cctx, ctx->tbl, zero_iv, bl))
+			return 0;
+		make_kn(ctx->k1, ctx->tbl, bl);
+		make_kn(ctx->k2, ctx->k1, bl);
+		explicit_bzero(ctx->tbl, bl);
+		/* Reset context again ready for first data block */
+		if (!EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, zero_iv))
+			return 0;
+		/* Zero tbl so resume works */
+		memset(ctx->tbl, 0, bl);
+		ctx->nlast_block = 0;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(CMAC_Init);
+
+int
+CMAC_Update(CMAC_CTX *ctx, const void *in, size_t dlen)
+{
+	const unsigned char *data = in;
+	size_t bl;
+
+	if (ctx->nlast_block == -1)
+		return 0;
+	if (dlen == 0)
+		return 1;
+	bl = EVP_CIPHER_CTX_block_size(&ctx->cctx);
+	/* 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;
+		memcpy(ctx->last_block + ctx->nlast_block, data, nleft);
+		dlen -= nleft;
+		ctx->nlast_block += nleft;
+		/* If no more to process return */
+		if (dlen == 0)
+			return 1;
+		data += nleft;
+		/* Else not final block so encrypt it */
+		if (!EVP_Cipher(&ctx->cctx, ctx->tbl, ctx->last_block, bl))
+			return 0;
+	}
+	/* Encrypt all but one of the complete blocks left */
+	while (dlen > bl) {
+		if (!EVP_Cipher(&ctx->cctx, ctx->tbl, data, bl))
+			return 0;
+		dlen -= bl;
+		data += bl;
+	}
+	/* Copy any data left to last block buffer */
+	memcpy(ctx->last_block, data, dlen);
+	ctx->nlast_block = dlen;
+	return 1;
+}
+LCRYPTO_ALIAS(CMAC_Update);
+
+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 (!out)
+		return 1;
+	lb = ctx->nlast_block;
+	/* Is last block complete? */
+	if (lb == bl) {
+		for (i = 0; i < bl; i++)
+			out[i] = ctx->last_block[i] ^ ctx->k1[i];
+	} else {
+		ctx->last_block[lb] = 0x80;
+		if (bl - lb > 1)
+			memset(ctx->last_block + lb + 1, 0, bl - lb - 1);
+		for (i = 0; i < bl; i++)
+			out[i] = ctx->last_block[i] ^ ctx->k2[i];
+	}
+	if (!EVP_Cipher(&ctx->cctx, out, out, bl)) {
+		explicit_bzero(out, bl);
+		return 0;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(CMAC_Final);
+
+int
+CMAC_resume(CMAC_CTX *ctx)
+{
+	if (ctx->nlast_block == -1)
+		return 0;
+	/* The buffer "tbl" containes the last fully encrypted block
+	 * which is the last IV (or all zeroes if no last encrypted block).
+	 * The last block has not been modified since CMAC_final().
+	 * So reinitialising using the last decrypted block will allow
+	 * CMAC to continue after calling CMAC_Final().
+	 */
+	return EVP_EncryptInit_ex(&ctx->cctx, NULL, NULL, NULL, ctx->tbl);
+}
+LCRYPTO_ALIAS(CMAC_resume);
diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c
new file mode 100644
index 0000000..531b8c5
--- /dev/null
+++ b/crypto/cms/cms_asn1.c
@@ -0,0 +1,1622 @@
+/* $OpenBSD: cms_asn1.c,v 1.23 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+
+
+static const ASN1_TEMPLATE CMS_IssuerAndSerialNumber_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_IssuerAndSerialNumber, issuer),
+		.field_name = "issuer",
+		.item = &X509_NAME_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_IssuerAndSerialNumber, serialNumber),
+		.field_name = "serialNumber",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM CMS_IssuerAndSerialNumber_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_IssuerAndSerialNumber_seq_tt,
+	.tcount = sizeof(CMS_IssuerAndSerialNumber_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_IssuerAndSerialNumber),
+	.sname = "CMS_IssuerAndSerialNumber",
+};
+
+static const ASN1_TEMPLATE CMS_OtherCertificateFormat_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherCertificateFormat, otherCertFormat),
+		.field_name = "otherCertFormat",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherCertificateFormat, otherCert),
+		.field_name = "otherCert",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+static const ASN1_ITEM CMS_OtherCertificateFormat_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OtherCertificateFormat_seq_tt,
+	.tcount = sizeof(CMS_OtherCertificateFormat_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OtherCertificateFormat),
+	.sname = "CMS_OtherCertificateFormat",
+};
+
+static const ASN1_TEMPLATE CMS_CertificateChoices_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_CertificateChoices, d.certificate),
+		.field_name = "d.certificate",
+		.item = &X509_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_CertificateChoices, d.extendedCertificate),
+		.field_name = "d.extendedCertificate",
+		.item = &ASN1_SEQUENCE_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(CMS_CertificateChoices, d.v1AttrCert),
+		.field_name = "d.v1AttrCert",
+		.item = &ASN1_SEQUENCE_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 2,
+		.offset = offsetof(CMS_CertificateChoices, d.v2AttrCert),
+		.field_name = "d.v2AttrCert",
+		.item = &ASN1_SEQUENCE_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 3,
+		.offset = offsetof(CMS_CertificateChoices, d.other),
+		.field_name = "d.other",
+		.item = &CMS_OtherCertificateFormat_it,
+	},
+};
+
+const ASN1_ITEM CMS_CertificateChoices_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_CertificateChoices, type),
+	.templates = CMS_CertificateChoices_ch_tt,
+	.tcount = sizeof(CMS_CertificateChoices_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_CertificateChoices),
+	.sname = "CMS_CertificateChoices",
+};
+
+static const ASN1_TEMPLATE CMS_SignerIdentifier_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerIdentifier, d.issuerAndSerialNumber),
+		.field_name = "d.issuerAndSerialNumber",
+		.item = &CMS_IssuerAndSerialNumber_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerIdentifier, d.subjectKeyIdentifier),
+		.field_name = "d.subjectKeyIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+static const ASN1_ITEM CMS_SignerIdentifier_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_SignerIdentifier, type),
+	.templates = CMS_SignerIdentifier_ch_tt,
+	.tcount = sizeof(CMS_SignerIdentifier_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_SignerIdentifier),
+	.sname = "CMS_SignerIdentifier",
+};
+
+static const ASN1_TEMPLATE CMS_EncapsulatedContentInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EncapsulatedContentInfo, eContentType),
+		.field_name = "eContentType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+		.tag = 0,
+		.offset = offsetof(CMS_EncapsulatedContentInfo, eContent),
+		.field_name = "eContent",
+		.item = &ASN1_OCTET_STRING_NDEF_it,
+	},
+};
+
+static const ASN1_ITEM CMS_EncapsulatedContentInfo_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_EncapsulatedContentInfo_seq_tt,
+	.tcount = sizeof(CMS_EncapsulatedContentInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_EncapsulatedContentInfo),
+	.sname = "CMS_EncapsulatedContentInfo",
+};
+
+/* Minor tweak to operation: free up signer key, cert */
+static int
+cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_FREE_POST) {
+		CMS_SignerInfo *si = (CMS_SignerInfo *)*pval;
+		EVP_PKEY_free(si->pkey);
+		X509_free(si->signer);
+		EVP_MD_CTX_free(si->mctx);
+	}
+	return 1;
+}
+
+static const ASN1_AUX CMS_SignerInfo_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = cms_si_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE CMS_SignerInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, sid),
+		.field_name = "sid",
+		.item = &CMS_SignerIdentifier_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, digestAlgorithm),
+		.field_name = "digestAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, signedAttrs),
+		.field_name = "signedAttrs",
+		.item = &X509_ATTRIBUTE_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, signatureAlgorithm),
+		.field_name = "signatureAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignerInfo, signature),
+		.field_name = "signature",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_SignerInfo, unsignedAttrs),
+		.field_name = "unsignedAttrs",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM CMS_SignerInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_SignerInfo_seq_tt,
+	.tcount = sizeof(CMS_SignerInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &CMS_SignerInfo_aux,
+	.size = sizeof(CMS_SignerInfo),
+	.sname = "CMS_SignerInfo",
+};
+
+static const ASN1_TEMPLATE CMS_OtherRevocationInfoFormat_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherRevocationInfoFormat, otherRevInfoFormat),
+		.field_name = "otherRevInfoFormat",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherRevocationInfoFormat, otherRevInfo),
+		.field_name = "otherRevInfo",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+static const ASN1_ITEM CMS_OtherRevocationInfoFormat_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OtherRevocationInfoFormat_seq_tt,
+	.tcount = sizeof(CMS_OtherRevocationInfoFormat_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OtherRevocationInfoFormat),
+	.sname = "CMS_OtherRevocationInfoFormat",
+};
+
+static const ASN1_TEMPLATE CMS_RevocationInfoChoice_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_RevocationInfoChoice, d.crl),
+		.field_name = "d.crl",
+		.item = &X509_CRL_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(CMS_RevocationInfoChoice, d.other),
+		.field_name = "d.other",
+		.item = &CMS_OtherRevocationInfoFormat_it,
+	},
+};
+
+const ASN1_ITEM CMS_RevocationInfoChoice_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_RevocationInfoChoice, type),
+	.templates = CMS_RevocationInfoChoice_ch_tt,
+	.tcount = sizeof(CMS_RevocationInfoChoice_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_RevocationInfoChoice),
+	.sname = "CMS_RevocationInfoChoice",
+};
+
+static const ASN1_TEMPLATE CMS_SignedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_SignedData, digestAlgorithms),
+		.field_name = "digestAlgorithms",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SignedData, encapContentInfo),
+		.field_name = "encapContentInfo",
+		.item = &CMS_EncapsulatedContentInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_SignedData, certificates),
+		.field_name = "certificates",
+		.item = &CMS_CertificateChoices_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_SignedData, crls),
+		.field_name = "crls",
+		.item = &CMS_RevocationInfoChoice_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_SignedData, signerInfos),
+		.field_name = "signerInfos",
+		.item = &CMS_SignerInfo_it,
+	},
+};
+
+const ASN1_ITEM CMS_SignedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_SignedData_seq_tt,
+	.tcount = sizeof(CMS_SignedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_SignedData),
+	.sname = "CMS_SignedData",
+};
+
+static const ASN1_TEMPLATE CMS_OriginatorInfo_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_OriginatorInfo, certificates),
+		.field_name = "certificates",
+		.item = &CMS_CertificateChoices_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_OriginatorInfo, crls),
+		.field_name = "crls",
+		.item = &CMS_RevocationInfoChoice_it,
+	},
+};
+
+static const ASN1_ITEM CMS_OriginatorInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OriginatorInfo_seq_tt,
+	.tcount = sizeof(CMS_OriginatorInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OriginatorInfo),
+	.sname = "CMS_OriginatorInfo",
+};
+
+static const ASN1_TEMPLATE CMS_EncryptedContentInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EncryptedContentInfo, contentType),
+		.field_name = "contentType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EncryptedContentInfo, contentEncryptionAlgorithm),
+		.field_name = "contentEncryptionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_EncryptedContentInfo, encryptedContent),
+		.field_name = "encryptedContent",
+		.item = &ASN1_OCTET_STRING_NDEF_it,
+	},
+};
+
+static const ASN1_ITEM CMS_EncryptedContentInfo_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_EncryptedContentInfo_seq_tt,
+	.tcount = sizeof(CMS_EncryptedContentInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_EncryptedContentInfo),
+	.sname = "CMS_EncryptedContentInfo",
+};
+
+static const ASN1_TEMPLATE CMS_KeyTransRecipientInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyTransRecipientInfo, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyTransRecipientInfo, rid),
+		.field_name = "rid",
+		.item = &CMS_SignerIdentifier_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyTransRecipientInfo, keyEncryptionAlgorithm),
+		.field_name = "keyEncryptionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyTransRecipientInfo, encryptedKey),
+		.field_name = "encryptedKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_KeyTransRecipientInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_KeyTransRecipientInfo_seq_tt,
+	.tcount = sizeof(CMS_KeyTransRecipientInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_KeyTransRecipientInfo),
+	.sname = "CMS_KeyTransRecipientInfo",
+};
+
+static const ASN1_TEMPLATE CMS_OtherKeyAttribute_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherKeyAttribute, keyAttrId),
+		.field_name = "keyAttrId",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherKeyAttribute, keyAttr),
+		.field_name = "keyAttr",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+const ASN1_ITEM CMS_OtherKeyAttribute_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OtherKeyAttribute_seq_tt,
+	.tcount = sizeof(CMS_OtherKeyAttribute_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OtherKeyAttribute),
+	.sname = "CMS_OtherKeyAttribute",
+};
+
+static const ASN1_TEMPLATE CMS_RecipientKeyIdentifier_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientKeyIdentifier, subjectKeyIdentifier),
+		.field_name = "subjectKeyIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientKeyIdentifier, date),
+		.field_name = "date",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientKeyIdentifier, other),
+		.field_name = "other",
+		.item = &CMS_OtherKeyAttribute_it,
+	},
+};
+
+const ASN1_ITEM CMS_RecipientKeyIdentifier_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_RecipientKeyIdentifier_seq_tt,
+	.tcount = sizeof(CMS_RecipientKeyIdentifier_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_RecipientKeyIdentifier),
+	.sname = "CMS_RecipientKeyIdentifier",
+};
+
+static const ASN1_TEMPLATE CMS_KeyAgreeRecipientIdentifier_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientIdentifier, d.issuerAndSerialNumber),
+		.field_name = "d.issuerAndSerialNumber",
+		.item = &CMS_IssuerAndSerialNumber_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientIdentifier, d.rKeyId),
+		.field_name = "d.rKeyId",
+		.item = &CMS_RecipientKeyIdentifier_it,
+	},
+};
+
+static const ASN1_ITEM CMS_KeyAgreeRecipientIdentifier_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_KeyAgreeRecipientIdentifier, type),
+	.templates = CMS_KeyAgreeRecipientIdentifier_ch_tt,
+	.tcount = sizeof(CMS_KeyAgreeRecipientIdentifier_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_KeyAgreeRecipientIdentifier),
+	.sname = "CMS_KeyAgreeRecipientIdentifier",
+};
+
+static int
+cms_rek_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	CMS_RecipientEncryptedKey *rek = (CMS_RecipientEncryptedKey *)*pval;
+	if (operation == ASN1_OP_FREE_POST) {
+		EVP_PKEY_free(rek->pkey);
+	}
+	return 1;
+}
+
+static const ASN1_AUX CMS_RecipientEncryptedKey_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = cms_rek_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE CMS_RecipientEncryptedKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientEncryptedKey, rid),
+		.field_name = "rid",
+		.item = &CMS_KeyAgreeRecipientIdentifier_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientEncryptedKey, encryptedKey),
+		.field_name = "encryptedKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_RecipientEncryptedKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_RecipientEncryptedKey_seq_tt,
+	.tcount = sizeof(CMS_RecipientEncryptedKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &CMS_RecipientEncryptedKey_aux,
+	.size = sizeof(CMS_RecipientEncryptedKey),
+	.sname = "CMS_RecipientEncryptedKey",
+};
+
+static const ASN1_TEMPLATE CMS_OriginatorPublicKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OriginatorPublicKey, algorithm),
+		.field_name = "algorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OriginatorPublicKey, publicKey),
+		.field_name = "publicKey",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_OriginatorPublicKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OriginatorPublicKey_seq_tt,
+	.tcount = sizeof(CMS_OriginatorPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OriginatorPublicKey),
+	.sname = "CMS_OriginatorPublicKey",
+};
+
+static const ASN1_TEMPLATE CMS_OriginatorIdentifierOrKey_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OriginatorIdentifierOrKey, d.issuerAndSerialNumber),
+		.field_name = "d.issuerAndSerialNumber",
+		.item = &CMS_IssuerAndSerialNumber_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_OriginatorIdentifierOrKey, d.subjectKeyIdentifier),
+		.field_name = "d.subjectKeyIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(CMS_OriginatorIdentifierOrKey, d.originatorKey),
+		.field_name = "d.originatorKey",
+		.item = &CMS_OriginatorPublicKey_it,
+	},
+};
+
+static const ASN1_ITEM CMS_OriginatorIdentifierOrKey_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_OriginatorIdentifierOrKey, type),
+	.templates = CMS_OriginatorIdentifierOrKey_ch_tt,
+	.tcount = sizeof(CMS_OriginatorIdentifierOrKey_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OriginatorIdentifierOrKey),
+	.sname = "CMS_OriginatorIdentifierOrKey",
+};
+
+static int
+cms_kari_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	CMS_KeyAgreeRecipientInfo *kari = (CMS_KeyAgreeRecipientInfo *)*pval;
+	if (operation == ASN1_OP_NEW_POST) {
+		kari->ctx = EVP_CIPHER_CTX_new();
+		if (kari->ctx == NULL)
+			return 0;
+		EVP_CIPHER_CTX_set_flags(kari->ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
+		kari->pctx = NULL;
+	} else if (operation == ASN1_OP_FREE_POST) {
+		EVP_PKEY_CTX_free(kari->pctx);
+		EVP_CIPHER_CTX_free(kari->ctx);
+	}
+	return 1;
+}
+
+static const ASN1_AUX CMS_KeyAgreeRecipientInfo_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = cms_kari_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE CMS_KeyAgreeRecipientInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientInfo, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientInfo, originator),
+		.field_name = "originator",
+		.item = &CMS_OriginatorIdentifierOrKey_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_KeyAgreeRecipientInfo, ukm),
+		.field_name = "ukm",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientInfo, keyEncryptionAlgorithm),
+		.field_name = "keyEncryptionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_KeyAgreeRecipientInfo, recipientEncryptedKeys),
+		.field_name = "recipientEncryptedKeys",
+		.item = &CMS_RecipientEncryptedKey_it,
+	},
+};
+
+const ASN1_ITEM CMS_KeyAgreeRecipientInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_KeyAgreeRecipientInfo_seq_tt,
+	.tcount = sizeof(CMS_KeyAgreeRecipientInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &CMS_KeyAgreeRecipientInfo_aux,
+	.size = sizeof(CMS_KeyAgreeRecipientInfo),
+	.sname = "CMS_KeyAgreeRecipientInfo",
+};
+
+static const ASN1_TEMPLATE CMS_KEKIdentifier_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKIdentifier, keyIdentifier),
+		.field_name = "keyIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKIdentifier, date),
+		.field_name = "date",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKIdentifier, other),
+		.field_name = "other",
+		.item = &CMS_OtherKeyAttribute_it,
+	},
+};
+
+static const ASN1_ITEM CMS_KEKIdentifier_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_KEKIdentifier_seq_tt,
+	.tcount = sizeof(CMS_KEKIdentifier_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_KEKIdentifier),
+	.sname = "CMS_KEKIdentifier",
+};
+
+static const ASN1_TEMPLATE CMS_KEKRecipientInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKRecipientInfo, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKRecipientInfo, kekid),
+		.field_name = "kekid",
+		.item = &CMS_KEKIdentifier_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKRecipientInfo, keyEncryptionAlgorithm),
+		.field_name = "keyEncryptionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_KEKRecipientInfo, encryptedKey),
+		.field_name = "encryptedKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_KEKRecipientInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_KEKRecipientInfo_seq_tt,
+	.tcount = sizeof(CMS_KEKRecipientInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_KEKRecipientInfo),
+	.sname = "CMS_KEKRecipientInfo",
+};
+
+static const ASN1_TEMPLATE CMS_PasswordRecipientInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_PasswordRecipientInfo, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_PasswordRecipientInfo, keyDerivationAlgorithm),
+		.field_name = "keyDerivationAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_PasswordRecipientInfo, keyEncryptionAlgorithm),
+		.field_name = "keyEncryptionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_PasswordRecipientInfo, encryptedKey),
+		.field_name = "encryptedKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_PasswordRecipientInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_PasswordRecipientInfo_seq_tt,
+	.tcount = sizeof(CMS_PasswordRecipientInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_PasswordRecipientInfo),
+	.sname = "CMS_PasswordRecipientInfo",
+};
+
+static const ASN1_TEMPLATE CMS_OtherRecipientInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherRecipientInfo, oriType),
+		.field_name = "oriType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_OtherRecipientInfo, oriValue),
+		.field_name = "oriValue",
+		.item = &ASN1_ANY_it,
+	},
+};
+
+static const ASN1_ITEM CMS_OtherRecipientInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_OtherRecipientInfo_seq_tt,
+	.tcount = sizeof(CMS_OtherRecipientInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_OtherRecipientInfo),
+	.sname = "CMS_OtherRecipientInfo",
+};
+
+/* Free up RecipientInfo additional data */
+static int
+cms_ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_FREE_PRE) {
+		CMS_RecipientInfo *ri = (CMS_RecipientInfo *)*pval;
+		if (ri->type == CMS_RECIPINFO_TRANS) {
+			CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
+			EVP_PKEY_free(ktri->pkey);
+			X509_free(ktri->recip);
+			EVP_PKEY_CTX_free(ktri->pctx);
+		} else if (ri->type == CMS_RECIPINFO_KEK) {
+			CMS_KEKRecipientInfo *kekri = ri->d.kekri;
+			freezero(kekri->key, kekri->keylen);
+		} else if (ri->type == CMS_RECIPINFO_PASS) {
+			CMS_PasswordRecipientInfo *pwri = ri->d.pwri;
+			freezero(pwri->pass, pwri->passlen);
+		}
+	}
+	return 1;
+}
+
+static const ASN1_AUX CMS_RecipientInfo_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = cms_ri_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE CMS_RecipientInfo_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_RecipientInfo, d.ktri),
+		.field_name = "d.ktri",
+		.item = &CMS_KeyTransRecipientInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(CMS_RecipientInfo, d.kari),
+		.field_name = "d.kari",
+		.item = &CMS_KeyAgreeRecipientInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 2,
+		.offset = offsetof(CMS_RecipientInfo, d.kekri),
+		.field_name = "d.kekri",
+		.item = &CMS_KEKRecipientInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 3,
+		.offset = offsetof(CMS_RecipientInfo, d.pwri),
+		.field_name = "d.pwri",
+		.item = &CMS_PasswordRecipientInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 4,
+		.offset = offsetof(CMS_RecipientInfo, d.ori),
+		.field_name = "d.ori",
+		.item = &CMS_OtherRecipientInfo_it,
+	},
+};
+
+const ASN1_ITEM CMS_RecipientInfo_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_RecipientInfo, type),
+	.templates = CMS_RecipientInfo_ch_tt,
+	.tcount = sizeof(CMS_RecipientInfo_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &CMS_RecipientInfo_aux,
+	.size = sizeof(CMS_RecipientInfo),
+	.sname = "CMS_RecipientInfo",
+};
+
+static const ASN1_TEMPLATE CMS_EnvelopedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EnvelopedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_EnvelopedData, originatorInfo),
+		.field_name = "originatorInfo",
+		.item = &CMS_OriginatorInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_EnvelopedData, recipientInfos),
+		.field_name = "recipientInfos",
+		.item = &CMS_RecipientInfo_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EnvelopedData, encryptedContentInfo),
+		.field_name = "encryptedContentInfo",
+		.item = &CMS_EncryptedContentInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_EnvelopedData, unprotectedAttrs),
+		.field_name = "unprotectedAttrs",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM CMS_EnvelopedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_EnvelopedData_seq_tt,
+	.tcount = sizeof(CMS_EnvelopedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_EnvelopedData),
+	.sname = "CMS_EnvelopedData",
+};
+
+static const ASN1_TEMPLATE CMS_DigestedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_DigestedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_DigestedData, digestAlgorithm),
+		.field_name = "digestAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_DigestedData, encapContentInfo),
+		.field_name = "encapContentInfo",
+		.item = &CMS_EncapsulatedContentInfo_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_DigestedData, digest),
+		.field_name = "digest",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_DigestedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_DigestedData_seq_tt,
+	.tcount = sizeof(CMS_DigestedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_DigestedData),
+	.sname = "CMS_DigestedData",
+};
+
+static const ASN1_TEMPLATE CMS_EncryptedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EncryptedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_EncryptedData, encryptedContentInfo),
+		.field_name = "encryptedContentInfo",
+		.item = &CMS_EncryptedContentInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(CMS_EncryptedData, unprotectedAttrs),
+		.field_name = "unprotectedAttrs",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM CMS_EncryptedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_EncryptedData_seq_tt,
+	.tcount = sizeof(CMS_EncryptedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_EncryptedData),
+	.sname = "CMS_EncryptedData",
+};
+
+static const ASN1_TEMPLATE CMS_AuthenticatedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, originatorInfo),
+		.field_name = "originatorInfo",
+		.item = &CMS_OriginatorInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, recipientInfos),
+		.field_name = "recipientInfos",
+		.item = &CMS_RecipientInfo_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, macAlgorithm),
+		.field_name = "macAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(CMS_AuthenticatedData, digestAlgorithm),
+		.field_name = "digestAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, encapContentInfo),
+		.field_name = "encapContentInfo",
+		.item = &CMS_EncapsulatedContentInfo_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(CMS_AuthenticatedData, authAttrs),
+		.field_name = "authAttrs",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_AuthenticatedData, mac),
+		.field_name = "mac",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 3,
+		.offset = offsetof(CMS_AuthenticatedData, unauthAttrs),
+		.field_name = "unauthAttrs",
+		.item = &X509_ALGOR_it,
+	},
+};
+
+static const ASN1_ITEM CMS_AuthenticatedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_AuthenticatedData_seq_tt,
+	.tcount = sizeof(CMS_AuthenticatedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_AuthenticatedData),
+	.sname = "CMS_AuthenticatedData",
+};
+
+static const ASN1_TEMPLATE CMS_CompressedData_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_CompressedData, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_CompressedData, compressionAlgorithm),
+		.field_name = "compressionAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_CompressedData, encapContentInfo),
+		.field_name = "encapContentInfo",
+		.item = &CMS_EncapsulatedContentInfo_it,
+	},
+};
+
+const ASN1_ITEM CMS_CompressedData_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_CompressedData_seq_tt,
+	.tcount = sizeof(CMS_CompressedData_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_CompressedData),
+	.sname = "CMS_CompressedData",
+};
+
+/* This is the ANY DEFINED BY table for the top level ContentInfo structure */
+
+static const ASN1_TEMPLATE cms_default_tt = {
+	.flags = ASN1_TFLG_EXPLICIT,
+	.tag = 0,
+	.offset = offsetof(CMS_ContentInfo, d.other),
+	.field_name = "d.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE CMS_ContentInfo_adbtbl[] = {
+	{
+		.value = NID_pkcs7_data,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.data),
+			.field_name = "d.data",
+			.item = &ASN1_OCTET_STRING_NDEF_it,
+		},
+	},
+	{
+		.value = NID_pkcs7_signed,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.signedData),
+			.field_name = "d.signedData",
+			.item = &CMS_SignedData_it,
+		},
+	},
+	{
+		.value = NID_pkcs7_enveloped,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.envelopedData),
+			.field_name = "d.envelopedData",
+			.item = &CMS_EnvelopedData_it,
+		},
+	},
+	{
+		.value = NID_pkcs7_digest,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.digestedData),
+			.field_name = "d.digestedData",
+			.item = &CMS_DigestedData_it,
+		},
+	},
+	{
+		.value = NID_pkcs7_encrypted,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.encryptedData),
+			.field_name = "d.encryptedData",
+			.item = &CMS_EncryptedData_it,
+		},
+	},
+	{
+		.value = NID_id_smime_ct_authData,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.authenticatedData),
+			.field_name = "d.authenticatedData",
+			.item = &CMS_AuthenticatedData_it,
+		},
+	},
+	{
+		.value = NID_id_smime_ct_compressedData,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(CMS_ContentInfo, d.compressedData),
+			.field_name = "d.compressedData",
+			.item = &CMS_CompressedData_it,
+		},
+	},
+};
+
+static const ASN1_ADB CMS_ContentInfo_adb = {
+	.flags = 0,
+	.offset = offsetof(CMS_ContentInfo, contentType),
+	.tbl = CMS_ContentInfo_adbtbl,
+	.tblcount = sizeof(CMS_ContentInfo_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &cms_default_tt,
+	.null_tt = NULL,
+};
+
+/* CMS streaming support */
+static int
+cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	ASN1_STREAM_ARG *sarg = exarg;
+	CMS_ContentInfo *cms = NULL;
+
+	if (pval)
+		cms = (CMS_ContentInfo *)*pval;
+	else
+		return 1;
+
+	switch (operation) {
+	case ASN1_OP_STREAM_PRE:
+		if (CMS_stream(&sarg->boundary, cms) <= 0)
+			return 0;
+		/* FALLTHROUGH */
+
+	case ASN1_OP_DETACHED_PRE:
+		sarg->ndef_bio = CMS_dataInit(cms, sarg->out);
+		if (!sarg->ndef_bio)
+			return 0;
+		break;
+
+	case ASN1_OP_STREAM_POST:
+	case ASN1_OP_DETACHED_POST:
+		if (CMS_dataFinal(cms, sarg->ndef_bio) <= 0)
+			return 0;
+		break;
+	}
+
+	return 1;
+}
+
+static const ASN1_AUX CMS_ContentInfo_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = cms_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE CMS_ContentInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_ContentInfo, contentType),
+		.field_name = "contentType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "CMS_ContentInfo",
+		.item = (const ASN1_ITEM *)&CMS_ContentInfo_adb,
+	},
+};
+
+const ASN1_ITEM CMS_ContentInfo_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_ContentInfo_seq_tt,
+	.tcount = sizeof(CMS_ContentInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &CMS_ContentInfo_aux,
+	.size = sizeof(CMS_ContentInfo),
+	.sname = "CMS_ContentInfo",
+};
+
+/* Specials for signed attributes */
+
+/*
+ * When signing attributes we want to reorder them to match the sorted
+ * encoding.
+ */
+
+static const ASN1_TEMPLATE CMS_Attributes_Sign_item_tt = {
+	.flags = ASN1_TFLG_SET_ORDER,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "CMS_ATTRIBUTES",
+	.item = &X509_ATTRIBUTE_it,
+};
+
+const ASN1_ITEM CMS_Attributes_Sign_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &CMS_Attributes_Sign_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "CMS_Attributes_Sign",
+};
+
+/*
+ * When verifying attributes we need to use the received order. So we use
+ * SEQUENCE OF and tag it to SET OF
+ */
+
+static const ASN1_TEMPLATE CMS_Attributes_Verify_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
+	.tag = V_ASN1_SET,
+	.offset = 0,
+	.field_name = "CMS_ATTRIBUTES",
+	.item = &X509_ATTRIBUTE_it,
+};
+
+const ASN1_ITEM CMS_Attributes_Verify_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &CMS_Attributes_Verify_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "CMS_Attributes_Verify",
+};
+
+
+
+static const ASN1_TEMPLATE CMS_ReceiptsFrom_ch_tt[] = {
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(CMS_ReceiptsFrom, d.allOrFirstTier),
+		.field_name = "d.allOrFirstTier",
+		.item = &LONG_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF,
+		.tag = 1,
+		.offset = offsetof(CMS_ReceiptsFrom, d.receiptList),
+		.field_name = "d.receiptList",
+		.item = &GENERAL_NAMES_it,
+	},
+};
+
+static const ASN1_ITEM CMS_ReceiptsFrom_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(CMS_ReceiptsFrom, type),
+	.templates = CMS_ReceiptsFrom_ch_tt,
+	.tcount = sizeof(CMS_ReceiptsFrom_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_ReceiptsFrom),
+	.sname = "CMS_ReceiptsFrom",
+};
+
+static const ASN1_TEMPLATE CMS_ReceiptRequest_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_ReceiptRequest, signedContentIdentifier),
+		.field_name = "signedContentIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_ReceiptRequest, receiptsFrom),
+		.field_name = "receiptsFrom",
+		.item = &CMS_ReceiptsFrom_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(CMS_ReceiptRequest, receiptsTo),
+		.field_name = "receiptsTo",
+		.item = &GENERAL_NAMES_it,
+	},
+};
+
+const ASN1_ITEM CMS_ReceiptRequest_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_ReceiptRequest_seq_tt,
+	.tcount = sizeof(CMS_ReceiptRequest_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_ReceiptRequest),
+	.sname = "CMS_ReceiptRequest",
+};
+
+static const ASN1_TEMPLATE CMS_Receipt_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_Receipt, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_Receipt, contentType),
+		.field_name = "contentType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_Receipt, signedContentIdentifier),
+		.field_name = "signedContentIdentifier",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_Receipt, originatorSignatureValue),
+		.field_name = "originatorSignatureValue",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM CMS_Receipt_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_Receipt_seq_tt,
+	.tcount = sizeof(CMS_Receipt_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_Receipt),
+	.sname = "CMS_Receipt",
+};
+
+/*
+ * Utilities to encode the CMS_SharedInfo structure used during key
+ * derivation.
+ */
+
+typedef struct {
+	X509_ALGOR *keyInfo;
+	ASN1_OCTET_STRING *entityUInfo;
+	ASN1_OCTET_STRING *suppPubInfo;
+} CMS_SharedInfo;
+
+static const ASN1_TEMPLATE CMS_SharedInfo_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(CMS_SharedInfo, keyInfo),
+		.field_name = "keyInfo",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(CMS_SharedInfo, entityUInfo),
+		.field_name = "entityUInfo",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(CMS_SharedInfo, suppPubInfo),
+		.field_name = "suppPubInfo",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+static const ASN1_ITEM CMS_SharedInfo_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = CMS_SharedInfo_seq_tt,
+	.tcount = sizeof(CMS_SharedInfo_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(CMS_SharedInfo),
+	.sname = "CMS_SharedInfo",
+};
+
+int
+CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg,
+    ASN1_OCTET_STRING *ukm, int keylen)
+{
+	union {
+		CMS_SharedInfo *pecsi;
+		ASN1_VALUE *a;
+	} intsi = {
+		NULL
+	};
+
+	ASN1_OCTET_STRING oklen;
+	unsigned char kl[4];
+	CMS_SharedInfo ecsi;
+
+	keylen <<= 3;
+	kl[0] = (keylen >> 24) & 0xff;
+	kl[1] = (keylen >> 16) & 0xff;
+	kl[2] = (keylen >> 8) & 0xff;
+	kl[3] = keylen & 0xff;
+	oklen.length = 4;
+	oklen.data = kl;
+	oklen.type = V_ASN1_OCTET_STRING;
+	oklen.flags = 0;
+	ecsi.keyInfo = kekalg;
+	ecsi.entityUInfo = ukm;
+	ecsi.suppPubInfo = &oklen;
+	intsi.pecsi = &ecsi;
+
+	return ASN1_item_i2d(intsi.a, pder, &CMS_SharedInfo_it);
+}
+LCRYPTO_ALIAS(CMS_SharedInfo_encode);
diff --git a/crypto/cms/cms_att.c b/crypto/cms/cms_att.c
new file mode 100644
index 0000000..62362ad
--- /dev/null
+++ b/crypto/cms/cms_att.c
@@ -0,0 +1,231 @@
+/* $OpenBSD: cms_att.c,v 1.11 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+
+/* CMS SignedData Attribute utilities */
+
+int
+CMS_signed_get_attr_count(const CMS_SignerInfo *si)
+{
+	return X509at_get_attr_count(si->signedAttrs);
+}
+LCRYPTO_ALIAS(CMS_signed_get_attr_count);
+
+int
+CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos)
+{
+	return X509at_get_attr_by_NID(si->signedAttrs, nid, lastpos);
+}
+LCRYPTO_ALIAS(CMS_signed_get_attr_by_NID);
+
+int
+CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509at_get_attr_by_OBJ(si->signedAttrs, obj, lastpos);
+}
+LCRYPTO_ALIAS(CMS_signed_get_attr_by_OBJ);
+
+X509_ATTRIBUTE *
+CMS_signed_get_attr(const CMS_SignerInfo *si, int loc)
+{
+	return X509at_get_attr(si->signedAttrs, loc);
+}
+LCRYPTO_ALIAS(CMS_signed_get_attr);
+
+X509_ATTRIBUTE *
+CMS_signed_delete_attr(CMS_SignerInfo *si, int loc)
+{
+	return X509at_delete_attr(si->signedAttrs, loc);
+}
+LCRYPTO_ALIAS(CMS_signed_delete_attr);
+
+int
+CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
+{
+	if (X509at_add1_attr(&si->signedAttrs, attr))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_signed_add1_attr);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_signed_add1_attr_by_OBJ);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_signed_add1_attr_by_NID);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_signed_add1_attr_by_txt);
+
+void *
+CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid,
+    int lastpos, int type)
+{
+	return X509at_get0_data_by_OBJ(si->signedAttrs, oid, lastpos, type);
+}
+LCRYPTO_ALIAS(CMS_signed_get0_data_by_OBJ);
+
+int
+CMS_unsigned_get_attr_count(const CMS_SignerInfo *si)
+{
+	return X509at_get_attr_count(si->unsignedAttrs);
+}
+LCRYPTO_ALIAS(CMS_unsigned_get_attr_count);
+
+int
+CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos)
+{
+	return X509at_get_attr_by_NID(si->unsignedAttrs, nid, lastpos);
+}
+LCRYPTO_ALIAS(CMS_unsigned_get_attr_by_NID);
+
+int
+CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509at_get_attr_by_OBJ(si->unsignedAttrs, obj, lastpos);
+}
+LCRYPTO_ALIAS(CMS_unsigned_get_attr_by_OBJ);
+
+X509_ATTRIBUTE *
+CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc)
+{
+	return X509at_get_attr(si->unsignedAttrs, loc);
+}
+LCRYPTO_ALIAS(CMS_unsigned_get_attr);
+
+X509_ATTRIBUTE *
+CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc)
+{
+	return X509at_delete_attr(si->unsignedAttrs, loc);
+}
+LCRYPTO_ALIAS(CMS_unsigned_delete_attr);
+
+int
+CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr)
+{
+	if (X509at_add1_attr(&si->unsignedAttrs, attr))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_unsigned_add1_attr);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_unsigned_add1_attr_by_OBJ);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_unsigned_add1_attr_by_NID);
+
+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))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_unsigned_add1_attr_by_txt);
+
+void *
+CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, int lastpos,
+    int type)
+{
+	return X509at_get0_data_by_OBJ(si->unsignedAttrs, oid, lastpos, type);
+}
+LCRYPTO_ALIAS(CMS_unsigned_get0_data_by_OBJ);
+
+/* Specific attribute cases */
diff --git a/crypto/cms/cms_dd.c b/crypto/cms/cms_dd.c
new file mode 100644
index 0000000..a08fccc
--- /dev/null
+++ b/crypto/cms/cms_dd.c
@@ -0,0 +1,150 @@
+/* $OpenBSD: cms_dd.c,v 1.15 2022/11/26 16:08:51 tb Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+
+/* CMS DigestedData Utilities */
+
+CMS_ContentInfo *
+cms_DigestedData_create(const EVP_MD *md)
+{
+	CMS_ContentInfo *cms;
+	CMS_DigestedData *dd;
+
+	cms = CMS_ContentInfo_new();
+	if (cms == NULL)
+		return NULL;
+
+	dd = (CMS_DigestedData *)ASN1_item_new(&CMS_DigestedData_it);
+
+	if (dd == NULL)
+		goto err;
+
+	cms->contentType = OBJ_nid2obj(NID_pkcs7_digest);
+	cms->d.digestedData = dd;
+
+	dd->version = 0;
+	dd->encapContentInfo->eContentType = OBJ_nid2obj(NID_pkcs7_data);
+
+	X509_ALGOR_set_md(dd->digestAlgorithm, md);
+
+	return cms;
+
+ err:
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+
+BIO *
+cms_DigestedData_init_bio(CMS_ContentInfo *cms)
+{
+	CMS_DigestedData *dd;
+
+	dd = cms->d.digestedData;
+
+	return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm);
+}
+
+int
+cms_DigestedData_do_final(CMS_ContentInfo *cms, BIO *chain, int verify)
+{
+	EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+	unsigned char md[EVP_MAX_MD_SIZE];
+	unsigned int mdlen;
+	int r = 0;
+	CMS_DigestedData *dd;
+
+	if (mctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	dd = cms->d.digestedData;
+
+	if (!cms_DigestAlgorithm_find_ctx(mctx, chain, dd->digestAlgorithm))
+		goto err;
+
+	if (EVP_DigestFinal_ex(mctx, md, &mdlen) <= 0)
+		goto err;
+
+	if (verify) {
+		if (mdlen != (unsigned int)dd->digest->length) {
+			CMSerror(CMS_R_MESSAGEDIGEST_WRONG_LENGTH);
+			goto err;
+		}
+
+		if (memcmp(md, dd->digest->data, mdlen))
+			CMSerror(CMS_R_VERIFICATION_FAILURE);
+		else
+			r = 1;
+	} else {
+		if (!ASN1_STRING_set(dd->digest, md, mdlen))
+			goto err;
+		r = 1;
+	}
+
+ err:
+	EVP_MD_CTX_free(mctx);
+
+	return r;
+}
diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c
new file mode 100644
index 0000000..547f9ff
--- /dev/null
+++ b/crypto/cms/cms_enc.c
@@ -0,0 +1,263 @@
+/* $OpenBSD: cms_enc.c,v 1.23 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+
+/* CMS EncryptedData Utilities */
+
+/* Return BIO based on EncryptedContentInfo and key */
+
+BIO *
+cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
+{
+	BIO *b;
+	EVP_CIPHER_CTX *ctx;
+	const EVP_CIPHER *ciph;
+	X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
+	unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
+	unsigned char *tkey = NULL;
+	size_t tkeylen = 0;
+
+	int ok = 0;
+
+	int enc, keep_key = 0;
+
+	enc = ec->cipher ? 1 : 0;
+
+	b = BIO_new(BIO_f_cipher());
+	if (b == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	BIO_get_cipher_ctx(b, &ctx);
+
+	if (enc) {
+		ciph = ec->cipher;
+		/*
+		 * If not keeping key set cipher to NULL so subsequent calls decrypt.
+		 */
+		if (ec->key)
+			ec->cipher = NULL;
+	} else {
+		ciph = EVP_get_cipherbyobj(calg->algorithm);
+
+		if (!ciph) {
+			CMSerror(CMS_R_UNKNOWN_CIPHER);
+			goto err;
+		}
+	}
+
+	if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
+		CMSerror(CMS_R_CIPHER_INITIALISATION_ERROR);
+		goto err;
+	}
+
+	if (enc) {
+		int ivlen;
+		calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
+		/* Generate a random IV if we need one */
+		ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+		if (ivlen > 0) {
+			arc4random_buf(iv, ivlen);
+			piv = iv;
+		}
+	} else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0) {
+		CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+		goto err;
+	}
+	tkeylen = EVP_CIPHER_CTX_key_length(ctx);
+	/* Generate random session key */
+	if (!enc || !ec->key) {
+		tkey = malloc(tkeylen);
+		if (tkey == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
+			goto err;
+	}
+
+	if (!ec->key) {
+		ec->key = tkey;
+		ec->keylen = tkeylen;
+		tkey = NULL;
+		if (enc)
+			keep_key = 1;
+		else
+			ERR_clear_error();
+
+	}
+
+	if (ec->keylen != tkeylen) {
+		/* If necessary set key length */
+		if (!EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen)) {
+			/*
+			 * Only reveal failure if debugging so we don't leak information
+			 * which may be useful in MMA.
+			 */
+			if (enc || ec->debug) {
+			    CMSerror(CMS_R_INVALID_KEY_LENGTH);
+			    goto err;
+			} else {
+			    /* Use random key */
+			    freezero(ec->key, ec->keylen);
+			    ec->key = tkey;
+			    ec->keylen = tkeylen;
+			    tkey = NULL;
+			    ERR_clear_error();
+			}
+		}
+	}
+
+	if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0) {
+		CMSerror(CMS_R_CIPHER_INITIALISATION_ERROR);
+		goto err;
+	}
+	if (enc) {
+		calg->parameter = ASN1_TYPE_new();
+		if (calg->parameter == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0) {
+			CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+			goto err;
+		}
+		/* If parameter type not set omit parameter */
+		if (calg->parameter->type == V_ASN1_UNDEF) {
+			ASN1_TYPE_free(calg->parameter);
+			calg->parameter = NULL;
+		}
+	}
+	ok = 1;
+
+ err:
+	if (!keep_key || !ok) {
+		freezero(ec->key, ec->keylen);
+		ec->key = NULL;
+	}
+	freezero(tkey, tkeylen);
+	if (ok)
+		return b;
+	BIO_free(b);
+	return NULL;
+}
+
+int
+cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
+    const EVP_CIPHER *cipher, const unsigned char *key, size_t keylen)
+{
+	ec->cipher = cipher;
+	if (key) {
+		if ((ec->key = malloc(keylen)) == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(ec->key, key, keylen);
+	}
+	ec->keylen = keylen;
+	if (cipher)
+		ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
+
+	return 1;
+}
+
+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) {
+		CMSerror(CMS_R_NO_KEY);
+		return 0;
+	}
+	if (ciph) {
+		cms->d.encryptedData = (CMS_EncryptedData *)ASN1_item_new(&CMS_EncryptedData_it);
+		if (!cms->d.encryptedData) {
+			CMSerror(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) {
+		CMSerror(CMS_R_NOT_ENCRYPTED_DATA);
+		return 0;
+	}
+	ec = cms->d.encryptedData->encryptedContentInfo;
+
+	return cms_EncryptedContent_init(ec, ciph, key, keylen);
+}
+LCRYPTO_ALIAS(CMS_EncryptedData_set1_key);
+
+BIO *
+cms_EncryptedData_init_bio(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);
+}
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
new file mode 100644
index 0000000..7bb8f61
--- /dev/null
+++ b/crypto/cms/cms_env.c
@@ -0,0 +1,994 @@
+/* $OpenBSD: cms_env.c,v 1.26 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+#include "asn1/asn1_local.h"
+#include "evp/evp_local.h"
+
+/* CMS EnvelopedData Utilities */
+
+CMS_EnvelopedData *
+cms_get0_enveloped(CMS_ContentInfo *cms)
+{
+	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
+		CMSerror(CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA);
+		return NULL;
+	}
+	return cms->d.envelopedData;
+}
+
+static CMS_EnvelopedData *
+cms_enveloped_data_init(CMS_ContentInfo *cms)
+{
+	if (cms->d.other == NULL) {
+		cms->d.envelopedData = (CMS_EnvelopedData *)ASN1_item_new(&CMS_EnvelopedData_it);
+		if (!cms->d.envelopedData) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+		cms->d.envelopedData->version = 0;
+		cms->d.envelopedData->encryptedContentInfo->contentType =
+			OBJ_nid2obj(NID_pkcs7_data);
+		ASN1_OBJECT_free(cms->contentType);
+		cms->contentType = OBJ_nid2obj(NID_pkcs7_enveloped);
+		return cms->d.envelopedData;
+	}
+	return cms_get0_enveloped(cms);
+}
+
+int
+cms_env_asn1_ctrl(CMS_RecipientInfo *ri, int cmd)
+{
+	EVP_PKEY *pkey;
+	int i;
+
+	if (ri->type == CMS_RECIPINFO_TRANS)
+		pkey = ri->d.ktri->pkey;
+	else if (ri->type == CMS_RECIPINFO_AGREE) {
+		EVP_PKEY_CTX *pctx = ri->d.kari->pctx;
+		if (!pctx)
+			return 0;
+		pkey = EVP_PKEY_CTX_get0_pkey(pctx);
+		if (!pkey)
+			return 0;
+	} else
+		return 0;
+	if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+		return 1;
+	i = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_ENVELOPE, cmd, ri);
+	if (i == -2) {
+		CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+		return 0;
+	}
+	if (i <= 0) {
+		CMSerror(CMS_R_CTRL_FAILURE);
+		return 0;
+	}
+
+	return 1;
+}
+
+STACK_OF(CMS_RecipientInfo) *
+CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
+{
+	CMS_EnvelopedData *env;
+
+	env = cms_get0_enveloped(cms);
+	if (!env)
+		return NULL;
+
+	return env->recipientInfos;
+}
+LCRYPTO_ALIAS(CMS_get0_RecipientInfos);
+
+int
+CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
+{
+	return ri->type;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_type);
+
+EVP_PKEY_CTX *
+CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
+{
+	if (ri->type == CMS_RECIPINFO_TRANS)
+		return ri->d.ktri->pctx;
+	else if (ri->type == CMS_RECIPINFO_AGREE)
+		return ri->d.kari->pctx;
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_get0_pkey_ctx);
+
+CMS_ContentInfo *
+CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
+{
+	CMS_ContentInfo *cms;
+	CMS_EnvelopedData *env;
+
+	cms = CMS_ContentInfo_new();
+	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))
+		goto merr;
+
+	return cms;
+
+ merr:
+	CMS_ContentInfo_free(cms);
+	CMSerror(ERR_R_MALLOC_FAILURE);
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_EnvelopedData_create);
+
+/* 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)
+{
+	CMS_KeyTransRecipientInfo *ktri;
+	int idtype;
+
+	ri->d.ktri = (CMS_KeyTransRecipientInfo *)ASN1_item_new(&CMS_KeyTransRecipientInfo_it);
+	if (!ri->d.ktri)
+		return 0;
+	ri->type = CMS_RECIPINFO_TRANS;
+
+	ktri = ri->d.ktri;
+
+	if (flags & CMS_USE_KEYID) {
+		ktri->version = 2;
+		idtype = CMS_RECIPINFO_KEYIDENTIFIER;
+	} else {
+		ktri->version = 0;
+		idtype = CMS_RECIPINFO_ISSUER_SERIAL;
+	}
+
+	/*
+	 * Not a typo: RecipientIdentifier and SignerIdentifier are the same
+	 * structure.
+	 */
+
+	if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype))
+		return 0;
+
+	X509_up_ref(recip);
+	EVP_PKEY_up_ref(pk);
+
+	ktri->pkey = pk;
+	ktri->recip = recip;
+
+	if (flags & CMS_KEY_PARAM) {
+		ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+		if (ktri->pctx == NULL)
+			return 0;
+		if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
+			return 0;
+	} else if (!cms_env_asn1_ctrl(ri, 0))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * 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 *ri = NULL;
+	CMS_EnvelopedData *env;
+	EVP_PKEY *pk = NULL;
+
+	env = cms_get0_enveloped(cms);
+	if (!env)
+		goto err;
+
+	/* Initialize recipient info */
+	ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it);
+	if (!ri)
+		goto merr;
+
+	pk = X509_get0_pubkey(recip);
+	if (!pk) {
+		CMSerror(CMS_R_ERROR_GETTING_PUBLIC_KEY);
+		goto err;
+	}
+
+	switch (cms_pkey_get_ri_type(pk)) {
+
+	case CMS_RECIPINFO_TRANS:
+		if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags))
+			goto err;
+		break;
+
+	case CMS_RECIPINFO_AGREE:
+		if (!cms_RecipientInfo_kari_init(ri, recip, pk, flags))
+			goto err;
+		break;
+
+	default:
+		CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+		goto err;
+
+	}
+
+	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+		goto merr;
+
+	return ri;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+ err:
+	ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it);
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_add1_recipient_cert);
+
+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) {
+		CMSerror(CMS_R_NOT_KEY_TRANSPORT);
+		return 0;
+	}
+
+	ktri = ri->d.ktri;
+
+	if (pk)
+		*pk = ktri->pkey;
+	if (recip)
+		*recip = ktri->recip;
+	if (palg)
+		*palg = ktri->keyEncryptionAlgorithm;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_get0_algs);
+
+int
+CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri,
+    ASN1_OCTET_STRING **keyid, X509_NAME **issuer, ASN1_INTEGER **sno)
+{
+	CMS_KeyTransRecipientInfo *ktri;
+
+	if (ri->type != CMS_RECIPINFO_TRANS) {
+		CMSerror(CMS_R_NOT_KEY_TRANSPORT);
+		return 0;
+	}
+	ktri = ri->d.ktri;
+
+	return cms_SignerIdentifier_get0_signer_id(ktri->rid, keyid, issuer, sno);
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_get0_signer_id);
+
+int
+CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert)
+{
+	if (ri->type != CMS_RECIPINFO_TRANS) {
+		CMSerror(CMS_R_NOT_KEY_TRANSPORT);
+		return -2;
+	}
+
+	return cms_SignerIdentifier_cert_cmp(ri->d.ktri->rid, cert);
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_ktri_cert_cmp);
+
+int
+CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey)
+{
+	if (ri->type != CMS_RECIPINFO_TRANS) {
+		CMSerror(CMS_R_NOT_KEY_TRANSPORT);
+		return 0;
+	}
+	EVP_PKEY_free(ri->d.ktri->pkey);
+	ri->d.ktri->pkey = pkey;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_set0_pkey);
+
+/* Encrypt content key in key transport recipient info */
+
+static int
+cms_RecipientInfo_ktri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	CMS_KeyTransRecipientInfo *ktri;
+	CMS_EncryptedContentInfo *ec;
+	EVP_PKEY_CTX *pctx;
+	unsigned char *ek = NULL;
+	size_t eklen;
+
+	int ret = 0;
+
+	if (ri->type != CMS_RECIPINFO_TRANS) {
+		CMSerror(CMS_R_NOT_KEY_TRANSPORT);
+		return 0;
+	}
+	ktri = ri->d.ktri;
+	ec = cms->d.envelopedData->encryptedContentInfo;
+
+	pctx = ktri->pctx;
+
+	if (pctx) {
+		if (!cms_env_asn1_ctrl(ri, 0))
+			goto err;
+	} else {
+		pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
+		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_CMS_ENCRYPT, 0, ri) <= 0) {
+		CMSerror(CMS_R_CTRL_ERROR);
+		goto err;
+	}
+
+	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, ec->key, ec->keylen) <= 0)
+		goto err;
+
+	ek = malloc(eklen);
+
+	if (ek == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_PKEY_encrypt(pctx, ek, &eklen, ec->key, ec->keylen) <= 0)
+		goto err;
+
+	ASN1_STRING_set0(ktri->encryptedKey, ek, eklen);
+	ek = NULL;
+
+	ret = 1;
+
+ err:
+	EVP_PKEY_CTX_free(pctx);
+	ktri->pctx = NULL;
+	free(ek);
+
+	return ret;
+}
+
+/* Decrypt content key from KTRI */
+
+static int
+cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	CMS_KeyTransRecipientInfo *ktri = ri->d.ktri;
+	EVP_PKEY *pkey = ktri->pkey;
+	unsigned char *ek = NULL;
+	size_t eklen;
+	size_t fixlen = 0;
+	int ret = 0;
+	CMS_EncryptedContentInfo *ec;
+
+	ec = cms->d.envelopedData->encryptedContentInfo;
+
+	if (ktri->pkey == NULL) {
+		CMSerror(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;
+
+		if ((ciph = EVP_get_cipherbyobj(calg->algorithm)) == NULL) {
+			CMSerror(CMS_R_UNKNOWN_CIPHER);
+			return 0;
+		}
+
+		fixlen = EVP_CIPHER_key_length(ciph);
+	}
+
+	ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
+	if (ktri->pctx == NULL)
+		return 0;
+
+	if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
+		goto err;
+
+	if (!cms_env_asn1_ctrl(ri, 1))
+		goto err;
+
+	if (EVP_PKEY_CTX_ctrl(ktri->pctx, -1, EVP_PKEY_OP_DECRYPT,
+	    EVP_PKEY_CTRL_CMS_DECRYPT, 0, ri) <= 0) {
+		CMSerror(CMS_R_CTRL_ERROR);
+		goto err;
+	}
+
+	if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen, ktri->encryptedKey->data,
+	    ktri->encryptedKey->length) <= 0 || eklen == 0 ||
+	    (fixlen != 0 && eklen != fixlen)) {
+		CMSerror(CMS_R_CMS_LIB);
+		goto err;
+	}
+
+	ek = malloc(eklen);
+
+	if (ek == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen, ktri->encryptedKey->data,
+	    ktri->encryptedKey->length) <= 0) {
+		CMSerror(CMS_R_CMS_LIB);
+		goto err;
+	}
+
+	ret = 1;
+
+	freezero(ec->key, ec->keylen);
+	ec->key = ek;
+	ec->keylen = eklen;
+
+ err:
+	EVP_PKEY_CTX_free(ktri->pctx);
+	ktri->pctx = NULL;
+	if (!ret)
+		free(ek);
+
+	return ret;
+}
+
+/* Key Encrypted Key (KEK) RecipientInfo routines */
+
+int
+CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, const unsigned char *id,
+    size_t idlen)
+{
+	ASN1_OCTET_STRING tmp_os;
+	CMS_KEKRecipientInfo *kekri;
+
+	if (ri->type != CMS_RECIPINFO_KEK) {
+		CMSerror(CMS_R_NOT_KEK);
+		return -2;
+	}
+	kekri = ri->d.kekri;
+	tmp_os.type = V_ASN1_OCTET_STRING;
+	tmp_os.flags = 0;
+	tmp_os.data = (unsigned char *)id;
+	tmp_os.length = (int)idlen;
+
+	return ASN1_OCTET_STRING_cmp(&tmp_os, kekri->kekid->keyIdentifier);
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kekri_id_cmp);
+
+/* For now hard code AES key wrap info */
+
+static size_t
+aes_wrap_keylen(int nid)
+{
+	switch (nid) {
+	case NID_id_aes128_wrap:
+		return 16;
+
+	case NID_id_aes192_wrap:
+		return 24;
+
+	case NID_id_aes256_wrap:
+		return 32;
+
+	default:
+		return 0;
+	}
+}
+
+CMS_RecipientInfo *
+CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, unsigned char *key,
+    size_t keylen, unsigned char *id, size_t idlen, ASN1_GENERALIZEDTIME *date,
+    ASN1_OBJECT *otherTypeId, ASN1_TYPE *otherType)
+{
+	CMS_RecipientInfo *ri = NULL;
+	CMS_EnvelopedData *env;
+	CMS_KEKRecipientInfo *kekri;
+
+	env = cms_get0_enveloped(cms);
+	if (!env)
+		goto err;
+
+	if (nid == NID_undef) {
+		switch (keylen) {
+		case 16:
+			nid = NID_id_aes128_wrap;
+			break;
+
+		case 24:
+			nid = NID_id_aes192_wrap;
+			break;
+
+		case 32:
+			nid = NID_id_aes256_wrap;
+			break;
+
+		default:
+			CMSerror(CMS_R_INVALID_KEY_LENGTH);
+			goto err;
+		}
+
+	} else {
+
+		size_t exp_keylen = aes_wrap_keylen(nid);
+
+		if (!exp_keylen) {
+			CMSerror(CMS_R_UNSUPPORTED_KEK_ALGORITHM);
+			goto err;
+		}
+
+		if (keylen != exp_keylen) {
+			CMSerror(CMS_R_INVALID_KEY_LENGTH);
+			goto err;
+		}
+
+	}
+
+	/* Initialize recipient info */
+	ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it);
+	if (!ri)
+		goto merr;
+
+	ri->d.kekri = (CMS_KEKRecipientInfo *)ASN1_item_new(&CMS_KEKRecipientInfo_it);
+	if (!ri->d.kekri)
+		goto merr;
+	ri->type = CMS_RECIPINFO_KEK;
+
+	kekri = ri->d.kekri;
+
+	if (otherTypeId) {
+		kekri->kekid->other = (CMS_OtherKeyAttribute *)ASN1_item_new(&CMS_OtherKeyAttribute_it);
+		if (kekri->kekid->other == NULL)
+			goto merr;
+	}
+
+	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+		goto merr;
+
+	/* After this point no calls can fail */
+
+	kekri->version = 4;
+
+	kekri->key = key;
+	kekri->keylen = keylen;
+
+	ASN1_STRING_set0(kekri->kekid->keyIdentifier, id, idlen);
+
+	kekri->kekid->date = date;
+
+	if (kekri->kekid->other) {
+		kekri->kekid->other->keyAttrId = otherTypeId;
+		kekri->kekid->other->keyAttr = otherType;
+	}
+
+	X509_ALGOR_set0(kekri->keyEncryptionAlgorithm,
+			        OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
+
+	return ri;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+ err:
+	ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it);
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_add0_recipient_key);
+
+int
+CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg,
+    ASN1_OCTET_STRING **pid, ASN1_GENERALIZEDTIME **pdate,
+    ASN1_OBJECT **potherid, ASN1_TYPE **pothertype)
+{
+	CMS_KEKIdentifier *rkid;
+
+	if (ri->type != CMS_RECIPINFO_KEK) {
+		CMSerror(CMS_R_NOT_KEK);
+		return 0;
+	}
+	rkid = ri->d.kekri->kekid;
+	if (palg)
+		*palg = ri->d.kekri->keyEncryptionAlgorithm;
+	if (pid)
+		*pid = rkid->keyIdentifier;
+	if (pdate)
+		*pdate = rkid->date;
+	if (potherid) {
+		if (rkid->other)
+			*potherid = rkid->other->keyAttrId;
+		else
+			*potherid = NULL;
+	}
+	if (pothertype) {
+		if (rkid->other)
+			*pothertype = rkid->other->keyAttr;
+		else
+			*pothertype = NULL;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kekri_get0_id);
+
+int
+CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, unsigned char *key,
+    size_t keylen)
+{
+	CMS_KEKRecipientInfo *kekri;
+
+	if (ri->type != CMS_RECIPINFO_KEK) {
+		CMSerror(CMS_R_NOT_KEK);
+		return 0;
+	}
+
+	kekri = ri->d.kekri;
+	kekri->key = key;
+	kekri->keylen = keylen;
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_set0_key);
+
+/* Encrypt content key in KEK recipient info */
+
+static int
+cms_RecipientInfo_kekri_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	CMS_EncryptedContentInfo *ec;
+	CMS_KEKRecipientInfo *kekri;
+	AES_KEY actx;
+	unsigned char *wkey = NULL;
+	int wkeylen;
+	int r = 0;
+
+	ec = cms->d.envelopedData->encryptedContentInfo;
+	kekri = ri->d.kekri;
+
+	if (!kekri->key) {
+		CMSerror(CMS_R_NO_KEY);
+		return 0;
+	}
+
+	if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
+		CMSerror(CMS_R_ERROR_SETTING_KEY);
+		goto err;
+	}
+
+	wkey = malloc(ec->keylen + 8);
+	if (wkey == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen);
+	if (wkeylen <= 0) {
+		CMSerror(CMS_R_WRAP_ERROR);
+		goto err;
+	}
+
+	ASN1_STRING_set0(kekri->encryptedKey, wkey, wkeylen);
+
+	r = 1;
+
+ err:
+	if (!r)
+		free(wkey);
+	explicit_bzero(&actx, sizeof(actx));
+
+	return r;
+}
+
+/* Decrypt content key in KEK recipient info */
+
+static int
+cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	CMS_EncryptedContentInfo *ec;
+	CMS_KEKRecipientInfo *kekri;
+	AES_KEY actx;
+	unsigned char *ukey = NULL;
+	int ukeylen;
+	int r = 0, wrap_nid;
+
+	ec = cms->d.envelopedData->encryptedContentInfo;
+	kekri = ri->d.kekri;
+
+	if (!kekri->key) {
+		CMSerror(CMS_R_NO_KEY);
+		return 0;
+	}
+
+	wrap_nid = OBJ_obj2nid(kekri->keyEncryptionAlgorithm->algorithm);
+	if (aes_wrap_keylen(wrap_nid) != kekri->keylen) {
+		CMSerror(CMS_R_INVALID_KEY_LENGTH);
+		return 0;
+	}
+
+	/* If encrypted key length is invalid don't bother */
+
+	if (kekri->encryptedKey->length < 16) {
+		CMSerror(CMS_R_INVALID_ENCRYPTED_KEY_LENGTH);
+		goto err;
+	}
+
+	if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) {
+		CMSerror(CMS_R_ERROR_SETTING_KEY);
+		goto err;
+	}
+
+	ukey = malloc(kekri->encryptedKey->length - 8);
+	if (ukey == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	ukeylen = AES_unwrap_key(&actx, NULL, ukey, kekri->encryptedKey->data,
+	    kekri->encryptedKey->length);
+
+	if (ukeylen <= 0) {
+		CMSerror(CMS_R_UNWRAP_ERROR);
+		goto err;
+	}
+
+	freezero(ec->key, ec->keylen);
+	ec->key = ukey;
+	ec->keylen = ukeylen;
+
+	r = 1;
+
+ err:
+
+	if (!r)
+		free(ukey);
+	explicit_bzero(&actx, sizeof(actx));
+
+	return r;
+}
+
+int
+CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	switch (ri->type) {
+	case CMS_RECIPINFO_TRANS:
+		return cms_RecipientInfo_ktri_decrypt(cms, ri);
+
+	case CMS_RECIPINFO_KEK:
+		return cms_RecipientInfo_kekri_decrypt(cms, ri);
+
+	case CMS_RECIPINFO_PASS:
+		return cms_RecipientInfo_pwri_crypt(cms, ri, 0);
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE);
+		return 0;
+	}
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_decrypt);
+
+int
+CMS_RecipientInfo_encrypt(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);
+
+	case CMS_RECIPINFO_KEK:
+		return cms_RecipientInfo_kekri_encrypt(cms, ri);
+
+	case CMS_RECIPINFO_PASS:
+		return cms_RecipientInfo_pwri_crypt(cms, ri, 1);
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_RECIPIENT_TYPE);
+		return 0;
+	}
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_encrypt);
+
+/* Check structures and fixup version numbers (if necessary) */
+
+static void
+cms_env_set_originfo_version(CMS_EnvelopedData *env)
+{
+	CMS_OriginatorInfo *org = env->originatorInfo;
+	int i;
+
+	if (org == NULL)
+		return;
+	for (i = 0; i < sk_CMS_CertificateChoices_num(org->certificates); i++) {
+		CMS_CertificateChoices *cch;
+
+		cch = sk_CMS_CertificateChoices_value(org->certificates, i);
+		if (cch->type == CMS_CERTCHOICE_OTHER) {
+			env->version = 4;
+			return;
+		} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
+			if (env->version < 3)
+			    env->version = 3;
+		}
+	}
+
+	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(org->crls); i++) {
+		CMS_RevocationInfoChoice *rch;
+
+		rch = sk_CMS_RevocationInfoChoice_value(org->crls, i);
+		if (rch->type == CMS_REVCHOICE_OTHER) {
+			env->version = 4;
+			return;
+		}
+	}
+}
+
+static void
+cms_env_set_version(CMS_EnvelopedData *env)
+{
+	int i;
+	CMS_RecipientInfo *ri;
+
+	/*
+	 * Can't set version higher than 4 so if 4 or more already nothing to do.
+	 */
+	if (env->version >= 4)
+		return;
+
+	cms_env_set_originfo_version(env);
+
+	if (env->version >= 3)
+		return;
+
+	for (i = 0; i < sk_CMS_RecipientInfo_num(env->recipientInfos); i++) {
+		ri = sk_CMS_RecipientInfo_value(env->recipientInfos, i);
+		if (ri->type == CMS_RECIPINFO_PASS || ri->type == CMS_RECIPINFO_OTHER) {
+			env->version = 3;
+			return;
+		} else if (ri->type != CMS_RECIPINFO_TRANS
+			       || ri->d.ktri->version != 0) {
+			env->version = 2;
+		}
+	}
+	if (env->originatorInfo || env->unprotectedAttrs)
+		env->version = 2;
+	if (env->version == 2)
+		return;
+	env->version = 0;
+}
+
+BIO *
+cms_EnvelopedData_init_bio(CMS_ContentInfo *cms)
+{
+	CMS_EncryptedContentInfo *ec;
+	STACK_OF(CMS_RecipientInfo) *rinfos;
+	CMS_RecipientInfo *ri;
+	int i, ok = 0;
+	BIO *ret;
+
+	/* 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 */
+
+	if (!ret || !ec->cipher)
+		return ret;
+
+	/* Now encrypt content key according to each RecipientInfo type */
+
+	rinfos = cms->d.envelopedData->recipientInfos;
+
+	for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
+		ri = sk_CMS_RecipientInfo_value(rinfos, i);
+		if (CMS_RecipientInfo_encrypt(cms, ri) <= 0) {
+			CMSerror(CMS_R_ERROR_SETTING_RECIPIENTINFO);
+			goto err;
+		}
+	}
+	cms_env_set_version(cms->d.envelopedData);
+
+	ok = 1;
+
+ err:
+	ec->cipher = NULL;
+	freezero(ec->key, ec->keylen);
+	ec->key = NULL;
+	ec->keylen = 0;
+	if (ok)
+		return ret;
+	BIO_free(ret);
+	return NULL;
+}
+
+/*
+ * Get RecipientInfo type (if any) supported by a key (public or private). To
+ * 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)
+{
+	if (pk->ameth && pk->ameth->pkey_ctrl) {
+		int i, r;
+		i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_RI_TYPE, 0, &r);
+		if (i > 0)
+			return r;
+	}
+	return CMS_RECIPINFO_TRANS;
+}
diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c
new file mode 100644
index 0000000..5758a26
--- /dev/null
+++ b/crypto/cms/cms_err.c
@@ -0,0 +1,164 @@
+/* $OpenBSD: cms_err.c,v 1.14 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * 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 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CMS,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CMS,0,reason)
+
+static ERR_STRING_DATA CMS_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static 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_CERTIFICATE_ALREADY_PRESENT),
+	"certificate already present"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_HAS_NO_KEYID),
+	"certificate has no keyid"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CERTIFICATE_VERIFY_ERROR),
+	"certificate verify error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_INITIALISATION_ERROR),
+	"cipher initialisation error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR),
+	"cipher parameter initialisation error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA),
+	"content type not signed data"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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_DECRYPT_ERROR), "decrypt error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_ERROR_GETTING_PUBLIC_KEY),
+	"error getting public key"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_ENCRYPTED_KEY_LENGTH),
+	"invalid encrypted key length"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER),
+	"invalid key encryption parameter"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_INVALID_KEY_LENGTH), "invalid key length"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MD_BIO_INIT_ERROR), "md bio init error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH),
+	"messagedigest attribute wrong length"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{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"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DEFAULT_DIGEST), "no default digest"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_DIGEST_SET), "no digest set"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_NO_KEY), "no key"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE),
+	"private key does not match certificate"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECEIPT_DECODE_ERROR),
+	"receipt decode error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_RECIPIENT_ERROR), "recipient error"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENCRYPTED_DATA),
+	"type not encrypted data"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_TYPE_NOT_ENVELOPED_DATA),
+	"type not enveloped data"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_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"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_CONTENT_TYPE),
+	"unsupported content type"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEK_ALGORITHM),
+	"unsupported kek algorithm"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM),
+	"unsupported key encryption algorithm"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE),
+	"unsupported recipientinfo type"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_UNSUPPORTED_RECIPIENT_TYPE),
+	"unsupported recipient type"},
+	{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"},
+	{ERR_PACK(ERR_LIB_CMS, 0, CMS_R_WRAP_ERROR), "wrap error"},
+	{0, NULL}
+};
+
+#endif
+
+int
+ERR_load_CMS_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(CMS_str_functs[0].error) == NULL) {
+		ERR_load_strings(ERR_LIB_CMS, CMS_str_functs);
+		ERR_load_strings(ERR_LIB_CMS, CMS_str_reasons);
+	}
+#endif
+	return 1;
+}
+LCRYPTO_ALIAS(ERR_load_CMS_strings);
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
new file mode 100644
index 0000000..b9a4cd8
--- /dev/null
+++ b/crypto/cms/cms_ess.c
@@ -0,0 +1,408 @@
+/* $OpenBSD: cms_ess.c,v 1.23 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+
+
+CMS_ReceiptRequest *
+d2i_CMS_ReceiptRequest(CMS_ReceiptRequest **a, const unsigned char **in, long len)
+{
+	return (CMS_ReceiptRequest *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &CMS_ReceiptRequest_it);
+}
+LCRYPTO_ALIAS(d2i_CMS_ReceiptRequest);
+
+int
+i2d_CMS_ReceiptRequest(CMS_ReceiptRequest *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ReceiptRequest_it);
+}
+LCRYPTO_ALIAS(i2d_CMS_ReceiptRequest);
+
+CMS_ReceiptRequest *
+CMS_ReceiptRequest_new(void)
+{
+	return (CMS_ReceiptRequest *)ASN1_item_new(&CMS_ReceiptRequest_it);
+}
+LCRYPTO_ALIAS(CMS_ReceiptRequest_new);
+
+void
+CMS_ReceiptRequest_free(CMS_ReceiptRequest *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &CMS_ReceiptRequest_it);
+}
+LCRYPTO_ALIAS(CMS_ReceiptRequest_free);
+
+/* ESS services: for now just Signed Receipt related */
+
+int
+CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
+{
+	ASN1_STRING *str;
+	CMS_ReceiptRequest *rr = NULL;
+
+	if (prr)
+		*prr = NULL;
+	str = CMS_signed_get0_data_by_OBJ(si,
+	    OBJ_nid2obj(NID_id_smime_aa_receiptRequest), -3, V_ASN1_SEQUENCE);
+	if (!str)
+		return 0;
+
+	rr = ASN1_item_unpack(str, &CMS_ReceiptRequest_it);
+	if (!rr)
+		return -1;
+	if (prr)
+		*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)
+{
+	CMS_ReceiptRequest *rr = NULL;
+
+	rr = CMS_ReceiptRequest_new();
+	if (rr == NULL)
+		goto merr;
+	if (id)
+		ASN1_STRING_set0(rr->signedContentIdentifier, id, idlen);
+	else {
+		if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
+			goto merr;
+		arc4random_buf(rr->signedContentIdentifier->data, 32);
+	}
+
+	sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
+	rr->receiptsTo = receiptsTo;
+
+	if (receiptList) {
+		rr->receiptsFrom->type = 1;
+		rr->receiptsFrom->d.receiptList = receiptList;
+	} else {
+		rr->receiptsFrom->type = 0;
+		rr->receiptsFrom->d.allOrFirstTier = allorfirst;
+	}
+
+	return rr;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+	CMS_ReceiptRequest_free(rr);
+
+	return NULL;
+}
+
+int
+CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
+{
+	unsigned char *rrder = NULL;
+	int rrderlen, r = 0;
+
+	rrderlen = i2d_CMS_ReceiptRequest(rr, &rrder);
+	if (rrderlen < 0)
+		goto merr;
+
+	if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_receiptRequest,
+	    V_ASN1_SEQUENCE, rrder, rrderlen))
+		goto merr;
+
+	r = 1;
+
+ merr:
+	if (!r)
+		CMSerror(ERR_R_MALLOC_FAILURE);
+
+	free(rrder);
+
+	return r;
+}
+
+void
+CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid,
+    int *pallorfirst, STACK_OF(GENERAL_NAMES) **plist,
+    STACK_OF(GENERAL_NAMES) **prto)
+{
+	if (pcid)
+		*pcid = rr->signedContentIdentifier;
+	if (rr->receiptsFrom->type == 0) {
+		if (pallorfirst)
+			*pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
+		if (plist)
+			*plist = NULL;
+	} else {
+		if (pallorfirst)
+			*pallorfirst = -1;
+		if (plist)
+			*plist = rr->receiptsFrom->d.receiptList;
+	}
+	if (prto)
+		*prto = rr->receiptsTo;
+}
+
+/* Digest a SignerInfo structure for msgSigDigest attribute processing */
+
+static int
+cms_msgSigDigest(CMS_SignerInfo *si, unsigned char *dig, unsigned int *diglen)
+{
+	const EVP_MD *md;
+
+	md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
+	if (md == NULL)
+		return 0;
+	if (!ASN1_item_digest(&CMS_Attributes_Verify_it, md,
+	    si->signedAttrs, dig, diglen))
+		return 0;
+
+	return 1;
+}
+
+/* Add a msgSigDigest attribute to a SignerInfo */
+
+int
+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)) {
+		CMSerror(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)) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Verify signed receipt after it has already passed normal CMS verify */
+
+int
+cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms)
+{
+	int r = 0, i;
+	CMS_ReceiptRequest *rr = NULL;
+	CMS_Receipt *rct = NULL;
+	STACK_OF(CMS_SignerInfo) *sis, *osis;
+	CMS_SignerInfo *si, *osi = NULL;
+	ASN1_OCTET_STRING *msig, **pcont;
+	ASN1_OBJECT *octype;
+	unsigned char dig[EVP_MAX_MD_SIZE];
+	unsigned int diglen;
+
+	/* Get SignerInfos, also checks SignedData content type */
+	osis = CMS_get0_SignerInfos(req_cms);
+	sis = CMS_get0_SignerInfos(cms);
+	if (!osis || !sis)
+		goto err;
+
+	if (sk_CMS_SignerInfo_num(sis) != 1) {
+		CMSerror(CMS_R_NEED_ONE_SIGNER);
+		goto err;
+	}
+
+	/* Check receipt content type */
+	if (OBJ_obj2nid(CMS_get0_eContentType(cms)) != NID_id_smime_ct_receipt) {
+		CMSerror(CMS_R_NOT_A_SIGNED_RECEIPT);
+		goto err;
+	}
+
+	/* Extract and decode receipt content */
+	pcont = CMS_get0_content(cms);
+	if (!pcont || !*pcont) {
+		CMSerror(CMS_R_NO_CONTENT);
+		goto err;
+	}
+
+	rct = ASN1_item_unpack(*pcont, &CMS_Receipt_it);
+
+	if (!rct) {
+		CMSerror(CMS_R_RECEIPT_DECODE_ERROR);
+		goto err;
+	}
+
+	/* Locate original request */
+
+	for (i = 0; i < sk_CMS_SignerInfo_num(osis); i++) {
+		osi = sk_CMS_SignerInfo_value(osis, i);
+		if (!ASN1_STRING_cmp(osi->signature, rct->originatorSignatureValue))
+			break;
+	}
+
+	if (i == sk_CMS_SignerInfo_num(osis)) {
+		CMSerror(CMS_R_NO_MATCHING_SIGNATURE);
+		goto err;
+	}
+
+	si = sk_CMS_SignerInfo_value(sis, 0);
+
+	/* Get msgSigDigest value and compare */
+
+	msig = CMS_signed_get0_data_by_OBJ(si,
+	    OBJ_nid2obj(NID_id_smime_aa_msgSigDigest), -3, V_ASN1_OCTET_STRING);
+
+	if (!msig) {
+		CMSerror(CMS_R_NO_MSGSIGDIGEST);
+		goto err;
+	}
+
+	if (!cms_msgSigDigest(osi, dig, &diglen)) {
+		CMSerror(CMS_R_MSGSIGDIGEST_ERROR);
+		goto err;
+	}
+
+	if (diglen != (unsigned int)msig->length) {
+		CMSerror(CMS_R_MSGSIGDIGEST_WRONG_LENGTH);
+		goto err;
+	}
+
+	if (memcmp(dig, msig->data, diglen)) {
+		CMSerror(CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE);
+		goto err;
+	}
+
+	/* Compare content types */
+
+	octype = CMS_signed_get0_data_by_OBJ(osi,
+	    OBJ_nid2obj(NID_pkcs9_contentType), -3, V_ASN1_OBJECT);
+	if (!octype) {
+		CMSerror(CMS_R_NO_CONTENT_TYPE);
+		goto err;
+	}
+
+	/* Compare details in receipt request */
+
+	if (OBJ_cmp(octype, rct->contentType)) {
+		CMSerror(CMS_R_CONTENT_TYPE_MISMATCH);
+		goto err;
+	}
+
+	/* Get original receipt request details */
+
+	if (CMS_get1_ReceiptRequest(osi, &rr) <= 0) {
+		CMSerror(CMS_R_NO_RECEIPT_REQUEST);
+		goto err;
+	}
+
+	if (ASN1_STRING_cmp(rr->signedContentIdentifier,
+	    rct->signedContentIdentifier)) {
+		CMSerror(CMS_R_CONTENTIDENTIFIER_MISMATCH);
+		goto err;
+	}
+
+	r = 1;
+
+ err:
+	CMS_ReceiptRequest_free(rr);
+	ASN1_item_free((ASN1_VALUE *)rct, &CMS_Receipt_it);
+	return r;
+}
+
+/*
+ * Encode a Receipt into an OCTET STRING read for including into content of a
+ * SignedData ContentInfo.
+ */
+
+ASN1_OCTET_STRING *
+cms_encode_Receipt(CMS_SignerInfo *si)
+{
+	CMS_Receipt rct;
+	CMS_ReceiptRequest *rr = NULL;
+	ASN1_OBJECT *ctype;
+	ASN1_OCTET_STRING *os = NULL;
+
+	/* Get original receipt request */
+
+	/* Get original receipt request details */
+
+	if (CMS_get1_ReceiptRequest(si, &rr) <= 0) {
+		CMSerror(CMS_R_NO_RECEIPT_REQUEST);
+		goto err;
+	}
+
+	/* Get original content type */
+
+	ctype = CMS_signed_get0_data_by_OBJ(si,
+	    OBJ_nid2obj(NID_pkcs9_contentType), -3, V_ASN1_OBJECT);
+	if (!ctype) {
+		CMSerror(CMS_R_NO_CONTENT_TYPE);
+		goto err;
+	}
+
+	rct.version = 1;
+	rct.contentType = ctype;
+	rct.signedContentIdentifier = rr->signedContentIdentifier;
+	rct.originatorSignatureValue = si->signature;
+
+	os = ASN1_item_pack(&rct, &CMS_Receipt_it, NULL);
+
+ err:
+	CMS_ReceiptRequest_free(rr);
+	return os;
+}
diff --git a/crypto/cms/cms_io.c b/crypto/cms/cms_io.c
new file mode 100644
index 0000000..ceb4ce8
--- /dev/null
+++ b/crypto/cms/cms_io.c
@@ -0,0 +1,176 @@
+/* $OpenBSD: cms_io.c,v 1.20 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "cms_local.h"
+
+int
+CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
+{
+	ASN1_OCTET_STRING **pos;
+
+	if ((pos = CMS_get0_content(cms)) == NULL)
+		return 0;
+
+	if (*pos == NULL)
+		*pos = ASN1_OCTET_STRING_new();
+	if (*pos == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	(*pos)->flags |= ASN1_STRING_FLAG_NDEF;
+	(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
+	*boundary = &(*pos)->data;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_stream);
+
+CMS_ContentInfo *
+d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms)
+{
+	return ASN1_item_d2i_bio(&CMS_ContentInfo_it, bp, cms);
+}
+LCRYPTO_ALIAS(d2i_CMS_bio);
+
+int
+i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
+{
+	return ASN1_item_i2d_bio(&CMS_ContentInfo_it, bp, cms);
+}
+LCRYPTO_ALIAS(i2d_CMS_bio);
+
+
+CMS_ContentInfo *
+PEM_read_bio_CMS(BIO *bp, CMS_ContentInfo **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_CMS_ContentInfo,
+	    PEM_STRING_CMS, bp, (void **)x, cb, u);
+}
+
+CMS_ContentInfo *
+PEM_read_CMS(FILE *fp, CMS_ContentInfo **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_CMS_ContentInfo,
+	    PEM_STRING_CMS, fp, (void **)x, cb, u);
+}
+
+int
+PEM_write_bio_CMS(BIO *bp, const CMS_ContentInfo *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_CMS_ContentInfo,
+	    PEM_STRING_CMS, bp, (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+
+int
+PEM_write_CMS(FILE *fp, const CMS_ContentInfo *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_CMS_ContentInfo,
+	    PEM_STRING_CMS, fp, (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+
+BIO *
+BIO_new_CMS(BIO *out, CMS_ContentInfo *cms)
+{
+	return BIO_new_NDEF(out, (ASN1_VALUE *)cms, &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(BIO_new_CMS);
+
+/* CMS wrappers round generalised stream and MIME routines */
+
+int
+i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags)
+{
+	return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)cms, in, flags,
+	    &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(i2d_CMS_bio_stream);
+
+int
+PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags)
+{
+	return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *)cms, in, flags,
+	    "CMS", &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(PEM_write_bio_CMS_stream);
+
+int
+SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags)
+{
+	STACK_OF(X509_ALGOR) *mdalgs = NULL;
+	int ctype_nid = OBJ_obj2nid(cms->contentType);
+	int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms));
+
+	if (ctype_nid == NID_pkcs7_signed)
+		mdalgs = cms->d.signedData->digestAlgorithms;
+
+	return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags, ctype_nid,
+	    econt_nid, mdalgs, &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(SMIME_write_CMS);
+
+CMS_ContentInfo *
+SMIME_read_CMS(BIO *bio, BIO **bcont)
+{
+	return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont,
+	    &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(SMIME_read_CMS);
diff --git a/crypto/cms/cms_kari.c b/crypto/cms/cms_kari.c
new file mode 100644
index 0000000..8ed54e7
--- /dev/null
+++ b/crypto/cms/cms_kari.c
@@ -0,0 +1,492 @@
+/* $OpenBSD: cms_kari.c,v 1.15 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2013 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+#include "asn1/asn1_local.h"
+
+/* Key Agreement Recipient Info (KARI) routines */
+
+int
+CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, X509_ALGOR **palg,
+    ASN1_OCTET_STRING **pukm)
+{
+	if (ri->type != CMS_RECIPINFO_AGREE) {
+		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
+		return 0;
+	}
+	if (palg)
+		*palg = ri->d.kari->keyEncryptionAlgorithm;
+	if (pukm)
+		*pukm = ri->d.kari->ukm;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_alg);
+
+/* Retrieve recipient encrypted keys from a kari */
+
+STACK_OF(CMS_RecipientEncryptedKey) *
+CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri)
+{
+	if (ri->type != CMS_RECIPINFO_AGREE) {
+		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
+		return NULL;
+	}
+	return ri->d.kari->recipientEncryptedKeys;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_reks);
+
+int
+CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, X509_ALGOR **pubalg,
+    ASN1_BIT_STRING **pubkey, ASN1_OCTET_STRING **keyid, X509_NAME **issuer,
+    ASN1_INTEGER **sno)
+{
+	CMS_OriginatorIdentifierOrKey *oik;
+
+	if (ri->type != CMS_RECIPINFO_AGREE) {
+		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
+		return 0;
+	}
+	oik = ri->d.kari->originator;
+	if (issuer)
+		*issuer = NULL;
+	if (sno)
+		*sno = NULL;
+	if (keyid)
+		*keyid = NULL;
+	if (pubalg)
+		*pubalg = NULL;
+	if (pubkey)
+		*pubkey = NULL;
+	if (oik->type == CMS_OIK_ISSUER_SERIAL) {
+		if (issuer)
+			*issuer = oik->d.issuerAndSerialNumber->issuer;
+		if (sno)
+			*sno = oik->d.issuerAndSerialNumber->serialNumber;
+	} else if (oik->type == CMS_OIK_KEYIDENTIFIER) {
+		if (keyid)
+			*keyid = oik->d.subjectKeyIdentifier;
+	} else if (oik->type == CMS_OIK_PUBKEY) {
+		if (pubalg)
+			*pubalg = oik->d.originatorKey->algorithm;
+		if (pubkey)
+			*pubkey = oik->d.originatorKey->publicKey;
+	} else
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_orig_id);
+
+int
+CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
+{
+	CMS_OriginatorIdentifierOrKey *oik;
+
+	if (ri->type != CMS_RECIPINFO_AGREE) {
+		CMSerror(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);
+	else if (oik->type == CMS_OIK_KEYIDENTIFIER)
+		return cms_keyid_cert_cmp(oik->d.subjectKeyIdentifier, cert);
+
+	return -1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_orig_id_cmp);
+
+int
+CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
+    ASN1_OCTET_STRING **keyid, ASN1_GENERALIZEDTIME **tm,
+    CMS_OtherKeyAttribute **other, 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;
+		if (sno)
+			*sno = rid->d.issuerAndSerialNumber->serialNumber;
+		if (keyid)
+			*keyid = NULL;
+		if (tm)
+			*tm = NULL;
+		if (other)
+			*other = NULL;
+	} else if (rid->type == CMS_REK_KEYIDENTIFIER) {
+		if (keyid)
+			*keyid = rid->d.rKeyId->subjectKeyIdentifier;
+		if (tm)
+			*tm = rid->d.rKeyId->date;
+		if (other)
+			*other = rid->d.rKeyId->other;
+		if (issuer)
+			*issuer = NULL;
+		if (sno)
+			*sno = NULL;
+	} else
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientEncryptedKey_get0_id);
+
+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);
+	else if (rid->type == CMS_REK_KEYIDENTIFIER)
+		return cms_keyid_cert_cmp(rid->d.rKeyId->subjectKeyIdentifier, cert);
+	else
+		return -1;
+}
+LCRYPTO_ALIAS(CMS_RecipientEncryptedKey_cert_cmp);
+
+int
+CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk)
+{
+	EVP_PKEY_CTX *pctx;
+	CMS_KeyAgreeRecipientInfo *kari = ri->d.kari;
+
+	EVP_PKEY_CTX_free(kari->pctx);
+	kari->pctx = NULL;
+	if (!pk)
+		return 1;
+	pctx = EVP_PKEY_CTX_new(pk, NULL);
+	if (!pctx || !EVP_PKEY_derive_init(pctx))
+		goto err;
+	kari->pctx = pctx;
+	return 1;
+
+ err:
+	EVP_PKEY_CTX_free(pctx);
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_set0_pkey);
+
+EVP_CIPHER_CTX *
+CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri)
+{
+	if (ri->type == CMS_RECIPINFO_AGREE)
+		return ri->d.kari->ctx;
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_get0_ctx);
+
+/*
+ * Derive KEK and decrypt/encrypt with it to produce either the original CEK
+ * or the encrypted CEK.
+ */
+
+static int
+cms_kek_cipher(unsigned char **pout, size_t *poutlen, const unsigned char *in,
+    size_t inlen, CMS_KeyAgreeRecipientInfo *kari, int enc)
+{
+	/* Key encryption key */
+	unsigned char kek[EVP_MAX_KEY_LENGTH];
+	size_t keklen;
+	int rv = 0;
+	unsigned char *out = NULL;
+	int outlen;
+
+	keklen = EVP_CIPHER_CTX_key_length(kari->ctx);
+	if (keklen > EVP_MAX_KEY_LENGTH)
+		return 0;
+	/* Derive KEK */
+	if (EVP_PKEY_derive(kari->pctx, kek, &keklen) <= 0)
+		goto err;
+	/* Set KEK in context */
+	if (!EVP_CipherInit_ex(kari->ctx, NULL, NULL, kek, NULL, enc))
+		goto err;
+	/* obtain output length of ciphered key */
+	if (!EVP_CipherUpdate(kari->ctx, NULL, &outlen, in, inlen))
+		goto err;
+	out = malloc(outlen);
+	if (out == NULL)
+		goto err;
+	if (!EVP_CipherUpdate(kari->ctx, out, &outlen, in, inlen))
+		goto err;
+	*pout = out;
+	*poutlen = (size_t)outlen;
+	rv = 1;
+
+ err:
+	explicit_bzero(kek, keklen);
+	if (!rv)
+		free(out);
+	EVP_CIPHER_CTX_reset(kari->ctx);
+	/* FIXME: WHY IS kari->pctx freed here?  /RL */
+	EVP_PKEY_CTX_free(kari->pctx);
+	kari->pctx = NULL;
+
+	return rv;
+}
+
+int
+CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+    CMS_RecipientEncryptedKey *rek)
+{
+	int rv = 0;
+	unsigned char *enckey = NULL, *cek = NULL;
+	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))
+		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;
+	freezero(ec->key, ec->keylen);
+	ec->key = cek;
+	ec->keylen = ceklen;
+	cek = NULL;
+	rv = 1;
+
+ err:
+	free(cek);
+
+	return rv;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_kari_decrypt);
+
+/* Create ephemeral key and initialise context based on it */
+static int
+cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *pk)
+{
+	EVP_PKEY_CTX *pctx = NULL;
+	EVP_PKEY *ekey = NULL;
+	int rv = 0;
+
+	pctx = EVP_PKEY_CTX_new(pk, NULL);
+	if (!pctx)
+		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)
+		goto err;
+	if (EVP_PKEY_derive_init(pctx) <= 0)
+		goto err;
+	kari->pctx = pctx;
+	rv = 1;
+
+ err:
+	if (!rv)
+		EVP_PKEY_CTX_free(pctx);
+	EVP_PKEY_free(ekey);
+
+	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)
+{
+	CMS_KeyAgreeRecipientInfo *kari;
+	CMS_RecipientEncryptedKey *rek = NULL;
+
+	ri->d.kari = (CMS_KeyAgreeRecipientInfo *)ASN1_item_new(&CMS_KeyAgreeRecipientInfo_it);
+	if (!ri->d.kari)
+		return 0;
+	ri->type = CMS_RECIPINFO_AGREE;
+
+	kari = ri->d.kari;
+	kari->version = 3;
+
+	rek = (CMS_RecipientEncryptedKey *)ASN1_item_new(&CMS_RecipientEncryptedKey_it);
+	if (rek == NULL)
+		return 0;
+
+	if (!sk_CMS_RecipientEncryptedKey_push(kari->recipientEncryptedKeys, rek)) {
+		ASN1_item_free((ASN1_VALUE *)rek, &CMS_RecipientEncryptedKey_it);
+		return 0;
+	}
+
+	if (flags & CMS_USE_KEYID) {
+		rek->rid->type = CMS_REK_KEYIDENTIFIER;
+		rek->rid->d.rKeyId = (CMS_RecipientKeyIdentifier *)ASN1_item_new(&CMS_RecipientKeyIdentifier_it);
+		if (rek->rid->d.rKeyId == NULL)
+			return 0;
+		if (!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))
+			return 0;
+	}
+
+	/* Create ephemeral key */
+	if (!cms_kari_create_ephemeral_key(kari, pk))
+		return 0;
+
+	EVP_PKEY_up_ref(pk);
+	rek->pkey = pk;
+
+	return 1;
+}
+
+static int
+cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari, const EVP_CIPHER *cipher)
+{
+	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);
+
+	if (kekcipher) {
+		if (EVP_CIPHER_CTX_mode(ctx) != EVP_CIPH_WRAP_MODE)
+			return 0;
+		return 1;
+	}
+	/*
+	 * 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 0
+	/*
+	 * XXX - we do not currently support DES3 wrap and probably should just
+	 * drop this code.
+	 */
+	if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
+		kekcipher = EVP_des_ede3_wrap();
+	else
+#endif
+#endif
+	if (keylen <= 16)
+		kekcipher = EVP_aes_128_wrap();
+	else if (keylen <= 24)
+		kekcipher = EVP_aes_192_wrap();
+	else
+		kekcipher = EVP_aes_256_wrap();
+
+	return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
+}
+
+/* Encrypt content key in key agreement recipient info */
+
+int
+cms_RecipientInfo_kari_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
+{
+	CMS_KeyAgreeRecipientInfo *kari;
+	CMS_EncryptedContentInfo *ec;
+	CMS_RecipientEncryptedKey *rek;
+	STACK_OF(CMS_RecipientEncryptedKey) *reks;
+	int i;
+
+	if (ri->type != CMS_RECIPINFO_AGREE) {
+		CMSerror(CMS_R_NOT_KEY_AGREEMENT);
+		return 0;
+	}
+	kari = ri->d.kari;
+	reks = kari->recipientEncryptedKeys;
+	ec = cms->d.envelopedData->encryptedContentInfo;
+	/* Initialise wrap algorithm parameters */
+	if (!cms_wrap_init(kari, ec->cipher))
+		return 0;
+	/*
+	 * If no originator key set up initialise for ephemeral key the public key
+	 * ASN1 structure will set the actual public key value.
+	 */
+	if (kari->originator->type == -1) {
+		CMS_OriginatorIdentifierOrKey *oik = kari->originator;
+		oik->type = CMS_OIK_PUBKEY;
+		oik->d.originatorKey = (CMS_OriginatorPublicKey *)ASN1_item_new(&CMS_OriginatorPublicKey_it);
+		if (!oik->d.originatorKey)
+			return 0;
+	}
+	/* Initialise KDF algorithm */
+	if (!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++) {
+		unsigned char *enckey;
+		size_t enckeylen;
+		rek = sk_CMS_RecipientEncryptedKey_value(reks, i);
+		if (EVP_PKEY_derive_set_peer(kari->pctx, rek->pkey) <= 0)
+			return 0;
+		if (!cms_kek_cipher(&enckey, &enckeylen, ec->key, ec->keylen,
+			                kari, 1))
+			return 0;
+		ASN1_STRING_set0(rek->encryptedKey, enckey, enckeylen);
+	}
+
+	return 1;
+}
diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c
new file mode 100644
index 0000000..8a8fdbc
--- /dev/null
+++ b/crypto/cms/cms_lib.c
@@ -0,0 +1,776 @@
+/* $OpenBSD: cms_lib.c,v 1.24 2023/08/24 04:56:36 tb Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cms_local.h"
+#include "x509_local.h"
+
+CMS_ContentInfo *
+d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len)
+{
+	return (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(d2i_CMS_ContentInfo);
+
+int
+i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(i2d_CMS_ContentInfo);
+
+CMS_ContentInfo *
+CMS_ContentInfo_new(void)
+{
+	return (CMS_ContentInfo *)ASN1_item_new(&CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(CMS_ContentInfo_new);
+
+void
+CMS_ContentInfo_free(CMS_ContentInfo *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &CMS_ContentInfo_it);
+}
+LCRYPTO_ALIAS(CMS_ContentInfo_free);
+
+int
+CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx)
+{
+	return ASN1_item_print(out, (ASN1_VALUE *)x, indent,
+	    &CMS_ContentInfo_it, pctx);
+}
+LCRYPTO_ALIAS(CMS_ContentInfo_print_ctx);
+
+const ASN1_OBJECT *
+CMS_get0_type(const CMS_ContentInfo *cms)
+{
+	return cms->contentType;
+}
+LCRYPTO_ALIAS(CMS_get0_type);
+
+CMS_ContentInfo *
+cms_Data_create(void)
+{
+	CMS_ContentInfo *cms;
+
+	cms = CMS_ContentInfo_new();
+	if (cms != NULL) {
+		cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
+		/* Never detached */
+		CMS_set_detached(cms, 0);
+	}
+	return cms;
+}
+
+static BIO *
+cms_content_bio(CMS_ContentInfo *cms)
+{
+	ASN1_OCTET_STRING **pos;
+
+	if ((pos = CMS_get0_content(cms)) == NULL)
+		return NULL;
+
+	/* If content is detached, data goes nowhere: create null BIO. */
+	if (*pos == NULL)
+		return BIO_new(BIO_s_null());
+
+	/* If content is not detached and was created, return memory BIO. */
+	if ((*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);
+}
+
+BIO *
+CMS_dataInit(CMS_ContentInfo *cms, BIO *in_content_bio)
+{
+	BIO *cms_bio = NULL, *content_bio = NULL;
+
+	if ((content_bio = in_content_bio) == NULL)
+		content_bio = cms_content_bio(cms);
+	if (content_bio == NULL) {
+		CMSerror(CMS_R_NO_CONTENT);
+		goto err;
+	}
+
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_data:
+		return content_bio;
+	case NID_pkcs7_signed:
+		if ((cms_bio = cms_SignedData_init_bio(cms)) == NULL)
+			goto err;
+		break;
+	case NID_pkcs7_digest:
+		if ((cms_bio = cms_DigestedData_init_bio(cms)) == NULL)
+			goto err;
+		break;
+	case NID_pkcs7_encrypted:
+		if ((cms_bio = cms_EncryptedData_init_bio(cms)) == NULL)
+			goto err;
+		break;
+	case NID_pkcs7_enveloped:
+		if ((cms_bio = cms_EnvelopedData_init_bio(cms)) == NULL)
+			goto err;
+		break;
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_TYPE);
+		goto err;
+	}
+
+	return BIO_push(cms_bio, content_bio);
+
+ err:
+	if (content_bio != in_content_bio)
+		BIO_free(content_bio);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_dataInit);
+
+int
+CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
+{
+	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
+
+	if (!pos)
+		return 0;
+	/* If embedded content find memory BIO and set content */
+	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT)) {
+		BIO *mbio;
+		unsigned char *cont;
+		long contlen;
+		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
+		if (!mbio) {
+			CMSerror(CMS_R_CONTENT_NOT_FOUND);
+			return 0;
+		}
+		contlen = BIO_get_mem_data(mbio, &cont);
+		/* Set bio as read only so its content can't be clobbered */
+		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
+		BIO_set_mem_eof_return(mbio, 0);
+		ASN1_STRING_set0(*pos, cont, contlen);
+		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
+	}
+
+	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_signed:
+		return cms_SignedData_final(cms, cmsbio);
+
+	case NID_pkcs7_digest:
+		return cms_DigestedData_do_final(cms, cmsbio, 0);
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_TYPE);
+		return 0;
+	}
+}
+LCRYPTO_ALIAS(CMS_dataFinal);
+
+int
+CMS_get_version(const CMS_ContentInfo *cms, long *version)
+{
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_signed:
+		*version = cms->d.signedData->version;
+		return 1;
+
+	case NID_pkcs7_enveloped:
+		*version = cms->d.envelopedData->version;
+		return 1;
+
+	case NID_pkcs7_digest:
+		*version = cms->d.digestedData->version;
+		return 1;
+
+	case NID_pkcs7_encrypted:
+		*version = cms->d.encryptedData->version;
+		return 1;
+
+	case NID_id_smime_ct_authData:
+		*version = cms->d.authenticatedData->version;
+		return 1;
+
+	case NID_id_smime_ct_compressedData:
+		*version = cms->d.compressedData->version;
+		return 1;
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_TYPE);
+		return 0;
+	}
+}
+LCRYPTO_ALIAS(CMS_get_version);
+
+int
+CMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version)
+{
+	*version = si->version;
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get_version);
+
+/*
+ * Return an OCTET STRING pointer to content. This allows it to be accessed
+ * or set later.
+ */
+
+ASN1_OCTET_STRING **
+CMS_get0_content(CMS_ContentInfo *cms)
+{
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_data:
+		return &cms->d.data;
+
+	case NID_pkcs7_signed:
+		return &cms->d.signedData->encapContentInfo->eContent;
+
+	case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->encryptedContentInfo->encryptedContent;
+
+	case NID_pkcs7_digest:
+		return &cms->d.digestedData->encapContentInfo->eContent;
+
+	case NID_pkcs7_encrypted:
+		return &cms->d.encryptedData->encryptedContentInfo->encryptedContent;
+
+	case NID_id_smime_ct_authData:
+		return &cms->d.authenticatedData->encapContentInfo->eContent;
+
+	case NID_id_smime_ct_compressedData:
+		return &cms->d.compressedData->encapContentInfo->eContent;
+
+	default:
+		if (cms->d.other->type == V_ASN1_OCTET_STRING)
+			return &cms->d.other->value.octet_string;
+		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+	}
+}
+
+/*
+ * Return an ASN1_OBJECT pointer to content type. This allows it to be
+ * accessed or set later.
+ */
+
+static ASN1_OBJECT **
+cms_get0_econtent_type(CMS_ContentInfo *cms)
+{
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_signed:
+		return &cms->d.signedData->encapContentInfo->eContentType;
+
+	case NID_pkcs7_enveloped:
+		return &cms->d.envelopedData->encryptedContentInfo->contentType;
+
+	case NID_pkcs7_digest:
+		return &cms->d.digestedData->encapContentInfo->eContentType;
+
+	case NID_pkcs7_encrypted:
+		return &cms->d.encryptedData->encryptedContentInfo->contentType;
+
+	case NID_id_smime_ct_authData:
+		return &cms->d.authenticatedData->encapContentInfo->eContentType;
+
+	case NID_id_smime_ct_compressedData:
+		return &cms->d.compressedData->encapContentInfo->eContentType;
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+	}
+}
+
+const ASN1_OBJECT *
+CMS_get0_eContentType(CMS_ContentInfo *cms)
+{
+	ASN1_OBJECT **petype;
+
+	petype = cms_get0_econtent_type(cms);
+	if (petype)
+		return *petype;
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_get0_eContentType);
+
+int
+CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid)
+{
+	ASN1_OBJECT **petype, *etype;
+
+	petype = cms_get0_econtent_type(cms);
+	if (!petype)
+		return 0;
+	if (!oid)
+		return 1;
+	etype = OBJ_dup(oid);
+	if (!etype)
+		return 0;
+	ASN1_OBJECT_free(*petype);
+	*petype = etype;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_set1_eContentType);
+
+int
+CMS_is_detached(CMS_ContentInfo *cms)
+{
+	ASN1_OCTET_STRING **pos;
+
+	pos = CMS_get0_content(cms);
+	if (!pos)
+		return -1;
+	if (*pos)
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_is_detached);
+
+int
+CMS_set_detached(CMS_ContentInfo *cms, int detached)
+{
+	ASN1_OCTET_STRING **pos;
+
+	pos = CMS_get0_content(cms);
+	if (!pos)
+		return 0;
+	if (detached) {
+		ASN1_OCTET_STRING_free(*pos);
+		*pos = NULL;
+		return 1;
+	}
+	if (*pos == NULL)
+		*pos = ASN1_OCTET_STRING_new();
+	if (*pos != NULL) {
+		/*
+		 * NB: special flag to show content is created and not read in.
+		 */
+		(*pos)->flags |= ASN1_STRING_FLAG_CONT;
+		return 1;
+	}
+	CMSerror(ERR_R_MALLOC_FAILURE);
+
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_set_detached);
+
+/* Create a digest BIO from an X509_ALGOR structure */
+
+BIO *
+cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
+{
+	BIO *mdbio = NULL;
+	const ASN1_OBJECT *digestoid;
+	const EVP_MD *digest;
+
+	X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
+	digest = EVP_get_digestbyobj(digestoid);
+	if (!digest) {
+		CMSerror(CMS_R_UNKNOWN_DIGEST_ALGORITHM);
+		goto err;
+	}
+	mdbio = BIO_new(BIO_f_md());
+	if (mdbio == NULL || !BIO_set_md(mdbio, digest)) {
+		CMSerror(CMS_R_MD_BIO_INIT_ERROR);
+		goto err;
+	}
+	return mdbio;
+
+ err:
+	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 nid;
+	const ASN1_OBJECT *mdoid;
+
+	X509_ALGOR_get0(&mdoid, NULL, NULL, mdalg);
+	nid = OBJ_obj2nid(mdoid);
+	/* Look for digest type to match signature */
+	for (;;) {
+		EVP_MD_CTX *mtmp;
+		chain = BIO_find_type(chain, BIO_TYPE_MD);
+		if (chain == NULL) {
+			CMSerror(CMS_R_NO_MATCHING_DIGEST);
+			return 0;
+		}
+		BIO_get_md_ctx(chain, &mtmp);
+		if (EVP_MD_CTX_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)
+			return EVP_MD_CTX_copy_ex(mctx, mtmp);
+		chain = BIO_next(chain);
+	}
+}
+
+static STACK_OF(CMS_CertificateChoices) **
+cms_get0_certificate_choices(CMS_ContentInfo *cms)
+{
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_signed:
+		return &cms->d.signedData->certificates;
+
+	case NID_pkcs7_enveloped:
+		if (cms->d.envelopedData->originatorInfo == NULL)
+			return NULL;
+		return &cms->d.envelopedData->originatorInfo->certificates;
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+	}
+}
+
+CMS_CertificateChoices *
+CMS_add0_CertificateChoices(CMS_ContentInfo *cms)
+{
+	STACK_OF(CMS_CertificateChoices) **pcerts;
+	CMS_CertificateChoices *cch;
+
+	pcerts = cms_get0_certificate_choices(cms);
+	if (!pcerts)
+		return NULL;
+	if (!*pcerts)
+		*pcerts = sk_CMS_CertificateChoices_new_null();
+	if (!*pcerts)
+		return NULL;
+	cch = (CMS_CertificateChoices *)ASN1_item_new(&CMS_CertificateChoices_it);
+	if (!cch)
+		return NULL;
+	if (!sk_CMS_CertificateChoices_push(*pcerts, cch)) {
+		ASN1_item_free((ASN1_VALUE *)cch, &CMS_CertificateChoices_it);
+		return NULL;
+	}
+
+	return cch;
+}
+LCRYPTO_ALIAS(CMS_add0_CertificateChoices);
+
+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)
+		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)) {
+			    CMSerror(CMS_R_CERTIFICATE_ALREADY_PRESENT);
+			    return 0;
+			}
+		}
+	}
+	cch = CMS_add0_CertificateChoices(cms);
+	if (!cch)
+		return 0;
+	cch->type = CMS_CERTCHOICE_CERT;
+	cch->d.certificate = cert;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_add0_cert);
+
+int
+CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert)
+{
+	int r;
+
+	r = CMS_add0_cert(cms, cert);
+	if (r > 0)
+		X509_up_ref(cert);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_add1_cert);
+
+static STACK_OF(CMS_RevocationInfoChoice) **
+cms_get0_revocation_choices(CMS_ContentInfo *cms)
+{
+	switch (OBJ_obj2nid(cms->contentType)) {
+	case NID_pkcs7_signed:
+		return &cms->d.signedData->crls;
+
+	case NID_pkcs7_enveloped:
+		if (cms->d.envelopedData->originatorInfo == NULL)
+			return NULL;
+		return &cms->d.envelopedData->originatorInfo->crls;
+
+	default:
+		CMSerror(CMS_R_UNSUPPORTED_CONTENT_TYPE);
+		return NULL;
+	}
+}
+
+CMS_RevocationInfoChoice *
+CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms)
+{
+	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
+	CMS_RevocationInfoChoice *rch;
+
+	pcrls = cms_get0_revocation_choices(cms);
+	if (!pcrls)
+		return NULL;
+	if (!*pcrls)
+		*pcrls = sk_CMS_RevocationInfoChoice_new_null();
+	if (!*pcrls)
+		return NULL;
+	rch = (CMS_RevocationInfoChoice *)ASN1_item_new(&CMS_RevocationInfoChoice_it);
+	if (!rch)
+		return NULL;
+	if (!sk_CMS_RevocationInfoChoice_push(*pcrls, rch)) {
+		ASN1_item_free((ASN1_VALUE *)rch, &CMS_RevocationInfoChoice_it);
+		return NULL;
+	}
+
+	return rch;
+}
+LCRYPTO_ALIAS(CMS_add0_RevocationInfoChoice);
+
+int
+CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl)
+{
+	CMS_RevocationInfoChoice *rch;
+
+	rch = CMS_add0_RevocationInfoChoice(cms);
+	if (!rch)
+		return 0;
+	rch->type = CMS_REVCHOICE_CRL;
+	rch->d.crl = crl;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_add0_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;
+}
+LCRYPTO_ALIAS(CMS_add1_crl);
+
+STACK_OF(X509) *
+CMS_get1_certs(CMS_ContentInfo *cms)
+{
+	STACK_OF(X509) *certs = NULL;
+	CMS_CertificateChoices *cch;
+	STACK_OF(CMS_CertificateChoices) **pcerts;
+	int i;
+
+	pcerts = cms_get0_certificate_choices(cms);
+	if (!pcerts)
+		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)) {
+			    sk_X509_pop_free(certs, X509_free);
+			    return NULL;
+			}
+			X509_up_ref(cch->d.certificate);
+		}
+	}
+	return certs;
+}
+LCRYPTO_ALIAS(CMS_get1_certs);
+
+STACK_OF(X509_CRL) *
+CMS_get1_crls(CMS_ContentInfo *cms)
+{
+	STACK_OF(X509_CRL) *crls = NULL;
+	STACK_OF(CMS_RevocationInfoChoice) **pcrls;
+	CMS_RevocationInfoChoice *rch;
+	int i;
+
+	pcrls = cms_get0_revocation_choices(cms);
+	if (!pcrls)
+		return NULL;
+	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(*pcrls); i++) {
+		rch = sk_CMS_RevocationInfoChoice_value(*pcrls, i);
+		if (rch->type == 0) {
+			if (!crls) {
+			    crls = sk_X509_CRL_new_null();
+			    if (!crls)
+			        return NULL;
+			}
+			if (!sk_X509_CRL_push(crls, rch->d.crl)) {
+			    sk_X509_CRL_pop_free(crls, X509_CRL_free);
+			    return NULL;
+			}
+			X509_CRL_up_ref(rch->d.crl);
+		}
+	}
+	return crls;
+}
+LCRYPTO_ALIAS(CMS_get1_crls);
+
+static const ASN1_OCTET_STRING *
+cms_X509_get0_subject_key_id(X509 *x)
+{
+	/* Call for side-effect of computing hash and caching extensions */
+	X509_check_purpose(x, -1, -1);
+	return x->skid;
+}
+
+int
+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));
+}
+
+int
+cms_keyid_cert_cmp(ASN1_OCTET_STRING *keyid, X509 *cert)
+{
+	const ASN1_OCTET_STRING *cert_keyid = cms_X509_get0_subject_key_id(cert);
+
+	if (cert_keyid == NULL)
+		return -1;
+
+	return ASN1_OCTET_STRING_cmp(keyid, cert_keyid);
+}
+
+int
+cms_set1_ias(CMS_IssuerAndSerialNumber **pias, X509 *cert)
+{
+	CMS_IssuerAndSerialNumber *ias;
+
+	ias = (CMS_IssuerAndSerialNumber *)ASN1_item_new(&CMS_IssuerAndSerialNumber_it);
+	if (!ias)
+		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)))
+		goto err;
+	ASN1_item_free((ASN1_VALUE *)*pias, &CMS_IssuerAndSerialNumber_it);
+	*pias = ias;
+
+	return 1;
+
+ err:
+	ASN1_item_free((ASN1_VALUE *)ias, &CMS_IssuerAndSerialNumber_it);
+	CMSerror(ERR_R_MALLOC_FAILURE);
+
+	return 0;
+}
+
+int
+cms_set1_keyid(ASN1_OCTET_STRING **pkeyid, X509 *cert)
+{
+	ASN1_OCTET_STRING *keyid = NULL;
+	const ASN1_OCTET_STRING *cert_keyid;
+
+	cert_keyid = cms_X509_get0_subject_key_id(cert);
+	if (cert_keyid == NULL) {
+		CMSerror(CMS_R_CERTIFICATE_HAS_NO_KEYID);
+		return 0;
+	}
+	keyid = ASN1_STRING_dup(cert_keyid);
+	if (!keyid) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_OCTET_STRING_free(*pkeyid);
+	*pkeyid = keyid;
+
+	return 1;
+}
diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h
new file mode 100644
index 0000000..2e3a363
--- /dev/null
+++ b/crypto/cms/cms_local.h
@@ -0,0 +1,477 @@
+/* $OpenBSD: cms_local.h,v 1.5 2023/08/24 04:56:36 tb Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifndef HEADER_CMS_LOCAL_H
+#define HEADER_CMS_LOCAL_H
+
+#include 
+
+/*
+ * Cryptographic message syntax (CMS) structures: taken from RFC3852
+ */
+
+/* Forward references */
+
+typedef struct CMS_IssuerAndSerialNumber_st CMS_IssuerAndSerialNumber;
+typedef struct CMS_EncapsulatedContentInfo_st CMS_EncapsulatedContentInfo;
+typedef struct CMS_SignerIdentifier_st CMS_SignerIdentifier;
+typedef struct CMS_SignedData_st CMS_SignedData;
+typedef struct CMS_OtherRevocationInfoFormat_st CMS_OtherRevocationInfoFormat;
+typedef struct CMS_OriginatorInfo_st CMS_OriginatorInfo;
+typedef struct CMS_EncryptedContentInfo_st CMS_EncryptedContentInfo;
+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_CompressedData_st CMS_CompressedData;
+typedef struct CMS_OtherCertificateFormat_st CMS_OtherCertificateFormat;
+typedef struct CMS_KeyTransRecipientInfo_st CMS_KeyTransRecipientInfo;
+typedef struct CMS_OriginatorPublicKey_st CMS_OriginatorPublicKey;
+typedef struct CMS_OriginatorIdentifierOrKey_st CMS_OriginatorIdentifierOrKey;
+typedef struct CMS_KeyAgreeRecipientInfo_st CMS_KeyAgreeRecipientInfo;
+typedef struct CMS_RecipientKeyIdentifier_st CMS_RecipientKeyIdentifier;
+typedef struct CMS_KeyAgreeRecipientIdentifier_st
+    CMS_KeyAgreeRecipientIdentifier;
+typedef struct CMS_KEKIdentifier_st CMS_KEKIdentifier;
+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;
+
+struct CMS_ContentInfo_st {
+	ASN1_OBJECT *contentType;
+	union {
+		ASN1_OCTET_STRING *data;
+		CMS_SignedData *signedData;
+		CMS_EnvelopedData *envelopedData;
+		CMS_DigestedData *digestedData;
+		CMS_EncryptedData *encryptedData;
+		CMS_AuthenticatedData *authenticatedData;
+		CMS_CompressedData *compressedData;
+		ASN1_TYPE *other;
+		/* Other types ... */
+		void *otherData;
+	} d;
+};
+
+DECLARE_STACK_OF(CMS_CertificateChoices)
+
+struct CMS_SignedData_st {
+	long version;
+	STACK_OF(X509_ALGOR) *digestAlgorithms;
+	CMS_EncapsulatedContentInfo *encapContentInfo;
+	STACK_OF(CMS_CertificateChoices) *certificates;
+	STACK_OF(CMS_RevocationInfoChoice) *crls;
+	STACK_OF(CMS_SignerInfo) *signerInfos;
+};
+
+struct CMS_EncapsulatedContentInfo_st {
+	ASN1_OBJECT *eContentType;
+	ASN1_OCTET_STRING *eContent;
+	/* Set to 1 if incomplete structure only part set up */
+	int partial;
+};
+
+struct CMS_SignerInfo_st {
+	long version;
+	CMS_SignerIdentifier *sid;
+	X509_ALGOR *digestAlgorithm;
+	STACK_OF(X509_ATTRIBUTE) *signedAttrs;
+	X509_ALGOR *signatureAlgorithm;
+	ASN1_OCTET_STRING *signature;
+	STACK_OF(X509_ATTRIBUTE) *unsignedAttrs;
+	/* Signing certificate and key */
+	X509 *signer;
+	EVP_PKEY *pkey;
+	/* Digest and public key context for alternative parameters */
+	EVP_MD_CTX *mctx;
+	EVP_PKEY_CTX *pctx;
+};
+
+struct CMS_SignerIdentifier_st {
+	int type;
+	union {
+		CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
+		ASN1_OCTET_STRING *subjectKeyIdentifier;
+	} d;
+};
+
+struct CMS_EnvelopedData_st {
+	long version;
+	CMS_OriginatorInfo *originatorInfo;
+	STACK_OF(CMS_RecipientInfo) *recipientInfos;
+	CMS_EncryptedContentInfo *encryptedContentInfo;
+	STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
+};
+
+struct CMS_OriginatorInfo_st {
+	STACK_OF(CMS_CertificateChoices) *certificates;
+	STACK_OF(CMS_RevocationInfoChoice) *crls;
+};
+
+struct CMS_EncryptedContentInfo_st {
+	ASN1_OBJECT *contentType;
+	X509_ALGOR *contentEncryptionAlgorithm;
+	ASN1_OCTET_STRING *encryptedContent;
+	/* Content encryption algorithm and key */
+	const EVP_CIPHER *cipher;
+	unsigned char *key;
+	size_t keylen;
+	/* 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 */
+	int havenocert;
+};
+
+struct CMS_RecipientInfo_st {
+	int type;
+	union {
+		CMS_KeyTransRecipientInfo *ktri;
+		CMS_KeyAgreeRecipientInfo *kari;
+		CMS_KEKRecipientInfo *kekri;
+		CMS_PasswordRecipientInfo *pwri;
+		CMS_OtherRecipientInfo *ori;
+	} d;
+};
+
+typedef CMS_SignerIdentifier CMS_RecipientIdentifier;
+
+struct CMS_KeyTransRecipientInfo_st {
+	long version;
+	CMS_RecipientIdentifier *rid;
+	X509_ALGOR *keyEncryptionAlgorithm;
+	ASN1_OCTET_STRING *encryptedKey;
+	/* Recipient Key and cert */
+	X509 *recip;
+	EVP_PKEY *pkey;
+	/* Public key context for this operation */
+	EVP_PKEY_CTX *pctx;
+};
+
+struct CMS_KeyAgreeRecipientInfo_st {
+	long version;
+	CMS_OriginatorIdentifierOrKey *originator;
+	ASN1_OCTET_STRING *ukm;
+	X509_ALGOR *keyEncryptionAlgorithm;
+	STACK_OF(CMS_RecipientEncryptedKey) *recipientEncryptedKeys;
+	/* Public key context associated with current operation */
+	EVP_PKEY_CTX *pctx;
+	/* Cipher context for CEK wrapping */
+	EVP_CIPHER_CTX *ctx;
+};
+
+struct CMS_OriginatorIdentifierOrKey_st {
+	int type;
+	union {
+		CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
+		ASN1_OCTET_STRING *subjectKeyIdentifier;
+		CMS_OriginatorPublicKey *originatorKey;
+	} d;
+};
+
+struct CMS_OriginatorPublicKey_st {
+	X509_ALGOR *algorithm;
+	ASN1_BIT_STRING *publicKey;
+};
+
+struct CMS_RecipientEncryptedKey_st {
+	CMS_KeyAgreeRecipientIdentifier *rid;
+	ASN1_OCTET_STRING *encryptedKey;
+	/* Public key associated with this recipient */
+	EVP_PKEY *pkey;
+};
+
+struct CMS_KeyAgreeRecipientIdentifier_st {
+	int type;
+	union {
+		CMS_IssuerAndSerialNumber *issuerAndSerialNumber;
+		CMS_RecipientKeyIdentifier *rKeyId;
+	} d;
+};
+
+struct CMS_RecipientKeyIdentifier_st {
+	ASN1_OCTET_STRING *subjectKeyIdentifier;
+	ASN1_GENERALIZEDTIME *date;
+	CMS_OtherKeyAttribute *other;
+};
+
+struct CMS_KEKRecipientInfo_st {
+	long version;
+	CMS_KEKIdentifier *kekid;
+	X509_ALGOR *keyEncryptionAlgorithm;
+	ASN1_OCTET_STRING *encryptedKey;
+	/* Extra info: symmetric key to use */
+	unsigned char *key;
+	size_t keylen;
+};
+
+struct CMS_KEKIdentifier_st {
+	ASN1_OCTET_STRING *keyIdentifier;
+	ASN1_GENERALIZEDTIME *date;
+	CMS_OtherKeyAttribute *other;
+};
+
+struct CMS_PasswordRecipientInfo_st {
+	long version;
+	X509_ALGOR *keyDerivationAlgorithm;
+	X509_ALGOR *keyEncryptionAlgorithm;
+	ASN1_OCTET_STRING *encryptedKey;
+	/* Extra info: password to use */
+	unsigned char *pass;
+	size_t passlen;
+};
+
+struct CMS_OtherRecipientInfo_st {
+	ASN1_OBJECT *oriType;
+	ASN1_TYPE *oriValue;
+};
+
+struct CMS_DigestedData_st {
+	long version;
+	X509_ALGOR *digestAlgorithm;
+	CMS_EncapsulatedContentInfo *encapContentInfo;
+	ASN1_OCTET_STRING *digest;
+};
+
+struct CMS_EncryptedData_st {
+	long version;
+	CMS_EncryptedContentInfo *encryptedContentInfo;
+	STACK_OF(X509_ATTRIBUTE) *unprotectedAttrs;
+};
+
+struct CMS_AuthenticatedData_st {
+	long version;
+	CMS_OriginatorInfo *originatorInfo;
+	STACK_OF(CMS_RecipientInfo) *recipientInfos;
+	X509_ALGOR *macAlgorithm;
+	X509_ALGOR *digestAlgorithm;
+	CMS_EncapsulatedContentInfo *encapContentInfo;
+	STACK_OF(X509_ATTRIBUTE) *authAttrs;
+	ASN1_OCTET_STRING *mac;
+	STACK_OF(X509_ATTRIBUTE) *unauthAttrs;
+};
+
+struct CMS_CompressedData_st {
+	long version;
+	X509_ALGOR *compressionAlgorithm;
+	STACK_OF(CMS_RecipientInfo) *recipientInfos;
+	CMS_EncapsulatedContentInfo *encapContentInfo;
+};
+
+struct CMS_RevocationInfoChoice_st {
+	int type;
+	union {
+		X509_CRL *crl;
+		CMS_OtherRevocationInfoFormat *other;
+	} d;
+};
+
+#define CMS_REVCHOICE_CRL               0
+#define CMS_REVCHOICE_OTHER             1
+
+struct CMS_OtherRevocationInfoFormat_st {
+	ASN1_OBJECT *otherRevInfoFormat;
+	ASN1_TYPE *otherRevInfo;
+};
+
+struct CMS_CertificateChoices {
+	int type;
+	union {
+		X509 *certificate;
+		ASN1_STRING *extendedCertificate; /* Obsolete */
+		ASN1_STRING *v1AttrCert; /* Left encoded for now */
+		ASN1_STRING *v2AttrCert; /* Left encoded for now */
+		CMS_OtherCertificateFormat *other;
+	} d;
+};
+
+#define CMS_CERTCHOICE_CERT             0
+#define CMS_CERTCHOICE_EXCERT           1
+#define CMS_CERTCHOICE_V1ACERT          2
+#define CMS_CERTCHOICE_V2ACERT          3
+#define CMS_CERTCHOICE_OTHER            4
+
+struct CMS_OtherCertificateFormat_st {
+	ASN1_OBJECT *otherCertFormat;
+	ASN1_TYPE *otherCert;
+};
+
+/*
+ * This is also defined in pkcs7.h but we duplicate it to allow the CMS code
+ * to be independent of PKCS#7
+ */
+
+struct CMS_IssuerAndSerialNumber_st {
+	X509_NAME *issuer;
+	ASN1_INTEGER *serialNumber;
+};
+
+struct CMS_OtherKeyAttribute_st {
+	ASN1_OBJECT *keyAttrId;
+	ASN1_TYPE *keyAttr;
+};
+
+/* ESS structures */
+
+#ifdef HEADER_X509V3_H
+
+struct CMS_ReceiptRequest_st {
+	ASN1_OCTET_STRING *signedContentIdentifier;
+	CMS_ReceiptsFrom *receiptsFrom;
+	STACK_OF(GENERAL_NAMES) *receiptsTo;
+};
+
+struct CMS_ReceiptsFrom_st {
+	int type;
+	union {
+		long allOrFirstTier;
+		STACK_OF(GENERAL_NAMES) *receiptList;
+	} d;
+};
+#endif
+
+struct CMS_Receipt_st {
+	long version;
+	ASN1_OBJECT *contentType;
+	ASN1_OCTET_STRING *signedContentIdentifier;
+	ASN1_OCTET_STRING *originatorSignatureValue;
+};
+
+extern const ASN1_ITEM CMS_SignerInfo_it;
+extern const ASN1_ITEM CMS_IssuerAndSerialNumber_it;
+extern const ASN1_ITEM CMS_Attributes_Sign_it;
+extern const ASN1_ITEM CMS_Attributes_Verify_it;
+extern const ASN1_ITEM CMS_RecipientInfo_it;
+extern const ASN1_ITEM CMS_PasswordRecipientInfo_it;
+CMS_IssuerAndSerialNumber *CMS_IssuerAndSerialNumber_new(void);
+void CMS_IssuerAndSerialNumber_free(CMS_IssuerAndSerialNumber *a);
+
+#define CMS_SIGNERINFO_ISSUER_SERIAL    0
+#define CMS_SIGNERINFO_KEYIDENTIFIER    1
+
+#define CMS_RECIPINFO_ISSUER_SERIAL     0
+#define CMS_RECIPINFO_KEYIDENTIFIER     1
+
+#define CMS_REK_ISSUER_SERIAL           0
+#define CMS_REK_KEYIDENTIFIER           1
+
+#define CMS_OIK_ISSUER_SERIAL           0
+#define CMS_OIK_KEYIDENTIFIER           1
+#define CMS_OIK_PUBKEY                  2
+
+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);
+/* 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);
+
+/* PWRI routines */
+int cms_RecipientInfo_pwri_crypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri,
+    int en_de);
+
+extern const ASN1_ITEM CMS_CertificateChoices_it;
+extern const ASN1_ITEM CMS_DigestedData_it;
+extern const ASN1_ITEM CMS_EncryptedData_it;
+extern const ASN1_ITEM CMS_EnvelopedData_it;
+extern const ASN1_ITEM CMS_KEKRecipientInfo_it;
+extern const ASN1_ITEM CMS_KeyAgreeRecipientInfo_it;
+extern const ASN1_ITEM CMS_KeyTransRecipientInfo_it;
+extern const ASN1_ITEM CMS_OriginatorPublicKey_it;
+extern const ASN1_ITEM CMS_OtherKeyAttribute_it;
+extern const ASN1_ITEM CMS_Receipt_it;
+extern const ASN1_ITEM CMS_ReceiptRequest_it;
+extern const ASN1_ITEM CMS_RecipientEncryptedKey_it;
+extern const ASN1_ITEM CMS_RecipientKeyIdentifier_it;
+extern const ASN1_ITEM CMS_RevocationInfoChoice_it;
+extern const ASN1_ITEM CMS_SignedData_it;
+extern const ASN1_ITEM CMS_CompressedData_it;
+
+#endif /* !HEADER_CMS_LOCAL_H */
diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c
new file mode 100644
index 0000000..9ea7cfd
--- /dev/null
+++ b/crypto/cms/cms_pwri.c
@@ -0,0 +1,435 @@
+/* $OpenBSD: cms_pwri.c,v 1.29 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2009 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+#include "asn1/asn1_local.h"
+
+int
+CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, unsigned char *pass,
+    ssize_t passlen)
+{
+	CMS_PasswordRecipientInfo *pwri;
+
+	if (ri->type != CMS_RECIPINFO_PASS) {
+		CMSerror(CMS_R_NOT_PWRI);
+		return 0;
+	}
+
+	pwri = ri->d.pwri;
+	pwri->pass = pass;
+	if (pass && passlen < 0)
+		passlen = strlen((char *)pass);
+	pwri->passlen = passlen;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_RecipientInfo_set0_password);
+
+CMS_RecipientInfo *
+CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, int wrap_nid,
+    int pbe_nid, unsigned char *pass, ssize_t passlen,
+    const EVP_CIPHER *kekciph)
+{
+	CMS_RecipientInfo *ri = NULL;
+	CMS_EnvelopedData *env;
+	CMS_PasswordRecipientInfo *pwri;
+	EVP_CIPHER_CTX *ctx = NULL;
+	X509_ALGOR *encalg = NULL;
+	unsigned char iv[EVP_MAX_IV_LENGTH];
+	int ivlen;
+
+	env = cms_get0_enveloped(cms);
+	if (!env)
+		return NULL;
+
+	if (wrap_nid <= 0)
+		wrap_nid = NID_id_alg_PWRI_KEK;
+
+	if (pbe_nid <= 0)
+		pbe_nid = NID_id_pbkdf2;
+
+	/* Get from enveloped data */
+	if (kekciph == NULL)
+		kekciph = env->encryptedContentInfo->cipher;
+
+	if (kekciph == NULL) {
+		CMSerror(CMS_R_NO_CIPHER);
+		return NULL;
+	}
+	if (wrap_nid != NID_id_alg_PWRI_KEK) {
+		CMSerror(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+		return NULL;
+	}
+
+	/* Setup algorithm identifier for cipher */
+	encalg = X509_ALGOR_new();
+	if (encalg == NULL) {
+		goto merr;
+	}
+
+	if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
+		goto merr;
+
+	if (EVP_EncryptInit_ex(ctx, kekciph, NULL, NULL, NULL) <= 0) {
+		CMSerror(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	ivlen = EVP_CIPHER_CTX_iv_length(ctx);
+
+	if (ivlen > 0) {
+		arc4random_buf(iv, ivlen);
+		if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) <= 0) {
+			CMSerror(ERR_R_EVP_LIB);
+			goto err;
+		}
+		encalg->parameter = ASN1_TYPE_new();
+		if (!encalg->parameter) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (EVP_CIPHER_param_to_asn1(ctx, encalg->parameter) <= 0) {
+			CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+			goto err;
+		}
+	}
+
+	encalg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
+
+	EVP_CIPHER_CTX_free(ctx);
+	ctx = NULL;
+
+	/* Initialize recipient info */
+	ri = (CMS_RecipientInfo *)ASN1_item_new(&CMS_RecipientInfo_it);
+	if (ri == NULL)
+		goto merr;
+
+	ri->d.pwri = (CMS_PasswordRecipientInfo *)ASN1_item_new(&CMS_PasswordRecipientInfo_it);
+	if (ri->d.pwri == NULL)
+		goto merr;
+	ri->type = CMS_RECIPINFO_PASS;
+
+	pwri = ri->d.pwri;
+	/* Since this is overwritten, free up empty structure already there */
+	X509_ALGOR_free(pwri->keyEncryptionAlgorithm);
+	pwri->keyEncryptionAlgorithm = X509_ALGOR_new();
+	if (pwri->keyEncryptionAlgorithm == NULL)
+		goto merr;
+	pwri->keyEncryptionAlgorithm->algorithm = OBJ_nid2obj(wrap_nid);
+	pwri->keyEncryptionAlgorithm->parameter = ASN1_TYPE_new();
+	if (pwri->keyEncryptionAlgorithm->parameter == NULL)
+		goto merr;
+
+	if (!ASN1_item_pack(encalg, &X509_ALGOR_it,
+	    &pwri->keyEncryptionAlgorithm->parameter->value.sequence))
+		 goto merr;
+	pwri->keyEncryptionAlgorithm->parameter->type = V_ASN1_SEQUENCE;
+
+	X509_ALGOR_free(encalg);
+	encalg = NULL;
+
+	/* Setup PBE algorithm */
+
+	pwri->keyDerivationAlgorithm = PKCS5_pbkdf2_set(iter, NULL, 0, -1, -1);
+
+	if (!pwri->keyDerivationAlgorithm)
+		goto err;
+
+	CMS_RecipientInfo_set0_password(ri, pass, passlen);
+	pwri->version = 0;
+
+	if (!sk_CMS_RecipientInfo_push(env->recipientInfos, ri))
+		goto merr;
+
+	return ri;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+ err:
+	EVP_CIPHER_CTX_free(ctx);
+	if (ri)
+		ASN1_item_free((ASN1_VALUE *)ri, &CMS_RecipientInfo_it);
+	X509_ALGOR_free(encalg);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_add0_recipient_password);
+
+/*
+ * This is an implementation of the key wrapping mechanism in RFC3211, at
+ * some point this should go into EVP.
+ */
+
+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);
+	unsigned char *tmp;
+	int outl, rv = 0;
+
+	if (inlen < 2 * blocklen) {
+		/* too small */
+		return 0;
+	}
+	if (inlen % blocklen) {
+		/* Invalid size */
+		return 0;
+	}
+	if ((tmp = malloc(inlen)) == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	/* setup IV by decrypting last two blocks */
+	if (!EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl,
+	    in + inlen - 2 * blocklen, blocklen * 2)
+		/*
+		 * Do a decrypt of last decrypted block to set IV to correct value
+		 * output it to start of buffer so we don't corrupt decrypted block
+		 * this works because buffer is at least two block lengths long.
+		 */
+		|| !EVP_DecryptUpdate(ctx, tmp, &outl, tmp + inlen - blocklen, blocklen)
+		/* Can now decrypt first n - 1 blocks */
+		|| !EVP_DecryptUpdate(ctx, tmp, &outl, in, inlen - blocklen)
+
+		/* Reset IV to original value */
+		|| !EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL)
+		/* Decrypt again */
+		|| !EVP_DecryptUpdate(ctx, tmp, &outl, tmp, inlen))
+		goto err;
+	/* Check check bytes */
+	if (((tmp[1] ^ tmp[4]) & (tmp[2] ^ tmp[5]) & (tmp[3] ^ tmp[6])) != 0xff) {
+		/* Check byte failure */
+		goto err;
+	}
+	if (inlen < (size_t)(tmp[0] - 4)) {
+		/* Invalid length value */
+		goto err;
+	}
+	*outlen = (size_t)tmp[0];
+	memcpy(out, tmp + 4, *outlen);
+	rv = 1;
+
+ err:
+	freezero(tmp, inlen);
+
+	return rv;
+}
+
+static int
+kek_wrap_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 olen;
+	int dummy;
+
+	/*
+	 * First decide length of output buffer: need header and round up to
+	 * multiple of block length.
+	 */
+	olen = (inlen + 4 + blocklen - 1) / blocklen;
+	olen *= blocklen;
+	if (olen < 2 * blocklen) {
+		/* Key too small */
+		return 0;
+	}
+	if (inlen > 0xFF) {
+		/* Key too large */
+		return 0;
+	}
+	if (out) {
+		/* Set header */
+		out[0] = (unsigned char)inlen;
+		out[1] = in[0] ^ 0xFF;
+		out[2] = in[1] ^ 0xFF;
+		out[3] = in[2] ^ 0xFF;
+		memcpy(out + 4, in, inlen);
+		/* Add random padding to end */
+		if (olen > inlen + 4)
+			arc4random_buf(out + 4 + inlen, olen - 4 - inlen);
+		/* Encrypt twice */
+		if (!EVP_EncryptUpdate(ctx, out, &dummy, out, olen) ||
+		    !EVP_EncryptUpdate(ctx, out, &dummy, out, olen))
+			return 0;
+	}
+
+	*outlen = olen;
+
+	return 1;
+}
+
+/* Encrypt/Decrypt content key in PWRI recipient info */
+
+int
+cms_RecipientInfo_pwri_crypt(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;
+	unsigned char *key = NULL;
+	size_t keylen;
+
+	ec = cms->d.envelopedData->encryptedContentInfo;
+
+	pwri = ri->d.pwri;
+
+	if (!pwri->pass) {
+		CMSerror(CMS_R_NO_PASSWORD);
+		return 0;
+	}
+	algtmp = pwri->keyEncryptionAlgorithm;
+
+	if (!algtmp || OBJ_obj2nid(algtmp->algorithm) != NID_id_alg_PWRI_KEK) {
+		CMSerror(CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
+		return 0;
+	}
+
+	if (algtmp->parameter != NULL &&
+	    algtmp->parameter->type == V_ASN1_SEQUENCE &&
+	    algtmp->parameter->value.sequence != NULL)
+		kekalg = ASN1_item_unpack(algtmp->parameter->value.sequence,
+		    &X509_ALGOR_it);
+
+	if (kekalg == NULL) {
+		CMSerror(CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER);
+		return 0;
+	}
+
+	kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
+	if (!kekcipher) {
+		CMSerror(CMS_R_UNKNOWN_CIPHER);
+		return 0;
+	}
+
+	kekctx = EVP_CIPHER_CTX_new();
+	if (kekctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	/* 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) {
+		CMSerror(CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
+		goto err;
+	}
+
+	algtmp = pwri->keyDerivationAlgorithm;
+
+	/* 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) {
+		CMSerror(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	/* Finally wrap/unwrap the key */
+
+	if (en_de) {
+		if (!kek_wrap_key(NULL, &keylen, ec->key, ec->keylen, kekctx))
+			goto err;
+
+		key = malloc(keylen);
+		if (key == NULL)
+			goto err;
+
+		if (!kek_wrap_key(key, &keylen, ec->key, ec->keylen, kekctx))
+			goto err;
+		pwri->encryptedKey->data = key;
+		pwri->encryptedKey->length = keylen;
+	} else {
+		key = malloc(pwri->encryptedKey->length);
+		if (key == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!kek_unwrap_key(key, &keylen, pwri->encryptedKey->data,
+		    pwri->encryptedKey->length, kekctx)) {
+			CMSerror(CMS_R_UNWRAP_FAILURE);
+			goto err;
+		}
+
+		freezero(ec->key, ec->keylen);
+		ec->key = key;
+		ec->keylen = keylen;
+	}
+
+	r = 1;
+
+ err:
+	EVP_CIPHER_CTX_free(kekctx);
+	if (!r)
+		free(key);
+	X509_ALGOR_free(kekalg);
+
+	return r;
+}
diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c
new file mode 100644
index 0000000..2458229
--- /dev/null
+++ b/crypto/cms/cms_sd.c
@@ -0,0 +1,1029 @@
+/* $OpenBSD: cms_sd.c,v 1.28 2023/09/11 09:29:30 tb Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+#include "asn1/asn1_local.h"
+#include "evp/evp_local.h"
+
+/* CMS SignedData Utilities */
+
+static CMS_SignedData *
+cms_get0_signed(CMS_ContentInfo *cms)
+{
+	if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_signed) {
+		CMSerror(CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA);
+		return NULL;
+	}
+	return cms->d.signedData;
+}
+
+static CMS_SignedData *
+cms_signed_data_init(CMS_ContentInfo *cms)
+{
+	if (cms->d.other == NULL) {
+		cms->d.signedData = (CMS_SignedData *)ASN1_item_new(&CMS_SignedData_it);
+		if (!cms->d.signedData) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+		cms->d.signedData->version = 1;
+		cms->d.signedData->encapContentInfo->eContentType =
+		    OBJ_nid2obj(NID_pkcs7_data);
+		cms->d.signedData->encapContentInfo->partial = 1;
+		ASN1_OBJECT_free(cms->contentType);
+		cms->contentType = OBJ_nid2obj(NID_pkcs7_signed);
+		return cms->d.signedData;
+	}
+	return cms_get0_signed(cms);
+}
+
+/* Just initialise SignedData e.g. for certs only structure */
+
+int
+CMS_SignedData_init(CMS_ContentInfo *cms)
+{
+	if (cms_signed_data_init(cms))
+		return 1;
+	else
+		return 0;
+}
+LCRYPTO_ALIAS(CMS_SignedData_init);
+
+/* Check structures and fixup version numbers (if necessary) */
+
+static void
+cms_sd_set_version(CMS_SignedData *sd)
+{
+	int i;
+	CMS_CertificateChoices *cch;
+	CMS_RevocationInfoChoice *rch;
+	CMS_SignerInfo *si;
+
+	for (i = 0; i < sk_CMS_CertificateChoices_num(sd->certificates); i++) {
+		cch = sk_CMS_CertificateChoices_value(sd->certificates, i);
+		if (cch->type == CMS_CERTCHOICE_OTHER) {
+			if (sd->version < 5)
+			    sd->version = 5;
+		} else if (cch->type == CMS_CERTCHOICE_V2ACERT) {
+			if (sd->version < 4)
+			    sd->version = 4;
+		} else if (cch->type == CMS_CERTCHOICE_V1ACERT) {
+			if (sd->version < 3)
+			    sd->version = 3;
+		}
+	}
+
+	for (i = 0; i < sk_CMS_RevocationInfoChoice_num(sd->crls); i++) {
+		rch = sk_CMS_RevocationInfoChoice_value(sd->crls, i);
+		if (rch->type == CMS_REVCHOICE_OTHER) {
+			if (sd->version < 5)
+			    sd->version = 5;
+		}
+	}
+
+	if ((OBJ_obj2nid(sd->encapContentInfo->eContentType) != NID_pkcs7_data)
+		&& (sd->version < 3))
+		sd->version = 3;
+
+	for (i = 0; i < sk_CMS_SignerInfo_num(sd->signerInfos); i++) {
+		si = sk_CMS_SignerInfo_value(sd->signerInfos, i);
+		if (si->sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
+			if (si->version < 3)
+			    si->version = 3;
+			if (sd->version < 3)
+			    sd->version = 3;
+		} else if (si->version < 1)
+			si->version = 1;
+	}
+
+	if (sd->version < 1)
+		sd->version = 1;
+}
+
+/* Copy an existing messageDigest value */
+
+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;
+		if (CMS_signed_get_attr_count(sitmp) < 0)
+			continue;
+		if (OBJ_cmp(si->digestAlgorithm->algorithm,
+		    sitmp->digestAlgorithm->algorithm))
+			continue;
+		messageDigest = CMS_signed_get0_data_by_OBJ(sitmp,
+		    OBJ_nid2obj(NID_pkcs9_messageDigest), -3, V_ASN1_OCTET_STRING);
+		if (!messageDigest) {
+			CMSerror(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
+			return 0;
+		}
+
+		if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_messageDigest,
+		    V_ASN1_OCTET_STRING, messageDigest, -1))
+			return 1;
+		else
+			return 0;
+	}
+
+	CMSerror(CMS_R_NO_MATCHING_DIGEST);
+
+	return 0;
+}
+
+int
+cms_set1_SignerIdentifier(CMS_SignerIdentifier *sid, X509 *cert, int type)
+{
+	switch (type) {
+	case CMS_SIGNERINFO_ISSUER_SERIAL:
+		if (!cms_set1_ias(&sid->d.issuerAndSerialNumber, cert))
+			return 0;
+		break;
+
+	case CMS_SIGNERINFO_KEYIDENTIFIER:
+		if (!cms_set1_keyid(&sid->d.subjectKeyIdentifier, cert))
+			return 0;
+		break;
+
+	default:
+		CMSerror(CMS_R_UNKNOWN_ID);
+		return 0;
+	}
+
+	sid->type = type;
+
+	return 1;
+}
+
+int
+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)
+			*issuer = sid->d.issuerAndSerialNumber->issuer;
+		if (sno)
+			*sno = sid->d.issuerAndSerialNumber->serialNumber;
+	} else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER) {
+		if (keyid)
+			*keyid = sid->d.subjectKeyIdentifier;
+	} else
+		return 0;
+
+	return 1;
+}
+
+int
+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);
+	else if (sid->type == CMS_SIGNERINFO_KEYIDENTIFIER)
+		return cms_keyid_cert_cmp(sid->d.subjectKeyIdentifier, cert);
+	else
+		return -1;
+}
+
+static int
+cms_sd_asn1_ctrl(CMS_SignerInfo *si, int cmd)
+{
+	EVP_PKEY *pkey = si->pkey;
+	int ret;
+
+	if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
+		return 1;
+	ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_CMS_SIGN, cmd, si);
+	if (ret == -2) {
+		CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+		return 0;
+	}
+	if (ret <= 0) {
+		CMSerror(CMS_R_CTRL_FAILURE);
+		return 0;
+	}
+
+	return 1;
+}
+
+CMS_SignerInfo *
+CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk,
+    const EVP_MD *md, unsigned int flags)
+{
+	CMS_SignedData *sd;
+	CMS_SignerInfo *si = NULL;
+	X509_ALGOR *alg;
+	int i, type;
+
+	if (!X509_check_private_key(signer, pk)) {
+		CMSerror(CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+		return NULL;
+	}
+	sd = cms_signed_data_init(cms);
+	if (!sd)
+		goto err;
+	si = (CMS_SignerInfo *)ASN1_item_new(&CMS_SignerInfo_it);
+	if (!si)
+		goto merr;
+	/* Call for side-effect of computing hash and caching extensions */
+	X509_check_purpose(signer, -1, -1);
+
+	X509_up_ref(signer);
+	EVP_PKEY_up_ref(pk);
+
+	si->pkey = pk;
+	si->signer = signer;
+	si->mctx = EVP_MD_CTX_new();
+	si->pctx = NULL;
+
+	if (si->mctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (flags & CMS_USE_KEYID) {
+		si->version = 3;
+		if (sd->version < 3)
+			sd->version = 3;
+		type = CMS_SIGNERINFO_KEYIDENTIFIER;
+	} else {
+		type = CMS_SIGNERINFO_ISSUER_SERIAL;
+		si->version = 1;
+	}
+
+	if (!cms_set1_SignerIdentifier(si->sid, signer, type))
+		goto err;
+
+	if (md == NULL) {
+		int def_nid;
+		if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0)
+			goto err;
+		md = EVP_get_digestbynid(def_nid);
+		if (md == NULL) {
+			CMSerror(CMS_R_NO_DEFAULT_DIGEST);
+			goto err;
+		}
+	}
+
+	if (!md) {
+		CMSerror(CMS_R_NO_DIGEST_SET);
+		goto err;
+	}
+
+	X509_ALGOR_set_md(si->digestAlgorithm, md);
+
+	/* See if digest is present in digestAlgorithms */
+	for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) {
+		const ASN1_OBJECT *aoid;
+		alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i);
+		X509_ALGOR_get0(&aoid, NULL, NULL, alg);
+		if (OBJ_obj2nid(aoid) == EVP_MD_type(md))
+			break;
+	}
+
+	if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) {
+		alg = X509_ALGOR_new();
+		if (alg == NULL)
+			goto merr;
+		X509_ALGOR_set_md(alg, md);
+		if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) {
+			X509_ALGOR_free(alg);
+			goto merr;
+		}
+	}
+
+	if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0))
+		goto err;
+	if (!(flags & CMS_NOATTR)) {
+		/*
+		 * Initialize signed attributes structure so other attributes
+		 * such as signing time etc are added later even if we add none here.
+		 */
+		if (!si->signedAttrs) {
+			si->signedAttrs = sk_X509_ATTRIBUTE_new_null();
+			if (!si->signedAttrs)
+				goto merr;
+		}
+
+		if (!(flags & CMS_NOSMIMECAP)) {
+			STACK_OF(X509_ALGOR) *smcap = NULL;
+
+			i = CMS_add_standard_smimecap(&smcap);
+			if (i)
+			    i = CMS_add_smimecap(si, smcap);
+			sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+			if (!i)
+				goto merr;
+		}
+		if (flags & CMS_REUSE_DIGEST) {
+			if (!cms_copy_messageDigest(cms, si))
+				goto err;
+			if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) &&
+			    !CMS_SignerInfo_sign(si))
+				goto err;
+		}
+	}
+
+	if (!(flags & CMS_NOCERTS)) {
+		/* NB ignore -1 return for duplicate cert */
+		if (!CMS_add1_cert(cms, signer))
+			goto merr;
+	}
+
+	if (flags & CMS_KEY_PARAM) {
+		if (flags & CMS_NOATTR) {
+			si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL);
+			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)
+			goto err;
+	}
+
+	if (!sd->signerInfos)
+		sd->signerInfos = sk_CMS_SignerInfo_new_null();
+	if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si))
+		goto merr;
+
+	return si;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+ err:
+	ASN1_item_free((ASN1_VALUE *)si, &CMS_SignerInfo_it);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_add1_signer);
+
+static int
+cms_add1_signingTime(CMS_SignerInfo *si, ASN1_TIME *t)
+{
+	ASN1_TIME *tt;
+	int r = 0;
+
+	if (t)
+		tt = t;
+	else
+		tt = X509_gmtime_adj(NULL, 0);
+
+	if (!tt)
+		goto merr;
+
+	if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_signingTime,
+			                        tt->type, tt, -1) <= 0)
+		goto merr;
+
+	r = 1;
+
+ merr:
+	if (!t)
+		ASN1_TIME_free(tt);
+	if (!r)
+		CMSerror(ERR_R_MALLOC_FAILURE);
+
+	return r;
+}
+
+EVP_PKEY_CTX *
+CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si)
+{
+	return si->pctx;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get0_pkey_ctx);
+
+EVP_MD_CTX *
+CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si)
+{
+	return si->mctx;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get0_md_ctx);
+
+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;
+}
+LCRYPTO_ALIAS(CMS_get0_SignerInfos);
+
+STACK_OF(X509) *
+CMS_get0_signers(CMS_ContentInfo *cms)
+{
+	STACK_OF(X509) *signers = NULL;
+	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)) {
+				sk_X509_free(signers);
+				return NULL;
+			}
+		}
+	}
+
+	return signers;
+}
+LCRYPTO_ALIAS(CMS_get0_signers);
+
+void
+CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer)
+{
+	if (signer) {
+		X509_up_ref(signer);
+		EVP_PKEY_free(si->pkey);
+		si->pkey = X509_get_pubkey(signer);
+	}
+	X509_free(si->signer);
+	si->signer = signer;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_set1_signer_cert);
+
+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);
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get0_signer_id);
+
+int
+CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert)
+{
+	return cms_SignerIdentifier_cert_cmp(si->sid, cert);
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_cert_cmp);
+
+int
+CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *scerts,
+    unsigned int flags)
+{
+	CMS_SignedData *sd;
+	CMS_SignerInfo *si;
+	CMS_CertificateChoices *cch;
+	STACK_OF(CMS_CertificateChoices) *certs;
+	X509 *x;
+	int i, j;
+	int ret = 0;
+
+	sd = cms_get0_signed(cms);
+	if (!sd)
+		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)
+			continue;
+
+		for (j = 0; j < sk_X509_num(scerts); j++) {
+			x = sk_X509_value(scerts, j);
+			if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
+				CMS_SignerInfo_set1_signer_cert(si, x);
+				ret++;
+				break;
+			}
+		}
+
+		if (si->signer || (flags & CMS_NOINTERN))
+			continue;
+
+		for (j = 0; j < sk_CMS_CertificateChoices_num(certs); j++) {
+			cch = sk_CMS_CertificateChoices_value(certs, j);
+			if (cch->type != 0)
+				continue;
+			x = cch->d.certificate;
+			if (CMS_SignerInfo_cert_cmp(si, x) == 0) {
+				CMS_SignerInfo_set1_signer_cert(si, x);
+				ret++;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(CMS_set1_signers_certs);
+
+void
+CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer,
+X509_ALGOR **pdig, X509_ALGOR **psig)
+{
+	if (pk)
+		*pk = si->pkey;
+	if (signer)
+		*signer = si->signer;
+	if (pdig)
+		*pdig = si->digestAlgorithm;
+	if (psig)
+		*psig = si->signatureAlgorithm;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get0_algs);
+
+ASN1_OCTET_STRING *
+CMS_SignerInfo_get0_signature(CMS_SignerInfo *si)
+{
+	return si->signature;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_get0_signature);
+
+static int
+cms_SignerInfo_content_sign(CMS_ContentInfo *cms, CMS_SignerInfo *si, BIO *chain)
+{
+	EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+	int r = 0;
+	EVP_PKEY_CTX *pctx = NULL;
+
+	if (mctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	if (!si->pkey) {
+		CMSerror(CMS_R_NO_PRIVATE_KEY);
+		goto err;
+	}
+
+	if (!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))
+		goto err;
+
+	/*
+	 * If any signed attributes calculate and add messageDigest attribute
+	 */
+
+	if (CMS_signed_get_attr_count(si) >= 0) {
+		ASN1_OBJECT *ctype =
+		    cms->d.signedData->encapContentInfo->eContentType;
+		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,
+		    V_ASN1_OCTET_STRING, md, mdlen))
+			goto err;
+		/* Copy content type across */
+		if (CMS_signed_add1_attr_by_NID(si, NID_pkcs9_contentType,
+		    V_ASN1_OBJECT, ctype, -1) <= 0)
+			goto err;
+		if (!CMS_SignerInfo_sign(si))
+			goto err;
+	} else if (si->pctx) {
+		unsigned char *sig;
+		size_t siglen;
+		unsigned char md[EVP_MAX_MD_SIZE];
+		unsigned int mdlen;
+
+		pctx = si->pctx;
+		if (!EVP_DigestFinal_ex(mctx, md, &mdlen))
+			goto err;
+		siglen = EVP_PKEY_size(si->pkey);
+		sig = malloc(siglen);
+		if (sig == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (EVP_PKEY_sign(pctx, sig, &siglen, md, mdlen) <= 0) {
+			free(sig);
+			goto err;
+		}
+		ASN1_STRING_set0(si->signature, sig, siglen);
+	} else {
+		unsigned char *sig;
+		unsigned int siglen;
+
+		sig = malloc(EVP_PKEY_size(si->pkey));
+		if (sig == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!EVP_SignFinal(mctx, sig, &siglen, si->pkey)) {
+			CMSerror(CMS_R_SIGNFINAL_ERROR);
+			free(sig);
+			goto err;
+		}
+		ASN1_STRING_set0(si->signature, sig, siglen);
+	}
+
+	r = 1;
+
+ err:
+	EVP_MD_CTX_free(mctx);
+	EVP_PKEY_CTX_free(pctx);
+
+	return r;
+}
+
+int
+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);
+		if (!cms_SignerInfo_content_sign(cms, si, chain))
+			return 0;
+	}
+	cms->d.signedData->encapContentInfo->partial = 0;
+
+	return 1;
+}
+
+int
+CMS_SignerInfo_sign(CMS_SignerInfo *si)
+{
+	const EVP_MD *md;
+	unsigned char *buf = NULL, *sig = NULL;
+	int buf_len = 0;
+	size_t sig_len = 0;
+	int ret = 0;
+
+	if ((md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)) == NULL)
+		goto err;
+
+	if (CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1) < 0) {
+		if (!cms_add1_signingTime(si, NULL))
+			goto err;
+	}
+
+	if (si->pctx == NULL) {
+		EVP_MD_CTX_reset(si->mctx);
+		if (!EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, si->pkey))
+			goto err;
+	}
+
+	if (EVP_PKEY_CTX_ctrl(si->pctx, -1, EVP_PKEY_OP_SIGN,
+	    EVP_PKEY_CTRL_CMS_SIGN, 0, si) <= 0) {
+		CMSerror(CMS_R_CTRL_ERROR);
+		goto err;
+	}
+
+	if ((buf_len = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &buf,
+	    &CMS_Attributes_Sign_it)) <= 0) {
+		buf_len = 0;
+		goto err;
+	}
+	if (!EVP_DigestSign(si->mctx, NULL, &sig_len, buf, buf_len))
+		goto err;
+	if ((sig = calloc(1, sig_len)) == NULL)
+		goto err;
+	if (!EVP_DigestSign(si->mctx, sig, &sig_len, buf, buf_len))
+		goto err;
+
+	if (EVP_PKEY_CTX_ctrl(si->pctx, -1, EVP_PKEY_OP_SIGN,
+	    EVP_PKEY_CTRL_CMS_SIGN, 1, si) <= 0) {
+		CMSerror(CMS_R_CTRL_ERROR);
+		goto err;
+	}
+
+	ASN1_STRING_set0(si->signature, sig, sig_len);
+	sig = NULL;
+
+	ret = 1;
+
+ err:
+	if (si->mctx != NULL)
+		EVP_MD_CTX_reset(si->mctx);
+	freezero(buf, buf_len);
+	freezero(sig, sig_len);
+
+	return ret;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_sign);
+
+int
+CMS_SignerInfo_verify(CMS_SignerInfo *si)
+{
+	const EVP_MD *md;
+	unsigned char *buf = NULL;
+	int buf_len = 0;
+	int ret = -1;
+
+	if ((md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm)) == NULL)
+		goto err;
+
+	if (si->pkey == NULL) {
+		CMSerror(CMS_R_NO_PUBLIC_KEY);
+		goto err;
+	}
+
+	if (si->mctx == NULL)
+		si->mctx = EVP_MD_CTX_new();
+	if (si->mctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_DigestVerifyInit(si->mctx, &si->pctx, md, NULL, si->pkey) <= 0)
+		goto err;
+
+	if (!cms_sd_asn1_ctrl(si, 1))
+		goto err;
+
+	if ((buf_len = ASN1_item_i2d((ASN1_VALUE *)si->signedAttrs, &buf,
+	    &CMS_Attributes_Verify_it)) <= 0) {
+		buf_len = 0;
+		goto err;
+	}
+
+	ret = EVP_DigestVerify(si->mctx, si->signature->data, si->signature->length,
+	    buf, buf_len);
+	if (ret <= 0) {
+		CMSerror(CMS_R_VERIFICATION_FAILURE);
+		goto err;
+	}
+
+ err:
+	if (si->mctx != NULL)
+		EVP_MD_CTX_reset(si->mctx);
+	freezero(buf, buf_len);
+
+	return ret;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_verify);
+
+/* Create a chain of digest BIOs from a CMS ContentInfo */
+
+BIO *
+cms_SignedData_init_bio(CMS_ContentInfo *cms)
+{
+	int i;
+	CMS_SignedData *sd;
+	BIO *chain = NULL;
+
+	sd = cms_get0_signed(cms);
+	if (!sd)
+		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)
+			goto err;
+		if (chain)
+			BIO_push(chain, mdbio);
+		else
+			chain = mdbio;
+	}
+
+	return chain;
+
+ err:
+	BIO_free_all(chain);
+
+	return NULL;
+}
+
+int
+CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
+{
+	ASN1_OCTET_STRING *os = NULL;
+	EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+	EVP_PKEY_CTX *pkctx = NULL;
+	int r = -1;
+	unsigned char mval[EVP_MAX_MD_SIZE];
+	unsigned int mlen;
+
+	if (mctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	/* If we have any signed attributes look for messageDigest value */
+	if (CMS_signed_get_attr_count(si) >= 0) {
+		os = CMS_signed_get0_data_by_OBJ(si,
+		    OBJ_nid2obj(NID_pkcs9_messageDigest), -3,
+		    V_ASN1_OCTET_STRING);
+		if (!os) {
+			CMSerror(CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE);
+			goto err;
+		}
+	}
+
+	if (!cms_DigestAlgorithm_find_ctx(mctx, chain, si->digestAlgorithm))
+		goto err;
+
+	if (EVP_DigestFinal_ex(mctx, mval, &mlen) <= 0) {
+		CMSerror(CMS_R_UNABLE_TO_FINALIZE_CONTEXT);
+		goto err;
+	}
+
+	/* If messageDigest found compare it */
+
+	if (os) {
+		if (mlen != (unsigned int)os->length) {
+			CMSerror(CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH);
+			goto err;
+		}
+
+		if (memcmp(mval, os->data, mlen)) {
+			CMSerror(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);
+		if (pkctx == NULL)
+			goto err;
+		if (EVP_PKEY_verify_init(pkctx) <= 0)
+			goto err;
+		if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
+			goto err;
+		si->pctx = pkctx;
+		if (!cms_sd_asn1_ctrl(si, 1))
+			goto err;
+		r = EVP_PKEY_verify(pkctx, si->signature->data,
+			                si->signature->length, mval, mlen);
+		if (r <= 0) {
+			CMSerror(CMS_R_VERIFICATION_FAILURE);
+			r = 0;
+		}
+	}
+
+ err:
+	EVP_PKEY_CTX_free(pkctx);
+	EVP_MD_CTX_free(mctx);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_SignerInfo_verify_content);
+
+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;
+	r = CMS_signed_add1_attr_by_NID(si, NID_SMIMECapabilities,
+	    V_ASN1_SEQUENCE, smder, smderlen);
+	free(smder);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_add_smimecap);
+
+int
+CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, int algnid, int keysize)
+{
+	X509_ALGOR *alg;
+	ASN1_INTEGER *key = NULL;
+
+	if (keysize > 0) {
+		if ((key = ASN1_INTEGER_new()) == NULL)
+			return 0;
+		if (!ASN1_INTEGER_set(key, keysize)) {
+			ASN1_INTEGER_free(key);
+			return 0;
+		}
+	}
+	alg = X509_ALGOR_new();
+	if (alg == NULL) {
+		ASN1_INTEGER_free(key);
+		return 0;
+	}
+
+	X509_ALGOR_set0(alg, OBJ_nid2obj(algnid),
+	    key ? V_ASN1_INTEGER : V_ASN1_UNDEF, key);
+	if (*algs == NULL)
+		*algs = sk_X509_ALGOR_new_null();
+	if (*algs == NULL || !sk_X509_ALGOR_push(*algs, alg)) {
+		X509_ALGOR_free(alg);
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_add_simple_smimecap);
+
+/* Check to see if a cipher exists and if so add S/MIME capabilities */
+
+static int
+cms_add_cipher_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
+{
+	if (EVP_get_cipherbynid(nid))
+		return CMS_add_simple_smimecap(sk, nid, arg);
+	return 1;
+}
+
+static int
+cms_add_digest_smcap(STACK_OF(X509_ALGOR) **sk, int nid, int arg)
+{
+	if (EVP_get_digestbynid(nid))
+		return CMS_add_simple_smimecap(sk, nid, arg);
+	return 1;
+}
+
+int
+CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap)
+{
+	if (!cms_add_cipher_smcap(smcap, NID_aes_256_cbc, -1) ||
+	    !cms_add_digest_smcap(smcap, NID_id_GostR3411_94, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_aes_192_cbc, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_aes_128_cbc, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 128) ||
+	    !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 64) ||
+	    !cms_add_cipher_smcap(smcap, NID_des_cbc, -1) ||
+	    !cms_add_cipher_smcap(smcap, NID_rc2_cbc, 40))
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(CMS_add_standard_smimecap);
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
new file mode 100644
index 0000000..b293001
--- /dev/null
+++ b/crypto/cms/cms_smime.c
@@ -0,0 +1,901 @@
+/* $OpenBSD: cms_smime.c,v 1.27 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include "cryptlib.h"
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cms_local.h"
+#include "asn1/asn1_local.h"
+
+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) {
+		rbio = BIO_new(BIO_s_mem());
+		BIO_set_mem_eof_return(rbio, 0);
+	} else
+		rbio = out;
+
+	return rbio;
+}
+
+static int
+cms_copy_content(BIO *out, BIO *in, unsigned int flags)
+{
+	unsigned char buf[4096];
+	int r = 0, i;
+	BIO *tmpout;
+
+	tmpout = cms_get_text_bio(out, flags);
+
+	if (tmpout == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* Read all content through chain to process digest, decrypt etc */
+	for (;;) {
+		i = BIO_read(in, buf, sizeof(buf));
+		if (i <= 0) {
+			if (BIO_method_type(in) == BIO_TYPE_CIPHER) {
+				if (!BIO_get_cipher_status(in))
+					goto err;
+			}
+			if (i < 0)
+				goto err;
+			break;
+		}
+
+		if (tmpout && (BIO_write(tmpout, buf, i) != i))
+			goto err;
+	}
+
+	if (flags & CMS_TEXT) {
+		if (!SMIME_text(tmpout, out)) {
+			CMSerror(CMS_R_SMIME_TEXT_ERROR);
+			goto err;
+		}
+	}
+
+	r = 1;
+
+ err:
+	if (tmpout != out)
+		BIO_free(tmpout);
+
+	return r;
+}
+
+static int
+check_content(CMS_ContentInfo *cms)
+{
+	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
+
+	if (!pos || !*pos) {
+		CMSerror(CMS_R_NO_CONTENT);
+		return 0;
+	}
+
+	return 1;
+}
+
+static void
+do_free_upto(BIO *f, BIO *upto)
+{
+	if (upto) {
+		BIO *tbio;
+		do {
+			tbio = BIO_pop(f);
+			BIO_free(f);
+			f = tbio;
+		}
+		while (f && 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) {
+		CMSerror(CMS_R_TYPE_NOT_DATA);
+		return 0;
+	}
+	cont = CMS_dataInit(cms, NULL);
+	if (!cont)
+		return 0;
+	r = cms_copy_content(out, cont, flags);
+	BIO_free_all(cont);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_data);
+
+CMS_ContentInfo *
+CMS_data_create(BIO *in, unsigned int flags)
+{
+	CMS_ContentInfo *cms;
+
+	cms = cms_Data_create();
+	if (!cms)
+		return NULL;
+
+	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
+		return cms;
+
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_data_create);
+
+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) {
+		CMSerror(CMS_R_TYPE_NOT_DIGESTED_DATA);
+		return 0;
+	}
+
+	if (!dcont && !check_content(cms))
+		return 0;
+
+	cont = CMS_dataInit(cms, dcont);
+	if (!cont)
+		return 0;
+	r = cms_copy_content(out, cont, flags);
+	if (r)
+		r = cms_DigestedData_do_final(cms, cont, 1);
+	do_free_upto(cont, dcont);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_digest_verify);
+
+CMS_ContentInfo *
+CMS_digest_create(BIO *in, const EVP_MD *md, unsigned int flags)
+{
+	CMS_ContentInfo *cms;
+
+	if (!md)
+		md = EVP_sha1();
+	cms = cms_DigestedData_create(md);
+	if (!cms)
+		return NULL;
+
+	if (!(flags & CMS_DETACHED))
+		CMS_set_detached(cms, 0);
+
+	if ((flags & CMS_STREAM) || CMS_final(cms, in, NULL, flags))
+		return cms;
+
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_digest_create);
+
+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) {
+		CMSerror(CMS_R_TYPE_NOT_ENCRYPTED_DATA);
+		return 0;
+	}
+
+	if (!dcont && !check_content(cms))
+		return 0;
+
+	if (CMS_EncryptedData_set1_key(cms, NULL, key, keylen) <= 0)
+		return 0;
+	cont = CMS_dataInit(cms, dcont);
+	if (!cont)
+		return 0;
+	r = cms_copy_content(out, cont, flags);
+	do_free_upto(cont, dcont);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_EncryptedData_decrypt);
+
+CMS_ContentInfo *
+CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher,
+    const unsigned char *key, size_t keylen, unsigned int flags)
+{
+	CMS_ContentInfo *cms;
+
+	if (!cipher) {
+		CMSerror(CMS_R_NO_CIPHER);
+		return NULL;
+	}
+	cms = CMS_ContentInfo_new();
+	if (cms == NULL)
+		return NULL;
+	if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
+		return NULL;
+
+	if (!(flags & CMS_DETACHED))
+		CMS_set_detached(cms, 0);
+
+	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
+	    CMS_final(cms, in, NULL, flags))
+		return cms;
+
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_EncryptedData_encrypt);
+
+static int
+cms_signerinfo_verify_cert(CMS_SignerInfo *si, X509_STORE *store,
+    STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls)
+{
+	X509_STORE_CTX *ctx = X509_STORE_CTX_new();
+	X509 *signer;
+	int i, j, r = 0;
+
+	if (ctx == NULL) {
+		CMSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
+	if (!X509_STORE_CTX_init(ctx, store, signer, certs)) {
+		CMSerror(CMS_R_STORE_INIT_ERROR);
+		goto err;
+	}
+	X509_STORE_CTX_set_default(ctx, "smime_sign");
+	if (crls)
+		X509_STORE_CTX_set0_crls(ctx, crls);
+
+	i = X509_verify_cert(ctx);
+	if (i <= 0) {
+		j = X509_STORE_CTX_get_error(ctx);
+		CMSerror(CMS_R_CERTIFICATE_VERIFY_ERROR);
+		ERR_asprintf_error_data("Verify error: %s",
+		    X509_verify_cert_error_string(j));
+		goto err;
+	}
+	r = 1;
+
+ err:
+	X509_STORE_CTX_free(ctx);
+
+	return r;
+}
+
+int
+CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, X509_STORE *store,
+    BIO *dcont, BIO *out, unsigned int flags)
+{
+	CMS_SignerInfo *si;
+	STACK_OF(CMS_SignerInfo) *sinfos;
+	STACK_OF(X509) *cms_certs = NULL;
+	STACK_OF(X509_CRL) *crls = NULL;
+	X509 *signer;
+	int i, scount = 0, ret = 0;
+	BIO *cmsbio = NULL, *tmpin = NULL, *tmpout = NULL;
+
+	if (!dcont && !check_content(cms))
+		return 0;
+	if (dcont && !(flags & CMS_BINARY)) {
+		const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);
+		if (OBJ_obj2nid(coid) == NID_id_ct_asciiTextWithCRLF)
+			flags |= CMS_ASCIICRLF;
+	}
+
+	/* Attempt to find all signer certificates */
+
+	sinfos = CMS_get0_SignerInfos(cms);
+	if (sk_CMS_SignerInfo_num(sinfos) <= 0) {
+		CMSerror(CMS_R_NO_SIGNERS);
+		goto err;
+	}
+
+	for (i = 0; i < sk_CMS_SignerInfo_num(sinfos); i++) {
+		si = sk_CMS_SignerInfo_value(sinfos, i);
+		CMS_SignerInfo_get0_algs(si, NULL, &signer, NULL, NULL);
+		if (signer)
+			scount++;
+	}
+
+	if (scount != sk_CMS_SignerInfo_num(sinfos))
+		scount += CMS_set1_signers_certs(cms, certs, flags);
+
+	if (scount != sk_CMS_SignerInfo_num(sinfos)) {
+		CMSerror(CMS_R_SIGNER_CERTIFICATE_NOT_FOUND);
+		goto err;
+	}
+
+	/* Attempt to verify all signers certs */
+
+	if (!(flags & CMS_NO_SIGNER_CERT_VERIFY)) {
+		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++) {
+			si = sk_CMS_SignerInfo_value(sinfos, i);
+			if (!cms_signerinfo_verify_cert(si, store, cms_certs, crls))
+				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++) {
+			si = sk_CMS_SignerInfo_value(sinfos, i);
+			if (CMS_signed_get_attr_count(si) < 0)
+				continue;
+			if (CMS_SignerInfo_verify(si) <= 0)
+				goto err;
+		}
+	}
+
+	/*
+	 * Performance optimization: if the content is a memory BIO then store
+	 * its contents in a temporary read only memory BIO. This avoids
+	 * potentially large numbers of slow copies of data which will occur when
+	 * reading from a read write memory BIO when signatures are calculated.
+	 */
+
+	if (dcont && (BIO_method_type(dcont) == BIO_TYPE_MEM)) {
+		char *ptr;
+		long len;
+
+		len = BIO_get_mem_data(dcont, &ptr);
+		tmpin = BIO_new_mem_buf(ptr, len);
+		if (tmpin == NULL) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err2;
+		}
+	} else
+		tmpin = dcont;
+
+	/*
+	 * If not binary mode and detached generate digests by *writing* through
+	 * the BIO. That makes it possible to canonicalise the input.
+	 */
+	if (!(flags & SMIME_BINARY) && dcont) {
+		/*
+		 * Create output BIO so we can either handle text or to ensure
+		 * included content doesn't override detached content.
+		 */
+		tmpout = cms_get_text_bio(out, flags);
+		if (!tmpout) {
+			CMSerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		cmsbio = CMS_dataInit(cms, tmpout);
+		if (!cmsbio)
+			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 (flags & CMS_TEXT) {
+			if (!SMIME_text(tmpout, out)) {
+				CMSerror(CMS_R_SMIME_TEXT_ERROR);
+				goto err;
+			}
+		}
+	} else {
+		cmsbio = CMS_dataInit(cms, tmpin);
+		if (!cmsbio)
+			goto err;
+
+		if (!cms_copy_content(out, cmsbio, flags))
+			goto err;
+
+	}
+	if (!(flags & CMS_NO_CONTENT_VERIFY)) {
+		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) {
+				CMSerror(CMS_R_CONTENT_VERIFY_ERROR);
+				goto err;
+			}
+		}
+	}
+
+	ret = 1;
+
+ err:
+	if (!(flags & SMIME_BINARY) && dcont) {
+		do_free_upto(cmsbio, tmpout);
+		if (tmpin != dcont)
+			BIO_free(tmpin);
+	} else {
+		if (dcont && (tmpin == dcont))
+			do_free_upto(cmsbio, dcont);
+		else
+			BIO_free_all(cmsbio);
+	}
+
+	if (out != tmpout)
+		BIO_free_all(tmpout);
+
+ err2:
+	sk_X509_pop_free(cms_certs, X509_free);
+	sk_X509_CRL_pop_free(crls, X509_CRL_free);
+
+	return ret;
+}
+LCRYPTO_ALIAS(CMS_verify);
+
+int
+CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms,
+    STACK_OF(X509) *certs, 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);
+}
+LCRYPTO_ALIAS(CMS_verify_receipt);
+
+CMS_ContentInfo *
+CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data,
+    unsigned int flags)
+{
+	CMS_ContentInfo *cms;
+	int i;
+
+	cms = CMS_ContentInfo_new();
+	if (cms == NULL || !CMS_SignedData_init(cms))
+		goto merr;
+	if (flags & CMS_ASCIICRLF &&
+	    !CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_ct_asciiTextWithCRLF)))
+		goto err;
+
+	if (pkey && !CMS_add1_signer(cms, signcert, pkey, NULL, flags)) {
+		CMSerror(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;
+	}
+
+	if (!(flags & CMS_DETACHED))
+		CMS_set_detached(cms, 0);
+
+	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
+	    CMS_final(cms, data, NULL, flags))
+		return cms;
+	else
+		goto err;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+
+ err:
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_sign);
+
+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;
+	BIO *rct_cont = NULL;
+	int r = 0;
+
+	flags &= ~(CMS_STREAM | CMS_TEXT);
+	/* Not really detached but avoids content being allocated */
+	flags |= CMS_PARTIAL | CMS_BINARY | CMS_DETACHED;
+	if (!pkey || !signcert) {
+		CMSerror(CMS_R_NO_KEY_OR_CERT);
+		return NULL;
+	}
+
+	/* Initialize signed data */
+
+	cms = CMS_sign(NULL, NULL, certs, NULL, flags);
+	if (!cms)
+		goto err;
+
+	/* Set inner content type to signed receipt */
+	if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt)))
+		goto err;
+
+	rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags);
+	if (!rct_si) {
+		CMSerror(CMS_R_ADD_SIGNER_ERROR);
+		goto err;
+	}
+
+	os = cms_encode_Receipt(si);
+	if (!os)
+		goto err;
+
+	/* Set content to digest */
+	rct_cont = BIO_new_mem_buf(os->data, os->length);
+	if (!rct_cont)
+		goto err;
+
+	/* Add msgSigDigest attribute */
+
+	if (!cms_msgSigDigest_add1(rct_si, si))
+		goto err;
+
+	/* Finalize structure */
+	if (!CMS_final(cms, rct_cont, NULL, flags))
+		goto err;
+
+	/* Set embedded content */
+	pos = CMS_get0_content(cms);
+	*pos = os;
+
+	r = 1;
+
+ err:
+	BIO_free(rct_cont);
+	if (r)
+		return cms;
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_sign_receipt);
+
+CMS_ContentInfo *
+CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher,
+    unsigned int flags)
+{
+	CMS_ContentInfo *cms;
+	int i;
+	X509 *recip;
+
+	cms = CMS_EnvelopedData_create(cipher);
+	if (!cms)
+		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)) {
+			CMSerror(CMS_R_RECIPIENT_ERROR);
+			goto err;
+		}
+	}
+
+	if (!(flags & CMS_DETACHED))
+		CMS_set_detached(cms, 0);
+
+	if ((flags & (CMS_STREAM | CMS_PARTIAL)) ||
+	    CMS_final(cms, data, NULL, flags))
+		return cms;
+	else
+		goto err;
+
+ merr:
+	CMSerror(ERR_R_MALLOC_FAILURE);
+ err:
+	CMS_ContentInfo_free(cms);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_encrypt);
+
+static int
+cms_kari_set1_pkey(CMS_ContentInfo *cms, CMS_RecipientInfo *ri, EVP_PKEY *pk,
+    X509 *cert)
+{
+	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);
+		rv = CMS_RecipientInfo_kari_decrypt(cms, ri, rek);
+		CMS_RecipientInfo_kari_set0_pkey(ri, NULL);
+		if (rv > 0)
+			return 1;
+		return cert == NULL ? 0 : -1;
+	}
+
+	return 0;
+}
+
+int
+CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert)
+{
+	STACK_OF(CMS_RecipientInfo) *ris;
+	CMS_RecipientInfo *ri;
+	int i, r, 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) {
+		CMSerror(CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+		return 0;
+	}
+
+	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+		ri = sk_CMS_RecipientInfo_value(ris, i);
+		if (CMS_RecipientInfo_type(ri) != ri_type)
+			continue;
+		match_ri = 1;
+		if (ri_type == CMS_RECIPINFO_AGREE) {
+			r = cms_kari_set1_pkey(cms, ri, pk, cert);
+			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)) {
+			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 not debugging clear any error and return success to
+				 * avoid leaking of information useful to MMA
+				 */
+				if (!debug) {
+					ERR_clear_error();
+					return 1;
+				}
+				if (r > 0)
+					return 1;
+				CMSerror(CMS_R_DECRYPT_ERROR);
+				return 0;
+			}
+			/*
+			 * If no cert and not debugging don't leave loop after first
+			 * successful decrypt. Always attempt to decrypt all recipients
+			 * to avoid leaking timing of a successful decrypt.
+			 */
+			else if (r > 0 && debug)
+				return 1;
+		}
+	}
+	/* If no cert, key transport and not debugging always return success */
+	if (cert == NULL && ri_type == CMS_RECIPINFO_TRANS && match_ri && !debug) {
+		ERR_clear_error();
+		return 1;
+	}
+
+	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
+
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_decrypt_set1_pkey);
+
+int
+CMS_decrypt_set1_key(CMS_ContentInfo *cms, unsigned char *key, size_t keylen,
+    const unsigned char *id, size_t idlen)
+{
+	STACK_OF(CMS_RecipientInfo) *ris;
+	CMS_RecipientInfo *ri;
+	int i, r;
+
+	ris = CMS_get0_RecipientInfos(cms);
+	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+		ri = sk_CMS_RecipientInfo_value(ris, i);
+		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)) {
+			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) {
+				CMSerror(CMS_R_DECRYPT_ERROR);
+				return 0;
+			}
+			ERR_clear_error();
+		}
+	}
+
+	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
+
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_decrypt_set1_key);
+
+int
+CMS_decrypt_set1_password(CMS_ContentInfo *cms, unsigned char *pass,
+    ssize_t passlen)
+{
+	STACK_OF(CMS_RecipientInfo) *ris;
+	CMS_RecipientInfo *ri;
+	int i, r;
+
+	ris = CMS_get0_RecipientInfos(cms);
+	for (i = 0; i < sk_CMS_RecipientInfo_num(ris); i++) {
+		ri = sk_CMS_RecipientInfo_value(ris, i);
+		if (CMS_RecipientInfo_type(ri) != CMS_RECIPINFO_PASS)
+			continue;
+		CMS_RecipientInfo_set0_password(ri, pass, passlen);
+		r = CMS_RecipientInfo_decrypt(cms, ri);
+		CMS_RecipientInfo_set0_password(ri, NULL, 0);
+		if (r > 0)
+			return 1;
+	}
+
+	CMSerror(CMS_R_NO_MATCHING_RECIPIENT);
+
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_decrypt_set1_password);
+
+int
+CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert, BIO *dcont,
+    BIO *out, unsigned int flags)
+{
+	int r;
+	BIO *cont;
+
+	if (OBJ_obj2nid(CMS_get0_type(cms)) != NID_pkcs7_enveloped) {
+		CMSerror(CMS_R_TYPE_NOT_ENVELOPED_DATA);
+		return 0;
+	}
+	if (!dcont && !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)
+		return 1;
+	if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
+		return 0;
+	cont = CMS_dataInit(cms, dcont);
+	if (!cont)
+		return 0;
+	r = cms_copy_content(out, cont, flags);
+	do_free_upto(cont, dcont);
+
+	return r;
+}
+LCRYPTO_ALIAS(CMS_decrypt);
+
+int
+CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags)
+{
+	BIO *cmsbio;
+	int ret = 0;
+
+	if ((cmsbio = CMS_dataInit(cms, dcont)) == NULL) {
+		CMSerror(CMS_R_CMS_LIB);
+		return 0;
+	}
+
+	SMIME_crlf_copy(data, cmsbio, flags);
+
+	(void)BIO_flush(cmsbio);
+
+	if (!CMS_dataFinal(cms, cmsbio)) {
+		CMSerror(CMS_R_CMS_DATAFINAL_ERROR);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	do_free_upto(cmsbio, dcont);
+
+	return ret;
+}
+LCRYPTO_ALIAS(CMS_final);
+
+int
+CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, unsigned int flags)
+{
+	CMSerror(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+	return 0;
+}
+LCRYPTO_ALIAS(CMS_uncompress);
+
+CMS_ContentInfo *
+CMS_compress(BIO *in, int comp_nid, unsigned int flags)
+{
+	CMSerror(CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+	return NULL;
+}
+LCRYPTO_ALIAS(CMS_compress);
diff --git a/crypto/compat/arc4random.c b/crypto/compat/arc4random.c
new file mode 100644
index 0000000..1ec8e1e
--- /dev/null
+++ b/crypto/compat/arc4random.c
@@ -0,0 +1,202 @@
+/*	$OpenBSD: arc4random.c,v 1.58 2022/07/31 13:41:45 tb Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * ChaCha based random number generator for OpenBSD.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define KEYSTREAM_ONLY
+#include "chacha_private.h"
+
+#define minimum(a, b) ((a) < (b) ? (a) : (b))
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+#define inline __inline
+#else				/* __GNUC__ || _MSC_VER */
+#define inline
+#endif				/* !__GNUC__ && !_MSC_VER */
+
+#define KEYSZ	32
+#define IVSZ	8
+#define BLOCKSZ	64
+#define RSBUFSZ	(16*BLOCKSZ)
+
+#define REKEY_BASE	(1024*1024) /* NB. should be a power of 2 */
+
+/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
+static struct _rs {
+	size_t		rs_have;	/* valid bytes at end of rs_buf */
+	size_t		rs_count;	/* bytes till reseed */
+} *rs;
+
+/* Maybe be preserved in fork children, if _rs_allocate() decides. */
+static struct _rsx {
+	chacha_ctx	rs_chacha;	/* chacha context for random keystream */
+	u_char		rs_buf[RSBUFSZ];	/* keystream blocks */
+} *rsx;
+
+static inline int _rs_allocate(struct _rs **, struct _rsx **);
+static inline void _rs_forkdetect(void);
+#include "arc4random.h"
+
+static inline void _rs_rekey(u_char *dat, size_t datlen);
+
+static inline void
+_rs_init(u_char *buf, size_t n)
+{
+	if (n < KEYSZ + IVSZ)
+		return;
+
+	if (rs == NULL) {
+		if (_rs_allocate(&rs, &rsx) == -1)
+			_exit(1);
+	}
+
+	chacha_keysetup(&rsx->rs_chacha, buf, KEYSZ * 8);
+	chacha_ivsetup(&rsx->rs_chacha, buf + KEYSZ);
+}
+
+static void
+_rs_stir(void)
+{
+	u_char rnd[KEYSZ + IVSZ];
+	uint32_t rekey_fuzz = 0;
+
+	if (getentropy(rnd, sizeof rnd) == -1)
+		_getentropy_fail();
+
+	if (!rs)
+		_rs_init(rnd, sizeof(rnd));
+	else
+		_rs_rekey(rnd, sizeof(rnd));
+	explicit_bzero(rnd, sizeof(rnd));	/* discard source seed */
+
+	/* invalidate rs_buf */
+	rs->rs_have = 0;
+	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+
+	/* rekey interval should not be predictable */
+	chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
+	    (uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
+	rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
+}
+
+static inline void
+_rs_stir_if_needed(size_t len)
+{
+	_rs_forkdetect();
+	if (!rs || rs->rs_count <= len)
+		_rs_stir();
+	if (rs->rs_count <= len)
+		rs->rs_count = 0;
+	else
+		rs->rs_count -= len;
+}
+
+static inline void
+_rs_rekey(u_char *dat, size_t datlen)
+{
+#ifndef KEYSTREAM_ONLY
+	memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
+#endif
+	/* fill rs_buf with the keystream */
+	chacha_encrypt_bytes(&rsx->rs_chacha, rsx->rs_buf,
+	    rsx->rs_buf, sizeof(rsx->rs_buf));
+	/* mix in optional user provided data */
+	if (dat) {
+		size_t i, m;
+
+		m = minimum(datlen, KEYSZ + IVSZ);
+		for (i = 0; i < m; i++)
+			rsx->rs_buf[i] ^= dat[i];
+	}
+	/* immediately reinit for backtracking resistance */
+	_rs_init(rsx->rs_buf, KEYSZ + IVSZ);
+	memset(rsx->rs_buf, 0, KEYSZ + IVSZ);
+	rs->rs_have = sizeof(rsx->rs_buf) - KEYSZ - IVSZ;
+}
+
+static inline void
+_rs_random_buf(void *_buf, size_t n)
+{
+	u_char *buf = (u_char *)_buf;
+	u_char *keystream;
+	size_t m;
+
+	_rs_stir_if_needed(n);
+	while (n > 0) {
+		if (rs->rs_have > 0) {
+			m = minimum(n, rs->rs_have);
+			keystream = rsx->rs_buf + sizeof(rsx->rs_buf)
+			    - rs->rs_have;
+			memcpy(buf, keystream, m);
+			memset(keystream, 0, m);
+			buf += m;
+			n -= m;
+			rs->rs_have -= m;
+		}
+		if (rs->rs_have == 0)
+			_rs_rekey(NULL, 0);
+	}
+}
+
+static inline void
+_rs_random_u32(uint32_t *val)
+{
+	u_char *keystream;
+
+	_rs_stir_if_needed(sizeof(*val));
+	if (rs->rs_have < sizeof(*val))
+		_rs_rekey(NULL, 0);
+	keystream = rsx->rs_buf + sizeof(rsx->rs_buf) - rs->rs_have;
+	memcpy(val, keystream, sizeof(*val));
+	memset(keystream, 0, sizeof(*val));
+	rs->rs_have -= sizeof(*val);
+}
+
+uint32_t
+arc4random(void)
+{
+	uint32_t val;
+
+	_ARC4_LOCK();
+	_rs_random_u32(&val);
+	_ARC4_UNLOCK();
+	return val;
+}
+
+void
+arc4random_buf(void *buf, size_t n)
+{
+	_ARC4_LOCK();
+	_rs_random_buf(buf, n);
+	_ARC4_UNLOCK();
+}
diff --git a/crypto/compat/arc4random_aix.h b/crypto/compat/arc4random_aix.h
new file mode 100644
index 0000000..3142a1f
--- /dev/null
+++ b/crypto/compat/arc4random_aix.h
@@ -0,0 +1,81 @@
+/*	$OpenBSD: arc4random_aix.h,v 1.2 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_freebsd.h b/crypto/compat/arc4random_freebsd.h
new file mode 100644
index 0000000..3faa5e4
--- /dev/null
+++ b/crypto/compat/arc4random_freebsd.h
@@ -0,0 +1,87 @@
+/*	$OpenBSD: arc4random_freebsd.h,v 1.4 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+/*
+ * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
+ * a program does not link to -lthr. Callbacks registered with pthread_atfork()
+ * appear to fail silently. So, it is not always possible to detect a PID
+ * wraparound.
+ */
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_hpux.h b/crypto/compat/arc4random_hpux.h
new file mode 100644
index 0000000..2a3fe8c
--- /dev/null
+++ b/crypto/compat/arc4random_hpux.h
@@ -0,0 +1,81 @@
+/*	$OpenBSD: arc4random_hpux.h,v 1.3 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_linux.h b/crypto/compat/arc4random_linux.h
new file mode 100644
index 0000000..5e1cf34
--- /dev/null
+++ b/crypto/compat/arc4random_linux.h
@@ -0,0 +1,88 @@
+/*	$OpenBSD: arc4random_linux.h,v 1.12 2019/07/11 10:37:28 inoguchi Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#if defined(__GLIBC__) && !(defined(__UCLIBC__) && !defined(__ARCH_USE_MMU__))
+extern void *__dso_handle;
+extern int __register_atfork(void (*)(void), void(*)(void), void (*)(void), void *);
+#define _ARC4_ATFORK(f) __register_atfork(NULL, NULL, (f), __dso_handle)
+#else
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+#endif
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+        /* XXX unusual calls to clone() can bypass checks */
+	if (_rs_pid == 0 || _rs_pid == 1 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_netbsd.h b/crypto/compat/arc4random_netbsd.h
new file mode 100644
index 0000000..611997d
--- /dev/null
+++ b/crypto/compat/arc4random_netbsd.h
@@ -0,0 +1,87 @@
+/*	$OpenBSD: arc4random_netbsd.h,v 1.3 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+/*
+ * Unfortunately, pthread_atfork() is broken on FreeBSD (at least 9 and 10) if
+ * a program does not link to -lthr. Callbacks registered with pthread_atfork()
+ * appear to fail silently. So, it is not always possible to detect a PID
+ * wraparound.
+ */
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_osx.h b/crypto/compat/arc4random_osx.h
new file mode 100644
index 0000000..818ae6b
--- /dev/null
+++ b/crypto/compat/arc4random_osx.h
@@ -0,0 +1,81 @@
+/*	$OpenBSD: arc4random_osx.h,v 1.11 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_solaris.h b/crypto/compat/arc4random_solaris.h
new file mode 100644
index 0000000..b1084cd
--- /dev/null
+++ b/crypto/compat/arc4random_solaris.h
@@ -0,0 +1,81 @@
+/*	$OpenBSD: arc4random_solaris.h,v 1.10 2016/06/30 12:19:51 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+#include 
+#include 
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+#define _ARC4_LOCK()   pthread_mutex_lock(&arc4random_mtx)
+#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
+
+#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f))
+
+static inline void
+_getentropy_fail(void)
+{
+	raise(SIGKILL);
+}
+
+static volatile sig_atomic_t _rs_forked;
+
+static inline void
+_rs_forkhandler(void)
+{
+	_rs_forked = 1;
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+	static pid_t _rs_pid = 0;
+	pid_t pid = getpid();
+
+	if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
+		_rs_pid = pid;
+		_rs_forked = 0;
+		if (rs)
+			memset(rs, 0, sizeof(*rs));
+	}
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
+		return (-1);
+
+	if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
+	    MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
+		munmap(*rsp, sizeof(**rsp));
+		*rsp = NULL;
+		return (-1);
+	}
+
+	_ARC4_ATFORK(_rs_forkhandler);
+	return (0);
+}
diff --git a/crypto/compat/arc4random_uniform.c b/crypto/compat/arc4random_uniform.c
new file mode 100644
index 0000000..06cd29c
--- /dev/null
+++ b/crypto/compat/arc4random_uniform.c
@@ -0,0 +1,56 @@
+/*	$OpenBSD: arc4random_uniform.c,v 1.3 2019/01/20 02:59:07 bcook Exp $	*/
+
+/*
+ * Copyright (c) 2008, Damien Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound).  This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+uint32_t
+arc4random_uniform(uint32_t upper_bound)
+{
+	uint32_t r, min;
+
+	if (upper_bound < 2)
+		return 0;
+
+	/* 2**32 % x == (2**32 - x) % x */
+	min = -upper_bound % upper_bound;
+
+	/*
+	 * This could theoretically loop forever but each retry has
+	 * p > 0.5 (worst case, usually far better) of selecting a
+	 * number inside the range we need, so it should rarely need
+	 * to re-roll.
+	 */
+	for (;;) {
+		r = arc4random();
+		if (r >= min)
+			break;
+	}
+
+	return r % upper_bound;
+}
diff --git a/crypto/compat/arc4random_win.h b/crypto/compat/arc4random_win.h
new file mode 100644
index 0000000..deec8a1
--- /dev/null
+++ b/crypto/compat/arc4random_win.h
@@ -0,0 +1,78 @@
+/*	$OpenBSD: arc4random_win.h,v 1.6 2016/06/30 12:17:29 bcook Exp $	*/
+
+/*
+ * Copyright (c) 1996, David Mazieres 
+ * Copyright (c) 2008, Damien Miller 
+ * Copyright (c) 2013, Markus Friedl 
+ * Copyright (c) 2014, Theo de Raadt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Stub functions for portability.
+ */
+
+#include 
+
+static volatile HANDLE arc4random_mtx = NULL;
+
+/*
+ * Initialize the mutex on the first lock attempt. On collision, each thread
+ * will attempt to allocate a mutex and compare-and-swap it into place as the
+ * global mutex. On failure to swap in the global mutex, the mutex is closed.
+ */
+#define _ARC4_LOCK() { \
+	if (!arc4random_mtx) { \
+		HANDLE p = CreateMutex(NULL, FALSE, NULL); \
+		if (InterlockedCompareExchangePointer((void **)&arc4random_mtx, (void *)p, NULL)) \
+			CloseHandle(p); \
+	} \
+	WaitForSingleObject(arc4random_mtx, INFINITE); \
+} \
+
+#define _ARC4_UNLOCK() ReleaseMutex(arc4random_mtx)
+
+static inline void
+_getentropy_fail(void)
+{
+	TerminateProcess(GetCurrentProcess(), 0);
+}
+
+static inline int
+_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
+{
+	*rsp = VirtualAlloc(NULL, sizeof(**rsp),
+	    MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+	if (*rsp == NULL)
+		return (-1);
+
+	*rsxp = VirtualAlloc(NULL, sizeof(**rsxp),
+	    MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+	if (*rsxp == NULL) {
+		VirtualFree(*rsp, 0, MEM_RELEASE);
+		*rsp = NULL;
+		return (-1);
+	}
+	return (0);
+}
+
+static inline void
+_rs_forkhandler(void)
+{
+}
+
+static inline void
+_rs_forkdetect(void)
+{
+}
diff --git a/crypto/compat/chacha_private.h b/crypto/compat/chacha_private.h
new file mode 100644
index 0000000..b0427b6
--- /dev/null
+++ b/crypto/compat/chacha_private.h
@@ -0,0 +1,222 @@
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+/* $OpenBSD: chacha_private.h,v 1.3 2022/02/28 21:56:29 dtucker Exp $ */
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+typedef struct
+{
+  u32 input[16]; /* could be compressed */
+} chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((u8)(v) & U8C(0xFF))
+#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+  (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+  (((u32)((p)[0])      ) | \
+   ((u32)((p)[1]) <<  8) | \
+   ((u32)((p)[2]) << 16) | \
+   ((u32)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+  do { \
+    (p)[0] = U8V((v)      ); \
+    (p)[1] = U8V((v) >>  8); \
+    (p)[2] = U8V((v) >> 16); \
+    (p)[3] = U8V((v) >> 24); \
+  } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+static void
+chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits)
+{
+  const char *constants;
+
+  x->input[4] = U8TO32_LITTLE(k + 0);
+  x->input[5] = U8TO32_LITTLE(k + 4);
+  x->input[6] = U8TO32_LITTLE(k + 8);
+  x->input[7] = U8TO32_LITTLE(k + 12);
+  if (kbits == 256) { /* recommended */
+    k += 16;
+    constants = sigma;
+  } else { /* kbits == 128 */
+    constants = tau;
+  }
+  x->input[8] = U8TO32_LITTLE(k + 0);
+  x->input[9] = U8TO32_LITTLE(k + 4);
+  x->input[10] = U8TO32_LITTLE(k + 8);
+  x->input[11] = U8TO32_LITTLE(k + 12);
+  x->input[0] = U8TO32_LITTLE(constants + 0);
+  x->input[1] = U8TO32_LITTLE(constants + 4);
+  x->input[2] = U8TO32_LITTLE(constants + 8);
+  x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+static void
+chacha_ivsetup(chacha_ctx *x,const u8 *iv)
+{
+  x->input[12] = 0;
+  x->input[13] = 0;
+  x->input[14] = U8TO32_LITTLE(iv + 0);
+  x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+static void
+chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
+{
+  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+  u8 *ctarget = NULL;
+  u8 tmp[64];
+  u_int i;
+
+  if (!bytes) return;
+
+  j0 = x->input[0];
+  j1 = x->input[1];
+  j2 = x->input[2];
+  j3 = x->input[3];
+  j4 = x->input[4];
+  j5 = x->input[5];
+  j6 = x->input[6];
+  j7 = x->input[7];
+  j8 = x->input[8];
+  j9 = x->input[9];
+  j10 = x->input[10];
+  j11 = x->input[11];
+  j12 = x->input[12];
+  j13 = x->input[13];
+  j14 = x->input[14];
+  j15 = x->input[15];
+
+  for (;;) {
+    if (bytes < 64) {
+      for (i = 0;i < bytes;++i) tmp[i] = m[i];
+      m = tmp;
+      ctarget = c;
+      c = tmp;
+    }
+    x0 = j0;
+    x1 = j1;
+    x2 = j2;
+    x3 = j3;
+    x4 = j4;
+    x5 = j5;
+    x6 = j6;
+    x7 = j7;
+    x8 = j8;
+    x9 = j9;
+    x10 = j10;
+    x11 = j11;
+    x12 = j12;
+    x13 = j13;
+    x14 = j14;
+    x15 = j15;
+    for (i = 20;i > 0;i -= 2) {
+      QUARTERROUND( x0, x4, x8,x12)
+      QUARTERROUND( x1, x5, x9,x13)
+      QUARTERROUND( x2, x6,x10,x14)
+      QUARTERROUND( x3, x7,x11,x15)
+      QUARTERROUND( x0, x5,x10,x15)
+      QUARTERROUND( x1, x6,x11,x12)
+      QUARTERROUND( x2, x7, x8,x13)
+      QUARTERROUND( x3, x4, x9,x14)
+    }
+    x0 = PLUS(x0,j0);
+    x1 = PLUS(x1,j1);
+    x2 = PLUS(x2,j2);
+    x3 = PLUS(x3,j3);
+    x4 = PLUS(x4,j4);
+    x5 = PLUS(x5,j5);
+    x6 = PLUS(x6,j6);
+    x7 = PLUS(x7,j7);
+    x8 = PLUS(x8,j8);
+    x9 = PLUS(x9,j9);
+    x10 = PLUS(x10,j10);
+    x11 = PLUS(x11,j11);
+    x12 = PLUS(x12,j12);
+    x13 = PLUS(x13,j13);
+    x14 = PLUS(x14,j14);
+    x15 = PLUS(x15,j15);
+
+#ifndef KEYSTREAM_ONLY
+    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+#endif
+
+    j12 = PLUSONE(j12);
+    if (!j12) {
+      j13 = PLUSONE(j13);
+      /* stopping at 2^70 bytes per nonce is user's responsibility */
+    }
+
+    U32TO8_LITTLE(c + 0,x0);
+    U32TO8_LITTLE(c + 4,x1);
+    U32TO8_LITTLE(c + 8,x2);
+    U32TO8_LITTLE(c + 12,x3);
+    U32TO8_LITTLE(c + 16,x4);
+    U32TO8_LITTLE(c + 20,x5);
+    U32TO8_LITTLE(c + 24,x6);
+    U32TO8_LITTLE(c + 28,x7);
+    U32TO8_LITTLE(c + 32,x8);
+    U32TO8_LITTLE(c + 36,x9);
+    U32TO8_LITTLE(c + 40,x10);
+    U32TO8_LITTLE(c + 44,x11);
+    U32TO8_LITTLE(c + 48,x12);
+    U32TO8_LITTLE(c + 52,x13);
+    U32TO8_LITTLE(c + 56,x14);
+    U32TO8_LITTLE(c + 60,x15);
+
+    if (bytes <= 64) {
+      if (bytes < 64) {
+        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+      }
+      x->input[12] = j12;
+      x->input[13] = j13;
+      return;
+    }
+    bytes -= 64;
+    c += 64;
+#ifndef KEYSTREAM_ONLY
+    m += 64;
+#endif
+  }
+}
diff --git a/crypto/compat/explicit_bzero.c b/crypto/compat/explicit_bzero.c
new file mode 100644
index 0000000..5dd0103
--- /dev/null
+++ b/crypto/compat/explicit_bzero.c
@@ -0,0 +1,19 @@
+/*	$OpenBSD: explicit_bzero.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
+/*
+ * Public domain.
+ * Written by Matthew Dempsky.
+ */
+
+#include 
+
+__attribute__((weak)) void
+__explicit_bzero_hook(void *buf, size_t len)
+{
+}
+
+void
+explicit_bzero(void *buf, size_t len)
+{
+	memset(buf, 0, len);
+	__explicit_bzero_hook(buf, len);
+}
diff --git a/crypto/compat/getentropy_aix.c b/crypto/compat/getentropy_aix.c
new file mode 100644
index 0000000..9d085cf
--- /dev/null
+++ b/crypto/compat/getentropy_aix.c
@@ -0,0 +1,402 @@
+/*	$OpenBSD: getentropy_aix.c,v 1.9 2022/12/26 07:18:50 jmc Exp $	*/
+
+/*
+ * Copyright (c) 2015 Michael Felt 
+ * Copyright (c) 2014 Theo de Raadt 
+ * Copyright (c) 2014 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+/*
+ * -lperfstat is needed for the pseudo entropy data
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#define REPEAT 5
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+    int devfscheck);
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 */
+	ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
+	if (ret != -1)
+		return (ret);
+
+	/*
+	 * Entropy collection via /dev/urandom has failed.
+	 *
+	 * No other API exists for collecting entropy, and we have
+	 * no failsafe way to get it on AIX that is not sensitive
+	 * to resource exhaustion.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that AIX
+	 * does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that AIX should consider
+	 * providing a new failsafe API which works in a chroot or
+	 * when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	errno = EIO;
+	return (ret);
+}
+
+static int
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
+{
+	struct stat st;
+	size_t i;
+	int fd, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open(path, flags);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	errno = save_errno;
+	return (0);		/* satisfied */
+nodevrandom:
+	errno = EIO;
+	return (-1);
+}
+
+static const int cl[] = {
+	CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+	CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+	CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+	CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+	CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+	CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+	CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+	CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	perfstat_cpu_total_t cpustats;
+#ifdef _AIX61
+	perfstat_cpu_total_wpar_t cpustats_wpar;
+#endif
+	perfstat_partition_total_t lparstats;
+	perfstat_disk_total_t diskinfo;
+	perfstat_netinterface_total_t netinfo;
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HX(perfstat_cpu_total(NULL, &cpustats,
+			    sizeof(cpustats), 1) == -1, cpustats);
+
+#ifdef _AIX61
+			HX(perfstat_cpu_total_wpar(NULL, &cpustats_wpar,
+			    sizeof(cpustats_wpar), 1) == -1, cpustats_wpar);
+#endif
+
+			HX(perfstat_partition_total(NULL, &lparstats,
+			    sizeof(lparstats), 1) == -1, lparstats);
+
+			HX(perfstat_disk_total(NULL, &diskinfo,
+			    sizeof(diskinfo), 1) == -1, diskinfo);
+
+			HX(perfstat_netinterface_total(NULL, &netinfo,
+			    sizeof(netinfo), 1) == -1, netinfo);
+
+			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+				HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+					    ii++) {
+						HX((e = clock_gettime(cl[ii],
+						    &ts)) == -1, ts);
+						if (e != -1)
+							cnt += (int)ts.tv_nsec;
+					}
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
+		i += MINIMUM(sizeof(results), len - i);
+	}
+	explicit_bzero(&ctx, sizeof ctx);
+	explicit_bzero(results, sizeof results);
+	errno = save_errno;
+	return (0);		/* satisfied */
+}
diff --git a/crypto/compat/getentropy_freebsd.c b/crypto/compat/getentropy_freebsd.c
new file mode 100644
index 0000000..ea90ffe
--- /dev/null
+++ b/crypto/compat/getentropy_freebsd.c
@@ -0,0 +1,60 @@
+/*	$OpenBSD: getentropy_freebsd.c,v 1.4 2020/10/12 22:08:33 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Pawel Jakub Dawidek 
+ * Copyright (c) 2014 Brent Cook 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+/*
+ * Derived from lib/libc/gen/arc4random.c from FreeBSD.
+ */
+static size_t
+getentropy_sysctl(u_char *buf, size_t size)
+{
+	const int mib[2] = { CTL_KERN, KERN_ARND };
+	size_t len, done;
+
+	done = 0;
+
+	do {
+		len = size;
+		if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
+			return (done);
+		done += len;
+		buf += len;
+		size -= len;
+	} while (size > 0);
+
+	return (done);
+}
+
+int
+getentropy(void *buf, size_t len)
+{
+	if (len <= 256 && getentropy_sysctl(buf, len) == len)
+		return (0);
+
+	errno = EIO;
+	return (-1);
+}
diff --git a/crypto/compat/getentropy_hpux.c b/crypto/compat/getentropy_hpux.c
new file mode 100644
index 0000000..7188ae5
--- /dev/null
+++ b/crypto/compat/getentropy_hpux.c
@@ -0,0 +1,396 @@
+/*	$OpenBSD: getentropy_hpux.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Theo de Raadt 
+ * Copyright (c) 2014 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#define REPEAT 5
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+    int devfscheck);
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 */
+	ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
+	if (ret != -1)
+		return (ret);
+
+	/*
+	 * Entropy collection via /dev/urandom has failed.
+	 *
+	 * No other API exists for collecting entropy, and we have
+	 * no failsafe way to get it on hpux that is not sensitive
+	 * to resource exhaustion.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that hpux 
+	 * does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that hpux should consider
+	 * providing a new failsafe API which works in a chroot or
+	 * when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	errno = EIO;
+	return (ret);
+}
+
+static int
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
+{
+	struct stat st;
+	size_t i;
+	int fd, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open(path, flags);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	errno = save_errno;
+	return (0);		/* satisfied */
+nodevrandom:
+	errno = EIO;
+	return (-1);
+}
+
+static const int cl[] = {
+	CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+	CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+	CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+	CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+	CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+	CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+	CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+	CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	struct pst_vminfo pvi;
+	struct pst_vm_status pvs;
+	struct pst_dynamic pdy;
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
+			HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);
+
+			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+				HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+
+			if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
+				HD(errno);
+			} else {
+				HD(pdy.psd_avg_1_min);
+				HD(pdy.psd_avg_5_min);
+				HD(pdy.psd_avg_15_min);
+			}
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+					    ii++) {
+						HX((e = clock_gettime(cl[ii],
+						    &ts)) == -1, ts);
+						if (e != -1)
+							cnt += (int)ts.tv_nsec;
+					}
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
+		i += MINIMUM(sizeof(results), len - i);
+	}
+	explicit_bzero(&ctx, sizeof ctx);
+	explicit_bzero(results, sizeof results);
+	errno = save_errno;
+	return (0);		/* satisfied */
+}
diff --git a/crypto/compat/getentropy_linux.c b/crypto/compat/getentropy_linux.c
new file mode 100644
index 0000000..c7c39c2
--- /dev/null
+++ b/crypto/compat/getentropy_linux.c
@@ -0,0 +1,525 @@
+/*	$OpenBSD: getentropy_linux.c,v 1.48 2021/10/24 21:24:20 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Theo de Raadt 
+ * Copyright (c) 2014 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#define	_POSIX_C_SOURCE	199309L
+#define	_GNU_SOURCE	1
+#include 
+#include 
+#include 
+#include 
+#include 
+#ifdef SYS__sysctl
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#ifdef HAVE_GETAUXVAL
+#include 
+#endif
+#include 
+
+#define REPEAT 5
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
+static int getentropy_getrandom(void *buf, size_t len);
+#endif
+static int getentropy_urandom(void *buf, size_t len);
+#ifdef SYS__sysctl
+static int getentropy_sysctl(void *buf, size_t len);
+#endif
+static int getentropy_fallback(void *buf, size_t len);
+static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
+	/*
+	 * Try descriptor-less getrandom(), in non-blocking mode.
+	 *
+	 * The design of Linux getrandom is broken.  It has an
+	 * uninitialized phase coupled with blocking behaviour, which
+	 * is unacceptable from within a library at boot time without
+	 * possible recovery. See http://bugs.python.org/issue26839#msg267745
+	 */
+	ret = getentropy_getrandom(buf, len);
+	if (ret != -1)
+		return (ret);
+#endif
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 *
+	 * This can fail if the process is inside a chroot or if file
+	 * descriptors are exhausted.
+	 */
+	ret = getentropy_urandom(buf, len);
+	if (ret != -1)
+		return (ret);
+
+#ifdef SYS__sysctl
+	/*
+	 * Try to use sysctl CTL_KERN, KERN_RANDOM, RANDOM_UUID.
+	 * sysctl is a failsafe API, so it guarantees a result.  This
+	 * should work inside a chroot, or when file descriptors are
+	 * exhausted.
+	 *
+	 * However this can fail if the Linux kernel removes support
+	 * for sysctl.  Starting in 2007, there have been efforts to
+	 * deprecate the sysctl API/ABI, and push callers towards use
+	 * of the chroot-unavailable fd-using /proc mechanism --
+	 * essentially the same problems as /dev/urandom.
+	 *
+	 * Numerous setbacks have been encountered in their deprecation
+	 * schedule, so as of June 2014 the kernel ABI still exists on
+	 * most Linux architectures. The sysctl() stub in libc is missing
+	 * on some systems.  There are also reports that some kernels
+	 * spew messages to the console.
+	 */
+	ret = getentropy_sysctl(buf, len);
+	if (ret != -1)
+		return (ret);
+#endif /* SYS__sysctl */
+
+	/*
+	 * Entropy collection via /dev/urandom and sysctl have failed.
+	 *
+	 * No other API exists for collecting entropy.  See the large
+	 * comment block above.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that Linux
+	 * still does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that Linux should either retain their
+	 * sysctl ABI, or consider providing a new failsafe API which
+	 * works in a chroot or when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	errno = EIO;
+	return (ret);
+}
+
+#if defined(SYS_getrandom) && defined(GRND_NONBLOCK)
+static int
+getentropy_getrandom(void *buf, size_t len)
+{
+	int pre_errno = errno;
+	int ret;
+	if (len > 256)
+		return (-1);
+	do {
+		ret = syscall(SYS_getrandom, buf, len, GRND_NONBLOCK);
+	} while (ret == -1 && errno == EINTR);
+
+	if (ret != len)
+		return (-1);
+	errno = pre_errno;
+	return (0);
+}
+#endif
+
+static int
+getentropy_urandom(void *buf, size_t len)
+{
+	struct stat st;
+	size_t i;
+	int fd, cnt, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open("/dev/urandom", flags);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		close(fd);
+		goto nodevrandom;
+	}
+	if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	errno = save_errno;
+	return (0);		/* satisfied */
+nodevrandom:
+	errno = EIO;
+	return (-1);
+}
+
+#ifdef SYS__sysctl
+static int
+getentropy_sysctl(void *buf, size_t len)
+{
+	static int mib[] = { CTL_KERN, KERN_RANDOM, RANDOM_UUID };
+	size_t i;
+	int save_errno = errno;
+
+	for (i = 0; i < len; ) {
+		size_t chunk = MINIMUM(len - i, 16);
+
+		/* SYS__sysctl because some systems already removed sysctl() */
+		struct __sysctl_args args = {
+			.name = mib,
+			.nlen = 3,
+			.oldval = (char *)buf + i,
+			.oldlenp = &chunk,
+		};
+		if (syscall(SYS__sysctl, &args) != 0)
+			goto sysctlfailed;
+		i += chunk;
+	}
+	errno = save_errno;
+	return (0);			/* satisfied */
+sysctlfailed:
+	errno = EIO;
+	return (-1);
+}
+#endif /* SYS__sysctl */
+
+static const int cl[] = {
+	CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+	CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+	CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+	CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+	CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+	CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+	CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+	CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
+{
+	SHA512_CTX *ctx = data;
+
+	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
+	return (0);
+}
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			dl_iterate_phdr(getentropy_phdr, &ctx);
+
+			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+				HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				struct statfs stfs;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+					    ii++) {
+						HX((e = clock_gettime(cl[ii],
+						    &ts)) == -1, ts);
+						if (e != -1)
+							cnt += (int)ts.tv_nsec;
+					}
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+				HX(statfs(".", &stfs) == -1, stfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+				HX(statfs("/", &stfs) == -1, stfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX(fstatfs(0, &stfs) == -1,
+						    stfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+#ifdef HAVE_GETAUXVAL
+#ifdef AT_RANDOM
+		/* Not as random as you think but we take what we are given */
+		p = (char *) getauxval(AT_RANDOM);
+		if (p)
+			HR(p, 16);
+#endif
+#ifdef AT_SYSINFO_EHDR
+		p = (char *) getauxval(AT_SYSINFO_EHDR);
+		if (p)
+			HR(p, pgs);
+#endif
+#ifdef AT_BASE
+		p = (char *) getauxval(AT_BASE);
+		if (p)
+			HD(p);
+#endif
+#endif
+
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
+		i += MINIMUM(sizeof(results), len - i);
+	}
+	explicit_bzero(&ctx, sizeof ctx);
+	explicit_bzero(results, sizeof results);
+	errno = save_errno;
+	return (0);		/* satisfied */
+}
diff --git a/crypto/compat/getentropy_netbsd.c b/crypto/compat/getentropy_netbsd.c
new file mode 100644
index 0000000..5dc8959
--- /dev/null
+++ b/crypto/compat/getentropy_netbsd.c
@@ -0,0 +1,62 @@
+/*	$OpenBSD: getentropy_netbsd.c,v 1.4 2020/10/12 22:08:33 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Pawel Jakub Dawidek 
+ * Copyright (c) 2014 Brent Cook 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+/*
+ * Derived from lib/libc/gen/arc4random.c from FreeBSD.
+ */
+static size_t
+getentropy_sysctl(u_char *buf, size_t size)
+{
+	const int mib[2] = { CTL_KERN, KERN_ARND };
+	size_t len, done;
+
+	done = 0;
+
+	do {
+		len = size;
+		if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
+			return (done);
+		done += len;
+		buf += len;
+		size -= len;
+	} while (size > 0);
+
+	return (done);
+}
+
+int
+getentropy(void *buf, size_t len)
+{
+	if (len <= 256 &&
+	    getentropy_sysctl(buf, len) == len) {
+		return (0);
+	}
+
+	errno = EIO;
+	return (-1);
+}
diff --git a/crypto/compat/getentropy_osx.c b/crypto/compat/getentropy_osx.c
new file mode 100644
index 0000000..db028d1
--- /dev/null
+++ b/crypto/compat/getentropy_osx.c
@@ -0,0 +1,417 @@
+/*	$OpenBSD: getentropy_osx.c,v 1.14 2021/10/24 21:24:20 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Theo de Raadt 
+ * Copyright (c) 2014 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#if TARGET_OS_OSX
+#include 
+#include 
+#endif
+#include 
+#include 
+#if TARGET_OS_OSX
+#include 
+#include 
+#include 
+#include 
+#endif
+#include 
+#define SHA512_Update(a, b, c)	(CC_SHA512_Update((a), (b), (c)))
+#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
+#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
+#define SHA512_CTX CC_SHA512_CTX
+#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
+
+#define REPEAT 5
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+static int getentropy_urandom(void *buf, size_t len);
+static int getentropy_fallback(void *buf, size_t len);
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 *
+	 * This can fail if the process is inside a chroot or if file
+	 * descriptors are exhausted.
+	 */
+	ret = getentropy_urandom(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	/*
+	 * Entropy collection via /dev/urandom and sysctl have failed.
+	 *
+	 * No other API exists for collecting entropy, and we have
+	 * no failsafe way to get it on OSX that is not sensitive
+	 * to resource exhaustion.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that OSX
+	 * does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that OSX should consider
+	 * providing a new failsafe API which works in a chroot or
+	 * when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	errno = EIO;
+	return (ret);
+}
+
+static int
+getentropy_urandom(void *buf, size_t len)
+{
+	struct stat st;
+	size_t i;
+	int fd, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open("/dev/urandom", flags);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	errno = save_errno;
+	return (0);		/* satisfied */
+nodevrandom:
+	errno = EIO;
+	return (-1);
+}
+
+#if TARGET_OS_OSX
+static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
+static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
+static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
+#endif
+static int kmib[] = { CTL_KERN, KERN_USRSTACK };
+static int hwmib[] = { CTL_HW, HW_USERMEM };
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+#if TARGET_OS_OSX
+	struct tcpstat tcpstat;
+	struct udpstat udpstat;
+	struct ipstat ipstat;
+#endif
+	u_int64_t mach_time;
+	unsigned int idata;
+	void *addr;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			mach_time = mach_absolute_time();
+			HD(mach_time);
+
+			ii = sizeof(addr);
+			HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
+			    &addr, &ii, NULL, 0) == -1, addr);
+
+			ii = sizeof(idata);
+			HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
+			    &idata, &ii, NULL, 0) == -1, idata);
+
+#if TARGET_OS_OSX
+			ii = sizeof(tcpstat);
+			HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
+			    &tcpstat, &ii, NULL, 0) == -1, tcpstat);
+
+			ii = sizeof(udpstat);
+			HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
+			    &udpstat, &ii, NULL, 0) == -1, udpstat);
+
+			ii = sizeof(ipstat);
+			HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
+			    &ipstat, &ii, NULL, 0) == -1, ipstat);
+#endif
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				struct statfs stfs;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					mach_time = mach_absolute_time();
+					HD(mach_time);
+					cnt += (int)mach_time;
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+				HX(statfs(".", &stfs) == -1, stfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+				HX(statfs("/", &stfs) == -1, stfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX(fstatfs(0, &stfs) == -1,
+						    stfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
+		i += MINIMUM(sizeof(results), len - i);
+	}
+	explicit_bzero(&ctx, sizeof ctx);
+	explicit_bzero(results, sizeof results);
+	errno = save_errno;
+	return (0);		/* satisfied */
+}
diff --git a/crypto/compat/getentropy_solaris.c b/crypto/compat/getentropy_solaris.c
new file mode 100644
index 0000000..e36426c
--- /dev/null
+++ b/crypto/compat/getentropy_solaris.c
@@ -0,0 +1,422 @@
+/*	$OpenBSD: getentropy_solaris.c,v 1.15 2021/10/24 21:24:20 deraadt Exp $	*/
+
+/*
+ * Copyright (c) 2014 Theo de Raadt 
+ * Copyright (c) 2014 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#define SHA512_Init SHA512Init
+#define SHA512_Update SHA512Update
+#define SHA512_Final SHA512Final
+
+#include 
+#include 
+#include 
+
+#define REPEAT 5
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define HX(a, b) \
+	do { \
+		if ((a)) \
+			HD(errno); \
+		else \
+			HD(b); \
+	} while (0)
+
+#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
+#define HD(x)	 (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
+#define HF(x)    (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
+int	getentropy(void *buf, size_t len);
+
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+    int devfscheck);
+static int getentropy_fallback(void *buf, size_t len);
+static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
+
+int
+getentropy(void *buf, size_t len)
+{
+	int ret = -1;
+
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+	/*
+	 * Try to get entropy with /dev/urandom
+	 *
+	 * Solaris provides /dev/urandom as a symbolic link to
+	 * /devices/pseudo/random@0:urandom which is provided by
+	 * a devfs filesystem.  Best practice is to use O_NOFOLLOW,
+	 * so we must try the unpublished name directly.
+	 *
+	 * This can fail if the process is inside a chroot which lacks
+	 * the devfs mount, or if file descriptors are exhausted.
+	 */
+	ret = getentropy_urandom(buf, len,
+	    "/devices/pseudo/random@0:urandom", 1);
+	if (ret != -1)
+		return (ret);
+
+	/*
+	 * Unfortunately, chroot spaces on Solaris are sometimes setup
+	 * with direct device node of the well-known /dev/urandom name
+	 * (perhaps to avoid dragging all of devfs into the space).
+	 *
+	 * This can fail if the process is inside a chroot or if file
+	 * descriptors are exhausted.
+	 */
+	ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
+	if (ret != -1)
+		return (ret);
+
+	/*
+	 * Entropy collection via /dev/urandom has failed.
+	 *
+	 * No other API exists for collecting entropy, and we have
+	 * no failsafe way to get it on Solaris that is not sensitive
+	 * to resource exhaustion.
+	 *
+	 * We have very few options:
+	 *     - Even syslog_r is unsafe to call at this low level, so
+	 *	 there is no way to alert the user or program.
+	 *     - Cannot call abort() because some systems have unsafe
+	 *	 corefiles.
+	 *     - Could raise(SIGKILL) resulting in silent program termination.
+	 *     - Return EIO, to hint that arc4random's stir function
+	 *       should raise(SIGKILL)
+	 *     - Do the best under the circumstances....
+	 *
+	 * This code path exists to bring light to the issue that Solaris
+	 * does not provide a failsafe API for entropy collection.
+	 *
+	 * We hope this demonstrates that Solaris should consider
+	 * providing a new failsafe API which works in a chroot or
+	 * when file descriptors are exhausted.
+	 */
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
+	raise(SIGKILL);
+#endif
+	ret = getentropy_fallback(buf, len);
+	if (ret != -1)
+		return (ret);
+
+	errno = EIO;
+	return (ret);
+}
+
+static int
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
+{
+	struct stat st;
+	size_t i;
+	int fd, flags;
+	int save_errno = errno;
+
+start:
+
+	flags = O_RDONLY;
+#ifdef O_NOFOLLOW
+	flags |= O_NOFOLLOW;
+#endif
+#ifdef O_CLOEXEC
+	flags |= O_CLOEXEC;
+#endif
+	fd = open(path, flags);
+	if (fd == -1) {
+		if (errno == EINTR)
+			goto start;
+		goto nodevrandom;
+	}
+#ifndef O_CLOEXEC
+	fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+#endif
+
+	/* Lightly verify that the device node looks sane */
+	if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
+	    (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
+		close(fd);
+		goto nodevrandom;
+	}
+	for (i = 0; i < len; ) {
+		size_t wanted = len - i;
+		ssize_t ret = read(fd, (char *)buf + i, wanted);
+
+		if (ret == -1) {
+			if (errno == EAGAIN || errno == EINTR)
+				continue;
+			close(fd);
+			goto nodevrandom;
+		}
+		i += ret;
+	}
+	close(fd);
+	errno = save_errno;
+	return (0);		/* satisfied */
+nodevrandom:
+	errno = EIO;
+	return (-1);
+}
+
+static const int cl[] = {
+	CLOCK_REALTIME,
+#ifdef CLOCK_MONOTONIC
+	CLOCK_MONOTONIC,
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+	CLOCK_MONOTONIC_RAW,
+#endif
+#ifdef CLOCK_TAI
+	CLOCK_TAI,
+#endif
+#ifdef CLOCK_VIRTUAL
+	CLOCK_VIRTUAL,
+#endif
+#ifdef CLOCK_UPTIME
+	CLOCK_UPTIME,
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+	CLOCK_PROCESS_CPUTIME_ID,
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+	CLOCK_THREAD_CPUTIME_ID,
+#endif
+};
+
+static int
+getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data)
+{
+	SHA512_CTX *ctx = data;
+
+	SHA512_Update(ctx, &info->dlpi_addr, sizeof (info->dlpi_addr));
+	return (0);
+}
+
+static int
+getentropy_fallback(void *buf, size_t len)
+{
+	uint8_t results[SHA512_DIGEST_LENGTH];
+	int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+	static int cnt;
+	struct timespec ts;
+	struct timeval tv;
+	double loadavg[3];
+	struct rusage ru;
+	sigset_t sigset;
+	struct stat st;
+	SHA512_CTX ctx;
+	static pid_t lastpid;
+	pid_t pid;
+	size_t i, ii, m;
+	char *p;
+
+	pid = getpid();
+	if (lastpid == pid) {
+		faster = 1;
+		repeat = 2;
+	} else {
+		faster = 0;
+		lastpid = pid;
+		repeat = REPEAT;
+	}
+	for (i = 0; i < len; ) {
+		int j;
+		SHA512_Init(&ctx);
+		for (j = 0; j < repeat; j++) {
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			dl_iterate_phdr(getentropy_phdr, &ctx);
+
+			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
+				HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
+			HX((pid = getpid()) == -1, pid);
+			HX((pid = getsid(pid)) == -1, pid);
+			HX((pid = getppid()) == -1, pid);
+			HX((pid = getpgid(0)) == -1, pid);
+			HX((e = getpriority(0, 0)) == -1, e);
+			HX((getloadavg(loadavg, 3) == -1), loadavg);
+
+			if (!faster) {
+				ts.tv_sec = 0;
+				ts.tv_nsec = 1;
+				(void) nanosleep(&ts, NULL);
+			}
+
+			HX(sigpending(&sigset) == -1, sigset);
+			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
+			    sigset);
+
+			HF(getentropy);	/* an addr in this library */
+			HF(printf);		/* an addr in libc */
+			p = (char *)&p;
+			HD(p);		/* an addr on stack */
+			p = (char *)&errno;
+			HD(p);		/* the addr of errno */
+
+			if (i == 0) {
+				struct sockaddr_storage ss;
+				struct statvfs stvfs;
+				struct termios tios;
+				socklen_t ssl;
+				off_t off;
+
+				/*
+				 * Prime-sized mappings encourage fragmentation;
+				 * thus exposing some address entropy.
+				 */
+				struct mm {
+					size_t	npg;
+					void	*p;
+				} mm[] =	 {
+					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
+					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
+					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
+					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
+				};
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					HX(mm[m].p = mmap(NULL,
+					    mm[m].npg * pgs,
+					    PROT_READ|PROT_WRITE,
+					    MAP_PRIVATE|MAP_ANON, -1,
+					    (off_t)0), mm[m].p);
+					if (mm[m].p != MAP_FAILED) {
+						size_t mo;
+
+						/* Touch some memory... */
+						p = mm[m].p;
+						mo = cnt %
+						    (mm[m].npg * pgs - 1);
+						p[mo] = 1;
+						cnt += (int)((long)(mm[m].p)
+						    / pgs);
+					}
+
+					/* Check cnts and times... */
+					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
+					    ii++) {
+						HX((e = clock_gettime(cl[ii],
+						    &ts)) == -1, ts);
+						if (e != -1)
+							cnt += (int)ts.tv_nsec;
+					}
+
+					HX((e = getrusage(RUSAGE_SELF,
+					    &ru)) == -1, ru);
+					if (e != -1) {
+						cnt += (int)ru.ru_utime.tv_sec;
+						cnt += (int)ru.ru_utime.tv_usec;
+					}
+				}
+
+				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
+					if (mm[m].p != MAP_FAILED)
+						munmap(mm[m].p, mm[m].npg * pgs);
+					mm[m].p = MAP_FAILED;
+				}
+
+				HX(stat(".", &st) == -1, st);
+				HX(statvfs(".", &stvfs) == -1, stvfs);
+
+				HX(stat("/", &st) == -1, st);
+				HX(statvfs("/", &stvfs) == -1, stvfs);
+
+				HX((e = fstat(0, &st)) == -1, st);
+				if (e == -1) {
+					if (S_ISREG(st.st_mode) ||
+					    S_ISFIFO(st.st_mode) ||
+					    S_ISSOCK(st.st_mode)) {
+						HX(fstatvfs(0, &stvfs) == -1,
+						    stvfs);
+						HX((off = lseek(0, (off_t)0,
+						    SEEK_CUR)) < 0, off);
+					}
+					if (S_ISCHR(st.st_mode)) {
+						HX(tcgetattr(0, &tios) == -1,
+						    tios);
+					} else if (S_ISSOCK(st.st_mode)) {
+						memset(&ss, 0, sizeof ss);
+						ssl = sizeof(ss);
+						HX(getpeername(0,
+						    (void *)&ss, &ssl) == -1,
+						    ss);
+					}
+				}
+
+				HX((e = getrusage(RUSAGE_CHILDREN,
+				    &ru)) == -1, ru);
+				if (e != -1) {
+					cnt += (int)ru.ru_utime.tv_sec;
+					cnt += (int)ru.ru_utime.tv_usec;
+				}
+			} else {
+				/* Subsequent hashes absorb previous result */
+				HD(results);
+			}
+
+			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
+			if (e != -1) {
+				cnt += (int)tv.tv_sec;
+				cnt += (int)tv.tv_usec;
+			}
+
+			HD(cnt);
+		}
+		SHA512_Final(results, &ctx);
+		memcpy((char *)buf + i, results, MINIMUM(sizeof(results), len - i));
+		i += MINIMUM(sizeof(results), len - i);
+	}
+	explicit_bzero(&ctx, sizeof ctx);
+	explicit_bzero(results, sizeof results);
+	errno = save_errno;
+	return (0);		/* satisfied */
+}
diff --git a/crypto/compat/getentropy_win.c b/crypto/compat/getentropy_win.c
new file mode 100644
index 0000000..64514b3
--- /dev/null
+++ b/crypto/compat/getentropy_win.c
@@ -0,0 +1,50 @@
+/*	$OpenBSD: getentropy_win.c,v 1.6 2020/11/11 10:41:24 bcook Exp $	*/
+
+/*
+ * Copyright (c) 2014, Theo de Raadt  
+ * Copyright (c) 2014, Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Emulation of getentropy(2) as documented at:
+ * http://man.openbsd.org/getentropy.2
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int	getentropy(void *buf, size_t len);
+
+/*
+ * On Windows, BCryptGenRandom with BCRYPT_USE_SYSTEM_PREFERRED_RNG is supposed
+ * to be a well-seeded, cryptographically strong random number generator.
+ * https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
+ */
+int
+getentropy(void *buf, size_t len)
+{
+	if (len > 256) {
+		errno = EIO;
+		return (-1);
+	}
+
+	if (FAILED(BCryptGenRandom(NULL, buf, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
+		errno = EIO;
+		return (-1);
+	}
+
+	return (0);
+}
diff --git a/crypto/compat/reallocarray.c b/crypto/compat/reallocarray.c
new file mode 100644
index 0000000..43f0b69
--- /dev/null
+++ b/crypto/compat/reallocarray.c
@@ -0,0 +1,38 @@
+/*	$OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $	*/
+/*
+ * Copyright (c) 2008 Otto Moerbeek 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    nmemb > 0 && SIZE_MAX / nmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	return realloc(optr, size * nmemb);
+}
diff --git a/crypto/compat/recallocarray.c b/crypto/compat/recallocarray.c
new file mode 100644
index 0000000..7ab2ec5
--- /dev/null
+++ b/crypto/compat/recallocarray.c
@@ -0,0 +1,80 @@
+/*	$OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $	*/
+/*
+ * Copyright (c) 2008, 2017 Otto Moerbeek 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+	size_t oldsize, newsize;
+	void *newptr;
+
+	if (ptr == NULL)
+		return calloc(newnmemb, size);
+
+	if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	newsize = newnmemb * size;
+
+	if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+		errno = EINVAL;
+		return NULL;
+	}
+	oldsize = oldnmemb * size;
+	
+	/*
+	 * Don't bother too much if we're shrinking just a bit,
+	 * we do not shrink for series of small steps, oh well.
+	 */
+	if (newsize <= oldsize) {
+		size_t d = oldsize - newsize;
+
+		if (d < oldsize / 2 && d < (size_t)getpagesize()) {
+			memset((char *)ptr + newsize, 0, d);
+			return ptr;
+		}
+	}
+
+	newptr = malloc(newsize);
+	if (newptr == NULL)
+		return NULL;
+
+	if (newsize > oldsize) {
+		memcpy(newptr, ptr, oldsize);
+		memset((char *)newptr + oldsize, 0, newsize - oldsize);
+	} else
+		memcpy(newptr, ptr, newsize);
+
+	explicit_bzero(ptr, oldsize);
+	free(ptr);
+
+	return newptr;
+}
diff --git a/crypto/compat/strcasecmp.c b/crypto/compat/strcasecmp.c
new file mode 100644
index 0000000..e5da89c
--- /dev/null
+++ b/crypto/compat/strcasecmp.c
@@ -0,0 +1,105 @@
+/*	$OpenBSD: strcasecmp.c,v 1.7 2015/08/31 02:53:57 guenther Exp $	*/
+
+/*
+ * Copyright (c) 1987, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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.
+ */
+
+#include 
+
+typedef unsigned char u_char;
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+	'\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+	'\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+	'\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+	'\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(const char *s1, const char *s2)
+{
+	const u_char *cm = charmap;
+	const u_char *us1 = (const u_char *)s1;
+	const u_char *us2 = (const u_char *)s2;
+
+	while (cm[*us1] == cm[*us2++])
+		if (*us1++ == '\0')
+			return (0);
+	return (cm[*us1] - cm[*--us2]);
+}
+
+int
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+	if (n != 0) {
+		const u_char *cm = charmap;
+		const u_char *us1 = (const u_char *)s1;
+		const u_char *us2 = (const u_char *)s2;
+
+		do {
+			if (cm[*us1] != cm[*us2++])
+				return (cm[*us1] - cm[*--us2]);
+			if (*us1++ == '\0')
+				break;
+		} while (--n != 0);
+	}
+	return (0);
+}
diff --git a/crypto/compat/strlcat.c b/crypto/compat/strlcat.c
new file mode 100644
index 0000000..c94e90d
--- /dev/null
+++ b/crypto/compat/strlcat.c
@@ -0,0 +1,55 @@
+/*	$OpenBSD: strlcat.c,v 1.19 2019/01/25 00:19:25 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left).  At most dsize-1 characters
+ * will be copied.  Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t dsize)
+{
+	const char *odst = dst;
+	const char *osrc = src;
+	size_t n = dsize;
+	size_t dlen;
+
+	/* Find the end of dst and adjust bytes left but don't go past end. */
+	while (n-- != 0 && *dst != '\0')
+		dst++;
+	dlen = dst - odst;
+	n = dsize - dlen;
+
+	if (n-- == 0)
+		return(dlen + strlen(src));
+	while (*src != '\0') {
+		if (n != 0) {
+			*dst++ = *src;
+			n--;
+		}
+		src++;
+	}
+	*dst = '\0';
+
+	return(dlen + (src - osrc));	/* count does not include NUL */
+}
diff --git a/crypto/compat/strlcpy.c b/crypto/compat/strlcpy.c
new file mode 100644
index 0000000..2fa498c
--- /dev/null
+++ b/crypto/compat/strlcpy.c
@@ -0,0 +1,50 @@
+/*	$OpenBSD: strlcpy.c,v 1.16 2019/01/25 00:19:25 millert Exp $	*/
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+/*
+ * Copy string src to buffer dst of size dsize.  At most dsize-1
+ * chars will be copied.  Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t dsize)
+{
+	const char *osrc = src;
+	size_t nleft = dsize;
+
+	/* Copy as many bytes as will fit. */
+	if (nleft != 0) {
+		while (--nleft != 0) {
+			if ((*dst++ = *src++) == '\0')
+				break;
+		}
+	}
+
+	/* Not enough room in dst, add NUL and traverse rest of src. */
+	if (nleft == 0) {
+		if (dsize != 0)
+			*dst = '\0';		/* NUL-terminate dst */
+		while (*src++)
+			;
+	}
+
+	return(src - osrc - 1);	/* count does not include NUL */
+}
diff --git a/crypto/compat/strndup.c b/crypto/compat/strndup.c
new file mode 100644
index 0000000..0f15e42
--- /dev/null
+++ b/crypto/compat/strndup.c
@@ -0,0 +1,39 @@
+/*	$OpenBSD: strndup.c,v 1.3 2019/01/25 00:19:25 millert Exp $	*/
+
+/*
+ * Copyright (c) 2010 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+char *
+strndup(const char *str, size_t maxlen)
+{
+	char *copy;
+	size_t len;
+
+	len = strnlen(str, maxlen);
+	copy = malloc(len + 1);
+	if (copy != NULL) {
+		(void)memcpy(copy, str, len);
+		copy[len] = '\0';
+	}
+
+	return copy;
+}
diff --git a/crypto/compat/strnlen.c b/crypto/compat/strnlen.c
new file mode 100644
index 0000000..84f2d22
--- /dev/null
+++ b/crypto/compat/strnlen.c
@@ -0,0 +1,32 @@
+/*	$OpenBSD: strnlen.c,v 1.9 2019/01/25 00:19:25 millert Exp $	*/
+
+/*
+ * Copyright (c) 2010 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+size_t
+strnlen(const char *str, size_t maxlen)
+{
+	const char *cp;
+
+	for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
+		;
+
+	return (size_t)(cp - str);
+}
diff --git a/crypto/compat/strsep.c b/crypto/compat/strsep.c
new file mode 100644
index 0000000..c5d6511
--- /dev/null
+++ b/crypto/compat/strsep.c
@@ -0,0 +1,70 @@
+/*	$OpenBSD: strsep.c,v 1.8 2015/08/31 02:53:57 guenther Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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.
+ */
+
+#include 
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.  
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+	char *s;
+	const char *spanp;
+	int c, sc;
+	char *tok;
+
+	if ((s = *stringp) == NULL)
+		return (NULL);
+	for (tok = s;;) {
+		c = *s++;
+		spanp = delim;
+		do {
+			if ((sc = *spanp++) == c) {
+				if (c == 0)
+					s = NULL;
+				else
+					s[-1] = 0;
+				*stringp = s;
+				return (tok);
+			}
+		} while (sc != 0);
+	}
+	/* NOTREACHED */
+}
diff --git a/crypto/compat/strtonum.c b/crypto/compat/strtonum.c
new file mode 100644
index 0000000..fdfc72a
--- /dev/null
+++ b/crypto/compat/strtonum.c
@@ -0,0 +1,65 @@
+/*	$OpenBSD: strtonum.c,v 1.8 2015/09/13 08:31:48 guenther Exp $	*/
+
+/*
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+
+#define	INVALID		1
+#define	TOOSMALL	2
+#define	TOOLARGE	3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+    const char **errstrp)
+{
+	long long ll = 0;
+	int error = 0;
+	char *ep;
+	struct errval {
+		const char *errstr;
+		int err;
+	} ev[4] = {
+		{ NULL,		0 },
+		{ "invalid",	EINVAL },
+		{ "too small",	ERANGE },
+		{ "too large",	ERANGE },
+	};
+
+	ev[0].err = errno;
+	errno = 0;
+	if (minval > maxval) {
+		error = INVALID;
+	} else {
+		ll = strtoll(numstr, &ep, 10);
+		if (numstr == ep || *ep != '\0')
+			error = INVALID;
+		else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+			error = TOOSMALL;
+		else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+			error = TOOLARGE;
+	}
+	if (errstrp != NULL)
+		*errstrp = ev[error].errstr;
+	errno = ev[error].err;
+	if (error)
+		ll = 0;
+
+	return (ll);
+}
diff --git a/crypto/compat/timingsafe_bcmp.c b/crypto/compat/timingsafe_bcmp.c
new file mode 100644
index 0000000..552e844
--- /dev/null
+++ b/crypto/compat/timingsafe_bcmp.c
@@ -0,0 +1,29 @@
+/*	$OpenBSD: timingsafe_bcmp.c,v 1.3 2015/08/31 02:53:57 guenther Exp $	*/
+/*
+ * Copyright (c) 2010 Damien Miller.  All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+int
+timingsafe_bcmp(const void *b1, const void *b2, size_t n)
+{
+	const unsigned char *p1 = b1, *p2 = b2;
+	int ret = 0;
+
+	for (; n > 0; n--)
+		ret |= *p1++ ^ *p2++;
+	return (ret != 0);
+}
diff --git a/crypto/compat/timingsafe_memcmp.c b/crypto/compat/timingsafe_memcmp.c
new file mode 100644
index 0000000..bb210a3
--- /dev/null
+++ b/crypto/compat/timingsafe_memcmp.c
@@ -0,0 +1,46 @@
+/*	$OpenBSD: timingsafe_memcmp.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+int
+timingsafe_memcmp(const void *b1, const void *b2, size_t len)
+{
+        const unsigned char *p1 = b1, *p2 = b2;
+        size_t i;
+        int res = 0, done = 0;
+
+        for (i = 0; i < len; i++) {
+                /* lt is -1 if p1[i] < p2[i]; else 0. */
+                int lt = (p1[i] - p2[i]) >> CHAR_BIT;
+
+                /* gt is -1 if p1[i] > p2[i]; else 0. */
+                int gt = (p2[i] - p1[i]) >> CHAR_BIT;
+
+                /* cmp is 1 if p1[i] > p2[i]; -1 if p1[i] < p2[i]; else 0. */
+                int cmp = lt - gt;
+
+                /* set res = cmp if !done. */
+                res |= cmp & ~done;
+
+                /* set done if p1[i] != p2[i]. */
+                done |= lt | gt;
+        }
+
+        return (res);
+}
diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c
new file mode 100644
index 0000000..6fe071e
--- /dev/null
+++ b/crypto/conf/conf_api.c
@@ -0,0 +1,286 @@
+/* $OpenBSD: conf_api.c,v 1.16 2023/07/08 08:26:26 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Part of the code in here was originally in conf.c, which is now removed */
+
+#ifndef CONF_DEBUG
+# undef NDEBUG /* avoid conflicting definitions */
+# define NDEBUG
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void value_free_hash_doall_arg(CONF_VALUE *a,
+    LHASH_OF(CONF_VALUE) *conf);
+static void value_free_stack_doall(CONF_VALUE *a);
+static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE,
+    LHASH_OF(CONF_VALUE))
+static IMPLEMENT_LHASH_DOALL_FN(value_free_stack, CONF_VALUE)
+
+/* 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;
+
+	if ((conf == NULL) || (section == NULL))
+		return (NULL);
+	vv.name = NULL;
+	vv.section = (char *)section;
+	v = lh_CONF_VALUE_retrieve(conf->data, &vv);
+	return (v);
+}
+LCRYPTO_ALIAS(_CONF_get_section);
+
+/* 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
+		return (NULL);
+}
+LCRYPTO_ALIAS(_CONF_get_section_values);
+
+int
+_CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value)
+{
+	CONF_VALUE *v = NULL;
+	STACK_OF(CONF_VALUE) *ts;
+
+	ts = (STACK_OF(CONF_VALUE) *)section->value;
+
+	value->section = section->section;
+	if (!sk_CONF_VALUE_push(ts, value)) {
+		return 0;
+	}
+
+	v = lh_CONF_VALUE_insert(conf->data, value);
+	if (v != NULL) {
+		(void)sk_CONF_VALUE_delete_ptr(ts, v);
+		free(v->name);
+		free(v->value);
+		free(v);
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(_CONF_add_string);
+
+char *
+_CONF_get_string(const CONF *conf, const char *section, const char *name)
+{
+	CONF_VALUE *v, vv;
+
+	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);
+		}
+		vv.section = "default";
+		vv.name = (char *)name;
+		v = lh_CONF_VALUE_retrieve(conf->data, &vv);
+		if (v != NULL)
+			return (v->value);
+		else
+			return (NULL);
+	} else
+		return (NULL);
+}
+LCRYPTO_ALIAS(_CONF_get_string);
+
+static unsigned long
+conf_value_hash(const CONF_VALUE *v)
+{
+	return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
+}
+
+static IMPLEMENT_LHASH_HASH_FN(conf_value, CONF_VALUE)
+
+static int
+conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b)
+{
+	int i;
+
+	if (a->section != b->section) {
+		i = strcmp(a->section, b->section);
+		if (i)
+			return (i);
+	}
+	if ((a->name != NULL) && (b->name != NULL)) {
+		i = strcmp(a->name, b->name);
+		return (i);
+	} else if (a->name == b->name)
+		return (0);
+	else
+		return ((a->name == NULL)?-1 : 1);
+}
+
+static IMPLEMENT_LHASH_COMP_FN(conf_value, CONF_VALUE)
+
+int
+_CONF_new_data(CONF *conf)
+{
+	if (conf == NULL) {
+		return 0;
+	}
+	if (conf->data == NULL)
+		if ((conf->data = lh_CONF_VALUE_new()) == NULL) {
+			return 0;
+		}
+	return 1;
+}
+LCRYPTO_ALIAS(_CONF_new_data);
+
+void
+_CONF_free_data(CONF *conf)
+{
+	if (conf == NULL || conf->data == NULL)
+		return;
+
+	lh_CONF_VALUE_down_load(conf->data) = 0; /* evil thing to make
+						  * sure the 'free()' works as
+						  * expected */
+	lh_CONF_VALUE_doall_arg(conf->data,
+	    LHASH_DOALL_ARG_FN(value_free_hash),
+	    LHASH_OF(CONF_VALUE), conf->data);
+
+	/* We now have only 'section' entries in the hash table.
+	 * Due to problems with */
+
+	lh_CONF_VALUE_doall(conf->data, LHASH_DOALL_FN(value_free_stack));
+	lh_CONF_VALUE_free(conf->data);
+}
+LCRYPTO_ALIAS(_CONF_free_data);
+
+static void
+value_free_hash_doall_arg(CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf)
+{
+	if (a->name != NULL)
+		(void)lh_CONF_VALUE_delete(conf, a);
+}
+
+static void
+value_free_stack_doall(CONF_VALUE *a)
+{
+	CONF_VALUE *vv;
+	STACK_OF(CONF_VALUE) *sk;
+	int i;
+
+	if (a->name != NULL)
+		return;
+
+	sk = (STACK_OF(CONF_VALUE) *)a->value;
+	for (i = sk_CONF_VALUE_num(sk) - 1; i >= 0; i--) {
+		vv = sk_CONF_VALUE_value(sk, i);
+		free(vv->value);
+		free(vv->name);
+		free(vv);
+	}
+	if (sk != NULL)
+		sk_CONF_VALUE_free(sk);
+	free(a->section);
+	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;
+	int ok = 0, i;
+	CONF_VALUE *v = NULL, *vv;
+
+	if ((sk = sk_CONF_VALUE_new_null()) == NULL)
+		goto err;
+	if ((v = malloc(sizeof(CONF_VALUE))) == NULL)
+		goto err;
+	i = strlen(section) + 1;
+	if ((v->section = malloc(i)) == NULL)
+		goto err;
+
+	memcpy(v->section, section, i);
+	v->name = NULL;
+	v->value = (char *)sk;
+
+	vv = lh_CONF_VALUE_insert(conf->data, v);
+	OPENSSL_assert(vv == NULL);
+	ok = 1;
+
+err:
+	if (!ok) {
+		if (sk != NULL)
+			sk_CONF_VALUE_free(sk);
+		free(v);
+		v = NULL;
+	}
+	return (v);
+}
+LCRYPTO_ALIAS(_CONF_new_section);
diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
new file mode 100644
index 0000000..f2b2c94
--- /dev/null
+++ b/crypto/conf/conf_def.c
@@ -0,0 +1,698 @@
+/* $OpenBSD: conf_def.c,v 1.33 2020/02/17 12:51:48 inoguchi Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Part of the code in here was originally in conf.c, which is now removed */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "conf_def.h"
+
+#define MAX_CONF_VALUE_LENGTH 65536
+
+static char *eat_ws(CONF *conf, char *p);
+static char *eat_alpha_numeric(CONF *conf, char *p);
+static void clear_comments(CONF *conf, char *p);
+static int str_copy(CONF *conf, char *section, char **to, char *from);
+static char *scan_quote(CONF *conf, char *p);
+static char *scan_dquote(CONF *conf, char *p);
+#define scan_esc(conf,p)	(((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
+
+static CONF *def_create(CONF_METHOD *meth);
+static int def_init_default(CONF *conf);
+static int def_init_WIN32(CONF *conf);
+static int def_destroy(CONF *conf);
+static int def_destroy_data(CONF *conf);
+static int def_load(CONF *conf, const char *name, long *eline);
+static int def_load_bio(CONF *conf, BIO *bp, long *eline);
+static int def_dump(const CONF *conf, BIO *bp);
+static int def_is_number(const CONF *conf, char c);
+static int def_to_int(const CONF *conf, char c);
+
+static CONF_METHOD default_method = {
+	.name = "OpenSSL default",
+	.create = def_create,
+	.init = def_init_default,
+	.destroy = def_destroy,
+	.destroy_data = def_destroy_data,
+	.load_bio = def_load_bio,
+	.dump = def_dump,
+	.is_number = def_is_number,
+	.to_int = def_to_int,
+	.load = def_load
+};
+
+static CONF_METHOD WIN32_method = {
+	"WIN32",
+	def_create,
+	def_init_WIN32,
+	def_destroy,
+	def_destroy_data,
+	def_load_bio,
+	def_dump,
+	def_is_number,
+	def_to_int,
+	def_load
+};
+
+CONF_METHOD *
+NCONF_default(void)
+{
+	return &default_method;
+}
+
+CONF_METHOD *
+NCONF_WIN32(void)
+{
+	return &WIN32_method;
+}
+
+static CONF *
+def_create(CONF_METHOD *meth)
+{
+	CONF *ret;
+
+	ret = malloc(sizeof(CONF) + sizeof(unsigned short *));
+	if (ret)
+		if (meth->init(ret) == 0) {
+			free(ret);
+			ret = NULL;
+		}
+	return ret;
+}
+
+static int
+def_init_default(CONF *conf)
+{
+	if (conf == NULL)
+		return 0;
+
+	conf->meth = &default_method;
+	conf->meth_data = CONF_type_default;
+	conf->data = NULL;
+
+	return 1;
+}
+
+static int
+def_init_WIN32(CONF *conf)
+{
+	if (conf == NULL)
+		return 0;
+
+	conf->meth = &WIN32_method;
+	conf->meth_data = (void *)CONF_type_win32;
+	conf->data = NULL;
+
+	return 1;
+}
+
+static int
+def_destroy(CONF *conf)
+{
+	if (def_destroy_data(conf)) {
+		free(conf);
+		return 1;
+	}
+	return 0;
+}
+
+static int
+def_destroy_data(CONF *conf)
+{
+	if (conf == NULL)
+		return 0;
+	_CONF_free_data(conf);
+	return 1;
+}
+
+static int
+def_load(CONF *conf, const char *name, long *line)
+{
+	int ret;
+	BIO *in = NULL;
+
+	in = BIO_new_file(name, "rb");
+	if (in == NULL) {
+		if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
+			CONFerror(CONF_R_NO_SUCH_FILE);
+		else
+			CONFerror(ERR_R_SYS_LIB);
+		return 0;
+	}
+
+	ret = def_load_bio(conf, in, line);
+	BIO_free(in);
+
+	return ret;
+}
+
+static int
+def_load_bio(CONF *conf, BIO *in, long *line)
+{
+/* The macro BUFSIZE conflicts with a system macro in VxWorks */
+#define CONFBUFSIZE	512
+	int bufnum = 0, i, ii;
+	BUF_MEM *buff = NULL;
+	char *s, *p, *end;
+	int again;
+	long eline = 0;
+	CONF_VALUE *v = NULL, *tv;
+	CONF_VALUE *sv = NULL;
+	char *section = NULL, *buf;
+	char *start, *psection, *pname;
+	void *h = (void *)(conf->data);
+
+	if ((buff = BUF_MEM_new()) == NULL) {
+		CONFerror(ERR_R_BUF_LIB);
+		goto err;
+	}
+
+	section = strdup("default");
+	if (section == NULL) {
+		CONFerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (_CONF_new_data(conf) == 0) {
+		CONFerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	sv = _CONF_new_section(conf, section);
+	if (sv == NULL) {
+		CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+		goto err;
+	}
+
+	bufnum = 0;
+	again = 0;
+	for (;;) {
+		if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
+			CONFerror(ERR_R_BUF_LIB);
+			goto err;
+		}
+		p = &(buff->data[bufnum]);
+		*p = '\0';
+		BIO_gets(in, p, CONFBUFSIZE - 1);
+		p[CONFBUFSIZE - 1] = '\0';
+		ii = i = strlen(p);
+		if (i == 0 && !again)
+			break;
+		again = 0;
+		while (i > 0) {
+			if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
+				break;
+			else
+				i--;
+		}
+		/* we removed some trailing stuff so there is a new
+		 * line on the end. */
+		if (ii && i == ii)
+			again = 1; /* long line */
+		else {
+			p[i] = '\0';
+			eline++; /* another input line */
+		}
+
+		/* we now have a line with trailing \r\n removed */
+
+		/* i is the number of bytes */
+		bufnum += i;
+
+		v = NULL;
+		/* check for line continuation */
+		if (bufnum >= 1) {
+			/* If we have bytes and the last char '\\' and
+			 * second last char is not '\\' */
+			p = &(buff->data[bufnum - 1]);
+			if (IS_ESC(conf, p[0]) &&
+			    ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
+				bufnum--;
+				again = 1;
+			}
+		}
+		if (again)
+			continue;
+		bufnum = 0;
+		buf = buff->data;
+
+		clear_comments(conf, buf);
+		s = eat_ws(conf, buf);
+		if (IS_EOF(conf, *s))
+			continue; /* blank line */
+		if (*s == '[') {
+			char *ss;
+
+			s++;
+			start = eat_ws(conf, s);
+			ss = start;
+again:
+			end = eat_alpha_numeric(conf, ss);
+			p = eat_ws(conf, end);
+			if (*p != ']') {
+				if (*p != '\0' && ss != p) {
+					ss = p;
+					goto again;
+				}
+				CONFerror(CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
+				goto err;
+			}
+			*end = '\0';
+			if (!str_copy(conf, NULL, §ion, start))
+				goto err;
+			if ((sv = _CONF_get_section(conf, section)) == NULL)
+				sv = _CONF_new_section(conf, section);
+			if (sv == NULL) {
+				CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+				goto err;
+			}
+			continue;
+		} else {
+			pname = s;
+			psection = NULL;
+			end = eat_alpha_numeric(conf, s);
+			if ((end[0] == ':') && (end[1] == ':')) {
+				*end = '\0';
+				end += 2;
+				psection = pname;
+				pname = end;
+				end = eat_alpha_numeric(conf, end);
+			}
+			p = eat_ws(conf, end);
+			if (*p != '=') {
+				CONFerror(CONF_R_MISSING_EQUAL_SIGN);
+				goto err;
+			}
+			*end = '\0';
+			p++;
+			start = eat_ws(conf, p);
+			while (!IS_EOF(conf, *p))
+				p++;
+			p--;
+			while ((p != start) && (IS_WS(conf, *p)))
+				p--;
+			p++;
+			*p = '\0';
+
+			if (!(v = malloc(sizeof(CONF_VALUE)))) {
+				CONFerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			if (psection == NULL)
+				psection = section;
+			v->name = strdup(pname);
+			v->value = NULL;
+			if (v->name == NULL) {
+				CONFerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			if (!str_copy(conf, psection, &(v->value), start))
+				goto err;
+
+			if (strcmp(psection, section) != 0) {
+				if ((tv = _CONF_get_section(conf, psection))
+					== NULL)
+					tv = _CONF_new_section(conf, psection);
+				if (tv == NULL) {
+					CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
+					goto err;
+				}
+			} else
+				tv = sv;
+
+			if (_CONF_add_string(conf, tv, v) == 0) {
+				CONFerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			v = NULL;
+		}
+	}
+	if (buff != NULL)
+		BUF_MEM_free(buff);
+	free(section);
+	return (1);
+
+err:
+	if (buff != NULL)
+		BUF_MEM_free(buff);
+	free(section);
+	if (line != NULL)
+		*line = eline;
+	ERR_asprintf_error_data("line %ld", eline);
+	if ((h != conf->data) && (conf->data != NULL)) {
+		CONF_free(conf->data);
+		conf->data = NULL;
+	}
+	if (v != NULL) {
+		free(v->name);
+		free(v->value);
+		free(v);
+	}
+	return (0);
+}
+
+static void
+clear_comments(CONF *conf, char *p)
+{
+	for (;;) {
+		if (IS_FCOMMENT(conf, *p)) {
+			*p = '\0';
+			return;
+		}
+		if (!IS_WS(conf, *p)) {
+			break;
+		}
+		p++;
+	}
+
+	for (;;) {
+		if (IS_COMMENT(conf, *p)) {
+			*p = '\0';
+			return;
+		}
+		if (IS_DQUOTE(conf, *p)) {
+			p = scan_dquote(conf, p);
+			continue;
+		}
+		if (IS_QUOTE(conf, *p)) {
+			p = scan_quote(conf, p);
+			continue;
+		}
+		if (IS_ESC(conf, *p)) {
+			p = scan_esc(conf, p);
+			continue;
+		}
+		if (IS_EOF(conf, *p))
+			return;
+		else
+			p++;
+	}
+}
+
+static int
+str_copy(CONF *conf, char *section, char **pto, char *from)
+{
+	int q, r,rr = 0, to = 0, len = 0;
+	char *s, *e, *rp, *p, *rrp, *np, *cp, v;
+	size_t newsize;
+	BUF_MEM *buf;
+
+	if ((buf = BUF_MEM_new()) == NULL)
+		return (0);
+
+	len = strlen(from) + 1;
+	if (!BUF_MEM_grow(buf, len))
+		goto err;
+
+	for (;;) {
+		if (IS_QUOTE(conf, *from)) {
+			q = *from;
+			from++;
+			while (!IS_EOF(conf, *from) && (*from != q)) {
+				if (IS_ESC(conf, *from)) {
+					from++;
+					if (IS_EOF(conf, *from))
+						break;
+				}
+				buf->data[to++] = *(from++);
+			}
+			if (*from == q)
+				from++;
+		} else if (IS_DQUOTE(conf, *from)) {
+			q = *from;
+			from++;
+			while (!IS_EOF(conf, *from)) {
+				if (*from == q) {
+					if (*(from + 1) == q) {
+						from++;
+					} else {
+						break;
+					}
+				}
+				buf->data[to++] = *(from++);
+			}
+			if (*from == q)
+				from++;
+		} else if (IS_ESC(conf, *from)) {
+			from++;
+			v = *(from++);
+			if (IS_EOF(conf, v))
+				break;
+			else if (v == 'r')
+				v = '\r';
+			else if (v == 'n')
+				v = '\n';
+			else if (v == 'b')
+				v = '\b';
+			else if (v == 't')
+				v = '\t';
+			buf->data[to++] = v;
+		} else if (IS_EOF(conf, *from))
+			break;
+		else if (*from == '$') {
+			/* try to expand it */
+			rrp = NULL;
+			s = &(from[1]);
+			if (*s == '{')
+				q = '}';
+			else if (*s == '(')
+				q = ')';
+			else
+				q = 0;
+
+			if (q)
+				s++;
+			cp = section;
+			e = np = s;
+			while (IS_ALPHA_NUMERIC(conf, *e))
+				e++;
+			if ((e[0] == ':') && (e[1] == ':')) {
+				cp = np;
+				rrp = e;
+				rr = *e;
+				*rrp = '\0';
+				e += 2;
+				np = e;
+				while (IS_ALPHA_NUMERIC(conf, *e))
+					e++;
+			}
+			r = *e;
+			*e = '\0';
+			rp = e;
+			if (q) {
+				if (r != q) {
+					CONFerror(CONF_R_NO_CLOSE_BRACE);
+					goto err;
+				}
+				e++;
+			}
+			/* So at this point we have
+			 * np which is the start of the name string which is
+			 *   '\0' terminated.
+			 * cp which is the start of the section string which is
+			 *   '\0' terminated.
+			 * e is the 'next point after'.
+			 * r and rr are the chars replaced by the '\0'
+			 * rp and rrp is where 'r' and 'rr' came from.
+			 */
+			p = _CONF_get_string(conf, cp, np);
+			if (rrp != NULL)
+				*rrp = rr;
+			*rp = r;
+			if (p == NULL) {
+				CONFerror(CONF_R_VARIABLE_HAS_NO_VALUE);
+				goto err;
+			}
+			newsize = strlen(p) + buf->length - (e - from);
+			if (newsize > MAX_CONF_VALUE_LENGTH) {
+				CONFerror(CONF_R_VARIABLE_EXPANSION_TOO_LONG);
+				goto err;
+			}
+			if (!BUF_MEM_grow_clean(buf, newsize)) {
+				CONFerror(CONF_R_MODULE_INITIALIZATION_ERROR);
+				goto err;
+			}
+			while (*p)
+				buf->data[to++] = *(p++);
+
+			/* Since we change the pointer 'from', we also have
+			   to change the perceived length of the string it
+			   points at.  /RL */
+			len -= e - from;
+			from = e;
+
+			/* In case there were no braces or parenthesis around
+			   the variable reference, we have to put back the
+			   character that was replaced with a '\0'.  /RL */
+			*rp = r;
+		} else
+			buf->data[to++] = *(from++);
+	}
+	buf->data[to]='\0';
+	free(*pto);
+	*pto = buf->data;
+	free(buf);
+	return (1);
+
+err:
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	return (0);
+}
+
+static char *
+eat_ws(CONF *conf, char *p)
+{
+	while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
+		p++;
+	return (p);
+}
+
+static char *
+eat_alpha_numeric(CONF *conf, char *p)
+{
+	for (;;) {
+		if (IS_ESC(conf, *p)) {
+			p = scan_esc(conf, p);
+			continue;
+		}
+		if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p))
+			return (p);
+		p++;
+	}
+}
+
+static char *
+scan_quote(CONF *conf, char *p)
+{
+	int q = *p;
+
+	p++;
+	while (!(IS_EOF(conf, *p)) && (*p != q)) {
+		if (IS_ESC(conf, *p)) {
+			p++;
+			if (IS_EOF(conf, *p))
+				return (p);
+		}
+		p++;
+	}
+	if (*p == q)
+		p++;
+	return (p);
+}
+
+
+static char *
+scan_dquote(CONF *conf, char *p)
+{
+	int q = *p;
+
+	p++;
+	while (!(IS_EOF(conf, *p))) {
+		if (*p == q) {
+			if (*(p + 1) == q) {
+				p++;
+			} else {
+				break;
+			}
+		}
+		p++;
+	}
+	if (*p == q)
+		p++;
+	return (p);
+}
+
+static void
+dump_value_doall_arg(CONF_VALUE *a, BIO *out)
+{
+	if (a->name)
+		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
+	else
+		BIO_printf(out, "[[%s]]\n", a->section);
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
+
+static int
+def_dump(const CONF *conf, BIO *out)
+{
+	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
+	    BIO, out);
+	return 1;
+}
+
+static int
+def_is_number(const CONF *conf, char c)
+{
+	return IS_NUMBER(conf, c);
+}
+
+static int
+def_to_int(const CONF *conf, char c)
+{
+	return c - '0';
+}
diff --git a/crypto/conf/conf_def.h b/crypto/conf/conf_def.h
new file mode 100644
index 0000000..956e443
--- /dev/null
+++ b/crypto/conf/conf_def.h
@@ -0,0 +1,166 @@
+/* $OpenBSD: conf_def.h,v 1.6 2016/12/21 15:49:29 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* THIS FILE WAS AUTOMAGICALLY GENERATED!
+   Please modify and use keysets.pl to regenerate it. */
+
+__BEGIN_HIDDEN_DECLS
+
+#define CONF_NUMBER		1
+#define CONF_UPPER		2
+#define CONF_LOWER		4
+#define CONF_UNDER		256
+#define CONF_PUNCTUATION	512
+#define CONF_WS			16
+#define CONF_ESC		32
+#define CONF_QUOTE		64
+#define CONF_DQUOTE		1024
+#define CONF_COMMENT		128
+#define CONF_FCOMMENT		2048
+#define CONF_EOF		8
+#define CONF_HIGHBIT		4096
+#define CONF_ALPHA		(CONF_UPPER|CONF_LOWER)
+#define CONF_ALPHA_NUMERIC	(CONF_ALPHA|CONF_NUMBER|CONF_UNDER)
+#define CONF_ALPHA_NUMERIC_PUNCT (CONF_ALPHA|CONF_NUMBER|CONF_UNDER| \
+					CONF_PUNCTUATION)
+
+#define KEYTYPES(c)		((unsigned short *)((c)->meth_data))
+#define IS_COMMENT(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_COMMENT)
+#define IS_FCOMMENT(c,a)	(KEYTYPES(c)[(a)&0xff]&CONF_FCOMMENT)
+#define IS_EOF(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_EOF)
+#define IS_ESC(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_ESC)
+#define IS_NUMBER(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_NUMBER)
+#define IS_WS(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_WS)
+#define IS_ALPHA_NUMERIC(c,a)	(KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC)
+#define IS_ALPHA_NUMERIC_PUNCT(c,a) \
+				(KEYTYPES(c)[(a)&0xff]&CONF_ALPHA_NUMERIC_PUNCT)
+#define IS_QUOTE(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_QUOTE)
+#define IS_DQUOTE(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_DQUOTE)
+#define IS_HIGHBIT(c,a)		(KEYTYPES(c)[(a)&0xff]&CONF_HIGHBIT)
+
+static unsigned short CONF_type_default[256] = {
+	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,
+	0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x0200,
+	0x0200, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0000, 0x0020, 0x0000, 0x0200, 0x0100,
+	0x0040, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+};
+
+static unsigned short CONF_type_win32[256] = {
+	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,
+	0x0000, 0x0000, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200,
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0000, 0x0A00, 0x0000, 0x0000, 0x0000, 0x0200,
+	0x0200, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+	0x0002, 0x0002, 0x0002, 0x0000, 0x0000, 0x0000, 0x0200, 0x0100,
+	0x0000, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+	0x0004, 0x0004, 0x0004, 0x0000, 0x0200, 0x0000, 0x0200, 0x0000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+	0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
+};
+
+__END_HIDDEN_DECLS
diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c
new file mode 100644
index 0000000..e6c707a
--- /dev/null
+++ b/crypto/conf/conf_err.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: conf_err.c,v 1.15 2022/07/12 14:42:48 kn Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CONF,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CONF,0,reason)
+
+static ERR_STRING_DATA CONF_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA CONF_str_reasons[]= {
+	{ERR_REASON(CONF_R_ERROR_LOADING_DSO)    , "error loading dso"},
+	{ERR_REASON(CONF_R_LIST_CANNOT_BE_NULL)  , "list cannot be null"},
+	{ERR_REASON(CONF_R_MISSING_CLOSE_SQUARE_BRACKET), "missing close square bracket"},
+	{ERR_REASON(CONF_R_MISSING_EQUAL_SIGN)   , "missing equal sign"},
+	{ERR_REASON(CONF_R_MISSING_FINISH_FUNCTION), "missing finish function"},
+	{ERR_REASON(CONF_R_MISSING_INIT_FUNCTION), "missing init function"},
+	{ERR_REASON(CONF_R_MODULE_INITIALIZATION_ERROR), "module initialization error"},
+	{ERR_REASON(CONF_R_NO_CLOSE_BRACE)       , "no close brace"},
+	{ERR_REASON(CONF_R_NO_CONF)              , "no conf"},
+	{ERR_REASON(CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE), "no conf or environment variable"},
+	{ERR_REASON(CONF_R_NO_SECTION)           , "no section"},
+	{ERR_REASON(CONF_R_NO_SUCH_FILE)         , "no such file"},
+	{ERR_REASON(CONF_R_NO_VALUE)             , "no value"},
+	{ERR_REASON(CONF_R_UNABLE_TO_CREATE_NEW_SECTION), "unable to create new section"},
+	{ERR_REASON(CONF_R_UNKNOWN_MODULE_NAME)  , "unknown module name"},
+	{ERR_REASON(CONF_R_VARIABLE_EXPANSION_TOO_LONG), "variable expansion too long"},
+	{ERR_REASON(CONF_R_VARIABLE_HAS_NO_VALUE), "variable has no value"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_CONF_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(CONF_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, CONF_str_functs);
+		ERR_load_strings(0, CONF_str_reasons);
+	}
+#endif
+}
diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
new file mode 100644
index 0000000..995ba3e
--- /dev/null
+++ b/crypto/conf/conf_lib.c
@@ -0,0 +1,375 @@
+/* $OpenBSD: conf_lib.c,v 1.15 2017/01/29 17:49:22 beck Exp $ */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static CONF_METHOD *default_CONF_method = NULL;
+
+/* Init a 'CONF' structure from an old LHASH */
+
+void
+CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash)
+{
+	if (default_CONF_method == NULL)
+		default_CONF_method = NCONF_default();
+	default_CONF_method->init(conf);
+	conf->data = hash;
+}
+
+/* The following section contains the "CONF classic" functions,
+   rewritten in terms of the new CONF interface. */
+
+int
+CONF_set_default_method(CONF_METHOD *meth)
+{
+	default_CONF_method = meth;
+	return 1;
+}
+
+LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
+    long *eline)
+{
+	LHASH_OF(CONF_VALUE) *ltmp;
+	BIO *in = NULL;
+
+	in = BIO_new_file(file, "rb");
+	if (in == NULL) {
+		CONFerror(ERR_R_SYS_LIB);
+		return NULL;
+	}
+
+	ltmp = CONF_load_bio(conf, in, eline);
+	BIO_free(in);
+
+	return ltmp;
+}
+
+LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
+    long *eline)
+{
+	BIO *btmp;
+	LHASH_OF(CONF_VALUE) *ltmp;
+
+	if (!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+		CONFerror(ERR_R_BUF_LIB);
+		return NULL;
+	}
+	ltmp = CONF_load_bio(conf, btmp, eline);
+	BIO_free(btmp);
+	return ltmp;
+}
+
+LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
+    long *eline)
+{
+	CONF ctmp;
+	int ret;
+
+	CONF_set_nconf(&ctmp, conf);
+
+	ret = NCONF_load_bio(&ctmp, bp, eline);
+	if (ret)
+		return ctmp.data;
+	return NULL;
+}
+
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
+    const char *section)
+{
+	if (conf == NULL) {
+		return NULL;
+	} else {
+		CONF ctmp;
+		CONF_set_nconf(&ctmp, conf);
+		return NCONF_get_section(&ctmp, section);
+	}
+}
+
+char *
+CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group,
+    const char *name)
+{
+	if (conf == NULL) {
+		return NCONF_get_string(NULL, group, name);
+	} else {
+		CONF ctmp;
+		CONF_set_nconf(&ctmp, conf);
+		return NCONF_get_string(&ctmp, group, name);
+	}
+}
+
+long
+CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group,
+    const char *name)
+{
+	int status;
+	long result = 0;
+
+	if (conf == NULL) {
+		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);
+	}
+
+	if (status == 0) {
+		/* This function does not believe in errors... */
+		ERR_clear_error();
+	}
+	return result;
+}
+
+void
+CONF_free(LHASH_OF(CONF_VALUE) *conf)
+{
+	CONF ctmp;
+
+	CONF_set_nconf(&ctmp, conf);
+	NCONF_free_data(&ctmp);
+}
+
+int
+CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out)
+{
+	BIO *btmp;
+	int ret;
+
+	if (!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
+		CONFerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	ret = CONF_dump_bio(conf, btmp);
+	BIO_free(btmp);
+	return ret;
+}
+
+int
+CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
+{
+	CONF ctmp;
+
+	CONF_set_nconf(&ctmp, conf);
+	return NCONF_dump_bio(&ctmp, out);
+}
+
+/* The following section contains the "New CONF" functions.  They are
+   completely centralised around a new CONF structure that may contain
+   basically anything, but at least a method pointer and a table of data.
+   These functions are also written in terms of the bridge functions used
+   by the "CONF classic" functions, for consistency.  */
+
+CONF *
+NCONF_new(CONF_METHOD *meth)
+{
+	CONF *ret;
+
+	if (meth == NULL)
+		meth = NCONF_default();
+
+	ret = meth->create(meth);
+	if (ret == NULL) {
+		CONFerror(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+
+	return ret;
+}
+
+void
+NCONF_free(CONF *conf)
+{
+	if (conf == NULL)
+		return;
+	conf->meth->destroy(conf);
+}
+
+void
+NCONF_free_data(CONF *conf)
+{
+	if (conf == NULL)
+		return;
+	conf->meth->destroy_data(conf);
+}
+
+int
+NCONF_load(CONF *conf, const char *file, long *eline)
+{
+	if (conf == NULL) {
+		CONFerror(CONF_R_NO_CONF);
+		return 0;
+	}
+
+	return conf->meth->load(conf, file, eline);
+}
+
+int
+NCONF_load_fp(CONF *conf, FILE *fp, long *eline)
+{
+	BIO *btmp;
+	int ret;
+
+	if (!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+		CONFerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	ret = NCONF_load_bio(conf, btmp, eline);
+	BIO_free(btmp);
+	return ret;
+}
+
+int
+NCONF_load_bio(CONF *conf, BIO *bp, long *eline)
+{
+	if (conf == NULL) {
+		CONFerror(CONF_R_NO_CONF);
+		return 0;
+	}
+
+	return conf->meth->load_bio(conf, bp, eline);
+}
+
+STACK_OF(CONF_VALUE) *
+NCONF_get_section(const CONF *conf, const char *section)
+{
+	if (conf == NULL) {
+		CONFerror(CONF_R_NO_CONF);
+		return NULL;
+	}
+
+	if (section == NULL) {
+		CONFerror(CONF_R_NO_SECTION);
+		return NULL;
+	}
+
+	return _CONF_get_section_values(conf, section);
+}
+
+char *
+NCONF_get_string(const CONF *conf, const char *group, const char *name)
+{
+	char *s = _CONF_get_string(conf, group, name);
+
+        /* Since we may get a value from an environment variable even
+           if conf is NULL, let's check the value first */
+	if (s)
+		return s;
+
+	if (conf == NULL) {
+		CONFerror(CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE);
+		return NULL;
+	}
+	CONFerror(CONF_R_NO_VALUE);
+	ERR_asprintf_error_data("group=%s name=%s",
+	    group ? group : "", name);
+	return NULL;
+}
+
+int
+NCONF_get_number_e(const CONF *conf, const char *group, const char *name,
+    long *result)
+{
+	char *str;
+
+	if (result == NULL) {
+		CONFerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+
+	str = NCONF_get_string(conf, group, name);
+
+	if (str == NULL)
+		return 0;
+
+	for (*result = 0; conf->meth->is_number(conf, *str); ) {
+		*result = (*result) * 10 + conf->meth->to_int(conf, *str);
+		str++;
+	}
+
+	return 1;
+}
+
+int
+NCONF_dump_fp(const CONF *conf, FILE *out)
+{
+	BIO *btmp;
+	int ret;
+	if (!(btmp = BIO_new_fp(out, BIO_NOCLOSE))) {
+		CONFerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	ret = NCONF_dump_bio(conf, btmp);
+	BIO_free(btmp);
+	return ret;
+}
+
+int
+NCONF_dump_bio(const CONF *conf, BIO *out)
+{
+	if (conf == NULL) {
+		CONFerror(CONF_R_NO_CONF);
+		return 0;
+	}
+
+	return conf->meth->dump(conf, out);
+}
diff --git a/crypto/conf/conf_mall.c b/crypto/conf/conf_mall.c
new file mode 100644
index 0000000..18631b3
--- /dev/null
+++ b/crypto/conf/conf_mall.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: conf_mall.c,v 1.9 2014/07/11 08:44:48 jsing Exp $ */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+/* Load all OpenSSL builtin modules */
+
+void
+OPENSSL_load_builtin_modules(void)
+{
+	/* Add builtin modules here */
+	ASN1_add_oid_module();
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_add_conf_module();
+#endif
+}
diff --git a/crypto/conf/conf_mod.c b/crypto/conf/conf_mod.c
new file mode 100644
index 0000000..aab108a
--- /dev/null
+++ b/crypto/conf/conf_mod.c
@@ -0,0 +1,527 @@
+/* $OpenBSD: conf_mod.c,v 1.28 2023/07/20 15:05:30 tb Exp $ */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* This structure contains data about supported modules. */
+struct conf_module_st {
+	/* Name of the module */
+	char *name;
+	/* Init function */
+	conf_init_func *init;
+	/* Finish function */
+	conf_finish_func *finish;
+	/* Number of successfully initialized modules */
+	int links;
+	void *usr_data;
+};
+
+
+/* This structure contains information about modules that have been
+ * successfully initialized. There may be more than one entry for a
+ * given module.
+ */
+
+struct conf_imodule_st {
+	CONF_MODULE *pmod;
+	char *name;
+	char *value;
+	unsigned long flags;
+	void *usr_data;
+};
+
+static STACK_OF(CONF_MODULE) *supported_modules = NULL;
+static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
+
+static void module_free(CONF_MODULE *md);
+static void module_finish(CONF_IMODULE *imod);
+static int module_run(const CONF *cnf, char *name, char *value,
+    unsigned long flags);
+static CONF_MODULE *module_add(const char *name, conf_init_func *ifunc,
+    conf_finish_func *ffunc);
+static CONF_MODULE *module_find(char *name);
+static int module_init(CONF_MODULE *pmod, char *name, char *value,
+    const CONF *cnf);
+
+/* Main function: load modules from a CONF structure */
+
+int
+CONF_modules_load(const CONF *cnf, const char *appname, unsigned long flags)
+{
+	STACK_OF(CONF_VALUE) *values;
+	CONF_VALUE *vl;
+	char *vsection = NULL;
+
+	int ret, i;
+
+	if (!cnf)
+		return 1;
+
+	if (appname)
+		vsection = NCONF_get_string(cnf, NULL, appname);
+
+	if (!appname || (!vsection && (flags & CONF_MFLAGS_DEFAULT_SECTION)))
+		vsection = NCONF_get_string(cnf, NULL, "openssl_conf");
+
+	if (!vsection) {
+		ERR_clear_error();
+		return 1;
+	}
+
+	values = NCONF_get_section(cnf, vsection);
+
+	if (!values)
+		return 0;
+
+	for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+		vl = sk_CONF_VALUE_value(values, i);
+		ret = module_run(cnf, vl->name, vl->value, flags);
+		if (ret <= 0)
+			if (!(flags & CONF_MFLAGS_IGNORE_ERRORS))
+				return ret;
+	}
+
+	return 1;
+}
+
+int
+CONF_modules_load_file(const char *filename, const char *appname,
+    unsigned long flags)
+{
+	char *file = NULL;
+	CONF *conf = NULL;
+	int ret = 0;
+	conf = NCONF_new(NULL);
+	if (!conf)
+		goto err;
+
+	if (filename == NULL) {
+		file = CONF_get1_default_config_file();
+		if (!file)
+			goto err;
+	} else
+		file = (char *)filename;
+
+	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);
+
+err:
+	if (filename == NULL)
+		free(file);
+	NCONF_free(conf);
+
+	return ret;
+}
+
+static int
+module_run(const CONF *cnf, char *name, char *value, unsigned long flags)
+{
+	CONF_MODULE *md;
+	int ret;
+
+	if ((md = module_find(name)) == NULL) {
+		if (!(flags & CONF_MFLAGS_SILENT)) {
+			CONFerror(CONF_R_UNKNOWN_MODULE_NAME);
+			ERR_asprintf_error_data("module=%s", name);
+		}
+		return -1;
+	}
+
+	ret = module_init(md, name, value, cnf);
+
+	if (ret <= 0) {
+		if (!(flags & CONF_MFLAGS_SILENT)) {
+			CONFerror(CONF_R_MODULE_INITIALIZATION_ERROR);
+			ERR_asprintf_error_data
+			    ("module=%s, value=%s, retcode=%-8d",
+			    name, value, ret);
+		}
+	}
+
+	return ret;
+}
+
+/* add module to list */
+static CONF_MODULE *
+module_add(const char *name, conf_init_func *ifunc, conf_finish_func *ffunc)
+{
+	CONF_MODULE *tmod = NULL;
+
+	if (name == NULL)
+		return NULL;
+	if (supported_modules == NULL)
+		supported_modules = sk_CONF_MODULE_new_null();
+	if (supported_modules == NULL)
+		return NULL;
+	tmod = malloc(sizeof(CONF_MODULE));
+	if (tmod == NULL)
+		return NULL;
+
+	tmod->name = strdup(name);
+	tmod->init = ifunc;
+	tmod->finish = ffunc;
+	tmod->links = 0;
+
+	if (!sk_CONF_MODULE_push(supported_modules, tmod)) {
+		free(tmod);
+		return NULL;
+	}
+
+	return tmod;
+}
+
+/* Find a module from the list. We allow module names of the
+ * form modname.XXXX to just search for modname to allow the
+ * same module to be initialized more than once.
+ */
+
+static CONF_MODULE *
+module_find(char *name)
+{
+	CONF_MODULE *tmod;
+	int i, nchar;
+	char *p;
+
+	p = strrchr(name, '.');
+
+	if (p)
+		nchar = p - name;
+	else
+		nchar = strlen(name);
+
+	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))
+			return tmod;
+	}
+
+	return NULL;
+}
+
+/* initialize a module */
+static int
+module_init(CONF_MODULE *pmod, char *name, char *value, const CONF *cnf)
+{
+	int ret = 1;
+	int init_called = 0;
+	CONF_IMODULE *imod = NULL;
+
+	/* Otherwise add initialized module to list */
+	imod = malloc(sizeof(CONF_IMODULE));
+	if (!imod)
+		goto err;
+
+	imod->pmod = pmod;
+	imod->name = name ? strdup(name) : NULL;
+	imod->value = value ? strdup(value) : NULL;
+	imod->usr_data = NULL;
+
+	if (!imod->name || !imod->value)
+		goto memerr;
+
+	/* Try to initialize module */
+	if (pmod->init) {
+		ret = pmod->init(imod, cnf);
+		init_called = 1;
+		/* Error occurred, exit */
+		if (ret <= 0)
+			goto err;
+	}
+
+	if (initialized_modules == NULL) {
+		initialized_modules = sk_CONF_IMODULE_new_null();
+		if (!initialized_modules) {
+			CONFerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	}
+
+	if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
+		CONFerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	pmod->links++;
+
+	return ret;
+
+err:
+	/* We've started the module so we'd better finish it */
+	if (pmod->finish && init_called)
+		pmod->finish(imod);
+
+memerr:
+	if (imod) {
+		free(imod->name);
+		free(imod->value);
+		free(imod);
+	}
+
+	return -1;
+}
+
+/* Unload any dynamic modules that have a link count of zero:
+ * i.e. have no active initialized modules. If 'all' is set
+ * then all modules are unloaded including static ones.
+ */
+
+void
+CONF_modules_unload(int all)
+{
+	int i;
+	CONF_MODULE *md;
+
+	CONF_modules_finish();
+
+	/* 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);
+		if (!all)
+			continue;
+		/* Since we're working in reverse this is OK */
+		(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;
+	}
+}
+
+/* unload a single module */
+static void
+module_free(CONF_MODULE *md)
+{
+	free(md->name);
+	free(md);
+}
+
+/* finish and free up all modules instances */
+
+void
+CONF_modules_finish(void)
+{
+	CONF_IMODULE *imod;
+
+	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;
+}
+
+/* finish a module instance */
+
+static void
+module_finish(CONF_IMODULE *imod)
+{
+	if (imod->pmod->finish)
+		imod->pmod->finish(imod);
+	imod->pmod->links--;
+	free(imod->name);
+	free(imod->value);
+	free(imod);
+}
+
+/* Add a static module to OpenSSL */
+
+int
+CONF_module_add(const char *name, conf_init_func *ifunc, conf_finish_func *ffunc)
+{
+	return module_add(name, ifunc, ffunc) != NULL;
+}
+
+void
+CONF_modules_free(void)
+{
+	CONF_modules_finish();
+	CONF_modules_unload(1);
+}
+
+/* Utility functions */
+
+const char *
+CONF_imodule_get_name(const CONF_IMODULE *md)
+{
+	return md->name;
+}
+
+const char *
+CONF_imodule_get_value(const CONF_IMODULE *md)
+{
+	return md->value;
+}
+
+void *
+CONF_imodule_get_usr_data(const CONF_IMODULE *md)
+{
+	return md->usr_data;
+}
+
+void
+CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data)
+{
+	md->usr_data = usr_data;
+}
+
+CONF_MODULE *
+CONF_imodule_get_module(const CONF_IMODULE *md)
+{
+	return md->pmod;
+}
+
+unsigned long
+CONF_imodule_get_flags(const CONF_IMODULE *md)
+{
+	return md->flags;
+}
+
+void
+CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags)
+{
+	md->flags = flags;
+}
+
+void *
+CONF_module_get_usr_data(CONF_MODULE *pmod)
+{
+	return pmod->usr_data;
+}
+
+void
+CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data)
+{
+	pmod->usr_data = usr_data;
+}
+
+/* Return default config file name */
+
+char *
+CONF_get1_default_config_file(void)
+{
+	char *file = NULL;
+
+	if (asprintf(&file, "%s/openssl.cnf",
+	    X509_get_default_cert_area()) == -1)
+		return (NULL);
+	return file;
+}
+
+/* This function takes a list separated by 'sep' and calls the
+ * callback function giving the start and length of each member
+ * optionally stripping leading and trailing whitespace. This can
+ * be used to parse comma separated lists for example.
+ */
+
+int
+CONF_parse_list(const char *list_, int sep, int nospc,
+    int (*list_cb)(const char *elem, int len, void *usr), void *arg)
+{
+	int ret;
+	const char *lstart, *tmpend, *p;
+
+	if (list_ == NULL) {
+		CONFerror(CONF_R_LIST_CANNOT_BE_NULL);
+		return 0;
+	}
+
+	lstart = list_;
+	for (;;) {
+		if (nospc) {
+			while (*lstart && isspace((unsigned char)*lstart))
+				lstart++;
+		}
+		p = strchr(lstart, sep);
+		if (p == lstart || !*lstart)
+			ret = list_cb(NULL, 0, arg);
+		else {
+			if (p)
+				tmpend = p - 1;
+			else
+				tmpend = lstart + strlen(lstart) - 1;
+			if (nospc) {
+				while (isspace((unsigned char)*tmpend))
+					tmpend--;
+			}
+			ret = list_cb(lstart, tmpend - lstart + 1, arg);
+		}
+		if (ret <= 0)
+			return ret;
+		if (p == NULL)
+			return 1;
+		lstart = p + 1;
+	}
+}
diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c
new file mode 100644
index 0000000..827cf96
--- /dev/null
+++ b/crypto/conf/conf_sap.c
@@ -0,0 +1,154 @@
+/* $OpenBSD: conf_sap.c,v 1.14 2018/03/19 03:56:08 beck Exp $ */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+/* This is the automatic configuration loader: it is called automatically by
+ * OpenSSL when any of a number of standard initialisation functions are called,
+ * unless this is overridden by calling OPENSSL_no_config()
+ */
+
+static pthread_once_t openssl_configured = PTHREAD_ONCE_INIT;
+
+static const char *openssl_config_name;
+
+static void
+OPENSSL_config_internal(void)
+{
+	OPENSSL_load_builtin_modules();
+#ifndef OPENSSL_NO_ENGINE
+	/* Need to load ENGINEs */
+	ENGINE_load_builtin_engines();
+#endif
+	/* Add others here? */
+
+	ERR_clear_error();
+	if (CONF_modules_load_file(NULL, openssl_config_name,
+	    CONF_MFLAGS_DEFAULT_SECTION|CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
+		BIO *bio_err;
+		ERR_load_crypto_strings();
+		if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) != NULL) {
+			BIO_printf(bio_err, "Auto configuration failed\n");
+			ERR_print_errors(bio_err);
+			BIO_free(bio_err);
+		}
+		exit(1);
+	}
+
+	return;
+}
+
+int
+OpenSSL_config(const char *config_name)
+{
+	/* Don't override if NULL */
+	/*
+	 * Note - multiple threads calling this with *different* config names
+	 * is probably not advisable.  One thread will win, but you don't know
+	 * if it will be the same thread as wins the pthread_once.
+	 */
+	if (config_name != NULL)
+		openssl_config_name = config_name;
+
+	if (OPENSSL_init_crypto(0, NULL) == 0)
+		return 0;
+
+	if (pthread_once(&openssl_configured, OPENSSL_config_internal) != 0)
+		return 0;
+
+	return 1;
+}
+
+void
+OPENSSL_config(const char *config_name)
+{
+	(void) OpenSSL_config(config_name);
+}
+
+static void
+OPENSSL_no_config_internal(void)
+{
+}
+
+int
+OpenSSL_no_config(void)
+{
+	if (pthread_once(&openssl_configured, OPENSSL_no_config_internal) != 0)
+		return 0;
+
+	return 1;
+}
+
+void
+OPENSSL_no_config(void)
+{
+	(void) OpenSSL_no_config();
+}
diff --git a/crypto/constant_time.h b/crypto/constant_time.h
new file mode 100644
index 0000000..ea7dede
--- /dev/null
+++ b/crypto/constant_time.h
@@ -0,0 +1,207 @@
+/*	$OpenBSD: constant_time.h,v 1.3 2023/04/06 18:43:47 tb Exp $ */
+/*-
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CONSTANT_TIME_H
+#define HEADER_CONSTANT_TIME_H
+
+__BEGIN_HIDDEN_DECLS
+
+/*-
+ * The boolean methods return a bitmask of all ones (0xff...f) for true
+ * and 0 for false. This is useful for choosing a value based on the result
+ * of a conditional in constant time. For example,
+ *
+ * if (a < b) {
+ *   c = a;
+ * } else {
+ *   c = b;
+ * }
+ *
+ * can be written as
+ *
+ * unsigned int lt = constant_time_lt(a, b);
+ * c = constant_time_select(lt, a, b);
+ */
+
+/*
+ * Returns the given value with the MSB copied to all the other
+ * bits. Uses the fact that arithmetic shift shifts-in the sign bit.
+ * However, this is not ensured by the C standard so you may need to
+ * replace this with something else on odd CPUs.
+ */
+static inline unsigned int constant_time_msb(unsigned int a);
+
+/*
+ * Returns 0xff..f if a < b and 0 otherwise.
+ */
+static inline unsigned int constant_time_lt(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_lt_8(unsigned int a,
+                                               unsigned int b);
+
+/*
+ * Returns 0xff..f if a >= b and 0 otherwise.
+ */
+static inline unsigned int constant_time_ge(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_ge_8(unsigned int a,
+                                               unsigned int b);
+
+/*
+ * Returns 0xff..f if a == 0 and 0 otherwise.
+ */
+static inline unsigned int constant_time_is_zero(unsigned int a);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_is_zero_8(unsigned int a);
+
+/*
+ * Returns 0xff..f if a == b and 0 otherwise.
+ */
+static inline unsigned int constant_time_eq(unsigned int a, unsigned int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_eq_8(unsigned int a,
+                                               unsigned int b);
+/* Signed integers. */
+static inline unsigned int constant_time_eq_int(int a, int b);
+/* Convenience method for getting an 8-bit mask. */
+static inline unsigned char constant_time_eq_int_8(int a, int b);
+
+/*-
+ * Returns (mask & a) | (~mask & b).
+ *
+ * When |mask| is all 1s or all 0s (as returned by the methods above),
+ * the select methods return either |a| (if |mask| is nonzero) or |b|
+ * (if |mask| is zero).
+ */
+static inline unsigned int constant_time_select(unsigned int mask,
+                                                unsigned int a,
+                                                unsigned int b);
+/* Convenience method for unsigned chars. */
+static inline unsigned char constant_time_select_8(unsigned char mask,
+                                                   unsigned char a,
+                                                   unsigned char b);
+/* Convenience method for signed integers. */
+static inline int constant_time_select_int(unsigned int mask, int a, int b);
+
+static inline unsigned int constant_time_msb(unsigned int a)
+{
+    return 0 - (a >> (sizeof(a) * 8 - 1));
+}
+
+static inline unsigned int constant_time_lt(unsigned int a, unsigned int b)
+{
+    return constant_time_msb(a ^ ((a ^ b) | ((a - b) ^ b)));
+}
+
+static inline unsigned char constant_time_lt_8(unsigned int a, unsigned int b)
+{
+    return (unsigned char)(constant_time_lt(a, b));
+}
+
+static inline unsigned int constant_time_ge(unsigned int a, unsigned int b)
+{
+    return ~constant_time_lt(a, b);
+}
+
+static inline unsigned char constant_time_ge_8(unsigned int a, unsigned int b)
+{
+    return (unsigned char)(constant_time_ge(a, b));
+}
+
+static inline unsigned int constant_time_is_zero(unsigned int a)
+{
+    return constant_time_msb(~a & (a - 1));
+}
+
+static inline unsigned char constant_time_is_zero_8(unsigned int a)
+{
+    return (unsigned char)(constant_time_is_zero(a));
+}
+
+static inline unsigned int constant_time_eq(unsigned int a, unsigned int b)
+{
+    return constant_time_is_zero(a ^ b);
+}
+
+static inline unsigned char constant_time_eq_8(unsigned int a, unsigned int b)
+{
+    return (unsigned char)(constant_time_eq(a, b));
+}
+
+static inline unsigned int constant_time_eq_int(int a, int b)
+{
+    return constant_time_eq((unsigned)(a), (unsigned)(b));
+}
+
+static inline unsigned char constant_time_eq_int_8(int a, int b)
+{
+    return constant_time_eq_8((unsigned)(a), (unsigned)(b));
+}
+
+static inline unsigned int constant_time_select(unsigned int mask,
+                                                unsigned int a,
+                                                unsigned int b)
+{
+    return (mask & a) | (~mask & b);
+}
+
+static inline unsigned char constant_time_select_8(unsigned char mask,
+                                                   unsigned char a,
+                                                   unsigned char b)
+{
+    return (unsigned char)(constant_time_select(mask, a, b));
+}
+
+static inline int constant_time_select_int(unsigned int mask, int a, int b)
+{
+    return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
+}
+
+void err_clear_last_constant_time(int clear);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_CONSTANT_TIME_H */
diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c
new file mode 100644
index 0000000..ff4e5c4
--- /dev/null
+++ b/crypto/cpt_err.c
@@ -0,0 +1,100 @@
+/* $OpenBSD: cpt_err.c,v 1.15 2023/07/08 08:28:23 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_CRYPTO,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_CRYPTO,0,reason)
+
+static ERR_STRING_DATA CRYPTO_str_functs[] = {
+	{ERR_FUNC(CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX),	"CRYPTO_get_ex_new_index"},
+	{ERR_FUNC(CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID),	"CRYPTO_get_new_dynlockid"},
+	{ERR_FUNC(CRYPTO_F_CRYPTO_GET_NEW_LOCKID),	"CRYPTO_get_new_lockid"},
+	{ERR_FUNC(CRYPTO_F_CRYPTO_SET_EX_DATA),	"CRYPTO_set_ex_data"},
+	{ERR_FUNC(CRYPTO_F_DEF_ADD_INDEX),	"DEF_ADD_INDEX"},
+	{ERR_FUNC(CRYPTO_F_DEF_GET_CLASS),	"DEF_GET_CLASS"},
+	{ERR_FUNC(CRYPTO_F_FIPS_MODE_SET),	"FIPS_mode_set"},
+	{ERR_FUNC(CRYPTO_F_INT_DUP_EX_DATA),	"INT_DUP_EX_DATA"},
+	{ERR_FUNC(CRYPTO_F_INT_FREE_EX_DATA),	"INT_FREE_EX_DATA"},
+	{ERR_FUNC(CRYPTO_F_INT_NEW_EX_DATA),	"INT_NEW_EX_DATA"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA CRYPTO_str_reasons[] = {
+	{ERR_REASON(CRYPTO_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"},
+	{ERR_REASON(CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK), "no dynlock create callback"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_CRYPTO_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(CRYPTO_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, CRYPTO_str_functs);
+		ERR_load_strings(0, CRYPTO_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_CRYPTO_strings);
diff --git a/crypto/cpuid-elf-x86_64.S b/crypto/cpuid-elf-x86_64.S
new file mode 100644
index 0000000..6dc8e58
--- /dev/null
+++ b/crypto/cpuid-elf-x86_64.S
@@ -0,0 +1,141 @@
+#include "x86_arch.h"
+
+.hidden	OPENSSL_cpuid_setup
+.section	.init
+	endbr64
+	call	OPENSSL_cpuid_setup
+
+
+.hidden	OPENSSL_ia32cap_P
+
+.text	
+
+.globl	OPENSSL_ia32_cpuid
+.type	OPENSSL_ia32_cpuid,@function
+.align	16
+OPENSSL_ia32_cpuid:
+	endbr64
+	movq	%rbx,%r8
+
+	xorl	%eax,%eax
+	cpuid
+	movl	%eax,%r11d
+
+	xorl	%eax,%eax
+	cmpl	$1970169159,%ebx
+	setne	%al
+	movl	%eax,%r9d
+	cmpl	$1231384169,%edx
+	setne	%al
+	orl	%eax,%r9d
+	cmpl	$1818588270,%ecx
+	setne	%al
+	orl	%eax,%r9d
+	jz	.Lintel
+
+	cmpl	$1752462657,%ebx
+	setne	%al
+	movl	%eax,%r10d
+	cmpl	$1769238117,%edx
+	setne	%al
+	orl	%eax,%r10d
+	cmpl	$1145913699,%ecx
+	setne	%al
+	orl	%eax,%r10d
+	jnz	.Lintel
+
+
+	movl	$2147483648,%eax
+	cpuid
+	cmpl	$2147483649,%eax
+	jb	.Lintel
+	movl	%eax,%r10d
+	movl	$2147483649,%eax
+	cpuid
+	orl	%ecx,%r9d
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	orl	$1,%r9d
+
+	cmpl	$2147483656,%r10d
+	jb	.Lintel
+
+	movl	$2147483656,%eax
+	cpuid
+	movzbq	%cl,%r10
+	incq	%r10
+
+	movl	$1,%eax
+	cpuid
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	.Lgeneric
+	shrl	$16,%ebx
+	cmpb	%r10b,%bl
+	ja	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+	jmp	.Lgeneric
+
+.Lintel:
+	cmpl	$4,%r11d
+	movl	$-1,%r10d
+	jb	.Lnocacheinfo
+
+	movl	$4,%eax
+	movl	$0,%ecx
+	cpuid
+	movl	%eax,%r10d
+	shrl	$14,%r10d
+	andl	$4095,%r10d
+
+.Lnocacheinfo:
+	movl	$1,%eax
+	cpuid
+
+	andl	$(~(IA32CAP_MASK0_INTELP4 | IA32CAP_MASK0_INTEL)),%edx
+	cmpl	$0,%r9d
+	jne	.Lnotintel
+
+	orl	$IA32CAP_MASK0_INTEL,%edx
+	andb	$15,%ah
+	cmpb	$15,%ah
+	jne	.Lnotintel
+
+	orl	$IA32CAP_MASK0_INTELP4,%edx
+.Lnotintel:
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+	cmpl	$0,%r10d
+	je	.Lgeneric
+
+	orl	$IA32CAP_MASK0_HT,%edx
+	shrl	$16,%ebx
+	cmpb	$1,%bl
+	ja	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+
+.Lgeneric:
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	andl	$(~IA32CAP_MASK1_AMD_XOP),%ecx
+	orl	%ecx,%r9d
+
+	movl	%edx,%r10d
+	btl	$IA32CAP_BIT1_OSXSAVE,%r9d
+	jnc	.Lclear_avx
+	xorl	%ecx,%ecx
+.byte	0x0f,0x01,0xd0		
+	andl	$6,%eax
+	cmpl	$6,%eax
+	je	.Ldone
+.Lclear_avx:
+	movl	$(~(IA32CAP_MASK1_AVX | IA32CAP_MASK1_FMA3 | IA32CAP_MASK1_AMD_XOP)),%eax
+	andl	%eax,%r9d
+.Ldone:
+	shlq	$32,%r9
+	movl	%r10d,%eax
+	movq	%r8,%rbx
+	orq	%r9,%rax
+	retq
+.size	OPENSSL_ia32_cpuid,.-OPENSSL_ia32_cpuid
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/cpuid-macosx-x86_64.S b/crypto/cpuid-macosx-x86_64.S
new file mode 100644
index 0000000..5d3f1a7
--- /dev/null
+++ b/crypto/cpuid-macosx-x86_64.S
@@ -0,0 +1,137 @@
+#include "x86_arch.h"
+
+.private_extern	_OPENSSL_cpuid_setup
+.mod_init_func
+	.p2align	3
+	.quad	_OPENSSL_cpuid_setup
+
+
+.private_extern	_OPENSSL_ia32cap_P
+
+.text	
+
+.globl	_OPENSSL_ia32_cpuid
+
+.p2align	4
+_OPENSSL_ia32_cpuid:
+	movq	%rbx,%r8
+
+	xorl	%eax,%eax
+	cpuid
+	movl	%eax,%r11d
+
+	xorl	%eax,%eax
+	cmpl	$1970169159,%ebx
+	setne	%al
+	movl	%eax,%r9d
+	cmpl	$1231384169,%edx
+	setne	%al
+	orl	%eax,%r9d
+	cmpl	$1818588270,%ecx
+	setne	%al
+	orl	%eax,%r9d
+	jz	L$intel
+
+	cmpl	$1752462657,%ebx
+	setne	%al
+	movl	%eax,%r10d
+	cmpl	$1769238117,%edx
+	setne	%al
+	orl	%eax,%r10d
+	cmpl	$1145913699,%ecx
+	setne	%al
+	orl	%eax,%r10d
+	jnz	L$intel
+
+
+	movl	$2147483648,%eax
+	cpuid
+	cmpl	$2147483649,%eax
+	jb	L$intel
+	movl	%eax,%r10d
+	movl	$2147483649,%eax
+	cpuid
+	orl	%ecx,%r9d
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	orl	$1,%r9d
+
+	cmpl	$2147483656,%r10d
+	jb	L$intel
+
+	movl	$2147483656,%eax
+	cpuid
+	movzbq	%cl,%r10
+	incq	%r10
+
+	movl	$1,%eax
+	cpuid
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	L$generic
+	shrl	$16,%ebx
+	cmpb	%r10b,%bl
+	ja	L$generic
+	xorl	$IA32CAP_MASK0_HT,%edx
+	jmp	L$generic
+
+L$intel:
+	cmpl	$4,%r11d
+	movl	$-1,%r10d
+	jb	L$nocacheinfo
+
+	movl	$4,%eax
+	movl	$0,%ecx
+	cpuid
+	movl	%eax,%r10d
+	shrl	$14,%r10d
+	andl	$4095,%r10d
+
+L$nocacheinfo:
+	movl	$1,%eax
+	cpuid
+
+	andl	$(~(IA32CAP_MASK0_INTELP4 | IA32CAP_MASK0_INTEL)),%edx
+	cmpl	$0,%r9d
+	jne	L$notintel
+
+	orl	$IA32CAP_MASK0_INTEL,%edx
+	andb	$15,%ah
+	cmpb	$15,%ah
+	jne	L$notintel
+
+	orl	$IA32CAP_MASK0_INTELP4,%edx
+L$notintel:
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	L$generic
+	xorl	$IA32CAP_MASK0_HT,%edx
+	cmpl	$0,%r10d
+	je	L$generic
+
+	orl	$IA32CAP_MASK0_HT,%edx
+	shrl	$16,%ebx
+	cmpb	$1,%bl
+	ja	L$generic
+	xorl	$IA32CAP_MASK0_HT,%edx
+
+L$generic:
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	andl	$(~IA32CAP_MASK1_AMD_XOP),%ecx
+	orl	%ecx,%r9d
+
+	movl	%edx,%r10d
+	btl	$IA32CAP_BIT1_OSXSAVE,%r9d
+	jnc	L$clear_avx
+	xorl	%ecx,%ecx
+.byte	0x0f,0x01,0xd0		
+	andl	$6,%eax
+	cmpl	$6,%eax
+	je	L$done
+L$clear_avx:
+	movl	$(~(IA32CAP_MASK1_AVX | IA32CAP_MASK1_FMA3 | IA32CAP_MASK1_AMD_XOP)),%eax
+	andl	%eax,%r9d
+L$done:
+	shlq	$32,%r9
+	movl	%r10d,%eax
+	movq	%r8,%rbx
+	orq	%r9,%rax
+	retq
+
diff --git a/crypto/cpuid-masm-x86_64.S b/crypto/cpuid-masm-x86_64.S
new file mode 100644
index 0000000..0dc2192
--- /dev/null
+++ b/crypto/cpuid-masm-x86_64.S
@@ -0,0 +1,209 @@
+; 1 "crypto/cpuid-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/cpuid-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/cpuid-masm-x86_64.S.tmp" 2
+EXTERN	OPENSSL_cpuid_setup:NEAR
+
+.CRT$XCU	SEGMENT READONLY ALIGN(8)
+		DQ	OPENSSL_cpuid_setup
+
+EXTERN	OPENSSL_ia32cap_P:NEAR
+
+
+.CRT$XCU	ENDS
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	OPENSSL_ia32_cpuid
+
+ALIGN	16
+OPENSSL_ia32_cpuid	PROC PUBLIC
+	mov	r8,rbx
+
+	xor	eax,eax
+	cpuid
+	mov	r11d,eax
+
+	xor	eax,eax
+	cmp	ebx,0756e6547h
+	setne	al
+	mov	r9d,eax
+	cmp	edx,049656e69h
+	setne	al
+	or	r9d,eax
+	cmp	ecx,06c65746eh
+	setne	al
+	or	r9d,eax
+	jz	$L$intel
+
+	cmp	ebx,068747541h
+	setne	al
+	mov	r10d,eax
+	cmp	edx,069746E65h
+	setne	al
+	or	r10d,eax
+	cmp	ecx,0444D4163h
+	setne	al
+	or	r10d,eax
+	jnz	$L$intel
+
+
+	mov	eax,080000000h
+	cpuid
+	cmp	eax,080000001h
+	jb	$L$intel
+	mov	r10d,eax
+	mov	eax,080000001h
+	cpuid
+	or	r9d,ecx
+	and	r9d,(1 SHL 11)
+	or	r9d,1
+
+	cmp	r10d,080000008h
+	jb	$L$intel
+
+	mov	eax,080000008h
+	cpuid
+	movzx	r10,cl
+	inc	r10
+
+	mov	eax,1
+	cpuid
+	bt	edx,28
+	jnc	$L$generic
+	shr	ebx,16
+	cmp	bl,r10b
+	ja	$L$generic
+	xor	edx,(1 SHL 28)
+	jmp	$L$generic
+
+$L$intel::
+	cmp	r11d,4
+	mov	r10d,-1
+	jb	$L$nocacheinfo
+
+	mov	eax,4
+	mov	ecx,0
+	cpuid
+	mov	r10d,eax
+	shr	r10d,14
+	and	r10d,0fffh
+
+$L$nocacheinfo::
+	mov	eax,1
+	cpuid
+
+	and	edx,(NOT((1 SHL 20) OR (1 SHL 30)))
+	cmp	r9d,0
+	jne	$L$notintel
+
+	or	edx,(1 SHL 30)
+	and	ah,15
+	cmp	ah,15
+	jne	$L$notintel
+
+	or	edx,(1 SHL 20)
+$L$notintel::
+	bt	edx,28
+	jnc	$L$generic
+	xor	edx,(1 SHL 28)
+	cmp	r10d,0
+	je	$L$generic
+
+	or	edx,(1 SHL 28)
+	shr	ebx,16
+	cmp	bl,1
+	ja	$L$generic
+	xor	edx,(1 SHL 28)
+
+$L$generic::
+	and	r9d,(1 SHL 11)
+	and	ecx,(NOT(1 SHL 11))
+	or	r9d,ecx
+
+	mov	r10d,edx
+	bt	r9d,27
+	jnc	$L$clear_avx
+	xor	ecx,ecx
+DB	00fh,001h,0d0h		
+	and	eax,6
+	cmp	eax,6
+	je	$L$done
+$L$clear_avx::
+	mov	eax,(NOT((1 SHL 28) OR (1 SHL 12) OR (1 SHL 11)))
+	and	r9d,eax
+$L$done::
+	shl	r9,32
+	mov	eax,r10d
+	mov	rbx,r8
+	or	rax,r9
+	DB	0F3h,0C3h		;repret
+OPENSSL_ia32_cpuid	ENDP
+
+.text$	ENDS
+END
+
diff --git a/crypto/cpuid-mingw64-x86_64.S b/crypto/cpuid-mingw64-x86_64.S
new file mode 100644
index 0000000..cf66d0f
--- /dev/null
+++ b/crypto/cpuid-mingw64-x86_64.S
@@ -0,0 +1,137 @@
+#include "x86_arch.h"
+
+
+.section	.ctors
+	.p2align	3
+	.quad	OPENSSL_cpuid_setup
+
+
+
+
+.text	
+
+.globl	OPENSSL_ia32_cpuid
+.def	OPENSSL_ia32_cpuid;	.scl 2;	.type 32;	.endef
+.p2align	4
+OPENSSL_ia32_cpuid:
+	movq	%rbx,%r8
+
+	xorl	%eax,%eax
+	cpuid
+	movl	%eax,%r11d
+
+	xorl	%eax,%eax
+	cmpl	$1970169159,%ebx
+	setne	%al
+	movl	%eax,%r9d
+	cmpl	$1231384169,%edx
+	setne	%al
+	orl	%eax,%r9d
+	cmpl	$1818588270,%ecx
+	setne	%al
+	orl	%eax,%r9d
+	jz	.Lintel
+
+	cmpl	$1752462657,%ebx
+	setne	%al
+	movl	%eax,%r10d
+	cmpl	$1769238117,%edx
+	setne	%al
+	orl	%eax,%r10d
+	cmpl	$1145913699,%ecx
+	setne	%al
+	orl	%eax,%r10d
+	jnz	.Lintel
+
+
+	movl	$2147483648,%eax
+	cpuid
+	cmpl	$2147483649,%eax
+	jb	.Lintel
+	movl	%eax,%r10d
+	movl	$2147483649,%eax
+	cpuid
+	orl	%ecx,%r9d
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	orl	$1,%r9d
+
+	cmpl	$2147483656,%r10d
+	jb	.Lintel
+
+	movl	$2147483656,%eax
+	cpuid
+	movzbq	%cl,%r10
+	incq	%r10
+
+	movl	$1,%eax
+	cpuid
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	.Lgeneric
+	shrl	$16,%ebx
+	cmpb	%r10b,%bl
+	ja	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+	jmp	.Lgeneric
+
+.Lintel:
+	cmpl	$4,%r11d
+	movl	$-1,%r10d
+	jb	.Lnocacheinfo
+
+	movl	$4,%eax
+	movl	$0,%ecx
+	cpuid
+	movl	%eax,%r10d
+	shrl	$14,%r10d
+	andl	$4095,%r10d
+
+.Lnocacheinfo:
+	movl	$1,%eax
+	cpuid
+
+	andl	$(~(IA32CAP_MASK0_INTELP4 | IA32CAP_MASK0_INTEL)),%edx
+	cmpl	$0,%r9d
+	jne	.Lnotintel
+
+	orl	$IA32CAP_MASK0_INTEL,%edx
+	andb	$15,%ah
+	cmpb	$15,%ah
+	jne	.Lnotintel
+
+	orl	$IA32CAP_MASK0_INTELP4,%edx
+.Lnotintel:
+	btl	$IA32CAP_BIT0_HT,%edx
+	jnc	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+	cmpl	$0,%r10d
+	je	.Lgeneric
+
+	orl	$IA32CAP_MASK0_HT,%edx
+	shrl	$16,%ebx
+	cmpb	$1,%bl
+	ja	.Lgeneric
+	xorl	$IA32CAP_MASK0_HT,%edx
+
+.Lgeneric:
+	andl	$IA32CAP_MASK1_AMD_XOP,%r9d
+	andl	$(~IA32CAP_MASK1_AMD_XOP),%ecx
+	orl	%ecx,%r9d
+
+	movl	%edx,%r10d
+	btl	$IA32CAP_BIT1_OSXSAVE,%r9d
+	jnc	.Lclear_avx
+	xorl	%ecx,%ecx
+.byte	0x0f,0x01,0xd0		
+	andl	$6,%eax
+	cmpl	$6,%eax
+	je	.Ldone
+.Lclear_avx:
+	movl	$(~(IA32CAP_MASK1_AVX | IA32CAP_MASK1_FMA3 | IA32CAP_MASK1_AMD_XOP)),%eax
+	andl	%eax,%r9d
+.Ldone:
+	shlq	$32,%r9
+	movl	%r10d,%eax
+	movq	%r8,%rbx
+	orq	%r9,%rax
+	retq
+
diff --git a/crypto/cryptlib.c b/crypto/cryptlib.c
new file mode 100644
index 0000000..18f40e5
--- /dev/null
+++ b/crypto/cryptlib.c
@@ -0,0 +1,384 @@
+/* $OpenBSD: cryptlib.c,v 1.46 2023/07/08 08:28:23 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+static void (*locking_callback)(int mode, int type,
+    const char *file, int line) = NULL;
+static int (*add_lock_callback)(int *pointer, int amount,
+    int type, const char *file, int line) = NULL;
+
+int
+CRYPTO_num_locks(void)
+{
+	return 1;
+}
+
+unsigned long
+(*CRYPTO_get_id_callback(void))(void)
+{
+	return NULL;
+}
+
+void
+CRYPTO_set_id_callback(unsigned long (*func)(void))
+{
+	return;
+}
+
+unsigned long
+CRYPTO_thread_id(void)
+{
+	return (unsigned long)pthread_self();
+}
+
+void
+CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num,
+    const char *file, int line))
+{
+	locking_callback = func;
+}
+
+void
+(*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+	const char *file, int line)
+{
+	return locking_callback;
+}
+
+void
+CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num,
+	const char *file, int line))
+{
+	add_lock_callback = func;
+}
+
+int
+(*CRYPTO_get_add_lock_callback(void))(int *num, int mount, int type,
+    const char *file, int line)
+{
+	return add_lock_callback;
+}
+
+const char *
+CRYPTO_get_lock_name(int lock_num)
+{
+	return "";
+}
+
+struct CRYPTO_dynlock_value *
+CRYPTO_get_dynlock_value(int i)
+{
+	return NULL;
+}
+
+int CRYPTO_get_new_dynlockid(void)
+{
+	return 0;
+}
+
+void
+CRYPTO_destroy_dynlockid(int i)
+{
+	return;
+}
+
+int CRYPTO_get_new_lockid(char *name)
+{
+	return 0;
+}
+
+int
+CRYPTO_THREADID_set_callback(void (*func)(CRYPTO_THREADID *))
+{
+	return 1;
+}
+
+void
+(*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *)
+{
+	return NULL;
+}
+
+void
+CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val)
+{
+	return;
+}
+
+void
+CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr)
+{
+	return;
+}
+
+void
+CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(
+    *dyn_create_function)(const char *file, int line))
+{
+	return;
+}
+
+void
+CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(
+    int mode, struct CRYPTO_dynlock_value *l, const char *file, int line))
+{
+	return;
+}
+
+void
+CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(
+    struct CRYPTO_dynlock_value *l, const char *file, int line))
+{
+	return;
+}
+
+struct CRYPTO_dynlock_value *
+(*CRYPTO_get_dynlock_create_callback(void))(
+    const char *file, int line)
+{
+	return NULL;
+}
+
+void
+(*CRYPTO_get_dynlock_lock_callback(void))(int mode,
+    struct CRYPTO_dynlock_value *l, const char *file, int line)
+{
+	return NULL;
+}
+
+void
+(*CRYPTO_get_dynlock_destroy_callback(void))(
+    struct CRYPTO_dynlock_value *l, const char *file, int line)
+{
+	return NULL;
+}
+
+void
+CRYPTO_THREADID_current(CRYPTO_THREADID *id)
+{
+	memset(id, 0, sizeof(*id));
+	id->val = (unsigned long)pthread_self();
+}
+LCRYPTO_ALIAS(CRYPTO_THREADID_current);
+
+int
+CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+LCRYPTO_ALIAS(CRYPTO_THREADID_cmp);
+
+void
+CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src)
+{
+	memcpy(dest, src, sizeof(*src));
+}
+LCRYPTO_ALIAS(CRYPTO_THREADID_cpy);
+
+unsigned long
+CRYPTO_THREADID_hash(const CRYPTO_THREADID *id)
+{
+	return id->val;
+}
+LCRYPTO_ALIAS(CRYPTO_THREADID_hash);
+
+#if	defined(__i386)   || defined(__i386__)   || defined(_M_IX86) || \
+	defined(__INTEL__) || \
+	defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
+
+uint64_t OPENSSL_ia32cap_P;
+
+uint64_t
+OPENSSL_cpu_caps(void)
+{
+	return OPENSSL_ia32cap_P;
+}
+LCRYPTO_ALIAS(OPENSSL_cpu_caps);
+
+#if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM)
+#define OPENSSL_CPUID_SETUP
+void
+OPENSSL_cpuid_setup(void)
+{
+	static int trigger = 0;
+	uint64_t OPENSSL_ia32_cpuid(void);
+
+	if (trigger)
+		return;
+	trigger = 1;
+	OPENSSL_ia32cap_P = OPENSSL_ia32_cpuid();
+}
+#endif
+
+#else
+uint64_t
+OPENSSL_cpu_caps(void)
+{
+	return 0;
+}
+LCRYPTO_ALIAS(OPENSSL_cpu_caps);
+#endif
+
+#if !defined(OPENSSL_CPUID_SETUP) && !defined(OPENSSL_CPUID_OBJ)
+void
+OPENSSL_cpuid_setup(void)
+{
+}
+#endif
+
+static void
+OPENSSL_showfatal(const char *fmta, ...)
+{
+	struct syslog_data sdata = SYSLOG_DATA_INIT;
+	va_list ap;
+
+	va_start(ap, fmta);
+	vsyslog_r(LOG_INFO|LOG_LOCAL2, &sdata, fmta, ap);
+	va_end(ap);
+}
+
+void
+OpenSSLDie(const char *file, int line, const char *assertion)
+{
+	OPENSSL_showfatal(
+	    "uid %u cmd %s %s(%d): OpenSSL internal error, assertion failed: %s\n",
+	    getuid(), getprogname(), file, line, assertion);
+	_exit(1);
+}
+LCRYPTO_ALIAS(OpenSSLDie);
+
+int
+CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len)
+{
+	size_t i;
+	const unsigned char *a = in_a;
+	const unsigned char *b = in_b;
+	unsigned char x = 0;
+
+	for (i = 0; i < len; i++)
+		x |= a[i] ^ b[i];
+
+	return x;
+}
diff --git a/crypto/cryptlib.h b/crypto/cryptlib.h
new file mode 100644
index 0000000..6c3731d
--- /dev/null
+++ b/crypto/cryptlib.h
@@ -0,0 +1,84 @@
+/* $OpenBSD: cryptlib.h,v 1.26 2021/11/24 01:12:43 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_CRYPTLIB_H
+#define HEADER_CRYPTLIB_H
+
+#include 
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#define X509_CERT_AREA		OPENSSLDIR
+#define X509_CERT_DIR		OPENSSLDIR "/certs"
+#define X509_CERT_FILE		OPENSSLDIR "/cert.pem"
+#define X509_PRIVATE_DIR	OPENSSLDIR "/private"
+#define X509_CERT_DIR_EVP        "SSL_CERT_DIR"
+#define X509_CERT_FILE_EVP       "SSL_CERT_FILE"
+
+#define CTLOG_FILE		OPENSSLDIR "/ct_log_list.cnf"
+#define CTLOG_FILE_EVP		"CTLOG_FILE"
+
+void OPENSSL_cpuid_setup(void);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/crypto/crypto_init.c b/crypto/crypto_init.c
new file mode 100644
index 0000000..a2c1c78
--- /dev/null
+++ b/crypto/crypto_init.c
@@ -0,0 +1,102 @@
+/*	$OpenBSD: crypto_init.c,v 1.11 2023/07/08 08:28:23 beck Exp $ */
+/*
+ * Copyright (c) 2018 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* OpenSSL style init */
+
+#include 
+#include 
+
+#include 
+#include 
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+
+#include "cryptlib.h"
+#include "x509_issuer_cache.h"
+
+int OpenSSL_config(const char *);
+int OpenSSL_no_config(void);
+
+static pthread_once_t crypto_init_once = PTHREAD_ONCE_INIT;
+static pthread_t crypto_init_thread;
+static int crypto_init_cleaned_up;
+
+static void
+OPENSSL_init_crypto_internal(void)
+{
+	crypto_init_thread = pthread_self();
+
+	OPENSSL_cpuid_setup();
+	ERR_load_crypto_strings();
+	OpenSSL_add_all_ciphers();
+	OpenSSL_add_all_digests();
+}
+
+int
+OPENSSL_init_crypto(uint64_t opts, const void *settings)
+{
+	if (crypto_init_cleaned_up) {
+		CRYPTOerror(ERR_R_INIT_FAIL);
+		return 0;
+	}
+
+	if (pthread_equal(pthread_self(), crypto_init_thread))
+		return 1; /* don't recurse */
+
+	if (pthread_once(&crypto_init_once, OPENSSL_init_crypto_internal) != 0)
+		return 0;
+
+	if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) &&
+	    (OpenSSL_no_config() == 0))
+		return 0;
+
+	if ((opts & OPENSSL_INIT_LOAD_CONFIG) &&
+	    (OpenSSL_config(NULL) == 0))
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(OPENSSL_init_crypto);
+
+void
+OPENSSL_cleanup(void)
+{
+	/* This currently calls init... */
+	ERR_free_strings();
+
+	CRYPTO_cleanup_all_ex_data();
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_cleanup();
+#endif
+	EVP_cleanup();
+
+	ASN1_STRING_TABLE_cleanup();
+	X509V3_EXT_cleanup();
+	X509_PURPOSE_cleanup();
+	X509_TRUST_cleanup();
+	X509_VERIFY_PARAM_table_cleanup();
+
+	x509_issuer_cache_free();
+
+	crypto_init_cleaned_up = 1;
+}
+LCRYPTO_ALIAS(OPENSSL_cleanup);
diff --git a/crypto/crypto_internal.h b/crypto/crypto_internal.h
new file mode 100644
index 0000000..e574265
--- /dev/null
+++ b/crypto/crypto_internal.h
@@ -0,0 +1,153 @@
+/*	$OpenBSD: crypto_internal.h,v 1.7 2023/08/15 08:39:27 jsing Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+
+#ifndef HEADER_CRYPTO_INTERNAL_H
+#define HEADER_CRYPTO_INTERNAL_H
+
+#define CTASSERT(x) \
+    extern char _ctassert[(x) ? 1 : -1] __attribute__((__unused__))
+
+/*
+ * crypto_load_be32toh() loads a 32 bit unsigned big endian value as a 32 bit
+ * unsigned host endian value, from the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_LOAD_BE32TOH
+static inline uint32_t
+crypto_load_be32toh(const uint8_t *src)
+{
+	uint32_t v;
+
+	memcpy(&v, src, sizeof(v));
+
+	return be32toh(v);
+}
+#endif
+
+/*
+ * crypto_store_htobe32() stores a 32 bit unsigned host endian value as a 32 bit
+ * unsigned big endian value, at the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_STORE_HTOBE32
+static inline void
+crypto_store_htobe32(uint8_t *dst, uint32_t v)
+{
+	v = htobe32(v);
+	memcpy(dst, &v, sizeof(v));
+}
+#endif
+
+/*
+ * crypto_load_be64toh() loads a 64 bit unsigned big endian value as a 64 bit
+ * unsigned host endian value, from the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_LOAD_BE64TOH
+static inline uint64_t
+crypto_load_be64toh(const uint8_t *src)
+{
+	uint64_t v;
+
+	memcpy(&v, src, sizeof(v));
+
+	return be64toh(v);
+}
+#endif
+
+/*
+ * crypto_store_htobe64() stores a 64 bit unsigned host endian value as a 64 bit
+ * unsigned big endian value, at the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_STORE_HTOBE64
+static inline void
+crypto_store_htobe64(uint8_t *dst, uint64_t v)
+{
+	v = htobe64(v);
+	memcpy(dst, &v, sizeof(v));
+}
+#endif
+
+/*
+ * crypto_load_le32toh() loads a 32 bit unsigned little endian value as a 32 bit
+ * unsigned host endian value, from the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_LOAD_BE32TOH
+static inline uint32_t
+crypto_load_le32toh(const uint8_t *src)
+{
+	uint32_t v;
+
+	memcpy(&v, src, sizeof(v));
+
+	return le32toh(v);
+}
+#endif
+
+/*
+ * crypto_store_htole32() stores a 32 bit unsigned host endian value as a 32 bit
+ * unsigned little endian value, at the specified address in memory. The memory
+ * address may have any alignment.
+ */
+#ifndef HAVE_CRYPTO_STORE_HTOBE32
+static inline void
+crypto_store_htole32(uint8_t *dst, uint32_t v)
+{
+	v = htole32(v);
+	memcpy(dst, &v, sizeof(v));
+}
+#endif
+
+#ifndef HAVE_CRYPTO_ROL_U32
+static inline uint32_t
+crypto_rol_u32(uint32_t v, size_t shift)
+{
+	return (v << shift) | (v >> (32 - shift));
+}
+#endif
+
+#ifndef HAVE_CRYPTO_ROR_U32
+static inline uint32_t
+crypto_ror_u32(uint32_t v, size_t shift)
+{
+	return (v << (32 - shift)) | (v >> shift);
+}
+#endif
+
+#ifndef HAVE_CRYPTO_ROL_U64
+static inline uint64_t
+crypto_rol_u64(uint64_t v, size_t shift)
+{
+	return (v << shift) | (v >> (64 - shift));
+}
+#endif
+
+#ifndef HAVE_CRYPTO_ROR_U64
+static inline uint64_t
+crypto_ror_u64(uint64_t v, size_t shift)
+{
+	return (v << (64 - shift)) | (v >> shift);
+}
+#endif
+
+#endif
diff --git a/crypto/crypto_lock.c b/crypto/crypto_lock.c
new file mode 100644
index 0000000..59c3933
--- /dev/null
+++ b/crypto/crypto_lock.c
@@ -0,0 +1,96 @@
+/* $OpenBSD: crypto_lock.c,v 1.6 2023/07/08 08:28:23 beck Exp $ */
+/*
+ * Copyright (c) 2018 Brent Cook 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#include "crypto_internal.h"
+
+static pthread_mutex_t locks[] = {
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+	PTHREAD_MUTEX_INITIALIZER,
+};
+
+CTASSERT((sizeof(locks) / sizeof(*locks)) == CRYPTO_NUM_LOCKS);
+
+void
+CRYPTO_lock(int mode, int type, const char *file, int line)
+{
+	if (type < 0 || type >= CRYPTO_NUM_LOCKS)
+		return;
+
+	if (mode & CRYPTO_LOCK)
+		(void) pthread_mutex_lock(&locks[type]);
+	else if (mode & CRYPTO_UNLOCK)
+		(void) pthread_mutex_unlock(&locks[type]);
+}
+LCRYPTO_ALIAS(CRYPTO_lock);
+
+int
+CRYPTO_add_lock(int *pointer, int amount, int type, const char *file,
+    int line)
+{
+	int ret;
+
+	CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE, type, file, line);
+	ret = *pointer + amount;
+	*pointer = ret;
+	CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE, type, file, line);
+
+	return (ret);
+}
+LCRYPTO_ALIAS(CRYPTO_add_lock);
diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c
new file mode 100644
index 0000000..101cd1e
--- /dev/null
+++ b/crypto/ct/ct_b64.c
@@ -0,0 +1,226 @@
+/*	$OpenBSD: ct_b64.c,v 1.7 2023/07/08 07:22:58 beck Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+#include "ct_local.h"
+
+/*
+ * Decodes the base64 string |in| into |out|.
+ * A new string will be malloc'd and assigned to |out|. This will be owned by
+ * the caller. Do not provide a pre-allocated string in |out|.
+ */
+static int
+ct_base64_decode(const char *in, unsigned char **out)
+{
+	size_t inlen = strlen(in);
+	int outlen, i;
+	unsigned char *outbuf = NULL;
+
+	if (inlen == 0) {
+		*out = NULL;
+		return 0;
+	}
+
+	outlen = (inlen / 4) * 3;
+	outbuf = malloc(outlen);
+	if (outbuf == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen);
+	if (outlen < 0) {
+		CTerror(CT_R_BASE64_DECODE_ERROR);
+		goto err;
+	}
+
+	/*
+	 * Subtract padding bytes from |outlen|.
+	 * Any more than 2 is malformed.
+	 */
+	i = 0;
+	while (in[--inlen] == '=') {
+		--outlen;
+		if (++i > 2)
+			goto err;
+	}
+
+	*out = outbuf;
+	return outlen;
+ err:
+	free(outbuf);
+	return -1;
+}
+
+SCT *
+SCT_new_from_base64(unsigned char version, const char *logid_base64,
+    ct_log_entry_type_t entry_type, uint64_t timestamp,
+    const char *extensions_base64, const char *signature_base64)
+{
+	unsigned char *dec = NULL;
+	int declen;
+	SCT *sct;
+	CBS cbs;
+
+	if ((sct = SCT_new()) == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	/*
+	 * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we
+	 * can only construct SCT versions that have been defined.
+	 */
+	if (!SCT_set_version(sct, version)) {
+		CTerror(CT_R_SCT_UNSUPPORTED_VERSION);
+		goto err;
+	}
+
+	declen = ct_base64_decode(logid_base64, &dec);
+	if (declen < 0) {
+		CTerror(X509_R_BASE64_DECODE_ERROR);
+		goto err;
+	}
+	if (!SCT_set0_log_id(sct, dec, declen))
+		goto err;
+	dec = NULL;
+
+	declen = ct_base64_decode(extensions_base64, &dec);
+	if (declen < 0) {
+		CTerror(X509_R_BASE64_DECODE_ERROR);
+		goto err;
+	}
+	SCT_set0_extensions(sct, dec, declen);
+	dec = NULL;
+
+	declen = ct_base64_decode(signature_base64, &dec);
+	if (declen < 0) {
+		CTerror(X509_R_BASE64_DECODE_ERROR);
+		goto err;
+	}
+
+	CBS_init(&cbs, dec, declen);
+	if (!o2i_SCT_signature(sct, &cbs))
+		goto err;
+	free(dec);
+	dec = NULL;
+
+	SCT_set_timestamp(sct, timestamp);
+
+	if (!SCT_set_log_entry_type(sct, entry_type))
+		goto err;
+
+	return sct;
+
+ err:
+	free(dec);
+	SCT_free(sct);
+	return NULL;
+}
+LCRYPTO_ALIAS(SCT_new_from_base64);
+
+/*
+ * Allocate, build and returns a new |ct_log| from input |pkey_base64|
+ * It returns 1 on success,
+ * 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)
+{
+	unsigned char *pkey_der = NULL;
+	int pkey_der_len;
+	const unsigned char *p;
+	EVP_PKEY *pkey = NULL;
+
+	if (ct_log == NULL) {
+	        CTerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+
+	pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der);
+	if (pkey_der_len < 0) {
+		CTerror(CT_R_LOG_CONF_INVALID_KEY);
+		return 0;
+	}
+
+	p = pkey_der;
+	pkey = d2i_PUBKEY(NULL, &p, pkey_der_len);
+	free(pkey_der);
+	if (pkey == NULL) {
+		CTerror(CT_R_LOG_CONF_INVALID_KEY);
+		return 0;
+	}
+
+	*ct_log = CTLOG_new(pkey, name);
+	if (*ct_log == NULL) {
+		EVP_PKEY_free(pkey);
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(CTLOG_new_from_base64);
diff --git a/crypto/ct/ct_err.c b/crypto/ct/ct_err.c
new file mode 100644
index 0000000..2597874
--- /dev/null
+++ b/crypto/ct/ct_err.c
@@ -0,0 +1,147 @@
+/*	$OpenBSD: ct_err.c,v 1.7 2022/07/12 14:42:48 kn Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+static 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}
+};
+
+static ERR_STRING_DATA CT_str_reasons[] = {
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_BASE64_DECODE_ERROR),
+	 "base64 decode error"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_INVALID_LOG_ID_LENGTH),
+	 "invalid log id length"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID), "log conf invalid"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_INVALID_KEY),
+	 "log conf invalid key"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_DESCRIPTION),
+	 "log conf missing description"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_CONF_MISSING_KEY),
+	 "log conf missing key"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_LOG_KEY_INVALID), "log key invalid"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_FUTURE_TIMESTAMP),
+	 "sct future timestamp"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID), "sct invalid"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_INVALID_SIGNATURE),
+	 "sct invalid signature"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LIST_INVALID), "sct list invalid"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_LOG_ID_MISMATCH),
+	 "sct log id mismatch"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_NOT_SET), "sct not set"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_SCT_UNSUPPORTED_VERSION),
+	 "sct unsupported version"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNRECOGNIZED_SIGNATURE_NID),
+	 "unrecognized signature nid"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_ENTRY_TYPE),
+	 "unsupported entry type"},
+	{ERR_PACK(ERR_LIB_CT, 0, CT_R_UNSUPPORTED_VERSION),
+	 "unsupported version"},
+	{0, NULL}
+};
+
+#endif
+
+int
+ERR_load_CT_strings(void)
+{
+	if (ERR_func_error_string(CT_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, CT_str_functs);
+		ERR_load_strings(0, CT_str_reasons);
+	}
+	return 1;
+}
diff --git a/crypto/ct/ct_local.h b/crypto/ct/ct_local.h
new file mode 100644
index 0000000..cd19ed0
--- /dev/null
+++ b/crypto/ct/ct_local.h
@@ -0,0 +1,260 @@
+/*	$OpenBSD: ct_local.h,v 1.8 2021/12/20 17:19:19 jsing Exp $ */
+/*
+ * Written by Rob Percival (robpercival@google.com) for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+
+/* Number of bytes in an SCT v1 LogID - see RFC 6962 section 3.2. */
+#define CT_V1_LOG_ID_LEN	32
+
+/* Maximum size of an SCT - see RFC 6962 section 3.3. */
+#define MAX_SCT_SIZE            65535
+#define MAX_SCT_LIST_SIZE       MAX_SCT_SIZE
+
+/*
+ * Macros to write integers in network-byte order.
+ */
+
+#define s2n(s,c)        ((c[0]=(unsigned char)(((s)>> 8)&0xff), \
+                          c[1]=(unsigned char)(((s)    )&0xff)),c+=2)
+
+#define l2n3(l,c)       ((c[0]=(unsigned char)(((l)>>16)&0xff), \
+                          c[1]=(unsigned char)(((l)>> 8)&0xff), \
+                          c[2]=(unsigned char)(((l)    )&0xff)),c+=3)
+
+#define l2n8(l,c)       (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>48)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>40)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>32)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>24)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>>16)&0xff), \
+                         *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
+                         *((c)++)=(unsigned char)(((l)    )&0xff))
+
+/* Signed Certificate Timestamp */
+struct sct_st {
+	sct_version_t version;
+	/* If version is not SCT_VERSION_V1, this contains the encoded SCT */
+	unsigned char *sct;
+	size_t sct_len;
+	/*
+	 * If version is SCT_VERSION_V1, fields below contain components of
+	 * the SCT
+	 */
+	unsigned char *log_id;
+	size_t log_id_len;
+	/*
+	 * Note, we cannot distinguish between an unset timestamp, and one
+	 * that is set to 0.  However since CT didn't exist in 1970, no real
+	 * SCT should ever be set as such.
+	 */
+	uint64_t timestamp;
+	unsigned char *ext;
+	size_t ext_len;
+	unsigned char hash_alg;
+	unsigned char sig_alg;
+	unsigned char *sig;
+	size_t sig_len;
+	/* Log entry type */
+	ct_log_entry_type_t entry_type;
+	/* Where this SCT was found, e.g. certificate, OCSP response, etc. */
+	sct_source_t source;
+	/* The result of the last attempt to validate this SCT. */
+	sct_validation_status_t validation_status;
+};
+
+/* Miscellaneous data that is useful when verifying an SCT  */
+struct sct_ctx_st {
+	/* Public key */
+	EVP_PKEY *pkey;
+	/* Hash of public key */
+	unsigned char *pkeyhash;
+	size_t pkeyhashlen;
+	/* For pre-certificate: issuer public key hash */
+	unsigned char *ihash;
+	size_t ihashlen;
+	/* certificate encoding */
+	unsigned char *certder;
+	size_t certderlen;
+	/* pre-certificate encoding */
+	unsigned char *preder;
+	size_t prederlen;
+	/*
+	 * milliseconds since epoch (to check that the SCT isn't from the
+	 * future)
+	 */
+	uint64_t epoch_time_in_ms;
+};
+
+/* Context when evaluating whether a Certificate Transparency policy is met */
+struct ct_policy_eval_ctx_st {
+	X509 *cert;
+	X509 *issuer;
+	CTLOG_STORE *log_store;
+	/*
+	 * milliseconds since epoch (to check that the SCT isn't from the
+	 * future)
+	 */
+	uint64_t epoch_time_in_ms;
+};
+
+/*
+ * Creates a new context for verifying an SCT.
+ */
+SCT_CTX *SCT_CTX_new(void);
+/*
+ * Deletes an SCT verification context.
+ */
+void SCT_CTX_free(SCT_CTX *sctx);
+
+/*
+ * Sets the certificate that the SCT was created for.
+ * If *cert does not have a poison extension, presigner must be NULL.
+ * If *cert does not have a poison extension, it may have a single SCT
+ * (NID_ct_precert_scts) extension.
+ * If either *cert or *presigner have an AKID (NID_authority_key_identifier)
+ * extension, both must have one.
+ * Returns 1 on success, 0 on failure.
+ */
+int SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner);
+
+/*
+ * Sets the issuer of the certificate that the SCT was created for.
+ * This is just a convenience method to save extracting the public key and
+ * calling SCT_CTX_set1_issuer_pubkey().
+ * Issuer must not be NULL.
+ * Returns 1 on success, 0 on failure.
+ */
+int SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer);
+
+/*
+ * Sets the public key of the issuer of the certificate that the SCT was created
+ * for.
+ * The public key must not be NULL.
+ * Returns 1 on success, 0 on failure.
+ */
+int SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
+
+/*
+ * Sets the public key of the CT log that the SCT is from.
+ * Returns 1 on success, 0 on failure.
+ */
+int SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey);
+
+/*
+ * Sets the time to evaluate the SCT against, in milliseconds since the Unix
+ * epoch. If the SCT's timestamp is after this time, it will be interpreted as
+ * having been issued in the future. RFC6962 states that "TLS clients MUST
+ * reject SCTs whose timestamp is in the future", so an SCT will not validate
+ * in this case.
+ */
+void SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms);
+
+/*
+ * Verifies an SCT with the given context.
+ * Returns 1 if the SCT verifies successfully; any other value indicates
+ * failure. See EVP_DigestVerifyFinal() for the meaning of those values.
+ */
+int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct);
+
+/*
+ * Does this SCT have the minimum fields populated to be usable?
+ * Returns 1 if so, 0 otherwise.
+ */
+int SCT_is_complete(const SCT *sct);
+
+/*
+ * Does this SCT have the signature-related fields populated?
+ * Returns 1 if so, 0 otherwise.
+ * This checks that the signature and hash algorithms are set to supported
+ * values and that the signature field is set.
+ */
+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
+ * TLS-format signature. It is the responsibility of the caller to free it.
+ * If |out| points to an allocated string, the signature will be written to it.
+ * The length of the signature in TLS format will be returned.
+ */
+int i2o_SCT_signature(const SCT *sct, unsigned char **out);
+
+/*
+ * Parses an SCT signature in TLS format and populates the |sct| with it.
+ * |in| should be a pointer to a string containing the TLS-format signature.
+ * |in| will be advanced to the end of the signature if parsing succeeds.
+ * |len| should be the length of the signature in |in|.
+ * Returns the number of bytes parsed, or a negative integer if an error occurs.
+ * If an error occurs, the SCT's signature NID may be updated whilst the
+ * signature field itself remains unset.
+ */
+int o2i_SCT_signature(SCT *sct, CBS *cbs);
+
+/*
+ * Handlers for Certificate Transparency X509v3/OCSP extensions
+ */
+extern const X509V3_EXT_METHOD v3_ct_scts[3];
diff --git a/crypto/ct/ct_log.c b/crypto/ct/ct_log.c
new file mode 100644
index 0000000..eb503a3
--- /dev/null
+++ b/crypto/ct/ct_log.c
@@ -0,0 +1,375 @@
+/*	$OpenBSD: ct_log.c,v 1.6 2023/07/08 07:22:58 beck Exp $ */
+/* Author: Adam Eijdenberg . */
+/* ====================================================================
+ * Copyright (c) 1998-2016 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ * 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 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "cryptlib.h"
+
+
+/*
+ * Information about a CT log server.
+ */
+struct ctlog_st {
+	char *name;
+	uint8_t log_id[CT_V1_HASHLEN];
+	EVP_PKEY *public_key;
+};
+
+/*
+ * A store for multiple CTLOG instances.
+ * It takes ownership of any CTLOG instances added to it.
+ */
+struct ctlog_store_st {
+	STACK_OF(CTLOG) *logs;
+};
+
+/* The context when loading a CT log list from a CONF file. */
+typedef struct ctlog_store_load_ctx_st {
+	CTLOG_STORE *log_store;
+	CONF *conf;
+	size_t invalid_log_entries;
+} CTLOG_STORE_LOAD_CTX;
+
+/*
+ * Creates an empty context for loading a CT log store.
+ * It should be populated before use.
+ */
+static CTLOG_STORE_LOAD_CTX *ctlog_store_load_ctx_new(void);
+
+/*
+ * Deletes a CT log store load context.
+ * Does not delete any of the fields.
+ */
+static void ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX *ctx);
+
+static CTLOG_STORE_LOAD_CTX *
+ctlog_store_load_ctx_new(void)
+{
+	CTLOG_STORE_LOAD_CTX *ctx = calloc(1, sizeof(*ctx));
+
+	if (ctx == NULL)
+		CTerror(ERR_R_MALLOC_FAILURE);
+
+	return ctx;
+}
+
+static void
+ctlog_store_load_ctx_free(CTLOG_STORE_LOAD_CTX  *ctx)
+{
+	free(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])
+{
+	int ret = 0;
+	unsigned char *pkey_der = NULL;
+	int pkey_der_len = i2d_PUBKEY(pkey, &pkey_der);
+
+	if (pkey_der_len <= 0) {
+		CTerror(CT_R_LOG_KEY_INVALID);
+		goto err;
+	}
+
+	SHA256(pkey_der, pkey_der_len, log_id);
+	ret = 1;
+ err:
+	free(pkey_der);
+	return ret;
+}
+
+CTLOG_STORE *
+CTLOG_STORE_new(void)
+{
+	CTLOG_STORE *ret = calloc(1, sizeof(*ret));
+
+	if (ret == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	ret->logs = sk_CTLOG_new_null();
+	if (ret->logs == NULL)
+		goto err;
+
+	return ret;
+ err:
+	free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(CTLOG_STORE_new);
+
+void
+CTLOG_STORE_free(CTLOG_STORE *store)
+{
+	if (store != NULL) {
+		sk_CTLOG_pop_free(store->logs, CTLOG_free);
+		free(store);
+	}
+}
+LCRYPTO_ALIAS(CTLOG_STORE_free);
+
+static int
+ctlog_new_from_conf(CTLOG **ct_log, const CONF *conf, const char *section)
+{
+	const char *description = NCONF_get_string(conf, section,
+	    "description");
+	char *pkey_base64;
+
+	if (description == NULL) {
+		CTerror(CT_R_LOG_CONF_MISSING_DESCRIPTION);
+		return 0;
+	}
+
+	pkey_base64 = NCONF_get_string(conf, section, "key");
+	if (pkey_base64 == NULL) {
+		CTerror(CT_R_LOG_CONF_MISSING_KEY);
+		return 0;
+	}
+
+	return CTLOG_new_from_base64(ct_log, pkey_base64, description);
+}
+
+int
+CTLOG_STORE_load_default_file(CTLOG_STORE *store)
+{
+	return CTLOG_STORE_load_file(store, CTLOG_FILE);
+}
+LCRYPTO_ALIAS(CTLOG_STORE_load_default_file);
+
+/*
+ * Called by CONF_parse_list, which stops if this returns <= 0,
+ * Otherwise, one bad log entry would stop loading of any of
+ * the following log entries.
+ * It may stop parsing and returns -1 on any internal (malloc) error.
+ */
+static int
+ctlog_store_load_log(const char *log_name, int log_name_len, void *arg)
+{
+	CTLOG_STORE_LOAD_CTX *load_ctx = arg;
+	CTLOG *ct_log = NULL;
+	/* log_name may not be null-terminated, so fix that before using it */
+	char *tmp;
+	int ret = 0;
+
+	/* log_name will be NULL for empty list entries */
+	if (log_name == NULL)
+		return 1;
+
+	tmp = strndup(log_name, log_name_len);
+	if (tmp == NULL)
+		goto mem_err;
+
+	ret = ctlog_new_from_conf(&ct_log, load_ctx->conf, tmp);
+	free(tmp);
+
+	if (ret < 0) {
+		/* Propagate any internal error */
+		return ret;
+	}
+	if (ret == 0) {
+		/* If we can't load this log, record that fact and skip it */
+		++load_ctx->invalid_log_entries;
+		return 1;
+	}
+
+	if (!sk_CTLOG_push(load_ctx->log_store->logs, ct_log)) {
+		goto mem_err;
+	}
+	return 1;
+
+ mem_err:
+	CTLOG_free(ct_log);
+	CTerror(ERR_R_MALLOC_FAILURE);
+	return -1;
+}
+
+int
+CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file)
+{
+	int ret = 0;
+	char *enabled_logs;
+	CTLOG_STORE_LOAD_CTX* load_ctx = ctlog_store_load_ctx_new();
+
+	if (load_ctx == NULL)
+		return 0;
+	load_ctx->log_store = store;
+	load_ctx->conf = NCONF_new(NULL);
+	if (load_ctx->conf == NULL)
+		goto end;
+
+	if (NCONF_load(load_ctx->conf, file, NULL) <= 0) {
+		CTerror(CT_R_LOG_CONF_INVALID);
+		goto end;
+	}
+
+	enabled_logs = NCONF_get_string(load_ctx->conf, NULL, "enabled_logs");
+	if (enabled_logs == NULL) {
+		CTerror(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) {
+		CTerror(CT_R_LOG_CONF_INVALID);
+		goto end;
+	}
+
+	ret = 1;
+ end:
+	NCONF_free(load_ctx->conf);
+	ctlog_store_load_ctx_free(load_ctx);
+	return ret;
+}
+LCRYPTO_ALIAS(CTLOG_STORE_load_file);
+
+/*
+ * Initialize a new CTLOG object.
+ * Takes ownership of the public key.
+ * Copies the name.
+ */
+CTLOG *
+CTLOG_new(EVP_PKEY *public_key, const char *name)
+{
+	CTLOG *ret = calloc(1, sizeof(*ret));
+
+	if (ret == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	ret->name = strdup(name);
+	if (ret->name == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (ct_v1_log_id_from_pkey(public_key, ret->log_id) != 1)
+		goto err;
+
+	ret->public_key = public_key;
+	return ret;
+ err:
+	CTLOG_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(CTLOG_new);
+
+/* Frees CT log and associated structures */
+void
+CTLOG_free(CTLOG *log)
+{
+	if (log != NULL) {
+		free(log->name);
+		EVP_PKEY_free(log->public_key);
+		free(log);
+	}
+}
+LCRYPTO_ALIAS(CTLOG_free);
+
+const char *
+CTLOG_get0_name(const CTLOG *log)
+{
+	return log->name;
+}
+LCRYPTO_ALIAS(CTLOG_get0_name);
+
+void
+CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, size_t *log_id_len)
+{
+	*log_id = log->log_id;
+	*log_id_len = CT_V1_HASHLEN;
+}
+LCRYPTO_ALIAS(CTLOG_get0_log_id);
+
+EVP_PKEY *
+CTLOG_get0_public_key(const CTLOG *log)
+{
+	return log->public_key;
+}
+LCRYPTO_ALIAS(CTLOG_get0_public_key);
+
+/*
+ * Given a log ID, finds the matching log.
+ * Returns NULL if no match found.
+ */
+const CTLOG *
+CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, const uint8_t *log_id,
+    size_t log_id_len)
+{
+	int i;
+
+	for (i = 0; i < sk_CTLOG_num(store->logs); ++i) {
+		const CTLOG *log = sk_CTLOG_value(store->logs, i);
+		if (memcmp(log->log_id, log_id, log_id_len) == 0)
+			return log;
+	}
+
+	return NULL;
+}
+LCRYPTO_ALIAS(CTLOG_STORE_get0_log_by_id);
diff --git a/crypto/ct/ct_oct.c b/crypto/ct/ct_oct.c
new file mode 100644
index 0000000..1f5e5c7
--- /dev/null
+++ b/crypto/ct/ct_oct.c
@@ -0,0 +1,464 @@
+/*	$OpenBSD: ct_oct.c,v 1.9 2023/07/08 07:22:58 beck Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT is disabled"
+#endif
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+#include "ct_local.h"
+
+int
+o2i_SCT_signature(SCT *sct, CBS *cbs)
+{
+	uint8_t hash_alg, sig_alg;
+	CBS signature;
+
+	if (sct->version != SCT_VERSION_V1) {
+		CTerror(CT_R_UNSUPPORTED_VERSION);
+		return 0;
+	}
+
+	/*
+	 * Parse a digitally-signed element - see RFC 6962 section 3.2 and
+	 * RFC 5246 sections 4.7 and 7.4.1.4.1.
+	 */
+	if (!CBS_get_u8(cbs, &hash_alg))
+		goto err_invalid;
+	if (!CBS_get_u8(cbs, &sig_alg))
+		goto err_invalid;
+	if (!CBS_get_u16_length_prefixed(cbs, &signature))
+		goto err_invalid;
+	if (CBS_len(cbs) != 0)
+		goto err_invalid;
+
+	/*
+	 * Reject empty signatures since they are invalid for all supported
+	 * algorithms (this really should be done by SCT_set1_signature()).
+	 */
+	if (CBS_len(&signature) == 0)
+		goto err_invalid;
+
+	sct->hash_alg = hash_alg;
+	sct->sig_alg = sig_alg;
+
+	if (SCT_get_signature_nid(sct) == NID_undef)
+		goto err_invalid;
+
+	if (!SCT_set1_signature(sct, CBS_data(&signature), CBS_len(&signature)))
+		return 0;
+
+	return 1;
+
+ err_invalid:
+	CTerror(CT_R_SCT_INVALID_SIGNATURE);
+	return 0;
+}
+
+static int
+o2i_SCT_internal(SCT **out_sct, CBS *cbs)
+{
+	SCT *sct = NULL;
+	uint8_t version;
+
+	*out_sct = NULL;
+
+	if ((sct = SCT_new()) == NULL)
+		goto err;
+
+	if (CBS_len(cbs) > MAX_SCT_SIZE)
+		goto err_invalid;
+	if (!CBS_peek_u8(cbs, &version))
+		goto err_invalid;
+
+	sct->version = version;
+
+	if (version == SCT_VERSION_V1) {
+		CBS extensions, log_id;
+		uint64_t timestamp;
+
+		/*
+		 * Parse a v1 SignedCertificateTimestamp - see RFC 6962
+		 * section 3.2.
+		 */
+		if (!CBS_get_u8(cbs, &version))
+			goto err_invalid;
+		if (!CBS_get_bytes(cbs, &log_id, CT_V1_LOG_ID_LEN))
+			goto err_invalid;
+		if (!CBS_get_u64(cbs, ×tamp))
+			goto err_invalid;
+		if (!CBS_get_u16_length_prefixed(cbs, &extensions))
+			goto err_invalid;
+
+		if (!CBS_stow(&log_id, &sct->log_id, &sct->log_id_len))
+			goto err;
+
+		sct->timestamp = timestamp;
+
+		if (!CBS_stow(&extensions, &sct->ext, &sct->ext_len))
+			goto err;
+
+		if (!o2i_SCT_signature(sct, cbs))
+			goto err;
+
+		if (CBS_len(cbs) != 0)
+			goto err_invalid;
+	} else {
+		/* If not V1 just cache encoding. */
+		if (!CBS_stow(cbs, &sct->sct, &sct->sct_len))
+			goto err;
+	}
+
+	*out_sct = sct;
+
+	return 1;
+
+ err_invalid:
+	CTerror(CT_R_SCT_INVALID);
+ err:
+	SCT_free(sct);
+
+	return 0;
+}
+
+SCT *
+o2i_SCT(SCT **psct, const unsigned char **in, size_t len)
+{
+	SCT *sct;
+	CBS cbs;
+
+	CBS_init(&cbs, *in, len);
+
+	if (psct != NULL) {
+		SCT_free(*psct);
+		*psct = NULL;
+	}
+
+	if (!o2i_SCT_internal(&sct, &cbs))
+		return NULL;
+
+	if (psct != NULL)
+		*psct = sct;
+
+	*in = CBS_data(&cbs);
+
+	return sct;
+}
+LCRYPTO_ALIAS(o2i_SCT);
+
+int
+i2o_SCT_signature(const SCT *sct, unsigned char **out)
+{
+	size_t len;
+	unsigned char *p = NULL, *pstart = NULL;
+
+	if (!SCT_signature_is_complete(sct)) {
+		CTerror(CT_R_SCT_INVALID_SIGNATURE);
+		goto err;
+	}
+
+	if (sct->version != SCT_VERSION_V1) {
+		CTerror(CT_R_UNSUPPORTED_VERSION);
+		goto err;
+	}
+
+	/*
+	 * (1 byte) Hash algorithm
+	 * (1 byte) Signature algorithm
+	 * (2 bytes + ?) Signature
+	 */
+	len = 4 + sct->sig_len;
+
+	if (out != NULL) {
+		if (*out != NULL) {
+			p = *out;
+			*out += len;
+		} else {
+			pstart = p = malloc(len);
+			if (p == NULL) {
+				CTerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			*out = p;
+		}
+
+		*p++ = sct->hash_alg;
+		*p++ = sct->sig_alg;
+		s2n(sct->sig_len, p);
+		memcpy(p, sct->sig, sct->sig_len);
+	}
+
+	return len;
+ err:
+	free(pstart);
+	return -1;
+}
+
+int
+i2o_SCT(const SCT *sct, unsigned char **out)
+{
+	size_t len;
+	unsigned char *p = NULL, *pstart = NULL;
+
+	if (!SCT_is_complete(sct)) {
+		CTerror(CT_R_SCT_NOT_SET);
+		goto err;
+	}
+	/*
+	 * Fixed-length header: struct { (1 byte) Version sct_version; (32 bytes)
+	 * log_id id; (8 bytes) uint64 timestamp; (2 bytes + ?) CtExtensions
+	 * extensions; (1 byte) Hash algorithm (1 byte) Signature algorithm (2
+	 * bytes + ?) Signature
+	 */
+	if (sct->version == SCT_VERSION_V1)
+		len = 43 + sct->ext_len + 4 + sct->sig_len;
+	else
+		len = sct->sct_len;
+
+	if (out == NULL)
+		return len;
+
+	if (*out != NULL) {
+		p = *out;
+		*out += len;
+	} else {
+		pstart = p = malloc(len);
+		if (p == NULL) {
+			CTerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		*out = p;
+	}
+
+	if (sct->version == SCT_VERSION_V1) {
+		*p++ = sct->version;
+		memcpy(p, sct->log_id, CT_V1_HASHLEN);
+		p += CT_V1_HASHLEN;
+		l2n8(sct->timestamp, p);
+		s2n(sct->ext_len, p);
+		if (sct->ext_len > 0) {
+			memcpy(p, sct->ext, sct->ext_len);
+			p += sct->ext_len;
+		}
+		if (i2o_SCT_signature(sct, &p) <= 0)
+			goto err;
+	} else {
+		memcpy(p, sct->sct, len);
+	}
+
+	return len;
+ err:
+	free(pstart);
+	return -1;
+}
+LCRYPTO_ALIAS(i2o_SCT);
+
+STACK_OF(SCT) *
+o2i_SCT_LIST(STACK_OF(SCT) **out_scts, const unsigned char **pp, size_t len)
+{
+	CBS cbs, cbs_scts, cbs_sct;
+	STACK_OF(SCT) *scts = NULL;
+
+	CBS_init(&cbs, *pp, len);
+
+	if (CBS_len(&cbs) > MAX_SCT_LIST_SIZE)
+		goto err_invalid;
+	if (!CBS_get_u16_length_prefixed(&cbs, &cbs_scts))
+		goto err_invalid;
+	if (CBS_len(&cbs) != 0)
+		goto err_invalid;
+
+	if (out_scts != NULL) {
+		SCT_LIST_free(*out_scts);
+		*out_scts = NULL;
+	}
+
+	if ((scts = sk_SCT_new_null()) == NULL)
+		return NULL;
+
+	while (CBS_len(&cbs_scts) > 0) {
+		SCT *sct;
+
+		if (!CBS_get_u16_length_prefixed(&cbs_scts, &cbs_sct))
+			goto err_invalid;
+
+		if (!o2i_SCT_internal(&sct, &cbs_sct))
+			goto err;
+		if (!sk_SCT_push(scts, sct)) {
+			SCT_free(sct);
+			goto err;
+		}
+	}
+
+	if (out_scts != NULL)
+		*out_scts = scts;
+
+	*pp = CBS_data(&cbs);
+
+	return scts;
+
+ err_invalid:
+	CTerror(CT_R_SCT_LIST_INVALID);
+ err:
+	SCT_LIST_free(scts);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(o2i_SCT_LIST);
+
+int
+i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp)
+{
+	int len, sct_len, i, is_pp_new = 0;
+	size_t len2;
+	unsigned char *p = NULL, *p2;
+
+	if (pp != NULL) {
+		if (*pp == NULL) {
+			if ((len = i2o_SCT_LIST(a, NULL)) == -1) {
+				CTerror(CT_R_SCT_LIST_INVALID);
+				return -1;
+			}
+			if ((*pp = malloc(len)) == NULL) {
+				CTerror(ERR_R_MALLOC_FAILURE);
+				return -1;
+			}
+			is_pp_new = 1;
+		}
+		p = *pp + 2;
+	}
+
+	len2 = 2;
+	for (i = 0; i < sk_SCT_num(a); i++) {
+		if (pp != NULL) {
+			p2 = p;
+			p += 2;
+			if ((sct_len = i2o_SCT(sk_SCT_value(a, i), &p)) == -1)
+				goto err;
+			s2n(sct_len, p2);
+		} else {
+			if ((sct_len = i2o_SCT(sk_SCT_value(a, i), NULL)) == -1)
+				goto err;
+		}
+		len2 += 2 + sct_len;
+	}
+
+	if (len2 > MAX_SCT_LIST_SIZE)
+		goto err;
+
+	if (pp != NULL) {
+		p = *pp;
+		s2n(len2 - 2, p);
+		if (!is_pp_new)
+			*pp += len2;
+	}
+	return len2;
+
+ err:
+	if (is_pp_new) {
+		free(*pp);
+		*pp = NULL;
+	}
+	return -1;
+}
+LCRYPTO_ALIAS(i2o_SCT_LIST);
+
+STACK_OF(SCT) *
+d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
+{
+	ASN1_OCTET_STRING *oct = NULL;
+	STACK_OF(SCT) *sk = NULL;
+	const unsigned char *p;
+
+	p = *pp;
+	if (d2i_ASN1_OCTET_STRING(&oct, &p, len) == NULL)
+		return NULL;
+
+	p = oct->data;
+	if ((sk = o2i_SCT_LIST(a, &p, oct->length)) != NULL)
+		*pp += len;
+
+	ASN1_OCTET_STRING_free(oct);
+	return sk;
+}
+LCRYPTO_ALIAS(d2i_SCT_LIST);
+
+int
+i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **out)
+{
+	ASN1_OCTET_STRING oct;
+	int len;
+
+	oct.data = NULL;
+	if ((oct.length = i2o_SCT_LIST(a, &oct.data)) == -1)
+		return -1;
+
+	len = i2d_ASN1_OCTET_STRING(&oct, out);
+	free(oct.data);
+	return len;
+}
+LCRYPTO_ALIAS(i2d_SCT_LIST);
diff --git a/crypto/ct/ct_policy.c b/crypto/ct/ct_policy.c
new file mode 100644
index 0000000..eb2b312
--- /dev/null
+++ b/crypto/ct/ct_policy.c
@@ -0,0 +1,163 @@
+/*	$OpenBSD: ct_policy.c,v 1.6 2023/07/08 07:22:58 beck Exp $ */
+/*
+ * Implementations of Certificate Transparency SCT policies.
+ * Written by Rob Percival (robpercival@google.com) for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT is disabled"
+#endif
+
+#include 
+#include 
+#include 
+
+#include "ct_local.h"
+
+/*
+ * Number of seconds in the future that an SCT timestamp can be, by default,
+ * without being considered invalid. This is added to time() when setting a
+ * default value for CT_POLICY_EVAL_CTX.epoch_time_in_ms.
+ * It can be overridden by calling CT_POLICY_EVAL_CTX_set_time().
+ */
+static const time_t SCT_CLOCK_DRIFT_TOLERANCE = 300;
+
+CT_POLICY_EVAL_CTX *
+CT_POLICY_EVAL_CTX_new(void)
+{
+	CT_POLICY_EVAL_CTX *ctx = calloc(1, sizeof(CT_POLICY_EVAL_CTX));
+
+	if (ctx == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		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;
+
+	return ctx;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_new);
+
+void
+CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+	X509_free(ctx->cert);
+	X509_free(ctx->issuer);
+	free(ctx);
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_free);
+
+int
+CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert)
+{
+	if (!X509_up_ref(cert))
+		return 0;
+	ctx->cert = cert;
+	return 1;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set1_cert);
+
+int
+CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer)
+{
+	if (!X509_up_ref(issuer))
+		return 0;
+	ctx->issuer = issuer;
+	return 1;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set1_issuer);
+
+void
+CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx,
+    CTLOG_STORE *log_store)
+{
+	ctx->log_store = log_store;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE);
+
+void
+CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms)
+{
+	ctx->epoch_time_in_ms = time_in_ms;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_set_time);
+
+X509 *
+CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx)
+{
+	return ctx->cert;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_cert);
+
+X509 *
+CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx)
+{
+	return ctx->issuer;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_issuer);
+
+const CTLOG_STORE *
+CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx)
+{
+	return ctx->log_store;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get0_log_store);
+
+uint64_t
+CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx)
+{
+	return ctx->epoch_time_in_ms;
+}
+LCRYPTO_ALIAS(CT_POLICY_EVAL_CTX_get_time);
diff --git a/crypto/ct/ct_prn.c b/crypto/ct/ct_prn.c
new file mode 100644
index 0000000..e6931ee
--- /dev/null
+++ b/crypto/ct/ct_prn.c
@@ -0,0 +1,211 @@
+/*	$OpenBSD: ct_prn.c,v 1.7 2023/07/08 07:22:58 beck Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT is disabled"
+#endif
+
+#include 
+#include 
+
+#include "ct_local.h"
+
+/*
+ * XXX public api in OpenSSL 1.1.0  but this is the only thing that uses it.
+ * so I am stuffing it here for the moment.
+ */
+static int
+BIO_hex_string(BIO *out, int indent, int width, unsigned char *data,
+    int datalen)
+{
+	int i, j = 0;
+
+	if (datalen < 1)
+		return 1;
+
+	for (i = 0; i < datalen - 1; i++) {
+		if (i && !j)
+			BIO_printf(out, "%*s", indent, "");
+
+		BIO_printf(out, "%02X:", data[i]);
+
+		j = (j + 1) % width;
+		if (!j)
+			BIO_printf(out, "\n");
+	}
+
+	if (i && !j)
+		BIO_printf(out, "%*s", indent, "");
+	BIO_printf(out, "%02X", data[datalen - 1]);
+	return 1;
+}
+
+static void
+SCT_signature_algorithms_print(const SCT *sct, BIO *out)
+{
+	int nid = SCT_get_signature_nid(sct);
+
+	if (nid == NID_undef)
+		BIO_printf(out, "%02X%02X", sct->hash_alg, sct->sig_alg);
+	else
+		BIO_printf(out, "%s", OBJ_nid2ln(nid));
+}
+
+static void
+timestamp_print(uint64_t timestamp, BIO *out)
+{
+	ASN1_GENERALIZEDTIME *gen = ASN1_GENERALIZEDTIME_new();
+	char genstr[20];
+
+	if (gen == NULL)
+		return;
+	ASN1_GENERALIZEDTIME_adj(gen, (time_t)0, (int)(timestamp / 86400000),
+	    (timestamp % 86400000) / 1000);
+	/*
+	 * Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15
+	 * characters long with a final Z. Update it with fractional seconds.
+	 */
+	snprintf(genstr, sizeof(genstr), "%.14sZ", ASN1_STRING_get0_data(gen));
+	if (ASN1_GENERALIZEDTIME_set_string(gen, genstr))
+		ASN1_GENERALIZEDTIME_print(out, gen);
+	ASN1_GENERALIZEDTIME_free(gen);
+}
+
+const char *
+SCT_validation_status_string(const SCT *sct)
+{
+	switch (SCT_get_validation_status(sct)) {
+	case SCT_VALIDATION_STATUS_NOT_SET:
+		return "not set";
+	case SCT_VALIDATION_STATUS_UNKNOWN_VERSION:
+		return "unknown version";
+	case SCT_VALIDATION_STATUS_UNKNOWN_LOG:
+		return "unknown log";
+	case SCT_VALIDATION_STATUS_UNVERIFIED:
+		return "unverified";
+	case SCT_VALIDATION_STATUS_INVALID:
+		return "invalid";
+	case SCT_VALIDATION_STATUS_VALID:
+		return "valid";
+	}
+	return "unknown status";
+}
+LCRYPTO_ALIAS(SCT_validation_status_string);
+
+void
+SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *log_store)
+{
+	const CTLOG *log = NULL;
+
+	if (log_store != NULL) {
+		log = CTLOG_STORE_get0_log_by_id(log_store, sct->log_id,
+		    sct->log_id_len);
+	}
+
+	BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, "");
+	BIO_printf(out, "\n%*sVersion   : ", indent + 4, "");
+
+	if (sct->version != SCT_VERSION_V1) {
+		BIO_printf(out, "unknown\n%*s", indent + 16, "");
+		BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len);
+		return;
+	}
+
+	BIO_printf(out, "v1 (0x0)");
+
+	if (log != NULL) {
+		BIO_printf(out, "\n%*sLog       : %s", indent + 4, "",
+		    CTLOG_get0_name(log));
+	}
+
+	BIO_printf(out, "\n%*sLog ID    : ", indent + 4, "");
+	BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len);
+
+	BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
+	timestamp_print(sct->timestamp, out);
+
+	BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
+	if (sct->ext_len == 0)
+		BIO_printf(out, "none");
+	else
+		BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len);
+
+	BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
+	SCT_signature_algorithms_print(sct, out);
+	BIO_printf(out, "\n%*s            ", indent + 4, "");
+	BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len);
+}
+LCRYPTO_ALIAS(SCT_print);
+
+void
+SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent,
+    const char *separator, const CTLOG_STORE *log_store)
+{
+	int sct_count = sk_SCT_num(sct_list);
+	int i;
+
+	for (i = 0; i < sct_count; ++i) {
+		SCT *sct = sk_SCT_value(sct_list, i);
+
+		SCT_print(sct, out, indent, log_store);
+		if (i < sk_SCT_num(sct_list) - 1)
+			BIO_printf(out, "%s", separator);
+	}
+}
+LCRYPTO_ALIAS(SCT_LIST_print);
diff --git a/crypto/ct/ct_sct.c b/crypto/ct/ct_sct.c
new file mode 100644
index 0000000..4b2716e
--- /dev/null
+++ b/crypto/ct/ct_sct.c
@@ -0,0 +1,507 @@
+/*	$OpenBSD: ct_sct.c,v 1.10 2023/07/22 17:02:49 tb Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com), Stephen Henson (steve@openssl.org)
+ * and Adam Eijdenberg (adam.eijdenberg@gmail.com) for the OpenSSL project 2016.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT disabled"
+#endif
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ct_local.h"
+
+SCT *
+SCT_new(void)
+{
+	SCT *sct = calloc(1, sizeof(*sct));
+
+	if (sct == NULL) {
+		CTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	sct->entry_type = CT_LOG_ENTRY_TYPE_NOT_SET;
+	sct->version = SCT_VERSION_NOT_SET;
+	return sct;
+}
+LCRYPTO_ALIAS(SCT_new);
+
+void
+SCT_free(SCT *sct)
+{
+	if (sct == NULL)
+		return;
+
+	free(sct->log_id);
+	free(sct->ext);
+	free(sct->sig);
+	free(sct->sct);
+	free(sct);
+}
+LCRYPTO_ALIAS(SCT_free);
+
+void
+SCT_LIST_free(STACK_OF(SCT) *scts)
+{
+	sk_SCT_pop_free(scts, SCT_free);
+}
+LCRYPTO_ALIAS(SCT_LIST_free);
+
+int
+SCT_set_version(SCT *sct, sct_version_t version)
+{
+	if (version != SCT_VERSION_V1) {
+		CTerror(CT_R_UNSUPPORTED_VERSION);
+		return 0;
+	}
+	sct->version = version;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set_version);
+
+int
+SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type)
+{
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+
+	switch (entry_type) {
+	case CT_LOG_ENTRY_TYPE_X509:
+	case CT_LOG_ENTRY_TYPE_PRECERT:
+		sct->entry_type = entry_type;
+		return 1;
+	case CT_LOG_ENTRY_TYPE_NOT_SET:
+		break;
+	}
+	CTerror(CT_R_UNSUPPORTED_ENTRY_TYPE);
+	return 0;
+}
+LCRYPTO_ALIAS(SCT_set_log_entry_type);
+
+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) {
+		CTerror(CT_R_INVALID_LOG_ID_LENGTH);
+		return 0;
+	}
+
+	free(sct->log_id);
+	sct->log_id = log_id;
+	sct->log_id_len = log_id_len;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set0_log_id);
+
+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) {
+		CTerror(CT_R_INVALID_LOG_ID_LENGTH);
+		return 0;
+	}
+
+	free(sct->log_id);
+	sct->log_id = NULL;
+	sct->log_id_len = 0;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+
+	if (log_id != NULL && log_id_len > 0) {
+		sct->log_id = malloc(log_id_len);
+		if (sct->log_id == NULL) {
+			CTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(sct->log_id, log_id, log_id_len);
+		sct->log_id_len = log_id_len;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set1_log_id);
+
+
+void
+SCT_set_timestamp(SCT *sct, uint64_t timestamp)
+{
+	sct->timestamp = timestamp;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+}
+LCRYPTO_ALIAS(SCT_set_timestamp);
+
+int
+SCT_set_signature_nid(SCT *sct, int nid)
+{
+	switch (nid) {
+	case NID_sha256WithRSAEncryption:
+		sct->hash_alg = 4; /* XXX */
+		sct->sig_alg = 1; /* XXX */
+		sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+		return 1;
+	case NID_ecdsa_with_SHA256:
+		sct->hash_alg = 4; /* XXX */
+		sct->sig_alg = 3; /* XXX */
+		sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+		return 1;
+	default:
+		CTerror(CT_R_UNRECOGNIZED_SIGNATURE_NID);
+		return 0;
+	}
+}
+LCRYPTO_ALIAS(SCT_set_signature_nid);
+
+void
+SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len)
+{
+	free(sct->ext);
+	sct->ext = ext;
+	sct->ext_len = ext_len;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+}
+LCRYPTO_ALIAS(SCT_set0_extensions);
+
+int
+SCT_set1_extensions(SCT *sct, const unsigned char *ext, size_t ext_len)
+{
+	free(sct->ext);
+	sct->ext = NULL;
+	sct->ext_len = 0;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+
+	if (ext != NULL && ext_len > 0) {
+		sct->ext = malloc(ext_len);
+		if (sct->ext == NULL) {
+			CTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(sct->ext, ext, ext_len);
+		sct->ext_len = ext_len;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set1_extensions);
+
+void
+SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len)
+{
+	free(sct->sig);
+	sct->sig = sig;
+	sct->sig_len = sig_len;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+}
+LCRYPTO_ALIAS(SCT_set0_signature);
+
+int
+SCT_set1_signature(SCT *sct, const unsigned char *sig, size_t sig_len)
+{
+	free(sct->sig);
+	sct->sig = NULL;
+	sct->sig_len = 0;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+
+	if (sig != NULL && sig_len > 0) {
+		sct->sig = malloc(sig_len);
+		if (sct->sig == NULL) {
+			CTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(sct->sig, sig, sig_len);
+		sct->sig_len = sig_len;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set1_signature);
+
+sct_version_t
+SCT_get_version(const SCT *sct)
+{
+	return sct->version;
+}
+LCRYPTO_ALIAS(SCT_get_version);
+
+ct_log_entry_type_t
+SCT_get_log_entry_type(const SCT *sct)
+{
+	return sct->entry_type;
+}
+LCRYPTO_ALIAS(SCT_get_log_entry_type);
+
+size_t
+SCT_get0_log_id(const SCT *sct, unsigned char **log_id)
+{
+	*log_id = sct->log_id;
+	return sct->log_id_len;
+}
+LCRYPTO_ALIAS(SCT_get0_log_id);
+
+uint64_t
+SCT_get_timestamp(const SCT *sct)
+{
+	return sct->timestamp;
+}
+LCRYPTO_ALIAS(SCT_get_timestamp);
+
+int
+SCT_get_signature_nid(const SCT *sct)
+{
+	if (sct->version == SCT_VERSION_V1) {
+		/* XXX sigalg numbers */
+		if (sct->hash_alg == 4) {
+			switch (sct->sig_alg) {
+			case 3:
+				return NID_ecdsa_with_SHA256;
+			case 1:
+				return NID_sha256WithRSAEncryption;
+			default:
+				return NID_undef;
+			}
+		}
+	}
+	return NID_undef;
+}
+LCRYPTO_ALIAS(SCT_get_signature_nid);
+
+size_t
+SCT_get0_extensions(const SCT *sct, unsigned char **ext)
+{
+	*ext = sct->ext;
+	return sct->ext_len;
+}
+LCRYPTO_ALIAS(SCT_get0_extensions);
+
+size_t
+SCT_get0_signature(const SCT *sct, unsigned char **sig)
+{
+	*sig = sct->sig;
+	return sct->sig_len;
+}
+LCRYPTO_ALIAS(SCT_get0_signature);
+
+int
+SCT_is_complete(const SCT *sct)
+{
+	switch (sct->version) {
+	case SCT_VERSION_NOT_SET:
+		return 0;
+	case SCT_VERSION_V1:
+		return sct->log_id != NULL && SCT_signature_is_complete(sct);
+	default:
+		return sct->sct != NULL; /* Just need cached encoding */
+	}
+}
+
+int
+SCT_signature_is_complete(const SCT *sct)
+{
+	return SCT_get_signature_nid(sct) != NID_undef &&
+	    sct->sig != NULL && sct->sig_len > 0;
+}
+
+sct_source_t
+SCT_get_source(const SCT *sct)
+{
+	return sct->source;
+}
+LCRYPTO_ALIAS(SCT_get_source);
+
+int
+SCT_set_source(SCT *sct, sct_source_t source)
+{
+	sct->source = source;
+	sct->validation_status = SCT_VALIDATION_STATUS_NOT_SET;
+	switch (source) {
+	case SCT_SOURCE_TLS_EXTENSION:
+	case SCT_SOURCE_OCSP_STAPLED_RESPONSE:
+		return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_X509);
+	case SCT_SOURCE_X509V3_EXTENSION:
+		return SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT);
+	case SCT_SOURCE_UNKNOWN:
+		break;
+	}
+	/* if we aren't sure, leave the log entry type alone */
+	return 1;
+}
+LCRYPTO_ALIAS(SCT_set_source);
+
+sct_validation_status_t
+SCT_get_validation_status(const SCT *sct)
+{
+	return sct->validation_status;
+}
+LCRYPTO_ALIAS(SCT_get_validation_status);
+
+int
+SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx)
+{
+	int is_sct_valid = -1;
+	SCT_CTX *sctx = NULL;
+	X509_PUBKEY *pub = NULL, *log_pkey = NULL;
+	const CTLOG *log;
+
+	/*
+	 * With an unrecognized SCT version we don't know what such an SCT means,
+	 * let alone validate one.  So we return validation failure (0).
+	 */
+	if (sct->version != SCT_VERSION_V1) {
+		sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_VERSION;
+		return 0;
+	}
+
+	log = CTLOG_STORE_get0_log_by_id(ctx->log_store, sct->log_id,
+	    sct->log_id_len);
+
+	/* Similarly, an SCT from an unknown log also cannot be validated. */
+	if (log == NULL) {
+		sct->validation_status = SCT_VALIDATION_STATUS_UNKNOWN_LOG;
+		return 0;
+	}
+
+	sctx = SCT_CTX_new();
+	if (sctx == NULL)
+		goto err;
+
+	if (X509_PUBKEY_set(&log_pkey, CTLOG_get0_public_key(log)) != 1)
+		goto err;
+	if (SCT_CTX_set1_pubkey(sctx, log_pkey) != 1)
+		goto err;
+
+	if (SCT_get_log_entry_type(sct) == CT_LOG_ENTRY_TYPE_PRECERT) {
+		EVP_PKEY *issuer_pkey;
+
+		if (ctx->issuer == NULL) {
+			sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
+			goto end;
+		}
+
+		if ((issuer_pkey = X509_get0_pubkey(ctx->issuer)) == NULL)
+			goto err;
+
+		if (X509_PUBKEY_set(&pub, issuer_pkey) != 1)
+			goto err;
+		if (SCT_CTX_set1_issuer_pubkey(sctx, pub) != 1)
+			goto err;
+	}
+
+	SCT_CTX_set_time(sctx, ctx->epoch_time_in_ms);
+
+	/*
+	 * 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
+	 * associated with the shared (by all SCTs) policy eval ctx.
+	 *
+	 * XXX: Failure here is global (SCT independent) and represents either an
+	 * issue with the certificate (e.g. duplicate extensions) or an out of
+	 * memory condition.  When the certificate is incompatible with CT, we just
+	 * mark the SCTs invalid, rather than report a failure to determine the
+	 * validation status.  That way, callbacks that want to do "soft" SCT
+	 * processing will not abort handshakes with false positive internal
+	 * errors.  Since the function does not distinguish between certificate
+	 * issues (peer's fault) and internal problems (out fault) the safe thing
+	 * to do is to report a validation failure and let the callback or
+	 * application decide what to do.
+	 */
+	if (SCT_CTX_set1_cert(sctx, ctx->cert, NULL) != 1)
+		sct->validation_status = SCT_VALIDATION_STATUS_UNVERIFIED;
+	else
+		sct->validation_status = SCT_CTX_verify(sctx, sct) == 1 ?
+		    SCT_VALIDATION_STATUS_VALID : SCT_VALIDATION_STATUS_INVALID;
+
+ end:
+	is_sct_valid = sct->validation_status == SCT_VALIDATION_STATUS_VALID;
+ err:
+	X509_PUBKEY_free(pub);
+	X509_PUBKEY_free(log_pkey);
+	SCT_CTX_free(sctx);
+
+	return is_sct_valid;
+}
+LCRYPTO_ALIAS(SCT_validate);
+
+int
+SCT_LIST_validate(const STACK_OF(SCT) *scts, CT_POLICY_EVAL_CTX *ctx)
+{
+	int are_scts_valid = 1;
+	int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
+	int i;
+
+	for (i = 0; i < sct_count; ++i) {
+		int is_sct_valid = -1;
+		SCT *sct = sk_SCT_value(scts, i);
+
+		if (sct == NULL)
+			continue;
+
+		is_sct_valid = SCT_validate(sct, ctx);
+		if (is_sct_valid < 0)
+			return is_sct_valid;
+		are_scts_valid &= is_sct_valid;
+	}
+
+	return are_scts_valid;
+}
+LCRYPTO_ALIAS(SCT_LIST_validate);
diff --git a/crypto/ct/ct_sct_ctx.c b/crypto/ct/ct_sct_ctx.c
new file mode 100644
index 0000000..b2b6d4e
--- /dev/null
+++ b/crypto/ct/ct_sct_ctx.c
@@ -0,0 +1,323 @@
+/*	$OpenBSD: ct_sct_ctx.c,v 1.6 2022/06/30 11:14:47 tb Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT is disabled"
+#endif
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "ct_local.h"
+
+SCT_CTX *
+SCT_CTX_new(void)
+{
+	SCT_CTX *sctx = calloc(1, sizeof(*sctx));
+
+	if (sctx == NULL)
+		CTerror(ERR_R_MALLOC_FAILURE);
+
+	return sctx;
+}
+
+void
+SCT_CTX_free(SCT_CTX *sctx)
+{
+	if (sctx == NULL)
+		return;
+	EVP_PKEY_free(sctx->pkey);
+	free(sctx->pkeyhash);
+	free(sctx->ihash);
+	free(sctx->certder);
+	free(sctx->preder);
+	free(sctx);
+}
+
+/*
+ * Finds the index of the first extension with the given NID in cert.
+ * If there is more than one extension with that NID, *is_duplicated is set to
+ * 1, otherwise 0 (unless it is NULL).
+ */
+static int
+ct_x509_get_ext(X509 *cert, int nid, int *is_duplicated)
+{
+	int ret = X509_get_ext_by_NID(cert, nid, -1);
+
+	if (is_duplicated != NULL)
+		*is_duplicated = ret >= 0 &&
+		    X509_get_ext_by_NID(cert, nid, ret) >= 0;
+
+	return ret;
+}
+
+/*
+ * Modifies a certificate by deleting extensions and copying the issuer and
+ * AKID from the presigner certificate, if necessary.
+ * Returns 1 on success, 0 otherwise.
+ */
+static int
+ct_x509_cert_fixup(X509 *cert, X509 *presigner)
+{
+	int preidx, certidx;
+	int pre_akid_ext_is_dup, cert_akid_ext_is_dup;
+
+	if (presigner == NULL)
+		return 1;
+
+	preidx = ct_x509_get_ext(presigner, NID_authority_key_identifier,
+	    &pre_akid_ext_is_dup);
+	certidx = ct_x509_get_ext(cert, NID_authority_key_identifier,
+	    &cert_akid_ext_is_dup);
+
+	/* An error occurred whilst searching for the extension */
+	if (preidx < -1 || certidx < -1)
+		return 0;
+	/* Invalid certificate if they contain duplicate extensions */
+	if (pre_akid_ext_is_dup || cert_akid_ext_is_dup)
+		return 0;
+	/* AKID must be present in both certificate or absent in both */
+	if (preidx >= 0 && certidx == -1)
+		return 0;
+	if (preidx == -1 && certidx >= 0)
+		return 0;
+	/* Copy issuer name */
+	if (!X509_set_issuer_name(cert, X509_get_issuer_name(presigner)))
+		return 0;
+	if (preidx != -1) {
+		/* Retrieve and copy AKID encoding */
+		X509_EXTENSION *preext = X509_get_ext(presigner, preidx);
+		X509_EXTENSION *certext = X509_get_ext(cert, certidx);
+		ASN1_OCTET_STRING *preextdata;
+
+		/* Should never happen */
+		if (preext == NULL || certext == NULL)
+			return 0;
+		preextdata = X509_EXTENSION_get_data(preext);
+		if (preextdata == NULL ||
+		    !X509_EXTENSION_set_data(certext, preextdata))
+			return 0;
+	}
+	return 1;
+}
+
+int
+SCT_CTX_set1_cert(SCT_CTX *sctx, X509 *cert, X509 *presigner)
+{
+	unsigned char *certder = NULL, *preder = NULL;
+	X509 *pretmp = NULL;
+	int certderlen = 0, prederlen = 0;
+	int idx = -1;
+	int poison_ext_is_dup, sct_ext_is_dup;
+	int poison_idx = ct_x509_get_ext(cert, NID_ct_precert_poison, &poison_ext_is_dup);
+
+	/* Duplicate poison extensions are present - error */
+	if (poison_ext_is_dup)
+		goto err;
+
+	/* If *cert doesn't have a poison extension, it isn't a precert */
+	if (poison_idx == -1) {
+		/* cert isn't a precert, so we shouldn't have a presigner */
+		if (presigner != NULL)
+			goto err;
+
+		certderlen = i2d_X509(cert, &certder);
+		if (certderlen < 0)
+			goto err;
+	}
+
+	/* See if cert has a precert SCTs extension */
+	idx = ct_x509_get_ext(cert, NID_ct_precert_scts, &sct_ext_is_dup);
+	/* Duplicate SCT extensions are present - error */
+	if (sct_ext_is_dup)
+		goto err;
+
+	if (idx >= 0 && poison_idx >= 0) {
+		/*
+		 * cert can't both contain SCTs (i.e. have an SCT extension) and be a
+		 * precert (i.e. have a poison extension).
+		 */
+		goto err;
+	}
+
+	if (idx == -1) {
+		idx = poison_idx;
+	}
+
+	/*
+	 * If either a poison or SCT extension is present, remove it before encoding
+	 * cert. This, along with ct_x509_cert_fixup(), gets a TBSCertificate (see
+	 * RFC5280) from cert, which is what the CT log signed when it produced the
+	 * 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);
+
+		if (!ct_x509_cert_fixup(pretmp, presigner))
+			goto err;
+
+		prederlen = i2d_re_X509_tbs(pretmp, &preder);
+		if (prederlen <= 0)
+			goto err;
+	}
+
+	X509_free(pretmp);
+
+	free(sctx->certder);
+	sctx->certder = certder;
+	sctx->certderlen = certderlen;
+
+	free(sctx->preder);
+	sctx->preder = preder;
+	sctx->prederlen = prederlen;
+
+	return 1;
+ err:
+	free(certder);
+	free(preder);
+	X509_free(pretmp);
+	return 0;
+}
+
+static int
+ct_public_key_hash(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;
+
+	/* Reuse buffer if possible */
+	if (*hash != NULL && *hash_len >= SHA256_DIGEST_LENGTH) {
+		md = *hash;
+	} else {
+		md = malloc(SHA256_DIGEST_LENGTH);
+		if (md == NULL)
+			goto err;
+	}
+
+	/* Calculate key hash */
+	der_len = i2d_X509_PUBKEY(pkey, &der);
+	if (der_len <= 0)
+		goto err;
+
+	if (!EVP_Digest(der, der_len, md, &md_len, EVP_sha256(), NULL))
+		goto err;
+
+	if (md != *hash) {
+		free(*hash);
+		*hash = md;
+		*hash_len = SHA256_DIGEST_LENGTH;
+	}
+
+	md = NULL;
+	ret = 1;
+ err:
+	free(md);
+	free(der);
+	return ret;
+}
+
+int
+SCT_CTX_set1_issuer(SCT_CTX *sctx, const X509 *issuer)
+{
+	return SCT_CTX_set1_issuer_pubkey(sctx, X509_get_X509_PUBKEY(issuer));
+}
+
+int
+SCT_CTX_set1_issuer_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
+{
+	return ct_public_key_hash(pubkey, &sctx->ihash, &sctx->ihashlen);
+}
+
+int
+SCT_CTX_set1_pubkey(SCT_CTX *sctx, X509_PUBKEY *pubkey)
+{
+	EVP_PKEY *pkey = X509_PUBKEY_get(pubkey);
+
+	if (pkey == NULL)
+		return 0;
+
+	if (!ct_public_key_hash(pubkey, &sctx->pkeyhash, &sctx->pkeyhashlen)) {
+		EVP_PKEY_free(pkey);
+		return 0;
+	}
+
+	EVP_PKEY_free(sctx->pkey);
+	sctx->pkey = pkey;
+	return 1;
+}
+
+void
+SCT_CTX_set_time(SCT_CTX *sctx, uint64_t time_in_ms)
+{
+	sctx->epoch_time_in_ms = time_in_ms;
+}
diff --git a/crypto/ct/ct_vfy.c b/crypto/ct/ct_vfy.c
new file mode 100644
index 0000000..4241172
--- /dev/null
+++ b/crypto/ct/ct_vfy.c
@@ -0,0 +1,195 @@
+/*	$OpenBSD: ct_vfy.c,v 1.6 2022/01/06 14:34:40 jsing Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ct_local.h"
+
+typedef enum sct_signature_type_t {
+	SIGNATURE_TYPE_NOT_SET = -1,
+	SIGNATURE_TYPE_CERT_TIMESTAMP,
+	SIGNATURE_TYPE_TREE_HASH
+} SCT_SIGNATURE_TYPE;
+
+/*
+ * Update encoding for SCT signature verification/generation to supplied
+ * EVP_MD_CTX.
+ */
+static int
+sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct)
+{
+	CBB cbb, entry, extensions;
+	uint8_t *data = NULL;
+	size_t data_len;
+	int ret = 0;
+
+	memset(&cbb, 0, sizeof(cbb));
+
+	if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET)
+		goto err;
+	if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)
+		goto err;
+
+	if (!CBB_init(&cbb, 0))
+		goto err;
+
+	/*
+	 * Build the digitally-signed struct per RFC 6962 section 3.2.
+	 */
+	if (!CBB_add_u8(&cbb, sct->version))
+		goto err;
+	if (!CBB_add_u8(&cbb, SIGNATURE_TYPE_CERT_TIMESTAMP))
+		goto err;
+	if (!CBB_add_u64(&cbb, sct->timestamp))
+		goto err;
+	if (!CBB_add_u16(&cbb, sct->entry_type))
+		goto err;
+
+	if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) {
+		if (!CBB_add_bytes(&cbb, sctx->ihash, sctx->ihashlen))
+			goto err;
+	}
+
+	if (!CBB_add_u24_length_prefixed(&cbb, &entry))
+		goto err;
+	if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT) {
+		if (sctx->preder == NULL)
+			goto err;
+		if (!CBB_add_bytes(&entry, sctx->preder, sctx->prederlen))
+			goto err;
+	} else {
+		if (sctx->certder == NULL)
+			goto err;
+		if (!CBB_add_bytes(&entry, sctx->certder, sctx->certderlen))
+			goto err;
+	}
+
+	if (!CBB_add_u16_length_prefixed(&cbb, &extensions))
+		goto err;
+	if (sct->ext_len > 0) {
+		if (!CBB_add_bytes(&extensions, sct->ext, sct->ext_len))
+			goto err;
+	}
+
+	if (!CBB_finish(&cbb, &data, &data_len))
+		goto err;
+
+	if (!EVP_DigestUpdate(ctx, data, data_len))
+		goto err;
+
+	ret = 1;
+
+ err:
+	CBB_cleanup(&cbb);
+	free(data);
+
+	return ret;
+}
+
+int
+SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct)
+{
+	EVP_MD_CTX *ctx = NULL;
+	int ret = 0;
+
+	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)) {
+		CTerror(CT_R_SCT_NOT_SET);
+		return 0;
+	}
+	if (sct->version != SCT_VERSION_V1) {
+		CTerror(CT_R_SCT_UNSUPPORTED_VERSION);
+		return 0;
+	}
+	if (sct->log_id_len != sctx->pkeyhashlen ||
+	    memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) {
+		CTerror(CT_R_SCT_LOG_ID_MISMATCH);
+		return 0;
+	}
+	if (sct->timestamp > sctx->epoch_time_in_ms) {
+		CTerror(CT_R_SCT_FUTURE_TIMESTAMP);
+		return 0;
+	}
+
+	if ((ctx = EVP_MD_CTX_new()) == NULL)
+		goto end;
+
+	if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey))
+		goto end;
+
+	if (!sct_ctx_update(ctx, sctx, sct))
+		goto end;
+
+	/* Verify signature */
+	/* If ret < 0 some other error: fall through without setting error */
+	if ((ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len)) == 0)
+		CTerror(CT_R_SCT_INVALID_SIGNATURE);
+
+ end:
+	EVP_MD_CTX_free(ctx);
+
+	return ret;
+}
diff --git a/crypto/ct/ct_x509v3.c b/crypto/ct/ct_x509v3.c
new file mode 100644
index 0000000..59f2975
--- /dev/null
+++ b/crypto/ct/ct_x509v3.c
@@ -0,0 +1,186 @@
+/*	$OpenBSD: ct_x509v3.c,v 1.6 2021/12/25 15:42:32 tb Exp $ */
+/*
+ * Written by Rob Stradling (rob@comodo.com) and Stephen Henson
+ * (steve@openssl.org) for the OpenSSL project 2014.
+ */
+/* ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifdef OPENSSL_NO_CT
+# error "CT is disabled"
+#endif
+
+#include 
+
+#include "ct_local.h"
+
+static char *
+i2s_poison(const X509V3_EXT_METHOD *method, void *val)
+{
+	return strdup("NULL");
+}
+
+static void *
+s2i_poison(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str)
+{
+	return ASN1_NULL_new();
+}
+
+static int
+i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list, BIO *out,
+    int indent)
+{
+	SCT_LIST_print(sct_list, out, indent, "\n", NULL);
+	return 1;
+}
+
+static int
+set_sct_list_source(STACK_OF(SCT) *s, sct_source_t source)
+{
+	if (s != NULL) {
+		int i;
+
+		for (i = 0; i < sk_SCT_num(s); i++) {
+			int res = SCT_set_source(sk_SCT_value(s, i), source);
+
+			if (res != 1) {
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
+
+static STACK_OF(SCT) *
+x509_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
+{
+	STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len);
+
+	if (set_sct_list_source(s, SCT_SOURCE_X509V3_EXTENSION) != 1) {
+		SCT_LIST_free(s);
+		*a = NULL;
+		return NULL;
+	}
+	return s;
+}
+
+static STACK_OF(SCT) *
+ocsp_ext_d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, long len)
+{
+	STACK_OF(SCT) *s = d2i_SCT_LIST(a, pp, len);
+
+	if (set_sct_list_source(s, SCT_SOURCE_OCSP_STAPLED_RESPONSE) != 1) {
+		SCT_LIST_free(s);
+		*a = NULL;
+		return NULL;
+	}
+	return s;
+}
+
+/* Handlers for X509v3/OCSP Certificate Transparency extensions */
+const X509V3_EXT_METHOD v3_ct_scts[3] = {
+	/* X509v3 extension in certificates that contains SCTs */
+	[0] = {
+		.ext_nid = NID_ct_precert_scts,
+		.ext_flags = 0,
+		.it = NULL,
+		.ext_new = NULL,
+		.ext_free = (X509V3_EXT_FREE)SCT_LIST_free,
+		.d2i = (X509V3_EXT_D2I)x509_ext_d2i_SCT_LIST,
+		.i2d = (X509V3_EXT_I2D)i2d_SCT_LIST,
+		.i2s = NULL,
+		.s2i = NULL,
+		.i2v = NULL,
+		.v2i = NULL,
+		.i2r = (X509V3_EXT_I2R)i2r_SCT_LIST,
+		.r2i = NULL,
+		.usr_data = NULL,
+	},
+
+	/* X509v3 extension to mark a certificate as a pre-certificate */
+	[1] = {
+		.ext_nid = NID_ct_precert_poison,
+		.ext_flags = 0,
+		.it = &ASN1_NULL_it,
+		.ext_new = NULL,
+		.ext_free = NULL,
+		.d2i = NULL,
+		.i2d = NULL,
+		.i2s = i2s_poison,
+		.s2i = s2i_poison,
+		.i2v = NULL,
+		.v2i = NULL,
+		.i2r = NULL,
+		.r2i = NULL,
+		.usr_data = NULL,
+	},
+
+	/* OCSP extension that contains SCTs */
+	[2] = {
+		.ext_nid = NID_ct_cert_scts,
+		.ext_flags = 0,
+		.it = NULL,
+		.ext_new = NULL,
+		.ext_free = (X509V3_EXT_FREE)SCT_LIST_free,
+		.d2i = (X509V3_EXT_D2I)ocsp_ext_d2i_SCT_LIST,
+		.i2d = (X509V3_EXT_I2D)i2d_SCT_LIST,
+		.i2s = NULL,
+		.s2i = NULL,
+		.i2v = NULL,
+		.v2i = NULL,
+		.i2r = (X509V3_EXT_I2R)i2r_SCT_LIST,
+		.r2i = NULL,
+		.usr_data = NULL,
+	},
+};
diff --git a/crypto/curve25519/curve25519-generic.c b/crypto/curve25519/curve25519-generic.c
new file mode 100644
index 0000000..d533731
--- /dev/null
+++ b/crypto/curve25519/curve25519-generic.c
@@ -0,0 +1,34 @@
+/*	$OpenBSD: curve25519-generic.c,v 1.2 2019/05/11 15:55:52 tb Exp $ */
+/*
+ * Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
+ * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
+ * public domain but this file has the ISC license just to keep licencing
+ * simple.
+ *
+ * The field functions are shared by Ed25519 and X25519 where possible.
+ */
+
+#include "curve25519_internal.h"
+
+void
+x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
+    const uint8_t point[32])
+{
+	x25519_scalar_mult_generic(out, scalar, point);
+}
diff --git a/crypto/curve25519/curve25519.c b/crypto/curve25519/curve25519.c
new file mode 100644
index 0000000..4e644c4
--- /dev/null
+++ b/crypto/curve25519/curve25519.c
@@ -0,0 +1,4946 @@
+/*	$OpenBSD: curve25519.c,v 1.16 2023/07/08 15:12:49 beck Exp $ */
+/*
+ * Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
+ * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
+ * public domain but this file has the ISC license just to keep licencing
+ * simple.
+ *
+ * The field functions are shared by Ed25519 and X25519 where possible.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "curve25519_internal.h"
+
+static const int64_t kBottom25Bits = 0x1ffffffLL;
+static const int64_t kBottom26Bits = 0x3ffffffLL;
+static const int64_t kTop39Bits = 0xfffffffffe000000LL;
+static const int64_t kTop38Bits = 0xfffffffffc000000LL;
+
+static uint64_t load_3(const uint8_t *in) {
+  uint64_t result;
+  result = (uint64_t)in[0];
+  result |= ((uint64_t)in[1]) << 8;
+  result |= ((uint64_t)in[2]) << 16;
+  return result;
+}
+
+static uint64_t load_4(const uint8_t *in) {
+  uint64_t result;
+  result = (uint64_t)in[0];
+  result |= ((uint64_t)in[1]) << 8;
+  result |= ((uint64_t)in[2]) << 16;
+  result |= ((uint64_t)in[3]) << 24;
+  return result;
+}
+
+static void fe_frombytes(fe h, const uint8_t *s) {
+  /* Ignores top bit of h. */
+  int64_t h0 = load_4(s);
+  int64_t h1 = load_3(s + 4) << 6;
+  int64_t h2 = load_3(s + 7) << 5;
+  int64_t h3 = load_3(s + 10) << 3;
+  int64_t h4 = load_3(s + 13) << 2;
+  int64_t h5 = load_4(s + 16);
+  int64_t h6 = load_3(s + 20) << 7;
+  int64_t h7 = load_3(s + 23) << 5;
+  int64_t h8 = load_3(s + 26) << 4;
+  int64_t h9 = (load_3(s + 29) & 8388607) << 2;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
+
+  h[0] = h0;
+  h[1] = h1;
+  h[2] = h2;
+  h[3] = h3;
+  h[4] = h4;
+  h[5] = h5;
+  h[6] = h6;
+  h[7] = h7;
+  h[8] = h8;
+  h[9] = h9;
+}
+
+/* Preconditions:
+ *  |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ *
+ * Write p=2^255-19; q=floor(h/p).
+ * Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
+ *
+ * Proof:
+ *   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
+ *   Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
+ *
+ *   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
+ *   Then 0> 25;
+  q = (h0 + q) >> 26;
+  q = (h1 + q) >> 25;
+  q = (h2 + q) >> 26;
+  q = (h3 + q) >> 25;
+  q = (h4 + q) >> 26;
+  q = (h5 + q) >> 25;
+  q = (h6 + q) >> 26;
+  q = (h7 + q) >> 25;
+  q = (h8 + q) >> 26;
+  q = (h9 + q) >> 25;
+
+  /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
+  h0 += 19 * q;
+  /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
+
+  h1 += h0 >> 26; h0 &= kBottom26Bits;
+  h2 += h1 >> 25; h1 &= kBottom25Bits;
+  h3 += h2 >> 26; h2 &= kBottom26Bits;
+  h4 += h3 >> 25; h3 &= kBottom25Bits;
+  h5 += h4 >> 26; h4 &= kBottom26Bits;
+  h6 += h5 >> 25; h5 &= kBottom25Bits;
+  h7 += h6 >> 26; h6 &= kBottom26Bits;
+  h8 += h7 >> 25; h7 &= kBottom25Bits;
+  h9 += h8 >> 26; h8 &= kBottom26Bits;
+                  h9 &= kBottom25Bits;
+                  /* h10 = carry9 */
+
+  /* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
+   * Have h0+...+2^230 h9 between 0 and 2^255-1;
+   * evidently 2^255 h10-2^255 q = 0.
+   * Goal: Output h0+...+2^230 h9.  */
+
+  s[0] = h0 >> 0;
+  s[1] = h0 >> 8;
+  s[2] = h0 >> 16;
+  s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
+  s[4] = h1 >> 6;
+  s[5] = h1 >> 14;
+  s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
+  s[7] = h2 >> 5;
+  s[8] = h2 >> 13;
+  s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
+  s[10] = h3 >> 3;
+  s[11] = h3 >> 11;
+  s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
+  s[13] = h4 >> 2;
+  s[14] = h4 >> 10;
+  s[15] = h4 >> 18;
+  s[16] = h5 >> 0;
+  s[17] = h5 >> 8;
+  s[18] = h5 >> 16;
+  s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
+  s[20] = h6 >> 7;
+  s[21] = h6 >> 15;
+  s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
+  s[23] = h7 >> 5;
+  s[24] = h7 >> 13;
+  s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
+  s[26] = h8 >> 4;
+  s[27] = h8 >> 12;
+  s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
+  s[29] = h9 >> 2;
+  s[30] = h9 >> 10;
+  s[31] = h9 >> 18;
+}
+
+/* h = f */
+static void fe_copy(fe h, const fe f) {
+  memmove(h, f, sizeof(int32_t) * 10);
+}
+
+/* h = 0 */
+static void fe_0(fe h) { memset(h, 0, sizeof(int32_t) * 10); }
+
+/* h = 1 */
+static void fe_1(fe h) {
+  memset(h, 0, sizeof(int32_t) * 10);
+  h[0] = 1;
+}
+
+/* h = f + g
+ * Can overlap h with f or g.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *    |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static void fe_add(fe h, const fe f, const fe g) {
+  unsigned i;
+  for (i = 0; i < 10; i++) {
+    h[i] = f[i] + g[i];
+  }
+}
+
+/* h = f - g
+ * Can overlap h with f or g.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *    |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static void fe_sub(fe h, const fe f, const fe g) {
+  unsigned i;
+  for (i = 0; i < 10; i++) {
+    h[i] = f[i] - g[i];
+  }
+}
+
+/* h = f * g
+ * Can overlap h with f or g.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *    |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ *
+ * Notes on implementation strategy:
+ *
+ * Using schoolbook multiplication.
+ * Karatsuba would save a little in some cost models.
+ *
+ * Most multiplications by 2 and 19 are 32-bit precomputations;
+ * cheaper than 64-bit postcomputations.
+ *
+ * There is one remaining multiplication by 19 in the carry chain;
+ * one *19 precomputation can be merged into this,
+ * but the resulting data flow is considerably less clean.
+ *
+ * There are 12 carries below.
+ * 10 of them are 2-way parallelizable and vectorizable.
+ * Can get away with 11 carries, but then data flow is much deeper.
+ *
+ * With tighter constraints on inputs can squeeze carries into int32. */
+static void fe_mul(fe h, const fe f, const fe g) {
+  int32_t f0 = f[0];
+  int32_t f1 = f[1];
+  int32_t f2 = f[2];
+  int32_t f3 = f[3];
+  int32_t f4 = f[4];
+  int32_t f5 = f[5];
+  int32_t f6 = f[6];
+  int32_t f7 = f[7];
+  int32_t f8 = f[8];
+  int32_t f9 = f[9];
+  int32_t g0 = g[0];
+  int32_t g1 = g[1];
+  int32_t g2 = g[2];
+  int32_t g3 = g[3];
+  int32_t g4 = g[4];
+  int32_t g5 = g[5];
+  int32_t g6 = g[6];
+  int32_t g7 = g[7];
+  int32_t g8 = g[8];
+  int32_t g9 = g[9];
+  int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
+  int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
+  int32_t g3_19 = 19 * g3;
+  int32_t g4_19 = 19 * g4;
+  int32_t g5_19 = 19 * g5;
+  int32_t g6_19 = 19 * g6;
+  int32_t g7_19 = 19 * g7;
+  int32_t g8_19 = 19 * g8;
+  int32_t g9_19 = 19 * g9;
+  int32_t f1_2 = 2 * f1;
+  int32_t f3_2 = 2 * f3;
+  int32_t f5_2 = 2 * f5;
+  int32_t f7_2 = 2 * f7;
+  int32_t f9_2 = 2 * f9;
+  int64_t f0g0    = f0   * (int64_t) g0;
+  int64_t f0g1    = f0   * (int64_t) g1;
+  int64_t f0g2    = f0   * (int64_t) g2;
+  int64_t f0g3    = f0   * (int64_t) g3;
+  int64_t f0g4    = f0   * (int64_t) g4;
+  int64_t f0g5    = f0   * (int64_t) g5;
+  int64_t f0g6    = f0   * (int64_t) g6;
+  int64_t f0g7    = f0   * (int64_t) g7;
+  int64_t f0g8    = f0   * (int64_t) g8;
+  int64_t f0g9    = f0   * (int64_t) g9;
+  int64_t f1g0    = f1   * (int64_t) g0;
+  int64_t f1g1_2  = f1_2 * (int64_t) g1;
+  int64_t f1g2    = f1   * (int64_t) g2;
+  int64_t f1g3_2  = f1_2 * (int64_t) g3;
+  int64_t f1g4    = f1   * (int64_t) g4;
+  int64_t f1g5_2  = f1_2 * (int64_t) g5;
+  int64_t f1g6    = f1   * (int64_t) g6;
+  int64_t f1g7_2  = f1_2 * (int64_t) g7;
+  int64_t f1g8    = f1   * (int64_t) g8;
+  int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
+  int64_t f2g0    = f2   * (int64_t) g0;
+  int64_t f2g1    = f2   * (int64_t) g1;
+  int64_t f2g2    = f2   * (int64_t) g2;
+  int64_t f2g3    = f2   * (int64_t) g3;
+  int64_t f2g4    = f2   * (int64_t) g4;
+  int64_t f2g5    = f2   * (int64_t) g5;
+  int64_t f2g6    = f2   * (int64_t) g6;
+  int64_t f2g7    = f2   * (int64_t) g7;
+  int64_t f2g8_19 = f2   * (int64_t) g8_19;
+  int64_t f2g9_19 = f2   * (int64_t) g9_19;
+  int64_t f3g0    = f3   * (int64_t) g0;
+  int64_t f3g1_2  = f3_2 * (int64_t) g1;
+  int64_t f3g2    = f3   * (int64_t) g2;
+  int64_t f3g3_2  = f3_2 * (int64_t) g3;
+  int64_t f3g4    = f3   * (int64_t) g4;
+  int64_t f3g5_2  = f3_2 * (int64_t) g5;
+  int64_t f3g6    = f3   * (int64_t) g6;
+  int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
+  int64_t f3g8_19 = f3   * (int64_t) g8_19;
+  int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
+  int64_t f4g0    = f4   * (int64_t) g0;
+  int64_t f4g1    = f4   * (int64_t) g1;
+  int64_t f4g2    = f4   * (int64_t) g2;
+  int64_t f4g3    = f4   * (int64_t) g3;
+  int64_t f4g4    = f4   * (int64_t) g4;
+  int64_t f4g5    = f4   * (int64_t) g5;
+  int64_t f4g6_19 = f4   * (int64_t) g6_19;
+  int64_t f4g7_19 = f4   * (int64_t) g7_19;
+  int64_t f4g8_19 = f4   * (int64_t) g8_19;
+  int64_t f4g9_19 = f4   * (int64_t) g9_19;
+  int64_t f5g0    = f5   * (int64_t) g0;
+  int64_t f5g1_2  = f5_2 * (int64_t) g1;
+  int64_t f5g2    = f5   * (int64_t) g2;
+  int64_t f5g3_2  = f5_2 * (int64_t) g3;
+  int64_t f5g4    = f5   * (int64_t) g4;
+  int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
+  int64_t f5g6_19 = f5   * (int64_t) g6_19;
+  int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
+  int64_t f5g8_19 = f5   * (int64_t) g8_19;
+  int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
+  int64_t f6g0    = f6   * (int64_t) g0;
+  int64_t f6g1    = f6   * (int64_t) g1;
+  int64_t f6g2    = f6   * (int64_t) g2;
+  int64_t f6g3    = f6   * (int64_t) g3;
+  int64_t f6g4_19 = f6   * (int64_t) g4_19;
+  int64_t f6g5_19 = f6   * (int64_t) g5_19;
+  int64_t f6g6_19 = f6   * (int64_t) g6_19;
+  int64_t f6g7_19 = f6   * (int64_t) g7_19;
+  int64_t f6g8_19 = f6   * (int64_t) g8_19;
+  int64_t f6g9_19 = f6   * (int64_t) g9_19;
+  int64_t f7g0    = f7   * (int64_t) g0;
+  int64_t f7g1_2  = f7_2 * (int64_t) g1;
+  int64_t f7g2    = f7   * (int64_t) g2;
+  int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
+  int64_t f7g4_19 = f7   * (int64_t) g4_19;
+  int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
+  int64_t f7g6_19 = f7   * (int64_t) g6_19;
+  int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
+  int64_t f7g8_19 = f7   * (int64_t) g8_19;
+  int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
+  int64_t f8g0    = f8   * (int64_t) g0;
+  int64_t f8g1    = f8   * (int64_t) g1;
+  int64_t f8g2_19 = f8   * (int64_t) g2_19;
+  int64_t f8g3_19 = f8   * (int64_t) g3_19;
+  int64_t f8g4_19 = f8   * (int64_t) g4_19;
+  int64_t f8g5_19 = f8   * (int64_t) g5_19;
+  int64_t f8g6_19 = f8   * (int64_t) g6_19;
+  int64_t f8g7_19 = f8   * (int64_t) g7_19;
+  int64_t f8g8_19 = f8   * (int64_t) g8_19;
+  int64_t f8g9_19 = f8   * (int64_t) g9_19;
+  int64_t f9g0    = f9   * (int64_t) g0;
+  int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
+  int64_t f9g2_19 = f9   * (int64_t) g2_19;
+  int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
+  int64_t f9g4_19 = f9   * (int64_t) g4_19;
+  int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
+  int64_t f9g6_19 = f9   * (int64_t) g6_19;
+  int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
+  int64_t f9g8_19 = f9   * (int64_t) g8_19;
+  int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
+  int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
+  int64_t h1 = f0g1+f1g0   +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
+  int64_t h2 = f0g2+f1g1_2 +f2g0   +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
+  int64_t h3 = f0g3+f1g2   +f2g1   +f3g0   +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
+  int64_t h4 = f0g4+f1g3_2 +f2g2   +f3g1_2 +f4g0   +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
+  int64_t h5 = f0g5+f1g4   +f2g3   +f3g2   +f4g1   +f5g0   +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
+  int64_t h6 = f0g6+f1g5_2 +f2g4   +f3g3_2 +f4g2   +f5g1_2 +f6g0   +f7g9_38+f8g8_19+f9g7_38;
+  int64_t h7 = f0g7+f1g6   +f2g5   +f3g4   +f4g3   +f5g2   +f6g1   +f7g0   +f8g9_19+f9g8_19;
+  int64_t h8 = f0g8+f1g7_2 +f2g6   +f3g5_2 +f4g4   +f5g3_2 +f6g2   +f7g1_2 +f8g0   +f9g9_38;
+  int64_t h9 = f0g9+f1g8   +f2g7   +f3g6   +f4g5   +f5g4   +f6g3   +f7g2   +f8g1   +f9g0   ;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+
+  /* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
+   *   i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
+   * |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
+   *   i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  /* |h0| <= 2^25 */
+  /* |h4| <= 2^25 */
+  /* |h1| <= 1.71*2^59 */
+  /* |h5| <= 1.71*2^59 */
+
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+  /* |h1| <= 2^24; from now on fits into int32 */
+  /* |h5| <= 2^24; from now on fits into int32 */
+  /* |h2| <= 1.41*2^60 */
+  /* |h6| <= 1.41*2^60 */
+
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+  /* |h2| <= 2^25; from now on fits into int32 unchanged */
+  /* |h6| <= 2^25; from now on fits into int32 unchanged */
+  /* |h3| <= 1.71*2^59 */
+  /* |h7| <= 1.71*2^59 */
+
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
+  /* |h3| <= 2^24; from now on fits into int32 unchanged */
+  /* |h7| <= 2^24; from now on fits into int32 unchanged */
+  /* |h4| <= 1.72*2^34 */
+  /* |h8| <= 1.41*2^60 */
+
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
+  /* |h4| <= 2^25; from now on fits into int32 unchanged */
+  /* |h8| <= 2^25; from now on fits into int32 unchanged */
+  /* |h5| <= 1.01*2^24 */
+  /* |h9| <= 1.71*2^59 */
+
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+  /* |h9| <= 2^24; from now on fits into int32 unchanged */
+  /* |h0| <= 1.1*2^39 */
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  /* |h0| <= 2^25; from now on fits into int32 unchanged */
+  /* |h1| <= 1.01*2^24 */
+
+  h[0] = h0;
+  h[1] = h1;
+  h[2] = h2;
+  h[3] = h3;
+  h[4] = h4;
+  h[5] = h5;
+  h[6] = h6;
+  h[7] = h7;
+  h[8] = h8;
+  h[9] = h9;
+}
+
+/* h = f * f
+ * Can overlap h with f.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ *
+ * See fe_mul.c for discussion of implementation strategy. */
+static void fe_sq(fe h, const fe f) {
+  int32_t f0 = f[0];
+  int32_t f1 = f[1];
+  int32_t f2 = f[2];
+  int32_t f3 = f[3];
+  int32_t f4 = f[4];
+  int32_t f5 = f[5];
+  int32_t f6 = f[6];
+  int32_t f7 = f[7];
+  int32_t f8 = f[8];
+  int32_t f9 = f[9];
+  int32_t f0_2 = 2 * f0;
+  int32_t f1_2 = 2 * f1;
+  int32_t f2_2 = 2 * f2;
+  int32_t f3_2 = 2 * f3;
+  int32_t f4_2 = 2 * f4;
+  int32_t f5_2 = 2 * f5;
+  int32_t f6_2 = 2 * f6;
+  int32_t f7_2 = 2 * f7;
+  int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
+  int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
+  int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
+  int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
+  int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
+  int64_t f0f0    = f0   * (int64_t) f0;
+  int64_t f0f1_2  = f0_2 * (int64_t) f1;
+  int64_t f0f2_2  = f0_2 * (int64_t) f2;
+  int64_t f0f3_2  = f0_2 * (int64_t) f3;
+  int64_t f0f4_2  = f0_2 * (int64_t) f4;
+  int64_t f0f5_2  = f0_2 * (int64_t) f5;
+  int64_t f0f6_2  = f0_2 * (int64_t) f6;
+  int64_t f0f7_2  = f0_2 * (int64_t) f7;
+  int64_t f0f8_2  = f0_2 * (int64_t) f8;
+  int64_t f0f9_2  = f0_2 * (int64_t) f9;
+  int64_t f1f1_2  = f1_2 * (int64_t) f1;
+  int64_t f1f2_2  = f1_2 * (int64_t) f2;
+  int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
+  int64_t f1f4_2  = f1_2 * (int64_t) f4;
+  int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
+  int64_t f1f6_2  = f1_2 * (int64_t) f6;
+  int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
+  int64_t f1f8_2  = f1_2 * (int64_t) f8;
+  int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
+  int64_t f2f2    = f2   * (int64_t) f2;
+  int64_t f2f3_2  = f2_2 * (int64_t) f3;
+  int64_t f2f4_2  = f2_2 * (int64_t) f4;
+  int64_t f2f5_2  = f2_2 * (int64_t) f5;
+  int64_t f2f6_2  = f2_2 * (int64_t) f6;
+  int64_t f2f7_2  = f2_2 * (int64_t) f7;
+  int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
+  int64_t f2f9_38 = f2   * (int64_t) f9_38;
+  int64_t f3f3_2  = f3_2 * (int64_t) f3;
+  int64_t f3f4_2  = f3_2 * (int64_t) f4;
+  int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
+  int64_t f3f6_2  = f3_2 * (int64_t) f6;
+  int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
+  int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
+  int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
+  int64_t f4f4    = f4   * (int64_t) f4;
+  int64_t f4f5_2  = f4_2 * (int64_t) f5;
+  int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
+  int64_t f4f7_38 = f4   * (int64_t) f7_38;
+  int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
+  int64_t f4f9_38 = f4   * (int64_t) f9_38;
+  int64_t f5f5_38 = f5   * (int64_t) f5_38;
+  int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
+  int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
+  int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
+  int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
+  int64_t f6f6_19 = f6   * (int64_t) f6_19;
+  int64_t f6f7_38 = f6   * (int64_t) f7_38;
+  int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
+  int64_t f6f9_38 = f6   * (int64_t) f9_38;
+  int64_t f7f7_38 = f7   * (int64_t) f7_38;
+  int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
+  int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
+  int64_t f8f8_19 = f8   * (int64_t) f8_19;
+  int64_t f8f9_38 = f8   * (int64_t) f9_38;
+  int64_t f9f9_38 = f9   * (int64_t) f9_38;
+  int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+  int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+  int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+  int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+  int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
+  int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+  int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+  int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+  int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
+  int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
+
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
+
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+
+  h[0] = h0;
+  h[1] = h1;
+  h[2] = h2;
+  h[3] = h3;
+  h[4] = h4;
+  h[5] = h5;
+  h[6] = h6;
+  h[7] = h7;
+  h[8] = h8;
+  h[9] = h9;
+}
+
+static void fe_invert(fe out, const fe z) {
+  fe t0;
+  fe t1;
+  fe t2;
+  fe t3;
+  int i;
+
+  fe_sq(t0, z);
+  fe_sq(t1, t0);
+  for (i = 1; i < 2; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t1, z, t1);
+  fe_mul(t0, t0, t1);
+  fe_sq(t2, t0);
+  fe_mul(t1, t1, t2);
+  fe_sq(t2, t1);
+  for (i = 1; i < 5; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t1, t2, t1);
+  fe_sq(t2, t1);
+  for (i = 1; i < 10; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t2, t2, t1);
+  fe_sq(t3, t2);
+  for (i = 1; i < 20; ++i) {
+    fe_sq(t3, t3);
+  }
+  fe_mul(t2, t3, t2);
+  fe_sq(t2, t2);
+  for (i = 1; i < 10; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t1, t2, t1);
+  fe_sq(t2, t1);
+  for (i = 1; i < 50; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t2, t2, t1);
+  fe_sq(t3, t2);
+  for (i = 1; i < 100; ++i) {
+    fe_sq(t3, t3);
+  }
+  fe_mul(t2, t3, t2);
+  fe_sq(t2, t2);
+  for (i = 1; i < 50; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t1, t2, t1);
+  fe_sq(t1, t1);
+  for (i = 1; i < 5; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(out, t1, t0);
+}
+
+/* h = -f
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */
+static void fe_neg(fe h, const fe f) {
+  unsigned i;
+  for (i = 0; i < 10; i++) {
+    h[i] = -f[i];
+  }
+}
+
+/* Replace (f,g) with (g,g) if b == 1;
+ * replace (f,g) with (f,g) if b == 0.
+ *
+ * Preconditions: b in {0,1}. */
+static void fe_cmov(fe f, const fe g, unsigned b) {
+  b = 0-b;
+  unsigned i;
+  for (i = 0; i < 10; i++) {
+    int32_t x = f[i] ^ g[i];
+    x &= b;
+    f[i] ^= x;
+  }
+}
+
+/* return 0 if f == 0
+ * return 1 if f != 0
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static int fe_isnonzero(const fe f) {
+  uint8_t s[32];
+  fe_tobytes(s, f);
+
+  static const uint8_t zero[32] = {0};
+  return timingsafe_memcmp(s, zero, sizeof(zero)) != 0;
+}
+
+/* return 1 if f is in {1,3,5,...,q-2}
+ * return 0 if f is in {0,2,4,...,q-1}
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
+static int fe_isnegative(const fe f) {
+  uint8_t s[32];
+  fe_tobytes(s, f);
+  return s[0] & 1;
+}
+
+/* h = 2 * f * f
+ * Can overlap h with f.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
+ *
+ * See fe_mul.c for discussion of implementation strategy. */
+static void fe_sq2(fe h, const fe f) {
+  int32_t f0 = f[0];
+  int32_t f1 = f[1];
+  int32_t f2 = f[2];
+  int32_t f3 = f[3];
+  int32_t f4 = f[4];
+  int32_t f5 = f[5];
+  int32_t f6 = f[6];
+  int32_t f7 = f[7];
+  int32_t f8 = f[8];
+  int32_t f9 = f[9];
+  int32_t f0_2 = 2 * f0;
+  int32_t f1_2 = 2 * f1;
+  int32_t f2_2 = 2 * f2;
+  int32_t f3_2 = 2 * f3;
+  int32_t f4_2 = 2 * f4;
+  int32_t f5_2 = 2 * f5;
+  int32_t f6_2 = 2 * f6;
+  int32_t f7_2 = 2 * f7;
+  int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
+  int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
+  int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
+  int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
+  int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
+  int64_t f0f0    = f0   * (int64_t) f0;
+  int64_t f0f1_2  = f0_2 * (int64_t) f1;
+  int64_t f0f2_2  = f0_2 * (int64_t) f2;
+  int64_t f0f3_2  = f0_2 * (int64_t) f3;
+  int64_t f0f4_2  = f0_2 * (int64_t) f4;
+  int64_t f0f5_2  = f0_2 * (int64_t) f5;
+  int64_t f0f6_2  = f0_2 * (int64_t) f6;
+  int64_t f0f7_2  = f0_2 * (int64_t) f7;
+  int64_t f0f8_2  = f0_2 * (int64_t) f8;
+  int64_t f0f9_2  = f0_2 * (int64_t) f9;
+  int64_t f1f1_2  = f1_2 * (int64_t) f1;
+  int64_t f1f2_2  = f1_2 * (int64_t) f2;
+  int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
+  int64_t f1f4_2  = f1_2 * (int64_t) f4;
+  int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
+  int64_t f1f6_2  = f1_2 * (int64_t) f6;
+  int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
+  int64_t f1f8_2  = f1_2 * (int64_t) f8;
+  int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
+  int64_t f2f2    = f2   * (int64_t) f2;
+  int64_t f2f3_2  = f2_2 * (int64_t) f3;
+  int64_t f2f4_2  = f2_2 * (int64_t) f4;
+  int64_t f2f5_2  = f2_2 * (int64_t) f5;
+  int64_t f2f6_2  = f2_2 * (int64_t) f6;
+  int64_t f2f7_2  = f2_2 * (int64_t) f7;
+  int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
+  int64_t f2f9_38 = f2   * (int64_t) f9_38;
+  int64_t f3f3_2  = f3_2 * (int64_t) f3;
+  int64_t f3f4_2  = f3_2 * (int64_t) f4;
+  int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
+  int64_t f3f6_2  = f3_2 * (int64_t) f6;
+  int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
+  int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
+  int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
+  int64_t f4f4    = f4   * (int64_t) f4;
+  int64_t f4f5_2  = f4_2 * (int64_t) f5;
+  int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
+  int64_t f4f7_38 = f4   * (int64_t) f7_38;
+  int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
+  int64_t f4f9_38 = f4   * (int64_t) f9_38;
+  int64_t f5f5_38 = f5   * (int64_t) f5_38;
+  int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
+  int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
+  int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
+  int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
+  int64_t f6f6_19 = f6   * (int64_t) f6_19;
+  int64_t f6f7_38 = f6   * (int64_t) f7_38;
+  int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
+  int64_t f6f9_38 = f6   * (int64_t) f9_38;
+  int64_t f7f7_38 = f7   * (int64_t) f7_38;
+  int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
+  int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
+  int64_t f8f8_19 = f8   * (int64_t) f8_19;
+  int64_t f8f9_38 = f8   * (int64_t) f9_38;
+  int64_t f9f9_38 = f9   * (int64_t) f9_38;
+  int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
+  int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
+  int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
+  int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
+  int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
+  int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
+  int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
+  int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
+  int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
+  int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+
+  h0 += h0;
+  h1 += h1;
+  h2 += h2;
+  h3 += h3;
+  h4 += h4;
+  h5 += h5;
+  h6 += h6;
+  h7 += h7;
+  h8 += h8;
+  h9 += h9;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
+
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
+
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+
+  h[0] = h0;
+  h[1] = h1;
+  h[2] = h2;
+  h[3] = h3;
+  h[4] = h4;
+  h[5] = h5;
+  h[6] = h6;
+  h[7] = h7;
+  h[8] = h8;
+  h[9] = h9;
+}
+
+static void fe_pow22523(fe out, const fe z) {
+  fe t0;
+  fe t1;
+  fe t2;
+  int i;
+
+  fe_sq(t0, z);
+  fe_sq(t1, t0);
+  for (i = 1; i < 2; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t1, z, t1);
+  fe_mul(t0, t0, t1);
+  fe_sq(t0, t0);
+  fe_mul(t0, t1, t0);
+  fe_sq(t1, t0);
+  for (i = 1; i < 5; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t0, t1, t0);
+  fe_sq(t1, t0);
+  for (i = 1; i < 10; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t1, t1, t0);
+  fe_sq(t2, t1);
+  for (i = 1; i < 20; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t1, t2, t1);
+  fe_sq(t1, t1);
+  for (i = 1; i < 10; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t0, t1, t0);
+  fe_sq(t1, t0);
+  for (i = 1; i < 50; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t1, t1, t0);
+  fe_sq(t2, t1);
+  for (i = 1; i < 100; ++i) {
+    fe_sq(t2, t2);
+  }
+  fe_mul(t1, t2, t1);
+  fe_sq(t1, t1);
+  for (i = 1; i < 50; ++i) {
+    fe_sq(t1, t1);
+  }
+  fe_mul(t0, t1, t0);
+  fe_sq(t0, t0);
+  for (i = 1; i < 2; ++i) {
+    fe_sq(t0, t0);
+  }
+  fe_mul(out, t0, z);
+}
+
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) {
+  fe recip;
+  fe x;
+  fe y;
+
+  fe_invert(recip, h->Z);
+  fe_mul(x, h->X, recip);
+  fe_mul(y, h->Y, recip);
+  fe_tobytes(s, y);
+  s[31] ^= fe_isnegative(x) << 7;
+}
+
+static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) {
+  fe recip;
+  fe x;
+  fe y;
+
+  fe_invert(recip, h->Z);
+  fe_mul(x, h->X, recip);
+  fe_mul(y, h->Y, recip);
+  fe_tobytes(s, y);
+  s[31] ^= fe_isnegative(x) << 7;
+}
+
+static const fe d = {-10913610, 13857413, -15372611, 6949391,   114729,
+                     -8787816,  -6275908, -3247719,  -18696448, -12055116};
+
+static const fe sqrtm1 = {-32595792, -7943725,  9377950,  3500415, 12389472,
+                          -272473,   -25146209, -2005654, 326686,  11406482};
+
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
+  fe u;
+  fe v;
+  fe v3;
+  fe vxx;
+  fe check;
+
+  fe_frombytes(h->Y, s);
+  fe_1(h->Z);
+  fe_sq(u, h->Y);
+  fe_mul(v, u, d);
+  fe_sub(u, u, h->Z); /* u = y^2-1 */
+  fe_add(v, v, h->Z); /* v = dy^2+1 */
+
+  fe_sq(v3, v);
+  fe_mul(v3, v3, v); /* v3 = v^3 */
+  fe_sq(h->X, v3);
+  fe_mul(h->X, h->X, v);
+  fe_mul(h->X, h->X, u); /* x = uv^7 */
+
+  fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
+  fe_mul(h->X, h->X, v3);
+  fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
+
+  fe_sq(vxx, h->X);
+  fe_mul(vxx, vxx, v);
+  fe_sub(check, vxx, u); /* vx^2-u */
+  if (fe_isnonzero(check)) {
+    fe_add(check, vxx, u); /* vx^2+u */
+    if (fe_isnonzero(check)) {
+      return -1;
+    }
+    fe_mul(h->X, h->X, sqrtm1);
+  }
+
+  if (fe_isnegative(h->X) != (s[31] >> 7)) {
+    fe_neg(h->X, h->X);
+  }
+
+  fe_mul(h->T, h->X, h->Y);
+  return 0;
+}
+
+static void ge_p2_0(ge_p2 *h) {
+  fe_0(h->X);
+  fe_1(h->Y);
+  fe_1(h->Z);
+}
+
+static void ge_p3_0(ge_p3 *h) {
+  fe_0(h->X);
+  fe_1(h->Y);
+  fe_1(h->Z);
+  fe_0(h->T);
+}
+
+static void ge_cached_0(ge_cached *h) {
+  fe_1(h->YplusX);
+  fe_1(h->YminusX);
+  fe_1(h->Z);
+  fe_0(h->T2d);
+}
+
+static void ge_precomp_0(ge_precomp *h) {
+  fe_1(h->yplusx);
+  fe_1(h->yminusx);
+  fe_0(h->xy2d);
+}
+
+/* r = p */
+static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
+  fe_copy(r->X, p->X);
+  fe_copy(r->Y, p->Y);
+  fe_copy(r->Z, p->Z);
+}
+
+static const fe d2 = {-21827239, -5839606,  -30745221, 13898782, 229458,
+                      15978800,  -12551817, -6495438,  29715968, 9444199};
+
+/* r = p */
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
+  fe_add(r->YplusX, p->Y, p->X);
+  fe_sub(r->YminusX, p->Y, p->X);
+  fe_copy(r->Z, p->Z);
+  fe_mul(r->T2d, p->T, d2);
+}
+
+/* r = p */
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
+  fe_mul(r->X, p->X, p->T);
+  fe_mul(r->Y, p->Y, p->Z);
+  fe_mul(r->Z, p->Z, p->T);
+}
+
+/* r = p */
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
+  fe_mul(r->X, p->X, p->T);
+  fe_mul(r->Y, p->Y, p->Z);
+  fe_mul(r->Z, p->Z, p->T);
+  fe_mul(r->T, p->X, p->Y);
+}
+
+/* r = p */
+static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
+  ge_p3 t;
+  x25519_ge_p1p1_to_p3(&t, p);
+  x25519_ge_p3_to_cached(r, &t);
+}
+
+/* r = 2 * p */
+static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
+  fe t0;
+
+  fe_sq(r->X, p->X);
+  fe_sq(r->Z, p->Y);
+  fe_sq2(r->T, p->Z);
+  fe_add(r->Y, p->X, p->Y);
+  fe_sq(t0, r->Y);
+  fe_add(r->Y, r->Z, r->X);
+  fe_sub(r->Z, r->Z, r->X);
+  fe_sub(r->X, t0, r->Y);
+  fe_sub(r->T, r->T, r->Z);
+}
+
+/* r = 2 * p */
+static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
+  ge_p2 q;
+  ge_p3_to_p2(&q, p);
+  ge_p2_dbl(r, &q);
+}
+
+/* r = p + q */
+static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
+  fe t0;
+
+  fe_add(r->X, p->Y, p->X);
+  fe_sub(r->Y, p->Y, p->X);
+  fe_mul(r->Z, r->X, q->yplusx);
+  fe_mul(r->Y, r->Y, q->yminusx);
+  fe_mul(r->T, q->xy2d, p->T);
+  fe_add(t0, p->Z, p->Z);
+  fe_sub(r->X, r->Z, r->Y);
+  fe_add(r->Y, r->Z, r->Y);
+  fe_add(r->Z, t0, r->T);
+  fe_sub(r->T, t0, r->T);
+}
+
+/* r = p - q */
+static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
+  fe t0;
+
+  fe_add(r->X, p->Y, p->X);
+  fe_sub(r->Y, p->Y, p->X);
+  fe_mul(r->Z, r->X, q->yminusx);
+  fe_mul(r->Y, r->Y, q->yplusx);
+  fe_mul(r->T, q->xy2d, p->T);
+  fe_add(t0, p->Z, p->Z);
+  fe_sub(r->X, r->Z, r->Y);
+  fe_add(r->Y, r->Z, r->Y);
+  fe_sub(r->Z, t0, r->T);
+  fe_add(r->T, t0, r->T);
+}
+
+/* r = p + q */
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+  fe t0;
+
+  fe_add(r->X, p->Y, p->X);
+  fe_sub(r->Y, p->Y, p->X);
+  fe_mul(r->Z, r->X, q->YplusX);
+  fe_mul(r->Y, r->Y, q->YminusX);
+  fe_mul(r->T, q->T2d, p->T);
+  fe_mul(r->X, p->Z, q->Z);
+  fe_add(t0, r->X, r->X);
+  fe_sub(r->X, r->Z, r->Y);
+  fe_add(r->Y, r->Z, r->Y);
+  fe_add(r->Z, t0, r->T);
+  fe_sub(r->T, t0, r->T);
+}
+
+/* r = p - q */
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+  fe t0;
+
+  fe_add(r->X, p->Y, p->X);
+  fe_sub(r->Y, p->Y, p->X);
+  fe_mul(r->Z, r->X, q->YminusX);
+  fe_mul(r->Y, r->Y, q->YplusX);
+  fe_mul(r->T, q->T2d, p->T);
+  fe_mul(r->X, p->Z, q->Z);
+  fe_add(t0, r->X, r->X);
+  fe_sub(r->X, r->Z, r->Y);
+  fe_add(r->Y, r->Z, r->Y);
+  fe_sub(r->Z, t0, r->T);
+  fe_add(r->T, t0, r->T);
+}
+
+static uint8_t equal(signed char b, signed char c) {
+  uint8_t ub = b;
+  uint8_t uc = c;
+  uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */
+  uint32_t y = x;      /* 0: yes; 1..255: no */
+  y -= 1;              /* 4294967295: yes; 0..254: no */
+  y >>= 31;            /* 1: yes; 0: no */
+  return y;
+}
+
+static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
+  fe_cmov(t->yplusx, u->yplusx, b);
+  fe_cmov(t->yminusx, u->yminusx, b);
+  fe_cmov(t->xy2d, u->xy2d, b);
+}
+
+void x25519_ge_scalarmult_small_precomp(
+    ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
+  /* precomp_table is first expanded into matching |ge_precomp|
+   * elements. */
+  ge_precomp multiples[15];
+
+  unsigned i;
+  for (i = 0; i < 15; i++) {
+    const uint8_t *bytes = &precomp_table[i*(2 * 32)];
+    fe x, y;
+    fe_frombytes(x, bytes);
+    fe_frombytes(y, bytes + 32);
+
+    ge_precomp *out = &multiples[i];
+    fe_add(out->yplusx, y, x);
+    fe_sub(out->yminusx, y, x);
+    fe_mul(out->xy2d, x, y);
+    fe_mul(out->xy2d, out->xy2d, d2);
+  }
+
+  /* See the comment above |k25519SmallPrecomp| about the structure of the
+   * precomputed elements. This loop does 64 additions and 64 doublings to
+   * calculate the result. */
+  ge_p3_0(h);
+
+  for (i = 63; i < 64; i--) {
+    unsigned j;
+    signed char index = 0;
+
+    for (j = 0; j < 4; j++) {
+      const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
+      index |= (bit << j);
+    }
+
+    ge_precomp e;
+    ge_precomp_0(&e);
+
+    for (j = 1; j < 16; j++) {
+      cmov(&e, &multiples[j-1], equal(index, j));
+    }
+
+    ge_cached cached;
+    ge_p1p1 r;
+    x25519_ge_p3_to_cached(&cached, h);
+    x25519_ge_add(&r, h, &cached);
+    x25519_ge_p1p1_to_p3(h, &r);
+
+    ge_madd(&r, h, &e);
+    x25519_ge_p1p1_to_p3(h, &r);
+  }
+}
+
+#if defined(OPENSSL_SMALL)
+
+/* This block of code replaces the standard base-point table with a much smaller
+ * one. The standard table is 30,720 bytes while this one is just 960.
+ *
+ * This table contains 15 pairs of group elements, (x, y), where each field
+ * element is serialised with |fe_tobytes|. If |i| is the index of the group
+ * element then consider i+1 as a four-bit number: (iâ‚€, iâ‚, iâ‚‚, i₃) (where iâ‚€
+ * is the most significant bit). The value of the group element is then:
+ * (i₀×2^192 + iâ‚×2^128 + i₂×2^64 + i₃)G, where G is the generator. */
+static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
+    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, 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, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e,
+    0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4,
+    0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62,
+    0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba,
+    0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd,
+    0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61,
+    0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c,
+    0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c,
+    0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5,
+    0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3,
+    0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18,
+    0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2,
+    0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95,
+    0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b,
+    0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90,
+    0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52,
+    0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb,
+    0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c,
+    0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e,
+    0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e,
+    0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a,
+    0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43,
+    0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53,
+    0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8,
+    0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89,
+    0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef,
+    0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60,
+    0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a,
+    0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8,
+    0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54,
+    0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b,
+    0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd,
+    0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb,
+    0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c,
+    0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b,
+    0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63,
+    0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a,
+    0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07,
+    0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa,
+    0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a,
+    0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84,
+    0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc,
+    0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42,
+    0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0,
+    0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0,
+    0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a,
+    0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5,
+    0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c,
+    0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27,
+    0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31,
+    0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c,
+    0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87,
+    0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0,
+    0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23,
+    0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2,
+    0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87,
+    0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d,
+    0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b,
+    0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d,
+    0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6,
+    0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84,
+    0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04,
+    0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19,
+    0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b,
+    0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a,
+    0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea,
+    0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30,
+    0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7,
+    0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa,
+    0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5,
+    0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71,
+    0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab,
+    0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb,
+    0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c,
+    0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
+};
+
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
+  x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
+}
+
+#else
+
+/* k25519Precomp[i][j] = (j+1)*256^i*B */
+static const ge_precomp k25519Precomp[32][8] = {
+    {
+        {
+            {25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
+             27544626, -11754271, -6079156, 2047605},
+            {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
+             5043384, 19500929, -15469378},
+            {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380,
+             29287919, 11864899, -24514362, -4438546},
+        },
+        {
+            {-12815894, -12976347, -21581243, 11784320, -25355658, -2750717,
+             -11717903, -3814571, -358445, -10211303},
+            {-21703237, 6903825, 27185491, 6451973, -29577724, -9554005,
+             -15616551, 11189268, -26829678, -5319081},
+            {26966642, 11152617, 32442495, 15396054, 14353839, -12752335,
+             -3128826, -9541118, -15472047, -4166697},
+        },
+        {
+            {15636291, -9688557, 24204773, -7912398, 616977, -16685262,
+             27787600, -14772189, 28944400, -1550024},
+            {16568933, 4717097, -11556148, -1102322, 15682896, -11807043,
+             16354577, -11775962, 7689662, 11199574},
+            {30464156, -5976125, -11779434, -15670865, 23220365, 15915852,
+             7512774, 10017326, -17749093, -9920357},
+        },
+        {
+            {-17036878, 13921892, 10945806, -6033431, 27105052, -16084379,
+             -28926210, 15006023, 3284568, -6276540},
+            {23599295, -8306047, -11193664, -7687416, 13236774, 10506355,
+             7464579, 9656445, 13059162, 10374397},
+            {7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664,
+             -3839045, -641708, -101325},
+        },
+        {
+            {10861363, 11473154, 27284546, 1981175, -30064349, 12577861,
+             32867885, 14515107, -15438304, 10819380},
+            {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
+             12483688, -12668491, 5581306},
+            {19563160, 16186464, -29386857, 4097519, 10237984, -4348115,
+             28542350, 13850243, -23678021, -15815942},
+        },
+        {
+            {-15371964, -12862754, 32573250, 4720197, -26436522, 5875511,
+             -19188627, -15224819, -9818940, -12085777},
+            {-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240,
+             -15689887, 1762328, 14866737},
+            {-18199695, -15951423, -10473290, 1707278, -17185920, 3916101,
+             -28236412, 3959421, 27914454, 4383652},
+        },
+        {
+            {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
+             5230134, -23952439, -15175766},
+            {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722,
+             20654025, 16520125, 30598449, 7715701},
+            {28881845, 14381568, 9657904, 3680757, -20181635, 7843316,
+             -31400660, 1370708, 29794553, -1409300},
+        },
+        {
+            {14499471, -2729599, -33191113, -4254652, 28494862, 14271267,
+             30290735, 10876454, -33154098, 2381726},
+            {-7195431, -2655363, -14730155, 462251, -27724326, 3941372,
+             -6236617, 3696005, -32300832, 15351955},
+            {27431194, 8222322, 16448760, -3907995, -18707002, 11938355,
+             -32961401, -2970515, 29551813, 10109425},
+        },
+    },
+    {
+        {
+            {-13657040, -13155431, -31283750, 11777098, 21447386, 6519384,
+             -2378284, -1627556, 10092783, -4764171},
+            {27939166, 14210322, 4677035, 16277044, -22964462, -12398139,
+             -32508754, 12005538, -17810127, 12803510},
+            {17228999, -15661624, -1233527, 300140, -1224870, -11714777,
+             30364213, -9038194, 18016357, 4397660},
+        },
+        {
+            {-10958843, -7690207, 4776341, -14954238, 27850028, -15602212,
+             -26619106, 14544525, -17477504, 982639},
+            {29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899,
+             -4120128, -21047696, 9934963},
+            {5793303, 16271923, -24131614, -10116404, 29188560, 1206517,
+             -14747930, 4559895, -30123922, -10897950},
+        },
+        {
+            {-27643952, -11493006, 16282657, -11036493, 28414021, -15012264,
+             24191034, 4541697, -13338309, 5500568},
+            {12650548, -1497113, 9052871, 11355358, -17680037, -8400164,
+             -17430592, 12264343, 10874051, 13524335},
+            {25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038,
+             5080568, -22528059, 5376628},
+        },
+        {
+            {-26088264, -4011052, -17013699, -3537628, -6726793, 1920897,
+             -22321305, -9447443, 4535768, 1569007},
+            {-2255422, 14606630, -21692440, -8039818, 28430649, 8775819,
+             -30494562, 3044290, 31848280, 12543772},
+            {-22028579, 2943893, -31857513, 6777306, 13784462, -4292203,
+             -27377195, -2062731, 7718482, 14474653},
+        },
+        {
+            {2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965,
+             -7236665, 24316168, -5253567},
+            {13741529, 10911568, -33233417, -8603737, -20177830, -1033297,
+             33040651, -13424532, -20729456, 8321686},
+            {21060490, -2212744, 15712757, -4336099, 1639040, 10656336,
+             23845965, -11874838, -9984458, 608372},
+        },
+        {
+            {-13672732, -15087586, -10889693, -7557059, -6036909, 11305547,
+             1123968, -6780577, 27229399, 23887},
+            {-23244140, -294205, -11744728, 14712571, -29465699, -2029617,
+             12797024, -6440308, -1633405, 16678954},
+            {-29500620, 4770662, -16054387, 14001338, 7830047, 9564805,
+             -1508144, -4795045, -17169265, 4904953},
+        },
+        {
+            {24059557, 14617003, 19037157, -15039908, 19766093, -14906429,
+             5169211, 16191880, 2128236, -4326833},
+            {-16981152, 4124966, -8540610, -10653797, 30336522, -14105247,
+             -29806336, 916033, -6882542, -2986532},
+            {-22630907, 12419372, -7134229, -7473371, -16478904, 16739175,
+             285431, 2763829, 15736322, 4143876},
+        },
+        {
+            {2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801,
+             -14594663, 23527084, -16458268},
+            {33431127, -11130478, -17838966, -15626900, 8909499, 8376530,
+             -32625340, 4087881, -15188911, -14416214},
+            {1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055,
+             4357868, -4774191, -16323038},
+        },
+    },
+    {
+        {
+            {6721966, 13833823, -23523388, -1551314, 26354293, -11863321,
+             23365147, -3949732, 7390890, 2759800},
+            {4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353,
+             -4264057, 1244380, -12919645},
+            {-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413,
+             9208236, 15886429, 16489664},
+        },
+        {
+            {1996075, 10375649, 14346367, 13311202, -6874135, -16438411,
+             -13693198, 398369, -30606455, -712933},
+            {-25307465, 9795880, -2777414, 14878809, -33531835, 14780363,
+             13348553, 12076947, -30836462, 5113182},
+            {-17770784, 11797796, 31950843, 13929123, -25888302, 12288344,
+             -30341101, -7336386, 13847711, 5387222},
+        },
+        {
+            {-18582163, -3416217, 17824843, -2340966, 22744343, -10442611,
+             8763061, 3617786, -19600662, 10370991},
+            {20246567, -14369378, 22358229, -543712, 18507283, -10413996,
+             14554437, -8746092, 32232924, 16763880},
+            {9648505, 10094563, 26416693, 14745928, -30374318, -6472621,
+             11094161, 15689506, 3140038, -16510092},
+        },
+        {
+            {-16160072, 5472695, 31895588, 4744994, 8823515, 10365685,
+             -27224800, 9448613, -28774454, 366295},
+            {19153450, 11523972, -11096490, -6503142, -24647631, 5420647,
+             28344573, 8041113, 719605, 11671788},
+            {8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916,
+             -15266516, 27000813, -10195553},
+        },
+        {
+            {-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065,
+             5336097, 6750977, -14521026},
+            {11836410, -3979488, 26297894, 16080799, 23455045, 15735944,
+             1695823, -8819122, 8169720, 16220347},
+            {-18115838, 8653647, 17578566, -6092619, -8025777, -16012763,
+             -11144307, -2627664, -5990708, -14166033},
+        },
+        {
+            {-23308498, -10968312, 15213228, -10081214, -30853605, -11050004,
+             27884329, 2847284, 2655861, 1738395},
+            {-27537433, -14253021, -25336301, -8002780, -9370762, 8129821,
+             21651608, -3239336, -19087449, -11005278},
+            {1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092,
+             5821408, 10478196, 8544890},
+        },
+        {
+            {32173121, -16129311, 24896207, 3921497, 22579056, -3410854,
+             19270449, 12217473, 17789017, -3395995},
+            {-30552961, -2228401, -15578829, -10147201, 13243889, 517024,
+             15479401, -3853233, 30460520, 1052596},
+            {-11614875, 13323618, 32618793, 8175907, -15230173, 12596687,
+             27491595, -4612359, 3179268, -9478891},
+        },
+        {
+            {31947069, -14366651, -4640583, -15339921, -15125977, -6039709,
+             -14756777, -16411740, 19072640, -9511060},
+            {11685058, 11822410, 3158003, -13952594, 33402194, -4165066,
+             5977896, -5215017, 473099, 5040608},
+            {-20290863, 8198642, -27410132, 11602123, 1290375, -2799760,
+             28326862, 1721092, -19558642, -3131606},
+        },
+    },
+    {
+        {
+            {7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786,
+             8076149, -27868496, 11538389},
+            {-19935666, 3899861, 18283497, -6801568, -15728660, -11249211,
+             8754525, 7446702, -5676054, 5797016},
+            {-11295600, -3793569, -15782110, -7964573, 12708869, -8456199,
+             2014099, -9050574, -2369172, -5877341},
+        },
+        {
+            {-22472376, -11568741, -27682020, 1146375, 18956691, 16640559,
+             1192730, -3714199, 15123619, 10811505},
+            {14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363,
+             15776356, -28886779, -11974553},
+            {-28241164, -8072475, -4978962, -5315317, 29416931, 1847569,
+             -20654173, -16484855, 4714547, -9600655},
+        },
+        {
+            {15200332, 8368572, 19679101, 15970074, -31872674, 1959451,
+             24611599, -4543832, -11745876, 12340220},
+            {12876937, -10480056, 33134381, 6590940, -6307776, 14872440,
+             9613953, 8241152, 15370987, 9608631},
+            {-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868,
+             15866074, -28210621, -8814099},
+        },
+        {
+            {26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233,
+             858697, 20571223, 8420556},
+            {14620715, 13067227, -15447274, 8264467, 14106269, 15080814,
+             33531827, 12516406, -21574435, -12476749},
+            {236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519,
+             7256740, 8791136, 15069930},
+        },
+        {
+            {1276410, -9371918, 22949635, -16322807, -23493039, -5702186,
+             14711875, 4874229, -30663140, -2331391},
+            {5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175,
+             -7912378, -33069337, 9234253},
+            {20590503, -9018988, 31529744, -7352666, -2706834, 10650548,
+             31559055, -11609587, 18979186, 13396066},
+        },
+        {
+            {24474287, 4968103, 22267082, 4407354, 24063882, -8325180,
+             -18816887, 13594782, 33514650, 7021958},
+            {-11566906, -6565505, -21365085, 15928892, -26158305, 4315421,
+             -25948728, -3916677, -21480480, 12868082},
+            {-28635013, 13504661, 19988037, -2132761, 21078225, 6443208,
+             -21446107, 2244500, -12455797, -8089383},
+        },
+        {
+            {-30595528, 13793479, -5852820, 319136, -25723172, -6263899,
+             33086546, 8957937, -15233648, 5540521},
+            {-11630176, -11503902, -8119500, -7643073, 2620056, 1022908,
+             -23710744, -1568984, -16128528, -14962807},
+            {23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819,
+             892185, -11513277, -15205948},
+        },
+        {
+            {9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819,
+             4763127, -19179614, 5867134},
+            {-32765025, 1927590, 31726409, -4753295, 23962434, -16019500,
+             27846559, 5931263, -29749703, -16108455},
+            {27461885, -2977536, 22380810, 1815854, -23033753, -3031938,
+             7283490, -15148073, -19526700, 7734629},
+        },
+    },
+    {
+        {
+            {-8010264, -9590817, -11120403, 6196038, 29344158, -13430885,
+             7585295, -3176626, 18549497, 15302069},
+            {-32658337, -6171222, -7672793, -11051681, 6258878, 13504381,
+             10458790, -6418461, -8872242, 8424746},
+            {24687205, 8613276, -30667046, -3233545, 1863892, -1830544,
+             19206234, 7134917, -11284482, -828919},
+        },
+        {
+            {11334899, -9218022, 8025293, 12707519, 17523892, -10476071,
+             10243738, -14685461, -5066034, 16498837},
+            {8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925,
+             -14124238, 6536641, 10543906},
+            {-28946384, 15479763, -17466835, 568876, -1497683, 11223454,
+             -2669190, -16625574, -27235709, 8876771},
+        },
+        {
+            {-25742899, -12566864, -15649966, -846607, -33026686, -796288,
+             -33481822, 15824474, -604426, -9039817},
+            {10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697,
+             -4890037, 1657394, 3084098},
+            {10477963, -7470260, 12119566, -13250805, 29016247, -5365589,
+             31280319, 14396151, -30233575, 15272409},
+        },
+        {
+            {-12288309, 3169463, 28813183, 16658753, 25116432, -5630466,
+             -25173957, -12636138, -25014757, 1950504},
+            {-26180358, 9489187, 11053416, -14746161, -31053720, 5825630,
+             -8384306, -8767532, 15341279, 8373727},
+            {28685821, 7759505, -14378516, -12002860, -31971820, 4079242,
+             298136, -10232602, -2878207, 15190420},
+        },
+        {
+            {-32932876, 13806336, -14337485, -15794431, -24004620, 10940928,
+             8669718, 2742393, -26033313, -6875003},
+            {-1580388, -11729417, -25979658, -11445023, -17411874, -10912854,
+             9291594, -16247779, -12154742, 6048605},
+            {-30305315, 14843444, 1539301, 11864366, 20201677, 1900163,
+             13934231, 5128323, 11213262, 9168384},
+        },
+        {
+            {-26280513, 11007847, 19408960, -940758, -18592965, -4328580,
+             -5088060, -11105150, 20470157, -16398701},
+            {-23136053, 9282192, 14855179, -15390078, -7362815, -14408560,
+             -22783952, 14461608, 14042978, 5230683},
+            {29969567, -2741594, -16711867, -8552442, 9175486, -2468974,
+             21556951, 3506042, -5933891, -12449708},
+        },
+        {
+            {-3144746, 8744661, 19704003, 4581278, -20430686, 6830683,
+             -21284170, 8971513, -28539189, 15326563},
+            {-19464629, 10110288, -17262528, -3503892, -23500387, 1355669,
+             -15523050, 15300988, -20514118, 9168260},
+            {-5353335, 4488613, -23803248, 16314347, 7780487, -15638939,
+             -28948358, 9601605, 33087103, -9011387},
+        },
+        {
+            {-19443170, -15512900, -20797467, -12445323, -29824447, 10229461,
+             -27444329, -15000531, -5996870, 15664672},
+            {23294591, -16632613, -22650781, -8470978, 27844204, 11461195,
+             13099750, -2460356, 18151676, 13417686},
+            {-24722913, -4176517, -31150679, 5988919, -26858785, 6685065,
+             1661597, -12551441, 15271676, -15452665},
+        },
+    },
+    {
+        {
+            {11433042, -13228665, 8239631, -5279517, -1985436, -725718,
+             -18698764, 2167544, -6921301, -13440182},
+            {-31436171, 15575146, 30436815, 12192228, -22463353, 9395379,
+             -9917708, -8638997, 12215110, 12028277},
+            {14098400, 6555944, 23007258, 5757252, -15427832, -12950502,
+             30123440, 4617780, -16900089, -655628},
+        },
+        {
+            {-4026201, -15240835, 11893168, 13718664, -14809462, 1847385,
+             -15819999, 10154009, 23973261, -12684474},
+            {-26531820, -3695990, -1908898, 2534301, -31870557, -16550355,
+             18341390, -11419951, 32013174, -10103539},
+            {-25479301, 10876443, -11771086, -14625140, -12369567, 1838104,
+             21911214, 6354752, 4425632, -837822},
+        },
+        {
+            {-10433389, -14612966, 22229858, -3091047, -13191166, 776729,
+             -17415375, -12020462, 4725005, 14044970},
+            {19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390,
+             -1411784, -19522291, -16109756},
+            {-24864089, 12986008, -10898878, -5558584, -11312371, -148526,
+             19541418, 8180106, 9282262, 10282508},
+        },
+        {
+            {-26205082, 4428547, -8661196, -13194263, 4098402, -14165257,
+             15522535, 8372215, 5542595, -10702683},
+            {-10562541, 14895633, 26814552, -16673850, -17480754, -2489360,
+             -2781891, 6993761, -18093885, 10114655},
+            {-20107055, -929418, 31422704, 10427861, -7110749, 6150669,
+             -29091755, -11529146, 25953725, -106158},
+        },
+        {
+            {-4234397, -8039292, -9119125, 3046000, 2101609, -12607294,
+             19390020, 6094296, -3315279, 12831125},
+            {-15998678, 7578152, 5310217, 14408357, -33548620, -224739,
+             31575954, 6326196, 7381791, -2421839},
+            {-20902779, 3296811, 24736065, -16328389, 18374254, 7318640,
+             6295303, 8082724, -15362489, 12339664},
+        },
+        {
+            {27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414,
+             15768922, 25091167, 14856294},
+            {-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300,
+             -12695493, -22182473, -9012899},
+            {-11423429, -5421590, 11632845, 3405020, 30536730, -11674039,
+             -27260765, 13866390, 30146206, 9142070},
+        },
+        {
+            {3924129, -15307516, -13817122, -10054960, 12291820, -668366,
+             -27702774, 9326384, -8237858, 4171294},
+            {-15921940, 16037937, 6713787, 16606682, -21612135, 2790944,
+             26396185, 3731949, 345228, -5462949},
+            {-21327538, 13448259, 25284571, 1143661, 20614966, -8849387,
+             2031539, -12391231, -16253183, -13582083},
+        },
+        {
+            {31016211, -16722429, 26371392, -14451233, -5027349, 14854137,
+             17477601, 3842657, 28012650, -16405420},
+            {-5075835, 9368966, -8562079, -4600902, -15249953, 6970560,
+             -9189873, 16292057, -8867157, 3507940},
+            {29439664, 3537914, 23333589, 6997794, -17555561, -11018068,
+             -15209202, -15051267, -9164929, 6580396},
+        },
+    },
+    {
+        {
+            {-12185861, -7679788, 16438269, 10826160, -8696817, -6235611,
+             17860444, -9273846, -2095802, 9304567},
+            {20714564, -4336911, 29088195, 7406487, 11426967, -5095705,
+             14792667, -14608617, 5289421, -477127},
+            {-16665533, -10650790, -6160345, -13305760, 9192020, -1802462,
+             17271490, 12349094, 26939669, -3752294},
+        },
+        {
+            {-12889898, 9373458, 31595848, 16374215, 21471720, 13221525,
+             -27283495, -12348559, -3698806, 117887},
+            {22263325, -6560050, 3984570, -11174646, -15114008, -566785,
+             28311253, 5358056, -23319780, 541964},
+            {16259219, 3261970, 2309254, -15534474, -16885711, -4581916,
+             24134070, -16705829, -13337066, -13552195},
+        },
+        {
+            {9378160, -13140186, -22845982, -12745264, 28198281, -7244098,
+             -2399684, -717351, 690426, 14876244},
+            {24977353, -314384, -8223969, -13465086, 28432343, -1176353,
+             -13068804, -12297348, -22380984, 6618999},
+            {-1538174, 11685646, 12944378, 13682314, -24389511, -14413193,
+             8044829, -13817328, 32239829, -5652762},
+        },
+        {
+            {-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647,
+             -10350059, 32779359, 5095274},
+            {-33008130, -5214506, -32264887, -3685216, 9460461, -9327423,
+             -24601656, 14506724, 21639561, -2630236},
+            {-16400943, -13112215, 25239338, 15531969, 3987758, -4499318,
+             -1289502, -6863535, 17874574, 558605},
+        },
+        {
+            {-13600129, 10240081, 9171883, 16131053, -20869254, 9599700,
+             33499487, 5080151, 2085892, 5119761},
+            {-22205145, -2519528, -16381601, 414691, -25019550, 2170430,
+             30634760, -8363614, -31999993, -5759884},
+            {-6845704, 15791202, 8550074, -1312654, 29928809, -12092256,
+             27534430, -7192145, -22351378, 12961482},
+        },
+        {
+            {-24492060, -9570771, 10368194, 11582341, -23397293, -2245287,
+             16533930, 8206996, -30194652, -5159638},
+            {-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630,
+             7031275, 7589640, 8945490},
+            {-32152748, 8917967, 6661220, -11677616, -1192060, -15793393,
+             7251489, -11182180, 24099109, -14456170},
+        },
+        {
+            {5019558, -7907470, 4244127, -14714356, -26933272, 6453165,
+             -19118182, -13289025, -6231896, -10280736},
+            {10853594, 10721687, 26480089, 5861829, -22995819, 1972175,
+             -1866647, -10557898, -3363451, -6441124},
+            {-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661,
+             -2008168, -13866408, 7421392},
+        },
+        {
+            {8139927, -6546497, 32257646, -5890546, 30375719, 1886181,
+             -21175108, 15441252, 28826358, -4123029},
+            {6267086, 9695052, 7709135, -16603597, -32869068, -1886135,
+             14795160, -7840124, 13746021, -1742048},
+            {28584902, 7787108, -6732942, -15050729, 22846041, -7571236,
+             -3181936, -363524, 4771362, -8419958},
+        },
+    },
+    {
+        {
+            {24949256, 6376279, -27466481, -8174608, -18646154, -9930606,
+             33543569, -12141695, 3569627, 11342593},
+            {26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886,
+             4608608, 7325975, -14801071},
+            {-11618399, -14554430, -24321212, 7655128, -1369274, 5214312,
+             -27400540, 10258390, -17646694, -8186692},
+        },
+        {
+            {11431204, 15823007, 26570245, 14329124, 18029990, 4796082,
+             -31446179, 15580664, 9280358, -3973687},
+            {-160783, -10326257, -22855316, -4304997, -20861367, -13621002,
+             -32810901, -11181622, -15545091, 4387441},
+            {-20799378, 12194512, 3937617, -5805892, -27154820, 9340370,
+             -24513992, 8548137, 20617071, -7482001},
+        },
+        {
+            {-938825, -3930586, -8714311, 16124718, 24603125, -6225393,
+             -13775352, -11875822, 24345683, 10325460},
+            {-19855277, -1568885, -22202708, 8714034, 14007766, 6928528,
+             16318175, -1010689, 4766743, 3552007},
+            {-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514,
+             14481909, 10988822, -3994762},
+        },
+        {
+            {15564307, -14311570, 3101243, 5684148, 30446780, -8051356,
+             12677127, -6505343, -8295852, 13296005},
+            {-9442290, 6624296, -30298964, -11913677, -4670981, -2057379,
+             31521204, 9614054, -30000824, 12074674},
+            {4771191, -135239, 14290749, -13089852, 27992298, 14998318,
+             -1413936, -1556716, 29832613, -16391035},
+        },
+        {
+            {7064884, -7541174, -19161962, -5067537, -18891269, -2912736,
+             25825242, 5293297, -27122660, 13101590},
+            {-2298563, 2439670, -7466610, 1719965, -27267541, -16328445,
+             32512469, -5317593, -30356070, -4190957},
+            {-30006540, 10162316, -33180176, 3981723, -16482138, -13070044,
+             14413974, 9515896, 19568978, 9628812},
+        },
+        {
+            {33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894,
+             -6106839, -6291786, 3437740},
+            {-18978877, 3884493, 19469877, 12726490, 15913552, 13614290,
+             -22961733, 70104, 7463304, 4176122},
+            {-27124001, 10659917, 11482427, -16070381, 12771467, -6635117,
+             -32719404, -5322751, 24216882, 5944158},
+        },
+        {
+            {8894125, 7450974, -2664149, -9765752, -28080517, -12389115,
+             19345746, 14680796, 11632993, 5847885},
+            {26942781, -2315317, 9129564, -4906607, 26024105, 11769399,
+             -11518837, 6367194, -9727230, 4782140},
+            {19916461, -4828410, -22910704, -11414391, 25606324, -5972441,
+             33253853, 8220911, 6358847, -1873857},
+        },
+        {
+            {801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388,
+             -4480480, -13538503, 1387155},
+            {19646058, 5720633, -11416706, 12814209, 11607948, 12749789,
+             14147075, 15156355, -21866831, 11835260},
+            {19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523,
+             15467869, -26560550, 5052483},
+        },
+    },
+    {
+        {
+            {-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123,
+             -12618185, 12228557, -7003677},
+            {32944382, 14922211, -22844894, 5188528, 21913450, -8719943,
+             4001465, 13238564, -6114803, 8653815},
+            {22865569, -4652735, 27603668, -12545395, 14348958, 8234005,
+             24808405, 5719875, 28483275, 2841751},
+        },
+        {
+            {-16420968, -1113305, -327719, -12107856, 21886282, -15552774,
+             -1887966, -315658, 19932058, -12739203},
+            {-11656086, 10087521, -8864888, -5536143, -19278573, -3055912,
+             3999228, 13239134, -4777469, -13910208},
+            {1382174, -11694719, 17266790, 9194690, -13324356, 9720081,
+             20403944, 11284705, -14013818, 3093230},
+        },
+        {
+            {16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424,
+             16271225, -24049421, -6691850},
+            {-21911077, -5927941, -4611316, -5560156, -31744103, -10785293,
+             24123614, 15193618, -21652117, -16739389},
+            {-9935934, -4289447, -25279823, 4372842, 2087473, 10399484,
+             31870908, 14690798, 17361620, 11864968},
+        },
+        {
+            {-11307610, 6210372, 13206574, 5806320, -29017692, -13967200,
+             -12331205, -7486601, -25578460, -16240689},
+            {14668462, -12270235, 26039039, 15305210, 25515617, 4542480,
+             10453892, 6577524, 9145645, -6443880},
+            {5974874, 3053895, -9433049, -10385191, -31865124, 3225009,
+             -7972642, 3936128, -5652273, -3050304},
+        },
+        {
+            {30625386, -4729400, -25555961, -12792866, -20484575, 7695099,
+             17097188, -16303496, -27999779, 1803632},
+            {-3553091, 9865099, -5228566, 4272701, -5673832, -16689700,
+             14911344, 12196514, -21405489, 7047412},
+            {20093277, 9920966, -11138194, -5343857, 13161587, 12044805,
+             -32856851, 4124601, -32343828, -10257566},
+        },
+        {
+            {-20788824, 14084654, -13531713, 7842147, 19119038, -13822605,
+             4752377, -8714640, -21679658, 2288038},
+            {-26819236, -3283715, 29965059, 3039786, -14473765, 2540457,
+             29457502, 14625692, -24819617, 12570232},
+            {-1063558, -11551823, 16920318, 12494842, 1278292, -5869109,
+             -21159943, -3498680, -11974704, 4724943},
+        },
+        {
+            {17960970, -11775534, -4140968, -9702530, -8876562, -1410617,
+             -12907383, -8659932, -29576300, 1903856},
+            {23134274, -14279132, -10681997, -1611936, 20684485, 15770816,
+             -12989750, 3190296, 26955097, 14109738},
+            {15308788, 5320727, -30113809, -14318877, 22902008, 7767164,
+             29425325, -11277562, 31960942, 11934971},
+        },
+        {
+            {-27395711, 8435796, 4109644, 12222639, -24627868, 14818669,
+             20638173, 4875028, 10491392, 1379718},
+            {-13159415, 9197841, 3875503, -8936108, -1383712, -5879801,
+             33518459, 16176658, 21432314, 12180697},
+            {-11787308, 11500838, 13787581, -13832590, -22430679, 10140205,
+             1465425, 12689540, -10301319, -13872883},
+        },
+    },
+    {
+        {
+            {5414091, -15386041, -21007664, 9643570, 12834970, 1186149,
+             -2622916, -1342231, 26128231, 6032912},
+            {-26337395, -13766162, 32496025, -13653919, 17847801, -12669156,
+             3604025, 8316894, -25875034, -10437358},
+            {3296484, 6223048, 24680646, -12246460, -23052020, 5903205,
+             -8862297, -4639164, 12376617, 3188849},
+        },
+        {
+            {29190488, -14659046, 27549113, -1183516, 3520066, -10697301,
+             32049515, -7309113, -16109234, -9852307},
+            {-14744486, -9309156, 735818, -598978, -20407687, -5057904,
+             25246078, -15795669, 18640741, -960977},
+            {-6928835, -16430795, 10361374, 5642961, 4910474, 12345252,
+             -31638386, -494430, 10530747, 1053335},
+        },
+        {
+            {-29265967, -14186805, -13538216, -12117373, -19457059, -10655384,
+             -31462369, -2948985, 24018831, 15026644},
+            {-22592535, -3145277, -2289276, 5953843, -13440189, 9425631,
+             25310643, 13003497, -2314791, -15145616},
+            {-27419985, -603321, -8043984, -1669117, -26092265, 13987819,
+             -27297622, 187899, -23166419, -2531735},
+        },
+        {
+            {-21744398, -13810475, 1844840, 5021428, -10434399, -15911473,
+             9716667, 16266922, -5070217, 726099},
+            {29370922, -6053998, 7334071, -15342259, 9385287, 2247707,
+             -13661962, -4839461, 30007388, -15823341},
+            {-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109,
+             730663, 9835848, 4555336},
+        },
+        {
+            {-23376435, 1410446, -22253753, -12899614, 30867635, 15826977,
+             17693930, 544696, -11985298, 12422646},
+            {31117226, -12215734, -13502838, 6561947, -9876867, -12757670,
+             -5118685, -4096706, 29120153, 13924425},
+            {-17400879, -14233209, 19675799, -2734756, -11006962, -5858820,
+             -9383939, -11317700, 7240931, -237388},
+        },
+        {
+            {-31361739, -11346780, -15007447, -5856218, -22453340, -12152771,
+             1222336, 4389483, 3293637, -15551743},
+            {-16684801, -14444245, 11038544, 11054958, -13801175, -3338533,
+             -24319580, 7733547, 12796905, -6335822},
+            {-8759414, -10817836, -25418864, 10783769, -30615557, -9746811,
+             -28253339, 3647836, 3222231, -11160462},
+        },
+        {
+            {18606113, 1693100, -25448386, -15170272, 4112353, 10045021,
+             23603893, -2048234, -7550776, 2484985},
+            {9255317, -3131197, -12156162, -1004256, 13098013, -9214866,
+             16377220, -2102812, -19802075, -3034702},
+            {-22729289, 7496160, -5742199, 11329249, 19991973, -3347502,
+             -31718148, 9936966, -30097688, -10618797},
+        },
+        {
+            {21878590, -5001297, 4338336, 13643897, -3036865, 13160960,
+             19708896, 5415497, -7360503, -4109293},
+            {27736861, 10103576, 12500508, 8502413, -3413016, -9633558,
+             10436918, -1550276, -23659143, -8132100},
+            {19492550, -12104365, -29681976, -852630, -3208171, 12403437,
+             30066266, 8367329, 13243957, 8709688},
+        },
+    },
+    {
+        {
+            {12015105, 2801261, 28198131, 10151021, 24818120, -4743133,
+             -11194191, -5645734, 5150968, 7274186},
+            {2831366, -12492146, 1478975, 6122054, 23825128, -12733586,
+             31097299, 6083058, 31021603, -9793610},
+            {-2529932, -2229646, 445613, 10720828, -13849527, -11505937,
+             -23507731, 16354465, 15067285, -14147707},
+        },
+        {
+            {7840942, 14037873, -33364863, 15934016, -728213, -3642706,
+             21403988, 1057586, -19379462, -12403220},
+            {915865, -16469274, 15608285, -8789130, -24357026, 6060030,
+             -17371319, 8410997, -7220461, 16527025},
+            {32922597, -556987, 20336074, -16184568, 10903705, -5384487,
+             16957574, 52992, 23834301, 6588044},
+        },
+        {
+            {32752030, 11232950, 3381995, -8714866, 22652988, -10744103,
+             17159699, 16689107, -20314580, -1305992},
+            {-4689649, 9166776, -25710296, -10847306, 11576752, 12733943,
+             7924251, -2752281, 1976123, -7249027},
+            {21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041,
+             -3371252, 12331345, -8237197},
+        },
+        {
+            {8651614, -4477032, -16085636, -4996994, 13002507, 2950805,
+             29054427, -5106970, 10008136, -4667901},
+            {31486080, 15114593, -14261250, 12951354, 14369431, -7387845,
+             16347321, -13662089, 8684155, -10532952},
+            {19443825, 11385320, 24468943, -9659068, -23919258, 2187569,
+             -26263207, -6086921, 31316348, 14219878},
+        },
+        {
+            {-28594490, 1193785, 32245219, 11392485, 31092169, 15722801,
+             27146014, 6992409, 29126555, 9207390},
+            {32382935, 1110093, 18477781, 11028262, -27411763, -7548111,
+             -4980517, 10843782, -7957600, -14435730},
+            {2814918, 7836403, 27519878, -7868156, -20894015, -11553689,
+             -21494559, 8550130, 28346258, 1994730},
+        },
+        {
+            {-19578299, 8085545, -14000519, -3948622, 2785838, -16231307,
+             -19516951, 7174894, 22628102, 8115180},
+            {-30405132, 955511, -11133838, -15078069, -32447087, -13278079,
+             -25651578, 3317160, -9943017, 930272},
+            {-15303681, -6833769, 28856490, 1357446, 23421993, 1057177,
+             24091212, -1388970, -22765376, -10650715},
+        },
+        {
+            {-22751231, -5303997, -12907607, -12768866, -15811511, -7797053,
+             -14839018, -16554220, -1867018, 8398970},
+            {-31969310, 2106403, -4736360, 1362501, 12813763, 16200670,
+             22981545, -6291273, 18009408, -15772772},
+            {-17220923, -9545221, -27784654, 14166835, 29815394, 7444469,
+             29551787, -3727419, 19288549, 1325865},
+        },
+        {
+            {15100157, -15835752, -23923978, -1005098, -26450192, 15509408,
+             12376730, -3479146, 33166107, -8042750},
+            {20909231, 13023121, -9209752, 16251778, -5778415, -8094914,
+             12412151, 10018715, 2213263, -13878373},
+            {32529814, -11074689, 30361439, -16689753, -9135940, 1513226,
+             22922121, 6382134, -5766928, 8371348},
+        },
+    },
+    {
+        {
+            {9923462, 11271500, 12616794, 3544722, -29998368, -1721626,
+             12891687, -8193132, -26442943, 10486144},
+            {-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726,
+             2610596, -23921530, -11455195},
+            {5408411, -1136691, -4969122, 10561668, 24145918, 14240566,
+             31319731, -4235541, 19985175, -3436086},
+        },
+        {
+            {-13994457, 16616821, 14549246, 3341099, 32155958, 13648976,
+             -17577068, 8849297, 65030, 8370684},
+            {-8320926, -12049626, 31204563, 5839400, -20627288, -1057277,
+             -19442942, 6922164, 12743482, -9800518},
+            {-2361371, 12678785, 28815050, 4759974, -23893047, 4884717,
+             23783145, 11038569, 18800704, 255233},
+        },
+        {
+            {-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847,
+             9066957, 19258688, -14753793},
+            {-2936654, -10827535, -10432089, 14516793, -3640786, 4372541,
+             -31934921, 2209390, -1524053, 2055794},
+            {580882, 16705327, 5468415, -2683018, -30926419, -14696000,
+             -7203346, -8994389, -30021019, 7394435},
+        },
+        {
+            {23838809, 1822728, -15738443, 15242727, 8318092, -3733104,
+             -21672180, -3492205, -4821741, 14799921},
+            {13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804,
+             13496856, -9056018, 7402518},
+            {2286874, -4435931, -20042458, -2008336, -13696227, 5038122,
+             11006906, -15760352, 8205061, 1607563},
+        },
+        {
+            {14414086, -8002132, 3331830, -3208217, 22249151, -5594188,
+             18364661, -2906958, 30019587, -9029278},
+            {-27688051, 1585953, -10775053, 931069, -29120221, -11002319,
+             -14410829, 12029093, 9944378, 8024},
+            {4368715, -3709630, 29874200, -15022983, -20230386, -11410704,
+             -16114594, -999085, -8142388, 5640030},
+        },
+        {
+            {10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887,
+             -16694564, 15219798, -14327783},
+            {27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605,
+             -1173195, -18342183, 9742717},
+            {6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614,
+             7406442, 12420155, 1994844},
+        },
+        {
+            {14012521, -5024720, -18384453, -9578469, -26485342, -3936439,
+             -13033478, -10909803, 24319929, -6446333},
+            {16412690, -4507367, 10772641, 15929391, -17068788, -4658621,
+             10555945, -10484049, -30102368, -4739048},
+            {22397382, -7767684, -9293161, -12792868, 17166287, -9755136,
+             -27333065, 6199366, 21880021, -12250760},
+        },
+        {
+            {-4283307, 5368523, -31117018, 8163389, -30323063, 3209128,
+             16557151, 8890729, 8840445, 4957760},
+            {-15447727, 709327, -6919446, -10870178, -29777922, 6522332,
+             -21720181, 12130072, -14796503, 5005757},
+            {-2114751, -14308128, 23019042, 15765735, -25269683, 6002752,
+             10183197, -13239326, -16395286, -2176112},
+        },
+    },
+    {
+        {
+            {-19025756, 1632005, 13466291, -7995100, -23640451, 16573537,
+             -32013908, -3057104, 22208662, 2000468},
+            {3065073, -1412761, -25598674, -361432, -17683065, -5703415,
+             -8164212, 11248527, -3691214, -7414184},
+            {10379208, -6045554, 8877319, 1473647, -29291284, -12507580,
+             16690915, 2553332, -3132688, 16400289},
+        },
+        {
+            {15716668, 1254266, -18472690, 7446274, -8448918, 6344164,
+             -22097271, -7285580, 26894937, 9132066},
+            {24158887, 12938817, 11085297, -8177598, -28063478, -4457083,
+             -30576463, 64452, -6817084, -2692882},
+            {13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710,
+             -3418511, -4688006, 2364226},
+        },
+        {
+            {16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024,
+             -11697457, 15445875, -7798101},
+            {29004207, -7867081, 28661402, -640412, -12794003, -7943086,
+             31863255, -4135540, -278050, -15759279},
+            {-6122061, -14866665, -28614905, 14569919, -10857999, -3591829,
+             10343412, -6976290, -29828287, -10815811},
+        },
+        {
+            {27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636,
+             15372179, 17293797, 960709},
+            {20263915, 11434237, -5765435, 11236810, 13505955, -10857102,
+             -16111345, 6493122, -19384511, 7639714},
+            {-2830798, -14839232, 25403038, -8215196, -8317012, -16173699,
+             18006287, -16043750, 29994677, -15808121},
+        },
+        {
+            {9769828, 5202651, -24157398, -13631392, -28051003, -11561624,
+             -24613141, -13860782, -31184575, 709464},
+            {12286395, 13076066, -21775189, -1176622, -25003198, 4057652,
+             -32018128, -8890874, 16102007, 13205847},
+            {13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170,
+             8525972, 10151379, 10394400},
+        },
+        {
+            {4024660, -16137551, 22436262, 12276534, -9099015, -2686099,
+             19698229, 11743039, -33302334, 8934414},
+            {-15879800, -4525240, -8580747, -2934061, 14634845, -698278,
+             -9449077, 3137094, -11536886, 11721158},
+            {17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229,
+             8835153, -9205489, -1280045},
+        },
+        {
+            {-461409, -7830014, 20614118, 16688288, -7514766, -4807119,
+             22300304, 505429, 6108462, -6183415},
+            {-5070281, 12367917, -30663534, 3234473, 32617080, -8422642,
+             29880583, -13483331, -26898490, -7867459},
+            {-31975283, 5726539, 26934134, 10237677, -3173717, -605053,
+             24199304, 3795095, 7592688, -14992079},
+        },
+        {
+            {21594432, -14964228, 17466408, -4077222, 32537084, 2739898,
+             6407723, 12018833, -28256052, 4298412},
+            {-20650503, -11961496, -27236275, 570498, 3767144, -1717540,
+             13891942, -1569194, 13717174, 10805743},
+            {-14676630, -15644296, 15287174, 11927123, 24177847, -8175568,
+             -796431, 14860609, -26938930, -5863836},
+        },
+    },
+    {
+        {
+            {12962541, 5311799, -10060768, 11658280, 18855286, -7954201,
+             13286263, -12808704, -4381056, 9882022},
+            {18512079, 11319350, -20123124, 15090309, 18818594, 5271736,
+             -22727904, 3666879, -23967430, -3299429},
+            {-6789020, -3146043, 16192429, 13241070, 15898607, -14206114,
+             -10084880, -6661110, -2403099, 5276065},
+        },
+        {
+            {30169808, -5317648, 26306206, -11750859, 27814964, 7069267,
+             7152851, 3684982, 1449224, 13082861},
+            {10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382,
+             15056736, -21016438, -8202000},
+            {-33150110, 3261608, 22745853, 7948688, 19370557, -15177665,
+             -26171976, 6482814, -10300080, -11060101},
+        },
+        {
+            {32869458, -5408545, 25609743, 15678670, -10687769, -15471071,
+             26112421, 2521008, -22664288, 6904815},
+            {29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737,
+             3841096, -29003639, -6657642},
+            {10340844, -6630377, -18656632, -2278430, 12621151, -13339055,
+             30878497, -11824370, -25584551, 5181966},
+        },
+        {
+            {25940115, -12658025, 17324188, -10307374, -8671468, 15029094,
+             24396252, -16450922, -2322852, -12388574},
+            {-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390,
+             12641087, 20603771, -6561742},
+            {-18882287, -11673380, 24849422, 11501709, 13161720, -4768874,
+             1925523, 11914390, 4662781, 7820689},
+        },
+        {
+            {12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456,
+             12172924, 16136752, 15264020},
+            {-10349955, -14680563, -8211979, 2330220, -17662549, -14545780,
+             10658213, 6671822, 19012087, 3772772},
+            {3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732,
+             -15762884, 20527771, 12988982},
+        },
+        {
+            {-14822485, -5797269, -3707987, 12689773, -898983, -10914866,
+             -24183046, -10564943, 3299665, -12424953},
+            {-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197,
+             6461331, -25583147, 8991218},
+            {-17226263, 1816362, -1673288, -6086439, 31783888, -8175991,
+             -32948145, 7417950, -30242287, 1507265},
+        },
+        {
+            {29692663, 6829891, -10498800, 4334896, 20945975, -11906496,
+             -28887608, 8209391, 14606362, -10647073},
+            {-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695,
+             9761487, 4170404, -2085325},
+            {-11587470, 14855945, -4127778, -1531857, -26649089, 15084046,
+             22186522, 16002000, -14276837, -8400798},
+        },
+        {
+            {-4811456, 13761029, -31703877, -2483919, -3312471, 7869047,
+             -7113572, -9620092, 13240845, 10965870},
+            {-7742563, -8256762, -14768334, -13656260, -23232383, 12387166,
+             4498947, 14147411, 29514390, 4302863},
+            {-13413405, -12407859, 20757302, -13801832, 14785143, 8976368,
+             -5061276, -2144373, 17846988, -13971927},
+        },
+    },
+    {
+        {
+            {-2244452, -754728, -4597030, -1066309, -6247172, 1455299,
+             -21647728, -9214789, -5222701, 12650267},
+            {-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813,
+             13770293, -19134326, 10958663},
+            {22470984, 12369526, 23446014, -5441109, -21520802, -9698723,
+             -11772496, -11574455, -25083830, 4271862},
+        },
+        {
+            {-25169565, -10053642, -19909332, 15361595, -5984358, 2159192,
+             75375, -4278529, -32526221, 8469673},
+            {15854970, 4148314, -8893890, 7259002, 11666551, 13824734,
+             -30531198, 2697372, 24154791, -9460943},
+            {15446137, -15806644, 29759747, 14019369, 30811221, -9610191,
+             -31582008, 12840104, 24913809, 9815020},
+        },
+        {
+            {-4709286, -5614269, -31841498, -12288893, -14443537, 10799414,
+             -9103676, 13438769, 18735128, 9466238},
+            {11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821,
+             -10896103, -22728655, 16199064},
+            {14576810, 379472, -26786533, -8317236, -29426508, -10812974,
+             -102766, 1876699, 30801119, 2164795},
+        },
+        {
+            {15995086, 3199873, 13672555, 13712240, -19378835, -4647646,
+             -13081610, -15496269, -13492807, 1268052},
+            {-10290614, -3659039, -3286592, 10948818, 23037027, 3794475,
+             -3470338, -12600221, -17055369, 3565904},
+            {29210088, -9419337, -5919792, -4952785, 10834811, -13327726,
+             -16512102, -10820713, -27162222, -14030531},
+        },
+        {
+            {-13161890, 15508588, 16663704, -8156150, -28349942, 9019123,
+             -29183421, -3769423, 2244111, -14001979},
+            {-5152875, -3800936, -9306475, -6071583, 16243069, 14684434,
+             -25673088, -16180800, 13491506, 4641841},
+            {10813417, 643330, -19188515, -728916, 30292062, -16600078,
+             27548447, -7721242, 14476989, -12767431},
+        },
+        {
+            {10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937,
+             -1644259, -27912810, 12651324},
+            {-31185513, -813383, 22271204, 11835308, 10201545, 15351028,
+             17099662, 3988035, 21721536, -3148940},
+            {10202177, -6545839, -31373232, -9574638, -32150642, -8119683,
+             -12906320, 3852694, 13216206, 14842320},
+        },
+        {
+            {-15815640, -10601066, -6538952, -7258995, -6984659, -6581778,
+             -31500847, 13765824, -27434397, 9900184},
+            {14465505, -13833331, -32133984, -14738873, -27443187, 12990492,
+             33046193, 15796406, -7051866, -8040114},
+            {30924417, -8279620, 6359016, -12816335, 16508377, 9071735,
+             -25488601, 15413635, 9524356, -7018878},
+        },
+        {
+            {12274201, -13175547, 32627641, -1785326, 6736625, 13267305,
+             5237659, -5109483, 15663516, 4035784},
+            {-2951309, 8903985, 17349946, 601635, -16432815, -4612556,
+             -13732739, -15889334, -22258478, 4659091},
+            {-16916263, -4952973, -30393711, -15158821, 20774812, 15897498,
+             5736189, 15026997, -2178256, -13455585},
+        },
+    },
+    {
+        {
+            {-8858980, -2219056, 28571666, -10155518, -474467, -10105698,
+             -3801496, 278095, 23440562, -290208},
+            {10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275,
+             11551483, -16571960, -7442864},
+            {17932739, -12437276, -24039557, 10749060, 11316803, 7535897,
+             22503767, 5561594, -3646624, 3898661},
+        },
+        {
+            {7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531,
+             7152530, 21831162, 1245233},
+            {26958459, -14658026, 4314586, 8346991, -5677764, 11960072,
+             -32589295, -620035, -30402091, -16716212},
+            {-12165896, 9166947, 33491384, 13673479, 29787085, 13096535,
+             6280834, 14587357, -22338025, 13987525},
+        },
+        {
+            {-24349909, 7778775, 21116000, 15572597, -4833266, -5357778,
+             -4300898, -5124639, -7469781, -2858068},
+            {9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781,
+             6439245, -14581012, 4091397},
+            {-8426427, 1470727, -28109679, -1596990, 3978627, -5123623,
+             -19622683, 12092163, 29077877, -14741988},
+        },
+        {
+            {5269168, -6859726, -13230211, -8020715, 25932563, 1763552,
+             -5606110, -5505881, -20017847, 2357889},
+            {32264008, -15407652, -5387735, -1160093, -2091322, -3946900,
+             23104804, -12869908, 5727338, 189038},
+            {14609123, -8954470, -6000566, -16622781, -14577387, -7743898,
+             -26745169, 10942115, -25888931, -14884697},
+        },
+        {
+            {20513500, 5557931, -15604613, 7829531, 26413943, -2019404,
+             -21378968, 7471781, 13913677, -5137875},
+            {-25574376, 11967826, 29233242, 12948236, -6754465, 4713227,
+             -8940970, 14059180, 12878652, 8511905},
+            {-25656801, 3393631, -2955415, -7075526, -2250709, 9366908,
+             -30223418, 6812974, 5568676, -3127656},
+        },
+        {
+            {11630004, 12144454, 2116339, 13606037, 27378885, 15676917,
+             -17408753, -13504373, -14395196, 8070818},
+            {27117696, -10007378, -31282771, -5570088, 1127282, 12772488,
+             -29845906, 10483306, -11552749, -1028714},
+            {10637467, -5688064, 5674781, 1072708, -26343588, -6982302,
+             -1683975, 9177853, -27493162, 15431203},
+        },
+        {
+            {20525145, 10892566, -12742472, 12779443, -29493034, 16150075,
+             -28240519, 14943142, -15056790, -7935931},
+            {-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767,
+             -3239766, -3356550, 9594024},
+            {-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683,
+             -6492290, 13352335, -10977084},
+        },
+        {
+            {-1931799, -5407458, 3304649, -12884869, 17015806, -4877091,
+             -29783850, -7752482, -13215537, -319204},
+            {20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742,
+             15077870, -22750759, 14523817},
+            {27406042, -6041657, 27423596, -4497394, 4996214, 10002360,
+             -28842031, -4545494, -30172742, -4805667},
+        },
+    },
+    {
+        {
+            {11374242, 12660715, 17861383, -12540833, 10935568, 1099227,
+             -13886076, -9091740, -27727044, 11358504},
+            {-12730809, 10311867, 1510375, 10778093, -2119455, -9145702,
+             32676003, 11149336, -26123651, 4985768},
+            {-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043,
+             13794114, -19414307, -15621255},
+        },
+        {
+            {6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603,
+             6970005, -1691065, -9004790},
+            {1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622,
+             -5475723, -16796596, -5031438},
+            {-22273315, -13524424, -64685, -4334223, -18605636, -10921968,
+             -20571065, -7007978, -99853, -10237333},
+        },
+        {
+            {17747465, 10039260, 19368299, -4050591, -20630635, -16041286,
+             31992683, -15857976, -29260363, -5511971},
+            {31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999,
+             -3744247, 4882242, -10626905},
+            {29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198,
+             3272828, -5190932, -4162409},
+        },
+        {
+            {12501286, 4044383, -8612957, -13392385, -32430052, 5136599,
+             -19230378, -3529697, 330070, -3659409},
+            {6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522,
+             -8573892, -271295, 12071499},
+            {-8365515, -4042521, 25133448, -4517355, -6211027, 2265927,
+             -32769618, 1936675, -5159697, 3829363},
+        },
+        {
+            {28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550,
+             -6567787, 26333140, 14267664},
+            {-11067219, 11871231, 27385719, -10559544, -4585914, -11189312,
+             10004786, -8709488, -21761224, 8930324},
+            {-21197785, -16396035, 25654216, -1725397, 12282012, 11008919,
+             1541940, 4757911, -26491501, -16408940},
+        },
+        {
+            {13537262, -7759490, -20604840, 10961927, -5922820, -13218065,
+             -13156584, 6217254, -15943699, 13814990},
+            {-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681,
+             9257833, -1956526, -1776914},
+            {-25045300, -10191966, 15366585, 15166509, -13105086, 8423556,
+             -29171540, 12361135, -18685978, 4578290},
+        },
+        {
+            {24579768, 3711570, 1342322, -11180126, -27005135, 14124956,
+             -22544529, 14074919, 21964432, 8235257},
+            {-6528613, -2411497, 9442966, -5925588, 12025640, -1487420,
+             -2981514, -1669206, 13006806, 2355433},
+            {-16304899, -13605259, -6632427, -5142349, 16974359, -10911083,
+             27202044, 1719366, 1141648, -12796236},
+        },
+        {
+            {-12863944, -13219986, -8318266, -11018091, -6810145, -4843894,
+             13475066, -3133972, 32674895, 13715045},
+            {11423335, -5468059, 32344216, 8962751, 24989809, 9241752,
+             -13265253, 16086212, -28740881, -15642093},
+            {-1409668, 12530728, -6368726, 10847387, 19531186, -14132160,
+             -11709148, 7791794, -27245943, 4383347},
+        },
+    },
+    {
+        {
+            {-28970898, 5271447, -1266009, -9736989, -12455236, 16732599,
+             -4862407, -4906449, 27193557, 6245191},
+            {-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898,
+             3260492, 22510453, 8577507},
+            {-12632451, 11257346, -32692994, 13548177, -721004, 10879011,
+             31168030, 13952092, -29571492, -3635906},
+        },
+        {
+            {3877321, -9572739, 32416692, 5405324, -11004407, -13656635,
+             3759769, 11935320, 5611860, 8164018},
+            {-16275802, 14667797, 15906460, 12155291, -22111149, -9039718,
+             32003002, -8832289, 5773085, -8422109},
+            {-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725,
+             12376320, 31632953, 190926},
+        },
+        {
+            {-24593607, -16138885, -8423991, 13378746, 14162407, 6901328,
+             -8288749, 4508564, -25341555, -3627528},
+            {8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941,
+             -14786005, -1672488, 827625},
+            {-32720583, -16289296, -32503547, 7101210, 13354605, 2659080,
+             -1800575, -14108036, -24878478, 1541286},
+        },
+        {
+            {2901347, -1117687, 3880376, -10059388, -17620940, -3612781,
+             -21802117, -3567481, 20456845, -1885033},
+            {27019610, 12299467, -13658288, -1603234, -12861660, -4861471,
+             -19540150, -5016058, 29439641, 15138866},
+            {21536104, -6626420, -32447818, -10690208, -22408077, 5175814,
+             -5420040, -16361163, 7779328, 109896},
+        },
+        {
+            {30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390,
+             12180118, 23177719, -554075},
+            {26572847, 3405927, -31701700, 12890905, -19265668, 5335866,
+             -6493768, 2378492, 4439158, -13279347},
+            {-22716706, 3489070, -9225266, -332753, 18875722, -1140095,
+             14819434, -12731527, -17717757, -5461437},
+        },
+        {
+            {-5056483, 16566551, 15953661, 3767752, -10436499, 15627060,
+             -820954, 2177225, 8550082, -15114165},
+            {-18473302, 16596775, -381660, 15663611, 22860960, 15585581,
+             -27844109, -3582739, -23260460, -8428588},
+            {-32480551, 15707275, -8205912, -5652081, 29464558, 2713815,
+             -22725137, 15860482, -21902570, 1494193},
+        },
+        {
+            {-19562091, -14087393, -25583872, -9299552, 13127842, 759709,
+             21923482, 16529112, 8742704, 12967017},
+            {-28464899, 1553205, 32536856, -10473729, -24691605, -406174,
+             -8914625, -2933896, -29903758, 15553883},
+            {21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572,
+             14513274, 19375923, -12647961},
+        },
+        {
+            {8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818,
+             -6222716, 2862653, 9455043},
+            {29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124,
+             -2990080, 15511449, 4789663},
+            {-20679756, 7004547, 8824831, -9434977, -4045704, -3750736,
+             -5754762, 108893, 23513200, 16652362},
+        },
+    },
+    {
+        {
+            {-33256173, 4144782, -4476029, -6579123, 10770039, -7155542,
+             -6650416, -12936300, -18319198, 10212860},
+            {2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801,
+             2600940, -9988298, -12506466},
+            {-24645692, 13317462, -30449259, -15653928, 21365574, -10869657,
+             11344424, 864440, -2499677, -16710063},
+        },
+        {
+            {-26432803, 6148329, -17184412, -14474154, 18782929, -275997,
+             -22561534, 211300, 2719757, 4940997},
+            {-1323882, 3911313, -6948744, 14759765, -30027150, 7851207,
+             21690126, 8518463, 26699843, 5276295},
+            {-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586,
+             149635, -15452774, 7159369},
+        },
+        {
+            {9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009,
+             8312176, 22477218, -8403385},
+            {18155857, -16504990, 19744716, 9006923, 15154154, -10538976,
+             24256460, -4864995, -22548173, 9334109},
+            {2986088, -4911893, 10776628, -3473844, 10620590, -7083203,
+             -21413845, 14253545, -22587149, 536906},
+        },
+        {
+            {4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551,
+             10589625, 10838060, -15420424},
+            {-19342404, 867880, 9277171, -3218459, -14431572, -1986443,
+             19295826, -15796950, 6378260, 699185},
+            {7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039,
+             15693155, -5045064, -13373962},
+        },
+        {
+            {-7737563, -5869402, -14566319, -7406919, 11385654, 13201616,
+             31730678, -10962840, -3918636, -9669325},
+            {10188286, -15770834, -7336361, 13427543, 22223443, 14896287,
+             30743455, 7116568, -21786507, 5427593},
+            {696102, 13206899, 27047647, -10632082, 15285305, -9853179,
+             10798490, -4578720, 19236243, 12477404},
+        },
+        {
+            {-11229439, 11243796, -17054270, -8040865, -788228, -8167967,
+             -3897669, 11180504, -23169516, 7733644},
+            {17800790, -14036179, -27000429, -11766671, 23887827, 3149671,
+             23466177, -10538171, 10322027, 15313801},
+            {26246234, 11968874, 32263343, -5468728, 6830755, -13323031,
+             -15794704, -101982, -24449242, 10890804},
+        },
+        {
+            {-31365647, 10271363, -12660625, -6267268, 16690207, -13062544,
+             -14982212, 16484931, 25180797, -5334884},
+            {-586574, 10376444, -32586414, -11286356, 19801893, 10997610,
+             2276632, 9482883, 316878, 13820577},
+            {-9882808, -4510367, -2115506, 16457136, -11100081, 11674996,
+             30756178, -7515054, 30696930, -3712849},
+        },
+        {
+            {32988917, -9603412, 12499366, 7910787, -10617257, -11931514,
+             -7342816, -9985397, -32349517, 7392473},
+            {-8855661, 15927861, 9866406, -3649411, -2396914, -16655781,
+             -30409476, -9134995, 25112947, -2926644},
+            {-2504044, -436966, 25621774, -5678772, 15085042, -5479877,
+             -24884878, -13526194, 5537438, -13914319},
+        },
+    },
+    {
+        {
+            {-11225584, 2320285, -9584280, 10149187, -33444663, 5808648,
+             -14876251, -1729667, 31234590, 6090599},
+            {-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721,
+             15878753, -6970405, -9034768},
+            {-27757857, 247744, -15194774, -9002551, 23288161, -10011936,
+             -23869595, 6503646, 20650474, 1804084},
+        },
+        {
+            {-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995,
+             -10329713, 27842616, -202328},
+            {-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656,
+             5031932, -11375082, 12714369},
+            {20807691, -7270825, 29286141, 11421711, -27876523, -13868230,
+             -21227475, 1035546, -19733229, 12796920},
+        },
+        {
+            {12076899, -14301286, -8785001, -11848922, -25012791, 16400684,
+             -17591495, -12899438, 3480665, -15182815},
+            {-32361549, 5457597, 28548107, 7833186, 7303070, -11953545,
+             -24363064, -15921875, -33374054, 2771025},
+            {-21389266, 421932, 26597266, 6860826, 22486084, -6737172,
+             -17137485, -4210226, -24552282, 15673397},
+        },
+        {
+            {-20184622, 2338216, 19788685, -9620956, -4001265, -8740893,
+             -20271184, 4733254, 3727144, -12934448},
+            {6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594,
+             7975683, 31123697, -10958981},
+            {30069250, -11435332, 30434654, 2958439, 18399564, -976289,
+             12296869, 9204260, -16432438, 9648165},
+        },
+        {
+            {32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266,
+             5248604, -26008332, -11377501},
+            {17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711,
+             15298639, 2662509, -16297073},
+            {-1172927, -7558695, -4366770, -4287744, -21346413, -8434326,
+             32087529, -1222777, 32247248, -14389861},
+        },
+        {
+            {14312628, 1221556, 17395390, -8700143, -4945741, -8684635,
+             -28197744, -9637817, -16027623, -13378845},
+            {-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502,
+             9803137, 17597934, 2346211},
+            {18510800, 15337574, 26171504, 981392, -22241552, 7827556,
+             -23491134, -11323352, 3059833, -11782870},
+        },
+        {
+            {10141598, 6082907, 17829293, -1947643, 9830092, 13613136,
+             -25556636, -5544586, -33502212, 3592096},
+            {33114168, -15889352, -26525686, -13343397, 33076705, 8716171,
+             1151462, 1521897, -982665, -6837803},
+            {-32939165, -4255815, 23947181, -324178, -33072974, -12305637,
+             -16637686, 3891704, 26353178, 693168},
+        },
+        {
+            {30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294,
+             -400668, 31375464, 14369965},
+            {-14370654, -7772529, 1510301, 6434173, -18784789, -6262728,
+             32732230, -13108839, 17901441, 16011505},
+            {18171223, -11934626, -12500402, 15197122, -11038147, -15230035,
+             -19172240, -16046376, 8764035, 12309598},
+        },
+    },
+    {
+        {
+            {5975908, -5243188, -19459362, -9681747, -11541277, 14015782,
+             -23665757, 1228319, 17544096, -10593782},
+            {5811932, -1715293, 3442887, -2269310, -18367348, -8359541,
+             -18044043, -15410127, -5565381, 12348900},
+            {-31399660, 11407555, 25755363, 6891399, -3256938, 14872274,
+             -24849353, 8141295, -10632534, -585479},
+        },
+        {
+            {-12675304, 694026, -5076145, 13300344, 14015258, -14451394,
+             -9698672, -11329050, 30944593, 1130208},
+            {8247766, -6710942, -26562381, -7709309, -14401939, -14648910,
+             4652152, 2488540, 23550156, -271232},
+            {17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737,
+             -5908146, -408818, -137719},
+        },
+        {
+            {16091085, -16253926, 18599252, 7340678, 2137637, -1221657,
+             -3364161, 14550936, 3260525, -7166271},
+            {-4910104, -13332887, 18550887, 10864893, -16459325, -7291596,
+             -23028869, -13204905, -12748722, 2701326},
+            {-8574695, 16099415, 4629974, -16340524, -20786213, -6005432,
+             -10018363, 9276971, 11329923, 1862132},
+        },
+        {
+            {14763076, -15903608, -30918270, 3689867, 3511892, 10313526,
+             -21951088, 12219231, -9037963, -940300},
+            {8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216,
+             -2909717, -15438168, 11595570},
+            {15214962, 3537601, -26238722, -14058872, 4418657, -15230761,
+             13947276, 10730794, -13489462, -4363670},
+        },
+        {
+            {-2538306, 7682793, 32759013, 263109, -29984731, -7955452,
+             -22332124, -10188635, 977108, 699994},
+            {-12466472, 4195084, -9211532, 550904, -15565337, 12917920,
+             19118110, -439841, -30534533, -14337913},
+            {31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237,
+             -10051775, 12493932, -5409317},
+        },
+        {
+            {-25680606, 5260744, -19235809, -6284470, -3695942, 16566087,
+             27218280, 2607121, 29375955, 6024730},
+            {842132, -2794693, -4763381, -8722815, 26332018, -12405641,
+             11831880, 6985184, -9940361, 2854096},
+            {-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645,
+             960770, 12121869, 16648078},
+        },
+        {
+            {-15218652, 14667096, -13336229, 2013717, 30598287, -464137,
+             -31504922, -7882064, 20237806, 2838411},
+            {-19288047, 4453152, 15298546, -16178388, 22115043, -15972604,
+             12544294, -13470457, 1068881, -12499905},
+            {-9558883, -16518835, 33238498, 13506958, 30505848, -1114596,
+             -8486907, -2630053, 12521378, 4845654},
+        },
+        {
+            {-28198521, 10744108, -2958380, 10199664, 7759311, -13088600,
+             3409348, -873400, -6482306, -12885870},
+            {-23561822, 6230156, -20382013, 10655314, -24040585, -11621172,
+             10477734, -1240216, -3113227, 13974498},
+            {12966261, 15550616, -32038948, -1615346, 21025980, -629444,
+             5642325, 7188737, 18895762, 12629579},
+        },
+    },
+    {
+        {
+            {14741879, -14946887, 22177208, -11721237, 1279741, 8058600,
+             11758140, 789443, 32195181, 3895677},
+            {10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575,
+             -3566119, -8982069, 4429647},
+            {-2453894, 15725973, -20436342, -10410672, -5803908, -11040220,
+             -7135870, -11642895, 18047436, -15281743},
+        },
+        {
+            {-25173001, -11307165, 29759956, 11776784, -22262383, -15820455,
+             10993114, -12850837, -17620701, -9408468},
+            {21987233, 700364, -24505048, 14972008, -7774265, -5718395,
+             32155026, 2581431, -29958985, 8773375},
+            {-25568350, 454463, -13211935, 16126715, 25240068, 8594567,
+             20656846, 12017935, -7874389, -13920155},
+        },
+        {
+            {6028182, 6263078, -31011806, -11301710, -818919, 2461772,
+             -31841174, -5468042, -1721788, -2776725},
+            {-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845,
+             -4166698, 28408820, 6816612},
+            {-10358094, -8237829, 19549651, -12169222, 22082623, 16147817,
+             20613181, 13982702, -10339570, 5067943},
+        },
+        {
+            {-30505967, -3821767, 12074681, 13582412, -19877972, 2443951,
+             -19719286, 12746132, 5331210, -10105944},
+            {30528811, 3601899, -1957090, 4619785, -27361822, -15436388,
+             24180793, -12570394, 27679908, -1648928},
+            {9402404, -13957065, 32834043, 10838634, -26580150, -13237195,
+             26653274, -8685565, 22611444, -12715406},
+        },
+        {
+            {22190590, 1118029, 22736441, 15130463, -30460692, -5991321,
+             19189625, -4648942, 4854859, 6622139},
+            {-8310738, -2953450, -8262579, -3388049, -10401731, -271929,
+             13424426, -3567227, 26404409, 13001963},
+            {-31241838, -15415700, -2994250, 8939346, 11562230, -12840670,
+             -26064365, -11621720, -15405155, 11020693},
+        },
+        {
+            {1866042, -7949489, -7898649, -10301010, 12483315, 13477547,
+             3175636, -12424163, 28761762, 1406734},
+            {-448555, -1777666, 13018551, 3194501, -9580420, -11161737,
+             24760585, -4347088, 25577411, -13378680},
+            {-24290378, 4759345, -690653, -1852816, 2066747, 10693769,
+             -29595790, 9884936, -9368926, 4745410},
+        },
+        {
+            {-9141284, 6049714, -19531061, -4341411, -31260798, 9944276,
+             -15462008, -11311852, 10931924, -11931931},
+            {-16561513, 14112680, -8012645, 4817318, -8040464, -11414606,
+             -22853429, 10856641, -20470770, 13434654},
+            {22759489, -10073434, -16766264, -1871422, 13637442, -10168091,
+             1765144, -12654326, 28445307, -5364710},
+        },
+        {
+            {29875063, 12493613, 2795536, -3786330, 1710620, 15181182,
+             -10195717, -8788675, 9074234, 1167180},
+            {-26205683, 11014233, -9842651, -2635485, -26908120, 7532294,
+             -18716888, -9535498, 3843903, 9367684},
+            {-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123,
+             8601684, -139197, 4242895},
+        },
+    },
+    {
+        {
+            {22092954, -13191123, -2042793, -11968512, 32186753, -11517388,
+             -6574341, 2470660, -27417366, 16625501},
+            {-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857,
+             2602725, -27351616, 14247413},
+            {6314175, -10264892, -32772502, 15957557, -10157730, 168750,
+             -8618807, 14290061, 27108877, -1180880},
+        },
+        {
+            {-8586597, -7170966, 13241782, 10960156, -32991015, -13794596,
+             33547976, -11058889, -27148451, 981874},
+            {22833440, 9293594, -32649448, -13618667, -9136966, 14756819,
+             -22928859, -13970780, -10479804, -16197962},
+            {-7768587, 3326786, -28111797, 10783824, 19178761, 14905060,
+             22680049, 13906969, -15933690, 3797899},
+        },
+        {
+            {21721356, -4212746, -12206123, 9310182, -3882239, -13653110,
+             23740224, -2709232, 20491983, -8042152},
+            {9209270, -15135055, -13256557, -6167798, -731016, 15289673,
+             25947805, 15286587, 30997318, -6703063},
+            {7392032, 16618386, 23946583, -8039892, -13265164, -1533858,
+             -14197445, -2321576, 17649998, -250080},
+        },
+        {
+            {-9301088, -14193827, 30609526, -3049543, -25175069, -1283752,
+             -15241566, -9525724, -2233253, 7662146},
+            {-17558673, 1763594, -33114336, 15908610, -30040870, -12174295,
+             7335080, -8472199, -3174674, 3440183},
+            {-19889700, -5977008, -24111293, -9688870, 10799743, -16571957,
+             40450, -4431835, 4862400, 1133},
+        },
+        {
+            {-32856209, -7873957, -5422389, 14860950, -16319031, 7956142,
+             7258061, 311861, -30594991, -7379421},
+            {-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763,
+             16527196, 18278453, 15405622},
+            {-4381906, 8508652, -19898366, -3674424, -5984453, 15149970,
+             -13313598, 843523, -21875062, 13626197},
+        },
+        {
+            {2281448, -13487055, -10915418, -2609910, 1879358, 16164207,
+             -10783882, 3953792, 13340839, 15928663},
+            {31727126, -7179855, -18437503, -8283652, 2875793, -16390330,
+             -25269894, -7014826, -23452306, 5964753},
+            {4100420, -5959452, -17179337, 6017714, -18705837, 12227141,
+             -26684835, 11344144, 2538215, -7570755},
+        },
+        {
+            {-9433605, 6123113, 11159803, -2156608, 30016280, 14966241,
+             -20474983, 1485421, -629256, -15958862},
+            {-26804558, 4260919, 11851389, 9658551, -32017107, 16367492,
+             -20205425, -13191288, 11659922, -11115118},
+            {26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568,
+             -10170080, 33100372, -1306171},
+        },
+        {
+            {15121113, -5201871, -10389905, 15427821, -27509937, -15992507,
+             21670947, 4486675, -5931810, -14466380},
+            {16166486, -9483733, -11104130, 6023908, -31926798, -1364923,
+             2340060, -16254968, -10735770, -10039824},
+            {28042865, -3557089, -12126526, 12259706, -3717498, -6945899,
+             6766453, -8689599, 18036436, 5803270},
+        },
+    },
+    {
+        {
+            {-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391,
+             4598332, -6159431, -14117438},
+            {-31031306, -14256194, 17332029, -2383520, 31312682, -5967183,
+             696309, 50292, -20095739, 11763584},
+            {-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117,
+             -12613632, -19773211, -10713562},
+        },
+        {
+            {30464590, -11262872, -4127476, -12734478, 19835327, -7105613,
+             -24396175, 2075773, -17020157, 992471},
+            {18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841,
+             8080033, -11574335, -10601610},
+            {19598397, 10334610, 12555054, 2555664, 18821899, -10339780,
+             21873263, 16014234, 26224780, 16452269},
+        },
+        {
+            {-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804,
+             -7618186, -20533829, 3698650},
+            {14187449, 3448569, -10636236, -10810935, -22663880, -3433596,
+             7268410, -10890444, 27394301, 12015369},
+            {19695761, 16087646, 28032085, 12999827, 6817792, 11427614,
+             20244189, -1312777, -13259127, -3402461},
+        },
+        {
+            {30860103, 12735208, -1888245, -4699734, -16974906, 2256940,
+             -8166013, 12298312, -8550524, -10393462},
+            {-5719826, -11245325, -1910649, 15569035, 26642876, -7587760,
+             -5789354, -15118654, -4976164, 12651793},
+            {-2848395, 9953421, 11531313, -5282879, 26895123, -12697089,
+             -13118820, -16517902, 9768698, -2533218},
+        },
+        {
+            {-24719459, 1894651, -287698, -4704085, 15348719, -8156530,
+             32767513, 12765450, 4940095, 10678226},
+            {18860224, 15980149, -18987240, -1562570, -26233012, -11071856,
+             -7843882, 13944024, -24372348, 16582019},
+            {-15504260, 4970268, -29893044, 4175593, -20993212, -2199756,
+             -11704054, 15444560, -11003761, 7989037},
+        },
+        {
+            {31490452, 5568061, -2412803, 2182383, -32336847, 4531686,
+             -32078269, 6200206, -19686113, -14800171},
+            {-17308668, -15879940, -31522777, -2831, -32887382, 16375549,
+             8680158, -16371713, 28550068, -6857132},
+            {-28126887, -5688091, 16837845, -1820458, -6850681, 12700016,
+             -30039981, 4364038, 1155602, 5988841},
+        },
+        {
+            {21890435, -13272907, -12624011, 12154349, -7831873, 15300496,
+             23148983, -4470481, 24618407, 8283181},
+            {-33136107, -10512751, 9975416, 6841041, -31559793, 16356536,
+             3070187, -7025928, 1466169, 10740210},
+            {-1509399, -15488185, -13503385, -10655916, 32799044, 909394,
+             -13938903, -5779719, -32164649, -15327040},
+        },
+        {
+            {3960823, -14267803, -28026090, -15918051, -19404858, 13146868,
+             15567327, 951507, -3260321, -573935},
+            {24740841, 5052253, -30094131, 8961361, 25877428, 6165135,
+             -24368180, 14397372, -7380369, -6144105},
+            {-28888365, 3510803, -28103278, -1158478, -11238128, -10631454,
+             -15441463, -14453128, -1625486, -6494814},
+        },
+    },
+    {
+        {
+            {793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843,
+             -4885251, -9906200, -621852},
+            {5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374,
+             1468826, -6171428, -15186581},
+            {-4859255, -3779343, -2917758, -6748019, 7778750, 11688288,
+             -30404353, -9871238, -1558923, -9863646},
+        },
+        {
+            {10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958,
+             14783338, -30581476, -15757844},
+            {10566929, 12612572, -31944212, 11118703, -12633376, 12362879,
+             21752402, 8822496, 24003793, 14264025},
+            {27713862, -7355973, -11008240, 9227530, 27050101, 2504721,
+             23886875, -13117525, 13958495, -5732453},
+        },
+        {
+            {-23481610, 4867226, -27247128, 3900521, 29838369, -8212291,
+             -31889399, -10041781, 7340521, -15410068},
+            {4646514, -8011124, -22766023, -11532654, 23184553, 8566613,
+             31366726, -1381061, -15066784, -10375192},
+            {-17270517, 12723032, -16993061, 14878794, 21619651, -6197576,
+             27584817, 3093888, -8843694, 3849921},
+        },
+        {
+            {-9064912, 2103172, 25561640, -15125738, -5239824, 9582958,
+             32477045, -9017955, 5002294, -15550259},
+            {-12057553, -11177906, 21115585, -13365155, 8808712, -12030708,
+             16489530, 13378448, -25845716, 12741426},
+            {-5946367, 10645103, -30911586, 15390284, -3286982, -7118677,
+             24306472, 15852464, 28834118, -7646072},
+        },
+        {
+            {-17335748, -9107057, -24531279, 9434953, -8472084, -583362,
+             -13090771, 455841, 20461858, 5491305},
+            {13669248, -16095482, -12481974, -10203039, -14569770, -11893198,
+             -24995986, 11293807, -28588204, -9421832},
+            {28497928, 6272777, -33022994, 14470570, 8906179, -1225630,
+             18504674, -14165166, 29867745, -8795943},
+        },
+        {
+            {-16207023, 13517196, -27799630, -13697798, 24009064, -6373891,
+             -6367600, -13175392, 22853429, -4012011},
+            {24191378, 16712145, -13931797, 15217831, 14542237, 1646131,
+             18603514, -11037887, 12876623, -2112447},
+            {17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753,
+             608397, 16031844, 3723494},
+        },
+        {
+            {-28632773, 12763728, -20446446, 7577504, 33001348, -13017745,
+             17558842, -7872890, 23896954, -4314245},
+            {-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064,
+             7229064, -9919646, -8826859},
+            {28816045, 298879, -28165016, -15920938, 19000928, -1665890,
+             -12680833, -2949325, -18051778, -2082915},
+        },
+        {
+            {16000882, -344896, 3493092, -11447198, -29504595, -13159789,
+             12577740, 16041268, -19715240, 7847707},
+            {10151868, 10572098, 27312476, 7922682, 14825339, 4723128,
+             -32855931, -6519018, -10020567, 3852848},
+            {-11430470, 15697596, -21121557, -4420647, 5386314, 15063598,
+             16514493, -15932110, 29330899, -15076224},
+        },
+    },
+    {
+        {
+            {-25499735, -4378794, -15222908, -6901211, 16615731, 2051784,
+             3303702, 15490, -27548796, 12314391},
+            {15683520, -6003043, 18109120, -9980648, 15337968, -5997823,
+             -16717435, 15921866, 16103996, -3731215},
+            {-23169824, -10781249, 13588192, -1628807, -3798557, -1074929,
+             -19273607, 5402699, -29815713, -9841101},
+        },
+        {
+            {23190676, 2384583, -32714340, 3462154, -29903655, -1529132,
+             -11266856, 8911517, -25205859, 2739713},
+            {21374101, -3554250, -33524649, 9874411, 15377179, 11831242,
+             -33529904, 6134907, 4931255, 11987849},
+            {-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539,
+             13861388, -30076310, 10117930},
+        },
+        {
+            {-29501170, -10744872, -26163768, 13051539, -25625564, 5089643,
+             -6325503, 6704079, 12890019, 15728940},
+            {-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376,
+             -10428139, 12885167, 8311031},
+            {-17516482, 5352194, 10384213, -13811658, 7506451, 13453191,
+             26423267, 4384730, 1888765, -5435404},
+        },
+        {
+            {-25817338, -3107312, -13494599, -3182506, 30896459, -13921729,
+             -32251644, -12707869, -19464434, -3340243},
+            {-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245,
+             14845197, 17151279, -9854116},
+            {-24830458, -12733720, -15165978, 10367250, -29530908, -265356,
+             22825805, -7087279, -16866484, 16176525},
+        },
+        {
+            {-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182,
+             -10363426, -28746253, -10197509},
+            {-10626600, -4486402, -13320562, -5125317, 3432136, -6393229,
+             23632037, -1940610, 32808310, 1099883},
+            {15030977, 5768825, -27451236, -2887299, -6427378, -15361371,
+             -15277896, -6809350, 2051441, -15225865},
+        },
+        {
+            {-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398,
+             -14154188, -22686354, 16633660},
+            {4577086, -16752288, 13249841, -15304328, 19958763, -14537274,
+             18559670, -10759549, 8402478, -9864273},
+            {-28406330, -1051581, -26790155, -907698, -17212414, -11030789,
+             9453451, -14980072, 17983010, 9967138},
+        },
+        {
+            {-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990,
+             7806337, 17507396, 3651560},
+            {-10420457, -4118111, 14584639, 15971087, -15768321, 8861010,
+             26556809, -5574557, -18553322, -11357135},
+            {2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121,
+             8459447, -5605463, -7621941},
+        },
+        {
+            {-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813,
+             -849066, 17258084, -7977739},
+            {18164541, -10595176, -17154882, -1542417, 19237078, -9745295,
+             23357533, -15217008, 26908270, 12150756},
+            {-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168,
+             -5537701, -32302074, 16215819},
+        },
+    },
+    {
+        {
+            {-6898905, 9824394, -12304779, -4401089, -31397141, -6276835,
+             32574489, 12532905, -7503072, -8675347},
+            {-27343522, -16515468, -27151524, -10722951, 946346, 16291093,
+             254968, 7168080, 21676107, -1943028},
+            {21260961, -8424752, -16831886, -11920822, -23677961, 3968121,
+             -3651949, -6215466, -3556191, -7913075},
+        },
+        {
+            {16544754, 13250366, -16804428, 15546242, -4583003, 12757258,
+             -2462308, -8680336, -18907032, -9662799},
+            {-2415239, -15577728, 18312303, 4964443, -15272530, -12653564,
+             26820651, 16690659, 25459437, -4564609},
+            {-25144690, 11425020, 28423002, -11020557, -6144921, -15826224,
+             9142795, -2391602, -6432418, -1644817},
+        },
+        {
+            {-23104652, 6253476, 16964147, -3768872, -25113972, -12296437,
+             -27457225, -16344658, 6335692, 7249989},
+            {-30333227, 13979675, 7503222, -12368314, -11956721, -4621693,
+             -30272269, 2682242, 25993170, -12478523},
+            {4364628, 5930691, 32304656, -10044554, -8054781, 15091131,
+             22857016, -10598955, 31820368, 15075278},
+        },
+        {
+            {31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788,
+             -9650886, -17970238, 12833045},
+            {19073683, 14851414, -24403169, -11860168, 7625278, 11091125,
+             -19619190, 2074449, -9413939, 14905377},
+            {24483667, -11935567, -2518866, -11547418, -1553130, 15355506,
+             -25282080, 9253129, 27628530, -7555480},
+        },
+        {
+            {17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324,
+             -9157582, -14110875, 15297016},
+            {510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417,
+             -11864220, 8683221, 2921426},
+            {18606791, 11874196, 27155355, -5281482, -24031742, 6265446,
+             -25178240, -1278924, 4674690, 13890525},
+        },
+        {
+            {13609624, 13069022, -27372361, -13055908, 24360586, 9592974,
+             14977157, 9835105, 4389687, 288396},
+            {9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062,
+             8317628, 23388070, 16052080},
+            {12720016, 11937594, -31970060, -5028689, 26900120, 8561328,
+             -20155687, -11632979, -14754271, -10812892},
+        },
+        {
+            {15961858, 14150409, 26716931, -665832, -22794328, 13603569,
+             11829573, 7467844, -28822128, 929275},
+            {11038231, -11582396, -27310482, -7316562, -10498527, -16307831,
+             -23479533, -9371869, -21393143, 2465074},
+            {20017163, -4323226, 27915242, 1529148, 12396362, 15675764,
+             13817261, -9658066, 2463391, -4622140},
+        },
+        {
+            {-16358878, -12663911, -12065183, 4996454, -1256422, 1073572,
+             9583558, 12851107, 4003896, 12673717},
+            {-1731589, -15155870, -3262930, 16143082, 19294135, 13385325,
+             14741514, -9103726, 7903886, 2348101},
+            {24536016, -16515207, 12715592, -3862155, 1511293, 10047386,
+             -3842346, -7129159, -28377538, 10048127},
+        },
+    },
+    {
+        {
+            {-12622226, -6204820, 30718825, 2591312, -10617028, 12192840,
+             18873298, -7297090, -32297756, 15221632},
+            {-26478122, -11103864, 11546244, -1852483, 9180880, 7656409,
+             -21343950, 2095755, 29769758, 6593415},
+            {-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345,
+             -6118678, 30958054, 8292160},
+        },
+        {
+            {31429822, -13959116, 29173532, 15632448, 12174511, -2760094,
+             32808831, 3977186, 26143136, -3148876},
+            {22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633,
+             -1674433, -3758243, -2304625},
+            {-15491917, 8012313, -2514730, -12702462, -23965846, -10254029,
+             -1612713, -1535569, -16664475, 8194478},
+        },
+        {
+            {27338066, -7507420, -7414224, 10140405, -19026427, -6589889,
+             27277191, 8855376, 28572286, 3005164},
+            {26287124, 4821776, 25476601, -4145903, -3764513, -15788984,
+             -18008582, 1182479, -26094821, -13079595},
+            {-7171154, 3178080, 23970071, 6201893, -17195577, -4489192,
+             -21876275, -13982627, 32208683, -1198248},
+        },
+        {
+            {-16657702, 2817643, -10286362, 14811298, 6024667, 13349505,
+             -27315504, -10497842, -27672585, -11539858},
+            {15941029, -9405932, -21367050, 8062055, 31876073, -238629,
+             -15278393, -1444429, 15397331, -4130193},
+            {8934485, -13485467, -23286397, -13423241, -32446090, 14047986,
+             31170398, -1441021, -27505566, 15087184},
+        },
+        {
+            {-18357243, -2156491, 24524913, -16677868, 15520427, -6360776,
+             -15502406, 11461896, 16788528, -5868942},
+            {-1947386, 16013773, 21750665, 3714552, -17401782, -16055433,
+             -3770287, -10323320, 31322514, -11615635},
+            {21426655, -5650218, -13648287, -5347537, -28812189, -4920970,
+             -18275391, -14621414, 13040862, -12112948},
+        },
+        {
+            {11293895, 12478086, -27136401, 15083750, -29307421, 14748872,
+             14555558, -13417103, 1613711, 4896935},
+            {-25894883, 15323294, -8489791, -8057900, 25967126, -13425460,
+             2825960, -4897045, -23971776, -11267415},
+            {-15924766, -5229880, -17443532, 6410664, 3622847, 10243618,
+             20615400, 12405433, -23753030, -8436416},
+        },
+        {
+            {-7091295, 12556208, -20191352, 9025187, -17072479, 4333801,
+             4378436, 2432030, 23097949, -566018},
+            {4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264,
+             10103221, -18512313, 2424778},
+            {366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678,
+             1344109, -3642553, 12412659},
+        },
+        {
+            {-24001791, 7690286, 14929416, -168257, -32210835, -13412986,
+             24162697, -15326504, -3141501, 11179385},
+            {18289522, -14724954, 8056945, 16430056, -21729724, 7842514,
+             -6001441, -1486897, -18684645, -11443503},
+            {476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959,
+             13403813, 11052904, 5219329},
+        },
+    },
+    {
+        {
+            {20678546, -8375738, -32671898, 8849123, -5009758, 14574752,
+             31186971, -3973730, 9014762, -8579056},
+            {-13644050, -10350239, -15962508, 5075808, -1514661, -11534600,
+             -33102500, 9160280, 8473550, -3256838},
+            {24900749, 14435722, 17209120, -15292541, -22592275, 9878983,
+             -7689309, -16335821, -24568481, 11788948},
+        },
+        {
+            {-3118155, -11395194, -13802089, 14797441, 9652448, -6845904,
+             -20037437, 10410733, -24568470, -1458691},
+            {-15659161, 16736706, -22467150, 10215878, -9097177, 7563911,
+             11871841, -12505194, -18513325, 8464118},
+            {-23400612, 8348507, -14585951, -861714, -3950205, -6373419,
+             14325289, 8628612, 33313881, -8370517},
+        },
+        {
+            {-20186973, -4967935, 22367356, 5271547, -1097117, -4788838,
+             -24805667, -10236854, -8940735, -5818269},
+            {-6948785, -1795212, -32625683, -16021179, 32635414, -7374245,
+             15989197, -12838188, 28358192, -4253904},
+            {-23561781, -2799059, -32351682, -1661963, -9147719, 10429267,
+             -16637684, 4072016, -5351664, 5596589},
+        },
+        {
+            {-28236598, -3390048, 12312896, 6213178, 3117142, 16078565,
+             29266239, 2557221, 1768301, 15373193},
+            {-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902,
+             -4504991, -24660491, 3442910},
+            {-30210571, 5124043, 14181784, 8197961, 18964734, -11939093,
+             22597931, 7176455, -18585478, 13365930},
+        },
+        {
+            {-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107,
+             -8570186, -9689599, -3031667},
+            {25008904, -10771599, -4305031, -9638010, 16265036, 15721635,
+             683793, -11823784, 15723479, -15163481},
+            {-9660625, 12374379, -27006999, -7026148, -7724114, -12314514,
+             11879682, 5400171, 519526, -1235876},
+        },
+        {
+            {22258397, -16332233, -7869817, 14613016, -22520255, -2950923,
+             -20353881, 7315967, 16648397, 7605640},
+            {-8081308, -8464597, -8223311, 9719710, 19259459, -15348212,
+             23994942, -5281555, -9468848, 4763278},
+            {-21699244, 9220969, -15730624, 1084137, -25476107, -2852390,
+             31088447, -7764523, -11356529, 728112},
+        },
+        {
+            {26047220, -11751471, -6900323, -16521798, 24092068, 9158119,
+             -4273545, -12555558, -29365436, -5498272},
+            {17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007,
+             12327945, 10750447, 10014012},
+            {-10312768, 3936952, 9156313, -8897683, 16498692, -994647,
+             -27481051, -666732, 3424691, 7540221},
+        },
+        {
+            {30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422,
+             -16317219, -9244265, 15258046},
+            {13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406,
+             2711395, 1062915, -5136345},
+            {-19240248, -11254599, -29509029, -7499965, -5835763, 13005411,
+             -6066489, 12194497, 32960380, 1459310},
+        },
+    },
+    {
+        {
+            {19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197,
+             -6101885, 18638003, -11174937},
+            {31395534, 15098109, 26581030, 8030562, -16527914, -5007134,
+             9012486, -7584354, -6643087, -5442636},
+            {-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222,
+             9677543, -32294889, -6456008},
+        },
+        {
+            {-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579,
+             -7839692, -7852844, -8138429},
+            {-15236356, -15433509, 7766470, 746860, 26346930, -10221762,
+             -27333451, 10754588, -9431476, 5203576},
+            {31834314, 14135496, -770007, 5159118, 20917671, -16768096,
+             -7467973, -7337524, 31809243, 7347066},
+        },
+        {
+            {-9606723, -11874240, 20414459, 13033986, 13716524, -11691881,
+             19797970, -12211255, 15192876, -2087490},
+            {-12663563, -2181719, 1168162, -3804809, 26747877, -14138091,
+             10609330, 12694420, 33473243, -13382104},
+            {33184999, 11180355, 15832085, -11385430, -1633671, 225884,
+             15089336, -11023903, -6135662, 14480053},
+        },
+        {
+            {31308717, -5619998, 31030840, -1897099, 15674547, -6582883,
+             5496208, 13685227, 27595050, 8737275},
+            {-20318852, -15150239, 10933843, -16178022, 8335352, -7546022,
+             -31008351, -12610604, 26498114, 66511},
+            {22644454, -8761729, -16671776, 4884562, -3105614, -13559366,
+             30540766, -4286747, -13327787, -7515095},
+        },
+        {
+            {-28017847, 9834845, 18617207, -2681312, -3401956, -13307506,
+             8205540, 13585437, -17127465, 15115439},
+            {23711543, -672915, 31206561, -8362711, 6164647, -9709987,
+             -33535882, -1426096, 8236921, 16492939},
+            {-23910559, -13515526, -26299483, -4503841, 25005590, -7687270,
+             19574902, 10071562, 6708380, -6222424},
+        },
+        {
+            {2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017,
+             9328700, 29955601, -11678310},
+            {3096359, 9271816, -21620864, -15521844, -14847996, -7592937,
+             -25892142, -12635595, -9917575, 6216608},
+            {-32615849, 338663, -25195611, 2510422, -29213566, -13820213,
+             24822830, -6146567, -26767480, 7525079},
+        },
+        {
+            {-23066649, -13985623, 16133487, -7896178, -3389565, 778788,
+             -910336, -2782495, -19386633, 11994101},
+            {21691500, -13624626, -641331, -14367021, 3285881, -3483596,
+             -25064666, 9718258, -7477437, 13381418},
+            {18445390, -4202236, 14979846, 11622458, -1727110, -3582980,
+             23111648, -6375247, 28535282, 15779576},
+        },
+        {
+            {30098053, 3089662, -9234387, 16662135, -21306940, 11308411,
+             -14068454, 12021730, 9955285, -16303356},
+            {9734894, -14576830, -7473633, -9138735, 2060392, 11313496,
+             -18426029, 9924399, 20194861, 13380996},
+            {-26378102, -7965207, -22167821, 15789297, -18055342, -6168792,
+             -1984914, 15707771, 26342023, 10146099},
+        },
+    },
+    {
+        {
+            {-26016874, -219943, 21339191, -41388, 19745256, -2878700,
+             -29637280, 2227040, 21612326, -545728},
+            {-13077387, 1184228, 23562814, -5970442, -20351244, -6348714,
+             25764461, 12243797, -20856566, 11649658},
+            {-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944,
+             6114064, 33514190, 2333242},
+        },
+        {
+            {-21433588, -12421821, 8119782, 7219913, -21830522, -9016134,
+             -6679750, -12670638, 24350578, -13450001},
+            {-4116307, -11271533, -23886186, 4843615, -30088339, 690623,
+             -31536088, -10406836, 8317860, 12352766},
+            {18200138, -14475911, -33087759, -2696619, -23702521, -9102511,
+             -23552096, -2287550, 20712163, 6719373},
+        },
+        {
+            {26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530,
+             -3763210, 26224235, -3297458},
+            {-17168938, -14854097, -3395676, -16369877, -19954045, 14050420,
+             21728352, 9493610, 18620611, -16428628},
+            {-13323321, 13325349, 11432106, 5964811, 18609221, 6062965,
+             -5269471, -9725556, -30701573, -16479657},
+        },
+        {
+            {-23860538, -11233159, 26961357, 1640861, -32413112, -16737940,
+             12248509, -5240639, 13735342, 1934062},
+            {25089769, 6742589, 17081145, -13406266, 21909293, -16067981,
+             -15136294, -3765346, -21277997, 5473616},
+            {31883677, -7961101, 1083432, -11572403, 22828471, 13290673,
+             -7125085, 12469656, 29111212, -5451014},
+        },
+        {
+            {24244947, -15050407, -26262976, 2791540, -14997599, 16666678,
+             24367466, 6388839, -10295587, 452383},
+            {-25640782, -3417841, 5217916, 16224624, 19987036, -4082269,
+             -24236251, -5915248, 15766062, 8407814},
+            {-20406999, 13990231, 15495425, 16395525, 5377168, 15166495,
+             -8917023, -4388953, -8067909, 2276718},
+        },
+        {
+            {30157918, 12924066, -17712050, 9245753, 19895028, 3368142,
+             -23827587, 5096219, 22740376, -7303417},
+            {2041139, -14256350, 7783687, 13876377, -25946985, -13352459,
+             24051124, 13742383, -15637599, 13295222},
+            {33338237, -8505733, 12532113, 7977527, 9106186, -1715251,
+             -17720195, -4612972, -4451357, -14669444},
+        },
+        {
+            {-20045281, 5454097, -14346548, 6447146, 28862071, 1883651,
+             -2469266, -4141880, 7770569, 9620597},
+            {23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528,
+             -1694323, -33502340, -14767970},
+            {1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801,
+             1220118, 30494170, -11440799},
+        },
+        {
+            {-5037580, -13028295, -2970559, -3061767, 15640974, -6701666,
+             -26739026, 926050, -1684339, -13333647},
+            {13908495, -3549272, 30919928, -6273825, -21521863, 7989039,
+             9021034, 9078865, 3353509, 4033511},
+            {-29663431, -15113610, 32259991, -344482, 24295849, -12912123,
+             23161163, 8839127, 27485041, 7356032},
+        },
+    },
+    {
+        {
+            {9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142,
+             2625015, 28431036, -16771834},
+            {-23839233, -8311415, -25945511, 7480958, -17681669, -8354183,
+             -22545972, 14150565, 15970762, 4099461},
+            {29262576, 16756590, 26350592, -8793563, 8529671, -11208050,
+             13617293, -9937143, 11465739, 8317062},
+        },
+        {
+            {-25493081, -6962928, 32500200, -9419051, -23038724, -2302222,
+             14898637, 3848455, 20969334, -5157516},
+            {-20384450, -14347713, -18336405, 13884722, -33039454, 2842114,
+             -21610826, -3649888, 11177095, 14989547},
+            {-24496721, -11716016, 16959896, 2278463, 12066309, 10137771,
+             13515641, 2581286, -28487508, 9930240},
+        },
+        {
+            {-17751622, -2097826, 16544300, -13009300, -15914807, -14949081,
+             18345767, -13403753, 16291481, -5314038},
+            {-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774,
+             6957617, 4368891, 9788741},
+            {16660756, 7281060, -10830758, 12911820, 20108584, -8101676,
+             -21722536, -8613148, 16250552, -11111103},
+        },
+        {
+            {-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584,
+             10604807, -30190403, 4782747},
+            {-1354539, 14736941, -7367442, -13292886, 7710542, -14155590,
+             -9981571, 4383045, 22546403, 437323},
+            {31665577, -12180464, -16186830, 1491339, -18368625, 3294682,
+             27343084, 2786261, -30633590, -14097016},
+        },
+        {
+            {-14467279, -683715, -33374107, 7448552, 19294360, 14334329,
+             -19690631, 2355319, -19284671, -6114373},
+            {15121312, -15796162, 6377020, -6031361, -10798111, -12957845,
+             18952177, 15496498, -29380133, 11754228},
+            {-2637277, -13483075, 8488727, -14303896, 12728761, -1622493,
+             7141596, 11724556, 22761615, -10134141},
+        },
+        {
+            {16918416, 11729663, -18083579, 3022987, -31015732, -13339659,
+             -28741185, -12227393, 32851222, 11717399},
+            {11166634, 7338049, -6722523, 4531520, -29468672, -7302055,
+             31474879, 3483633, -1193175, -4030831},
+            {-185635, 9921305, 31456609, -13536438, -12013818, 13348923,
+             33142652, 6546660, -19985279, -3948376},
+        },
+        {
+            {-32460596, 11266712, -11197107, -7899103, 31703694, 3855903,
+             -8537131, -12833048, -30772034, -15486313},
+            {-18006477, 12709068, 3991746, -6479188, -21491523, -10550425,
+             -31135347, -16049879, 10928917, 3011958},
+            {-6957757, -15594337, 31696059, 334240, 29576716, 14796075,
+             -30831056, -12805180, 18008031, 10258577},
+        },
+        {
+            {-22448644, 15655569, 7018479, -4410003, -30314266, -1201591,
+             -1853465, 1367120, 25127874, 6671743},
+            {29701166, -14373934, -10878120, 9279288, -17568, 13127210,
+             21382910, 11042292, 25838796, 4642684},
+            {-20430234, 14955537, -24126347, 8124619, -5369288, -5990470,
+             30468147, -13900640, 18423289, 4177476},
+        },
+    },
+};
+
+static uint8_t negative(signed char b) {
+  uint32_t x = b;
+  x >>= 31; /* 1: yes; 0: no */
+  return x;
+}
+
+static void table_select(ge_precomp *t, int pos, signed char b) {
+  ge_precomp minust;
+  uint8_t bnegative = negative(b);
+  uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
+
+  ge_precomp_0(t);
+  cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
+  cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
+  cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
+  cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
+  cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
+  cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
+  cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
+  cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
+  fe_copy(minust.yplusx, t->yminusx);
+  fe_copy(minust.yminusx, t->yplusx);
+  fe_neg(minust.xy2d, t->xy2d);
+  cmov(t, &minust, bnegative);
+}
+
+/* h = a * B
+ * where a = a[0]+256*a[1]+...+256^31 a[31]
+ * B is the Ed25519 base point (x,4/5) with x positive.
+ *
+ * Preconditions:
+ *   a[31] <= 127 */
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
+  signed char e[64];
+  signed char carry;
+  ge_p1p1 r;
+  ge_p2 s;
+  ge_precomp t;
+  int i;
+
+  for (i = 0; i < 32; ++i) {
+    e[2 * i + 0] = (a[i] >> 0) & 15;
+    e[2 * i + 1] = (a[i] >> 4) & 15;
+  }
+  /* each e[i] is between 0 and 15 */
+  /* e[63] is between 0 and 7 */
+
+  carry = 0;
+  for (i = 0; i < 63; ++i) {
+    e[i] += carry;
+    carry = e[i] + 8;
+    carry >>= 4;
+    e[i] -= carry << 4;
+  }
+  e[63] += carry;
+  /* each e[i] is between -8 and 8 */
+
+  ge_p3_0(h);
+  for (i = 1; i < 64; i += 2) {
+    table_select(&t, i / 2, e[i]);
+    ge_madd(&r, h, &t);
+    x25519_ge_p1p1_to_p3(h, &r);
+  }
+
+  ge_p3_dbl(&r, h);
+  x25519_ge_p1p1_to_p2(&s, &r);
+  ge_p2_dbl(&r, &s);
+  x25519_ge_p1p1_to_p2(&s, &r);
+  ge_p2_dbl(&r, &s);
+  x25519_ge_p1p1_to_p2(&s, &r);
+  ge_p2_dbl(&r, &s);
+  x25519_ge_p1p1_to_p3(h, &r);
+
+  for (i = 0; i < 64; i += 2) {
+    table_select(&t, i / 2, e[i]);
+    ge_madd(&r, h, &t);
+    x25519_ge_p1p1_to_p3(h, &r);
+  }
+}
+
+#endif
+
+static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
+  fe_cmov(t->YplusX, u->YplusX, b);
+  fe_cmov(t->YminusX, u->YminusX, b);
+  fe_cmov(t->Z, u->Z, b);
+  fe_cmov(t->T2d, u->T2d, b);
+}
+
+/* r = scalar * A.
+ * where a = a[0]+256*a[1]+...+256^31 a[31]. */
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) {
+  ge_p2 Ai_p2[8];
+  ge_cached Ai[16];
+  ge_p1p1 t;
+
+  ge_cached_0(&Ai[0]);
+  x25519_ge_p3_to_cached(&Ai[1], A);
+  ge_p3_to_p2(&Ai_p2[1], A);
+
+  unsigned i;
+  for (i = 2; i < 16; i += 2) {
+    ge_p2_dbl(&t, &Ai_p2[i / 2]);
+    ge_p1p1_to_cached(&Ai[i], &t);
+    if (i < 8) {
+      x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
+    }
+    x25519_ge_add(&t, A, &Ai[i]);
+    ge_p1p1_to_cached(&Ai[i + 1], &t);
+    if (i < 7) {
+      x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
+    }
+  }
+
+  ge_p2_0(r);
+  ge_p3 u;
+
+  for (i = 0; i < 256; i += 4) {
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p3(&u, &t);
+
+    uint8_t index = scalar[31 - i/8];
+    index >>= 4 - (i & 4);
+    index &= 0xf;
+
+    unsigned j;
+    ge_cached selected;
+    ge_cached_0(&selected);
+    for (j = 0; j < 16; j++) {
+      cmov_cached(&selected, &Ai[j], equal(j, index));
+    }
+
+    x25519_ge_add(&t, &u, &selected);
+    x25519_ge_p1p1_to_p2(r, &t);
+  }
+}
+
+static void slide(signed char *r, const uint8_t *a) {
+  int i;
+  int b;
+  int k;
+
+  for (i = 0; i < 256; ++i) {
+    r[i] = 1 & (a[i >> 3] >> (i & 7));
+  }
+
+  for (i = 0; i < 256; ++i) {
+    if (r[i]) {
+      for (b = 1; b <= 6 && i + b < 256; ++b) {
+        if (r[i + b]) {
+          if (r[i] + (r[i + b] << b) <= 15) {
+            r[i] += r[i + b] << b;
+            r[i + b] = 0;
+          } else if (r[i] - (r[i + b] << b) >= -15) {
+            r[i] -= r[i + b] << b;
+            for (k = i + b; k < 256; ++k) {
+              if (!r[k]) {
+                r[k] = 1;
+                break;
+              }
+              r[k] = 0;
+            }
+          } else {
+            break;
+          }
+        }
+      }
+    }
+  }
+}
+
+static const ge_precomp Bi[8] = {
+    {
+        {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
+         -11754271, -6079156, 2047605},
+        {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
+         5043384, 19500929, -15469378},
+        {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919,
+         11864899, -24514362, -4438546},
+    },
+    {
+        {15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600,
+         -14772189, 28944400, -1550024},
+        {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577,
+         -11775962, 7689662, 11199574},
+        {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774,
+         10017326, -17749093, -9920357},
+    },
+    {
+        {10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885,
+         14515107, -15438304, 10819380},
+        {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
+         12483688, -12668491, 5581306},
+        {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350,
+         13850243, -23678021, -15815942},
+    },
+    {
+        {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
+         5230134, -23952439, -15175766},
+        {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025,
+         16520125, 30598449, 7715701},
+        {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660,
+         1370708, 29794553, -1409300},
+    },
+    {
+        {-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211,
+         -1361450, -13062696, 13821877},
+        {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028,
+         -7212327, 18853322, -14220951},
+        {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358,
+         -10431137, 2207753, -3209784},
+    },
+    {
+        {-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364,
+         -663000, -31111463, -16132436},
+        {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789,
+         15725684, 171356, 6466918},
+        {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339,
+         -14088058, -30714912, 16193877},
+    },
+    {
+        {-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398,
+         4729455, -18074513, 9256800},
+        {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405,
+         9761698, -19827198, 630305},
+        {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551,
+         -15960994, -2449256, -14291300},
+    },
+    {
+        {-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575,
+         15033784, 25105118, -7894876},
+        {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925,
+         1573892, -2625887, 2198790, -15804619},
+        {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022,
+         -16236442, -32461234, -12290683},
+    },
+};
+
+/* r = a * A + b * B
+ * where a = a[0]+256*a[1]+...+256^31 a[31].
+ * and b = b[0]+256*b[1]+...+256^31 b[31].
+ * B is the Ed25519 base point (x,4/5) with x positive. */
+static void
+ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
+    const ge_p3 *A, const uint8_t *b) {
+  signed char aslide[256];
+  signed char bslide[256];
+  ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
+  ge_p1p1 t;
+  ge_p3 u;
+  ge_p3 A2;
+  int i;
+
+  slide(aslide, a);
+  slide(bslide, b);
+
+  x25519_ge_p3_to_cached(&Ai[0], A);
+  ge_p3_dbl(&t, A);
+  x25519_ge_p1p1_to_p3(&A2, &t);
+  x25519_ge_add(&t, &A2, &Ai[0]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[1], &u);
+  x25519_ge_add(&t, &A2, &Ai[1]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[2], &u);
+  x25519_ge_add(&t, &A2, &Ai[2]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[3], &u);
+  x25519_ge_add(&t, &A2, &Ai[3]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[4], &u);
+  x25519_ge_add(&t, &A2, &Ai[4]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[5], &u);
+  x25519_ge_add(&t, &A2, &Ai[5]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[6], &u);
+  x25519_ge_add(&t, &A2, &Ai[6]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[7], &u);
+
+  ge_p2_0(r);
+
+  for (i = 255; i >= 0; --i) {
+    if (aslide[i] || bslide[i]) {
+      break;
+    }
+  }
+
+  for (; i >= 0; --i) {
+    ge_p2_dbl(&t, r);
+
+    if (aslide[i] > 0) {
+      x25519_ge_p1p1_to_p3(&u, &t);
+      x25519_ge_add(&t, &u, &Ai[aslide[i] / 2]);
+    } else if (aslide[i] < 0) {
+      x25519_ge_p1p1_to_p3(&u, &t);
+      x25519_ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+    }
+
+    if (bslide[i] > 0) {
+      x25519_ge_p1p1_to_p3(&u, &t);
+      ge_madd(&t, &u, &Bi[bslide[i] / 2]);
+    } else if (bslide[i] < 0) {
+      x25519_ge_p1p1_to_p3(&u, &t);
+      ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
+    }
+
+    x25519_ge_p1p1_to_p2(r, &t);
+  }
+}
+
+/* The set of scalars is \Z/l
+ * where l = 2^252 + 27742317777372353535851937790883648493. */
+
+/* Input:
+ *   s[0]+256*s[1]+...+256^63*s[63] = s
+ *
+ * Output:
+ *   s[0]+256*s[1]+...+256^31*s[31] = s mod l
+ *   where l = 2^252 + 27742317777372353535851937790883648493.
+ *   Overwrites s in place. */
+void
+x25519_sc_reduce(uint8_t *s) {
+  int64_t s0 = 2097151 & load_3(s);
+  int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
+  int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
+  int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
+  int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
+  int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
+  int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
+  int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
+  int64_t s8 = 2097151 & load_3(s + 21);
+  int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
+  int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
+  int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
+  int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
+  int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
+  int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
+  int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
+  int64_t s16 = 2097151 & load_3(s + 42);
+  int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
+  int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
+  int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
+  int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
+  int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
+  int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
+  int64_t s23 = (load_4(s + 60) >> 3);
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+  int64_t carry10;
+  int64_t carry11;
+  int64_t carry12;
+  int64_t carry13;
+  int64_t carry14;
+  int64_t carry15;
+  int64_t carry16;
+
+  s11 += s23 * 666643;
+  s12 += s23 * 470296;
+  s13 += s23 * 654183;
+  s14 -= s23 * 997805;
+  s15 += s23 * 136657;
+  s16 -= s23 * 683901;
+  s23 = 0;
+
+  s10 += s22 * 666643;
+  s11 += s22 * 470296;
+  s12 += s22 * 654183;
+  s13 -= s22 * 997805;
+  s14 += s22 * 136657;
+  s15 -= s22 * 683901;
+  s22 = 0;
+
+  s9 += s21 * 666643;
+  s10 += s21 * 470296;
+  s11 += s21 * 654183;
+  s12 -= s21 * 997805;
+  s13 += s21 * 136657;
+  s14 -= s21 * 683901;
+  s21 = 0;
+
+  s8 += s20 * 666643;
+  s9 += s20 * 470296;
+  s10 += s20 * 654183;
+  s11 -= s20 * 997805;
+  s12 += s20 * 136657;
+  s13 -= s20 * 683901;
+  s20 = 0;
+
+  s7 += s19 * 666643;
+  s8 += s19 * 470296;
+  s9 += s19 * 654183;
+  s10 -= s19 * 997805;
+  s11 += s19 * 136657;
+  s12 -= s19 * 683901;
+  s19 = 0;
+
+  s6 += s18 * 666643;
+  s7 += s18 * 470296;
+  s8 += s18 * 654183;
+  s9 -= s18 * 997805;
+  s10 += s18 * 136657;
+  s11 -= s18 * 683901;
+  s18 = 0;
+
+  carry6 = (s6 + (1 << 20)) >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry8 = (s8 + (1 << 20)) >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry10 = (s10 + (1 << 20)) >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+  carry12 = (s12 + (1 << 20)) >> 21;
+  s13 += carry12;
+  s12 -= carry12 << 21;
+  carry14 = (s14 + (1 << 20)) >> 21;
+  s15 += carry14;
+  s14 -= carry14 << 21;
+  carry16 = (s16 + (1 << 20)) >> 21;
+  s17 += carry16;
+  s16 -= carry16 << 21;
+
+  carry7 = (s7 + (1 << 20)) >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry9 = (s9 + (1 << 20)) >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry11 = (s11 + (1 << 20)) >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+  carry13 = (s13 + (1 << 20)) >> 21;
+  s14 += carry13;
+  s13 -= carry13 << 21;
+  carry15 = (s15 + (1 << 20)) >> 21;
+  s16 += carry15;
+  s15 -= carry15 << 21;
+
+  s5 += s17 * 666643;
+  s6 += s17 * 470296;
+  s7 += s17 * 654183;
+  s8 -= s17 * 997805;
+  s9 += s17 * 136657;
+  s10 -= s17 * 683901;
+  s17 = 0;
+
+  s4 += s16 * 666643;
+  s5 += s16 * 470296;
+  s6 += s16 * 654183;
+  s7 -= s16 * 997805;
+  s8 += s16 * 136657;
+  s9 -= s16 * 683901;
+  s16 = 0;
+
+  s3 += s15 * 666643;
+  s4 += s15 * 470296;
+  s5 += s15 * 654183;
+  s6 -= s15 * 997805;
+  s7 += s15 * 136657;
+  s8 -= s15 * 683901;
+  s15 = 0;
+
+  s2 += s14 * 666643;
+  s3 += s14 * 470296;
+  s4 += s14 * 654183;
+  s5 -= s14 * 997805;
+  s6 += s14 * 136657;
+  s7 -= s14 * 683901;
+  s14 = 0;
+
+  s1 += s13 * 666643;
+  s2 += s13 * 470296;
+  s3 += s13 * 654183;
+  s4 -= s13 * 997805;
+  s5 += s13 * 136657;
+  s6 -= s13 * 683901;
+  s13 = 0;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = (s0 + (1 << 20)) >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry2 = (s2 + (1 << 20)) >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry4 = (s4 + (1 << 20)) >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry6 = (s6 + (1 << 20)) >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry8 = (s8 + (1 << 20)) >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry10 = (s10 + (1 << 20)) >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+
+  carry1 = (s1 + (1 << 20)) >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry3 = (s3 + (1 << 20)) >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry5 = (s5 + (1 << 20)) >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry7 = (s7 + (1 << 20)) >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry9 = (s9 + (1 << 20)) >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry11 = (s11 + (1 << 20)) >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = s0 >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry1 = s1 >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry2 = s2 >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry3 = s3 >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry4 = s4 >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry5 = s5 >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry6 = s6 >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry7 = s7 >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry8 = s8 >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry9 = s9 >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry10 = s10 >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+  carry11 = s11 >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = s0 >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry1 = s1 >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry2 = s2 >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry3 = s3 >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry4 = s4 >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry5 = s5 >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry6 = s6 >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry7 = s7 >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry8 = s8 >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry9 = s9 >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry10 = s10 >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+
+  s[0] = s0 >> 0;
+  s[1] = s0 >> 8;
+  s[2] = (s0 >> 16) | (s1 << 5);
+  s[3] = s1 >> 3;
+  s[4] = s1 >> 11;
+  s[5] = (s1 >> 19) | (s2 << 2);
+  s[6] = s2 >> 6;
+  s[7] = (s2 >> 14) | (s3 << 7);
+  s[8] = s3 >> 1;
+  s[9] = s3 >> 9;
+  s[10] = (s3 >> 17) | (s4 << 4);
+  s[11] = s4 >> 4;
+  s[12] = s4 >> 12;
+  s[13] = (s4 >> 20) | (s5 << 1);
+  s[14] = s5 >> 7;
+  s[15] = (s5 >> 15) | (s6 << 6);
+  s[16] = s6 >> 2;
+  s[17] = s6 >> 10;
+  s[18] = (s6 >> 18) | (s7 << 3);
+  s[19] = s7 >> 5;
+  s[20] = s7 >> 13;
+  s[21] = s8 >> 0;
+  s[22] = s8 >> 8;
+  s[23] = (s8 >> 16) | (s9 << 5);
+  s[24] = s9 >> 3;
+  s[25] = s9 >> 11;
+  s[26] = (s9 >> 19) | (s10 << 2);
+  s[27] = s10 >> 6;
+  s[28] = (s10 >> 14) | (s11 << 7);
+  s[29] = s11 >> 1;
+  s[30] = s11 >> 9;
+  s[31] = s11 >> 17;
+}
+
+/* Input:
+ *   a[0]+256*a[1]+...+256^31*a[31] = a
+ *   b[0]+256*b[1]+...+256^31*b[31] = b
+ *   c[0]+256*c[1]+...+256^31*c[31] = c
+ *
+ * Output:
+ *   s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
+ *   where l = 2^252 + 27742317777372353535851937790883648493. */
+static void
+sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
+    const uint8_t *c)
+{
+  int64_t a0 = 2097151 & load_3(a);
+  int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
+  int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
+  int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
+  int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
+  int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
+  int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
+  int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
+  int64_t a8 = 2097151 & load_3(a + 21);
+  int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
+  int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
+  int64_t a11 = (load_4(a + 28) >> 7);
+  int64_t b0 = 2097151 & load_3(b);
+  int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
+  int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
+  int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
+  int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
+  int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
+  int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
+  int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
+  int64_t b8 = 2097151 & load_3(b + 21);
+  int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
+  int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
+  int64_t b11 = (load_4(b + 28) >> 7);
+  int64_t c0 = 2097151 & load_3(c);
+  int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
+  int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
+  int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
+  int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
+  int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
+  int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
+  int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
+  int64_t c8 = 2097151 & load_3(c + 21);
+  int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
+  int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
+  int64_t c11 = (load_4(c + 28) >> 7);
+  int64_t s0;
+  int64_t s1;
+  int64_t s2;
+  int64_t s3;
+  int64_t s4;
+  int64_t s5;
+  int64_t s6;
+  int64_t s7;
+  int64_t s8;
+  int64_t s9;
+  int64_t s10;
+  int64_t s11;
+  int64_t s12;
+  int64_t s13;
+  int64_t s14;
+  int64_t s15;
+  int64_t s16;
+  int64_t s17;
+  int64_t s18;
+  int64_t s19;
+  int64_t s20;
+  int64_t s21;
+  int64_t s22;
+  int64_t s23;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+  int64_t carry10;
+  int64_t carry11;
+  int64_t carry12;
+  int64_t carry13;
+  int64_t carry14;
+  int64_t carry15;
+  int64_t carry16;
+  int64_t carry17;
+  int64_t carry18;
+  int64_t carry19;
+  int64_t carry20;
+  int64_t carry21;
+  int64_t carry22;
+
+  s0 = c0 + a0 * b0;
+  s1 = c1 + a0 * b1 + a1 * b0;
+  s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
+  s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
+  s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
+  s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
+  s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
+  s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
+       a6 * b1 + a7 * b0;
+  s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
+       a6 * b2 + a7 * b1 + a8 * b0;
+  s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
+       a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
+  s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
+        a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
+  s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
+        a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
+  s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 +
+        a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
+  s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 +
+        a9 * b4 + a10 * b3 + a11 * b2;
+  s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 +
+        a10 * b4 + a11 * b3;
+  s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 +
+        a11 * b4;
+  s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
+  s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
+  s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
+  s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
+  s20 = a9 * b11 + a10 * b10 + a11 * b9;
+  s21 = a10 * b11 + a11 * b10;
+  s22 = a11 * b11;
+  s23 = 0;
+
+  carry0 = (s0 + (1 << 20)) >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry2 = (s2 + (1 << 20)) >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry4 = (s4 + (1 << 20)) >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry6 = (s6 + (1 << 20)) >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry8 = (s8 + (1 << 20)) >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry10 = (s10 + (1 << 20)) >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+  carry12 = (s12 + (1 << 20)) >> 21;
+  s13 += carry12;
+  s12 -= carry12 << 21;
+  carry14 = (s14 + (1 << 20)) >> 21;
+  s15 += carry14;
+  s14 -= carry14 << 21;
+  carry16 = (s16 + (1 << 20)) >> 21;
+  s17 += carry16;
+  s16 -= carry16 << 21;
+  carry18 = (s18 + (1 << 20)) >> 21;
+  s19 += carry18;
+  s18 -= carry18 << 21;
+  carry20 = (s20 + (1 << 20)) >> 21;
+  s21 += carry20;
+  s20 -= carry20 << 21;
+  carry22 = (s22 + (1 << 20)) >> 21;
+  s23 += carry22;
+  s22 -= carry22 << 21;
+
+  carry1 = (s1 + (1 << 20)) >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry3 = (s3 + (1 << 20)) >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry5 = (s5 + (1 << 20)) >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry7 = (s7 + (1 << 20)) >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry9 = (s9 + (1 << 20)) >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry11 = (s11 + (1 << 20)) >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+  carry13 = (s13 + (1 << 20)) >> 21;
+  s14 += carry13;
+  s13 -= carry13 << 21;
+  carry15 = (s15 + (1 << 20)) >> 21;
+  s16 += carry15;
+  s15 -= carry15 << 21;
+  carry17 = (s17 + (1 << 20)) >> 21;
+  s18 += carry17;
+  s17 -= carry17 << 21;
+  carry19 = (s19 + (1 << 20)) >> 21;
+  s20 += carry19;
+  s19 -= carry19 << 21;
+  carry21 = (s21 + (1 << 20)) >> 21;
+  s22 += carry21;
+  s21 -= carry21 << 21;
+
+  s11 += s23 * 666643;
+  s12 += s23 * 470296;
+  s13 += s23 * 654183;
+  s14 -= s23 * 997805;
+  s15 += s23 * 136657;
+  s16 -= s23 * 683901;
+  s23 = 0;
+
+  s10 += s22 * 666643;
+  s11 += s22 * 470296;
+  s12 += s22 * 654183;
+  s13 -= s22 * 997805;
+  s14 += s22 * 136657;
+  s15 -= s22 * 683901;
+  s22 = 0;
+
+  s9 += s21 * 666643;
+  s10 += s21 * 470296;
+  s11 += s21 * 654183;
+  s12 -= s21 * 997805;
+  s13 += s21 * 136657;
+  s14 -= s21 * 683901;
+  s21 = 0;
+
+  s8 += s20 * 666643;
+  s9 += s20 * 470296;
+  s10 += s20 * 654183;
+  s11 -= s20 * 997805;
+  s12 += s20 * 136657;
+  s13 -= s20 * 683901;
+  s20 = 0;
+
+  s7 += s19 * 666643;
+  s8 += s19 * 470296;
+  s9 += s19 * 654183;
+  s10 -= s19 * 997805;
+  s11 += s19 * 136657;
+  s12 -= s19 * 683901;
+  s19 = 0;
+
+  s6 += s18 * 666643;
+  s7 += s18 * 470296;
+  s8 += s18 * 654183;
+  s9 -= s18 * 997805;
+  s10 += s18 * 136657;
+  s11 -= s18 * 683901;
+  s18 = 0;
+
+  carry6 = (s6 + (1 << 20)) >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry8 = (s8 + (1 << 20)) >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry10 = (s10 + (1 << 20)) >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+  carry12 = (s12 + (1 << 20)) >> 21;
+  s13 += carry12;
+  s12 -= carry12 << 21;
+  carry14 = (s14 + (1 << 20)) >> 21;
+  s15 += carry14;
+  s14 -= carry14 << 21;
+  carry16 = (s16 + (1 << 20)) >> 21;
+  s17 += carry16;
+  s16 -= carry16 << 21;
+
+  carry7 = (s7 + (1 << 20)) >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry9 = (s9 + (1 << 20)) >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry11 = (s11 + (1 << 20)) >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+  carry13 = (s13 + (1 << 20)) >> 21;
+  s14 += carry13;
+  s13 -= carry13 << 21;
+  carry15 = (s15 + (1 << 20)) >> 21;
+  s16 += carry15;
+  s15 -= carry15 << 21;
+
+  s5 += s17 * 666643;
+  s6 += s17 * 470296;
+  s7 += s17 * 654183;
+  s8 -= s17 * 997805;
+  s9 += s17 * 136657;
+  s10 -= s17 * 683901;
+  s17 = 0;
+
+  s4 += s16 * 666643;
+  s5 += s16 * 470296;
+  s6 += s16 * 654183;
+  s7 -= s16 * 997805;
+  s8 += s16 * 136657;
+  s9 -= s16 * 683901;
+  s16 = 0;
+
+  s3 += s15 * 666643;
+  s4 += s15 * 470296;
+  s5 += s15 * 654183;
+  s6 -= s15 * 997805;
+  s7 += s15 * 136657;
+  s8 -= s15 * 683901;
+  s15 = 0;
+
+  s2 += s14 * 666643;
+  s3 += s14 * 470296;
+  s4 += s14 * 654183;
+  s5 -= s14 * 997805;
+  s6 += s14 * 136657;
+  s7 -= s14 * 683901;
+  s14 = 0;
+
+  s1 += s13 * 666643;
+  s2 += s13 * 470296;
+  s3 += s13 * 654183;
+  s4 -= s13 * 997805;
+  s5 += s13 * 136657;
+  s6 -= s13 * 683901;
+  s13 = 0;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = (s0 + (1 << 20)) >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry2 = (s2 + (1 << 20)) >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry4 = (s4 + (1 << 20)) >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry6 = (s6 + (1 << 20)) >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry8 = (s8 + (1 << 20)) >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry10 = (s10 + (1 << 20)) >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+
+  carry1 = (s1 + (1 << 20)) >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry3 = (s3 + (1 << 20)) >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry5 = (s5 + (1 << 20)) >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry7 = (s7 + (1 << 20)) >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry9 = (s9 + (1 << 20)) >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry11 = (s11 + (1 << 20)) >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = s0 >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry1 = s1 >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry2 = s2 >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry3 = s3 >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry4 = s4 >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry5 = s5 >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry6 = s6 >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry7 = s7 >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry8 = s8 >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry9 = s9 >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry10 = s10 >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+  carry11 = s11 >> 21;
+  s12 += carry11;
+  s11 -= carry11 << 21;
+
+  s0 += s12 * 666643;
+  s1 += s12 * 470296;
+  s2 += s12 * 654183;
+  s3 -= s12 * 997805;
+  s4 += s12 * 136657;
+  s5 -= s12 * 683901;
+  s12 = 0;
+
+  carry0 = s0 >> 21;
+  s1 += carry0;
+  s0 -= carry0 << 21;
+  carry1 = s1 >> 21;
+  s2 += carry1;
+  s1 -= carry1 << 21;
+  carry2 = s2 >> 21;
+  s3 += carry2;
+  s2 -= carry2 << 21;
+  carry3 = s3 >> 21;
+  s4 += carry3;
+  s3 -= carry3 << 21;
+  carry4 = s4 >> 21;
+  s5 += carry4;
+  s4 -= carry4 << 21;
+  carry5 = s5 >> 21;
+  s6 += carry5;
+  s5 -= carry5 << 21;
+  carry6 = s6 >> 21;
+  s7 += carry6;
+  s6 -= carry6 << 21;
+  carry7 = s7 >> 21;
+  s8 += carry7;
+  s7 -= carry7 << 21;
+  carry8 = s8 >> 21;
+  s9 += carry8;
+  s8 -= carry8 << 21;
+  carry9 = s9 >> 21;
+  s10 += carry9;
+  s9 -= carry9 << 21;
+  carry10 = s10 >> 21;
+  s11 += carry10;
+  s10 -= carry10 << 21;
+
+  s[0] = s0 >> 0;
+  s[1] = s0 >> 8;
+  s[2] = (s0 >> 16) | (s1 << 5);
+  s[3] = s1 >> 3;
+  s[4] = s1 >> 11;
+  s[5] = (s1 >> 19) | (s2 << 2);
+  s[6] = s2 >> 6;
+  s[7] = (s2 >> 14) | (s3 << 7);
+  s[8] = s3 >> 1;
+  s[9] = s3 >> 9;
+  s[10] = (s3 >> 17) | (s4 << 4);
+  s[11] = s4 >> 4;
+  s[12] = s4 >> 12;
+  s[13] = (s4 >> 20) | (s5 << 1);
+  s[14] = s5 >> 7;
+  s[15] = (s5 >> 15) | (s6 << 6);
+  s[16] = s6 >> 2;
+  s[17] = s6 >> 10;
+  s[18] = (s6 >> 18) | (s7 << 3);
+  s[19] = s7 >> 5;
+  s[20] = s7 >> 13;
+  s[21] = s8 >> 0;
+  s[22] = s8 >> 8;
+  s[23] = (s8 >> 16) | (s9 << 5);
+  s[24] = s9 >> 3;
+  s[25] = s9 >> 11;
+  s[26] = (s9 >> 19) | (s10 << 2);
+  s[27] = s10 >> 6;
+  s[28] = (s10 >> 14) | (s11 << 7);
+  s[29] = s11 >> 1;
+  s[30] = s11 >> 9;
+  s[31] = s11 >> 17;
+}
+
+void ED25519_public_from_private(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH],
+    const uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH]) {
+  uint8_t az[SHA512_DIGEST_LENGTH];
+  SHA512(private_key, 32, az);
+
+  az[0] &= 248;
+  az[31] &= 63;
+  az[31] |= 64;
+
+  ge_p3 A;
+  x25519_ge_scalarmult_base(&A, az);
+  ge_p3_tobytes(out_public_key, &A);
+}
+
+void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH],
+    uint8_t out_private_key[ED25519_PRIVATE_KEY_LENGTH]) {
+  arc4random_buf(out_private_key, 32);
+
+  ED25519_public_from_private(out_public_key, out_private_key);
+}
+LCRYPTO_ALIAS(ED25519_keypair);
+
+int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
+    const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH],
+    const uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH]) {
+  uint8_t az[SHA512_DIGEST_LENGTH];
+  SHA512(private_key, 32, az);
+
+  az[0] &= 248;
+  az[31] &= 63;
+  az[31] |= 64;
+
+  SHA512_CTX hash_ctx;
+  SHA512_Init(&hash_ctx);
+  SHA512_Update(&hash_ctx, az + 32, 32);
+  SHA512_Update(&hash_ctx, message, message_len);
+  uint8_t nonce[SHA512_DIGEST_LENGTH];
+  SHA512_Final(nonce, &hash_ctx);
+
+  x25519_sc_reduce(nonce);
+  ge_p3 R;
+  x25519_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);
+  uint8_t hram[SHA512_DIGEST_LENGTH];
+  SHA512_Final(hram, &hash_ctx);
+
+  x25519_sc_reduce(hram);
+  sc_muladd(out_sig + 32, hram, az, nonce);
+
+  return 1;
+}
+LCRYPTO_ALIAS(ED25519_sign);
+
+/*
+ * Little endian representation of the order of edwards25519,
+ * see https://www.rfc-editor.org/rfc/rfc7748#section-4.1
+ */
+static const uint8_t order[] = {
+  0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
+  0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+};
+
+int ED25519_verify(const uint8_t *message, size_t message_len,
+    const uint8_t signature[ED25519_SIGNATURE_LENGTH],
+    const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]) {
+  ge_p3 A;
+  int i;
+  if ((signature[63] & 224) != 0 ||
+      x25519_ge_frombytes_vartime(&A, public_key) != 0) {
+    return 0;
+  }
+
+  fe_neg(A.X, A.X);
+  fe_neg(A.T, A.T);
+
+  uint8_t pkcopy[32];
+  memcpy(pkcopy, public_key, 32);
+  uint8_t rcopy[32];
+  memcpy(rcopy, signature, 32);
+  uint8_t scopy[32];
+  memcpy(scopy, signature + 32, 32);
+
+  /*
+   * https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that scopy be
+   * in the range [0, order) to prevent signature malleability. This value is
+   * public, so there is no need to make this constant time.
+   */
+  for (i = 31; i >= 0; i--) {
+    if (scopy[i] > order[i])
+      return 0;
+    if (scopy[i] < order[i])
+      break;
+    if (i == 0)
+      return 0;
+  }
+
+  SHA512_CTX hash_ctx;
+  SHA512_Init(&hash_ctx);
+  SHA512_Update(&hash_ctx, signature, 32);
+  SHA512_Update(&hash_ctx, public_key, 32);
+  SHA512_Update(&hash_ctx, message, message_len);
+  uint8_t h[SHA512_DIGEST_LENGTH];
+  SHA512_Final(h, &hash_ctx);
+
+  x25519_sc_reduce(h);
+
+  ge_p2 R;
+  ge_double_scalarmult_vartime(&R, h, &A, scopy);
+
+  uint8_t rcheck[32];
+  x25519_ge_tobytes(rcheck, &R);
+
+  return timingsafe_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
+}
+LCRYPTO_ALIAS(ED25519_verify);
+
+/* Replace (f,g) with (g,f) if b == 1;
+ * replace (f,g) with (f,g) if b == 0.
+ *
+ * Preconditions: b in {0,1}. */
+static void fe_cswap(fe f, fe g, unsigned int b) {
+  b = 0-b;
+  unsigned i;
+  for (i = 0; i < 10; i++) {
+    int32_t x = f[i] ^ g[i];
+    x &= b;
+    f[i] ^= x;
+    g[i] ^= x;
+  }
+}
+
+/* h = f * 121666
+ * Can overlap h with f.
+ *
+ * Preconditions:
+ *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
+ *
+ * Postconditions:
+ *    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */
+static void fe_mul121666(fe h, fe f) {
+  int32_t f0 = f[0];
+  int32_t f1 = f[1];
+  int32_t f2 = f[2];
+  int32_t f3 = f[3];
+  int32_t f4 = f[4];
+  int32_t f5 = f[5];
+  int32_t f6 = f[6];
+  int32_t f7 = f[7];
+  int32_t f8 = f[8];
+  int32_t f9 = f[9];
+  int64_t h0 = f0 * (int64_t) 121666;
+  int64_t h1 = f1 * (int64_t) 121666;
+  int64_t h2 = f2 * (int64_t) 121666;
+  int64_t h3 = f3 * (int64_t) 121666;
+  int64_t h4 = f4 * (int64_t) 121666;
+  int64_t h5 = f5 * (int64_t) 121666;
+  int64_t h6 = f6 * (int64_t) 121666;
+  int64_t h7 = f7 * (int64_t) 121666;
+  int64_t h8 = f8 * (int64_t) 121666;
+  int64_t h9 = f9 * (int64_t) 121666;
+  int64_t carry0;
+  int64_t carry1;
+  int64_t carry2;
+  int64_t carry3;
+  int64_t carry4;
+  int64_t carry5;
+  int64_t carry6;
+  int64_t carry7;
+  int64_t carry8;
+  int64_t carry9;
+
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
+
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
+
+  h[0] = h0;
+  h[1] = h1;
+  h[2] = h2;
+  h[3] = h3;
+  h[4] = h4;
+  h[5] = h5;
+  h[6] = h6;
+  h[7] = h7;
+  h[8] = h8;
+  h[9] = h9;
+}
+
+void
+x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32],
+    const uint8_t point[32]) {
+  fe x1, x2, z2, x3, z3, tmp0, tmp1;
+
+  uint8_t e[32];
+  memcpy(e, scalar, 32);
+  e[0] &= 248;
+  e[31] &= 127;
+  e[31] |= 64;
+  fe_frombytes(x1, point);
+  fe_1(x2);
+  fe_0(z2);
+  fe_copy(x3, x1);
+  fe_1(z3);
+
+  unsigned swap = 0;
+  int pos;
+  for (pos = 254; pos >= 0; --pos) {
+    unsigned b = 1 & (e[pos / 8] >> (pos & 7));
+    swap ^= b;
+    fe_cswap(x2, x3, swap);
+    fe_cswap(z2, z3, swap);
+    swap = b;
+    fe_sub(tmp0, x3, z3);
+    fe_sub(tmp1, x2, z2);
+    fe_add(x2, x2, z2);
+    fe_add(z2, x3, z3);
+    fe_mul(z3, tmp0, x2);
+    fe_mul(z2, z2, tmp1);
+    fe_sq(tmp0, tmp1);
+    fe_sq(tmp1, x2);
+    fe_add(x3, z3, z2);
+    fe_sub(z2, z3, z2);
+    fe_mul(x2, tmp1, tmp0);
+    fe_sub(tmp1, tmp1, tmp0);
+    fe_sq(z2, z2);
+    fe_mul121666(z3, tmp1);
+    fe_sq(x3, x3);
+    fe_add(tmp0, tmp0, z3);
+    fe_mul(z3, x1, z2);
+    fe_mul(z2, tmp1, tmp0);
+  }
+  fe_cswap(x2, x3, swap);
+  fe_cswap(z2, z3, swap);
+
+  fe_invert(z2, z2);
+  fe_mul(x2, x2, z2);
+  fe_tobytes(out, x2);
+}
+
+#ifdef unused
+void
+x25519_public_from_private_generic(uint8_t out_public_key[32],
+    const uint8_t private_key[32])
+{
+  uint8_t e[32];
+
+  memcpy(e, private_key, 32);
+  e[0] &= 248;
+  e[31] &= 127;
+  e[31] |= 64;
+
+  ge_p3 A;
+  x25519_ge_scalarmult_base(&A, e);
+
+  /* We only need the u-coordinate of the curve25519 point. The map is
+   * u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
+  fe zplusy, zminusy, zminusy_inv;
+  fe_add(zplusy, A.Z, A.Y);
+  fe_sub(zminusy, A.Z, A.Y);
+  fe_invert(zminusy_inv, zminusy);
+  fe_mul(zplusy, zplusy, zminusy_inv);
+  fe_tobytes(out_public_key, zplusy);
+}
+#endif
+
+void
+X25519_public_from_private(uint8_t out_public_key[X25519_KEY_LENGTH],
+    const uint8_t private_key[X25519_KEY_LENGTH])
+{
+  static const uint8_t kMongomeryBasePoint[32] = {9};
+
+  x25519_scalar_mult(out_public_key, private_key, kMongomeryBasePoint);
+}
+
+void
+X25519_keypair(uint8_t out_public_key[X25519_KEY_LENGTH],
+    uint8_t out_private_key[X25519_KEY_LENGTH])
+{
+  /* All X25519 implementations should decode scalars correctly (see
+   * https://tools.ietf.org/html/rfc7748#section-5). However, if an
+   * implementation doesn't then it might interoperate with random keys a
+   * fraction of the time because they'll, randomly, happen to be correctly
+   * formed.
+   *
+   * Thus we do the opposite of the masking here to make sure that our private
+   * keys are never correctly masked and so, hopefully, any incorrect
+   * implementations are deterministically broken.
+   *
+   * This does not affect security because, although we're throwing away
+   * entropy, a valid implementation of scalarmult should throw away the exact
+   * same bits anyway. */
+  arc4random_buf(out_private_key, 32);
+
+  out_private_key[0] |= 7;
+  out_private_key[31] &= 63;
+  out_private_key[31] |= 128;
+
+  X25519_public_from_private(out_public_key, out_private_key);
+}
+LCRYPTO_ALIAS(X25519_keypair);
+
+int
+X25519(uint8_t out_shared_key[X25519_KEY_LENGTH],
+    const uint8_t private_key[X25519_KEY_LENGTH],
+    const uint8_t peer_public_key[X25519_KEY_LENGTH])
+{
+  static const uint8_t kZeros[32] = {0};
+
+  x25519_scalar_mult(out_shared_key, private_key, peer_public_key);
+
+  /* The all-zero output results when the input is a point of small order. */
+  return timingsafe_memcmp(kZeros, out_shared_key, 32) != 0;
+}
+LCRYPTO_ALIAS(X25519);
diff --git a/crypto/curve25519/curve25519_internal.h b/crypto/curve25519/curve25519_internal.h
new file mode 100644
index 0000000..abfaaaf
--- /dev/null
+++ b/crypto/curve25519/curve25519_internal.h
@@ -0,0 +1,105 @@
+/*	$OpenBSD: curve25519_internal.h,v 1.6 2022/11/09 17:45:55 jsing Exp $ */
+/*
+ * Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef HEADER_CURVE25519_INTERNAL_H
+#define HEADER_CURVE25519_INTERNAL_H
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+ * context.  */
+typedef int32_t fe[10];
+
+/* ge means group element.
+
+ * Here the group is the set of pairs (x,y) of field elements (see fe.h)
+ * satisfying -x^2 + y^2 = 1 + d x^2y^2
+ * where d = -121665/121666.
+ *
+ * Representations:
+ *   ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ *   ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ *   ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ *   ge_precomp (Duif): (y+x,y-x,2dxy) */
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+} ge_p2;
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+  fe T;
+} ge_p3;
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+  fe T;
+} ge_p1p1;
+
+typedef struct {
+  fe yplusx;
+  fe yminusx;
+  fe xy2d;
+} ge_precomp;
+
+typedef struct {
+  fe YplusX;
+  fe YminusX;
+  fe Z;
+  fe T2d;
+} ge_cached;
+
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h);
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s);
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_scalarmult_small_precomp(ge_p3 *h, const uint8_t a[32],
+    const uint8_t precomp_table[15 * 2 * 32]);
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]);
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A);
+void x25519_sc_reduce(uint8_t *s);
+
+void x25519_public_from_private(uint8_t out_public_value[32],
+    const uint8_t private_key[32]);
+
+void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
+    const uint8_t point[32]);
+void x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32],
+    const uint8_t point[32]);
+
+void ED25519_public_from_private(uint8_t out_public_key[32],
+    const uint8_t private_key[32]);
+
+void X25519_public_from_private(uint8_t out_public_key[32],
+    const uint8_t private_key[32]);
+
+__END_HIDDEN_DECLS
+
+#endif  /* HEADER_CURVE25519_INTERNAL_H */
diff --git a/crypto/cversion.c b/crypto/cversion.c
new file mode 100644
index 0000000..acb7b70
--- /dev/null
+++ b/crypto/cversion.c
@@ -0,0 +1,116 @@
+/* $OpenBSD: cversion.c,v 1.18 2023/07/08 08:28:23 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include "cryptlib.h"
+
+const char *
+SSLeay_version(int t)
+{
+	switch (t) {
+	case SSLEAY_VERSION:
+		return OPENSSL_VERSION_TEXT;
+	case SSLEAY_BUILT_ON:
+		return("built on: date not available");
+	case SSLEAY_CFLAGS:
+		return("compiler: information not available");
+	case SSLEAY_PLATFORM:
+		return("platform: information not available");
+	case SSLEAY_DIR:
+		return "OPENSSLDIR: \"" OPENSSLDIR "\"";
+	}
+	return("not available");
+}
+LCRYPTO_ALIAS(SSLeay_version);
+
+unsigned long
+SSLeay(void)
+{
+	return (SSLEAY_VERSION_NUMBER);
+}
+LCRYPTO_ALIAS(SSLeay);
+
+const char *
+OpenSSL_version(int t)
+{
+	switch (t) {
+	case OPENSSL_VERSION:
+		return OPENSSL_VERSION_TEXT;
+	case OPENSSL_BUILT_ON:
+		return("built on: date not available");
+	case OPENSSL_CFLAGS:
+		return("compiler: information not available");
+	case OPENSSL_PLATFORM:
+		return("platform: information not available");
+	case OPENSSL_DIR:
+		return "OPENSSLDIR: \"" OPENSSLDIR "\"";
+	case OPENSSL_ENGINES_DIR:
+		return "ENGINESDIR: N/A";
+	}
+	return("not available");
+}
+LCRYPTO_ALIAS(OpenSSL_version);
+
+unsigned long
+OpenSSL_version_num(void)
+{
+	return SSLeay();
+}
+LCRYPTO_ALIAS(OpenSSL_version_num);
diff --git a/crypto/des/cbc_cksm.c b/crypto/des/cbc_cksm.c
new file mode 100644
index 0000000..afa3f03
--- /dev/null
+++ b/crypto/des/cbc_cksm.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: cbc_cksm.c,v 1.10 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+DES_LONG
+DES_cbc_cksum(const unsigned char *in, DES_cblock *output,
+    long length, DES_key_schedule *schedule,
+    const_DES_cblock *ivec)
+{
+	DES_LONG tout0, tout1, tin0, tin1;
+	long l = length;
+	DES_LONG tin[2];
+	unsigned char *out = &(*output)[0];
+	const unsigned char *iv = &(*ivec)[0];
+
+	c2l(iv, tout0);
+	c2l(iv, tout1);
+	for (; l > 0; l -= 8) {
+		if (l >= 8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+		} else
+			c2ln(in, tin0, tin1, l);
+
+		tin0 ^= tout0;
+		tin[0] = tin0;
+		tin1 ^= tout1;
+		tin[1] = tin1;
+		DES_encrypt1((DES_LONG *)tin, schedule, DES_ENCRYPT);
+		/* fix 15/10/91 eay - thanks to keithr@sco.COM */
+		tout0 = tin[0];
+		tout1 = tin[1];
+	}
+	if (out != NULL) {
+		l2c(tout0, out);
+		l2c(tout1, out);
+	}
+	tout0 = tin0 = tin1 = tin[0] = tin[1] = 0;
+	/*
+	  Transform the data in tout1 so that it will
+	  match the return value that the MIT Kerberos
+	  mit_des_cbc_cksum API returns.
+	*/
+	tout1 = ((tout1 >> 24L) & 0x000000FF) |
+	    ((tout1 >> 8L) & 0x0000FF00) |
+	    ((tout1 << 8L) & 0x00FF0000) |
+	    ((tout1 << 24L) & 0xFF000000);
+	return (tout1);
+}
diff --git a/crypto/des/cbc_enc.c b/crypto/des/cbc_enc.c
new file mode 100644
index 0000000..6c1ec71
--- /dev/null
+++ b/crypto/des/cbc_enc.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: cbc_enc.c,v 1.4 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#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
new file mode 100644
index 0000000..e91dbbf
--- /dev/null
+++ b/crypto/des/cfb64ede.c
@@ -0,0 +1,240 @@
+/* $OpenBSD: cfb64ede.c,v 1.12 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, DES_key_schedule *ks1,
+    DES_key_schedule *ks2, DES_key_schedule *ks3,
+    DES_cblock *ivec, int *num, int enc)
+{
+	DES_LONG v0, v1;
+	long l = length;
+	int n = *num;
+	DES_LONG ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = &(*ivec)[0];
+	if (enc) {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				c2l(iv, v1);
+
+				ti[0] = v0;
+				ti[1] = v1;
+				DES_encrypt3(ti, ks1, ks2, ks3);
+				v0 = ti[0];
+				v1 = ti[1];
+
+				iv = &(*ivec)[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				iv = &(*ivec)[0];
+			}
+			c = *(in++) ^ iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1) & 0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				c2l(iv, v1);
+
+				ti[0] = v0;
+				ti[1] = v1;
+				DES_encrypt3(ti, ks1, ks2, ks3);
+				v0 = ti[0];
+				v1 = ti[1];
+
+				iv = &(*ivec)[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				iv = &(*ivec)[0];
+			}
+			cc = *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c ^ cc;
+			n = (n + 1) & 0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = c = cc = 0;
+	*num = n;
+}
+
+/* This is compatible with the single key CFB-r for DES, even thought that's
+ * not what EVP needs.
+ */
+
+void
+DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out,
+    int numbits, long length, DES_key_schedule *ks1,
+    DES_key_schedule *ks2, DES_key_schedule *ks3,
+    DES_cblock *ivec, int enc)
+{
+	DES_LONG d0, d1, v0, v1;
+	unsigned long l = length, n = ((unsigned int)numbits + 7)/8;
+	int num = numbits, i;
+	DES_LONG ti[2];
+	unsigned char *iv;
+	unsigned char ovec[16];
+
+	if (num > 64)
+		return;
+	iv = &(*ivec)[0];
+	c2l(iv, v0);
+	c2l(iv, v1);
+	if (enc) {
+		while (l >= n) {
+			l -= n;
+			ti[0] = v0;
+			ti[1] = v1;
+			DES_encrypt3(ti, ks1, ks2, ks3);
+			c2ln(in, d0, d1, n);
+			in += n;
+			d0 ^= ti[0];
+			d1 ^= ti[1];
+			l2cn(d0, d1, out, n);
+			out += n;
+			/* 30-08-94 - eay - changed because l>>32 and
+			 * l<<32 are bad under gcc :-( */
+			if (num == 32) {
+				v0 = v1;
+				v1 = d0;
+			} else if (num == 64) {
+				v0 = d0;
+				v1 = d1;
+			} else {
+				iv = &ovec[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				l2c(d0, iv);
+				l2c(d1, iv);
+				/* shift ovec left most of the bits... */
+				memmove(ovec, ovec + num/8,
+				    8 + (num % 8 ? 1 : 0));
+				/* now the remaining bits */
+				if (num % 8 != 0) {
+					for (i = 0; i < 8; ++i) {
+						ovec[i] <<= num % 8;
+						ovec[i] |= ovec[i + 1] >>
+						    (8 - num % 8);
+					}
+				}
+				iv = &ovec[0];
+				c2l(iv, v0);
+				c2l(iv, v1);
+			}
+		}
+	} else {
+		while (l >= n) {
+			l -= n;
+			ti[0] = v0;
+			ti[1] = v1;
+			DES_encrypt3(ti, ks1, ks2, ks3);
+			c2ln(in, d0, d1, n);
+			in += n;
+			/* 30-08-94 - eay - changed because l>>32 and
+			 * l<<32 are bad under gcc :-( */
+			if (num == 32) {
+				v0 = v1;
+				v1 = d0;
+			} else if (num == 64) {
+				v0 = d0;
+				v1 = d1;
+			} else {
+				iv = &ovec[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				l2c(d0, iv);
+				l2c(d1, iv);
+				/* shift ovec left most of the bits... */
+				memmove(ovec, ovec + num/8,
+				    8 + (num % 8 ? 1 : 0));
+				/* now the remaining bits */
+				if (num % 8 != 0) {
+					for (i = 0; i < 8; ++i) {
+						ovec[i] <<= num % 8;
+						ovec[i] |= ovec[i + 1] >>
+						    (8 - num % 8);
+					}
+				}
+				iv = &ovec[0];
+				c2l(iv, v0);
+				c2l(iv, v1);
+			}
+			d0 ^= ti[0];
+			d1 ^= ti[1];
+			l2cn(d0, d1, out, n);
+			out += n;
+		}
+	}
+	iv = &(*ivec)[0];
+	l2c(v0, iv);
+	l2c(v1, iv);
+	v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0;
+}
diff --git a/crypto/des/cfb64enc.c b/crypto/des/cfb64enc.c
new file mode 100644
index 0000000..d7434b9
--- /dev/null
+++ b/crypto/des/cfb64enc.c
@@ -0,0 +1,122 @@
+/* $OpenBSD: cfb64enc.c,v 1.8 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+DES_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, DES_key_schedule *schedule,
+    DES_cblock *ivec, int *num, int enc)
+{
+	DES_LONG v0, v1;
+	long l = length;
+	int n = *num;
+	DES_LONG ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = &(*ivec)[0];
+	if (enc) {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				ti[0] = v0;
+				c2l(iv, v1);
+				ti[1] = v1;
+				DES_encrypt1(ti, schedule, DES_ENCRYPT);
+				iv = &(*ivec)[0];
+				v0 = ti[0];
+				l2c(v0, iv);
+				v0 = ti[1];
+				l2c(v0, iv);
+				iv = &(*ivec)[0];
+			}
+			c = *(in++) ^ iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1) & 0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				ti[0] = v0;
+				c2l(iv, v1);
+				ti[1] = v1;
+				DES_encrypt1(ti, schedule, DES_ENCRYPT);
+				iv = &(*ivec)[0];
+				v0 = ti[0];
+				l2c(v0, iv);
+				v0 = ti[1];
+				l2c(v0, iv);
+				iv = &(*ivec)[0];
+			}
+			cc = *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c ^ cc;
+			n = (n + 1) & 0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = c = cc = 0;
+	*num = n;
+}
diff --git a/crypto/des/cfb_enc.c b/crypto/des/cfb_enc.c
new file mode 100644
index 0000000..dac8675
--- /dev/null
+++ b/crypto/des/cfb_enc.c
@@ -0,0 +1,189 @@
+/* $OpenBSD: cfb_enc.c,v 1.16 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+#include 
+
+/* The input and output are loaded in multiples of 8 bits.
+ * What this means is that if you hame numbits=12 and length=2
+ * the first 12 bits will be retrieved from the first byte and half
+ * the second.  The second 12 bits will come from the 3rd and half the 4th
+ * byte.
+ */
+/* Until Aug 1 2003 this function did not correctly implement CFB-r, so it
+ * will not be compatible with any encryption prior to that date. Ben. */
+void
+DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
+    long length, DES_key_schedule *schedule, DES_cblock *ivec,
+    int enc)
+{
+	DES_LONG d0, d1, v0, v1;
+	unsigned long l = length;
+	int num = numbits/8, n = (numbits + 7)/8, i, rem = numbits % 8;
+	DES_LONG ti[2];
+	unsigned char *iv;
+#if BYTE_ORDER != LITTLE_ENDIAN
+	unsigned char ovec[16];
+#else
+	unsigned int sh[4];
+	unsigned char *ovec = (unsigned char *)sh;
+#endif
+
+	if (numbits <= 0 || numbits > 64)
+		return;
+	iv = &(*ivec)[0];
+	c2l(iv, v0);
+	c2l(iv, v1);
+	if (enc) {
+		while (l >= (unsigned long)n) {
+			l -= n;
+			ti[0] = v0;
+			ti[1] = v1;
+			DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT);
+			c2ln(in, d0, d1, n);
+			in += n;
+			d0 ^= ti[0];
+			d1 ^= ti[1];
+			l2cn(d0, d1, out, n);
+			out += n;
+			/* 30-08-94 - eay - changed because l>>32 and
+			 * l<<32 are bad under gcc :-( */
+			if (numbits == 32) {
+				v0 = v1;
+				v1 = d0;
+			} else if (numbits == 64) {
+				v0 = d0;
+				v1 = d1;
+			} else {
+#if BYTE_ORDER != LITTLE_ENDIAN
+				iv = &ovec[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				l2c(d0, iv);
+				l2c(d1, iv);
+#else
+				sh[0] = v0, sh[1] = v1, sh[2] = d0, sh[3] = d1;
+#endif
+				if (rem == 0)
+					memmove(ovec, ovec + num, 8);
+				else
+					for (i = 0; i < 8; ++i)
+						ovec[i] = ovec[i + num] << rem |
+						    ovec[i + num + 1] >> (8 -
+						    rem);
+#if BYTE_ORDER == LITTLE_ENDIAN
+				v0 = sh[0], v1 = sh[1];
+#else
+				iv = &ovec[0];
+				c2l(iv, v0);
+				c2l(iv, v1);
+#endif
+			}
+		}
+	} else {
+		while (l >= (unsigned long)n) {
+			l -= n;
+			ti[0] = v0;
+			ti[1] = v1;
+			DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT);
+			c2ln(in, d0, d1, n);
+			in += n;
+			/* 30-08-94 - eay - changed because l>>32 and
+			 * l<<32 are bad under gcc :-( */
+			if (numbits == 32) {
+				v0 = v1;
+				v1 = d0;
+			} else if (numbits == 64) {
+				v0 = d0;
+				v1 = d1;
+			} else {
+#if BYTE_ORDER != LITTLE_ENDIAN
+				iv = &ovec[0];
+				l2c(v0, iv);
+				l2c(v1, iv);
+				l2c(d0, iv);
+				l2c(d1, iv);
+#else
+				sh[0] = v0, sh[1] = v1, sh[2] = d0, sh[3] = d1;
+#endif
+				if (rem == 0)
+					memmove(ovec, ovec + num, 8);
+				else
+					for (i = 0; i < 8; ++i)
+						ovec[i] = ovec[i + num] << rem |
+						    ovec[i + num + 1] >> (8 -
+						    rem);
+#if BYTE_ORDER == LITTLE_ENDIAN
+				v0 = sh[0], v1 = sh[1];
+#else
+				iv = &ovec[0];
+				c2l(iv, v0);
+				c2l(iv, v1);
+#endif
+			}
+			d0 ^= ti[0];
+			d1 ^= ti[1];
+			l2cn(d0, d1, out, n);
+			out += n;
+		}
+	}
+	iv = &(*ivec)[0];
+	l2c(v0, iv);
+	l2c(v1, iv);
+	v0 = v1 = d0 = d1 = ti[0] = ti[1] = 0;
+}
diff --git a/crypto/des/des_enc.c b/crypto/des/des_enc.c
new file mode 100644
index 0000000..7319639
--- /dev/null
+++ b/crypto/des/des_enc.c
@@ -0,0 +1,392 @@
+/* $OpenBSD: des_enc.c,v 1.15 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+#include "spr.h"
+
+#ifndef OPENBSD_DES_ASM
+
+void
+DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc)
+{
+	DES_LONG l, r, t, u;
+#ifdef DES_PTR
+	const unsigned char *des_SP = (const unsigned char *)DES_SPtrans;
+#endif
+#ifndef DES_UNROLL
+	int i;
+#endif
+	DES_LONG *s;
+
+	r = data[0];
+	l = data[1];
+
+	IP(r, l);
+	/* Things have been modified so that the initial rotate is
+	 * done outside the loop.  This required the
+	 * DES_SPtrans values in sp.h to be rotated 1 bit to the right.
+	 * One perl script later and things have a 5% speed up on a sparc2.
+	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+	 * for pointing this out. */
+	/* clear the top bits on machines with 8byte longs */
+	/* shift left by 2 */
+	r = ROTATE(r, 29) & 0xffffffffL;
+	l = ROTATE(l, 29) & 0xffffffffL;
+
+	s = ks->ks->deslong;
+	/* I don't know if it is worth the effort of loop unrolling the
+	 * inner loop */
+	if (enc) {
+#ifdef DES_UNROLL
+		D_ENCRYPT(l, r, 0); /*  1 */
+		D_ENCRYPT(r, l, 2); /*  2 */
+		D_ENCRYPT(l, r, 4); /*  3 */
+		D_ENCRYPT(r, l, 6); /*  4 */
+		D_ENCRYPT(l, r, 8); /*  5 */
+		D_ENCRYPT(r, l, 10); /*  6 */
+		D_ENCRYPT(l, r, 12); /*  7 */
+		D_ENCRYPT(r, l, 14); /*  8 */
+		D_ENCRYPT(l, r, 16); /*  9 */
+		D_ENCRYPT(r, l, 18); /*  10 */
+		D_ENCRYPT(l, r, 20); /*  11 */
+		D_ENCRYPT(r, l, 22); /*  12 */
+		D_ENCRYPT(l, r, 24); /*  13 */
+		D_ENCRYPT(r, l, 26); /*  14 */
+		D_ENCRYPT(l, r, 28); /*  15 */
+		D_ENCRYPT(r, l, 30); /*  16 */
+#else
+		for (i = 0; i < 32; i += 4) {
+			D_ENCRYPT(l, r, i + 0); /*  1 */
+			D_ENCRYPT(r, l, i + 2); /*  2 */
+		}
+#endif
+	} else {
+#ifdef DES_UNROLL
+		D_ENCRYPT(l, r, 30); /* 16 */
+		D_ENCRYPT(r, l, 28); /* 15 */
+		D_ENCRYPT(l, r, 26); /* 14 */
+		D_ENCRYPT(r, l, 24); /* 13 */
+		D_ENCRYPT(l, r, 22); /* 12 */
+		D_ENCRYPT(r, l, 20); /* 11 */
+		D_ENCRYPT(l, r, 18); /* 10 */
+		D_ENCRYPT(r, l, 16); /*  9 */
+		D_ENCRYPT(l, r, 14); /*  8 */
+		D_ENCRYPT(r, l, 12); /*  7 */
+		D_ENCRYPT(l, r, 10); /*  6 */
+		D_ENCRYPT(r, l, 8); /*  5 */
+		D_ENCRYPT(l, r, 6); /*  4 */
+		D_ENCRYPT(r, l, 4); /*  3 */
+		D_ENCRYPT(l, r, 2); /*  2 */
+		D_ENCRYPT(r, l, 0); /*  1 */
+#else
+		for (i = 30; i > 0; i -= 4) {
+			D_ENCRYPT(l, r, i - 0); /* 16 */
+			D_ENCRYPT(r, l, i - 2); /* 15 */
+		}
+#endif
+	}
+
+	/* rotate and clear the top bits on machines with 8byte longs */
+	l = ROTATE(l, 3) & 0xffffffffL;
+	r = ROTATE(r, 3) & 0xffffffffL;
+
+	FP(r, l);
+	data[0] = l;
+	data[1] = r;
+	l = r = t = u = 0;
+}
+
+void
+DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc)
+{
+	DES_LONG l, r, t, u;
+#ifdef DES_PTR
+	const unsigned char *des_SP = (const unsigned char *)DES_SPtrans;
+#endif
+#ifndef DES_UNROLL
+	int i;
+#endif
+	DES_LONG *s;
+
+	r = data[0];
+	l = data[1];
+
+	/* Things have been modified so that the initial rotate is
+	 * done outside the loop.  This required the
+	 * DES_SPtrans values in sp.h to be rotated 1 bit to the right.
+	 * One perl script later and things have a 5% speed up on a sparc2.
+	 * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
+	 * for pointing this out. */
+	/* clear the top bits on machines with 8byte longs */
+	r = ROTATE(r, 29) & 0xffffffffL;
+	l = ROTATE(l, 29) & 0xffffffffL;
+
+	s = ks->ks->deslong;
+	/* I don't know if it is worth the effort of loop unrolling the
+	 * inner loop */
+	if (enc) {
+#ifdef DES_UNROLL
+		D_ENCRYPT(l, r, 0); /*  1 */
+		D_ENCRYPT(r, l, 2); /*  2 */
+		D_ENCRYPT(l, r, 4); /*  3 */
+		D_ENCRYPT(r, l, 6); /*  4 */
+		D_ENCRYPT(l, r, 8); /*  5 */
+		D_ENCRYPT(r, l, 10); /*  6 */
+		D_ENCRYPT(l, r, 12); /*  7 */
+		D_ENCRYPT(r, l, 14); /*  8 */
+		D_ENCRYPT(l, r, 16); /*  9 */
+		D_ENCRYPT(r, l, 18); /*  10 */
+		D_ENCRYPT(l, r, 20); /*  11 */
+		D_ENCRYPT(r, l, 22); /*  12 */
+		D_ENCRYPT(l, r, 24); /*  13 */
+		D_ENCRYPT(r, l, 26); /*  14 */
+		D_ENCRYPT(l, r, 28); /*  15 */
+		D_ENCRYPT(r, l, 30); /*  16 */
+#else
+		for (i = 0; i < 32; i += 4) {
+			D_ENCRYPT(l, r, i + 0); /*  1 */
+			D_ENCRYPT(r, l, i + 2); /*  2 */
+		}
+#endif
+	} else {
+#ifdef DES_UNROLL
+		D_ENCRYPT(l, r, 30); /* 16 */
+		D_ENCRYPT(r, l, 28); /* 15 */
+		D_ENCRYPT(l, r, 26); /* 14 */
+		D_ENCRYPT(r, l, 24); /* 13 */
+		D_ENCRYPT(l, r, 22); /* 12 */
+		D_ENCRYPT(r, l, 20); /* 11 */
+		D_ENCRYPT(l, r, 18); /* 10 */
+		D_ENCRYPT(r, l, 16); /*  9 */
+		D_ENCRYPT(l, r, 14); /*  8 */
+		D_ENCRYPT(r, l, 12); /*  7 */
+		D_ENCRYPT(l, r, 10); /*  6 */
+		D_ENCRYPT(r, l, 8); /*  5 */
+		D_ENCRYPT(l, r, 6); /*  4 */
+		D_ENCRYPT(r, l, 4); /*  3 */
+		D_ENCRYPT(l, r, 2); /*  2 */
+		D_ENCRYPT(r, l, 0); /*  1 */
+#else
+		for (i = 30; i > 0; i -= 4) {
+			D_ENCRYPT(l, r, i - 0); /* 16 */
+			D_ENCRYPT(r, l, i - 2); /* 15 */
+		}
+#endif
+	}
+	/* rotate and clear the top bits on machines with 8byte longs */
+	data[0] = ROTATE(l, 3) & 0xffffffffL;
+	data[1] = ROTATE(r, 3) & 0xffffffffL;
+	l = r = t = u = 0;
+}
+
+#endif /* OPENBSD_DES_ASM */
+
+void
+DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1,
+    DES_key_schedule *ks2, DES_key_schedule *ks3)
+{
+	DES_LONG l, r;
+
+	l = data[0];
+	r = data[1];
+	IP(l, r);
+	data[0] = l;
+	data[1] = r;
+	DES_encrypt2((DES_LONG *)data, ks1, DES_ENCRYPT);
+	DES_encrypt2((DES_LONG *)data, ks2, DES_DECRYPT);
+	DES_encrypt2((DES_LONG *)data, ks3, DES_ENCRYPT);
+	l = data[0];
+	r = data[1];
+	FP(r, l);
+	data[0] = l;
+	data[1] = r;
+}
+
+void
+DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1,
+    DES_key_schedule *ks2, DES_key_schedule *ks3)
+{
+	DES_LONG l, r;
+
+	l = data[0];
+	r = data[1];
+	IP(l, r);
+	data[0] = l;
+	data[1] = r;
+	DES_encrypt2((DES_LONG *)data, ks3, DES_DECRYPT);
+	DES_encrypt2((DES_LONG *)data, ks2, DES_ENCRYPT);
+	DES_encrypt2((DES_LONG *)data, ks1, DES_DECRYPT);
+	l = data[0];
+	r = data[1];
+	FP(r, l);
+	data[0] = l;
+	data[1] = r;
+}
+
+#ifndef DES_DEFAULT_OPTIONS
+
+#undef CBC_ENC_C__DONT_UPDATE_IV
+#include "ncbc_enc.c" /* DES_ncbc_encrypt */
+
+void
+DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
+    long length, DES_key_schedule *ks1,
+    DES_key_schedule *ks2, DES_key_schedule *ks3,
+    DES_cblock *ivec, int enc)
+{
+	DES_LONG tin0, tin1;
+	DES_LONG tout0, tout1, xor0, xor1;
+	const unsigned char *in;
+	unsigned char *out;
+	long l = length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	in = input;
+	out = output;
+	iv = &(*ivec)[0];
+
+	if (enc) {
+		c2l(iv, tout0);
+		c2l(iv, tout1);
+		for (l -= 8; l >= 0; l -= 8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			l2c(tout0, out);
+			l2c(tout1, out);
+		}
+		if (l != -8) {
+			c2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_encrypt3((DES_LONG *)tin, ks1, ks2, ks3);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			l2c(tout0, out);
+			l2c(tout1, out);
+		}
+		iv = &(*ivec)[0];
+		l2c(tout0, iv);
+		l2c(tout1, iv);
+	} else {
+		DES_LONG t0, t1;
+
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		for (l -= 8; l >= 0; l -= 8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+
+			t0 = tin0;
+			t1 = tin1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			tout0 ^= xor0;
+			tout1 ^= xor1;
+			l2c(tout0, out);
+			l2c(tout1, out);
+			xor0 = t0;
+			xor1 = t1;
+		}
+		if (l != -8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+
+			t0 = tin0;
+			t1 = tin1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_decrypt3((DES_LONG *)tin, ks1, ks2, ks3);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			tout0 ^= xor0;
+			tout1 ^= xor1;
+			l2cn(tout0, tout1, out, l + 8);
+			xor0 = t0;
+			xor1 = t1;
+		}
+
+		iv = &(*ivec)[0];
+		l2c(xor0, iv);
+		l2c(xor1, iv);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+
+#endif /* DES_DEFAULT_OPTIONS */
diff --git a/crypto/des/des_local.h b/crypto/des/des_local.h
new file mode 100644
index 0000000..f081ade
--- /dev/null
+++ b/crypto/des/des_local.h
@@ -0,0 +1,398 @@
+/* $OpenBSD: des_local.h,v 1.2 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DES_LOCL_H
+#define HEADER_DES_LOCL_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+#define ITERATIONS 16
+#define HALF_ITERATIONS 8
+
+/* used in des_read and des_write */
+#define MAXWRITE	(1024*16)
+#define BSIZE		(MAXWRITE+4)
+
+#define c2l(c,l)	(l =((DES_LONG)(*((c)++)))    ,			\
+			 l|=((DES_LONG)(*((c)++)))<< 8L,		\
+			 l|=((DES_LONG)(*((c)++)))<<16L,		\
+			 l|=((DES_LONG)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#define c2ln(c,l1,l2,n)	{						\
+			c+=n;						\
+			l1=l2=0;					\
+			switch (n) {					\
+			case 8: l2 =((DES_LONG)(*(--(c))))<<24L;	\
+			case 7: l2|=((DES_LONG)(*(--(c))))<<16L;	\
+			case 6: l2|=((DES_LONG)(*(--(c))))<< 8L;	\
+			case 5: l2|=((DES_LONG)(*(--(c))));		\
+			case 4: l1 =((DES_LONG)(*(--(c))))<<24L;	\
+			case 3: l1|=((DES_LONG)(*(--(c))))<<16L;	\
+			case 2: l1|=((DES_LONG)(*(--(c))))<< 8L;	\
+			case 1: l1|=((DES_LONG)(*(--(c))));		\
+				}					\
+			}
+
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* replacements for htonl and ntohl since I have no idea what to do
+ * when faced with machines with 8 byte longs. */
+#define HDRSIZE 4
+
+#define n2l(c,l)	(l =((DES_LONG)(*((c)++)))<<24L,		\
+			 l|=((DES_LONG)(*((c)++)))<<16L,		\
+			 l|=((DES_LONG)(*((c)++)))<< 8L,		\
+			 l|=((DES_LONG)(*((c)++))))
+
+#define l2n(l,c)	(*((c)++)=(unsigned char)(((l)>>24L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)     )&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#define l2cn(l1,l2,c,n)	{						\
+			c+=n;						\
+			switch (n) {					\
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff);\
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff);\
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff);\
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff);\
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff);\
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff);\
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff);\
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff);\
+				}					\
+			}
+
+static inline uint32_t
+ROTATE(uint32_t a, uint32_t n)
+{
+	return (a >> n) + (a << (32 - n));
+}
+
+/* Don't worry about the LOAD_DATA() stuff, that is used by
+ * fcrypt() to add it's little bit to the front */
+
+#ifdef DES_FCRYPT
+
+#define LOAD_DATA_tmp(R,S,u,t,E0,E1) \
+	{ DES_LONG tmp; LOAD_DATA(R,S,u,t,E0,E1,tmp); }
+
+#define LOAD_DATA(R,S,u,t,E0,E1,tmp)					\
+	t=R^(R>>16L);							\
+	u=t&E0; t&=E1;							\
+	tmp=(u<<16); u^=R^s[S  ]; u^=tmp;				\
+	tmp=(t<<16); t^=R^s[S+1]; t^=tmp
+#else
+#define LOAD_DATA_tmp(a,b,c,d,e,f) LOAD_DATA(a,b,c,d,e,f,g)
+#define LOAD_DATA(R,S,u,t,E0,E1,tmp)					\
+	u=R^s[S  ];							\
+	t=R^s[S+1]
+#endif
+
+/* The changes to this macro may help or hinder, depending on the
+ * compiler and the architecture.  gcc2 always seems to do well :-).
+ * Inspired by Dana How 
+ * DO NOT use the alternative version on machines with 8 byte longs.
+ * It does not seem to work on the Alpha, even when DES_LONG is 4
+ * bytes, probably an issue of accessing non-word aligned objects :-( */
+#ifdef DES_PTR
+
+/* It recently occurred to me that 0^0^0^0^0^0^0 == 0, so there
+ * is no reason to not xor all the sub items together.  This potentially
+ * saves a register since things can be xored directly into L */
+
+#if defined(DES_RISC1) || defined(DES_RISC2)
+#ifdef DES_RISC1
+#define D_ENCRYPT(LL,R,S) {						\
+	unsigned int u1,u2,u3;						\
+	LOAD_DATA(R,S,u,t,E0,E1,u1);					\
+	u2=(int)u>>8L;							\
+	u1=(int)u&0xfc;							\
+	u2&=0xfc;							\
+	t=ROTATE(t,4);							\
+	u>>=16L;							\
+	LL^= *(const DES_LONG *)(des_SP      +u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x200+u2);			\
+	u3=(int)(u>>8L);						\
+	u1=(int)u&0xfc;							\
+	u3&=0xfc;							\
+	LL^= *(const DES_LONG *)(des_SP+0x400+u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x600+u3);			\
+	u2=(int)t>>8L;							\
+	u1=(int)t&0xfc;							\
+	u2&=0xfc;							\
+	t>>=16L;							\
+	LL^= *(const DES_LONG *)(des_SP+0x100+u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x300+u2);			\
+	u3=(int)t>>8L;							\
+	u1=(int)t&0xfc;							\
+	u3&=0xfc;							\
+	LL^= *(const DES_LONG *)(des_SP+0x500+u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x700+u3); }
+#endif
+#ifdef DES_RISC2
+#define D_ENCRYPT(LL,R,S) {						\
+	unsigned int u1,u2,s1,s2;					\
+	LOAD_DATA(R,S,u,t,E0,E1,u1);					\
+	u2=(int)u>>8L;							\
+	u1=(int)u&0xfc;							\
+	u2&=0xfc;							\
+	t=ROTATE(t,4);							\
+	LL^= *(const DES_LONG *)(des_SP      +u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x200+u2);			\
+	s1=(int)(u>>16L);						\
+	s2=(int)(u>>24L);						\
+	s1&=0xfc;							\
+	s2&=0xfc;							\
+	LL^= *(const DES_LONG *)(des_SP+0x400+s1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x600+s2);			\
+	u2=(int)t>>8L;							\
+	u1=(int)t&0xfc;							\
+	u2&=0xfc;							\
+	LL^= *(const DES_LONG *)(des_SP+0x100+u1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x300+u2);			\
+	s1=(int)(t>>16L);						\
+	s2=(int)(t>>24L);						\
+	s1&=0xfc;							\
+	s2&=0xfc;							\
+	LL^= *(const DES_LONG *)(des_SP+0x500+s1);			\
+	LL^= *(const DES_LONG *)(des_SP+0x700+s2); }
+#endif
+#else
+#define D_ENCRYPT(LL,R,S) {						\
+	LOAD_DATA_tmp(R,S,u,t,E0,E1);					\
+	t=ROTATE(t,4);							\
+	LL^=								\
+	*(const DES_LONG *)(des_SP      +((u     )&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x200+((u>> 8L)&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x400+((u>>16L)&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x600+((u>>24L)&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x100+((t     )&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x300+((t>> 8L)&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x500+((t>>16L)&0xfc))^		\
+	*(const DES_LONG *)(des_SP+0x700+((t>>24L)&0xfc)); }
+#endif
+
+#else /* original version */
+
+#if defined(DES_RISC1) || defined(DES_RISC2)
+#ifdef DES_RISC1
+#define D_ENCRYPT(LL,R,S) {						\
+	unsigned int u1,u2,u3;						\
+	LOAD_DATA(R,S,u,t,E0,E1,u1);					\
+	u>>=2L;								\
+	t=ROTATE(t,6);							\
+	u2=(int)u>>8L;							\
+	u1=(int)u&0x3f;							\
+	u2&=0x3f;							\
+	u>>=16L;							\
+	LL^=DES_SPtrans[0][u1];						\
+	LL^=DES_SPtrans[2][u2];						\
+	u3=(int)u>>8L;							\
+	u1=(int)u&0x3f;							\
+	u3&=0x3f;							\
+	LL^=DES_SPtrans[4][u1];						\
+	LL^=DES_SPtrans[6][u3];						\
+	u2=(int)t>>8L;							\
+	u1=(int)t&0x3f;							\
+	u2&=0x3f;							\
+	t>>=16L;							\
+	LL^=DES_SPtrans[1][u1];						\
+	LL^=DES_SPtrans[3][u2];						\
+	u3=(int)t>>8L;							\
+	u1=(int)t&0x3f;							\
+	u3&=0x3f;							\
+	LL^=DES_SPtrans[5][u1];						\
+	LL^=DES_SPtrans[7][u3]; }
+#endif
+#ifdef DES_RISC2
+#define D_ENCRYPT(LL,R,S) {						\
+	unsigned int u1,u2,s1,s2;					\
+	LOAD_DATA(R,S,u,t,E0,E1,u1);					\
+	u>>=2L;								\
+	t=ROTATE(t,6);							\
+	u2=(int)u>>8L;							\
+	u1=(int)u&0x3f;							\
+	u2&=0x3f;							\
+	LL^=DES_SPtrans[0][u1];						\
+	LL^=DES_SPtrans[2][u2];						\
+	s1=(int)u>>16L;							\
+	s2=(int)u>>24L;							\
+	s1&=0x3f;							\
+	s2&=0x3f;							\
+	LL^=DES_SPtrans[4][s1];						\
+	LL^=DES_SPtrans[6][s2];						\
+	u2=(int)t>>8L;							\
+	u1=(int)t&0x3f;							\
+	u2&=0x3f;							\
+	LL^=DES_SPtrans[1][u1];						\
+	LL^=DES_SPtrans[3][u2];						\
+	s1=(int)t>>16;							\
+	s2=(int)t>>24L;							\
+	s1&=0x3f;							\
+	s2&=0x3f;							\
+	LL^=DES_SPtrans[5][s1];						\
+	LL^=DES_SPtrans[7][s2]; }
+#endif
+
+#else
+
+#define D_ENCRYPT(LL,R,S) {						\
+	LOAD_DATA_tmp(R,S,u,t,E0,E1);					\
+	t=ROTATE(t,4);							\
+	LL^=								\
+		DES_SPtrans[0][(u>> 2L)&0x3f]^				\
+		DES_SPtrans[2][(u>>10L)&0x3f]^				\
+		DES_SPtrans[4][(u>>18L)&0x3f]^				\
+		DES_SPtrans[6][(u>>26L)&0x3f]^				\
+		DES_SPtrans[1][(t>> 2L)&0x3f]^				\
+		DES_SPtrans[3][(t>>10L)&0x3f]^				\
+		DES_SPtrans[5][(t>>18L)&0x3f]^				\
+		DES_SPtrans[7][(t>>26L)&0x3f]; }
+#endif
+#endif
+
+	/* IP and FP
+	 * The problem is more of a geometric problem that random bit fiddling.
+	 0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
+	 8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
+	16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
+	24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
+
+	32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
+	40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
+	48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
+	56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
+
+	The output has been subject to swaps of the form
+	0 1 -> 3 1 but the odd and even bits have been put into
+	2 3    2 0
+	different words.  The main trick is to remember that
+	t=((l>>size)^r)&(mask);
+	r^=t;
+	l^=(t<>(n))^(b))&(m)),			\
+	(b)^=(t),							\
+	(a)^=((t)<<(n)))
+
+#define IP(l,r)								\
+	{								\
+	DES_LONG tt;							\
+	PERM_OP(r,l,tt, 4,0x0f0f0f0fL);					\
+	PERM_OP(l,r,tt,16,0x0000ffffL);					\
+	PERM_OP(r,l,tt, 2,0x33333333L);					\
+	PERM_OP(l,r,tt, 8,0x00ff00ffL);					\
+	PERM_OP(r,l,tt, 1,0x55555555L);					\
+	}
+
+#define FP(l,r)								\
+	{								\
+	DES_LONG tt;							\
+	PERM_OP(l,r,tt, 1,0x55555555L);					\
+	PERM_OP(r,l,tt, 8,0x00ff00ffL);					\
+	PERM_OP(l,r,tt, 2,0x33333333L);					\
+	PERM_OP(r,l,tt,16,0x0000ffffL);					\
+	PERM_OP(l,r,tt, 4,0x0f0f0f0fL);					\
+	}
+
+extern const DES_LONG DES_SPtrans[8][64];
+
+void fcrypt_body(DES_LONG *out, DES_key_schedule *ks,
+    DES_LONG Eswap0, DES_LONG Eswap1);
+
+#ifdef OPENSSL_SMALL_FOOTPRINT
+#undef DES_UNROLL
+#endif
+
+__END_HIDDEN_DECLS
+
+#endif
diff --git a/crypto/des/ecb3_enc.c b/crypto/des/ecb3_enc.c
new file mode 100644
index 0000000..129b5fa
--- /dev/null
+++ b/crypto/des/ecb3_enc.c
@@ -0,0 +1,84 @@
+/* $OpenBSD: ecb3_enc.c,v 1.9 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+void
+DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
+    DES_key_schedule *ks1, DES_key_schedule *ks2,
+    DES_key_schedule *ks3,
+    int enc)
+{
+	DES_LONG l0, l1;
+	DES_LONG ll[2];
+	const unsigned char *in = &(*input)[0];
+	unsigned char *out = &(*output)[0];
+
+	c2l(in, l0);
+	c2l(in, l1);
+	ll[0] = l0;
+	ll[1] = l1;
+	if (enc)
+		DES_encrypt3(ll, ks1, ks2, ks3);
+	else
+		DES_decrypt3(ll, ks1, ks2, ks3);
+	l0 = ll[0];
+	l1 = ll[1];
+	l2c(l0, out);
+	l2c(l1, out);
+}
diff --git a/crypto/des/ecb_enc.c b/crypto/des/ecb_enc.c
new file mode 100644
index 0000000..3599fb8
--- /dev/null
+++ b/crypto/des/ecb_enc.c
@@ -0,0 +1,82 @@
+/* $OpenBSD: ecb_enc.c,v 1.19 2023/07/31 05:04:06 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+#include 
+#include 
+
+void
+DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
+    DES_key_schedule *ks, int enc)
+{
+	DES_LONG l;
+	DES_LONG ll[2];
+	const unsigned char *in = &(*input)[0];
+	unsigned char *out = &(*output)[0];
+
+	c2l(in, l);
+	ll[0] = l;
+	c2l(in, l);
+	ll[1] = l;
+	DES_encrypt1(ll, ks, enc);
+	l = ll[0];
+	l2c(l, out);
+	l = ll[1];
+	l2c(l, out);
+	l = ll[0] = ll[1] = 0;
+}
diff --git a/crypto/des/ede_cbcm_enc.c b/crypto/des/ede_cbcm_enc.c
new file mode 100644
index 0000000..eb6fd4f
--- /dev/null
+++ b/crypto/des/ede_cbcm_enc.c
@@ -0,0 +1,189 @@
+/* $OpenBSD: ede_cbcm_enc.c,v 1.9 2023/07/08 07:34:34 jsing Exp $ */
+/* Written by Ben Laurie  for the OpenSSL
+ * project 13 Feb 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/*
+
+This is an implementation of Triple DES Cipher Block Chaining with Output
+Feedback Masking, by Coppersmith, Johnson and Matyas, (IBM and Certicom).
+
+Note that there is a known attack on this by Biham and Knudsen but it takes
+a lot of work:
+
+http://www.cs.technion.ac.il/users/wwwb/cgi-bin/tr-get.cgi/1998/CS/CS0928.ps.gz
+
+*/
+
+#include  /* To see if OPENSSL_NO_DESCBCM is defined */
+
+#ifndef OPENSSL_NO_DESCBCM
+#include "des_local.h"
+
+void
+DES_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out,
+    long length, DES_key_schedule *ks1, DES_key_schedule *ks2,
+    DES_key_schedule *ks3, DES_cblock *ivec1, DES_cblock *ivec2,
+    int enc)
+{
+	DES_LONG tin0, tin1;
+	DES_LONG tout0, tout1, xor0, xor1, m0, m1;
+	long l = length;
+	DES_LONG tin[2];
+	unsigned char *iv1, *iv2;
+
+	iv1 = &(*ivec1)[0];
+	iv2 = &(*ivec2)[0];
+
+	if (enc) {
+		c2l(iv1, m0);
+		c2l(iv1, m1);
+		c2l(iv2, tout0);
+		c2l(iv2, tout1);
+		for (l -= 8; l >= -7; l -= 8) {
+			tin[0] = m0;
+			tin[1] = m1;
+			DES_encrypt1(tin, ks3, 1);
+			m0 = tin[0];
+			m1 = tin[1];
+
+			if (l < 0) {
+				c2ln(in, tin0, tin1, l + 8);
+			} else {
+				c2l(in, tin0);
+				c2l(in, tin1);
+			}
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_encrypt1(tin, ks1, 1);
+			tin[0] ^= m0;
+			tin[1] ^= m1;
+			DES_encrypt1(tin, ks2, 0);
+			tin[0] ^= m0;
+			tin[1] ^= m1;
+			DES_encrypt1(tin, ks1, 1);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			l2c(tout0, out);
+			l2c(tout1, out);
+		}
+		iv1 = &(*ivec1)[0];
+		l2c(m0, iv1);
+		l2c(m1, iv1);
+
+		iv2 = &(*ivec2)[0];
+		l2c(tout0, iv2);
+		l2c(tout1, iv2);
+	} else {
+		DES_LONG t0, t1;
+
+		c2l(iv1, m0);
+		c2l(iv1, m1);
+		c2l(iv2, xor0);
+		c2l(iv2, xor1);
+		for (l -= 8; l >= -7; l -= 8) {
+			tin[0] = m0;
+			tin[1] = m1;
+			DES_encrypt1(tin, ks3, 1);
+			m0 = tin[0];
+			m1 = tin[1];
+
+			c2l(in, tin0);
+			c2l(in, tin1);
+
+			t0 = tin0;
+			t1 = tin1;
+
+			tin[0] = tin0;
+			tin[1] = tin1;
+			DES_encrypt1(tin, ks1, 0);
+			tin[0] ^= m0;
+			tin[1] ^= m1;
+			DES_encrypt1(tin, ks2, 1);
+			tin[0] ^= m0;
+			tin[1] ^= m1;
+			DES_encrypt1(tin, ks1, 0);
+			tout0 = tin[0];
+			tout1 = tin[1];
+
+			tout0 ^= xor0;
+			tout1 ^= xor1;
+			if (l < 0) {
+				l2cn(tout0, tout1, out, l + 8);
+			} else {
+				l2c(tout0, out);
+				l2c(tout1, out);
+			}
+			xor0 = t0;
+			xor1 = t1;
+		}
+
+		iv1 = &(*ivec1)[0];
+		l2c(m0, iv1);
+		l2c(m1, iv1);
+
+		iv2 = &(*ivec2)[0];
+		l2c(xor0, iv2);
+		l2c(xor1, iv2);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+#endif
diff --git a/crypto/des/enc_read.c b/crypto/des/enc_read.c
new file mode 100644
index 0000000..8095f26
--- /dev/null
+++ b/crypto/des/enc_read.c
@@ -0,0 +1,222 @@
+/* $OpenBSD: enc_read.c,v 1.17 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include "des_local.h"
+
+/* This has some uglies in it but it works - even over sockets. */
+/*extern int errno;*/
+int DES_rw_mode = DES_PCBC_MODE;
+
+/*
+ * WARNINGS:
+ *
+ *  -  The data format used by DES_enc_write() and DES_enc_read()
+ *     has a cryptographic weakness: When asked to write more
+ *     than MAXWRITE bytes, DES_enc_write will split the data
+ *     into several chunks that are all encrypted
+ *     using the same IV.  So don't use these functions unless you
+ *     are sure you know what you do (in which case you might
+ *     not want to use them anyway).
+ *
+ *  -  This code cannot handle non-blocking sockets.
+ *
+ *  -  This function uses an internal state and thus cannot be
+ *     used on multiple files.
+ */
+
+int
+DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched,
+    DES_cblock *iv)
+{
+	/* data to be unencrypted */
+	int net_num = 0;
+	static unsigned char *net = NULL;
+	/* extra unencrypted data
+	 * for when a block of 100 comes in but is des_read one byte at
+	 * a time. */
+	static unsigned char *unnet = NULL;
+	static int unnet_start = 0;
+	static int unnet_left = 0;
+	static unsigned char *tmpbuf = NULL;
+	int i;
+	long num = 0, rnum;
+	unsigned char *p;
+
+	if (tmpbuf == NULL) {
+		tmpbuf = malloc(BSIZE);
+		if (tmpbuf == NULL)
+			return (-1);
+	}
+	if (net == NULL) {
+		net = malloc(BSIZE);
+		if (net == NULL)
+			return (-1);
+	}
+	if (unnet == NULL) {
+		unnet = malloc(BSIZE);
+		if (unnet == NULL)
+			return (-1);
+	}
+	/* left over data from last decrypt */
+	if (unnet_left != 0) {
+		if (unnet_left < len) {
+			/* we still still need more data but will return
+			 * with the number of bytes we have - should always
+			 * check the return value */
+			memcpy(buf, &(unnet[unnet_start]),
+			    unnet_left);
+			/* eay 26/08/92 I had the next 2 lines
+			 * reversed :-( */
+			i = unnet_left;
+			unnet_start = unnet_left = 0;
+		} else {
+			memcpy(buf, &(unnet[unnet_start]), len);
+			unnet_start += len;
+			unnet_left -= len;
+			i = len;
+		}
+		return (i);
+	}
+
+	/* We need to get more data. */
+	if (len > MAXWRITE)
+		len = MAXWRITE;
+
+	/* first - get the length */
+	while (net_num < HDRSIZE) {
+		i = read(fd, (void *)&(net[net_num]), HDRSIZE - net_num);
+#ifdef EINTR
+		if ((i == -1) && (errno == EINTR))
+			continue;
+#endif
+		if (i <= 0)
+			return (0);
+		net_num += i;
+	}
+
+	/* we now have at net_num bytes in net */
+	p = net;
+	/* num=0;  */
+	n2l(p, num);
+	/* num should be rounded up to the next group of eight
+	 * we make sure that we have read a multiple of 8 bytes from the net.
+	 */
+	if ((num > MAXWRITE) || (num < 0)) /* error */
+		return (-1);
+	rnum = (num < 8) ? 8 : ((num + 7)/8*8);
+
+	net_num = 0;
+	while (net_num < rnum) {
+		i = read(fd, (void *)&(net[net_num]), rnum - net_num);
+#ifdef EINTR
+		if ((i == -1) && (errno == EINTR))
+			continue;
+#endif
+		if (i <= 0)
+			return (0);
+		net_num += i;
+	}
+
+	/* Check if there will be data left over. */
+	if (len < num) {
+		if (DES_rw_mode & DES_PCBC_MODE)
+			DES_pcbc_encrypt(net, unnet, num, sched, iv,
+			    DES_DECRYPT);
+		else
+			DES_cbc_encrypt(net, unnet, num, sched, iv,
+			    DES_DECRYPT);
+		memcpy(buf, unnet, len);
+		unnet_start = len;
+		unnet_left = num - len;
+
+		/* The following line is done because we return num
+		 * as the number of bytes read. */
+		num = len;
+	} else {
+		/* >output is a multiple of 8 byes, if len < rnum
+		 * >we must be careful.  The user must be aware that this
+		 * >routine will write more bytes than he asked for.
+		 * >The length of the buffer must be correct.
+		 * FIXED - Should be ok now 18-9-90 - eay */
+		if (len < rnum) {
+			if (DES_rw_mode & DES_PCBC_MODE)
+				DES_pcbc_encrypt(net, tmpbuf, num, sched, iv,
+				    DES_DECRYPT);
+			else
+				DES_cbc_encrypt(net, tmpbuf, num, sched, iv,
+				    DES_DECRYPT);
+
+			/* eay 26/08/92 fix a bug that returned more
+			 * bytes than you asked for (returned len bytes :-( */
+			memcpy(buf, tmpbuf, num);
+		} else {
+			if (DES_rw_mode & DES_PCBC_MODE)
+				DES_pcbc_encrypt(net, buf, num, sched, iv,
+				    DES_DECRYPT);
+			else
+				DES_cbc_encrypt(net, buf, num, sched, iv,
+				    DES_DECRYPT);
+		}
+	}
+	return num;
+}
diff --git a/crypto/des/enc_writ.c b/crypto/des/enc_writ.c
new file mode 100644
index 0000000..3def8a8
--- /dev/null
+++ b/crypto/des/enc_writ.c
@@ -0,0 +1,167 @@
+/* $OpenBSD: enc_writ.c,v 1.17 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "des_local.h"
+
+/*
+ * WARNINGS:
+ *
+ *  -  The data format used by DES_enc_write() and DES_enc_read()
+ *     has a cryptographic weakness: When asked to write more
+ *     than MAXWRITE bytes, DES_enc_write will split the data
+ *     into several chunks that are all encrypted
+ *     using the same IV.  So don't use these functions unless you
+ *     are sure you know what you do (in which case you might
+ *     not want to use them anyway).
+ *
+ *  -  This code cannot handle non-blocking sockets.
+ */
+
+int
+DES_enc_write(int fd, const void *_buf, int len,
+    DES_key_schedule *sched, DES_cblock *iv)
+{
+#ifdef _LIBC
+	extern unsigned long time();
+	extern int write();
+#endif
+	const unsigned char *buf = _buf;
+	long rnum;
+	int i, j, k, outnum;
+	static unsigned char *outbuf = NULL;
+	unsigned char shortbuf[8];
+	unsigned char *p;
+	const unsigned char *cp;
+	static int start = 1;
+
+	if (outbuf == NULL) {
+		outbuf = malloc(BSIZE + HDRSIZE);
+		if (outbuf == NULL)
+			return (-1);
+	}
+	/* If we are sending less than 8 bytes, the same char will look
+	 * the same if we don't pad it out with random bytes */
+	if (start) {
+		start = 0;
+	}
+
+	/* lets recurse if we want to send the data in small chunks */
+	if (len > MAXWRITE) {
+		j = 0;
+		for (i = 0; i < len; i += k) {
+			k = DES_enc_write(fd, &(buf[i]),
+			    ((len - i) > MAXWRITE) ? MAXWRITE : (len - i),
+			    sched, iv);
+			if (k < 0)
+				return (k);
+			else
+				j += k;
+		}
+		return (j);
+	}
+
+	/* write length first */
+	p = outbuf;
+	l2n(len, p);
+
+	/* pad short strings */
+	if (len < 8) {
+		cp = shortbuf;
+		memcpy(shortbuf, buf, len);
+		arc4random_buf(shortbuf + len, 8 - len);
+		rnum = 8;
+	} else {
+		cp = buf;
+		rnum = ((len + 7)/8*8); /* round up to nearest eight */
+	}
+
+	if (DES_rw_mode & DES_PCBC_MODE)
+		DES_pcbc_encrypt(cp, &(outbuf[HDRSIZE]), (len < 8) ? 8 : len,
+		    sched, iv, DES_ENCRYPT);
+	else
+		DES_cbc_encrypt(cp, &(outbuf[HDRSIZE]), (len < 8) ? 8 : len,
+		    sched, iv, DES_ENCRYPT);
+
+	/* output */
+	outnum = rnum + HDRSIZE;
+
+	for (j = 0; j < outnum; j += i) {
+		/* eay 26/08/92 I was not doing writing from where we
+		 * got up to. */
+		i = write(fd, (void *)&(outbuf[j]), outnum - j);
+		if (i == -1) {
+#ifdef EINTR
+			if (errno == EINTR)
+				i = 0;
+			else
+#endif
+				/* This is really a bad error - very bad
+				 * It will stuff-up both ends. */
+				return (-1);
+		}
+	}
+
+	return (len);
+}
diff --git a/crypto/des/fcrypt.c b/crypto/des/fcrypt.c
new file mode 100644
index 0000000..b183cee
--- /dev/null
+++ b/crypto/des/fcrypt.c
@@ -0,0 +1,125 @@
+/* $OpenBSD: fcrypt.c,v 1.15 2023/07/08 07:34:34 jsing Exp $ */
+
+#include 
+
+/* This version of crypt has been developed from my MIT compatible
+ * DES library.
+ * Eric Young (eay@cryptsoft.com)
+ */
+
+/* Modification by Jens Kupferschmidt (Cu)
+ * I have included directive PARA for shared memory computers.
+ * I have included a directive LONGCRYPT to using this routine to cipher
+ * passwords with more than 8 bytes like HP-UX 10.x it used. The MAXPLEN
+ * definition is the maximum of length of password and can changed. I have
+ * defined 24.
+ */
+
+#include "des_local.h"
+
+/* Added more values to handle illegal salt values the way normal
+ * crypt() implementations do.  The patch was sent by
+ * Bjorn Gronvall 
+ */
+static unsigned const 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,
+	0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1,
+	0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9,
+	0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0x00, 0x01,
+	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+	0x0A, 0x0B, 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, 0x20, 0x21, 0x22,
+	0x23, 0x24, 0x25, 0x20, 0x21, 0x22, 0x23, 0x24,
+	0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C,
+	0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
+	0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C,
+	0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,
+};
+
+static unsigned const 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,
+	0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
+	0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62,
+	0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A,
+	0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
+	0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A
+};
+
+char *
+DES_crypt(const char *buf, const char *salt)
+{
+	static char buff[14];
+
+	return (DES_fcrypt(buf, salt, buff));
+}
+
+char *
+DES_fcrypt(const char *buf, const char *salt, char *ret)
+{
+	unsigned int i, j, x, y;
+	DES_LONG Eswap0, Eswap1;
+	DES_LONG out[2], ll;
+	DES_cblock key;
+	DES_key_schedule ks;
+	unsigned char bb[9];
+	unsigned char *b = bb;
+	unsigned char c, u;
+
+	/* eay 25/08/92
+	 * If you call crypt("pwd","*") as often happens when you
+	 * have * as the pwd field in /etc/passwd, the function
+	 * returns *\0xxxxxxxxx
+	 * The \0 makes the string look like * so the pwd "*" would
+	 * crypt to "*".  This was found when replacing the crypt in
+	 * our shared libraries.  People found that the disabled
+	 * accounts effectively had no passwd :-(. */
+	x = ret[0] = ((salt[0] == '\0') ? 'A' : salt[0]);
+	Eswap0 = con_salt[x] << 2;
+	x = ret[1] = ((salt[1] == '\0') ? 'A' : salt[1]);
+	Eswap1 = con_salt[x] << 6;
+/* EAY
+r=strlen(buf);
+r=(r+7)/8;
+*/
+	for (i = 0; i < 8; i++) {
+		c = *(buf++);
+		if (!c)
+			break;
+		key[i] = (c << 1);
+	}
+	for (; i < 8; i++)
+		key[i] = 0;
+
+	DES_set_key_unchecked(&key, &ks);
+	fcrypt_body(&(out[0]), &ks, Eswap0, Eswap1);
+
+	ll = out[0];
+	l2c(ll, b);
+	ll = out[1];
+	l2c(ll, b);
+	y = 0;
+	u = 0x80;
+	bb[8] = 0;
+	for (i = 2; i < 13; i++) {
+		c = 0;
+		for (j = 0; j < 6; j++) {
+			c <<= 1;
+			if (bb[y] & u)
+				c |= 1;
+			u >>= 1;
+			if (!u) {
+				y++;
+				u = 0x80;
+			}
+		}
+		ret[i] = cov_2char[c];
+	}
+	ret[13] = '\0';
+	return (ret);
+}
diff --git a/crypto/des/fcrypt_b.c b/crypto/des/fcrypt_b.c
new file mode 100644
index 0000000..58c9bc3
--- /dev/null
+++ b/crypto/des/fcrypt_b.c
@@ -0,0 +1,145 @@
+/* $OpenBSD: fcrypt_b.c,v 1.12 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+/* This version of crypt has been developed from my MIT compatible
+ * DES library.
+ * The library is available at pub/Crypto/DES at ftp.psy.uq.oz.au
+ * Eric Young (eay@cryptsoft.com)
+ */
+
+#define DES_FCRYPT
+#include "des_local.h"
+#undef DES_FCRYPT
+
+#ifndef OPENBSD_DES_ASM
+
+#undef PERM_OP
+#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),			\
+	(b)^=(t),							\
+	(a)^=((t)<<(n)))
+
+#undef HPERM_OP
+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),		\
+	(a)=(a)^(t)^(t>>(16-(n))))					\
+
+void
+fcrypt_body(DES_LONG *out, DES_key_schedule *ks, DES_LONG Eswap0,
+    DES_LONG Eswap1)
+{
+	DES_LONG l, r, t, u;
+#ifdef DES_PTR
+	const unsigned char *des_SP = (const unsigned char *)DES_SPtrans;
+#endif
+	DES_LONG *s;
+	int j;
+	DES_LONG E0, E1;
+
+	l = 0;
+	r = 0;
+
+	s = (DES_LONG *)ks;
+	E0 = Eswap0;
+	E1 = Eswap1;
+
+	for (j = 0; j < 25; j++) {
+#ifndef DES_UNROLL
+		int i;
+
+		for (i = 0; i < 32; i += 4) {
+			D_ENCRYPT(l, r, i + 0); /*  1 */
+			D_ENCRYPT(r, l, i + 2); /*  2 */
+		}
+#else
+		D_ENCRYPT(l, r, 0); /*  1 */
+		D_ENCRYPT(r, l, 2); /*  2 */
+		D_ENCRYPT(l, r, 4); /*  3 */
+		D_ENCRYPT(r, l, 6); /*  4 */
+		D_ENCRYPT(l, r, 8); /*  5 */
+		D_ENCRYPT(r, l, 10); /*  6 */
+		D_ENCRYPT(l, r, 12); /*  7 */
+		D_ENCRYPT(r, l, 14); /*  8 */
+		D_ENCRYPT(l, r, 16); /*  9 */
+		D_ENCRYPT(r, l, 18); /*  10 */
+		D_ENCRYPT(l, r, 20); /*  11 */
+		D_ENCRYPT(r, l, 22); /*  12 */
+		D_ENCRYPT(l, r, 24); /*  13 */
+		D_ENCRYPT(r, l, 26); /*  14 */
+		D_ENCRYPT(l, r, 28); /*  15 */
+		D_ENCRYPT(r, l, 30); /*  16 */
+#endif
+
+		t = l;
+		l = r;
+		r = t;
+	}
+	l = ROTATE(l, 3) & 0xffffffffL;
+	r = ROTATE(r, 3) & 0xffffffffL;
+
+	PERM_OP(l, r, t, 1, 0x55555555L);
+	PERM_OP(r, l, t, 8, 0x00ff00ffL);
+	PERM_OP(l, r, t, 2, 0x33333333L);
+	PERM_OP(r, l, t, 16, 0x0000ffffL);
+	PERM_OP(l, r, t, 4, 0x0f0f0f0fL);
+
+	out[0] = r;
+	out[1] = l;
+}
+
+#endif /* OPENBSD_DES_ASM */
diff --git a/crypto/des/ncbc_enc.c b/crypto/des/ncbc_enc.c
new file mode 100644
index 0000000..c4da94c
--- /dev/null
+++ b/crypto/des/ncbc_enc.c
@@ -0,0 +1,155 @@
+/* $OpenBSD: ncbc_enc.c,v 1.10 2023/07/08 07:34:34 jsing Exp $ */
+/*
+ * #included by:
+ *    cbc_enc.c  (DES_cbc_encrypt)
+ *    des_enc.c  (DES_ncbc_encrypt)
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+#ifdef CBC_ENC_C__DONT_UPDATE_IV
+void
+DES_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    DES_key_schedule *_schedule, DES_cblock *ivec, int enc)
+#else
+void
+DES_ncbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    DES_key_schedule *_schedule, DES_cblock *ivec, int enc)
+#endif
+{
+	DES_LONG tin0, tin1;
+	DES_LONG tout0, tout1, xor0, xor1;
+	long l = length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	iv = &(*ivec)[0];
+
+	if (enc) {
+		c2l(iv, tout0);
+		c2l(iv, tout1);
+		for (l -= 8; l >= 0; l -= 8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+			tin0 ^= tout0;
+			tin[0] = tin0;
+			tin1 ^= tout1;
+			tin[1] = tin1;
+			DES_encrypt1((DES_LONG *)tin, _schedule, DES_ENCRYPT);
+			tout0 = tin[0];
+			l2c(tout0, out);
+			tout1 = tin[1];
+			l2c(tout1, out);
+		}
+		if (l != -8) {
+			c2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin[0] = tin0;
+			tin1 ^= tout1;
+			tin[1] = tin1;
+			DES_encrypt1((DES_LONG *)tin, _schedule, DES_ENCRYPT);
+			tout0 = tin[0];
+			l2c(tout0, out);
+			tout1 = tin[1];
+			l2c(tout1, out);
+		}
+#ifndef CBC_ENC_C__DONT_UPDATE_IV
+		iv = &(*ivec)[0];
+		l2c(tout0, iv);
+		l2c(tout1, iv);
+#endif
+	} else {
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		for (l -= 8; l >= 0; l -= 8) {
+			c2l(in, tin0);
+			tin[0] = tin0;
+			c2l(in, tin1);
+			tin[1] = tin1;
+			DES_encrypt1((DES_LONG *)tin, _schedule, DES_DECRYPT);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2c(tout0, out);
+			l2c(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			c2l(in, tin0);
+			tin[0] = tin0;
+			c2l(in, tin1);
+			tin[1] = tin1;
+			DES_encrypt1((DES_LONG *)tin, _schedule, DES_DECRYPT);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2cn(tout0, tout1, out, l + 8);
+#ifndef CBC_ENC_C__DONT_UPDATE_IV
+			xor0 = tin0;
+			xor1 = tin1;
+#endif
+		}
+#ifndef CBC_ENC_C__DONT_UPDATE_IV
+		iv = &(*ivec)[0];
+		l2c(xor0, iv);
+		l2c(xor1, iv);
+#endif
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
diff --git a/crypto/des/ofb64ede.c b/crypto/des/ofb64ede.c
new file mode 100644
index 0000000..2922fc7
--- /dev/null
+++ b/crypto/des/ofb64ede.c
@@ -0,0 +1,112 @@
+/* $OpenBSD: ofb64ede.c,v 1.8 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+DES_ede3_ofb64_encrypt(const unsigned char *in,
+    unsigned char *out, long length,
+    DES_key_schedule *k1, DES_key_schedule *k2,
+    DES_key_schedule *k3, DES_cblock *ivec,
+    int *num)
+{
+	DES_LONG v0, v1;
+	int n = *num;
+	long l = length;
+	DES_cblock d;
+	char *dp;
+	DES_LONG ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = &(*ivec)[0];
+	c2l(iv, v0);
+	c2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = (char *)d;
+	l2c(v0, dp);
+	l2c(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			/* ti[0]=v0; */
+			/* ti[1]=v1; */
+			DES_encrypt3(ti, k1, k2, k3);
+			v0 = ti[0];
+			v1 = ti[1];
+
+			dp = (char *)d;
+			l2c(v0, dp);
+			l2c(v1, dp);
+			save++;
+		}
+		*(out++) = *(in++) ^ d[n];
+		n = (n + 1) & 0x07;
+	}
+	if (save) {
+		iv = &(*ivec)[0];
+		l2c(v0, iv);
+		l2c(v1, iv);
+	}
+	v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
diff --git a/crypto/des/ofb64enc.c b/crypto/des/ofb64enc.c
new file mode 100644
index 0000000..c3b1b8a
--- /dev/null
+++ b/crypto/des/ofb64enc.c
@@ -0,0 +1,109 @@
+/* $OpenBSD: ofb64enc.c,v 1.8 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+DES_ofb64_encrypt(const unsigned char *in,
+    unsigned char *out, long length,
+    DES_key_schedule *schedule, DES_cblock *ivec, int *num)
+{
+	DES_LONG v0, v1, t;
+	int n = *num;
+	long l = length;
+	DES_cblock d;
+	unsigned char *dp;
+	DES_LONG ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = &(*ivec)[0];
+	c2l(iv, v0);
+	c2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = d;
+	l2c(v0, dp);
+	l2c(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			DES_encrypt1(ti, schedule, DES_ENCRYPT);
+			dp = d;
+			t = ti[0];
+			l2c(t, dp);
+			t = ti[1];
+			l2c(t, dp);
+			save++;
+		}
+		*(out++) = *(in++) ^ d[n];
+		n = (n + 1) & 0x07;
+	}
+	if (save) {
+		v0 = ti[0];
+		v1 = ti[1];
+		iv = &(*ivec)[0];
+		l2c(v0, iv);
+		l2c(v1, iv);
+	}
+	t = v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
diff --git a/crypto/des/ofb_enc.c b/crypto/des/ofb_enc.c
new file mode 100644
index 0000000..990b927
--- /dev/null
+++ b/crypto/des/ofb_enc.c
@@ -0,0 +1,133 @@
+/* $OpenBSD: ofb_enc.c,v 1.8 2023/07/08 07:11:07 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* The input and output are loaded in multiples of 8 bits.
+ * What this means is that if you hame numbits=12 and length=2
+ * the first 12 bits will be retrieved from the first byte and half
+ * the second.  The second 12 bits will come from the 3rd and half the 4th
+ * byte.
+ */
+void
+DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits,
+    long length, DES_key_schedule *schedule,
+    DES_cblock *ivec)
+{
+	DES_LONG d0, d1, vv0, vv1, v0, v1, n = (numbits + 7)/8;
+	DES_LONG mask0, mask1;
+	long l = length;
+	int num = numbits;
+	DES_LONG ti[2];
+	unsigned char *iv;
+
+	if (num > 64)
+		return;
+	if (num > 32) {
+		mask0 = 0xffffffffL;
+		if (num >= 64)
+			mask1 = mask0;
+		else
+			mask1 = (1L << (num - 32)) - 1;
+	} else {
+		if (num == 32)
+			mask0 = 0xffffffffL;
+		else
+			mask0 = (1L << num) - 1;
+		mask1 = 0x00000000L;
+	}
+
+	iv = &(*ivec)[0];
+	c2l(iv, v0);
+	c2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	while (l-- > 0) {
+		ti[0] = v0;
+		ti[1] = v1;
+		DES_encrypt1((DES_LONG *)ti, schedule, DES_ENCRYPT);
+		vv0 = ti[0];
+		vv1 = ti[1];
+		c2ln(in, d0, d1, n);
+		in += n;
+		d0 = (d0 ^ vv0) & mask0;
+		d1 = (d1 ^ vv1) & mask1;
+		l2cn(d0, d1, out, n);
+		out += n;
+
+		if (num == 32) {
+			v0 = v1;
+			v1 = vv0;
+		} else if (num == 64) {
+			v0 = vv0;
+			v1 = vv1;
+		} else if (num > 32) { /* && num != 64 */
+			v0 = ((v1 >> (num - 32))|(vv0 << (64 - num))) &
+			    0xffffffffL;
+			v1 = ((vv0 >> (num - 32))|(vv1 << (64 - num))) &
+			    0xffffffffL;
+		} else /* num < 32 */ {
+			v0 = ((v0 >> num)|(v1 << (32 - num))) & 0xffffffffL;
+			v1 = ((v1 >> num)|(vv0 << (32 - num))) & 0xffffffffL;
+		}
+	}
+	iv = &(*ivec)[0];
+	l2c(v0, iv);
+	l2c(v1, iv);
+	v0 = v1 = d0 = d1 = ti[0] = ti[1] = vv0 = vv1 = 0;
+}
diff --git a/crypto/des/pcbc_enc.c b/crypto/des/pcbc_enc.c
new file mode 100644
index 0000000..3a420f0
--- /dev/null
+++ b/crypto/des/pcbc_enc.c
@@ -0,0 +1,116 @@
+/* $OpenBSD: pcbc_enc.c,v 1.9 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+void
+DES_pcbc_encrypt(const unsigned char *input, unsigned char *output,
+    long length, DES_key_schedule *schedule,
+    DES_cblock *ivec, int enc)
+{
+	DES_LONG sin0, sin1, xor0, xor1, tout0, tout1;
+	DES_LONG tin[2];
+	const unsigned char *in;
+	unsigned char *out, *iv;
+
+	in = input;
+	out = output;
+	iv = &(*ivec)[0];
+
+	if (enc) {
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		for (; length > 0; length -= 8) {
+			if (length >= 8) {
+				c2l(in, sin0);
+				c2l(in, sin1);
+			} else
+				c2ln(in, sin0, sin1, length);
+			tin[0] = sin0 ^ xor0;
+			tin[1] = sin1 ^ xor1;
+			DES_encrypt1((DES_LONG *)tin, schedule, DES_ENCRYPT);
+			tout0 = tin[0];
+			tout1 = tin[1];
+			xor0 = sin0 ^ tout0;
+			xor1 = sin1 ^ tout1;
+			l2c(tout0, out);
+			l2c(tout1, out);
+		}
+	} else {
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		for (; length > 0; length -= 8) {
+			c2l(in, sin0);
+			c2l(in, sin1);
+			tin[0] = sin0;
+			tin[1] = sin1;
+			DES_encrypt1((DES_LONG *)tin, schedule, DES_DECRYPT);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			if (length >= 8) {
+				l2c(tout0, out);
+				l2c(tout1, out);
+			} else
+				l2cn(tout0, tout1, out, length);
+			xor0 = tout0 ^ sin0;
+			xor1 = tout1 ^ sin1;
+		}
+	}
+	tin[0] = tin[1] = 0;
+	sin0 = sin1 = xor0 = xor1 = tout0 = tout1 = 0;
+}
diff --git a/crypto/des/qud_cksm.c b/crypto/des/qud_cksm.c
new file mode 100644
index 0000000..ab28668
--- /dev/null
+++ b/crypto/des/qud_cksm.c
@@ -0,0 +1,125 @@
+/* $OpenBSD: qud_cksm.c,v 1.10 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* From "Message Authentication"  R.R. Jueneman, S.M. Matyas, C.H. Meyer
+ * IEEE Communications Magazine Sept 1985 Vol. 23 No. 9 p 29-40
+ * This module in only based on the code in this paper and is
+ * almost definitely not the same as the MIT implementation.
+ */
+#include "des_local.h"
+
+/* bug fix for dos - 7/6/91 - Larry hughes@logos.ucs.indiana.edu */
+#define Q_B0(a)	(((DES_LONG)(a)))
+#define Q_B1(a)	(((DES_LONG)(a))<<8)
+#define Q_B2(a)	(((DES_LONG)(a))<<16)
+#define Q_B3(a)	(((DES_LONG)(a))<<24)
+
+/* used to scramble things a bit */
+/* Got the value MIT uses via brute force :-) 2/10/90 eay */
+#define NOISE	((DES_LONG)83653421L)
+
+DES_LONG
+DES_quad_cksum(const unsigned char *input, DES_cblock output[],
+    long length, int out_count, DES_cblock *seed)
+{
+	DES_LONG z0, z1, t0, t1;
+	int i;
+	long l;
+	const unsigned char *cp;
+	DES_LONG *lp;
+
+	if (out_count < 1)
+		out_count = 1;
+	lp = (DES_LONG *)&(output[0])[0];
+
+	z0 = Q_B0((*seed)[0])|Q_B1((*seed)[1])|Q_B2((*seed)[2])|Q_B3(
+	    (*seed)[3]);
+	z1 = Q_B0((*seed)[4])|Q_B1((*seed)[5])|Q_B2((*seed)[6])|Q_B3(
+	    (*seed)[7]);
+
+	for (i = 0; ((i < 4) && (i < out_count)); i++) {
+		cp = input;
+		l = length;
+		while (l > 0) {
+			if (l > 1) {
+				t0 = (DES_LONG)(*(cp++));
+				t0 |= (DES_LONG)Q_B1(*(cp++));
+				l--;
+			} else
+				t0 = (DES_LONG)(*(cp++));
+			l--;
+			/* add */
+			t0 += z0;
+			t0 &= 0xffffffffL;
+			t1 = z1;
+			/* square, well sort of square */
+			z0 = ((((t0*t0) & 0xffffffffL) +
+			    ((t1*t1) & 0xffffffffL)) & 0xffffffffL) %
+			    0x7fffffffL;
+			z1 = ((t0*((t1 + NOISE) & 0xffffffffL)) & 0xffffffffL) %
+			    0x7fffffffL;
+		}
+		if (lp != NULL) {
+			/* The MIT library assumes that the checksum is
+			 * composed of 2*out_count 32 bit ints */
+			*lp++ = z0;
+			*lp++ = z1;
+		}
+	}
+	return (z0);
+}
diff --git a/crypto/des/rand_key.c b/crypto/des/rand_key.c
new file mode 100644
index 0000000..aba899f
--- /dev/null
+++ b/crypto/des/rand_key.c
@@ -0,0 +1,68 @@
+/* $OpenBSD: rand_key.c,v 1.9 2023/07/08 07:11:07 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+int
+DES_random_key(DES_cblock *ret)
+{
+	do {
+		arc4random_buf(ret, sizeof(DES_cblock));
+		DES_set_odd_parity(ret);
+	} while (DES_is_weak_key(ret));
+	return (1);
+}
diff --git a/crypto/des/set_key.c b/crypto/des/set_key.c
new file mode 100644
index 0000000..91116c4
--- /dev/null
+++ b/crypto/des/set_key.c
@@ -0,0 +1,407 @@
+/* $OpenBSD: set_key.c,v 1.23 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* set_key.c v 1.4 eay 24/9/91
+ * 1.4 Speed up by 400% :-)
+ * 1.3 added register declarations.
+ * 1.2 unrolled make_key_sched a bit more
+ * 1.1 added norm_expand_bits
+ * 1.0 First working version
+ */
+#include 
+#include "des_local.h"
+
+int DES_check_key = 0;	/* defaults to false */
+
+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,
+	32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
+	49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
+	64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
+	81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
+	97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110,
+	112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127,
+	128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143,
+	145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158,
+	161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174,
+	176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191,
+	193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206,
+	208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223,
+	224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239,
+	241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254,
+};
+
+void
+DES_set_odd_parity(DES_cblock *key)
+{
+	unsigned int i;
+
+	for (i = 0; i < DES_KEY_SZ; i++)
+		(*key)[i] = odd_parity[(*key)[i]];
+}
+
+int
+DES_check_key_parity(const_DES_cblock *key)
+{
+	unsigned int i;
+
+	for (i = 0; i < DES_KEY_SZ; i++) {
+		if ((*key)[i] != odd_parity[(*key)[i]])
+			return (0);
+	}
+	return (1);
+}
+
+/* Weak and semi weak keys as taken from
+ * %A D.W. Davies
+ * %A W.L. Price
+ * %T Security for Computer Networks
+ * %I John Wiley & Sons
+ * %D 1984
+ * Many thanks to smb@ulysses.att.com (Steven Bellovin) for the reference
+ * (and actual cblock values).
+ */
+#define NUM_WEAK_KEY	16
+static const DES_cblock weak_keys[NUM_WEAK_KEY] = {
+	/* weak keys */
+	{0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
+	{0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE},
+	{0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
+	{0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1},
+	/* semi-weak keys */
+	{0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE},
+	{0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01},
+	{0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1},
+	{0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E},
+	{0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1},
+	{0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01},
+	{0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE},
+	{0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E},
+	{0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E},
+	{0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01},
+	{0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
+	{0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1},
+};
+
+int
+DES_is_weak_key(const_DES_cblock *key)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_WEAK_KEY; i++)
+		if (memcmp(weak_keys[i], key, sizeof(DES_cblock)) == 0)
+			return 1;
+	return 0;
+}
+
+/* NOW DEFINED IN des_local.h
+ * See ecb_encrypt.c for a pseudo description of these macros.
+ * #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
+ * 	(b)^=(t),\
+ * 	(a)=((a)^((t)<<(n))))
+ */
+
+#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)), \
+	(a)=(a)^(t)^(t>>(16-(n))))
+
+static const DES_LONG des_skb[8][64] = {
+	{
+		/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+		0x00000000L, 0x00000010L, 0x20000000L, 0x20000010L,
+		0x00010000L, 0x00010010L, 0x20010000L, 0x20010010L,
+		0x00000800L, 0x00000810L, 0x20000800L, 0x20000810L,
+		0x00010800L, 0x00010810L, 0x20010800L, 0x20010810L,
+		0x00000020L, 0x00000030L, 0x20000020L, 0x20000030L,
+		0x00010020L, 0x00010030L, 0x20010020L, 0x20010030L,
+		0x00000820L, 0x00000830L, 0x20000820L, 0x20000830L,
+		0x00010820L, 0x00010830L, 0x20010820L, 0x20010830L,
+		0x00080000L, 0x00080010L, 0x20080000L, 0x20080010L,
+		0x00090000L, 0x00090010L, 0x20090000L, 0x20090010L,
+		0x00080800L, 0x00080810L, 0x20080800L, 0x20080810L,
+		0x00090800L, 0x00090810L, 0x20090800L, 0x20090810L,
+		0x00080020L, 0x00080030L, 0x20080020L, 0x20080030L,
+		0x00090020L, 0x00090030L, 0x20090020L, 0x20090030L,
+		0x00080820L, 0x00080830L, 0x20080820L, 0x20080830L,
+		0x00090820L, 0x00090830L, 0x20090820L, 0x20090830L,
+	}, {
+		/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
+		0x00000000L, 0x02000000L, 0x00002000L, 0x02002000L,
+		0x00200000L, 0x02200000L, 0x00202000L, 0x02202000L,
+		0x00000004L, 0x02000004L, 0x00002004L, 0x02002004L,
+		0x00200004L, 0x02200004L, 0x00202004L, 0x02202004L,
+		0x00000400L, 0x02000400L, 0x00002400L, 0x02002400L,
+		0x00200400L, 0x02200400L, 0x00202400L, 0x02202400L,
+		0x00000404L, 0x02000404L, 0x00002404L, 0x02002404L,
+		0x00200404L, 0x02200404L, 0x00202404L, 0x02202404L,
+		0x10000000L, 0x12000000L, 0x10002000L, 0x12002000L,
+		0x10200000L, 0x12200000L, 0x10202000L, 0x12202000L,
+		0x10000004L, 0x12000004L, 0x10002004L, 0x12002004L,
+		0x10200004L, 0x12200004L, 0x10202004L, 0x12202004L,
+		0x10000400L, 0x12000400L, 0x10002400L, 0x12002400L,
+		0x10200400L, 0x12200400L, 0x10202400L, 0x12202400L,
+		0x10000404L, 0x12000404L, 0x10002404L, 0x12002404L,
+		0x10200404L, 0x12200404L, 0x10202404L, 0x12202404L,
+	}, {
+		/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
+		0x00000000L, 0x00000001L, 0x00040000L, 0x00040001L,
+		0x01000000L, 0x01000001L, 0x01040000L, 0x01040001L,
+		0x00000002L, 0x00000003L, 0x00040002L, 0x00040003L,
+		0x01000002L, 0x01000003L, 0x01040002L, 0x01040003L,
+		0x00000200L, 0x00000201L, 0x00040200L, 0x00040201L,
+		0x01000200L, 0x01000201L, 0x01040200L, 0x01040201L,
+		0x00000202L, 0x00000203L, 0x00040202L, 0x00040203L,
+		0x01000202L, 0x01000203L, 0x01040202L, 0x01040203L,
+		0x08000000L, 0x08000001L, 0x08040000L, 0x08040001L,
+		0x09000000L, 0x09000001L, 0x09040000L, 0x09040001L,
+		0x08000002L, 0x08000003L, 0x08040002L, 0x08040003L,
+		0x09000002L, 0x09000003L, 0x09040002L, 0x09040003L,
+		0x08000200L, 0x08000201L, 0x08040200L, 0x08040201L,
+		0x09000200L, 0x09000201L, 0x09040200L, 0x09040201L,
+		0x08000202L, 0x08000203L, 0x08040202L, 0x08040203L,
+		0x09000202L, 0x09000203L, 0x09040202L, 0x09040203L,
+	}, {
+		/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
+		0x00000000L, 0x00100000L, 0x00000100L, 0x00100100L,
+		0x00000008L, 0x00100008L, 0x00000108L, 0x00100108L,
+		0x00001000L, 0x00101000L, 0x00001100L, 0x00101100L,
+		0x00001008L, 0x00101008L, 0x00001108L, 0x00101108L,
+		0x04000000L, 0x04100000L, 0x04000100L, 0x04100100L,
+		0x04000008L, 0x04100008L, 0x04000108L, 0x04100108L,
+		0x04001000L, 0x04101000L, 0x04001100L, 0x04101100L,
+		0x04001008L, 0x04101008L, 0x04001108L, 0x04101108L,
+		0x00020000L, 0x00120000L, 0x00020100L, 0x00120100L,
+		0x00020008L, 0x00120008L, 0x00020108L, 0x00120108L,
+		0x00021000L, 0x00121000L, 0x00021100L, 0x00121100L,
+		0x00021008L, 0x00121008L, 0x00021108L, 0x00121108L,
+		0x04020000L, 0x04120000L, 0x04020100L, 0x04120100L,
+		0x04020008L, 0x04120008L, 0x04020108L, 0x04120108L,
+		0x04021000L, 0x04121000L, 0x04021100L, 0x04121100L,
+		0x04021008L, 0x04121008L, 0x04021108L, 0x04121108L,
+	}, {
+		/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
+		0x00000000L, 0x10000000L, 0x00010000L, 0x10010000L,
+		0x00000004L, 0x10000004L, 0x00010004L, 0x10010004L,
+		0x20000000L, 0x30000000L, 0x20010000L, 0x30010000L,
+		0x20000004L, 0x30000004L, 0x20010004L, 0x30010004L,
+		0x00100000L, 0x10100000L, 0x00110000L, 0x10110000L,
+		0x00100004L, 0x10100004L, 0x00110004L, 0x10110004L,
+		0x20100000L, 0x30100000L, 0x20110000L, 0x30110000L,
+		0x20100004L, 0x30100004L, 0x20110004L, 0x30110004L,
+		0x00001000L, 0x10001000L, 0x00011000L, 0x10011000L,
+		0x00001004L, 0x10001004L, 0x00011004L, 0x10011004L,
+		0x20001000L, 0x30001000L, 0x20011000L, 0x30011000L,
+		0x20001004L, 0x30001004L, 0x20011004L, 0x30011004L,
+		0x00101000L, 0x10101000L, 0x00111000L, 0x10111000L,
+		0x00101004L, 0x10101004L, 0x00111004L, 0x10111004L,
+		0x20101000L, 0x30101000L, 0x20111000L, 0x30111000L,
+		0x20101004L, 0x30101004L, 0x20111004L, 0x30111004L,
+	}, {
+		/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
+		0x00000000L, 0x08000000L, 0x00000008L, 0x08000008L,
+		0x00000400L, 0x08000400L, 0x00000408L, 0x08000408L,
+		0x00020000L, 0x08020000L, 0x00020008L, 0x08020008L,
+		0x00020400L, 0x08020400L, 0x00020408L, 0x08020408L,
+		0x00000001L, 0x08000001L, 0x00000009L, 0x08000009L,
+		0x00000401L, 0x08000401L, 0x00000409L, 0x08000409L,
+		0x00020001L, 0x08020001L, 0x00020009L, 0x08020009L,
+		0x00020401L, 0x08020401L, 0x00020409L, 0x08020409L,
+		0x02000000L, 0x0A000000L, 0x02000008L, 0x0A000008L,
+		0x02000400L, 0x0A000400L, 0x02000408L, 0x0A000408L,
+		0x02020000L, 0x0A020000L, 0x02020008L, 0x0A020008L,
+		0x02020400L, 0x0A020400L, 0x02020408L, 0x0A020408L,
+		0x02000001L, 0x0A000001L, 0x02000009L, 0x0A000009L,
+		0x02000401L, 0x0A000401L, 0x02000409L, 0x0A000409L,
+		0x02020001L, 0x0A020001L, 0x02020009L, 0x0A020009L,
+		0x02020401L, 0x0A020401L, 0x02020409L, 0x0A020409L,
+	}, {
+		/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
+		0x00000000L, 0x00000100L, 0x00080000L, 0x00080100L,
+		0x01000000L, 0x01000100L, 0x01080000L, 0x01080100L,
+		0x00000010L, 0x00000110L, 0x00080010L, 0x00080110L,
+		0x01000010L, 0x01000110L, 0x01080010L, 0x01080110L,
+		0x00200000L, 0x00200100L, 0x00280000L, 0x00280100L,
+		0x01200000L, 0x01200100L, 0x01280000L, 0x01280100L,
+		0x00200010L, 0x00200110L, 0x00280010L, 0x00280110L,
+		0x01200010L, 0x01200110L, 0x01280010L, 0x01280110L,
+		0x00000200L, 0x00000300L, 0x00080200L, 0x00080300L,
+		0x01000200L, 0x01000300L, 0x01080200L, 0x01080300L,
+		0x00000210L, 0x00000310L, 0x00080210L, 0x00080310L,
+		0x01000210L, 0x01000310L, 0x01080210L, 0x01080310L,
+		0x00200200L, 0x00200300L, 0x00280200L, 0x00280300L,
+		0x01200200L, 0x01200300L, 0x01280200L, 0x01280300L,
+		0x00200210L, 0x00200310L, 0x00280210L, 0x00280310L,
+		0x01200210L, 0x01200310L, 0x01280210L, 0x01280310L,
+	}, {
+		/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
+		0x00000000L, 0x04000000L, 0x00040000L, 0x04040000L,
+		0x00000002L, 0x04000002L, 0x00040002L, 0x04040002L,
+		0x00002000L, 0x04002000L, 0x00042000L, 0x04042000L,
+		0x00002002L, 0x04002002L, 0x00042002L, 0x04042002L,
+		0x00000020L, 0x04000020L, 0x00040020L, 0x04040020L,
+		0x00000022L, 0x04000022L, 0x00040022L, 0x04040022L,
+		0x00002020L, 0x04002020L, 0x00042020L, 0x04042020L,
+		0x00002022L, 0x04002022L, 0x00042022L, 0x04042022L,
+		0x00000800L, 0x04000800L, 0x00040800L, 0x04040800L,
+		0x00000802L, 0x04000802L, 0x00040802L, 0x04040802L,
+		0x00002800L, 0x04002800L, 0x00042800L, 0x04042800L,
+		0x00002802L, 0x04002802L, 0x00042802L, 0x04042802L,
+		0x00000820L, 0x04000820L, 0x00040820L, 0x04040820L,
+		0x00000822L, 0x04000822L, 0x00040822L, 0x04040822L,
+		0x00002820L, 0x04002820L, 0x00042820L, 0x04042820L,
+		0x00002822L, 0x04002822L, 0x00042822L, 0x04042822L,
+	},
+};
+
+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;
+	}
+}
+
+/* return 0 if key parity is odd (correct),
+ * return -1 if key parity error,
+ * return -2 if illegal weak key.
+ */
+int
+DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule)
+{
+	if (!DES_check_key_parity(key))
+		return (-1);
+	if (DES_is_weak_key(key))
+		return (-2);
+	DES_set_key_unchecked(key, schedule);
+	return 0;
+}
+
+void
+DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule)
+{
+	static const int shifts2[16] = {0, 0,1, 1,1, 1,1, 1,0, 1,1, 1,1, 1,1, 0};
+	DES_LONG c, d, t, s, t2;
+	const unsigned char *in;
+	DES_LONG *k;
+	int i;
+
+	k = &schedule->ks->deslong[0];
+	in = &(*key)[0];
+
+	c2l(in, c);
+	c2l(in, d);
+
+	/* do PC1 in 47 simple operations :-)
+	 * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
+	 * for the inspiration. :-) */
+	PERM_OP(d, c, t, 4, 0x0f0f0f0fL);
+	HPERM_OP(c, t, -2, 0xcccc0000L);
+	HPERM_OP(d, t, -2, 0xcccc0000L);
+	PERM_OP(d, c, t, 1, 0x55555555L);
+	PERM_OP(c, d, t, 8, 0x00ff00ffL);
+	PERM_OP(d, c, t, 1, 0x55555555L);
+	d = (((d & 0x000000ffL) << 16L) | (d & 0x0000ff00L) |
+	    ((d & 0x00ff0000L) >> 16L)|((c & 0xf0000000L) >> 4L));
+	c &= 0x0fffffffL;
+
+	for (i = 0; i < ITERATIONS; i++) {
+		if (shifts2[i]) {
+			c = ((c >> 2L)|(c << 26L));
+			d = ((d >> 2L)|(d << 26L));
+		} else {
+			c = ((c >> 1L)|(c << 27L));
+			d = ((d >> 1L)|(d << 27L));
+		}
+		c &= 0x0fffffffL;
+		d &= 0x0fffffffL;
+		/* could be a few less shifts but I am to lazy at this
+		 * point in time to investigate */
+		s = des_skb[0][(c)&0x3f]|
+		    des_skb[1][((c >> 6L) & 0x03)|((c >> 7L) & 0x3c)]|
+		    des_skb[2][((c >> 13L) & 0x0f)|((c >> 14L) & 0x30)]|
+		    des_skb[3][((c >> 20L) & 0x01)|((c >> 21L) & 0x06) |
+		    ((c >> 22L) & 0x38)];
+		t = des_skb[4][(d)&0x3f]|
+		    des_skb[5][((d >> 7L) & 0x03)|((d >> 8L) & 0x3c)]|
+		    des_skb[6][(d >> 15L) & 0x3f]|
+		    des_skb[7][((d >> 21L) & 0x0f)|((d >> 22L) & 0x30)];
+
+		/* table contained 0213 4657 */
+		t2 = ((t << 16L)|(s & 0x0000ffffL)) & 0xffffffffL;
+		*(k++) = ROTATE(t2, 30) & 0xffffffffL;
+
+		t2 = ((s >> 16L)|(t & 0xffff0000L));
+		*(k++) = ROTATE(t2, 26) & 0xffffffffL;
+	}
+}
+
+int
+DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule)
+{
+	return (DES_set_key(key, schedule));
+}
+/*
+#undef des_fixup_key_parity
+void des_fixup_key_parity(des_cblock *key)
+	{
+	des_set_odd_parity(key);
+	}
+*/
diff --git a/crypto/des/spr.h b/crypto/des/spr.h
new file mode 100644
index 0000000..e0f413e
--- /dev/null
+++ b/crypto/des/spr.h
@@ -0,0 +1,209 @@
+/* $OpenBSD: spr.h,v 1.8 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+__BEGIN_HIDDEN_DECLS
+
+const DES_LONG DES_SPtrans[8][64] = {
+	{
+/* nibble 0 */
+		0x02080800L, 0x00080000L, 0x02000002L, 0x02080802L,
+		0x02000000L, 0x00080802L, 0x00080002L, 0x02000002L,
+		0x00080802L, 0x02080800L, 0x02080000L, 0x00000802L,
+		0x02000802L, 0x02000000L, 0x00000000L, 0x00080002L,
+		0x00080000L, 0x00000002L, 0x02000800L, 0x00080800L,
+		0x02080802L, 0x02080000L, 0x00000802L, 0x02000800L,
+		0x00000002L, 0x00000800L, 0x00080800L, 0x02080002L,
+		0x00000800L, 0x02000802L, 0x02080002L, 0x00000000L,
+		0x00000000L, 0x02080802L, 0x02000800L, 0x00080002L,
+		0x02080800L, 0x00080000L, 0x00000802L, 0x02000800L,
+		0x02080002L, 0x00000800L, 0x00080800L, 0x02000002L,
+		0x00080802L, 0x00000002L, 0x02000002L, 0x02080000L,
+		0x02080802L, 0x00080800L, 0x02080000L, 0x02000802L,
+		0x02000000L, 0x00000802L, 0x00080002L, 0x00000000L,
+		0x00080000L, 0x02000000L, 0x02000802L, 0x02080800L,
+		0x00000002L, 0x02080002L, 0x00000800L, 0x00080802L,
+	}, {
+/* nibble 1 */
+		0x40108010L, 0x00000000L, 0x00108000L, 0x40100000L,
+		0x40000010L, 0x00008010L, 0x40008000L, 0x00108000L,
+		0x00008000L, 0x40100010L, 0x00000010L, 0x40008000L,
+		0x00100010L, 0x40108000L, 0x40100000L, 0x00000010L,
+		0x00100000L, 0x40008010L, 0x40100010L, 0x00008000L,
+		0x00108010L, 0x40000000L, 0x00000000L, 0x00100010L,
+		0x40008010L, 0x00108010L, 0x40108000L, 0x40000010L,
+		0x40000000L, 0x00100000L, 0x00008010L, 0x40108010L,
+		0x00100010L, 0x40108000L, 0x40008000L, 0x00108010L,
+		0x40108010L, 0x00100010L, 0x40000010L, 0x00000000L,
+		0x40000000L, 0x00008010L, 0x00100000L, 0x40100010L,
+		0x00008000L, 0x40000000L, 0x00108010L, 0x40008010L,
+		0x40108000L, 0x00008000L, 0x00000000L, 0x40000010L,
+		0x00000010L, 0x40108010L, 0x00108000L, 0x40100000L,
+		0x40100010L, 0x00100000L, 0x00008010L, 0x40008000L,
+		0x40008010L, 0x00000010L, 0x40100000L, 0x00108000L,
+	}, {
+/* nibble 2 */
+		0x04000001L, 0x04040100L, 0x00000100L, 0x04000101L,
+		0x00040001L, 0x04000000L, 0x04000101L, 0x00040100L,
+		0x04000100L, 0x00040000L, 0x04040000L, 0x00000001L,
+		0x04040101L, 0x00000101L, 0x00000001L, 0x04040001L,
+		0x00000000L, 0x00040001L, 0x04040100L, 0x00000100L,
+		0x00000101L, 0x04040101L, 0x00040000L, 0x04000001L,
+		0x04040001L, 0x04000100L, 0x00040101L, 0x04040000L,
+		0x00040100L, 0x00000000L, 0x04000000L, 0x00040101L,
+		0x04040100L, 0x00000100L, 0x00000001L, 0x00040000L,
+		0x00000101L, 0x00040001L, 0x04040000L, 0x04000101L,
+		0x00000000L, 0x04040100L, 0x00040100L, 0x04040001L,
+		0x00040001L, 0x04000000L, 0x04040101L, 0x00000001L,
+		0x00040101L, 0x04000001L, 0x04000000L, 0x04040101L,
+		0x00040000L, 0x04000100L, 0x04000101L, 0x00040100L,
+		0x04000100L, 0x00000000L, 0x04040001L, 0x00000101L,
+		0x04000001L, 0x00040101L, 0x00000100L, 0x04040000L,
+	}, {
+/* nibble 3 */
+		0x00401008L, 0x10001000L, 0x00000008L, 0x10401008L,
+		0x00000000L, 0x10400000L, 0x10001008L, 0x00400008L,
+		0x10401000L, 0x10000008L, 0x10000000L, 0x00001008L,
+		0x10000008L, 0x00401008L, 0x00400000L, 0x10000000L,
+		0x10400008L, 0x00401000L, 0x00001000L, 0x00000008L,
+		0x00401000L, 0x10001008L, 0x10400000L, 0x00001000L,
+		0x00001008L, 0x00000000L, 0x00400008L, 0x10401000L,
+		0x10001000L, 0x10400008L, 0x10401008L, 0x00400000L,
+		0x10400008L, 0x00001008L, 0x00400000L, 0x10000008L,
+		0x00401000L, 0x10001000L, 0x00000008L, 0x10400000L,
+		0x10001008L, 0x00000000L, 0x00001000L, 0x00400008L,
+		0x00000000L, 0x10400008L, 0x10401000L, 0x00001000L,
+		0x10000000L, 0x10401008L, 0x00401008L, 0x00400000L,
+		0x10401008L, 0x00000008L, 0x10001000L, 0x00401008L,
+		0x00400008L, 0x00401000L, 0x10400000L, 0x10001008L,
+		0x00001008L, 0x10000000L, 0x10000008L, 0x10401000L,
+	}, {
+/* nibble 4 */
+		0x08000000L, 0x00010000L, 0x00000400L, 0x08010420L,
+		0x08010020L, 0x08000400L, 0x00010420L, 0x08010000L,
+		0x00010000L, 0x00000020L, 0x08000020L, 0x00010400L,
+		0x08000420L, 0x08010020L, 0x08010400L, 0x00000000L,
+		0x00010400L, 0x08000000L, 0x00010020L, 0x00000420L,
+		0x08000400L, 0x00010420L, 0x00000000L, 0x08000020L,
+		0x00000020L, 0x08000420L, 0x08010420L, 0x00010020L,
+		0x08010000L, 0x00000400L, 0x00000420L, 0x08010400L,
+		0x08010400L, 0x08000420L, 0x00010020L, 0x08010000L,
+		0x00010000L, 0x00000020L, 0x08000020L, 0x08000400L,
+		0x08000000L, 0x00010400L, 0x08010420L, 0x00000000L,
+		0x00010420L, 0x08000000L, 0x00000400L, 0x00010020L,
+		0x08000420L, 0x00000400L, 0x00000000L, 0x08010420L,
+		0x08010020L, 0x08010400L, 0x00000420L, 0x00010000L,
+		0x00010400L, 0x08010020L, 0x08000400L, 0x00000420L,
+		0x00000020L, 0x00010420L, 0x08010000L, 0x08000020L,
+	}, {
+/* nibble 5 */
+		0x80000040L, 0x00200040L, 0x00000000L, 0x80202000L,
+		0x00200040L, 0x00002000L, 0x80002040L, 0x00200000L,
+		0x00002040L, 0x80202040L, 0x00202000L, 0x80000000L,
+		0x80002000L, 0x80000040L, 0x80200000L, 0x00202040L,
+		0x00200000L, 0x80002040L, 0x80200040L, 0x00000000L,
+		0x00002000L, 0x00000040L, 0x80202000L, 0x80200040L,
+		0x80202040L, 0x80200000L, 0x80000000L, 0x00002040L,
+		0x00000040L, 0x00202000L, 0x00202040L, 0x80002000L,
+		0x00002040L, 0x80000000L, 0x80002000L, 0x00202040L,
+		0x80202000L, 0x00200040L, 0x00000000L, 0x80002000L,
+		0x80000000L, 0x00002000L, 0x80200040L, 0x00200000L,
+		0x00200040L, 0x80202040L, 0x00202000L, 0x00000040L,
+		0x80202040L, 0x00202000L, 0x00200000L, 0x80002040L,
+		0x80000040L, 0x80200000L, 0x00202040L, 0x00000000L,
+		0x00002000L, 0x80000040L, 0x80002040L, 0x80202000L,
+		0x80200000L, 0x00002040L, 0x00000040L, 0x80200040L,
+	}, {
+/* nibble 6 */
+		0x00004000L, 0x00000200L, 0x01000200L, 0x01000004L,
+		0x01004204L, 0x00004004L, 0x00004200L, 0x00000000L,
+		0x01000000L, 0x01000204L, 0x00000204L, 0x01004000L,
+		0x00000004L, 0x01004200L, 0x01004000L, 0x00000204L,
+		0x01000204L, 0x00004000L, 0x00004004L, 0x01004204L,
+		0x00000000L, 0x01000200L, 0x01000004L, 0x00004200L,
+		0x01004004L, 0x00004204L, 0x01004200L, 0x00000004L,
+		0x00004204L, 0x01004004L, 0x00000200L, 0x01000000L,
+		0x00004204L, 0x01004000L, 0x01004004L, 0x00000204L,
+		0x00004000L, 0x00000200L, 0x01000000L, 0x01004004L,
+		0x01000204L, 0x00004204L, 0x00004200L, 0x00000000L,
+		0x00000200L, 0x01000004L, 0x00000004L, 0x01000200L,
+		0x00000000L, 0x01000204L, 0x01000200L, 0x00004200L,
+		0x00000204L, 0x00004000L, 0x01004204L, 0x01000000L,
+		0x01004200L, 0x00000004L, 0x00004004L, 0x01004204L,
+		0x01000004L, 0x01004200L, 0x01004000L, 0x00004004L,
+	}, {
+/* nibble 7 */
+		0x20800080L, 0x20820000L, 0x00020080L, 0x00000000L,
+		0x20020000L, 0x00800080L, 0x20800000L, 0x20820080L,
+		0x00000080L, 0x20000000L, 0x00820000L, 0x00020080L,
+		0x00820080L, 0x20020080L, 0x20000080L, 0x20800000L,
+		0x00020000L, 0x00820080L, 0x00800080L, 0x20020000L,
+		0x20820080L, 0x20000080L, 0x00000000L, 0x00820000L,
+		0x20000000L, 0x00800000L, 0x20020080L, 0x20800080L,
+		0x00800000L, 0x00020000L, 0x20820000L, 0x00000080L,
+		0x00800000L, 0x00020000L, 0x20000080L, 0x20820080L,
+		0x00020080L, 0x20000000L, 0x00000000L, 0x00820000L,
+		0x20800080L, 0x20020080L, 0x20020000L, 0x00800080L,
+		0x20820000L, 0x00000080L, 0x00800080L, 0x20020000L,
+		0x20820080L, 0x00800000L, 0x20800000L, 0x20000080L,
+		0x00820000L, 0x00020080L, 0x20020080L, 0x20800000L,
+		0x00000080L, 0x20820000L, 0x00820080L, 0x00000000L,
+		0x20000000L, 0x20800080L, 0x00020000L, 0x00820080L,
+	},
+};
+
+__END_HIDDEN_DECLS
diff --git a/crypto/des/str2key.c b/crypto/des/str2key.c
new file mode 100644
index 0000000..dd17a44
--- /dev/null
+++ b/crypto/des/str2key.c
@@ -0,0 +1,166 @@
+/* $OpenBSD: str2key.c,v 1.13 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "des_local.h"
+
+void
+DES_string_to_key(const char *str, DES_cblock *key)
+{
+	DES_key_schedule ks;
+	int i, length;
+	unsigned char j;
+
+	memset(key, 0, 8);
+	length = strlen(str);
+#ifdef OLD_STR_TO_KEY
+	for (i = 0; i < length; i++)
+		(*key)[i % 8] ^= (str[i] << 1);
+#else /* MIT COMPATIBLE */
+	for (i = 0; i < length; i++) {
+		j = str[i];
+		if ((i % 16) < 8)
+			(*key)[i % 8] ^= (j << 1);
+		else {
+			/* Reverse the bit order 05/05/92 eay */
+			j = ((j << 4) & 0xf0)|((j >> 4) & 0x0f);
+			j = ((j << 2) & 0xcc)|((j >> 2) & 0x33);
+			j = ((j << 1) & 0xaa)|((j >> 1) & 0x55);
+			(*key)[7 - (i % 8)] ^= j;
+		}
+	}
+#endif
+	DES_set_odd_parity(key);
+#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
+	if (DES_is_weak_key(key))
+		(*key)[7] ^= 0xF0;
+	DES_set_key(key, &ks);
+#else
+	DES_set_key_unchecked(key, &ks);
+#endif
+	DES_cbc_cksum((const unsigned char *)str, key, length, &ks, key);
+	explicit_bzero(&ks, sizeof(ks));
+	DES_set_odd_parity(key);
+}
+
+void
+DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2)
+{
+	DES_key_schedule ks;
+	int i, length;
+	unsigned char j;
+
+	memset(key1, 0, 8);
+	memset(key2, 0, 8);
+	length = strlen(str);
+#ifdef OLD_STR_TO_KEY
+	if (length <= 8) {
+		for (i = 0; i < length; i++) {
+			(*key2)[i] = (*key1)[i] = (str[i] << 1);
+		}
+	} else {
+		for (i = 0; i < length; i++) {
+			if ((i/8) & 1)
+				(*key2)[i % 8] ^= (str[i] << 1);
+			else
+				(*key1)[i % 8] ^= (str[i] << 1);
+		}
+	}
+#else /* MIT COMPATIBLE */
+	for (i = 0; i < length; i++) {
+		j = str[i];
+		if ((i % 32) < 16) {
+			if ((i % 16) < 8)
+				(*key1)[i % 8] ^= (j << 1);
+			else
+				(*key2)[i % 8] ^= (j << 1);
+		} else {
+			j = ((j << 4) & 0xf0)|((j >> 4) & 0x0f);
+			j = ((j << 2) & 0xcc)|((j >> 2) & 0x33);
+			j = ((j << 1) & 0xaa)|((j >> 1) & 0x55);
+			if ((i % 16) < 8)
+				(*key1)[7 - (i % 8)] ^= j;
+			else
+				(*key2)[7 - (i % 8)] ^= j;
+		}
+	}
+	if (length <= 8)
+		memcpy(key2, key1, 8);
+#endif
+	DES_set_odd_parity(key1);
+	DES_set_odd_parity(key2);
+#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
+	if (DES_is_weak_key(key1))
+		(*key1)[7] ^= 0xF0;
+	DES_set_key(key1, &ks);
+#else
+	DES_set_key_unchecked(key1, &ks);
+#endif
+	DES_cbc_cksum((const unsigned char *)str, key1, length, &ks, key1);
+#ifdef EXPERIMENTAL_STR_TO_STRONG_KEY
+	if (DES_is_weak_key(key2))
+		(*key2)[7] ^= 0xF0;
+	DES_set_key(key2, &ks);
+#else
+	DES_set_key_unchecked(key2, &ks);
+#endif
+	DES_cbc_cksum((const unsigned char *)str, key2, length, &ks, key2);
+	explicit_bzero(&ks, sizeof(ks));
+	DES_set_odd_parity(key1);
+	DES_set_odd_parity(key2);
+}
diff --git a/crypto/des/xcbc_enc.c b/crypto/des/xcbc_enc.c
new file mode 100644
index 0000000..87f348a
--- /dev/null
+++ b/crypto/des/xcbc_enc.c
@@ -0,0 +1,153 @@
+/* $OpenBSD: xcbc_enc.c,v 1.12 2023/07/08 07:34:34 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "des_local.h"
+
+/* RSA's DESX */
+
+void
+DES_xcbc_encrypt(const unsigned char *in, unsigned char *out,
+    long length, DES_key_schedule *schedule,
+    DES_cblock *ivec, const_DES_cblock *inw,
+    const_DES_cblock *outw, int enc)
+{
+	DES_LONG tin0, tin1;
+	DES_LONG tout0, tout1, xor0, xor1;
+	DES_LONG inW0, inW1, outW0, outW1;
+	const unsigned char *in2;
+	long l = length;
+	DES_LONG tin[2];
+	unsigned char *iv;
+
+	in2 = &(*inw)[0];
+	c2l(in2, inW0);
+	c2l(in2, inW1);
+	in2 = &(*outw)[0];
+	c2l(in2, outW0);
+	c2l(in2, outW1);
+
+	iv = &(*ivec)[0];
+
+	if (enc) {
+		c2l(iv, tout0);
+		c2l(iv, tout1);
+		for (l -= 8; l >= 0; l -= 8) {
+			c2l(in, tin0);
+			c2l(in, tin1);
+			tin0 ^= tout0 ^ inW0;
+			tin[0] = tin0;
+			tin1 ^= tout1 ^ inW1;
+			tin[1] = tin1;
+			DES_encrypt1(tin, schedule, DES_ENCRYPT);
+			tout0 = tin[0] ^ outW0;
+			l2c(tout0, out);
+			tout1 = tin[1] ^ outW1;
+			l2c(tout1, out);
+		}
+		if (l != -8) {
+			c2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0 ^ inW0;
+			tin[0] = tin0;
+			tin1 ^= tout1 ^ inW1;
+			tin[1] = tin1;
+			DES_encrypt1(tin, schedule, DES_ENCRYPT);
+			tout0 = tin[0] ^ outW0;
+			l2c(tout0, out);
+			tout1 = tin[1] ^ outW1;
+			l2c(tout1, out);
+		}
+		iv = &(*ivec)[0];
+		l2c(tout0, iv);
+		l2c(tout1, iv);
+	} else {
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		for (l -= 8; l > 0; l -= 8) {
+			c2l(in, tin0);
+			tin[0] = tin0 ^ outW0;
+			c2l(in, tin1);
+			tin[1] = tin1 ^ outW1;
+			DES_encrypt1(tin, schedule, DES_DECRYPT);
+			tout0 = tin[0] ^ xor0 ^ inW0;
+			tout1 = tin[1] ^ xor1 ^ inW1;
+			l2c(tout0, out);
+			l2c(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			c2l(in, tin0);
+			tin[0] = tin0 ^ outW0;
+			c2l(in, tin1);
+			tin[1] = tin1 ^ outW1;
+			DES_encrypt1(tin, schedule, DES_DECRYPT);
+			tout0 = tin[0] ^ xor0 ^ inW0;
+			tout1 = tin[1] ^ xor1 ^ inW1;
+			l2cn(tout0, tout1, out, l + 8);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+
+		iv = &(*ivec)[0];
+		l2c(xor0, iv);
+		l2c(xor1, iv);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	inW0 = inW1 = outW0 = outW1 = 0;
+	tin[0] = tin[1] = 0;
+}
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
new file mode 100644
index 0000000..43beb46
--- /dev/null
+++ b/crypto/dh/dh_ameth.c
@@ -0,0 +1,557 @@
+/* $OpenBSD: dh_ameth.c,v 1.39 2023/08/12 07:59:48 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bn_local.h"
+#include "dh_local.h"
+#include "evp_local.h"
+
+static void
+dh_free(EVP_PKEY *pkey)
+{
+	DH_free(pkey->pkey.dh);
+}
+
+static int
+dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+{
+	X509_ALGOR *algor;
+	int ptype;
+	const void *pval;
+	const ASN1_STRING *astr;
+	const unsigned char *key, *params, *p;
+	int key_len, params_len;
+	ASN1_INTEGER *aint = NULL;
+	DH *dh = NULL;
+	int ret = 0;
+
+	if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
+		goto err;
+	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
+
+	if (ptype != V_ASN1_SEQUENCE) {
+		DHerror(DH_R_PARAMETER_ENCODING_ERROR);
+		goto err;
+	}
+
+	astr = pval;
+	params = astr->data;
+	params_len = astr->length;
+
+	p = params;
+	if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
+		DHerror(DH_R_DECODE_ERROR);
+		goto err;
+	}
+	p = key;
+	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
+		DHerror(DH_R_DECODE_ERROR);
+		goto err;
+	}
+	BN_free(dh->pub_key);
+	if ((dh->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
+		DHerror(DH_R_BN_DECODE_ERROR);
+		goto err;
+	}
+
+	if (!EVP_PKEY_assign_DH(pkey, dh))
+		goto err;
+	dh = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+	DH_free(dh);
+
+	return ret;
+}
+
+static int
+dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
+{
+	const DH *dh = pkey->pkey.dh;
+	ASN1_STRING *astr = NULL;
+	int ptype = V_ASN1_SEQUENCE;
+	ASN1_INTEGER *aint = NULL;
+	ASN1_OBJECT *aobj;
+	unsigned char *params = NULL, *key = NULL;
+	int params_len = 0, key_len = 0;
+	int ret = 0;
+
+	if ((params_len = i2d_DHparams(dh, ¶ms)) <= 0) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		params_len = 0;
+		goto err;
+	}
+	if ((astr = ASN1_STRING_new()) == NULL) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	ASN1_STRING_set0(astr, params, params_len);
+	params = NULL;
+	params_len = 0;
+
+	if ((aint = BN_to_ASN1_INTEGER(dh->pub_key, NULL)) == NULL)
+		goto err;
+	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		key_len = 0;
+		goto err;
+	}
+
+	if ((aobj = OBJ_nid2obj(EVP_PKEY_DH)) == NULL)
+		goto err;
+	if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
+		goto err;
+	astr = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	ASN1_STRING_free(astr);
+	ASN1_INTEGER_free(aint);
+	freezero(params, params_len);
+	freezero(key, key_len);
+
+	return ret;
+}
+
+/*
+ * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in
+ * that the AlgorithmIdentifier contains the parameters, the private key
+ * is explcitly included and the pubkey must be recalculated.
+ */
+
+static int
+dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
+{
+	const X509_ALGOR *algor;
+	int ptype;
+	const void *pval;
+	const ASN1_STRING *astr;
+	const unsigned char *key, *params, *p;
+	int key_len, params_len;
+	ASN1_INTEGER *aint = NULL;
+	DH *dh = NULL;
+	int ret = 0;
+
+	if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
+		goto err;
+	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
+
+	if (ptype != V_ASN1_SEQUENCE) {
+		DHerror(DH_R_PARAMETER_ENCODING_ERROR);
+		goto err;
+	}
+
+	astr = pval;
+	params = astr->data;
+	params_len = astr->length;
+
+	p = params;
+	if ((dh = d2i_DHparams(NULL, &p, params_len)) == NULL) {
+		DHerror(DH_R_DECODE_ERROR);
+		goto err;
+	}
+	p = key;
+	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
+		DHerror(DH_R_DECODE_ERROR);
+		goto err;
+	}
+	BN_free(dh->priv_key);
+	if ((dh->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
+		DHerror(DH_R_BN_DECODE_ERROR);
+		goto err;
+	}
+	if (!DH_generate_key(dh))
+		goto err;
+
+	if (!EVP_PKEY_assign_DH(pkey, dh))
+		goto err;
+	dh = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+	DH_free(dh);
+
+	return ret;
+}
+
+static int
+dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
+{
+	const DH *dh = pkey->pkey.dh;
+	ASN1_STRING *astr = NULL;
+	int ptype = V_ASN1_SEQUENCE;
+	ASN1_INTEGER *aint = NULL;
+	ASN1_OBJECT *aobj;
+	unsigned char *params = NULL, *key = NULL;
+	int params_len = 0, key_len = 0;
+	int ret = 0;
+
+	if ((params_len = i2d_DHparams(dh, ¶ms)) <= 0) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		params_len = 0;
+		goto err;
+	}
+	if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	ASN1_STRING_set0(astr, params, params_len);
+	params = NULL;
+	params_len = 0;
+
+	if ((aint = BN_to_ASN1_INTEGER(dh->priv_key, NULL)) == NULL) {
+		DHerror(DH_R_BN_ERROR);
+		goto err;
+	}
+	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		key_len = 0;
+		goto err;
+	}
+
+	if ((aobj = OBJ_nid2obj(NID_dhKeyAgreement)) == NULL)
+		goto err;
+	if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
+		goto err;
+	astr = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	ASN1_STRING_free(astr);
+	ASN1_INTEGER_free(aint);
+	freezero(params, params_len);
+	freezero(key, key_len);
+
+	return ret;
+}
+
+static int
+dh_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
+{
+	DH *dh = NULL;
+	int ret = 0;
+
+	if ((dh = d2i_DHparams(NULL, params, params_len)) == NULL) {
+		DHerror(ERR_R_DH_LIB);
+		goto err;
+	}
+	if (!EVP_PKEY_assign_DH(pkey, dh))
+		goto err;
+	dh = NULL;
+
+	ret = 1;
+
+ err:
+	DH_free(dh);
+
+	return ret;
+}
+
+static int
+dh_param_encode(const EVP_PKEY *pkey, unsigned char **params)
+{
+	return i2d_DHparams(pkey->pkey.dh, params);
+}
+
+static int
+do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype)
+{
+	int reason = ERR_R_BUF_LIB, ret = 0;
+	const char *ktype = NULL;
+	BIGNUM *priv_key, *pub_key;
+
+	if (ptype == 2)
+		priv_key = x->priv_key;
+	else
+		priv_key = NULL;
+
+	if (ptype > 0)
+		pub_key = x->pub_key;
+	else
+		pub_key = NULL;
+
+	if (ptype == 2)
+		ktype = "PKCS#3 DH Private-Key";
+	else if (ptype == 1)
+		ktype = "PKCS#3 DH Public-Key";
+	else
+		ktype = "PKCS#3 DH Parameters";
+
+	if (x->p == NULL) {
+		reason = ERR_R_PASSED_NULL_PARAMETER;
+		goto err;
+	}
+
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+	if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
+		goto err;
+	indent += 4;
+
+	if (!bn_printf(bp, priv_key, indent, "private-key:"))
+		goto err;
+	if (!bn_printf(bp, pub_key, indent, "public-key:"))
+		goto err;
+
+	if (!bn_printf(bp, x->p, indent, "prime:"))
+		goto err;
+	if (!bn_printf(bp, x->g, indent, "generator:"))
+		goto err;
+	if (x->length != 0) {
+		if (!BIO_indent(bp, indent, 128))
+			goto err;
+		if (BIO_printf(bp, "recommended-private-length: %d bits\n",
+		    (int)x->length) <= 0)
+			goto err;
+	}
+
+	ret = 1;
+	if (0) {
+ err:
+		DHerror(reason);
+	}
+	return(ret);
+}
+
+static int
+dh_size(const EVP_PKEY *pkey)
+{
+	return DH_size(pkey->pkey.dh);
+}
+
+static int
+dh_bits(const EVP_PKEY *pkey)
+{
+	return BN_num_bits(pkey->pkey.dh->p);
+}
+
+static int
+dh_security_bits(const EVP_PKEY *pkey)
+{
+	return DH_security_bits(pkey->pkey.dh);
+}
+
+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
+		return 1;
+}
+
+static int
+dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+{
+	BIGNUM *a;
+
+	if ((a = BN_dup(from->pkey.dh->p)) == NULL)
+		return 0;
+	BN_free(to->pkey.dh->p);
+	to->pkey.dh->p = a;
+
+	if ((a = BN_dup(from->pkey.dh->g)) == NULL)
+		return 0;
+	BN_free(to->pkey.dh->g);
+	to->pkey.dh->g = a;
+
+	return 1;
+}
+
+static int
+dh_missing_parameters(const EVP_PKEY *pkey)
+{
+	const DH *dh = pkey->pkey.dh;
+
+	return dh->p == NULL || dh->g == NULL;
+}
+
+static int
+dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	if (dh_cmp_parameters(a, b) == 0)
+		return 0;
+	if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
+		return 0;
+	else
+		return 1;
+}
+
+static int
+dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
+}
+
+static int
+dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
+}
+
+static int
+dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
+}
+
+int
+DHparams_print(BIO *bp, const DH *x)
+{
+	return do_dh_print(bp, x, 4, NULL, 0);
+}
+LCRYPTO_ALIAS(DHparams_print);
+
+int
+DHparams_print_fp(FILE *fp, const DH *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		DHerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = DHparams_print(b, x);
+	BIO_free(b);
+
+	return ret;
+}
+LCRYPTO_ALIAS(DHparams_print_fp);
+
+static int
+dh_pkey_public_check(const EVP_PKEY *pkey)
+{
+	DH *dh = pkey->pkey.dh;
+
+	if (dh->pub_key == NULL) {
+		DHerror(DH_R_MISSING_PUBKEY);
+		return 0;
+	}
+
+	return DH_check_pub_key_ex(dh, dh->pub_key);
+}
+
+static int
+dh_pkey_param_check(const EVP_PKEY *pkey)
+{
+	DH *dh = pkey->pkey.dh;
+
+	/*
+	 * It would have made more sense to support EVP_PKEY_check() for DH
+	 * keys and call DH_check_ex() there and keeping this as a wrapper
+	 * for DH_param_check_ex(). We follow OpenSSL's choice.
+	 */
+	return DH_check_ex(dh);
+}
+
+const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
+	.pkey_id = EVP_PKEY_DH,
+	.pkey_base_id = EVP_PKEY_DH,
+
+	.pem_str = "DH",
+	.info = "OpenSSL PKCS#3 DH method",
+
+	.pub_decode = dh_pub_decode,
+	.pub_encode = dh_pub_encode,
+	.pub_cmp = dh_pub_cmp,
+	.pub_print = dh_public_print,
+
+	.priv_decode = dh_priv_decode,
+	.priv_encode = dh_priv_encode,
+	.priv_print = dh_private_print,
+
+	.pkey_size = dh_size,
+	.pkey_bits = dh_bits,
+	.pkey_security_bits = dh_security_bits,
+
+	.param_decode = dh_param_decode,
+	.param_encode = dh_param_encode,
+	.param_missing = dh_missing_parameters,
+	.param_copy = dh_copy_parameters,
+	.param_cmp = dh_cmp_parameters,
+	.param_print = dh_param_print,
+
+	.pkey_free = dh_free,
+
+	.pkey_check = NULL,
+	.pkey_public_check = dh_pkey_public_check,
+	.pkey_param_check = dh_pkey_param_check,
+};
diff --git a/crypto/dh/dh_asn1.c b/crypto/dh/dh_asn1.c
new file mode 100644
index 0000000..2e0b054
--- /dev/null
+++ b/crypto/dh/dh_asn1.c
@@ -0,0 +1,176 @@
+/* $OpenBSD: dh_asn1.c,v 1.12 2023/07/08 15:29:03 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "dh_local.h"
+
+/* Override the default free and new methods */
+static int
+dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_NEW_PRE) {
+		*pval = (ASN1_VALUE *)DH_new();
+		if (*pval)
+			return 2;
+		return 0;
+	} else if (operation == ASN1_OP_FREE_PRE) {
+		DH_free((DH *)*pval);
+		*pval = NULL;
+		return 2;
+	}
+	return 1;
+}
+
+static const ASN1_AUX DHparams_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = dh_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE DHparams_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DH, p),
+		.field_name = "p",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DH, g),
+		.field_name = "g",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(DH, length),
+		.field_name = "length",
+		.item = &ZLONG_it,
+	},
+};
+
+const ASN1_ITEM DHparams_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = DHparams_seq_tt,
+	.tcount = sizeof(DHparams_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &DHparams_aux,
+	.size = sizeof(DH),
+	.sname = "DH",
+};
+
+
+DH *
+d2i_DHparams(DH **a, const unsigned char **in, long len)
+{
+	return (DH *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DHparams_it);
+}
+LCRYPTO_ALIAS(d2i_DHparams);
+
+int
+i2d_DHparams(const DH *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DHparams_it);
+}
+LCRYPTO_ALIAS(i2d_DHparams);
+
+DH *
+d2i_DHparams_bio(BIO *bp, DH **a)
+{
+	return ASN1_item_d2i_bio(&DHparams_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_DHparams_bio);
+
+int
+i2d_DHparams_bio(BIO *bp, DH *a)
+{
+	return ASN1_item_i2d_bio(&DHparams_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_DHparams_bio);
+
+DH *
+d2i_DHparams_fp(FILE *fp, DH **a)
+{
+	return ASN1_item_d2i_fp(&DHparams_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_DHparams_fp);
+
+int
+i2d_DHparams_fp(FILE *fp, DH *a)
+{
+	return ASN1_item_i2d_fp(&DHparams_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_DHparams_fp);
+
+DH *
+DHparams_dup(DH *dh)
+{
+	return ASN1_item_dup(&DHparams_it, dh);
+}
+LCRYPTO_ALIAS(DHparams_dup);
diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
new file mode 100644
index 0000000..be79c2a
--- /dev/null
+++ b/crypto/dh/dh_check.c
@@ -0,0 +1,303 @@
+/* $OpenBSD: dh_check.c,v 1.28 2023/07/24 16:25:02 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dh_local.h"
+
+#define DH_NUMBER_ITERATIONS_FOR_PRIME 64
+
+/*
+ * Check that p is odd and 1 < g < p - 1. The _ex version removes the need of
+ * inspecting flags and pushes errors on the stack instead.
+ */
+
+int
+DH_check_params_ex(const DH *dh)
+{
+	int flags = 0;
+
+	if (!DH_check_params(dh, &flags))
+		return 0;
+
+	if ((flags & DH_CHECK_P_NOT_PRIME) != 0)
+		DHerror(DH_R_CHECK_P_NOT_PRIME);
+	if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0)
+		DHerror(DH_R_NOT_SUITABLE_GENERATOR);
+
+	return flags == 0;
+}
+
+int
+DH_check_params(const DH *dh, int *flags)
+{
+	BIGNUM *max_g = NULL;
+	int ok = 0;
+
+	*flags = 0;
+
+	if (!BN_is_odd(dh->p))
+		*flags |= DH_CHECK_P_NOT_PRIME;
+
+	/*
+	 * Check that 1 < dh->g < p - 1
+	 */
+
+	if (BN_cmp(dh->g, BN_value_one()) <= 0)
+		*flags |= DH_NOT_SUITABLE_GENERATOR;
+	/* max_g = p - 1 */
+	if ((max_g = BN_dup(dh->p)) == NULL)
+		goto err;
+	if (!BN_sub_word(max_g, 1))
+		goto err;
+	/* check that g < max_g */
+	if (BN_cmp(dh->g, max_g) >= 0)
+		*flags |= DH_NOT_SUITABLE_GENERATOR;
+
+	ok = 1;
+
+ err:
+	BN_free(max_g);
+
+	return ok;
+}
+
+/*
+ * Check that p is a safe prime and that g is a suitable generator.
+ * The _ex version puts errors on the stack instead of returning flags.
+ */
+
+int
+DH_check_ex(const DH *dh)
+{
+	int flags = 0;
+
+	if (!DH_check(dh, &flags))
+		return 0;
+
+	if ((flags & DH_NOT_SUITABLE_GENERATOR) != 0)
+		DHerror(DH_R_NOT_SUITABLE_GENERATOR);
+	if ((flags & DH_CHECK_Q_NOT_PRIME) != 0)
+		DHerror(DH_R_CHECK_Q_NOT_PRIME);
+	if ((flags & DH_CHECK_INVALID_Q_VALUE) != 0)
+		DHerror(DH_R_CHECK_INVALID_Q_VALUE);
+	if ((flags & DH_CHECK_INVALID_J_VALUE) != 0)
+		DHerror(DH_R_CHECK_INVALID_J_VALUE);
+	if ((flags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
+		DHerror(DH_R_UNABLE_TO_CHECK_GENERATOR);
+	if ((flags & DH_CHECK_P_NOT_PRIME) != 0)
+		DHerror(DH_R_CHECK_P_NOT_PRIME);
+	if ((flags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
+		DHerror(DH_R_CHECK_P_NOT_SAFE_PRIME);
+
+	return flags == 0;
+}
+
+int
+DH_check(const DH *dh, int *flags)
+{
+	BN_CTX *ctx = NULL;
+	int is_prime;
+	int ok = 0;
+
+	*flags = 0;
+
+	if (!DH_check_params(dh, flags))
+		goto err;
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+
+	if (dh->q != NULL) {
+		BIGNUM *quotient, *residue;
+
+		if ((quotient = BN_CTX_get(ctx)) == NULL)
+			goto err;
+		if ((residue = BN_CTX_get(ctx)) == NULL)
+			goto err;
+		if ((*flags & DH_NOT_SUITABLE_GENERATOR) == 0) {
+			/* Check g^q == 1 mod p */
+			if (!BN_mod_exp_ct(residue, dh->g, dh->q, dh->p, ctx))
+				goto err;
+			if (!BN_is_one(residue))
+				*flags |= DH_NOT_SUITABLE_GENERATOR;
+		}
+		is_prime = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME,
+		    ctx, NULL);
+		if (is_prime < 0)
+			goto err;
+		if (is_prime == 0)
+			*flags |= DH_CHECK_Q_NOT_PRIME;
+		/* Check p == 1 mod q, i.e., q divides p - 1 */
+		if (!BN_div_ct(quotient, residue, dh->p, dh->q, ctx))
+			goto err;
+		if (!BN_is_one(residue))
+			*flags |= DH_CHECK_INVALID_Q_VALUE;
+		if (dh->j != NULL && BN_cmp(dh->j, quotient) != 0)
+			*flags |= DH_CHECK_INVALID_J_VALUE;
+	}
+
+	is_prime = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME,
+	    ctx, NULL);
+	if (is_prime < 0)
+		goto err;
+	if (is_prime == 0)
+		*flags |= DH_CHECK_P_NOT_PRIME;
+	else if (dh->q == NULL) {
+		BIGNUM *q;
+
+		if ((q = BN_CTX_get(ctx)) == NULL)
+			goto err;
+		if (!BN_rshift1(q, dh->p))
+			goto err;
+		is_prime = BN_is_prime_ex(q, DH_NUMBER_ITERATIONS_FOR_PRIME,
+		    ctx, NULL);
+		if (is_prime < 0)
+			goto err;
+		if (is_prime == 0)
+			*flags |= DH_CHECK_P_NOT_SAFE_PRIME;
+	}
+
+	ok = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	return ok;
+}
+LCRYPTO_ALIAS(DH_check);
+
+int
+DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
+{
+	int flags = 0;
+
+	if (!DH_check_pub_key(dh, pub_key, &flags))
+		return 0;
+
+	if ((flags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
+		DHerror(DH_R_CHECK_PUBKEY_TOO_SMALL);
+	if ((flags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
+		DHerror(DH_R_CHECK_PUBKEY_TOO_LARGE);
+	if ((flags & DH_CHECK_PUBKEY_INVALID) != 0)
+		DHerror(DH_R_CHECK_PUBKEY_INVALID);
+
+	return flags == 0;
+}
+
+int
+DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *flags)
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *max_pub_key;
+	int ok = 0;
+
+	*flags = 0;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((max_pub_key = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Check that 1 < pub_key < dh->p - 1
+	 */
+
+	if (BN_cmp(pub_key, BN_value_one()) <= 0)
+		*flags |= DH_CHECK_PUBKEY_TOO_SMALL;
+
+	/* max_pub_key = dh->p - 1 */
+	if (!BN_sub(max_pub_key, dh->p, BN_value_one()))
+		goto err;
+
+	if (BN_cmp(pub_key, max_pub_key) >= 0)
+		*flags |= DH_CHECK_PUBKEY_TOO_LARGE;
+
+	/*
+	 * If dh->q is set, check that pub_key^q == 1 mod p
+	 */
+
+	if (dh->q != NULL) {
+		BIGNUM *residue;
+
+		if ((residue = BN_CTX_get(ctx)) == NULL)
+			goto err;
+
+		if (!BN_mod_exp_ct(residue, pub_key, dh->q, dh->p, ctx))
+			goto err;
+		if (!BN_is_one(residue))
+			*flags |= DH_CHECK_PUBKEY_INVALID;
+	}
+
+	ok = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return ok;
+}
+LCRYPTO_ALIAS(DH_check_pub_key);
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
new file mode 100644
index 0000000..f5dda28
--- /dev/null
+++ b/crypto/dh/dh_err.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: dh_err.c,v 1.19 2023/07/08 15:29:03 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_DH,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_DH,0,reason)
+
+static ERR_STRING_DATA DH_str_functs[]=	{
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA DH_str_reasons[]=
+	{
+{ERR_REASON(DH_R_BAD_GENERATOR)          ,"bad generator"},
+{ERR_REASON(DH_R_BN_DECODE_ERROR)        ,"bn decode error"},
+{ERR_REASON(DH_R_BN_ERROR)               ,"bn error"},
+{ERR_REASON(DH_R_DECODE_ERROR)           ,"decode error"},
+{ERR_REASON(DH_R_INVALID_PUBKEY)         ,"invalid public key"},
+{ERR_REASON(DH_R_KEYS_NOT_SET)           ,"keys not set"},
+{ERR_REASON(DH_R_KEY_SIZE_TOO_SMALL)     ,"key size too small"},
+{ERR_REASON(DH_R_MODULUS_TOO_LARGE)      ,"modulus too large"},
+{ERR_REASON(DH_R_NON_FIPS_METHOD)        ,"non fips method"},
+{ERR_REASON(DH_R_NO_PARAMETERS_SET)      ,"no parameters set"},
+{ERR_REASON(DH_R_NO_PRIVATE_VALUE)       ,"no private value"},
+{ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
+{ERR_REASON(DH_R_CHECK_INVALID_J_VALUE)   ,"check invalid j value"},
+{ERR_REASON(DH_R_CHECK_INVALID_Q_VALUE)   ,"check invalid q value"},
+{ERR_REASON(DH_R_CHECK_PUBKEY_INVALID)    ,"check pubkey invalid"},
+{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_LARGE)  ,"check pubkey too large"},
+{ERR_REASON(DH_R_CHECK_PUBKEY_TOO_SMALL)  ,"check pubkey too small"},
+{ERR_REASON(DH_R_CHECK_P_NOT_PRIME)       ,"check p not prime"},
+{ERR_REASON(DH_R_CHECK_P_NOT_SAFE_PRIME)  ,"check p not safe prime"},
+{ERR_REASON(DH_R_CHECK_Q_NOT_PRIME)       ,"check q not prime"},
+{ERR_REASON(DH_R_MISSING_PUBKEY)          ,"missing pubkey"},
+{ERR_REASON(DH_R_NOT_SUITABLE_GENERATOR)  ,"not suitable generator"},
+{ERR_REASON(DH_R_UNABLE_TO_CHECK_GENERATOR),"unable to check generator"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_DH_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(DH_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,DH_str_functs);
+		ERR_load_strings(0,DH_str_reasons);
+		}
+#endif
+	}
+LCRYPTO_ALIAS(ERR_load_DH_strings);
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
new file mode 100644
index 0000000..3ffa5d8
--- /dev/null
+++ b/crypto/dh/dh_gen.c
@@ -0,0 +1,197 @@
+/* $OpenBSD: dh_gen.c,v 1.21 2023/07/08 15:29:03 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dh_local.h"
+
+static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
+	    BN_GENCB *cb);
+
+int
+DH_generate_parameters_ex(DH *ret, int prime_len, int generator, BN_GENCB *cb)
+{
+	if (ret->meth->generate_params)
+		return ret->meth->generate_params(ret, prime_len, generator, cb);
+	return dh_builtin_genparams(ret, prime_len, generator, cb);
+}
+LCRYPTO_ALIAS(DH_generate_parameters_ex);
+
+/*
+ * We generate DH parameters as follows:
+ * find a prime q which is prime_len/2 bits long.
+ * p=(2*q)+1 or (p-1)/2 = q
+ * For this case, g is a generator if
+ * g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
+ * Since the factors of p-1 are q and 2, we just need to check
+ * g^2 mod p != 1 and g^q mod p != 1.
+ *
+ * Having said all that,
+ * there is another special case method for the generators 2, 3 and 5.
+ * for 2, p mod 24 == 11
+ * for 3, p mod 12 == 5  <<<<< does not work for safe primes.
+ * for 5, p mod 10 == 3 or 7
+ *
+ * Thanks to Phil Karn  for the pointers about the
+ * special generators and for answering some of my questions.
+ *
+ * I've implemented the second simple method :-).
+ * Since DH should be using a safe prime (both p and q are prime),
+ * this generator function can take a very very long time to run.
+ */
+/* Actually there is no reason to insist that 'generator' be a generator.
+ * It's just as OK (and in some sense better) to use a generator of the
+ * order-q subgroup.
+ */
+static int
+dh_builtin_genparams(DH *ret, int prime_len, int generator, BN_GENCB *cb)
+{
+	BIGNUM *t1, *t2;
+	int g, ok = -1;
+	BN_CTX *ctx = NULL;
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((t1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((t2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Make sure 'ret' has the necessary elements */
+	if (!ret->p && ((ret->p = BN_new()) == NULL))
+		goto err;
+	if (!ret->g && ((ret->g = BN_new()) == NULL))
+		goto err;
+
+	if (generator <= 1) {
+		DHerror(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))
+			goto err;
+		g = 2;
+	} else if (generator == DH_GENERATOR_5) {
+		if (!BN_set_word(t1, 10))
+			goto err;
+		if (!BN_set_word(t2, 3))
+			goto err;
+		/* BN_set_word(t3,7); just have to miss
+		 * out on these ones :-( */
+		g = 5;
+	} else {
+		/*
+		 * in the general case, don't worry if 'generator' is a
+		 * generator or not: since we are using safe primes,
+		 * it will generate either an order-q or an order-2q group,
+		 * which both is OK
+		 */
+		if (!BN_set_word(t1, 2))
+			goto err;
+		if (!BN_set_word(t2, 1))
+			goto err;
+		g = generator;
+	}
+
+	if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
+		goto err;
+	if (!BN_GENCB_call(cb, 3, 0))
+		goto err;
+	if (!BN_set_word(ret->g, g))
+		goto err;
+	ok = 1;
+err:
+	if (ok == -1) {
+		DHerror(ERR_R_BN_LIB);
+		ok = 0;
+	}
+
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	return ok;
+}
+
+DH *
+DH_generate_parameters(int prime_len, int generator,
+    void (*callback)(int, int, void *), void *cb_arg)
+{
+	BN_GENCB cb;
+	DH *ret = NULL;
+
+	if ((ret = DH_new()) == NULL)
+		return NULL;
+
+	BN_GENCB_set_old(&cb, callback, cb_arg);
+
+	if (DH_generate_parameters_ex(ret, prime_len, generator, &cb))
+		return ret;
+	DH_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(DH_generate_parameters);
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
new file mode 100644
index 0000000..050d114
--- /dev/null
+++ b/crypto/dh/dh_key.c
@@ -0,0 +1,247 @@
+/* $OpenBSD: dh_key.c,v 1.40 2023/08/03 18:53:55 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dh_local.h"
+
+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)
+{
+	return dh->meth->generate_key(dh);
+}
+LCRYPTO_ALIAS(DH_generate_key);
+
+int
+DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+{
+	return dh->meth->compute_key(key, pub_key, dh);
+}
+LCRYPTO_ALIAS(DH_compute_key);
+
+static DH_METHOD dh_ossl = {
+	.name = "OpenSSL DH Method",
+	.generate_key = generate_key,
+	.compute_key = compute_key,
+	.bn_mod_exp = dh_bn_mod_exp,
+	.init = dh_init,
+	.finish = dh_finish,
+};
+
+const DH_METHOD *
+DH_OpenSSL(void)
+{
+	return &dh_ossl;
+}
+LCRYPTO_ALIAS(DH_OpenSSL);
+
+static int
+generate_key(DH *dh)
+{
+	int ok = 0;
+	unsigned l;
+	BN_CTX *ctx;
+	BN_MONT_CTX *mont = NULL;
+	BIGNUM *pub_key = NULL, *priv_key = NULL;
+
+	if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+		DHerror(DH_R_MODULUS_TOO_LARGE);
+		return 0;
+	}
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if ((priv_key = dh->priv_key) == NULL) {
+		if ((priv_key = BN_new()) == NULL)
+			goto err;
+	}
+
+	if ((pub_key = dh->pub_key) == NULL) {
+		if ((pub_key = BN_new()) == NULL)
+			goto err;
+	}
+
+	if (dh->flags & DH_FLAG_CACHE_MONT_P) {
+		mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
+		    CRYPTO_LOCK_DH, dh->p, ctx);
+		if (!mont)
+			goto err;
+	}
+
+	if (dh->priv_key == NULL) {
+		if (dh->q) {
+			if (!bn_rand_interval(priv_key, 2, dh->q))
+				goto err;
+		} else {
+			/* secret exponent length */
+			l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
+			if (!BN_rand(priv_key, l, 0, 0))
+				goto err;
+		}
+	}
+
+	if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, priv_key, dh->p, ctx,
+	    mont))
+		goto err;
+
+	dh->pub_key = pub_key;
+	dh->priv_key = priv_key;
+	ok = 1;
+ err:
+	if (ok != 1)
+		DHerror(ERR_R_BN_LIB);
+
+	if (dh->pub_key == NULL)
+		BN_free(pub_key);
+	if (dh->priv_key == NULL)
+		BN_free(priv_key);
+	BN_CTX_free(ctx);
+
+	return ok;
+}
+
+static int
+compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+{
+	BN_CTX *ctx = NULL;
+	BN_MONT_CTX *mont = NULL;
+	BIGNUM *tmp;
+	int ret = -1;
+        int check_result;
+
+	if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
+		DHerror(DH_R_MODULUS_TOO_LARGE);
+		goto err;
+	}
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (dh->priv_key == NULL) {
+		DHerror(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,
+		    CRYPTO_LOCK_DH, 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) {
+		DHerror(DH_R_INVALID_PUBKEY);
+		goto err;
+	}
+
+	if (!dh->meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx,
+	    mont)) {
+		DHerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	ret = BN_bn2bin(tmp, key);
+ err:
+	if (ctx != NULL) {
+		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_ct(r, a, p, m, ctx, m_ctx);
+}
+
+static int
+dh_init(DH *dh)
+{
+	dh->flags |= DH_FLAG_CACHE_MONT_P;
+	return 1;
+}
+
+static int
+dh_finish(DH *dh)
+{
+	BN_MONT_CTX_free(dh->method_mont_p);
+	return 1;
+}
diff --git a/crypto/dh/dh_lib.c b/crypto/dh/dh_lib.c
new file mode 100644
index 0000000..8d63787
--- /dev/null
+++ b/crypto/dh/dh_lib.c
@@ -0,0 +1,400 @@
+/* $OpenBSD: dh_lib.c,v 1.41 2023/08/13 12:09:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "dh_local.h"
+
+static const DH_METHOD *default_DH_method = NULL;
+
+void
+DH_set_default_method(const DH_METHOD *meth)
+{
+	default_DH_method = meth;
+}
+LCRYPTO_ALIAS(DH_set_default_method);
+
+const DH_METHOD *
+DH_get_default_method(void)
+{
+	if (!default_DH_method)
+		default_DH_method = DH_OpenSSL();
+	return default_DH_method;
+}
+LCRYPTO_ALIAS(DH_get_default_method);
+
+int
+DH_set_method(DH *dh, const DH_METHOD *meth)
+{
+	/*
+	 * NB: The caller is specifically setting a method, so it's not up to us
+	 * to deal with which ENGINE it comes from.
+	 */
+	const DH_METHOD *mtmp;
+
+	mtmp = dh->meth;
+	if (mtmp->finish)
+		mtmp->finish(dh);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(dh->engine);
+	dh->engine = NULL;
+#endif
+	dh->meth = meth;
+	if (meth->init)
+		meth->init(dh);
+	return 1;
+}
+LCRYPTO_ALIAS(DH_set_method);
+
+DH *
+DH_new(void)
+{
+	return DH_new_method(NULL);
+}
+LCRYPTO_ALIAS(DH_new);
+
+DH *
+DH_new_method(ENGINE *engine)
+{
+	DH *dh;
+
+	if ((dh = calloc(1, sizeof(*dh))) == NULL) {
+		DHerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	dh->meth = DH_get_default_method();
+	dh->flags = dh->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
+	dh->references = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+	if (engine != NULL) {
+		if (!ENGINE_init(engine)) {
+			DHerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		dh->engine = engine;
+	} else
+		dh->engine = ENGINE_get_default_DH();
+	if (dh->engine != NULL) {
+		if ((dh->meth = ENGINE_get_DH(dh->engine)) == NULL) {
+			DHerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		dh->flags = dh->meth->flags & ~DH_FLAG_NON_FIPS_ALLOW;
+	}
+#endif
+
+	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, dh, &dh->ex_data))
+		goto err;
+	if (dh->meth->init != NULL && !dh->meth->init(dh))
+		goto err;
+
+	return dh;
+
+ err:
+	DH_free(dh);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(DH_new_method);
+
+void
+DH_free(DH *r)
+{
+	int i;
+
+	if (r == NULL)
+		return;
+	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DH);
+	if (i > 0)
+		return;
+
+	if (r->meth != NULL && r->meth->finish != NULL)
+		r->meth->finish(r);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(r->engine);
+#endif
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data);
+
+	BN_free(r->p);
+	BN_free(r->g);
+	BN_free(r->q);
+	BN_free(r->j);
+	free(r->seed);
+	BN_free(r->counter);
+	BN_free(r->pub_key);
+	BN_free(r->priv_key);
+	free(r);
+}
+LCRYPTO_ALIAS(DH_free);
+
+int
+DH_up_ref(DH *r)
+{
+	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DH);
+
+	return i > 1 ? 1 : 0;
+}
+LCRYPTO_ALIAS(DH_up_ref);
+
+int
+DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DH, argl, argp, new_func,
+	    dup_func, free_func);
+}
+LCRYPTO_ALIAS(DH_get_ex_new_index);
+
+int
+DH_set_ex_data(DH *d, int idx, void *arg)
+{
+	return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+LCRYPTO_ALIAS(DH_set_ex_data);
+
+void *
+DH_get_ex_data(DH *d, int idx)
+{
+	return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+LCRYPTO_ALIAS(DH_get_ex_data);
+
+int
+DH_size(const DH *dh)
+{
+	return BN_num_bytes(dh->p);
+}
+LCRYPTO_ALIAS(DH_size);
+
+int
+DH_bits(const DH *dh)
+{
+	return BN_num_bits(dh->p);
+}
+LCRYPTO_ALIAS(DH_bits);
+
+int
+DH_security_bits(const DH *dh)
+{
+	int N = -1;
+
+	if (dh->q != NULL)
+		N = BN_num_bits(dh->q);
+	else if (dh->length > 0)
+		N = dh->length;
+
+	return BN_security_bits(BN_num_bits(dh->p), N);
+}
+LCRYPTO_ALIAS(DH_security_bits);
+
+ENGINE *
+DH_get0_engine(DH *dh)
+{
+	return dh->engine;
+}
+LCRYPTO_ALIAS(DH_get0_engine);
+
+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;
+}
+LCRYPTO_ALIAS(DH_get0_pqg);
+
+int
+DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+	if ((dh->p == NULL && p == NULL) || (dh->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;
+		dh->length = BN_num_bits(dh->q);
+	}
+	if (g != NULL) {
+		BN_free(dh->g);
+		dh->g = g;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(DH_set0_pqg);
+
+void
+DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+	if (pub_key != NULL)
+		*pub_key = dh->pub_key;
+	if (priv_key != NULL)
+		*priv_key = dh->priv_key;
+}
+LCRYPTO_ALIAS(DH_get0_key);
+
+int
+DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+	if (pub_key != NULL) {
+		BN_free(dh->pub_key);
+		dh->pub_key = pub_key;
+	}
+	if (priv_key != NULL) {
+		BN_free(dh->priv_key);
+		dh->priv_key = priv_key;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(DH_set0_key);
+
+const BIGNUM *
+DH_get0_p(const DH *dh)
+{
+	return dh->p;
+}
+LCRYPTO_ALIAS(DH_get0_p);
+
+const BIGNUM *
+DH_get0_q(const DH *dh)
+{
+	return dh->q;
+}
+LCRYPTO_ALIAS(DH_get0_q);
+
+const BIGNUM *
+DH_get0_g(const DH *dh)
+{
+	return dh->g;
+}
+LCRYPTO_ALIAS(DH_get0_g);
+
+const BIGNUM *
+DH_get0_priv_key(const DH *dh)
+{
+	return dh->priv_key;
+}
+LCRYPTO_ALIAS(DH_get0_priv_key);
+
+const BIGNUM *
+DH_get0_pub_key(const DH *dh)
+{
+	return dh->pub_key;
+}
+LCRYPTO_ALIAS(DH_get0_pub_key);
+
+void
+DH_clear_flags(DH *dh, int flags)
+{
+	dh->flags &= ~flags;
+}
+LCRYPTO_ALIAS(DH_clear_flags);
+
+int
+DH_test_flags(const DH *dh, int flags)
+{
+	return dh->flags & flags;
+}
+LCRYPTO_ALIAS(DH_test_flags);
+
+void
+DH_set_flags(DH *dh, int flags)
+{
+	dh->flags |= flags;
+}
+LCRYPTO_ALIAS(DH_set_flags);
+
+long
+DH_get_length(const DH *dh)
+{
+	return dh->length;
+}
+LCRYPTO_ALIAS(DH_get_length);
+
+int
+DH_set_length(DH *dh, long length)
+{
+	if (length < 0 || length > INT_MAX)
+		return 0;
+
+	dh->length = length;
+	return 1;
+}
+LCRYPTO_ALIAS(DH_set_length);
diff --git a/crypto/dh/dh_local.h b/crypto/dh/dh_local.h
new file mode 100644
index 0000000..928f2c0
--- /dev/null
+++ b/crypto/dh/dh_local.h
@@ -0,0 +1,117 @@
+/* $OpenBSD: dh_local.h,v 1.3 2022/01/14 08:25:44 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_DH_LOCAL_H
+#define HEADER_DH_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+struct dh_method {
+	const char *name;
+	/* Methods here */
+	int (*generate_key)(DH *dh);
+	int (*compute_key)(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+	int (*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);
+	int (*init)(DH *dh);
+	int (*finish)(DH *dh);
+	int flags;
+	char *app_data;
+	/* If this is non-NULL, it will be used to generate parameters */
+	int (*generate_params)(DH *dh, int prime_len, int generator,
+	    BN_GENCB *cb);
+};
+
+struct dh_st {
+	/* This first argument is used to pick up errors when
+	 * a DH is passed instead of a EVP_PKEY */
+	int pad;
+	int version;
+	BIGNUM *p;
+	BIGNUM *g;
+	long length; /* optional */
+	BIGNUM *pub_key;	/* g^x */
+	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;
+
+	int references;
+	CRYPTO_EX_DATA ex_data;
+	const DH_METHOD *meth;
+	ENGINE *engine;
+};
+
+/*
+ * Public API in OpenSSL that we only want to use internally.
+ */
+
+int DH_check_params_ex(const DH *dh);
+int DH_check_params(const DH *dh, int *flags);
+int DH_check_ex(const DH *dh);
+int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_DH_LOCAL_H */
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
new file mode 100644
index 0000000..7a598da
--- /dev/null
+++ b/crypto/dh/dh_pmeth.c
@@ -0,0 +1,266 @@
+/* $OpenBSD: dh_pmeth.c,v 1.13 2022/11/26 16:08:51 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dh_local.h"
+#include "evp_local.h"
+
+/* DH pkey context structure */
+
+typedef struct {
+	/* Parameter gen parameters */
+	int prime_len;
+	int generator;
+	int use_dsa;
+	/* Keygen callback info */
+	int gentmp[2];
+	/* message digest */
+} DH_PKEY_CTX;
+
+static int
+pkey_dh_init(EVP_PKEY_CTX *ctx)
+{
+	DH_PKEY_CTX *dctx;
+
+	dctx = malloc(sizeof(DH_PKEY_CTX));
+	if (!dctx)
+		return 0;
+	dctx->prime_len = 1024;
+	dctx->generator = 2;
+	dctx->use_dsa = 0;
+
+	ctx->data = dctx;
+	ctx->keygen_info = dctx->gentmp;
+	ctx->keygen_info_count = 2;
+	
+	return 1;
+}
+
+static int
+pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	DH_PKEY_CTX *dctx, *sctx;
+
+	if (!pkey_dh_init(dst))
+		return 0;
+       	sctx = src->data;
+	dctx = dst->data;
+	dctx->prime_len = sctx->prime_len;
+	dctx->generator = sctx->generator;
+	dctx->use_dsa = sctx->use_dsa;
+	return 1;
+}
+
+static void
+pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
+{
+	DH_PKEY_CTX *dctx = ctx->data;
+
+	free(dctx);
+}
+
+static int
+pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	DH_PKEY_CTX *dctx = ctx->data;
+
+	switch (type) {
+	case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
+		if (p1 < 256)
+			return -2;
+		dctx->prime_len = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
+		dctx->generator = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_PEER_KEY:
+		/* Default behaviour is OK */
+		return 1;
+
+	default:
+		return -2;
+	}
+}
+			
+static int
+pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+ 	long lval;
+	char *ep;
+	int len;
+
+	if (!strcmp(type, "dh_paramgen_prime_len")) {
+		errno = 0;
+		lval = strtol(value, &ep, 10);
+		if (value[0] == '\0' || *ep != '\0')
+			goto not_a_number;
+		if ((errno == ERANGE &&
+		    (lval == LONG_MAX || lval == LONG_MIN)) ||
+		    (lval > INT_MAX || lval < INT_MIN))
+			goto out_of_range;
+		len = lval;
+		return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
+	} else if (!strcmp(type, "dh_paramgen_generator")) {
+		errno = 0;
+		lval = strtol(value, &ep, 10);
+		if (value[0] == '\0' || *ep != '\0')
+			goto not_a_number;
+		if ((errno == ERANGE &&
+		    (lval == LONG_MAX || lval == LONG_MIN)) ||
+		    (lval > INT_MAX || lval < INT_MIN))
+			goto out_of_range;
+		len = lval;
+		return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
+	}
+
+not_a_number:
+out_of_range:
+	return -2;
+}
+
+static int
+pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	DH *dh = NULL;
+	DH_PKEY_CTX *dctx = ctx->data;
+	BN_GENCB *pcb, cb;
+	int ret;
+
+	if (ctx->pkey_gencb) {
+		pcb = &cb;
+		evp_pkey_set_cb_translate(pcb, ctx);
+	} else
+		pcb = NULL;
+	dh = DH_new();
+	if (!dh)
+		return 0;
+	ret = DH_generate_parameters_ex(dh, dctx->prime_len, dctx->generator,
+	    pcb);
+	if (ret)
+		EVP_PKEY_assign_DH(pkey, dh);
+	else
+		DH_free(dh);
+	return ret;
+}
+
+static int
+pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	DH *dh = NULL;
+
+	if (ctx->pkey == NULL) {
+		DHerror(DH_R_NO_PARAMETERS_SET);
+		return 0;
+	}
+	dh = DH_new();
+	if (!dh)
+		return 0;
+	EVP_PKEY_assign_DH(pkey, dh);
+	/* Note: if error return, pkey is freed by parent routine */
+	if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+		return 0;
+	return DH_generate_key(pkey->pkey.dh);
+}
+
+static int
+pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+	int ret;
+
+	if (!ctx->pkey || !ctx->peerkey) {
+		DHerror(DH_R_KEYS_NOT_SET);
+		return 0;
+	}
+	ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
+	    ctx->pkey->pkey.dh);
+	if (ret < 0)
+		return ret;
+	*keylen = ret;
+	return 1;
+}
+
+const EVP_PKEY_METHOD dh_pkey_meth = {
+	.pkey_id = EVP_PKEY_DH,
+	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
+
+	.init = pkey_dh_init,
+	.copy = pkey_dh_copy,
+	.cleanup = pkey_dh_cleanup,
+
+	.paramgen = pkey_dh_paramgen,
+
+	.keygen = pkey_dh_keygen,
+
+	.derive = pkey_dh_derive,
+
+	.ctrl = pkey_dh_ctrl,
+	.ctrl_str = pkey_dh_ctrl_str
+};
diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c
new file mode 100644
index 0000000..4c20b45
--- /dev/null
+++ b/crypto/dsa/dsa_ameth.c
@@ -0,0 +1,737 @@
+/* $OpenBSD: dsa_ameth.c,v 1.55 2023/08/12 07:59:48 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bn_local.h"
+#include "dsa_local.h"
+#include "evp_local.h"
+
+static int
+dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+{
+	X509_ALGOR *algor;
+	int ptype;
+	const void *pval;
+	const ASN1_STRING *astr;
+	const unsigned char *key, *params, *p;
+	int key_len, params_len;
+	ASN1_INTEGER *aint = NULL;
+	DSA *dsa = NULL;
+	int ret = 0;
+
+	if (!X509_PUBKEY_get0_param(NULL, &key, &key_len, &algor, pubkey))
+		goto err;
+	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
+
+	if (ptype == V_ASN1_SEQUENCE) {
+		astr = pval;
+		params = astr->data;
+		params_len = astr->length;
+
+		p = params;
+		if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
+			DSAerror(DSA_R_DECODE_ERROR);
+			goto err;
+		}
+	} else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
+		if ((dsa = DSA_new()) == NULL) {
+			DSAerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	} else {
+		DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
+		goto err;
+	}
+
+	p = key;
+	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
+		DSAerror(DSA_R_DECODE_ERROR);
+		goto err;
+	}
+	BN_free(dsa->pub_key);
+	if ((dsa->pub_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
+		DSAerror(DSA_R_BN_DECODE_ERROR);
+		goto err;
+	}
+
+	/* We can only check for key consistency if we have parameters. */
+	if (ptype == V_ASN1_SEQUENCE) {
+		if (!dsa_check_key(dsa))
+			goto err;
+	}
+
+	if (!EVP_PKEY_assign_DSA(pkey, dsa))
+		goto err;
+	dsa = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_INTEGER_free(aint);
+	DSA_free(dsa);
+
+	return ret;
+}
+
+static int
+dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
+{
+	const DSA *dsa = pkey->pkey.dsa;
+	ASN1_STRING *astr = NULL;
+	int ptype = V_ASN1_UNDEF;
+	ASN1_INTEGER *aint = NULL;
+	ASN1_OBJECT *aobj;
+	unsigned char *params = NULL, *key = NULL;
+	int params_len = 0, key_len = 0;
+	int ret = 0;
+
+	if (pkey->save_parameters > 0 && !EVP_PKEY_missing_parameters(pkey)) {
+		if ((params_len = i2d_DSAparams(dsa, ¶ms)) <= 0) {
+			DSAerror(ERR_R_MALLOC_FAILURE);
+			params_len = 0;
+			goto err;
+		}
+		if ((astr = ASN1_STRING_new()) == NULL) {
+			DSAerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		ASN1_STRING_set0(astr, params, params_len);
+		params = NULL;
+		params_len = 0;
+		ptype = V_ASN1_SEQUENCE;
+	}
+
+	if ((aint = BN_to_ASN1_INTEGER(dsa->pub_key, NULL)) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		key_len = 0;
+		goto err;
+	}
+
+	if ((aobj = OBJ_nid2obj(EVP_PKEY_DSA)) == NULL)
+		goto err;
+	if (!X509_PUBKEY_set0_param(pk, aobj, ptype, astr, key, key_len))
+		goto err;
+	astr = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	ASN1_STRING_free(astr);
+	ASN1_INTEGER_free(aint);
+	freezero(params, params_len);
+	freezero(key, key_len);
+
+	return ret;
+}
+
+/*
+ * In PKCS#8 DSA: you just get a private key integer and parameters in the
+ * AlgorithmIdentifier the pubkey must be recalculated.
+ */
+static int
+dsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
+{
+	const X509_ALGOR *algor;
+	int ptype;
+	const void *pval;
+	const ASN1_STRING *astr;
+	const unsigned char *key, *params, *p;
+	int key_len, params_len;
+	ASN1_INTEGER *aint = NULL;
+	BN_CTX *ctx = NULL;
+	DSA *dsa = NULL;
+	int ret = 0;
+
+	if (!PKCS8_pkey_get0(NULL, &key, &key_len, &algor, p8))
+		goto err;
+	X509_ALGOR_get0(NULL, &ptype, &pval, algor);
+
+	if (ptype != V_ASN1_SEQUENCE) {
+		DSAerror(DSA_R_PARAMETER_ENCODING_ERROR);
+		goto err;
+	}
+
+	astr = pval;
+	params = astr->data;
+	params_len = astr->length;
+
+	p = params;
+	if ((dsa = d2i_DSAparams(NULL, &p, params_len)) == NULL) {
+		DSAerror(DSA_R_DECODE_ERROR);
+		goto err;
+	}
+	p = key;
+	if ((aint = d2i_ASN1_INTEGER(NULL, &p, key_len)) == NULL) {
+		DSAerror(DSA_R_DECODE_ERROR);
+		goto err;
+	}
+	BN_free(dsa->priv_key);
+	if ((dsa->priv_key = ASN1_INTEGER_to_BN(aint, NULL)) == NULL) {
+		DSAerror(DSA_R_BN_DECODE_ERROR);
+		goto err;
+	}
+
+	/* Check the key for basic consistency before doing expensive things. */
+	if (!dsa_check_key(dsa))
+		goto err;
+
+	/* Calculate public key */
+	BN_free(dsa->pub_key);
+	if ((dsa->pub_key = BN_new()) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	BN_CTX_start(ctx);
+
+	if (!BN_mod_exp_ct(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
+		DSAerror(DSA_R_BN_ERROR);
+		goto err;
+	}
+
+	if (!EVP_PKEY_assign_DSA(pkey, dsa))
+		goto err;
+	dsa = NULL;
+
+	ret = 1;
+
+ err:
+	DSA_free(dsa);
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	ASN1_INTEGER_free(aint);
+
+	return ret;
+}
+
+static int
+dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
+{
+	const DSA *dsa = pkey->pkey.dsa;
+	ASN1_STRING *astr = NULL;
+	int ptype = V_ASN1_SEQUENCE;
+	ASN1_INTEGER *aint = NULL;
+	ASN1_OBJECT *aobj;
+	unsigned char *params = NULL, *key = NULL;
+	int params_len = 0, key_len = 0;
+	int ret = 0;
+
+	if ((params_len = i2d_DSAparams(dsa, ¶ms)) <= 0) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		params_len = 0;
+		goto err;
+	}
+	if ((astr = ASN1_STRING_type_new(V_ASN1_SEQUENCE)) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	ASN1_STRING_set0(astr, params, params_len);
+	params = NULL;
+	params_len = 0;
+
+	if ((aint = BN_to_ASN1_INTEGER(dsa->priv_key, NULL)) == NULL) {
+		DSAerror(DSA_R_BN_ERROR);
+		goto err;
+	}
+	if ((key_len = i2d_ASN1_INTEGER(aint, &key)) <= 0) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		key_len = 0;
+		goto err;
+	}
+
+	if ((aobj = OBJ_nid2obj(NID_dsa)) == NULL)
+		goto err;
+	if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, astr, key, key_len))
+		goto err;
+	astr = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	ASN1_STRING_free(astr);
+	ASN1_INTEGER_free(aint);
+	freezero(params, params_len);
+	freezero(key, key_len);
+
+	return ret;
+}
+
+static int
+dsa_size(const EVP_PKEY *pkey)
+{
+	return DSA_size(pkey->pkey.dsa);
+}
+
+static int
+dsa_bits(const EVP_PKEY *pkey)
+{
+	return BN_num_bits(pkey->pkey.dsa->p);
+}
+
+static int
+dsa_security_bits(const EVP_PKEY *pkey)
+{
+	return DSA_security_bits(pkey->pkey.dsa);
+}
+
+static int
+dsa_missing_parameters(const EVP_PKEY *pkey)
+{
+	const DSA *dsa = pkey->pkey.dsa;
+
+	return dsa->p == NULL || dsa->q == NULL || dsa->g == NULL;
+}
+
+static int
+dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+{
+	BIGNUM *a;
+
+	if ((a = BN_dup(from->pkey.dsa->p)) == NULL)
+		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;
+	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;
+}
+
+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;
+}
+
+static void
+dsa_free(EVP_PKEY *pkey)
+{
+	DSA_free(pkey->pkey.dsa);
+}
+
+static int
+do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
+{
+	const char *ktype = NULL;
+	const BIGNUM *priv_key, *pub_key;
+	int ret = 0;
+
+	if (ptype == 2)
+		priv_key = x->priv_key;
+	else
+		priv_key = NULL;
+
+	if (ptype > 0)
+		pub_key = x->pub_key;
+	else
+		pub_key = NULL;
+
+	if (ptype == 2)
+		ktype = "Private-Key";
+	else if (ptype == 1)
+		ktype = "Public-Key";
+	else
+		ktype = "DSA-Parameters";
+
+	if (priv_key) {
+		if (!BIO_indent(bp, off, 128))
+			goto err;
+		if (BIO_printf(bp, "%s: (%d bit)\n", ktype,
+		    BN_num_bits(x->p)) <= 0)
+			goto err;
+	}
+
+	if (!bn_printf(bp, priv_key, off, "priv:"))
+		goto err;
+	if (!bn_printf(bp, pub_key, off, "pub: "))
+		goto err;
+	if (!bn_printf(bp, x->p, off, "P:   "))
+		goto err;
+	if (!bn_printf(bp, x->q, off, "Q:   "))
+		goto err;
+	if (!bn_printf(bp, x->g, off, "G:   "))
+		goto err;
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+static int
+dsa_param_decode(EVP_PKEY *pkey, const unsigned char **params, int params_len)
+{
+	DSA *dsa = NULL;
+	int ret = 0;
+
+	if ((dsa = d2i_DSAparams(NULL, params, params_len)) == NULL) {
+		DSAerror(ERR_R_DSA_LIB);
+		goto err;
+	}
+	if (!dsa_check_key(dsa))
+		goto err;
+	if (!EVP_PKEY_assign_DSA(pkey, dsa))
+		goto err;
+	dsa = NULL;
+
+	ret = 1;
+
+ err:
+	DSA_free(dsa);
+
+	return ret;
+}
+
+static int
+dsa_param_encode(const EVP_PKEY *pkey, unsigned char **params)
+{
+	return i2d_DSAparams(pkey->pkey.dsa, params);
+}
+
+static int
+dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
+}
+
+static int
+dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
+}
+
+static int
+dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
+}
+
+static int
+old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **key, int key_len)
+{
+	DSA *dsa = NULL;
+	BN_CTX *ctx = NULL;
+	BIGNUM *result;
+	int ret = 0;
+
+	if ((dsa = d2i_DSAPrivateKey(NULL, key, key_len)) == NULL) {
+		DSAerror(ERR_R_DSA_LIB);
+		goto err;
+	}
+
+	if (!dsa_check_key(dsa))
+		goto err;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((result = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Check that p and q are consistent with each other. dsa_check_key()
+	 * ensures that 1 < q < p. Now check that q divides p - 1.
+	 */
+
+	if (!BN_sub(result, dsa->p, BN_value_one()))
+		goto err;
+	if (!BN_mod_ct(result, result, dsa->q, ctx))
+		goto err;
+	if (!BN_is_zero(result)) {
+		DSAerror(DSA_R_BAD_Q_VALUE);
+		goto err;
+	}
+
+	/*
+	 * Check that g generates a multiplicative subgroup of order q.
+	 * We only check that g^q == 1, so the order is a divisor of q.
+	 * Once we know that q is prime, this is enough.
+	 */
+
+	if (!BN_mod_exp_ct(result, dsa->g, dsa->q, dsa->p, ctx))
+		goto err;
+	if (BN_cmp(result, BN_value_one()) != 0) {
+		DSAerror(DSA_R_INVALID_PARAMETERS);
+		goto err;
+	}
+
+	/*
+	 * Check that q is not a composite number.
+	 */
+
+	if (BN_is_prime_ex(dsa->q, BN_prime_checks, ctx, NULL) <= 0) {
+		DSAerror(DSA_R_BAD_Q_VALUE);
+		goto err;
+	}
+
+	if (!EVP_PKEY_assign_DSA(pkey, dsa))
+		goto err;
+	dsa = NULL;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	DSA_free(dsa);
+
+	return ret;
+}
+
+static int
+old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **key)
+{
+	return i2d_DSAPrivateKey(pkey->pkey.dsa, key);
+}
+
+static int
+dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
+    int indent, ASN1_PCTX *pctx)
+{
+	DSA_SIG *dsa_sig;
+	const unsigned char *p;
+
+	if (!sig) {
+		if (BIO_puts(bp, "\n") <= 0)
+			return 0;
+		else
+			return 1;
+	}
+	p = sig->data;
+	dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
+	if (dsa_sig) {
+		int rv = 0;
+
+		if (BIO_write(bp, "\n", 1) != 1)
+			goto err;
+
+		if (!bn_printf(bp, dsa_sig->r, indent, "r:   "))
+			goto err;
+		if (!bn_printf(bp, dsa_sig->s, indent, "s:   "))
+			goto err;
+		rv = 1;
+ err:
+		DSA_SIG_free(dsa_sig);
+		return rv;
+	}
+	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_sha1;
+		return 2;
+
+	default:
+		return -2;
+	}
+}
+
+/* NB these are sorted in pkey_id order, lowest first */
+
+const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = {
+	{
+		.pkey_id = EVP_PKEY_DSA2,
+		.pkey_base_id = EVP_PKEY_DSA,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+
+	{
+		.pkey_id = EVP_PKEY_DSA1,
+		.pkey_base_id = EVP_PKEY_DSA,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+
+	{
+		.pkey_id = EVP_PKEY_DSA4,
+		.pkey_base_id = EVP_PKEY_DSA,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+
+	{
+		.pkey_id = EVP_PKEY_DSA3,
+		.pkey_base_id = EVP_PKEY_DSA,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+
+	{
+		.pkey_id = EVP_PKEY_DSA,
+		.pkey_base_id = EVP_PKEY_DSA,
+
+		.pem_str = "DSA",
+		.info = "OpenSSL DSA method",
+
+		.pub_decode = dsa_pub_decode,
+		.pub_encode = dsa_pub_encode,
+		.pub_cmp = dsa_pub_cmp,
+		.pub_print = dsa_pub_print,
+
+		.priv_decode = dsa_priv_decode,
+		.priv_encode = dsa_priv_encode,
+		.priv_print = dsa_priv_print,
+
+		.pkey_size = dsa_size,
+		.pkey_bits = dsa_bits,
+		.pkey_security_bits = dsa_security_bits,
+
+		.param_decode = dsa_param_decode,
+		.param_encode = dsa_param_encode,
+		.param_missing = dsa_missing_parameters,
+		.param_copy = dsa_copy_parameters,
+		.param_cmp = dsa_cmp_parameters,
+		.param_print = dsa_param_print,
+		.sig_print = dsa_sig_print,
+
+		.pkey_free = dsa_free,
+		.pkey_ctrl = dsa_pkey_ctrl,
+		.old_priv_decode = old_dsa_priv_decode,
+		.old_priv_encode = old_dsa_priv_encode
+	}
+};
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
new file mode 100644
index 0000000..5e4f882
--- /dev/null
+++ b/crypto/dsa/dsa_asn1.c
@@ -0,0 +1,476 @@
+/* $OpenBSD: dsa_asn1.c,v 1.31 2023/07/08 14:28:15 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "dsa_local.h"
+
+/* Override the default new methods */
+static int
+sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_NEW_PRE) {
+		DSA_SIG *sig;
+
+		if ((sig = DSA_SIG_new()) == NULL) {
+			DSAerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		*pval = (ASN1_VALUE *)sig;
+		return 2;
+	}
+	return 1;
+}
+
+static const ASN1_AUX DSA_SIG_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = sig_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE DSA_SIG_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA_SIG, r),
+		.field_name = "r",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA_SIG, s),
+		.field_name = "s",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM DSA_SIG_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = DSA_SIG_seq_tt,
+	.tcount = sizeof(DSA_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &DSA_SIG_aux,
+	.size = sizeof(DSA_SIG),
+	.sname = "DSA_SIG",
+};
+
+
+DSA_SIG *
+d2i_DSA_SIG(DSA_SIG **a, const unsigned char **in, long len)
+{
+	return (DSA_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DSA_SIG_it);
+}
+LCRYPTO_ALIAS(d2i_DSA_SIG);
+
+int
+i2d_DSA_SIG(const DSA_SIG *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSA_SIG_it);
+}
+LCRYPTO_ALIAS(i2d_DSA_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;
+}
+LCRYPTO_ALIAS(DSA_SIG_get0);
+
+int
+DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+	if (r == NULL || s == NULL)
+		return 0;
+
+	BN_free(sig->r);
+	sig->r = r;
+	BN_free(sig->s);
+	sig->s = s;
+
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_SIG_set0);
+
+/* Override the default free and new methods */
+static int
+dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_NEW_PRE) {
+		*pval = (ASN1_VALUE *)DSA_new();
+		if (*pval)
+			return 2;
+		return 0;
+	} else if (operation == ASN1_OP_FREE_PRE) {
+		DSA_free((DSA *)*pval);
+		*pval = NULL;
+		return 2;
+	}
+	return 1;
+}
+
+static const ASN1_AUX DSAPrivateKey_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = dsa_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE DSAPrivateKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, p),
+		.field_name = "p",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, q),
+		.field_name = "q",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, g),
+		.field_name = "g",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, pub_key),
+		.field_name = "pub_key",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, priv_key),
+		.field_name = "priv_key",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM DSAPrivateKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = DSAPrivateKey_seq_tt,
+	.tcount = sizeof(DSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &DSAPrivateKey_aux,
+	.size = sizeof(DSA),
+	.sname = "DSA",
+};
+
+
+DSA *
+d2i_DSAPrivateKey(DSA **a, const unsigned char **in, long len)
+{
+	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DSAPrivateKey_it);
+}
+LCRYPTO_ALIAS(d2i_DSAPrivateKey);
+
+int
+i2d_DSAPrivateKey(const DSA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPrivateKey_it);
+}
+LCRYPTO_ALIAS(i2d_DSAPrivateKey);
+
+static const ASN1_AUX DSAparams_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = dsa_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE DSAparams_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, p),
+		.field_name = "p",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, q),
+		.field_name = "q",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, g),
+		.field_name = "g",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM DSAparams_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = DSAparams_seq_tt,
+	.tcount = sizeof(DSAparams_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &DSAparams_aux,
+	.size = sizeof(DSA),
+	.sname = "DSA",
+};
+
+
+DSA *
+d2i_DSAparams(DSA **a, const unsigned char **in, long len)
+{
+	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DSAparams_it);
+}
+LCRYPTO_ALIAS(d2i_DSAparams);
+
+int
+i2d_DSAparams(const DSA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAparams_it);
+}
+LCRYPTO_ALIAS(i2d_DSAparams);
+
+DSA *
+d2i_DSAparams_bio(BIO *bp, DSA **a)
+{
+	return ASN1_item_d2i_bio(&DSAparams_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_DSAparams_bio);
+
+int
+i2d_DSAparams_bio(BIO *bp, DSA *a)
+{
+	return ASN1_item_i2d_bio(&DSAparams_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_DSAparams_bio);
+
+DSA *
+d2i_DSAparams_fp(FILE *fp, DSA **a)
+{
+	return ASN1_item_d2i_fp(&DSAparams_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_DSAparams_fp);
+
+int
+i2d_DSAparams_fp(FILE *fp, DSA *a)
+{
+	return ASN1_item_i2d_fp(&DSAparams_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_DSAparams_fp);
+
+static const ASN1_AUX DSAPublicKey_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = dsa_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE DSAPublicKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, pub_key),
+		.field_name = "pub_key",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, p),
+		.field_name = "p",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, q),
+		.field_name = "q",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(DSA, g),
+		.field_name = "g",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM DSAPublicKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = DSAPublicKey_seq_tt,
+	.tcount = sizeof(DSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &DSAPublicKey_aux,
+	.size = sizeof(DSA),
+	.sname = "DSA",
+};
+
+DSA *
+d2i_DSAPublicKey(DSA **a, const unsigned char **in, long len)
+{
+	return (DSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &DSAPublicKey_it);
+}
+LCRYPTO_ALIAS(d2i_DSAPublicKey);
+
+int
+i2d_DSAPublicKey(const DSA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &DSAPublicKey_it);
+}
+LCRYPTO_ALIAS(i2d_DSAPublicKey);
+
+DSA *
+DSAparams_dup(DSA *dsa)
+{
+	return ASN1_item_dup(&DSAparams_it, dsa);
+}
+LCRYPTO_ALIAS(DSAparams_dup);
+
+int
+DSA_sign(int type, const unsigned char *dgst, int dlen, unsigned char *sig,
+    unsigned int *out_siglen, DSA *dsa)
+{
+	DSA_SIG *s;
+	int siglen;
+	int ret = 0;
+
+	*out_siglen = 0;
+
+	if ((s = DSA_do_sign(dgst, dlen, dsa)) == NULL)
+		goto err;
+
+	if ((siglen = i2d_DSA_SIG(s, &sig)) < 0)
+		goto err;
+
+	*out_siglen = siglen;
+
+	ret = 1;
+ err:
+	DSA_SIG_free(s);
+
+	return ret;
+}
+LCRYPTO_ALIAS(DSA_sign);
+
+/*
+ * 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 = NULL;
+	unsigned char *der = NULL;
+	const unsigned char *p;
+	int ret = -1;
+
+	p = sigbuf;
+	if ((s = d2i_DSA_SIG(NULL, &p, siglen)) == NULL)
+		goto err;
+
+	/* Ensure signature uses DER and doesn't have trailing garbage */
+	if (i2d_DSA_SIG(s, &der) != siglen)
+		goto err;
+
+	if (memcmp(der, sigbuf, siglen) != 0)
+		goto err;
+
+	ret = DSA_do_verify(dgst, dgst_len, s, dsa);
+ err:
+	free(der);
+	DSA_SIG_free(s);
+
+	return ret;
+}
+LCRYPTO_ALIAS(DSA_verify);
diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
new file mode 100644
index 0000000..6934fe1
--- /dev/null
+++ b/crypto/dsa/dsa_err.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: dsa_err.c,v 1.19 2023/07/08 14:28:15 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_DSA,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_DSA,0,reason)
+
+static ERR_STRING_DATA DSA_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA DSA_str_reasons[]=
+	{
+{ERR_REASON(DSA_R_BAD_Q_VALUE)           ,"bad q value"},
+{ERR_REASON(DSA_R_BN_DECODE_ERROR)       ,"bn decode error"},
+{ERR_REASON(DSA_R_BN_ERROR)              ,"bn error"},
+{ERR_REASON(DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),"data too large for key size"},
+{ERR_REASON(DSA_R_DECODE_ERROR)          ,"decode error"},
+{ERR_REASON(DSA_R_INVALID_DIGEST_TYPE)   ,"invalid digest type"},
+{ERR_REASON(DSA_R_INVALID_PARAMETERS)    ,"invalid parameters"},
+{ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
+{ERR_REASON(DSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
+{ERR_REASON(DSA_R_NEED_NEW_SETUP_VALUES) ,"need new setup values"},
+{ERR_REASON(DSA_R_NON_FIPS_DSA_METHOD)   ,"non fips dsa method"},
+{ERR_REASON(DSA_R_NO_PARAMETERS_SET)     ,"no parameters set"},
+{ERR_REASON(DSA_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
+{0,NULL}
+	};
+
+#endif
+
+void ERR_load_DSA_strings(void)
+	{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(DSA_str_functs[0].error) == NULL)
+		{
+		ERR_load_strings(0,DSA_str_functs);
+		ERR_load_strings(0,DSA_str_reasons);
+		}
+#endif
+	}
+LCRYPTO_ALIAS(ERR_load_DSA_strings);
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
new file mode 100644
index 0000000..490c7e5
--- /dev/null
+++ b/crypto/dsa/dsa_gen.c
@@ -0,0 +1,381 @@
+/* $OpenBSD: dsa_gen.c,v 1.30 2023/07/08 14:28:15 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include  /* To see if OPENSSL_NO_SHA is defined */
+
+#ifndef OPENSSL_NO_SHA
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dsa_local.h"
+
+int
+DSA_generate_parameters_ex(DSA *ret, 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,
+		    counter_ret, h_ret, cb);
+	else {
+		const EVP_MD *evpmd;
+		size_t qbits;
+
+		if (bits >= 2048) {
+			qbits = 256;
+			evpmd = EVP_sha256();
+		} else {
+			qbits = 160;
+			evpmd = EVP_sha1();
+		}
+
+		return dsa_builtin_paramgen(ret, bits, qbits, evpmd, seed_in,
+		    seed_len, NULL, counter_ret, h_ret, cb);
+	}
+}
+LCRYPTO_ALIAS(DSA_generate_parameters_ex);
+
+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 */
+		return 0;
+
+	if (evpmd == NULL)
+		/* use SHA1 as default */
+		evpmd = EVP_sha1();
+
+	if (bits < 512)
+		bits = 512;
+
+	bits = (bits + 63) / 64 * 64;
+
+	if (seed_len < (size_t)qsize) {
+		seed_in = NULL;		/* seed buffer too small -- ignore */
+		seed_len = 0;
+	}
+	/*
+	 * App. 2.2 of FIPS PUB 186 allows larger SEED,
+	 * but our internal buffers are restricted to 160 bits
+	 */
+	if (seed_len > (size_t)qsize)
+		seed_len = qsize;
+	if (seed_in != NULL)
+		memcpy(seed, seed_in, seed_len);
+	else if (seed_len != 0)
+		goto err;
+
+	if ((mont = BN_MONT_CTX_new()) == NULL)
+		goto err;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((r0 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((g = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((W = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((q = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((c = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((test = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_lshift(test, BN_value_one(), bits - 1))
+		goto err;
+
+	for (;;) {
+		for (;;) { /* find q */
+			int seed_is_random;
+
+			/* step 1 */
+			if (!BN_GENCB_call(cb, 0, m++))
+				goto err;
+
+			if (seed_len == 0) {
+				arc4random_buf(seed, qsize);
+				seed_is_random = 1;
+			} else {
+				seed_is_random = 0;
+				/* use random seed if 'seed_in' turns out
+				   to be bad */
+				seed_len = 0;
+			}
+			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,
+			    seed_is_random, 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_ct(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_ct(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_ct(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 != NULL)
+			memcpy(seed_out, seed, qsize);
+	}
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_MONT_CTX_free(mont);
+
+	return ok;
+}
+
+DSA *
+DSA_generate_parameters(int bits, unsigned char *seed_in, int seed_len,
+    int *counter_ret, unsigned long *h_ret, void (*callback)(int, int, void *),
+    void *cb_arg)
+{
+	BN_GENCB cb;
+	DSA *ret;
+
+	if ((ret = DSA_new()) == NULL)
+		return NULL;
+
+	BN_GENCB_set_old(&cb, callback, cb_arg);
+
+	if (DSA_generate_parameters_ex(ret, bits, seed_in, seed_len,
+	    counter_ret, h_ret, &cb))
+		return ret;
+	DSA_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(DSA_generate_parameters);
+
+#endif
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
new file mode 100644
index 0000000..431748a
--- /dev/null
+++ b/crypto/dsa/dsa_key.c
@@ -0,0 +1,120 @@
+/* $OpenBSD: dsa_key.c,v 1.35 2023/08/03 18:53:55 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_SHA
+
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dsa_local.h"
+
+static int dsa_builtin_keygen(DSA *dsa);
+
+int
+DSA_generate_key(DSA *dsa)
+{
+	if (dsa->meth->dsa_keygen)
+		return dsa->meth->dsa_keygen(dsa);
+	return dsa_builtin_keygen(dsa);
+}
+LCRYPTO_ALIAS(DSA_generate_key);
+
+static int
+dsa_builtin_keygen(DSA *dsa)
+{
+	BIGNUM *pub_key = NULL, *priv_key = NULL;
+	BN_CTX *ctx = NULL;
+	int ok = 0;
+
+	if ((priv_key = BN_new()) == NULL)
+		goto err;
+	if ((pub_key = BN_new()) == NULL)
+		goto err;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	if (!bn_rand_interval(priv_key, 1, dsa->q))
+		goto err;
+	if (!BN_mod_exp_ct(pub_key, dsa->g, priv_key, dsa->p, ctx))
+		goto err;
+
+	BN_free(dsa->priv_key);
+	dsa->priv_key = priv_key;
+	priv_key = NULL;
+
+	BN_free(dsa->pub_key);
+	dsa->pub_key = pub_key;
+	pub_key = NULL;
+
+	ok = 1;
+
+ err:
+	BN_free(pub_key);
+	BN_free(priv_key);
+	BN_CTX_free(ctx);
+
+	return ok;
+}
+#endif
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
new file mode 100644
index 0000000..a9d2179
--- /dev/null
+++ b/crypto/dsa/dsa_lib.c
@@ -0,0 +1,510 @@
+/* $OpenBSD: dsa_lib.c,v 1.44 2023/08/12 06:14:36 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Original version from Steven Schoch  */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "dh_local.h"
+#include "dsa_local.h"
+
+static const DSA_METHOD *default_DSA_method = NULL;
+
+void
+DSA_set_default_method(const DSA_METHOD *meth)
+{
+	default_DSA_method = meth;
+}
+LCRYPTO_ALIAS(DSA_set_default_method);
+
+const DSA_METHOD *
+DSA_get_default_method(void)
+{
+	if (!default_DSA_method)
+		default_DSA_method = DSA_OpenSSL();
+	return default_DSA_method;
+}
+LCRYPTO_ALIAS(DSA_get_default_method);
+
+DSA *
+DSA_new(void)
+{
+	return DSA_new_method(NULL);
+}
+LCRYPTO_ALIAS(DSA_new);
+
+int
+DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
+{
+	/*
+	 * NB: The caller is specifically setting a method, so it's not up to us
+	 * to deal with which ENGINE it comes from.
+	 */
+	const DSA_METHOD *mtmp;
+	mtmp = dsa->meth;
+	if (mtmp->finish)
+		mtmp->finish(dsa);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(dsa->engine);
+	dsa->engine = NULL;
+#endif
+	dsa->meth = meth;
+	if (meth->init)
+		meth->init(dsa);
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_set_method);
+
+DSA *
+DSA_new_method(ENGINE *engine)
+{
+	DSA *dsa;
+
+	if ((dsa = calloc(1, sizeof(DSA))) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	dsa->meth = DSA_get_default_method();
+	dsa->flags = dsa->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
+	dsa->references = 1;
+
+#ifndef OPENSSL_NO_ENGINE
+	if (engine) {
+		if (!ENGINE_init(engine)) {
+			DSAerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		dsa->engine = engine;
+	} else
+		dsa->engine = ENGINE_get_default_DSA();
+	if (dsa->engine != NULL) {
+		if ((dsa->meth = ENGINE_get_DSA(dsa->engine)) == NULL) {
+			DSAerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		dsa->flags = dsa->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
+	}
+#endif
+
+	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DSA, dsa, &dsa->ex_data))
+		goto err;
+	if (dsa->meth->init != NULL && !dsa->meth->init(dsa))
+		goto err;
+
+	return dsa;
+
+ err:
+	DSA_free(dsa);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(DSA_new_method);
+
+void
+DSA_free(DSA *r)
+{
+	int i;
+
+	if (r == NULL)
+		return;
+
+	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_DSA);
+	if (i > 0)
+		return;
+
+	if (r->meth != NULL && r->meth->finish != NULL)
+		r->meth->finish(r);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(r->engine);
+#endif
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
+
+	BN_free(r->p);
+	BN_free(r->q);
+	BN_free(r->g);
+	BN_free(r->pub_key);
+	BN_free(r->priv_key);
+	BN_free(r->kinv);
+	BN_free(r->r);
+	free(r);
+}
+LCRYPTO_ALIAS(DSA_free);
+
+int
+DSA_up_ref(DSA *r)
+{
+	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_DSA);
+	return i > 1 ? 1 : 0;
+}
+LCRYPTO_ALIAS(DSA_up_ref);
+
+int
+DSA_size(const DSA *r)
+{
+	DSA_SIG signature;
+	int ret = 0;
+
+	signature.r = r->q;
+	signature.s = r->q;
+
+	if ((ret = i2d_DSA_SIG(&signature, NULL)) < 0)
+		ret = 0;
+
+	return ret;
+}
+LCRYPTO_ALIAS(DSA_size);
+
+int
+DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_DSA, argl, argp,
+	    new_func, dup_func, free_func);
+}
+LCRYPTO_ALIAS(DSA_get_ex_new_index);
+
+int
+DSA_set_ex_data(DSA *d, int idx, void *arg)
+{
+	return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
+}
+LCRYPTO_ALIAS(DSA_set_ex_data);
+
+void *
+DSA_get_ex_data(DSA *d, int idx)
+{
+	return CRYPTO_get_ex_data(&d->ex_data, idx);
+}
+LCRYPTO_ALIAS(DSA_get_ex_data);
+
+int
+DSA_security_bits(const DSA *d)
+{
+	if (d->p == NULL || d->q == NULL)
+		return -1;
+
+	return BN_security_bits(BN_num_bits(d->p), BN_num_bits(d->q));
+}
+LCRYPTO_ALIAS(DSA_security_bits);
+
+#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;
+
+	if (r == NULL)
+		goto err;
+	ret = DH_new();
+	if (ret == NULL)
+		goto err;
+	if (r->p != NULL)
+		if ((ret->p = BN_dup(r->p)) == NULL)
+			goto err;
+	if (r->q != NULL) {
+		ret->length = BN_num_bits(r->q);
+		if ((ret->q = BN_dup(r->q)) == NULL)
+			goto err;
+	}
+	if (r->g != NULL)
+		if ((ret->g = BN_dup(r->g)) == NULL)
+			goto err;
+	if (r->pub_key != NULL)
+		if ((ret->pub_key = BN_dup(r->pub_key)) == NULL)
+			goto err;
+	if (r->priv_key != NULL)
+		if ((ret->priv_key = BN_dup(r->priv_key)) == NULL)
+			goto err;
+
+	return ret;
+
+err:
+	DH_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(DSA_dup_DH);
+#endif
+
+void
+DSA_get0_pqg(const DSA *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;
+}
+LCRYPTO_ALIAS(DSA_get0_pqg);
+
+int
+DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
+{
+	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 1;
+}
+LCRYPTO_ALIAS(DSA_set0_pqg);
+
+void
+DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key)
+{
+	if (pub_key != NULL)
+		*pub_key = d->pub_key;
+	if (priv_key != NULL)
+		*priv_key = d->priv_key;
+}
+LCRYPTO_ALIAS(DSA_get0_key);
+
+int
+DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
+{
+	if (d->pub_key == NULL && pub_key == NULL)
+		return 0;
+
+	if (pub_key != NULL) {
+		BN_free(d->pub_key);
+		d->pub_key = pub_key;
+	}
+	if (priv_key != NULL) {
+		BN_free(d->priv_key);
+		d->priv_key = priv_key;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_set0_key);
+
+const BIGNUM *
+DSA_get0_p(const DSA *d)
+{
+	return d->p;
+}
+LCRYPTO_ALIAS(DSA_get0_p);
+
+const BIGNUM *
+DSA_get0_q(const DSA *d)
+{
+	return d->q;
+}
+LCRYPTO_ALIAS(DSA_get0_q);
+
+const BIGNUM *
+DSA_get0_g(const DSA *d)
+{
+	return d->g;
+}
+LCRYPTO_ALIAS(DSA_get0_g);
+
+const BIGNUM *
+DSA_get0_pub_key(const DSA *d)
+{
+	return d->pub_key;
+}
+LCRYPTO_ALIAS(DSA_get0_pub_key);
+
+const BIGNUM *
+DSA_get0_priv_key(const DSA *d)
+{
+	return d->priv_key;
+}
+LCRYPTO_ALIAS(DSA_get0_priv_key);
+
+void
+DSA_clear_flags(DSA *d, int flags)
+{
+	d->flags &= ~flags;
+}
+LCRYPTO_ALIAS(DSA_clear_flags);
+
+int
+DSA_test_flags(const DSA *d, int flags)
+{
+	return d->flags & flags;
+}
+LCRYPTO_ALIAS(DSA_test_flags);
+
+void
+DSA_set_flags(DSA *d, int flags)
+{
+	d->flags |= flags;
+}
+LCRYPTO_ALIAS(DSA_set_flags);
+
+ENGINE *
+DSA_get0_engine(DSA *d)
+{
+	return d->engine;
+}
+LCRYPTO_ALIAS(DSA_get0_engine);
+
+int
+DSA_bits(const DSA *dsa)
+{
+	return BN_num_bits(dsa->p);
+}
+LCRYPTO_ALIAS(DSA_bits);
+
+int
+dsa_check_key(const DSA *dsa)
+{
+	int p_bits, q_bits;
+
+	if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+		DSAerror(DSA_R_MISSING_PARAMETERS);
+		return 0;
+	}
+
+	/* Checking that p and q are primes is expensive. Check they are odd. */
+	if (!BN_is_odd(dsa->p) || !BN_is_odd(dsa->q)) {
+		DSAerror(DSA_R_INVALID_PARAMETERS);
+		return 0;
+	}
+
+	/* FIPS 186-4: 1 < g < p. */
+	if (BN_cmp(dsa->g, BN_value_one()) <= 0 ||
+	    BN_cmp(dsa->g, dsa->p) >= 0) {
+		DSAerror(DSA_R_INVALID_PARAMETERS);
+		return 0;
+	}
+
+	/* We know p and g are positive. The next two checks imply q > 0. */
+	if (BN_is_negative(dsa->q)) {
+		DSAerror(DSA_R_BAD_Q_VALUE);
+		return 0;
+	}
+
+	/* FIPS 186-4 only allows three sizes for q. */
+	q_bits = BN_num_bits(dsa->q);
+	if (q_bits != 160 && q_bits != 224 && q_bits != 256) {
+		DSAerror(DSA_R_BAD_Q_VALUE);
+		return 0;
+	}
+
+	/*
+	 * XXX - FIPS 186-4 only allows 1024, 2048, and 3072 bits for p.
+	 * Cap the size to reduce DoS risks. Poor defaults make keys with
+	 * incorrect p sizes >= 512 bits common, so only enforce a weak
+	 * lower bound.
+	 */
+	p_bits = BN_num_bits(dsa->p);
+	if (p_bits > OPENSSL_DSA_MAX_MODULUS_BITS) {
+		DSAerror(DSA_R_MODULUS_TOO_LARGE);
+		return 0;
+	}
+	if (p_bits < 512) {
+		DSAerror(DSA_R_INVALID_PARAMETERS);
+		return 0;
+	}
+
+	/* The public key must be in the multiplicative group (mod p). */
+	if (dsa->pub_key != NULL) {
+		if (BN_cmp(dsa->pub_key, BN_value_one()) <= 0 ||
+		    BN_cmp(dsa->pub_key, dsa->p) >= 0) {
+			DSAerror(DSA_R_INVALID_PARAMETERS);
+			return 0;
+		}
+	}
+
+	/* The private key must be nonzero and in GF(q). */
+	if (dsa->priv_key != NULL) {
+		if (BN_cmp(dsa->priv_key, BN_value_one()) < 0 ||
+		    BN_cmp(dsa->priv_key, dsa->q) >= 0) {
+			DSAerror(DSA_R_INVALID_PARAMETERS);
+			return 0;
+		}
+	}
+
+	return 1;
+}
diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h
new file mode 100644
index 0000000..a413db9
--- /dev/null
+++ b/crypto/dsa/dsa_local.h
@@ -0,0 +1,120 @@
+/* $OpenBSD: dsa_local.h,v 1.2 2023/03/04 20:54:52 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+struct DSA_SIG_st {
+	BIGNUM *r;
+	BIGNUM *s;
+} /* DSA_SIG */;
+
+struct dsa_method {
+	char *name;
+	DSA_SIG *(*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa);
+	int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+	    BIGNUM **rp);
+	int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len,
+	    DSA_SIG *sig, DSA *dsa);
+	int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
+	    BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
+	    BN_MONT_CTX *in_mont);
+	int (*bn_mod_exp)(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
+	    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */
+	int (*init)(DSA *dsa);
+	int (*finish)(DSA *dsa);
+	int flags;
+	char *app_data;
+	/* If this is non-NULL, it is used to generate DSA parameters */
+	int (*dsa_paramgen)(DSA *dsa, int bits, const unsigned char *seed,
+	    int seed_len, int *counter_ret, unsigned long *h_ret, BN_GENCB *cb);
+	/* If this is non-NULL, it is used to generate DSA keys */
+	int (*dsa_keygen)(DSA *dsa);
+} /* DSA_METHOD */;
+
+struct dsa_st {
+	/* This first variable is used to pick up errors where
+	 * a DSA is passed instead of of a EVP_PKEY */
+	int pad;
+	long version;
+	BIGNUM *p;
+	BIGNUM *q;	/* == 20 */
+	BIGNUM *g;
+
+	BIGNUM *pub_key;  /* y public key */
+	BIGNUM *priv_key; /* x private key */
+
+	BIGNUM *kinv;	/* Signing pre-calc */
+	BIGNUM *r;	/* Signing pre-calc */
+
+	int flags;
+	/* Normally used to cache montgomery values */
+	BN_MONT_CTX *method_mont_p;
+	int references;
+	CRYPTO_EX_DATA ex_data;
+	const DSA_METHOD *meth;
+	/* functional reference if 'meth' is ENGINE-provided */
+	ENGINE *engine;
+} /* 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_check_key(const DSA *dsa);
+
+__END_HIDDEN_DECLS
diff --git a/crypto/dsa/dsa_meth.c b/crypto/dsa/dsa_meth.c
new file mode 100644
index 0000000..c84b528
--- /dev/null
+++ b/crypto/dsa/dsa_meth.c
@@ -0,0 +1,110 @@
+/*	$OpenBSD: dsa_meth.c,v 1.7 2023/07/08 14:28:15 beck Exp $	*/
+/*
+ * Copyright (c) 2018 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "dsa_local.h"
+
+DSA_METHOD *
+DSA_meth_new(const char *name, int flags)
+{
+	DSA_METHOD *meth;
+
+	if ((meth = calloc(1, sizeof(*meth))) == NULL)
+		return NULL;
+	if ((meth->name = strdup(name)) == NULL) {
+		free(meth);
+		return NULL;
+	}
+	meth->flags = flags;
+
+	return meth;
+}
+LCRYPTO_ALIAS(DSA_meth_new);
+
+void
+DSA_meth_free(DSA_METHOD *meth)
+{
+	if (meth == NULL)
+		return;
+
+	free(meth->name);
+	free(meth);
+}
+LCRYPTO_ALIAS(DSA_meth_free);
+
+DSA_METHOD *
+DSA_meth_dup(const DSA_METHOD *meth)
+{
+	DSA_METHOD *copy;
+
+	if ((copy = calloc(1, sizeof(*copy))) == NULL)
+		return NULL;
+	memcpy(copy, meth, sizeof(*copy));
+	if ((copy->name = strdup(meth->name)) == NULL) {
+		free(copy);
+		return NULL;
+	}
+
+	return copy;
+}
+LCRYPTO_ALIAS(DSA_meth_dup);
+
+const char *
+DSA_meth_get0_name(const DSA_METHOD *meth)
+{
+	return meth->name;
+}
+LCRYPTO_ALIAS(DSA_meth_get0_name);
+
+int
+DSA_meth_set1_name(DSA_METHOD *meth, const char *name)
+{
+	char *new_name;
+
+	if ((new_name = strdup(name)) == NULL) {
+		DSAerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	free(meth->name);
+	meth->name = new_name;
+
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_meth_set1_name);
+
+int
+DSA_meth_set_sign(DSA_METHOD *meth,
+    DSA_SIG *(*sign)(const unsigned char *, int, DSA *))
+{
+	meth->dsa_do_sign = sign;
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_meth_set_sign);
+
+int
+DSA_meth_set_finish(DSA_METHOD *meth, int (*finish)(DSA *))
+{
+	meth->finish = finish;
+	return 1;
+}
+LCRYPTO_ALIAS(DSA_meth_set_finish);
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
new file mode 100644
index 0000000..b92d0b8
--- /dev/null
+++ b/crypto/dsa/dsa_ossl.c
@@ -0,0 +1,477 @@
+/* $OpenBSD: dsa_ossl.c,v 1.53 2023/08/03 18:53:55 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Original version from Steven Schoch  */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dsa_local.h"
+
+static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
+    BIGNUM **rp);
+static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
+    DSA *dsa);
+static int dsa_init(DSA *dsa);
+static int dsa_finish(DSA *dsa);
+
+static DSA_METHOD openssl_dsa_meth = {
+	.name = "OpenSSL DSA method",
+	.dsa_do_sign = dsa_do_sign,
+	.dsa_sign_setup = dsa_sign_setup,
+	.dsa_do_verify = dsa_do_verify,
+	.init = dsa_init,
+	.finish = dsa_finish,
+};
+
+const DSA_METHOD *
+DSA_OpenSSL(void)
+{
+	return &openssl_dsa_meth;
+}
+LCRYPTO_ALIAS(DSA_OpenSSL);
+
+/*
+ * Since DSA parameters are entirely arbitrary and checking them to be
+ * consistent is very expensive, we cannot do so on every sign operation.
+ * Instead, cap the number of retries so we do not loop indefinitely if
+ * the generator of the multiplicative group happens to be nilpotent.
+ * The probability of needing a retry with valid parameters is negligible,
+ * so trying 32 times is amply enough.
+ */
+#define DSA_MAX_SIGN_ITERATIONS		32
+
+static DSA_SIG *
+dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+	BIGNUM *b = NULL, *bm = NULL, *bxr = NULL, *binv = NULL, *m = NULL;
+	BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
+	BN_CTX *ctx = NULL;
+	int reason = ERR_R_BN_LIB;
+	DSA_SIG *ret = NULL;
+	int attempts = 0;
+	int noredo = 0;
+
+	if (!dsa_check_key(dsa)) {
+		reason = DSA_R_INVALID_PARAMETERS;
+		goto err;
+	}
+
+	if ((s = BN_new()) == NULL)
+		goto err;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((binv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((bm = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((bxr = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((m = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * If the digest length is greater than N (the bit length of q), the
+	 * leftmost N bits of the digest shall be used, see FIPS 186-3, 4.2.
+	 * In this case the digest length is given in bytes.
+	 */
+	if (dlen > BN_num_bytes(dsa->q))
+		dlen = BN_num_bytes(dsa->q);
+	if (BN_bin2bn(dgst, dlen, m) == NULL)
+		goto err;
+
+ redo:
+	if (dsa->kinv == NULL || dsa->r == NULL) {
+		if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
+			goto err;
+	} else {
+		kinv = dsa->kinv;
+		dsa->kinv = NULL;
+		r = dsa->r;
+		dsa->r = NULL;
+		noredo = 1;
+	}
+
+	/*
+	 * Compute:
+	 *
+	 *  s = inv(k)(m + xr) mod q
+	 *
+	 * In order to reduce the possibility of a side-channel attack, the
+	 * following is calculated using a blinding value:
+	 *
+	 *  s = inv(b)(bm + bxr)inv(k) mod q
+	 *
+	 * Where b is a random value in the range [1, q).
+	 */
+	if (!bn_rand_interval(b, 1, dsa->q))
+		goto err;
+	if (BN_mod_inverse_ct(binv, b, dsa->q, ctx) == NULL)
+		goto err;
+
+	if (!BN_mod_mul(bxr, b, dsa->priv_key, dsa->q, ctx))	/* bx */
+		goto err;
+	if (!BN_mod_mul(bxr, bxr, r, dsa->q, ctx))	/* bxr */
+		goto err;
+	if (!BN_mod_mul(bm, b, m, dsa->q, ctx))		/* bm */
+		goto err;
+	if (!BN_mod_add(s, bxr, bm, dsa->q, ctx))	/* s = bm + bxr */
+		goto err;
+	if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))	/* s = b(m + xr)k^-1 */
+		goto err;
+	if (!BN_mod_mul(s, s, binv, dsa->q, ctx))	/* s = (m + xr)k^-1 */
+		goto err;
+
+	/*
+	 * Redo if r or s is zero as required by FIPS 186-3: this is very
+	 * unlikely.
+	 */
+	if (BN_is_zero(r) || BN_is_zero(s)) {
+		if (noredo) {
+			reason = DSA_R_NEED_NEW_SETUP_VALUES;
+			goto err;
+		}
+		if (++attempts > DSA_MAX_SIGN_ITERATIONS) {
+			reason = DSA_R_INVALID_PARAMETERS;
+			goto err;
+		}
+		goto redo;
+	}
+
+	if ((ret = DSA_SIG_new()) == NULL) {
+		reason = ERR_R_MALLOC_FAILURE;
+		goto err;
+	}
+	ret->r = r;
+	ret->s = s;
+
+ err:
+	if (!ret) {
+		DSAerror(reason);
+		BN_free(r);
+		BN_free(s);
+	}
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(kinv);
+
+	return ret;
+}
+
+static int
+dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
+{
+	BIGNUM *k = NULL, *l = NULL, *m = NULL, *kinv = NULL, *r = NULL;
+	BN_CTX *ctx = NULL;
+	int q_bits;
+	int ret = 0;
+
+	if (!dsa_check_key(dsa))
+		goto err;
+
+	if ((r = BN_new()) == NULL)
+		goto err;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((l = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((m = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Preallocate space */
+	q_bits = BN_num_bits(dsa->q);
+	if (!BN_set_bit(k, q_bits) ||
+	    !BN_set_bit(l, q_bits) ||
+	    !BN_set_bit(m, q_bits))
+		goto err;
+
+	if (!bn_rand_interval(k, 1, dsa->q))
+		goto err;
+
+	BN_set_flags(k, BN_FLG_CONSTTIME);
+
+	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
+		if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
+		    CRYPTO_LOCK_DSA, dsa->p, ctx))
+			goto err;
+	}
+
+	/* Compute r = (g^k mod p) mod q */
+
+	/*
+	 * We do not want timing information to leak the length of k,
+	 * so we compute G^k using an equivalent exponent of fixed
+	 * bit-length.
+	 *
+	 * We unconditionally perform both of these additions to prevent a
+	 * small timing information leakage.  We then choose the sum that is
+	 * one bit longer than the modulus.
+	 *
+	 * TODO: revisit the bn_copy aiming for a memory access agnostic
+	 * conditional copy.
+	 */
+
+	if (!BN_add(l, k, dsa->q) ||
+	    !BN_add(m, l, dsa->q) ||
+	    !bn_copy(k, BN_num_bits(l) > q_bits ? l : m))
+		goto err;
+
+	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))
+			goto err;
+	} else {
+		if (!BN_mod_exp_mont_ct(r, dsa->g, k, dsa->p, ctx,
+		    dsa->method_mont_p))
+			goto err;
+	}
+
+	if (!BN_mod_ct(r, r, dsa->q, ctx))
+		goto err;
+
+	/* Compute  part of 's = inv(k) (m + xr) mod q' */
+	if ((kinv = BN_mod_inverse_ct(NULL, k, dsa->q, ctx)) == NULL)
+		goto err;
+
+	BN_free(*kinvp);
+	*kinvp = kinv;
+	kinv = NULL;
+
+	BN_free(*rp);
+	*rp = r;
+
+	ret = 1;
+
+ err:
+	if (!ret) {
+		DSAerror(ERR_R_BN_LIB);
+		BN_free(r);
+	}
+	BN_CTX_end(ctx);
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+
+static int
+dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
+{
+	BIGNUM *u1 = NULL, *u2 = NULL, *t1 = NULL;
+	BN_CTX *ctx = NULL;
+	BN_MONT_CTX *mont = NULL;
+	int qbits;
+	int ret = -1;
+
+	if (!dsa_check_key(dsa))
+		goto err;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((u1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((u2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((t1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
+	    BN_ucmp(sig->r, dsa->q) >= 0) {
+		ret = 0;
+		goto err;
+	}
+	if (BN_is_zero(sig->s) || BN_is_negative(sig->s) ||
+	    BN_ucmp(sig->s, dsa->q) >= 0) {
+		ret = 0;
+		goto err;
+	}
+
+	/* Calculate w = inv(s) mod q, saving w in u2. */
+	if ((BN_mod_inverse_ct(u2, sig->s, dsa->q, ctx)) == NULL)
+		goto err;
+
+	/*
+	 * 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-4, 4.2.
+	 */
+	qbits = BN_num_bits(dsa->q);
+	if (dgst_len > (qbits >> 3))
+		dgst_len = (qbits >> 3);
+
+	/* Save m in u1. */
+	if (BN_bin2bn(dgst, dgst_len, u1) == NULL)
+		goto err;
+
+	/* u1 = m * w mod q */
+	if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx))
+		goto err;
+
+	/* u2 = r * w mod q */
+	if (!BN_mod_mul(u2, sig->r, u2, dsa->q, ctx))
+		goto err;
+
+	if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
+		mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
+		    CRYPTO_LOCK_DSA, dsa->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))
+			goto err;
+	} else {
+		if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2,
+		    dsa->p, ctx, mont))
+			goto err;
+	}
+
+	/* let u1 = u1 mod q */
+	if (!BN_mod_ct(u1, t1, dsa->q, ctx))
+		goto err;
+
+	/* v is in u1 - if the signature is correct, it will be equal to r. */
+	ret = BN_ucmp(u1, sig->r) == 0;
+
+ err:
+	if (ret < 0)
+		DSAerror(ERR_R_BN_LIB);
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return ret;
+}
+
+static int
+dsa_init(DSA *dsa)
+{
+	dsa->flags |= DSA_FLAG_CACHE_MONT_P;
+	return 1;
+}
+
+static int
+dsa_finish(DSA *dsa)
+{
+	BN_MONT_CTX_free(dsa->method_mont_p);
+	return 1;
+}
+
+DSA_SIG *
+DSA_SIG_new(void)
+{
+	return calloc(1, sizeof(DSA_SIG));
+}
+LCRYPTO_ALIAS(DSA_SIG_new);
+
+void
+DSA_SIG_free(DSA_SIG *sig)
+{
+	if (sig == NULL)
+		return;
+
+	BN_free(sig->r);
+	BN_free(sig->s);
+	free(sig);
+}
+LCRYPTO_ALIAS(DSA_SIG_free);
+
+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);
+}
+LCRYPTO_ALIAS(DSA_sign_setup);
+
+DSA_SIG *
+DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+	return dsa->meth->dsa_do_sign(dgst, dlen, dsa);
+}
+LCRYPTO_ALIAS(DSA_do_sign);
+
+int
+DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
+{
+	return dsa->meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
+}
+LCRYPTO_ALIAS(DSA_do_verify);
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
new file mode 100644
index 0000000..9b03a2f
--- /dev/null
+++ b/crypto/dsa/dsa_pmeth.c
@@ -0,0 +1,350 @@
+/* $OpenBSD: dsa_pmeth.c,v 1.17 2023/04/25 15:48:48 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dsa_local.h"
+#include "evp_local.h"
+
+/* DSA pkey context structure */
+
+typedef struct {
+	/* Parameter gen parameters */
+	int nbits;		/* size of p in bits (default: 1024) */
+	int qbits;		/* size of q in bits (default: 160)  */
+	const EVP_MD *pmd;	/* MD for parameter generation */
+	/* Keygen callback info */
+	int gentmp[2];
+	/* message digest */
+	const EVP_MD *md;	/* MD for the signature */
+} DSA_PKEY_CTX;
+
+static int
+pkey_dsa_init(EVP_PKEY_CTX *ctx)
+{
+	DSA_PKEY_CTX *dctx;
+
+	dctx = malloc(sizeof(DSA_PKEY_CTX));
+	if (!dctx)
+		return 0;
+	dctx->nbits = 1024;
+	dctx->qbits = 160;
+	dctx->pmd = NULL;
+	dctx->md = NULL;
+
+	ctx->data = dctx;
+	ctx->keygen_info = dctx->gentmp;
+	ctx->keygen_info_count = 2;
+
+	return 1;
+}
+
+static int
+pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	DSA_PKEY_CTX *dctx, *sctx;
+
+	if (!pkey_dsa_init(dst))
+		return 0;
+	sctx = src->data;
+	dctx = dst->data;
+	dctx->nbits = sctx->nbits;
+	dctx->qbits = sctx->qbits;
+	dctx->pmd = sctx->pmd;
+	dctx->md  = sctx->md;
+	return 1;
+}
+
+static void
+pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
+{
+	DSA_PKEY_CTX *dctx = ctx->data;
+
+	free(dctx);
+}
+
+static int
+pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *out_siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	DSA *dsa = ctx->pkey->pkey.dsa;
+	DSA_PKEY_CTX *dctx = ctx->data;
+	unsigned int siglen;
+
+	*out_siglen = 0;
+
+	if (tbslen > INT_MAX)
+		 return 0;
+
+	if (dctx->md != NULL) {
+		if (tbslen != EVP_MD_size(dctx->md))
+			return 0;
+	}
+
+	if (!DSA_sign(0, tbs, tbslen, sig, &siglen, dsa))
+		return 0;
+
+	*out_siglen = siglen;
+
+	return 1;
+}
+
+static int
+pkey_dsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	DSA *dsa = ctx->pkey->pkey.dsa;
+	DSA_PKEY_CTX *dctx = ctx->data;
+
+	if (tbslen > INT_MAX || siglen > INT_MAX)
+		 return 0;
+
+	if (dctx->md != NULL) {
+		if (tbslen != EVP_MD_size(dctx->md))
+			return 0;
+	}
+
+	return DSA_verify(0, tbs, tbslen, sig, siglen, dsa);
+}
+
+static int
+pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	DSA_PKEY_CTX *dctx = ctx->data;
+
+	switch (type) {
+	case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
+		if (p1 < 256)
+			return -2;
+		dctx->nbits = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
+		if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
+			return -2;
+		dctx->qbits = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
+		switch (EVP_MD_type((const EVP_MD *)p2)) {
+		case NID_sha1:
+		case NID_sha224:
+		case NID_sha256:
+			break;
+		default:
+			DSAerror(DSA_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		dctx->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_MD:
+		/* ANSI X9.57 and NIST CSOR. */
+		switch (EVP_MD_type((const EVP_MD *)p2)) {
+		case NID_sha1:
+		case NID_dsa:
+		case NID_dsaWithSHA:
+		case NID_sha224:
+		case NID_sha256:
+		case NID_sha384:
+		case NID_sha512:
+		case NID_sha3_224:
+		case NID_sha3_256:
+		case NID_sha3_384:
+		case NID_sha3_512:
+			break;
+		default:
+			DSAerror(DSA_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		dctx->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_MD:
+		*(const EVP_MD **)p2 = dctx->md;
+		return 1;
+
+	case EVP_PKEY_CTRL_DIGESTINIT:
+	case EVP_PKEY_CTRL_PKCS7_SIGN:
+	case EVP_PKEY_CTRL_CMS_SIGN:
+		return 1;
+
+	case EVP_PKEY_CTRL_PEER_KEY:
+		DSAerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	default:
+		return -2;
+	}
+}
+
+static int
+pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+	long lval;
+	char *ep;
+
+	if (!strcmp(type, "dsa_paramgen_bits")) {
+		int nbits;
+
+		errno = 0;
+		lval = strtol(value, &ep, 10);
+		if (value[0] == '\0' || *ep != '\0')
+			goto not_a_number;
+		if ((errno == ERANGE &&
+		    (lval == LONG_MAX || lval == LONG_MIN)) ||
+		    (lval > INT_MAX || lval < INT_MIN))
+			goto out_of_range;
+		nbits = lval;
+		return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
+	} else if (!strcmp(type, "dsa_paramgen_q_bits")) {
+		int qbits;
+
+		errno = 0;
+		lval = strtol(value, &ep, 10);
+		if (value[0] == '\0' || *ep != '\0')
+			goto not_a_number;
+		if ((errno == ERANGE &&
+		    (lval == LONG_MAX || lval == LONG_MIN)) ||
+		    (lval > INT_MAX || lval < INT_MIN))
+			goto out_of_range;
+		qbits = lval;
+		return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA,
+		    EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS,
+		    qbits, NULL);
+	} else if (!strcmp(type, "dsa_paramgen_md")) {
+		return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA,
+		    EVP_PKEY_OP_PARAMGEN, EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
+		    (void *)EVP_get_digestbyname(value));
+	}
+not_a_number:
+out_of_range:
+	return -2;
+}
+
+static int
+pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	DSA *dsa = NULL;
+	DSA_PKEY_CTX *dctx = ctx->data;
+	BN_GENCB *pcb, cb;
+	int ret;
+
+	if (ctx->pkey_gencb) {
+		pcb = &cb;
+		evp_pkey_set_cb_translate(pcb, ctx);
+	} else
+		pcb = NULL;
+	dsa = DSA_new();
+	if (!dsa)
+		return 0;
+	ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
+	    NULL, 0, NULL, NULL, NULL, pcb);
+	if (ret)
+		EVP_PKEY_assign_DSA(pkey, dsa);
+	else
+		DSA_free(dsa);
+	return ret;
+}
+
+static int
+pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	DSA *dsa = NULL;
+
+	if (ctx->pkey == NULL) {
+		DSAerror(DSA_R_NO_PARAMETERS_SET);
+		return 0;
+	}
+	dsa = DSA_new();
+	if (!dsa)
+		return 0;
+	EVP_PKEY_assign_DSA(pkey, dsa);
+	/* 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);
+}
+
+const EVP_PKEY_METHOD dsa_pkey_meth = {
+	.pkey_id = EVP_PKEY_DSA,
+	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
+
+	.init = pkey_dsa_init,
+	.copy = pkey_dsa_copy,
+	.cleanup = pkey_dsa_cleanup,
+
+	.paramgen = pkey_dsa_paramgen,
+
+	.keygen = pkey_dsa_keygen,
+
+	.sign = pkey_dsa_sign,
+
+	.verify = pkey_dsa_verify,
+
+	.ctrl = pkey_dsa_ctrl,
+	.ctrl_str = pkey_dsa_ctrl_str
+};
diff --git a/crypto/dsa/dsa_prn.c b/crypto/dsa/dsa_prn.c
new file mode 100644
index 0000000..f276d82
--- /dev/null
+++ b/crypto/dsa/dsa_prn.c
@@ -0,0 +1,135 @@
+/* $OpenBSD: dsa_prn.c,v 1.10 2023/07/08 14:28:15 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+int
+DSA_print_fp(FILE *fp, const DSA *x, int off)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		DSAerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = DSA_print(b, x, off);
+	BIO_free(b);
+	return ret;
+}
+LCRYPTO_ALIAS(DSA_print_fp);
+
+int
+DSAparams_print_fp(FILE *fp, const DSA *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		DSAerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = DSAparams_print(b, x);
+	BIO_free(b);
+	return ret;
+}
+LCRYPTO_ALIAS(DSAparams_print_fp);
+
+int
+DSA_print(BIO *bp, const DSA *x, int off)
+{
+	EVP_PKEY *pk;
+	int ret = 0;
+
+	if ((pk = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!EVP_PKEY_set1_DSA(pk, (DSA *)x))
+		goto err;
+
+	ret = EVP_PKEY_print_private(bp, pk, off, NULL);
+ err:
+	EVP_PKEY_free(pk);
+	return ret;
+}
+LCRYPTO_ALIAS(DSA_print);
+
+int
+DSAparams_print(BIO *bp, const DSA *x)
+{
+	EVP_PKEY *pk;
+	int ret = 0;
+
+	if ((pk = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!EVP_PKEY_set1_DSA(pk, (DSA *)x))
+		goto err;
+
+	ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
+ err:
+	EVP_PKEY_free(pk);
+	return ret;
+}
+LCRYPTO_ALIAS(DSAparams_print);
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
new file mode 100644
index 0000000..3248658
--- /dev/null
+++ b/crypto/ec/ec_ameth.c
@@ -0,0 +1,1071 @@
+/* $OpenBSD: ec_ameth.c,v 1.45 2023/09/24 08:08:54 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "ec_local.h"
+#include "evp_local.h"
+
+#ifndef OPENSSL_NO_CMS
+static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
+static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
+#endif
+
+static void
+eckey_param_free(int ptype, void *pval)
+{
+	if (pval == NULL)
+		return;
+	if (ptype == V_ASN1_OBJECT)
+		ASN1_OBJECT_free(pval);		/* XXX - really necessary? */
+	else
+		ASN1_STRING_free(pval);
+}
+
+static int
+eckey_get_curve_name(const EC_KEY *eckey, int *nid)
+{
+	const EC_GROUP *group;
+
+	*nid = NID_undef;
+
+	if ((group = EC_KEY_get0_group(eckey)) == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		return 0;
+	}
+	if (EC_GROUP_get_asn1_flag(group) != 0)
+		*nid = EC_GROUP_get_curve_name(group);
+
+	return 1;
+}
+
+static int
+eckey_to_explicit_params(EC_KEY *eckey, void **out_val)
+{
+	ASN1_STRING *astr = NULL;
+	unsigned char *params = NULL;
+	int params_len = 0;
+	int ret = 0;
+
+	*out_val = NULL;
+
+	if ((params_len = i2d_ECParameters(eckey, ¶ms)) <= 0) {
+		ECerror(ERR_R_EC_LIB);
+		params_len = 0;
+		goto err;
+	}
+
+	if ((astr = ASN1_STRING_new()) == NULL)
+		goto err;
+	ASN1_STRING_set0(astr, params, params_len);
+	params = NULL;
+	params_len = 0;
+
+	*out_val = astr;
+	astr = NULL;
+
+	ret = 1;
+
+ err:
+	freezero(params, params_len);
+	ASN1_STRING_free(astr);
+
+	return ret;
+}
+
+static int
+eckey_from_explicit_params(const ASN1_STRING *astr, EC_KEY **out_eckey)
+{
+	const unsigned char *params = astr->data;
+	int params_len = astr->length;
+
+	EC_KEY_free(*out_eckey);
+	if ((*out_eckey = d2i_ECParameters(NULL, ¶ms, params_len)) == NULL) {
+		ECerror(EC_R_DECODE_ERROR);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+eckey_to_object(const EC_KEY *eckey, void **out_val)
+{
+	int nid = NID_undef;
+
+	*out_val = NULL;
+
+	if (!eckey_get_curve_name(eckey, &nid))
+		return 0;
+	if ((*out_val = OBJ_nid2obj(nid)) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static int
+eckey_from_object(const ASN1_OBJECT *aobj, EC_KEY **out_eckey)
+{
+	int nid;
+
+	*out_eckey = NULL;
+
+	if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
+		return 0;
+	if ((*out_eckey = EC_KEY_new_by_curve_name(nid)) == NULL)
+		return 0;
+
+	return 1;
+}
+
+static int
+eckey_to_params(EC_KEY *eckey, int *out_type, void **out_val)
+{
+	int nid;
+
+	*out_type = NID_undef;
+	*out_val = NULL;
+
+	if (!eckey_get_curve_name(eckey, &nid))
+		return 0;
+
+	if (nid == NID_undef) {
+		*out_type = V_ASN1_SEQUENCE;
+		return eckey_to_explicit_params(eckey, out_val);
+	} else {
+		*out_type = V_ASN1_OBJECT;
+		return eckey_to_object(eckey, out_val);
+	}
+}
+
+static int
+eckey_from_params(int ptype, const void *pval, EC_KEY **out_eckey)
+{
+	*out_eckey = NULL;
+
+	if (ptype == V_ASN1_SEQUENCE)
+		return eckey_from_explicit_params(pval, out_eckey);
+	if (ptype == V_ASN1_OBJECT)
+		return eckey_from_object(pval, out_eckey);
+
+	ECerror(EC_R_DECODE_ERROR);
+	return 0;
+}
+
+static int
+eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
+{
+	EC_KEY *eckey = pkey->pkey.ec;
+	int ptype = V_ASN1_UNDEF;
+	void *pval = NULL;
+	ASN1_OBJECT *aobj;
+	unsigned char *key = NULL;
+	int key_len = 0;
+	int ret = 0;
+
+	if (!eckey_to_params(eckey, &ptype, &pval)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if ((key_len = i2o_ECPublicKey(eckey, &key)) <= 0) {
+		key_len = 0;
+		goto err;
+	}
+	if ((aobj = OBJ_nid2obj(EVP_PKEY_EC)) == NULL)
+		goto err;
+	if (!X509_PUBKEY_set0_param(pk, aobj, ptype, pval, key, key_len))
+		goto err;
+	pval = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	eckey_param_free(ptype, pval);
+	freezero(key, key_len);
+
+	return ret;
+}
+
+static int
+eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+{
+	const unsigned char *p = NULL;
+	const void *pval;
+	int ptype, pklen;
+	EC_KEY *eckey = NULL;
+	X509_ALGOR *palg;
+	int ret = 0;
+
+	if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+		goto err;
+	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
+
+	if (!eckey_from_params(ptype, pval, &eckey))
+		goto err;
+
+	if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
+		ECerror(EC_R_DECODE_ERROR);
+		goto err;
+	}
+	if (!EVP_PKEY_assign_EC_KEY(pkey, eckey))
+		goto err;
+	eckey = NULL;
+
+	ret = 1;
+
+ err:
+	EC_KEY_free(eckey);
+
+	return ret;
+}
+
+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);
+	const EC_POINT *pb = EC_KEY_get0_public_key(b->pkey.ec);
+	int r;
+
+	r = EC_POINT_cmp(group, pa, pb, NULL);
+	if (r == 0)
+		return 1;
+	if (r == 1)
+		return 0;
+	return -2;
+}
+
+static int
+eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
+{
+	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);
+
+	if (!eckey_from_params(ptype, pval, &eckey))
+		goto ecliberr;
+
+	/* We have parameters now set private key */
+	if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+		ECerror(EC_R_DECODE_ERROR);
+		goto ecerr;
+	}
+	/* calculate public key (if necessary) */
+	if (EC_KEY_get0_public_key(eckey) == NULL) {
+		const BIGNUM *priv_key;
+		const EC_GROUP *group;
+		EC_POINT *pub_key;
+		/*
+		 * the public key was not included in the SEC1 private key =>
+		 * calculate the public key
+		 */
+		group = EC_KEY_get0_group(eckey);
+		pub_key = EC_POINT_new(group);
+		if (pub_key == NULL) {
+			ECerror(ERR_R_EC_LIB);
+			goto ecliberr;
+		}
+		if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
+			EC_POINT_free(pub_key);
+			ECerror(ERR_R_EC_LIB);
+			goto ecliberr;
+		}
+		priv_key = EC_KEY_get0_private_key(eckey);
+		if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
+			EC_POINT_free(pub_key);
+			ECerror(ERR_R_EC_LIB);
+			goto ecliberr;
+		}
+		if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
+			EC_POINT_free(pub_key);
+			ECerror(ERR_R_EC_LIB);
+			goto ecliberr;
+		}
+		EC_POINT_free(pub_key);
+	}
+	EVP_PKEY_assign_EC_KEY(pkey, eckey);
+	return 1;
+
+ ecliberr:
+	ECerror(ERR_R_EC_LIB);
+ ecerr:
+	if (eckey)
+		EC_KEY_free(eckey);
+	return 0;
+}
+
+static int
+eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
+{
+	EC_KEY *eckey = pkey->pkey.ec;
+	void *pval = NULL;
+	int ptype = V_ASN1_UNDEF;
+	ASN1_OBJECT *aobj;
+	unsigned char *key = NULL;
+	int key_len = 0;
+	unsigned int flags;
+	int ret = 0;
+
+	flags = EC_KEY_get_enc_flags(eckey);
+
+	if (!eckey_to_params(eckey, &ptype, &pval)) {
+		ECerror(EC_R_DECODE_ERROR);
+		goto err;
+	}
+
+	/* PKCS#11 12.11: don't include parameters in the SEC1 private key. */
+	EC_KEY_set_enc_flags(eckey, flags | EC_PKEY_NO_PARAMETERS);
+
+	if ((key_len = i2d_ECPrivateKey(eckey, &key)) <= 0) {
+		ECerror(ERR_R_EC_LIB);
+		key_len = 0;
+		goto err;
+	}
+	if ((aobj = OBJ_nid2obj(NID_X9_62_id_ecPublicKey)) == NULL)
+		goto err;
+	if (!PKCS8_pkey_set0(p8, aobj, 0, ptype, pval, key, key_len))
+		goto err;
+	pval = NULL;
+	key = NULL;
+	key_len = 0;
+
+	ret = 1;
+
+ err:
+	eckey_param_free(ptype, pval);
+	freezero(key, key_len);
+
+	EC_KEY_set_enc_flags(eckey, flags);
+
+	return ret;
+}
+
+static int
+ec_size(const EVP_PKEY *pkey)
+{
+	return ECDSA_size(pkey->pkey.ec);
+}
+
+static int
+ec_bits(const EVP_PKEY *pkey)
+{
+	const EC_GROUP *group;
+
+	if ((group = EC_KEY_get0_group(pkey->pkey.ec)) == NULL)
+		return 0;
+
+	return EC_GROUP_order_bits(group);
+}
+
+static int
+ec_security_bits(const EVP_PKEY *pkey)
+{
+	int ecbits = ec_bits(pkey);
+
+	if (ecbits >= 512)
+		return 256;
+	if (ecbits >= 384)
+		return 192;
+	if (ecbits >= 256)
+		return 128;
+	if (ecbits >= 224)
+		return 112;
+	if (ecbits >= 160)
+		return 80;
+
+	return ecbits / 2;
+}
+
+static int
+ec_missing_parameters(const EVP_PKEY *pkey)
+{
+	if (EC_KEY_get0_group(pkey->pkey.ec) == NULL)
+		return 1;
+	return 0;
+}
+
+static int
+ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+{
+	return EC_KEY_set_group(to->pkey.ec, EC_KEY_get0_group(from->pkey.ec));
+}
+
+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);
+	const EC_GROUP *group_b = EC_KEY_get0_group(b->pkey.ec);
+
+	if (EC_GROUP_cmp(group_a, group_b, NULL))
+		return 0;
+	else
+		return 1;
+}
+
+static void
+ec_free(EVP_PKEY *pkey)
+{
+	EC_KEY_free(pkey->pkey.ec);
+}
+
+static int
+do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype)
+{
+	const char *ecstr;
+	int ret = 0, reason = ERR_R_BIO_LIB;
+	BIGNUM *pub_key = NULL;
+	BN_CTX *ctx = NULL;
+	const EC_GROUP *group;
+	const EC_POINT *public_key;
+	const BIGNUM *priv_key;
+
+	if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
+		reason = ERR_R_PASSED_NULL_PARAMETER;
+		goto err;
+	}
+	ctx = BN_CTX_new();
+	if (ctx == NULL) {
+		reason = ERR_R_MALLOC_FAILURE;
+		goto err;
+	}
+	if (ktype > 0) {
+		public_key = EC_KEY_get0_public_key(x);
+		if (public_key != NULL) {
+			if ((pub_key = EC_POINT_point2bn(group, public_key,
+			    EC_KEY_get_conv_form(x), NULL, ctx)) == NULL) {
+				reason = ERR_R_EC_LIB;
+				goto err;
+			}
+		}
+	}
+	if (ktype == 2) {
+		priv_key = EC_KEY_get0_private_key(x);
+	} else
+		priv_key = NULL;
+
+	if (ktype == 2)
+		ecstr = "Private-Key";
+	else if (ktype == 1)
+		ecstr = "Public-Key";
+	else
+		ecstr = "ECDSA-Parameters";
+
+	if (!BIO_indent(bp, off, 128))
+		goto err;
+	if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
+	    EC_GROUP_order_bits(group)) <= 0)
+		goto err;
+
+	if (!bn_printf(bp, priv_key, off, "priv:"))
+		goto err;
+	if (!bn_printf(bp, pub_key, off, "pub: "))
+		goto err;
+	if (!ECPKParameters_print(bp, group, off))
+		goto err;
+
+	ret = 1;
+
+ err:
+	if (!ret)
+		ECerror(reason);
+	BN_free(pub_key);
+	BN_CTX_free(ctx);
+
+	return (ret);
+}
+
+static int
+eckey_param_decode(EVP_PKEY *pkey,
+    const unsigned char **pder, int derlen)
+{
+	EC_KEY *eckey;
+	if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
+		ECerror(ERR_R_EC_LIB);
+		return 0;
+	}
+	EVP_PKEY_assign_EC_KEY(pkey, eckey);
+	return 1;
+}
+
+static int
+eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
+{
+	return i2d_ECParameters(pkey->pkey.ec, pder);
+}
+
+static int
+eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+    ASN1_PCTX *ctx)
+{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+}
+
+static int
+eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+    ASN1_PCTX *ctx)
+{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+}
+
+
+static int
+eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+    ASN1_PCTX *ctx)
+{
+	return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+}
+
+static int
+old_ec_priv_decode(EVP_PKEY *pkey,
+    const unsigned char **pder, int derlen)
+{
+	EC_KEY *ec;
+	if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
+		ECerror(EC_R_DECODE_ERROR);
+		return 0;
+	}
+	EVP_PKEY_assign_EC_KEY(pkey, ec);
+	return 1;
+}
+
+static int
+old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+{
+	return i2d_ECPrivateKey(pkey->pkey.ec, 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) {
+			X509_ALGOR *alg1, *alg2;
+			int snid, hnid;
+
+			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 == 0)
+			return ecdh_cms_encrypt(arg2);
+		else if (arg1 == 1)
+			return ecdh_cms_decrypt(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:
+		*(int *) arg2 = NID_sha1;
+		return 2;
+
+	default:
+		return -2;
+
+	}
+
+}
+
+static int
+ec_pkey_check(const EVP_PKEY *pkey)
+{
+	EC_KEY *eckey = pkey->pkey.ec;
+
+	if (eckey->priv_key == NULL) {
+		ECerror(EC_R_MISSING_PRIVATE_KEY);
+		return 0;
+	}
+
+	return EC_KEY_check_key(eckey);
+}
+
+static int
+ec_pkey_public_check(const EVP_PKEY *pkey)
+{
+	EC_KEY *eckey = pkey->pkey.ec;
+
+	/* This also checks the private key, but oh, well... */
+	return EC_KEY_check_key(eckey);
+}
+
+static int
+ec_pkey_param_check(const EVP_PKEY *pkey)
+{
+	EC_KEY *eckey = pkey->pkey.ec;
+
+	if (eckey->group == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		return 0;
+	}
+
+	return EC_GROUP_check(eckey->group, NULL);
+}
+
+#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 {
+		if (!eckey_from_params(atype, aval, &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)
+{
+	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;
+	int rv = 0;
+
+	if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
+		return 0;
+
+	if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
+		ECerror(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 <= 0)
+		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);
+	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)) {
+			ECerror(EC_R_PEER_KEY_ERROR);
+			return 0;
+		}
+	}
+
+	/* Set ECDH derivation parameters and initialise unwrap context */
+	if (!ecdh_cms_set_shared_info(pctx, ri)) {
+		ECerror(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 ecdh_nid, kdf_type, kdf_nid, wrap_nid;
+	const EVP_MD *kdf_md;
+	int rv = 0;
+
+	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;
+		unsigned char *p;
+
+		/* Set the key */
+		penclen = i2o_ECPublicKey(eckey, NULL);
+		if (penclen <= 0)
+			goto err;
+		penc = 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);
+		if (!asn1_abs_set_unused_bits(pubkey, 0))
+			goto err;
+		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 <= 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:
+	free(penc);
+	X509_ALGOR_free(wrap_alg);
+	return rv;
+}
+
+#endif
+
+const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
+	.pkey_id = EVP_PKEY_EC,
+	.pkey_base_id = EVP_PKEY_EC,
+
+	.pem_str = "EC",
+	.info = "OpenSSL EC algorithm",
+
+	.pub_decode = eckey_pub_decode,
+	.pub_encode = eckey_pub_encode,
+	.pub_cmp = eckey_pub_cmp,
+	.pub_print = eckey_pub_print,
+
+	.priv_decode = eckey_priv_decode,
+	.priv_encode = eckey_priv_encode,
+	.priv_print = eckey_priv_print,
+
+	.pkey_size = ec_size,
+	.pkey_bits = ec_bits,
+	.pkey_security_bits = ec_security_bits,
+
+	.param_decode = eckey_param_decode,
+	.param_encode = eckey_param_encode,
+	.param_missing = ec_missing_parameters,
+	.param_copy = ec_copy_parameters,
+	.param_cmp = ec_cmp_parameters,
+	.param_print = eckey_param_print,
+
+	.pkey_free = ec_free,
+	.pkey_ctrl = ec_pkey_ctrl,
+	.old_priv_decode = old_ec_priv_decode,
+	.old_priv_encode = old_ec_priv_encode,
+
+	.pkey_check = ec_pkey_check,
+	.pkey_public_check = ec_pkey_public_check,
+	.pkey_param_check = ec_pkey_param_check,
+};
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
new file mode 100644
index 0000000..683ca17
--- /dev/null
+++ b/crypto/ec/ec_asn1.c
@@ -0,0 +1,1411 @@
+/* $OpenBSD: ec_asn1.c,v 1.48 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "ec_local.h"
+
+int
+EC_GROUP_get_basis_type(const EC_GROUP *group)
+{
+	return 0;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_basis_type);
+
+/* some structures needed for the asn1 encoding */
+typedef struct x9_62_pentanomial_st {
+	long k1;
+	long k2;
+	long k3;
+} X9_62_PENTANOMIAL;
+
+typedef struct x9_62_characteristic_two_st {
+	long m;
+	ASN1_OBJECT *type;
+	union {
+		char *ptr;
+		/* NID_X9_62_onBasis */
+		ASN1_NULL *onBasis;
+		/* NID_X9_62_tpBasis */
+		ASN1_INTEGER *tpBasis;
+		/* NID_X9_62_ppBasis */
+		X9_62_PENTANOMIAL *ppBasis;
+		/* anything else */
+		ASN1_TYPE *other;
+	} p;
+} X9_62_CHARACTERISTIC_TWO;
+
+typedef struct x9_62_fieldid_st {
+	ASN1_OBJECT *fieldType;
+	union {
+		char *ptr;
+		/* NID_X9_62_prime_field */
+		ASN1_INTEGER *prime;
+		/* NID_X9_62_characteristic_two_field */
+		X9_62_CHARACTERISTIC_TWO *char_two;
+		/* anything else */
+		ASN1_TYPE *other;
+	} p;
+} X9_62_FIELDID;
+
+typedef struct x9_62_curve_st {
+	ASN1_OCTET_STRING *a;
+	ASN1_OCTET_STRING *b;
+	ASN1_BIT_STRING *seed;
+} X9_62_CURVE;
+
+typedef struct ec_parameters_st {
+	long version;
+	X9_62_FIELDID *fieldID;
+	X9_62_CURVE *curve;
+	ASN1_OCTET_STRING *base;
+	ASN1_INTEGER *order;
+	ASN1_INTEGER *cofactor;
+} ECPARAMETERS;
+
+struct ecpk_parameters_st {
+	int type;
+	union {
+		ASN1_OBJECT *named_curve;
+		ECPARAMETERS *parameters;
+		ASN1_NULL *implicitlyCA;
+	} value;
+} /* ECPKPARAMETERS */ ;
+
+/* SEC1 ECPrivateKey */
+typedef struct ec_privatekey_st {
+	long version;
+	ASN1_OCTET_STRING *privateKey;
+	ECPKPARAMETERS *parameters;
+	ASN1_BIT_STRING *publicKey;
+} EC_PRIVATEKEY;
+
+/* the OpenSSL ASN.1 definitions */
+static const ASN1_TEMPLATE X9_62_PENTANOMIAL_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_PENTANOMIAL, k1),
+		.field_name = "k1",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_PENTANOMIAL, k2),
+		.field_name = "k2",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_PENTANOMIAL, k3),
+		.field_name = "k3",
+		.item = &LONG_it,
+	},
+};
+
+const ASN1_ITEM X9_62_PENTANOMIAL_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X9_62_PENTANOMIAL_seq_tt,
+	.tcount = sizeof(X9_62_PENTANOMIAL_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(X9_62_PENTANOMIAL),
+	.sname = "X9_62_PENTANOMIAL",
+};
+
+X9_62_PENTANOMIAL *X9_62_PENTANOMIAL_new(void);
+void X9_62_PENTANOMIAL_free(X9_62_PENTANOMIAL *a);
+
+X9_62_PENTANOMIAL *
+X9_62_PENTANOMIAL_new(void)
+{
+	return (X9_62_PENTANOMIAL*)ASN1_item_new(&X9_62_PENTANOMIAL_it);
+}
+
+void
+X9_62_PENTANOMIAL_free(X9_62_PENTANOMIAL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X9_62_PENTANOMIAL_it);
+}
+
+static const ASN1_TEMPLATE char_two_def_tt = {
+	.flags = 0,
+	.tag = 0,
+	.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.other),
+	.field_name = "p.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE X9_62_CHARACTERISTIC_TWO_adbtbl[] = {
+	{
+		.value = NID_X9_62_onBasis,
+		.tt = {
+			.flags = 0,
+			.tag = 0,
+			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.onBasis),
+			.field_name = "p.onBasis",
+			.item = &ASN1_NULL_it,
+		},
+	},
+	{
+		.value = NID_X9_62_tpBasis,
+		.tt = {
+			.flags = 0,
+			.tag = 0,
+			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.tpBasis),
+			.field_name = "p.tpBasis",
+			.item = &ASN1_INTEGER_it,
+		},
+	},
+	{
+		.value = NID_X9_62_ppBasis,
+		.tt = {
+			.flags = 0,
+			.tag = 0,
+			.offset = offsetof(X9_62_CHARACTERISTIC_TWO, p.ppBasis),
+			.field_name = "p.ppBasis",
+			.item = &X9_62_PENTANOMIAL_it,
+		},
+
+	},
+};
+
+static const ASN1_ADB X9_62_CHARACTERISTIC_TWO_adb = {
+	.flags = 0,
+	.offset = offsetof(X9_62_CHARACTERISTIC_TWO, type),
+	.tbl = X9_62_CHARACTERISTIC_TWO_adbtbl,
+	.tblcount = sizeof(X9_62_CHARACTERISTIC_TWO_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &char_two_def_tt,
+	.null_tt = NULL,
+};
+
+static const ASN1_TEMPLATE X9_62_CHARACTERISTIC_TWO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_CHARACTERISTIC_TWO, m),
+		.field_name = "m",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_CHARACTERISTIC_TWO, type),
+		.field_name = "type",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "X9_62_CHARACTERISTIC_TWO",
+		.item = (const ASN1_ITEM *)&X9_62_CHARACTERISTIC_TWO_adb,
+	},
+};
+
+const ASN1_ITEM X9_62_CHARACTERISTIC_TWO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X9_62_CHARACTERISTIC_TWO_seq_tt,
+	.tcount = sizeof(X9_62_CHARACTERISTIC_TWO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(X9_62_CHARACTERISTIC_TWO),
+	.sname = "X9_62_CHARACTERISTIC_TWO",
+};
+
+X9_62_CHARACTERISTIC_TWO *X9_62_CHARACTERISTIC_TWO_new(void);
+void X9_62_CHARACTERISTIC_TWO_free(X9_62_CHARACTERISTIC_TWO *a);
+
+X9_62_CHARACTERISTIC_TWO *
+X9_62_CHARACTERISTIC_TWO_new(void)
+{
+	return (X9_62_CHARACTERISTIC_TWO*)ASN1_item_new(&X9_62_CHARACTERISTIC_TWO_it);
+}
+
+void
+X9_62_CHARACTERISTIC_TWO_free(X9_62_CHARACTERISTIC_TWO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &X9_62_CHARACTERISTIC_TWO_it);
+}
+
+static const ASN1_TEMPLATE fieldID_def_tt = {
+	.flags = 0,
+	.tag = 0,
+	.offset = offsetof(X9_62_FIELDID, p.other),
+	.field_name = "p.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE X9_62_FIELDID_adbtbl[] = {
+	{
+		.value = NID_X9_62_prime_field,
+		.tt = {
+			.flags = 0,
+			.tag = 0,
+			.offset = offsetof(X9_62_FIELDID, p.prime),
+			.field_name = "p.prime",
+			.item = &ASN1_INTEGER_it,
+		},
+	},
+	{
+		.value = NID_X9_62_characteristic_two_field,
+		.tt = {
+			.flags = 0,
+			.tag = 0,
+			.offset = offsetof(X9_62_FIELDID, p.char_two),
+			.field_name = "p.char_two",
+			.item = &X9_62_CHARACTERISTIC_TWO_it,
+		},
+	},
+};
+
+static const ASN1_ADB X9_62_FIELDID_adb = {
+	.flags = 0,
+	.offset = offsetof(X9_62_FIELDID, fieldType),
+	.tbl = X9_62_FIELDID_adbtbl,
+	.tblcount = sizeof(X9_62_FIELDID_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &fieldID_def_tt,
+	.null_tt = NULL,
+};
+
+static const ASN1_TEMPLATE X9_62_FIELDID_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_FIELDID, fieldType),
+		.field_name = "fieldType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "X9_62_FIELDID",
+		.item = (const ASN1_ITEM *)&X9_62_FIELDID_adb,
+	},
+};
+
+const ASN1_ITEM X9_62_FIELDID_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X9_62_FIELDID_seq_tt,
+	.tcount = sizeof(X9_62_FIELDID_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(X9_62_FIELDID),
+	.sname = "X9_62_FIELDID",
+};
+
+static const ASN1_TEMPLATE X9_62_CURVE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_CURVE, a),
+		.field_name = "a",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(X9_62_CURVE, b),
+		.field_name = "b",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(X9_62_CURVE, seed),
+		.field_name = "seed",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM X9_62_CURVE_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = X9_62_CURVE_seq_tt,
+	.tcount = sizeof(X9_62_CURVE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(X9_62_CURVE),
+	.sname = "X9_62_CURVE",
+};
+
+static const ASN1_TEMPLATE ECPARAMETERS_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, fieldID),
+		.field_name = "fieldID",
+		.item = &X9_62_FIELDID_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, curve),
+		.field_name = "curve",
+		.item = &X9_62_CURVE_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, base),
+		.field_name = "base",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, order),
+		.field_name = "order",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ECPARAMETERS, cofactor),
+		.field_name = "cofactor",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM ECPARAMETERS_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ECPARAMETERS_seq_tt,
+	.tcount = sizeof(ECPARAMETERS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ECPARAMETERS),
+	.sname = "ECPARAMETERS",
+};
+
+ECPARAMETERS *ECPARAMETERS_new(void);
+void ECPARAMETERS_free(ECPARAMETERS *a);
+
+ECPARAMETERS *
+ECPARAMETERS_new(void)
+{
+	return (ECPARAMETERS*)ASN1_item_new(&ECPARAMETERS_it);
+}
+
+void
+ECPARAMETERS_free(ECPARAMETERS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ECPARAMETERS_it);
+}
+
+static const ASN1_TEMPLATE ECPKPARAMETERS_ch_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPKPARAMETERS, value.named_curve),
+		.field_name = "value.named_curve",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPKPARAMETERS, value.parameters),
+		.field_name = "value.parameters",
+		.item = &ECPARAMETERS_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECPKPARAMETERS, value.implicitlyCA),
+		.field_name = "value.implicitlyCA",
+		.item = &ASN1_NULL_it,
+	},
+};
+
+const ASN1_ITEM ECPKPARAMETERS_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(ECPKPARAMETERS, type),
+	.templates = ECPKPARAMETERS_ch_tt,
+	.tcount = sizeof(ECPKPARAMETERS_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ECPKPARAMETERS),
+	.sname = "ECPKPARAMETERS",
+};
+
+ECPKPARAMETERS *ECPKPARAMETERS_new(void);
+void ECPKPARAMETERS_free(ECPKPARAMETERS *a);
+ECPKPARAMETERS *d2i_ECPKPARAMETERS(ECPKPARAMETERS **a, const unsigned char **in, long len);
+int i2d_ECPKPARAMETERS(const ECPKPARAMETERS *a, unsigned char **out);
+
+ECPKPARAMETERS *
+d2i_ECPKPARAMETERS(ECPKPARAMETERS **a, const unsigned char **in, long len)
+{
+	return (ECPKPARAMETERS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ECPKPARAMETERS_it);
+}
+
+int
+i2d_ECPKPARAMETERS(const ECPKPARAMETERS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ECPKPARAMETERS_it);
+}
+
+ECPKPARAMETERS *
+ECPKPARAMETERS_new(void)
+{
+	return (ECPKPARAMETERS *)ASN1_item_new(&ECPKPARAMETERS_it);
+}
+
+void
+ECPKPARAMETERS_free(ECPKPARAMETERS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ECPKPARAMETERS_it);
+}
+
+static const ASN1_TEMPLATE EC_PRIVATEKEY_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(EC_PRIVATEKEY, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(EC_PRIVATEKEY, privateKey),
+		.field_name = "privateKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(EC_PRIVATEKEY, parameters),
+		.field_name = "parameters",
+		.item = &ECPKPARAMETERS_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(EC_PRIVATEKEY, publicKey),
+		.field_name = "publicKey",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM EC_PRIVATEKEY_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = EC_PRIVATEKEY_seq_tt,
+	.tcount = sizeof(EC_PRIVATEKEY_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(EC_PRIVATEKEY),
+	.sname = "EC_PRIVATEKEY",
+};
+
+EC_PRIVATEKEY *EC_PRIVATEKEY_new(void);
+void EC_PRIVATEKEY_free(EC_PRIVATEKEY *a);
+EC_PRIVATEKEY *d2i_EC_PRIVATEKEY(EC_PRIVATEKEY **a, const unsigned char **in, long len);
+int i2d_EC_PRIVATEKEY(const EC_PRIVATEKEY *a, unsigned char **out);
+
+EC_PRIVATEKEY *
+d2i_EC_PRIVATEKEY(EC_PRIVATEKEY **a, const unsigned char **in, long len)
+{
+	return (EC_PRIVATEKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &EC_PRIVATEKEY_it);
+}
+
+int
+i2d_EC_PRIVATEKEY(const EC_PRIVATEKEY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &EC_PRIVATEKEY_it);
+}
+
+EC_PRIVATEKEY *
+EC_PRIVATEKEY_new(void)
+{
+	return (EC_PRIVATEKEY *)ASN1_item_new(&EC_PRIVATEKEY_it);
+}
+
+void
+EC_PRIVATEKEY_free(EC_PRIVATEKEY *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &EC_PRIVATEKEY_it);
+}
+
+/* some declarations of internal function */
+
+/* ec_asn1_group2fieldid() sets the values in a X9_62_FIELDID object */
+static int ec_asn1_group2fieldid(const EC_GROUP *, X9_62_FIELDID *);
+/* ec_asn1_group2curve() sets the values in a X9_62_CURVE object */
+static int ec_asn1_group2curve(const EC_GROUP *, X9_62_CURVE *);
+/* ec_asn1_parameters2group() creates a EC_GROUP object from a
+ * ECPARAMETERS object */
+static EC_GROUP *ec_asn1_parameters2group(const ECPARAMETERS *);
+/* ec_asn1_group2parameters() creates a ECPARAMETERS object from a
+ * EC_GROUP object */
+static ECPARAMETERS *ec_asn1_group2parameters(const EC_GROUP *, ECPARAMETERS *);
+/* ec_asn1_pkparameters2group() creates a EC_GROUP object from a
+ * ECPKPARAMETERS object */
+static EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *);
+/* ec_asn1_group2pkparameters() creates a ECPKPARAMETERS object from a
+ * EC_GROUP object */
+static ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *,
+    ECPKPARAMETERS *);
+
+/* the function definitions */
+
+static int
+ec_asn1_group2fieldid(const EC_GROUP *group, X9_62_FIELDID *field)
+{
+	int ok = 0, nid;
+	BIGNUM *tmp = NULL;
+
+	if (group == NULL || field == NULL)
+		return 0;
+
+	/* clear the old values (if necessary) */
+	if (field->fieldType != NULL)
+		ASN1_OBJECT_free(field->fieldType);
+	if (field->p.other != NULL)
+		ASN1_TYPE_free(field->p.other);
+
+	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+	/* set OID for the field */
+	if ((field->fieldType = OBJ_nid2obj(nid)) == NULL) {
+		ECerror(ERR_R_OBJ_LIB);
+		goto err;
+	}
+	if (nid == NID_X9_62_prime_field) {
+		if ((tmp = BN_new()) == NULL) {
+			ECerror(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)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		/* set the prime number */
+		field->p.prime = BN_to_ASN1_INTEGER(tmp, NULL);
+		if (field->p.prime == NULL) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+	} else {
+		ECerror(EC_R_GF2M_NOT_SUPPORTED);
+		goto err;
+	}
+
+	ok = 1;
+
+ err:
+	BN_free(tmp);
+	return (ok);
+}
+
+static int
+ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
+{
+	BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
+	unsigned char *buffer_1 = NULL, *buffer_2 = NULL, *a_buf = NULL,
+	*b_buf = NULL;
+	size_t len_1, len_2;
+	unsigned char char_zero = 0;
+	int ok = 0;
+
+	if (!group || !curve || !curve->a || !curve->b)
+		return 0;
+
+	if ((tmp_1 = BN_new()) == NULL || (tmp_2 = BN_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* get a and b */
+	if (!EC_GROUP_get_curve(group, NULL, tmp_1, tmp_2, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	len_1 = (size_t) BN_num_bytes(tmp_1);
+	len_2 = (size_t) BN_num_bytes(tmp_2);
+
+	if (len_1 == 0) {
+		/* len_1 == 0 => a == 0 */
+		a_buf = &char_zero;
+		len_1 = 1;
+	} else {
+		if ((buffer_1 = malloc(len_1)) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
+			ECerror(ERR_R_BN_LIB);
+			goto err;
+		}
+		a_buf = buffer_1;
+	}
+
+	if (len_2 == 0) {
+		/* len_2 == 0 => b == 0 */
+		b_buf = &char_zero;
+		len_2 = 1;
+	} else {
+		if ((buffer_2 = malloc(len_2)) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
+			ECerror(ERR_R_BN_LIB);
+			goto err;
+		}
+		b_buf = buffer_2;
+	}
+
+	/* set a and b */
+	if (!ASN1_STRING_set(curve->a, a_buf, len_1) ||
+	    !ASN1_STRING_set(curve->b, b_buf, len_2)) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+
+	ASN1_BIT_STRING_free(curve->seed);
+	curve->seed = NULL;
+
+	/* set the seed (optional) */
+	if (group->seed != NULL) {
+		if ((curve->seed = ASN1_BIT_STRING_new()) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!ASN1_BIT_STRING_set(curve->seed, group->seed,
+			(int) group->seed_len)) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		if (!asn1_abs_set_unused_bits(curve->seed, 0)) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+	}
+
+	ok = 1;
+
+ err:
+	free(buffer_1);
+	free(buffer_2);
+	BN_free(tmp_1);
+	BN_free(tmp_2);
+	return (ok);
+}
+
+static ECPARAMETERS *
+ec_asn1_group2parameters(const EC_GROUP *group, ECPARAMETERS *param)
+{
+	int ok = 0;
+	size_t len = 0;
+	ECPARAMETERS *ret = NULL;
+	BIGNUM *tmp = NULL;
+	unsigned char *buffer = NULL;
+	const EC_POINT *point = NULL;
+	point_conversion_form_t form;
+
+	if ((tmp = BN_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (param == NULL) {
+		if ((ret = ECPARAMETERS_new()) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	} else
+		ret = param;
+
+	/* set the version (always one) */
+	ret->version = (long) 0x1;
+
+	/* set the fieldID */
+	if (!ec_asn1_group2fieldid(group, ret->fieldID)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	/* set the curve */
+	if (!ec_asn1_group2curve(group, ret->curve)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	/* set the base point */
+	if ((point = EC_GROUP_get0_generator(group)) == NULL) {
+		ECerror(EC_R_UNDEFINED_GENERATOR);
+		goto err;
+	}
+	form = EC_GROUP_get_point_conversion_form(group);
+
+	len = EC_POINT_point2oct(group, point, form, NULL, len, NULL);
+	if (len == 0) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if ((buffer = malloc(len)) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!EC_POINT_point2oct(group, point, form, buffer, len, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	/* set the order */
+	if (!EC_GROUP_get_order(group, tmp, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	ret->order = BN_to_ASN1_INTEGER(tmp, ret->order);
+	if (ret->order == NULL) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	/* set the cofactor (optional) */
+	if (EC_GROUP_get_cofactor(group, tmp, NULL)) {
+		ret->cofactor = BN_to_ASN1_INTEGER(tmp, ret->cofactor);
+		if (ret->cofactor == NULL) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+	}
+	ok = 1;
+
+ err:
+	if (!ok) {
+		if (ret && !param)
+			ECPARAMETERS_free(ret);
+		ret = NULL;
+	}
+	BN_free(tmp);
+	free(buffer);
+	return (ret);
+}
+
+ECPKPARAMETERS *
+ec_asn1_group2pkparameters(const EC_GROUP *group, ECPKPARAMETERS *params)
+{
+	int ok = 1, tmp;
+	ECPKPARAMETERS *ret = params;
+
+	if (ret == NULL) {
+		if ((ret = ECPKPARAMETERS_new()) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+	} else {
+		if (ret->type == 0 && ret->value.named_curve)
+			ASN1_OBJECT_free(ret->value.named_curve);
+		else if (ret->type == 1 && ret->value.parameters)
+			ECPARAMETERS_free(ret->value.parameters);
+	}
+
+	if (EC_GROUP_get_asn1_flag(group)) {
+		/*
+		 * use the asn1 OID to describe the elliptic curve
+		 * parameters
+		 */
+		tmp = EC_GROUP_get_curve_name(group);
+		if (tmp) {
+			ret->type = 0;
+			if ((ret->value.named_curve = OBJ_nid2obj(tmp)) == NULL)
+				ok = 0;
+		} else
+			/* we don't know the group => ERROR */
+			ok = 0;
+	} else {
+		/* use the ECPARAMETERS structure */
+		ret->type = 1;
+		if ((ret->value.parameters = ec_asn1_group2parameters(group,
+		    NULL)) == NULL)
+			ok = 0;
+	}
+
+	if (!ok) {
+		ECPKPARAMETERS_free(ret);
+		return NULL;
+	}
+	return ret;
+}
+
+static EC_GROUP *
+ec_asn1_parameters2group(const ECPARAMETERS *params)
+{
+	int ok = 0, tmp;
+	EC_GROUP *ret = NULL;
+	BIGNUM *p = NULL, *a = NULL, *b = NULL;
+	EC_POINT *point = NULL;
+	long field_bits;
+
+	if (!params->fieldID || !params->fieldID->fieldType ||
+	    !params->fieldID->p.ptr) {
+		ECerror(EC_R_ASN1_ERROR);
+		goto err;
+	}
+	/* now extract the curve parameters a and b */
+	if (!params->curve || !params->curve->a ||
+	    !params->curve->a->data || !params->curve->b ||
+	    !params->curve->b->data) {
+		ECerror(EC_R_ASN1_ERROR);
+		goto err;
+	}
+	a = BN_bin2bn(params->curve->a->data, params->curve->a->length, NULL);
+	if (a == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	b = BN_bin2bn(params->curve->b->data, params->curve->b->length, NULL);
+	if (b == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	/* get the field parameters */
+	tmp = OBJ_obj2nid(params->fieldID->fieldType);
+	if (tmp == NID_X9_62_characteristic_two_field) {
+		ECerror(EC_R_GF2M_NOT_SUPPORTED);
+		goto err;
+	} 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) {
+			ECerror(EC_R_ASN1_ERROR);
+			goto err;
+		}
+		p = ASN1_INTEGER_to_BN(params->fieldID->p.prime, NULL);
+		if (p == NULL) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		if (BN_is_negative(p) || BN_is_zero(p)) {
+			ECerror(EC_R_INVALID_FIELD);
+			goto err;
+		}
+		field_bits = BN_num_bits(p);
+		if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
+			ECerror(EC_R_FIELD_TOO_LARGE);
+			goto err;
+		}
+		/* create the EC_GROUP structure */
+		ret = EC_GROUP_new_curve_GFp(p, a, b, NULL);
+	} else {
+		ECerror(EC_R_INVALID_FIELD);
+		goto err;
+	}
+
+	if (ret == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	/* extract seed (optional) */
+	if (params->curve->seed != NULL) {
+		free(ret->seed);
+		if (!(ret->seed = malloc(params->curve->seed->length))) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		memcpy(ret->seed, params->curve->seed->data,
+		    params->curve->seed->length);
+		ret->seed_len = params->curve->seed->length;
+	}
+	if (!params->order || !params->base || !params->base->data) {
+		ECerror(EC_R_ASN1_ERROR);
+		goto err;
+	}
+	if ((point = EC_POINT_new(ret)) == NULL)
+		goto err;
+
+	/* set the point conversion form */
+	EC_GROUP_set_point_conversion_form(ret, (point_conversion_form_t)
+	    (params->base->data[0] & ~0x01));
+
+	/* extract the ec point */
+	if (!EC_POINT_oct2point(ret, point, params->base->data,
+		params->base->length, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	/* extract the order */
+	if ((a = ASN1_INTEGER_to_BN(params->order, a)) == NULL) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	if (BN_is_negative(a) || BN_is_zero(a)) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+	if (BN_num_bits(a) > (int) field_bits + 1) {	/* Hasse bound */
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+	/* extract the cofactor (optional) */
+	if (params->cofactor == NULL) {
+		BN_free(b);
+		b = NULL;
+	} else if ((b = ASN1_INTEGER_to_BN(params->cofactor, b)) == NULL) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	/* set the generator, order and cofactor (if present) */
+	if (!EC_GROUP_set_generator(ret, point, a, b)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	ok = 1;
+
+ err:
+	if (!ok) {
+		EC_GROUP_free(ret);
+		ret = NULL;
+	}
+	BN_free(p);
+	BN_free(a);
+	BN_free(b);
+	EC_POINT_free(point);
+	return (ret);
+}
+
+EC_GROUP *
+ec_asn1_pkparameters2group(const ECPKPARAMETERS *params)
+{
+	EC_GROUP *ret = NULL;
+	int tmp = 0;
+
+	if (params == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		return NULL;
+	}
+	if (params->type == 0) {/* the curve is given by an OID */
+		tmp = OBJ_obj2nid(params->value.named_curve);
+		if ((ret = EC_GROUP_new_by_curve_name(tmp)) == NULL) {
+			ECerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+			return NULL;
+		}
+		EC_GROUP_set_asn1_flag(ret, OPENSSL_EC_NAMED_CURVE);
+	} else if (params->type == 1) {	/* the parameters are given by a
+					 * ECPARAMETERS structure */
+		ret = ec_asn1_parameters2group(params->value.parameters);
+		if (!ret) {
+			ECerror(ERR_R_EC_LIB);
+			return NULL;
+		}
+		EC_GROUP_set_asn1_flag(ret, 0x0);
+	} else if (params->type == 2) {	/* implicitlyCA */
+		return NULL;
+	} else {
+		ECerror(EC_R_ASN1_ERROR);
+		return NULL;
+	}
+
+	return ret;
+}
+
+/* EC_GROUP <-> DER encoding of ECPKPARAMETERS */
+
+EC_GROUP *
+d2i_ECPKParameters(EC_GROUP **a, const unsigned char **in, long len)
+{
+	EC_GROUP *group = NULL;
+	ECPKPARAMETERS *params;
+
+	if ((params = d2i_ECPKPARAMETERS(NULL, in, len)) == NULL) {
+		ECerror(EC_R_D2I_ECPKPARAMETERS_FAILURE);
+		goto err;
+	}
+	if ((group = ec_asn1_pkparameters2group(params)) == NULL) {
+		ECerror(EC_R_PKPARAMETERS2GROUP_FAILURE);
+		goto err;
+	}
+
+	if (a != NULL) {
+		EC_GROUP_free(*a);
+		*a = group;
+	}
+
+ err:
+	ECPKPARAMETERS_free(params);
+	return (group);
+}
+LCRYPTO_ALIAS(d2i_ECPKParameters);
+
+int
+i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
+{
+	int ret = 0;
+	ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(a, NULL);
+	if (tmp == NULL) {
+		ECerror(EC_R_GROUP2PKPARAMETERS_FAILURE);
+		return 0;
+	}
+	if ((ret = i2d_ECPKPARAMETERS(tmp, out)) == 0) {
+		ECerror(EC_R_I2D_ECPKPARAMETERS_FAILURE);
+		ECPKPARAMETERS_free(tmp);
+		return 0;
+	}
+	ECPKPARAMETERS_free(tmp);
+	return (ret);
+}
+LCRYPTO_ALIAS(i2d_ECPKParameters);
+
+/* some EC_KEY functions */
+
+EC_KEY *
+d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
+{
+	EC_KEY *ret = NULL;
+	EC_PRIVATEKEY *priv_key = NULL;
+
+	if ((priv_key = d2i_EC_PRIVATEKEY(NULL, in, len)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		return NULL;
+	}
+	if (a == NULL || *a == NULL) {
+		if ((ret = EC_KEY_new()) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	} else
+		ret = *a;
+
+	if (priv_key->parameters) {
+		EC_GROUP_free(ret->group);
+		ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
+	}
+	if (ret->group == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	ret->version = priv_key->version;
+
+	if (priv_key->privateKey) {
+		ret->priv_key = BN_bin2bn(
+		    ASN1_STRING_data(priv_key->privateKey),
+		    ASN1_STRING_length(priv_key->privateKey),
+		    ret->priv_key);
+		if (ret->priv_key == NULL) {
+			ECerror(ERR_R_BN_LIB);
+			goto err;
+		}
+	} else {
+		ECerror(EC_R_MISSING_PRIVATE_KEY);
+		goto err;
+	}
+
+	if (ret->pub_key)
+		EC_POINT_free(ret->pub_key);
+	ret->pub_key = EC_POINT_new(ret->group);
+	if (ret->pub_key == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if (priv_key->publicKey) {
+		const unsigned char *pub_oct;
+		size_t pub_oct_len;
+
+		pub_oct = ASN1_STRING_data(priv_key->publicKey);
+		pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
+		if (pub_oct == NULL || pub_oct_len <= 0) {
+			ECerror(EC_R_BUFFER_TOO_SMALL);
+			goto err;
+		}
+
+		/* save the point conversion form */
+		ret->conv_form = (point_conversion_form_t) (pub_oct[0] & ~0x01);
+		if (!EC_POINT_oct2point(ret->group, ret->pub_key,
+			pub_oct, pub_oct_len, NULL)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+	} else {
+		if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key,
+			NULL, NULL, NULL)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		/* Remember the original private-key-only encoding. */
+		ret->enc_flag |= EC_PKEY_NO_PUBKEY;
+	}
+
+	EC_PRIVATEKEY_free(priv_key);
+	if (a != NULL)
+		*a = ret;
+	return (ret);
+
+ err:
+	if (a == NULL || *a != ret)
+		EC_KEY_free(ret);
+	if (priv_key)
+		EC_PRIVATEKEY_free(priv_key);
+
+	return (NULL);
+}
+LCRYPTO_ALIAS(d2i_ECPrivateKey);
+
+int
+i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
+{
+	int ret = 0, ok = 0;
+	unsigned char *buffer = NULL;
+	size_t buf_len = 0, tmp_len;
+	EC_PRIVATEKEY *priv_key = NULL;
+
+	if (a == NULL || a->group == NULL || a->priv_key == NULL ||
+	    (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key == NULL)) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+	if ((priv_key = EC_PRIVATEKEY_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	priv_key->version = a->version;
+
+	buf_len = (size_t) BN_num_bytes(a->priv_key);
+	buffer = malloc(buf_len);
+	if (buffer == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!BN_bn2bin(a->priv_key, buffer)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!ASN1_STRING_set(priv_key->privateKey, buffer, buf_len)) {
+		ECerror(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
+		if ((priv_key->parameters = ec_asn1_group2pkparameters(
+			    a->group, priv_key->parameters)) == NULL) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+	}
+	if (!(a->enc_flag & EC_PKEY_NO_PUBKEY) && a->pub_key != NULL) {
+		priv_key->publicKey = ASN1_BIT_STRING_new();
+		if (priv_key->publicKey == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
+		    a->conv_form, NULL, 0, NULL);
+
+		if (tmp_len > buf_len) {
+			unsigned char *tmp_buffer = realloc(buffer, tmp_len);
+			if (!tmp_buffer) {
+				ECerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			buffer = tmp_buffer;
+			buf_len = tmp_len;
+		}
+		if (!EC_POINT_point2oct(a->group, a->pub_key,
+			a->conv_form, buffer, buf_len, NULL)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		if (!ASN1_STRING_set(priv_key->publicKey, buffer, buf_len)) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+		if (!asn1_abs_set_unused_bits(priv_key->publicKey, 0)) {
+			ECerror(ERR_R_ASN1_LIB);
+			goto err;
+		}
+	}
+	if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	ok = 1;
+ err:
+	free(buffer);
+	if (priv_key)
+		EC_PRIVATEKEY_free(priv_key);
+	return (ok ? ret : 0);
+}
+LCRYPTO_ALIAS(i2d_ECPrivateKey);
+
+int
+i2d_ECParameters(EC_KEY *a, unsigned char **out)
+{
+	if (a == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	return i2d_ECPKParameters(a->group, out);
+}
+LCRYPTO_ALIAS(i2d_ECParameters);
+
+EC_KEY *
+d2i_ECParameters(EC_KEY **a, const unsigned char **in, long len)
+{
+	EC_KEY *ret;
+
+	if (in == NULL || *in == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+	}
+	if (a == NULL || *a == NULL) {
+		if ((ret = EC_KEY_new()) == NULL) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+	} else
+		ret = *a;
+
+	if (!d2i_ECPKParameters(&ret->group, in, len)) {
+		ECerror(ERR_R_EC_LIB);
+		if (a == NULL || *a != ret)
+			EC_KEY_free(ret);
+		return NULL;
+	}
+
+	if (a != NULL)
+		*a = ret;
+	return ret;
+}
+LCRYPTO_ALIAS(d2i_ECParameters);
+
+EC_KEY *
+o2i_ECPublicKey(EC_KEY **a, const unsigned char **in, long len)
+{
+	EC_KEY *ret = NULL;
+
+	if (a == NULL || (*a) == NULL || (*a)->group == NULL) {
+		/* An EC_GROUP structure is necessary to set the public key. */
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	ret = *a;
+	if (ret->pub_key == NULL &&
+	    (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	if (!EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		return 0;
+	}
+	/* save the point conversion form */
+	ret->conv_form = (point_conversion_form_t) (*in[0] & ~0x01);
+	*in += len;
+	return ret;
+}
+LCRYPTO_ALIAS(o2i_ECPublicKey);
+
+int
+i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
+{
+	size_t buf_len = 0;
+	int new_buffer = 0;
+
+	if (a == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	buf_len = EC_POINT_point2oct(a->group, a->pub_key,
+	    a->conv_form, NULL, 0, NULL);
+
+	if (out == NULL || buf_len == 0)
+		/* out == NULL => just return the length of the octet string */
+		return buf_len;
+
+	if (*out == NULL) {
+		if ((*out = malloc(buf_len)) == NULL) {
+			ECerror(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)) {
+		ECerror(ERR_R_EC_LIB);
+		if (new_buffer) {
+			free(*out);
+			*out = NULL;
+		}
+		return 0;
+	}
+	if (!new_buffer)
+		*out += buf_len;
+	return buf_len;
+}
+LCRYPTO_ALIAS(i2o_ECPublicKey);
diff --git a/crypto/ec/ec_check.c b/crypto/ec/ec_check.c
new file mode 100644
index 0000000..0f98ef6
--- /dev/null
+++ b/crypto/ec/ec_check.c
@@ -0,0 +1,112 @@
+/* $OpenBSD: ec_check.c,v 1.15 2023/07/07 13:54:45 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include "ec_local.h"
+#include 
+
+int
+EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	EC_POINT *point = NULL;
+	const BIGNUM *order;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	/* check the discriminant */
+	if (!EC_GROUP_check_discriminant(group, ctx)) {
+		ECerror(EC_R_DISCRIMINANT_IS_ZERO);
+		goto err;
+	}
+	/* check the generator */
+	if (group->generator == NULL) {
+		ECerror(EC_R_UNDEFINED_GENERATOR);
+		goto err;
+	}
+	if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) {
+		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+	}
+	/* check the order of the generator */
+	if ((point = EC_POINT_new(group)) == NULL)
+		goto err;
+	if ((order = EC_GROUP_get0_order(group)) == NULL)
+		goto err;
+	if (BN_is_zero(order)) {
+		ECerror(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) <= 0) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	EC_POINT_free(point);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_GROUP_check);
diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c
new file mode 100644
index 0000000..9d19628
--- /dev/null
+++ b/crypto/ec/ec_curve.c
@@ -0,0 +1,3193 @@
+/* $OpenBSD: ec_curve.c,v 1.42 2023/07/07 13:54:45 beck Exp $ */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "ec_local.h"
+
+/* the nist prime curves */
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_NIST_PRIME_192 = {
+	.seed = {
+		0x30, 0x45, 0xae, 0x6f, 0xc8, 0x42, 0x2f, 0x64, 0xed, 0x57,
+		0x95, 0x28, 0xd3, 0x81, 0x20, 0xea, 0xe1, 0x21, 0x96, 0xd5,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7, 0x0f, 0xa7,
+		0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec,
+		0xc1, 0x46, 0xb9, 0xb1,
+	},
+	.x = {
+		0x18, 0x8d, 0xa8, 0x0e, 0xb0, 0x30, 0x90, 0xf6, 0x7c, 0xbf,
+		0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00, 0xf4, 0xff, 0x0a, 0xfd,
+		0x82, 0xff, 0x10, 0x12,
+	},
+	.y = {
+		0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10,
+		0x11, 0xed, 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1,
+		0x1e, 0x79, 0x48, 0x11,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, 0x6b, 0xc9, 0xb1,
+		0xb4, 0xd2, 0x28, 0x31,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[28];
+	uint8_t a[28];
+	uint8_t b[28];
+	uint8_t x[28];
+	uint8_t y[28];
+	uint8_t order[28];
+} _EC_NIST_PRIME_224 = {
+	.seed = {
+		0xbd, 0x71, 0x34, 0x47, 0x99, 0xd5, 0xc7, 0xfc, 0xdc, 0x45,
+		0xb5, 0x9f, 0xa3, 0xb9, 0xab, 0x8f, 0x6a, 0x94, 0x8b, 0xc5,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+	},
+	.b = {
+		0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41,
+		0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba,
+		0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4,
+	},
+	.x = {
+		0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13,
+		0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22,
+		0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21,
+	},
+	.y = {
+		0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22,
+		0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+		0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, 0xe0, 0xb8, 0xf0, 0x3e,
+		0x13, 0xdd, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[48];
+	uint8_t a[48];
+	uint8_t b[48];
+	uint8_t x[48];
+	uint8_t y[48];
+	uint8_t order[48];
+} _EC_NIST_PRIME_384 = {
+	.seed = {
+		0xa3, 0x35, 0x92, 0x6a, 0xa3, 0x19, 0xa2, 0x7a, 0x1d, 0x00,
+		0x89, 0x6a, 0x67, 0x73, 0xa4, 0x82, 0x7a, 0xcd, 0xac, 0x73,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0xb3, 0x31, 0x2f, 0xa7, 0xe2, 0x3e, 0xe7, 0xe4, 0x98, 0x8e,
+		0x05, 0x6b, 0xe3, 0xf8, 0x2d, 0x19, 0x18, 0x1d, 0x9c, 0x6e,
+		0xfe, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8f, 0x50, 0x13,
+		0x87, 0x5a, 0xc6, 0x56, 0x39, 0x8d, 0x8a, 0x2e, 0xd1, 0x9d,
+		0x2a, 0x85, 0xc8, 0xed, 0xd3, 0xec, 0x2a, 0xef,
+	},
+	.x = {
+		0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1,
+		0xc7, 0x1e, 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62,
+		0x8b, 0xa7, 0x9b, 0x98, 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54,
+		0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d, 0xbf, 0x55, 0x29, 0x6c,
+		0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xb7,
+	},
+	.y = {
+		0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e,
+		0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd,
+		0x28, 0x9a, 0x14, 0x7c, 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0,
+		0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d,
+		0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37,
+		0x2d, 0xdf, 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a,
+		0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[66];
+	uint8_t a[66];
+	uint8_t b[66];
+	uint8_t x[66];
+	uint8_t y[66];
+	uint8_t order[66];
+} _EC_NIST_PRIME_521 = {
+	.seed = {
+		0xd0, 0x9e, 0x88, 0x00, 0x29, 0x1c, 0xb8, 0x53, 0x96, 0xcc,
+		0x67, 0x17, 0x39, 0x32, 0x84, 0xaa, 0xa0, 0xda, 0x64, 0xba,
+	},
+	.p = {
+		0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, 0x9a, 0x1f,
+		0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85, 0x40, 0xee, 0xa2, 0xda,
+		0x72, 0x5b, 0x99, 0xb3, 0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91,
+		0x8e, 0xf1, 0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e,
+		0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1, 0xbf, 0x07,
+		0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c, 0x34, 0xf1, 0xef, 0x45,
+		0x1f, 0xd4, 0x6b, 0x50, 0x3f, 0x00,
+	},
+	.x = {
+		0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, 0xe9, 0xcd,
+		0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95, 0xb4, 0x42, 0x9c, 0x64,
+		0x81, 0x39, 0x05, 0x3f, 0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60,
+		0x6b, 0x4d, 0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
+		0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff, 0xa8, 0xde,
+		0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a, 0x42, 0x9b, 0xf9, 0x7e,
+		0x7e, 0x31, 0xc2, 0xe5, 0xbd, 0x66,
+	},
+	.y = {
+		0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04,
+		0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5,
+		0x44, 0x49, 0x57, 0x9b, 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17,
+		0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
+		0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, 0x07, 0x61,
+		0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+		0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
+	},
+	.order = {
+		0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xfa, 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f,
+		0x96, 0x6b, 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0,
+		0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, 0xbb, 0x6f,
+		0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09,
+	},
+};
+
+/* the x9.62 prime curves (minus the nist prime curves) */
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_X9_62_PRIME_192V2 = {
+	.seed = {
+		0x31, 0xa9, 0x2e, 0xe2, 0x02, 0x9f, 0xd1, 0x0d, 0x90, 0x1b,
+		0x11, 0x3e, 0x99, 0x07, 0x10, 0xf0, 0xd2, 0x1a, 0xc6, 0xb6,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0xcc, 0x22, 0xd6, 0xdf, 0xb9, 0x5c, 0x6b, 0x25, 0xe4, 0x9c,
+		0x0d, 0x63, 0x64, 0xa4, 0xe5, 0x98, 0x0c, 0x39, 0x3a, 0xa2,
+		0x16, 0x68, 0xd9, 0x53,
+	},
+	.x = {
+		0xee, 0xa2, 0xba, 0xe7, 0xe1, 0x49, 0x78, 0x42, 0xf2, 0xde,
+		0x77, 0x69, 0xcf, 0xe9, 0xc9, 0x89, 0xc0, 0x72, 0xad, 0x69,
+		0x6f, 0x48, 0x03, 0x4a,
+	},
+	.y = {
+		0x65, 0x74, 0xd1, 0x1d, 0x69, 0xb6, 0xec, 0x7a, 0x67, 0x2b,
+		0xb8, 0x2a, 0x08, 0x3d, 0xf2, 0xf2, 0xb0, 0x84, 0x7d, 0xe9,
+		0x70, 0xb2, 0xde, 0x15,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xfe, 0x5f, 0xb1, 0xa7, 0x24, 0xdc, 0x80, 0x41, 0x86,
+		0x48, 0xd8, 0xdd, 0x31,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_X9_62_PRIME_192V3 = {
+	.seed = {
+		0xc4, 0x69, 0x68, 0x44, 0x35, 0xde, 0xb3, 0x78, 0xc4, 0xb6,
+		0x5c, 0xa9, 0x59, 0x1e, 0x2a, 0x57, 0x63, 0x05, 0x9a, 0x2e,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x22, 0x12, 0x3d, 0xc2, 0x39, 0x5a, 0x05, 0xca, 0xa7, 0x42,
+		0x3d, 0xae, 0xcc, 0xc9, 0x47, 0x60, 0xa7, 0xd4, 0x62, 0x25,
+		0x6b, 0xd5, 0x69, 0x16,
+	},
+	.x = {
+		0x7d, 0x29, 0x77, 0x81, 0x00, 0xc6, 0x5a, 0x1d, 0xa1, 0x78,
+		0x37, 0x16, 0x58, 0x8d, 0xce, 0x2b, 0x8b, 0x4a, 0xee, 0x8e,
+		0x22, 0x8f, 0x18, 0x96,
+	},
+	.y = {
+		0x38, 0xa9, 0x0f, 0x22, 0x63, 0x73, 0x37, 0x33, 0x4b, 0x49,
+		0xdc, 0xb6, 0x6a, 0x6d, 0xc8, 0xf9, 0x97, 0x8a, 0xca, 0x76,
+		0x48, 0xa9, 0x43, 0xb0,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7a, 0x62, 0xd0, 0x31, 0xc8, 0x3f, 0x42, 0x94,
+		0xf6, 0x40, 0xec, 0x13,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[30];
+	uint8_t a[30];
+	uint8_t b[30];
+	uint8_t x[30];
+	uint8_t y[30];
+	uint8_t order[30];
+} _EC_X9_62_PRIME_239V1 = {
+	.seed = {
+		0xe4, 0x3b, 0xb4, 0x60, 0xf0, 0xb8, 0x0c, 0xc0, 0xc0, 0xb0,
+		0x75, 0x79, 0x8e, 0x94, 0x80, 0x60, 0xf8, 0x32, 0x1b, 0x7d,
+	},
+	.p = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x6b, 0x01, 0x6c, 0x3b, 0xdc, 0xf1, 0x89, 0x41, 0xd0, 0xd6,
+		0x54, 0x92, 0x14, 0x75, 0xca, 0x71, 0xa9, 0xdb, 0x2f, 0xb2,
+		0x7d, 0x1d, 0x37, 0x79, 0x61, 0x85, 0xc2, 0x94, 0x2c, 0x0a,
+	},
+	.x = {
+		0x0f, 0xfa, 0x96, 0x3c, 0xdc, 0xa8, 0x81, 0x6c, 0xcc, 0x33,
+		0xb8, 0x64, 0x2b, 0xed, 0xf9, 0x05, 0xc3, 0xd3, 0x58, 0x57,
+		0x3d, 0x3f, 0x27, 0xfb, 0xbd, 0x3b, 0x3c, 0xb9, 0xaa, 0xaf,
+	},
+	.y = {
+		0x7d, 0xeb, 0xe8, 0xe4, 0xe9, 0x0a, 0x5d, 0xae, 0x6e, 0x40,
+		0x54, 0xca, 0x53, 0x0b, 0xa0, 0x46, 0x54, 0xb3, 0x68, 0x18,
+		0xce, 0x22, 0x6b, 0x39, 0xfc, 0xcb, 0x7b, 0x02, 0xf1, 0xae,
+	},
+	.order = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0x9e, 0x5e, 0x9a, 0x9f, 0x5d,
+		0x90, 0x71, 0xfb, 0xd1, 0x52, 0x26, 0x88, 0x90, 0x9d, 0x0b,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[30];
+	uint8_t a[30];
+	uint8_t b[30];
+	uint8_t x[30];
+	uint8_t y[30];
+	uint8_t order[30];
+} _EC_X9_62_PRIME_239V2 = {
+	.seed = {
+		0xe8, 0xb4, 0x01, 0x16, 0x04, 0x09, 0x53, 0x03, 0xca, 0x3b,
+		0x80, 0x99, 0x98, 0x2b, 0xe0, 0x9f, 0xcb, 0x9a, 0xe6, 0x16,
+	},
+	.p = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x61, 0x7f, 0xab, 0x68, 0x32, 0x57, 0x6c, 0xbb, 0xfe, 0xd5,
+		0x0d, 0x99, 0xf0, 0x24, 0x9c, 0x3f, 0xee, 0x58, 0xb9, 0x4b,
+		0xa0, 0x03, 0x8c, 0x7a, 0xe8, 0x4c, 0x8c, 0x83, 0x2f, 0x2c,
+	},
+	.x = {
+		0x38, 0xaf, 0x09, 0xd9, 0x87, 0x27, 0x70, 0x51, 0x20, 0xc9,
+		0x21, 0xbb, 0x5e, 0x9e, 0x26, 0x29, 0x6a, 0x3c, 0xdc, 0xf2,
+		0xf3, 0x57, 0x57, 0xa0, 0xea, 0xfd, 0x87, 0xb8, 0x30, 0xe7,
+	},
+	.y = {
+		0x5b, 0x01, 0x25, 0xe4, 0xdb, 0xea, 0x0e, 0xc7, 0x20, 0x6d,
+		0xa0, 0xfc, 0x01, 0xd9, 0xb0, 0x81, 0x32, 0x9f, 0xb5, 0x55,
+		0xde, 0x6e, 0xf4, 0x60, 0x23, 0x7d, 0xff, 0x8b, 0xe4, 0xba,
+	},
+	.order = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x80, 0x00, 0x00, 0xcf, 0xa7, 0xe8, 0x59, 0x43,
+		0x77, 0xd4, 0x14, 0xc0, 0x38, 0x21, 0xbc, 0x58, 0x20, 0x63,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[30];
+	uint8_t a[30];
+	uint8_t b[30];
+	uint8_t x[30];
+	uint8_t y[30];
+	uint8_t order[30];
+} _EC_X9_62_PRIME_239V3 = {
+	.seed = {
+		0x7d, 0x73, 0x74, 0x16, 0x8f, 0xfe, 0x34, 0x71, 0xb6, 0x0a,
+		0x85, 0x76, 0x86, 0xa1, 0x94, 0x75, 0xd3, 0xbf, 0xa2, 0xff,
+	},
+	.p = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0x25, 0x57, 0x05, 0xfa, 0x2a, 0x30, 0x66, 0x54, 0xb1, 0xf4,
+		0xcb, 0x03, 0xd6, 0xa7, 0x50, 0xa3, 0x0c, 0x25, 0x01, 0x02,
+		0xd4, 0x98, 0x87, 0x17, 0xd9, 0xba, 0x15, 0xab, 0x6d, 0x3e,
+	},
+	.x = {
+		0x67, 0x68, 0xae, 0x8e, 0x18, 0xbb, 0x92, 0xcf, 0xcf, 0x00,
+		0x5c, 0x94, 0x9a, 0xa2, 0xc6, 0xd9, 0x48, 0x53, 0xd0, 0xe6,
+		0x60, 0xbb, 0xf8, 0x54, 0xb1, 0xc9, 0x50, 0x5f, 0xe9, 0x5a,
+	},
+	.y = {
+		0x16, 0x07, 0xe6, 0x89, 0x8f, 0x39, 0x0c, 0x06, 0xbc, 0x1d,
+		0x55, 0x2b, 0xad, 0x22, 0x6f, 0x3b, 0x6f, 0xcf, 0xe4, 0x8b,
+		0x6e, 0x81, 0x84, 0x99, 0xaf, 0x18, 0xe3, 0xed, 0x6c, 0xf3,
+	},
+	.order = {
+		0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x7f, 0xff, 0xff, 0x97, 0x5d, 0xeb, 0x41, 0xb3,
+		0xa6, 0x05, 0x7c, 0x3c, 0x43, 0x21, 0x46, 0x52, 0x65, 0x51,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_X9_62_PRIME_256V1 = {
+	.seed = {
+		0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66,
+		0x78, 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xfc,
+	},
+	.b = {
+		0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
+		0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0,
+		0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2,
+		0x60, 0x4b,
+	},
+	.x = {
+		0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc,
+		0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
+		0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98,
+		0xc2, 0x96,
+	},
+	.y = {
+		0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7,
+		0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
+		0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf,
+		0x51, 0xf5,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad,
+		0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63,
+		0x25, 0x51,
+	},
+};
+
+/* the secg prime curves (minus the nist and x9.62 prime curves) */
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[14];
+	uint8_t a[14];
+	uint8_t b[14];
+	uint8_t x[14];
+	uint8_t y[14];
+	uint8_t order[14];
+} _EC_SECG_PRIME_112R1 = {
+	.seed = {
+		0x00, 0xf5, 0x0b, 0x02, 0x8e, 0x4d, 0x69, 0x6e, 0x67, 0x68,
+		0x75, 0x61, 0x51, 0x75, 0x29, 0x04, 0x72, 0x78, 0x3f, 0xb1,
+	},
+	.p = {
+		0xdb, 0x7c, 0x2a, 0xbf, 0x62, 0xe3, 0x5e, 0x66, 0x80, 0x76,
+		0xbe, 0xad, 0x20, 0x8b,
+	},
+	.a = {
+		0xdb, 0x7c, 0x2a, 0xbf, 0x62, 0xe3, 0x5e, 0x66, 0x80, 0x76,
+		0xbe, 0xad, 0x20, 0x88,
+	},
+	.b = {
+		0x65, 0x9e, 0xf8, 0xba, 0x04, 0x39, 0x16, 0xee, 0xde, 0x89,
+		0x11, 0x70, 0x2b, 0x22,
+	},
+	.x = {
+		0x09, 0x48, 0x72, 0x39, 0x99, 0x5a, 0x5e, 0xe7, 0x6b, 0x55,
+		0xf9, 0xc2, 0xf0, 0x98,
+	},
+	.y = {
+		0xa8, 0x9c, 0xe5, 0xaf, 0x87, 0x24, 0xc0, 0xa2, 0x3e, 0x0e,
+		0x0f, 0xf7, 0x75, 0x00,
+	},
+	.order = {
+		0xdb, 0x7c, 0x2a, 0xbf, 0x62, 0xe3, 0x5e, 0x76, 0x28, 0xdf,
+		0xac, 0x65, 0x61, 0xc5,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[14];
+	uint8_t a[14];
+	uint8_t b[14];
+	uint8_t x[14];
+	uint8_t y[14];
+	uint8_t order[14];
+} _EC_SECG_PRIME_112R2 = {
+	.seed = {
+		0x00, 0x27, 0x57, 0xa1, 0x11, 0x4d, 0x69, 0x6e, 0x67, 0x68,
+		0x75, 0x61, 0x51, 0x75, 0x53, 0x16, 0xc0, 0x5e, 0x0b, 0xd4,
+	},
+	.p = {
+		0xdb, 0x7c, 0x2a, 0xbf, 0x62, 0xe3, 0x5e, 0x66, 0x80, 0x76,
+		0xbe, 0xad, 0x20, 0x8b,
+	},
+	.a = {
+		0x61, 0x27, 0xc2, 0x4c, 0x05, 0xf3, 0x8a, 0x0a, 0xaa, 0xf6,
+		0x5c, 0x0e, 0xf0, 0x2c,
+	},
+	.b = {
+		0x51, 0xde, 0xf1, 0x81, 0x5d, 0xb5, 0xed, 0x74, 0xfc, 0xc3,
+		0x4c, 0x85, 0xd7, 0x09,
+	},
+	.x = {
+		0x4b, 0xa3, 0x0a, 0xb5, 0xe8, 0x92, 0xb4, 0xe1, 0x64, 0x9d,
+		0xd0, 0x92, 0x86, 0x43,
+	},
+	.y = {
+		0xad, 0xcd, 0x46, 0xf5, 0x88, 0x2e, 0x37, 0x47, 0xde, 0xf3,
+		0x6e, 0x95, 0x6e, 0x97,
+	},
+	.order = {
+		0x36, 0xdf, 0x0a, 0xaf, 0xd8, 0xb8, 0xd7, 0x59, 0x7c, 0xa1,
+		0x05, 0x20, 0xd0, 0x4b,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[16];
+	uint8_t a[16];
+	uint8_t b[16];
+	uint8_t x[16];
+	uint8_t y[16];
+	uint8_t order[16];
+} _EC_SECG_PRIME_128R1 = {
+	.seed = {
+		0x00, 0x0e, 0x0d, 0x4d, 0x69, 0x6e, 0x67, 0x68, 0x75, 0x61,
+		0x51, 0x75, 0x0c, 0xc0, 0x3a, 0x44, 0x73, 0xd0, 0x36, 0x79,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+	},
+	.b = {
+		0xe8, 0x75, 0x79, 0xc1, 0x10, 0x79, 0xf4, 0x3d, 0xd8, 0x24,
+		0x99, 0x3c, 0x2c, 0xee, 0x5e, 0xd3,
+	},
+	.x = {
+		0x16, 0x1f, 0xf7, 0x52, 0x8b, 0x89, 0x9b, 0x2d, 0x0c, 0x28,
+		0x60, 0x7c, 0xa5, 0x2c, 0x5b, 0x86,
+	},
+	.y = {
+		0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d,
+		0xa2, 0x92, 0xdd, 0xed, 0x7a, 0x83,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x75, 0xa3,
+		0x0d, 0x1b, 0x90, 0x38, 0xa1, 0x15,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[16];
+	uint8_t a[16];
+	uint8_t b[16];
+	uint8_t x[16];
+	uint8_t y[16];
+	uint8_t order[16];
+} _EC_SECG_PRIME_128R2 = {
+	.seed = {
+		0x00, 0x4d, 0x69, 0x6e, 0x67, 0x68, 0x75, 0x61, 0x51, 0x75,
+		0x12, 0xd8, 0xf0, 0x34, 0x31, 0xfc, 0xe6, 0x3b, 0x88, 0xf4,
+	},
+	.p = {
+		0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	},
+	.a = {
+		0xd6, 0x03, 0x19, 0x98, 0xd1, 0xb3, 0xbb, 0xfe, 0xbf, 0x59,
+		0xcc, 0x9b, 0xbf, 0xf9, 0xae, 0xe1,
+	},
+	.b = {
+		0x5e, 0xee, 0xfc, 0xa3, 0x80, 0xd0, 0x29, 0x19, 0xdc, 0x2c,
+		0x65, 0x58, 0xbb, 0x6d, 0x8a, 0x5d,
+	},
+	.x = {
+		0x7b, 0x6a, 0xa5, 0xd8, 0x5e, 0x57, 0x29, 0x83, 0xe6, 0xfb,
+		0x32, 0xa7, 0xcd, 0xeb, 0xc1, 0x40,
+	},
+	.y = {
+		0x27, 0xb6, 0x91, 0x6a, 0x89, 0x4d, 0x3a, 0xee, 0x71, 0x06,
+		0xfe, 0x80, 0x5f, 0xc3, 0x4b, 0x44,
+	},
+	.order = {
+		0x3f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xbe, 0x00,
+		0x24, 0x72, 0x06, 0x13, 0xb5, 0xa3,
+	},
+};
+
+static const struct {
+	uint8_t p[21];
+	uint8_t a[21];
+	uint8_t b[21];
+	uint8_t x[21];
+	uint8_t y[21];
+	uint8_t order[21];
+} _EC_SECG_PRIME_160K1 = {
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xac,
+		0x73,
+	},
+	.a = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00,
+	},
+	.b  = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x07,
+	},
+	.x = {
+		0x00, 0x3b, 0x4c, 0x38, 0x2c, 0xe3, 0x7a, 0xa1, 0x92, 0xa4,
+		0x01, 0x9e, 0x76, 0x30, 0x36, 0xf4, 0xf5, 0xdd, 0x4d, 0x7e,
+		0xbb,
+	},
+	.y = {
+		0x00, 0x93, 0x8c, 0xf9, 0x35, 0x31, 0x8f, 0xdc, 0xed, 0x6b,
+		0xc2, 0x82, 0x86, 0x53, 0x17, 0x33, 0xc3, 0xf0, 0x3c, 0x4f,
+		0xee,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xb8, 0xfa, 0x16, 0xdf, 0xab, 0x9a, 0xca, 0x16, 0xb6,
+		0xb3,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[21];
+	uint8_t a[21];
+	uint8_t b[21];
+	uint8_t x[21];
+	uint8_t y[21];
+	uint8_t order[21];
+} _EC_SECG_PRIME_160R1 = {
+	.seed = {
+		0x10, 0x53, 0xcd, 0xe4, 0x2c, 0x14, 0xd6, 0x96, 0xe6, 0x76,
+		0x87, 0x56, 0x15, 0x17, 0x53, 0x3b, 0xf3, 0xf8, 0x33, 0x45,
+	},
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff,
+		0xff,
+	},
+	.a = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff,
+		0xfc,
+	},
+	.b = {
+		0x00, 0x1c, 0x97, 0xbe, 0xfc, 0x54, 0xbd, 0x7a, 0x8b, 0x65,
+		0xac, 0xf8, 0x9f, 0x81, 0xd4, 0xd4, 0xad, 0xc5, 0x65, 0xfa,
+		0x45,
+	},
+	.x = {
+		0x00, 0x4a, 0x96, 0xb5, 0x68, 0x8e, 0xf5, 0x73, 0x28, 0x46,
+		0x64, 0x69, 0x89, 0x68, 0xc3, 0x8b, 0xb9, 0x13, 0xcb, 0xfc,
+		0x82,
+	},
+	.y = {
+		0x00, 0x23, 0xa6, 0x28, 0x55, 0x31, 0x68, 0x94, 0x7d, 0x59,
+		0xdc, 0xc9, 0x12, 0x04, 0x23, 0x51, 0x37, 0x7a, 0xc5, 0xfb,
+		0x32,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xf4, 0xc8, 0xf9, 0x27, 0xae, 0xd3, 0xca, 0x75, 0x22,
+		0x57,
+	},
+};
+
+static const struct {
+	uint8_t seed[20];
+	uint8_t p[21];
+	uint8_t a[21];
+	uint8_t b[21];
+	uint8_t x[21];
+	uint8_t y[21];
+	uint8_t order[21];
+} _EC_SECG_PRIME_160R2 = {
+	.seed = {
+		0xb9, 0x9b, 0x99, 0xb0, 0x99, 0xb3, 0x23, 0xe0, 0x27, 0x09,
+		0xa4, 0xd6, 0x96, 0xe6, 0x76, 0x87, 0x56, 0x15, 0x17, 0x51,
+	},
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xac,
+		0x73,
+	},
+	.a = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xac,
+		0x70,
+	},
+	.b = {
+		0x00, 0xb4, 0xe1, 0x34, 0xd3, 0xfb, 0x59, 0xeb, 0x8b, 0xab,
+		0x57, 0x27, 0x49, 0x04, 0x66, 0x4d, 0x5a, 0xf5, 0x03, 0x88,
+		0xba,
+	},
+	.x = {
+		0x00, 0x52, 0xdc, 0xb0, 0x34, 0x29, 0x3a, 0x11, 0x7e, 0x1f,
+		0x4f, 0xf1, 0x1b, 0x30, 0xf7, 0x19, 0x9d, 0x31, 0x44, 0xce,
+		0x6d,
+	},
+	.y = {
+		0x00, 0xfe, 0xaf, 0xfe, 0xf2, 0xe3, 0x31, 0xf2, 0x96, 0xe0,
+		0x71, 0xfa, 0x0d, 0xf9, 0x98, 0x2c, 0xfe, 0xa7, 0xd4, 0x3f,
+		0x2e,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x35, 0x1e, 0xe7, 0x86, 0xa8, 0x18, 0xf3, 0xa1, 0xa1,
+		0x6b,
+	},
+};
+
+static const struct {
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_SECG_PRIME_192K1 = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+		0xff, 0xff, 0xee, 0x37,
+	},
+	.a = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00,
+	},
+	.b = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x03,
+	},
+	.x = {
+		0xdb, 0x4f, 0xf1, 0x0e, 0xc0, 0x57, 0xe9, 0xae, 0x26, 0xb0,
+		0x7d, 0x02, 0x80, 0xb7, 0xf4, 0x34, 0x1d, 0xa5, 0xd1, 0xb1,
+		0xea, 0xe0, 0x6c, 0x7d,
+	},
+	.y = {
+		0x9b, 0x2f, 0x2f, 0x6d, 0x9c, 0x56, 0x28, 0xa7, 0x84, 0x41,
+		0x63, 0xd0, 0x15, 0xbe, 0x86, 0x34, 0x40, 0x82, 0xaa, 0x88,
+		0xd9, 0x5e, 0x2f, 0x9d,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xfe, 0x26, 0xf2, 0xfc, 0x17, 0x0f, 0x69, 0x46, 0x6a,
+		0x74, 0xde, 0xfd, 0x8d,
+	},
+};
+
+static const struct {
+	uint8_t p[29];
+	uint8_t a[29];
+	uint8_t b[29];
+	uint8_t x[29];
+	uint8_t y[29];
+	uint8_t order[29];
+} _EC_SECG_PRIME_224K1 = {
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xe5, 0x6d,
+	},
+	.a = {
+		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,
+	},
+	.b = {
+		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, 0x05,
+	},
+	.x = {
+		0x00, 0xa1, 0x45, 0x5b, 0x33, 0x4d, 0xf0, 0x99, 0xdf, 0x30,
+		0xfc, 0x28, 0xa1, 0x69, 0xa4, 0x67, 0xe9, 0xe4, 0x70, 0x75,
+		0xa9, 0x0f, 0x7e, 0x65, 0x0e, 0xb6, 0xb7, 0xa4, 0x5c,
+	},
+	.y = {
+		0x00, 0x7e, 0x08, 0x9f, 0xed, 0x7f, 0xba, 0x34, 0x42, 0x82,
+		0xca, 0xfb, 0xd6, 0xf7, 0xe3, 0x19, 0xf7, 0xc0, 0xb0, 0xbd,
+		0x59, 0xe2, 0xca, 0x4b, 0xdb, 0x55, 0x6d, 0x61, 0xa5,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01, 0xdc, 0xe8, 0xd2, 0xec, 0x61,
+		0x84, 0xca, 0xf0, 0xa9, 0x71, 0x76, 0x9f, 0xb1, 0xf7,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_SECG_PRIME_256K1 = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff,
+		0xfc, 0x2f,
+	},
+	.a = {
+		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,
+	},
+	.b = {
+		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, 0x07,
+	},
+	.x = {
+		0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0,
+		0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb,
+		0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8,
+		0x17, 0x98,
+	},
+	.y = {
+		0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4,
+		0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48,
+		0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10,
+		0xd4, 0xb8,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6,
+		0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36,
+		0x41, 0x41,
+	},
+};
+
+/* some wap/wtls curves */
+static const struct {
+	uint8_t p[15];
+	uint8_t a[15];
+	uint8_t b[15];
+	uint8_t x[15];
+	uint8_t y[15];
+	uint8_t order[15];
+} _EC_WTLS_8 = {
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xfd, 0xe7,
+	},
+	.a = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00,
+	},
+	.b = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x03,
+	},
+	.x = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x01,
+	},
+	.y = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x02,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xec, 0xea,
+		0x55, 0x1a, 0xd8, 0x37, 0xe9,
+	},
+};
+
+static const struct {
+	uint8_t p[21];
+	uint8_t a[21];
+	uint8_t b[21];
+	uint8_t x[21];
+	uint8_t y[21];
+	uint8_t order[21];
+} _EC_WTLS_9 = {
+	.p = {
+		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x80,
+		0x8f,
+	},
+	.a = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00,
+	},
+	.b = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x03,
+	},
+	.x = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01,
+	},
+	.y = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x02,
+	},
+	.order = {
+		0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x01, 0xcd, 0xc9, 0x8a, 0xe0, 0xe2, 0xde, 0x57, 0x4a, 0xbf,
+		0x33,
+	},
+};
+
+static const struct {
+	uint8_t p[28];
+	uint8_t a[28];
+	uint8_t b[28];
+	uint8_t x[28];
+	uint8_t y[28];
+	uint8_t order[28];
+} _EC_WTLS_12 = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+	},
+	.b = {
+		0xb4, 0x05, 0x0a, 0x85, 0x0c, 0x04, 0xb3, 0xab, 0xf5, 0x41,
+		0x32, 0x56, 0x50, 0x44, 0xb0, 0xb7, 0xd7, 0xbf, 0xd8, 0xba,
+		0x27, 0x0b, 0x39, 0x43, 0x23, 0x55, 0xff, 0xb4,
+	},
+	.x = {
+		0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13,
+		0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22,
+		0x34, 0x32, 0x80, 0xd6, 0x11, 0x5c, 0x1d, 0x21,
+	},
+	.y = {
+		0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22,
+		0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+		0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0x16, 0xa2, 0xe0, 0xb8, 0xf0, 0x3e,
+		0x13, 0xdd, 0x29, 0x45, 0x5c, 0x5c, 0x2a, 0x3d,
+	},
+};
+
+static const struct {
+	uint8_t p[20];
+	uint8_t a[20];
+	uint8_t b[20];
+	uint8_t x[20];
+	uint8_t y[20];
+	uint8_t order[20];
+} _EC_brainpoolP160r1 = {
+	.p = {
+		0xe9, 0x5e, 0x4a, 0x5f, 0x73, 0x70, 0x59, 0xdc, 0x60, 0xdf,
+		0xc7, 0xad, 0x95, 0xb3, 0xd8, 0x13, 0x95, 0x15, 0x62, 0x0f,
+	},
+	.a = {
+		0x34, 0x0e, 0x7b, 0xe2, 0xa2, 0x80, 0xeb, 0x74, 0xe2, 0xbe,
+		0x61, 0xba, 0xda, 0x74, 0x5d, 0x97, 0xe8, 0xf7, 0xc3, 0x00,
+	},
+	.b = {
+		0x1e, 0x58, 0x9a, 0x85, 0x95, 0x42, 0x34, 0x12, 0x13, 0x4f,
+		0xaa, 0x2d, 0xbd, 0xec, 0x95, 0xc8, 0xd8, 0x67, 0x5e, 0x58,
+	},
+	.x = {
+		0xbe, 0xd5, 0xaf, 0x16, 0xea, 0x3f, 0x6a, 0x4f, 0x62, 0x93,
+		0x8c, 0x46, 0x31, 0xeb, 0x5a, 0xf7, 0xbd, 0xbc, 0xdb, 0xc3,
+	},
+	.y = {
+		0x16, 0x67, 0xcb, 0x47, 0x7a, 0x1a, 0x8e, 0xc3, 0x38, 0xf9,
+		0x47, 0x41, 0x66, 0x9c, 0x97, 0x63, 0x16, 0xda, 0x63, 0x21,
+	},
+	.order = {
+		0xe9, 0x5e, 0x4a, 0x5f, 0x73, 0x70, 0x59, 0xdc, 0x60, 0xdf,
+		0x59, 0x91, 0xd4, 0x50, 0x29, 0x40, 0x9e, 0x60, 0xfc, 0x09,
+	},
+};
+
+static const struct {
+	uint8_t p[20];
+	uint8_t a[20];
+	uint8_t b[20];
+	uint8_t x[20];
+	uint8_t y[20];
+	uint8_t order[20];
+} _EC_brainpoolP160t1 = {
+	.p = {
+		0xe9, 0x5e, 0x4a, 0x5f, 0x73, 0x70, 0x59, 0xdc, 0x60, 0xdf,
+		0xc7, 0xad, 0x95, 0xb3, 0xd8, 0x13, 0x95, 0x15, 0x62, 0x0f,
+	},
+	.a = {
+		0xe9, 0x5e, 0x4a, 0x5f, 0x73, 0x70, 0x59, 0xdc, 0x60, 0xdf,
+		0xc7, 0xad, 0x95, 0xb3, 0xd8, 0x13, 0x95, 0x15, 0x62, 0x0c,
+	},
+	.b = {
+		0x7a, 0x55, 0x6b, 0x6d, 0xae, 0x53, 0x5b, 0x7b, 0x51, 0xed,
+		0x2c, 0x4d, 0x7d, 0xaa, 0x7a, 0x0b, 0x5c, 0x55, 0xf3, 0x80,
+	},
+	.x = {
+		0xb1, 0x99, 0xb1, 0x3b, 0x9b, 0x34, 0xef, 0xc1, 0x39, 0x7e,
+		0x64, 0xba, 0xeb, 0x05, 0xac, 0xc2, 0x65, 0xff, 0x23, 0x78,
+	},
+	.y = {
+		0xad, 0xd6, 0x71, 0x8b, 0x7c, 0x7c, 0x19, 0x61, 0xf0, 0x99,
+		0x1b, 0x84, 0x24, 0x43, 0x77, 0x21, 0x52, 0xc9, 0xe0, 0xad,
+	},
+	.order = {
+		0xe9, 0x5e, 0x4a, 0x5f, 0x73, 0x70, 0x59, 0xdc, 0x60, 0xdf,
+		0x59, 0x91, 0xd4, 0x50, 0x29, 0x40, 0x9e, 0x60, 0xfc, 0x09,
+	},
+};
+
+static const struct {
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_brainpoolP192r1 = {
+	.p = {
+		0xc3, 0x02, 0xf4, 0x1d, 0x93, 0x2a, 0x36, 0xcd, 0xa7, 0xa3,
+		0x46, 0x30, 0x93, 0xd1, 0x8d, 0xb7, 0x8f, 0xce, 0x47, 0x6d,
+		0xe1, 0xa8, 0x62, 0x97,
+	},
+	.a = {
+		0x6a, 0x91, 0x17, 0x40, 0x76, 0xb1, 0xe0, 0xe1, 0x9c, 0x39,
+		0xc0, 0x31, 0xfe, 0x86, 0x85, 0xc1, 0xca, 0xe0, 0x40, 0xe5,
+		0xc6, 0x9a, 0x28, 0xef,
+	},
+	.b = {
+		0x46, 0x9a, 0x28, 0xef, 0x7c, 0x28, 0xcc, 0xa3, 0xdc, 0x72,
+		0x1d, 0x04, 0x4f, 0x44, 0x96, 0xbc, 0xca, 0x7e, 0xf4, 0x14,
+		0x6f, 0xbf, 0x25, 0xc9,
+	},
+	.x = {
+		0xc0, 0xa0, 0x64, 0x7e, 0xaa, 0xb6, 0xa4, 0x87, 0x53, 0xb0,
+		0x33, 0xc5, 0x6c, 0xb0, 0xf0, 0x90, 0x0a, 0x2f, 0x5c, 0x48,
+		0x53, 0x37, 0x5f, 0xd6,
+	},
+	.y = {
+		0x14, 0xb6, 0x90, 0x86, 0x6a, 0xbd, 0x5b, 0xb8, 0x8b, 0x5f,
+		0x48, 0x28, 0xc1, 0x49, 0x00, 0x02, 0xe6, 0x77, 0x3f, 0xa2,
+		0xfa, 0x29, 0x9b, 0x8f,
+	},
+	.order = {
+		0xc3, 0x02, 0xf4, 0x1d, 0x93, 0x2a, 0x36, 0xcd, 0xa7, 0xa3,
+		0x46, 0x2f, 0x9e, 0x9e, 0x91, 0x6b, 0x5b, 0xe8, 0xf1, 0x02,
+		0x9a, 0xc4, 0xac, 0xc1,
+	},
+};
+
+static const struct {
+	uint8_t p[24];
+	uint8_t a[24];
+	uint8_t b[24];
+	uint8_t x[24];
+	uint8_t y[24];
+	uint8_t order[24];
+} _EC_brainpoolP192t1 = {
+	.p = {
+		0xc3, 0x02, 0xf4, 0x1d, 0x93, 0x2a, 0x36, 0xcd, 0xa7, 0xa3,
+		0x46, 0x30, 0x93, 0xd1, 0x8d, 0xb7, 0x8f, 0xce, 0x47, 0x6d,
+		0xe1, 0xa8, 0x62, 0x97,
+	},
+	.a = {
+		0xc3, 0x02, 0xf4, 0x1d, 0x93, 0x2a, 0x36, 0xcd, 0xa7, 0xa3,
+		0x46, 0x30, 0x93, 0xd1, 0x8d, 0xb7, 0x8f, 0xce, 0x47, 0x6d,
+		0xe1, 0xa8, 0x62, 0x94,
+	},
+	.b = {
+		0x13, 0xd5, 0x6f, 0xfa, 0xec, 0x78, 0x68, 0x1e, 0x68, 0xf9,
+		0xde, 0xb4, 0x3b, 0x35, 0xbe, 0xc2, 0xfb, 0x68, 0x54, 0x2e,
+		0x27, 0x89, 0x7b, 0x79,
+	},
+	.x = {
+		0x3a, 0xe9, 0xe5, 0x8c, 0x82, 0xf6, 0x3c, 0x30, 0x28, 0x2e,
+		0x1f, 0xe7, 0xbb, 0xf4, 0x3f, 0xa7, 0x2c, 0x44, 0x6a, 0xf6,
+		0xf4, 0x61, 0x81, 0x29,
+	},
+	.y = {
+		0x09, 0x7e, 0x2c, 0x56, 0x67, 0xc2, 0x22, 0x3a, 0x90, 0x2a,
+		0xb5, 0xca, 0x44, 0x9d, 0x00, 0x84, 0xb7, 0xe5, 0xb3, 0xde,
+		0x7c, 0xcc, 0x01, 0xc9,
+	},
+	.order = {
+		0xc3, 0x02, 0xf4, 0x1d, 0x93, 0x2a, 0x36, 0xcd, 0xa7, 0xa3,
+		0x46, 0x2f, 0x9e, 0x9e, 0x91, 0x6b, 0x5b, 0xe8, 0xf1, 0x02,
+		0x9a, 0xc4, 0xac, 0xc1,
+	},
+};
+
+static const struct {
+	uint8_t p[28];
+	uint8_t a[28];
+	uint8_t b[28];
+	uint8_t x[28];
+	uint8_t y[28];
+	uint8_t order[28];
+} _EC_brainpoolP224r1 = {
+	.p = {
+		0xd7, 0xc1, 0x34, 0xaa, 0x26, 0x43, 0x66, 0x86, 0x2a, 0x18,
+		0x30, 0x25, 0x75, 0xd1, 0xd7, 0x87, 0xb0, 0x9f, 0x07, 0x57,
+		0x97, 0xda, 0x89, 0xf5, 0x7e, 0xc8, 0xc0, 0xff,
+	},
+	.a = {
+		0x68, 0xa5, 0xe6, 0x2c, 0xa9, 0xce, 0x6c, 0x1c, 0x29, 0x98,
+		0x03, 0xa6, 0xc1, 0x53, 0x0b, 0x51, 0x4e, 0x18, 0x2a, 0xd8,
+		0xb0, 0x04, 0x2a, 0x59, 0xca, 0xd2, 0x9f, 0x43,
+	},
+	.b = {
+		0x25, 0x80, 0xf6, 0x3c, 0xcf, 0xe4, 0x41, 0x38, 0x87, 0x07,
+		0x13, 0xb1, 0xa9, 0x23, 0x69, 0xe3, 0x3e, 0x21, 0x35, 0xd2,
+		0x66, 0xdb, 0xb3, 0x72, 0x38, 0x6c, 0x40, 0x0b,
+	},
+	.x = {
+		0x0d, 0x90, 0x29, 0xad, 0x2c, 0x7e, 0x5c, 0xf4, 0x34, 0x08,
+		0x23, 0xb2, 0xa8, 0x7d, 0xc6, 0x8c, 0x9e, 0x4c, 0xe3, 0x17,
+		0x4c, 0x1e, 0x6e, 0xfd, 0xee, 0x12, 0xc0, 0x7d,
+	},
+	.y = {
+		0x58, 0xaa, 0x56, 0xf7, 0x72, 0xc0, 0x72, 0x6f, 0x24, 0xc6,
+		0xb8, 0x9e, 0x4e, 0xcd, 0xac, 0x24, 0x35, 0x4b, 0x9e, 0x99,
+		0xca, 0xa3, 0xf6, 0xd3, 0x76, 0x14, 0x02, 0xcd,
+	},
+	.order = {
+		0xd7, 0xc1, 0x34, 0xaa, 0x26, 0x43, 0x66, 0x86, 0x2a, 0x18,
+		0x30, 0x25, 0x75, 0xd0, 0xfb, 0x98, 0xd1, 0x16, 0xbc, 0x4b,
+		0x6d, 0xde, 0xbc, 0xa3, 0xa5, 0xa7, 0x93, 0x9f,
+	},
+};
+
+static const struct {
+	uint8_t p[28];
+	uint8_t a[28];
+	uint8_t b[28];
+	uint8_t x[28];
+	uint8_t y[28];
+	uint8_t order[28];
+} _EC_brainpoolP224t1 = {
+	.p = {
+		0xd7, 0xc1, 0x34, 0xaa, 0x26, 0x43, 0x66, 0x86, 0x2a, 0x18,
+		0x30, 0x25, 0x75, 0xd1, 0xd7, 0x87, 0xb0, 0x9f, 0x07, 0x57,
+		0x97, 0xda, 0x89, 0xf5, 0x7e, 0xc8, 0xc0, 0xff,
+	},
+	.a = {
+		0xd7, 0xc1, 0x34, 0xaa, 0x26, 0x43, 0x66, 0x86, 0x2a, 0x18,
+		0x30, 0x25, 0x75, 0xd1, 0xd7, 0x87, 0xb0, 0x9f, 0x07, 0x57,
+		0x97, 0xda, 0x89, 0xf5, 0x7e, 0xc8, 0xc0, 0xfc,
+	},
+	.b = {
+		0x4b, 0x33, 0x7d, 0x93, 0x41, 0x04, 0xcd, 0x7b, 0xef, 0x27,
+		0x1b, 0xf6, 0x0c, 0xed, 0x1e, 0xd2, 0x0d, 0xa1, 0x4c, 0x08,
+		0xb3, 0xbb, 0x64, 0xf1, 0x8a, 0x60, 0x88, 0x8d,
+	},
+	.x = {
+		0x6a, 0xb1, 0xe3, 0x44, 0xce, 0x25, 0xff, 0x38, 0x96, 0x42,
+		0x4e, 0x7f, 0xfe, 0x14, 0x76, 0x2e, 0xcb, 0x49, 0xf8, 0x92,
+		0x8a, 0xc0, 0xc7, 0x60, 0x29, 0xb4, 0xd5, 0x80,
+	},
+	.y = {
+		0x03, 0x74, 0xe9, 0xf5, 0x14, 0x3e, 0x56, 0x8c, 0xd2, 0x3f,
+		0x3f, 0x4d, 0x7c, 0x0d, 0x4b, 0x1e, 0x41, 0xc8, 0xcc, 0x0d,
+		0x1c, 0x6a, 0xbd, 0x5f, 0x1a, 0x46, 0xdb, 0x4c,
+	},
+	.order = {
+		0xd7, 0xc1, 0x34, 0xaa, 0x26, 0x43, 0x66, 0x86, 0x2a, 0x18,
+		0x30, 0x25, 0x75, 0xd0, 0xfb, 0x98, 0xd1, 0x16, 0xbc, 0x4b,
+		0x6d, 0xde, 0xbc, 0xa3, 0xa5, 0xa7, 0x93, 0x9f,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_brainpoolP256r1 = {
+	.p = {
+		0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66,
+		0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x72, 0x6e, 0x3b, 0xf6, 0x23,
+		0xd5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1d, 0x1f, 0x6e,
+		0x53, 0x77,
+	},
+	.a = {
+		0x7d, 0x5a, 0x09, 0x75, 0xfc, 0x2c, 0x30, 0x57, 0xee, 0xf6,
+		0x75, 0x30, 0x41, 0x7a, 0xff, 0xe7, 0xfb, 0x80, 0x55, 0xc1,
+		0x26, 0xdc, 0x5c, 0x6c, 0xe9, 0x4a, 0x4b, 0x44, 0xf3, 0x30,
+		0xb5, 0xd9,
+	},
+	.b = {
+		0x26, 0xdc, 0x5c, 0x6c, 0xe9, 0x4a, 0x4b, 0x44, 0xf3, 0x30,
+		0xb5, 0xd9, 0xbb, 0xd7, 0x7c, 0xbf, 0x95, 0x84, 0x16, 0x29,
+		0x5c, 0xf7, 0xe1, 0xce, 0x6b, 0xcc, 0xdc, 0x18, 0xff, 0x8c,
+		0x07, 0xb6,
+	},
+	.x = {
+		0x8b, 0xd2, 0xae, 0xb9, 0xcb, 0x7e, 0x57, 0xcb, 0x2c, 0x4b,
+		0x48, 0x2f, 0xfc, 0x81, 0xb7, 0xaf, 0xb9, 0xde, 0x27, 0xe1,
+		0xe3, 0xbd, 0x23, 0xc2, 0x3a, 0x44, 0x53, 0xbd, 0x9a, 0xce,
+		0x32, 0x62,
+	},
+	.y = {
+		0x54, 0x7e, 0xf8, 0x35, 0xc3, 0xda, 0xc4, 0xfd, 0x97, 0xf8,
+		0x46, 0x1a, 0x14, 0x61, 0x1d, 0xc9, 0xc2, 0x77, 0x45, 0x13,
+		0x2d, 0xed, 0x8e, 0x54, 0x5c, 0x1d, 0x54, 0xc7, 0x2f, 0x04,
+		0x69, 0x97,
+	},
+	.order = {
+		0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66,
+		0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x71, 0x8c, 0x39, 0x7a, 0xa3,
+		0xb5, 0x61, 0xa6, 0xf7, 0x90, 0x1e, 0x0e, 0x82, 0x97, 0x48,
+		0x56, 0xa7,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_brainpoolP256t1 = {
+	.p = {
+		0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66,
+		0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x72, 0x6e, 0x3b, 0xf6, 0x23,
+		0xd5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1d, 0x1f, 0x6e,
+		0x53, 0x77,
+	},
+	.a = {
+		0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66,
+		0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x72, 0x6e, 0x3b, 0xf6, 0x23,
+		0xd5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1d, 0x1f, 0x6e,
+		0x53, 0x74,
+	},
+	.b = {
+		0x66, 0x2c, 0x61, 0xc4, 0x30, 0xd8, 0x4e, 0xa4, 0xfe, 0x66,
+		0xa7, 0x73, 0x3d, 0x0b, 0x76, 0xb7, 0xbf, 0x93, 0xeb, 0xc4,
+		0xaf, 0x2f, 0x49, 0x25, 0x6a, 0xe5, 0x81, 0x01, 0xfe, 0xe9,
+		0x2b, 0x04,
+	},
+	.x = {
+		0xa3, 0xe8, 0xeb, 0x3c, 0xc1, 0xcf, 0xe7, 0xb7, 0x73, 0x22,
+		0x13, 0xb2, 0x3a, 0x65, 0x61, 0x49, 0xaf, 0xa1, 0x42, 0xc4,
+		0x7a, 0xaf, 0xbc, 0x2b, 0x79, 0xa1, 0x91, 0x56, 0x2e, 0x13,
+		0x05, 0xf4,
+	},
+	.y = {
+		0x2d, 0x99, 0x6c, 0x82, 0x34, 0x39, 0xc5, 0x6d, 0x7f, 0x7b,
+		0x22, 0xe1, 0x46, 0x44, 0x41, 0x7e, 0x69, 0xbc, 0xb6, 0xde,
+		0x39, 0xd0, 0x27, 0x00, 0x1d, 0xab, 0xe8, 0xf3, 0x5b, 0x25,
+		0xc9, 0xbe,
+	},
+	.order = {
+		0xa9, 0xfb, 0x57, 0xdb, 0xa1, 0xee, 0xa9, 0xbc, 0x3e, 0x66,
+		0x0a, 0x90, 0x9d, 0x83, 0x8d, 0x71, 0x8c, 0x39, 0x7a, 0xa3,
+		0xb5, 0x61, 0xa6, 0xf7, 0x90, 0x1e, 0x0e, 0x82, 0x97, 0x48,
+		0x56, 0xa7,
+	},
+};
+
+static const struct {
+	uint8_t p[40];
+	uint8_t a[40];
+	uint8_t b[40];
+	uint8_t x[40];
+	uint8_t y[40];
+	uint8_t order[40];
+} _EC_brainpoolP320r1 = {
+	.p = {
+		0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c,
+		0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, 0xf9, 0x8f, 0xcf, 0xa6,
+		0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93,
+		0xec, 0x28, 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x27,
+	},
+	.a = {
+		0x3e, 0xe3, 0x0b, 0x56, 0x8f, 0xba, 0xb0, 0xf8, 0x83, 0xcc,
+		0xeb, 0xd4, 0x6d, 0x3f, 0x3b, 0xb8, 0xa2, 0xa7, 0x35, 0x13,
+		0xf5, 0xeb, 0x79, 0xda, 0x66, 0x19, 0x0e, 0xb0, 0x85, 0xff,
+		0xa9, 0xf4, 0x92, 0xf3, 0x75, 0xa9, 0x7d, 0x86, 0x0e, 0xb4,
+	},
+	.b = {
+		0x52, 0x08, 0x83, 0x94, 0x9d, 0xfd, 0xbc, 0x42, 0xd3, 0xad,
+		0x19, 0x86, 0x40, 0x68, 0x8a, 0x6f, 0xe1, 0x3f, 0x41, 0x34,
+		0x95, 0x54, 0xb4, 0x9a, 0xcc, 0x31, 0xdc, 0xcd, 0x88, 0x45,
+		0x39, 0x81, 0x6f, 0x5e, 0xb4, 0xac, 0x8f, 0xb1, 0xf1, 0xa6,
+	},
+	.x = {
+		0x43, 0xbd, 0x7e, 0x9a, 0xfb, 0x53, 0xd8, 0xb8, 0x52, 0x89,
+		0xbc, 0xc4, 0x8e, 0xe5, 0xbf, 0xe6, 0xf2, 0x01, 0x37, 0xd1,
+		0x0a, 0x08, 0x7e, 0xb6, 0xe7, 0x87, 0x1e, 0x2a, 0x10, 0xa5,
+		0x99, 0xc7, 0x10, 0xaf, 0x8d, 0x0d, 0x39, 0xe2, 0x06, 0x11,
+	},
+	.y = {
+		0x14, 0xfd, 0xd0, 0x55, 0x45, 0xec, 0x1c, 0xc8, 0xab, 0x40,
+		0x93, 0x24, 0x7f, 0x77, 0x27, 0x5e, 0x07, 0x43, 0xff, 0xed,
+		0x11, 0x71, 0x82, 0xea, 0xa9, 0xc7, 0x78, 0x77, 0xaa, 0xac,
+		0x6a, 0xc7, 0xd3, 0x52, 0x45, 0xd1, 0x69, 0x2e, 0x8e, 0xe1,
+	},
+	.order = {
+		0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c,
+		0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, 0xf9, 0x8f, 0xcf, 0xa5,
+		0xb6, 0x8f, 0x12, 0xa3, 0x2d, 0x48, 0x2e, 0xc7, 0xee, 0x86,
+		0x58, 0xe9, 0x86, 0x91, 0x55, 0x5b, 0x44, 0xc5, 0x93, 0x11,
+	},
+};
+
+static const struct {
+	uint8_t p[40];
+	uint8_t a[40];
+	uint8_t b[40];
+	uint8_t x[40];
+	uint8_t y[40];
+	uint8_t order[40];
+} _EC_brainpoolP320t1 = {
+	.p = {
+		0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c,
+		0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, 0xf9, 0x8f, 0xcf, 0xa6,
+		0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93,
+		0xec, 0x28, 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x27,
+	},
+	.a = {
+		0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c,
+		0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, 0xf9, 0x8f, 0xcf, 0xa6,
+		0xf6, 0xf4, 0x0d, 0xef, 0x4f, 0x92, 0xb9, 0xec, 0x78, 0x93,
+		0xec, 0x28, 0xfc, 0xd4, 0x12, 0xb1, 0xf1, 0xb3, 0x2e, 0x24,
+	},
+	.b = {
+		0xa7, 0xf5, 0x61, 0xe0, 0x38, 0xeb, 0x1e, 0xd5, 0x60, 0xb3,
+		0xd1, 0x47, 0xdb, 0x78, 0x20, 0x13, 0x06, 0x4c, 0x19, 0xf2,
+		0x7e, 0xd2, 0x7c, 0x67, 0x80, 0xaa, 0xf7, 0x7f, 0xb8, 0xa5,
+		0x47, 0xce, 0xb5, 0xb4, 0xfe, 0xf4, 0x22, 0x34, 0x03, 0x53,
+	},
+	.x = {
+		0x92, 0x5b, 0xe9, 0xfb, 0x01, 0xaf, 0xc6, 0xfb, 0x4d, 0x3e,
+		0x7d, 0x49, 0x90, 0x01, 0x0f, 0x81, 0x34, 0x08, 0xab, 0x10,
+		0x6c, 0x4f, 0x09, 0xcb, 0x7e, 0xe0, 0x78, 0x68, 0xcc, 0x13,
+		0x6f, 0xff, 0x33, 0x57, 0xf6, 0x24, 0xa2, 0x1b, 0xed, 0x52,
+	},
+	.y = {
+		0x63, 0xba, 0x3a, 0x7a, 0x27, 0x48, 0x3e, 0xbf, 0x66, 0x71,
+		0xdb, 0xef, 0x7a, 0xbb, 0x30, 0xeb, 0xee, 0x08, 0x4e, 0x58,
+		0xa0, 0xb0, 0x77, 0xad, 0x42, 0xa5, 0xa0, 0x98, 0x9d, 0x1e,
+		0xe7, 0x1b, 0x1b, 0x9b, 0xc0, 0x45, 0x5f, 0xb0, 0xd2, 0xc3,
+	},
+	.order = {
+		0xd3, 0x5e, 0x47, 0x20, 0x36, 0xbc, 0x4f, 0xb7, 0xe1, 0x3c,
+		0x78, 0x5e, 0xd2, 0x01, 0xe0, 0x65, 0xf9, 0x8f, 0xcf, 0xa5,
+		0xb6, 0x8f, 0x12, 0xa3, 0x2d, 0x48, 0x2e, 0xc7, 0xee, 0x86,
+		0x58, 0xe9, 0x86, 0x91, 0x55, 0x5b, 0x44, 0xc5, 0x93, 0x11,
+	},
+};
+
+static const struct {
+	uint8_t p[48];
+	uint8_t a[48];
+	uint8_t b[48];
+	uint8_t x[48];
+	uint8_t y[48];
+	uint8_t order[48];
+} _EC_brainpoolP384r1 = {
+	.p = {
+		0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d,
+		0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, 0x15, 0x2f, 0x71, 0x09,
+		0xed, 0x54, 0x56, 0xb4, 0x12, 0xb1, 0xda, 0x19, 0x7f, 0xb7,
+		0x11, 0x23, 0xac, 0xd3, 0xa7, 0x29, 0x90, 0x1d, 0x1a, 0x71,
+		0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xec, 0x53,
+	},
+	.a = {
+		0x7b, 0xc3, 0x82, 0xc6, 0x3d, 0x8c, 0x15, 0x0c, 0x3c, 0x72,
+		0x08, 0x0a, 0xce, 0x05, 0xaf, 0xa0, 0xc2, 0xbe, 0xa2, 0x8e,
+		0x4f, 0xb2, 0x27, 0x87, 0x13, 0x91, 0x65, 0xef, 0xba, 0x91,
+		0xf9, 0x0f, 0x8a, 0xa5, 0x81, 0x4a, 0x50, 0x3a, 0xd4, 0xeb,
+		0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26,
+	},
+	.b = {
+		0x04, 0xa8, 0xc7, 0xdd, 0x22, 0xce, 0x28, 0x26, 0x8b, 0x39,
+		0xb5, 0x54, 0x16, 0xf0, 0x44, 0x7c, 0x2f, 0xb7, 0x7d, 0xe1,
+		0x07, 0xdc, 0xd2, 0xa6, 0x2e, 0x88, 0x0e, 0xa5, 0x3e, 0xeb,
+		0x62, 0xd5, 0x7c, 0xb4, 0x39, 0x02, 0x95, 0xdb, 0xc9, 0x94,
+		0x3a, 0xb7, 0x86, 0x96, 0xfa, 0x50, 0x4c, 0x11,
+	},
+	.x = {
+		0x1d, 0x1c, 0x64, 0xf0, 0x68, 0xcf, 0x45, 0xff, 0xa2, 0xa6,
+		0x3a, 0x81, 0xb7, 0xc1, 0x3f, 0x6b, 0x88, 0x47, 0xa3, 0xe7,
+		0x7e, 0xf1, 0x4f, 0xe3, 0xdb, 0x7f, 0xca, 0xfe, 0x0c, 0xbd,
+		0x10, 0xe8, 0xe8, 0x26, 0xe0, 0x34, 0x36, 0xd6, 0x46, 0xaa,
+		0xef, 0x87, 0xb2, 0xe2, 0x47, 0xd4, 0xaf, 0x1e,
+	},
+	.y = {
+		0x8a, 0xbe, 0x1d, 0x75, 0x20, 0xf9, 0xc2, 0xa4, 0x5c, 0xb1,
+		0xeb, 0x8e, 0x95, 0xcf, 0xd5, 0x52, 0x62, 0xb7, 0x0b, 0x29,
+		0xfe, 0xec, 0x58, 0x64, 0xe1, 0x9c, 0x05, 0x4f, 0xf9, 0x91,
+		0x29, 0x28, 0x0e, 0x46, 0x46, 0x21, 0x77, 0x91, 0x81, 0x11,
+		0x42, 0x82, 0x03, 0x41, 0x26, 0x3c, 0x53, 0x15,
+	},
+	.order = {
+		0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d,
+		0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, 0x15, 0x2f, 0x71, 0x09,
+		0xed, 0x54, 0x56, 0xb3, 0x1f, 0x16, 0x6e, 0x6c, 0xac, 0x04,
+		0x25, 0xa7, 0xcf, 0x3a, 0xb6, 0xaf, 0x6b, 0x7f, 0xc3, 0x10,
+		0x3b, 0x88, 0x32, 0x02, 0xe9, 0x04, 0x65, 0x65,
+	},
+};
+
+static const struct {
+	uint8_t p[48];
+	uint8_t a[48];
+	uint8_t b[48];
+	uint8_t x[48];
+	uint8_t y[48];
+	uint8_t order[48];
+} _EC_brainpoolP384t1 = {
+	.p = {
+		0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d,
+		0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, 0x15, 0x2f, 0x71, 0x09,
+		0xed, 0x54, 0x56, 0xb4, 0x12, 0xb1, 0xda, 0x19, 0x7f, 0xb7,
+		0x11, 0x23, 0xac, 0xd3, 0xa7, 0x29, 0x90, 0x1d, 0x1a, 0x71,
+		0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xec, 0x53,
+	},
+	.a = {
+		0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d,
+		0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, 0x15, 0x2f, 0x71, 0x09,
+		0xed, 0x54, 0x56, 0xb4, 0x12, 0xb1, 0xda, 0x19, 0x7f, 0xb7,
+		0x11, 0x23, 0xac, 0xd3, 0xa7, 0x29, 0x90, 0x1d, 0x1a, 0x71,
+		0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xec, 0x50,
+	},
+	.b = {
+		0x7f, 0x51, 0x9e, 0xad, 0xa7, 0xbd, 0xa8, 0x1b, 0xd8, 0x26,
+		0xdb, 0xa6, 0x47, 0x91, 0x0f, 0x8c, 0x4b, 0x93, 0x46, 0xed,
+		0x8c, 0xcd, 0xc6, 0x4e, 0x4b, 0x1a, 0xbd, 0x11, 0x75, 0x6d,
+		0xce, 0x1d, 0x20, 0x74, 0xaa, 0x26, 0x3b, 0x88, 0x80, 0x5c,
+		0xed, 0x70, 0x35, 0x5a, 0x33, 0xb4, 0x71, 0xee,
+	},
+	.x = {
+		0x18, 0xde, 0x98, 0xb0, 0x2d, 0xb9, 0xa3, 0x06, 0xf2, 0xaf,
+		0xcd, 0x72, 0x35, 0xf7, 0x2a, 0x81, 0x9b, 0x80, 0xab, 0x12,
+		0xeb, 0xd6, 0x53, 0x17, 0x24, 0x76, 0xfe, 0xcd, 0x46, 0x2a,
+		0xab, 0xff, 0xc4, 0xff, 0x19, 0x1b, 0x94, 0x6a, 0x5f, 0x54,
+		0xd8, 0xd0, 0xaa, 0x2f, 0x41, 0x88, 0x08, 0xcc,
+	},
+	.y = {
+		0x25, 0xab, 0x05, 0x69, 0x62, 0xd3, 0x06, 0x51, 0xa1, 0x14,
+		0xaf, 0xd2, 0x75, 0x5a, 0xd3, 0x36, 0x74, 0x7f, 0x93, 0x47,
+		0x5b, 0x7a, 0x1f, 0xca, 0x3b, 0x88, 0xf2, 0xb6, 0xa2, 0x08,
+		0xcc, 0xfe, 0x46, 0x94, 0x08, 0x58, 0x4d, 0xc2, 0xb2, 0x91,
+		0x26, 0x75, 0xbf, 0x5b, 0x9e, 0x58, 0x29, 0x28,
+	},
+	.order = {
+		0x8c, 0xb9, 0x1e, 0x82, 0xa3, 0x38, 0x6d, 0x28, 0x0f, 0x5d,
+		0x6f, 0x7e, 0x50, 0xe6, 0x41, 0xdf, 0x15, 0x2f, 0x71, 0x09,
+		0xed, 0x54, 0x56, 0xb3, 0x1f, 0x16, 0x6e, 0x6c, 0xac, 0x04,
+		0x25, 0xa7, 0xcf, 0x3a, 0xb6, 0xaf, 0x6b, 0x7f, 0xc3, 0x10,
+		0x3b, 0x88, 0x32, 0x02, 0xe9, 0x04, 0x65, 0x65,
+	},
+};
+
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_brainpoolP512r1 = {
+	.p = {
+		0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4,
+		0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07, 0xcb, 0x30, 0x8d, 0xb3,
+		0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33,
+		0x08, 0x71, 0x7d, 0x4d, 0x9b, 0x00, 0x9b, 0xc6, 0x68, 0x42,
+		0xae, 0xcd, 0xa1, 0x2a, 0xe6, 0xa3, 0x80, 0xe6, 0x28, 0x81,
+		0xff, 0x2f, 0x2d, 0x82, 0xc6, 0x85, 0x28, 0xaa, 0x60, 0x56,
+		0x58, 0x3a, 0x48, 0xf3,
+	},
+	.a = {
+		0x78, 0x30, 0xa3, 0x31, 0x8b, 0x60, 0x3b, 0x89, 0xe2, 0x32,
+		0x71, 0x45, 0xac, 0x23, 0x4c, 0xc5, 0x94, 0xcb, 0xdd, 0x8d,
+		0x3d, 0xf9, 0x16, 0x10, 0xa8, 0x34, 0x41, 0xca, 0xea, 0x98,
+		0x63, 0xbc, 0x2d, 0xed, 0x5d, 0x5a, 0xa8, 0x25, 0x3a, 0xa1,
+		0x0a, 0x2e, 0xf1, 0xc9, 0x8b, 0x9a, 0xc8, 0xb5, 0x7f, 0x11,
+		0x17, 0xa7, 0x2b, 0xf2, 0xc7, 0xb9, 0xe7, 0xc1, 0xac, 0x4d,
+		0x77, 0xfc, 0x94, 0xca,
+	},
+	.b = {
+		0x3d, 0xf9, 0x16, 0x10, 0xa8, 0x34, 0x41, 0xca, 0xea, 0x98,
+		0x63, 0xbc, 0x2d, 0xed, 0x5d, 0x5a, 0xa8, 0x25, 0x3a, 0xa1,
+		0x0a, 0x2e, 0xf1, 0xc9, 0x8b, 0x9a, 0xc8, 0xb5, 0x7f, 0x11,
+		0x17, 0xa7, 0x2b, 0xf2, 0xc7, 0xb9, 0xe7, 0xc1, 0xac, 0x4d,
+		0x77, 0xfc, 0x94, 0xca, 0xdc, 0x08, 0x3e, 0x67, 0x98, 0x40,
+		0x50, 0xb7, 0x5e, 0xba, 0xe5, 0xdd, 0x28, 0x09, 0xbd, 0x63,
+		0x80, 0x16, 0xf7, 0x23,
+	},
+	.x = {
+		0x81, 0xae, 0xe4, 0xbd, 0xd8, 0x2e, 0xd9, 0x64, 0x5a, 0x21,
+		0x32, 0x2e, 0x9c, 0x4c, 0x6a, 0x93, 0x85, 0xed, 0x9f, 0x70,
+		0xb5, 0xd9, 0x16, 0xc1, 0xb4, 0x3b, 0x62, 0xee, 0xf4, 0xd0,
+		0x09, 0x8e, 0xff, 0x3b, 0x1f, 0x78, 0xe2, 0xd0, 0xd4, 0x8d,
+		0x50, 0xd1, 0x68, 0x7b, 0x93, 0xb9, 0x7d, 0x5f, 0x7c, 0x6d,
+		0x50, 0x47, 0x40, 0x6a, 0x5e, 0x68, 0x8b, 0x35, 0x22, 0x09,
+		0xbc, 0xb9, 0xf8, 0x22,
+	},
+	.y = {
+		0x7d, 0xde, 0x38, 0x5d, 0x56, 0x63, 0x32, 0xec, 0xc0, 0xea,
+		0xbf, 0xa9, 0xcf, 0x78, 0x22, 0xfd, 0xf2, 0x09, 0xf7, 0x00,
+		0x24, 0xa5, 0x7b, 0x1a, 0xa0, 0x00, 0xc5, 0x5b, 0x88, 0x1f,
+		0x81, 0x11, 0xb2, 0xdc, 0xde, 0x49, 0x4a, 0x5f, 0x48, 0x5e,
+		0x5b, 0xca, 0x4b, 0xd8, 0x8a, 0x27, 0x63, 0xae, 0xd1, 0xca,
+		0x2b, 0x2f, 0xa8, 0xf0, 0x54, 0x06, 0x78, 0xcd, 0x1e, 0x0f,
+		0x3a, 0xd8, 0x08, 0x92,
+	},
+	.order = {
+		0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4,
+		0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07, 0xcb, 0x30, 0x8d, 0xb3,
+		0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33,
+		0x08, 0x70, 0x55, 0x3e, 0x5c, 0x41, 0x4c, 0xa9, 0x26, 0x19,
+		0x41, 0x86, 0x61, 0x19, 0x7f, 0xac, 0x10, 0x47, 0x1d, 0xb1,
+		0xd3, 0x81, 0x08, 0x5d, 0xda, 0xdd, 0xb5, 0x87, 0x96, 0x82,
+		0x9c, 0xa9, 0x00, 0x69,
+	},
+};
+
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_brainpoolP512t1 = {
+	.p = {
+		0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4,
+		0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07, 0xcb, 0x30, 0x8d, 0xb3,
+		0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33,
+		0x08, 0x71, 0x7d, 0x4d, 0x9b, 0x00, 0x9b, 0xc6, 0x68, 0x42,
+		0xae, 0xcd, 0xa1, 0x2a, 0xe6, 0xa3, 0x80, 0xe6, 0x28, 0x81,
+		0xff, 0x2f, 0x2d, 0x82, 0xc6, 0x85, 0x28, 0xaa, 0x60, 0x56,
+		0x58, 0x3a, 0x48, 0xf3,
+	},
+	.a = {
+		0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4,
+		0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07, 0xcb, 0x30, 0x8d, 0xb3,
+		0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33,
+		0x08, 0x71, 0x7d, 0x4d, 0x9b, 0x00, 0x9b, 0xc6, 0x68, 0x42,
+		0xae, 0xcd, 0xa1, 0x2a, 0xe6, 0xa3, 0x80, 0xe6, 0x28, 0x81,
+		0xff, 0x2f, 0x2d, 0x82, 0xc6, 0x85, 0x28, 0xaa, 0x60, 0x56,
+		0x58, 0x3a, 0x48, 0xf0,
+	},
+	.b = {
+		0x7c, 0xbb, 0xbc, 0xf9, 0x44, 0x1c, 0xfa, 0xb7, 0x6e, 0x18,
+		0x90, 0xe4, 0x68, 0x84, 0xea, 0xe3, 0x21, 0xf7, 0x0c, 0x0b,
+		0xcb, 0x49, 0x81, 0x52, 0x78, 0x97, 0x50, 0x4b, 0xec, 0x3e,
+		0x36, 0xa6, 0x2b, 0xcd, 0xfa, 0x23, 0x04, 0x97, 0x65, 0x40,
+		0xf6, 0x45, 0x00, 0x85, 0xf2, 0xda, 0xe1, 0x45, 0xc2, 0x25,
+		0x53, 0xb4, 0x65, 0x76, 0x36, 0x89, 0x18, 0x0e, 0xa2, 0x57,
+		0x18, 0x67, 0x42, 0x3e,
+	},
+	.x = {
+		0x64, 0x0e, 0xce, 0x5c, 0x12, 0x78, 0x87, 0x17, 0xb9, 0xc1,
+		0xba, 0x06, 0xcb, 0xc2, 0xa6, 0xfe, 0xba, 0x85, 0x84, 0x24,
+		0x58, 0xc5, 0x6d, 0xde, 0x9d, 0xb1, 0x75, 0x8d, 0x39, 0xc0,
+		0x31, 0x3d, 0x82, 0xba, 0x51, 0x73, 0x5c, 0xdb, 0x3e, 0xa4,
+		0x99, 0xaa, 0x77, 0xa7, 0xd6, 0x94, 0x3a, 0x64, 0xf7, 0xa3,
+		0xf2, 0x5f, 0xe2, 0x6f, 0x06, 0xb5, 0x1b, 0xaa, 0x26, 0x96,
+		0xfa, 0x90, 0x35, 0xda,
+	},
+	.y = {
+		0x5b, 0x53, 0x4b, 0xd5, 0x95, 0xf5, 0xaf, 0x0f, 0xa2, 0xc8,
+		0x92, 0x37, 0x6c, 0x84, 0xac, 0xe1, 0xbb, 0x4e, 0x30, 0x19,
+		0xb7, 0x16, 0x34, 0xc0, 0x11, 0x31, 0x15, 0x9c, 0xae, 0x03,
+		0xce, 0xe9, 0xd9, 0x93, 0x21, 0x84, 0xbe, 0xef, 0x21, 0x6b,
+		0xd7, 0x1d, 0xf2, 0xda, 0xdf, 0x86, 0xa6, 0x27, 0x30, 0x6e,
+		0xcf, 0xf9, 0x6d, 0xbb, 0x8b, 0xac, 0xe1, 0x98, 0xb6, 0x1e,
+		0x00, 0xf8, 0xb3, 0x32,
+	},
+	.order = {
+		0xaa, 0xdd, 0x9d, 0xb8, 0xdb, 0xe9, 0xc4, 0x8b, 0x3f, 0xd4,
+		0xe6, 0xae, 0x33, 0xc9, 0xfc, 0x07, 0xcb, 0x30, 0x8d, 0xb3,
+		0xb3, 0xc9, 0xd2, 0x0e, 0xd6, 0x63, 0x9c, 0xca, 0x70, 0x33,
+		0x08, 0x70, 0x55, 0x3e, 0x5c, 0x41, 0x4c, 0xa9, 0x26, 0x19,
+		0x41, 0x86, 0x61, 0x19, 0x7f, 0xac, 0x10, 0x47, 0x1d, 0xb1,
+		0xd3, 0x81, 0x08, 0x5d, 0xda, 0xdd, 0xb5, 0x87, 0x96, 0x82,
+		0x9c, 0xa9, 0x00, 0x69,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_FRP256v1 = {
+	.p = {
+		0xf1, 0xfd, 0x17, 0x8c, 0x0b, 0x3a, 0xd5, 0x8f, 0x10, 0x12,
+		0x6d, 0xe8, 0xce, 0x42, 0x43, 0x5b, 0x39, 0x61, 0xad, 0xbc,
+		0xab, 0xc8, 0xca, 0x6d, 0xe8, 0xfc, 0xf3, 0x53, 0xd8, 0x6e,
+		0x9c, 0x03,
+	},
+	.a = {
+		0xf1, 0xfd, 0x17, 0x8c, 0x0b, 0x3a, 0xd5, 0x8f, 0x10, 0x12,
+		0x6d, 0xe8, 0xce, 0x42, 0x43, 0x5b, 0x39, 0x61, 0xad, 0xbc,
+		0xab, 0xc8, 0xca, 0x6d, 0xe8, 0xfc, 0xf3, 0x53, 0xd8, 0x6e,
+		0x9c, 0x00,
+	},
+	.b = {
+		0xee, 0x35, 0x3f, 0xca, 0x54, 0x28, 0xa9, 0x30, 0x0d, 0x4a,
+		0xba, 0x75, 0x4a, 0x44, 0xc0, 0x0f, 0xdf, 0xec, 0x0c, 0x9a,
+		0xe4, 0xb1, 0xa1, 0x80, 0x30, 0x75, 0xed, 0x96, 0x7b, 0x7b,
+		0xb7, 0x3f,
+	},
+	.x = {
+		0xb6, 0xb3, 0xd4, 0xc3, 0x56, 0xc1, 0x39, 0xeb, 0x31, 0x18,
+		0x3d, 0x47, 0x49, 0xd4, 0x23, 0x95, 0x8c, 0x27, 0xd2, 0xdc,
+		0xaf, 0x98, 0xb7, 0x01, 0x64, 0xc9, 0x7a, 0x2d, 0xd9, 0x8f,
+		0x5c, 0xff,
+	},
+	.y = {
+		0x61, 0x42, 0xe0, 0xf7, 0xc8, 0xb2, 0x04, 0x91, 0x1f, 0x92,
+		0x71, 0xf0, 0xf3, 0xec, 0xef, 0x8c, 0x27, 0x01, 0xc3, 0x07,
+		0xe8, 0xe4, 0xc9, 0xe1, 0x83, 0x11, 0x5a, 0x15, 0x54, 0x06,
+		0x2c, 0xfb,
+	},
+	.order = {
+		0xf1, 0xfd, 0x17, 0x8c, 0x0b, 0x3a, 0xd5, 0x8f, 0x10, 0x12,
+		0x6d, 0xe8, 0xce, 0x42, 0x43, 0x5b, 0x53, 0xdc, 0x67, 0xe1,
+		0x40, 0xd2, 0xbf, 0x94, 0x1f, 0xfd, 0xd4, 0x59, 0xc6, 0xd6,
+		0x55, 0xe1,
+	},
+};
+
+#ifndef OPENSSL_NO_GOST
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_GOST_2001_Test = {
+	.p = {
+		0x80, 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,
+		0x04, 0x31,
+	},
+	.a = {
+		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, 0x07,
+	},
+	.b = {
+		0x5f, 0xbf, 0xf4, 0x98, 0xaa, 0x93, 0x8c, 0xe7, 0x39, 0xb8,
+		0xe0, 0x22, 0xfb, 0xaf, 0xef, 0x40, 0x56, 0x3f, 0x6e, 0x6a,
+		0x34, 0x72, 0xfc, 0x2a, 0x51, 0x4c, 0x0c, 0xe9, 0xda, 0xe2,
+		0x3b, 0x7e,
+	},
+	.x = {
+		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, 0x02,
+	},
+	.y = {
+		0x08, 0xe2, 0xa8, 0xa0, 0xe6, 0x51, 0x47, 0xd4, 0xbd, 0x63,
+		0x16, 0x03, 0x0e, 0x16, 0xd1, 0x9c, 0x85, 0xc9, 0x7f, 0x0a,
+		0x9c, 0xa2, 0x67, 0x12, 0x2b, 0x96, 0xab, 0xbc, 0xea, 0x7e,
+		0x8f, 0xc8,
+	},
+	.order = {
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x50, 0xfe, 0x8a, 0x18,
+		0x92, 0x97, 0x61, 0x54, 0xc5, 0x9c, 0xfc, 0x19, 0x3a, 0xcc,
+		0xf5, 0xb3,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_GOST_2001_CryptoPro_A = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xfd, 0x97,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xfd, 0x94,
+	},
+	.b = {
+		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, 0xa6,
+	},
+	.x = {
+		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, 0x01,
+	},
+	.y = {
+		0x8d, 0x91, 0xe4, 0x71, 0xe0, 0x98, 0x9c, 0xda, 0x27, 0xdf,
+		0x50, 0x5a, 0x45, 0x3f, 0x2b, 0x76, 0x35, 0x29, 0x4f, 0x2d,
+		0xdf, 0x23, 0xe3, 0xb1, 0x22, 0xac, 0xc9, 0x9c, 0x9e, 0x9f,
+		0x1e, 0x14,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6c, 0x61, 0x10, 0x70,
+		0x99, 0x5a, 0xd1, 0x00, 0x45, 0x84, 0x1b, 0x09, 0xb7, 0x61,
+		0xb8, 0x93,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_GOST_2001_CryptoPro_B = {
+	.p = {
+		0x80, 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,
+		0x0c, 0x99,
+	},
+	.a = {
+		0x80, 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,
+		0x0c, 0x96,
+	},
+	.b = {
+		0x3e, 0x1a, 0xf4, 0x19, 0xa2, 0x69, 0xa5, 0xf8, 0x66, 0xa7,
+		0xd3, 0xc2, 0x5c, 0x3d, 0xf8, 0x0a, 0xe9, 0x79, 0x25, 0x93,
+		0x73, 0xff, 0x2b, 0x18, 0x2f, 0x49, 0xd4, 0xce, 0x7e, 0x1b,
+		0xbc, 0x8b,
+	},
+	.x = {
+		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, 0x01,
+	},
+	.y = {
+		0x3f, 0xa8, 0x12, 0x43, 0x59, 0xf9, 0x66, 0x80, 0xb8, 0x3d,
+		0x1c, 0x3e, 0xb2, 0xc0, 0x70, 0xe5, 0xc5, 0x45, 0xc9, 0x85,
+		0x8d, 0x03, 0xec, 0xfb, 0x74, 0x4b, 0xf8, 0xd7, 0x17, 0x71,
+		0x7e, 0xfc,
+	},
+	.order = {
+		0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x70, 0x0c, 0xff,
+		0xf1, 0xa6, 0x24, 0xe5, 0xe4, 0x97, 0x16, 0x1b, 0xcc, 0x8a,
+		0x19, 0x8f,
+	},
+};
+
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_GOST_2001_CryptoPro_C = {
+	.p = {
+		0x9b, 0x9f, 0x60, 0x5f, 0x5a, 0x85, 0x81, 0x07, 0xab, 0x1e,
+		0xc8, 0x5e, 0x6b, 0x41, 0xc8, 0xaa, 0xcf, 0x84, 0x6e, 0x86,
+		0x78, 0x90, 0x51, 0xd3, 0x79, 0x98, 0xf7, 0xb9, 0x02, 0x2d,
+		0x75, 0x9b,
+	},
+	.a = {
+		0x9b, 0x9f, 0x60, 0x5f, 0x5a, 0x85, 0x81, 0x07, 0xab, 0x1e,
+		0xc8, 0x5e, 0x6b, 0x41, 0xc8, 0xaa, 0xcf, 0x84, 0x6e, 0x86,
+		0x78, 0x90, 0x51, 0xd3, 0x79, 0x98, 0xf7, 0xb9, 0x02, 0x2d,
+		0x75, 0x98,
+	},
+	.b = {
+		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,
+		0x80, 0x5a,
+	},
+	.x = {
+		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,
+	},
+	.y = {
+		0x41, 0xec, 0xe5, 0x57, 0x43, 0x71, 0x1a, 0x8c, 0x3c, 0xbf,
+		0x37, 0x83, 0xcd, 0x08, 0xc0, 0xee, 0x4d, 0x4d, 0xc4, 0x40,
+		0xd4, 0x64, 0x1a, 0x8f, 0x36, 0x6e, 0x55, 0x0d, 0xfd, 0xb3,
+		0xbb, 0x67,
+	},
+	.order = {
+		0x9b, 0x9f, 0x60, 0x5f, 0x5a, 0x85, 0x81, 0x07, 0xab, 0x1e,
+		0xc8, 0x5e, 0x6b, 0x41, 0xc8, 0xaa, 0x58, 0x2c, 0xa3, 0x51,
+		0x1e, 0xdd, 0xfb, 0x74, 0xf0, 0x2f, 0x3a, 0x65, 0x98, 0x98,
+		0x0b, 0xb9,
+	},
+};
+
+/*
+ * This curve is defined in two birationally equal forms: canonical and Twisted
+ * Edwards. We do calculations in canonical (Weierstrass) form.
+ */
+static const struct {
+	uint8_t p[32];
+	uint8_t a[32];
+	uint8_t b[32];
+	uint8_t x[32];
+	uint8_t y[32];
+	uint8_t order[32];
+} _EC_GOST_2012_256_TC26_A = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xfd, 0x97,
+	},
+	.a = {
+		0xc2, 0x17, 0x3f, 0x15, 0x13, 0x98, 0x16, 0x73, 0xaf, 0x48,
+		0x92, 0xc2, 0x30, 0x35, 0xa2, 0x7c, 0xe2, 0x5e, 0x20, 0x13,
+		0xbf, 0x95, 0xaa, 0x33, 0xb2, 0x2c, 0x65, 0x6f, 0x27, 0x7e,
+		0x73, 0x35,
+	},
+	.b = {
+		0x29, 0x5f, 0x9b, 0xae, 0x74, 0x28, 0xed, 0x9c, 0xcc, 0x20,
+		0xe7, 0xc3, 0x59, 0xa9, 0xd4, 0x1a, 0x22, 0xfc, 0xcd, 0x91,
+		0x08, 0xe1, 0x7b, 0xf7, 0xba, 0x93, 0x37, 0xa6, 0xf8, 0xae,
+		0x95, 0x13,
+	},
+	.x = {
+		0x91, 0xe3, 0x84, 0x43, 0xa5, 0xe8, 0x2c, 0x0d, 0x88, 0x09,
+		0x23, 0x42, 0x57, 0x12, 0xb2, 0xbb, 0x65, 0x8b, 0x91, 0x96,
+		0x93, 0x2e, 0x02, 0xc7, 0x8b, 0x25, 0x82, 0xfe, 0x74, 0x2d,
+		0xaa, 0x28,
+	},
+	.y = {
+		0x32, 0x87, 0x94, 0x23, 0xab, 0x1a, 0x03, 0x75, 0x89, 0x57,
+		0x86, 0xc4, 0xbb, 0x46, 0xe9, 0x56, 0x5f, 0xde, 0x0b, 0x53,
+		0x44, 0x76, 0x67, 0x40, 0xaf, 0x26, 0x8a, 0xdb, 0x32, 0x32,
+		0x2e, 0x5c,
+	},
+	.order = {
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xd8, 0xcd, 0xdf,
+		0xc8, 0x7b, 0x66, 0x35, 0xc1, 0x15, 0xaf, 0x55, 0x6c, 0x36,
+		0x0c, 0x67,
+	},
+};
+
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_GOST_2012_512_Test = {
+	.p = {
+		0x45, 0x31, 0xac, 0xd1, 0xfe, 0x00, 0x23, 0xc7, 0x55, 0x0d,
+		0x26, 0x7b, 0x6b, 0x2f, 0xee, 0x80, 0x92, 0x2b, 0x14, 0xb2,
+		0xff, 0xb9, 0x0f, 0x04, 0xd4, 0xeb, 0x7c, 0x09, 0xb5, 0xd2,
+		0xd1, 0x5d, 0xf1, 0xd8, 0x52, 0x74, 0x1a, 0xf4, 0x70, 0x4a,
+		0x04, 0x58, 0x04, 0x7e, 0x80, 0xe4, 0x54, 0x6d, 0x35, 0xb8,
+		0x33, 0x6f, 0xac, 0x22, 0x4d, 0xd8, 0x16, 0x64, 0xbb, 0xf5,
+		0x28, 0xbe, 0x63, 0x73,
+	},
+	.a = {
+		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, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x07,
+	},
+	.b = {
+		0x1c, 0xff, 0x08, 0x06, 0xa3, 0x11, 0x16, 0xda, 0x29, 0xd8,
+		0xcf, 0xa5, 0x4e, 0x57, 0xeb, 0x74, 0x8b, 0xc5, 0xf3, 0x77,
+		0xe4, 0x94, 0x00, 0xfd, 0xd7, 0x88, 0xb6, 0x49, 0xec, 0xa1,
+		0xac, 0x43, 0x61, 0x83, 0x40, 0x13, 0xb2, 0xad, 0x73, 0x22,
+		0x48, 0x0a, 0x89, 0xca, 0x58, 0xe0, 0xcf, 0x74, 0xbc, 0x9e,
+		0x54, 0x0c, 0x2a, 0xdd, 0x68, 0x97, 0xfa, 0xd0, 0xa3, 0x08,
+		0x4f, 0x30, 0x2a, 0xdc,
+	},
+	.x = {
+		0x24, 0xd1, 0x9c, 0xc6, 0x45, 0x72, 0xee, 0x30, 0xf3, 0x96,
+		0xbf, 0x6e, 0xbb, 0xfd, 0x7a, 0x6c, 0x52, 0x13, 0xb3, 0xb3,
+		0xd7, 0x05, 0x7c, 0xc8, 0x25, 0xf9, 0x10, 0x93, 0xa6, 0x8c,
+		0xd7, 0x62, 0xfd, 0x60, 0x61, 0x12, 0x62, 0xcd, 0x83, 0x8d,
+		0xc6, 0xb6, 0x0a, 0xa7, 0xee, 0xe8, 0x04, 0xe2, 0x8b, 0xc8,
+		0x49, 0x97, 0x7f, 0xac, 0x33, 0xb4, 0xb5, 0x30, 0xf1, 0xb1,
+		0x20, 0x24, 0x8a, 0x9a,
+	},
+	.y = {
+		0x2b, 0xb3, 0x12, 0xa4, 0x3b, 0xd2, 0xce, 0x6e, 0x0d, 0x02,
+		0x06, 0x13, 0xc8, 0x57, 0xac, 0xdd, 0xcf, 0xbf, 0x06, 0x1e,
+		0x91, 0xe5, 0xf2, 0xc3, 0xf3, 0x24, 0x47, 0xc2, 0x59, 0xf3,
+		0x9b, 0x2c, 0x83, 0xab, 0x15, 0x6d, 0x77, 0xf1, 0x49, 0x6b,
+		0xf7, 0xeb, 0x33, 0x51, 0xe1, 0xee, 0x4e, 0x43, 0xdc, 0x1a,
+		0x18, 0xb9, 0x1b, 0x24, 0x64, 0x0b, 0x6d, 0xbb, 0x92, 0xcb,
+		0x1a, 0xdd, 0x37, 0x1e,
+	},
+	.order = {
+		0x45, 0x31, 0xac, 0xd1, 0xfe, 0x00, 0x23, 0xc7, 0x55, 0x0d,
+		0x26, 0x7b, 0x6b, 0x2f, 0xee, 0x80, 0x92, 0x2b, 0x14, 0xb2,
+		0xff, 0xb9, 0x0f, 0x04, 0xd4, 0xeb, 0x7c, 0x09, 0xb5, 0xd2,
+		0xd1, 0x5d, 0xa8, 0x2f, 0x2d, 0x7e, 0xcb, 0x1d, 0xba, 0xc7,
+		0x19, 0x90, 0x5c, 0x5e, 0xec, 0xc4, 0x23, 0xf1, 0xd8, 0x6e,
+		0x25, 0xed, 0xbe, 0x23, 0xc5, 0x95, 0xd6, 0x44, 0xaa, 0xf1,
+		0x87, 0xe6, 0xe6, 0xdf,
+	},
+};
+
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_GOST_2012_512_TC26_A = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xfd, 0xc7,
+	},
+	.a = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xfd, 0xc4,
+	},
+	.b = {
+		0xe8, 0xc2, 0x50, 0x5d, 0xed, 0xfc, 0x86, 0xdd, 0xc1, 0xbd,
+		0x0b, 0x2b, 0x66, 0x67, 0xf1, 0xda, 0x34, 0xb8, 0x25, 0x74,
+		0x76, 0x1c, 0xb0, 0xe8, 0x79, 0xbd, 0x08, 0x1c, 0xfd, 0x0b,
+		0x62, 0x65, 0xee, 0x3c, 0xb0, 0x90, 0xf3, 0x0d, 0x27, 0x61,
+		0x4c, 0xb4, 0x57, 0x40, 0x10, 0xda, 0x90, 0xdd, 0x86, 0x2e,
+		0xf9, 0xd4, 0xeb, 0xee, 0x47, 0x61, 0x50, 0x31, 0x90, 0x78,
+		0x5a, 0x71, 0xc7, 0x60,
+	},
+	.x = {
+		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, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x03,
+	},
+	.y = {
+		0x75, 0x03, 0xcf, 0xe8, 0x7a, 0x83, 0x6a, 0xe3, 0xa6, 0x1b,
+		0x88, 0x16, 0xe2, 0x54, 0x50, 0xe6, 0xce, 0x5e, 0x1c, 0x93,
+		0xac, 0xf1, 0xab, 0xc1, 0x77, 0x80, 0x64, 0xfd, 0xcb, 0xef,
+		0xa9, 0x21, 0xdf, 0x16, 0x26, 0xbe, 0x4f, 0xd0, 0x36, 0xe9,
+		0x3d, 0x75, 0xe6, 0xa5, 0x0e, 0x3a, 0x41, 0xe9, 0x80, 0x28,
+		0xfe, 0x5f, 0xc2, 0x35, 0xf5, 0xb8, 0x89, 0xa5, 0x89, 0xcb,
+		0x52, 0x15, 0xf2, 0xa4,
+	},
+	.order = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0x27, 0xe6, 0x95, 0x32, 0xf4, 0x8d, 0x89, 0x11,
+		0x6f, 0xf2, 0x2b, 0x8d, 0x4e, 0x05, 0x60, 0x60, 0x9b, 0x4b,
+		0x38, 0xab, 0xfa, 0xd2, 0xb8, 0x5d, 0xca, 0xcd, 0xb1, 0x41,
+		0x1f, 0x10, 0xb2, 0x75,
+	},
+};
+
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_GOST_2012_512_TC26_B = {
+	.p = {
+		0x80, 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, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x6f,
+	},
+	.a = {
+		0x80, 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, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x6c,
+	},
+	.b = {
+		0x68, 0x7d, 0x1b, 0x45, 0x9d, 0xc8, 0x41, 0x45, 0x7e, 0x3e,
+		0x06, 0xcf, 0x6f, 0x5e, 0x25, 0x17, 0xb9, 0x7c, 0x7d, 0x61,
+		0x4a, 0xf1, 0x38, 0xbc, 0xbf, 0x85, 0xdc, 0x80, 0x6c, 0x4b,
+		0x28, 0x9f, 0x3e, 0x96, 0x5d, 0x2d, 0xb1, 0x41, 0x6d, 0x21,
+		0x7f, 0x8b, 0x27, 0x6f, 0xad, 0x1a, 0xb6, 0x9c, 0x50, 0xf7,
+		0x8b, 0xee, 0x1f, 0xa3, 0x10, 0x6e, 0xfb, 0x8c, 0xcb, 0xc7,
+		0xc5, 0x14, 0x01, 0x16,
+	},
+	.x = {
+		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, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x02,
+	},
+	.y = {
+		0x1a, 0x8f, 0x7e, 0xda, 0x38, 0x9b, 0x09, 0x4c, 0x2c, 0x07,
+		0x1e, 0x36, 0x47, 0xa8, 0x94, 0x0f, 0x3c, 0x12, 0x3b, 0x69,
+		0x75, 0x78, 0xc2, 0x13, 0xbe, 0x6d, 0xd9, 0xe6, 0xc8, 0xec,
+		0x73, 0x35, 0xdc, 0xb2, 0x28, 0xfd, 0x1e, 0xdf, 0x4a, 0x39,
+		0x15, 0x2c, 0xbc, 0xaa, 0xf8, 0xc0, 0x39, 0x88, 0x28, 0x04,
+		0x10, 0x55, 0xf9, 0x4c, 0xee, 0xec, 0x7e, 0x21, 0x34, 0x07,
+		0x80, 0xfe, 0x41, 0xbd,
+	},
+	.order = {
+		0x80, 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, 0x01, 0x49, 0xa1, 0xec, 0x14, 0x25, 0x65, 0xa5, 0x45,
+		0xac, 0xfd, 0xb7, 0x7b, 0xd9, 0xd4, 0x0c, 0xfa, 0x8b, 0x99,
+		0x67, 0x12, 0x10, 0x1b, 0xea, 0x0e, 0xc6, 0x34, 0x6c, 0x54,
+		0x37, 0x4f, 0x25, 0xbd,
+	},
+};
+
+/*
+ * This curve is defined in two birationally equal forms: canonical and Twisted
+ * Edwards. We do calculations in canonical (Weierstrass) form.
+ */
+static const struct {
+	uint8_t p[64];
+	uint8_t a[64];
+	uint8_t b[64];
+	uint8_t x[64];
+	uint8_t y[64];
+	uint8_t order[64];
+} _EC_GOST_2012_512_TC26_C = {
+	.p = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xfd, 0xc7,
+	},
+	.a = {
+		0xdc, 0x92, 0x03, 0xe5, 0x14, 0xa7, 0x21, 0x87, 0x54, 0x85,
+		0xa5, 0x29, 0xd2, 0xc7, 0x22, 0xfb, 0x18, 0x7b, 0xc8, 0x98,
+		0x0e, 0xb8, 0x66, 0x64, 0x4d, 0xe4, 0x1c, 0x68, 0xe1, 0x43,
+		0x06, 0x45, 0x46, 0xe8, 0x61, 0xc0, 0xe2, 0xc9, 0xed, 0xd9,
+		0x2a, 0xde, 0x71, 0xf4, 0x6f, 0xcf, 0x50, 0xff, 0x2a, 0xd9,
+		0x7f, 0x95, 0x1f, 0xda, 0x9f, 0x2a, 0x2e, 0xb6, 0x54, 0x6f,
+		0x39, 0x68, 0x9b, 0xd3,
+	},
+	.b = {
+		0xb4, 0xc4, 0xee, 0x28, 0xce, 0xbc, 0x6c, 0x2c, 0x8a, 0xc1,
+		0x29, 0x52, 0xcf, 0x37, 0xf1, 0x6a, 0xc7, 0xef, 0xb6, 0xa9,
+		0xf6, 0x9f, 0x4b, 0x57, 0xff, 0xda, 0x2e, 0x4f, 0x0d, 0xe5,
+		0xad, 0xe0, 0x38, 0xcb, 0xc2, 0xff, 0xf7, 0x19, 0xd2, 0xc1,
+		0x8d, 0xe0, 0x28, 0x4b, 0x8b, 0xfe, 0xf3, 0xb5, 0x2b, 0x8c,
+		0xc7, 0xa5, 0xf5, 0xbf, 0x0a, 0x3c, 0x8d, 0x23, 0x19, 0xa5,
+		0x31, 0x25, 0x57, 0xe1,
+	},
+	.x = {
+		0xe2, 0xe3, 0x1e, 0xdf, 0xc2, 0x3d, 0xe7, 0xbd, 0xeb, 0xe2,
+		0x41, 0xce, 0x59, 0x3e, 0xf5, 0xde, 0x22, 0x95, 0xb7, 0xa9,
+		0xcb, 0xae, 0xf0, 0x21, 0xd3, 0x85, 0xf7, 0x07, 0x4c, 0xea,
+		0x04, 0x3a, 0xa2, 0x72, 0x72, 0xa7, 0xae, 0x60, 0x2b, 0xf2,
+		0xa7, 0xb9, 0x03, 0x3d, 0xb9, 0xed, 0x36, 0x10, 0xc6, 0xfb,
+		0x85, 0x48, 0x7e, 0xae, 0x97, 0xaa, 0xc5, 0xbc, 0x79, 0x28,
+		0xc1, 0x95, 0x01, 0x48,
+	},
+	.y = {
+		0xf5, 0xce, 0x40, 0xd9, 0x5b, 0x5e, 0xb8, 0x99, 0xab, 0xbc,
+		0xcf, 0xf5, 0x91, 0x1c, 0xb8, 0x57, 0x79, 0x39, 0x80, 0x4d,
+		0x65, 0x27, 0x37, 0x8b, 0x8c, 0x10, 0x8c, 0x3d, 0x20, 0x90,
+		0xff, 0x9b, 0xe1, 0x8e, 0x2d, 0x33, 0xe3, 0x02, 0x1e, 0xd2,
+		0xef, 0x32, 0xd8, 0x58, 0x22, 0x42, 0x3b, 0x63, 0x04, 0xf7,
+		0x26, 0xaa, 0x85, 0x4b, 0xae, 0x07, 0xd0, 0x39, 0x6e, 0x9a,
+		0x9a, 0xdd, 0xc4, 0x0f,
+	},
+	.order = {
+		0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+		0xff, 0xff, 0xc9, 0x8c, 0xdb, 0xa4, 0x65, 0x06, 0xab, 0x00,
+		0x4c, 0x33, 0xa9, 0xff, 0x51, 0x47, 0x50, 0x2c, 0xc8, 0xed,
+		0xa9, 0xe7, 0xa7, 0x69, 0xa1, 0x26, 0x94, 0x62, 0x3c, 0xef,
+		0x47, 0xf0, 0x23, 0xed,
+	},
+};
+#endif
+
+static const struct ec_list_element {
+	const char *comment;
+	int nid;
+	int seed_len;
+	int param_len;
+	unsigned int cofactor;
+	const uint8_t *seed;
+	const uint8_t *p;
+	const uint8_t *a;
+	const uint8_t *b;
+	const uint8_t *x;
+	const uint8_t *y;
+	const uint8_t *order;
+} curve_list[] = {
+	/* secg curves */
+	{
+		.comment = "SECG/WTLS curve over a 112 bit prime field",
+		.nid = NID_secp112r1,
+		.seed_len = sizeof(_EC_SECG_PRIME_112R1.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_112R1.p),
+		.seed = _EC_SECG_PRIME_112R1.seed,
+		.p = _EC_SECG_PRIME_112R1.p,
+		.a = _EC_SECG_PRIME_112R1.a,
+		.b = _EC_SECG_PRIME_112R1.b,
+		.x = _EC_SECG_PRIME_112R1.x,
+		.y = _EC_SECG_PRIME_112R1.y,
+		.order = _EC_SECG_PRIME_112R1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG curve over a 112 bit prime field",
+		.nid = NID_secp112r2,
+		.seed_len = sizeof(_EC_SECG_PRIME_112R2.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_112R2.p),
+		.seed = _EC_SECG_PRIME_112R2.seed,
+		.p = _EC_SECG_PRIME_112R2.p,
+		.a = _EC_SECG_PRIME_112R2.a,
+		.b = _EC_SECG_PRIME_112R2.b,
+		.x = _EC_SECG_PRIME_112R2.x,
+		.y = _EC_SECG_PRIME_112R2.y,
+		.order = _EC_SECG_PRIME_112R2.order,
+		.cofactor = 4,
+	},
+	{
+		.comment = "SECG curve over a 128 bit prime field",
+		.nid = NID_secp128r1,
+		.seed_len = sizeof(_EC_SECG_PRIME_128R1.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_128R1.p),
+		.seed = _EC_SECG_PRIME_128R1.seed,
+		.p = _EC_SECG_PRIME_128R1.p,
+		.a = _EC_SECG_PRIME_128R1.a,
+		.b = _EC_SECG_PRIME_128R1.b,
+		.x = _EC_SECG_PRIME_128R1.x,
+		.y = _EC_SECG_PRIME_128R1.y,
+		.order = _EC_SECG_PRIME_128R1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG curve over a 128 bit prime field",
+		.nid = NID_secp128r2,
+		.seed_len = sizeof(_EC_SECG_PRIME_128R2.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_128R2.p),
+		.seed = _EC_SECG_PRIME_128R2.seed,
+		.p = _EC_SECG_PRIME_128R2.p,
+		.a = _EC_SECG_PRIME_128R2.a,
+		.b = _EC_SECG_PRIME_128R2.b,
+		.x = _EC_SECG_PRIME_128R2.x,
+		.y = _EC_SECG_PRIME_128R2.y,
+		.order = _EC_SECG_PRIME_128R2.order,
+		.cofactor = 4,
+	},
+	{
+		.comment = "SECG curve over a 160 bit prime field",
+		.nid = NID_secp160k1,
+		.param_len = sizeof(_EC_SECG_PRIME_160K1.p),
+		.p = _EC_SECG_PRIME_160K1.p,
+		.a = _EC_SECG_PRIME_160K1.a,
+		.b = _EC_SECG_PRIME_160K1.b,
+		.x = _EC_SECG_PRIME_160K1.x,
+		.y = _EC_SECG_PRIME_160K1.y,
+		.order = _EC_SECG_PRIME_160K1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG curve over a 160 bit prime field",
+		.nid = NID_secp160r1,
+		.seed_len = sizeof(_EC_SECG_PRIME_160R1.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_160R1.p),
+		.seed = _EC_SECG_PRIME_160R1.seed,
+		.p = _EC_SECG_PRIME_160R1.p,
+		.a = _EC_SECG_PRIME_160R1.a,
+		.b = _EC_SECG_PRIME_160R1.b,
+		.x = _EC_SECG_PRIME_160R1.x,
+		.y = _EC_SECG_PRIME_160R1.y,
+		.order = _EC_SECG_PRIME_160R1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG/WTLS curve over a 160 bit prime field",
+		.nid = NID_secp160r2,
+		.seed_len = sizeof(_EC_SECG_PRIME_160R2.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_160R2.p),
+		.seed = _EC_SECG_PRIME_160R2.seed,
+		.p = _EC_SECG_PRIME_160R2.p,
+		.a = _EC_SECG_PRIME_160R2.a,
+		.b = _EC_SECG_PRIME_160R2.b,
+		.x = _EC_SECG_PRIME_160R2.x,
+		.y = _EC_SECG_PRIME_160R2.y,
+		.order = _EC_SECG_PRIME_160R2.order,
+		.cofactor = 1,
+	},
+	/* SECG secp192r1 is the same as X9.62 prime192v1 and hence omitted */
+	{
+		.comment = "SECG curve over a 192 bit prime field",
+		.nid = NID_secp192k1,
+		.param_len = sizeof(_EC_SECG_PRIME_192K1.p),
+		.p = _EC_SECG_PRIME_192K1.p,
+		.a = _EC_SECG_PRIME_192K1.a,
+		.b = _EC_SECG_PRIME_192K1.b,
+		.x = _EC_SECG_PRIME_192K1.x,
+		.y = _EC_SECG_PRIME_192K1.y,
+		.order = _EC_SECG_PRIME_192K1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG curve over a 224 bit prime field",
+		.nid = NID_secp224k1,
+		.param_len = sizeof(_EC_SECG_PRIME_224K1.p),
+		.p = _EC_SECG_PRIME_224K1.p,
+		.a = _EC_SECG_PRIME_224K1.a,
+		.b = _EC_SECG_PRIME_224K1.b,
+		.x = _EC_SECG_PRIME_224K1.x,
+		.y = _EC_SECG_PRIME_224K1.y,
+		.order = _EC_SECG_PRIME_224K1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "NIST/SECG curve over a 224 bit prime field",
+		.nid = NID_secp224r1,
+		.seed_len = sizeof(_EC_NIST_PRIME_224.seed),
+		.param_len = sizeof(_EC_NIST_PRIME_224.p),
+		.seed = _EC_NIST_PRIME_224.seed,
+		.p = _EC_NIST_PRIME_224.p,
+		.a = _EC_NIST_PRIME_224.a,
+		.b = _EC_NIST_PRIME_224.b,
+		.x = _EC_NIST_PRIME_224.x,
+		.y = _EC_NIST_PRIME_224.y,
+		.order = _EC_NIST_PRIME_224.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG curve over a 256 bit prime field",
+		.nid = NID_secp256k1,
+		.param_len = sizeof(_EC_SECG_PRIME_256K1.p),
+		.p = _EC_SECG_PRIME_256K1.p,
+		.a = _EC_SECG_PRIME_256K1.a,
+		.b = _EC_SECG_PRIME_256K1.b,
+		.x = _EC_SECG_PRIME_256K1.x,
+		.y = _EC_SECG_PRIME_256K1.y,
+		.order = _EC_SECG_PRIME_256K1.order,
+		.cofactor = 1,
+	},
+	/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
+	{
+		.comment = "NIST/SECG curve over a 384 bit prime field",
+		.nid = NID_secp384r1,
+		.seed_len = sizeof(_EC_NIST_PRIME_384.seed),
+		.param_len = sizeof(_EC_NIST_PRIME_384.p),
+		.seed = _EC_NIST_PRIME_384.seed,
+		.p = _EC_NIST_PRIME_384.p,
+		.a = _EC_NIST_PRIME_384.a,
+		.b = _EC_NIST_PRIME_384.b,
+		.x = _EC_NIST_PRIME_384.x,
+		.y = _EC_NIST_PRIME_384.y,
+		.order = _EC_NIST_PRIME_384.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "NIST/SECG curve over a 521 bit prime field",
+		.nid = NID_secp521r1,
+		.seed_len = sizeof(_EC_NIST_PRIME_521.seed),
+		.param_len = sizeof(_EC_NIST_PRIME_521.p),
+		.seed = _EC_NIST_PRIME_521.seed,
+		.p = _EC_NIST_PRIME_521.p,
+		.a = _EC_NIST_PRIME_521.a,
+		.b = _EC_NIST_PRIME_521.b,
+		.x = _EC_NIST_PRIME_521.x,
+		.y = _EC_NIST_PRIME_521.y,
+		.order = _EC_NIST_PRIME_521.order,
+		.cofactor = 1,
+	},
+	/* X9.62 curves */
+	{
+		.comment = "NIST/X9.62/SECG curve over a 192 bit prime field",
+		.nid = NID_X9_62_prime192v1,
+		.seed_len = sizeof(_EC_NIST_PRIME_192.seed),
+		.param_len = sizeof(_EC_NIST_PRIME_192.p),
+		.seed = _EC_NIST_PRIME_192.seed,
+		.p = _EC_NIST_PRIME_192.p,
+		.a = _EC_NIST_PRIME_192.a,
+		.b = _EC_NIST_PRIME_192.b,
+		.x = _EC_NIST_PRIME_192.x,
+		.y = _EC_NIST_PRIME_192.y,
+		.order = _EC_NIST_PRIME_192.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62 curve over a 192 bit prime field",
+		.nid = NID_X9_62_prime192v2,
+		.seed_len = sizeof(_EC_X9_62_PRIME_192V2.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_192V2.p),
+		.seed = _EC_X9_62_PRIME_192V2.seed,
+		.p = _EC_X9_62_PRIME_192V2.p,
+		.a = _EC_X9_62_PRIME_192V2.a,
+		.b = _EC_X9_62_PRIME_192V2.b,
+		.x = _EC_X9_62_PRIME_192V2.x,
+		.y = _EC_X9_62_PRIME_192V2.y,
+		.order = _EC_X9_62_PRIME_192V2.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62 curve over a 192 bit prime field",
+		.nid = NID_X9_62_prime192v3,
+		.seed_len = sizeof(_EC_X9_62_PRIME_192V3.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_192V3.p),
+		.seed = _EC_X9_62_PRIME_192V3.seed,
+		.p = _EC_X9_62_PRIME_192V3.p,
+		.a = _EC_X9_62_PRIME_192V3.a,
+		.b = _EC_X9_62_PRIME_192V3.b,
+		.x = _EC_X9_62_PRIME_192V3.x,
+		.y = _EC_X9_62_PRIME_192V3.y,
+		.order = _EC_X9_62_PRIME_192V3.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62 curve over a 239 bit prime field",
+		.nid = NID_X9_62_prime239v1,
+		.seed_len = sizeof(_EC_X9_62_PRIME_239V1.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_239V1.p),
+		.seed = _EC_X9_62_PRIME_239V1.seed,
+		.p = _EC_X9_62_PRIME_239V1.p,
+		.a = _EC_X9_62_PRIME_239V1.a,
+		.b = _EC_X9_62_PRIME_239V1.b,
+		.x = _EC_X9_62_PRIME_239V1.x,
+		.y = _EC_X9_62_PRIME_239V1.y,
+		.order = _EC_X9_62_PRIME_239V1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62 curve over a 239 bit prime field",
+		.nid = NID_X9_62_prime239v2,
+		.seed_len = sizeof(_EC_X9_62_PRIME_239V2.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_239V2.p),
+		.seed = _EC_X9_62_PRIME_239V2.seed,
+		.p = _EC_X9_62_PRIME_239V2.p,
+		.a = _EC_X9_62_PRIME_239V2.a,
+		.b = _EC_X9_62_PRIME_239V2.b,
+		.x = _EC_X9_62_PRIME_239V2.x,
+		.y = _EC_X9_62_PRIME_239V2.y,
+		.order = _EC_X9_62_PRIME_239V2.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62 curve over a 239 bit prime field",
+		.nid = NID_X9_62_prime239v3,
+		.seed_len = sizeof(_EC_X9_62_PRIME_239V3.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_239V3.p),
+		.seed = _EC_X9_62_PRIME_239V3.seed,
+		.p = _EC_X9_62_PRIME_239V3.p,
+		.a = _EC_X9_62_PRIME_239V3.a,
+		.b = _EC_X9_62_PRIME_239V3.b,
+		.x = _EC_X9_62_PRIME_239V3.x,
+		.y = _EC_X9_62_PRIME_239V3.y,
+		.order = _EC_X9_62_PRIME_239V3.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "X9.62/SECG curve over a 256 bit prime field",
+		.nid = NID_X9_62_prime256v1,
+		.seed_len = sizeof(_EC_X9_62_PRIME_256V1.seed),
+		.param_len = sizeof(_EC_X9_62_PRIME_256V1.p),
+		.seed = _EC_X9_62_PRIME_256V1.seed,
+		.p = _EC_X9_62_PRIME_256V1.p,
+		.a = _EC_X9_62_PRIME_256V1.a,
+		.b = _EC_X9_62_PRIME_256V1.b,
+		.x = _EC_X9_62_PRIME_256V1.x,
+		.y = _EC_X9_62_PRIME_256V1.y,
+		.order = _EC_X9_62_PRIME_256V1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG/WTLS curve over a 112 bit prime field",
+		.nid = NID_wap_wsg_idm_ecid_wtls6,
+		.seed_len = sizeof(_EC_SECG_PRIME_112R1.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_112R1.p),
+		.seed = _EC_SECG_PRIME_112R1.seed,
+		.p = _EC_SECG_PRIME_112R1.p,
+		.a = _EC_SECG_PRIME_112R1.a,
+		.b = _EC_SECG_PRIME_112R1.b,
+		.x = _EC_SECG_PRIME_112R1.x,
+		.y = _EC_SECG_PRIME_112R1.y,
+		.order = _EC_SECG_PRIME_112R1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "SECG/WTLS curve over a 160 bit prime field",
+		.nid = NID_wap_wsg_idm_ecid_wtls7,
+		.seed_len = sizeof(_EC_SECG_PRIME_160R2.seed),
+		.param_len = sizeof(_EC_SECG_PRIME_160R2.p),
+		.seed = _EC_SECG_PRIME_160R2.seed,
+		.p = _EC_SECG_PRIME_160R2.p,
+		.a = _EC_SECG_PRIME_160R2.a,
+		.b = _EC_SECG_PRIME_160R2.b,
+		.x = _EC_SECG_PRIME_160R2.x,
+		.y = _EC_SECG_PRIME_160R2.y,
+		.order = _EC_SECG_PRIME_160R2.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "WTLS curve over a 112 bit prime field",
+		.nid = NID_wap_wsg_idm_ecid_wtls8,
+		.param_len = sizeof(_EC_WTLS_8.p),
+		.p = _EC_WTLS_8.p,
+		.a = _EC_WTLS_8.a,
+		.b = _EC_WTLS_8.b,
+		.x = _EC_WTLS_8.x,
+		.y = _EC_WTLS_8.y,
+		.order = _EC_WTLS_8.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "WTLS curve over a 160 bit prime field",
+		.nid = NID_wap_wsg_idm_ecid_wtls9,
+		.param_len = sizeof(_EC_WTLS_9.p),
+		.p = _EC_WTLS_9.p,
+		.a = _EC_WTLS_9.a,
+		.b = _EC_WTLS_9.b,
+		.x = _EC_WTLS_9.x,
+		.y = _EC_WTLS_9.y,
+		.order = _EC_WTLS_9.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "WTLS curve over a 224 bit prime field",
+		.nid = NID_wap_wsg_idm_ecid_wtls12,
+		.param_len = sizeof(_EC_WTLS_12.p),
+		.p = _EC_WTLS_12.p,
+		.a = _EC_WTLS_12.a,
+		.b = _EC_WTLS_12.b,
+		.x = _EC_WTLS_12.x,
+		.y = _EC_WTLS_12.y,
+		.order = _EC_WTLS_12.order,
+		.cofactor = 1,
+	},
+	/* RFC 5639 curves */
+	{
+		.comment = "RFC 5639 curve over a 160 bit prime field",
+		.nid = NID_brainpoolP160r1,
+		.param_len = sizeof(_EC_brainpoolP160r1.p),
+		.p = _EC_brainpoolP160r1.p,
+		.a = _EC_brainpoolP160r1.a,
+		.b = _EC_brainpoolP160r1.b,
+		.x = _EC_brainpoolP160r1.x,
+		.y = _EC_brainpoolP160r1.y,
+		.order = _EC_brainpoolP160r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 160 bit prime field",
+		.nid = NID_brainpoolP160t1,
+		.param_len = sizeof(_EC_brainpoolP160t1.p),
+		.p = _EC_brainpoolP160t1.p,
+		.a = _EC_brainpoolP160t1.a,
+		.b = _EC_brainpoolP160t1.b,
+		.x = _EC_brainpoolP160t1.x,
+		.y = _EC_brainpoolP160t1.y,
+		.order = _EC_brainpoolP160t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 192 bit prime field",
+		.nid = NID_brainpoolP192r1,
+		.param_len = sizeof(_EC_brainpoolP192r1.p),
+		.p = _EC_brainpoolP192r1.p,
+		.a = _EC_brainpoolP192r1.a,
+		.b = _EC_brainpoolP192r1.b,
+		.x = _EC_brainpoolP192r1.x,
+		.y = _EC_brainpoolP192r1.y,
+		.order = _EC_brainpoolP192r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 192 bit prime field",
+		.nid = NID_brainpoolP192t1,
+		.param_len = sizeof(_EC_brainpoolP192t1.p),
+		.p = _EC_brainpoolP192t1.p,
+		.a = _EC_brainpoolP192t1.a,
+		.b = _EC_brainpoolP192t1.b,
+		.x = _EC_brainpoolP192t1.x,
+		.y = _EC_brainpoolP192t1.y,
+		.order = _EC_brainpoolP192t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 224 bit prime field",
+		.nid = NID_brainpoolP224r1,
+		.param_len = sizeof(_EC_brainpoolP224r1.p),
+		.p = _EC_brainpoolP224r1.p,
+		.a = _EC_brainpoolP224r1.a,
+		.b = _EC_brainpoolP224r1.b,
+		.x = _EC_brainpoolP224r1.x,
+		.y = _EC_brainpoolP224r1.y,
+		.order = _EC_brainpoolP224r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 224 bit prime field",
+		.nid = NID_brainpoolP224t1,
+		.param_len = sizeof(_EC_brainpoolP224t1.p),
+		.p = _EC_brainpoolP224t1.p,
+		.a = _EC_brainpoolP224t1.a,
+		.b = _EC_brainpoolP224t1.b,
+		.x = _EC_brainpoolP224t1.x,
+		.y = _EC_brainpoolP224t1.y,
+		.order = _EC_brainpoolP224t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 256 bit prime field",
+		.nid = NID_brainpoolP256r1,
+		.param_len = sizeof(_EC_brainpoolP256r1.p),
+		.p = _EC_brainpoolP256r1.p,
+		.a = _EC_brainpoolP256r1.a,
+		.b = _EC_brainpoolP256r1.b,
+		.x = _EC_brainpoolP256r1.x,
+		.y = _EC_brainpoolP256r1.y,
+		.order = _EC_brainpoolP256r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 256 bit prime field",
+		.nid = NID_brainpoolP256t1,
+		.param_len = sizeof(_EC_brainpoolP256t1.p),
+		.p = _EC_brainpoolP256t1.p,
+		.a = _EC_brainpoolP256t1.a,
+		.b = _EC_brainpoolP256t1.b,
+		.x = _EC_brainpoolP256t1.x,
+		.y = _EC_brainpoolP256t1.y,
+		.order = _EC_brainpoolP256t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 320 bit prime field",
+		.nid = NID_brainpoolP320r1,
+		.param_len = sizeof(_EC_brainpoolP320r1.p),
+		.p = _EC_brainpoolP320r1.p,
+		.a = _EC_brainpoolP320r1.a,
+		.b = _EC_brainpoolP320r1.b,
+		.x = _EC_brainpoolP320r1.x,
+		.y = _EC_brainpoolP320r1.y,
+		.order = _EC_brainpoolP320r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 320 bit prime field",
+		.nid = NID_brainpoolP320t1,
+		.param_len = sizeof(_EC_brainpoolP320t1.p),
+		.p = _EC_brainpoolP320t1.p,
+		.a = _EC_brainpoolP320t1.a,
+		.b = _EC_brainpoolP320t1.b,
+		.x = _EC_brainpoolP320t1.x,
+		.y = _EC_brainpoolP320t1.y,
+		.order = _EC_brainpoolP320t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 384 bit prime field",
+		.nid = NID_brainpoolP384r1,
+		.param_len = sizeof(_EC_brainpoolP384r1.p),
+		.p = _EC_brainpoolP384r1.p,
+		.a = _EC_brainpoolP384r1.a,
+		.b = _EC_brainpoolP384r1.b,
+		.x = _EC_brainpoolP384r1.x,
+		.y = _EC_brainpoolP384r1.y,
+		.order = _EC_brainpoolP384r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 384 bit prime field",
+		.nid = NID_brainpoolP384t1,
+		.param_len = sizeof(_EC_brainpoolP384t1.p),
+		.p = _EC_brainpoolP384t1.p,
+		.a = _EC_brainpoolP384t1.a,
+		.b = _EC_brainpoolP384t1.b,
+		.x = _EC_brainpoolP384t1.x,
+		.y = _EC_brainpoolP384t1.y,
+		.order = _EC_brainpoolP384t1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 512 bit prime field",
+		.nid = NID_brainpoolP512r1,
+		.param_len = sizeof(_EC_brainpoolP512r1.p),
+		.p = _EC_brainpoolP512r1.p,
+		.a = _EC_brainpoolP512r1.a,
+		.b = _EC_brainpoolP512r1.b,
+		.x = _EC_brainpoolP512r1.x,
+		.y = _EC_brainpoolP512r1.y,
+		.order = _EC_brainpoolP512r1.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "RFC 5639 curve over a 512 bit prime field",
+		.nid = NID_brainpoolP512t1,
+		.param_len = sizeof(_EC_brainpoolP512t1.p),
+		.p = _EC_brainpoolP512t1.p,
+		.a = _EC_brainpoolP512t1.a,
+		.b = _EC_brainpoolP512t1.b,
+		.x = _EC_brainpoolP512t1.x,
+		.y = _EC_brainpoolP512t1.y,
+		.order = _EC_brainpoolP512t1.order,
+		.cofactor = 1,
+	},
+	/* ANSSI */
+	{
+		.comment = "FRP256v1",
+		.nid = NID_FRP256v1,
+		.param_len = sizeof(_EC_FRP256v1.p),
+		.p = _EC_FRP256v1.p,
+		.a = _EC_FRP256v1.a,
+		.b = _EC_FRP256v1.b,
+		.x = _EC_FRP256v1.x,
+		.y = _EC_FRP256v1.y,
+		.order = _EC_FRP256v1.order,
+		.cofactor = 1,
+	},
+#ifndef OPENSSL_NO_GOST
+	/* GOST R 34.10-2001 */
+	{
+		.comment = "GOST R 34.10-2001 Test Curve",
+		.nid = NID_id_GostR3410_2001_TestParamSet,
+		.param_len = sizeof(_EC_GOST_2001_Test.p),
+		.p = _EC_GOST_2001_Test.p,
+		.a = _EC_GOST_2001_Test.a,
+		.b = _EC_GOST_2001_Test.b,
+		.x = _EC_GOST_2001_Test.x,
+		.y = _EC_GOST_2001_Test.y,
+		.order = _EC_GOST_2001_Test.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2001 CryptoPro-A",
+		.nid = NID_id_GostR3410_2001_CryptoPro_A_ParamSet,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_A.p),
+		.p = _EC_GOST_2001_CryptoPro_A.p,
+		.a = _EC_GOST_2001_CryptoPro_A.a,
+		.b = _EC_GOST_2001_CryptoPro_A.b,
+		.x = _EC_GOST_2001_CryptoPro_A.x,
+		.y = _EC_GOST_2001_CryptoPro_A.y,
+		.order = _EC_GOST_2001_CryptoPro_A.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2001 CryptoPro-B",
+		.nid = NID_id_GostR3410_2001_CryptoPro_B_ParamSet,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_B.p),
+		.p = _EC_GOST_2001_CryptoPro_B.p,
+		.a = _EC_GOST_2001_CryptoPro_B.a,
+		.b = _EC_GOST_2001_CryptoPro_B.b,
+		.x = _EC_GOST_2001_CryptoPro_B.x,
+		.y = _EC_GOST_2001_CryptoPro_B.y,
+		.order = _EC_GOST_2001_CryptoPro_B.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2001 CryptoPro-C",
+		.nid = NID_id_GostR3410_2001_CryptoPro_C_ParamSet,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_C.p),
+		.p = _EC_GOST_2001_CryptoPro_C.p,
+		.a = _EC_GOST_2001_CryptoPro_C.a,
+		.b = _EC_GOST_2001_CryptoPro_C.b,
+		.x = _EC_GOST_2001_CryptoPro_C.x,
+		.y = _EC_GOST_2001_CryptoPro_C.y,
+		.order = _EC_GOST_2001_CryptoPro_C.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2001 CryptoPro-XchA",
+		.nid = NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_A.p),
+		.p = _EC_GOST_2001_CryptoPro_A.p,
+		.a = _EC_GOST_2001_CryptoPro_A.a,
+		.b = _EC_GOST_2001_CryptoPro_A.b,
+		.x = _EC_GOST_2001_CryptoPro_A.x,
+		.y = _EC_GOST_2001_CryptoPro_A.y,
+		.order = _EC_GOST_2001_CryptoPro_A.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2001 CryptoPro-XchB",
+		.nid = NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_C.p),
+		.p = _EC_GOST_2001_CryptoPro_C.p,
+		.a = _EC_GOST_2001_CryptoPro_C.a,
+		.b = _EC_GOST_2001_CryptoPro_C.b,
+		.x = _EC_GOST_2001_CryptoPro_C.x,
+		.y = _EC_GOST_2001_CryptoPro_C.y,
+		.order = _EC_GOST_2001_CryptoPro_C.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 256 TC26-A",
+		.nid = NID_id_tc26_gost_3410_12_256_paramSetA,
+		.param_len = sizeof(_EC_GOST_2012_256_TC26_A.p),
+		.p = _EC_GOST_2012_256_TC26_A.p,
+		.a = _EC_GOST_2012_256_TC26_A.a,
+		.b = _EC_GOST_2012_256_TC26_A.b,
+		.x = _EC_GOST_2012_256_TC26_A.x,
+		.y = _EC_GOST_2012_256_TC26_A.y,
+		.order = _EC_GOST_2012_256_TC26_A.order,
+		.cofactor = 4,
+	},
+	{
+		.comment = "GOST R 34.10-2012 256 TC26-B",
+		.nid = NID_id_tc26_gost_3410_12_256_paramSetB,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_A.p),
+		.p = _EC_GOST_2001_CryptoPro_A.p,
+		.a = _EC_GOST_2001_CryptoPro_A.a,
+		.b = _EC_GOST_2001_CryptoPro_A.b,
+		.x = _EC_GOST_2001_CryptoPro_A.x,
+		.y = _EC_GOST_2001_CryptoPro_A.y,
+		.order = _EC_GOST_2001_CryptoPro_A.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 256 TC26-C",
+		.nid = NID_id_tc26_gost_3410_12_256_paramSetC,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_B.p),
+		.p = _EC_GOST_2001_CryptoPro_B.p,
+		.a = _EC_GOST_2001_CryptoPro_B.a,
+		.b = _EC_GOST_2001_CryptoPro_B.b,
+		.x = _EC_GOST_2001_CryptoPro_B.x,
+		.y = _EC_GOST_2001_CryptoPro_B.y,
+		.order = _EC_GOST_2001_CryptoPro_B.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 256 TC26-D",
+		.nid = NID_id_tc26_gost_3410_12_256_paramSetD,
+		.param_len = sizeof(_EC_GOST_2001_CryptoPro_C.p),
+		.p = _EC_GOST_2001_CryptoPro_C.p,
+		.a = _EC_GOST_2001_CryptoPro_C.a,
+		.b = _EC_GOST_2001_CryptoPro_C.b,
+		.x = _EC_GOST_2001_CryptoPro_C.x,
+		.y = _EC_GOST_2001_CryptoPro_C.y,
+		.order = _EC_GOST_2001_CryptoPro_C.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 512 Test Curve",
+		.nid = NID_id_tc26_gost_3410_12_512_paramSetTest,
+		.param_len = sizeof(_EC_GOST_2012_512_Test.p),
+		.p = _EC_GOST_2012_512_Test.p,
+		.a = _EC_GOST_2012_512_Test.a,
+		.b = _EC_GOST_2012_512_Test.b,
+		.x = _EC_GOST_2012_512_Test.x,
+		.y = _EC_GOST_2012_512_Test.y,
+		.order = _EC_GOST_2012_512_Test.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 512 TC26-A",
+		.nid = NID_id_tc26_gost_3410_12_512_paramSetA,
+		.param_len = sizeof(_EC_GOST_2012_512_TC26_A.p),
+		.p = _EC_GOST_2012_512_TC26_A.p,
+		.a = _EC_GOST_2012_512_TC26_A.a,
+		.b = _EC_GOST_2012_512_TC26_A.b,
+		.x = _EC_GOST_2012_512_TC26_A.x,
+		.y = _EC_GOST_2012_512_TC26_A.y,
+		.order = _EC_GOST_2012_512_TC26_A.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 512 TC26-B",
+		.nid = NID_id_tc26_gost_3410_12_512_paramSetB,
+		.param_len = sizeof(_EC_GOST_2012_512_TC26_B.p),
+		.p = _EC_GOST_2012_512_TC26_B.p,
+		.a = _EC_GOST_2012_512_TC26_B.a,
+		.b = _EC_GOST_2012_512_TC26_B.b,
+		.x = _EC_GOST_2012_512_TC26_B.x,
+		.y = _EC_GOST_2012_512_TC26_B.y,
+		.order = _EC_GOST_2012_512_TC26_B.order,
+		.cofactor = 1,
+	},
+	{
+		.comment = "GOST R 34.10-2012 512 TC26-C",
+		.nid = NID_id_tc26_gost_3410_12_512_paramSetC,
+		.param_len = sizeof(_EC_GOST_2012_512_TC26_C.p),
+		.p = _EC_GOST_2012_512_TC26_C.p,
+		.a = _EC_GOST_2012_512_TC26_C.a,
+		.b = _EC_GOST_2012_512_TC26_C.b,
+		.x = _EC_GOST_2012_512_TC26_C.x,
+		.y = _EC_GOST_2012_512_TC26_C.y,
+		.order = _EC_GOST_2012_512_TC26_C.order,
+		.cofactor = 4,
+	},
+#endif
+};
+
+#define CURVE_LIST_LENGTH (sizeof(curve_list) / sizeof(curve_list[0]))
+
+static EC_GROUP *
+ec_group_new_from_data(const struct ec_list_element *curve)
+{
+	EC_GROUP *group = NULL, *ret = NULL;
+	EC_POINT *generator = NULL;
+	BN_CTX *ctx = NULL;
+	BIGNUM *p, *a, *b, *x, *y, *order, *cofactor;
+
+	if ((ctx = BN_CTX_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	BN_CTX_start(ctx);
+
+	if ((p = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((a = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((b = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((x = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((y = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((order = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((cofactor = BN_CTX_get(ctx)) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	if (BN_bin2bn(curve->p, curve->param_len, p) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (BN_bin2bn(curve->a, curve->param_len, a) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (BN_bin2bn(curve->b, curve->param_len, b) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	EC_GROUP_set_curve_name(group, curve->nid);
+
+	if ((generator = EC_POINT_new(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (BN_bin2bn(curve->x, curve->param_len, x) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (BN_bin2bn(curve->y, curve->param_len, y) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (BN_bin2bn(curve->order, curve->param_len, order) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (!BN_set_word(cofactor, curve->cofactor)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!EC_GROUP_set_generator(group, generator, order, cofactor)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if (curve->seed != NULL) {
+		if (!EC_GROUP_set_seed(group, curve->seed, curve->seed_len)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+	}
+
+	ret = group;
+	group = NULL;
+
+ err:
+	EC_GROUP_free(group);
+	EC_POINT_free(generator);
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return ret;
+}
+
+EC_GROUP *
+EC_GROUP_new_by_curve_name(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 ec_group_new_from_data(&curve_list[i]);
+	}
+
+	ECerror(EC_R_UNKNOWN_GROUP);
+	return NULL;
+}
+LCRYPTO_ALIAS(EC_GROUP_new_by_curve_name);
+
+size_t
+EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems)
+{
+	size_t i, min;
+
+	if (r == NULL || nitems == 0)
+		return CURVE_LIST_LENGTH;
+
+	min = nitems < CURVE_LIST_LENGTH ? nitems : CURVE_LIST_LENGTH;
+
+	for (i = 0; i < min; i++) {
+		r[i].nid = curve_list[i].nid;
+		r[i].comment = curve_list[i].comment;
+	}
+
+	return CURVE_LIST_LENGTH;
+}
+LCRYPTO_ALIAS(EC_get_builtin_curves);
+
+static const struct {
+	const char *name;
+	int nid;
+} 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 < sizeof(nist_curves) / sizeof(nist_curves[0]); i++) {
+		if (nist_curves[i].nid == nid)
+			return nist_curves[i].name;
+	}
+
+	return NULL;
+}
+LCRYPTO_ALIAS(EC_curve_nid2nist);
+
+int
+EC_curve_nist2nid(const char *name)
+{
+	size_t i;
+
+	for (i = 0; i < sizeof(nist_curves) / sizeof(nist_curves[0]); i++) {
+		if (strcmp(nist_curves[i].name, name) == 0)
+			return nist_curves[i].nid;
+	}
+
+	return NID_undef;
+}
+LCRYPTO_ALIAS(EC_curve_nist2nid);
diff --git a/crypto/ec/ec_cvt.c b/crypto/ec/ec_cvt.c
new file mode 100644
index 0000000..5b196dd
--- /dev/null
+++ b/crypto/ec/ec_cvt.c
@@ -0,0 +1,103 @@
+/* $OpenBSD: ec_cvt.c,v 1.12 2023/07/07 13:54:45 beck Exp $ */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include 
+
+#include 
+#include "ec_local.h"
+
+static EC_GROUP *
+ec_group_new_curve(const EC_METHOD *method, const BIGNUM *p, const BIGNUM *a,
+    const BIGNUM *b, BN_CTX *ctx)
+{
+	EC_GROUP *group;
+
+	if ((group = EC_GROUP_new(method)) == NULL)
+		goto err;
+
+	if (!EC_GROUP_set_curve(group, p, a, b, ctx))
+		goto err;
+
+	return group;
+
+ err:
+	EC_GROUP_free(group);
+
+	return NULL;
+}
+
+EC_GROUP *
+EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, const BIGNUM *b,
+    BN_CTX *ctx)
+{
+	return ec_group_new_curve(EC_GFp_mont_method(), p, a, b, ctx);
+}
+LCRYPTO_ALIAS(EC_GROUP_new_curve_GFp);
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
new file mode 100644
index 0000000..9f2253d
--- /dev/null
+++ b/crypto/ec/ec_err.c
@@ -0,0 +1,151 @@
+/* $OpenBSD: ec_err.c,v 1.18 2023/07/28 09:28:37 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_EC,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_EC,0,reason)
+
+static ERR_STRING_DATA EC_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA EC_str_reasons[] =
+{
+	{ERR_REASON(EC_R_ASN1_ERROR), "asn1 error"},
+	{ERR_REASON(EC_R_ASN1_UNKNOWN_FIELD), "asn1 unknown field"},
+	{ERR_REASON(EC_R_BAD_SIGNATURE), "bad signature"},
+	{ERR_REASON(EC_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"},
+	{ERR_REASON(EC_R_BUFFER_TOO_SMALL), "buffer too small"},
+	{ERR_REASON(EC_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"},
+	{ERR_REASON(EC_R_D2I_ECPKPARAMETERS_FAILURE), "d2i ecpkparameters failure"},
+	{ERR_REASON(EC_R_DECODE_ERROR), "decode error"},
+	{ERR_REASON(EC_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"},
+	{ERR_REASON(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE), "ec group new by name failure"},
+	{ERR_REASON(EC_R_FIELD_TOO_LARGE), "field too large"},
+	{ERR_REASON(EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
+	{ERR_REASON(EC_R_GROUP2PKPARAMETERS_FAILURE), "group2pkparameters failure"},
+	{ERR_REASON(EC_R_I2D_ECPKPARAMETERS_FAILURE), "i2d ecpkparameters failure"},
+	{ERR_REASON(EC_R_INCOMPATIBLE_OBJECTS), "incompatible objects"},
+	{ERR_REASON(EC_R_INVALID_ARGUMENT), "invalid argument"},
+	{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT), "invalid compressed point"},
+	{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT), "invalid compression bit"},
+	{ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"},
+	{ERR_REASON(EC_R_INVALID_DIGEST), "invalid digest"},
+	{ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
+	{ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"},
+	{ERR_REASON(EC_R_INVALID_FIELD), "invalid field"},
+	{ERR_REASON(EC_R_INVALID_FORM), "invalid form"},
+	{ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"},
+	{ERR_REASON(EC_R_INVALID_KEY), "invalid key"},
+	{ERR_REASON(EC_R_INVALID_OUTPUT_LENGTH), "invalid output length"},
+	{ERR_REASON(EC_R_INVALID_PEER_KEY), "invalid peer key"},
+	{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
+	{ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
+	{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"},
+	{ERR_REASON(EC_R_KDF_FAILED), "kdf failed"},
+	{ERR_REASON(EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
+	{ERR_REASON(EC_R_KEY_TRUNCATION), "key would be truncated"},
+	{ERR_REASON(EC_R_KEYS_NOT_SET), "keys not set"},
+	{ERR_REASON(EC_R_MISSING_PARAMETERS), "missing parameters"},
+	{ERR_REASON(EC_R_MISSING_PRIVATE_KEY), "missing private key"},
+	{ERR_REASON(EC_R_NEED_NEW_SETUP_VALUES), "need new setup values"},
+	{ERR_REASON(EC_R_NOT_A_NIST_PRIME), "not a NIST prime"},
+	{ERR_REASON(EC_R_NOT_A_SUPPORTED_NIST_PRIME), "not a supported NIST prime"},
+	{ERR_REASON(EC_R_NOT_IMPLEMENTED), "not implemented"},
+	{ERR_REASON(EC_R_NOT_INITIALIZED), "not initialized"},
+	{ERR_REASON(EC_R_NO_FIELD_MOD), "no field mod"},
+	{ERR_REASON(EC_R_NO_PARAMETERS_SET), "no parameters set"},
+	{ERR_REASON(EC_R_PASSED_NULL_PARAMETER), "passed null parameter"},
+	{ERR_REASON(EC_R_PEER_KEY_ERROR), "peer key error"},
+	{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE), "pkparameters2group failure"},
+	{ERR_REASON(EC_R_POINT_ARITHMETIC_FAILURE), "point arithmetic failure"},
+	{ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"},
+	{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"},
+	{ERR_REASON(EC_R_SHARED_INFO_ERROR), "shared info error"},
+	{ERR_REASON(EC_R_SLOT_FULL), "slot full"},
+	{ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
+	{ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
+	{ERR_REASON(EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
+	{ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"},
+	{ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"},
+	{ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"},
+	{ERR_REASON(EC_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"},
+	{ERR_REASON(EC_R_WRONG_ORDER), "wrong order"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_EC_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+
+	if (ERR_func_error_string(EC_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, EC_str_functs);
+		ERR_load_strings(0, EC_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_EC_strings);
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
new file mode 100644
index 0000000..d9ddd5d
--- /dev/null
+++ b/crypto/ec/ec_key.c
@@ -0,0 +1,553 @@
+/* $OpenBSD: ec_key.c,v 1.37 2023/08/03 18:53:56 tb Exp $ */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions originally developed by SUN MICROSYSTEMS, INC., and
+ * contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+
+EC_KEY *
+EC_KEY_new(void)
+{
+	return EC_KEY_new_method(NULL);
+}
+LCRYPTO_ALIAS(EC_KEY_new);
+
+EC_KEY *
+EC_KEY_new_by_curve_name(int nid)
+{
+	EC_KEY *ret = EC_KEY_new();
+	if (ret == NULL)
+		return NULL;
+	ret->group = EC_GROUP_new_by_curve_name(nid);
+	if (ret->group == NULL) {
+		EC_KEY_free(ret);
+		return NULL;
+	}
+	if (ret->meth->set_group != NULL &&
+	    ret->meth->set_group(ret, ret->group) == 0) {
+		EC_KEY_free(ret);
+		return NULL;
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_new_by_curve_name);
+
+void
+EC_KEY_free(EC_KEY *r)
+{
+	int i;
+
+	if (r == NULL)
+		return;
+
+	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
+	if (i > 0)
+		return;
+
+	if (r->meth != NULL && r->meth->finish != NULL)
+		r->meth->finish(r);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(r->engine);
+#endif
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EC_KEY, r, &r->ex_data);
+
+	EC_GROUP_free(r->group);
+	EC_POINT_free(r->pub_key);
+	BN_free(r->priv_key);
+
+	freezero(r, sizeof(EC_KEY));
+}
+LCRYPTO_ALIAS(EC_KEY_free);
+
+EC_KEY *
+EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
+{
+	if (dest == NULL || src == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+	}
+	if (src->meth != dest->meth) {
+		if (dest->meth != NULL && dest->meth->finish != NULL)
+			dest->meth->finish(dest);
+#ifndef OPENSSL_NO_ENGINE
+		if (ENGINE_finish(dest->engine) == 0)
+			return 0;
+		dest->engine = NULL;
+#endif
+	}
+	/* copy the parameters */
+	if (src->group) {
+		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);
+		if (dest->group == NULL)
+			return NULL;
+		if (!EC_GROUP_copy(dest->group, src->group))
+			return NULL;
+	}
+	/* copy the public key */
+	if (src->pub_key && src->group) {
+		EC_POINT_free(dest->pub_key);
+		dest->pub_key = EC_POINT_new(src->group);
+		if (dest->pub_key == NULL)
+			return NULL;
+		if (!EC_POINT_copy(dest->pub_key, src->pub_key))
+			return NULL;
+	}
+	/* copy the private key */
+	if (src->priv_key) {
+		if (dest->priv_key == NULL) {
+			dest->priv_key = BN_new();
+			if (dest->priv_key == NULL)
+				return NULL;
+		}
+		if (!bn_copy(dest->priv_key, src->priv_key))
+			return NULL;
+	}
+
+	/* copy the rest */
+	dest->enc_flag = src->enc_flag;
+	dest->conv_form = src->conv_form;
+	dest->version = src->version;
+	dest->flags = src->flags;
+
+	if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
+	    &((EC_KEY *)src)->ex_data))	/* XXX const */
+		return NULL;
+
+	if (src->meth != dest->meth) {
+#ifndef OPENSSL_NO_ENGINE
+		if (src->engine != NULL && ENGINE_init(src->engine) == 0)
+			return 0;
+		dest->engine = src->engine;
+#endif
+		dest->meth = src->meth;
+	}
+
+	if (src->meth != NULL && src->meth->copy != NULL &&
+	    src->meth->copy(dest, src) == 0)
+		return 0;
+
+	return dest;
+}
+LCRYPTO_ALIAS(EC_KEY_copy);
+
+EC_KEY *
+EC_KEY_dup(const EC_KEY *ec_key)
+{
+	EC_KEY *ret;
+
+	if ((ret = EC_KEY_new_method(ec_key->engine)) == NULL)
+		return NULL;
+	if (EC_KEY_copy(ret, ec_key) == NULL) {
+		EC_KEY_free(ret);
+		return NULL;
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_dup);
+
+int
+EC_KEY_up_ref(EC_KEY *r)
+{
+	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_EC);
+	return ((i > 1) ? 1 : 0);
+}
+LCRYPTO_ALIAS(EC_KEY_up_ref);
+
+int
+EC_KEY_set_ex_data(EC_KEY *r, int idx, void *arg)
+{
+	return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
+}
+LCRYPTO_ALIAS(EC_KEY_set_ex_data);
+
+void *
+EC_KEY_get_ex_data(const EC_KEY *r, int idx)
+{
+	return CRYPTO_get_ex_data(&r->ex_data, idx);
+}
+LCRYPTO_ALIAS(EC_KEY_get_ex_data);
+
+int
+EC_KEY_generate_key(EC_KEY *eckey)
+{
+	if (eckey->meth->keygen != NULL)
+		return eckey->meth->keygen(eckey);
+	ECerror(EC_R_NOT_IMPLEMENTED);
+	return 0;
+}
+LCRYPTO_ALIAS(EC_KEY_generate_key);
+
+int
+ec_key_gen(EC_KEY *eckey)
+{
+	BIGNUM *priv_key = NULL;
+	EC_POINT *pub_key = NULL;
+	const BIGNUM *order;
+	int ret = 0;
+
+	if (eckey == NULL || eckey->group == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if ((priv_key = BN_new()) == NULL)
+		goto err;
+	if ((pub_key = EC_POINT_new(eckey->group)) == NULL)
+		goto err;
+
+	if ((order = EC_GROUP_get0_order(eckey->group)) == NULL)
+		goto err;
+	if (!bn_rand_interval(priv_key, 1, order))
+		goto err;
+	if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, NULL))
+		goto err;
+
+	BN_free(eckey->priv_key);
+	eckey->priv_key = priv_key;
+	priv_key = NULL;
+
+	EC_POINT_free(eckey->pub_key);
+	eckey->pub_key = pub_key;
+	pub_key = NULL;
+
+	ret = 1;
+
+ err:
+	EC_POINT_free(pub_key);
+	BN_free(priv_key);
+
+	return ret;
+}
+
+int
+EC_KEY_check_key(const EC_KEY *eckey)
+{
+	BN_CTX *ctx = NULL;
+	EC_POINT *point = NULL;
+	const BIGNUM *order;
+	int ret = 0;
+
+	if (eckey == NULL || eckey->group == NULL || eckey->pub_key == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if (EC_POINT_is_at_infinity(eckey->group, eckey->pub_key) > 0) {
+		ECerror(EC_R_POINT_AT_INFINITY);
+		goto err;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	if ((point = EC_POINT_new(eckey->group)) == NULL)
+		goto err;
+
+	/* Ensure public key is on the elliptic curve. */
+	if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) {
+		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+	}
+
+	/* Ensure public key multiplied by the order is the point at infinity. */
+	if ((order = EC_GROUP_get0_order(eckey->group)) == NULL) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+	if (!EC_POINT_mul(eckey->group, point, NULL, eckey->pub_key, order, ctx)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (EC_POINT_is_at_infinity(eckey->group, point) <= 0) {
+		ECerror(EC_R_WRONG_ORDER);
+		goto err;
+	}
+
+	/*
+	 * If the private key is present, ensure that the private key multiplied
+	 * by the generator matches the public key.
+	 */
+	if (eckey->priv_key != NULL) {
+		if (BN_cmp(eckey->priv_key, order) >= 0) {
+			ECerror(EC_R_WRONG_ORDER);
+			goto err;
+		}
+		if (!EC_POINT_mul(eckey->group, point, eckey->priv_key, NULL,
+		    NULL, ctx)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		if (EC_POINT_cmp(eckey->group, point, eckey->pub_key,
+		    ctx) != 0) {
+			ECerror(EC_R_INVALID_PRIVATE_KEY);
+			goto err;
+		}
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_free(ctx);
+	EC_POINT_free(point);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_check_key);
+
+int
+EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y)
+{
+	BN_CTX *ctx = NULL;
+	EC_POINT *point = NULL;
+	BIGNUM *tx, *ty;
+	int ret = 0;
+
+	if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((tx = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((ty = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if ((point = EC_POINT_new(key->group)) == NULL)
+		goto err;
+
+	if (!EC_POINT_set_affine_coordinates(key->group, point, x, y, ctx))
+		goto err;
+	if (!EC_POINT_get_affine_coordinates(key->group, point, tx, ty, ctx))
+		goto err;
+
+	/*
+	 * Check if retrieved coordinates match originals: if not values are
+	 * out of range.
+	 */
+	if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
+		ECerror(EC_R_COORDINATES_OUT_OF_RANGE);
+		goto err;
+	}
+	if (!EC_KEY_set_public_key(key, point))
+		goto err;
+	if (EC_KEY_check_key(key) == 0)
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	EC_POINT_free(point);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_set_public_key_affine_coordinates);
+
+const EC_GROUP *
+EC_KEY_get0_group(const EC_KEY *key)
+{
+	return key->group;
+}
+LCRYPTO_ALIAS(EC_KEY_get0_group);
+
+int
+EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group)
+{
+	if (key->meth->set_group != NULL &&
+	    key->meth->set_group(key, group) == 0)
+		return 0;
+	EC_GROUP_free(key->group);
+	key->group = EC_GROUP_dup(group);
+	return (key->group == NULL) ? 0 : 1;
+}
+LCRYPTO_ALIAS(EC_KEY_set_group);
+
+const BIGNUM *
+EC_KEY_get0_private_key(const EC_KEY *key)
+{
+	return key->priv_key;
+}
+LCRYPTO_ALIAS(EC_KEY_get0_private_key);
+
+int
+EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key)
+{
+	if (key->meth->set_private != NULL &&
+	    key->meth->set_private(key, priv_key) == 0)
+		return 0;
+
+	BN_free(key->priv_key);
+	if ((key->priv_key = BN_dup(priv_key)) == NULL)
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(EC_KEY_set_private_key);
+
+const EC_POINT *
+EC_KEY_get0_public_key(const EC_KEY *key)
+{
+	return key->pub_key;
+}
+LCRYPTO_ALIAS(EC_KEY_get0_public_key);
+
+int
+EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub_key)
+{
+	if (key->meth->set_public != NULL &&
+	    key->meth->set_public(key, pub_key) == 0)
+		return 0;
+
+	EC_POINT_free(key->pub_key);
+	if ((key->pub_key = EC_POINT_dup(pub_key, key->group)) == NULL)
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(EC_KEY_set_public_key);
+
+unsigned int
+EC_KEY_get_enc_flags(const EC_KEY *key)
+{
+	return key->enc_flag;
+}
+LCRYPTO_ALIAS(EC_KEY_get_enc_flags);
+
+void
+EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
+{
+	key->enc_flag = flags;
+}
+LCRYPTO_ALIAS(EC_KEY_set_enc_flags);
+
+point_conversion_form_t
+EC_KEY_get_conv_form(const EC_KEY *key)
+{
+	return key->conv_form;
+}
+LCRYPTO_ALIAS(EC_KEY_get_conv_form);
+
+void
+EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform)
+{
+	key->conv_form = cform;
+	if (key->group != NULL)
+		EC_GROUP_set_point_conversion_form(key->group, cform);
+}
+LCRYPTO_ALIAS(EC_KEY_set_conv_form);
+
+void
+EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
+{
+	if (key->group != NULL)
+		EC_GROUP_set_asn1_flag(key->group, flag);
+}
+LCRYPTO_ALIAS(EC_KEY_set_asn1_flag);
+
+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);
+}
+LCRYPTO_ALIAS(EC_KEY_precompute_mult);
+
+int
+EC_KEY_get_flags(const EC_KEY *key)
+{
+	return key->flags;
+}
+LCRYPTO_ALIAS(EC_KEY_get_flags);
+
+void
+EC_KEY_set_flags(EC_KEY *key, int flags)
+{
+	key->flags |= flags;
+}
+LCRYPTO_ALIAS(EC_KEY_set_flags);
+
+void
+EC_KEY_clear_flags(EC_KEY *key, int flags)
+{
+	key->flags &= ~flags;
+}
+LCRYPTO_ALIAS(EC_KEY_clear_flags);
diff --git a/crypto/ec/ec_kmeth.c b/crypto/ec/ec_kmeth.c
new file mode 100644
index 0000000..38aca00
--- /dev/null
+++ b/crypto/ec/ec_kmeth.c
@@ -0,0 +1,353 @@
+/*	$OpenBSD: ec_kmeth.c,v 1.12 2023/07/28 09:28:37 tb Exp $	*/
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+#include "ecdsa_local.h"
+
+static const EC_KEY_METHOD openssl_ec_key_method = {
+	.name = "OpenSSL EC_KEY method",
+	.flags = 0,
+
+	.init = NULL,
+	.finish = NULL,
+	.copy = NULL,
+
+	.set_group = NULL,
+	.set_private = NULL,
+	.set_public = NULL,
+
+	.keygen = ec_key_gen,
+	.compute_key = ecdh_compute_key,
+
+	.sign = ecdsa_sign,
+	.sign_setup = ecdsa_sign_setup,
+	.sign_sig = ecdsa_sign_sig,
+
+	.verify = ecdsa_verify,
+	.verify_sig = ecdsa_verify_sig,
+};
+
+const EC_KEY_METHOD *default_ec_key_meth = &openssl_ec_key_method;
+
+const EC_KEY_METHOD *
+EC_KEY_OpenSSL(void)
+{
+	return &openssl_ec_key_method;
+}
+LCRYPTO_ALIAS(EC_KEY_OpenSSL);
+
+const EC_KEY_METHOD *
+EC_KEY_get_default_method(void)
+{
+	return default_ec_key_meth;
+}
+LCRYPTO_ALIAS(EC_KEY_get_default_method);
+
+void
+EC_KEY_set_default_method(const EC_KEY_METHOD *meth)
+{
+	if (meth == NULL)
+		default_ec_key_meth = &openssl_ec_key_method;
+	else
+		default_ec_key_meth = meth;
+}
+LCRYPTO_ALIAS(EC_KEY_set_default_method);
+
+const EC_KEY_METHOD *
+EC_KEY_get_method(const EC_KEY *key)
+{
+	return key->meth;
+}
+LCRYPTO_ALIAS(EC_KEY_get_method);
+
+int
+EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth)
+{
+	void (*finish)(EC_KEY *key) = key->meth->finish;
+
+	if (finish != NULL)
+		finish(key);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(key->engine);
+	key->engine = NULL;
+#endif
+
+	key->meth = meth;
+	if (meth->init != NULL)
+		return meth->init(key);
+	return 1;
+}
+LCRYPTO_ALIAS(EC_KEY_set_method);
+
+EC_KEY *
+EC_KEY_new_method(ENGINE *engine)
+{
+	EC_KEY *ret;
+
+	if ((ret = calloc(1, sizeof(EC_KEY))) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	ret->meth = EC_KEY_get_default_method();
+#ifndef OPENSSL_NO_ENGINE
+	if (engine != NULL) {
+		if (!ENGINE_init(engine)) {
+			ECerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		ret->engine = engine;
+	} else
+		ret->engine = ENGINE_get_default_EC();
+	if (ret->engine) {
+		ret->meth = ENGINE_get_EC(ret->engine);
+		if (ret->meth == NULL) {
+			ECerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+	}
+#endif
+	ret->version = 1;
+	ret->flags = 0;
+	ret->group = NULL;
+	ret->pub_key = NULL;
+	ret->priv_key = NULL;
+	ret->enc_flag = 0;
+	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
+	ret->references = 1;
+
+	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
+		goto err;
+	if (ret->meth->init != NULL && ret->meth->init(ret) == 0)
+		goto err;
+
+	return ret;
+
+ err:
+	EC_KEY_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(EC_KEY_new_method);
+
+EC_KEY_METHOD *
+EC_KEY_METHOD_new(const EC_KEY_METHOD *meth)
+{
+	EC_KEY_METHOD *ret;
+
+	if ((ret = calloc(1, sizeof(*meth))) == NULL)
+		return NULL;
+	if (meth != NULL)
+		*ret = *meth;
+	ret->flags |= EC_KEY_METHOD_DYNAMIC;
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_new);
+
+void
+EC_KEY_METHOD_free(EC_KEY_METHOD *meth)
+{
+	if (meth == NULL)
+		return;
+	if (meth->flags & EC_KEY_METHOD_DYNAMIC)
+		free(meth);
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_free);
+
+void
+EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth,
+    int (*init)(EC_KEY *key),
+    void (*finish)(EC_KEY *key),
+    int (*copy)(EC_KEY *dest, const EC_KEY *src),
+    int (*set_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (*set_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (*set_public)(EC_KEY *key, const EC_POINT *pub_key))
+{
+	meth->init = init;
+	meth->finish = finish;
+	meth->copy = copy;
+	meth->set_group = set_group;
+	meth->set_private = set_private;
+	meth->set_public = set_public;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_set_init);
+
+void
+EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, int (*keygen)(EC_KEY *key))
+{
+	meth->keygen = keygen;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_set_keygen);
+
+void
+EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth,
+    int (*ckey)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
+        const EC_KEY *ecdh))
+{
+	meth->compute_key = ckey;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_set_compute_key);
+
+void
+EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth,
+    int (*sign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(*sign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv,
+	const BIGNUM *in_r, EC_KEY *eckey))
+{
+	meth->sign = sign;
+	meth->sign_setup = sign_setup;
+	meth->sign_sig = sign_sig;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_set_sign);
+
+void
+EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth,
+    int (*verify)(int type, const unsigned char *dgst, int dgst_len,
+	const unsigned char *sigbuf, int sig_len, EC_KEY *eckey),
+    int (*verify_sig)(const unsigned char *dgst, int dgst_len,
+	const ECDSA_SIG *sig, EC_KEY *eckey))
+{
+	meth->verify = verify;
+	meth->verify_sig = verify_sig;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_set_verify);
+
+
+void
+EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth,
+    int (**pinit)(EC_KEY *key),
+    void (**pfinish)(EC_KEY *key),
+    int (**pcopy)(EC_KEY *dest, const EC_KEY *src),
+    int (**pset_group)(EC_KEY *key, const EC_GROUP *grp),
+    int (**pset_private)(EC_KEY *key, const BIGNUM *priv_key),
+    int (**pset_public)(EC_KEY *key, const EC_POINT *pub_key))
+{
+	if (pinit != NULL)
+		*pinit = meth->init;
+	if (pfinish != NULL)
+		*pfinish = meth->finish;
+	if (pcopy != NULL)
+		*pcopy = meth->copy;
+	if (pset_group != NULL)
+		*pset_group = meth->set_group;
+	if (pset_private != NULL)
+		*pset_private = meth->set_private;
+	if (pset_public != NULL)
+		*pset_public = meth->set_public;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_get_init);
+
+void
+EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth,
+    int (**pkeygen)(EC_KEY *key))
+{
+	if (pkeygen != NULL)
+		*pkeygen = meth->keygen;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_get_keygen);
+
+void
+EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth,
+    int (**pck)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
+        const EC_KEY *ecdh))
+{
+	if (pck != NULL)
+		*pck = meth->compute_key;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_get_compute_key);
+
+void
+EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth,
+    int (**psign)(int type, const unsigned char *dgst,
+	int dlen, unsigned char *sig, unsigned int *siglen,
+	const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey),
+    int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in,
+	BIGNUM **kinvp, BIGNUM **rp),
+    ECDSA_SIG *(**psign_sig)(const unsigned char *dgst,
+	int dgst_len, const BIGNUM *in_kinv, const BIGNUM *in_r,
+	EC_KEY *eckey))
+{
+	if (psign != NULL)
+		*psign = meth->sign;
+	if (psign_setup != NULL)
+		*psign_setup = meth->sign_setup;
+	if (psign_sig != NULL)
+		*psign_sig = meth->sign_sig;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_get_sign);
+
+void
+EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth,
+    int (**pverify)(int type, const unsigned char *dgst, int dgst_len,
+	const unsigned char *sigbuf, int sig_len, EC_KEY *eckey),
+    int (**pverify_sig)(const unsigned char *dgst, int dgst_len,
+	const ECDSA_SIG *sig, EC_KEY *eckey))
+{
+	if (pverify != NULL)
+		*pverify = meth->verify;
+	if (pverify_sig != NULL)
+		*pverify_sig = meth->verify_sig;
+}
+LCRYPTO_ALIAS(EC_KEY_METHOD_get_verify);
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
new file mode 100644
index 0000000..00a4a70
--- /dev/null
+++ b/crypto/ec/ec_lib.c
@@ -0,0 +1,1331 @@
+/* $OpenBSD: ec_lib.c,v 1.65 2023/07/25 06:57:26 tb Exp $ */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Binary polynomial ECC support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+
+/* functions for EC_GROUP objects */
+
+EC_GROUP *
+EC_GROUP_new(const EC_METHOD *meth)
+{
+	EC_GROUP *ret;
+
+	if (meth == NULL) {
+		ECerror(EC_R_SLOT_FULL);
+		return NULL;
+	}
+	if (meth->group_init == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return NULL;
+	}
+	ret = malloc(sizeof *ret);
+	if (ret == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	ret->meth = meth;
+
+	ret->generator = NULL;
+	BN_init(&ret->order);
+	BN_init(&ret->cofactor);
+
+	ret->curve_name = 0;
+	ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
+	ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
+
+	ret->seed = NULL;
+	ret->seed_len = 0;
+
+	if (!meth->group_init(ret)) {
+		free(ret);
+		return NULL;
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(EC_GROUP_new);
+
+
+void
+EC_GROUP_free(EC_GROUP *group)
+{
+	if (group == NULL)
+		return;
+
+	if (group->meth->group_finish != NULL)
+		group->meth->group_finish(group);
+
+	EC_POINT_free(group->generator);
+	BN_free(&group->order);
+	BN_free(&group->cofactor);
+
+	freezero(group->seed, group->seed_len);
+	freezero(group, sizeof *group);
+}
+LCRYPTO_ALIAS(EC_GROUP_free);
+
+void
+EC_GROUP_clear_free(EC_GROUP *group)
+{
+	EC_GROUP_free(group);
+}
+
+int
+EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
+{
+	if (dest->meth->group_copy == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+	}
+	if (dest->meth != src->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+	}
+	if (dest == src)
+		return 1;
+
+	if (src->generator != NULL) {
+		if (dest->generator == NULL) {
+			dest->generator = EC_POINT_new(dest);
+			if (dest->generator == NULL)
+				return 0;
+		}
+		if (!EC_POINT_copy(dest->generator, src->generator))
+			return 0;
+	} else {
+		/* src->generator == NULL */
+		EC_POINT_free(dest->generator);
+		dest->generator = NULL;
+	}
+
+	if (!bn_copy(&dest->order, &src->order))
+		return 0;
+	if (!bn_copy(&dest->cofactor, &src->cofactor))
+		return 0;
+
+	dest->curve_name = src->curve_name;
+	dest->asn1_flag = src->asn1_flag;
+	dest->asn1_form = src->asn1_form;
+
+	if (src->seed) {
+		free(dest->seed);
+		dest->seed = malloc(src->seed_len);
+		if (dest->seed == NULL)
+			return 0;
+		memcpy(dest->seed, src->seed, src->seed_len);
+		dest->seed_len = src->seed_len;
+	} else {
+		free(dest->seed);
+		dest->seed = NULL;
+		dest->seed_len = 0;
+	}
+
+
+	return dest->meth->group_copy(dest, src);
+}
+LCRYPTO_ALIAS(EC_GROUP_copy);
+
+
+EC_GROUP *
+EC_GROUP_dup(const EC_GROUP *a)
+{
+	EC_GROUP *t = NULL;
+
+	if ((a != NULL) && ((t = EC_GROUP_new(a->meth)) != NULL) &&
+	    (!EC_GROUP_copy(t, a))) {
+		EC_GROUP_free(t);
+		t = NULL;
+	}
+	return t;
+}
+LCRYPTO_ALIAS(EC_GROUP_dup);
+
+
+const EC_METHOD *
+EC_GROUP_method_of(const EC_GROUP *group)
+{
+	return group->meth;
+}
+LCRYPTO_ALIAS(EC_GROUP_method_of);
+
+
+int
+EC_METHOD_get_field_type(const EC_METHOD *meth)
+{
+	return meth->field_type;
+}
+LCRYPTO_ALIAS(EC_METHOD_get_field_type);
+
+/*
+ * If there is a user-provided cofactor, sanity check and use it. Otherwise
+ * try computing the cofactor from generator order n and field cardinality q.
+ * This works for all curves of cryptographic interest.
+ *
+ * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q)
+ *
+ * So: h_min = (q + 1 - 2*sqrt(q)) / n and h_max = (q + 1 + 2*sqrt(q)) / n and
+ * therefore h_max - h_min = 4*sqrt(q) / n. So if n > 4*sqrt(q) holds, there is
+ * only one possible value for h:
+ *
+ *	h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
+ *
+ * Otherwise, zero cofactor and return success.
+ */
+static int
+ec_set_cofactor(EC_GROUP *group, const BIGNUM *in_cofactor)
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *cofactor;
+	int ret = 0;
+
+	BN_zero(&group->cofactor);
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+	if ((cofactor = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Unfortunately, the cofactor is an optional field in many standards.
+	 * Internally, the library uses a 0 cofactor as a marker for "unknown
+	 * cofactor".  So accept in_cofactor == NULL or in_cofactor >= 0.
+	 */
+	if (in_cofactor != NULL && !BN_is_zero(in_cofactor)) {
+		if (BN_is_negative(in_cofactor)) {
+			ECerror(EC_R_UNKNOWN_COFACTOR);
+			goto err;
+		}
+		if (!bn_copy(cofactor, in_cofactor))
+			goto err;
+		goto done;
+	}
+
+	/*
+	 * If the cofactor is too large, we cannot guess it and default to zero.
+	 * The RHS of below is a strict overestimate of log(4 * sqrt(q)).
+	 */
+	if (BN_num_bits(&group->order) <=
+	    (BN_num_bits(&group->field) + 1) / 2 + 3)
+		goto done;
+
+	/*
+	 * Compute
+	 *     h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor.
+	 */
+
+	/* h = n/2 */
+	if (!BN_rshift1(cofactor, &group->order))
+		goto err;
+	/* h = 1 + n/2 */
+	if (!BN_add_word(cofactor, 1))
+		goto err;
+	/* h = q + 1 + n/2 */
+	if (!BN_add(cofactor, cofactor, &group->field))
+		goto err;
+	/* h = (q + 1 + n/2) / n */
+	if (!BN_div_ct(cofactor, NULL, cofactor, &group->order, ctx))
+		goto err;
+
+ done:
+	/* Use Hasse's theorem to bound the cofactor. */
+	if (BN_num_bits(cofactor) > BN_num_bits(&group->field) + 1) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+
+	if (!bn_copy(&group->cofactor, cofactor))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return ret;
+}
+
+int
+EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
+    const BIGNUM *order, const BIGNUM *cofactor)
+{
+	if (generator == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+
+	/* Require group->field >= 1. */
+	if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) {
+		ECerror(EC_R_INVALID_FIELD);
+		return 0;
+	}
+
+	/*
+	 * Require order > 1 and enforce an upper bound of at most one bit more
+	 * than the field cardinality due to Hasse's theorem.
+	 */
+	if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 ||
+	    BN_num_bits(order) > BN_num_bits(&group->field) + 1) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		return 0;
+	}
+
+	if (group->generator == NULL) {
+		group->generator = EC_POINT_new(group);
+		if (group->generator == NULL)
+			return 0;
+	}
+	if (!EC_POINT_copy(group->generator, generator))
+		return 0;
+
+	if (!bn_copy(&group->order, order))
+		return 0;
+
+	if (!ec_set_cofactor(group, cofactor))
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_generator);
+
+
+const EC_POINT *
+EC_GROUP_get0_generator(const EC_GROUP *group)
+{
+	return group->generator;
+}
+LCRYPTO_ALIAS(EC_GROUP_get0_generator);
+
+int
+EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
+{
+	if (!bn_copy(order, &group->order))
+		return 0;
+
+	return !BN_is_zero(order);
+}
+LCRYPTO_ALIAS(EC_GROUP_get_order);
+
+const BIGNUM *
+EC_GROUP_get0_order(const EC_GROUP *group)
+{
+	return &group->order;
+}
+
+int
+EC_GROUP_order_bits(const EC_GROUP *group)
+{
+	return group->meth->group_order_bits(group);
+}
+LCRYPTO_ALIAS(EC_GROUP_order_bits);
+
+int
+EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
+{
+	if (!bn_copy(cofactor, &group->cofactor))
+		return 0;
+
+	return !BN_is_zero(&group->cofactor);
+}
+LCRYPTO_ALIAS(EC_GROUP_get_cofactor);
+
+
+void
+EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
+{
+	group->curve_name = nid;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_curve_name);
+
+
+int
+EC_GROUP_get_curve_name(const EC_GROUP *group)
+{
+	return group->curve_name;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_curve_name);
+
+
+void
+EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
+{
+	group->asn1_flag = flag;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_asn1_flag);
+
+
+int
+EC_GROUP_get_asn1_flag(const EC_GROUP *group)
+{
+	return group->asn1_flag;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_asn1_flag);
+
+
+void
+EC_GROUP_set_point_conversion_form(EC_GROUP *group,
+    point_conversion_form_t form)
+{
+	group->asn1_form = form;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_point_conversion_form);
+
+
+point_conversion_form_t
+EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
+{
+	return group->asn1_form;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_point_conversion_form);
+
+
+size_t
+EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
+{
+	if (group->seed) {
+		free(group->seed);
+		group->seed = NULL;
+		group->seed_len = 0;
+	}
+	if (!len || !p)
+		return 1;
+
+	if ((group->seed = malloc(len)) == NULL)
+		return 0;
+	memcpy(group->seed, p, len);
+	group->seed_len = len;
+
+	return len;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_seed);
+
+
+unsigned char *
+EC_GROUP_get0_seed(const EC_GROUP *group)
+{
+	return group->seed;
+}
+LCRYPTO_ALIAS(EC_GROUP_get0_seed);
+
+
+size_t
+EC_GROUP_get_seed_len(const EC_GROUP *group)
+{
+	return group->seed_len;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_seed_len);
+
+int
+EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+    const BIGNUM *b, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->group_set_curve == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	ret = group->meth->group_set_curve(group, p, a, b, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_GROUP_set_curve);
+
+int
+EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
+    BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->group_get_curve == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	ret = group->meth->group_get_curve(group, p, a, b, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_GROUP_get_curve);
+
+int
+EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+    const BIGNUM *b, BN_CTX *ctx)
+{
+	return EC_GROUP_set_curve(group, p, a, b, ctx);
+}
+
+int
+EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
+    BN_CTX *ctx)
+{
+	return EC_GROUP_get_curve(group, p, a, b, ctx);
+}
+
+int
+EC_GROUP_get_degree(const EC_GROUP *group)
+{
+	if (group->meth->group_get_degree == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+	}
+	return group->meth->group_get_degree(group);
+}
+LCRYPTO_ALIAS(EC_GROUP_get_degree);
+
+
+int
+EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->group_check_discriminant == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	ret = group->meth->group_check_discriminant(group, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_GROUP_check_discriminant);
+
+
+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;
+	BN_CTX *ctx_new = NULL;
+
+	/* 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)))
+		return 1;
+	/* compare the curve name (if present in both) */
+	if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
+	    EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
+		return 1;
+
+	if (!ctx)
+		ctx_new = ctx = BN_CTX_new();
+	if (!ctx)
+		return -1;
+
+	BN_CTX_start(ctx);
+	if ((a1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((a2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((a3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * XXX This approach assumes that the external representation of
+	 * curves over the same field type is the same.
+	 */
+	if (!a->meth->group_get_curve(a, a1, a2, a3, 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))
+		r = 1;
+
+	/* XXX EC_POINT_cmp() assumes that the methods are equal */
+	if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
+		EC_GROUP_get0_generator(b), ctx))
+		r = 1;
+
+	if (!r) {
+		/* compare the order and cofactor */
+		if (!EC_GROUP_get_order(a, a1, ctx) ||
+		    !EC_GROUP_get_order(b, b1, ctx) ||
+		    !EC_GROUP_get_cofactor(a, a2, ctx) ||
+		    !EC_GROUP_get_cofactor(b, b2, ctx))
+			goto err;
+		if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
+			r = 1;
+	}
+	BN_CTX_end(ctx);
+	if (ctx_new)
+		BN_CTX_free(ctx);
+
+	return r;
+
+ err:
+	BN_CTX_end(ctx);
+	if (ctx_new)
+		BN_CTX_free(ctx);
+	return -1;
+}
+LCRYPTO_ALIAS(EC_GROUP_cmp);
+
+/*
+ * Coordinate blinding for EC_POINT.
+ *
+ * The underlying EC_METHOD can optionally implement this function:
+ * underlying implementations should return 0 on errors, or 1 on success.
+ *
+ * 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)
+{
+	if (group->meth->blind_coordinates == NULL)
+		return 1;
+
+	return group->meth->blind_coordinates(group, p, ctx);
+}
+
+EC_POINT *
+EC_POINT_new(const EC_GROUP *group)
+{
+	EC_POINT *ret;
+
+	if (group == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+	}
+	if (group->meth->point_init == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return NULL;
+	}
+	ret = malloc(sizeof *ret);
+	if (ret == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	ret->meth = group->meth;
+
+	if (!ret->meth->point_init(ret)) {
+		free(ret);
+		return NULL;
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_new);
+
+void
+EC_POINT_free(EC_POINT *point)
+{
+	if (point == NULL)
+		return;
+
+	if (point->meth->point_finish != NULL)
+		point->meth->point_finish(point);
+
+	freezero(point, sizeof *point);
+}
+LCRYPTO_ALIAS(EC_POINT_free);
+
+void
+EC_POINT_clear_free(EC_POINT *point)
+{
+	EC_POINT_free(point);
+}
+
+int
+EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
+{
+	if (dest->meth->point_copy == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+	}
+	if (dest->meth != src->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+	}
+	if (dest == src)
+		return 1;
+	return dest->meth->point_copy(dest, src);
+}
+LCRYPTO_ALIAS(EC_POINT_copy);
+
+EC_POINT *
+EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
+{
+	EC_POINT *t;
+	int r;
+
+	if (a == NULL)
+		return NULL;
+
+	t = EC_POINT_new(group);
+	if (t == NULL)
+		return (NULL);
+	r = EC_POINT_copy(t, a);
+	if (!r) {
+		EC_POINT_free(t);
+		return NULL;
+	} else
+		return t;
+}
+LCRYPTO_ALIAS(EC_POINT_dup);
+
+const EC_METHOD *
+EC_POINT_method_of(const EC_POINT *point)
+{
+	return point->meth;
+}
+LCRYPTO_ALIAS(EC_POINT_method_of);
+
+int
+EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
+{
+	if (group->meth->point_set_to_infinity == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+	}
+	return group->meth->point_set_to_infinity(group, point);
+}
+LCRYPTO_ALIAS(EC_POINT_set_to_infinity);
+
+int
+EC_POINT_set_Jprojective_coordinates(const EC_GROUP *group, EC_POINT *point,
+    const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_set_Jprojective_coordinates == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	if (!group->meth->point_set_Jprojective_coordinates(group, point,
+	    x, y, z, ctx))
+		goto err;
+
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
+		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+
+int
+EC_POINT_get_Jprojective_coordinates(const EC_GROUP *group,
+    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_get_Jprojective_coordinates == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->point_get_Jprojective_coordinates(group, point,
+	    x, y, z, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+
+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)
+{
+	return EC_POINT_set_Jprojective_coordinates(group, point, x, y, z, ctx);
+}
+
+int
+EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
+    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
+{
+	return EC_POINT_get_Jprojective_coordinates(group, point, x, y, z, ctx);
+}
+
+int
+EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
+    const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_set_affine_coordinates == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
+		goto err;
+
+	if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
+		ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_set_affine_coordinates);
+
+int
+EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+    const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
+{
+	return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
+}
+
+int
+EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
+    BIGNUM *x, BIGNUM *y, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_get_affine_coordinates == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_get_affine_coordinates);
+
+int
+EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
+    BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
+{
+	return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
+}
+
+int
+EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+    const EC_POINT *b, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->add == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != r->meth || group->meth != a->meth ||
+	    group->meth != b->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->add(group, r, a, b, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_add);
+
+int
+EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
+    BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->dbl == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != r->meth || r->meth != a->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->dbl(group, r, a, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_dbl);
+
+int
+EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->invert == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != a->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->invert(group, a, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_invert);
+
+int
+EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
+{
+	if (group->meth->is_at_infinity == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		return 0;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+	}
+	return group->meth->is_at_infinity(group, point);
+}
+LCRYPTO_ALIAS(EC_POINT_is_at_infinity);
+
+int
+EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
+    BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = -1;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->is_on_curve == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->is_on_curve(group, point, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_is_on_curve);
+
+int
+EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
+    BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = -1;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_cmp == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != a->meth || a->meth != b->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->point_cmp(group, a, b, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_cmp);
+
+int
+EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->make_affine == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->make_affine(group, point, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_make_affine);
+
+int
+EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
+    BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	size_t i;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->points_make_affine == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	for (i = 0; i < num; i++) {
+		if (group->meth != points[i]->meth) {
+			ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+			goto err;
+		}
+	}
+	ret = group->meth->points_make_affine(group, num, points, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINTs_make_affine);
+
+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_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	/* Only num == 0 and num == 1 is supported. */
+	if (group->meth->mul_generator_ct == NULL ||
+	    group->meth->mul_single_ct == NULL ||
+	    group->meth->mul_double_nonct == NULL ||
+	    num > 1) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+
+	if (num == 1 && points != NULL && scalars != NULL) {
+		/* Either bP or aG + bP, this is sane. */
+		ret = EC_POINT_mul(group, r, scalar, points[0], scalars[0], ctx);
+	} else if (scalar != NULL && points == NULL && scalars == NULL) {
+		/* aG, this is sane */
+		ret = EC_POINT_mul(group, r, scalar, NULL, NULL, ctx);
+	} else {
+		/* anything else is an error */
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINTs_mul);
+
+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_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->mul_generator_ct == NULL ||
+	    group->meth->mul_single_ct == NULL ||
+	    group->meth->mul_double_nonct == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+
+	if (g_scalar != NULL && point == NULL && p_scalar == NULL) {
+		/*
+		 * In this case we want to compute g_scalar * GeneratorPoint:
+		 * this codepath is reached most prominently by (ephemeral) key
+		 * generation of EC cryptosystems (i.e. ECDSA keygen and sign
+		 * setup, ECDH keygen/first half), where the scalar is always
+		 * secret. This is why we ignore if BN_FLG_CONSTTIME is actually
+		 * set and we always call the constant time version.
+		 */
+		ret = group->meth->mul_generator_ct(group, r, g_scalar, ctx);
+	} else if (g_scalar == NULL && point != NULL && p_scalar != NULL) {
+		/*
+		 * In this case we want to compute p_scalar * GenericPoint:
+		 * this codepath is reached most prominently by the second half
+		 * of ECDH, where the secret scalar is multiplied by the peer's
+		 * public point. To protect the secret scalar, we ignore if
+		 * BN_FLG_CONSTTIME is actually set and we always call the
+		 * constant time version.
+		 */
+		ret = group->meth->mul_single_ct(group, r, p_scalar, point, ctx);
+	} else if (g_scalar != NULL && point != NULL && p_scalar != NULL) {
+		/*
+		 * In this case we want to compute
+		 *   g_scalar * GeneratorPoint + p_scalar * GenericPoint:
+		 * this codepath is reached most prominently by ECDSA signature
+		 * verification. So we call the non-ct version.
+		 */
+		ret = group->meth->mul_double_nonct(group, r, g_scalar,
+		    p_scalar, point, ctx);
+	} else {
+		/* Anything else is an error. */
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_mul);
+
+int
+EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx_in)
+{
+	return 1;
+}
+LCRYPTO_ALIAS(EC_GROUP_precompute_mult);
+
+int
+EC_GROUP_have_precompute_mult(const EC_GROUP *group)
+{
+	return 0;
+}
+LCRYPTO_ALIAS(EC_GROUP_have_precompute_mult);
+
+int
+ec_group_simple_order_bits(const EC_GROUP *group)
+{
+	/* XXX change group->order to a pointer? */
+#if 0
+	if (group->order == NULL)
+		return 0;
+#endif
+	return BN_num_bits(&group->order);
+}
+
+EC_KEY *
+ECParameters_dup(EC_KEY *key)
+{
+	const unsigned char *p;
+	unsigned char *der = NULL;
+	EC_KEY *dup = NULL;
+	int len;
+
+	if (key == NULL)
+		return NULL;
+
+	if ((len = i2d_ECParameters(key, &der)) <= 0)
+		return NULL;
+
+	p = der;
+	dup = d2i_ECParameters(NULL, &p, len);
+	freezero(der, len);
+
+	return dup;
+}
+LCRYPTO_ALIAS(ECParameters_dup);
diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h
new file mode 100644
index 0000000..3252eeb
--- /dev/null
+++ b/crypto/ec/ec_local.h
@@ -0,0 +1,365 @@
+/* $OpenBSD: ec_local.h,v 1.26 2023/07/28 15:50:33 tb Exp $ */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * The elliptic curve binary polynomial software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+
+__BEGIN_HIDDEN_DECLS
+
+#if defined(__SUNPRO_C)
+# if __SUNPRO_C >= 0x520
+# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE)
+# endif
+#endif
+
+struct ec_method_st {
+	int field_type;
+
+	int (*group_init)(EC_GROUP *);
+	void (*group_finish)(EC_GROUP *);
+	int (*group_copy)(EC_GROUP *, const EC_GROUP *);
+
+	int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
+	    const BIGNUM *b, BN_CTX *);
+	int (*group_get_curve)(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
+	    BIGNUM *b, BN_CTX *);
+
+	int (*group_get_degree)(const EC_GROUP *);
+	int (*group_order_bits)(const EC_GROUP *);
+	int (*group_check_discriminant)(const EC_GROUP *, BN_CTX *);
+
+	int (*point_init)(EC_POINT *);
+	void (*point_finish)(EC_POINT *);
+	int (*point_copy)(EC_POINT *, const EC_POINT *);
+
+	int (*point_set_to_infinity)(const EC_GROUP *, EC_POINT *);
+	int (*point_set_Jprojective_coordinates)(const EC_GROUP *, EC_POINT *,
+	    const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+	int (*point_get_Jprojective_coordinates)(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 *);
+	int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
+	    BIGNUM *x, BIGNUM *y, BN_CTX *);
+	int (*point_set_compressed_coordinates)(const EC_GROUP *, EC_POINT *,
+	    const BIGNUM *x, int y_bit, BN_CTX *);
+
+	size_t (*point2oct)(const EC_GROUP *, const EC_POINT *,
+	    point_conversion_form_t form, unsigned char *buf, size_t len,
+	    BN_CTX *);
+	int (*oct2point)(const EC_GROUP *, EC_POINT *, const unsigned char *buf,
+	    size_t len, BN_CTX *);
+
+	int (*add)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
+	    const EC_POINT *b, BN_CTX *);
+	int (*dbl)(const EC_GROUP *, EC_POINT *r, const EC_POINT *a, BN_CTX *);
+	int (*invert)(const EC_GROUP *, EC_POINT *, BN_CTX *);
+
+	int (*is_at_infinity)(const EC_GROUP *, const EC_POINT *);
+	int (*is_on_curve)(const EC_GROUP *, const EC_POINT *, BN_CTX *);
+	int (*point_cmp)(const EC_GROUP *, const EC_POINT *a, const EC_POINT *b,
+	    BN_CTX *);
+
+	int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *);
+	int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[],
+	    BN_CTX *);
+
+	int (*mul_generator_ct)(const EC_GROUP *, EC_POINT *r,
+	    const BIGNUM *scalar, BN_CTX *);
+	int (*mul_single_ct)(const EC_GROUP *group, EC_POINT *r,
+	    const BIGNUM *scalar, const EC_POINT *point, BN_CTX *);
+	int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r,
+	    const BIGNUM *g_scalar, const BIGNUM *p_scalar,
+	    const EC_POINT *point, BN_CTX *);
+
+	/*
+	 * Internal methods.
+	 */
+
+	/*
+	 * These can be used by 'add' and 'dbl' so that the same implementations
+	 * of point operations can be used with different optimized versions of
+	 * expensive field operations.
+	 */
+	int (*field_mul)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+	    const BIGNUM *b, BN_CTX *);
+	int (*field_sqr)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+	    BN_CTX *);
+	int (*field_div)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+	    const BIGNUM *b, BN_CTX *);
+
+	/* Encode to and decode from other forms (e.g. Montgomery). */
+	int (*field_encode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+	    BN_CTX *);
+	int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
+	    BN_CTX *);
+
+	int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
+	int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p,
+	    BN_CTX *ctx);
+} /* EC_METHOD */;
+
+struct ec_group_st {
+	/*
+	 * Methods and members exposed via the public API.
+	 */
+
+	const EC_METHOD *meth;
+
+	EC_POINT *generator;	/* Optional */
+	BIGNUM order;
+	BIGNUM cofactor;
+
+	int curve_name;		/* Optional NID for named curve. */
+
+	/* ASN.1 encoding controls. */
+	int asn1_flag;
+	point_conversion_form_t asn1_form;
+
+	/* Optional seed for parameters (appears in ASN.1). */
+	unsigned char *seed;
+	size_t seed_len;
+
+	/*
+	 * Internal methods and members. Handled by the method functions, even
+	 * if they appear to be generic.
+	 */
+
+	/*
+	 * Field specification. For GF(p) this is the modulus; for GF(2^m),
+	 * this is the irreducible polynomial defining the field.
+	 */
+	BIGNUM field;
+
+	/*
+	 * Curve coefficients. In characteristic > 3, the curve is defined by a
+	 * Weierstrass equation of the form y^2 = x^3 + a*x + b.
+	 */
+	BIGNUM a, b;
+
+	/* Enables optimized point arithmetics for special case. */
+	int a_is_minus3;
+
+	/* Montgomery context and values used by EC_GFp_mont_method. */
+	BN_MONT_CTX *mont_ctx;
+	BIGNUM *mont_one;
+
+	int (*field_mod_func)(BIGNUM *, const BIGNUM *, const BIGNUM *,
+	    BN_CTX *);
+} /* EC_GROUP */;
+
+struct ec_key_st {
+	const EC_KEY_METHOD *meth;
+	ENGINE	*engine;
+
+	int version;
+
+	EC_GROUP *group;
+
+	EC_POINT *pub_key;
+	BIGNUM	 *priv_key;
+
+	unsigned int enc_flag;
+	point_conversion_form_t conv_form;
+
+	int	references;
+	int	flags;
+
+	CRYPTO_EX_DATA ex_data;
+} /* EC_KEY */;
+
+struct ec_point_st {
+	const EC_METHOD *meth;
+
+	/*
+	 * All members except 'meth' are handled by the method functions,
+	 * even if they appear generic.
+	 */
+
+	/*
+	 * Jacobian projective coordinates: (X, Y, Z) represents (X/Z^2, Y/Z^3)
+	 * if Z != 0
+	 */
+	BIGNUM X;
+	BIGNUM Y;
+	BIGNUM Z;
+	int Z_is_one; /* enable optimized point arithmetics for special case */
+} /* EC_POINT */;
+
+/* 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 *);
+
+/* method functions in ecp_smpl.c */
+int ec_GFp_simple_group_init(EC_GROUP *);
+void ec_GFp_simple_group_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 *);
+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(const EC_GROUP *, EC_POINT *,
+    const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *);
+int ec_GFp_simple_get_Jprojective_coordinates(const EC_GROUP *,
+    const EC_POINT *, BIGNUM *x, BIGNUM *y, BIGNUM *z, 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_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
+int ec_GFp_simple_mul_generator_ct(const EC_GROUP *, EC_POINT *r, const BIGNUM *scalar, BN_CTX *);
+int ec_GFp_simple_mul_single_ct(const EC_GROUP *, EC_POINT *r, const BIGNUM *scalar,
+	const EC_POINT *point, BN_CTX *);
+int ec_GFp_simple_mul_double_nonct(const EC_GROUP *, EC_POINT *r, const BIGNUM *g_scalar,
+	const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *);
+
+int ec_group_simple_order_bits(const EC_GROUP *group);
+int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
+
+/* EC_METHOD definitions */
+
+struct ec_key_method_st {
+	const char *name;
+	int32_t flags;
+	int (*init)(EC_KEY *key);
+	void (*finish)(EC_KEY *key);
+	int (*copy)(EC_KEY *dest, const EC_KEY *src);
+	int (*set_group)(EC_KEY *key, const EC_GROUP *grp);
+	int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
+	int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
+	int (*keygen)(EC_KEY *key);
+	int (*compute_key)(unsigned char **out, size_t *out_len,
+	    const EC_POINT *pub_key, const EC_KEY *ecdh);
+	int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
+	    *sig, unsigned int *siglen, const BIGNUM *kinv,
+	    const BIGNUM *r, EC_KEY *eckey);
+	int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+	    BIGNUM **rp);
+	ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
+	    const BIGNUM *in_kinv, const BIGNUM *in_r,
+	    EC_KEY *eckey);
+	int (*verify)(int type, const unsigned char *dgst, int dgst_len,
+	    const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
+	int (*verify_sig)(const unsigned char *dgst, int dgst_len,
+	    const ECDSA_SIG *sig, EC_KEY *eckey);
+} /* EC_KEY_METHOD */;
+
+#define EC_KEY_METHOD_DYNAMIC   1
+
+int ec_key_gen(EC_KEY *eckey);
+int ecdh_compute_key(unsigned char **out, size_t *out_len,
+    const EC_POINT *pub_key, const EC_KEY *ecdh);
+int ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
+    const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
+int ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
+    const ECDSA_SIG *sig, EC_KEY *eckey);
+
+/*
+ * ECDH Key Derivation Function as defined in ANSI X9.63.
+ */
+int ecdh_KDF_X9_63(unsigned char *out, size_t outlen, const unsigned char *Z,
+    size_t Zlen, const unsigned char *sinfo, size_t sinfolen, const EVP_MD *md);
+
+int EC_POINT_set_Jprojective_coordinates(const EC_GROUP *group, EC_POINT *p,
+    const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx);
+int EC_POINT_get_Jprojective_coordinates(const EC_GROUP *group,
+    const EC_POINT *p, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx);
+
+/* Public API in OpenSSL */
+const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group);
+
+__END_HIDDEN_DECLS
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
new file mode 100644
index 0000000..a0e9743
--- /dev/null
+++ b/crypto/ec/ec_mult.c
@@ -0,0 +1,450 @@
+/* $OpenBSD: ec_mult.c,v 1.31 2023/06/24 17:49:44 jsing Exp $ */
+/*
+ * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include 
+
+#include "ec_local.h"
+
+/*
+ * This file implements the wNAF-based interleaving multi-exponentation method
+ * ();
+ * for multiplication with precomputation, we use wNAF splitting
+ * ().
+ */
+
+/* Determine the modified width-(w+1) Non-Adjacent Form (wNAF) of 'scalar'.
+ * This is an array  r[]  of values that are either zero or odd with an
+ * absolute value less than  2^w  satisfying
+ *     scalar = \sum_j r[j]*2^j
+ * where at most one of any  w+1  consecutive digits is non-zero
+ * with the exception that the most significant digit may be only
+ * w-1 zeros away from that next non-zero digit.
+ */
+static signed char *
+compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len)
+{
+	int window_val;
+	int ok = 0;
+	signed char *r = NULL;
+	int sign = 1;
+	int bit, next_bit, mask;
+	size_t len = 0, j;
+
+	if (BN_is_zero(scalar)) {
+		r = malloc(1);
+		if (!r) {
+			ECerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		r[0] = 0;
+		*ret_len = 1;
+		return r;
+	}
+	if (w <= 0 || w > 7) {
+		/* 'signed char' can represent integers with
+		 * absolute values less than 2^7 */
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	bit = 1 << w;		/* at most 128 */
+	next_bit = bit << 1;	/* at most 256 */
+	mask = next_bit - 1;	/* at most 255 */
+
+	if (BN_is_negative(scalar)) {
+		sign = -1;
+	}
+	if (scalar->d == NULL || scalar->top == 0) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	len = BN_num_bits(scalar);
+	r = malloc(len + 1);	/* modified wNAF may be one digit longer than
+				 * binary representation (*ret_len will be
+				 * set to the actual length, i.e. at most
+				 * BN_num_bits(scalar) + 1) */
+	if (r == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	window_val = scalar->d[0] & mask;
+	j = 0;
+	while ((window_val != 0) || (j + w + 1 < len)) {
+		/* if j+w+1 >= len, window_val will not increase */
+		int digit = 0;
+
+		/* 0 <= window_val <= 2^(w+1) */
+		if (window_val & 1) {
+			/* 0 < window_val < 2^(w+1) */
+			if (window_val & bit) {
+				digit = window_val - next_bit;	/* -2^w < digit < 0 */
+
+#if 1				/* modified wNAF */
+				if (j + w + 1 >= len) {
+					/*
+					 * special case for generating
+					 * modified wNAFs: no new bits will
+					 * be added into window_val, so using
+					 * a positive digit here will
+					 * decrease the total length of the
+					 * representation
+					 */
+
+					digit = window_val & (mask >> 1);	/* 0 < digit < 2^w */
+				}
+#endif
+			} else {
+				digit = window_val;	/* 0 < digit < 2^w */
+			}
+
+			if (digit <= -bit || digit >= bit || !(digit & 1)) {
+				ECerror(ERR_R_INTERNAL_ERROR);
+				goto err;
+			}
+			window_val -= digit;
+
+			/*
+			 * now window_val is 0 or 2^(w+1) in standard wNAF
+			 * generation; for modified window NAFs, it may also
+			 * be 2^w
+			 */
+			if (window_val != 0 && window_val != next_bit && window_val != bit) {
+				ECerror(ERR_R_INTERNAL_ERROR);
+				goto err;
+			}
+		}
+		r[j++] = sign * digit;
+
+		window_val >>= 1;
+		window_val += bit * BN_is_bit_set(scalar, j + w);
+
+		if (window_val > next_bit) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+
+	if (j > len + 1) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	len = j;
+	ok = 1;
+
+ err:
+	if (!ok) {
+		free(r);
+		r = NULL;
+	}
+	if (ok)
+		*ret_len = len;
+	return r;
+}
+
+
+/* TODO: table should be optimised for the wNAF-based implementation,
+ *       sometimes smaller windows will give better performance
+ *       (thus the boundaries should be increased)
+ */
+#define EC_window_bits_for_scalar_size(b) \
+		((size_t) \
+		 ((b) >= 2000 ? 6 : \
+		  (b) >=  800 ? 5 : \
+		  (b) >=  300 ? 4 : \
+		  (b) >=   70 ? 3 : \
+		  (b) >=   20 ? 2 : \
+		  1))
+
+/* Compute
+ *      \sum scalars[i]*points[i],
+ * also including
+ *      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)
+{
+	const EC_POINT *generator = NULL;
+	EC_POINT *tmp = NULL;
+	size_t totalnum;
+	size_t numblocks = 0;	/* for wNAF splitting */
+	size_t i, j;
+	int k;
+	int r_is_inverted = 0;
+	int r_is_at_infinity = 1;
+	size_t *wsize = NULL;	/* individual window sizes */
+	signed char **wNAF = NULL;	/* individual wNAFs */
+	signed char *tmp_wNAF = NULL;
+	size_t *wNAF_len = NULL;
+	size_t max_len = 0;
+	size_t num_val;
+	EC_POINT **val = NULL;	/* precomputation */
+	EC_POINT **v;
+	EC_POINT ***val_sub = NULL;	/* pointers to sub-arrays of 'val' or
+					 * 'pre_comp->points' */
+	int num_scalar = 0;	/* flag: will be set to 1 if 'scalar' must be
+				 * treated like other scalars, i.e.
+				 * precomputation is not available */
+	int ret = 0;
+
+	if (group->meth != r->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		return 0;
+	}
+	if ((scalar == NULL) && (num == 0)) {
+		return EC_POINT_set_to_infinity(group, r);
+	}
+	for (i = 0; i < num; i++) {
+		if (group->meth != points[i]->meth) {
+			ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+			return 0;
+		}
+	}
+
+	if (scalar != NULL) {
+		generator = EC_GROUP_get0_generator(group);
+		if (generator == NULL) {
+			ECerror(EC_R_UNDEFINED_GENERATOR);
+			goto err;
+		}
+
+		numblocks = 1;
+		num_scalar = 1;	/* treat 'scalar' like 'num'-th
+				 * element of 'scalars' */
+	}
+	totalnum = num + numblocks;
+
+	/* includes space for pivot */
+	wNAF = reallocarray(NULL, (totalnum + 1), sizeof wNAF[0]);
+	if (wNAF == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	wNAF[0] = NULL;		/* preliminary pivot */
+
+	wsize = reallocarray(NULL, totalnum, sizeof wsize[0]);
+	wNAF_len = reallocarray(NULL, totalnum, sizeof wNAF_len[0]);
+	val_sub = reallocarray(NULL, totalnum, sizeof val_sub[0]);
+
+	if (wsize == NULL || wNAF_len == NULL || val_sub == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* num_val will be the total number of temporarily precomputed points */
+	num_val = 0;
+
+	for (i = 0; i < num + num_scalar; i++) {
+		size_t bits;
+
+		bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
+		wsize[i] = EC_window_bits_for_scalar_size(bits);
+		num_val += (size_t) 1 << (wsize[i] - 1);
+		wNAF[i + 1] = NULL;	/* make sure we always have a pivot */
+		wNAF[i] = compute_wNAF((i < num ? scalars[i] : scalar), wsize[i], &wNAF_len[i]);
+		if (wNAF[i] == NULL)
+			goto err;
+		if (wNAF_len[i] > max_len)
+			max_len = wNAF_len[i];
+	}
+
+	if (numblocks) {
+		/* we go here iff scalar != NULL */
+
+		if (num_scalar != 1) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+	/*
+	 * All points we precompute now go into a single array 'val'.
+	 * 'val_sub[i]' is a pointer to the subarray for the i-th point, or
+	 * to a subarray of 'pre_comp->points' if we already have
+	 * precomputation.
+	 */
+	val = reallocarray(NULL, (num_val + 1), sizeof val[0]);
+	if (val == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	val[num_val] = NULL;	/* pivot element */
+
+	/* allocate points for precomputation */
+	v = val;
+	for (i = 0; i < num + num_scalar; i++) {
+		val_sub[i] = v;
+		for (j = 0; j < ((size_t) 1 << (wsize[i] - 1)); j++) {
+			*v = EC_POINT_new(group);
+			if (*v == NULL)
+				goto err;
+			v++;
+		}
+	}
+	if (!(v == val + num_val)) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	if (!(tmp = EC_POINT_new(group)))
+		goto err;
+
+	/*
+	 * prepare precomputed values: val_sub[i][0] :=     points[i]
+	 * val_sub[i][1] := 3 * points[i] val_sub[i][2] := 5 * points[i] ...
+	 */
+	for (i = 0; i < num + num_scalar; i++) {
+		if (i < num) {
+			if (!EC_POINT_copy(val_sub[i][0], points[i]))
+				goto err;
+		} else {
+			if (!EC_POINT_copy(val_sub[i][0], generator))
+				goto err;
+		}
+
+		if (wsize[i] > 1) {
+			if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
+				goto err;
+			for (j = 1; j < ((size_t) 1 << (wsize[i] - 1)); j++) {
+				if (!EC_POINT_add(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
+					goto err;
+			}
+		}
+	}
+
+	if (!EC_POINTs_make_affine(group, num_val, val, ctx))
+		goto err;
+
+	r_is_at_infinity = 1;
+
+	for (k = max_len - 1; k >= 0; k--) {
+		if (!r_is_at_infinity) {
+			if (!EC_POINT_dbl(group, r, r, ctx))
+				goto err;
+		}
+		for (i = 0; i < totalnum; i++) {
+			if (wNAF_len[i] > (size_t) k) {
+				int digit = wNAF[i][k];
+				int is_neg;
+
+				if (digit) {
+					is_neg = digit < 0;
+
+					if (is_neg)
+						digit = -digit;
+
+					if (is_neg != r_is_inverted) {
+						if (!r_is_at_infinity) {
+							if (!EC_POINT_invert(group, r, ctx))
+								goto err;
+						}
+						r_is_inverted = !r_is_inverted;
+					}
+					/* digit > 0 */
+
+					if (r_is_at_infinity) {
+						if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
+							goto err;
+						r_is_at_infinity = 0;
+					} else {
+						if (!EC_POINT_add(group, r, r, val_sub[i][digit >> 1], ctx))
+							goto err;
+					}
+				}
+			}
+		}
+	}
+
+	if (r_is_at_infinity) {
+		if (!EC_POINT_set_to_infinity(group, r))
+			goto err;
+	} else {
+		if (r_is_inverted)
+			if (!EC_POINT_invert(group, r, ctx))
+				goto err;
+	}
+
+	ret = 1;
+
+ err:
+	EC_POINT_free(tmp);
+	free(wsize);
+	free(wNAF_len);
+	free(tmp_wNAF);
+	if (wNAF != NULL) {
+		signed char **w;
+
+		for (w = wNAF; *w != NULL; w++)
+			free(*w);
+
+		free(wNAF);
+	}
+	if (val != NULL) {
+		for (v = val; *v != NULL; v++)
+			EC_POINT_free(*v);
+		free(val);
+	}
+	free(val_sub);
+	return ret;
+}
diff --git a/crypto/ec/ec_oct.c b/crypto/ec/ec_oct.c
new file mode 100644
index 0000000..9308d40
--- /dev/null
+++ b/crypto/ec/ec_oct.c
@@ -0,0 +1,170 @@
+/* $OpenBSD: ec_oct.c,v 1.16 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Binary polynomial ECC support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "ec_local.h"
+
+int
+EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
+    const BIGNUM *x, int y_bit, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point_set_compressed_coordinates == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->point_set_compressed_coordinates(group, point,
+	    x, y_bit, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_set_compressed_coordinates);
+
+int
+EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
+    const BIGNUM *x, int y_bit, BN_CTX *ctx)
+{
+	return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
+}
+
+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_in)
+{
+	BN_CTX *ctx;
+	size_t ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->point2oct == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->point2oct(group, point, form, buf, len, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_point2oct);
+
+int
+EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
+    const unsigned char *buf, size_t len, BN_CTX *ctx_in)
+{
+	BN_CTX *ctx;
+	int ret = 0;
+
+	if ((ctx = ctx_in) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	if (group->meth->oct2point == NULL) {
+		ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+		goto err;
+	}
+	if (group->meth != point->meth) {
+		ECerror(EC_R_INCOMPATIBLE_OBJECTS);
+		goto err;
+	}
+	ret = group->meth->oct2point(group, point, buf, len, ctx);
+
+ err:
+	if (ctx != ctx_in)
+		BN_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_oct2point);
diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c
new file mode 100644
index 0000000..d3bf7e8
--- /dev/null
+++ b/crypto/ec/ec_pmeth.c
@@ -0,0 +1,524 @@
+/* $OpenBSD: ec_pmeth.c,v 1.19 2023/07/28 15:50:33 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+#include "evp_local.h"
+
+/* EC pkey context structure */
+
+typedef struct {
+	/* Key and paramgen group */
+	EC_GROUP *gen_group;
+	/* message digest */
+	const EVP_MD *md;
+	/* Duplicate key if custom cofactor needed */
+	EC_KEY *co_key;
+	/* Cofactor mode */
+	signed char cofactor_mode;
+	/* KDF (if any) to use for ECDH */
+	char kdf_type;
+	/* Message digest to use for key derivation */
+	const EVP_MD *kdf_md;
+	/* User key material */
+	unsigned char *kdf_ukm;
+	size_t kdf_ukmlen;
+	/* KDF output length */
+	size_t kdf_outlen;
+} EC_PKEY_CTX;
+
+static int
+pkey_ec_init(EVP_PKEY_CTX *ctx)
+{
+	EC_PKEY_CTX *dctx;
+
+	if ((dctx = calloc(1, sizeof(EC_PKEY_CTX))) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	dctx->cofactor_mode = -1;
+	dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
+
+	ctx->data = dctx;
+
+	return 1;
+}
+
+static int
+pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	EC_PKEY_CTX *dctx, *sctx;
+	if (!pkey_ec_init(dst))
+		return 0;
+	sctx = src->data;
+	dctx = dst->data;
+	if (sctx->gen_group) {
+		dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
+		if (!dctx->gen_group)
+			return 0;
+	}
+	dctx->md = sctx->md;
+
+	if (sctx->co_key) {
+		dctx->co_key = EC_KEY_dup(sctx->co_key);
+		if (!dctx->co_key)
+			return 0;
+	}
+	dctx->kdf_type = sctx->kdf_type;
+	dctx->kdf_md = sctx->kdf_md;
+	dctx->kdf_outlen = sctx->kdf_outlen;
+	if (sctx->kdf_ukm) {
+		if ((dctx->kdf_ukm = calloc(1, sctx->kdf_ukmlen)) == NULL)
+			return 0;
+		memcpy(dctx->kdf_ukm, sctx->kdf_ukm, sctx->kdf_ukmlen);
+	} else
+		dctx->kdf_ukm = NULL;
+
+	dctx->kdf_ukmlen = sctx->kdf_ukmlen;
+
+	return 1;
+}
+
+static void
+pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
+{
+	EC_PKEY_CTX *dctx = ctx->data;
+
+	if (dctx != NULL) {
+		EC_GROUP_free(dctx->gen_group);
+		EC_KEY_free(dctx->co_key);
+		free(dctx->kdf_ukm);
+		free(dctx);
+		ctx->data = NULL;
+	}
+}
+
+static int
+pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	int ret, type;
+	unsigned int sltmp;
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_KEY *ec = ctx->pkey->pkey.ec;
+
+	if (!sig) {
+		*siglen = ECDSA_size(ec);
+		return 1;
+	} else if (*siglen < (size_t) ECDSA_size(ec)) {
+		ECerror(EC_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+	if (dctx->md)
+		type = EVP_MD_type(dctx->md);
+	else
+		type = NID_sha1;
+
+	ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
+	if (ret <= 0)
+		return ret;
+	*siglen = (size_t) sltmp;
+	return 1;
+}
+
+static int
+pkey_ec_verify(EVP_PKEY_CTX *ctx,
+    const unsigned char *sig, size_t siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	int ret, type;
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_KEY *ec = ctx->pkey->pkey.ec;
+
+	if (dctx->md)
+		type = EVP_MD_type(dctx->md);
+	else
+		type = NID_sha1;
+
+	ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
+
+	return ret;
+}
+
+static int
+pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+	int ret;
+	size_t outlen;
+	const EC_POINT *pubkey = NULL;
+	EC_KEY *eckey;
+	EC_PKEY_CTX *dctx = ctx->data;
+
+	if (!ctx->pkey || !ctx->peerkey) {
+		ECerror(EC_R_KEYS_NOT_SET);
+		return 0;
+	}
+
+	eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
+	if (!key) {
+		const EC_GROUP *group;
+		group = EC_KEY_get0_group(eckey);
+		*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
+		return 1;
+	}
+	pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
+
+	/*
+	 * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is
+	 * not an error, the result is truncated.
+	 */
+
+	outlen = *keylen;
+
+	ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
+	if (ret <= 0)
+		return 0;
+
+	*keylen = ret;
+
+	return 1;
+}
+
+static int
+pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+	EC_PKEY_CTX *dctx = ctx->data;
+	unsigned char *ktmp = NULL;
+	size_t ktmplen;
+	int rv = 0;
+
+	if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
+		return pkey_ec_derive(ctx, key, keylen);
+
+	if (!key) {
+		*keylen = dctx->kdf_outlen;
+		return 1;
+	}
+	if (*keylen != dctx->kdf_outlen)
+		return 0;
+	if (!pkey_ec_derive(ctx, NULL, &ktmplen))
+		return 0;
+	if ((ktmp = calloc(1, ktmplen)) == NULL) {
+		ECerror(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))
+		goto err;
+	rv = 1;
+
+ err:
+	freezero(ktmp, ktmplen);
+
+	return rv;
+}
+
+static int
+pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	EC_PKEY_CTX *dctx = ctx->data;
+	EC_GROUP *group;
+
+	switch (type) {
+	case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
+		group = EC_GROUP_new_by_curve_name(p1);
+		if (group == NULL) {
+			ECerror(EC_R_INVALID_CURVE);
+			return 0;
+		}
+		EC_GROUP_free(dctx->gen_group);
+		dctx->gen_group = group;
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_PARAM_ENC:
+		if (!dctx->gen_group) {
+			ECerror(EC_R_NO_PARAMETERS_SET);
+			return 0;
+		}
+		EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
+		if (p1 == -2) {
+			if (dctx->cofactor_mode != -1)
+				return dctx->cofactor_mode;
+			else {
+				EC_KEY *ec_key = ctx->pkey->pkey.ec;
+				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;
+			if (!ec_key->group)
+				return -2;
+			/* If cofactor is 1 cofactor mode does nothing */
+			if (BN_is_one(&ec_key->group->cofactor))
+				return 1;
+			if (!dctx->co_key) {
+				dctx->co_key = EC_KEY_dup(ec_key);
+				if (!dctx->co_key)
+					return 0;
+			}
+			if (p1)
+				EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
+			else
+				EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
+		} else {
+			EC_KEY_free(dctx->co_key);
+			dctx->co_key = NULL;
+		}
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_KDF_TYPE:
+		if (p1 == -2)
+			return dctx->kdf_type;
+		if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
+			return -2;
+		dctx->kdf_type = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_KDF_MD:
+		dctx->kdf_md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_EC_KDF_MD:
+		*(const EVP_MD **)p2 = dctx->kdf_md;
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
+		if (p1 <= 0)
+			return -2;
+		dctx->kdf_outlen = (size_t)p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
+		*(int *)p2 = dctx->kdf_outlen;
+		return 1;
+
+	case EVP_PKEY_CTRL_EC_KDF_UKM:
+		free(dctx->kdf_ukm);
+		dctx->kdf_ukm = p2;
+		if (p2)
+			dctx->kdf_ukmlen = p1;
+		else
+			dctx->kdf_ukmlen = 0;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
+		*(unsigned char **)p2 = dctx->kdf_ukm;
+		return dctx->kdf_ukmlen;
+
+	case EVP_PKEY_CTRL_MD:
+		/* RFC 3279, RFC 5758 and NIST CSOR. */
+		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) {
+			ECerror(EC_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		dctx->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_MD:
+		*(const EVP_MD **)p2 = dctx->md;
+		return 1;
+
+	case EVP_PKEY_CTRL_PEER_KEY:
+		/* Default behaviour is OK */
+	case EVP_PKEY_CTRL_DIGESTINIT:
+	case EVP_PKEY_CTRL_PKCS7_SIGN:
+	case EVP_PKEY_CTRL_CMS_SIGN:
+		return 1;
+
+	default:
+		return -2;
+
+	}
+}
+
+static int
+pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+	if (!strcmp(type, "ec_paramgen_curve")) {
+		int nid;
+		nid = EC_curve_nist2nid(value);
+		if (nid == NID_undef)
+			nid = OBJ_sn2nid(value);
+		if (nid == NID_undef)
+			nid = OBJ_ln2nid(value);
+		if (nid == NID_undef) {
+			ECerror(EC_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);
+	} else if (strcmp(type, "ecdh_kdf_md") == 0) {
+		const EVP_MD *md;
+		if ((md = EVP_get_digestbyname(value)) == NULL) {
+			ECerror(EC_R_INVALID_DIGEST);
+			return 0;
+		}
+		return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
+	} else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
+		int co_mode;
+		co_mode = atoi(value);
+		return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
+	}
+	return -2;
+}
+
+static int
+pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	EC_KEY *ec = NULL;
+	EC_PKEY_CTX *dctx = ctx->data;
+	int ret = 0;
+	if (dctx->gen_group == NULL) {
+		ECerror(EC_R_NO_PARAMETERS_SET);
+		return 0;
+	}
+	ec = EC_KEY_new();
+	if (!ec)
+		return 0;
+	ret = EC_KEY_set_group(ec, dctx->gen_group);
+	if (ret)
+		EVP_PKEY_assign_EC_KEY(pkey, ec);
+	else
+		EC_KEY_free(ec);
+	return ret;
+}
+
+static int
+pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	EC_KEY *ec = NULL;
+	EC_PKEY_CTX *dctx = ctx->data;
+
+	if (ctx->pkey == NULL && dctx->gen_group == NULL) {
+		ECerror(EC_R_NO_PARAMETERS_SET);
+		return 0;
+	}
+	ec = EC_KEY_new();
+	if (ec == NULL)
+		return 0;
+	if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+		EC_KEY_free(ec);
+		return 0;
+	}
+	/* Note: if error is returned, we count on caller to free pkey->pkey.ec */
+	if (ctx->pkey != NULL) {
+		if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+			return 0;
+	} else {
+		if (!EC_KEY_set_group(ec, dctx->gen_group))
+			return 0;
+	}
+
+	return EC_KEY_generate_key(ec);
+}
+
+const EVP_PKEY_METHOD ec_pkey_meth = {
+	.pkey_id = EVP_PKEY_EC,
+
+	.init = pkey_ec_init,
+	.copy = pkey_ec_copy,
+	.cleanup = pkey_ec_cleanup,
+
+	.paramgen = pkey_ec_paramgen,
+
+	.keygen = pkey_ec_keygen,
+
+	.sign = pkey_ec_sign,
+
+	.verify = pkey_ec_verify,
+
+	.derive = pkey_ec_kdf_derive,
+
+	.ctrl = pkey_ec_ctrl,
+	.ctrl_str = pkey_ec_ctrl_str
+};
diff --git a/crypto/ec/ec_print.c b/crypto/ec/ec_print.c
new file mode 100644
index 0000000..312770f
--- /dev/null
+++ b/crypto/ec/ec_print.c
@@ -0,0 +1,182 @@
+/* $OpenBSD: ec_print.c,v 1.13 2023/07/07 13:54:45 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#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_point2oct(group, point, form,
+	    NULL, 0, ctx);
+	if (buf_len == 0)
+		return NULL;
+
+	if ((buf = malloc(buf_len)) == NULL)
+		return NULL;
+
+	if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) {
+		free(buf);
+		return NULL;
+	}
+	ret = BN_bin2bn(buf, buf_len, ret);
+
+	free(buf);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_point2bn);
+
+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)
+		return NULL;
+	buf = malloc(buf_len);
+	if (buf == NULL)
+		return NULL;
+
+	if (!BN_bn2bin(bn, buf)) {
+		free(buf);
+		return NULL;
+	}
+	if (point == NULL) {
+		if ((ret = EC_POINT_new(group)) == NULL) {
+			free(buf);
+			return NULL;
+		}
+	} else
+		ret = point;
+
+	if (!EC_POINT_oct2point(group, ret, buf, buf_len, ctx)) {
+		if (point == NULL)
+			EC_POINT_free(ret);
+		free(buf);
+		return NULL;
+	}
+	free(buf);
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_bn2point);
+
+static const char *HEX_DIGITS = "0123456789ABCDEF";
+
+/* the return value must be freed (using free()) */
+char *
+EC_POINT_point2hex(const EC_GROUP *group, const EC_POINT *point,
+    point_conversion_form_t form, BN_CTX *ctx)
+{
+	char *ret, *p;
+	size_t buf_len = 0, i;
+	unsigned char *buf, *pbuf;
+
+	buf_len = EC_POINT_point2oct(group, point, form,
+	    NULL, 0, ctx);
+	if (buf_len == 0 || buf_len + 1 == 0)
+		return NULL;
+
+	if ((buf = malloc(buf_len)) == NULL)
+		return NULL;
+
+	if (!EC_POINT_point2oct(group, point, form, buf, buf_len, ctx)) {
+		free(buf);
+		return NULL;
+	}
+	ret = reallocarray(NULL, buf_len + 1, 2);
+	if (ret == NULL) {
+		free(buf);
+		return NULL;
+	}
+	p = ret;
+	pbuf = buf;
+	for (i = buf_len; i > 0; i--) {
+		int v = (int) *(pbuf++);
+		*(p++) = HEX_DIGITS[v >> 4];
+		*(p++) = HEX_DIGITS[v & 0x0F];
+	}
+	*p = '\0';
+
+	free(buf);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_point2hex);
+
+EC_POINT *
+EC_POINT_hex2point(const EC_GROUP *group, const char *buf,
+    EC_POINT *point, BN_CTX *ctx)
+{
+	EC_POINT *ret = NULL;
+	BIGNUM *tmp_bn = NULL;
+
+	if (BN_hex2bn(&tmp_bn, buf) == 0)
+		return NULL;
+
+	ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);
+
+	BN_free(tmp_bn);
+
+	return ret;
+}
+LCRYPTO_ALIAS(EC_POINT_hex2point);
diff --git a/crypto/ec/eck_prn.c b/crypto/ec/eck_prn.c
new file mode 100644
index 0000000..6e89bfa
--- /dev/null
+++ b/crypto/ec/eck_prn.c
@@ -0,0 +1,353 @@
+/* $OpenBSD: eck_prn.c,v 1.28 2023/07/07 13:54:45 beck Exp $ */
+/*
+ * Written by Nils Larsch for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions originally developed by SUN MICROSYSTEMS, INC., and
+ * contributed to the OpenSSL project.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ec_local.h"
+
+int
+ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ECerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = ECPKParameters_print(b, x, off);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ECPKParameters_print_fp);
+
+int
+EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ECerror(ERR_R_BIO_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = EC_KEY_print(b, x, off);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(EC_KEY_print_fp);
+
+int
+ECParameters_print_fp(FILE *fp, const EC_KEY *x)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		ECerror(ERR_R_BIO_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = ECParameters_print(b, x);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(ECParameters_print_fp);
+
+int
+EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
+{
+	EVP_PKEY *pk;
+	int ret = 0;
+
+	if ((pk = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *) x))
+		goto err;
+
+	ret = EVP_PKEY_print_private(bp, pk, off, NULL);
+ err:
+	EVP_PKEY_free(pk);
+	return ret;
+}
+LCRYPTO_ALIAS(EC_KEY_print);
+
+int
+ECParameters_print(BIO *bp, const EC_KEY *x)
+{
+	EVP_PKEY *pk;
+	int ret = 0;
+
+	if ((pk = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *) x))
+		goto err;
+
+	ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
+ err:
+	EVP_PKEY_free(pk);
+	return ret;
+}
+LCRYPTO_ALIAS(ECParameters_print);
+
+static int
+print_bin(BIO *fp, const char *str, const unsigned char *num,
+    size_t len, int off);
+
+static int
+ecpk_print_asn1_parameters(BIO *bp, const EC_GROUP *group, int off)
+{
+	const char *nist_name;
+	int nid;
+	int ret = 0;
+
+	if (!BIO_indent(bp, off, 128)) {
+		ECerror(ERR_R_BIO_LIB);
+		goto err;
+	}
+
+	if ((nid = EC_GROUP_get_curve_name(group)) == NID_undef) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+
+	if (BIO_printf(bp, "ASN1 OID: %s\n", OBJ_nid2sn(nid)) <= 0) {
+		ECerror(ERR_R_BIO_LIB);
+		goto err;
+	}
+
+	if ((nist_name = EC_curve_nid2nist(nid)) != NULL) {
+		if (!BIO_indent(bp, off, 128)) {
+			ECerror(ERR_R_BIO_LIB);
+			goto err;
+		}
+		if (BIO_printf(bp, "NIST CURVE: %s\n", nist_name) <= 0) {
+			ECerror(ERR_R_BIO_LIB);
+			goto err;
+		}
+	}
+
+	ret = 1;
+ err:
+
+	return ret;
+}
+
+static int
+ecpk_print_explicit_parameters(BIO *bp, const EC_GROUP *group, int off)
+{
+	BN_CTX *ctx = NULL;
+	const BIGNUM *order;
+	BIGNUM *p, *a, *b, *cofactor;
+	BIGNUM *gen = NULL;
+	const EC_POINT *generator;
+	const char *conversion_form;
+	const unsigned char *seed;
+	size_t seed_len;
+	point_conversion_form_t form;
+	int nid;
+	int ret = 0;
+
+	if ((ctx = BN_CTX_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((cofactor = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((gen = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if ((order = EC_GROUP_get0_order(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	form = EC_GROUP_get_point_conversion_form(group);
+	if (EC_POINT_point2bn(group, generator, form, gen, ctx) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if (!BIO_indent(bp, off, 128))
+		goto err;
+
+	nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group));
+	if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(nid)) <= 0)
+		goto err;
+
+	if (!bn_printf(bp, p, off, "Prime:"))
+		goto err;
+	if (!bn_printf(bp, a, off, "A:   "))
+		goto err;
+	if (!bn_printf(bp, b, off, "B:   "))
+		goto err;
+
+	if (form == POINT_CONVERSION_COMPRESSED)
+		conversion_form = "compressed";
+	else if (form == POINT_CONVERSION_UNCOMPRESSED)
+		conversion_form = "uncompressed";
+	else if (form == POINT_CONVERSION_HYBRID)
+		conversion_form = "hybrid";
+	else
+		conversion_form = "unknown";
+	if (!bn_printf(bp, gen, off, "Generator (%s):", conversion_form))
+		goto err;
+
+	if (!bn_printf(bp, order, off, "Order: "))
+		goto err;
+	if (!bn_printf(bp, cofactor, off, "Cofactor: "))
+		goto err;
+	if ((seed = EC_GROUP_get0_seed(group)) != NULL) {
+		seed_len = EC_GROUP_get_seed_len(group);
+		if (!print_bin(bp, "Seed:", seed, seed_len, off))
+			goto err;
+	}
+
+	ret = 1;
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return ret;
+}
+
+int
+ECPKParameters_print(BIO *bp, const EC_GROUP *group, int off)
+{
+	if (group == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+
+	if (EC_GROUP_get_asn1_flag(group))
+		return ecpk_print_asn1_parameters(bp, group, off);
+
+	return ecpk_print_explicit_parameters(bp, group, off);
+}
+LCRYPTO_ALIAS(ECPKParameters_print);
+
+static int
+print_bin(BIO *fp, const char *name, const unsigned char *buf,
+    size_t len, int off)
+{
+	size_t i;
+	char str[128];
+
+	if (buf == NULL)
+		return 1;
+	if (off) {
+		if (off > 128)
+			off = 128;
+		memset(str, ' ', off);
+		if (BIO_write(fp, str, off) <= 0)
+			return 0;
+	}
+	if (BIO_printf(fp, "%s", name) <= 0)
+		return 0;
+
+	for (i = 0; i < len; i++) {
+		if ((i % 15) == 0) {
+			str[0] = '\n';
+			memset(&(str[1]), ' ', off + 4);
+			if (BIO_write(fp, str, off + 1 + 4) <= 0)
+				return 0;
+		}
+		if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= 0)
+			return 0;
+	}
+	if (BIO_write(fp, "\n", 1) <= 0)
+		return 0;
+
+	return 1;
+}
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
new file mode 100644
index 0000000..76d1f57
--- /dev/null
+++ b/crypto/ec/ecp_mont.c
@@ -0,0 +1,272 @@
+/* $OpenBSD: ecp_mont.c,v 1.30 2023/07/07 13:54:45 beck Exp $ */
+/*
+ * Originally written by Bodo Moeller for the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include "ec_local.h"
+
+static void
+ec_GFp_mont_group_clear(EC_GROUP *group)
+{
+	BN_MONT_CTX_free(group->mont_ctx);
+	group->mont_ctx = NULL;
+
+	BN_free(group->mont_one);
+	group->mont_one = NULL;
+}
+
+static int
+ec_GFp_mont_group_init(EC_GROUP *group)
+{
+	int ok;
+
+	ok = ec_GFp_simple_group_init(group);
+	group->mont_ctx = NULL;
+	group->mont_one = NULL;
+	return ok;
+}
+
+static void
+ec_GFp_mont_group_finish(EC_GROUP *group)
+{
+	ec_GFp_mont_group_clear(group);
+	ec_GFp_simple_group_finish(group);
+}
+
+static int
+ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+{
+	ec_GFp_mont_group_clear(dest);
+
+	if (!ec_GFp_simple_group_copy(dest, src))
+		return 0;
+
+	if (src->mont_ctx != NULL) {
+		dest->mont_ctx = BN_MONT_CTX_new();
+		if (dest->mont_ctx == NULL)
+			return 0;
+		if (!BN_MONT_CTX_copy(dest->mont_ctx, src->mont_ctx))
+			goto err;
+	}
+	if (src->mont_one != NULL) {
+		dest->mont_one = BN_dup(src->mont_one);
+		if (dest->mont_one == NULL)
+			goto err;
+	}
+	return 1;
+
+ err:
+	if (dest->mont_ctx != NULL) {
+		BN_MONT_CTX_free(dest->mont_ctx);
+		dest->mont_ctx = NULL;
+	}
+	return 0;
+}
+
+static int
+ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
+    const BIGNUM *b, BN_CTX *ctx)
+{
+	BN_MONT_CTX *mont = NULL;
+	BIGNUM *one = NULL;
+	int ret = 0;
+
+	ec_GFp_mont_group_clear(group);
+
+	mont = BN_MONT_CTX_new();
+	if (mont == NULL)
+		goto err;
+	if (!BN_MONT_CTX_set(mont, p, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	one = BN_new();
+	if (one == NULL)
+		goto err;
+	if (!BN_to_montgomery(one, BN_value_one(), mont, ctx))
+		goto err;
+
+	group->mont_ctx = mont;
+	mont = NULL;
+	group->mont_one = one;
+	one = NULL;
+
+	ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
+	if (!ret)
+		ec_GFp_mont_group_clear(group);
+
+ err:
+	BN_MONT_CTX_free(mont);
+	BN_free(one);
+
+	return ret;
+}
+
+static int
+ec_GFp_mont_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+    const BIGNUM *b, BN_CTX *ctx)
+{
+	if (group->mont_ctx == NULL) {
+		ECerror(EC_R_NOT_INITIALIZED);
+		return 0;
+	}
+	return BN_mod_mul_montgomery(r, a, b, group->mont_ctx, ctx);
+}
+
+static int
+ec_GFp_mont_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+    BN_CTX *ctx)
+{
+	if (group->mont_ctx == NULL) {
+		ECerror(EC_R_NOT_INITIALIZED);
+		return 0;
+	}
+	return BN_mod_mul_montgomery(r, a, a, group->mont_ctx, ctx);
+}
+
+static int
+ec_GFp_mont_field_encode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+    BN_CTX *ctx)
+{
+	if (group->mont_ctx == NULL) {
+		ECerror(EC_R_NOT_INITIALIZED);
+		return 0;
+	}
+	return BN_to_montgomery(r, a, group->mont_ctx, ctx);
+}
+
+static int
+ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
+    BN_CTX *ctx)
+{
+	if (group->mont_ctx == NULL) {
+		ECerror(EC_R_NOT_INITIALIZED);
+		return 0;
+	}
+	return BN_from_montgomery(r, a, group->mont_ctx, ctx);
+}
+
+static int
+ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r, BN_CTX *ctx)
+{
+	if (group->mont_one == NULL) {
+		ECerror(EC_R_NOT_INITIALIZED);
+		return 0;
+	}
+	if (!bn_copy(r, group->mont_one))
+		return 0;
+
+	return 1;
+}
+
+static const EC_METHOD ec_GFp_mont_method = {
+	.field_type = NID_X9_62_prime_field,
+	.group_init = ec_GFp_mont_group_init,
+	.group_finish = ec_GFp_mont_group_finish,
+	.group_copy = ec_GFp_mont_group_copy,
+	.group_set_curve = ec_GFp_mont_group_set_curve,
+	.group_get_curve = ec_GFp_simple_group_get_curve,
+	.group_get_degree = ec_GFp_simple_group_get_degree,
+	.group_order_bits = ec_group_simple_order_bits,
+	.group_check_discriminant = ec_GFp_simple_group_check_discriminant,
+	.point_init = ec_GFp_simple_point_init,
+	.point_finish = ec_GFp_simple_point_finish,
+	.point_copy = ec_GFp_simple_point_copy,
+	.point_set_to_infinity = ec_GFp_simple_point_set_to_infinity,
+	.point_set_Jprojective_coordinates =
+	    ec_GFp_simple_set_Jprojective_coordinates,
+	.point_get_Jprojective_coordinates =
+	    ec_GFp_simple_get_Jprojective_coordinates,
+	.point_set_affine_coordinates =
+	    ec_GFp_simple_point_set_affine_coordinates,
+	.point_get_affine_coordinates =
+	    ec_GFp_simple_point_get_affine_coordinates,
+	.point_set_compressed_coordinates =
+	    ec_GFp_simple_set_compressed_coordinates,
+	.point2oct = ec_GFp_simple_point2oct,
+	.oct2point = ec_GFp_simple_oct2point,
+	.add = ec_GFp_simple_add,
+	.dbl = ec_GFp_simple_dbl,
+	.invert = ec_GFp_simple_invert,
+	.is_at_infinity = ec_GFp_simple_is_at_infinity,
+	.is_on_curve = ec_GFp_simple_is_on_curve,
+	.point_cmp = ec_GFp_simple_cmp,
+	.make_affine = ec_GFp_simple_make_affine,
+	.points_make_affine = ec_GFp_simple_points_make_affine,
+	.mul_generator_ct = ec_GFp_simple_mul_generator_ct,
+	.mul_single_ct = ec_GFp_simple_mul_single_ct,
+	.mul_double_nonct = ec_GFp_simple_mul_double_nonct,
+	.field_mul = ec_GFp_mont_field_mul,
+	.field_sqr = ec_GFp_mont_field_sqr,
+	.field_encode = ec_GFp_mont_field_encode,
+	.field_decode = ec_GFp_mont_field_decode,
+	.field_set_to_one = ec_GFp_mont_field_set_to_one,
+	.blind_coordinates = ec_GFp_simple_blind_coordinates,
+};
+
+const EC_METHOD *
+EC_GFp_mont_method(void)
+{
+	return &ec_GFp_mont_method;
+}
+LCRYPTO_ALIAS(EC_GFp_mont_method);
diff --git a/crypto/ec/ecp_oct.c b/crypto/ec/ecp_oct.c
new file mode 100644
index 0000000..b3cf441
--- /dev/null
+++ b/crypto/ec/ecp_oct.c
@@ -0,0 +1,365 @@
+/* $OpenBSD: ecp_oct.c,v 1.21 2023/04/18 18:29:32 tb Exp $ */
+/* Includes code written by Lenka Fibikova 
+ * for the OpenSSL project.
+ * Includes code written by Bodo Moeller for the OpenSSL project.
+*/
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#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)
+{
+	BIGNUM *tmp1, *tmp2, *x, *y;
+	int ret = 0;
+
+	/* clear error queue */
+	ERR_clear_error();
+
+	y_bit = (y_bit != 0);
+
+	BN_CTX_start(ctx);
+
+	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Recover y.  We have a Weierstrass equation y^2 = x^3 + a*x + b, so
+	 * y  is one of the square roots of  x^3 + a*x + b.
+	 */
+
+	/* tmp1 := x^3 */
+	if (!BN_nnmod(x, x_, &group->field, ctx))
+		goto err;
+	if (group->meth->field_decode == NULL) {
+		/* field_{sqr,mul} work on standard representation */
+		if (!group->meth->field_sqr(group, tmp2, x_, ctx))
+			goto err;
+		if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx))
+			goto err;
+	} else {
+		if (!BN_mod_sqr(tmp2, x_, &group->field, ctx))
+			goto err;
+		if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx))
+			goto err;
+	}
+
+	/* tmp1 := tmp1 + a*x */
+	if (group->a_is_minus3) {
+		if (!BN_mod_lshift1_quick(tmp2, x, &group->field))
+			goto err;
+		if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field))
+			goto err;
+		if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field))
+			goto err;
+	} else {
+		if (group->meth->field_decode) {
+			if (!group->meth->field_decode(group, tmp2, &group->a, ctx))
+				goto err;
+			if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx))
+				goto err;
+		} else {
+			/* field_mul works on standard representation */
+			if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx))
+				goto err;
+		}
+
+		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
+			goto err;
+	}
+
+	/* tmp1 := tmp1 + b */
+	if (group->meth->field_decode != NULL) {
+		if (!group->meth->field_decode(group, tmp2, &group->b, ctx))
+			goto err;
+		if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field))
+			goto err;
+	} else {
+		if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field))
+			goto err;
+	}
+
+	if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
+		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();
+			ECerror(EC_R_INVALID_COMPRESSED_POINT);
+		} else
+			ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (y_bit != BN_is_odd(y)) {
+		if (BN_is_zero(y)) {
+			ECerror(EC_R_INVALID_COMPRESSION_BIT);
+			goto err;
+		}
+		if (!BN_usub(y, &group->field, y))
+			goto err;
+		if (y_bit != BN_is_odd(y)) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+	if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	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)
+{
+	BIGNUM *x, *y;
+	size_t field_len, i, skip;
+	size_t ret = 0;
+
+	if (form != POINT_CONVERSION_COMPRESSED &&
+	    form != POINT_CONVERSION_UNCOMPRESSED &&
+	    form != POINT_CONVERSION_HYBRID) {
+		ECerror(EC_R_INVALID_FORM);
+		return 0;
+	}
+
+	if (EC_POINT_is_at_infinity(group, point) > 0) {
+		/* encodes to a single 0 octet */
+		if (buf != NULL) {
+			if (len < 1) {
+				ECerror(EC_R_BUFFER_TOO_SMALL);
+				return 0;
+			}
+			buf[0] = 0;
+		}
+		return 1;
+	}
+
+	/* ret := required output buffer length */
+	field_len = BN_num_bytes(&group->field);
+	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
+
+	BN_CTX_start(ctx);
+
+	/* if 'buf' is NULL, just return required length */
+	if (buf != NULL) {
+		if (len < ret) {
+			ECerror(EC_R_BUFFER_TOO_SMALL);
+			goto err;
+		}
+
+		if ((x = BN_CTX_get(ctx)) == NULL)
+			goto err;
+		if ((y = BN_CTX_get(ctx)) == NULL)
+			goto err;
+
+		if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
+			goto err;
+
+		if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
+			buf[0] = form + 1;
+		else
+			buf[0] = form;
+
+		i = 1;
+
+		skip = field_len - BN_num_bytes(x);
+		if (skip > field_len) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+		while (skip > 0) {
+			buf[i++] = 0;
+			skip--;
+		}
+		skip = BN_bn2bin(x, buf + i);
+		i += skip;
+		if (i != 1 + field_len) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID) {
+			skip = field_len - BN_num_bytes(y);
+			if (skip > field_len) {
+				ECerror(ERR_R_INTERNAL_ERROR);
+				goto err;
+			}
+			while (skip > 0) {
+				buf[i++] = 0;
+				skip--;
+			}
+			skip = BN_bn2bin(y, buf + i);
+			i += skip;
+		}
+		if (i != ret) {
+			ECerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+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;
+	BIGNUM *x, *y;
+	size_t field_len, enc_len;
+	int ret = 0;
+
+	if (len == 0) {
+		ECerror(EC_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+	form = buf[0];
+	y_bit = form & 1;
+	form = form & ~1U;
+	if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
+	    && (form != POINT_CONVERSION_UNCOMPRESSED)
+	    && (form != POINT_CONVERSION_HYBRID)) {
+		ECerror(EC_R_INVALID_ENCODING);
+		return 0;
+	}
+	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
+		ECerror(EC_R_INVALID_ENCODING);
+		return 0;
+	}
+	if (form == 0) {
+		if (len != 1) {
+			ECerror(EC_R_INVALID_ENCODING);
+			return 0;
+		}
+		return EC_POINT_set_to_infinity(group, point);
+	}
+	field_len = BN_num_bytes(&group->field);
+	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
+
+	if (len != enc_len) {
+		ECerror(EC_R_INVALID_ENCODING);
+		return 0;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_bin2bn(buf + 1, field_len, x))
+		goto err;
+	if (BN_ucmp(x, &group->field) >= 0) {
+		ECerror(EC_R_INVALID_ENCODING);
+		goto err;
+	}
+	if (form == POINT_CONVERSION_COMPRESSED) {
+		/*
+		 * EC_POINT_set_compressed_coordinates checks that the point
+		 * is on the curve as required by X9.62.
+		 */
+		if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx))
+			goto err;
+	} else {
+		if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
+			goto err;
+		if (BN_ucmp(y, &group->field) >= 0) {
+			ECerror(EC_R_INVALID_ENCODING);
+			goto err;
+		}
+		if (form == POINT_CONVERSION_HYBRID) {
+			if (y_bit != BN_is_odd(y)) {
+				ECerror(EC_R_INVALID_ENCODING);
+				goto err;
+			}
+		}
+		/*
+		 * EC_POINT_set_affine_coordinates checks that the point is
+		 * on the curve as required by X9.62.
+		 */
+		if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
new file mode 100644
index 0000000..018aedf
--- /dev/null
+++ b/crypto/ec/ecp_smpl.c
@@ -0,0 +1,1560 @@
+/* $OpenBSD: ecp_smpl.c,v 1.56 2023/08/03 18:53:56 tb Exp $ */
+/* Includes code written by Lenka Fibikova 
+ * for the OpenSSL project.
+ * Includes code written by Bodo Moeller for the OpenSSL project.
+*/
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * Portions of this software developed by SUN MICROSYSTEMS, INC.,
+ * and contributed to the OpenSSL project.
+ */
+
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+
+/*
+ * Most method functions in this file are designed to work with
+ * non-trivial representations of field elements if necessary
+ * (see ecp_mont.c): while standard modular addition and subtraction
+ * are used, the field_mul and field_sqr methods will be used for
+ * multiplication, and field_encode and field_decode (if defined)
+ * will be used for converting between representations.
+ *
+ * Functions ec_GFp_simple_points_make_affine() and
+ * ec_GFp_simple_point_get_affine_coordinates() specifically assume
+ * that if a non-trivial representation is used, it is a Montgomery
+ * representation (i.e. 'encoding' means multiplying by some factor R).
+ */
+
+int
+ec_GFp_simple_group_init(EC_GROUP *group)
+{
+	BN_init(&group->field);
+	BN_init(&group->a);
+	BN_init(&group->b);
+	group->a_is_minus3 = 0;
+	return 1;
+}
+
+void
+ec_GFp_simple_group_finish(EC_GROUP *group)
+{
+	BN_free(&group->field);
+	BN_free(&group->a);
+	BN_free(&group->b);
+}
+
+int
+ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
+{
+	if (!bn_copy(&dest->field, &src->field))
+		return 0;
+	if (!bn_copy(&dest->a, &src->a))
+		return 0;
+	if (!bn_copy(&dest->b, &src->b))
+		return 0;
+
+	dest->a_is_minus3 = src->a_is_minus3;
+
+	return 1;
+}
+
+static int
+ec_decode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
+{
+	if (bn == NULL)
+		return 1;
+
+	if (group->meth->field_decode != NULL)
+		return group->meth->field_decode(group, bn, x, ctx);
+
+	return bn_copy(bn, x);
+}
+
+static int
+ec_encode_scalar(const EC_GROUP *group, BIGNUM *bn, const BIGNUM *x, BN_CTX *ctx)
+{
+	if (!BN_nnmod(bn, x, &group->field, ctx))
+		return 0;
+
+	if (group->meth->field_encode != NULL)
+		return group->meth->field_encode(group, bn, bn, ctx);
+
+	return 1;
+}
+
+static int
+ec_encode_z_coordinate(const EC_GROUP *group, BIGNUM *bn, int *is_one,
+    const BIGNUM *z, BN_CTX *ctx)
+{
+	if (!BN_nnmod(bn, z, &group->field, ctx))
+		return 0;
+
+	*is_one = BN_is_one(bn);
+	if (*is_one && group->meth->field_set_to_one != NULL)
+		return group->meth->field_set_to_one(group, bn, ctx);
+
+	if (group->meth->field_encode != NULL)
+		return group->meth->field_encode(group, bn, bn, ctx);
+
+	return 1;
+}
+
+int
+ec_GFp_simple_group_set_curve(EC_GROUP *group,
+    const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+{
+	BIGNUM *a_plus_3;
+	int ret = 0;
+
+	/* p must be a prime > 3 */
+	if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
+		ECerror(EC_R_INVALID_FIELD);
+		return 0;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((a_plus_3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!bn_copy(&group->field, p))
+		goto err;
+	BN_set_negative(&group->field, 0);
+
+	if (!ec_encode_scalar(group, &group->a, a, ctx))
+		goto err;
+	if (!ec_encode_scalar(group, &group->b, b, ctx))
+		goto err;
+
+	if (!BN_set_word(a_plus_3, 3))
+		goto err;
+	if (!BN_mod_add(a_plus_3, a_plus_3, a, &group->field, ctx))
+		goto err;
+
+	group->a_is_minus3 = BN_is_zero(a_plus_3);
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
+    BIGNUM *b, BN_CTX *ctx)
+{
+	if (p != NULL) {
+		if (!bn_copy(p, &group->field))
+			return 0;
+	}
+	if (!ec_decode_scalar(group, a, &group->a, ctx))
+		return 0;
+	if (!ec_decode_scalar(group, b, &group->b, ctx))
+		return 0;
+
+	return 1;
+}
+
+int
+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)
+{
+	BIGNUM *p, *a, *b, *discriminant;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((a = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((discriminant = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!EC_GROUP_get_curve(group, p, a, b, ctx))
+		goto err;
+
+	/*
+	 * Check that the discriminant 4a^3 + 27b^2 is non-zero modulo p.
+	 */
+
+	if (BN_is_zero(a) && BN_is_zero(b))
+		goto err;
+	if (BN_is_zero(a) || BN_is_zero(b))
+		goto done;
+
+	/* Compute the discriminant: first 4a^3, then 27b^2, then their sum. */
+	if (!BN_mod_sqr(discriminant, a, p, ctx))
+		goto err;
+	if (!BN_mod_mul(discriminant, discriminant, a, p, ctx))
+		goto err;
+	if (!BN_lshift(discriminant, discriminant, 2))
+		goto err;
+
+	if (!BN_mod_sqr(b, b, p, ctx))
+		goto err;
+	if (!BN_mul_word(b, 27))
+		goto err;
+
+	if (!BN_mod_add(discriminant, discriminant, b, p, ctx))
+		goto err;
+
+	if (BN_is_zero(discriminant))
+		goto err;
+
+ done:
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_point_init(EC_POINT * point)
+{
+	BN_init(&point->X);
+	BN_init(&point->Y);
+	BN_init(&point->Z);
+	point->Z_is_one = 0;
+
+	return 1;
+}
+
+void
+ec_GFp_simple_point_finish(EC_POINT *point)
+{
+	BN_free(&point->X);
+	BN_free(&point->Y);
+	BN_free(&point->Z);
+	point->Z_is_one = 0;
+}
+
+int
+ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
+{
+	if (!bn_copy(&dest->X, &src->X))
+		return 0;
+	if (!bn_copy(&dest->Y, &src->Y))
+		return 0;
+	if (!bn_copy(&dest->Z, &src->Z))
+		return 0;
+	dest->Z_is_one = src->Z_is_one;
+
+	return 1;
+}
+
+int
+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(const EC_GROUP *group,
+    EC_POINT *point, const BIGNUM *x, const BIGNUM *y, const BIGNUM *z,
+    BN_CTX *ctx)
+{
+	int ret = 0;
+
+	/*
+	 * Setting individual coordinates allows the creation of bad points.
+	 * EC_POINT_set_Jprojective_coordinates() checks at the API boundary.
+	 */
+
+	if (x != NULL) {
+		if (!ec_encode_scalar(group, &point->X, x, ctx))
+			goto err;
+	}
+	if (y != NULL) {
+		if (!ec_encode_scalar(group, &point->Y, y, ctx))
+			goto err;
+	}
+	if (z != NULL) {
+		if (!ec_encode_z_coordinate(group, &point->Z, &point->Z_is_one,
+		    z, ctx))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+int
+ec_GFp_simple_get_Jprojective_coordinates(const EC_GROUP *group,
+    const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
+{
+	int ret = 0;
+
+	if (!ec_decode_scalar(group, x, &point->X, ctx))
+		goto err;
+	if (!ec_decode_scalar(group, y, &point->Y, ctx))
+		goto err;
+	if (!ec_decode_scalar(group, z, &point->Z, ctx))
+		goto err;
+
+	ret = 1;
+
+ err:
+	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)
+{
+	if (x == NULL || y == NULL) {
+		/* unlike for projective coordinates, we do not tolerate this */
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	return EC_POINT_set_Jprojective_coordinates(group, point, x, y,
+	    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)
+{
+	BIGNUM *z, *Z, *Z_1, *Z_2, *Z_3;
+	int ret = 0;
+
+	if (EC_POINT_is_at_infinity(group, point) > 0) {
+		ECerror(EC_R_POINT_AT_INFINITY);
+		return 0;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((z = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z_1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z_2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z_3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Convert from projective coordinates (X, Y, Z) into (X/Z^2, Y/Z^3). */
+
+	if (!ec_decode_scalar(group, z, &point->Z, ctx))
+		goto err;
+
+	if (BN_is_one(z)) {
+		if (!ec_decode_scalar(group, x, &point->X, ctx))
+			goto err;
+		if (!ec_decode_scalar(group, y, &point->Y, ctx))
+			goto err;
+		goto done;
+	}
+
+	if (BN_mod_inverse_ct(Z_1, z, &group->field, ctx) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (group->meth->field_encode == NULL) {
+		/* field_sqr works on standard representation */
+		if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
+			goto err;
+	} else {
+		if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))
+			goto err;
+	}
+
+	if (x != NULL) {
+		/*
+		 * in the Montgomery case, field_mul will cancel out
+		 * Montgomery factor in X:
+		 */
+		if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))
+			goto err;
+	}
+	if (y != NULL) {
+		if (group->meth->field_encode == NULL) {
+			/* field_mul works on standard representation */
+			if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
+				goto err;
+		} else {
+			if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))
+				goto err;
+		}
+
+		/*
+		 * in the Montgomery case, field_mul will cancel out
+		 * Montgomery factor in Y:
+		 */
+		if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx))
+			goto err;
+	}
+
+ done:
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	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 (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
+	const BIGNUM *p;
+	int ret = 0;
+
+	if (a == b)
+		return EC_POINT_dbl(group, r, a, ctx);
+	if (EC_POINT_is_at_infinity(group, a) > 0)
+		return EC_POINT_copy(r, b);
+	if (EC_POINT_is_at_infinity(group, b) > 0)
+		return EC_POINT_copy(r, a);
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	BN_CTX_start(ctx);
+
+	if ((n0 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n1 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n2 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n3 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n4 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n5 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((n6 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+
+	/*
+	 * Note that in this function we must not read components of 'a' or
+	 * 'b' once we have written the corresponding components of 'r'. ('r'
+	 * might be one of 'a' or 'b'.)
+	 */
+
+	/* n1, n2 */
+	if (b->Z_is_one) {
+		if (!bn_copy(n1, &a->X))
+			goto end;
+		if (!bn_copy(n2, &a->Y))
+			goto end;
+		/* n1 = X_a */
+		/* n2 = Y_a */
+	} else {
+		if (!field_sqr(group, n0, &b->Z, ctx))
+			goto end;
+		if (!field_mul(group, n1, &a->X, n0, ctx))
+			goto end;
+		/* n1 = X_a * Z_b^2 */
+
+		if (!field_mul(group, n0, n0, &b->Z, ctx))
+			goto end;
+		if (!field_mul(group, n2, &a->Y, n0, ctx))
+			goto end;
+		/* n2 = Y_a * Z_b^3 */
+	}
+
+	/* n3, n4 */
+	if (a->Z_is_one) {
+		if (!bn_copy(n3, &b->X))
+			goto end;
+		if (!bn_copy(n4, &b->Y))
+			goto end;
+		/* n3 = X_b */
+		/* n4 = Y_b */
+	} else {
+		if (!field_sqr(group, n0, &a->Z, ctx))
+			goto end;
+		if (!field_mul(group, n3, &b->X, n0, ctx))
+			goto end;
+		/* n3 = X_b * Z_a^2 */
+
+		if (!field_mul(group, n0, n0, &a->Z, ctx))
+			goto end;
+		if (!field_mul(group, n4, &b->Y, n0, ctx))
+			goto end;
+		/* n4 = Y_b * Z_a^3 */
+	}
+
+	/* n5, n6 */
+	if (!BN_mod_sub_quick(n5, n1, n3, p))
+		goto end;
+	if (!BN_mod_sub_quick(n6, n2, n4, p))
+		goto end;
+	/* n5 = n1 - n3 */
+	/* n6 = n2 - n4 */
+
+	if (BN_is_zero(n5)) {
+		if (BN_is_zero(n6)) {
+			/* a is the same point as b */
+			BN_CTX_end(ctx);
+			ret = EC_POINT_dbl(group, r, a, ctx);
+			ctx = NULL;
+			goto end;
+		} else {
+			/* a is the inverse of b */
+			BN_zero(&r->Z);
+			r->Z_is_one = 0;
+			ret = 1;
+			goto end;
+		}
+	}
+	/* 'n7', 'n8' */
+	if (!BN_mod_add_quick(n1, n1, n3, p))
+		goto end;
+	if (!BN_mod_add_quick(n2, n2, n4, p))
+		goto end;
+	/* 'n7' = n1 + n3 */
+	/* 'n8' = n2 + n4 */
+
+	/* Z_r */
+	if (a->Z_is_one && b->Z_is_one) {
+		if (!bn_copy(&r->Z, n5))
+			goto end;
+	} else {
+		if (a->Z_is_one) {
+			if (!bn_copy(n0, &b->Z))
+				goto end;
+		} else if (b->Z_is_one) {
+			if (!bn_copy(n0, &a->Z))
+				goto end;
+		} else {
+			if (!field_mul(group, n0, &a->Z, &b->Z, ctx))
+				goto end;
+		}
+		if (!field_mul(group, &r->Z, n0, n5, ctx))
+			goto end;
+	}
+	r->Z_is_one = 0;
+	/* Z_r = Z_a * Z_b * n5 */
+
+	/* X_r */
+	if (!field_sqr(group, n0, n6, ctx))
+		goto end;
+	if (!field_sqr(group, n4, n5, ctx))
+		goto end;
+	if (!field_mul(group, n3, n1, n4, ctx))
+		goto end;
+	if (!BN_mod_sub_quick(&r->X, n0, n3, p))
+		goto end;
+	/* X_r = n6^2 - n5^2 * 'n7' */
+
+	/* 'n9' */
+	if (!BN_mod_lshift1_quick(n0, &r->X, p))
+		goto end;
+	if (!BN_mod_sub_quick(n0, n3, n0, p))
+		goto end;
+	/* n9 = n5^2 * 'n7' - 2 * X_r */
+
+	/* Y_r */
+	if (!field_mul(group, n0, n0, n6, ctx))
+		goto end;
+	if (!field_mul(group, n5, n4, n5, ctx))
+		goto end;	/* now n5 is n5^3 */
+	if (!field_mul(group, n1, n2, n5, ctx))
+		goto end;
+	if (!BN_mod_sub_quick(n0, n0, n1, p))
+		goto end;
+	if (BN_is_odd(n0))
+		if (!BN_add(n0, n0, p))
+			goto end;
+	/* now  0 <= n0 < 2*p,  and n0 is even */
+	if (!BN_rshift1(&r->Y, n0))
+		goto end;
+	/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
+
+	ret = 1;
+
+ end:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+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 *);
+	int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	const BIGNUM *p;
+	BIGNUM *n0, *n1, *n2, *n3;
+	int ret = 0;
+
+	if (EC_POINT_is_at_infinity(group, a) > 0)
+		return EC_POINT_set_to_infinity(group, r);
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	BN_CTX_start(ctx);
+
+	if ((n0 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((n1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((n2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((n3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Note that in this function we must not read components of 'a' once
+	 * we have written the corresponding components of 'r'. ('r' might
+	 * the same as 'a'.)
+	 */
+
+	/* n1 */
+	if (a->Z_is_one) {
+		if (!field_sqr(group, n0, &a->X, ctx))
+			goto err;
+		if (!BN_mod_lshift1_quick(n1, n0, p))
+			goto err;
+		if (!BN_mod_add_quick(n0, n0, n1, p))
+			goto err;
+		if (!BN_mod_add_quick(n1, n0, &group->a, p))
+			goto err;
+		/* n1 = 3 * X_a^2 + a_curve */
+	} else if (group->a_is_minus3) {
+		if (!field_sqr(group, n1, &a->Z, ctx))
+			goto err;
+		if (!BN_mod_add_quick(n0, &a->X, n1, p))
+			goto err;
+		if (!BN_mod_sub_quick(n2, &a->X, n1, p))
+			goto err;
+		if (!field_mul(group, n1, n0, n2, ctx))
+			goto err;
+		if (!BN_mod_lshift1_quick(n0, n1, p))
+			goto err;
+		if (!BN_mod_add_quick(n1, n0, n1, p))
+			goto err;
+		/*
+		 * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) = 3 * X_a^2 - 3 *
+		 * Z_a^4
+		 */
+	} else {
+		if (!field_sqr(group, n0, &a->X, ctx))
+			goto err;
+		if (!BN_mod_lshift1_quick(n1, n0, p))
+			goto err;
+		if (!BN_mod_add_quick(n0, n0, n1, p))
+			goto err;
+		if (!field_sqr(group, n1, &a->Z, ctx))
+			goto err;
+		if (!field_sqr(group, n1, n1, ctx))
+			goto err;
+		if (!field_mul(group, n1, n1, &group->a, ctx))
+			goto err;
+		if (!BN_mod_add_quick(n1, n1, n0, p))
+			goto err;
+		/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
+	}
+
+	/* Z_r */
+	if (a->Z_is_one) {
+		if (!bn_copy(n0, &a->Y))
+			goto err;
+	} else {
+		if (!field_mul(group, n0, &a->Y, &a->Z, ctx))
+			goto err;
+	}
+	if (!BN_mod_lshift1_quick(&r->Z, n0, p))
+		goto err;
+	r->Z_is_one = 0;
+	/* Z_r = 2 * Y_a * Z_a */
+
+	/* n2 */
+	if (!field_sqr(group, n3, &a->Y, ctx))
+		goto err;
+	if (!field_mul(group, n2, &a->X, n3, ctx))
+		goto err;
+	if (!BN_mod_lshift_quick(n2, n2, 2, p))
+		goto err;
+	/* n2 = 4 * X_a * Y_a^2 */
+
+	/* X_r */
+	if (!BN_mod_lshift1_quick(n0, n2, p))
+		goto err;
+	if (!field_sqr(group, &r->X, n1, ctx))
+		goto err;
+	if (!BN_mod_sub_quick(&r->X, &r->X, n0, p))
+		goto err;
+	/* X_r = n1^2 - 2 * n2 */
+
+	/* n3 */
+	if (!field_sqr(group, n0, n3, ctx))
+		goto err;
+	if (!BN_mod_lshift_quick(n3, n0, 3, p))
+		goto err;
+	/* n3 = 8 * Y_a^4 */
+
+	/* Y_r */
+	if (!BN_mod_sub_quick(n0, n2, &r->X, p))
+		goto err;
+	if (!field_mul(group, n0, n1, n0, ctx))
+		goto err;
+	if (!BN_mod_sub_quick(&r->Y, n0, n3, p))
+		goto err;
+	/* Y_r = n1 * (n2 - X_r) - n3 */
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+{
+	if (EC_POINT_is_at_infinity(group, point) > 0 || BN_is_zero(&point->Y))
+		/* point is its own inverse */
+		return 1;
+
+	return BN_usub(&point->Y, &group->field, &point->Y);
+}
+
+int
+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 (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	const BIGNUM *p;
+	BIGNUM *rh, *tmp, *Z4, *Z6;
+	int ret = -1;
+
+	if (EC_POINT_is_at_infinity(group, point) > 0)
+		return 1;
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+	p = &group->field;
+
+	BN_CTX_start(ctx);
+
+	if ((rh = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z4 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Z6 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * We have a curve defined by a Weierstrass equation y^2 = x^3 + a*x
+	 * + b. The point to consider is given in Jacobian projective
+	 * coordinates where  (X, Y, Z)  represents  (x, y) = (X/Z^2, Y/Z^3).
+	 * Substituting this and multiplying by  Z^6  transforms the above
+	 * equation into Y^2 = X^3 + a*X*Z^4 + b*Z^6. To test this, we add up
+	 * the right-hand side in 'rh'.
+	 */
+
+	/* rh := X^2 */
+	if (!field_sqr(group, rh, &point->X, ctx))
+		goto err;
+
+	if (!point->Z_is_one) {
+		if (!field_sqr(group, tmp, &point->Z, ctx))
+			goto err;
+		if (!field_sqr(group, Z4, tmp, ctx))
+			goto err;
+		if (!field_mul(group, Z6, Z4, tmp, ctx))
+			goto err;
+
+		/* rh := (rh + a*Z^4)*X */
+		if (group->a_is_minus3) {
+			if (!BN_mod_lshift1_quick(tmp, Z4, p))
+				goto err;
+			if (!BN_mod_add_quick(tmp, tmp, Z4, p))
+				goto err;
+			if (!BN_mod_sub_quick(rh, rh, tmp, p))
+				goto err;
+			if (!field_mul(group, rh, rh, &point->X, ctx))
+				goto err;
+		} else {
+			if (!field_mul(group, tmp, Z4, &group->a, ctx))
+				goto err;
+			if (!BN_mod_add_quick(rh, rh, tmp, p))
+				goto err;
+			if (!field_mul(group, rh, rh, &point->X, ctx))
+				goto err;
+		}
+
+		/* rh := rh + b*Z^6 */
+		if (!field_mul(group, tmp, &group->b, Z6, ctx))
+			goto err;
+		if (!BN_mod_add_quick(rh, rh, tmp, p))
+			goto err;
+	} else {
+		/* point->Z_is_one */
+
+		/* rh := (rh + a)*X */
+		if (!BN_mod_add_quick(rh, rh, &group->a, p))
+			goto err;
+		if (!field_mul(group, rh, rh, &point->X, ctx))
+			goto err;
+		/* rh := rh + b */
+		if (!BN_mod_add_quick(rh, rh, &group->b, p))
+			goto err;
+	}
+
+	/* 'lh' := Y^2 */
+	if (!field_sqr(group, tmp, &point->Y, ctx))
+		goto err;
+
+	ret = (0 == BN_ucmp(tmp, rh));
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
+{
+	/*
+	 * return values: -1   error 0   equal (in affine coordinates) 1
+	 * not equal
+	 */
+
+	int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *);
+	int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
+	BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
+	const BIGNUM *tmp1_, *tmp2_;
+	int ret = -1;
+
+	if (EC_POINT_is_at_infinity(group, a) > 0)
+		return EC_POINT_is_at_infinity(group, b) > 0 ? 0 : 1;
+
+	if (EC_POINT_is_at_infinity(group, b) > 0)
+		return 1;
+
+	if (a->Z_is_one && b->Z_is_one)
+		return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
+
+	field_mul = group->meth->field_mul;
+	field_sqr = group->meth->field_sqr;
+
+	BN_CTX_start(ctx);
+
+	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((tmp2 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((Za23 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+	if ((Zb23 = BN_CTX_get(ctx)) == NULL)
+		goto end;
+
+	/*
+	 * We have to decide whether (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2,
+	 * Y_b/Z_b^3), or equivalently, whether (X_a*Z_b^2, Y_a*Z_b^3) =
+	 * (X_b*Z_a^2, Y_b*Z_a^3).
+	 */
+
+	if (!b->Z_is_one) {
+		if (!field_sqr(group, Zb23, &b->Z, ctx))
+			goto end;
+		if (!field_mul(group, tmp1, &a->X, Zb23, ctx))
+			goto end;
+		tmp1_ = tmp1;
+	} else
+		tmp1_ = &a->X;
+	if (!a->Z_is_one) {
+		if (!field_sqr(group, Za23, &a->Z, ctx))
+			goto end;
+		if (!field_mul(group, tmp2, &b->X, Za23, ctx))
+			goto end;
+		tmp2_ = tmp2;
+	} else
+		tmp2_ = &b->X;
+
+	/* compare  X_a*Z_b^2  with  X_b*Z_a^2 */
+	if (BN_cmp(tmp1_, tmp2_) != 0) {
+		ret = 1;	/* points differ */
+		goto end;
+	}
+	if (!b->Z_is_one) {
+		if (!field_mul(group, Zb23, Zb23, &b->Z, ctx))
+			goto end;
+		if (!field_mul(group, tmp1, &a->Y, Zb23, ctx))
+			goto end;
+		/* tmp1_ = tmp1 */
+	} else
+		tmp1_ = &a->Y;
+	if (!a->Z_is_one) {
+		if (!field_mul(group, Za23, Za23, &a->Z, ctx))
+			goto end;
+		if (!field_mul(group, tmp2, &b->Y, Za23, ctx))
+			goto end;
+		/* tmp2_ = tmp2 */
+	} else
+		tmp2_ = &b->Y;
+
+	/* compare  Y_a*Z_b^3  with  Y_b*Z_a^3 */
+	if (BN_cmp(tmp1_, tmp2_) != 0) {
+		ret = 1;	/* points differ */
+		goto end;
+	}
+	/* points are equal */
+	ret = 0;
+
+ end:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
+{
+	BIGNUM *x, *y;
+	int ret = 0;
+
+	if (point->Z_is_one || EC_POINT_is_at_infinity(group, point) > 0)
+		return 1;
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
+		goto err;
+	if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
+		goto err;
+	if (!point->Z_is_one) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+int
+ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
+{
+	BIGNUM *tmp0, *tmp1;
+	size_t pow2 = 0;
+	BIGNUM **heap = NULL;
+	size_t i;
+	int ret = 0;
+
+	if (num == 0)
+		return 1;
+
+	BN_CTX_start(ctx);
+
+	if ((tmp0 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/*
+	 * Before converting the individual points, compute inverses of all Z
+	 * values. Modular inversion is rather slow, but luckily we can do
+	 * with a single explicit inversion, plus about 3 multiplications per
+	 * input value.
+	 */
+
+	pow2 = 1;
+	while (num > pow2)
+		pow2 <<= 1;
+	/*
+	 * Now pow2 is the smallest power of 2 satifsying pow2 >= num. We
+	 * need twice that.
+	 */
+	pow2 <<= 1;
+
+	heap = reallocarray(NULL, pow2, sizeof heap[0]);
+	if (heap == NULL)
+		goto err;
+
+	/*
+	 * The array is used as a binary tree, exactly as in heapsort:
+	 *
+	 * heap[1] heap[2]                     heap[3] heap[4]       heap[5]
+	 * heap[6]       heap[7] heap[8]heap[9] heap[10]heap[11]
+	 * heap[12]heap[13] heap[14] heap[15]
+	 *
+	 * We put the Z's in the last line; then we set each other node to the
+	 * product of its two child-nodes (where empty or 0 entries are
+	 * treated as ones); then we invert heap[1]; then we invert each
+	 * other node by replacing it by the product of its parent (after
+	 * inversion) and its sibling (before inversion).
+	 */
+	heap[0] = NULL;
+	for (i = pow2 / 2 - 1; i > 0; i--)
+		heap[i] = NULL;
+	for (i = 0; i < num; i++)
+		heap[pow2 / 2 + i] = &points[i]->Z;
+	for (i = pow2 / 2 + num; i < pow2; i++)
+		heap[i] = NULL;
+
+	/* set each node to the product of its children */
+	for (i = pow2 / 2 - 1; i > 0; i--) {
+		heap[i] = BN_new();
+		if (heap[i] == NULL)
+			goto err;
+
+		if (heap[2 * i] != NULL) {
+			if ((heap[2 * i + 1] == NULL) || BN_is_zero(heap[2 * i + 1])) {
+				if (!bn_copy(heap[i], heap[2 * i]))
+					goto err;
+			} else {
+				if (BN_is_zero(heap[2 * i])) {
+					if (!bn_copy(heap[i], heap[2 * i + 1]))
+						goto err;
+				} else {
+					if (!group->meth->field_mul(group, heap[i],
+						heap[2 * i], heap[2 * i + 1], ctx))
+						goto err;
+				}
+			}
+		}
+	}
+
+	/* invert heap[1] */
+	if (!BN_is_zero(heap[1])) {
+		if (BN_mod_inverse_ct(heap[1], heap[1], &group->field, ctx) == NULL) {
+			ECerror(ERR_R_BN_LIB);
+			goto err;
+		}
+	}
+	if (group->meth->field_encode != NULL) {
+		/*
+		 * in the Montgomery case, we just turned  R*H  (representing
+		 * H) into  1/(R*H),  but we need  R*(1/H)  (representing
+		 * 1/H); i.e. we have need to multiply by the Montgomery
+		 * factor twice
+		 */
+		if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
+			goto err;
+		if (!group->meth->field_encode(group, heap[1], heap[1], ctx))
+			goto err;
+	}
+	/* set other heap[i]'s to their inverses */
+	for (i = 2; i < pow2 / 2 + num; i += 2) {
+		/* i is even */
+		if ((heap[i + 1] != NULL) && !BN_is_zero(heap[i + 1])) {
+			if (!group->meth->field_mul(group, tmp0, heap[i / 2], heap[i + 1], ctx))
+				goto err;
+			if (!group->meth->field_mul(group, tmp1, heap[i / 2], heap[i], ctx))
+				goto err;
+			if (!bn_copy(heap[i], tmp0))
+				goto err;
+			if (!bn_copy(heap[i + 1], tmp1))
+				goto err;
+		} else {
+			if (!bn_copy(heap[i], heap[i / 2]))
+				goto err;
+		}
+	}
+
+	/*
+	 * we have replaced all non-zero Z's by their inverses, now fix up
+	 * all the points
+	 */
+	for (i = 0; i < num; i++) {
+		EC_POINT *p = points[i];
+
+		if (!BN_is_zero(&p->Z)) {
+			/* turn  (X, Y, 1/Z)  into  (X/Z^2, Y/Z^3, 1) */
+
+			if (!group->meth->field_sqr(group, tmp1, &p->Z, ctx))
+				goto err;
+			if (!group->meth->field_mul(group, &p->X, &p->X, tmp1, ctx))
+				goto err;
+
+			if (!group->meth->field_mul(group, tmp1, tmp1, &p->Z, ctx))
+				goto err;
+			if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp1, ctx))
+				goto err;
+
+			if (group->meth->field_set_to_one != NULL) {
+				if (!group->meth->field_set_to_one(group, &p->Z, ctx))
+					goto err;
+			} else {
+				if (!BN_one(&p->Z))
+					goto err;
+			}
+			p->Z_is_one = 1;
+		}
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+
+	if (heap != NULL) {
+		/*
+		 * heap[pow2/2] .. heap[pow2-1] have not been allocated
+		 * locally!
+		 */
+		for (i = pow2 / 2 - 1; i > 0; i--) {
+			BN_free(heap[i]);
+		}
+		free(heap);
+	}
+	return ret;
+}
+
+int
+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)
+{
+	return BN_mod_sqr(r, a, &group->field, ctx);
+}
+
+/*
+ * Apply randomization of EC point projective coordinates:
+ *
+ *	(X, Y, Z) = (lambda^2 * X, lambda^3 * Y, lambda * Z)
+ *
+ * where lambda is in the interval [1, group->field).
+ */
+int
+ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
+{
+	BIGNUM *lambda = NULL;
+	BIGNUM *tmp = NULL;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+	if ((lambda = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Generate lambda in [1, group->field). */
+	if (!bn_rand_interval(lambda, 1, &group->field))
+		goto err;
+
+	if (group->meth->field_encode != NULL &&
+	    !group->meth->field_encode(group, lambda, lambda, ctx))
+		goto err;
+
+	/* Z = lambda * Z */
+	if (!group->meth->field_mul(group, &p->Z, lambda, &p->Z, ctx))
+		goto err;
+
+	/* tmp = lambda^2 */
+	if (!group->meth->field_sqr(group, tmp, lambda, ctx))
+		goto err;
+
+	/* X = lambda^2 * X */
+	if (!group->meth->field_mul(group, &p->X, tmp, &p->X, ctx))
+		goto err;
+
+	/* tmp = lambda^3 */
+	if (!group->meth->field_mul(group, tmp, tmp, lambda, ctx))
+		goto err;
+
+	/* Y = lambda^3 * Y */
+	if (!group->meth->field_mul(group, &p->Y, tmp, &p->Y, ctx))
+		goto err;
+
+	/* Disable optimized arithmetics after replacing Z by lambda * Z. */
+	p->Z_is_one = 0;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	return ret;
+}
+
+#define EC_POINT_BN_set_flags(P, flags) do {				\
+	BN_set_flags(&(P)->X, (flags));					\
+	BN_set_flags(&(P)->Y, (flags));					\
+	BN_set_flags(&(P)->Z, (flags));					\
+} while(0)
+
+#define EC_POINT_CSWAP(c, a, b, w, t) do {				\
+	if (!BN_swap_ct(c, &(a)->X, &(b)->X, w)	||			\
+	    !BN_swap_ct(c, &(a)->Y, &(b)->Y, w)	||			\
+	    !BN_swap_ct(c, &(a)->Z, &(b)->Z, w))			\
+		goto err;						\
+	t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c);			\
+	(a)->Z_is_one ^= (t);						\
+	(b)->Z_is_one ^= (t);						\
+} while(0)
+
+/*
+ * This function computes (in constant time) a point multiplication over the
+ * EC group.
+ *
+ * At a high level, it is Montgomery ladder with conditional swaps.
+ *
+ * It performs either a fixed point multiplication
+ *          (scalar * generator)
+ * when point is NULL, or a variable point multiplication
+ *          (scalar * point)
+ * when point is not NULL.
+ *
+ * scalar should be in the range [0,n) otherwise all constant time bets are off.
+ *
+ * NB: This says nothing about EC_POINT_add and EC_POINT_dbl,
+ * which of course are not constant time themselves.
+ *
+ * The product is stored in r.
+ *
+ * Returns 1 on success, 0 otherwise.
+ */
+static int
+ec_GFp_simple_mul_ct(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 *s = NULL;
+	BIGNUM *k = NULL;
+	BIGNUM *lambda = NULL;
+	BIGNUM *cardinality = NULL;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+
+	if ((s = EC_POINT_new(group)) == NULL)
+		goto err;
+
+	if (point == NULL) {
+		if (!EC_POINT_copy(s, group->generator))
+			goto err;
+	} else {
+		if (!EC_POINT_copy(s, point))
+			goto err;
+	}
+
+	EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
+
+	if ((cardinality = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((lambda = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (!BN_mul(cardinality, &group->order, &group->cofactor, ctx))
+		goto err;
+
+	/*
+	 * Group cardinalities are often on a word boundary.
+	 * So when we pad the scalar, some timing diff might
+	 * pop if it needs to be expanded due to carries.
+	 * So expand ahead of time.
+	 */
+	cardinality_bits = BN_num_bits(cardinality);
+	group_top = cardinality->top;
+	if (!bn_wexpand(k, group_top + 2) ||
+	    !bn_wexpand(lambda, group_top + 2))
+		goto err;
+
+	if (!bn_copy(k, scalar))
+		goto err;
+
+	BN_set_flags(k, BN_FLG_CONSTTIME);
+
+	if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) {
+		/*
+		 * This is an unusual input, and we don't guarantee
+		 * constant-timeness
+		 */
+		if (!BN_nnmod(k, k, cardinality, ctx))
+			goto err;
+	}
+
+	if (!BN_add(lambda, k, cardinality))
+		goto err;
+	BN_set_flags(lambda, BN_FLG_CONSTTIME);
+	if (!BN_add(k, lambda, cardinality))
+		goto err;
+	/*
+	 * lambda := scalar + cardinality
+	 * k := scalar + 2*cardinality
+	 */
+	kbit = BN_is_bit_set(lambda, cardinality_bits);
+	if (!BN_swap_ct(kbit, k, lambda, group_top + 2))
+		goto err;
+
+	group_top = group->field.top;
+	if (!bn_wexpand(&s->X, group_top) ||
+	    !bn_wexpand(&s->Y, group_top) ||
+	    !bn_wexpand(&s->Z, group_top) ||
+	    !bn_wexpand(&r->X, group_top) ||
+	    !bn_wexpand(&r->Y, group_top) ||
+	    !bn_wexpand(&r->Z, group_top))
+		goto err;
+
+	/*
+	 * Apply coordinate blinding for EC_POINT if the underlying EC_METHOD
+	 * implements it.
+	 */
+	if (!ec_point_blind_coordinates(group, s, ctx))
+		goto err;
+
+	/* top bit is a 1, in a fixed pos */
+	if (!EC_POINT_copy(r, s))
+		goto err;
+
+	EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
+
+	if (!EC_POINT_dbl(group, s, s, ctx))
+		goto err;
+
+	pbit = 0;
+
+	/*
+	 * The ladder step, with branches, is
+	 *
+	 * k[i] == 0: S = add(R, S), R = dbl(R)
+	 * k[i] == 1: R = add(S, R), S = dbl(S)
+	 *
+	 * Swapping R, S conditionally on k[i] leaves you with state
+	 *
+	 * k[i] == 0: T, U = R, S
+	 * k[i] == 1: T, U = S, R
+	 *
+	 * Then perform the ECC ops.
+	 *
+	 * U = add(T, U)
+	 * T = dbl(T)
+	 *
+	 * Which leaves you with state
+	 *
+	 * k[i] == 0: U = add(R, S), T = dbl(R)
+	 * k[i] == 1: U = add(S, R), T = dbl(S)
+	 *
+	 * Swapping T, U conditionally on k[i] leaves you with state
+	 *
+	 * k[i] == 0: R, S = T, U
+	 * k[i] == 1: R, S = U, T
+	 *
+	 * Which leaves you with state
+	 *
+	 * k[i] == 0: S = add(R, S), R = dbl(R)
+	 * k[i] == 1: R = add(S, R), S = dbl(S)
+	 *
+	 * So we get the same logic, but instead of a branch it's a
+	 * conditional swap, followed by ECC ops, then another conditional swap.
+	 *
+	 * Optimization: The end of iteration i and start of i-1 looks like
+	 *
+	 * ...
+	 * CSWAP(k[i], R, S)
+	 * ECC
+	 * CSWAP(k[i], R, S)
+	 * (next iteration)
+	 * CSWAP(k[i-1], R, S)
+	 * ECC
+	 * CSWAP(k[i-1], R, S)
+	 * ...
+	 *
+	 * So instead of two contiguous swaps, you can merge the condition
+	 * bits and do a single swap.
+	 *
+	 * k[i]   k[i-1]    Outcome
+	 * 0      0         No Swap
+	 * 0      1         Swap
+	 * 1      0         Swap
+	 * 1      1         No Swap
+	 *
+	 * This is XOR. pbit tracks the previous bit of k.
+	 */
+
+	for (i = cardinality_bits - 1; i >= 0; i--) {
+		kbit = BN_is_bit_set(k, i) ^ pbit;
+		EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
+		if (!EC_POINT_add(group, s, r, s, ctx))
+			goto err;
+		if (!EC_POINT_dbl(group, r, r, ctx))
+			goto err;
+		/*
+		 * pbit logic merges this cswap with that of the
+		 * next iteration
+		 */
+		pbit ^= kbit;
+	}
+	/* one final cswap to move the right value into r */
+	EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
+
+	ret = 1;
+
+ err:
+	EC_POINT_free(s);
+	BN_CTX_end(ctx);
+
+	return ret;
+}
+
+#undef EC_POINT_BN_set_flags
+#undef EC_POINT_CSWAP
+
+int
+ec_GFp_simple_mul_generator_ct(const EC_GROUP *group, EC_POINT *r,
+    const BIGNUM *scalar, BN_CTX *ctx)
+{
+	return ec_GFp_simple_mul_ct(group, r, scalar, NULL, ctx);
+}
+
+int
+ec_GFp_simple_mul_single_ct(const EC_GROUP *group, EC_POINT *r,
+    const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx)
+{
+	return ec_GFp_simple_mul_ct(group, r, scalar, point, ctx);
+}
+
+int
+ec_GFp_simple_mul_double_nonct(const EC_GROUP *group, EC_POINT *r,
+    const BIGNUM *g_scalar, const BIGNUM *p_scalar, const EC_POINT *point,
+    BN_CTX *ctx)
+{
+	return ec_wNAF_mul(group, r, g_scalar, 1, &point, &p_scalar, ctx);
+}
+
+static const EC_METHOD ec_GFp_simple_method = {
+	.field_type = NID_X9_62_prime_field,
+	.group_init = ec_GFp_simple_group_init,
+	.group_finish = ec_GFp_simple_group_finish,
+	.group_copy = ec_GFp_simple_group_copy,
+	.group_set_curve = ec_GFp_simple_group_set_curve,
+	.group_get_curve = ec_GFp_simple_group_get_curve,
+	.group_get_degree = ec_GFp_simple_group_get_degree,
+	.group_order_bits = ec_group_simple_order_bits,
+	.group_check_discriminant = ec_GFp_simple_group_check_discriminant,
+	.point_init = ec_GFp_simple_point_init,
+	.point_finish = ec_GFp_simple_point_finish,
+	.point_copy = ec_GFp_simple_point_copy,
+	.point_set_to_infinity = ec_GFp_simple_point_set_to_infinity,
+	.point_set_Jprojective_coordinates =
+	    ec_GFp_simple_set_Jprojective_coordinates,
+	.point_get_Jprojective_coordinates =
+	    ec_GFp_simple_get_Jprojective_coordinates,
+	.point_set_affine_coordinates =
+	    ec_GFp_simple_point_set_affine_coordinates,
+	.point_get_affine_coordinates =
+	    ec_GFp_simple_point_get_affine_coordinates,
+	.point_set_compressed_coordinates =
+	    ec_GFp_simple_set_compressed_coordinates,
+	.point2oct = ec_GFp_simple_point2oct,
+	.oct2point = ec_GFp_simple_oct2point,
+	.add = ec_GFp_simple_add,
+	.dbl = ec_GFp_simple_dbl,
+	.invert = ec_GFp_simple_invert,
+	.is_at_infinity = ec_GFp_simple_is_at_infinity,
+	.is_on_curve = ec_GFp_simple_is_on_curve,
+	.point_cmp = ec_GFp_simple_cmp,
+	.make_affine = ec_GFp_simple_make_affine,
+	.points_make_affine = ec_GFp_simple_points_make_affine,
+	.mul_generator_ct = ec_GFp_simple_mul_generator_ct,
+	.mul_single_ct = ec_GFp_simple_mul_single_ct,
+	.mul_double_nonct = ec_GFp_simple_mul_double_nonct,
+	.field_mul = ec_GFp_simple_field_mul,
+	.field_sqr = ec_GFp_simple_field_sqr,
+	.blind_coordinates = ec_GFp_simple_blind_coordinates,
+};
+
+const EC_METHOD *
+EC_GFp_simple_method(void)
+{
+	return &ec_GFp_simple_method;
+}
+LCRYPTO_ALIAS(EC_GFp_simple_method);
diff --git a/crypto/ec/ecx_methods.c b/crypto/ec/ecx_methods.c
new file mode 100644
index 0000000..4bb8b78
--- /dev/null
+++ b/crypto/ec/ecx_methods.c
@@ -0,0 +1,897 @@
+/*	$OpenBSD: ecx_methods.c,v 1.9 2023/07/22 19:33:25 tb Exp $ */
+/*
+ * Copyright (c) 2022 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bytestring.h"
+#include "curve25519_internal.h"
+#include "evp_local.h"
+
+/*
+ * EVP PKEY and PKEY ASN.1 methods Ed25519 and X25519.
+ *
+ * RFC 7748 - Elliptic Curves for Security.
+ * RFC 8032 - Edwards-Curve Digital Signature Algorithm (EdDSA).
+ */
+
+#define ED25519_BITS		253
+#define ED25519_SECURITY_BITS	128
+#define ED25519_SIG_SIZE	64
+
+#define X25519_BITS		253
+#define X25519_SECURITY_BITS	128
+
+static int
+ecx_key_len(int nid)
+{
+	switch (nid) {
+	case NID_ED25519:
+		return ED25519_KEYLEN;
+	case NID_X25519:
+		return X25519_KEYLEN;
+	}
+
+	return 0;
+}
+
+static struct ecx_key_st *
+ecx_key_new(int nid)
+{
+	struct ecx_key_st *ecx_key;
+	int key_len;
+
+	if ((key_len = ecx_key_len(nid)) == 0)
+		return NULL;
+
+	if ((ecx_key = calloc(1, sizeof(*ecx_key))) == NULL)
+		return NULL;
+
+	ecx_key->nid = nid;
+	ecx_key->key_len = key_len;
+
+	return ecx_key;
+}
+
+static void
+ecx_key_clear(struct ecx_key_st *ecx_key)
+{
+	freezero(ecx_key->priv_key, ecx_key->priv_key_len);
+	ecx_key->priv_key = NULL;
+	ecx_key->priv_key_len = 0;
+
+	freezero(ecx_key->pub_key, ecx_key->pub_key_len);
+	ecx_key->pub_key = NULL;
+	ecx_key->pub_key_len = 0;
+}
+
+static void
+ecx_key_free(struct ecx_key_st *ecx_key)
+{
+	if (ecx_key == NULL)
+		return;
+
+	ecx_key_clear(ecx_key);
+
+	freezero(ecx_key, sizeof(*ecx_key));
+}
+
+static int
+ecx_key_generate(struct ecx_key_st *ecx_key)
+{
+	uint8_t *pub_key = NULL, *priv_key = NULL;
+	int ret = 0;
+
+	ecx_key_clear(ecx_key);
+
+	if ((pub_key = calloc(1, ecx_key->key_len)) == NULL)
+		goto err;
+	if ((priv_key = calloc(1, ecx_key->key_len)) == NULL)
+		goto err;
+
+	switch (ecx_key->nid) {
+	case NID_ED25519:
+		ED25519_keypair(pub_key, priv_key);
+		break;
+	case NID_X25519:
+		X25519_keypair(pub_key, priv_key);
+		break;
+	default:
+		goto err;
+	}
+
+	ecx_key->priv_key = priv_key;
+	ecx_key->priv_key_len = ecx_key->key_len;
+	priv_key = NULL;
+
+	ecx_key->pub_key = pub_key;
+	ecx_key->pub_key_len = ecx_key->key_len;
+	pub_key = NULL;
+
+	ret = 1;
+
+ err:
+	freezero(pub_key, ecx_key->key_len);
+	freezero(priv_key, ecx_key->key_len);
+
+	return ret;
+}
+
+static int
+ecx_key_set_priv(struct ecx_key_st *ecx_key, const uint8_t *priv_key,
+    size_t priv_key_len)
+{
+	uint8_t *pub_key = NULL;
+	CBS cbs;
+
+	ecx_key_clear(ecx_key);
+
+	if (priv_key_len != ecx_key->key_len)
+		goto err;
+
+	if ((pub_key = calloc(1, ecx_key->key_len)) == NULL)
+		goto err;
+
+	switch (ecx_key->nid) {
+	case NID_ED25519:
+		ED25519_public_from_private(pub_key, priv_key);
+		break;
+	case NID_X25519:
+		X25519_public_from_private(pub_key, priv_key);
+		break;
+	default:
+		goto err;
+	}
+
+	CBS_init(&cbs, priv_key, priv_key_len);
+	if (!CBS_stow(&cbs, &ecx_key->priv_key, &ecx_key->priv_key_len))
+		goto err;
+
+	ecx_key->pub_key = pub_key;
+	ecx_key->pub_key_len = ecx_key->key_len;
+	pub_key = NULL;
+
+ err:
+	freezero(pub_key, ecx_key->key_len);
+
+	return 1;
+}
+
+static int
+ecx_key_set_pub(struct ecx_key_st *ecx_key, const uint8_t *pub_key,
+    size_t pub_key_len)
+{
+	CBS cbs;
+
+	ecx_key_clear(ecx_key);
+
+	if (pub_key_len != ecx_key->key_len)
+		return 0;
+
+	CBS_init(&cbs, pub_key, pub_key_len);
+	if (!CBS_stow(&cbs, &ecx_key->pub_key, &ecx_key->pub_key_len))
+		return 0;
+
+	return 1;
+}
+
+static int
+ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *xpubkey)
+{
+	struct ecx_key_st *ecx_key = NULL;
+	X509_ALGOR *algor;
+	int algor_type;
+	const uint8_t *param;
+	int param_len;
+	int ret = 0;
+
+	if (!X509_PUBKEY_get0_param(NULL, ¶m, ¶m_len, &algor, xpubkey))
+		goto err;
+
+	/* Ensure that parameters have not been specified in the encoding. */
+	if (algor != NULL) {
+		X509_ALGOR_get0(NULL, &algor_type, NULL, algor);
+		if (algor_type != V_ASN1_UNDEF) {
+			ECerror(EC_R_INVALID_ENCODING);
+			goto err;
+		}
+	}
+
+	if (param == NULL || param_len != ecx_key_len(pkey->ameth->pkey_id)) {
+		ECerror(EC_R_INVALID_ENCODING);
+		goto err;
+	}
+
+	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!ecx_key_set_pub(ecx_key, param, param_len))
+		goto err;
+	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
+		goto err;
+	ecx_key = NULL;
+
+	ret = 1;
+
+ err:
+	ecx_key_free(ecx_key);
+
+	return ret;
+}
+
+static int
+ecx_pub_encode(X509_PUBKEY *xpubkey, const EVP_PKEY *pkey)
+{
+	const struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	uint8_t *pub_key = NULL;
+	size_t pub_key_len = 0;
+	ASN1_OBJECT *aobj;
+	CBS cbs;
+	int ret = 0;
+
+	if (ecx_key == NULL) {
+		ECerror(EC_R_INVALID_KEY);
+		goto err;
+	}
+
+	if (ecx_key->pub_key_len != ecx_key->key_len)
+		goto err;
+
+	if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+
+	CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
+	if (!CBS_stow(&cbs, &pub_key, &pub_key_len))
+		goto err;
+
+	if (!X509_PUBKEY_set0_param(xpubkey, aobj, V_ASN1_UNDEF, NULL,
+	    pub_key, pub_key_len))
+		goto err;
+
+	pub_key = NULL;
+	pub_key_len = 0;
+
+	ret = 1;
+
+ err:
+	free(pub_key);
+
+	return ret;
+}
+
+static int
+ecx_pub_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
+{
+	if (pkey1->pkey.ecx == NULL || pkey1->pkey.ecx->pub_key == NULL)
+		return -2;
+	if (pkey2->pkey.ecx == NULL || pkey2->pkey.ecx->pub_key == NULL)
+		return -2;
+	if (pkey1->pkey.ecx->pub_key_len != pkey2->pkey.ecx->pub_key_len)
+		return -2;
+
+	return timingsafe_memcmp(pkey1->pkey.ecx->pub_key, pkey2->pkey.ecx->pub_key,
+	    pkey1->pkey.ecx->pub_key_len) == 0;
+}
+
+/* Reimplementation of ASN1_buf_print() that adds a secondary indent of 4. */
+static int
+ecx_buf_print(BIO *bio, const uint8_t *buf, size_t buf_len, int indent)
+{
+	uint8_t u8;
+	size_t octets = 0;
+	const char *sep = ":", *nl = "";
+	CBS cbs;
+
+	if (indent > 60)
+		indent = 60;
+	indent += 4;
+	if (indent < 0)
+		indent = 0;
+
+	CBS_init(&cbs, buf, buf_len);
+	while (CBS_len(&cbs) > 0) {
+		if (!CBS_get_u8(&cbs, &u8))
+			return 0;
+		if (octets++ % 15 == 0) {
+			if (BIO_printf(bio, "%s%*s", nl, indent, "") < 0)
+				return 0;
+			nl = "\n";
+		}
+		if (CBS_len(&cbs) == 0)
+			sep = "";
+		if (BIO_printf(bio, "%02x%s", u8, sep) <= 0)
+			return 0;
+	}
+
+	if (BIO_printf(bio, "\n") <= 0)
+		return 0;
+
+	return 1;
+}
+
+static int
+ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	const char *name;
+
+	if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
+		return 0;
+
+	if (ecx_key == NULL || ecx_key->pub_key == NULL)
+		return BIO_printf(bio, "%*s\n",
+		    indent, "") > 0;
+
+	if (BIO_printf(bio, "%*s%s Public-Key:\n", indent, "", name) <= 0)
+		return 0;
+	if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
+		return 0;
+	if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
+		return 0;
+
+	return 1;
+}
+
+static int
+ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8pki)
+{
+	struct ecx_key_st *ecx_key = NULL;
+	ASN1_OCTET_STRING *aos = NULL;
+	const X509_ALGOR *algor;
+	int algor_type;
+	const uint8_t *param;
+	int param_len;
+	int ret = 0;
+
+	if (!PKCS8_pkey_get0(NULL, ¶m, ¶m_len, &algor, p8pki))
+		goto err;
+	if ((aos = d2i_ASN1_OCTET_STRING(NULL, ¶m, param_len)) == NULL)
+		goto err;
+
+	/* Ensure that parameters have not been specified in the encoding. */
+	if (algor != NULL) {
+		X509_ALGOR_get0(NULL, &algor_type, NULL, algor);
+		if (algor_type != V_ASN1_UNDEF) {
+			ECerror(EC_R_INVALID_ENCODING);
+			goto err;
+		}
+	}
+
+	if (ASN1_STRING_get0_data(aos) == NULL ||
+	    ASN1_STRING_length(aos) != ecx_key_len(pkey->ameth->pkey_id)) {
+		ECerror(EC_R_INVALID_ENCODING);
+		goto err;
+	}
+
+	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!ecx_key_set_priv(ecx_key, ASN1_STRING_get0_data(aos),
+	    ASN1_STRING_length(aos)))
+		goto err;
+	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
+		goto err;
+	ecx_key = NULL;
+
+	ret = 1;
+
+ err:
+	ASN1_OCTET_STRING_free(aos);
+	ecx_key_free(ecx_key);
+
+	return ret;
+}
+
+static int
+ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8pki, const EVP_PKEY *pkey)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	ASN1_OCTET_STRING *aos = NULL;
+	ASN1_OBJECT *aobj;
+	uint8_t *der = NULL;
+	int der_len = 0;
+	int ret = 0;
+
+	if (ecx_key == NULL || ecx_key->priv_key == NULL) {
+		ECerror(EC_R_INVALID_PRIVATE_KEY);
+		goto err;
+	}
+
+	if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+
+	if ((aos = ASN1_OCTET_STRING_new()) == NULL)
+		goto err;
+	if (!ASN1_OCTET_STRING_set(aos, ecx_key->priv_key,
+	    ecx_key->priv_key_len))
+		goto err;
+	if ((der_len = i2d_ASN1_OCTET_STRING(aos, &der)) < 0)
+		goto err;
+	if (!PKCS8_pkey_set0(p8pki, aobj, 0, V_ASN1_UNDEF, NULL, der, der_len))
+		goto err;
+
+	der = NULL;
+	der_len = 0;
+
+	ret = 1;
+
+ err:
+	freezero(der, der_len);
+	ASN1_OCTET_STRING_free(aos);
+
+	return ret;
+}
+
+static int
+ecx_priv_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	const char *name;
+
+	if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
+		return 0;
+
+	if (ecx_key == NULL || ecx_key->priv_key == NULL)
+		return BIO_printf(bio, "%*s\n",
+		    indent, "") > 0;
+
+	if (BIO_printf(bio, "%*s%s Private-Key:\n", indent, "", name) <= 0)
+		return 0;
+	if (BIO_printf(bio, "%*spriv:\n", indent, "") <= 0)
+		return 0;
+	if (!ecx_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len, indent))
+		return 0;
+	if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
+		return 0;
+	if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
+		return 0;
+
+	return 1;
+}
+
+static int
+ecx_size(const EVP_PKEY *pkey)
+{
+	return ecx_key_len(pkey->ameth->pkey_id);
+}
+
+static int
+ecx_sig_size(const EVP_PKEY *pkey)
+{
+	switch (pkey->ameth->pkey_id) {
+	case EVP_PKEY_ED25519:
+		return ED25519_SIG_SIZE;
+	}
+	return 0;
+}
+
+static int
+ecx_bits(const EVP_PKEY *pkey)
+{
+	switch (pkey->ameth->pkey_id) {
+	case EVP_PKEY_ED25519:
+		return ED25519_BITS;
+	case EVP_PKEY_X25519:
+		return X25519_BITS;
+	}
+	return 0;
+}
+
+static int
+ecx_security_bits(const EVP_PKEY *pkey)
+{
+	switch (pkey->ameth->pkey_id) {
+	case EVP_PKEY_ED25519:
+		return ED25519_SECURITY_BITS;
+	case EVP_PKEY_X25519:
+		return X25519_SECURITY_BITS;
+	}
+	return 0;
+}
+
+static int
+ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
+{
+	/* No parameters, so always equivalent. */
+	return 1;
+}
+
+static void
+ecx_free(EVP_PKEY *pkey)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+
+	ecx_key_free(ecx_key);
+}
+
+static int
+ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+	/* Not supported. */
+	return -2;
+}
+
+static int
+ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+	switch (op) {
+	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		/* PureEdDSA does its own hashing. */
+		*(int *)arg2 = NID_undef;
+		return 2;
+	}
+	return -2;
+}
+
+static int
+ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len)
+{
+	struct ecx_key_st *ecx_key = NULL;
+	int ret = 0;
+
+	if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
+		ECerror(EC_R_INVALID_ENCODING);
+		goto err;
+	}
+
+	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!ecx_key_set_priv(ecx_key, priv, len))
+		goto err;
+	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
+		goto err;
+	ecx_key = NULL;
+
+	ret = 1;
+
+ err:
+	ecx_key_free(ecx_key);
+
+	return ret;
+}
+
+static int
+ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len)
+{
+	struct ecx_key_st *ecx_key = NULL;
+	int ret = 0;
+
+	if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
+		ECerror(EC_R_INVALID_ENCODING);
+		goto err;
+	}
+
+	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!ecx_key_set_pub(ecx_key, pub, len))
+		goto err;
+	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
+		goto err;
+	ecx_key = NULL;
+
+	ret = 1;
+
+ err:
+	ecx_key_free(ecx_key);
+
+	return ret;
+}
+
+static int
+ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *out_priv, size_t *out_len)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	CBS cbs;
+
+	if (out_priv == NULL) {
+		*out_len = ecx_key_len(pkey->ameth->pkey_id);
+		return 1;
+	}
+
+	if (ecx_key == NULL || ecx_key->priv_key == NULL)
+		return 0;
+
+	CBS_init(&cbs, ecx_key->priv_key, ecx_key->priv_key_len);
+	if (!CBS_write_bytes(&cbs, out_priv, *out_len, out_len))
+		return 0;
+
+	return 1;
+}
+
+static int
+ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *out_pub, size_t *out_len)
+{
+	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
+	CBS cbs;
+
+	if (out_pub == NULL) {
+		*out_len = ecx_key_len(pkey->ameth->pkey_id);
+		return 1;
+	}
+
+	if (ecx_key == NULL || ecx_key->pub_key == NULL)
+		return 0;
+
+	CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
+	if (!CBS_write_bytes(&cbs, out_pub, *out_len, out_len))
+		return 0;
+
+	return 1;
+}
+
+static int
+pkey_ecx_keygen(EVP_PKEY_CTX *pkey_ctx, EVP_PKEY *pkey)
+{
+	struct ecx_key_st *ecx_key = NULL;
+	int ret = 0;
+
+	if ((ecx_key = ecx_key_new(pkey_ctx->pmeth->pkey_id)) == NULL)
+		goto err;
+	if (!ecx_key_generate(ecx_key))
+		goto err;
+	if (!EVP_PKEY_assign(pkey, pkey_ctx->pmeth->pkey_id, ecx_key))
+		goto err;
+	ecx_key = NULL;
+
+	ret = 1;
+
+ err:
+	ecx_key_free(ecx_key);
+
+	return ret;
+}
+
+static int
+pkey_ecx_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *out_key,
+    size_t *out_key_len)
+{
+	struct ecx_key_st *ecx_key, *ecx_peer_key;
+
+	if (pkey_ctx->pkey == NULL || pkey_ctx->peerkey == NULL) {
+		ECerror(EC_R_KEYS_NOT_SET);
+		return 0;
+	}
+
+	if ((ecx_key = pkey_ctx->pkey->pkey.ecx) == NULL) {
+		ECerror(EC_R_INVALID_PRIVATE_KEY);
+		return 0;
+	}
+	if (ecx_key->priv_key == NULL) {
+		ECerror(EC_R_INVALID_PRIVATE_KEY);
+		return 0;
+	}
+
+	if ((ecx_peer_key = pkey_ctx->peerkey->pkey.ecx) == NULL) {
+		ECerror(EC_R_INVALID_PEER_KEY);
+		return 0;
+	}
+
+	if (out_key != NULL) {
+		if (!X25519(out_key, ecx_key->priv_key, ecx_peer_key->pub_key))
+			return 0;
+	}
+
+	*out_key_len = X25519_KEYLEN;
+
+	return 1;
+}
+
+static int
+pkey_ecx_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
+{
+	if (op == EVP_PKEY_CTRL_PEER_KEY)
+		return 1;
+
+	return -2;
+}
+
+static int
+ecx_item_verify(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
+   X509_ALGOR *algor, ASN1_BIT_STRING *abs, EVP_PKEY *pkey)
+{
+	const ASN1_OBJECT *aobj;
+	int nid, param_type;
+
+	X509_ALGOR_get0(&aobj, ¶m_type, NULL, algor);
+
+	nid = OBJ_obj2nid(aobj);
+
+	if (nid != NID_ED25519 || param_type != V_ASN1_UNDEF) {
+		ECerror(EC_R_INVALID_ENCODING);
+		return -1;
+	}
+
+	if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey))
+		return -1;
+
+	return 2;
+}
+
+static int
+ecx_item_sign(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
+    X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *abs)
+{
+	ASN1_OBJECT *aobj;
+
+	if ((aobj = OBJ_nid2obj(NID_ED25519)) == NULL)
+		return 0;
+
+	if (!X509_ALGOR_set0(algor1, aobj, V_ASN1_UNDEF, NULL))
+		return 0;
+
+	if (algor2 != NULL) {
+		if (!X509_ALGOR_set0(algor2, aobj, V_ASN1_UNDEF, NULL))
+			return 0;
+	}
+
+	/* Tell ASN1_item_sign_ctx() that identifiers are set and it needs to sign. */
+	return 3;
+}
+
+static int
+pkey_ecx_digestsign(EVP_MD_CTX *md_ctx, unsigned char *out_sig,
+    size_t *out_sig_len, const unsigned char *message, size_t message_len)
+{
+	struct ecx_key_st *ecx_key;
+	EVP_PKEY_CTX *pkey_ctx;
+
+	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
+	ecx_key = pkey_ctx->pkey->pkey.ecx;
+
+	if (out_sig == NULL) {
+		*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
+		return 1;
+	}
+	if (*out_sig_len < ecx_sig_size(pkey_ctx->pkey)) {
+		ECerror(EC_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	if (ecx_key == NULL)
+		return 0;
+	if (ecx_key->priv_key == NULL || ecx_key->pub_key == NULL)
+		return 0;
+
+	if (!ED25519_sign(out_sig, message, message_len, ecx_key->pub_key,
+	    ecx_key->priv_key))
+		return 0;
+
+	*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
+
+	return 1;
+}
+
+static int
+pkey_ecx_digestverify(EVP_MD_CTX *md_ctx, const unsigned char *sig,
+   size_t sig_len, const unsigned char *message, size_t message_len)
+{
+	struct ecx_key_st *ecx_key;
+	EVP_PKEY_CTX *pkey_ctx;
+
+	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
+	ecx_key = pkey_ctx->pkey->pkey.ecx;
+
+	if (ecx_key == NULL || ecx_key->pub_key == NULL)
+		return -1;
+	if (sig_len != ecx_sig_size(pkey_ctx->pkey))
+		return -1;
+
+	return ED25519_verify(message, message_len, sig, ecx_key->pub_key);
+}
+
+static int
+pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
+{
+	switch (op) {
+	case EVP_PKEY_CTRL_MD:
+		/* PureEdDSA does its own hashing. */
+		if (arg2 != NULL && (const EVP_MD *)arg2 != EVP_md_null()) {
+			ECerror(EC_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		return 1;
+
+	case EVP_PKEY_CTRL_DIGESTINIT:
+		return 1;
+	}
+	return -2;
+}
+
+const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
+	.pkey_id = EVP_PKEY_X25519,
+	.pkey_base_id = EVP_PKEY_X25519,
+	.pkey_flags = 0,
+	.pem_str = "X25519",
+	.info = "OpenSSL X25519 algorithm",
+
+	.pub_decode = ecx_pub_decode,
+	.pub_encode = ecx_pub_encode,
+	.pub_cmp = ecx_pub_cmp,
+	.pub_print = ecx_pub_print,
+
+	.priv_decode = ecx_priv_decode,
+	.priv_encode = ecx_priv_encode,
+	.priv_print = ecx_priv_print,
+
+	.pkey_size = ecx_size,
+	.pkey_bits = ecx_bits,
+	.pkey_security_bits = ecx_security_bits,
+
+	.param_cmp = ecx_param_cmp,
+
+	.pkey_free = ecx_free,
+	.pkey_ctrl = ecx_ctrl,
+
+	.set_priv_key = ecx_set_priv_key,
+	.set_pub_key = ecx_set_pub_key,
+	.get_priv_key = ecx_get_priv_key,
+	.get_pub_key = ecx_get_pub_key,
+};
+
+const EVP_PKEY_METHOD x25519_pkey_meth = {
+	.pkey_id = EVP_PKEY_X25519,
+	.keygen = pkey_ecx_keygen,
+	.derive = pkey_ecx_derive,
+	.ctrl = pkey_ecx_ctrl,
+};
+
+const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
+	.pkey_id = EVP_PKEY_ED25519,
+	.pkey_base_id = EVP_PKEY_ED25519,
+	.pkey_flags = 0,
+	.pem_str = "ED25519",
+	.info = "OpenSSL ED25519 algorithm",
+
+	.pub_decode = ecx_pub_decode,
+	.pub_encode = ecx_pub_encode,
+	.pub_cmp = ecx_pub_cmp,
+	.pub_print = ecx_pub_print,
+
+	.priv_decode = ecx_priv_decode,
+	.priv_encode = ecx_priv_encode,
+	.priv_print = ecx_priv_print,
+
+	.pkey_size = ecx_sig_size,
+	.pkey_bits = ecx_bits,
+	.pkey_security_bits = ecx_security_bits,
+
+	.param_cmp = ecx_param_cmp,
+
+	.pkey_free = ecx_free,
+	.pkey_ctrl = ecx_sign_ctrl,
+
+	.item_verify = ecx_item_verify,
+	.item_sign = ecx_item_sign,
+
+	.set_priv_key = ecx_set_priv_key,
+	.set_pub_key = ecx_set_pub_key,
+	.get_priv_key = ecx_get_priv_key,
+	.get_pub_key = ecx_get_pub_key,
+};
+
+const EVP_PKEY_METHOD ed25519_pkey_meth = {
+	.pkey_id = EVP_PKEY_ED25519,
+	.flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM,
+	.keygen = pkey_ecx_keygen,
+	.ctrl = pkey_ecx_ed_ctrl,
+	.digestsign = pkey_ecx_digestsign,
+	.digestverify = pkey_ecx_digestverify,
+};
diff --git a/crypto/ecdh/ecdh.c b/crypto/ecdh/ecdh.c
new file mode 100644
index 0000000..b0a8e60
--- /dev/null
+++ b/crypto/ecdh/ecdh.c
@@ -0,0 +1,281 @@
+/* $OpenBSD: ecdh.c,v 1.10 2023/07/28 09:31:21 tb Exp $ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
+ * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
+ * to the OpenSSL project.
+ *
+ * The ECC Code is licensed pursuant to the OpenSSL open source
+ * license provided below.
+ *
+ * The ECDH software is originally written by Douglas Stebila of
+ * Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#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)
+{
+	EVP_MD_CTX *mctx = NULL;
+	unsigned int i;
+	size_t mdlen;
+	unsigned char ctr[4];
+	int rv = 0;
+
+	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);
+			explicit_bzero(mtmp, mdlen);
+			break;
+		}
+	}
+	rv = 1;
+
+ err:
+	EVP_MD_CTX_free(mctx);
+
+	return rv;
+}
+
+/*
+ * Based on the ECKAS-DH1 and ECSVDP-DH primitives in the IEEE 1363 standard.
+ */
+int
+ecdh_compute_key(unsigned char **out, size_t *out_len, const EC_POINT *pub_key,
+    const EC_KEY *ecdh)
+{
+	BN_CTX *ctx;
+	BIGNUM *x;
+	const BIGNUM *priv_key;
+	const EC_GROUP *group;
+	EC_POINT *point = NULL;
+	unsigned char *buf = NULL;
+	int buf_len = 0;
+	int ret = 0;
+
+	*out = NULL;
+	*out_len = 0;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if ((group = EC_KEY_get0_group(ecdh)) == NULL)
+		goto err;
+
+	if (EC_POINT_is_on_curve(group, pub_key, ctx) <= 0)
+		goto err;
+
+	if ((point = EC_POINT_new(group)) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if ((priv_key = EC_KEY_get0_private_key(ecdh)) == NULL) {
+		ECerror(EC_R_MISSING_PRIVATE_KEY);
+		goto err;
+	}
+
+	if (!EC_POINT_mul(group, point, NULL, pub_key, priv_key, ctx)) {
+		ECerror(EC_R_POINT_ARITHMETIC_FAILURE);
+		goto err;
+	}
+
+	if (!EC_POINT_get_affine_coordinates(group, point, x, NULL, ctx)) {
+		ECerror(EC_R_POINT_ARITHMETIC_FAILURE);
+		goto err;
+	}
+
+	if ((buf_len = ECDH_size(ecdh)) < BN_num_bytes(x)) {
+		ECerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	if ((buf = calloc(1, buf_len)) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (BN_bn2binpad(x, buf, buf_len) != buf_len) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	*out = buf;
+	*out_len = buf_len;
+	buf = NULL;
+	buf_len = 0;
+
+	ret = 1;
+
+ err:
+	EC_POINT_free(point);
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	freezero(buf, buf_len);
+
+	return ret;
+}
+
+int
+ECDH_compute_key(void *out, size_t out_len, const EC_POINT *pub_key,
+    EC_KEY *eckey,
+    void *(*KDF)(const void *in, size_t inlen, void *out, size_t *out_len))
+{
+	unsigned char *secret = NULL;
+	size_t secret_len = 0;
+	int ret = 0;
+
+	if (eckey->meth->compute_key == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		goto err;
+	}
+
+	if (out_len > INT_MAX) {
+		ECerror(EC_R_INVALID_OUTPUT_LENGTH);
+		goto err;
+	}
+
+	if (!eckey->meth->compute_key(&secret, &secret_len, pub_key, eckey))
+		goto err;
+
+	memset(out, 0, out_len);
+	if (KDF != NULL) {
+		if (KDF(secret, secret_len, out, &out_len) == NULL) {
+			ECerror(EC_R_KDF_FAILED);
+			goto err;
+		}
+	} else {
+		if (out_len < secret_len) {
+			/* The resulting key would be truncated. */
+			ECerror(EC_R_KEY_TRUNCATION);
+			goto err;
+		}
+		out_len = secret_len;
+		memcpy(out, secret, out_len);
+	}
+
+	if (out_len > INT_MAX) {
+		ECerror(EC_R_INVALID_OUTPUT_LENGTH);
+		goto err;
+	}
+
+	ret = out_len;
+
+ err:
+	freezero(secret, secret_len);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ECDH_compute_key);
+
+int
+ECDH_size(const EC_KEY *d)
+{
+	return (EC_GROUP_get_degree(EC_KEY_get0_group(d)) + 7) / 8;
+}
+LCRYPTO_ALIAS(ECDH_size);
diff --git a/crypto/ecdsa/ecdsa.c b/crypto/ecdsa/ecdsa.c
new file mode 100644
index 0000000..52f5044
--- /dev/null
+++ b/crypto/ecdsa/ecdsa.c
@@ -0,0 +1,774 @@
+/* $OpenBSD: ecdsa.c,v 1.18 2023/08/08 13:09:28 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2000-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "ec_local.h"
+#include "ecdsa_local.h"
+
+static const ASN1_TEMPLATE ECDSA_SIG_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECDSA_SIG, r),
+		.field_name = "r",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ECDSA_SIG, s),
+		.field_name = "s",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM ECDSA_SIG_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ECDSA_SIG_seq_tt,
+	.tcount = sizeof(ECDSA_SIG_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ECDSA_SIG),
+	.sname = "ECDSA_SIG",
+};
+
+ECDSA_SIG *
+d2i_ECDSA_SIG(ECDSA_SIG **a, const unsigned char **in, long len)
+{
+	return (ECDSA_SIG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ECDSA_SIG_it);
+}
+LCRYPTO_ALIAS(d2i_ECDSA_SIG);
+
+int
+i2d_ECDSA_SIG(const ECDSA_SIG *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ECDSA_SIG_it);
+}
+LCRYPTO_ALIAS(i2d_ECDSA_SIG);
+
+ECDSA_SIG *
+ECDSA_SIG_new(void)
+{
+	return (ECDSA_SIG *)ASN1_item_new(&ECDSA_SIG_it);
+}
+LCRYPTO_ALIAS(ECDSA_SIG_new);
+
+void
+ECDSA_SIG_free(ECDSA_SIG *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ECDSA_SIG_it);
+}
+LCRYPTO_ALIAS(ECDSA_SIG_free);
+
+void
+ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
+{
+	if (pr != NULL)
+		*pr = sig->r;
+	if (ps != NULL)
+		*ps = sig->s;
+}
+LCRYPTO_ALIAS(ECDSA_SIG_get0);
+
+const BIGNUM *
+ECDSA_SIG_get0_r(const ECDSA_SIG *sig)
+{
+	return sig->r;
+}
+LCRYPTO_ALIAS(ECDSA_SIG_get0_r);
+
+const BIGNUM *
+ECDSA_SIG_get0_s(const ECDSA_SIG *sig)
+{
+	return sig->s;
+}
+LCRYPTO_ALIAS(ECDSA_SIG_get0_s);
+
+int
+ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
+{
+	if (r == NULL || s == NULL)
+		return 0;
+
+	BN_free(sig->r);
+	BN_free(sig->s);
+	sig->r = r;
+	sig->s = s;
+	return 1;
+}
+LCRYPTO_ALIAS(ECDSA_SIG_set0);
+
+int
+ECDSA_size(const EC_KEY *key)
+{
+	const EC_GROUP *group;
+	const BIGNUM *order = NULL;
+	ECDSA_SIG sig;
+	int ret = 0;
+
+	if (key == NULL)
+		goto err;
+
+	if ((group = EC_KEY_get0_group(key)) == NULL)
+		goto err;
+
+	if ((order = EC_GROUP_get0_order(group)) == NULL)
+		goto err;
+
+	sig.r = (BIGNUM *)order;
+	sig.s = (BIGNUM *)order;
+
+	if ((ret = i2d_ECDSA_SIG(&sig, NULL)) < 0)
+		ret = 0;
+
+ err:
+	return ret;
+}
+LCRYPTO_ALIAS(ECDSA_size);
+
+/*
+ * FIPS 186-5, section 6.4.1, step 2: convert hashed message into an integer.
+ * Use the order_bits leftmost bits if it exceeds the group order.
+ */
+static int
+ecdsa_prepare_digest(const unsigned char *digest, int digest_len,
+    const EC_KEY *key, BIGNUM *e)
+{
+	const EC_GROUP *group;
+	int digest_bits, order_bits;
+
+	if (BN_bin2bn(digest, digest_len, e) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		return 0;
+	}
+
+	if ((group = EC_KEY_get0_group(key)) == NULL)
+		return 0;
+	order_bits = EC_GROUP_order_bits(group);
+
+	digest_bits = 8 * digest_len;
+	if (digest_bits <= order_bits)
+		return 1;
+
+	return BN_rshift(e, e, digest_bits - order_bits);
+}
+
+int
+ecdsa_sign(int type, const unsigned char *digest, int digest_len,
+    unsigned char *signature, unsigned int *signature_len, const BIGNUM *kinv,
+    const BIGNUM *r, EC_KEY *key)
+{
+	ECDSA_SIG *sig = NULL;
+	int out_len = 0;
+	int ret = 0;
+
+	if (kinv != NULL || r != NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		goto err;
+	}
+
+	if ((sig = ECDSA_do_sign(digest, digest_len, key)) == NULL)
+		goto err;
+
+	if ((out_len = i2d_ECDSA_SIG(sig, &signature)) < 0) {
+		out_len = 0;
+		goto err;
+	}
+
+	ret = 1;
+
+ err:
+	*signature_len = out_len;
+	ECDSA_SIG_free(sig);
+
+	return ret;
+}
+
+int
+ECDSA_sign(int type, const unsigned char *digest, int digest_len,
+    unsigned char *signature, unsigned int *signature_len, EC_KEY *key)
+{
+	if (key->meth->sign == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return key->meth->sign(type, digest, digest_len, signature,
+	    signature_len, NULL, NULL, key);
+}
+LCRYPTO_ALIAS(ECDSA_sign);
+
+/*
+ * FIPS 186-5, section 6.4.1, steps 3-8 and 11: Generate k, calculate r and
+ * kinv. If r == 0, try again with a new random k.
+ */
+
+int
+ecdsa_sign_setup(EC_KEY *key, BN_CTX *in_ctx, BIGNUM **out_kinv, BIGNUM **out_r)
+{
+	const EC_GROUP *group;
+	EC_POINT *point = NULL;
+	BN_CTX *ctx = NULL;
+	BIGNUM *k = NULL, *r = NULL;
+	const BIGNUM *order;
+	BIGNUM *x;
+	int order_bits;
+	int ret = 0;
+
+	BN_free(*out_kinv);
+	*out_kinv = NULL;
+
+	BN_free(*out_r);
+	*out_r = NULL;
+
+	if (key == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+	if ((group = EC_KEY_get0_group(key)) == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if ((k = BN_new()) == NULL)
+		goto err;
+	if ((r = BN_new()) == NULL)
+		goto err;
+
+	if ((ctx = in_ctx) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if ((point = EC_POINT_new(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if ((order = EC_GROUP_get0_order(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if (BN_cmp(order, BN_value_one()) <= 0) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+
+	/* Reject curves with an order that is smaller than 80 bits. */
+	if ((order_bits = BN_num_bits(order)) < 80) {
+		ECerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+
+	/* Preallocate space. */
+	if (!BN_set_bit(k, order_bits) ||
+	    !BN_set_bit(r, order_bits) ||
+	    !BN_set_bit(x, order_bits))
+		goto err;
+
+	/* Step 11: repeat until r != 0. */
+	do {
+		/* Step 3: generate random k. */
+		if (!bn_rand_interval(k, 1, order))
+			goto err;
+
+		/* Step 5: P = k * G. */
+		if (!EC_POINT_mul(group, point, k, NULL, NULL, ctx)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		/* Steps 6 (and 7): from P = (x, y) retain the x-coordinate. */
+		if (!EC_POINT_get_affine_coordinates(group, point, x, NULL,
+		    ctx)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		/* Step 8: r = x (mod order). */
+		if (!BN_nnmod(r, x, order, ctx)) {
+			ECerror(ERR_R_BN_LIB);
+			goto err;
+		}
+	} while (BN_is_zero(r));
+
+	/* Step 4: calculate kinv. */
+	if (BN_mod_inverse_ct(k, k, order, ctx) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	*out_kinv = k;
+	k = NULL;
+
+	*out_r = r;
+	r = NULL;
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	if (ctx != in_ctx)
+		BN_CTX_free(ctx);
+	BN_free(k);
+	BN_free(r);
+	EC_POINT_free(point);
+
+	return ret;
+}
+
+static int
+ECDSA_sign_setup(EC_KEY *key, BN_CTX *in_ctx, BIGNUM **out_kinv,
+    BIGNUM **out_r)
+{
+	if (key->meth->sign_setup == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return key->meth->sign_setup(key, in_ctx, out_kinv, out_r);
+}
+
+/*
+ * FIPS 186-5, section 6.4.1, step 9: compute s = inv(k)(e + xr) mod order.
+ * In order to reduce the possibility of a side-channel attack, the following
+ * is calculated using a random blinding value b in [1, order):
+ * s = inv(b)(be + bxr)inv(k) mod order.
+ */
+
+static int
+ecdsa_compute_s(BIGNUM **out_s, const BIGNUM *e, const BIGNUM *kinv,
+    const BIGNUM *r, const EC_KEY *key, BN_CTX *ctx)
+{
+	const EC_GROUP *group;
+	const BIGNUM *order, *priv_key;
+	BIGNUM *b, *binv, *be, *bxr;
+	BIGNUM *s = NULL;
+	int ret = 0;
+
+	*out_s = NULL;
+
+	BN_CTX_start(ctx);
+
+	if ((group = EC_KEY_get0_group(key)) == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+	if ((order = EC_GROUP_get0_order(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if ((priv_key = EC_KEY_get0_private_key(key)) == NULL) {
+		ECerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+
+	if ((b = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((binv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((be = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((bxr = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if ((s = BN_new()) == NULL)
+		goto err;
+
+	/*
+	 * In a valid ECDSA signature, r must be in [1, order). Since r can be
+	 * caller provided - either directly or by replacing sign_setup() - we
+	 * can't rely on this being the case.
+	 */
+	if (BN_cmp(r, BN_value_one()) < 0 || BN_cmp(r, order) >= 0) {
+		ECerror(EC_R_BAD_SIGNATURE);
+		goto err;
+	}
+
+	if (!bn_rand_interval(b, 1, order)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	if (BN_mod_inverse_ct(binv, b, order, ctx) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	if (!BN_mod_mul(bxr, b, priv_key, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!BN_mod_mul(bxr, bxr, r, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!BN_mod_mul(be, b, e, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!BN_mod_add(s, be, bxr, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	/* s = b(e + xr)k^-1 */
+	if (!BN_mod_mul(s, s, kinv, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	/* s = (e + xr)k^-1 */
+	if (!BN_mod_mul(s, s, binv, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	/* Step 11: if s == 0 start over. */
+	if (!BN_is_zero(s)) {
+		*out_s = s;
+		s = NULL;
+	}
+
+	ret = 1;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_free(s);
+
+	return ret;
+}
+
+/*
+ * It is too expensive to check curve parameters on every sign operation.
+ * Instead, cap the number of retries. A single retry is very unlikely, so
+ * allowing 32 retries is amply enough.
+ */
+#define ECDSA_MAX_SIGN_ITERATIONS		32
+
+/*
+ * FIPS 186-5: Section 6.4.1: ECDSA signature generation, steps 2-12.
+ * The caller provides the hash of the message, thus performs step 1.
+ * Step 10, zeroing k and kinv, is done by BN_free().
+ */
+
+ECDSA_SIG *
+ecdsa_sign_sig(const unsigned char *digest, int digest_len,
+    const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *key)
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
+	BIGNUM *e;
+	int attempts = 0;
+	ECDSA_SIG *sig = NULL;
+
+	if (in_kinv != NULL || in_r != NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		goto err;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((e = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	/* Step 2: convert hash into an integer. */
+	if (!ecdsa_prepare_digest(digest, digest_len, key, e))
+		goto err;
+
+	do {
+		/* Steps 3-8: calculate kinv and r. */
+		if (!ECDSA_sign_setup(key, ctx, &kinv, &r)) {
+			ECerror(ERR_R_EC_LIB);
+			goto err;
+		}
+
+		/*
+		 * Steps 9 and 11: if s is non-NULL, we have a valid signature.
+		 */
+		if (!ecdsa_compute_s(&s, e, kinv, r, key, ctx))
+			goto err;
+		if (s != NULL)
+			break;
+
+		if (++attempts > ECDSA_MAX_SIGN_ITERATIONS) {
+			ECerror(EC_R_WRONG_CURVE_PARAMETERS);
+			goto err;
+		}
+	} while (1);
+
+	/* Step 12: output (r, s). */
+	if ((sig = ECDSA_SIG_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!ECDSA_SIG_set0(sig, r, s)) {
+		ECDSA_SIG_free(sig);
+		goto err;
+	}
+	r = NULL;
+	s = NULL;
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(kinv);
+	BN_free(r);
+	BN_free(s);
+
+	return sig;
+}
+
+ECDSA_SIG *
+ECDSA_do_sign(const unsigned char *digest, int digest_len, EC_KEY *key)
+{
+	if (key->meth->sign_sig == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return key->meth->sign_sig(digest, digest_len, NULL, NULL, key);
+}
+LCRYPTO_ALIAS(ECDSA_do_sign);
+
+int
+ecdsa_verify(int type, const unsigned char *digest, int digest_len,
+    const unsigned char *sigbuf, int sig_len, EC_KEY *key)
+{
+	ECDSA_SIG *s;
+	unsigned char *der = NULL;
+	const unsigned char *p;
+	int der_len = 0;
+	int ret = -1;
+
+	if ((s = ECDSA_SIG_new()) == NULL)
+		goto err;
+
+	p = sigbuf;
+	if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL)
+		goto err;
+
+	/* Ensure signature uses DER and doesn't have trailing garbage. */
+	if ((der_len = i2d_ECDSA_SIG(s, &der)) != sig_len)
+		goto err;
+	if (timingsafe_memcmp(sigbuf, der, der_len))
+		goto err;
+
+	ret = ECDSA_do_verify(digest, digest_len, s, key);
+
+ err:
+	freezero(der, der_len);
+	ECDSA_SIG_free(s);
+
+	return ret;
+}
+
+int
+ECDSA_verify(int type, const unsigned char *digest, int digest_len,
+    const unsigned char *sigbuf, int sig_len, EC_KEY *key)
+{
+	if (key->meth->verify == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return key->meth->verify(type, digest, digest_len, sigbuf, sig_len, key);
+}
+LCRYPTO_ALIAS(ECDSA_verify);
+
+/*
+ * FIPS 186-5, section 6.4.2: ECDSA signature verification.
+ * The caller provides us with the hash of the message, so has performed step 2.
+ */
+
+int
+ecdsa_verify_sig(const unsigned char *digest, int digest_len,
+    const ECDSA_SIG *sig, EC_KEY *key)
+{
+	const EC_GROUP *group;
+	const EC_POINT *pub_key;
+	EC_POINT *point = NULL;
+	const BIGNUM *order;
+	BN_CTX *ctx = NULL;
+	BIGNUM *e, *sinv, *u, *v, *x;
+	int ret = -1;
+
+	if (key == NULL || sig == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		goto err;
+	}
+	if ((group = EC_KEY_get0_group(key)) == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		goto err;
+	}
+	if ((pub_key = EC_KEY_get0_public_key(key)) == NULL) {
+		ECerror(EC_R_MISSING_PARAMETERS);
+		goto err;
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	BN_CTX_start(ctx);
+
+	if ((e = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((sinv = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((u = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((v = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((x = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if ((order = EC_GROUP_get0_order(group)) == NULL) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	/* Step 1: verify that r and s are in the range [1, order). */
+	if (BN_cmp(sig->r, BN_value_one()) < 0 || BN_cmp(sig->r, order) >= 0) {
+		ECerror(EC_R_BAD_SIGNATURE);
+		ret = 0;
+		goto err;
+	}
+	if (BN_cmp(sig->s, BN_value_one()) < 0 || BN_cmp(sig->s, order) >= 0) {
+		ECerror(EC_R_BAD_SIGNATURE);
+		ret = 0;
+		goto err;
+	}
+
+	/* Step 3: convert the hash into an integer. */
+	if (!ecdsa_prepare_digest(digest, digest_len, key, e))
+		goto err;
+
+	/* Step 4: compute the inverse of s modulo order. */
+	if (BN_mod_inverse_ct(sinv, sig->s, order, ctx) == NULL) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	/* Step 5: compute u = s^-1 * e and v = s^-1 * r (modulo order). */
+	if (!BN_mod_mul(u, e, sinv, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+	if (!BN_mod_mul(v, sig->r, sinv, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	/*
+	 * Steps 6 and 7: compute R = G * u + pub_key * v = (x, y). Reject if
+	 * it's the point at infinity - getting affine coordinates fails. Keep
+	 * the x coordinate.
+	 */
+	if ((point = EC_POINT_new(group)) == NULL) {
+		ECerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!EC_POINT_mul(group, point, u, pub_key, v, ctx)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (!EC_POINT_get_affine_coordinates(group, point, x, NULL, ctx)) {
+		ECerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	/* Step 8: convert x to a number in [0, order). */
+	if (!BN_nnmod(x, x, order, ctx)) {
+		ECerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+	/* Step 9: the signature is valid iff the x-coordinate is equal to r. */
+	ret = (BN_cmp(x, sig->r) == 0);
+
+ err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	EC_POINT_free(point);
+
+	return ret;
+}
+
+int
+ECDSA_do_verify(const unsigned char *digest, int digest_len,
+    const ECDSA_SIG *sig, EC_KEY *key)
+{
+	if (key->meth->verify_sig == NULL) {
+		ECerror(EC_R_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return key->meth->verify_sig(digest, digest_len, sig, key);
+}
+LCRYPTO_ALIAS(ECDSA_do_verify);
diff --git a/crypto/ecdsa/ecdsa_local.h b/crypto/ecdsa/ecdsa_local.h
new file mode 100644
index 0000000..cc3af3e
--- /dev/null
+++ b/crypto/ecdsa/ecdsa_local.h
@@ -0,0 +1,81 @@
+/* $OpenBSD: ecdsa_local.h,v 1.2 2023/07/28 15:50:33 tb Exp $ */
+/*
+ * Written by Nils Larsch for the OpenSSL project
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_ECS_LOCAL_H
+#define HEADER_ECS_LOCAL_H
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+struct ECDSA_SIG_st {
+	BIGNUM *r;
+	BIGNUM *s;
+};
+
+int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *in_ctx, BIGNUM **out_kinv,
+    BIGNUM **out_r);
+int ecdsa_sign(int type, const unsigned char *digest, int digest_len,
+    unsigned char *signature, unsigned int *signature_len, const BIGNUM *kinv,
+    const BIGNUM *r, EC_KEY *eckey);
+ECDSA_SIG *ecdsa_sign_sig(const unsigned char *digest, int digest_len,
+    const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_ECS_LOCAL_H */
diff --git a/crypto/empty.c b/crypto/empty.c
new file mode 100644
index 0000000..e69de29
diff --git a/crypto/engine/engine_stubs.c b/crypto/engine/engine_stubs.c
new file mode 100644
index 0000000..3621da8
--- /dev/null
+++ b/crypto/engine/engine_stubs.c
@@ -0,0 +1,125 @@
+/*	$OpenBSD: engine_stubs.c,v 1.1 2023/07/21 09:04:23 tb Exp $ */
+
+/*
+ * Written by Theo Buehler. Public domain.
+ */
+
+#include 
+
+#ifdef OPENSSL_NO_ENGINE
+
+void
+ENGINE_load_builtin_engines(void)
+{
+}
+
+void
+ENGINE_load_dynamic(void)
+{
+}
+
+void
+ENGINE_load_openssl(void)
+{
+}
+
+int
+ENGINE_register_all_complete(void)
+{
+	return 0;
+}
+
+void
+ENGINE_cleanup(void)
+{
+}
+
+ENGINE *
+ENGINE_new(void)
+{
+	return NULL;
+}
+
+int
+ENGINE_free(ENGINE *engine)
+{
+	return 0;
+}
+
+int
+ENGINE_init(ENGINE *engine)
+{
+	return 0;
+}
+
+int
+ENGINE_finish(ENGINE *engine)
+{
+	return 0;
+}
+
+ENGINE *
+ENGINE_by_id(const char *id)
+{
+	return NULL;
+}
+
+const char *
+ENGINE_get_id(const ENGINE *engine)
+{
+	return "";
+}
+
+const char *
+ENGINE_get_name(const ENGINE *engine)
+{
+	return "";
+}
+
+int
+ENGINE_set_default(ENGINE *engine, unsigned int flags)
+{
+	return 0;
+}
+
+ENGINE *
+ENGINE_get_default_RSA(void)
+{
+	return NULL;
+}
+
+int
+ENGINE_set_default_RSA(ENGINE *engine)
+{
+	return 0;
+}
+
+int
+ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, long i, void *p,
+    void (*f)(void), int cmd_optional)
+{
+	return 0;
+}
+
+int
+ENGINE_ctrl_cmd_string(ENGINE *engine, const char *cmd, const char *arg,
+    int cmd_optional)
+{
+	return 0;
+}
+
+EVP_PKEY *
+ENGINE_load_private_key(ENGINE *engine, const char *key_id,
+    UI_METHOD *ui_method, void *callback_data)
+{
+	return NULL;
+}
+
+EVP_PKEY *
+ENGINE_load_public_key(ENGINE *engine, const char *key_id,
+    UI_METHOD *ui_method, void *callback_data)
+{
+	return NULL;
+}
+
+#endif
diff --git a/crypto/err/err.c b/crypto/err/err.c
new file mode 100644
index 0000000..4b4be21
--- /dev/null
+++ b/crypto/err/err.c
@@ -0,0 +1,1196 @@
+/* $OpenBSD: err.c,v 1.56 2023/07/28 10:23:19 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+DECLARE_LHASH_OF(ERR_STRING_DATA);
+DECLARE_LHASH_OF(ERR_STATE);
+
+typedef struct st_ERR_FNS ERR_FNS;
+
+static void err_load_strings(int lib, ERR_STRING_DATA *str);
+
+static void ERR_STATE_free(ERR_STATE *s);
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA ERR_str_libraries[] = {
+	{ERR_PACK(ERR_LIB_NONE,0,0),		"unknown library"},
+	{ERR_PACK(ERR_LIB_SYS,0,0),		"system library"},
+	{ERR_PACK(ERR_LIB_BN,0,0),		"bignum routines"},
+	{ERR_PACK(ERR_LIB_RSA,0,0),		"rsa routines"},
+	{ERR_PACK(ERR_LIB_DH,0,0),		"Diffie-Hellman routines"},
+	{ERR_PACK(ERR_LIB_EVP,0,0),		"digital envelope routines"},
+	{ERR_PACK(ERR_LIB_BUF,0,0),		"memory buffer routines"},
+	{ERR_PACK(ERR_LIB_OBJ,0,0),		"object identifier routines"},
+	{ERR_PACK(ERR_LIB_PEM,0,0),		"PEM routines"},
+	{ERR_PACK(ERR_LIB_DSA,0,0),		"dsa routines"},
+	{ERR_PACK(ERR_LIB_X509,0,0),		"x509 certificate routines"},
+	{ERR_PACK(ERR_LIB_ASN1,0,0),		"asn1 encoding routines"},
+	{ERR_PACK(ERR_LIB_CONF,0,0),		"configuration file routines"},
+	{ERR_PACK(ERR_LIB_CRYPTO,0,0),		"common libcrypto routines"},
+	{ERR_PACK(ERR_LIB_EC,0,0),		"elliptic curve routines"},
+	{ERR_PACK(ERR_LIB_SSL,0,0),		"SSL routines"},
+	{ERR_PACK(ERR_LIB_BIO,0,0),		"BIO routines"},
+	{ERR_PACK(ERR_LIB_PKCS7,0,0),		"PKCS7 routines"},
+	{ERR_PACK(ERR_LIB_X509V3,0,0),		"X509 V3 routines"},
+	{ERR_PACK(ERR_LIB_PKCS12,0,0),		"PKCS12 routines"},
+	{ERR_PACK(ERR_LIB_RAND,0,0),		"random number generator"},
+	{ERR_PACK(ERR_LIB_DSO,0,0),		"DSO support routines"},
+	{ERR_PACK(ERR_LIB_TS,0,0),		"time stamp routines"},
+	{ERR_PACK(ERR_LIB_ENGINE,0,0),		"engine routines"},
+	{ERR_PACK(ERR_LIB_OCSP,0,0),		"OCSP routines"},
+	{ERR_PACK(ERR_LIB_FIPS,0,0),		"FIPS routines"},
+	{ERR_PACK(ERR_LIB_CMS,0,0),		"CMS routines"},
+	{ERR_PACK(ERR_LIB_HMAC,0,0),		"HMAC routines"},
+	{ERR_PACK(ERR_LIB_GOST,0,0),		"GOST 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),	"ioctl"},
+	{ERR_PACK(0,SYS_F_BIND, 0),		"bind"},
+	{ERR_PACK(0,SYS_F_LISTEN, 0),		"listen"},
+	{ERR_PACK(0,SYS_F_ACCEPT, 0),		"accept"},
+	{ERR_PACK(0,SYS_F_OPENDIR, 0),		"opendir"},
+	{ERR_PACK(0,SYS_F_FREAD, 0),		"fread"},
+	{0, NULL},
+};
+
+static ERR_STRING_DATA ERR_str_reasons[] = {
+	{ERR_R_SYS_LIB,				"system lib"},
+	{ERR_R_BN_LIB,				"BN lib"},
+	{ERR_R_RSA_LIB,				"RSA lib"},
+	{ERR_R_DH_LIB,				"DH lib"},
+	{ERR_R_EVP_LIB,				"EVP lib"},
+	{ERR_R_BUF_LIB,				"BUF lib"},
+	{ERR_R_OBJ_LIB,				"OBJ lib"},
+	{ERR_R_PEM_LIB,				"PEM lib"},
+	{ERR_R_DSA_LIB,				"DSA lib"},
+	{ERR_R_X509_LIB,			"X509 lib"},
+	{ERR_R_ASN1_LIB,			"ASN1 lib"},
+	{ERR_R_CONF_LIB,			"CONF lib"},
+	{ERR_R_CRYPTO_LIB,			"CRYPTO lib"},
+	{ERR_R_EC_LIB,				"EC lib"},
+	{ERR_R_SSL_LIB,				"SSL lib"},
+	{ERR_R_BIO_LIB,				"BIO lib"},
+	{ERR_R_PKCS7_LIB,			"PKCS7 lib"},
+	{ERR_R_X509V3_LIB,			"X509V3 lib"},
+	{ERR_R_PKCS12_LIB,			"PKCS12 lib"},
+	{ERR_R_RAND_LIB,			"RAND lib"},
+	{ERR_R_DSO_LIB,				"DSO lib"},
+	{ERR_R_ENGINE_LIB,			"ENGINE lib"},
+	{ERR_R_OCSP_LIB,			"OCSP lib"},
+	{ERR_R_TS_LIB,				"TS lib"},
+
+	{ERR_R_NESTED_ASN1_ERROR,		"nested asn1 error"},
+	{ERR_R_BAD_ASN1_OBJECT_HEADER,		"bad asn1 object header"},
+	{ERR_R_BAD_GET_ASN1_OBJECT_CALL,	"bad get asn1 object call"},
+	{ERR_R_EXPECTING_AN_ASN1_SEQUENCE,	"expecting an asn1 sequence"},
+	{ERR_R_ASN1_LENGTH_MISMATCH,		"asn1 length mismatch"},
+	{ERR_R_MISSING_ASN1_EOS,		"missing asn1 eos"},
+
+	{ERR_R_FATAL,				"fatal"},
+	{ERR_R_MALLOC_FAILURE,			"malloc failure"},
+	{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,	"called a function you should not call"},
+	{ERR_R_PASSED_NULL_PARAMETER,		"passed a null parameter"},
+	{ERR_R_INTERNAL_ERROR,			"internal error"},
+	{ERR_R_DISABLED	,			"called a function that was disabled at compile-time"},
+	{ERR_R_INIT_FAIL,			"initialization failure"},
+
+	{0, NULL},
+};
+#endif
+
+
+/* Define the predeclared (but externally opaque) "ERR_FNS" type */
+struct st_ERR_FNS {
+	/* Works on the "error_hash" string table */
+	LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create);
+	void (*cb_err_del)(void);
+	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
+	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
+	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
+	/* Works on the "thread_hash" error-state table */
+	LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create);
+	void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash);
+	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
+	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
+	void (*cb_thread_del_item)(const ERR_STATE *);
+	/* Returns the next available error "library" numbers */
+	int (*cb_get_next_lib)(void);
+};
+
+/* Predeclarations of the "err_defaults" functions */
+static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
+static void int_err_del(void);
+static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
+static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
+static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
+static LHASH_OF(ERR_STATE) *int_thread_get(int create);
+static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
+static ERR_STATE *int_thread_get_item(const ERR_STATE *);
+static ERR_STATE *int_thread_set_item(ERR_STATE *);
+static void int_thread_del_item(const ERR_STATE *);
+static int int_err_get_next_lib(void);
+
+/* The static ERR_FNS table using these defaults functions */
+static const ERR_FNS err_defaults = {
+	int_err_get,
+	int_err_del,
+	int_err_get_item,
+	int_err_set_item,
+	int_err_del_item,
+	int_thread_get,
+	int_thread_release,
+	int_thread_get_item,
+	int_thread_set_item,
+	int_thread_del_item,
+	int_err_get_next_lib
+};
+
+/* The replacable table of ERR_FNS functions we use at run-time */
+static const ERR_FNS *err_fns = NULL;
+
+/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
+#define ERRFN(a) err_fns->cb_##a
+
+/* The internal state used by "err_defaults" - as such, the setting, reading,
+ * creating, and deleting of this data should only be permitted via the
+ * "err_defaults" functions. This way, a linked module can completely defer all
+ * ERR state operation (together with requisite locking) to the implementations
+ * and state in the loading application. */
+static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
+static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
+static int int_thread_hash_references = 0;
+static int int_err_library_number = ERR_LIB_USER;
+
+static pthread_t err_init_thread;
+
+/* Internal function that checks whether "err_fns" is set and if not, sets it to
+ * the defaults. */
+static void
+err_fns_check(void)
+{
+	if (err_fns)
+		return;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (!err_fns)
+		err_fns = &err_defaults;
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+}
+
+/* These are the callbacks provided to "lh_new()" when creating the LHASH tables
+ * internal to the "err_defaults" implementation. */
+
+static unsigned long get_error_values(int inc, int top, const char **file,
+    int *line, const char **data, int *flags);
+
+/* The internal functions used in the "err_defaults" implementation */
+
+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);
+	return (ret^ret % 19*13);
+}
+static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA)
+
+static int
+err_string_data_cmp(const ERR_STRING_DATA *a, const ERR_STRING_DATA *b)
+{
+	return (int)(a->error - b->error);
+}
+static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA)
+
+static
+LHASH_OF(ERR_STRING_DATA) *int_err_get(int create)
+{
+	LHASH_OF(ERR_STRING_DATA) *ret = NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (!int_error_hash && create) {
+		CRYPTO_push_info("int_err_get (err.c)");
+		int_error_hash = lh_ERR_STRING_DATA_new();
+		CRYPTO_pop_info();
+	}
+	if (int_error_hash)
+		ret = int_error_hash;
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	return ret;
+}
+
+static void
+int_err_del(void)
+{
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (int_error_hash) {
+		lh_ERR_STRING_DATA_free(int_error_hash);
+		int_error_hash = NULL;
+	}
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+}
+
+static ERR_STRING_DATA *
+int_err_get_item(const ERR_STRING_DATA *d)
+{
+	ERR_STRING_DATA *p;
+	LHASH_OF(ERR_STRING_DATA) *hash;
+
+	err_fns_check();
+	hash = ERRFN(err_get)(0);
+	if (!hash)
+		return NULL;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STRING_DATA_retrieve(hash, d);
+	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+
+	return p;
+}
+
+static ERR_STRING_DATA *
+int_err_set_item(ERR_STRING_DATA *d)
+{
+	ERR_STRING_DATA *p;
+	LHASH_OF(ERR_STRING_DATA) *hash;
+
+	err_fns_check();
+	hash = ERRFN(err_get)(1);
+	if (!hash)
+		return NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STRING_DATA_insert(hash, d);
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	return p;
+}
+
+static ERR_STRING_DATA *
+int_err_del_item(ERR_STRING_DATA *d)
+{
+	ERR_STRING_DATA *p;
+	LHASH_OF(ERR_STRING_DATA) *hash;
+
+	err_fns_check();
+	hash = ERRFN(err_get)(0);
+	if (!hash)
+		return NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STRING_DATA_delete(hash, d);
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	return p;
+}
+
+static unsigned long
+err_state_hash(const ERR_STATE *a)
+{
+	return CRYPTO_THREADID_hash(&a->tid) * 13;
+}
+static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE)
+
+static int
+err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
+{
+	return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
+}
+static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE)
+
+static
+LHASH_OF(ERR_STATE) *int_thread_get(int create)
+{
+	LHASH_OF(ERR_STATE) *ret = NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (!int_thread_hash && create) {
+		CRYPTO_push_info("int_thread_get (err.c)");
+		int_thread_hash = lh_ERR_STATE_new();
+		CRYPTO_pop_info();
+	}
+	if (int_thread_hash) {
+		int_thread_hash_references++;
+		ret = int_thread_hash;
+	}
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+	return ret;
+}
+
+static void
+int_thread_release(LHASH_OF(ERR_STATE) **hash)
+{
+	int i;
+
+	if (hash == NULL || *hash == NULL)
+		return;
+
+	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);
+	if (i > 0)
+		return;
+
+	*hash = NULL;
+}
+
+static ERR_STATE *
+int_thread_get_item(const ERR_STATE *d)
+{
+	ERR_STATE *p;
+	LHASH_OF(ERR_STATE) *hash;
+
+	err_fns_check();
+	hash = ERRFN(thread_get)(0);
+	if (!hash)
+		return NULL;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STATE_retrieve(hash, d);
+	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+
+	ERRFN(thread_release)(&hash);
+	return p;
+}
+
+static ERR_STATE *
+int_thread_set_item(ERR_STATE *d)
+{
+	ERR_STATE *p;
+	LHASH_OF(ERR_STATE) *hash;
+
+	err_fns_check();
+	hash = ERRFN(thread_get)(1);
+	if (!hash)
+		return NULL;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STATE_insert(hash, d);
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	ERRFN(thread_release)(&hash);
+	return p;
+}
+
+static void
+int_thread_del_item(const ERR_STATE *d)
+{
+	ERR_STATE *p;
+	LHASH_OF(ERR_STATE) *hash;
+
+	err_fns_check();
+	hash = ERRFN(thread_get)(0);
+	if (!hash)
+		return;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	p = lh_ERR_STATE_delete(hash, d);
+	/* make sure we don't leak memory */
+	if (int_thread_hash_references == 1 &&
+	    int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0) {
+		lh_ERR_STATE_free(int_thread_hash);
+		int_thread_hash = NULL;
+	}
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	ERRFN(thread_release)(&hash);
+	if (p)
+		ERR_STATE_free(p);
+}
+
+static int
+int_err_get_next_lib(void)
+{
+	int ret;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	ret = int_err_library_number++;
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+
+	return ret;
+}
+
+
+#ifndef OPENSSL_NO_ERR
+#define NUM_SYS_STR_REASONS 127
+#define LEN_SYS_STR_REASON 32
+
+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 SYSerror(which always gets an errno
+ * value and never one of those 'standard' reason codes. */
+
+static void
+build_SYS_str_reasons(void)
+{
+	/* malloc cannot be used here, use static storage instead */
+	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
+	int i;
+	static int init = 1;
+	int save_errno;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
+	if (!init) {
+		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+		return;
+	}
+
+	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
+	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
+	if (!init) {
+		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+		return;
+	}
+
+	/* strerror(3) will set errno to EINVAL when i is an unknown errno. */
+	save_errno = errno;
+	for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
+		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
+
+		str->error = (unsigned long)i;
+		if (str->string == NULL) {
+			char (*dest)[LEN_SYS_STR_REASON] =
+			    &(strerror_tab[i - 1]);
+			const char *src = strerror(i);
+			if (src != NULL) {
+				strlcpy(*dest, src, sizeof *dest);
+				str->string = *dest;
+			}
+		}
+		if (str->string == NULL)
+			str->string = "unknown";
+	}
+	errno = save_errno;
+
+	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
+	 * as required by ERR_load_strings. */
+
+	init = 0;
+
+	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
+}
+#endif
+
+#define err_clear_data(p,i) \
+	do { \
+		if (((p)->err_data[i] != NULL) && \
+		    (p)->err_data_flags[i] & ERR_TXT_MALLOCED) { \
+			free((p)->err_data[i]); \
+			(p)->err_data[i] = NULL; \
+		} \
+		(p)->err_data_flags[i] = 0; \
+	} while(0)
+
+#define err_clear(p,i) \
+	do { \
+		(p)->err_flags[i] = 0; \
+		(p)->err_buffer[i] = 0; \
+		err_clear_data(p, i); \
+		(p)->err_file[i] = NULL; \
+		(p)->err_line[i] = -1; \
+	} while(0)
+
+static void
+ERR_STATE_free(ERR_STATE *s)
+{
+	int i;
+
+	if (s == NULL)
+		return;
+
+	for (i = 0; i < ERR_NUM_ERRORS; i++) {
+		err_clear_data(s, i);
+	}
+	free(s);
+}
+
+void
+ERR_load_ERR_strings_internal(void)
+{
+	err_init_thread = pthread_self();
+	err_fns_check();
+#ifndef OPENSSL_NO_ERR
+	err_load_strings(0, ERR_str_libraries);
+	err_load_strings(0, ERR_str_reasons);
+	err_load_strings(ERR_LIB_SYS, ERR_str_functs);
+	build_SYS_str_reasons();
+	err_load_strings(ERR_LIB_SYS, SYS_str_reasons);
+#endif
+}
+
+
+void
+ERR_load_ERR_strings(void)
+{
+	static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+	if (pthread_equal(pthread_self(), err_init_thread))
+		return; /* don't recurse */
+
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	(void) pthread_once(&once, ERR_load_ERR_strings_internal);
+}
+LCRYPTO_ALIAS(ERR_load_ERR_strings);
+
+static void
+err_load_strings(int lib, ERR_STRING_DATA *str)
+{
+	while (str->error) {
+		if (lib)
+			str->error |= ERR_PACK(lib, 0, 0);
+		ERRFN(err_set_item)(str);
+		str++;
+	}
+}
+
+void
+ERR_load_strings(int lib, ERR_STRING_DATA *str)
+{
+	ERR_load_ERR_strings();
+	err_load_strings(lib, str);
+}
+LCRYPTO_ALIAS(ERR_load_strings);
+
+void
+ERR_unload_strings(int lib, ERR_STRING_DATA *str)
+{
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	while (str->error) {
+		if (lib)
+			str->error |= ERR_PACK(lib, 0, 0);
+		ERRFN(err_del_item)(str);
+		str++;
+	}
+}
+LCRYPTO_ALIAS(ERR_unload_strings);
+
+void
+ERR_free_strings(void)
+{
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	err_fns_check();
+	ERRFN(err_del)();
+}
+LCRYPTO_ALIAS(ERR_free_strings);
+
+/********************************************************/
+
+void
+ERR_put_error(int lib, int func, int reason, const char *file, int line)
+{
+	ERR_STATE *es;
+	int save_errno = errno;
+
+	es = ERR_get_state();
+
+	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);
+	errno = save_errno;
+}
+LCRYPTO_ALIAS(ERR_put_error);
+
+void
+ERR_clear_error(void)
+{
+	int i;
+	ERR_STATE *es;
+
+	es = ERR_get_state();
+
+	for (i = 0; i < ERR_NUM_ERRORS; i++) {
+		err_clear(es, i);
+	}
+	es->top = es->bottom = 0;
+}
+LCRYPTO_ALIAS(ERR_clear_error);
+
+
+unsigned long
+ERR_get_error(void)
+{
+	return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_get_error);
+
+unsigned long
+ERR_get_error_line(const char **file, int *line)
+{
+	return (get_error_values(1, 0, file, line, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_get_error_line);
+
+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));
+}
+LCRYPTO_ALIAS(ERR_get_error_line_data);
+
+
+unsigned long
+ERR_peek_error(void)
+{
+	return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_error);
+
+unsigned long
+ERR_peek_error_line(const char **file, int *line)
+{
+	return (get_error_values(0, 0, file, line, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_error_line);
+
+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));
+}
+LCRYPTO_ALIAS(ERR_peek_error_line_data);
+
+unsigned long
+ERR_peek_last_error(void)
+{
+	return (get_error_values(0, 1, NULL, NULL, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_last_error);
+
+unsigned long
+ERR_peek_last_error_line(const char **file, int *line)
+{
+	return (get_error_values(0, 1, file, line, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_last_error_line);
+
+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));
+}
+LCRYPTO_ALIAS(ERR_peek_last_error_line_data);
+
+static unsigned long
+get_error_values(int inc, int top, const char **file, int *line,
+    const char **data, int *flags)
+{
+	int i = 0;
+	ERR_STATE *es;
+	unsigned long ret;
+
+	es = ERR_get_state();
+
+	if (inc && top) {
+		if (file)
+			*file = "";
+		if (line)
+			*line = 0;
+		if (data)
+			*data = "";
+		if (flags)
+			*flags = 0;
+
+		return ERR_R_INTERNAL_ERROR;
+	}
+
+	if (es->bottom == es->top)
+		return 0;
+	if (top)
+		i = es->top;			 /* last error */
+	else
+		i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+
+	ret = es->err_buffer[i];
+	if (inc) {
+		es->bottom = i;
+		es->err_buffer[i] = 0;
+	}
+
+	if ((file != NULL) && (line != NULL)) {
+		if (es->err_file[i] == NULL) {
+			*file = "NA";
+			if (line != NULL)
+				*line = 0;
+		} else {
+			*file = es->err_file[i];
+			if (line != NULL)
+				*line = es->err_line[i];
+		}
+	}
+
+	if (data == NULL) {
+		if (inc) {
+			err_clear_data(es, i);
+		}
+	} else {
+		if (es->err_data[i] == 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)
+{
+	char lsbuf[30], fsbuf[30], rsbuf[30];
+	const char *ls, *fs, *rs;
+	int l, f, r, ret;
+
+	l = ERR_GET_LIB(e);
+	f = ERR_GET_FUNC(e);
+	r = ERR_GET_REASON(e);
+
+	ls = ERR_lib_error_string(e);
+	fs = ERR_func_error_string(e);
+	rs = ERR_reason_error_string(e);
+
+	if (ls == NULL) {
+		(void) snprintf(lsbuf, sizeof(lsbuf), "lib(%d)", l);
+		ls = lsbuf;
+	}
+	if (fs == NULL) {
+		(void) snprintf(fsbuf, sizeof(fsbuf), "func(%d)", f);
+		fs = fsbuf;
+	}
+	if (rs == NULL) {
+		(void) snprintf(rsbuf, sizeof(rsbuf), "reason(%d)", r);
+		rs = rsbuf;
+	}
+
+	ret = snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs);
+	if (ret == -1)
+		return;	/* can't happen, and can't do better if it does */
+	if (ret >= len) {
+		/* output may be truncated; make sure we always have 5
+		 * colon-separated fields, i.e. 4 colons ... */
+#define NUM_COLONS 4
+		if (len > NUM_COLONS) /* ... if possible */
+		{
+			int i;
+			char *s = buf;
+
+			for (i = 0; i < NUM_COLONS; i++) {
+				char *colon = strchr(s, ':');
+				if (colon == NULL ||
+				    colon > &buf[len - 1] - NUM_COLONS + i) {
+					/* set colon no. i at last possible position
+					 * (buf[len-1] is the terminating 0)*/
+					colon = &buf[len - 1] - NUM_COLONS + i;
+					*colon = ':';
+				}
+				s = colon + 1;
+			}
+		}
+	}
+}
+LCRYPTO_ALIAS(ERR_error_string_n);
+
+/* BAD for multi-threading: uses a local buffer if ret == NULL */
+/* ERR_error_string_n should be used instead for ret != NULL
+ * as ERR_error_string cannot know how large the buffer is */
+char *
+ERR_error_string(unsigned long e, char *ret)
+{
+	static char buf[256];
+
+	if (ret == NULL)
+		ret = buf;
+	ERR_error_string_n(e, ret, 256);
+
+	return ret;
+}
+LCRYPTO_ALIAS(ERR_error_string);
+
+const char *
+ERR_lib_error_string(unsigned long e)
+{
+	ERR_STRING_DATA d, *p;
+	unsigned long l;
+
+	if (!OPENSSL_init_crypto(0, NULL))
+		return NULL;
+
+	err_fns_check();
+	l = ERR_GET_LIB(e);
+	d.error = ERR_PACK(l, 0, 0);
+	p = ERRFN(err_get_item)(&d);
+	return ((p == NULL) ? NULL : p->string);
+}
+LCRYPTO_ALIAS(ERR_lib_error_string);
+
+const char *
+ERR_func_error_string(unsigned long e)
+{
+	ERR_STRING_DATA d, *p;
+	unsigned long l, f;
+
+	err_fns_check();
+	l = ERR_GET_LIB(e);
+	f = ERR_GET_FUNC(e);
+	d.error = ERR_PACK(l, f, 0);
+	p = ERRFN(err_get_item)(&d);
+	return ((p == NULL) ? NULL : p->string);
+}
+LCRYPTO_ALIAS(ERR_func_error_string);
+
+const char *
+ERR_reason_error_string(unsigned long e)
+{
+	ERR_STRING_DATA d, *p = NULL;
+	unsigned long l, r;
+
+	err_fns_check();
+	l = ERR_GET_LIB(e);
+	r = ERR_GET_REASON(e);
+	d.error = ERR_PACK(l, 0, r);
+	p = ERRFN(err_get_item)(&d);
+	if (!p) {
+		d.error = ERR_PACK(0, 0, r);
+		p = ERRFN(err_get_item)(&d);
+	}
+	return ((p == NULL) ? NULL : p->string);
+}
+LCRYPTO_ALIAS(ERR_reason_error_string);
+
+void
+ERR_remove_thread_state(const CRYPTO_THREADID *id)
+{
+	ERR_STATE tmp;
+
+	if (id)
+		CRYPTO_THREADID_cpy(&tmp.tid, id);
+	else
+		CRYPTO_THREADID_current(&tmp.tid);
+	err_fns_check();
+	/* thread_del_item automatically destroys the LHASH if the number of
+	 * items reaches zero. */
+	ERRFN(thread_del_item)(&tmp);
+}
+LCRYPTO_ALIAS(ERR_remove_thread_state);
+
+void
+ERR_remove_state(unsigned long pid)
+{
+	ERR_remove_thread_state(NULL);
+}
+LCRYPTO_ALIAS(ERR_remove_state);
+
+ERR_STATE *
+ERR_get_state(void)
+{
+	static ERR_STATE fallback;
+	ERR_STATE *ret, tmp, *tmpp = NULL;
+	int i;
+	CRYPTO_THREADID tid;
+
+	err_fns_check();
+	CRYPTO_THREADID_current(&tid);
+	CRYPTO_THREADID_cpy(&tmp.tid, &tid);
+	ret = ERRFN(thread_get_item)(&tmp);
+
+	/* ret == the error state, if NULL, make a new one */
+	if (ret == NULL) {
+		ret = malloc(sizeof(ERR_STATE));
+		if (ret == NULL)
+			return (&fallback);
+		CRYPTO_THREADID_cpy(&ret->tid, &tid);
+		ret->top = 0;
+		ret->bottom = 0;
+		for (i = 0; i < ERR_NUM_ERRORS; i++) {
+			ret->err_data[i] = NULL;
+			ret->err_data_flags[i] = 0;
+		}
+		tmpp = ERRFN(thread_set_item)(ret);
+		/* To check if insertion failed, do a get. */
+		if (ERRFN(thread_get_item)(ret) != ret) {
+			ERR_STATE_free(ret); /* could not insert it */
+			return (&fallback);
+		}
+		/* If a race occurred in this function and we came second, tmpp
+		 * is the first one that we just replaced. */
+		if (tmpp)
+			ERR_STATE_free(tmpp);
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(ERR_get_state);
+
+int
+ERR_get_next_error_library(void)
+{
+	err_fns_check();
+	return ERRFN(get_next_lib)();
+}
+LCRYPTO_ALIAS(ERR_get_next_error_library);
+
+void
+ERR_set_error_data(char *data, int flags)
+{
+	ERR_STATE *es;
+	int i;
+
+	es = ERR_get_state();
+
+	i = es->top;
+	if (i == 0)
+		i = ERR_NUM_ERRORS - 1;
+
+	err_clear_data(es, i);
+	es->err_data[i] = data;
+	es->err_data_flags[i] = flags;
+}
+LCRYPTO_ALIAS(ERR_set_error_data);
+
+void
+ERR_asprintf_error_data(char * format, ...)
+{
+	char *errbuf = NULL;
+	va_list ap;
+	int r;
+
+	va_start(ap, format);
+	r = vasprintf(&errbuf, format, ap);
+	va_end(ap);
+	if (r == -1)
+		ERR_set_error_data("malloc failed", ERR_TXT_STRING);
+	else
+		ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING);
+}
+LCRYPTO_ALIAS(ERR_asprintf_error_data);
+
+void
+ERR_add_error_vdata(int num, va_list args)
+{
+	char format[129];
+	char *errbuf;
+	int i;
+
+	format[0] = '\0';
+	for (i = 0; i < num; i++) {
+		if (strlcat(format, "%s", sizeof(format)) >= sizeof(format)) {
+			ERR_set_error_data("too many errors", ERR_TXT_STRING);
+			return;
+		}
+	}
+	if (vasprintf(&errbuf, format, args) == -1)
+		ERR_set_error_data("malloc failed", ERR_TXT_STRING);
+	else
+		ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING);
+}
+
+void
+ERR_add_error_data(int num, ...)
+{
+	va_list args;
+	va_start(args, num);
+	ERR_add_error_vdata(num, args);
+	va_end(args);
+}
+
+int
+ERR_set_mark(void)
+{
+	ERR_STATE *es;
+
+	es = ERR_get_state();
+
+	if (es->bottom == es->top)
+		return 0;
+	es->err_flags[es->top] |= ERR_FLAG_MARK;
+	return 1;
+}
+LCRYPTO_ALIAS(ERR_set_mark);
+
+int
+ERR_pop_to_mark(void)
+{
+	ERR_STATE *es;
+
+	es = ERR_get_state();
+
+	while (es->bottom != es->top &&
+	    (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
+		err_clear(es, es->top);
+		es->top -= 1;
+		if (es->top == -1)
+			es->top = ERR_NUM_ERRORS - 1;
+	}
+
+	if (es->bottom == es->top)
+		return 0;
+	es->err_flags[es->top]&=~ERR_FLAG_MARK;
+	return 1;
+}
+LCRYPTO_ALIAS(ERR_pop_to_mark);
+
+void
+err_clear_last_constant_time(int clear)
+{
+	ERR_STATE *es;
+	int top;
+
+	es = ERR_get_state();
+	if (es == NULL)
+        return;
+
+	top = es->top;
+
+	es->err_flags[top] &= ~(0 - clear);
+	es->err_buffer[top] &= ~(0UL - clear);
+	es->err_file[top] = (const char *)((uintptr_t)es->err_file[top] &
+	    ~((uintptr_t)0 - clear));
+	es->err_line[top] |= 0 - clear;
+
+	es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
+}
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
new file mode 100644
index 0000000..2c8a273
--- /dev/null
+++ b/crypto/err/err_all.c
@@ -0,0 +1,163 @@
+/* $OpenBSD: err_all.c,v 1.32 2023/07/28 09:46:36 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_EC
+#include 
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+#ifndef OPENSSL_NO_GOST
+#include 
+#endif
+
+void ERR_load_ERR_strings_internal(void);
+
+static void
+ERR_load_crypto_strings_internal(void)
+{
+#ifndef OPENSSL_NO_ERR
+	ERR_load_ERR_strings_internal(); /* include error strings for SYSerr */
+
+	ERR_load_ASN1_strings();
+	ERR_load_BIO_strings();
+	ERR_load_BN_strings();
+	ERR_load_BUF_strings();
+#ifndef OPENSSL_NO_CMS
+	ERR_load_CMS_strings();
+#endif
+	ERR_load_CONF_strings();
+	ERR_load_CRYPTO_strings();
+#ifndef OPENSSL_NO_CT
+	ERR_load_CT_strings();
+#endif
+#ifndef OPENSSL_NO_DH
+	ERR_load_DH_strings();
+#endif
+#ifndef OPENSSL_NO_DSA
+	ERR_load_DSA_strings();
+#endif
+#ifndef OPENSSL_NO_EC
+	ERR_load_EC_strings();
+#endif
+#ifndef OPENSSL_NO_ENGINE
+	ERR_load_ENGINE_strings();
+#endif
+	ERR_load_EVP_strings();
+#ifndef OPENSSL_NO_GOST
+	ERR_load_GOST_strings();
+#endif
+	ERR_load_KDF_strings();
+	ERR_load_OBJ_strings();
+	ERR_load_OCSP_strings();
+	ERR_load_PEM_strings();
+	ERR_load_PKCS12_strings();
+	ERR_load_PKCS7_strings();
+	ERR_load_RAND_strings();
+#ifndef OPENSSL_NO_RSA
+	ERR_load_RSA_strings();
+#endif
+	ERR_load_TS_strings();
+	ERR_load_UI_strings();
+	ERR_load_X509V3_strings();
+	ERR_load_X509_strings();
+#endif
+}
+
+void
+ERR_load_crypto_strings(void)
+{
+	static pthread_once_t loaded = PTHREAD_ONCE_INIT;
+	(void) pthread_once(&loaded, ERR_load_crypto_strings_internal);
+}
+LCRYPTO_ALIAS(ERR_load_crypto_strings);
diff --git a/crypto/err/err_prn.c b/crypto/err/err_prn.c
new file mode 100644
index 0000000..d60cfdc
--- /dev/null
+++ b/crypto/err/err_prn.c
@@ -0,0 +1,122 @@
+/* $OpenBSD: err_prn.c,v 1.20 2023/07/07 13:54:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bio_local.h"
+
+void
+ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), void *u)
+{
+	unsigned long l;
+	char buf[256];
+	char buf2[4096];
+	const char *file, *data;
+	int line, flags;
+	unsigned long es;
+	CRYPTO_THREADID cur;
+
+	CRYPTO_THREADID_current(&cur);
+	es = CRYPTO_THREADID_hash(&cur);
+	while ((l = ERR_get_error_line_data(&file, &line, &data,
+	    &flags)) != 0) {
+		ERR_error_string_n(l, buf, sizeof buf);
+		(void) snprintf(buf2, sizeof(buf2), "%lu:%s:%s:%d:%s\n", es,
+		    buf, file, line, (flags & ERR_TXT_STRING) ? data : "");
+		if (cb(buf2, strlen(buf2), u) <= 0)
+			break; /* abort outputting the error report */
+	}
+}
+LCRYPTO_ALIAS(ERR_print_errors_cb);
+
+static int
+print_fp(const char *str, size_t len, void *fp)
+{
+	BIO bio;
+
+	BIO_set(&bio, BIO_s_file());
+	BIO_set_fp(&bio, fp, BIO_NOCLOSE);
+
+	return BIO_printf(&bio, "%s", str);
+}
+
+void
+ERR_print_errors_fp(FILE *fp)
+{
+	ERR_print_errors_cb(print_fp, fp);
+}
+LCRYPTO_ALIAS(ERR_print_errors_fp);
+
+static int
+print_bio(const char *str, size_t len, void *bp)
+{
+	return BIO_write((BIO *)bp, str, len);
+}
+
+void
+ERR_print_errors(BIO *bp)
+{
+	ERR_print_errors_cb(print_bio, bp);
+}
+LCRYPTO_ALIAS(ERR_print_errors);
diff --git a/crypto/evp/bio_b64.c b/crypto/evp/bio_b64.c
new file mode 100644
index 0000000..3c47628
--- /dev/null
+++ b/crypto/evp/bio_b64.c
@@ -0,0 +1,571 @@
+/* $OpenBSD: bio_b64.c,v 1.28 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+#include "evp_local.h"
+
+static int b64_write(BIO *h, const char *buf, int num);
+static int b64_read(BIO *h, char *buf, int size);
+static int b64_puts(BIO *h, const char *str);
+/*static int b64_gets(BIO *h, char *str, int size); */
+static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int b64_new(BIO *h);
+static int b64_free(BIO *data);
+static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+#define B64_BLOCK_SIZE	1024
+#define B64_BLOCK_SIZE2	768
+#define B64_NONE	0
+#define B64_ENCODE	1
+#define B64_DECODE	2
+
+typedef struct b64_struct {
+	/*BIO *bio; moved to the BIO structure */
+	int buf_len;
+	int buf_off;
+	int tmp_len;		/* used to find the start when decoding */
+	int tmp_nl;		/* If true, scan until '\n' */
+	int encode;
+	int start;		/* have we started decoding yet? */
+	int cont;		/* <= 0 when finished */
+	EVP_ENCODE_CTX base64;
+	char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10];
+	char tmp[B64_BLOCK_SIZE];
+} BIO_B64_CTX;
+
+static const BIO_METHOD methods_b64 = {
+	.type = BIO_TYPE_BASE64,
+	.name = "base64 encoding",
+	.bwrite = b64_write,
+	.bread = b64_read,
+	.bputs = b64_puts,
+	.ctrl = b64_ctrl,
+	.create = b64_new,
+	.destroy = b64_free,
+	.callback_ctrl = b64_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_base64(void)
+{
+	return (&methods_b64);
+}
+
+static int
+b64_new(BIO *bi)
+{
+	BIO_B64_CTX *ctx;
+
+	ctx = malloc(sizeof(BIO_B64_CTX));
+	if (ctx == NULL)
+		return (0);
+
+	ctx->buf_len = 0;
+	ctx->tmp_len = 0;
+	ctx->tmp_nl = 0;
+	ctx->buf_off = 0;
+	ctx->cont = 1;
+	ctx->start = 1;
+	ctx->encode = 0;
+
+	bi->init = 1;
+	bi->ptr = (char *)ctx;
+	bi->flags = 0;
+	bi->num = 0;
+	return (1);
+}
+
+static int
+b64_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	free(a->ptr);
+	a->ptr = NULL;
+	a->init = 0;
+	a->flags = 0;
+	return (1);
+}
+
+static int
+b64_read(BIO *b, char *out, int outl)
+{
+	int ret = 0, i, ii, j, k, x, n, num, ret_code = 0;
+	BIO_B64_CTX *ctx;
+	unsigned char *p, *q;
+
+	if (out == NULL)
+		return (0);
+	ctx = (BIO_B64_CTX *)b->ptr;
+
+	if ((ctx == NULL) || (b->next_bio == NULL))
+		return (0);
+
+	BIO_clear_retry_flags(b);
+
+	if (ctx->encode != B64_DECODE) {
+		ctx->encode = B64_DECODE;
+		ctx->buf_len = 0;
+		ctx->buf_off = 0;
+		ctx->tmp_len = 0;
+		EVP_DecodeInit(&(ctx->base64));
+	}
+
+	/* First check if there are bytes decoded/encoded */
+	if (ctx->buf_len > 0) {
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+		i = ctx->buf_len - ctx->buf_off;
+		if (i > outl)
+			i = outl;
+		OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
+		memcpy(out, &(ctx->buf[ctx->buf_off]), i);
+		ret = i;
+		out += i;
+		outl -= i;
+		ctx->buf_off += i;
+		if (ctx->buf_len == ctx->buf_off) {
+			ctx->buf_len = 0;
+			ctx->buf_off = 0;
+		}
+	}
+
+	/* At this point, we have room of outl bytes and an empty
+	 * buffer, so we should read in some more. */
+
+	ret_code = 0;
+	while (outl > 0) {
+		if (ctx->cont <= 0)
+			break;
+
+		i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]),
+		    B64_BLOCK_SIZE - ctx->tmp_len);
+
+		if (i <= 0) {
+			ret_code = i;
+
+			/* Should we continue next time we are called? */
+			if (!BIO_should_retry(b->next_bio)) {
+				ctx->cont = i;
+				/* If buffer empty break */
+				if (ctx->tmp_len == 0)
+					break;
+				/* Fall through and process what we have */
+				else
+					i = 0;
+			}
+			/* else we retry and add more data to buffer */
+			else
+				break;
+		}
+		i += ctx->tmp_len;
+		ctx->tmp_len = i;
+
+		/* We need to scan, a line at a time until we
+		 * have a valid line if we are starting. */
+		if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) {
+			/* ctx->start=1; */
+			ctx->tmp_len = 0;
+		} else if (ctx->start) {
+			q = p =(unsigned char *)ctx->tmp;
+			num = 0;
+			for (j = 0; j < i; j++) {
+				if (*(q++) != '\n')
+					continue;
+
+				/* due to a previous very long line,
+				 * we need to keep on scanning for a '\n'
+				 * before we even start looking for
+				 * base64 encoded stuff. */
+				if (ctx->tmp_nl) {
+					p = q;
+					ctx->tmp_nl = 0;
+					continue;
+				}
+
+				k = EVP_DecodeUpdate(&(ctx->base64),
+				    (unsigned char *)ctx->buf,
+				    &num, p, q - p);
+				if ((k <= 0) && (num == 0) && (ctx->start))
+					EVP_DecodeInit(&ctx->base64);
+				else {
+					if (p != (unsigned char *)
+						&(ctx->tmp[0])) {
+						i -= (p - (unsigned char *)
+						&(ctx->tmp[0]));
+						for (x = 0; x < i; x++)
+							ctx->tmp[x] = p[x];
+					}
+					EVP_DecodeInit(&ctx->base64);
+					ctx->start = 0;
+					break;
+				}
+				p = q;
+			}
+
+			/* we fell off the end without starting */
+			if ((j == i) && (num == 0)) {
+				/* Is this is one long chunk?, if so, keep on
+				 * reading until a new line. */
+				if (p == (unsigned char *)&(ctx->tmp[0])) {
+					/* Check buffer full */
+					if (i == B64_BLOCK_SIZE) {
+						ctx->tmp_nl = 1;
+						ctx->tmp_len = 0;
+					}
+				}
+				else if (p != q) /* finished on a '\n' */
+				{
+					n = q - p;
+					for (ii = 0; ii < n; ii++)
+						ctx->tmp[ii] = p[ii];
+					ctx->tmp_len = n;
+				}
+				/* else finished on a '\n' */
+				continue;
+			} else {
+				ctx->tmp_len = 0;
+			}
+		} else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) {
+			/* If buffer isn't full and we can retry then
+			 * restart to read in more data.
+			 */
+			continue;
+		}
+
+		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
+			int z, jj;
+
+			jj = i & ~3; /* process per 4 */
+			z = EVP_DecodeBlock((unsigned char *)ctx->buf,
+			    (unsigned char *)ctx->tmp, jj);
+			if (jj > 2) {
+				if (ctx->tmp[jj-1] == '=') {
+					z--;
+					if (ctx->tmp[jj-2] == '=')
+						z--;
+				}
+			}
+			/* z is now number of output bytes and jj is the
+			 * number consumed */
+			if (jj != i) {
+				memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
+				ctx->tmp_len = i - jj;
+			}
+			ctx->buf_len = 0;
+			if (z > 0) {
+				ctx->buf_len = z;
+			}
+			i = z;
+		} else {
+			i = EVP_DecodeUpdate(&(ctx->base64),
+			    (unsigned char *)ctx->buf, &ctx->buf_len,
+			    (unsigned char *)ctx->tmp, i);
+			ctx->tmp_len = 0;
+		}
+		ctx->buf_off = 0;
+		if (i < 0) {
+			ret_code = 0;
+			ctx->buf_len = 0;
+			break;
+		}
+
+		if (ctx->buf_len <= outl)
+			i = ctx->buf_len;
+		else
+			i = outl;
+
+		memcpy(out, ctx->buf, i);
+		ret += i;
+		ctx->buf_off = i;
+		if (ctx->buf_off == ctx->buf_len) {
+			ctx->buf_len = 0;
+			ctx->buf_off = 0;
+		}
+		outl -= i;
+		out += i;
+	}
+	/* BIO_clear_retry_flags(b); */
+	BIO_copy_next_retry(b);
+	return ((ret == 0) ? ret_code : ret);
+}
+
+static int
+b64_write(BIO *b, const char *in, int inl)
+{
+	int ret = 0;
+	int n;
+	int i;
+	BIO_B64_CTX *ctx;
+
+	ctx = (BIO_B64_CTX *)b->ptr;
+	BIO_clear_retry_flags(b);
+
+	if (ctx->encode != B64_ENCODE) {
+		ctx->encode = B64_ENCODE;
+		ctx->buf_len = 0;
+		ctx->buf_off = 0;
+		ctx->tmp_len = 0;
+		EVP_EncodeInit(&(ctx->base64));
+	}
+
+	OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
+	OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
+	OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+	n = ctx->buf_len - ctx->buf_off;
+	while (n > 0) {
+		i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
+		if (i <= 0) {
+			BIO_copy_next_retry(b);
+			return (i);
+		}
+		OPENSSL_assert(i <= n);
+		ctx->buf_off += i;
+		OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+		n -= i;
+	}
+	/* at this point all pending data has been written */
+	ctx->buf_off = 0;
+	ctx->buf_len = 0;
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+
+	while (inl > 0) {
+		n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl;
+
+		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
+			if (ctx->tmp_len > 0) {
+				OPENSSL_assert(ctx->tmp_len <= 3);
+				n = 3 - ctx->tmp_len;
+				/* There's a theoretical possibility for this */
+				if (n > inl)
+					n = inl;
+				memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
+				ctx->tmp_len += n;
+				ret += n;
+				if (ctx->tmp_len < 3)
+					break;
+				ctx->buf_len = EVP_EncodeBlock(
+				    (unsigned char *)ctx->buf,
+				    (unsigned char *)ctx->tmp, ctx->tmp_len);
+				OPENSSL_assert(ctx->buf_len <=
+				    (int)sizeof(ctx->buf));
+				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+				/* Since we're now done using the temporary
+				   buffer, the length should be 0'd */
+				ctx->tmp_len = 0;
+			} else {
+				if (n < 3) {
+					memcpy(ctx->tmp, in, n);
+					ctx->tmp_len = n;
+					ret += n;
+					break;
+				}
+				n -= n % 3;
+				ctx->buf_len = EVP_EncodeBlock(
+				    (unsigned char *)ctx->buf,
+				    (const unsigned char *)in, n);
+				OPENSSL_assert(ctx->buf_len <=
+				    (int)sizeof(ctx->buf));
+				OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+				ret += n;
+			}
+		} else {
+			if (!EVP_EncodeUpdate(&(ctx->base64),
+			    (unsigned char *)ctx->buf, &ctx->buf_len,
+			    (unsigned char *)in, n))
+				return ((ret == 0) ? -1 : ret);
+			OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
+			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+			ret += n;
+		}
+		inl -= n;
+		in += n;
+
+		ctx->buf_off = 0;
+		n = ctx->buf_len;
+		while (n > 0) {
+			i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
+			if (i <= 0) {
+				BIO_copy_next_retry(b);
+				return ((ret == 0) ? i : ret);
+			}
+			OPENSSL_assert(i <= n);
+			n -= i;
+			ctx->buf_off += i;
+			OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
+			OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+		}
+		ctx->buf_len = 0;
+		ctx->buf_off = 0;
+	}
+	return (ret);
+}
+
+static long
+b64_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	BIO_B64_CTX *ctx;
+	long ret = 1;
+	int i;
+
+	ctx = (BIO_B64_CTX *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		ctx->cont = 1;
+		ctx->start = 1;
+		ctx->encode = B64_NONE;
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_EOF:	/* More to read */
+		if (ctx->cont <= 0)
+			ret = 1;
+		else
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_WPENDING: /* More to write in buffer */
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+		ret = ctx->buf_len - ctx->buf_off;
+		if ((ret == 0) && (ctx->encode != B64_NONE) &&
+		    (ctx->base64.num != 0))
+			ret = 1;
+		else if (ret <= 0)
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_PENDING: /* More to read in buffer */
+		OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
+		ret = ctx->buf_len - ctx->buf_off;
+		if (ret <= 0)
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_FLUSH:
+		/* do a final write */
+again:
+		while (ctx->buf_len != ctx->buf_off) {
+			i = b64_write(b, NULL, 0);
+			if (i < 0)
+				return i;
+		}
+		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
+			if (ctx->tmp_len != 0) {
+				ctx->buf_len = EVP_EncodeBlock(
+				    (unsigned char *)ctx->buf,
+				    (unsigned char *)ctx->tmp,
+				    ctx->tmp_len);
+				ctx->buf_off = 0;
+				ctx->tmp_len = 0;
+				goto again;
+			}
+		} else if (ctx->encode != B64_NONE && ctx->base64.num != 0) {
+			ctx->buf_off = 0;
+			EVP_EncodeFinal(&(ctx->base64),
+			    (unsigned char *)ctx->buf,
+			    &(ctx->buf_len));
+			/* push out the bytes */
+			goto again;
+		}
+		/* Finally flush the underlying BIO */
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+
+	case BIO_CTRL_DUP:
+		break;
+	case BIO_CTRL_INFO:
+	case BIO_CTRL_GET:
+	case BIO_CTRL_SET:
+	default:
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	}
+	return (ret);
+}
+
+static long
+b64_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);
+}
+
+static int
+b64_puts(BIO *b, const char *str)
+{
+	return b64_write(b, str, strlen(str));
+}
diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c
new file mode 100644
index 0000000..d2132ad
--- /dev/null
+++ b/crypto/evp/bio_enc.c
@@ -0,0 +1,418 @@
+/* $OpenBSD: bio_enc.c,v 1.29 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+#include "evp_local.h"
+
+static int enc_write(BIO *h, const char *buf, int num);
+static int enc_read(BIO *h, char *buf, int size);
+/*static int enc_puts(BIO *h, const char *str); */
+/*static int enc_gets(BIO *h, char *str, int size); */
+static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int enc_new(BIO *h);
+static int enc_free(BIO *data);
+static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps);
+#define ENC_BLOCK_SIZE	(1024*4)
+#define BUF_OFFSET	(EVP_MAX_BLOCK_LENGTH*2)
+
+typedef struct enc_struct {
+	int buf_len;
+	int buf_off;
+	int cont;		/* <= 0 when finished */
+	int finished;
+	int ok;			/* bad decrypt */
+	EVP_CIPHER_CTX cipher;
+	/* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate
+	 * can return up to a block more data than is presented to it
+	 */
+	char buf[ENC_BLOCK_SIZE + BUF_OFFSET + 2];
+} BIO_ENC_CTX;
+
+static const BIO_METHOD methods_enc = {
+	.type = BIO_TYPE_CIPHER,
+	.name = "cipher",
+	.bwrite = enc_write,
+	.bread = enc_read,
+	.ctrl = enc_ctrl,
+	.create = enc_new,
+	.destroy = enc_free,
+	.callback_ctrl = enc_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_cipher(void)
+{
+	return (&methods_enc);
+}
+
+static int
+enc_new(BIO *bi)
+{
+	BIO_ENC_CTX *ctx;
+
+	ctx = malloc(sizeof(BIO_ENC_CTX));
+	if (ctx == NULL)
+		return (0);
+	EVP_CIPHER_CTX_init(&ctx->cipher);
+
+	ctx->buf_len = 0;
+	ctx->buf_off = 0;
+	ctx->cont = 1;
+	ctx->finished = 0;
+	ctx->ok = 1;
+
+	bi->init = 0;
+	bi->ptr = (char *)ctx;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+enc_free(BIO *a)
+{
+	BIO_ENC_CTX *b;
+
+	if (a == NULL)
+		return (0);
+	b = (BIO_ENC_CTX *)a->ptr;
+	EVP_CIPHER_CTX_cleanup(&(b->cipher));
+	freezero(a->ptr, sizeof(BIO_ENC_CTX));
+	a->ptr = NULL;
+	a->init = 0;
+	a->flags = 0;
+	return (1);
+}
+
+static int
+enc_read(BIO *b, char *out, int outl)
+{
+	int ret = 0, i;
+	BIO_ENC_CTX *ctx;
+
+	if (out == NULL)
+		return (0);
+	ctx = (BIO_ENC_CTX *)b->ptr;
+
+	if ((ctx == NULL) || (b->next_bio == NULL))
+		return (0);
+
+	/* First check if there are bytes decoded/encoded */
+	if (ctx->buf_len > 0) {
+		i = ctx->buf_len - ctx->buf_off;
+		if (i > outl)
+			i = outl;
+		memcpy(out, &(ctx->buf[ctx->buf_off]), i);
+		ret = i;
+		out += i;
+		outl -= i;
+		ctx->buf_off += i;
+		if (ctx->buf_len == ctx->buf_off) {
+			ctx->buf_len = 0;
+			ctx->buf_off = 0;
+		}
+	}
+
+	/* At this point, we have room of outl bytes and an empty
+	 * buffer, so we should read in some more. */
+
+	while (outl > 0) {
+		if (ctx->cont <= 0)
+			break;
+
+		/* read in at IV offset, read the EVP_Cipher
+		 * documentation about why */
+		i = BIO_read(b->next_bio, &(ctx->buf[BUF_OFFSET]), ENC_BLOCK_SIZE);
+
+		if (i <= 0) {
+			/* Should be continue next time we are called? */
+			if (!BIO_should_retry(b->next_bio)) {
+				ctx->cont = i;
+				i = EVP_CipherFinal_ex(&(ctx->cipher),
+				    (unsigned char *)ctx->buf,
+				    &(ctx->buf_len));
+				ctx->ok = i;
+				ctx->buf_off = 0;
+			} else {
+				ret = (ret == 0) ? i : ret;
+				break;
+			}
+		} else {
+			EVP_CipherUpdate(&(ctx->cipher),
+			    (unsigned char *)ctx->buf, &ctx->buf_len,
+			    (unsigned char *)&(ctx->buf[BUF_OFFSET]), i);
+			ctx->cont = 1;
+			/* Note: it is possible for EVP_CipherUpdate to
+			 * decrypt zero bytes because this is or looks like
+			 * the final block: if this happens we should retry
+			 * and either read more data or decrypt the final
+			 * block
+			 */
+			if (ctx->buf_len == 0)
+				continue;
+		}
+
+		if (ctx->buf_len <= outl)
+			i = ctx->buf_len;
+		else
+			i = outl;
+		if (i <= 0)
+			break;
+		memcpy(out, ctx->buf, i);
+		ret += i;
+		ctx->buf_off = i;
+		outl -= i;
+		out += i;
+	}
+
+	BIO_clear_retry_flags(b);
+	BIO_copy_next_retry(b);
+	return ((ret == 0) ? ctx->cont : ret);
+}
+
+static int
+enc_write(BIO *b, const char *in, int inl)
+{
+	int ret = 0, n, i;
+	BIO_ENC_CTX *ctx;
+
+	ctx = (BIO_ENC_CTX *)b->ptr;
+	ret = inl;
+
+	BIO_clear_retry_flags(b);
+	n = ctx->buf_len - ctx->buf_off;
+	while (n > 0) {
+		i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
+		if (i <= 0) {
+			BIO_copy_next_retry(b);
+			return (i);
+		}
+		ctx->buf_off += i;
+		n -= i;
+	}
+	/* at this point all pending data has been written */
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+
+	ctx->buf_off = 0;
+	while (inl > 0) {
+		n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl;
+		EVP_CipherUpdate(&(ctx->cipher),
+		    (unsigned char *)ctx->buf, &ctx->buf_len,
+		    (unsigned char *)in, n);
+		inl -= n;
+		in += n;
+
+		ctx->buf_off = 0;
+		n = ctx->buf_len;
+		while (n > 0) {
+			i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
+			if (i <= 0) {
+				BIO_copy_next_retry(b);
+				return (ret == inl) ? i : ret - inl;
+			}
+			n -= i;
+			ctx->buf_off += i;
+		}
+		ctx->buf_len = 0;
+		ctx->buf_off = 0;
+	}
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static long
+enc_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	BIO *dbio;
+	BIO_ENC_CTX *ctx, *dctx;
+	long ret = 1;
+	int i;
+	EVP_CIPHER_CTX **c_ctx;
+
+	ctx = (BIO_ENC_CTX *)b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		ctx->ok = 1;
+		ctx->finished = 0;
+		EVP_CipherInit_ex(&(ctx->cipher), NULL, NULL, NULL, NULL,
+		    ctx->cipher.encrypt);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_EOF:	/* More to read */
+		if (ctx->cont <= 0)
+			ret = 1;
+		else
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_WPENDING:
+		ret = ctx->buf_len - ctx->buf_off;
+		if (ret <= 0)
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_PENDING: /* More to read in buffer */
+		ret = ctx->buf_len - ctx->buf_off;
+		if (ret <= 0)
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_CTRL_FLUSH:
+		/* do a final write */
+again:
+		while (ctx->buf_len != ctx->buf_off) {
+			i = enc_write(b, NULL, 0);
+			if (i < 0)
+				return i;
+		}
+
+		if (!ctx->finished) {
+			ctx->finished = 1;
+			ctx->buf_off = 0;
+			ret = EVP_CipherFinal_ex(&(ctx->cipher),
+			    (unsigned char *)ctx->buf,
+			    &(ctx->buf_len));
+			ctx->ok = (int)ret;
+			if (ret <= 0)
+				break;
+
+			/* push out the bytes */
+			goto again;
+		}
+
+		/* Finally flush the underlying BIO */
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_C_GET_CIPHER_STATUS:
+		ret = (long)ctx->ok;
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+	case BIO_C_GET_CIPHER_CTX:
+		c_ctx = (EVP_CIPHER_CTX **)ptr;
+		(*c_ctx) = &(ctx->cipher);
+		b->init = 1;
+		break;
+	case BIO_CTRL_DUP:
+		dbio = (BIO *)ptr;
+		dctx = (BIO_ENC_CTX *)dbio->ptr;
+		EVP_CIPHER_CTX_init(&dctx->cipher);
+		ret = EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher);
+		if (ret)
+			dbio->init = 1;
+		break;
+	default:
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	}
+	return (ret);
+}
+
+static long
+enc_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);
+}
+
+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 (*cb)(BIO *, int, const char *, int, long, long);
+
+	if (b == NULL)
+		return 0;
+
+	if ((ctx = BIO_get_data(b)) == NULL)
+		return 0;
+
+	if ((cb = BIO_get_callback(b)) != NULL) {
+		if (cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L)
+		    <= 0)
+			return 0;
+	}
+
+	BIO_set_init(b, 1);
+
+	if (!EVP_CipherInit_ex(&(ctx->cipher), c, NULL, k, i, e))
+		return 0;
+
+	if (cb != NULL)
+		return cb(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L);
+
+	return 1;
+}
diff --git a/crypto/evp/bio_md.c b/crypto/evp/bio_md.c
new file mode 100644
index 0000000..ccfcd1e
--- /dev/null
+++ b/crypto/evp/bio_md.c
@@ -0,0 +1,280 @@
+/* $OpenBSD: bio_md.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "bio_local.h"
+#include "evp_local.h"
+
+/* BIO_put and BIO_get both add to the digest,
+ * BIO_gets returns the digest */
+
+static int md_write(BIO *h, char const *buf, int num);
+static int md_read(BIO *h, char *buf, int size);
+/*static int md_puts(BIO *h, const char *str); */
+static int md_gets(BIO *h, char *str, int size);
+static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2);
+static int md_new(BIO *h);
+static int md_free(BIO *data);
+static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);
+
+static const BIO_METHOD methods_md = {
+	.type = BIO_TYPE_MD,
+	.name = "message digest",
+	.bwrite = md_write,
+	.bread = md_read,
+	.bgets = md_gets,
+	.ctrl = md_ctrl,
+	.create = md_new,
+	.destroy = md_free,
+	.callback_ctrl = md_callback_ctrl
+};
+
+const BIO_METHOD *
+BIO_f_md(void)
+{
+	return (&methods_md);
+}
+
+static int
+md_new(BIO *bi)
+{
+	EVP_MD_CTX *ctx;
+
+	ctx = EVP_MD_CTX_create();
+	if (ctx == NULL)
+		return (0);
+
+	bi->init = 0;
+	bi->ptr = (char *)ctx;
+	bi->flags = 0;
+	return (1);
+}
+
+static int
+md_free(BIO *a)
+{
+	if (a == NULL)
+		return (0);
+	EVP_MD_CTX_destroy(a->ptr);
+	a->ptr = NULL;
+	a->init = 0;
+	a->flags = 0;
+	return (1);
+}
+
+static int
+md_read(BIO *b, char *out, int outl)
+{
+	int ret = 0;
+	EVP_MD_CTX *ctx;
+
+	if (out == NULL)
+		return (0);
+	ctx = b->ptr;
+
+	if ((ctx == NULL) || (b->next_bio == NULL))
+		return (0);
+
+	ret = BIO_read(b->next_bio, out, outl);
+	if (b->init) {
+		if (ret > 0) {
+			if (EVP_DigestUpdate(ctx, (unsigned char *)out,
+			    (unsigned int)ret) <= 0)
+				return (-1);
+		}
+	}
+	BIO_clear_retry_flags(b);
+	BIO_copy_next_retry(b);
+	return (ret);
+}
+
+static int
+md_write(BIO *b, const char *in, int inl)
+{
+	int ret = 0;
+	EVP_MD_CTX *ctx;
+
+	if ((in == NULL) || (inl <= 0))
+		return (0);
+	ctx = b->ptr;
+
+	if ((ctx != NULL) && (b->next_bio != NULL))
+		ret = BIO_write(b->next_bio, in, inl);
+	if (b->init) {
+		if (ret > 0) {
+			if (!EVP_DigestUpdate(ctx, (const unsigned char *)in,
+			    (unsigned int)ret)) {
+				BIO_clear_retry_flags(b);
+				return 0;
+			}
+		}
+	}
+	if (b->next_bio != NULL) {
+		BIO_clear_retry_flags(b);
+		BIO_copy_next_retry(b);
+	}
+	return (ret);
+}
+
+static long
+md_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+	EVP_MD_CTX *ctx, *dctx, **pctx;
+	const EVP_MD **ppmd;
+	EVP_MD *md;
+	long ret = 1;
+	BIO *dbio;
+
+	ctx = b->ptr;
+
+	switch (cmd) {
+	case BIO_CTRL_RESET:
+		if (b->init)
+			ret = EVP_DigestInit_ex(ctx, ctx->digest, NULL);
+		else
+			ret = 0;
+		if (ret > 0)
+			ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	case BIO_C_GET_MD:
+		if (b->init) {
+			ppmd = ptr;
+			*ppmd = ctx->digest;
+		} else
+			ret = 0;
+		break;
+	case BIO_C_GET_MD_CTX:
+		pctx = ptr;
+		*pctx = ctx;
+		b->init = 1;
+		break;
+	case BIO_C_SET_MD_CTX:
+		if (b->init)
+			b->ptr = ptr;
+		else
+			ret = 0;
+		break;
+	case BIO_C_DO_STATE_MACHINE:
+		BIO_clear_retry_flags(b);
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		BIO_copy_next_retry(b);
+		break;
+
+	case BIO_C_SET_MD:
+		md = ptr;
+		ret = EVP_DigestInit_ex(ctx, md, NULL);
+		if (ret > 0)
+			b->init = 1;
+		break;
+	case BIO_CTRL_DUP:
+		dbio = ptr;
+		dctx = dbio->ptr;
+		if (!EVP_MD_CTX_copy_ex(dctx, ctx))
+			return 0;
+		b->init = 1;
+		break;
+	default:
+		ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
+		break;
+	}
+	return (ret);
+}
+
+static long
+md_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);
+}
+
+static int
+md_gets(BIO *bp, char *buf, int size)
+{
+	EVP_MD_CTX *ctx;
+	unsigned int ret;
+
+	ctx = bp->ptr;
+	if (size < ctx->digest->md_size)
+		return (0);
+	if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0)
+		return -1;
+
+	return ((int)ret);
+}
+
+/*
+static int md_puts(bp,str)
+BIO *bp;
+char *str;
+	{
+	return(-1);
+	}
+*/
diff --git a/crypto/evp/c_all.c b/crypto/evp/c_all.c
new file mode 100644
index 0000000..871abe6
--- /dev/null
+++ b/crypto/evp/c_all.c
@@ -0,0 +1,329 @@
+/* $OpenBSD: c_all.c,v 1.32 2023/07/24 10:24:58 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "cryptlib.h"
+
+static void
+OpenSSL_add_all_ciphers_internal(void)
+{
+#ifndef OPENSSL_NO_DES
+	EVP_add_cipher(EVP_des_cfb());
+	EVP_add_cipher(EVP_des_cfb1());
+	EVP_add_cipher(EVP_des_cfb8());
+	EVP_add_cipher(EVP_des_ede_cfb());
+	EVP_add_cipher(EVP_des_ede3_cfb());
+	EVP_add_cipher(EVP_des_ede3_cfb1());
+	EVP_add_cipher(EVP_des_ede3_cfb8());
+
+	EVP_add_cipher(EVP_des_ofb());
+	EVP_add_cipher(EVP_des_ede_ofb());
+	EVP_add_cipher(EVP_des_ede3_ofb());
+
+	EVP_add_cipher(EVP_desx_cbc());
+	EVP_add_cipher_alias(SN_desx_cbc, "DESX");
+	EVP_add_cipher_alias(SN_desx_cbc, "desx");
+
+	EVP_add_cipher(EVP_des_cbc());
+	EVP_add_cipher_alias(SN_des_cbc, "DES");
+	EVP_add_cipher_alias(SN_des_cbc, "des");
+	EVP_add_cipher(EVP_des_ede_cbc());
+	EVP_add_cipher(EVP_des_ede3_cbc());
+	EVP_add_cipher_alias(SN_des_ede3_cbc, "DES3");
+	EVP_add_cipher_alias(SN_des_ede3_cbc, "des3");
+
+	EVP_add_cipher(EVP_des_ecb());
+	EVP_add_cipher(EVP_des_ede());
+	EVP_add_cipher(EVP_des_ede3());
+#endif
+
+#ifndef OPENSSL_NO_RC4
+	EVP_add_cipher(EVP_rc4());
+	EVP_add_cipher(EVP_rc4_40());
+#ifndef OPENSSL_NO_MD5
+	EVP_add_cipher(EVP_rc4_hmac_md5());
+#endif
+#endif
+
+#ifndef OPENSSL_NO_IDEA
+	EVP_add_cipher(EVP_idea_ecb());
+	EVP_add_cipher(EVP_idea_cfb());
+	EVP_add_cipher(EVP_idea_ofb());
+	EVP_add_cipher(EVP_idea_cbc());
+	EVP_add_cipher_alias(SN_idea_cbc, "IDEA");
+	EVP_add_cipher_alias(SN_idea_cbc, "idea");
+#endif
+
+#ifndef OPENSSL_NO_RC2
+	EVP_add_cipher(EVP_rc2_ecb());
+	EVP_add_cipher(EVP_rc2_cfb());
+	EVP_add_cipher(EVP_rc2_ofb());
+	EVP_add_cipher(EVP_rc2_cbc());
+	EVP_add_cipher(EVP_rc2_40_cbc());
+	EVP_add_cipher(EVP_rc2_64_cbc());
+	EVP_add_cipher_alias(SN_rc2_cbc, "RC2");
+	EVP_add_cipher_alias(SN_rc2_cbc, "rc2");
+#endif
+
+#ifndef OPENSSL_NO_BF
+	EVP_add_cipher(EVP_bf_ecb());
+	EVP_add_cipher(EVP_bf_cfb());
+	EVP_add_cipher(EVP_bf_ofb());
+	EVP_add_cipher(EVP_bf_cbc());
+	EVP_add_cipher_alias(SN_bf_cbc, "BF");
+	EVP_add_cipher_alias(SN_bf_cbc, "bf");
+	EVP_add_cipher_alias(SN_bf_cbc, "blowfish");
+#endif
+
+#ifndef OPENSSL_NO_CAST
+	EVP_add_cipher(EVP_cast5_ecb());
+	EVP_add_cipher(EVP_cast5_cfb());
+	EVP_add_cipher(EVP_cast5_ofb());
+	EVP_add_cipher(EVP_cast5_cbc());
+	EVP_add_cipher_alias(SN_cast5_cbc, "CAST");
+	EVP_add_cipher_alias(SN_cast5_cbc, "cast");
+	EVP_add_cipher_alias(SN_cast5_cbc, "CAST-cbc");
+	EVP_add_cipher_alias(SN_cast5_cbc, "cast-cbc");
+#endif
+
+#ifndef OPENSSL_NO_AES
+	EVP_add_cipher(EVP_aes_128_ecb());
+	EVP_add_cipher(EVP_aes_128_cbc());
+	EVP_add_cipher(EVP_aes_128_ccm());
+	EVP_add_cipher(EVP_aes_128_cfb());
+	EVP_add_cipher(EVP_aes_128_cfb1());
+	EVP_add_cipher(EVP_aes_128_cfb8());
+	EVP_add_cipher(EVP_aes_128_ofb());
+	EVP_add_cipher(EVP_aes_128_ctr());
+	EVP_add_cipher(EVP_aes_128_gcm());
+	EVP_add_cipher(EVP_aes_128_wrap());
+	EVP_add_cipher(EVP_aes_128_xts());
+	EVP_add_cipher_alias(SN_aes_128_cbc, "AES128");
+	EVP_add_cipher_alias(SN_aes_128_cbc, "aes128");
+	EVP_add_cipher(EVP_aes_192_ecb());
+	EVP_add_cipher(EVP_aes_192_cbc());
+	EVP_add_cipher(EVP_aes_192_ccm());
+	EVP_add_cipher(EVP_aes_192_cfb());
+	EVP_add_cipher(EVP_aes_192_cfb1());
+	EVP_add_cipher(EVP_aes_192_cfb8());
+	EVP_add_cipher(EVP_aes_192_ofb());
+	EVP_add_cipher(EVP_aes_192_ctr());
+	EVP_add_cipher(EVP_aes_192_gcm());
+	EVP_add_cipher(EVP_aes_192_wrap());
+	EVP_add_cipher_alias(SN_aes_192_cbc, "AES192");
+	EVP_add_cipher_alias(SN_aes_192_cbc, "aes192");
+	EVP_add_cipher(EVP_aes_256_ecb());
+	EVP_add_cipher(EVP_aes_256_cbc());
+	EVP_add_cipher(EVP_aes_256_ccm());
+	EVP_add_cipher(EVP_aes_256_cfb());
+	EVP_add_cipher(EVP_aes_256_cfb1());
+	EVP_add_cipher(EVP_aes_256_cfb8());
+	EVP_add_cipher(EVP_aes_256_ofb());
+	EVP_add_cipher(EVP_aes_256_ctr());
+	EVP_add_cipher(EVP_aes_256_gcm());
+	EVP_add_cipher(EVP_aes_256_wrap());
+	EVP_add_cipher(EVP_aes_256_xts());
+	EVP_add_cipher_alias(SN_aes_256_cbc, "AES256");
+	EVP_add_cipher_alias(SN_aes_256_cbc, "aes256");
+#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
+	EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1());
+	EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1());
+#endif
+#endif
+
+#ifndef OPENSSL_NO_CAMELLIA
+	EVP_add_cipher(EVP_camellia_128_ecb());
+	EVP_add_cipher(EVP_camellia_128_cbc());
+	EVP_add_cipher(EVP_camellia_128_cfb());
+	EVP_add_cipher(EVP_camellia_128_cfb1());
+	EVP_add_cipher(EVP_camellia_128_cfb8());
+	EVP_add_cipher(EVP_camellia_128_ofb());
+	EVP_add_cipher_alias(SN_camellia_128_cbc, "CAMELLIA128");
+	EVP_add_cipher_alias(SN_camellia_128_cbc, "camellia128");
+	EVP_add_cipher(EVP_camellia_192_ecb());
+	EVP_add_cipher(EVP_camellia_192_cbc());
+	EVP_add_cipher(EVP_camellia_192_cfb());
+	EVP_add_cipher(EVP_camellia_192_cfb1());
+	EVP_add_cipher(EVP_camellia_192_cfb8());
+	EVP_add_cipher(EVP_camellia_192_ofb());
+	EVP_add_cipher_alias(SN_camellia_192_cbc, "CAMELLIA192");
+	EVP_add_cipher_alias(SN_camellia_192_cbc, "camellia192");
+	EVP_add_cipher(EVP_camellia_256_ecb());
+	EVP_add_cipher(EVP_camellia_256_cbc());
+	EVP_add_cipher(EVP_camellia_256_cfb());
+	EVP_add_cipher(EVP_camellia_256_cfb1());
+	EVP_add_cipher(EVP_camellia_256_cfb8());
+	EVP_add_cipher(EVP_camellia_256_ofb());
+	EVP_add_cipher_alias(SN_camellia_256_cbc, "CAMELLIA256");
+	EVP_add_cipher_alias(SN_camellia_256_cbc, "camellia256");
+#endif
+
+#ifndef OPENSSL_NO_CHACHA
+	EVP_add_cipher(EVP_chacha20());
+#endif
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+	EVP_add_cipher(EVP_chacha20_poly1305());
+#endif
+
+#ifndef OPENSSL_NO_GOST
+	EVP_add_cipher(EVP_gost2814789_ecb());
+	EVP_add_cipher(EVP_gost2814789_cfb64());
+	EVP_add_cipher(EVP_gost2814789_cnt());
+#endif
+
+#ifndef OPENSSL_NO_SM4
+	EVP_add_cipher(EVP_sm4_ecb());
+	EVP_add_cipher(EVP_sm4_cbc());
+	EVP_add_cipher(EVP_sm4_cfb());
+	EVP_add_cipher(EVP_sm4_ofb());
+	EVP_add_cipher(EVP_sm4_ctr());
+	EVP_add_cipher_alias(SN_sm4_cbc, "SM4");
+	EVP_add_cipher_alias(SN_sm4_cbc, "sm4");
+#endif
+}
+
+void
+OpenSSL_add_all_ciphers(void)
+{
+	static pthread_once_t add_all_ciphers_once = PTHREAD_ONCE_INIT;
+	(void) pthread_once(&add_all_ciphers_once, OpenSSL_add_all_ciphers_internal);
+}
+
+static void
+OpenSSL_add_all_digests_internal(void)
+{
+#ifndef OPENSSL_NO_MD4
+	EVP_add_digest(EVP_md4());
+#endif
+
+#ifndef OPENSSL_NO_MD5
+	EVP_add_digest(EVP_md5());
+	EVP_add_digest(EVP_md5_sha1());
+	EVP_add_digest_alias(SN_md5, "ssl2-md5");
+	EVP_add_digest_alias(SN_md5, "ssl3-md5");
+#endif
+
+#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
+	EVP_add_digest(EVP_sha1());
+	EVP_add_digest_alias(SN_sha1, "ssl3-sha1");
+	EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA);
+#endif
+
+#ifndef OPENSSL_NO_GOST
+	EVP_add_digest(EVP_gostr341194());
+	EVP_add_digest(EVP_gost2814789imit());
+	EVP_add_digest(EVP_streebog256());
+	EVP_add_digest(EVP_streebog512());
+#endif
+#ifndef OPENSSL_NO_RIPEMD
+	EVP_add_digest(EVP_ripemd160());
+	EVP_add_digest_alias(SN_ripemd160, "ripemd");
+	EVP_add_digest_alias(SN_ripemd160, "rmd160");
+#endif
+#ifndef OPENSSL_NO_SHA256
+	EVP_add_digest(EVP_sha224());
+	EVP_add_digest(EVP_sha256());
+#endif
+#ifndef OPENSSL_NO_SHA512
+	EVP_add_digest(EVP_sha384());
+	EVP_add_digest(EVP_sha512());
+	EVP_add_digest(EVP_sha512_224());
+	EVP_add_digest(EVP_sha512_256());
+#endif
+#ifndef OPENSSL_NO_SHA3
+	EVP_add_digest(EVP_sha3_224());
+	EVP_add_digest(EVP_sha3_256());
+	EVP_add_digest(EVP_sha3_384());
+	EVP_add_digest(EVP_sha3_512());
+#endif
+#ifndef OPENSSL_NO_SM3
+	EVP_add_digest(EVP_sm3());
+#endif
+#ifndef OPENSSL_NO_WHIRLPOOL
+	EVP_add_digest(EVP_whirlpool());
+#endif
+}
+
+void
+OpenSSL_add_all_digests(void)
+{
+	static pthread_once_t add_all_digests_once = PTHREAD_ONCE_INIT;
+	(void) pthread_once(&add_all_digests_once, OpenSSL_add_all_digests_internal);
+}
+
+void
+OPENSSL_add_all_algorithms_noconf(void)
+{
+	OpenSSL_add_all_ciphers();
+	OpenSSL_add_all_digests();
+}
+
+void
+OPENSSL_add_all_algorithms_conf(void)
+{
+	OPENSSL_add_all_algorithms_noconf();
+	OPENSSL_config(NULL);
+}
diff --git a/crypto/evp/cipher_method_lib.c b/crypto/evp/cipher_method_lib.c
new file mode 100644
index 0000000..c3f510f
--- /dev/null
+++ b/crypto/evp/cipher_method_lib.c
@@ -0,0 +1,178 @@
+/*	$OpenBSD: cipher_method_lib.c,v 1.10 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Written by Richard Levitte (levitte@openssl.org) for the OpenSSL project
+ * 2015.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include "evp_local.h"
+
+EVP_CIPHER *
+EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
+{
+	EVP_CIPHER *cipher;
+
+	if ((cipher = calloc(1, sizeof(*cipher))) == NULL)
+		return NULL;
+
+	cipher->nid = cipher_type;
+	cipher->block_size = block_size;
+	cipher->key_len = key_len;
+
+	return cipher;
+}
+
+EVP_CIPHER *
+EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
+{
+	EVP_CIPHER *copy;
+
+	if ((copy = calloc(1, sizeof(*copy))) == NULL)
+		return NULL;
+
+	*copy = *cipher;
+
+	return copy;
+}
+
+void
+EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
+{
+	free(cipher);
+}
+
+int
+EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
+{
+	cipher->iv_len = iv_len;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags)
+{
+	cipher->flags = flags;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size)
+{
+	cipher->ctx_size = ctx_size;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
+    int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc))
+{
+	cipher->init = init;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
+    int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl))
+{
+	cipher->do_cipher = do_cipher;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
+    int (*cleanup)(EVP_CIPHER_CTX *))
+{
+	cipher->cleanup = cleanup;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher,
+    int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *))
+{
+	cipher->set_asn1_parameters = set_asn1_parameters;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher,
+    int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *))
+{
+	cipher->get_asn1_parameters = get_asn1_parameters;
+
+	return 1;
+}
+
+int
+EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
+    int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr))
+{
+	cipher->ctrl = ctrl;
+
+	return 1;
+}
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
new file mode 100644
index 0000000..ca3fb21
--- /dev/null
+++ b/crypto/evp/digest.c
@@ -0,0 +1,429 @@
+/* $OpenBSD: digest.c,v 1.38 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "evp_local.h"
+
+int
+EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
+{
+	EVP_MD_CTX_init(ctx);
+	return EVP_DigestInit_ex(ctx, type, NULL);
+}
+
+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
+	/* 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 previous handle, re-querying for an ENGINE, and having a
+	 * reinitialisation, when it may all be unnecessary. */
+	if (ctx->engine && ctx->digest && (!type ||
+	    (type && (type->type == ctx->digest->type))))
+		goto skip_to_init;
+	if (type) {
+		/* 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);
+		if (impl != NULL) {
+			if (!ENGINE_init(impl)) {
+				EVPerror(EVP_R_INITIALIZATION_ERROR);
+				return 0;
+			}
+		} else
+			/* Ask if an ENGINE is reserved for this job */
+			impl = ENGINE_get_digest_engine(type->type);
+		if (impl != NULL) {
+			/* There's an ENGINE for this job ... (apparently) */
+			const EVP_MD *d = ENGINE_get_digest(impl, type->type);
+			if (d == NULL) {
+				/* Same comment from evp_enc.c */
+				EVPerror(EVP_R_INITIALIZATION_ERROR);
+				ENGINE_finish(impl);
+				return 0;
+			}
+			/* We'll use the ENGINE's private digest definition */
+			type = d;
+			/* Store the ENGINE functional reference so we know
+			 * 'type' came from an ENGINE and we need to release
+			 * it when done. */
+			ctx->engine = impl;
+		} else
+			ctx->engine = NULL;
+	} else if (!ctx->digest) {
+		EVPerror(EVP_R_NO_DIGEST_SET);
+		return 0;
+	}
+#endif
+	if (ctx->digest != type) {
+		if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
+		    !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
+			freezero(ctx->md_data, ctx->digest->ctx_size);
+			ctx->md_data = NULL;
+		}
+		ctx->digest = type;
+		if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
+			ctx->update = type->update;
+			ctx->md_data = calloc(1, type->ctx_size);
+			if (ctx->md_data == NULL) {
+				EVP_PKEY_CTX_free(ctx->pctx);
+				ctx->pctx = NULL;
+				EVPerror(ERR_R_MALLOC_FAILURE);
+				return 0;
+			}
+		}
+	}
+#ifndef OPENSSL_NO_ENGINE
+skip_to_init:
+#endif
+	if (ctx->pctx) {
+		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;
+	}
+	if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
+		return 1;
+	return ctx->digest->init(ctx);
+}
+
+int
+EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return ctx->update(ctx, data, count);
+}
+
+/* The caller can assume that this removes any secret data from the context */
+int
+EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+{
+	int ret;
+
+	ret = EVP_DigestFinal_ex(ctx, md, size);
+	EVP_MD_CTX_cleanup(ctx);
+	return ret;
+}
+
+/* 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 ret;
+
+	if ((size_t)ctx->digest->md_size > EVP_MAX_MD_SIZE) {
+		EVPerror(EVP_R_TOO_LARGE);
+		return 0;
+	}
+	ret = ctx->digest->final(ctx, md);
+	if (size != NULL)
+		*size = ctx->digest->md_size;
+	if (ctx->digest->cleanup) {
+		ctx->digest->cleanup(ctx);
+		EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+	}
+	memset(ctx->md_data, 0, ctx->digest->ctx_size);
+	return ret;
+}
+
+int
+EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
+{
+	EVP_MD_CTX_init(out);
+	return EVP_MD_CTX_copy_ex(out, in);
+}
+
+int
+EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
+{
+	unsigned char *tmp_buf;
+
+	if ((in == NULL) || (in->digest == NULL)) {
+		EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
+		return 0;
+	}
+#ifndef OPENSSL_NO_ENGINE
+	/* Make sure it's safe to copy a digest context using an ENGINE */
+	if (in->engine && !ENGINE_init(in->engine)) {
+		EVPerror(ERR_R_ENGINE_LIB);
+		return 0;
+	}
+#endif
+
+	if (out->digest == in->digest) {
+		tmp_buf = out->md_data;
+		EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE);
+	} else
+		tmp_buf = NULL;
+	EVP_MD_CTX_cleanup(out);
+	memcpy(out, in, sizeof *out);
+	out->md_data = NULL;
+	out->pctx = NULL;
+
+	/*
+	 * Because of the EVP_PKEY_CTX_dup() below, EVP_MD_CTX_cleanup() needs
+	 * to free out->pctx in all cases (even if this flag is set on in).
+	 */
+	EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+
+	if (in->md_data && out->digest->ctx_size) {
+		if (tmp_buf) {
+			out->md_data = tmp_buf;
+		} else {
+			out->md_data = calloc(1, out->digest->ctx_size);
+			if (out->md_data == NULL) {
+				EVPerror(ERR_R_MALLOC_FAILURE);
+				return 0;
+			}
+		}
+		memcpy(out->md_data, in->md_data, out->digest->ctx_size);
+	}
+
+	out->update = in->update;
+
+	if (in->pctx) {
+		out->pctx = EVP_PKEY_CTX_dup(in->pctx);
+		if (!out->pctx) {
+			EVP_MD_CTX_cleanup(out);
+			return 0;
+		}
+	}
+
+	if (out->digest->copy)
+		return out->digest->copy(out, in);
+
+	return 1;
+}
+
+int
+EVP_Digest(const void *data, size_t count,
+    unsigned char *md, unsigned int *size, const EVP_MD *type, ENGINE *impl)
+{
+	EVP_MD_CTX ctx;
+	int ret;
+
+	EVP_MD_CTX_init(&ctx);
+	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_ONESHOT);
+	ret = EVP_DigestInit_ex(&ctx, type, impl) &&
+	    EVP_DigestUpdate(&ctx, data, count) &&
+	    EVP_DigestFinal_ex(&ctx, md, size);
+	EVP_MD_CTX_cleanup(&ctx);
+
+	return ret;
+}
+
+EVP_MD_CTX *
+EVP_MD_CTX_new(void)
+{
+	return calloc(1, sizeof(EVP_MD_CTX));
+}
+
+void
+EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	EVP_MD_CTX_cleanup(ctx);
+
+	free(ctx);
+}
+
+void
+EVP_MD_CTX_init(EVP_MD_CTX *ctx)
+{
+	memset(ctx, 0, sizeof(*ctx));
+}
+
+int
+EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+	return EVP_MD_CTX_cleanup(ctx);
+}
+
+EVP_MD_CTX *
+EVP_MD_CTX_create(void)
+{
+	return EVP_MD_CTX_new();
+}
+
+void
+EVP_MD_CTX_destroy(EVP_MD_CTX *ctx)
+{
+	EVP_MD_CTX_free(ctx);
+}
+
+/* This call frees resources associated with the context */
+int
+EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx)
+{
+	/*
+	 * Don't assume ctx->md_data was cleaned in EVP_Digest_Final,
+	 * because sometimes only copies of the context are ever finalised.
+	 */
+	if (ctx->digest && ctx->digest->cleanup &&
+	    !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
+		ctx->digest->cleanup(ctx);
+	if (ctx->digest && ctx->digest->ctx_size && ctx->md_data &&
+	    !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE))
+		freezero(ctx->md_data, ctx->digest->ctx_size);
+	/*
+	 * If EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set, EVP_MD_CTX_set_pkey() was
+	 * called and its strange API contract implies we don't own ctx->pctx.
+	 */
+	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);
+#endif
+	memset(ctx, 0, sizeof(*ctx));
+
+	return 1;
+}
+
+int
+EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
+{
+	int ret;
+
+	if (!ctx->digest) {
+		EVPerror(EVP_R_NO_CIPHER_SET);
+		return 0;
+	}
+
+	if (!ctx->digest->md_ctrl) {
+		EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
+		return 0;
+	}
+
+	ret = ctx->digest->md_ctrl(ctx, type, arg, ptr);
+	if (ret == -1) {
+		EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return ret;
+}
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
new file mode 100644
index 0000000..3d357f0
--- /dev/null
+++ b/crypto/evp/e_aes.c
@@ -0,0 +1,2602 @@
+/* $OpenBSD: e_aes.c,v 1.54 2023/09/28 11:29:10 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2001-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_AES
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "modes_local.h"
+
+typedef struct {
+	AES_KEY ks;
+	block128_f block;
+	union {
+		cbc128_f cbc;
+		ctr128_f ctr;
+	} stream;
+} EVP_AES_KEY;
+
+typedef struct {
+	AES_KEY ks;		/* AES key schedule to use */
+	int key_set;		/* Set if key initialised */
+	int iv_set;		/* Set if an iv is set */
+	GCM128_CONTEXT gcm;
+	unsigned char *iv;	/* Temporary IV store */
+	int ivlen;		/* IV length */
+	int taglen;
+	int iv_gen;		/* It is OK to generate IVs */
+	int tls_aad_len;	/* TLS AAD length */
+	ctr128_f ctr;
+} EVP_AES_GCM_CTX;
+
+typedef struct {
+	AES_KEY ks1, ks2;	/* AES key schedules to use */
+	XTS128_CONTEXT xts;
+	void (*stream)(const unsigned char *in, unsigned char *out,
+	    size_t length, const AES_KEY *key1, const AES_KEY *key2,
+	    const unsigned char iv[16]);
+} EVP_AES_XTS_CTX;
+
+typedef struct {
+	AES_KEY ks;		/* AES key schedule to use */
+	int key_set;		/* Set if key initialised */
+	int iv_set;		/* Set if an iv is set */
+	int tag_set;		/* Set if tag is valid */
+	int len_set;		/* Set if message length set */
+	int L, M;		/* L and M parameters from RFC3610 */
+	CCM128_CONTEXT ccm;
+	ccm128_f str;
+} EVP_AES_CCM_CTX;
+
+#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 char *inp, char *out, size_t len,
+    const AES_KEY *key1, const AES_KEY *key2, const unsigned char iv[16]);
+void AES_xts_decrypt(const char *inp, char *out, size_t len,
+    const AES_KEY *key1, const AES_KEY *key2, const unsigned char iv[16]);
+#endif
+
+#if	defined(AES_ASM) &&				(  \
+	((defined(__i386)	|| defined(__i386__)	|| \
+	  defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
+	defined(__x86_64)	|| defined(__x86_64__)	|| \
+	defined(_M_AMD64)	|| defined(_M_X64)	|| \
+	defined(__INTEL__)				)
+
+#include "x86_arch.h"
+
+#ifdef VPAES_ASM
+#define VPAES_CAPABLE	(OPENSSL_cpu_caps() & CPUCAP_MASK_SSSE3)
+#endif
+#ifdef BSAES_ASM
+#define BSAES_CAPABLE	VPAES_CAPABLE
+#endif
+/*
+ * AES-NI section
+ */
+#define	AESNI_CAPABLE	(OPENSSL_cpu_caps() & CPUCAP_MASK_AESNI)
+
+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]);
+
+static int
+aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	int ret, mode;
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	mode = ctx->cipher->flags & EVP_CIPH_MODE;
+	if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) &&
+	    !enc) {
+		ret = aesni_set_decrypt_key(key, ctx->key_len * 8,
+		    ctx->cipher_data);
+		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, ctx->key_len * 8,
+		    ctx->cipher_data);
+		dat->block = (block128_f)aesni_encrypt;
+		if (mode == EVP_CIPH_CBC_MODE)
+			dat->stream.cbc = (cbc128_f)aesni_cbc_encrypt;
+		else if (mode == EVP_CIPH_CTR_MODE)
+			dat->stream.ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
+		else
+			dat->stream.cbc = NULL;
+	}
+
+	if (ret < 0) {
+		EVPerror(EVP_R_AES_KEY_SETUP_FAILED);
+		return 0;
+	}
+
+	return 1;
+}
+
+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, ctx->cipher_data, ctx->iv,
+	    ctx->encrypt);
+
+	return 1;
+}
+
+static int
+aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	size_t	bl = ctx->cipher->block_size;
+
+	if (len < bl)
+		return 1;
+
+	aesni_ecb_encrypt(in, out, len, ctx->cipher_data, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+	if (key) {
+		aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks);
+		CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
+		    (block128_f)aesni_encrypt);
+		gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
+		/* If we have an iv can set it directly, otherwise use
+		 * saved IV.
+		 */
+		if (iv == NULL && gctx->iv_set)
+			iv = gctx->iv;
+		if (iv) {
+			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+			gctx->iv_set = 1;
+		}
+		gctx->key_set = 1;
+	} else {
+		/* If key set use IV, otherwise copy */
+		if (gctx->key_set)
+			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+		else
+			memcpy(gctx->iv, iv, gctx->ivlen);
+		gctx->iv_set = 1;
+		gctx->iv_gen = 0;
+	}
+	return 1;
+}
+
+static int
+aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+
+	if (key) {
+		/* key_len is two AES keys */
+		if (enc) {
+			aesni_set_encrypt_key(key, ctx->key_len * 4,
+			    &xctx->ks1);
+			xctx->xts.block1 = (block128_f)aesni_encrypt;
+			xctx->stream = aesni_xts_encrypt;
+		} else {
+			aesni_set_decrypt_key(key, ctx->key_len * 4,
+			    &xctx->ks1);
+			xctx->xts.block1 = (block128_f)aesni_decrypt;
+			xctx->stream = aesni_xts_decrypt;
+		}
+
+		aesni_set_encrypt_key(key + ctx->key_len / 2,
+		    ctx->key_len * 4, &xctx->ks2);
+		xctx->xts.block2 = (block128_f)aesni_encrypt;
+
+		xctx->xts.key1 = &xctx->ks1;
+	}
+
+	if (iv) {
+		xctx->xts.key2 = &xctx->ks2;
+		memcpy(ctx->iv, iv, 16);
+	}
+
+	return 1;
+}
+
+static int
+aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+	if (key) {
+		aesni_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
+		CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
+		    &cctx->ks, (block128_f)aesni_encrypt);
+		cctx->str = enc ? (ccm128_f)aesni_ccm64_encrypt_blocks :
+		    (ccm128_f)aesni_ccm64_decrypt_blocks;
+		cctx->key_set = 1;
+	}
+	if (iv) {
+		memcpy(ctx->iv, iv, 15 - cctx->L);
+		cctx->iv_set = 1;
+	}
+	return 1;
+}
+
+#endif
+
+static int
+aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	int ret, mode;
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	mode = ctx->cipher->flags & EVP_CIPH_MODE;
+	if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) &&
+	    !enc)
+#ifdef BSAES_CAPABLE
+		if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
+			ret = AES_set_decrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)AES_decrypt;
+			dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
+		} else
+#endif
+#ifdef VPAES_CAPABLE
+		if (VPAES_CAPABLE) {
+			ret = vpaes_set_decrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)vpaes_decrypt;
+			dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+			    (cbc128_f)vpaes_cbc_encrypt : NULL;
+		} else
+#endif
+		{
+			ret = AES_set_decrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)AES_decrypt;
+			dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+			    (cbc128_f)AES_cbc_encrypt : NULL;
+		} else
+#ifdef BSAES_CAPABLE
+		if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) {
+			ret = AES_set_encrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)AES_encrypt;
+			dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
+		} else
+#endif
+#ifdef VPAES_CAPABLE
+		if (VPAES_CAPABLE) {
+			ret = vpaes_set_encrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)vpaes_encrypt;
+			dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+			    (cbc128_f)vpaes_cbc_encrypt : NULL;
+		} else
+#endif
+		{
+			ret = AES_set_encrypt_key(key, ctx->key_len * 8,
+			    &dat->ks);
+			dat->block = (block128_f)AES_encrypt;
+			dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
+			    (cbc128_f)AES_cbc_encrypt : NULL;
+#ifdef AES_CTR_ASM
+			if (mode == EVP_CIPH_CTR_MODE)
+				dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
+#endif
+		}
+
+	if (ret < 0) {
+		EVPerror(EVP_R_AES_KEY_SETUP_FAILED);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	if (dat->stream.cbc)
+		(*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv,
+		    ctx->encrypt);
+	else if (ctx->encrypt)
+		CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv,
+		    dat->block);
+	else
+		CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv,
+		    dat->block);
+
+	return 1;
+}
+
+static int
+aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	size_t	bl = ctx->cipher->block_size;
+	size_t	i;
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	if (len < bl)
+		return 1;
+
+	for (i = 0, len -= bl; i <= len; i += bl)
+		(*dat->block)(in + i, out + i, &dat->ks);
+
+	return 1;
+}
+
+static int
+aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num,
+	    dat->block);
+	return 1;
+}
+
+static int
+aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num,
+	    ctx->encrypt, dat->block);
+	return 1;
+}
+
+static int
+aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num,
+	    ctx->encrypt, dat->block);
+	return 1;
+}
+
+static int
+aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	if (ctx->flags&EVP_CIPH_FLAG_LENGTH_BITS) {
+		CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, ctx->iv,
+		    &ctx->num, ctx->encrypt, dat->block);
+		return 1;
+	}
+
+	while (len >= MAXBITCHUNK) {
+		CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK*8, &dat->ks,
+		    ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+		len -= MAXBITCHUNK;
+		in += MAXBITCHUNK;
+		out += MAXBITCHUNK;
+	}
+	if (len)
+		CRYPTO_cfb128_1_encrypt(in, out, len*8, &dat->ks,
+		    ctx->iv, &ctx->num, ctx->encrypt, dat->block);
+
+	return 1;
+}
+
+static int
+aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	unsigned int num = ctx->num;
+	EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
+
+	if (dat->stream.ctr)
+		CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
+		    ctx->iv, ctx->buf, &num, dat->stream.ctr);
+	else
+		CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
+		    ctx->iv, ctx->buf, &num, dat->block);
+	ctx->num = (size_t)num;
+	return 1;
+}
+
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_cbc = {
+	.nid = NID_aes_128_cbc,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_cbc = {
+	.nid = NID_aes_128_cbc,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_cbc(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_cbc : &aes_128_cbc;
+#else
+	return &aes_128_cbc;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_ecb = {
+	.nid = NID_aes_128_ecb,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_ecb = {
+	.nid = NID_aes_128_ecb,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_ecb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_ecb : &aes_128_ecb;
+#else
+	return &aes_128_ecb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_ofb = {
+	.nid = NID_aes_128_ofb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_ofb = {
+	.nid = NID_aes_128_ofb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_ofb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_ofb : &aes_128_ofb;
+#else
+	return &aes_128_ofb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_cfb = {
+	.nid = NID_aes_128_cfb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_cfb = {
+	.nid = NID_aes_128_cfb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_cfb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_cfb : &aes_128_cfb;
+#else
+	return &aes_128_cfb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_cfb1 = {
+	.nid = NID_aes_128_cfb1,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_cfb1 = {
+	.nid = NID_aes_128_cfb1,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_cfb1(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_cfb1 : &aes_128_cfb1;
+#else
+	return &aes_128_cfb1;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_cfb8 = {
+	.nid = NID_aes_128_cfb8,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_cfb8 = {
+	.nid = NID_aes_128_cfb8,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_cfb8(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_cfb8 : &aes_128_cfb8;
+#else
+	return &aes_128_cfb8;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_ctr = {
+	.nid = NID_aes_128_ctr,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_128_ctr = {
+	.nid = NID_aes_128_ctr,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_128_ctr(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_ctr : &aes_128_ctr;
+#else
+	return &aes_128_ctr;
+#endif
+}
+
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_cbc = {
+	.nid = NID_aes_192_cbc,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_cbc = {
+	.nid = NID_aes_192_cbc,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_cbc(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_cbc : &aes_192_cbc;
+#else
+	return &aes_192_cbc;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_ecb = {
+	.nid = NID_aes_192_ecb,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_ecb = {
+	.nid = NID_aes_192_ecb,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_ecb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_ecb : &aes_192_ecb;
+#else
+	return &aes_192_ecb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_ofb = {
+	.nid = NID_aes_192_ofb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_ofb = {
+	.nid = NID_aes_192_ofb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_ofb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_ofb : &aes_192_ofb;
+#else
+	return &aes_192_ofb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_cfb = {
+	.nid = NID_aes_192_cfb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_cfb = {
+	.nid = NID_aes_192_cfb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_cfb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_cfb : &aes_192_cfb;
+#else
+	return &aes_192_cfb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_cfb1 = {
+	.nid = NID_aes_192_cfb1,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_cfb1 = {
+	.nid = NID_aes_192_cfb1,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_cfb1(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_cfb1 : &aes_192_cfb1;
+#else
+	return &aes_192_cfb1;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_cfb8 = {
+	.nid = NID_aes_192_cfb8,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_cfb8 = {
+	.nid = NID_aes_192_cfb8,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_cfb8(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_cfb8 : &aes_192_cfb8;
+#else
+	return &aes_192_cfb8;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_ctr = {
+	.nid = NID_aes_192_ctr,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_192_ctr = {
+	.nid = NID_aes_192_ctr,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_192_ctr(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_ctr : &aes_192_ctr;
+#else
+	return &aes_192_ctr;
+#endif
+}
+
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_cbc = {
+	.nid = NID_aes_256_cbc,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_cbc = {
+	.nid = NID_aes_256_cbc,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cbc_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_cbc(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_cbc : &aes_256_cbc;
+#else
+	return &aes_256_cbc;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_ecb = {
+	.nid = NID_aes_256_ecb,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aesni_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_ecb = {
+	.nid = NID_aes_256_ecb,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ecb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_ecb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_ecb : &aes_256_ecb;
+#else
+	return &aes_256_ecb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_ofb = {
+	.nid = NID_aes_256_ofb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_ofb = {
+	.nid = NID_aes_256_ofb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ofb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_ofb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_ofb : &aes_256_ofb;
+#else
+	return &aes_256_ofb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_cfb = {
+	.nid = NID_aes_256_cfb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_cfb = {
+	.nid = NID_aes_256_cfb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_cfb(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_cfb : &aes_256_cfb;
+#else
+	return &aes_256_cfb;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_cfb1 = {
+	.nid = NID_aes_256_cfb1,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_cfb1 = {
+	.nid = NID_aes_256_cfb1,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb1_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_cfb1(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_cfb1 : &aes_256_cfb1;
+#else
+	return &aes_256_cfb1;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_cfb8 = {
+	.nid = NID_aes_256_cfb8,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_cfb8 = {
+	.nid = NID_aes_256_cfb8,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CFB_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_cfb8_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_cfb8(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_cfb8 : &aes_256_cfb8;
+#else
+	return &aes_256_cfb8;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_ctr = {
+	.nid = NID_aes_256_ctr,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aesni_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+#endif
+
+static const EVP_CIPHER aes_256_ctr = {
+	.nid = NID_aes_256_ctr,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = aes_init_key,
+	.do_cipher = aes_ctr_cipher,
+	.ctx_size = sizeof(EVP_AES_KEY),
+};
+
+const EVP_CIPHER *
+EVP_aes_256_ctr(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_ctr : &aes_256_ctr;
+#else
+	return &aes_256_ctr;
+#endif
+}
+
+static int
+aes_gcm_cleanup(EVP_CIPHER_CTX *c)
+{
+	EVP_AES_GCM_CTX *gctx = c->cipher_data;
+
+	if (gctx->iv != c->iv)
+		free(gctx->iv);
+
+	explicit_bzero(gctx, sizeof(*gctx));
+
+	return 1;
+}
+
+/* increment counter (64-bit int) by 1 */
+static void
+ctr64_inc(unsigned char *counter)
+{
+	int n = 8;
+	unsigned char  c;
+
+	do {
+		--n;
+		c = counter[n];
+		++c;
+		counter[n] = c;
+		if (c)
+			return;
+	} while (n);
+}
+
+static int
+aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	EVP_AES_GCM_CTX *gctx = c->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_INIT:
+		gctx->key_set = 0;
+		gctx->iv_set = 0;
+		if (c->cipher->iv_len == 0) {
+			EVPerror(EVP_R_INVALID_IV_LENGTH);
+			return 0;
+		}
+		gctx->ivlen = c->cipher->iv_len;
+		gctx->iv = c->iv;
+		gctx->taglen = -1;
+		gctx->iv_gen = 0;
+		gctx->tls_aad_len = -1;
+		return 1;
+
+	case EVP_CTRL_AEAD_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 != c->iv)
+				free(gctx->iv);
+			gctx->iv = malloc(arg);
+			if (!gctx->iv)
+				return 0;
+		}
+		gctx->ivlen = arg;
+		return 1;
+
+	case EVP_CTRL_GCM_SET_TAG:
+		if (arg <= 0 || arg > 16 || c->encrypt)
+			return 0;
+		memcpy(c->buf, ptr, arg);
+		gctx->taglen = arg;
+		return 1;
+
+	case EVP_CTRL_GCM_GET_TAG:
+		if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0)
+			return 0;
+		memcpy(ptr, c->buf, arg);
+		return 1;
+
+	case EVP_CTRL_GCM_SET_IV_FIXED:
+		/* Special case: -1 length restores whole IV */
+		if (arg == -1) {
+			memcpy(gctx->iv, ptr, gctx->ivlen);
+			gctx->iv_gen = 1;
+			return 1;
+		}
+		/* Fixed field must be at least 4 bytes and invocation field
+		 * at least 8.
+		 */
+		if ((arg < 4) || (gctx->ivlen - arg) < 8)
+			return 0;
+		if (arg)
+			memcpy(gctx->iv, ptr, arg);
+		if (c->encrypt)
+			arc4random_buf(gctx->iv + arg, gctx->ivlen - arg);
+		gctx->iv_gen = 1;
+		return 1;
+
+	case EVP_CTRL_GCM_IV_GEN:
+		if (gctx->iv_gen == 0 || gctx->key_set == 0)
+			return 0;
+		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
+		if (arg <= 0 || arg > gctx->ivlen)
+			arg = gctx->ivlen;
+		memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
+		/* Invocation field will be at least 8 bytes in size and
+		 * so no need to check wrap around or increment more than
+		 * last 8 bytes.
+		 */
+		ctr64_inc(gctx->iv + gctx->ivlen - 8);
+		gctx->iv_set = 1;
+		return 1;
+
+	case EVP_CTRL_GCM_SET_IV_INV:
+		if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
+			return 0;
+		memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
+		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
+		gctx->iv_set = 1;
+		return 1;
+
+	case EVP_CTRL_AEAD_TLS1_AAD:
+		/* Save the AAD for later use */
+		if (arg != 13)
+			return 0;
+		memcpy(c->buf, ptr, arg);
+		gctx->tls_aad_len = arg;
+		{
+			unsigned int len = c->buf[arg - 2] << 8 |
+			    c->buf[arg - 1];
+
+			/* Correct length for explicit IV */
+			if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+				return 0;
+			len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+
+			/* If decrypting correct for tag too */
+			if (!c->encrypt) {
+				if (len < EVP_GCM_TLS_TAG_LEN)
+					return 0;
+				len -= EVP_GCM_TLS_TAG_LEN;
+			}
+			c->buf[arg - 2] = len >> 8;
+			c->buf[arg - 1] = len & 0xff;
+		}
+		/* Extra padding: tag appended to record */
+		return EVP_GCM_TLS_TAG_LEN;
+
+	case EVP_CTRL_COPY:
+	    {
+		EVP_CIPHER_CTX *out = ptr;
+		EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
+
+		if (gctx->gcm.key) {
+			if (gctx->gcm.key != &gctx->ks)
+				return 0;
+			gctx_out->gcm.key = &gctx_out->ks;
+		}
+
+		if (gctx->iv == c->iv) {
+			gctx_out->iv = out->iv;
+		} else {
+			if ((gctx_out->iv = calloc(1, gctx->ivlen)) == NULL)
+				return 0;
+			memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
+		}
+		return 1;
+	    }
+
+	default:
+		return -1;
+
+	}
+}
+
+static ctr128_f
+aes_gcm_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
+    const unsigned char *key, size_t key_len)
+{
+#ifdef BSAES_CAPABLE
+	if (BSAES_CAPABLE) {
+		AES_set_encrypt_key(key, key_len * 8, aes_key);
+		CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+		return (ctr128_f)bsaes_ctr32_encrypt_blocks;
+	} else
+#endif
+#ifdef VPAES_CAPABLE
+	if (VPAES_CAPABLE) {
+		vpaes_set_encrypt_key(key, key_len * 8, aes_key);
+		CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt);
+		return NULL;
+	} else
+#endif
+		(void)0; /* terminate potentially open 'else' */
+
+	AES_set_encrypt_key(key, key_len * 8, aes_key);
+	CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt);
+#ifdef AES_CTR_ASM
+	return (ctr128_f)AES_ctr32_encrypt;
+#else
+	return NULL;
+#endif
+}
+
+static int
+aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+	if (key) {
+		gctx->ctr = aes_gcm_set_key(&gctx->ks, &gctx->gcm,
+		    key, ctx->key_len);
+
+		/* If we have an iv can set it directly, otherwise use
+		 * saved IV.
+		 */
+		if (iv == NULL && gctx->iv_set)
+			iv = gctx->iv;
+		if (iv) {
+			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+			gctx->iv_set = 1;
+		}
+		gctx->key_set = 1;
+	} else {
+		/* If key set use IV, otherwise copy */
+		if (gctx->key_set)
+			CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
+		else
+			memcpy(gctx->iv, iv, gctx->ivlen);
+		gctx->iv_set = 1;
+		gctx->iv_gen = 0;
+	}
+	return 1;
+}
+
+/* Handle TLS GCM packet format. This consists of the last portion of the IV
+ * followed by the payload and finally the tag. On encrypt generate IV,
+ * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
+ * and verify tag.
+ */
+
+static int
+aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
+	int rv = -1;
+
+	/* Encrypt/decrypt must be performed in place */
+	if (out != in ||
+	    len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
+		return -1;
+
+	/* Set IV from start of buffer or generate IV and write to start
+	 * of buffer.
+	 */
+	if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
+	    EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
+	    EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
+		goto err;
+
+	/* Use saved AAD */
+	if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
+		goto err;
+
+	/* Fix buffer and length to point to payload */
+	in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+	out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+	if (ctx->encrypt) {
+		/* Encrypt payload */
+		if (gctx->ctr) {
+			if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, in, out,
+			    len, gctx->ctr))
+				goto err;
+		} else {
+			if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
+				goto err;
+		}
+		out += len;
+
+		/* Finally write tag */
+		CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
+		rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+	} else {
+		/* Decrypt */
+		if (gctx->ctr) {
+			if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, in, out,
+			    len, gctx->ctr))
+				goto err;
+		} else {
+			if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
+				goto err;
+		}
+		/* Retrieve tag */
+		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN);
+
+		/* If tag mismatch wipe buffer */
+		if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) {
+			explicit_bzero(out, len);
+			goto err;
+		}
+		rv = len;
+	}
+
+err:
+	gctx->iv_set = 0;
+	gctx->tls_aad_len = -1;
+	return rv;
+}
+
+static int
+aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
+
+	/* If not set up, return error */
+	if (!gctx->key_set)
+		return -1;
+
+	if (gctx->tls_aad_len >= 0)
+		return aes_gcm_tls_cipher(ctx, out, in, len);
+
+	if (!gctx->iv_set)
+		return -1;
+
+	if (in) {
+		if (out == NULL) {
+			if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
+				return -1;
+		} else if (ctx->encrypt) {
+			if (gctx->ctr) {
+				if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
+				    in, out, len, gctx->ctr))
+					return -1;
+			} else {
+				if (CRYPTO_gcm128_encrypt(&gctx->gcm,
+				    in, out, len))
+					return -1;
+			}
+		} else {
+			if (gctx->ctr) {
+				if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
+				    in, out, len, gctx->ctr))
+					return -1;
+			} else {
+				if (CRYPTO_gcm128_decrypt(&gctx->gcm,
+				    in, out, len))
+					return -1;
+			}
+		}
+		return len;
+	} else {
+		if (!ctx->encrypt) {
+			if (gctx->taglen < 0)
+				return -1;
+			if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf,
+			    gctx->taglen) != 0)
+				return -1;
+			gctx->iv_set = 0;
+			return 0;
+		}
+		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
+		gctx->taglen = 16;
+
+		/* Don't reuse the IV */
+		gctx->iv_set = 0;
+		return 0;
+	}
+
+}
+
+#define CUSTOM_FLAGS \
+    ( EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | \
+      EVP_CIPH_FLAG_CUSTOM_IV_LENGTH | \
+      EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT | \
+      EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY )
+
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_gcm = {
+	.nid = NID_aes_128_gcm,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aesni_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_128_gcm = {
+	.nid = NID_aes_128_gcm,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aes_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_128_gcm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_gcm : &aes_128_gcm;
+#else
+	return &aes_128_gcm;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_gcm = {
+	.nid = NID_aes_192_gcm,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aesni_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_192_gcm = {
+	.nid = NID_aes_192_gcm,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aes_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_192_gcm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_gcm : &aes_192_gcm;
+#else
+	return &aes_192_gcm;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_gcm = {
+	.nid = NID_aes_256_gcm,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aesni_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_256_gcm = {
+	.nid = NID_aes_256_gcm,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 12,
+	.flags = EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS | EVP_CIPH_GCM_MODE,
+	.init = aes_gcm_init_key,
+	.do_cipher = aes_gcm_cipher,
+	.cleanup = aes_gcm_cleanup,
+	.ctx_size = sizeof(EVP_AES_GCM_CTX),
+	.ctrl = aes_gcm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_256_gcm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_gcm : &aes_256_gcm;
+#else
+	return &aes_256_gcm;
+#endif
+}
+
+static int
+aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	EVP_AES_XTS_CTX *xctx = c->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_INIT:
+		/*
+		 * key1 and key2 are used as an indicator both key and IV
+		 * are set
+		 */
+		xctx->xts.key1 = NULL;
+		xctx->xts.key2 = NULL;
+		return 1;
+
+	case EVP_CTRL_COPY:
+	    {
+		EVP_CIPHER_CTX *out = ptr;
+		EVP_AES_XTS_CTX *xctx_out = out->cipher_data;
+
+		if (xctx->xts.key1) {
+			if (xctx->xts.key1 != &xctx->ks1)
+				return 0;
+			xctx_out->xts.key1 = &xctx_out->ks1;
+		}
+		if (xctx->xts.key2) {
+			if (xctx->xts.key2 != &xctx->ks2)
+				return 0;
+			xctx_out->xts.key2 = &xctx_out->ks2;
+		}
+		return 1;
+	    }
+	}
+	return -1;
+}
+
+static int
+aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+
+	if (key) do {
+#ifdef AES_XTS_ASM
+		xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
+#else
+		xctx->stream = NULL;
+#endif
+		/* key_len is two AES keys */
+#ifdef BSAES_CAPABLE
+		if (BSAES_CAPABLE)
+			xctx->stream = enc ? bsaes_xts_encrypt :
+			    bsaes_xts_decrypt;
+		else
+#endif
+#ifdef VPAES_CAPABLE
+		if (VPAES_CAPABLE) {
+			if (enc) {
+				vpaes_set_encrypt_key(key, ctx->key_len * 4,
+				    &xctx->ks1);
+				xctx->xts.block1 = (block128_f)vpaes_encrypt;
+			} else {
+				vpaes_set_decrypt_key(key, ctx->key_len * 4,
+				    &xctx->ks1);
+				xctx->xts.block1 = (block128_f)vpaes_decrypt;
+			}
+
+			vpaes_set_encrypt_key(key + ctx->key_len / 2,
+			    ctx->key_len * 4, &xctx->ks2);
+			xctx->xts.block2 = (block128_f)vpaes_encrypt;
+
+			xctx->xts.key1 = &xctx->ks1;
+			break;
+		} else
+#endif
+			(void)0;	/* terminate potentially open 'else' */
+
+		if (enc) {
+			AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+			xctx->xts.block1 = (block128_f)AES_encrypt;
+		} else {
+			AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+			xctx->xts.block1 = (block128_f)AES_decrypt;
+		}
+
+		AES_set_encrypt_key(key + ctx->key_len / 2,
+		    ctx->key_len * 4, &xctx->ks2);
+		xctx->xts.block2 = (block128_f)AES_encrypt;
+
+		xctx->xts.key1 = &xctx->ks1;
+	} while (0);
+
+	if (iv) {
+		xctx->xts.key2 = &xctx->ks2;
+		memcpy(ctx->iv, iv, 16);
+	}
+
+	return 1;
+}
+
+static int
+aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_XTS_CTX *xctx = ctx->cipher_data;
+
+	if (!xctx->xts.key1 || !xctx->xts.key2)
+		return 0;
+	if (!out || !in || len < AES_BLOCK_SIZE)
+		return 0;
+
+	if (xctx->stream)
+		(*xctx->stream)(in, out, len, xctx->xts.key1, xctx->xts.key2,
+		    ctx->iv);
+	else if (CRYPTO_xts128_encrypt(&xctx->xts, ctx->iv, in, out, len,
+	    ctx->encrypt))
+		return 0;
+	return 1;
+}
+
+#define XTS_FLAGS \
+    ( EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV | \
+      EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY )
+
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_xts = {
+	.nid = NID_aes_128_xts,
+	.block_size = 1,
+	.key_len = 2 * 16,
+	.iv_len = 16,
+	.flags = XTS_FLAGS | EVP_CIPH_XTS_MODE,
+	.init = aesni_xts_init_key,
+	.do_cipher = aes_xts_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_XTS_CTX),
+	.ctrl = aes_xts_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_128_xts = {
+	.nid = NID_aes_128_xts,
+	.block_size = 1,
+	.key_len = 2 * 16,
+	.iv_len = 16,
+	.flags = XTS_FLAGS | EVP_CIPH_XTS_MODE,
+	.init = aes_xts_init_key,
+	.do_cipher = aes_xts_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_XTS_CTX),
+	.ctrl = aes_xts_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_128_xts(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_xts : &aes_128_xts;
+#else
+	return &aes_128_xts;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_xts = {
+	.nid = NID_aes_256_xts,
+	.block_size = 1,
+	.key_len = 2 * 32,
+	.iv_len = 16,
+	.flags = XTS_FLAGS | EVP_CIPH_XTS_MODE,
+	.init = aesni_xts_init_key,
+	.do_cipher = aes_xts_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_XTS_CTX),
+	.ctrl = aes_xts_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_256_xts = {
+	.nid = NID_aes_256_xts,
+	.block_size = 1,
+	.key_len = 2 * 32,
+	.iv_len = 16,
+	.flags = XTS_FLAGS | EVP_CIPH_XTS_MODE,
+	.init = aes_xts_init_key,
+	.do_cipher = aes_xts_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_XTS_CTX),
+	.ctrl = aes_xts_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_256_xts(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_xts : &aes_256_xts;
+#else
+	return &aes_256_xts;
+#endif
+}
+
+static int
+aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	EVP_AES_CCM_CTX *cctx = c->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_INIT:
+		cctx->key_set = 0;
+		cctx->iv_set = 0;
+		cctx->L = 8;
+		cctx->M = 12;
+		cctx->tag_set = 0;
+		cctx->len_set = 0;
+		return 1;
+
+	case EVP_CTRL_AEAD_GET_IVLEN:
+		*(int *)ptr = 15 - cctx->L;
+		return 1;
+
+	case EVP_CTRL_AEAD_SET_IVLEN:
+		arg = 15 - arg;
+
+	case EVP_CTRL_CCM_SET_L:
+		if (arg < 2 || arg > 8)
+			return 0;
+		cctx->L = arg;
+		return 1;
+
+	case EVP_CTRL_CCM_SET_TAG:
+		if ((arg & 1) || arg < 4 || arg > 16)
+			return 0;
+		if ((c->encrypt && ptr) || (!c->encrypt && !ptr))
+			return 0;
+		if (ptr) {
+			cctx->tag_set = 1;
+			memcpy(c->buf, ptr, arg);
+		}
+		cctx->M = arg;
+		return 1;
+
+	case EVP_CTRL_CCM_GET_TAG:
+		if (!c->encrypt || !cctx->tag_set)
+			return 0;
+		if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
+			return 0;
+		cctx->tag_set = 0;
+		cctx->iv_set = 0;
+		cctx->len_set = 0;
+		return 1;
+
+	case EVP_CTRL_COPY:
+	    {
+		EVP_CIPHER_CTX *out = ptr;
+		EVP_AES_CCM_CTX *cctx_out = out->cipher_data;
+
+		if (cctx->ccm.key) {
+			if (cctx->ccm.key != &cctx->ks)
+				return 0;
+			cctx_out->ccm.key = &cctx_out->ks;
+		}
+		return 1;
+	    }
+
+	default:
+		return -1;
+	}
+}
+
+static int
+aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
+
+	if (!iv && !key)
+		return 1;
+	if (key) do {
+#ifdef VPAES_CAPABLE
+		if (VPAES_CAPABLE) {
+			vpaes_set_encrypt_key(key, ctx->key_len*8, &cctx->ks);
+			CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
+			    &cctx->ks, (block128_f)vpaes_encrypt);
+			cctx->str = NULL;
+			cctx->key_set = 1;
+			break;
+		}
+#endif
+		AES_set_encrypt_key(key, ctx->key_len * 8, &cctx->ks);
+		CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
+		    &cctx->ks, (block128_f)AES_encrypt);
+		cctx->str = NULL;
+		cctx->key_set = 1;
+	} while (0);
+	if (iv) {
+		memcpy(ctx->iv, iv, 15 - cctx->L);
+		cctx->iv_set = 1;
+	}
+	return 1;
+}
+
+static int
+aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
+	CCM128_CONTEXT *ccm = &cctx->ccm;
+
+	/* If not set up, return error */
+	if (!cctx->iv_set && !cctx->key_set)
+		return -1;
+	if (!ctx->encrypt && !cctx->tag_set)
+		return -1;
+
+	if (!out) {
+		if (!in) {
+			if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,
+			    len))
+				return -1;
+			cctx->len_set = 1;
+			return len;
+		}
+		/* If have AAD need message length */
+		if (!cctx->len_set && len)
+			return -1;
+		CRYPTO_ccm128_aad(ccm, in, len);
+		return len;
+	}
+	/* EVP_*Final() doesn't return any data */
+	if (!in)
+		return 0;
+	/* If not set length yet do it */
+	if (!cctx->len_set) {
+		if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
+			return -1;
+		cctx->len_set = 1;
+	}
+	if (ctx->encrypt) {
+		if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
+		    cctx->str) : CRYPTO_ccm128_encrypt(ccm, in, out, len))
+			return -1;
+		cctx->tag_set = 1;
+		return len;
+	} else {
+		int rv = -1;
+		if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
+		    cctx->str) : !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
+			unsigned char tag[16];
+			if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
+				if (!memcmp(tag, ctx->buf, cctx->M))
+					rv = len;
+			}
+		}
+		if (rv == -1)
+			explicit_bzero(out, len);
+		cctx->iv_set = 0;
+		cctx->tag_set = 0;
+		cctx->len_set = 0;
+		return rv;
+	}
+
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_128_ccm = {
+	.nid = NID_aes_128_ccm,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aesni_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_128_ccm = {
+	.nid = NID_aes_128_ccm,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aes_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_128_ccm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_128_ccm : &aes_128_ccm;
+#else
+	return &aes_128_ccm;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_192_ccm = {
+	.nid = NID_aes_192_ccm,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aesni_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_192_ccm = {
+	.nid = NID_aes_192_ccm,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aes_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_192_ccm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_192_ccm : &aes_192_ccm;
+#else
+	return &aes_192_ccm;
+#endif
+}
+
+#ifdef AESNI_CAPABLE
+static const EVP_CIPHER aesni_256_ccm = {
+	.nid = NID_aes_256_ccm,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aesni_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+#endif
+
+static const EVP_CIPHER aes_256_ccm = {
+	.nid = NID_aes_256_ccm,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 12,
+	.flags = CUSTOM_FLAGS | EVP_CIPH_CCM_MODE,
+	.init = aes_ccm_init_key,
+	.do_cipher = aes_ccm_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_CCM_CTX),
+	.ctrl = aes_ccm_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_aes_256_ccm(void)
+{
+#ifdef AESNI_CAPABLE
+	return AESNI_CAPABLE ? &aesni_256_ccm : &aes_256_ccm;
+#else
+	return &aes_256_ccm;
+#endif
+}
+
+#define EVP_AEAD_AES_GCM_TAG_LEN 16
+
+struct aead_aes_gcm_ctx {
+	union {
+		double align;
+		AES_KEY ks;
+	} ks;
+	GCM128_CONTEXT gcm;
+	ctr128_f ctr;
+	unsigned char tag_len;
+};
+
+static int
+aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const unsigned char *key, size_t key_len,
+    size_t tag_len)
+{
+	struct aead_aes_gcm_ctx *gcm_ctx;
+	const size_t key_bits = key_len * 8;
+
+	/* EVP_AEAD_CTX_init should catch this. */
+	if (key_bits != 128 && key_bits != 256) {
+		EVPerror(EVP_R_BAD_KEY_LENGTH);
+		return 0;
+	}
+
+	if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH)
+		tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
+
+	if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) {
+		EVPerror(EVP_R_TAG_TOO_LARGE);
+		return 0;
+	}
+
+	if ((gcm_ctx = calloc(1, sizeof(struct aead_aes_gcm_ctx))) == NULL)
+		return 0;
+
+#ifdef AESNI_CAPABLE
+	if (AESNI_CAPABLE) {
+		aesni_set_encrypt_key(key, key_bits, &gcm_ctx->ks.ks);
+		CRYPTO_gcm128_init(&gcm_ctx->gcm, &gcm_ctx->ks.ks,
+		    (block128_f)aesni_encrypt);
+		gcm_ctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
+	} else
+#endif
+	{
+		gcm_ctx->ctr = aes_gcm_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm,
+		    key, key_len);
+	}
+	gcm_ctx->tag_len = tag_len;
+	ctx->aead_state = gcm_ctx;
+
+	return 1;
+}
+
+static void
+aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx)
+{
+	struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
+
+	freezero(gcm_ctx, sizeof(*gcm_ctx));
+}
+
+static int
+aead_aes_gcm_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
+    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
+    const unsigned char *in, size_t in_len, const unsigned char *ad,
+    size_t ad_len)
+{
+	const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
+	GCM128_CONTEXT gcm;
+	size_t bulk = 0;
+
+	if (max_out_len < in_len + gcm_ctx->tag_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+
+	if (nonce_len == 0) {
+		EVPerror(EVP_R_INVALID_IV_LENGTH);
+		return 0;
+	}
+	CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);
+
+	if (ad_len > 0 && CRYPTO_gcm128_aad(&gcm, ad, ad_len))
+		return 0;
+
+	if (gcm_ctx->ctr) {
+		if (CRYPTO_gcm128_encrypt_ctr32(&gcm, in + bulk, out + bulk,
+		    in_len - bulk, gcm_ctx->ctr))
+			return 0;
+	} else {
+		if (CRYPTO_gcm128_encrypt(&gcm, in + bulk, out + bulk,
+		    in_len - bulk))
+			return 0;
+	}
+
+	CRYPTO_gcm128_tag(&gcm, out + in_len, gcm_ctx->tag_len);
+	*out_len = in_len + gcm_ctx->tag_len;
+
+	return 1;
+}
+
+static int
+aead_aes_gcm_open(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
+    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
+    const unsigned char *in, size_t in_len, const unsigned char *ad,
+    size_t ad_len)
+{
+	const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
+	unsigned char tag[EVP_AEAD_AES_GCM_TAG_LEN];
+	GCM128_CONTEXT gcm;
+	size_t plaintext_len;
+	size_t bulk = 0;
+
+	if (in_len < gcm_ctx->tag_len) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	plaintext_len = in_len - gcm_ctx->tag_len;
+
+	if (max_out_len < plaintext_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+
+	if (nonce_len == 0) {
+		EVPerror(EVP_R_INVALID_IV_LENGTH);
+		return 0;
+	}
+	CRYPTO_gcm128_setiv(&gcm, nonce, nonce_len);
+
+	if (CRYPTO_gcm128_aad(&gcm, ad, ad_len))
+		return 0;
+
+	if (gcm_ctx->ctr) {
+		if (CRYPTO_gcm128_decrypt_ctr32(&gcm, in + bulk, out + bulk,
+		    in_len - bulk - gcm_ctx->tag_len, gcm_ctx->ctr))
+			return 0;
+	} else {
+		if (CRYPTO_gcm128_decrypt(&gcm, in + bulk, out + bulk,
+		    in_len - bulk - gcm_ctx->tag_len))
+			return 0;
+	}
+
+	CRYPTO_gcm128_tag(&gcm, tag, gcm_ctx->tag_len);
+	if (timingsafe_memcmp(tag, in + plaintext_len, gcm_ctx->tag_len) != 0) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	*out_len = plaintext_len;
+
+	return 1;
+}
+
+static const EVP_AEAD aead_aes_128_gcm = {
+	.key_len = 16,
+	.nonce_len = 12,
+	.overhead = EVP_AEAD_AES_GCM_TAG_LEN,
+	.max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN,
+
+	.init = aead_aes_gcm_init,
+	.cleanup = aead_aes_gcm_cleanup,
+	.seal = aead_aes_gcm_seal,
+	.open = aead_aes_gcm_open,
+};
+
+static const EVP_AEAD aead_aes_256_gcm = {
+	.key_len = 32,
+	.nonce_len = 12,
+	.overhead = EVP_AEAD_AES_GCM_TAG_LEN,
+	.max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN,
+
+	.init = aead_aes_gcm_init,
+	.cleanup = aead_aes_gcm_cleanup,
+	.seal = aead_aes_gcm_seal,
+	.open = aead_aes_gcm_open,
+};
+
+const EVP_AEAD *
+EVP_aead_aes_128_gcm(void)
+{
+	return &aead_aes_128_gcm;
+}
+
+const EVP_AEAD *
+EVP_aead_aes_256_gcm(void)
+{
+	return &aead_aes_256_gcm;
+}
+
+typedef struct {
+	union {
+		double align;
+		AES_KEY ks;
+	} ks;
+	unsigned char *iv;
+} EVP_AES_WRAP_CTX;
+
+static int
+aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_WRAP_CTX *wctx = (EVP_AES_WRAP_CTX *)ctx->cipher_data;
+
+	if (iv == NULL && key == NULL)
+		return 1;
+
+	if (key != NULL) {
+		if (ctx->encrypt)
+			AES_set_encrypt_key(key, 8 * ctx->key_len,
+			    &wctx->ks.ks);
+		else
+			AES_set_decrypt_key(key, 8 * ctx->key_len,
+			    &wctx->ks.ks);
+
+		if (iv == NULL)
+			wctx->iv = NULL;
+	}
+
+	if (iv != NULL) {
+		memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+		wctx->iv = ctx->iv;
+	}
+
+	return 1;
+}
+
+static int
+aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inlen)
+{
+	EVP_AES_WRAP_CTX *wctx = ctx->cipher_data;
+	int ret;
+
+	if (in == NULL)
+		return 0;
+
+	if (inlen % 8 != 0)
+		return -1;
+	if (ctx->encrypt && inlen < 8)
+		return -1;
+	if (!ctx->encrypt && inlen < 16)
+		return -1;
+	if (inlen > INT_MAX)
+		return -1;
+
+	if (out == NULL) {
+		if (ctx->encrypt)
+			return inlen + 8;
+		else
+			return inlen - 8;
+	}
+
+	if (ctx->encrypt)
+		ret = AES_wrap_key(&wctx->ks.ks, wctx->iv, out, in,
+		    (unsigned int)inlen);
+	else
+		ret = AES_unwrap_key(&wctx->ks.ks, wctx->iv, out, in,
+		    (unsigned int)inlen);
+
+	return ret != 0 ? ret : -1;
+}
+
+static int
+aes_wrap_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	EVP_AES_WRAP_CTX *wctx = c->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_COPY:
+	    {
+		EVP_CIPHER_CTX *out = ptr;
+		EVP_AES_WRAP_CTX *wctx_out = out->cipher_data;
+
+		if (wctx->iv != NULL) {
+			if (c->iv != wctx->iv)
+				return 0;
+
+			wctx_out->iv = out->iv;
+		}
+
+		return 1;
+	    }
+	}
+
+	return -1;
+}
+
+#define WRAP_FLAGS \
+    ( EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER | \
+      EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1 | \
+      EVP_CIPH_CUSTOM_COPY )
+
+static const EVP_CIPHER aes_128_wrap = {
+	.nid = NID_id_aes128_wrap,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = WRAP_FLAGS,
+	.init = aes_wrap_init_key,
+	.do_cipher = aes_wrap_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_WRAP_CTX),
+	.set_asn1_parameters = NULL,
+	.get_asn1_parameters = NULL,
+	.ctrl = aes_wrap_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_aes_128_wrap(void)
+{
+	return &aes_128_wrap;
+}
+
+static const EVP_CIPHER aes_192_wrap = {
+	.nid = NID_id_aes192_wrap,
+	.block_size = 8,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = WRAP_FLAGS,
+	.init = aes_wrap_init_key,
+	.do_cipher = aes_wrap_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_WRAP_CTX),
+	.set_asn1_parameters = NULL,
+	.get_asn1_parameters = NULL,
+	.ctrl = aes_wrap_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_aes_192_wrap(void)
+{
+	return &aes_192_wrap;
+}
+
+static const EVP_CIPHER aes_256_wrap = {
+	.nid = NID_id_aes256_wrap,
+	.block_size = 8,
+	.key_len = 32,
+	.iv_len = 8,
+	.flags = WRAP_FLAGS,
+	.init = aes_wrap_init_key,
+	.do_cipher = aes_wrap_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_AES_WRAP_CTX),
+	.set_asn1_parameters = NULL,
+	.get_asn1_parameters = NULL,
+	.ctrl = aes_wrap_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_aes_256_wrap(void)
+{
+	return &aes_256_wrap;
+}
+
+#endif
diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c
new file mode 100644
index 0000000..09a73da
--- /dev/null
+++ b/crypto/evp/e_aes_cbc_hmac_sha1.c
@@ -0,0 +1,604 @@
+/* $OpenBSD: e_aes_cbc_hmac_sha1.c,v 1.19 2023/07/07 19:37:53 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2011-2013 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+
+#include 
+
+#if !defined(OPENSSL_NO_AES) && !defined(OPENSSL_NO_SHA1)
+
+#include 
+#include 
+#include 
+#include 
+
+#include "constant_time.h"
+#include "evp_local.h"
+
+#define TLS1_1_VERSION 0x0302
+
+typedef struct {
+	AES_KEY		ks;
+	SHA_CTX		head, tail, md;
+	size_t		payload_length;	/* AAD length in decrypt case */
+	union {
+		unsigned int	tls_ver;
+		unsigned char	tls_aad[16];	/* 13 used */
+	} aux;
+} EVP_AES_HMAC_SHA1;
+
+#define NO_PAYLOAD_LENGTH	((size_t)-1)
+
+#if	defined(AES_ASM) &&	( \
+	defined(__x86_64)	|| defined(__x86_64__)	|| \
+	defined(_M_AMD64)	|| defined(_M_X64)	|| \
+	defined(__INTEL__)	)
+
+#include "x86_arch.h"
+
+#if defined(__GNUC__) && __GNUC__>=2
+# define BSWAP(x) ({ unsigned int r=(x); asm ("bswapl %0":"=r"(r):"0"(r)); r; })
+#endif
+
+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_cbc_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const AES_KEY *key, unsigned char *ivec, int enc);
+
+void aesni_cbc_sha1_enc (const void *inp, void *out, size_t blocks,
+    const AES_KEY *key, unsigned char iv[16], SHA_CTX *ctx, const void *in0);
+
+#define data(ctx) ((EVP_AES_HMAC_SHA1 *)(ctx)->cipher_data)
+
+static int
+aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *inkey,
+    const unsigned char *iv, int enc)
+{
+	EVP_AES_HMAC_SHA1 *key = data(ctx);
+	int ret;
+
+	if (enc)
+		ret = aesni_set_encrypt_key(inkey, ctx->key_len * 8, &key->ks);
+	else
+		ret = aesni_set_decrypt_key(inkey, ctx->key_len * 8, &key->ks);
+
+	SHA1_Init(&key->head);	/* handy when benchmarking */
+	key->tail = key->head;
+	key->md = key->head;
+
+	key->payload_length = NO_PAYLOAD_LENGTH;
+
+	return ret < 0 ? 0 : 1;
+}
+
+#define	STITCHED_CALL
+
+#if !defined(STITCHED_CALL)
+#define	aes_off 0
+#endif
+
+void sha1_block_data_order (void *c, const void *p, size_t len);
+
+static void
+sha1_update(SHA_CTX *c, const void *data, size_t len)
+{
+	const unsigned char *ptr = data;
+	size_t res;
+
+	if ((res = c->num)) {
+		res = SHA_CBLOCK - res;
+		if (len < res)
+			res = len;
+		SHA1_Update(c, ptr, res);
+		ptr += res;
+		len -= res;
+	}
+
+	res = len % SHA_CBLOCK;
+	len -= res;
+
+	if (len) {
+		sha1_block_data_order(c, ptr, len / SHA_CBLOCK);
+
+		ptr += len;
+		c->Nh += len >> 29;
+		c->Nl += len <<= 3;
+		if (c->Nl < (unsigned int)len)
+			c->Nh++;
+	}
+
+	if (res)
+		SHA1_Update(c, ptr, res);
+}
+
+#ifdef SHA1_Update
+#undef SHA1_Update
+#endif
+#define SHA1_Update sha1_update
+
+static int
+aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_AES_HMAC_SHA1 *key = data(ctx);
+	unsigned int l;
+	size_t plen = key->payload_length,
+	    iv = 0,		/* explicit IV in TLS 1.1 and later */
+	    sha_off = 0;
+#if defined(STITCHED_CALL)
+	size_t aes_off = 0, blocks;
+
+	sha_off = SHA_CBLOCK - key->md.num;
+#endif
+
+	key->payload_length = NO_PAYLOAD_LENGTH;
+
+	if (len % AES_BLOCK_SIZE)
+		return 0;
+
+	if (ctx->encrypt) {
+		if (plen == NO_PAYLOAD_LENGTH)
+			plen = len;
+		else if (len != ((plen + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE) &
+		    -AES_BLOCK_SIZE))
+			return 0;
+		else if (key->aux.tls_ver >= TLS1_1_VERSION)
+			iv = AES_BLOCK_SIZE;
+
+#if defined(STITCHED_CALL)
+		if (plen > (sha_off + iv) &&
+		    (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) {
+			SHA1_Update(&key->md, in + iv, sha_off);
+
+			aesni_cbc_sha1_enc(in, out, blocks, &key->ks,
+			    ctx->iv, &key->md, in + iv + sha_off);
+			blocks *= SHA_CBLOCK;
+			aes_off += blocks;
+			sha_off += blocks;
+			key->md.Nh += blocks >> 29;
+			key->md.Nl += blocks <<= 3;
+			if (key->md.Nl < (unsigned int)blocks)
+				key->md.Nh++;
+		} else {
+			sha_off = 0;
+		}
+#endif
+		sha_off += iv;
+		SHA1_Update(&key->md, in + sha_off, plen - sha_off);
+
+		if (plen != len) {	/* "TLS" mode of operation */
+			if (in != out)
+				memcpy(out + aes_off, in + aes_off,
+				    plen - aes_off);
+
+			/* calculate HMAC and append it to payload */
+			SHA1_Final(out + plen, &key->md);
+			key->md = key->tail;
+			SHA1_Update(&key->md, out + plen, SHA_DIGEST_LENGTH);
+			SHA1_Final(out + plen, &key->md);
+
+			/* pad the payload|hmac */
+			plen += SHA_DIGEST_LENGTH;
+			for (l = len - plen - 1; plen < len; plen++)
+				out[plen] = l;
+
+			/* encrypt HMAC|padding at once */
+			aesni_cbc_encrypt(out + aes_off, out + aes_off,
+			    len - aes_off, &key->ks, ctx->iv, 1);
+		} else {
+			aesni_cbc_encrypt(in + aes_off, out + aes_off,
+			    len - aes_off, &key->ks, ctx->iv, 1);
+		}
+	} else {
+		union {
+			unsigned int u[SHA_DIGEST_LENGTH/sizeof(unsigned int)];
+			unsigned char c[32 + SHA_DIGEST_LENGTH];
+		} mac, *pmac;
+
+		/* arrange cache line alignment */
+		pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32));
+
+		/* decrypt HMAC|padding at once */
+		aesni_cbc_encrypt(in, out, len, &key->ks, ctx->iv, 0);
+
+		if (plen == 0 || plen == NO_PAYLOAD_LENGTH) {
+			SHA1_Update(&key->md, out, len);
+		} else if (plen < 4) {
+			return 0;
+		} else {	/* "TLS" mode of operation */
+			size_t inp_len, mask, j, i;
+			unsigned int res, maxpad, pad, bitlen;
+			int ret = 1;
+			union {
+				unsigned int u[SHA_LBLOCK];
+				unsigned char c[SHA_CBLOCK];
+			}
+			*data = (void *)key->md.data;
+
+			if ((key->aux.tls_aad[plen - 4] << 8 |
+			    key->aux.tls_aad[plen - 3]) >= TLS1_1_VERSION)
+				iv = AES_BLOCK_SIZE;
+
+			if (len < (iv + SHA_DIGEST_LENGTH + 1))
+				return 0;
+
+			/* omit explicit iv */
+			out += iv;
+			len -= iv;
+
+			/* figure out payload length */
+			pad = out[len - 1];
+			maxpad = len - (SHA_DIGEST_LENGTH + 1);
+			maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8);
+			maxpad &= 255;
+
+			ret &= constant_time_ge(maxpad, pad);
+
+			inp_len = len - (SHA_DIGEST_LENGTH + pad + 1);
+			mask = (0 - ((inp_len - len) >>
+			    (sizeof(inp_len) * 8 - 1)));
+			inp_len &= mask;
+			ret &= (int)mask;
+
+			key->aux.tls_aad[plen - 2] = inp_len >> 8;
+			key->aux.tls_aad[plen - 1] = inp_len;
+
+			/* calculate HMAC */
+			key->md = key->head;
+			SHA1_Update(&key->md, key->aux.tls_aad, plen);
+
+#if 1
+			len -= SHA_DIGEST_LENGTH;		/* amend mac */
+			if (len >= (256 + SHA_CBLOCK)) {
+				j = (len - (256 + SHA_CBLOCK)) &
+				    (0 - SHA_CBLOCK);
+				j += SHA_CBLOCK - key->md.num;
+				SHA1_Update(&key->md, out, j);
+				out += j;
+				len -= j;
+				inp_len -= j;
+			}
+
+			/* but pretend as if we hashed padded payload */
+			bitlen = key->md.Nl + (inp_len << 3);	/* at most 18 bits */
+#ifdef BSWAP
+			bitlen = BSWAP(bitlen);
+#else
+			mac.c[0] = 0;
+			mac.c[1] = (unsigned char)(bitlen >> 16);
+			mac.c[2] = (unsigned char)(bitlen >> 8);
+			mac.c[3] = (unsigned char)bitlen;
+			bitlen = mac.u[0];
+#endif
+
+			pmac->u[0] = 0;
+			pmac->u[1] = 0;
+			pmac->u[2] = 0;
+			pmac->u[3] = 0;
+			pmac->u[4] = 0;
+
+			for (res = key->md.num, j = 0; j < len; j++) {
+				size_t c = out[j];
+				mask = (j - inp_len) >> (sizeof(j) * 8 - 8);
+				c &= mask;
+				c |= 0x80 & ~mask &
+				    ~((inp_len - j) >> (sizeof(j) * 8 - 8));
+				data->c[res++] = (unsigned char)c;
+
+				if (res != SHA_CBLOCK)
+					continue;
+
+				/* j is not incremented yet */
+				mask = 0 - ((inp_len + 7 - j) >>
+				    (sizeof(j) * 8 - 1));
+				data->u[SHA_LBLOCK - 1] |= bitlen&mask;
+				sha1_block_data_order(&key->md, data, 1);
+				mask &= 0 - ((j - inp_len - 72) >>
+				    (sizeof(j) * 8 - 1));
+				pmac->u[0] |= key->md.h0 & mask;
+				pmac->u[1] |= key->md.h1 & mask;
+				pmac->u[2] |= key->md.h2 & mask;
+				pmac->u[3] |= key->md.h3 & mask;
+				pmac->u[4] |= key->md.h4 & mask;
+				res = 0;
+			}
+
+			for (i = res; i < SHA_CBLOCK; i++, j++)
+				data->c[i] = 0;
+
+			if (res > SHA_CBLOCK - 8) {
+				mask = 0 - ((inp_len + 8 - j) >>
+				    (sizeof(j) * 8 - 1));
+				data->u[SHA_LBLOCK - 1] |= bitlen & mask;
+				sha1_block_data_order(&key->md, data, 1);
+				mask &= 0 - ((j - inp_len - 73) >>
+				    (sizeof(j) * 8 - 1));
+				pmac->u[0] |= key->md.h0 & mask;
+				pmac->u[1] |= key->md.h1 & mask;
+				pmac->u[2] |= key->md.h2 & mask;
+				pmac->u[3] |= key->md.h3 & mask;
+				pmac->u[4] |= key->md.h4 & mask;
+
+				memset(data, 0, SHA_CBLOCK);
+				j += 64;
+			}
+			data->u[SHA_LBLOCK - 1] = bitlen;
+			sha1_block_data_order(&key->md, data, 1);
+			mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1));
+			pmac->u[0] |= key->md.h0 & mask;
+			pmac->u[1] |= key->md.h1 & mask;
+			pmac->u[2] |= key->md.h2 & mask;
+			pmac->u[3] |= key->md.h3 & mask;
+			pmac->u[4] |= key->md.h4 & mask;
+
+#ifdef BSWAP
+			pmac->u[0] = BSWAP(pmac->u[0]);
+			pmac->u[1] = BSWAP(pmac->u[1]);
+			pmac->u[2] = BSWAP(pmac->u[2]);
+			pmac->u[3] = BSWAP(pmac->u[3]);
+			pmac->u[4] = BSWAP(pmac->u[4]);
+#else
+			for (i = 0; i < 5; i++) {
+				res = pmac->u[i];
+				pmac->c[4 * i + 0] = (unsigned char)(res >> 24);
+				pmac->c[4 * i + 1] = (unsigned char)(res >> 16);
+				pmac->c[4 * i + 2] = (unsigned char)(res >> 8);
+				pmac->c[4 * i + 3] = (unsigned char)res;
+			}
+#endif
+			len += SHA_DIGEST_LENGTH;
+#else
+			SHA1_Update(&key->md, out, inp_len);
+			res = key->md.num;
+			SHA1_Final(pmac->c, &key->md);
+
+			{
+				unsigned int inp_blocks, pad_blocks;
+
+				/* but pretend as if we hashed padded payload */
+				inp_blocks = 1 + ((SHA_CBLOCK - 9 - res) >>
+				    (sizeof(res) * 8 - 1));
+				res += (unsigned int)(len - inp_len);
+				pad_blocks = res / SHA_CBLOCK;
+				res %= SHA_CBLOCK;
+				pad_blocks += 1 + ((SHA_CBLOCK - 9 - res) >>
+				    (sizeof(res) * 8 - 1));
+				for (; inp_blocks < pad_blocks; inp_blocks++)
+					sha1_block_data_order(&key->md,
+					    data, 1);
+			}
+#endif
+			key->md = key->tail;
+			SHA1_Update(&key->md, pmac->c, SHA_DIGEST_LENGTH);
+			SHA1_Final(pmac->c, &key->md);
+
+			/* verify HMAC */
+			out += inp_len;
+			len -= inp_len;
+#if 1
+			{
+				unsigned char *p =
+				    out + len - 1 - maxpad - SHA_DIGEST_LENGTH;
+				size_t off = out - p;
+				unsigned int c, cmask;
+
+				maxpad += SHA_DIGEST_LENGTH;
+				for (res = 0, i = 0, j = 0; j < maxpad; j++) {
+					c = p[j];
+					cmask = ((int)(j - off -
+					    SHA_DIGEST_LENGTH)) >>
+					    (sizeof(int) * 8 - 1);
+					res |= (c ^ pad) & ~cmask;	/* ... and padding */
+					cmask &= ((int)(off - 1 - j)) >>
+					    (sizeof(int) * 8 - 1);
+					res |= (c ^ pmac->c[i]) & cmask;
+					i += 1 & cmask;
+				}
+				maxpad -= SHA_DIGEST_LENGTH;
+
+				res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+				ret &= (int)~res;
+			}
+#else
+			for (res = 0, i = 0; i < SHA_DIGEST_LENGTH; i++)
+				res |= out[i] ^ pmac->c[i];
+			res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1));
+			ret &= (int)~res;
+
+			/* verify padding */
+			pad = (pad & ~res) | (maxpad & res);
+			out = out + len - 1 - pad;
+			for (res = 0, i = 0; i < pad; i++)
+				res |= out[i] ^ pad;
+
+			res = (0 - res) >> (sizeof(res) * 8 - 1);
+			ret &= (int)~res;
+#endif
+			return ret;
+		}
+	}
+
+	return 1;
+}
+
+static int
+aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+	EVP_AES_HMAC_SHA1 *key = data(ctx);
+
+	switch (type) {
+	case EVP_CTRL_AEAD_SET_MAC_KEY:
+		{
+			unsigned int  i;
+			unsigned char hmac_key[64];
+
+			memset(hmac_key, 0, sizeof(hmac_key));
+
+			if (arg > (int)sizeof(hmac_key)) {
+				SHA1_Init(&key->head);
+				SHA1_Update(&key->head, ptr, arg);
+				SHA1_Final(hmac_key, &key->head);
+			} else {
+				memcpy(hmac_key, ptr, arg);
+			}
+
+			for (i = 0; i < sizeof(hmac_key); i++)
+				hmac_key[i] ^= 0x36;		/* ipad */
+			SHA1_Init(&key->head);
+			SHA1_Update(&key->head, hmac_key, sizeof(hmac_key));
+
+			for (i = 0; i < sizeof(hmac_key); i++)
+				hmac_key[i] ^= 0x36 ^ 0x5c;	/* opad */
+			SHA1_Init(&key->tail);
+			SHA1_Update(&key->tail, hmac_key, sizeof(hmac_key));
+
+			explicit_bzero(hmac_key, sizeof(hmac_key));
+
+			return 1;
+		}
+	case EVP_CTRL_AEAD_TLS1_AAD:
+		{
+			unsigned char *p = ptr;
+			unsigned int len;
+
+			/* RFC 5246, 6.2.3.3: additional data has length 13 */
+			if (arg != 13)
+				return -1;
+
+			len = p[arg - 2] << 8 | p[arg - 1];
+
+			if (ctx->encrypt) {
+				key->payload_length = len;
+				if ((key->aux.tls_ver = p[arg - 4] << 8 |
+				    p[arg - 3]) >= TLS1_1_VERSION) {
+					len -= AES_BLOCK_SIZE;
+					p[arg - 2] = len >> 8;
+					p[arg - 1] = len;
+				}
+				key->md = key->head;
+				SHA1_Update(&key->md, p, arg);
+
+				return (int)(((len + SHA_DIGEST_LENGTH +
+				    AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) - len);
+			} else {
+				memcpy(key->aux.tls_aad, ptr, arg);
+				key->payload_length = arg;
+
+				return SHA_DIGEST_LENGTH;
+			}
+		}
+	default:
+		return -1;
+	}
+}
+
+static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = {
+#ifdef NID_aes_128_cbc_hmac_sha1
+	.nid = NID_aes_128_cbc_hmac_sha1,
+#else
+	.nid = NID_undef,
+#endif
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+	    EVP_CIPH_FLAG_AEAD_CIPHER,
+	.init = aesni_cbc_hmac_sha1_init_key,
+	.do_cipher = aesni_cbc_hmac_sha1_cipher,
+	.ctx_size = sizeof(EVP_AES_HMAC_SHA1),
+	.ctrl = aesni_cbc_hmac_sha1_ctrl
+};
+
+static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = {
+#ifdef NID_aes_256_cbc_hmac_sha1
+	.nid = NID_aes_256_cbc_hmac_sha1,
+#else
+	.nid = NID_undef,
+#endif
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 |
+	    EVP_CIPH_FLAG_AEAD_CIPHER,
+	.init = aesni_cbc_hmac_sha1_init_key,
+	.do_cipher = aesni_cbc_hmac_sha1_cipher,
+	.ctx_size = sizeof(EVP_AES_HMAC_SHA1),
+	.ctrl = aesni_cbc_hmac_sha1_ctrl
+};
+
+const EVP_CIPHER *
+EVP_aes_128_cbc_hmac_sha1(void)
+{
+	return (OPENSSL_cpu_caps() & CPUCAP_MASK_AESNI) ?
+	    &aesni_128_cbc_hmac_sha1_cipher : NULL;
+}
+
+const EVP_CIPHER *
+EVP_aes_256_cbc_hmac_sha1(void)
+{
+	return (OPENSSL_cpu_caps() & CPUCAP_MASK_AESNI) ?
+	    &aesni_256_cbc_hmac_sha1_cipher : NULL;
+}
+#else
+const EVP_CIPHER *
+EVP_aes_128_cbc_hmac_sha1(void)
+{
+	return NULL;
+}
+
+const EVP_CIPHER *
+EVP_aes_256_cbc_hmac_sha1(void)
+{
+	    return NULL;
+}
+#endif
+#endif
diff --git a/crypto/evp/e_bf.c b/crypto/evp/e_bf.c
new file mode 100644
index 0000000..9146a53
--- /dev/null
+++ b/crypto/evp/e_bf.c
@@ -0,0 +1,247 @@
+/* $OpenBSD: e_bf.c,v 1.17 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_BF
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+typedef struct {
+	BF_KEY ks;
+} EVP_BF_KEY;
+
+#define data(ctx)	((EVP_BF_KEY *)(ctx)->cipher_data)
+
+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);
+	return 1;
+}
+
+static int
+bf_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		BF_cbc_encrypt(in, out, (long)chunk, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		BF_cbc_encrypt(in, out, (long)inl, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+bf_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		BF_cfb64_encrypt(in, out, (long)chunk, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+bf_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		BF_ecb_encrypt(in + i, out + i, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+bf_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		BF_ofb64_encrypt(in, out, (long)chunk, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		BF_ofb64_encrypt(in, out, (long)inl, &((EVP_BF_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER bf_cbc = {
+	.nid = NID_bf_cbc,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CBC_MODE,
+	.init = bf_init_key,
+	.do_cipher = bf_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_BF_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_bf_cbc(void)
+{
+	return &bf_cbc;
+}
+
+static const EVP_CIPHER bf_cfb64 = {
+	.nid = NID_bf_cfb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CFB_MODE,
+	.init = bf_init_key,
+	.do_cipher = bf_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_BF_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_bf_cfb64(void)
+{
+	return &bf_cfb64;
+}
+
+static const EVP_CIPHER bf_ofb = {
+	.nid = NID_bf_ofb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_OFB_MODE,
+	.init = bf_init_key,
+	.do_cipher = bf_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_BF_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_bf_ofb(void)
+{
+	return &bf_ofb;
+}
+
+static const EVP_CIPHER bf_ecb = {
+	.nid = NID_bf_ecb,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ECB_MODE,
+	.init = bf_init_key,
+	.do_cipher = bf_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_BF_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_bf_ecb(void)
+{
+	return &bf_ecb;
+}
+#endif
diff --git a/crypto/evp/e_camellia.c b/crypto/evp/e_camellia.c
new file mode 100644
index 0000000..cec7649
--- /dev/null
+++ b/crypto/evp/e_camellia.c
@@ -0,0 +1,823 @@
+/* $OpenBSD: e_camellia.c,v 1.18 2023/07/07 19:37:53 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_CAMELLIA
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* Camellia subkey Structure */
+typedef struct {
+	CAMELLIA_KEY ks;
+} EVP_CAMELLIA_KEY;
+
+/* Attribute operation for Camellia */
+#define data(ctx)	((EVP_CAMELLIA_KEY *)(ctx)->cipher_data)
+
+static int
+camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	int ret;
+
+	ret = Camellia_set_key(key, ctx->key_len * 8, ctx->cipher_data);
+
+	if (ret < 0) {
+		EVPerror(EVP_R_CAMELLIA_KEY_SETUP_FAILED);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+camellia_128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_cbc_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_128_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb128_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+camellia_128_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		Camellia_ecb_encrypt(in + i, out + i, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_128_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_ofb128_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_128_cbc = {
+	.nid = NID_camellia_128_cbc,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CBC_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_cbc(void)
+{
+	return &camellia_128_cbc;
+}
+
+static const EVP_CIPHER camellia_128_cfb128 = {
+	.nid = NID_camellia_128_cfb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_cfb128_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_cfb128(void)
+{
+	return &camellia_128_cfb128;
+}
+
+static const EVP_CIPHER camellia_128_ofb = {
+	.nid = NID_camellia_128_ofb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_OFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_ofb(void)
+{
+	return &camellia_128_ofb;
+}
+
+static const EVP_CIPHER camellia_128_ecb = {
+	.nid = NID_camellia_128_ecb,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = 0 | EVP_CIPH_ECB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_ecb(void)
+{
+	return &camellia_128_ecb;
+}
+
+static int
+camellia_192_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_cbc_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_192_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb128_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+camellia_192_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		Camellia_ecb_encrypt(in + i, out + i, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_192_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_ofb128_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_192_cbc = {
+	.nid = NID_camellia_192_cbc,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CBC_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_cbc(void)
+{
+	return &camellia_192_cbc;
+}
+
+static const EVP_CIPHER camellia_192_cfb128 = {
+	.nid = NID_camellia_192_cfb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_cfb128_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_cfb128(void)
+{
+	return &camellia_192_cfb128;
+}
+
+static const EVP_CIPHER camellia_192_ofb = {
+	.nid = NID_camellia_192_ofb128,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_OFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_ofb(void)
+{
+	return &camellia_192_ofb;
+}
+
+static const EVP_CIPHER camellia_192_ecb = {
+	.nid = NID_camellia_192_ecb,
+	.block_size = 16,
+	.key_len = 24,
+	.iv_len = 0,
+	.flags = 0 | EVP_CIPH_ECB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_ecb(void)
+{
+	return &camellia_192_ecb;
+}
+
+static int
+camellia_256_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_cbc_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_256_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb128_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+camellia_256_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		Camellia_ecb_encrypt(in + i, out + i, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+camellia_256_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		Camellia_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Camellia_ofb128_encrypt(in, out, inl, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_256_cbc = {
+	.nid = NID_camellia_256_cbc,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CBC_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_cbc(void)
+{
+	return &camellia_256_cbc;
+}
+
+static const EVP_CIPHER camellia_256_cfb128 = {
+	.nid = NID_camellia_256_cfb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_cfb128_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_cfb128(void)
+{
+	return &camellia_256_cfb128;
+}
+
+static const EVP_CIPHER camellia_256_ofb = {
+	.nid = NID_camellia_256_ofb128,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_OFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_ofb(void)
+{
+	return &camellia_256_ofb;
+}
+
+static const EVP_CIPHER camellia_256_ecb = {
+	.nid = NID_camellia_256_ecb,
+	.block_size = 16,
+	.key_len = 32,
+	.iv_len = 0,
+	.flags = 0 | EVP_CIPH_ECB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_ecb(void)
+{
+	return &camellia_256_ecb;
+}
+
+static int
+camellia_128_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	chunk >>= 3;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb1_encrypt(in, out, ((1 == 1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ? chunk * 8 : chunk), &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_128_cfb1 = {
+	.nid = NID_camellia_128_cfb1,
+	.block_size = 1,
+	.key_len = 128/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_cfb1_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_cfb1(void)
+{
+	return &camellia_128_cfb1;
+}
+
+static int
+camellia_192_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	chunk >>= 3;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb1_encrypt(in, out, ((1 == 1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ? chunk * 8 : chunk), &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_192_cfb1 = {
+	.nid = NID_camellia_192_cfb1,
+	.block_size = 1,
+	.key_len = 192/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_cfb1_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_cfb1(void)
+{
+	return &camellia_192_cfb1;
+}
+
+static int
+camellia_256_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	chunk >>= 3;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb1_encrypt(in, out, ((1 == 1) && !(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) ? chunk * 8 : chunk), &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_256_cfb1 = {
+	.nid = NID_camellia_256_cfb1,
+	.block_size = 1,
+	.key_len = 256/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_cfb1_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_cfb1(void)
+{
+	return &camellia_256_cfb1;
+}
+
+
+static int
+camellia_128_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb8_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_128_cfb8 = {
+	.nid = NID_camellia_128_cfb8,
+	.block_size = 1,
+	.key_len = 128/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_128_cfb8_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_128_cfb8(void)
+{
+	return &camellia_128_cfb8;
+}
+
+static int
+camellia_192_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb8_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_192_cfb8 = {
+	.nid = NID_camellia_192_cfb8,
+	.block_size = 1,
+	.key_len = 192/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_192_cfb8_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_192_cfb8(void)
+{
+	return &camellia_192_cfb8;
+}
+
+static int
+camellia_256_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Camellia_cfb8_encrypt(in, out, chunk, &((EVP_CAMELLIA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER camellia_256_cfb8 = {
+	.nid = NID_camellia_256_cfb8,
+	.block_size = 1,
+	.key_len = 256/8,
+	.iv_len = 16,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = camellia_init_key,
+	.do_cipher = camellia_256_cfb8_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAMELLIA_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_camellia_256_cfb8(void)
+{
+	return &camellia_256_cfb8;
+}
+#endif
diff --git a/crypto/evp/e_cast.c b/crypto/evp/e_cast.c
new file mode 100644
index 0000000..a0e52df
--- /dev/null
+++ b/crypto/evp/e_cast.c
@@ -0,0 +1,247 @@
+/* $OpenBSD: e_cast.c,v 1.16 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_CAST
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+typedef struct {
+	CAST_KEY ks;
+} EVP_CAST_KEY;
+
+#define data(ctx)	((EVP_CAST_KEY *)(ctx)->cipher_data)
+
+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);
+	return 1;
+}
+
+static int
+cast5_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		CAST_cbc_encrypt(in, out, (long)chunk, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		CAST_cbc_encrypt(in, out, (long)inl, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+cast5_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		CAST_cfb64_encrypt(in, out, (long)chunk, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+cast5_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		CAST_ecb_encrypt(in + i, out + i, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+cast5_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		CAST_ofb64_encrypt(in, out, (long)chunk, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		CAST_ofb64_encrypt(in, out, (long)inl, &((EVP_CAST_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER cast5_cbc = {
+	.nid = NID_cast5_cbc,
+	.block_size = 8,
+	.key_len = CAST_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CBC_MODE,
+	.init = cast_init_key,
+	.do_cipher = cast5_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAST_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_cast5_cbc(void)
+{
+	return &cast5_cbc;
+}
+
+static const EVP_CIPHER cast5_cfb64 = {
+	.nid = NID_cast5_cfb64,
+	.block_size = 1,
+	.key_len = CAST_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CFB_MODE,
+	.init = cast_init_key,
+	.do_cipher = cast5_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAST_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_cast5_cfb64(void)
+{
+	return &cast5_cfb64;
+}
+
+static const EVP_CIPHER cast5_ofb = {
+	.nid = NID_cast5_ofb64,
+	.block_size = 1,
+	.key_len = CAST_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_OFB_MODE,
+	.init = cast_init_key,
+	.do_cipher = cast5_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAST_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_cast5_ofb(void)
+{
+	return &cast5_ofb;
+}
+
+static const EVP_CIPHER cast5_ecb = {
+	.nid = NID_cast5_ecb,
+	.block_size = 8,
+	.key_len = CAST_KEY_LENGTH,
+	.iv_len = 0,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ECB_MODE,
+	.init = cast_init_key,
+	.do_cipher = cast5_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_CAST_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_cast5_ecb(void)
+{
+	return &cast5_ecb;
+}
+#endif
diff --git a/crypto/evp/e_chacha.c b/crypto/evp/e_chacha.c
new file mode 100644
index 0000000..5cd03c7
--- /dev/null
+++ b/crypto/evp/e_chacha.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: e_chacha.c,v 1.13 2023/08/24 04:20:57 tb Exp $ */
+/*
+ * Copyright (c) 2014 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_CHACHA
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+chacha_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *openssl_iv, int enc)
+{
+	if (key != NULL)
+		ChaCha_set_key((ChaCha_ctx *)ctx->cipher_data, key,
+		    EVP_CIPHER_CTX_key_length(ctx) * 8);
+	if (openssl_iv != NULL) {
+		const unsigned char *iv = openssl_iv + 8;
+		const unsigned char *counter = openssl_iv;
+
+		ChaCha_set_iv((ChaCha_ctx *)ctx->cipher_data, iv, counter);
+	}
+	return 1;
+}
+
+static int
+chacha_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+    size_t len)
+{
+	ChaCha((ChaCha_ctx *)ctx->cipher_data, out, in, len);
+	return 1;
+}
+
+static const EVP_CIPHER chacha20_cipher = {
+	.nid = NID_chacha20,
+	.block_size = 1,
+	.key_len = 32,
+	/*
+	 * The 16-byte EVP IV is split into 4 little-endian 4-byte words
+	 *      evpiv[15:12]	evpiv[11:8]	evpiv[7:4]	evpiv[3:0]
+	 *	iv[1]		iv[0]		counter[1]	counter[0]
+	 * and passed as iv[] and counter[] to ChaCha_set_iv().
+	 */
+	.iv_len = 16,
+	.flags = EVP_CIPH_STREAM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
+	    EVP_CIPH_CUSTOM_IV,
+	.init = chacha_init,
+	.do_cipher = chacha_cipher,
+	.ctx_size = sizeof(ChaCha_ctx)
+};
+
+const EVP_CIPHER *
+EVP_chacha20(void)
+{
+	return (&chacha20_cipher);
+}
+
+#endif
diff --git a/crypto/evp/e_chacha20poly1305.c b/crypto/evp/e_chacha20poly1305.c
new file mode 100644
index 0000000..4a393c2
--- /dev/null
+++ b/crypto/evp/e_chacha20poly1305.c
@@ -0,0 +1,618 @@
+/* $OpenBSD: e_chacha20poly1305.c,v 1.32 2023/09/28 11:29:10 tb Exp $ */
+
+/*
+ * Copyright (c) 2022 Joel Sing 
+ * Copyright (c) 2015 Reyk Floter 
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bytestring.h"
+#include "evp_local.h"
+
+#define POLY1305_TAG_LEN 16
+
+#define CHACHA20_CONSTANT_LEN 4
+#define CHACHA20_IV_LEN 8
+#define CHACHA20_NONCE_LEN (CHACHA20_CONSTANT_LEN + CHACHA20_IV_LEN)
+#define XCHACHA20_NONCE_LEN 24
+
+struct aead_chacha20_poly1305_ctx {
+	unsigned char key[32];
+	unsigned char tag_len;
+};
+
+static int
+aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const unsigned char *key,
+    size_t key_len, size_t tag_len)
+{
+	struct aead_chacha20_poly1305_ctx *c20_ctx;
+
+	if (tag_len == 0)
+		tag_len = POLY1305_TAG_LEN;
+
+	if (tag_len > POLY1305_TAG_LEN) {
+		EVPerror(EVP_R_TOO_LARGE);
+		return 0;
+	}
+
+	/* Internal error - EVP_AEAD_CTX_init should catch this. */
+	if (key_len != sizeof(c20_ctx->key))
+		return 0;
+
+	c20_ctx = malloc(sizeof(struct aead_chacha20_poly1305_ctx));
+	if (c20_ctx == NULL)
+		return 0;
+
+	memcpy(&c20_ctx->key[0], key, key_len);
+	c20_ctx->tag_len = tag_len;
+	ctx->aead_state = c20_ctx;
+
+	return 1;
+}
+
+static void
+aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx)
+{
+	struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+
+	freezero(c20_ctx, sizeof(*c20_ctx));
+}
+
+static void
+poly1305_update_with_length(poly1305_state *poly1305,
+    const unsigned char *data, size_t data_len)
+{
+	size_t j = data_len;
+	unsigned char length_bytes[8];
+	unsigned i;
+
+	for (i = 0; i < sizeof(length_bytes); i++) {
+		length_bytes[i] = j;
+		j >>= 8;
+	}
+
+	if (data != NULL)
+		CRYPTO_poly1305_update(poly1305, data, data_len);
+	CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
+}
+
+static void
+poly1305_pad16(poly1305_state *poly1305, size_t data_len)
+{
+	static const unsigned char zero_pad16[16];
+	size_t pad_len;
+
+	/* pad16() is defined in RFC 8439 2.8.1. */
+	if ((pad_len = data_len % 16) == 0)
+		return;
+
+	CRYPTO_poly1305_update(poly1305, zero_pad16, 16 - pad_len);
+}
+
+static void
+poly1305_update_with_pad16(poly1305_state *poly1305,
+    const unsigned char *data, size_t data_len)
+{
+	CRYPTO_poly1305_update(poly1305, data, data_len);
+	poly1305_pad16(poly1305, data_len);
+}
+
+static int
+aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
+    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+    size_t nonce_len, const unsigned char *in, size_t in_len,
+    const unsigned char *ad, size_t ad_len)
+{
+	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+	unsigned char poly1305_key[32];
+	poly1305_state poly1305;
+	const unsigned char *iv;
+	uint64_t ctr;
+
+	if (max_out_len < in_len + c20_ctx->tag_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	if (nonce_len != ctx->aead->nonce_len) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		return 0;
+	}
+
+	ctr = (uint64_t)((uint32_t)(nonce[0]) | (uint32_t)(nonce[1]) << 8 |
+	    (uint32_t)(nonce[2]) << 16 | (uint32_t)(nonce[3]) << 24) << 32;
+	iv = nonce + CHACHA20_CONSTANT_LEN;
+
+	memset(poly1305_key, 0, sizeof(poly1305_key));
+	CRYPTO_chacha_20(poly1305_key, poly1305_key,
+	    sizeof(poly1305_key), c20_ctx->key, iv, ctr);
+
+	CRYPTO_poly1305_init(&poly1305, poly1305_key);
+	poly1305_update_with_pad16(&poly1305, ad, ad_len);
+	CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, iv, ctr + 1);
+	poly1305_update_with_pad16(&poly1305, out, in_len);
+	poly1305_update_with_length(&poly1305, NULL, ad_len);
+	poly1305_update_with_length(&poly1305, NULL, in_len);
+
+	if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
+		unsigned char tag[POLY1305_TAG_LEN];
+		CRYPTO_poly1305_finish(&poly1305, tag);
+		memcpy(out + in_len, tag, c20_ctx->tag_len);
+		*out_len = in_len + c20_ctx->tag_len;
+		return 1;
+	}
+
+	CRYPTO_poly1305_finish(&poly1305, out + in_len);
+	*out_len = in_len + POLY1305_TAG_LEN;
+	return 1;
+}
+
+static int
+aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
+    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+    size_t nonce_len, const unsigned char *in, size_t in_len,
+    const unsigned char *ad, size_t ad_len)
+{
+	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+	unsigned char mac[POLY1305_TAG_LEN];
+	unsigned char poly1305_key[32];
+	const unsigned char *iv = nonce;
+	poly1305_state poly1305;
+	size_t plaintext_len;
+	uint64_t ctr = 0;
+
+	if (in_len < c20_ctx->tag_len) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	if (nonce_len != ctx->aead->nonce_len) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		return 0;
+	}
+
+	plaintext_len = in_len - c20_ctx->tag_len;
+
+	if (max_out_len < plaintext_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	ctr = (uint64_t)((uint32_t)(nonce[0]) | (uint32_t)(nonce[1]) << 8 |
+	    (uint32_t)(nonce[2]) << 16 | (uint32_t)(nonce[3]) << 24) << 32;
+	iv = nonce + CHACHA20_CONSTANT_LEN;
+
+	memset(poly1305_key, 0, sizeof(poly1305_key));
+	CRYPTO_chacha_20(poly1305_key, poly1305_key,
+	    sizeof(poly1305_key), c20_ctx->key, iv, ctr);
+
+	CRYPTO_poly1305_init(&poly1305, poly1305_key);
+	poly1305_update_with_pad16(&poly1305, ad, ad_len);
+	poly1305_update_with_pad16(&poly1305, in, plaintext_len);
+	poly1305_update_with_length(&poly1305, NULL, ad_len);
+	poly1305_update_with_length(&poly1305, NULL, plaintext_len);
+
+	CRYPTO_poly1305_finish(&poly1305, mac);
+
+	if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, iv, ctr + 1);
+	*out_len = plaintext_len;
+	return 1;
+}
+
+static int
+aead_xchacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, unsigned char *out,
+    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+    size_t nonce_len, const unsigned char *in, size_t in_len,
+    const unsigned char *ad, size_t ad_len)
+{
+	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+	unsigned char poly1305_key[32];
+	unsigned char subkey[32];
+	poly1305_state poly1305;
+
+	if (max_out_len < in_len + c20_ctx->tag_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	if (nonce_len != ctx->aead->nonce_len) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		return 0;
+	}
+
+	CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce);
+
+	CRYPTO_chacha_20(out, in, in_len, subkey, nonce + 16, 1);
+
+	memset(poly1305_key, 0, sizeof(poly1305_key));
+	CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
+	    subkey, nonce + 16, 0);
+
+	CRYPTO_poly1305_init(&poly1305, poly1305_key);
+	poly1305_update_with_pad16(&poly1305, ad, ad_len);
+	poly1305_update_with_pad16(&poly1305, out, in_len);
+	poly1305_update_with_length(&poly1305, NULL, ad_len);
+	poly1305_update_with_length(&poly1305, NULL, in_len);
+
+	if (c20_ctx->tag_len != POLY1305_TAG_LEN) {
+		unsigned char tag[POLY1305_TAG_LEN];
+		CRYPTO_poly1305_finish(&poly1305, tag);
+		memcpy(out + in_len, tag, c20_ctx->tag_len);
+		*out_len = in_len + c20_ctx->tag_len;
+		return 1;
+	}
+
+	CRYPTO_poly1305_finish(&poly1305, out + in_len);
+	*out_len = in_len + POLY1305_TAG_LEN;
+	return 1;
+}
+
+static int
+aead_xchacha20_poly1305_open(const EVP_AEAD_CTX *ctx, unsigned char *out,
+    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+    size_t nonce_len, const unsigned char *in, size_t in_len,
+    const unsigned char *ad, size_t ad_len)
+{
+	const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
+	unsigned char mac[POLY1305_TAG_LEN];
+	unsigned char poly1305_key[32];
+	unsigned char subkey[32];
+	poly1305_state poly1305;
+	size_t plaintext_len;
+
+	if (in_len < c20_ctx->tag_len) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	if (nonce_len != ctx->aead->nonce_len) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		return 0;
+	}
+
+	plaintext_len = in_len - c20_ctx->tag_len;
+
+	if (max_out_len < plaintext_len) {
+		EVPerror(EVP_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+
+	CRYPTO_hchacha_20(subkey, c20_ctx->key, nonce);
+
+	memset(poly1305_key, 0, sizeof(poly1305_key));
+	CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
+	    subkey, nonce + 16, 0);
+
+	CRYPTO_poly1305_init(&poly1305, poly1305_key);
+	poly1305_update_with_pad16(&poly1305, ad, ad_len);
+	poly1305_update_with_pad16(&poly1305, in, plaintext_len);
+	poly1305_update_with_length(&poly1305, NULL, ad_len);
+	poly1305_update_with_length(&poly1305, NULL, plaintext_len);
+
+	CRYPTO_poly1305_finish(&poly1305, mac);
+	if (timingsafe_memcmp(mac, in + plaintext_len, c20_ctx->tag_len) != 0) {
+		EVPerror(EVP_R_BAD_DECRYPT);
+		return 0;
+	}
+
+	CRYPTO_chacha_20(out, in, plaintext_len, subkey, nonce + 16, 1);
+
+	*out_len = plaintext_len;
+	return 1;
+}
+
+/* RFC 8439 */
+static const EVP_AEAD aead_chacha20_poly1305 = {
+	.key_len = 32,
+	.nonce_len = CHACHA20_NONCE_LEN,
+	.overhead = POLY1305_TAG_LEN,
+	.max_tag_len = POLY1305_TAG_LEN,
+
+	.init = aead_chacha20_poly1305_init,
+	.cleanup = aead_chacha20_poly1305_cleanup,
+	.seal = aead_chacha20_poly1305_seal,
+	.open = aead_chacha20_poly1305_open,
+};
+
+const EVP_AEAD *
+EVP_aead_chacha20_poly1305()
+{
+	return &aead_chacha20_poly1305;
+}
+
+static const EVP_AEAD aead_xchacha20_poly1305 = {
+	.key_len = 32,
+	.nonce_len = XCHACHA20_NONCE_LEN,
+	.overhead = POLY1305_TAG_LEN,
+	.max_tag_len = POLY1305_TAG_LEN,
+
+	.init = aead_chacha20_poly1305_init,
+	.cleanup = aead_chacha20_poly1305_cleanup,
+	.seal = aead_xchacha20_poly1305_seal,
+	.open = aead_xchacha20_poly1305_open,
+};
+
+const EVP_AEAD *
+EVP_aead_xchacha20_poly1305()
+{
+	return &aead_xchacha20_poly1305;
+}
+
+struct chacha20_poly1305_ctx {
+	ChaCha_ctx chacha;
+	poly1305_state poly1305;
+
+	unsigned char key[32];
+	unsigned char nonce[CHACHA20_NONCE_LEN];
+	size_t nonce_len;
+	unsigned char tag[POLY1305_TAG_LEN];
+	size_t tag_len;
+
+	size_t ad_len;
+	size_t in_len;
+
+	int in_ad;
+	int started;
+};
+
+static int
+chacha20_poly1305_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int encrypt)
+{
+	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
+	uint8_t *data;
+	CBB cbb;
+	int ret = 0;
+
+	memset(&cbb, 0, sizeof(cbb));
+
+	if (key == NULL && iv == NULL)
+		goto done;
+
+	cpx->started = 0;
+
+	if (key != NULL)
+		memcpy(cpx->key, key, sizeof(cpx->key));
+
+	if (iv != NULL) {
+		/*
+		 * Left zero pad if configured nonce length is less than ChaCha
+		 * nonce length.
+		 */
+		if (!CBB_init_fixed(&cbb, cpx->nonce, sizeof(cpx->nonce)))
+			goto err;
+		if (!CBB_add_space(&cbb, &data, sizeof(cpx->nonce) - cpx->nonce_len))
+			goto err;
+		if (!CBB_add_bytes(&cbb, iv, cpx->nonce_len))
+			goto err;
+		if (!CBB_finish(&cbb, NULL, NULL))
+			goto err;
+	}
+
+ done:
+	ret = 1;
+
+ err:
+	CBB_cleanup(&cbb);
+
+	return ret;
+}
+
+static int
+chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
+
+	/*
+	 * Since we're making AEAD work within the constraints of EVP_CIPHER...
+	 * If in is non-NULL then this is an update, while if in is NULL then
+	 * this is a final. If in is non-NULL but out is NULL, then the input
+	 * being provided is associated data. Plus we have to handle encryption
+	 * (sealing) and decryption (opening) in the same function.
+	 */
+
+	if (!cpx->started) {
+		unsigned char poly1305_key[32];
+		const unsigned char *iv;
+		uint64_t ctr;
+
+		ctr = (uint64_t)((uint32_t)(cpx->nonce[0]) |
+		    (uint32_t)(cpx->nonce[1]) << 8 |
+		    (uint32_t)(cpx->nonce[2]) << 16 |
+		    (uint32_t)(cpx->nonce[3]) << 24) << 32;
+		iv = cpx->nonce + CHACHA20_CONSTANT_LEN;
+
+		ChaCha_set_key(&cpx->chacha, cpx->key, 8 * sizeof(cpx->key));
+		ChaCha_set_iv(&cpx->chacha, iv, NULL);
+
+		/* See chacha.c for details re handling of counter. */
+		cpx->chacha.input[12] = (uint32_t)ctr;
+		cpx->chacha.input[13] = (uint32_t)(ctr >> 32);
+
+		memset(poly1305_key, 0, sizeof(poly1305_key));
+		ChaCha(&cpx->chacha, poly1305_key, poly1305_key,
+		    sizeof(poly1305_key));
+		CRYPTO_poly1305_init(&cpx->poly1305, poly1305_key);
+
+		/* Mark remaining key block as used. */
+		cpx->chacha.unused = 0;
+
+		cpx->ad_len = 0;
+		cpx->in_len = 0;
+		cpx->in_ad = 0;
+
+		cpx->started = 1;
+	}
+
+	if (len > SIZE_MAX - cpx->in_len) {
+		EVPerror(EVP_R_TOO_LARGE);
+		return 0;
+	}
+
+	/* Disallow authenticated data after plaintext/ciphertext. */
+	if (cpx->in_len > 0 && in != NULL && out == NULL)
+		return -1;
+
+	if (cpx->in_ad && (in == NULL || out != NULL)) {
+		poly1305_pad16(&cpx->poly1305, cpx->ad_len);
+		cpx->in_ad = 0;
+	}
+
+	/* Update with AD or plaintext/ciphertext. */
+	if (in != NULL) {
+		if (out == NULL) {
+			cpx->ad_len += len;
+			cpx->in_ad = 1;
+		} else {
+			ChaCha(&cpx->chacha, out, in, len);
+			cpx->in_len += len;
+		}
+		if (ctx->encrypt && out != NULL)
+			CRYPTO_poly1305_update(&cpx->poly1305, out, len);
+		else
+			CRYPTO_poly1305_update(&cpx->poly1305, in, len);
+
+		return len;
+	}
+
+	/* Final. */
+	poly1305_pad16(&cpx->poly1305, cpx->in_len);
+	poly1305_update_with_length(&cpx->poly1305, NULL, cpx->ad_len);
+	poly1305_update_with_length(&cpx->poly1305, NULL, cpx->in_len);
+
+	if (ctx->encrypt) {
+		CRYPTO_poly1305_finish(&cpx->poly1305, cpx->tag);
+		cpx->tag_len = sizeof(cpx->tag);
+	} else {
+		unsigned char tag[POLY1305_TAG_LEN];
+
+		/* Ensure that a tag has been provided. */
+		if (cpx->tag_len <= 0)
+			return -1;
+
+		CRYPTO_poly1305_finish(&cpx->poly1305, tag);
+		if (timingsafe_memcmp(tag, cpx->tag, cpx->tag_len) != 0)
+			return -1;
+	}
+
+	cpx->started = 0;
+
+	return len;
+}
+
+static int
+chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
+{
+	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
+
+	explicit_bzero(cpx, sizeof(*cpx));
+
+	return 1;
+}
+
+static int
+chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+	struct chacha20_poly1305_ctx *cpx = ctx->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_INIT:
+		memset(cpx, 0, sizeof(*cpx));
+		cpx->nonce_len = sizeof(cpx->nonce);
+		return 1;
+
+	case EVP_CTRL_AEAD_GET_IVLEN:
+		if (cpx->nonce_len > INT_MAX)
+			return 0;
+		*(int *)ptr = (int)cpx->nonce_len;
+		return 1;
+
+	case EVP_CTRL_AEAD_SET_IVLEN:
+		if (arg <= 0 || arg > sizeof(cpx->nonce))
+			return 0;
+		cpx->nonce_len = arg;
+		return 1;
+
+	case EVP_CTRL_AEAD_SET_TAG:
+		if (ctx->encrypt)
+			return 0;
+		if (arg <= 0 || arg > sizeof(cpx->tag))
+			return 0;
+		if (ptr != NULL) {
+			memcpy(cpx->tag, ptr, arg);
+			cpx->tag_len = arg;
+		}
+		return 1;
+
+	case EVP_CTRL_AEAD_GET_TAG:
+		if (!ctx->encrypt)
+			return 0;
+		if (arg <= 0 || arg > cpx->tag_len)
+			return 0;
+		memcpy(ptr, cpx->tag, arg);
+		return 1;
+
+	case EVP_CTRL_AEAD_SET_IV_FIXED:
+		if (arg != sizeof(cpx->nonce))
+			return 0;
+		memcpy(cpx->nonce, ptr, arg);
+		return 1;
+	}
+
+	return 0;
+}
+
+static const EVP_CIPHER cipher_chacha20_poly1305 = {
+	.nid = NID_chacha20_poly1305,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 12,
+	.flags = EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
+	    EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_IV_LENGTH |
+	    EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_CUSTOM_CIPHER |
+	    EVP_CIPH_FLAG_DEFAULT_ASN1,
+	.init = chacha20_poly1305_init,
+	.do_cipher = chacha20_poly1305_cipher,
+	.cleanup = chacha20_poly1305_cleanup,
+	.ctx_size = sizeof(struct chacha20_poly1305_ctx),
+	.ctrl = chacha20_poly1305_ctrl,
+};
+
+const EVP_CIPHER *
+EVP_chacha20_poly1305(void)
+{
+	return &cipher_chacha20_poly1305;
+}
+
+#endif  /* !OPENSSL_NO_CHACHA && !OPENSSL_NO_POLY1305 */
diff --git a/crypto/evp/e_des.c b/crypto/evp/e_des.c
new file mode 100644
index 0000000..64d098c
--- /dev/null
+++ b/crypto/evp/e_des.c
@@ -0,0 +1,355 @@
+/* $OpenBSD: e_des.c,v 1.22 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_DES
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	DES_cblock *deskey = (DES_cblock *)key;
+
+	DES_set_key_unchecked(deskey, ctx->cipher_data);
+	return 1;
+}
+
+static int
+des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	switch (type) {
+	case EVP_CTRL_RAND_KEY:
+		if (DES_random_key((DES_cblock *)ptr) == 0)
+			return 0;
+		return 1;
+
+	default:
+		return -1;
+	}
+}
+
+static int
+des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i),
+		    ctx->cipher_data, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ofb64_encrypt(in, out, (long)chunk, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ofb64_encrypt(in, out, (long)inl, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, &ctx->num);
+	return 1;
+}
+
+static int
+des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ncbc_encrypt(in, out, (long)chunk, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ncbc_encrypt(in, out, (long)inl, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+	return 1;
+}
+
+static int
+des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_cfb64_encrypt(in, out, (long)chunk, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_cfb64_encrypt(in, out, (long)inl, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
+	return 1;
+}
+
+/* Although we have a CFB-r implementation for DES, it doesn't pack the right
+   way, so wrap it here */
+static int
+des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	unsigned char c[1], d[1];
+	size_t chunk = LONG_MAX / 8;
+	size_t n;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		for (n = 0; n < chunk*8; ++n) {
+			c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0;
+			DES_cfb_encrypt(c, d, 1, 1, ctx->cipher_data,
+			    (DES_cblock *)ctx->iv, ctx->encrypt);
+			out[n / 8] = (out[n / 8] &
+			    ~(0x80 >> (unsigned int)(n % 8))) |
+			    ((d[0] & 0x80) >> (unsigned int)(n % 8));
+		}
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_cfb_encrypt(in, out, 8, (long)chunk,
+		    ctx->cipher_data, (DES_cblock *)ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_cfb_encrypt(in, out, 8, (long)inl, ctx->cipher_data,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+	return 1;
+}
+
+static const EVP_CIPHER des_cbc = {
+	.nid = NID_des_cbc,
+	.block_size = 8,
+	.key_len = 8,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CBC_MODE,
+	.init = des_init_key,
+	.do_cipher = des_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_cbc(void)
+{
+	return &des_cbc;
+}
+
+static const EVP_CIPHER des_cfb64 = {
+	.nid = NID_des_cfb64,
+	.block_size = 1,
+	.key_len = 8,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_init_key,
+	.do_cipher = des_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_cfb64(void)
+{
+	return &des_cfb64;
+}
+
+static const EVP_CIPHER des_ofb = {
+	.nid = NID_des_ofb64,
+	.block_size = 1,
+	.key_len = 8,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_OFB_MODE,
+	.init = des_init_key,
+	.do_cipher = des_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ofb(void)
+{
+	return &des_ofb;
+}
+
+static const EVP_CIPHER des_ecb = {
+	.nid = NID_des_ecb,
+	.block_size = 8,
+	.key_len = 8,
+	.iv_len = 0,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_ECB_MODE,
+	.init = des_init_key,
+	.do_cipher = des_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ecb(void)
+{
+	return &des_ecb;
+}
+
+static const EVP_CIPHER des_cfb1 = {
+	.nid = NID_des_cfb1,
+	.block_size = 1,
+	.key_len = 8,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_init_key,
+	.do_cipher = des_cfb1_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_cfb1(void)
+{
+	return &des_cfb1;
+}
+
+static const EVP_CIPHER des_cfb8 = {
+	.nid = NID_des_cfb8,
+	.block_size = 1,
+	.key_len = 8,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_init_key,
+	.do_cipher = des_cfb8_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_key_schedule),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_cfb8(void)
+{
+	return &des_cfb8;
+}
+#endif
diff --git a/crypto/evp/e_des3.c b/crypto/evp/e_des3.c
new file mode 100644
index 0000000..3e6c523
--- /dev/null
+++ b/crypto/evp/e_des3.c
@@ -0,0 +1,495 @@
+/* $OpenBSD: e_des3.c,v 1.28 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_DES
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+typedef struct {
+    DES_key_schedule ks1;/* key schedule */
+    DES_key_schedule ks2;/* key schedule (for ede) */
+    DES_key_schedule ks3;/* key schedule (for ede3) */
+} DES_EDE_KEY;
+
+#define data(ctx) ((DES_EDE_KEY *)(ctx)->cipher_data)
+
+static int
+des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	DES_cblock *deskey = (DES_cblock *)key;
+
+	DES_set_key_unchecked(&deskey[0], &data(ctx)->ks1);
+	DES_set_key_unchecked(&deskey[1], &data(ctx)->ks2);
+	memcpy(&data(ctx)->ks3, &data(ctx)->ks1,
+	    sizeof(data(ctx)->ks1));
+	return 1;
+}
+
+static int
+des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	DES_cblock *deskey = (DES_cblock *)key;
+
+
+	DES_set_key_unchecked(&deskey[0], &data(ctx)->ks1);
+	DES_set_key_unchecked(&deskey[1], &data(ctx)->ks2);
+	DES_set_key_unchecked(&deskey[2], &data(ctx)->ks3);
+	return 1;
+}
+
+static int
+des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
+{
+	DES_cblock *deskey = ptr;
+
+	switch (type) {
+	case EVP_CTRL_RAND_KEY:
+		if (DES_random_key(deskey) == 0)
+			return 0;
+		if (c->key_len >= 16 && DES_random_key(deskey + 1) == 0)
+			return 0;
+		if (c->key_len >= 24 && DES_random_key(deskey + 2) == 0)
+			return 0;
+		return 1;
+
+	default:
+		return -1;
+	}
+}
+
+static int
+des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		DES_ecb3_encrypt((const_DES_cblock *)(in + i), (DES_cblock *)(out + i),
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ede3_ofb64_encrypt(in, out, (long)chunk,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ede3_ofb64_encrypt(in, out, (long)inl,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static int
+des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ede3_cbc_encrypt(in, out, (long)chunk,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ede3_cbc_encrypt(in, out, (long)inl,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+	return 1;
+}
+
+static int
+des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ede3_cfb64_encrypt(in, out, (long)chunk,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ede3_cfb64_encrypt(in, out, (long)inl,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt);
+	return 1;
+}
+
+/* Although we have a CFB-r implementation for 3-DES, it doesn't pack the right
+   way, so wrap it here */
+static int
+des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	unsigned char c[1], d[1];
+	size_t n;
+
+	if (!(ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS))
+		inl *= 8;
+
+	for (n = 0; n < inl; ++n) {
+		c[0] = (in[n/8]&(1 << (7 - n % 8))) ? 0x80 : 0;
+		DES_ede3_cfb_encrypt(c, d, 1, 1,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+		out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) |
+		    ((d[0] & 0x80) >> (unsigned int)(n % 8));
+	}
+
+	return 1;
+}
+
+static int
+des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		DES_ede3_cfb_encrypt(in, out, 8, (long)chunk,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+	if (inl)
+		DES_ede3_cfb_encrypt(in, out, 8, (long)inl,
+		    &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3,
+		    (DES_cblock *)ctx->iv, ctx->encrypt);
+	return 1;
+}
+
+static const EVP_CIPHER des_ede_cbc = {
+	.nid = NID_des_ede_cbc,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CBC_MODE,
+	.init = des_ede_init_key,
+	.do_cipher = des_ede_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede_cbc(void)
+{
+	return &des_ede_cbc;
+}
+
+static const EVP_CIPHER des_ede_cfb64 = {
+	.nid = NID_des_ede_cfb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_ede_init_key,
+	.do_cipher = des_ede_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede_cfb64(void)
+{
+	return &des_ede_cfb64;
+}
+
+static const EVP_CIPHER des_ede_ofb = {
+	.nid = NID_des_ede_ofb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_OFB_MODE,
+	.init = des_ede_init_key,
+	.do_cipher = des_ede_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede_ofb(void)
+{
+	return &des_ede_ofb;
+}
+
+static const EVP_CIPHER des_ede_ecb = {
+	.nid = NID_des_ede_ecb,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_ECB_MODE,
+	.init = des_ede_init_key,
+	.do_cipher = des_ede_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede_ecb(void)
+{
+	return &des_ede_ecb;
+}
+
+
+#define des_ede3_cfb64_cipher des_ede_cfb64_cipher
+#define des_ede3_ofb_cipher des_ede_ofb_cipher
+#define des_ede3_cbc_cipher des_ede_cbc_cipher
+#define des_ede3_ecb_cipher des_ede_ecb_cipher
+
+static const EVP_CIPHER des_ede3_cbc = {
+	.nid = NID_des_ede3_cbc,
+	.block_size = 8,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CBC_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_cbc(void)
+{
+	return &des_ede3_cbc;
+}
+
+static const EVP_CIPHER des_ede3_cfb64 = {
+	.nid = NID_des_ede3_cfb64,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_cfb64(void)
+{
+	return &des_ede3_cfb64;
+}
+
+static const EVP_CIPHER des_ede3_ofb = {
+	.nid = NID_des_ede3_ofb64,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_OFB_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_ofb(void)
+{
+	return &des_ede3_ofb;
+}
+
+static const EVP_CIPHER des_ede3_ecb = {
+	.nid = NID_des_ede3_ecb,
+	.block_size = 8,
+	.key_len = 24,
+	.iv_len = 0,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_ECB_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_ecb(void)
+{
+	return &des_ede3_ecb;
+}
+
+
+static const EVP_CIPHER des_ede3_cfb1 = {
+	.nid = NID_des_ede3_cfb1,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_cfb1_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_cfb1(void)
+{
+	return &des_ede3_cfb1;
+}
+
+
+static const EVP_CIPHER des_ede3_cfb8 = {
+	.nid = NID_des_ede3_cfb8,
+	.block_size = 1,
+	.key_len = 24,
+	.iv_len = 8,
+	.flags = EVP_CIPH_RAND_KEY | EVP_CIPH_CFB_MODE,
+	.init = des_ede3_init_key,
+	.do_cipher = des_ede3_cfb8_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(DES_EDE_KEY),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = des3_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_des_ede3_cfb8(void)
+{
+	return &des_ede3_cfb8;
+}
+
+const EVP_CIPHER *
+EVP_des_ede(void)
+{
+	return &des_ede_ecb;
+}
+
+const EVP_CIPHER *
+EVP_des_ede3(void)
+{
+	return &des_ede3_ecb;
+}
+#endif
diff --git a/crypto/evp/e_gost2814789.c b/crypto/evp/e_gost2814789.c
new file mode 100644
index 0000000..359cf5e
--- /dev/null
+++ b/crypto/evp/e_gost2814789.c
@@ -0,0 +1,315 @@
+/* $OpenBSD: e_gost2814789.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+typedef struct {
+	GOST2814789_KEY ks;
+	int param_nid;
+} EVP_GOST2814789_CTX;
+
+static int
+gost2814789_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	EVP_GOST2814789_CTX *c = ctx->cipher_data;
+
+	return Gost2814789_set_key(&c->ks, key, ctx->key_len * 8);
+}
+
+static int
+gost2814789_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+	EVP_GOST2814789_CTX *c = ctx->cipher_data;
+
+	switch (type) {
+	case EVP_CTRL_PBE_PRF_NID:
+		if (ptr != NULL) {
+			*((int *)ptr) = NID_id_HMACGostR3411_94;
+			return 1;
+		} else {
+			return 0;
+		}
+	case EVP_CTRL_INIT:
+		/* Default value to have any s-box set at all */
+		c->param_nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
+		return Gost2814789_set_sbox(&c->ks, c->param_nid);
+	case EVP_CTRL_GOST_SET_SBOX:
+		return Gost2814789_set_sbox(&c->ks, arg);
+	default:
+		return -1;
+	}
+}
+
+int
+gost2814789_set_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
+{
+	int len = 0;
+	unsigned char *buf = NULL;
+	unsigned char *p = NULL;
+	EVP_GOST2814789_CTX *c = ctx->cipher_data;
+	ASN1_OCTET_STRING *os = NULL;
+	GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new();
+
+	if (gcp == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	if (ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len) == 0) {
+		GOST_CIPHER_PARAMS_free(gcp);
+		GOSTerror(ERR_R_ASN1_LIB);
+		return 0;
+	}
+	ASN1_OBJECT_free(gcp->enc_param_set);
+	gcp->enc_param_set = OBJ_nid2obj(c->param_nid);
+
+	len = i2d_GOST_CIPHER_PARAMS(gcp, NULL);
+	p = buf = malloc(len);
+	if (buf == NULL) {
+		GOST_CIPHER_PARAMS_free(gcp);
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	i2d_GOST_CIPHER_PARAMS(gcp, &p);
+	GOST_CIPHER_PARAMS_free(gcp);
+
+	os = ASN1_OCTET_STRING_new();
+	if (os == NULL) {
+		free(buf);
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	if (ASN1_OCTET_STRING_set(os, buf, len) == 0) {
+		ASN1_OCTET_STRING_free(os);
+		free(buf);
+		GOSTerror(ERR_R_ASN1_LIB);
+		return 0;
+	}
+	free(buf);
+
+	ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
+	return 1;
+}
+
+int
+gost2814789_get_asn1_params(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params)
+{
+	int ret = -1;
+	int len;
+	GOST_CIPHER_PARAMS *gcp = NULL;
+	EVP_GOST2814789_CTX *c = ctx->cipher_data;
+	unsigned char *p;
+
+	if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE)
+		return ret;
+
+	p = params->value.sequence->data;
+
+	gcp = d2i_GOST_CIPHER_PARAMS(NULL, (const unsigned char **)&p,
+	    params->value.sequence->length);
+
+	len = gcp->iv->length;
+	if (len != ctx->cipher->iv_len) {
+		GOST_CIPHER_PARAMS_free(gcp);
+		GOSTerror(GOST_R_INVALID_IV_LENGTH);
+		return -1;
+	}
+
+	if (!Gost2814789_set_sbox(&c->ks, OBJ_obj2nid(gcp->enc_param_set))) {
+		GOST_CIPHER_PARAMS_free(gcp);
+		return -1;
+	}
+	c->param_nid = OBJ_obj2nid(gcp->enc_param_set);
+
+	memcpy(ctx->oiv, gcp->iv->data, len);
+	memcpy(ctx->iv, gcp->iv->data, len);
+
+	GOST_CIPHER_PARAMS_free(gcp);
+
+	return 1;
+}
+
+static int
+gost2814789_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		Gost2814789_ecb_encrypt(in + i, out + i, &((EVP_GOST2814789_CTX *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+gost2814789_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		Gost2814789_cfb64_encrypt(in, out, chunk, &((EVP_GOST2814789_CTX *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+gost2814789_cnt_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	EVP_GOST2814789_CTX *c = ctx->cipher_data;
+
+	while (inl >= EVP_MAXCHUNK) {
+		Gost2814789_cnt_encrypt(in, out, EVP_MAXCHUNK, &c->ks,
+		    ctx->iv, ctx->buf, &ctx->num);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		Gost2814789_cnt_encrypt(in, out, inl, &c->ks, ctx->iv, ctx->buf,
+		    &ctx->num);
+	return 1;
+}
+
+/* gost89 is CFB-64 */
+#define NID_gost89_cfb64 NID_id_Gost28147_89
+
+static const EVP_CIPHER gost2814789_ecb = {
+	.nid = NID_gost89_ecb,
+	.block_size = 8,
+	.key_len = 32,
+	.iv_len = 0,
+	.flags = EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT | EVP_CIPH_ECB_MODE,
+	.init = gost2814789_init_key,
+	.do_cipher = gost2814789_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_GOST2814789_CTX),
+	.set_asn1_parameters = gost2814789_set_asn1_params,
+	.get_asn1_parameters = gost2814789_get_asn1_params,
+	.ctrl = gost2814789_ctl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_gost2814789_ecb(void)
+{
+	return &gost2814789_ecb;
+}
+
+static const EVP_CIPHER gost2814789_cfb64 = {
+	.nid = NID_gost89_cfb64,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 8,
+	.flags = EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT | EVP_CIPH_CFB_MODE,
+	.init = gost2814789_init_key,
+	.do_cipher = gost2814789_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_GOST2814789_CTX),
+	.set_asn1_parameters = gost2814789_set_asn1_params,
+	.get_asn1_parameters = gost2814789_get_asn1_params,
+	.ctrl = gost2814789_ctl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_gost2814789_cfb64(void)
+{
+	return &gost2814789_cfb64;
+}
+
+static const EVP_CIPHER gost2814789_cnt = {
+	.nid = NID_gost89_cnt,
+	.block_size = 1,
+	.key_len = 32,
+	.iv_len = 8,
+	.flags = EVP_CIPH_NO_PADDING | EVP_CIPH_CTRL_INIT | EVP_CIPH_OFB_MODE,
+	.init = gost2814789_init_key,
+	.do_cipher = gost2814789_cnt_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_GOST2814789_CTX),
+	.set_asn1_parameters = gost2814789_set_asn1_params,
+	.get_asn1_parameters = gost2814789_get_asn1_params,
+	.ctrl = gost2814789_ctl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_gost2814789_cnt(void)
+{
+	return &gost2814789_cnt;
+}
+#endif
diff --git a/crypto/evp/e_idea.c b/crypto/evp/e_idea.c
new file mode 100644
index 0000000..b2129dc
--- /dev/null
+++ b/crypto/evp/e_idea.c
@@ -0,0 +1,266 @@
+/* $OpenBSD: e_idea.c,v 1.20 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_IDEA
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* NB idea_ecb_encrypt doesn't take an 'encrypt' argument so we treat it as a special
+ * case
+ */
+
+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)
+			enc = 1;
+		else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE)
+			enc = 1;
+	}
+	if (enc)
+		idea_set_encrypt_key(key, ctx->cipher_data);
+	else {
+		IDEA_KEY_SCHEDULE tmp;
+
+		idea_set_encrypt_key(key, &tmp);
+		idea_set_decrypt_key(&tmp, ctx->cipher_data);
+		explicit_bzero((unsigned char *)&tmp,
+		    sizeof(IDEA_KEY_SCHEDULE));
+	}
+	return 1;
+}
+
+static int
+idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		idea_ecb_encrypt(in + i, out + i, ctx->cipher_data);
+
+	return 1;
+}
+
+typedef struct {
+	IDEA_KEY_SCHEDULE ks;
+} EVP_IDEA_KEY;
+
+static int
+idea_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		idea_cbc_encrypt(in, out, (long)chunk, &((EVP_IDEA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		idea_cbc_encrypt(in, out, (long)inl, &((EVP_IDEA_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+idea_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		idea_ofb64_encrypt(in, out, (long)chunk, &((EVP_IDEA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		idea_ofb64_encrypt(in, out, (long)inl, &((EVP_IDEA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static int
+idea_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		idea_cfb64_encrypt(in, out, (long)chunk, &((EVP_IDEA_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static const EVP_CIPHER idea_cbc = {
+	.nid = NID_idea_cbc,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = 0 | EVP_CIPH_CBC_MODE,
+	.init = idea_init_key,
+	.do_cipher = idea_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(IDEA_KEY_SCHEDULE),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_idea_cbc(void)
+{
+	return &idea_cbc;
+}
+
+static const EVP_CIPHER idea_cfb64 = {
+	.nid = NID_idea_cfb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = 0 | EVP_CIPH_CFB_MODE,
+	.init = idea_init_key,
+	.do_cipher = idea_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(IDEA_KEY_SCHEDULE),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_idea_cfb64(void)
+{
+	return &idea_cfb64;
+}
+
+static const EVP_CIPHER idea_ofb = {
+	.nid = NID_idea_ofb64,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 8,
+	.flags = 0 | EVP_CIPH_OFB_MODE,
+	.init = idea_init_key,
+	.do_cipher = idea_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(IDEA_KEY_SCHEDULE),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_idea_ofb(void)
+{
+	return &idea_ofb;
+}
+
+static const EVP_CIPHER idea_ecb = {
+	.nid = NID_idea_ecb,
+	.block_size = 8,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = 0 | EVP_CIPH_ECB_MODE,
+	.init = idea_init_key,
+	.do_cipher = idea_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(IDEA_KEY_SCHEDULE),
+	.set_asn1_parameters = EVP_CIPHER_set_asn1_iv,
+	.get_asn1_parameters = EVP_CIPHER_get_asn1_iv,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_idea_ecb(void)
+{
+	return &idea_ecb;
+}
+#endif
diff --git a/crypto/evp/e_null.c b/crypto/evp/e_null.c
new file mode 100644
index 0000000..f30c207
--- /dev/null
+++ b/crypto/evp/e_null.c
@@ -0,0 +1,107 @@
+/* $OpenBSD: e_null.c,v 1.18 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc);
+static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl);
+
+static const EVP_CIPHER n_cipher = {
+	NID_undef,
+	1, 0, 0,
+	0,
+	null_init_key,
+	null_cipher,
+	NULL,
+	0,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+const EVP_CIPHER *
+EVP_enc_null(void)
+{
+	return (&n_cipher);
+}
+
+static int
+null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	/*	memset(&(ctx->c),0,sizeof(ctx->c));*/
+	return 1;
+}
+
+static int
+null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	if (in != out)
+		memcpy((char *)out, (const char *)in, inl);
+	return 1;
+}
diff --git a/crypto/evp/e_rc2.c b/crypto/evp/e_rc2.c
new file mode 100644
index 0000000..32559e2
--- /dev/null
+++ b/crypto/evp/e_rc2.c
@@ -0,0 +1,411 @@
+/* $OpenBSD: e_rc2.c,v 1.22 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_RC2
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc);
+static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx);
+static int rc2_magic_to_meth(int i);
+static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
+static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
+
+typedef struct {
+	int key_bits;	/* effective key bits */
+	RC2_KEY ks;	/* key schedule */
+} EVP_RC2_KEY;
+
+#define data(ctx)	((EVP_RC2_KEY *)(ctx)->cipher_data)
+
+static int
+rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		RC2_cbc_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		RC2_cbc_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+rc2_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		RC2_cfb64_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+rc2_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		RC2_ecb_encrypt(in + i, out + i, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+rc2_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = LONG_MAX & ~0xff;
+
+	while (inl >= chunk) {
+		RC2_ofb64_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+	}
+
+	if (inl)
+		RC2_ofb64_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER rc2_cbc = {
+	.nid = NID_rc2_cbc,
+	.block_size = 8,
+	.key_len = RC2_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CBC_MODE,
+	.init = rc2_init_key,
+	.do_cipher = rc2_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_RC2_KEY),
+	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
+	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
+	.ctrl = rc2_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_rc2_cbc(void)
+{
+	return &rc2_cbc;
+}
+
+static const EVP_CIPHER rc2_cfb64 = {
+	.nid = NID_rc2_cfb64,
+	.block_size = 1,
+	.key_len = RC2_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CFB_MODE,
+	.init = rc2_init_key,
+	.do_cipher = rc2_cfb64_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_RC2_KEY),
+	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
+	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
+	.ctrl = rc2_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_rc2_cfb64(void)
+{
+	return &rc2_cfb64;
+}
+
+static const EVP_CIPHER rc2_ofb = {
+	.nid = NID_rc2_ofb64,
+	.block_size = 1,
+	.key_len = RC2_KEY_LENGTH,
+	.iv_len = 8,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_OFB_MODE,
+	.init = rc2_init_key,
+	.do_cipher = rc2_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_RC2_KEY),
+	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
+	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
+	.ctrl = rc2_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_rc2_ofb(void)
+{
+	return &rc2_ofb;
+}
+
+static const EVP_CIPHER rc2_ecb = {
+	.nid = NID_rc2_ecb,
+	.block_size = 8,
+	.key_len = RC2_KEY_LENGTH,
+	.iv_len = 0,
+	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_ECB_MODE,
+	.init = rc2_init_key,
+	.do_cipher = rc2_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_RC2_KEY),
+	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
+	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
+	.ctrl = rc2_ctrl,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_rc2_ecb(void)
+{
+	return &rc2_ecb;
+}
+
+#define RC2_40_MAGIC	0xa0
+#define RC2_64_MAGIC	0x78
+#define RC2_128_MAGIC	0x3a
+
+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,
+	rc2_init_key,
+	rc2_cbc_cipher,
+	NULL,
+	sizeof(EVP_RC2_KEY),
+	rc2_set_asn1_type_and_iv,
+	rc2_get_asn1_type_and_iv,
+	rc2_ctrl,
+	NULL
+};
+
+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,
+	rc2_init_key,
+	rc2_cbc_cipher,
+	NULL,
+	sizeof(EVP_RC2_KEY),
+	rc2_set_asn1_type_and_iv,
+	rc2_get_asn1_type_and_iv,
+	rc2_ctrl,
+	NULL
+};
+
+const EVP_CIPHER *
+EVP_rc2_64_cbc(void)
+{
+	return (&r2_64_cbc_cipher);
+}
+
+const EVP_CIPHER *
+EVP_rc2_40_cbc(void)
+{
+	return (&r2_40_cbc_cipher);
+}
+
+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),
+	    key, data(ctx)->key_bits);
+	return 1;
+}
+
+static int
+rc2_meth_to_magic(EVP_CIPHER_CTX *e)
+{
+	int i;
+
+	if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0)
+		return (0);
+	if (i == 128)
+		return (RC2_128_MAGIC);
+	else if (i == 64)
+		return (RC2_64_MAGIC);
+	else if (i == 40)
+		return (RC2_40_MAGIC);
+	else
+		return (0);
+}
+
+static int
+rc2_magic_to_meth(int i)
+{
+	if (i == RC2_128_MAGIC)
+		return 128;
+	else if (i == RC2_64_MAGIC)
+		return 64;
+	else if (i == RC2_40_MAGIC)
+		return 40;
+	else {
+		EVPerror(EVP_R_UNSUPPORTED_KEY_SIZE);
+		return (0);
+	}
+}
+
+static int
+rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+	long num = 0;
+	int i = 0;
+	int key_bits;
+	unsigned int l;
+	unsigned char iv[EVP_MAX_IV_LENGTH];
+
+	if (type != NULL) {
+		l = EVP_CIPHER_CTX_iv_length(c);
+		if (l > sizeof(iv)) {
+			EVPerror(EVP_R_IV_TOO_LARGE);
+			return -1;
+		}
+		i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l);
+		if (i != (int)l)
+			return (-1);
+		key_bits = rc2_magic_to_meth((int)num);
+		if (!key_bits)
+			return (-1);
+		if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1))
+			return -1;
+		if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS,
+		    key_bits, NULL) <= 0)
+			return -1;
+		if (!EVP_CIPHER_CTX_set_key_length(c, key_bits / 8))
+			return -1;
+	}
+	return (i);
+}
+
+static int
+rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+	long num;
+	int i = 0, j;
+
+	if (type != NULL) {
+		num = rc2_meth_to_magic(c);
+		j = EVP_CIPHER_CTX_iv_length(c);
+		i = ASN1_TYPE_set_int_octetstring(type, num, c->oiv, j);
+	}
+	return (i);
+}
+
+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;
+		return 1;
+
+	case EVP_CTRL_GET_RC2_KEY_BITS:
+		*(int *)ptr = data(c)->key_bits;
+		return 1;
+
+	case EVP_CTRL_SET_RC2_KEY_BITS:
+		if (arg > 0) {
+			data(c)->key_bits = arg;
+			return 1;
+		}
+		return 0;
+
+#ifdef PBE_PRF_TEST
+	case EVP_CTRL_PBE_PRF_NID:
+		*(int *)ptr = NID_hmacWithMD5;
+		return 1;
+#endif
+
+	default:
+		return -1;
+	}
+}
+
+#endif
diff --git a/crypto/evp/e_rc4.c b/crypto/evp/e_rc4.c
new file mode 100644
index 0000000..2503d37
--- /dev/null
+++ b/crypto/evp/e_rc4.c
@@ -0,0 +1,140 @@
+/* $OpenBSD: e_rc4.c,v 1.17 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_RC4
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* FIXME: surely this is available elsewhere? */
+#define EVP_RC4_KEY_SIZE		16
+
+typedef struct {
+    RC4_KEY ks;	/* working key */
+} EVP_RC4_KEY;
+
+#define data(ctx) ((EVP_RC4_KEY *)(ctx)->cipher_data)
+
+static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc);
+static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl);
+
+static const EVP_CIPHER r4_cipher = {
+	NID_rc4,
+	1, EVP_RC4_KEY_SIZE, 0,
+	EVP_CIPH_VARIABLE_LENGTH,
+	rc4_init_key,
+	rc4_cipher,
+	NULL,
+	sizeof(EVP_RC4_KEY),
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+static const EVP_CIPHER r4_40_cipher = {
+	NID_rc4_40,
+	1, 5 /* 40 bit */, 0,
+	EVP_CIPH_VARIABLE_LENGTH,
+	rc4_init_key,
+	rc4_cipher,
+	NULL,
+	sizeof(EVP_RC4_KEY),
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
+const EVP_CIPHER *
+EVP_rc4(void)
+{
+	return (&r4_cipher);
+}
+
+const EVP_CIPHER *
+EVP_rc4_40(void)
+{
+	return (&r4_40_cipher);
+}
+
+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);
+	return 1;
+}
+
+static int
+rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	RC4(&data(ctx)->ks, inl, in, out);
+	return 1;
+}
+#endif
diff --git a/crypto/evp/e_rc4_hmac_md5.c b/crypto/evp/e_rc4_hmac_md5.c
new file mode 100644
index 0000000..bcf8dae
--- /dev/null
+++ b/crypto/evp/e_rc4_hmac_md5.c
@@ -0,0 +1,307 @@
+/* $OpenBSD: e_rc4_hmac_md5.c,v 1.12 2023/07/07 19:37:53 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+
+#include 
+
+#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5)
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* FIXME: surely this is available elsewhere? */
+#define EVP_RC4_KEY_SIZE		16
+
+typedef struct {
+	RC4_KEY		ks;
+	MD5_CTX		head, tail, md;
+	size_t		payload_length;
+} EVP_RC4_HMAC_MD5;
+
+#define NO_PAYLOAD_LENGTH	((size_t)-1)
+
+void rc4_md5_enc (RC4_KEY *key, const void *in0, void *out,
+    MD5_CTX *ctx, const void *inp, size_t blocks);
+
+#define data(ctx) ((EVP_RC4_HMAC_MD5 *)(ctx)->cipher_data)
+
+static int
+rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *inkey,
+    const unsigned char *iv, int enc)
+{
+	EVP_RC4_HMAC_MD5 *key = data(ctx);
+
+	RC4_set_key(&key->ks, EVP_CIPHER_CTX_key_length(ctx), inkey);
+
+	MD5_Init(&key->head);	/* handy when benchmarking */
+	key->tail = key->head;
+	key->md = key->head;
+
+	key->payload_length = NO_PAYLOAD_LENGTH;
+
+	return 1;
+}
+
+#if	!defined(OPENSSL_NO_ASM) && defined(RC4_MD5_ASM) &&	( \
+	defined(__x86_64)	|| defined(__x86_64__)	|| \
+	defined(_M_AMD64)	|| defined(_M_X64)	|| \
+	defined(__INTEL__)		) && \
+	!(defined(__APPLE__) && defined(__MACH__))
+#define	STITCHED_CALL
+#include "x86_arch.h"
+#endif
+
+#if !defined(STITCHED_CALL)
+#define	rc4_off 0
+#define	md5_off 0
+#endif
+
+static int
+rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t len)
+{
+	EVP_RC4_HMAC_MD5 *key = data(ctx);
+#if defined(STITCHED_CALL)
+	size_t	rc4_off = 32-1-(key->ks.x&(32-1)),	/* 32 is $MOD from rc4_md5-x86_64.pl */
+	md5_off = MD5_CBLOCK - key->md.num,
+	    blocks;
+	unsigned int l;
+#endif
+	size_t	plen = key->payload_length;
+
+	if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH))
+		return 0;
+
+	if (ctx->encrypt) {
+		if (plen == NO_PAYLOAD_LENGTH)
+			plen = len;
+#if defined(STITCHED_CALL)
+		/* cipher has to "fall behind" */
+		if (rc4_off > md5_off)
+			md5_off += MD5_CBLOCK;
+
+		if (plen > md5_off &&
+		    (blocks = (plen - md5_off) / MD5_CBLOCK) &&
+		    (OPENSSL_cpu_caps() & CPUCAP_MASK_INTELP4) == 0) {
+			MD5_Update(&key->md, in, md5_off);
+			RC4(&key->ks, rc4_off, in, out);
+
+			rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off,
+			    &key->md, in + md5_off, blocks);
+			blocks *= MD5_CBLOCK;
+			rc4_off += blocks;
+			md5_off += blocks;
+			key->md.Nh += blocks >> 29;
+			key->md.Nl += blocks <<= 3;
+			if (key->md.Nl < (unsigned int)blocks)
+				key->md.Nh++;
+		} else {
+			rc4_off = 0;
+			md5_off = 0;
+		}
+#endif
+		MD5_Update(&key->md, in + md5_off, plen - md5_off);
+
+		if (plen!=len) {	/* "TLS" mode of operation */
+			if (in != out)
+				memcpy(out + rc4_off, in + rc4_off,
+				    plen - rc4_off);
+
+			/* calculate HMAC and append it to payload */
+			MD5_Final(out + plen, &key->md);
+			key->md = key->tail;
+			MD5_Update(&key->md, out + plen, MD5_DIGEST_LENGTH);
+			MD5_Final(out + plen, &key->md);
+
+			/* encrypt HMAC at once */
+			RC4(&key->ks, len - rc4_off, out + rc4_off,
+			    out + rc4_off);
+		} else {
+			RC4(&key->ks, len - rc4_off, in + rc4_off,
+			    out + rc4_off);
+		}
+	} else {
+		unsigned char mac[MD5_DIGEST_LENGTH];
+#if defined(STITCHED_CALL)
+		/* digest has to "fall behind" */
+		if (md5_off > rc4_off)
+			rc4_off += 2*MD5_CBLOCK;
+		else
+			rc4_off += MD5_CBLOCK;
+
+		if (len > rc4_off && (blocks = (len - rc4_off) / MD5_CBLOCK) &&
+		    (OPENSSL_cpu_caps() & CPUCAP_MASK_INTELP4) == 0) {
+			RC4(&key->ks, rc4_off, in, out);
+			MD5_Update(&key->md, out, md5_off);
+
+			rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off,
+			    &key->md, out + md5_off, blocks);
+			blocks *= MD5_CBLOCK;
+			rc4_off += blocks;
+			md5_off += blocks;
+			l = (key->md.Nl + (blocks << 3)) & 0xffffffffU;
+			if (l < key->md.Nl)
+				key->md.Nh++;
+			key->md.Nl = l;
+			key->md.Nh += blocks >> 29;
+		} else {
+			md5_off = 0;
+			rc4_off = 0;
+		}
+#endif
+		/* decrypt HMAC at once */
+		RC4(&key->ks, len - rc4_off, in + rc4_off, out + rc4_off);
+		if (plen!=NO_PAYLOAD_LENGTH) {	/* "TLS" mode of operation */
+			MD5_Update(&key->md, out + md5_off, plen - md5_off);
+
+			/* calculate HMAC and verify it */
+			MD5_Final(mac, &key->md);
+			key->md = key->tail;
+			MD5_Update(&key->md, mac, MD5_DIGEST_LENGTH);
+			MD5_Final(mac, &key->md);
+
+			if (memcmp(out + plen, mac, MD5_DIGEST_LENGTH))
+				return 0;
+		} else {
+			MD5_Update(&key->md, out + md5_off, len - md5_off);
+		}
+	}
+
+	key->payload_length = NO_PAYLOAD_LENGTH;
+
+	return 1;
+}
+
+static int
+rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+	EVP_RC4_HMAC_MD5 *key = data(ctx);
+
+	switch (type) {
+	case EVP_CTRL_AEAD_SET_MAC_KEY:
+		{
+			unsigned int  i;
+			unsigned char hmac_key[64];
+
+			memset (hmac_key, 0, sizeof(hmac_key));
+
+			if (arg > (int)sizeof(hmac_key)) {
+				MD5_Init(&key->head);
+				MD5_Update(&key->head, ptr, arg);
+				MD5_Final(hmac_key, &key->head);
+			} else {
+				memcpy(hmac_key, ptr, arg);
+			}
+
+			for (i = 0; i < sizeof(hmac_key); i++)
+				hmac_key[i] ^= 0x36;		/* ipad */
+			MD5_Init(&key->head);
+			MD5_Update(&key->head, hmac_key, sizeof(hmac_key));
+
+			for (i = 0; i < sizeof(hmac_key); i++)
+				hmac_key[i] ^= 0x36 ^ 0x5c;	/* opad */
+			MD5_Init(&key->tail);
+			MD5_Update(&key->tail, hmac_key, sizeof(hmac_key));
+
+			return 1;
+		}
+	case EVP_CTRL_AEAD_TLS1_AAD:
+		{
+			unsigned char *p = ptr;
+			unsigned int len = p[arg - 2] << 8 | p[arg - 1];
+
+			if (!ctx->encrypt) {
+				if (len < MD5_DIGEST_LENGTH)
+					return -1;
+				len -= MD5_DIGEST_LENGTH;
+				p[arg - 2] = len >> 8;
+				p[arg - 1] = len;
+			}
+			key->payload_length = len;
+			key->md = key->head;
+			MD5_Update(&key->md, p, arg);
+
+			return MD5_DIGEST_LENGTH;
+		}
+	default:
+		return -1;
+	}
+}
+
+static EVP_CIPHER r4_hmac_md5_cipher = {
+#ifdef NID_rc4_hmac_md5
+	NID_rc4_hmac_md5,
+#else
+	NID_undef,
+#endif
+	1, EVP_RC4_KEY_SIZE, 0,
+	EVP_CIPH_STREAM_CIPHER|EVP_CIPH_VARIABLE_LENGTH|EVP_CIPH_FLAG_AEAD_CIPHER,
+	rc4_hmac_md5_init_key,
+	rc4_hmac_md5_cipher,
+	NULL,
+	sizeof(EVP_RC4_HMAC_MD5),
+	NULL,
+	NULL,
+	rc4_hmac_md5_ctrl,
+	NULL
+};
+
+const EVP_CIPHER *
+EVP_rc4_hmac_md5(void)
+{
+	return (&r4_hmac_md5_cipher);
+}
+#endif
diff --git a/crypto/evp/e_sm4.c b/crypto/evp/e_sm4.c
new file mode 100644
index 0000000..c1664db
--- /dev/null
+++ b/crypto/evp/e_sm4.c
@@ -0,0 +1,267 @@
+/*	$OpenBSD: e_sm4.c,v 1.9 2023/07/07 19:37:53 beck Exp $	*/
+/*
+ * Copyright (c) 2017, 2019 Ribose Inc
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_SM4
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+typedef struct {
+	SM4_KEY ks;
+} EVP_SM4_KEY;
+
+static int
+sm4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	SM4_set_key(key, ctx->cipher_data);
+	return 1;
+}
+
+static void
+sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+    const SM4_KEY *key, unsigned char *ivec, const int enc)
+{
+	if (enc)
+		CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
+		    (block128_f)SM4_encrypt);
+	else
+		CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
+		    (block128_f)SM4_decrypt);
+}
+
+static void
+sm4_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const SM4_KEY *key, unsigned char *ivec, int *num, const int enc)
+{
+	CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+	    (block128_f)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);
+	else
+		SM4_decrypt(in, out, key);
+}
+
+static void
+sm4_ofb128_encrypt(const unsigned char *in, unsigned char *out, size_t length,
+    const SM4_KEY *key, unsigned char *ivec, int *num)
+{
+	CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+	    (block128_f)SM4_encrypt);
+}
+
+static int
+sm4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		sm4_cbc_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		sm4_cbc_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+sm4_cfb128_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t chunk = EVP_MAXCHUNK;
+
+	if (inl < chunk)
+		chunk = inl;
+
+	while (inl && inl >= chunk) {
+		sm4_cfb128_encrypt(in, out, chunk, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
+		inl -= chunk;
+		in += chunk;
+		out += chunk;
+		if (inl < chunk)
+			chunk = inl;
+	}
+
+	return 1;
+}
+
+static int
+sm4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	size_t i, bl;
+
+	bl = ctx->cipher->block_size;
+
+	if (inl < bl)
+		return 1;
+
+	inl -= bl;
+
+	for (i = 0; i <= inl; i += bl)
+		sm4_ecb_encrypt(in + i, out + i, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
+
+	return 1;
+}
+
+static int
+sm4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		sm4_ofb128_encrypt(in, out, EVP_MAXCHUNK, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+
+	if (inl)
+		sm4_ofb128_encrypt(in, out, inl, &((EVP_SM4_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
+
+	return 1;
+}
+
+static const EVP_CIPHER sm4_cbc = {
+	.nid = NID_sm4_cbc,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CBC_MODE,
+	.init = sm4_init_key,
+	.do_cipher = sm4_cbc_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_SM4_KEY),
+	.set_asn1_parameters = 0,
+	.get_asn1_parameters = 0,
+	.ctrl = 0,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_sm4_cbc(void)
+{
+	return &sm4_cbc;
+}
+
+static const EVP_CIPHER sm4_cfb128 = {
+	.nid = NID_sm4_cfb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CFB_MODE,
+	.init = sm4_init_key,
+	.do_cipher = sm4_cfb128_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_SM4_KEY),
+	.set_asn1_parameters = 0,
+	.get_asn1_parameters = 0,
+	.ctrl = 0,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_sm4_cfb128(void)
+{
+	return &sm4_cfb128;
+}
+
+static const EVP_CIPHER sm4_ofb = {
+	.nid = NID_sm4_ofb128,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_OFB_MODE,
+	.init = sm4_init_key,
+	.do_cipher = sm4_ofb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_SM4_KEY),
+	.set_asn1_parameters = 0,
+	.get_asn1_parameters = 0,
+	.ctrl = 0,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_sm4_ofb(void)
+{
+	return &sm4_ofb;
+}
+
+static const EVP_CIPHER sm4_ecb = {
+	.nid = NID_sm4_ecb,
+	.block_size = 16,
+	.key_len = 16,
+	.iv_len = 0,
+	.flags = EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_ECB_MODE,
+	.init = sm4_init_key,
+	.do_cipher = sm4_ecb_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_SM4_KEY),
+	.set_asn1_parameters = 0,
+	.get_asn1_parameters = 0,
+	.ctrl = 0,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_sm4_ecb(void)
+{
+	return &sm4_ecb;
+}
+
+static int
+sm4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+    size_t len)
+{
+	EVP_SM4_KEY *key = ((EVP_SM4_KEY *)(ctx)->cipher_data);
+
+	CRYPTO_ctr128_encrypt(in, out, len, &key->ks, ctx->iv, ctx->buf,
+	    &ctx->num, (block128_f)SM4_encrypt);
+	return 1;
+}
+
+static const EVP_CIPHER sm4_ctr_mode = {
+	.nid = NID_sm4_ctr,
+	.block_size = 1,
+	.key_len = 16,
+	.iv_len = 16,
+	.flags = EVP_CIPH_CTR_MODE,
+	.init = sm4_init_key,
+	.do_cipher = sm4_ctr_cipher,
+	.cleanup = NULL,
+	.ctx_size = sizeof(EVP_SM4_KEY),
+	.set_asn1_parameters = NULL,
+	.get_asn1_parameters = NULL,
+	.ctrl = NULL,
+	.app_data = NULL,
+};
+
+const EVP_CIPHER *
+EVP_sm4_ctr(void)
+{
+	return &sm4_ctr_mode;
+}
+#endif
diff --git a/crypto/evp/e_xcbc_d.c b/crypto/evp/e_xcbc_d.c
new file mode 100644
index 0000000..32f9f2e
--- /dev/null
+++ b/crypto/evp/e_xcbc_d.c
@@ -0,0 +1,137 @@
+/* $OpenBSD: e_xcbc_d.c,v 1.15 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_DES
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc);
+static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl);
+
+
+typedef struct {
+	DES_key_schedule ks;/* key schedule */
+	DES_cblock inw;
+	DES_cblock outw;
+} DESX_CBC_KEY;
+
+#define data(ctx) ((DESX_CBC_KEY *)(ctx)->cipher_data)
+
+static const EVP_CIPHER d_xcbc_cipher = {
+	NID_desx_cbc,
+	8, 24, 8,
+	EVP_CIPH_CBC_MODE,
+	desx_cbc_init_key,
+	desx_cbc_cipher,
+	NULL,
+	sizeof(DESX_CBC_KEY),
+	EVP_CIPHER_set_asn1_iv,
+	EVP_CIPHER_get_asn1_iv,
+	NULL,
+	NULL
+};
+
+const EVP_CIPHER *
+EVP_desx_cbc(void)
+{
+	return (&d_xcbc_cipher);
+}
+
+static int
+desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+    const unsigned char *iv, int enc)
+{
+	DES_cblock *deskey = (DES_cblock *)key;
+
+	DES_set_key_unchecked(deskey, &data(ctx)->ks);
+	memcpy(&data(ctx)->inw[0], &key[8], 8);
+	memcpy(&data(ctx)->outw[0], &key[16], 8);
+
+	return 1;
+}
+
+static int
+desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+    const unsigned char *in, size_t inl)
+{
+	while (inl >= EVP_MAXCHUNK) {
+		DES_xcbc_encrypt(in, out, (long)EVP_MAXCHUNK, &data(ctx)->ks,
+		    (DES_cblock *)&(ctx->iv[0]), &data(ctx)->inw,
+		    &data(ctx)->outw, ctx->encrypt);
+		inl -= EVP_MAXCHUNK;
+		in += EVP_MAXCHUNK;
+		out += EVP_MAXCHUNK;
+	}
+	if (inl)
+		DES_xcbc_encrypt(in, out, (long)inl, &data(ctx)->ks,
+		    (DES_cblock *)&(ctx->iv[0]), &data(ctx)->inw,
+		    &data(ctx)->outw, ctx->encrypt);
+	return 1;
+}
+#endif
diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c
new file mode 100644
index 0000000..c62a1de
--- /dev/null
+++ b/crypto/evp/encode.c
@@ -0,0 +1,414 @@
+/* $OpenBSD: encode.c,v 1.32 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "evp_local.h"
+
+static unsigned char conv_ascii2bin(unsigned char a);
+#define conv_bin2ascii(a)	(data_bin2ascii[(a)&0x3f])
+
+/* 64 char lines
+ * pad input with 0
+ * left over chars are set to =
+ * 1 byte  => xx==
+ * 2 bytes => xxx=
+ * 3 bytes => xxxx
+ */
+#define BIN_PER_LINE    (64/4*3)
+#define CHUNKS_PER_LINE (64/4)
+#define CHAR_PER_LINE   (64+1)
+
+static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\
+abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* 0xF0 is a EOLN
+ * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
+ * 0xF2 is EOF
+ * 0xE0 is ignore at start of line.
+ * 0xFF is error
+ */
+
+#define B64_EOLN		0xF0
+#define B64_CR			0xF1
+#define B64_EOF			0xF2
+#define B64_WS			0xE0
+#define B64_ERROR       	0xFF
+#define B64_NOT_BASE64(a)	(((a)|0x13) == 0xF3)
+#define B64_BASE64(a)		!B64_NOT_BASE64(a)
+
+static const unsigned char data_ascii2bin[128] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
+	0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+	0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
+	0xFF, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+	0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+	0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+	0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+static unsigned char
+conv_ascii2bin(unsigned char a)
+{
+	if (a & 0x80)
+		return B64_ERROR;
+	return data_ascii2bin[a];
+}
+
+EVP_ENCODE_CTX *
+EVP_ENCODE_CTX_new(void)
+{
+	return calloc(1, sizeof(EVP_ENCODE_CTX));
+}
+
+void
+EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx)
+{
+	free(ctx);
+}
+
+void
+EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
+{
+	ctx->length = 48;
+	ctx->num = 0;
+	ctx->line_num = 0;
+}
+
+int
+EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+	int i, j;
+	size_t total = 0;
+
+	*outl = 0;
+	if (inl <= 0)
+		return 0;
+	OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data));
+	if (ctx->length - ctx->num > inl) {
+		memcpy(&(ctx->enc_data[ctx->num]), in, inl);
+		ctx->num += inl;
+		return 1;
+	}
+	if (ctx->num != 0) {
+		i = ctx->length - ctx->num;
+		memcpy(&(ctx->enc_data[ctx->num]), in, i);
+		in += i;
+		inl -= i;
+		j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
+		ctx->num = 0;
+		out += j;
+		*(out++) = '\n';
+		*out = '\0';
+		total = j + 1;
+	}
+	while (inl >= ctx->length && total <= INT_MAX) {
+		j = EVP_EncodeBlock(out, in, ctx->length);
+		in += ctx->length;
+		inl -= ctx->length;
+		out += j;
+		*(out++) = '\n';
+		*out = '\0';
+		total += j + 1;
+	}
+	if (total > INT_MAX) {
+		/* Too much output data! */
+		*outl = 0;
+		return 0;
+	}
+	if (inl != 0)
+		memcpy(&(ctx->enc_data[0]), in, inl);
+	ctx->num = inl;
+	*outl = total;
+
+	return 1;
+}
+
+void
+EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
+{
+	unsigned int ret = 0;
+
+	if (ctx->num != 0) {
+		ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
+		out[ret++] = '\n';
+		out[ret] = '\0';
+		ctx->num = 0;
+	}
+	*outl = ret;
+}
+
+int
+EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)
+{
+	int i, ret = 0;
+	unsigned long l;
+
+	for (i = dlen; i > 0; i -= 3) {
+		if (i >= 3) {
+			l = (((unsigned long)f[0]) << 16L) |
+			    (((unsigned long)f[1]) << 8L) | f[2];
+			*(t++) = conv_bin2ascii(l >> 18L);
+			*(t++) = conv_bin2ascii(l >> 12L);
+			*(t++) = conv_bin2ascii(l >> 6L);
+			*(t++) = conv_bin2ascii(l     );
+		} else {
+			l = ((unsigned long)f[0]) << 16L;
+			if (i == 2)
+				l |= ((unsigned long)f[1] << 8L);
+
+			*(t++) = conv_bin2ascii(l >> 18L);
+			*(t++) = conv_bin2ascii(l >> 12L);
+			*(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L);
+			*(t++) = '=';
+		}
+		ret += 4;
+		f += 3;
+	}
+
+	*t = '\0';
+	return (ret);
+}
+
+void
+EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
+{
+	ctx->num = 0;
+	ctx->length = 0;
+	ctx->line_num = 0;
+	ctx->expect_nl = 0;
+}
+
+int
+EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+	int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len;
+	unsigned char *d;
+
+	n = ctx->num;
+	d = ctx->enc_data;
+
+	if (n > 0 && d[n - 1] == '=') {
+		eof++;
+		if (n > 1 && d[n - 2] == '=')
+			eof++;
+	}
+
+	/* Legacy behaviour: an empty input chunk signals end of input. */
+	if (inl == 0) {
+		rv = 0;
+		goto end;
+	}
+
+	for (i = 0; i < inl; i++) {
+		tmp = *(in++);
+		v = conv_ascii2bin(tmp);
+		if (v == B64_ERROR) {
+			rv = -1;
+			goto end;
+		}
+
+		if (tmp == '=') {
+			eof++;
+		} else if (eof > 0 && B64_BASE64(v)) {
+			/* More data after padding. */
+			rv = -1;
+			goto end;
+		}
+
+		if (eof > 2) {
+			rv = -1;
+			goto end;
+		}
+
+		if (v == B64_EOF) {
+			seof = 1;
+			goto tail;
+		}
+
+		/* Only save valid base64 characters. */
+		if (B64_BASE64(v)) {
+			if (n >= 64) {
+				/*
+				 * We increment n once per loop, and empty the
+				 * buffer as soon as we reach 64 characters, so
+				 * this can only happen if someone's manually
+				 * messed with the ctx. Refuse to write any
+				 * more data.
+				 */
+				rv = -1;
+				goto end;
+			}
+			OPENSSL_assert(n < (int)sizeof(ctx->enc_data));
+			d[n++] = tmp;
+		}
+
+		if (n == 64) {
+			decoded_len = EVP_DecodeBlock(out, d, n);
+			n = 0;
+			if (decoded_len < 0 || eof > decoded_len) {
+				rv = -1;
+				goto end;
+			}
+			ret += decoded_len - eof;
+			out += decoded_len - eof;
+		}
+	}
+
+	/*
+	 * Legacy behaviour: if the current line is a full base64-block (i.e.,
+	 * has 0 mod 4 base64 characters), it is processed immediately. We keep
+	 * this behaviour as applications may not be calling EVP_DecodeFinal
+	 * properly.
+	 */
+ tail:
+	if (n > 0) {
+		if ((n & 3) == 0) {
+			decoded_len = EVP_DecodeBlock(out, d, n);
+			n = 0;
+			if (decoded_len < 0 || eof > decoded_len) {
+				rv = -1;
+				goto end;
+			}
+			ret += (decoded_len - eof);
+		} else if (seof) {
+			/* EOF in the middle of a base64 block. */
+			rv = -1;
+			goto end;
+		}
+	}
+
+	rv = seof || (n == 0 && eof) ? 0 : 1;
+ end:
+	/* Legacy behaviour. This should probably rather be zeroed on error. */
+	*outl = ret;
+	ctx->num = n;
+	return (rv);
+}
+
+int
+EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n)
+{
+	int i, ret = 0, a, b, c, d;
+	unsigned long l;
+
+	/* trim white space from the start of the line. */
+	while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) {
+		f++;
+		n--;
+	}
+
+	/* strip off stuff at the end of the line
+	 * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
+	while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1]))))
+		n--;
+
+	if (n % 4 != 0)
+		return (-1);
+
+	for (i = 0; i < n; i += 4) {
+		a = conv_ascii2bin(*(f++));
+		b = conv_ascii2bin(*(f++));
+		c = conv_ascii2bin(*(f++));
+		d = conv_ascii2bin(*(f++));
+		if ((a & 0x80) || (b & 0x80) ||
+		    (c & 0x80) || (d & 0x80))
+			return (-1);
+		l = ((((unsigned long)a) << 18L) |
+		    (((unsigned long)b) << 12L) |
+		    (((unsigned long)c) << 6L) |
+		    (((unsigned long)d)));
+		*(t++) = (unsigned char)(l >> 16L) & 0xff;
+		*(t++) = (unsigned char)(l >> 8L) & 0xff;
+		*(t++) = (unsigned char)(l) & 0xff;
+		ret += 3;
+	}
+	return (ret);
+}
+
+int
+EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)
+{
+	int i;
+
+	*outl = 0;
+	if (ctx->num != 0) {
+		i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
+		if (i < 0)
+			return (-1);
+		ctx->num = 0;
+		*outl = i;
+		return (1);
+	} else
+		return (1);
+}
diff --git a/crypto/evp/evp_aead.c b/crypto/evp/evp_aead.c
new file mode 100644
index 0000000..3579533
--- /dev/null
+++ b/crypto/evp/evp_aead.c
@@ -0,0 +1,160 @@
+/* $OpenBSD: evp_aead.c,v 1.10 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "evp_local.h"
+
+size_t
+EVP_AEAD_key_length(const EVP_AEAD *aead)
+{
+	return aead->key_len;
+}
+
+size_t
+EVP_AEAD_nonce_length(const EVP_AEAD *aead)
+{
+	return aead->nonce_len;
+}
+
+size_t
+EVP_AEAD_max_overhead(const EVP_AEAD *aead)
+{
+	return aead->overhead;
+}
+
+size_t
+EVP_AEAD_max_tag_len(const EVP_AEAD *aead)
+{
+	return aead->max_tag_len;
+}
+
+int
+EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
+    const unsigned char *key, size_t key_len, size_t tag_len, ENGINE *impl)
+{
+	ctx->aead = aead;
+	if (key_len != aead->key_len) {
+		EVPerror(EVP_R_UNSUPPORTED_KEY_SIZE);
+		return 0;
+	}
+	return aead->init(ctx, key, key_len, tag_len);
+}
+
+void
+EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx)
+{
+	if (ctx->aead == NULL)
+		return;
+	ctx->aead->cleanup(ctx);
+	ctx->aead = NULL;
+}
+
+EVP_AEAD_CTX *
+EVP_AEAD_CTX_new(void)
+{
+	return calloc(1, sizeof(EVP_AEAD_CTX));
+}
+
+void
+EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	EVP_AEAD_CTX_cleanup(ctx);
+	free(ctx);
+}
+
+/* check_alias returns 0 if out points within the buffer determined by in
+ * and in_len and 1 otherwise.
+ *
+ * When processing, there's only an issue if out points within in[:in_len]
+ * and isn't equal to in. If that's the case then writing the output will
+ * stomp input that hasn't been read yet.
+ *
+ * This function checks for that case. */
+static int
+check_alias(const unsigned char *in, size_t in_len, const unsigned char *out)
+{
+	if (out <= in)
+		return 1;
+	if (in + in_len <= out)
+		return 1;
+	return 0;
+}
+
+int
+EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
+    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
+    const unsigned char *in, size_t in_len, const unsigned char *ad,
+    size_t ad_len)
+{
+	size_t possible_out_len = in_len + ctx->aead->overhead;
+
+	/* Overflow. */
+	if (possible_out_len < in_len) {
+		EVPerror(EVP_R_TOO_LARGE);
+		goto error;
+	}
+
+	if (!check_alias(in, in_len, out)) {
+		EVPerror(EVP_R_OUTPUT_ALIASES_INPUT);
+		goto error;
+	}
+
+	if (ctx->aead->seal(ctx, out, out_len, max_out_len, nonce, nonce_len,
+	    in, in_len, ad, ad_len)) {
+		return 1;
+	}
+
+error:
+	/* In the event of an error, clear the output buffer so that a caller
+	 * that doesn't check the return value doesn't send raw data. */
+	memset(out, 0, max_out_len);
+	*out_len = 0;
+	return 0;
+}
+
+int
+EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, unsigned char *out, size_t *out_len,
+    size_t max_out_len, const unsigned char *nonce, size_t nonce_len,
+    const unsigned char *in, size_t in_len, const unsigned char *ad,
+    size_t ad_len)
+{
+	if (!check_alias(in, in_len, out)) {
+		EVPerror(EVP_R_OUTPUT_ALIASES_INPUT);
+		goto error;
+	}
+
+	if (ctx->aead->open(ctx, out, out_len, max_out_len, nonce, nonce_len,
+	    in, in_len, ad, ad_len)) {
+		return 1;
+	}
+
+error:
+	/* In the event of an error, clear the output buffer so that a caller
+	 * that doesn't check the return value doesn't try and process bad
+	 * data. */
+	memset(out, 0, max_out_len);
+	*out_len = 0;
+	return 0;
+}
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
new file mode 100644
index 0000000..7534b4c
--- /dev/null
+++ b/crypto/evp/evp_enc.c
@@ -0,0 +1,725 @@
+/* $OpenBSD: evp_enc.c,v 1.53 2023/09/10 16:53:56 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "evp_local.h"
+
+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_cleanup(ctx);
+	return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
+}
+
+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)
+		enc = ctx->encrypt;
+	else {
+		if (enc)
+			enc = 1;
+		ctx->encrypt = enc;
+	}
+#ifndef OPENSSL_NO_ENGINE
+	/* 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 previous handle, re-querying for an ENGINE, and having a
+	 * reinitialisation, when it may all be unnecessary. */
+	if (ctx->engine && ctx->cipher &&
+	    (!cipher || (cipher && (cipher->nid == ctx->cipher->nid))))
+		goto skip_to_init;
+#endif
+	if (cipher) {
+		/* 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 (ctx->cipher) {
+			unsigned long flags = ctx->flags;
+			EVP_CIPHER_CTX_cleanup(ctx);
+			/* Restore encrypt and flags */
+			ctx->encrypt = enc;
+			ctx->flags = flags;
+		}
+#ifndef OPENSSL_NO_ENGINE
+		if (impl) {
+			if (!ENGINE_init(impl)) {
+				EVPerror(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) {
+			/* There's an ENGINE for this job ... (apparently) */
+			const EVP_CIPHER *c =
+			    ENGINE_get_cipher(impl, cipher->nid);
+			if (!c) {
+				EVPerror(EVP_R_INITIALIZATION_ERROR);
+				return 0;
+			}
+			/* We'll use the ENGINE's private cipher definition */
+			cipher = c;
+			/* Store the ENGINE functional reference so we know
+			 * 'cipher' came from an ENGINE and we need to release
+			 * it when done. */
+			ctx->engine = impl;
+		} else
+			ctx->engine = NULL;
+#endif
+
+		ctx->cipher = cipher;
+		if (ctx->cipher->ctx_size) {
+			ctx->cipher_data = calloc(1, ctx->cipher->ctx_size);
+			if (ctx->cipher_data == NULL) {
+				EVPerror(ERR_R_MALLOC_FAILURE);
+				return 0;
+			}
+		} else {
+			ctx->cipher_data = NULL;
+		}
+		ctx->key_len = cipher->key_len;
+		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)) {
+				EVPerror(EVP_R_INITIALIZATION_ERROR);
+				return 0;
+			}
+		}
+	} else if (!ctx->cipher) {
+		EVPerror(EVP_R_NO_CIPHER_SET);
+		return 0;
+	}
+#ifndef OPENSSL_NO_ENGINE
+skip_to_init:
+#endif
+	/* we assume block size is a power of 2 in *cryptUpdate */
+	if (ctx->cipher->block_size != 1 &&
+	    ctx->cipher->block_size != 8 &&
+	    ctx->cipher->block_size != 16) {
+		EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+		return 0;
+	}
+
+	if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) &&
+	    EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) {
+		EVPerror(EVP_R_WRAP_MODE_NOT_ALLOWED);
+		return 0;
+	}
+
+	if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
+		switch (EVP_CIPHER_CTX_mode(ctx)) {
+
+		case EVP_CIPH_STREAM_CIPHER:
+		case EVP_CIPH_ECB_MODE:
+			break;
+
+		case EVP_CIPH_CFB_MODE:
+		case EVP_CIPH_OFB_MODE:
+
+			ctx->num = 0;
+			/* fall-through */
+
+		case EVP_CIPH_CBC_MODE:
+
+			if ((size_t)EVP_CIPHER_CTX_iv_length(ctx) >
+			    sizeof(ctx->iv)) {
+				EVPerror(EVP_R_IV_TOO_LARGE);
+				return 0;
+			}
+			if (iv)
+				memcpy(ctx->oiv, iv,
+				    EVP_CIPHER_CTX_iv_length(ctx));
+			memcpy(ctx->iv, ctx->oiv,
+			    EVP_CIPHER_CTX_iv_length(ctx));
+			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));
+			break;
+
+		default:
+			return 0;
+			break;
+		}
+	}
+
+	if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
+		if (!ctx->cipher->init(ctx, key, iv, enc))
+			return 0;
+	}
+	ctx->buf_len = 0;
+	ctx->final_used = 0;
+	ctx->block_mask = ctx->cipher->block_size - 1;
+	return 1;
+}
+
+int
+EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+	if (ctx->encrypt)
+		return EVP_EncryptUpdate(ctx, out, outl, in, inl);
+	else
+		return EVP_DecryptUpdate(ctx, out, outl, in, inl);
+}
+
+int
+EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	if (ctx->encrypt)
+		return EVP_EncryptFinal_ex(ctx, out, outl);
+	else
+		return EVP_DecryptFinal_ex(ctx, out, outl);
+}
+
+__warn_references(EVP_CipherFinal,
+    "EVP_CipherFinal is often misused, please use EVP_CipherFinal_ex and EVP_CIPHER_CTX_cleanup");
+
+int
+EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int ret;
+	if (ctx->encrypt)
+		ret = EVP_EncryptFinal_ex(ctx, out, outl);
+	else
+		ret = EVP_DecryptFinal_ex(ctx, out, outl);
+	return ret;
+}
+
+int
+EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+    const unsigned char *key, const unsigned char *iv)
+{
+	return EVP_CipherInit(ctx, cipher, key, iv, 1);
+}
+
+int
+EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
+    const unsigned char *key, const unsigned char *iv)
+{
+	return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
+}
+
+int
+EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+    const unsigned char *key, const unsigned char *iv)
+{
+	return EVP_CipherInit(ctx, cipher, key, iv, 0);
+}
+
+int
+EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
+    const unsigned char *key, const unsigned char *iv)
+{
+	return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
+}
+
+int
+EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+	int i, j, bl;
+
+	*outl = 0;
+
+	if (inl < 0)
+		return 0;
+
+	if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
+		return 1;
+
+	if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+		i = ctx->cipher->do_cipher(ctx, out, in, inl);
+		if (i < 0)
+			return 0;
+		else
+			*outl = i;
+		return 1;
+	}
+
+	if (ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0) {
+		if (ctx->cipher->do_cipher(ctx, out, in, inl)) {
+			*outl = inl;
+			return 1;
+		} else {
+			*outl = 0;
+			return 0;
+		}
+	}
+	i = ctx->buf_len;
+	bl = ctx->cipher->block_size;
+	if ((size_t)bl > sizeof(ctx->buf)) {
+		EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+		*outl = 0;
+		return 0;
+	}
+	if (i != 0) {
+		if (bl - i > inl) {
+			memcpy(&(ctx->buf[i]), in, inl);
+			ctx->buf_len += inl;
+			*outl = 0;
+			return 1;
+		} else {
+			j = bl - i;
+
+			/*
+			 * Once we've processed the first j bytes from in, the
+			 * amount of data left that is a multiple of the block
+			 * length is (inl - j) & ~(bl - 1).  Ensure this plus
+			 * the block processed from ctx-buf doesn't overflow.
+			 */
+			if (((inl - j) & ~(bl - 1)) > INT_MAX - bl) {
+				EVPerror(EVP_R_TOO_LARGE);
+				return 0;
+			}
+			memcpy(&(ctx->buf[i]), in, j);
+			if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl))
+				return 0;
+			inl -= j;
+			in += j;
+			out += bl;
+			*outl = bl;
+		}
+	} else
+		*outl = 0;
+	i = inl&(bl - 1);
+	inl -= i;
+	if (inl > 0) {
+		if (!ctx->cipher->do_cipher(ctx, out, in, inl))
+			return 0;
+		*outl += inl;
+	}
+
+	if (i != 0)
+		memcpy(ctx->buf, &(in[inl]), i);
+	ctx->buf_len = i;
+	return 1;
+}
+
+__warn_references(EVP_EncryptFinal,
+    "EVP_EncryptFinal is often misused, please use EVP_EncryptFinal_ex and EVP_CIPHER_CTX_cleanup");
+
+int
+EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int ret;
+
+	ret = EVP_EncryptFinal_ex(ctx, out, outl);
+	return ret;
+}
+
+int
+EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int n, ret;
+	unsigned int i, b, bl;
+
+	if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+		ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
+		if (ret < 0)
+			return 0;
+		else
+			*outl = ret;
+		return 1;
+	}
+
+	b = ctx->cipher->block_size;
+	if (b > sizeof ctx->buf) {
+		EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+		return 0;
+	}
+	if (b == 1) {
+		*outl = 0;
+		return 1;
+	}
+	bl = ctx->buf_len;
+	if (ctx->flags & EVP_CIPH_NO_PADDING) {
+		if (bl) {
+			EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+			return 0;
+		}
+		*outl = 0;
+		return 1;
+	}
+
+	n = b - bl;
+	for (i = bl; i < b; i++)
+		ctx->buf[i] = n;
+	ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b);
+
+
+	if (ret)
+		*outl = b;
+
+	return ret;
+}
+
+int
+EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
+    const unsigned char *in, int inl)
+{
+	int fix_len;
+	unsigned int b;
+
+	*outl = 0;
+
+	if (inl < 0)
+		return 0;
+
+	if (inl == 0 && EVP_CIPHER_mode(ctx->cipher) != EVP_CIPH_CCM_MODE)
+		return 1;
+
+	if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+		fix_len = ctx->cipher->do_cipher(ctx, out, in, inl);
+		if (fix_len < 0) {
+			*outl = 0;
+			return 0;
+		} else
+			*outl = fix_len;
+		return 1;
+	}
+
+	if (ctx->flags & EVP_CIPH_NO_PADDING)
+		return EVP_EncryptUpdate(ctx, out, outl, in, inl);
+
+	b = ctx->cipher->block_size;
+	if (b > sizeof ctx->final) {
+		EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+		return 0;
+	}
+
+	if (ctx->final_used) {
+		/*
+		 * final_used is only ever set if buf_len is 0. Therefore the
+		 * maximum length output we will ever see from EVP_EncryptUpdate
+		 * is inl & ~(b - 1). Since final_used is set, the final output
+		 * length is (inl & ~(b - 1)) + b. Ensure it doesn't overflow.
+		 */
+		if ((inl & ~(b - 1)) > INT_MAX - b) {
+			EVPerror(EVP_R_TOO_LARGE);
+			return 0;
+		}
+		memcpy(out, ctx->final, b);
+		out += b;
+		fix_len = 1;
+	} else
+		fix_len = 0;
+
+
+	if (!EVP_EncryptUpdate(ctx, out, outl, in, inl))
+		return 0;
+
+	/* if we have 'decrypted' a multiple of block size, make sure
+	 * we have a copy of this last block */
+	if (b > 1 && !ctx->buf_len) {
+		*outl -= b;
+		ctx->final_used = 1;
+		memcpy(ctx->final, &out[*outl], b);
+	} else
+		ctx->final_used = 0;
+
+	if (fix_len)
+		*outl += b;
+
+	return 1;
+}
+
+__warn_references(EVP_DecryptFinal,
+    "EVP_DecryptFinal is often misused, please use EVP_DecryptFinal_ex and EVP_CIPHER_CTX_cleanup");
+
+int
+EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int ret;
+
+	ret = EVP_DecryptFinal_ex(ctx, out, outl);
+	return ret;
+}
+
+int
+EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int i, n;
+	unsigned int b;
+	*outl = 0;
+
+	if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
+		i = ctx->cipher->do_cipher(ctx, out, NULL, 0);
+		if (i < 0)
+			return 0;
+		else
+			*outl = i;
+		return 1;
+	}
+
+	b = ctx->cipher->block_size;
+	if (ctx->flags & EVP_CIPH_NO_PADDING) {
+		if (ctx->buf_len) {
+			EVPerror(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+			return 0;
+		}
+		*outl = 0;
+		return 1;
+	}
+	if (b > 1) {
+		if (ctx->buf_len || !ctx->final_used) {
+			EVPerror(EVP_R_WRONG_FINAL_BLOCK_LENGTH);
+			return (0);
+		}
+		if (b > sizeof ctx->final) {
+			EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+			return 0;
+		}
+		n = ctx->final[b - 1];
+		if (n == 0 || n > (int)b) {
+			EVPerror(EVP_R_BAD_DECRYPT);
+			return (0);
+		}
+		for (i = 0; i < n; i++) {
+			if (ctx->final[--b] != n) {
+				EVPerror(EVP_R_BAD_DECRYPT);
+				return (0);
+			}
+		}
+		n = ctx->cipher->block_size - n;
+		for (i = 0; i < n; i++)
+			out[i] = ctx->final[i];
+		*outl = n;
+	} else
+		*outl = 0;
+	return (1);
+}
+
+EVP_CIPHER_CTX *
+EVP_CIPHER_CTX_new(void)
+{
+	return calloc(1, sizeof(EVP_CIPHER_CTX));
+}
+
+void
+EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	EVP_CIPHER_CTX_cleanup(ctx);
+
+	free(ctx);
+}
+
+void
+EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
+{
+	memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
+}
+
+int
+EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *a)
+{
+	return EVP_CIPHER_CTX_cleanup(a);
+}
+
+int
+EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
+{
+	if (c->cipher != NULL) {
+		/* XXX - Avoid leaks, so ignore return value of cleanup()... */
+		if (c->cipher->cleanup != NULL)
+			c->cipher->cleanup(c);
+		if (c->cipher_data != NULL)
+			explicit_bzero(c->cipher_data, c->cipher->ctx_size);
+	}
+
+	/* XXX - store size of cipher_data so we can always freezero(). */
+	free(c->cipher_data);
+
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(c->engine);
+#endif
+
+	explicit_bzero(c, sizeof(EVP_CIPHER_CTX));
+
+	return 1;
+}
+
+int
+EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
+{
+	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)
+		return 1;
+	if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
+		c->key_len = keylen;
+		return 1;
+	}
+	EVPerror(EVP_R_INVALID_KEY_LENGTH);
+	return 0;
+}
+
+int
+EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
+{
+	if (pad)
+		ctx->flags &= ~EVP_CIPH_NO_PADDING;
+	else
+		ctx->flags |= EVP_CIPH_NO_PADDING;
+	return 1;
+}
+
+int
+EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
+{
+	int ret;
+
+	if (!ctx->cipher) {
+		EVPerror(EVP_R_NO_CIPHER_SET);
+		return 0;
+	}
+
+	if (!ctx->cipher->ctrl) {
+		EVPerror(EVP_R_CTRL_NOT_IMPLEMENTED);
+		return 0;
+	}
+
+	ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
+	if (ret == -1) {
+		EVPerror(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
+		return 0;
+	}
+	return ret;
+}
+
+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);
+	arc4random_buf(key, ctx->key_len);
+	return 1;
+}
+
+int
+EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
+{
+	if ((in == NULL) || (in->cipher == NULL)) {
+		EVPerror(EVP_R_INPUT_NOT_INITIALIZED);
+		return 0;
+	}
+#ifndef OPENSSL_NO_ENGINE
+	/* Make sure it's safe to copy a cipher context using an ENGINE */
+	if (in->engine && !ENGINE_init(in->engine)) {
+		EVPerror(ERR_R_ENGINE_LIB);
+		return 0;
+	}
+#endif
+
+	EVP_CIPHER_CTX_cleanup(out);
+	memcpy(out, in, sizeof *out);
+
+	if (in->cipher_data && in->cipher->ctx_size) {
+		out->cipher_data = calloc(1, in->cipher->ctx_size);
+		if (out->cipher_data == NULL) {
+			EVPerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+	}
+
+	if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
+		if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY,
+		    0, out)) {
+			/*
+			 * If the custom copy control failed, assume that there
+			 * may still be pointers copied in the cipher_data that
+			 * we do not own. This may result in a leak from a bad
+			 * custom copy control, but that's preferable to a
+			 * double free...
+			 */
+			freezero(out->cipher_data, in->cipher->ctx_size);
+			out->cipher_data = NULL;
+			return 0;
+		}
+	}
+
+	return 1;
+}
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
new file mode 100644
index 0000000..039e17e
--- /dev/null
+++ b/crypto/evp/evp_err.c
@@ -0,0 +1,166 @@
+/* $OpenBSD: evp_err.c,v 1.32 2023/07/07 19:37:53 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_EVP,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_EVP,0,reason)
+
+static ERR_STRING_DATA EVP_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA EVP_str_reasons[] = {
+	{ERR_REASON(EVP_R_AES_IV_SETUP_FAILED)   , "aes iv setup failed"},
+	{ERR_REASON(EVP_R_AES_KEY_SETUP_FAILED)  , "aes key setup failed"},
+	{ERR_REASON(EVP_R_ASN1_LIB)              , "asn1 lib"},
+	{ERR_REASON(EVP_R_BAD_BLOCK_LENGTH)      , "bad block length"},
+	{ERR_REASON(EVP_R_BAD_DECRYPT)           , "bad decrypt"},
+	{ERR_REASON(EVP_R_BAD_KEY_LENGTH)        , "bad key length"},
+	{ERR_REASON(EVP_R_BN_DECODE_ERROR)       , "bn decode error"},
+	{ERR_REASON(EVP_R_BN_PUBKEY_ERROR)       , "bn pubkey error"},
+	{ERR_REASON(EVP_R_BUFFER_TOO_SMALL)      , "buffer too small"},
+	{ERR_REASON(EVP_R_CAMELLIA_KEY_SETUP_FAILED), "camellia key setup failed"},
+	{ERR_REASON(EVP_R_CIPHER_PARAMETER_ERROR), "cipher parameter error"},
+	{ERR_REASON(EVP_R_COMMAND_NOT_SUPPORTED) , "command not supported"},
+	{ERR_REASON(EVP_R_CTRL_NOT_IMPLEMENTED)  , "ctrl not implemented"},
+	{ERR_REASON(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED), "ctrl operation not implemented"},
+	{ERR_REASON(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), "data not multiple of block length"},
+	{ERR_REASON(EVP_R_DECODE_ERROR)          , "decode error"},
+	{ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES)   , "different key types"},
+	{ERR_REASON(EVP_R_DIFFERENT_PARAMETERS)  , "different parameters"},
+	{ERR_REASON(EVP_R_DISABLED_FOR_FIPS)     , "disabled for fips"},
+	{ERR_REASON(EVP_R_ENCODE_ERROR)          , "encode error"},
+	{ERR_REASON(EVP_R_ERROR_LOADING_SECTION) , "error loading section"},
+	{ERR_REASON(EVP_R_ERROR_SETTING_FIPS_MODE), "error setting fips mode"},
+	{ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR), "evp pbe cipherinit error"},
+	{ERR_REASON(EVP_R_EXPECTING_AN_HMAC_KEY), "expecting an hmac key"},
+	{ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY)  , "expecting an rsa key"},
+	{ERR_REASON(EVP_R_EXPECTING_A_DH_KEY)    , "expecting a dh key"},
+	{ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY)   , "expecting a dsa key"},
+	{ERR_REASON(EVP_R_EXPECTING_A_ECDSA_KEY) , "expecting a ecdsa key"},
+	{ERR_REASON(EVP_R_EXPECTING_A_EC_KEY)    , "expecting a ec key"},
+	{ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"},
+	{ERR_REASON(EVP_R_GET_RAW_KEY_FAILED)    , "get raw key failed"},
+	{ERR_REASON(EVP_R_INITIALIZATION_ERROR)  , "initialization error"},
+	{ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED) , "input not initialized"},
+	{ERR_REASON(EVP_R_INVALID_DIGEST)        , "invalid digest"},
+	{ERR_REASON(EVP_R_INVALID_FIPS_MODE)     , "invalid fips mode"},
+	{ERR_REASON(EVP_R_INVALID_IV_LENGTH)     , "invalid iv length"},
+	{ERR_REASON(EVP_R_INVALID_KEY_LENGTH)    , "invalid key length"},
+	{ERR_REASON(EVP_R_INVALID_OPERATION)     , "invalid operation"},
+	{ERR_REASON(EVP_R_IV_TOO_LARGE)          , "iv too large"},
+	{ERR_REASON(EVP_R_KEYGEN_FAILURE)        , "keygen failure"},
+	{ERR_REASON(EVP_R_KEY_SETUP_FAILED)      , "key setup failed"},
+	{ERR_REASON(EVP_R_MESSAGE_DIGEST_IS_NULL), "message digest is null"},
+	{ERR_REASON(EVP_R_METHOD_NOT_SUPPORTED)  , "method not supported"},
+	{ERR_REASON(EVP_R_MISSING_PARAMETERS)    , "missing parameters"},
+	{ERR_REASON(EVP_R_NO_CIPHER_SET)         , "no cipher set"},
+	{ERR_REASON(EVP_R_NO_DEFAULT_DIGEST)     , "no default digest"},
+	{ERR_REASON(EVP_R_NO_DIGEST_SET)         , "no digest set"},
+	{ERR_REASON(EVP_R_NO_DSA_PARAMETERS)     , "no dsa parameters"},
+	{ERR_REASON(EVP_R_NO_KEY_SET)            , "no key set"},
+	{ERR_REASON(EVP_R_NO_OPERATION_SET)      , "no operation set"},
+	{ERR_REASON(EVP_R_NO_SIGN_FUNCTION_CONFIGURED), "no sign function configured"},
+	{ERR_REASON(EVP_R_NO_VERIFY_FUNCTION_CONFIGURED), "no verify function configured"},
+	{ERR_REASON(EVP_R_ONLY_ONESHOT_SUPPORTED), "only oneshot supported"},
+	{ERR_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), "operation not supported for this keytype"},
+	{ERR_REASON(EVP_R_OPERATON_NOT_INITIALIZED), "operaton not initialized"},
+	{ERR_REASON(EVP_R_OUTPUT_ALIASES_INPUT)  , "output aliases input"},
+	{ERR_REASON(EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE), "pkcs8 unknown broken type"},
+	{ERR_REASON(EVP_R_PRIVATE_KEY_DECODE_ERROR), "private key decode error"},
+	{ERR_REASON(EVP_R_PRIVATE_KEY_ENCODE_ERROR), "private key encode error"},
+	{ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA)    , "public key not rsa"},
+	{ERR_REASON(EVP_R_TAG_TOO_LARGE)         , "tag too large"},
+	{ERR_REASON(EVP_R_TOO_LARGE)             , "too large"},
+	{ERR_REASON(EVP_R_UNKNOWN_CIPHER)        , "unknown cipher"},
+	{ERR_REASON(EVP_R_UNKNOWN_DIGEST)        , "unknown digest"},
+	{ERR_REASON(EVP_R_UNKNOWN_OPTION)        , "unknown option"},
+	{ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM) , "unknown pbe algorithm"},
+	{ERR_REASON(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS), "unsuported number of rounds"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_ALGORITHM) , "unsupported algorithm"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_CIPHER)    , "unsupported cipher"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_KEYLENGTH) , "unsupported keylength"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION), "unsupported key derivation function"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_KEY_SIZE)  , "unsupported key size"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_PRF)       , "unsupported prf"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), "unsupported private key algorithm"},
+	{ERR_REASON(EVP_R_UNSUPPORTED_SALT_TYPE) , "unsupported salt type"},
+	{ERR_REASON(EVP_R_WRAP_MODE_NOT_ALLOWED), "wrap mode not allowed"},
+	{ERR_REASON(EVP_R_WRONG_FINAL_BLOCK_LENGTH), "wrong final block length"},
+	{ERR_REASON(EVP_R_WRONG_PUBLIC_KEY_TYPE) , "wrong public key type"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_EVP_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(EVP_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, EVP_str_functs);
+		ERR_load_strings(0, EVP_str_reasons);
+	}
+#endif
+}
diff --git a/crypto/evp/evp_key.c b/crypto/evp/evp_key.c
new file mode 100644
index 0000000..2f6e7e7
--- /dev/null
+++ b/crypto/evp/evp_key.c
@@ -0,0 +1,212 @@
+/* $OpenBSD: evp_key.c,v 1.30 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* should be init to zeros. */
+static char prompt_string[80];
+
+void
+EVP_set_pw_prompt(const char *prompt)
+{
+	if (prompt == NULL)
+		prompt_string[0] = '\0';
+	else {
+		strlcpy(prompt_string, prompt, sizeof(prompt_string));
+	}
+}
+
+char *
+EVP_get_pw_prompt(void)
+{
+	if (prompt_string[0] == '\0')
+		return (NULL);
+	else
+		return (prompt_string);
+}
+
+int
+EVP_read_pw_string(char *buf, int len, const char *prompt, int verify)
+{
+	return EVP_read_pw_string_min(buf, 0, len, prompt, verify);
+}
+
+int
+EVP_read_pw_string_min(char *buf, int min, int len, const char *prompt,
+    int verify)
+{
+	int ret;
+	char buff[BUFSIZ];
+	UI *ui;
+
+	if (len > BUFSIZ)
+		len = BUFSIZ;
+	/* Ensure that 0 <= min <= len - 1. In particular, 1 <= len. */
+	if (min < 0 || len - 1 < min)
+		return -1;
+	if ((prompt == NULL) && (prompt_string[0] != '\0'))
+		prompt = prompt_string;
+	ui = UI_new();
+	if (ui == NULL)
+		return -1;
+	if (UI_add_input_string(ui, prompt, 0, buf, min, len - 1) < 0)
+		return -1;
+	if (verify) {
+		if (UI_add_verify_string(ui, prompt, 0, buff, min, len - 1, buf)
+		    < 0)
+			return -1;
+	}
+	ret = UI_process(ui);
+	UI_free(ui);
+	explicit_bzero(buff, BUFSIZ);
+	return ret;
+}
+
+int
+EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
+    const unsigned char *salt, const unsigned char *data, int datal,
+    int count, unsigned char *key, unsigned char *iv)
+{
+	EVP_MD_CTX c;
+	unsigned char md_buf[EVP_MAX_MD_SIZE];
+	int niv, nkey, addmd = 0;
+	unsigned int mds = 0, i;
+	int rv = 0;
+
+	nkey = type->key_len;
+	niv = type->iv_len;
+
+	if ((size_t)nkey > EVP_MAX_KEY_LENGTH) {
+		EVPerror(EVP_R_BAD_KEY_LENGTH);
+		return 0;
+	}
+	if ((size_t)niv > EVP_MAX_IV_LENGTH) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		return 0;
+	}
+
+	if (data == NULL)
+		return (nkey);
+
+	EVP_MD_CTX_init(&c);
+	for (;;) {
+		if (!EVP_DigestInit_ex(&c, md, NULL))
+			goto err;
+		if (addmd++)
+			if (!EVP_DigestUpdate(&c, &(md_buf[0]), mds))
+				goto err;
+		if (!EVP_DigestUpdate(&c, data, datal))
+			goto err;
+		if (salt != NULL)
+			if (!EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN))
+				goto err;
+		if (!EVP_DigestFinal_ex(&c, &(md_buf[0]), &mds))
+			goto err;
+
+		for (i = 1; i < (unsigned int)count; i++) {
+			if (!EVP_DigestInit_ex(&c, md, NULL))
+				goto err;
+			if (!EVP_DigestUpdate(&c, &(md_buf[0]), mds))
+				goto err;
+			if (!EVP_DigestFinal_ex(&c, &(md_buf[0]), &mds))
+				goto err;
+		}
+		i = 0;
+		if (nkey) {
+			for (;;) {
+				if (nkey == 0)
+					break;
+				if (i == mds)
+					break;
+				if (key != NULL)
+					*(key++) = md_buf[i];
+				nkey--;
+				i++;
+			}
+		}
+		if (niv && (i != mds)) {
+			for (;;) {
+				if (niv == 0)
+					break;
+				if (i == mds)
+					break;
+				if (iv != NULL)
+					*(iv++) = md_buf[i];
+				niv--;
+				i++;
+			}
+		}
+		if ((nkey == 0) && (niv == 0))
+			break;
+	}
+	rv = type->key_len;
+
+err:
+	EVP_MD_CTX_cleanup(&c);
+	explicit_bzero(md_buf, sizeof md_buf);
+	return rv;
+}
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
new file mode 100644
index 0000000..f4e46ae
--- /dev/null
+++ b/crypto/evp/evp_lib.c
@@ -0,0 +1,572 @@
+/* $OpenBSD: evp_lib.c,v 1.28 2023/09/28 11:29:10 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+int
+EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+	int ret;
+
+	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)
+		ret = EVP_CIPHER_set_asn1_iv(c, type);
+	else
+		ret = -1;
+	return (ret);
+}
+
+int
+EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+	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)
+		ret = EVP_CIPHER_get_asn1_iv(c, type);
+	else
+		ret = -1;
+	return (ret);
+}
+
+int
+EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+{
+	int i = 0;
+	unsigned int l;
+
+	if (type != NULL) {
+		l = EVP_CIPHER_CTX_iv_length(c);
+		if (l > sizeof(c->iv)) {
+			EVPerror(EVP_R_IV_TOO_LARGE);
+			return 0;
+		}
+		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 i = 0;
+	unsigned int j;
+
+	if (type != NULL) {
+		j = EVP_CIPHER_CTX_iv_length(c);
+		if (j > sizeof(c->iv)) {
+			EVPerror(EVP_R_IV_TOO_LARGE);
+			return 0;
+		}
+		i = ASN1_TYPE_set_octetstring(type, c->oiv, j);
+	}
+	return (i);
+}
+
+/* Convert the various cipher NIDs and dummies to a proper OID NID */
+int
+EVP_CIPHER_type(const EVP_CIPHER *ctx)
+{
+	int nid;
+	ASN1_OBJECT *otmp;
+	nid = EVP_CIPHER_nid(ctx);
+
+	switch (nid) {
+	case NID_rc2_cbc:
+	case NID_rc2_64_cbc:
+	case NID_rc2_40_cbc:
+		return NID_rc2_cbc;
+
+	case NID_rc4:
+	case NID_rc4_40:
+		return NID_rc4;
+
+	case NID_aes_128_cfb128:
+	case NID_aes_128_cfb8:
+	case NID_aes_128_cfb1:
+		return NID_aes_128_cfb128;
+
+	case NID_aes_192_cfb128:
+	case NID_aes_192_cfb8:
+	case NID_aes_192_cfb1:
+		return NID_aes_192_cfb128;
+
+	case NID_aes_256_cfb128:
+	case NID_aes_256_cfb8:
+	case NID_aes_256_cfb1:
+		return NID_aes_256_cfb128;
+
+	case NID_des_cfb64:
+	case NID_des_cfb8:
+	case NID_des_cfb1:
+		return NID_des_cfb64;
+
+	case NID_des_ede3_cfb64:
+	case NID_des_ede3_cfb8:
+	case NID_des_ede3_cfb1:
+		return NID_des_cfb64;
+
+	default:
+		/* Check it has an OID and it is valid */
+		otmp = OBJ_nid2obj(nid);
+		if (!otmp || !otmp->data)
+			nid = NID_undef;
+		ASN1_OBJECT_free(otmp);
+		return nid;
+	}
+}
+
+int
+EVP_CIPHER_block_size(const EVP_CIPHER *e)
+{
+	return e->block_size;
+}
+
+int
+EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->cipher->block_size;
+}
+
+int
+EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
+    unsigned int inl)
+{
+	return ctx->cipher->do_cipher(ctx, out, in, inl);
+}
+
+const EVP_CIPHER *
+EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->cipher;
+}
+
+int
+EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->encrypt;
+}
+
+unsigned long
+EVP_CIPHER_flags(const EVP_CIPHER *cipher)
+{
+	return cipher->flags;
+}
+
+unsigned long
+EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->cipher->flags;
+}
+
+void *
+EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->app_data;
+}
+
+void
+EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data)
+{
+	ctx->app_data = data;
+}
+
+void *
+EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->cipher_data;
+}
+
+void *
+EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
+{
+	void *old_cipher_data;
+
+	old_cipher_data = ctx->cipher_data;
+	ctx->cipher_data = cipher_data;
+
+	return old_cipher_data;
+}
+
+int
+EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
+{
+	return cipher->iv_len;
+}
+
+int
+EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
+{
+	int iv_length = 0;
+
+	if ((ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_IV_LENGTH) == 0)
+		return ctx->cipher->iv_len;
+
+	/*
+	 * XXX - sanity would suggest to pass the size of the pointer along,
+	 * but unfortunately we have to match the other crowd.
+	 */
+	if (EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, 0,
+	    &iv_length) != 1)
+		return -1;
+
+	return iv_length;
+}
+
+unsigned char *
+EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx)
+{
+	return ctx->buf;
+}
+
+int
+EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
+{
+	return cipher->key_len;
+}
+
+int
+EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->key_len;
+}
+
+int
+EVP_CIPHER_nid(const EVP_CIPHER *cipher)
+{
+	return cipher->nid;
+}
+
+int
+EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
+{
+	return ctx->cipher->nid;
+}
+
+int
+EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
+{
+	if (ctx == NULL || len != EVP_CIPHER_CTX_iv_length(ctx))
+		return 0;
+	if (len > EVP_MAX_IV_LENGTH)
+		return 0; /* sanity check; shouldn't happen */
+	/*
+	 * Skip the memcpy entirely when the requested IV length is zero,
+	 * since the iv pointer may be NULL or invalid.
+	 */
+	if (len != 0) {
+		if (iv == NULL)
+			return 0;
+		memcpy(iv, ctx->iv, len);
+	}
+	return 1;
+}
+
+int
+EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, const unsigned char *iv, size_t len)
+{
+	if (ctx == NULL || len != EVP_CIPHER_CTX_iv_length(ctx))
+		return 0;
+	if (len > EVP_MAX_IV_LENGTH)
+		return 0; /* sanity check; shouldn't happen */
+	/*
+	 * Skip the memcpy entirely when the requested IV length is zero,
+	 * since the iv pointer may be NULL or invalid.
+	 */
+	if (len != 0) {
+		if (iv == NULL)
+			return 0;
+		memcpy(ctx->iv, iv, len);
+	}
+	return 1;
+}
+
+int
+EVP_MD_block_size(const EVP_MD *md)
+{
+	return md->block_size;
+}
+
+int
+EVP_MD_type(const EVP_MD *md)
+{
+	return md->type;
+}
+
+int
+EVP_MD_pkey_type(const EVP_MD *md)
+{
+	return md->pkey_type;
+}
+
+int
+EVP_MD_size(const EVP_MD *md)
+{
+	if (!md) {
+		EVPerror(EVP_R_MESSAGE_DIGEST_IS_NULL);
+		return -1;
+	}
+	return md->md_size;
+}
+
+unsigned long
+EVP_MD_flags(const EVP_MD *md)
+{
+	return md->flags;
+}
+
+EVP_MD *
+EVP_MD_meth_new(int md_type, int pkey_type)
+{
+	EVP_MD *md;
+
+	if ((md = calloc(1, sizeof(*md))) == NULL)
+		return NULL;
+
+	md->type = md_type;
+	md->pkey_type = pkey_type;
+
+	return md;
+}
+
+EVP_MD *
+EVP_MD_meth_dup(const EVP_MD *md)
+{
+	EVP_MD *to;
+
+	if ((to = EVP_MD_meth_new(md->type, md->pkey_type)) == NULL)
+		return NULL;
+
+	memcpy(to, md, sizeof(*to));
+
+	return to;
+}
+
+void
+EVP_MD_meth_free(EVP_MD *md)
+{
+	freezero(md, sizeof(*md));
+}
+
+int
+EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize)
+{
+	md->block_size = blocksize;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_result_size(EVP_MD *md, int result_size)
+{
+	md->md_size = result_size;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize)
+{
+	md->ctx_size = datasize;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags)
+{
+	md->flags = flags;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx))
+{
+	md->init = init;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_update(EVP_MD *md,
+    int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count))
+{
+	md->update = update;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_final(EVP_MD *md,
+    int (*final)(EVP_MD_CTX *ctx, unsigned char *md))
+{
+	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))
+{
+	md->copy = copy;
+	return 1;
+}
+
+int
+EVP_MD_meth_set_cleanup(EVP_MD *md,
+    int (*cleanup)(EVP_MD_CTX *ctx))
+{
+	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))
+{
+	md->md_ctrl = ctrl;
+	return 1;
+}
+
+const EVP_MD *
+EVP_MD_CTX_md(const EVP_MD_CTX *ctx)
+{
+	if (!ctx)
+		return NULL;
+	return ctx->digest;
+}
+
+void *
+EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx)
+{
+	return ctx->md_data;
+}
+
+EVP_PKEY_CTX *
+EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx)
+{
+	return ctx->pctx;
+}
+
+void
+EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
+{
+	if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) {
+		EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+	} else {
+		EVP_PKEY_CTX_free(ctx->pctx);
+	}
+
+	ctx->pctx = pctx;
+
+	if (pctx != NULL) {
+		/*
+		 * For unclear reasons it was decided that the caller keeps
+		 * ownership of pctx. So a flag was invented to make sure we
+		 * don't free it in EVP_MD_CTX_cleanup(). We also need to
+		 * unset it in EVP_MD_CTX_copy_ex(). Fortunately, the flag
+		 * isn't public...
+		 */
+		EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+	}
+}
+
+void
+EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags)
+{
+	ctx->flags |= flags;
+}
+
+void
+EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags)
+{
+	ctx->flags &= ~flags;
+}
+
+int
+EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags)
+{
+	return (ctx->flags & flags);
+}
+
+void
+EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags)
+{
+	ctx->flags |= flags;
+}
+
+void
+EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags)
+{
+	ctx->flags &= ~flags;
+}
+
+int
+EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
+{
+	return (ctx->flags & flags);
+}
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
new file mode 100644
index 0000000..015fbb5
--- /dev/null
+++ b/crypto/evp/evp_local.h
@@ -0,0 +1,330 @@
+/* $OpenBSD: evp_local.h,v 1.5 2023/09/28 11:29:10 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_EVP_LOCAL_H
+#define HEADER_EVP_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+/* XXX - move these to evp.h after unlock. */
+#define	EVP_CTRL_GET_IVLEN		0x25
+#define	EVP_CIPH_FLAG_CUSTOM_IV_LENGTH	0x400000
+
+#define	EVP_CTRL_AEAD_GET_IVLEN		EVP_CTRL_GET_IVLEN
+
+/*
+ * Don't free md_ctx->pctx in EVP_MD_CTX_cleanup().  Needed for ownership
+ * handling in EVP_MD_CTX_set_pkey_ctx().
+ */
+#define EVP_MD_CTX_FLAG_KEEP_PKEY_CTX   0x0400
+
+typedef int evp_sign_method(int type, const unsigned char *m,
+    unsigned int m_length, unsigned char *sigret, unsigned int *siglen,
+    void *key);
+typedef int evp_verify_method(int type, const unsigned char *m,
+    unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen,
+    void *key);
+
+struct ecx_key_st {
+	int nid;
+	int key_len;
+	uint8_t *priv_key;
+	size_t priv_key_len;
+	uint8_t *pub_key;
+	size_t pub_key_len;
+};
+
+/* Type needs to be a bit field
+ * Sub-type needs to be for variations on the method, as in, can it do
+ * arbitrary encryption.... */
+struct evp_pkey_st {
+	int type;
+	int save_type;
+	int references;
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	ENGINE *engine;
+	union	{
+		void *ptr;
+#ifndef OPENSSL_NO_RSA
+		struct rsa_st *rsa;	/* RSA */
+#endif
+#ifndef OPENSSL_NO_DSA
+		struct dsa_st *dsa;	/* DSA */
+#endif
+#ifndef OPENSSL_NO_DH
+		struct dh_st *dh;	/* DH */
+#endif
+#ifndef OPENSSL_NO_EC
+		struct ec_key_st *ec;	/* ECC */
+		struct ecx_key_st *ecx;	/* ECX */
+#endif
+#ifndef OPENSSL_NO_GOST
+		struct gost_key_st *gost; /* GOST */
+#endif
+	} pkey;
+	int save_parameters;
+	STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */
+} /* EVP_PKEY */;
+
+struct evp_md_st {
+	int type;
+	int pkey_type;
+	int md_size;
+	unsigned long flags;
+	int (*init)(EVP_MD_CTX *ctx);
+	int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
+	int (*final)(EVP_MD_CTX *ctx, unsigned char *md);
+	int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from);
+	int (*cleanup)(EVP_MD_CTX *ctx);
+
+	int block_size;
+	int ctx_size; /* how big does the ctx->md_data need to be */
+	/* control function */
+	int (*md_ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
+} /* EVP_MD */;
+
+struct evp_md_ctx_st {
+	const EVP_MD *digest;
+	ENGINE *engine; /* functional reference if 'digest' is ENGINE-provided */
+	unsigned long flags;
+	void *md_data;
+	/* Public key context for sign/verify */
+	EVP_PKEY_CTX *pctx;
+	/* Update function: usually copied from EVP_MD */
+	int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count);
+} /* EVP_MD_CTX */;
+
+struct evp_cipher_st {
+	int nid;
+	int block_size;
+	int key_len;		/* Default value for variable length ciphers */
+	int iv_len;
+	unsigned long flags;	/* Various flags */
+	int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+	    const unsigned char *iv, int enc);	/* init key */
+	int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out,
+	    const unsigned char *in, size_t inl);/* encrypt/decrypt data */
+	int (*cleanup)(EVP_CIPHER_CTX *); /* cleanup ctx */
+	int ctx_size;		/* how big ctx->cipher_data needs to be */
+	int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Populate a ASN1_TYPE with parameters */
+	int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *); /* Get parameters from a ASN1_TYPE */
+	int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr); /* Miscellaneous operations */
+	void *app_data;		/* Application data */
+} /* EVP_CIPHER */;
+
+struct evp_cipher_ctx_st {
+	const EVP_CIPHER *cipher;
+	ENGINE *engine;	/* functional reference if 'cipher' is ENGINE-provided */
+	int encrypt;		/* encrypt or decrypt */
+	int buf_len;		/* number we have left */
+
+	unsigned char  oiv[EVP_MAX_IV_LENGTH];	/* original iv */
+	unsigned char  iv[EVP_MAX_IV_LENGTH];	/* working iv */
+	unsigned char buf[EVP_MAX_BLOCK_LENGTH];/* saved partial block */
+	int num;				/* used by cfb/ofb/ctr mode */
+
+	void *app_data;		/* application stuff */
+	int key_len;		/* May change for variable length cipher */
+	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 */
+} /* EVP_CIPHER_CTX */;
+
+struct evp_Encode_Ctx_st {
+
+	int num;	/* number saved in a partial encode/decode */
+	int length;	/* The length is either the output line length
+			 * (in input bytes) or the shortest input line
+			 * length that is ok.  Once decoding begins,
+			 * the length is adjusted up each time a longer
+			 * line is decoded */
+	unsigned char enc_data[80];	/* data to encode */
+	int line_num;	/* number read on current line */
+	int expect_nl;
+} /* EVP_ENCODE_CTX */;
+
+#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2))
+
+struct evp_pkey_ctx_st {
+	/* Method associated with this operation */
+	const EVP_PKEY_METHOD *pmeth;
+	/* Engine that implements this method or NULL if builtin */
+	ENGINE *engine;
+	/* Key: may be NULL */
+	EVP_PKEY *pkey;
+	/* Peer key for key agreement, may be NULL */
+	EVP_PKEY *peerkey;
+	/* Actual operation */
+	int operation;
+	/* Algorithm specific data */
+	void *data;
+	/* Application specific data */
+	void *app_data;
+	/* Keygen callback */
+	EVP_PKEY_gen_cb *pkey_gencb;
+	/* implementation specific keygen data */
+	int *keygen_info;
+	int keygen_info_count;
+} /* EVP_PKEY_CTX */;
+
+#define EVP_PKEY_FLAG_DYNAMIC	1
+
+struct evp_pkey_method_st {
+	int pkey_id;
+	int flags;
+
+	int (*init)(EVP_PKEY_CTX *ctx);
+	int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
+	void (*cleanup)(EVP_PKEY_CTX *ctx);
+
+	int (*paramgen_init)(EVP_PKEY_CTX *ctx);
+	int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
+
+	int (*keygen_init)(EVP_PKEY_CTX *ctx);
+	int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
+
+	int (*sign_init)(EVP_PKEY_CTX *ctx);
+	int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+	    const unsigned char *tbs, size_t tbslen);
+
+	int (*verify_init)(EVP_PKEY_CTX *ctx);
+	int (*verify)(EVP_PKEY_CTX *ctx,
+	    const unsigned char *sig, size_t siglen,
+	    const unsigned char *tbs, size_t tbslen);
+
+	int (*verify_recover_init)(EVP_PKEY_CTX *ctx);
+	int (*verify_recover)(EVP_PKEY_CTX *ctx,
+	    unsigned char *rout, size_t *routlen,
+	    const unsigned char *sig, size_t siglen);
+
+	int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
+	int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+	    EVP_MD_CTX *mctx);
+
+	int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
+	int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig,
+	    int siglen, EVP_MD_CTX *mctx);
+
+	int (*encrypt_init)(EVP_PKEY_CTX *ctx);
+	int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+	    const unsigned char *in, size_t inlen);
+
+	int (*decrypt_init)(EVP_PKEY_CTX *ctx);
+	int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+	    const unsigned char *in, size_t inlen);
+
+	int (*derive_init)(EVP_PKEY_CTX *ctx);
+	int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+
+	int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
+	int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value);
+
+	int (*digestsign)(EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
+	    const unsigned char *tbs, size_t tbslen);
+	int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
+	    size_t siglen, const unsigned char *tbs, size_t tbslen);
+
+	int (*check)(EVP_PKEY *pkey);
+	int (*public_check)(EVP_PKEY *pkey);
+	int (*param_check)(EVP_PKEY *pkey);
+} /* EVP_PKEY_METHOD */;
+
+void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx);
+
+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);
+
+/* EVP_AEAD represents a specific AEAD algorithm. */
+struct evp_aead_st {
+	unsigned char key_len;
+	unsigned char nonce_len;
+	unsigned char overhead;
+	unsigned char max_tag_len;
+
+	int (*init)(struct evp_aead_ctx_st*, const unsigned char *key,
+	    size_t key_len, size_t tag_len);
+	void (*cleanup)(struct evp_aead_ctx_st*);
+
+	int (*seal)(const struct evp_aead_ctx_st *ctx, unsigned char *out,
+	    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+	    size_t nonce_len, const unsigned char *in, size_t in_len,
+	    const unsigned char *ad, size_t ad_len);
+
+	int (*open)(const struct evp_aead_ctx_st *ctx, unsigned char *out,
+	    size_t *out_len, size_t max_out_len, const unsigned char *nonce,
+	    size_t nonce_len, const unsigned char *in, size_t in_len,
+	    const unsigned char *ad, size_t ad_len);
+};
+
+/* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key
+ * and message-independent IV. */
+struct evp_aead_ctx_st {
+	const EVP_AEAD *aead;
+	/* aead_state is an opaque pointer to the AEAD specific state. */
+	void *aead_state;
+};
+
+int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str);
+int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex);
+int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md_name);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_EVP_LOCAL_H */
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
new file mode 100644
index 0000000..4a23a98
--- /dev/null
+++ b/crypto/evp/evp_pbe.c
@@ -0,0 +1,312 @@
+/* $OpenBSD: evp_pbe.c,v 1.29 2023/07/07 19:37:53 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* Password based encryption (PBE) functions */
+
+DECLARE_STACK_OF(EVP_PBE_CTL)
+static STACK_OF(EVP_PBE_CTL) *pbe_algs;
+
+/* Setup a cipher context from a PBE algorithm */
+
+typedef struct {
+	int pbe_type;
+	int pbe_nid;
+	int cipher_nid;
+	int md_nid;
+	EVP_PBE_KEYGEN *keygen;
+} EVP_PBE_CTL;
+
+static const EVP_PBE_CTL builtin_pbe[] = {
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC, NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC, NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC, NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+
+#ifndef OPENSSL_NO_HMAC
+	{EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen},
+#endif
+
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4, NID_rc4, NID_sha1, PKCS12_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4, NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC, NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC, NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC, NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen},
+
+#ifndef OPENSSL_NO_HMAC
+	{EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen},
+#endif
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC, NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC, NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen},
+	{EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC, NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen},
+
+
+	{EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0},
+	{EVP_PBE_TYPE_PRF, NID_hmacWithMD5, -1, NID_md5, 0},
+	{EVP_PBE_TYPE_PRF, NID_hmacWithSHA224, -1, NID_sha224, 0},
+	{EVP_PBE_TYPE_PRF, NID_hmacWithSHA256, -1, NID_sha256, 0},
+	{EVP_PBE_TYPE_PRF, NID_hmacWithSHA384, -1, NID_sha384, 0},
+	{EVP_PBE_TYPE_PRF, NID_hmacWithSHA512, -1, NID_sha512, 0},
+	{EVP_PBE_TYPE_PRF, NID_id_HMACGostR3411_94, -1, NID_id_GostR3411_94, 0},
+	{EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_12_256, -1, NID_id_tc26_gost3411_2012_256, 0},
+	{EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_12_512, -1, NID_id_tc26_gost3411_2012_512, 0},
+};
+
+int
+EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
+    ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
+{
+	const EVP_CIPHER *cipher;
+	const EVP_MD *md;
+	int cipher_nid, md_nid;
+	EVP_PBE_KEYGEN *keygen;
+
+	if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
+	    &cipher_nid, &md_nid, &keygen)) {
+		char obj_tmp[80];
+		EVPerror(EVP_R_UNKNOWN_PBE_ALGORITHM);
+		if (!pbe_obj)
+			strlcpy(obj_tmp, "NULL", sizeof obj_tmp);
+		else
+			i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj);
+		ERR_asprintf_error_data("TYPE=%s", obj_tmp);
+		return 0;
+	}
+
+	if (!pass)
+		passlen = 0;
+	else if (passlen == -1)
+		passlen = strlen(pass);
+
+	if (cipher_nid == -1)
+		cipher = NULL;
+	else {
+		cipher = EVP_get_cipherbynid(cipher_nid);
+		if (!cipher) {
+			EVPerror(EVP_R_UNKNOWN_CIPHER);
+			return 0;
+		}
+	}
+
+	if (md_nid == -1)
+		md = NULL;
+	else {
+		md = EVP_get_digestbynid(md_nid);
+		if (!md) {
+			EVPerror(EVP_R_UNKNOWN_DIGEST);
+			return 0;
+		}
+	}
+
+	if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) {
+		EVPerror(EVP_R_KEYGEN_FAILURE);
+		return 0;
+	}
+	return 1;
+}
+
+static int pbe2_cmp_BSEARCH_CMP_FN(const void *, const void *);
+static int pbe2_cmp(EVP_PBE_CTL const *, EVP_PBE_CTL const *);
+static EVP_PBE_CTL *OBJ_bsearch_pbe2(EVP_PBE_CTL *key, EVP_PBE_CTL const *base, int num);
+
+static int
+pbe2_cmp(const EVP_PBE_CTL *pbe1, const EVP_PBE_CTL *pbe2)
+{
+	int ret = pbe1->pbe_type - pbe2->pbe_type;
+
+	if (ret)
+		return ret;
+	else
+		return pbe1->pbe_nid - pbe2->pbe_nid;
+}
+
+
+static int
+pbe2_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
+{
+	EVP_PBE_CTL const *a = a_;
+	EVP_PBE_CTL const *b = b_;
+	return pbe2_cmp(a, b);
+}
+
+static EVP_PBE_CTL *
+OBJ_bsearch_pbe2(EVP_PBE_CTL *key, EVP_PBE_CTL const *base, int num)
+{
+	return (EVP_PBE_CTL *)OBJ_bsearch_(key, base, num, sizeof(EVP_PBE_CTL),
+	    pbe2_cmp_BSEARCH_CMP_FN);
+}
+
+static int
+pbe_cmp(const EVP_PBE_CTL * const *a, const EVP_PBE_CTL * const *b)
+{
+	int ret = (*a)->pbe_type - (*b)->pbe_type;
+
+	if (ret)
+		return ret;
+	else
+		return (*a)->pbe_nid - (*b)->pbe_nid;
+}
+
+/* Add a PBE algorithm */
+
+int
+EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, int md_nid,
+    EVP_PBE_KEYGEN *keygen)
+{
+	EVP_PBE_CTL *pbe_tmp;
+
+	if (pbe_algs == NULL) {
+		pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp);
+		if (pbe_algs == NULL) {
+			EVPerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+	pbe_tmp = malloc(sizeof(EVP_PBE_CTL));
+	if (pbe_tmp == NULL) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	pbe_tmp->pbe_type = pbe_type;
+	pbe_tmp->pbe_nid = pbe_nid;
+	pbe_tmp->cipher_nid = cipher_nid;
+	pbe_tmp->md_nid = md_nid;
+	pbe_tmp->keygen = keygen;
+
+	if (sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp) == 0) {
+		free(pbe_tmp);
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	return 1;
+}
+
+int
+EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
+    EVP_PBE_KEYGEN *keygen)
+{
+	int cipher_nid, md_nid;
+
+	if (cipher)
+		cipher_nid = EVP_CIPHER_nid(cipher);
+	else
+		cipher_nid = -1;
+	if (md)
+		md_nid = EVP_MD_type(md);
+	else
+		md_nid = -1;
+
+	return EVP_PBE_alg_add_type(EVP_PBE_TYPE_OUTER, nid,
+	    cipher_nid, md_nid, keygen);
+}
+
+int
+EVP_PBE_find(int type, int pbe_nid,
+    int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen)
+{
+	EVP_PBE_CTL *pbetmp = NULL, pbelu;
+	int i;
+	if (pbe_nid == NID_undef)
+		return 0;
+
+	pbelu.pbe_type = type;
+	pbelu.pbe_nid = pbe_nid;
+
+	if (pbe_algs) {
+		i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu);
+		if (i != -1)
+			pbetmp = sk_EVP_PBE_CTL_value (pbe_algs, i);
+	}
+	if (pbetmp == NULL) {
+		pbetmp = OBJ_bsearch_pbe2(&pbelu, builtin_pbe,
+		    sizeof(builtin_pbe)/sizeof(EVP_PBE_CTL));
+	}
+	if (pbetmp == NULL)
+		return 0;
+	if (pcnid)
+		*pcnid = pbetmp->cipher_nid;
+	if (pmnid)
+		*pmnid = pbetmp->md_nid;
+	if (pkeygen)
+		*pkeygen = pbetmp->keygen;
+	return 1;
+}
+
+static void
+free_evp_pbe_ctl(EVP_PBE_CTL *pbe)
+{
+	free(pbe);
+}
+
+void
+EVP_PBE_cleanup(void)
+{
+	sk_EVP_PBE_CTL_pop_free(pbe_algs, free_evp_pbe_ctl);
+	pbe_algs = NULL;
+}
diff --git a/crypto/evp/evp_pkey.c b/crypto/evp/evp_pkey.c
new file mode 100644
index 0000000..9e29a1a
--- /dev/null
+++ b/crypto/evp/evp_pkey.c
@@ -0,0 +1,209 @@
+/* $OpenBSD: evp_pkey.c,v 1.27 2023/07/07 19:37:53 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+/* Extract a private key from a PKCS8 structure */
+
+EVP_PKEY *
+EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
+{
+	EVP_PKEY *pkey = NULL;
+	const ASN1_OBJECT *algoid;
+	char obj_tmp[80];
+
+	if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8))
+		return NULL;
+
+	if (!(pkey = EVP_PKEY_new())) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
+		EVPerror(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+		i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
+		ERR_asprintf_error_data("TYPE=%s", obj_tmp);
+		goto error;
+	}
+
+	if (pkey->ameth->priv_decode) {
+		if (!pkey->ameth->priv_decode(pkey, p8)) {
+			EVPerror(EVP_R_PRIVATE_KEY_DECODE_ERROR);
+			goto error;
+		}
+	} else {
+		EVPerror(EVP_R_METHOD_NOT_SUPPORTED);
+		goto error;
+	}
+
+	return pkey;
+
+error:
+	EVP_PKEY_free(pkey);
+	return NULL;
+}
+
+/* Turn a private key into a PKCS8 structure */
+
+PKCS8_PRIV_KEY_INFO *
+EVP_PKEY2PKCS8(EVP_PKEY *pkey)
+{
+	PKCS8_PRIV_KEY_INFO *p8;
+
+	if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (pkey->ameth) {
+		if (pkey->ameth->priv_encode) {
+			if (!pkey->ameth->priv_encode(p8, pkey)) {
+				EVPerror(EVP_R_PRIVATE_KEY_ENCODE_ERROR);
+				goto error;
+			}
+		} else {
+			EVPerror(EVP_R_METHOD_NOT_SUPPORTED);
+			goto error;
+		}
+	} else {
+		EVPerror(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
+		goto error;
+	}
+	return p8;
+
+error:
+	PKCS8_PRIV_KEY_INFO_free(p8);
+	return NULL;
+}
+
+/* EVP_PKEY attribute functions */
+
+int
+EVP_PKEY_get_attr_count(const EVP_PKEY *key)
+{
+	return X509at_get_attr_count(key->attributes);
+}
+
+int
+EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos)
+{
+	return X509at_get_attr_by_NID(key->attributes, nid, lastpos);
+}
+
+int
+EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos);
+}
+
+X509_ATTRIBUTE *
+EVP_PKEY_get_attr(const EVP_PKEY *key, int loc)
+{
+	return X509at_get_attr(key->attributes, loc);
+}
+
+X509_ATTRIBUTE *
+EVP_PKEY_delete_attr(EVP_PKEY *key, int loc)
+{
+	return X509at_delete_attr(key->attributes, loc);
+}
+
+int
+EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr)
+{
+	if (X509at_add1_attr(&key->attributes, attr))
+		return 1;
+	return 0;
+}
+
+int
+EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, const ASN1_OBJECT *obj, int type,
+    const unsigned char *bytes, int len)
+{
+	if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len))
+		return 1;
+	return 0;
+}
+
+int
+EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, int nid, int type,
+    const unsigned char *bytes, int len)
+{
+	if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len))
+		return 1;
+	return 0;
+}
+
+int
+EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, const char *attrname, int type,
+    const unsigned char *bytes, int len)
+{
+	if (X509at_add1_attr_by_txt(&key->attributes, attrname, type,
+	    bytes, len))
+		return 1;
+	return 0;
+}
diff --git a/crypto/evp/m_gost2814789.c b/crypto/evp/m_gost2814789.c
new file mode 100644
index 0000000..9b8a09e
--- /dev/null
+++ b/crypto/evp/m_gost2814789.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: m_gost2814789.c,v 1.6 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+gost2814789_init(EVP_MD_CTX *ctx)
+{
+	return GOST2814789IMIT_Init(ctx->md_data,
+	    NID_id_Gost28147_89_CryptoPro_A_ParamSet);
+}
+
+static int
+gost2814789_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return GOST2814789IMIT_Update(ctx->md_data, data, count);
+}
+
+static int
+gost2814789_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return GOST2814789IMIT_Final(md, ctx->md_data);
+}
+
+static int
+gost2814789_md_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
+{
+	GOST2814789IMIT_CTX *gctx = ctx->md_data;
+
+	switch (cmd) {
+	case EVP_MD_CTRL_SET_KEY:
+		return Gost2814789_set_key(&gctx->cipher, p2, p1);
+	case EVP_MD_CTRL_GOST_SET_SBOX:
+		return Gost2814789_set_sbox(&gctx->cipher, p1);
+	}
+	return -2;
+}
+
+static const EVP_MD gost2814789imit_md = {
+	.type = NID_id_Gost28147_89_MAC,
+	.pkey_type = NID_undef,
+	.md_size = GOST2814789IMIT_LENGTH,
+	.flags = 0,
+	.init = gost2814789_init,
+	.update = gost2814789_update,
+	.final = gost2814789_final,
+	.block_size = GOST2814789IMIT_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(GOST2814789IMIT_CTX),
+	.md_ctrl = gost2814789_md_ctrl,
+};
+
+const EVP_MD *
+EVP_gost2814789imit(void)
+{
+	return (&gost2814789imit_md);
+}
+#endif
diff --git a/crypto/evp/m_gostr341194.c b/crypto/evp/m_gostr341194.c
new file mode 100644
index 0000000..723349a
--- /dev/null
+++ b/crypto/evp/m_gostr341194.c
@@ -0,0 +1,100 @@
+/* $OpenBSD: m_gostr341194.c,v 1.7 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+gostr341194_init(EVP_MD_CTX *ctx)
+{
+	return GOSTR341194_Init(ctx->md_data,
+	    NID_id_GostR3411_94_CryptoProParamSet);
+}
+
+static int
+gostr341194_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return GOSTR341194_Update(ctx->md_data, data, count);
+}
+
+static int
+gostr341194_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return GOSTR341194_Final(md, ctx->md_data);
+}
+
+static const EVP_MD gostr341194_md = {
+	.type = NID_id_GostR3411_94,
+	.pkey_type = NID_undef,
+	.md_size = GOSTR341194_LENGTH,
+	.flags = 0,
+	.init = gostr341194_init,
+	.update = gostr341194_update,
+	.final = gostr341194_final,
+	.block_size = GOSTR341194_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(GOSTR341194_CTX),
+};
+
+const EVP_MD *
+EVP_gostr341194(void)
+{
+	return (&gostr341194_md);
+}
+#endif
diff --git a/crypto/evp/m_md4.c b/crypto/evp/m_md4.c
new file mode 100644
index 0000000..199dba8
--- /dev/null
+++ b/crypto/evp/m_md4.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: m_md4.c,v 1.21 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_MD4
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+static int
+init(EVP_MD_CTX *ctx)
+{
+	return MD4_Init(ctx->md_data);
+}
+
+static int
+update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return MD4_Update(ctx->md_data, data, count);
+}
+
+static int
+final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return MD4_Final(md, ctx->md_data);
+}
+
+static const EVP_MD md4_md = {
+	.type = NID_md4,
+	.pkey_type = NID_md4WithRSAEncryption,
+	.md_size = MD4_DIGEST_LENGTH,
+	.flags = 0,
+	.init = init,
+	.update = update,
+	.final = final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = MD4_CBLOCK,
+	.ctx_size = 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
new file mode 100644
index 0000000..0dfad89
--- /dev/null
+++ b/crypto/evp/m_md5.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: m_md5.c,v 1.20 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_MD5
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+static int
+init(EVP_MD_CTX *ctx)
+{
+	return MD5_Init(ctx->md_data);
+}
+
+static int
+update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return MD5_Update(ctx->md_data, data, count);
+}
+
+static int
+final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return MD5_Final(md, ctx->md_data);
+}
+
+static const EVP_MD md5_md = {
+	.type = NID_md5,
+	.pkey_type = NID_md5WithRSAEncryption,
+	.md_size = MD5_DIGEST_LENGTH,
+	.flags = 0,
+	.init = init,
+	.update = update,
+	.final = final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = MD5_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(MD5_CTX),
+};
+
+const EVP_MD *
+EVP_md5(void)
+{
+	return (&md5_md);
+}
+#endif
diff --git a/crypto/evp/m_md5_sha1.c b/crypto/evp/m_md5_sha1.c
new file mode 100644
index 0000000..7dd1ae1
--- /dev/null
+++ b/crypto/evp/m_md5_sha1.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: m_md5_sha1.c,v 1.8 2023/09/02 04:55:18 tb Exp $ */
+/*
+ * Copyright (c) 2017 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+struct md5_sha1_ctx {
+	MD5_CTX md5;
+	SHA_CTX sha1;
+};
+
+static int
+md5_sha1_init(EVP_MD_CTX *ctx)
+{
+	struct md5_sha1_ctx *mdctx = ctx->md_data;
+
+	if (!MD5_Init(&mdctx->md5))
+		return 0;
+	if (!SHA1_Init(&mdctx->sha1))
+		return 0;
+
+	return 1;
+}
+
+static int
+md5_sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	struct md5_sha1_ctx *mdctx = ctx->md_data;
+
+	if (!MD5_Update(&mdctx->md5, data, count))
+		return 0;
+	if (!SHA1_Update(&mdctx->sha1, data, count))
+		return 0;
+
+	return 1;
+}
+
+static int
+md5_sha1_final(EVP_MD_CTX *ctx, unsigned char *out)
+{
+	struct md5_sha1_ctx *mdctx = ctx->md_data;
+
+	if (!MD5_Final(out, &mdctx->md5))
+		return 0;
+	if (!SHA1_Final(out + MD5_DIGEST_LENGTH, &mdctx->sha1))
+		return 0;
+
+	return 1;
+}
+
+static const EVP_MD md5_sha1_md = {
+        .type = NID_md5_sha1,
+        .pkey_type = NID_md5_sha1,
+        .md_size = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+        .flags = 0,
+        .init = md5_sha1_init,
+        .update = md5_sha1_update,
+        .final = md5_sha1_final,
+        .block_size = MD5_CBLOCK, /* MD5_CBLOCK == SHA_CBLOCK */
+        .ctx_size = sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx),
+};
+
+const EVP_MD *
+EVP_md5_sha1(void)
+{
+	return &md5_sha1_md;
+}
diff --git a/crypto/evp/m_null.c b/crypto/evp/m_null.c
new file mode 100644
index 0000000..28634d2
--- /dev/null
+++ b/crypto/evp/m_null.c
@@ -0,0 +1,103 @@
+/* $OpenBSD: m_null.c,v 1.14 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+init(EVP_MD_CTX *ctx)
+{
+	return 1;
+}
+
+static int
+update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return 1;
+}
+
+static int
+final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return 1;
+}
+
+static const EVP_MD null_md = {
+	.type = NID_undef,
+	.pkey_type = NID_undef,
+	.md_size = 0,
+	.flags = 0,
+	.init = init,
+	.update = update,
+	.final = final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = 0,
+	.ctx_size = sizeof(EVP_MD *),
+};
+
+const EVP_MD *
+EVP_md_null(void)
+{
+	return (&null_md);
+}
diff --git a/crypto/evp/m_ripemd.c b/crypto/evp/m_ripemd.c
new file mode 100644
index 0000000..638d0cd
--- /dev/null
+++ b/crypto/evp/m_ripemd.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: m_ripemd.c,v 1.17 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_RIPEMD
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+static int
+init(EVP_MD_CTX *ctx)
+{
+	return RIPEMD160_Init(ctx->md_data);
+}
+
+static int
+update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return RIPEMD160_Update(ctx->md_data, data, count);
+}
+
+static int
+final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return RIPEMD160_Final(md, ctx->md_data);
+}
+
+static const EVP_MD ripemd160_md = {
+	.type = NID_ripemd160,
+	.pkey_type = NID_ripemd160WithRSA,
+	.md_size = RIPEMD160_DIGEST_LENGTH,
+	.flags = 0,
+	.init = init,
+	.update = update,
+	.final = final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = RIPEMD160_CBLOCK,
+	.ctx_size = 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
new file mode 100644
index 0000000..c65e051
--- /dev/null
+++ b/crypto/evp/m_sha1.c
@@ -0,0 +1,351 @@
+/* $OpenBSD: m_sha1.c,v 1.25 2023/07/07 19:37:53 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_SHA
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+#include "sha_internal.h"
+
+static int
+sha1_init(EVP_MD_CTX *ctx)
+{
+	return SHA1_Init(ctx->md_data);
+}
+
+static int
+sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SHA1_Update(ctx->md_data, data, count);
+}
+
+static int
+sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA1_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha1_md = {
+	.type = NID_sha1,
+	.pkey_type = NID_sha1WithRSAEncryption,
+	.md_size = SHA_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha1_init,
+	.update = sha1_update,
+	.final = sha1_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA_CTX),
+};
+
+const EVP_MD *
+EVP_sha1(void)
+{
+	return &sha1_md;
+}
+#endif
+
+#ifndef OPENSSL_NO_SHA256
+static int
+sha224_init(EVP_MD_CTX *ctx)
+{
+	return SHA224_Init(ctx->md_data);
+}
+
+static int
+sha224_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	/*
+	 * Even though there're separate SHA224_[Update|Final], we call
+	 * SHA256 functions even in SHA224 context. This is what happens
+	 * there anyway, so we can spare few CPU cycles:-)
+	 */
+	return SHA256_Update(ctx->md_data, data, count);
+}
+
+static int
+sha224_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA224_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha224_md = {
+	.type = NID_sha224,
+	.pkey_type = NID_sha224WithRSAEncryption,
+	.md_size = SHA224_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha224_init,
+	.update = sha224_update,
+	.final = sha224_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA256_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA256_CTX),
+};
+
+const EVP_MD *
+EVP_sha224(void)
+{
+	return &sha224_md;
+}
+
+static int
+sha256_init(EVP_MD_CTX *ctx)
+{
+	return SHA256_Init(ctx->md_data);
+}
+
+static int
+sha256_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SHA256_Update(ctx->md_data, data, count);
+}
+
+static int
+sha256_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA256_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha256_md = {
+	.type = NID_sha256,
+	.pkey_type = NID_sha256WithRSAEncryption,
+	.md_size = SHA256_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha256_init,
+	.update = sha256_update,
+	.final = sha256_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA256_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA256_CTX),
+};
+
+const EVP_MD *
+EVP_sha256(void)
+{
+	return &sha256_md;
+}
+#endif	/* ifndef OPENSSL_NO_SHA256 */
+
+#ifndef OPENSSL_NO_SHA512
+static int
+sha384_init(EVP_MD_CTX *ctx)
+{
+	return SHA384_Init(ctx->md_data);
+}
+
+static int
+sha384_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	/* See comment in SHA224/256 section */
+	return SHA512_Update(ctx->md_data, data, count);
+}
+
+static int
+sha384_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA384_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha384_md = {
+	.type = NID_sha384,
+	.pkey_type = NID_sha384WithRSAEncryption,
+	.md_size = SHA384_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha384_init,
+	.update = sha384_update,
+	.final = sha384_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA512_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX),
+};
+
+const EVP_MD *
+EVP_sha384(void)
+{
+	return &sha384_md;
+}
+
+static int
+sha512_init(EVP_MD_CTX *ctx)
+{
+	return SHA512_Init(ctx->md_data);
+}
+
+static int
+sha512_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SHA512_Update(ctx->md_data, data, count);
+}
+
+static int
+sha512_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA512_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha512_md = {
+	.type = NID_sha512,
+	.pkey_type = NID_sha512WithRSAEncryption,
+	.md_size = SHA512_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha512_init,
+	.update = sha512_update,
+	.final = sha512_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA512_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX),
+};
+
+const EVP_MD *
+EVP_sha512(void)
+{
+	return &sha512_md;
+}
+
+static int
+sha512_224_init(EVP_MD_CTX *ctx)
+{
+	return SHA512_224_Init(ctx->md_data);
+}
+
+static int
+sha512_224_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SHA512_224_Update(ctx->md_data, data, count);
+}
+
+static int
+sha512_224_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA512_224_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha512_224_md = {
+	.type = NID_sha512_224,
+	.pkey_type = NID_sha512_224WithRSAEncryption,
+	.md_size = SHA512_224_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha512_224_init,
+	.update = sha512_224_update,
+	.final = sha512_224_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA512_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX),
+};
+
+const EVP_MD *
+EVP_sha512_224(void)
+{
+	return &sha512_224_md;
+}
+
+static int
+sha512_256_init(EVP_MD_CTX *ctx)
+{
+	return SHA512_256_Init(ctx->md_data);
+}
+
+static int
+sha512_256_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SHA512_256_Update(ctx->md_data, data, count);
+}
+
+static int
+sha512_256_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SHA512_256_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sha512_256_md = {
+	.type = NID_sha512_256,
+	.pkey_type = NID_sha512_256WithRSAEncryption,
+	.md_size = SHA512_256_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha512_256_init,
+	.update = sha512_256_update,
+	.final = sha512_256_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA512_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SHA512_CTX),
+};
+
+const EVP_MD *
+EVP_sha512_256(void)
+{
+	return &sha512_256_md;
+}
+#endif	/* ifndef OPENSSL_NO_SHA512 */
diff --git a/crypto/evp/m_sha3.c b/crypto/evp/m_sha3.c
new file mode 100644
index 0000000..67f94f7
--- /dev/null
+++ b/crypto/evp/m_sha3.c
@@ -0,0 +1,173 @@
+/* $OpenBSD: m_sha3.c,v 1.3 2023/07/07 19:37:53 beck Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include "evp_local.h"
+#include "sha3_internal.h"
+
+static int
+sha3_224_init(EVP_MD_CTX *ctx)
+{
+	return sha3_init(ctx->md_data, SHA3_224_DIGEST_LENGTH);
+}
+
+static int
+sha3_224_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return sha3_update(ctx->md_data, data, count);
+}
+
+static int
+sha3_224_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return sha3_final(md, ctx->md_data);
+}
+
+static const EVP_MD sha3_224_md = {
+	.type = NID_sha3_224,
+	.pkey_type = NID_RSA_SHA3_224,
+	.md_size = SHA3_224_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha3_224_init,
+	.update = sha3_224_update,
+	.final = sha3_224_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA3_224_BLOCK_SIZE,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(sha3_ctx),
+};
+
+const EVP_MD *
+EVP_sha3_224(void)
+{
+	return &sha3_224_md;
+}
+
+static int
+sha3_256_init(EVP_MD_CTX *ctx)
+{
+	return sha3_init(ctx->md_data, SHA3_256_DIGEST_LENGTH);
+}
+
+static int
+sha3_256_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return sha3_update(ctx->md_data, data, count);
+}
+
+static int
+sha3_256_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return sha3_final(md, ctx->md_data);
+}
+
+static const EVP_MD sha3_256_md = {
+	.type = NID_sha3_256,
+	.pkey_type = NID_RSA_SHA3_256,
+	.md_size = SHA3_256_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha3_256_init,
+	.update = sha3_256_update,
+	.final = sha3_256_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA3_256_BLOCK_SIZE,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(sha3_ctx),
+};
+
+const EVP_MD *
+EVP_sha3_256(void)
+{
+	return &sha3_256_md;
+}
+
+static int
+sha3_384_init(EVP_MD_CTX *ctx)
+{
+	return sha3_init(ctx->md_data, SHA3_384_DIGEST_LENGTH);
+}
+
+static int
+sha3_384_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return sha3_update(ctx->md_data, data, count);
+}
+
+static int
+sha3_384_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return sha3_final(md, ctx->md_data);
+}
+
+static const EVP_MD sha3_384_md = {
+	.type = NID_sha3_384,
+	.pkey_type = NID_RSA_SHA3_384,
+	.md_size = SHA3_384_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha3_384_init,
+	.update = sha3_384_update,
+	.final = sha3_384_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA3_384_BLOCK_SIZE,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(sha3_ctx),
+};
+
+const EVP_MD *
+EVP_sha3_384(void)
+{
+	return &sha3_384_md;
+}
+
+static int
+sha3_512_init(EVP_MD_CTX *ctx)
+{
+	return sha3_init(ctx->md_data, SHA3_512_DIGEST_LENGTH);
+}
+
+static int
+sha3_512_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return sha3_update(ctx->md_data, data, count);
+}
+
+static int
+sha3_512_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return sha3_final(md, ctx->md_data);
+}
+
+static const EVP_MD sha3_512_md = {
+	.type = NID_sha3_512,
+	.pkey_type = NID_RSA_SHA3_512,
+	.md_size = SHA3_512_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sha3_512_init,
+	.update = sha3_512_update,
+	.final = sha3_512_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SHA3_512_BLOCK_SIZE,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(sha3_ctx),
+};
+
+const EVP_MD *
+EVP_sha3_512(void)
+{
+	return &sha3_512_md;
+}
diff --git a/crypto/evp/m_sigver.c b/crypto/evp/m_sigver.c
new file mode 100644
index 0000000..47c01f7
--- /dev/null
+++ b/crypto/evp/m_sigver.c
@@ -0,0 +1,257 @@
+/* $OpenBSD: m_sigver.c,v 1.13 2023/07/07 19:37:53 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006,2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+update_oneshot_only(EVP_MD_CTX *ctx, const void *data, size_t datalen)
+{
+	EVPerror(EVP_R_ONLY_ONESHOT_SUPPORTED);
+	return 0;
+}
+
+static int
+do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
+    ENGINE *e, EVP_PKEY *pkey, int ver)
+{
+	if (ctx->pctx == NULL)
+		ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
+	if (ctx->pctx == NULL)
+		return 0;
+
+	if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) {
+		if (type == NULL) {
+			int def_nid;
+			if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0)
+				type = EVP_get_digestbynid(def_nid);
+		}
+
+		if (type == NULL) {
+			EVPerror(EVP_R_NO_DEFAULT_DIGEST);
+			return 0;
+		}
+	}
+
+	if (ver) {
+		if (ctx->pctx->pmeth->verifyctx_init) {
+			if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx,
+			    ctx) <=0)
+				return 0;
+			ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX;
+		} else if (ctx->pctx->pmeth->digestverify != NULL) {
+			ctx->pctx->operation = EVP_PKEY_OP_VERIFY;
+			ctx->update = update_oneshot_only;
+		} else if (EVP_PKEY_verify_init(ctx->pctx) <= 0)
+			return 0;
+	} else {
+		if (ctx->pctx->pmeth->signctx_init) {
+			if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0)
+				return 0;
+			ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX;
+		} else if (ctx->pctx->pmeth->digestsign != NULL) {
+			ctx->pctx->operation = EVP_PKEY_OP_SIGN;
+			ctx->update = update_oneshot_only;
+		} else if (EVP_PKEY_sign_init(ctx->pctx) <= 0)
+			return 0;
+	}
+	if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0)
+		return 0;
+	if (pctx)
+		*pctx = ctx->pctx;
+	if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)
+		return 1;
+	if (!EVP_DigestInit_ex(ctx, type, e))
+		return 0;
+	return 1;
+}
+
+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);
+}
+
+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);
+}
+
+int
+EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen)
+{
+	EVP_PKEY_CTX *pctx = ctx->pctx;
+	int sctx;
+	int r = 0;
+
+	if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
+		EVP_PKEY_CTX *dctx;
+
+		if (sigret == NULL)
+			return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
+
+		/* XXX - support EVP_MD_CTX_FLAG_FINALISE? */
+		if ((dctx = EVP_PKEY_CTX_dup(ctx->pctx)) == NULL)
+			return 0;
+		r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
+		EVP_PKEY_CTX_free(dctx);
+
+		return r;
+	}
+
+	if (ctx->pctx->pmeth->signctx)
+		sctx = 1;
+	else
+		sctx = 0;
+	if (sigret) {
+		EVP_MD_CTX tmp_ctx;
+		unsigned char md[EVP_MAX_MD_SIZE];
+		unsigned int mdlen = 0;
+		EVP_MD_CTX_init(&tmp_ctx);
+		if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx))
+			return 0;
+		if (sctx)
+			r = tmp_ctx.pctx->pmeth->signctx(tmp_ctx.pctx,
+			    sigret, siglen, &tmp_ctx);
+		else
+			r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+		EVP_MD_CTX_cleanup(&tmp_ctx);
+		if (sctx || !r)
+			return r;
+		if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
+			return 0;
+	} else {
+		if (sctx) {
+			if (ctx->pctx->pmeth->signctx(ctx->pctx, sigret,
+			    siglen, ctx) <= 0)
+				return 0;
+		} else {
+			int s = EVP_MD_size(ctx->digest);
+			if (s < 0 || EVP_PKEY_sign(ctx->pctx, sigret, siglen,
+			    NULL, s) <= 0)
+				return 0;
+		}
+	}
+	return 1;
+}
+
+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);
+
+	if (sigret != NULL) {
+		if (EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0)
+			return 0;
+	}
+
+	return EVP_DigestSignFinal(ctx, sigret, siglen);
+}
+
+int
+EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen)
+{
+	EVP_MD_CTX tmp_ctx;
+	unsigned char md[EVP_MAX_MD_SIZE];
+	int r;
+	unsigned int mdlen = 0;
+	int vctx;
+
+	if (ctx->pctx->pmeth->verifyctx)
+		vctx = 1;
+	else
+		vctx = 0;
+	EVP_MD_CTX_init(&tmp_ctx);
+	if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx))
+		return -1;
+	if (vctx) {
+		r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx, sig,
+		    siglen, &tmp_ctx);
+	} else
+		r = EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen);
+	EVP_MD_CTX_cleanup(&tmp_ctx);
+	if (vctx || !r)
+		return r;
+	return EVP_PKEY_verify(ctx->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);
+
+	if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0)
+		return -1;
+
+	return EVP_DigestVerifyFinal(ctx, sigret, siglen);
+}
diff --git a/crypto/evp/m_sm3.c b/crypto/evp/m_sm3.c
new file mode 100644
index 0000000..ea30d8d
--- /dev/null
+++ b/crypto/evp/m_sm3.c
@@ -0,0 +1,68 @@
+/*	$OpenBSD: m_sm3.c,v 1.6 2023/07/07 19:37:53 beck Exp $	*/
+/*
+ * Copyright (c) 2018, Ribose Inc
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_SM3
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+static int
+sm3_init(EVP_MD_CTX *ctx)
+{
+	return SM3_Init(ctx->md_data);
+}
+
+static int
+sm3_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return SM3_Update(ctx->md_data, data, count);
+}
+
+static int
+sm3_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return SM3_Final(md, ctx->md_data);
+}
+
+static const EVP_MD sm3_md = {
+	.type = NID_sm3,
+	.pkey_type = NID_sm3WithRSAEncryption,
+	.md_size = SM3_DIGEST_LENGTH,
+	.flags = EVP_MD_FLAG_DIGALGID_ABSENT,
+	.init = sm3_init,
+	.update = sm3_update,
+	.final = sm3_final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = SM3_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(SM3_CTX),
+};
+
+const EVP_MD *
+EVP_sm3(void)
+{
+	return &sm3_md;
+}
+
+#endif /* OPENSSL_NO_SM3 */
diff --git a/crypto/evp/m_streebog.c b/crypto/evp/m_streebog.c
new file mode 100644
index 0000000..48fa658
--- /dev/null
+++ b/crypto/evp/m_streebog.c
@@ -0,0 +1,133 @@
+/* $OpenBSD: m_streebog.c,v 1.7 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+streebog_init256(EVP_MD_CTX *ctx)
+{
+	return STREEBOG256_Init(ctx->md_data);
+}
+
+static int
+streebog_update256(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return STREEBOG256_Update(ctx->md_data, data, count);
+}
+
+static int
+streebog_final256(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return STREEBOG256_Final(md, ctx->md_data);
+}
+
+static int
+streebog_init512(EVP_MD_CTX *ctx)
+{
+	return STREEBOG512_Init(ctx->md_data);
+}
+
+static int
+streebog_update512(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return STREEBOG512_Update(ctx->md_data, data, count);
+}
+
+static int
+streebog_final512(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return STREEBOG512_Final(md, ctx->md_data);
+}
+
+static const EVP_MD streebog256_md = {
+	.type = NID_id_tc26_gost3411_2012_256,
+	.pkey_type = NID_undef,
+	.md_size = STREEBOG256_LENGTH,
+	.flags = 0,
+	.init = streebog_init256,
+	.update = streebog_update256,
+	.final = streebog_final256,
+	.block_size = STREEBOG_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(STREEBOG_CTX),
+};
+
+static const EVP_MD streebog512_md = {
+	.type = NID_id_tc26_gost3411_2012_512,
+	.pkey_type = NID_undef,
+	.md_size = STREEBOG512_LENGTH,
+	.flags = 0,
+	.init = streebog_init512,
+	.update = streebog_update512,
+	.final = streebog_final512,
+	.block_size = STREEBOG_CBLOCK,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(STREEBOG_CTX),
+};
+
+const EVP_MD *
+EVP_streebog256(void)
+{
+	return (&streebog256_md);
+}
+
+const EVP_MD *
+EVP_streebog512(void)
+{
+	return (&streebog512_md);
+}
+#endif
diff --git a/crypto/evp/m_wp.c b/crypto/evp/m_wp.c
new file mode 100644
index 0000000..44d13b1
--- /dev/null
+++ b/crypto/evp/m_wp.c
@@ -0,0 +1,53 @@
+/* $OpenBSD: m_wp.c,v 1.13 2023/07/07 19:37:54 beck Exp $ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_WHIRLPOOL
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+static int
+init(EVP_MD_CTX *ctx)
+{
+	return WHIRLPOOL_Init(ctx->md_data);
+}
+
+static int
+update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+	return WHIRLPOOL_Update(ctx->md_data, data, count);
+}
+
+static int
+final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+	return WHIRLPOOL_Final(md, ctx->md_data);
+}
+
+static const EVP_MD whirlpool_md = {
+	.type = NID_whirlpool,
+	.pkey_type = 0,
+	.md_size = WHIRLPOOL_DIGEST_LENGTH,
+	.flags = 0,
+	.init = init,
+	.update = update,
+	.final = final,
+	.copy = NULL,
+	.cleanup = NULL,
+	.block_size = WHIRLPOOL_BBLOCK / 8,
+	.ctx_size = sizeof(EVP_MD *) + sizeof(WHIRLPOOL_CTX),
+};
+
+const EVP_MD *
+EVP_whirlpool(void)
+{
+	return (&whirlpool_md);
+}
+#endif
diff --git a/crypto/evp/names.c b/crypto/evp/names.c
new file mode 100644
index 0000000..5242892
--- /dev/null
+++ b/crypto/evp/names.c
@@ -0,0 +1,240 @@
+/* $OpenBSD: names.c,v 1.21 2023/08/26 02:59:13 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+extern int obj_cleanup_defer;
+void check_defer(int nid);
+
+int
+EVP_add_cipher(const EVP_CIPHER *c)
+{
+	int r;
+
+	if (c == NULL)
+		return 0;
+
+	r = OBJ_NAME_add(OBJ_nid2sn(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
+	    (const char *)c);
+	if (r == 0)
+		return (0);
+	check_defer(c->nid);
+	r = OBJ_NAME_add(OBJ_nid2ln(c->nid), OBJ_NAME_TYPE_CIPHER_METH,
+	    (const char *)c);
+	return (r);
+}
+
+int
+EVP_add_digest(const EVP_MD *md)
+{
+	int r;
+	const char *name;
+
+	name = OBJ_nid2sn(md->type);
+	r = OBJ_NAME_add(name, OBJ_NAME_TYPE_MD_METH, (const char *)md);
+	if (r == 0)
+		return (0);
+	check_defer(md->type);
+	r = OBJ_NAME_add(OBJ_nid2ln(md->type), OBJ_NAME_TYPE_MD_METH,
+	    (const char *)md);
+	if (r == 0)
+		return (0);
+
+	if (md->pkey_type && md->type != md->pkey_type) {
+		r = OBJ_NAME_add(OBJ_nid2sn(md->pkey_type),
+		    OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS, name);
+		if (r == 0)
+			return (0);
+		check_defer(md->pkey_type);
+		r = OBJ_NAME_add(OBJ_nid2ln(md->pkey_type),
+		    OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS, name);
+	}
+	return (r);
+}
+
+const EVP_CIPHER *
+EVP_get_cipherbyname(const char *name)
+{
+	if (!OPENSSL_init_crypto(0, NULL))
+		return NULL;
+
+	return (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH);
+}
+
+const EVP_MD *
+EVP_get_digestbyname(const char *name)
+{
+	if (!OPENSSL_init_crypto(0, NULL))
+		return NULL;
+
+	return (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH);
+}
+
+void
+EVP_cleanup(void)
+{
+	OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
+	OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
+	/* The above calls will only clean out the contents of the name
+	   hash table, but not the hash table itself.  The following line
+	   does that part.  -- Richard Levitte */
+	OBJ_NAME_cleanup(-1);
+
+	EVP_PBE_cleanup();
+	if (obj_cleanup_defer == 2) {
+		obj_cleanup_defer = 0;
+		OBJ_cleanup();
+	}
+}
+
+struct doall_cipher {
+	void *arg;
+	void (*fn)(const EVP_CIPHER *ciph, const char *from, const char *to,
+	    void *arg);
+};
+
+static void
+do_all_cipher_fn(const OBJ_NAME *nm, void *arg)
+{
+	struct doall_cipher *dc = arg;
+
+	if (nm->alias)
+		dc->fn(NULL, nm->name, nm->data, dc->arg);
+	else
+		dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg);
+}
+
+void
+EVP_CIPHER_do_all(void (*fn)(const EVP_CIPHER *ciph, const char *from,
+    const char *to, void *x), void *arg)
+{
+	struct doall_cipher dc;
+
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	dc.fn = fn;
+	dc.arg = arg;
+	OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc);
+}
+
+void
+EVP_CIPHER_do_all_sorted(void (*fn)(const EVP_CIPHER *ciph, const char *from,
+    const char *to, void *x), void *arg)
+{
+	struct doall_cipher dc;
+
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	dc.fn = fn;
+	dc.arg = arg;
+	OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
+	    do_all_cipher_fn, &dc);
+}
+
+struct doall_md {
+	void *arg;
+	void (*fn)(const EVP_MD *ciph, const char *from, const char *to,
+	    void *arg);
+};
+
+static void
+do_all_md_fn(const OBJ_NAME *nm, void *arg)
+{
+	struct doall_md *dc = arg;
+
+	if (nm->alias)
+		dc->fn(NULL, nm->name, nm->data, dc->arg);
+	else
+		dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg);
+}
+
+void
+EVP_MD_do_all(void (*fn)(const EVP_MD *md, const char *from, const char *to,
+    void *x), void *arg)
+{
+	struct doall_md dc;
+
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	dc.fn = fn;
+	dc.arg = arg;
+	OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
+}
+
+void
+EVP_MD_do_all_sorted(void (*fn)(const EVP_MD *md,
+    const char *from, const char *to, void *x), void *arg)
+{
+	struct doall_md dc;
+
+	/* Prayer and clean living lets you ignore errors, OpenSSL style */
+	(void) OPENSSL_init_crypto(0, NULL);
+
+	dc.fn = fn;
+	dc.arg = arg;
+	OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
+}
diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c
new file mode 100644
index 0000000..d26439a
--- /dev/null
+++ b/crypto/evp/p5_crpt.c
@@ -0,0 +1,163 @@
+/* $OpenBSD: p5_crpt.c,v 1.23 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* Doesn't do anything now: Builtin PBE algorithms in static table.
+ */
+
+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)
+{
+	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;
+	PBEPARAM *pbe;
+	int saltlen, iter;
+	unsigned char *salt;
+	const unsigned char *pbuf;
+	int mdsize;
+	int rv = 0;
+
+	/* Extract useful info from parameter */
+	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
+	    param->value.sequence == NULL) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		return 0;
+	}
+
+	mdsize = EVP_MD_size(md);
+	if (mdsize < 0)
+		return 0;
+
+	pbuf = param->value.sequence->data;
+	if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		return 0;
+	}
+
+	if (!pbe->iter)
+		iter = 1;
+	else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) {
+		EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS);
+		PBEPARAM_free(pbe);
+		return 0;
+	}
+	salt = pbe->salt->data;
+	saltlen = pbe->salt->length;
+
+	if (!pass)
+		passlen = 0;
+	else if (passlen == -1)
+		passlen = strlen(pass);
+
+	EVP_MD_CTX_init(&ctx);
+
+	if (!EVP_DigestInit_ex(&ctx, md, NULL))
+		goto err;
+	if (!EVP_DigestUpdate(&ctx, pass, passlen))
+		goto err;
+	if (!EVP_DigestUpdate(&ctx, salt, saltlen))
+		goto err;
+	if (!EVP_DigestFinal_ex(&ctx, md_tmp, NULL))
+		goto err;
+	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;
+	}
+	if ((size_t)EVP_CIPHER_key_length(cipher) > sizeof(md_tmp)) {
+		EVPerror(EVP_R_BAD_KEY_LENGTH);
+		goto err;
+	}
+	memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher));
+	if ((size_t)EVP_CIPHER_iv_length(cipher) > 16) {
+		EVPerror(EVP_R_IV_TOO_LARGE);
+		goto err;
+	}
+	memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)),
+	    EVP_CIPHER_iv_length(cipher));
+	if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de))
+		goto err;
+	explicit_bzero(md_tmp, EVP_MAX_MD_SIZE);
+	explicit_bzero(key, EVP_MAX_KEY_LENGTH);
+	explicit_bzero(iv, EVP_MAX_IV_LENGTH);
+	rv = 1;
+err:
+	EVP_MD_CTX_cleanup(&ctx);
+	PBEPARAM_free(pbe);
+	return rv;
+}
diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c
new file mode 100644
index 0000000..3c66af9
--- /dev/null
+++ b/crypto/evp/p5_crpt2.c
@@ -0,0 +1,307 @@
+/* $OpenBSD: p5_crpt2.c,v 1.27 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#if !defined(OPENSSL_NO_HMAC) && !defined(OPENSSL_NO_SHA)
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "hmac_local.h"
+
+/* 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)
+{
+	unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
+	int cplen, j, k, tkeylen, mdlen;
+	unsigned long i = 1;
+	HMAC_CTX hctx_tpl, hctx;
+
+	mdlen = EVP_MD_size(digest);
+	if (mdlen < 0)
+		return 0;
+
+	HMAC_CTX_init(&hctx_tpl);
+	p = out;
+	tkeylen = keylen;
+	if (!pass)
+		passlen = 0;
+	else if (passlen == -1)
+		passlen = strlen(pass);
+	if (!HMAC_Init_ex(&hctx_tpl, pass, passlen, digest, NULL)) {
+		HMAC_CTX_cleanup(&hctx_tpl);
+		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_cleanup(&hctx_tpl);
+			return 0;
+		}
+		if (!HMAC_Update(&hctx, salt, saltlen) ||
+		    !HMAC_Update(&hctx, itmp, 4) ||
+		    !HMAC_Final(&hctx, digtmp, NULL)) {
+			HMAC_CTX_cleanup(&hctx_tpl);
+			HMAC_CTX_cleanup(&hctx);
+			return 0;
+		}
+		HMAC_CTX_cleanup(&hctx);
+		memcpy(p, digtmp, cplen);
+		for (j = 1; j < iter; j++) {
+			if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
+				HMAC_CTX_cleanup(&hctx_tpl);
+				return 0;
+			}
+			if (!HMAC_Update(&hctx, digtmp, mdlen) ||
+			    !HMAC_Final(&hctx, digtmp, NULL)) {
+				HMAC_CTX_cleanup(&hctx_tpl);
+				HMAC_CTX_cleanup(&hctx);
+				return 0;
+			}
+			HMAC_CTX_cleanup(&hctx);
+			for (k = 0; k < cplen; k++)
+				p[k] ^= digtmp[k];
+		}
+		tkeylen -= cplen;
+		i++;
+		p += cplen;
+	}
+	HMAC_CTX_cleanup(&hctx_tpl);
+	return 1;
+}
+
+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);
+}
+
+/* Now the key derivation function itself. This is a bit evil because
+ * it has to check the ASN1 parameters are valid: and there are quite a
+ * few of 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)
+{
+	const unsigned char *pbuf;
+	int plen;
+	PBE2PARAM *pbe2 = NULL;
+	const EVP_CIPHER *cipher;
+
+	int rv = 0;
+
+	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
+	    param->value.sequence == NULL) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		goto err;
+	}
+
+	pbuf = param->value.sequence->data;
+	plen = param->value.sequence->length;
+	if (!(pbe2 = d2i_PBE2PARAM(NULL, &pbuf, plen))) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		goto err;
+	}
+
+	/* See if we recognise the key derivation function */
+
+	if (OBJ_obj2nid(pbe2->keyfunc->algorithm) != NID_id_pbkdf2) {
+		EVPerror(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
+		goto err;
+	}
+
+	/* lets see if we recognise the encryption algorithm.
+	 */
+
+	cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm);
+
+	if (!cipher) {
+		EVPerror(EVP_R_UNSUPPORTED_CIPHER);
+		goto err;
+	}
+
+	/* 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) {
+		EVPerror(EVP_R_CIPHER_PARAMETER_ERROR);
+		goto err;
+	}
+	rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass, passlen,
+	    pbe2->keyfunc->parameter, c, md, en_de);
+
+err:
+	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)
+{
+	unsigned char *salt, key[EVP_MAX_KEY_LENGTH];
+	const unsigned char *pbuf;
+	int saltlen, iter, plen;
+	int rv = 0;
+	unsigned int keylen = 0;
+	int prf_nid, hmac_md_nid;
+	PBKDF2PARAM *kdf = NULL;
+	const EVP_MD *prfmd;
+
+	if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
+		EVPerror(EVP_R_NO_CIPHER_SET);
+		return 0;
+	}
+	keylen = EVP_CIPHER_CTX_key_length(ctx);
+	if (keylen > sizeof key) {
+		EVPerror(EVP_R_BAD_KEY_LENGTH);
+		return 0;
+	}
+
+	/* Decode parameter */
+
+	if (!param || (param->type != V_ASN1_SEQUENCE)) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		return 0;
+	}
+
+	pbuf = param->value.sequence->data;
+	plen = param->value.sequence->length;
+
+	if (!(kdf = d2i_PBKDF2PARAM(NULL, &pbuf, plen)) ) {
+		EVPerror(EVP_R_DECODE_ERROR);
+		return 0;
+	}
+
+	/* Now check the parameters of the kdf */
+
+	if (kdf->keylength &&
+	    (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)){
+		EVPerror(EVP_R_UNSUPPORTED_KEYLENGTH);
+		goto err;
+	}
+
+	if (kdf->prf)
+		prf_nid = OBJ_obj2nid(kdf->prf->algorithm);
+	else
+		prf_nid = NID_hmacWithSHA1;
+
+	if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) {
+		EVPerror(EVP_R_UNSUPPORTED_PRF);
+		goto err;
+	}
+
+	prfmd = EVP_get_digestbynid(hmac_md_nid);
+	if (prfmd == NULL) {
+		EVPerror(EVP_R_UNSUPPORTED_PRF);
+		goto err;
+	}
+
+	if (kdf->salt->type != V_ASN1_OCTET_STRING) {
+		EVPerror(EVP_R_UNSUPPORTED_SALT_TYPE);
+		goto err;
+	}
+
+	/* it seems that its all OK */
+	salt = kdf->salt->value.octet_string->data;
+	saltlen = kdf->salt->value.octet_string->length;
+	if ((iter = ASN1_INTEGER_get(kdf->iter)) <= 0) {
+		EVPerror(EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS);
+		goto err;
+	}
+	if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd,
+	    keylen, key))
+		goto err;
+	rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de);
+
+err:
+	explicit_bzero(key, keylen);
+	PBKDF2PARAM_free(kdf);
+	return rv;
+}
+
+#endif
diff --git a/crypto/evp/p_dec.c b/crypto/evp/p_dec.c
new file mode 100644
index 0000000..d55b48b
--- /dev/null
+++ b/crypto/evp/p_dec.c
@@ -0,0 +1,94 @@
+/* $OpenBSD: p_dec.c,v 1.15 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+int
+EVP_PKEY_decrypt_old(unsigned char *key, const unsigned char *ek, int ekl,
+    EVP_PKEY *priv)
+{
+	int ret = -1;
+
+#ifndef OPENSSL_NO_RSA
+	if (priv->type != EVP_PKEY_RSA) {
+#endif
+		EVPerror(EVP_R_PUBLIC_KEY_NOT_RSA);
+#ifndef OPENSSL_NO_RSA
+		goto err;
+	}
+
+	ret = RSA_private_decrypt(ekl, ek, key, priv->pkey.rsa,
+	    RSA_PKCS1_PADDING);
+
+err:
+#endif
+	return (ret);
+}
diff --git a/crypto/evp/p_enc.c b/crypto/evp/p_enc.c
new file mode 100644
index 0000000..1abaf0b
--- /dev/null
+++ b/crypto/evp/p_enc.c
@@ -0,0 +1,91 @@
+/* $OpenBSD: p_enc.c,v 1.15 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+int
+EVP_PKEY_encrypt_old(unsigned char *ek, const unsigned char *key, int key_len,
+    EVP_PKEY *pubk)
+{
+	int ret = 0;
+
+#ifndef OPENSSL_NO_RSA
+	if (pubk->type != EVP_PKEY_RSA) {
+#endif
+		EVPerror(EVP_R_PUBLIC_KEY_NOT_RSA);
+#ifndef OPENSSL_NO_RSA
+		goto err;
+	}
+	ret = RSA_public_encrypt(key_len, key, ek, pubk->pkey.rsa, RSA_PKCS1_PADDING);
+err:
+#endif
+	return (ret);
+}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
new file mode 100644
index 0000000..23ec8e6
--- /dev/null
+++ b/crypto/evp/p_lib.c
@@ -0,0 +1,681 @@
+/* $OpenBSD: p_lib.c,v 1.37 2023/09/10 17:32:17 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+static void EVP_PKEY_free_it(EVP_PKEY *x);
+
+int
+EVP_PKEY_bits(const EVP_PKEY *pkey)
+{
+	if (pkey && pkey->ameth && pkey->ameth->pkey_bits)
+		return pkey->ameth->pkey_bits(pkey);
+	return 0;
+}
+
+int
+EVP_PKEY_security_bits(const EVP_PKEY *pkey)
+{
+	if (pkey == NULL)
+		return 0;
+	if (pkey->ameth == NULL || pkey->ameth->pkey_security_bits == NULL)
+		return -2;
+
+	return pkey->ameth->pkey_security_bits(pkey);
+}
+
+int
+EVP_PKEY_size(const EVP_PKEY *pkey)
+{
+	if (pkey && pkey->ameth && pkey->ameth->pkey_size)
+		return pkey->ameth->pkey_size(pkey);
+	return 0;
+}
+
+int
+EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
+{
+#ifndef OPENSSL_NO_DSA
+	if (pkey->type == EVP_PKEY_DSA) {
+		int ret = pkey->save_parameters;
+
+		if (mode >= 0)
+			pkey->save_parameters = mode;
+		return (ret);
+	}
+#endif
+#ifndef OPENSSL_NO_EC
+	if (pkey->type == EVP_PKEY_EC) {
+		int ret = pkey->save_parameters;
+
+		if (mode >= 0)
+			pkey->save_parameters = mode;
+		return (ret);
+	}
+#endif
+	return (0);
+}
+
+int
+EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
+{
+	if (to->type != from->type) {
+		EVPerror(EVP_R_DIFFERENT_KEY_TYPES);
+		goto err;
+	}
+
+	if (EVP_PKEY_missing_parameters(from)) {
+		EVPerror(EVP_R_MISSING_PARAMETERS);
+		goto err;
+	}
+	if (from->ameth && from->ameth->param_copy)
+		return from->ameth->param_copy(to, from);
+
+err:
+	return 0;
+}
+
+int
+EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
+{
+	if (pkey->ameth && pkey->ameth->param_missing)
+		return pkey->ameth->param_missing(pkey);
+	return 0;
+}
+
+int
+EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	if (a->type != b->type)
+		return -1;
+	if (a->ameth && a->ameth->param_cmp)
+		return a->ameth->param_cmp(a, b);
+	return -2;
+}
+
+int
+EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	if (a->type != b->type)
+		return -1;
+
+	if (a->ameth) {
+		int ret;
+		/* Compare parameters if the algorithm has them */
+		if (a->ameth->param_cmp) {
+			ret = a->ameth->param_cmp(a, b);
+			if (ret <= 0)
+				return ret;
+		}
+
+		if (a->ameth->pub_cmp)
+			return a->ameth->pub_cmp(a, b);
+	}
+
+	return -2;
+}
+
+EVP_PKEY *
+EVP_PKEY_new(void)
+{
+	EVP_PKEY *ret;
+
+	ret = malloc(sizeof(EVP_PKEY));
+	if (ret == NULL) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	ret->type = EVP_PKEY_NONE;
+	ret->save_type = EVP_PKEY_NONE;
+	ret->references = 1;
+	ret->ameth = NULL;
+	ret->engine = NULL;
+	ret->pkey.ptr = NULL;
+	ret->attributes = NULL;
+	ret->save_parameters = 1;
+	return (ret);
+}
+
+int
+EVP_PKEY_up_ref(EVP_PKEY *pkey)
+{
+	int refs = CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+	return ((refs > 1) ? 1 : 0);
+}
+
+/* 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.
+ */
+
+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 = NULL;
+
+	if (e == NULL)
+		eptr = &e;
+
+	if (pkey) {
+		if (pkey->pkey.ptr)
+			EVP_PKEY_free_it(pkey);
+		/* If key type matches and a method exists then this
+		 * lookup has succeeded once so just indicate success.
+		 */
+		if ((type == pkey->save_type) && pkey->ameth)
+			return 1;
+#ifndef OPENSSL_NO_ENGINE
+		ENGINE_finish(pkey->engine);
+		pkey->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) {
+		EVPerror(EVP_R_UNSUPPORTED_ALGORITHM);
+		return 0;
+	}
+	if (pkey) {
+		pkey->ameth = ameth;
+		pkey->engine = e;
+
+		pkey->type = pkey->ameth->pkey_id;
+		pkey->save_type = type;
+	}
+	return 1;
+}
+
+int
+EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
+{
+	return pkey_set_type(pkey, NULL, type, NULL, -1);
+}
+
+EVP_PKEY *
+EVP_PKEY_new_raw_private_key(int type, ENGINE *engine,
+    const unsigned char *private_key, size_t len)
+{
+	EVP_PKEY *ret;
+
+	if ((ret = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!pkey_set_type(ret, engine, type, NULL, -1))
+		goto err;
+
+	if (ret->ameth->set_priv_key == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		goto err;
+	}
+	if (!ret->ameth->set_priv_key(ret, private_key, len)) {
+		EVPerror(EVP_R_KEY_SETUP_FAILED);
+		goto err;
+	}
+
+	return ret;
+
+ err:
+	EVP_PKEY_free(ret);
+
+	return NULL;
+}
+
+EVP_PKEY *
+EVP_PKEY_new_raw_public_key(int type, ENGINE *engine,
+    const unsigned char *public_key, size_t len)
+{
+	EVP_PKEY *ret;
+
+	if ((ret = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!pkey_set_type(ret, engine, type, NULL, -1))
+		goto err;
+
+	if (ret->ameth->set_pub_key == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		goto err;
+	}
+	if (!ret->ameth->set_pub_key(ret, public_key, len)) {
+		EVPerror(EVP_R_KEY_SETUP_FAILED);
+		goto err;
+	}
+
+	return ret;
+
+ err:
+	EVP_PKEY_free(ret);
+
+	return NULL;
+}
+
+int
+EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey,
+    unsigned char *out_private_key, size_t *out_len)
+{
+	if (pkey->ameth->get_priv_key == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return 0;
+	}
+	if (!pkey->ameth->get_priv_key(pkey, out_private_key, out_len)) {
+		EVPerror(EVP_R_GET_RAW_KEY_FAILED);
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey,
+    unsigned char *out_public_key, size_t *out_len)
+{
+	if (pkey->ameth->get_pub_key == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return 0;
+	}
+	if (!pkey->ameth->get_pub_key(pkey, out_public_key, out_len)) {
+		EVPerror(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)
+{
+	EVP_PKEY *ret = NULL;
+	CMAC_CTX *cmctx = NULL;
+
+	if ((ret = EVP_PKEY_new()) == NULL)
+		goto err;
+	if ((cmctx = CMAC_CTX_new()) == NULL)
+		goto err;
+
+	if (!pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1))
+		goto err;
+
+	if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
+		EVPerror(EVP_R_KEY_SETUP_FAILED);
+		goto err;
+	}
+
+	ret->pkey.ptr = cmctx;
+
+	return ret;
+
+ err:
+	EVP_PKEY_free(ret);
+	CMAC_CTX_free(cmctx);
+	return NULL;
+}
+
+int
+EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
+{
+	return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
+}
+
+int
+EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
+{
+	if (!EVP_PKEY_set_type(pkey, type))
+		return 0;
+	pkey->pkey.ptr = key;
+	return (key != NULL);
+}
+
+void *
+EVP_PKEY_get0(const EVP_PKEY *pkey)
+{
+	return pkey->pkey.ptr;
+}
+
+const unsigned char *
+EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
+{
+	ASN1_OCTET_STRING *os;
+
+	if (pkey->type != EVP_PKEY_HMAC) {
+		EVPerror(EVP_R_EXPECTING_AN_HMAC_KEY);
+		return NULL;
+	}
+
+	os = EVP_PKEY_get0(pkey);
+	*len = os->length;
+
+	return os->data;
+}
+
+#ifndef OPENSSL_NO_RSA
+RSA *
+EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+{
+	if (pkey->type == EVP_PKEY_RSA || pkey->type == EVP_PKEY_RSA_PSS)
+		return pkey->pkey.rsa;
+
+	EVPerror(EVP_R_EXPECTING_AN_RSA_KEY);
+	return NULL;
+}
+
+RSA *
+EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
+{
+	RSA *rsa;
+
+	if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL)
+		return NULL;
+
+	RSA_up_ref(rsa);
+
+	return rsa;
+}
+
+int
+EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
+{
+	int ret = EVP_PKEY_assign_RSA(pkey, key);
+	if (ret != 0)
+		RSA_up_ref(key);
+	return ret;
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+DSA *
+EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
+{
+	if (pkey->type != EVP_PKEY_DSA) {
+		EVPerror(EVP_R_EXPECTING_A_DSA_KEY);
+		return NULL;
+	}
+	return pkey->pkey.dsa;
+}
+
+DSA *
+EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
+{
+	DSA *dsa;
+
+	if ((dsa = EVP_PKEY_get0_DSA(pkey)) == NULL)
+		return NULL;
+
+	DSA_up_ref(dsa);
+
+	return dsa;
+}
+
+int
+EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
+{
+	int ret = EVP_PKEY_assign_DSA(pkey, key);
+	if (ret != 0)
+		DSA_up_ref(key);
+	return ret;
+}
+#endif
+
+#ifndef OPENSSL_NO_EC
+EC_KEY *
+EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
+{
+	if (pkey->type != EVP_PKEY_EC) {
+		EVPerror(EVP_R_EXPECTING_A_EC_KEY);
+		return NULL;
+	}
+	return pkey->pkey.ec;
+}
+
+EC_KEY *
+EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
+{
+	EC_KEY *key;
+
+	if ((key = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
+		return NULL;
+
+	EC_KEY_up_ref(key);
+
+	return key;
+}
+
+int
+EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
+{
+	int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
+	if (ret != 0)
+		EC_KEY_up_ref(key);
+	return ret;
+}
+#endif
+
+
+#ifndef OPENSSL_NO_DH
+DH *
+EVP_PKEY_get0_DH(EVP_PKEY *pkey)
+{
+	if (pkey->type != EVP_PKEY_DH) {
+		EVPerror(EVP_R_EXPECTING_A_DH_KEY);
+		return NULL;
+	}
+	return pkey->pkey.dh;
+}
+
+DH *
+EVP_PKEY_get1_DH(EVP_PKEY *pkey)
+{
+	DH *dh;
+
+	if ((dh = EVP_PKEY_get0_DH(pkey)) == NULL)
+		return NULL;
+
+	DH_up_ref(dh);
+
+	return dh;
+}
+
+int
+EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
+{
+	int ret = EVP_PKEY_assign_DH(pkey, key);
+	if (ret != 0)
+		DH_up_ref(key);
+	return ret;
+}
+#endif
+
+int
+EVP_PKEY_type(int type)
+{
+	int ret;
+	const EVP_PKEY_ASN1_METHOD *ameth;
+	ENGINE *e;
+	ameth = EVP_PKEY_asn1_find(&e, type);
+	if (ameth)
+		ret = ameth->pkey_id;
+	else
+		ret = NID_undef;
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(e);
+#endif
+	return ret;
+}
+
+int
+EVP_PKEY_id(const EVP_PKEY *pkey)
+{
+	return pkey->type;
+}
+
+int
+EVP_PKEY_base_id(const EVP_PKEY *pkey)
+{
+	return EVP_PKEY_type(pkey->type);
+}
+
+void
+EVP_PKEY_free(EVP_PKEY *x)
+{
+	int i;
+
+	if (x == NULL)
+		return;
+
+	i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
+	if (i > 0)
+		return;
+
+	EVP_PKEY_free_it(x);
+	if (x->attributes)
+		sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
+	free(x);
+}
+
+static void
+EVP_PKEY_free_it(EVP_PKEY *x)
+{
+	if (x->ameth && x->ameth->pkey_free) {
+		x->ameth->pkey_free(x);
+		x->pkey.ptr = NULL;
+	}
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(x->engine);
+	x->engine = NULL;
+#endif
+}
+
+static int
+unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, const char *kstr)
+{
+	if (!BIO_indent(out, indent, 128))
+		return 0;
+	BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
+	    kstr, OBJ_nid2ln(pkey->type));
+	return 1;
+}
+
+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");
+}
+
+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");
+}
+
+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");
+}
+
+int
+EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
+{
+	if (!pkey->ameth || !pkey->ameth->pkey_ctrl)
+		return -2;
+	return pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID,
+	    0, pnid);
+}
diff --git a/crypto/evp/p_open.c b/crypto/evp/p_open.c
new file mode 100644
index 0000000..d18548e
--- /dev/null
+++ b/crypto/evp/p_open.c
@@ -0,0 +1,128 @@
+/* $OpenBSD: p_open.c,v 1.23 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_RSA
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.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;
+
+	if (type) {
+		EVP_CIPHER_CTX_init(ctx);
+		if (!EVP_DecryptInit_ex(ctx, type, NULL, NULL, NULL))
+			return 0;
+	}
+
+	if (!priv)
+		return 1;
+
+	if (priv->type != EVP_PKEY_RSA) {
+		EVPerror(EVP_R_PUBLIC_KEY_NOT_RSA);
+		goto err;
+	}
+
+	size = RSA_size(priv->pkey.rsa);
+	key = malloc(size + 2);
+	if (key == NULL) {
+		/* ERROR */
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	i = EVP_PKEY_decrypt_old(key, ek, ekl, priv);
+	if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) {
+		/* ERROR */
+		goto err;
+	}
+	if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
+		goto err;
+
+	ret = 1;
+
+err:
+	freezero(key, size);
+	return (ret);
+}
+
+int
+EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int i;
+
+	i = EVP_DecryptFinal_ex(ctx, out, outl);
+	if (i)
+		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
new file mode 100644
index 0000000..b98da94
--- /dev/null
+++ b/crypto/evp/p_seal.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: p_seal.c,v 1.16 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+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;
+
+	if (type) {
+		EVP_CIPHER_CTX_init(ctx);
+		if (!EVP_EncryptInit_ex(ctx, type, NULL, NULL, NULL))
+			return 0;
+	}
+	if ((npubk <= 0) || !pubk)
+		return 1;
+	if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
+		return 0;
+	if (EVP_CIPHER_CTX_iv_length(ctx))
+		arc4random_buf(iv, EVP_CIPHER_CTX_iv_length(ctx));
+
+	if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
+		return 0;
+
+	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)
+			return (-1);
+	}
+	return (npubk);
+}
+
+/* MACRO
+void EVP_SealUpdate(ctx,out,outl,in,inl)
+EVP_CIPHER_CTX *ctx;
+unsigned char *out;
+int *outl;
+unsigned char *in;
+int inl;
+	{
+	EVP_EncryptUpdate(ctx,out,outl,in,inl);
+	}
+*/
+
+int
+EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
+{
+	int i;
+
+	i = EVP_EncryptFinal_ex(ctx, out, outl);
+	if (i)
+		i = EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, NULL);
+	return i;
+}
diff --git a/crypto/evp/p_sign.c b/crypto/evp/p_sign.c
new file mode 100644
index 0000000..f7c2117
--- /dev/null
+++ b/crypto/evp/p_sign.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: p_sign.c,v 1.19 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+int
+EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
+    EVP_PKEY *pkey)
+{
+	unsigned char m[EVP_MAX_MD_SIZE];
+	unsigned int m_len;
+	EVP_MD_CTX tmp_ctx;
+	EVP_PKEY_CTX *pkctx = NULL;
+	size_t sltmp;
+	int ret = 0;
+
+	*siglen = 0;
+	EVP_MD_CTX_init(&tmp_ctx);
+	if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx))
+		goto err;
+	if (!EVP_DigestFinal_ex(&tmp_ctx, &(m[0]), &m_len))
+		goto err;
+	EVP_MD_CTX_cleanup(&tmp_ctx);
+
+	sltmp = (size_t)EVP_PKEY_size(pkey);
+
+	if ((pkctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
+		goto err;
+	if (EVP_PKEY_sign_init(pkctx) <= 0)
+		goto err;
+	if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0)
+		goto err;
+	if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0)
+		goto err;
+	*siglen = sltmp;
+
+	ret = 1;
+
+ err:
+	EVP_PKEY_CTX_free(pkctx);
+	return ret;
+}
diff --git a/crypto/evp/p_verify.c b/crypto/evp/p_verify.c
new file mode 100644
index 0000000..da7ab54
--- /dev/null
+++ b/crypto/evp/p_verify.c
@@ -0,0 +1,97 @@
+/* $OpenBSD: p_verify.c,v 1.18 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+int
+EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
+    unsigned int siglen, EVP_PKEY *pkey)
+{
+	unsigned char m[EVP_MAX_MD_SIZE];
+	unsigned int m_len;
+	EVP_MD_CTX tmp_ctx;
+	EVP_PKEY_CTX *pkctx = NULL;
+	int ret = 0;
+
+	EVP_MD_CTX_init(&tmp_ctx);
+	if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx))
+		goto err;
+	if (!EVP_DigestFinal_ex(&tmp_ctx, &(m[0]), &m_len))
+		goto err;
+	EVP_MD_CTX_cleanup(&tmp_ctx);
+
+	ret = -1;
+	if ((pkctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL)
+		goto err;
+	if (EVP_PKEY_verify_init(pkctx) <= 0)
+		goto err;
+	if (EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0)
+		goto err;
+	ret = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len);
+
+ err:
+	EVP_PKEY_CTX_free(pkctx);
+	return ret;
+}
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
new file mode 100644
index 0000000..a304752
--- /dev/null
+++ b/crypto/evp/pmeth_fn.c
@@ -0,0 +1,345 @@
+/* $OpenBSD: pmeth_fn.c,v 1.9 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.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 (!arg) \
+			{ \
+			*arglen = pksize; \
+			return 1; \
+			} \
+		else if (*arglen < pksize) \
+			{ \
+			EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_SIGN) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_VERIFY) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_ENCRYPT) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_DECRYPT) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(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) {
+		EVPerror(EVP_R_NO_KEY_SET);
+		return -1;
+	}
+
+	if (ctx->pkey->type != peer->type) {
+		EVPerror(EVP_R_DIFFERENT_KEY_TYPES);
+		return -1;
+	}
+
+	/* ran@cryptocom.ru: 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)) {
+		EVPerror(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;
+	}
+
+	CRYPTO_add(&peer->references, 1, CRYPTO_LOCK_EVP_PKEY);
+	return 1;
+}
+
+int
+EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen)
+{
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_DERIVE) {
+		EVPerror(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
new file mode 100644
index 0000000..b4c0395
--- /dev/null
+++ b/crypto/evp/pmeth_gn.c
@@ -0,0 +1,288 @@
+/* $OpenBSD: pmeth_gn.c,v 1.13 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bn_local.h"
+#include "evp_local.h"
+
+int
+EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
+{
+	int ret;
+
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	ctx->operation = EVP_PKEY_OP_PARAMGEN;
+	if (!ctx->pmeth->paramgen_init)
+		return 1;
+	ret = ctx->pmeth->paramgen_init(ctx);
+	if (ret <= 0)
+		ctx->operation = EVP_PKEY_OP_UNDEFINED;
+	return ret;
+}
+
+int
+EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+{
+	int ret;
+
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+
+	if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
+		EVPerror(EVP_R_OPERATON_NOT_INITIALIZED);
+		return -1;
+	}
+
+	if (!ppkey)
+		return -1;
+
+	if (!*ppkey)
+		*ppkey = EVP_PKEY_new();
+
+	ret = ctx->pmeth->paramgen(ctx, *ppkey);
+	if (ret <= 0) {
+		EVP_PKEY_free(*ppkey);
+		*ppkey = NULL;
+	}
+	return ret;
+}
+
+int
+EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
+{
+	int ret;
+
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	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;
+}
+
+int
+EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
+{
+	int ret;
+
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+	if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
+		EVPerror(EVP_R_OPERATON_NOT_INITIALIZED);
+		return -1;
+	}
+
+	if (!ppkey)
+		return -1;
+
+	if (!*ppkey)
+		*ppkey = EVP_PKEY_new();
+
+	ret = ctx->pmeth->keygen(ctx, *ppkey);
+	if (ret <= 0) {
+		EVP_PKEY_free(*ppkey);
+		*ppkey = NULL;
+	}
+	return ret;
+}
+
+void
+EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
+{
+	ctx->pkey_gencb = cb;
+}
+
+EVP_PKEY_gen_cb *
+EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
+{
+	return ctx->pkey_gencb;
+}
+
+/* "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB
+ * style callbacks.
+ */
+
+static int
+trans_cb(int a, int b, BN_GENCB *gcb)
+{
+	EVP_PKEY_CTX *ctx = gcb->arg;
+	ctx->keygen_info[0] = a;
+	ctx->keygen_info[1] = b;
+	return ctx->pkey_gencb(ctx);
+}
+
+void
+evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
+{
+	BN_GENCB_set(cb, trans_cb, ctx);
+}
+
+int
+EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
+{
+	if (idx == -1)
+		return ctx->keygen_info_count;
+	if (idx < 0 || idx > ctx->keygen_info_count)
+		return 0;
+	return ctx->keygen_info[idx];
+}
+
+EVP_PKEY *
+EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key, int keylen)
+{
+	EVP_PKEY_CTX *mac_ctx = NULL;
+	EVP_PKEY *mac_key = NULL;
+
+	mac_ctx = EVP_PKEY_CTX_new_id(type, e);
+	if (!mac_ctx)
+		return NULL;
+	if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
+		goto merr;
+	if (EVP_PKEY_CTX_ctrl(mac_ctx, -1, EVP_PKEY_OP_KEYGEN,
+	    EVP_PKEY_CTRL_SET_MAC_KEY, keylen, (void *)key) <= 0)
+		goto merr;
+	if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
+		goto merr;
+
+merr:
+	EVP_PKEY_CTX_free(mac_ctx);
+	return mac_key;
+}
+
+int
+EVP_PKEY_check(EVP_PKEY_CTX *ctx)
+{
+	EVP_PKEY *pkey;
+
+	if ((pkey = ctx->pkey) == NULL) {
+		EVPerror(EVP_R_NO_KEY_SET);
+		return 0;
+	}
+
+	if (ctx->pmeth->check != NULL)
+		return ctx->pmeth->check(pkey);
+
+	if (pkey->ameth == NULL || pkey->ameth->pkey_check == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+
+	return pkey->ameth->pkey_check(pkey);
+}
+
+int
+EVP_PKEY_public_check(EVP_PKEY_CTX *ctx)
+{
+	EVP_PKEY *pkey;
+
+	if ((pkey = ctx->pkey) == NULL) {
+		EVPerror(EVP_R_NO_KEY_SET);
+		return 0;
+	}
+
+	if (ctx->pmeth->public_check != NULL)
+		return ctx->pmeth->public_check(pkey);
+
+	if (pkey->ameth == NULL || pkey->ameth->pkey_public_check == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+
+	return pkey->ameth->pkey_public_check(pkey);
+}
+
+int
+EVP_PKEY_param_check(EVP_PKEY_CTX *ctx)
+{
+	EVP_PKEY *pkey;
+
+	if ((pkey = ctx->pkey) == NULL) {
+		EVPerror(EVP_R_NO_KEY_SET);
+		return 0;
+	}
+
+	if (ctx->pmeth->param_check != NULL)
+		return ctx->pmeth->param_check(pkey);
+
+	if (pkey->ameth == NULL || pkey->ameth->pkey_param_check == NULL) {
+		EVPerror(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+	}
+
+	return pkey->ameth->pkey_param_check(pkey);
+}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
new file mode 100644
index 0000000..b480a57
--- /dev/null
+++ b/crypto/evp/pmeth_lib.c
@@ -0,0 +1,627 @@
+/* $OpenBSD: pmeth_lib.c,v 1.33 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+DECLARE_STACK_OF(EVP_PKEY_METHOD)
+STACK_OF(EVP_PKEY_METHOD) *pkey_app_methods = NULL;
+
+extern const EVP_PKEY_METHOD cmac_pkey_meth;
+extern const EVP_PKEY_METHOD dh_pkey_meth;
+extern const EVP_PKEY_METHOD dsa_pkey_meth;
+extern const EVP_PKEY_METHOD ec_pkey_meth;
+extern const EVP_PKEY_METHOD ed25519_pkey_meth;
+extern const EVP_PKEY_METHOD gostimit_pkey_meth;
+extern const EVP_PKEY_METHOD gostr01_pkey_meth;
+extern const EVP_PKEY_METHOD hkdf_pkey_meth;
+extern const EVP_PKEY_METHOD hmac_pkey_meth;
+extern const EVP_PKEY_METHOD rsa_pkey_meth;
+extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
+extern const EVP_PKEY_METHOD x25519_pkey_meth;
+
+static const EVP_PKEY_METHOD *pkey_methods[] = {
+	&cmac_pkey_meth,
+	&dh_pkey_meth,
+	&dsa_pkey_meth,
+	&ec_pkey_meth,
+	&ed25519_pkey_meth,
+	&gostimit_pkey_meth,
+	&gostr01_pkey_meth,
+	&hkdf_pkey_meth,
+	&hmac_pkey_meth,
+	&rsa_pkey_meth,
+	&rsa_pss_pkey_meth,
+	&x25519_pkey_meth,
+};
+
+static const size_t pkey_methods_count =
+    sizeof(pkey_methods) / sizeof(pkey_methods[0]);
+
+int
+evp_pkey_meth_get_count(void)
+{
+	int num = pkey_methods_count;
+
+	if (pkey_app_methods != NULL)
+		num += sk_EVP_PKEY_METHOD_num(pkey_app_methods);
+
+	return num;
+}
+
+const EVP_PKEY_METHOD *
+evp_pkey_meth_get0(int idx)
+{
+	int num = pkey_methods_count;
+
+	if (idx < 0)
+		return NULL;
+	if (idx < num)
+		return pkey_methods[idx];
+
+	idx -= num;
+
+	return sk_EVP_PKEY_METHOD_value(pkey_app_methods, idx);
+}
+
+const EVP_PKEY_METHOD *
+EVP_PKEY_meth_find(int type)
+{
+	const EVP_PKEY_METHOD *pmeth;
+	int i;
+
+	for (i = evp_pkey_meth_get_count() - 1; i >= 0; i--) {
+		pmeth = evp_pkey_meth_get0(i);
+		if (pmeth->pkey_id == type)
+			return pmeth;
+	}
+
+	return NULL;
+}
+
+static EVP_PKEY_CTX *
+evp_pkey_ctx_new(EVP_PKEY *pkey, ENGINE *engine, int id)
+{
+	EVP_PKEY_CTX *pkey_ctx = NULL;
+	const EVP_PKEY_METHOD *pmeth;
+
+	if (id == -1) {
+		if (pkey == NULL || pkey->ameth == NULL)
+			return NULL;
+		id = pkey->ameth->pkey_id;
+	}
+#ifndef OPENSSL_NO_ENGINE
+	if (pkey != NULL && pkey->engine != NULL)
+		engine = pkey->engine;
+	/* Try to find an ENGINE which implements this method. */
+	if (engine != NULL) {
+		if (!ENGINE_init(engine)) {
+			EVPerror(ERR_R_ENGINE_LIB);
+			return NULL;
+		}
+	} else
+		engine = ENGINE_get_pkey_meth_engine(id);
+
+	/* Look up method handler in ENGINE or use internal tables. */
+	if (engine != NULL)
+		pmeth = ENGINE_get_pkey_meth(engine, id);
+	else
+#endif
+		pmeth = EVP_PKEY_meth_find(id);
+
+	if (pmeth == NULL) {
+		EVPerror(EVP_R_UNSUPPORTED_ALGORITHM);
+		goto err;
+	}
+
+	if ((pkey_ctx = calloc(1, sizeof(*pkey_ctx))) == NULL) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	pkey_ctx->engine = engine;
+	engine = NULL;
+	pkey_ctx->pmeth = pmeth;
+	pkey_ctx->operation = EVP_PKEY_OP_UNDEFINED;
+	if ((pkey_ctx->pkey = pkey) != NULL)
+		EVP_PKEY_up_ref(pkey_ctx->pkey);
+
+	if (pmeth->init != NULL) {
+		if (pmeth->init(pkey_ctx) <= 0)
+			goto err;
+	}
+
+	return pkey_ctx;
+
+ err:
+	EVP_PKEY_CTX_free(pkey_ctx);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(engine);
+#endif
+
+	return NULL;
+}
+
+EVP_PKEY_METHOD*
+EVP_PKEY_meth_new(int id, int flags)
+{
+	EVP_PKEY_METHOD *pmeth;
+
+	if ((pmeth = calloc(1, sizeof(EVP_PKEY_METHOD))) == NULL)
+		return NULL;
+
+	pmeth->pkey_id = id;
+	pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
+
+	return pmeth;
+}
+
+void
+EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, const EVP_PKEY_METHOD *meth)
+{
+	if (ppkey_id)
+		*ppkey_id = meth->pkey_id;
+	if (pflags)
+		*pflags = meth->flags;
+}
+
+void
+EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src)
+{
+	EVP_PKEY_METHOD preserve;
+
+	preserve.pkey_id = dst->pkey_id;
+	preserve.flags = dst->flags;
+
+	*dst = *src;
+
+	dst->pkey_id = preserve.pkey_id;
+	dst->flags = preserve.flags;
+}
+
+void
+EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
+{
+	if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC))
+		free(pmeth);
+}
+
+EVP_PKEY_CTX *
+EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *engine)
+{
+	return evp_pkey_ctx_new(pkey, engine, -1);
+}
+
+EVP_PKEY_CTX *
+EVP_PKEY_CTX_new_id(int id, ENGINE *engine)
+{
+	return evp_pkey_ctx_new(NULL, engine, id);
+}
+
+EVP_PKEY_CTX *
+EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
+{
+	EVP_PKEY_CTX *rctx = NULL;
+
+	if (pctx->pmeth == NULL || pctx->pmeth->copy == NULL)
+		goto err;
+#ifndef OPENSSL_NO_ENGINE
+	/* Make sure it's safe to copy a pkey context using an ENGINE */
+	if (pctx->engine != NULL && !ENGINE_init(pctx->engine)) {
+		EVPerror(ERR_R_ENGINE_LIB);
+		goto err;
+	}
+#endif
+	if ((rctx = calloc(1, sizeof(*rctx))) == NULL) {
+		EVPerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	rctx->pmeth = pctx->pmeth;
+#ifndef OPENSSL_NO_ENGINE
+	rctx->engine = pctx->engine;
+#endif
+
+	if ((rctx->pkey = pctx->pkey) != NULL)
+		EVP_PKEY_up_ref(rctx->pkey);
+	if ((rctx->peerkey = pctx->peerkey) != NULL)
+		EVP_PKEY_up_ref(rctx->peerkey);
+
+	rctx->operation = pctx->operation;
+
+	if (pctx->pmeth->copy(rctx, pctx) <= 0)
+		goto err;
+
+	return rctx;
+
+ err:
+	EVP_PKEY_CTX_free(rctx);
+	return NULL;
+}
+
+int
+EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
+{
+	if (pkey_app_methods == NULL) {
+		pkey_app_methods = sk_EVP_PKEY_METHOD_new(NULL);
+		if (pkey_app_methods == NULL)
+			return 0;
+	}
+
+	if (!sk_EVP_PKEY_METHOD_push(pkey_app_methods, pmeth))
+		return 0;
+
+	return 1;
+}
+
+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_free(ctx->pkey);
+	EVP_PKEY_free(ctx->peerkey);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(ctx->engine);
+#endif
+	free(ctx);
+}
+
+int
+EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
+    int p1, void *p2)
+{
+	int ret;
+
+	if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
+		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
+		return -2;
+	}
+	if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
+		return -1;
+
+	if (ctx->operation == EVP_PKEY_OP_UNDEFINED) {
+		EVPerror(EVP_R_NO_OPERATION_SET);
+		return -1;
+	}
+
+	if ((optype != -1) && !(ctx->operation & optype)) {
+		EVPerror(EVP_R_INVALID_OPERATION);
+		return -1;
+	}
+
+	ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
+
+	if (ret == -2)
+		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
+
+	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) {
+		EVPerror(EVP_R_COMMAND_NOT_SUPPORTED);
+		return -2;
+	}
+	if (!strcmp(name, "digest")) {
+		return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_SIG,
+		    EVP_PKEY_CTRL_MD, value);
+	}
+	return ctx->pmeth->ctrl_str(ctx, name, value);
+}
+
+int
+EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str)
+{
+	size_t len;
+
+	if ((len = strlen(str)) > INT_MAX)
+		return -1;
+
+	return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str);
+}
+
+int
+EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hexstr)
+{
+	unsigned char *hex = NULL;
+	long length;
+	int ret = 0;
+
+	if ((hex = string_to_hex(hexstr, &length)) == NULL)
+		goto err;
+	if (length < 0 || length > INT_MAX) {
+		ret = -1;
+		goto err;
+	}
+
+	ret = ctx->pmeth->ctrl(ctx, cmd, length, hex);
+
+ err:
+	free(hex);
+	return ret;
+}
+
+int
+EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md_name)
+{
+	const EVP_MD *md;
+
+	if ((md = EVP_get_digestbyname(md_name)) == NULL) {
+		EVPerror(EVP_R_INVALID_DIGEST);
+		return 0;
+	}
+	return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, 0, (void *)md);
+}
+
+int
+EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
+{
+	return ctx->operation;
+}
+
+void
+EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen)
+{
+	ctx->keygen_info = dat;
+	ctx->keygen_info_count = datlen;
+}
+
+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)
+{
+	return ctx->data;
+}
+
+EVP_PKEY *
+EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
+{
+	return ctx->pkey;
+}
+
+EVP_PKEY *
+EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx)
+{
+	return ctx->peerkey;
+}
+
+void
+EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
+{
+	ctx->app_data = data;
+}
+
+void *
+EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
+{
+	return ctx->app_data;
+}
+
+void
+EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
+    int (*init)(EVP_PKEY_CTX *ctx))
+{
+	pmeth->init = init;
+}
+
+void
+EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
+    int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src))
+{
+	pmeth->copy = copy;
+}
+
+void
+EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
+    void (*cleanup)(EVP_PKEY_CTX *ctx))
+{
+	pmeth->cleanup = cleanup;
+}
+
+void
+EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
+    int (*paramgen_init)(EVP_PKEY_CTX *ctx),
+    int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey))
+{
+	pmeth->paramgen_init = paramgen_init;
+	pmeth->paramgen = paramgen;
+}
+
+void
+EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
+    int (*keygen_init)(EVP_PKEY_CTX *ctx),
+    int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey))
+{
+	pmeth->keygen_init = keygen_init;
+	pmeth->keygen = keygen;
+}
+
+void
+EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
+    int (*sign_init)(EVP_PKEY_CTX *ctx),
+    int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    const unsigned char *tbs, size_t tbslen))
+{
+	pmeth->sign_init = sign_init;
+	pmeth->sign = sign;
+}
+
+void
+EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
+    int (*verify_init)(EVP_PKEY_CTX *ctx),
+    int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
+    const unsigned char *tbs, size_t tbslen))
+{
+	pmeth->verify_init = verify_init;
+	pmeth->verify = verify;
+}
+
+void
+EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
+    int (*verify_recover_init)(EVP_PKEY_CTX *ctx),
+    int (*verify_recover)(EVP_PKEY_CTX *ctx,
+    unsigned char *sig, size_t *siglen,
+    const unsigned char *tbs, size_t tbslen))
+{
+	pmeth->verify_recover_init = verify_recover_init;
+	pmeth->verify_recover = verify_recover;
+}
+
+void
+EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
+    int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
+    int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    EVP_MD_CTX *mctx))
+{
+	pmeth->signctx_init = signctx_init;
+	pmeth->signctx = signctx;
+}
+
+void
+EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
+    int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
+    int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen,
+    EVP_MD_CTX *mctx))
+{
+	pmeth->verifyctx_init = verifyctx_init;
+	pmeth->verifyctx = verifyctx;
+}
+
+void
+EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
+    int (*encrypt_init)(EVP_PKEY_CTX *ctx),
+    int (*encryptfn)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+    const unsigned char *in, size_t inlen))
+{
+	pmeth->encrypt_init = encrypt_init;
+	pmeth->encrypt = encryptfn;
+}
+
+void
+EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
+    int (*decrypt_init)(EVP_PKEY_CTX *ctx),
+    int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+    const unsigned char *in, size_t inlen))
+{
+	pmeth->decrypt_init = decrypt_init;
+	pmeth->decrypt = decrypt;
+}
+
+void
+EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
+    int (*derive_init)(EVP_PKEY_CTX *ctx),
+    int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen))
+{
+	pmeth->derive_init = derive_init;
+	pmeth->derive = derive;
+}
+
+void
+EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
+    int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2),
+    int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value))
+{
+	pmeth->ctrl = ctrl;
+	pmeth->ctrl_str = ctrl_str;
+}
+
+void
+EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, int (*check)(EVP_PKEY *pkey))
+{
+	pmeth->check = check;
+}
+
+void
+EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
+    int (*public_check)(EVP_PKEY *pkey))
+{
+	pmeth->public_check = public_check;
+}
+
+void
+EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
+    int (*param_check)(EVP_PKEY *pkey))
+{
+	pmeth->param_check = param_check;
+}
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
new file mode 100644
index 0000000..17db16e
--- /dev/null
+++ b/crypto/ex_data.c
@@ -0,0 +1,637 @@
+/* $OpenBSD: ex_data.c,v 1.23 2023/07/28 10:19:20 tb Exp $ */
+
+/*
+ * Overhaul notes;
+ *
+ * This code is now *mostly* thread-safe. It is now easier to understand in what
+ * ways it is safe and in what ways it is not, which is an improvement. Firstly,
+ * all per-class stacks and index-counters for ex_data are stored in the same
+ * global LHASH table (keyed by class). This hash table uses locking for all
+ * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be
+ * called when no other threads can possibly race against it (even if it was
+ * locked, the race would mean it's possible the hash table might have been
+ * recreated after the cleanup). As classes can only be added to the hash table,
+ * and within each class, the stack of methods can only be incremented, the
+ * locking mechanics are simpler than they would otherwise be. For example, the
+ * new/dup/free ex_data functions will lock the hash table, copy the method
+ * pointers it needs from the relevant class, then unlock the hash table before
+ * actually applying those method pointers to the task of the new/dup/free
+ * operations. As they can't be removed from the method-stack, only
+ * supplemented, there's no race conditions associated with using them outside
+ * the lock. The get/set_ex_data functions are not locked because they do not
+ * involve this global state at all - they operate directly with a previously
+ * obtained per-class method index and a particular "ex_data" variable. These
+ * variables are usually instantiated per-context (eg. each RSA structure has
+ * one) so locking on read/write access to that variable can be locked locally
+ * if required (eg. using the "RSA" lock to synchronise access to a
+ * per-RSA-structure ex_data variable if required).
+ * [Geoff]
+ */
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+typedef struct crypto_ex_data_func_st {
+	long argl;	/* Arbitrary long */
+	void *argp;	/* Arbitrary void * */
+	CRYPTO_EX_new *new_func;
+	CRYPTO_EX_free *free_func;
+	CRYPTO_EX_dup *dup_func;
+} CRYPTO_EX_DATA_FUNCS;
+
+DECLARE_STACK_OF(CRYPTO_EX_DATA_FUNCS)
+
+#define sk_CRYPTO_EX_DATA_FUNCS_new_null() SKM_sk_new_null(CRYPTO_EX_DATA_FUNCS)
+#define sk_CRYPTO_EX_DATA_FUNCS_num(st) SKM_sk_num(CRYPTO_EX_DATA_FUNCS, (st))
+#define sk_CRYPTO_EX_DATA_FUNCS_value(st, i) SKM_sk_value(CRYPTO_EX_DATA_FUNCS, (st), (i))
+#define sk_CRYPTO_EX_DATA_FUNCS_set(st, i, val) SKM_sk_set(CRYPTO_EX_DATA_FUNCS, (st), (i), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_push(st, val) SKM_sk_push(CRYPTO_EX_DATA_FUNCS, (st), (val))
+#define sk_CRYPTO_EX_DATA_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_EX_DATA_FUNCS, (st), (free_func))
+
+/* An opaque type representing an implementation of "ex_data" support */
+typedef struct st_CRYPTO_EX_DATA_IMPL	CRYPTO_EX_DATA_IMPL;
+
+/* What an "implementation of ex_data functionality" looks like */
+struct st_CRYPTO_EX_DATA_IMPL {
+	/*********************/
+	/* GLOBAL OPERATIONS */
+	/* Return a new class index */
+	int (*cb_new_class)(void);
+	/* Cleanup all state used by the implementation */
+	void (*cb_cleanup)(void);
+	/************************/
+	/* PER-CLASS OPERATIONS */
+	/* Get a new method index within a class */
+	int (*cb_get_new_index)(int class_index, long argl, void *argp,
+	    CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+	    CRYPTO_EX_free *free_func);
+	/* Initialise a new CRYPTO_EX_DATA of a given class */
+	int (*cb_new_ex_data)(int class_index, void *obj,
+	    CRYPTO_EX_DATA *ad);
+	/* Duplicate a CRYPTO_EX_DATA of a given class onto a copy */
+	int (*cb_dup_ex_data)(int class_index, CRYPTO_EX_DATA *to,
+	    CRYPTO_EX_DATA *from);
+	/* Cleanup a CRYPTO_EX_DATA of a given class */
+	void (*cb_free_ex_data)(int class_index, void *obj,
+	    CRYPTO_EX_DATA *ad);
+};
+
+/* The implementation we use at run-time */
+static const CRYPTO_EX_DATA_IMPL *impl = NULL;
+
+/* To call "impl" functions, use this macro rather than referring to 'impl' directly, eg.
+ * EX_IMPL(get_new_index)(...);
+*/
+#define EX_IMPL(a) impl->cb_##a
+
+/* Predeclare the "default" ex_data implementation */
+static int int_new_class(void);
+static void int_cleanup(void);
+static int int_get_new_index(int class_index, long argl, void *argp,
+    CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+    CRYPTO_EX_free *free_func);
+static int int_new_ex_data(int class_index, void *obj,
+    CRYPTO_EX_DATA *ad);
+static int int_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
+    CRYPTO_EX_DATA *from);
+static void int_free_ex_data(int class_index, void *obj,
+    CRYPTO_EX_DATA *ad);
+
+static CRYPTO_EX_DATA_IMPL impl_default = {
+	int_new_class,
+	int_cleanup,
+	int_get_new_index,
+	int_new_ex_data,
+	int_dup_ex_data,
+	int_free_ex_data
+};
+
+/* Internal function that checks whether "impl" is set and if not, sets it to
+ * the default. */
+static void
+impl_check(void)
+{
+	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+	if (!impl)
+		impl = &impl_default;
+	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+}
+/* A macro wrapper for impl_check that first uses a non-locked test before
+ * invoking the function (which checks again inside a lock). */
+#define IMPL_CHECK if(!impl) impl_check();
+
+/****************************************************************************/
+/* Interal (default) implementation of "ex_data" support. API functions are
+ * further down. */
+
+/* The type that represents what each "class" used to implement locally. A STACK
+ * of CRYPTO_EX_DATA_FUNCS plus a index-counter. The 'class_index' is the global
+ * value representing the class that is used to distinguish these items. */
+typedef struct st_ex_class_item {
+	int class_index;
+	STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth;
+	int meth_num;
+} EX_CLASS_ITEM;
+
+/* When assigning new class indexes, this is our counter */
+#define CRYPTO_EX_INDEX_USER		100
+static int ex_class = CRYPTO_EX_INDEX_USER;
+
+/* The global hash table of EX_CLASS_ITEM items */
+DECLARE_LHASH_OF(EX_CLASS_ITEM);
+static LHASH_OF(EX_CLASS_ITEM) *ex_data = NULL;
+
+/* The callbacks required in the "ex_data" hash table */
+static unsigned long
+ex_class_item_hash(const EX_CLASS_ITEM *a)
+{
+	return a->class_index;
+}
+
+static IMPLEMENT_LHASH_HASH_FN(ex_class_item, EX_CLASS_ITEM)
+
+static int
+ex_class_item_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b)
+{
+	return a->class_index - b->class_index;
+}
+
+static IMPLEMENT_LHASH_COMP_FN(ex_class_item, EX_CLASS_ITEM)
+
+/* Internal functions used by the "impl_default" implementation to access the
+ * state */
+
+static int
+ex_data_check(void)
+{
+	int toret = 1;
+	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+	if (!ex_data &&
+	    (ex_data = lh_EX_CLASS_ITEM_new()) == NULL)
+		toret = 0;
+	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+	return toret;
+}
+/* This macros helps reduce the locking from repeated checks because the
+ * ex_data_check() function checks ex_data again inside a lock. */
+#define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail}
+
+/* This "inner" callback is used by the callback function that follows it */
+static void
+def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs)
+{
+	free(funcs);
+}
+
+/* This callback is used in lh_doall to destroy all EX_CLASS_ITEM values from
+ * "ex_data" prior to the ex_data hash table being itself destroyed. Doesn't do
+ * any locking. */
+static void
+def_cleanup_cb(void *a_void)
+{
+	EX_CLASS_ITEM *item = (EX_CLASS_ITEM *)a_void;
+	sk_CRYPTO_EX_DATA_FUNCS_pop_free(item->meth, def_cleanup_util_cb);
+	free(item);
+}
+
+/* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a
+ * given class. Handles locking. */
+static EX_CLASS_ITEM *
+def_get_class(int class_index)
+{
+	EX_CLASS_ITEM d, *p, *gen;
+	EX_DATA_CHECK(return NULL;)
+	d.class_index = class_index;
+	if (!OPENSSL_init_crypto(0, NULL))
+		return NULL;
+	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+	p = lh_EX_CLASS_ITEM_retrieve(ex_data, &d);
+	if (!p) {
+		gen = malloc(sizeof(EX_CLASS_ITEM));
+		if (gen) {
+			gen->class_index = class_index;
+			gen->meth_num = 1;
+			gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null();
+			if (!gen->meth)
+				free(gen);
+			else {
+				/* Because we're inside the ex_data lock, the
+				 * return value from the insert will be NULL */
+				(void)lh_EX_CLASS_ITEM_insert(ex_data, gen);
+				p = gen;
+			}
+		}
+	}
+	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+	if (!p)
+		CRYPTOerror(ERR_R_MALLOC_FAILURE);
+	return p;
+}
+
+/* Add a new method to the given EX_CLASS_ITEM and return the corresponding
+ * index (or -1 for error). Handles locking. */
+static int
+def_add_index(EX_CLASS_ITEM *item, long argl, void *argp,
+    CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	int toret = -1;
+	CRYPTO_EX_DATA_FUNCS *a = malloc(sizeof(CRYPTO_EX_DATA_FUNCS));
+
+	if (!a) {
+		CRYPTOerror(ERR_R_MALLOC_FAILURE);
+		return -1;
+	}
+	a->argl = argl;
+	a->argp = argp;
+	a->new_func = new_func;
+	a->dup_func = dup_func;
+	a->free_func = free_func;
+	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+	while (sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) <= item->meth_num) {
+		if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, NULL)) {
+			CRYPTOerror(ERR_R_MALLOC_FAILURE);
+			free(a);
+			goto err;
+		}
+	}
+	toret = item->meth_num++;
+	(void)sk_CRYPTO_EX_DATA_FUNCS_set(item->meth, toret, a);
+err:
+	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+	return toret;
+}
+
+/**************************************************************/
+/* The functions in the default CRYPTO_EX_DATA_IMPL structure */
+
+static int
+int_new_class(void)
+{
+	int toret;
+
+	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
+	toret = ex_class++;
+	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
+	return toret;
+}
+
+static void
+int_cleanup(void)
+{
+	EX_DATA_CHECK(return;)
+	lh_EX_CLASS_ITEM_doall(ex_data, def_cleanup_cb);
+	lh_EX_CLASS_ITEM_free(ex_data);
+	ex_data = NULL;
+	impl = NULL;
+}
+
+static int
+int_get_new_index(int class_index, long argl, void *argp,
+    CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
+    CRYPTO_EX_free *free_func)
+{
+	EX_CLASS_ITEM *item = def_get_class(class_index);
+
+	if (!item)
+		return -1;
+	return def_add_index(item, argl, argp, new_func, dup_func, free_func);
+}
+
+/* Thread-safe by copying a class's array of "CRYPTO_EX_DATA_FUNCS" entries in
+ * the lock, then using them outside the lock. NB: Thread-safety only applies to
+ * the global "ex_data" state (ie. class definitions), not thread-safe on 'ad'
+ * itself. */
+static int
+int_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+	int mx, i;
+	void *ptr;
+	CRYPTO_EX_DATA_FUNCS **storage = NULL;
+	EX_CLASS_ITEM *item = def_get_class(class_index);
+
+	if (!item)
+		/* error is already set */
+		return 0;
+	ad->sk = NULL;
+	CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+	mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
+	if (mx > 0) {
+		storage = reallocarray(NULL, mx, sizeof(CRYPTO_EX_DATA_FUNCS*));
+		if (!storage)
+			goto skip;
+		for (i = 0; i < mx; i++)
+			storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(
+			    item->meth, i);
+	}
+skip:
+	CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+	if ((mx > 0) && !storage) {
+		CRYPTOerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	for (i = 0; i < mx; i++) {
+		if (storage[i] && storage[i]->new_func) {
+			ptr = CRYPTO_get_ex_data(ad, i);
+			storage[i]->new_func(obj, ptr, ad, i,
+			    storage[i]->argl, storage[i]->argp);
+		}
+	}
+	free(storage);
+	return 1;
+}
+
+/* Same thread-safety notes as for "int_new_ex_data" */
+static int
+int_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from)
+{
+	int mx, j, i;
+	char *ptr;
+	CRYPTO_EX_DATA_FUNCS **storage = NULL;
+	EX_CLASS_ITEM *item;
+
+	if (!from->sk)
+		/* 'to' should be "blank" which *is* just like 'from' */
+		return 1;
+	if ((item = def_get_class(class_index)) == NULL)
+		return 0;
+	CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+	mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
+	j = sk_void_num(from->sk);
+	if (j < mx)
+		mx = j;
+	if (mx > 0) {
+		storage = reallocarray(NULL, mx, sizeof(CRYPTO_EX_DATA_FUNCS*));
+		if (!storage)
+			goto skip;
+		for (i = 0; i < mx; i++)
+			storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(
+			    item->meth, i);
+	}
+skip:
+	CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+	if ((mx > 0) && !storage) {
+		CRYPTOerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	for (i = 0; i < mx; i++) {
+		ptr = CRYPTO_get_ex_data(from, i);
+		if (storage[i] && storage[i]->dup_func)
+			storage[i]->dup_func(to, from, &ptr, i,
+			    storage[i]->argl, storage[i]->argp);
+		CRYPTO_set_ex_data(to, i, ptr);
+	}
+	free(storage);
+	return 1;
+}
+
+/* Same thread-safety notes as for "int_new_ex_data" */
+static void
+int_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+	int mx, i;
+	EX_CLASS_ITEM *item;
+	void *ptr;
+	CRYPTO_EX_DATA_FUNCS **storage = NULL;
+
+	if ((item = def_get_class(class_index)) == NULL)
+		return;
+	CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
+	mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
+	if (mx > 0) {
+		storage = reallocarray(NULL, mx, sizeof(CRYPTO_EX_DATA_FUNCS*));
+		if (!storage)
+			goto skip;
+		for (i = 0; i < mx; i++)
+			storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(
+			    item->meth, i);
+	}
+skip:
+	CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
+	if ((mx > 0) && !storage) {
+		CRYPTOerror(ERR_R_MALLOC_FAILURE);
+		return;
+	}
+	for (i = 0; i < mx; i++) {
+		if (storage[i] && storage[i]->free_func) {
+			ptr = CRYPTO_get_ex_data(ad, i);
+			storage[i]->free_func(obj, ptr, ad, i,
+			    storage[i]->argl, storage[i]->argp);
+		}
+	}
+	free(storage);
+	if (ad->sk) {
+		sk_void_free(ad->sk);
+		ad->sk = NULL;
+	}
+}
+
+/********************************************************************/
+/* API functions that defer all "state" operations to the "ex_data"
+ * implementation we have set. */
+
+/* Release all "ex_data" state to prevent memory leaks. This can't be made
+ * thread-safe without overhauling a lot of stuff, and shouldn't really be
+ * called under potential race-conditions anyway (it's for program shutdown
+ * after all). */
+void
+CRYPTO_cleanup_all_ex_data(void)
+{
+	IMPL_CHECK
+	EX_IMPL(cleanup)();
+}
+LCRYPTO_ALIAS(CRYPTO_cleanup_all_ex_data);
+
+/* Inside an existing class, get/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 ret = -1;
+
+	IMPL_CHECK
+	ret = EX_IMPL(get_new_index)(class_index,
+	    argl, argp, new_func, dup_func, free_func);
+	return ret;
+}
+LCRYPTO_ALIAS(CRYPTO_get_ex_new_index);
+
+/* 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 */
+int
+CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+	IMPL_CHECK
+	return EX_IMPL(new_ex_data)(class_index, obj, ad);
+}
+LCRYPTO_ALIAS(CRYPTO_new_ex_data);
+
+/* Duplicate a CRYPTO_EX_DATA variable - including calling dup() callbacks for
+ * each index in the class used by this variable */
+int
+CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from)
+{
+	IMPL_CHECK
+	return EX_IMPL(dup_ex_data)(class_index, to, from);
+}
+LCRYPTO_ALIAS(CRYPTO_dup_ex_data);
+
+/* Cleanup a CRYPTO_EX_DATA variable - including calling free() callbacks for
+ * each index in the class used by this variable */
+void
+CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
+{
+	IMPL_CHECK
+	EX_IMPL(free_ex_data)(class_index, obj, ad);
+}
+LCRYPTO_ALIAS(CRYPTO_free_ex_data);
+
+/* For a given CRYPTO_EX_DATA variable, set the value corresponding to a
+ * particular index in the class used by this variable */
+int
+CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val)
+{
+	int i;
+
+	if (ad->sk == NULL) {
+		if ((ad->sk = sk_void_new_null()) == NULL) {
+			CRYPTOerror(ERR_R_MALLOC_FAILURE);
+			return (0);
+		}
+	}
+	i = sk_void_num(ad->sk);
+
+	while (i <= idx) {
+		if (!sk_void_push(ad->sk, NULL)) {
+			CRYPTOerror(ERR_R_MALLOC_FAILURE);
+			return (0);
+		}
+		i++;
+	}
+	sk_void_set(ad->sk, idx, val);
+	return (1);
+}
+LCRYPTO_ALIAS(CRYPTO_set_ex_data);
+
+/* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a
+ * particular index in the class used by this variable */
+void *
+CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx)
+{
+	if (ad->sk == NULL)
+		return (0);
+	else if (idx >= sk_void_num(ad->sk))
+		return (0);
+	else
+		return (sk_void_value(ad->sk, idx));
+}
+LCRYPTO_ALIAS(CRYPTO_get_ex_data);
diff --git a/crypto/gost/gost2814789.c b/crypto/gost/gost2814789.c
new file mode 100644
index 0000000..dac3a8e
--- /dev/null
+++ b/crypto/gost/gost2814789.c
@@ -0,0 +1,480 @@
+/* $OpenBSD: gost2814789.c,v 1.9 2023/07/08 14:30:44 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+
+#include "gost_local.h"
+
+static inline unsigned int
+f(const GOST2814789_KEY *c, unsigned int x)
+{
+	return  c->k87[(x>>24) & 255] | c->k65[(x>>16) & 255]|
+		c->k43[(x>> 8) & 255] | c->k21[(x    ) & 255];
+}
+
+void
+Gost2814789_encrypt(const unsigned char *in, unsigned char *out,
+    const GOST2814789_KEY *key)
+{
+	unsigned int n1, n2; /* As named in the GOST */
+
+	c2l(in, n1);
+	c2l(in, n2);
+
+	/* Instead of swapping halves, swap names each round */
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
+	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
+	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
+	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
+
+	l2c(n2, out);
+	l2c(n1, out);
+}
+
+void
+Gost2814789_decrypt(const unsigned char *in, unsigned char *out,
+    const GOST2814789_KEY *key)
+{
+	unsigned int n1, n2; /* As named in the GOST */
+
+	c2l(in, n1);
+	c2l(in, n2);
+
+	/* Instead of swapping halves, swap names each round */
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
+	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
+	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
+	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
+
+	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
+	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
+	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
+	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
+
+	n2 ^= f(key, n1 + key->key[7]); n1 ^= f(key, n2 + key->key[6]);
+	n2 ^= f(key, n1 + key->key[5]); n1 ^= f(key, n2 + key->key[4]);
+	n2 ^= f(key, n1 + key->key[3]); n1 ^= f(key, n2 + key->key[2]);
+	n2 ^= f(key, n1 + key->key[1]); n1 ^= f(key, n2 + key->key[0]);
+
+	l2c(n2, out);
+	l2c(n1, out);
+}
+
+static void
+Gost2814789_mac(const unsigned char *in, unsigned char *mac,
+    GOST2814789_KEY *key)
+{
+	unsigned int n1, n2; /* As named in the GOST */
+	unsigned char *p;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		mac[i] ^= in[i];
+
+	p = mac;
+	c2l(p, n1);
+	c2l(p, n2);
+
+	/* Instead of swapping halves, swap names each round */
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	n2 ^= f(key, n1 + key->key[0]); n1 ^= f(key, n2 + key->key[1]);
+	n2 ^= f(key, n1 + key->key[2]); n1 ^= f(key, n2 + key->key[3]);
+	n2 ^= f(key, n1 + key->key[4]); n1 ^= f(key, n2 + key->key[5]);
+	n2 ^= f(key, n1 + key->key[6]); n1 ^= f(key, n2 + key->key[7]);
+
+	p = mac;
+	l2c(n1, p);
+	l2c(n2, p);
+}
+
+void
+Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    GOST2814789_KEY *key, const int enc)
+{
+	if (key->key_meshing && key->count == 1024) {
+		Gost2814789_cryptopro_key_mesh(key);
+		key->count = 0;
+	}
+
+	if (enc)
+		Gost2814789_encrypt(in, out, key);
+	else
+		Gost2814789_decrypt(in, out, key);
+}
+LCRYPTO_ALIAS(Gost2814789_ecb_encrypt);
+
+static inline void
+Gost2814789_encrypt_mesh(unsigned char *iv, GOST2814789_KEY *key)
+{
+	if (key->key_meshing && key->count == 1024) {
+		Gost2814789_cryptopro_key_mesh(key);
+		Gost2814789_encrypt(iv, iv, key);
+		key->count = 0;
+	}
+	Gost2814789_encrypt(iv, iv, key);
+	key->count += 8;
+}
+
+static inline void
+Gost2814789_mac_mesh(const unsigned char *data, unsigned char *mac,
+    GOST2814789_KEY *key)
+{
+	if (key->key_meshing && key->count == 1024) {
+		Gost2814789_cryptopro_key_mesh(key);
+		key->count = 0;
+	}
+	Gost2814789_mac(data, mac, key);
+	key->count += 8;
+}
+
+void
+Gost2814789_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, GOST2814789_KEY *key, unsigned char *ivec, int *num,
+    const int enc)
+{
+	unsigned int n;
+	size_t l = 0;
+
+	n = *num;
+
+	if (enc) {
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+		if (8 % sizeof(size_t) == 0) do { /* always true actually */
+			while (n && len) {
+				*(out++) = ivec[n] ^= *(in++);
+				--len;
+				n = (n + 1) % 8;
+			}
+#ifdef __STRICT_ALIGNMENT
+			if (((size_t)in | (size_t)out | (size_t)ivec) %
+			    sizeof(size_t) != 0)
+				break;
+#endif
+			while (len >= 8) {
+				Gost2814789_encrypt_mesh(ivec, key);
+				for (; n < 8; n += sizeof(size_t)) {
+					*(size_t*)(out + n) =
+					*(size_t*)(ivec + n) ^=
+					    *(size_t*)(in + n);
+				}
+				len -= 8;
+				out += 8;
+				in  += 8;
+				n = 0;
+			}
+			if (len) {
+				Gost2814789_encrypt_mesh(ivec, key);
+				while (len--) {
+					out[n] = ivec[n] ^= in[n];
+					++n;
+				}
+			}
+			*num = n;
+			return;
+		} while (0);
+		/* the rest would be commonly eliminated by x86* compiler */
+#endif
+		while (l= 8) {
+				Gost2814789_encrypt_mesh(ivec, key);
+				for (; n < 8; n += sizeof(size_t)) {
+					size_t t = *(size_t*)(in + n);
+					*(size_t*)(out + n) =
+					    *(size_t*)(ivec + n) ^ t;
+					*(size_t*)(ivec + n) = t;
+				}
+				len -= 8;
+				out += 8;
+				in  += 8;
+				n = 0;
+			}
+			if (len) {
+				Gost2814789_encrypt_mesh(ivec, key);
+				while (len--) {
+					unsigned char c;
+
+					out[n] = ivec[n] ^ (c = in[n]);
+					ivec[n] = c;
+					++n;
+				}
+ 			}
+			*num = n;
+			return;
+		} while (0);
+		/* the rest would be commonly eliminated by x86* compiler */
+#endif
+		while (l < len) {
+			unsigned char c;
+
+			if (n == 0) {
+				Gost2814789_encrypt_mesh(ivec, key);
+			}
+			out[l] = ivec[n] ^ (c = in[l]); ivec[n] = c;
+			++l;
+			n = (n + 1) % 8;
+		}
+		*num = n;
+	}
+}
+LCRYPTO_ALIAS(Gost2814789_cfb64_encrypt);
+
+static inline void
+Gost2814789_cnt_next(unsigned char *ivec, unsigned char *out,
+    GOST2814789_KEY *key)
+{
+	unsigned char *p = ivec, *p2 = ivec;
+	unsigned int val, val2;
+
+	if (key->count == 0)
+		Gost2814789_encrypt(ivec, ivec, key);
+
+	if (key->key_meshing && key->count == 1024) {
+		Gost2814789_cryptopro_key_mesh(key);
+		Gost2814789_encrypt(ivec, ivec, key);
+		key->count = 0;
+	}
+
+	c2l(p, val);
+	val2 = val + 0x01010101;
+	l2c(val2, p2);
+
+	c2l(p, val);
+	val2 = val + 0x01010104;
+	if (val > val2) /* overflow */
+		val2++;
+	l2c(val2, p2);
+
+	Gost2814789_encrypt(ivec, out, key);
+	key->count += 8;
+}
+
+void
+Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+    GOST2814789_KEY *key, unsigned char *ivec, unsigned char *cnt_buf, int *num)
+{
+	unsigned int n;
+	size_t l = 0;
+
+	n = *num;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (8 % sizeof(size_t) == 0) do { /* always true actually */
+		while (n && len) {
+			*(out++) = *(in++) ^ cnt_buf[n];
+			--len;
+			n = (n + 1) % 8;
+		}
+
+#ifdef __STRICT_ALIGNMENT
+		if (((size_t)in | (size_t)out | (size_t)ivec) %
+		    sizeof(size_t) != 0)
+			break;
+#endif
+		while (len >= 8) {
+			Gost2814789_cnt_next(ivec, cnt_buf, key);
+			for (; n < 8; n += sizeof(size_t))
+				*(size_t *)(out + n) = *(size_t *)(in + n) ^
+				    *(size_t *)(cnt_buf + n);
+			len -= 8;
+			out += 8;
+			in  += 8;
+			n = 0;
+		}
+		if (len) {
+			Gost2814789_cnt_next(ivec, cnt_buf, key);
+			while (len--) {
+				out[n] = in[n] ^ cnt_buf[n];
+				++n;
+			}
+		}
+		*num = n;
+		return;
+	} while(0);
+	/* the rest would be commonly eliminated by x86* compiler */
+#endif
+	while (l < len) {
+		if (n==0)
+			Gost2814789_cnt_next(ivec, cnt_buf, key);
+		out[l] = in[l] ^ cnt_buf[n];
+		++l;
+		n = (n + 1) % 8;
+	}
+
+	*num=n;
+}
+LCRYPTO_ALIAS(Gost2814789_cnt_encrypt);
+
+int
+GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid)
+{
+	c->Nl = c->Nh = c->num = 0;
+	memset(c->mac, 0, 8);
+	return Gost2814789_set_sbox(&c->cipher, nid);
+}
+LCRYPTO_ALIAS(GOST2814789IMIT_Init);
+
+static void
+GOST2814789IMIT_block_data_order(GOST2814789IMIT_CTX *ctx,
+    const unsigned char *p, size_t num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		Gost2814789_mac_mesh(p, ctx->mac, &ctx->cipher);
+		p += 8;
+	}
+}
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_CBLOCK	GOST2814789IMIT_CBLOCK
+#define HASH_LONG	GOST2814789IMIT_LONG
+#define HASH_CTX	GOST2814789IMIT_CTX
+#define HASH_UPDATE	GOST2814789IMIT_Update
+#define HASH_TRANSFORM	GOST2814789IMIT_Transform
+#define HASH_NO_FINAL	1
+#define HASH_BLOCK_DATA_ORDER	GOST2814789IMIT_block_data_order
+
+#include "md32_common.h"
+LCRYPTO_ALIAS(GOST2814789IMIT_Update);
+LCRYPTO_ALIAS(GOST2814789IMIT_Transform);
+
+int
+GOST2814789IMIT_Final(unsigned char *md, GOST2814789IMIT_CTX *c)
+{
+	if (c->num) {
+		memset(c->data + c->num, 0, 8 - c->num);
+		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
+	}
+	if (c->Nl <= 8 * 8 && c->Nl > 0 && c->Nh == 0) {
+		memset(c->data, 0, 8);
+		Gost2814789_mac_mesh(c->data, c->mac, &c->cipher);
+	}
+	memcpy(md, c->mac, 4);
+	return 1;
+}
+LCRYPTO_ALIAS(GOST2814789IMIT_Final);
+
+unsigned char *
+GOST2814789IMIT(const unsigned char *d, size_t n, unsigned char *md, int nid,
+    const unsigned char *key, const unsigned char *iv)
+{
+	GOST2814789IMIT_CTX c;
+	static unsigned char m[GOST2814789IMIT_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	GOST2814789IMIT_Init(&c, nid);
+	memcpy(c.mac, iv, 8);
+	Gost2814789_set_key(&c.cipher, key, 256);
+	GOST2814789IMIT_Update(&c, d, n);
+	GOST2814789IMIT_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(GOST2814789IMIT);
+
+#endif
diff --git a/crypto/gost/gost89_keywrap.c b/crypto/gost/gost89_keywrap.c
new file mode 100644
index 0000000..9bfc5b4
--- /dev/null
+++ b/crypto/gost/gost89_keywrap.c
@@ -0,0 +1,138 @@
+/* $OpenBSD: gost89_keywrap.c,v 1.4 2022/11/26 16:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+
+#include 
+
+#include "gost_local.h"
+
+static void
+key_diversify_crypto_pro(GOST2814789_KEY *ctx, const unsigned char *inputKey,
+    const unsigned char *ukm, unsigned char *outputKey)
+{
+	unsigned long k, s1, s2;
+	int i, mask;
+	unsigned char S[8];
+	unsigned char *p;
+
+	memcpy(outputKey, inputKey, 32);
+	for (i = 0; i < 8; i++) {
+		/* Make array of integers from key */
+		/* Compute IV S */
+		s1 = 0, s2 = 0;
+		p = outputKey;
+		for (mask = 1; mask < 256; mask <<= 1) {
+			c2l(p, k);
+			if (mask & ukm[i]) {
+				s1 += k;
+			} else {
+				s2 += k;
+			}
+		}
+		p = S;
+		l2c (s1, p);
+		l2c (s2, p);
+		Gost2814789_set_key(ctx, outputKey, 256);
+		mask = 0;
+		Gost2814789_cfb64_encrypt(outputKey, outputKey, 32, ctx, S,
+		    &mask, 1);
+	}
+}
+
+int
+gost_key_wrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
+    const unsigned char *ukm, const unsigned char *sessionKey,
+    unsigned char *wrappedKey)
+{
+	GOST2814789_KEY ctx;
+	unsigned char kek_ukm[32];
+
+	Gost2814789_set_sbox(&ctx, nid);
+	key_diversify_crypto_pro(&ctx, keyExchangeKey, ukm, kek_ukm);
+	Gost2814789_set_key(&ctx, kek_ukm, 256);
+	memcpy(wrappedKey, ukm, 8);
+	Gost2814789_encrypt(sessionKey +  0, wrappedKey + 8 +  0, &ctx);
+	Gost2814789_encrypt(sessionKey +  8, wrappedKey + 8 +  8, &ctx);
+	Gost2814789_encrypt(sessionKey + 16, wrappedKey + 8 + 16, &ctx);
+	Gost2814789_encrypt(sessionKey + 24, wrappedKey + 8 + 24, &ctx);
+	GOST2814789IMIT(sessionKey, 32, wrappedKey + 40, nid, kek_ukm, ukm);
+	return 1;
+}
+
+int
+gost_key_unwrap_crypto_pro(int nid, const unsigned char *keyExchangeKey,
+    const unsigned char *wrappedKey, unsigned char *sessionKey)
+{
+	unsigned char kek_ukm[32], cek_mac[4];
+	GOST2814789_KEY ctx;
+
+	Gost2814789_set_sbox(&ctx, nid);
+	/* First 8 bytes of wrapped Key is ukm */
+	key_diversify_crypto_pro(&ctx, keyExchangeKey, wrappedKey, kek_ukm);
+	Gost2814789_set_key(&ctx, kek_ukm, 256);
+	Gost2814789_decrypt(wrappedKey + 8 +  0, sessionKey +  0, &ctx);
+	Gost2814789_decrypt(wrappedKey + 8 +  8, sessionKey +  8, &ctx);
+	Gost2814789_decrypt(wrappedKey + 8 + 16, sessionKey + 16, &ctx);
+	Gost2814789_decrypt(wrappedKey + 8 + 24, sessionKey + 24, &ctx);
+
+	GOST2814789IMIT(sessionKey, 32, cek_mac, nid, kek_ukm, wrappedKey);
+	if (memcmp(cek_mac, wrappedKey + 40, 4))
+		return 0;
+
+	return 1;
+}
+
+#endif
diff --git a/crypto/gost/gost89_params.c b/crypto/gost/gost89_params.c
new file mode 100644
index 0000000..ef9c9cd
--- /dev/null
+++ b/crypto/gost/gost89_params.c
@@ -0,0 +1,246 @@
+/* $OpenBSD: gost89_params.c,v 1.4 2023/07/08 14:30:44 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+
+#include "gost_local.h"
+
+/* Substitution blocks from test examples for GOST R 34.11-94*/
+static const gost_subst_block GostR3411_94_TestParamSet = {
+	{0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC},
+	{0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC},
+	{0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE},
+	{0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2},
+	{0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3},
+	{0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB},
+	{0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9},
+	{0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3}
+};
+
+/* Substitution blocks for hash function 1.2.643.2.9.1.6.1  */
+static const gost_subst_block GostR3411_94_CryptoProParamSet = {
+	{0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC},
+	{0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB},
+	{0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3},
+	{0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5},
+	{0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3},
+	{0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD},
+	{0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8},
+	{0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF}
+};
+
+/* Test paramset from GOST 28147 */
+gost_subst_block Gost28147_TestParamSet = {
+	{0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8},
+	{0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD},
+	{0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4},
+	{0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4},
+	{0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8},
+	{0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB},
+	{0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5},
+	{0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6}
+};
+
+
+/* 1.2.643.2.2.31.1 */
+static const gost_subst_block Gost28147_CryptoProParamSetA = {
+	{0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4},
+	{0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE},
+	{0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6},
+	{0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6},
+	{0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6},
+	{0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9},
+	{0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1},
+	{0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5}
+};
+
+/* 1.2.643.2.2.31.2 */
+static const gost_subst_block Gost28147_CryptoProParamSetB = {
+	{0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC},
+	{0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE},
+	{0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5},
+	{0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3},
+	{0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8},
+	{0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4},
+	{0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE},
+	{0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF}
+};
+
+/* 1.2.643.2.2.31.3 */
+static const gost_subst_block Gost28147_CryptoProParamSetC = {
+	{0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8},
+	{0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7},
+	{0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD},
+	{0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7},
+	{0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4},
+	{0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB},
+	{0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3},
+	{0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3}
+};
+
+/* 1.2.643.2.2.31.4 */
+static const gost_subst_block Gost28147_CryptoProParamSetD = {
+	{0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE},
+	{0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7},
+	{0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6},
+	{0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1},
+	{0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8},
+	{0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2},
+	{0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1},
+	{0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3}
+};
+
+static const gost_subst_block Gost28147_TC26ParamSetZ = {
+	{0x1,0x7,0xe,0xd,0x0,0x5,0x8,0x3,0x4,0xf,0xa,0x6,0x9,0xc,0xb,0x2},
+	{0x8,0xe,0x2,0x5,0x6,0x9,0x1,0xc,0xf,0x4,0xb,0x0,0xd,0xa,0x3,0x7},
+	{0x5,0xd,0xf,0x6,0x9,0x2,0xc,0xa,0xb,0x7,0x8,0x1,0x4,0x3,0xe,0x0},
+	{0x7,0xf,0x5,0xa,0x8,0x1,0x6,0xd,0x0,0x9,0x3,0xe,0xb,0x4,0x2,0xc},
+	{0xc,0x8,0x2,0x1,0xd,0x4,0xf,0x6,0x7,0x0,0xa,0x5,0x3,0xe,0x9,0xb},
+	{0xb,0x3,0x5,0x8,0x2,0xf,0xa,0xd,0xe,0x1,0x7,0x4,0xc,0x9,0x6,0x0},
+	{0x6,0x8,0x2,0x3,0x9,0xa,0x5,0xc,0x1,0xe,0x4,0x7,0xb,0xd,0x0,0xf},
+	{0xc,0x4,0x6,0x2,0xa,0x5,0xb,0x9,0xe,0x8,0xd,0x7,0x0,0x3,0xf,0x1}
+};
+
+static const unsigned char CryptoProKeyMeshingKey[] = {
+	0x69, 0x00, 0x72, 0x22,   0x64, 0xC9, 0x04, 0x23,
+	0x8D, 0x3A, 0xDB, 0x96,   0x46, 0xE9, 0x2A, 0xC4,
+	0x18, 0xFE, 0xAC, 0x94,   0x00, 0xED, 0x07, 0x12,
+	0xC0, 0x86, 0xDC, 0xC2,   0xEF, 0x4C, 0xA9, 0x2B
+};
+
+static const struct gost89_parameters_info {
+	int nid;
+	const gost_subst_block *sblock;
+	int key_meshing;
+} gost_cipher_list[] =
+{
+	{NID_id_Gost28147_89_CryptoPro_A_ParamSet,&Gost28147_CryptoProParamSetA,1},
+	{NID_id_Gost28147_89_CryptoPro_B_ParamSet,&Gost28147_CryptoProParamSetB,1},
+	{NID_id_Gost28147_89_CryptoPro_C_ParamSet,&Gost28147_CryptoProParamSetC,1},
+	{NID_id_Gost28147_89_CryptoPro_D_ParamSet,&Gost28147_CryptoProParamSetD,1},
+	{NID_id_tc26_gost_28147_param_Z,&Gost28147_TC26ParamSetZ,1},
+	{NID_id_Gost28147_89_TestParamSet,&Gost28147_TestParamSet,0},
+	{NID_id_GostR3411_94_TestParamSet,&GostR3411_94_TestParamSet,0},
+	{NID_id_GostR3411_94_CryptoProParamSet,&GostR3411_94_CryptoProParamSet,0},
+	{NID_undef,NULL,0}
+};
+
+int
+Gost2814789_set_sbox(GOST2814789_KEY *key, int nid)
+{
+	int i;
+	const gost_subst_block *b = NULL;
+	unsigned int t;
+
+	for (i = 0; gost_cipher_list[i].nid != NID_undef; i++) {
+		if (gost_cipher_list[i].nid != nid)
+			continue;
+
+		b = gost_cipher_list[i].sblock;
+		key->key_meshing = gost_cipher_list[i].key_meshing;
+		break;
+	}
+
+	if (b == NULL)
+		return 0;
+
+	for (i = 0; i < 256; i++) {
+		t = (unsigned int)(b->k8[i >> 4] <<4 | b->k7 [i & 15]) << 24;
+		key->k87[i] = (t << 11) | (t >> 21);
+		t = (unsigned int)(b->k6[i >> 4] <<4 | b->k5 [i & 15]) << 16;
+		key->k65[i] = (t << 11) | (t >> 21);
+		t = (unsigned int)(b->k4[i >> 4] <<4 | b->k3 [i & 15]) << 8;
+		key->k43[i] = (t << 11) | (t >> 21);
+		t = (unsigned int)(b->k2[i >> 4] <<4 | b->k1 [i & 15]) << 0;
+		key->k21[i] = (t << 11) | (t >> 21);
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(Gost2814789_set_sbox);
+
+int
+Gost2814789_set_key(GOST2814789_KEY *key, const unsigned char *userKey,
+    const int bits)
+{
+	int i;
+
+	if (bits != 256)
+		return 0;
+
+	for (i = 0; i < 8; i++)
+		c2l(userKey, key->key[i]);
+
+	key->count = 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(Gost2814789_set_key);
+
+void
+Gost2814789_cryptopro_key_mesh(GOST2814789_KEY *key)
+{
+	unsigned char newkey[32];
+
+	Gost2814789_decrypt(CryptoProKeyMeshingKey +  0, newkey +  0, key);
+	Gost2814789_decrypt(CryptoProKeyMeshingKey +  8, newkey +  8, key);
+	Gost2814789_decrypt(CryptoProKeyMeshingKey + 16, newkey + 16, key);
+	Gost2814789_decrypt(CryptoProKeyMeshingKey + 24, newkey + 24, key);
+
+	Gost2814789_set_key(key, newkey, 256);
+}
+#endif
diff --git a/crypto/gost/gost89imit_ameth.c b/crypto/gost/gost89imit_ameth.c
new file mode 100644
index 0000000..e300b52
--- /dev/null
+++ b/crypto/gost/gost89imit_ameth.c
@@ -0,0 +1,89 @@
+/* $OpenBSD: gost89imit_ameth.c,v 1.4 2022/11/26 16:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+static void
+mackey_free_gost(EVP_PKEY *pk)
+{
+	free(pk->pkey.ptr);
+}
+
+static int
+mac_ctrl_gost(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+	switch (op) {
+	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = NID_id_Gost28147_89_MAC;
+		return 2;
+	}
+	return -2;
+}
+
+const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth = {
+	.pkey_id = EVP_PKEY_GOSTIMIT,
+	.pkey_base_id = EVP_PKEY_GOSTIMIT,
+	.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
+
+	.pem_str = "GOST-MAC",
+	.info = "GOST 28147-89 MAC",
+
+	.pkey_free = mackey_free_gost,
+	.pkey_ctrl = mac_ctrl_gost,
+};
+
+#endif
diff --git a/crypto/gost/gost89imit_pmeth.c b/crypto/gost/gost89imit_pmeth.c
new file mode 100644
index 0000000..63b7ef5
--- /dev/null
+++ b/crypto/gost/gost89imit_pmeth.c
@@ -0,0 +1,248 @@
+/* $OpenBSD: gost89imit_pmeth.c,v 1.5 2022/11/26 16:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+#include  /* For string_to_hex */
+
+#include "evp_local.h"
+#include "gost_local.h"
+
+struct gost_mac_pmeth_data {
+	EVP_MD *md;
+	unsigned char key[32];
+	unsigned key_set :1;
+};
+
+static int
+pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
+{
+	struct gost_mac_pmeth_data *data;
+
+	data = calloc(1, sizeof(struct gost_mac_pmeth_data));
+	if (data == NULL)
+		return 0;
+	EVP_PKEY_CTX_set_data(ctx, data);
+	return 1;
+}
+
+static void
+pkey_gost_mac_cleanup(EVP_PKEY_CTX *ctx)
+{
+	struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+	free(data);
+}
+
+static int
+pkey_gost_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	struct gost_mac_pmeth_data *dst_data, *src_data;
+
+	if (pkey_gost_mac_init(dst) == 0)
+		return 0;
+
+	src_data = EVP_PKEY_CTX_get_data(src);
+	dst_data = EVP_PKEY_CTX_get_data(dst);
+
+	*dst_data = *src_data;
+
+	return 1;
+}
+
+static int
+pkey_gost_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+	unsigned char *keydata;
+
+	if (!data->key_set) {
+		GOSTerror(GOST_R_MAC_KEY_NOT_SET);
+		return 0;
+	}
+
+	keydata = malloc(32);
+	if (keydata == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	memcpy(keydata, data->key, 32);
+	EVP_PKEY_assign(pkey, NID_id_Gost28147_89_MAC, keydata);
+
+	return 1;
+}
+
+static int
+pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+
+	switch (type) {
+	case EVP_PKEY_CTRL_MD:
+		if (EVP_MD_type(p2) != NID_id_Gost28147_89_MAC) {
+			GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		data->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_SET_MAC_KEY:
+		if (p1 != 32) {
+			GOSTerror(GOST_R_INVALID_MAC_KEY_LENGTH);
+			return 0;
+		}
+
+		memcpy(data->key, p2, 32);
+		data->key_set = 1;
+		return 1;
+
+	case EVP_PKEY_CTRL_DIGESTINIT:
+	    {
+		EVP_MD_CTX *mctx = p2;
+		void *key;
+
+		if (!data->key_set) {
+			EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+			if (pkey == NULL) {
+				GOSTerror(GOST_R_MAC_KEY_NOT_SET);
+				return 0;
+			}
+			key = EVP_PKEY_get0(pkey);
+			if (key == NULL) {
+				GOSTerror(GOST_R_MAC_KEY_NOT_SET);
+				return 0;
+			}
+		} else {
+			key = &(data->key);
+		}
+		if (mctx->digest->md_ctrl == NULL)
+			return 0;
+		return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32 * 8,
+		    key);
+	    }
+
+	}
+
+	return -2;
+}
+
+static int
+pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+	if (value == NULL)
+		return 0;
+	if (strcmp(type, "key") == 0) {
+		void *p = (void *)value;
+		return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY,
+		    strlen(value), p);
+	}
+	if (strcmp(type, "hexkey") == 0) {
+		unsigned char *key;
+		int r;
+		long keylen;
+
+		key = string_to_hex(value, &keylen);
+		if (key == NULL)
+			return 0;
+		r = pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen,
+		    key);
+		free(key);
+		return r;
+	}
+	return -2;
+}
+
+static int
+pkey_gost_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+	return 1;
+}
+
+static int
+pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    EVP_MD_CTX *mctx)
+{
+	/* for platforms where sizeof(int) != sizeof(size_t)*/
+	unsigned int tmpsiglen = *siglen;
+	int ret;
+
+	if (sig == NULL) {
+		*siglen = 4;
+		return 1;
+	}
+
+	ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
+	*siglen = tmpsiglen;
+	return ret;
+}
+
+const EVP_PKEY_METHOD gostimit_pkey_meth = {
+	.pkey_id = EVP_PKEY_GOSTIMIT,
+
+	.init = pkey_gost_mac_init,
+	.cleanup = pkey_gost_mac_cleanup,
+	.copy = pkey_gost_mac_copy,
+
+	.keygen = pkey_gost_mac_keygen,
+
+	.signctx_init = pkey_gost_mac_signctx_init,
+	.signctx = pkey_gost_mac_signctx,
+
+	.ctrl = pkey_gost_mac_ctrl,
+	.ctrl_str = pkey_gost_mac_ctrl_str,
+};
+
+#endif
diff --git a/crypto/gost/gost_asn1.c b/crypto/gost/gost_asn1.c
new file mode 100644
index 0000000..28e3a58
--- /dev/null
+++ b/crypto/gost/gost_asn1.c
@@ -0,0 +1,299 @@
+/**********************************************************************
+ *                          gost_keytrans.c                           *
+ *             Copyright (c) 2005-2006 Cryptocom LTD                  *
+ *         This file is distributed under the same license as OpenSSL *
+ *                                                                    *
+ *   ASN1 structure definition for GOST key transport                 *
+ *          Requires OpenSSL 0.9.9 for compilation                    *
+ **********************************************************************/
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+
+#include "gost_local.h"
+#include "gost_asn1.h"
+
+static const ASN1_TEMPLATE GOST_KEY_TRANSPORT_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_TRANSPORT, key_info),
+		.field_name = "key_info",
+		.item = &GOST_KEY_INFO_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_TRANSPORT, key_agreement_info),
+		.field_name = "key_agreement_info",
+		.item = &GOST_KEY_AGREEMENT_INFO_it,
+	},
+};
+
+const ASN1_ITEM GOST_KEY_TRANSPORT_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = GOST_KEY_TRANSPORT_seq_tt,
+	.tcount = sizeof(GOST_KEY_TRANSPORT_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(GOST_KEY_TRANSPORT),
+	.sname = "GOST_KEY_TRANSPORT",
+};
+
+GOST_KEY_TRANSPORT *
+d2i_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT **a, const unsigned char **in, long len)
+{
+	return (GOST_KEY_TRANSPORT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &GOST_KEY_TRANSPORT_it);
+}
+
+int
+i2d_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_TRANSPORT_it);
+}
+
+GOST_KEY_TRANSPORT *
+GOST_KEY_TRANSPORT_new(void)
+{
+	return (GOST_KEY_TRANSPORT *)ASN1_item_new(&GOST_KEY_TRANSPORT_it);
+}
+
+void
+GOST_KEY_TRANSPORT_free(GOST_KEY_TRANSPORT *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_TRANSPORT_it);
+}
+
+static const ASN1_TEMPLATE GOST_KEY_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_INFO, encrypted_key),
+		.field_name = "encrypted_key",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_INFO, imit),
+		.field_name = "imit",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM GOST_KEY_INFO_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = GOST_KEY_INFO_seq_tt,
+	.tcount = sizeof(GOST_KEY_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(GOST_KEY_INFO),
+	.sname = "GOST_KEY_INFO",
+};
+
+GOST_KEY_INFO *
+d2i_GOST_KEY_INFO(GOST_KEY_INFO **a, const unsigned char **in, long len)
+{
+	return (GOST_KEY_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &GOST_KEY_INFO_it);
+}
+
+int
+i2d_GOST_KEY_INFO(GOST_KEY_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_INFO_it);
+}
+
+GOST_KEY_INFO *
+GOST_KEY_INFO_new(void)
+{
+	return (GOST_KEY_INFO *)ASN1_item_new(&GOST_KEY_INFO_it);
+}
+
+void
+GOST_KEY_INFO_free(GOST_KEY_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_INFO_it);
+}
+
+static const ASN1_TEMPLATE GOST_KEY_AGREEMENT_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_AGREEMENT_INFO, cipher),
+		.field_name = "cipher",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_AGREEMENT_INFO, ephem_key),
+		.field_name = "ephem_key",
+		.item = &X509_PUBKEY_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_AGREEMENT_INFO, eph_iv),
+		.field_name = "eph_iv",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM GOST_KEY_AGREEMENT_INFO_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = GOST_KEY_AGREEMENT_INFO_seq_tt,
+	.tcount = sizeof(GOST_KEY_AGREEMENT_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(GOST_KEY_AGREEMENT_INFO),
+	.sname = "GOST_KEY_AGREEMENT_INFO",
+};
+
+GOST_KEY_AGREEMENT_INFO *
+d2i_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO **a, const unsigned char **in, long len)
+{
+	return (GOST_KEY_AGREEMENT_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &GOST_KEY_AGREEMENT_INFO_it);
+}
+
+int
+i2d_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_AGREEMENT_INFO_it);
+}
+
+GOST_KEY_AGREEMENT_INFO *
+GOST_KEY_AGREEMENT_INFO_new(void)
+{
+	return (GOST_KEY_AGREEMENT_INFO *)ASN1_item_new(&GOST_KEY_AGREEMENT_INFO_it);
+}
+
+void
+GOST_KEY_AGREEMENT_INFO_free(GOST_KEY_AGREEMENT_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_AGREEMENT_INFO_it);
+}
+
+
+static const ASN1_TEMPLATE GOST_KEY_PARAMS_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_PARAMS, key_params),
+		.field_name = "key_params",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_PARAMS, hash_params),
+		.field_name = "hash_params",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(GOST_KEY_PARAMS, cipher_params),
+		.field_name = "cipher_params",
+		.item = &ASN1_OBJECT_it,
+	},
+};
+
+const ASN1_ITEM GOST_KEY_PARAMS_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = GOST_KEY_PARAMS_seq_tt,
+	.tcount = sizeof(GOST_KEY_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(GOST_KEY_PARAMS),
+	.sname = "GOST_KEY_PARAMS",
+};
+
+GOST_KEY_PARAMS *
+d2i_GOST_KEY_PARAMS(GOST_KEY_PARAMS **a, const unsigned char **in, long len)
+{
+	return (GOST_KEY_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &GOST_KEY_PARAMS_it);
+}
+
+int
+i2d_GOST_KEY_PARAMS(GOST_KEY_PARAMS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_KEY_PARAMS_it);
+}
+
+GOST_KEY_PARAMS *
+GOST_KEY_PARAMS_new(void)
+{
+	return (GOST_KEY_PARAMS *)ASN1_item_new(&GOST_KEY_PARAMS_it);
+}
+
+void
+GOST_KEY_PARAMS_free(GOST_KEY_PARAMS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &GOST_KEY_PARAMS_it);
+}
+
+static const ASN1_TEMPLATE GOST_CIPHER_PARAMS_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_CIPHER_PARAMS, iv),
+		.field_name = "iv",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(GOST_CIPHER_PARAMS, enc_param_set),
+		.field_name = "enc_param_set",
+		.item = &ASN1_OBJECT_it,
+	},
+};
+
+const ASN1_ITEM GOST_CIPHER_PARAMS_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = GOST_CIPHER_PARAMS_seq_tt,
+	.tcount = sizeof(GOST_CIPHER_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(GOST_CIPHER_PARAMS),
+	.sname = "GOST_CIPHER_PARAMS",
+};
+
+GOST_CIPHER_PARAMS *
+d2i_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS **a, const unsigned char **in, long len)
+{
+	return (GOST_CIPHER_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &GOST_CIPHER_PARAMS_it);
+}
+LCRYPTO_ALIAS(d2i_GOST_CIPHER_PARAMS);
+
+int
+i2d_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &GOST_CIPHER_PARAMS_it);
+}
+LCRYPTO_ALIAS(i2d_GOST_CIPHER_PARAMS);
+
+GOST_CIPHER_PARAMS *
+GOST_CIPHER_PARAMS_new(void)
+{
+	return (GOST_CIPHER_PARAMS *)ASN1_item_new(&GOST_CIPHER_PARAMS_it);
+}
+LCRYPTO_ALIAS(GOST_CIPHER_PARAMS_new);
+
+void
+GOST_CIPHER_PARAMS_free(GOST_CIPHER_PARAMS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &GOST_CIPHER_PARAMS_it);
+}
+LCRYPTO_ALIAS(GOST_CIPHER_PARAMS_free);
+
+#endif
diff --git a/crypto/gost/gost_asn1.h b/crypto/gost/gost_asn1.h
new file mode 100644
index 0000000..7cabfc7
--- /dev/null
+++ b/crypto/gost/gost_asn1.h
@@ -0,0 +1,107 @@
+/* $OpenBSD: gost_asn1.h,v 1.3 2016/12/21 15:49:29 jsing Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifndef HEADER_GOST_ASN1_H
+#define HEADER_GOST_ASN1_H
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+typedef struct {
+	ASN1_OCTET_STRING *encrypted_key;
+	ASN1_OCTET_STRING *imit;
+} GOST_KEY_INFO;
+
+GOST_KEY_INFO *GOST_KEY_INFO_new(void);
+void GOST_KEY_INFO_free(GOST_KEY_INFO *a);
+GOST_KEY_INFO *d2i_GOST_KEY_INFO(GOST_KEY_INFO **a, const unsigned char **in, long len);
+int i2d_GOST_KEY_INFO(GOST_KEY_INFO *a, unsigned char **out);
+extern const ASN1_ITEM GOST_KEY_INFO_it;
+
+typedef struct {
+	ASN1_OBJECT *cipher;
+	X509_PUBKEY *ephem_key;
+	ASN1_OCTET_STRING *eph_iv;
+} GOST_KEY_AGREEMENT_INFO;
+
+GOST_KEY_AGREEMENT_INFO *GOST_KEY_AGREEMENT_INFO_new(void);
+void GOST_KEY_AGREEMENT_INFO_free(GOST_KEY_AGREEMENT_INFO *a);
+GOST_KEY_AGREEMENT_INFO *d2i_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO **a, const unsigned char **in, long len);
+int i2d_GOST_KEY_AGREEMENT_INFO(GOST_KEY_AGREEMENT_INFO *a, unsigned char **out);
+extern const ASN1_ITEM GOST_KEY_AGREEMENT_INFO_it;
+
+typedef struct {
+	GOST_KEY_INFO *key_info;
+	GOST_KEY_AGREEMENT_INFO *key_agreement_info;
+} GOST_KEY_TRANSPORT;
+
+GOST_KEY_TRANSPORT *GOST_KEY_TRANSPORT_new(void);
+void GOST_KEY_TRANSPORT_free(GOST_KEY_TRANSPORT *a);
+GOST_KEY_TRANSPORT *d2i_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT **a, const unsigned char **in, long len);
+int i2d_GOST_KEY_TRANSPORT(GOST_KEY_TRANSPORT *a, unsigned char **out);
+extern const ASN1_ITEM GOST_KEY_TRANSPORT_it;
+
+typedef struct {
+	ASN1_OBJECT *key_params;
+	ASN1_OBJECT *hash_params;
+	ASN1_OBJECT *cipher_params;
+} GOST_KEY_PARAMS;
+
+GOST_KEY_PARAMS *GOST_KEY_PARAMS_new(void);
+void GOST_KEY_PARAMS_free(GOST_KEY_PARAMS *a);
+GOST_KEY_PARAMS *d2i_GOST_KEY_PARAMS(GOST_KEY_PARAMS **a, const unsigned char **in, long len);
+int i2d_GOST_KEY_PARAMS(GOST_KEY_PARAMS *a, unsigned char **out);
+extern const ASN1_ITEM GOST_KEY_PARAMS_it;
+
+__END_HIDDEN_DECLS
+
+#endif
diff --git a/crypto/gost/gost_err.c b/crypto/gost/gost_err.c
new file mode 100644
index 0000000..380f602
--- /dev/null
+++ b/crypto/gost/gost_err.c
@@ -0,0 +1,106 @@
+/* crypto/gost/gost_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_GOST,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_GOST,0,reason)
+
+static ERR_STRING_DATA GOST_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA GOST_str_reasons[] = {
+	{ERR_REASON(GOST_R_BAD_KEY_PARAMETERS_FORMAT),"bad key parameters format"},
+	{ERR_REASON(GOST_R_BAD_PKEY_PARAMETERS_FORMAT),"bad pkey parameters format"},
+	{ERR_REASON(GOST_R_CANNOT_PACK_EPHEMERAL_KEY),"cannot pack ephemeral key"},
+	{ERR_REASON(GOST_R_CTRL_CALL_FAILED)     ,"ctrl call failed"},
+	{ERR_REASON(GOST_R_ERROR_COMPUTING_SHARED_KEY),"error computing shared key"},
+	{ERR_REASON(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO),"error parsing key transport info"},
+	{ERR_REASON(GOST_R_INCOMPATIBLE_ALGORITHMS),"incompatible algorithms"},
+	{ERR_REASON(GOST_R_INCOMPATIBLE_PEER_KEY),"incompatible peer key"},
+	{ERR_REASON(GOST_R_INVALID_DIGEST_TYPE)  ,"invalid digest type"},
+	{ERR_REASON(GOST_R_INVALID_IV_LENGTH)    ,"invalid iv length"},
+	{ERR_REASON(GOST_R_INVALID_MAC_KEY_LENGTH),"invalid mac key length"},
+	{ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED),"key is not initialized"},
+	{ERR_REASON(GOST_R_KEY_PARAMETERS_MISSING),"key parameters missing"},
+	{ERR_REASON(GOST_R_MAC_KEY_NOT_SET)      ,"mac key not set"},
+	{ERR_REASON(GOST_R_NO_PARAMETERS_SET)    ,"no parameters set"},
+	{ERR_REASON(GOST_R_NO_PEER_KEY)          ,"no peer key"},
+	{ERR_REASON(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR),"no private part of non ephemeral keypair"},
+	{ERR_REASON(GOST_R_PUBLIC_KEY_UNDEFINED) ,"public key undefined"},
+	{ERR_REASON(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED),"random number generator failed"},
+	{ERR_REASON(GOST_R_SIGNATURE_MISMATCH)   ,"signature mismatch"},
+	{ERR_REASON(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q),"signature parts greater than q"},
+	{ERR_REASON(GOST_R_UKM_NOT_SET)          ,"ukm not set"},
+	{0, NULL}
+};
+#endif
+
+void
+ERR_load_GOST_strings(void) {
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(GOST_str_functs[0].error) == NULL) {
+		ERR_load_strings(0,GOST_str_functs);
+		ERR_load_strings(0,GOST_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_GOST_strings);
diff --git a/crypto/gost/gost_local.h b/crypto/gost/gost_local.h
new file mode 100644
index 0000000..db07d06
--- /dev/null
+++ b/crypto/gost/gost_local.h
@@ -0,0 +1,116 @@
+/* $OpenBSD: gost_local.h,v 1.3 2023/07/28 15:50:33 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#ifndef HEADER_GOST_LOCAL_H
+#define HEADER_GOST_LOCAL_H
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+/* Internal representation of GOST substitution blocks */
+typedef struct {
+	unsigned char k8[16];
+	unsigned char k7[16];
+	unsigned char k6[16];
+	unsigned char k5[16];
+	unsigned char k4[16];
+	unsigned char k3[16];
+	unsigned char k2[16];
+	unsigned char k1[16];
+} gost_subst_block;		
+
+#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
+#  define c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4)
+#  define l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4)
+#else
+#define c2l(c,l)	(l =(((unsigned long)(*((c)++)))    ),		\
+			 l|=(((unsigned long)(*((c)++)))<< 8),		\
+			 l|=(((unsigned long)(*((c)++)))<<16),		\
+			 l|=(((unsigned long)(*((c)++)))<<24))
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)    )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24)&0xff))
+#endif
+
+extern void Gost2814789_encrypt(const unsigned char *in, unsigned char *out,
+	const GOST2814789_KEY *key);
+extern void Gost2814789_decrypt(const unsigned char *in, unsigned char *out,
+	const GOST2814789_KEY *key);
+extern void Gost2814789_cryptopro_key_mesh(GOST2814789_KEY *key);
+
+/* GOST 28147-89 key wrapping */
+extern int gost_key_unwrap_crypto_pro(int nid,
+    const unsigned char *keyExchangeKey, const unsigned char *wrappedKey,
+    unsigned char *sessionKey);
+extern int gost_key_wrap_crypto_pro(int nid,
+    const unsigned char *keyExchangeKey, const unsigned char *ukm,
+    const unsigned char *sessionKey, unsigned char *wrappedKey);
+/* Pkey part */
+extern int gost2001_compute_public(GOST_KEY *ec);
+extern ECDSA_SIG *gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey);
+extern int gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec);
+extern int gost2001_keygen(GOST_KEY *ec);
+extern int VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey,
+    GOST_KEY *priv_key, const BIGNUM *ukm);
+extern BIGNUM *GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn);
+extern int GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len);
+
+/* GOST R 34.10 parameters */
+extern int GostR3410_get_md_digest(int nid);
+extern int GostR3410_get_pk_digest(int nid);
+extern int GostR3410_256_param_id(const char *value);
+extern int GostR3410_512_param_id(const char *value);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_GOST_LOCAL_H */
diff --git a/crypto/gost/gostr341001.c b/crypto/gost/gostr341001.c
new file mode 100644
index 0000000..1c34626
--- /dev/null
+++ b/crypto/gost/gostr341001.c
@@ -0,0 +1,403 @@
+/* $OpenBSD: gostr341001.c,v 1.12 2023/07/05 11:37:45 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "ecdsa_local.h"
+#include "gost_local.h"
+
+/* Convert little-endian byte array into bignum */
+BIGNUM *
+GOST_le2bn(const unsigned char *buf, size_t len, BIGNUM *bn)
+{
+	unsigned char temp[64];
+	int i;
+
+	if (len > 64)
+		return NULL;
+
+	for (i = 0; i < len; i++) {
+		temp[len - 1 - i] = buf[i];
+	}
+
+	return BN_bin2bn(temp, len, bn);
+}
+
+int
+GOST_bn2le(BIGNUM *bn, unsigned char *buf, int len)
+{
+	unsigned char temp[64];
+	int i, bytes;
+
+	bytes = BN_num_bytes(bn);
+	if (len > 64 || bytes > len)
+		return 0;
+
+	BN_bn2bin(bn, temp);
+
+	for (i = 0; i < bytes; i++) {
+		buf[bytes - 1 - i] = temp[i];
+	}
+
+	memset(buf + bytes, 0, len - bytes);
+
+	return 1;
+}
+
+int
+gost2001_compute_public(GOST_KEY *ec)
+{
+	const EC_GROUP *group = GOST_KEY_get0_group(ec);
+	EC_POINT *pub_key = NULL;
+	const BIGNUM *priv_key = NULL;
+	BN_CTX *ctx = NULL;
+	int ok = 0;
+
+	if (group == NULL) {
+		GOSTerror(GOST_R_KEY_IS_NOT_INITIALIZED);
+		return 0;
+	}
+	ctx = BN_CTX_new();
+	if (ctx == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	BN_CTX_start(ctx);
+	if ((priv_key = GOST_KEY_get0_private_key(ec)) == NULL)
+		goto err;
+
+	pub_key = EC_POINT_new(group);
+	if (pub_key == NULL)
+		goto err;
+	if (EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx) == 0)
+		goto err;
+	if (GOST_KEY_set_public_key(ec, pub_key) == 0)
+		goto err;
+	ok = 1;
+
+	if (ok == 0) {
+err:
+		GOSTerror(ERR_R_EC_LIB);
+	}
+	EC_POINT_free(pub_key);
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	return ok;
+}
+
+ECDSA_SIG *
+gost2001_do_sign(BIGNUM *md, GOST_KEY *eckey)
+{
+	ECDSA_SIG *newsig = NULL;
+	BIGNUM *order = NULL;
+	const EC_GROUP *group;
+	const BIGNUM *priv_key;
+	BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k =
+	    NULL, *e = NULL;
+	EC_POINT *C = NULL;
+	BN_CTX *ctx = BN_CTX_new();
+	int ok = 0;
+
+	if (ctx == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	BN_CTX_start(ctx);
+	newsig = ECDSA_SIG_new();
+	if (newsig == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	s = newsig->s;
+	r = newsig->r;
+	group = GOST_KEY_get0_group(eckey);
+	if ((order = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (EC_GROUP_get_order(group, order, ctx) == 0)
+		goto err;
+	priv_key = GOST_KEY_get0_private_key(eckey);
+	if ((e = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (BN_mod_ct(e, md, order, ctx) == 0)
+		goto err;
+	if (BN_is_zero(e)) {
+		if (!BN_one(e))
+			goto err;
+	}
+	if ((k = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((C = EC_POINT_new(group)) == NULL)
+		goto err;
+	do {
+		do {
+			if (!BN_rand_range(k, order)) {
+				GOSTerror(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
+				goto err;
+			}
+			/*
+			 * We do not want timing information to leak the length
+			 * of k, so we compute G*k using an equivalent scalar
+			 * of fixed bit-length.
+			 */
+			if (BN_add(k, k, order) == 0)
+				goto err;
+			if (BN_num_bits(k) <= BN_num_bits(order))
+				if (BN_add(k, k, order) == 0)
+					goto err;
+
+			if (EC_POINT_mul(group, C, k, NULL, NULL, ctx) == 0) {
+				GOSTerror(ERR_R_EC_LIB);
+				goto err;
+			}
+			if (EC_POINT_get_affine_coordinates(group, C, X,
+			    NULL, ctx) == 0) {
+				GOSTerror(ERR_R_EC_LIB);
+				goto err;
+			}
+			if (BN_nnmod(r, X, order, ctx) == 0)
+				goto err;
+		} while (BN_is_zero(r));
+		/* s = (r*priv_key+k*e) mod order */
+		if (tmp == NULL) {
+			if ((tmp = BN_CTX_get(ctx)) == NULL)
+				goto err;
+		}
+		if (BN_mod_mul(tmp, priv_key, r, order, ctx) == 0)
+			goto err;
+		if (tmp2 == NULL) {
+			if ((tmp2 = BN_CTX_get(ctx)) == NULL)
+				goto err;
+		}
+		if (BN_mod_mul(tmp2, k, e, order, ctx) == 0)
+			goto err;
+		if (BN_mod_add(s, tmp, tmp2, order, ctx) == 0)
+			goto err;
+	} while (BN_is_zero(s));
+	ok = 1;
+
+err:
+	EC_POINT_free(C);
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	if (ok == 0) {
+		ECDSA_SIG_free(newsig);
+		newsig = NULL;
+	}
+	return newsig;
+}
+
+int
+gost2001_do_verify(BIGNUM *md, ECDSA_SIG *sig, GOST_KEY *ec)
+{
+	BN_CTX *ctx = BN_CTX_new();
+	const EC_GROUP *group = GOST_KEY_get0_group(ec);
+	BIGNUM *order;
+	BIGNUM *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 = NULL;
+	BIGNUM *X = NULL, *tmp = NULL;
+	EC_POINT *C = NULL;
+	const EC_POINT *pub_key = NULL;
+	int ok = 0;
+
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((order = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((e = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((z1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((z2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((tmp = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((R = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((v = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (EC_GROUP_get_order(group, order, ctx) == 0)
+		goto err;
+	pub_key = GOST_KEY_get0_public_key(ec);
+	if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
+	    BN_cmp(sig->s, order) >= 1 || BN_cmp(sig->r, order) >= 1) {
+		GOSTerror(GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
+		goto err;
+	}
+
+	if (BN_mod_ct(e, md, order, ctx) == 0)
+		goto err;
+	if (BN_is_zero(e)) {
+		if (!BN_one(e))
+			goto err;
+	}
+	if ((v = BN_mod_inverse_ct(v, e, order, ctx)) == NULL)
+		goto err;
+	if (BN_mod_mul(z1, sig->s, v, order, ctx) == 0)
+		goto err;
+	if (BN_sub(tmp, order, sig->r) == 0)
+		goto err;
+	if (BN_mod_mul(z2, tmp, v, order, ctx) == 0)
+		goto err;
+	if ((C = EC_POINT_new(group)) == NULL)
+		goto err;
+	if (EC_POINT_mul(group, C, z1, pub_key, z2, ctx) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (EC_POINT_get_affine_coordinates(group, C, X, NULL, ctx) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (BN_mod_ct(R, X, order, ctx) == 0)
+		goto err;
+	if (BN_cmp(R, sig->r) != 0) {
+		GOSTerror(GOST_R_SIGNATURE_MISMATCH);
+	} else {
+		ok = 1;
+	}
+err:
+	EC_POINT_free(C);
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	return ok;
+}
+
+/* Implementation of CryptoPro VKO 34.10-2001 algorithm */
+int
+VKO_compute_key(BIGNUM *X, BIGNUM *Y, const GOST_KEY *pkey, GOST_KEY *priv_key,
+    const BIGNUM *ukm)
+{
+	BIGNUM *p = NULL, *order = NULL;
+	const BIGNUM *key = GOST_KEY_get0_private_key(priv_key);
+	const EC_GROUP *group = GOST_KEY_get0_group(priv_key);
+	const EC_POINT *pub_key = GOST_KEY_get0_public_key(pkey);
+	EC_POINT *pnt;
+	BN_CTX *ctx = NULL;
+	int ok = 0;
+
+	pnt = EC_POINT_new(group);
+	if (pnt == NULL)
+		goto err;
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((p = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((order = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (EC_GROUP_get_order(group, order, ctx) == 0)
+		goto err;
+	if (BN_mod_mul(p, key, ukm, order, ctx) == 0)
+		goto err;
+	if (EC_POINT_mul(group, pnt, NULL, pub_key, p, ctx) == 0)
+		goto err;
+	if (EC_POINT_get_affine_coordinates(group, pnt, X, Y, ctx) == 0)
+		goto err;
+	ok = 1;
+
+err:
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	EC_POINT_free(pnt);
+	return ok;
+}
+
+int
+gost2001_keygen(GOST_KEY *ec)
+{
+	BIGNUM *order = BN_new(), *d = BN_new();
+	const EC_GROUP *group = GOST_KEY_get0_group(ec);
+	int rc = 0;
+
+	if (order == NULL || d == NULL)
+		goto err;
+	if (EC_GROUP_get_order(group, order, NULL) == 0)
+		goto err;
+
+	do {
+		if (BN_rand_range(d, order) == 0) {
+			GOSTerror(GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
+			goto err;
+		}
+	} while (BN_is_zero(d));
+
+	if (GOST_KEY_set_private_key(ec, d) == 0)
+		goto err;
+	rc = gost2001_compute_public(ec);
+
+err:
+	BN_free(d);
+	BN_free(order);
+	return rc;
+}
+#endif
diff --git a/crypto/gost/gostr341001_ameth.c b/crypto/gost/gostr341001_ameth.c
new file mode 100644
index 0000000..9ef7cdf
--- /dev/null
+++ b/crypto/gost/gostr341001_ameth.c
@@ -0,0 +1,721 @@
+/* $OpenBSD: gostr341001_ameth.c,v 1.20 2022/11/26 16:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#include "asn1_local.h"
+#include "evp_local.h"
+#include "gost_local.h"
+#include "gost_asn1.h"
+
+static void
+pkey_free_gost01(EVP_PKEY *key)
+{
+	GOST_KEY_free(key->pkey.gost);
+}
+
+/*
+ * Parses GOST algorithm parameters from X509_ALGOR and
+ * modifies pkey setting NID and parameters
+ */
+static int
+decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
+{
+	int param_nid = NID_undef, digest_nid = NID_undef;
+	GOST_KEY_PARAMS *gkp = NULL;
+	EC_GROUP *group;
+	GOST_KEY *ec;
+
+	gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
+	if (gkp == NULL) {
+		GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
+		return 0;
+	}
+	param_nid = OBJ_obj2nid(gkp->key_params);
+	digest_nid = OBJ_obj2nid(gkp->hash_params);
+	GOST_KEY_PARAMS_free(gkp);
+
+	ec = pkey->pkey.gost;
+	if (ec == NULL) {
+		ec = GOST_KEY_new();
+		if (ec == NULL) {
+			GOSTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
+			return 0;
+	}
+
+	group = EC_GROUP_new_by_curve_name(param_nid);
+	if (group == NULL) {
+		GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+		return 0;
+	}
+	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+	if (GOST_KEY_set_group(ec, group) == 0) {
+		EC_GROUP_free(group);
+		return 0;
+	}
+	EC_GROUP_free(group);
+	if (GOST_KEY_set_digest(ec, digest_nid) == 0)
+		return 0;
+	return 1;
+}
+
+static ASN1_STRING *
+encode_gost01_algor_params(const EVP_PKEY *key)
+{
+	ASN1_STRING *params = ASN1_STRING_new();
+	GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
+	int pkey_param_nid = NID_undef;
+
+	if (params == NULL || gkp == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		ASN1_STRING_free(params);
+		params = NULL;
+		goto err;
+	}
+
+	pkey_param_nid =
+	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
+	gkp->key_params = OBJ_nid2obj(pkey_param_nid);
+	gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
+	/*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
+	params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data);
+	if (params->length <= 0) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		ASN1_STRING_free(params);
+		params = NULL;
+		goto err;
+	}
+	params->type = V_ASN1_SEQUENCE;
+err:
+	GOST_KEY_PARAMS_free(gkp);
+	return params;
+}
+
+static int
+pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	const GOST_KEY *ea = a->pkey.gost;
+	const GOST_KEY *eb = b->pkey.gost;
+	const EC_POINT *ka, *kb;
+	int ret = 0;
+
+	if (ea == NULL || eb == NULL)
+		return 0;
+	ka = GOST_KEY_get0_public_key(ea);
+	kb = GOST_KEY_get0_public_key(eb);
+	if (ka == NULL || kb == NULL)
+		return 0;
+	ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
+	return ret;
+}
+
+static int
+pkey_size_gost01(const EVP_PKEY *pk)
+{
+	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
+		return 128;
+	return 64;
+}
+
+static int
+pkey_bits_gost01(const EVP_PKEY *pk)
+{
+	if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
+		return 512;
+	return 256;
+}
+
+static int
+pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
+{
+	X509_ALGOR *palg = NULL;
+	const unsigned char *pubkey_buf = NULL;
+	const unsigned char *p;
+	ASN1_OBJECT *palgobj = NULL;
+	int pub_len;
+	BIGNUM *X, *Y;
+	ASN1_OCTET_STRING *octet = NULL;
+	int len;
+	int ret;
+	int ptype = V_ASN1_UNDEF;
+	ASN1_STRING *pval = NULL;
+
+	if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
+	    == 0)
+		return 0;
+	(void)EVP_PKEY_assign_GOST(pk, NULL);
+	X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
+	if (ptype != V_ASN1_SEQUENCE) {
+		GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
+		return 0;
+	}
+	p = pval->data;
+	if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
+		GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
+		return 0;
+	}
+
+	octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
+	if (octet == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	len = octet->length / 2;
+
+	X = GOST_le2bn(octet->data, len, NULL);
+	Y = GOST_le2bn(octet->data + len, len, NULL);
+
+	ASN1_OCTET_STRING_free(octet);
+
+	ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y);
+	if (ret == 0)
+		GOSTerror(ERR_R_EC_LIB);
+
+	BN_free(X);
+	BN_free(Y);
+
+	return ret;
+}
+
+static int
+pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
+{
+	ASN1_OBJECT *algobj = NULL;
+	ASN1_OCTET_STRING *octet = NULL;
+	ASN1_STRING *params = NULL;
+	void *pval = NULL;
+	unsigned char *buf = NULL, *sptr;
+	int key_size, ret = 0;
+	const EC_POINT *pub_key;
+	BIGNUM *X = NULL, *Y = NULL;
+	const GOST_KEY *ec = pk->pkey.gost;
+	int ptype = V_ASN1_UNDEF;
+
+	algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
+	if (pk->save_parameters) {
+		params = encode_gost01_algor_params(pk);
+		if (params == NULL)
+			return 0;
+		pval = params;
+		ptype = V_ASN1_SEQUENCE;
+	}
+
+	key_size = GOST_KEY_get_size(ec);
+
+	pub_key = GOST_KEY_get0_public_key(ec);
+	if (pub_key == NULL) {
+		GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED);
+		goto err;
+	}
+
+	octet = ASN1_OCTET_STRING_new();
+	if (octet == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
+	if (ret == 0) {
+		GOSTerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+
+	sptr = ASN1_STRING_data(octet);
+
+	X = BN_new();
+	Y = BN_new();
+	if (X == NULL || Y == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EC_POINT_get_affine_coordinates(GOST_KEY_get0_group(ec),
+	    pub_key, X, Y, NULL) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		goto err;
+	}
+
+	GOST_bn2le(X, sptr, key_size);
+	GOST_bn2le(Y, sptr + key_size, key_size);
+
+	BN_free(Y);
+	BN_free(X);
+
+	ret = i2d_ASN1_OCTET_STRING(octet, &buf);
+	ASN1_BIT_STRING_free(octet);
+	if (ret < 0)
+		return 0;
+
+	return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
+
+err:
+	BN_free(Y);
+	BN_free(X);
+	ASN1_BIT_STRING_free(octet);
+	ASN1_STRING_free(params);
+	return 0;
+}
+
+static int
+param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
+{
+	int param_nid =
+	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
+
+	if (BIO_indent(out, indent, 128) == 0)
+		return 0;
+	BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
+	if (BIO_indent(out, indent, 128) == 0)
+		return 0;
+	BIO_printf(out, "Digest Algorithm: %s\n",
+	    OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost)));
+	return 1;
+}
+
+static int
+pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
+{
+	BN_CTX *ctx = BN_CTX_new();
+	BIGNUM *X, *Y;
+	const EC_POINT *pubkey;
+	const EC_GROUP *group;
+
+	if (ctx == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	BN_CTX_start(ctx);
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost);
+	group = GOST_KEY_get0_group(pkey->pkey.gost);
+	if (EC_POINT_get_affine_coordinates(group, pubkey, X, Y, ctx) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (BIO_indent(out, indent, 128) == 0)
+		goto err;
+	BIO_printf(out, "Public key:\n");
+	if (BIO_indent(out, indent + 3, 128) == 0)
+		goto err;
+	BIO_printf(out, "X:");
+	BN_print(out, X);
+	BIO_printf(out, "\n");
+	if (BIO_indent(out, indent + 3, 128) == 0)
+		goto err;
+	BIO_printf(out, "Y:");
+	BN_print(out, Y);
+	BIO_printf(out, "\n");
+
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+
+	return param_print_gost01(out, pkey, indent, pctx);
+
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	return 0;
+}
+
+static int
+priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
+{
+	const BIGNUM *key;
+
+	if (BIO_indent(out, indent, 128) == 0)
+		return 0;
+	BIO_printf(out, "Private key: ");
+	key = GOST_KEY_get0_private_key(pkey->pkey.gost);
+	if (key == NULL)
+		BIO_printf(out, "data;
+	if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
+		GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
+		return 0;
+	}
+	p = pkey_buf;
+	if (V_ASN1_OCTET_STRING == *p) {
+		/* New format - Little endian octet string */
+		ASN1_OCTET_STRING *s =
+		    d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
+
+		if (s == NULL) {
+			GOSTerror(EVP_R_DECODE_ERROR);
+			ASN1_STRING_free(s);
+			return 0;
+		}
+
+		pk_num = GOST_le2bn(s->data, s->length, NULL);
+		ASN1_STRING_free(s);
+	} else {
+		priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
+		if (priv_key == NULL)
+			return 0;
+		ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
+		ASN1_INTEGER_free(priv_key);
+		if (ret == 0) {
+			GOSTerror(EVP_R_DECODE_ERROR);
+			return 0;
+		}
+	}
+
+	ec = pk->pkey.gost;
+	if (ec == NULL) {
+		ec = GOST_KEY_new();
+		if (ec == NULL) {
+			BN_free(pk_num);
+			return 0;
+		}
+		if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
+			BN_free(pk_num);
+			GOST_KEY_free(ec);
+			return 0;
+		}
+	}
+	if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
+		BN_free(pk_num);
+		return 0;
+	}
+	ret = 0;
+	if (EVP_PKEY_missing_parameters(pk) == 0)
+		ret = gost2001_compute_public(ec) != 0;
+	BN_free(pk_num);
+
+	return ret;
+}
+
+static int
+priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
+{
+	ASN1_OBJECT *algobj =
+	    OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
+	ASN1_STRING *params = encode_gost01_algor_params(pk);
+	unsigned char *priv_buf = NULL;
+	int priv_len;
+	ASN1_INTEGER *asn1key = NULL;
+
+	if (params == NULL)
+		return 0;
+
+	asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
+	    NULL);
+	if (asn1key == NULL) {
+		ASN1_STRING_free(params);
+		return 0;
+	}
+	priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
+	ASN1_INTEGER_free(asn1key);
+	return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
+	    priv_len);
+}
+
+static int
+param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
+{
+	ASN1_STRING *params = encode_gost01_algor_params(pkey);
+	int len;
+
+	if (params == NULL)
+		return 0;
+	len = params->length;
+	if (pder != NULL)
+		memcpy(*pder, params->data, params->length);
+	ASN1_STRING_free(params);
+	return len;
+}
+
+static int
+param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
+{
+	ASN1_OBJECT *obj = NULL;
+	int nid;
+	GOST_KEY *ec;
+	EC_GROUP *group;
+	int ret;
+
+	/* New format */
+	if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
+		return decode_gost01_algor_params(pkey, pder, derlen);
+
+	/* Compatibility */
+	if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	nid = OBJ_obj2nid(obj);
+	ASN1_OBJECT_free(obj);
+
+	ec = GOST_KEY_new();
+	if (ec == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	group = EC_GROUP_new_by_curve_name(nid);
+	if (group == NULL) {
+		GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
+		GOST_KEY_free(ec);
+		return 0;
+	}
+
+	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+	if (GOST_KEY_set_group(ec, group) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		EC_GROUP_free(group);
+		GOST_KEY_free(ec);
+		return 0;
+	}
+	EC_GROUP_free(group);
+	if (GOST_KEY_set_digest(ec,
+	    NID_id_GostR3411_94_CryptoProParamSet) == 0) {
+		GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
+		GOST_KEY_free(ec);
+		return 0;
+	}
+	ret = EVP_PKEY_assign_GOST(pkey, ec);
+	if (ret == 0)
+		GOST_KEY_free(ec);
+	return ret;
+}
+
+static int
+param_missing_gost01(const EVP_PKEY *pk)
+{
+	const GOST_KEY *ec = pk->pkey.gost;
+
+	if (ec == NULL)
+		return 1;
+	if (GOST_KEY_get0_group(ec) == NULL)
+		return 1;
+	if (GOST_KEY_get_digest(ec) == NID_undef)
+		return 1;
+	return 0;
+}
+
+static int
+param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
+{
+	GOST_KEY *eto = to->pkey.gost;
+	const GOST_KEY *efrom = from->pkey.gost;
+	int ret = 1;
+
+	if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
+		GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
+		return 0;
+	}
+	if (efrom == NULL) {
+		GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
+		return 0;
+	}
+	if (eto == NULL) {
+		eto = GOST_KEY_new();
+		if (eto == NULL) {
+			GOSTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
+			GOST_KEY_free(eto);
+			return 0;
+		}
+	}
+	GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
+	GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
+	if (GOST_KEY_get0_private_key(eto) != NULL)
+		ret = gost2001_compute_public(eto);
+
+	return ret;
+}
+
+static int
+param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
+	    EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
+		return 0;
+
+	if (GOST_KEY_get_digest(a->pkey.gost) !=
+	    GOST_KEY_get_digest(b->pkey.gost))
+		return 0;
+
+	return 1;
+}
+
+static int
+pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
+{
+	X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
+	int digest = GOST_KEY_get_digest(pkey->pkey.gost);
+
+	switch (op) {
+	case ASN1_PKEY_CTRL_PKCS7_SIGN:
+		if (arg1 == 0)
+			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
+		break;
+
+	case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
+		if (arg1 == 0)
+			PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
+		break;
+	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
+		*(int *)arg2 = GostR3410_get_md_digest(digest);
+		return 2;
+
+	default:
+		return -2;
+	}
+
+	if (alg1)
+		X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
+	if (alg2)
+		X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
+	if (alg3) {
+		ASN1_STRING *params = encode_gost01_algor_params(pkey);
+		if (params == NULL) {
+			return -1;
+		}
+		X509_ALGOR_set0(alg3,
+		    OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
+		    V_ASN1_SEQUENCE, params);
+	}
+
+	return 1;
+}
+
+const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
+	{
+		.pkey_id = EVP_PKEY_GOSTR01,
+		.pkey_base_id = EVP_PKEY_GOSTR01,
+		.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
+
+		.pem_str = "GOST2001",
+		.info = "GOST R 34.10-2001",
+
+		.pkey_free = pkey_free_gost01,
+		.pkey_ctrl = pkey_ctrl_gost01,
+
+		.priv_decode = priv_decode_gost01,
+		.priv_encode = priv_encode_gost01,
+		.priv_print = priv_print_gost01,
+
+		.param_decode = param_decode_gost01,
+		.param_encode = param_encode_gost01,
+		.param_missing = param_missing_gost01,
+		.param_copy = param_copy_gost01,
+		.param_cmp = param_cmp_gost01,
+		.param_print = param_print_gost01,
+
+		.pub_decode = pub_decode_gost01,
+		.pub_encode = pub_encode_gost01,
+		.pub_cmp = pub_cmp_gost01,
+		.pub_print = pub_print_gost01,
+		.pkey_size = pkey_size_gost01,
+		.pkey_bits = pkey_bits_gost01,
+	},
+	{
+		.pkey_id = EVP_PKEY_GOSTR12_256,
+		.pkey_base_id = EVP_PKEY_GOSTR01,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+	{
+		.pkey_id = EVP_PKEY_GOSTR12_512,
+		.pkey_base_id = EVP_PKEY_GOSTR01,
+		.pkey_flags = ASN1_PKEY_ALIAS
+	},
+};
+
+#endif
diff --git a/crypto/gost/gostr341001_key.c b/crypto/gost/gostr341001_key.c
new file mode 100644
index 0000000..0170ab4
--- /dev/null
+++ b/crypto/gost/gostr341001_key.c
@@ -0,0 +1,334 @@
+/* $OpenBSD: gostr341001_key.c,v 1.14 2023/07/24 17:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+#include 
+#include "gost_local.h"
+
+struct gost_key_st {
+	EC_GROUP *group;
+
+	EC_POINT *pub_key;
+	BIGNUM	 *priv_key;
+
+	int	references;
+
+	int digest_nid;
+};
+
+GOST_KEY *
+GOST_KEY_new(void)
+{
+	GOST_KEY *ret;
+
+	ret = malloc(sizeof(GOST_KEY));
+	if (ret == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return (NULL);
+	}
+	ret->group = NULL;
+	ret->pub_key = NULL;
+	ret->priv_key = NULL;
+	ret->references = 1;
+	ret->digest_nid = NID_undef;
+	return (ret);
+}
+LCRYPTO_ALIAS(GOST_KEY_new);
+
+void
+GOST_KEY_free(GOST_KEY *r)
+{
+	int i;
+
+	if (r == NULL)
+		return;
+
+	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_EC);
+	if (i > 0)
+		return;
+
+	EC_GROUP_free(r->group);
+	EC_POINT_free(r->pub_key);
+	BN_free(r->priv_key);
+
+	freezero(r, sizeof(GOST_KEY));
+}
+LCRYPTO_ALIAS(GOST_KEY_free);
+
+int
+GOST_KEY_check_key(const GOST_KEY *key)
+{
+	int ok = 0;
+	BN_CTX *ctx = NULL;
+	BIGNUM *order = NULL;
+	EC_POINT *point = NULL;
+
+	if (key == NULL || key->group == NULL || key->pub_key == NULL) {
+		GOSTerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	if (EC_POINT_is_at_infinity(key->group, key->pub_key) != 0) {
+		GOSTerror(EC_R_POINT_AT_INFINITY);
+		goto err;
+	}
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+	if ((point = EC_POINT_new(key->group)) == NULL)
+		goto err;
+
+	/* testing whether the pub_key is on the elliptic curve */
+	if (EC_POINT_is_on_curve(key->group, key->pub_key, ctx) <= 0) {
+		GOSTerror(EC_R_POINT_IS_NOT_ON_CURVE);
+		goto err;
+	}
+	/* testing whether pub_key * order is the point at infinity */
+	if ((order = BN_new()) == NULL)
+		goto err;
+	if (EC_GROUP_get_order(key->group, order, ctx) == 0) {
+		GOSTerror(EC_R_INVALID_GROUP_ORDER);
+		goto err;
+	}
+	if (EC_POINT_mul(key->group, point, NULL, key->pub_key, order,
+	    ctx) == 0) {
+		GOSTerror(ERR_R_EC_LIB);
+		goto err;
+	}
+	if (EC_POINT_is_at_infinity(key->group, point) == 0) {
+		GOSTerror(EC_R_WRONG_ORDER);
+		goto err;
+	}
+	/*
+	 * in case the priv_key is present : check if generator * priv_key ==
+	 * pub_key
+	 */
+	if (key->priv_key != NULL) {
+		if (BN_cmp(key->priv_key, order) >= 0) {
+			GOSTerror(EC_R_WRONG_ORDER);
+			goto err;
+		}
+		if (EC_POINT_mul(key->group, point, key->priv_key, NULL, NULL,
+		    ctx) == 0) {
+			GOSTerror(ERR_R_EC_LIB);
+			goto err;
+		}
+		if (EC_POINT_cmp(key->group, point, key->pub_key, ctx) != 0) {
+			GOSTerror(EC_R_INVALID_PRIVATE_KEY);
+			goto err;
+		}
+	}
+	ok = 1;
+err:
+	BN_free(order);
+	BN_CTX_free(ctx);
+	EC_POINT_free(point);
+	return (ok);
+}
+LCRYPTO_ALIAS(GOST_KEY_check_key);
+
+int
+GOST_KEY_set_public_key_affine_coordinates(GOST_KEY *key, BIGNUM *x, BIGNUM *y)
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *tx, *ty;
+	EC_POINT *point = NULL;
+	int ok = 0;
+
+	if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
+		GOSTerror(ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	point = EC_POINT_new(key->group);
+	if (point == NULL)
+		goto err;
+
+	if ((tx = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((ty = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if (EC_POINT_set_affine_coordinates(key->group, point, x, y,
+	    ctx) == 0)
+		goto err;
+	if (EC_POINT_get_affine_coordinates(key->group, point, tx, ty,
+	    ctx) == 0)
+		goto err;
+	/*
+	 * Check if retrieved coordinates match originals: if not, values are
+	 * out of range.
+	 */
+	if (BN_cmp(x, tx) != 0 || BN_cmp(y, ty) != 0) {
+		GOSTerror(EC_R_COORDINATES_OUT_OF_RANGE);
+		goto err;
+	}
+	if (GOST_KEY_set_public_key(key, point) == 0)
+		goto err;
+
+	if (GOST_KEY_check_key(key) == 0)
+		goto err;
+
+	ok = 1;
+
+err:
+	EC_POINT_free(point);
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	return ok;
+
+}
+LCRYPTO_ALIAS(GOST_KEY_set_public_key_affine_coordinates);
+
+const EC_GROUP *
+GOST_KEY_get0_group(const GOST_KEY *key)
+{
+	return key->group;
+}
+LCRYPTO_ALIAS(GOST_KEY_get0_group);
+
+int
+GOST_KEY_set_group(GOST_KEY *key, const EC_GROUP *group)
+{
+	EC_GROUP_free(key->group);
+	key->group = EC_GROUP_dup(group);
+	return (key->group == NULL) ? 0 : 1;
+}
+LCRYPTO_ALIAS(GOST_KEY_set_group);
+
+const BIGNUM *
+GOST_KEY_get0_private_key(const GOST_KEY *key)
+{
+	return key->priv_key;
+}
+LCRYPTO_ALIAS(GOST_KEY_get0_private_key);
+
+int
+GOST_KEY_set_private_key(GOST_KEY *key, const BIGNUM *priv_key)
+{
+	BN_free(key->priv_key);
+	key->priv_key = BN_dup(priv_key);
+	return (key->priv_key == NULL) ? 0 : 1;
+}
+LCRYPTO_ALIAS(GOST_KEY_set_private_key);
+
+const EC_POINT *
+GOST_KEY_get0_public_key(const GOST_KEY *key)
+{
+	return key->pub_key;
+}
+LCRYPTO_ALIAS(GOST_KEY_get0_public_key);
+
+int
+GOST_KEY_set_public_key(GOST_KEY *key, const EC_POINT *pub_key)
+{
+	EC_POINT_free(key->pub_key);
+	key->pub_key = EC_POINT_dup(pub_key, key->group);
+	return (key->pub_key == NULL) ? 0 : 1;
+}
+LCRYPTO_ALIAS(GOST_KEY_set_public_key);
+
+int
+GOST_KEY_get_digest(const GOST_KEY *key)
+{
+	return key->digest_nid;
+}
+LCRYPTO_ALIAS(GOST_KEY_get_digest);
+int
+GOST_KEY_set_digest(GOST_KEY *key, int digest_nid)
+{
+	if (digest_nid == NID_id_GostR3411_94_CryptoProParamSet ||
+	    digest_nid == NID_id_tc26_gost3411_2012_256 ||
+	    digest_nid == NID_id_tc26_gost3411_2012_512) {
+		key->digest_nid = digest_nid;
+		return 1;
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(GOST_KEY_set_digest);
+
+size_t
+GOST_KEY_get_size(const GOST_KEY *r)
+{
+	int i;
+	BIGNUM *order = NULL;
+	const EC_GROUP *group;
+
+	if (r == NULL)
+		return 0;
+	group = GOST_KEY_get0_group(r);
+	if (group == NULL)
+		return 0;
+
+	if ((order = BN_new()) == NULL)
+		return 0;
+
+	if (EC_GROUP_get_order(group, order, NULL) == 0) {
+		BN_free(order);
+		return 0;
+	}
+
+	i = BN_num_bytes(order);
+	BN_free(order);
+	return (i);
+}
+LCRYPTO_ALIAS(GOST_KEY_get_size);
+#endif
diff --git a/crypto/gost/gostr341001_params.c b/crypto/gost/gostr341001_params.c
new file mode 100644
index 0000000..ca8a27d
--- /dev/null
+++ b/crypto/gost/gostr341001_params.c
@@ -0,0 +1,132 @@
+/* $OpenBSD: gostr341001_params.c,v 1.5 2022/11/26 16:08:53 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+
+#include "gost_local.h"
+
+int
+GostR3410_get_md_digest(int nid)
+{
+	if (nid == NID_id_GostR3411_94_CryptoProParamSet)
+		return NID_id_GostR3411_94;
+	return nid;
+}
+
+int
+GostR3410_get_pk_digest(int nid)
+{
+	switch (nid) {
+	case NID_id_GostR3411_94_CryptoProParamSet:
+		return NID_id_GostR3410_2001;
+	case NID_id_tc26_gost3411_2012_256:
+		return NID_id_tc26_gost3410_2012_256;
+	case NID_id_tc26_gost3411_2012_512:
+		return NID_id_tc26_gost3410_2012_512;
+	default:
+		return NID_undef;
+	}
+}
+
+typedef struct GostR3410_params {
+	const char *name;
+	int nid;
+} GostR3410_params;
+
+static const GostR3410_params GostR3410_256_params[] = {
+	{ "A",  NID_id_GostR3410_2001_CryptoPro_A_ParamSet },
+	{ "B",  NID_id_GostR3410_2001_CryptoPro_B_ParamSet },
+	{ "C",  NID_id_GostR3410_2001_CryptoPro_C_ParamSet },
+	{ "0",  NID_id_GostR3410_2001_TestParamSet },
+	{ "XA", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet },
+	{ "XB", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet },
+	{ NULL, NID_undef },
+};
+
+static const GostR3410_params GostR3410_512_params[] = {
+	{ "A",  NID_id_tc26_gost_3410_12_512_paramSetA },
+	{ "B",  NID_id_tc26_gost_3410_12_512_paramSetB },
+	{ NULL, NID_undef },
+};
+
+int
+GostR3410_256_param_id(const char *value)
+{
+	int i;
+
+	for (i = 0; GostR3410_256_params[i].nid != NID_undef; i++) {
+		if (strcasecmp(GostR3410_256_params[i].name, value) == 0)
+			return GostR3410_256_params[i].nid;
+	}
+
+	return NID_undef;
+}
+
+int
+GostR3410_512_param_id(const char *value)
+{
+	int i;
+
+	for (i = 0; GostR3410_512_params[i].nid != NID_undef; i++) {
+		if (strcasecmp(GostR3410_512_params[i].name, value) == 0)
+			return GostR3410_512_params[i].nid;
+	}
+
+	return NID_undef;
+}
+
+#endif
diff --git a/crypto/gost/gostr341001_pmeth.c b/crypto/gost/gostr341001_pmeth.c
new file mode 100644
index 0000000..c5e05be
--- /dev/null
+++ b/crypto/gost/gostr341001_pmeth.c
@@ -0,0 +1,705 @@
+/* $OpenBSD: gostr341001_pmeth.c,v 1.19 2023/07/28 15:50:33 tb Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ecdsa_local.h"
+#include "evp_local.h"
+#include "gost_local.h"
+#include "gost_asn1.h"
+
+static ECDSA_SIG *
+unpack_signature_cp(const unsigned char *sig, size_t siglen)
+{
+	ECDSA_SIG *s;
+
+	s = ECDSA_SIG_new();
+	if (s == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	BN_bin2bn(sig, siglen / 2, s->s);
+	BN_bin2bn(sig + siglen / 2, siglen / 2, s->r);
+	return s;
+}
+
+static int
+pack_signature_cp(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
+{
+	int r_len = BN_num_bytes(s->r);
+	int s_len = BN_num_bytes(s->s);
+
+	if (r_len > order || s_len > order)
+		return 0;
+
+	*siglen = 2 * order;
+
+	memset(sig, 0, *siglen);
+	BN_bn2bin(s->s, sig + order - s_len);
+	BN_bn2bin(s->r, sig + 2 * order - r_len);
+	ECDSA_SIG_free(s);
+	return 1;
+}
+
+static ECDSA_SIG *
+unpack_signature_le(const unsigned char *sig, size_t siglen)
+{
+	ECDSA_SIG *s;
+
+	s = ECDSA_SIG_new();
+	if (s == NULL) {
+		GOSTerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	GOST_le2bn(sig, siglen / 2, s->r);
+	GOST_le2bn(sig + siglen / 2, siglen / 2, s->s);
+	return s;
+}
+
+static int
+pack_signature_le(ECDSA_SIG *s, int order, unsigned char *sig, size_t *siglen)
+{
+	*siglen = 2 * order;
+	memset(sig, 0, *siglen);
+	GOST_bn2le(s->r, sig, order);
+	GOST_bn2le(s->s, sig + order, order);
+	ECDSA_SIG_free(s);
+	return 1;
+}
+
+struct gost_pmeth_data {
+	int sign_param_nid; /* Should be set whenever parameters are filled */
+	int digest_nid;
+	EVP_MD *md;
+	unsigned char *shared_ukm;
+	int peer_key_used;
+	int sig_format;
+};
+
+static int
+pkey_gost01_init(EVP_PKEY_CTX *ctx)
+{
+	struct gost_pmeth_data *data;
+	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+
+	data = calloc(1, sizeof(struct gost_pmeth_data));
+	if (data == NULL)
+		return 0;
+
+	if (pkey != NULL && pkey->pkey.gost != NULL) {
+		data->sign_param_nid =
+		    EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
+		data->digest_nid = GOST_KEY_get_digest(pkey->pkey.gost);
+	}
+	EVP_PKEY_CTX_set_data(ctx, data);
+	return 1;
+}
+
+/* Copies contents of gost_pmeth_data structure */
+static int
+pkey_gost01_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	struct gost_pmeth_data *dst_data, *src_data;
+
+	if (pkey_gost01_init(dst) == 0)
+		return 0;
+
+	src_data = EVP_PKEY_CTX_get_data(src);
+	dst_data = EVP_PKEY_CTX_get_data(dst);
+	*dst_data = *src_data;
+	if (src_data->shared_ukm != NULL)
+		dst_data->shared_ukm = NULL;
+	return 1;
+}
+
+/* Frees up gost_pmeth_data structure */
+static void
+pkey_gost01_cleanup(EVP_PKEY_CTX *ctx)
+{
+	struct gost_pmeth_data *data;
+
+	if ((data = EVP_PKEY_CTX_get_data(ctx)) == NULL)
+		return;
+
+	free(data->shared_ukm);
+	free(data);
+}
+
+static int
+pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+	EC_GROUP *group = NULL;
+	GOST_KEY *gost = NULL;
+	int ret = 0;
+
+	if (data->sign_param_nid == NID_undef ||
+	    data->digest_nid == NID_undef) {
+		GOSTerror(GOST_R_NO_PARAMETERS_SET);
+		return 0;
+	}
+
+	group = EC_GROUP_new_by_curve_name(data->sign_param_nid);
+	if (group == NULL)
+		goto done;
+
+	EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+
+	gost = GOST_KEY_new();
+	if (gost == NULL)
+		goto done;
+
+	if (GOST_KEY_set_digest(gost, data->digest_nid) == 0)
+		goto done;
+
+	if (GOST_KEY_set_group(gost, group) != 0)
+		ret = EVP_PKEY_assign_GOST(pkey, gost);
+
+done:
+	if (ret == 0)
+		GOST_KEY_free(gost);
+	EC_GROUP_free(group);
+	return ret;
+}
+
+static int
+pkey_gost01_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	if (pkey_gost01_paramgen(ctx, pkey) == 0)
+		return 0;
+	return gost2001_keygen(pkey->pkey.gost) != 0;
+}
+
+static int
+pkey_gost01_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    const unsigned char *tbs, size_t tbs_len)
+{
+	ECDSA_SIG *unpacked_sig = NULL;
+	EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
+	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
+	BIGNUM *md;
+	size_t size;
+	int ret;
+
+	if (pkey == NULL || pkey->pkey.gost == NULL)
+		return 0;
+	size = GOST_KEY_get_size(pkey->pkey.gost);
+
+	if (siglen == NULL)
+		return 0;
+	if (sig == NULL) {
+		*siglen = 2 * size;
+		return 1;
+	} else if (*siglen < 2 * size) {
+		GOSTerror(EC_R_BUFFER_TOO_SMALL);
+		return 0;
+	}
+	if (tbs_len != 32 && tbs_len != 64) {
+		GOSTerror(EVP_R_BAD_BLOCK_LENGTH);
+		return 0;
+	}
+	md = GOST_le2bn(tbs, tbs_len, NULL);
+	if (md == NULL)
+		return 0;
+	unpacked_sig = gost2001_do_sign(md, pkey->pkey.gost);
+	BN_free(md);
+	if (unpacked_sig == NULL) {
+		return 0;
+	}
+	switch (pctx->sig_format) {
+	case GOST_SIG_FORMAT_SR_BE:
+		ret = pack_signature_cp(unpacked_sig, size, sig, siglen);
+		break;
+	case GOST_SIG_FORMAT_RS_LE:
+		ret = pack_signature_le(unpacked_sig, size, sig, siglen);
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	if (ret <= 0)
+		ECDSA_SIG_free(unpacked_sig);
+	return ret;
+}
+
+static int
+pkey_gost01_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
+    const unsigned char *tbs, size_t tbs_len)
+{
+	int ok = 0;
+	EVP_PKEY *pub_key = EVP_PKEY_CTX_get0_pkey(ctx);
+	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
+	ECDSA_SIG *s = NULL;
+	BIGNUM *md;
+
+	if (pub_key == NULL)
+		return 0;
+	switch (pctx->sig_format) {
+	case GOST_SIG_FORMAT_SR_BE:
+		s = unpack_signature_cp(sig, siglen);
+		break;
+	case GOST_SIG_FORMAT_RS_LE:
+		s = unpack_signature_le(sig, siglen);
+		break;
+	}
+	if (s == NULL)
+		return 0;
+	md = GOST_le2bn(tbs, tbs_len, NULL);
+	if (md == NULL)
+		goto err;
+	ok = gost2001_do_verify(md, s, pub_key->pkey.gost);
+
+err:
+	BN_free(md);
+	ECDSA_SIG_free(s);
+	return ok;
+}
+
+static int
+gost01_VKO_key(EVP_PKEY *pub_key, EVP_PKEY *priv_key, const unsigned char *ukm,
+    unsigned char *key)
+{
+	unsigned char hashbuf[128];
+	int digest_nid;
+	int ret = 0;
+	BN_CTX *ctx = BN_CTX_new();
+	BIGNUM *UKM, *X, *Y;
+
+	if (ctx == NULL)
+		return 0;
+
+	BN_CTX_start(ctx);
+	if ((UKM = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((X = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((Y = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	GOST_le2bn(ukm, 8, UKM);
+
+	digest_nid = GOST_KEY_get_digest(priv_key->pkey.gost);
+	if (VKO_compute_key(X, Y, pub_key->pkey.gost, priv_key->pkey.gost,
+	    UKM) == 0)
+		goto err;
+
+	switch (digest_nid) {
+	case NID_id_GostR3411_94_CryptoProParamSet:
+		GOST_bn2le(X, hashbuf, 32);
+		GOST_bn2le(Y, hashbuf + 32, 32);
+		GOSTR341194(hashbuf, 64, key, digest_nid);
+		ret = 1;
+		break;
+	case NID_id_tc26_gost3411_2012_256:
+		GOST_bn2le(X, hashbuf, 32);
+		GOST_bn2le(Y, hashbuf + 32, 32);
+		STREEBOG256(hashbuf, 64, key);
+		ret = 1;
+		break;
+	case NID_id_tc26_gost3411_2012_512:
+		GOST_bn2le(X, hashbuf, 64);
+		GOST_bn2le(Y, hashbuf + 64, 64);
+		STREEBOG256(hashbuf, 128, key);
+		ret = 1;
+		break;
+	default:
+		ret = -2;
+		break;
+	}
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	return ret;
+}
+
+int
+pkey_gost01_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t *key_len,
+    const unsigned char *in, size_t in_len)
+{
+	const unsigned char *p = in;
+	EVP_PKEY *priv = EVP_PKEY_CTX_get0_pkey(pctx);
+	GOST_KEY_TRANSPORT *gkt = NULL;
+	int ret = 0;
+	unsigned char wrappedKey[44];
+	unsigned char sharedKey[32];
+	EVP_PKEY *eph_key = NULL, *peerkey = NULL;
+	int nid;
+
+	if (key == NULL) {
+		*key_len = 32;
+		return 1;
+	}
+	gkt = d2i_GOST_KEY_TRANSPORT(NULL, (const unsigned char **)&p, in_len);
+	if (gkt == NULL) {
+		GOSTerror(GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO);
+		return -1;
+	}
+
+	/* If key transport structure contains public key, use it */
+	eph_key = X509_PUBKEY_get(gkt->key_agreement_info->ephem_key);
+	if (eph_key != NULL) {
+		if (EVP_PKEY_derive_set_peer(pctx, eph_key) <= 0) {
+			GOSTerror(GOST_R_INCOMPATIBLE_PEER_KEY);
+			goto err;
+		}
+	} else {
+		/* Set control "public key from client certificate used" */
+		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
+		    NULL) <= 0) {
+			GOSTerror(GOST_R_CTRL_CALL_FAILED);
+			goto err;
+		}
+	}
+	peerkey = EVP_PKEY_CTX_get0_peerkey(pctx);
+	if (peerkey == NULL) {
+		GOSTerror(GOST_R_NO_PEER_KEY);
+		goto err;
+	}
+
+	nid = OBJ_obj2nid(gkt->key_agreement_info->cipher);
+
+	if (gkt->key_agreement_info->eph_iv->length != 8) {
+		GOSTerror(GOST_R_INVALID_IV_LENGTH);
+		goto err;
+	}
+	memcpy(wrappedKey, gkt->key_agreement_info->eph_iv->data, 8);
+	if (gkt->key_info->encrypted_key->length != 32) {
+		GOSTerror(EVP_R_BAD_KEY_LENGTH);
+		goto err;
+	}
+	memcpy(wrappedKey + 8, gkt->key_info->encrypted_key->data, 32);
+	if (gkt->key_info->imit->length != 4) {
+		GOSTerror(ERR_R_INTERNAL_ERROR);
+		goto err;
+	}
+	memcpy(wrappedKey + 40, gkt->key_info->imit->data, 4);
+	if (gost01_VKO_key(peerkey, priv, wrappedKey, sharedKey) <= 0)
+		goto err;
+	if (gost_key_unwrap_crypto_pro(nid, sharedKey, wrappedKey, key) == 0) {
+		GOSTerror(GOST_R_ERROR_COMPUTING_SHARED_KEY);
+		goto err;
+	}
+
+	ret = 1;
+err:
+	EVP_PKEY_free(eph_key);
+	GOST_KEY_TRANSPORT_free(gkt);
+	return ret;
+}
+
+int
+pkey_gost01_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+	/*
+	 * Public key of peer in the ctx field peerkey
+	 * Our private key in the ctx pkey
+	 * ukm is in the algorithm specific context data
+	 */
+	EVP_PKEY *my_key = EVP_PKEY_CTX_get0_pkey(ctx);
+	EVP_PKEY *peer_key = EVP_PKEY_CTX_get0_peerkey(ctx);
+	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+
+	if (data->shared_ukm == NULL) {
+		GOSTerror(GOST_R_UKM_NOT_SET);
+		return 0;
+	}
+
+	if (key == NULL) {
+		*keylen = 32;
+		return 32;
+	}
+
+	if (gost01_VKO_key(peer_key, my_key, data->shared_ukm, key) <= 0)
+		return 0;
+
+	*keylen = 32;
+	return 1;
+}
+
+int
+pkey_gost01_encrypt(EVP_PKEY_CTX *pctx, unsigned char *out, size_t *out_len,
+    const unsigned char *key, size_t key_len)
+{
+	GOST_KEY_TRANSPORT *gkt = NULL;
+	EVP_PKEY *pubk = EVP_PKEY_CTX_get0_pkey(pctx);
+	struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(pctx);
+	unsigned char ukm[8], shared_key[32], crypted_key[44];
+	int ret = 0;
+	int key_is_ephemeral;
+	EVP_PKEY *sec_key = EVP_PKEY_CTX_get0_peerkey(pctx);
+	int nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
+
+	if (data->shared_ukm != NULL) {
+		memcpy(ukm, data->shared_ukm, 8);
+	} else /* if (out != NULL) */ {
+		arc4random_buf(ukm, 8);
+	}
+	/* Check for private key in the peer_key of context */
+	if (sec_key) {
+		key_is_ephemeral = 0;
+		if (GOST_KEY_get0_private_key(sec_key->pkey.gost) == 0) {
+			GOSTerror(GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR);
+			goto err;
+		}
+	} else {
+		key_is_ephemeral = 1;
+		if (out != NULL) {
+			GOST_KEY *tmp_key;
+
+			sec_key = EVP_PKEY_new();
+			if (sec_key == NULL)
+				goto err;
+			tmp_key = GOST_KEY_new();
+			if (tmp_key == NULL)
+				goto err;
+			if (EVP_PKEY_assign(sec_key, EVP_PKEY_base_id(pubk),
+			    tmp_key) == 0) {
+				GOST_KEY_free(tmp_key);
+				goto err;
+			}
+			if (EVP_PKEY_copy_parameters(sec_key, pubk) == 0)
+				goto err;
+			if (gost2001_keygen(sec_key->pkey.gost) == 0) {
+				goto err;
+			}
+		}
+	}
+
+	if (out != NULL) {
+		if (gost01_VKO_key(pubk, sec_key, ukm, shared_key) <= 0)
+			goto err;
+		gost_key_wrap_crypto_pro(nid, shared_key, ukm, key,
+		    crypted_key);
+	}
+	gkt = GOST_KEY_TRANSPORT_new();
+	if (gkt == NULL)
+		goto err;
+	if (ASN1_OCTET_STRING_set(gkt->key_agreement_info->eph_iv, ukm, 8) == 0)
+		goto err;
+	if (ASN1_OCTET_STRING_set(gkt->key_info->imit, crypted_key + 40,
+	    4) == 0)
+		goto err;
+	if (ASN1_OCTET_STRING_set(gkt->key_info->encrypted_key, crypted_key + 8,
+	    32) == 0)
+		goto err;
+	if (key_is_ephemeral) {
+		if (X509_PUBKEY_set(&gkt->key_agreement_info->ephem_key,
+		    out != NULL ? sec_key : pubk) == 0) {
+			GOSTerror(GOST_R_CANNOT_PACK_EPHEMERAL_KEY);
+			goto err;
+		}
+	}
+	ASN1_OBJECT_free(gkt->key_agreement_info->cipher);
+	gkt->key_agreement_info->cipher = OBJ_nid2obj(nid);
+	if (key_is_ephemeral)
+		EVP_PKEY_free(sec_key);
+	else {
+		/* Set control "public key from client certificate used" */
+		if (EVP_PKEY_CTX_ctrl(pctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3,
+		    NULL) <= 0) {
+			GOSTerror(GOST_R_CTRL_CALL_FAILED);
+			goto err;
+		}
+	}
+	if ((*out_len = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL)) > 0)
+		ret = 1;
+	GOST_KEY_TRANSPORT_free(gkt);
+	return ret;
+
+err:
+	if (key_is_ephemeral)
+		EVP_PKEY_free(sec_key);
+	GOST_KEY_TRANSPORT_free(gkt);
+	return -1;
+}
+
+
+static int
+pkey_gost01_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	struct gost_pmeth_data *pctx = EVP_PKEY_CTX_get_data(ctx);
+
+	switch (type) {
+	case EVP_PKEY_CTRL_MD:
+		if (EVP_MD_type(p2) !=
+		    GostR3410_get_md_digest(pctx->digest_nid)) {
+			GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
+			return 0;
+		}
+		pctx->md = p2;
+		return 1;
+	case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
+	case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+	case EVP_PKEY_CTRL_PKCS7_SIGN:
+	case EVP_PKEY_CTRL_DIGESTINIT:
+		return 1;
+
+	case EVP_PKEY_CTRL_GOST_PARAMSET:
+		pctx->sign_param_nid = (int)p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_SET_IV:
+	    {
+		char *ukm = malloc(p1);
+
+		if (ukm == NULL) {
+			GOSTerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		memcpy(ukm, p2, p1);
+		free(pctx->shared_ukm);
+		pctx->shared_ukm = ukm;
+		return 1;
+	    }
+
+	case EVP_PKEY_CTRL_PEER_KEY:
+		if (p1 == 0 || p1 == 1)	/* call from EVP_PKEY_derive_set_peer */
+			return 1;
+		if (p1 == 2)	/* TLS: peer key used? */
+			return pctx->peer_key_used;
+		if (p1 == 3)	/* TLS: peer key used! */
+			return (pctx->peer_key_used = 1);
+		return -2;
+	case EVP_PKEY_CTRL_GOST_SIG_FORMAT:
+		switch (p1) {
+		case GOST_SIG_FORMAT_SR_BE:
+		case GOST_SIG_FORMAT_RS_LE:
+			pctx->sig_format = p1;
+			return 1;
+		default:
+			return 0;
+		}
+		break;
+	case EVP_PKEY_CTRL_GOST_SET_DIGEST:
+		pctx->digest_nid = (int)p1;
+		return 1;
+	case EVP_PKEY_CTRL_GOST_GET_DIGEST:
+		*(int *)p2 = pctx->digest_nid;
+		return 1;
+	default:
+		return -2;
+	}
+}
+
+static int
+pkey_gost01_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+	int param_nid = NID_undef;
+	int digest_nid = NID_undef;
+
+	if (strcmp(type, "paramset") == 0) {
+		if (value == NULL)
+			return 0;
+		if (pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_GET_DIGEST, 0,
+		    &digest_nid) == 0)
+			return 0;
+		if (digest_nid == NID_id_tc26_gost3411_2012_512)
+			param_nid = GostR3410_512_param_id(value);
+		else
+			param_nid = GostR3410_256_param_id(value);
+		if (param_nid == NID_undef)
+			param_nid = OBJ_txt2nid(value);
+		if (param_nid == NID_undef)
+			return 0;
+
+		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
+		    param_nid, NULL);
+	}
+	if (strcmp(type, "dgst") == 0) {
+		if (value == NULL)
+			return 0;
+		else if (strcmp(value, "gost94") == 0 ||
+		    strcmp(value, "md_gost94") == 0)
+			digest_nid = NID_id_GostR3411_94_CryptoProParamSet;
+		else if (strcmp(value, "streebog256") == 0)
+			digest_nid = NID_id_tc26_gost3411_2012_256;
+		else if (strcmp(value, "streebog512") == 0)
+			digest_nid = NID_id_tc26_gost3411_2012_512;
+
+		if (digest_nid == NID_undef)
+			return 0;
+
+		return pkey_gost01_ctrl(ctx, EVP_PKEY_CTRL_GOST_SET_DIGEST,
+		    digest_nid, NULL);
+	}
+	return -2;
+}
+
+const EVP_PKEY_METHOD gostr01_pkey_meth = {
+	.pkey_id = EVP_PKEY_GOSTR01,
+
+	.init = pkey_gost01_init,
+	.copy = pkey_gost01_copy,
+	.cleanup = pkey_gost01_cleanup,
+
+	.paramgen = pkey_gost01_paramgen,
+	.keygen = pkey_gost01_keygen,
+	.sign = pkey_gost01_sign,
+	.verify = pkey_gost01_verify,
+
+	.encrypt = pkey_gost01_encrypt,
+	.decrypt = pkey_gost01_decrypt,
+	.derive = pkey_gost01_derive,
+
+	.ctrl = pkey_gost01_ctrl,
+	.ctrl_str = pkey_gost01_ctrl_str,
+};
+#endif
diff --git a/crypto/gost/gostr341194.c b/crypto/gost/gostr341194.c
new file mode 100644
index 0000000..311c304
--- /dev/null
+++ b/crypto/gost/gostr341194.c
@@ -0,0 +1,278 @@
+/* $OpenBSD: gostr341194.c,v 1.7 2023/07/08 14:30:44 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+
+#include "gost_local.h"
+
+/* Following functions are various bit meshing routines used in
+ * GOST R 34.11-94 algorithms */
+static void
+swap_bytes(unsigned char *w, unsigned char *k)
+{
+	int i, j;
+
+	for (i = 0; i < 4; i++)
+		for (j = 0; j < 8; j++)
+			k[i + 4 * j] = w[8 * i + j];
+}
+
+/* was A_A */
+static void
+circle_xor8(const unsigned char *w, unsigned char *k)
+{
+	unsigned char buf[8];
+	int i;
+
+	memcpy(buf, w, 8);
+	memmove(k, w + 8, 24);
+	for (i = 0; i < 8; i++)
+		k[i + 24] = buf[i] ^ k[i];
+}
+
+/* was R_R */
+static void
+transform_3(unsigned char *data)
+{
+	unsigned short int acc;
+
+	acc = (data[0] ^ data[2] ^ data[4] ^ data[6] ^ data[24] ^ data[30]) |
+	     ((data[1] ^ data[3] ^ data[5] ^ data[7] ^ data[25] ^ data[31]) << 8);
+	memmove(data, data + 2, 30);
+	data[30] = acc & 0xff;
+	data[31] = acc >> 8;
+}
+
+/* Adds blocks of N bytes modulo 2**(8*n). Returns carry*/
+static int
+add_blocks(int n, unsigned char *left, const unsigned char *right)
+{
+	int i;
+	int carry = 0;
+	int sum;
+
+	for (i = 0; i < n; i++) {
+		sum = (int)left[i] + (int)right[i] + carry;
+		left[i] = sum & 0xff;
+		carry = sum >> 8;
+	}
+	return carry;
+}
+
+/* Xor two sequences of bytes */
+static void
+xor_blocks(unsigned char *result, const unsigned char *a,
+    const unsigned char *b, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++)
+		result[i] = a[i] ^ b[i];
+}
+
+/* 
+ * 	Calculate H(i+1) = Hash(Hi,Mi) 
+ * 	Where H and M are 32 bytes long
+ */
+static int
+hash_step(GOSTR341194_CTX *c, unsigned char *H, const unsigned char *M)
+{
+	unsigned char U[32], W[32], V[32], S[32], Key[32];
+	int i;
+
+	/* Compute first key */
+	xor_blocks(W, H, M, 32);
+	swap_bytes(W, Key);
+	/* Encrypt first 8 bytes of H with first key */
+	Gost2814789_set_key(&c->cipher, Key, 256);
+	Gost2814789_encrypt(H, S, &c->cipher);
+
+	/* Compute second key */
+	circle_xor8(H, U);
+	circle_xor8(M, V);
+	circle_xor8(V, V);
+	xor_blocks(W, U, V, 32);
+	swap_bytes(W, Key);
+	/* encrypt second 8 bytes of H with second key */
+	Gost2814789_set_key(&c->cipher, Key, 256);
+	Gost2814789_encrypt(H+8, S+8, &c->cipher);
+
+	/* compute third key */
+	circle_xor8(U, U);
+	U[31] = ~U[31];
+	U[29] = ~U[29];
+	U[28] = ~U[28];
+	U[24] = ~U[24];
+	U[23] = ~U[23];
+	U[20] = ~U[20];
+	U[18] = ~U[18];
+	U[17] = ~U[17];
+	U[14] = ~U[14];
+	U[12] = ~U[12];
+	U[10] = ~U[10];
+	U[8] = ~U[8];
+	U[7] = ~U[7];
+	U[5] = ~U[5];
+	U[3] = ~U[3];
+	U[1] = ~U[1];
+	circle_xor8(V, V);
+	circle_xor8(V, V);
+	xor_blocks(W, U, V, 32);
+	swap_bytes(W, Key);
+	/* encrypt third 8 bytes of H with third key */
+	Gost2814789_set_key(&c->cipher, Key, 256);
+	Gost2814789_encrypt(H+16, S+16, &c->cipher);
+
+	/* Compute fourth key */
+	circle_xor8(U, U);
+	circle_xor8(V, V);
+	circle_xor8(V, V);
+	xor_blocks(W, U, V, 32);
+	swap_bytes(W, Key);
+	/* Encrypt last 8 bytes with fourth key */
+	Gost2814789_set_key(&c->cipher, Key, 256);
+	Gost2814789_encrypt(H+24, S+24, &c->cipher);
+
+	for (i = 0; i < 12; i++)
+		transform_3(S);
+	xor_blocks(S, S, M, 32);
+	transform_3(S);
+	xor_blocks(S, S, H, 32);
+	for (i = 0; i < 61; i++)
+		transform_3(S);
+	memcpy(H, S, 32);
+	return 1;
+}
+
+int
+GOSTR341194_Init(GOSTR341194_CTX *c, int nid)
+{
+	memset(c, 0, sizeof(*c));
+	return Gost2814789_set_sbox(&c->cipher, nid);
+}
+LCRYPTO_ALIAS(GOSTR341194_Init);
+
+static void
+GOSTR341194_block_data_order(GOSTR341194_CTX *ctx, const unsigned char *p,
+    size_t num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		hash_step(ctx, ctx->H, p);
+		add_blocks(32, ctx->S, p);
+		p += 32;
+	}
+}
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_CBLOCK	GOSTR341194_CBLOCK
+#define HASH_LONG	GOSTR341194_LONG
+#define HASH_CTX	GOSTR341194_CTX
+#define HASH_UPDATE	GOSTR341194_Update
+#define HASH_TRANSFORM	GOSTR341194_Transform
+#define HASH_NO_FINAL	1
+#define HASH_BLOCK_DATA_ORDER	GOSTR341194_block_data_order
+
+#include "md32_common.h"
+LCRYPTO_ALIAS(GOSTR341194_Update);
+LCRYPTO_ALIAS(GOSTR341194_Transform);
+
+int
+GOSTR341194_Final(unsigned char *md, GOSTR341194_CTX * c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	unsigned char T[32];
+
+	if (c->num > 0) {
+		memset(p + c->num, 0, 32 - c->num);
+		hash_step(c, c->H, p);
+		add_blocks(32, c->S, p);
+	}
+
+	p = T;
+	HOST_l2c(c->Nl, p);
+	HOST_l2c(c->Nh, p);
+	memset(p, 0, 32 - 8);
+	hash_step(c, c->H, T);
+	hash_step(c, c->H, c->S);
+
+	memcpy(md, c->H, 32);
+
+	return 1;
+}
+LCRYPTO_ALIAS(GOSTR341194_Final);
+
+unsigned char *
+GOSTR341194(const unsigned char *d, size_t n, unsigned char *md, int nid)
+{
+	GOSTR341194_CTX c;
+	static unsigned char m[GOSTR341194_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	if (!GOSTR341194_Init(&c, nid))
+		return 0;
+	GOSTR341194_Update(&c, d, n);
+	GOSTR341194_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(GOSTR341194);
+#endif
diff --git a/crypto/gost/streebog.c b/crypto/gost/streebog.c
new file mode 100644
index 0000000..60c5757
--- /dev/null
+++ b/crypto/gost/streebog.c
@@ -0,0 +1,1487 @@
+/* $OpenBSD: streebog.c,v 1.9 2023/07/08 14:30:44 beck Exp $ */
+/*
+ * Copyright (c) 2014 Dmitry Eremin-Solenikov 
+ * Copyright (c) 2005-2006 Cryptocom LTD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_GOST
+#include 
+#include 
+#include 
+
+#include "gost_local.h"
+
+static const STREEBOG_LONG64 A_PI_table[8][256] = {
+	{ /* 0 */
+		U64(0xd01f715b5c7ef8e6), U64(0x16fa240980778325),
+		U64(0xa8a42e857ee049c8), U64(0x6ac1068fa186465b),
+		U64(0x6e417bd7a2e9320b), U64(0x665c8167a437daab),
+		U64(0x7666681aa89617f6), U64(0x4b959163700bdcf5),
+		U64(0xf14be6b78df36248), U64(0xc585bd689a625cff),
+		U64(0x9557d7fca67d82cb), U64(0x89f0b969af6dd366),
+		U64(0xb0833d48749f6c35), U64(0xa1998c23b1ecbc7c),
+		U64(0x8d70c431ac02a736), U64(0xd6dfbc2fd0a8b69e),
+		U64(0x37aeb3e551fa198b), U64(0x0b7d128a40b5cf9c),
+		U64(0x5a8f2008b5780cbc), U64(0xedec882284e333e5),
+		U64(0xd25fc177d3c7c2ce), U64(0x5e0f5d50b61778ec),
+		U64(0x1d873683c0c24cb9), U64(0xad040bcbb45d208c),
+		U64(0x2f89a0285b853c76), U64(0x5732fff6791b8d58),
+		U64(0x3e9311439ef6ec3f), U64(0xc9183a809fd3c00f),
+		U64(0x83adf3f5260a01ee), U64(0xa6791941f4e8ef10),
+		U64(0x103ae97d0ca1cd5d), U64(0x2ce948121dee1b4a),
+		U64(0x39738421dbf2bf53), U64(0x093da2a6cf0cf5b4),
+		U64(0xcd9847d89cbcb45f), U64(0xf9561c078b2d8ae8),
+		U64(0x9c6a755a6971777f), U64(0xbc1ebaa0712ef0c5),
+		U64(0x72e61542abf963a6), U64(0x78bb5fde229eb12e),
+		U64(0x14ba94250fceb90d), U64(0x844d6697630e5282),
+		U64(0x98ea08026a1e032f), U64(0xf06bbea144217f5c),
+		U64(0xdb6263d11ccb377a), U64(0x641c314b2b8ee083),
+		U64(0x320e96ab9b4770cf), U64(0x1ee7deb986a96b85),
+		U64(0xe96cf57a878c47b5), U64(0xfdd6615f8842feb8),
+		U64(0xc83862965601dd1b), U64(0x2ea9f83e92572162),
+		U64(0xf876441142ff97fc), U64(0xeb2c455608357d9d),
+		U64(0x5612a7e0b0c9904c), U64(0x6c01cbfb2d500823),
+		U64(0x4548a6a7fa037a2d), U64(0xabc4c6bf388b6ef4),
+		U64(0xbade77d4fdf8bebd), U64(0x799b07c8eb4cac3a),
+		U64(0x0c9d87e805b19cf0), U64(0xcb588aac106afa27),
+		U64(0xea0c1d40c1e76089), U64(0x2869354a1e816f1a),
+		U64(0xff96d17307fbc490), U64(0x9f0a9d602f1a5043),
+		U64(0x96373fc6e016a5f7), U64(0x5292dab8b3a6e41c),
+		U64(0x9b8ae0382c752413), U64(0x4f15ec3b7364a8a5),
+		U64(0x3fb349555724f12b), U64(0xc7c50d4415db66d7),
+		U64(0x92b7429ee379d1a7), U64(0xd37f99611a15dfda),
+		U64(0x231427c05e34a086), U64(0xa439a96d7b51d538),
+		U64(0xb403401077f01865), U64(0xdda2aea5901d7902),
+		U64(0x0a5d4a9c8967d288), U64(0xc265280adf660f93),
+		U64(0x8bb0094520d4e94e), U64(0x2a29856691385532),
+		U64(0x42a833c5bf072941), U64(0x73c64d54622b7eb2),
+		U64(0x07e095624504536c), U64(0x8a905153e906f45a),
+		U64(0x6f6123c16b3b2f1f), U64(0xc6e55552dc097bc3),
+		U64(0x4468feb133d16739), U64(0xe211e7f0c7398829),
+		U64(0xa2f96419f7879b40), U64(0x19074bdbc3ad38e9),
+		U64(0xf4ebc3f9474e0b0c), U64(0x43886bd376d53455),
+		U64(0xd8028beb5aa01046), U64(0x51f23282f5cdc320),
+		U64(0xe7b1c2be0d84e16d), U64(0x081dfab006dee8a0),
+		U64(0x3b33340d544b857b), U64(0x7f5bcabc679ae242),
+		U64(0x0edd37c48a08a6d8), U64(0x81ed43d9a9b33bc6),
+		U64(0xb1a3655ebd4d7121), U64(0x69a1eeb5e7ed6167),
+		U64(0xf6ab73d5c8f73124), U64(0x1a67a3e185c61fd5),
+		U64(0x2dc91004d43c065e), U64(0x0240b02c8fb93a28),
+		U64(0x90f7f2b26cc0eb8f), U64(0x3cd3a16f114fd617),
+		U64(0xaae49ea9f15973e0), U64(0x06c0cd748cd64e78),
+		U64(0xda423bc7d5192a6e), U64(0xc345701c16b41287),
+		U64(0x6d2193ede4821537), U64(0xfcf639494190e3ac),
+		U64(0x7c3b228621f1c57e), U64(0xfb16ac2b0494b0c0),
+		U64(0xbf7e529a3745d7f9), U64(0x6881b6a32e3f7c73),
+		U64(0xca78d2bad9b8e733), U64(0xbbfe2fc2342aa3a9),
+		U64(0x0dbddffecc6381e4), U64(0x70a6a56e2440598e),
+		U64(0xe4d12a844befc651), U64(0x8c509c2765d0ba22),
+		U64(0xee8c6018c28814d9), U64(0x17da7c1f49a59e31),
+		U64(0x609c4c1328e194d3), U64(0xb3e3d57232f44b09),
+		U64(0x91d7aaa4a512f69b), U64(0x0ffd6fd243dabbcc),
+		U64(0x50d26a943c1fde34), U64(0x6be15e9968545b4f),
+		U64(0x94778fea6faf9fdf), U64(0x2b09dd7058ea4826),
+		U64(0x677cd9716de5c7bf), U64(0x49d5214fffb2e6dd),
+		U64(0x0360e83a466b273c), U64(0x1fc786af4f7b7691),
+		U64(0xa0b9d435783ea168), U64(0xd49f0c035f118cb6),
+		U64(0x01205816c9d21d14), U64(0xac2453dd7d8f3d98),
+		U64(0x545217cc3f70aa64), U64(0x26b4028e9489c9c2),
+		U64(0xdec2469fd6765e3e), U64(0x04807d58036f7450),
+		U64(0xe5f17292823ddb45), U64(0xf30b569b024a5860),
+		U64(0x62dcfc3fa758aefb), U64(0xe84cad6c4e5e5aa1),
+		U64(0xccb81fce556ea94b), U64(0x53b282ae7a74f908),
+		U64(0x1b47fbf74c1402c1), U64(0x368eebf39828049f),
+		U64(0x7afbeff2ad278b06), U64(0xbe5e0a8cfe97caed),
+		U64(0xcfd8f7f413058e77), U64(0xf78b2bc301252c30),
+		U64(0x4d555c17fcdd928d), U64(0x5f2f05467fc565f8),
+		U64(0x24f4b2a21b30f3ea), U64(0x860dd6bbecb768aa),
+		U64(0x4c750401350f8f99), U64(0x0000000000000000),
+		U64(0xecccd0344d312ef1), U64(0xb5231806be220571),
+		U64(0xc105c030990d28af), U64(0x653c695de25cfd97),
+		U64(0x159acc33c61ca419), U64(0xb89ec7f872418495),
+		U64(0xa9847693b73254dc), U64(0x58cf90243ac13694),
+		U64(0x59efc832f3132b80), U64(0x5c4fed7c39ae42c4),
+		U64(0x828dabe3efd81cfa), U64(0xd13f294d95ace5f2),
+		U64(0x7d1b7a90e823d86a), U64(0xb643f03cf849224d),
+		U64(0x3df3f979d89dcb03), U64(0x7426d836272f2dde),
+		U64(0xdfe21e891fa4432a), U64(0x3a136c1b9d99986f),
+		U64(0xfa36f43dcd46add4), U64(0xc025982650df35bb),
+		U64(0x856d3e81aadc4f96), U64(0xc4a5e57e53b041eb),
+		U64(0x4708168b75ba4005), U64(0xaf44bbe73be41aa4),
+		U64(0x971767d029c4b8e3), U64(0xb9be9feebb939981),
+		U64(0x215497ecd18d9aae), U64(0x316e7e91dd2c57f3),
+		U64(0xcef8afe2dad79363), U64(0x3853dc371220a247),
+		U64(0x35ee03c9de4323a3), U64(0xe6919aa8c456fc79),
+		U64(0xe05157dc4880b201), U64(0x7bdbb7e464f59612),
+		U64(0x127a59518318f775), U64(0x332ecebd52956ddb),
+		U64(0x8f30741d23bb9d1e), U64(0xd922d3fd93720d52),
+		U64(0x7746300c61440ae2), U64(0x25d4eab4d2e2eefe),
+		U64(0x75068020eefd30ca), U64(0x135a01474acaea61),
+		U64(0x304e268714fe4ae7), U64(0xa519f17bb283c82c),
+		U64(0xdc82f6b359cf6416), U64(0x5baf781e7caa11a8),
+		U64(0xb2c38d64fb26561d), U64(0x34ce5bdf17913eb7),
+		U64(0x5d6fb56af07c5fd0), U64(0x182713cd0a7f25fd),
+		U64(0x9e2ac576e6c84d57), U64(0x9aaab82ee5a73907),
+		U64(0xa3d93c0f3e558654), U64(0x7e7b92aaae48ff56),
+		U64(0x872d8ead256575be), U64(0x41c8dbfff96c0e7d),
+		U64(0x99ca5014a3cc1e3b), U64(0x40e883e930be1369),
+		U64(0x1ca76e95091051ad), U64(0x4e35b42dbab6b5b1),
+		U64(0x05a0254ecabd6944), U64(0xe1710fca8152af15),
+		U64(0xf22b0e8dcb984574), U64(0xb763a82a319b3f59),
+		U64(0x63fca4296e8ab3ef), U64(0x9d4a2d4ca0a36a6b),
+		U64(0xe331bfe60eeb953d), U64(0xd5bf541596c391a2),
+		U64(0xf5cb9bef8e9c1618), U64(0x46284e9dbc685d11),
+		U64(0x2074cffa185f87ba), U64(0xbd3ee2b6b8fcedd1),
+		U64(0xae64e3f1f23607b0), U64(0xfeb68965ce29d984),
+		U64(0x55724fdaf6a2b770), U64(0x29496d5cd753720e),
+		U64(0xa75941573d3af204), U64(0x8e102c0bea69800a),
+		U64(0x111ab16bc573d049), U64(0xd7ffe439197aab8a),
+		U64(0xefac380e0b5a09cd), U64(0x48f579593660fbc9),
+		U64(0x22347fd697e6bd92), U64(0x61bc1405e13389c7),
+		U64(0x4ab5c975b9d9c1e1), U64(0x80cd1bcf606126d2),
+		U64(0x7186fd78ed92449a), U64(0x93971a882aabccb3),
+		U64(0x88d0e17f66bfce72), U64(0x27945a985d5bd4d6)
+	}, { /* 1 */
+		U64(0xde553f8c05a811c8), U64(0x1906b59631b4f565),
+		U64(0x436e70d6b1964ff7), U64(0x36d343cb8b1e9d85),
+		U64(0x843dfacc858aab5a), U64(0xfdfc95c299bfc7f9),
+		U64(0x0f634bdea1d51fa2), U64(0x6d458b3b76efb3cd),
+		U64(0x85c3f77cf8593f80), U64(0x3c91315fbe737cb2),
+		U64(0x2148b03366ace398), U64(0x18f8b8264c6761bf),
+		U64(0xc830c1c495c9fb0f), U64(0x981a76102086a0aa),
+		U64(0xaa16012142f35760), U64(0x35cc54060c763cf6),
+		U64(0x42907d66cc45db2d), U64(0x8203d44b965af4bc),
+		U64(0x3d6f3cefc3a0e868), U64(0xbc73ff69d292bda7),
+		U64(0x8722ed0102e20a29), U64(0x8f8185e8cd34deb7),
+		U64(0x9b0561dda7ee01d9), U64(0x5335a0193227fad6),
+		U64(0xc9cecc74e81a6fd5), U64(0x54f5832e5c2431ea),
+		U64(0x99e47ba05d553470), U64(0xf7bee756acd226ce),
+		U64(0x384e05a5571816fd), U64(0xd1367452a47d0e6a),
+		U64(0xf29fde1c386ad85b), U64(0x320c77316275f7ca),
+		U64(0xd0c879e2d9ae9ab0), U64(0xdb7406c69110ef5d),
+		U64(0x45505e51a2461011), U64(0xfc029872e46c5323),
+		U64(0xfa3cb6f5f7bc0cc5), U64(0x031f17cd8768a173),
+		U64(0xbd8df2d9af41297d), U64(0x9d3b4f5ab43e5e3f),
+		U64(0x4071671b36feee84), U64(0x716207e7d3e3b83d),
+		U64(0x48d20ff2f9283a1a), U64(0x27769eb4757cbc7e),
+		U64(0x5c56ebc793f2e574), U64(0xa48b474f9ef5dc18),
+		U64(0x52cbada94ff46e0c), U64(0x60c7da982d8199c6),
+		U64(0x0e9d466edc068b78), U64(0x4eec2175eaf865fc),
+		U64(0x550b8e9e21f7a530), U64(0x6b7ba5bc653fec2b),
+		U64(0x5eb7f1ba6949d0dd), U64(0x57ea94e3db4c9099),
+		U64(0xf640eae6d101b214), U64(0xdd4a284182c0b0bb),
+		U64(0xff1d8fbf6304f250), U64(0xb8accb933bf9d7e8),
+		U64(0xe8867c478eb68c4d), U64(0x3f8e2692391bddc1),
+		U64(0xcb2fd60912a15a7c), U64(0xaec935dbab983d2f),
+		U64(0xf55ffd2b56691367), U64(0x80e2ce366ce1c115),
+		U64(0x179bf3f8edb27e1d), U64(0x01fe0db07dd394da),
+		U64(0xda8a0b76ecc37b87), U64(0x44ae53e1df9584cb),
+		U64(0xb310b4b77347a205), U64(0xdfab323c787b8512),
+		U64(0x3b511268d070b78e), U64(0x65e6e3d2b9396753),
+		U64(0x6864b271e2574d58), U64(0x259784c98fc789d7),
+		U64(0x02e11a7dfabb35a9), U64(0x8841a6dfa337158b),
+		U64(0x7ade78c39b5dcdd0), U64(0xb7cf804d9a2cc84a),
+		U64(0x20b6bd831b7f7742), U64(0x75bd331d3a88d272),
+		U64(0x418f6aab4b2d7a5e), U64(0xd9951cbb6babdaf4),
+		U64(0xb6318dfde7ff5c90), U64(0x1f389b112264aa83),
+		U64(0x492c024284fbaec0), U64(0xe33a0363c608f9a0),
+		U64(0x2688930408af28a4), U64(0xc7538a1a341ce4ad),
+		U64(0x5da8e677ee2171ae), U64(0x8c9e92254a5c7fc4),
+		U64(0x63d8cd55aae938b5), U64(0x29ebd8daa97a3706),
+		U64(0x959827b37be88aa1), U64(0x1484e4356adadf6e),
+		U64(0xa7945082199d7d6b), U64(0xbf6ce8a455fa1cd4),
+		U64(0x9cc542eac9edcae5), U64(0x79c16f0e1c356ca3),
+		U64(0x89bfab6fdee48151), U64(0xd4174d1830c5f0ff),
+		U64(0x9258048415eb419d), U64(0x6139d72850520d1c),
+		U64(0x6a85a80c18ec78f1), U64(0xcd11f88e0171059a),
+		U64(0xcceff53e7ca29140), U64(0xd229639f2315af19),
+		U64(0x90b91ef9ef507434), U64(0x5977d28d074a1be1),
+		U64(0x311360fce51d56b9), U64(0xc093a92d5a1f2f91),
+		U64(0x1a19a25bb6dc5416), U64(0xeb996b8a09de2d3e),
+		U64(0xfee3820f1ed7668a), U64(0xd7085ad5b7ad518c),
+		U64(0x7fff41890fe53345), U64(0xec5948bd67dde602),
+		U64(0x2fd5f65dbaaa68e0), U64(0xa5754affe32648c2),
+		U64(0xf8ddac880d07396c), U64(0x6fa491468c548664),
+		U64(0x0c7c5c1326bdbed1), U64(0x4a33158f03930fb3),
+		U64(0x699abfc19f84d982), U64(0xe4fa2054a80b329c),
+		U64(0x6707f9af438252fa), U64(0x08a368e9cfd6d49e),
+		U64(0x47b1442c58fd25b8), U64(0xbbb3dc5ebc91769b),
+		U64(0x1665fe489061eac7), U64(0x33f27a811fa66310),
+		U64(0x93a609346838d547), U64(0x30ed6d4c98cec263),
+		U64(0x1dd9816cd8df9f2a), U64(0x94662a03063b1e7b),
+		U64(0x83fdd9fbeb896066), U64(0x7b207573e68e590a),
+		U64(0x5f49fc0a149a4407), U64(0x343259b671a5a82c),
+		U64(0xfbc2bb458a6f981f), U64(0xc272b350a0a41a38),
+		U64(0x3aaf1fd8ada32354), U64(0x6cbb868b0b3c2717),
+		U64(0xa2b569c88d2583fe), U64(0xf180c9d1bf027928),
+		U64(0xaf37386bd64ba9f5), U64(0x12bacab2790a8088),
+		U64(0x4c0d3b0810435055), U64(0xb2eeb9070e9436df),
+		U64(0xc5b29067cea7d104), U64(0xdcb425f1ff132461),
+		U64(0x4f122cc5972bf126), U64(0xac282fa651230886),
+		U64(0xe7e537992f6393ef), U64(0xe61b3a2952b00735),
+		U64(0x709c0a57ae302ce7), U64(0xe02514ae416058d3),
+		U64(0xc44c9dd7b37445de), U64(0x5a68c5408022ba92),
+		U64(0x1c278cdca50c0bf0), U64(0x6e5a9cf6f18712be),
+		U64(0x86dce0b17f319ef3), U64(0x2d34ec2040115d49),
+		U64(0x4bcd183f7e409b69), U64(0x2815d56ad4a9a3dc),
+		U64(0x24698979f2141d0d), U64(0x0000000000000000),
+		U64(0x1ec696a15fb73e59), U64(0xd86b110b16784e2e),
+		U64(0x8e7f8858b0e74a6d), U64(0x063e2e8713d05fe6),
+		U64(0xe2c40ed3bbdb6d7a), U64(0xb1f1aeca89fc97ac),
+		U64(0xe1db191e3cb3cc09), U64(0x6418ee62c4eaf389),
+		U64(0xc6ad87aa49cf7077), U64(0xd6f65765ca7ec556),
+		U64(0x9afb6c6dda3d9503), U64(0x7ce05644888d9236),
+		U64(0x8d609f95378feb1e), U64(0x23a9aa4e9c17d631),
+		U64(0x6226c0e5d73aac6f), U64(0x56149953a69f0443),
+		U64(0xeeb852c09d66d3ab), U64(0x2b0ac2a753c102af),
+		U64(0x07c023376e03cb3c), U64(0x2ccae1903dc2c993),
+		U64(0xd3d76e2f5ec63bc3), U64(0x9e2458973356ff4c),
+		U64(0xa66a5d32644ee9b1), U64(0x0a427294356de137),
+		U64(0x783f62be61e6f879), U64(0x1344c70204d91452),
+		U64(0x5b96c8f0fdf12e48), U64(0xa90916ecc59bf613),
+		U64(0xbe92e5142829880e), U64(0x727d102a548b194e),
+		U64(0x1be7afebcb0fc0cc), U64(0x3e702b2244c8491b),
+		U64(0xd5e940a84d166425), U64(0x66f9f41f3e51c620),
+		U64(0xabe80c913f20c3ba), U64(0xf07ec461c2d1edf2),
+		U64(0xf361d3ac45b94c81), U64(0x0521394a94b8fe95),
+		U64(0xadd622162cf09c5c), U64(0xe97871f7f3651897),
+		U64(0xf4a1f09b2bba87bd), U64(0x095d6559b2054044),
+		U64(0x0bbc7f2448be75ed), U64(0x2af4cf172e129675),
+		U64(0x157ae98517094bb4), U64(0x9fda55274e856b96),
+		U64(0x914713499283e0ee), U64(0xb952c623462a4332),
+		U64(0x74433ead475b46a8), U64(0x8b5eb112245fb4f8),
+		U64(0xa34b6478f0f61724), U64(0x11a5dd7ffe6221fb),
+		U64(0xc16da49d27ccbb4b), U64(0x76a224d0bde07301),
+		U64(0x8aa0bca2598c2022), U64(0x4df336b86d90c48f),
+		U64(0xea67663a740db9e4), U64(0xef465f70e0b54771),
+		U64(0x39b008152acb8227), U64(0x7d1e5bf4f55e06ec),
+		U64(0x105bd0cf83b1b521), U64(0x775c2960c033e7db),
+		U64(0x7e014c397236a79f), U64(0x811cc386113255cf),
+		U64(0xeda7450d1a0e72d8), U64(0x5889df3d7a998f3b),
+		U64(0x2e2bfbedc779fc3a), U64(0xce0eef438619a4e9),
+		U64(0x372d4e7bf6cd095f), U64(0x04df34fae96b6a4f),
+		U64(0xf923a13870d4adb6), U64(0xa1aa7e050a4d228d),
+		U64(0xa8f71b5cb84862c9), U64(0xb52e9a306097fde3),
+		U64(0x0d8251a35b6e2a0b), U64(0x2257a7fee1c442eb),
+		U64(0x73831d9a29588d94), U64(0x51d4ba64c89ccf7f),
+		U64(0x502ab7d4b54f5ba5), U64(0x97793dce8153bf08),
+		U64(0xe5042de4d5d8a646), U64(0x9687307efc802bd2),
+		U64(0xa05473b5779eb657), U64(0xb4d097801d446939),
+		U64(0xcff0e2f3fbca3033), U64(0xc38cbee0dd778ee2),
+		U64(0x464f499c252eb162), U64(0xcad1dbb96f72cea6),
+		U64(0xba4dd1eec142e241), U64(0xb00fa37af42f0376)
+	}, { /* 2 */
+		U64(0xcce4cd3aa968b245), U64(0x089d5484e80b7faf),
+		U64(0x638246c1b3548304), U64(0xd2fe0ec8c2355492),
+		U64(0xa7fbdf7ff2374eee), U64(0x4df1600c92337a16),
+		U64(0x84e503ea523b12fb), U64(0x0790bbfd53ab0c4a),
+		U64(0x198a780f38f6ea9d), U64(0x2ab30c8f55ec48cb),
+		U64(0xe0f7fed6b2c49db5), U64(0xb6ecf3f422cadbdc),
+		U64(0x409c9a541358df11), U64(0xd3ce8a56dfde3fe3),
+		U64(0xc3e9224312c8c1a0), U64(0x0d6dfa58816ba507),
+		U64(0xddf3e1b179952777), U64(0x04c02a42748bb1d9),
+		U64(0x94c2abff9f2decb8), U64(0x4f91752da8f8acf4),
+		U64(0x78682befb169bf7b), U64(0xe1c77a48af2ff6c4),
+		U64(0x0c5d7ec69c80ce76), U64(0x4cc1e4928fd81167),
+		U64(0xfeed3d24d9997b62), U64(0x518bb6dfc3a54a23),
+		U64(0x6dbf2d26151f9b90), U64(0xb5bc624b05ea664f),
+		U64(0xe86aaa525acfe21a), U64(0x4801ced0fb53a0be),
+		U64(0xc91463e6c00868ed), U64(0x1027a815cd16fe43),
+		U64(0xf67069a0319204cd), U64(0xb04ccc976c8abce7),
+		U64(0xc0b9b3fc35e87c33), U64(0xf380c77c58f2de65),
+		U64(0x50bb3241de4e2152), U64(0xdf93f490435ef195),
+		U64(0xf1e0d25d62390887), U64(0xaf668bfb1a3c3141),
+		U64(0xbc11b251f00a7291), U64(0x73a5eed47e427d47),
+		U64(0x25bee3f6ee4c3b2e), U64(0x43cc0beb34786282),
+		U64(0xc824e778dde3039c), U64(0xf97d86d98a327728),
+		U64(0xf2b043e24519b514), U64(0xe297ebf7880f4b57),
+		U64(0x3a94a49a98fab688), U64(0x868516cb68f0c419),
+		U64(0xeffa11af0964ee50), U64(0xa4ab4ec0d517f37d),
+		U64(0xa9c6b498547c567a), U64(0x8e18424f80fbbbb6),
+		U64(0x0bcdc53bcf2bc23c), U64(0x137739aaea3643d0),
+		U64(0x2c1333ec1bac2ff0), U64(0x8d48d3f0a7db0625),
+		U64(0x1e1ac3f26b5de6d7), U64(0xf520f81f16b2b95e),
+		U64(0x9f0f6ec450062e84), U64(0x0130849e1deb6b71),
+		U64(0xd45e31ab8c7533a9), U64(0x652279a2fd14e43f),
+		U64(0x3209f01e70f1c927), U64(0xbe71a770cac1a473),
+		U64(0x0e3d6be7a64b1894), U64(0x7ec8148cff29d840),
+		U64(0xcb7476c7fac3be0f), U64(0x72956a4a63a91636),
+		U64(0x37f95ec21991138f), U64(0x9e3fea5a4ded45f5),
+		U64(0x7b38ba50964902e8), U64(0x222e580bbde73764),
+		U64(0x61e253e0899f55e6), U64(0xfc8d2805e352ad80),
+		U64(0x35994be3235ac56d), U64(0x09add01af5e014de),
+		U64(0x5e8659a6780539c6), U64(0xb17c48097161d796),
+		U64(0x026015213acbd6e2), U64(0xd1ae9f77e515e901),
+		U64(0xb7dc776a3f21b0ad), U64(0xaba6a1b96eb78098),
+		U64(0x9bcf4486248d9f5d), U64(0x582666c536455efd),
+		U64(0xfdbdac9bfeb9c6f1), U64(0xc47999be4163cdea),
+		U64(0x765540081722a7ef), U64(0x3e548ed8ec710751),
+		U64(0x3d041f67cb51bac2), U64(0x7958af71ac82d40a),
+		U64(0x36c9da5c047a78fe), U64(0xed9a048e33af38b2),
+		U64(0x26ee7249c96c86bd), U64(0x900281bdeba65d61),
+		U64(0x11172c8bd0fd9532), U64(0xea0abf73600434f8),
+		U64(0x42fc8f75299309f3), U64(0x34a9cf7d3eb1ae1c),
+		U64(0x2b838811480723ba), U64(0x5ce64c8742ceef24),
+		U64(0x1adae9b01fd6570e), U64(0x3c349bf9d6bad1b3),
+		U64(0x82453c891c7b75c0), U64(0x97923a40b80d512b),
+		U64(0x4a61dbf1c198765c), U64(0xb48ce6d518010d3e),
+		U64(0xcfb45c858e480fd6), U64(0xd933cbf30d1e96ae),
+		U64(0xd70ea014ab558e3a), U64(0xc189376228031742),
+		U64(0x9262949cd16d8b83), U64(0xeb3a3bed7def5f89),
+		U64(0x49314a4ee6b8cbcf), U64(0xdcc3652f647e4c06),
+		U64(0xda635a4c2a3e2b3d), U64(0x470c21a940f3d35b),
+		U64(0x315961a157d174b4), U64(0x6672e81dda3459ac),
+		U64(0x5b76f77a1165e36e), U64(0x445cb01667d36ec8),
+		U64(0xc5491d205c88a69b), U64(0x456c34887a3805b9),
+		U64(0xffddb9bac4721013), U64(0x99af51a71e4649bf),
+		U64(0xa15be01cbc7729d5), U64(0x52db2760e485f7b0),
+		U64(0x8c78576eba306d54), U64(0xae560f6507d75a30),
+		U64(0x95f22f6182c687c9), U64(0x71c5fbf54489aba5),
+		U64(0xca44f259e728d57e), U64(0x88b87d2ccebbdc8d),
+		U64(0xbab18d32be4a15aa), U64(0x8be8ec93e99b611e),
+		U64(0x17b713e89ebdf209), U64(0xb31c5d284baa0174),
+		U64(0xeeca9531148f8521), U64(0xb8d198138481c348),
+		U64(0x8988f9b2d350b7fc), U64(0xb9e11c8d996aa839),
+		U64(0x5a4673e40c8e881f), U64(0x1687977683569978),
+		U64(0xbf4123eed72acf02), U64(0x4ea1f1b3b513c785),
+		U64(0xe767452be16f91ff), U64(0x7505d1b730021a7c),
+		U64(0xa59bca5ec8fc980c), U64(0xad069eda20f7e7a3),
+		U64(0x38f4b1bba231606a), U64(0x60d2d77e94743e97),
+		U64(0x9affc0183966f42c), U64(0x248e6768f3a7505f),
+		U64(0xcdd449a4b483d934), U64(0x87b59255751baf68),
+		U64(0x1bea6d2e023d3c7f), U64(0x6b1f12455b5ffcab),
+		U64(0x743555292de9710d), U64(0xd8034f6d10f5fddf),
+		U64(0xc6198c9f7ba81b08), U64(0xbb8109aca3a17edb),
+		U64(0xfa2d1766ad12cabb), U64(0xc729080166437079),
+		U64(0x9c5fff7b77269317), U64(0x0000000000000000),
+		U64(0x15d706c9a47624eb), U64(0x6fdf38072fd44d72),
+		U64(0x5fb6dd3865ee52b7), U64(0xa33bf53d86bcff37),
+		U64(0xe657c1b5fc84fa8e), U64(0xaa962527735cebe9),
+		U64(0x39c43525bfda0b1b), U64(0x204e4d2a872ce186),
+		U64(0x7a083ece8ba26999), U64(0x554b9c9db72efbfa),
+		U64(0xb22cd9b656416a05), U64(0x96a2bedea5e63a5a),
+		U64(0x802529a826b0a322), U64(0x8115ad363b5bc853),
+		U64(0x8375b81701901eb1), U64(0x3069e53f4a3a1fc5),
+		U64(0xbd2136cfede119e0), U64(0x18bafc91251d81ec),
+		U64(0x1d4a524d4c7d5b44), U64(0x05f0aedc6960daa8),
+		U64(0x29e39d3072ccf558), U64(0x70f57f6b5962c0d4),
+		U64(0x989fd53903ad22ce), U64(0xf84d024797d91c59),
+		U64(0x547b1803aac5908b), U64(0xf0d056c37fd263f6),
+		U64(0xd56eb535919e58d8), U64(0x1c7ad6d351963035),
+		U64(0x2e7326cd2167f912), U64(0xac361a443d1c8cd2),
+		U64(0x697f076461942a49), U64(0x4b515f6fdc731d2d),
+		U64(0x8ad8680df4700a6f), U64(0x41ac1eca0eb3b460),
+		U64(0x7d988533d80965d3), U64(0xa8f6300649973d0b),
+		U64(0x7765c4960ac9cc9e), U64(0x7ca801adc5e20ea2),
+		U64(0xdea3700e5eb59ae4), U64(0xa06b6482a19c42a4),
+		U64(0x6a2f96db46b497da), U64(0x27def6d7d487edcc),
+		U64(0x463ca5375d18b82a), U64(0xa6cb5be1efdc259f),
+		U64(0x53eba3fef96e9cc1), U64(0xce84d81b93a364a7),
+		U64(0xf4107c810b59d22f), U64(0x333974806d1aa256),
+		U64(0x0f0def79bba073e5), U64(0x231edc95a00c5c15),
+		U64(0xe437d494c64f2c6c), U64(0x91320523f64d3610),
+		U64(0x67426c83c7df32dd), U64(0x6eefbc99323f2603),
+		U64(0x9d6f7be56acdf866), U64(0x5916e25b2bae358c),
+		U64(0x7ff89012e2c2b331), U64(0x035091bf2720bd93),
+		U64(0x561b0d22900e4669), U64(0x28d319ae6f279e29),
+		U64(0x2f43a2533c8c9263), U64(0xd09e1be9f8fe8270),
+		U64(0xf740ed3e2c796fbc), U64(0xdb53ded237d5404c),
+		U64(0x62b2c25faebfe875), U64(0x0afd41a5d2c0a94d),
+		U64(0x6412fd3ce0ff8f4e), U64(0xe3a76f6995e42026),
+		U64(0x6c8fa9b808f4f0e1), U64(0xc2d9a6dd0f23aad1),
+		U64(0x8f28c6d19d10d0c7), U64(0x85d587744fd0798a),
+		U64(0xa20b71a39b579446), U64(0x684f83fa7c7f4138),
+		U64(0xe507500adba4471d), U64(0x3f640a46f19a6c20),
+		U64(0x1247bd34f7dd28a1), U64(0x2d23b77206474481),
+		U64(0x93521002cc86e0f2), U64(0x572b89bc8de52d18),
+		U64(0xfb1d93f8b0f9a1ca), U64(0xe95a2ecc4724896b),
+		U64(0x3ba420048511ddf9), U64(0xd63e248ab6bee54b),
+		U64(0x5dd6c8195f258455), U64(0x06a03f634e40673b),
+		U64(0x1f2a476c76b68da6), U64(0x217ec9b49ac78af7),
+		U64(0xecaa80102e4453c3), U64(0x14e78257b99d4f9a)
+	}, { /* 3 */
+		U64(0x20329b2cc87bba05), U64(0x4f5eb6f86546a531),
+		U64(0xd4f44775f751b6b1), U64(0x8266a47b850dfa8b),
+		U64(0xbb986aa15a6ca985), U64(0xc979eb08f9ae0f99),
+		U64(0x2da6f447a2375ea1), U64(0x1e74275dcd7d8576),
+		U64(0xbc20180a800bc5f8), U64(0xb4a2f701b2dc65be),
+		U64(0xe726946f981b6d66), U64(0x48e6c453bf21c94c),
+		U64(0x42cad9930f0a4195), U64(0xefa47b64aacccd20),
+		U64(0x71180a8960409a42), U64(0x8bb3329bf6a44e0c),
+		U64(0xd34c35de2d36dacc), U64(0xa92f5b7cbc23dc96),
+		U64(0xb31a85aa68bb09c3), U64(0x13e04836a73161d2),
+		U64(0xb24dfc4129c51d02), U64(0x8ae44b70b7da5acd),
+		U64(0xe671ed84d96579a7), U64(0xa4bb3417d66f3832),
+		U64(0x4572ab38d56d2de8), U64(0xb1b47761ea47215c),
+		U64(0xe81c09cf70aba15d), U64(0xffbdb872ce7f90ac),
+		U64(0xa8782297fd5dc857), U64(0x0d946f6b6a4ce4a4),
+		U64(0xe4df1f4f5b995138), U64(0x9ebc71edca8c5762),
+		U64(0x0a2c1dc0b02b88d9), U64(0x3b503c115d9d7b91),
+		U64(0xc64376a8111ec3a2), U64(0xcec199a323c963e4),
+		U64(0xdc76a87ec58616f7), U64(0x09d596e073a9b487),
+		U64(0x14583a9d7d560daf), U64(0xf4c6dc593f2a0cb4),
+		U64(0xdd21d19584f80236), U64(0x4a4836983ddde1d3),
+		U64(0xe58866a41ae745f9), U64(0xf591a5b27e541875),
+		U64(0x891dc05074586693), U64(0x5b068c651810a89e),
+		U64(0xa30346bc0c08544f), U64(0x3dbf3751c684032d),
+		U64(0x2a1e86ec785032dc), U64(0xf73f5779fca830ea),
+		U64(0xb60c05ca30204d21), U64(0x0cc316802b32f065),
+		U64(0x8770241bdd96be69), U64(0xb861e18199ee95db),
+		U64(0xf805cad91418fcd1), U64(0x29e70dccbbd20e82),
+		U64(0xc7140f435060d763), U64(0x0f3a9da0e8b0cc3b),
+		U64(0xa2543f574d76408e), U64(0xbd7761e1c175d139),
+		U64(0x4b1f4f737ca3f512), U64(0x6dc2df1f2fc137ab),
+		U64(0xf1d05c3967b14856), U64(0xa742bf3715ed046c),
+		U64(0x654030141d1697ed), U64(0x07b872abda676c7d),
+		U64(0x3ce84eba87fa17ec), U64(0xc1fb0403cb79afdf),
+		U64(0x3e46bc7105063f73), U64(0x278ae987121cd678),
+		U64(0xa1adb4778ef47cd0), U64(0x26dd906c5362c2b9),
+		U64(0x05168060589b44e2), U64(0xfbfc41f9d79ac08f),
+		U64(0x0e6de44ba9ced8fa), U64(0x9feb08068bf243a3),
+		U64(0x7b341749d06b129b), U64(0x229c69e74a87929a),
+		U64(0xe09ee6c4427c011b), U64(0x5692e30e725c4c3a),
+		U64(0xda99a33e5e9f6e4b), U64(0x353dd85af453a36b),
+		U64(0x25241b4c90e0fee7), U64(0x5de987258309d022),
+		U64(0xe230140fc0802984), U64(0x93281e86a0c0b3c6),
+		U64(0xf229d719a4337408), U64(0x6f6c2dd4ad3d1f34),
+		U64(0x8ea5b2fbae3f0aee), U64(0x8331dd90c473ee4a),
+		U64(0x346aa1b1b52db7aa), U64(0xdf8f235e06042aa9),
+		U64(0xcc6f6b68a1354b7b), U64(0x6c95a6f46ebf236a),
+		U64(0x52d31a856bb91c19), U64(0x1a35ded6d498d555),
+		U64(0xf37eaef2e54d60c9), U64(0x72e181a9a3c2a61c),
+		U64(0x98537aad51952fde), U64(0x16f6c856ffaa2530),
+		U64(0xd960281e9d1d5215), U64(0x3a0745fa1ce36f50),
+		U64(0x0b7b642bf1559c18), U64(0x59a87eae9aec8001),
+		U64(0x5e100c05408bec7c), U64(0x0441f98b19e55023),
+		U64(0xd70dcc5534d38aef), U64(0x927f676de1bea707),
+		U64(0x9769e70db925e3e5), U64(0x7a636ea29115065a),
+		U64(0x468b201816ef11b6), U64(0xab81a9b73edff409),
+		U64(0xc0ac7de88a07bb1e), U64(0x1f235eb68c0391b7),
+		U64(0x6056b074458dd30f), U64(0xbe8eeac102f7ed67),
+		U64(0xcd381283e04b5fba), U64(0x5cbefecec277c4e3),
+		U64(0xd21b4c356c48ce0d), U64(0x1019c31664b35d8c),
+		U64(0x247362a7d19eea26), U64(0xebe582efb3299d03),
+		U64(0x02aef2cb82fc289f), U64(0x86275df09ce8aaa8),
+		U64(0x28b07427faac1a43), U64(0x38a9b7319e1f47cf),
+		U64(0xc82e92e3b8d01b58), U64(0x06ef0b409b1978bc),
+		U64(0x62f842bfc771fb90), U64(0x9904034610eb3b1f),
+		U64(0xded85ab5477a3e68), U64(0x90d195a663428f98),
+		U64(0x5384636e2ac708d8), U64(0xcbd719c37b522706),
+		U64(0xae9729d76644b0eb), U64(0x7c8c65e20a0c7ee6),
+		U64(0x80c856b007f1d214), U64(0x8c0b40302cc32271),
+		U64(0xdbcedad51fe17a8a), U64(0x740e8ae938dbdea0),
+		U64(0xa615c6dc549310ad), U64(0x19cc55f6171ae90b),
+		U64(0x49b1bdb8fe5fdd8d), U64(0xed0a89af2830e5bf),
+		U64(0x6a7aadb4f5a65bd6), U64(0x7e22972988f05679),
+		U64(0xf952b3325566e810), U64(0x39fecedadf61530e),
+		U64(0x6101c99f04f3c7ce), U64(0x2e5f7f6761b562ff),
+		U64(0xf08725d226cf5c97), U64(0x63af3b54860fef51),
+		U64(0x8ff2cb10ef411e2f), U64(0x884ab9bb35267252),
+		U64(0x4df04433e7ba8dae), U64(0x9afd8866d3690741),
+		U64(0x66b9bb34de94abb3), U64(0x9baaf18d92171380),
+		U64(0x543c11c5f0a064a5), U64(0x17a1b1bdbed431f1),
+		U64(0xb5f58eeaf3a2717f), U64(0xc355f6c849858740),
+		U64(0xec5df044694ef17e), U64(0xd83751f5dc6346d4),
+		U64(0xfc4433520dfdacf2), U64(0x0000000000000000),
+		U64(0x5a51f58e596ebc5f), U64(0x3285aaf12e34cf16),
+		U64(0x8d5c39db6dbd36b0), U64(0x12b731dde64f7513),
+		U64(0x94906c2d7aa7dfbb), U64(0x302b583aacc8e789),
+		U64(0x9d45facd090e6b3c), U64(0x2165e2c78905aec4),
+		U64(0x68d45f7f775a7349), U64(0x189b2c1d5664fdca),
+		U64(0xe1c99f2f030215da), U64(0x6983269436246788),
+		U64(0x8489af3b1e148237), U64(0xe94b702431d5b59c),
+		U64(0x33d2d31a6f4adbd7), U64(0xbfd9932a4389f9a6),
+		U64(0xb0e30e8aab39359d), U64(0xd1e2c715afcaf253),
+		U64(0x150f43763c28196e), U64(0xc4ed846393e2eb3d),
+		U64(0x03f98b20c3823c5e), U64(0xfd134ab94c83b833),
+		U64(0x556b682eb1de7064), U64(0x36c4537a37d19f35),
+		U64(0x7559f30279a5ca61), U64(0x799ae58252973a04),
+		U64(0x9c12832648707ffd), U64(0x78cd9c6913e92ec5),
+		U64(0x1d8dac7d0effb928), U64(0x439da0784e745554),
+		U64(0x413352b3cc887dcb), U64(0xbacf134a1b12bd44),
+		U64(0x114ebafd25cd494d), U64(0x2f08068c20cb763e),
+		U64(0x76a07822ba27f63f), U64(0xeab2fb04f25789c2),
+		U64(0xe3676de481fe3d45), U64(0x1b62a73d95e6c194),
+		U64(0x641749ff5c68832c), U64(0xa5ec4dfc97112cf3),
+		U64(0xf6682e92bdd6242b), U64(0x3f11c59a44782bb2),
+		U64(0x317c21d1edb6f348), U64(0xd65ab5be75ad9e2e),
+		U64(0x6b2dd45fb4d84f17), U64(0xfaab381296e4d44e),
+		U64(0xd0b5befeeeb4e692), U64(0x0882ef0b32d7a046),
+		U64(0x512a91a5a83b2047), U64(0x963e9ee6f85bf724),
+		U64(0x4e09cf132438b1f0), U64(0x77f701c9fb59e2fe),
+		U64(0x7ddb1c094b726a27), U64(0x5f4775ee01f5f8bd),
+		U64(0x9186ec4d223c9b59), U64(0xfeeac1998f01846d),
+		U64(0xac39db1ce4b89874), U64(0xb75b7c21715e59e0),
+		U64(0xafc0503c273aa42a), U64(0x6e3b543fec430bf5),
+		U64(0x704f7362213e8e83), U64(0x58ff0745db9294c0),
+		U64(0x67eec2df9feabf72), U64(0xa0facd9ccf8a6811),
+		U64(0xb936986ad890811a), U64(0x95c715c63bd9cb7a),
+		U64(0xca8060283a2c33c7), U64(0x507de84ee9453486),
+		U64(0x85ded6d05f6a96f6), U64(0x1cdad5964f81ade9),
+		U64(0xd5a33e9eb62fa270), U64(0x40642b588df6690a),
+		U64(0x7f75eec2c98e42b8), U64(0x2cf18dace3494a60),
+		U64(0x23cb100c0bf9865b), U64(0xeef3028febb2d9e1),
+		U64(0x4425d2d394133929), U64(0xaad6d05c7fa1e0c8),
+		U64(0xad6ea2f7a5c68cb5), U64(0xc2028f2308fb9381),
+		U64(0x819f2f5b468fc6d5), U64(0xc5bafd88d29cfffc),
+		U64(0x47dc59f357910577), U64(0x2b49ff07392e261d),
+		U64(0x57c59ae5332258fb), U64(0x73b6f842e2bcb2dd),
+		U64(0xcf96e04862b77725), U64(0x4ca73dd8a6c4996f),
+		U64(0x015779eb417e14c1), U64(0x37932a9176af8bf4)
+	}, { /* 4 */
+		U64(0x190a2c9b249df23e), U64(0x2f62f8b62263e1e9),
+		U64(0x7a7f754740993655), U64(0x330b7ba4d5564d9f),
+		U64(0x4c17a16a46672582), U64(0xb22f08eb7d05f5b8),
+		U64(0x535f47f40bc148cc), U64(0x3aec5d27d4883037),
+		U64(0x10ed0a1825438f96), U64(0x516101f72c233d17),
+		U64(0x13cc6f949fd04eae), U64(0x739853c441474bfd),
+		U64(0x653793d90d3f5b1b), U64(0x5240647b96b0fc2f),
+		U64(0x0c84890ad27623e0), U64(0xd7189b32703aaea3),
+		U64(0x2685de3523bd9c41), U64(0x99317c5b11bffefa),
+		U64(0x0d9baa854f079703), U64(0x70b93648fbd48ac5),
+		U64(0xa80441fce30bc6be), U64(0x7287704bdc36ff1e),
+		U64(0xb65384ed33dc1f13), U64(0xd36417343ee34408),
+		U64(0x39cd38ab6e1bf10f), U64(0x5ab861770a1f3564),
+		U64(0x0ebacf09f594563b), U64(0xd04572b884708530),
+		U64(0x3cae9722bdb3af47), U64(0x4a556b6f2f5cbaf2),
+		U64(0xe1704f1f76c4bd74), U64(0x5ec4ed7144c6dfcf),
+		U64(0x16afc01d4c7810e6), U64(0x283f113cd629ca7a),
+		U64(0xaf59a8761741ed2d), U64(0xeed5a3991e215fac),
+		U64(0x3bf37ea849f984d4), U64(0xe413e096a56ce33c),
+		U64(0x2c439d3a98f020d1), U64(0x637559dc6404c46b),
+		U64(0x9e6c95d1e5f5d569), U64(0x24bb9836045fe99a),
+		U64(0x44efa466dac8ecc9), U64(0xc6eab2a5c80895d6),
+		U64(0x803b50c035220cc4), U64(0x0321658cba93c138),
+		U64(0x8f9ebc465dc7ee1c), U64(0xd15a5137190131d3),
+		U64(0x0fa5ec8668e5e2d8), U64(0x91c979578d1037b1),
+		U64(0x0642ca05693b9f70), U64(0xefca80168350eb4f),
+		U64(0x38d21b24f36a45ec), U64(0xbeab81e1af73d658),
+		U64(0x8cbfd9cae7542f24), U64(0xfd19cc0d81f11102),
+		U64(0x0ac6430fbb4dbc90), U64(0x1d76a09d6a441895),
+		U64(0x2a01573ff1cbbfa1), U64(0xb572e161894fde2b),
+		U64(0x8124734fa853b827), U64(0x614b1fdf43e6b1b0),
+		U64(0x68ac395c4238cc18), U64(0x21d837bfd7f7b7d2),
+		U64(0x20c714304a860331), U64(0x5cfaab726324aa14),
+		U64(0x74c5ba4eb50d606e), U64(0xf3a3030474654739),
+		U64(0x23e671bcf015c209), U64(0x45f087e947b9582a),
+		U64(0xd8bd77b418df4c7b), U64(0xe06f6c90ebb50997),
+		U64(0x0bd96080263c0873), U64(0x7e03f9410e40dcfe),
+		U64(0xb8e94be4c6484928), U64(0xfb5b0608e8ca8e72),
+		U64(0x1a2b49179e0e3306), U64(0x4e29e76961855059),
+		U64(0x4f36c4e6fcf4e4ba), U64(0x49740ee395cf7bca),
+		U64(0xc2963ea386d17f7d), U64(0x90d65ad810618352),
+		U64(0x12d34c1b02a1fa4d), U64(0xfa44258775bb3a91),
+		U64(0x18150f14b9ec46dd), U64(0x1491861e6b9a653d),
+		U64(0x9a1019d7ab2c3fc2), U64(0x3668d42d06fe13d7),
+		U64(0xdcc1fbb25606a6d0), U64(0x969490dd795a1c22),
+		U64(0x3549b1a1bc6dd2ef), U64(0xc94f5e23a0ed770e),
+		U64(0xb9f6686b5b39fdcb), U64(0xc4d4f4a6efeae00d),
+		U64(0xe732851a1fff2204), U64(0x94aad6de5eb869f9),
+		U64(0x3f8ff2ae07206e7f), U64(0xfe38a9813b62d03a),
+		U64(0xa7a1ad7a8bee2466), U64(0x7b6056c8dde882b6),
+		U64(0x302a1e286fc58ca7), U64(0x8da0fa457a259bc7),
+		U64(0xb3302b64e074415b), U64(0x5402ae7eff8b635f),
+		U64(0x08f8050c9cafc94b), U64(0xae468bf98a3059ce),
+		U64(0x88c355cca98dc58f), U64(0xb10e6d67c7963480),
+		U64(0xbad70de7e1aa3cf3), U64(0xbfb4a26e320262bb),
+		U64(0xcb711820870f02d5), U64(0xce12b7a954a75c9d),
+		U64(0x563ce87dd8691684), U64(0x9f73b65e7884618a),
+		U64(0x2b1e74b06cba0b42), U64(0x47cec1ea605b2df1),
+		U64(0x1c698312f735ac76), U64(0x5fdbcefed9b76b2c),
+		U64(0x831a354c8fb1cdfc), U64(0x820516c312c0791f),
+		U64(0xb74ca762aeadabf0), U64(0xfc06ef821c80a5e1),
+		U64(0x5723cbf24518a267), U64(0x9d4df05d5f661451),
+		U64(0x588627742dfd40bf), U64(0xda8331b73f3d39a0),
+		U64(0x17b0e392d109a405), U64(0xf965400bcf28fba9),
+		U64(0x7c3dbf4229a2a925), U64(0x023e460327e275db),
+		U64(0x6cd0b55a0ce126b3), U64(0xe62da695828e96e7),
+		U64(0x42ad6e63b3f373b9), U64(0xe50cc319381d57df),
+		U64(0xc5cbd729729b54ee), U64(0x46d1e265fd2a9912),
+		U64(0x6428b056904eeff8), U64(0x8be23040131e04b7),
+		U64(0x6709d5da2add2ec0), U64(0x075de98af44a2b93),
+		U64(0x8447dcc67bfbe66f), U64(0x6616f655b7ac9a23),
+		U64(0xd607b8bded4b1a40), U64(0x0563af89d3a85e48),
+		U64(0x3db1b4ad20c21ba4), U64(0x11f22997b8323b75),
+		U64(0x292032b34b587e99), U64(0x7f1cdace9331681d),
+		U64(0x8e819fc9c0b65aff), U64(0xa1e3677fe2d5bb16),
+		U64(0xcd33d225ee349da5), U64(0xd9a2543b85aef898),
+		U64(0x795e10cbfa0af76d), U64(0x25a4bbb9992e5d79),
+		U64(0x78413344677b438e), U64(0xf0826688cef68601),
+		U64(0xd27b34bba392f0eb), U64(0x551d8df162fad7bc),
+		U64(0x1e57c511d0d7d9ad), U64(0xdeffbdb171e4d30b),
+		U64(0xf4feea8e802f6caa), U64(0xa480c8f6317de55e),
+		U64(0xa0fc44f07fa40ff5), U64(0x95b5f551c3c9dd1a),
+		U64(0x22f952336d6476ea), U64(0x0000000000000000),
+		U64(0xa6be8ef5169f9085), U64(0xcc2cf1aa73452946),
+		U64(0x2e7ddb39bf12550a), U64(0xd526dd3157d8db78),
+		U64(0x486b2d6c08becf29), U64(0x9b0f3a58365d8b21),
+		U64(0xac78cdfaadd22c15), U64(0xbc95c7e28891a383),
+		U64(0x6a927f5f65dab9c3), U64(0xc3891d2c1ba0cb9e),
+		U64(0xeaa92f9f50f8b507), U64(0xcf0d9426c9d6e87e),
+		U64(0xca6e3baf1a7eb636), U64(0xab25247059980786),
+		U64(0x69b31ad3df4978fb), U64(0xe2512a93cc577c4c),
+		U64(0xff278a0ea61364d9), U64(0x71a615c766a53e26),
+		U64(0x89dc764334fc716c), U64(0xf87a638452594f4a),
+		U64(0xf2bc208be914f3da), U64(0x8766b94ac1682757),
+		U64(0xbbc82e687cdb8810), U64(0x626a7a53f9757088),
+		U64(0xa2c202f358467a2e), U64(0x4d0882e5db169161),
+		U64(0x09e7268301de7da8), U64(0xe897699c771ac0dc),
+		U64(0xc8507dac3d9cc3ed), U64(0xc0a878a0a1330aa6),
+		U64(0x978bb352e42ba8c1), U64(0xe9884a13ea6b743f),
+		U64(0x279afdbabecc28a2), U64(0x047c8c064ed9eaab),
+		U64(0x507e2278b15289f4), U64(0x599904fbb08cf45c),
+		U64(0xbd8ae46d15e01760), U64(0x31353da7f2b43844),
+		U64(0x8558ff49e68a528c), U64(0x76fbfc4d92ef15b5),
+		U64(0x3456922e211c660c), U64(0x86799ac55c1993b4),
+		U64(0x3e90d1219a51da9c), U64(0x2d5cbeb505819432),
+		U64(0x982e5fd48cce4a19), U64(0xdb9c1238a24c8d43),
+		U64(0xd439febecaa96f9b), U64(0x418c0bef0960b281),
+		U64(0x158ea591f6ebd1de), U64(0x1f48e69e4da66d4e),
+		U64(0x8afd13cf8e6fb054), U64(0xf5e1c9011d5ed849),
+		U64(0xe34e091c5126c8af), U64(0xad67ee7530a398f6),
+		U64(0x43b24dec2e82c75a), U64(0x75da99c1287cd48d),
+		U64(0x92e81cdb3783f689), U64(0xa3dd217cc537cecd),
+		U64(0x60543c50de970553), U64(0x93f73f54aaf2426a),
+		U64(0xa91b62737e7a725d), U64(0xf19d4507538732e2),
+		U64(0x77e4dfc20f9ea156), U64(0x7d229ccdb4d31dc6),
+		U64(0x1b346a98037f87e5), U64(0xedf4c615a4b29e94),
+		U64(0x4093286094110662), U64(0xb0114ee85ae78063),
+		U64(0x6ff1d0d6b672e78b), U64(0x6dcf96d591909250),
+		U64(0xdfe09e3eec9567e8), U64(0x3214582b4827f97c),
+		U64(0xb46dc2ee143e6ac8), U64(0xf6c0ac8da7cd1971),
+		U64(0xebb60c10cd8901e4), U64(0xf7df8f023abcad92),
+		U64(0x9c52d3d2c217a0b2), U64(0x6b8d5cd0f8ab0d20),
+		U64(0x3777f7a29b8fa734), U64(0x011f238f9d71b4e3),
+		U64(0xc1b75b2f3c42be45), U64(0x5de588fdfe551ef7),
+		U64(0x6eeef3592b035368), U64(0xaa3a07ffc4e9b365),
+		U64(0xecebe59a39c32a77), U64(0x5ba742f8976e8187),
+		U64(0x4b4a48e0b22d0e11), U64(0xddded83dcb771233),
+		U64(0xa59feb79ac0c51bd), U64(0xc7f5912a55792135)
+	}, { /* 5 */
+		U64(0x6d6ae04668a9b08a), U64(0x3ab3f04b0be8c743),
+		U64(0xe51e166b54b3c908), U64(0xbe90a9eb35c2f139),
+		U64(0xb2c7066637f2bec1), U64(0xaa6945613392202c),
+		U64(0x9a28c36f3b5201eb), U64(0xddce5a93ab536994),
+		U64(0x0e34133ef6382827), U64(0x52a02ba1ec55048b),
+		U64(0xa2f88f97c4b2a177), U64(0x8640e513ca2251a5),
+		U64(0xcdf1d36258137622), U64(0xfe6cb708dedf8ddb),
+		U64(0x8a174a9ec8121e5d), U64(0x679896036b81560e),
+		U64(0x59ed033395795fee), U64(0x1dd778ab8b74edaf),
+		U64(0xee533ef92d9f926d), U64(0x2a8c79baf8a8d8f5),
+		U64(0x6bcf398e69b119f6), U64(0xe20491742fafdd95),
+		U64(0x276488e0809c2aec), U64(0xea955b82d88f5cce),
+		U64(0x7102c63a99d9e0c4), U64(0xf9763017a5c39946),
+		U64(0x429fa2501f151b3d), U64(0x4659c72bea05d59e),
+		U64(0x984b7fdccf5a6634), U64(0xf742232953fbb161),
+		U64(0x3041860e08c021c7), U64(0x747bfd9616cd9386),
+		U64(0x4bb1367192312787), U64(0x1b72a1638a6c44d3),
+		U64(0x4a0e68a6e8359a66), U64(0x169a5039f258b6ca),
+		U64(0xb98a2ef44edee5a4), U64(0xd9083fe85e43a737),
+		U64(0x967f6ce239624e13), U64(0x8874f62d3c1a7982),
+		U64(0x3c1629830af06e3f), U64(0x9165ebfd427e5a8e),
+		U64(0xb5dd81794ceeaa5c), U64(0x0de8f15a7834f219),
+		U64(0x70bd98ede3dd5d25), U64(0xaccc9ca9328a8950),
+		U64(0x56664eda1945ca28), U64(0x221db34c0f8859ae),
+		U64(0x26dbd637fa98970d), U64(0x1acdffb4f068f932),
+		U64(0x4585254f64090fa0), U64(0x72de245e17d53afa),
+		U64(0x1546b25d7c546cf4), U64(0x207e0ffffb803e71),
+		U64(0xfaaad2732bcf4378), U64(0xb462dfae36ea17bd),
+		U64(0xcf926fd1ac1b11fd), U64(0xe0672dc7dba7ba4a),
+		U64(0xd3fa49ad5d6b41b3), U64(0x8ba81449b216a3bc),
+		U64(0x14f9ec8a0650d115), U64(0x40fc1ee3eb1d7ce2),
+		U64(0x23a2ed9b758ce44f), U64(0x782c521b14fddc7e),
+		U64(0x1c68267cf170504e), U64(0xbcf31558c1ca96e6),
+		U64(0xa781b43b4ba6d235), U64(0xf6fd7dfe29ff0c80),
+		U64(0xb0a4bad5c3fad91e), U64(0xd199f51ea963266c),
+		U64(0x414340349119c103), U64(0x5405f269ed4dadf7),
+		U64(0xabd61bb649969dcd), U64(0x6813dbeae7bdc3c8),
+		U64(0x65fb2ab09f8931d1), U64(0xf1e7fae152e3181d),
+		U64(0xc1a67cef5a2339da), U64(0x7a4feea8e0f5bba1),
+		U64(0x1e0b9acf05783791), U64(0x5b8ebf8061713831),
+		U64(0x80e53cdbcb3af8d9), U64(0x7e898bd315e57502),
+		U64(0xc6bcfbf0213f2d47), U64(0x95a38e86b76e942d),
+		U64(0x092e94218d243cba), U64(0x8339debf453622e7),
+		U64(0xb11be402b9fe64ff), U64(0x57d9100d634177c9),
+		U64(0xcc4e8db52217cbc3), U64(0x3b0cae9c71ec7aa2),
+		U64(0xfb158ca451cbfe99), U64(0x2b33276d82ac6514),
+		U64(0x01bf5ed77a04bde1), U64(0xc5601994af33f779),
+		U64(0x75c4a3416cc92e67), U64(0xf3844652a6eb7fc2),
+		U64(0x3487e375fdd0ef64), U64(0x18ae430704609eed),
+		U64(0x4d14efb993298efb), U64(0x815a620cb13e4538),
+		U64(0x125c354207487869), U64(0x9eeea614ce42cf48),
+		U64(0xce2d3106d61fac1c), U64(0xbbe99247bad6827b),
+		U64(0x071a871f7b1c149d), U64(0x2e4a1cc10db81656),
+		U64(0x77a71ff298c149b8), U64(0x06a5d9c80118a97c),
+		U64(0xad73c27e488e34b1), U64(0x443a7b981e0db241),
+		U64(0xe3bbcfa355ab6074), U64(0x0af276450328e684),
+		U64(0x73617a896dd1871b), U64(0x58525de4ef7de20f),
+		U64(0xb7be3dcab8e6cd83), U64(0x19111dd07e64230c),
+		U64(0x842359a03e2a367a), U64(0x103f89f1f3401fb6),
+		U64(0xdc710444d157d475), U64(0xb835702334da5845),
+		U64(0x4320fc876511a6dc), U64(0xd026abc9d3679b8d),
+		U64(0x17250eee885c0b2b), U64(0x90dab52a387ae76f),
+		U64(0x31fed8d972c49c26), U64(0x89cba8fa461ec463),
+		U64(0x2ff5421677bcabb7), U64(0x396f122f85e41d7d),
+		U64(0xa09b332430bac6a8), U64(0xc888e8ced7070560),
+		U64(0xaeaf201ac682ee8f), U64(0x1180d7268944a257),
+		U64(0xf058a43628e7a5fc), U64(0xbd4c4b8fbbce2b07),
+		U64(0xa1246df34abe7b49), U64(0x7d5569b79be9af3c),
+		U64(0xa9b5a705bd9efa12), U64(0xdb6b835baa4bc0e8),
+		U64(0x05793bac8f147342), U64(0x21c1512881848390),
+		U64(0xfdb0556c50d357e5), U64(0x613d4fcb6a99ff72),
+		U64(0x03dce2648e0cda3e), U64(0xe949b9e6568386f0),
+		U64(0xfc0f0bbb2ad7ea04), U64(0x6a70675913b5a417),
+		U64(0x7f36d5046fe1c8e3), U64(0x0c57af8d02304ff8),
+		U64(0x32223abdfcc84618), U64(0x0891caf6f720815b),
+		U64(0xa63eeaec31a26fd4), U64(0x2507345374944d33),
+		U64(0x49d28ac266394058), U64(0xf5219f9aa7f3d6be),
+		U64(0x2d96fea583b4cc68), U64(0x5a31e1571b7585d0),
+		U64(0x8ed12fe53d02d0fe), U64(0xdfade6205f5b0e4b),
+		U64(0x4cabb16ee92d331a), U64(0x04c6657bf510cea3),
+		U64(0xd73c2cd6a87b8f10), U64(0xe1d87310a1a307ab),
+		U64(0x6cd5be9112ad0d6b), U64(0x97c032354366f3f2),
+		U64(0xd4e0ceb22677552e), U64(0x0000000000000000),
+		U64(0x29509bde76a402cb), U64(0xc27a9e8bd42fe3e4),
+		U64(0x5ef7842cee654b73), U64(0xaf107ecdbc86536e),
+		U64(0x3fcacbe784fcb401), U64(0xd55f90655c73e8cf),
+		U64(0xe6c2f40fdabf1336), U64(0xe8f6e7312c873b11),
+		U64(0xeb2a0555a28be12f), U64(0xe4a148bc2eb774e9),
+		U64(0x9b979db84156bc0a), U64(0x6eb60222e6a56ab4),
+		U64(0x87ffbbc4b026ec44), U64(0xc703a5275b3b90a6),
+		U64(0x47e699fc9001687f), U64(0x9c8d1aa73a4aa897),
+		U64(0x7cea3760e1ed12dd), U64(0x4ec80ddd1d2554c5),
+		U64(0x13e36b957d4cc588), U64(0x5d2b66486069914d),
+		U64(0x92b90999cc7280b0), U64(0x517cc9c56259deb5),
+		U64(0xc937b619ad03b881), U64(0xec30824ad997f5b2),
+		U64(0xa45d565fc5aa080b), U64(0xd6837201d27f32f1),
+		U64(0x635ef3789e9198ad), U64(0x531f75769651b96a),
+		U64(0x4f77530a6721e924), U64(0x486dd4151c3dfdb9),
+		U64(0x5f48dafb9461f692), U64(0x375b011173dc355a),
+		U64(0x3da9775470f4d3de), U64(0x8d0dcd81b30e0ac0),
+		U64(0x36e45fc609d888bb), U64(0x55baacbe97491016),
+		U64(0x8cb29356c90ab721), U64(0x76184125e2c5f459),
+		U64(0x99f4210bb55edbd5), U64(0x6f095cf59ca1d755),
+		U64(0x9f51f8c3b44672a9), U64(0x3538bda287d45285),
+		U64(0x50c39712185d6354), U64(0xf23b1885dcefc223),
+		U64(0x79930ccc6ef9619f), U64(0xed8fdc9da3934853),
+		U64(0xcb540aaa590bdf5e), U64(0x5c94389f1a6d2cac),
+		U64(0xe77daad8a0bbaed7), U64(0x28efc5090ca0bf2a),
+		U64(0xbf2ff73c4fc64cd8), U64(0xb37858b14df60320),
+		U64(0xf8c96ec0dfc724a7), U64(0x828680683f329f06),
+		U64(0x941cd051cd6a29cc), U64(0xc3c5c05cae2b5e05),
+		U64(0xb601631dc2e27062), U64(0xc01922382027843b),
+		U64(0x24b86a840e90f0d2), U64(0xd245177a276ffc52),
+		U64(0x0f8b4de98c3c95c6), U64(0x3e759530fef809e0),
+		U64(0x0b4d2892792c5b65), U64(0xc4df4743d5374a98),
+		U64(0xa5e20888bfaeb5ea), U64(0xba56cc90c0d23f9a),
+		U64(0x38d04cf8ffe0a09c), U64(0x62e1adafe495254c),
+		U64(0x0263bcb3f40867df), U64(0xcaeb547d230f62bf),
+		U64(0x6082111c109d4293), U64(0xdad4dd8cd04f7d09),
+		U64(0xefec602e579b2f8c), U64(0x1fb4c4187f7c8a70),
+		U64(0xffd3e9dfa4db303a), U64(0x7bf0b07f9af10640),
+		U64(0xf49ec14dddf76b5f), U64(0x8f6e713247066d1f),
+		U64(0x339d646a86ccfbf9), U64(0x64447467e58d8c30),
+		U64(0x2c29a072f9b07189), U64(0xd8b7613f24471ad6),
+		U64(0x6627c8d41185ebef), U64(0xa347d140beb61c96),
+		U64(0xde12b8f7255fb3aa), U64(0x9d324470404e1576),
+		U64(0x9306574eb6763d51), U64(0xa80af9d2c79a47f3),
+		U64(0x859c0777442e8b9b), U64(0x69ac853d9db97e29)
+	}, { /* 6 */
+		U64(0xc3407dfc2de6377e), U64(0x5b9e93eea4256f77),
+		U64(0xadb58fdd50c845e0), U64(0x5219ff11a75bed86),
+		U64(0x356b61cfd90b1de9), U64(0xfb8f406e25abe037),
+		U64(0x7a5a0231c0f60796), U64(0x9d3cd216e1f5020b),
+		U64(0x0c6550fb6b48d8f3), U64(0xf57508c427ff1c62),
+		U64(0x4ad35ffa71cb407d), U64(0x6290a2da1666aa6d),
+		U64(0xe284ec2349355f9f), U64(0xb3c307c53d7c84ec),
+		U64(0x05e23c0468365a02), U64(0x190bac4d6c9ebfa8),
+		U64(0x94bbbee9e28b80fa), U64(0xa34fc777529cb9b5),
+		U64(0xcc7b39f095bcd978), U64(0x2426addb0ce532e3),
+		U64(0x7e79329312ce4fc7), U64(0xab09a72eebec2917),
+		U64(0xf8d15499f6b9d6c2), U64(0x1a55b8babf8c895d),
+		U64(0xdb8add17fb769a85), U64(0xb57f2f368658e81b),
+		U64(0x8acd36f18f3f41f6), U64(0x5ce3b7bba50f11d3),
+		U64(0x114dcc14d5ee2f0a), U64(0xb91a7fcded1030e8),
+		U64(0x81d5425fe55de7a1), U64(0xb6213bc1554adeee),
+		U64(0x80144ef95f53f5f2), U64(0x1e7688186db4c10c),
+		U64(0x3b912965db5fe1bc), U64(0xc281715a97e8252d),
+		U64(0x54a5d7e21c7f8171), U64(0x4b12535ccbc5522e),
+		U64(0x1d289cefbea6f7f9), U64(0x6ef5f2217d2e729e),
+		U64(0xe6a7dc819b0d17ce), U64(0x1b94b41c05829b0e),
+		U64(0x33d7493c622f711e), U64(0xdcf7f942fa5ce421),
+		U64(0x600fba8b7f7a8ecb), U64(0x46b60f011a83988e),
+		U64(0x235b898e0dcf4c47), U64(0x957ab24f588592a9),
+		U64(0x4354330572b5c28c), U64(0xa5f3ef84e9b8d542),
+		U64(0x8c711e02341b2d01), U64(0x0b1874ae6a62a657),
+		U64(0x1213d8e306fc19ff), U64(0xfe6d7c6a4d9dba35),
+		U64(0x65ed868f174cd4c9), U64(0x88522ea0e6236550),
+		U64(0x899322065c2d7703), U64(0xc01e690bfef4018b),
+		U64(0x915982ed8abddaf8), U64(0xbe675b98ec3a4e4c),
+		U64(0xa996bf7f82f00db1), U64(0xe1daf8d49a27696a),
+		U64(0x2effd5d3dc8986e7), U64(0xd153a51f2b1a2e81),
+		U64(0x18caa0ebd690adfb), U64(0x390e3134b243c51a),
+		U64(0x2778b92cdff70416), U64(0x029f1851691c24a6),
+		U64(0x5e7cafeacc133575), U64(0xfa4e4cc89fa5f264),
+		U64(0x5a5f9f481e2b7d24), U64(0x484c47ab18d764db),
+		U64(0x400a27f2a1a7f479), U64(0xaeeb9b2a83da7315),
+		U64(0x721c626879869734), U64(0x042330a2d2384851),
+		U64(0x85f672fd3765aff0), U64(0xba446b3a3e02061d),
+		U64(0x73dd6ecec3888567), U64(0xffac70ccf793a866),
+		U64(0xdfa9edb5294ed2d4), U64(0x6c6aea7014325638),
+		U64(0x834a5a0e8c41c307), U64(0xcdba35562fb2cb2b),
+		U64(0x0ad97808d06cb404), U64(0x0f3b440cb85aee06),
+		U64(0xe5f9c876481f213b), U64(0x98deee1289c35809),
+		U64(0x59018bbfcd394bd1), U64(0xe01bf47220297b39),
+		U64(0xde68e1139340c087), U64(0x9fa3ca4788e926ad),
+		U64(0xbb85679c840c144e), U64(0x53d8f3b71d55ffd5),
+		U64(0x0da45c5dd146caa0), U64(0x6f34fe87c72060cd),
+		U64(0x57fbc315cf6db784), U64(0xcee421a1fca0fdde),
+		U64(0x3d2d0196607b8d4b), U64(0x642c8a29ad42c69a),
+		U64(0x14aff010bdd87508), U64(0xac74837beac657b3),
+		U64(0x3216459ad821634d), U64(0x3fb219c70967a9ed),
+		U64(0x06bc28f3bb246cf7), U64(0xf2082c9126d562c6),
+		U64(0x66b39278c45ee23c), U64(0xbd394f6f3f2878b9),
+		U64(0xfd33689d9e8f8cc0), U64(0x37f4799eb017394f),
+		U64(0x108cc0b26fe03d59), U64(0xda4bd1b1417888d6),
+		U64(0xb09d1332ee6eb219), U64(0x2f3ed975668794b4),
+		U64(0x58c0871977375982), U64(0x7561463d78ace990),
+		U64(0x09876cff037e82f1), U64(0x7fb83e35a8c05d94),
+		U64(0x26b9b58a65f91645), U64(0xef20b07e9873953f),
+		U64(0x3148516d0b3355b8), U64(0x41cb2b541ba9e62a),
+		U64(0x790416c613e43163), U64(0xa011d380818e8f40),
+		U64(0x3a5025c36151f3ef), U64(0xd57095bdf92266d0),
+		U64(0x498d4b0da2d97688), U64(0x8b0c3a57353153a5),
+		U64(0x21c491df64d368e1), U64(0x8f2f0af5e7091bf4),
+		U64(0x2da1c1240f9bb012), U64(0xc43d59a92ccc49da),
+		U64(0xbfa6573e56345c1f), U64(0x828b56a8364fd154),
+		U64(0x9a41f643e0df7caf), U64(0xbcf843c985266aea),
+		U64(0x2b1de9d7b4bfdce5), U64(0x20059d79dedd7ab2),
+		U64(0x6dabe6d6ae3c446b), U64(0x45e81bf6c991ae7b),
+		U64(0x6351ae7cac68b83e), U64(0xa432e32253b6c711),
+		U64(0xd092a9b991143cd2), U64(0xcac711032e98b58f),
+		U64(0xd8d4c9e02864ac70), U64(0xc5fc550f96c25b89),
+		U64(0xd7ef8dec903e4276), U64(0x67729ede7e50f06f),
+		U64(0xeac28c7af045cf3d), U64(0xb15c1f945460a04a),
+		U64(0x9cfddeb05bfb1058), U64(0x93c69abce3a1fe5e),
+		U64(0xeb0380dc4a4bdd6e), U64(0xd20db1e8f8081874),
+		U64(0x229a8528b7c15e14), U64(0x44291750739fbc28),
+		U64(0xd3ccbd4e42060a27), U64(0xf62b1c33f4ed2a97),
+		U64(0x86a8660ae4779905), U64(0xd62e814a2a305025),
+		U64(0x477703a7a08d8add), U64(0x7b9b0e977af815c5),
+		U64(0x78c51a60a9ea2330), U64(0xa6adfb733aaae3b7),
+		U64(0x97e5aa1e3199b60f), U64(0x0000000000000000),
+		U64(0xf4b404629df10e31), U64(0x5564db44a6719322),
+		U64(0x9207961a59afec0d), U64(0x9624a6b88b97a45c),
+		U64(0x363575380a192b1c), U64(0x2c60cd82b595a241),
+		U64(0x7d272664c1dc7932), U64(0x7142769faa94a1c1),
+		U64(0xa1d0df263b809d13), U64(0x1630e841d4c451ae),
+		U64(0xc1df65ad44fa13d8), U64(0x13d2d445bcf20bac),
+		U64(0xd915c546926abe23), U64(0x38cf3d92084dd749),
+		U64(0xe766d0272103059d), U64(0xc7634d5effde7f2f),
+		U64(0x077d2455012a7ea4), U64(0xedbfa82ff16fb199),
+		U64(0xaf2a978c39d46146), U64(0x42953fa3c8bbd0df),
+		U64(0xcb061da59496a7dc), U64(0x25e7a17db6eb20b0),
+		U64(0x34aa6d6963050fba), U64(0xa76cf7d580a4f1e4),
+		U64(0xf7ea10954ee338c4), U64(0xfcf2643b24819e93),
+		U64(0xcf252d0746aeef8d), U64(0x4ef06f58a3f3082c),
+		U64(0x563acfb37563a5d7), U64(0x5086e740ce47c920),
+		U64(0x2982f186dda3f843), U64(0x87696aac5e798b56),
+		U64(0x5d22bb1d1f010380), U64(0x035e14f7d31236f5),
+		U64(0x3cec0d30da759f18), U64(0xf3c920379cdb7095),
+		U64(0xb8db736b571e22bb), U64(0xdd36f5e44052f672),
+		U64(0xaac8ab8851e23b44), U64(0xa857b3d938fe1fe2),
+		U64(0x17f1e4e76eca43fd), U64(0xec7ea4894b61a3ca),
+		U64(0x9e62c6e132e734fe), U64(0xd4b1991b432c7483),
+		U64(0x6ad6c283af163acf), U64(0x1ce9904904a8e5aa),
+		U64(0x5fbda34c761d2726), U64(0xf910583f4cb7c491),
+		U64(0xc6a241f845d06d7c), U64(0x4f3163fe19fd1a7f),
+		U64(0xe99c988d2357f9c8), U64(0x8eee06535d0709a7),
+		U64(0x0efa48aa0254fc55), U64(0xb4be23903c56fa48),
+		U64(0x763f52caabbedf65), U64(0xeee1bcd8227d876c),
+		U64(0xe345e085f33b4dcc), U64(0x3e731561b369bbbe),
+		U64(0x2843fd2067adea10), U64(0x2adce5710eb1ceb6),
+		U64(0xb7e03767ef44ccbd), U64(0x8db012a48e153f52),
+		U64(0x61ceb62dc5749c98), U64(0xe85d942b9959eb9b),
+		U64(0x4c6f7709caef2c8a), U64(0x84377e5b8d6bbda3),
+		U64(0x30895dcbb13d47eb), U64(0x74a04a9bc2a2fbc3),
+		U64(0x6b17ce251518289c), U64(0xe438c4d0f2113368),
+		U64(0x1fb784bed7bad35f), U64(0x9b80fae55ad16efc),
+		U64(0x77fe5e6c11b0cd36), U64(0xc858095247849129),
+		U64(0x08466059b97090a2), U64(0x01c10ca6ba0e1253),
+		U64(0x6988d6747c040c3a), U64(0x6849dad2c60a1e69),
+		U64(0x5147ebe67449db73), U64(0xc99905f4fd8a837a),
+		U64(0x991fe2b433cd4a5a), U64(0xf09734c04fc94660),
+		U64(0xa28ecbd1e892abe6), U64(0xf1563866f5c75433),
+		U64(0x4dae7baf70e13ed9), U64(0x7ce62ac27bd26b61),
+		U64(0x70837a39109ab392), U64(0x90988e4b30b3c8ab),
+		U64(0xb2020b63877296bf), U64(0x156efcb607d6675b)
+	}, { /* 7 */
+		U64(0xe63f55ce97c331d0), U64(0x25b506b0015bba16),
+		U64(0xc8706e29e6ad9ba8), U64(0x5b43d3775d521f6a),
+		U64(0x0bfa3d577035106e), U64(0xab95fc172afb0e66),
+		U64(0xf64b63979e7a3276), U64(0xf58b4562649dad4b),
+		U64(0x48f7c3dbae0c83f1), U64(0xff31916642f5c8c5),
+		U64(0xcbb048dc1c4a0495), U64(0x66b8f83cdf622989),
+		U64(0x35c130e908e2b9b0), U64(0x7c761a61f0b34fa1),
+		U64(0x3601161cf205268d), U64(0x9e54ccfe2219b7d6),
+		U64(0x8b7d90a538940837), U64(0x9cd403588ea35d0b),
+		U64(0xbc3c6fea9ccc5b5a), U64(0xe5ff733b6d24aeed),
+		U64(0xceed22de0f7eb8d2), U64(0xec8581cab1ab545e),
+		U64(0xb96105e88ff8e71d), U64(0x8ca03501871a5ead),
+		U64(0x76ccce65d6db2a2f), U64(0x5883f582a7b58057),
+		U64(0x3f7be4ed2e8adc3e), U64(0x0fe7be06355cd9c9),
+		U64(0xee054e6c1d11be83), U64(0x1074365909b903a6),
+		U64(0x5dde9f80b4813c10), U64(0x4a770c7d02b6692c),
+		U64(0x5379c8d5d7809039), U64(0xb4067448161ed409),
+		U64(0x5f5e5026183bd6cd), U64(0xe898029bf4c29df9),
+		U64(0x7fb63c940a54d09c), U64(0xc5171f897f4ba8bc),
+		U64(0xa6f28db7b31d3d72), U64(0x2e4f3be7716eaa78),
+		U64(0x0d6771a099e63314), U64(0x82076254e41bf284),
+		U64(0x2f0fd2b42733df98), U64(0x5c9e76d3e2dc49f0),
+		U64(0x7aeb569619606cdb), U64(0x83478b07b2468764),
+		U64(0xcfadcb8d5923cd32), U64(0x85dac7f05b95a41e),
+		U64(0xb5469d1b4043a1e9), U64(0xb821ecbbd9a592fd),
+		U64(0x1b8e0b0e798c13c8), U64(0x62a57b6d9a0be02e),
+		U64(0xfcf1b793b81257f8), U64(0x9d94ea0bd8fe28eb),
+		U64(0x4cea408aeb654a56), U64(0x23284a47e888996c),
+		U64(0x2d8f1d128b893545), U64(0xf4cbac3132c0d8ab),
+		U64(0xbd7c86b9ca912eba), U64(0x3a268eef3dbe6079),
+		U64(0xf0d62f6077a9110c), U64(0x2735c916ade150cb),
+		U64(0x89fd5f03942ee2ea), U64(0x1acee25d2fd16628),
+		U64(0x90f39bab41181bff), U64(0x430dfe8cde39939f),
+		U64(0xf70b8ac4c8274796), U64(0x1c53aeaac6024552),
+		U64(0x13b410acf35e9c9b), U64(0xa532ab4249faa24f),
+		U64(0x2b1251e5625a163f), U64(0xd7e3e676da4841c7),
+		U64(0xa7b264e4e5404892), U64(0xda8497d643ae72d3),
+		U64(0x861ae105a1723b23), U64(0x38a6414991048aa4),
+		U64(0x6578dec92585b6b4), U64(0x0280cfa6acbaeadd),
+		U64(0x88bdb650c273970a), U64(0x9333bd5ebbff84c2),
+		U64(0x4e6a8f2c47dfa08b), U64(0x321c954db76cef2a),
+		U64(0x418d312a72837942), U64(0xb29b38bfffcdf773),
+		U64(0x6c022c38f90a4c07), U64(0x5a033a240b0f6a8a),
+		U64(0x1f93885f3ce5da6f), U64(0xc38a537e96988bc6),
+		U64(0x39e6a81ac759ff44), U64(0x29929e43cee0fce2),
+		U64(0x40cdd87924de0ca2), U64(0xe9d8ebc8a29fe819),
+		U64(0x0c2798f3cfbb46f4), U64(0x55e484223e53b343),
+		U64(0x4650948ecd0d2fd8), U64(0x20e86cb2126f0651),
+		U64(0x6d42c56baf5739e7), U64(0xa06fc1405ace1e08),
+		U64(0x7babbfc54f3d193b), U64(0x424d17df8864e67f),
+		U64(0xd8045870ef14980e), U64(0xc6d7397c85ac3781),
+		U64(0x21a885e1443273b1), U64(0x67f8116f893f5c69),
+		U64(0x24f5efe35706cff6), U64(0xd56329d076f2ab1a),
+		U64(0x5e1eb9754e66a32d), U64(0x28d2771098bd8902),
+		U64(0x8f6013f47dfdc190), U64(0x17a993fdb637553c),
+		U64(0xe0a219397e1012aa), U64(0x786b9930b5da8606),
+		U64(0x6e82e39e55b0a6da), U64(0x875a0856f72f4ec3),
+		U64(0x3741ff4fa458536d), U64(0xac4859b3957558fc),
+		U64(0x7ef6d5c75c09a57c), U64(0xc04a758b6c7f14fb),
+		U64(0xf9acdd91ab26ebbf), U64(0x7391a467c5ef9668),
+		U64(0x335c7c1ee1319aca), U64(0xa91533b18641e4bb),
+		U64(0xe4bf9a683b79db0d), U64(0x8e20faa72ba0b470),
+		U64(0x51f907737b3a7ae4), U64(0x2268a314bed5ec8c),
+		U64(0xd944b123b949edee), U64(0x31dcb3b84d8b7017),
+		U64(0xd3fe65279f218860), U64(0x097af2f1dc8ffab3),
+		U64(0x9b09a6fc312d0b91), U64(0xcc6ded78a3c4520f),
+		U64(0x3481d9ba5ebfcc50), U64(0x4f2a667f1182d56b),
+		U64(0xdfd9fdd4509ace94), U64(0x26752045fbbc252b),
+		U64(0xbffc491f662bc467), U64(0xdd593272fc202449),
+		U64(0x3cbbc218d46d4303), U64(0x91b372f817456e1f),
+		U64(0x681faf69bc6385a0), U64(0xb686bbeebaa43ed4),
+		U64(0x1469b5084cd0ca01), U64(0x98c98009cbca94ac),
+		U64(0x6438379a73d8c354), U64(0xc2caba2dc0c5fe26),
+		U64(0x3e3b0dbe78d7a9de), U64(0x50b9ee202d670f04),
+		U64(0x4590b27b37eab0e5), U64(0x6025b4cb36b10af3),
+		U64(0xfb2c1237079c0162), U64(0xa12f28130c936be8),
+		U64(0x4b37e52e54eb1ccc), U64(0x083a1ba28ad28f53),
+		U64(0xc10a9cd83a22611b), U64(0x9f1425ad7444c236),
+		U64(0x069d4cf7e9d3237a), U64(0xedc56899e7f621be),
+		U64(0x778c273680865fcf), U64(0x309c5aeb1bd605f7),
+		U64(0x8de0dc52d1472b4d), U64(0xf8ec34c2fd7b9e5f),
+		U64(0xea18cd3d58787724), U64(0xaad515447ca67b86),
+		U64(0x9989695a9d97e14c), U64(0x0000000000000000),
+		U64(0xf196c63321f464ec), U64(0x71116bc169557cb5),
+		U64(0xaf887f466f92c7c1), U64(0x972e3e0ffe964d65),
+		U64(0x190ec4a8d536f915), U64(0x95aef1a9522ca7b8),
+		U64(0xdc19db21aa7d51a9), U64(0x94ee18fa0471d258),
+		U64(0x8087adf248a11859), U64(0xc457f6da2916dd5c),
+		U64(0xfa6cfb6451c17482), U64(0xf256e0c6db13fbd1),
+		U64(0x6a9f60cf10d96f7d), U64(0x4daaa9d9bd383fb6),
+		U64(0x03c026f5fae79f3d), U64(0xde99148706c7bb74),
+		U64(0x2a52b8b6340763df), U64(0x6fc20acd03edd33a),
+		U64(0xd423c08320afdefa), U64(0xbbe1ca4e23420dc0),
+		U64(0x966ed75ca8cb3885), U64(0xeb58246e0e2502c4),
+		U64(0x055d6a021334bc47), U64(0xa47242111fa7d7af),
+		U64(0xe3623fcc84f78d97), U64(0x81c744a11efc6db9),
+		U64(0xaec8961539cfb221), U64(0xf31609958d4e8e31),
+		U64(0x63e5923ecc5695ce), U64(0x47107ddd9b505a38),
+		U64(0xa3afe7b5a0298135), U64(0x792b7063e387f3e6),
+		U64(0x0140e953565d75e0), U64(0x12f4f9ffa503e97b),
+		U64(0x750ce8902c3cb512), U64(0xdbc47e8515f30733),
+		U64(0x1ed3610c6ab8af8f), U64(0x5239218681dde5d9),
+		U64(0xe222d69fd2aaf877), U64(0xfe71783514a8bd25),
+		U64(0xcaf0a18f4a177175), U64(0x61655d9860ec7f13),
+		U64(0xe77fbc9dc19e4430), U64(0x2ccff441ddd440a5),
+		U64(0x16e97aaee06a20dc), U64(0xa855dae2d01c915b),
+		U64(0x1d1347f9905f30b2), U64(0xb7c652bdecf94b34),
+		U64(0xd03e43d265c6175d), U64(0xfdb15ec0ee4f2218),
+		U64(0x57644b8492e9599e), U64(0x07dda5a4bf8e569a),
+		U64(0x54a46d71680ec6a3), U64(0x5624a2d7c4b42c7e),
+		U64(0xbebca04c3076b187), U64(0x7d36f332a6ee3a41),
+		U64(0x3b6667bc6be31599), U64(0x695f463aea3ef040),
+		U64(0xad08b0e0c3282d1c), U64(0xb15b1e4a052a684e),
+		U64(0x44d05b2861b7c505), U64(0x15295c5b1a8dbfe1),
+		U64(0x744c01c37a61c0f2), U64(0x59c31cd1f1e8f5b7),
+		U64(0xef45a73f4b4ccb63), U64(0x6bdf899c46841a9d),
+		U64(0x3dfb2b4b823036e3), U64(0xa2ef0ee6f674f4d5),
+		U64(0x184e2dfb836b8cf5), U64(0x1134df0a5fe47646),
+		U64(0xbaa1231d751f7820), U64(0xd17eaa81339b62bd),
+		U64(0xb01bf71953771dae), U64(0x849a2ea30dc8d1fe),
+		U64(0x705182923f080955), U64(0x0ea757556301ac29),
+		U64(0x041d83514569c9a7), U64(0x0abad4042668658e),
+		U64(0x49b72a88f851f611), U64(0x8a3d79f66ec97dd7),
+		U64(0xcd2d042bf59927ef), U64(0xc930877ab0f0ee48),
+		U64(0x9273540deda2f122), U64(0xc797d02fd3f14261),
+		U64(0xe1e2f06a284d674a), U64(0xd2be8c74c97cfd80),
+		U64(0x9a494faf67707e71), U64(0xb3dbd1eca9908293),
+		U64(0x72d14d3493b2e388), U64(0xd6a30f258c153427)
+	},
+};
+
+static const STREEBOG_LONG64 C16[12][8] = {
+	{
+		U64(0xdd806559f2a64507), U64(0x05767436cc744d23),
+		U64(0xa2422a08a460d315), U64(0x4b7ce09192676901),
+		U64(0x714eb88d7585c4fc), U64(0x2f6a76432e45d016),
+		U64(0xebcb2f81c0657c1f), U64(0xb1085bda1ecadae9)
+	}, {
+		U64(0xe679047021b19bb7), U64(0x55dda21bd7cbcd56),
+		U64(0x5cb561c2db0aa7ca), U64(0x9ab5176b12d69958),
+		U64(0x61d55e0f16b50131), U64(0xf3feea720a232b98),
+		U64(0x4fe39d460f70b5d7), U64(0x6fa3b58aa99d2f1a)
+	}, {
+		U64(0x991e96f50aba0ab2), U64(0xc2b6f443867adb31),
+		U64(0xc1c93a376062db09), U64(0xd3e20fe490359eb1),
+		U64(0xf2ea7514b1297b7b), U64(0x06f15e5f529c1f8b),
+		U64(0x0a39fc286a3d8435), U64(0xf574dcac2bce2fc7)
+	}, {
+		U64(0x220cbebc84e3d12e), U64(0x3453eaa193e837f1),
+		U64(0xd8b71333935203be), U64(0xa9d72c82ed03d675),
+		U64(0x9d721cad685e353f), U64(0x488e857e335c3c7d),
+		U64(0xf948e1a05d71e4dd), U64(0xef1fdfb3e81566d2)
+	}, {
+		U64(0x601758fd7c6cfe57), U64(0x7a56a27ea9ea63f5),
+		U64(0xdfff00b723271a16), U64(0xbfcd1747253af5a3),
+		U64(0x359e35d7800fffbd), U64(0x7f151c1f1686104a),
+		U64(0x9a3f410c6ca92363), U64(0x4bea6bacad474799)
+	}, {
+		U64(0xfa68407a46647d6e), U64(0xbf71c57236904f35),
+		U64(0x0af21f66c2bec6b6), U64(0xcffaa6b71c9ab7b4),
+		U64(0x187f9ab49af08ec6), U64(0x2d66c4f95142a46c),
+		U64(0x6fa4c33b7a3039c0), U64(0xae4faeae1d3ad3d9)
+	}, {
+		U64(0x8886564d3a14d493), U64(0x3517454ca23c4af3),
+		U64(0x06476983284a0504), U64(0x0992abc52d822c37),
+		U64(0xd3473e33197a93c9), U64(0x399ec6c7e6bf87c9),
+		U64(0x51ac86febf240954), U64(0xf4c70e16eeaac5ec)
+	}, {
+		U64(0xa47f0dd4bf02e71e), U64(0x36acc2355951a8d9),
+		U64(0x69d18d2bd1a5c42f), U64(0xf4892bcb929b0690),
+		U64(0x89b4443b4ddbc49a), U64(0x4eb7f8719c36de1e),
+		U64(0x03e7aa020c6e4141), U64(0x9b1f5b424d93c9a7)
+	}, {
+		U64(0x7261445183235adb), U64(0x0e38dc92cb1f2a60),
+		U64(0x7b2b8a9aa6079c54), U64(0x800a440bdbb2ceb1),
+		U64(0x3cd955b7e00d0984), U64(0x3a7d3a1b25894224),
+		U64(0x944c9ad8ec165fde), U64(0x378f5a541631229b)
+	}, {
+		U64(0x74b4c7fb98459ced), U64(0x3698fad1153bb6c3),
+		U64(0x7a1e6c303b7652f4), U64(0x9fe76702af69334b),
+		U64(0x1fffe18a1b336103), U64(0x8941e71cff8a78db),
+		U64(0x382ae548b2e4f3f3), U64(0xabbedea680056f52)
+	}, {
+		U64(0x6bcaa4cd81f32d1b), U64(0xdea2594ac06fd85d),
+		U64(0xefbacd1d7d476e98), U64(0x8a1d71efea48b9ca),
+		U64(0x2001802114846679), U64(0xd8fa6bbbebab0761),
+		U64(0x3002c6cd635afe94), U64(0x7bcd9ed0efc889fb)
+	}, {
+		U64(0x48bc924af11bd720), U64(0xfaf417d5d9b21b99),
+		U64(0xe71da4aa88e12852), U64(0x5d80ef9d1891cc86),
+		U64(0xf82012d430219f9b), U64(0xcda43c32bcdf1d77),
+		U64(0xd21380b00449b17a), U64(0x378ee767f11631ba)
+	},
+};
+
+#define B(x,i,j)	(((STREEBOG_LONG64)(*(((const unsigned char *)(&x))+i)))<<(j*8))
+#define PULL64(x) (B(x,0,0)|B(x,1,1)|B(x,2,2)|B(x,3,3)|B(x,4,4)|B(x,5,5)|B(x,6,6)|B(x,7,7))
+#define SWAB64(x) (B(x,0,7)|B(x,1,6)|B(x,2,5)|B(x,3,4)|B(x,4,3)|B(x,5,2)|B(x,6,1)|B(x,7,0))
+
+static inline STREEBOG_LONG64
+multipermute(const STREEBOG_LONG64 *in, int i)
+{
+	STREEBOG_LONG64 t = 0;
+
+	t ^= A_PI_table[0][(in[0] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[1][(in[1] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[2][(in[2] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[3][(in[3] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[4][(in[4] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[5][(in[5] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[6][(in[6] >> (i * 8)) & 0xff];
+	t ^= A_PI_table[7][(in[7] >> (i * 8)) & 0xff];
+
+	return t;
+}
+
+static void
+transform(STREEBOG_LONG64 *out, const STREEBOG_LONG64 *a,
+    const STREEBOG_LONG64 *b)
+{
+	STREEBOG_LONG64 tmp[8];
+
+	tmp[0] = a[0] ^ b[0];
+	tmp[1] = a[1] ^ b[1];
+	tmp[2] = a[2] ^ b[2];
+	tmp[3] = a[3] ^ b[3];
+	tmp[4] = a[4] ^ b[4];
+	tmp[5] = a[5] ^ b[5];
+	tmp[6] = a[6] ^ b[6];
+	tmp[7] = a[7] ^ b[7];
+
+	out[0] = multipermute(tmp, 0);
+	out[1] = multipermute(tmp, 1);
+	out[2] = multipermute(tmp, 2);
+	out[3] = multipermute(tmp, 3);
+	out[4] = multipermute(tmp, 4);
+	out[5] = multipermute(tmp, 5);
+	out[6] = multipermute(tmp, 6);
+	out[7] = multipermute(tmp, 7);
+}
+
+static inline void
+gN(STREEBOG_LONG64 *h, STREEBOG_LONG64 *m, STREEBOG_LONG64 *N)
+{
+	STREEBOG_LONG64 K[8];
+	STREEBOG_LONG64 T[8];
+	int i;
+
+	transform(K, h, N);
+
+	transform(T, K, m);
+	transform(K, K, C16[0]);
+	for (i = 1; i < 12; i++) {
+		transform(T, K, T);
+		transform(K, K, C16[i]);
+	}
+
+	h[0] ^= T[0] ^ K[0] ^ m[0];
+	h[1] ^= T[1] ^ K[1] ^ m[1];
+	h[2] ^= T[2] ^ K[2] ^ m[2];
+	h[3] ^= T[3] ^ K[3] ^ m[3];
+	h[4] ^= T[4] ^ K[4] ^ m[4];
+	h[5] ^= T[5] ^ K[5] ^ m[5];
+	h[6] ^= T[6] ^ K[6] ^ m[6];
+	h[7] ^= T[7] ^ K[7] ^ m[7];
+}
+
+
+static void
+streebog_single_block(STREEBOG_CTX *ctx, const unsigned char *in, size_t num)
+{
+	STREEBOG_LONG64 M[8], l;
+	STREEBOG_LONG64 CF;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		M[i] = PULL64(in[i*8]);
+
+	gN(ctx->h, M, ctx->N);
+
+	l = ctx->N[0];
+	ctx->N[0] += num;
+
+	if (ctx->N[0] < l || ctx->N[0] < num) {
+		for (i = 1; i < 8; i++) {
+			ctx->N[i]++;
+			if (ctx->N[i] != 0)
+				break;
+		}
+	}
+
+	CF = 0;
+	ctx->Sigma[0] += M[0];
+	for (i = 1; i < 8; i++) {
+		if (ctx->Sigma[i-1] != M[i-1])
+			CF = (ctx->Sigma[i-1] < M[i-1]);
+		ctx->Sigma[i] += M[i] + CF;
+	}
+}
+
+
+
+static void
+streebog_block_data_order(STREEBOG_CTX *ctx, const unsigned char *in,
+    size_t num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		streebog_single_block(ctx, in + i * STREEBOG_CBLOCK, 64 * 8);
+}
+
+int
+STREEBOG512_Final(unsigned char *md, STREEBOG_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	STREEBOG_LONG64 Z[STREEBOG_LBLOCK] = {0};
+	int n;
+
+	if (c->num == STREEBOG_CBLOCK) {
+		streebog_block_data_order(c, p, 1);
+		c->num -= STREEBOG_CBLOCK;
+	}
+
+	n = c->num;
+	p[n++] = 1;
+	memset(p + n, 0, STREEBOG_CBLOCK - n);
+
+	streebog_single_block(c, p, c->num * 8);
+
+	gN(c->h, c->N, Z);
+	gN(c->h, c->Sigma, Z);
+
+	for (n = 0; n < STREEBOG_LBLOCK; n++)
+		c->h[n] = SWAB64(c->h[n]);
+
+	if (md == NULL)
+		return 0;
+
+	switch (c->md_len) {
+		/* Let compiler decide if it's appropriate to unroll... */
+	case STREEBOG256_LENGTH:
+		for (n = 0; n < STREEBOG256_LENGTH / 8; n++) {
+			STREEBOG_LONG64 t = c->h[4+n];
+
+#if BYTE_ORDER == BIG_ENDIAN
+			*(md++) = (unsigned char)(t);
+			*(md++) = (unsigned char)(t >> 8);
+			*(md++) = (unsigned char)(t >> 16);
+			*(md++) = (unsigned char)(t >> 24);
+			*(md++) = (unsigned char)(t >> 32);
+			*(md++) = (unsigned char)(t >> 40);
+			*(md++) = (unsigned char)(t >> 48);
+			*(md++) = (unsigned char)(t >> 56);
+#else
+			*(md++) = (unsigned char)(t >> 56);
+			*(md++) = (unsigned char)(t >> 48);
+			*(md++) = (unsigned char)(t >> 40);
+			*(md++) = (unsigned char)(t >> 32);
+			*(md++) = (unsigned char)(t >> 24);
+			*(md++) = (unsigned char)(t >> 16);
+			*(md++) = (unsigned char)(t >> 8);
+			*(md++) = (unsigned char)(t);
+#endif
+		}
+		break;
+	case STREEBOG512_LENGTH:
+		for (n = 0; n < STREEBOG512_LENGTH / 8; n++) {
+			STREEBOG_LONG64 t = c->h[n];
+
+#if BYTE_ORDER == BIG_ENDIAN
+			*(md++) = (unsigned char)(t);
+			*(md++) = (unsigned char)(t >> 8);
+			*(md++) = (unsigned char)(t >> 16);
+			*(md++) = (unsigned char)(t >> 24);
+			*(md++) = (unsigned char)(t >> 32);
+			*(md++) = (unsigned char)(t >> 40);
+			*(md++) = (unsigned char)(t >> 48);
+			*(md++) = (unsigned char)(t >> 56);
+#else
+			*(md++) = (unsigned char)(t >> 56);
+			*(md++) = (unsigned char)(t >> 48);
+			*(md++) = (unsigned char)(t >> 40);
+			*(md++) = (unsigned char)(t >> 32);
+			*(md++) = (unsigned char)(t >> 24);
+			*(md++) = (unsigned char)(t >> 16);
+			*(md++) = (unsigned char)(t >> 8);
+			*(md++) = (unsigned char)(t);
+#endif
+		}
+		break;
+		/* ... as well as make sure md_len is not abused. */
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(STREEBOG512_Final);
+
+int
+STREEBOG256_Final(unsigned char *md, STREEBOG_CTX * c)
+{
+	return STREEBOG512_Final(md, c);
+}
+LCRYPTO_ALIAS(STREEBOG256_Final);
+
+int
+STREEBOG512_Update(STREEBOG_CTX *c, const void *_data, size_t len)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	const unsigned char *data = (const unsigned char *)_data;
+
+	if (len == 0)
+		return 1;
+
+	if (c->num != 0) {
+		size_t n = STREEBOG_CBLOCK - c->num;
+
+		if (len < n) {
+			memcpy(p + c->num, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		} else {
+			memcpy(p + c->num, data, n);
+			c->num = 0;
+			len -= n;
+			data += n;
+			streebog_block_data_order(c, p, 1);
+		}
+	}
+
+	if (len >= STREEBOG_CBLOCK) {
+		streebog_block_data_order(c, data, len / STREEBOG_CBLOCK);
+		data += len;
+		len %= STREEBOG_CBLOCK;
+		data -= len;
+	}
+
+	if (len != 0) {
+		memcpy(p, data, len);
+		c->num = (int)len;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(STREEBOG512_Update);
+
+int
+STREEBOG256_Update(STREEBOG_CTX *c, const void *data, size_t len)
+{
+	return STREEBOG512_Update(c, data, len);
+}
+LCRYPTO_ALIAS(STREEBOG256_Update);
+
+void
+STREEBOG512_Transform(STREEBOG_CTX *c, const unsigned char *data)
+{
+	streebog_block_data_order(c, data, 1);
+}
+LCRYPTO_ALIAS(STREEBOG512_Transform);
+
+int
+STREEBOG256_Init(STREEBOG_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+	memset(c->h, 1, sizeof(c->h));
+
+	c->md_len = STREEBOG256_LENGTH;
+	return 1;
+}
+LCRYPTO_ALIAS(STREEBOG256_Init);
+
+int
+STREEBOG512_Init(STREEBOG_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+	memset(c->h, 0, sizeof(c->h));
+
+	c->num = 0;
+	c->md_len = STREEBOG512_LENGTH;
+	return 1;
+}
+LCRYPTO_ALIAS(STREEBOG512_Init);
+
+unsigned char *
+STREEBOG256(const unsigned char *d, size_t n, unsigned char *md)
+{
+	STREEBOG_CTX c;
+	static unsigned char m[STREEBOG256_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	STREEBOG256_Init(&c);
+	STREEBOG256_Update(&c, d, n);
+	STREEBOG256_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(STREEBOG256);
+
+unsigned char *
+STREEBOG512(const unsigned char *d, size_t n, unsigned char *md)
+{
+	STREEBOG_CTX c;
+	static unsigned char m[STREEBOG512_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	STREEBOG512_Init(&c);
+	STREEBOG512_Update(&c, d, n);
+	STREEBOG512_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(STREEBOG512);
+
+#endif
diff --git a/crypto/hidden/crypto_namespace.h b/crypto/hidden/crypto_namespace.h
new file mode 100644
index 0000000..85e62ba
--- /dev/null
+++ b/crypto/hidden/crypto_namespace.h
@@ -0,0 +1,51 @@
+/*	$OpenBSD: crypto_namespace.h,v 1.2 2023/02/16 08:38:17 tb Exp $	*/
+/*
+ * Copyright (c) 2016 Philip Guenther 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CRYPTO_NAMESPACE_H_
+#define _LIBCRYPTO_CRYPTO_NAMESPACE_H_
+
+/*
+ * If marked as 'used', then internal calls use the name with prefix "_lcry_"
+ * and we alias that to the normal name *and* the name with prefix "_libre_";
+ * external calls use the latter name.
+ */
+
+#ifdef _MSC_VER
+# define LCRYPTO_UNUSED(x)
+# define LCRYPTO_USED(x)
+# define LCRYPTO_ALIAS1(pre, x)
+# define LCRYPTO_ALIAS(x)
+#else
+#ifdef LIBRESSL_NAMESPACE
+# define LCRYPTO_UNUSED(x)		typeof(x) x __attribute__((deprecated))
+#ifdef LIBRESSL_CRYPTO_NAMESPACE
+#  define LCRYPTO_USED(x)		__attribute__((visibility("hidden")))	\
+				typeof(x) x asm("_lcry_"#x)
+#  define LCRYPTO_ALIAS1(pre,x)	asm(".global "#pre#x"; "#pre#x" = _lcry_"#x)
+#  define LCRYPTO_ALIAS(x)	LCRYPTO_ALIAS1(,x); LCRYPTO_ALIAS1(_libre_,x)
+#else
+#  define LCRYPTO_USED(x)          typeof(x) x asm("_libre_"#x)
+#endif
+#else
+# define LCRYPTO_UNUSED(x)
+# define LCRYPTO_USED(x)
+# define LCRYPTO_ALIAS1(pre,x)
+# define LCRYPTO_ALIAS(x)	asm("")
+#endif
+#endif /* _MSC_VER */
+
+#endif	/* _LIBCRYPTO_CRYPTO_NAMESPACE_H_ */
diff --git a/crypto/hidden/openssl/asn1.h b/crypto/hidden/openssl/asn1.h
new file mode 100644
index 0000000..fb1393f
--- /dev/null
+++ b/crypto/hidden/openssl/asn1.h
@@ -0,0 +1,253 @@
+/* $OpenBSD: asn1.h,v 1.6 2023/07/28 10:33:13 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_ASN1_H
+#define _LIBCRYPTO_ASN1_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/asn1.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(d2i_ASN1_SEQUENCE_ANY);
+LCRYPTO_USED(i2d_ASN1_SEQUENCE_ANY);
+LCRYPTO_USED(d2i_ASN1_SET_ANY);
+LCRYPTO_USED(i2d_ASN1_SET_ANY);
+LCRYPTO_USED(ASN1_TYPE_new);
+LCRYPTO_USED(ASN1_TYPE_free);
+LCRYPTO_USED(d2i_ASN1_TYPE);
+LCRYPTO_USED(i2d_ASN1_TYPE);
+LCRYPTO_USED(ASN1_TYPE_get);
+LCRYPTO_USED(ASN1_TYPE_set);
+LCRYPTO_USED(ASN1_TYPE_set1);
+LCRYPTO_USED(ASN1_TYPE_cmp);
+LCRYPTO_USED(ASN1_OBJECT_new);
+LCRYPTO_USED(ASN1_OBJECT_free);
+LCRYPTO_USED(i2d_ASN1_OBJECT);
+LCRYPTO_USED(d2i_ASN1_OBJECT);
+LCRYPTO_USED(ASN1_STRING_new);
+LCRYPTO_USED(ASN1_STRING_free);
+LCRYPTO_USED(ASN1_STRING_copy);
+LCRYPTO_USED(ASN1_STRING_dup);
+LCRYPTO_USED(ASN1_STRING_type_new);
+LCRYPTO_USED(ASN1_STRING_cmp);
+LCRYPTO_USED(ASN1_STRING_set);
+LCRYPTO_USED(ASN1_STRING_set0);
+LCRYPTO_USED(ASN1_STRING_length);
+LCRYPTO_USED(ASN1_STRING_length_set);
+LCRYPTO_USED(ASN1_STRING_type);
+LCRYPTO_USED(ASN1_STRING_data);
+LCRYPTO_USED(ASN1_STRING_get0_data);
+LCRYPTO_USED(ASN1_BIT_STRING_new);
+LCRYPTO_USED(ASN1_BIT_STRING_free);
+LCRYPTO_USED(d2i_ASN1_BIT_STRING);
+LCRYPTO_USED(i2d_ASN1_BIT_STRING);
+LCRYPTO_USED(ASN1_BIT_STRING_set);
+LCRYPTO_USED(ASN1_BIT_STRING_set_bit);
+LCRYPTO_USED(ASN1_BIT_STRING_get_bit);
+LCRYPTO_USED(ASN1_INTEGER_new);
+LCRYPTO_USED(ASN1_INTEGER_free);
+LCRYPTO_USED(d2i_ASN1_INTEGER);
+LCRYPTO_USED(i2d_ASN1_INTEGER);
+LCRYPTO_USED(d2i_ASN1_UINTEGER);
+LCRYPTO_USED(ASN1_INTEGER_dup);
+LCRYPTO_USED(ASN1_INTEGER_cmp);
+LCRYPTO_USED(ASN1_ENUMERATED_new);
+LCRYPTO_USED(ASN1_ENUMERATED_free);
+LCRYPTO_USED(d2i_ASN1_ENUMERATED);
+LCRYPTO_USED(i2d_ASN1_ENUMERATED);
+LCRYPTO_USED(ASN1_UTCTIME_check);
+LCRYPTO_USED(ASN1_UTCTIME_set);
+LCRYPTO_USED(ASN1_UTCTIME_adj);
+LCRYPTO_USED(ASN1_UTCTIME_set_string);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_check);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_set);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_adj);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_set_string);
+LCRYPTO_USED(ASN1_OCTET_STRING_new);
+LCRYPTO_USED(ASN1_OCTET_STRING_free);
+LCRYPTO_USED(d2i_ASN1_OCTET_STRING);
+LCRYPTO_USED(i2d_ASN1_OCTET_STRING);
+LCRYPTO_USED(ASN1_OCTET_STRING_dup);
+LCRYPTO_USED(ASN1_OCTET_STRING_cmp);
+LCRYPTO_USED(ASN1_OCTET_STRING_set);
+LCRYPTO_USED(ASN1_VISIBLESTRING_new);
+LCRYPTO_USED(ASN1_VISIBLESTRING_free);
+LCRYPTO_USED(d2i_ASN1_VISIBLESTRING);
+LCRYPTO_USED(i2d_ASN1_VISIBLESTRING);
+LCRYPTO_USED(ASN1_UNIVERSALSTRING_new);
+LCRYPTO_USED(ASN1_UNIVERSALSTRING_free);
+LCRYPTO_USED(d2i_ASN1_UNIVERSALSTRING);
+LCRYPTO_USED(i2d_ASN1_UNIVERSALSTRING);
+LCRYPTO_USED(ASN1_UTF8STRING_new);
+LCRYPTO_USED(ASN1_UTF8STRING_free);
+LCRYPTO_USED(d2i_ASN1_UTF8STRING);
+LCRYPTO_USED(i2d_ASN1_UTF8STRING);
+LCRYPTO_USED(ASN1_NULL_new);
+LCRYPTO_USED(ASN1_NULL_free);
+LCRYPTO_USED(d2i_ASN1_NULL);
+LCRYPTO_USED(i2d_ASN1_NULL);
+LCRYPTO_USED(ASN1_BMPSTRING_new);
+LCRYPTO_USED(ASN1_BMPSTRING_free);
+LCRYPTO_USED(d2i_ASN1_BMPSTRING);
+LCRYPTO_USED(i2d_ASN1_BMPSTRING);
+LCRYPTO_USED(ASN1_PRINTABLE_new);
+LCRYPTO_USED(ASN1_PRINTABLE_free);
+LCRYPTO_USED(d2i_ASN1_PRINTABLE);
+LCRYPTO_USED(i2d_ASN1_PRINTABLE);
+LCRYPTO_USED(DIRECTORYSTRING_new);
+LCRYPTO_USED(DIRECTORYSTRING_free);
+LCRYPTO_USED(d2i_DIRECTORYSTRING);
+LCRYPTO_USED(i2d_DIRECTORYSTRING);
+LCRYPTO_USED(DISPLAYTEXT_new);
+LCRYPTO_USED(DISPLAYTEXT_free);
+LCRYPTO_USED(d2i_DISPLAYTEXT);
+LCRYPTO_USED(i2d_DISPLAYTEXT);
+LCRYPTO_USED(ASN1_PRINTABLESTRING_new);
+LCRYPTO_USED(ASN1_PRINTABLESTRING_free);
+LCRYPTO_USED(d2i_ASN1_PRINTABLESTRING);
+LCRYPTO_USED(i2d_ASN1_PRINTABLESTRING);
+LCRYPTO_USED(ASN1_T61STRING_new);
+LCRYPTO_USED(ASN1_T61STRING_free);
+LCRYPTO_USED(d2i_ASN1_T61STRING);
+LCRYPTO_USED(i2d_ASN1_T61STRING);
+LCRYPTO_USED(ASN1_IA5STRING_new);
+LCRYPTO_USED(ASN1_IA5STRING_free);
+LCRYPTO_USED(d2i_ASN1_IA5STRING);
+LCRYPTO_USED(i2d_ASN1_IA5STRING);
+LCRYPTO_USED(ASN1_GENERALSTRING_new);
+LCRYPTO_USED(ASN1_GENERALSTRING_free);
+LCRYPTO_USED(d2i_ASN1_GENERALSTRING);
+LCRYPTO_USED(i2d_ASN1_GENERALSTRING);
+LCRYPTO_USED(ASN1_UTCTIME_new);
+LCRYPTO_USED(ASN1_UTCTIME_free);
+LCRYPTO_USED(d2i_ASN1_UTCTIME);
+LCRYPTO_USED(i2d_ASN1_UTCTIME);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_new);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_free);
+LCRYPTO_USED(d2i_ASN1_GENERALIZEDTIME);
+LCRYPTO_USED(i2d_ASN1_GENERALIZEDTIME);
+LCRYPTO_USED(ASN1_TIME_new);
+LCRYPTO_USED(ASN1_TIME_free);
+LCRYPTO_USED(d2i_ASN1_TIME);
+LCRYPTO_USED(i2d_ASN1_TIME);
+LCRYPTO_USED(ASN1_TIME_to_tm);
+LCRYPTO_USED(ASN1_TIME_compare);
+LCRYPTO_USED(ASN1_TIME_cmp_time_t);
+LCRYPTO_USED(ASN1_TIME_normalize);
+LCRYPTO_USED(ASN1_TIME_set_string_X509);
+LCRYPTO_USED(ASN1_TIME_diff);
+LCRYPTO_USED(ASN1_TIME_set);
+LCRYPTO_USED(ASN1_TIME_set_tm);
+LCRYPTO_USED(ASN1_TIME_adj);
+LCRYPTO_USED(ASN1_TIME_check);
+LCRYPTO_USED(ASN1_TIME_to_generalizedtime);
+LCRYPTO_USED(ASN1_TIME_set_string);
+LCRYPTO_USED(i2a_ASN1_INTEGER);
+LCRYPTO_USED(a2i_ASN1_INTEGER);
+LCRYPTO_USED(i2a_ASN1_ENUMERATED);
+LCRYPTO_USED(a2i_ASN1_ENUMERATED);
+LCRYPTO_USED(i2a_ASN1_OBJECT);
+LCRYPTO_USED(a2i_ASN1_STRING);
+LCRYPTO_USED(i2a_ASN1_STRING);
+LCRYPTO_USED(i2t_ASN1_OBJECT);
+LCRYPTO_USED(a2d_ASN1_OBJECT);
+LCRYPTO_USED(ASN1_OBJECT_create);
+LCRYPTO_USED(ASN1_INTEGER_get_uint64);
+LCRYPTO_USED(ASN1_INTEGER_set_uint64);
+LCRYPTO_USED(ASN1_INTEGER_get_int64);
+LCRYPTO_USED(ASN1_INTEGER_set_int64);
+LCRYPTO_USED(ASN1_INTEGER_set);
+LCRYPTO_USED(ASN1_INTEGER_get);
+LCRYPTO_USED(BN_to_ASN1_INTEGER);
+LCRYPTO_USED(ASN1_INTEGER_to_BN);
+LCRYPTO_USED(ASN1_ENUMERATED_get_int64);
+LCRYPTO_USED(ASN1_ENUMERATED_set_int64);
+LCRYPTO_USED(ASN1_ENUMERATED_set);
+LCRYPTO_USED(ASN1_ENUMERATED_get);
+LCRYPTO_USED(BN_to_ASN1_ENUMERATED);
+LCRYPTO_USED(ASN1_ENUMERATED_to_BN);
+LCRYPTO_USED(ASN1_PRINTABLE_type);
+LCRYPTO_USED(ASN1_get_object);
+LCRYPTO_USED(ASN1_put_object);
+LCRYPTO_USED(ASN1_put_eoc);
+LCRYPTO_USED(ASN1_object_size);
+LCRYPTO_USED(ASN1_item_dup);
+LCRYPTO_USED(ASN1_d2i_fp);
+LCRYPTO_USED(ASN1_item_d2i_fp);
+LCRYPTO_USED(ASN1_i2d_fp);
+LCRYPTO_USED(ASN1_item_i2d_fp);
+LCRYPTO_USED(ASN1_STRING_print_ex_fp);
+LCRYPTO_USED(ASN1_STRING_to_UTF8);
+LCRYPTO_USED(ASN1_d2i_bio);
+LCRYPTO_USED(ASN1_item_d2i_bio);
+LCRYPTO_USED(ASN1_i2d_bio);
+LCRYPTO_USED(ASN1_item_i2d_bio);
+LCRYPTO_USED(ASN1_UTCTIME_print);
+LCRYPTO_USED(ASN1_GENERALIZEDTIME_print);
+LCRYPTO_USED(ASN1_TIME_print);
+LCRYPTO_USED(ASN1_STRING_print);
+LCRYPTO_USED(ASN1_STRING_print_ex);
+LCRYPTO_USED(ASN1_parse);
+LCRYPTO_USED(ASN1_parse_dump);
+LCRYPTO_USED(ASN1_tag2bit);
+LCRYPTO_USED(ASN1_tag2str);
+LCRYPTO_USED(ASN1_UNIVERSALSTRING_to_string);
+LCRYPTO_USED(ASN1_TYPE_set_octetstring);
+LCRYPTO_USED(ASN1_TYPE_get_octetstring);
+LCRYPTO_USED(ASN1_TYPE_set_int_octetstring);
+LCRYPTO_USED(ASN1_TYPE_get_int_octetstring);
+LCRYPTO_USED(ASN1_item_pack);
+LCRYPTO_USED(ASN1_item_unpack);
+LCRYPTO_USED(ASN1_STRING_set_default_mask);
+LCRYPTO_USED(ASN1_STRING_set_default_mask_asc);
+LCRYPTO_USED(ASN1_STRING_get_default_mask);
+LCRYPTO_USED(ASN1_mbstring_copy);
+LCRYPTO_USED(ASN1_mbstring_ncopy);
+LCRYPTO_USED(ASN1_STRING_set_by_NID);
+LCRYPTO_USED(ASN1_STRING_TABLE_get);
+LCRYPTO_USED(ASN1_STRING_TABLE_add);
+LCRYPTO_USED(ASN1_STRING_TABLE_cleanup);
+LCRYPTO_USED(ASN1_item_new);
+LCRYPTO_USED(ASN1_item_free);
+LCRYPTO_USED(ASN1_item_d2i);
+LCRYPTO_USED(ASN1_item_i2d);
+LCRYPTO_USED(ASN1_add_oid_module);
+LCRYPTO_USED(ASN1_generate_nconf);
+LCRYPTO_USED(ASN1_generate_v3);
+LCRYPTO_USED(ASN1_item_print);
+LCRYPTO_USED(ASN1_PCTX_new);
+LCRYPTO_USED(ASN1_PCTX_free);
+LCRYPTO_USED(ASN1_PCTX_get_flags);
+LCRYPTO_USED(ASN1_PCTX_set_flags);
+LCRYPTO_USED(ASN1_PCTX_get_nm_flags);
+LCRYPTO_USED(ASN1_PCTX_set_nm_flags);
+LCRYPTO_USED(ASN1_PCTX_get_cert_flags);
+LCRYPTO_USED(ASN1_PCTX_set_cert_flags);
+LCRYPTO_USED(ASN1_PCTX_get_oid_flags);
+LCRYPTO_USED(ASN1_PCTX_set_oid_flags);
+LCRYPTO_USED(ASN1_PCTX_get_str_flags);
+LCRYPTO_USED(ASN1_PCTX_set_str_flags);
+LCRYPTO_USED(SMIME_crlf_copy);
+LCRYPTO_USED(SMIME_text);
+LCRYPTO_USED(ERR_load_ASN1_strings);
+LCRYPTO_USED(ASN1_time_parse);
+LCRYPTO_USED(ASN1_time_tm_cmp);
+
+#endif /* _LIBCRYPTO_ASN1_H */
diff --git a/crypto/hidden/openssl/asn1t.h b/crypto/hidden/openssl/asn1t.h
new file mode 100644
index 0000000..666dea5
--- /dev/null
+++ b/crypto/hidden/openssl/asn1t.h
@@ -0,0 +1,33 @@
+/* $OpenBSD: asn1t.h,v 1.3 2023/07/28 10:00:10 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_ASN1T_H
+#define _LIBCRYPTO_ASN1T_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/asn1t.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(ASN1_item_ex_new);
+LCRYPTO_USED(ASN1_item_ex_free);
+LCRYPTO_USED(ASN1_item_ex_d2i);
+LCRYPTO_USED(ASN1_item_ex_i2d);
+
+#endif /* _LIBCRYPTO_ASN1T_H */
diff --git a/crypto/hidden/openssl/bio.h b/crypto/hidden/openssl/bio.h
new file mode 100644
index 0000000..f7e7cd3
--- /dev/null
+++ b/crypto/hidden/openssl/bio.h
@@ -0,0 +1,146 @@
+/* $OpenBSD: bio.h,v 1.4 2023/07/28 10:13:50 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_BIO_H
+#define _LIBCRYPTO_BIO_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/bio.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(BIO_set_flags);
+LCRYPTO_USED(BIO_test_flags);
+LCRYPTO_USED(BIO_clear_flags);
+LCRYPTO_USED(BIO_get_callback);
+LCRYPTO_USED(BIO_set_callback);
+LCRYPTO_USED(BIO_get_callback_ex);
+LCRYPTO_USED(BIO_set_callback_ex);
+LCRYPTO_USED(BIO_get_callback_arg);
+LCRYPTO_USED(BIO_set_callback_arg);
+LCRYPTO_USED(BIO_method_name);
+LCRYPTO_USED(BIO_method_type);
+LCRYPTO_USED(BIO_meth_new);
+LCRYPTO_USED(BIO_meth_free);
+LCRYPTO_USED(BIO_meth_get_write);
+LCRYPTO_USED(BIO_meth_set_write);
+LCRYPTO_USED(BIO_meth_get_read);
+LCRYPTO_USED(BIO_meth_set_read);
+LCRYPTO_USED(BIO_meth_get_puts);
+LCRYPTO_USED(BIO_meth_set_puts);
+LCRYPTO_USED(BIO_meth_get_gets);
+LCRYPTO_USED(BIO_meth_set_gets);
+LCRYPTO_USED(BIO_meth_get_ctrl);
+LCRYPTO_USED(BIO_meth_set_ctrl);
+LCRYPTO_USED(BIO_meth_get_create);
+LCRYPTO_USED(BIO_meth_set_create);
+LCRYPTO_USED(BIO_meth_get_destroy);
+LCRYPTO_USED(BIO_meth_set_destroy);
+LCRYPTO_USED(BIO_meth_get_callback_ctrl);
+LCRYPTO_USED(BIO_meth_set_callback_ctrl);
+LCRYPTO_USED(BIO_ctrl_pending);
+LCRYPTO_USED(BIO_ctrl_wpending);
+LCRYPTO_USED(BIO_ctrl_get_write_guarantee);
+LCRYPTO_USED(BIO_ctrl_get_read_request);
+LCRYPTO_USED(BIO_ctrl_reset_read_request);
+LCRYPTO_USED(BIO_set_ex_data);
+LCRYPTO_USED(BIO_get_ex_data);
+LCRYPTO_USED(BIO_number_read);
+LCRYPTO_USED(BIO_number_written);
+LCRYPTO_USED(BIO_get_new_index);
+LCRYPTO_USED(BIO_s_file);
+LCRYPTO_USED(BIO_new_file);
+LCRYPTO_USED(BIO_new_fp);
+LCRYPTO_USED(BIO_new);
+LCRYPTO_USED(BIO_set);
+LCRYPTO_USED(BIO_free);
+LCRYPTO_USED(BIO_up_ref);
+LCRYPTO_USED(BIO_get_data);
+LCRYPTO_USED(BIO_set_data);
+LCRYPTO_USED(BIO_get_init);
+LCRYPTO_USED(BIO_set_init);
+LCRYPTO_USED(BIO_get_shutdown);
+LCRYPTO_USED(BIO_set_shutdown);
+LCRYPTO_USED(BIO_vfree);
+LCRYPTO_USED(BIO_read);
+LCRYPTO_USED(BIO_gets);
+LCRYPTO_USED(BIO_write);
+LCRYPTO_USED(BIO_puts);
+LCRYPTO_USED(BIO_indent);
+LCRYPTO_USED(BIO_ctrl);
+LCRYPTO_USED(BIO_callback_ctrl);
+LCRYPTO_USED(BIO_ptr_ctrl);
+LCRYPTO_USED(BIO_int_ctrl);
+LCRYPTO_USED(BIO_push);
+LCRYPTO_USED(BIO_pop);
+LCRYPTO_USED(BIO_free_all);
+LCRYPTO_USED(BIO_find_type);
+LCRYPTO_USED(BIO_next);
+LCRYPTO_USED(BIO_set_next);
+LCRYPTO_USED(BIO_get_retry_BIO);
+LCRYPTO_USED(BIO_get_retry_reason);
+LCRYPTO_USED(BIO_set_retry_reason);
+LCRYPTO_USED(BIO_dup_chain);
+LCRYPTO_USED(BIO_debug_callback);
+LCRYPTO_USED(BIO_s_mem);
+LCRYPTO_USED(BIO_new_mem_buf);
+LCRYPTO_USED(BIO_s_socket);
+LCRYPTO_USED(BIO_s_connect);
+LCRYPTO_USED(BIO_s_accept);
+LCRYPTO_USED(BIO_s_fd);
+LCRYPTO_USED(BIO_s_log);
+LCRYPTO_USED(BIO_s_bio);
+LCRYPTO_USED(BIO_s_null);
+LCRYPTO_USED(BIO_f_null);
+LCRYPTO_USED(BIO_f_buffer);
+LCRYPTO_USED(BIO_f_nbio_test);
+LCRYPTO_USED(BIO_s_datagram);
+LCRYPTO_USED(BIO_sock_should_retry);
+LCRYPTO_USED(BIO_sock_non_fatal_error);
+LCRYPTO_USED(BIO_dgram_non_fatal_error);
+LCRYPTO_USED(BIO_fd_should_retry);
+LCRYPTO_USED(BIO_fd_non_fatal_error);
+LCRYPTO_USED(BIO_dump);
+LCRYPTO_USED(BIO_dump_indent);
+LCRYPTO_USED(BIO_dump_fp);
+LCRYPTO_USED(BIO_dump_indent_fp);
+LCRYPTO_USED(BIO_gethostbyname);
+LCRYPTO_USED(BIO_sock_error);
+LCRYPTO_USED(BIO_socket_ioctl);
+LCRYPTO_USED(BIO_socket_nbio);
+LCRYPTO_USED(BIO_get_port);
+LCRYPTO_USED(BIO_get_host_ip);
+LCRYPTO_USED(BIO_get_accept_socket);
+LCRYPTO_USED(BIO_accept);
+LCRYPTO_USED(BIO_sock_init);
+LCRYPTO_USED(BIO_sock_cleanup);
+LCRYPTO_USED(BIO_set_tcp_ndelay);
+LCRYPTO_USED(BIO_new_socket);
+LCRYPTO_USED(BIO_new_dgram);
+LCRYPTO_USED(BIO_new_fd);
+LCRYPTO_USED(BIO_new_connect);
+LCRYPTO_USED(BIO_new_accept);
+LCRYPTO_USED(BIO_copy_next_retry);
+LCRYPTO_USED(BIO_printf);
+LCRYPTO_USED(BIO_vprintf);
+LCRYPTO_USED(BIO_snprintf);
+LCRYPTO_USED(BIO_vsnprintf);
+LCRYPTO_USED(ERR_load_BIO_strings);
+
+#endif /* _LIBCRYPTO_BIO_H */
diff --git a/crypto/hidden/openssl/bn.h b/crypto/hidden/openssl/bn.h
new file mode 100644
index 0000000..9942cf6
--- /dev/null
+++ b/crypto/hidden/openssl/bn.h
@@ -0,0 +1,143 @@
+/* $OpenBSD: bn.h,v 1.4 2023/07/29 03:13:38 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_BN_H
+#define _LIBCRYPTO_BN_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/bn.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(BN_set_flags);
+LCRYPTO_USED(BN_get_flags);
+LCRYPTO_USED(BN_with_flags);
+LCRYPTO_USED(BN_GENCB_new);
+LCRYPTO_USED(BN_GENCB_free);
+LCRYPTO_USED(BN_GENCB_call);
+LCRYPTO_USED(BN_GENCB_set_old);
+LCRYPTO_USED(BN_GENCB_set);
+LCRYPTO_USED(BN_GENCB_get_arg);
+LCRYPTO_USED(BN_abs_is_word);
+LCRYPTO_USED(BN_is_zero);
+LCRYPTO_USED(BN_is_one);
+LCRYPTO_USED(BN_is_word);
+LCRYPTO_USED(BN_is_odd);
+LCRYPTO_USED(BN_zero);
+LCRYPTO_USED(BN_one);
+LCRYPTO_USED(BN_value_one);
+LCRYPTO_USED(BN_CTX_new);
+LCRYPTO_USED(BN_CTX_free);
+LCRYPTO_USED(BN_CTX_start);
+LCRYPTO_USED(BN_CTX_get);
+LCRYPTO_USED(BN_CTX_end);
+LCRYPTO_USED(BN_rand);
+LCRYPTO_USED(BN_pseudo_rand);
+LCRYPTO_USED(BN_rand_range);
+LCRYPTO_USED(BN_pseudo_rand_range);
+LCRYPTO_USED(BN_num_bits);
+LCRYPTO_USED(BN_num_bits_word);
+LCRYPTO_USED(BN_new);
+LCRYPTO_USED(BN_clear_free);
+LCRYPTO_USED(BN_copy);
+LCRYPTO_USED(BN_swap);
+LCRYPTO_USED(BN_bin2bn);
+LCRYPTO_USED(BN_bn2bin);
+LCRYPTO_USED(BN_bn2binpad);
+LCRYPTO_USED(BN_lebin2bn);
+LCRYPTO_USED(BN_bn2lebinpad);
+LCRYPTO_USED(BN_mpi2bn);
+LCRYPTO_USED(BN_bn2mpi);
+LCRYPTO_USED(BN_sub);
+LCRYPTO_USED(BN_usub);
+LCRYPTO_USED(BN_uadd);
+LCRYPTO_USED(BN_add);
+LCRYPTO_USED(BN_mul);
+LCRYPTO_USED(BN_sqr);
+LCRYPTO_USED(BN_set_negative);
+LCRYPTO_USED(BN_is_negative);
+LCRYPTO_USED(BN_nnmod);
+LCRYPTO_USED(BN_mod_add);
+LCRYPTO_USED(BN_mod_add_quick);
+LCRYPTO_USED(BN_mod_sub);
+LCRYPTO_USED(BN_mod_sub_quick);
+LCRYPTO_USED(BN_mod_mul);
+LCRYPTO_USED(BN_mod_sqr);
+LCRYPTO_USED(BN_mod_lshift1);
+LCRYPTO_USED(BN_mod_lshift1_quick);
+LCRYPTO_USED(BN_mod_lshift);
+LCRYPTO_USED(BN_mod_lshift_quick);
+LCRYPTO_USED(BN_mod_word);
+LCRYPTO_USED(BN_div_word);
+LCRYPTO_USED(BN_mul_word);
+LCRYPTO_USED(BN_add_word);
+LCRYPTO_USED(BN_sub_word);
+LCRYPTO_USED(BN_set_word);
+LCRYPTO_USED(BN_get_word);
+LCRYPTO_USED(BN_cmp);
+LCRYPTO_USED(BN_free);
+LCRYPTO_USED(BN_is_bit_set);
+LCRYPTO_USED(BN_lshift);
+LCRYPTO_USED(BN_lshift1);
+LCRYPTO_USED(BN_exp);
+LCRYPTO_USED(BN_mod_exp_mont_consttime);
+LCRYPTO_USED(BN_mod_exp_mont_word);
+LCRYPTO_USED(BN_mod_exp2_mont);
+LCRYPTO_USED(BN_mod_exp_simple);
+LCRYPTO_USED(BN_mask_bits);
+LCRYPTO_USED(BN_print_fp);
+LCRYPTO_USED(BN_print);
+LCRYPTO_USED(BN_rshift);
+LCRYPTO_USED(BN_rshift1);
+LCRYPTO_USED(BN_clear);
+LCRYPTO_USED(BN_dup);
+LCRYPTO_USED(BN_ucmp);
+LCRYPTO_USED(BN_set_bit);
+LCRYPTO_USED(BN_clear_bit);
+LCRYPTO_USED(BN_bn2hex);
+LCRYPTO_USED(BN_bn2dec);
+LCRYPTO_USED(BN_hex2bn);
+LCRYPTO_USED(BN_dec2bn);
+LCRYPTO_USED(BN_asc2bn);
+LCRYPTO_USED(BN_kronecker);
+LCRYPTO_USED(BN_mod_sqrt);
+LCRYPTO_USED(BN_consttime_swap);
+LCRYPTO_USED(BN_security_bits);
+LCRYPTO_USED(BN_generate_prime_ex);
+LCRYPTO_USED(BN_is_prime_ex);
+LCRYPTO_USED(BN_is_prime_fasttest_ex);
+LCRYPTO_USED(BN_MONT_CTX_new);
+LCRYPTO_USED(BN_mod_mul_montgomery);
+LCRYPTO_USED(BN_to_montgomery);
+LCRYPTO_USED(BN_from_montgomery);
+LCRYPTO_USED(BN_MONT_CTX_free);
+LCRYPTO_USED(BN_MONT_CTX_set);
+LCRYPTO_USED(BN_MONT_CTX_copy);
+LCRYPTO_USED(BN_MONT_CTX_set_locked);
+LCRYPTO_USED(BN_get_rfc2409_prime_768);
+LCRYPTO_USED(BN_get_rfc2409_prime_1024);
+LCRYPTO_USED(BN_get_rfc3526_prime_1536);
+LCRYPTO_USED(BN_get_rfc3526_prime_2048);
+LCRYPTO_USED(BN_get_rfc3526_prime_3072);
+LCRYPTO_USED(BN_get_rfc3526_prime_4096);
+LCRYPTO_USED(BN_get_rfc3526_prime_6144);
+LCRYPTO_USED(BN_get_rfc3526_prime_8192);
+LCRYPTO_USED(ERR_load_BN_strings);
+
+#endif /* _LIBCRYPTO_BN_H */
diff --git a/crypto/hidden/openssl/buffer.h b/crypto/hidden/openssl/buffer.h
new file mode 100644
index 0000000..8dd8627
--- /dev/null
+++ b/crypto/hidden/openssl/buffer.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: buffer.h,v 1.1 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_BUFFER_H
+#define _LIBCRYPTO_BUFFER_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/buffer.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(BUF_MEM_new);
+LCRYPTO_USED(BUF_MEM_free);
+LCRYPTO_USED(BUF_MEM_grow);
+LCRYPTO_USED(BUF_MEM_grow_clean);
+LCRYPTO_USED(ERR_load_BUF_strings);
+
+#endif /* _LIBCRYPTO_BUFFER_H */
diff --git a/crypto/hidden/openssl/cast.h b/crypto/hidden/openssl/cast.h
new file mode 100644
index 0000000..68cf618
--- /dev/null
+++ b/crypto/hidden/openssl/cast.h
@@ -0,0 +1,36 @@
+/* $OpenBSD: cast.h,v 1.1 2023/07/08 10:44:00 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CAST_H
+#define _LIBCRYPTO_CAST_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/cast.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CAST_set_key);
+LCRYPTO_USED(CAST_ecb_encrypt);
+LCRYPTO_USED(CAST_encrypt);
+LCRYPTO_USED(CAST_decrypt);
+LCRYPTO_USED(CAST_cbc_encrypt);
+LCRYPTO_USED(CAST_cfb64_encrypt);
+LCRYPTO_USED(CAST_ofb64_encrypt);
+
+#endif /* _LIBCRYPTO_CAST_H */
diff --git a/crypto/hidden/openssl/chacha.h b/crypto/hidden/openssl/chacha.h
new file mode 100644
index 0000000..a9f3b7e
--- /dev/null
+++ b/crypto/hidden/openssl/chacha.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: chacha.h,v 1.3 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CHACHA_H
+#define _LIBCRYPTO_CHACHA_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/chacha.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(ChaCha_set_key);
+LCRYPTO_USED(ChaCha_set_iv);
+LCRYPTO_USED(ChaCha);
+LCRYPTO_USED(CRYPTO_chacha_20);
+LCRYPTO_USED(CRYPTO_xchacha_20);
+LCRYPTO_USED(CRYPTO_hchacha_20);
+
+#endif /* _LIBCRYPTO_CHACHA_H */
diff --git a/crypto/hidden/openssl/cmac.h b/crypto/hidden/openssl/cmac.h
new file mode 100644
index 0000000..cefdb4f
--- /dev/null
+++ b/crypto/hidden/openssl/cmac.h
@@ -0,0 +1,38 @@
+/* $OpenBSD: cmac.h,v 1.1 2023/07/08 14:27:14 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CMAC_H
+#define _LIBCRYPTO_CMAC_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/cmac.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CMAC_CTX_new);
+LCRYPTO_USED(CMAC_CTX_cleanup);
+LCRYPTO_USED(CMAC_CTX_free);
+LCRYPTO_USED(CMAC_CTX_get0_cipher_ctx);
+LCRYPTO_USED(CMAC_CTX_copy);
+LCRYPTO_USED(CMAC_Init);
+LCRYPTO_USED(CMAC_Update);
+LCRYPTO_USED(CMAC_Final);
+LCRYPTO_USED(CMAC_resume);
+
+#endif /* _LIBCRYPTO_CMAC_H */
diff --git a/crypto/hidden/openssl/cms.h b/crypto/hidden/openssl/cms.h
new file mode 100644
index 0000000..0f450e6
--- /dev/null
+++ b/crypto/hidden/openssl/cms.h
@@ -0,0 +1,148 @@
+/* $OpenBSD: cms.h,v 1.2 2023/07/28 10:28:02 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CMS_H
+#define _LIBCRYPTO_CMS_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/cms.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CMS_ContentInfo_new);
+LCRYPTO_USED(CMS_ContentInfo_free);
+LCRYPTO_USED(d2i_CMS_ContentInfo);
+LCRYPTO_USED(i2d_CMS_ContentInfo);
+LCRYPTO_USED(CMS_ReceiptRequest_new);
+LCRYPTO_USED(CMS_ReceiptRequest_free);
+LCRYPTO_USED(d2i_CMS_ReceiptRequest);
+LCRYPTO_USED(i2d_CMS_ReceiptRequest);
+LCRYPTO_USED(CMS_ContentInfo_print_ctx);
+LCRYPTO_USED(CMS_get0_type);
+LCRYPTO_USED(CMS_get_version);
+LCRYPTO_USED(CMS_SignerInfo_get_version);
+LCRYPTO_USED(CMS_dataInit);
+LCRYPTO_USED(CMS_dataFinal);
+LCRYPTO_USED(CMS_is_detached);
+LCRYPTO_USED(CMS_set_detached);
+LCRYPTO_USED(CMS_stream);
+LCRYPTO_USED(d2i_CMS_bio);
+LCRYPTO_USED(i2d_CMS_bio);
+LCRYPTO_USED(BIO_new_CMS);
+LCRYPTO_USED(i2d_CMS_bio_stream);
+LCRYPTO_USED(PEM_write_bio_CMS_stream);
+LCRYPTO_USED(SMIME_read_CMS);
+LCRYPTO_USED(SMIME_write_CMS);
+LCRYPTO_USED(CMS_final);
+LCRYPTO_USED(CMS_sign);
+LCRYPTO_USED(CMS_sign_receipt);
+LCRYPTO_USED(CMS_data);
+LCRYPTO_USED(CMS_data_create);
+LCRYPTO_USED(CMS_digest_verify);
+LCRYPTO_USED(CMS_digest_create);
+LCRYPTO_USED(CMS_EncryptedData_decrypt);
+LCRYPTO_USED(CMS_EncryptedData_encrypt);
+LCRYPTO_USED(CMS_EncryptedData_set1_key);
+LCRYPTO_USED(CMS_verify);
+LCRYPTO_USED(CMS_verify_receipt);
+LCRYPTO_USED(CMS_get0_signers);
+LCRYPTO_USED(CMS_encrypt);
+LCRYPTO_USED(CMS_decrypt);
+LCRYPTO_USED(CMS_decrypt_set1_pkey);
+LCRYPTO_USED(CMS_decrypt_set1_key);
+LCRYPTO_USED(CMS_decrypt_set1_password);
+LCRYPTO_USED(CMS_get0_RecipientInfos);
+LCRYPTO_USED(CMS_RecipientInfo_type);
+LCRYPTO_USED(CMS_RecipientInfo_get0_pkey_ctx);
+LCRYPTO_USED(CMS_EnvelopedData_create);
+LCRYPTO_USED(CMS_add1_recipient_cert);
+LCRYPTO_USED(CMS_RecipientInfo_set0_pkey);
+LCRYPTO_USED(CMS_RecipientInfo_ktri_cert_cmp);
+LCRYPTO_USED(CMS_RecipientInfo_ktri_get0_algs);
+LCRYPTO_USED(CMS_RecipientInfo_ktri_get0_signer_id);
+LCRYPTO_USED(CMS_add0_recipient_key);
+LCRYPTO_USED(CMS_RecipientInfo_kekri_get0_id);
+LCRYPTO_USED(CMS_RecipientInfo_set0_key);
+LCRYPTO_USED(CMS_RecipientInfo_kekri_id_cmp);
+LCRYPTO_USED(CMS_RecipientInfo_set0_password);
+LCRYPTO_USED(CMS_add0_recipient_password);
+LCRYPTO_USED(CMS_RecipientInfo_decrypt);
+LCRYPTO_USED(CMS_RecipientInfo_encrypt);
+LCRYPTO_USED(CMS_uncompress);
+LCRYPTO_USED(CMS_compress);
+LCRYPTO_USED(CMS_set1_eContentType);
+LCRYPTO_USED(CMS_get0_eContentType);
+LCRYPTO_USED(CMS_add0_CertificateChoices);
+LCRYPTO_USED(CMS_add0_cert);
+LCRYPTO_USED(CMS_add1_cert);
+LCRYPTO_USED(CMS_get1_certs);
+LCRYPTO_USED(CMS_add0_RevocationInfoChoice);
+LCRYPTO_USED(CMS_add0_crl);
+LCRYPTO_USED(CMS_add1_crl);
+LCRYPTO_USED(CMS_get1_crls);
+LCRYPTO_USED(CMS_SignedData_init);
+LCRYPTO_USED(CMS_add1_signer);
+LCRYPTO_USED(CMS_SignerInfo_get0_pkey_ctx);
+LCRYPTO_USED(CMS_SignerInfo_get0_md_ctx);
+LCRYPTO_USED(CMS_get0_SignerInfos);
+LCRYPTO_USED(CMS_SignerInfo_set1_signer_cert);
+LCRYPTO_USED(CMS_SignerInfo_get0_signer_id);
+LCRYPTO_USED(CMS_SignerInfo_cert_cmp);
+LCRYPTO_USED(CMS_set1_signers_certs);
+LCRYPTO_USED(CMS_SignerInfo_get0_algs);
+LCRYPTO_USED(CMS_SignerInfo_get0_signature);
+LCRYPTO_USED(CMS_SignerInfo_sign);
+LCRYPTO_USED(CMS_SignerInfo_verify);
+LCRYPTO_USED(CMS_SignerInfo_verify_content);
+LCRYPTO_USED(CMS_add_smimecap);
+LCRYPTO_USED(CMS_add_simple_smimecap);
+LCRYPTO_USED(CMS_add_standard_smimecap);
+LCRYPTO_USED(CMS_signed_get_attr_count);
+LCRYPTO_USED(CMS_signed_get_attr_by_NID);
+LCRYPTO_USED(CMS_signed_get_attr_by_OBJ);
+LCRYPTO_USED(CMS_signed_get_attr);
+LCRYPTO_USED(CMS_signed_delete_attr);
+LCRYPTO_USED(CMS_signed_add1_attr);
+LCRYPTO_USED(CMS_signed_add1_attr_by_OBJ);
+LCRYPTO_USED(CMS_signed_add1_attr_by_NID);
+LCRYPTO_USED(CMS_signed_add1_attr_by_txt);
+LCRYPTO_USED(CMS_signed_get0_data_by_OBJ);
+LCRYPTO_USED(CMS_unsigned_get_attr_count);
+LCRYPTO_USED(CMS_unsigned_get_attr_by_NID);
+LCRYPTO_USED(CMS_unsigned_get_attr_by_OBJ);
+LCRYPTO_USED(CMS_unsigned_get_attr);
+LCRYPTO_USED(CMS_unsigned_delete_attr);
+LCRYPTO_USED(CMS_unsigned_add1_attr);
+LCRYPTO_USED(CMS_unsigned_add1_attr_by_OBJ);
+LCRYPTO_USED(CMS_unsigned_add1_attr_by_NID);
+LCRYPTO_USED(CMS_unsigned_add1_attr_by_txt);
+LCRYPTO_USED(CMS_unsigned_get0_data_by_OBJ);
+LCRYPTO_USED(CMS_RecipientInfo_kari_get0_alg);
+LCRYPTO_USED(CMS_RecipientInfo_kari_get0_reks);
+LCRYPTO_USED(CMS_RecipientInfo_kari_get0_orig_id);
+LCRYPTO_USED(CMS_RecipientInfo_kari_orig_id_cmp);
+LCRYPTO_USED(CMS_RecipientEncryptedKey_get0_id);
+LCRYPTO_USED(CMS_RecipientEncryptedKey_cert_cmp);
+LCRYPTO_USED(CMS_RecipientInfo_kari_set0_pkey);
+LCRYPTO_USED(CMS_RecipientInfo_kari_get0_ctx);
+LCRYPTO_USED(CMS_RecipientInfo_kari_decrypt);
+LCRYPTO_USED(CMS_SharedInfo_encode);
+LCRYPTO_USED(ERR_load_CMS_strings);
+
+#endif /* _LIBCRYPTO_CMS_H */
diff --git a/crypto/hidden/openssl/conf_api.h b/crypto/hidden/openssl/conf_api.h
new file mode 100644
index 0000000..5ff8956
--- /dev/null
+++ b/crypto/hidden/openssl/conf_api.h
@@ -0,0 +1,36 @@
+/* $OpenBSD: conf_api.h,v 1.1 2023/07/08 08:26:26 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CONF_API_H
+#define _LIBCRYPTO_CONF_API_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/conf_api.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(_CONF_new_section);
+LCRYPTO_USED(_CONF_get_section);
+LCRYPTO_USED(_CONF_get_section_values);
+LCRYPTO_USED(_CONF_add_string);
+LCRYPTO_USED(_CONF_get_string);
+LCRYPTO_USED(_CONF_new_data);
+LCRYPTO_USED(_CONF_free_data);
+
+#endif /* _LIBCRYPTO_CONF_API_H */
diff --git a/crypto/hidden/openssl/crypto.h b/crypto/hidden/openssl/crypto.h
new file mode 100644
index 0000000..dc0b7a0
--- /dev/null
+++ b/crypto/hidden/openssl/crypto.h
@@ -0,0 +1,76 @@
+/* $OpenBSD: crypto.h,v 1.2 2023/07/28 10:19:20 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CRYPTO_H
+#define _LIBCRYPTO_CRYPTO_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/crypto.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(OpenSSL_version);
+LCRYPTO_USED(OpenSSL_version_num);
+LCRYPTO_USED(SSLeay_version);
+LCRYPTO_USED(SSLeay);
+LCRYPTO_USED(CRYPTO_get_ex_new_index);
+LCRYPTO_USED(CRYPTO_new_ex_data);
+LCRYPTO_USED(CRYPTO_dup_ex_data);
+LCRYPTO_USED(CRYPTO_free_ex_data);
+LCRYPTO_USED(CRYPTO_set_ex_data);
+LCRYPTO_USED(CRYPTO_get_ex_data);
+LCRYPTO_USED(CRYPTO_cleanup_all_ex_data);
+LCRYPTO_USED(CRYPTO_lock);
+LCRYPTO_USED(CRYPTO_add_lock);
+LCRYPTO_USED(CRYPTO_THREADID_current);
+LCRYPTO_USED(CRYPTO_THREADID_cmp);
+LCRYPTO_USED(CRYPTO_THREADID_cpy);
+LCRYPTO_USED(CRYPTO_THREADID_hash);
+LCRYPTO_USED(CRYPTO_set_mem_functions);
+LCRYPTO_USED(CRYPTO_set_locked_mem_functions);
+LCRYPTO_USED(CRYPTO_set_mem_ex_functions);
+LCRYPTO_USED(CRYPTO_set_locked_mem_ex_functions);
+LCRYPTO_USED(CRYPTO_set_mem_debug_functions);
+LCRYPTO_USED(CRYPTO_get_mem_functions);
+LCRYPTO_USED(CRYPTO_get_locked_mem_functions);
+LCRYPTO_USED(CRYPTO_get_mem_ex_functions);
+LCRYPTO_USED(CRYPTO_get_locked_mem_ex_functions);
+LCRYPTO_USED(CRYPTO_get_mem_debug_functions);
+LCRYPTO_USED(CRYPTO_realloc_clean);
+LCRYPTO_USED(CRYPTO_remalloc);
+LCRYPTO_USED(CRYPTO_set_mem_debug_options);
+LCRYPTO_USED(CRYPTO_get_mem_debug_options);
+LCRYPTO_USED(CRYPTO_push_info_);
+LCRYPTO_USED(CRYPTO_pop_info);
+LCRYPTO_USED(CRYPTO_remove_all_info);
+LCRYPTO_USED(CRYPTO_dbg_malloc);
+LCRYPTO_USED(CRYPTO_dbg_realloc);
+LCRYPTO_USED(CRYPTO_dbg_free);
+LCRYPTO_USED(CRYPTO_dbg_set_options);
+LCRYPTO_USED(CRYPTO_dbg_get_options);
+LCRYPTO_USED(CRYPTO_mem_leaks_fp);
+LCRYPTO_USED(CRYPTO_mem_leaks);
+LCRYPTO_USED(CRYPTO_mem_leaks_cb);
+LCRYPTO_USED(OpenSSLDie);
+LCRYPTO_USED(OPENSSL_cpu_caps);
+LCRYPTO_USED(OPENSSL_init_crypto);
+LCRYPTO_USED(OPENSSL_cleanup);
+LCRYPTO_USED(ERR_load_CRYPTO_strings);
+
+#endif /* _LIBCRYPTO_CRYPTO_H */
diff --git a/crypto/hidden/openssl/ct.h b/crypto/hidden/openssl/ct.h
new file mode 100644
index 0000000..a1c9b33
--- /dev/null
+++ b/crypto/hidden/openssl/ct.h
@@ -0,0 +1,85 @@
+/* $OpenBSD: ct.h,v 1.1 2023/07/08 07:22:58 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CT_H
+#define _LIBCRYPTO_CT_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/ct.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_new);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_free);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_get0_cert);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_set1_cert);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_get0_issuer);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_set1_issuer);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_get0_log_store);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_get_time);
+LCRYPTO_USED(CT_POLICY_EVAL_CTX_set_time);
+LCRYPTO_USED(SCT_new);
+LCRYPTO_USED(SCT_new_from_base64);
+LCRYPTO_USED(SCT_free);
+LCRYPTO_USED(SCT_LIST_free);
+LCRYPTO_USED(SCT_get_version);
+LCRYPTO_USED(SCT_set_version);
+LCRYPTO_USED(SCT_get_log_entry_type);
+LCRYPTO_USED(SCT_set_log_entry_type);
+LCRYPTO_USED(SCT_get0_log_id);
+LCRYPTO_USED(SCT_set0_log_id);
+LCRYPTO_USED(SCT_set1_log_id);
+LCRYPTO_USED(SCT_get_timestamp);
+LCRYPTO_USED(SCT_set_timestamp);
+LCRYPTO_USED(SCT_get_signature_nid);
+LCRYPTO_USED(SCT_set_signature_nid);
+LCRYPTO_USED(SCT_get0_extensions);
+LCRYPTO_USED(SCT_set0_extensions);
+LCRYPTO_USED(SCT_set1_extensions);
+LCRYPTO_USED(SCT_get0_signature);
+LCRYPTO_USED(SCT_set0_signature);
+LCRYPTO_USED(SCT_set1_signature);
+LCRYPTO_USED(SCT_get_source);
+LCRYPTO_USED(SCT_set_source);
+LCRYPTO_USED(SCT_validation_status_string);
+LCRYPTO_USED(SCT_print);
+LCRYPTO_USED(SCT_LIST_print);
+LCRYPTO_USED(SCT_get_validation_status);
+LCRYPTO_USED(SCT_validate);
+LCRYPTO_USED(SCT_LIST_validate);
+LCRYPTO_USED(i2o_SCT_LIST);
+LCRYPTO_USED(o2i_SCT_LIST);
+LCRYPTO_USED(i2d_SCT_LIST);
+LCRYPTO_USED(d2i_SCT_LIST);
+LCRYPTO_USED(i2o_SCT);
+LCRYPTO_USED(o2i_SCT);
+LCRYPTO_USED(CTLOG_new);
+LCRYPTO_USED(CTLOG_new_from_base64);
+LCRYPTO_USED(CTLOG_free);
+LCRYPTO_USED(CTLOG_get0_name);
+LCRYPTO_USED(CTLOG_get0_log_id);
+LCRYPTO_USED(CTLOG_get0_public_key);
+LCRYPTO_USED(CTLOG_STORE_new);
+LCRYPTO_USED(CTLOG_STORE_free);
+LCRYPTO_USED(CTLOG_STORE_get0_log_by_id);
+LCRYPTO_USED(CTLOG_STORE_load_file);
+LCRYPTO_USED(CTLOG_STORE_load_default_file);
+
+#endif /* _LIBCRYPTO_CT_H */
diff --git a/crypto/hidden/openssl/curve25519.h b/crypto/hidden/openssl/curve25519.h
new file mode 100644
index 0000000..3afa324
--- /dev/null
+++ b/crypto/hidden/openssl/curve25519.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: curve25519.h,v 1.1 2023/07/08 15:12:49 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_CURVE25519_H
+#define _LIBCRYPTO_CURVE25519_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/curve25519.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(X25519_keypair);
+LCRYPTO_USED(X25519);
+LCRYPTO_USED(ED25519_keypair);
+LCRYPTO_USED(ED25519_sign);
+LCRYPTO_USED(ED25519_verify);
+
+#endif /* _LIBCRYPTO_CURVE25519_H */
diff --git a/crypto/hidden/openssl/dh.h b/crypto/hidden/openssl/dh.h
new file mode 100644
index 0000000..7e6d578
--- /dev/null
+++ b/crypto/hidden/openssl/dh.h
@@ -0,0 +1,74 @@
+/* $OpenBSD: dh.h,v 1.1 2023/07/08 15:29:04 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_DH_H
+#define _LIBCRYPTO_DH_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/dh.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(d2i_DHparams_bio);
+LCRYPTO_USED(i2d_DHparams_bio);
+LCRYPTO_USED(d2i_DHparams_fp);
+LCRYPTO_USED(i2d_DHparams_fp);
+LCRYPTO_USED(DHparams_dup);
+LCRYPTO_USED(DH_OpenSSL);
+LCRYPTO_USED(DH_set_default_method);
+LCRYPTO_USED(DH_get_default_method);
+LCRYPTO_USED(DH_set_method);
+LCRYPTO_USED(DH_new_method);
+LCRYPTO_USED(DH_new);
+LCRYPTO_USED(DH_free);
+LCRYPTO_USED(DH_up_ref);
+LCRYPTO_USED(DH_size);
+LCRYPTO_USED(DH_bits);
+LCRYPTO_USED(DH_get_ex_new_index);
+LCRYPTO_USED(DH_set_ex_data);
+LCRYPTO_USED(DH_get_ex_data);
+LCRYPTO_USED(DH_security_bits);
+LCRYPTO_USED(DH_get0_engine);
+LCRYPTO_USED(DH_get0_pqg);
+LCRYPTO_USED(DH_set0_pqg);
+LCRYPTO_USED(DH_get0_key);
+LCRYPTO_USED(DH_set0_key);
+LCRYPTO_USED(DH_get0_p);
+LCRYPTO_USED(DH_get0_q);
+LCRYPTO_USED(DH_get0_g);
+LCRYPTO_USED(DH_get0_priv_key);
+LCRYPTO_USED(DH_get0_pub_key);
+LCRYPTO_USED(DH_clear_flags);
+LCRYPTO_USED(DH_test_flags);
+LCRYPTO_USED(DH_set_flags);
+LCRYPTO_USED(DH_get_length);
+LCRYPTO_USED(DH_set_length);
+LCRYPTO_USED(DH_generate_parameters);
+LCRYPTO_USED(DH_generate_parameters_ex);
+LCRYPTO_USED(DH_check);
+LCRYPTO_USED(DH_check_pub_key);
+LCRYPTO_USED(DH_generate_key);
+LCRYPTO_USED(DH_compute_key);
+LCRYPTO_USED(d2i_DHparams);
+LCRYPTO_USED(i2d_DHparams);
+LCRYPTO_USED(DHparams_print_fp);
+LCRYPTO_USED(DHparams_print);
+LCRYPTO_USED(ERR_load_DH_strings);
+
+#endif /* _LIBCRYPTO_DH_H */
diff --git a/crypto/hidden/openssl/dsa.h b/crypto/hidden/openssl/dsa.h
new file mode 100644
index 0000000..b2b0058
--- /dev/null
+++ b/crypto/hidden/openssl/dsa.h
@@ -0,0 +1,94 @@
+/* $OpenBSD: dsa.h,v 1.1 2023/07/08 14:28:15 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_DSA_H
+#define _LIBCRYPTO_DSA_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/dsa.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(d2i_DSAparams_bio);
+LCRYPTO_USED(i2d_DSAparams_bio);
+LCRYPTO_USED(d2i_DSAparams_fp);
+LCRYPTO_USED(i2d_DSAparams_fp);
+LCRYPTO_USED(DSAparams_dup);
+LCRYPTO_USED(DSA_SIG_new);
+LCRYPTO_USED(DSA_SIG_free);
+LCRYPTO_USED(i2d_DSA_SIG);
+LCRYPTO_USED(d2i_DSA_SIG);
+LCRYPTO_USED(DSA_SIG_get0);
+LCRYPTO_USED(DSA_SIG_set0);
+LCRYPTO_USED(DSA_do_sign);
+LCRYPTO_USED(DSA_do_verify);
+LCRYPTO_USED(DSA_OpenSSL);
+LCRYPTO_USED(DSA_set_default_method);
+LCRYPTO_USED(DSA_get_default_method);
+LCRYPTO_USED(DSA_set_method);
+LCRYPTO_USED(DSA_new);
+LCRYPTO_USED(DSA_new_method);
+LCRYPTO_USED(DSA_free);
+LCRYPTO_USED(DSA_up_ref);
+LCRYPTO_USED(DSA_size);
+LCRYPTO_USED(DSA_bits);
+LCRYPTO_USED(DSA_sign_setup);
+LCRYPTO_USED(DSA_sign);
+LCRYPTO_USED(DSA_verify);
+LCRYPTO_USED(DSA_get_ex_new_index);
+LCRYPTO_USED(DSA_set_ex_data);
+LCRYPTO_USED(DSA_get_ex_data);
+LCRYPTO_USED(DSA_security_bits);
+LCRYPTO_USED(d2i_DSAPublicKey);
+LCRYPTO_USED(i2d_DSAPublicKey);
+LCRYPTO_USED(d2i_DSAPrivateKey);
+LCRYPTO_USED(i2d_DSAPrivateKey);
+LCRYPTO_USED(d2i_DSAparams);
+LCRYPTO_USED(i2d_DSAparams);
+LCRYPTO_USED(DSA_generate_parameters);
+LCRYPTO_USED(DSA_generate_parameters_ex);
+LCRYPTO_USED(DSA_generate_key);
+LCRYPTO_USED(DSAparams_print);
+LCRYPTO_USED(DSA_print);
+LCRYPTO_USED(DSAparams_print_fp);
+LCRYPTO_USED(DSA_print_fp);
+LCRYPTO_USED(DSA_dup_DH);
+LCRYPTO_USED(DSA_get0_pqg);
+LCRYPTO_USED(DSA_set0_pqg);
+LCRYPTO_USED(DSA_get0_key);
+LCRYPTO_USED(DSA_set0_key);
+LCRYPTO_USED(DSA_get0_p);
+LCRYPTO_USED(DSA_get0_q);
+LCRYPTO_USED(DSA_get0_g);
+LCRYPTO_USED(DSA_get0_pub_key);
+LCRYPTO_USED(DSA_get0_priv_key);
+LCRYPTO_USED(DSA_clear_flags);
+LCRYPTO_USED(DSA_test_flags);
+LCRYPTO_USED(DSA_set_flags);
+LCRYPTO_USED(DSA_get0_engine);
+LCRYPTO_USED(DSA_meth_new);
+LCRYPTO_USED(DSA_meth_free);
+LCRYPTO_USED(DSA_meth_dup);
+LCRYPTO_USED(DSA_meth_get0_name);
+LCRYPTO_USED(DSA_meth_set1_name);
+LCRYPTO_USED(DSA_meth_set_sign);
+LCRYPTO_USED(DSA_meth_set_finish);
+LCRYPTO_USED(ERR_load_DSA_strings);
+
+#endif /* _LIBCRYPTO_DSA_H */
diff --git a/crypto/hidden/openssl/ec.h b/crypto/hidden/openssl/ec.h
new file mode 100644
index 0000000..4e82f48
--- /dev/null
+++ b/crypto/hidden/openssl/ec.h
@@ -0,0 +1,165 @@
+/* $OpenBSD: ec.h,v 1.4 2023/07/28 09:25:12 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_EC_H
+#define _LIBCRYPTO_EC_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/ec.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(EC_GFp_simple_method);
+LCRYPTO_USED(EC_GFp_mont_method);
+LCRYPTO_USED(EC_GROUP_new);
+LCRYPTO_USED(EC_GROUP_free);
+LCRYPTO_USED(EC_GROUP_copy);
+LCRYPTO_USED(EC_GROUP_dup);
+LCRYPTO_USED(EC_GROUP_method_of);
+LCRYPTO_USED(EC_METHOD_get_field_type);
+LCRYPTO_USED(EC_GROUP_set_generator);
+LCRYPTO_USED(EC_GROUP_get0_generator);
+LCRYPTO_USED(EC_GROUP_get_order);
+LCRYPTO_USED(EC_GROUP_order_bits);
+LCRYPTO_USED(EC_GROUP_get_cofactor);
+LCRYPTO_USED(EC_GROUP_set_curve_name);
+LCRYPTO_USED(EC_GROUP_get_curve_name);
+LCRYPTO_USED(EC_GROUP_set_asn1_flag);
+LCRYPTO_USED(EC_GROUP_get_asn1_flag);
+LCRYPTO_USED(EC_GROUP_set_point_conversion_form);
+LCRYPTO_USED(EC_GROUP_get_point_conversion_form);
+LCRYPTO_USED(EC_GROUP_get0_seed);
+LCRYPTO_USED(EC_GROUP_get_seed_len);
+LCRYPTO_USED(EC_GROUP_set_seed);
+LCRYPTO_USED(EC_GROUP_set_curve);
+LCRYPTO_USED(EC_GROUP_get_curve);
+LCRYPTO_USED(EC_GROUP_get_degree);
+LCRYPTO_USED(EC_GROUP_check);
+LCRYPTO_USED(EC_GROUP_check_discriminant);
+LCRYPTO_USED(EC_GROUP_cmp);
+LCRYPTO_USED(EC_GROUP_new_curve_GFp);
+LCRYPTO_USED(EC_GROUP_new_by_curve_name);
+LCRYPTO_USED(EC_get_builtin_curves);
+LCRYPTO_USED(EC_curve_nid2nist);
+LCRYPTO_USED(EC_curve_nist2nid);
+LCRYPTO_USED(EC_POINT_new);
+LCRYPTO_USED(EC_POINT_free);
+LCRYPTO_USED(EC_POINT_copy);
+LCRYPTO_USED(EC_POINT_dup);
+LCRYPTO_USED(EC_POINT_method_of);
+LCRYPTO_USED(EC_POINT_set_to_infinity);
+LCRYPTO_USED(EC_POINT_set_affine_coordinates);
+LCRYPTO_USED(EC_POINT_get_affine_coordinates);
+LCRYPTO_USED(EC_POINT_set_compressed_coordinates);
+LCRYPTO_USED(EC_POINT_point2oct);
+LCRYPTO_USED(EC_POINT_oct2point);
+LCRYPTO_USED(EC_POINT_point2bn);
+LCRYPTO_USED(EC_POINT_bn2point);
+LCRYPTO_USED(EC_POINT_point2hex);
+LCRYPTO_USED(EC_POINT_hex2point);
+LCRYPTO_USED(EC_POINT_add);
+LCRYPTO_USED(EC_POINT_dbl);
+LCRYPTO_USED(EC_POINT_invert);
+LCRYPTO_USED(EC_POINT_is_at_infinity);
+LCRYPTO_USED(EC_POINT_is_on_curve);
+LCRYPTO_USED(EC_POINT_cmp);
+LCRYPTO_USED(EC_POINT_make_affine);
+LCRYPTO_USED(EC_POINTs_make_affine);
+LCRYPTO_USED(EC_POINTs_mul);
+LCRYPTO_USED(EC_POINT_mul);
+LCRYPTO_USED(EC_GROUP_precompute_mult);
+LCRYPTO_USED(EC_GROUP_have_precompute_mult);
+LCRYPTO_USED(EC_GROUP_get_basis_type);
+LCRYPTO_USED(d2i_ECPKParameters);
+LCRYPTO_USED(i2d_ECPKParameters);
+LCRYPTO_USED(ECPKParameters_print);
+LCRYPTO_USED(ECPKParameters_print_fp);
+LCRYPTO_USED(EC_KEY_new);
+LCRYPTO_USED(EC_KEY_get_flags);
+LCRYPTO_USED(EC_KEY_set_flags);
+LCRYPTO_USED(EC_KEY_clear_flags);
+LCRYPTO_USED(EC_KEY_new_by_curve_name);
+LCRYPTO_USED(EC_KEY_free);
+LCRYPTO_USED(EC_KEY_copy);
+LCRYPTO_USED(EC_KEY_dup);
+LCRYPTO_USED(EC_KEY_up_ref);
+LCRYPTO_USED(EC_KEY_get0_group);
+LCRYPTO_USED(EC_KEY_set_group);
+LCRYPTO_USED(EC_KEY_get0_private_key);
+LCRYPTO_USED(EC_KEY_set_private_key);
+LCRYPTO_USED(EC_KEY_get0_public_key);
+LCRYPTO_USED(EC_KEY_set_public_key);
+LCRYPTO_USED(EC_KEY_get_enc_flags);
+LCRYPTO_USED(EC_KEY_set_enc_flags);
+LCRYPTO_USED(EC_KEY_get_conv_form);
+LCRYPTO_USED(EC_KEY_set_conv_form);
+LCRYPTO_USED(EC_KEY_set_asn1_flag);
+LCRYPTO_USED(EC_KEY_precompute_mult);
+LCRYPTO_USED(EC_KEY_generate_key);
+LCRYPTO_USED(EC_KEY_check_key);
+LCRYPTO_USED(EC_KEY_set_public_key_affine_coordinates);
+LCRYPTO_USED(d2i_ECPrivateKey);
+LCRYPTO_USED(i2d_ECPrivateKey);
+LCRYPTO_USED(d2i_ECParameters);
+LCRYPTO_USED(i2d_ECParameters);
+LCRYPTO_USED(o2i_ECPublicKey);
+LCRYPTO_USED(i2o_ECPublicKey);
+LCRYPTO_USED(ECParameters_print);
+LCRYPTO_USED(EC_KEY_print);
+LCRYPTO_USED(ECParameters_print_fp);
+LCRYPTO_USED(EC_KEY_print_fp);
+LCRYPTO_USED(EC_KEY_set_ex_data);
+LCRYPTO_USED(EC_KEY_get_ex_data);
+LCRYPTO_USED(EC_KEY_OpenSSL);
+LCRYPTO_USED(EC_KEY_get_default_method);
+LCRYPTO_USED(EC_KEY_set_default_method);
+LCRYPTO_USED(EC_KEY_get_method);
+LCRYPTO_USED(EC_KEY_set_method);
+LCRYPTO_USED(EC_KEY_new_method);
+LCRYPTO_USED(ECDH_size);
+LCRYPTO_USED(ECDH_compute_key);
+LCRYPTO_USED(ECDSA_SIG_new);
+LCRYPTO_USED(ECDSA_SIG_free);
+LCRYPTO_USED(i2d_ECDSA_SIG);
+LCRYPTO_USED(d2i_ECDSA_SIG);
+LCRYPTO_USED(ECDSA_SIG_get0_r);
+LCRYPTO_USED(ECDSA_SIG_get0_s);
+LCRYPTO_USED(ECDSA_SIG_get0);
+LCRYPTO_USED(ECDSA_SIG_set0);
+LCRYPTO_USED(ECDSA_size);
+LCRYPTO_USED(ECDSA_do_sign);
+LCRYPTO_USED(ECDSA_do_verify);
+LCRYPTO_USED(ECDSA_sign);
+LCRYPTO_USED(ECDSA_verify);
+LCRYPTO_USED(EC_KEY_METHOD_new);
+LCRYPTO_USED(EC_KEY_METHOD_free);
+LCRYPTO_USED(EC_KEY_METHOD_set_init);
+LCRYPTO_USED(EC_KEY_METHOD_set_keygen);
+LCRYPTO_USED(EC_KEY_METHOD_set_compute_key);
+LCRYPTO_USED(EC_KEY_METHOD_set_sign);
+LCRYPTO_USED(EC_KEY_METHOD_set_verify);
+LCRYPTO_USED(EC_KEY_METHOD_get_init);
+LCRYPTO_USED(EC_KEY_METHOD_get_keygen);
+LCRYPTO_USED(EC_KEY_METHOD_get_compute_key);
+LCRYPTO_USED(EC_KEY_METHOD_get_sign);
+LCRYPTO_USED(EC_KEY_METHOD_get_verify);
+LCRYPTO_USED(ECParameters_dup);
+LCRYPTO_USED(ERR_load_EC_strings);
+
+#endif /* _LIBCRYPTO_EC_H */
diff --git a/crypto/hidden/openssl/err.h b/crypto/hidden/openssl/err.h
new file mode 100644
index 0000000..036ead8
--- /dev/null
+++ b/crypto/hidden/openssl/err.h
@@ -0,0 +1,61 @@
+/* $OpenBSD: err.h,v 1.4 2023/07/28 10:23:19 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_ERR_H
+#define _LIBCRYPTO_ERR_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/err.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(ERR_put_error);
+LCRYPTO_USED(ERR_set_error_data);
+LCRYPTO_USED(ERR_get_error);
+LCRYPTO_USED(ERR_get_error_line);
+LCRYPTO_USED(ERR_get_error_line_data);
+LCRYPTO_USED(ERR_peek_error);
+LCRYPTO_USED(ERR_peek_error_line);
+LCRYPTO_USED(ERR_peek_error_line_data);
+LCRYPTO_USED(ERR_peek_last_error);
+LCRYPTO_USED(ERR_peek_last_error_line);
+LCRYPTO_USED(ERR_peek_last_error_line_data);
+LCRYPTO_USED(ERR_clear_error);
+LCRYPTO_USED(ERR_error_string);
+LCRYPTO_USED(ERR_error_string_n);
+LCRYPTO_USED(ERR_lib_error_string);
+LCRYPTO_USED(ERR_func_error_string);
+LCRYPTO_USED(ERR_reason_error_string);
+LCRYPTO_USED(ERR_print_errors_cb);
+LCRYPTO_USED(ERR_print_errors_fp);
+LCRYPTO_USED(ERR_print_errors);
+LCRYPTO_USED(ERR_asprintf_error_data);
+LCRYPTO_USED(ERR_load_strings);
+LCRYPTO_USED(ERR_unload_strings);
+LCRYPTO_USED(ERR_load_ERR_strings);
+LCRYPTO_USED(ERR_load_crypto_strings);
+LCRYPTO_USED(ERR_free_strings);
+LCRYPTO_USED(ERR_remove_thread_state);
+LCRYPTO_USED(ERR_remove_state);
+LCRYPTO_USED(ERR_get_state);
+LCRYPTO_USED(ERR_get_next_error_library);
+LCRYPTO_USED(ERR_set_mark);
+LCRYPTO_USED(ERR_pop_to_mark);
+
+#endif /* _LIBCRYPTO_ERR_H */
diff --git a/crypto/hidden/openssl/gost.h b/crypto/hidden/openssl/gost.h
new file mode 100644
index 0000000..e30e661
--- /dev/null
+++ b/crypto/hidden/openssl/gost.h
@@ -0,0 +1,71 @@
+/* $OpenBSD: gost.h,v 1.1 2023/07/08 14:30:44 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_GOST_H
+#define _LIBCRYPTO_GOST_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/gost.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(Gost2814789_set_sbox);
+LCRYPTO_USED(Gost2814789_set_key);
+LCRYPTO_USED(Gost2814789_ecb_encrypt);
+LCRYPTO_USED(Gost2814789_cfb64_encrypt);
+LCRYPTO_USED(Gost2814789_cnt_encrypt);
+LCRYPTO_USED(GOST_CIPHER_PARAMS_new);
+LCRYPTO_USED(GOST_CIPHER_PARAMS_free);
+LCRYPTO_USED(d2i_GOST_CIPHER_PARAMS);
+LCRYPTO_USED(i2d_GOST_CIPHER_PARAMS);
+LCRYPTO_USED(GOST2814789IMIT_Init);
+LCRYPTO_USED(GOST2814789IMIT_Update);
+LCRYPTO_USED(GOST2814789IMIT_Final);
+LCRYPTO_USED(GOST2814789IMIT_Transform);
+LCRYPTO_USED(GOST2814789IMIT);
+LCRYPTO_USED(GOSTR341194_Init);
+LCRYPTO_USED(GOSTR341194_Update);
+LCRYPTO_USED(GOSTR341194_Final);
+LCRYPTO_USED(GOSTR341194_Transform);
+LCRYPTO_USED(GOSTR341194);
+LCRYPTO_USED(STREEBOG256_Init);
+LCRYPTO_USED(STREEBOG256_Update);
+LCRYPTO_USED(STREEBOG256_Final);
+LCRYPTO_USED(STREEBOG256);
+LCRYPTO_USED(STREEBOG512_Init);
+LCRYPTO_USED(STREEBOG512_Update);
+LCRYPTO_USED(STREEBOG512_Final);
+LCRYPTO_USED(STREEBOG512_Transform);
+LCRYPTO_USED(STREEBOG512);
+LCRYPTO_USED(GOST_KEY_new);
+LCRYPTO_USED(GOST_KEY_free);
+LCRYPTO_USED(GOST_KEY_check_key);
+LCRYPTO_USED(GOST_KEY_set_public_key_affine_coordinates);
+LCRYPTO_USED(GOST_KEY_get0_group);
+LCRYPTO_USED(GOST_KEY_set_group);
+LCRYPTO_USED(GOST_KEY_get_digest);
+LCRYPTO_USED(GOST_KEY_set_digest);
+LCRYPTO_USED(GOST_KEY_get0_private_key);
+LCRYPTO_USED(GOST_KEY_set_private_key);
+LCRYPTO_USED(GOST_KEY_get0_public_key);
+LCRYPTO_USED(GOST_KEY_set_public_key);
+LCRYPTO_USED(GOST_KEY_get_size);
+LCRYPTO_USED(ERR_load_GOST_strings);
+
+#endif /* _LIBCRYPTO_GOST_H */
diff --git a/crypto/hidden/openssl/hkdf.h b/crypto/hidden/openssl/hkdf.h
new file mode 100644
index 0000000..0c01cf3
--- /dev/null
+++ b/crypto/hidden/openssl/hkdf.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: hkdf.h,v 1.2 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_HKDF_H
+#define _LIBCRYPTO_HKDF_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/hkdf.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(HKDF);
+LCRYPTO_USED(HKDF_extract);
+LCRYPTO_USED(HKDF_expand);
+
+#endif /* _LIBCRYPTO_HKDF_H */
diff --git a/crypto/hidden/openssl/hmac.h b/crypto/hidden/openssl/hmac.h
new file mode 100644
index 0000000..ecf8aa9
--- /dev/null
+++ b/crypto/hidden/openssl/hmac.h
@@ -0,0 +1,40 @@
+/*	$OpenBSD: hmac.h,v 1.2 2023/07/05 21:14:54 bcook Exp $	*/
+/*
+ * Copyright (c) 2016 Philip Guenther 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_HMAC_H_
+#define _LIBCRYPTO_HMAC_H_
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/hmac.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(HMAC_CTX_new);
+LCRYPTO_USED(HMAC_CTX_free);
+LCRYPTO_UNUSED(HMAC_CTX_reset);
+LCRYPTO_UNUSED(HMAC_Init);
+LCRYPTO_USED(HMAC_Init_ex);
+LCRYPTO_USED(HMAC_Update);
+LCRYPTO_USED(HMAC_Final);
+LCRYPTO_USED(HMAC);
+LCRYPTO_USED(HMAC_CTX_copy);
+LCRYPTO_USED(HMAC_CTX_set_flags);
+LCRYPTO_USED(HMAC_CTX_get_md);
+
+#endif /* _LIBCRYPTO_HMAC_H_ */
diff --git a/crypto/hidden/openssl/idea.h b/crypto/hidden/openssl/idea.h
new file mode 100644
index 0000000..93b20a9
--- /dev/null
+++ b/crypto/hidden/openssl/idea.h
@@ -0,0 +1,36 @@
+/* $OpenBSD: idea.h,v 1.2 2023/07/29 03:13:38 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_IDEA_H
+#define _LIBCRYPTO_IDEA_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/idea.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(idea_ecb_encrypt);
+LCRYPTO_USED(idea_set_encrypt_key);
+LCRYPTO_USED(idea_set_decrypt_key);
+LCRYPTO_USED(idea_cbc_encrypt);
+LCRYPTO_USED(idea_cfb64_encrypt);
+LCRYPTO_USED(idea_ofb64_encrypt);
+LCRYPTO_USED(idea_encrypt);
+
+#endif /* _LIBCRYPTO_IDEA_H */
diff --git a/crypto/hidden/openssl/lhash.h b/crypto/hidden/openssl/lhash.h
new file mode 100644
index 0000000..151f154
--- /dev/null
+++ b/crypto/hidden/openssl/lhash.h
@@ -0,0 +1,44 @@
+/* $OpenBSD: lhash.h,v 1.2 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_LHASH_H
+#define _LIBCRYPTO_LHASH_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/lhash.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(lh_new);
+LCRYPTO_USED(lh_free);
+LCRYPTO_USED(lh_insert);
+LCRYPTO_USED(lh_delete);
+LCRYPTO_USED(lh_retrieve);
+LCRYPTO_USED(lh_doall);
+LCRYPTO_USED(lh_doall_arg);
+LCRYPTO_USED(lh_strhash);
+LCRYPTO_USED(lh_num_items);
+LCRYPTO_USED(lh_stats);
+LCRYPTO_USED(lh_node_stats);
+LCRYPTO_USED(lh_node_usage_stats);
+LCRYPTO_USED(lh_stats_bio);
+LCRYPTO_USED(lh_node_stats_bio);
+LCRYPTO_USED(lh_node_usage_stats_bio);
+
+#endif /* _LIBCRYPTO_LHASH_H */
diff --git a/crypto/hidden/openssl/md4.h b/crypto/hidden/openssl/md4.h
new file mode 100644
index 0000000..c5fc22c
--- /dev/null
+++ b/crypto/hidden/openssl/md4.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: md4.h,v 1.1 2023/07/08 10:45:57 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_MD4_H
+#define _LIBCRYPTO_MD4_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/md4.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(MD4_Init);
+LCRYPTO_USED(MD4_Update);
+LCRYPTO_USED(MD4_Final);
+LCRYPTO_USED(MD4);
+LCRYPTO_USED(MD4_Transform);
+
+#endif /* _LIBCRYPTO_MD4_H */
diff --git a/crypto/hidden/openssl/md5.h b/crypto/hidden/openssl/md5.h
new file mode 100644
index 0000000..3dfade7
--- /dev/null
+++ b/crypto/hidden/openssl/md5.h
@@ -0,0 +1,34 @@
+/* $OpenBSD: md5.h,v 1.1 2023/07/08 10:45:57 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_MD5_H
+#define _LIBCRYPTO_MD5_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/md5.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(MD5_Init);
+LCRYPTO_USED(MD5_Update);
+LCRYPTO_USED(MD5_Final);
+LCRYPTO_USED(MD5);
+LCRYPTO_USED(MD5_Transform);
+
+#endif /* _LIBCRYPTO_MD5_H */
diff --git a/crypto/hidden/openssl/modes.h b/crypto/hidden/openssl/modes.h
new file mode 100644
index 0000000..4162861
--- /dev/null
+++ b/crypto/hidden/openssl/modes.h
@@ -0,0 +1,57 @@
+/* $OpenBSD: modes.h,v 1.1 2023/07/08 14:56:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_MODES_H
+#define _LIBCRYPTO_MODES_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/modes.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CRYPTO_cbc128_encrypt);
+LCRYPTO_USED(CRYPTO_cbc128_decrypt);
+LCRYPTO_USED(CRYPTO_ctr128_encrypt);
+LCRYPTO_USED(CRYPTO_ctr128_encrypt_ctr32);
+LCRYPTO_USED(CRYPTO_ofb128_encrypt);
+LCRYPTO_USED(CRYPTO_cfb128_encrypt);
+LCRYPTO_USED(CRYPTO_cfb128_8_encrypt);
+LCRYPTO_USED(CRYPTO_cfb128_1_encrypt);
+LCRYPTO_USED(CRYPTO_gcm128_new);
+LCRYPTO_USED(CRYPTO_gcm128_init);
+LCRYPTO_USED(CRYPTO_gcm128_setiv);
+LCRYPTO_USED(CRYPTO_gcm128_aad);
+LCRYPTO_USED(CRYPTO_gcm128_encrypt);
+LCRYPTO_USED(CRYPTO_gcm128_decrypt);
+LCRYPTO_USED(CRYPTO_gcm128_encrypt_ctr32);
+LCRYPTO_USED(CRYPTO_gcm128_decrypt_ctr32);
+LCRYPTO_USED(CRYPTO_gcm128_finish);
+LCRYPTO_USED(CRYPTO_gcm128_tag);
+LCRYPTO_USED(CRYPTO_gcm128_release);
+LCRYPTO_USED(CRYPTO_ccm128_init);
+LCRYPTO_USED(CRYPTO_ccm128_setiv);
+LCRYPTO_USED(CRYPTO_ccm128_aad);
+LCRYPTO_USED(CRYPTO_ccm128_encrypt);
+LCRYPTO_USED(CRYPTO_ccm128_decrypt);
+LCRYPTO_USED(CRYPTO_ccm128_encrypt_ccm64);
+LCRYPTO_USED(CRYPTO_ccm128_decrypt_ccm64);
+LCRYPTO_USED(CRYPTO_ccm128_tag);
+LCRYPTO_USED(CRYPTO_xts128_encrypt);
+
+#endif /* _LIBCRYPTO_MODES_H */
diff --git a/crypto/hidden/openssl/objects.h b/crypto/hidden/openssl/objects.h
new file mode 100644
index 0000000..ba5bf8e
--- /dev/null
+++ b/crypto/hidden/openssl/objects.h
@@ -0,0 +1,59 @@
+/* $OpenBSD: objects.h,v 1.2 2023/07/28 10:25:05 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_OBJECTS_H
+#define _LIBCRYPTO_OBJECTS_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/objects.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(OBJ_NAME_init);
+LCRYPTO_USED(OBJ_NAME_new_index);
+LCRYPTO_USED(OBJ_NAME_get);
+LCRYPTO_USED(OBJ_NAME_add);
+LCRYPTO_USED(OBJ_NAME_remove);
+LCRYPTO_USED(OBJ_NAME_cleanup);
+LCRYPTO_USED(OBJ_NAME_do_all);
+LCRYPTO_USED(OBJ_NAME_do_all_sorted);
+LCRYPTO_USED(OBJ_dup);
+LCRYPTO_USED(OBJ_nid2obj);
+LCRYPTO_USED(OBJ_nid2ln);
+LCRYPTO_USED(OBJ_nid2sn);
+LCRYPTO_USED(OBJ_obj2nid);
+LCRYPTO_USED(OBJ_txt2obj);
+LCRYPTO_USED(OBJ_obj2txt);
+LCRYPTO_USED(OBJ_txt2nid);
+LCRYPTO_USED(OBJ_ln2nid);
+LCRYPTO_USED(OBJ_sn2nid);
+LCRYPTO_USED(OBJ_cmp);
+LCRYPTO_USED(OBJ_bsearch_);
+LCRYPTO_USED(OBJ_new_nid);
+LCRYPTO_USED(OBJ_add_object);
+LCRYPTO_USED(OBJ_create);
+LCRYPTO_USED(OBJ_cleanup);
+LCRYPTO_USED(OBJ_create_objects);
+LCRYPTO_USED(OBJ_length);
+LCRYPTO_USED(OBJ_get0_data);
+LCRYPTO_USED(OBJ_find_sigid_algs);
+LCRYPTO_USED(OBJ_find_sigid_by_algs);
+LCRYPTO_USED(ERR_load_OBJ_strings);
+
+#endif /* _LIBCRYPTO_OBJECTS_H */
diff --git a/crypto/hidden/openssl/ocsp.h b/crypto/hidden/openssl/ocsp.h
new file mode 100644
index 0000000..6546962
--- /dev/null
+++ b/crypto/hidden/openssl/ocsp.h
@@ -0,0 +1,190 @@
+/* $OpenBSD: ocsp.h,v 1.1 2023/07/08 10:44:00 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_OCSP_H
+#define _LIBCRYPTO_OCSP_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/ocsp.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(OCSP_RESPID_new);
+LCRYPTO_USED(OCSP_RESPID_free);
+LCRYPTO_USED(d2i_OCSP_RESPID);
+LCRYPTO_USED(i2d_OCSP_RESPID);
+LCRYPTO_USED(OCSP_CERTID_dup);
+LCRYPTO_USED(OCSP_sendreq_bio);
+LCRYPTO_USED(OCSP_sendreq_new);
+LCRYPTO_USED(OCSP_sendreq_nbio);
+LCRYPTO_USED(OCSP_REQ_CTX_free);
+LCRYPTO_USED(OCSP_REQ_CTX_set1_req);
+LCRYPTO_USED(OCSP_REQ_CTX_add1_header);
+LCRYPTO_USED(OCSP_cert_to_id);
+LCRYPTO_USED(OCSP_cert_id_new);
+LCRYPTO_USED(OCSP_request_add0_id);
+LCRYPTO_USED(OCSP_request_add1_nonce);
+LCRYPTO_USED(OCSP_basic_add1_nonce);
+LCRYPTO_USED(OCSP_check_nonce);
+LCRYPTO_USED(OCSP_copy_nonce);
+LCRYPTO_USED(OCSP_request_set1_name);
+LCRYPTO_USED(OCSP_request_add1_cert);
+LCRYPTO_USED(OCSP_request_sign);
+LCRYPTO_USED(OCSP_response_status);
+LCRYPTO_USED(OCSP_response_get1_basic);
+LCRYPTO_USED(OCSP_resp_get0_signature);
+LCRYPTO_USED(OCSP_resp_get0_tbs_sigalg);
+LCRYPTO_USED(OCSP_resp_get0_respdata);
+LCRYPTO_USED(OCSP_resp_get0_signer);
+LCRYPTO_USED(OCSP_resp_count);
+LCRYPTO_USED(OCSP_resp_get0);
+LCRYPTO_USED(OCSP_resp_get0_produced_at);
+LCRYPTO_USED(OCSP_resp_get0_certs);
+LCRYPTO_USED(OCSP_resp_get0_id);
+LCRYPTO_USED(OCSP_resp_find);
+LCRYPTO_USED(OCSP_single_get0_status);
+LCRYPTO_USED(OCSP_resp_find_status);
+LCRYPTO_USED(OCSP_check_validity);
+LCRYPTO_USED(OCSP_request_verify);
+LCRYPTO_USED(OCSP_parse_url);
+LCRYPTO_USED(OCSP_id_issuer_cmp);
+LCRYPTO_USED(OCSP_id_cmp);
+LCRYPTO_USED(OCSP_request_onereq_count);
+LCRYPTO_USED(OCSP_request_onereq_get0);
+LCRYPTO_USED(OCSP_onereq_get0_id);
+LCRYPTO_USED(OCSP_id_get0_info);
+LCRYPTO_USED(OCSP_request_is_signed);
+LCRYPTO_USED(OCSP_response_create);
+LCRYPTO_USED(OCSP_basic_add1_status);
+LCRYPTO_USED(OCSP_basic_add1_cert);
+LCRYPTO_USED(OCSP_basic_sign);
+LCRYPTO_USED(OCSP_crlID_new);
+LCRYPTO_USED(OCSP_accept_responses_new);
+LCRYPTO_USED(OCSP_archive_cutoff_new);
+LCRYPTO_USED(OCSP_url_svcloc_new);
+LCRYPTO_USED(OCSP_REQUEST_get_ext_count);
+LCRYPTO_USED(OCSP_REQUEST_get_ext_by_NID);
+LCRYPTO_USED(OCSP_REQUEST_get_ext_by_OBJ);
+LCRYPTO_USED(OCSP_REQUEST_get_ext_by_critical);
+LCRYPTO_USED(OCSP_REQUEST_get_ext);
+LCRYPTO_USED(OCSP_REQUEST_delete_ext);
+LCRYPTO_USED(OCSP_REQUEST_get1_ext_d2i);
+LCRYPTO_USED(OCSP_REQUEST_add1_ext_i2d);
+LCRYPTO_USED(OCSP_REQUEST_add_ext);
+LCRYPTO_USED(OCSP_ONEREQ_get_ext_count);
+LCRYPTO_USED(OCSP_ONEREQ_get_ext_by_NID);
+LCRYPTO_USED(OCSP_ONEREQ_get_ext_by_OBJ);
+LCRYPTO_USED(OCSP_ONEREQ_get_ext_by_critical);
+LCRYPTO_USED(OCSP_ONEREQ_get_ext);
+LCRYPTO_USED(OCSP_ONEREQ_delete_ext);
+LCRYPTO_USED(OCSP_ONEREQ_get1_ext_d2i);
+LCRYPTO_USED(OCSP_ONEREQ_add1_ext_i2d);
+LCRYPTO_USED(OCSP_ONEREQ_add_ext);
+LCRYPTO_USED(OCSP_BASICRESP_get_ext_count);
+LCRYPTO_USED(OCSP_BASICRESP_get_ext_by_NID);
+LCRYPTO_USED(OCSP_BASICRESP_get_ext_by_OBJ);
+LCRYPTO_USED(OCSP_BASICRESP_get_ext_by_critical);
+LCRYPTO_USED(OCSP_BASICRESP_get_ext);
+LCRYPTO_USED(OCSP_BASICRESP_delete_ext);
+LCRYPTO_USED(OCSP_BASICRESP_get1_ext_d2i);
+LCRYPTO_USED(OCSP_BASICRESP_add1_ext_i2d);
+LCRYPTO_USED(OCSP_BASICRESP_add_ext);
+LCRYPTO_USED(OCSP_SINGLERESP_get_ext_count);
+LCRYPTO_USED(OCSP_SINGLERESP_get_ext_by_NID);
+LCRYPTO_USED(OCSP_SINGLERESP_get_ext_by_OBJ);
+LCRYPTO_USED(OCSP_SINGLERESP_get_ext_by_critical);
+LCRYPTO_USED(OCSP_SINGLERESP_get_ext);
+LCRYPTO_USED(OCSP_SINGLERESP_delete_ext);
+LCRYPTO_USED(OCSP_SINGLERESP_get1_ext_d2i);
+LCRYPTO_USED(OCSP_SINGLERESP_add1_ext_i2d);
+LCRYPTO_USED(OCSP_SINGLERESP_add_ext);
+LCRYPTO_USED(OCSP_SINGLERESP_get0_id);
+LCRYPTO_USED(OCSP_SINGLERESP_new);
+LCRYPTO_USED(OCSP_SINGLERESP_free);
+LCRYPTO_USED(d2i_OCSP_SINGLERESP);
+LCRYPTO_USED(i2d_OCSP_SINGLERESP);
+LCRYPTO_USED(OCSP_CERTSTATUS_new);
+LCRYPTO_USED(OCSP_CERTSTATUS_free);
+LCRYPTO_USED(d2i_OCSP_CERTSTATUS);
+LCRYPTO_USED(i2d_OCSP_CERTSTATUS);
+LCRYPTO_USED(OCSP_REVOKEDINFO_new);
+LCRYPTO_USED(OCSP_REVOKEDINFO_free);
+LCRYPTO_USED(d2i_OCSP_REVOKEDINFO);
+LCRYPTO_USED(i2d_OCSP_REVOKEDINFO);
+LCRYPTO_USED(OCSP_BASICRESP_new);
+LCRYPTO_USED(OCSP_BASICRESP_free);
+LCRYPTO_USED(d2i_OCSP_BASICRESP);
+LCRYPTO_USED(i2d_OCSP_BASICRESP);
+LCRYPTO_USED(OCSP_RESPDATA_new);
+LCRYPTO_USED(OCSP_RESPDATA_free);
+LCRYPTO_USED(d2i_OCSP_RESPDATA);
+LCRYPTO_USED(i2d_OCSP_RESPDATA);
+LCRYPTO_USED(OCSP_RESPID_new);
+LCRYPTO_USED(OCSP_RESPID_free);
+LCRYPTO_USED(d2i_OCSP_RESPID);
+LCRYPTO_USED(i2d_OCSP_RESPID);
+LCRYPTO_USED(OCSP_RESPONSE_new);
+LCRYPTO_USED(OCSP_RESPONSE_free);
+LCRYPTO_USED(d2i_OCSP_RESPONSE);
+LCRYPTO_USED(i2d_OCSP_RESPONSE);
+LCRYPTO_USED(d2i_OCSP_RESPONSE_bio);
+LCRYPTO_USED(i2d_OCSP_RESPONSE_bio);
+LCRYPTO_USED(OCSP_RESPBYTES_new);
+LCRYPTO_USED(OCSP_RESPBYTES_free);
+LCRYPTO_USED(d2i_OCSP_RESPBYTES);
+LCRYPTO_USED(i2d_OCSP_RESPBYTES);
+LCRYPTO_USED(OCSP_ONEREQ_new);
+LCRYPTO_USED(OCSP_ONEREQ_free);
+LCRYPTO_USED(d2i_OCSP_ONEREQ);
+LCRYPTO_USED(i2d_OCSP_ONEREQ);
+LCRYPTO_USED(OCSP_CERTID_new);
+LCRYPTO_USED(OCSP_CERTID_free);
+LCRYPTO_USED(d2i_OCSP_CERTID);
+LCRYPTO_USED(i2d_OCSP_CERTID);
+LCRYPTO_USED(OCSP_REQUEST_new);
+LCRYPTO_USED(OCSP_REQUEST_free);
+LCRYPTO_USED(d2i_OCSP_REQUEST);
+LCRYPTO_USED(i2d_OCSP_REQUEST);
+LCRYPTO_USED(d2i_OCSP_REQUEST_bio);
+LCRYPTO_USED(i2d_OCSP_REQUEST_bio);
+LCRYPTO_USED(OCSP_SIGNATURE_new);
+LCRYPTO_USED(OCSP_SIGNATURE_free);
+LCRYPTO_USED(d2i_OCSP_SIGNATURE);
+LCRYPTO_USED(i2d_OCSP_SIGNATURE);
+LCRYPTO_USED(OCSP_REQINFO_new);
+LCRYPTO_USED(OCSP_REQINFO_free);
+LCRYPTO_USED(d2i_OCSP_REQINFO);
+LCRYPTO_USED(i2d_OCSP_REQINFO);
+LCRYPTO_USED(OCSP_CRLID_new);
+LCRYPTO_USED(OCSP_CRLID_free);
+LCRYPTO_USED(d2i_OCSP_CRLID);
+LCRYPTO_USED(i2d_OCSP_CRLID);
+LCRYPTO_USED(OCSP_SERVICELOC_new);
+LCRYPTO_USED(OCSP_SERVICELOC_free);
+LCRYPTO_USED(d2i_OCSP_SERVICELOC);
+LCRYPTO_USED(i2d_OCSP_SERVICELOC);
+LCRYPTO_USED(OCSP_response_status_str);
+LCRYPTO_USED(OCSP_cert_status_str);
+LCRYPTO_USED(OCSP_crl_reason_str);
+LCRYPTO_USED(OCSP_REQUEST_print);
+LCRYPTO_USED(OCSP_RESPONSE_print);
+LCRYPTO_USED(OCSP_basic_verify);
+LCRYPTO_USED(ERR_load_OCSP_strings);
+
+#endif /* _LIBCRYPTO_OCSP_H */
diff --git a/crypto/hidden/openssl/pem.h b/crypto/hidden/openssl/pem.h
new file mode 100644
index 0000000..5838f07
--- /dev/null
+++ b/crypto/hidden/openssl/pem.h
@@ -0,0 +1,149 @@
+/* $OpenBSD: pem.h,v 1.2 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_PEM_H
+#define _LIBCRYPTO_PEM_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/pem.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(PEM_get_EVP_CIPHER_INFO);
+LCRYPTO_USED(PEM_do_header);
+LCRYPTO_USED(PEM_read_bio);
+LCRYPTO_USED(PEM_write_bio);
+LCRYPTO_USED(PEM_bytes_read_bio);
+LCRYPTO_USED(PEM_ASN1_read_bio);
+LCRYPTO_USED(PEM_ASN1_write_bio);
+LCRYPTO_USED(PEM_X509_INFO_read_bio);
+LCRYPTO_USED(PEM_X509_INFO_write_bio);
+LCRYPTO_USED(PEM_read);
+LCRYPTO_USED(PEM_write);
+LCRYPTO_USED(PEM_ASN1_read);
+LCRYPTO_USED(PEM_ASN1_write);
+LCRYPTO_USED(PEM_X509_INFO_read);
+LCRYPTO_USED(PEM_SignInit);
+LCRYPTO_USED(PEM_SignUpdate);
+LCRYPTO_USED(PEM_SignFinal);
+LCRYPTO_USED(PEM_def_callback);
+LCRYPTO_USED(PEM_proc_type);
+LCRYPTO_USED(PEM_dek_info);
+LCRYPTO_USED(PEM_read_X509);
+LCRYPTO_USED(PEM_read_bio_X509);
+LCRYPTO_USED(PEM_write_X509);
+LCRYPTO_USED(PEM_write_bio_X509);
+LCRYPTO_USED(PEM_read_X509_AUX);
+LCRYPTO_USED(PEM_read_bio_X509_AUX);
+LCRYPTO_USED(PEM_write_X509_AUX);
+LCRYPTO_USED(PEM_write_bio_X509_AUX);
+LCRYPTO_USED(PEM_read_X509_REQ);
+LCRYPTO_USED(PEM_read_bio_X509_REQ);
+LCRYPTO_USED(PEM_write_X509_REQ);
+LCRYPTO_USED(PEM_write_bio_X509_REQ);
+LCRYPTO_USED(PEM_write_X509_REQ_NEW);
+LCRYPTO_USED(PEM_write_bio_X509_REQ_NEW);
+LCRYPTO_USED(PEM_read_X509_CRL);
+LCRYPTO_USED(PEM_read_bio_X509_CRL);
+LCRYPTO_USED(PEM_write_X509_CRL);
+LCRYPTO_USED(PEM_write_bio_X509_CRL);
+LCRYPTO_USED(PEM_read_PKCS7);
+LCRYPTO_USED(PEM_read_bio_PKCS7);
+LCRYPTO_USED(PEM_write_PKCS7);
+LCRYPTO_USED(PEM_write_bio_PKCS7);
+LCRYPTO_USED(PEM_read_PKCS8);
+LCRYPTO_USED(PEM_read_bio_PKCS8);
+LCRYPTO_USED(PEM_write_PKCS8);
+LCRYPTO_USED(PEM_write_bio_PKCS8);
+LCRYPTO_USED(PEM_read_PKCS8_PRIV_KEY_INFO);
+LCRYPTO_USED(PEM_read_bio_PKCS8_PRIV_KEY_INFO);
+LCRYPTO_USED(PEM_write_PKCS8_PRIV_KEY_INFO);
+LCRYPTO_USED(PEM_write_bio_PKCS8_PRIV_KEY_INFO);
+LCRYPTO_USED(PEM_read_RSAPrivateKey);
+LCRYPTO_USED(PEM_read_bio_RSAPrivateKey);
+LCRYPTO_USED(PEM_write_RSAPrivateKey);
+LCRYPTO_USED(PEM_write_bio_RSAPrivateKey);
+LCRYPTO_USED(PEM_read_RSAPublicKey);
+LCRYPTO_USED(PEM_read_bio_RSAPublicKey);
+LCRYPTO_USED(PEM_write_RSAPublicKey);
+LCRYPTO_USED(PEM_write_bio_RSAPublicKey);
+LCRYPTO_USED(PEM_read_RSA_PUBKEY);
+LCRYPTO_USED(PEM_read_bio_RSA_PUBKEY);
+LCRYPTO_USED(PEM_write_RSA_PUBKEY);
+LCRYPTO_USED(PEM_write_bio_RSA_PUBKEY);
+LCRYPTO_USED(PEM_read_DSAPrivateKey);
+LCRYPTO_USED(PEM_read_bio_DSAPrivateKey);
+LCRYPTO_USED(PEM_write_DSAPrivateKey);
+LCRYPTO_USED(PEM_write_bio_DSAPrivateKey);
+LCRYPTO_USED(PEM_read_DSA_PUBKEY);
+LCRYPTO_USED(PEM_read_bio_DSA_PUBKEY);
+LCRYPTO_USED(PEM_write_DSA_PUBKEY);
+LCRYPTO_USED(PEM_write_bio_DSA_PUBKEY);
+LCRYPTO_USED(PEM_read_DSAparams);
+LCRYPTO_USED(PEM_read_bio_DSAparams);
+LCRYPTO_USED(PEM_write_DSAparams);
+LCRYPTO_USED(PEM_write_bio_DSAparams);
+LCRYPTO_USED(PEM_read_ECPKParameters);
+LCRYPTO_USED(PEM_read_bio_ECPKParameters);
+LCRYPTO_USED(PEM_write_ECPKParameters);
+LCRYPTO_USED(PEM_write_bio_ECPKParameters);
+LCRYPTO_USED(PEM_read_ECPrivateKey);
+LCRYPTO_USED(PEM_read_bio_ECPrivateKey);
+LCRYPTO_USED(PEM_write_ECPrivateKey);
+LCRYPTO_USED(PEM_write_bio_ECPrivateKey);
+LCRYPTO_USED(PEM_read_EC_PUBKEY);
+LCRYPTO_USED(PEM_read_bio_EC_PUBKEY);
+LCRYPTO_USED(PEM_write_EC_PUBKEY);
+LCRYPTO_USED(PEM_write_bio_EC_PUBKEY);
+LCRYPTO_USED(PEM_read_DHparams);
+LCRYPTO_USED(PEM_read_bio_DHparams);
+LCRYPTO_USED(PEM_write_DHparams);
+LCRYPTO_USED(PEM_write_bio_DHparams);
+LCRYPTO_USED(PEM_read_PrivateKey);
+LCRYPTO_USED(PEM_read_bio_PrivateKey);
+LCRYPTO_USED(PEM_write_PrivateKey);
+LCRYPTO_USED(PEM_write_bio_PrivateKey);
+LCRYPTO_USED(PEM_read_PUBKEY);
+LCRYPTO_USED(PEM_read_bio_PUBKEY);
+LCRYPTO_USED(PEM_write_PUBKEY);
+LCRYPTO_USED(PEM_write_bio_PUBKEY);
+LCRYPTO_USED(PEM_write_bio_PrivateKey_traditional);
+LCRYPTO_USED(PEM_write_bio_PKCS8PrivateKey_nid);
+LCRYPTO_USED(PEM_write_bio_PKCS8PrivateKey);
+LCRYPTO_USED(i2d_PKCS8PrivateKey_bio);
+LCRYPTO_USED(i2d_PKCS8PrivateKey_nid_bio);
+LCRYPTO_USED(d2i_PKCS8PrivateKey_bio);
+LCRYPTO_USED(i2d_PKCS8PrivateKey_fp);
+LCRYPTO_USED(i2d_PKCS8PrivateKey_nid_fp);
+LCRYPTO_USED(PEM_write_PKCS8PrivateKey_nid);
+LCRYPTO_USED(d2i_PKCS8PrivateKey_fp);
+LCRYPTO_USED(PEM_write_PKCS8PrivateKey);
+LCRYPTO_USED(PEM_read_bio_Parameters);
+LCRYPTO_USED(PEM_write_bio_Parameters);
+LCRYPTO_USED(b2i_PrivateKey);
+LCRYPTO_USED(b2i_PublicKey);
+LCRYPTO_USED(b2i_PrivateKey_bio);
+LCRYPTO_USED(b2i_PublicKey_bio);
+LCRYPTO_USED(i2b_PrivateKey_bio);
+LCRYPTO_USED(i2b_PublicKey_bio);
+LCRYPTO_USED(b2i_PVK_bio);
+LCRYPTO_USED(i2b_PVK_bio);
+LCRYPTO_USED(ERR_load_PEM_strings);
+
+#endif /* _LIBCRYPTO_PEM_H */
diff --git a/crypto/hidden/openssl/pkcs12.h b/crypto/hidden/openssl/pkcs12.h
new file mode 100644
index 0000000..9a2dffa
--- /dev/null
+++ b/crypto/hidden/openssl/pkcs12.h
@@ -0,0 +1,106 @@
+/* $OpenBSD: pkcs12.h,v 1.2 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_PKCS12_H
+#define _LIBCRYPTO_PKCS12_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/pkcs12.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_attr);
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_attrs);
+LCRYPTO_USED(PKCS12_SAFEBAG_get_nid);
+LCRYPTO_USED(PKCS12_SAFEBAG_get_bag_nid);
+LCRYPTO_USED(PKCS12_SAFEBAG_get1_cert);
+LCRYPTO_USED(PKCS12_SAFEBAG_get1_crl);
+LCRYPTO_USED(PKCS8_get_attr);
+LCRYPTO_USED(PKCS12_mac_present);
+LCRYPTO_USED(PKCS12_get0_mac);
+LCRYPTO_USED(PKCS12_SAFEBAG_create_cert);
+LCRYPTO_USED(PKCS12_SAFEBAG_create_crl);
+LCRYPTO_USED(PKCS12_SAFEBAG_create0_p8inf);
+LCRYPTO_USED(PKCS12_SAFEBAG_create0_pkcs8);
+LCRYPTO_USED(PKCS12_SAFEBAG_create_pkcs8_encrypt);
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_p8inf);
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_pkcs8);
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_safes);
+LCRYPTO_USED(PKCS12_SAFEBAG_get0_type);
+LCRYPTO_USED(PKCS12_item_pack_safebag);
+LCRYPTO_USED(PKCS8_decrypt);
+LCRYPTO_USED(PKCS12_decrypt_skey);
+LCRYPTO_USED(PKCS8_encrypt);
+LCRYPTO_USED(PKCS12_pack_p7data);
+LCRYPTO_USED(PKCS12_unpack_p7data);
+LCRYPTO_USED(PKCS12_pack_p7encdata);
+LCRYPTO_USED(PKCS12_unpack_p7encdata);
+LCRYPTO_USED(PKCS12_pack_authsafes);
+LCRYPTO_USED(PKCS12_unpack_authsafes);
+LCRYPTO_USED(PKCS12_add_localkeyid);
+LCRYPTO_USED(PKCS12_add_friendlyname_asc);
+LCRYPTO_USED(PKCS12_add_CSPName_asc);
+LCRYPTO_USED(PKCS12_add_friendlyname_uni);
+LCRYPTO_USED(PKCS8_add_keyusage);
+LCRYPTO_USED(PKCS12_get_attr_gen);
+LCRYPTO_USED(PKCS12_get_friendlyname);
+LCRYPTO_USED(PKCS12_pbe_crypt);
+LCRYPTO_USED(PKCS12_item_decrypt_d2i);
+LCRYPTO_USED(PKCS12_item_i2d_encrypt);
+LCRYPTO_USED(PKCS12_init);
+LCRYPTO_USED(PKCS12_key_gen_asc);
+LCRYPTO_USED(PKCS12_key_gen_uni);
+LCRYPTO_USED(PKCS12_PBE_keyivgen);
+LCRYPTO_USED(PKCS12_gen_mac);
+LCRYPTO_USED(PKCS12_verify_mac);
+LCRYPTO_USED(PKCS12_set_mac);
+LCRYPTO_USED(PKCS12_setup_mac);
+LCRYPTO_USED(OPENSSL_asc2uni);
+LCRYPTO_USED(OPENSSL_uni2asc);
+LCRYPTO_USED(PKCS12_new);
+LCRYPTO_USED(PKCS12_free);
+LCRYPTO_USED(d2i_PKCS12);
+LCRYPTO_USED(i2d_PKCS12);
+LCRYPTO_USED(PKCS12_MAC_DATA_new);
+LCRYPTO_USED(PKCS12_MAC_DATA_free);
+LCRYPTO_USED(d2i_PKCS12_MAC_DATA);
+LCRYPTO_USED(i2d_PKCS12_MAC_DATA);
+LCRYPTO_USED(PKCS12_SAFEBAG_new);
+LCRYPTO_USED(PKCS12_SAFEBAG_free);
+LCRYPTO_USED(d2i_PKCS12_SAFEBAG);
+LCRYPTO_USED(i2d_PKCS12_SAFEBAG);
+LCRYPTO_USED(PKCS12_BAGS_new);
+LCRYPTO_USED(PKCS12_BAGS_free);
+LCRYPTO_USED(d2i_PKCS12_BAGS);
+LCRYPTO_USED(i2d_PKCS12_BAGS);
+LCRYPTO_USED(PKCS12_PBE_add);
+LCRYPTO_USED(PKCS12_parse);
+LCRYPTO_USED(PKCS12_create);
+LCRYPTO_USED(PKCS12_add_cert);
+LCRYPTO_USED(PKCS12_add_key);
+LCRYPTO_USED(PKCS12_add_safe);
+LCRYPTO_USED(PKCS12_add_safes);
+LCRYPTO_USED(i2d_PKCS12_bio);
+LCRYPTO_USED(i2d_PKCS12_fp);
+LCRYPTO_USED(d2i_PKCS12_bio);
+LCRYPTO_USED(d2i_PKCS12_fp);
+LCRYPTO_USED(PKCS12_newpass);
+LCRYPTO_USED(ERR_load_PKCS12_strings);
+
+#endif /* _LIBCRYPTO_PKCS12_H */
diff --git a/crypto/hidden/openssl/pkcs7.h b/crypto/hidden/openssl/pkcs7.h
new file mode 100644
index 0000000..f12b5df
--- /dev/null
+++ b/crypto/hidden/openssl/pkcs7.h
@@ -0,0 +1,129 @@
+/* $OpenBSD: pkcs7.h,v 1.3 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_PKCS7_H
+#define _LIBCRYPTO_PKCS7_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/pkcs7.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(PKCS7_ISSUER_AND_SERIAL_new);
+LCRYPTO_USED(PKCS7_ISSUER_AND_SERIAL_free);
+LCRYPTO_USED(d2i_PKCS7_ISSUER_AND_SERIAL);
+LCRYPTO_USED(i2d_PKCS7_ISSUER_AND_SERIAL);
+LCRYPTO_USED(PKCS7_ISSUER_AND_SERIAL_digest);
+LCRYPTO_USED(d2i_PKCS7_fp);
+LCRYPTO_USED(i2d_PKCS7_fp);
+LCRYPTO_USED(PKCS7_dup);
+LCRYPTO_USED(d2i_PKCS7_bio);
+LCRYPTO_USED(i2d_PKCS7_bio);
+LCRYPTO_USED(i2d_PKCS7_bio_stream);
+LCRYPTO_USED(PEM_write_bio_PKCS7_stream);
+LCRYPTO_USED(PKCS7_SIGNER_INFO_new);
+LCRYPTO_USED(PKCS7_SIGNER_INFO_free);
+LCRYPTO_USED(d2i_PKCS7_SIGNER_INFO);
+LCRYPTO_USED(i2d_PKCS7_SIGNER_INFO);
+LCRYPTO_USED(PKCS7_RECIP_INFO_new);
+LCRYPTO_USED(PKCS7_RECIP_INFO_free);
+LCRYPTO_USED(d2i_PKCS7_RECIP_INFO);
+LCRYPTO_USED(i2d_PKCS7_RECIP_INFO);
+LCRYPTO_USED(PKCS7_SIGNED_new);
+LCRYPTO_USED(PKCS7_SIGNED_free);
+LCRYPTO_USED(d2i_PKCS7_SIGNED);
+LCRYPTO_USED(i2d_PKCS7_SIGNED);
+LCRYPTO_USED(PKCS7_ENC_CONTENT_new);
+LCRYPTO_USED(PKCS7_ENC_CONTENT_free);
+LCRYPTO_USED(d2i_PKCS7_ENC_CONTENT);
+LCRYPTO_USED(i2d_PKCS7_ENC_CONTENT);
+LCRYPTO_USED(PKCS7_ENVELOPE_new);
+LCRYPTO_USED(PKCS7_ENVELOPE_free);
+LCRYPTO_USED(d2i_PKCS7_ENVELOPE);
+LCRYPTO_USED(i2d_PKCS7_ENVELOPE);
+LCRYPTO_USED(PKCS7_SIGN_ENVELOPE_new);
+LCRYPTO_USED(PKCS7_SIGN_ENVELOPE_free);
+LCRYPTO_USED(d2i_PKCS7_SIGN_ENVELOPE);
+LCRYPTO_USED(i2d_PKCS7_SIGN_ENVELOPE);
+LCRYPTO_USED(PKCS7_DIGEST_new);
+LCRYPTO_USED(PKCS7_DIGEST_free);
+LCRYPTO_USED(d2i_PKCS7_DIGEST);
+LCRYPTO_USED(i2d_PKCS7_DIGEST);
+LCRYPTO_USED(PKCS7_ENCRYPT_new);
+LCRYPTO_USED(PKCS7_ENCRYPT_free);
+LCRYPTO_USED(d2i_PKCS7_ENCRYPT);
+LCRYPTO_USED(i2d_PKCS7_ENCRYPT);
+LCRYPTO_USED(PKCS7_new);
+LCRYPTO_USED(PKCS7_free);
+LCRYPTO_USED(d2i_PKCS7);
+LCRYPTO_USED(i2d_PKCS7);
+LCRYPTO_USED(PKCS7_print_ctx);
+LCRYPTO_USED(PKCS7_ctrl);
+LCRYPTO_USED(PKCS7_set_type);
+LCRYPTO_USED(PKCS7_set0_type_other);
+LCRYPTO_USED(PKCS7_set_content);
+LCRYPTO_USED(PKCS7_SIGNER_INFO_set);
+LCRYPTO_USED(PKCS7_SIGNER_INFO_sign);
+LCRYPTO_USED(PKCS7_add_signer);
+LCRYPTO_USED(PKCS7_add_certificate);
+LCRYPTO_USED(PKCS7_add_crl);
+LCRYPTO_USED(PKCS7_content_new);
+LCRYPTO_USED(PKCS7_dataVerify);
+LCRYPTO_USED(PKCS7_signatureVerify);
+LCRYPTO_USED(PKCS7_dataInit);
+LCRYPTO_USED(PKCS7_dataFinal);
+LCRYPTO_USED(PKCS7_dataDecode);
+LCRYPTO_USED(PKCS7_add_signature);
+LCRYPTO_USED(PKCS7_cert_from_signer_info);
+LCRYPTO_USED(PKCS7_set_digest);
+LCRYPTO_USED(PKCS7_get_signer_info);
+LCRYPTO_USED(PKCS7_add_recipient);
+LCRYPTO_USED(PKCS7_SIGNER_INFO_get0_algs);
+LCRYPTO_USED(PKCS7_RECIP_INFO_get0_alg);
+LCRYPTO_USED(PKCS7_add_recipient_info);
+LCRYPTO_USED(PKCS7_RECIP_INFO_set);
+LCRYPTO_USED(PKCS7_set_cipher);
+LCRYPTO_USED(PKCS7_stream);
+LCRYPTO_USED(PKCS7_get_issuer_and_serial);
+LCRYPTO_USED(PKCS7_digest_from_attributes);
+LCRYPTO_USED(PKCS7_add_signed_attribute);
+LCRYPTO_USED(PKCS7_add_attribute);
+LCRYPTO_USED(PKCS7_get_attribute);
+LCRYPTO_USED(PKCS7_get_signed_attribute);
+LCRYPTO_USED(PKCS7_set_signed_attributes);
+LCRYPTO_USED(PKCS7_set_attributes);
+LCRYPTO_USED(PKCS7_sign);
+LCRYPTO_USED(PKCS7_sign_add_signer);
+LCRYPTO_USED(PKCS7_final);
+LCRYPTO_USED(PKCS7_verify);
+LCRYPTO_USED(PKCS7_get0_signers);
+LCRYPTO_USED(PKCS7_encrypt);
+LCRYPTO_USED(PKCS7_decrypt);
+LCRYPTO_USED(PKCS7_add_attrib_smimecap);
+LCRYPTO_USED(PKCS7_get_smimecap);
+LCRYPTO_USED(PKCS7_simple_smimecap);
+LCRYPTO_USED(PKCS7_add_attrib_content_type);
+LCRYPTO_USED(PKCS7_add0_attrib_signing_time);
+LCRYPTO_USED(PKCS7_add1_attrib_digest);
+LCRYPTO_USED(SMIME_write_PKCS7);
+LCRYPTO_USED(SMIME_read_PKCS7);
+LCRYPTO_USED(BIO_new_PKCS7);
+LCRYPTO_USED(ERR_load_PKCS7_strings);
+
+#endif /* _LIBCRYPTO_PKCS7_H */
diff --git a/crypto/hidden/openssl/poly1305.h b/crypto/hidden/openssl/poly1305.h
new file mode 100644
index 0000000..7a459cb
--- /dev/null
+++ b/crypto/hidden/openssl/poly1305.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: poly1305.h,v 1.2 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_POLY1305_H
+#define _LIBCRYPTO_POLY1305_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/poly1305.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(CRYPTO_poly1305_init);
+LCRYPTO_USED(CRYPTO_poly1305_update);
+LCRYPTO_USED(CRYPTO_poly1305_finish);
+
+#endif /* _LIBCRYPTO_POLY1305_H */
diff --git a/crypto/hidden/openssl/rand.h b/crypto/hidden/openssl/rand.h
new file mode 100644
index 0000000..978d10f
--- /dev/null
+++ b/crypto/hidden/openssl/rand.h
@@ -0,0 +1,33 @@
+/* $OpenBSD: rand.h,v 1.3 2023/07/28 09:53:55 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_RAND_H
+#define _LIBCRYPTO_RAND_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/rand.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(RAND_set_rand_method);
+LCRYPTO_USED(RAND_get_rand_method);
+LCRYPTO_USED(RAND_SSLeay);
+LCRYPTO_USED(ERR_load_RAND_strings);
+
+#endif /* _LIBCRYPTO_RAND_H */
diff --git a/crypto/hidden/openssl/rc2.h b/crypto/hidden/openssl/rc2.h
new file mode 100644
index 0000000..c08c38d
--- /dev/null
+++ b/crypto/hidden/openssl/rc2.h
@@ -0,0 +1,36 @@
+/* $OpenBSD: rc2.h,v 1.1 2023/07/07 13:40:44 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_RC2_H
+#define _LIBCRYPTO_RC2_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/rc2.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(RC2_set_key);
+LCRYPTO_USED(RC2_ecb_encrypt);
+LCRYPTO_USED(RC2_encrypt);
+LCRYPTO_USED(RC2_decrypt);
+LCRYPTO_USED(RC2_cbc_encrypt);
+LCRYPTO_USED(RC2_cfb64_encrypt);
+LCRYPTO_USED(RC2_ofb64_encrypt);
+
+#endif /* _LIBCRYPTO_RC2_H */
diff --git a/crypto/hidden/openssl/rsa.h b/crypto/hidden/openssl/rsa.h
new file mode 100644
index 0000000..ff47101
--- /dev/null
+++ b/crypto/hidden/openssl/rsa.h
@@ -0,0 +1,141 @@
+/* $OpenBSD: rsa.h,v 1.2 2023/07/28 10:05:16 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_RSA_H
+#define _LIBCRYPTO_RSA_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/rsa.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(RSA_new);
+LCRYPTO_USED(RSA_new_method);
+LCRYPTO_USED(RSA_bits);
+LCRYPTO_USED(RSA_size);
+LCRYPTO_USED(RSA_generate_key);
+LCRYPTO_USED(RSA_generate_key_ex);
+LCRYPTO_USED(RSA_check_key);
+LCRYPTO_USED(RSA_public_encrypt);
+LCRYPTO_USED(RSA_private_encrypt);
+LCRYPTO_USED(RSA_public_decrypt);
+LCRYPTO_USED(RSA_private_decrypt);
+LCRYPTO_USED(RSA_free);
+LCRYPTO_USED(RSA_up_ref);
+LCRYPTO_USED(RSA_flags);
+LCRYPTO_USED(RSA_set_default_method);
+LCRYPTO_USED(RSA_get_default_method);
+LCRYPTO_USED(RSA_get_method);
+LCRYPTO_USED(RSA_set_method);
+LCRYPTO_USED(RSA_PKCS1_OpenSSL);
+LCRYPTO_USED(RSA_PKCS1_SSLeay);
+LCRYPTO_USED(RSA_pkey_ctx_ctrl);
+LCRYPTO_USED(d2i_RSAPublicKey);
+LCRYPTO_USED(i2d_RSAPublicKey);
+LCRYPTO_USED(d2i_RSAPrivateKey);
+LCRYPTO_USED(i2d_RSAPrivateKey);
+LCRYPTO_USED(RSA_PSS_PARAMS_new);
+LCRYPTO_USED(RSA_PSS_PARAMS_free);
+LCRYPTO_USED(d2i_RSA_PSS_PARAMS);
+LCRYPTO_USED(i2d_RSA_PSS_PARAMS);
+LCRYPTO_USED(RSA_OAEP_PARAMS_new);
+LCRYPTO_USED(RSA_OAEP_PARAMS_free);
+LCRYPTO_USED(d2i_RSA_OAEP_PARAMS);
+LCRYPTO_USED(i2d_RSA_OAEP_PARAMS);
+LCRYPTO_USED(RSA_print_fp);
+LCRYPTO_USED(RSA_print);
+LCRYPTO_USED(RSA_sign);
+LCRYPTO_USED(RSA_verify);
+LCRYPTO_USED(RSA_sign_ASN1_OCTET_STRING);
+LCRYPTO_USED(RSA_verify_ASN1_OCTET_STRING);
+LCRYPTO_USED(RSA_blinding_on);
+LCRYPTO_USED(RSA_blinding_off);
+LCRYPTO_USED(RSA_padding_add_PKCS1_type_1);
+LCRYPTO_USED(RSA_padding_check_PKCS1_type_1);
+LCRYPTO_USED(RSA_padding_add_PKCS1_type_2);
+LCRYPTO_USED(RSA_padding_check_PKCS1_type_2);
+LCRYPTO_USED(PKCS1_MGF1);
+LCRYPTO_USED(RSA_padding_add_PKCS1_OAEP);
+LCRYPTO_USED(RSA_padding_check_PKCS1_OAEP);
+LCRYPTO_USED(RSA_padding_add_PKCS1_OAEP_mgf1);
+LCRYPTO_USED(RSA_padding_check_PKCS1_OAEP_mgf1);
+LCRYPTO_USED(RSA_padding_add_none);
+LCRYPTO_USED(RSA_padding_check_none);
+LCRYPTO_USED(RSA_verify_PKCS1_PSS);
+LCRYPTO_USED(RSA_padding_add_PKCS1_PSS);
+LCRYPTO_USED(RSA_verify_PKCS1_PSS_mgf1);
+LCRYPTO_USED(RSA_padding_add_PKCS1_PSS_mgf1);
+LCRYPTO_USED(RSA_get_ex_new_index);
+LCRYPTO_USED(RSA_set_ex_data);
+LCRYPTO_USED(RSA_get_ex_data);
+LCRYPTO_USED(RSA_security_bits);
+LCRYPTO_USED(RSA_get0_key);
+LCRYPTO_USED(RSA_set0_key);
+LCRYPTO_USED(RSA_get0_crt_params);
+LCRYPTO_USED(RSA_set0_crt_params);
+LCRYPTO_USED(RSA_get0_factors);
+LCRYPTO_USED(RSA_set0_factors);
+LCRYPTO_USED(RSA_get0_n);
+LCRYPTO_USED(RSA_get0_e);
+LCRYPTO_USED(RSA_get0_d);
+LCRYPTO_USED(RSA_get0_p);
+LCRYPTO_USED(RSA_get0_q);
+LCRYPTO_USED(RSA_get0_dmp1);
+LCRYPTO_USED(RSA_get0_dmq1);
+LCRYPTO_USED(RSA_get0_iqmp);
+LCRYPTO_USED(RSA_get0_pss_params);
+LCRYPTO_USED(RSA_clear_flags);
+LCRYPTO_USED(RSA_test_flags);
+LCRYPTO_USED(RSA_set_flags);
+LCRYPTO_USED(RSAPublicKey_dup);
+LCRYPTO_USED(RSAPrivateKey_dup);
+LCRYPTO_USED(RSA_meth_new);
+LCRYPTO_USED(RSA_meth_free);
+LCRYPTO_USED(RSA_meth_dup);
+LCRYPTO_USED(RSA_meth_set1_name);
+LCRYPTO_USED(RSA_meth_set_priv_enc);
+LCRYPTO_USED(RSA_meth_set_priv_dec);
+LCRYPTO_USED(RSA_meth_get_finish);
+LCRYPTO_USED(RSA_meth_set_finish);
+LCRYPTO_USED(RSA_meth_set_pub_enc);
+LCRYPTO_USED(RSA_meth_set_pub_dec);
+LCRYPTO_USED(RSA_meth_set_mod_exp);
+LCRYPTO_USED(RSA_meth_set_bn_mod_exp);
+LCRYPTO_USED(RSA_meth_set_init);
+LCRYPTO_USED(RSA_meth_set_keygen);
+LCRYPTO_USED(RSA_meth_set_flags);
+LCRYPTO_USED(RSA_meth_set0_app_data);
+LCRYPTO_USED(RSA_meth_get0_name);
+LCRYPTO_USED(RSA_meth_get_pub_enc);
+LCRYPTO_USED(RSA_meth_get_pub_dec);
+LCRYPTO_USED(RSA_meth_get_priv_enc);
+LCRYPTO_USED(RSA_meth_get_priv_dec);
+LCRYPTO_USED(RSA_meth_get_mod_exp);
+LCRYPTO_USED(RSA_meth_get_bn_mod_exp);
+LCRYPTO_USED(RSA_meth_get_init);
+LCRYPTO_USED(RSA_meth_get_keygen);
+LCRYPTO_USED(RSA_meth_get_flags);
+LCRYPTO_USED(RSA_meth_get0_app_data);
+LCRYPTO_USED(RSA_meth_get_sign);
+LCRYPTO_USED(RSA_meth_set_sign);
+LCRYPTO_USED(RSA_meth_get_verify);
+LCRYPTO_USED(RSA_meth_set_verify);
+LCRYPTO_USED(ERR_load_RSA_strings);
+
+#endif /* _LIBCRYPTO_RSA_H */
diff --git a/crypto/hidden/openssl/sha.h b/crypto/hidden/openssl/sha.h
new file mode 100644
index 0000000..ee58793
--- /dev/null
+++ b/crypto/hidden/openssl/sha.h
@@ -0,0 +1,52 @@
+/* $OpenBSD: sha.h,v 1.1 2023/07/08 12:24:10 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_SHA_H
+#define _LIBCRYPTO_SHA_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/sha.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(SHA1_Init);
+LCRYPTO_USED(SHA1_Update);
+LCRYPTO_USED(SHA1_Final);
+LCRYPTO_USED(SHA1);
+LCRYPTO_USED(SHA1_Transform);
+LCRYPTO_USED(SHA224_Init);
+LCRYPTO_USED(SHA224_Update);
+LCRYPTO_USED(SHA224_Final);
+LCRYPTO_USED(SHA224);
+LCRYPTO_USED(SHA256_Init);
+LCRYPTO_USED(SHA256_Update);
+LCRYPTO_USED(SHA256_Final);
+LCRYPTO_USED(SHA256);
+LCRYPTO_USED(SHA256_Transform);
+LCRYPTO_USED(SHA384_Init);
+LCRYPTO_USED(SHA384_Update);
+LCRYPTO_USED(SHA384_Final);
+LCRYPTO_USED(SHA384);
+LCRYPTO_USED(SHA512_Init);
+LCRYPTO_USED(SHA512_Update);
+LCRYPTO_USED(SHA512_Final);
+LCRYPTO_USED(SHA512);
+LCRYPTO_USED(SHA512_Transform);
+
+#endif /* _LIBCRYPTO_SHA_H */
diff --git a/crypto/hidden/openssl/sm3.h b/crypto/hidden/openssl/sm3.h
new file mode 100644
index 0000000..12a0e1a
--- /dev/null
+++ b/crypto/hidden/openssl/sm3.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: sm3.h,v 1.3 2023/07/08 06:13:08 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_SM3_H
+#define _LIBCRYPTO_SM3_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/sm3.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(SM3_Init);
+LCRYPTO_USED(SM3_Update);
+LCRYPTO_USED(SM3_Final);
+
+#endif /* _LIBCRYPTO_SM3_H */
diff --git a/crypto/hidden/openssl/sm4.h b/crypto/hidden/openssl/sm4.h
new file mode 100644
index 0000000..1b80e5c
--- /dev/null
+++ b/crypto/hidden/openssl/sm4.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: sm4.h,v 1.2 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_SM4_H
+#define _LIBCRYPTO_SM4_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/sm4.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(SM4_set_key);
+LCRYPTO_USED(SM4_decrypt);
+LCRYPTO_USED(SM4_encrypt);
+
+#endif /* _LIBCRYPTO_SM4_H */
diff --git a/crypto/hidden/openssl/stack.h b/crypto/hidden/openssl/stack.h
new file mode 100644
index 0000000..38bb02e
--- /dev/null
+++ b/crypto/hidden/openssl/stack.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: stack.h,v 1.2 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_STACK_H
+#define _LIBCRYPTO_STACK_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/stack.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(sk_num);
+LCRYPTO_USED(sk_value);
+LCRYPTO_USED(sk_set);
+LCRYPTO_USED(sk_new);
+LCRYPTO_USED(sk_new_null);
+LCRYPTO_USED(sk_free);
+LCRYPTO_USED(sk_pop_free);
+LCRYPTO_USED(sk_insert);
+LCRYPTO_USED(sk_delete);
+LCRYPTO_USED(sk_delete_ptr);
+LCRYPTO_USED(sk_find);
+LCRYPTO_USED(sk_find_ex);
+LCRYPTO_USED(sk_push);
+LCRYPTO_USED(sk_unshift);
+LCRYPTO_USED(sk_shift);
+LCRYPTO_USED(sk_pop);
+LCRYPTO_USED(sk_zero);
+LCRYPTO_USED(sk_set_cmp_func);
+LCRYPTO_USED(sk_dup);
+LCRYPTO_USED(sk_sort);
+LCRYPTO_USED(sk_is_sorted);
+
+#endif /* _LIBCRYPTO_STACK_H */
diff --git a/crypto/hidden/openssl/ts.h b/crypto/hidden/openssl/ts.h
new file mode 100644
index 0000000..0acad21
--- /dev/null
+++ b/crypto/hidden/openssl/ts.h
@@ -0,0 +1,217 @@
+/* $OpenBSD: ts.h,v 1.3 2023/07/28 09:53:55 tb Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_TS_H
+#define _LIBCRYPTO_TS_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/ts.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(TS_REQ_new);
+LCRYPTO_USED(TS_REQ_free);
+LCRYPTO_USED(i2d_TS_REQ);
+LCRYPTO_USED(d2i_TS_REQ);
+LCRYPTO_USED(TS_REQ_dup);
+LCRYPTO_USED(d2i_TS_REQ_fp);
+LCRYPTO_USED(i2d_TS_REQ_fp);
+LCRYPTO_USED(d2i_TS_REQ_bio);
+LCRYPTO_USED(i2d_TS_REQ_bio);
+LCRYPTO_USED(TS_MSG_IMPRINT_new);
+LCRYPTO_USED(TS_MSG_IMPRINT_free);
+LCRYPTO_USED(i2d_TS_MSG_IMPRINT);
+LCRYPTO_USED(d2i_TS_MSG_IMPRINT);
+LCRYPTO_USED(TS_MSG_IMPRINT_dup);
+LCRYPTO_USED(d2i_TS_MSG_IMPRINT_fp);
+LCRYPTO_USED(i2d_TS_MSG_IMPRINT_fp);
+LCRYPTO_USED(d2i_TS_MSG_IMPRINT_bio);
+LCRYPTO_USED(i2d_TS_MSG_IMPRINT_bio);
+LCRYPTO_USED(TS_RESP_new);
+LCRYPTO_USED(TS_RESP_free);
+LCRYPTO_USED(i2d_TS_RESP);
+LCRYPTO_USED(d2i_TS_RESP);
+LCRYPTO_USED(PKCS7_to_TS_TST_INFO);
+LCRYPTO_USED(TS_RESP_dup);
+LCRYPTO_USED(d2i_TS_RESP_fp);
+LCRYPTO_USED(i2d_TS_RESP_fp);
+LCRYPTO_USED(d2i_TS_RESP_bio);
+LCRYPTO_USED(i2d_TS_RESP_bio);
+LCRYPTO_USED(TS_STATUS_INFO_new);
+LCRYPTO_USED(TS_STATUS_INFO_free);
+LCRYPTO_USED(i2d_TS_STATUS_INFO);
+LCRYPTO_USED(d2i_TS_STATUS_INFO);
+LCRYPTO_USED(TS_STATUS_INFO_dup);
+LCRYPTO_USED(TS_TST_INFO_new);
+LCRYPTO_USED(TS_TST_INFO_free);
+LCRYPTO_USED(i2d_TS_TST_INFO);
+LCRYPTO_USED(d2i_TS_TST_INFO);
+LCRYPTO_USED(TS_TST_INFO_dup);
+LCRYPTO_USED(d2i_TS_TST_INFO_fp);
+LCRYPTO_USED(i2d_TS_TST_INFO_fp);
+LCRYPTO_USED(d2i_TS_TST_INFO_bio);
+LCRYPTO_USED(i2d_TS_TST_INFO_bio);
+LCRYPTO_USED(TS_ACCURACY_new);
+LCRYPTO_USED(TS_ACCURACY_free);
+LCRYPTO_USED(i2d_TS_ACCURACY);
+LCRYPTO_USED(d2i_TS_ACCURACY);
+LCRYPTO_USED(TS_ACCURACY_dup);
+LCRYPTO_USED(ESS_ISSUER_SERIAL_new);
+LCRYPTO_USED(ESS_ISSUER_SERIAL_free);
+LCRYPTO_USED(i2d_ESS_ISSUER_SERIAL);
+LCRYPTO_USED(d2i_ESS_ISSUER_SERIAL);
+LCRYPTO_USED(ESS_ISSUER_SERIAL_dup);
+LCRYPTO_USED(ESS_CERT_ID_new);
+LCRYPTO_USED(ESS_CERT_ID_free);
+LCRYPTO_USED(i2d_ESS_CERT_ID);
+LCRYPTO_USED(d2i_ESS_CERT_ID);
+LCRYPTO_USED(ESS_CERT_ID_dup);
+LCRYPTO_USED(ESS_SIGNING_CERT_new);
+LCRYPTO_USED(ESS_SIGNING_CERT_free);
+LCRYPTO_USED(i2d_ESS_SIGNING_CERT);
+LCRYPTO_USED(d2i_ESS_SIGNING_CERT);
+LCRYPTO_USED(ESS_SIGNING_CERT_dup);
+LCRYPTO_USED(TS_REQ_set_version);
+LCRYPTO_USED(TS_REQ_get_version);
+LCRYPTO_USED(TS_REQ_set_msg_imprint);
+LCRYPTO_USED(TS_REQ_get_msg_imprint);
+LCRYPTO_USED(TS_MSG_IMPRINT_set_algo);
+LCRYPTO_USED(TS_MSG_IMPRINT_get_algo);
+LCRYPTO_USED(TS_MSG_IMPRINT_set_msg);
+LCRYPTO_USED(TS_MSG_IMPRINT_get_msg);
+LCRYPTO_USED(TS_REQ_set_policy_id);
+LCRYPTO_USED(TS_REQ_get_policy_id);
+LCRYPTO_USED(TS_REQ_set_nonce);
+LCRYPTO_USED(TS_REQ_get_nonce);
+LCRYPTO_USED(TS_REQ_set_cert_req);
+LCRYPTO_USED(TS_REQ_get_cert_req);
+LCRYPTO_USED(TS_REQ_get_exts);
+LCRYPTO_USED(TS_REQ_ext_free);
+LCRYPTO_USED(TS_REQ_get_ext_count);
+LCRYPTO_USED(TS_REQ_get_ext_by_NID);
+LCRYPTO_USED(TS_REQ_get_ext_by_OBJ);
+LCRYPTO_USED(TS_REQ_get_ext_by_critical);
+LCRYPTO_USED(TS_REQ_get_ext);
+LCRYPTO_USED(TS_REQ_delete_ext);
+LCRYPTO_USED(TS_REQ_add_ext);
+LCRYPTO_USED(TS_REQ_get_ext_d2i);
+LCRYPTO_USED(TS_REQ_print_bio);
+LCRYPTO_USED(TS_RESP_set_status_info);
+LCRYPTO_USED(TS_RESP_get_status_info);
+LCRYPTO_USED(TS_STATUS_INFO_get0_failure_info);
+LCRYPTO_USED(TS_STATUS_INFO_get0_text);
+LCRYPTO_USED(TS_STATUS_INFO_get0_status);
+LCRYPTO_USED(TS_STATUS_INFO_set_status);
+LCRYPTO_USED(TS_RESP_set_tst_info);
+LCRYPTO_USED(TS_RESP_get_token);
+LCRYPTO_USED(TS_RESP_get_tst_info);
+LCRYPTO_USED(TS_TST_INFO_set_version);
+LCRYPTO_USED(TS_TST_INFO_get_version);
+LCRYPTO_USED(TS_TST_INFO_set_policy_id);
+LCRYPTO_USED(TS_TST_INFO_get_policy_id);
+LCRYPTO_USED(TS_TST_INFO_set_msg_imprint);
+LCRYPTO_USED(TS_TST_INFO_get_msg_imprint);
+LCRYPTO_USED(TS_TST_INFO_set_serial);
+LCRYPTO_USED(TS_TST_INFO_get_serial);
+LCRYPTO_USED(TS_TST_INFO_set_time);
+LCRYPTO_USED(TS_TST_INFO_get_time);
+LCRYPTO_USED(TS_TST_INFO_set_accuracy);
+LCRYPTO_USED(TS_TST_INFO_get_accuracy);
+LCRYPTO_USED(TS_ACCURACY_set_seconds);
+LCRYPTO_USED(TS_ACCURACY_get_seconds);
+LCRYPTO_USED(TS_ACCURACY_set_millis);
+LCRYPTO_USED(TS_ACCURACY_get_millis);
+LCRYPTO_USED(TS_ACCURACY_set_micros);
+LCRYPTO_USED(TS_ACCURACY_get_micros);
+LCRYPTO_USED(TS_TST_INFO_set_ordering);
+LCRYPTO_USED(TS_TST_INFO_get_ordering);
+LCRYPTO_USED(TS_TST_INFO_set_nonce);
+LCRYPTO_USED(TS_TST_INFO_get_nonce);
+LCRYPTO_USED(TS_TST_INFO_set_tsa);
+LCRYPTO_USED(TS_TST_INFO_get_tsa);
+LCRYPTO_USED(TS_TST_INFO_get_exts);
+LCRYPTO_USED(TS_TST_INFO_ext_free);
+LCRYPTO_USED(TS_TST_INFO_get_ext_count);
+LCRYPTO_USED(TS_TST_INFO_get_ext_by_NID);
+LCRYPTO_USED(TS_TST_INFO_get_ext_by_OBJ);
+LCRYPTO_USED(TS_TST_INFO_get_ext_by_critical);
+LCRYPTO_USED(TS_TST_INFO_get_ext);
+LCRYPTO_USED(TS_TST_INFO_delete_ext);
+LCRYPTO_USED(TS_TST_INFO_add_ext);
+LCRYPTO_USED(TS_TST_INFO_get_ext_d2i);
+LCRYPTO_USED(TS_RESP_CTX_new);
+LCRYPTO_USED(TS_RESP_CTX_free);
+LCRYPTO_USED(TS_RESP_CTX_set_signer_cert);
+LCRYPTO_USED(TS_RESP_CTX_set_signer_key);
+LCRYPTO_USED(TS_RESP_CTX_set_def_policy);
+LCRYPTO_USED(TS_RESP_CTX_set_certs);
+LCRYPTO_USED(TS_RESP_CTX_add_policy);
+LCRYPTO_USED(TS_RESP_CTX_add_md);
+LCRYPTO_USED(TS_RESP_CTX_set_accuracy);
+LCRYPTO_USED(TS_RESP_CTX_set_clock_precision_digits);
+LCRYPTO_USED(TS_RESP_CTX_add_flags);
+LCRYPTO_USED(TS_RESP_CTX_set_serial_cb);
+LCRYPTO_USED(TS_RESP_CTX_set_time_cb);
+LCRYPTO_USED(TS_RESP_CTX_set_extension_cb);
+LCRYPTO_USED(TS_RESP_CTX_set_status_info);
+LCRYPTO_USED(TS_RESP_CTX_set_status_info_cond);
+LCRYPTO_USED(TS_RESP_CTX_add_failure_info);
+LCRYPTO_USED(TS_RESP_CTX_get_request);
+LCRYPTO_USED(TS_RESP_CTX_get_tst_info);
+LCRYPTO_USED(TS_RESP_create_response);
+LCRYPTO_USED(TS_RESP_verify_signature);
+LCRYPTO_USED(TS_RESP_verify_response);
+LCRYPTO_USED(TS_RESP_verify_token);
+LCRYPTO_USED(TS_VERIFY_CTX_new);
+LCRYPTO_USED(TS_VERIFY_CTX_free);
+LCRYPTO_USED(TS_VERIFY_CTX_cleanup);
+LCRYPTO_USED(TS_VERIFY_CTX_add_flags);
+LCRYPTO_USED(TS_VERIFY_CTX_set_flags);
+LCRYPTO_USED(TS_VERIFY_CTX_set_data);
+LCRYPTO_USED(TS_VERIFY_CTX_set_store);
+LCRYPTO_USED(TS_VERIFY_CTX_set_certs);
+LCRYPTO_USED(TS_VERIFY_CTX_set_imprint);
+LCRYPTO_USED(TS_REQ_to_TS_VERIFY_CTX);
+LCRYPTO_USED(TS_RESP_print_bio);
+LCRYPTO_USED(TS_STATUS_INFO_print_bio);
+LCRYPTO_USED(TS_TST_INFO_print_bio);
+LCRYPTO_USED(TS_ASN1_INTEGER_print_bio);
+LCRYPTO_USED(TS_OBJ_print_bio);
+LCRYPTO_USED(TS_ext_print_bio);
+LCRYPTO_USED(TS_X509_ALGOR_print_bio);
+LCRYPTO_USED(TS_MSG_IMPRINT_print_bio);
+LCRYPTO_USED(TS_CONF_load_cert);
+LCRYPTO_USED(TS_CONF_load_certs);
+LCRYPTO_USED(TS_CONF_load_key);
+LCRYPTO_USED(TS_CONF_get_tsa_section);
+LCRYPTO_USED(TS_CONF_set_serial);
+LCRYPTO_USED(TS_CONF_set_signer_cert);
+LCRYPTO_USED(TS_CONF_set_certs);
+LCRYPTO_USED(TS_CONF_set_signer_key);
+LCRYPTO_USED(TS_CONF_set_def_policy);
+LCRYPTO_USED(TS_CONF_set_policies);
+LCRYPTO_USED(TS_CONF_set_digests);
+LCRYPTO_USED(TS_CONF_set_accuracy);
+LCRYPTO_USED(TS_CONF_set_clock_precision_digits);
+LCRYPTO_USED(TS_CONF_set_ordering);
+LCRYPTO_USED(TS_CONF_set_tsa_name);
+LCRYPTO_USED(TS_CONF_set_ess_cert_id_chain);
+LCRYPTO_USED(ERR_load_TS_strings);
+
+#endif /* _LIBCRYPTO_TS_H */
diff --git a/crypto/hidden/openssl/txt_db.h b/crypto/hidden/openssl/txt_db.h
new file mode 100644
index 0000000..f93dbc6
--- /dev/null
+++ b/crypto/hidden/openssl/txt_db.h
@@ -0,0 +1,35 @@
+/* $OpenBSD: txt_db.h,v 1.1 2023/07/08 11:28:03 beck Exp $ */
+/*
+ * Copyright (c) 2023 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_TXT_DB_H
+#define _LIBCRYPTO_TXT_DB_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/txt_db.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(TXT_DB_read);
+LCRYPTO_USED(TXT_DB_write);
+LCRYPTO_USED(TXT_DB_create_index);
+LCRYPTO_USED(TXT_DB_free);
+LCRYPTO_USED(TXT_DB_get_by_index);
+LCRYPTO_USED(TXT_DB_insert);
+
+#endif /* _LIBCRYPTO_TXT_DB_H */
diff --git a/crypto/hidden/openssl/ui.h b/crypto/hidden/openssl/ui.h
new file mode 100644
index 0000000..f6c749f
--- /dev/null
+++ b/crypto/hidden/openssl/ui.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: ui.h,v 1.3 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_UI_H
+#define _LIBCRYPTO_UI_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/ui.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(UI_new);
+LCRYPTO_USED(UI_new_method);
+LCRYPTO_USED(UI_free);
+LCRYPTO_USED(UI_add_input_string);
+LCRYPTO_USED(UI_dup_input_string);
+LCRYPTO_USED(UI_add_verify_string);
+LCRYPTO_USED(UI_dup_verify_string);
+LCRYPTO_USED(UI_add_input_boolean);
+LCRYPTO_USED(UI_dup_input_boolean);
+LCRYPTO_USED(UI_add_info_string);
+LCRYPTO_USED(UI_dup_info_string);
+LCRYPTO_USED(UI_add_error_string);
+LCRYPTO_USED(UI_dup_error_string);
+LCRYPTO_USED(UI_construct_prompt);
+LCRYPTO_USED(UI_add_user_data);
+LCRYPTO_USED(UI_get0_user_data);
+LCRYPTO_USED(UI_get0_result);
+LCRYPTO_USED(UI_process);
+LCRYPTO_USED(UI_ctrl);
+LCRYPTO_USED(UI_get_ex_new_index);
+LCRYPTO_USED(UI_set_ex_data);
+LCRYPTO_USED(UI_get_ex_data);
+LCRYPTO_USED(UI_set_default_method);
+LCRYPTO_USED(UI_get_default_method);
+LCRYPTO_USED(UI_get_method);
+LCRYPTO_USED(UI_set_method);
+LCRYPTO_USED(UI_OpenSSL);
+LCRYPTO_USED(UI_null);
+LCRYPTO_USED(UI_create_method);
+LCRYPTO_USED(UI_destroy_method);
+LCRYPTO_USED(UI_method_set_opener);
+LCRYPTO_USED(UI_method_set_writer);
+LCRYPTO_USED(UI_method_set_flusher);
+LCRYPTO_USED(UI_method_set_reader);
+LCRYPTO_USED(UI_method_set_closer);
+LCRYPTO_USED(UI_method_set_prompt_constructor);
+LCRYPTO_USED(UI_method_get_opener);
+LCRYPTO_USED(UI_method_get_writer);
+LCRYPTO_USED(UI_method_get_flusher);
+LCRYPTO_USED(UI_method_get_reader);
+LCRYPTO_USED(UI_method_get_closer);
+LCRYPTO_USED(UI_get_string_type);
+LCRYPTO_USED(UI_get_input_flags);
+LCRYPTO_USED(UI_get0_output_string);
+LCRYPTO_USED(UI_get0_action_string);
+LCRYPTO_USED(UI_get0_result_string);
+LCRYPTO_USED(UI_get0_test_string);
+LCRYPTO_USED(UI_get_result_minsize);
+LCRYPTO_USED(UI_get_result_maxsize);
+LCRYPTO_USED(UI_set_result);
+LCRYPTO_USED(UI_UTIL_read_pw_string);
+LCRYPTO_USED(UI_UTIL_read_pw);
+LCRYPTO_USED(ERR_load_UI_strings);
+LCRYPTO_USED(UI_method_get_prompt_constructor);
+
+#endif /* _LIBCRYPTO_UI_H */
diff --git a/crypto/hidden/openssl/x509.h b/crypto/hidden/openssl/x509.h
new file mode 100644
index 0000000..13bd5b5
--- /dev/null
+++ b/crypto/hidden/openssl/x509.h
@@ -0,0 +1,283 @@
+/* $OpenBSD: x509.h,v 1.3 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_X509_H
+#define _LIBCRYPTO_X509_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/x509.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(X509_CRL_up_ref);
+LCRYPTO_USED(i2d_re_X509_CRL_tbs);
+LCRYPTO_USED(X509_get_X509_PUBKEY);
+LCRYPTO_USED(X509_verify_cert_error_string);
+LCRYPTO_USED(X509_verify);
+LCRYPTO_USED(X509_REQ_verify);
+LCRYPTO_USED(NETSCAPE_SPKI_verify);
+LCRYPTO_USED(NETSCAPE_SPKI_b64_decode);
+LCRYPTO_USED(NETSCAPE_SPKI_b64_encode);
+LCRYPTO_USED(NETSCAPE_SPKI_get_pubkey);
+LCRYPTO_USED(NETSCAPE_SPKI_set_pubkey);
+LCRYPTO_USED(X509_sign);
+LCRYPTO_USED(X509_sign_ctx);
+LCRYPTO_USED(X509_REQ_sign);
+LCRYPTO_USED(X509_REQ_sign_ctx);
+LCRYPTO_USED(X509_CRL_sign);
+LCRYPTO_USED(X509_CRL_sign_ctx);
+LCRYPTO_USED(NETSCAPE_SPKI_sign);
+LCRYPTO_USED(X509_pubkey_digest);
+LCRYPTO_USED(X509_digest);
+LCRYPTO_USED(X509_CRL_digest);
+LCRYPTO_USED(X509_REQ_digest);
+LCRYPTO_USED(X509_NAME_digest);
+LCRYPTO_USED(d2i_X509_fp);
+LCRYPTO_USED(i2d_X509_fp);
+LCRYPTO_USED(d2i_X509_CRL_fp);
+LCRYPTO_USED(i2d_X509_CRL_fp);
+LCRYPTO_USED(d2i_X509_REQ_fp);
+LCRYPTO_USED(i2d_X509_REQ_fp);
+LCRYPTO_USED(d2i_RSAPrivateKey_fp);
+LCRYPTO_USED(i2d_RSAPrivateKey_fp);
+LCRYPTO_USED(d2i_RSAPublicKey_fp);
+LCRYPTO_USED(i2d_RSAPublicKey_fp);
+LCRYPTO_USED(d2i_DSAPrivateKey_fp);
+LCRYPTO_USED(i2d_DSAPrivateKey_fp);
+LCRYPTO_USED(d2i_ECPrivateKey_fp);
+LCRYPTO_USED(i2d_ECPrivateKey_fp);
+LCRYPTO_USED(d2i_PKCS8_fp);
+LCRYPTO_USED(i2d_PKCS8_fp);
+LCRYPTO_USED(d2i_PKCS8_PRIV_KEY_INFO_fp);
+LCRYPTO_USED(i2d_PKCS8_PRIV_KEY_INFO_fp);
+LCRYPTO_USED(i2d_PKCS8PrivateKeyInfo_fp);
+LCRYPTO_USED(i2d_PrivateKey_fp);
+LCRYPTO_USED(d2i_PrivateKey_fp);
+LCRYPTO_USED(d2i_X509_bio);
+LCRYPTO_USED(i2d_X509_bio);
+LCRYPTO_USED(d2i_X509_CRL_bio);
+LCRYPTO_USED(i2d_X509_CRL_bio);
+LCRYPTO_USED(d2i_X509_REQ_bio);
+LCRYPTO_USED(i2d_X509_REQ_bio);
+LCRYPTO_USED(d2i_RSAPrivateKey_bio);
+LCRYPTO_USED(i2d_RSAPrivateKey_bio);
+LCRYPTO_USED(d2i_RSAPublicKey_bio);
+LCRYPTO_USED(i2d_RSAPublicKey_bio);
+LCRYPTO_USED(d2i_DSAPrivateKey_bio);
+LCRYPTO_USED(i2d_DSAPrivateKey_bio);
+LCRYPTO_USED(d2i_ECPrivateKey_bio);
+LCRYPTO_USED(i2d_ECPrivateKey_bio);
+LCRYPTO_USED(d2i_PKCS8_bio);
+LCRYPTO_USED(i2d_PKCS8_bio);
+LCRYPTO_USED(d2i_PKCS8_PRIV_KEY_INFO_bio);
+LCRYPTO_USED(i2d_PKCS8_PRIV_KEY_INFO_bio);
+LCRYPTO_USED(i2d_PKCS8PrivateKeyInfo_bio);
+LCRYPTO_USED(i2d_PrivateKey_bio);
+LCRYPTO_USED(d2i_PrivateKey_bio);
+LCRYPTO_USED(X509_cmp_time);
+LCRYPTO_USED(X509_cmp_current_time);
+LCRYPTO_USED(X509_time_adj);
+LCRYPTO_USED(X509_time_adj_ex);
+LCRYPTO_USED(X509_gmtime_adj);
+LCRYPTO_USED(X509_get_default_cert_area);
+LCRYPTO_USED(X509_get_default_cert_dir);
+LCRYPTO_USED(X509_get_default_cert_file);
+LCRYPTO_USED(X509_get_default_cert_dir_env);
+LCRYPTO_USED(X509_get_default_cert_file_env);
+LCRYPTO_USED(X509_get_default_private_dir);
+LCRYPTO_USED(X509_to_X509_REQ);
+LCRYPTO_USED(X509_REQ_to_X509);
+LCRYPTO_USED(X509_get_pubkey_parameters);
+LCRYPTO_USED(X509_TRUST_set_default);
+LCRYPTO_USED(X509_TRUST_set);
+LCRYPTO_USED(X509_NAME_oneline);
+LCRYPTO_USED(X509_get0_extensions);
+LCRYPTO_USED(X509_get0_tbs_sigalg);
+LCRYPTO_USED(X509_get0_uids);
+LCRYPTO_USED(X509_set_version);
+LCRYPTO_USED(X509_get_version);
+LCRYPTO_USED(X509_set_serialNumber);
+LCRYPTO_USED(X509_get_serialNumber);
+LCRYPTO_USED(X509_get0_serialNumber);
+LCRYPTO_USED(X509_set_issuer_name);
+LCRYPTO_USED(X509_get_issuer_name);
+LCRYPTO_USED(X509_set_subject_name);
+LCRYPTO_USED(X509_get_subject_name);
+LCRYPTO_USED(X509_set_notBefore);
+LCRYPTO_USED(X509_set1_notBefore);
+LCRYPTO_USED(X509_set_notAfter);
+LCRYPTO_USED(X509_set1_notAfter);
+LCRYPTO_USED(X509_get0_notBefore);
+LCRYPTO_USED(X509_getm_notBefore);
+LCRYPTO_USED(X509_get0_notAfter);
+LCRYPTO_USED(X509_getm_notAfter);
+LCRYPTO_USED(X509_set_pubkey);
+LCRYPTO_USED(X509_get_pubkey);
+LCRYPTO_USED(X509_get0_pubkey);
+LCRYPTO_USED(X509_get0_pubkey_bitstr);
+LCRYPTO_USED(X509_certificate_type);
+LCRYPTO_USED(X509_get_signature_type);
+LCRYPTO_USED(X509_REQ_set_version);
+LCRYPTO_USED(X509_REQ_get_version);
+LCRYPTO_USED(X509_REQ_set_subject_name);
+LCRYPTO_USED(X509_REQ_get_subject_name);
+LCRYPTO_USED(X509_REQ_set_pubkey);
+LCRYPTO_USED(X509_REQ_get_pubkey);
+LCRYPTO_USED(i2d_re_X509_REQ_tbs);
+LCRYPTO_USED(X509_REQ_get0_pubkey);
+LCRYPTO_USED(X509_REQ_extension_nid);
+LCRYPTO_USED(X509_REQ_get_extension_nids);
+LCRYPTO_USED(X509_REQ_set_extension_nids);
+LCRYPTO_USED(X509_REQ_get_extensions);
+LCRYPTO_USED(X509_REQ_add_extensions_nid);
+LCRYPTO_USED(X509_REQ_add_extensions);
+LCRYPTO_USED(X509_REQ_get_attr_count);
+LCRYPTO_USED(X509_REQ_get_attr_by_NID);
+LCRYPTO_USED(X509_REQ_get_attr_by_OBJ);
+LCRYPTO_USED(X509_REQ_get_attr);
+LCRYPTO_USED(X509_REQ_delete_attr);
+LCRYPTO_USED(X509_REQ_add1_attr);
+LCRYPTO_USED(X509_REQ_add1_attr_by_OBJ);
+LCRYPTO_USED(X509_REQ_add1_attr_by_NID);
+LCRYPTO_USED(X509_REQ_add1_attr_by_txt);
+LCRYPTO_USED(X509_CRL_set_version);
+LCRYPTO_USED(X509_CRL_set_issuer_name);
+LCRYPTO_USED(X509_CRL_set_lastUpdate);
+LCRYPTO_USED(X509_CRL_set1_lastUpdate);
+LCRYPTO_USED(X509_CRL_set_nextUpdate);
+LCRYPTO_USED(X509_CRL_set1_nextUpdate);
+LCRYPTO_USED(X509_CRL_sort);
+LCRYPTO_USED(X509_REVOKED_get0_extensions);
+LCRYPTO_USED(X509_REVOKED_get0_revocationDate);
+LCRYPTO_USED(X509_REVOKED_get0_serialNumber);
+LCRYPTO_USED(X509_REVOKED_set_revocationDate);
+LCRYPTO_USED(X509_REVOKED_set_serialNumber);
+LCRYPTO_USED(X509_REQ_check_private_key);
+LCRYPTO_USED(X509_check_private_key);
+LCRYPTO_USED(X509_issuer_and_serial_cmp);
+LCRYPTO_USED(X509_issuer_and_serial_hash);
+LCRYPTO_USED(X509_issuer_name_cmp);
+LCRYPTO_USED(X509_issuer_name_hash);
+LCRYPTO_USED(X509_subject_name_cmp);
+LCRYPTO_USED(X509_subject_name_hash);
+LCRYPTO_USED(X509_issuer_name_hash_old);
+LCRYPTO_USED(X509_subject_name_hash_old);
+LCRYPTO_USED(X509_cmp);
+LCRYPTO_USED(X509_NAME_cmp);
+LCRYPTO_USED(X509_NAME_hash);
+LCRYPTO_USED(X509_NAME_hash_old);
+LCRYPTO_USED(X509_CRL_cmp);
+LCRYPTO_USED(X509_CRL_match);
+LCRYPTO_USED(X509_NAME_entry_count);
+LCRYPTO_USED(X509_NAME_get_text_by_NID);
+LCRYPTO_USED(X509_NAME_get_text_by_OBJ);
+LCRYPTO_USED(X509_NAME_get_index_by_NID);
+LCRYPTO_USED(X509_NAME_get_index_by_OBJ);
+LCRYPTO_USED(X509_NAME_get_entry);
+LCRYPTO_USED(X509_NAME_delete_entry);
+LCRYPTO_USED(X509_NAME_add_entry);
+LCRYPTO_USED(X509_NAME_add_entry_by_OBJ);
+LCRYPTO_USED(X509_NAME_add_entry_by_NID);
+LCRYPTO_USED(X509_NAME_ENTRY_create_by_txt);
+LCRYPTO_USED(X509_NAME_ENTRY_create_by_NID);
+LCRYPTO_USED(X509_NAME_add_entry_by_txt);
+LCRYPTO_USED(X509_NAME_ENTRY_create_by_OBJ);
+LCRYPTO_USED(X509_NAME_ENTRY_set_object);
+LCRYPTO_USED(X509_NAME_ENTRY_set_data);
+LCRYPTO_USED(X509_NAME_ENTRY_get_object);
+LCRYPTO_USED(X509_NAME_ENTRY_get_data);
+LCRYPTO_USED(X509_NAME_ENTRY_set);
+LCRYPTO_USED(X509v3_get_ext_count);
+LCRYPTO_USED(X509v3_get_ext_by_NID);
+LCRYPTO_USED(X509v3_get_ext_by_OBJ);
+LCRYPTO_USED(X509v3_get_ext_by_critical);
+LCRYPTO_USED(X509v3_get_ext);
+LCRYPTO_USED(X509v3_delete_ext);
+LCRYPTO_USED(X509v3_add_ext);
+LCRYPTO_USED(X509_get_ext_count);
+LCRYPTO_USED(X509_get_ext_by_NID);
+LCRYPTO_USED(X509_get_ext_by_OBJ);
+LCRYPTO_USED(X509_get_ext_by_critical);
+LCRYPTO_USED(X509_get_ext);
+LCRYPTO_USED(X509_delete_ext);
+LCRYPTO_USED(X509_add_ext);
+LCRYPTO_USED(X509_get_ext_d2i);
+LCRYPTO_USED(X509_add1_ext_i2d);
+LCRYPTO_USED(X509_CRL_get_ext_count);
+LCRYPTO_USED(X509_CRL_get_ext_by_NID);
+LCRYPTO_USED(X509_CRL_get_ext_by_OBJ);
+LCRYPTO_USED(X509_CRL_get_ext_by_critical);
+LCRYPTO_USED(X509_CRL_get_ext);
+LCRYPTO_USED(X509_CRL_delete_ext);
+LCRYPTO_USED(X509_CRL_add_ext);
+LCRYPTO_USED(X509_CRL_get_ext_d2i);
+LCRYPTO_USED(X509_CRL_add1_ext_i2d);
+LCRYPTO_USED(X509_REVOKED_get_ext_count);
+LCRYPTO_USED(X509_REVOKED_get_ext_by_NID);
+LCRYPTO_USED(X509_REVOKED_get_ext_by_OBJ);
+LCRYPTO_USED(X509_REVOKED_get_ext_by_critical);
+LCRYPTO_USED(X509_REVOKED_get_ext);
+LCRYPTO_USED(X509_REVOKED_delete_ext);
+LCRYPTO_USED(X509_REVOKED_add_ext);
+LCRYPTO_USED(X509_REVOKED_get_ext_d2i);
+LCRYPTO_USED(X509_REVOKED_add1_ext_i2d);
+LCRYPTO_USED(X509_EXTENSION_create_by_NID);
+LCRYPTO_USED(X509_EXTENSION_create_by_OBJ);
+LCRYPTO_USED(X509_EXTENSION_set_object);
+LCRYPTO_USED(X509_EXTENSION_set_critical);
+LCRYPTO_USED(X509_EXTENSION_set_data);
+LCRYPTO_USED(X509_EXTENSION_get_object);
+LCRYPTO_USED(X509_EXTENSION_get_data);
+LCRYPTO_USED(X509_EXTENSION_get_critical);
+LCRYPTO_USED(X509at_get_attr_count);
+LCRYPTO_USED(X509at_get_attr_by_NID);
+LCRYPTO_USED(X509at_get_attr_by_OBJ);
+LCRYPTO_USED(X509at_get_attr);
+LCRYPTO_USED(X509at_delete_attr);
+LCRYPTO_USED(X509at_add1_attr);
+LCRYPTO_USED(X509at_add1_attr_by_OBJ);
+LCRYPTO_USED(X509at_add1_attr_by_NID);
+LCRYPTO_USED(X509at_add1_attr_by_txt);
+LCRYPTO_USED(X509at_get0_data_by_OBJ);
+LCRYPTO_USED(X509_ATTRIBUTE_create_by_NID);
+LCRYPTO_USED(X509_ATTRIBUTE_create_by_OBJ);
+LCRYPTO_USED(X509_ATTRIBUTE_create_by_txt);
+LCRYPTO_USED(X509_ATTRIBUTE_set1_object);
+LCRYPTO_USED(X509_ATTRIBUTE_set1_data);
+LCRYPTO_USED(X509_ATTRIBUTE_get0_data);
+LCRYPTO_USED(X509_ATTRIBUTE_count);
+LCRYPTO_USED(X509_ATTRIBUTE_get0_object);
+LCRYPTO_USED(X509_ATTRIBUTE_get0_type);
+LCRYPTO_USED(X509_verify_cert);
+LCRYPTO_USED(X509_find_by_issuer_and_serial);
+LCRYPTO_USED(X509_find_by_subject);
+LCRYPTO_USED(X509_check_trust);
+LCRYPTO_USED(X509_TRUST_get_count);
+LCRYPTO_USED(X509_TRUST_get0);
+LCRYPTO_USED(X509_TRUST_get_by_id);
+LCRYPTO_USED(X509_TRUST_add);
+LCRYPTO_USED(X509_TRUST_cleanup);
+LCRYPTO_USED(X509_TRUST_get_flags);
+LCRYPTO_USED(X509_TRUST_get0_name);
+LCRYPTO_USED(X509_TRUST_get_trust);
+LCRYPTO_USED(X509_up_ref);
+LCRYPTO_USED(X509_chain_up_ref);
+LCRYPTO_USED(ERR_load_X509_strings);
+
+#endif /* _LIBCRYPTO_X509_H */
diff --git a/crypto/hidden/openssl/x509_vfy.h b/crypto/hidden/openssl/x509_vfy.h
new file mode 100644
index 0000000..b5f2ac1
--- /dev/null
+++ b/crypto/hidden/openssl/x509_vfy.h
@@ -0,0 +1,156 @@
+/* $OpenBSD: x509_vfy.h,v 1.6 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_X509_VFY_H
+#define _LIBCRYPTO_X509_VFY_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/x509_vfy.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(X509_STORE_set_depth);
+LCRYPTO_USED(X509_STORE_CTX_set_depth);
+LCRYPTO_USED(X509_OBJECT_new);
+LCRYPTO_USED(X509_OBJECT_free);
+LCRYPTO_USED(X509_OBJECT_idx_by_subject);
+LCRYPTO_USED(X509_OBJECT_retrieve_by_subject);
+LCRYPTO_USED(X509_OBJECT_retrieve_match);
+LCRYPTO_USED(X509_OBJECT_up_ref_count);
+LCRYPTO_USED(X509_OBJECT_get_type);
+LCRYPTO_USED(X509_OBJECT_get0_X509);
+LCRYPTO_USED(X509_OBJECT_get0_X509_CRL);
+LCRYPTO_USED(X509_STORE_new);
+LCRYPTO_USED(X509_STORE_free);
+LCRYPTO_USED(X509_STORE_up_ref);
+LCRYPTO_USED(X509_STORE_get0_objects);
+LCRYPTO_USED(X509_STORE_get_ex_data);
+LCRYPTO_USED(X509_STORE_set_ex_data);
+LCRYPTO_USED(X509_STORE_set_flags);
+LCRYPTO_USED(X509_STORE_set_purpose);
+LCRYPTO_USED(X509_STORE_set_trust);
+LCRYPTO_USED(X509_STORE_set1_param);
+LCRYPTO_USED(X509_STORE_get0_param);
+LCRYPTO_USED(X509_STORE_get_verify_cb);
+LCRYPTO_USED(X509_STORE_set_verify_cb);
+LCRYPTO_USED(X509_STORE_get_check_issued);
+LCRYPTO_USED(X509_STORE_set_check_issued);
+LCRYPTO_USED(X509_STORE_CTX_get_check_issued);
+LCRYPTO_USED(X509_STORE_CTX_new);
+LCRYPTO_USED(X509_STORE_CTX_get1_issuer);
+LCRYPTO_USED(X509_STORE_CTX_free);
+LCRYPTO_USED(X509_STORE_CTX_init);
+LCRYPTO_USED(X509_STORE_CTX_get0_cert);
+LCRYPTO_USED(X509_STORE_CTX_get0_chain);
+LCRYPTO_USED(X509_STORE_CTX_get0_store);
+LCRYPTO_USED(X509_STORE_CTX_get0_untrusted);
+LCRYPTO_USED(X509_STORE_CTX_set0_untrusted);
+LCRYPTO_USED(X509_STORE_CTX_get1_certs);
+LCRYPTO_USED(X509_STORE_CTX_get1_crls);
+LCRYPTO_USED(X509_STORE_CTX_trusted_stack);
+LCRYPTO_USED(X509_STORE_CTX_set0_trusted_stack);
+LCRYPTO_USED(X509_STORE_CTX_cleanup);
+LCRYPTO_USED(X509_STORE_add_lookup);
+LCRYPTO_USED(X509_LOOKUP_hash_dir);
+LCRYPTO_USED(X509_LOOKUP_file);
+LCRYPTO_USED(X509_LOOKUP_mem);
+LCRYPTO_USED(X509_STORE_add_cert);
+LCRYPTO_USED(X509_STORE_add_crl);
+LCRYPTO_USED(X509_STORE_CTX_get_by_subject);
+LCRYPTO_USED(X509_STORE_CTX_get_obj_by_subject);
+LCRYPTO_USED(X509_LOOKUP_ctrl);
+LCRYPTO_USED(X509_load_cert_file);
+LCRYPTO_USED(X509_load_crl_file);
+LCRYPTO_USED(X509_load_cert_crl_file);
+LCRYPTO_USED(X509_LOOKUP_new);
+LCRYPTO_USED(X509_LOOKUP_free);
+LCRYPTO_USED(X509_LOOKUP_init);
+LCRYPTO_USED(X509_LOOKUP_by_subject);
+LCRYPTO_USED(X509_LOOKUP_by_issuer_serial);
+LCRYPTO_USED(X509_LOOKUP_by_fingerprint);
+LCRYPTO_USED(X509_LOOKUP_by_alias);
+LCRYPTO_USED(X509_LOOKUP_shutdown);
+LCRYPTO_USED(X509_STORE_load_locations);
+LCRYPTO_USED(X509_STORE_load_mem);
+LCRYPTO_USED(X509_STORE_set_default_paths);
+LCRYPTO_USED(X509_STORE_CTX_get_ex_new_index);
+LCRYPTO_USED(X509_STORE_CTX_set_ex_data);
+LCRYPTO_USED(X509_STORE_CTX_get_ex_data);
+LCRYPTO_USED(X509_STORE_CTX_get_error);
+LCRYPTO_USED(X509_STORE_CTX_set_error);
+LCRYPTO_USED(X509_STORE_CTX_get_error_depth);
+LCRYPTO_USED(X509_STORE_CTX_set_error_depth);
+LCRYPTO_USED(X509_STORE_CTX_get_current_cert);
+LCRYPTO_USED(X509_STORE_CTX_set_current_cert);
+LCRYPTO_USED(X509_STORE_CTX_get0_current_issuer);
+LCRYPTO_USED(X509_STORE_CTX_get0_current_crl);
+LCRYPTO_USED(X509_STORE_CTX_get0_parent_ctx);
+LCRYPTO_USED(X509_STORE_CTX_get_chain);
+LCRYPTO_USED(X509_STORE_CTX_get1_chain);
+LCRYPTO_USED(X509_STORE_CTX_set_cert);
+LCRYPTO_USED(X509_STORE_CTX_set_chain);
+LCRYPTO_USED(X509_STORE_CTX_set0_crls);
+LCRYPTO_USED(X509_STORE_CTX_set_purpose);
+LCRYPTO_USED(X509_STORE_CTX_set_trust);
+LCRYPTO_USED(X509_STORE_CTX_purpose_inherit);
+LCRYPTO_USED(X509_STORE_CTX_set_flags);
+LCRYPTO_USED(X509_STORE_CTX_set_time);
+LCRYPTO_USED(X509_STORE_CTX_set0_verified_chain);
+LCRYPTO_USED(X509_STORE_CTX_get_verify);
+LCRYPTO_USED(X509_STORE_CTX_set_verify);
+LCRYPTO_USED(X509_STORE_CTX_get_verify_cb);
+LCRYPTO_USED(X509_STORE_CTX_set_verify_cb);
+LCRYPTO_USED(X509_STORE_set_verify);
+LCRYPTO_USED(X509_STORE_get_verify);
+LCRYPTO_USED(X509_STORE_CTX_get_num_untrusted);
+LCRYPTO_USED(X509_STORE_CTX_get0_param);
+LCRYPTO_USED(X509_STORE_CTX_set0_param);
+LCRYPTO_USED(X509_STORE_CTX_set_default);
+LCRYPTO_USED(X509_VERIFY_PARAM_new);
+LCRYPTO_USED(X509_VERIFY_PARAM_free);
+LCRYPTO_USED(X509_VERIFY_PARAM_inherit);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_name);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_flags);
+LCRYPTO_USED(X509_VERIFY_PARAM_clear_flags);
+LCRYPTO_USED(X509_VERIFY_PARAM_get_flags);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_purpose);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_trust);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_depth);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_auth_level);
+LCRYPTO_USED(X509_VERIFY_PARAM_get_time);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_time);
+LCRYPTO_USED(X509_VERIFY_PARAM_add0_policy);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_policies);
+LCRYPTO_USED(X509_VERIFY_PARAM_get_depth);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_host);
+LCRYPTO_USED(X509_VERIFY_PARAM_add1_host);
+LCRYPTO_USED(X509_VERIFY_PARAM_set_hostflags);
+LCRYPTO_USED(X509_VERIFY_PARAM_get0_peername);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_email);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_ip);
+LCRYPTO_USED(X509_VERIFY_PARAM_set1_ip_asc);
+LCRYPTO_USED(X509_VERIFY_PARAM_get0_name);
+LCRYPTO_USED(X509_VERIFY_PARAM_get0);
+LCRYPTO_USED(X509_VERIFY_PARAM_get_count);
+LCRYPTO_USED(X509_VERIFY_PARAM_add0_table);
+LCRYPTO_USED(X509_VERIFY_PARAM_lookup);
+LCRYPTO_USED(X509_VERIFY_PARAM_table_cleanup);
+
+#endif /* _LIBCRYPTO_X509_VFY_H */
diff --git a/crypto/hidden/openssl/x509v3.h b/crypto/hidden/openssl/x509v3.h
new file mode 100644
index 0000000..a85c5c2
--- /dev/null
+++ b/crypto/hidden/openssl/x509v3.h
@@ -0,0 +1,265 @@
+/* $OpenBSD: x509v3.h,v 1.5 2023/07/05 21:14:54 bcook Exp $ */
+/*
+ * Copyright (c) 2022 Bob Beck 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _LIBCRYPTO_X509V3_H
+#define _LIBCRYPTO_X509V3_H
+
+#ifndef _MSC_VER
+#include_next 
+#else
+#include "../include/openssl/x509v3.h"
+#endif
+#include "crypto_namespace.h"
+
+LCRYPTO_USED(BASIC_CONSTRAINTS_new);
+LCRYPTO_USED(BASIC_CONSTRAINTS_free);
+LCRYPTO_USED(d2i_BASIC_CONSTRAINTS);
+LCRYPTO_USED(i2d_BASIC_CONSTRAINTS);
+LCRYPTO_USED(AUTHORITY_KEYID_new);
+LCRYPTO_USED(AUTHORITY_KEYID_free);
+LCRYPTO_USED(d2i_AUTHORITY_KEYID);
+LCRYPTO_USED(i2d_AUTHORITY_KEYID);
+LCRYPTO_USED(PKEY_USAGE_PERIOD_new);
+LCRYPTO_USED(PKEY_USAGE_PERIOD_free);
+LCRYPTO_USED(d2i_PKEY_USAGE_PERIOD);
+LCRYPTO_USED(i2d_PKEY_USAGE_PERIOD);
+LCRYPTO_USED(GENERAL_NAME_new);
+LCRYPTO_USED(GENERAL_NAME_free);
+LCRYPTO_USED(d2i_GENERAL_NAME);
+LCRYPTO_USED(i2d_GENERAL_NAME);
+LCRYPTO_USED(GENERAL_NAME_dup);
+LCRYPTO_USED(GENERAL_NAME_cmp);
+LCRYPTO_USED(v2i_ASN1_BIT_STRING);
+LCRYPTO_USED(i2v_ASN1_BIT_STRING);
+LCRYPTO_USED(i2v_GENERAL_NAME);
+LCRYPTO_USED(GENERAL_NAME_print);
+LCRYPTO_USED(GENERAL_NAMES_new);
+LCRYPTO_USED(GENERAL_NAMES_free);
+LCRYPTO_USED(d2i_GENERAL_NAMES);
+LCRYPTO_USED(i2d_GENERAL_NAMES);
+LCRYPTO_USED(i2v_GENERAL_NAMES);
+LCRYPTO_USED(v2i_GENERAL_NAMES);
+LCRYPTO_USED(OTHERNAME_new);
+LCRYPTO_USED(OTHERNAME_free);
+LCRYPTO_USED(d2i_OTHERNAME);
+LCRYPTO_USED(i2d_OTHERNAME);
+LCRYPTO_USED(EDIPARTYNAME_new);
+LCRYPTO_USED(EDIPARTYNAME_free);
+LCRYPTO_USED(d2i_EDIPARTYNAME);
+LCRYPTO_USED(i2d_EDIPARTYNAME);
+LCRYPTO_USED(OTHERNAME_cmp);
+LCRYPTO_USED(GENERAL_NAME_set0_value);
+LCRYPTO_USED(GENERAL_NAME_get0_value);
+LCRYPTO_USED(GENERAL_NAME_set0_othername);
+LCRYPTO_USED(GENERAL_NAME_get0_otherName);
+LCRYPTO_USED(i2s_ASN1_OCTET_STRING);
+LCRYPTO_USED(s2i_ASN1_OCTET_STRING);
+LCRYPTO_USED(EXTENDED_KEY_USAGE_new);
+LCRYPTO_USED(EXTENDED_KEY_USAGE_free);
+LCRYPTO_USED(d2i_EXTENDED_KEY_USAGE);
+LCRYPTO_USED(i2d_EXTENDED_KEY_USAGE);
+LCRYPTO_USED(i2a_ACCESS_DESCRIPTION);
+LCRYPTO_USED(CERTIFICATEPOLICIES_new);
+LCRYPTO_USED(CERTIFICATEPOLICIES_free);
+LCRYPTO_USED(d2i_CERTIFICATEPOLICIES);
+LCRYPTO_USED(i2d_CERTIFICATEPOLICIES);
+LCRYPTO_USED(POLICYINFO_new);
+LCRYPTO_USED(POLICYINFO_free);
+LCRYPTO_USED(d2i_POLICYINFO);
+LCRYPTO_USED(i2d_POLICYINFO);
+LCRYPTO_USED(POLICYQUALINFO_new);
+LCRYPTO_USED(POLICYQUALINFO_free);
+LCRYPTO_USED(d2i_POLICYQUALINFO);
+LCRYPTO_USED(i2d_POLICYQUALINFO);
+LCRYPTO_USED(USERNOTICE_new);
+LCRYPTO_USED(USERNOTICE_free);
+LCRYPTO_USED(d2i_USERNOTICE);
+LCRYPTO_USED(i2d_USERNOTICE);
+LCRYPTO_USED(NOTICEREF_new);
+LCRYPTO_USED(NOTICEREF_free);
+LCRYPTO_USED(d2i_NOTICEREF);
+LCRYPTO_USED(i2d_NOTICEREF);
+LCRYPTO_USED(CRL_DIST_POINTS_new);
+LCRYPTO_USED(CRL_DIST_POINTS_free);
+LCRYPTO_USED(d2i_CRL_DIST_POINTS);
+LCRYPTO_USED(i2d_CRL_DIST_POINTS);
+LCRYPTO_USED(DIST_POINT_new);
+LCRYPTO_USED(DIST_POINT_free);
+LCRYPTO_USED(d2i_DIST_POINT);
+LCRYPTO_USED(i2d_DIST_POINT);
+LCRYPTO_USED(DIST_POINT_NAME_new);
+LCRYPTO_USED(DIST_POINT_NAME_free);
+LCRYPTO_USED(d2i_DIST_POINT_NAME);
+LCRYPTO_USED(i2d_DIST_POINT_NAME);
+LCRYPTO_USED(ISSUING_DIST_POINT_new);
+LCRYPTO_USED(ISSUING_DIST_POINT_free);
+LCRYPTO_USED(d2i_ISSUING_DIST_POINT);
+LCRYPTO_USED(i2d_ISSUING_DIST_POINT);
+LCRYPTO_USED(DIST_POINT_set_dpname);
+LCRYPTO_USED(NAME_CONSTRAINTS_check);
+LCRYPTO_USED(ACCESS_DESCRIPTION_new);
+LCRYPTO_USED(ACCESS_DESCRIPTION_free);
+LCRYPTO_USED(d2i_ACCESS_DESCRIPTION);
+LCRYPTO_USED(i2d_ACCESS_DESCRIPTION);
+LCRYPTO_USED(AUTHORITY_INFO_ACCESS_new);
+LCRYPTO_USED(AUTHORITY_INFO_ACCESS_free);
+LCRYPTO_USED(d2i_AUTHORITY_INFO_ACCESS);
+LCRYPTO_USED(i2d_AUTHORITY_INFO_ACCESS);
+LCRYPTO_USED(POLICY_MAPPING_new);
+LCRYPTO_USED(POLICY_MAPPING_free);
+LCRYPTO_USED(GENERAL_SUBTREE_new);
+LCRYPTO_USED(GENERAL_SUBTREE_free);
+LCRYPTO_USED(NAME_CONSTRAINTS_new);
+LCRYPTO_USED(NAME_CONSTRAINTS_free);
+LCRYPTO_USED(POLICY_CONSTRAINTS_new);
+LCRYPTO_USED(POLICY_CONSTRAINTS_free);
+LCRYPTO_USED(a2i_GENERAL_NAME);
+LCRYPTO_USED(v2i_GENERAL_NAME);
+LCRYPTO_USED(v2i_GENERAL_NAME_ex);
+LCRYPTO_USED(X509V3_conf_free);
+LCRYPTO_USED(X509V3_EXT_nconf_nid);
+LCRYPTO_USED(X509V3_EXT_nconf);
+LCRYPTO_USED(X509V3_EXT_add_nconf_sk);
+LCRYPTO_USED(X509V3_EXT_add_nconf);
+LCRYPTO_USED(X509V3_EXT_REQ_add_nconf);
+LCRYPTO_USED(X509V3_EXT_CRL_add_nconf);
+LCRYPTO_USED(X509V3_EXT_conf_nid);
+LCRYPTO_USED(X509V3_EXT_conf);
+LCRYPTO_USED(X509V3_EXT_add_conf);
+LCRYPTO_USED(X509V3_EXT_REQ_add_conf);
+LCRYPTO_USED(X509V3_EXT_CRL_add_conf);
+LCRYPTO_USED(X509V3_add_value_bool_nf);
+LCRYPTO_USED(X509V3_get_value_bool);
+LCRYPTO_USED(X509V3_get_value_int);
+LCRYPTO_USED(X509V3_set_nconf);
+LCRYPTO_USED(X509V3_set_conf_lhash);
+LCRYPTO_USED(X509V3_get_string);
+LCRYPTO_USED(X509V3_get_section);
+LCRYPTO_USED(X509V3_string_free);
+LCRYPTO_USED(X509V3_section_free);
+LCRYPTO_USED(X509V3_set_ctx);
+LCRYPTO_USED(X509V3_add_value);
+LCRYPTO_USED(X509V3_add_value_uchar);
+LCRYPTO_USED(X509V3_add_value_bool);
+LCRYPTO_USED(X509V3_add_value_int);
+LCRYPTO_USED(i2s_ASN1_INTEGER);
+LCRYPTO_USED(s2i_ASN1_INTEGER);
+LCRYPTO_USED(i2s_ASN1_ENUMERATED);
+LCRYPTO_USED(i2s_ASN1_ENUMERATED_TABLE);
+LCRYPTO_USED(X509V3_EXT_add);
+LCRYPTO_USED(X509V3_EXT_add_list);
+LCRYPTO_USED(X509V3_EXT_add_alias);
+LCRYPTO_USED(X509V3_EXT_cleanup);
+LCRYPTO_USED(X509V3_EXT_get);
+LCRYPTO_USED(X509V3_EXT_get_nid);
+LCRYPTO_USED(X509V3_add_standard_extensions);
+LCRYPTO_USED(X509V3_parse_list);
+LCRYPTO_USED(X509V3_EXT_d2i);
+LCRYPTO_USED(X509V3_get_d2i);
+LCRYPTO_USED(X509V3_EXT_i2d);
+LCRYPTO_USED(X509V3_add1_i2d);
+LCRYPTO_USED(hex_to_string);
+LCRYPTO_USED(string_to_hex);
+LCRYPTO_USED(X509V3_EXT_val_prn);
+LCRYPTO_USED(X509V3_EXT_print);
+LCRYPTO_USED(X509V3_EXT_print_fp);
+LCRYPTO_USED(X509V3_extensions_print);
+LCRYPTO_USED(X509_check_ca);
+LCRYPTO_USED(X509_check_purpose);
+LCRYPTO_USED(X509_supported_extension);
+LCRYPTO_USED(X509_PURPOSE_set);
+LCRYPTO_USED(X509_check_issued);
+LCRYPTO_USED(X509_check_akid);
+LCRYPTO_USED(X509_PURPOSE_get_count);
+LCRYPTO_USED(X509_PURPOSE_get0);
+LCRYPTO_USED(X509_PURPOSE_get_by_sname);
+LCRYPTO_USED(X509_PURPOSE_get_by_id);
+LCRYPTO_USED(X509_PURPOSE_add);
+LCRYPTO_USED(X509_PURPOSE_get0_name);
+LCRYPTO_USED(X509_PURPOSE_get0_sname);
+LCRYPTO_USED(X509_PURPOSE_get_trust);
+LCRYPTO_USED(X509_PURPOSE_cleanup);
+LCRYPTO_USED(X509_PURPOSE_get_id);
+LCRYPTO_USED(X509_get_extension_flags);
+LCRYPTO_USED(X509_get_key_usage);
+LCRYPTO_USED(X509_get_extended_key_usage);
+LCRYPTO_USED(X509_get1_email);
+LCRYPTO_USED(X509_REQ_get1_email);
+LCRYPTO_USED(X509_email_free);
+LCRYPTO_USED(X509_get1_ocsp);
+LCRYPTO_USED(X509_check_host);
+LCRYPTO_USED(X509_check_email);
+LCRYPTO_USED(X509_check_ip);
+LCRYPTO_USED(X509_check_ip_asc);
+LCRYPTO_USED(a2i_IPADDRESS);
+LCRYPTO_USED(a2i_IPADDRESS_NC);
+LCRYPTO_USED(a2i_ipadd);
+LCRYPTO_USED(X509V3_NAME_from_section);
+LCRYPTO_USED(ASRange_new);
+LCRYPTO_USED(ASRange_free);
+LCRYPTO_USED(d2i_ASRange);
+LCRYPTO_USED(i2d_ASRange);
+LCRYPTO_USED(ASIdOrRange_new);
+LCRYPTO_USED(ASIdOrRange_free);
+LCRYPTO_USED(d2i_ASIdOrRange);
+LCRYPTO_USED(i2d_ASIdOrRange);
+LCRYPTO_USED(ASIdentifierChoice_new);
+LCRYPTO_USED(ASIdentifierChoice_free);
+LCRYPTO_USED(d2i_ASIdentifierChoice);
+LCRYPTO_USED(i2d_ASIdentifierChoice);
+LCRYPTO_USED(ASIdentifiers_new);
+LCRYPTO_USED(ASIdentifiers_free);
+LCRYPTO_USED(d2i_ASIdentifiers);
+LCRYPTO_USED(i2d_ASIdentifiers);
+LCRYPTO_USED(IPAddressRange_new);
+LCRYPTO_USED(IPAddressRange_free);
+LCRYPTO_USED(d2i_IPAddressRange);
+LCRYPTO_USED(i2d_IPAddressRange);
+LCRYPTO_USED(IPAddressOrRange_new);
+LCRYPTO_USED(IPAddressOrRange_free);
+LCRYPTO_USED(d2i_IPAddressOrRange);
+LCRYPTO_USED(i2d_IPAddressOrRange);
+LCRYPTO_USED(IPAddressChoice_new);
+LCRYPTO_USED(IPAddressChoice_free);
+LCRYPTO_USED(d2i_IPAddressChoice);
+LCRYPTO_USED(i2d_IPAddressChoice);
+LCRYPTO_USED(IPAddressFamily_new);
+LCRYPTO_USED(IPAddressFamily_free);
+LCRYPTO_USED(d2i_IPAddressFamily);
+LCRYPTO_USED(i2d_IPAddressFamily);
+LCRYPTO_USED(X509v3_asid_add_inherit);
+LCRYPTO_USED(X509v3_asid_add_id_or_range);
+LCRYPTO_USED(X509v3_addr_add_inherit);
+LCRYPTO_USED(X509v3_addr_add_prefix);
+LCRYPTO_USED(X509v3_addr_add_range);
+LCRYPTO_USED(X509v3_addr_get_afi);
+LCRYPTO_USED(X509v3_addr_get_range);
+LCRYPTO_USED(X509v3_asid_is_canonical);
+LCRYPTO_USED(X509v3_addr_is_canonical);
+LCRYPTO_USED(X509v3_asid_canonize);
+LCRYPTO_USED(X509v3_addr_canonize);
+LCRYPTO_USED(X509v3_asid_inherits);
+LCRYPTO_USED(X509v3_addr_inherits);
+LCRYPTO_USED(X509v3_asid_subset);
+LCRYPTO_USED(X509v3_addr_subset);
+LCRYPTO_USED(X509v3_asid_validate_path);
+LCRYPTO_USED(X509v3_addr_validate_path);
+LCRYPTO_USED(X509v3_asid_validate_resource_set);
+LCRYPTO_USED(X509v3_addr_validate_resource_set);
+LCRYPTO_USED(ERR_load_X509V3_strings);
+
+#endif /* _LIBCRYPTO_X509V3_H */
diff --git a/crypto/hkdf/hkdf.c b/crypto/hkdf/hkdf.c
new file mode 100644
index 0000000..4f9c9e5
--- /dev/null
+++ b/crypto/hkdf/hkdf.c
@@ -0,0 +1,123 @@
+/* $OpenBSD: hkdf.c,v 1.10 2023/07/07 13:54:46 beck Exp $ */
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "evp_local.h"
+#include "hmac_local.h"
+
+/* https://tools.ietf.org/html/rfc5869#section-2 */
+int
+HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
+    const uint8_t *secret, size_t secret_len, const uint8_t *salt,
+    size_t salt_len, const uint8_t *info, size_t info_len)
+{
+	uint8_t prk[EVP_MAX_MD_SIZE];
+	size_t prk_len;
+
+	if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
+	    salt_len))
+		return 0;
+	if (!HKDF_expand(out_key, out_len, digest, prk, prk_len, info,
+	    info_len))
+		return 0;
+
+	return 1;
+}
+LCRYPTO_ALIAS(HKDF);
+
+/* https://tools.ietf.org/html/rfc5869#section-2.2 */
+int
+HKDF_extract(uint8_t *out_key, size_t *out_len,
+    const EVP_MD *digest, const uint8_t *secret, size_t secret_len,
+    const uint8_t *salt, size_t salt_len)
+{
+	unsigned int len;
+
+	/*
+	 * If salt is not given, HashLength zeros are used. However, HMAC does
+	 * that internally already so we can ignore it.
+	 */
+	if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) ==
+	    NULL) {
+		CRYPTOerror(ERR_R_CRYPTO_LIB);
+		return 0;
+	}
+	*out_len = len;
+	return 1;
+}
+LCRYPTO_ALIAS(HKDF_extract);
+
+/* https://tools.ietf.org/html/rfc5869#section-2.3 */
+int
+HKDF_expand(uint8_t *out_key, size_t out_len,
+    const EVP_MD *digest, const uint8_t *prk, size_t prk_len,
+    const uint8_t *info, size_t info_len)
+{
+	const size_t digest_len = EVP_MD_size(digest);
+	uint8_t previous[EVP_MAX_MD_SIZE];
+	size_t n, done = 0;
+	unsigned int i;
+	int ret = 0;
+	HMAC_CTX hmac;
+
+	/* Expand key material to desired length. */
+	n = (out_len + digest_len - 1) / digest_len;
+	if (out_len + digest_len < out_len || n > 255) {
+		CRYPTOerror(EVP_R_TOO_LARGE);
+		return 0;
+	}
+
+	HMAC_CTX_init(&hmac);
+	if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL))
+		goto out;
+
+	for (i = 0; i < n; i++) {
+		uint8_t ctr = i + 1;
+		size_t todo;
+
+		if (i != 0 && (!HMAC_Init_ex(&hmac, NULL, 0, NULL, NULL) ||
+		    !HMAC_Update(&hmac, previous, digest_len)))
+			goto out;
+
+		if (!HMAC_Update(&hmac, info, info_len) ||
+		    !HMAC_Update(&hmac, &ctr, 1) ||
+		    !HMAC_Final(&hmac, previous, NULL))
+			goto out;
+
+		todo = digest_len;
+		if (todo > out_len - done)
+			todo = out_len - done;
+
+		memcpy(out_key + done, previous, todo);
+		done += todo;
+	}
+
+	ret = 1;
+
+ out:
+	HMAC_CTX_cleanup(&hmac);
+	explicit_bzero(previous, sizeof(previous));
+	if (ret != 1)
+		CRYPTOerror(ERR_R_CRYPTO_LIB);
+	return ret;
+}
+LCRYPTO_ALIAS(HKDF_expand);
diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c
new file mode 100644
index 0000000..7e6ad6d
--- /dev/null
+++ b/crypto/hmac/hm_ameth.c
@@ -0,0 +1,171 @@
+/* $OpenBSD: hm_ameth.c,v 1.19 2022/11/26 16:08:53 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2007.
+ */
+/* ====================================================================
+ * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bytestring.h"
+#include "evp_local.h"
+#include "hmac_local.h"
+
+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(a->pkey.ptr, b->pkey.ptr) == 0;
+}
+
+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;
+
+	if ((os = pkey->pkey.ptr) == NULL)
+		return;
+
+	if (os->data != NULL)
+		explicit_bzero(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_sha1;
+		return 1;
+	default:
+		return -2;
+	}
+}
+
+static int
+hmac_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, size_t len)
+{
+	ASN1_OCTET_STRING *os = NULL;
+
+	if (pkey->pkey.ptr != NULL)
+		goto err;
+
+	if (len > INT_MAX)
+		goto err;
+
+	if ((os = ASN1_OCTET_STRING_new()) == NULL)
+		goto err;
+
+	if (!ASN1_OCTET_STRING_set(os, priv, len))
+		goto err;
+
+	pkey->pkey.ptr = os;
+
+	return 1;
+
+ err:
+	ASN1_OCTET_STRING_free(os);
+
+	return 0;
+}
+
+static int
+hmac_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, size_t *len)
+{
+	ASN1_OCTET_STRING *os;
+	CBS cbs;
+
+	if ((os = pkey->pkey.ptr) == NULL)
+		return 0;
+
+	if (priv == NULL) {
+		*len = os->length;
+		return 1;
+	}
+
+	CBS_init(&cbs, os->data, os->length);
+	return CBS_write_bytes(&cbs, priv, *len, len);
+}
+
+const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
+	.pkey_id = EVP_PKEY_HMAC,
+	.pkey_base_id = EVP_PKEY_HMAC,
+
+	.pem_str = "HMAC",
+	.info = "OpenSSL HMAC method",
+
+	.pub_cmp = hmac_pkey_public_cmp,
+
+	.pkey_size = hmac_size,
+
+	.pkey_free = hmac_key_free,
+	.pkey_ctrl = hmac_pkey_ctrl,
+
+	.set_priv_key = hmac_set_priv_key,
+	.get_priv_key = hmac_get_priv_key,
+};
diff --git a/crypto/hmac/hm_pmeth.c b/crypto/hmac/hm_pmeth.c
new file mode 100644
index 0000000..bb043d1
--- /dev/null
+++ b/crypto/hmac/hm_pmeth.c
@@ -0,0 +1,254 @@
+/* $OpenBSD: hm_pmeth.c,v 1.15 2022/11/26 16:08:53 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2007.
+ */
+/* ====================================================================
+ * Copyright (c) 2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "hmac_local.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 = calloc(1, sizeof(HMAC_PKEY_CTX))) == NULL)
+		return 0;
+
+	hctx->ktmp.type = V_ASN1_OCTET_STRING;
+	HMAC_CTX_init(&hctx->ctx);
+
+	ctx->data = hctx;
+	ctx->keygen_info_count = 0;
+
+	return 1;
+}
+
+static int
+pkey_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	HMAC_PKEY_CTX *sctx, *dctx;
+
+	if (!pkey_hmac_init(dst))
+		return 0;
+	sctx = src->data;
+	dctx = dst->data;
+	dctx->md = sctx->md;
+	HMAC_CTX_init(&dctx->ctx);
+	if (!HMAC_CTX_copy(&dctx->ctx, &sctx->ctx))
+		return 0;
+	if (sctx->ktmp.data) {
+		if (!ASN1_OCTET_STRING_set(&dctx->ktmp, sctx->ktmp.data,
+		    sctx->ktmp.length))
+			return 0;
+	}
+	return 1;
+}
+
+static void
+pkey_hmac_cleanup(EVP_PKEY_CTX *ctx)
+{
+	HMAC_PKEY_CTX *hctx;
+
+	if ((hctx = ctx->data) == NULL)
+		return;
+
+	HMAC_CTX_cleanup(&hctx->ctx);
+	freezero(hctx->ktmp.data, hctx->ktmp.length);
+	free(hctx);
+}
+
+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 = ctx->pctx->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, mctx->flags & ~EVP_MD_CTX_FLAG_NO_INIT);
+	EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
+	mctx->update = 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 = 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")) {
+		void *p = (void *)value;
+		return pkey_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, -1, p);
+	}
+	if (!strcmp(type, "hexkey")) {
+		unsigned char *key;
+		int r;
+		long keylen;
+		key = string_to_hex(value, &keylen);
+		if (!key)
+			return 0;
+		r = pkey_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key);
+		free(key);
+		return r;
+	}
+	return -2;
+}
+
+const EVP_PKEY_METHOD hmac_pkey_meth = {
+	.pkey_id = EVP_PKEY_HMAC,
+
+	.init = pkey_hmac_init,
+	.copy = pkey_hmac_copy,
+	.cleanup = pkey_hmac_cleanup,
+
+	.keygen = pkey_hmac_keygen,
+
+	.signctx_init = hmac_signctx_init,
+	.signctx = hmac_signctx,
+
+	.ctrl = pkey_hmac_ctrl,
+	.ctrl_str = pkey_hmac_ctrl_str
+};
diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
new file mode 100644
index 0000000..ea3a1b4
--- /dev/null
+++ b/crypto/hmac/hmac.c
@@ -0,0 +1,293 @@
+/* $OpenBSD: hmac.c,v 1.31 2023/02/16 08:38:17 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "evp_local.h"
+#include "hmac_local.h"
+
+int
+HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md,
+    ENGINE *impl)
+{
+	int i, j, reset = 0;
+	unsigned char pad[HMAC_MAX_MD_CBLOCK];
+
+	/* If we are changing MD then we must have a key */
+	if (md != NULL && md != ctx->md && (key == NULL || len < 0))
+		return 0;
+
+	if (md != NULL) {
+		reset = 1;
+		ctx->md = md;
+	} else if (ctx->md != NULL)
+		md = ctx->md;
+	else
+		return 0;
+
+	if (key != NULL) {
+		reset = 1;
+		j = EVP_MD_block_size(md);
+		if ((size_t)j > sizeof(ctx->key)) {
+			EVPerror(EVP_R_BAD_BLOCK_LENGTH);
+			goto err;
+		}
+		if (j < len) {
+			if (!EVP_DigestInit_ex(&ctx->md_ctx, md, impl))
+				goto err;
+			if (!EVP_DigestUpdate(&ctx->md_ctx, key, len))
+				goto err;
+			if (!EVP_DigestFinal_ex(&(ctx->md_ctx), ctx->key,
+			    &ctx->key_length))
+				goto err;
+		} else {
+			if (len < 0 || (size_t)len > sizeof(ctx->key)) {
+				EVPerror(EVP_R_BAD_KEY_LENGTH);
+				goto err;
+			}
+			memcpy(ctx->key, key, len);
+			ctx->key_length = len;
+		}
+		if (ctx->key_length != HMAC_MAX_MD_CBLOCK)
+			memset(&ctx->key[ctx->key_length], 0,
+			    HMAC_MAX_MD_CBLOCK - ctx->key_length);
+	}
+
+	if (reset) {
+		for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++)
+			pad[i] = 0x36 ^ ctx->key[i];
+		if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl))
+			goto err;
+		if (!EVP_DigestUpdate(&ctx->i_ctx, pad, EVP_MD_block_size(md)))
+			goto err;
+
+		for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++)
+			pad[i] = 0x5c ^ ctx->key[i];
+		if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl))
+			goto err;
+		if (!EVP_DigestUpdate(&ctx->o_ctx, pad, EVP_MD_block_size(md)))
+			goto err;
+	}
+	if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->i_ctx))
+		goto err;
+	return 1;
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(HMAC_Init_ex);
+
+int
+HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
+{
+	if (key && md)
+		HMAC_CTX_init(ctx);
+	return HMAC_Init_ex(ctx, key, len, md, NULL);
+}
+
+int
+HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
+{
+	if (ctx->md == NULL)
+		return 0;
+
+	return EVP_DigestUpdate(&ctx->md_ctx, data, len);
+}
+LCRYPTO_ALIAS(HMAC_Update);
+
+int
+HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
+{
+	unsigned int i;
+	unsigned char buf[EVP_MAX_MD_SIZE];
+
+	if (ctx->md == NULL)
+		goto err;
+
+	if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i))
+		goto err;
+	if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx))
+		goto err;
+	if (!EVP_DigestUpdate(&ctx->md_ctx, buf, i))
+		goto err;
+	if (!EVP_DigestFinal_ex(&ctx->md_ctx, md, len))
+		goto err;
+	return 1;
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(HMAC_Final);
+
+HMAC_CTX *
+HMAC_CTX_new(void)
+{
+	HMAC_CTX *ctx;
+
+	if ((ctx = calloc(1, sizeof(*ctx))) == NULL)
+		return NULL;
+
+	HMAC_CTX_init(ctx);
+
+	return ctx;
+}
+LCRYPTO_ALIAS(HMAC_CTX_new);
+
+void
+HMAC_CTX_free(HMAC_CTX *ctx)
+{
+	if (ctx == NULL)
+		return;
+
+	HMAC_CTX_cleanup(ctx);
+
+	free(ctx);
+}
+LCRYPTO_ALIAS(HMAC_CTX_free);
+
+int
+HMAC_CTX_reset(HMAC_CTX *ctx)
+{
+	HMAC_CTX_cleanup(ctx);
+	HMAC_CTX_init(ctx);
+	return 1;
+}
+
+void
+HMAC_CTX_init(HMAC_CTX *ctx)
+{
+	EVP_MD_CTX_init(&ctx->i_ctx);
+	EVP_MD_CTX_init(&ctx->o_ctx);
+	EVP_MD_CTX_init(&ctx->md_ctx);
+	ctx->md = NULL;
+}
+
+int
+HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
+{
+	if (!EVP_MD_CTX_copy(&dctx->i_ctx, &sctx->i_ctx))
+		goto err;
+	if (!EVP_MD_CTX_copy(&dctx->o_ctx, &sctx->o_ctx))
+		goto err;
+	if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx))
+		goto err;
+	memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK);
+	dctx->key_length = sctx->key_length;
+	dctx->md = sctx->md;
+	return 1;
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(HMAC_CTX_copy);
+
+void
+HMAC_CTX_cleanup(HMAC_CTX *ctx)
+{
+	EVP_MD_CTX_cleanup(&ctx->i_ctx);
+	EVP_MD_CTX_cleanup(&ctx->o_ctx);
+	EVP_MD_CTX_cleanup(&ctx->md_ctx);
+	explicit_bzero(ctx, sizeof(*ctx));
+}
+
+void
+HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
+{
+	EVP_MD_CTX_set_flags(&ctx->i_ctx, flags);
+	EVP_MD_CTX_set_flags(&ctx->o_ctx, flags);
+	EVP_MD_CTX_set_flags(&ctx->md_ctx, flags);
+}
+LCRYPTO_ALIAS(HMAC_CTX_set_flags);
+
+const EVP_MD *
+HMAC_CTX_get_md(const HMAC_CTX *ctx)
+{
+	return ctx->md;
+}
+LCRYPTO_ALIAS(HMAC_CTX_get_md);
+
+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)
+{
+	HMAC_CTX c;
+	static unsigned char m[EVP_MAX_MD_SIZE];
+	const unsigned char dummy_key[1] = { 0 };
+
+	if (md == NULL)
+		md = m;
+	if (key == NULL) {
+		key = dummy_key;
+		key_len = 0;
+	}
+	HMAC_CTX_init(&c);
+	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_cleanup(&c);
+	return md;
+err:
+	HMAC_CTX_cleanup(&c);
+	return NULL;
+}
+LCRYPTO_ALIAS(HMAC);
diff --git a/crypto/hmac/hmac_local.h b/crypto/hmac/hmac_local.h
new file mode 100644
index 0000000..e06cd6a
--- /dev/null
+++ b/crypto/hmac/hmac_local.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: hmac_local.h,v 1.4 2022/11/26 16:08:53 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+#ifndef HEADER_HMAC_LOCAL_H
+#define HEADER_HMAC_LOCAL_H
+
+#include 
+
+#include 
+
+#include "evp_local.h"
+
+__BEGIN_HIDDEN_DECLS
+
+struct hmac_ctx_st {
+	const EVP_MD *md;
+	EVP_MD_CTX md_ctx;
+	EVP_MD_CTX i_ctx;
+	EVP_MD_CTX o_ctx;
+	unsigned int key_length;
+	unsigned char key[HMAC_MAX_MD_CBLOCK];
+} /* HMAC_CTX */;
+
+void HMAC_CTX_init(HMAC_CTX *ctx);
+void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_HMAC_LOCAL_H */
diff --git a/crypto/idea/i_cbc.c b/crypto/idea/i_cbc.c
new file mode 100644
index 0000000..d751340
--- /dev/null
+++ b/crypto/idea/i_cbc.c
@@ -0,0 +1,176 @@
+/* $OpenBSD: i_cbc.c,v 1.6 2023/07/08 10:44:00 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "idea_local.h"
+
+void
+idea_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int encrypt)
+{
+	unsigned long tin0, tin1;
+	unsigned long tout0, tout1, xor0, xor1;
+	long l = length;
+	unsigned long tin[2];
+
+	if (encrypt) {
+		n2l(iv, tout0);
+		n2l(iv, tout1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8)
+		{
+			n2l(in, tin0);
+			n2l(in, tin1);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			idea_encrypt(tin, ks);
+			tout0 = tin[0];
+			l2n(tout0, out);
+			tout1 = tin[1];
+			l2n(tout1, out);
+		}
+		if (l != -8) {
+			n2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			idea_encrypt(tin, ks);
+			tout0 = tin[0];
+			l2n(tout0, out);
+			tout1 = tin[1];
+			l2n(tout1, out);
+		}
+		l2n(tout0, iv);
+		l2n(tout1, iv);
+	} else {
+		n2l(iv, xor0);
+		n2l(iv, xor1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8)
+		{
+			n2l(in, tin0);
+			tin[0] = tin0;
+			n2l(in, tin1);
+			tin[1] = tin1;
+			idea_encrypt(tin, ks);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2n(tout0, out);
+			l2n(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			n2l(in, tin0);
+			tin[0] = tin0;
+			n2l(in, tin1);
+			tin[1] = tin1;
+			idea_encrypt(tin, ks);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2nn(tout0, tout1, out, l + 8);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		l2n(xor0, iv);
+		l2n(xor1, iv);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+LCRYPTO_ALIAS(idea_cbc_encrypt);
+
+void
+idea_encrypt(unsigned long *d, IDEA_KEY_SCHEDULE *key)
+{
+	IDEA_INT *p;
+	unsigned long x1, x2, x3, x4, t0, t1, ul;
+
+	x2 = d[0];
+	x1 = (x2 >> 16);
+	x4 = d[1];
+	x3 = (x4 >> 16);
+
+	p = &(key->data[0][0]);
+
+	E_IDEA(0);
+	E_IDEA(1);
+	E_IDEA(2);
+	E_IDEA(3);
+	E_IDEA(4);
+	E_IDEA(5);
+	E_IDEA(6);
+	E_IDEA(7);
+
+	x1 &= 0xffff;
+	idea_mul(x1, x1, *p, ul);
+	p++;
+
+	t0 = x3 + *(p++);
+	t1 = x2 + *(p++);
+
+	x4 &= 0xffff;
+	idea_mul(x4, x4, *p, ul);
+
+	d[0] = (t0 & 0xffff)|((x1 & 0xffff) << 16);
+	d[1] = (x4 & 0xffff)|((t1 & 0xffff) << 16);
+}
+LCRYPTO_ALIAS(idea_encrypt);
diff --git a/crypto/idea/i_cfb64.c b/crypto/idea/i_cfb64.c
new file mode 100644
index 0000000..a1a543f
--- /dev/null
+++ b/crypto/idea/i_cfb64.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: i_cfb64.c,v 1.6 2023/07/08 10:44:00 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "idea_local.h"
+
+/* The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+idea_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, IDEA_KEY_SCHEDULE *schedule,
+    unsigned char *ivec, int *num, int encrypt)
+{
+	unsigned long v0, v1, t;
+	int n = *num;
+	long l = length;
+	unsigned long ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = (unsigned char *)ivec;
+	if (encrypt) {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				idea_encrypt((unsigned long *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			c = *(in++) ^ iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1) & 0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				n2l(iv, v0);
+				ti[0] = v0;
+				n2l(iv, v1);
+				ti[1] = v1;
+				idea_encrypt((unsigned long *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2n(t, iv);
+				t = ti[1];
+				l2n(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			cc = *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c ^ cc;
+			n = (n + 1) & 0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = t = c = cc = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(idea_cfb64_encrypt);
diff --git a/crypto/idea/i_ecb.c b/crypto/idea/i_ecb.c
new file mode 100644
index 0000000..9f7db23
--- /dev/null
+++ b/crypto/idea/i_ecb.c
@@ -0,0 +1,80 @@
+/* $OpenBSD: i_ecb.c,v 1.7 2023/07/28 10:35:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "idea_local.h"
+#include 
+
+void
+idea_ecb_encrypt(const unsigned char *in, unsigned char *out,
+    IDEA_KEY_SCHEDULE *ks)
+{
+	unsigned long l0, l1, d[2];
+
+	n2l(in, l0);
+	d[0] = l0;
+	n2l(in, l1);
+	d[1] = l1;
+	idea_encrypt(d, ks);
+	l0 = d[0];
+	l2n(l0, out);
+	l1 = d[1];
+	l2n(l1, out);
+	l0 = l1 = d[0] = d[1] = 0;
+}
+LCRYPTO_ALIAS(idea_ecb_encrypt);
diff --git a/crypto/idea/i_ofb64.c b/crypto/idea/i_ofb64.c
new file mode 100644
index 0000000..5af394e
--- /dev/null
+++ b/crypto/idea/i_ofb64.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: i_ofb64.c,v 1.6 2023/07/08 10:44:00 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "idea_local.h"
+
+/* The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+idea_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, IDEA_KEY_SCHEDULE *schedule,
+    unsigned char *ivec, int *num)
+{
+	unsigned long v0, v1, t;
+	int n = *num;
+	long l = length;
+	unsigned char d[8];
+	char *dp;
+	unsigned long ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = (unsigned char *)ivec;
+	n2l(iv, v0);
+	n2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = (char *)d;
+	l2n(v0, dp);
+	l2n(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			idea_encrypt((unsigned long *)ti, schedule);
+			dp = (char *)d;
+			t = ti[0];
+			l2n(t, dp);
+			t = ti[1];
+			l2n(t, dp);
+			save++;
+		}
+		*(out++) = *(in++) ^ d[n];
+		n = (n + 1) & 0x07;
+	}
+	if (save) {
+		v0 = ti[0];
+		v1 = ti[1];
+		iv = (unsigned char *)ivec;
+		l2n(v0, iv);
+		l2n(v1, iv);
+	}
+	t = v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(idea_ofb64_encrypt);
diff --git a/crypto/idea/i_skey.c b/crypto/idea/i_skey.c
new file mode 100644
index 0000000..ad349bb
--- /dev/null
+++ b/crypto/idea/i_skey.c
@@ -0,0 +1,169 @@
+/* $OpenBSD: i_skey.c,v 1.7 2023/07/08 10:44:00 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include "idea_local.h"
+
+static IDEA_INT inverse(unsigned int xin);
+void
+idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks)
+{
+	int i;
+	IDEA_INT *kt, *kf, r0, r1, r2;
+
+	kt = &(ks->data[0][0]);
+	n2s(key, kt[0]);
+	n2s(key, kt[1]);
+	n2s(key, kt[2]);
+	n2s(key, kt[3]);
+	n2s(key, kt[4]);
+	n2s(key, kt[5]);
+	n2s(key, kt[6]);
+	n2s(key, kt[7]);
+
+	kf = kt;
+	kt += 8;
+	for (i = 0; i < 6; i++)
+	{
+		r2 = kf[1];
+		r1 = kf[2];
+		*(kt++) = ((r2 << 9) | (r1 >> 7)) & 0xffff;
+		r0 = kf[3];
+		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
+		r1 = kf[4];
+		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
+		r0 = kf[5];
+		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
+		r1 = kf[6];
+		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
+		r0 = kf[7];
+		*(kt++) = ((r1 << 9) | (r0 >> 7)) & 0xffff;
+		r1 = kf[0];
+		if (i >= 5)
+			break;
+		*(kt++) = ((r0 << 9) | (r1 >> 7)) & 0xffff;
+		*(kt++) = ((r1 << 9) | (r2 >> 7)) & 0xffff;
+		kf += 8;
+	}
+}
+LCRYPTO_ALIAS(idea_set_encrypt_key);
+
+void
+idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk)
+{
+	int r;
+	IDEA_INT *fp, *tp, t;
+
+	tp = &(dk->data[0][0]);
+	fp = &(ek->data[8][0]);
+	for (r = 0; r < 9; r++)
+	{
+		*(tp++) = inverse(fp[0]);
+		*(tp++) = ((int)(0x10000L - fp[2]) & 0xffff);
+		*(tp++) = ((int)(0x10000L - fp[1]) & 0xffff);
+		*(tp++) = inverse(fp[3]);
+		if (r == 8)
+			break;
+		fp -= 6;
+		*(tp++) = fp[4];
+		*(tp++) = fp[5];
+	}
+
+	tp = &(dk->data[0][0]);
+	t = tp[1];
+	tp[1] = tp[2];
+	tp[2] = t;
+
+	t = tp[49];
+	tp[49] = tp[50];
+	tp[50] = t;
+}
+LCRYPTO_ALIAS(idea_set_decrypt_key);
+
+/* taken directly from the 'paper' I'll have a look at it later */
+static IDEA_INT
+inverse(unsigned int xin)
+{
+	long n1, n2, q, r, b1, b2, t;
+
+	if (xin == 0)
+		b2 = 0;
+	else {
+		n1 = 0x10001;
+		n2 = xin;
+		b2 = 1;
+		b1 = 0;
+
+		do {
+			r = (n1 % n2);
+			q = (n1 - r)/n2;
+			if (r == 0) {
+				if (b2 < 0)
+					b2 = 0x10001 + b2;
+			} else {
+				n1 = n2;
+				n2 = r;
+				t = b2;
+				b2 = b1 - q*b2;
+				b1 = t;
+			}
+		} while (r != 0);
+	}
+	return ((IDEA_INT)b2);
+}
diff --git a/crypto/idea/idea_local.h b/crypto/idea/idea_local.h
new file mode 100644
index 0000000..c7fd327
--- /dev/null
+++ b/crypto/idea/idea_local.h
@@ -0,0 +1,149 @@
+/* $OpenBSD: idea_local.h,v 1.2 2023/07/07 12:51:58 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* The new form of this macro (check if the a*b == 0) was suggested by
+ * Colin Plumb  */
+/* Removal of the inner if from from Wei Dai 24/4/96 */
+#define idea_mul(r,a,b,ul)						\
+ul=(unsigned long)a*b;							\
+if (ul != 0)								\
+	{								\
+	r=(ul&0xffff)-(ul>>16);						\
+	r-=((r)>>16);							\
+	}								\
+else									\
+	r=(-(int)a-b+1); /* assuming a or b is 0 and in range */ 
+
+/*  7/12/95 - Many thanks to Rhys Weatherley 
+ * for pointing out that I was assuming little endian
+ * byte order for all quantities what idea
+ * actually used bigendian.  No where in the spec does it mention
+ * this, it is all in terms of 16 bit numbers and even the example
+ * does not use byte streams for the input example :-(.
+ * If you byte swap each pair of input, keys and iv, the functions
+ * would produce the output as the old version :-(.
+ */
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{						\
+			c+=n;						\
+			l1=l2=0;					\
+			switch (n) {					\
+			case 8: l2 =((unsigned long)(*(--(c))))    ;	\
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8;	\
+			case 6: l2|=((unsigned long)(*(--(c))))<<16;	\
+			case 5: l2|=((unsigned long)(*(--(c))))<<24;	\
+			case 4: l1 =((unsigned long)(*(--(c))))    ;	\
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l1|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l1|=((unsigned long)(*(--(c))))<<24;	\
+				}					\
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{						\
+			c+=n;						\
+			switch (n) {					\
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff);\
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff);\
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff);\
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff);\
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff);\
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff);\
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff);\
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff);\
+				}					\
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L,		\
+                         l|=((unsigned long)(*((c)++)))<<16L,		\
+                         l|=((unsigned long)(*((c)++)))<< 8L,		\
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+#undef s2n
+#define s2n(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff), \
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff))
+
+#undef n2s
+#define n2s(c,l)	(l =((IDEA_INT)(*((c)++)))<< 8L, \
+			 l|=((IDEA_INT)(*((c)++)))      )
+
+#define E_IDEA(num)							\
+	x1&=0xffff;							\
+	idea_mul(x1,x1,*p,ul); p++;					\
+	x2+= *(p++);							\
+	x3+= *(p++);							\
+	x4&=0xffff;							\
+	idea_mul(x4,x4,*p,ul); p++;					\
+	t0=(x1^x3)&0xffff;						\
+	idea_mul(t0,t0,*p,ul); p++;					\
+	t1=(t0+(x2^x4))&0xffff;						\
+	idea_mul(t1,t1,*p,ul); p++;					\
+	t0+=t1;								\
+	x1^=t1;								\
+	x4^=t0;								\
+	ul=x2^t0; /* do the swap to x3 */				\
+	x2=x3^t1;							\
+	x3=ul;
diff --git a/crypto/kdf/hkdf_evp.c b/crypto/kdf/hkdf_evp.c
new file mode 100644
index 0000000..b33e2e0
--- /dev/null
+++ b/crypto/kdf/hkdf_evp.c
@@ -0,0 +1,276 @@
+/*	$OpenBSD: hkdf_evp.c,v 1.20 2023/06/26 08:57:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2016-2018 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+#define HKDF_MAXBUF 1024
+
+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 = calloc(1, sizeof(*kctx))) == NULL) {
+		KDFerror(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;
+
+	freezero(kctx->salt, kctx->salt_len);
+	freezero(kctx->key, kctx->key_len);
+	freezero(kctx, sizeof(*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;
+
+		freezero(kctx->salt, kctx->salt_len);
+		if ((kctx->salt = malloc(p1)) == NULL)
+			return 0;
+		memcpy(kctx->salt, p2, p1);
+
+		kctx->salt_len = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_HKDF_KEY:
+		if (p1 < 0)
+			return 0;
+
+		freezero(kctx->key, kctx->key_len);
+		kctx->key = NULL;
+		kctx->key_len = 0;
+
+		/* Match OpenSSL's behavior. */
+		if (p1 == 0 || p2 == NULL)
+			return 0;
+
+		if ((kctx->key = malloc(p1)) == NULL)
+			return 0;
+		memcpy(kctx->key, p2, p1);
+
+		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);
+
+	KDFerror(KDF_R_UNKNOWN_PARAMETER_TYPE);
+	return -2;
+}
+
+static int
+pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
+{
+	HKDF_PKEY_CTX *kctx = ctx->data;
+
+	freezero(kctx->key, kctx->key_len);
+	freezero(kctx->salt, kctx->salt_len);
+	explicit_bzero(kctx, 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) {
+		KDFerror(KDF_R_MISSING_MESSAGE_DIGEST);
+		return 0;
+	}
+	if (kctx->key == NULL) {
+		KDFerror(KDF_R_MISSING_KEY);
+		return 0;
+	}
+
+	switch (kctx->mode) {
+	case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
+		return HKDF(key, *keylen, kctx->md, kctx->key, kctx->key_len,
+		    kctx->salt, kctx->salt_len, kctx->info, kctx->info_len);
+
+	case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
+		if (key == NULL) {
+			*keylen = EVP_MD_size(kctx->md);
+			return 1;
+		}
+		return HKDF_extract(key, keylen, kctx->md, kctx->key,
+		    kctx->key_len, kctx->salt, kctx->salt_len);
+
+	case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
+		return HKDF_expand(key, *keylen, kctx->md, kctx->key,
+		    kctx->key_len, kctx->info, kctx->info_len);
+
+	default:
+		return 0;
+	}
+}
+
+const EVP_PKEY_METHOD hkdf_pkey_meth = {
+	.pkey_id = EVP_PKEY_HKDF,
+	.flags = 0,
+
+	.init = pkey_hkdf_init,
+	.copy = NULL,
+	.cleanup = pkey_hkdf_cleanup,
+
+	.derive_init = pkey_hkdf_derive_init,
+	.derive = pkey_hkdf_derive,
+	.ctrl = pkey_hkdf_ctrl,
+	.ctrl_str = pkey_hkdf_ctrl_str,
+};
diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c
new file mode 100644
index 0000000..4dd3237
--- /dev/null
+++ b/crypto/kdf/kdf_err.c
@@ -0,0 +1,89 @@
+/*	$OpenBSD: kdf_err.c,v 1.9 2022/07/12 14:42:49 kn Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2018 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+static 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"},
+	{0, NULL},
+};
+
+static ERR_STRING_DATA KDF_str_reasons[] = {
+	{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_UNKNOWN_PARAMETER_TYPE),
+	 "unknown parameter type"},
+	{0, NULL},
+};
+
+#endif
+
+int
+ERR_load_KDF_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(KDF_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, KDF_str_functs);
+		ERR_load_strings(0, KDF_str_reasons);
+	}
+#endif
+	return 1;
+}
diff --git a/crypto/lhash/lh_stats.c b/crypto/lhash/lh_stats.c
new file mode 100644
index 0000000..123792a
--- /dev/null
+++ b/crypto/lhash/lh_stats.c
@@ -0,0 +1,263 @@
+/* $OpenBSD: lh_stats.c,v 1.13 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_BIO
+#include 
+#endif
+#include 
+
+#ifdef OPENSSL_NO_BIO
+
+void
+lh_stats(LHASH *lh, FILE *out)
+{
+	fprintf(out, "num_items             = %lu\n", lh->num_items);
+	fprintf(out, "num_nodes             = %u\n", lh->num_nodes);
+	fprintf(out, "num_alloc_nodes       = %u\n", lh->num_alloc_nodes);
+	fprintf(out, "num_expands           = %lu\n", lh->num_expands);
+	fprintf(out, "num_expand_reallocs   = %lu\n", lh->num_expand_reallocs);
+	fprintf(out, "num_contracts         = %lu\n", lh->num_contracts);
+	fprintf(out, "num_contract_reallocs = %lu\n",
+	    lh->num_contract_reallocs);
+	fprintf(out, "num_hash_calls        = %lu\n", lh->num_hash_calls);
+	fprintf(out, "num_comp_calls        = %lu\n", lh->num_comp_calls);
+	fprintf(out, "num_insert            = %lu\n", lh->num_insert);
+	fprintf(out, "num_replace           = %lu\n", lh->num_replace);
+	fprintf(out, "num_delete            = %lu\n", lh->num_delete);
+	fprintf(out, "num_no_delete         = %lu\n", lh->num_no_delete);
+	fprintf(out, "num_retrieve          = %lu\n", lh->num_retrieve);
+	fprintf(out, "num_retrieve_miss     = %lu\n", lh->num_retrieve_miss);
+	fprintf(out, "num_hash_comps        = %lu\n", lh->num_hash_comps);
+#if 0
+	fprintf(out, "p                     = %u\n", lh->p);
+	fprintf(out, "pmax                  = %u\n", lh->pmax);
+	fprintf(out, "up_load               = %lu\n", lh->up_load);
+	fprintf(out, "down_load             = %lu\n", lh->down_load);
+#endif
+}
+LCRYPTO_ALIAS(lh_stats);
+
+void
+lh_node_stats(LHASH *lh, FILE *out)
+{
+	LHASH_NODE *n;
+	unsigned int i, num;
+
+	for (i = 0; i < lh->num_nodes; i++) {
+		for (n = lh->b[i], num = 0; n != NULL; n = n->next)
+			num++;
+		fprintf(out, "node %6u -> %3u\n", i, num);
+	}
+}
+LCRYPTO_ALIAS(lh_node_stats);
+
+void
+lh_node_usage_stats(LHASH *lh, FILE *out)
+{
+	LHASH_NODE *n;
+	unsigned long num;
+	unsigned int i;
+	unsigned long total = 0, n_used = 0;
+
+	for (i = 0; i < lh->num_nodes; i++) {
+		for (n = lh->b[i], num = 0; n != NULL; n = n->next)
+			num++;
+		if (num != 0) {
+			n_used++;
+			total += num;
+		}
+	}
+	fprintf(out, "%lu nodes used out of %u\n", n_used, lh->num_nodes);
+	fprintf(out, "%lu items\n", total);
+	if (n_used == 0)
+		return;
+	fprintf(out, "load %d.%02d  actual load %d.%02d\n",
+	    (int)(total / lh->num_nodes),
+	    (int)((total % lh->num_nodes) * 100 / lh->num_nodes),
+	    (int)(total / n_used),
+	    (int)((total % n_used) * 100 / n_used));
+}
+LCRYPTO_ALIAS(lh_node_usage_stats);
+
+#else
+
+void
+lh_stats(const _LHASH *lh, FILE *fp)
+{
+	BIO *bp;
+
+	bp = BIO_new(BIO_s_file());
+	if (bp == NULL)
+		goto end;
+	BIO_set_fp(bp, fp, BIO_NOCLOSE);
+	lh_stats_bio(lh, bp);
+	BIO_free(bp);
+end:;
+}
+LCRYPTO_ALIAS(lh_stats);
+
+void
+lh_node_stats(const _LHASH *lh, FILE *fp)
+{
+	BIO *bp;
+
+	bp = BIO_new(BIO_s_file());
+	if (bp == NULL)
+		goto end;
+	BIO_set_fp(bp, fp, BIO_NOCLOSE);
+	lh_node_stats_bio(lh, bp);
+	BIO_free(bp);
+end:;
+}
+LCRYPTO_ALIAS(lh_node_stats);
+
+void
+lh_node_usage_stats(const _LHASH *lh, FILE *fp)
+{
+	BIO *bp;
+
+	bp = BIO_new(BIO_s_file());
+	if (bp == NULL)
+		goto end;
+	BIO_set_fp(bp, fp, BIO_NOCLOSE);
+	lh_node_usage_stats_bio(lh, bp);
+	BIO_free(bp);
+end:;
+}
+LCRYPTO_ALIAS(lh_node_usage_stats);
+
+
+void
+lh_stats_bio(const _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);
+#if 0
+	BIO_printf(out, "p                     = %u\n", lh->p);
+	BIO_printf(out, "pmax                  = %u\n", lh->pmax);
+	BIO_printf(out, "up_load               = %lu\n", lh->up_load);
+	BIO_printf(out, "down_load             = %lu\n", lh->down_load);
+#endif
+}
+LCRYPTO_ALIAS(lh_stats_bio);
+
+void
+lh_node_stats_bio(const _LHASH *lh, BIO *out)
+{
+	LHASH_NODE *n;
+	unsigned int i, num;
+
+	for (i = 0; i < lh->num_nodes; i++) {
+		for (n = lh->b[i], num = 0; n != NULL; n = n->next)
+			num++;
+		BIO_printf(out, "node %6u -> %3u\n", i, num);
+	}
+}
+LCRYPTO_ALIAS(lh_node_stats_bio);
+
+void
+lh_node_usage_stats_bio(const _LHASH *lh, BIO *out)
+{
+	LHASH_NODE *n;
+	unsigned long num;
+	unsigned int i;
+	unsigned long total = 0, n_used = 0;
+
+	for (i = 0; i < lh->num_nodes; i++) {
+		for (n = lh->b[i], num = 0; n != NULL; n = n->next)
+			num++;
+		if (num != 0) {
+			n_used++;
+			total += num;
+		}
+	}
+	BIO_printf(out, "%lu nodes used out of %u\n", n_used, lh->num_nodes);
+	BIO_printf(out, "%lu items\n", total);
+	if (n_used == 0)
+		return;
+	BIO_printf(out, "load %d.%02d  actual load %d.%02d\n",
+	    (int)(total / lh->num_nodes),
+	    (int)((total % lh->num_nodes) * 100 / lh->num_nodes),
+	    (int)(total / n_used),
+	    (int)((total % n_used) * 100 / n_used));
+}
+LCRYPTO_ALIAS(lh_node_usage_stats_bio);
+
+#endif
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
new file mode 100644
index 0000000..3adec71
--- /dev/null
+++ b/crypto/lhash/lhash.c
@@ -0,0 +1,443 @@
+/* $OpenBSD: lhash.c,v 1.20 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* Code for dynamic hash table routines
+ * Author - Eric Young v 2.0
+ *
+ * 2.2 eay - added #include "crypto.h" so the memory leak checking code is
+ *	     present. eay 18-Jun-98
+ *
+ * 2.1 eay - Added an 'error in last operation' flag. eay 6-May-98
+ *
+ * 2.0 eay - Fixed a bug that occurred when using lh_delete
+ *	     from inside lh_doall().  As entries were deleted,
+ *	     the 'table' was 'contract()ed', making some entries
+ *	     jump from the end of the table to the start, there by
+ *	     skipping the lh_doall() processing. eay - 4/12/95
+ *
+ * 1.9 eay - Fixed a memory leak in lh_free, the LHASH_NODEs
+ *	     were not being free()ed. 21/11/95
+ *
+ * 1.8 eay - Put the stats routines into a separate file, lh_stats.c
+ *	     19/09/95
+ *
+ * 1.7 eay - Removed the fputs() for realloc failures - the code
+ *           should silently tolerate them.  I have also fixed things
+ *           lint complained about 04/05/95
+ *
+ * 1.6 eay - Fixed an invalid pointers in contract/expand 27/07/92
+ *
+ * 1.5 eay - Fixed a misuse of realloc in expand 02/03/1992
+ *
+ * 1.4 eay - Fixed lh_doall so the function can call lh_delete 28/05/91
+ *
+ * 1.3 eay - Fixed a few lint problems 19/3/1991
+ *
+ * 1.2 eay - Fixed lh_doall problem 13/3/1991
+ *
+ * 1.1 eay - Added lh_doall
+ *
+ * 1.0 eay - First version
+ */
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#undef MIN_NODES
+#define MIN_NODES	16
+#define UP_LOAD		(2*LH_LOAD_MULT) /* load times 256  (default 2) */
+#define DOWN_LOAD	(LH_LOAD_MULT)   /* load times 256  (default 1) */
+
+static void expand(_LHASH *lh);
+static void contract(_LHASH *lh);
+static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash);
+
+_LHASH *
+lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
+{
+	_LHASH *ret;
+
+	if ((ret = calloc(1, sizeof(_LHASH))) == NULL)
+		return NULL;
+	if ((ret->b = calloc(MIN_NODES, sizeof(LHASH_NODE *))) == NULL) {
+		free(ret);
+		return NULL;
+	}
+	ret->comp = ((c == NULL) ? (LHASH_COMP_FN_TYPE)strcmp : c);
+	ret->hash = ((h == NULL) ? (LHASH_HASH_FN_TYPE)lh_strhash : h);
+	ret->num_nodes = MIN_NODES / 2;
+	ret->num_alloc_nodes = MIN_NODES;
+	ret->pmax = MIN_NODES / 2;
+	ret->up_load = UP_LOAD;
+	ret->down_load = DOWN_LOAD;
+
+	return (ret);
+}
+LCRYPTO_ALIAS(lh_new);
+
+void
+lh_free(_LHASH *lh)
+{
+	unsigned int i;
+	LHASH_NODE *n, *nn;
+
+	if (lh == NULL)
+		return;
+
+	for (i = 0; i < lh->num_nodes; i++) {
+		n = lh->b[i];
+		while (n != NULL) {
+			nn = n->next;
+			free(n);
+			n = nn;
+		}
+	}
+	free(lh->b);
+	free(lh);
+}
+LCRYPTO_ALIAS(lh_free);
+
+void *
+lh_insert(_LHASH *lh, void *data)
+{
+	unsigned long hash;
+	LHASH_NODE *nn, **rn;
+	void *ret;
+
+	lh->error = 0;
+	if (lh->up_load <= (lh->num_items * LH_LOAD_MULT / lh->num_nodes))
+		expand(lh);
+
+	rn = getrn(lh, data, &hash);
+
+	if (*rn == NULL) {
+		if ((nn = malloc(sizeof(LHASH_NODE))) == NULL) {
+			lh->error++;
+			return (NULL);
+		}
+		nn->data = data;
+		nn->next = NULL;
+#ifndef OPENSSL_NO_HASH_COMP
+		nn->hash = hash;
+#endif
+		*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);
+}
+LCRYPTO_ALIAS(lh_insert);
+
+void *
+lh_delete(_LHASH *lh, const void *data)
+{
+	unsigned long hash;
+	LHASH_NODE *nn, **rn;
+	void *ret;
+
+	lh->error = 0;
+	rn = getrn(lh, data, &hash);
+
+	if (*rn == NULL) {
+		lh->num_no_delete++;
+		return (NULL);
+	} else {
+		nn= *rn;
+		*rn = nn->next;
+		ret = nn->data;
+		free(nn);
+		lh->num_delete++;
+	}
+
+	lh->num_items--;
+	if ((lh->num_nodes > MIN_NODES) &&
+	    (lh->down_load >= (lh->num_items * LH_LOAD_MULT / lh->num_nodes)))
+		contract(lh);
+
+	return (ret);
+}
+LCRYPTO_ALIAS(lh_delete);
+
+void *
+lh_retrieve(_LHASH *lh, const void *data)
+{
+	unsigned long hash;
+	LHASH_NODE **rn;
+	void *ret;
+
+	lh->error = 0;
+	rn = getrn(lh, data, &hash);
+
+	if (*rn == NULL) {
+		lh->num_retrieve_miss++;
+		return (NULL);
+	} else {
+		ret = (*rn)->data;
+		lh->num_retrieve++;
+	}
+	return (ret);
+}
+LCRYPTO_ALIAS(lh_retrieve);
+
+static void
+doall_util_fn(_LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,
+    LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg)
+{
+	int i;
+	LHASH_NODE *a, *n;
+
+	if (lh == NULL)
+		return;
+
+	/* reverse the order so we search from 'top to bottom'
+	 * We were having memory leaks otherwise */
+	for (i = lh->num_nodes - 1; i >= 0; i--) {
+		a = lh->b[i];
+		while (a != NULL) {
+			/* 28/05/91 - eay - n added so items can be deleted
+			 * via lh_doall */
+			/* 22/05/08 - ben - eh? since a is not passed,
+			 * this should not be needed */
+			n = a->next;
+			if (use_arg)
+				func_arg(a->data, arg);
+			else
+				func(a->data);
+			a = n;
+		}
+	}
+}
+
+void
+lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func)
+{
+	doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL);
+}
+LCRYPTO_ALIAS(lh_doall);
+
+void
+lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg)
+{
+	doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg);
+}
+LCRYPTO_ALIAS(lh_doall_arg);
+
+static void
+expand(_LHASH *lh)
+{
+	LHASH_NODE **n, **n1, **n2, *np;
+	unsigned int p, i, j;
+	unsigned long hash, nni;
+
+	lh->num_nodes++;
+	lh->num_expands++;
+	p = (int)lh->p++;
+	n1 = &(lh->b[p]);
+	n2 = &(lh->b[p + (int)lh->pmax]);
+	*n2 = NULL;        /* 27/07/92 - eay - undefined pointer bug */
+	nni = lh->num_alloc_nodes;
+
+	for (np = *n1; np != NULL; ) {
+#ifndef OPENSSL_NO_HASH_COMP
+		hash = np->hash;
+#else
+		hash = lh->hash(np->data);
+		lh->num_hash_calls++;
+#endif
+		if ((hash % nni) != p) { /* move it */
+			*n1 = (*n1)->next;
+			np->next= *n2;
+			*n2 = np;
+		} else
+			n1 = &((*n1)->next);
+		np= *n1;
+	}
+
+	if ((lh->p) >= lh->pmax) {
+		j = (int)lh->num_alloc_nodes * 2;
+		n = reallocarray(lh->b, j, sizeof(LHASH_NODE *));
+		if (n == NULL) {
+/*			fputs("realloc error in lhash", stderr); */
+			lh->error++;
+			lh->p = 0;
+			return;
+		}
+		/* else */
+		for (i = (int)lh->num_alloc_nodes; i < j; i++)/* 26/02/92 eay */
+			n[i] = NULL;			  /* 02/03/92 eay */
+		lh->pmax = lh->num_alloc_nodes;
+		lh->num_alloc_nodes = j;
+		lh->num_expand_reallocs++;
+		lh->p = 0;
+		lh->b = n;
+	}
+}
+
+static void
+contract(_LHASH *lh)
+{
+	LHASH_NODE **n, *n1, *np;
+
+	np = lh->b[lh->p + lh->pmax - 1];
+	lh->b[lh->p+lh->pmax - 1] = NULL; /* 24/07-92 - eay - weird but :-( */
+	if (lh->p == 0) {
+		n = reallocarray(lh->b, lh->pmax, sizeof(LHASH_NODE *));
+		if (n == NULL) {
+/*			fputs("realloc error in lhash", stderr); */
+			lh->error++;
+			return;
+		}
+		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)
+		lh->b[(int)lh->p] = np;
+	else {
+		while (n1->next != NULL)
+			n1 = n1->next;
+		n1->next = np;
+	}
+}
+
+static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash)
+{
+	LHASH_NODE **ret, *n1;
+	unsigned long hash, nn;
+	LHASH_COMP_FN_TYPE cf;
+
+	hash = (*(lh->hash))(data);
+	lh->num_hash_calls++;
+	*rhash = hash;
+
+	nn = hash % lh->pmax;
+	if (nn < lh->p)
+		nn = hash % lh->num_alloc_nodes;
+
+	cf = lh->comp;
+	ret = &(lh->b[(int)nn]);
+	for (n1 = *ret; n1 != NULL; n1 = n1->next) {
+#ifndef OPENSSL_NO_HASH_COMP
+		lh->num_hash_comps++;
+		if (n1->hash != hash) {
+			ret = &(n1->next);
+			continue;
+		}
+#endif
+		lh->num_comp_calls++;
+		if (cf(n1->data, data) == 0)
+			break;
+		ret = &(n1->next);
+	}
+	return (ret);
+}
+
+/* The following hash seems to work very well on normal text strings
+ * no collisions on /usr/dict/words and it distributes on %2^n quite
+ * well, not as good as MD5, but still good.
+ */
+unsigned long
+lh_strhash(const char *c)
+{
+	unsigned long ret = 0;
+	unsigned long n, v;
+	unsigned int r;
+
+	if (c == NULL || *c == '\0')
+		return ret;
+
+	n = 0x100;
+	while (*c) {
+		v = n | *c;
+		n += 0x100;
+		if ((r = ((v >> 2) ^ v) & 0x0f) != 0)
+			ret = (ret << r) | (ret >> (32 - r));
+		ret &= 0xFFFFFFFFUL;
+		ret ^= v * v;
+		c++;
+	}
+	return (ret >> 16) ^ ret;
+}
+LCRYPTO_ALIAS(lh_strhash);
+
+unsigned long
+lh_num_items(const _LHASH *lh)
+{
+	return lh ? lh->num_items : 0;
+}
+LCRYPTO_ALIAS(lh_num_items);
diff --git a/crypto/malloc-wrapper.c b/crypto/malloc-wrapper.c
new file mode 100644
index 0000000..4d57f00
--- /dev/null
+++ b/crypto/malloc-wrapper.c
@@ -0,0 +1,205 @@
+/* $OpenBSD: malloc-wrapper.c,v 1.8 2023/07/08 08:28:23 beck Exp $ */
+/*
+ * Copyright (c) 2014 Bob Beck
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include 
+#include 
+#include 
+
+#include 
+
+int
+CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t),
+    void (*f)(void *))
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_set_mem_functions);
+
+int
+CRYPTO_set_mem_ex_functions(void *(*m)(size_t, const char *, int),
+    void *(*r)(void *, size_t, const char *, int), void (*f)(void *))
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_set_mem_ex_functions);
+
+int
+CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*f)(void *))
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_set_locked_mem_functions);
+
+int
+CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t, const char *, int),
+    void (*f)(void *))
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_set_locked_mem_ex_functions);
+
+int
+CRYPTO_set_mem_debug_functions(void (*m)(void *, int, const char *, int, int),
+    void (*r)(void *, void *, int, const char *, int, int),
+    void (*f)(void *, int), void (*so)(long), long (*go)(void))
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_set_mem_debug_functions);
+
+
+void
+CRYPTO_get_mem_functions(void *(**m)(size_t), void *(**r)(void *, size_t),
+    void (**f)(void *))
+{
+	if (m != NULL)
+		*m = malloc;
+	if (r != NULL)
+		*r = realloc;
+	if (f != NULL)
+		*f = free;
+}
+LCRYPTO_ALIAS(CRYPTO_get_mem_functions);
+
+void
+CRYPTO_get_mem_ex_functions(void *(**m)(size_t, const char *, int),
+    void *(**r)(void *, size_t, const char *, int), void (**f)(void *))
+{
+	if (m != NULL)
+		*m = NULL;
+	if (r != NULL)
+		*r = NULL;
+	if (f != NULL)
+		*f = free;
+}
+LCRYPTO_ALIAS(CRYPTO_get_mem_ex_functions);
+
+void
+CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *))
+{
+	if (m != NULL)
+		*m = malloc;
+	if (f != NULL)
+		*f = free;
+}
+LCRYPTO_ALIAS(CRYPTO_get_locked_mem_functions);
+
+void
+CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t, const char *, int),
+    void (**f)(void *))
+{
+	if (m != NULL)
+		*m = NULL;
+	if (f != NULL)
+		*f = free;
+}
+LCRYPTO_ALIAS(CRYPTO_get_locked_mem_ex_functions);
+
+void
+CRYPTO_get_mem_debug_functions(void (**m)(void *, int, const char *, int, int),
+    void (**r)(void *, void *, int, const char *, int, int),
+    void (**f)(void *, int), void (**so)(long), long (**go)(void))
+{
+	if (m != NULL)
+		*m = NULL;
+	if (r != NULL)
+		*r = NULL;
+	if (f != NULL)
+		*f = NULL;
+	if (so != NULL)
+		*so = NULL;
+	if (go != NULL)
+		*go = NULL;
+}
+LCRYPTO_ALIAS(CRYPTO_get_mem_debug_functions);
+
+
+void *
+CRYPTO_malloc_locked(int num, const char *file, int line)
+{
+	if (num <= 0)
+		return NULL;
+	return malloc(num);
+}
+
+void
+CRYPTO_free_locked(void *ptr)
+{
+	free(ptr);
+}
+
+void *
+CRYPTO_malloc(int num, const char *file, int line)
+{
+	if (num <= 0)
+		return NULL;
+	return malloc(num);
+}
+
+char *
+CRYPTO_strdup(const char *str, const char *file, int line)
+{
+	return strdup(str);
+}
+
+void *
+CRYPTO_realloc(void *ptr, int num, const char *file, int line)
+{
+	if (num <= 0)
+		return NULL;
+	return realloc(ptr, num);
+}
+
+void *
+CRYPTO_realloc_clean(void *ptr, int old_len, int num, const char *file,
+    int line)
+{
+	if (num <= 0)
+		return NULL;
+	/* Original does not support shrinking. */
+	if (num < old_len)
+		return NULL;
+	return recallocarray(ptr, old_len, num, 1);
+}
+LCRYPTO_ALIAS(CRYPTO_realloc_clean);
+
+void
+CRYPTO_free(void *ptr)
+{
+	free(ptr);
+}
+
+void *
+CRYPTO_remalloc(void *a, int num, const char *file, int line)
+{
+	free(a);
+	return malloc(num);
+}
+LCRYPTO_ALIAS(CRYPTO_remalloc);
+
+void
+CRYPTO_set_mem_debug_options(long bits)
+{
+	return;
+}
+LCRYPTO_ALIAS(CRYPTO_set_mem_debug_options);
+
+long
+CRYPTO_get_mem_debug_options(void)
+{
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_get_mem_debug_options);
diff --git a/crypto/md32_common.h b/crypto/md32_common.h
new file mode 100644
index 0000000..f61c49f
--- /dev/null
+++ b/crypto/md32_common.h
@@ -0,0 +1,309 @@
+/* $OpenBSD: md32_common.h,v 1.26 2023/08/10 07:15:23 jsing Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+/*
+ * This is a generic 32 bit "collector" for message digest algorithms.
+ * Whenever needed it collects input character stream into chunks of
+ * 32 bit values and invokes a block function that performs actual hash
+ * calculations.
+ *
+ * Porting guide.
+ *
+ * Obligatory macros:
+ *
+ * DATA_ORDER_IS_BIG_ENDIAN or DATA_ORDER_IS_LITTLE_ENDIAN
+ *	this macro defines byte order of input stream.
+ * HASH_CBLOCK
+ *	size of a unit chunk HASH_BLOCK operates on.
+ * HASH_LONG
+ *	has to be at least 32 bit wide.
+ * HASH_CTX
+ *	context structure that at least contains following
+ *	members:
+ *		typedef struct {
+ *			...
+ *			HASH_LONG	Nl,Nh;
+ *			either {
+ *			HASH_LONG	data[HASH_LBLOCK];
+ *			unsigned char	data[HASH_CBLOCK];
+ *			};
+ *			unsigned int	num;
+ *			...
+ *			} HASH_CTX;
+ *	data[] vector is expected to be zeroed upon first call to
+ *	HASH_UPDATE.
+ * HASH_UPDATE
+ *	name of "Update" function, implemented here.
+ * HASH_TRANSFORM
+ *	name of "Transform" function, implemented here.
+ * HASH_FINAL
+ *	name of "Final" function, implemented here.
+ * HASH_BLOCK_DATA_ORDER
+ *	name of "block" function capable of treating *unaligned* input
+ *	message in original (data) byte order, implemented externally.
+ * HASH_MAKE_STRING
+ *	macro convering context variables to an ASCII hash string.
+ *
+ * MD5 example:
+ *
+ *	#define DATA_ORDER_IS_LITTLE_ENDIAN
+ *
+ *	#define HASH_LONG		MD5_LONG
+ *	#define HASH_CTX		MD5_CTX
+ *	#define HASH_CBLOCK		MD5_CBLOCK
+ *	#define HASH_UPDATE		MD5_Update
+ *	#define HASH_TRANSFORM		MD5_Transform
+ *	#define HASH_FINAL		MD5_Final
+ *	#define HASH_BLOCK_DATA_ORDER	md5_block_data_order
+ *
+ *					
+ */
+
+#include 
+
+#include 
+
+#include "crypto_internal.h"
+
+#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+#error "DATA_ORDER must be defined!"
+#endif
+
+#ifndef HASH_CBLOCK
+#error "HASH_CBLOCK must be defined!"
+#endif
+#ifndef HASH_LONG
+#error "HASH_LONG must be defined!"
+#endif
+#ifndef HASH_CTX
+#error "HASH_CTX must be defined!"
+#endif
+
+#if !defined(HASH_UPDATE) && !defined(HASH_NO_UPDATE)
+#error "HASH_UPDATE must be defined!"
+#endif
+#if !defined(HASH_TRANSFORM) && !defined(HASH_NO_TRANSFORM)
+#error "HASH_TRANSFORM must be defined!"
+#endif
+#if !defined(HASH_FINAL) && !defined(HASH_NO_FINAL)
+#error "HASH_FINAL or HASH_NO_FINAL must be defined!"
+#endif
+
+#ifndef HASH_BLOCK_DATA_ORDER
+#error "HASH_BLOCK_DATA_ORDER must be defined!"
+#endif
+
+#define ROTATE(a, n)	crypto_rol_u32(a, n)
+
+#if defined(DATA_ORDER_IS_BIG_ENDIAN)
+
+#if defined(__GNUC__) && __GNUC__>=2 && !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM)
+# if (defined(__i386) || defined(__i386__) || \
+      defined(__x86_64) || defined(__x86_64__))
+    /*
+     * This gives ~30-40% performance improvement in SHA-256 compiled
+     * with gcc [on P4]. Well, first macro to be frank. We can pull
+     * this trick on x86* platforms only, because these CPUs can fetch
+     * unaligned data without raising an exception.
+     */
+#  define HOST_c2l(c,l)	({ unsigned int r=*((const unsigned int *)(c));	\
+				   asm ("bswapl %0":"=r"(r):"0"(r));	\
+				   (c)+=4; (l)=r;			})
+#  define HOST_l2c(l,c)	({ unsigned int r=(l);			\
+				   asm ("bswapl %0":"=r"(r):"0"(r));	\
+				   *((unsigned int *)(c))=r; (c)+=4;	})
+# endif
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l) do {l =(((unsigned long)(*((c)++)))<<24);	\
+			  l|=(((unsigned long)(*((c)++)))<<16);	\
+			  l|=(((unsigned long)(*((c)++)))<< 8);	\
+			  l|=(((unsigned long)(*((c)++)))    );	\
+		      } while (0)
+#endif
+#ifndef HOST_l2c
+#define HOST_l2c(l,c) do {*((c)++)=(unsigned char)(((l)>>24)&0xff);	\
+			  *((c)++)=(unsigned char)(((l)>>16)&0xff);	\
+			  *((c)++)=(unsigned char)(((l)>> 8)&0xff);	\
+			  *((c)++)=(unsigned char)(((l)    )&0xff);	\
+		      } while (0)
+#endif
+
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+
+#if defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__)
+#  define HOST_c2l(c,l)	((l)=*((const unsigned int *)(c)), (c)+=4)
+#  define HOST_l2c(l,c)	(*((unsigned int *)(c))=(l), (c)+=4)
+#endif
+
+#ifndef HOST_c2l
+#define HOST_c2l(c,l) do {l =(((unsigned long)(*((c)++)))    );	\
+			  l|=(((unsigned long)(*((c)++)))<< 8);	\
+			  l|=(((unsigned long)(*((c)++)))<<16);	\
+			  l|=(((unsigned long)(*((c)++)))<<24);	\
+		      } while (0)
+#endif
+#ifndef HOST_l2c
+#define HOST_l2c(l,c) do {*((c)++)=(unsigned char)(((l)    )&0xff);	\
+			  *((c)++)=(unsigned char)(((l)>> 8)&0xff);	\
+			  *((c)++)=(unsigned char)(((l)>>16)&0xff);	\
+			  *((c)++)=(unsigned char)(((l)>>24)&0xff);	\
+		      } while (0)
+#endif
+
+#endif
+
+/*
+ * Time for some action:-)
+ */
+
+#ifndef HASH_NO_UPDATE
+int
+HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
+{
+	const unsigned char *data = data_;
+	unsigned char *p;
+	HASH_LONG l;
+	size_t n;
+
+	if (len == 0)
+		return 1;
+
+	l = (c->Nl + (((HASH_LONG)len) << 3))&0xffffffffUL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai  for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(HASH_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
+	c->Nl = l;
+
+	n = c->num;
+	if (n != 0) {
+		p = (unsigned char *)c->data;
+
+		if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
+			memcpy (p + n, data, HASH_CBLOCK - n);
+			HASH_BLOCK_DATA_ORDER (c, p, 1);
+			n = HASH_CBLOCK - n;
+			data += n;
+			len -= n;
+			c->num = 0;
+			memset (p,0,HASH_CBLOCK);	/* keep it zeroed */
+		} else {
+			memcpy (p + n, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		}
+	}
+
+	n = len/HASH_CBLOCK;
+	if (n > 0) {
+		HASH_BLOCK_DATA_ORDER (c, data, n);
+		n    *= HASH_CBLOCK;
+		data += n;
+		len -= n;
+	}
+
+	if (len != 0) {
+		p = (unsigned char *)c->data;
+		c->num = (unsigned int)len;
+		memcpy (p, data, len);
+	}
+	return 1;
+}
+#endif
+
+#ifndef HASH_NO_TRANSFORM
+void HASH_TRANSFORM (HASH_CTX *c, const unsigned char *data)
+{
+	HASH_BLOCK_DATA_ORDER (c, data, 1);
+}
+#endif
+
+#ifndef HASH_NO_FINAL
+int HASH_FINAL (unsigned char *md, HASH_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	size_t n = c->num;
+
+	p[n] = 0x80; /* there is always room for one */
+	n++;
+
+	if (n > (HASH_CBLOCK - 8)) {
+		memset (p + n, 0, HASH_CBLOCK - n);
+		n = 0;
+		HASH_BLOCK_DATA_ORDER (c, p, 1);
+	}
+	memset (p + n, 0, HASH_CBLOCK - 8 - n);
+
+	p += HASH_CBLOCK - 8;
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	HOST_l2c(c->Nh, p);
+	HOST_l2c(c->Nl, p);
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	HOST_l2c(c->Nl, p);
+	HOST_l2c(c->Nh, p);
+#endif
+	p -= HASH_CBLOCK;
+	HASH_BLOCK_DATA_ORDER (c, p, 1);
+	c->num = 0;
+	memset (p, 0, HASH_CBLOCK);
+
+#ifndef HASH_MAKE_STRING
+#error "HASH_MAKE_STRING must be defined!"
+#else
+	HASH_MAKE_STRING(c, md);
+#endif
+
+	return 1;
+}
+#endif
diff --git a/crypto/md4/md4.c b/crypto/md4/md4.c
new file mode 100644
index 0000000..12e3ac7
--- /dev/null
+++ b/crypto/md4/md4.c
@@ -0,0 +1,264 @@
+/* $OpenBSD: md4.c,v 1.7 2023/08/10 13:41:56 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+void md4_block_data_order (MD4_CTX *c, const void *p, size_t num);
+
+__END_HIDDEN_DECLS
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG		MD4_LONG
+#define HASH_CTX		MD4_CTX
+#define HASH_CBLOCK		MD4_CBLOCK
+#define HASH_UPDATE		MD4_Update
+#define HASH_TRANSFORM		MD4_Transform
+#define HASH_FINAL		MD4_Final
+#define	HASH_MAKE_STRING(c,s)	do {	\
+	unsigned long ll;		\
+	ll=(c)->A; HOST_l2c(ll,(s));	\
+	ll=(c)->B; HOST_l2c(ll,(s));	\
+	ll=(c)->C; HOST_l2c(ll,(s));	\
+	ll=(c)->D; HOST_l2c(ll,(s));	\
+	} while (0)
+#define	HASH_BLOCK_DATA_ORDER	md4_block_data_order
+
+#include "md32_common.h"
+LCRYPTO_ALIAS(MD4_Update);
+LCRYPTO_ALIAS(MD4_Final);
+LCRYPTO_ALIAS(MD4_Transform);
+
+/*
+#define	F(x,y,z)	(((x) & (y))  |  ((~(x)) & (z)))
+#define	G(x,y,z)	(((x) & (y))  |  ((x) & ((z))) | ((y) & ((z))))
+*/
+
+/* As pointed out by Wei Dai , the above can be
+ * simplified to the code below.  Wei attributes these optimizations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ */
+#define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
+#define G(b,c,d)	(((b) & (c)) | ((b) & (d)) | ((c) & (d)))
+#define	H(b,c,d)	((b) ^ (c) ^ (d))
+
+#define R0(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+F((b),(c),(d))); \
+	a=ROTATE(a,s); };
+
+#define R1(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+G((b),(c),(d))); \
+	a=ROTATE(a,s); };\
+
+#define R2(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+H((b),(c),(d))); \
+	a=ROTATE(a,s); };
+
+/* Implemented from RFC1186 The MD4 Message-Digest Algorithm
+ */
+
+#define INIT_DATA_A (unsigned long)0x67452301L
+#define INIT_DATA_B (unsigned long)0xefcdab89L
+#define INIT_DATA_C (unsigned long)0x98badcfeL
+#define INIT_DATA_D (unsigned long)0x10325476L
+
+int
+MD4_Init(MD4_CTX *c)
+{
+	memset (c, 0, sizeof(*c));
+	c->A = INIT_DATA_A;
+	c->B = INIT_DATA_B;
+	c->C = INIT_DATA_C;
+	c->D = INIT_DATA_D;
+	return 1;
+}
+LCRYPTO_ALIAS(MD4_Init);
+
+#ifndef md4_block_data_order
+#ifdef X
+#undef X
+#endif
+void
+md4_block_data_order(MD4_CTX *c, const void *data_, size_t num)
+{
+	const unsigned char *data = data_;
+	unsigned int A, B, C, D, l;
+	unsigned int X0, X1, X2, X3, X4, X5, X6, X7,
+	    X8, X9, X10, X11, X12, X13, X14, X15;
+
+	A = c->A;
+	B = c->B;
+	C = c->C;
+	D = c->D;
+
+	for (; num--; ) {
+		HOST_c2l(data, l);
+		X0 = l;
+		HOST_c2l(data, l);
+		X1 = l;
+		/* Round 0 */
+		R0(A, B, C, D, X0, 3, 0);
+		HOST_c2l(data, l);
+		X2 = l;
+		R0(D, A, B, C, X1, 7, 0);
+		HOST_c2l(data, l);
+		X3 = l;
+		R0(C, D, A, B, X2, 11, 0);
+		HOST_c2l(data, l);
+		X4 = l;
+		R0(B, C, D, A, X3, 19, 0);
+		HOST_c2l(data, l);
+		X5 = l;
+		R0(A, B, C, D, X4, 3, 0);
+		HOST_c2l(data, l);
+		X6 = l;
+		R0(D, A, B, C, X5, 7, 0);
+		HOST_c2l(data, l);
+		X7 = l;
+		R0(C, D, A, B, X6, 11, 0);
+		HOST_c2l(data, l);
+		X8 = l;
+		R0(B, C, D, A, X7, 19, 0);
+		HOST_c2l(data, l);
+		X9 = l;
+		R0(A, B, C, D, X8, 3, 0);
+		HOST_c2l(data, l);
+		X10 = l;
+		R0(D, A,B, C,X9, 7, 0);
+		HOST_c2l(data, l);
+		X11 = l;
+		R0(C, D,A, B,X10, 11, 0);
+		HOST_c2l(data, l);
+		X12 = l;
+		R0(B, C,D, A,X11, 19, 0);
+		HOST_c2l(data, l);
+		X13 = l;
+		R0(A, B,C, D,X12, 3, 0);
+		HOST_c2l(data, l);
+		X14 = l;
+		R0(D, A,B, C,X13, 7, 0);
+		HOST_c2l(data, l);
+		X15 = l;
+		R0(C, D,A, B,X14, 11, 0);
+		R0(B, C,D, A,X15, 19, 0);
+		/* Round 1 */
+		R1(A, B, C, D, X0, 3, 0x5A827999L);
+		R1(D, A, B, C, X4, 5, 0x5A827999L);
+		R1(C, D, A, B, X8, 9, 0x5A827999L);
+		R1(B, C, D, A, X12, 13, 0x5A827999L);
+		R1(A, B, C, D, X1, 3, 0x5A827999L);
+		R1(D, A, B, C, X5, 5, 0x5A827999L);
+		R1(C, D, A, B, X9, 9, 0x5A827999L);
+		R1(B, C, D, A, X13, 13, 0x5A827999L);
+		R1(A, B, C, D, X2, 3, 0x5A827999L);
+		R1(D, A, B, C, X6, 5, 0x5A827999L);
+		R1(C, D, A, B, X10, 9, 0x5A827999L);
+		R1(B, C, D, A, X14, 13, 0x5A827999L);
+		R1(A, B, C, D, X3, 3, 0x5A827999L);
+		R1(D, A, B, C, X7, 5, 0x5A827999L);
+		R1(C, D, A, B, X11, 9, 0x5A827999L);
+		R1(B, C, D, A, X15, 13, 0x5A827999L);
+		/* Round 2 */
+		R2(A, B, C, D, X0, 3, 0x6ED9EBA1L);
+		R2(D, A, B, C, X8, 9, 0x6ED9EBA1L);
+		R2(C, D, A, B, X4, 11, 0x6ED9EBA1L);
+		R2(B, C, D, A, X12, 15, 0x6ED9EBA1L);
+		R2(A, B, C, D, X2, 3, 0x6ED9EBA1L);
+		R2(D, A, B, C, X10, 9, 0x6ED9EBA1L);
+		R2(C, D, A, B, X6, 11, 0x6ED9EBA1L);
+		R2(B, C, D, A, X14, 15, 0x6ED9EBA1L);
+		R2(A, B, C, D, X1, 3, 0x6ED9EBA1L);
+		R2(D, A, B, C, X9, 9, 0x6ED9EBA1L);
+		R2(C, D, A, B, X5, 11, 0x6ED9EBA1L);
+		R2(B, C, D, A, X13, 15, 0x6ED9EBA1L);
+		R2(A, B, C, D, X3, 3, 0x6ED9EBA1L);
+		R2(D, A, B, C, X11, 9, 0x6ED9EBA1L);
+		R2(C, D, A, B, X7, 11, 0x6ED9EBA1L);
+		R2(B, C, D, A, X15, 15, 0x6ED9EBA1L);
+
+		A = c->A += A;
+		B = c->B += B;
+		C = c->C += C;
+		D = c->D += D;
+	}
+}
+#endif
+
+unsigned char *
+MD4(const unsigned char *d, size_t n, unsigned char *md)
+{
+	MD4_CTX c;
+	static unsigned char m[MD4_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	if (!MD4_Init(&c))
+		return NULL;
+	MD4_Update(&c, d, n);
+	MD4_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(MD4);
diff --git a/crypto/md5/md5-elf-x86_64.S b/crypto/md5/md5-elf-x86_64.S
new file mode 100644
index 0000000..8fc10c9
--- /dev/null
+++ b/crypto/md5/md5-elf-x86_64.S
@@ -0,0 +1,673 @@
+#include "x86_arch.h"
+.text	
+.align	16
+
+.globl	md5_block_asm_data_order
+.type	md5_block_asm_data_order,@function
+md5_block_asm_data_order:
+	endbr64
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r14
+	pushq	%r15
+.Lprologue:
+
+
+
+
+	movq	%rdi,%rbp
+	shlq	$6,%rdx
+	leaq	(%rsi,%rdx,1),%rdi
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+
+
+
+
+
+
+	cmpq	%rdi,%rsi
+	je	.Lend				
+
+
+.Lloop:
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r14d
+	movl	%edx,%r15d
+	movl	0(%rsi),%r10d
+	movl	%edx,%r11d
+	xorl	%ecx,%r11d
+	leal	-680876936(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	4(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-389564586(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	606105819(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1044525330(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	-176418897(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	1200080426(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1473231341(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-45705983(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1770035416(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-1958414417(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-42063(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1990404162(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1804603682(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-40341101(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1502002290(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	1236535329(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	movl	4(%rsi),%r10d
+	movl	%edx,%r11d
+	movl	%edx,%r12d
+	notl	%r11d
+	leal	-165796510(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1069501632(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	643717713(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-373897302(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-701558691(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	38016083(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-660478335(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-405537848(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	568446438(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1019803690(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-187363961(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	1163531501(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-1444681467(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-51403784(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	1735328473(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-1926607734(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	movl	20(%rsi),%r10d
+	movl	%ecx,%r11d
+	leal	-378558(%rax,%r10,1),%eax
+	movl	32(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-2022574463(%rdx,%r10,1),%edx
+	movl	44(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	1839030562(%rcx,%r10,1),%ecx
+	movl	56(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-35309556(%rbx,%r10,1),%ebx
+	movl	4(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-1530992060(%rax,%r10,1),%eax
+	movl	16(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	1272893353(%rdx,%r10,1),%edx
+	movl	28(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-155497632(%rcx,%r10,1),%ecx
+	movl	40(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-1094730640(%rbx,%r10,1),%ebx
+	movl	52(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	681279174(%rax,%r10,1),%eax
+	movl	0(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-358537222(%rdx,%r10,1),%edx
+	movl	12(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-722521979(%rcx,%r10,1),%ecx
+	movl	24(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	76029189(%rbx,%r10,1),%ebx
+	movl	36(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-640364487(%rax,%r10,1),%eax
+	movl	48(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-421815835(%rdx,%r10,1),%edx
+	movl	60(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	530742520(%rcx,%r10,1),%ecx
+	movl	8(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-995338651(%rbx,%r10,1),%ebx
+	movl	0(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	xorl	%edx,%r11d
+	leal	-198630844(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	28(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	1126891415(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	56(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1416354905(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	20(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-57434055(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	48(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1700485571(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	12(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1894986606(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	40(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1051523(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	4(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-2054922799(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	32(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1873313359(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	60(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-30611744(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	24(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1560198380(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	52(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	1309151649(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	16(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	-145523070(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	44(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1120210379(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	8(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	718787259(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	36(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-343485551(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+
+	addl	%r8d,%eax
+	addl	%r9d,%ebx
+	addl	%r14d,%ecx
+	addl	%r15d,%edx
+
+
+	addq	$64,%rsi
+	cmpq	%rdi,%rsi
+	jb	.Lloop				
+
+
+.Lend:
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	movq	(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r12
+	movq	24(%rsp),%rbx
+	movq	32(%rsp),%rbp
+	addq	$40,%rsp
+.Lepilogue:
+	retq
+.size	md5_block_asm_data_order,.-md5_block_asm_data_order
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/md5/md5-macosx-x86_64.S b/crypto/md5/md5-macosx-x86_64.S
new file mode 100644
index 0000000..b4fcd18
--- /dev/null
+++ b/crypto/md5/md5-macosx-x86_64.S
@@ -0,0 +1,669 @@
+#include "x86_arch.h"
+.text	
+.p2align	4
+
+.globl	_md5_block_asm_data_order
+
+_md5_block_asm_data_order:
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r14
+	pushq	%r15
+L$prologue:
+
+
+
+
+	movq	%rdi,%rbp
+	shlq	$6,%rdx
+	leaq	(%rsi,%rdx,1),%rdi
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+
+
+
+
+
+
+	cmpq	%rdi,%rsi
+	je	L$end				
+
+
+L$loop:
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r14d
+	movl	%edx,%r15d
+	movl	0(%rsi),%r10d
+	movl	%edx,%r11d
+	xorl	%ecx,%r11d
+	leal	-680876936(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	4(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-389564586(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	606105819(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1044525330(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	-176418897(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	1200080426(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1473231341(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-45705983(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1770035416(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-1958414417(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-42063(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1990404162(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1804603682(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-40341101(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1502002290(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	1236535329(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	movl	4(%rsi),%r10d
+	movl	%edx,%r11d
+	movl	%edx,%r12d
+	notl	%r11d
+	leal	-165796510(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1069501632(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	643717713(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-373897302(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-701558691(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	38016083(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-660478335(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-405537848(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	568446438(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1019803690(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-187363961(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	1163531501(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-1444681467(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-51403784(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	1735328473(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-1926607734(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	movl	20(%rsi),%r10d
+	movl	%ecx,%r11d
+	leal	-378558(%rax,%r10,1),%eax
+	movl	32(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-2022574463(%rdx,%r10,1),%edx
+	movl	44(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	1839030562(%rcx,%r10,1),%ecx
+	movl	56(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-35309556(%rbx,%r10,1),%ebx
+	movl	4(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-1530992060(%rax,%r10,1),%eax
+	movl	16(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	1272893353(%rdx,%r10,1),%edx
+	movl	28(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-155497632(%rcx,%r10,1),%ecx
+	movl	40(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-1094730640(%rbx,%r10,1),%ebx
+	movl	52(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	681279174(%rax,%r10,1),%eax
+	movl	0(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-358537222(%rdx,%r10,1),%edx
+	movl	12(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-722521979(%rcx,%r10,1),%ecx
+	movl	24(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	76029189(%rbx,%r10,1),%ebx
+	movl	36(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-640364487(%rax,%r10,1),%eax
+	movl	48(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-421815835(%rdx,%r10,1),%edx
+	movl	60(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	530742520(%rcx,%r10,1),%ecx
+	movl	8(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-995338651(%rbx,%r10,1),%ebx
+	movl	0(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	xorl	%edx,%r11d
+	leal	-198630844(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	28(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	1126891415(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	56(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1416354905(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	20(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-57434055(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	48(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1700485571(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	12(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1894986606(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	40(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1051523(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	4(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-2054922799(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	32(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1873313359(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	60(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-30611744(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	24(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1560198380(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	52(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	1309151649(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	16(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	-145523070(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	44(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1120210379(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	8(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	718787259(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	36(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-343485551(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+
+	addl	%r8d,%eax
+	addl	%r9d,%ebx
+	addl	%r14d,%ecx
+	addl	%r15d,%edx
+
+
+	addq	$64,%rsi
+	cmpq	%rdi,%rsi
+	jb	L$loop				
+
+
+L$end:
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	movq	(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r12
+	movq	24(%rsp),%rbx
+	movq	32(%rsp),%rbp
+	addq	$40,%rsp
+L$epilogue:
+	retq
+
diff --git a/crypto/md5/md5-masm-x86_64.S b/crypto/md5/md5-masm-x86_64.S
new file mode 100644
index 0000000..24e8d07
--- /dev/null
+++ b/crypto/md5/md5-masm-x86_64.S
@@ -0,0 +1,753 @@
+; 1 "crypto/md5/md5-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/md5/md5-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/md5/md5-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+ALIGN	16
+
+PUBLIC	md5_block_asm_data_order
+
+md5_block_asm_data_order	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_md5_block_asm_data_order::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbp
+	push	rbx
+	push	r12
+	push	r14
+	push	r15
+$L$prologue::
+
+
+
+
+	mov	rbp,rdi
+	shl	rdx,6
+	lea	rdi,QWORD PTR[rdx*1+rsi]
+	mov	eax,DWORD PTR[rbp]
+	mov	ebx,DWORD PTR[4+rbp]
+	mov	ecx,DWORD PTR[8+rbp]
+	mov	edx,DWORD PTR[12+rbp]
+
+
+
+
+
+
+
+	cmp	rsi,rdi
+	je	$L$end				
+
+
+$L$loop::
+	mov	r8d,eax
+	mov	r9d,ebx
+	mov	r14d,ecx
+	mov	r15d,edx
+	mov	r10d,DWORD PTR[rsi]
+	mov	r11d,edx
+	xor	r11d,ecx
+	lea	eax,DWORD PTR[((-680876936))+r10*1+rax]
+	and	r11d,ebx
+	xor	r11d,edx
+	mov	r10d,DWORD PTR[4+rsi]
+	add	eax,r11d
+	rol	eax,7
+	mov	r11d,ecx
+	add	eax,ebx
+	xor	r11d,ebx
+	lea	edx,DWORD PTR[((-389564586))+r10*1+rdx]
+	and	r11d,eax
+	xor	r11d,ecx
+	mov	r10d,DWORD PTR[8+rsi]
+	add	edx,r11d
+	rol	edx,12
+	mov	r11d,ebx
+	add	edx,eax
+	xor	r11d,eax
+	lea	ecx,DWORD PTR[606105819+r10*1+rcx]
+	and	r11d,edx
+	xor	r11d,ebx
+	mov	r10d,DWORD PTR[12+rsi]
+	add	ecx,r11d
+	rol	ecx,17
+	mov	r11d,eax
+	add	ecx,edx
+	xor	r11d,edx
+	lea	ebx,DWORD PTR[((-1044525330))+r10*1+rbx]
+	and	r11d,ecx
+	xor	r11d,eax
+	mov	r10d,DWORD PTR[16+rsi]
+	add	ebx,r11d
+	rol	ebx,22
+	mov	r11d,edx
+	add	ebx,ecx
+	xor	r11d,ecx
+	lea	eax,DWORD PTR[((-176418897))+r10*1+rax]
+	and	r11d,ebx
+	xor	r11d,edx
+	mov	r10d,DWORD PTR[20+rsi]
+	add	eax,r11d
+	rol	eax,7
+	mov	r11d,ecx
+	add	eax,ebx
+	xor	r11d,ebx
+	lea	edx,DWORD PTR[1200080426+r10*1+rdx]
+	and	r11d,eax
+	xor	r11d,ecx
+	mov	r10d,DWORD PTR[24+rsi]
+	add	edx,r11d
+	rol	edx,12
+	mov	r11d,ebx
+	add	edx,eax
+	xor	r11d,eax
+	lea	ecx,DWORD PTR[((-1473231341))+r10*1+rcx]
+	and	r11d,edx
+	xor	r11d,ebx
+	mov	r10d,DWORD PTR[28+rsi]
+	add	ecx,r11d
+	rol	ecx,17
+	mov	r11d,eax
+	add	ecx,edx
+	xor	r11d,edx
+	lea	ebx,DWORD PTR[((-45705983))+r10*1+rbx]
+	and	r11d,ecx
+	xor	r11d,eax
+	mov	r10d,DWORD PTR[32+rsi]
+	add	ebx,r11d
+	rol	ebx,22
+	mov	r11d,edx
+	add	ebx,ecx
+	xor	r11d,ecx
+	lea	eax,DWORD PTR[1770035416+r10*1+rax]
+	and	r11d,ebx
+	xor	r11d,edx
+	mov	r10d,DWORD PTR[36+rsi]
+	add	eax,r11d
+	rol	eax,7
+	mov	r11d,ecx
+	add	eax,ebx
+	xor	r11d,ebx
+	lea	edx,DWORD PTR[((-1958414417))+r10*1+rdx]
+	and	r11d,eax
+	xor	r11d,ecx
+	mov	r10d,DWORD PTR[40+rsi]
+	add	edx,r11d
+	rol	edx,12
+	mov	r11d,ebx
+	add	edx,eax
+	xor	r11d,eax
+	lea	ecx,DWORD PTR[((-42063))+r10*1+rcx]
+	and	r11d,edx
+	xor	r11d,ebx
+	mov	r10d,DWORD PTR[44+rsi]
+	add	ecx,r11d
+	rol	ecx,17
+	mov	r11d,eax
+	add	ecx,edx
+	xor	r11d,edx
+	lea	ebx,DWORD PTR[((-1990404162))+r10*1+rbx]
+	and	r11d,ecx
+	xor	r11d,eax
+	mov	r10d,DWORD PTR[48+rsi]
+	add	ebx,r11d
+	rol	ebx,22
+	mov	r11d,edx
+	add	ebx,ecx
+	xor	r11d,ecx
+	lea	eax,DWORD PTR[1804603682+r10*1+rax]
+	and	r11d,ebx
+	xor	r11d,edx
+	mov	r10d,DWORD PTR[52+rsi]
+	add	eax,r11d
+	rol	eax,7
+	mov	r11d,ecx
+	add	eax,ebx
+	xor	r11d,ebx
+	lea	edx,DWORD PTR[((-40341101))+r10*1+rdx]
+	and	r11d,eax
+	xor	r11d,ecx
+	mov	r10d,DWORD PTR[56+rsi]
+	add	edx,r11d
+	rol	edx,12
+	mov	r11d,ebx
+	add	edx,eax
+	xor	r11d,eax
+	lea	ecx,DWORD PTR[((-1502002290))+r10*1+rcx]
+	and	r11d,edx
+	xor	r11d,ebx
+	mov	r10d,DWORD PTR[60+rsi]
+	add	ecx,r11d
+	rol	ecx,17
+	mov	r11d,eax
+	add	ecx,edx
+	xor	r11d,edx
+	lea	ebx,DWORD PTR[1236535329+r10*1+rbx]
+	and	r11d,ecx
+	xor	r11d,eax
+	mov	r10d,DWORD PTR[rsi]
+	add	ebx,r11d
+	rol	ebx,22
+	mov	r11d,edx
+	add	ebx,ecx
+	mov	r10d,DWORD PTR[4+rsi]
+	mov	r11d,edx
+	mov	r12d,edx
+	not	r11d
+	lea	eax,DWORD PTR[((-165796510))+r10*1+rax]
+	and	r12d,ebx
+	and	r11d,ecx
+	mov	r10d,DWORD PTR[24+rsi]
+	or	r12d,r11d
+	mov	r11d,ecx
+	add	eax,r12d
+	mov	r12d,ecx
+	rol	eax,5
+	add	eax,ebx
+	not	r11d
+	lea	edx,DWORD PTR[((-1069501632))+r10*1+rdx]
+	and	r12d,eax
+	and	r11d,ebx
+	mov	r10d,DWORD PTR[44+rsi]
+	or	r12d,r11d
+	mov	r11d,ebx
+	add	edx,r12d
+	mov	r12d,ebx
+	rol	edx,9
+	add	edx,eax
+	not	r11d
+	lea	ecx,DWORD PTR[643717713+r10*1+rcx]
+	and	r12d,edx
+	and	r11d,eax
+	mov	r10d,DWORD PTR[rsi]
+	or	r12d,r11d
+	mov	r11d,eax
+	add	ecx,r12d
+	mov	r12d,eax
+	rol	ecx,14
+	add	ecx,edx
+	not	r11d
+	lea	ebx,DWORD PTR[((-373897302))+r10*1+rbx]
+	and	r12d,ecx
+	and	r11d,edx
+	mov	r10d,DWORD PTR[20+rsi]
+	or	r12d,r11d
+	mov	r11d,edx
+	add	ebx,r12d
+	mov	r12d,edx
+	rol	ebx,20
+	add	ebx,ecx
+	not	r11d
+	lea	eax,DWORD PTR[((-701558691))+r10*1+rax]
+	and	r12d,ebx
+	and	r11d,ecx
+	mov	r10d,DWORD PTR[40+rsi]
+	or	r12d,r11d
+	mov	r11d,ecx
+	add	eax,r12d
+	mov	r12d,ecx
+	rol	eax,5
+	add	eax,ebx
+	not	r11d
+	lea	edx,DWORD PTR[38016083+r10*1+rdx]
+	and	r12d,eax
+	and	r11d,ebx
+	mov	r10d,DWORD PTR[60+rsi]
+	or	r12d,r11d
+	mov	r11d,ebx
+	add	edx,r12d
+	mov	r12d,ebx
+	rol	edx,9
+	add	edx,eax
+	not	r11d
+	lea	ecx,DWORD PTR[((-660478335))+r10*1+rcx]
+	and	r12d,edx
+	and	r11d,eax
+	mov	r10d,DWORD PTR[16+rsi]
+	or	r12d,r11d
+	mov	r11d,eax
+	add	ecx,r12d
+	mov	r12d,eax
+	rol	ecx,14
+	add	ecx,edx
+	not	r11d
+	lea	ebx,DWORD PTR[((-405537848))+r10*1+rbx]
+	and	r12d,ecx
+	and	r11d,edx
+	mov	r10d,DWORD PTR[36+rsi]
+	or	r12d,r11d
+	mov	r11d,edx
+	add	ebx,r12d
+	mov	r12d,edx
+	rol	ebx,20
+	add	ebx,ecx
+	not	r11d
+	lea	eax,DWORD PTR[568446438+r10*1+rax]
+	and	r12d,ebx
+	and	r11d,ecx
+	mov	r10d,DWORD PTR[56+rsi]
+	or	r12d,r11d
+	mov	r11d,ecx
+	add	eax,r12d
+	mov	r12d,ecx
+	rol	eax,5
+	add	eax,ebx
+	not	r11d
+	lea	edx,DWORD PTR[((-1019803690))+r10*1+rdx]
+	and	r12d,eax
+	and	r11d,ebx
+	mov	r10d,DWORD PTR[12+rsi]
+	or	r12d,r11d
+	mov	r11d,ebx
+	add	edx,r12d
+	mov	r12d,ebx
+	rol	edx,9
+	add	edx,eax
+	not	r11d
+	lea	ecx,DWORD PTR[((-187363961))+r10*1+rcx]
+	and	r12d,edx
+	and	r11d,eax
+	mov	r10d,DWORD PTR[32+rsi]
+	or	r12d,r11d
+	mov	r11d,eax
+	add	ecx,r12d
+	mov	r12d,eax
+	rol	ecx,14
+	add	ecx,edx
+	not	r11d
+	lea	ebx,DWORD PTR[1163531501+r10*1+rbx]
+	and	r12d,ecx
+	and	r11d,edx
+	mov	r10d,DWORD PTR[52+rsi]
+	or	r12d,r11d
+	mov	r11d,edx
+	add	ebx,r12d
+	mov	r12d,edx
+	rol	ebx,20
+	add	ebx,ecx
+	not	r11d
+	lea	eax,DWORD PTR[((-1444681467))+r10*1+rax]
+	and	r12d,ebx
+	and	r11d,ecx
+	mov	r10d,DWORD PTR[8+rsi]
+	or	r12d,r11d
+	mov	r11d,ecx
+	add	eax,r12d
+	mov	r12d,ecx
+	rol	eax,5
+	add	eax,ebx
+	not	r11d
+	lea	edx,DWORD PTR[((-51403784))+r10*1+rdx]
+	and	r12d,eax
+	and	r11d,ebx
+	mov	r10d,DWORD PTR[28+rsi]
+	or	r12d,r11d
+	mov	r11d,ebx
+	add	edx,r12d
+	mov	r12d,ebx
+	rol	edx,9
+	add	edx,eax
+	not	r11d
+	lea	ecx,DWORD PTR[1735328473+r10*1+rcx]
+	and	r12d,edx
+	and	r11d,eax
+	mov	r10d,DWORD PTR[48+rsi]
+	or	r12d,r11d
+	mov	r11d,eax
+	add	ecx,r12d
+	mov	r12d,eax
+	rol	ecx,14
+	add	ecx,edx
+	not	r11d
+	lea	ebx,DWORD PTR[((-1926607734))+r10*1+rbx]
+	and	r12d,ecx
+	and	r11d,edx
+	mov	r10d,DWORD PTR[rsi]
+	or	r12d,r11d
+	mov	r11d,edx
+	add	ebx,r12d
+	mov	r12d,edx
+	rol	ebx,20
+	add	ebx,ecx
+	mov	r10d,DWORD PTR[20+rsi]
+	mov	r11d,ecx
+	lea	eax,DWORD PTR[((-378558))+r10*1+rax]
+	mov	r10d,DWORD PTR[32+rsi]
+	xor	r11d,edx
+	xor	r11d,ebx
+	add	eax,r11d
+	rol	eax,4
+	mov	r11d,ebx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-2022574463))+r10*1+rdx]
+	mov	r10d,DWORD PTR[44+rsi]
+	xor	r11d,ecx
+	xor	r11d,eax
+	add	edx,r11d
+	rol	edx,11
+	mov	r11d,eax
+	add	edx,eax
+	lea	ecx,DWORD PTR[1839030562+r10*1+rcx]
+	mov	r10d,DWORD PTR[56+rsi]
+	xor	r11d,ebx
+	xor	r11d,edx
+	add	ecx,r11d
+	rol	ecx,16
+	mov	r11d,edx
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-35309556))+r10*1+rbx]
+	mov	r10d,DWORD PTR[4+rsi]
+	xor	r11d,eax
+	xor	r11d,ecx
+	add	ebx,r11d
+	rol	ebx,23
+	mov	r11d,ecx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[((-1530992060))+r10*1+rax]
+	mov	r10d,DWORD PTR[16+rsi]
+	xor	r11d,edx
+	xor	r11d,ebx
+	add	eax,r11d
+	rol	eax,4
+	mov	r11d,ebx
+	add	eax,ebx
+	lea	edx,DWORD PTR[1272893353+r10*1+rdx]
+	mov	r10d,DWORD PTR[28+rsi]
+	xor	r11d,ecx
+	xor	r11d,eax
+	add	edx,r11d
+	rol	edx,11
+	mov	r11d,eax
+	add	edx,eax
+	lea	ecx,DWORD PTR[((-155497632))+r10*1+rcx]
+	mov	r10d,DWORD PTR[40+rsi]
+	xor	r11d,ebx
+	xor	r11d,edx
+	add	ecx,r11d
+	rol	ecx,16
+	mov	r11d,edx
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-1094730640))+r10*1+rbx]
+	mov	r10d,DWORD PTR[52+rsi]
+	xor	r11d,eax
+	xor	r11d,ecx
+	add	ebx,r11d
+	rol	ebx,23
+	mov	r11d,ecx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[681279174+r10*1+rax]
+	mov	r10d,DWORD PTR[rsi]
+	xor	r11d,edx
+	xor	r11d,ebx
+	add	eax,r11d
+	rol	eax,4
+	mov	r11d,ebx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-358537222))+r10*1+rdx]
+	mov	r10d,DWORD PTR[12+rsi]
+	xor	r11d,ecx
+	xor	r11d,eax
+	add	edx,r11d
+	rol	edx,11
+	mov	r11d,eax
+	add	edx,eax
+	lea	ecx,DWORD PTR[((-722521979))+r10*1+rcx]
+	mov	r10d,DWORD PTR[24+rsi]
+	xor	r11d,ebx
+	xor	r11d,edx
+	add	ecx,r11d
+	rol	ecx,16
+	mov	r11d,edx
+	add	ecx,edx
+	lea	ebx,DWORD PTR[76029189+r10*1+rbx]
+	mov	r10d,DWORD PTR[36+rsi]
+	xor	r11d,eax
+	xor	r11d,ecx
+	add	ebx,r11d
+	rol	ebx,23
+	mov	r11d,ecx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[((-640364487))+r10*1+rax]
+	mov	r10d,DWORD PTR[48+rsi]
+	xor	r11d,edx
+	xor	r11d,ebx
+	add	eax,r11d
+	rol	eax,4
+	mov	r11d,ebx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-421815835))+r10*1+rdx]
+	mov	r10d,DWORD PTR[60+rsi]
+	xor	r11d,ecx
+	xor	r11d,eax
+	add	edx,r11d
+	rol	edx,11
+	mov	r11d,eax
+	add	edx,eax
+	lea	ecx,DWORD PTR[530742520+r10*1+rcx]
+	mov	r10d,DWORD PTR[8+rsi]
+	xor	r11d,ebx
+	xor	r11d,edx
+	add	ecx,r11d
+	rol	ecx,16
+	mov	r11d,edx
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-995338651))+r10*1+rbx]
+	mov	r10d,DWORD PTR[rsi]
+	xor	r11d,eax
+	xor	r11d,ecx
+	add	ebx,r11d
+	rol	ebx,23
+	mov	r11d,ecx
+	add	ebx,ecx
+	mov	r10d,DWORD PTR[rsi]
+	mov	r11d,0ffffffffh
+	xor	r11d,edx
+	lea	eax,DWORD PTR[((-198630844))+r10*1+rax]
+	or	r11d,ebx
+	xor	r11d,ecx
+	add	eax,r11d
+	mov	r10d,DWORD PTR[28+rsi]
+	mov	r11d,0ffffffffh
+	rol	eax,6
+	xor	r11d,ecx
+	add	eax,ebx
+	lea	edx,DWORD PTR[1126891415+r10*1+rdx]
+	or	r11d,eax
+	xor	r11d,ebx
+	add	edx,r11d
+	mov	r10d,DWORD PTR[56+rsi]
+	mov	r11d,0ffffffffh
+	rol	edx,10
+	xor	r11d,ebx
+	add	edx,eax
+	lea	ecx,DWORD PTR[((-1416354905))+r10*1+rcx]
+	or	r11d,edx
+	xor	r11d,eax
+	add	ecx,r11d
+	mov	r10d,DWORD PTR[20+rsi]
+	mov	r11d,0ffffffffh
+	rol	ecx,15
+	xor	r11d,eax
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-57434055))+r10*1+rbx]
+	or	r11d,ecx
+	xor	r11d,edx
+	add	ebx,r11d
+	mov	r10d,DWORD PTR[48+rsi]
+	mov	r11d,0ffffffffh
+	rol	ebx,21
+	xor	r11d,edx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[1700485571+r10*1+rax]
+	or	r11d,ebx
+	xor	r11d,ecx
+	add	eax,r11d
+	mov	r10d,DWORD PTR[12+rsi]
+	mov	r11d,0ffffffffh
+	rol	eax,6
+	xor	r11d,ecx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-1894986606))+r10*1+rdx]
+	or	r11d,eax
+	xor	r11d,ebx
+	add	edx,r11d
+	mov	r10d,DWORD PTR[40+rsi]
+	mov	r11d,0ffffffffh
+	rol	edx,10
+	xor	r11d,ebx
+	add	edx,eax
+	lea	ecx,DWORD PTR[((-1051523))+r10*1+rcx]
+	or	r11d,edx
+	xor	r11d,eax
+	add	ecx,r11d
+	mov	r10d,DWORD PTR[4+rsi]
+	mov	r11d,0ffffffffh
+	rol	ecx,15
+	xor	r11d,eax
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-2054922799))+r10*1+rbx]
+	or	r11d,ecx
+	xor	r11d,edx
+	add	ebx,r11d
+	mov	r10d,DWORD PTR[32+rsi]
+	mov	r11d,0ffffffffh
+	rol	ebx,21
+	xor	r11d,edx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[1873313359+r10*1+rax]
+	or	r11d,ebx
+	xor	r11d,ecx
+	add	eax,r11d
+	mov	r10d,DWORD PTR[60+rsi]
+	mov	r11d,0ffffffffh
+	rol	eax,6
+	xor	r11d,ecx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-30611744))+r10*1+rdx]
+	or	r11d,eax
+	xor	r11d,ebx
+	add	edx,r11d
+	mov	r10d,DWORD PTR[24+rsi]
+	mov	r11d,0ffffffffh
+	rol	edx,10
+	xor	r11d,ebx
+	add	edx,eax
+	lea	ecx,DWORD PTR[((-1560198380))+r10*1+rcx]
+	or	r11d,edx
+	xor	r11d,eax
+	add	ecx,r11d
+	mov	r10d,DWORD PTR[52+rsi]
+	mov	r11d,0ffffffffh
+	rol	ecx,15
+	xor	r11d,eax
+	add	ecx,edx
+	lea	ebx,DWORD PTR[1309151649+r10*1+rbx]
+	or	r11d,ecx
+	xor	r11d,edx
+	add	ebx,r11d
+	mov	r10d,DWORD PTR[16+rsi]
+	mov	r11d,0ffffffffh
+	rol	ebx,21
+	xor	r11d,edx
+	add	ebx,ecx
+	lea	eax,DWORD PTR[((-145523070))+r10*1+rax]
+	or	r11d,ebx
+	xor	r11d,ecx
+	add	eax,r11d
+	mov	r10d,DWORD PTR[44+rsi]
+	mov	r11d,0ffffffffh
+	rol	eax,6
+	xor	r11d,ecx
+	add	eax,ebx
+	lea	edx,DWORD PTR[((-1120210379))+r10*1+rdx]
+	or	r11d,eax
+	xor	r11d,ebx
+	add	edx,r11d
+	mov	r10d,DWORD PTR[8+rsi]
+	mov	r11d,0ffffffffh
+	rol	edx,10
+	xor	r11d,ebx
+	add	edx,eax
+	lea	ecx,DWORD PTR[718787259+r10*1+rcx]
+	or	r11d,edx
+	xor	r11d,eax
+	add	ecx,r11d
+	mov	r10d,DWORD PTR[36+rsi]
+	mov	r11d,0ffffffffh
+	rol	ecx,15
+	xor	r11d,eax
+	add	ecx,edx
+	lea	ebx,DWORD PTR[((-343485551))+r10*1+rbx]
+	or	r11d,ecx
+	xor	r11d,edx
+	add	ebx,r11d
+	mov	r10d,DWORD PTR[rsi]
+	mov	r11d,0ffffffffh
+	rol	ebx,21
+	xor	r11d,edx
+	add	ebx,ecx
+
+	add	eax,r8d
+	add	ebx,r9d
+	add	ecx,r14d
+	add	edx,r15d
+
+
+	add	rsi,64
+	cmp	rsi,rdi
+	jb	$L$loop				
+
+
+$L$end::
+	mov	DWORD PTR[rbp],eax
+	mov	DWORD PTR[4+rbp],ebx
+	mov	DWORD PTR[8+rbp],ecx
+	mov	DWORD PTR[12+rbp],edx
+
+	mov	r15,QWORD PTR[rsp]
+	mov	r14,QWORD PTR[8+rsp]
+	mov	r12,QWORD PTR[16+rsp]
+	mov	rbx,QWORD PTR[24+rsp]
+	mov	rbp,QWORD PTR[32+rsp]
+	add	rsp,40
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_md5_block_asm_data_order::
+md5_block_asm_data_order	ENDP
+
+.text$	ENDS
+END
+
diff --git a/crypto/md5/md5-mingw64-x86_64.S b/crypto/md5/md5-mingw64-x86_64.S
new file mode 100644
index 0000000..5a611f5
--- /dev/null
+++ b/crypto/md5/md5-mingw64-x86_64.S
@@ -0,0 +1,679 @@
+#include "x86_arch.h"
+.text	
+.p2align	4
+
+.globl	md5_block_asm_data_order
+.def	md5_block_asm_data_order;	.scl 2;	.type 32;	.endef
+md5_block_asm_data_order:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_md5_block_asm_data_order:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r14
+	pushq	%r15
+.Lprologue:
+
+
+
+
+	movq	%rdi,%rbp
+	shlq	$6,%rdx
+	leaq	(%rsi,%rdx,1),%rdi
+	movl	0(%rbp),%eax
+	movl	4(%rbp),%ebx
+	movl	8(%rbp),%ecx
+	movl	12(%rbp),%edx
+
+
+
+
+
+
+
+	cmpq	%rdi,%rsi
+	je	.Lend				
+
+
+.Lloop:
+	movl	%eax,%r8d
+	movl	%ebx,%r9d
+	movl	%ecx,%r14d
+	movl	%edx,%r15d
+	movl	0(%rsi),%r10d
+	movl	%edx,%r11d
+	xorl	%ecx,%r11d
+	leal	-680876936(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	4(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-389564586(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	606105819(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1044525330(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	-176418897(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	1200080426(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1473231341(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-45705983(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1770035416(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-1958414417(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-42063(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	-1990404162(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	xorl	%ecx,%r11d
+	leal	1804603682(%rax,%r10,1),%eax
+	andl	%ebx,%r11d
+	xorl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	addl	%r11d,%eax
+	roll	$7,%eax
+	movl	%ecx,%r11d
+	addl	%ebx,%eax
+	xorl	%ebx,%r11d
+	leal	-40341101(%rdx,%r10,1),%edx
+	andl	%eax,%r11d
+	xorl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	addl	%r11d,%edx
+	roll	$12,%edx
+	movl	%ebx,%r11d
+	addl	%eax,%edx
+	xorl	%eax,%r11d
+	leal	-1502002290(%rcx,%r10,1),%ecx
+	andl	%edx,%r11d
+	xorl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	addl	%r11d,%ecx
+	roll	$17,%ecx
+	movl	%eax,%r11d
+	addl	%edx,%ecx
+	xorl	%edx,%r11d
+	leal	1236535329(%rbx,%r10,1),%ebx
+	andl	%ecx,%r11d
+	xorl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	addl	%r11d,%ebx
+	roll	$22,%ebx
+	movl	%edx,%r11d
+	addl	%ecx,%ebx
+	movl	4(%rsi),%r10d
+	movl	%edx,%r11d
+	movl	%edx,%r12d
+	notl	%r11d
+	leal	-165796510(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	24(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1069501632(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	44(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	643717713(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-373897302(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	20(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-701558691(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	40(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	38016083(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	60(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-660478335(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	16(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-405537848(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	36(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	568446438(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	56(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-1019803690(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	12(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	-187363961(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	32(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	1163531501(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	52(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	notl	%r11d
+	leal	-1444681467(%rax,%r10,1),%eax
+	andl	%ebx,%r12d
+	andl	%ecx,%r11d
+	movl	8(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ecx,%r11d
+	addl	%r12d,%eax
+	movl	%ecx,%r12d
+	roll	$5,%eax
+	addl	%ebx,%eax
+	notl	%r11d
+	leal	-51403784(%rdx,%r10,1),%edx
+	andl	%eax,%r12d
+	andl	%ebx,%r11d
+	movl	28(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%ebx,%r11d
+	addl	%r12d,%edx
+	movl	%ebx,%r12d
+	roll	$9,%edx
+	addl	%eax,%edx
+	notl	%r11d
+	leal	1735328473(%rcx,%r10,1),%ecx
+	andl	%edx,%r12d
+	andl	%eax,%r11d
+	movl	48(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%eax,%r11d
+	addl	%r12d,%ecx
+	movl	%eax,%r12d
+	roll	$14,%ecx
+	addl	%edx,%ecx
+	notl	%r11d
+	leal	-1926607734(%rbx,%r10,1),%ebx
+	andl	%ecx,%r12d
+	andl	%edx,%r11d
+	movl	0(%rsi),%r10d
+	orl	%r11d,%r12d
+	movl	%edx,%r11d
+	addl	%r12d,%ebx
+	movl	%edx,%r12d
+	roll	$20,%ebx
+	addl	%ecx,%ebx
+	movl	20(%rsi),%r10d
+	movl	%ecx,%r11d
+	leal	-378558(%rax,%r10,1),%eax
+	movl	32(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-2022574463(%rdx,%r10,1),%edx
+	movl	44(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	1839030562(%rcx,%r10,1),%ecx
+	movl	56(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-35309556(%rbx,%r10,1),%ebx
+	movl	4(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-1530992060(%rax,%r10,1),%eax
+	movl	16(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	1272893353(%rdx,%r10,1),%edx
+	movl	28(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-155497632(%rcx,%r10,1),%ecx
+	movl	40(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-1094730640(%rbx,%r10,1),%ebx
+	movl	52(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	681279174(%rax,%r10,1),%eax
+	movl	0(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-358537222(%rdx,%r10,1),%edx
+	movl	12(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	-722521979(%rcx,%r10,1),%ecx
+	movl	24(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	76029189(%rbx,%r10,1),%ebx
+	movl	36(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	leal	-640364487(%rax,%r10,1),%eax
+	movl	48(%rsi),%r10d
+	xorl	%edx,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%eax
+	roll	$4,%eax
+	movl	%ebx,%r11d
+	addl	%ebx,%eax
+	leal	-421815835(%rdx,%r10,1),%edx
+	movl	60(%rsi),%r10d
+	xorl	%ecx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%edx
+	roll	$11,%edx
+	movl	%eax,%r11d
+	addl	%eax,%edx
+	leal	530742520(%rcx,%r10,1),%ecx
+	movl	8(%rsi),%r10d
+	xorl	%ebx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ecx
+	roll	$16,%ecx
+	movl	%edx,%r11d
+	addl	%edx,%ecx
+	leal	-995338651(%rbx,%r10,1),%ebx
+	movl	0(%rsi),%r10d
+	xorl	%eax,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%ebx
+	roll	$23,%ebx
+	movl	%ecx,%r11d
+	addl	%ecx,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	xorl	%edx,%r11d
+	leal	-198630844(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	28(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	1126891415(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	56(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1416354905(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	20(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-57434055(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	48(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1700485571(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	12(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1894986606(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	40(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1051523(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	4(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-2054922799(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	32(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	1873313359(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	60(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-30611744(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	24(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	-1560198380(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	52(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	1309151649(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	16(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+	leal	-145523070(%rax,%r10,1),%eax
+	orl	%ebx,%r11d
+	xorl	%ecx,%r11d
+	addl	%r11d,%eax
+	movl	44(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$6,%eax
+	xorl	%ecx,%r11d
+	addl	%ebx,%eax
+	leal	-1120210379(%rdx,%r10,1),%edx
+	orl	%eax,%r11d
+	xorl	%ebx,%r11d
+	addl	%r11d,%edx
+	movl	8(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$10,%edx
+	xorl	%ebx,%r11d
+	addl	%eax,%edx
+	leal	718787259(%rcx,%r10,1),%ecx
+	orl	%edx,%r11d
+	xorl	%eax,%r11d
+	addl	%r11d,%ecx
+	movl	36(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$15,%ecx
+	xorl	%eax,%r11d
+	addl	%edx,%ecx
+	leal	-343485551(%rbx,%r10,1),%ebx
+	orl	%ecx,%r11d
+	xorl	%edx,%r11d
+	addl	%r11d,%ebx
+	movl	0(%rsi),%r10d
+	movl	$4294967295,%r11d
+	roll	$21,%ebx
+	xorl	%edx,%r11d
+	addl	%ecx,%ebx
+
+	addl	%r8d,%eax
+	addl	%r9d,%ebx
+	addl	%r14d,%ecx
+	addl	%r15d,%edx
+
+
+	addq	$64,%rsi
+	cmpq	%rdi,%rsi
+	jb	.Lloop				
+
+
+.Lend:
+	movl	%eax,0(%rbp)
+	movl	%ebx,4(%rbp)
+	movl	%ecx,8(%rbp)
+	movl	%edx,12(%rbp)
+
+	movq	(%rsp),%r15
+	movq	8(%rsp),%r14
+	movq	16(%rsp),%r12
+	movq	24(%rsp),%rbx
+	movq	32(%rsp),%rbp
+	addq	$40,%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_md5_block_asm_data_order:
diff --git a/crypto/md5/md5.c b/crypto/md5/md5.c
new file mode 100644
index 0000000..c2ee295
--- /dev/null
+++ b/crypto/md5/md5.c
@@ -0,0 +1,362 @@
+/* $OpenBSD: md5.c,v 1.18 2023/08/15 08:39:27 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+
+#include "crypto_internal.h"
+
+/* Ensure that MD5_LONG and uint32_t are equivalent size. */
+CTASSERT(sizeof(MD5_LONG) == sizeof(uint32_t));
+
+#ifdef MD5_ASM
+void md5_block_asm_data_order(MD5_CTX *c, const void *p, size_t num);
+#define md5_block_data_order md5_block_asm_data_order
+#endif
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG		MD5_LONG
+#define HASH_CTX		MD5_CTX
+#define HASH_CBLOCK		MD5_CBLOCK
+#define HASH_UPDATE		MD5_Update
+#define HASH_TRANSFORM		MD5_Transform
+#define HASH_FINAL		MD5_Final
+#define	HASH_BLOCK_DATA_ORDER	md5_block_data_order
+
+#define HASH_NO_UPDATE
+#define HASH_NO_TRANSFORM
+#define HASH_NO_FINAL
+
+#include "md32_common.h"
+
+/*
+#define	F(x,y,z)	(((x) & (y))  |  ((~(x)) & (z)))
+#define	G(x,y,z)	(((x) & (z))  |  ((y) & (~(z))))
+*/
+
+/* As pointed out by Wei Dai , the above can be
+ * simplified to the code below.  Wei attributes these optimizations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ */
+#define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
+#define	G(b,c,d)	((((b) ^ (c)) & (d)) ^ (c))
+#define	H(b,c,d)	((b) ^ (c) ^ (d))
+#define	I(b,c,d)	(((~(d)) | (b)) ^ (c))
+
+#define R0(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+F((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };\
+
+#define R1(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+G((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
+
+#define R2(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+H((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
+
+#define R3(a,b,c,d,k,s,t) { \
+	a+=((k)+(t)+I((b),(c),(d))); \
+	a=ROTATE(a,s); \
+	a+=b; };
+
+/* Implemented from RFC1321 The MD5 Message-Digest Algorithm. */
+
+#ifndef MD5_ASM
+static void
+md5_block_data_order(MD5_CTX *c, const void *_in, size_t num)
+{
+	const uint8_t *in = _in;
+	MD5_LONG A, B, C, D;
+	MD5_LONG X0, X1, X2, X3, X4, X5, X6, X7,
+	    X8, X9, X10, X11, X12, X13, X14, X15;
+
+	A = c->A;
+	B = c->B;
+	C = c->C;
+	D = c->D;
+
+	for (; num--; ) {
+		X0 = crypto_load_le32toh(&in[0 * 4]);
+		X1 = crypto_load_le32toh(&in[1 * 4]);
+		X2 = crypto_load_le32toh(&in[2 * 4]);
+		X3 = crypto_load_le32toh(&in[3 * 4]);
+		X4 = crypto_load_le32toh(&in[4 * 4]);
+		X5 = crypto_load_le32toh(&in[5 * 4]);
+		X6 = crypto_load_le32toh(&in[6 * 4]);
+		X7 = crypto_load_le32toh(&in[7 * 4]);
+		X8 = crypto_load_le32toh(&in[8 * 4]);
+		X9 = crypto_load_le32toh(&in[9 * 4]);
+		X10 = crypto_load_le32toh(&in[10 * 4]);
+		X11 = crypto_load_le32toh(&in[11 * 4]);
+		X12 = crypto_load_le32toh(&in[12 * 4]);
+		X13 = crypto_load_le32toh(&in[13 * 4]);
+		X14 = crypto_load_le32toh(&in[14 * 4]);
+		X15 = crypto_load_le32toh(&in[15 * 4]);
+		in += MD5_CBLOCK;
+
+		/* Round 0 */
+		R0(A, B, C, D, X0, 7, 0xd76aa478L);
+		R0(D, A, B, C, X1, 12, 0xe8c7b756L);
+		R0(C, D, A, B, X2, 17, 0x242070dbL);
+		R0(B, C, D, A, X3, 22, 0xc1bdceeeL);
+		R0(A, B, C, D, X4, 7, 0xf57c0fafL);
+		R0(D, A, B, C, X5, 12, 0x4787c62aL);
+		R0(C, D, A, B, X6, 17, 0xa8304613L);
+		R0(B, C, D, A, X7, 22, 0xfd469501L);
+		R0(A, B, C, D, X8, 7, 0x698098d8L);
+		R0(D, A, B, C, X9, 12, 0x8b44f7afL);
+		R0(C, D, A, B, X10, 17, 0xffff5bb1L);
+		R0(B, C, D, A, X11, 22, 0x895cd7beL);
+		R0(A, B, C, D, X12, 7, 0x6b901122L);
+		R0(D, A, B, C, X13, 12, 0xfd987193L);
+		R0(C, D, A, B, X14, 17, 0xa679438eL);
+		R0(B, C, D, A, X15, 22, 0x49b40821L);
+		/* Round 1 */
+		R1(A, B, C, D, X1, 5, 0xf61e2562L);
+		R1(D, A, B, C, X6, 9, 0xc040b340L);
+		R1(C, D, A, B, X11, 14, 0x265e5a51L);
+		R1(B, C, D, A, X0, 20, 0xe9b6c7aaL);
+		R1(A, B, C, D, X5, 5, 0xd62f105dL);
+		R1(D, A, B, C, X10, 9, 0x02441453L);
+		R1(C, D, A, B, X15, 14, 0xd8a1e681L);
+		R1(B, C, D, A, X4, 20, 0xe7d3fbc8L);
+		R1(A, B, C, D, X9, 5, 0x21e1cde6L);
+		R1(D, A, B, C, X14, 9, 0xc33707d6L);
+		R1(C, D, A, B, X3, 14, 0xf4d50d87L);
+		R1(B, C, D, A, X8, 20, 0x455a14edL);
+		R1(A, B, C, D, X13, 5, 0xa9e3e905L);
+		R1(D, A, B, C, X2, 9, 0xfcefa3f8L);
+		R1(C, D, A, B, X7, 14, 0x676f02d9L);
+		R1(B, C, D, A, X12, 20, 0x8d2a4c8aL);
+		/* Round 2 */
+		R2(A, B, C, D, X5, 4, 0xfffa3942L);
+		R2(D, A, B, C, X8, 11, 0x8771f681L);
+		R2(C, D, A, B, X11, 16, 0x6d9d6122L);
+		R2(B, C, D, A, X14, 23, 0xfde5380cL);
+		R2(A, B, C, D, X1, 4, 0xa4beea44L);
+		R2(D, A, B, C, X4, 11, 0x4bdecfa9L);
+		R2(C, D, A, B, X7, 16, 0xf6bb4b60L);
+		R2(B, C, D, A, X10, 23, 0xbebfbc70L);
+		R2(A, B, C, D, X13, 4, 0x289b7ec6L);
+		R2(D, A, B, C, X0, 11, 0xeaa127faL);
+		R2(C, D, A, B, X3, 16, 0xd4ef3085L);
+		R2(B, C, D, A, X6, 23, 0x04881d05L);
+		R2(A, B, C, D, X9, 4, 0xd9d4d039L);
+		R2(D, A, B, C, X12, 11, 0xe6db99e5L);
+		R2(C, D, A, B, X15, 16, 0x1fa27cf8L);
+		R2(B, C, D, A, X2, 23, 0xc4ac5665L);
+		/* Round 3 */
+		R3(A, B, C, D, X0, 6, 0xf4292244L);
+		R3(D, A, B, C, X7, 10, 0x432aff97L);
+		R3(C, D, A, B, X14, 15, 0xab9423a7L);
+		R3(B, C, D, A, X5, 21, 0xfc93a039L);
+		R3(A, B, C, D, X12, 6, 0x655b59c3L);
+		R3(D, A, B, C, X3, 10, 0x8f0ccc92L);
+		R3(C, D, A, B, X10, 15, 0xffeff47dL);
+		R3(B, C, D, A, X1, 21, 0x85845dd1L);
+		R3(A, B, C, D, X8, 6, 0x6fa87e4fL);
+		R3(D, A, B, C, X15, 10, 0xfe2ce6e0L);
+		R3(C, D, A, B, X6, 15, 0xa3014314L);
+		R3(B, C, D, A, X13, 21, 0x4e0811a1L);
+		R3(A, B, C, D, X4, 6, 0xf7537e82L);
+		R3(D, A, B, C, X11, 10, 0xbd3af235L);
+		R3(C, D, A, B, X2, 15, 0x2ad7d2bbL);
+		R3(B, C, D, A, X9, 21, 0xeb86d391L);
+
+		A = c->A += A;
+		B = c->B += B;
+		C = c->C += C;
+		D = c->D += D;
+	}
+}
+#endif
+
+int
+MD5_Init(MD5_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->A = 0x67452301UL;
+	c->B = 0xefcdab89UL;
+	c->C = 0x98badcfeUL;
+	c->D = 0x10325476UL;
+
+	return 1;
+}
+LCRYPTO_ALIAS(MD5_Init);
+
+int
+MD5_Update(MD5_CTX *c, const void *data_, size_t len)
+{
+	const unsigned char *data = data_;
+	unsigned char *p;
+	MD5_LONG l;
+	size_t n;
+
+	if (len == 0)
+		return 1;
+
+	l = (c->Nl + (((MD5_LONG)len) << 3))&0xffffffffUL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai  for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(MD5_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
+	c->Nl = l;
+
+	n = c->num;
+	if (n != 0) {
+		p = (unsigned char *)c->data;
+
+		if (len >= MD5_CBLOCK || len + n >= MD5_CBLOCK) {
+			memcpy(p + n, data, MD5_CBLOCK - n);
+			md5_block_data_order(c, p, 1);
+			n = MD5_CBLOCK - n;
+			data += n;
+			len -= n;
+			c->num = 0;
+			memset(p, 0, MD5_CBLOCK);	/* keep it zeroed */
+		} else {
+			memcpy(p + n, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		}
+	}
+
+	n = len/MD5_CBLOCK;
+	if (n > 0) {
+		md5_block_data_order(c, data, n);
+		n *= MD5_CBLOCK;
+		data += n;
+		len -= n;
+	}
+
+	if (len != 0) {
+		p = (unsigned char *)c->data;
+		c->num = (unsigned int)len;
+		memcpy(p, data, len);
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(MD5_Update);
+
+void
+MD5_Transform(MD5_CTX *c, const unsigned char *data)
+{
+	md5_block_data_order(c, data, 1);
+}
+LCRYPTO_ALIAS(MD5_Transform);
+
+int
+MD5_Final(unsigned char *md, MD5_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	size_t n = c->num;
+
+	p[n] = 0x80; /* there is always room for one */
+	n++;
+
+	if (n > (MD5_CBLOCK - 8)) {
+		memset(p + n, 0, MD5_CBLOCK - n);
+		n = 0;
+		md5_block_data_order(c, p, 1);
+	}
+
+	memset(p + n, 0, MD5_CBLOCK - 8 - n);
+	c->data[MD5_LBLOCK - 2] = htole32(c->Nl);
+	c->data[MD5_LBLOCK - 1] = htole32(c->Nh);
+
+	md5_block_data_order(c, p, 1);
+	c->num = 0;
+	memset(p, 0, MD5_CBLOCK);
+
+	crypto_store_htole32(&md[0 * 4], c->A);
+	crypto_store_htole32(&md[1 * 4], c->B);
+	crypto_store_htole32(&md[2 * 4], c->C);
+	crypto_store_htole32(&md[3 * 4], c->D);
+
+	return 1;
+}
+LCRYPTO_ALIAS(MD5_Final);
+
+unsigned char *
+MD5(const unsigned char *d, size_t n, unsigned char *md)
+{
+	MD5_CTX c;
+	static unsigned char m[MD5_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	if (!MD5_Init(&c))
+		return NULL;
+	MD5_Update(&c, d, n);
+	MD5_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
+LCRYPTO_ALIAS(MD5);
diff --git a/crypto/mem_clr.c b/crypto/mem_clr.c
new file mode 100644
index 0000000..9ee5e65
--- /dev/null
+++ b/crypto/mem_clr.c
@@ -0,0 +1,11 @@
+/* $OpenBSD: mem_clr.c,v 1.4 2014/06/12 15:49:27 deraadt Exp $ */
+
+/* Ted Unangst places this file in the public domain. */
+#include 
+#include 
+
+void
+OPENSSL_cleanse(void *ptr, size_t len)
+{
+	explicit_bzero(ptr, len);
+}
diff --git a/crypto/mem_dbg.c b/crypto/mem_dbg.c
new file mode 100644
index 0000000..e2eaceb
--- /dev/null
+++ b/crypto/mem_dbg.c
@@ -0,0 +1,209 @@
+/* $OpenBSD: mem_dbg.c,v 1.25 2023/07/08 08:28:23 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+CRYPTO_mem_ctrl(int mode)
+{
+	return (CRYPTO_MEM_CHECK_OFF);
+}
+
+int
+CRYPTO_is_mem_check_on(void)
+{
+	return (0);
+}
+
+
+void
+CRYPTO_dbg_set_options(long bits)
+{
+	return;
+}
+LCRYPTO_ALIAS(CRYPTO_dbg_set_options);
+
+long
+CRYPTO_dbg_get_options(void)
+{
+	return (0);
+}
+LCRYPTO_ALIAS(CRYPTO_dbg_get_options);
+
+int
+CRYPTO_push_info_(const char *info, const char *file, int line)
+{
+	return (0);
+}
+LCRYPTO_ALIAS(CRYPTO_push_info_);
+
+int
+CRYPTO_pop_info(void)
+{
+	return (0);
+}
+LCRYPTO_ALIAS(CRYPTO_pop_info);
+
+int
+CRYPTO_remove_all_info(void)
+{
+	return (0);
+}
+LCRYPTO_ALIAS(CRYPTO_remove_all_info);
+
+void
+CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
+    int before_p)
+{
+	OPENSSL_assert("CRYPTO_dbg_malloc is no longer permitted");
+}
+LCRYPTO_ALIAS(CRYPTO_dbg_malloc);
+
+void
+CRYPTO_dbg_free(void *addr, int before_p)
+{
+	OPENSSL_assert("CRYPTO_dbg_free is no longer permitted");
+}
+LCRYPTO_ALIAS(CRYPTO_dbg_free);
+
+void
+CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
+    const char *file, int line, int before_p)
+{
+	OPENSSL_assert("CRYPTO_dbg_realloc is no longer permitted");
+}
+LCRYPTO_ALIAS(CRYPTO_dbg_realloc);
+
+int
+CRYPTO_mem_leaks(BIO *b)
+{
+	return -1;
+}
+LCRYPTO_ALIAS(CRYPTO_mem_leaks);
+
+int
+CRYPTO_mem_leaks_fp(FILE *fp)
+{
+	return -1;
+}
+LCRYPTO_ALIAS(CRYPTO_mem_leaks_fp);
+
+
+int
+CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
+{
+	return -1;
+}
+LCRYPTO_ALIAS(CRYPTO_mem_leaks_cb);
diff --git a/crypto/modes/cbc128.c b/crypto/modes/cbc128.c
new file mode 100644
index 0000000..f8ebf79
--- /dev/null
+++ b/crypto/modes/cbc128.c
@@ -0,0 +1,214 @@
+/* $OpenBSD: cbc128.c,v 1.8 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+#undef STRICT_ALIGNMENT
+#ifdef __STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 1
+#else
+#define STRICT_ALIGNMENT 0
+#endif
+
+void
+CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], block128_f block)
+{
+	size_t n;
+	const unsigned char *iv = ivec;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (STRICT_ALIGNMENT &&
+	    ((size_t)in|(size_t)out|(size_t)ivec) % sizeof(size_t) != 0) {
+		while (len >= 16) {
+			for (n = 0; n < 16; ++n)
+				out[n] = in[n] ^ iv[n];
+			(*block)(out, out, key);
+			iv = out;
+			len -= 16;
+			in += 16;
+			out += 16;
+		}
+	} else {
+		while (len >= 16) {
+			for (n = 0; n < 16; n += sizeof(size_t))
+				*(size_t *)(out + n) =
+				    *(size_t *)(in + n) ^ *(size_t *)(iv + n);
+			(*block)(out, out, key);
+			iv = out;
+			len -= 16;
+			in += 16;
+			out += 16;
+		}
+	}
+#endif
+	while (len) {
+		for (n = 0; n < 16 && n < len; ++n)
+			out[n] = in[n] ^ iv[n];
+		for (; n < 16; ++n)
+			out[n] = iv[n];
+		(*block)(out, out, key);
+		iv = out;
+		if (len <= 16)
+			break;
+		len -= 16;
+		in += 16;
+		out += 16;
+	}
+	memmove(ivec, iv, 16);
+}
+LCRYPTO_ALIAS(CRYPTO_cbc128_encrypt);
+
+void
+CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], block128_f block)
+{
+	size_t n;
+	union {
+		size_t t[16/sizeof(size_t)];
+		unsigned char c[16];
+	} tmp;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (in != out) {
+		const unsigned char *iv = ivec;
+
+		if (STRICT_ALIGNMENT &&
+		    ((size_t)in|(size_t)out|(size_t)ivec) % sizeof(size_t) !=
+		    0) {
+			while (len >= 16) {
+				(*block)(in, out, key);
+				for (n = 0; n < 16; ++n)
+					out[n] ^= iv[n];
+				iv = in;
+				len -= 16;
+				in += 16;
+				out += 16;
+			}
+		} else if (16 % sizeof(size_t) == 0) { /* always true */
+			while (len >= 16) {
+				size_t *out_t = (size_t *)out,
+				       *iv_t = (size_t *)iv;
+
+				(*block)(in, out, key);
+				for (n = 0; n < 16/sizeof(size_t); n++)
+					out_t[n] ^= iv_t[n];
+				iv = in;
+				len -= 16;
+				in += 16;
+				out += 16;
+			}
+		}
+		memmove(ivec, iv, 16);
+	} else {
+		if (STRICT_ALIGNMENT &&
+		    ((size_t)in|(size_t)out|(size_t)ivec) % sizeof(size_t) !=
+		    0) {
+			unsigned char c;
+			while (len >= 16) {
+				(*block)(in, tmp.c, key);
+				for (n = 0; n < 16; ++n) {
+					c = in[n];
+					out[n] = tmp.c[n] ^ ivec[n];
+					ivec[n] = c;
+				}
+				len -= 16;
+				in += 16;
+				out += 16;
+			}
+		} else if (16 % sizeof(size_t) == 0) { /* always true */
+			while (len >= 16) {
+				size_t c, *out_t = (size_t *)out,
+				       *ivec_t = (size_t *)ivec;
+				const size_t *in_t = (const size_t *)in;
+
+				(*block)(in, tmp.c, key);
+				for (n = 0; n < 16/sizeof(size_t); n++) {
+					c = in_t[n];
+					out_t[n] = tmp.t[n] ^ ivec_t[n];
+					ivec_t[n] = c;
+				}
+				len -= 16;
+				in += 16;
+				out += 16;
+			}
+		}
+	}
+#endif
+	while (len) {
+		unsigned char c;
+		(*block)(in, tmp.c, key);
+		for (n = 0; n < 16 && n < len; ++n) {
+			c = in[n];
+			out[n] = tmp.c[n] ^ ivec[n];
+			ivec[n] = c;
+		}
+		if (len <= 16) {
+			for (; n < 16; ++n)
+				ivec[n] = in[n];
+			break;
+		}
+		len -= 16;
+		in += 16;
+		out += 16;
+	}
+}
+LCRYPTO_ALIAS(CRYPTO_cbc128_decrypt);
diff --git a/crypto/modes/ccm128.c b/crypto/modes/ccm128.c
new file mode 100644
index 0000000..68c5cce
--- /dev/null
+++ b/crypto/modes/ccm128.c
@@ -0,0 +1,498 @@
+/* $OpenBSD: ccm128.c,v 1.8 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+/* First you setup M and L parameters and pass the key schedule.
+ * This is called once per session setup... */
+void
+CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
+    unsigned int M, unsigned int L, void *key, block128_f block)
+{
+	memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
+	ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2)/2) & 7) << 3;
+	ctx->blocks = 0;
+	ctx->block = block;
+	ctx->key = key;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_init);
+
+/* !!! Following interfaces are to be called *once* per packet !!! */
+
+/* Then you setup per-message nonce and pass the length of the message */
+int
+CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
+    const unsigned char *nonce, size_t nlen, size_t mlen)
+{
+	unsigned int L = ctx->nonce.c[0] & 7;	/* the L parameter */
+
+	if (nlen < (14 - L))
+		return -1;		/* nonce is too short */
+
+	if (sizeof(mlen) == 8 && L >= 3) {
+		ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen)*8)));
+		ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen)*8)));
+		ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen)*8)));
+		ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen)*8)));
+	} else
+		ctx->nonce.u[1] = 0;
+
+	ctx->nonce.c[12] = (u8)(mlen >> 24);
+	ctx->nonce.c[13] = (u8)(mlen >> 16);
+	ctx->nonce.c[14] = (u8)(mlen >> 8);
+	ctx->nonce.c[15] = (u8)mlen;
+
+	ctx->nonce.c[0] &= ~0x40;	/* clear Adata flag */
+	memcpy(&ctx->nonce.c[1], nonce, 14 - L);
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_setiv);
+
+/* Then you pass additional authentication data, this is optional */
+void
+CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
+    const unsigned char *aad, size_t alen)
+{
+	unsigned int i;
+	block128_f block = ctx->block;
+
+	if (alen == 0)
+		return;
+
+	ctx->nonce.c[0] |= 0x40;	/* set Adata flag */
+	(*block)(ctx->nonce.c, ctx->cmac.c, ctx->key),
+	    ctx->blocks++;
+
+	if (alen < (0x10000 - 0x100)) {
+		ctx->cmac.c[0] ^= (u8)(alen >> 8);
+		ctx->cmac.c[1] ^= (u8)alen;
+		i = 2;
+	} else if (sizeof(alen) == 8 &&
+	    alen >= (size_t)1 << (32 % (sizeof(alen)*8))) {
+		ctx->cmac.c[0] ^= 0xFF;
+		ctx->cmac.c[1] ^= 0xFF;
+		ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen)*8)));
+		ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen)*8)));
+		ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen)*8)));
+		ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen)*8)));
+		ctx->cmac.c[6] ^= (u8)(alen >> 24);
+		ctx->cmac.c[7] ^= (u8)(alen >> 16);
+		ctx->cmac.c[8] ^= (u8)(alen >> 8);
+		ctx->cmac.c[9] ^= (u8)alen;
+		i = 10;
+	} else {
+		ctx->cmac.c[0] ^= 0xFF;
+		ctx->cmac.c[1] ^= 0xFE;
+		ctx->cmac.c[2] ^= (u8)(alen >> 24);
+		ctx->cmac.c[3] ^= (u8)(alen >> 16);
+		ctx->cmac.c[4] ^= (u8)(alen >> 8);
+		ctx->cmac.c[5] ^= (u8)alen;
+		i = 6;
+	}
+
+	do {
+		for (; i < 16 && alen; ++i, ++aad, --alen)
+			ctx->cmac.c[i] ^= *aad;
+		(*block)(ctx->cmac.c, ctx->cmac.c, ctx->key),
+		    ctx->blocks++;
+		i = 0;
+	} while (alen);
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_aad);
+
+/* Finally you encrypt or decrypt the message */
+
+/* counter part of nonce may not be larger than L*8 bits,
+ * L is not larger than 8, therefore 64-bit counter... */
+static void
+ctr64_inc(unsigned char *counter)
+{
+	unsigned int n = 8;
+	u8 c;
+
+	counter += 8;
+	do {
+		--n;
+		c = counter[n];
+		++c;
+		counter[n] = c;
+		if (c)
+			return;
+	} while (n);
+}
+
+int
+CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
+    const unsigned char *inp, unsigned char *out,
+    size_t len)
+{
+	size_t		 n;
+	unsigned int	 i, L;
+	unsigned char	 flags0 = ctx->nonce.c[0];
+	block128_f	 block = ctx->block;
+	void		*key = ctx->key;
+	union {
+		u64 u[2];
+		u8 c[16];
+	} scratch;
+
+	if (!(flags0 & 0x40))
+		(*block)(ctx->nonce.c, ctx->cmac.c, key),
+		    ctx->blocks++;
+
+	ctx->nonce.c[0] = L = flags0 & 7;
+	for (n = 0, i = 15 - L; i < 15; ++i) {
+		n |= ctx->nonce.c[i];
+		ctx->nonce.c[i] = 0;
+		n <<= 8;
+	}
+	n |= ctx->nonce.c[15];	/* reconstructed length */
+	ctx->nonce.c[15] = 1;
+
+	if (n != len)
+		return -1;	/* length mismatch */
+
+	ctx->blocks += ((len + 15) >> 3)|1;
+	if (ctx->blocks > (U64(1) << 61))
+		return -2; /* too much data */
+
+	while (len >= 16) {
+#ifdef __STRICT_ALIGNMENT
+		union {
+			u64 u[2];
+			u8 c[16];
+		} temp;
+
+		memcpy(temp.c, inp, 16);
+		ctx->cmac.u[0] ^= temp.u[0];
+		ctx->cmac.u[1] ^= temp.u[1];
+#else
+		ctx->cmac.u[0] ^= ((u64 *)inp)[0];
+		ctx->cmac.u[1] ^= ((u64 *)inp)[1];
+#endif
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+		(*block)(ctx->nonce.c, scratch.c, key);
+		ctr64_inc(ctx->nonce.c);
+#ifdef __STRICT_ALIGNMENT
+		temp.u[0] ^= scratch.u[0];
+		temp.u[1] ^= scratch.u[1];
+		memcpy(out, temp.c, 16);
+#else
+		((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
+		((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
+#endif
+		inp += 16;
+		out += 16;
+		len -= 16;
+	}
+
+	if (len) {
+		for (i = 0; i < len; ++i)
+			ctx->cmac.c[i] ^= inp[i];
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+		(*block)(ctx->nonce.c, scratch.c, key);
+		for (i = 0; i < len; ++i)
+			out[i] = scratch.c[i] ^ inp[i];
+	}
+
+	for (i = 15 - L; i < 16; ++i)
+		ctx->nonce.c[i] = 0;
+
+	(*block)(ctx->nonce.c, scratch.c, key);
+	ctx->cmac.u[0] ^= scratch.u[0];
+	ctx->cmac.u[1] ^= scratch.u[1];
+
+	ctx->nonce.c[0] = flags0;
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_encrypt);
+
+int
+CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
+    const unsigned char *inp, unsigned char *out,
+    size_t len)
+{
+	size_t		 n;
+	unsigned int	 i, L;
+	unsigned char	 flags0 = ctx->nonce.c[0];
+	block128_f	 block = ctx->block;
+	void		*key = ctx->key;
+	union {
+		u64 u[2];
+		u8 c[16];
+	} scratch;
+
+	if (!(flags0 & 0x40))
+		(*block)(ctx->nonce.c, ctx->cmac.c, key);
+
+	ctx->nonce.c[0] = L = flags0 & 7;
+	for (n = 0, i = 15 - L; i < 15; ++i) {
+		n |= ctx->nonce.c[i];
+		ctx->nonce.c[i] = 0;
+		n <<= 8;
+	}
+	n |= ctx->nonce.c[15];	/* reconstructed length */
+	ctx->nonce.c[15] = 1;
+
+	if (n != len)
+		return -1;
+
+	while (len >= 16) {
+#ifdef __STRICT_ALIGNMENT
+		union {
+			u64 u[2];
+			u8 c[16];
+		} temp;
+#endif
+		(*block)(ctx->nonce.c, scratch.c, key);
+		ctr64_inc(ctx->nonce.c);
+#ifdef __STRICT_ALIGNMENT
+		memcpy(temp.c, inp, 16);
+		ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
+		ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
+		memcpy(out, scratch.c, 16);
+#else
+		ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^
+		    ((u64 *)inp)[0]);
+		ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^
+		    ((u64 *)inp)[1]);
+#endif
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+
+		inp += 16;
+		out += 16;
+		len -= 16;
+	}
+
+	if (len) {
+		(*block)(ctx->nonce.c, scratch.c, key);
+		for (i = 0; i < len; ++i)
+			ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+	}
+
+	for (i = 15 - L; i < 16; ++i)
+		ctx->nonce.c[i] = 0;
+
+	(*block)(ctx->nonce.c, scratch.c, key);
+	ctx->cmac.u[0] ^= scratch.u[0];
+	ctx->cmac.u[1] ^= scratch.u[1];
+
+	ctx->nonce.c[0] = flags0;
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_decrypt);
+
+static void
+ctr64_add(unsigned char *counter, size_t inc)
+{
+	size_t n = 8, val = 0;
+
+	counter += 8;
+	do {
+		--n;
+		val += counter[n] + (inc & 0xff);
+		counter[n] = (unsigned char)val;
+		val >>= 8;	/* carry bit */
+		inc >>= 8;
+	} while (n && (inc || val));
+}
+
+int
+CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
+    const unsigned char *inp, unsigned char *out,
+    size_t len, ccm128_f stream)
+{
+	size_t		 n;
+	unsigned int	 i, L;
+	unsigned char	 flags0 = ctx->nonce.c[0];
+	block128_f	 block = ctx->block;
+	void		*key = ctx->key;
+	union {
+		u64 u[2];
+		u8 c[16];
+	} scratch;
+
+	if (!(flags0 & 0x40))
+		(*block)(ctx->nonce.c, ctx->cmac.c, key),
+		    ctx->blocks++;
+
+	ctx->nonce.c[0] = L = flags0 & 7;
+	for (n = 0, i = 15 - L; i < 15; ++i) {
+		n |= ctx->nonce.c[i];
+		ctx->nonce.c[i] = 0;
+		n <<= 8;
+	}
+	n |= ctx->nonce.c[15];	/* reconstructed length */
+	ctx->nonce.c[15] = 1;
+
+	if (n != len)
+		return -1;	/* length mismatch */
+
+	ctx->blocks += ((len + 15) >> 3)|1;
+	if (ctx->blocks > (U64(1) << 61))
+		return -2; /* too much data */
+
+	if ((n = len/16)) {
+		(*stream)(inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
+		n *= 16;
+		inp += n;
+		out += n;
+		len -= n;
+		if (len)
+			ctr64_add(ctx->nonce.c, n/16);
+	}
+
+	if (len) {
+		for (i = 0; i < len; ++i)
+			ctx->cmac.c[i] ^= inp[i];
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+		(*block)(ctx->nonce.c, scratch.c, key);
+		for (i = 0; i < len; ++i)
+			out[i] = scratch.c[i] ^ inp[i];
+	}
+
+	for (i = 15 - L; i < 16; ++i)
+		ctx->nonce.c[i] = 0;
+
+	(*block)(ctx->nonce.c, scratch.c, key);
+	ctx->cmac.u[0] ^= scratch.u[0];
+	ctx->cmac.u[1] ^= scratch.u[1];
+
+	ctx->nonce.c[0] = flags0;
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_encrypt_ccm64);
+
+int
+CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
+    const unsigned char *inp, unsigned char *out,
+    size_t len, ccm128_f stream)
+{
+	size_t		 n;
+	unsigned int	 i, L;
+	unsigned char	 flags0 = ctx->nonce.c[0];
+	block128_f	 block = ctx->block;
+	void		*key = ctx->key;
+	union {
+		u64 u[2];
+		u8 c[16];
+	} scratch;
+
+	if (!(flags0 & 0x40))
+		(*block)(ctx->nonce.c, ctx->cmac.c, key);
+
+	ctx->nonce.c[0] = L = flags0 & 7;
+	for (n = 0, i = 15 - L; i < 15; ++i) {
+		n |= ctx->nonce.c[i];
+		ctx->nonce.c[i] = 0;
+		n <<= 8;
+	}
+	n |= ctx->nonce.c[15];	/* reconstructed length */
+	ctx->nonce.c[15] = 1;
+
+	if (n != len)
+		return -1;
+
+	if ((n = len/16)) {
+		(*stream)(inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
+		n *= 16;
+		inp += n;
+		out += n;
+		len -= n;
+		if (len)
+			ctr64_add(ctx->nonce.c, n/16);
+	}
+
+	if (len) {
+		(*block)(ctx->nonce.c, scratch.c, key);
+		for (i = 0; i < len; ++i)
+			ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
+		(*block)(ctx->cmac.c, ctx->cmac.c, key);
+	}
+
+	for (i = 15 - L; i < 16; ++i)
+		ctx->nonce.c[i] = 0;
+
+	(*block)(ctx->nonce.c, scratch.c, key);
+	ctx->cmac.u[0] ^= scratch.u[0];
+	ctx->cmac.u[1] ^= scratch.u[1];
+
+	ctx->nonce.c[0] = flags0;
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_decrypt_ccm64);
+
+size_t
+CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
+{
+	unsigned int M = (ctx->nonce.c[0] >> 3) & 7;	/* the M parameter */
+
+	M *= 2;
+	M += 2;
+	if (len != M)
+		return 0;
+	memcpy(tag, ctx->cmac.c, M);
+	return M;
+}
+LCRYPTO_ALIAS(CRYPTO_ccm128_tag);
diff --git a/crypto/modes/cfb128.c b/crypto/modes/cfb128.c
new file mode 100644
index 0000000..931353a
--- /dev/null
+++ b/crypto/modes/cfb128.c
@@ -0,0 +1,251 @@
+/* $OpenBSD: cfb128.c,v 1.7 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+/* The input and output encrypted as though 128bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num;
+ */
+void
+CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], int *num,
+    int enc, block128_f block)
+{
+	unsigned int n;
+	size_t l = 0;
+
+	n = *num;
+
+	if (enc) {
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+		if (16 % sizeof(size_t) == 0)
+			do {	/* always true actually */
+				while (n && len) {
+					*(out++) = ivec[n] ^= *(in++);
+					--len;
+					n = (n + 1) % 16;
+				}
+#ifdef __STRICT_ALIGNMENT
+				if (((size_t)in|(size_t)out|(size_t)ivec) %
+				    sizeof(size_t) != 0)
+					break;
+#endif
+				while (len >= 16) {
+					(*block)(ivec, ivec, key);
+					for (; n < 16; n += sizeof(size_t)) {
+						*(size_t *)(out + n) =
+						    *(size_t *)(ivec + n) ^= *(size_t *)(in +
+						    n);
+					}
+					len -= 16;
+					out += 16;
+					in += 16;
+					n = 0;
+				}
+				if (len) {
+					(*block)(ivec, ivec, key);
+					while (len--) {
+						out[n] = ivec[n] ^= in[n];
+						++n;
+					}
+				}
+				*num = n;
+				return;
+			} while (0);
+	/* the rest would be commonly eliminated by x86* compiler */
+#endif
+		while (l < len) {
+			if (n == 0) {
+				(*block)(ivec, ivec, key);
+			}
+			out[l] = ivec[n] ^= in[l];
+			++l;
+			n = (n + 1) % 16;
+		}
+		*num = n;
+	} else {
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+		if (16 % sizeof(size_t) == 0)
+			do {	/* always true actually */
+				while (n && len) {
+					unsigned char c;
+					*(out++) = ivec[n] ^ (c = *(in++));
+					ivec[n] = c;
+					--len;
+					n = (n + 1) % 16;
+				}
+#ifdef __STRICT_ALIGNMENT
+				if (((size_t)in|(size_t)out|(size_t)ivec) %
+				    sizeof(size_t) != 0)
+					break;
+#endif
+				while (len >= 16) {
+					(*block)(ivec, ivec, key);
+					for (; n < 16; n += sizeof(size_t)) {
+						size_t t = *(size_t *)(in + n);
+						*(size_t *)(out + n) = *(size_t *)(ivec +
+						    n) ^ t;
+						*(size_t *)(ivec + n) = t;
+					}
+					len -= 16;
+					out += 16;
+					in += 16;
+					n = 0;
+				}
+				if (len) {
+					(*block)(ivec, ivec, key);
+					while (len--) {
+						unsigned char c;
+						out[n] = ivec[n] ^ (c = in[n]);
+						ivec[n] = c;
+						++n;
+					}
+				}
+				*num = n;
+				return;
+			} while (0);
+	/* the rest would be commonly eliminated by x86* compiler */
+#endif
+		while (l < len) {
+			unsigned char c;
+			if (n == 0) {
+				(*block)(ivec, ivec, key);
+			}
+			out[l] = ivec[n] ^ (c = in[l]);
+			ivec[n] = c;
+			++l;
+			n = (n + 1) % 16;
+		}
+		*num = n;
+	}
+}
+LCRYPTO_ALIAS(CRYPTO_cfb128_encrypt);
+
+/* This expects a single block of size nbits for both in and out. Note that
+   it corrupts any extra bits in the last byte of out */
+static void
+cfbr_encrypt_block(const unsigned char *in, unsigned char *out,
+    int nbits, const void *key,
+    unsigned char ivec[16], int enc,
+    block128_f block)
+{
+	int n, rem, num;
+	unsigned char ovec[16*2 + 1];  /* +1 because we dererefence (but don't use) one byte off the end */
+
+	if (nbits <= 0 || nbits > 128)
+		return;
+
+	/* fill in the first half of the new IV with the current IV */
+	memcpy(ovec, ivec, 16);
+	/* construct the new IV */
+	(*block)(ivec, ivec, key);
+	num = (nbits + 7)/8;
+	if (enc)	/* encrypt the input */
+		for (n = 0; n < num; ++n)
+			out[n] = (ovec[16 + n] = in[n] ^ ivec[n]);
+	else		/* decrypt the input */
+		for (n = 0; n < num; ++n)
+			out[n] = (ovec[16 + n] = in[n]) ^ ivec[n];
+	/* shift ovec left... */
+	rem = nbits % 8;
+	num = nbits/8;
+	if (rem == 0)
+		memcpy(ivec, ovec + num, 16);
+	else
+		for (n = 0; n < 16; ++n)
+			ivec[n] = ovec[n + num] << rem |
+			    ovec[n + num + 1] >> (8 - rem);
+
+    /* it is not necessary to cleanse ovec, since the IV is not secret */
+}
+
+/* N.B. This expects the input to be packed, MS bit first */
+void
+CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out,
+    size_t bits, const void *key,
+    unsigned char ivec[16], int *num,
+    int enc, block128_f block)
+{
+	size_t n;
+	unsigned char c[1], d[1];
+
+	for (n = 0; n < bits; ++n)
+	{
+		c[0] = (in[n/8] & (1 << (7 - n % 8))) ? 0x80 : 0;
+		cfbr_encrypt_block(c, d, 1, key, ivec, enc, block);
+		out[n/8] = (out[n/8] & ~(1 << (unsigned int)(7 - n % 8))) |
+		    ((d[0] & 0x80) >> (unsigned int)(n % 8));
+	}
+}
+LCRYPTO_ALIAS(CRYPTO_cfb128_1_encrypt);
+
+void
+CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
+    size_t length, const void *key,
+    unsigned char ivec[16], int *num,
+    int enc, block128_f block)
+{
+	size_t n;
+
+	for (n = 0; n < length; ++n)
+		cfbr_encrypt_block(&in[n], &out[n], 8, key, ivec, enc, block);
+}
+LCRYPTO_ALIAS(CRYPTO_cfb128_8_encrypt);
diff --git a/crypto/modes/ctr128.c b/crypto/modes/ctr128.c
new file mode 100644
index 0000000..6d507df
--- /dev/null
+++ b/crypto/modes/ctr128.c
@@ -0,0 +1,267 @@
+/* $OpenBSD: ctr128.c,v 1.11 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+#include 
+
+/* NOTE: the IV/counter CTR mode is big-endian.  The code itself
+ * is endian-neutral. */
+
+/* increment counter (128-bit int) by 1 */
+static void
+ctr128_inc(unsigned char *counter)
+{
+	u32 n = 16;
+	u8  c;
+
+	do {
+		--n;
+		c = counter[n];
+		++c;
+		counter[n] = c;
+		if (c)
+			return;
+	} while (n);
+}
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+static void
+ctr128_inc_aligned(unsigned char *counter)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+	ctr128_inc(counter);
+#else
+	size_t *data, c, n;
+	data = (size_t *)counter;
+	n = 16 / sizeof(size_t);
+	do {
+		--n;
+		c = data[n];
+		++c;
+		data[n] = c;
+		if (c)
+			return;
+	} while (n);
+#endif
+}
+#endif
+
+/* The input encrypted as though 128bit counter mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num, and the
+ * encrypted counter is kept in ecount_buf.  Both *num and
+ * ecount_buf must be initialised with zeros before the first
+ * call to CRYPTO_ctr128_encrypt().
+ *
+ * This algorithm assumes that the counter is in the x lower bits
+ * of the IV (ivec), and that the application has full control over
+ * overflow and the rest of the IV.  This implementation takes NO
+ * responsibility for checking that the counter doesn't overflow
+ * into the rest of the IV when incremented.
+ */
+void
+CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], unsigned char ecount_buf[16],
+    unsigned int *num, block128_f block)
+{
+	unsigned int n;
+	size_t l = 0;
+
+	assert(*num < 16);
+
+	n = *num;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (16 % sizeof(size_t) == 0)
+		do { /* always true actually */
+			while (n && len) {
+				*(out++) = *(in++) ^ ecount_buf[n];
+				--len;
+				n = (n + 1) % 16;
+			}
+
+#ifdef __STRICT_ALIGNMENT
+			if (((size_t)in|(size_t)out|(size_t)ivec) %
+			    sizeof(size_t) != 0)
+				break;
+#endif
+			while (len >= 16) {
+				(*block)(ivec, ecount_buf, key);
+				ctr128_inc_aligned(ivec);
+				for (; n < 16; n += sizeof(size_t))
+					*(size_t *)(out + n) =
+					    *(size_t *)(in + n) ^ *(size_t *)(ecount_buf +
+					    n);
+				len -= 16;
+				out += 16;
+				in += 16;
+				n = 0;
+			}
+			if (len) {
+				(*block)(ivec, ecount_buf, key);
+				ctr128_inc_aligned(ivec);
+				while (len--) {
+					out[n] = in[n] ^ ecount_buf[n];
+					++n;
+				}
+			}
+			*num = n;
+			return;
+		} while (0);
+	/* the rest would be commonly eliminated by x86* compiler */
+#endif
+	while (l < len) {
+		if (n == 0) {
+			(*block)(ivec, ecount_buf, key);
+			ctr128_inc(ivec);
+		}
+		out[l] = in[l] ^ ecount_buf[n];
+		++l;
+		n = (n + 1) % 16;
+	}
+
+	*num = n;
+}
+LCRYPTO_ALIAS(CRYPTO_ctr128_encrypt);
+
+/* increment upper 96 bits of 128-bit counter by 1 */
+static void
+ctr96_inc(unsigned char *counter)
+{
+	u32 n = 12;
+	u8  c;
+
+	do {
+		--n;
+		c = counter[n];
+		++c;
+		counter[n] = c;
+		if (c)
+			return;
+	} while (n);
+}
+
+void
+CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], unsigned char ecount_buf[16],
+    unsigned int *num, ctr128_f func)
+{
+	unsigned int n, ctr32;
+
+	assert(*num < 16);
+
+	n = *num;
+
+	while (n && len) {
+		*(out++) = *(in++) ^ ecount_buf[n];
+		--len;
+		n = (n + 1) % 16;
+	}
+
+	ctr32 = GETU32(ivec + 12);
+	while (len >= 16) {
+		size_t blocks = len/16;
+		/*
+		 * 1<<28 is just a not-so-small yet not-so-large number...
+		 * Below condition is practically never met, but it has to
+		 * be checked for code correctness.
+		 */
+		if (sizeof(size_t) > sizeof(unsigned int) &&
+		    blocks > (1U << 28))
+			blocks = (1U << 28);
+		/*
+		 * As (*func) operates on 32-bit counter, caller
+		 * has to handle overflow. 'if' below detects the
+		 * overflow, which is then handled by limiting the
+		 * amount of blocks to the exact overflow point...
+		 */
+		ctr32 += (u32)blocks;
+		if (ctr32 < blocks) {
+			blocks -= ctr32;
+			ctr32 = 0;
+		}
+		(*func)(in, out, blocks, key, ivec);
+		/* (*ctr) does not update ivec, caller does: */
+		PUTU32(ivec + 12, ctr32);
+		/* ... overflow was detected, propagate carry. */
+		if (ctr32 == 0)
+			ctr96_inc(ivec);
+		blocks *= 16;
+		len -= blocks;
+		out += blocks;
+		in += blocks;
+	}
+	if (len) {
+		memset(ecount_buf, 0, 16);
+		(*func)(ecount_buf, ecount_buf, 1, key, ivec);
+		++ctr32;
+		PUTU32(ivec + 12, ctr32);
+		if (ctr32 == 0)
+			ctr96_inc(ivec);
+		while (len--) {
+			out[n] = in[n] ^ ecount_buf[n];
+			++n;
+		}
+	}
+
+	*num = n;
+}
+LCRYPTO_ALIAS(CRYPTO_ctr128_encrypt_ctr32);
diff --git a/crypto/modes/gcm128.c b/crypto/modes/gcm128.c
new file mode 100644
index 0000000..cbda8ad
--- /dev/null
+++ b/crypto/modes/gcm128.c
@@ -0,0 +1,1355 @@
+/* $OpenBSD: gcm128.c,v 1.26 2023/08/10 07:18:43 jsing Exp $ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#define OPENSSL_FIPSAPI
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+#if defined(BSWAP4) && defined(__STRICT_ALIGNMENT)
+/* redefine, because alignment is ensured */
+#undef	GETU32
+#define	GETU32(p)	BSWAP4(*(const u32 *)(p))
+#endif
+
+#define	PACK(s)		((size_t)(s)<<(sizeof(size_t)*8-16))
+#define REDUCE1BIT(V)							\
+	do {								\
+		if (sizeof(size_t)==8) {				\
+			u64 T = U64(0xe100000000000000) & (0-(V.lo&1));	\
+			V.lo  = (V.hi<<63)|(V.lo>>1);			\
+			V.hi  = (V.hi>>1 )^T;				\
+		} else {						\
+			u32 T = 0xe1000000U & (0-(u32)(V.lo&1));	\
+			V.lo  = (V.hi<<63)|(V.lo>>1);			\
+			V.hi  = (V.hi>>1 )^((u64)T<<32);		\
+		}							\
+	} while(0)
+
+/*
+ * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
+ * never be set to 8. 8 is effectively reserved for testing purposes.
+ * TABLE_BITS>1 are lookup-table-driven implementations referred to as
+ * "Shoup's" in GCM specification. In other words OpenSSL does not cover
+ * whole spectrum of possible table driven implementations. Why? In
+ * non-"Shoup's" case memory access pattern is segmented in such manner,
+ * that it's trivial to see that cache timing information can reveal
+ * fair portion of intermediate hash value. Given that ciphertext is
+ * always available to attacker, it's possible for him to attempt to
+ * deduce secret parameter H and if successful, tamper with messages
+ * [which is nothing but trivial in CTR mode]. In "Shoup's" case it's
+ * not as trivial, but there is no reason to believe that it's resistant
+ * to cache-timing attack. And the thing about "8-bit" implementation is
+ * that it consumes 16 (sixteen) times more memory, 4KB per individual
+ * key + 1KB shared. Well, on pros side it should be twice as fast as
+ * "4-bit" version. And for gcc-generated x86[_64] code, "8-bit" version
+ * was observed to run ~75% faster, closer to 100% for commercial
+ * compilers... Yet "4-bit" procedure is preferred, because it's
+ * believed to provide better security-performance balance and adequate
+ * all-round performance. "All-round" refers to things like:
+ *
+ * - shorter setup time effectively improves overall timing for
+ *   handling short messages;
+ * - larger table allocation can become unbearable because of VM
+ *   subsystem penalties (for example on Windows large enough free
+ *   results in VM working set trimming, meaning that consequent
+ *   malloc would immediately incur working set expansion);
+ * - larger table has larger cache footprint, which can affect
+ *   performance of other code paths (not necessarily even from same
+ *   thread in Hyper-Threading world);
+ *
+ * Value of 1 is not appropriate for performance reasons.
+ */
+#if	TABLE_BITS==8
+
+static void
+gcm_init_8bit(u128 Htable[256], u64 H[2])
+{
+	int  i, j;
+	u128 V;
+
+	Htable[0].hi = 0;
+	Htable[0].lo = 0;
+	V.hi = H[0];
+	V.lo = H[1];
+
+	for (Htable[128] = V, i = 64; i > 0; i >>= 1) {
+		REDUCE1BIT(V);
+		Htable[i] = V;
+	}
+
+	for (i = 2; i < 256; i <<= 1) {
+		u128 *Hi = Htable + i, H0 = *Hi;
+		for (j = 1; j < i; ++j) {
+			Hi[j].hi = H0.hi ^ Htable[j].hi;
+			Hi[j].lo = H0.lo ^ Htable[j].lo;
+		}
+	}
+}
+
+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;
+	static const size_t rem_8bit[256] = {
+		PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246),
+		PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E),
+		PACK(0x0E10), PACK(0x0FD2), PACK(0x0D94), PACK(0x0C56),
+		PACK(0x0918), PACK(0x08DA), PACK(0x0A9C), PACK(0x0B5E),
+		PACK(0x1C20), PACK(0x1DE2), PACK(0x1FA4), PACK(0x1E66),
+		PACK(0x1B28), PACK(0x1AEA), PACK(0x18AC), PACK(0x196E),
+		PACK(0x1230), PACK(0x13F2), PACK(0x11B4), PACK(0x1076),
+		PACK(0x1538), PACK(0x14FA), PACK(0x16BC), PACK(0x177E),
+		PACK(0x3840), PACK(0x3982), PACK(0x3BC4), PACK(0x3A06),
+		PACK(0x3F48), PACK(0x3E8A), PACK(0x3CCC), PACK(0x3D0E),
+		PACK(0x3650), PACK(0x3792), PACK(0x35D4), PACK(0x3416),
+		PACK(0x3158), PACK(0x309A), PACK(0x32DC), PACK(0x331E),
+		PACK(0x2460), PACK(0x25A2), PACK(0x27E4), PACK(0x2626),
+		PACK(0x2368), PACK(0x22AA), PACK(0x20EC), PACK(0x212E),
+		PACK(0x2A70), PACK(0x2BB2), PACK(0x29F4), PACK(0x2836),
+		PACK(0x2D78), PACK(0x2CBA), PACK(0x2EFC), PACK(0x2F3E),
+		PACK(0x7080), PACK(0x7142), PACK(0x7304), PACK(0x72C6),
+		PACK(0x7788), PACK(0x764A), PACK(0x740C), PACK(0x75CE),
+		PACK(0x7E90), PACK(0x7F52), PACK(0x7D14), PACK(0x7CD6),
+		PACK(0x7998), PACK(0x785A), PACK(0x7A1C), PACK(0x7BDE),
+		PACK(0x6CA0), PACK(0x6D62), PACK(0x6F24), PACK(0x6EE6),
+		PACK(0x6BA8), PACK(0x6A6A), PACK(0x682C), PACK(0x69EE),
+		PACK(0x62B0), PACK(0x6372), PACK(0x6134), PACK(0x60F6),
+		PACK(0x65B8), PACK(0x647A), PACK(0x663C), PACK(0x67FE),
+		PACK(0x48C0), PACK(0x4902), PACK(0x4B44), PACK(0x4A86),
+		PACK(0x4FC8), PACK(0x4E0A), PACK(0x4C4C), PACK(0x4D8E),
+		PACK(0x46D0), PACK(0x4712), PACK(0x4554), PACK(0x4496),
+		PACK(0x41D8), PACK(0x401A), PACK(0x425C), PACK(0x439E),
+		PACK(0x54E0), PACK(0x5522), PACK(0x5764), PACK(0x56A6),
+		PACK(0x53E8), PACK(0x522A), PACK(0x506C), PACK(0x51AE),
+		PACK(0x5AF0), PACK(0x5B32), PACK(0x5974), PACK(0x58B6),
+		PACK(0x5DF8), PACK(0x5C3A), PACK(0x5E7C), PACK(0x5FBE),
+		PACK(0xE100), PACK(0xE0C2), PACK(0xE284), PACK(0xE346),
+		PACK(0xE608), PACK(0xE7CA), PACK(0xE58C), PACK(0xE44E),
+		PACK(0xEF10), PACK(0xEED2), PACK(0xEC94), PACK(0xED56),
+		PACK(0xE818), PACK(0xE9DA), PACK(0xEB9C), PACK(0xEA5E),
+		PACK(0xFD20), PACK(0xFCE2), PACK(0xFEA4), PACK(0xFF66),
+		PACK(0xFA28), PACK(0xFBEA), PACK(0xF9AC), PACK(0xF86E),
+		PACK(0xF330), PACK(0xF2F2), PACK(0xF0B4), PACK(0xF176),
+		PACK(0xF438), PACK(0xF5FA), PACK(0xF7BC), PACK(0xF67E),
+		PACK(0xD940), PACK(0xD882), PACK(0xDAC4), PACK(0xDB06),
+		PACK(0xDE48), PACK(0xDF8A), PACK(0xDDCC), PACK(0xDC0E),
+		PACK(0xD750), PACK(0xD692), PACK(0xD4D4), PACK(0xD516),
+		PACK(0xD058), PACK(0xD19A), PACK(0xD3DC), PACK(0xD21E),
+		PACK(0xC560), PACK(0xC4A2), PACK(0xC6E4), PACK(0xC726),
+		PACK(0xC268), PACK(0xC3AA), PACK(0xC1EC), PACK(0xC02E),
+		PACK(0xCB70), PACK(0xCAB2), PACK(0xC8F4), PACK(0xC936),
+		PACK(0xCC78), PACK(0xCDBA), PACK(0xCFFC), PACK(0xCE3E),
+		PACK(0x9180), PACK(0x9042), PACK(0x9204), PACK(0x93C6),
+		PACK(0x9688), PACK(0x974A), PACK(0x950C), PACK(0x94CE),
+		PACK(0x9F90), PACK(0x9E52), PACK(0x9C14), PACK(0x9DD6),
+		PACK(0x9898), PACK(0x995A), PACK(0x9B1C), PACK(0x9ADE),
+		PACK(0x8DA0), PACK(0x8C62), PACK(0x8E24), PACK(0x8FE6),
+		PACK(0x8AA8), PACK(0x8B6A), PACK(0x892C), PACK(0x88EE),
+		PACK(0x83B0), PACK(0x8272), PACK(0x8034), PACK(0x81F6),
+		PACK(0x84B8), PACK(0x857A), PACK(0x873C), PACK(0x86FE),
+		PACK(0xA9C0), PACK(0xA802), PACK(0xAA44), PACK(0xAB86),
+		PACK(0xAEC8), PACK(0xAF0A), PACK(0xAD4C), PACK(0xAC8E),
+		PACK(0xA7D0), PACK(0xA612), PACK(0xA454), PACK(0xA596),
+		PACK(0xA0D8), PACK(0xA11A), PACK(0xA35C), PACK(0xA29E),
+		PACK(0xB5E0), PACK(0xB422), PACK(0xB664), PACK(0xB7A6),
+		PACK(0xB2E8), PACK(0xB32A), PACK(0xB16C), PACK(0xB0AE),
+		PACK(0xBBF0), PACK(0xBA32), PACK(0xB874), PACK(0xB9B6),
+		PACK(0xBCF8), PACK(0xBD3A), PACK(0xBF7C), PACK(0xBEBE) };
+
+	while (1) {
+		Z.hi ^= Htable[n].hi;
+		Z.lo ^= Htable[n].lo;
+
+		if ((u8 *)Xi == xi)
+			break;
+
+		n = *(--xi);
+
+		rem = (size_t)Z.lo & 0xff;
+		Z.lo = (Z.hi << 56)|(Z.lo >> 8);
+		Z.hi = (Z.hi >> 8);
+#if SIZE_MAX == 0xffffffffffffffff
+		Z.hi ^= rem_8bit[rem];
+#else
+		Z.hi ^= (u64)rem_8bit[rem] << 32;
+#endif
+	}
+
+	Xi[0] = htobe64(Z.hi);
+	Xi[1] = htobe64(Z.lo);
+}
+#define GCM_MUL(ctx,Xi)   gcm_gmult_8bit(ctx->Xi.u,ctx->Htable)
+
+#elif	TABLE_BITS==4
+
+static void
+gcm_init_4bit(u128 Htable[16], u64 H[2])
+{
+	u128 V;
+#if defined(OPENSSL_SMALL_FOOTPRINT)
+	int  i;
+#endif
+
+	Htable[0].hi = 0;
+	Htable[0].lo = 0;
+	V.hi = H[0];
+	V.lo = H[1];
+
+#if defined(OPENSSL_SMALL_FOOTPRINT)
+	for (Htable[8] = V, i = 4; i > 0; i >>= 1) {
+		REDUCE1BIT(V);
+		Htable[i] = V;
+	}
+
+	for (i = 2; i < 16; i <<= 1) {
+		u128 *Hi = Htable + i;
+		int   j;
+		for (V = *Hi, j = 1; j < i; ++j) {
+			Hi[j].hi = V.hi ^ Htable[j].hi;
+			Hi[j].lo = V.lo ^ Htable[j].lo;
+		}
+	}
+#else
+	Htable[8] = V;
+	REDUCE1BIT(V);
+	Htable[4] = V;
+	REDUCE1BIT(V);
+	Htable[2] = V;
+	REDUCE1BIT(V);
+	Htable[1] = V;
+	Htable[3].hi = V.hi ^ Htable[2].hi, Htable[3].lo = V.lo ^ Htable[2].lo;
+	V = Htable[4];
+	Htable[5].hi = V.hi ^ Htable[1].hi, Htable[5].lo = V.lo ^ Htable[1].lo;
+	Htable[6].hi = V.hi ^ Htable[2].hi, Htable[6].lo = V.lo ^ Htable[2].lo;
+	Htable[7].hi = V.hi ^ Htable[3].hi, Htable[7].lo = V.lo ^ Htable[3].lo;
+	V = Htable[8];
+	Htable[9].hi = V.hi ^ Htable[1].hi, Htable[9].lo = V.lo ^ Htable[1].lo;
+	Htable[10].hi = V.hi ^ Htable[2].hi,
+	    Htable[10].lo = V.lo ^ Htable[2].lo;
+	Htable[11].hi = V.hi ^ Htable[3].hi,
+	    Htable[11].lo = V.lo ^ Htable[3].lo;
+	Htable[12].hi = V.hi ^ Htable[4].hi,
+	    Htable[12].lo = V.lo ^ Htable[4].lo;
+	Htable[13].hi = V.hi ^ Htable[5].hi,
+	    Htable[13].lo = V.lo ^ Htable[5].lo;
+	Htable[14].hi = V.hi ^ Htable[6].hi,
+	    Htable[14].lo = V.lo ^ Htable[6].lo;
+	Htable[15].hi = V.hi ^ Htable[7].hi,
+	    Htable[15].lo = V.lo ^ Htable[7].lo;
+#endif
+#if defined(GHASH_ASM) && (defined(__arm__) || defined(__arm))
+	/*
+	 * ARM assembler expects specific dword order in Htable.
+	 */
+	{
+		int j;
+#if BYTE_ORDER == LITTLE_ENDIAN
+		for (j = 0; j < 16; ++j) {
+			V = Htable[j];
+			Htable[j].hi = V.lo;
+			Htable[j].lo = V.hi;
+		}
+#else /* BIG_ENDIAN */
+		for (j = 0; j < 16; ++j) {
+			V = Htable[j];
+			Htable[j].hi = V.lo << 32|V.lo >> 32;
+			Htable[j].lo = V.hi << 32|V.hi >> 32;
+		}
+#endif
+	}
+#endif
+}
+
+#ifndef GHASH_ASM
+static const size_t rem_4bit[16] = {
+	PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460),
+	PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0),
+	PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560),
+	PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0) };
+
+static void
+gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
+{
+	u128 Z;
+	int cnt = 15;
+	size_t rem, nlo, nhi;
+
+	nlo = ((const u8 *)Xi)[15];
+	nhi = nlo >> 4;
+	nlo &= 0xf;
+
+	Z.hi = Htable[nlo].hi;
+	Z.lo = Htable[nlo].lo;
+
+	while (1) {
+		rem = (size_t)Z.lo & 0xf;
+		Z.lo = (Z.hi << 60)|(Z.lo >> 4);
+		Z.hi = (Z.hi >> 4);
+#if SIZE_MAX == 0xffffffffffffffff
+		Z.hi ^= rem_4bit[rem];
+#else
+		Z.hi ^= (u64)rem_4bit[rem] << 32;
+#endif
+		Z.hi ^= Htable[nhi].hi;
+		Z.lo ^= Htable[nhi].lo;
+
+		if (--cnt < 0)
+			break;
+
+		nlo = ((const u8 *)Xi)[cnt];
+		nhi = nlo >> 4;
+		nlo &= 0xf;
+
+		rem = (size_t)Z.lo & 0xf;
+		Z.lo = (Z.hi << 60)|(Z.lo >> 4);
+		Z.hi = (Z.hi >> 4);
+#if SIZE_MAX == 0xffffffffffffffff
+		Z.hi ^= rem_4bit[rem];
+#else
+		Z.hi ^= (u64)rem_4bit[rem] << 32;
+#endif
+		Z.hi ^= Htable[nlo].hi;
+		Z.lo ^= Htable[nlo].lo;
+	}
+
+	Xi[0] = htobe64(Z.hi);
+	Xi[1] = htobe64(Z.lo);
+}
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+/*
+ * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
+ * details... Compiler-generated code doesn't seem to give any
+ * performance improvement, at least not on x86[_64]. It's here
+ * mostly as reference and a placeholder for possible future
+ * non-trivial optimization[s]...
+ */
+static void
+gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16],
+    const u8 *inp, size_t len)
+{
+	u128 Z;
+	int cnt;
+	size_t rem, nlo, nhi;
+
+#if 1
+	do {
+		cnt = 15;
+		nlo = ((const u8 *)Xi)[15];
+		nlo ^= inp[15];
+		nhi = nlo >> 4;
+		nlo &= 0xf;
+
+		Z.hi = Htable[nlo].hi;
+		Z.lo = Htable[nlo].lo;
+
+		while (1) {
+			rem = (size_t)Z.lo & 0xf;
+			Z.lo = (Z.hi << 60)|(Z.lo >> 4);
+			Z.hi = (Z.hi >> 4);
+#if SIZE_MAX == 0xffffffffffffffff
+			Z.hi ^= rem_4bit[rem];
+#else
+			Z.hi ^= (u64)rem_4bit[rem] << 32;
+#endif
+			Z.hi ^= Htable[nhi].hi;
+			Z.lo ^= Htable[nhi].lo;
+
+			if (--cnt < 0)
+				break;
+
+			nlo = ((const u8 *)Xi)[cnt];
+			nlo ^= inp[cnt];
+			nhi = nlo >> 4;
+			nlo &= 0xf;
+
+			rem = (size_t)Z.lo & 0xf;
+			Z.lo = (Z.hi << 60)|(Z.lo >> 4);
+			Z.hi = (Z.hi >> 4);
+#if SIZE_MAX == 0xffffffffffffffff
+			Z.hi ^= rem_4bit[rem];
+#else
+			Z.hi ^= (u64)rem_4bit[rem] << 32;
+#endif
+			Z.hi ^= Htable[nlo].hi;
+			Z.lo ^= Htable[nlo].lo;
+		}
+#else
+    /*
+     * Extra 256+16 bytes per-key plus 512 bytes shared tables
+     * [should] give ~50% improvement... One could have PACK()-ed
+     * the rem_8bit even here, but the priority is to minimize
+     * cache footprint...
+     */
+	u128 Hshr4[16];	/* Htable shifted right by 4 bits */
+	u8 Hshl4[16];	/* Htable shifted left  by 4 bits */
+	static const unsigned short rem_8bit[256] = {
+		0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E,
+		0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E,
+		0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E,
+		0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E,
+		0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E,
+		0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E,
+		0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E,
+		0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E,
+		0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE,
+		0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE,
+		0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE,
+		0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE,
+		0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E,
+		0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E,
+		0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE,
+		0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE,
+		0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E,
+		0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E,
+		0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E,
+		0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E,
+		0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E,
+		0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E,
+		0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E,
+		0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E,
+		0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE,
+		0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE,
+		0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE,
+		0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE,
+		0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E,
+		0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E,
+		0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE,
+		0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE };
+    /*
+     * This pre-processing phase slows down procedure by approximately
+     * same time as it makes each loop spin faster. In other words
+     * single block performance is approximately same as straightforward
+     * "4-bit" implementation, and then it goes only faster...
+     */
+	for (cnt = 0; cnt < 16; ++cnt) {
+		Z.hi = Htable[cnt].hi;
+		Z.lo = Htable[cnt].lo;
+		Hshr4[cnt].lo = (Z.hi << 60)|(Z.lo >> 4);
+		Hshr4[cnt].hi = (Z.hi >> 4);
+		Hshl4[cnt] = (u8)(Z.lo << 4);
+	}
+
+	do {
+		for (Z.lo = 0, Z.hi = 0, cnt = 15; cnt; --cnt) {
+			nlo = ((const u8 *)Xi)[cnt];
+			nlo ^= inp[cnt];
+			nhi = nlo >> 4;
+			nlo &= 0xf;
+
+			Z.hi ^= Htable[nlo].hi;
+			Z.lo ^= Htable[nlo].lo;
+
+			rem = (size_t)Z.lo & 0xff;
+
+			Z.lo = (Z.hi << 56)|(Z.lo >> 8);
+			Z.hi = (Z.hi >> 8);
+
+			Z.hi ^= Hshr4[nhi].hi;
+			Z.lo ^= Hshr4[nhi].lo;
+			Z.hi ^= (u64)rem_8bit[rem ^ Hshl4[nhi]] << 48;
+		}
+
+		nlo = ((const u8 *)Xi)[0];
+		nlo ^= inp[0];
+		nhi = nlo >> 4;
+		nlo &= 0xf;
+
+		Z.hi ^= Htable[nlo].hi;
+		Z.lo ^= Htable[nlo].lo;
+
+		rem = (size_t)Z.lo & 0xf;
+
+		Z.lo = (Z.hi << 60)|(Z.lo >> 4);
+		Z.hi = (Z.hi >> 4);
+
+		Z.hi ^= Htable[nhi].hi;
+		Z.lo ^= Htable[nhi].lo;
+		Z.hi ^= ((u64)rem_8bit[rem << 4]) << 48;
+#endif
+
+		Xi[0] = htobe64(Z.hi);
+		Xi[1] = htobe64(Z.lo);
+	} while (inp += 16, len -= 16);
+}
+#endif
+#else
+void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+    size_t len);
+#endif
+
+#define GCM_MUL(ctx,Xi)   gcm_gmult_4bit(ctx->Xi.u,ctx->Htable)
+#if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT)
+#define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len)
+/* GHASH_CHUNK is "stride parameter" missioned to mitigate cache
+ * trashing effect. In other words idea is to hash data while it's
+ * still in L1 cache after encryption pass... */
+#define GHASH_CHUNK       (3*1024)
+#endif
+
+#else	/* TABLE_BITS */
+
+static void
+gcm_gmult_1bit(u64 Xi[2], const u64 H[2])
+{
+	u128 V, Z = { 0,0 };
+	long X;
+	int i, j;
+	const long *xi = (const long *)Xi;
+
+	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 BYTE_ORDER == LITTLE_ENDIAN
+#if SIZE_MAX == 0xffffffffffffffff
+#ifdef BSWAP8
+		X = (long)(BSWAP8(xi[j]));
+#else
+		const u8 *p = (const u8 *)(xi + j);
+		X = (long)((u64)GETU32(p) << 32|GETU32(p + 4));
+#endif
+#else
+		const u8 *p = (const u8 *)(xi + j);
+		X = (long)GETU32(p);
+#endif
+#else /* BIG_ENDIAN */
+		X = xi[j];
+#endif
+
+		for (i = 0; i < 8*sizeof(long); ++i, X <<= 1) {
+			u64 M = (u64)(X >> (8*sizeof(long) - 1));
+			Z.hi ^= V.hi & M;
+			Z.lo ^= V.lo & M;
+
+			REDUCE1BIT(V);
+		}
+	}
+
+	Xi[0] = htobe64(Z.hi);
+	Xi[1] = htobe64(Z.lo);
+}
+#define GCM_MUL(ctx,Xi)	  gcm_gmult_1bit(ctx->Xi.u,ctx->H.u)
+
+#endif
+
+#if	defined(GHASH_ASM) &&						\
+	(defined(__i386)	|| defined(__i386__)	||		\
+	 defined(__x86_64)	|| defined(__x86_64__)	||		\
+	 defined(_M_IX86)	|| defined(_M_AMD64)	|| defined(_M_X64))
+#include "x86_arch.h"
+#endif
+
+#if	TABLE_BITS==4 && defined(GHASH_ASM)
+# if	(defined(__i386)	|| defined(__i386__)	||		\
+	 defined(__x86_64)	|| defined(__x86_64__)	||		\
+	 defined(_M_IX86)	|| defined(_M_AMD64)	|| defined(_M_X64))
+#  define GHASH_ASM_X86_OR_64
+#  define GCM_FUNCREF_4BIT
+
+void gcm_init_clmul(u128 Htable[16], const u64 Xi[2]);
+void gcm_gmult_clmul(u64 Xi[2], const u128 Htable[16]);
+void gcm_ghash_clmul(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+    size_t len);
+
+#  if	defined(__i386) || defined(__i386__) || defined(_M_IX86)
+#   define GHASH_ASM_X86
+void gcm_gmult_4bit_mmx(u64 Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit_mmx(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+    size_t len);
+
+void gcm_gmult_4bit_x86(u64 Xi[2], const u128 Htable[16]);
+void gcm_ghash_4bit_x86(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+    size_t len);
+#  endif
+# elif defined(__arm__) || defined(__arm)
+#  include "arm_arch.h"
+#  if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+#   define GHASH_ASM_ARM
+#   define GCM_FUNCREF_4BIT
+void gcm_gmult_neon(u64 Xi[2], const u128 Htable[16]);
+void gcm_ghash_neon(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+    size_t len);
+#  endif
+# endif
+#endif
+
+#ifdef GCM_FUNCREF_4BIT
+# undef  GCM_MUL
+# define GCM_MUL(ctx,Xi)	(*gcm_gmult_p)(ctx->Xi.u,ctx->Htable)
+# ifdef GHASH
+#  undef  GHASH
+#  define GHASH(ctx,in,len)	(*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len)
+# endif
+#endif
+
+void
+CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
+{
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->block = block;
+	ctx->key = key;
+
+	(*block)(ctx->H.c, ctx->H.c, key);
+
+	/* H is stored in host byte order */
+	ctx->H.u[0] = be64toh(ctx->H.u[0]);
+	ctx->H.u[1] = be64toh(ctx->H.u[1]);
+
+#if	TABLE_BITS==8
+	gcm_init_8bit(ctx->Htable, ctx->H.u);
+#elif	TABLE_BITS==4
+# if	defined(GHASH_ASM_X86_OR_64)
+#  if	!defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
+	/* check FXSR and PCLMULQDQ bits */
+	if ((OPENSSL_cpu_caps() & (CPUCAP_MASK_FXSR | CPUCAP_MASK_PCLMUL)) ==
+	    (CPUCAP_MASK_FXSR | CPUCAP_MASK_PCLMUL)) {
+		gcm_init_clmul(ctx->Htable, ctx->H.u);
+		ctx->gmult = gcm_gmult_clmul;
+		ctx->ghash = gcm_ghash_clmul;
+		return;
+	}
+#  endif
+	gcm_init_4bit(ctx->Htable, ctx->H.u);
+#  if	defined(GHASH_ASM_X86)			/* x86 only */
+#   if	defined(OPENSSL_IA32_SSE2)
+	if (OPENSSL_cpu_caps() & CPUCAP_MASK_SSE) {	/* check SSE bit */
+#   else
+	if (OPENSSL_cpu_caps() & CPUCAP_MASK_MMX) {	/* check MMX bit */
+#   endif
+		ctx->gmult = gcm_gmult_4bit_mmx;
+		ctx->ghash = gcm_ghash_4bit_mmx;
+	} else {
+		ctx->gmult = gcm_gmult_4bit_x86;
+		ctx->ghash = gcm_ghash_4bit_x86;
+	}
+#  else
+	ctx->gmult = gcm_gmult_4bit;
+	ctx->ghash = gcm_ghash_4bit;
+#  endif
+# elif	defined(GHASH_ASM_ARM)
+	if (OPENSSL_armcap_P & ARMV7_NEON) {
+		ctx->gmult = gcm_gmult_neon;
+		ctx->ghash = gcm_ghash_neon;
+	} else {
+		gcm_init_4bit(ctx->Htable, ctx->H.u);
+		ctx->gmult = gcm_gmult_4bit;
+		ctx->ghash = gcm_ghash_4bit;
+	}
+# else
+	gcm_init_4bit(ctx->Htable, ctx->H.u);
+# endif
+#endif
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_init);
+
+void
+CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const unsigned char *iv, size_t len)
+{
+	unsigned int ctr;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+#endif
+
+	ctx->Yi.u[0] = 0;
+	ctx->Yi.u[1] = 0;
+	ctx->Xi.u[0] = 0;
+	ctx->Xi.u[1] = 0;
+	ctx->len.u[0] = 0;	/* AAD length */
+	ctx->len.u[1] = 0;	/* message length */
+	ctx->ares = 0;
+	ctx->mres = 0;
+
+	if (len == 12) {
+		memcpy(ctx->Yi.c, iv, 12);
+		ctx->Yi.c[15] = 1;
+		ctr = 1;
+	} else {
+		size_t i;
+		u64 len0 = len;
+
+		while (len >= 16) {
+			for (i = 0; i < 16; ++i)
+				ctx->Yi.c[i] ^= iv[i];
+			GCM_MUL(ctx, Yi);
+			iv += 16;
+			len -= 16;
+		}
+		if (len) {
+			for (i = 0; i < len; ++i)
+				ctx->Yi.c[i] ^= iv[i];
+			GCM_MUL(ctx, Yi);
+		}
+		len0 <<= 3;
+		ctx->Yi.u[1] ^= htobe64(len0);
+
+		GCM_MUL(ctx, Yi);
+
+		ctr = be32toh(ctx->Yi.d[3]);
+	}
+
+	(*ctx->block)(ctx->Yi.c, ctx->EK0.c, ctx->key);
+	++ctr;
+	ctx->Yi.d[3] = htobe32(ctr);
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_setiv);
+
+int
+CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, size_t len)
+{
+	size_t i;
+	unsigned int n;
+	u64 alen = ctx->len.u[0];
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+# ifdef GHASH
+	void (*gcm_ghash_p)(u64 Xi[2], const u128 Htable[16],
+	    const u8 *inp, size_t len) = ctx->ghash;
+# endif
+#endif
+
+	if (ctx->len.u[1])
+		return -2;
+
+	alen += len;
+	if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
+		return -1;
+	ctx->len.u[0] = alen;
+
+	n = ctx->ares;
+	if (n) {
+		while (n && len) {
+			ctx->Xi.c[n] ^= *(aad++);
+			--len;
+			n = (n + 1) % 16;
+		}
+		if (n == 0)
+			GCM_MUL(ctx, Xi);
+		else {
+			ctx->ares = n;
+			return 0;
+		}
+	}
+
+#ifdef GHASH
+	if ((i = (len & (size_t)-16))) {
+		GHASH(ctx, aad, i);
+		aad += i;
+		len -= i;
+	}
+#else
+	while (len >= 16) {
+		for (i = 0; i < 16; ++i)
+			ctx->Xi.c[i] ^= aad[i];
+		GCM_MUL(ctx, Xi);
+		aad += 16;
+		len -= 16;
+	}
+#endif
+	if (len) {
+		n = (unsigned int)len;
+		for (i = 0; i < len; ++i)
+			ctx->Xi.c[i] ^= aad[i];
+	}
+
+	ctx->ares = n;
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_aad);
+
+int
+CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
+    const unsigned char *in, unsigned char *out,
+    size_t len)
+{
+	unsigned int n, ctr;
+	size_t i;
+	u64 mlen = ctx->len.u[1];
+	block128_f block = ctx->block;
+	void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+# ifdef GHASH
+	void (*gcm_ghash_p)(u64 Xi[2], const u128 Htable[16],
+	    const u8 *inp, size_t len) = ctx->ghash;
+# endif
+#endif
+
+	mlen += len;
+	if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
+		return -1;
+	ctx->len.u[1] = mlen;
+
+	if (ctx->ares) {
+		/* First call to encrypt finalizes GHASH(AAD) */
+		GCM_MUL(ctx, Xi);
+		ctx->ares = 0;
+	}
+
+	ctr = be32toh(ctx->Yi.d[3]);
+
+	n = ctx->mres;
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (16 % sizeof(size_t) == 0)
+		do {	/* always true actually */
+			if (n) {
+				while (n && len) {
+					ctx->Xi.c[n] ^= *(out++) = *(in++) ^
+					    ctx->EKi.c[n];
+					--len;
+					n = (n + 1) % 16;
+				}
+				if (n == 0)
+					GCM_MUL(ctx, Xi);
+				else {
+					ctx->mres = n;
+					return 0;
+				}
+			}
+#ifdef __STRICT_ALIGNMENT
+			if (((size_t)in|(size_t)out) % sizeof(size_t) != 0)
+				break;
+#endif
+#if defined(GHASH) && defined(GHASH_CHUNK)
+			while (len >= GHASH_CHUNK) {
+				size_t j = GHASH_CHUNK;
+
+				while (j) {
+					size_t *out_t = (size_t *)out;
+					const size_t *in_t = (const size_t *)in;
+
+					(*block)(ctx->Yi.c, ctx->EKi.c, key);
+					++ctr;
+					ctx->Yi.d[3] = htobe32(ctr);
+
+					for (i = 0; i < 16/sizeof(size_t); ++i)
+						out_t[i] = in_t[i] ^
+						    ctx->EKi.t[i];
+					out += 16;
+					in += 16;
+					j -= 16;
+				}
+				GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK);
+				len -= GHASH_CHUNK;
+			}
+			if ((i = (len & (size_t)-16))) {
+				size_t j = i;
+
+				while (len >= 16) {
+					size_t *out_t = (size_t *)out;
+					const size_t *in_t = (const size_t *)in;
+
+					(*block)(ctx->Yi.c, ctx->EKi.c, key);
+					++ctr;
+					ctx->Yi.d[3] = htobe32(ctr);
+
+					for (i = 0; i < 16/sizeof(size_t); ++i)
+						out_t[i] = in_t[i] ^
+						    ctx->EKi.t[i];
+					out += 16;
+					in += 16;
+					len -= 16;
+				}
+				GHASH(ctx, out - j, j);
+			}
+#else
+			while (len >= 16) {
+				size_t *out_t = (size_t *)out;
+				const size_t *in_t = (const size_t *)in;
+
+				(*block)(ctx->Yi.c, ctx->EKi.c, key);
+				++ctr;
+				ctx->Yi.d[3] = htobe32(ctr);
+
+				for (i = 0; i < 16/sizeof(size_t); ++i)
+					ctx->Xi.t[i] ^=
+					    out_t[i] = in_t[i] ^ ctx->EKi.t[i];
+				GCM_MUL(ctx, Xi);
+				out += 16;
+				in += 16;
+				len -= 16;
+			}
+#endif
+			if (len) {
+				(*block)(ctx->Yi.c, ctx->EKi.c, key);
+				++ctr;
+				ctx->Yi.d[3] = htobe32(ctr);
+
+				while (len--) {
+					ctx->Xi.c[n] ^= out[n] = in[n] ^
+					    ctx->EKi.c[n];
+					++n;
+				}
+			}
+
+			ctx->mres = n;
+			return 0;
+		} while (0);
+#endif
+	for (i = 0; i < len; ++i) {
+		if (n == 0) {
+			(*block)(ctx->Yi.c, ctx->EKi.c, key);
+			++ctr;
+			ctx->Yi.d[3] = htobe32(ctr);
+		}
+		ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n];
+		n = (n + 1) % 16;
+		if (n == 0)
+			GCM_MUL(ctx, Xi);
+	}
+
+	ctx->mres = n;
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_encrypt);
+
+int
+CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
+    const unsigned char *in, unsigned char *out,
+    size_t len)
+{
+	unsigned int n, ctr;
+	size_t i;
+	u64 mlen = ctx->len.u[1];
+	block128_f block = ctx->block;
+	void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+# ifdef GHASH
+	void (*gcm_ghash_p)(u64 Xi[2], const u128 Htable[16],
+	    const u8 *inp, size_t len) = ctx->ghash;
+# endif
+#endif
+
+	mlen += len;
+	if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
+		return -1;
+	ctx->len.u[1] = mlen;
+
+	if (ctx->ares) {
+		/* First call to decrypt finalizes GHASH(AAD) */
+		GCM_MUL(ctx, Xi);
+		ctx->ares = 0;
+	}
+
+	ctr = be32toh(ctx->Yi.d[3]);
+
+	n = ctx->mres;
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (16 % sizeof(size_t) == 0)
+		do {	/* always true actually */
+			if (n) {
+				while (n && len) {
+					u8 c = *(in++);
+					*(out++) = c ^ ctx->EKi.c[n];
+					ctx->Xi.c[n] ^= c;
+					--len;
+					n = (n + 1) % 16;
+				}
+				if (n == 0)
+					GCM_MUL(ctx, Xi);
+				else {
+					ctx->mres = n;
+					return 0;
+				}
+			}
+#ifdef __STRICT_ALIGNMENT
+			if (((size_t)in|(size_t)out) % sizeof(size_t) != 0)
+				break;
+#endif
+#if defined(GHASH) && defined(GHASH_CHUNK)
+			while (len >= GHASH_CHUNK) {
+				size_t j = GHASH_CHUNK;
+
+				GHASH(ctx, in, GHASH_CHUNK);
+				while (j) {
+					size_t *out_t = (size_t *)out;
+					const size_t *in_t = (const size_t *)in;
+
+					(*block)(ctx->Yi.c, ctx->EKi.c, key);
+					++ctr;
+					ctx->Yi.d[3] = htobe32(ctr);
+
+					for (i = 0; i < 16/sizeof(size_t); ++i)
+						out_t[i] = in_t[i] ^
+						    ctx->EKi.t[i];
+					out += 16;
+					in += 16;
+					j -= 16;
+				}
+				len -= GHASH_CHUNK;
+			}
+			if ((i = (len & (size_t)-16))) {
+				GHASH(ctx, in, i);
+				while (len >= 16) {
+					size_t *out_t = (size_t *)out;
+					const size_t *in_t = (const size_t *)in;
+
+					(*block)(ctx->Yi.c, ctx->EKi.c, key);
+					++ctr;
+					ctx->Yi.d[3] = htobe32(ctr);
+
+					for (i = 0; i < 16/sizeof(size_t); ++i)
+						out_t[i] = in_t[i] ^
+						    ctx->EKi.t[i];
+					out += 16;
+					in += 16;
+					len -= 16;
+				}
+			}
+#else
+			while (len >= 16) {
+				size_t *out_t = (size_t *)out;
+				const size_t *in_t = (const size_t *)in;
+
+				(*block)(ctx->Yi.c, ctx->EKi.c, key);
+				++ctr;
+				ctx->Yi.d[3] = htobe32(ctr);
+
+				for (i = 0; i < 16/sizeof(size_t); ++i) {
+					size_t c = in[i];
+					out[i] = c ^ ctx->EKi.t[i];
+					ctx->Xi.t[i] ^= c;
+				}
+				GCM_MUL(ctx, Xi);
+				out += 16;
+				in += 16;
+				len -= 16;
+			}
+#endif
+			if (len) {
+				(*block)(ctx->Yi.c, ctx->EKi.c, key);
+				++ctr;
+				ctx->Yi.d[3] = htobe32(ctr);
+
+				while (len--) {
+					u8 c = in[n];
+					ctx->Xi.c[n] ^= c;
+					out[n] = c ^ ctx->EKi.c[n];
+					++n;
+				}
+			}
+
+			ctx->mres = n;
+			return 0;
+		} while (0);
+#endif
+	for (i = 0; i < len; ++i) {
+		u8 c;
+		if (n == 0) {
+			(*block)(ctx->Yi.c, ctx->EKi.c, key);
+			++ctr;
+			ctx->Yi.d[3] = htobe32(ctr);
+		}
+		c = in[i];
+		out[i] = c ^ ctx->EKi.c[n];
+		ctx->Xi.c[n] ^= c;
+		n = (n + 1) % 16;
+		if (n == 0)
+			GCM_MUL(ctx, Xi);
+	}
+
+	ctx->mres = n;
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_decrypt);
+
+int
+CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
+    const unsigned char *in, unsigned char *out,
+    size_t len, ctr128_f stream)
+{
+	unsigned int n, ctr;
+	size_t i;
+	u64 mlen = ctx->len.u[1];
+	void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+# ifdef GHASH
+	void (*gcm_ghash_p)(u64 Xi[2], const u128 Htable[16],
+	    const u8 *inp, size_t len) = ctx->ghash;
+# endif
+#endif
+
+	mlen += len;
+	if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
+		return -1;
+	ctx->len.u[1] = mlen;
+
+	if (ctx->ares) {
+		/* First call to encrypt finalizes GHASH(AAD) */
+		GCM_MUL(ctx, Xi);
+		ctx->ares = 0;
+	}
+
+	ctr = be32toh(ctx->Yi.d[3]);
+
+	n = ctx->mres;
+	if (n) {
+		while (n && len) {
+			ctx->Xi.c[n] ^= *(out++) = *(in++) ^ ctx->EKi.c[n];
+			--len;
+			n = (n + 1) % 16;
+		}
+		if (n == 0)
+			GCM_MUL(ctx, Xi);
+		else {
+			ctx->mres = n;
+			return 0;
+		}
+	}
+#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
+	while (len >= GHASH_CHUNK) {
+		(*stream)(in, out, GHASH_CHUNK/16, key, ctx->Yi.c);
+		ctr += GHASH_CHUNK/16;
+		ctx->Yi.d[3] = htobe32(ctr);
+		GHASH(ctx, out, GHASH_CHUNK);
+		out += GHASH_CHUNK;
+		in += GHASH_CHUNK;
+		len -= GHASH_CHUNK;
+	}
+#endif
+	if ((i = (len & (size_t)-16))) {
+		size_t j = i/16;
+
+		(*stream)(in, out, j, key, ctx->Yi.c);
+		ctr += (unsigned int)j;
+		ctx->Yi.d[3] = htobe32(ctr);
+		in += i;
+		len -= i;
+#if defined(GHASH)
+		GHASH(ctx, out, i);
+		out += i;
+#else
+		while (j--) {
+			for (i = 0; i < 16; ++i)
+				ctx->Xi.c[i] ^= out[i];
+			GCM_MUL(ctx, Xi);
+			out += 16;
+		}
+#endif
+	}
+	if (len) {
+		(*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
+		++ctr;
+		ctx->Yi.d[3] = htobe32(ctr);
+		while (len--) {
+			ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
+			++n;
+		}
+	}
+
+	ctx->mres = n;
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_encrypt_ctr32);
+
+int
+CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
+    const unsigned char *in, unsigned char *out,
+    size_t len, ctr128_f stream)
+{
+	unsigned int n, ctr;
+	size_t i;
+	u64 mlen = ctx->len.u[1];
+	void *key = ctx->key;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+# ifdef GHASH
+	void (*gcm_ghash_p)(u64 Xi[2], const u128 Htable[16],
+	    const u8 *inp, size_t len) = ctx->ghash;
+# endif
+#endif
+
+	mlen += len;
+	if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
+		return -1;
+	ctx->len.u[1] = mlen;
+
+	if (ctx->ares) {
+		/* First call to decrypt finalizes GHASH(AAD) */
+		GCM_MUL(ctx, Xi);
+		ctx->ares = 0;
+	}
+
+	ctr = be32toh(ctx->Yi.d[3]);
+
+	n = ctx->mres;
+	if (n) {
+		while (n && len) {
+			u8 c = *(in++);
+			*(out++) = c ^ ctx->EKi.c[n];
+			ctx->Xi.c[n] ^= c;
+			--len;
+			n = (n + 1) % 16;
+		}
+		if (n == 0)
+			GCM_MUL(ctx, Xi);
+		else {
+			ctx->mres = n;
+			return 0;
+		}
+	}
+#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
+	while (len >= GHASH_CHUNK) {
+		GHASH(ctx, in, GHASH_CHUNK);
+		(*stream)(in, out, GHASH_CHUNK/16, key, ctx->Yi.c);
+		ctr += GHASH_CHUNK/16;
+		ctx->Yi.d[3] = htobe32(ctr);
+		out += GHASH_CHUNK;
+		in += GHASH_CHUNK;
+		len -= GHASH_CHUNK;
+	}
+#endif
+	if ((i = (len & (size_t)-16))) {
+		size_t j = i/16;
+
+#if defined(GHASH)
+		GHASH(ctx, in, i);
+#else
+		while (j--) {
+			size_t k;
+			for (k = 0; k < 16; ++k)
+				ctx->Xi.c[k] ^= in[k];
+			GCM_MUL(ctx, Xi);
+			in += 16;
+		}
+		j = i/16;
+		in -= i;
+#endif
+		(*stream)(in, out, j, key, ctx->Yi.c);
+		ctr += (unsigned int)j;
+		ctx->Yi.d[3] = htobe32(ctr);
+		out += i;
+		in += i;
+		len -= i;
+	}
+	if (len) {
+		(*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
+		++ctr;
+		ctx->Yi.d[3] = htobe32(ctr);
+		while (len--) {
+			u8 c = in[n];
+			ctx->Xi.c[n] ^= c;
+			out[n] = c ^ ctx->EKi.c[n];
+			++n;
+		}
+	}
+
+	ctx->mres = n;
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_decrypt_ctr32);
+
+int
+CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag,
+    size_t len)
+{
+	u64 alen = ctx->len.u[0] << 3;
+	u64 clen = ctx->len.u[1] << 3;
+#ifdef GCM_FUNCREF_4BIT
+	void (*gcm_gmult_p)(u64 Xi[2], const u128 Htable[16]) = ctx->gmult;
+#endif
+
+	if (ctx->mres || ctx->ares)
+		GCM_MUL(ctx, Xi);
+
+	ctx->Xi.u[0] ^= htobe64(alen);
+	ctx->Xi.u[1] ^= htobe64(clen);
+	GCM_MUL(ctx, Xi);
+
+	ctx->Xi.u[0] ^= ctx->EK0.u[0];
+	ctx->Xi.u[1] ^= ctx->EK0.u[1];
+
+	if (tag && len <= sizeof(ctx->Xi))
+		return memcmp(ctx->Xi.c, tag, len);
+	else
+		return -1;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_finish);
+
+void
+CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
+{
+	CRYPTO_gcm128_finish(ctx, NULL, 0);
+	memcpy(tag, ctx->Xi.c,
+	    len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_tag);
+
+GCM128_CONTEXT *
+CRYPTO_gcm128_new(void *key, block128_f block)
+{
+	GCM128_CONTEXT *ret;
+
+	if ((ret = malloc(sizeof(GCM128_CONTEXT))))
+		CRYPTO_gcm128_init(ret, key, block);
+
+	return ret;
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_new);
+
+void
+CRYPTO_gcm128_release(GCM128_CONTEXT *ctx)
+{
+	freezero(ctx, sizeof(*ctx));
+}
+LCRYPTO_ALIAS(CRYPTO_gcm128_release);
diff --git a/crypto/modes/ghash-elf-armv4.S b/crypto/modes/ghash-elf-armv4.S
new file mode 100644
index 0000000..af42593
--- /dev/null
+++ b/crypto/modes/ghash-elf-armv4.S
@@ -0,0 +1,412 @@
+#include "arm_arch.h"
+
+.text
+.syntax	unified
+.code	32
+
+.type	rem_4bit,%object
+.align	5
+rem_4bit:
+.short	0x0000,0x1C20,0x3840,0x2460
+.short	0x7080,0x6CA0,0x48C0,0x54E0
+.short	0xE100,0xFD20,0xD940,0xC560
+.short	0x9180,0x8DA0,0xA9C0,0xB5E0
+.size	rem_4bit,.-rem_4bit
+
+.type	rem_4bit_get,%function
+rem_4bit_get:
+	sub	r2,pc,#8
+	sub	r2,r2,#32	@ &rem_4bit
+	b	.Lrem_4bit_got
+	nop
+.size	rem_4bit_get,.-rem_4bit_get
+
+.global	gcm_ghash_4bit
+.type	gcm_ghash_4bit,%function
+gcm_ghash_4bit:
+	sub	r12,pc,#8
+	add	r3,r2,r3		@ r3 to point at the end
+	stmdb	sp!,{r3-r11,lr}		@ save r3/end too
+	sub	r12,r12,#48		@ &rem_4bit
+
+	ldmia	r12,{r4-r11}		@ copy rem_4bit ...
+	stmdb	sp!,{r4-r11}		@ ... to stack
+
+	ldrb	r12,[r2,#15]
+	ldrb	r14,[r0,#15]
+.Louter:
+	eor	r12,r12,r14
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	mov	r3,#14
+
+	add	r7,r1,r12,lsl#4
+	ldmia	r7,{r4-r7}	@ load Htbl[nlo]
+	add	r11,r1,r14
+	ldrb	r12,[r2,#14]
+
+	and	r14,r4,#0xf		@ rem
+	ldmia	r11,{r8-r11}	@ load Htbl[nhi]
+	add	r14,r14,r14
+	eor	r4,r8,r4,lsr#4
+	ldrh	r8,[sp,r14]		@ rem_4bit[rem]
+	eor	r4,r4,r5,lsl#28
+	ldrb	r14,[r0,#14]
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	eor	r12,r12,r14
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	eor	r7,r7,r8,lsl#16
+
+.Linner:
+	add	r11,r1,r12,lsl#4
+	and	r12,r4,#0xf		@ rem
+	subs	r3,r3,#1
+	add	r12,r12,r12
+	ldmia	r11,{r8-r11}	@ load Htbl[nlo]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	ldrh	r8,[sp,r12]		@ rem_4bit[rem]
+	eor	r6,r10,r6,lsr#4
+	ldrbpl	r12,[r2,r3]
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	add	r14,r14,r14
+	ldmia	r11,{r8-r11}	@ load Htbl[nhi]
+	eor	r4,r8,r4,lsr#4
+	ldrbpl	r8,[r0,r3]
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	ldrh	r9,[sp,r14]
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eorpl	r12,r12,r8
+	eor	r7,r11,r7,lsr#4
+	andpl	r14,r12,#0xf0
+	andpl	r12,r12,#0x0f
+	eor	r7,r7,r9,lsl#16	@ ^= rem_4bit[rem]
+	bpl	.Linner
+
+	ldr	r3,[sp,#32]		@ re-load r3/end
+	add	r2,r2,#16
+	mov	r14,r4
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r4,r4
+	str	r4,[r0,#12]
+#elif defined(__ARMEB__)
+	str	r4,[r0,#12]
+#else
+	mov	r9,r4,lsr#8
+	strb	r4,[r0,#12+3]
+	mov	r10,r4,lsr#16
+	strb	r9,[r0,#12+2]
+	mov	r11,r4,lsr#24
+	strb	r10,[r0,#12+1]
+	strb	r11,[r0,#12]
+#endif
+	cmp	r2,r3
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r5,r5
+	str	r5,[r0,#8]
+#elif defined(__ARMEB__)
+	str	r5,[r0,#8]
+#else
+	mov	r9,r5,lsr#8
+	strb	r5,[r0,#8+3]
+	mov	r10,r5,lsr#16
+	strb	r9,[r0,#8+2]
+	mov	r11,r5,lsr#24
+	strb	r10,[r0,#8+1]
+	strb	r11,[r0,#8]
+#endif
+	ldrbne	r12,[r2,#15]
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r6,r6
+	str	r6,[r0,#4]
+#elif defined(__ARMEB__)
+	str	r6,[r0,#4]
+#else
+	mov	r9,r6,lsr#8
+	strb	r6,[r0,#4+3]
+	mov	r10,r6,lsr#16
+	strb	r9,[r0,#4+2]
+	mov	r11,r6,lsr#24
+	strb	r10,[r0,#4+1]
+	strb	r11,[r0,#4]
+#endif
+	
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r7,r7
+	str	r7,[r0,#0]
+#elif defined(__ARMEB__)
+	str	r7,[r0,#0]
+#else
+	mov	r9,r7,lsr#8
+	strb	r7,[r0,#0+3]
+	mov	r10,r7,lsr#16
+	strb	r9,[r0,#0+2]
+	mov	r11,r7,lsr#24
+	strb	r10,[r0,#0+1]
+	strb	r11,[r0,#0]
+#endif
+	
+	bne	.Louter
+
+	add	sp,sp,#36
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	gcm_ghash_4bit,.-gcm_ghash_4bit
+
+.global	gcm_gmult_4bit
+.type	gcm_gmult_4bit,%function
+gcm_gmult_4bit:
+	stmdb	sp!,{r4-r11,lr}
+	ldrb	r12,[r0,#15]
+	b	rem_4bit_get
+.Lrem_4bit_got:
+	and	r14,r12,#0xf0
+	and	r12,r12,#0x0f
+	mov	r3,#14
+
+	add	r7,r1,r12,lsl#4
+	ldmia	r7,{r4-r7}	@ load Htbl[nlo]
+	ldrb	r12,[r0,#14]
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	ldmia	r11,{r8-r11}	@ load Htbl[nhi]
+	add	r14,r14,r14
+	eor	r4,r8,r4,lsr#4
+	ldrh	r8,[r2,r14]	@ rem_4bit[rem]
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	and	r14,r12,#0xf0
+	eor	r7,r7,r8,lsl#16
+	and	r12,r12,#0x0f
+
+.Loop:
+	add	r11,r1,r12,lsl#4
+	and	r12,r4,#0xf		@ rem
+	subs	r3,r3,#1
+	add	r12,r12,r12
+	ldmia	r11,{r8-r11}	@ load Htbl[nlo]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	eor	r5,r5,r6,lsl#28
+	ldrh	r8,[r2,r12]	@ rem_4bit[rem]
+	eor	r6,r10,r6,lsr#4
+	ldrbpl	r12,[r0,r3]
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+
+	add	r11,r1,r14
+	and	r14,r4,#0xf		@ rem
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	add	r14,r14,r14
+	ldmia	r11,{r8-r11}	@ load Htbl[nhi]
+	eor	r4,r8,r4,lsr#4
+	eor	r4,r4,r5,lsl#28
+	eor	r5,r9,r5,lsr#4
+	ldrh	r8,[r2,r14]	@ rem_4bit[rem]
+	eor	r5,r5,r6,lsl#28
+	eor	r6,r10,r6,lsr#4
+	eor	r6,r6,r7,lsl#28
+	eor	r7,r11,r7,lsr#4
+	andpl	r14,r12,#0xf0
+	andpl	r12,r12,#0x0f
+	eor	r7,r7,r8,lsl#16	@ ^= rem_4bit[rem]
+	bpl	.Loop
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r4,r4
+	str	r4,[r0,#12]
+#elif defined(__ARMEB__)
+	str	r4,[r0,#12]
+#else
+	mov	r9,r4,lsr#8
+	strb	r4,[r0,#12+3]
+	mov	r10,r4,lsr#16
+	strb	r9,[r0,#12+2]
+	mov	r11,r4,lsr#24
+	strb	r10,[r0,#12+1]
+	strb	r11,[r0,#12]
+#endif
+	
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r5,r5
+	str	r5,[r0,#8]
+#elif defined(__ARMEB__)
+	str	r5,[r0,#8]
+#else
+	mov	r9,r5,lsr#8
+	strb	r5,[r0,#8+3]
+	mov	r10,r5,lsr#16
+	strb	r9,[r0,#8+2]
+	mov	r11,r5,lsr#24
+	strb	r10,[r0,#8+1]
+	strb	r11,[r0,#8]
+#endif
+	
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r6,r6
+	str	r6,[r0,#4]
+#elif defined(__ARMEB__)
+	str	r6,[r0,#4]
+#else
+	mov	r9,r6,lsr#8
+	strb	r6,[r0,#4+3]
+	mov	r10,r6,lsr#16
+	strb	r9,[r0,#4+2]
+	mov	r11,r6,lsr#24
+	strb	r10,[r0,#4+1]
+	strb	r11,[r0,#4]
+#endif
+	
+#if __ARM_ARCH__>=7 && defined(__ARMEL__)
+	rev	r7,r7
+	str	r7,[r0,#0]
+#elif defined(__ARMEB__)
+	str	r7,[r0,#0]
+#else
+	mov	r9,r7,lsr#8
+	strb	r7,[r0,#0+3]
+	mov	r10,r7,lsr#16
+	strb	r9,[r0,#0+2]
+	mov	r11,r7,lsr#24
+	strb	r10,[r0,#0+1]
+	strb	r11,[r0,#0]
+#endif
+	
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size	gcm_gmult_4bit,.-gcm_gmult_4bit
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+.fpu	neon
+
+.global	gcm_gmult_neon
+.type	gcm_gmult_neon,%function
+.align	4
+gcm_gmult_neon:
+	sub		r1,#16		@ point at H in GCM128_CTX
+	vld1.64		d29,[r0,:64]!@ load Xi
+	vmov.i32	d5,#0xe1		@ our irreducible polynomial
+	vld1.64		d28,[r0,:64]!
+	vshr.u64	d5,#32
+	vldmia		r1,{d0-d1}	@ load H
+	veor		q12,q12
+#ifdef __ARMEL__
+	vrev64.8	q14,q14
+#endif
+	veor		q13,q13
+	veor		q11,q11
+	mov		r1,#16
+	veor		q10,q10
+	mov		r3,#16
+	veor		d2,d2
+	vdup.8		d4,d28[0]	@ broadcast lowest byte
+	b		.Linner_neon
+.size	gcm_gmult_neon,.-gcm_gmult_neon
+
+.global	gcm_ghash_neon
+.type	gcm_ghash_neon,%function
+.align	4
+gcm_ghash_neon:
+	vld1.64		d21,[r0,:64]!	@ load Xi
+	vmov.i32	d5,#0xe1		@ our irreducible polynomial
+	vld1.64		d20,[r0,:64]!
+	vshr.u64	d5,#32
+	vldmia		r0,{d0-d1}		@ load H
+	veor		q12,q12
+	nop
+#ifdef __ARMEL__
+	vrev64.8	q10,q10
+#endif
+.Louter_neon:
+	vld1.64		d29,[r2]!	@ load inp
+	veor		q13,q13
+	vld1.64		d28,[r2]!
+	veor		q11,q11
+	mov		r1,#16
+#ifdef __ARMEL__
+	vrev64.8	q14,q14
+#endif
+	veor		d2,d2
+	veor		q14,q10			@ inp^=Xi
+	veor		q10,q10
+	vdup.8		d4,d28[0]	@ broadcast lowest byte
+.Linner_neon:
+	subs		r1,r1,#1
+	vmull.p8	q9,d1,d4		@ H.lo·Xi[i]
+	vmull.p8	q8,d0,d4		@ H.hi·Xi[i]
+	vext.8		q14,q12,#1		@ IN>>=8
+
+	veor		q10,q13		@ modulo-scheduled part
+	vshl.i64	d22,#48
+	vdup.8		d4,d28[0]	@ broadcast lowest byte
+	veor		d3,d18,d20
+
+	veor		d21,d22
+	vuzp.8		q9,q8
+	vsli.8		d2,d3,#1		@ compose the "carry" byte
+	vext.8		q10,q12,#1		@ Z>>=8
+
+	vmull.p8	q11,d2,d5		@ "carry"·0xe1
+	vshr.u8		d2,d3,#7		@ save Z's bottom bit
+	vext.8		q13,q9,q12,#1	@ Qlo>>=8
+	veor		q10,q8
+	bne		.Linner_neon
+
+	veor		q10,q13		@ modulo-scheduled artefact
+	vshl.i64	d22,#48
+	veor		d21,d22
+
+	@ finalization, normalize Z:Zo
+	vand		d2,d5		@ suffices to mask the bit
+	vshr.u64	d3,d20,#63
+	vshl.i64	q10,#1
+	subs		r3,#16
+	vorr		q10,q1		@ Z=Z:Zo<<1
+	bne		.Louter_neon
+
+#ifdef __ARMEL__
+	vrev64.8	q10,q10
+#endif
+	sub		r0,#16	
+	vst1.64		d21,[r0,:64]!	@ write out Xi
+	vst1.64		d20,[r0,:64]
+
+	.word	0xe12fff1e
+.size	gcm_ghash_neon,.-gcm_ghash_neon
+#endif
+.asciz  "GHASH for ARMv4/NEON, CRYPTOGAMS by "
+.align  2
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/modes/ghash-elf-x86_64.S b/crypto/modes/ghash-elf-x86_64.S
new file mode 100644
index 0000000..039cd49
--- /dev/null
+++ b/crypto/modes/ghash-elf-x86_64.S
@@ -0,0 +1,1033 @@
+#include "x86_arch.h"
+.text	
+
+.globl	gcm_gmult_4bit
+.type	gcm_gmult_4bit,@function
+.align	16
+gcm_gmult_4bit:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+.Lgmult_prologue:
+
+	movzbq	15(%rdi),%r8
+	leaq	.Lrem_4bit(%rip),%r11
+	xorq	%rax,%rax
+	xorq	%rbx,%rbx
+	movb	%r8b,%al
+	movb	%r8b,%bl
+	shlb	$4,%al
+	movq	$14,%rcx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	movq	%r8,%rdx
+	jmp	.Loop1
+
+.align	16
+.Loop1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	movb	(%rdi,%rcx,1),%al
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	movb	%al,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	shlb	$4,%al
+	xorq	%r10,%r8
+	decq	%rcx
+	js	.Lbreak1
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+	jmp	.Loop1
+
+.align	16
+.Lbreak1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	xorq	%r10,%r8
+	xorq	(%r11,%rdx,8),%r9
+
+	bswapq	%r8
+	bswapq	%r9
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	movq	16(%rsp),%rbx
+	leaq	24(%rsp),%rsp
+.Lgmult_epilogue:
+	retq
+.size	gcm_gmult_4bit,.-gcm_gmult_4bit
+.globl	gcm_ghash_4bit
+.type	gcm_ghash_4bit,@function
+.align	16
+gcm_ghash_4bit:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$280,%rsp
+.Lghash_prologue:
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	subq	$-128,%rsi
+	leaq	16+128(%rsp),%rbp
+	xorl	%edx,%edx
+	movq	0+0-128(%rsi),%r8
+	movq	0+8-128(%rsi),%rax
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	16+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	16+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,0(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,0(%rbp)
+	movq	32+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,0-128(%rbp)
+	movq	32+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,1(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,8(%rbp)
+	movq	48+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,8-128(%rbp)
+	movq	48+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,2(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,16(%rbp)
+	movq	64+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,16-128(%rbp)
+	movq	64+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,3(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,24(%rbp)
+	movq	80+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,24-128(%rbp)
+	movq	80+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,4(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,32(%rbp)
+	movq	96+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,32-128(%rbp)
+	movq	96+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,5(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,40(%rbp)
+	movq	112+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,40-128(%rbp)
+	movq	112+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,6(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,48(%rbp)
+	movq	128+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,48-128(%rbp)
+	movq	128+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,7(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,56(%rbp)
+	movq	144+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,56-128(%rbp)
+	movq	144+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,8(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,64(%rbp)
+	movq	160+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,64-128(%rbp)
+	movq	160+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,9(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,72(%rbp)
+	movq	176+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,72-128(%rbp)
+	movq	176+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,10(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,80(%rbp)
+	movq	192+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,80-128(%rbp)
+	movq	192+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,11(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,88(%rbp)
+	movq	208+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,88-128(%rbp)
+	movq	208+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,12(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,96(%rbp)
+	movq	224+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,96-128(%rbp)
+	movq	224+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,13(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,104(%rbp)
+	movq	240+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,104-128(%rbp)
+	movq	240+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,14(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,112(%rbp)
+	shlb	$4,%dl
+	movq	%rax,112-128(%rbp)
+	shlq	$60,%r10
+	movb	%dl,15(%rsp)
+	orq	%r10,%rbx
+	movq	%r9,120(%rbp)
+	movq	%rbx,120-128(%rbp)
+	addq	$-128,%rsi
+	movq	8(%rdi),%r8
+	movq	0(%rdi),%r9
+	addq	%r14,%r15
+	leaq	.Lrem_8bit(%rip),%r11
+	jmp	.Louter_loop
+.align	16
+.Louter_loop:
+	xorq	(%r14),%r9
+	movq	8(%r14),%rdx
+	leaq	16(%r14),%r14
+	xorq	%r8,%rdx
+	movq	%r9,(%rdi)
+	movq	%rdx,8(%rdi)
+	shrq	$32,%rdx
+	xorq	%rax,%rax
+	roll	$8,%edx
+	movb	%dl,%al
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	shrl	$4,%ebx
+	roll	$8,%edx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	8(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	0(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	andl	$240,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	-4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	movzwq	(%r11,%r12,2),%r12
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	shlq	$48,%r12
+	xorq	%r10,%r8
+	xorq	%r12,%r9
+	movzbq	%r8b,%r13
+	shrq	$4,%r8
+	movq	%r9,%r10
+	shlb	$4,%r13b
+	shrq	$4,%r9
+	xorq	8(%rsi,%rcx,1),%r8
+	movzwq	(%r11,%r13,2),%r13
+	shlq	$60,%r10
+	xorq	(%rsi,%rcx,1),%r9
+	xorq	%r10,%r8
+	shlq	$48,%r13
+	bswapq	%r8
+	xorq	%r13,%r9
+	bswapq	%r9
+	cmpq	%r15,%r14
+	jb	.Louter_loop
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	leaq	280(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lghash_epilogue:
+	retq
+.size	gcm_ghash_4bit,.-gcm_ghash_4bit
+.globl	gcm_init_clmul
+.type	gcm_init_clmul,@function
+.align	16
+gcm_init_clmul:
+	endbr64
+	movdqu	(%rsi),%xmm2
+	pshufd	$78,%xmm2,%xmm2
+
+
+	pshufd	$255,%xmm2,%xmm4
+	movdqa	%xmm2,%xmm3
+	psllq	$1,%xmm2
+	pxor	%xmm5,%xmm5
+	psrlq	$63,%xmm3
+	pcmpgtd	%xmm4,%xmm5
+	pslldq	$8,%xmm3
+	por	%xmm3,%xmm2
+
+
+	pand	.L0x1c2_polynomial(%rip),%xmm5
+	pxor	%xmm5,%xmm2
+
+
+	movdqa	%xmm2,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	movdqu	%xmm2,(%rdi)
+	movdqu	%xmm0,16(%rdi)
+	retq
+.size	gcm_init_clmul,.-gcm_init_clmul
+.globl	gcm_gmult_clmul
+.type	gcm_gmult_clmul,@function
+.align	16
+gcm_gmult_clmul:
+	endbr64
+	movdqu	(%rdi),%xmm0
+	movdqa	.Lbswap_mask(%rip),%xmm5
+	movdqu	(%rsi),%xmm2
+.byte	102,15,56,0,197
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rdi)
+	retq
+.size	gcm_gmult_clmul,.-gcm_gmult_clmul
+.globl	gcm_ghash_clmul
+.type	gcm_ghash_clmul,@function
+.align	16
+gcm_ghash_clmul:
+	endbr64
+	movdqa	.Lbswap_mask(%rip),%xmm5
+
+	movdqu	(%rdi),%xmm0
+	movdqu	(%rsi),%xmm2
+.byte	102,15,56,0,197
+
+	subq	$16,%rcx
+	jz	.Lodd_tail
+
+	movdqu	16(%rsi),%xmm8
+
+
+
+
+
+	movdqu	(%rdx),%xmm3
+	movdqu	16(%rdx),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm6,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,242,0
+.byte	102,15,58,68,250,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm7,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm7
+	pxor	%xmm4,%xmm6
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	leaq	32(%rdx),%rdx
+	subq	$32,%rcx
+	jbe	.Leven_tail
+
+.Lmod_loop:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqu	(%rdx),%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqu	16(%rdx),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm9
+	pshufd	$78,%xmm2,%xmm10
+	pxor	%xmm6,%xmm9
+	pxor	%xmm2,%xmm10
+	pxor	%xmm3,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+.byte	102,15,58,68,242,0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+.byte	102,15,58,68,250,17
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+
+.byte	102,69,15,58,68,202,0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	pxor	%xmm6,%xmm9
+	pxor	%xmm7,%xmm9
+	movdqa	%xmm9,%xmm10
+	psrldq	$8,%xmm9
+	pslldq	$8,%xmm10
+	pxor	%xmm9,%xmm7
+	pxor	%xmm10,%xmm6
+
+	leaq	32(%rdx),%rdx
+	subq	$32,%rcx
+	ja	.Lmod_loop
+
+.Leven_tail:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	testq	%rcx,%rcx
+	jnz	.Ldone
+
+.Lodd_tail:
+	movdqu	(%rdx),%xmm3
+.byte	102,15,56,0,221
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+.Ldone:
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rdi)
+	retq
+.LSEH_end_gcm_ghash_clmul:
+.size	gcm_ghash_clmul,.-gcm_ghash_clmul
+.section	.rodata
+.align	64
+.Lbswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.L0x1c2_polynomial:
+.byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+.align	64
+.type	.Lrem_4bit,@object
+.Lrem_4bit:
+.long	0,0,0,471859200,0,943718400,0,610271232
+.long	0,1887436800,0,1822425088,0,1220542464,0,1423966208
+.long	0,3774873600,0,4246732800,0,3644850176,0,3311403008
+.long	0,2441084928,0,2376073216,0,2847932416,0,3051356160
+.type	.Lrem_8bit,@object
+.Lrem_8bit:
+.value	0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E
+.value	0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E
+.value	0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E
+.value	0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E
+.value	0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E
+.value	0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E
+.value	0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E
+.value	0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E
+.value	0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE
+.value	0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE
+.value	0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE
+.value	0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE
+.value	0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E
+.value	0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E
+.value	0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE
+.value	0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE
+.value	0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E
+.value	0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E
+.value	0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E
+.value	0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E
+.value	0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E
+.value	0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E
+.value	0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E
+.value	0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E
+.value	0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE
+.value	0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE
+.value	0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE
+.value	0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE
+.value	0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E
+.value	0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E
+.value	0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE
+.value	0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE
+.align	64
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/modes/ghash-macosx-x86_64.S b/crypto/modes/ghash-macosx-x86_64.S
new file mode 100644
index 0000000..e6840a7
--- /dev/null
+++ b/crypto/modes/ghash-macosx-x86_64.S
@@ -0,0 +1,1027 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_gcm_gmult_4bit
+
+.p2align	4
+_gcm_gmult_4bit:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+L$gmult_prologue:
+
+	movzbq	15(%rdi),%r8
+	leaq	L$rem_4bit(%rip),%r11
+	xorq	%rax,%rax
+	xorq	%rbx,%rbx
+	movb	%r8b,%al
+	movb	%r8b,%bl
+	shlb	$4,%al
+	movq	$14,%rcx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	movq	%r8,%rdx
+	jmp	L$oop1
+
+.p2align	4
+L$oop1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	movb	(%rdi,%rcx,1),%al
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	movb	%al,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	shlb	$4,%al
+	xorq	%r10,%r8
+	decq	%rcx
+	js	L$break1
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+	jmp	L$oop1
+
+.p2align	4
+L$break1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	xorq	%r10,%r8
+	xorq	(%r11,%rdx,8),%r9
+
+	bswapq	%r8
+	bswapq	%r9
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	movq	16(%rsp),%rbx
+	leaq	24(%rsp),%rsp
+L$gmult_epilogue:
+	retq
+
+.globl	_gcm_ghash_4bit
+
+.p2align	4
+_gcm_ghash_4bit:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$280,%rsp
+L$ghash_prologue:
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	subq	$-128,%rsi
+	leaq	16+128(%rsp),%rbp
+	xorl	%edx,%edx
+	movq	0+0-128(%rsi),%r8
+	movq	0+8-128(%rsi),%rax
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	16+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	16+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,0(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,0(%rbp)
+	movq	32+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,0-128(%rbp)
+	movq	32+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,1(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,8(%rbp)
+	movq	48+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,8-128(%rbp)
+	movq	48+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,2(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,16(%rbp)
+	movq	64+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,16-128(%rbp)
+	movq	64+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,3(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,24(%rbp)
+	movq	80+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,24-128(%rbp)
+	movq	80+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,4(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,32(%rbp)
+	movq	96+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,32-128(%rbp)
+	movq	96+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,5(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,40(%rbp)
+	movq	112+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,40-128(%rbp)
+	movq	112+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,6(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,48(%rbp)
+	movq	128+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,48-128(%rbp)
+	movq	128+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,7(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,56(%rbp)
+	movq	144+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,56-128(%rbp)
+	movq	144+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,8(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,64(%rbp)
+	movq	160+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,64-128(%rbp)
+	movq	160+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,9(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,72(%rbp)
+	movq	176+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,72-128(%rbp)
+	movq	176+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,10(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,80(%rbp)
+	movq	192+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,80-128(%rbp)
+	movq	192+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,11(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,88(%rbp)
+	movq	208+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,88-128(%rbp)
+	movq	208+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,12(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,96(%rbp)
+	movq	224+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,96-128(%rbp)
+	movq	224+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,13(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,104(%rbp)
+	movq	240+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,104-128(%rbp)
+	movq	240+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,14(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,112(%rbp)
+	shlb	$4,%dl
+	movq	%rax,112-128(%rbp)
+	shlq	$60,%r10
+	movb	%dl,15(%rsp)
+	orq	%r10,%rbx
+	movq	%r9,120(%rbp)
+	movq	%rbx,120-128(%rbp)
+	addq	$-128,%rsi
+	movq	8(%rdi),%r8
+	movq	0(%rdi),%r9
+	addq	%r14,%r15
+	leaq	L$rem_8bit(%rip),%r11
+	jmp	L$outer_loop
+.p2align	4
+L$outer_loop:
+	xorq	(%r14),%r9
+	movq	8(%r14),%rdx
+	leaq	16(%r14),%r14
+	xorq	%r8,%rdx
+	movq	%r9,(%rdi)
+	movq	%rdx,8(%rdi)
+	shrq	$32,%rdx
+	xorq	%rax,%rax
+	roll	$8,%edx
+	movb	%dl,%al
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	shrl	$4,%ebx
+	roll	$8,%edx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	8(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	0(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	andl	$240,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	-4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	movzwq	(%r11,%r12,2),%r12
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	shlq	$48,%r12
+	xorq	%r10,%r8
+	xorq	%r12,%r9
+	movzbq	%r8b,%r13
+	shrq	$4,%r8
+	movq	%r9,%r10
+	shlb	$4,%r13b
+	shrq	$4,%r9
+	xorq	8(%rsi,%rcx,1),%r8
+	movzwq	(%r11,%r13,2),%r13
+	shlq	$60,%r10
+	xorq	(%rsi,%rcx,1),%r9
+	xorq	%r10,%r8
+	shlq	$48,%r13
+	bswapq	%r8
+	xorq	%r13,%r9
+	bswapq	%r9
+	cmpq	%r15,%r14
+	jb	L$outer_loop
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	leaq	280(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$ghash_epilogue:
+	retq
+
+.globl	_gcm_init_clmul
+
+.p2align	4
+_gcm_init_clmul:
+	movdqu	(%rsi),%xmm2
+	pshufd	$78,%xmm2,%xmm2
+
+
+	pshufd	$255,%xmm2,%xmm4
+	movdqa	%xmm2,%xmm3
+	psllq	$1,%xmm2
+	pxor	%xmm5,%xmm5
+	psrlq	$63,%xmm3
+	pcmpgtd	%xmm4,%xmm5
+	pslldq	$8,%xmm3
+	por	%xmm3,%xmm2
+
+
+	pand	L$0x1c2_polynomial(%rip),%xmm5
+	pxor	%xmm5,%xmm2
+
+
+	movdqa	%xmm2,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	movdqu	%xmm2,(%rdi)
+	movdqu	%xmm0,16(%rdi)
+	retq
+
+.globl	_gcm_gmult_clmul
+
+.p2align	4
+_gcm_gmult_clmul:
+	movdqu	(%rdi),%xmm0
+	movdqa	L$bswap_mask(%rip),%xmm5
+	movdqu	(%rsi),%xmm2
+.byte	102,15,56,0,197
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rdi)
+	retq
+
+.globl	_gcm_ghash_clmul
+
+.p2align	4
+_gcm_ghash_clmul:
+	movdqa	L$bswap_mask(%rip),%xmm5
+
+	movdqu	(%rdi),%xmm0
+	movdqu	(%rsi),%xmm2
+.byte	102,15,56,0,197
+
+	subq	$16,%rcx
+	jz	L$odd_tail
+
+	movdqu	16(%rsi),%xmm8
+
+
+
+
+
+	movdqu	(%rdx),%xmm3
+	movdqu	16(%rdx),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm6,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,242,0
+.byte	102,15,58,68,250,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm7,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm7
+	pxor	%xmm4,%xmm6
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	leaq	32(%rdx),%rdx
+	subq	$32,%rcx
+	jbe	L$even_tail
+
+L$mod_loop:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqu	(%rdx),%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqu	16(%rdx),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm9
+	pshufd	$78,%xmm2,%xmm10
+	pxor	%xmm6,%xmm9
+	pxor	%xmm2,%xmm10
+	pxor	%xmm3,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+.byte	102,15,58,68,242,0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+.byte	102,15,58,68,250,17
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+
+.byte	102,69,15,58,68,202,0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	pxor	%xmm6,%xmm9
+	pxor	%xmm7,%xmm9
+	movdqa	%xmm9,%xmm10
+	psrldq	$8,%xmm9
+	pslldq	$8,%xmm10
+	pxor	%xmm9,%xmm7
+	pxor	%xmm10,%xmm6
+
+	leaq	32(%rdx),%rdx
+	subq	$32,%rcx
+	ja	L$mod_loop
+
+L$even_tail:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	testq	%rcx,%rcx
+	jnz	L$done
+
+L$odd_tail:
+	movdqu	(%rdx),%xmm3
+.byte	102,15,56,0,221
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+L$done:
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rdi)
+	retq
+L$SEH_end_gcm_ghash_clmul:
+
+.p2align	6
+L$bswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+L$0x1c2_polynomial:
+.byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+.p2align	6
+
+L$rem_4bit:
+.long	0,0,0,471859200,0,943718400,0,610271232
+.long	0,1887436800,0,1822425088,0,1220542464,0,1423966208
+.long	0,3774873600,0,4246732800,0,3644850176,0,3311403008
+.long	0,2441084928,0,2376073216,0,2847932416,0,3051356160
+
+L$rem_8bit:
+.value	0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E
+.value	0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E
+.value	0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E
+.value	0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E
+.value	0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E
+.value	0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E
+.value	0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E
+.value	0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E
+.value	0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE
+.value	0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE
+.value	0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE
+.value	0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE
+.value	0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E
+.value	0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E
+.value	0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE
+.value	0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE
+.value	0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E
+.value	0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E
+.value	0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E
+.value	0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E
+.value	0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E
+.value	0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E
+.value	0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E
+.value	0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E
+.value	0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE
+.value	0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE
+.value	0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE
+.value	0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE
+.value	0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E
+.value	0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E
+.value	0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE
+.value	0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE
+
+.byte	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
diff --git a/crypto/modes/ghash-masm-x86_64.S b/crypto/modes/ghash-masm-x86_64.S
new file mode 100644
index 0000000..6d45517
--- /dev/null
+++ b/crypto/modes/ghash-masm-x86_64.S
@@ -0,0 +1,1256 @@
+; 1 "crypto/modes/ghash-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/modes/ghash-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/modes/ghash-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	gcm_gmult_4bit
+
+ALIGN	16
+gcm_gmult_4bit	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_gcm_gmult_4bit::
+	mov	rdi,rcx
+	mov	rsi,rdx
+
+
+	push	rbx
+	push	rbp
+	push	r12
+$L$gmult_prologue::
+
+	movzx	r8,BYTE PTR[15+rdi]
+	lea	r11,QWORD PTR[$L$rem_4bit]
+	xor	rax,rax
+	xor	rbx,rbx
+	mov	al,r8b
+	mov	bl,r8b
+	shl	al,4
+	mov	rcx,14
+	mov	r8,QWORD PTR[8+rax*1+rsi]
+	mov	r9,QWORD PTR[rax*1+rsi]
+	and	bl,0f0h
+	mov	rdx,r8
+	jmp	$L$oop1
+
+ALIGN	16
+$L$oop1::
+	shr	r8,4
+	and	rdx,0fh
+	mov	r10,r9
+	mov	al,BYTE PTR[rcx*1+rdi]
+	shr	r9,4
+	xor	r8,QWORD PTR[8+rbx*1+rsi]
+	shl	r10,60
+	xor	r9,QWORD PTR[rbx*1+rsi]
+	mov	bl,al
+	xor	r9,QWORD PTR[rdx*8+r11]
+	mov	rdx,r8
+	shl	al,4
+	xor	r8,r10
+	dec	rcx
+	js	$L$break1
+
+	shr	r8,4
+	and	rdx,0fh
+	mov	r10,r9
+	shr	r9,4
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	shl	r10,60
+	xor	r9,QWORD PTR[rax*1+rsi]
+	and	bl,0f0h
+	xor	r9,QWORD PTR[rdx*8+r11]
+	mov	rdx,r8
+	xor	r8,r10
+	jmp	$L$oop1
+
+ALIGN	16
+$L$break1::
+	shr	r8,4
+	and	rdx,0fh
+	mov	r10,r9
+	shr	r9,4
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	shl	r10,60
+	xor	r9,QWORD PTR[rax*1+rsi]
+	and	bl,0f0h
+	xor	r9,QWORD PTR[rdx*8+r11]
+	mov	rdx,r8
+	xor	r8,r10
+
+	shr	r8,4
+	and	rdx,0fh
+	mov	r10,r9
+	shr	r9,4
+	xor	r8,QWORD PTR[8+rbx*1+rsi]
+	shl	r10,60
+	xor	r9,QWORD PTR[rbx*1+rsi]
+	xor	r8,r10
+	xor	r9,QWORD PTR[rdx*8+r11]
+
+	bswap	r8
+	bswap	r9
+	mov	QWORD PTR[8+rdi],r8
+	mov	QWORD PTR[rdi],r9
+
+	mov	rbx,QWORD PTR[16+rsp]
+	lea	rsp,QWORD PTR[24+rsp]
+$L$gmult_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_gcm_gmult_4bit::
+gcm_gmult_4bit	ENDP
+PUBLIC	gcm_ghash_4bit
+
+ALIGN	16
+gcm_ghash_4bit	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_gcm_ghash_4bit::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	sub	rsp,280
+$L$ghash_prologue::
+	mov	r14,rdx
+	mov	r15,rcx
+	sub	rsi,-128
+	lea	rbp,QWORD PTR[((16+128))+rsp]
+	xor	edx,edx
+	mov	r8,QWORD PTR[((0+0-128))+rsi]
+	mov	rax,QWORD PTR[((0+8-128))+rsi]
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	r9,QWORD PTR[((16+0-128))+rsi]
+	shl	dl,4
+	mov	rbx,QWORD PTR[((16+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[rbp],r8
+	mov	r8,QWORD PTR[((32+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((0-128))+rbp],rax
+	mov	rax,QWORD PTR[((32+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[1+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[8+rbp],r9
+	mov	r9,QWORD PTR[((48+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((8-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((48+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[2+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[16+rbp],r8
+	mov	r8,QWORD PTR[((64+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((16-128))+rbp],rax
+	mov	rax,QWORD PTR[((64+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[3+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[24+rbp],r9
+	mov	r9,QWORD PTR[((80+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((24-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((80+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[4+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[32+rbp],r8
+	mov	r8,QWORD PTR[((96+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((32-128))+rbp],rax
+	mov	rax,QWORD PTR[((96+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[5+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[40+rbp],r9
+	mov	r9,QWORD PTR[((112+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((40-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((112+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[6+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[48+rbp],r8
+	mov	r8,QWORD PTR[((128+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((48-128))+rbp],rax
+	mov	rax,QWORD PTR[((128+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[7+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[56+rbp],r9
+	mov	r9,QWORD PTR[((144+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((56-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((144+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[8+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[64+rbp],r8
+	mov	r8,QWORD PTR[((160+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((64-128))+rbp],rax
+	mov	rax,QWORD PTR[((160+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[9+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[72+rbp],r9
+	mov	r9,QWORD PTR[((176+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((72-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((176+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[10+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[80+rbp],r8
+	mov	r8,QWORD PTR[((192+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((80-128))+rbp],rax
+	mov	rax,QWORD PTR[((192+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[11+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[88+rbp],r9
+	mov	r9,QWORD PTR[((208+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((88-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((208+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[12+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[96+rbp],r8
+	mov	r8,QWORD PTR[((224+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((96-128))+rbp],rax
+	mov	rax,QWORD PTR[((224+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[13+rsp],dl
+	or	rbx,r10
+	mov	dl,al
+	shr	rax,4
+	mov	r10,r8
+	shr	r8,4
+	mov	QWORD PTR[104+rbp],r9
+	mov	r9,QWORD PTR[((240+0-128))+rsi]
+	shl	dl,4
+	mov	QWORD PTR[((104-128))+rbp],rbx
+	mov	rbx,QWORD PTR[((240+8-128))+rsi]
+	shl	r10,60
+	mov	BYTE PTR[14+rsp],dl
+	or	rax,r10
+	mov	dl,bl
+	shr	rbx,4
+	mov	r10,r9
+	shr	r9,4
+	mov	QWORD PTR[112+rbp],r8
+	shl	dl,4
+	mov	QWORD PTR[((112-128))+rbp],rax
+	shl	r10,60
+	mov	BYTE PTR[15+rsp],dl
+	or	rbx,r10
+	mov	QWORD PTR[120+rbp],r9
+	mov	QWORD PTR[((120-128))+rbp],rbx
+	add	rsi,-128
+	mov	r8,QWORD PTR[8+rdi]
+	mov	r9,QWORD PTR[rdi]
+	add	r15,r14
+	lea	r11,QWORD PTR[$L$rem_8bit]
+	jmp	$L$outer_loop
+ALIGN	16
+$L$outer_loop::
+	xor	r9,QWORD PTR[r14]
+	mov	rdx,QWORD PTR[8+r14]
+	lea	r14,QWORD PTR[16+r14]
+	xor	rdx,r8
+	mov	QWORD PTR[rdi],r9
+	mov	QWORD PTR[8+rdi],rdx
+	shr	rdx,32
+	xor	rax,rax
+	rol	edx,8
+	mov	al,dl
+	movzx	ebx,dl
+	shl	al,4
+	shr	ebx,4
+	rol	edx,8
+	mov	r8,QWORD PTR[8+rax*1+rsi]
+	mov	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	xor	r12,r8
+	mov	r10,r9
+	shr	r8,8
+	movzx	r12,r12b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	mov	edx,DWORD PTR[8+rdi]
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	mov	edx,DWORD PTR[4+rdi]
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	mov	edx,DWORD PTR[rdi]
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	shr	ecx,4
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r12,WORD PTR[r12*2+r11]
+	movzx	ebx,dl
+	shl	al,4
+	movzx	r13,BYTE PTR[rcx*1+rsp]
+	shr	ebx,4
+	shl	r12,48
+	xor	r13,r8
+	mov	r10,r9
+	xor	r9,r12
+	shr	r8,8
+	movzx	r13,r13b
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rcx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rcx*8+rbp]
+	rol	edx,8
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	mov	al,dl
+	xor	r8,r10
+	movzx	r13,WORD PTR[r13*2+r11]
+	movzx	ecx,dl
+	shl	al,4
+	movzx	r12,BYTE PTR[rbx*1+rsp]
+	and	ecx,240
+	shl	r13,48
+	xor	r12,r8
+	mov	r10,r9
+	xor	r9,r13
+	shr	r8,8
+	movzx	r12,r12b
+	mov	edx,DWORD PTR[((-4))+rdi]
+	shr	r9,8
+	xor	r8,QWORD PTR[((-128))+rbx*8+rbp]
+	shl	r10,56
+	xor	r9,QWORD PTR[rbx*8+rbp]
+	movzx	r12,WORD PTR[r12*2+r11]
+	xor	r8,QWORD PTR[8+rax*1+rsi]
+	xor	r9,QWORD PTR[rax*1+rsi]
+	shl	r12,48
+	xor	r8,r10
+	xor	r9,r12
+	movzx	r13,r8b
+	shr	r8,4
+	mov	r10,r9
+	shl	r13b,4
+	shr	r9,4
+	xor	r8,QWORD PTR[8+rcx*1+rsi]
+	movzx	r13,WORD PTR[r13*2+r11]
+	shl	r10,60
+	xor	r9,QWORD PTR[rcx*1+rsi]
+	xor	r8,r10
+	shl	r13,48
+	bswap	r8
+	xor	r9,r13
+	bswap	r9
+	cmp	r14,r15
+	jb	$L$outer_loop
+	mov	QWORD PTR[8+rdi],r8
+	mov	QWORD PTR[rdi],r9
+
+	lea	rsi,QWORD PTR[280+rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$ghash_epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_gcm_ghash_4bit::
+gcm_ghash_4bit	ENDP
+PUBLIC	gcm_init_clmul
+
+ALIGN	16
+gcm_init_clmul	PROC PUBLIC
+	movdqu	xmm2,XMMWORD PTR[rdx]
+	pshufd	xmm2,xmm2,78
+
+
+	pshufd	xmm4,xmm2,255
+	movdqa	xmm3,xmm2
+	psllq	xmm2,1
+	pxor	xmm5,xmm5
+	psrlq	xmm3,63
+	pcmpgtd	xmm5,xmm4
+	pslldq	xmm3,8
+	por	xmm2,xmm3
+
+
+	pand	xmm5,XMMWORD PTR[$L$0x1c2_polynomial]
+	pxor	xmm2,xmm5
+
+
+	movdqa	xmm0,xmm2
+	movdqa	xmm1,xmm0
+	pshufd	xmm3,xmm0,78
+	pshufd	xmm4,xmm2,78
+	pxor	xmm3,xmm0
+	pxor	xmm4,xmm2
+DB	102,15,58,68,194,0
+DB	102,15,58,68,202,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm1,xmm3
+	pxor	xmm0,xmm4
+
+	movdqa	xmm3,xmm0
+	psllq	xmm0,1
+	pxor	xmm0,xmm3
+	psllq	xmm0,5
+	pxor	xmm0,xmm3
+	psllq	xmm0,57
+	movdqa	xmm4,xmm0
+	pslldq	xmm0,8
+	psrldq	xmm4,8
+	pxor	xmm0,xmm3
+	pxor	xmm1,xmm4
+
+
+	movdqa	xmm4,xmm0
+	psrlq	xmm0,5
+	pxor	xmm0,xmm4
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	movdqu	XMMWORD PTR[rcx],xmm2
+	movdqu	XMMWORD PTR[16+rcx],xmm0
+	DB	0F3h,0C3h		;repret
+gcm_init_clmul	ENDP
+PUBLIC	gcm_gmult_clmul
+
+ALIGN	16
+gcm_gmult_clmul	PROC PUBLIC
+	movdqu	xmm0,XMMWORD PTR[rcx]
+	movdqa	xmm5,XMMWORD PTR[$L$bswap_mask]
+	movdqu	xmm2,XMMWORD PTR[rdx]
+DB	102,15,56,0,197
+	movdqa	xmm1,xmm0
+	pshufd	xmm3,xmm0,78
+	pshufd	xmm4,xmm2,78
+	pxor	xmm3,xmm0
+	pxor	xmm4,xmm2
+DB	102,15,58,68,194,0
+DB	102,15,58,68,202,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm1,xmm3
+	pxor	xmm0,xmm4
+
+	movdqa	xmm3,xmm0
+	psllq	xmm0,1
+	pxor	xmm0,xmm3
+	psllq	xmm0,5
+	pxor	xmm0,xmm3
+	psllq	xmm0,57
+	movdqa	xmm4,xmm0
+	pslldq	xmm0,8
+	psrldq	xmm4,8
+	pxor	xmm0,xmm3
+	pxor	xmm1,xmm4
+
+
+	movdqa	xmm4,xmm0
+	psrlq	xmm0,5
+	pxor	xmm0,xmm4
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+DB	102,15,56,0,197
+	movdqu	XMMWORD PTR[rcx],xmm0
+	DB	0F3h,0C3h		;repret
+gcm_gmult_clmul	ENDP
+PUBLIC	gcm_ghash_clmul
+
+ALIGN	16
+gcm_ghash_clmul	PROC PUBLIC
+$L$SEH_begin_gcm_ghash_clmul::
+
+DB	048h,083h,0ech,058h		
+DB	00fh,029h,034h,024h		
+DB	00fh,029h,07ch,024h,010h	
+DB	044h,00fh,029h,044h,024h,020h	
+DB	044h,00fh,029h,04ch,024h,030h	
+DB	044h,00fh,029h,054h,024h,040h	
+	movdqa	xmm5,XMMWORD PTR[$L$bswap_mask]
+
+	movdqu	xmm0,XMMWORD PTR[rcx]
+	movdqu	xmm2,XMMWORD PTR[rdx]
+DB	102,15,56,0,197
+
+	sub	r9,010h
+	jz	$L$odd_tail
+
+	movdqu	xmm8,XMMWORD PTR[16+rdx]
+
+
+
+
+
+	movdqu	xmm3,XMMWORD PTR[r8]
+	movdqu	xmm6,XMMWORD PTR[16+r8]
+DB	102,15,56,0,221
+DB	102,15,56,0,245
+	pxor	xmm0,xmm3
+	movdqa	xmm7,xmm6
+	pshufd	xmm3,xmm6,78
+	pshufd	xmm4,xmm2,78
+	pxor	xmm3,xmm6
+	pxor	xmm4,xmm2
+DB	102,15,58,68,242,0
+DB	102,15,58,68,250,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm6
+	pxor	xmm3,xmm7
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm7,xmm3
+	pxor	xmm6,xmm4
+	movdqa	xmm1,xmm0
+	pshufd	xmm3,xmm0,78
+	pshufd	xmm4,xmm8,78
+	pxor	xmm3,xmm0
+	pxor	xmm4,xmm8
+
+	lea	r8,QWORD PTR[32+r8]
+	sub	r9,020h
+	jbe	$L$even_tail
+
+$L$mod_loop::
+DB	102,65,15,58,68,192,0
+DB	102,65,15,58,68,200,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm1,xmm3
+	pxor	xmm0,xmm4
+	movdqu	xmm3,XMMWORD PTR[r8]
+	pxor	xmm0,xmm6
+	pxor	xmm1,xmm7
+
+	movdqu	xmm6,XMMWORD PTR[16+r8]
+DB	102,15,56,0,221
+DB	102,15,56,0,245
+
+	movdqa	xmm7,xmm6
+	pshufd	xmm9,xmm6,78
+	pshufd	xmm10,xmm2,78
+	pxor	xmm9,xmm6
+	pxor	xmm10,xmm2
+	pxor	xmm1,xmm3
+
+	movdqa	xmm3,xmm0
+	psllq	xmm0,1
+	pxor	xmm0,xmm3
+	psllq	xmm0,5
+	pxor	xmm0,xmm3
+DB	102,15,58,68,242,0
+	psllq	xmm0,57
+	movdqa	xmm4,xmm0
+	pslldq	xmm0,8
+	psrldq	xmm4,8
+	pxor	xmm0,xmm3
+	pxor	xmm1,xmm4
+
+DB	102,15,58,68,250,17
+	movdqa	xmm4,xmm0
+	psrlq	xmm0,5
+	pxor	xmm0,xmm4
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+
+DB	102,69,15,58,68,202,0
+	movdqa	xmm1,xmm0
+	pshufd	xmm3,xmm0,78
+	pshufd	xmm4,xmm8,78
+	pxor	xmm3,xmm0
+	pxor	xmm4,xmm8
+
+	pxor	xmm9,xmm6
+	pxor	xmm9,xmm7
+	movdqa	xmm10,xmm9
+	psrldq	xmm9,8
+	pslldq	xmm10,8
+	pxor	xmm7,xmm9
+	pxor	xmm6,xmm10
+
+	lea	r8,QWORD PTR[32+r8]
+	sub	r9,020h
+	ja	$L$mod_loop
+
+$L$even_tail::
+DB	102,65,15,58,68,192,0
+DB	102,65,15,58,68,200,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm1,xmm3
+	pxor	xmm0,xmm4
+	pxor	xmm0,xmm6
+	pxor	xmm1,xmm7
+
+	movdqa	xmm3,xmm0
+	psllq	xmm0,1
+	pxor	xmm0,xmm3
+	psllq	xmm0,5
+	pxor	xmm0,xmm3
+	psllq	xmm0,57
+	movdqa	xmm4,xmm0
+	pslldq	xmm0,8
+	psrldq	xmm4,8
+	pxor	xmm0,xmm3
+	pxor	xmm1,xmm4
+
+
+	movdqa	xmm4,xmm0
+	psrlq	xmm0,5
+	pxor	xmm0,xmm4
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	test	r9,r9
+	jnz	$L$done
+
+$L$odd_tail::
+	movdqu	xmm3,XMMWORD PTR[r8]
+DB	102,15,56,0,221
+	pxor	xmm0,xmm3
+	movdqa	xmm1,xmm0
+	pshufd	xmm3,xmm0,78
+	pshufd	xmm4,xmm2,78
+	pxor	xmm3,xmm0
+	pxor	xmm4,xmm2
+DB	102,15,58,68,194,0
+DB	102,15,58,68,202,17
+DB	102,15,58,68,220,0
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+
+	movdqa	xmm4,xmm3
+	psrldq	xmm3,8
+	pslldq	xmm4,8
+	pxor	xmm1,xmm3
+	pxor	xmm0,xmm4
+
+	movdqa	xmm3,xmm0
+	psllq	xmm0,1
+	pxor	xmm0,xmm3
+	psllq	xmm0,5
+	pxor	xmm0,xmm3
+	psllq	xmm0,57
+	movdqa	xmm4,xmm0
+	pslldq	xmm0,8
+	psrldq	xmm4,8
+	pxor	xmm0,xmm3
+	pxor	xmm1,xmm4
+
+
+	movdqa	xmm4,xmm0
+	psrlq	xmm0,5
+	pxor	xmm0,xmm4
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+	pxor	xmm4,xmm1
+	psrlq	xmm0,1
+	pxor	xmm0,xmm4
+$L$done::
+DB	102,15,56,0,197
+	movdqu	XMMWORD PTR[rcx],xmm0
+	movaps	xmm6,XMMWORD PTR[rsp]
+	movaps	xmm7,XMMWORD PTR[16+rsp]
+	movaps	xmm8,XMMWORD PTR[32+rsp]
+	movaps	xmm9,XMMWORD PTR[48+rsp]
+	movaps	xmm10,XMMWORD PTR[64+rsp]
+	add	rsp,058h
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_gcm_ghash_clmul::
+gcm_ghash_clmul	ENDP
+ALIGN	64
+$L$bswap_mask::
+DB	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+$L$0x1c2_polynomial::
+DB	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0c2h
+ALIGN	64
+
+$L$rem_4bit::
+	DD	0,0,0,471859200,0,943718400,0,610271232
+	DD	0,1887436800,0,1822425088,0,1220542464,0,1423966208
+	DD	0,3774873600,0,4246732800,0,3644850176,0,3311403008
+	DD	0,2441084928,0,2376073216,0,2847932416,0,3051356160
+
+$L$rem_8bit::
+	DW	00000h,001C2h,00384h,00246h,00708h,006CAh,0048Ch,0054Eh
+	DW	00E10h,00FD2h,00D94h,00C56h,00918h,008DAh,00A9Ch,00B5Eh
+	DW	01C20h,01DE2h,01FA4h,01E66h,01B28h,01AEAh,018ACh,0196Eh
+	DW	01230h,013F2h,011B4h,01076h,01538h,014FAh,016BCh,0177Eh
+	DW	03840h,03982h,03BC4h,03A06h,03F48h,03E8Ah,03CCCh,03D0Eh
+	DW	03650h,03792h,035D4h,03416h,03158h,0309Ah,032DCh,0331Eh
+	DW	02460h,025A2h,027E4h,02626h,02368h,022AAh,020ECh,0212Eh
+	DW	02A70h,02BB2h,029F4h,02836h,02D78h,02CBAh,02EFCh,02F3Eh
+	DW	07080h,07142h,07304h,072C6h,07788h,0764Ah,0740Ch,075CEh
+	DW	07E90h,07F52h,07D14h,07CD6h,07998h,0785Ah,07A1Ch,07BDEh
+	DW	06CA0h,06D62h,06F24h,06EE6h,06BA8h,06A6Ah,0682Ch,069EEh
+	DW	062B0h,06372h,06134h,060F6h,065B8h,0647Ah,0663Ch,067FEh
+	DW	048C0h,04902h,04B44h,04A86h,04FC8h,04E0Ah,04C4Ch,04D8Eh
+	DW	046D0h,04712h,04554h,04496h,041D8h,0401Ah,0425Ch,0439Eh
+	DW	054E0h,05522h,05764h,056A6h,053E8h,0522Ah,0506Ch,051AEh
+	DW	05AF0h,05B32h,05974h,058B6h,05DF8h,05C3Ah,05E7Ch,05FBEh
+	DW	0E100h,0E0C2h,0E284h,0E346h,0E608h,0E7CAh,0E58Ch,0E44Eh
+	DW	0EF10h,0EED2h,0EC94h,0ED56h,0E818h,0E9DAh,0EB9Ch,0EA5Eh
+	DW	0FD20h,0FCE2h,0FEA4h,0FF66h,0FA28h,0FBEAh,0F9ACh,0F86Eh
+	DW	0F330h,0F2F2h,0F0B4h,0F176h,0F438h,0F5FAh,0F7BCh,0F67Eh
+	DW	0D940h,0D882h,0DAC4h,0DB06h,0DE48h,0DF8Ah,0DDCCh,0DC0Eh
+	DW	0D750h,0D692h,0D4D4h,0D516h,0D058h,0D19Ah,0D3DCh,0D21Eh
+	DW	0C560h,0C4A2h,0C6E4h,0C726h,0C268h,0C3AAh,0C1ECh,0C02Eh
+	DW	0CB70h,0CAB2h,0C8F4h,0C936h,0CC78h,0CDBAh,0CFFCh,0CE3Eh
+	DW	09180h,09042h,09204h,093C6h,09688h,0974Ah,0950Ch,094CEh
+	DW	09F90h,09E52h,09C14h,09DD6h,09898h,0995Ah,09B1Ch,09ADEh
+	DW	08DA0h,08C62h,08E24h,08FE6h,08AA8h,08B6Ah,0892Ch,088EEh
+	DW	083B0h,08272h,08034h,081F6h,084B8h,0857Ah,0873Ch,086FEh
+	DW	0A9C0h,0A802h,0AA44h,0AB86h,0AEC8h,0AF0Ah,0AD4Ch,0AC8Eh
+	DW	0A7D0h,0A612h,0A454h,0A596h,0A0D8h,0A11Ah,0A35Ch,0A29Eh
+	DW	0B5E0h,0B422h,0B664h,0B7A6h,0B2E8h,0B32Ah,0B16Ch,0B0AEh
+	DW	0BBF0h,0BA32h,0B874h,0B9B6h,0BCF8h,0BD3Ah,0BF7Ch,0BEBEh
+
+DB	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52
+DB	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
+DB	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
+DB	114,103,62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$in_prologue
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$in_prologue
+
+	lea	rax,QWORD PTR[24+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+
+$L$in_prologue::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+se_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_gcm_gmult_4bit
+	DD	imagerel $L$SEH_end_gcm_gmult_4bit
+	DD	imagerel $L$SEH_info_gcm_gmult_4bit
+
+	DD	imagerel $L$SEH_begin_gcm_ghash_4bit
+	DD	imagerel $L$SEH_end_gcm_ghash_4bit
+	DD	imagerel $L$SEH_info_gcm_ghash_4bit
+
+	DD	imagerel $L$SEH_begin_gcm_ghash_clmul
+	DD	imagerel $L$SEH_end_gcm_ghash_clmul
+	DD	imagerel $L$SEH_info_gcm_ghash_clmul
+
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_gcm_gmult_4bit::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$gmult_prologue,imagerel $L$gmult_epilogue	
+$L$SEH_info_gcm_ghash_4bit::
+DB	9,0,0,0
+	DD	imagerel se_handler
+	DD	imagerel $L$ghash_prologue,imagerel $L$ghash_epilogue	
+$L$SEH_info_gcm_ghash_clmul::
+DB	001h,01fh,00bh,000h
+DB	01fh,0a8h,004h,000h	
+DB	019h,098h,003h,000h	
+DB	013h,088h,002h,000h	
+DB	00dh,078h,001h,000h	
+DB	008h,068h,000h,000h	
+DB	004h,0a2h,000h,000h	
+
+.xdata	ENDS
+END
+
diff --git a/crypto/modes/ghash-mingw64-x86_64.S b/crypto/modes/ghash-mingw64-x86_64.S
new file mode 100644
index 0000000..cd0823b
--- /dev/null
+++ b/crypto/modes/ghash-mingw64-x86_64.S
@@ -0,0 +1,1175 @@
+#include "x86_arch.h"
+.text	
+
+.globl	gcm_gmult_4bit
+.def	gcm_gmult_4bit;	.scl 2;	.type 32;	.endef
+.p2align	4
+gcm_gmult_4bit:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_gcm_gmult_4bit:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+.Lgmult_prologue:
+
+	movzbq	15(%rdi),%r8
+	leaq	.Lrem_4bit(%rip),%r11
+	xorq	%rax,%rax
+	xorq	%rbx,%rbx
+	movb	%r8b,%al
+	movb	%r8b,%bl
+	shlb	$4,%al
+	movq	$14,%rcx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	movq	%r8,%rdx
+	jmp	.Loop1
+
+.p2align	4
+.Loop1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	movb	(%rdi,%rcx,1),%al
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	movb	%al,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	shlb	$4,%al
+	xorq	%r10,%r8
+	decq	%rcx
+	js	.Lbreak1
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+	jmp	.Loop1
+
+.p2align	4
+.Lbreak1:
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rax,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rax,1),%r9
+	andb	$240,%bl
+	xorq	(%r11,%rdx,8),%r9
+	movq	%r8,%rdx
+	xorq	%r10,%r8
+
+	shrq	$4,%r8
+	andq	$15,%rdx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	xorq	8(%rsi,%rbx,1),%r8
+	shlq	$60,%r10
+	xorq	(%rsi,%rbx,1),%r9
+	xorq	%r10,%r8
+	xorq	(%r11,%rdx,8),%r9
+
+	bswapq	%r8
+	bswapq	%r9
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	movq	16(%rsp),%rbx
+	leaq	24(%rsp),%rsp
+.Lgmult_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_gcm_gmult_4bit:
+.globl	gcm_ghash_4bit
+.def	gcm_ghash_4bit;	.scl 2;	.type 32;	.endef
+.p2align	4
+gcm_ghash_4bit:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_gcm_ghash_4bit:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$280,%rsp
+.Lghash_prologue:
+	movq	%rdx,%r14
+	movq	%rcx,%r15
+	subq	$-128,%rsi
+	leaq	16+128(%rsp),%rbp
+	xorl	%edx,%edx
+	movq	0+0-128(%rsi),%r8
+	movq	0+8-128(%rsi),%rax
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	16+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	16+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,0(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,0(%rbp)
+	movq	32+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,0-128(%rbp)
+	movq	32+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,1(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,8(%rbp)
+	movq	48+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,8-128(%rbp)
+	movq	48+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,2(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,16(%rbp)
+	movq	64+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,16-128(%rbp)
+	movq	64+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,3(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,24(%rbp)
+	movq	80+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,24-128(%rbp)
+	movq	80+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,4(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,32(%rbp)
+	movq	96+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,32-128(%rbp)
+	movq	96+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,5(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,40(%rbp)
+	movq	112+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,40-128(%rbp)
+	movq	112+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,6(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,48(%rbp)
+	movq	128+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,48-128(%rbp)
+	movq	128+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,7(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,56(%rbp)
+	movq	144+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,56-128(%rbp)
+	movq	144+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,8(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,64(%rbp)
+	movq	160+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,64-128(%rbp)
+	movq	160+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,9(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,72(%rbp)
+	movq	176+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,72-128(%rbp)
+	movq	176+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,10(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,80(%rbp)
+	movq	192+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,80-128(%rbp)
+	movq	192+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,11(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,88(%rbp)
+	movq	208+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,88-128(%rbp)
+	movq	208+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,12(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,96(%rbp)
+	movq	224+0-128(%rsi),%r8
+	shlb	$4,%dl
+	movq	%rax,96-128(%rbp)
+	movq	224+8-128(%rsi),%rax
+	shlq	$60,%r10
+	movb	%dl,13(%rsp)
+	orq	%r10,%rbx
+	movb	%al,%dl
+	shrq	$4,%rax
+	movq	%r8,%r10
+	shrq	$4,%r8
+	movq	%r9,104(%rbp)
+	movq	240+0-128(%rsi),%r9
+	shlb	$4,%dl
+	movq	%rbx,104-128(%rbp)
+	movq	240+8-128(%rsi),%rbx
+	shlq	$60,%r10
+	movb	%dl,14(%rsp)
+	orq	%r10,%rax
+	movb	%bl,%dl
+	shrq	$4,%rbx
+	movq	%r9,%r10
+	shrq	$4,%r9
+	movq	%r8,112(%rbp)
+	shlb	$4,%dl
+	movq	%rax,112-128(%rbp)
+	shlq	$60,%r10
+	movb	%dl,15(%rsp)
+	orq	%r10,%rbx
+	movq	%r9,120(%rbp)
+	movq	%rbx,120-128(%rbp)
+	addq	$-128,%rsi
+	movq	8(%rdi),%r8
+	movq	0(%rdi),%r9
+	addq	%r14,%r15
+	leaq	.Lrem_8bit(%rip),%r11
+	jmp	.Louter_loop
+.p2align	4
+.Louter_loop:
+	xorq	(%r14),%r9
+	movq	8(%r14),%rdx
+	leaq	16(%r14),%r14
+	xorq	%r8,%rdx
+	movq	%r9,(%rdi)
+	movq	%rdx,8(%rdi)
+	shrq	$32,%rdx
+	xorq	%rax,%rax
+	roll	$8,%edx
+	movb	%dl,%al
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	shrl	$4,%ebx
+	roll	$8,%edx
+	movq	8(%rsi,%rax,1),%r8
+	movq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	8(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	0(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	shrl	$4,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r12,2),%r12
+	movzbl	%dl,%ebx
+	shlb	$4,%al
+	movzbq	(%rsp,%rcx,1),%r13
+	shrl	$4,%ebx
+	shlq	$48,%r12
+	xorq	%r8,%r13
+	movq	%r9,%r10
+	xorq	%r12,%r9
+	shrq	$8,%r8
+	movzbq	%r13b,%r13
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rcx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rcx,8),%r9
+	roll	$8,%edx
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	movb	%dl,%al
+	xorq	%r10,%r8
+	movzwq	(%r11,%r13,2),%r13
+	movzbl	%dl,%ecx
+	shlb	$4,%al
+	movzbq	(%rsp,%rbx,1),%r12
+	andl	$240,%ecx
+	shlq	$48,%r13
+	xorq	%r8,%r12
+	movq	%r9,%r10
+	xorq	%r13,%r9
+	shrq	$8,%r8
+	movzbq	%r12b,%r12
+	movl	-4(%rdi),%edx
+	shrq	$8,%r9
+	xorq	-128(%rbp,%rbx,8),%r8
+	shlq	$56,%r10
+	xorq	(%rbp,%rbx,8),%r9
+	movzwq	(%r11,%r12,2),%r12
+	xorq	8(%rsi,%rax,1),%r8
+	xorq	(%rsi,%rax,1),%r9
+	shlq	$48,%r12
+	xorq	%r10,%r8
+	xorq	%r12,%r9
+	movzbq	%r8b,%r13
+	shrq	$4,%r8
+	movq	%r9,%r10
+	shlb	$4,%r13b
+	shrq	$4,%r9
+	xorq	8(%rsi,%rcx,1),%r8
+	movzwq	(%r11,%r13,2),%r13
+	shlq	$60,%r10
+	xorq	(%rsi,%rcx,1),%r9
+	xorq	%r10,%r8
+	shlq	$48,%r13
+	bswapq	%r8
+	xorq	%r13,%r9
+	bswapq	%r9
+	cmpq	%r15,%r14
+	jb	.Louter_loop
+	movq	%r8,8(%rdi)
+	movq	%r9,(%rdi)
+
+	leaq	280(%rsp),%rsi
+	movq	0(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lghash_epilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_gcm_ghash_4bit:
+.globl	gcm_init_clmul
+.def	gcm_init_clmul;	.scl 2;	.type 32;	.endef
+.p2align	4
+gcm_init_clmul:
+	movdqu	(%rdx),%xmm2
+	pshufd	$78,%xmm2,%xmm2
+
+
+	pshufd	$255,%xmm2,%xmm4
+	movdqa	%xmm2,%xmm3
+	psllq	$1,%xmm2
+	pxor	%xmm5,%xmm5
+	psrlq	$63,%xmm3
+	pcmpgtd	%xmm4,%xmm5
+	pslldq	$8,%xmm3
+	por	%xmm3,%xmm2
+
+
+	pand	.L0x1c2_polynomial(%rip),%xmm5
+	pxor	%xmm5,%xmm2
+
+
+	movdqa	%xmm2,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	movdqu	%xmm2,(%rcx)
+	movdqu	%xmm0,16(%rcx)
+	retq
+
+.globl	gcm_gmult_clmul
+.def	gcm_gmult_clmul;	.scl 2;	.type 32;	.endef
+.p2align	4
+gcm_gmult_clmul:
+	movdqu	(%rcx),%xmm0
+	movdqa	.Lbswap_mask(%rip),%xmm5
+	movdqu	(%rdx),%xmm2
+.byte	102,15,56,0,197
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rcx)
+	retq
+
+.globl	gcm_ghash_clmul
+.def	gcm_ghash_clmul;	.scl 2;	.type 32;	.endef
+.p2align	4
+gcm_ghash_clmul:
+.LSEH_begin_gcm_ghash_clmul:
+
+.byte	0x48,0x83,0xec,0x58		
+.byte	0x0f,0x29,0x34,0x24		
+.byte	0x0f,0x29,0x7c,0x24,0x10	
+.byte	0x44,0x0f,0x29,0x44,0x24,0x20	
+.byte	0x44,0x0f,0x29,0x4c,0x24,0x30	
+.byte	0x44,0x0f,0x29,0x54,0x24,0x40	
+	movdqa	.Lbswap_mask(%rip),%xmm5
+
+	movdqu	(%rcx),%xmm0
+	movdqu	(%rdx),%xmm2
+.byte	102,15,56,0,197
+
+	subq	$16,%r9
+	jz	.Lodd_tail
+
+	movdqu	16(%rdx),%xmm8
+
+
+
+
+
+	movdqu	(%r8),%xmm3
+	movdqu	16(%r8),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm6,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,242,0
+.byte	102,15,58,68,250,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm6,%xmm3
+	pxor	%xmm7,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm7
+	pxor	%xmm4,%xmm6
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	leaq	32(%r8),%r8
+	subq	$32,%r9
+	jbe	.Leven_tail
+
+.Lmod_loop:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	movdqu	(%r8),%xmm3
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqu	16(%r8),%xmm6
+.byte	102,15,56,0,221
+.byte	102,15,56,0,245
+
+	movdqa	%xmm6,%xmm7
+	pshufd	$78,%xmm6,%xmm9
+	pshufd	$78,%xmm2,%xmm10
+	pxor	%xmm6,%xmm9
+	pxor	%xmm2,%xmm10
+	pxor	%xmm3,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+.byte	102,15,58,68,242,0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+.byte	102,15,58,68,250,17
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+
+.byte	102,69,15,58,68,202,0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm8,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm8,%xmm4
+
+	pxor	%xmm6,%xmm9
+	pxor	%xmm7,%xmm9
+	movdqa	%xmm9,%xmm10
+	psrldq	$8,%xmm9
+	pslldq	$8,%xmm10
+	pxor	%xmm9,%xmm7
+	pxor	%xmm10,%xmm6
+
+	leaq	32(%r8),%r8
+	subq	$32,%r9
+	ja	.Lmod_loop
+
+.Leven_tail:
+.byte	102,65,15,58,68,192,0
+.byte	102,65,15,58,68,200,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+	pxor	%xmm6,%xmm0
+	pxor	%xmm7,%xmm1
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	testq	%r9,%r9
+	jnz	.Ldone
+
+.Lodd_tail:
+	movdqu	(%r8),%xmm3
+.byte	102,15,56,0,221
+	pxor	%xmm3,%xmm0
+	movdqa	%xmm0,%xmm1
+	pshufd	$78,%xmm0,%xmm3
+	pshufd	$78,%xmm2,%xmm4
+	pxor	%xmm0,%xmm3
+	pxor	%xmm2,%xmm4
+.byte	102,15,58,68,194,0
+.byte	102,15,58,68,202,17
+.byte	102,15,58,68,220,0
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+
+	movdqa	%xmm3,%xmm4
+	psrldq	$8,%xmm3
+	pslldq	$8,%xmm4
+	pxor	%xmm3,%xmm1
+	pxor	%xmm4,%xmm0
+
+	movdqa	%xmm0,%xmm3
+	psllq	$1,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$5,%xmm0
+	pxor	%xmm3,%xmm0
+	psllq	$57,%xmm0
+	movdqa	%xmm0,%xmm4
+	pslldq	$8,%xmm0
+	psrldq	$8,%xmm4
+	pxor	%xmm3,%xmm0
+	pxor	%xmm4,%xmm1
+
+
+	movdqa	%xmm0,%xmm4
+	psrlq	$5,%xmm0
+	pxor	%xmm4,%xmm0
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+	pxor	%xmm1,%xmm4
+	psrlq	$1,%xmm0
+	pxor	%xmm4,%xmm0
+.Ldone:
+.byte	102,15,56,0,197
+	movdqu	%xmm0,(%rcx)
+	movaps	(%rsp),%xmm6
+	movaps	16(%rsp),%xmm7
+	movaps	32(%rsp),%xmm8
+	movaps	48(%rsp),%xmm9
+	movaps	64(%rsp),%xmm10
+	addq	$88,%rsp
+	retq
+.LSEH_end_gcm_ghash_clmul:
+
+.p2align	6
+.Lbswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.L0x1c2_polynomial:
+.byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+.p2align	6
+
+.Lrem_4bit:
+.long	0,0,0,471859200,0,943718400,0,610271232
+.long	0,1887436800,0,1822425088,0,1220542464,0,1423966208
+.long	0,3774873600,0,4246732800,0,3644850176,0,3311403008
+.long	0,2441084928,0,2376073216,0,2847932416,0,3051356160
+
+.Lrem_8bit:
+.value	0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E
+.value	0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E
+.value	0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E
+.value	0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E
+.value	0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E
+.value	0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E
+.value	0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E
+.value	0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E
+.value	0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE
+.value	0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE
+.value	0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE
+.value	0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE
+.value	0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E
+.value	0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E
+.value	0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE
+.value	0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE
+.value	0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E
+.value	0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E
+.value	0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E
+.value	0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E
+.value	0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E
+.value	0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E
+.value	0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E
+.value	0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E
+.value	0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE
+.value	0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE
+.value	0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE
+.value	0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE
+.value	0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E
+.value	0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E
+.value	0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE
+.value	0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE
+
+.byte	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
+
+.def	se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lin_prologue
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lin_prologue
+
+	leaq	24(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+
+.Lin_prologue:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_gcm_gmult_4bit
+.rva	.LSEH_end_gcm_gmult_4bit
+.rva	.LSEH_info_gcm_gmult_4bit
+
+.rva	.LSEH_begin_gcm_ghash_4bit
+.rva	.LSEH_end_gcm_ghash_4bit
+.rva	.LSEH_info_gcm_ghash_4bit
+
+.rva	.LSEH_begin_gcm_ghash_clmul
+.rva	.LSEH_end_gcm_ghash_clmul
+.rva	.LSEH_info_gcm_ghash_clmul
+
+.section	.xdata
+.p2align	3
+.LSEH_info_gcm_gmult_4bit:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lgmult_prologue,.Lgmult_epilogue	
+.LSEH_info_gcm_ghash_4bit:
+.byte	9,0,0,0
+.rva	se_handler
+.rva	.Lghash_prologue,.Lghash_epilogue	
+.LSEH_info_gcm_ghash_clmul:
+.byte	0x01,0x1f,0x0b,0x00
+.byte	0x1f,0xa8,0x04,0x00	
+.byte	0x19,0x98,0x03,0x00	
+.byte	0x13,0x88,0x02,0x00	
+.byte	0x0d,0x78,0x01,0x00	
+.byte	0x08,0x68,0x00,0x00	
+.byte	0x04,0xa2,0x00,0x00	
diff --git a/crypto/modes/modes_local.h b/crypto/modes/modes_local.h
new file mode 100644
index 0000000..852ba19
--- /dev/null
+++ b/crypto/modes/modes_local.h
@@ -0,0 +1,123 @@
+/* $OpenBSD: modes_local.h,v 1.2 2023/07/08 14:55:36 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use is governed by OpenSSL license.
+ * ====================================================================
+ */
+
+#include 
+
+#include 
+
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+#if defined(_LP64)
+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;
+
+#if !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__))
+#  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(__arm__) || defined(__arm)) && !defined(__STRICT_ALIGNMENT)
+#  if (__ARM_ARCH >= 6)
+#  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
+# endif
+#endif
+#endif
+
+#if defined(BSWAP4) && !defined(__STRICT_ALIGNMENT)
+#define GETU32(p)	BSWAP4(*(const u32 *)(p))
+#define PUTU32(p,v)	*(u32 *)(p) = BSWAP4(v)
+#else
+#define GETU32(p)	((u32)(p)[0]<<24|(u32)(p)[1]<<16|(u32)(p)[2]<<8|(u32)(p)[3])
+#define PUTU32(p,v)	((p)[0]=(u8)((v)>>24),(p)[1]=(u8)((v)>>16),(p)[2]=(u8)((v)>>8),(p)[3]=(u8)(v))
+#endif
+
+/* GCM definitions */
+
+typedef struct {
+	u64 hi, lo;
+} u128;
+
+#ifdef	TABLE_BITS
+#undef	TABLE_BITS
+#endif
+/*
+ * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
+ * never be set to 8 [or 1]. For further information see gcm128.c.
+ */
+#define	TABLE_BITS 4
+
+struct gcm128_context {
+	/* Following 6 names follow names in GCM specification */
+	union {
+		u64 u[2];
+		u32 d[4];
+		u8 c[16];
+		size_t t[16/sizeof(size_t)];
+	} Yi, EKi, EK0, len, Xi, H;
+	/* Relative position of Xi, H and pre-computed Htable is used
+	 * in some assembler modules, i.e. don't change the order! */
+#if TABLE_BITS==8
+	u128 Htable[256];
+#else
+	u128 Htable[16];
+	void (*gmult)(u64 Xi[2], const u128 Htable[16]);
+	void (*ghash)(u64 Xi[2], const u128 Htable[16], const u8 *inp,
+	    size_t len);
+#endif
+	unsigned int mres, ares;
+	block128_f block;
+	void *key;
+};
+
+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;
+};
+
+__END_HIDDEN_DECLS
diff --git a/crypto/modes/ofb128.c b/crypto/modes/ofb128.c
new file mode 100644
index 0000000..42afd29
--- /dev/null
+++ b/crypto/modes/ofb128.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: ofb128.c,v 1.7 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include "modes_local.h"
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+/* The input and output encrypted as though 128bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 128bit block we have used is contained in *num;
+ */
+void
+CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out,
+    size_t len, const void *key,
+    unsigned char ivec[16], int *num,
+    block128_f block)
+{
+	unsigned int n;
+	size_t l = 0;
+
+	n = *num;
+
+#if !defined(OPENSSL_SMALL_FOOTPRINT)
+	if (16 % sizeof(size_t) == 0)
+		do { /* always true actually */
+			while (n && len) {
+				*(out++) = *(in++) ^ ivec[n];
+				--len;
+				n = (n + 1) % 16;
+			}
+#ifdef __STRICT_ALIGNMENT
+			if (((size_t)in|(size_t)out|(size_t)ivec) %
+			    sizeof(size_t) != 0)
+				break;
+#endif
+			while (len >= 16) {
+				(*block)(ivec, ivec, key);
+				for (; n < 16; n += sizeof(size_t))
+					*(size_t *)(out + n) =
+					    *(size_t *)(in + n) ^ *(size_t *)(ivec +
+					    n);
+				len -= 16;
+				out += 16;
+				in += 16;
+				n = 0;
+			}
+			if (len) {
+				(*block)(ivec, ivec, key);
+				while (len--) {
+					out[n] = in[n] ^ ivec[n];
+					++n;
+				}
+			}
+			*num = n;
+			return;
+		} while (0);
+	/* the rest would be commonly eliminated by x86* compiler */
+#endif
+	while (l < len) {
+		if (n == 0) {
+			(*block)(ivec, ivec, key);
+		}
+		out[l] = in[l] ^ ivec[n];
+		++l;
+		n = (n + 1) % 16;
+	}
+
+	*num = n;
+}
+LCRYPTO_ALIAS(CRYPTO_ofb128_encrypt);
diff --git a/crypto/modes/xts128.c b/crypto/modes/xts128.c
new file mode 100644
index 0000000..7516acf
--- /dev/null
+++ b/crypto/modes/xts128.c
@@ -0,0 +1,197 @@
+/* $OpenBSD: xts128.c,v 1.12 2023/07/08 14:56:54 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include "modes_local.h"
+
+#include 
+#include 
+
+#ifndef MODES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
+
+int
+CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16],
+    const unsigned char *inp, unsigned char *out,
+    size_t len, int enc)
+{
+	union {
+		u64 u[2];
+		u32 d[4];
+		u8 c[16];
+	} tweak, scratch;
+	unsigned int i;
+
+	if (len < 16)
+		return -1;
+
+	memcpy(tweak.c, iv, 16);
+
+	(*ctx->block2)(tweak.c, tweak.c, ctx->key2);
+
+	if (!enc && (len % 16))
+		len -= 16;
+
+	while (len >= 16) {
+#ifdef __STRICT_ALIGNMENT
+		memcpy(scratch.c, inp, 16);
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+#else
+		scratch.u[0] = ((u64 *)inp)[0] ^ tweak.u[0];
+		scratch.u[1] = ((u64 *)inp)[1] ^ tweak.u[1];
+#endif
+		(*ctx->block1)(scratch.c, scratch.c, ctx->key1);
+#ifdef __STRICT_ALIGNMENT
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+		memcpy(out, scratch.c, 16);
+#else
+		((u64 *)out)[0] = scratch.u[0] ^= tweak.u[0];
+		((u64 *)out)[1] = scratch.u[1] ^= tweak.u[1];
+#endif
+		inp += 16;
+		out += 16;
+		len -= 16;
+
+		if (len == 0)
+			return 0;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+		unsigned int carry, res;
+
+		res = 0x87 & (((int)tweak.d[3]) >> 31);
+		carry = (unsigned int)(tweak.u[0] >> 63);
+		tweak.u[0] = (tweak.u[0] << 1) ^ res;
+		tweak.u[1] = (tweak.u[1] << 1)|carry;
+#else /* BIG_ENDIAN */
+		size_t c;
+
+		for (c = 0, i = 0; i < 16; ++i) {
+			/*+ substitutes for |, because c is 1 bit */
+			c += ((size_t)tweak.c[i]) << 1;
+			tweak.c[i] = (u8)c;
+			c = c >> 8;
+		}
+		tweak.c[0] ^= (u8)(0x87 & (0 - c));
+#endif
+	}
+	if (enc) {
+		for (i = 0; i < len; ++i) {
+			u8 ch = inp[i];
+			out[i] = scratch.c[i];
+			scratch.c[i] = ch;
+		}
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+		(*ctx->block1)(scratch.c, scratch.c, ctx->key1);
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+		memcpy(out - 16, scratch.c, 16);
+	} else {
+		union {
+			u64 u[2];
+			u8 c[16];
+		} tweak1;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+		unsigned int carry, res;
+
+		res = 0x87 & (((int)tweak.d[3]) >> 31);
+		carry = (unsigned int)(tweak.u[0] >> 63);
+		tweak1.u[0] = (tweak.u[0] << 1) ^ res;
+		tweak1.u[1] = (tweak.u[1] << 1)|carry;
+#else
+		size_t c;
+
+		for (c = 0, i = 0; i < 16; ++i) {
+			/*+ substitutes for |, because c is 1 bit */
+			c += ((size_t)tweak.c[i]) << 1;
+			tweak1.c[i] = (u8)c;
+			c = c >> 8;
+		}
+		tweak1.c[0] ^= (u8)(0x87 & (0 - c));
+#endif
+#ifdef __STRICT_ALIGNMENT
+		memcpy(scratch.c, inp, 16);
+		scratch.u[0] ^= tweak1.u[0];
+		scratch.u[1] ^= tweak1.u[1];
+#else
+		scratch.u[0] = ((u64 *)inp)[0] ^ tweak1.u[0];
+		scratch.u[1] = ((u64 *)inp)[1] ^ tweak1.u[1];
+#endif
+		(*ctx->block1)(scratch.c, scratch.c, ctx->key1);
+		scratch.u[0] ^= tweak1.u[0];
+		scratch.u[1] ^= tweak1.u[1];
+
+		for (i = 0; i < len; ++i) {
+			u8 ch = inp[16 + i];
+			out[16 + i] = scratch.c[i];
+			scratch.c[i] = ch;
+		}
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+		(*ctx->block1)(scratch.c, scratch.c, ctx->key1);
+#ifdef __STRICT_ALIGNMENT
+		scratch.u[0] ^= tweak.u[0];
+		scratch.u[1] ^= tweak.u[1];
+		memcpy(out, scratch.c, 16);
+#else
+		((u64 *)out)[0] = scratch.u[0] ^ tweak.u[0];
+		((u64 *)out)[1] = scratch.u[1] ^ tweak.u[1];
+#endif
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(CRYPTO_xts128_encrypt);
diff --git a/crypto/o_fips.c b/crypto/o_fips.c
new file mode 100644
index 0000000..b1487e3
--- /dev/null
+++ b/crypto/o_fips.c
@@ -0,0 +1,76 @@
+/* $OpenBSD: o_fips.c,v 1.6 2021/10/23 13:57:00 schwarze Exp $ */
+/* Written by Stephen Henson (steve@openssl.org) for the OpenSSL
+ * project 2011.
+ */
+/* ====================================================================
+ * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include "cryptlib.h"
+
+int
+FIPS_mode(void)
+{
+	return 0;
+}
+
+int
+FIPS_mode_set(int r)
+{
+	if (r == 0)
+		return 1;
+	CRYPTOerror(CRYPTO_R_FIPS_MODE_NOT_SUPPORTED);
+	return 0;
+}
diff --git a/crypto/o_init.c b/crypto/o_init.c
new file mode 100644
index 0000000..2f819ea
--- /dev/null
+++ b/crypto/o_init.c
@@ -0,0 +1,10 @@
+/* $OpenBSD: o_init.c,v 1.8 2014/06/12 15:49:27 deraadt Exp $ */
+/* Ted Unangst places this file in the public domain. */
+
+#include 
+
+void
+OPENSSL_init(void)
+{
+
+}
diff --git a/crypto/o_str.c b/crypto/o_str.c
new file mode 100644
index 0000000..f05889e
--- /dev/null
+++ b/crypto/o_str.c
@@ -0,0 +1,21 @@
+/* $OpenBSD: o_str.c,v 1.9 2014/07/09 20:22:14 tedu Exp $ */
+/*
+ * Written by Theo de Raadt.  Public domain.
+ */
+
+#include 
+
+int OPENSSL_strcasecmp(const char *str1, const char *str2);
+int OPENSSL_strncasecmp(const char *str1, const char *str2, size_t n);
+
+int
+OPENSSL_strncasecmp(const char *str1, const char *str2, size_t n)
+{
+	return strncasecmp(str1, str2, n);
+}
+
+int
+OPENSSL_strcasecmp(const char *str1, const char *str2)
+{
+	return strcasecmp(str1, str2);
+}
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
new file mode 100644
index 0000000..48b95d6
--- /dev/null
+++ b/crypto/objects/o_names.c
@@ -0,0 +1,363 @@
+/* $OpenBSD: o_names.c,v 1.24 2023/07/08 12:27:51 beck Exp $ */
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* 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.
+ */
+DECLARE_LHASH_OF(OBJ_NAME);
+static LHASH_OF(OBJ_NAME) *names_lh = NULL;
+static int names_type_num = OBJ_NAME_TYPE_NUM;
+
+typedef struct name_funcs_st {
+	unsigned long (*hash_func)(const char *name);
+	int (*cmp_func)(const char *a, const char *b);
+	void (*free_func)(const char *, int, const char *);
+} NAME_FUNCS;
+
+DECLARE_STACK_OF(NAME_FUNCS)
+
+static STACK_OF(NAME_FUNCS) *name_funcs_stack;
+
+/* The LHASH callbacks now use the raw "void *" prototypes and do per-variable
+ * casting in the functions. This prevents function pointer casting without the
+ * need for macro-generated wrapper functions. */
+
+/* static unsigned long obj_name_hash(OBJ_NAME *a); */
+static unsigned long obj_name_hash(const void *a_void);
+/* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
+static int obj_name_cmp(const void *a_void, const void *b_void);
+
+static IMPLEMENT_LHASH_HASH_FN(obj_name, OBJ_NAME)
+static IMPLEMENT_LHASH_COMP_FN(obj_name, OBJ_NAME)
+
+int
+OBJ_NAME_init(void)
+{
+	if (names_lh != NULL)
+		return (1);
+	names_lh = lh_OBJ_NAME_new();
+	return (names_lh != NULL);
+}
+LCRYPTO_ALIAS(OBJ_NAME_init);
+
+int
+OBJ_NAME_new_index(unsigned long (*hash_func)(const char *),
+    int (*cmp_func)(const char *, const char *),
+    void (*free_func)(const char *, int, const char *))
+{
+	int ret;
+	int i;
+	NAME_FUNCS *name_funcs;
+
+	if (name_funcs_stack == NULL)
+		name_funcs_stack = sk_NAME_FUNCS_new_null();
+	if (name_funcs_stack == NULL)
+		return (0);
+
+	ret = names_type_num;
+	names_type_num++;
+	for (i = sk_NAME_FUNCS_num(name_funcs_stack); i < names_type_num; i++) {
+		name_funcs = malloc(sizeof(NAME_FUNCS));
+		if (!name_funcs) {
+			OBJerror(ERR_R_MALLOC_FAILURE);
+			return (0);
+		}
+		name_funcs->hash_func = lh_strhash;
+		name_funcs->cmp_func = strcmp;
+		name_funcs->free_func = NULL;
+		if (sk_NAME_FUNCS_push(name_funcs_stack, name_funcs) == 0) {
+			free(name_funcs);
+			OBJerror(ERR_R_MALLOC_FAILURE);
+			return (0);
+		}
+	}
+	name_funcs = sk_NAME_FUNCS_value(name_funcs_stack, ret);
+	if (hash_func != NULL)
+		name_funcs->hash_func = hash_func;
+	if (cmp_func != NULL)
+		name_funcs->cmp_func = cmp_func;
+	if (free_func != NULL)
+		name_funcs->free_func = free_func;
+	return (ret);
+}
+LCRYPTO_ALIAS(OBJ_NAME_new_index);
+
+/* static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b) */
+static int
+obj_name_cmp(const void *a_void, const void *b_void)
+{
+	int ret;
+	const OBJ_NAME *a = (const OBJ_NAME *)a_void;
+	const OBJ_NAME *b = (const OBJ_NAME *)b_void;
+
+	ret = a->type - b->type;
+	if (ret == 0) {
+		if ((name_funcs_stack != NULL) &&
+		    (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) {
+			ret = sk_NAME_FUNCS_value(name_funcs_stack,
+			    a->type)->cmp_func(a->name, b->name);
+		} else
+			ret = strcmp(a->name, b->name);
+	}
+	return (ret);
+}
+
+/* static unsigned long obj_name_hash(OBJ_NAME *a) */
+static unsigned long
+obj_name_hash(const void *a_void)
+{
+	unsigned long ret;
+	const OBJ_NAME *a = (const OBJ_NAME *)a_void;
+
+	if ((name_funcs_stack != NULL) &&
+	    (sk_NAME_FUNCS_num(name_funcs_stack) > a->type)) {
+		ret = sk_NAME_FUNCS_value(name_funcs_stack,
+		    a->type)->hash_func(a->name);
+	} else {
+		ret = lh_strhash(a->name);
+	}
+	ret ^= a->type;
+	return (ret);
+}
+
+const char *
+OBJ_NAME_get(const char *name, int type)
+{
+	OBJ_NAME on, *ret;
+	int num = 0, alias;
+
+	if (name == NULL)
+		return (NULL);
+	if ((names_lh == NULL) && !OBJ_NAME_init())
+		return (NULL);
+
+	alias = type&OBJ_NAME_ALIAS;
+	type&= ~OBJ_NAME_ALIAS;
+
+	on.name = name;
+	on.type = type;
+
+	for (;;) {
+		ret = lh_OBJ_NAME_retrieve(names_lh, &on);
+		if (ret == NULL)
+			return (NULL);
+		if ((ret->alias) && !alias) {
+			if (++num > 10)
+				return (NULL);
+			on.name = ret->data;
+		} else {
+			return (ret->data);
+		}
+	}
+}
+LCRYPTO_ALIAS(OBJ_NAME_get);
+
+int
+OBJ_NAME_add(const char *name, int type, const char *data)
+{
+	OBJ_NAME *onp, *ret;
+	int alias;
+
+	if ((names_lh == NULL) && !OBJ_NAME_init())
+		return (0);
+
+	alias = type & OBJ_NAME_ALIAS;
+	type &= ~OBJ_NAME_ALIAS;
+
+	onp = malloc(sizeof(OBJ_NAME));
+	if (onp == NULL) {
+		/* ERROR */
+		return (0);
+	}
+
+	onp->name = name;
+	onp->alias = alias;
+	onp->type = type;
+	onp->data = data;
+
+	ret = lh_OBJ_NAME_insert(names_lh, onp);
+	if (ret != NULL) {
+		/* free things */
+		if ((name_funcs_stack != NULL) &&
+		    (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) {
+			/* XXX: I'm not sure I understand why the free
+			 * function should get three arguments...
+			 * -- Richard Levitte
+			 */
+			sk_NAME_FUNCS_value(
+			    name_funcs_stack, ret->type)->free_func(
+			    ret->name, ret->type, ret->data);
+		}
+		free(ret);
+	} else {
+		if (lh_OBJ_NAME_error(names_lh)) {
+			free(onp);
+			/* ERROR */
+			return (0);
+		}
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(OBJ_NAME_add);
+
+int
+OBJ_NAME_remove(const char *name, int type)
+{
+	OBJ_NAME on, *ret;
+
+	if (names_lh == NULL)
+		return (0);
+
+	type &= ~OBJ_NAME_ALIAS;
+	on.name = name;
+	on.type = type;
+	ret = lh_OBJ_NAME_delete(names_lh, &on);
+	if (ret != NULL) {
+		/* free things */
+		if ((name_funcs_stack != NULL) &&
+		    (sk_NAME_FUNCS_num(name_funcs_stack) > ret->type)) {
+			/* XXX: I'm not sure I understand why the free
+			 * function should get three arguments...
+			 * -- Richard Levitte
+			 */
+			sk_NAME_FUNCS_value(
+			    name_funcs_stack, ret->type)->free_func(
+			    ret->name, ret->type, ret->data);
+		}
+		free(ret);
+		return (1);
+	} else
+		return (0);
+}
+LCRYPTO_ALIAS(OBJ_NAME_remove);
+
+struct doall {
+	int type;
+	void (*fn)(const OBJ_NAME *, void *arg);
+	void *arg;
+};
+
+static void
+do_all_fn_doall_arg(const OBJ_NAME *name, struct doall *d)
+{
+	if (name->type == d->type)
+		d->fn(name, d->arg);
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall)
+
+void
+OBJ_NAME_do_all(int type, void (*fn)(const OBJ_NAME *, void *arg), void *arg)
+{
+	struct doall d;
+
+	d.type = type;
+	d.fn = fn;
+	d.arg = arg;
+
+	lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn),
+	    struct doall, &d);
+}
+LCRYPTO_ALIAS(OBJ_NAME_do_all);
+
+struct doall_sorted {
+	int type;
+	int n;
+	const OBJ_NAME **names;
+};
+
+static void
+do_all_sorted_fn(const OBJ_NAME *name, void *d_)
+{
+	struct doall_sorted *d = d_;
+
+	if (name->type != d->type)
+		return;
+
+	d->names[d->n++] = name;
+}
+
+static int
+do_all_sorted_cmp(const void *n1_, const void *n2_)
+{
+	const OBJ_NAME * const *n1 = n1_;
+	const OBJ_NAME * const *n2 = n2_;
+
+	return strcmp((*n1)->name, (*n2)->name);
+}
+
+void
+OBJ_NAME_do_all_sorted(int type, void (*fn)(const OBJ_NAME *, void *arg),
+    void *arg)
+{
+	struct doall_sorted d;
+	int n;
+
+	d.type = type;
+	d.names = reallocarray(NULL, lh_OBJ_NAME_num_items(names_lh),
+	    sizeof *d.names);
+	d.n = 0;
+	if (d.names != NULL) {
+		OBJ_NAME_do_all(type, do_all_sorted_fn, &d);
+
+		qsort((void *)d.names, d.n, sizeof *d.names, do_all_sorted_cmp);
+
+		for (n = 0; n < d.n; ++n)
+			fn(d.names[n], arg);
+
+		free(d.names);
+	}
+}
+LCRYPTO_ALIAS(OBJ_NAME_do_all_sorted);
+
+static int free_type;
+
+static void
+names_lh_free_doall(OBJ_NAME *onp)
+{
+	if (onp == NULL)
+		return;
+
+	if (free_type < 0 || free_type == onp->type)
+		OBJ_NAME_remove(onp->name, onp->type);
+}
+
+static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME)
+
+static void
+name_funcs_free(NAME_FUNCS *ptr)
+{
+	free(ptr);
+}
+
+void
+OBJ_NAME_cleanup(int type)
+{
+	unsigned long down_load;
+
+	if (names_lh == NULL)
+		return;
+
+	free_type = type;
+	down_load = lh_OBJ_NAME_down_load(names_lh);
+	lh_OBJ_NAME_down_load(names_lh) = 0;
+
+	lh_OBJ_NAME_doall(names_lh, LHASH_DOALL_FN(names_lh_free));
+	if (type < 0) {
+		lh_OBJ_NAME_free(names_lh);
+		sk_NAME_FUNCS_pop_free(name_funcs_stack, name_funcs_free);
+		names_lh = NULL;
+		name_funcs_stack = NULL;
+	} else
+		lh_OBJ_NAME_down_load(names_lh) = down_load;
+}
+LCRYPTO_ALIAS(OBJ_NAME_cleanup);
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
new file mode 100644
index 0000000..6cfbf8f
--- /dev/null
+++ b/crypto/objects/obj_dat.c
@@ -0,0 +1,698 @@
+/* $OpenBSD: obj_dat.c,v 1.61 2023/09/05 14:59:00 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+/* obj_dat.h is generated from objects.h by obj_dat.pl */
+#include "obj_dat.h"
+
+static int sn_cmp_BSEARCH_CMP_FN(const void *, const void *);
+static int sn_cmp(const ASN1_OBJECT * const *, unsigned int const *);
+static unsigned int *OBJ_bsearch_sn(const ASN1_OBJECT * *key, unsigned int const *base, int num);
+static int ln_cmp_BSEARCH_CMP_FN(const void *, const void *);
+static int ln_cmp(const ASN1_OBJECT * const *, unsigned int const *);
+static unsigned int *OBJ_bsearch_ln(const ASN1_OBJECT * *key, unsigned int const *base, int num);
+static int obj_cmp_BSEARCH_CMP_FN(const void *, const void *);
+static int obj_cmp(const ASN1_OBJECT * const *, unsigned int const *);
+static unsigned int *OBJ_bsearch_obj(const ASN1_OBJECT * *key, unsigned int const *base, int num);
+
+#define ADDED_DATA	0
+#define ADDED_SNAME	1
+#define ADDED_LNAME	2
+#define ADDED_NID	3
+
+typedef struct added_obj_st {
+	int type;
+	ASN1_OBJECT *obj;
+} ADDED_OBJ;
+DECLARE_LHASH_OF(ADDED_OBJ);
+
+static int new_nid = NUM_NID;
+static LHASH_OF(ADDED_OBJ) *added = NULL;
+
+static int sn_cmp(const ASN1_OBJECT * const *a, const unsigned int *b)
+{
+	return (strcmp((*a)->sn, nid_objs[*b].sn));
+}
+
+
+static int
+sn_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
+{
+	const ASN1_OBJECT * const *a = a_;
+	unsigned int const *b = b_;
+	return sn_cmp(a, b);
+}
+
+static unsigned int *
+OBJ_bsearch_sn(const ASN1_OBJECT * *key, unsigned int const *base, int num)
+{
+	return (unsigned int *)OBJ_bsearch_(key, base, num, sizeof(unsigned int),
+	    sn_cmp_BSEARCH_CMP_FN);
+}
+
+static int ln_cmp(const ASN1_OBJECT * const *a, const unsigned int *b)
+{
+	return (strcmp((*a)->ln, nid_objs[*b].ln));
+}
+
+
+static int
+ln_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
+{
+	const ASN1_OBJECT * const *a = a_;
+	unsigned int const *b = b_;
+	return ln_cmp(a, b);
+}
+
+static unsigned int *
+OBJ_bsearch_ln(const ASN1_OBJECT * *key, unsigned int const *base, int num)
+{
+	return (unsigned int *)OBJ_bsearch_(key, base, num, sizeof(unsigned int),
+	    ln_cmp_BSEARCH_CMP_FN);
+}
+
+static unsigned long
+added_obj_hash(const ADDED_OBJ *ca)
+{
+	const ASN1_OBJECT *a;
+	int i;
+	unsigned long ret = 0;
+	unsigned char *p;
+
+	a = ca->obj;
+	switch (ca->type) {
+	case ADDED_DATA:
+		ret = a->length << 20L;
+		p = (unsigned char *)a->data;
+		for (i = 0; i < a->length; i++)
+			ret ^= p[i] << ((i * 3) % 24);
+		break;
+	case ADDED_SNAME:
+		ret = lh_strhash(a->sn);
+		break;
+	case ADDED_LNAME:
+		ret = lh_strhash(a->ln);
+		break;
+	case ADDED_NID:
+		ret = a->nid;
+		break;
+	default:
+		return 0;
+	}
+	ret &= 0x3fffffffL;
+	ret |= ca->type << 30L;
+	return (ret);
+}
+static IMPLEMENT_LHASH_HASH_FN(added_obj, ADDED_OBJ)
+
+static int
+added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
+{
+	const ASN1_OBJECT *a, *b;
+	int cmp;
+
+	if ((cmp = ca->type - cb->type) != 0)
+		return cmp;
+
+	a = ca->obj;
+	b = cb->obj;
+	switch (ca->type) {
+	case ADDED_DATA:
+		return OBJ_cmp(a, b);
+	case ADDED_SNAME:
+		if (a->sn == NULL)
+			return -1;
+		if (b->sn == NULL)
+			return 1;
+		return strcmp(a->sn, b->sn);
+	case ADDED_LNAME:
+		if (a->ln == NULL)
+			return -1;
+		if (b->ln == NULL)
+			return 1;
+		return strcmp(a->ln, b->ln);
+	case ADDED_NID:
+		return a->nid - b->nid;
+	default:
+		return 0;
+	}
+}
+static IMPLEMENT_LHASH_COMP_FN(added_obj, ADDED_OBJ)
+
+static void
+cleanup1_doall(ADDED_OBJ *a)
+{
+	a->obj->nid = 0;
+	a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC |
+	    ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+	    ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+}
+
+static void cleanup2_doall(ADDED_OBJ *a)
+{
+	a->obj->nid++;
+}
+
+static void
+cleanup3_doall(ADDED_OBJ *a)
+{
+	if (--a->obj->nid == 0)
+		ASN1_OBJECT_free(a->obj);
+	free(a);
+}
+
+static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ)
+static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ)
+static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ)
+
+/* The purpose of obj_cleanup_defer is to avoid EVP_cleanup() attempting
+ * to use freed up OIDs. If necessary the actual freeing up of OIDs is
+ * delayed.
+ */
+
+int obj_cleanup_defer = 0;
+
+void
+check_defer(int nid)
+{
+	if (!obj_cleanup_defer && nid >= NUM_NID)
+		obj_cleanup_defer = 1;
+}
+
+void
+OBJ_cleanup(void)
+{
+	if (obj_cleanup_defer) {
+		obj_cleanup_defer = 2;
+		return;
+	}
+	if (added == NULL)
+		return;
+	lh_ADDED_OBJ_down_load(added) = 0;
+	lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup1)); /* zero counters */
+	lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup2)); /* set counters */
+	lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup3)); /* free objects */
+	lh_ADDED_OBJ_free(added);
+	added = NULL;
+}
+LCRYPTO_ALIAS(OBJ_cleanup);
+
+int
+OBJ_new_nid(int num)
+{
+	int i;
+
+	i = new_nid;
+	new_nid += num;
+	return (i);
+}
+LCRYPTO_ALIAS(OBJ_new_nid);
+
+int
+OBJ_add_object(const ASN1_OBJECT *obj)
+{
+	ASN1_OBJECT *o = NULL;
+	ADDED_OBJ *ao[4] = {NULL, NULL, NULL, NULL}, *aop;
+	int i;
+
+	if (added == NULL)
+		added = lh_ADDED_OBJ_new();
+	if (added == NULL)
+		goto err;
+	if (obj == NULL || obj->nid == NID_undef)
+		goto err;
+	if ((o = OBJ_dup(obj)) == NULL)
+		goto err;
+	if (!(ao[ADDED_NID] = malloc(sizeof(ADDED_OBJ))))
+		goto err2;
+	if ((o->length != 0) && (obj->data != NULL))
+		if (!(ao[ADDED_DATA] = malloc(sizeof(ADDED_OBJ))))
+			goto err2;
+	if (o->sn != NULL)
+		if (!(ao[ADDED_SNAME] = malloc(sizeof(ADDED_OBJ))))
+			goto err2;
+	if (o->ln != NULL)
+		if (!(ao[ADDED_LNAME] = malloc(sizeof(ADDED_OBJ))))
+			goto err2;
+
+	for (i = ADDED_DATA; i <= ADDED_NID; i++) {
+		if (ao[i] != NULL) {
+			ao[i]->type = i;
+			ao[i]->obj = o;
+			aop = lh_ADDED_OBJ_insert(added, ao[i]);
+			/* memory leak, but should not normally matter */
+			free(aop);
+		}
+	}
+	o->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC |
+	    ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+	    ASN1_OBJECT_FLAG_DYNAMIC_DATA);
+
+	return (o->nid);
+
+ err2:
+	OBJerror(ERR_R_MALLOC_FAILURE);
+ err:
+	for (i = ADDED_DATA; i <= ADDED_NID; i++)
+		free(ao[i]);
+	ASN1_OBJECT_free(o);
+	return (NID_undef);
+}
+LCRYPTO_ALIAS(OBJ_add_object);
+
+ASN1_OBJECT *
+OBJ_nid2obj(int n)
+{
+	ADDED_OBJ ad, *adp;
+	ASN1_OBJECT ob;
+
+	if ((n >= 0) && (n < NUM_NID)) {
+		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
+			OBJerror(OBJ_R_UNKNOWN_NID);
+			return (NULL);
+		}
+		return ((ASN1_OBJECT *)&(nid_objs[n]));
+	} 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);
+		else {
+			OBJerror(OBJ_R_UNKNOWN_NID);
+			return (NULL);
+		}
+	}
+}
+LCRYPTO_ALIAS(OBJ_nid2obj);
+
+const char *
+OBJ_nid2sn(int n)
+{
+	ADDED_OBJ ad, *adp;
+	ASN1_OBJECT ob;
+
+	if ((n >= 0) && (n < NUM_NID)) {
+		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
+			OBJerror(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 {
+			OBJerror(OBJ_R_UNKNOWN_NID);
+			return (NULL);
+		}
+	}
+}
+LCRYPTO_ALIAS(OBJ_nid2sn);
+
+const char *
+OBJ_nid2ln(int n)
+{
+	ADDED_OBJ ad, *adp;
+	ASN1_OBJECT ob;
+
+	if ((n >= 0) && (n < NUM_NID)) {
+		if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
+			OBJerror(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 {
+			OBJerror(OBJ_R_UNKNOWN_NID);
+			return (NULL);
+		}
+	}
+}
+LCRYPTO_ALIAS(OBJ_nid2ln);
+
+static int
+obj_cmp(const ASN1_OBJECT * const *ap, const unsigned int *bp)
+{
+	const ASN1_OBJECT *a = *ap;
+	const ASN1_OBJECT *b = &nid_objs[*bp];
+
+	return OBJ_cmp(a, b);
+}
+
+static int
+obj_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
+{
+	const ASN1_OBJECT * const *a = a_;
+	unsigned int const *b = b_;
+	return obj_cmp(a, b);
+}
+
+static unsigned int *
+OBJ_bsearch_obj(const ASN1_OBJECT * *key, unsigned int const *base, int num)
+{
+	return (unsigned int *)OBJ_bsearch_(key, base, num, sizeof(unsigned int),
+	    obj_cmp_BSEARCH_CMP_FN);
+}
+
+int
+OBJ_obj2nid(const ASN1_OBJECT *a)
+{
+	const unsigned int *op;
+	ADDED_OBJ ad, *adp;
+
+	if (a == NULL || a->length == 0)
+		return (NID_undef);
+	if (a->nid != NID_undef)
+		return (a->nid);
+
+	if (added != NULL) {
+		ad.type = ADDED_DATA;
+		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
+		adp = lh_ADDED_OBJ_retrieve(added, &ad);
+		if (adp != NULL)
+			return (adp->obj->nid);
+	}
+	op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
+	if (op == NULL)
+		return (NID_undef);
+	return (nid_objs[*op].nid);
+}
+LCRYPTO_ALIAS(OBJ_obj2nid);
+
+/* Convert an object name into an ASN1_OBJECT
+ * if "noname" is not set then search for short and long names first.
+ * This will convert the "dotted" form into an object: unlike OBJ_txt2nid
+ * it can be used with any objects, not just registered ones.
+ */
+
+ASN1_OBJECT *
+OBJ_txt2obj(const char *s, int no_name)
+{
+	int nid;
+
+	if (!no_name) {
+		if (((nid = OBJ_sn2nid(s)) != NID_undef) ||
+		    ((nid = OBJ_ln2nid(s)) != NID_undef) )
+			return OBJ_nid2obj(nid);
+	}
+
+	return t2i_ASN1_OBJECT_internal(s);
+}
+LCRYPTO_ALIAS(OBJ_txt2obj);
+
+int
+OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *aobj, int no_name)
+{
+	return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, no_name);
+}
+LCRYPTO_ALIAS(OBJ_obj2txt);
+
+int
+OBJ_txt2nid(const char *s)
+{
+	ASN1_OBJECT *obj;
+	int nid;
+
+	obj = OBJ_txt2obj(s, 0);
+	nid = OBJ_obj2nid(obj);
+	ASN1_OBJECT_free(obj);
+	return nid;
+}
+LCRYPTO_ALIAS(OBJ_txt2nid);
+
+int
+OBJ_ln2nid(const char *s)
+{
+	ASN1_OBJECT o;
+	const ASN1_OBJECT *oo = &o;
+	ADDED_OBJ ad, *adp;
+	const unsigned int *op;
+
+	o.ln = s;
+	if (added != NULL) {
+		ad.type = ADDED_LNAME;
+		ad.obj = &o;
+		adp = lh_ADDED_OBJ_retrieve(added, &ad);
+		if (adp != NULL)
+			return (adp->obj->nid);
+	}
+	op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
+	if (op == NULL)
+		return (NID_undef);
+	return (nid_objs[*op].nid);
+}
+LCRYPTO_ALIAS(OBJ_ln2nid);
+
+int
+OBJ_sn2nid(const char *s)
+{
+	ASN1_OBJECT o;
+	const ASN1_OBJECT *oo = &o;
+	ADDED_OBJ ad, *adp;
+	const unsigned int *op;
+
+	o.sn = s;
+	if (added != NULL) {
+		ad.type = ADDED_SNAME;
+		ad.obj = &o;
+		adp = lh_ADDED_OBJ_retrieve(added, &ad);
+		if (adp != NULL)
+			return (adp->obj->nid);
+	}
+	op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
+	if (op == NULL)
+		return (NID_undef);
+	return (nid_objs[*op].nid);
+}
+LCRYPTO_ALIAS(OBJ_sn2nid);
+
+const void *
+OBJ_bsearch_(const void *key, const void *base, int num, int size,
+    int (*cmp)(const void *, const void *))
+{
+	return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
+}
+LCRYPTO_ALIAS(OBJ_bsearch_);
+
+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;
+
+	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 & 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);
+}
+
+int
+OBJ_create_objects(BIO *in)
+{
+	char buf[512];
+	int i, num = 0;
+	char *o, *s, *l = NULL;
+
+	for (;;) {
+		s = o = NULL;
+		i = BIO_gets(in, buf, 512);
+		if (i <= 0)
+			return (num);
+		buf[i - 1] = '\0';
+		if (!isalnum((unsigned char)buf[0]))
+			return (num);
+		o = s=buf;
+		while (isdigit((unsigned char)*s) || (*s == '.'))
+			s++;
+		if (*s != '\0') {
+			*(s++) = '\0';
+			while (isspace((unsigned char)*s))
+				s++;
+			if (*s == '\0')
+				s = NULL;
+			else {
+				l = s;
+				while ((*l != '\0') &&
+				    !isspace((unsigned char)*l))
+					l++;
+				if (*l != '\0') {
+					*(l++) = '\0';
+					while (isspace((unsigned char)*l))
+						l++;
+					if (*l == '\0')
+						l = NULL;
+				} else
+					l = NULL;
+			}
+		} else
+			s = NULL;
+		if ((o == NULL) || (*o == '\0'))
+			return (num);
+		if (!OBJ_create(o, s, l))
+			return (num);
+		num++;
+	}
+	/* return(num); */
+}
+LCRYPTO_ALIAS(OBJ_create_objects);
+
+int
+OBJ_create(const char *oid, const char *sn, const char *ln)
+{
+	int ok = 0;
+	ASN1_OBJECT *op = NULL;
+	unsigned char *buf;
+	int i;
+
+	i = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
+	if (i <= 0)
+		return (0);
+
+	if ((buf = malloc(i)) == NULL) {
+		OBJerror(ERR_R_MALLOC_FAILURE);
+		return (0);
+	}
+	i = a2d_ASN1_OBJECT(buf, i, oid, -1);
+	if (i == 0)
+		goto err;
+	op = (ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1), buf, i, sn, ln);
+	if (op == NULL)
+		goto err;
+	ok = OBJ_add_object(op);
+
+ err:
+	ASN1_OBJECT_free(op);
+	free(buf);
+	return (ok);
+}
+LCRYPTO_ALIAS(OBJ_create);
+
+size_t
+OBJ_length(const ASN1_OBJECT *obj)
+{
+	if (obj == NULL)
+		return 0;
+
+	if (obj->length < 0)
+		return 0;
+
+	return obj->length;
+}
+LCRYPTO_ALIAS(OBJ_length);
+
+const unsigned char *
+OBJ_get0_data(const ASN1_OBJECT *obj)
+{
+	if (obj == NULL)
+		return NULL;
+
+	return obj->data;
+}
+LCRYPTO_ALIAS(OBJ_get0_data);
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
new file mode 100644
index 0000000..578725a
--- /dev/null
+++ b/crypto/objects/obj_dat.h
@@ -0,0 +1,5835 @@
+/* crypto/objects/obj_dat.h */
+
+/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
+ * following command:
+ * perl obj_dat.pl obj_mac.h obj_dat.h
+ */
+
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#define NUM_NID 1053
+#define NUM_SN 1046
+#define NUM_LN 1046
+#define NUM_OBJ 975
+
+static const unsigned char lvalues[6949]={
+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 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,     /* [ 21] OBJ_md5 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04,     /* [ 29] OBJ_rc4 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,/* [ 37] OBJ_rsaEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,/* [ 46] OBJ_md2WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,/* [ 55] OBJ_md5WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01,/* [ 64] OBJ_pbeWithMD2AndDES_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03,/* [ 73] OBJ_pbeWithMD5AndDES_CBC */
+0x55,                                        /* [ 82] OBJ_X500 */
+0x55,0x04,                                   /* [ 83] OBJ_X509 */
+0x55,0x04,0x03,                              /* [ 85] OBJ_commonName */
+0x55,0x04,0x06,                              /* [ 88] OBJ_countryName */
+0x55,0x04,0x07,                              /* [ 91] OBJ_localityName */
+0x55,0x04,0x08,                              /* [ 94] OBJ_stateOrProvinceName */
+0x55,0x04,0x0A,                              /* [ 97] OBJ_organizationName */
+0x55,0x04,0x0B,                              /* [100] OBJ_organizationalUnitName */
+0x55,0x08,0x01,0x01,                         /* [103] OBJ_rsa */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,     /* [107] OBJ_pkcs7 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01,/* [115] OBJ_pkcs7_data */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02,/* [124] OBJ_pkcs7_signed */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03,/* [133] OBJ_pkcs7_enveloped */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04,/* [142] OBJ_pkcs7_signedAndEnveloped */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05,/* [151] OBJ_pkcs7_digest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06,/* [160] OBJ_pkcs7_encrypted */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,     /* [169] OBJ_pkcs3 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01,/* [177] OBJ_dhKeyAgreement */
+0x2B,0x0E,0x03,0x02,0x06,                    /* [186] OBJ_des_ecb */
+0x2B,0x0E,0x03,0x02,0x09,                    /* [191] OBJ_des_cfb64 */
+0x2B,0x0E,0x03,0x02,0x07,                    /* [196] OBJ_des_cbc */
+0x2B,0x0E,0x03,0x02,0x11,                    /* [201] OBJ_des_ede_ecb */
+0x2B,0x06,0x01,0x04,0x01,0x81,0x3C,0x07,0x01,0x01,0x02,/* [206] OBJ_idea_cbc */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02,     /* [217] OBJ_rc2_cbc */
+0x2B,0x0E,0x03,0x02,0x12,                    /* [225] OBJ_sha */
+0x2B,0x0E,0x03,0x02,0x0F,                    /* [230] OBJ_shaWithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07,     /* [235] OBJ_des_ede3_cbc */
+0x2B,0x0E,0x03,0x02,0x08,                    /* [243] OBJ_des_ofb64 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,     /* [248] OBJ_pkcs9 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,/* [256] OBJ_pkcs9_emailAddress */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02,/* [265] OBJ_pkcs9_unstructuredName */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03,/* [274] OBJ_pkcs9_contentType */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04,/* [283] OBJ_pkcs9_messageDigest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05,/* [292] OBJ_pkcs9_signingTime */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06,/* [301] OBJ_pkcs9_countersignature */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07,/* [310] OBJ_pkcs9_challengePassword */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08,/* [319] OBJ_pkcs9_unstructuredAddress */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09,/* [328] OBJ_pkcs9_extCertAttributes */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,          /* [337] OBJ_netscape */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,     /* [344] OBJ_netscape_cert_extension */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,     /* [352] OBJ_netscape_data_type */
+0x2B,0x0E,0x03,0x02,0x1A,                    /* [360] OBJ_sha1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,/* [365] OBJ_sha1WithRSAEncryption */
+0x2B,0x0E,0x03,0x02,0x0D,                    /* [374] OBJ_dsaWithSHA */
+0x2B,0x0E,0x03,0x02,0x0C,                    /* [379] OBJ_dsa_2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B,/* [384] OBJ_pbeWithSHA1AndRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C,/* [393] OBJ_id_pbkdf2 */
+0x2B,0x0E,0x03,0x02,0x1B,                    /* [402] OBJ_dsaWithSHA1_2 */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,/* [407] OBJ_netscape_cert_type */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02,/* [416] OBJ_netscape_base_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03,/* [425] OBJ_netscape_revocation_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04,/* [434] OBJ_netscape_ca_revocation_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07,/* [443] OBJ_netscape_renewal_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08,/* [452] OBJ_netscape_ca_policy_url */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C,/* [461] OBJ_netscape_ssl_server_name */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D,/* [470] OBJ_netscape_comment */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05,/* [479] OBJ_netscape_cert_sequence */
+0x55,0x1D,                                   /* [488] OBJ_id_ce */
+0x55,0x1D,0x0E,                              /* [490] OBJ_subject_key_identifier */
+0x55,0x1D,0x0F,                              /* [493] OBJ_key_usage */
+0x55,0x1D,0x10,                              /* [496] OBJ_private_key_usage_period */
+0x55,0x1D,0x11,                              /* [499] OBJ_subject_alt_name */
+0x55,0x1D,0x12,                              /* [502] OBJ_issuer_alt_name */
+0x55,0x1D,0x13,                              /* [505] OBJ_basic_constraints */
+0x55,0x1D,0x14,                              /* [508] OBJ_crl_number */
+0x55,0x1D,0x20,                              /* [511] OBJ_certificate_policies */
+0x55,0x1D,0x23,                              /* [514] OBJ_authority_key_identifier */
+0x2B,0x06,0x01,0x04,0x01,0x97,0x55,0x01,0x02,/* [517] OBJ_bf_cbc */
+0x55,0x08,0x03,0x65,                         /* [526] OBJ_mdc2 */
+0x55,0x08,0x03,0x64,                         /* [530] OBJ_mdc2WithRSA */
+0x55,0x04,0x2A,                              /* [534] OBJ_givenName */
+0x55,0x04,0x04,                              /* [537] OBJ_surname */
+0x55,0x04,0x2B,                              /* [540] OBJ_initials */
+0x55,0x1D,0x1F,                              /* [543] OBJ_crl_distribution_points */
+0x2B,0x0E,0x03,0x02,0x03,                    /* [546] OBJ_md5WithRSA */
+0x55,0x04,0x05,                              /* [551] OBJ_serialNumber */
+0x55,0x04,0x0C,                              /* [554] OBJ_title */
+0x55,0x04,0x0D,                              /* [557] OBJ_description */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A,/* [560] OBJ_cast5_cbc */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C,/* [569] OBJ_pbeWithMD5AndCast5_CBC */
+0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,          /* [578] OBJ_dsaWithSHA1 */
+0x2B,0x0E,0x03,0x02,0x1D,                    /* [585] OBJ_sha1WithRSA */
+0x2A,0x86,0x48,0xCE,0x38,0x04,0x01,          /* [590] OBJ_dsa */
+0x2B,0x24,0x03,0x02,0x01,                    /* [597] OBJ_ripemd160 */
+0x2B,0x24,0x03,0x03,0x01,0x02,               /* [602] OBJ_ripemd160WithRSA */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08,     /* [608] OBJ_rc5_cbc */
+0x29,0x01,0x01,0x85,0x1A,0x01,               /* [616] OBJ_rle_compression */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x08,/* [622] OBJ_zlib_compression */
+0x55,0x1D,0x25,                              /* [633] OBJ_ext_key_usage */
+0x2B,0x06,0x01,0x05,0x05,0x07,               /* [636] OBJ_id_pkix */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,          /* [642] OBJ_id_kp */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,     /* [649] OBJ_server_auth */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,     /* [657] OBJ_client_auth */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03,     /* [665] OBJ_code_sign */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04,     /* [673] OBJ_email_protect */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x08,     /* [681] OBJ_time_stamp */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x15,/* [689] OBJ_ms_code_ind */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x16,/* [699] OBJ_ms_code_com */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x01,/* [709] OBJ_ms_ctl_sign */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x03,/* [719] OBJ_ms_sgc */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x04,/* [729] OBJ_ms_efs */
+0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01,/* [739] OBJ_ns_sgc */
+0x55,0x1D,0x1B,                              /* [748] OBJ_delta_crl */
+0x55,0x1D,0x15,                              /* [751] OBJ_crl_reason */
+0x55,0x1D,0x18,                              /* [754] OBJ_invalidity_date */
+0x2B,0x65,0x01,0x04,0x01,                    /* [757] OBJ_sxnet */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x01,/* [762] OBJ_pbe_WithSHA1And128BitRC4 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x02,/* [772] OBJ_pbe_WithSHA1And40BitRC4 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x03,/* [782] OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x04,/* [792] OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x05,/* [802] OBJ_pbe_WithSHA1And128BitRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x06,/* [812] OBJ_pbe_WithSHA1And40BitRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x01,/* [822] OBJ_keyBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x02,/* [833] OBJ_pkcs8ShroudedKeyBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x03,/* [844] OBJ_certBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x04,/* [855] OBJ_crlBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x05,/* [866] OBJ_secretBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x06,/* [877] OBJ_safeContentsBag */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x14,/* [888] OBJ_friendlyName */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x15,/* [897] OBJ_localKeyID */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x01,/* [906] OBJ_x509Certificate */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x02,/* [916] OBJ_sdsiCertificate */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x17,0x01,/* [926] OBJ_x509Crl */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0D,/* [936] OBJ_pbes2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0E,/* [945] OBJ_pbmac1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x07,     /* [954] OBJ_hmacWithSHA1 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,     /* [962] OBJ_id_qt_cps */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,     /* [970] OBJ_id_qt_unotice */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0F,/* [978] OBJ_SMIMECapabilities */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x04,/* [987] OBJ_pbeWithMD2AndRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x06,/* [996] OBJ_pbeWithMD5AndRC2_CBC */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0A,/* [1005] OBJ_pbeWithSHA1AndDES_CBC */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0E,/* [1014] OBJ_ms_ext_req */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0E,/* [1024] OBJ_ext_req */
+0x55,0x04,0x29,                              /* [1033] OBJ_name */
+0x55,0x04,0x2E,                              /* [1036] OBJ_dnQualifier */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,          /* [1039] OBJ_id_pe */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,          /* [1046] OBJ_id_ad */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,     /* [1053] OBJ_info_access */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,     /* [1061] OBJ_ad_OCSP */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,     /* [1069] OBJ_ad_ca_issuers */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09,     /* [1077] OBJ_OCSP_sign */
+0x2A,                                        /* [1085] OBJ_member_body */
+0x2A,0x86,0x48,                              /* [1086] OBJ_ISO_US */
+0x2A,0x86,0x48,0xCE,0x38,                    /* [1089] OBJ_X9_57 */
+0x2A,0x86,0x48,0xCE,0x38,0x04,               /* [1094] OBJ_X9cm */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,     /* [1100] OBJ_pkcs1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,     /* [1108] OBJ_pkcs5 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,/* [1116] OBJ_SMIME */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,/* [1125] OBJ_id_smime_mod */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,/* [1135] OBJ_id_smime_ct */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,/* [1145] OBJ_id_smime_aa */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,/* [1155] OBJ_id_smime_alg */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,/* [1165] OBJ_id_smime_cd */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,/* [1175] OBJ_id_smime_spq */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,/* [1185] OBJ_id_smime_cti */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x01,/* [1195] OBJ_id_smime_mod_cms */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x02,/* [1206] OBJ_id_smime_mod_ess */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x03,/* [1217] OBJ_id_smime_mod_oid */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x04,/* [1228] OBJ_id_smime_mod_msg_v3 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x05,/* [1239] OBJ_id_smime_mod_ets_eSignature_88 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x06,/* [1250] OBJ_id_smime_mod_ets_eSignature_97 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x07,/* [1261] OBJ_id_smime_mod_ets_eSigPolicy_88 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x08,/* [1272] OBJ_id_smime_mod_ets_eSigPolicy_97 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x01,/* [1283] OBJ_id_smime_ct_receipt */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x02,/* [1294] OBJ_id_smime_ct_authData */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x03,/* [1305] OBJ_id_smime_ct_publishCert */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x04,/* [1316] OBJ_id_smime_ct_TSTInfo */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x05,/* [1327] OBJ_id_smime_ct_TDTInfo */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x06,/* [1338] OBJ_id_smime_ct_contentInfo */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x07,/* [1349] OBJ_id_smime_ct_DVCSRequestData */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x08,/* [1360] OBJ_id_smime_ct_DVCSResponseData */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x01,/* [1371] OBJ_id_smime_aa_receiptRequest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x02,/* [1382] OBJ_id_smime_aa_securityLabel */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x03,/* [1393] OBJ_id_smime_aa_mlExpandHistory */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x04,/* [1404] OBJ_id_smime_aa_contentHint */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x05,/* [1415] OBJ_id_smime_aa_msgSigDigest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x06,/* [1426] OBJ_id_smime_aa_encapContentType */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x07,/* [1437] OBJ_id_smime_aa_contentIdentifier */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x08,/* [1448] OBJ_id_smime_aa_macValue */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x09,/* [1459] OBJ_id_smime_aa_equivalentLabels */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0A,/* [1470] OBJ_id_smime_aa_contentReference */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0B,/* [1481] OBJ_id_smime_aa_encrypKeyPref */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0C,/* [1492] OBJ_id_smime_aa_signingCertificate */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0D,/* [1503] OBJ_id_smime_aa_smimeEncryptCerts */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0E,/* [1514] OBJ_id_smime_aa_timeStampToken */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0F,/* [1525] OBJ_id_smime_aa_ets_sigPolicyId */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x10,/* [1536] OBJ_id_smime_aa_ets_commitmentType */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x11,/* [1547] OBJ_id_smime_aa_ets_signerLocation */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x12,/* [1558] OBJ_id_smime_aa_ets_signerAttr */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x13,/* [1569] OBJ_id_smime_aa_ets_otherSigCert */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x14,/* [1580] OBJ_id_smime_aa_ets_contentTimestamp */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x15,/* [1591] OBJ_id_smime_aa_ets_CertificateRefs */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x16,/* [1602] OBJ_id_smime_aa_ets_RevocationRefs */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x17,/* [1613] OBJ_id_smime_aa_ets_certValues */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x18,/* [1624] OBJ_id_smime_aa_ets_revocationValues */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x19,/* [1635] OBJ_id_smime_aa_ets_escTimeStamp */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1A,/* [1646] OBJ_id_smime_aa_ets_certCRLTimestamp */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1B,/* [1657] OBJ_id_smime_aa_ets_archiveTimeStamp */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1C,/* [1668] OBJ_id_smime_aa_signatureType */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1D,/* [1679] OBJ_id_smime_aa_dvcs_dvc */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x01,/* [1690] OBJ_id_smime_alg_ESDHwith3DES */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x02,/* [1701] OBJ_id_smime_alg_ESDHwithRC2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x03,/* [1712] OBJ_id_smime_alg_3DESwrap */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x04,/* [1723] OBJ_id_smime_alg_RC2wrap */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x05,/* [1734] OBJ_id_smime_alg_ESDH */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x06,/* [1745] OBJ_id_smime_alg_CMS3DESwrap */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x07,/* [1756] OBJ_id_smime_alg_CMSRC2wrap */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,0x01,/* [1767] OBJ_id_smime_cd_ldap */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x01,/* [1778] OBJ_id_smime_spq_ets_sqt_uri */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x02,/* [1789] OBJ_id_smime_spq_ets_sqt_unotice */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x01,/* [1800] OBJ_id_smime_cti_ets_proofOfOrigin */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x02,/* [1811] OBJ_id_smime_cti_ets_proofOfReceipt */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x03,/* [1822] OBJ_id_smime_cti_ets_proofOfDelivery */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x04,/* [1833] OBJ_id_smime_cti_ets_proofOfSender */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x05,/* [1844] OBJ_id_smime_cti_ets_proofOfApproval */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x06,/* [1855] OBJ_id_smime_cti_ets_proofOfCreation */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x04,     /* [1866] OBJ_md4 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,          /* [1874] OBJ_id_pkix_mod */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x02,          /* [1881] OBJ_id_qt */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,          /* [1888] OBJ_id_it */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,          /* [1895] OBJ_id_pkip */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x06,          /* [1902] OBJ_id_alg */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,          /* [1909] OBJ_id_cmc */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x08,          /* [1916] OBJ_id_on */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,          /* [1923] OBJ_id_pda */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,          /* [1930] OBJ_id_aca */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,          /* [1937] OBJ_id_qcs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,          /* [1944] OBJ_id_cct */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x01,     /* [1951] OBJ_id_pkix1_explicit_88 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x02,     /* [1959] OBJ_id_pkix1_implicit_88 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x03,     /* [1967] OBJ_id_pkix1_explicit_93 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x04,     /* [1975] OBJ_id_pkix1_implicit_93 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x05,     /* [1983] OBJ_id_mod_crmf */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x06,     /* [1991] OBJ_id_mod_cmc */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x07,     /* [1999] OBJ_id_mod_kea_profile_88 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x08,     /* [2007] OBJ_id_mod_kea_profile_93 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x09,     /* [2015] OBJ_id_mod_cmp */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0A,     /* [2023] OBJ_id_mod_qualified_cert_88 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0B,     /* [2031] OBJ_id_mod_qualified_cert_93 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0C,     /* [2039] OBJ_id_mod_attribute_cert */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0D,     /* [2047] OBJ_id_mod_timestamp_protocol */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0E,     /* [2055] OBJ_id_mod_ocsp */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0F,     /* [2063] OBJ_id_mod_dvcs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x10,     /* [2071] OBJ_id_mod_cmp2000 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x02,     /* [2079] OBJ_biometricInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x03,     /* [2087] OBJ_qcStatements */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04,     /* [2095] OBJ_ac_auditEntity */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x05,     /* [2103] OBJ_ac_targeting */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x06,     /* [2111] OBJ_aaControls */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x07,     /* [2119] OBJ_sbgp_ipAddrBlock */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x08,     /* [2127] OBJ_sbgp_autonomousSysNum */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x09,     /* [2135] OBJ_sbgp_routerIdentifier */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x03,     /* [2143] OBJ_textNotice */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05,     /* [2151] OBJ_ipsecEndSystem */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06,     /* [2159] OBJ_ipsecTunnel */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,     /* [2167] OBJ_ipsecUser */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x0A,     /* [2175] OBJ_dvcs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x01,     /* [2183] OBJ_id_it_caProtEncCert */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x02,     /* [2191] OBJ_id_it_signKeyPairTypes */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x03,     /* [2199] OBJ_id_it_encKeyPairTypes */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x04,     /* [2207] OBJ_id_it_preferredSymmAlg */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x05,     /* [2215] OBJ_id_it_caKeyUpdateInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x06,     /* [2223] OBJ_id_it_currentCRL */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x07,     /* [2231] OBJ_id_it_unsupportedOIDs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x08,     /* [2239] OBJ_id_it_subscriptionRequest */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x09,     /* [2247] OBJ_id_it_subscriptionResponse */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0A,     /* [2255] OBJ_id_it_keyPairParamReq */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0B,     /* [2263] OBJ_id_it_keyPairParamRep */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0C,     /* [2271] OBJ_id_it_revPassphrase */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0D,     /* [2279] OBJ_id_it_implicitConfirm */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0E,     /* [2287] OBJ_id_it_confirmWaitTime */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0F,     /* [2295] OBJ_id_it_origPKIMessage */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,     /* [2303] OBJ_id_regCtrl */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,     /* [2311] OBJ_id_regInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x01,/* [2319] OBJ_id_regCtrl_regToken */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x02,/* [2328] OBJ_id_regCtrl_authenticator */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x03,/* [2337] OBJ_id_regCtrl_pkiPublicationInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x04,/* [2346] OBJ_id_regCtrl_pkiArchiveOptions */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x05,/* [2355] OBJ_id_regCtrl_oldCertID */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x06,/* [2364] OBJ_id_regCtrl_protocolEncrKey */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x01,/* [2373] OBJ_id_regInfo_utf8Pairs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x02,/* [2382] OBJ_id_regInfo_certReq */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x01,     /* [2391] OBJ_id_alg_des40 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x02,     /* [2399] OBJ_id_alg_noSignature */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x03,     /* [2407] OBJ_id_alg_dh_sig_hmac_sha1 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x04,     /* [2415] OBJ_id_alg_dh_pop */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x01,     /* [2423] OBJ_id_cmc_statusInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x02,     /* [2431] OBJ_id_cmc_identification */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x03,     /* [2439] OBJ_id_cmc_identityProof */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x04,     /* [2447] OBJ_id_cmc_dataReturn */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x05,     /* [2455] OBJ_id_cmc_transactionId */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x06,     /* [2463] OBJ_id_cmc_senderNonce */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x07,     /* [2471] OBJ_id_cmc_recipientNonce */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x08,     /* [2479] OBJ_id_cmc_addExtensions */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x09,     /* [2487] OBJ_id_cmc_encryptedPOP */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0A,     /* [2495] OBJ_id_cmc_decryptedPOP */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0B,     /* [2503] OBJ_id_cmc_lraPOPWitness */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0F,     /* [2511] OBJ_id_cmc_getCert */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x10,     /* [2519] OBJ_id_cmc_getCRL */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x11,     /* [2527] OBJ_id_cmc_revokeRequest */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x12,     /* [2535] OBJ_id_cmc_regInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x13,     /* [2543] OBJ_id_cmc_responseInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x15,     /* [2551] OBJ_id_cmc_queryPending */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x16,     /* [2559] OBJ_id_cmc_popLinkRandom */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x17,     /* [2567] OBJ_id_cmc_popLinkWitness */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x18,     /* [2575] OBJ_id_cmc_confirmCertAcceptance */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x01,     /* [2583] OBJ_id_on_personalData */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x01,     /* [2591] OBJ_id_pda_dateOfBirth */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x02,     /* [2599] OBJ_id_pda_placeOfBirth */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x03,     /* [2607] OBJ_id_pda_gender */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x04,     /* [2615] OBJ_id_pda_countryOfCitizenship */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x05,     /* [2623] OBJ_id_pda_countryOfResidence */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x01,     /* [2631] OBJ_id_aca_authenticationInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x02,     /* [2639] OBJ_id_aca_accessIdentity */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x03,     /* [2647] OBJ_id_aca_chargingIdentity */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x04,     /* [2655] OBJ_id_aca_group */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x05,     /* [2663] OBJ_id_aca_role */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,0x01,     /* [2671] OBJ_id_qcs_pkixQCSyntax_v1 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x01,     /* [2679] OBJ_id_cct_crs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x02,     /* [2687] OBJ_id_cct_PKIData */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x03,     /* [2695] OBJ_id_cct_PKIResponse */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x03,     /* [2703] OBJ_ad_timeStamping */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x04,     /* [2711] OBJ_ad_dvcs */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,/* [2719] OBJ_id_pkix_OCSP_basic */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02,/* [2728] OBJ_id_pkix_OCSP_Nonce */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x03,/* [2737] OBJ_id_pkix_OCSP_CrlID */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x04,/* [2746] OBJ_id_pkix_OCSP_acceptableResponses */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05,/* [2755] OBJ_id_pkix_OCSP_noCheck */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x06,/* [2764] OBJ_id_pkix_OCSP_archiveCutoff */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x07,/* [2773] OBJ_id_pkix_OCSP_serviceLocator */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x08,/* [2782] OBJ_id_pkix_OCSP_extendedStatus */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x09,/* [2791] OBJ_id_pkix_OCSP_valid */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0A,/* [2800] OBJ_id_pkix_OCSP_path */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0B,/* [2809] OBJ_id_pkix_OCSP_trustRoot */
+0x2B,0x0E,0x03,0x02,                         /* [2818] OBJ_algorithm */
+0x2B,0x0E,0x03,0x02,0x0B,                    /* [2822] OBJ_rsaSignature */
+0x55,0x08,                                   /* [2827] OBJ_X500algorithms */
+0x2B,                                        /* [2829] OBJ_org */
+0x2B,0x06,                                   /* [2830] OBJ_dod */
+0x2B,0x06,0x01,                              /* [2832] OBJ_iana */
+0x2B,0x06,0x01,0x01,                         /* [2835] OBJ_Directory */
+0x2B,0x06,0x01,0x02,                         /* [2839] OBJ_Management */
+0x2B,0x06,0x01,0x03,                         /* [2843] OBJ_Experimental */
+0x2B,0x06,0x01,0x04,                         /* [2847] OBJ_Private */
+0x2B,0x06,0x01,0x05,                         /* [2851] OBJ_Security */
+0x2B,0x06,0x01,0x06,                         /* [2855] OBJ_SNMPv2 */
+0x2B,0x06,0x01,0x07,                         /* [2859] OBJ_Mail */
+0x2B,0x06,0x01,0x04,0x01,                    /* [2863] OBJ_Enterprises */
+0x2B,0x06,0x01,0x04,0x01,0x8B,0x3A,0x82,0x58,/* [2868] OBJ_dcObject */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x19,/* [2877] OBJ_domainComponent */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0D,/* [2887] OBJ_Domain */
+0x55,0x01,0x05,                              /* [2897] OBJ_selected_attribute_types */
+0x55,0x01,0x05,0x37,                         /* [2900] OBJ_clearance */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x03,/* [2904] OBJ_md4WithRSAEncryption */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0A,     /* [2913] OBJ_ac_proxying */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0B,     /* [2921] OBJ_sinfo_access */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x06,     /* [2929] OBJ_id_aca_encAttrs */
+0x55,0x04,0x48,                              /* [2937] OBJ_role */
+0x55,0x1D,0x24,                              /* [2940] OBJ_policy_constraints */
+0x55,0x1D,0x37,                              /* [2943] OBJ_target_information */
+0x55,0x1D,0x38,                              /* [2946] OBJ_no_rev_avail */
+0x2A,0x86,0x48,0xCE,0x3D,                    /* [2949] OBJ_ansi_X9_62 */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x01,          /* [2954] OBJ_X9_62_prime_field */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,          /* [2961] OBJ_X9_62_characteristic_two_field */
+0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,          /* [2968] OBJ_X9_62_id_ecPublicKey */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01,     /* [2975] OBJ_X9_62_prime192v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02,     /* [2983] OBJ_X9_62_prime192v2 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03,     /* [2991] OBJ_X9_62_prime192v3 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04,     /* [2999] OBJ_X9_62_prime239v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05,     /* [3007] OBJ_X9_62_prime239v2 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06,     /* [3015] OBJ_X9_62_prime239v3 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,     /* [3023] OBJ_X9_62_prime256v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,          /* [3031] OBJ_ecdsa_with_SHA1 */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x01,/* [3038] OBJ_ms_csp_name */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x01,/* [3047] OBJ_aes_128_ecb */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x02,/* [3056] OBJ_aes_128_cbc */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x03,/* [3065] OBJ_aes_128_ofb128 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x04,/* [3074] OBJ_aes_128_cfb128 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x15,/* [3083] OBJ_aes_192_ecb */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x16,/* [3092] OBJ_aes_192_cbc */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x17,/* [3101] OBJ_aes_192_ofb128 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x18,/* [3110] OBJ_aes_192_cfb128 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x29,/* [3119] OBJ_aes_256_ecb */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2A,/* [3128] OBJ_aes_256_cbc */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2B,/* [3137] OBJ_aes_256_ofb128 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2C,/* [3146] OBJ_aes_256_cfb128 */
+0x55,0x1D,0x17,                              /* [3155] OBJ_hold_instruction_code */
+0x2A,0x86,0x48,0xCE,0x38,0x02,0x01,          /* [3158] OBJ_hold_instruction_none */
+0x2A,0x86,0x48,0xCE,0x38,0x02,0x02,          /* [3165] OBJ_hold_instruction_call_issuer */
+0x2A,0x86,0x48,0xCE,0x38,0x02,0x03,          /* [3172] OBJ_hold_instruction_reject */
+0x09,                                        /* [3179] OBJ_data */
+0x09,0x92,0x26,                              /* [3180] OBJ_pss */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,          /* [3183] OBJ_ucl */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,     /* [3190] OBJ_pilot */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,/* [3198] OBJ_pilotAttributeType */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,/* [3207] OBJ_pilotAttributeSyntax */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,/* [3216] OBJ_pilotObjectClass */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x0A,/* [3225] OBJ_pilotGroups */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x04,/* [3234] OBJ_iA5StringSyntax */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x05,/* [3244] OBJ_caseIgnoreIA5StringSyntax */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x03,/* [3254] OBJ_pilotObject */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x04,/* [3264] OBJ_pilotPerson */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x05,/* [3274] OBJ_account */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x06,/* [3284] OBJ_document */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x07,/* [3294] OBJ_room */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x09,/* [3304] OBJ_documentSeries */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0E,/* [3314] OBJ_rFC822localPart */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0F,/* [3324] OBJ_dNSDomain */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x11,/* [3334] OBJ_domainRelatedObject */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x12,/* [3344] OBJ_friendlyCountry */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x13,/* [3354] OBJ_simpleSecurityObject */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x14,/* [3364] OBJ_pilotOrganization */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x15,/* [3374] OBJ_pilotDSA */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x16,/* [3384] OBJ_qualityLabelledData */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01,/* [3394] OBJ_userId */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x02,/* [3404] OBJ_textEncodedORAddress */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x03,/* [3414] OBJ_rfc822Mailbox */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x04,/* [3424] OBJ_info */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x05,/* [3434] OBJ_favouriteDrink */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x06,/* [3444] OBJ_roomNumber */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x07,/* [3454] OBJ_photo */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x08,/* [3464] OBJ_userClass */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x09,/* [3474] OBJ_host */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0A,/* [3484] OBJ_manager */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0B,/* [3494] OBJ_documentIdentifier */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0C,/* [3504] OBJ_documentTitle */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0D,/* [3514] OBJ_documentVersion */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0E,/* [3524] OBJ_documentAuthor */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0F,/* [3534] OBJ_documentLocation */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x14,/* [3544] OBJ_homeTelephoneNumber */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x15,/* [3554] OBJ_secretary */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x16,/* [3564] OBJ_otherMailbox */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x17,/* [3574] OBJ_lastModifiedTime */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x18,/* [3584] OBJ_lastModifiedBy */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1A,/* [3594] OBJ_aRecord */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1B,/* [3604] OBJ_pilotAttributeType27 */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1C,/* [3614] OBJ_mXRecord */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1D,/* [3624] OBJ_nSRecord */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1E,/* [3634] OBJ_sOARecord */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1F,/* [3644] OBJ_cNAMERecord */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x25,/* [3654] OBJ_associatedDomain */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x26,/* [3664] OBJ_associatedName */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x27,/* [3674] OBJ_homePostalAddress */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x28,/* [3684] OBJ_personalTitle */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x29,/* [3694] OBJ_mobileTelephoneNumber */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2A,/* [3704] OBJ_pagerTelephoneNumber */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2B,/* [3714] OBJ_friendlyCountryName */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2D,/* [3724] OBJ_organizationalStatus */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2E,/* [3734] OBJ_janetMailbox */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2F,/* [3744] OBJ_mailPreferenceOption */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x30,/* [3754] OBJ_buildingName */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x31,/* [3764] OBJ_dSAQuality */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x32,/* [3774] OBJ_singleLevelQuality */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x33,/* [3784] OBJ_subtreeMinimumQuality */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x34,/* [3794] OBJ_subtreeMaximumQuality */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x35,/* [3804] OBJ_personalSignature */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x36,/* [3814] OBJ_dITRedirect */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x37,/* [3824] OBJ_audio */
+0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x38,/* [3834] OBJ_documentPublisher */
+0x55,0x04,0x2D,                              /* [3844] OBJ_x500UniqueIdentifier */
+0x2B,0x06,0x01,0x07,0x01,                    /* [3847] OBJ_mime_mhs */
+0x2B,0x06,0x01,0x07,0x01,0x01,               /* [3852] OBJ_mime_mhs_headings */
+0x2B,0x06,0x01,0x07,0x01,0x02,               /* [3858] OBJ_mime_mhs_bodies */
+0x2B,0x06,0x01,0x07,0x01,0x01,0x01,          /* [3864] OBJ_id_hex_partial_message */
+0x2B,0x06,0x01,0x07,0x01,0x01,0x02,          /* [3871] OBJ_id_hex_multipart_message */
+0x55,0x04,0x2C,                              /* [3878] OBJ_generationQualifier */
+0x55,0x04,0x41,                              /* [3881] OBJ_pseudonym */
+0x67,0x2A,                                   /* [3884] OBJ_id_set */
+0x67,0x2A,0x00,                              /* [3886] OBJ_set_ctype */
+0x67,0x2A,0x01,                              /* [3889] OBJ_set_msgExt */
+0x67,0x2A,0x03,                              /* [3892] OBJ_set_attr */
+0x67,0x2A,0x05,                              /* [3895] OBJ_set_policy */
+0x67,0x2A,0x07,                              /* [3898] OBJ_set_certExt */
+0x67,0x2A,0x08,                              /* [3901] OBJ_set_brand */
+0x67,0x2A,0x00,0x00,                         /* [3904] OBJ_setct_PANData */
+0x67,0x2A,0x00,0x01,                         /* [3908] OBJ_setct_PANToken */
+0x67,0x2A,0x00,0x02,                         /* [3912] OBJ_setct_PANOnly */
+0x67,0x2A,0x00,0x03,                         /* [3916] OBJ_setct_OIData */
+0x67,0x2A,0x00,0x04,                         /* [3920] OBJ_setct_PI */
+0x67,0x2A,0x00,0x05,                         /* [3924] OBJ_setct_PIData */
+0x67,0x2A,0x00,0x06,                         /* [3928] OBJ_setct_PIDataUnsigned */
+0x67,0x2A,0x00,0x07,                         /* [3932] OBJ_setct_HODInput */
+0x67,0x2A,0x00,0x08,                         /* [3936] OBJ_setct_AuthResBaggage */
+0x67,0x2A,0x00,0x09,                         /* [3940] OBJ_setct_AuthRevReqBaggage */
+0x67,0x2A,0x00,0x0A,                         /* [3944] OBJ_setct_AuthRevResBaggage */
+0x67,0x2A,0x00,0x0B,                         /* [3948] OBJ_setct_CapTokenSeq */
+0x67,0x2A,0x00,0x0C,                         /* [3952] OBJ_setct_PInitResData */
+0x67,0x2A,0x00,0x0D,                         /* [3956] OBJ_setct_PI_TBS */
+0x67,0x2A,0x00,0x0E,                         /* [3960] OBJ_setct_PResData */
+0x67,0x2A,0x00,0x10,                         /* [3964] OBJ_setct_AuthReqTBS */
+0x67,0x2A,0x00,0x11,                         /* [3968] OBJ_setct_AuthResTBS */
+0x67,0x2A,0x00,0x12,                         /* [3972] OBJ_setct_AuthResTBSX */
+0x67,0x2A,0x00,0x13,                         /* [3976] OBJ_setct_AuthTokenTBS */
+0x67,0x2A,0x00,0x14,                         /* [3980] OBJ_setct_CapTokenData */
+0x67,0x2A,0x00,0x15,                         /* [3984] OBJ_setct_CapTokenTBS */
+0x67,0x2A,0x00,0x16,                         /* [3988] OBJ_setct_AcqCardCodeMsg */
+0x67,0x2A,0x00,0x17,                         /* [3992] OBJ_setct_AuthRevReqTBS */
+0x67,0x2A,0x00,0x18,                         /* [3996] OBJ_setct_AuthRevResData */
+0x67,0x2A,0x00,0x19,                         /* [4000] OBJ_setct_AuthRevResTBS */
+0x67,0x2A,0x00,0x1A,                         /* [4004] OBJ_setct_CapReqTBS */
+0x67,0x2A,0x00,0x1B,                         /* [4008] OBJ_setct_CapReqTBSX */
+0x67,0x2A,0x00,0x1C,                         /* [4012] OBJ_setct_CapResData */
+0x67,0x2A,0x00,0x1D,                         /* [4016] OBJ_setct_CapRevReqTBS */
+0x67,0x2A,0x00,0x1E,                         /* [4020] OBJ_setct_CapRevReqTBSX */
+0x67,0x2A,0x00,0x1F,                         /* [4024] OBJ_setct_CapRevResData */
+0x67,0x2A,0x00,0x20,                         /* [4028] OBJ_setct_CredReqTBS */
+0x67,0x2A,0x00,0x21,                         /* [4032] OBJ_setct_CredReqTBSX */
+0x67,0x2A,0x00,0x22,                         /* [4036] OBJ_setct_CredResData */
+0x67,0x2A,0x00,0x23,                         /* [4040] OBJ_setct_CredRevReqTBS */
+0x67,0x2A,0x00,0x24,                         /* [4044] OBJ_setct_CredRevReqTBSX */
+0x67,0x2A,0x00,0x25,                         /* [4048] OBJ_setct_CredRevResData */
+0x67,0x2A,0x00,0x26,                         /* [4052] OBJ_setct_PCertReqData */
+0x67,0x2A,0x00,0x27,                         /* [4056] OBJ_setct_PCertResTBS */
+0x67,0x2A,0x00,0x28,                         /* [4060] OBJ_setct_BatchAdminReqData */
+0x67,0x2A,0x00,0x29,                         /* [4064] OBJ_setct_BatchAdminResData */
+0x67,0x2A,0x00,0x2A,                         /* [4068] OBJ_setct_CardCInitResTBS */
+0x67,0x2A,0x00,0x2B,                         /* [4072] OBJ_setct_MeAqCInitResTBS */
+0x67,0x2A,0x00,0x2C,                         /* [4076] OBJ_setct_RegFormResTBS */
+0x67,0x2A,0x00,0x2D,                         /* [4080] OBJ_setct_CertReqData */
+0x67,0x2A,0x00,0x2E,                         /* [4084] OBJ_setct_CertReqTBS */
+0x67,0x2A,0x00,0x2F,                         /* [4088] OBJ_setct_CertResData */
+0x67,0x2A,0x00,0x30,                         /* [4092] OBJ_setct_CertInqReqTBS */
+0x67,0x2A,0x00,0x31,                         /* [4096] OBJ_setct_ErrorTBS */
+0x67,0x2A,0x00,0x32,                         /* [4100] OBJ_setct_PIDualSignedTBE */
+0x67,0x2A,0x00,0x33,                         /* [4104] OBJ_setct_PIUnsignedTBE */
+0x67,0x2A,0x00,0x34,                         /* [4108] OBJ_setct_AuthReqTBE */
+0x67,0x2A,0x00,0x35,                         /* [4112] OBJ_setct_AuthResTBE */
+0x67,0x2A,0x00,0x36,                         /* [4116] OBJ_setct_AuthResTBEX */
+0x67,0x2A,0x00,0x37,                         /* [4120] OBJ_setct_AuthTokenTBE */
+0x67,0x2A,0x00,0x38,                         /* [4124] OBJ_setct_CapTokenTBE */
+0x67,0x2A,0x00,0x39,                         /* [4128] OBJ_setct_CapTokenTBEX */
+0x67,0x2A,0x00,0x3A,                         /* [4132] OBJ_setct_AcqCardCodeMsgTBE */
+0x67,0x2A,0x00,0x3B,                         /* [4136] OBJ_setct_AuthRevReqTBE */
+0x67,0x2A,0x00,0x3C,                         /* [4140] OBJ_setct_AuthRevResTBE */
+0x67,0x2A,0x00,0x3D,                         /* [4144] OBJ_setct_AuthRevResTBEB */
+0x67,0x2A,0x00,0x3E,                         /* [4148] OBJ_setct_CapReqTBE */
+0x67,0x2A,0x00,0x3F,                         /* [4152] OBJ_setct_CapReqTBEX */
+0x67,0x2A,0x00,0x40,                         /* [4156] OBJ_setct_CapResTBE */
+0x67,0x2A,0x00,0x41,                         /* [4160] OBJ_setct_CapRevReqTBE */
+0x67,0x2A,0x00,0x42,                         /* [4164] OBJ_setct_CapRevReqTBEX */
+0x67,0x2A,0x00,0x43,                         /* [4168] OBJ_setct_CapRevResTBE */
+0x67,0x2A,0x00,0x44,                         /* [4172] OBJ_setct_CredReqTBE */
+0x67,0x2A,0x00,0x45,                         /* [4176] OBJ_setct_CredReqTBEX */
+0x67,0x2A,0x00,0x46,                         /* [4180] OBJ_setct_CredResTBE */
+0x67,0x2A,0x00,0x47,                         /* [4184] OBJ_setct_CredRevReqTBE */
+0x67,0x2A,0x00,0x48,                         /* [4188] OBJ_setct_CredRevReqTBEX */
+0x67,0x2A,0x00,0x49,                         /* [4192] OBJ_setct_CredRevResTBE */
+0x67,0x2A,0x00,0x4A,                         /* [4196] OBJ_setct_BatchAdminReqTBE */
+0x67,0x2A,0x00,0x4B,                         /* [4200] OBJ_setct_BatchAdminResTBE */
+0x67,0x2A,0x00,0x4C,                         /* [4204] OBJ_setct_RegFormReqTBE */
+0x67,0x2A,0x00,0x4D,                         /* [4208] OBJ_setct_CertReqTBE */
+0x67,0x2A,0x00,0x4E,                         /* [4212] OBJ_setct_CertReqTBEX */
+0x67,0x2A,0x00,0x4F,                         /* [4216] OBJ_setct_CertResTBE */
+0x67,0x2A,0x00,0x50,                         /* [4220] OBJ_setct_CRLNotificationTBS */
+0x67,0x2A,0x00,0x51,                         /* [4224] OBJ_setct_CRLNotificationResTBS */
+0x67,0x2A,0x00,0x52,                         /* [4228] OBJ_setct_BCIDistributionTBS */
+0x67,0x2A,0x01,0x01,                         /* [4232] OBJ_setext_genCrypt */
+0x67,0x2A,0x01,0x03,                         /* [4236] OBJ_setext_miAuth */
+0x67,0x2A,0x01,0x04,                         /* [4240] OBJ_setext_pinSecure */
+0x67,0x2A,0x01,0x05,                         /* [4244] OBJ_setext_pinAny */
+0x67,0x2A,0x01,0x07,                         /* [4248] OBJ_setext_track2 */
+0x67,0x2A,0x01,0x08,                         /* [4252] OBJ_setext_cv */
+0x67,0x2A,0x05,0x00,                         /* [4256] OBJ_set_policy_root */
+0x67,0x2A,0x07,0x00,                         /* [4260] OBJ_setCext_hashedRoot */
+0x67,0x2A,0x07,0x01,                         /* [4264] OBJ_setCext_certType */
+0x67,0x2A,0x07,0x02,                         /* [4268] OBJ_setCext_merchData */
+0x67,0x2A,0x07,0x03,                         /* [4272] OBJ_setCext_cCertRequired */
+0x67,0x2A,0x07,0x04,                         /* [4276] OBJ_setCext_tunneling */
+0x67,0x2A,0x07,0x05,                         /* [4280] OBJ_setCext_setExt */
+0x67,0x2A,0x07,0x06,                         /* [4284] OBJ_setCext_setQualf */
+0x67,0x2A,0x07,0x07,                         /* [4288] OBJ_setCext_PGWYcapabilities */
+0x67,0x2A,0x07,0x08,                         /* [4292] OBJ_setCext_TokenIdentifier */
+0x67,0x2A,0x07,0x09,                         /* [4296] OBJ_setCext_Track2Data */
+0x67,0x2A,0x07,0x0A,                         /* [4300] OBJ_setCext_TokenType */
+0x67,0x2A,0x07,0x0B,                         /* [4304] OBJ_setCext_IssuerCapabilities */
+0x67,0x2A,0x03,0x00,                         /* [4308] OBJ_setAttr_Cert */
+0x67,0x2A,0x03,0x01,                         /* [4312] OBJ_setAttr_PGWYcap */
+0x67,0x2A,0x03,0x02,                         /* [4316] OBJ_setAttr_TokenType */
+0x67,0x2A,0x03,0x03,                         /* [4320] OBJ_setAttr_IssCap */
+0x67,0x2A,0x03,0x00,0x00,                    /* [4324] OBJ_set_rootKeyThumb */
+0x67,0x2A,0x03,0x00,0x01,                    /* [4329] OBJ_set_addPolicy */
+0x67,0x2A,0x03,0x02,0x01,                    /* [4334] OBJ_setAttr_Token_EMV */
+0x67,0x2A,0x03,0x02,0x02,                    /* [4339] OBJ_setAttr_Token_B0Prime */
+0x67,0x2A,0x03,0x03,0x03,                    /* [4344] OBJ_setAttr_IssCap_CVM */
+0x67,0x2A,0x03,0x03,0x04,                    /* [4349] OBJ_setAttr_IssCap_T2 */
+0x67,0x2A,0x03,0x03,0x05,                    /* [4354] OBJ_setAttr_IssCap_Sig */
+0x67,0x2A,0x03,0x03,0x03,0x01,               /* [4359] OBJ_setAttr_GenCryptgrm */
+0x67,0x2A,0x03,0x03,0x04,0x01,               /* [4365] OBJ_setAttr_T2Enc */
+0x67,0x2A,0x03,0x03,0x04,0x02,               /* [4371] OBJ_setAttr_T2cleartxt */
+0x67,0x2A,0x03,0x03,0x05,0x01,               /* [4377] OBJ_setAttr_TokICCsig */
+0x67,0x2A,0x03,0x03,0x05,0x02,               /* [4383] OBJ_setAttr_SecDevSig */
+0x67,0x2A,0x08,0x01,                         /* [4389] OBJ_set_brand_IATA_ATA */
+0x67,0x2A,0x08,0x1E,                         /* [4393] OBJ_set_brand_Diners */
+0x67,0x2A,0x08,0x22,                         /* [4397] OBJ_set_brand_AmericanExpress */
+0x67,0x2A,0x08,0x23,                         /* [4401] OBJ_set_brand_JCB */
+0x67,0x2A,0x08,0x04,                         /* [4405] OBJ_set_brand_Visa */
+0x67,0x2A,0x08,0x05,                         /* [4409] OBJ_set_brand_MasterCard */
+0x67,0x2A,0x08,0xAE,0x7B,                    /* [4413] OBJ_set_brand_Novus */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x0A,     /* [4418] OBJ_des_cdmf */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x06,/* [4426] OBJ_rsaOAEPEncryptionSET */
+0x67,                                        /* [4435] OBJ_international_organizations */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,/* [4436] OBJ_ms_smartcard_login */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x03,/* [4446] OBJ_ms_upn */
+0x55,0x04,0x09,                              /* [4456] OBJ_streetAddress */
+0x55,0x04,0x11,                              /* [4459] OBJ_postalCode */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x15,          /* [4462] OBJ_id_ppl */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0E,     /* [4469] OBJ_proxyCertInfo */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x00,     /* [4477] OBJ_id_ppl_anyLanguage */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x01,     /* [4485] OBJ_id_ppl_inheritAll */
+0x55,0x1D,0x1E,                              /* [4493] OBJ_name_constraints */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x02,     /* [4496] OBJ_Independent */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,/* [4504] OBJ_sha256WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,/* [4513] OBJ_sha384WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D,/* [4522] OBJ_sha512WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0E,/* [4531] OBJ_sha224WithRSAEncryption */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,/* [4540] OBJ_sha256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,/* [4549] OBJ_sha384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,/* [4558] OBJ_sha512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,/* [4567] OBJ_sha224 */
+0x2B,                                        /* [4576] OBJ_identified_organization */
+0x2B,0x81,0x04,                              /* [4577] OBJ_certicom_arc */
+0x67,0x2B,                                   /* [4580] OBJ_wap */
+0x67,0x2B,0x01,                              /* [4582] OBJ_wap_wsg */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,     /* [4585] OBJ_X9_62_id_characteristic_two_basis */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x01,/* [4593] OBJ_X9_62_onBasis */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x02,/* [4602] OBJ_X9_62_tpBasis */
+0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x03,/* [4611] OBJ_X9_62_ppBasis */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x01,     /* [4620] OBJ_X9_62_c2pnb163v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x02,     /* [4628] OBJ_X9_62_c2pnb163v2 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x03,     /* [4636] OBJ_X9_62_c2pnb163v3 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x04,     /* [4644] OBJ_X9_62_c2pnb176v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x05,     /* [4652] OBJ_X9_62_c2tnb191v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x06,     /* [4660] OBJ_X9_62_c2tnb191v2 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x07,     /* [4668] OBJ_X9_62_c2tnb191v3 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x08,     /* [4676] OBJ_X9_62_c2onb191v4 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x09,     /* [4684] OBJ_X9_62_c2onb191v5 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0A,     /* [4692] OBJ_X9_62_c2pnb208w1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0B,     /* [4700] OBJ_X9_62_c2tnb239v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0C,     /* [4708] OBJ_X9_62_c2tnb239v2 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0D,     /* [4716] OBJ_X9_62_c2tnb239v3 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0E,     /* [4724] OBJ_X9_62_c2onb239v4 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0F,     /* [4732] OBJ_X9_62_c2onb239v5 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x10,     /* [4740] OBJ_X9_62_c2pnb272w1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x11,     /* [4748] OBJ_X9_62_c2pnb304w1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x12,     /* [4756] OBJ_X9_62_c2tnb359v1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x13,     /* [4764] OBJ_X9_62_c2pnb368w1 */
+0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x14,     /* [4772] OBJ_X9_62_c2tnb431r1 */
+0x2B,0x81,0x04,0x00,0x06,                    /* [4780] OBJ_secp112r1 */
+0x2B,0x81,0x04,0x00,0x07,                    /* [4785] OBJ_secp112r2 */
+0x2B,0x81,0x04,0x00,0x1C,                    /* [4790] OBJ_secp128r1 */
+0x2B,0x81,0x04,0x00,0x1D,                    /* [4795] OBJ_secp128r2 */
+0x2B,0x81,0x04,0x00,0x09,                    /* [4800] OBJ_secp160k1 */
+0x2B,0x81,0x04,0x00,0x08,                    /* [4805] OBJ_secp160r1 */
+0x2B,0x81,0x04,0x00,0x1E,                    /* [4810] OBJ_secp160r2 */
+0x2B,0x81,0x04,0x00,0x1F,                    /* [4815] OBJ_secp192k1 */
+0x2B,0x81,0x04,0x00,0x20,                    /* [4820] OBJ_secp224k1 */
+0x2B,0x81,0x04,0x00,0x21,                    /* [4825] OBJ_secp224r1 */
+0x2B,0x81,0x04,0x00,0x0A,                    /* [4830] OBJ_secp256k1 */
+0x2B,0x81,0x04,0x00,0x22,                    /* [4835] OBJ_secp384r1 */
+0x2B,0x81,0x04,0x00,0x23,                    /* [4840] OBJ_secp521r1 */
+0x2B,0x81,0x04,0x00,0x04,                    /* [4845] OBJ_sect113r1 */
+0x2B,0x81,0x04,0x00,0x05,                    /* [4850] OBJ_sect113r2 */
+0x2B,0x81,0x04,0x00,0x16,                    /* [4855] OBJ_sect131r1 */
+0x2B,0x81,0x04,0x00,0x17,                    /* [4860] OBJ_sect131r2 */
+0x2B,0x81,0x04,0x00,0x01,                    /* [4865] OBJ_sect163k1 */
+0x2B,0x81,0x04,0x00,0x02,                    /* [4870] OBJ_sect163r1 */
+0x2B,0x81,0x04,0x00,0x0F,                    /* [4875] OBJ_sect163r2 */
+0x2B,0x81,0x04,0x00,0x18,                    /* [4880] OBJ_sect193r1 */
+0x2B,0x81,0x04,0x00,0x19,                    /* [4885] OBJ_sect193r2 */
+0x2B,0x81,0x04,0x00,0x1A,                    /* [4890] OBJ_sect233k1 */
+0x2B,0x81,0x04,0x00,0x1B,                    /* [4895] OBJ_sect233r1 */
+0x2B,0x81,0x04,0x00,0x03,                    /* [4900] OBJ_sect239k1 */
+0x2B,0x81,0x04,0x00,0x10,                    /* [4905] OBJ_sect283k1 */
+0x2B,0x81,0x04,0x00,0x11,                    /* [4910] OBJ_sect283r1 */
+0x2B,0x81,0x04,0x00,0x24,                    /* [4915] OBJ_sect409k1 */
+0x2B,0x81,0x04,0x00,0x25,                    /* [4920] OBJ_sect409r1 */
+0x2B,0x81,0x04,0x00,0x26,                    /* [4925] OBJ_sect571k1 */
+0x2B,0x81,0x04,0x00,0x27,                    /* [4930] OBJ_sect571r1 */
+0x67,0x2B,0x01,0x04,0x01,                    /* [4935] OBJ_wap_wsg_idm_ecid_wtls1 */
+0x67,0x2B,0x01,0x04,0x03,                    /* [4940] OBJ_wap_wsg_idm_ecid_wtls3 */
+0x67,0x2B,0x01,0x04,0x04,                    /* [4945] OBJ_wap_wsg_idm_ecid_wtls4 */
+0x67,0x2B,0x01,0x04,0x05,                    /* [4950] OBJ_wap_wsg_idm_ecid_wtls5 */
+0x67,0x2B,0x01,0x04,0x06,                    /* [4955] OBJ_wap_wsg_idm_ecid_wtls6 */
+0x67,0x2B,0x01,0x04,0x07,                    /* [4960] OBJ_wap_wsg_idm_ecid_wtls7 */
+0x67,0x2B,0x01,0x04,0x08,                    /* [4965] OBJ_wap_wsg_idm_ecid_wtls8 */
+0x67,0x2B,0x01,0x04,0x09,                    /* [4970] OBJ_wap_wsg_idm_ecid_wtls9 */
+0x67,0x2B,0x01,0x04,0x0A,                    /* [4975] OBJ_wap_wsg_idm_ecid_wtls10 */
+0x67,0x2B,0x01,0x04,0x0B,                    /* [4980] OBJ_wap_wsg_idm_ecid_wtls11 */
+0x67,0x2B,0x01,0x04,0x0C,                    /* [4985] OBJ_wap_wsg_idm_ecid_wtls12 */
+0x55,0x1D,0x20,0x00,                         /* [4990] OBJ_any_policy */
+0x55,0x1D,0x21,                              /* [4994] OBJ_policy_mappings */
+0x55,0x1D,0x36,                              /* [4997] OBJ_inhibit_any_policy */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x02,/* [5000] OBJ_camellia_128_cbc */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x03,/* [5011] OBJ_camellia_192_cbc */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x04,/* [5022] OBJ_camellia_256_cbc */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x01,     /* [5033] OBJ_camellia_128_ecb */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x15,     /* [5041] OBJ_camellia_192_ecb */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x29,     /* [5049] OBJ_camellia_256_ecb */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x04,     /* [5057] OBJ_camellia_128_cfb128 */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x18,     /* [5065] OBJ_camellia_192_cfb128 */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2C,     /* [5073] OBJ_camellia_256_cfb128 */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x03,     /* [5081] OBJ_camellia_128_ofb128 */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x17,     /* [5089] OBJ_camellia_192_ofb128 */
+0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2B,     /* [5097] OBJ_camellia_256_ofb128 */
+0x55,0x1D,0x09,                              /* [5105] OBJ_subject_directory_attributes */
+0x55,0x1D,0x1C,                              /* [5108] OBJ_issuing_distribution_point */
+0x55,0x1D,0x1D,                              /* [5111] OBJ_certificate_issuer */
+0x2A,0x83,0x1A,0x8C,0x9A,0x44,               /* [5114] OBJ_kisa */
+0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x03,     /* [5120] OBJ_seed_ecb */
+0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x04,     /* [5128] OBJ_seed_cbc */
+0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x06,     /* [5136] OBJ_seed_ofb128 */
+0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x05,     /* [5144] OBJ_seed_cfb128 */
+0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x01,     /* [5152] OBJ_hmac_md5 */
+0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x02,     /* [5160] OBJ_hmac_sha1 */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0D,/* [5168] OBJ_id_PasswordBasedMAC */
+0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x1E,/* [5177] OBJ_id_DHBasedMac */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x10,     /* [5186] OBJ_id_it_suppLangTags */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x05,     /* [5194] OBJ_caRepository */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x09,/* [5202] OBJ_id_smime_ct_compressedData */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1B,/* [5213] OBJ_id_ct_asciiTextWithCRLF */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x05,/* [5224] OBJ_id_aes128_wrap */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x19,/* [5233] OBJ_id_aes192_wrap */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2D,/* [5242] OBJ_id_aes256_wrap */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x02,          /* [5251] OBJ_ecdsa_with_Recommended */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,          /* [5258] OBJ_ecdsa_with_Specified */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x01,     /* [5265] OBJ_ecdsa_with_SHA224 */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,     /* [5273] OBJ_ecdsa_with_SHA256 */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,     /* [5281] OBJ_ecdsa_with_SHA384 */
+0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x04,     /* [5289] OBJ_ecdsa_with_SHA512 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x06,     /* [5297] OBJ_hmacWithMD5 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x08,     /* [5305] OBJ_hmacWithSHA224 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x09,     /* [5313] OBJ_hmacWithSHA256 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0A,     /* [5321] OBJ_hmacWithSHA384 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0B,     /* [5329] OBJ_hmacWithSHA512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x01,/* [5337] OBJ_dsa_with_SHA224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x02,/* [5346] OBJ_dsa_with_SHA256 */
+0x28,0xCF,0x06,0x03,0x00,0x37,               /* [5355] OBJ_whirlpool */
+0x2A,0x85,0x03,0x02,0x02,                    /* [5361] OBJ_cryptopro */
+0x2A,0x85,0x03,0x02,0x09,                    /* [5366] OBJ_cryptocom */
+0x2A,0x85,0x03,0x02,0x02,0x03,               /* [5371] OBJ_id_GostR3411_94_with_GostR3410_2001 */
+0x2A,0x85,0x03,0x02,0x02,0x04,               /* [5377] OBJ_id_GostR3411_94_with_GostR3410_94 */
+0x2A,0x85,0x03,0x02,0x02,0x09,               /* [5383] OBJ_id_GostR3411_94 */
+0x2A,0x85,0x03,0x02,0x02,0x0A,               /* [5389] OBJ_id_HMACGostR3411_94 */
+0x2A,0x85,0x03,0x02,0x02,0x13,               /* [5395] OBJ_id_GostR3410_2001 */
+0x2A,0x85,0x03,0x02,0x02,0x14,               /* [5401] OBJ_id_GostR3410_94 */
+0x2A,0x85,0x03,0x02,0x02,0x15,               /* [5407] OBJ_id_Gost28147_89 */
+0x2A,0x85,0x03,0x02,0x02,0x16,               /* [5413] OBJ_id_Gost28147_89_MAC */
+0x2A,0x85,0x03,0x02,0x02,0x17,               /* [5419] OBJ_id_GostR3411_94_prf */
+0x2A,0x85,0x03,0x02,0x02,0x62,               /* [5425] OBJ_id_GostR3410_2001DH */
+0x2A,0x85,0x03,0x02,0x02,0x63,               /* [5431] OBJ_id_GostR3410_94DH */
+0x2A,0x85,0x03,0x02,0x02,0x0E,0x01,          /* [5437] OBJ_id_Gost28147_89_CryptoPro_KeyMeshing */
+0x2A,0x85,0x03,0x02,0x02,0x0E,0x00,          /* [5444] OBJ_id_Gost28147_89_None_KeyMeshing */
+0x2A,0x85,0x03,0x02,0x02,0x1E,0x00,          /* [5451] OBJ_id_GostR3411_94_TestParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1E,0x01,          /* [5458] OBJ_id_GostR3411_94_CryptoProParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x00,          /* [5465] OBJ_id_Gost28147_89_TestParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x01,          /* [5472] OBJ_id_Gost28147_89_CryptoPro_A_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x02,          /* [5479] OBJ_id_Gost28147_89_CryptoPro_B_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x03,          /* [5486] OBJ_id_Gost28147_89_CryptoPro_C_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x04,          /* [5493] OBJ_id_Gost28147_89_CryptoPro_D_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x05,          /* [5500] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x06,          /* [5507] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x1F,0x07,          /* [5514] OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x20,0x00,          /* [5521] OBJ_id_GostR3410_94_TestParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x20,0x02,          /* [5528] OBJ_id_GostR3410_94_CryptoPro_A_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x20,0x03,          /* [5535] OBJ_id_GostR3410_94_CryptoPro_B_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x20,0x04,          /* [5542] OBJ_id_GostR3410_94_CryptoPro_C_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x20,0x05,          /* [5549] OBJ_id_GostR3410_94_CryptoPro_D_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x21,0x01,          /* [5556] OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x21,0x02,          /* [5563] OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x21,0x03,          /* [5570] OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x23,0x00,          /* [5577] OBJ_id_GostR3410_2001_TestParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x23,0x01,          /* [5584] OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x23,0x02,          /* [5591] OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x23,0x03,          /* [5598] OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x24,0x00,          /* [5605] OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x24,0x01,          /* [5612] OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet */
+0x2A,0x85,0x03,0x02,0x02,0x14,0x01,          /* [5619] OBJ_id_GostR3410_94_a */
+0x2A,0x85,0x03,0x02,0x02,0x14,0x02,          /* [5626] OBJ_id_GostR3410_94_aBis */
+0x2A,0x85,0x03,0x02,0x02,0x14,0x03,          /* [5633] OBJ_id_GostR3410_94_b */
+0x2A,0x85,0x03,0x02,0x02,0x14,0x04,          /* [5640] OBJ_id_GostR3410_94_bBis */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x06,0x01,     /* [5647] OBJ_id_Gost28147_89_cc */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x03,     /* [5655] OBJ_id_GostR3410_94_cc */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x04,     /* [5663] OBJ_id_GostR3410_2001_cc */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x03,     /* [5671] OBJ_id_GostR3411_94_with_GostR3410_94_cc */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x04,     /* [5679] OBJ_id_GostR3411_94_with_GostR3410_2001_cc */
+0x2A,0x85,0x03,0x02,0x09,0x01,0x08,0x01,     /* [5687] OBJ_id_GostR3410_2001_ParamSet_cc */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x02,/* [5695] OBJ_LocalKeySet */
+0x55,0x1D,0x2E,                              /* [5704] OBJ_freshest_crl */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x03,     /* [5707] OBJ_id_on_permanentIdentifier */
+0x55,0x04,0x0E,                              /* [5715] OBJ_searchGuide */
+0x55,0x04,0x0F,                              /* [5718] OBJ_businessCategory */
+0x55,0x04,0x10,                              /* [5721] OBJ_postalAddress */
+0x55,0x04,0x12,                              /* [5724] OBJ_postOfficeBox */
+0x55,0x04,0x13,                              /* [5727] OBJ_physicalDeliveryOfficeName */
+0x55,0x04,0x14,                              /* [5730] OBJ_telephoneNumber */
+0x55,0x04,0x15,                              /* [5733] OBJ_telexNumber */
+0x55,0x04,0x16,                              /* [5736] OBJ_teletexTerminalIdentifier */
+0x55,0x04,0x17,                              /* [5739] OBJ_facsimileTelephoneNumber */
+0x55,0x04,0x18,                              /* [5742] OBJ_x121Address */
+0x55,0x04,0x19,                              /* [5745] OBJ_internationaliSDNNumber */
+0x55,0x04,0x1A,                              /* [5748] OBJ_registeredAddress */
+0x55,0x04,0x1B,                              /* [5751] OBJ_destinationIndicator */
+0x55,0x04,0x1C,                              /* [5754] OBJ_preferredDeliveryMethod */
+0x55,0x04,0x1D,                              /* [5757] OBJ_presentationAddress */
+0x55,0x04,0x1E,                              /* [5760] OBJ_supportedApplicationContext */
+0x55,0x04,0x1F,                              /* [5763] OBJ_member */
+0x55,0x04,0x20,                              /* [5766] OBJ_owner */
+0x55,0x04,0x21,                              /* [5769] OBJ_roleOccupant */
+0x55,0x04,0x22,                              /* [5772] OBJ_seeAlso */
+0x55,0x04,0x23,                              /* [5775] OBJ_userPassword */
+0x55,0x04,0x24,                              /* [5778] OBJ_userCertificate */
+0x55,0x04,0x25,                              /* [5781] OBJ_cACertificate */
+0x55,0x04,0x26,                              /* [5784] OBJ_authorityRevocationList */
+0x55,0x04,0x27,                              /* [5787] OBJ_certificateRevocationList */
+0x55,0x04,0x28,                              /* [5790] OBJ_crossCertificatePair */
+0x55,0x04,0x2F,                              /* [5793] OBJ_enhancedSearchGuide */
+0x55,0x04,0x30,                              /* [5796] OBJ_protocolInformation */
+0x55,0x04,0x31,                              /* [5799] OBJ_distinguishedName */
+0x55,0x04,0x32,                              /* [5802] OBJ_uniqueMember */
+0x55,0x04,0x33,                              /* [5805] OBJ_houseIdentifier */
+0x55,0x04,0x34,                              /* [5808] OBJ_supportedAlgorithms */
+0x55,0x04,0x35,                              /* [5811] OBJ_deltaRevocationList */
+0x55,0x04,0x36,                              /* [5814] OBJ_dmdName */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x09,/* [5817] OBJ_id_alg_PWRI_KEK */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x06,/* [5828] OBJ_aes_128_gcm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x07,/* [5837] OBJ_aes_128_ccm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x08,/* [5846] OBJ_id_aes128_wrap_pad */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1A,/* [5855] OBJ_aes_192_gcm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1B,/* [5864] OBJ_aes_192_ccm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1C,/* [5873] OBJ_id_aes192_wrap_pad */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2E,/* [5882] OBJ_aes_256_gcm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2F,/* [5891] OBJ_aes_256_ccm */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x30,/* [5900] OBJ_id_aes256_wrap_pad */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x02,/* [5909] OBJ_id_camellia128_wrap */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x03,/* [5920] OBJ_id_camellia192_wrap */
+0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x04,/* [5931] OBJ_id_camellia256_wrap */
+0x55,0x1D,0x25,0x00,                         /* [5942] OBJ_anyExtendedKeyUsage */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,/* [5946] OBJ_mgf1 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,/* [5955] OBJ_rsassaPss */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x07,/* [5964] OBJ_rsaesOaep */
+0x2B,0x24,                                   /* [5973] OBJ_teletrust */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,          /* [5975] OBJ_brainpool */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01,/* [5982] OBJ_brainpoolP160r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x02,/* [5991] OBJ_brainpoolP160t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03,/* [6000] OBJ_brainpoolP192r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x04,/* [6009] OBJ_brainpoolP192t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05,/* [6018] OBJ_brainpoolP224r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x06,/* [6027] OBJ_brainpoolP224t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07,/* [6036] OBJ_brainpoolP256r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x08,/* [6045] OBJ_brainpoolP256t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09,/* [6054] OBJ_brainpoolP320r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0A,/* [6063] OBJ_brainpoolP320t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B,/* [6072] OBJ_brainpoolP384r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0C,/* [6081] OBJ_brainpoolP384t1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D,/* [6090] OBJ_brainpoolP512r1 */
+0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0E,/* [6099] OBJ_brainpoolP512t1 */
+0x2A,0x81,0x7A,0x01,0x81,0x5F,0x65,0x82,0x00,0x01,/* [6108] OBJ_FRP256v1 */
+0x2A,0x85,0x03,0x07,0x01,                    /* [6118] OBJ_tc26 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02,     /* [6123] OBJ_id_tc26_gost3411_2012_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03,     /* [6131] OBJ_id_tc26_gost3411_2012_512 */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01,/* [6139] OBJ_id_tc26_gost_3410_12_512_paramSetA */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02,/* [6148] OBJ_id_tc26_gost_3410_12_512_paramSetB */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01,/* [6157] OBJ_id_tc26_gost_28147_param_Z */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01,     /* [6166] OBJ_id_tc26_gost3410_2012_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02,     /* [6174] OBJ_id_tc26_gost3410_2012_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02,     /* [6182] OBJ_id_tc26_signwithdigest_gost3410_2012_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03,     /* [6190] OBJ_id_tc26_signwithdigest_gost3410_2012_512 */
+0x2B,0x65,0x6E,                              /* [6198] OBJ_X25519 */
+0x2B,0x65,0x6F,                              /* [6201] OBJ_X448 */
+0x2B,0x65,0x70,                              /* [6204] OBJ_Ed25519 */
+0x2B,0x65,0x71,                              /* [6207] OBJ_Ed448 */
+0x2B,0x65,0x72,                              /* [6210] OBJ_Ed25519ph */
+0x2B,0x65,0x73,                              /* [6213] OBJ_Ed448ph */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x01,/* [6216] OBJ_jurisdictionLocalityName */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02,/* [6227] OBJ_jurisdictionStateOrProvinceName */
+0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03,/* [6238] OBJ_jurisdictionCountryName */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11,     /* [6249] OBJ_sm3 */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78,     /* [6257] OBJ_sm3WithRSAEncryption */
+0x2A,0x81,0x1C,                              /* [6265] OBJ_ISO_CN */
+0x2A,0x81,0x1C,0xCF,0x55,                    /* [6268] OBJ_oscca */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,               /* [6273] OBJ_sm_scheme */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x01,     /* [6279] OBJ_sm4_ecb */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x02,     /* [6287] OBJ_sm4_cbc */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x03,     /* [6295] OBJ_sm4_ofb128 */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x04,     /* [6303] OBJ_sm4_cfb128 */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x05,     /* [6311] OBJ_sm4_cfb1 */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x06,     /* [6319] OBJ_sm4_cfb8 */
+0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x07,     /* [6327] OBJ_sm4_ctr */
+0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x02,/* [6335] OBJ_dhSinglePass_stdDH_sha1kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x00,               /* [6344] OBJ_dhSinglePass_stdDH_sha224kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x01,               /* [6350] OBJ_dhSinglePass_stdDH_sha256kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x02,               /* [6356] OBJ_dhSinglePass_stdDH_sha384kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0B,0x03,               /* [6362] OBJ_dhSinglePass_stdDH_sha512kdf_scheme */
+0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x03,/* [6368] OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x00,               /* [6377] OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x01,               /* [6383] OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x02,               /* [6389] OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme */
+0x2B,0x81,0x04,0x01,0x0E,0x03,               /* [6395] OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x09,/* [6401] OBJ_pSpecified */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x01,/* [6410] OBJ_id_tc26_gost_3410_12_256_paramSetA */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02,/* [6419] OBJ_id_tc26_gost_3410_12_256_paramSetB */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03,/* [6428] OBJ_id_tc26_gost_3410_12_256_paramSetC */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04,/* [6437] OBJ_id_tc26_gost_3410_12_256_paramSetD */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00,/* [6446] OBJ_id_tc26_gost_3410_12_512_paramSetTest */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x03,/* [6455] OBJ_id_tc26_gost_3410_12_512_paramSetC */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01,     /* [6464] OBJ_id_tc26_hmac_gost_3411_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02,     /* [6472] OBJ_id_tc26_hmac_gost_3411_12_512 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x18,/* [6480] OBJ_id_ct_routeOriginAuthz */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1A,/* [6491] OBJ_id_ct_rpkiManifest */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x23,/* [6502] OBJ_id_ct_rpkiGhostbusters */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x24,/* [6513] OBJ_id_ct_resourceTaggedAttest */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0E,          /* [6524] OBJ_id_cp */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x1C,     /* [6531] OBJ_sbgp_ipAddrBlockv2 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x1D,     /* [6539] OBJ_sbgp_autonomousSysNumv2 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0E,0x02,     /* [6547] OBJ_ipAddr_asNumber */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x0E,0x03,     /* [6555] OBJ_ipAddr_asNumberv2 */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0A,     /* [6563] OBJ_rpkiManifest */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0B,     /* [6571] OBJ_signedObject */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x0D,     /* [6579] OBJ_rpkiNotify */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x2F,/* [6587] OBJ_id_ct_geofeedCSVwithCRLF */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x30,/* [6598] OBJ_id_ct_signedChecklist */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1E,     /* [6609] OBJ_id_kp_bgpsec_router */
+0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x18,     /* [6617] OBJ_tlsfeature */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x31,/* [6625] OBJ_id_ct_ASPA */
+0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02,/* [6636] OBJ_ct_precert_scts */
+0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x03,/* [6646] OBJ_ct_precert_poison */
+0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x04,/* [6656] OBJ_ct_precert_signer */
+0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x05,/* [6666] OBJ_ct_cert_scts */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x2F,/* [6676] OBJ_id_smime_aa_signingCertificateV2 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x32,/* [6687] OBJ_id_ct_signedTAL */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0F,/* [6698] OBJ_sha512_224WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x10,/* [6707] OBJ_sha512_256WithRSAEncryption */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C,     /* [6716] OBJ_hmacWithSHA512_224 */
+0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D,     /* [6724] OBJ_hmacWithSHA512_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x05,/* [6732] OBJ_sha512_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x06,/* [6741] OBJ_sha512_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x07,/* [6750] OBJ_sha3_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x08,/* [6759] OBJ_sha3_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x09,/* [6768] OBJ_sha3_384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0A,/* [6777] OBJ_sha3_512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0D,/* [6786] OBJ_hmac_sha3_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0E,/* [6795] OBJ_hmac_sha3_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0F,/* [6804] OBJ_hmac_sha3_384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x10,/* [6813] OBJ_hmac_sha3_512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x03,/* [6822] OBJ_dsa_with_SHA384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x04,/* [6831] OBJ_dsa_with_SHA512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x05,/* [6840] OBJ_dsa_with_SHA3_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x06,/* [6849] OBJ_dsa_with_SHA3_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x07,/* [6858] OBJ_dsa_with_SHA3_384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x08,/* [6867] OBJ_dsa_with_SHA3_512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x09,/* [6876] OBJ_ecdsa_with_SHA3_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0A,/* [6885] OBJ_ecdsa_with_SHA3_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0B,/* [6894] OBJ_ecdsa_with_SHA3_384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0C,/* [6903] OBJ_ecdsa_with_SHA3_512 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0D,/* [6912] OBJ_RSA_SHA3_224 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0E,/* [6921] OBJ_RSA_SHA3_256 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0F,/* [6930] OBJ_RSA_SHA3_384 */
+0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x10,/* [6939] OBJ_RSA_SHA3_512 */
+};
+
+static const ASN1_OBJECT nid_objs[NUM_NID]={
+{"UNDEF","undefined",NID_undef,0,NULL,0},
+{"rsadsi","RSA Data Security, Inc.",NID_rsadsi,6,&(lvalues[0]),0},
+{"pkcs","RSA Data Security, Inc. PKCS",NID_pkcs,7,&(lvalues[6]),0},
+{"MD2","md2",NID_md2,8,&(lvalues[13]),0},
+{"MD5","md5",NID_md5,8,&(lvalues[21]),0},
+{"RC4","rc4",NID_rc4,8,&(lvalues[29]),0},
+{"rsaEncryption","rsaEncryption",NID_rsaEncryption,9,&(lvalues[37]),0},
+{"RSA-MD2","md2WithRSAEncryption",NID_md2WithRSAEncryption,9,
+	&(lvalues[46]),0},
+{"RSA-MD5","md5WithRSAEncryption",NID_md5WithRSAEncryption,9,
+	&(lvalues[55]),0},
+{"PBE-MD2-DES","pbeWithMD2AndDES-CBC",NID_pbeWithMD2AndDES_CBC,9,
+	&(lvalues[64]),0},
+{"PBE-MD5-DES","pbeWithMD5AndDES-CBC",NID_pbeWithMD5AndDES_CBC,9,
+	&(lvalues[73]),0},
+{"X500","directory services (X.500)",NID_X500,1,&(lvalues[82]),0},
+{"X509","X509",NID_X509,2,&(lvalues[83]),0},
+{"CN","commonName",NID_commonName,3,&(lvalues[85]),0},
+{"C","countryName",NID_countryName,3,&(lvalues[88]),0},
+{"L","localityName",NID_localityName,3,&(lvalues[91]),0},
+{"ST","stateOrProvinceName",NID_stateOrProvinceName,3,&(lvalues[94]),0},
+{"O","organizationName",NID_organizationName,3,&(lvalues[97]),0},
+{"OU","organizationalUnitName",NID_organizationalUnitName,3,
+	&(lvalues[100]),0},
+{"RSA","rsa",NID_rsa,4,&(lvalues[103]),0},
+{"pkcs7","pkcs7",NID_pkcs7,8,&(lvalues[107]),0},
+{"pkcs7-data","pkcs7-data",NID_pkcs7_data,9,&(lvalues[115]),0},
+{"pkcs7-signedData","pkcs7-signedData",NID_pkcs7_signed,9,
+	&(lvalues[124]),0},
+{"pkcs7-envelopedData","pkcs7-envelopedData",NID_pkcs7_enveloped,9,
+	&(lvalues[133]),0},
+{"pkcs7-signedAndEnvelopedData","pkcs7-signedAndEnvelopedData",
+	NID_pkcs7_signedAndEnveloped,9,&(lvalues[142]),0},
+{"pkcs7-digestData","pkcs7-digestData",NID_pkcs7_digest,9,
+	&(lvalues[151]),0},
+{"pkcs7-encryptedData","pkcs7-encryptedData",NID_pkcs7_encrypted,9,
+	&(lvalues[160]),0},
+{"pkcs3","pkcs3",NID_pkcs3,8,&(lvalues[169]),0},
+{"dhKeyAgreement","dhKeyAgreement",NID_dhKeyAgreement,9,
+	&(lvalues[177]),0},
+{"DES-ECB","des-ecb",NID_des_ecb,5,&(lvalues[186]),0},
+{"DES-CFB","des-cfb",NID_des_cfb64,5,&(lvalues[191]),0},
+{"DES-CBC","des-cbc",NID_des_cbc,5,&(lvalues[196]),0},
+{"DES-EDE","des-ede",NID_des_ede_ecb,5,&(lvalues[201]),0},
+{"DES-EDE3","des-ede3",NID_des_ede3_ecb,0,NULL,0},
+{"IDEA-CBC","idea-cbc",NID_idea_cbc,11,&(lvalues[206]),0},
+{"IDEA-CFB","idea-cfb",NID_idea_cfb64,0,NULL,0},
+{"IDEA-ECB","idea-ecb",NID_idea_ecb,0,NULL,0},
+{"RC2-CBC","rc2-cbc",NID_rc2_cbc,8,&(lvalues[217]),0},
+{"RC2-ECB","rc2-ecb",NID_rc2_ecb,0,NULL,0},
+{"RC2-CFB","rc2-cfb",NID_rc2_cfb64,0,NULL,0},
+{"RC2-OFB","rc2-ofb",NID_rc2_ofb64,0,NULL,0},
+{"SHA","sha",NID_sha,5,&(lvalues[225]),0},
+{"RSA-SHA","shaWithRSAEncryption",NID_shaWithRSAEncryption,5,
+	&(lvalues[230]),0},
+{"DES-EDE-CBC","des-ede-cbc",NID_des_ede_cbc,0,NULL,0},
+{"DES-EDE3-CBC","des-ede3-cbc",NID_des_ede3_cbc,8,&(lvalues[235]),0},
+{"DES-OFB","des-ofb",NID_des_ofb64,5,&(lvalues[243]),0},
+{"IDEA-OFB","idea-ofb",NID_idea_ofb64,0,NULL,0},
+{"pkcs9","pkcs9",NID_pkcs9,8,&(lvalues[248]),0},
+{"emailAddress","emailAddress",NID_pkcs9_emailAddress,9,
+	&(lvalues[256]),0},
+{"unstructuredName","unstructuredName",NID_pkcs9_unstructuredName,9,
+	&(lvalues[265]),0},
+{"contentType","contentType",NID_pkcs9_contentType,9,&(lvalues[274]),0},
+{"messageDigest","messageDigest",NID_pkcs9_messageDigest,9,
+	&(lvalues[283]),0},
+{"signingTime","signingTime",NID_pkcs9_signingTime,9,&(lvalues[292]),0},
+{"countersignature","countersignature",NID_pkcs9_countersignature,9,
+	&(lvalues[301]),0},
+{"challengePassword","challengePassword",NID_pkcs9_challengePassword,
+	9,&(lvalues[310]),0},
+{"unstructuredAddress","unstructuredAddress",
+	NID_pkcs9_unstructuredAddress,9,&(lvalues[319]),0},
+{"extendedCertificateAttributes","extendedCertificateAttributes",
+	NID_pkcs9_extCertAttributes,9,&(lvalues[328]),0},
+{"Netscape","Netscape Communications Corp.",NID_netscape,7,
+	&(lvalues[337]),0},
+{"nsCertExt","Netscape Certificate Extension",
+	NID_netscape_cert_extension,8,&(lvalues[344]),0},
+{"nsDataType","Netscape Data Type",NID_netscape_data_type,8,
+	&(lvalues[352]),0},
+{"DES-EDE-CFB","des-ede-cfb",NID_des_ede_cfb64,0,NULL,0},
+{"DES-EDE3-CFB","des-ede3-cfb",NID_des_ede3_cfb64,0,NULL,0},
+{"DES-EDE-OFB","des-ede-ofb",NID_des_ede_ofb64,0,NULL,0},
+{"DES-EDE3-OFB","des-ede3-ofb",NID_des_ede3_ofb64,0,NULL,0},
+{"SHA1","sha1",NID_sha1,5,&(lvalues[360]),0},
+{"RSA-SHA1","sha1WithRSAEncryption",NID_sha1WithRSAEncryption,9,
+	&(lvalues[365]),0},
+{"DSA-SHA","dsaWithSHA",NID_dsaWithSHA,5,&(lvalues[374]),0},
+{"DSA-old","dsaEncryption-old",NID_dsa_2,5,&(lvalues[379]),0},
+{"PBE-SHA1-RC2-64","pbeWithSHA1AndRC2-CBC",NID_pbeWithSHA1AndRC2_CBC,
+	9,&(lvalues[384]),0},
+{"PBKDF2","PBKDF2",NID_id_pbkdf2,9,&(lvalues[393]),0},
+{"DSA-SHA1-old","dsaWithSHA1-old",NID_dsaWithSHA1_2,5,&(lvalues[402]),0},
+{"nsCertType","Netscape Cert Type",NID_netscape_cert_type,9,
+	&(lvalues[407]),0},
+{"nsBaseUrl","Netscape Base Url",NID_netscape_base_url,9,
+	&(lvalues[416]),0},
+{"nsRevocationUrl","Netscape Revocation Url",
+	NID_netscape_revocation_url,9,&(lvalues[425]),0},
+{"nsCaRevocationUrl","Netscape CA Revocation Url",
+	NID_netscape_ca_revocation_url,9,&(lvalues[434]),0},
+{"nsRenewalUrl","Netscape Renewal Url",NID_netscape_renewal_url,9,
+	&(lvalues[443]),0},
+{"nsCaPolicyUrl","Netscape CA Policy Url",NID_netscape_ca_policy_url,
+	9,&(lvalues[452]),0},
+{"nsSslServerName","Netscape SSL Server Name",
+	NID_netscape_ssl_server_name,9,&(lvalues[461]),0},
+{"nsComment","Netscape Comment",NID_netscape_comment,9,&(lvalues[470]),0},
+{"nsCertSequence","Netscape Certificate Sequence",
+	NID_netscape_cert_sequence,9,&(lvalues[479]),0},
+{"DESX-CBC","desx-cbc",NID_desx_cbc,0,NULL,0},
+{"id-ce","id-ce",NID_id_ce,2,&(lvalues[488]),0},
+{"subjectKeyIdentifier","X509v3 Subject Key Identifier",
+	NID_subject_key_identifier,3,&(lvalues[490]),0},
+{"keyUsage","X509v3 Key Usage",NID_key_usage,3,&(lvalues[493]),0},
+{"privateKeyUsagePeriod","X509v3 Private Key Usage Period",
+	NID_private_key_usage_period,3,&(lvalues[496]),0},
+{"subjectAltName","X509v3 Subject Alternative Name",
+	NID_subject_alt_name,3,&(lvalues[499]),0},
+{"issuerAltName","X509v3 Issuer Alternative Name",NID_issuer_alt_name,
+	3,&(lvalues[502]),0},
+{"basicConstraints","X509v3 Basic Constraints",NID_basic_constraints,
+	3,&(lvalues[505]),0},
+{"crlNumber","X509v3 CRL Number",NID_crl_number,3,&(lvalues[508]),0},
+{"certificatePolicies","X509v3 Certificate Policies",
+	NID_certificate_policies,3,&(lvalues[511]),0},
+{"authorityKeyIdentifier","X509v3 Authority Key Identifier",
+	NID_authority_key_identifier,3,&(lvalues[514]),0},
+{"BF-CBC","bf-cbc",NID_bf_cbc,9,&(lvalues[517]),0},
+{"BF-ECB","bf-ecb",NID_bf_ecb,0,NULL,0},
+{"BF-CFB","bf-cfb",NID_bf_cfb64,0,NULL,0},
+{"BF-OFB","bf-ofb",NID_bf_ofb64,0,NULL,0},
+{"MDC2","mdc2",NID_mdc2,4,&(lvalues[526]),0},
+{"RSA-MDC2","mdc2WithRSA",NID_mdc2WithRSA,4,&(lvalues[530]),0},
+{"RC4-40","rc4-40",NID_rc4_40,0,NULL,0},
+{"RC2-40-CBC","rc2-40-cbc",NID_rc2_40_cbc,0,NULL,0},
+{"GN","givenName",NID_givenName,3,&(lvalues[534]),0},
+{"SN","surname",NID_surname,3,&(lvalues[537]),0},
+{"initials","initials",NID_initials,3,&(lvalues[540]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"crlDistributionPoints","X509v3 CRL Distribution Points",
+	NID_crl_distribution_points,3,&(lvalues[543]),0},
+{"RSA-NP-MD5","md5WithRSA",NID_md5WithRSA,5,&(lvalues[546]),0},
+{"serialNumber","serialNumber",NID_serialNumber,3,&(lvalues[551]),0},
+{"title","title",NID_title,3,&(lvalues[554]),0},
+{"description","description",NID_description,3,&(lvalues[557]),0},
+{"CAST5-CBC","cast5-cbc",NID_cast5_cbc,9,&(lvalues[560]),0},
+{"CAST5-ECB","cast5-ecb",NID_cast5_ecb,0,NULL,0},
+{"CAST5-CFB","cast5-cfb",NID_cast5_cfb64,0,NULL,0},
+{"CAST5-OFB","cast5-ofb",NID_cast5_ofb64,0,NULL,0},
+{"pbeWithMD5AndCast5CBC","pbeWithMD5AndCast5CBC",
+	NID_pbeWithMD5AndCast5_CBC,9,&(lvalues[569]),0},
+{"DSA-SHA1","dsaWithSHA1",NID_dsaWithSHA1,7,&(lvalues[578]),0},
+{"MD5-SHA1","md5-sha1",NID_md5_sha1,0,NULL,0},
+{"RSA-SHA1-2","sha1WithRSA",NID_sha1WithRSA,5,&(lvalues[585]),0},
+{"DSA","dsaEncryption",NID_dsa,7,&(lvalues[590]),0},
+{"RIPEMD160","ripemd160",NID_ripemd160,5,&(lvalues[597]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"RSA-RIPEMD160","ripemd160WithRSA",NID_ripemd160WithRSA,6,
+	&(lvalues[602]),0},
+{"RC5-CBC","rc5-cbc",NID_rc5_cbc,8,&(lvalues[608]),0},
+{"RC5-ECB","rc5-ecb",NID_rc5_ecb,0,NULL,0},
+{"RC5-CFB","rc5-cfb",NID_rc5_cfb64,0,NULL,0},
+{"RC5-OFB","rc5-ofb",NID_rc5_ofb64,0,NULL,0},
+{"RLE","run length compression",NID_rle_compression,6,&(lvalues[616]),0},
+{"ZLIB","zlib compression",NID_zlib_compression,11,&(lvalues[622]),0},
+{"extendedKeyUsage","X509v3 Extended Key Usage",NID_ext_key_usage,3,
+	&(lvalues[633]),0},
+{"PKIX","PKIX",NID_id_pkix,6,&(lvalues[636]),0},
+{"id-kp","id-kp",NID_id_kp,7,&(lvalues[642]),0},
+{"serverAuth","TLS Web Server Authentication",NID_server_auth,8,
+	&(lvalues[649]),0},
+{"clientAuth","TLS Web Client Authentication",NID_client_auth,8,
+	&(lvalues[657]),0},
+{"codeSigning","Code Signing",NID_code_sign,8,&(lvalues[665]),0},
+{"emailProtection","E-mail Protection",NID_email_protect,8,
+	&(lvalues[673]),0},
+{"timeStamping","Time Stamping",NID_time_stamp,8,&(lvalues[681]),0},
+{"msCodeInd","Microsoft Individual Code Signing",NID_ms_code_ind,10,
+	&(lvalues[689]),0},
+{"msCodeCom","Microsoft Commercial Code Signing",NID_ms_code_com,10,
+	&(lvalues[699]),0},
+{"msCTLSign","Microsoft Trust List Signing",NID_ms_ctl_sign,10,
+	&(lvalues[709]),0},
+{"msSGC","Microsoft Server Gated Crypto",NID_ms_sgc,10,&(lvalues[719]),0},
+{"msEFS","Microsoft Encrypted File System",NID_ms_efs,10,
+	&(lvalues[729]),0},
+{"nsSGC","Netscape Server Gated Crypto",NID_ns_sgc,9,&(lvalues[739]),0},
+{"deltaCRL","X509v3 Delta CRL Indicator",NID_delta_crl,3,
+	&(lvalues[748]),0},
+{"CRLReason","X509v3 CRL Reason Code",NID_crl_reason,3,&(lvalues[751]),0},
+{"invalidityDate","Invalidity Date",NID_invalidity_date,3,
+	&(lvalues[754]),0},
+{"SXNetID","Strong Extranet ID",NID_sxnet,5,&(lvalues[757]),0},
+{"PBE-SHA1-RC4-128","pbeWithSHA1And128BitRC4",
+	NID_pbe_WithSHA1And128BitRC4,10,&(lvalues[762]),0},
+{"PBE-SHA1-RC4-40","pbeWithSHA1And40BitRC4",
+	NID_pbe_WithSHA1And40BitRC4,10,&(lvalues[772]),0},
+{"PBE-SHA1-3DES","pbeWithSHA1And3-KeyTripleDES-CBC",
+	NID_pbe_WithSHA1And3_Key_TripleDES_CBC,10,&(lvalues[782]),0},
+{"PBE-SHA1-2DES","pbeWithSHA1And2-KeyTripleDES-CBC",
+	NID_pbe_WithSHA1And2_Key_TripleDES_CBC,10,&(lvalues[792]),0},
+{"PBE-SHA1-RC2-128","pbeWithSHA1And128BitRC2-CBC",
+	NID_pbe_WithSHA1And128BitRC2_CBC,10,&(lvalues[802]),0},
+{"PBE-SHA1-RC2-40","pbeWithSHA1And40BitRC2-CBC",
+	NID_pbe_WithSHA1And40BitRC2_CBC,10,&(lvalues[812]),0},
+{"keyBag","keyBag",NID_keyBag,11,&(lvalues[822]),0},
+{"pkcs8ShroudedKeyBag","pkcs8ShroudedKeyBag",NID_pkcs8ShroudedKeyBag,
+	11,&(lvalues[833]),0},
+{"certBag","certBag",NID_certBag,11,&(lvalues[844]),0},
+{"crlBag","crlBag",NID_crlBag,11,&(lvalues[855]),0},
+{"secretBag","secretBag",NID_secretBag,11,&(lvalues[866]),0},
+{"safeContentsBag","safeContentsBag",NID_safeContentsBag,11,
+	&(lvalues[877]),0},
+{"friendlyName","friendlyName",NID_friendlyName,9,&(lvalues[888]),0},
+{"localKeyID","localKeyID",NID_localKeyID,9,&(lvalues[897]),0},
+{"x509Certificate","x509Certificate",NID_x509Certificate,10,
+	&(lvalues[906]),0},
+{"sdsiCertificate","sdsiCertificate",NID_sdsiCertificate,10,
+	&(lvalues[916]),0},
+{"x509Crl","x509Crl",NID_x509Crl,10,&(lvalues[926]),0},
+{"PBES2","PBES2",NID_pbes2,9,&(lvalues[936]),0},
+{"PBMAC1","PBMAC1",NID_pbmac1,9,&(lvalues[945]),0},
+{"hmacWithSHA1","hmacWithSHA1",NID_hmacWithSHA1,8,&(lvalues[954]),0},
+{"id-qt-cps","Policy Qualifier CPS",NID_id_qt_cps,8,&(lvalues[962]),0},
+{"id-qt-unotice","Policy Qualifier User Notice",NID_id_qt_unotice,8,
+	&(lvalues[970]),0},
+{"RC2-64-CBC","rc2-64-cbc",NID_rc2_64_cbc,0,NULL,0},
+{"SMIME-CAPS","S/MIME Capabilities",NID_SMIMECapabilities,9,
+	&(lvalues[978]),0},
+{"PBE-MD2-RC2-64","pbeWithMD2AndRC2-CBC",NID_pbeWithMD2AndRC2_CBC,9,
+	&(lvalues[987]),0},
+{"PBE-MD5-RC2-64","pbeWithMD5AndRC2-CBC",NID_pbeWithMD5AndRC2_CBC,9,
+	&(lvalues[996]),0},
+{"PBE-SHA1-DES","pbeWithSHA1AndDES-CBC",NID_pbeWithSHA1AndDES_CBC,9,
+	&(lvalues[1005]),0},
+{"msExtReq","Microsoft Extension Request",NID_ms_ext_req,10,
+	&(lvalues[1014]),0},
+{"extReq","Extension Request",NID_ext_req,9,&(lvalues[1024]),0},
+{"name","name",NID_name,3,&(lvalues[1033]),0},
+{"dnQualifier","dnQualifier",NID_dnQualifier,3,&(lvalues[1036]),0},
+{"id-pe","id-pe",NID_id_pe,7,&(lvalues[1039]),0},
+{"id-ad","id-ad",NID_id_ad,7,&(lvalues[1046]),0},
+{"authorityInfoAccess","Authority Information Access",NID_info_access,
+	8,&(lvalues[1053]),0},
+{"OCSP","OCSP",NID_ad_OCSP,8,&(lvalues[1061]),0},
+{"caIssuers","CA Issuers",NID_ad_ca_issuers,8,&(lvalues[1069]),0},
+{"OCSPSigning","OCSP Signing",NID_OCSP_sign,8,&(lvalues[1077]),0},
+{"ISO","iso",NID_iso,0,NULL,0},
+{"member-body","ISO Member Body",NID_member_body,1,&(lvalues[1085]),0},
+{"ISO-US","ISO US Member Body",NID_ISO_US,3,&(lvalues[1086]),0},
+{"X9-57","X9.57",NID_X9_57,5,&(lvalues[1089]),0},
+{"X9cm","X9.57 CM ?",NID_X9cm,6,&(lvalues[1094]),0},
+{"pkcs1","pkcs1",NID_pkcs1,8,&(lvalues[1100]),0},
+{"pkcs5","pkcs5",NID_pkcs5,8,&(lvalues[1108]),0},
+{"SMIME","S/MIME",NID_SMIME,9,&(lvalues[1116]),0},
+{"id-smime-mod","id-smime-mod",NID_id_smime_mod,10,&(lvalues[1125]),0},
+{"id-smime-ct","id-smime-ct",NID_id_smime_ct,10,&(lvalues[1135]),0},
+{"id-smime-aa","id-smime-aa",NID_id_smime_aa,10,&(lvalues[1145]),0},
+{"id-smime-alg","id-smime-alg",NID_id_smime_alg,10,&(lvalues[1155]),0},
+{"id-smime-cd","id-smime-cd",NID_id_smime_cd,10,&(lvalues[1165]),0},
+{"id-smime-spq","id-smime-spq",NID_id_smime_spq,10,&(lvalues[1175]),0},
+{"id-smime-cti","id-smime-cti",NID_id_smime_cti,10,&(lvalues[1185]),0},
+{"id-smime-mod-cms","id-smime-mod-cms",NID_id_smime_mod_cms,11,
+	&(lvalues[1195]),0},
+{"id-smime-mod-ess","id-smime-mod-ess",NID_id_smime_mod_ess,11,
+	&(lvalues[1206]),0},
+{"id-smime-mod-oid","id-smime-mod-oid",NID_id_smime_mod_oid,11,
+	&(lvalues[1217]),0},
+{"id-smime-mod-msg-v3","id-smime-mod-msg-v3",NID_id_smime_mod_msg_v3,
+	11,&(lvalues[1228]),0},
+{"id-smime-mod-ets-eSignature-88","id-smime-mod-ets-eSignature-88",
+	NID_id_smime_mod_ets_eSignature_88,11,&(lvalues[1239]),0},
+{"id-smime-mod-ets-eSignature-97","id-smime-mod-ets-eSignature-97",
+	NID_id_smime_mod_ets_eSignature_97,11,&(lvalues[1250]),0},
+{"id-smime-mod-ets-eSigPolicy-88","id-smime-mod-ets-eSigPolicy-88",
+	NID_id_smime_mod_ets_eSigPolicy_88,11,&(lvalues[1261]),0},
+{"id-smime-mod-ets-eSigPolicy-97","id-smime-mod-ets-eSigPolicy-97",
+	NID_id_smime_mod_ets_eSigPolicy_97,11,&(lvalues[1272]),0},
+{"id-smime-ct-receipt","id-smime-ct-receipt",NID_id_smime_ct_receipt,
+	11,&(lvalues[1283]),0},
+{"id-smime-ct-authData","id-smime-ct-authData",
+	NID_id_smime_ct_authData,11,&(lvalues[1294]),0},
+{"id-smime-ct-publishCert","id-smime-ct-publishCert",
+	NID_id_smime_ct_publishCert,11,&(lvalues[1305]),0},
+{"id-smime-ct-TSTInfo","id-smime-ct-TSTInfo",NID_id_smime_ct_TSTInfo,
+	11,&(lvalues[1316]),0},
+{"id-smime-ct-TDTInfo","id-smime-ct-TDTInfo",NID_id_smime_ct_TDTInfo,
+	11,&(lvalues[1327]),0},
+{"id-smime-ct-contentInfo","id-smime-ct-contentInfo",
+	NID_id_smime_ct_contentInfo,11,&(lvalues[1338]),0},
+{"id-smime-ct-DVCSRequestData","id-smime-ct-DVCSRequestData",
+	NID_id_smime_ct_DVCSRequestData,11,&(lvalues[1349]),0},
+{"id-smime-ct-DVCSResponseData","id-smime-ct-DVCSResponseData",
+	NID_id_smime_ct_DVCSResponseData,11,&(lvalues[1360]),0},
+{"id-smime-aa-receiptRequest","id-smime-aa-receiptRequest",
+	NID_id_smime_aa_receiptRequest,11,&(lvalues[1371]),0},
+{"id-smime-aa-securityLabel","id-smime-aa-securityLabel",
+	NID_id_smime_aa_securityLabel,11,&(lvalues[1382]),0},
+{"id-smime-aa-mlExpandHistory","id-smime-aa-mlExpandHistory",
+	NID_id_smime_aa_mlExpandHistory,11,&(lvalues[1393]),0},
+{"id-smime-aa-contentHint","id-smime-aa-contentHint",
+	NID_id_smime_aa_contentHint,11,&(lvalues[1404]),0},
+{"id-smime-aa-msgSigDigest","id-smime-aa-msgSigDigest",
+	NID_id_smime_aa_msgSigDigest,11,&(lvalues[1415]),0},
+{"id-smime-aa-encapContentType","id-smime-aa-encapContentType",
+	NID_id_smime_aa_encapContentType,11,&(lvalues[1426]),0},
+{"id-smime-aa-contentIdentifier","id-smime-aa-contentIdentifier",
+	NID_id_smime_aa_contentIdentifier,11,&(lvalues[1437]),0},
+{"id-smime-aa-macValue","id-smime-aa-macValue",
+	NID_id_smime_aa_macValue,11,&(lvalues[1448]),0},
+{"id-smime-aa-equivalentLabels","id-smime-aa-equivalentLabels",
+	NID_id_smime_aa_equivalentLabels,11,&(lvalues[1459]),0},
+{"id-smime-aa-contentReference","id-smime-aa-contentReference",
+	NID_id_smime_aa_contentReference,11,&(lvalues[1470]),0},
+{"id-smime-aa-encrypKeyPref","id-smime-aa-encrypKeyPref",
+	NID_id_smime_aa_encrypKeyPref,11,&(lvalues[1481]),0},
+{"id-smime-aa-signingCertificate","id-smime-aa-signingCertificate",
+	NID_id_smime_aa_signingCertificate,11,&(lvalues[1492]),0},
+{"id-smime-aa-smimeEncryptCerts","id-smime-aa-smimeEncryptCerts",
+	NID_id_smime_aa_smimeEncryptCerts,11,&(lvalues[1503]),0},
+{"id-smime-aa-timeStampToken","id-smime-aa-timeStampToken",
+	NID_id_smime_aa_timeStampToken,11,&(lvalues[1514]),0},
+{"id-smime-aa-ets-sigPolicyId","id-smime-aa-ets-sigPolicyId",
+	NID_id_smime_aa_ets_sigPolicyId,11,&(lvalues[1525]),0},
+{"id-smime-aa-ets-commitmentType","id-smime-aa-ets-commitmentType",
+	NID_id_smime_aa_ets_commitmentType,11,&(lvalues[1536]),0},
+{"id-smime-aa-ets-signerLocation","id-smime-aa-ets-signerLocation",
+	NID_id_smime_aa_ets_signerLocation,11,&(lvalues[1547]),0},
+{"id-smime-aa-ets-signerAttr","id-smime-aa-ets-signerAttr",
+	NID_id_smime_aa_ets_signerAttr,11,&(lvalues[1558]),0},
+{"id-smime-aa-ets-otherSigCert","id-smime-aa-ets-otherSigCert",
+	NID_id_smime_aa_ets_otherSigCert,11,&(lvalues[1569]),0},
+{"id-smime-aa-ets-contentTimestamp",
+	"id-smime-aa-ets-contentTimestamp",
+	NID_id_smime_aa_ets_contentTimestamp,11,&(lvalues[1580]),0},
+{"id-smime-aa-ets-CertificateRefs","id-smime-aa-ets-CertificateRefs",
+	NID_id_smime_aa_ets_CertificateRefs,11,&(lvalues[1591]),0},
+{"id-smime-aa-ets-RevocationRefs","id-smime-aa-ets-RevocationRefs",
+	NID_id_smime_aa_ets_RevocationRefs,11,&(lvalues[1602]),0},
+{"id-smime-aa-ets-certValues","id-smime-aa-ets-certValues",
+	NID_id_smime_aa_ets_certValues,11,&(lvalues[1613]),0},
+{"id-smime-aa-ets-revocationValues",
+	"id-smime-aa-ets-revocationValues",
+	NID_id_smime_aa_ets_revocationValues,11,&(lvalues[1624]),0},
+{"id-smime-aa-ets-escTimeStamp","id-smime-aa-ets-escTimeStamp",
+	NID_id_smime_aa_ets_escTimeStamp,11,&(lvalues[1635]),0},
+{"id-smime-aa-ets-certCRLTimestamp",
+	"id-smime-aa-ets-certCRLTimestamp",
+	NID_id_smime_aa_ets_certCRLTimestamp,11,&(lvalues[1646]),0},
+{"id-smime-aa-ets-archiveTimeStamp",
+	"id-smime-aa-ets-archiveTimeStamp",
+	NID_id_smime_aa_ets_archiveTimeStamp,11,&(lvalues[1657]),0},
+{"id-smime-aa-signatureType","id-smime-aa-signatureType",
+	NID_id_smime_aa_signatureType,11,&(lvalues[1668]),0},
+{"id-smime-aa-dvcs-dvc","id-smime-aa-dvcs-dvc",
+	NID_id_smime_aa_dvcs_dvc,11,&(lvalues[1679]),0},
+{"id-smime-alg-ESDHwith3DES","id-smime-alg-ESDHwith3DES",
+	NID_id_smime_alg_ESDHwith3DES,11,&(lvalues[1690]),0},
+{"id-smime-alg-ESDHwithRC2","id-smime-alg-ESDHwithRC2",
+	NID_id_smime_alg_ESDHwithRC2,11,&(lvalues[1701]),0},
+{"id-smime-alg-3DESwrap","id-smime-alg-3DESwrap",
+	NID_id_smime_alg_3DESwrap,11,&(lvalues[1712]),0},
+{"id-smime-alg-RC2wrap","id-smime-alg-RC2wrap",
+	NID_id_smime_alg_RC2wrap,11,&(lvalues[1723]),0},
+{"id-smime-alg-ESDH","id-smime-alg-ESDH",NID_id_smime_alg_ESDH,11,
+	&(lvalues[1734]),0},
+{"id-smime-alg-CMS3DESwrap","id-smime-alg-CMS3DESwrap",
+	NID_id_smime_alg_CMS3DESwrap,11,&(lvalues[1745]),0},
+{"id-smime-alg-CMSRC2wrap","id-smime-alg-CMSRC2wrap",
+	NID_id_smime_alg_CMSRC2wrap,11,&(lvalues[1756]),0},
+{"id-smime-cd-ldap","id-smime-cd-ldap",NID_id_smime_cd_ldap,11,
+	&(lvalues[1767]),0},
+{"id-smime-spq-ets-sqt-uri","id-smime-spq-ets-sqt-uri",
+	NID_id_smime_spq_ets_sqt_uri,11,&(lvalues[1778]),0},
+{"id-smime-spq-ets-sqt-unotice","id-smime-spq-ets-sqt-unotice",
+	NID_id_smime_spq_ets_sqt_unotice,11,&(lvalues[1789]),0},
+{"id-smime-cti-ets-proofOfOrigin","id-smime-cti-ets-proofOfOrigin",
+	NID_id_smime_cti_ets_proofOfOrigin,11,&(lvalues[1800]),0},
+{"id-smime-cti-ets-proofOfReceipt","id-smime-cti-ets-proofOfReceipt",
+	NID_id_smime_cti_ets_proofOfReceipt,11,&(lvalues[1811]),0},
+{"id-smime-cti-ets-proofOfDelivery",
+	"id-smime-cti-ets-proofOfDelivery",
+	NID_id_smime_cti_ets_proofOfDelivery,11,&(lvalues[1822]),0},
+{"id-smime-cti-ets-proofOfSender","id-smime-cti-ets-proofOfSender",
+	NID_id_smime_cti_ets_proofOfSender,11,&(lvalues[1833]),0},
+{"id-smime-cti-ets-proofOfApproval",
+	"id-smime-cti-ets-proofOfApproval",
+	NID_id_smime_cti_ets_proofOfApproval,11,&(lvalues[1844]),0},
+{"id-smime-cti-ets-proofOfCreation",
+	"id-smime-cti-ets-proofOfCreation",
+	NID_id_smime_cti_ets_proofOfCreation,11,&(lvalues[1855]),0},
+{"MD4","md4",NID_md4,8,&(lvalues[1866]),0},
+{"id-pkix-mod","id-pkix-mod",NID_id_pkix_mod,7,&(lvalues[1874]),0},
+{"id-qt","id-qt",NID_id_qt,7,&(lvalues[1881]),0},
+{"id-it","id-it",NID_id_it,7,&(lvalues[1888]),0},
+{"id-pkip","id-pkip",NID_id_pkip,7,&(lvalues[1895]),0},
+{"id-alg","id-alg",NID_id_alg,7,&(lvalues[1902]),0},
+{"id-cmc","id-cmc",NID_id_cmc,7,&(lvalues[1909]),0},
+{"id-on","id-on",NID_id_on,7,&(lvalues[1916]),0},
+{"id-pda","id-pda",NID_id_pda,7,&(lvalues[1923]),0},
+{"id-aca","id-aca",NID_id_aca,7,&(lvalues[1930]),0},
+{"id-qcs","id-qcs",NID_id_qcs,7,&(lvalues[1937]),0},
+{"id-cct","id-cct",NID_id_cct,7,&(lvalues[1944]),0},
+{"id-pkix1-explicit-88","id-pkix1-explicit-88",
+	NID_id_pkix1_explicit_88,8,&(lvalues[1951]),0},
+{"id-pkix1-implicit-88","id-pkix1-implicit-88",
+	NID_id_pkix1_implicit_88,8,&(lvalues[1959]),0},
+{"id-pkix1-explicit-93","id-pkix1-explicit-93",
+	NID_id_pkix1_explicit_93,8,&(lvalues[1967]),0},
+{"id-pkix1-implicit-93","id-pkix1-implicit-93",
+	NID_id_pkix1_implicit_93,8,&(lvalues[1975]),0},
+{"id-mod-crmf","id-mod-crmf",NID_id_mod_crmf,8,&(lvalues[1983]),0},
+{"id-mod-cmc","id-mod-cmc",NID_id_mod_cmc,8,&(lvalues[1991]),0},
+{"id-mod-kea-profile-88","id-mod-kea-profile-88",
+	NID_id_mod_kea_profile_88,8,&(lvalues[1999]),0},
+{"id-mod-kea-profile-93","id-mod-kea-profile-93",
+	NID_id_mod_kea_profile_93,8,&(lvalues[2007]),0},
+{"id-mod-cmp","id-mod-cmp",NID_id_mod_cmp,8,&(lvalues[2015]),0},
+{"id-mod-qualified-cert-88","id-mod-qualified-cert-88",
+	NID_id_mod_qualified_cert_88,8,&(lvalues[2023]),0},
+{"id-mod-qualified-cert-93","id-mod-qualified-cert-93",
+	NID_id_mod_qualified_cert_93,8,&(lvalues[2031]),0},
+{"id-mod-attribute-cert","id-mod-attribute-cert",
+	NID_id_mod_attribute_cert,8,&(lvalues[2039]),0},
+{"id-mod-timestamp-protocol","id-mod-timestamp-protocol",
+	NID_id_mod_timestamp_protocol,8,&(lvalues[2047]),0},
+{"id-mod-ocsp","id-mod-ocsp",NID_id_mod_ocsp,8,&(lvalues[2055]),0},
+{"id-mod-dvcs","id-mod-dvcs",NID_id_mod_dvcs,8,&(lvalues[2063]),0},
+{"id-mod-cmp2000","id-mod-cmp2000",NID_id_mod_cmp2000,8,
+	&(lvalues[2071]),0},
+{"biometricInfo","Biometric Info",NID_biometricInfo,8,&(lvalues[2079]),0},
+{"qcStatements","qcStatements",NID_qcStatements,8,&(lvalues[2087]),0},
+{"ac-auditEntity","ac-auditEntity",NID_ac_auditEntity,8,
+	&(lvalues[2095]),0},
+{"ac-targeting","ac-targeting",NID_ac_targeting,8,&(lvalues[2103]),0},
+{"aaControls","aaControls",NID_aaControls,8,&(lvalues[2111]),0},
+{"sbgp-ipAddrBlock","sbgp-ipAddrBlock",NID_sbgp_ipAddrBlock,8,
+	&(lvalues[2119]),0},
+{"sbgp-autonomousSysNum","sbgp-autonomousSysNum",
+	NID_sbgp_autonomousSysNum,8,&(lvalues[2127]),0},
+{"sbgp-routerIdentifier","sbgp-routerIdentifier",
+	NID_sbgp_routerIdentifier,8,&(lvalues[2135]),0},
+{"textNotice","textNotice",NID_textNotice,8,&(lvalues[2143]),0},
+{"ipsecEndSystem","IPSec End System",NID_ipsecEndSystem,8,
+	&(lvalues[2151]),0},
+{"ipsecTunnel","IPSec Tunnel",NID_ipsecTunnel,8,&(lvalues[2159]),0},
+{"ipsecUser","IPSec User",NID_ipsecUser,8,&(lvalues[2167]),0},
+{"DVCS","dvcs",NID_dvcs,8,&(lvalues[2175]),0},
+{"id-it-caProtEncCert","id-it-caProtEncCert",NID_id_it_caProtEncCert,
+	8,&(lvalues[2183]),0},
+{"id-it-signKeyPairTypes","id-it-signKeyPairTypes",
+	NID_id_it_signKeyPairTypes,8,&(lvalues[2191]),0},
+{"id-it-encKeyPairTypes","id-it-encKeyPairTypes",
+	NID_id_it_encKeyPairTypes,8,&(lvalues[2199]),0},
+{"id-it-preferredSymmAlg","id-it-preferredSymmAlg",
+	NID_id_it_preferredSymmAlg,8,&(lvalues[2207]),0},
+{"id-it-caKeyUpdateInfo","id-it-caKeyUpdateInfo",
+	NID_id_it_caKeyUpdateInfo,8,&(lvalues[2215]),0},
+{"id-it-currentCRL","id-it-currentCRL",NID_id_it_currentCRL,8,
+	&(lvalues[2223]),0},
+{"id-it-unsupportedOIDs","id-it-unsupportedOIDs",
+	NID_id_it_unsupportedOIDs,8,&(lvalues[2231]),0},
+{"id-it-subscriptionRequest","id-it-subscriptionRequest",
+	NID_id_it_subscriptionRequest,8,&(lvalues[2239]),0},
+{"id-it-subscriptionResponse","id-it-subscriptionResponse",
+	NID_id_it_subscriptionResponse,8,&(lvalues[2247]),0},
+{"id-it-keyPairParamReq","id-it-keyPairParamReq",
+	NID_id_it_keyPairParamReq,8,&(lvalues[2255]),0},
+{"id-it-keyPairParamRep","id-it-keyPairParamRep",
+	NID_id_it_keyPairParamRep,8,&(lvalues[2263]),0},
+{"id-it-revPassphrase","id-it-revPassphrase",NID_id_it_revPassphrase,
+	8,&(lvalues[2271]),0},
+{"id-it-implicitConfirm","id-it-implicitConfirm",
+	NID_id_it_implicitConfirm,8,&(lvalues[2279]),0},
+{"id-it-confirmWaitTime","id-it-confirmWaitTime",
+	NID_id_it_confirmWaitTime,8,&(lvalues[2287]),0},
+{"id-it-origPKIMessage","id-it-origPKIMessage",
+	NID_id_it_origPKIMessage,8,&(lvalues[2295]),0},
+{"id-regCtrl","id-regCtrl",NID_id_regCtrl,8,&(lvalues[2303]),0},
+{"id-regInfo","id-regInfo",NID_id_regInfo,8,&(lvalues[2311]),0},
+{"id-regCtrl-regToken","id-regCtrl-regToken",NID_id_regCtrl_regToken,
+	9,&(lvalues[2319]),0},
+{"id-regCtrl-authenticator","id-regCtrl-authenticator",
+	NID_id_regCtrl_authenticator,9,&(lvalues[2328]),0},
+{"id-regCtrl-pkiPublicationInfo","id-regCtrl-pkiPublicationInfo",
+	NID_id_regCtrl_pkiPublicationInfo,9,&(lvalues[2337]),0},
+{"id-regCtrl-pkiArchiveOptions","id-regCtrl-pkiArchiveOptions",
+	NID_id_regCtrl_pkiArchiveOptions,9,&(lvalues[2346]),0},
+{"id-regCtrl-oldCertID","id-regCtrl-oldCertID",
+	NID_id_regCtrl_oldCertID,9,&(lvalues[2355]),0},
+{"id-regCtrl-protocolEncrKey","id-regCtrl-protocolEncrKey",
+	NID_id_regCtrl_protocolEncrKey,9,&(lvalues[2364]),0},
+{"id-regInfo-utf8Pairs","id-regInfo-utf8Pairs",
+	NID_id_regInfo_utf8Pairs,9,&(lvalues[2373]),0},
+{"id-regInfo-certReq","id-regInfo-certReq",NID_id_regInfo_certReq,9,
+	&(lvalues[2382]),0},
+{"id-alg-des40","id-alg-des40",NID_id_alg_des40,8,&(lvalues[2391]),0},
+{"id-alg-noSignature","id-alg-noSignature",NID_id_alg_noSignature,8,
+	&(lvalues[2399]),0},
+{"id-alg-dh-sig-hmac-sha1","id-alg-dh-sig-hmac-sha1",
+	NID_id_alg_dh_sig_hmac_sha1,8,&(lvalues[2407]),0},
+{"id-alg-dh-pop","id-alg-dh-pop",NID_id_alg_dh_pop,8,&(lvalues[2415]),0},
+{"id-cmc-statusInfo","id-cmc-statusInfo",NID_id_cmc_statusInfo,8,
+	&(lvalues[2423]),0},
+{"id-cmc-identification","id-cmc-identification",
+	NID_id_cmc_identification,8,&(lvalues[2431]),0},
+{"id-cmc-identityProof","id-cmc-identityProof",
+	NID_id_cmc_identityProof,8,&(lvalues[2439]),0},
+{"id-cmc-dataReturn","id-cmc-dataReturn",NID_id_cmc_dataReturn,8,
+	&(lvalues[2447]),0},
+{"id-cmc-transactionId","id-cmc-transactionId",
+	NID_id_cmc_transactionId,8,&(lvalues[2455]),0},
+{"id-cmc-senderNonce","id-cmc-senderNonce",NID_id_cmc_senderNonce,8,
+	&(lvalues[2463]),0},
+{"id-cmc-recipientNonce","id-cmc-recipientNonce",
+	NID_id_cmc_recipientNonce,8,&(lvalues[2471]),0},
+{"id-cmc-addExtensions","id-cmc-addExtensions",
+	NID_id_cmc_addExtensions,8,&(lvalues[2479]),0},
+{"id-cmc-encryptedPOP","id-cmc-encryptedPOP",NID_id_cmc_encryptedPOP,
+	8,&(lvalues[2487]),0},
+{"id-cmc-decryptedPOP","id-cmc-decryptedPOP",NID_id_cmc_decryptedPOP,
+	8,&(lvalues[2495]),0},
+{"id-cmc-lraPOPWitness","id-cmc-lraPOPWitness",
+	NID_id_cmc_lraPOPWitness,8,&(lvalues[2503]),0},
+{"id-cmc-getCert","id-cmc-getCert",NID_id_cmc_getCert,8,
+	&(lvalues[2511]),0},
+{"id-cmc-getCRL","id-cmc-getCRL",NID_id_cmc_getCRL,8,&(lvalues[2519]),0},
+{"id-cmc-revokeRequest","id-cmc-revokeRequest",
+	NID_id_cmc_revokeRequest,8,&(lvalues[2527]),0},
+{"id-cmc-regInfo","id-cmc-regInfo",NID_id_cmc_regInfo,8,
+	&(lvalues[2535]),0},
+{"id-cmc-responseInfo","id-cmc-responseInfo",NID_id_cmc_responseInfo,
+	8,&(lvalues[2543]),0},
+{"id-cmc-queryPending","id-cmc-queryPending",NID_id_cmc_queryPending,
+	8,&(lvalues[2551]),0},
+{"id-cmc-popLinkRandom","id-cmc-popLinkRandom",
+	NID_id_cmc_popLinkRandom,8,&(lvalues[2559]),0},
+{"id-cmc-popLinkWitness","id-cmc-popLinkWitness",
+	NID_id_cmc_popLinkWitness,8,&(lvalues[2567]),0},
+{"id-cmc-confirmCertAcceptance","id-cmc-confirmCertAcceptance",
+	NID_id_cmc_confirmCertAcceptance,8,&(lvalues[2575]),0},
+{"id-on-personalData","id-on-personalData",NID_id_on_personalData,8,
+	&(lvalues[2583]),0},
+{"id-pda-dateOfBirth","id-pda-dateOfBirth",NID_id_pda_dateOfBirth,8,
+	&(lvalues[2591]),0},
+{"id-pda-placeOfBirth","id-pda-placeOfBirth",NID_id_pda_placeOfBirth,
+	8,&(lvalues[2599]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"id-pda-gender","id-pda-gender",NID_id_pda_gender,8,&(lvalues[2607]),0},
+{"id-pda-countryOfCitizenship","id-pda-countryOfCitizenship",
+	NID_id_pda_countryOfCitizenship,8,&(lvalues[2615]),0},
+{"id-pda-countryOfResidence","id-pda-countryOfResidence",
+	NID_id_pda_countryOfResidence,8,&(lvalues[2623]),0},
+{"id-aca-authenticationInfo","id-aca-authenticationInfo",
+	NID_id_aca_authenticationInfo,8,&(lvalues[2631]),0},
+{"id-aca-accessIdentity","id-aca-accessIdentity",
+	NID_id_aca_accessIdentity,8,&(lvalues[2639]),0},
+{"id-aca-chargingIdentity","id-aca-chargingIdentity",
+	NID_id_aca_chargingIdentity,8,&(lvalues[2647]),0},
+{"id-aca-group","id-aca-group",NID_id_aca_group,8,&(lvalues[2655]),0},
+{"id-aca-role","id-aca-role",NID_id_aca_role,8,&(lvalues[2663]),0},
+{"id-qcs-pkixQCSyntax-v1","id-qcs-pkixQCSyntax-v1",
+	NID_id_qcs_pkixQCSyntax_v1,8,&(lvalues[2671]),0},
+{"id-cct-crs","id-cct-crs",NID_id_cct_crs,8,&(lvalues[2679]),0},
+{"id-cct-PKIData","id-cct-PKIData",NID_id_cct_PKIData,8,
+	&(lvalues[2687]),0},
+{"id-cct-PKIResponse","id-cct-PKIResponse",NID_id_cct_PKIResponse,8,
+	&(lvalues[2695]),0},
+{"ad_timestamping","AD Time Stamping",NID_ad_timeStamping,8,
+	&(lvalues[2703]),0},
+{"AD_DVCS","ad dvcs",NID_ad_dvcs,8,&(lvalues[2711]),0},
+{"basicOCSPResponse","Basic OCSP Response",NID_id_pkix_OCSP_basic,9,
+	&(lvalues[2719]),0},
+{"Nonce","OCSP Nonce",NID_id_pkix_OCSP_Nonce,9,&(lvalues[2728]),0},
+{"CrlID","OCSP CRL ID",NID_id_pkix_OCSP_CrlID,9,&(lvalues[2737]),0},
+{"acceptableResponses","Acceptable OCSP Responses",
+	NID_id_pkix_OCSP_acceptableResponses,9,&(lvalues[2746]),0},
+{"noCheck","OCSP No Check",NID_id_pkix_OCSP_noCheck,9,&(lvalues[2755]),0},
+{"archiveCutoff","OCSP Archive Cutoff",NID_id_pkix_OCSP_archiveCutoff,
+	9,&(lvalues[2764]),0},
+{"serviceLocator","OCSP Service Locator",
+	NID_id_pkix_OCSP_serviceLocator,9,&(lvalues[2773]),0},
+{"extendedStatus","Extended OCSP Status",
+	NID_id_pkix_OCSP_extendedStatus,9,&(lvalues[2782]),0},
+{"valid","valid",NID_id_pkix_OCSP_valid,9,&(lvalues[2791]),0},
+{"path","path",NID_id_pkix_OCSP_path,9,&(lvalues[2800]),0},
+{"trustRoot","Trust Root",NID_id_pkix_OCSP_trustRoot,9,
+	&(lvalues[2809]),0},
+{"algorithm","algorithm",NID_algorithm,4,&(lvalues[2818]),0},
+{"rsaSignature","rsaSignature",NID_rsaSignature,5,&(lvalues[2822]),0},
+{"X500algorithms","directory services - algorithms",
+	NID_X500algorithms,2,&(lvalues[2827]),0},
+{"ORG","org",NID_org,1,&(lvalues[2829]),0},
+{"DOD","dod",NID_dod,2,&(lvalues[2830]),0},
+{"IANA","iana",NID_iana,3,&(lvalues[2832]),0},
+{"directory","Directory",NID_Directory,4,&(lvalues[2835]),0},
+{"mgmt","Management",NID_Management,4,&(lvalues[2839]),0},
+{"experimental","Experimental",NID_Experimental,4,&(lvalues[2843]),0},
+{"private","Private",NID_Private,4,&(lvalues[2847]),0},
+{"security","Security",NID_Security,4,&(lvalues[2851]),0},
+{"snmpv2","SNMPv2",NID_SNMPv2,4,&(lvalues[2855]),0},
+{"Mail","Mail",NID_Mail,4,&(lvalues[2859]),0},
+{"enterprises","Enterprises",NID_Enterprises,5,&(lvalues[2863]),0},
+{"dcobject","dcObject",NID_dcObject,9,&(lvalues[2868]),0},
+{"DC","domainComponent",NID_domainComponent,10,&(lvalues[2877]),0},
+{"domain","Domain",NID_Domain,10,&(lvalues[2887]),0},
+{"NULL","NULL",NID_joint_iso_ccitt,0,NULL,0},
+{"selected-attribute-types","Selected Attribute Types",
+	NID_selected_attribute_types,3,&(lvalues[2897]),0},
+{"clearance","clearance",NID_clearance,4,&(lvalues[2900]),0},
+{"RSA-MD4","md4WithRSAEncryption",NID_md4WithRSAEncryption,9,
+	&(lvalues[2904]),0},
+{"ac-proxying","ac-proxying",NID_ac_proxying,8,&(lvalues[2913]),0},
+{"subjectInfoAccess","Subject Information Access",NID_sinfo_access,8,
+	&(lvalues[2921]),0},
+{"id-aca-encAttrs","id-aca-encAttrs",NID_id_aca_encAttrs,8,
+	&(lvalues[2929]),0},
+{"role","role",NID_role,3,&(lvalues[2937]),0},
+{"policyConstraints","X509v3 Policy Constraints",
+	NID_policy_constraints,3,&(lvalues[2940]),0},
+{"targetInformation","X509v3 AC Targeting",NID_target_information,3,
+	&(lvalues[2943]),0},
+{"noRevAvail","X509v3 No Revocation Available",NID_no_rev_avail,3,
+	&(lvalues[2946]),0},
+{"NULL","NULL",NID_ccitt,0,NULL,0},
+{"ansi-X9-62","ANSI X9.62",NID_ansi_X9_62,5,&(lvalues[2949]),0},
+{"prime-field","prime-field",NID_X9_62_prime_field,7,&(lvalues[2954]),0},
+{"characteristic-two-field","characteristic-two-field",
+	NID_X9_62_characteristic_two_field,7,&(lvalues[2961]),0},
+{"id-ecPublicKey","id-ecPublicKey",NID_X9_62_id_ecPublicKey,7,
+	&(lvalues[2968]),0},
+{"prime192v1","prime192v1",NID_X9_62_prime192v1,8,&(lvalues[2975]),0},
+{"prime192v2","prime192v2",NID_X9_62_prime192v2,8,&(lvalues[2983]),0},
+{"prime192v3","prime192v3",NID_X9_62_prime192v3,8,&(lvalues[2991]),0},
+{"prime239v1","prime239v1",NID_X9_62_prime239v1,8,&(lvalues[2999]),0},
+{"prime239v2","prime239v2",NID_X9_62_prime239v2,8,&(lvalues[3007]),0},
+{"prime239v3","prime239v3",NID_X9_62_prime239v3,8,&(lvalues[3015]),0},
+{"prime256v1","prime256v1",NID_X9_62_prime256v1,8,&(lvalues[3023]),0},
+{"ecdsa-with-SHA1","ecdsa-with-SHA1",NID_ecdsa_with_SHA1,7,
+	&(lvalues[3031]),0},
+{"CSPName","Microsoft CSP Name",NID_ms_csp_name,9,&(lvalues[3038]),0},
+{"AES-128-ECB","aes-128-ecb",NID_aes_128_ecb,9,&(lvalues[3047]),0},
+{"AES-128-CBC","aes-128-cbc",NID_aes_128_cbc,9,&(lvalues[3056]),0},
+{"AES-128-OFB","aes-128-ofb",NID_aes_128_ofb128,9,&(lvalues[3065]),0},
+{"AES-128-CFB","aes-128-cfb",NID_aes_128_cfb128,9,&(lvalues[3074]),0},
+{"AES-192-ECB","aes-192-ecb",NID_aes_192_ecb,9,&(lvalues[3083]),0},
+{"AES-192-CBC","aes-192-cbc",NID_aes_192_cbc,9,&(lvalues[3092]),0},
+{"AES-192-OFB","aes-192-ofb",NID_aes_192_ofb128,9,&(lvalues[3101]),0},
+{"AES-192-CFB","aes-192-cfb",NID_aes_192_cfb128,9,&(lvalues[3110]),0},
+{"AES-256-ECB","aes-256-ecb",NID_aes_256_ecb,9,&(lvalues[3119]),0},
+{"AES-256-CBC","aes-256-cbc",NID_aes_256_cbc,9,&(lvalues[3128]),0},
+{"AES-256-OFB","aes-256-ofb",NID_aes_256_ofb128,9,&(lvalues[3137]),0},
+{"AES-256-CFB","aes-256-cfb",NID_aes_256_cfb128,9,&(lvalues[3146]),0},
+{"holdInstructionCode","Hold Instruction Code",
+	NID_hold_instruction_code,3,&(lvalues[3155]),0},
+{"holdInstructionNone","Hold Instruction None",
+	NID_hold_instruction_none,7,&(lvalues[3158]),0},
+{"holdInstructionCallIssuer","Hold Instruction Call Issuer",
+	NID_hold_instruction_call_issuer,7,&(lvalues[3165]),0},
+{"holdInstructionReject","Hold Instruction Reject",
+	NID_hold_instruction_reject,7,&(lvalues[3172]),0},
+{"data","data",NID_data,1,&(lvalues[3179]),0},
+{"pss","pss",NID_pss,3,&(lvalues[3180]),0},
+{"ucl","ucl",NID_ucl,7,&(lvalues[3183]),0},
+{"pilot","pilot",NID_pilot,8,&(lvalues[3190]),0},
+{"pilotAttributeType","pilotAttributeType",NID_pilotAttributeType,9,
+	&(lvalues[3198]),0},
+{"pilotAttributeSyntax","pilotAttributeSyntax",
+	NID_pilotAttributeSyntax,9,&(lvalues[3207]),0},
+{"pilotObjectClass","pilotObjectClass",NID_pilotObjectClass,9,
+	&(lvalues[3216]),0},
+{"pilotGroups","pilotGroups",NID_pilotGroups,9,&(lvalues[3225]),0},
+{"iA5StringSyntax","iA5StringSyntax",NID_iA5StringSyntax,10,
+	&(lvalues[3234]),0},
+{"caseIgnoreIA5StringSyntax","caseIgnoreIA5StringSyntax",
+	NID_caseIgnoreIA5StringSyntax,10,&(lvalues[3244]),0},
+{"pilotObject","pilotObject",NID_pilotObject,10,&(lvalues[3254]),0},
+{"pilotPerson","pilotPerson",NID_pilotPerson,10,&(lvalues[3264]),0},
+{"account","account",NID_account,10,&(lvalues[3274]),0},
+{"document","document",NID_document,10,&(lvalues[3284]),0},
+{"room","room",NID_room,10,&(lvalues[3294]),0},
+{"documentSeries","documentSeries",NID_documentSeries,10,
+	&(lvalues[3304]),0},
+{"rFC822localPart","rFC822localPart",NID_rFC822localPart,10,
+	&(lvalues[3314]),0},
+{"dNSDomain","dNSDomain",NID_dNSDomain,10,&(lvalues[3324]),0},
+{"domainRelatedObject","domainRelatedObject",NID_domainRelatedObject,
+	10,&(lvalues[3334]),0},
+{"friendlyCountry","friendlyCountry",NID_friendlyCountry,10,
+	&(lvalues[3344]),0},
+{"simpleSecurityObject","simpleSecurityObject",
+	NID_simpleSecurityObject,10,&(lvalues[3354]),0},
+{"pilotOrganization","pilotOrganization",NID_pilotOrganization,10,
+	&(lvalues[3364]),0},
+{"pilotDSA","pilotDSA",NID_pilotDSA,10,&(lvalues[3374]),0},
+{"qualityLabelledData","qualityLabelledData",NID_qualityLabelledData,
+	10,&(lvalues[3384]),0},
+{"UID","userId",NID_userId,10,&(lvalues[3394]),0},
+{"textEncodedORAddress","textEncodedORAddress",
+	NID_textEncodedORAddress,10,&(lvalues[3404]),0},
+{"mail","rfc822Mailbox",NID_rfc822Mailbox,10,&(lvalues[3414]),0},
+{"info","info",NID_info,10,&(lvalues[3424]),0},
+{"favouriteDrink","favouriteDrink",NID_favouriteDrink,10,
+	&(lvalues[3434]),0},
+{"roomNumber","roomNumber",NID_roomNumber,10,&(lvalues[3444]),0},
+{"photo","photo",NID_photo,10,&(lvalues[3454]),0},
+{"userClass","userClass",NID_userClass,10,&(lvalues[3464]),0},
+{"host","host",NID_host,10,&(lvalues[3474]),0},
+{"manager","manager",NID_manager,10,&(lvalues[3484]),0},
+{"documentIdentifier","documentIdentifier",NID_documentIdentifier,10,
+	&(lvalues[3494]),0},
+{"documentTitle","documentTitle",NID_documentTitle,10,&(lvalues[3504]),0},
+{"documentVersion","documentVersion",NID_documentVersion,10,
+	&(lvalues[3514]),0},
+{"documentAuthor","documentAuthor",NID_documentAuthor,10,
+	&(lvalues[3524]),0},
+{"documentLocation","documentLocation",NID_documentLocation,10,
+	&(lvalues[3534]),0},
+{"homeTelephoneNumber","homeTelephoneNumber",NID_homeTelephoneNumber,
+	10,&(lvalues[3544]),0},
+{"secretary","secretary",NID_secretary,10,&(lvalues[3554]),0},
+{"otherMailbox","otherMailbox",NID_otherMailbox,10,&(lvalues[3564]),0},
+{"lastModifiedTime","lastModifiedTime",NID_lastModifiedTime,10,
+	&(lvalues[3574]),0},
+{"lastModifiedBy","lastModifiedBy",NID_lastModifiedBy,10,
+	&(lvalues[3584]),0},
+{"aRecord","aRecord",NID_aRecord,10,&(lvalues[3594]),0},
+{"pilotAttributeType27","pilotAttributeType27",
+	NID_pilotAttributeType27,10,&(lvalues[3604]),0},
+{"mXRecord","mXRecord",NID_mXRecord,10,&(lvalues[3614]),0},
+{"nSRecord","nSRecord",NID_nSRecord,10,&(lvalues[3624]),0},
+{"sOARecord","sOARecord",NID_sOARecord,10,&(lvalues[3634]),0},
+{"cNAMERecord","cNAMERecord",NID_cNAMERecord,10,&(lvalues[3644]),0},
+{"associatedDomain","associatedDomain",NID_associatedDomain,10,
+	&(lvalues[3654]),0},
+{"associatedName","associatedName",NID_associatedName,10,
+	&(lvalues[3664]),0},
+{"homePostalAddress","homePostalAddress",NID_homePostalAddress,10,
+	&(lvalues[3674]),0},
+{"personalTitle","personalTitle",NID_personalTitle,10,&(lvalues[3684]),0},
+{"mobileTelephoneNumber","mobileTelephoneNumber",
+	NID_mobileTelephoneNumber,10,&(lvalues[3694]),0},
+{"pagerTelephoneNumber","pagerTelephoneNumber",
+	NID_pagerTelephoneNumber,10,&(lvalues[3704]),0},
+{"friendlyCountryName","friendlyCountryName",NID_friendlyCountryName,
+	10,&(lvalues[3714]),0},
+{"organizationalStatus","organizationalStatus",
+	NID_organizationalStatus,10,&(lvalues[3724]),0},
+{"janetMailbox","janetMailbox",NID_janetMailbox,10,&(lvalues[3734]),0},
+{"mailPreferenceOption","mailPreferenceOption",
+	NID_mailPreferenceOption,10,&(lvalues[3744]),0},
+{"buildingName","buildingName",NID_buildingName,10,&(lvalues[3754]),0},
+{"dSAQuality","dSAQuality",NID_dSAQuality,10,&(lvalues[3764]),0},
+{"singleLevelQuality","singleLevelQuality",NID_singleLevelQuality,10,
+	&(lvalues[3774]),0},
+{"subtreeMinimumQuality","subtreeMinimumQuality",
+	NID_subtreeMinimumQuality,10,&(lvalues[3784]),0},
+{"subtreeMaximumQuality","subtreeMaximumQuality",
+	NID_subtreeMaximumQuality,10,&(lvalues[3794]),0},
+{"personalSignature","personalSignature",NID_personalSignature,10,
+	&(lvalues[3804]),0},
+{"dITRedirect","dITRedirect",NID_dITRedirect,10,&(lvalues[3814]),0},
+{"audio","audio",NID_audio,10,&(lvalues[3824]),0},
+{"documentPublisher","documentPublisher",NID_documentPublisher,10,
+	&(lvalues[3834]),0},
+{"x500UniqueIdentifier","x500UniqueIdentifier",
+	NID_x500UniqueIdentifier,3,&(lvalues[3844]),0},
+{"mime-mhs","MIME MHS",NID_mime_mhs,5,&(lvalues[3847]),0},
+{"mime-mhs-headings","mime-mhs-headings",NID_mime_mhs_headings,6,
+	&(lvalues[3852]),0},
+{"mime-mhs-bodies","mime-mhs-bodies",NID_mime_mhs_bodies,6,
+	&(lvalues[3858]),0},
+{"id-hex-partial-message","id-hex-partial-message",
+	NID_id_hex_partial_message,7,&(lvalues[3864]),0},
+{"id-hex-multipart-message","id-hex-multipart-message",
+	NID_id_hex_multipart_message,7,&(lvalues[3871]),0},
+{"generationQualifier","generationQualifier",NID_generationQualifier,
+	3,&(lvalues[3878]),0},
+{"pseudonym","pseudonym",NID_pseudonym,3,&(lvalues[3881]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"id-set","Secure Electronic Transactions",NID_id_set,2,
+	&(lvalues[3884]),0},
+{"set-ctype","content types",NID_set_ctype,3,&(lvalues[3886]),0},
+{"set-msgExt","message extensions",NID_set_msgExt,3,&(lvalues[3889]),0},
+{"set-attr","set-attr",NID_set_attr,3,&(lvalues[3892]),0},
+{"set-policy","set-policy",NID_set_policy,3,&(lvalues[3895]),0},
+{"set-certExt","certificate extensions",NID_set_certExt,3,
+	&(lvalues[3898]),0},
+{"set-brand","set-brand",NID_set_brand,3,&(lvalues[3901]),0},
+{"setct-PANData","setct-PANData",NID_setct_PANData,4,&(lvalues[3904]),0},
+{"setct-PANToken","setct-PANToken",NID_setct_PANToken,4,
+	&(lvalues[3908]),0},
+{"setct-PANOnly","setct-PANOnly",NID_setct_PANOnly,4,&(lvalues[3912]),0},
+{"setct-OIData","setct-OIData",NID_setct_OIData,4,&(lvalues[3916]),0},
+{"setct-PI","setct-PI",NID_setct_PI,4,&(lvalues[3920]),0},
+{"setct-PIData","setct-PIData",NID_setct_PIData,4,&(lvalues[3924]),0},
+{"setct-PIDataUnsigned","setct-PIDataUnsigned",
+	NID_setct_PIDataUnsigned,4,&(lvalues[3928]),0},
+{"setct-HODInput","setct-HODInput",NID_setct_HODInput,4,
+	&(lvalues[3932]),0},
+{"setct-AuthResBaggage","setct-AuthResBaggage",
+	NID_setct_AuthResBaggage,4,&(lvalues[3936]),0},
+{"setct-AuthRevReqBaggage","setct-AuthRevReqBaggage",
+	NID_setct_AuthRevReqBaggage,4,&(lvalues[3940]),0},
+{"setct-AuthRevResBaggage","setct-AuthRevResBaggage",
+	NID_setct_AuthRevResBaggage,4,&(lvalues[3944]),0},
+{"setct-CapTokenSeq","setct-CapTokenSeq",NID_setct_CapTokenSeq,4,
+	&(lvalues[3948]),0},
+{"setct-PInitResData","setct-PInitResData",NID_setct_PInitResData,4,
+	&(lvalues[3952]),0},
+{"setct-PI-TBS","setct-PI-TBS",NID_setct_PI_TBS,4,&(lvalues[3956]),0},
+{"setct-PResData","setct-PResData",NID_setct_PResData,4,
+	&(lvalues[3960]),0},
+{"setct-AuthReqTBS","setct-AuthReqTBS",NID_setct_AuthReqTBS,4,
+	&(lvalues[3964]),0},
+{"setct-AuthResTBS","setct-AuthResTBS",NID_setct_AuthResTBS,4,
+	&(lvalues[3968]),0},
+{"setct-AuthResTBSX","setct-AuthResTBSX",NID_setct_AuthResTBSX,4,
+	&(lvalues[3972]),0},
+{"setct-AuthTokenTBS","setct-AuthTokenTBS",NID_setct_AuthTokenTBS,4,
+	&(lvalues[3976]),0},
+{"setct-CapTokenData","setct-CapTokenData",NID_setct_CapTokenData,4,
+	&(lvalues[3980]),0},
+{"setct-CapTokenTBS","setct-CapTokenTBS",NID_setct_CapTokenTBS,4,
+	&(lvalues[3984]),0},
+{"setct-AcqCardCodeMsg","setct-AcqCardCodeMsg",
+	NID_setct_AcqCardCodeMsg,4,&(lvalues[3988]),0},
+{"setct-AuthRevReqTBS","setct-AuthRevReqTBS",NID_setct_AuthRevReqTBS,
+	4,&(lvalues[3992]),0},
+{"setct-AuthRevResData","setct-AuthRevResData",
+	NID_setct_AuthRevResData,4,&(lvalues[3996]),0},
+{"setct-AuthRevResTBS","setct-AuthRevResTBS",NID_setct_AuthRevResTBS,
+	4,&(lvalues[4000]),0},
+{"setct-CapReqTBS","setct-CapReqTBS",NID_setct_CapReqTBS,4,
+	&(lvalues[4004]),0},
+{"setct-CapReqTBSX","setct-CapReqTBSX",NID_setct_CapReqTBSX,4,
+	&(lvalues[4008]),0},
+{"setct-CapResData","setct-CapResData",NID_setct_CapResData,4,
+	&(lvalues[4012]),0},
+{"setct-CapRevReqTBS","setct-CapRevReqTBS",NID_setct_CapRevReqTBS,4,
+	&(lvalues[4016]),0},
+{"setct-CapRevReqTBSX","setct-CapRevReqTBSX",NID_setct_CapRevReqTBSX,
+	4,&(lvalues[4020]),0},
+{"setct-CapRevResData","setct-CapRevResData",NID_setct_CapRevResData,
+	4,&(lvalues[4024]),0},
+{"setct-CredReqTBS","setct-CredReqTBS",NID_setct_CredReqTBS,4,
+	&(lvalues[4028]),0},
+{"setct-CredReqTBSX","setct-CredReqTBSX",NID_setct_CredReqTBSX,4,
+	&(lvalues[4032]),0},
+{"setct-CredResData","setct-CredResData",NID_setct_CredResData,4,
+	&(lvalues[4036]),0},
+{"setct-CredRevReqTBS","setct-CredRevReqTBS",NID_setct_CredRevReqTBS,
+	4,&(lvalues[4040]),0},
+{"setct-CredRevReqTBSX","setct-CredRevReqTBSX",
+	NID_setct_CredRevReqTBSX,4,&(lvalues[4044]),0},
+{"setct-CredRevResData","setct-CredRevResData",
+	NID_setct_CredRevResData,4,&(lvalues[4048]),0},
+{"setct-PCertReqData","setct-PCertReqData",NID_setct_PCertReqData,4,
+	&(lvalues[4052]),0},
+{"setct-PCertResTBS","setct-PCertResTBS",NID_setct_PCertResTBS,4,
+	&(lvalues[4056]),0},
+{"setct-BatchAdminReqData","setct-BatchAdminReqData",
+	NID_setct_BatchAdminReqData,4,&(lvalues[4060]),0},
+{"setct-BatchAdminResData","setct-BatchAdminResData",
+	NID_setct_BatchAdminResData,4,&(lvalues[4064]),0},
+{"setct-CardCInitResTBS","setct-CardCInitResTBS",
+	NID_setct_CardCInitResTBS,4,&(lvalues[4068]),0},
+{"setct-MeAqCInitResTBS","setct-MeAqCInitResTBS",
+	NID_setct_MeAqCInitResTBS,4,&(lvalues[4072]),0},
+{"setct-RegFormResTBS","setct-RegFormResTBS",NID_setct_RegFormResTBS,
+	4,&(lvalues[4076]),0},
+{"setct-CertReqData","setct-CertReqData",NID_setct_CertReqData,4,
+	&(lvalues[4080]),0},
+{"setct-CertReqTBS","setct-CertReqTBS",NID_setct_CertReqTBS,4,
+	&(lvalues[4084]),0},
+{"setct-CertResData","setct-CertResData",NID_setct_CertResData,4,
+	&(lvalues[4088]),0},
+{"setct-CertInqReqTBS","setct-CertInqReqTBS",NID_setct_CertInqReqTBS,
+	4,&(lvalues[4092]),0},
+{"setct-ErrorTBS","setct-ErrorTBS",NID_setct_ErrorTBS,4,
+	&(lvalues[4096]),0},
+{"setct-PIDualSignedTBE","setct-PIDualSignedTBE",
+	NID_setct_PIDualSignedTBE,4,&(lvalues[4100]),0},
+{"setct-PIUnsignedTBE","setct-PIUnsignedTBE",NID_setct_PIUnsignedTBE,
+	4,&(lvalues[4104]),0},
+{"setct-AuthReqTBE","setct-AuthReqTBE",NID_setct_AuthReqTBE,4,
+	&(lvalues[4108]),0},
+{"setct-AuthResTBE","setct-AuthResTBE",NID_setct_AuthResTBE,4,
+	&(lvalues[4112]),0},
+{"setct-AuthResTBEX","setct-AuthResTBEX",NID_setct_AuthResTBEX,4,
+	&(lvalues[4116]),0},
+{"setct-AuthTokenTBE","setct-AuthTokenTBE",NID_setct_AuthTokenTBE,4,
+	&(lvalues[4120]),0},
+{"setct-CapTokenTBE","setct-CapTokenTBE",NID_setct_CapTokenTBE,4,
+	&(lvalues[4124]),0},
+{"setct-CapTokenTBEX","setct-CapTokenTBEX",NID_setct_CapTokenTBEX,4,
+	&(lvalues[4128]),0},
+{"setct-AcqCardCodeMsgTBE","setct-AcqCardCodeMsgTBE",
+	NID_setct_AcqCardCodeMsgTBE,4,&(lvalues[4132]),0},
+{"setct-AuthRevReqTBE","setct-AuthRevReqTBE",NID_setct_AuthRevReqTBE,
+	4,&(lvalues[4136]),0},
+{"setct-AuthRevResTBE","setct-AuthRevResTBE",NID_setct_AuthRevResTBE,
+	4,&(lvalues[4140]),0},
+{"setct-AuthRevResTBEB","setct-AuthRevResTBEB",
+	NID_setct_AuthRevResTBEB,4,&(lvalues[4144]),0},
+{"setct-CapReqTBE","setct-CapReqTBE",NID_setct_CapReqTBE,4,
+	&(lvalues[4148]),0},
+{"setct-CapReqTBEX","setct-CapReqTBEX",NID_setct_CapReqTBEX,4,
+	&(lvalues[4152]),0},
+{"setct-CapResTBE","setct-CapResTBE",NID_setct_CapResTBE,4,
+	&(lvalues[4156]),0},
+{"setct-CapRevReqTBE","setct-CapRevReqTBE",NID_setct_CapRevReqTBE,4,
+	&(lvalues[4160]),0},
+{"setct-CapRevReqTBEX","setct-CapRevReqTBEX",NID_setct_CapRevReqTBEX,
+	4,&(lvalues[4164]),0},
+{"setct-CapRevResTBE","setct-CapRevResTBE",NID_setct_CapRevResTBE,4,
+	&(lvalues[4168]),0},
+{"setct-CredReqTBE","setct-CredReqTBE",NID_setct_CredReqTBE,4,
+	&(lvalues[4172]),0},
+{"setct-CredReqTBEX","setct-CredReqTBEX",NID_setct_CredReqTBEX,4,
+	&(lvalues[4176]),0},
+{"setct-CredResTBE","setct-CredResTBE",NID_setct_CredResTBE,4,
+	&(lvalues[4180]),0},
+{"setct-CredRevReqTBE","setct-CredRevReqTBE",NID_setct_CredRevReqTBE,
+	4,&(lvalues[4184]),0},
+{"setct-CredRevReqTBEX","setct-CredRevReqTBEX",
+	NID_setct_CredRevReqTBEX,4,&(lvalues[4188]),0},
+{"setct-CredRevResTBE","setct-CredRevResTBE",NID_setct_CredRevResTBE,
+	4,&(lvalues[4192]),0},
+{"setct-BatchAdminReqTBE","setct-BatchAdminReqTBE",
+	NID_setct_BatchAdminReqTBE,4,&(lvalues[4196]),0},
+{"setct-BatchAdminResTBE","setct-BatchAdminResTBE",
+	NID_setct_BatchAdminResTBE,4,&(lvalues[4200]),0},
+{"setct-RegFormReqTBE","setct-RegFormReqTBE",NID_setct_RegFormReqTBE,
+	4,&(lvalues[4204]),0},
+{"setct-CertReqTBE","setct-CertReqTBE",NID_setct_CertReqTBE,4,
+	&(lvalues[4208]),0},
+{"setct-CertReqTBEX","setct-CertReqTBEX",NID_setct_CertReqTBEX,4,
+	&(lvalues[4212]),0},
+{"setct-CertResTBE","setct-CertResTBE",NID_setct_CertResTBE,4,
+	&(lvalues[4216]),0},
+{"setct-CRLNotificationTBS","setct-CRLNotificationTBS",
+	NID_setct_CRLNotificationTBS,4,&(lvalues[4220]),0},
+{"setct-CRLNotificationResTBS","setct-CRLNotificationResTBS",
+	NID_setct_CRLNotificationResTBS,4,&(lvalues[4224]),0},
+{"setct-BCIDistributionTBS","setct-BCIDistributionTBS",
+	NID_setct_BCIDistributionTBS,4,&(lvalues[4228]),0},
+{"setext-genCrypt","generic cryptogram",NID_setext_genCrypt,4,
+	&(lvalues[4232]),0},
+{"setext-miAuth","merchant initiated auth",NID_setext_miAuth,4,
+	&(lvalues[4236]),0},
+{"setext-pinSecure","setext-pinSecure",NID_setext_pinSecure,4,
+	&(lvalues[4240]),0},
+{"setext-pinAny","setext-pinAny",NID_setext_pinAny,4,&(lvalues[4244]),0},
+{"setext-track2","setext-track2",NID_setext_track2,4,&(lvalues[4248]),0},
+{"setext-cv","additional verification",NID_setext_cv,4,
+	&(lvalues[4252]),0},
+{"set-policy-root","set-policy-root",NID_set_policy_root,4,
+	&(lvalues[4256]),0},
+{"setCext-hashedRoot","setCext-hashedRoot",NID_setCext_hashedRoot,4,
+	&(lvalues[4260]),0},
+{"setCext-certType","setCext-certType",NID_setCext_certType,4,
+	&(lvalues[4264]),0},
+{"setCext-merchData","setCext-merchData",NID_setCext_merchData,4,
+	&(lvalues[4268]),0},
+{"setCext-cCertRequired","setCext-cCertRequired",
+	NID_setCext_cCertRequired,4,&(lvalues[4272]),0},
+{"setCext-tunneling","setCext-tunneling",NID_setCext_tunneling,4,
+	&(lvalues[4276]),0},
+{"setCext-setExt","setCext-setExt",NID_setCext_setExt,4,
+	&(lvalues[4280]),0},
+{"setCext-setQualf","setCext-setQualf",NID_setCext_setQualf,4,
+	&(lvalues[4284]),0},
+{"setCext-PGWYcapabilities","setCext-PGWYcapabilities",
+	NID_setCext_PGWYcapabilities,4,&(lvalues[4288]),0},
+{"setCext-TokenIdentifier","setCext-TokenIdentifier",
+	NID_setCext_TokenIdentifier,4,&(lvalues[4292]),0},
+{"setCext-Track2Data","setCext-Track2Data",NID_setCext_Track2Data,4,
+	&(lvalues[4296]),0},
+{"setCext-TokenType","setCext-TokenType",NID_setCext_TokenType,4,
+	&(lvalues[4300]),0},
+{"setCext-IssuerCapabilities","setCext-IssuerCapabilities",
+	NID_setCext_IssuerCapabilities,4,&(lvalues[4304]),0},
+{"setAttr-Cert","setAttr-Cert",NID_setAttr_Cert,4,&(lvalues[4308]),0},
+{"setAttr-PGWYcap","payment gateway capabilities",NID_setAttr_PGWYcap,
+	4,&(lvalues[4312]),0},
+{"setAttr-TokenType","setAttr-TokenType",NID_setAttr_TokenType,4,
+	&(lvalues[4316]),0},
+{"setAttr-IssCap","issuer capabilities",NID_setAttr_IssCap,4,
+	&(lvalues[4320]),0},
+{"set-rootKeyThumb","set-rootKeyThumb",NID_set_rootKeyThumb,5,
+	&(lvalues[4324]),0},
+{"set-addPolicy","set-addPolicy",NID_set_addPolicy,5,&(lvalues[4329]),0},
+{"setAttr-Token-EMV","setAttr-Token-EMV",NID_setAttr_Token_EMV,5,
+	&(lvalues[4334]),0},
+{"setAttr-Token-B0Prime","setAttr-Token-B0Prime",
+	NID_setAttr_Token_B0Prime,5,&(lvalues[4339]),0},
+{"setAttr-IssCap-CVM","setAttr-IssCap-CVM",NID_setAttr_IssCap_CVM,5,
+	&(lvalues[4344]),0},
+{"setAttr-IssCap-T2","setAttr-IssCap-T2",NID_setAttr_IssCap_T2,5,
+	&(lvalues[4349]),0},
+{"setAttr-IssCap-Sig","setAttr-IssCap-Sig",NID_setAttr_IssCap_Sig,5,
+	&(lvalues[4354]),0},
+{"setAttr-GenCryptgrm","generate cryptogram",NID_setAttr_GenCryptgrm,
+	6,&(lvalues[4359]),0},
+{"setAttr-T2Enc","encrypted track 2",NID_setAttr_T2Enc,6,
+	&(lvalues[4365]),0},
+{"setAttr-T2cleartxt","cleartext track 2",NID_setAttr_T2cleartxt,6,
+	&(lvalues[4371]),0},
+{"setAttr-TokICCsig","ICC or token signature",NID_setAttr_TokICCsig,6,
+	&(lvalues[4377]),0},
+{"setAttr-SecDevSig","secure device signature",NID_setAttr_SecDevSig,
+	6,&(lvalues[4383]),0},
+{"set-brand-IATA-ATA","set-brand-IATA-ATA",NID_set_brand_IATA_ATA,4,
+	&(lvalues[4389]),0},
+{"set-brand-Diners","set-brand-Diners",NID_set_brand_Diners,4,
+	&(lvalues[4393]),0},
+{"set-brand-AmericanExpress","set-brand-AmericanExpress",
+	NID_set_brand_AmericanExpress,4,&(lvalues[4397]),0},
+{"set-brand-JCB","set-brand-JCB",NID_set_brand_JCB,4,&(lvalues[4401]),0},
+{"set-brand-Visa","set-brand-Visa",NID_set_brand_Visa,4,
+	&(lvalues[4405]),0},
+{"set-brand-MasterCard","set-brand-MasterCard",
+	NID_set_brand_MasterCard,4,&(lvalues[4409]),0},
+{"set-brand-Novus","set-brand-Novus",NID_set_brand_Novus,5,
+	&(lvalues[4413]),0},
+{"DES-CDMF","des-cdmf",NID_des_cdmf,8,&(lvalues[4418]),0},
+{"rsaOAEPEncryptionSET","rsaOAEPEncryptionSET",
+	NID_rsaOAEPEncryptionSET,9,&(lvalues[4426]),0},
+{"ITU-T","itu-t",NID_itu_t,0,NULL,0},
+{"JOINT-ISO-ITU-T","joint-iso-itu-t",NID_joint_iso_itu_t,0,NULL,0},
+{"international-organizations","International Organizations",
+	NID_international_organizations,1,&(lvalues[4435]),0},
+{"msSmartcardLogin","Microsoft Smartcardlogin",NID_ms_smartcard_login,
+	10,&(lvalues[4436]),0},
+{"msUPN","Microsoft Universal Principal Name",NID_ms_upn,10,
+	&(lvalues[4446]),0},
+{"AES-128-CFB1","aes-128-cfb1",NID_aes_128_cfb1,0,NULL,0},
+{"AES-192-CFB1","aes-192-cfb1",NID_aes_192_cfb1,0,NULL,0},
+{"AES-256-CFB1","aes-256-cfb1",NID_aes_256_cfb1,0,NULL,0},
+{"AES-128-CFB8","aes-128-cfb8",NID_aes_128_cfb8,0,NULL,0},
+{"AES-192-CFB8","aes-192-cfb8",NID_aes_192_cfb8,0,NULL,0},
+{"AES-256-CFB8","aes-256-cfb8",NID_aes_256_cfb8,0,NULL,0},
+{"DES-CFB1","des-cfb1",NID_des_cfb1,0,NULL,0},
+{"DES-CFB8","des-cfb8",NID_des_cfb8,0,NULL,0},
+{"DES-EDE3-CFB1","des-ede3-cfb1",NID_des_ede3_cfb1,0,NULL,0},
+{"DES-EDE3-CFB8","des-ede3-cfb8",NID_des_ede3_cfb8,0,NULL,0},
+{"street","streetAddress",NID_streetAddress,3,&(lvalues[4456]),0},
+{"postalCode","postalCode",NID_postalCode,3,&(lvalues[4459]),0},
+{"id-ppl","id-ppl",NID_id_ppl,7,&(lvalues[4462]),0},
+{"proxyCertInfo","Proxy Certificate Information",NID_proxyCertInfo,8,
+	&(lvalues[4469]),0},
+{"id-ppl-anyLanguage","Any language",NID_id_ppl_anyLanguage,8,
+	&(lvalues[4477]),0},
+{"id-ppl-inheritAll","Inherit all",NID_id_ppl_inheritAll,8,
+	&(lvalues[4485]),0},
+{"nameConstraints","X509v3 Name Constraints",NID_name_constraints,3,
+	&(lvalues[4493]),0},
+{"id-ppl-independent","Independent",NID_Independent,8,&(lvalues[4496]),0},
+{"RSA-SHA256","sha256WithRSAEncryption",NID_sha256WithRSAEncryption,9,
+	&(lvalues[4504]),0},
+{"RSA-SHA384","sha384WithRSAEncryption",NID_sha384WithRSAEncryption,9,
+	&(lvalues[4513]),0},
+{"RSA-SHA512","sha512WithRSAEncryption",NID_sha512WithRSAEncryption,9,
+	&(lvalues[4522]),0},
+{"RSA-SHA224","sha224WithRSAEncryption",NID_sha224WithRSAEncryption,9,
+	&(lvalues[4531]),0},
+{"SHA256","sha256",NID_sha256,9,&(lvalues[4540]),0},
+{"SHA384","sha384",NID_sha384,9,&(lvalues[4549]),0},
+{"SHA512","sha512",NID_sha512,9,&(lvalues[4558]),0},
+{"SHA224","sha224",NID_sha224,9,&(lvalues[4567]),0},
+{"identified-organization","identified-organization",
+	NID_identified_organization,1,&(lvalues[4576]),0},
+{"certicom-arc","certicom-arc",NID_certicom_arc,3,&(lvalues[4577]),0},
+{"wap","wap",NID_wap,2,&(lvalues[4580]),0},
+{"wap-wsg","wap-wsg",NID_wap_wsg,3,&(lvalues[4582]),0},
+{"id-characteristic-two-basis","id-characteristic-two-basis",
+	NID_X9_62_id_characteristic_two_basis,8,&(lvalues[4585]),0},
+{"onBasis","onBasis",NID_X9_62_onBasis,9,&(lvalues[4593]),0},
+{"tpBasis","tpBasis",NID_X9_62_tpBasis,9,&(lvalues[4602]),0},
+{"ppBasis","ppBasis",NID_X9_62_ppBasis,9,&(lvalues[4611]),0},
+{"c2pnb163v1","c2pnb163v1",NID_X9_62_c2pnb163v1,8,&(lvalues[4620]),0},
+{"c2pnb163v2","c2pnb163v2",NID_X9_62_c2pnb163v2,8,&(lvalues[4628]),0},
+{"c2pnb163v3","c2pnb163v3",NID_X9_62_c2pnb163v3,8,&(lvalues[4636]),0},
+{"c2pnb176v1","c2pnb176v1",NID_X9_62_c2pnb176v1,8,&(lvalues[4644]),0},
+{"c2tnb191v1","c2tnb191v1",NID_X9_62_c2tnb191v1,8,&(lvalues[4652]),0},
+{"c2tnb191v2","c2tnb191v2",NID_X9_62_c2tnb191v2,8,&(lvalues[4660]),0},
+{"c2tnb191v3","c2tnb191v3",NID_X9_62_c2tnb191v3,8,&(lvalues[4668]),0},
+{"c2onb191v4","c2onb191v4",NID_X9_62_c2onb191v4,8,&(lvalues[4676]),0},
+{"c2onb191v5","c2onb191v5",NID_X9_62_c2onb191v5,8,&(lvalues[4684]),0},
+{"c2pnb208w1","c2pnb208w1",NID_X9_62_c2pnb208w1,8,&(lvalues[4692]),0},
+{"c2tnb239v1","c2tnb239v1",NID_X9_62_c2tnb239v1,8,&(lvalues[4700]),0},
+{"c2tnb239v2","c2tnb239v2",NID_X9_62_c2tnb239v2,8,&(lvalues[4708]),0},
+{"c2tnb239v3","c2tnb239v3",NID_X9_62_c2tnb239v3,8,&(lvalues[4716]),0},
+{"c2onb239v4","c2onb239v4",NID_X9_62_c2onb239v4,8,&(lvalues[4724]),0},
+{"c2onb239v5","c2onb239v5",NID_X9_62_c2onb239v5,8,&(lvalues[4732]),0},
+{"c2pnb272w1","c2pnb272w1",NID_X9_62_c2pnb272w1,8,&(lvalues[4740]),0},
+{"c2pnb304w1","c2pnb304w1",NID_X9_62_c2pnb304w1,8,&(lvalues[4748]),0},
+{"c2tnb359v1","c2tnb359v1",NID_X9_62_c2tnb359v1,8,&(lvalues[4756]),0},
+{"c2pnb368w1","c2pnb368w1",NID_X9_62_c2pnb368w1,8,&(lvalues[4764]),0},
+{"c2tnb431r1","c2tnb431r1",NID_X9_62_c2tnb431r1,8,&(lvalues[4772]),0},
+{"secp112r1","secp112r1",NID_secp112r1,5,&(lvalues[4780]),0},
+{"secp112r2","secp112r2",NID_secp112r2,5,&(lvalues[4785]),0},
+{"secp128r1","secp128r1",NID_secp128r1,5,&(lvalues[4790]),0},
+{"secp128r2","secp128r2",NID_secp128r2,5,&(lvalues[4795]),0},
+{"secp160k1","secp160k1",NID_secp160k1,5,&(lvalues[4800]),0},
+{"secp160r1","secp160r1",NID_secp160r1,5,&(lvalues[4805]),0},
+{"secp160r2","secp160r2",NID_secp160r2,5,&(lvalues[4810]),0},
+{"secp192k1","secp192k1",NID_secp192k1,5,&(lvalues[4815]),0},
+{"secp224k1","secp224k1",NID_secp224k1,5,&(lvalues[4820]),0},
+{"secp224r1","secp224r1",NID_secp224r1,5,&(lvalues[4825]),0},
+{"secp256k1","secp256k1",NID_secp256k1,5,&(lvalues[4830]),0},
+{"secp384r1","secp384r1",NID_secp384r1,5,&(lvalues[4835]),0},
+{"secp521r1","secp521r1",NID_secp521r1,5,&(lvalues[4840]),0},
+{"sect113r1","sect113r1",NID_sect113r1,5,&(lvalues[4845]),0},
+{"sect113r2","sect113r2",NID_sect113r2,5,&(lvalues[4850]),0},
+{"sect131r1","sect131r1",NID_sect131r1,5,&(lvalues[4855]),0},
+{"sect131r2","sect131r2",NID_sect131r2,5,&(lvalues[4860]),0},
+{"sect163k1","sect163k1",NID_sect163k1,5,&(lvalues[4865]),0},
+{"sect163r1","sect163r1",NID_sect163r1,5,&(lvalues[4870]),0},
+{"sect163r2","sect163r2",NID_sect163r2,5,&(lvalues[4875]),0},
+{"sect193r1","sect193r1",NID_sect193r1,5,&(lvalues[4880]),0},
+{"sect193r2","sect193r2",NID_sect193r2,5,&(lvalues[4885]),0},
+{"sect233k1","sect233k1",NID_sect233k1,5,&(lvalues[4890]),0},
+{"sect233r1","sect233r1",NID_sect233r1,5,&(lvalues[4895]),0},
+{"sect239k1","sect239k1",NID_sect239k1,5,&(lvalues[4900]),0},
+{"sect283k1","sect283k1",NID_sect283k1,5,&(lvalues[4905]),0},
+{"sect283r1","sect283r1",NID_sect283r1,5,&(lvalues[4910]),0},
+{"sect409k1","sect409k1",NID_sect409k1,5,&(lvalues[4915]),0},
+{"sect409r1","sect409r1",NID_sect409r1,5,&(lvalues[4920]),0},
+{"sect571k1","sect571k1",NID_sect571k1,5,&(lvalues[4925]),0},
+{"sect571r1","sect571r1",NID_sect571r1,5,&(lvalues[4930]),0},
+{"wap-wsg-idm-ecid-wtls1","wap-wsg-idm-ecid-wtls1",
+	NID_wap_wsg_idm_ecid_wtls1,5,&(lvalues[4935]),0},
+{"wap-wsg-idm-ecid-wtls3","wap-wsg-idm-ecid-wtls3",
+	NID_wap_wsg_idm_ecid_wtls3,5,&(lvalues[4940]),0},
+{"wap-wsg-idm-ecid-wtls4","wap-wsg-idm-ecid-wtls4",
+	NID_wap_wsg_idm_ecid_wtls4,5,&(lvalues[4945]),0},
+{"wap-wsg-idm-ecid-wtls5","wap-wsg-idm-ecid-wtls5",
+	NID_wap_wsg_idm_ecid_wtls5,5,&(lvalues[4950]),0},
+{"wap-wsg-idm-ecid-wtls6","wap-wsg-idm-ecid-wtls6",
+	NID_wap_wsg_idm_ecid_wtls6,5,&(lvalues[4955]),0},
+{"wap-wsg-idm-ecid-wtls7","wap-wsg-idm-ecid-wtls7",
+	NID_wap_wsg_idm_ecid_wtls7,5,&(lvalues[4960]),0},
+{"wap-wsg-idm-ecid-wtls8","wap-wsg-idm-ecid-wtls8",
+	NID_wap_wsg_idm_ecid_wtls8,5,&(lvalues[4965]),0},
+{"wap-wsg-idm-ecid-wtls9","wap-wsg-idm-ecid-wtls9",
+	NID_wap_wsg_idm_ecid_wtls9,5,&(lvalues[4970]),0},
+{"wap-wsg-idm-ecid-wtls10","wap-wsg-idm-ecid-wtls10",
+	NID_wap_wsg_idm_ecid_wtls10,5,&(lvalues[4975]),0},
+{"wap-wsg-idm-ecid-wtls11","wap-wsg-idm-ecid-wtls11",
+	NID_wap_wsg_idm_ecid_wtls11,5,&(lvalues[4980]),0},
+{"wap-wsg-idm-ecid-wtls12","wap-wsg-idm-ecid-wtls12",
+	NID_wap_wsg_idm_ecid_wtls12,5,&(lvalues[4985]),0},
+{"anyPolicy","X509v3 Any Policy",NID_any_policy,4,&(lvalues[4990]),0},
+{"policyMappings","X509v3 Policy Mappings",NID_policy_mappings,3,
+	&(lvalues[4994]),0},
+{"inhibitAnyPolicy","X509v3 Inhibit Any Policy",
+	NID_inhibit_any_policy,3,&(lvalues[4997]),0},
+{"Oakley-EC2N-3","ipsec3",NID_ipsec3,0,NULL,0},
+{"Oakley-EC2N-4","ipsec4",NID_ipsec4,0,NULL,0},
+{"CAMELLIA-128-CBC","camellia-128-cbc",NID_camellia_128_cbc,11,
+	&(lvalues[5000]),0},
+{"CAMELLIA-192-CBC","camellia-192-cbc",NID_camellia_192_cbc,11,
+	&(lvalues[5011]),0},
+{"CAMELLIA-256-CBC","camellia-256-cbc",NID_camellia_256_cbc,11,
+	&(lvalues[5022]),0},
+{"CAMELLIA-128-ECB","camellia-128-ecb",NID_camellia_128_ecb,8,
+	&(lvalues[5033]),0},
+{"CAMELLIA-192-ECB","camellia-192-ecb",NID_camellia_192_ecb,8,
+	&(lvalues[5041]),0},
+{"CAMELLIA-256-ECB","camellia-256-ecb",NID_camellia_256_ecb,8,
+	&(lvalues[5049]),0},
+{"CAMELLIA-128-CFB","camellia-128-cfb",NID_camellia_128_cfb128,8,
+	&(lvalues[5057]),0},
+{"CAMELLIA-192-CFB","camellia-192-cfb",NID_camellia_192_cfb128,8,
+	&(lvalues[5065]),0},
+{"CAMELLIA-256-CFB","camellia-256-cfb",NID_camellia_256_cfb128,8,
+	&(lvalues[5073]),0},
+{"CAMELLIA-128-CFB1","camellia-128-cfb1",NID_camellia_128_cfb1,0,NULL,0},
+{"CAMELLIA-192-CFB1","camellia-192-cfb1",NID_camellia_192_cfb1,0,NULL,0},
+{"CAMELLIA-256-CFB1","camellia-256-cfb1",NID_camellia_256_cfb1,0,NULL,0},
+{"CAMELLIA-128-CFB8","camellia-128-cfb8",NID_camellia_128_cfb8,0,NULL,0},
+{"CAMELLIA-192-CFB8","camellia-192-cfb8",NID_camellia_192_cfb8,0,NULL,0},
+{"CAMELLIA-256-CFB8","camellia-256-cfb8",NID_camellia_256_cfb8,0,NULL,0},
+{"CAMELLIA-128-OFB","camellia-128-ofb",NID_camellia_128_ofb128,8,
+	&(lvalues[5081]),0},
+{"CAMELLIA-192-OFB","camellia-192-ofb",NID_camellia_192_ofb128,8,
+	&(lvalues[5089]),0},
+{"CAMELLIA-256-OFB","camellia-256-ofb",NID_camellia_256_ofb128,8,
+	&(lvalues[5097]),0},
+{"subjectDirectoryAttributes","X509v3 Subject Directory Attributes",
+	NID_subject_directory_attributes,3,&(lvalues[5105]),0},
+{"issuingDistributionPoint","X509v3 Issuing Distribution Point",
+	NID_issuing_distribution_point,3,&(lvalues[5108]),0},
+{"certificateIssuer","X509v3 Certificate Issuer",
+	NID_certificate_issuer,3,&(lvalues[5111]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"KISA","kisa",NID_kisa,6,&(lvalues[5114]),0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{NULL,NULL,NID_undef,0,NULL,0},
+{"SEED-ECB","seed-ecb",NID_seed_ecb,8,&(lvalues[5120]),0},
+{"SEED-CBC","seed-cbc",NID_seed_cbc,8,&(lvalues[5128]),0},
+{"SEED-OFB","seed-ofb",NID_seed_ofb128,8,&(lvalues[5136]),0},
+{"SEED-CFB","seed-cfb",NID_seed_cfb128,8,&(lvalues[5144]),0},
+{"HMAC-MD5","hmac-md5",NID_hmac_md5,8,&(lvalues[5152]),0},
+{"HMAC-SHA1","hmac-sha1",NID_hmac_sha1,8,&(lvalues[5160]),0},
+{"id-PasswordBasedMAC","password based MAC",NID_id_PasswordBasedMAC,9,
+	&(lvalues[5168]),0},
+{"id-DHBasedMac","Diffie-Hellman based MAC",NID_id_DHBasedMac,9,
+	&(lvalues[5177]),0},
+{"id-it-suppLangTags","id-it-suppLangTags",NID_id_it_suppLangTags,8,
+	&(lvalues[5186]),0},
+{"caRepository","CA Repository",NID_caRepository,8,&(lvalues[5194]),0},
+{"id-smime-ct-compressedData","id-smime-ct-compressedData",
+	NID_id_smime_ct_compressedData,11,&(lvalues[5202]),0},
+{"id-ct-asciiTextWithCRLF","id-ct-asciiTextWithCRLF",
+	NID_id_ct_asciiTextWithCRLF,11,&(lvalues[5213]),0},
+{"id-aes128-wrap","id-aes128-wrap",NID_id_aes128_wrap,9,
+	&(lvalues[5224]),0},
+{"id-aes192-wrap","id-aes192-wrap",NID_id_aes192_wrap,9,
+	&(lvalues[5233]),0},
+{"id-aes256-wrap","id-aes256-wrap",NID_id_aes256_wrap,9,
+	&(lvalues[5242]),0},
+{"ecdsa-with-Recommended","ecdsa-with-Recommended",
+	NID_ecdsa_with_Recommended,7,&(lvalues[5251]),0},
+{"ecdsa-with-Specified","ecdsa-with-Specified",
+	NID_ecdsa_with_Specified,7,&(lvalues[5258]),0},
+{"ecdsa-with-SHA224","ecdsa-with-SHA224",NID_ecdsa_with_SHA224,8,
+	&(lvalues[5265]),0},
+{"ecdsa-with-SHA256","ecdsa-with-SHA256",NID_ecdsa_with_SHA256,8,
+	&(lvalues[5273]),0},
+{"ecdsa-with-SHA384","ecdsa-with-SHA384",NID_ecdsa_with_SHA384,8,
+	&(lvalues[5281]),0},
+{"ecdsa-with-SHA512","ecdsa-with-SHA512",NID_ecdsa_with_SHA512,8,
+	&(lvalues[5289]),0},
+{"hmacWithMD5","hmacWithMD5",NID_hmacWithMD5,8,&(lvalues[5297]),0},
+{"hmacWithSHA224","hmacWithSHA224",NID_hmacWithSHA224,8,
+	&(lvalues[5305]),0},
+{"hmacWithSHA256","hmacWithSHA256",NID_hmacWithSHA256,8,
+	&(lvalues[5313]),0},
+{"hmacWithSHA384","hmacWithSHA384",NID_hmacWithSHA384,8,
+	&(lvalues[5321]),0},
+{"hmacWithSHA512","hmacWithSHA512",NID_hmacWithSHA512,8,
+	&(lvalues[5329]),0},
+{"id-dsa-with-sha224","dsa_with_SHA224",NID_dsa_with_SHA224,9,
+	&(lvalues[5337]),0},
+{"id-dsa-with-sha256","dsa_with_SHA256",NID_dsa_with_SHA256,9,
+	&(lvalues[5346]),0},
+{"whirlpool","whirlpool",NID_whirlpool,6,&(lvalues[5355]),0},
+{"cryptopro","cryptopro",NID_cryptopro,5,&(lvalues[5361]),0},
+{"cryptocom","cryptocom",NID_cryptocom,5,&(lvalues[5366]),0},
+{"id-GostR3411-94-with-GostR3410-2001",
+	"GOST R 34.11-94 with GOST R 34.10-2001",
+	NID_id_GostR3411_94_with_GostR3410_2001,6,&(lvalues[5371]),0},
+{"id-GostR3411-94-with-GostR3410-94",
+	"GOST R 34.11-94 with GOST R 34.10-94",
+	NID_id_GostR3411_94_with_GostR3410_94,6,&(lvalues[5377]),0},
+{"md_gost94","GOST R 34.11-94",NID_id_GostR3411_94,6,&(lvalues[5383]),0},
+{"id-HMACGostR3411-94","HMAC GOST 34.11-94",NID_id_HMACGostR3411_94,6,
+	&(lvalues[5389]),0},
+{"gost2001","GOST R 34.10-2001",NID_id_GostR3410_2001,6,
+	&(lvalues[5395]),0},
+{"gost94","GOST R 34.10-94",NID_id_GostR3410_94,6,&(lvalues[5401]),0},
+{"gost89","GOST 28147-89",NID_id_Gost28147_89,6,&(lvalues[5407]),0},
+{"gost89-cnt","gost89-cnt",NID_gost89_cnt,0,NULL,0},
+{"gost-mac","GOST 28147-89 MAC",NID_id_Gost28147_89_MAC,6,
+	&(lvalues[5413]),0},
+{"prf-gostr3411-94","GOST R 34.11-94 PRF",NID_id_GostR3411_94_prf,6,
+	&(lvalues[5419]),0},
+{"id-GostR3410-2001DH","GOST R 34.10-2001 DH",NID_id_GostR3410_2001DH,
+	6,&(lvalues[5425]),0},
+{"id-GostR3410-94DH","GOST R 34.10-94 DH",NID_id_GostR3410_94DH,6,
+	&(lvalues[5431]),0},
+{"id-Gost28147-89-CryptoPro-KeyMeshing",
+	"id-Gost28147-89-CryptoPro-KeyMeshing",
+	NID_id_Gost28147_89_CryptoPro_KeyMeshing,7,&(lvalues[5437]),0},
+{"id-Gost28147-89-None-KeyMeshing","id-Gost28147-89-None-KeyMeshing",
+	NID_id_Gost28147_89_None_KeyMeshing,7,&(lvalues[5444]),0},
+{"id-GostR3411-94-TestParamSet","id-GostR3411-94-TestParamSet",
+	NID_id_GostR3411_94_TestParamSet,7,&(lvalues[5451]),0},
+{"id-GostR3411-94-CryptoProParamSet",
+	"id-GostR3411-94-CryptoProParamSet",
+	NID_id_GostR3411_94_CryptoProParamSet,7,&(lvalues[5458]),0},
+{"id-Gost28147-89-TestParamSet","id-Gost28147-89-TestParamSet",
+	NID_id_Gost28147_89_TestParamSet,7,&(lvalues[5465]),0},
+{"id-Gost28147-89-CryptoPro-A-ParamSet",
+	"id-Gost28147-89-CryptoPro-A-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_A_ParamSet,7,&(lvalues[5472]),0},
+{"id-Gost28147-89-CryptoPro-B-ParamSet",
+	"id-Gost28147-89-CryptoPro-B-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_B_ParamSet,7,&(lvalues[5479]),0},
+{"id-Gost28147-89-CryptoPro-C-ParamSet",
+	"id-Gost28147-89-CryptoPro-C-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_C_ParamSet,7,&(lvalues[5486]),0},
+{"id-Gost28147-89-CryptoPro-D-ParamSet",
+	"id-Gost28147-89-CryptoPro-D-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_D_ParamSet,7,&(lvalues[5493]),0},
+{"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+	"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet,7,&(lvalues[5500]),
+	0},
+{"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+	"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet,7,&(lvalues[5507]),
+	0},
+{"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+	"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+	NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet,7,&(lvalues[5514]),0},
+{"id-GostR3410-94-TestParamSet","id-GostR3410-94-TestParamSet",
+	NID_id_GostR3410_94_TestParamSet,7,&(lvalues[5521]),0},
+{"id-GostR3410-94-CryptoPro-A-ParamSet",
+	"id-GostR3410-94-CryptoPro-A-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_A_ParamSet,7,&(lvalues[5528]),0},
+{"id-GostR3410-94-CryptoPro-B-ParamSet",
+	"id-GostR3410-94-CryptoPro-B-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_B_ParamSet,7,&(lvalues[5535]),0},
+{"id-GostR3410-94-CryptoPro-C-ParamSet",
+	"id-GostR3410-94-CryptoPro-C-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_C_ParamSet,7,&(lvalues[5542]),0},
+{"id-GostR3410-94-CryptoPro-D-ParamSet",
+	"id-GostR3410-94-CryptoPro-D-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_D_ParamSet,7,&(lvalues[5549]),0},
+{"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+	"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_XchA_ParamSet,7,&(lvalues[5556]),0},
+{"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+	"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_XchB_ParamSet,7,&(lvalues[5563]),0},
+{"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+	"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+	NID_id_GostR3410_94_CryptoPro_XchC_ParamSet,7,&(lvalues[5570]),0},
+{"id-GostR3410-2001-TestParamSet","id-GostR3410-2001-TestParamSet",
+	NID_id_GostR3410_2001_TestParamSet,7,&(lvalues[5577]),0},
+{"id-GostR3410-2001-CryptoPro-A-ParamSet",
+	"id-GostR3410-2001-CryptoPro-A-ParamSet",
+	NID_id_GostR3410_2001_CryptoPro_A_ParamSet,7,&(lvalues[5584]),0},
+{"id-GostR3410-2001-CryptoPro-B-ParamSet",
+	"id-GostR3410-2001-CryptoPro-B-ParamSet",
+	NID_id_GostR3410_2001_CryptoPro_B_ParamSet,7,&(lvalues[5591]),0},
+{"id-GostR3410-2001-CryptoPro-C-ParamSet",
+	"id-GostR3410-2001-CryptoPro-C-ParamSet",
+	NID_id_GostR3410_2001_CryptoPro_C_ParamSet,7,&(lvalues[5598]),0},
+{"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+	"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+	NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet,7,&(lvalues[5605]),0},
+	
+{"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+	"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+	NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet,7,&(lvalues[5612]),0},
+	
+{"id-GostR3410-94-a","id-GostR3410-94-a",NID_id_GostR3410_94_a,7,
+	&(lvalues[5619]),0},
+{"id-GostR3410-94-aBis","id-GostR3410-94-aBis",
+	NID_id_GostR3410_94_aBis,7,&(lvalues[5626]),0},
+{"id-GostR3410-94-b","id-GostR3410-94-b",NID_id_GostR3410_94_b,7,
+	&(lvalues[5633]),0},
+{"id-GostR3410-94-bBis","id-GostR3410-94-bBis",
+	NID_id_GostR3410_94_bBis,7,&(lvalues[5640]),0},
+{"id-Gost28147-89-cc","GOST 28147-89 Cryptocom ParamSet",
+	NID_id_Gost28147_89_cc,8,&(lvalues[5647]),0},
+{"gost94cc","GOST 34.10-94 Cryptocom",NID_id_GostR3410_94_cc,8,
+	&(lvalues[5655]),0},
+{"gost2001cc","GOST 34.10-2001 Cryptocom",NID_id_GostR3410_2001_cc,8,
+	&(lvalues[5663]),0},
+{"id-GostR3411-94-with-GostR3410-94-cc",
+	"GOST R 34.11-94 with GOST R 34.10-94 Cryptocom",
+	NID_id_GostR3411_94_with_GostR3410_94_cc,8,&(lvalues[5671]),0},
+{"id-GostR3411-94-with-GostR3410-2001-cc",
+	"GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom",
+	NID_id_GostR3411_94_with_GostR3410_2001_cc,8,&(lvalues[5679]),0},
+{"id-GostR3410-2001-ParamSet-cc",
+	"GOST R 3410-2001 Parameter Set Cryptocom",
+	NID_id_GostR3410_2001_ParamSet_cc,8,&(lvalues[5687]),0},
+{"HMAC","hmac",NID_hmac,0,NULL,0},
+{"LocalKeySet","Microsoft Local Key set",NID_LocalKeySet,9,
+	&(lvalues[5695]),0},
+{"freshestCRL","X509v3 Freshest CRL",NID_freshest_crl,3,
+	&(lvalues[5704]),0},
+{"id-on-permanentIdentifier","Permanent Identifier",
+	NID_id_on_permanentIdentifier,8,&(lvalues[5707]),0},
+{"searchGuide","searchGuide",NID_searchGuide,3,&(lvalues[5715]),0},
+{"businessCategory","businessCategory",NID_businessCategory,3,
+	&(lvalues[5718]),0},
+{"postalAddress","postalAddress",NID_postalAddress,3,&(lvalues[5721]),0},
+{"postOfficeBox","postOfficeBox",NID_postOfficeBox,3,&(lvalues[5724]),0},
+{"physicalDeliveryOfficeName","physicalDeliveryOfficeName",
+	NID_physicalDeliveryOfficeName,3,&(lvalues[5727]),0},
+{"telephoneNumber","telephoneNumber",NID_telephoneNumber,3,
+	&(lvalues[5730]),0},
+{"telexNumber","telexNumber",NID_telexNumber,3,&(lvalues[5733]),0},
+{"teletexTerminalIdentifier","teletexTerminalIdentifier",
+	NID_teletexTerminalIdentifier,3,&(lvalues[5736]),0},
+{"facsimileTelephoneNumber","facsimileTelephoneNumber",
+	NID_facsimileTelephoneNumber,3,&(lvalues[5739]),0},
+{"x121Address","x121Address",NID_x121Address,3,&(lvalues[5742]),0},
+{"internationaliSDNNumber","internationaliSDNNumber",
+	NID_internationaliSDNNumber,3,&(lvalues[5745]),0},
+{"registeredAddress","registeredAddress",NID_registeredAddress,3,
+	&(lvalues[5748]),0},
+{"destinationIndicator","destinationIndicator",
+	NID_destinationIndicator,3,&(lvalues[5751]),0},
+{"preferredDeliveryMethod","preferredDeliveryMethod",
+	NID_preferredDeliveryMethod,3,&(lvalues[5754]),0},
+{"presentationAddress","presentationAddress",NID_presentationAddress,
+	3,&(lvalues[5757]),0},
+{"supportedApplicationContext","supportedApplicationContext",
+	NID_supportedApplicationContext,3,&(lvalues[5760]),0},
+{"member","member",NID_member,3,&(lvalues[5763]),0},
+{"owner","owner",NID_owner,3,&(lvalues[5766]),0},
+{"roleOccupant","roleOccupant",NID_roleOccupant,3,&(lvalues[5769]),0},
+{"seeAlso","seeAlso",NID_seeAlso,3,&(lvalues[5772]),0},
+{"userPassword","userPassword",NID_userPassword,3,&(lvalues[5775]),0},
+{"userCertificate","userCertificate",NID_userCertificate,3,
+	&(lvalues[5778]),0},
+{"cACertificate","cACertificate",NID_cACertificate,3,&(lvalues[5781]),0},
+{"authorityRevocationList","authorityRevocationList",
+	NID_authorityRevocationList,3,&(lvalues[5784]),0},
+{"certificateRevocationList","certificateRevocationList",
+	NID_certificateRevocationList,3,&(lvalues[5787]),0},
+{"crossCertificatePair","crossCertificatePair",
+	NID_crossCertificatePair,3,&(lvalues[5790]),0},
+{"enhancedSearchGuide","enhancedSearchGuide",NID_enhancedSearchGuide,
+	3,&(lvalues[5793]),0},
+{"protocolInformation","protocolInformation",NID_protocolInformation,
+	3,&(lvalues[5796]),0},
+{"distinguishedName","distinguishedName",NID_distinguishedName,3,
+	&(lvalues[5799]),0},
+{"uniqueMember","uniqueMember",NID_uniqueMember,3,&(lvalues[5802]),0},
+{"houseIdentifier","houseIdentifier",NID_houseIdentifier,3,
+	&(lvalues[5805]),0},
+{"supportedAlgorithms","supportedAlgorithms",NID_supportedAlgorithms,
+	3,&(lvalues[5808]),0},
+{"deltaRevocationList","deltaRevocationList",NID_deltaRevocationList,
+	3,&(lvalues[5811]),0},
+{"dmdName","dmdName",NID_dmdName,3,&(lvalues[5814]),0},
+{"id-alg-PWRI-KEK","id-alg-PWRI-KEK",NID_id_alg_PWRI_KEK,11,
+	&(lvalues[5817]),0},
+{"CMAC","cmac",NID_cmac,0,NULL,0},
+{"id-aes128-GCM","aes-128-gcm",NID_aes_128_gcm,9,&(lvalues[5828]),0},
+{"id-aes128-CCM","aes-128-ccm",NID_aes_128_ccm,9,&(lvalues[5837]),0},
+{"id-aes128-wrap-pad","id-aes128-wrap-pad",NID_id_aes128_wrap_pad,9,
+	&(lvalues[5846]),0},
+{"id-aes192-GCM","aes-192-gcm",NID_aes_192_gcm,9,&(lvalues[5855]),0},
+{"id-aes192-CCM","aes-192-ccm",NID_aes_192_ccm,9,&(lvalues[5864]),0},
+{"id-aes192-wrap-pad","id-aes192-wrap-pad",NID_id_aes192_wrap_pad,9,
+	&(lvalues[5873]),0},
+{"id-aes256-GCM","aes-256-gcm",NID_aes_256_gcm,9,&(lvalues[5882]),0},
+{"id-aes256-CCM","aes-256-ccm",NID_aes_256_ccm,9,&(lvalues[5891]),0},
+{"id-aes256-wrap-pad","id-aes256-wrap-pad",NID_id_aes256_wrap_pad,9,
+	&(lvalues[5900]),0},
+{"AES-128-CTR","aes-128-ctr",NID_aes_128_ctr,0,NULL,0},
+{"AES-192-CTR","aes-192-ctr",NID_aes_192_ctr,0,NULL,0},
+{"AES-256-CTR","aes-256-ctr",NID_aes_256_ctr,0,NULL,0},
+{"id-camellia128-wrap","id-camellia128-wrap",NID_id_camellia128_wrap,
+	11,&(lvalues[5909]),0},
+{"id-camellia192-wrap","id-camellia192-wrap",NID_id_camellia192_wrap,
+	11,&(lvalues[5920]),0},
+{"id-camellia256-wrap","id-camellia256-wrap",NID_id_camellia256_wrap,
+	11,&(lvalues[5931]),0},
+{"anyExtendedKeyUsage","Any Extended Key Usage",
+	NID_anyExtendedKeyUsage,4,&(lvalues[5942]),0},
+{"MGF1","mgf1",NID_mgf1,9,&(lvalues[5946]),0},
+{"RSASSA-PSS","rsassaPss",NID_rsassaPss,9,&(lvalues[5955]),0},
+{"AES-128-XTS","aes-128-xts",NID_aes_128_xts,0,NULL,0},
+{"AES-256-XTS","aes-256-xts",NID_aes_256_xts,0,NULL,0},
+{"RC4-HMAC-MD5","rc4-hmac-md5",NID_rc4_hmac_md5,0,NULL,0},
+{"AES-128-CBC-HMAC-SHA1","aes-128-cbc-hmac-sha1",
+	NID_aes_128_cbc_hmac_sha1,0,NULL,0},
+{"AES-192-CBC-HMAC-SHA1","aes-192-cbc-hmac-sha1",
+	NID_aes_192_cbc_hmac_sha1,0,NULL,0},
+{"AES-256-CBC-HMAC-SHA1","aes-256-cbc-hmac-sha1",
+	NID_aes_256_cbc_hmac_sha1,0,NULL,0},
+{"RSAES-OAEP","rsaesOaep",NID_rsaesOaep,9,&(lvalues[5964]),0},
+{"teletrust","teletrust",NID_teletrust,2,&(lvalues[5973]),0},
+{"brainpool","brainpool",NID_brainpool,7,&(lvalues[5975]),0},
+{"brainpoolP160r1","brainpoolP160r1",NID_brainpoolP160r1,9,
+	&(lvalues[5982]),0},
+{"brainpoolP160t1","brainpoolP160t1",NID_brainpoolP160t1,9,
+	&(lvalues[5991]),0},
+{"brainpoolP192r1","brainpoolP192r1",NID_brainpoolP192r1,9,
+	&(lvalues[6000]),0},
+{"brainpoolP192t1","brainpoolP192t1",NID_brainpoolP192t1,9,
+	&(lvalues[6009]),0},
+{"brainpoolP224r1","brainpoolP224r1",NID_brainpoolP224r1,9,
+	&(lvalues[6018]),0},
+{"brainpoolP224t1","brainpoolP224t1",NID_brainpoolP224t1,9,
+	&(lvalues[6027]),0},
+{"brainpoolP256r1","brainpoolP256r1",NID_brainpoolP256r1,9,
+	&(lvalues[6036]),0},
+{"brainpoolP256t1","brainpoolP256t1",NID_brainpoolP256t1,9,
+	&(lvalues[6045]),0},
+{"brainpoolP320r1","brainpoolP320r1",NID_brainpoolP320r1,9,
+	&(lvalues[6054]),0},
+{"brainpoolP320t1","brainpoolP320t1",NID_brainpoolP320t1,9,
+	&(lvalues[6063]),0},
+{"brainpoolP384r1","brainpoolP384r1",NID_brainpoolP384r1,9,
+	&(lvalues[6072]),0},
+{"brainpoolP384t1","brainpoolP384t1",NID_brainpoolP384t1,9,
+	&(lvalues[6081]),0},
+{"brainpoolP512r1","brainpoolP512r1",NID_brainpoolP512r1,9,
+	&(lvalues[6090]),0},
+{"brainpoolP512t1","brainpoolP512t1",NID_brainpoolP512t1,9,
+	&(lvalues[6099]),0},
+{"FRP256v1","FRP256v1",NID_FRP256v1,10,&(lvalues[6108]),0},
+{"ChaCha","chacha",NID_chacha20,0,NULL,0},
+{"gost89-ecb","gost89-ecb",NID_gost89_ecb,0,NULL,0},
+{"gost89-cbc","gost89-cbc",NID_gost89_cbc,0,NULL,0},
+{"tc26","tc26",NID_tc26,5,&(lvalues[6118]),0},
+{"streebog256","GOST R 34.11-2012 (256 bit)",
+	NID_id_tc26_gost3411_2012_256,8,&(lvalues[6123]),0},
+{"streebog512","GOST R 34-11-2012 (512 bit)",
+	NID_id_tc26_gost3411_2012_512,8,&(lvalues[6131]),0},
+{"id-tc26-gost-3410-12-512-paramSetA",
+	"GOST R 34.10-2012 (512 bit) ParamSet A",
+	NID_id_tc26_gost_3410_12_512_paramSetA,9,&(lvalues[6139]),0},
+{"id-tc26-gost-3410-12-512-paramSetB",
+	"GOST R 34.10-2012 (512 bit) ParamSet B",
+	NID_id_tc26_gost_3410_12_512_paramSetB,9,&(lvalues[6148]),0},
+{"id-tc26-gost-28147-param-Z","id-tc26-gost-28147-param-Z",
+	NID_id_tc26_gost_28147_param_Z,9,&(lvalues[6157]),0},
+{"id-tc26-gost3410-2012-256","GOST R 34.10-2012 (256 bit)",
+	NID_id_tc26_gost3410_2012_256,8,&(lvalues[6166]),0},
+{"id-tc26-gost3410-2012-512","GOST R 34.10-2012 (512 bit)",
+	NID_id_tc26_gost3410_2012_512,8,&(lvalues[6174]),0},
+{"id-tc26-signwithdigest-gost3410-2012-256",
+	"GOST R 34.11-2012 with GOST R 34.10-2012 (256 bit)",
+	NID_id_tc26_signwithdigest_gost3410_2012_256,8,&(lvalues[6182]),0},
+{"id-tc26-signwithdigest-gost3410-2012-512",
+	"GOST R 34.11-2012 with GOST R 34.10-2012 (512 bit)",
+	NID_id_tc26_signwithdigest_gost3410_2012_512,8,&(lvalues[6190]),0},
+{"X25519","X25519",NID_X25519,3,&(lvalues[6198]),0},
+{"X448","X448",NID_X448,3,&(lvalues[6201]),0},
+{"Ed25519","Ed25519",NID_Ed25519,3,&(lvalues[6204]),0},
+{"Ed448","Ed448",NID_Ed448,3,&(lvalues[6207]),0},
+{"Ed25519ph","Ed25519ph",NID_Ed25519ph,3,&(lvalues[6210]),0},
+{"Ed448ph","Ed448ph",NID_Ed448ph,3,&(lvalues[6213]),0},
+{"jurisdictionLocalityName","jurisdictionLocalityName",
+	NID_jurisdictionLocalityName,11,&(lvalues[6216]),0},
+{"jurisdictionStateOrProvinceName","jurisdictionStateOrProvinceName",
+	NID_jurisdictionStateOrProvinceName,11,&(lvalues[6227]),0},
+{"jurisdictionCountryName","jurisdictionCountryName",
+	NID_jurisdictionCountryName,11,&(lvalues[6238]),0},
+{"KxRSA","kx-rsa",NID_kx_rsa,0,NULL,0},
+{"KxECDHE","kx-ecdhe",NID_kx_ecdhe,0,NULL,0},
+{"KxDHE","kx-dhe",NID_kx_dhe,0,NULL,0},
+{"KxGOST","kx-gost",NID_kx_gost,0,NULL,0},
+{"AuthRSA","auth-rsa",NID_auth_rsa,0,NULL,0},
+{"AuthECDSA","auth-ecdsa",NID_auth_ecdsa,0,NULL,0},
+{"AuthGOST01","auth-gost01",NID_auth_gost01,0,NULL,0},
+{"AuthNULL","auth-null",NID_auth_null,0,NULL,0},
+{"ChaCha20-Poly1305","chacha20-poly1305",NID_chacha20_poly1305,0,NULL,0},
+{"SM3","sm3",NID_sm3,8,&(lvalues[6249]),0},
+{"RSA-SM3","sm3WithRSAEncryption",NID_sm3WithRSAEncryption,8,
+	&(lvalues[6257]),0},
+{"ISO-CN","ISO CN Member Body",NID_ISO_CN,3,&(lvalues[6265]),0},
+{"oscca","oscca",NID_oscca,5,&(lvalues[6268]),0},
+{"sm-scheme","sm-scheme",NID_sm_scheme,6,&(lvalues[6273]),0},
+{"SM4-ECB","sm4-ecb",NID_sm4_ecb,8,&(lvalues[6279]),0},
+{"SM4-CBC","sm4-cbc",NID_sm4_cbc,8,&(lvalues[6287]),0},
+{"SM4-OFB","sm4-ofb",NID_sm4_ofb128,8,&(lvalues[6295]),0},
+{"SM4-CFB","sm4-cfb",NID_sm4_cfb128,8,&(lvalues[6303]),0},
+{"SM4-CFB1","sm4-cfb1",NID_sm4_cfb1,8,&(lvalues[6311]),0},
+{"SM4-CFB8","sm4-cfb8",NID_sm4_cfb8,8,&(lvalues[6319]),0},
+{"SM4-CTR","sm4-ctr",NID_sm4_ctr,8,&(lvalues[6327]),0},
+{"dhSinglePass-stdDH-sha1kdf-scheme",
+	"dhSinglePass-stdDH-sha1kdf-scheme",
+	NID_dhSinglePass_stdDH_sha1kdf_scheme,9,&(lvalues[6335]),0},
+{"dhSinglePass-stdDH-sha224kdf-scheme",
+	"dhSinglePass-stdDH-sha224kdf-scheme",
+	NID_dhSinglePass_stdDH_sha224kdf_scheme,6,&(lvalues[6344]),0},
+{"dhSinglePass-stdDH-sha256kdf-scheme",
+	"dhSinglePass-stdDH-sha256kdf-scheme",
+	NID_dhSinglePass_stdDH_sha256kdf_scheme,6,&(lvalues[6350]),0},
+{"dhSinglePass-stdDH-sha384kdf-scheme",
+	"dhSinglePass-stdDH-sha384kdf-scheme",
+	NID_dhSinglePass_stdDH_sha384kdf_scheme,6,&(lvalues[6356]),0},
+{"dhSinglePass-stdDH-sha512kdf-scheme",
+	"dhSinglePass-stdDH-sha512kdf-scheme",
+	NID_dhSinglePass_stdDH_sha512kdf_scheme,6,&(lvalues[6362]),0},
+{"dhSinglePass-cofactorDH-sha1kdf-scheme",
+	"dhSinglePass-cofactorDH-sha1kdf-scheme",
+	NID_dhSinglePass_cofactorDH_sha1kdf_scheme,9,&(lvalues[6368]),0},
+{"dhSinglePass-cofactorDH-sha224kdf-scheme",
+	"dhSinglePass-cofactorDH-sha224kdf-scheme",
+	NID_dhSinglePass_cofactorDH_sha224kdf_scheme,6,&(lvalues[6377]),0},
+{"dhSinglePass-cofactorDH-sha256kdf-scheme",
+	"dhSinglePass-cofactorDH-sha256kdf-scheme",
+	NID_dhSinglePass_cofactorDH_sha256kdf_scheme,6,&(lvalues[6383]),0},
+{"dhSinglePass-cofactorDH-sha384kdf-scheme",
+	"dhSinglePass-cofactorDH-sha384kdf-scheme",
+	NID_dhSinglePass_cofactorDH_sha384kdf_scheme,6,&(lvalues[6389]),0},
+{"dhSinglePass-cofactorDH-sha512kdf-scheme",
+	"dhSinglePass-cofactorDH-sha512kdf-scheme",
+	NID_dhSinglePass_cofactorDH_sha512kdf_scheme,6,&(lvalues[6395]),0},
+{"dh-std-kdf","dh-std-kdf",NID_dh_std_kdf,0,NULL,0},
+{"dh-cofactor-kdf","dh-cofactor-kdf",NID_dh_cofactor_kdf,0,NULL,0},
+{"PSPECIFIED","pSpecified",NID_pSpecified,9,&(lvalues[6401]),0},
+{"id-tc26-gost-3410-12-256-paramSetA",
+	"GOST R 34.10-2012 (256 bit) ParamSet A",
+	NID_id_tc26_gost_3410_12_256_paramSetA,9,&(lvalues[6410]),0},
+{"id-tc26-gost-3410-12-256-paramSetB",
+	"GOST R 34.10-2012 (256 bit) ParamSet B",
+	NID_id_tc26_gost_3410_12_256_paramSetB,9,&(lvalues[6419]),0},
+{"id-tc26-gost-3410-12-256-paramSetC",
+	"GOST R 34.10-2012 (256 bit) ParamSet C",
+	NID_id_tc26_gost_3410_12_256_paramSetC,9,&(lvalues[6428]),0},
+{"id-tc26-gost-3410-12-256-paramSetD",
+	"GOST R 34.10-2012 (256 bit) ParamSet D",
+	NID_id_tc26_gost_3410_12_256_paramSetD,9,&(lvalues[6437]),0},
+{"id-tc26-gost-3410-12-512-paramSetTest",
+	"GOST R 34.10-2012 (512 bit) testing parameter set",
+	NID_id_tc26_gost_3410_12_512_paramSetTest,9,&(lvalues[6446]),0},
+{"id-tc26-gost-3410-12-512-paramSetC",
+	"GOST R 34.10-2012 (512 bit) ParamSet C",
+	NID_id_tc26_gost_3410_12_512_paramSetC,9,&(lvalues[6455]),0},
+{"id-tc26-hmac-gost-3411-12-256","HMAC STREEBOG 256",
+	NID_id_tc26_hmac_gost_3411_12_256,8,&(lvalues[6464]),0},
+{"id-tc26-hmac-gost-3411-12-512","HMAC STREEBOG 512",
+	NID_id_tc26_hmac_gost_3411_12_512,8,&(lvalues[6472]),0},
+{"id-ct-routeOriginAuthz","id-ct-routeOriginAuthz",
+	NID_id_ct_routeOriginAuthz,11,&(lvalues[6480]),0},
+{"id-ct-rpkiManifest","id-ct-rpkiManifest",NID_id_ct_rpkiManifest,11,
+	&(lvalues[6491]),0},
+{"id-ct-rpkiGhostbusters","id-ct-rpkiGhostbusters",
+	NID_id_ct_rpkiGhostbusters,11,&(lvalues[6502]),0},
+{"id-ct-resourceTaggedAttest","id-ct-resourceTaggedAttest",
+	NID_id_ct_resourceTaggedAttest,11,&(lvalues[6513]),0},
+{"id-cp","id-cp",NID_id_cp,7,&(lvalues[6524]),0},
+{"sbgp-ipAddrBlockv2","sbgp-ipAddrBlockv2",NID_sbgp_ipAddrBlockv2,8,
+	&(lvalues[6531]),0},
+{"sbgp-autonomousSysNumv2","sbgp-autonomousSysNumv2",
+	NID_sbgp_autonomousSysNumv2,8,&(lvalues[6539]),0},
+{"ipAddr-asNumber","ipAddr-asNumber",NID_ipAddr_asNumber,8,
+	&(lvalues[6547]),0},
+{"ipAddr-asNumberv2","ipAddr-asNumberv2",NID_ipAddr_asNumberv2,8,
+	&(lvalues[6555]),0},
+{"rpkiManifest","RPKI Manifest",NID_rpkiManifest,8,&(lvalues[6563]),0},
+{"signedObject","Signed Object",NID_signedObject,8,&(lvalues[6571]),0},
+{"rpkiNotify","RPKI Notify",NID_rpkiNotify,8,&(lvalues[6579]),0},
+{"id-ct-geofeedCSVwithCRLF","id-ct-geofeedCSVwithCRLF",
+	NID_id_ct_geofeedCSVwithCRLF,11,&(lvalues[6587]),0},
+{"id-ct-signedChecklist","id-ct-signedChecklist",
+	NID_id_ct_signedChecklist,11,&(lvalues[6598]),0},
+{"id-kp-bgpsec-router","BGPsec Router",NID_id_kp_bgpsec_router,8,
+	&(lvalues[6609]),0},
+{"tlsfeature","TLS Feature",NID_tlsfeature,8,&(lvalues[6617]),0},
+{"id-ct-ASPA","id-ct-ASPA",NID_id_ct_ASPA,11,&(lvalues[6625]),0},
+{"ct_precert_scts","CT Precertificate SCTs",NID_ct_precert_scts,10,
+	&(lvalues[6636]),0},
+{"ct_precert_poison","CT Precertificate Poison",NID_ct_precert_poison,
+	10,&(lvalues[6646]),0},
+{"ct_precert_signer","CT Precertificate Signer",NID_ct_precert_signer,
+	10,&(lvalues[6656]),0},
+{"ct_cert_scts","CT Certificate SCTs",NID_ct_cert_scts,10,
+	&(lvalues[6666]),0},
+{"HKDF","hkdf",NID_hkdf,0,NULL,0},
+{"id-smime-aa-signingCertificateV2",
+	"id-smime-aa-signingCertificateV2",
+	NID_id_smime_aa_signingCertificateV2,11,&(lvalues[6676]),0},
+{"id-ct-signedTAL","id-ct-signedTAL",NID_id_ct_signedTAL,11,
+	&(lvalues[6687]),0},
+{"RSA-SHA512/224","sha512-224WithRSAEncryption",
+	NID_sha512_224WithRSAEncryption,9,&(lvalues[6698]),0},
+{"RSA-SHA512/256","sha512-256WithRSAEncryption",
+	NID_sha512_256WithRSAEncryption,9,&(lvalues[6707]),0},
+{"hmacWithSHA512-224","hmacWithSHA512-224",NID_hmacWithSHA512_224,8,
+	&(lvalues[6716]),0},
+{"hmacWithSHA512-256","hmacWithSHA512-256",NID_hmacWithSHA512_256,8,
+	&(lvalues[6724]),0},
+{"SHA512-224","sha512-224",NID_sha512_224,9,&(lvalues[6732]),0},
+{"SHA512-256","sha512-256",NID_sha512_256,9,&(lvalues[6741]),0},
+{"SHA3-224","sha3-224",NID_sha3_224,9,&(lvalues[6750]),0},
+{"SHA3-256","sha3-256",NID_sha3_256,9,&(lvalues[6759]),0},
+{"SHA3-384","sha3-384",NID_sha3_384,9,&(lvalues[6768]),0},
+{"SHA3-512","sha3-512",NID_sha3_512,9,&(lvalues[6777]),0},
+{"id-hmacWithSHA3-224","hmac-sha3-224",NID_hmac_sha3_224,9,
+	&(lvalues[6786]),0},
+{"id-hmacWithSHA3-256","hmac-sha3-256",NID_hmac_sha3_256,9,
+	&(lvalues[6795]),0},
+{"id-hmacWithSHA3-384","hmac-sha3-384",NID_hmac_sha3_384,9,
+	&(lvalues[6804]),0},
+{"id-hmacWithSHA3-512","hmac-sha3-512",NID_hmac_sha3_512,9,
+	&(lvalues[6813]),0},
+{"id-dsa-with-sha384","dsa_with_SHA384",NID_dsa_with_SHA384,9,
+	&(lvalues[6822]),0},
+{"id-dsa-with-sha512","dsa_with_SHA512",NID_dsa_with_SHA512,9,
+	&(lvalues[6831]),0},
+{"id-dsa-with-sha3-224","dsa_with_SHA3-224",NID_dsa_with_SHA3_224,9,
+	&(lvalues[6840]),0},
+{"id-dsa-with-sha3-256","dsa_with_SHA3-256",NID_dsa_with_SHA3_256,9,
+	&(lvalues[6849]),0},
+{"id-dsa-with-sha3-384","dsa_with_SHA3-384",NID_dsa_with_SHA3_384,9,
+	&(lvalues[6858]),0},
+{"id-dsa-with-sha3-512","dsa_with_SHA3-512",NID_dsa_with_SHA3_512,9,
+	&(lvalues[6867]),0},
+{"id-ecdsa-with-sha3-224","ecdsa_with_SHA3-224",
+	NID_ecdsa_with_SHA3_224,9,&(lvalues[6876]),0},
+{"id-ecdsa-with-sha3-256","ecdsa_with_SHA3-256",
+	NID_ecdsa_with_SHA3_256,9,&(lvalues[6885]),0},
+{"id-ecdsa-with-sha3-384","ecdsa_with_SHA3-384",
+	NID_ecdsa_with_SHA3_384,9,&(lvalues[6894]),0},
+{"id-ecdsa-with-sha3-512","ecdsa_with_SHA3-512",
+	NID_ecdsa_with_SHA3_512,9,&(lvalues[6903]),0},
+{"id-rsassa-pkcs1-v1_5-with-sha3-224","RSA-SHA3-224",NID_RSA_SHA3_224,
+	9,&(lvalues[6912]),0},
+{"id-rsassa-pkcs1-v1_5-with-sha3-256","RSA-SHA3-256",NID_RSA_SHA3_256,
+	9,&(lvalues[6921]),0},
+{"id-rsassa-pkcs1-v1_5-with-sha3-384","RSA-SHA3-384",NID_RSA_SHA3_384,
+	9,&(lvalues[6930]),0},
+{"id-rsassa-pkcs1-v1_5-with-sha3-512","RSA-SHA3-512",NID_RSA_SHA3_512,
+	9,&(lvalues[6939]),0},
+};
+
+static const unsigned int sn_objs[NUM_SN]={
+364,	/* "AD_DVCS" */
+419,	/* "AES-128-CBC" */
+916,	/* "AES-128-CBC-HMAC-SHA1" */
+421,	/* "AES-128-CFB" */
+650,	/* "AES-128-CFB1" */
+653,	/* "AES-128-CFB8" */
+904,	/* "AES-128-CTR" */
+418,	/* "AES-128-ECB" */
+420,	/* "AES-128-OFB" */
+913,	/* "AES-128-XTS" */
+423,	/* "AES-192-CBC" */
+917,	/* "AES-192-CBC-HMAC-SHA1" */
+425,	/* "AES-192-CFB" */
+651,	/* "AES-192-CFB1" */
+654,	/* "AES-192-CFB8" */
+905,	/* "AES-192-CTR" */
+422,	/* "AES-192-ECB" */
+424,	/* "AES-192-OFB" */
+427,	/* "AES-256-CBC" */
+918,	/* "AES-256-CBC-HMAC-SHA1" */
+429,	/* "AES-256-CFB" */
+652,	/* "AES-256-CFB1" */
+655,	/* "AES-256-CFB8" */
+906,	/* "AES-256-CTR" */
+426,	/* "AES-256-ECB" */
+428,	/* "AES-256-OFB" */
+914,	/* "AES-256-XTS" */
+964,	/* "AuthECDSA" */
+965,	/* "AuthGOST01" */
+966,	/* "AuthNULL" */
+963,	/* "AuthRSA" */
+91,	/* "BF-CBC" */
+93,	/* "BF-CFB" */
+92,	/* "BF-ECB" */
+94,	/* "BF-OFB" */
+14,	/* "C" */
+751,	/* "CAMELLIA-128-CBC" */
+757,	/* "CAMELLIA-128-CFB" */
+760,	/* "CAMELLIA-128-CFB1" */
+763,	/* "CAMELLIA-128-CFB8" */
+754,	/* "CAMELLIA-128-ECB" */
+766,	/* "CAMELLIA-128-OFB" */
+752,	/* "CAMELLIA-192-CBC" */
+758,	/* "CAMELLIA-192-CFB" */
+761,	/* "CAMELLIA-192-CFB1" */
+764,	/* "CAMELLIA-192-CFB8" */
+755,	/* "CAMELLIA-192-ECB" */
+767,	/* "CAMELLIA-192-OFB" */
+753,	/* "CAMELLIA-256-CBC" */
+759,	/* "CAMELLIA-256-CFB" */
+762,	/* "CAMELLIA-256-CFB1" */
+765,	/* "CAMELLIA-256-CFB8" */
+756,	/* "CAMELLIA-256-ECB" */
+768,	/* "CAMELLIA-256-OFB" */
+108,	/* "CAST5-CBC" */
+110,	/* "CAST5-CFB" */
+109,	/* "CAST5-ECB" */
+111,	/* "CAST5-OFB" */
+894,	/* "CMAC" */
+13,	/* "CN" */
+141,	/* "CRLReason" */
+417,	/* "CSPName" */
+937,	/* "ChaCha" */
+967,	/* "ChaCha20-Poly1305" */
+367,	/* "CrlID" */
+391,	/* "DC" */
+31,	/* "DES-CBC" */
+643,	/* "DES-CDMF" */
+30,	/* "DES-CFB" */
+656,	/* "DES-CFB1" */
+657,	/* "DES-CFB8" */
+29,	/* "DES-ECB" */
+32,	/* "DES-EDE" */
+43,	/* "DES-EDE-CBC" */
+60,	/* "DES-EDE-CFB" */
+62,	/* "DES-EDE-OFB" */
+33,	/* "DES-EDE3" */
+44,	/* "DES-EDE3-CBC" */
+61,	/* "DES-EDE3-CFB" */
+658,	/* "DES-EDE3-CFB1" */
+659,	/* "DES-EDE3-CFB8" */
+63,	/* "DES-EDE3-OFB" */
+45,	/* "DES-OFB" */
+80,	/* "DESX-CBC" */
+380,	/* "DOD" */
+116,	/* "DSA" */
+66,	/* "DSA-SHA" */
+113,	/* "DSA-SHA1" */
+70,	/* "DSA-SHA1-old" */
+67,	/* "DSA-old" */
+297,	/* "DVCS" */
+952,	/* "Ed25519" */
+954,	/* "Ed25519ph" */
+953,	/* "Ed448" */
+955,	/* "Ed448ph" */
+936,	/* "FRP256v1" */
+99,	/* "GN" */
+1022,	/* "HKDF" */
+855,	/* "HMAC" */
+780,	/* "HMAC-MD5" */
+781,	/* "HMAC-SHA1" */
+381,	/* "IANA" */
+34,	/* "IDEA-CBC" */
+35,	/* "IDEA-CFB" */
+36,	/* "IDEA-ECB" */
+46,	/* "IDEA-OFB" */
+181,	/* "ISO" */
+970,	/* "ISO-CN" */
+183,	/* "ISO-US" */
+645,	/* "ITU-T" */
+646,	/* "JOINT-ISO-ITU-T" */
+773,	/* "KISA" */
+961,	/* "KxDHE" */
+960,	/* "KxECDHE" */
+962,	/* "KxGOST" */
+959,	/* "KxRSA" */
+15,	/* "L" */
+856,	/* "LocalKeySet" */
+ 3,	/* "MD2" */
+257,	/* "MD4" */
+ 4,	/* "MD5" */
+114,	/* "MD5-SHA1" */
+95,	/* "MDC2" */
+911,	/* "MGF1" */
+388,	/* "Mail" */
+393,	/* "NULL" */
+404,	/* "NULL" */
+57,	/* "Netscape" */
+366,	/* "Nonce" */
+17,	/* "O" */
+178,	/* "OCSP" */
+180,	/* "OCSPSigning" */
+379,	/* "ORG" */
+18,	/* "OU" */
+749,	/* "Oakley-EC2N-3" */
+750,	/* "Oakley-EC2N-4" */
+ 9,	/* "PBE-MD2-DES" */
+168,	/* "PBE-MD2-RC2-64" */
+10,	/* "PBE-MD5-DES" */
+169,	/* "PBE-MD5-RC2-64" */
+147,	/* "PBE-SHA1-2DES" */
+146,	/* "PBE-SHA1-3DES" */
+170,	/* "PBE-SHA1-DES" */
+148,	/* "PBE-SHA1-RC2-128" */
+149,	/* "PBE-SHA1-RC2-40" */
+68,	/* "PBE-SHA1-RC2-64" */
+144,	/* "PBE-SHA1-RC4-128" */
+145,	/* "PBE-SHA1-RC4-40" */
+161,	/* "PBES2" */
+69,	/* "PBKDF2" */
+162,	/* "PBMAC1" */
+127,	/* "PKIX" */
+992,	/* "PSPECIFIED" */
+98,	/* "RC2-40-CBC" */
+166,	/* "RC2-64-CBC" */
+37,	/* "RC2-CBC" */
+39,	/* "RC2-CFB" */
+38,	/* "RC2-ECB" */
+40,	/* "RC2-OFB" */
+ 5,	/* "RC4" */
+97,	/* "RC4-40" */
+915,	/* "RC4-HMAC-MD5" */
+120,	/* "RC5-CBC" */
+122,	/* "RC5-CFB" */
+121,	/* "RC5-ECB" */
+123,	/* "RC5-OFB" */
+117,	/* "RIPEMD160" */
+124,	/* "RLE" */
+19,	/* "RSA" */
+ 7,	/* "RSA-MD2" */
+396,	/* "RSA-MD4" */
+ 8,	/* "RSA-MD5" */
+96,	/* "RSA-MDC2" */
+104,	/* "RSA-NP-MD5" */
+119,	/* "RSA-RIPEMD160" */
+42,	/* "RSA-SHA" */
+65,	/* "RSA-SHA1" */
+115,	/* "RSA-SHA1-2" */
+671,	/* "RSA-SHA224" */
+668,	/* "RSA-SHA256" */
+669,	/* "RSA-SHA384" */
+670,	/* "RSA-SHA512" */
+1025,	/* "RSA-SHA512/224" */
+1026,	/* "RSA-SHA512/256" */
+969,	/* "RSA-SM3" */
+919,	/* "RSAES-OAEP" */
+912,	/* "RSASSA-PSS" */
+777,	/* "SEED-CBC" */
+779,	/* "SEED-CFB" */
+776,	/* "SEED-ECB" */
+778,	/* "SEED-OFB" */
+41,	/* "SHA" */
+64,	/* "SHA1" */
+675,	/* "SHA224" */
+672,	/* "SHA256" */
+1031,	/* "SHA3-224" */
+1032,	/* "SHA3-256" */
+1033,	/* "SHA3-384" */
+1034,	/* "SHA3-512" */
+673,	/* "SHA384" */
+674,	/* "SHA512" */
+1029,	/* "SHA512-224" */
+1030,	/* "SHA512-256" */
+968,	/* "SM3" */
+974,	/* "SM4-CBC" */
+976,	/* "SM4-CFB" */
+977,	/* "SM4-CFB1" */
+978,	/* "SM4-CFB8" */
+979,	/* "SM4-CTR" */
+973,	/* "SM4-ECB" */
+975,	/* "SM4-OFB" */
+188,	/* "SMIME" */
+167,	/* "SMIME-CAPS" */
+100,	/* "SN" */
+16,	/* "ST" */
+143,	/* "SXNetID" */
+458,	/* "UID" */
+ 0,	/* "UNDEF" */
+950,	/* "X25519" */
+951,	/* "X448" */
+11,	/* "X500" */
+378,	/* "X500algorithms" */
+12,	/* "X509" */
+184,	/* "X9-57" */
+185,	/* "X9cm" */
+125,	/* "ZLIB" */
+478,	/* "aRecord" */
+289,	/* "aaControls" */
+287,	/* "ac-auditEntity" */
+397,	/* "ac-proxying" */
+288,	/* "ac-targeting" */
+368,	/* "acceptableResponses" */
+446,	/* "account" */
+363,	/* "ad_timestamping" */
+376,	/* "algorithm" */
+405,	/* "ansi-X9-62" */
+910,	/* "anyExtendedKeyUsage" */
+746,	/* "anyPolicy" */
+370,	/* "archiveCutoff" */
+484,	/* "associatedDomain" */
+485,	/* "associatedName" */
+501,	/* "audio" */
+177,	/* "authorityInfoAccess" */
+90,	/* "authorityKeyIdentifier" */
+882,	/* "authorityRevocationList" */
+87,	/* "basicConstraints" */
+365,	/* "basicOCSPResponse" */
+285,	/* "biometricInfo" */
+921,	/* "brainpool" */
+922,	/* "brainpoolP160r1" */
+923,	/* "brainpoolP160t1" */
+924,	/* "brainpoolP192r1" */
+925,	/* "brainpoolP192t1" */
+926,	/* "brainpoolP224r1" */
+927,	/* "brainpoolP224t1" */
+928,	/* "brainpoolP256r1" */
+929,	/* "brainpoolP256t1" */
+930,	/* "brainpoolP320r1" */
+931,	/* "brainpoolP320t1" */
+932,	/* "brainpoolP384r1" */
+933,	/* "brainpoolP384t1" */
+934,	/* "brainpoolP512r1" */
+935,	/* "brainpoolP512t1" */
+494,	/* "buildingName" */
+860,	/* "businessCategory" */
+691,	/* "c2onb191v4" */
+692,	/* "c2onb191v5" */
+697,	/* "c2onb239v4" */
+698,	/* "c2onb239v5" */
+684,	/* "c2pnb163v1" */
+685,	/* "c2pnb163v2" */
+686,	/* "c2pnb163v3" */
+687,	/* "c2pnb176v1" */
+693,	/* "c2pnb208w1" */
+699,	/* "c2pnb272w1" */
+700,	/* "c2pnb304w1" */
+702,	/* "c2pnb368w1" */
+688,	/* "c2tnb191v1" */
+689,	/* "c2tnb191v2" */
+690,	/* "c2tnb191v3" */
+694,	/* "c2tnb239v1" */
+695,	/* "c2tnb239v2" */
+696,	/* "c2tnb239v3" */
+701,	/* "c2tnb359v1" */
+703,	/* "c2tnb431r1" */
+881,	/* "cACertificate" */
+483,	/* "cNAMERecord" */
+179,	/* "caIssuers" */
+785,	/* "caRepository" */
+443,	/* "caseIgnoreIA5StringSyntax" */
+152,	/* "certBag" */
+677,	/* "certicom-arc" */
+771,	/* "certificateIssuer" */
+89,	/* "certificatePolicies" */
+883,	/* "certificateRevocationList" */
+54,	/* "challengePassword" */
+407,	/* "characteristic-two-field" */
+395,	/* "clearance" */
+130,	/* "clientAuth" */
+131,	/* "codeSigning" */
+50,	/* "contentType" */
+53,	/* "countersignature" */
+153,	/* "crlBag" */
+103,	/* "crlDistributionPoints" */
+88,	/* "crlNumber" */
+884,	/* "crossCertificatePair" */
+806,	/* "cryptocom" */
+805,	/* "cryptopro" */
+1021,	/* "ct_cert_scts" */
+1019,	/* "ct_precert_poison" */
+1018,	/* "ct_precert_scts" */
+1020,	/* "ct_precert_signer" */
+500,	/* "dITRedirect" */
+451,	/* "dNSDomain" */
+495,	/* "dSAQuality" */
+434,	/* "data" */
+390,	/* "dcobject" */
+140,	/* "deltaCRL" */
+891,	/* "deltaRevocationList" */
+107,	/* "description" */
+871,	/* "destinationIndicator" */
+991,	/* "dh-cofactor-kdf" */
+990,	/* "dh-std-kdf" */
+28,	/* "dhKeyAgreement" */
+985,	/* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
+986,	/* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
+987,	/* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
+988,	/* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
+989,	/* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
+980,	/* "dhSinglePass-stdDH-sha1kdf-scheme" */
+981,	/* "dhSinglePass-stdDH-sha224kdf-scheme" */
+982,	/* "dhSinglePass-stdDH-sha256kdf-scheme" */
+983,	/* "dhSinglePass-stdDH-sha384kdf-scheme" */
+984,	/* "dhSinglePass-stdDH-sha512kdf-scheme" */
+382,	/* "directory" */
+887,	/* "distinguishedName" */
+892,	/* "dmdName" */
+174,	/* "dnQualifier" */
+447,	/* "document" */
+471,	/* "documentAuthor" */
+468,	/* "documentIdentifier" */
+472,	/* "documentLocation" */
+502,	/* "documentPublisher" */
+449,	/* "documentSeries" */
+469,	/* "documentTitle" */
+470,	/* "documentVersion" */
+392,	/* "domain" */
+452,	/* "domainRelatedObject" */
+791,	/* "ecdsa-with-Recommended" */
+416,	/* "ecdsa-with-SHA1" */
+793,	/* "ecdsa-with-SHA224" */
+794,	/* "ecdsa-with-SHA256" */
+795,	/* "ecdsa-with-SHA384" */
+796,	/* "ecdsa-with-SHA512" */
+792,	/* "ecdsa-with-Specified" */
+48,	/* "emailAddress" */
+132,	/* "emailProtection" */
+885,	/* "enhancedSearchGuide" */
+389,	/* "enterprises" */
+384,	/* "experimental" */
+172,	/* "extReq" */
+56,	/* "extendedCertificateAttributes" */
+126,	/* "extendedKeyUsage" */
+372,	/* "extendedStatus" */
+867,	/* "facsimileTelephoneNumber" */
+462,	/* "favouriteDrink" */
+857,	/* "freshestCRL" */
+453,	/* "friendlyCountry" */
+490,	/* "friendlyCountryName" */
+156,	/* "friendlyName" */
+509,	/* "generationQualifier" */
+815,	/* "gost-mac" */
+811,	/* "gost2001" */
+851,	/* "gost2001cc" */
+813,	/* "gost89" */
+939,	/* "gost89-cbc" */
+814,	/* "gost89-cnt" */
+938,	/* "gost89-ecb" */
+812,	/* "gost94" */
+850,	/* "gost94cc" */
+797,	/* "hmacWithMD5" */
+163,	/* "hmacWithSHA1" */
+798,	/* "hmacWithSHA224" */
+799,	/* "hmacWithSHA256" */
+800,	/* "hmacWithSHA384" */
+801,	/* "hmacWithSHA512" */
+1027,	/* "hmacWithSHA512-224" */
+1028,	/* "hmacWithSHA512-256" */
+432,	/* "holdInstructionCallIssuer" */
+430,	/* "holdInstructionCode" */
+431,	/* "holdInstructionNone" */
+433,	/* "holdInstructionReject" */
+486,	/* "homePostalAddress" */
+473,	/* "homeTelephoneNumber" */
+466,	/* "host" */
+889,	/* "houseIdentifier" */
+442,	/* "iA5StringSyntax" */
+783,	/* "id-DHBasedMac" */
+824,	/* "id-Gost28147-89-CryptoPro-A-ParamSet" */
+825,	/* "id-Gost28147-89-CryptoPro-B-ParamSet" */
+826,	/* "id-Gost28147-89-CryptoPro-C-ParamSet" */
+827,	/* "id-Gost28147-89-CryptoPro-D-ParamSet" */
+819,	/* "id-Gost28147-89-CryptoPro-KeyMeshing" */
+829,	/* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
+828,	/* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
+830,	/* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
+820,	/* "id-Gost28147-89-None-KeyMeshing" */
+823,	/* "id-Gost28147-89-TestParamSet" */
+849,	/* "id-Gost28147-89-cc" */
+840,	/* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
+841,	/* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
+842,	/* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
+843,	/* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
+844,	/* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
+854,	/* "id-GostR3410-2001-ParamSet-cc" */
+839,	/* "id-GostR3410-2001-TestParamSet" */
+817,	/* "id-GostR3410-2001DH" */
+832,	/* "id-GostR3410-94-CryptoPro-A-ParamSet" */
+833,	/* "id-GostR3410-94-CryptoPro-B-ParamSet" */
+834,	/* "id-GostR3410-94-CryptoPro-C-ParamSet" */
+835,	/* "id-GostR3410-94-CryptoPro-D-ParamSet" */
+836,	/* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
+837,	/* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
+838,	/* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
+831,	/* "id-GostR3410-94-TestParamSet" */
+845,	/* "id-GostR3410-94-a" */
+846,	/* "id-GostR3410-94-aBis" */
+847,	/* "id-GostR3410-94-b" */
+848,	/* "id-GostR3410-94-bBis" */
+818,	/* "id-GostR3410-94DH" */
+822,	/* "id-GostR3411-94-CryptoProParamSet" */
+821,	/* "id-GostR3411-94-TestParamSet" */
+807,	/* "id-GostR3411-94-with-GostR3410-2001" */
+853,	/* "id-GostR3411-94-with-GostR3410-2001-cc" */
+808,	/* "id-GostR3411-94-with-GostR3410-94" */
+852,	/* "id-GostR3411-94-with-GostR3410-94-cc" */
+810,	/* "id-HMACGostR3411-94" */
+782,	/* "id-PasswordBasedMAC" */
+266,	/* "id-aca" */
+355,	/* "id-aca-accessIdentity" */
+354,	/* "id-aca-authenticationInfo" */
+356,	/* "id-aca-chargingIdentity" */
+399,	/* "id-aca-encAttrs" */
+357,	/* "id-aca-group" */
+358,	/* "id-aca-role" */
+176,	/* "id-ad" */
+896,	/* "id-aes128-CCM" */
+895,	/* "id-aes128-GCM" */
+788,	/* "id-aes128-wrap" */
+897,	/* "id-aes128-wrap-pad" */
+899,	/* "id-aes192-CCM" */
+898,	/* "id-aes192-GCM" */
+789,	/* "id-aes192-wrap" */
+900,	/* "id-aes192-wrap-pad" */
+902,	/* "id-aes256-CCM" */
+901,	/* "id-aes256-GCM" */
+790,	/* "id-aes256-wrap" */
+903,	/* "id-aes256-wrap-pad" */
+262,	/* "id-alg" */
+893,	/* "id-alg-PWRI-KEK" */
+323,	/* "id-alg-des40" */
+326,	/* "id-alg-dh-pop" */
+325,	/* "id-alg-dh-sig-hmac-sha1" */
+324,	/* "id-alg-noSignature" */
+907,	/* "id-camellia128-wrap" */
+908,	/* "id-camellia192-wrap" */
+909,	/* "id-camellia256-wrap" */
+268,	/* "id-cct" */
+361,	/* "id-cct-PKIData" */
+362,	/* "id-cct-PKIResponse" */
+360,	/* "id-cct-crs" */
+81,	/* "id-ce" */
+680,	/* "id-characteristic-two-basis" */
+263,	/* "id-cmc" */
+334,	/* "id-cmc-addExtensions" */
+346,	/* "id-cmc-confirmCertAcceptance" */
+330,	/* "id-cmc-dataReturn" */
+336,	/* "id-cmc-decryptedPOP" */
+335,	/* "id-cmc-encryptedPOP" */
+339,	/* "id-cmc-getCRL" */
+338,	/* "id-cmc-getCert" */
+328,	/* "id-cmc-identification" */
+329,	/* "id-cmc-identityProof" */
+337,	/* "id-cmc-lraPOPWitness" */
+344,	/* "id-cmc-popLinkRandom" */
+345,	/* "id-cmc-popLinkWitness" */
+343,	/* "id-cmc-queryPending" */
+333,	/* "id-cmc-recipientNonce" */
+341,	/* "id-cmc-regInfo" */
+342,	/* "id-cmc-responseInfo" */
+340,	/* "id-cmc-revokeRequest" */
+332,	/* "id-cmc-senderNonce" */
+327,	/* "id-cmc-statusInfo" */
+331,	/* "id-cmc-transactionId" */
+1005,	/* "id-cp" */
+1017,	/* "id-ct-ASPA" */
+787,	/* "id-ct-asciiTextWithCRLF" */
+1013,	/* "id-ct-geofeedCSVwithCRLF" */
+1004,	/* "id-ct-resourceTaggedAttest" */
+1001,	/* "id-ct-routeOriginAuthz" */
+1003,	/* "id-ct-rpkiGhostbusters" */
+1002,	/* "id-ct-rpkiManifest" */
+1014,	/* "id-ct-signedChecklist" */
+1024,	/* "id-ct-signedTAL" */
+802,	/* "id-dsa-with-sha224" */
+803,	/* "id-dsa-with-sha256" */
+1041,	/* "id-dsa-with-sha3-224" */
+1042,	/* "id-dsa-with-sha3-256" */
+1043,	/* "id-dsa-with-sha3-384" */
+1044,	/* "id-dsa-with-sha3-512" */
+1039,	/* "id-dsa-with-sha384" */
+1040,	/* "id-dsa-with-sha512" */
+408,	/* "id-ecPublicKey" */
+1045,	/* "id-ecdsa-with-sha3-224" */
+1046,	/* "id-ecdsa-with-sha3-256" */
+1047,	/* "id-ecdsa-with-sha3-384" */
+1048,	/* "id-ecdsa-with-sha3-512" */
+508,	/* "id-hex-multipart-message" */
+507,	/* "id-hex-partial-message" */
+1035,	/* "id-hmacWithSHA3-224" */
+1036,	/* "id-hmacWithSHA3-256" */
+1037,	/* "id-hmacWithSHA3-384" */
+1038,	/* "id-hmacWithSHA3-512" */
+260,	/* "id-it" */
+302,	/* "id-it-caKeyUpdateInfo" */
+298,	/* "id-it-caProtEncCert" */
+311,	/* "id-it-confirmWaitTime" */
+303,	/* "id-it-currentCRL" */
+300,	/* "id-it-encKeyPairTypes" */
+310,	/* "id-it-implicitConfirm" */
+308,	/* "id-it-keyPairParamRep" */
+307,	/* "id-it-keyPairParamReq" */
+312,	/* "id-it-origPKIMessage" */
+301,	/* "id-it-preferredSymmAlg" */
+309,	/* "id-it-revPassphrase" */
+299,	/* "id-it-signKeyPairTypes" */
+305,	/* "id-it-subscriptionRequest" */
+306,	/* "id-it-subscriptionResponse" */
+784,	/* "id-it-suppLangTags" */
+304,	/* "id-it-unsupportedOIDs" */
+128,	/* "id-kp" */
+1015,	/* "id-kp-bgpsec-router" */
+280,	/* "id-mod-attribute-cert" */
+274,	/* "id-mod-cmc" */
+277,	/* "id-mod-cmp" */
+284,	/* "id-mod-cmp2000" */
+273,	/* "id-mod-crmf" */
+283,	/* "id-mod-dvcs" */
+275,	/* "id-mod-kea-profile-88" */
+276,	/* "id-mod-kea-profile-93" */
+282,	/* "id-mod-ocsp" */
+278,	/* "id-mod-qualified-cert-88" */
+279,	/* "id-mod-qualified-cert-93" */
+281,	/* "id-mod-timestamp-protocol" */
+264,	/* "id-on" */
+858,	/* "id-on-permanentIdentifier" */
+347,	/* "id-on-personalData" */
+265,	/* "id-pda" */
+352,	/* "id-pda-countryOfCitizenship" */
+353,	/* "id-pda-countryOfResidence" */
+348,	/* "id-pda-dateOfBirth" */
+351,	/* "id-pda-gender" */
+349,	/* "id-pda-placeOfBirth" */
+175,	/* "id-pe" */
+261,	/* "id-pkip" */
+258,	/* "id-pkix-mod" */
+269,	/* "id-pkix1-explicit-88" */
+271,	/* "id-pkix1-explicit-93" */
+270,	/* "id-pkix1-implicit-88" */
+272,	/* "id-pkix1-implicit-93" */
+662,	/* "id-ppl" */
+664,	/* "id-ppl-anyLanguage" */
+667,	/* "id-ppl-independent" */
+665,	/* "id-ppl-inheritAll" */
+267,	/* "id-qcs" */
+359,	/* "id-qcs-pkixQCSyntax-v1" */
+259,	/* "id-qt" */
+164,	/* "id-qt-cps" */
+165,	/* "id-qt-unotice" */
+313,	/* "id-regCtrl" */
+316,	/* "id-regCtrl-authenticator" */
+319,	/* "id-regCtrl-oldCertID" */
+318,	/* "id-regCtrl-pkiArchiveOptions" */
+317,	/* "id-regCtrl-pkiPublicationInfo" */
+320,	/* "id-regCtrl-protocolEncrKey" */
+315,	/* "id-regCtrl-regToken" */
+314,	/* "id-regInfo" */
+322,	/* "id-regInfo-certReq" */
+321,	/* "id-regInfo-utf8Pairs" */
+1049,	/* "id-rsassa-pkcs1-v1_5-with-sha3-224" */
+1050,	/* "id-rsassa-pkcs1-v1_5-with-sha3-256" */
+1051,	/* "id-rsassa-pkcs1-v1_5-with-sha3-384" */
+1052,	/* "id-rsassa-pkcs1-v1_5-with-sha3-512" */
+512,	/* "id-set" */
+191,	/* "id-smime-aa" */
+215,	/* "id-smime-aa-contentHint" */
+218,	/* "id-smime-aa-contentIdentifier" */
+221,	/* "id-smime-aa-contentReference" */
+240,	/* "id-smime-aa-dvcs-dvc" */
+217,	/* "id-smime-aa-encapContentType" */
+222,	/* "id-smime-aa-encrypKeyPref" */
+220,	/* "id-smime-aa-equivalentLabels" */
+232,	/* "id-smime-aa-ets-CertificateRefs" */
+233,	/* "id-smime-aa-ets-RevocationRefs" */
+238,	/* "id-smime-aa-ets-archiveTimeStamp" */
+237,	/* "id-smime-aa-ets-certCRLTimestamp" */
+234,	/* "id-smime-aa-ets-certValues" */
+227,	/* "id-smime-aa-ets-commitmentType" */
+231,	/* "id-smime-aa-ets-contentTimestamp" */
+236,	/* "id-smime-aa-ets-escTimeStamp" */
+230,	/* "id-smime-aa-ets-otherSigCert" */
+235,	/* "id-smime-aa-ets-revocationValues" */
+226,	/* "id-smime-aa-ets-sigPolicyId" */
+229,	/* "id-smime-aa-ets-signerAttr" */
+228,	/* "id-smime-aa-ets-signerLocation" */
+219,	/* "id-smime-aa-macValue" */
+214,	/* "id-smime-aa-mlExpandHistory" */
+216,	/* "id-smime-aa-msgSigDigest" */
+212,	/* "id-smime-aa-receiptRequest" */
+213,	/* "id-smime-aa-securityLabel" */
+239,	/* "id-smime-aa-signatureType" */
+223,	/* "id-smime-aa-signingCertificate" */
+1023,	/* "id-smime-aa-signingCertificateV2" */
+224,	/* "id-smime-aa-smimeEncryptCerts" */
+225,	/* "id-smime-aa-timeStampToken" */
+192,	/* "id-smime-alg" */
+243,	/* "id-smime-alg-3DESwrap" */
+246,	/* "id-smime-alg-CMS3DESwrap" */
+247,	/* "id-smime-alg-CMSRC2wrap" */
+245,	/* "id-smime-alg-ESDH" */
+241,	/* "id-smime-alg-ESDHwith3DES" */
+242,	/* "id-smime-alg-ESDHwithRC2" */
+244,	/* "id-smime-alg-RC2wrap" */
+193,	/* "id-smime-cd" */
+248,	/* "id-smime-cd-ldap" */
+190,	/* "id-smime-ct" */
+210,	/* "id-smime-ct-DVCSRequestData" */
+211,	/* "id-smime-ct-DVCSResponseData" */
+208,	/* "id-smime-ct-TDTInfo" */
+207,	/* "id-smime-ct-TSTInfo" */
+205,	/* "id-smime-ct-authData" */
+786,	/* "id-smime-ct-compressedData" */
+209,	/* "id-smime-ct-contentInfo" */
+206,	/* "id-smime-ct-publishCert" */
+204,	/* "id-smime-ct-receipt" */
+195,	/* "id-smime-cti" */
+255,	/* "id-smime-cti-ets-proofOfApproval" */
+256,	/* "id-smime-cti-ets-proofOfCreation" */
+253,	/* "id-smime-cti-ets-proofOfDelivery" */
+251,	/* "id-smime-cti-ets-proofOfOrigin" */
+252,	/* "id-smime-cti-ets-proofOfReceipt" */
+254,	/* "id-smime-cti-ets-proofOfSender" */
+189,	/* "id-smime-mod" */
+196,	/* "id-smime-mod-cms" */
+197,	/* "id-smime-mod-ess" */
+202,	/* "id-smime-mod-ets-eSigPolicy-88" */
+203,	/* "id-smime-mod-ets-eSigPolicy-97" */
+200,	/* "id-smime-mod-ets-eSignature-88" */
+201,	/* "id-smime-mod-ets-eSignature-97" */
+199,	/* "id-smime-mod-msg-v3" */
+198,	/* "id-smime-mod-oid" */
+194,	/* "id-smime-spq" */
+250,	/* "id-smime-spq-ets-sqt-unotice" */
+249,	/* "id-smime-spq-ets-sqt-uri" */
+945,	/* "id-tc26-gost-28147-param-Z" */
+993,	/* "id-tc26-gost-3410-12-256-paramSetA" */
+994,	/* "id-tc26-gost-3410-12-256-paramSetB" */
+995,	/* "id-tc26-gost-3410-12-256-paramSetC" */
+996,	/* "id-tc26-gost-3410-12-256-paramSetD" */
+943,	/* "id-tc26-gost-3410-12-512-paramSetA" */
+944,	/* "id-tc26-gost-3410-12-512-paramSetB" */
+998,	/* "id-tc26-gost-3410-12-512-paramSetC" */
+997,	/* "id-tc26-gost-3410-12-512-paramSetTest" */
+946,	/* "id-tc26-gost3410-2012-256" */
+947,	/* "id-tc26-gost3410-2012-512" */
+999,	/* "id-tc26-hmac-gost-3411-12-256" */
+1000,	/* "id-tc26-hmac-gost-3411-12-512" */
+948,	/* "id-tc26-signwithdigest-gost3410-2012-256" */
+949,	/* "id-tc26-signwithdigest-gost3410-2012-512" */
+676,	/* "identified-organization" */
+461,	/* "info" */
+748,	/* "inhibitAnyPolicy" */
+101,	/* "initials" */
+647,	/* "international-organizations" */
+869,	/* "internationaliSDNNumber" */
+142,	/* "invalidityDate" */
+1008,	/* "ipAddr-asNumber" */
+1009,	/* "ipAddr-asNumberv2" */
+294,	/* "ipsecEndSystem" */
+295,	/* "ipsecTunnel" */
+296,	/* "ipsecUser" */
+86,	/* "issuerAltName" */
+770,	/* "issuingDistributionPoint" */
+492,	/* "janetMailbox" */
+958,	/* "jurisdictionCountryName" */
+956,	/* "jurisdictionLocalityName" */
+957,	/* "jurisdictionStateOrProvinceName" */
+150,	/* "keyBag" */
+83,	/* "keyUsage" */
+477,	/* "lastModifiedBy" */
+476,	/* "lastModifiedTime" */
+157,	/* "localKeyID" */
+480,	/* "mXRecord" */
+460,	/* "mail" */
+493,	/* "mailPreferenceOption" */
+467,	/* "manager" */
+809,	/* "md_gost94" */
+875,	/* "member" */
+182,	/* "member-body" */
+51,	/* "messageDigest" */
+383,	/* "mgmt" */
+504,	/* "mime-mhs" */
+506,	/* "mime-mhs-bodies" */
+505,	/* "mime-mhs-headings" */
+488,	/* "mobileTelephoneNumber" */
+136,	/* "msCTLSign" */
+135,	/* "msCodeCom" */
+134,	/* "msCodeInd" */
+138,	/* "msEFS" */
+171,	/* "msExtReq" */
+137,	/* "msSGC" */
+648,	/* "msSmartcardLogin" */
+649,	/* "msUPN" */
+481,	/* "nSRecord" */
+173,	/* "name" */
+666,	/* "nameConstraints" */
+369,	/* "noCheck" */
+403,	/* "noRevAvail" */
+72,	/* "nsBaseUrl" */
+76,	/* "nsCaPolicyUrl" */
+74,	/* "nsCaRevocationUrl" */
+58,	/* "nsCertExt" */
+79,	/* "nsCertSequence" */
+71,	/* "nsCertType" */
+78,	/* "nsComment" */
+59,	/* "nsDataType" */
+75,	/* "nsRenewalUrl" */
+73,	/* "nsRevocationUrl" */
+139,	/* "nsSGC" */
+77,	/* "nsSslServerName" */
+681,	/* "onBasis" */
+491,	/* "organizationalStatus" */
+971,	/* "oscca" */
+475,	/* "otherMailbox" */
+876,	/* "owner" */
+489,	/* "pagerTelephoneNumber" */
+374,	/* "path" */
+112,	/* "pbeWithMD5AndCast5CBC" */
+499,	/* "personalSignature" */
+487,	/* "personalTitle" */
+464,	/* "photo" */
+863,	/* "physicalDeliveryOfficeName" */
+437,	/* "pilot" */
+439,	/* "pilotAttributeSyntax" */
+438,	/* "pilotAttributeType" */
+479,	/* "pilotAttributeType27" */
+456,	/* "pilotDSA" */
+441,	/* "pilotGroups" */
+444,	/* "pilotObject" */
+440,	/* "pilotObjectClass" */
+455,	/* "pilotOrganization" */
+445,	/* "pilotPerson" */
+ 2,	/* "pkcs" */
+186,	/* "pkcs1" */
+27,	/* "pkcs3" */
+187,	/* "pkcs5" */
+20,	/* "pkcs7" */
+21,	/* "pkcs7-data" */
+25,	/* "pkcs7-digestData" */
+26,	/* "pkcs7-encryptedData" */
+23,	/* "pkcs7-envelopedData" */
+24,	/* "pkcs7-signedAndEnvelopedData" */
+22,	/* "pkcs7-signedData" */
+151,	/* "pkcs8ShroudedKeyBag" */
+47,	/* "pkcs9" */
+401,	/* "policyConstraints" */
+747,	/* "policyMappings" */
+862,	/* "postOfficeBox" */
+861,	/* "postalAddress" */
+661,	/* "postalCode" */
+683,	/* "ppBasis" */
+872,	/* "preferredDeliveryMethod" */
+873,	/* "presentationAddress" */
+816,	/* "prf-gostr3411-94" */
+406,	/* "prime-field" */
+409,	/* "prime192v1" */
+410,	/* "prime192v2" */
+411,	/* "prime192v3" */
+412,	/* "prime239v1" */
+413,	/* "prime239v2" */
+414,	/* "prime239v3" */
+415,	/* "prime256v1" */
+385,	/* "private" */
+84,	/* "privateKeyUsagePeriod" */
+886,	/* "protocolInformation" */
+663,	/* "proxyCertInfo" */
+510,	/* "pseudonym" */
+435,	/* "pss" */
+286,	/* "qcStatements" */
+457,	/* "qualityLabelledData" */
+450,	/* "rFC822localPart" */
+870,	/* "registeredAddress" */
+400,	/* "role" */
+877,	/* "roleOccupant" */
+448,	/* "room" */
+463,	/* "roomNumber" */
+1010,	/* "rpkiManifest" */
+1012,	/* "rpkiNotify" */
+ 6,	/* "rsaEncryption" */
+644,	/* "rsaOAEPEncryptionSET" */
+377,	/* "rsaSignature" */
+ 1,	/* "rsadsi" */
+482,	/* "sOARecord" */
+155,	/* "safeContentsBag" */
+291,	/* "sbgp-autonomousSysNum" */
+1007,	/* "sbgp-autonomousSysNumv2" */
+290,	/* "sbgp-ipAddrBlock" */
+1006,	/* "sbgp-ipAddrBlockv2" */
+292,	/* "sbgp-routerIdentifier" */
+159,	/* "sdsiCertificate" */
+859,	/* "searchGuide" */
+704,	/* "secp112r1" */
+705,	/* "secp112r2" */
+706,	/* "secp128r1" */
+707,	/* "secp128r2" */
+708,	/* "secp160k1" */
+709,	/* "secp160r1" */
+710,	/* "secp160r2" */
+711,	/* "secp192k1" */
+712,	/* "secp224k1" */
+713,	/* "secp224r1" */
+714,	/* "secp256k1" */
+715,	/* "secp384r1" */
+716,	/* "secp521r1" */
+154,	/* "secretBag" */
+474,	/* "secretary" */
+717,	/* "sect113r1" */
+718,	/* "sect113r2" */
+719,	/* "sect131r1" */
+720,	/* "sect131r2" */
+721,	/* "sect163k1" */
+722,	/* "sect163r1" */
+723,	/* "sect163r2" */
+724,	/* "sect193r1" */
+725,	/* "sect193r2" */
+726,	/* "sect233k1" */
+727,	/* "sect233r1" */
+728,	/* "sect239k1" */
+729,	/* "sect283k1" */
+730,	/* "sect283r1" */
+731,	/* "sect409k1" */
+732,	/* "sect409r1" */
+733,	/* "sect571k1" */
+734,	/* "sect571r1" */
+386,	/* "security" */
+878,	/* "seeAlso" */
+394,	/* "selected-attribute-types" */
+105,	/* "serialNumber" */
+129,	/* "serverAuth" */
+371,	/* "serviceLocator" */
+625,	/* "set-addPolicy" */
+515,	/* "set-attr" */
+518,	/* "set-brand" */
+638,	/* "set-brand-AmericanExpress" */
+637,	/* "set-brand-Diners" */
+636,	/* "set-brand-IATA-ATA" */
+639,	/* "set-brand-JCB" */
+641,	/* "set-brand-MasterCard" */
+642,	/* "set-brand-Novus" */
+640,	/* "set-brand-Visa" */
+517,	/* "set-certExt" */
+513,	/* "set-ctype" */
+514,	/* "set-msgExt" */
+516,	/* "set-policy" */
+607,	/* "set-policy-root" */
+624,	/* "set-rootKeyThumb" */
+620,	/* "setAttr-Cert" */
+631,	/* "setAttr-GenCryptgrm" */
+623,	/* "setAttr-IssCap" */
+628,	/* "setAttr-IssCap-CVM" */
+630,	/* "setAttr-IssCap-Sig" */
+629,	/* "setAttr-IssCap-T2" */
+621,	/* "setAttr-PGWYcap" */
+635,	/* "setAttr-SecDevSig" */
+632,	/* "setAttr-T2Enc" */
+633,	/* "setAttr-T2cleartxt" */
+634,	/* "setAttr-TokICCsig" */
+627,	/* "setAttr-Token-B0Prime" */
+626,	/* "setAttr-Token-EMV" */
+622,	/* "setAttr-TokenType" */
+619,	/* "setCext-IssuerCapabilities" */
+615,	/* "setCext-PGWYcapabilities" */
+616,	/* "setCext-TokenIdentifier" */
+618,	/* "setCext-TokenType" */
+617,	/* "setCext-Track2Data" */
+611,	/* "setCext-cCertRequired" */
+609,	/* "setCext-certType" */
+608,	/* "setCext-hashedRoot" */
+610,	/* "setCext-merchData" */
+613,	/* "setCext-setExt" */
+614,	/* "setCext-setQualf" */
+612,	/* "setCext-tunneling" */
+540,	/* "setct-AcqCardCodeMsg" */
+576,	/* "setct-AcqCardCodeMsgTBE" */
+570,	/* "setct-AuthReqTBE" */
+534,	/* "setct-AuthReqTBS" */
+527,	/* "setct-AuthResBaggage" */
+571,	/* "setct-AuthResTBE" */
+572,	/* "setct-AuthResTBEX" */
+535,	/* "setct-AuthResTBS" */
+536,	/* "setct-AuthResTBSX" */
+528,	/* "setct-AuthRevReqBaggage" */
+577,	/* "setct-AuthRevReqTBE" */
+541,	/* "setct-AuthRevReqTBS" */
+529,	/* "setct-AuthRevResBaggage" */
+542,	/* "setct-AuthRevResData" */
+578,	/* "setct-AuthRevResTBE" */
+579,	/* "setct-AuthRevResTBEB" */
+543,	/* "setct-AuthRevResTBS" */
+573,	/* "setct-AuthTokenTBE" */
+537,	/* "setct-AuthTokenTBS" */
+600,	/* "setct-BCIDistributionTBS" */
+558,	/* "setct-BatchAdminReqData" */
+592,	/* "setct-BatchAdminReqTBE" */
+559,	/* "setct-BatchAdminResData" */
+593,	/* "setct-BatchAdminResTBE" */
+599,	/* "setct-CRLNotificationResTBS" */
+598,	/* "setct-CRLNotificationTBS" */
+580,	/* "setct-CapReqTBE" */
+581,	/* "setct-CapReqTBEX" */
+544,	/* "setct-CapReqTBS" */
+545,	/* "setct-CapReqTBSX" */
+546,	/* "setct-CapResData" */
+582,	/* "setct-CapResTBE" */
+583,	/* "setct-CapRevReqTBE" */
+584,	/* "setct-CapRevReqTBEX" */
+547,	/* "setct-CapRevReqTBS" */
+548,	/* "setct-CapRevReqTBSX" */
+549,	/* "setct-CapRevResData" */
+585,	/* "setct-CapRevResTBE" */
+538,	/* "setct-CapTokenData" */
+530,	/* "setct-CapTokenSeq" */
+574,	/* "setct-CapTokenTBE" */
+575,	/* "setct-CapTokenTBEX" */
+539,	/* "setct-CapTokenTBS" */
+560,	/* "setct-CardCInitResTBS" */
+566,	/* "setct-CertInqReqTBS" */
+563,	/* "setct-CertReqData" */
+595,	/* "setct-CertReqTBE" */
+596,	/* "setct-CertReqTBEX" */
+564,	/* "setct-CertReqTBS" */
+565,	/* "setct-CertResData" */
+597,	/* "setct-CertResTBE" */
+586,	/* "setct-CredReqTBE" */
+587,	/* "setct-CredReqTBEX" */
+550,	/* "setct-CredReqTBS" */
+551,	/* "setct-CredReqTBSX" */
+552,	/* "setct-CredResData" */
+588,	/* "setct-CredResTBE" */
+589,	/* "setct-CredRevReqTBE" */
+590,	/* "setct-CredRevReqTBEX" */
+553,	/* "setct-CredRevReqTBS" */
+554,	/* "setct-CredRevReqTBSX" */
+555,	/* "setct-CredRevResData" */
+591,	/* "setct-CredRevResTBE" */
+567,	/* "setct-ErrorTBS" */
+526,	/* "setct-HODInput" */
+561,	/* "setct-MeAqCInitResTBS" */
+522,	/* "setct-OIData" */
+519,	/* "setct-PANData" */
+521,	/* "setct-PANOnly" */
+520,	/* "setct-PANToken" */
+556,	/* "setct-PCertReqData" */
+557,	/* "setct-PCertResTBS" */
+523,	/* "setct-PI" */
+532,	/* "setct-PI-TBS" */
+524,	/* "setct-PIData" */
+525,	/* "setct-PIDataUnsigned" */
+568,	/* "setct-PIDualSignedTBE" */
+569,	/* "setct-PIUnsignedTBE" */
+531,	/* "setct-PInitResData" */
+533,	/* "setct-PResData" */
+594,	/* "setct-RegFormReqTBE" */
+562,	/* "setct-RegFormResTBS" */
+606,	/* "setext-cv" */
+601,	/* "setext-genCrypt" */
+602,	/* "setext-miAuth" */
+604,	/* "setext-pinAny" */
+603,	/* "setext-pinSecure" */
+605,	/* "setext-track2" */
+1011,	/* "signedObject" */
+52,	/* "signingTime" */
+454,	/* "simpleSecurityObject" */
+496,	/* "singleLevelQuality" */
+972,	/* "sm-scheme" */
+387,	/* "snmpv2" */
+941,	/* "streebog256" */
+942,	/* "streebog512" */
+660,	/* "street" */
+85,	/* "subjectAltName" */
+769,	/* "subjectDirectoryAttributes" */
+398,	/* "subjectInfoAccess" */
+82,	/* "subjectKeyIdentifier" */
+498,	/* "subtreeMaximumQuality" */
+497,	/* "subtreeMinimumQuality" */
+890,	/* "supportedAlgorithms" */
+874,	/* "supportedApplicationContext" */
+402,	/* "targetInformation" */
+940,	/* "tc26" */
+864,	/* "telephoneNumber" */
+866,	/* "teletexTerminalIdentifier" */
+920,	/* "teletrust" */
+865,	/* "telexNumber" */
+459,	/* "textEncodedORAddress" */
+293,	/* "textNotice" */
+133,	/* "timeStamping" */
+106,	/* "title" */
+1016,	/* "tlsfeature" */
+682,	/* "tpBasis" */
+375,	/* "trustRoot" */
+436,	/* "ucl" */
+888,	/* "uniqueMember" */
+55,	/* "unstructuredAddress" */
+49,	/* "unstructuredName" */
+880,	/* "userCertificate" */
+465,	/* "userClass" */
+879,	/* "userPassword" */
+373,	/* "valid" */
+678,	/* "wap" */
+679,	/* "wap-wsg" */
+735,	/* "wap-wsg-idm-ecid-wtls1" */
+743,	/* "wap-wsg-idm-ecid-wtls10" */
+744,	/* "wap-wsg-idm-ecid-wtls11" */
+745,	/* "wap-wsg-idm-ecid-wtls12" */
+736,	/* "wap-wsg-idm-ecid-wtls3" */
+737,	/* "wap-wsg-idm-ecid-wtls4" */
+738,	/* "wap-wsg-idm-ecid-wtls5" */
+739,	/* "wap-wsg-idm-ecid-wtls6" */
+740,	/* "wap-wsg-idm-ecid-wtls7" */
+741,	/* "wap-wsg-idm-ecid-wtls8" */
+742,	/* "wap-wsg-idm-ecid-wtls9" */
+804,	/* "whirlpool" */
+868,	/* "x121Address" */
+503,	/* "x500UniqueIdentifier" */
+158,	/* "x509Certificate" */
+160,	/* "x509Crl" */
+};
+
+static const unsigned int ln_objs[NUM_LN]={
+363,	/* "AD Time Stamping" */
+405,	/* "ANSI X9.62" */
+368,	/* "Acceptable OCSP Responses" */
+910,	/* "Any Extended Key Usage" */
+664,	/* "Any language" */
+177,	/* "Authority Information Access" */
+1015,	/* "BGPsec Router" */
+365,	/* "Basic OCSP Response" */
+285,	/* "Biometric Info" */
+179,	/* "CA Issuers" */
+785,	/* "CA Repository" */
+1021,	/* "CT Certificate SCTs" */
+1019,	/* "CT Precertificate Poison" */
+1018,	/* "CT Precertificate SCTs" */
+1020,	/* "CT Precertificate Signer" */
+131,	/* "Code Signing" */
+783,	/* "Diffie-Hellman based MAC" */
+382,	/* "Directory" */
+392,	/* "Domain" */
+132,	/* "E-mail Protection" */
+952,	/* "Ed25519" */
+954,	/* "Ed25519ph" */
+953,	/* "Ed448" */
+955,	/* "Ed448ph" */
+389,	/* "Enterprises" */
+384,	/* "Experimental" */
+372,	/* "Extended OCSP Status" */
+172,	/* "Extension Request" */
+936,	/* "FRP256v1" */
+813,	/* "GOST 28147-89" */
+849,	/* "GOST 28147-89 Cryptocom ParamSet" */
+815,	/* "GOST 28147-89 MAC" */
+851,	/* "GOST 34.10-2001 Cryptocom" */
+850,	/* "GOST 34.10-94 Cryptocom" */
+942,	/* "GOST R 34-11-2012 (512 bit)" */
+811,	/* "GOST R 34.10-2001" */
+817,	/* "GOST R 34.10-2001 DH" */
+946,	/* "GOST R 34.10-2012 (256 bit)" */
+993,	/* "GOST R 34.10-2012 (256 bit) ParamSet A" */
+994,	/* "GOST R 34.10-2012 (256 bit) ParamSet B" */
+995,	/* "GOST R 34.10-2012 (256 bit) ParamSet C" */
+996,	/* "GOST R 34.10-2012 (256 bit) ParamSet D" */
+947,	/* "GOST R 34.10-2012 (512 bit)" */
+943,	/* "GOST R 34.10-2012 (512 bit) ParamSet A" */
+944,	/* "GOST R 34.10-2012 (512 bit) ParamSet B" */
+998,	/* "GOST R 34.10-2012 (512 bit) ParamSet C" */
+997,	/* "GOST R 34.10-2012 (512 bit) testing parameter set" */
+812,	/* "GOST R 34.10-94" */
+818,	/* "GOST R 34.10-94 DH" */
+941,	/* "GOST R 34.11-2012 (256 bit)" */
+948,	/* "GOST R 34.11-2012 with GOST R 34.10-2012 (256 bit)" */
+949,	/* "GOST R 34.11-2012 with GOST R 34.10-2012 (512 bit)" */
+809,	/* "GOST R 34.11-94" */
+816,	/* "GOST R 34.11-94 PRF" */
+807,	/* "GOST R 34.11-94 with GOST R 34.10-2001" */
+853,	/* "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" */
+808,	/* "GOST R 34.11-94 with GOST R 34.10-94" */
+852,	/* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
+854,	/* "GOST R 3410-2001 Parameter Set Cryptocom" */
+810,	/* "HMAC GOST 34.11-94" */
+999,	/* "HMAC STREEBOG 256" */
+1000,	/* "HMAC STREEBOG 512" */
+432,	/* "Hold Instruction Call Issuer" */
+430,	/* "Hold Instruction Code" */
+431,	/* "Hold Instruction None" */
+433,	/* "Hold Instruction Reject" */
+634,	/* "ICC or token signature" */
+294,	/* "IPSec End System" */
+295,	/* "IPSec Tunnel" */
+296,	/* "IPSec User" */
+970,	/* "ISO CN Member Body" */
+182,	/* "ISO Member Body" */
+183,	/* "ISO US Member Body" */
+667,	/* "Independent" */
+665,	/* "Inherit all" */
+647,	/* "International Organizations" */
+142,	/* "Invalidity Date" */
+504,	/* "MIME MHS" */
+388,	/* "Mail" */
+383,	/* "Management" */
+417,	/* "Microsoft CSP Name" */
+135,	/* "Microsoft Commercial Code Signing" */
+138,	/* "Microsoft Encrypted File System" */
+171,	/* "Microsoft Extension Request" */
+134,	/* "Microsoft Individual Code Signing" */
+856,	/* "Microsoft Local Key set" */
+137,	/* "Microsoft Server Gated Crypto" */
+648,	/* "Microsoft Smartcardlogin" */
+136,	/* "Microsoft Trust List Signing" */
+649,	/* "Microsoft Universal Principal Name" */
+393,	/* "NULL" */
+404,	/* "NULL" */
+72,	/* "Netscape Base Url" */
+76,	/* "Netscape CA Policy Url" */
+74,	/* "Netscape CA Revocation Url" */
+71,	/* "Netscape Cert Type" */
+58,	/* "Netscape Certificate Extension" */
+79,	/* "Netscape Certificate Sequence" */
+78,	/* "Netscape Comment" */
+57,	/* "Netscape Communications Corp." */
+59,	/* "Netscape Data Type" */
+75,	/* "Netscape Renewal Url" */
+73,	/* "Netscape Revocation Url" */
+77,	/* "Netscape SSL Server Name" */
+139,	/* "Netscape Server Gated Crypto" */
+178,	/* "OCSP" */
+370,	/* "OCSP Archive Cutoff" */
+367,	/* "OCSP CRL ID" */
+369,	/* "OCSP No Check" */
+366,	/* "OCSP Nonce" */
+371,	/* "OCSP Service Locator" */
+180,	/* "OCSP Signing" */
+161,	/* "PBES2" */
+69,	/* "PBKDF2" */
+162,	/* "PBMAC1" */
+127,	/* "PKIX" */
+858,	/* "Permanent Identifier" */
+164,	/* "Policy Qualifier CPS" */
+165,	/* "Policy Qualifier User Notice" */
+385,	/* "Private" */
+663,	/* "Proxy Certificate Information" */
+1010,	/* "RPKI Manifest" */
+1012,	/* "RPKI Notify" */
+ 1,	/* "RSA Data Security, Inc." */
+ 2,	/* "RSA Data Security, Inc. PKCS" */
+1049,	/* "RSA-SHA3-224" */
+1050,	/* "RSA-SHA3-256" */
+1051,	/* "RSA-SHA3-384" */
+1052,	/* "RSA-SHA3-512" */
+188,	/* "S/MIME" */
+167,	/* "S/MIME Capabilities" */
+387,	/* "SNMPv2" */
+512,	/* "Secure Electronic Transactions" */
+386,	/* "Security" */
+394,	/* "Selected Attribute Types" */
+1011,	/* "Signed Object" */
+143,	/* "Strong Extranet ID" */
+398,	/* "Subject Information Access" */
+1016,	/* "TLS Feature" */
+130,	/* "TLS Web Client Authentication" */
+129,	/* "TLS Web Server Authentication" */
+133,	/* "Time Stamping" */
+375,	/* "Trust Root" */
+950,	/* "X25519" */
+951,	/* "X448" */
+12,	/* "X509" */
+402,	/* "X509v3 AC Targeting" */
+746,	/* "X509v3 Any Policy" */
+90,	/* "X509v3 Authority Key Identifier" */
+87,	/* "X509v3 Basic Constraints" */
+103,	/* "X509v3 CRL Distribution Points" */
+88,	/* "X509v3 CRL Number" */
+141,	/* "X509v3 CRL Reason Code" */
+771,	/* "X509v3 Certificate Issuer" */
+89,	/* "X509v3 Certificate Policies" */
+140,	/* "X509v3 Delta CRL Indicator" */
+126,	/* "X509v3 Extended Key Usage" */
+857,	/* "X509v3 Freshest CRL" */
+748,	/* "X509v3 Inhibit Any Policy" */
+86,	/* "X509v3 Issuer Alternative Name" */
+770,	/* "X509v3 Issuing Distribution Point" */
+83,	/* "X509v3 Key Usage" */
+666,	/* "X509v3 Name Constraints" */
+403,	/* "X509v3 No Revocation Available" */
+401,	/* "X509v3 Policy Constraints" */
+747,	/* "X509v3 Policy Mappings" */
+84,	/* "X509v3 Private Key Usage Period" */
+85,	/* "X509v3 Subject Alternative Name" */
+769,	/* "X509v3 Subject Directory Attributes" */
+82,	/* "X509v3 Subject Key Identifier" */
+184,	/* "X9.57" */
+185,	/* "X9.57 CM ?" */
+478,	/* "aRecord" */
+289,	/* "aaControls" */
+287,	/* "ac-auditEntity" */
+397,	/* "ac-proxying" */
+288,	/* "ac-targeting" */
+446,	/* "account" */
+364,	/* "ad dvcs" */
+606,	/* "additional verification" */
+419,	/* "aes-128-cbc" */
+916,	/* "aes-128-cbc-hmac-sha1" */
+896,	/* "aes-128-ccm" */
+421,	/* "aes-128-cfb" */
+650,	/* "aes-128-cfb1" */
+653,	/* "aes-128-cfb8" */
+904,	/* "aes-128-ctr" */
+418,	/* "aes-128-ecb" */
+895,	/* "aes-128-gcm" */
+420,	/* "aes-128-ofb" */
+913,	/* "aes-128-xts" */
+423,	/* "aes-192-cbc" */
+917,	/* "aes-192-cbc-hmac-sha1" */
+899,	/* "aes-192-ccm" */
+425,	/* "aes-192-cfb" */
+651,	/* "aes-192-cfb1" */
+654,	/* "aes-192-cfb8" */
+905,	/* "aes-192-ctr" */
+422,	/* "aes-192-ecb" */
+898,	/* "aes-192-gcm" */
+424,	/* "aes-192-ofb" */
+427,	/* "aes-256-cbc" */
+918,	/* "aes-256-cbc-hmac-sha1" */
+902,	/* "aes-256-ccm" */
+429,	/* "aes-256-cfb" */
+652,	/* "aes-256-cfb1" */
+655,	/* "aes-256-cfb8" */
+906,	/* "aes-256-ctr" */
+426,	/* "aes-256-ecb" */
+901,	/* "aes-256-gcm" */
+428,	/* "aes-256-ofb" */
+914,	/* "aes-256-xts" */
+376,	/* "algorithm" */
+484,	/* "associatedDomain" */
+485,	/* "associatedName" */
+501,	/* "audio" */
+964,	/* "auth-ecdsa" */
+965,	/* "auth-gost01" */
+966,	/* "auth-null" */
+963,	/* "auth-rsa" */
+882,	/* "authorityRevocationList" */
+91,	/* "bf-cbc" */
+93,	/* "bf-cfb" */
+92,	/* "bf-ecb" */
+94,	/* "bf-ofb" */
+921,	/* "brainpool" */
+922,	/* "brainpoolP160r1" */
+923,	/* "brainpoolP160t1" */
+924,	/* "brainpoolP192r1" */
+925,	/* "brainpoolP192t1" */
+926,	/* "brainpoolP224r1" */
+927,	/* "brainpoolP224t1" */
+928,	/* "brainpoolP256r1" */
+929,	/* "brainpoolP256t1" */
+930,	/* "brainpoolP320r1" */
+931,	/* "brainpoolP320t1" */
+932,	/* "brainpoolP384r1" */
+933,	/* "brainpoolP384t1" */
+934,	/* "brainpoolP512r1" */
+935,	/* "brainpoolP512t1" */
+494,	/* "buildingName" */
+860,	/* "businessCategory" */
+691,	/* "c2onb191v4" */
+692,	/* "c2onb191v5" */
+697,	/* "c2onb239v4" */
+698,	/* "c2onb239v5" */
+684,	/* "c2pnb163v1" */
+685,	/* "c2pnb163v2" */
+686,	/* "c2pnb163v3" */
+687,	/* "c2pnb176v1" */
+693,	/* "c2pnb208w1" */
+699,	/* "c2pnb272w1" */
+700,	/* "c2pnb304w1" */
+702,	/* "c2pnb368w1" */
+688,	/* "c2tnb191v1" */
+689,	/* "c2tnb191v2" */
+690,	/* "c2tnb191v3" */
+694,	/* "c2tnb239v1" */
+695,	/* "c2tnb239v2" */
+696,	/* "c2tnb239v3" */
+701,	/* "c2tnb359v1" */
+703,	/* "c2tnb431r1" */
+881,	/* "cACertificate" */
+483,	/* "cNAMERecord" */
+751,	/* "camellia-128-cbc" */
+757,	/* "camellia-128-cfb" */
+760,	/* "camellia-128-cfb1" */
+763,	/* "camellia-128-cfb8" */
+754,	/* "camellia-128-ecb" */
+766,	/* "camellia-128-ofb" */
+752,	/* "camellia-192-cbc" */
+758,	/* "camellia-192-cfb" */
+761,	/* "camellia-192-cfb1" */
+764,	/* "camellia-192-cfb8" */
+755,	/* "camellia-192-ecb" */
+767,	/* "camellia-192-ofb" */
+753,	/* "camellia-256-cbc" */
+759,	/* "camellia-256-cfb" */
+762,	/* "camellia-256-cfb1" */
+765,	/* "camellia-256-cfb8" */
+756,	/* "camellia-256-ecb" */
+768,	/* "camellia-256-ofb" */
+443,	/* "caseIgnoreIA5StringSyntax" */
+108,	/* "cast5-cbc" */
+110,	/* "cast5-cfb" */
+109,	/* "cast5-ecb" */
+111,	/* "cast5-ofb" */
+152,	/* "certBag" */
+677,	/* "certicom-arc" */
+517,	/* "certificate extensions" */
+883,	/* "certificateRevocationList" */
+937,	/* "chacha" */
+967,	/* "chacha20-poly1305" */
+54,	/* "challengePassword" */
+407,	/* "characteristic-two-field" */
+395,	/* "clearance" */
+633,	/* "cleartext track 2" */
+894,	/* "cmac" */
+13,	/* "commonName" */
+513,	/* "content types" */
+50,	/* "contentType" */
+53,	/* "countersignature" */
+14,	/* "countryName" */
+153,	/* "crlBag" */
+884,	/* "crossCertificatePair" */
+806,	/* "cryptocom" */
+805,	/* "cryptopro" */
+500,	/* "dITRedirect" */
+451,	/* "dNSDomain" */
+495,	/* "dSAQuality" */
+434,	/* "data" */
+390,	/* "dcObject" */
+891,	/* "deltaRevocationList" */
+31,	/* "des-cbc" */
+643,	/* "des-cdmf" */
+30,	/* "des-cfb" */
+656,	/* "des-cfb1" */
+657,	/* "des-cfb8" */
+29,	/* "des-ecb" */
+32,	/* "des-ede" */
+43,	/* "des-ede-cbc" */
+60,	/* "des-ede-cfb" */
+62,	/* "des-ede-ofb" */
+33,	/* "des-ede3" */
+44,	/* "des-ede3-cbc" */
+61,	/* "des-ede3-cfb" */
+658,	/* "des-ede3-cfb1" */
+659,	/* "des-ede3-cfb8" */
+63,	/* "des-ede3-ofb" */
+45,	/* "des-ofb" */
+107,	/* "description" */
+871,	/* "destinationIndicator" */
+80,	/* "desx-cbc" */
+991,	/* "dh-cofactor-kdf" */
+990,	/* "dh-std-kdf" */
+28,	/* "dhKeyAgreement" */
+985,	/* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
+986,	/* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
+987,	/* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
+988,	/* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
+989,	/* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
+980,	/* "dhSinglePass-stdDH-sha1kdf-scheme" */
+981,	/* "dhSinglePass-stdDH-sha224kdf-scheme" */
+982,	/* "dhSinglePass-stdDH-sha256kdf-scheme" */
+983,	/* "dhSinglePass-stdDH-sha384kdf-scheme" */
+984,	/* "dhSinglePass-stdDH-sha512kdf-scheme" */
+11,	/* "directory services (X.500)" */
+378,	/* "directory services - algorithms" */
+887,	/* "distinguishedName" */
+892,	/* "dmdName" */
+174,	/* "dnQualifier" */
+447,	/* "document" */
+471,	/* "documentAuthor" */
+468,	/* "documentIdentifier" */
+472,	/* "documentLocation" */
+502,	/* "documentPublisher" */
+449,	/* "documentSeries" */
+469,	/* "documentTitle" */
+470,	/* "documentVersion" */
+380,	/* "dod" */
+391,	/* "domainComponent" */
+452,	/* "domainRelatedObject" */
+116,	/* "dsaEncryption" */
+67,	/* "dsaEncryption-old" */
+66,	/* "dsaWithSHA" */
+113,	/* "dsaWithSHA1" */
+70,	/* "dsaWithSHA1-old" */
+802,	/* "dsa_with_SHA224" */
+803,	/* "dsa_with_SHA256" */
+1041,	/* "dsa_with_SHA3-224" */
+1042,	/* "dsa_with_SHA3-256" */
+1043,	/* "dsa_with_SHA3-384" */
+1044,	/* "dsa_with_SHA3-512" */
+1039,	/* "dsa_with_SHA384" */
+1040,	/* "dsa_with_SHA512" */
+297,	/* "dvcs" */
+791,	/* "ecdsa-with-Recommended" */
+416,	/* "ecdsa-with-SHA1" */
+793,	/* "ecdsa-with-SHA224" */
+794,	/* "ecdsa-with-SHA256" */
+795,	/* "ecdsa-with-SHA384" */
+796,	/* "ecdsa-with-SHA512" */
+792,	/* "ecdsa-with-Specified" */
+1045,	/* "ecdsa_with_SHA3-224" */
+1046,	/* "ecdsa_with_SHA3-256" */
+1047,	/* "ecdsa_with_SHA3-384" */
+1048,	/* "ecdsa_with_SHA3-512" */
+48,	/* "emailAddress" */
+632,	/* "encrypted track 2" */
+885,	/* "enhancedSearchGuide" */
+56,	/* "extendedCertificateAttributes" */
+867,	/* "facsimileTelephoneNumber" */
+462,	/* "favouriteDrink" */
+453,	/* "friendlyCountry" */
+490,	/* "friendlyCountryName" */
+156,	/* "friendlyName" */
+631,	/* "generate cryptogram" */
+509,	/* "generationQualifier" */
+601,	/* "generic cryptogram" */
+99,	/* "givenName" */
+939,	/* "gost89-cbc" */
+814,	/* "gost89-cnt" */
+938,	/* "gost89-ecb" */
+1022,	/* "hkdf" */
+855,	/* "hmac" */
+780,	/* "hmac-md5" */
+781,	/* "hmac-sha1" */
+1035,	/* "hmac-sha3-224" */
+1036,	/* "hmac-sha3-256" */
+1037,	/* "hmac-sha3-384" */
+1038,	/* "hmac-sha3-512" */
+797,	/* "hmacWithMD5" */
+163,	/* "hmacWithSHA1" */
+798,	/* "hmacWithSHA224" */
+799,	/* "hmacWithSHA256" */
+800,	/* "hmacWithSHA384" */
+801,	/* "hmacWithSHA512" */
+1027,	/* "hmacWithSHA512-224" */
+1028,	/* "hmacWithSHA512-256" */
+486,	/* "homePostalAddress" */
+473,	/* "homeTelephoneNumber" */
+466,	/* "host" */
+889,	/* "houseIdentifier" */
+442,	/* "iA5StringSyntax" */
+381,	/* "iana" */
+824,	/* "id-Gost28147-89-CryptoPro-A-ParamSet" */
+825,	/* "id-Gost28147-89-CryptoPro-B-ParamSet" */
+826,	/* "id-Gost28147-89-CryptoPro-C-ParamSet" */
+827,	/* "id-Gost28147-89-CryptoPro-D-ParamSet" */
+819,	/* "id-Gost28147-89-CryptoPro-KeyMeshing" */
+829,	/* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
+828,	/* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
+830,	/* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
+820,	/* "id-Gost28147-89-None-KeyMeshing" */
+823,	/* "id-Gost28147-89-TestParamSet" */
+840,	/* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
+841,	/* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
+842,	/* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
+843,	/* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
+844,	/* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
+839,	/* "id-GostR3410-2001-TestParamSet" */
+832,	/* "id-GostR3410-94-CryptoPro-A-ParamSet" */
+833,	/* "id-GostR3410-94-CryptoPro-B-ParamSet" */
+834,	/* "id-GostR3410-94-CryptoPro-C-ParamSet" */
+835,	/* "id-GostR3410-94-CryptoPro-D-ParamSet" */
+836,	/* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
+837,	/* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
+838,	/* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
+831,	/* "id-GostR3410-94-TestParamSet" */
+845,	/* "id-GostR3410-94-a" */
+846,	/* "id-GostR3410-94-aBis" */
+847,	/* "id-GostR3410-94-b" */
+848,	/* "id-GostR3410-94-bBis" */
+822,	/* "id-GostR3411-94-CryptoProParamSet" */
+821,	/* "id-GostR3411-94-TestParamSet" */
+266,	/* "id-aca" */
+355,	/* "id-aca-accessIdentity" */
+354,	/* "id-aca-authenticationInfo" */
+356,	/* "id-aca-chargingIdentity" */
+399,	/* "id-aca-encAttrs" */
+357,	/* "id-aca-group" */
+358,	/* "id-aca-role" */
+176,	/* "id-ad" */
+788,	/* "id-aes128-wrap" */
+897,	/* "id-aes128-wrap-pad" */
+789,	/* "id-aes192-wrap" */
+900,	/* "id-aes192-wrap-pad" */
+790,	/* "id-aes256-wrap" */
+903,	/* "id-aes256-wrap-pad" */
+262,	/* "id-alg" */
+893,	/* "id-alg-PWRI-KEK" */
+323,	/* "id-alg-des40" */
+326,	/* "id-alg-dh-pop" */
+325,	/* "id-alg-dh-sig-hmac-sha1" */
+324,	/* "id-alg-noSignature" */
+907,	/* "id-camellia128-wrap" */
+908,	/* "id-camellia192-wrap" */
+909,	/* "id-camellia256-wrap" */
+268,	/* "id-cct" */
+361,	/* "id-cct-PKIData" */
+362,	/* "id-cct-PKIResponse" */
+360,	/* "id-cct-crs" */
+81,	/* "id-ce" */
+680,	/* "id-characteristic-two-basis" */
+263,	/* "id-cmc" */
+334,	/* "id-cmc-addExtensions" */
+346,	/* "id-cmc-confirmCertAcceptance" */
+330,	/* "id-cmc-dataReturn" */
+336,	/* "id-cmc-decryptedPOP" */
+335,	/* "id-cmc-encryptedPOP" */
+339,	/* "id-cmc-getCRL" */
+338,	/* "id-cmc-getCert" */
+328,	/* "id-cmc-identification" */
+329,	/* "id-cmc-identityProof" */
+337,	/* "id-cmc-lraPOPWitness" */
+344,	/* "id-cmc-popLinkRandom" */
+345,	/* "id-cmc-popLinkWitness" */
+343,	/* "id-cmc-queryPending" */
+333,	/* "id-cmc-recipientNonce" */
+341,	/* "id-cmc-regInfo" */
+342,	/* "id-cmc-responseInfo" */
+340,	/* "id-cmc-revokeRequest" */
+332,	/* "id-cmc-senderNonce" */
+327,	/* "id-cmc-statusInfo" */
+331,	/* "id-cmc-transactionId" */
+1005,	/* "id-cp" */
+1017,	/* "id-ct-ASPA" */
+787,	/* "id-ct-asciiTextWithCRLF" */
+1013,	/* "id-ct-geofeedCSVwithCRLF" */
+1004,	/* "id-ct-resourceTaggedAttest" */
+1001,	/* "id-ct-routeOriginAuthz" */
+1003,	/* "id-ct-rpkiGhostbusters" */
+1002,	/* "id-ct-rpkiManifest" */
+1014,	/* "id-ct-signedChecklist" */
+1024,	/* "id-ct-signedTAL" */
+408,	/* "id-ecPublicKey" */
+508,	/* "id-hex-multipart-message" */
+507,	/* "id-hex-partial-message" */
+260,	/* "id-it" */
+302,	/* "id-it-caKeyUpdateInfo" */
+298,	/* "id-it-caProtEncCert" */
+311,	/* "id-it-confirmWaitTime" */
+303,	/* "id-it-currentCRL" */
+300,	/* "id-it-encKeyPairTypes" */
+310,	/* "id-it-implicitConfirm" */
+308,	/* "id-it-keyPairParamRep" */
+307,	/* "id-it-keyPairParamReq" */
+312,	/* "id-it-origPKIMessage" */
+301,	/* "id-it-preferredSymmAlg" */
+309,	/* "id-it-revPassphrase" */
+299,	/* "id-it-signKeyPairTypes" */
+305,	/* "id-it-subscriptionRequest" */
+306,	/* "id-it-subscriptionResponse" */
+784,	/* "id-it-suppLangTags" */
+304,	/* "id-it-unsupportedOIDs" */
+128,	/* "id-kp" */
+280,	/* "id-mod-attribute-cert" */
+274,	/* "id-mod-cmc" */
+277,	/* "id-mod-cmp" */
+284,	/* "id-mod-cmp2000" */
+273,	/* "id-mod-crmf" */
+283,	/* "id-mod-dvcs" */
+275,	/* "id-mod-kea-profile-88" */
+276,	/* "id-mod-kea-profile-93" */
+282,	/* "id-mod-ocsp" */
+278,	/* "id-mod-qualified-cert-88" */
+279,	/* "id-mod-qualified-cert-93" */
+281,	/* "id-mod-timestamp-protocol" */
+264,	/* "id-on" */
+347,	/* "id-on-personalData" */
+265,	/* "id-pda" */
+352,	/* "id-pda-countryOfCitizenship" */
+353,	/* "id-pda-countryOfResidence" */
+348,	/* "id-pda-dateOfBirth" */
+351,	/* "id-pda-gender" */
+349,	/* "id-pda-placeOfBirth" */
+175,	/* "id-pe" */
+261,	/* "id-pkip" */
+258,	/* "id-pkix-mod" */
+269,	/* "id-pkix1-explicit-88" */
+271,	/* "id-pkix1-explicit-93" */
+270,	/* "id-pkix1-implicit-88" */
+272,	/* "id-pkix1-implicit-93" */
+662,	/* "id-ppl" */
+267,	/* "id-qcs" */
+359,	/* "id-qcs-pkixQCSyntax-v1" */
+259,	/* "id-qt" */
+313,	/* "id-regCtrl" */
+316,	/* "id-regCtrl-authenticator" */
+319,	/* "id-regCtrl-oldCertID" */
+318,	/* "id-regCtrl-pkiArchiveOptions" */
+317,	/* "id-regCtrl-pkiPublicationInfo" */
+320,	/* "id-regCtrl-protocolEncrKey" */
+315,	/* "id-regCtrl-regToken" */
+314,	/* "id-regInfo" */
+322,	/* "id-regInfo-certReq" */
+321,	/* "id-regInfo-utf8Pairs" */
+191,	/* "id-smime-aa" */
+215,	/* "id-smime-aa-contentHint" */
+218,	/* "id-smime-aa-contentIdentifier" */
+221,	/* "id-smime-aa-contentReference" */
+240,	/* "id-smime-aa-dvcs-dvc" */
+217,	/* "id-smime-aa-encapContentType" */
+222,	/* "id-smime-aa-encrypKeyPref" */
+220,	/* "id-smime-aa-equivalentLabels" */
+232,	/* "id-smime-aa-ets-CertificateRefs" */
+233,	/* "id-smime-aa-ets-RevocationRefs" */
+238,	/* "id-smime-aa-ets-archiveTimeStamp" */
+237,	/* "id-smime-aa-ets-certCRLTimestamp" */
+234,	/* "id-smime-aa-ets-certValues" */
+227,	/* "id-smime-aa-ets-commitmentType" */
+231,	/* "id-smime-aa-ets-contentTimestamp" */
+236,	/* "id-smime-aa-ets-escTimeStamp" */
+230,	/* "id-smime-aa-ets-otherSigCert" */
+235,	/* "id-smime-aa-ets-revocationValues" */
+226,	/* "id-smime-aa-ets-sigPolicyId" */
+229,	/* "id-smime-aa-ets-signerAttr" */
+228,	/* "id-smime-aa-ets-signerLocation" */
+219,	/* "id-smime-aa-macValue" */
+214,	/* "id-smime-aa-mlExpandHistory" */
+216,	/* "id-smime-aa-msgSigDigest" */
+212,	/* "id-smime-aa-receiptRequest" */
+213,	/* "id-smime-aa-securityLabel" */
+239,	/* "id-smime-aa-signatureType" */
+223,	/* "id-smime-aa-signingCertificate" */
+1023,	/* "id-smime-aa-signingCertificateV2" */
+224,	/* "id-smime-aa-smimeEncryptCerts" */
+225,	/* "id-smime-aa-timeStampToken" */
+192,	/* "id-smime-alg" */
+243,	/* "id-smime-alg-3DESwrap" */
+246,	/* "id-smime-alg-CMS3DESwrap" */
+247,	/* "id-smime-alg-CMSRC2wrap" */
+245,	/* "id-smime-alg-ESDH" */
+241,	/* "id-smime-alg-ESDHwith3DES" */
+242,	/* "id-smime-alg-ESDHwithRC2" */
+244,	/* "id-smime-alg-RC2wrap" */
+193,	/* "id-smime-cd" */
+248,	/* "id-smime-cd-ldap" */
+190,	/* "id-smime-ct" */
+210,	/* "id-smime-ct-DVCSRequestData" */
+211,	/* "id-smime-ct-DVCSResponseData" */
+208,	/* "id-smime-ct-TDTInfo" */
+207,	/* "id-smime-ct-TSTInfo" */
+205,	/* "id-smime-ct-authData" */
+786,	/* "id-smime-ct-compressedData" */
+209,	/* "id-smime-ct-contentInfo" */
+206,	/* "id-smime-ct-publishCert" */
+204,	/* "id-smime-ct-receipt" */
+195,	/* "id-smime-cti" */
+255,	/* "id-smime-cti-ets-proofOfApproval" */
+256,	/* "id-smime-cti-ets-proofOfCreation" */
+253,	/* "id-smime-cti-ets-proofOfDelivery" */
+251,	/* "id-smime-cti-ets-proofOfOrigin" */
+252,	/* "id-smime-cti-ets-proofOfReceipt" */
+254,	/* "id-smime-cti-ets-proofOfSender" */
+189,	/* "id-smime-mod" */
+196,	/* "id-smime-mod-cms" */
+197,	/* "id-smime-mod-ess" */
+202,	/* "id-smime-mod-ets-eSigPolicy-88" */
+203,	/* "id-smime-mod-ets-eSigPolicy-97" */
+200,	/* "id-smime-mod-ets-eSignature-88" */
+201,	/* "id-smime-mod-ets-eSignature-97" */
+199,	/* "id-smime-mod-msg-v3" */
+198,	/* "id-smime-mod-oid" */
+194,	/* "id-smime-spq" */
+250,	/* "id-smime-spq-ets-sqt-unotice" */
+249,	/* "id-smime-spq-ets-sqt-uri" */
+945,	/* "id-tc26-gost-28147-param-Z" */
+34,	/* "idea-cbc" */
+35,	/* "idea-cfb" */
+36,	/* "idea-ecb" */
+46,	/* "idea-ofb" */
+676,	/* "identified-organization" */
+461,	/* "info" */
+101,	/* "initials" */
+869,	/* "internationaliSDNNumber" */
+1008,	/* "ipAddr-asNumber" */
+1009,	/* "ipAddr-asNumberv2" */
+749,	/* "ipsec3" */
+750,	/* "ipsec4" */
+181,	/* "iso" */
+623,	/* "issuer capabilities" */
+645,	/* "itu-t" */
+492,	/* "janetMailbox" */
+646,	/* "joint-iso-itu-t" */
+958,	/* "jurisdictionCountryName" */
+956,	/* "jurisdictionLocalityName" */
+957,	/* "jurisdictionStateOrProvinceName" */
+150,	/* "keyBag" */
+773,	/* "kisa" */
+961,	/* "kx-dhe" */
+960,	/* "kx-ecdhe" */
+962,	/* "kx-gost" */
+959,	/* "kx-rsa" */
+477,	/* "lastModifiedBy" */
+476,	/* "lastModifiedTime" */
+157,	/* "localKeyID" */
+15,	/* "localityName" */
+480,	/* "mXRecord" */
+493,	/* "mailPreferenceOption" */
+467,	/* "manager" */
+ 3,	/* "md2" */
+ 7,	/* "md2WithRSAEncryption" */
+257,	/* "md4" */
+396,	/* "md4WithRSAEncryption" */
+ 4,	/* "md5" */
+114,	/* "md5-sha1" */
+104,	/* "md5WithRSA" */
+ 8,	/* "md5WithRSAEncryption" */
+95,	/* "mdc2" */
+96,	/* "mdc2WithRSA" */
+875,	/* "member" */
+602,	/* "merchant initiated auth" */
+514,	/* "message extensions" */
+51,	/* "messageDigest" */
+911,	/* "mgf1" */
+506,	/* "mime-mhs-bodies" */
+505,	/* "mime-mhs-headings" */
+488,	/* "mobileTelephoneNumber" */
+481,	/* "nSRecord" */
+173,	/* "name" */
+681,	/* "onBasis" */
+379,	/* "org" */
+17,	/* "organizationName" */
+491,	/* "organizationalStatus" */
+18,	/* "organizationalUnitName" */
+971,	/* "oscca" */
+475,	/* "otherMailbox" */
+876,	/* "owner" */
+992,	/* "pSpecified" */
+489,	/* "pagerTelephoneNumber" */
+782,	/* "password based MAC" */
+374,	/* "path" */
+621,	/* "payment gateway capabilities" */
+ 9,	/* "pbeWithMD2AndDES-CBC" */
+168,	/* "pbeWithMD2AndRC2-CBC" */
+112,	/* "pbeWithMD5AndCast5CBC" */
+10,	/* "pbeWithMD5AndDES-CBC" */
+169,	/* "pbeWithMD5AndRC2-CBC" */
+148,	/* "pbeWithSHA1And128BitRC2-CBC" */
+144,	/* "pbeWithSHA1And128BitRC4" */
+147,	/* "pbeWithSHA1And2-KeyTripleDES-CBC" */
+146,	/* "pbeWithSHA1And3-KeyTripleDES-CBC" */
+149,	/* "pbeWithSHA1And40BitRC2-CBC" */
+145,	/* "pbeWithSHA1And40BitRC4" */
+170,	/* "pbeWithSHA1AndDES-CBC" */
+68,	/* "pbeWithSHA1AndRC2-CBC" */
+499,	/* "personalSignature" */
+487,	/* "personalTitle" */
+464,	/* "photo" */
+863,	/* "physicalDeliveryOfficeName" */
+437,	/* "pilot" */
+439,	/* "pilotAttributeSyntax" */
+438,	/* "pilotAttributeType" */
+479,	/* "pilotAttributeType27" */
+456,	/* "pilotDSA" */
+441,	/* "pilotGroups" */
+444,	/* "pilotObject" */
+440,	/* "pilotObjectClass" */
+455,	/* "pilotOrganization" */
+445,	/* "pilotPerson" */
+186,	/* "pkcs1" */
+27,	/* "pkcs3" */
+187,	/* "pkcs5" */
+20,	/* "pkcs7" */
+21,	/* "pkcs7-data" */
+25,	/* "pkcs7-digestData" */
+26,	/* "pkcs7-encryptedData" */
+23,	/* "pkcs7-envelopedData" */
+24,	/* "pkcs7-signedAndEnvelopedData" */
+22,	/* "pkcs7-signedData" */
+151,	/* "pkcs8ShroudedKeyBag" */
+47,	/* "pkcs9" */
+862,	/* "postOfficeBox" */
+861,	/* "postalAddress" */
+661,	/* "postalCode" */
+683,	/* "ppBasis" */
+872,	/* "preferredDeliveryMethod" */
+873,	/* "presentationAddress" */
+406,	/* "prime-field" */
+409,	/* "prime192v1" */
+410,	/* "prime192v2" */
+411,	/* "prime192v3" */
+412,	/* "prime239v1" */
+413,	/* "prime239v2" */
+414,	/* "prime239v3" */
+415,	/* "prime256v1" */
+886,	/* "protocolInformation" */
+510,	/* "pseudonym" */
+435,	/* "pss" */
+286,	/* "qcStatements" */
+457,	/* "qualityLabelledData" */
+450,	/* "rFC822localPart" */
+98,	/* "rc2-40-cbc" */
+166,	/* "rc2-64-cbc" */
+37,	/* "rc2-cbc" */
+39,	/* "rc2-cfb" */
+38,	/* "rc2-ecb" */
+40,	/* "rc2-ofb" */
+ 5,	/* "rc4" */
+97,	/* "rc4-40" */
+915,	/* "rc4-hmac-md5" */
+120,	/* "rc5-cbc" */
+122,	/* "rc5-cfb" */
+121,	/* "rc5-ecb" */
+123,	/* "rc5-ofb" */
+870,	/* "registeredAddress" */
+460,	/* "rfc822Mailbox" */
+117,	/* "ripemd160" */
+119,	/* "ripemd160WithRSA" */
+400,	/* "role" */
+877,	/* "roleOccupant" */
+448,	/* "room" */
+463,	/* "roomNumber" */
+19,	/* "rsa" */
+ 6,	/* "rsaEncryption" */
+644,	/* "rsaOAEPEncryptionSET" */
+377,	/* "rsaSignature" */
+919,	/* "rsaesOaep" */
+912,	/* "rsassaPss" */
+124,	/* "run length compression" */
+482,	/* "sOARecord" */
+155,	/* "safeContentsBag" */
+291,	/* "sbgp-autonomousSysNum" */
+1007,	/* "sbgp-autonomousSysNumv2" */
+290,	/* "sbgp-ipAddrBlock" */
+1006,	/* "sbgp-ipAddrBlockv2" */
+292,	/* "sbgp-routerIdentifier" */
+159,	/* "sdsiCertificate" */
+859,	/* "searchGuide" */
+704,	/* "secp112r1" */
+705,	/* "secp112r2" */
+706,	/* "secp128r1" */
+707,	/* "secp128r2" */
+708,	/* "secp160k1" */
+709,	/* "secp160r1" */
+710,	/* "secp160r2" */
+711,	/* "secp192k1" */
+712,	/* "secp224k1" */
+713,	/* "secp224r1" */
+714,	/* "secp256k1" */
+715,	/* "secp384r1" */
+716,	/* "secp521r1" */
+154,	/* "secretBag" */
+474,	/* "secretary" */
+717,	/* "sect113r1" */
+718,	/* "sect113r2" */
+719,	/* "sect131r1" */
+720,	/* "sect131r2" */
+721,	/* "sect163k1" */
+722,	/* "sect163r1" */
+723,	/* "sect163r2" */
+724,	/* "sect193r1" */
+725,	/* "sect193r2" */
+726,	/* "sect233k1" */
+727,	/* "sect233r1" */
+728,	/* "sect239k1" */
+729,	/* "sect283k1" */
+730,	/* "sect283r1" */
+731,	/* "sect409k1" */
+732,	/* "sect409r1" */
+733,	/* "sect571k1" */
+734,	/* "sect571r1" */
+635,	/* "secure device signature" */
+878,	/* "seeAlso" */
+777,	/* "seed-cbc" */
+779,	/* "seed-cfb" */
+776,	/* "seed-ecb" */
+778,	/* "seed-ofb" */
+105,	/* "serialNumber" */
+625,	/* "set-addPolicy" */
+515,	/* "set-attr" */
+518,	/* "set-brand" */
+638,	/* "set-brand-AmericanExpress" */
+637,	/* "set-brand-Diners" */
+636,	/* "set-brand-IATA-ATA" */
+639,	/* "set-brand-JCB" */
+641,	/* "set-brand-MasterCard" */
+642,	/* "set-brand-Novus" */
+640,	/* "set-brand-Visa" */
+516,	/* "set-policy" */
+607,	/* "set-policy-root" */
+624,	/* "set-rootKeyThumb" */
+620,	/* "setAttr-Cert" */
+628,	/* "setAttr-IssCap-CVM" */
+630,	/* "setAttr-IssCap-Sig" */
+629,	/* "setAttr-IssCap-T2" */
+627,	/* "setAttr-Token-B0Prime" */
+626,	/* "setAttr-Token-EMV" */
+622,	/* "setAttr-TokenType" */
+619,	/* "setCext-IssuerCapabilities" */
+615,	/* "setCext-PGWYcapabilities" */
+616,	/* "setCext-TokenIdentifier" */
+618,	/* "setCext-TokenType" */
+617,	/* "setCext-Track2Data" */
+611,	/* "setCext-cCertRequired" */
+609,	/* "setCext-certType" */
+608,	/* "setCext-hashedRoot" */
+610,	/* "setCext-merchData" */
+613,	/* "setCext-setExt" */
+614,	/* "setCext-setQualf" */
+612,	/* "setCext-tunneling" */
+540,	/* "setct-AcqCardCodeMsg" */
+576,	/* "setct-AcqCardCodeMsgTBE" */
+570,	/* "setct-AuthReqTBE" */
+534,	/* "setct-AuthReqTBS" */
+527,	/* "setct-AuthResBaggage" */
+571,	/* "setct-AuthResTBE" */
+572,	/* "setct-AuthResTBEX" */
+535,	/* "setct-AuthResTBS" */
+536,	/* "setct-AuthResTBSX" */
+528,	/* "setct-AuthRevReqBaggage" */
+577,	/* "setct-AuthRevReqTBE" */
+541,	/* "setct-AuthRevReqTBS" */
+529,	/* "setct-AuthRevResBaggage" */
+542,	/* "setct-AuthRevResData" */
+578,	/* "setct-AuthRevResTBE" */
+579,	/* "setct-AuthRevResTBEB" */
+543,	/* "setct-AuthRevResTBS" */
+573,	/* "setct-AuthTokenTBE" */
+537,	/* "setct-AuthTokenTBS" */
+600,	/* "setct-BCIDistributionTBS" */
+558,	/* "setct-BatchAdminReqData" */
+592,	/* "setct-BatchAdminReqTBE" */
+559,	/* "setct-BatchAdminResData" */
+593,	/* "setct-BatchAdminResTBE" */
+599,	/* "setct-CRLNotificationResTBS" */
+598,	/* "setct-CRLNotificationTBS" */
+580,	/* "setct-CapReqTBE" */
+581,	/* "setct-CapReqTBEX" */
+544,	/* "setct-CapReqTBS" */
+545,	/* "setct-CapReqTBSX" */
+546,	/* "setct-CapResData" */
+582,	/* "setct-CapResTBE" */
+583,	/* "setct-CapRevReqTBE" */
+584,	/* "setct-CapRevReqTBEX" */
+547,	/* "setct-CapRevReqTBS" */
+548,	/* "setct-CapRevReqTBSX" */
+549,	/* "setct-CapRevResData" */
+585,	/* "setct-CapRevResTBE" */
+538,	/* "setct-CapTokenData" */
+530,	/* "setct-CapTokenSeq" */
+574,	/* "setct-CapTokenTBE" */
+575,	/* "setct-CapTokenTBEX" */
+539,	/* "setct-CapTokenTBS" */
+560,	/* "setct-CardCInitResTBS" */
+566,	/* "setct-CertInqReqTBS" */
+563,	/* "setct-CertReqData" */
+595,	/* "setct-CertReqTBE" */
+596,	/* "setct-CertReqTBEX" */
+564,	/* "setct-CertReqTBS" */
+565,	/* "setct-CertResData" */
+597,	/* "setct-CertResTBE" */
+586,	/* "setct-CredReqTBE" */
+587,	/* "setct-CredReqTBEX" */
+550,	/* "setct-CredReqTBS" */
+551,	/* "setct-CredReqTBSX" */
+552,	/* "setct-CredResData" */
+588,	/* "setct-CredResTBE" */
+589,	/* "setct-CredRevReqTBE" */
+590,	/* "setct-CredRevReqTBEX" */
+553,	/* "setct-CredRevReqTBS" */
+554,	/* "setct-CredRevReqTBSX" */
+555,	/* "setct-CredRevResData" */
+591,	/* "setct-CredRevResTBE" */
+567,	/* "setct-ErrorTBS" */
+526,	/* "setct-HODInput" */
+561,	/* "setct-MeAqCInitResTBS" */
+522,	/* "setct-OIData" */
+519,	/* "setct-PANData" */
+521,	/* "setct-PANOnly" */
+520,	/* "setct-PANToken" */
+556,	/* "setct-PCertReqData" */
+557,	/* "setct-PCertResTBS" */
+523,	/* "setct-PI" */
+532,	/* "setct-PI-TBS" */
+524,	/* "setct-PIData" */
+525,	/* "setct-PIDataUnsigned" */
+568,	/* "setct-PIDualSignedTBE" */
+569,	/* "setct-PIUnsignedTBE" */
+531,	/* "setct-PInitResData" */
+533,	/* "setct-PResData" */
+594,	/* "setct-RegFormReqTBE" */
+562,	/* "setct-RegFormResTBS" */
+604,	/* "setext-pinAny" */
+603,	/* "setext-pinSecure" */
+605,	/* "setext-track2" */
+41,	/* "sha" */
+64,	/* "sha1" */
+115,	/* "sha1WithRSA" */
+65,	/* "sha1WithRSAEncryption" */
+675,	/* "sha224" */
+671,	/* "sha224WithRSAEncryption" */
+672,	/* "sha256" */
+668,	/* "sha256WithRSAEncryption" */
+1031,	/* "sha3-224" */
+1032,	/* "sha3-256" */
+1033,	/* "sha3-384" */
+1034,	/* "sha3-512" */
+673,	/* "sha384" */
+669,	/* "sha384WithRSAEncryption" */
+674,	/* "sha512" */
+1029,	/* "sha512-224" */
+1025,	/* "sha512-224WithRSAEncryption" */
+1030,	/* "sha512-256" */
+1026,	/* "sha512-256WithRSAEncryption" */
+670,	/* "sha512WithRSAEncryption" */
+42,	/* "shaWithRSAEncryption" */
+52,	/* "signingTime" */
+454,	/* "simpleSecurityObject" */
+496,	/* "singleLevelQuality" */
+972,	/* "sm-scheme" */
+968,	/* "sm3" */
+969,	/* "sm3WithRSAEncryption" */
+974,	/* "sm4-cbc" */
+976,	/* "sm4-cfb" */
+977,	/* "sm4-cfb1" */
+978,	/* "sm4-cfb8" */
+979,	/* "sm4-ctr" */
+973,	/* "sm4-ecb" */
+975,	/* "sm4-ofb" */
+16,	/* "stateOrProvinceName" */
+660,	/* "streetAddress" */
+498,	/* "subtreeMaximumQuality" */
+497,	/* "subtreeMinimumQuality" */
+890,	/* "supportedAlgorithms" */
+874,	/* "supportedApplicationContext" */
+100,	/* "surname" */
+940,	/* "tc26" */
+864,	/* "telephoneNumber" */
+866,	/* "teletexTerminalIdentifier" */
+920,	/* "teletrust" */
+865,	/* "telexNumber" */
+459,	/* "textEncodedORAddress" */
+293,	/* "textNotice" */
+106,	/* "title" */
+682,	/* "tpBasis" */
+436,	/* "ucl" */
+ 0,	/* "undefined" */
+888,	/* "uniqueMember" */
+55,	/* "unstructuredAddress" */
+49,	/* "unstructuredName" */
+880,	/* "userCertificate" */
+465,	/* "userClass" */
+458,	/* "userId" */
+879,	/* "userPassword" */
+373,	/* "valid" */
+678,	/* "wap" */
+679,	/* "wap-wsg" */
+735,	/* "wap-wsg-idm-ecid-wtls1" */
+743,	/* "wap-wsg-idm-ecid-wtls10" */
+744,	/* "wap-wsg-idm-ecid-wtls11" */
+745,	/* "wap-wsg-idm-ecid-wtls12" */
+736,	/* "wap-wsg-idm-ecid-wtls3" */
+737,	/* "wap-wsg-idm-ecid-wtls4" */
+738,	/* "wap-wsg-idm-ecid-wtls5" */
+739,	/* "wap-wsg-idm-ecid-wtls6" */
+740,	/* "wap-wsg-idm-ecid-wtls7" */
+741,	/* "wap-wsg-idm-ecid-wtls8" */
+742,	/* "wap-wsg-idm-ecid-wtls9" */
+804,	/* "whirlpool" */
+868,	/* "x121Address" */
+503,	/* "x500UniqueIdentifier" */
+158,	/* "x509Certificate" */
+160,	/* "x509Crl" */
+125,	/* "zlib compression" */
+};
+
+static const unsigned int obj_objs[NUM_OBJ]={
+ 0,	/* OBJ_undef                        0 */
+181,	/* OBJ_iso                          1 */
+393,	/* OBJ_joint_iso_ccitt              OBJ_joint_iso_itu_t */
+404,	/* OBJ_ccitt                        OBJ_itu_t */
+645,	/* OBJ_itu_t                        0 */
+646,	/* OBJ_joint_iso_itu_t              2 */
+434,	/* OBJ_data                         0 9 */
+182,	/* OBJ_member_body                  1 2 */
+379,	/* OBJ_org                          1 3 */
+676,	/* OBJ_identified_organization      1 3 */
+11,	/* OBJ_X500                         2 5 */
+647,	/* OBJ_international_organizations  2 23 */
+380,	/* OBJ_dod                          1 3 6 */
+920,	/* OBJ_teletrust                    1 3 36 */
+12,	/* OBJ_X509                         2 5 4 */
+378,	/* OBJ_X500algorithms               2 5 8 */
+81,	/* OBJ_id_ce                        2 5 29 */
+512,	/* OBJ_id_set                       2 23 42 */
+678,	/* OBJ_wap                          2 23 43 */
+435,	/* OBJ_pss                          0 9 2342 */
+970,	/* OBJ_ISO_CN                       1 2 156 */
+183,	/* OBJ_ISO_US                       1 2 840 */
+381,	/* OBJ_iana                         1 3 6 1 */
+950,	/* OBJ_X25519                       1 3 101 110 */
+951,	/* OBJ_X448                         1 3 101 111 */
+952,	/* OBJ_Ed25519                      1 3 101 112 */
+953,	/* OBJ_Ed448                        1 3 101 113 */
+954,	/* OBJ_Ed25519ph                    1 3 101 114 */
+955,	/* OBJ_Ed448ph                      1 3 101 115 */
+677,	/* OBJ_certicom_arc                 1 3 132 */
+394,	/* OBJ_selected_attribute_types     2 5 1 5 */
+13,	/* OBJ_commonName                   2 5 4 3 */
+100,	/* OBJ_surname                      2 5 4 4 */
+105,	/* OBJ_serialNumber                 2 5 4 5 */
+14,	/* OBJ_countryName                  2 5 4 6 */
+15,	/* OBJ_localityName                 2 5 4 7 */
+16,	/* OBJ_stateOrProvinceName          2 5 4 8 */
+660,	/* OBJ_streetAddress                2 5 4 9 */
+17,	/* OBJ_organizationName             2 5 4 10 */
+18,	/* OBJ_organizationalUnitName       2 5 4 11 */
+106,	/* OBJ_title                        2 5 4 12 */
+107,	/* OBJ_description                  2 5 4 13 */
+859,	/* OBJ_searchGuide                  2 5 4 14 */
+860,	/* OBJ_businessCategory             2 5 4 15 */
+861,	/* OBJ_postalAddress                2 5 4 16 */
+661,	/* OBJ_postalCode                   2 5 4 17 */
+862,	/* OBJ_postOfficeBox                2 5 4 18 */
+863,	/* OBJ_physicalDeliveryOfficeName   2 5 4 19 */
+864,	/* OBJ_telephoneNumber              2 5 4 20 */
+865,	/* OBJ_telexNumber                  2 5 4 21 */
+866,	/* OBJ_teletexTerminalIdentifier    2 5 4 22 */
+867,	/* OBJ_facsimileTelephoneNumber     2 5 4 23 */
+868,	/* OBJ_x121Address                  2 5 4 24 */
+869,	/* OBJ_internationaliSDNNumber      2 5 4 25 */
+870,	/* OBJ_registeredAddress            2 5 4 26 */
+871,	/* OBJ_destinationIndicator         2 5 4 27 */
+872,	/* OBJ_preferredDeliveryMethod      2 5 4 28 */
+873,	/* OBJ_presentationAddress          2 5 4 29 */
+874,	/* OBJ_supportedApplicationContext  2 5 4 30 */
+875,	/* OBJ_member                       2 5 4 31 */
+876,	/* OBJ_owner                        2 5 4 32 */
+877,	/* OBJ_roleOccupant                 2 5 4 33 */
+878,	/* OBJ_seeAlso                      2 5 4 34 */
+879,	/* OBJ_userPassword                 2 5 4 35 */
+880,	/* OBJ_userCertificate              2 5 4 36 */
+881,	/* OBJ_cACertificate                2 5 4 37 */
+882,	/* OBJ_authorityRevocationList      2 5 4 38 */
+883,	/* OBJ_certificateRevocationList    2 5 4 39 */
+884,	/* OBJ_crossCertificatePair         2 5 4 40 */
+173,	/* OBJ_name                         2 5 4 41 */
+99,	/* OBJ_givenName                    2 5 4 42 */
+101,	/* OBJ_initials                     2 5 4 43 */
+509,	/* OBJ_generationQualifier          2 5 4 44 */
+503,	/* OBJ_x500UniqueIdentifier         2 5 4 45 */
+174,	/* OBJ_dnQualifier                  2 5 4 46 */
+885,	/* OBJ_enhancedSearchGuide          2 5 4 47 */
+886,	/* OBJ_protocolInformation          2 5 4 48 */
+887,	/* OBJ_distinguishedName            2 5 4 49 */
+888,	/* OBJ_uniqueMember                 2 5 4 50 */
+889,	/* OBJ_houseIdentifier              2 5 4 51 */
+890,	/* OBJ_supportedAlgorithms          2 5 4 52 */
+891,	/* OBJ_deltaRevocationList          2 5 4 53 */
+892,	/* OBJ_dmdName                      2 5 4 54 */
+510,	/* OBJ_pseudonym                    2 5 4 65 */
+400,	/* OBJ_role                         2 5 4 72 */
+769,	/* OBJ_subject_directory_attributes 2 5 29 9 */
+82,	/* OBJ_subject_key_identifier       2 5 29 14 */
+83,	/* OBJ_key_usage                    2 5 29 15 */
+84,	/* OBJ_private_key_usage_period     2 5 29 16 */
+85,	/* OBJ_subject_alt_name             2 5 29 17 */
+86,	/* OBJ_issuer_alt_name              2 5 29 18 */
+87,	/* OBJ_basic_constraints            2 5 29 19 */
+88,	/* OBJ_crl_number                   2 5 29 20 */
+141,	/* OBJ_crl_reason                   2 5 29 21 */
+430,	/* OBJ_hold_instruction_code        2 5 29 23 */
+142,	/* OBJ_invalidity_date              2 5 29 24 */
+140,	/* OBJ_delta_crl                    2 5 29 27 */
+770,	/* OBJ_issuing_distribution_point   2 5 29 28 */
+771,	/* OBJ_certificate_issuer           2 5 29 29 */
+666,	/* OBJ_name_constraints             2 5 29 30 */
+103,	/* OBJ_crl_distribution_points      2 5 29 31 */
+89,	/* OBJ_certificate_policies         2 5 29 32 */
+747,	/* OBJ_policy_mappings              2 5 29 33 */
+90,	/* OBJ_authority_key_identifier     2 5 29 35 */
+401,	/* OBJ_policy_constraints           2 5 29 36 */
+126,	/* OBJ_ext_key_usage                2 5 29 37 */
+857,	/* OBJ_freshest_crl                 2 5 29 46 */
+748,	/* OBJ_inhibit_any_policy           2 5 29 54 */
+402,	/* OBJ_target_information           2 5 29 55 */
+403,	/* OBJ_no_rev_avail                 2 5 29 56 */
+513,	/* OBJ_set_ctype                    2 23 42 0 */
+514,	/* OBJ_set_msgExt                   2 23 42 1 */
+515,	/* OBJ_set_attr                     2 23 42 3 */
+516,	/* OBJ_set_policy                   2 23 42 5 */
+517,	/* OBJ_set_certExt                  2 23 42 7 */
+518,	/* OBJ_set_brand                    2 23 42 8 */
+679,	/* OBJ_wap_wsg                      2 23 43 1 */
+382,	/* OBJ_Directory                    1 3 6 1 1 */
+383,	/* OBJ_Management                   1 3 6 1 2 */
+384,	/* OBJ_Experimental                 1 3 6 1 3 */
+385,	/* OBJ_Private                      1 3 6 1 4 */
+386,	/* OBJ_Security                     1 3 6 1 5 */
+387,	/* OBJ_SNMPv2                       1 3 6 1 6 */
+388,	/* OBJ_Mail                         1 3 6 1 7 */
+376,	/* OBJ_algorithm                    1 3 14 3 2 */
+395,	/* OBJ_clearance                    2 5 1 5 55 */
+19,	/* OBJ_rsa                          2 5 8 1 1 */
+96,	/* OBJ_mdc2WithRSA                  2 5 8 3 100 */
+95,	/* OBJ_mdc2                         2 5 8 3 101 */
+746,	/* OBJ_any_policy                   2 5 29 32 0 */
+910,	/* OBJ_anyExtendedKeyUsage          2 5 29 37 0 */
+519,	/* OBJ_setct_PANData                2 23 42 0 0 */
+520,	/* OBJ_setct_PANToken               2 23 42 0 1 */
+521,	/* OBJ_setct_PANOnly                2 23 42 0 2 */
+522,	/* OBJ_setct_OIData                 2 23 42 0 3 */
+523,	/* OBJ_setct_PI                     2 23 42 0 4 */
+524,	/* OBJ_setct_PIData                 2 23 42 0 5 */
+525,	/* OBJ_setct_PIDataUnsigned         2 23 42 0 6 */
+526,	/* OBJ_setct_HODInput               2 23 42 0 7 */
+527,	/* OBJ_setct_AuthResBaggage         2 23 42 0 8 */
+528,	/* OBJ_setct_AuthRevReqBaggage      2 23 42 0 9 */
+529,	/* OBJ_setct_AuthRevResBaggage      2 23 42 0 10 */
+530,	/* OBJ_setct_CapTokenSeq            2 23 42 0 11 */
+531,	/* OBJ_setct_PInitResData           2 23 42 0 12 */
+532,	/* OBJ_setct_PI_TBS                 2 23 42 0 13 */
+533,	/* OBJ_setct_PResData               2 23 42 0 14 */
+534,	/* OBJ_setct_AuthReqTBS             2 23 42 0 16 */
+535,	/* OBJ_setct_AuthResTBS             2 23 42 0 17 */
+536,	/* OBJ_setct_AuthResTBSX            2 23 42 0 18 */
+537,	/* OBJ_setct_AuthTokenTBS           2 23 42 0 19 */
+538,	/* OBJ_setct_CapTokenData           2 23 42 0 20 */
+539,	/* OBJ_setct_CapTokenTBS            2 23 42 0 21 */
+540,	/* OBJ_setct_AcqCardCodeMsg         2 23 42 0 22 */
+541,	/* OBJ_setct_AuthRevReqTBS          2 23 42 0 23 */
+542,	/* OBJ_setct_AuthRevResData         2 23 42 0 24 */
+543,	/* OBJ_setct_AuthRevResTBS          2 23 42 0 25 */
+544,	/* OBJ_setct_CapReqTBS              2 23 42 0 26 */
+545,	/* OBJ_setct_CapReqTBSX             2 23 42 0 27 */
+546,	/* OBJ_setct_CapResData             2 23 42 0 28 */
+547,	/* OBJ_setct_CapRevReqTBS           2 23 42 0 29 */
+548,	/* OBJ_setct_CapRevReqTBSX          2 23 42 0 30 */
+549,	/* OBJ_setct_CapRevResData          2 23 42 0 31 */
+550,	/* OBJ_setct_CredReqTBS             2 23 42 0 32 */
+551,	/* OBJ_setct_CredReqTBSX            2 23 42 0 33 */
+552,	/* OBJ_setct_CredResData            2 23 42 0 34 */
+553,	/* OBJ_setct_CredRevReqTBS          2 23 42 0 35 */
+554,	/* OBJ_setct_CredRevReqTBSX         2 23 42 0 36 */
+555,	/* OBJ_setct_CredRevResData         2 23 42 0 37 */
+556,	/* OBJ_setct_PCertReqData           2 23 42 0 38 */
+557,	/* OBJ_setct_PCertResTBS            2 23 42 0 39 */
+558,	/* OBJ_setct_BatchAdminReqData      2 23 42 0 40 */
+559,	/* OBJ_setct_BatchAdminResData      2 23 42 0 41 */
+560,	/* OBJ_setct_CardCInitResTBS        2 23 42 0 42 */
+561,	/* OBJ_setct_MeAqCInitResTBS        2 23 42 0 43 */
+562,	/* OBJ_setct_RegFormResTBS          2 23 42 0 44 */
+563,	/* OBJ_setct_CertReqData            2 23 42 0 45 */
+564,	/* OBJ_setct_CertReqTBS             2 23 42 0 46 */
+565,	/* OBJ_setct_CertResData            2 23 42 0 47 */
+566,	/* OBJ_setct_CertInqReqTBS          2 23 42 0 48 */
+567,	/* OBJ_setct_ErrorTBS               2 23 42 0 49 */
+568,	/* OBJ_setct_PIDualSignedTBE        2 23 42 0 50 */
+569,	/* OBJ_setct_PIUnsignedTBE          2 23 42 0 51 */
+570,	/* OBJ_setct_AuthReqTBE             2 23 42 0 52 */
+571,	/* OBJ_setct_AuthResTBE             2 23 42 0 53 */
+572,	/* OBJ_setct_AuthResTBEX            2 23 42 0 54 */
+573,	/* OBJ_setct_AuthTokenTBE           2 23 42 0 55 */
+574,	/* OBJ_setct_CapTokenTBE            2 23 42 0 56 */
+575,	/* OBJ_setct_CapTokenTBEX           2 23 42 0 57 */
+576,	/* OBJ_setct_AcqCardCodeMsgTBE      2 23 42 0 58 */
+577,	/* OBJ_setct_AuthRevReqTBE          2 23 42 0 59 */
+578,	/* OBJ_setct_AuthRevResTBE          2 23 42 0 60 */
+579,	/* OBJ_setct_AuthRevResTBEB         2 23 42 0 61 */
+580,	/* OBJ_setct_CapReqTBE              2 23 42 0 62 */
+581,	/* OBJ_setct_CapReqTBEX             2 23 42 0 63 */
+582,	/* OBJ_setct_CapResTBE              2 23 42 0 64 */
+583,	/* OBJ_setct_CapRevReqTBE           2 23 42 0 65 */
+584,	/* OBJ_setct_CapRevReqTBEX          2 23 42 0 66 */
+585,	/* OBJ_setct_CapRevResTBE           2 23 42 0 67 */
+586,	/* OBJ_setct_CredReqTBE             2 23 42 0 68 */
+587,	/* OBJ_setct_CredReqTBEX            2 23 42 0 69 */
+588,	/* OBJ_setct_CredResTBE             2 23 42 0 70 */
+589,	/* OBJ_setct_CredRevReqTBE          2 23 42 0 71 */
+590,	/* OBJ_setct_CredRevReqTBEX         2 23 42 0 72 */
+591,	/* OBJ_setct_CredRevResTBE          2 23 42 0 73 */
+592,	/* OBJ_setct_BatchAdminReqTBE       2 23 42 0 74 */
+593,	/* OBJ_setct_BatchAdminResTBE       2 23 42 0 75 */
+594,	/* OBJ_setct_RegFormReqTBE          2 23 42 0 76 */
+595,	/* OBJ_setct_CertReqTBE             2 23 42 0 77 */
+596,	/* OBJ_setct_CertReqTBEX            2 23 42 0 78 */
+597,	/* OBJ_setct_CertResTBE             2 23 42 0 79 */
+598,	/* OBJ_setct_CRLNotificationTBS     2 23 42 0 80 */
+599,	/* OBJ_setct_CRLNotificationResTBS  2 23 42 0 81 */
+600,	/* OBJ_setct_BCIDistributionTBS     2 23 42 0 82 */
+601,	/* OBJ_setext_genCrypt              2 23 42 1 1 */
+602,	/* OBJ_setext_miAuth                2 23 42 1 3 */
+603,	/* OBJ_setext_pinSecure             2 23 42 1 4 */
+604,	/* OBJ_setext_pinAny                2 23 42 1 5 */
+605,	/* OBJ_setext_track2                2 23 42 1 7 */
+606,	/* OBJ_setext_cv                    2 23 42 1 8 */
+620,	/* OBJ_setAttr_Cert                 2 23 42 3 0 */
+621,	/* OBJ_setAttr_PGWYcap              2 23 42 3 1 */
+622,	/* OBJ_setAttr_TokenType            2 23 42 3 2 */
+623,	/* OBJ_setAttr_IssCap               2 23 42 3 3 */
+607,	/* OBJ_set_policy_root              2 23 42 5 0 */
+608,	/* OBJ_setCext_hashedRoot           2 23 42 7 0 */
+609,	/* OBJ_setCext_certType             2 23 42 7 1 */
+610,	/* OBJ_setCext_merchData            2 23 42 7 2 */
+611,	/* OBJ_setCext_cCertRequired        2 23 42 7 3 */
+612,	/* OBJ_setCext_tunneling            2 23 42 7 4 */
+613,	/* OBJ_setCext_setExt               2 23 42 7 5 */
+614,	/* OBJ_setCext_setQualf             2 23 42 7 6 */
+615,	/* OBJ_setCext_PGWYcapabilities     2 23 42 7 7 */
+616,	/* OBJ_setCext_TokenIdentifier      2 23 42 7 8 */
+617,	/* OBJ_setCext_Track2Data           2 23 42 7 9 */
+618,	/* OBJ_setCext_TokenType            2 23 42 7 10 */
+619,	/* OBJ_setCext_IssuerCapabilities   2 23 42 7 11 */
+636,	/* OBJ_set_brand_IATA_ATA           2 23 42 8 1 */
+640,	/* OBJ_set_brand_Visa               2 23 42 8 4 */
+641,	/* OBJ_set_brand_MasterCard         2 23 42 8 5 */
+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 */
+971,	/* OBJ_oscca                        1 2 156 10197 */
+805,	/* OBJ_cryptopro                    1 2 643 2 2 */
+806,	/* OBJ_cryptocom                    1 2 643 2 9 */
+940,	/* OBJ_tc26                         1 2 643 7 1 */
+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 */
+504,	/* OBJ_mime_mhs                     1 3 6 1 7 1 */
+104,	/* OBJ_md5WithRSA                   1 3 14 3 2 3 */
+29,	/* OBJ_des_ecb                      1 3 14 3 2 6 */
+31,	/* OBJ_des_cbc                      1 3 14 3 2 7 */
+45,	/* OBJ_des_ofb64                    1 3 14 3 2 8 */
+30,	/* OBJ_des_cfb64                    1 3 14 3 2 9 */
+377,	/* OBJ_rsaSignature                 1 3 14 3 2 11 */
+67,	/* OBJ_dsa_2                        1 3 14 3 2 12 */
+66,	/* OBJ_dsaWithSHA                   1 3 14 3 2 13 */
+42,	/* OBJ_shaWithRSAEncryption         1 3 14 3 2 15 */
+32,	/* OBJ_des_ede_ecb                  1 3 14 3 2 17 */
+41,	/* OBJ_sha                          1 3 14 3 2 18 */
+64,	/* OBJ_sha1                         1 3 14 3 2 26 */
+70,	/* OBJ_dsaWithSHA1_2                1 3 14 3 2 27 */
+115,	/* OBJ_sha1WithRSA                  1 3 14 3 2 29 */
+117,	/* OBJ_ripemd160                    1 3 36 3 2 1 */
+143,	/* OBJ_sxnet                        1 3 101 1 4 1 */
+721,	/* OBJ_sect163k1                    1 3 132 0 1 */
+722,	/* OBJ_sect163r1                    1 3 132 0 2 */
+728,	/* OBJ_sect239k1                    1 3 132 0 3 */
+717,	/* OBJ_sect113r1                    1 3 132 0 4 */
+718,	/* OBJ_sect113r2                    1 3 132 0 5 */
+704,	/* OBJ_secp112r1                    1 3 132 0 6 */
+705,	/* OBJ_secp112r2                    1 3 132 0 7 */
+709,	/* OBJ_secp160r1                    1 3 132 0 8 */
+708,	/* OBJ_secp160k1                    1 3 132 0 9 */
+714,	/* OBJ_secp256k1                    1 3 132 0 10 */
+723,	/* OBJ_sect163r2                    1 3 132 0 15 */
+729,	/* OBJ_sect283k1                    1 3 132 0 16 */
+730,	/* OBJ_sect283r1                    1 3 132 0 17 */
+719,	/* OBJ_sect131r1                    1 3 132 0 22 */
+720,	/* OBJ_sect131r2                    1 3 132 0 23 */
+724,	/* OBJ_sect193r1                    1 3 132 0 24 */
+725,	/* OBJ_sect193r2                    1 3 132 0 25 */
+726,	/* OBJ_sect233k1                    1 3 132 0 26 */
+727,	/* OBJ_sect233r1                    1 3 132 0 27 */
+706,	/* OBJ_secp128r1                    1 3 132 0 28 */
+707,	/* OBJ_secp128r2                    1 3 132 0 29 */
+710,	/* OBJ_secp160r2                    1 3 132 0 30 */
+711,	/* OBJ_secp192k1                    1 3 132 0 31 */
+712,	/* OBJ_secp224k1                    1 3 132 0 32 */
+713,	/* OBJ_secp224r1                    1 3 132 0 33 */
+715,	/* OBJ_secp384r1                    1 3 132 0 34 */
+716,	/* OBJ_secp521r1                    1 3 132 0 35 */
+731,	/* OBJ_sect409k1                    1 3 132 0 36 */
+732,	/* OBJ_sect409r1                    1 3 132 0 37 */
+733,	/* OBJ_sect571k1                    1 3 132 0 38 */
+734,	/* OBJ_sect571r1                    1 3 132 0 39 */
+624,	/* OBJ_set_rootKeyThumb             2 23 42 3 0 0 */
+625,	/* OBJ_set_addPolicy                2 23 42 3 0 1 */
+626,	/* OBJ_setAttr_Token_EMV            2 23 42 3 2 1 */
+627,	/* OBJ_setAttr_Token_B0Prime        2 23 42 3 2 2 */
+628,	/* OBJ_setAttr_IssCap_CVM           2 23 42 3 3 3 */
+629,	/* OBJ_setAttr_IssCap_T2            2 23 42 3 3 4 */
+630,	/* OBJ_setAttr_IssCap_Sig           2 23 42 3 3 5 */
+642,	/* OBJ_set_brand_Novus              2 23 42 8 6011 */
+735,	/* OBJ_wap_wsg_idm_ecid_wtls1       2 23 43 1 4 1 */
+736,	/* OBJ_wap_wsg_idm_ecid_wtls3       2 23 43 1 4 3 */
+737,	/* OBJ_wap_wsg_idm_ecid_wtls4       2 23 43 1 4 4 */
+738,	/* OBJ_wap_wsg_idm_ecid_wtls5       2 23 43 1 4 5 */
+739,	/* OBJ_wap_wsg_idm_ecid_wtls6       2 23 43 1 4 6 */
+740,	/* OBJ_wap_wsg_idm_ecid_wtls7       2 23 43 1 4 7 */
+741,	/* OBJ_wap_wsg_idm_ecid_wtls8       2 23 43 1 4 8 */
+742,	/* OBJ_wap_wsg_idm_ecid_wtls9       2 23 43 1 4 9 */
+743,	/* OBJ_wap_wsg_idm_ecid_wtls10      2 23 43 1 4 10 */
+744,	/* OBJ_wap_wsg_idm_ecid_wtls11      2 23 43 1 4 11 */
+745,	/* OBJ_wap_wsg_idm_ecid_wtls12      2 23 43 1 4 12 */
+804,	/* OBJ_whirlpool                    1 0 10118 3 0 55 */
+124,	/* OBJ_rle_compression              1 1 1 1 666 1 */
+972,	/* OBJ_sm_scheme                    1 2 156 10197 1 */
+773,	/* OBJ_kisa                         1 2 410 200004 */
+807,	/* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */
+808,	/* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */
+809,	/* OBJ_id_GostR3411_94              1 2 643 2 2 9 */
+810,	/* OBJ_id_HMACGostR3411_94          1 2 643 2 2 10 */
+811,	/* OBJ_id_GostR3410_2001            1 2 643 2 2 19 */
+812,	/* OBJ_id_GostR3410_94              1 2 643 2 2 20 */
+813,	/* OBJ_id_Gost28147_89              1 2 643 2 2 21 */
+815,	/* OBJ_id_Gost28147_89_MAC          1 2 643 2 2 22 */
+816,	/* OBJ_id_GostR3411_94_prf          1 2 643 2 2 23 */
+817,	/* OBJ_id_GostR3410_2001DH          1 2 643 2 2 98 */
+818,	/* OBJ_id_GostR3410_94DH            1 2 643 2 2 99 */
+ 1,	/* OBJ_rsadsi                       1 2 840 113549 */
+185,	/* OBJ_X9cm                         1 2 840 10040 4 */
+127,	/* OBJ_id_pkix                      1 3 6 1 5 5 7 */
+505,	/* OBJ_mime_mhs_headings            1 3 6 1 7 1 1 */
+506,	/* OBJ_mime_mhs_bodies              1 3 6 1 7 1 2 */
+119,	/* OBJ_ripemd160WithRSA             1 3 36 3 3 1 2 */
+981,	/* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
+982,	/* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
+983,	/* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
+984,	/* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
+986,	/* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
+987,	/* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
+988,	/* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
+989,	/* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */
+631,	/* OBJ_setAttr_GenCryptgrm          2 23 42 3 3 3 1 */
+632,	/* OBJ_setAttr_T2Enc                2 23 42 3 3 4 1 */
+633,	/* OBJ_setAttr_T2cleartxt           2 23 42 3 3 4 2 */
+634,	/* OBJ_setAttr_TokICCsig            2 23 42 3 3 5 1 */
+635,	/* OBJ_setAttr_SecDevSig            2 23 42 3 3 5 2 */
+436,	/* OBJ_ucl                          0 9 2342 19200300 */
+820,	/* OBJ_id_Gost28147_89_None_KeyMeshing 1 2 643 2 2 14 0 */
+819,	/* OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1 2 643 2 2 14 1 */
+845,	/* OBJ_id_GostR3410_94_a            1 2 643 2 2 20 1 */
+846,	/* OBJ_id_GostR3410_94_aBis         1 2 643 2 2 20 2 */
+847,	/* OBJ_id_GostR3410_94_b            1 2 643 2 2 20 3 */
+848,	/* OBJ_id_GostR3410_94_bBis         1 2 643 2 2 20 4 */
+821,	/* OBJ_id_GostR3411_94_TestParamSet 1 2 643 2 2 30 0 */
+822,	/* OBJ_id_GostR3411_94_CryptoProParamSet 1 2 643 2 2 30 1 */
+823,	/* OBJ_id_Gost28147_89_TestParamSet 1 2 643 2 2 31 0 */
+824,	/* OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1 2 643 2 2 31 1 */
+825,	/* OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1 2 643 2 2 31 2 */
+826,	/* OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1 2 643 2 2 31 3 */
+827,	/* OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1 2 643 2 2 31 4 */
+828,	/* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 1 2 643 2 2 31 5 */
+829,	/* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 1 2 643 2 2 31 6 */
+830,	/* OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 1 2 643 2 2 31 7 */
+831,	/* OBJ_id_GostR3410_94_TestParamSet 1 2 643 2 2 32 0 */
+832,	/* OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1 2 643 2 2 32 2 */
+833,	/* OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1 2 643 2 2 32 3 */
+834,	/* OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1 2 643 2 2 32 4 */
+835,	/* OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1 2 643 2 2 32 5 */
+836,	/* OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet 1 2 643 2 2 33 1 */
+837,	/* OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet 1 2 643 2 2 33 2 */
+838,	/* OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet 1 2 643 2 2 33 3 */
+839,	/* OBJ_id_GostR3410_2001_TestParamSet 1 2 643 2 2 35 0 */
+840,	/* OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1 2 643 2 2 35 1 */
+841,	/* OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1 2 643 2 2 35 2 */
+842,	/* OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1 2 643 2 2 35 3 */
+843,	/* OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet 1 2 643 2 2 36 0 */
+844,	/* OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet 1 2 643 2 2 36 1 */
+ 2,	/* OBJ_pkcs                         1 2 840 113549 1 */
+431,	/* OBJ_hold_instruction_none        1 2 840 10040 2 1 */
+432,	/* OBJ_hold_instruction_call_issuer 1 2 840 10040 2 2 */
+433,	/* OBJ_hold_instruction_reject      1 2 840 10040 2 3 */
+116,	/* OBJ_dsa                          1 2 840 10040 4 1 */
+113,	/* OBJ_dsaWithSHA1                  1 2 840 10040 4 3 */
+406,	/* OBJ_X9_62_prime_field            1 2 840 10045 1 1 */
+407,	/* OBJ_X9_62_characteristic_two_field 1 2 840 10045 1 2 */
+408,	/* OBJ_X9_62_id_ecPublicKey         1 2 840 10045 2 1 */
+416,	/* OBJ_ecdsa_with_SHA1              1 2 840 10045 4 1 */
+791,	/* OBJ_ecdsa_with_Recommended       1 2 840 10045 4 2 */
+792,	/* OBJ_ecdsa_with_Specified         1 2 840 10045 4 3 */
+258,	/* OBJ_id_pkix_mod                  1 3 6 1 5 5 7 0 */
+175,	/* OBJ_id_pe                        1 3 6 1 5 5 7 1 */
+259,	/* OBJ_id_qt                        1 3 6 1 5 5 7 2 */
+128,	/* OBJ_id_kp                        1 3 6 1 5 5 7 3 */
+260,	/* OBJ_id_it                        1 3 6 1 5 5 7 4 */
+261,	/* OBJ_id_pkip                      1 3 6 1 5 5 7 5 */
+262,	/* OBJ_id_alg                       1 3 6 1 5 5 7 6 */
+263,	/* OBJ_id_cmc                       1 3 6 1 5 5 7 7 */
+264,	/* OBJ_id_on                        1 3 6 1 5 5 7 8 */
+265,	/* OBJ_id_pda                       1 3 6 1 5 5 7 9 */
+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 */
+1005,	/* 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 */
+508,	/* OBJ_id_hex_multipart_message     1 3 6 1 7 1 1 2 */
+921,	/* OBJ_brainpool                    1 3 36 3 3 2 8 1 */
+57,	/* OBJ_netscape                     2 16 840 1 113730 */
+754,	/* OBJ_camellia_128_ecb             0 3 4401 5 3 1 9 1 */
+766,	/* OBJ_camellia_128_ofb128          0 3 4401 5 3 1 9 3 */
+757,	/* OBJ_camellia_128_cfb128          0 3 4401 5 3 1 9 4 */
+755,	/* OBJ_camellia_192_ecb             0 3 4401 5 3 1 9 21 */
+767,	/* OBJ_camellia_192_ofb128          0 3 4401 5 3 1 9 23 */
+758,	/* OBJ_camellia_192_cfb128          0 3 4401 5 3 1 9 24 */
+756,	/* OBJ_camellia_256_ecb             0 3 4401 5 3 1 9 41 */
+768,	/* OBJ_camellia_256_ofb128          0 3 4401 5 3 1 9 43 */
+759,	/* OBJ_camellia_256_cfb128          0 3 4401 5 3 1 9 44 */
+437,	/* OBJ_pilot                        0 9 2342 19200300 100 */
+973,	/* OBJ_sm4_ecb                      1 2 156 10197 1 104 1 */
+974,	/* OBJ_sm4_cbc                      1 2 156 10197 1 104 2 */
+975,	/* OBJ_sm4_ofb128                   1 2 156 10197 1 104 3 */
+976,	/* OBJ_sm4_cfb128                   1 2 156 10197 1 104 4 */
+977,	/* OBJ_sm4_cfb1                     1 2 156 10197 1 104 5 */
+978,	/* OBJ_sm4_cfb8                     1 2 156 10197 1 104 6 */
+979,	/* OBJ_sm4_ctr                      1 2 156 10197 1 104 7 */
+968,	/* OBJ_sm3                          1 2 156 10197 1 401 */
+969,	/* 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 */
+779,	/* OBJ_seed_cfb128                  1 2 410 200004 1 5 */
+778,	/* OBJ_seed_ofb128                  1 2 410 200004 1 6 */
+852,	/* OBJ_id_GostR3411_94_with_GostR3410_94_cc 1 2 643 2 9 1 3 3 */
+853,	/* OBJ_id_GostR3411_94_with_GostR3410_2001_cc 1 2 643 2 9 1 3 4 */
+850,	/* OBJ_id_GostR3410_94_cc           1 2 643 2 9 1 5 3 */
+851,	/* OBJ_id_GostR3410_2001_cc         1 2 643 2 9 1 5 4 */
+849,	/* OBJ_id_Gost28147_89_cc           1 2 643 2 9 1 6 1 */
+854,	/* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
+946,	/* OBJ_id_tc26_gost3410_2012_256    1 2 643 7 1 1 1 1 */
+947,	/* OBJ_id_tc26_gost3410_2012_512    1 2 643 7 1 1 1 2 */
+941,	/* OBJ_id_tc26_gost3411_2012_256    1 2 643 7 1 1 2 2 */
+942,	/* OBJ_id_tc26_gost3411_2012_512    1 2 643 7 1 1 2 3 */
+948,	/* OBJ_id_tc26_signwithdigest_gost3410_2012_256 1 2 643 7 1 1 3 2 */
+949,	/* OBJ_id_tc26_signwithdigest_gost3410_2012_512 1 2 643 7 1 1 3 3 */
+999,	/* OBJ_id_tc26_hmac_gost_3411_12_256 1 2 643 7 1 1 4 1 */
+1000,	/* OBJ_id_tc26_hmac_gost_3411_12_512 1 2 643 7 1 1 4 2 */
+186,	/* OBJ_pkcs1                        1 2 840 113549 1 1 */
+27,	/* OBJ_pkcs3                        1 2 840 113549 1 3 */
+187,	/* OBJ_pkcs5                        1 2 840 113549 1 5 */
+20,	/* OBJ_pkcs7                        1 2 840 113549 1 7 */
+47,	/* OBJ_pkcs9                        1 2 840 113549 1 9 */
+ 3,	/* OBJ_md2                          1 2 840 113549 2 2 */
+257,	/* OBJ_md4                          1 2 840 113549 2 4 */
+ 4,	/* OBJ_md5                          1 2 840 113549 2 5 */
+797,	/* OBJ_hmacWithMD5                  1 2 840 113549 2 6 */
+163,	/* OBJ_hmacWithSHA1                 1 2 840 113549 2 7 */
+798,	/* OBJ_hmacWithSHA224               1 2 840 113549 2 8 */
+799,	/* OBJ_hmacWithSHA256               1 2 840 113549 2 9 */
+800,	/* OBJ_hmacWithSHA384               1 2 840 113549 2 10 */
+801,	/* OBJ_hmacWithSHA512               1 2 840 113549 2 11 */
+1027,	/* OBJ_hmacWithSHA512_224           1 2 840 113549 2 12 */
+1028,	/* OBJ_hmacWithSHA512_256           1 2 840 113549 2 13 */
+37,	/* OBJ_rc2_cbc                      1 2 840 113549 3 2 */
+ 5,	/* OBJ_rc4                          1 2 840 113549 3 4 */
+44,	/* OBJ_des_ede3_cbc                 1 2 840 113549 3 7 */
+120,	/* OBJ_rc5_cbc                      1 2 840 113549 3 8 */
+643,	/* OBJ_des_cdmf                     1 2 840 113549 3 10 */
+680,	/* OBJ_X9_62_id_characteristic_two_basis 1 2 840 10045 1 2 3 */
+684,	/* OBJ_X9_62_c2pnb163v1             1 2 840 10045 3 0 1 */
+685,	/* OBJ_X9_62_c2pnb163v2             1 2 840 10045 3 0 2 */
+686,	/* OBJ_X9_62_c2pnb163v3             1 2 840 10045 3 0 3 */
+687,	/* OBJ_X9_62_c2pnb176v1             1 2 840 10045 3 0 4 */
+688,	/* OBJ_X9_62_c2tnb191v1             1 2 840 10045 3 0 5 */
+689,	/* OBJ_X9_62_c2tnb191v2             1 2 840 10045 3 0 6 */
+690,	/* OBJ_X9_62_c2tnb191v3             1 2 840 10045 3 0 7 */
+691,	/* OBJ_X9_62_c2onb191v4             1 2 840 10045 3 0 8 */
+692,	/* OBJ_X9_62_c2onb191v5             1 2 840 10045 3 0 9 */
+693,	/* OBJ_X9_62_c2pnb208w1             1 2 840 10045 3 0 10 */
+694,	/* OBJ_X9_62_c2tnb239v1             1 2 840 10045 3 0 11 */
+695,	/* OBJ_X9_62_c2tnb239v2             1 2 840 10045 3 0 12 */
+696,	/* OBJ_X9_62_c2tnb239v3             1 2 840 10045 3 0 13 */
+697,	/* OBJ_X9_62_c2onb239v4             1 2 840 10045 3 0 14 */
+698,	/* OBJ_X9_62_c2onb239v5             1 2 840 10045 3 0 15 */
+699,	/* OBJ_X9_62_c2pnb272w1             1 2 840 10045 3 0 16 */
+700,	/* OBJ_X9_62_c2pnb304w1             1 2 840 10045 3 0 17 */
+701,	/* OBJ_X9_62_c2tnb359v1             1 2 840 10045 3 0 18 */
+702,	/* OBJ_X9_62_c2pnb368w1             1 2 840 10045 3 0 19 */
+703,	/* OBJ_X9_62_c2tnb431r1             1 2 840 10045 3 0 20 */
+409,	/* OBJ_X9_62_prime192v1             1 2 840 10045 3 1 1 */
+410,	/* OBJ_X9_62_prime192v2             1 2 840 10045 3 1 2 */
+411,	/* OBJ_X9_62_prime192v3             1 2 840 10045 3 1 3 */
+412,	/* OBJ_X9_62_prime239v1             1 2 840 10045 3 1 4 */
+413,	/* OBJ_X9_62_prime239v2             1 2 840 10045 3 1 5 */
+414,	/* OBJ_X9_62_prime239v3             1 2 840 10045 3 1 6 */
+415,	/* OBJ_X9_62_prime256v1             1 2 840 10045 3 1 7 */
+793,	/* OBJ_ecdsa_with_SHA224            1 2 840 10045 4 3 1 */
+794,	/* OBJ_ecdsa_with_SHA256            1 2 840 10045 4 3 2 */
+795,	/* OBJ_ecdsa_with_SHA384            1 2 840 10045 4 3 3 */
+796,	/* OBJ_ecdsa_with_SHA512            1 2 840 10045 4 3 4 */
+269,	/* OBJ_id_pkix1_explicit_88         1 3 6 1 5 5 7 0 1 */
+270,	/* OBJ_id_pkix1_implicit_88         1 3 6 1 5 5 7 0 2 */
+271,	/* OBJ_id_pkix1_explicit_93         1 3 6 1 5 5 7 0 3 */
+272,	/* OBJ_id_pkix1_implicit_93         1 3 6 1 5 5 7 0 4 */
+273,	/* OBJ_id_mod_crmf                  1 3 6 1 5 5 7 0 5 */
+274,	/* OBJ_id_mod_cmc                   1 3 6 1 5 5 7 0 6 */
+275,	/* OBJ_id_mod_kea_profile_88        1 3 6 1 5 5 7 0 7 */
+276,	/* OBJ_id_mod_kea_profile_93        1 3 6 1 5 5 7 0 8 */
+277,	/* OBJ_id_mod_cmp                   1 3 6 1 5 5 7 0 9 */
+278,	/* OBJ_id_mod_qualified_cert_88     1 3 6 1 5 5 7 0 10 */
+279,	/* OBJ_id_mod_qualified_cert_93     1 3 6 1 5 5 7 0 11 */
+280,	/* OBJ_id_mod_attribute_cert        1 3 6 1 5 5 7 0 12 */
+281,	/* OBJ_id_mod_timestamp_protocol    1 3 6 1 5 5 7 0 13 */
+282,	/* OBJ_id_mod_ocsp                  1 3 6 1 5 5 7 0 14 */
+283,	/* OBJ_id_mod_dvcs                  1 3 6 1 5 5 7 0 15 */
+284,	/* OBJ_id_mod_cmp2000               1 3 6 1 5 5 7 0 16 */
+177,	/* OBJ_info_access                  1 3 6 1 5 5 7 1 1 */
+285,	/* OBJ_biometricInfo                1 3 6 1 5 5 7 1 2 */
+286,	/* OBJ_qcStatements                 1 3 6 1 5 5 7 1 3 */
+287,	/* OBJ_ac_auditEntity               1 3 6 1 5 5 7 1 4 */
+288,	/* OBJ_ac_targeting                 1 3 6 1 5 5 7 1 5 */
+289,	/* OBJ_aaControls                   1 3 6 1 5 5 7 1 6 */
+290,	/* OBJ_sbgp_ipAddrBlock             1 3 6 1 5 5 7 1 7 */
+291,	/* OBJ_sbgp_autonomousSysNum        1 3 6 1 5 5 7 1 8 */
+292,	/* OBJ_sbgp_routerIdentifier        1 3 6 1 5 5 7 1 9 */
+397,	/* OBJ_ac_proxying                  1 3 6 1 5 5 7 1 10 */
+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 */
+1016,	/* OBJ_tlsfeature                   1 3 6 1 5 5 7 1 24 */
+1006,	/* OBJ_sbgp_ipAddrBlockv2           1 3 6 1 5 5 7 1 28 */
+1007,	/* 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 */
+129,	/* OBJ_server_auth                  1 3 6 1 5 5 7 3 1 */
+130,	/* OBJ_client_auth                  1 3 6 1 5 5 7 3 2 */
+131,	/* OBJ_code_sign                    1 3 6 1 5 5 7 3 3 */
+132,	/* OBJ_email_protect                1 3 6 1 5 5 7 3 4 */
+294,	/* OBJ_ipsecEndSystem               1 3 6 1 5 5 7 3 5 */
+295,	/* OBJ_ipsecTunnel                  1 3 6 1 5 5 7 3 6 */
+296,	/* OBJ_ipsecUser                    1 3 6 1 5 5 7 3 7 */
+133,	/* OBJ_time_stamp                   1 3 6 1 5 5 7 3 8 */
+180,	/* OBJ_OCSP_sign                    1 3 6 1 5 5 7 3 9 */
+297,	/* OBJ_dvcs                         1 3 6 1 5 5 7 3 10 */
+1015,	/* OBJ_id_kp_bgpsec_router          1 3 6 1 5 5 7 3 30 */
+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 */
+301,	/* OBJ_id_it_preferredSymmAlg       1 3 6 1 5 5 7 4 4 */
+302,	/* OBJ_id_it_caKeyUpdateInfo        1 3 6 1 5 5 7 4 5 */
+303,	/* OBJ_id_it_currentCRL             1 3 6 1 5 5 7 4 6 */
+304,	/* OBJ_id_it_unsupportedOIDs        1 3 6 1 5 5 7 4 7 */
+305,	/* OBJ_id_it_subscriptionRequest    1 3 6 1 5 5 7 4 8 */
+306,	/* OBJ_id_it_subscriptionResponse   1 3 6 1 5 5 7 4 9 */
+307,	/* OBJ_id_it_keyPairParamReq        1 3 6 1 5 5 7 4 10 */
+308,	/* OBJ_id_it_keyPairParamRep        1 3 6 1 5 5 7 4 11 */
+309,	/* OBJ_id_it_revPassphrase          1 3 6 1 5 5 7 4 12 */
+310,	/* OBJ_id_it_implicitConfirm        1 3 6 1 5 5 7 4 13 */
+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 */
+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 */
+324,	/* OBJ_id_alg_noSignature           1 3 6 1 5 5 7 6 2 */
+325,	/* OBJ_id_alg_dh_sig_hmac_sha1      1 3 6 1 5 5 7 6 3 */
+326,	/* OBJ_id_alg_dh_pop                1 3 6 1 5 5 7 6 4 */
+327,	/* OBJ_id_cmc_statusInfo            1 3 6 1 5 5 7 7 1 */
+328,	/* OBJ_id_cmc_identification        1 3 6 1 5 5 7 7 2 */
+329,	/* OBJ_id_cmc_identityProof         1 3 6 1 5 5 7 7 3 */
+330,	/* OBJ_id_cmc_dataReturn            1 3 6 1 5 5 7 7 4 */
+331,	/* OBJ_id_cmc_transactionId         1 3 6 1 5 5 7 7 5 */
+332,	/* OBJ_id_cmc_senderNonce           1 3 6 1 5 5 7 7 6 */
+333,	/* OBJ_id_cmc_recipientNonce        1 3 6 1 5 5 7 7 7 */
+334,	/* OBJ_id_cmc_addExtensions         1 3 6 1 5 5 7 7 8 */
+335,	/* OBJ_id_cmc_encryptedPOP          1 3 6 1 5 5 7 7 9 */
+336,	/* OBJ_id_cmc_decryptedPOP          1 3 6 1 5 5 7 7 10 */
+337,	/* OBJ_id_cmc_lraPOPWitness         1 3 6 1 5 5 7 7 11 */
+338,	/* OBJ_id_cmc_getCert               1 3 6 1 5 5 7 7 15 */
+339,	/* OBJ_id_cmc_getCRL                1 3 6 1 5 5 7 7 16 */
+340,	/* OBJ_id_cmc_revokeRequest         1 3 6 1 5 5 7 7 17 */
+341,	/* OBJ_id_cmc_regInfo               1 3 6 1 5 5 7 7 18 */
+342,	/* OBJ_id_cmc_responseInfo          1 3 6 1 5 5 7 7 19 */
+343,	/* OBJ_id_cmc_queryPending          1 3 6 1 5 5 7 7 21 */
+344,	/* OBJ_id_cmc_popLinkRandom         1 3 6 1 5 5 7 7 22 */
+345,	/* OBJ_id_cmc_popLinkWitness        1 3 6 1 5 5 7 7 23 */
+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 */
+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 */
+352,	/* OBJ_id_pda_countryOfCitizenship  1 3 6 1 5 5 7 9 4 */
+353,	/* OBJ_id_pda_countryOfResidence    1 3 6 1 5 5 7 9 5 */
+354,	/* OBJ_id_aca_authenticationInfo    1 3 6 1 5 5 7 10 1 */
+355,	/* OBJ_id_aca_accessIdentity        1 3 6 1 5 5 7 10 2 */
+356,	/* OBJ_id_aca_chargingIdentity      1 3 6 1 5 5 7 10 3 */
+357,	/* OBJ_id_aca_group                 1 3 6 1 5 5 7 10 4 */
+358,	/* OBJ_id_aca_role                  1 3 6 1 5 5 7 10 5 */
+399,	/* OBJ_id_aca_encAttrs              1 3 6 1 5 5 7 10 6 */
+359,	/* OBJ_id_qcs_pkixQCSyntax_v1       1 3 6 1 5 5 7 11 1 */
+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 */
+1008,	/* OBJ_ipAddr_asNumber              1 3 6 1 5 5 7 14 2 */
+1009,	/* 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 */
+178,	/* OBJ_ad_OCSP                      1 3 6 1 5 5 7 48 1 */
+179,	/* OBJ_ad_ca_issuers                1 3 6 1 5 5 7 48 2 */
+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 */
+1010,	/* OBJ_rpkiManifest                 1 3 6 1 5 5 7 48 10 */
+1011,	/* OBJ_signedObject                 1 3 6 1 5 5 7 48 11 */
+1012,	/* 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 */
+58,	/* OBJ_netscape_cert_extension      2 16 840 1 113730 1 */
+59,	/* OBJ_netscape_data_type           2 16 840 1 113730 2 */
+438,	/* OBJ_pilotAttributeType           0 9 2342 19200300 100 1 */
+439,	/* OBJ_pilotAttributeSyntax         0 9 2342 19200300 100 3 */
+440,	/* OBJ_pilotObjectClass             0 9 2342 19200300 100 4 */
+441,	/* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
+993,	/* OBJ_id_tc26_gost_3410_12_256_paramSetA 1 2 643 7 1 2 1 1 1 */
+994,	/* OBJ_id_tc26_gost_3410_12_256_paramSetB 1 2 643 7 1 2 1 1 2 */
+995,	/* OBJ_id_tc26_gost_3410_12_256_paramSetC 1 2 643 7 1 2 1 1 3 */
+996,	/* OBJ_id_tc26_gost_3410_12_256_paramSetD 1 2 643 7 1 2 1 1 4 */
+997,	/* OBJ_id_tc26_gost_3410_12_512_paramSetTest 1 2 643 7 1 2 1 2 0 */
+943,	/* OBJ_id_tc26_gost_3410_12_512_paramSetA 1 2 643 7 1 2 1 2 1 */
+944,	/* OBJ_id_tc26_gost_3410_12_512_paramSetB 1 2 643 7 1 2 1 2 2 */
+998,	/* OBJ_id_tc26_gost_3410_12_512_paramSetC 1 2 643 7 1 2 1 2 3 */
+945,	/* OBJ_id_tc26_gost_28147_param_Z   1 2 643 7 1 2 5 1 1 */
+108,	/* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
+112,	/* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
+782,	/* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
+783,	/* OBJ_id_DHBasedMac                1 2 840 113533 7 66 30 */
+ 6,	/* OBJ_rsaEncryption                1 2 840 113549 1 1 1 */
+ 7,	/* OBJ_md2WithRSAEncryption         1 2 840 113549 1 1 2 */
+396,	/* OBJ_md4WithRSAEncryption         1 2 840 113549 1 1 3 */
+ 8,	/* OBJ_md5WithRSAEncryption         1 2 840 113549 1 1 4 */
+65,	/* OBJ_sha1WithRSAEncryption        1 2 840 113549 1 1 5 */
+644,	/* OBJ_rsaOAEPEncryptionSET         1 2 840 113549 1 1 6 */
+919,	/* OBJ_rsaesOaep                    1 2 840 113549 1 1 7 */
+911,	/* OBJ_mgf1                         1 2 840 113549 1 1 8 */
+992,	/* OBJ_pSpecified                   1 2 840 113549 1 1 9 */
+912,	/* OBJ_rsassaPss                    1 2 840 113549 1 1 10 */
+668,	/* OBJ_sha256WithRSAEncryption      1 2 840 113549 1 1 11 */
+669,	/* OBJ_sha384WithRSAEncryption      1 2 840 113549 1 1 12 */
+670,	/* OBJ_sha512WithRSAEncryption      1 2 840 113549 1 1 13 */
+671,	/* OBJ_sha224WithRSAEncryption      1 2 840 113549 1 1 14 */
+1025,	/* OBJ_sha512_224WithRSAEncryption  1 2 840 113549 1 1 15 */
+1026,	/* OBJ_sha512_256WithRSAEncryption  1 2 840 113549 1 1 16 */
+28,	/* OBJ_dhKeyAgreement               1 2 840 113549 1 3 1 */
+ 9,	/* OBJ_pbeWithMD2AndDES_CBC         1 2 840 113549 1 5 1 */
+10,	/* OBJ_pbeWithMD5AndDES_CBC         1 2 840 113549 1 5 3 */
+168,	/* OBJ_pbeWithMD2AndRC2_CBC         1 2 840 113549 1 5 4 */
+169,	/* OBJ_pbeWithMD5AndRC2_CBC         1 2 840 113549 1 5 6 */
+170,	/* OBJ_pbeWithSHA1AndDES_CBC        1 2 840 113549 1 5 10 */
+68,	/* OBJ_pbeWithSHA1AndRC2_CBC        1 2 840 113549 1 5 11 */
+69,	/* OBJ_id_pbkdf2                    1 2 840 113549 1 5 12 */
+161,	/* OBJ_pbes2                        1 2 840 113549 1 5 13 */
+162,	/* OBJ_pbmac1                       1 2 840 113549 1 5 14 */
+21,	/* OBJ_pkcs7_data                   1 2 840 113549 1 7 1 */
+22,	/* OBJ_pkcs7_signed                 1 2 840 113549 1 7 2 */
+23,	/* OBJ_pkcs7_enveloped              1 2 840 113549 1 7 3 */
+24,	/* OBJ_pkcs7_signedAndEnveloped     1 2 840 113549 1 7 4 */
+25,	/* OBJ_pkcs7_digest                 1 2 840 113549 1 7 5 */
+26,	/* OBJ_pkcs7_encrypted              1 2 840 113549 1 7 6 */
+48,	/* OBJ_pkcs9_emailAddress           1 2 840 113549 1 9 1 */
+49,	/* OBJ_pkcs9_unstructuredName       1 2 840 113549 1 9 2 */
+50,	/* OBJ_pkcs9_contentType            1 2 840 113549 1 9 3 */
+51,	/* OBJ_pkcs9_messageDigest          1 2 840 113549 1 9 4 */
+52,	/* OBJ_pkcs9_signingTime            1 2 840 113549 1 9 5 */
+53,	/* OBJ_pkcs9_countersignature       1 2 840 113549 1 9 6 */
+54,	/* OBJ_pkcs9_challengePassword      1 2 840 113549 1 9 7 */
+55,	/* OBJ_pkcs9_unstructuredAddress    1 2 840 113549 1 9 8 */
+56,	/* OBJ_pkcs9_extCertAttributes      1 2 840 113549 1 9 9 */
+172,	/* OBJ_ext_req                      1 2 840 113549 1 9 14 */
+167,	/* OBJ_SMIMECapabilities            1 2 840 113549 1 9 15 */
+188,	/* OBJ_SMIME                        1 2 840 113549 1 9 16 */
+156,	/* OBJ_friendlyName                 1 2 840 113549 1 9 20 */
+157,	/* OBJ_localKeyID                   1 2 840 113549 1 9 21 */
+681,	/* OBJ_X9_62_onBasis                1 2 840 10045 1 2 3 1 */
+682,	/* OBJ_X9_62_tpBasis                1 2 840 10045 1 2 3 2 */
+683,	/* OBJ_X9_62_ppBasis                1 2 840 10045 1 2 3 3 */
+417,	/* OBJ_ms_csp_name                  1 3 6 1 4 1 311 17 1 */
+856,	/* OBJ_LocalKeySet                  1 3 6 1 4 1 311 17 2 */
+390,	/* OBJ_dcObject                     1 3 6 1 4 1 1466 344 */
+91,	/* OBJ_bf_cbc                       1 3 6 1 4 1 3029 1 2 */
+315,	/* OBJ_id_regCtrl_regToken          1 3 6 1 5 5 7 5 1 1 */
+316,	/* OBJ_id_regCtrl_authenticator     1 3 6 1 5 5 7 5 1 2 */
+317,	/* OBJ_id_regCtrl_pkiPublicationInfo 1 3 6 1 5 5 7 5 1 3 */
+318,	/* OBJ_id_regCtrl_pkiArchiveOptions 1 3 6 1 5 5 7 5 1 4 */
+319,	/* OBJ_id_regCtrl_oldCertID         1 3 6 1 5 5 7 5 1 5 */
+320,	/* OBJ_id_regCtrl_protocolEncrKey   1 3 6 1 5 5 7 5 1 6 */
+321,	/* OBJ_id_regInfo_utf8Pairs         1 3 6 1 5 5 7 5 2 1 */
+322,	/* OBJ_id_regInfo_certReq           1 3 6 1 5 5 7 5 2 2 */
+365,	/* OBJ_id_pkix_OCSP_basic           1 3 6 1 5 5 7 48 1 1 */
+366,	/* OBJ_id_pkix_OCSP_Nonce           1 3 6 1 5 5 7 48 1 2 */
+367,	/* OBJ_id_pkix_OCSP_CrlID           1 3 6 1 5 5 7 48 1 3 */
+368,	/* OBJ_id_pkix_OCSP_acceptableResponses 1 3 6 1 5 5 7 48 1 4 */
+369,	/* OBJ_id_pkix_OCSP_noCheck         1 3 6 1 5 5 7 48 1 5 */
+370,	/* OBJ_id_pkix_OCSP_archiveCutoff   1 3 6 1 5 5 7 48 1 6 */
+371,	/* OBJ_id_pkix_OCSP_serviceLocator  1 3 6 1 5 5 7 48 1 7 */
+372,	/* OBJ_id_pkix_OCSP_extendedStatus  1 3 6 1 5 5 7 48 1 8 */
+373,	/* OBJ_id_pkix_OCSP_valid           1 3 6 1 5 5 7 48 1 9 */
+374,	/* OBJ_id_pkix_OCSP_path            1 3 6 1 5 5 7 48 1 10 */
+375,	/* OBJ_id_pkix_OCSP_trustRoot       1 3 6 1 5 5 7 48 1 11 */
+922,	/* OBJ_brainpoolP160r1              1 3 36 3 3 2 8 1 1 1 */
+923,	/* OBJ_brainpoolP160t1              1 3 36 3 3 2 8 1 1 2 */
+924,	/* OBJ_brainpoolP192r1              1 3 36 3 3 2 8 1 1 3 */
+925,	/* OBJ_brainpoolP192t1              1 3 36 3 3 2 8 1 1 4 */
+926,	/* OBJ_brainpoolP224r1              1 3 36 3 3 2 8 1 1 5 */
+927,	/* OBJ_brainpoolP224t1              1 3 36 3 3 2 8 1 1 6 */
+928,	/* OBJ_brainpoolP256r1              1 3 36 3 3 2 8 1 1 7 */
+929,	/* OBJ_brainpoolP256t1              1 3 36 3 3 2 8 1 1 8 */
+930,	/* OBJ_brainpoolP320r1              1 3 36 3 3 2 8 1 1 9 */
+931,	/* OBJ_brainpoolP320t1              1 3 36 3 3 2 8 1 1 10 */
+932,	/* OBJ_brainpoolP384r1              1 3 36 3 3 2 8 1 1 11 */
+933,	/* OBJ_brainpoolP384t1              1 3 36 3 3 2 8 1 1 12 */
+934,	/* OBJ_brainpoolP512r1              1 3 36 3 3 2 8 1 1 13 */
+935,	/* OBJ_brainpoolP512t1              1 3 36 3 3 2 8 1 1 14 */
+980,	/* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
+985,	/* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */
+418,	/* OBJ_aes_128_ecb                  2 16 840 1 101 3 4 1 1 */
+419,	/* OBJ_aes_128_cbc                  2 16 840 1 101 3 4 1 2 */
+420,	/* OBJ_aes_128_ofb128               2 16 840 1 101 3 4 1 3 */
+421,	/* OBJ_aes_128_cfb128               2 16 840 1 101 3 4 1 4 */
+788,	/* OBJ_id_aes128_wrap               2 16 840 1 101 3 4 1 5 */
+895,	/* OBJ_aes_128_gcm                  2 16 840 1 101 3 4 1 6 */
+896,	/* OBJ_aes_128_ccm                  2 16 840 1 101 3 4 1 7 */
+897,	/* OBJ_id_aes128_wrap_pad           2 16 840 1 101 3 4 1 8 */
+422,	/* OBJ_aes_192_ecb                  2 16 840 1 101 3 4 1 21 */
+423,	/* OBJ_aes_192_cbc                  2 16 840 1 101 3 4 1 22 */
+424,	/* OBJ_aes_192_ofb128               2 16 840 1 101 3 4 1 23 */
+425,	/* OBJ_aes_192_cfb128               2 16 840 1 101 3 4 1 24 */
+789,	/* OBJ_id_aes192_wrap               2 16 840 1 101 3 4 1 25 */
+898,	/* OBJ_aes_192_gcm                  2 16 840 1 101 3 4 1 26 */
+899,	/* OBJ_aes_192_ccm                  2 16 840 1 101 3 4 1 27 */
+900,	/* OBJ_id_aes192_wrap_pad           2 16 840 1 101 3 4 1 28 */
+426,	/* OBJ_aes_256_ecb                  2 16 840 1 101 3 4 1 41 */
+427,	/* OBJ_aes_256_cbc                  2 16 840 1 101 3 4 1 42 */
+428,	/* OBJ_aes_256_ofb128               2 16 840 1 101 3 4 1 43 */
+429,	/* OBJ_aes_256_cfb128               2 16 840 1 101 3 4 1 44 */
+790,	/* OBJ_id_aes256_wrap               2 16 840 1 101 3 4 1 45 */
+901,	/* OBJ_aes_256_gcm                  2 16 840 1 101 3 4 1 46 */
+902,	/* OBJ_aes_256_ccm                  2 16 840 1 101 3 4 1 47 */
+903,	/* OBJ_id_aes256_wrap_pad           2 16 840 1 101 3 4 1 48 */
+672,	/* OBJ_sha256                       2 16 840 1 101 3 4 2 1 */
+673,	/* OBJ_sha384                       2 16 840 1 101 3 4 2 2 */
+674,	/* OBJ_sha512                       2 16 840 1 101 3 4 2 3 */
+675,	/* OBJ_sha224                       2 16 840 1 101 3 4 2 4 */
+1029,	/* OBJ_sha512_224                   2 16 840 1 101 3 4 2 5 */
+1030,	/* OBJ_sha512_256                   2 16 840 1 101 3 4 2 6 */
+1031,	/* OBJ_sha3_224                     2 16 840 1 101 3 4 2 7 */
+1032,	/* OBJ_sha3_256                     2 16 840 1 101 3 4 2 8 */
+1033,	/* OBJ_sha3_384                     2 16 840 1 101 3 4 2 9 */
+1034,	/* OBJ_sha3_512                     2 16 840 1 101 3 4 2 10 */
+1035,	/* OBJ_hmac_sha3_224                2 16 840 1 101 3 4 2 13 */
+1036,	/* OBJ_hmac_sha3_256                2 16 840 1 101 3 4 2 14 */
+1037,	/* OBJ_hmac_sha3_384                2 16 840 1 101 3 4 2 15 */
+1038,	/* OBJ_hmac_sha3_512                2 16 840 1 101 3 4 2 16 */
+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 */
+1039,	/* OBJ_dsa_with_SHA384              2 16 840 1 101 3 4 3 3 */
+1040,	/* OBJ_dsa_with_SHA512              2 16 840 1 101 3 4 3 4 */
+1041,	/* OBJ_dsa_with_SHA3_224            2 16 840 1 101 3 4 3 5 */
+1042,	/* OBJ_dsa_with_SHA3_256            2 16 840 1 101 3 4 3 6 */
+1043,	/* OBJ_dsa_with_SHA3_384            2 16 840 1 101 3 4 3 7 */
+1044,	/* OBJ_dsa_with_SHA3_512            2 16 840 1 101 3 4 3 8 */
+1045,	/* OBJ_ecdsa_with_SHA3_224          2 16 840 1 101 3 4 3 9 */
+1046,	/* OBJ_ecdsa_with_SHA3_256          2 16 840 1 101 3 4 3 10 */
+1047,	/* OBJ_ecdsa_with_SHA3_384          2 16 840 1 101 3 4 3 11 */
+1048,	/* OBJ_ecdsa_with_SHA3_512          2 16 840 1 101 3 4 3 12 */
+1049,	/* OBJ_RSA_SHA3_224                 2 16 840 1 101 3 4 3 13 */
+1050,	/* OBJ_RSA_SHA3_256                 2 16 840 1 101 3 4 3 14 */
+1051,	/* OBJ_RSA_SHA3_384                 2 16 840 1 101 3 4 3 15 */
+1052,	/* OBJ_RSA_SHA3_512                 2 16 840 1 101 3 4 3 16 */
+71,	/* OBJ_netscape_cert_type           2 16 840 1 113730 1 1 */
+72,	/* OBJ_netscape_base_url            2 16 840 1 113730 1 2 */
+73,	/* OBJ_netscape_revocation_url      2 16 840 1 113730 1 3 */
+74,	/* OBJ_netscape_ca_revocation_url   2 16 840 1 113730 1 4 */
+75,	/* OBJ_netscape_renewal_url         2 16 840 1 113730 1 7 */
+76,	/* OBJ_netscape_ca_policy_url       2 16 840 1 113730 1 8 */
+77,	/* OBJ_netscape_ssl_server_name     2 16 840 1 113730 1 12 */
+78,	/* OBJ_netscape_comment             2 16 840 1 113730 1 13 */
+79,	/* OBJ_netscape_cert_sequence       2 16 840 1 113730 2 5 */
+139,	/* OBJ_ns_sgc                       2 16 840 1 113730 4 1 */
+458,	/* OBJ_userId                       0 9 2342 19200300 100 1 1 */
+459,	/* OBJ_textEncodedORAddress         0 9 2342 19200300 100 1 2 */
+460,	/* OBJ_rfc822Mailbox                0 9 2342 19200300 100 1 3 */
+461,	/* OBJ_info                         0 9 2342 19200300 100 1 4 */
+462,	/* OBJ_favouriteDrink               0 9 2342 19200300 100 1 5 */
+463,	/* OBJ_roomNumber                   0 9 2342 19200300 100 1 6 */
+464,	/* OBJ_photo                        0 9 2342 19200300 100 1 7 */
+465,	/* OBJ_userClass                    0 9 2342 19200300 100 1 8 */
+466,	/* OBJ_host                         0 9 2342 19200300 100 1 9 */
+467,	/* OBJ_manager                      0 9 2342 19200300 100 1 10 */
+468,	/* OBJ_documentIdentifier           0 9 2342 19200300 100 1 11 */
+469,	/* OBJ_documentTitle                0 9 2342 19200300 100 1 12 */
+470,	/* OBJ_documentVersion              0 9 2342 19200300 100 1 13 */
+471,	/* OBJ_documentAuthor               0 9 2342 19200300 100 1 14 */
+472,	/* OBJ_documentLocation             0 9 2342 19200300 100 1 15 */
+473,	/* OBJ_homeTelephoneNumber          0 9 2342 19200300 100 1 20 */
+474,	/* OBJ_secretary                    0 9 2342 19200300 100 1 21 */
+475,	/* OBJ_otherMailbox                 0 9 2342 19200300 100 1 22 */
+476,	/* OBJ_lastModifiedTime             0 9 2342 19200300 100 1 23 */
+477,	/* OBJ_lastModifiedBy               0 9 2342 19200300 100 1 24 */
+391,	/* OBJ_domainComponent              0 9 2342 19200300 100 1 25 */
+478,	/* OBJ_aRecord                      0 9 2342 19200300 100 1 26 */
+479,	/* OBJ_pilotAttributeType27         0 9 2342 19200300 100 1 27 */
+480,	/* OBJ_mXRecord                     0 9 2342 19200300 100 1 28 */
+481,	/* OBJ_nSRecord                     0 9 2342 19200300 100 1 29 */
+482,	/* OBJ_sOARecord                    0 9 2342 19200300 100 1 30 */
+483,	/* OBJ_cNAMERecord                  0 9 2342 19200300 100 1 31 */
+484,	/* OBJ_associatedDomain             0 9 2342 19200300 100 1 37 */
+485,	/* OBJ_associatedName               0 9 2342 19200300 100 1 38 */
+486,	/* OBJ_homePostalAddress            0 9 2342 19200300 100 1 39 */
+487,	/* OBJ_personalTitle                0 9 2342 19200300 100 1 40 */
+488,	/* OBJ_mobileTelephoneNumber        0 9 2342 19200300 100 1 41 */
+489,	/* OBJ_pagerTelephoneNumber         0 9 2342 19200300 100 1 42 */
+490,	/* OBJ_friendlyCountryName          0 9 2342 19200300 100 1 43 */
+491,	/* OBJ_organizationalStatus         0 9 2342 19200300 100 1 45 */
+492,	/* OBJ_janetMailbox                 0 9 2342 19200300 100 1 46 */
+493,	/* OBJ_mailPreferenceOption         0 9 2342 19200300 100 1 47 */
+494,	/* OBJ_buildingName                 0 9 2342 19200300 100 1 48 */
+495,	/* OBJ_dSAQuality                   0 9 2342 19200300 100 1 49 */
+496,	/* OBJ_singleLevelQuality           0 9 2342 19200300 100 1 50 */
+497,	/* OBJ_subtreeMinimumQuality        0 9 2342 19200300 100 1 51 */
+498,	/* OBJ_subtreeMaximumQuality        0 9 2342 19200300 100 1 52 */
+499,	/* OBJ_personalSignature            0 9 2342 19200300 100 1 53 */
+500,	/* OBJ_dITRedirect                  0 9 2342 19200300 100 1 54 */
+501,	/* OBJ_audio                        0 9 2342 19200300 100 1 55 */
+502,	/* OBJ_documentPublisher            0 9 2342 19200300 100 1 56 */
+442,	/* OBJ_iA5StringSyntax              0 9 2342 19200300 100 3 4 */
+443,	/* OBJ_caseIgnoreIA5StringSyntax    0 9 2342 19200300 100 3 5 */
+444,	/* OBJ_pilotObject                  0 9 2342 19200300 100 4 3 */
+445,	/* OBJ_pilotPerson                  0 9 2342 19200300 100 4 4 */
+446,	/* OBJ_account                      0 9 2342 19200300 100 4 5 */
+447,	/* OBJ_document                     0 9 2342 19200300 100 4 6 */
+448,	/* OBJ_room                         0 9 2342 19200300 100 4 7 */
+449,	/* OBJ_documentSeries               0 9 2342 19200300 100 4 9 */
+392,	/* OBJ_Domain                       0 9 2342 19200300 100 4 13 */
+450,	/* OBJ_rFC822localPart              0 9 2342 19200300 100 4 14 */
+451,	/* OBJ_dNSDomain                    0 9 2342 19200300 100 4 15 */
+452,	/* OBJ_domainRelatedObject          0 9 2342 19200300 100 4 17 */
+453,	/* OBJ_friendlyCountry              0 9 2342 19200300 100 4 18 */
+454,	/* OBJ_simpleSecurityObject         0 9 2342 19200300 100 4 19 */
+455,	/* OBJ_pilotOrganization            0 9 2342 19200300 100 4 20 */
+456,	/* OBJ_pilotDSA                     0 9 2342 19200300 100 4 21 */
+457,	/* OBJ_qualityLabelledData          0 9 2342 19200300 100 4 22 */
+936,	/* OBJ_FRP256v1                     1 2 250 1 223 101 256 1 */
+189,	/* OBJ_id_smime_mod                 1 2 840 113549 1 9 16 0 */
+190,	/* OBJ_id_smime_ct                  1 2 840 113549 1 9 16 1 */
+191,	/* OBJ_id_smime_aa                  1 2 840 113549 1 9 16 2 */
+192,	/* OBJ_id_smime_alg                 1 2 840 113549 1 9 16 3 */
+193,	/* OBJ_id_smime_cd                  1 2 840 113549 1 9 16 4 */
+194,	/* OBJ_id_smime_spq                 1 2 840 113549 1 9 16 5 */
+195,	/* OBJ_id_smime_cti                 1 2 840 113549 1 9 16 6 */
+158,	/* OBJ_x509Certificate              1 2 840 113549 1 9 22 1 */
+159,	/* OBJ_sdsiCertificate              1 2 840 113549 1 9 22 2 */
+160,	/* OBJ_x509Crl                      1 2 840 113549 1 9 23 1 */
+144,	/* OBJ_pbe_WithSHA1And128BitRC4     1 2 840 113549 1 12 1 1 */
+145,	/* OBJ_pbe_WithSHA1And40BitRC4      1 2 840 113549 1 12 1 2 */
+146,	/* OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC 1 2 840 113549 1 12 1 3 */
+147,	/* OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC 1 2 840 113549 1 12 1 4 */
+148,	/* OBJ_pbe_WithSHA1And128BitRC2_CBC 1 2 840 113549 1 12 1 5 */
+149,	/* OBJ_pbe_WithSHA1And40BitRC2_CBC  1 2 840 113549 1 12 1 6 */
+171,	/* OBJ_ms_ext_req                   1 3 6 1 4 1 311 2 1 14 */
+134,	/* OBJ_ms_code_ind                  1 3 6 1 4 1 311 2 1 21 */
+135,	/* OBJ_ms_code_com                  1 3 6 1 4 1 311 2 1 22 */
+136,	/* OBJ_ms_ctl_sign                  1 3 6 1 4 1 311 10 3 1 */
+137,	/* OBJ_ms_sgc                       1 3 6 1 4 1 311 10 3 3 */
+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 */
+1018,	/* OBJ_ct_precert_scts              1 3 6 1 4 1 11129 2 4 2 */
+1019,	/* OBJ_ct_precert_poison            1 3 6 1 4 1 11129 2 4 3 */
+1020,	/* OBJ_ct_precert_signer            1 3 6 1 4 1 11129 2 4 4 */
+1021,	/* OBJ_ct_cert_scts                 1 3 6 1 4 1 11129 2 4 5 */
+751,	/* OBJ_camellia_128_cbc             1 2 392 200011 61 1 1 1 2 */
+752,	/* OBJ_camellia_192_cbc             1 2 392 200011 61 1 1 1 3 */
+753,	/* OBJ_camellia_256_cbc             1 2 392 200011 61 1 1 1 4 */
+907,	/* OBJ_id_camellia128_wrap          1 2 392 200011 61 1 1 3 2 */
+908,	/* OBJ_id_camellia192_wrap          1 2 392 200011 61 1 1 3 3 */
+909,	/* OBJ_id_camellia256_wrap          1 2 392 200011 61 1 1 3 4 */
+196,	/* OBJ_id_smime_mod_cms             1 2 840 113549 1 9 16 0 1 */
+197,	/* OBJ_id_smime_mod_ess             1 2 840 113549 1 9 16 0 2 */
+198,	/* OBJ_id_smime_mod_oid             1 2 840 113549 1 9 16 0 3 */
+199,	/* OBJ_id_smime_mod_msg_v3          1 2 840 113549 1 9 16 0 4 */
+200,	/* OBJ_id_smime_mod_ets_eSignature_88 1 2 840 113549 1 9 16 0 5 */
+201,	/* OBJ_id_smime_mod_ets_eSignature_97 1 2 840 113549 1 9 16 0 6 */
+202,	/* OBJ_id_smime_mod_ets_eSigPolicy_88 1 2 840 113549 1 9 16 0 7 */
+203,	/* OBJ_id_smime_mod_ets_eSigPolicy_97 1 2 840 113549 1 9 16 0 8 */
+204,	/* OBJ_id_smime_ct_receipt          1 2 840 113549 1 9 16 1 1 */
+205,	/* OBJ_id_smime_ct_authData         1 2 840 113549 1 9 16 1 2 */
+206,	/* OBJ_id_smime_ct_publishCert      1 2 840 113549 1 9 16 1 3 */
+207,	/* OBJ_id_smime_ct_TSTInfo          1 2 840 113549 1 9 16 1 4 */
+208,	/* OBJ_id_smime_ct_TDTInfo          1 2 840 113549 1 9 16 1 5 */
+209,	/* OBJ_id_smime_ct_contentInfo      1 2 840 113549 1 9 16 1 6 */
+210,	/* OBJ_id_smime_ct_DVCSRequestData  1 2 840 113549 1 9 16 1 7 */
+211,	/* OBJ_id_smime_ct_DVCSResponseData 1 2 840 113549 1 9 16 1 8 */
+786,	/* OBJ_id_smime_ct_compressedData   1 2 840 113549 1 9 16 1 9 */
+1001,	/* OBJ_id_ct_routeOriginAuthz       1 2 840 113549 1 9 16 1 24 */
+1002,	/* 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 */
+1003,	/* OBJ_id_ct_rpkiGhostbusters       1 2 840 113549 1 9 16 1 35 */
+1004,	/* OBJ_id_ct_resourceTaggedAttest   1 2 840 113549 1 9 16 1 36 */
+1013,	/* OBJ_id_ct_geofeedCSVwithCRLF     1 2 840 113549 1 9 16 1 47 */
+1014,	/* OBJ_id_ct_signedChecklist        1 2 840 113549 1 9 16 1 48 */
+1017,	/* OBJ_id_ct_ASPA                   1 2 840 113549 1 9 16 1 49 */
+1024,	/* OBJ_id_ct_signedTAL              1 2 840 113549 1 9 16 1 50 */
+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 */
+215,	/* OBJ_id_smime_aa_contentHint      1 2 840 113549 1 9 16 2 4 */
+216,	/* OBJ_id_smime_aa_msgSigDigest     1 2 840 113549 1 9 16 2 5 */
+217,	/* OBJ_id_smime_aa_encapContentType 1 2 840 113549 1 9 16 2 6 */
+218,	/* OBJ_id_smime_aa_contentIdentifier 1 2 840 113549 1 9 16 2 7 */
+219,	/* OBJ_id_smime_aa_macValue         1 2 840 113549 1 9 16 2 8 */
+220,	/* OBJ_id_smime_aa_equivalentLabels 1 2 840 113549 1 9 16 2 9 */
+221,	/* OBJ_id_smime_aa_contentReference 1 2 840 113549 1 9 16 2 10 */
+222,	/* OBJ_id_smime_aa_encrypKeyPref    1 2 840 113549 1 9 16 2 11 */
+223,	/* OBJ_id_smime_aa_signingCertificate 1 2 840 113549 1 9 16 2 12 */
+224,	/* OBJ_id_smime_aa_smimeEncryptCerts 1 2 840 113549 1 9 16 2 13 */
+225,	/* OBJ_id_smime_aa_timeStampToken   1 2 840 113549 1 9 16 2 14 */
+226,	/* OBJ_id_smime_aa_ets_sigPolicyId  1 2 840 113549 1 9 16 2 15 */
+227,	/* OBJ_id_smime_aa_ets_commitmentType 1 2 840 113549 1 9 16 2 16 */
+228,	/* OBJ_id_smime_aa_ets_signerLocation 1 2 840 113549 1 9 16 2 17 */
+229,	/* OBJ_id_smime_aa_ets_signerAttr   1 2 840 113549 1 9 16 2 18 */
+230,	/* OBJ_id_smime_aa_ets_otherSigCert 1 2 840 113549 1 9 16 2 19 */
+231,	/* OBJ_id_smime_aa_ets_contentTimestamp 1 2 840 113549 1 9 16 2 20 */
+232,	/* OBJ_id_smime_aa_ets_CertificateRefs 1 2 840 113549 1 9 16 2 21 */
+233,	/* OBJ_id_smime_aa_ets_RevocationRefs 1 2 840 113549 1 9 16 2 22 */
+234,	/* OBJ_id_smime_aa_ets_certValues   1 2 840 113549 1 9 16 2 23 */
+235,	/* OBJ_id_smime_aa_ets_revocationValues 1 2 840 113549 1 9 16 2 24 */
+236,	/* OBJ_id_smime_aa_ets_escTimeStamp 1 2 840 113549 1 9 16 2 25 */
+237,	/* OBJ_id_smime_aa_ets_certCRLTimestamp 1 2 840 113549 1 9 16 2 26 */
+238,	/* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */
+239,	/* OBJ_id_smime_aa_signatureType    1 2 840 113549 1 9 16 2 28 */
+240,	/* OBJ_id_smime_aa_dvcs_dvc         1 2 840 113549 1 9 16 2 29 */
+1023,	/* OBJ_id_smime_aa_signingCertificateV2 1 2 840 113549 1 9 16 2 47 */
+241,	/* OBJ_id_smime_alg_ESDHwith3DES    1 2 840 113549 1 9 16 3 1 */
+242,	/* OBJ_id_smime_alg_ESDHwithRC2     1 2 840 113549 1 9 16 3 2 */
+243,	/* OBJ_id_smime_alg_3DESwrap        1 2 840 113549 1 9 16 3 3 */
+244,	/* OBJ_id_smime_alg_RC2wrap         1 2 840 113549 1 9 16 3 4 */
+245,	/* OBJ_id_smime_alg_ESDH            1 2 840 113549 1 9 16 3 5 */
+246,	/* OBJ_id_smime_alg_CMS3DESwrap     1 2 840 113549 1 9 16 3 6 */
+247,	/* OBJ_id_smime_alg_CMSRC2wrap      1 2 840 113549 1 9 16 3 7 */
+125,	/* OBJ_zlib_compression             1 2 840 113549 1 9 16 3 8 */
+893,	/* OBJ_id_alg_PWRI_KEK              1 2 840 113549 1 9 16 3 9 */
+248,	/* OBJ_id_smime_cd_ldap             1 2 840 113549 1 9 16 4 1 */
+249,	/* OBJ_id_smime_spq_ets_sqt_uri     1 2 840 113549 1 9 16 5 1 */
+250,	/* OBJ_id_smime_spq_ets_sqt_unotice 1 2 840 113549 1 9 16 5 2 */
+251,	/* OBJ_id_smime_cti_ets_proofOfOrigin 1 2 840 113549 1 9 16 6 1 */
+252,	/* OBJ_id_smime_cti_ets_proofOfReceipt 1 2 840 113549 1 9 16 6 2 */
+253,	/* OBJ_id_smime_cti_ets_proofOfDelivery 1 2 840 113549 1 9 16 6 3 */
+254,	/* OBJ_id_smime_cti_ets_proofOfSender 1 2 840 113549 1 9 16 6 4 */
+255,	/* OBJ_id_smime_cti_ets_proofOfApproval 1 2 840 113549 1 9 16 6 5 */
+256,	/* OBJ_id_smime_cti_ets_proofOfCreation 1 2 840 113549 1 9 16 6 6 */
+150,	/* OBJ_keyBag                       1 2 840 113549 1 12 10 1 1 */
+151,	/* OBJ_pkcs8ShroudedKeyBag          1 2 840 113549 1 12 10 1 2 */
+152,	/* OBJ_certBag                      1 2 840 113549 1 12 10 1 3 */
+153,	/* OBJ_crlBag                       1 2 840 113549 1 12 10 1 4 */
+154,	/* OBJ_secretBag                    1 2 840 113549 1 12 10 1 5 */
+155,	/* OBJ_safeContentsBag              1 2 840 113549 1 12 10 1 6 */
+34,	/* OBJ_idea_cbc                     1 3 6 1 4 1 188 7 1 1 2 */
+956,	/* OBJ_jurisdictionLocalityName     1 3 6 1 4 1 311 60 2 1 1 */
+957,	/* OBJ_jurisdictionStateOrProvinceName 1 3 6 1 4 1 311 60 2 1 2 */
+958,	/* OBJ_jurisdictionCountryName      1 3 6 1 4 1 311 60 2 1 3 */
+};
+
diff --git a/crypto/objects/obj_err.c b/crypto/objects/obj_err.c
new file mode 100644
index 0000000..04cb421
--- /dev/null
+++ b/crypto/objects/obj_err.c
@@ -0,0 +1,91 @@
+/* $OpenBSD: obj_err.c,v 1.14 2023/07/08 12:27:51 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_OBJ,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_OBJ,0,reason)
+
+static ERR_STRING_DATA OBJ_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA OBJ_str_reasons[] = {
+	{ERR_REASON(OBJ_R_MALLOC_FAILURE)        , "malloc failure"},
+	{ERR_REASON(OBJ_R_UNKNOWN_NID)           , "unknown nid"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_OBJ_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(OBJ_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, OBJ_str_functs);
+		ERR_load_strings(0, OBJ_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_OBJ_strings);
diff --git a/crypto/objects/obj_lib.c b/crypto/objects/obj_lib.c
new file mode 100644
index 0000000..45062db
--- /dev/null
+++ b/crypto/objects/obj_lib.c
@@ -0,0 +1,135 @@
+/* $OpenBSD: obj_lib.c,v 1.19 2023/08/17 09:13:01 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+
+ASN1_OBJECT *
+OBJ_dup(const ASN1_OBJECT *o)
+{
+	ASN1_OBJECT *r;
+	char *ln = NULL, *sn = NULL;
+	unsigned char *data = NULL;
+
+	if (o == NULL)
+		return (NULL);
+	if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC))
+		return((ASN1_OBJECT *)o); /* XXX: ugh! Why? What kind of
+					     duplication is this??? */
+
+	r = ASN1_OBJECT_new();
+	if (r == NULL) {
+		OBJerror(ERR_R_ASN1_LIB);
+		return (NULL);
+	}
+	data = malloc(o->length);
+	if (data == NULL)
+		goto err;
+	if (o->data != NULL)
+		memcpy(data, o->data, o->length);
+	/* once data attached to object it remains const */
+	r->data = data;
+	r->length = o->length;
+	r->nid = o->nid;
+	r->ln = r->sn = NULL;
+	if (o->ln != NULL) {
+		ln = strdup(o->ln);
+		if (ln == NULL)
+			goto err;
+		r->ln = ln;
+	}
+
+	if (o->sn != NULL) {
+		sn = strdup(o->sn);
+		if (sn == NULL)
+			goto err;
+		r->sn = sn;
+	}
+	r->flags = o->flags | (ASN1_OBJECT_FLAG_DYNAMIC |
+	    ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA);
+	return (r);
+
+ err:
+	OBJerror(ERR_R_MALLOC_FAILURE);
+	free(ln);
+	free(sn);
+	free(data);
+	free(r);
+	return (NULL);
+}
+LCRYPTO_ALIAS(OBJ_dup);
+
+int
+OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b)
+{
+	int cmp;
+
+	if ((cmp = a->length - b->length) != 0)
+		return cmp;
+	if (a->length == 0)
+		return 0;
+	return memcmp(a->data, b->data, a->length);
+}
+LCRYPTO_ALIAS(OBJ_cmp);
diff --git a/crypto/objects/obj_xref.c b/crypto/objects/obj_xref.c
new file mode 100644
index 0000000..0fca228
--- /dev/null
+++ b/crypto/objects/obj_xref.c
@@ -0,0 +1,312 @@
+/*	$OpenBSD: obj_xref.c,v 1.13 2023/07/28 10:25:05 tb Exp $ */
+
+/*
+ * Copyright (c) 2023 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+/*
+ * Map between signature nids and pairs of (hash, pkey) nids. If the hash nid
+ * is NID_undef, this indicates to ASN1_item_{sign,verify}() that the pkey's
+ * ASN.1 method needs to handle algorithm identifiers and part of the message
+ * digest.
+ */
+
+static const struct {
+	int sign_nid;
+	int hash_nid;
+	int pkey_nid;
+} nid_triple[] = {
+	{
+		.sign_nid = NID_md2WithRSAEncryption,
+		.hash_nid = NID_md2,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_md5WithRSAEncryption,
+		.hash_nid = NID_md5,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_shaWithRSAEncryption,
+		.hash_nid = NID_sha,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_sha1WithRSAEncryption,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_dsaWithSHA,
+		.hash_nid = NID_sha,
+		.pkey_nid = NID_dsa,
+	},
+	{
+		.sign_nid = NID_dsaWithSHA1_2,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_dsa_2,
+	},
+	{
+		.sign_nid = NID_mdc2WithRSA,
+		.hash_nid = NID_mdc2,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_md5WithRSA,
+		.hash_nid = NID_md5,
+		.pkey_nid = NID_rsa,
+	},
+	{
+		.sign_nid = NID_dsaWithSHA1,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_dsa,
+	},
+	{
+		.sign_nid = NID_sha1WithRSA,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_rsa,
+	},
+	{
+		.sign_nid = NID_ripemd160WithRSA,
+		.hash_nid = NID_ripemd160,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_md4WithRSAEncryption,
+		.hash_nid = NID_md4,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_SHA1,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_sha256WithRSAEncryption,
+		.hash_nid = NID_sha256,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_sha384WithRSAEncryption,
+		.hash_nid = NID_sha384,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_sha512WithRSAEncryption,
+		.hash_nid = NID_sha512,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_sha224WithRSAEncryption,
+		.hash_nid = NID_sha224,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_Recommended,
+		.hash_nid = NID_undef,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_Specified,
+		.hash_nid = NID_undef,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_SHA224,
+		.hash_nid = NID_sha224,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_SHA256,
+		.hash_nid = NID_sha256,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_SHA384,
+		.hash_nid = NID_sha384,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_ecdsa_with_SHA512,
+		.hash_nid = NID_sha512,
+		.pkey_nid = NID_X9_62_id_ecPublicKey,
+	},
+	{
+		.sign_nid = NID_dsa_with_SHA224,
+		.hash_nid = NID_sha224,
+		.pkey_nid = NID_dsa,
+	},
+	{
+		.sign_nid = NID_dsa_with_SHA256,
+		.hash_nid = NID_sha256,
+		.pkey_nid = NID_dsa,
+	},
+	{
+		.sign_nid = NID_id_GostR3411_94_with_GostR3410_2001,
+		.hash_nid = NID_id_GostR3411_94,
+		.pkey_nid = NID_id_GostR3410_2001,
+	},
+	{
+		.sign_nid = NID_id_GostR3411_94_with_GostR3410_94,
+		.hash_nid = NID_id_GostR3411_94,
+		.pkey_nid = NID_id_GostR3410_94,
+	},
+	{
+		.sign_nid = NID_id_GostR3411_94_with_GostR3410_94_cc,
+		.hash_nid = NID_id_GostR3411_94,
+		.pkey_nid = NID_id_GostR3410_94_cc,
+	},
+	{
+		.sign_nid = NID_id_GostR3411_94_with_GostR3410_2001_cc,
+		.hash_nid = NID_id_GostR3411_94,
+		.pkey_nid = NID_id_GostR3410_2001_cc,
+	},
+	{
+		.sign_nid = NID_rsassaPss,
+		.hash_nid = NID_undef,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_id_tc26_signwithdigest_gost3410_2012_256,
+		.hash_nid = NID_id_tc26_gost3411_2012_256,
+		.pkey_nid = NID_id_GostR3410_2001,
+	},
+	{
+		.sign_nid = NID_id_tc26_signwithdigest_gost3410_2012_512,
+		.hash_nid = NID_id_tc26_gost3411_2012_512,
+		.pkey_nid = NID_id_GostR3410_2001,
+	},
+	{
+		.sign_nid = NID_Ed25519,
+		.hash_nid = NID_undef,
+		.pkey_nid = NID_Ed25519,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_stdDH_sha1kdf_scheme,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_dh_std_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_stdDH_sha224kdf_scheme,
+		.hash_nid = NID_sha224,
+		.pkey_nid = NID_dh_std_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_stdDH_sha256kdf_scheme,
+		.hash_nid = NID_sha256,
+		.pkey_nid = NID_dh_std_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_stdDH_sha384kdf_scheme,
+		.hash_nid = NID_sha384,
+		.pkey_nid = NID_dh_std_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_stdDH_sha512kdf_scheme,
+		.hash_nid = NID_sha512,
+		.pkey_nid = NID_dh_std_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_cofactorDH_sha1kdf_scheme,
+		.hash_nid = NID_sha1,
+		.pkey_nid = NID_dh_cofactor_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_cofactorDH_sha224kdf_scheme,
+		.hash_nid = NID_sha224,
+		.pkey_nid = NID_dh_cofactor_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_cofactorDH_sha256kdf_scheme,
+		.hash_nid = NID_sha256,
+		.pkey_nid = NID_dh_cofactor_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_cofactorDH_sha384kdf_scheme,
+		.hash_nid = NID_sha384,
+		.pkey_nid = NID_dh_cofactor_kdf,
+	},
+	{
+		.sign_nid = NID_dhSinglePass_cofactorDH_sha512kdf_scheme,
+		.hash_nid = NID_sha512,
+		.pkey_nid = NID_dh_cofactor_kdf,
+	},
+	{
+		.sign_nid = NID_RSA_SHA3_224,
+		.hash_nid = NID_sha3_224,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_RSA_SHA3_256,
+		.hash_nid = NID_sha3_256,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_RSA_SHA3_384,
+		.hash_nid = NID_sha3_384,
+		.pkey_nid = NID_rsaEncryption,
+	},
+	{
+		.sign_nid = NID_RSA_SHA3_512,
+		.hash_nid = NID_sha3_512,
+		.pkey_nid = NID_rsaEncryption,
+	},
+};
+
+#define N_NID_TRIPLES (sizeof(nid_triple) / sizeof(nid_triple[0]))
+
+int
+OBJ_find_sigid_algs(int sign_nid, int *hash_nid, int *pkey_nid)
+{
+	size_t i;
+
+	for (i = 0; i < N_NID_TRIPLES; i++) {
+		if (sign_nid != nid_triple[i].sign_nid)
+			continue;
+
+		if (hash_nid != NULL)
+			*hash_nid = nid_triple[i].hash_nid;
+		if (pkey_nid != NULL)
+			*pkey_nid = nid_triple[i].pkey_nid;
+
+		return 1;
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(OBJ_find_sigid_algs);
+
+int
+OBJ_find_sigid_by_algs(int *sign_nid, int hash_nid, int pkey_nid)
+{
+	size_t i;
+
+	for (i = 0; i < N_NID_TRIPLES; i++) {
+		if (hash_nid != nid_triple[i].hash_nid)
+			continue;
+		if (pkey_nid != nid_triple[i].pkey_nid)
+			continue;
+
+		if (sign_nid != NULL)
+			*sign_nid = nid_triple[i].sign_nid;
+
+		return 1;
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(OBJ_find_sigid_by_algs);
diff --git a/crypto/ocsp/ocsp_asn.c b/crypto/ocsp/ocsp_asn.c
new file mode 100644
index 0000000..4fbdd5f
--- /dev/null
+++ b/crypto/ocsp/ocsp_asn.c
@@ -0,0 +1,1051 @@
+/* $OpenBSD: ocsp_asn.c,v 1.11 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+
+static const ASN1_TEMPLATE OCSP_SIGNATURE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SIGNATURE, signatureAlgorithm),
+		.field_name = "signatureAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SIGNATURE, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_SIGNATURE, certs),
+		.field_name = "certs",
+		.item = &X509_it,
+	},
+};
+
+const ASN1_ITEM OCSP_SIGNATURE_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_SIGNATURE_seq_tt,
+	.tcount = sizeof(OCSP_SIGNATURE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_SIGNATURE),
+	.sname = "OCSP_SIGNATURE",
+};
+
+
+OCSP_SIGNATURE *
+d2i_OCSP_SIGNATURE(OCSP_SIGNATURE **a, const unsigned char **in, long len)
+{
+	return (OCSP_SIGNATURE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_SIGNATURE_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_SIGNATURE);
+
+int
+i2d_OCSP_SIGNATURE(OCSP_SIGNATURE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_SIGNATURE_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_SIGNATURE);
+
+OCSP_SIGNATURE *
+OCSP_SIGNATURE_new(void)
+{
+	return (OCSP_SIGNATURE *)ASN1_item_new(&OCSP_SIGNATURE_it);
+}
+LCRYPTO_ALIAS(OCSP_SIGNATURE_new);
+
+void
+OCSP_SIGNATURE_free(OCSP_SIGNATURE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_SIGNATURE_it);
+}
+LCRYPTO_ALIAS(OCSP_SIGNATURE_free);
+
+static const ASN1_TEMPLATE OCSP_CERTID_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_CERTID, hashAlgorithm),
+		.field_name = "hashAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_CERTID, issuerNameHash),
+		.field_name = "issuerNameHash",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_CERTID, issuerKeyHash),
+		.field_name = "issuerKeyHash",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_CERTID, serialNumber),
+		.field_name = "serialNumber",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM OCSP_CERTID_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_CERTID_seq_tt,
+	.tcount = sizeof(OCSP_CERTID_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_CERTID),
+	.sname = "OCSP_CERTID",
+};
+
+
+OCSP_CERTID *
+d2i_OCSP_CERTID(OCSP_CERTID **a, const unsigned char **in, long len)
+{
+	return (OCSP_CERTID *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_CERTID_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_CERTID);
+
+int
+i2d_OCSP_CERTID(OCSP_CERTID *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_CERTID_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_CERTID);
+
+OCSP_CERTID *
+OCSP_CERTID_new(void)
+{
+	return (OCSP_CERTID *)ASN1_item_new(&OCSP_CERTID_it);
+}
+LCRYPTO_ALIAS(OCSP_CERTID_new);
+
+void
+OCSP_CERTID_free(OCSP_CERTID *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_CERTID_it);
+}
+LCRYPTO_ALIAS(OCSP_CERTID_free);
+
+static const ASN1_TEMPLATE OCSP_ONEREQ_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_ONEREQ, reqCert),
+		.field_name = "reqCert",
+		.item = &OCSP_CERTID_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_ONEREQ, singleRequestExtensions),
+		.field_name = "singleRequestExtensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM OCSP_ONEREQ_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_ONEREQ_seq_tt,
+	.tcount = sizeof(OCSP_ONEREQ_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_ONEREQ),
+	.sname = "OCSP_ONEREQ",
+};
+
+
+OCSP_ONEREQ *
+d2i_OCSP_ONEREQ(OCSP_ONEREQ **a, const unsigned char **in, long len)
+{
+	return (OCSP_ONEREQ *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_ONEREQ_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_ONEREQ);
+
+int
+i2d_OCSP_ONEREQ(OCSP_ONEREQ *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_ONEREQ_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_ONEREQ);
+
+OCSP_ONEREQ *
+OCSP_ONEREQ_new(void)
+{
+	return (OCSP_ONEREQ *)ASN1_item_new(&OCSP_ONEREQ_it);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_new);
+
+void
+OCSP_ONEREQ_free(OCSP_ONEREQ *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_ONEREQ_it);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_free);
+
+static const ASN1_TEMPLATE OCSP_REQINFO_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_REQINFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(OCSP_REQINFO, requestorName),
+		.field_name = "requestorName",
+		.item = &GENERAL_NAME_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(OCSP_REQINFO, requestList),
+		.field_name = "requestList",
+		.item = &OCSP_ONEREQ_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(OCSP_REQINFO, requestExtensions),
+		.field_name = "requestExtensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM OCSP_REQINFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_REQINFO_seq_tt,
+	.tcount = sizeof(OCSP_REQINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_REQINFO),
+	.sname = "OCSP_REQINFO",
+};
+
+
+OCSP_REQINFO *
+d2i_OCSP_REQINFO(OCSP_REQINFO **a, const unsigned char **in, long len)
+{
+	return (OCSP_REQINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_REQINFO_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_REQINFO);
+
+int
+i2d_OCSP_REQINFO(OCSP_REQINFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_REQINFO_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_REQINFO);
+
+OCSP_REQINFO *
+OCSP_REQINFO_new(void)
+{
+	return (OCSP_REQINFO *)ASN1_item_new(&OCSP_REQINFO_it);
+}
+LCRYPTO_ALIAS(OCSP_REQINFO_new);
+
+void
+OCSP_REQINFO_free(OCSP_REQINFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_REQINFO_it);
+}
+LCRYPTO_ALIAS(OCSP_REQINFO_free);
+
+static const ASN1_TEMPLATE OCSP_REQUEST_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_REQUEST, tbsRequest),
+		.field_name = "tbsRequest",
+		.item = &OCSP_REQINFO_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_REQUEST, optionalSignature),
+		.field_name = "optionalSignature",
+		.item = &OCSP_SIGNATURE_it,
+	},
+};
+
+const ASN1_ITEM OCSP_REQUEST_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_REQUEST_seq_tt,
+	.tcount = sizeof(OCSP_REQUEST_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_REQUEST),
+	.sname = "OCSP_REQUEST",
+};
+
+OCSP_REQUEST *
+d2i_OCSP_REQUEST(OCSP_REQUEST **a, const unsigned char **in, long len)
+{
+	return (OCSP_REQUEST *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_REQUEST_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_REQUEST);
+
+int
+i2d_OCSP_REQUEST(OCSP_REQUEST *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_REQUEST_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_REQUEST);
+
+OCSP_REQUEST *
+d2i_OCSP_REQUEST_bio(BIO *bp, OCSP_REQUEST **a)
+{
+	return ASN1_item_d2i_bio(&OCSP_REQUEST_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_OCSP_REQUEST_bio);
+
+int
+i2d_OCSP_REQUEST_bio(BIO *bp, OCSP_REQUEST *a)
+{
+	return ASN1_item_i2d_bio(&OCSP_REQUEST_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_OCSP_REQUEST_bio);
+
+OCSP_REQUEST *
+OCSP_REQUEST_new(void)
+{
+	return (OCSP_REQUEST *)ASN1_item_new(&OCSP_REQUEST_it);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_new);
+
+void
+OCSP_REQUEST_free(OCSP_REQUEST *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_REQUEST_it);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_free);
+
+/* OCSP_RESPONSE templates */
+
+static const ASN1_TEMPLATE OCSP_RESPBYTES_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPBYTES, responseType),
+		.field_name = "responseType",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPBYTES, response),
+		.field_name = "response",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM OCSP_RESPBYTES_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_RESPBYTES_seq_tt,
+	.tcount = sizeof(OCSP_RESPBYTES_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_RESPBYTES),
+	.sname = "OCSP_RESPBYTES",
+};
+
+
+OCSP_RESPBYTES *
+d2i_OCSP_RESPBYTES(OCSP_RESPBYTES **a, const unsigned char **in, long len)
+{
+	return (OCSP_RESPBYTES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_RESPBYTES_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_RESPBYTES);
+
+int
+i2d_OCSP_RESPBYTES(OCSP_RESPBYTES *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_RESPBYTES_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_RESPBYTES);
+
+OCSP_RESPBYTES *
+OCSP_RESPBYTES_new(void)
+{
+	return (OCSP_RESPBYTES *)ASN1_item_new(&OCSP_RESPBYTES_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPBYTES_new);
+
+void
+OCSP_RESPBYTES_free(OCSP_RESPBYTES *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_RESPBYTES_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPBYTES_free);
+
+static const ASN1_TEMPLATE OCSP_RESPONSE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPONSE, responseStatus),
+		.field_name = "responseStatus",
+		.item = &ASN1_ENUMERATED_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPONSE, responseBytes),
+		.field_name = "responseBytes",
+		.item = &OCSP_RESPBYTES_it,
+	},
+};
+
+const ASN1_ITEM OCSP_RESPONSE_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_RESPONSE_seq_tt,
+	.tcount = sizeof(OCSP_RESPONSE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_RESPONSE),
+	.sname = "OCSP_RESPONSE",
+};
+
+
+OCSP_RESPONSE *
+d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len)
+{
+	return (OCSP_RESPONSE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_RESPONSE_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_RESPONSE);
+
+int
+i2d_OCSP_RESPONSE(OCSP_RESPONSE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_RESPONSE_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_RESPONSE);
+
+OCSP_RESPONSE *
+d2i_OCSP_RESPONSE_bio(BIO *bp, OCSP_RESPONSE **a)
+{
+	return ASN1_item_d2i_bio(&OCSP_RESPONSE_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_OCSP_RESPONSE_bio);
+
+int
+i2d_OCSP_RESPONSE_bio(BIO *bp, OCSP_RESPONSE *a)
+{
+	return ASN1_item_i2d_bio(&OCSP_RESPONSE_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_OCSP_RESPONSE_bio);
+
+OCSP_RESPONSE *
+OCSP_RESPONSE_new(void)
+{
+	return (OCSP_RESPONSE *)ASN1_item_new(&OCSP_RESPONSE_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPONSE_new);
+
+void
+OCSP_RESPONSE_free(OCSP_RESPONSE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_RESPONSE_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPONSE_free);
+
+static const ASN1_TEMPLATE OCSP_RESPID_ch_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT,
+		.tag = 1,
+		.offset = offsetof(OCSP_RESPID, value.byName),
+		.field_name = "value.byName",
+		.item = &X509_NAME_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT,
+		.tag = 2,
+		.offset = offsetof(OCSP_RESPID, value.byKey),
+		.field_name = "value.byKey",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM OCSP_RESPID_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(OCSP_RESPID, type),
+	.templates = OCSP_RESPID_ch_tt,
+	.tcount = sizeof(OCSP_RESPID_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_RESPID),
+	.sname = "OCSP_RESPID",
+};
+
+
+OCSP_RESPID *
+d2i_OCSP_RESPID(OCSP_RESPID **a, const unsigned char **in, long len)
+{
+	return (OCSP_RESPID *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_RESPID_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_RESPID);
+
+int
+i2d_OCSP_RESPID(OCSP_RESPID *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_RESPID_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_RESPID);
+
+OCSP_RESPID *
+OCSP_RESPID_new(void)
+{
+	return (OCSP_RESPID *)ASN1_item_new(&OCSP_RESPID_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPID_new);
+
+void
+OCSP_RESPID_free(OCSP_RESPID *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_RESPID_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPID_free);
+
+static const ASN1_TEMPLATE OCSP_REVOKEDINFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_REVOKEDINFO, revocationTime),
+		.field_name = "revocationTime",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_REVOKEDINFO, revocationReason),
+		.field_name = "revocationReason",
+		.item = &ASN1_ENUMERATED_it,
+	},
+};
+
+const ASN1_ITEM OCSP_REVOKEDINFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_REVOKEDINFO_seq_tt,
+	.tcount = sizeof(OCSP_REVOKEDINFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_REVOKEDINFO),
+	.sname = "OCSP_REVOKEDINFO",
+};
+
+
+OCSP_REVOKEDINFO *
+d2i_OCSP_REVOKEDINFO(OCSP_REVOKEDINFO **a, const unsigned char **in, long len)
+{
+	return (OCSP_REVOKEDINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_REVOKEDINFO_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_REVOKEDINFO);
+
+int
+i2d_OCSP_REVOKEDINFO(OCSP_REVOKEDINFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_REVOKEDINFO_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_REVOKEDINFO);
+
+OCSP_REVOKEDINFO *
+OCSP_REVOKEDINFO_new(void)
+{
+	return (OCSP_REVOKEDINFO *)ASN1_item_new(&OCSP_REVOKEDINFO_it);
+}
+LCRYPTO_ALIAS(OCSP_REVOKEDINFO_new);
+
+void
+OCSP_REVOKEDINFO_free(OCSP_REVOKEDINFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_REVOKEDINFO_it);
+}
+LCRYPTO_ALIAS(OCSP_REVOKEDINFO_free);
+
+static const ASN1_TEMPLATE OCSP_CERTSTATUS_ch_tt[] = {
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 0,
+		.offset = offsetof(OCSP_CERTSTATUS, value.good),
+		.field_name = "value.good",
+		.item = &ASN1_NULL_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 1,
+		.offset = offsetof(OCSP_CERTSTATUS, value.revoked),
+		.field_name = "value.revoked",
+		.item = &OCSP_REVOKEDINFO_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT,
+		.tag = 2,
+		.offset = offsetof(OCSP_CERTSTATUS, value.unknown),
+		.field_name = "value.unknown",
+		.item = &ASN1_NULL_it,
+	},
+};
+
+const ASN1_ITEM OCSP_CERTSTATUS_it = {
+	.itype = ASN1_ITYPE_CHOICE,
+	.utype = offsetof(OCSP_CERTSTATUS, type),
+	.templates = OCSP_CERTSTATUS_ch_tt,
+	.tcount = sizeof(OCSP_CERTSTATUS_ch_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_CERTSTATUS),
+	.sname = "OCSP_CERTSTATUS",
+};
+
+
+OCSP_CERTSTATUS *
+d2i_OCSP_CERTSTATUS(OCSP_CERTSTATUS **a, const unsigned char **in, long len)
+{
+	return (OCSP_CERTSTATUS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_CERTSTATUS_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_CERTSTATUS);
+
+int
+i2d_OCSP_CERTSTATUS(OCSP_CERTSTATUS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_CERTSTATUS_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_CERTSTATUS);
+
+OCSP_CERTSTATUS *
+OCSP_CERTSTATUS_new(void)
+{
+	return (OCSP_CERTSTATUS *)ASN1_item_new(&OCSP_CERTSTATUS_it);
+}
+LCRYPTO_ALIAS(OCSP_CERTSTATUS_new);
+
+void
+OCSP_CERTSTATUS_free(OCSP_CERTSTATUS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_CERTSTATUS_it);
+}
+LCRYPTO_ALIAS(OCSP_CERTSTATUS_free);
+
+static const ASN1_TEMPLATE OCSP_SINGLERESP_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SINGLERESP, certId),
+		.field_name = "certId",
+		.item = &OCSP_CERTID_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SINGLERESP, certStatus),
+		.field_name = "certStatus",
+		.item = &OCSP_CERTSTATUS_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SINGLERESP, thisUpdate),
+		.field_name = "thisUpdate",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_SINGLERESP, nextUpdate),
+		.field_name = "nextUpdate",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(OCSP_SINGLERESP, singleExtensions),
+		.field_name = "singleExtensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM OCSP_SINGLERESP_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_SINGLERESP_seq_tt,
+	.tcount = sizeof(OCSP_SINGLERESP_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_SINGLERESP),
+	.sname = "OCSP_SINGLERESP",
+};
+
+
+OCSP_SINGLERESP *
+d2i_OCSP_SINGLERESP(OCSP_SINGLERESP **a, const unsigned char **in, long len)
+{
+	return (OCSP_SINGLERESP *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_SINGLERESP_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_SINGLERESP);
+
+int
+i2d_OCSP_SINGLERESP(OCSP_SINGLERESP *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_SINGLERESP_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_SINGLERESP);
+
+OCSP_SINGLERESP *
+OCSP_SINGLERESP_new(void)
+{
+	return (OCSP_SINGLERESP *)ASN1_item_new(&OCSP_SINGLERESP_it);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_new);
+
+void
+OCSP_SINGLERESP_free(OCSP_SINGLERESP *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_SINGLERESP_it);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_free);
+
+static const ASN1_TEMPLATE OCSP_RESPDATA_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPDATA, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPDATA, responderId),
+		.field_name = "responderId",
+		.item = &OCSP_RESPID_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPDATA, producedAt),
+		.field_name = "producedAt",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(OCSP_RESPDATA, responses),
+		.field_name = "responses",
+		.item = &OCSP_SINGLERESP_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(OCSP_RESPDATA, responseExtensions),
+		.field_name = "responseExtensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM OCSP_RESPDATA_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_RESPDATA_seq_tt,
+	.tcount = sizeof(OCSP_RESPDATA_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_RESPDATA),
+	.sname = "OCSP_RESPDATA",
+};
+
+
+OCSP_RESPDATA *
+d2i_OCSP_RESPDATA(OCSP_RESPDATA **a, const unsigned char **in, long len)
+{
+	return (OCSP_RESPDATA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_RESPDATA_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_RESPDATA);
+
+int
+i2d_OCSP_RESPDATA(OCSP_RESPDATA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_RESPDATA_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_RESPDATA);
+
+OCSP_RESPDATA *
+OCSP_RESPDATA_new(void)
+{
+	return (OCSP_RESPDATA *)ASN1_item_new(&OCSP_RESPDATA_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPDATA_new);
+
+void
+OCSP_RESPDATA_free(OCSP_RESPDATA *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_RESPDATA_it);
+}
+LCRYPTO_ALIAS(OCSP_RESPDATA_free);
+
+static const ASN1_TEMPLATE OCSP_BASICRESP_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_BASICRESP, tbsResponseData),
+		.field_name = "tbsResponseData",
+		.item = &OCSP_RESPDATA_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_BASICRESP, signatureAlgorithm),
+		.field_name = "signatureAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_BASICRESP, signature),
+		.field_name = "signature",
+		.item = &ASN1_BIT_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_BASICRESP, certs),
+		.field_name = "certs",
+		.item = &X509_it,
+	},
+};
+
+const ASN1_ITEM OCSP_BASICRESP_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_BASICRESP_seq_tt,
+	.tcount = sizeof(OCSP_BASICRESP_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_BASICRESP),
+	.sname = "OCSP_BASICRESP",
+};
+
+
+OCSP_BASICRESP *
+d2i_OCSP_BASICRESP(OCSP_BASICRESP **a, const unsigned char **in, long len)
+{
+	return (OCSP_BASICRESP *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_BASICRESP_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_BASICRESP);
+
+int
+i2d_OCSP_BASICRESP(OCSP_BASICRESP *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_BASICRESP_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_BASICRESP);
+
+OCSP_BASICRESP *
+OCSP_BASICRESP_new(void)
+{
+	return (OCSP_BASICRESP *)ASN1_item_new(&OCSP_BASICRESP_it);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_new);
+
+void
+OCSP_BASICRESP_free(OCSP_BASICRESP *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_BASICRESP_it);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_free);
+
+static const ASN1_TEMPLATE OCSP_CRLID_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_CRLID, crlUrl),
+		.field_name = "crlUrl",
+		.item = &ASN1_IA5STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(OCSP_CRLID, crlNum),
+		.field_name = "crlNum",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(OCSP_CRLID, crlTime),
+		.field_name = "crlTime",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+};
+
+const ASN1_ITEM OCSP_CRLID_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_CRLID_seq_tt,
+	.tcount = sizeof(OCSP_CRLID_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_CRLID),
+	.sname = "OCSP_CRLID",
+};
+
+
+OCSP_CRLID *
+d2i_OCSP_CRLID(OCSP_CRLID **a, const unsigned char **in, long len)
+{
+	return (OCSP_CRLID *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_CRLID_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_CRLID);
+
+int
+i2d_OCSP_CRLID(OCSP_CRLID *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_CRLID_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_CRLID);
+
+OCSP_CRLID *
+OCSP_CRLID_new(void)
+{
+	return (OCSP_CRLID *)ASN1_item_new(&OCSP_CRLID_it);
+}
+LCRYPTO_ALIAS(OCSP_CRLID_new);
+
+void
+OCSP_CRLID_free(OCSP_CRLID *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_CRLID_it);
+}
+LCRYPTO_ALIAS(OCSP_CRLID_free);
+
+static const ASN1_TEMPLATE OCSP_SERVICELOC_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(OCSP_SERVICELOC, issuer),
+		.field_name = "issuer",
+		.item = &X509_NAME_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(OCSP_SERVICELOC, locator),
+		.field_name = "locator",
+		.item = &ACCESS_DESCRIPTION_it,
+	},
+};
+
+const ASN1_ITEM OCSP_SERVICELOC_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = OCSP_SERVICELOC_seq_tt,
+	.tcount = sizeof(OCSP_SERVICELOC_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(OCSP_SERVICELOC),
+	.sname = "OCSP_SERVICELOC",
+};
+
+
+OCSP_SERVICELOC *
+d2i_OCSP_SERVICELOC(OCSP_SERVICELOC **a, const unsigned char **in, long len)
+{
+	return (OCSP_SERVICELOC *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &OCSP_SERVICELOC_it);
+}
+LCRYPTO_ALIAS(d2i_OCSP_SERVICELOC);
+
+int
+i2d_OCSP_SERVICELOC(OCSP_SERVICELOC *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &OCSP_SERVICELOC_it);
+}
+LCRYPTO_ALIAS(i2d_OCSP_SERVICELOC);
+
+OCSP_SERVICELOC *
+OCSP_SERVICELOC_new(void)
+{
+	return (OCSP_SERVICELOC *)ASN1_item_new(&OCSP_SERVICELOC_it);
+}
+LCRYPTO_ALIAS(OCSP_SERVICELOC_new);
+
+void
+OCSP_SERVICELOC_free(OCSP_SERVICELOC *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &OCSP_SERVICELOC_it);
+}
+LCRYPTO_ALIAS(OCSP_SERVICELOC_free);
diff --git a/crypto/ocsp/ocsp_cl.c b/crypto/ocsp/ocsp_cl.c
new file mode 100644
index 0000000..89113f7
--- /dev/null
+++ b/crypto/ocsp/ocsp_cl.c
@@ -0,0 +1,469 @@
+/* $OpenBSD: ocsp_cl.c,v 1.23 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was transfered to Richard Levitte from CertCo by Kathy
+   Weinhold in mid-spring 2000 to be included in OpenSSL or released
+   as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+
+/* Utility functions related to sending OCSP requests and extracting
+ * relevant information from the response.
+ */
+
+/* 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;
+
+	if ((one = OCSP_ONEREQ_new()) == NULL)
+		goto err;
+	if (req != NULL) {
+		if (!sk_OCSP_ONEREQ_push(req->tbsRequest->requestList, one))
+			goto err;
+	}
+	OCSP_CERTID_free(one->reqCert);
+	one->reqCert = cid;
+	return one;
+
+ err:
+	OCSP_ONEREQ_free(one);
+	return NULL;
+}
+LCRYPTO_ALIAS(OCSP_request_add0_id);
+
+/* Set requestorName from an X509_NAME structure */
+int
+OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm)
+{
+	GENERAL_NAME *gen;
+
+	gen = GENERAL_NAME_new();
+	if (gen == NULL)
+		return 0;
+	if (!X509_NAME_set(&gen->d.directoryName, nm)) {
+		GENERAL_NAME_free(gen);
+		return 0;
+	}
+	gen->type = GEN_DIRNAME;
+	if (req->tbsRequest->requestorName)
+		GENERAL_NAME_free(req->tbsRequest->requestorName);
+	req->tbsRequest->requestorName = gen;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_request_set1_name);
+
+/* Add a certificate to an OCSP request */
+int
+OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert)
+{
+	OCSP_SIGNATURE *sig;
+
+	if (!req->optionalSignature)
+		req->optionalSignature = OCSP_SIGNATURE_new();
+	sig = req->optionalSignature;
+	if (!sig)
+		return 0;
+	if (!cert)
+		return 1;
+	if (!sig->certs && !(sig->certs = sk_X509_new_null()))
+		return 0;
+
+	if (!sk_X509_push(sig->certs, cert))
+		return 0;
+	X509_up_ref(cert);
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_request_add1_cert);
+
+/* Sign an OCSP request set the requestorName to the subject
+ * name of an 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;
+	OCSP_SIGNATURE *sig;
+	X509 *x;
+
+	if (!OCSP_request_set1_name(req, X509_get_subject_name(signer)))
+		goto err;
+
+	if (!(req->optionalSignature = sig = OCSP_SIGNATURE_new()))
+		goto err;
+	if (key) {
+		if (!X509_check_private_key(signer, key)) {
+			OCSPerror(OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+			goto err;
+		}
+		if (!OCSP_REQUEST_sign(req, key, dgst))
+			goto err;
+	}
+
+	if (!(flags & OCSP_NOCERTS)) {
+		if (!OCSP_request_add1_cert(req, signer))
+			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;
+
+err:
+	OCSP_SIGNATURE_free(req->optionalSignature);
+	req->optionalSignature = NULL;
+	return 0;
+}
+LCRYPTO_ALIAS(OCSP_request_sign);
+
+/* Get response status */
+int
+OCSP_response_status(OCSP_RESPONSE *resp)
+{
+	return ASN1_ENUMERATED_get(resp->responseStatus);
+}
+LCRYPTO_ALIAS(OCSP_response_status);
+
+/* 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) {
+		OCSPerror(OCSP_R_NO_RESPONSE_DATA);
+		return NULL;
+	}
+	if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
+		OCSPerror(OCSP_R_NOT_BASIC_RESPONSE);
+		return NULL;
+	}
+
+	return ASN1_item_unpack(rb->response, &OCSP_BASICRESP_it);
+}
+LCRYPTO_ALIAS(OCSP_response_get1_basic);
+
+/* Return number of OCSP_SINGLERESP responses present in
+ * a basic response.
+ */
+int
+OCSP_resp_count(OCSP_BASICRESP *bs)
+{
+	if (!bs)
+		return -1;
+	return sk_OCSP_SINGLERESP_num(bs->tbsResponseData->responses);
+}
+LCRYPTO_ALIAS(OCSP_resp_count);
+
+/* Extract an OCSP_SINGLERESP response with a given index */
+OCSP_SINGLERESP *
+OCSP_resp_get0(OCSP_BASICRESP *bs, int idx)
+{
+	if (!bs)
+		return NULL;
+	return sk_OCSP_SINGLERESP_value(bs->tbsResponseData->responses, idx);
+}
+LCRYPTO_ALIAS(OCSP_resp_get0);
+
+const ASN1_GENERALIZEDTIME *
+OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs)
+{
+	return bs->tbsResponseData->producedAt;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_produced_at);
+
+const STACK_OF(X509) *
+OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
+{
+	return bs->certs;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_certs);
+
+int
+OCSP_resp_get0_id(const OCSP_BASICRESP *bs, const ASN1_OCTET_STRING **pid,
+    const X509_NAME **pname)
+{
+	const OCSP_RESPID *rid = bs->tbsResponseData->responderId;
+
+	if (rid->type == V_OCSP_RESPID_NAME) {
+		*pname = rid->value.byName;
+		*pid = NULL;
+	} else if (rid->type == V_OCSP_RESPID_KEY) {
+		*pid = rid->value.byKey;
+		*pname = NULL;
+	} else {
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_id);
+
+const ASN1_OCTET_STRING *
+OCSP_resp_get0_signature(const OCSP_BASICRESP *bs)
+{
+	return bs->signature;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_signature);
+
+const X509_ALGOR *
+OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs)
+{
+	return bs->signatureAlgorithm;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_tbs_sigalg);
+
+const OCSP_RESPDATA *
+OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs)
+{
+	return bs->tbsResponseData;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_respdata);
+
+/* 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)
+		return -1;
+	if (last < 0)
+		last = 0;
+	else
+		last++;
+	sresp = bs->tbsResponseData->responses;
+	for (i = last; i < sk_OCSP_SINGLERESP_num(sresp); i++) {
+		single = sk_OCSP_SINGLERESP_value(sresp, i);
+		if (!OCSP_id_cmp(id, single->certId))
+			return i;
+	}
+	return -1;
+}
+LCRYPTO_ALIAS(OCSP_resp_find);
+
+/* Extract status information from an OCSP_SINGLERESP structure.
+ * Note: the 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,
+    ASN1_GENERALIZEDTIME **nextupd)
+{
+	int ret;
+	OCSP_CERTSTATUS *cst;
+
+	if (!single)
+		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) {
+			if (rev->revocationReason)
+				*reason = ASN1_ENUMERATED_get(
+				    rev->revocationReason);
+			else
+				*reason = -1;
+		}
+	}
+	if (thisupd)
+		*thisupd = single->thisUpdate;
+	if (nextupd)
+		*nextupd = single->nextUpdate;
+	return ret;
+}
+LCRYPTO_ALIAS(OCSP_single_get0_status);
+
+/* 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;
+	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)
+		*status = i;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_resp_find_status);
+
+/* Check validity of thisUpdate and nextUpdate fields. It is possible that the request will
+ * take a few seconds to process and/or the time wont be totally accurate. Therefore to avoid
+ * rejecting otherwise valid time we allow the times to be within 'nsec' of the current time.
+ * Also to avoid 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)
+{
+	time_t t_now, t_tmp;
+	struct tm tm_this, tm_next, tm_tmp;
+
+	time(&t_now);
+
+	/*
+	 * Times must explicitly be a GENERALIZEDTIME as per section
+	 * 4.2.2.1 of RFC 6960 - It is invalid to accept other times
+	 * (such as UTCTIME permitted/required by RFC 5280 for certificates)
+	 */
+
+	/* Check thisUpdate is valid and not more than nsec in the future */
+	if (ASN1_time_parse(thisupd->data, thisupd->length, &tm_this,
+	    V_ASN1_GENERALIZEDTIME) != V_ASN1_GENERALIZEDTIME) {
+		OCSPerror(OCSP_R_ERROR_IN_THISUPDATE_FIELD);
+		return 0;
+	} else {
+		t_tmp = t_now + nsec;
+		if (gmtime_r(&t_tmp, &tm_tmp) == NULL)
+			return 0;
+		if (ASN1_time_tm_cmp(&tm_this, &tm_tmp) > 0) {
+			OCSPerror(OCSP_R_STATUS_NOT_YET_VALID);
+			return 0;
+		}
+
+		/*
+		 * If maxsec specified check thisUpdate is not more than maxsec
+		 * in the past
+		 */
+		if (maxsec >= 0) {
+			t_tmp = t_now - maxsec;
+			if (gmtime_r(&t_tmp, &tm_tmp) == NULL)
+				return 0;
+			if (ASN1_time_tm_cmp(&tm_this, &tm_tmp) < 0) {
+				OCSPerror(OCSP_R_STATUS_TOO_OLD);
+				return 0;
+			}
+		}
+	}
+
+	if (!nextupd)
+		return 1;
+
+	/* Check nextUpdate is valid and not more than nsec in the past */
+	if (ASN1_time_parse(nextupd->data, nextupd->length, &tm_next,
+	    V_ASN1_GENERALIZEDTIME) != V_ASN1_GENERALIZEDTIME) {
+		OCSPerror(OCSP_R_ERROR_IN_NEXTUPDATE_FIELD);
+		return 0;
+	} else {
+		t_tmp = t_now - nsec;
+		if (gmtime_r(&t_tmp, &tm_tmp) == NULL)
+			return 0;
+		if (ASN1_time_tm_cmp(&tm_next, &tm_tmp) < 0) {
+			OCSPerror(OCSP_R_STATUS_EXPIRED);
+			return 0;
+		}
+	}
+
+	/* Also don't allow nextUpdate to precede thisUpdate */
+	if (ASN1_time_tm_cmp(&tm_next, &tm_this) < 0) {
+		OCSPerror(OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE);
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_check_validity);
+
+const OCSP_CERTID *
+OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single)
+{
+	return single->certId;
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get0_id);
diff --git a/crypto/ocsp/ocsp_err.c b/crypto/ocsp/ocsp_err.c
new file mode 100644
index 0000000..865091f
--- /dev/null
+++ b/crypto/ocsp/ocsp_err.c
@@ -0,0 +1,119 @@
+/* $OpenBSD: ocsp_err.c,v 1.10 2023/07/08 10:44:00 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_OCSP,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_OCSP,0,reason)
+
+static ERR_STRING_DATA OCSP_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA OCSP_str_reasons[]= {
+	{ERR_REASON(OCSP_R_BAD_DATA)             , "bad data"},
+	{ERR_REASON(OCSP_R_CERTIFICATE_VERIFY_ERROR), "certificate verify error"},
+	{ERR_REASON(OCSP_R_DIGEST_ERR)           , "digest err"},
+	{ERR_REASON(OCSP_R_ERROR_IN_NEXTUPDATE_FIELD), "error in nextupdate field"},
+	{ERR_REASON(OCSP_R_ERROR_IN_THISUPDATE_FIELD), "error in thisupdate field"},
+	{ERR_REASON(OCSP_R_ERROR_PARSING_URL)    , "error parsing url"},
+	{ERR_REASON(OCSP_R_MISSING_OCSPSIGNING_USAGE), "missing ocspsigning usage"},
+	{ERR_REASON(OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE), "nextupdate before thisupdate"},
+	{ERR_REASON(OCSP_R_NOT_BASIC_RESPONSE)   , "not basic response"},
+	{ERR_REASON(OCSP_R_NO_CERTIFICATES_IN_CHAIN), "no certificates in chain"},
+	{ERR_REASON(OCSP_R_NO_CONTENT)           , "no content"},
+	{ERR_REASON(OCSP_R_NO_PUBLIC_KEY)        , "no public key"},
+	{ERR_REASON(OCSP_R_NO_RESPONSE_DATA)     , "no response data"},
+	{ERR_REASON(OCSP_R_NO_REVOKED_TIME)      , "no revoked time"},
+	{ERR_REASON(OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), "private key does not match certificate"},
+	{ERR_REASON(OCSP_R_REQUEST_NOT_SIGNED)   , "request not signed"},
+	{ERR_REASON(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA), "response contains no revocation data"},
+	{ERR_REASON(OCSP_R_ROOT_CA_NOT_TRUSTED)  , "root ca not trusted"},
+	{ERR_REASON(OCSP_R_SERVER_READ_ERROR)    , "server read error"},
+	{ERR_REASON(OCSP_R_SERVER_RESPONSE_ERROR), "server response error"},
+	{ERR_REASON(OCSP_R_SERVER_RESPONSE_PARSE_ERROR), "server response parse error"},
+	{ERR_REASON(OCSP_R_SERVER_WRITE_ERROR)   , "server write error"},
+	{ERR_REASON(OCSP_R_SIGNATURE_FAILURE)    , "signature failure"},
+	{ERR_REASON(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND), "signer certificate not found"},
+	{ERR_REASON(OCSP_R_STATUS_EXPIRED)       , "status expired"},
+	{ERR_REASON(OCSP_R_STATUS_NOT_YET_VALID) , "status not yet valid"},
+	{ERR_REASON(OCSP_R_STATUS_TOO_OLD)       , "status too old"},
+	{ERR_REASON(OCSP_R_UNKNOWN_MESSAGE_DIGEST), "unknown message digest"},
+	{ERR_REASON(OCSP_R_UNKNOWN_NID)          , "unknown nid"},
+	{ERR_REASON(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE), "unsupported requestorname type"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_OCSP_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(OCSP_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, OCSP_str_functs);
+		ERR_load_strings(0, OCSP_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_OCSP_strings);
diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c
new file mode 100644
index 0000000..9f8cb74
--- /dev/null
+++ b/crypto/ocsp/ocsp_ext.c
@@ -0,0 +1,612 @@
+/* $OpenBSD: ocsp_ext.c,v 1.23 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was transfered to Richard Levitte from CertCo by Kathy
+   Weinhold in mid-spring 2000 to be included in OpenSSL or released
+   as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+#include "x509_local.h"
+
+/* Standard wrapper functions for extensions */
+
+/* OCSP request extensions */
+
+int
+OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
+{
+	return X509v3_get_ext_count(x->tbsRequest->requestExtensions);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get_ext_count);
+
+int
+OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(x->tbsRequest->requestExtensions, nid,
+	    lastpos);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get_ext_by_NID);
+
+int
+OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(x->tbsRequest->requestExtensions, obj,
+	    lastpos);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get_ext_by_OBJ);
+
+int
+OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(x->tbsRequest->requestExtensions,
+	    crit, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get_ext_by_critical);
+
+X509_EXTENSION *
+OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
+{
+	return X509v3_get_ext(x->tbsRequest->requestExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get_ext);
+
+X509_EXTENSION *
+OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
+{
+	return X509v3_delete_ext(x->tbsRequest->requestExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_delete_ext);
+
+void *
+OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(x->tbsRequest->requestExtensions, nid, crit, idx);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_get1_ext_d2i);
+
+int
+OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
+    unsigned long flags)
+{
+	return X509V3_add1_i2d(&x->tbsRequest->requestExtensions, nid, value,
+	    crit, flags);
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_add1_ext_i2d);
+
+int
+OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&(x->tbsRequest->requestExtensions), ex,
+	    loc) != NULL;
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_add_ext);
+
+/* Single extensions */
+
+int
+OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
+{
+	return X509v3_get_ext_count(x->singleRequestExtensions);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get_ext_count);
+
+int
+OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get_ext_by_NID);
+
+int
+OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get_ext_by_OBJ);
+
+int
+OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(x->singleRequestExtensions, crit,
+	    lastpos);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get_ext_by_critical);
+
+X509_EXTENSION *
+OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
+{
+	return X509v3_get_ext(x->singleRequestExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get_ext);
+
+X509_EXTENSION *
+OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
+{
+	return X509v3_delete_ext(x->singleRequestExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_delete_ext);
+
+void *
+OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_get1_ext_d2i);
+
+int
+OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
+    unsigned long flags)
+{
+	return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit,
+	    flags);
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_add1_ext_i2d);
+
+int
+OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL;
+}
+LCRYPTO_ALIAS(OCSP_ONEREQ_add_ext);
+
+/* OCSP Basic response */
+
+int
+OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
+{
+	return X509v3_get_ext_count(x->tbsResponseData->responseExtensions);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get_ext_count);
+
+int
+OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(x->tbsResponseData->responseExtensions,
+	    nid, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get_ext_by_NID);
+
+int
+OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(x->tbsResponseData->responseExtensions,
+	    obj, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get_ext_by_OBJ);
+
+int
+OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(
+	    x->tbsResponseData->responseExtensions, crit, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get_ext_by_critical);
+
+X509_EXTENSION *
+OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
+{
+	return X509v3_get_ext(x->tbsResponseData->responseExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get_ext);
+
+X509_EXTENSION *
+OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
+{
+	return X509v3_delete_ext(x->tbsResponseData->responseExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_delete_ext);
+
+void *
+OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(x->tbsResponseData->responseExtensions, nid,
+	    crit, idx);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_get1_ext_d2i);
+
+int
+OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, int crit,
+    unsigned long flags)
+{
+	return X509V3_add1_i2d(&x->tbsResponseData->responseExtensions, nid,
+	    value, crit, flags);
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_add1_ext_i2d);
+
+int
+OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&(x->tbsResponseData->responseExtensions), ex,
+	    loc) != NULL;
+}
+LCRYPTO_ALIAS(OCSP_BASICRESP_add_ext);
+
+/* OCSP single response extensions */
+
+int
+OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
+{
+	return X509v3_get_ext_count(x->singleExtensions);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get_ext_count);
+
+int
+OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get_ext_by_NID);
+
+int
+OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
+    int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get_ext_by_OBJ);
+
+int
+OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get_ext_by_critical);
+
+X509_EXTENSION *
+OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
+{
+	return X509v3_get_ext(x->singleExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get_ext);
+
+X509_EXTENSION *
+OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
+{
+	return X509v3_delete_ext(x->singleExtensions, loc);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_delete_ext);
+
+void *
+OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_get1_ext_d2i);
+
+int
+OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, int crit,
+    unsigned long flags)
+{
+	return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_add1_ext_i2d);
+
+int
+OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL;
+}
+LCRYPTO_ALIAS(OCSP_SINGLERESP_add_ext);
+
+/* Nonce handling functions */
+
+/* Add a nonce to an extension stack. A nonce can be specified or if NULL
+ * a random nonce will be generated.
+ * Note: OpenSSL 0.9.7d and later create an OCTET STRING containing the
+ * nonce, previous versions used the raw nonce.
+ */
+
+static int
+ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, unsigned char *val, int len)
+{
+	unsigned char *tmpval;
+	ASN1_OCTET_STRING os;
+	int ret = 0;
+
+	if (len <= 0)
+		len = OCSP_DEFAULT_NONCE_LENGTH;
+	/* Create the OCTET STRING manually by writing out the header and
+	 * appending the content octets. This avoids an extra memory allocation
+	 * operation in some cases. Applications should *NOT* do this because
+	 * it relies on library internals.
+	 */
+	os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING);
+	os.data = malloc(os.length);
+	if (os.data == NULL)
+		goto err;
+	tmpval = os.data;
+	ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL);
+	if (val)
+		memcpy(tmpval, val, len);
+	else
+		arc4random_buf(tmpval, len);
+	if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, &os, 0,
+	    X509V3_ADD_REPLACE))
+		goto err;
+	ret = 1;
+
+err:
+	free(os.data);
+	return ret;
+}
+
+/* Add nonce to an OCSP request */
+int
+OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
+{
+	return ocsp_add1_nonce(&req->tbsRequest->requestExtensions, val, len);
+}
+LCRYPTO_ALIAS(OCSP_request_add1_nonce);
+
+/* Same as above but for a response */
+int
+OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
+{
+	return ocsp_add1_nonce(&resp->tbsResponseData->responseExtensions, val,
+	    len);
+}
+LCRYPTO_ALIAS(OCSP_basic_add1_nonce);
+
+/* Check nonce validity in a request and response.
+ * Return value reflects result:
+ *  1: nonces present and equal.
+ *  2: nonces both absent.
+ *  3: nonce present in response only.
+ *  0: nonces both present and not equal.
+ * -1: nonce in request only.
+ *
+ *  For most responders clients can check return > 0.
+ *  If responder doesn't handle nonces return != 0 may be
+ *  necessary. return == 0 is always an error.
+ */
+int
+OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
+{
+	/*
+	 * Since we are only interested in the presence or absence of
+	 * the nonce and comparing its value there is no need to use
+	 * the X509V3 routines: this way we can avoid them allocating an
+	 * ASN1_OCTET_STRING structure for the value which would be
+	 * freed immediately anyway.
+	 */
+	int req_idx, resp_idx;
+	X509_EXTENSION *req_ext, *resp_ext;
+
+	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
+	resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs,
+	    NID_id_pkix_OCSP_Nonce, -1);
+	/* Check both absent */
+	if (req_idx < 0 && resp_idx < 0)
+		return 2;
+	/* Check in request only */
+	if (req_idx >= 0 && resp_idx < 0)
+		return -1;
+	/* Check in response but not request */
+	if (req_idx < 0 && resp_idx >= 0)
+		return 3;
+	/* Otherwise nonce in request and response so retrieve the extensions */
+	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
+	resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
+	if (ASN1_OCTET_STRING_cmp(req_ext->value, resp_ext->value))
+		return 0;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_check_nonce);
+
+/* Copy the nonce value (if any) from an OCSP request to
+ * a response.
+ */
+int
+OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req)
+{
+	X509_EXTENSION *req_ext;
+	int req_idx;
+
+	/* Check for nonce in request */
+	req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
+	/* If no nonce that's OK */
+	if (req_idx < 0)
+		return 2;
+	req_ext = OCSP_REQUEST_get_ext(req, req_idx);
+	return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
+}
+LCRYPTO_ALIAS(OCSP_copy_nonce);
+
+X509_EXTENSION *
+OCSP_crlID_new(const char *url, long *n, char *tim)
+{
+	X509_EXTENSION *x = NULL;
+	OCSP_CRLID *cid = NULL;
+
+	if (!(cid = OCSP_CRLID_new()))
+		goto err;
+	if (url) {
+		if (!(cid->crlUrl = ASN1_IA5STRING_new()))
+			goto err;
+		if (!(ASN1_STRING_set(cid->crlUrl, url, -1)))
+			goto err;
+	}
+	if (n) {
+		if (!(cid->crlNum = ASN1_INTEGER_new()))
+			goto err;
+		if (!(ASN1_INTEGER_set(cid->crlNum, *n)))
+			goto err;
+	}
+	if (tim) {
+		if (!(cid->crlTime = ASN1_GENERALIZEDTIME_new()))
+			goto err;
+		if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
+			goto err;
+	}
+	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid);
+
+err:
+	if (cid)
+		OCSP_CRLID_free(cid);
+	return x;
+}
+LCRYPTO_ALIAS(OCSP_crlID_new);
+
+/*   AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
+X509_EXTENSION *
+OCSP_accept_responses_new(char **oids)
+{
+	int nid;
+	STACK_OF(ASN1_OBJECT) *sk = NULL;
+	ASN1_OBJECT *o = NULL;
+	X509_EXTENSION *x = NULL;
+
+	if (!(sk = sk_ASN1_OBJECT_new_null()))
+		return NULL;
+	while (oids && *oids) {
+		if ((nid = OBJ_txt2nid(*oids)) != NID_undef &&
+		    (o = OBJ_nid2obj(nid)))
+			if (sk_ASN1_OBJECT_push(sk, o) == 0) {
+				sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
+				return NULL;
+			}
+		oids++;
+	}
+	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk);
+	sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
+	return x;
+}
+LCRYPTO_ALIAS(OCSP_accept_responses_new);
+
+/*  ArchiveCutoff ::= GeneralizedTime */
+X509_EXTENSION *
+OCSP_archive_cutoff_new(char* tim)
+{
+	X509_EXTENSION *x = NULL;
+	ASN1_GENERALIZEDTIME *gt = NULL;
+
+	if (!(gt = ASN1_GENERALIZEDTIME_new()))
+		return NULL;
+	if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim)))
+		goto err;
+	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt);
+
+err:
+	if (gt)
+		ASN1_GENERALIZEDTIME_free(gt);
+	return x;
+}
+LCRYPTO_ALIAS(OCSP_archive_cutoff_new);
+
+/* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
+ * 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 *x = NULL;
+	ASN1_IA5STRING *ia5 = NULL;
+	OCSP_SERVICELOC *sloc = NULL;
+	ACCESS_DESCRIPTION *ad = NULL;
+
+	if (!(sloc = OCSP_SERVICELOC_new()))
+		goto err;
+	if (!(sloc->issuer = X509_NAME_dup(issuer)))
+		goto err;
+	if (urls && *urls &&
+	    !(sloc->locator = sk_ACCESS_DESCRIPTION_new_null()))
+		goto err;
+	while (urls && *urls) {
+		if (!(ad = ACCESS_DESCRIPTION_new()))
+			goto err;
+		if (!(ad->method = OBJ_nid2obj(NID_ad_OCSP)))
+			goto err;
+		if (!(ad->location = GENERAL_NAME_new()))
+			goto err;
+		if (!(ia5 = ASN1_IA5STRING_new()))
+			goto err;
+		if (!ASN1_STRING_set((ASN1_STRING*)ia5, *urls, -1))
+			goto err;
+		ad->location->type = GEN_URI;
+		ad->location->d.ia5 = ia5;
+		ia5 = NULL;
+		if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad))
+			goto err;
+		ad = NULL;
+		urls++;
+	}
+	x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc);
+
+err:
+	if (ia5)
+		ASN1_IA5STRING_free(ia5);
+	if (ad)
+		ACCESS_DESCRIPTION_free(ad);
+	if (sloc)
+		OCSP_SERVICELOC_free(sloc);
+	return x;
+}
+LCRYPTO_ALIAS(OCSP_url_svcloc_new);
diff --git a/crypto/ocsp/ocsp_ht.c b/crypto/ocsp/ocsp_ht.c
new file mode 100644
index 0000000..bf735c7
--- /dev/null
+++ b/crypto/ocsp/ocsp_ht.c
@@ -0,0 +1,469 @@
+/* $OpenBSD: ocsp_ht.c,v 1.26 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* 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 */
+};
+
+#define OCSP_MAX_REQUEST_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
+/* 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)
+
+
+static int parse_http_line1(char *line);
+
+void
+OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
+{
+	if (rctx == NULL)
+		return;
+
+	BIO_free(rctx->mem);
+	free(rctx->iobuf);
+	free(rctx);
+}
+LCRYPTO_ALIAS(OCSP_REQ_CTX_free);
+
+int
+OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req)
+{
+	if (BIO_printf(rctx->mem, "Content-Type: application/ocsp-request\r\n"
+	    "Content-Length: %d\r\n\r\n", i2d_OCSP_REQUEST(req, NULL)) <= 0)
+		return 0;
+	if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0)
+		return 0;
+	rctx->state = OHS_ASN1_WRITE;
+	rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_REQ_CTX_set1_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;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_REQ_CTX_add1_header);
+
+OCSP_REQ_CTX *
+OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, int maxline)
+{
+	OCSP_REQ_CTX *rctx;
+
+	rctx = malloc(sizeof(OCSP_REQ_CTX));
+	if (rctx == NULL)
+		return NULL;
+	rctx->state = OHS_ERROR;
+	if ((rctx->mem = BIO_new(BIO_s_mem())) == NULL) {
+		free(rctx);
+		return NULL;
+	}
+	rctx->io = io;
+	rctx->asn1_len = 0;
+	if (maxline > 0)
+		rctx->iobuflen = maxline;
+	else
+		rctx->iobuflen = OCSP_MAX_LINE_LEN;
+	rctx->iobuf = malloc(rctx->iobuflen);
+	if (!rctx->iobuf) {
+		BIO_free(rctx->mem);
+		free(rctx);
+		return NULL;
+	}
+	if (!path)
+		path = "/";
+
+	if (BIO_printf(rctx->mem, "POST %s HTTP/1.0\r\n", path) <= 0) {
+		free(rctx->iobuf);
+		BIO_free(rctx->mem);
+		free(rctx);
+		return NULL;
+	}
+
+	if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) {
+		free(rctx->iobuf);
+		BIO_free(rctx->mem);
+		free(rctx);
+		return NULL;
+	}
+
+	return rctx;
+}
+LCRYPTO_ALIAS(OCSP_sendreq_new);
+
+/* 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 && !isspace((unsigned char)*p); p++)
+		continue;
+	if (!*p) {
+		OCSPerror(OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+		return 0;
+	}
+
+	/* Skip past white space to start of response code */
+	while (*p && isspace((unsigned char)*p))
+		p++;
+	if (!*p) {
+		OCSPerror(OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
+		return 0;
+	}
+
+	/* Find end of response code: first whitespace after start of code */
+	for (q = p; *q && !isspace((unsigned char)*q); q++)
+		continue;
+	if (!*q) {
+		OCSPerror(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 && isspace((unsigned char)*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; isspace((unsigned char)*r); r--)
+			*r = 0;
+	}
+	if (retcode != 200) {
+		OCSPerror(OCSP_R_SERVER_RESPONSE_ERROR);
+		if (!*q)
+			ERR_asprintf_error_data("Code=%s", p);
+		else
+			ERR_asprintf_error_data("Code=%s,Reason=%s", p, q);
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+OCSP_sendreq_nbio(OCSP_RESPONSE **presp, 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_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);
+		/* FALLTHROUGH */
+
+	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;
+		}
+		/* FALLTRHOUGH */
+
+	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 > OCSP_MAX_REQUEST_LENGTH) {
+				rctx->state = OHS_ERROR;
+				return 0;
+			}
+
+			rctx->asn1_len += n + 2;
+		} else
+			rctx->asn1_len = *p + 2;
+
+		rctx->state = OHS_ASN1_CONTENT;
+
+		/* FALLTHROUGH */
+
+	case OHS_ASN1_CONTENT:
+		n = BIO_get_mem_data(rctx->mem, &p);
+		if (n < (int)rctx->asn1_len)
+			goto next_io;
+
+		*presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len);
+		if (*presp) {
+			rctx->state = OHS_DONE;
+			return 1;
+		}
+
+		rctx->state = OHS_ERROR;
+		return 0;
+
+	case OHS_DONE:
+		return 1;
+	}
+
+	return 0;
+}
+LCRYPTO_ALIAS(OCSP_sendreq_nbio);
+
+/* 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;
+}
+LCRYPTO_ALIAS(OCSP_sendreq_bio);
diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c
new file mode 100644
index 0000000..d3eada2
--- /dev/null
+++ b/crypto/ocsp/ocsp_lib.c
@@ -0,0 +1,249 @@
+/* $OpenBSD: ocsp_lib.c,v 1.26 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was transfered to Richard Levitte from CertCo by Kathy
+   Weinhold in mid-spring 2000 to be included in OpenSSL or released
+   as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+
+/* Convert a certificate and its issuer to an OCSP_CERTID */
+
+OCSP_CERTID *
+OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, const X509 *issuer)
+{
+	X509_NAME *iname;
+	const ASN1_INTEGER *serial;
+	ASN1_BIT_STRING *ikey;
+
+#ifndef OPENSSL_NO_SHA1
+	if (!dgst)
+		dgst = EVP_sha1();
+#endif
+	if (subject) {
+		iname = X509_get_issuer_name(subject);
+		serial = X509_get0_serialNumber(subject);
+	} else {
+		iname = X509_get_subject_name(issuer);
+		serial = NULL;
+	}
+	if ((ikey = X509_get0_pubkey_bitstr(issuer)) == NULL)
+		return NULL;
+
+	return OCSP_cert_id_new(dgst, iname, ikey, serial);
+}
+LCRYPTO_ALIAS(OCSP_cert_to_id);
+
+OCSP_CERTID *
+OCSP_cert_id_new(const EVP_MD *dgst, const X509_NAME *issuerName,
+    const ASN1_BIT_STRING *issuerKey, const ASN1_INTEGER *serialNumber)
+{
+	int nid;
+	unsigned int i;
+	X509_ALGOR *alg;
+	OCSP_CERTID *cid = NULL;
+	unsigned char md[EVP_MAX_MD_SIZE];
+
+	if (!(cid = OCSP_CERTID_new()))
+		goto err;
+
+	alg = cid->hashAlgorithm;
+	if (alg->algorithm != NULL)
+		ASN1_OBJECT_free(alg->algorithm);
+	if ((nid = EVP_MD_type(dgst)) == NID_undef) {
+		OCSPerror(OCSP_R_UNKNOWN_NID);
+		goto err;
+	}
+	if (!(alg->algorithm = OBJ_nid2obj(nid)))
+		goto err;
+	if ((alg->parameter = ASN1_TYPE_new()) == NULL)
+		goto err;
+	alg->parameter->type = V_ASN1_NULL;
+
+	if (!X509_NAME_digest(issuerName, dgst, md, &i))
+		goto digerr;
+	if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i)))
+		goto err;
+
+	/* Calculate the issuerKey hash, excluding tag and length */
+	if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL))
+		goto err;
+
+	if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i)))
+		goto err;
+
+	if (serialNumber) {
+		ASN1_INTEGER_free(cid->serialNumber);
+		if (!(cid->serialNumber = ASN1_INTEGER_dup(serialNumber)))
+			goto err;
+	}
+	return cid;
+
+digerr:
+	OCSPerror(OCSP_R_DIGEST_ERR);
+err:
+	if (cid)
+		OCSP_CERTID_free(cid);
+	return NULL;
+}
+LCRYPTO_ALIAS(OCSP_cert_id_new);
+
+int
+OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+{
+	int ret;
+
+	ret = OBJ_cmp(a->hashAlgorithm->algorithm, b->hashAlgorithm->algorithm);
+	if (ret)
+		return ret;
+	ret = ASN1_OCTET_STRING_cmp(a->issuerNameHash, b->issuerNameHash);
+	if (ret)
+		return ret;
+	return ASN1_OCTET_STRING_cmp(a->issuerKeyHash, b->issuerKeyHash);
+}
+LCRYPTO_ALIAS(OCSP_id_issuer_cmp);
+
+int
+OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+{
+	int ret;
+
+	ret = OCSP_id_issuer_cmp(a, b);
+	if (ret)
+		return ret;
+	return ASN1_INTEGER_cmp(a->serialNumber, b->serialNumber);
+}
+LCRYPTO_ALIAS(OCSP_id_cmp);
+
+/* 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 *host, *path, *port, *tmp;
+
+	*phost = *pport = *ppath = NULL;
+	*pssl = 0;
+
+	if (strncmp(url, "https://", 8) == 0) {
+		*pssl = 1;
+		host = strdup(url + 8);
+	} else if (strncmp(url, "http://", 7) == 0)
+		host = strdup(url + 7);
+	else {
+		OCSPerror(OCSP_R_ERROR_PARSING_URL);
+		return 0;
+	}
+	if (host == NULL) {
+		OCSPerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	if ((tmp = strchr(host, '/')) != NULL) {
+		path = strdup(tmp);
+		*tmp = '\0';
+	} else
+		path = strdup("/");
+
+	if ((tmp = strchr(host, ':')) != NULL ) {
+		port = strdup(tmp + 1);
+		*tmp = '\0';
+	} else {
+		if (*pssl)
+			port = strdup("443");
+		else
+			port = strdup("80");
+	}
+
+	if (path == NULL || port == NULL) {
+		free(host);
+		free(path);
+		free(port);
+		OCSPerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	*phost = host;
+	*ppath = path;
+	*pport = port;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_parse_url);
+
+OCSP_CERTID *
+OCSP_CERTID_dup(OCSP_CERTID *x)
+{
+	return ASN1_item_dup(&OCSP_CERTID_it, x);
+}
+LCRYPTO_ALIAS(OCSP_CERTID_dup);
diff --git a/crypto/ocsp/ocsp_local.h b/crypto/ocsp/ocsp_local.h
new file mode 100644
index 0000000..bd933b1
--- /dev/null
+++ b/crypto/ocsp/ocsp_local.h
@@ -0,0 +1,291 @@
+/* $OpenBSD: ocsp_local.h,v 1.2 2022/01/14 08:32:26 tb Exp $ */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was transfered to Richard Levitte from CertCo by Kathy
+   Weinhold in mid-spring 2000 to be included in OpenSSL or released
+   as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_OCSP_LOCAL_H
+#define HEADER_OCSP_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+/*   CertID ::= SEQUENCE {
+ *       hashAlgorithm            AlgorithmIdentifier,
+ *       issuerNameHash     OCTET STRING, -- Hash of Issuer's DN
+ *       issuerKeyHash      OCTET STRING, -- Hash of Issuers public key (excluding the tag & length fields)
+ *       serialNumber       CertificateSerialNumber }
+ */
+struct ocsp_cert_id_st {
+	X509_ALGOR *hashAlgorithm;
+	ASN1_OCTET_STRING *issuerNameHash;
+	ASN1_OCTET_STRING *issuerKeyHash;
+	ASN1_INTEGER *serialNumber;
+} /* OCSP_CERTID */;
+
+/*   Request ::=     SEQUENCE {
+ *       reqCert                    CertID,
+ *       singleRequestExtensions    [0] EXPLICIT Extensions OPTIONAL }
+ */
+struct ocsp_one_request_st {
+	OCSP_CERTID *reqCert;
+	STACK_OF(X509_EXTENSION) *singleRequestExtensions;
+} /* OCSP_ONEREQ */;
+
+/*   TBSRequest      ::=     SEQUENCE {
+ *       version             [0] EXPLICIT Version DEFAULT v1,
+ *       requestorName       [1] EXPLICIT GeneralName OPTIONAL,
+ *       requestList             SEQUENCE OF Request,
+ *       requestExtensions   [2] EXPLICIT Extensions OPTIONAL }
+ */
+struct ocsp_req_info_st {
+	ASN1_INTEGER *version;
+	GENERAL_NAME *requestorName;
+	STACK_OF(OCSP_ONEREQ) *requestList;
+	STACK_OF(X509_EXTENSION) *requestExtensions;
+} /* OCSP_REQINFO */;
+
+/*   Signature       ::=     SEQUENCE {
+ *       signatureAlgorithm   AlgorithmIdentifier,
+ *       signature            BIT STRING,
+ *       certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+struct ocsp_signature_st {
+	X509_ALGOR *signatureAlgorithm;
+	ASN1_BIT_STRING *signature;
+	STACK_OF(X509) *certs;
+} /* OCSP_SIGNATURE */;
+
+/*   OCSPRequest     ::=     SEQUENCE {
+ *       tbsRequest                  TBSRequest,
+ *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+ */
+struct ocsp_request_st {
+	OCSP_REQINFO *tbsRequest;
+	OCSP_SIGNATURE *optionalSignature; /* OPTIONAL */
+} /* OCSP_REQUEST */;
+
+/*   OCSPResponseStatus ::= ENUMERATED {
+ *       successful            (0),      --Response has valid confirmations
+ *       malformedRequest      (1),      --Illegal confirmation request
+ *       internalError         (2),      --Internal error in issuer
+ *       tryLater              (3),      --Try again later
+ *                                       --(4) is not used
+ *       sigRequired           (5),      --Must sign the request
+ *       unauthorized          (6)       --Request unauthorized
+ *   }
+ */
+
+/*   ResponseBytes ::=       SEQUENCE {
+ *       responseType   OBJECT IDENTIFIER,
+ *       response       OCTET STRING }
+ */
+struct ocsp_resp_bytes_st {
+	ASN1_OBJECT *responseType;
+	ASN1_OCTET_STRING *response;
+} /* OCSP_RESPBYTES */;
+
+/*   OCSPResponse ::= SEQUENCE {
+ *      responseStatus         OCSPResponseStatus,
+ *      responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+ */
+struct ocsp_response_st {
+	ASN1_ENUMERATED *responseStatus;
+	OCSP_RESPBYTES  *responseBytes;
+};
+
+/*   ResponderID ::= CHOICE {
+ *      byName   [1] Name,
+ *      byKey    [2] KeyHash }
+ */
+struct ocsp_responder_id_st {
+	int type;
+	union {
+		X509_NAME* byName;
+		ASN1_OCTET_STRING *byKey;
+	} value;
+};
+
+/*   KeyHash ::= OCTET STRING --SHA-1 hash of responder's public key
+ *                            --(excluding the tag and length fields)
+ */
+
+/*   RevokedInfo ::= SEQUENCE {
+ *       revocationTime              GeneralizedTime,
+ *       revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+ */
+struct ocsp_revoked_info_st {
+	ASN1_GENERALIZEDTIME *revocationTime;
+	ASN1_ENUMERATED *revocationReason;
+} /* OCSP_REVOKEDINFO */;
+
+/*   CertStatus ::= CHOICE {
+ *       good                [0]     IMPLICIT NULL,
+ *       revoked             [1]     IMPLICIT RevokedInfo,
+ *       unknown             [2]     IMPLICIT UnknownInfo }
+ */
+struct ocsp_cert_status_st {
+	int type;
+	union {
+		ASN1_NULL *good;
+		OCSP_REVOKEDINFO *revoked;
+		ASN1_NULL *unknown;
+	} value;
+} /* OCSP_CERTSTATUS */;
+
+/*   SingleResponse ::= SEQUENCE {
+ *      certID                       CertID,
+ *      certStatus                   CertStatus,
+ *      thisUpdate                   GeneralizedTime,
+ *      nextUpdate           [0]     EXPLICIT GeneralizedTime OPTIONAL,
+ *      singleExtensions     [1]     EXPLICIT Extensions OPTIONAL }
+ */
+struct ocsp_single_response_st {
+	OCSP_CERTID *certId;
+	OCSP_CERTSTATUS *certStatus;
+	ASN1_GENERALIZEDTIME *thisUpdate;
+	ASN1_GENERALIZEDTIME *nextUpdate;
+	STACK_OF(X509_EXTENSION) *singleExtensions;
+} /* OCSP_SINGLERESP */;
+
+/*   ResponseData ::= SEQUENCE {
+ *      version              [0] EXPLICIT Version DEFAULT v1,
+ *      responderID              ResponderID,
+ *      producedAt               GeneralizedTime,
+ *      responses                SEQUENCE OF SingleResponse,
+ *      responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+ */
+struct ocsp_response_data_st {
+	ASN1_INTEGER *version;
+	OCSP_RESPID  *responderId;
+	ASN1_GENERALIZEDTIME *producedAt;
+	STACK_OF(OCSP_SINGLERESP) *responses;
+	STACK_OF(X509_EXTENSION) *responseExtensions;
+} /* OCSP_RESPDATA */;
+
+/*   BasicOCSPResponse       ::= SEQUENCE {
+ *      tbsResponseData      ResponseData,
+ *      signatureAlgorithm   AlgorithmIdentifier,
+ *      signature            BIT STRING,
+ *      certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+ */
+  /* Note 1:
+     The value for "signature" is specified in the OCSP rfc2560 as follows:
+     "The value for the signature SHALL be computed on the hash of the DER
+     encoding ResponseData."  This means that you must hash the DER-encoded
+     tbsResponseData, and then run it through a crypto-signing function, which
+     will (at least w/RSA) do a hash-'n'-private-encrypt operation.  This seems
+     a bit odd, but that's the spec.  Also note that the data structures do not
+     leave anywhere to independently specify the algorithm used for the initial
+     hash. So, we look at the signature-specification algorithm, and try to do
+     something intelligent.	-- Kathy Weinhold, CertCo */
+  /* Note 2:
+     It seems that the mentioned passage from RFC 2560 (section 4.2.1) is open
+     for interpretation.  I've done tests against another responder, and found
+     that it doesn't do the double hashing that the RFC seems to say one
+     should.  Therefore, all relevant functions take a flag saying which
+     variant should be used.	-- Richard Levitte, OpenSSL team and CeloCom */
+struct ocsp_basic_response_st {
+	OCSP_RESPDATA *tbsResponseData;
+	X509_ALGOR *signatureAlgorithm;
+	ASN1_BIT_STRING *signature;
+	STACK_OF(X509) *certs;
+} /* OCSP_BASICRESP */;
+
+/* CrlID ::= SEQUENCE {
+ *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+ *     crlNum               [1]     EXPLICIT INTEGER OPTIONAL,
+ *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+ */
+struct ocsp_crl_id_st {
+	ASN1_IA5STRING *crlUrl;
+	ASN1_INTEGER *crlNum;
+	ASN1_GENERALIZEDTIME *crlTime;
+} /* OCSP_CRLID */;
+
+/* ServiceLocator ::= SEQUENCE {
+ *      issuer    Name,
+ *      locator   AuthorityInfoAccessSyntax OPTIONAL }
+ */
+struct ocsp_service_locator_st {
+	X509_NAME* issuer;
+	STACK_OF(ACCESS_DESCRIPTION) *locator;
+} /* OCSP_SERVICELOC */;
+
+#define OCSP_REQUEST_sign(o,pkey,md) \
+    ASN1_item_sign(&OCSP_REQINFO_it, \
+	(o)->optionalSignature->signatureAlgorithm, NULL, \
+	(o)->optionalSignature->signature,o->tbsRequest, (pkey), (md))
+
+#define OCSP_BASICRESP_sign(o,pkey,md,d) \
+    ASN1_item_sign(&OCSP_RESPDATA_it,o->signatureAlgorithm,NULL, \
+	(o)->signature,(o)->tbsResponseData,(pkey),(md))
+
+#define OCSP_REQUEST_verify(a,r) \
+    ASN1_item_verify(&OCSP_REQINFO_it, \
+	(a)->optionalSignature->signatureAlgorithm, \
+	(a)->optionalSignature->signature, (a)->tbsRequest, (r))
+
+#define OCSP_BASICRESP_verify(a,r,d) \
+    ASN1_item_verify(&OCSP_RESPDATA_it, \
+	(a)->signatureAlgorithm, (a)->signature, (a)->tbsResponseData, (r))
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_OCSP_LOCAL_H */
diff --git a/crypto/ocsp/ocsp_prn.c b/crypto/ocsp/ocsp_prn.c
new file mode 100644
index 0000000..7e3175b
--- /dev/null
+++ b/crypto/ocsp/ocsp_prn.c
@@ -0,0 +1,319 @@
+/* $OpenBSD: ocsp_prn.c,v 1.10 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Tom Titchener  for the OpenSSL
+ * project. */
+
+/* History:
+   This file was originally part of ocsp.c and was transfered to Richard
+   Levitte from CertCo by Kathy Weinhold in mid-spring 2000 to be included
+   in OpenSSL or released as a patch kit. */
+
+/* ====================================================================
+ * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+
+static int
+ocsp_certid_print(BIO *bp, OCSP_CERTID* a, int indent)
+{
+	BIO_printf(bp, "%*sCertificate ID:\n", indent, "");
+	indent += 2;
+	BIO_printf(bp, "%*sHash Algorithm: ", indent, "");
+	i2a_ASN1_OBJECT(bp, a->hashAlgorithm->algorithm);
+	BIO_printf(bp, "\n%*sIssuer Name Hash: ", indent, "");
+	i2a_ASN1_STRING(bp, a->issuerNameHash, V_ASN1_OCTET_STRING);
+	BIO_printf(bp, "\n%*sIssuer Key Hash: ", indent, "");
+	i2a_ASN1_STRING(bp, a->issuerKeyHash, V_ASN1_OCTET_STRING);
+	BIO_printf(bp, "\n%*sSerial Number: ", indent, "");
+	i2a_ASN1_INTEGER(bp, a->serialNumber);
+	BIO_printf(bp, "\n");
+	return 1;
+}
+
+typedef struct {
+	long t;
+	const char *m;
+} OCSP_TBLSTR;
+
+static const char *
+table2string(long s, const OCSP_TBLSTR *ts, int len)
+{
+	const OCSP_TBLSTR *p;
+
+	for (p = ts; p < ts + len; p++)
+		if (p->t == s)
+			return p->m;
+	return "(UNKNOWN)";
+}
+
+const char *
+OCSP_response_status_str(long s)
+{
+	static const OCSP_TBLSTR rstat_tbl[] = {
+		{ OCSP_RESPONSE_STATUS_SUCCESSFUL, "successful" },
+		{ OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, "malformedrequest" },
+		{ OCSP_RESPONSE_STATUS_INTERNALERROR, "internalerror" },
+		{ OCSP_RESPONSE_STATUS_TRYLATER, "trylater" },
+		{ OCSP_RESPONSE_STATUS_SIGREQUIRED, "sigrequired" },
+		{ OCSP_RESPONSE_STATUS_UNAUTHORIZED, "unauthorized" }
+	};
+	return table2string(s, rstat_tbl, 6);
+}
+LCRYPTO_ALIAS(OCSP_response_status_str);
+
+const char *
+OCSP_cert_status_str(long s)
+{
+	static const OCSP_TBLSTR cstat_tbl[] = {
+		{ V_OCSP_CERTSTATUS_GOOD, "good" },
+		{ V_OCSP_CERTSTATUS_REVOKED, "revoked" },
+		{ V_OCSP_CERTSTATUS_UNKNOWN, "unknown" }
+	};
+	return table2string(s, cstat_tbl, 3);
+}
+LCRYPTO_ALIAS(OCSP_cert_status_str);
+
+const char *
+OCSP_crl_reason_str(long s)
+{
+	static const OCSP_TBLSTR reason_tbl[] = {
+		{ OCSP_REVOKED_STATUS_UNSPECIFIED, "unspecified" },
+		{ OCSP_REVOKED_STATUS_KEYCOMPROMISE, "keyCompromise" },
+		{ OCSP_REVOKED_STATUS_CACOMPROMISE, "cACompromise" },
+		{ OCSP_REVOKED_STATUS_AFFILIATIONCHANGED, "affiliationChanged" },
+		{ OCSP_REVOKED_STATUS_SUPERSEDED, "superseded" },
+		{ OCSP_REVOKED_STATUS_CESSATIONOFOPERATION, "cessationOfOperation" },
+		{ OCSP_REVOKED_STATUS_CERTIFICATEHOLD, "certificateHold" },
+		{ OCSP_REVOKED_STATUS_REMOVEFROMCRL, "removeFromCRL" }
+	};
+	return table2string(s, reason_tbl, 8);
+}
+LCRYPTO_ALIAS(OCSP_crl_reason_str);
+
+int
+OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* o, unsigned long flags)
+{
+	int i;
+	long l;
+	OCSP_CERTID* cid = NULL;
+	OCSP_ONEREQ *one = NULL;
+	OCSP_REQINFO *inf = o->tbsRequest;
+	OCSP_SIGNATURE *sig = o->optionalSignature;
+
+	if (BIO_write(bp, "OCSP Request Data:\n", 19) <= 0)
+		goto err;
+	l = ASN1_INTEGER_get(inf->version);
+	if (BIO_printf(bp, "    Version: %lu (0x%lx)", l+1, l) <= 0)
+		goto err;
+	if (inf->requestorName != NULL) {
+		if (BIO_write(bp, "\n    Requestor Name: ", 21) <= 0)
+			goto err;
+		GENERAL_NAME_print(bp, inf->requestorName);
+	}
+	if (BIO_write(bp, "\n    Requestor List:\n", 21) <= 0)
+		goto err;
+	for (i = 0; i < sk_OCSP_ONEREQ_num(inf->requestList); i++) {
+		one = sk_OCSP_ONEREQ_value(inf->requestList, i);
+		cid = one->reqCert;
+		ocsp_certid_print(bp, cid, 8);
+		if (!X509V3_extensions_print(bp, "Request Single Extensions",
+		    one->singleRequestExtensions, flags, 8))
+			goto err;
+	}
+	if (!X509V3_extensions_print(bp, "Request Extensions",
+	    inf->requestExtensions, flags, 4))
+		goto err;
+	if (sig) {
+		if (X509_signature_print(bp, sig->signatureAlgorithm,
+		    sig->signature) == 0)
+			goto err;
+		for (i = 0; i < sk_X509_num(sig->certs); i++) {
+			if (X509_print(bp, sk_X509_value(sig->certs, i)) == 0)
+				goto err;
+			if (PEM_write_bio_X509(bp,
+			    sk_X509_value(sig->certs, i)) == 0)
+				goto err;
+		}
+	}
+	return 1;
+
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(OCSP_REQUEST_print);
+
+int
+OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags)
+{
+	int i, ret = 0;
+	long l;
+	OCSP_CERTID *cid = NULL;
+	OCSP_BASICRESP *br = NULL;
+	OCSP_RESPID *rid = NULL;
+	OCSP_RESPDATA  *rd = NULL;
+	OCSP_CERTSTATUS *cst = NULL;
+	OCSP_REVOKEDINFO *rev = NULL;
+	OCSP_SINGLERESP *single = NULL;
+	OCSP_RESPBYTES *rb = o->responseBytes;
+
+	if (BIO_puts(bp, "OCSP Response Data:\n") <= 0)
+		goto err;
+	l = ASN1_ENUMERATED_get(o->responseStatus);
+	if (BIO_printf(bp, "    OCSP Response Status: %s (0x%lx)\n",
+	    OCSP_response_status_str(l), l) <= 0)
+		goto err;
+	if (rb == NULL)
+		return 1;
+	if (BIO_puts(bp, "    Response Type: ") <= 0)
+		goto err;
+	if (i2a_ASN1_OBJECT(bp, rb->responseType) <= 0)
+		goto err;
+	if (OBJ_obj2nid(rb->responseType) != NID_id_pkix_OCSP_basic) {
+		BIO_puts(bp, " (unknown response type)\n");
+		return 1;
+	}
+
+	i = ASN1_STRING_length(rb->response);
+	if (!(br = OCSP_response_get1_basic(o)))
+		goto err;
+	rd = br->tbsResponseData;
+	l = ASN1_INTEGER_get(rd->version);
+	if (BIO_printf(bp, "\n    Version: %lu (0x%lx)\n", l+1, l) <= 0)
+		goto err;
+	if (BIO_puts(bp, "    Responder Id: ") <= 0)
+		goto err;
+
+	rid = rd->responderId;
+	switch (rid->type) {
+	case V_OCSP_RESPID_NAME:
+		X509_NAME_print_ex(bp, rid->value.byName, 0, XN_FLAG_ONELINE);
+		break;
+	case V_OCSP_RESPID_KEY:
+		i2a_ASN1_STRING(bp, rid->value.byKey, V_ASN1_OCTET_STRING);
+		break;
+	}
+
+	if (BIO_printf(bp, "\n    Produced At: ")<=0)
+		goto err;
+	if (!ASN1_GENERALIZEDTIME_print(bp, rd->producedAt))
+		goto err;
+	if (BIO_printf(bp, "\n    Responses:\n") <= 0)
+		goto err;
+	for (i = 0; i < sk_OCSP_SINGLERESP_num(rd->responses); i++) {
+		if (! sk_OCSP_SINGLERESP_value(rd->responses, i))
+			continue;
+		single = sk_OCSP_SINGLERESP_value(rd->responses, i);
+		cid = single->certId;
+		if (ocsp_certid_print(bp, cid, 4) <= 0)
+			goto err;
+		cst = single->certStatus;
+		if (BIO_printf(bp, "    Cert Status: %s",
+		    OCSP_cert_status_str(cst->type)) <= 0)
+			goto err;
+		if (cst->type == V_OCSP_CERTSTATUS_REVOKED) {
+			rev = cst->value.revoked;
+			if (BIO_printf(bp, "\n    Revocation Time: ") <= 0)
+				goto err;
+			if (!ASN1_GENERALIZEDTIME_print(bp,
+			    rev->revocationTime))
+				goto err;
+			if (rev->revocationReason) {
+				l = ASN1_ENUMERATED_get(rev->revocationReason);
+				if (BIO_printf(bp,
+				    "\n    Revocation Reason: %s (0x%lx)",
+				    OCSP_crl_reason_str(l), l) <= 0)
+					goto err;
+			}
+		}
+		if (BIO_printf(bp, "\n    This Update: ") <= 0)
+			goto err;
+		if (!ASN1_GENERALIZEDTIME_print(bp, single->thisUpdate))
+			goto err;
+		if (single->nextUpdate) {
+			if (BIO_printf(bp, "\n    Next Update: ") <= 0)
+				goto err;
+			if (!ASN1_GENERALIZEDTIME_print(bp, single->nextUpdate))
+				goto err;
+		}
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+		if (!X509V3_extensions_print(bp, "Response Single Extensions",
+		    single->singleExtensions, flags, 8))
+			goto err;
+		if (BIO_write(bp, "\n", 1) <= 0)
+			goto err;
+	}
+	if (!X509V3_extensions_print(bp, "Response Extensions",
+	    rd->responseExtensions, flags, 4))
+		goto err;
+	if (X509_signature_print(bp, br->signatureAlgorithm, br->signature) <=
+	    0)
+		goto err;
+
+	for (i = 0; i < sk_X509_num(br->certs); i++) {
+		X509_print(bp, sk_X509_value(br->certs, i));
+		PEM_write_bio_X509(bp, sk_X509_value(br->certs, i));
+	}
+
+	ret = 1;
+
+err:
+	OCSP_BASICRESP_free(br);
+	return ret;
+}
+LCRYPTO_ALIAS(OCSP_RESPONSE_print);
diff --git a/crypto/ocsp/ocsp_srv.c b/crypto/ocsp/ocsp_srv.c
new file mode 100644
index 0000000..77c5e2e
--- /dev/null
+++ b/crypto/ocsp/ocsp_srv.c
@@ -0,0 +1,285 @@
+/* $OpenBSD: ocsp_srv.c,v 1.13 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+
+/* 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);
+}
+LCRYPTO_ALIAS(OCSP_request_onereq_count);
+
+OCSP_ONEREQ *
+OCSP_request_onereq_get0(OCSP_REQUEST *req, int i)
+{
+	return sk_OCSP_ONEREQ_value(req->tbsRequest->requestList, i);
+}
+LCRYPTO_ALIAS(OCSP_request_onereq_get0);
+
+OCSP_CERTID *
+OCSP_onereq_get0_id(OCSP_ONEREQ *one)
+{
+	return one->reqCert;
+}
+LCRYPTO_ALIAS(OCSP_onereq_get0_id);
+
+int
+OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
+    ASN1_OCTET_STRING **pikeyHash, ASN1_INTEGER **pserial, OCSP_CERTID *cid)
+{
+	if (!cid)
+		return 0;
+	if (pmd)
+		*pmd = cid->hashAlgorithm->algorithm;
+	if (piNameHash)
+		*piNameHash = cid->issuerNameHash;
+	if (pikeyHash)
+		*pikeyHash = cid->issuerKeyHash;
+	if (pserial)
+		*pserial = cid->serialNumber;
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_id_get0_info);
+
+int
+OCSP_request_is_signed(OCSP_REQUEST *req)
+{
+	if (req->optionalSignature)
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(OCSP_request_is_signed);
+
+/* Create an OCSP response and encode an optional basic response */
+OCSP_RESPONSE *
+OCSP_response_create(int status, OCSP_BASICRESP *bs)
+{
+	OCSP_RESPONSE *rsp = NULL;
+
+	if (!(rsp = OCSP_RESPONSE_new()))
+		goto err;
+	if (!(ASN1_ENUMERATED_set(rsp->responseStatus, status)))
+		goto err;
+	if (!bs)
+		return rsp;
+	if (!(rsp->responseBytes = OCSP_RESPBYTES_new()))
+		goto err;
+	rsp->responseBytes->responseType = OBJ_nid2obj(NID_id_pkix_OCSP_basic);
+	if (!ASN1_item_pack(bs, &OCSP_BASICRESP_it,
+	    &rsp->responseBytes->response))
+		goto err;
+	return rsp;
+
+err:
+	if (rsp)
+		OCSP_RESPONSE_free(rsp);
+	return NULL;
+}
+LCRYPTO_ALIAS(OCSP_response_create);
+
+OCSP_SINGLERESP *
+OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid, int status,
+    int reason, ASN1_TIME *revtime, ASN1_TIME *thisupd, ASN1_TIME *nextupd)
+{
+	OCSP_SINGLERESP *single = NULL;
+	OCSP_CERTSTATUS *cs;
+	OCSP_REVOKEDINFO *ri;
+
+	if (!rsp->tbsResponseData->responses &&
+	    !(rsp->tbsResponseData->responses = sk_OCSP_SINGLERESP_new_null()))
+		goto err;
+
+	if (!(single = OCSP_SINGLERESP_new()))
+		goto err;
+
+	if (!ASN1_TIME_to_generalizedtime(thisupd, &single->thisUpdate))
+		goto err;
+	if (nextupd &&
+	    !ASN1_TIME_to_generalizedtime(nextupd, &single->nextUpdate))
+		goto err;
+
+	OCSP_CERTID_free(single->certId);
+
+	if (!(single->certId = OCSP_CERTID_dup(cid)))
+		goto err;
+
+	cs = single->certStatus;
+	switch (cs->type = status) {
+	case V_OCSP_CERTSTATUS_REVOKED:
+		if (!revtime) {
+			OCSPerror(OCSP_R_NO_REVOKED_TIME);
+			goto err;
+		}
+		if (!(cs->value.revoked = ri = OCSP_REVOKEDINFO_new()))
+			goto err;
+		if (!ASN1_TIME_to_generalizedtime(revtime, &ri->revocationTime))
+			goto err;
+		if (reason != OCSP_REVOKED_STATUS_NOSTATUS) {
+			if (!(ri->revocationReason = ASN1_ENUMERATED_new()))
+				goto err;
+			if (!(ASN1_ENUMERATED_set(ri->revocationReason,
+			    reason)))
+				goto err;
+		}
+		break;
+
+	case V_OCSP_CERTSTATUS_GOOD:
+		cs->value.good = ASN1_NULL_new();
+		break;
+
+	case V_OCSP_CERTSTATUS_UNKNOWN:
+		cs->value.unknown = ASN1_NULL_new();
+		break;
+
+	default:
+		goto err;
+	}
+	if (!(sk_OCSP_SINGLERESP_push(rsp->tbsResponseData->responses, single)))
+		goto err;
+	return single;
+
+err:
+	OCSP_SINGLERESP_free(single);
+	return NULL;
+}
+LCRYPTO_ALIAS(OCSP_basic_add1_status);
+
+/* Add a certificate to an OCSP request */
+int
+OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert)
+{
+	if (!resp->certs && !(resp->certs = sk_X509_new_null()))
+		return 0;
+
+	if (!sk_X509_push(resp->certs, cert))
+		return 0;
+	X509_up_ref(cert);
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_basic_add1_cert);
+
+int
+OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key,
+    const EVP_MD *dgst, STACK_OF(X509) *certs, unsigned long flags)
+{
+	int i;
+	OCSP_RESPID *rid;
+
+	if (!X509_check_private_key(signer, key)) {
+		OCSPerror(OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+		goto err;
+	}
+
+	if (!(flags & OCSP_NOCERTS)) {
+		if (!OCSP_basic_add1_cert(brsp, signer))
+			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;
+	if (flags & OCSP_RESPID_KEY) {
+		unsigned char md[SHA_DIGEST_LENGTH];
+
+		X509_pubkey_digest(signer, EVP_sha1(), md, NULL);
+		if (!(rid->value.byKey = ASN1_OCTET_STRING_new()))
+			goto err;
+		if (!(ASN1_OCTET_STRING_set(rid->value.byKey, md,
+		    SHA_DIGEST_LENGTH)))
+			goto err;
+		rid->type = V_OCSP_RESPID_KEY;
+	} else {
+		if (!X509_NAME_set(&rid->value.byName,
+		    X509_get_subject_name(signer)))
+			goto err;
+		rid->type = V_OCSP_RESPID_NAME;
+	}
+
+	if (!(flags & OCSP_NOTIME) &&
+	    !ASN1_GENERALIZEDTIME_set(brsp->tbsResponseData->producedAt, time(NULL)))
+		goto err;
+
+	/* Right now, I think that not doing double hashing is the right
+	   thing.	-- Richard Levitte */
+
+	if (!OCSP_BASICRESP_sign(brsp, key, dgst, 0))
+		goto err;
+
+	return 1;
+
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(OCSP_basic_sign);
diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c
new file mode 100644
index 0000000..d197fe4
--- /dev/null
+++ b/crypto/ocsp/ocsp_vfy.c
@@ -0,0 +1,475 @@
+/* $OpenBSD: ocsp_vfy.c,v 1.23 2023/07/08 10:44:00 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include "ocsp_local.h"
+#include "x509_local.h"
+
+static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs,
+    STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags);
+static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id);
+static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
+    unsigned long flags);
+static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret);
+static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
+    STACK_OF(OCSP_SINGLERESP) *sresp);
+static int ocsp_check_delegated(X509 *x, int flags);
+static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req,
+    X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st,
+    unsigned long flags);
+
+/* 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;
+	int i, ret = 0;
+
+	ret = ocsp_find_signer(&signer, bs, certs, st, flags);
+	if (!ret) {
+		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+		goto end;
+	}
+	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
+		flags |= OCSP_NOVERIFY;
+	if (!(flags & OCSP_NOSIGS)) {
+		EVP_PKEY *skey;
+
+		skey = X509_get0_pubkey(signer);
+		if (skey) {
+			ret = OCSP_BASICRESP_verify(bs, skey, 0);
+		}
+		if (!skey || ret <= 0) {
+			OCSPerror(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))) {
+					OCSPerror(ERR_R_MALLOC_FAILURE);
+					goto end;
+				}
+			}
+		} else if (certs != NULL) {
+			untrusted = certs;
+		} else {
+			untrusted = bs->certs;
+		}
+		init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted);
+		if (!init_res) {
+			ret = -1;
+			OCSPerror(ERR_R_X509_LIB);
+			goto end;
+		}
+
+		if (X509_STORE_CTX_set_purpose(&ctx,
+		    X509_PURPOSE_OCSP_HELPER) == 0) {
+			X509_STORE_CTX_cleanup(&ctx);
+			ret = -1;
+			goto end;
+		}
+		ret = X509_verify_cert(&ctx);
+		chain = X509_STORE_CTX_get1_chain(&ctx);
+		X509_STORE_CTX_cleanup(&ctx);
+		if (ret <= 0) {
+			i = X509_STORE_CTX_get_error(&ctx);
+			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
+			ERR_asprintf_error_data("Verify error:%s",
+			    X509_verify_cert_error_string(i));
+			goto end;
+		}
+		if (flags & OCSP_NOCHECKS) {
+			ret = 1;
+			goto end;
+		}
+		/* At this point we have a valid certificate chain
+		 * need to verify it against the OCSP issuer criteria.
+		 */
+		ret = ocsp_check_issuer(bs, chain, flags);
+
+		/* If fatal error or valid match then finish */
+		if (ret != 0)
+			goto end;
+
+		/* Easy case: explicitly trusted. Get root CA and
+		 * check for explicit trust
+		 */
+		if (flags & OCSP_NOEXPLICIT)
+			goto end;
+
+		x = sk_X509_value(chain, sk_X509_num(chain) - 1);
+		if (X509_check_trust(x, NID_OCSP_sign, 0) !=
+			X509_TRUST_TRUSTED) {
+			OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED);
+			goto end;
+		}
+		ret = 1;
+	}
+
+end:
+	if (chain)
+		sk_X509_pop_free(chain, X509_free);
+	if (bs->certs && certs)
+		sk_X509_free(untrusted);
+	return ret;
+}
+LCRYPTO_ALIAS(OCSP_basic_verify);
+
+int
+OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
+    STACK_OF(X509) *extra_certs)
+{
+	return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0;
+}
+LCRYPTO_ALIAS(OCSP_resp_get0_signer);
+
+static int
+ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
+    X509_STORE *st, unsigned long flags)
+{
+	X509 *signer;
+	OCSP_RESPID *rid = bs->tbsResponseData->responderId;
+
+	if ((signer = ocsp_find_signer_sk(certs, rid))) {
+		*psigner = signer;
+		return 2;
+	}
+	if (!(flags & OCSP_NOINTERN) &&
+	    (signer = ocsp_find_signer_sk(bs->certs, rid))) {
+		*psigner = signer;
+		return 1;
+	}
+	/* Maybe lookup from store if by subject name */
+
+	*psigner = NULL;
+	return 0;
+}
+
+static X509 *
+ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id)
+{
+	int i;
+	unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash;
+	X509 *x;
+
+	/* Easy if lookup by name */
+	if (id->type == V_OCSP_RESPID_NAME)
+		return X509_find_by_subject(certs, id->value.byName);
+
+	/* Lookup by key hash */
+
+	/* If key hash isn't SHA1 length then forget it */
+	if (id->value.byKey->length != SHA_DIGEST_LENGTH)
+		return NULL;
+	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;
+	}
+	return NULL;
+}
+
+static int
+ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain,
+    unsigned long flags)
+{
+	STACK_OF(OCSP_SINGLERESP) *sresp;
+	X509 *signer, *sca;
+	OCSP_CERTID *caid = NULL;
+	int i;
+
+	sresp = bs->tbsResponseData->responses;
+
+	if (sk_X509_num(chain) <= 0) {
+		OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN);
+		return -1;
+	}
+
+	/* See if the issuer IDs match. */
+	i = ocsp_check_ids(sresp, &caid);
+
+	/* If ID mismatch or other error then return */
+	if (i <= 0)
+		return i;
+
+	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) {
+			/* We have a match, if extensions OK then success */
+			if (ocsp_check_delegated(signer, flags))
+				return 1;
+			return 0;
+		}
+	}
+
+	/* Otherwise check if OCSP request signed directly by request CA */
+	return ocsp_match_issuerid(signer, caid, sresp);
+}
+
+/* Check the issuer certificate IDs for equality. If there is a mismatch with the same
+ * algorithm then there's no point trying to match any certificates against the issuer.
+ * If the issuer IDs all match then we just need to check equality against one of them.
+ */
+static int
+ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret)
+{
+	OCSP_CERTID *tmpid, *cid;
+	int i, idcount;
+
+	idcount = sk_OCSP_SINGLERESP_num(sresp);
+	if (idcount <= 0) {
+		OCSPerror(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 */
+		if (OCSP_id_issuer_cmp(cid, tmpid)) {
+			return 0;
+		}
+	}
+
+	/* All IDs match: only need to check one ID */
+	*ret = cid;
+	return 1;
+}
+
+static int
+ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid,
+    STACK_OF(OCSP_SINGLERESP) *sresp)
+{
+	/* If only one ID to match then do it */
+	if (cid) {
+		const EVP_MD *dgst;
+		X509_NAME *iname;
+		int mdlen;
+		unsigned char md[EVP_MAX_MD_SIZE];
+
+		if (!(dgst =
+		    EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) {
+			OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST);
+			return -1;
+		}
+
+		mdlen = EVP_MD_size(dgst);
+		if (mdlen < 0)
+			return -1;
+		if (cid->issuerNameHash->length != mdlen ||
+		    cid->issuerKeyHash->length != mdlen)
+			return 0;
+		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;
+	} else {
+		/* We have to match the whole lot */
+		int i, ret;
+		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;
+	}
+}
+
+static int
+ocsp_check_delegated(X509 *x, int flags)
+{
+	X509_check_purpose(x, -1, 0);
+	if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN))
+		return 1;
+	OCSPerror(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.
+ */
+int
+OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store,
+    unsigned long flags)
+{
+	X509 *signer;
+	X509_NAME *nm;
+	GENERAL_NAME *gen;
+	int ret;
+	X509_STORE_CTX ctx;
+
+	if (!req->optionalSignature) {
+		OCSPerror(OCSP_R_REQUEST_NOT_SIGNED);
+		return 0;
+	}
+	gen = req->tbsRequest->requestorName;
+	if (!gen || gen->type != GEN_DIRNAME) {
+		OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE);
+		return 0;
+	}
+	nm = gen->d.directoryName;
+	ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags);
+	if (ret <= 0) {
+		OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND);
+		return 0;
+	}
+	if ((ret == 2) && (flags & OCSP_TRUSTOTHER))
+		flags |= OCSP_NOVERIFY;
+	if (!(flags & OCSP_NOSIGS)) {
+		EVP_PKEY *skey;
+
+		if ((skey = X509_get0_pubkey(signer)) == NULL)
+			return 0;
+		ret = OCSP_REQUEST_verify(req, skey);
+		if (ret <= 0) {
+			OCSPerror(OCSP_R_SIGNATURE_FAILURE);
+			return 0;
+		}
+	}
+	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) {
+			OCSPerror(ERR_R_X509_LIB);
+			return 0;
+		}
+
+		if (X509_STORE_CTX_set_purpose(&ctx,
+		      X509_PURPOSE_OCSP_HELPER) == 0 ||
+		    X509_STORE_CTX_set_trust(&ctx,
+		      X509_TRUST_OCSP_REQUEST) == 0) {
+			X509_STORE_CTX_cleanup(&ctx);
+			return 0;
+		}
+		ret = X509_verify_cert(&ctx);
+		X509_STORE_CTX_cleanup(&ctx);
+		if (ret <= 0) {
+			ret = X509_STORE_CTX_get_error(&ctx);
+			OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR);
+			ERR_asprintf_error_data("Verify error:%s",
+			    X509_verify_cert_error_string(ret));
+			return 0;
+		}
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(OCSP_request_verify);
+
+static int
+ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm,
+    STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags)
+{
+	X509 *signer;
+
+	if (!(flags & OCSP_NOINTERN)) {
+		signer = X509_find_by_subject(req->optionalSignature->certs, nm);
+		if (signer) {
+			*psigner = signer;
+			return 1;
+		}
+	}
+
+	signer = X509_find_by_subject(certs, nm);
+	if (signer) {
+		*psigner = signer;
+		return 2;
+	}
+	return 0;
+}
diff --git a/crypto/pem/pem_all.c b/crypto/pem/pem_all.c
new file mode 100644
index 0000000..21e325b
--- /dev/null
+++ b/crypto/pem/pem_all.c
@@ -0,0 +1,704 @@
+/* $OpenBSD: pem_all.c,v 1.21 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DH
+#include 
+#endif
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#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
+
+#ifndef OPENSSL_NO_EC
+static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey);
+#endif
+
+
+X509_REQ *
+PEM_read_X509_REQ(FILE *fp, X509_REQ **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_X509_REQ, PEM_STRING_X509_REQ, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_X509_REQ);
+
+int
+PEM_write_X509_REQ(FILE *fp, X509_REQ *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509_REQ, PEM_STRING_X509_REQ, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_X509_REQ);
+
+X509_REQ *
+PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509_REQ, PEM_STRING_X509_REQ, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_X509_REQ);
+
+int
+PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_REQ, PEM_STRING_X509_REQ, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_X509_REQ);
+
+int
+PEM_write_X509_REQ_NEW(FILE *fp, X509_REQ *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509_REQ, PEM_STRING_X509_REQ_OLD, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_X509_REQ_NEW);
+
+int
+PEM_write_bio_X509_REQ_NEW(BIO *bp, X509_REQ *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_REQ, PEM_STRING_X509_REQ_OLD, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_X509_REQ_NEW);
+
+X509_CRL *
+PEM_read_X509_CRL(FILE *fp, X509_CRL **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_X509_CRL, PEM_STRING_X509_CRL, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_X509_CRL);
+
+int
+PEM_write_X509_CRL(FILE *fp, X509_CRL *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509_CRL, PEM_STRING_X509_CRL, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_X509_CRL);
+
+X509_CRL *
+PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509_CRL, PEM_STRING_X509_CRL, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_X509_CRL);
+
+int
+PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_CRL, PEM_STRING_X509_CRL, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_X509_CRL);
+
+PKCS7 *
+PEM_read_PKCS7(FILE *fp, PKCS7 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_PKCS7, PEM_STRING_PKCS7, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_PKCS7);
+
+int
+PEM_write_PKCS7(FILE *fp, PKCS7 *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_PKCS7, PEM_STRING_PKCS7, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_PKCS7);
+
+PKCS7 *
+PEM_read_bio_PKCS7(BIO *bp, PKCS7 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_PKCS7, PEM_STRING_PKCS7, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_PKCS7);
+
+int
+PEM_write_bio_PKCS7(BIO *bp, PKCS7 *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_PKCS7, PEM_STRING_PKCS7, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS7);
+
+#ifndef OPENSSL_NO_RSA
+
+/* 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 the relevant private
+ * key: this means can handle "traditional" and PKCS#8 formats
+ * transparently.
+ */
+
+static RSA *
+pkey_get_rsa(EVP_PKEY *key, RSA **rsa)
+{
+	RSA *rtmp;
+
+	if (!key)
+		return NULL;
+	rtmp = EVP_PKEY_get1_RSA(key);
+	EVP_PKEY_free(key);
+	if (!rtmp)
+		return NULL;
+	if (rsa) {
+		RSA_free(*rsa);
+		*rsa = rtmp;
+	}
+	return rtmp;
+}
+
+RSA *
+PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+	return pkey_get_rsa(pktmp, rsa);
+}
+LCRYPTO_ALIAS(PEM_read_RSAPrivateKey);
+
+int
+PEM_write_RSAPrivateKey(FILE *fp, RSA *x, const EVP_CIPHER *enc,
+    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+        return PEM_ASN1_write((i2d_of_void *)i2d_RSAPrivateKey, PEM_STRING_RSA, fp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_RSAPrivateKey);
+
+RSA *
+PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+	return pkey_get_rsa(pktmp, rsa);
+}
+LCRYPTO_ALIAS(PEM_read_bio_RSAPrivateKey);
+
+int
+PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x,
+    const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb,
+    void *u)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_RSAPrivateKey, PEM_STRING_RSA, bp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_bio_RSAPrivateKey);
+
+RSA *
+PEM_read_RSAPublicKey(FILE *fp, RSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_RSAPublicKey, PEM_STRING_RSA_PUBLIC, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_RSAPublicKey);
+
+int
+PEM_write_RSAPublicKey(FILE *fp, const RSA *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_RSAPublicKey, PEM_STRING_RSA_PUBLIC, fp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_RSAPublicKey);
+
+RSA *
+PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_RSAPublicKey);
+
+int
+PEM_write_bio_RSAPublicKey(BIO *bp, const RSA *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_RSAPublicKey, PEM_STRING_RSA_PUBLIC, bp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_RSAPublicKey);
+
+RSA *
+PEM_read_RSA_PUBKEY(FILE *fp, RSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_RSA_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_RSA_PUBKEY);
+
+int
+PEM_write_RSA_PUBKEY(FILE *fp, RSA *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_RSA_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_RSA_PUBKEY);
+
+RSA *
+PEM_read_bio_RSA_PUBKEY(BIO *bp, RSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_RSA_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_RSA_PUBKEY);
+
+int
+PEM_write_bio_RSA_PUBKEY(BIO *bp, RSA *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_RSA_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_RSA_PUBKEY);
+
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+static DSA *
+pkey_get_dsa(EVP_PKEY *key, DSA **dsa)
+{
+	DSA *dtmp;
+
+	if (!key)
+		return NULL;
+	dtmp = EVP_PKEY_get1_DSA(key);
+	EVP_PKEY_free(key);
+	if (!dtmp)
+		return NULL;
+	if (dsa) {
+		DSA_free(*dsa);
+		*dsa = dtmp;
+	}
+	return dtmp;
+}
+
+DSA *
+PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+	return pkey_get_dsa(pktmp, dsa);	/* will free pktmp */
+}
+LCRYPTO_ALIAS(PEM_read_DSAPrivateKey);
+
+int
+PEM_write_DSAPrivateKey(FILE *fp, DSA *x, const EVP_CIPHER *enc,
+    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+        return PEM_ASN1_write((i2d_of_void *)i2d_DSAPrivateKey, PEM_STRING_DSA, fp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_DSAPrivateKey);
+
+DSA *
+PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+	return pkey_get_dsa(pktmp, dsa);	/* will free pktmp */
+}
+LCRYPTO_ALIAS(PEM_read_bio_DSAPrivateKey);
+
+int
+PEM_write_bio_DSAPrivateKey(BIO *bp, DSA *x,
+    const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb,
+    void *u)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAPrivateKey, PEM_STRING_DSA, bp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_bio_DSAPrivateKey);
+
+DSA *
+PEM_read_DSA_PUBKEY(FILE *fp, DSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_DSA_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_DSA_PUBKEY);
+
+int
+PEM_write_DSA_PUBKEY(FILE *fp, DSA *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_DSA_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_DSA_PUBKEY);
+
+int
+PEM_write_bio_DSA_PUBKEY(BIO *bp, DSA *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_DSA_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_DSA_PUBKEY);
+
+DSA *
+PEM_read_bio_DSA_PUBKEY(BIO *bp, DSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_DSA_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_DSA_PUBKEY);
+
+DSA *
+PEM_read_DSAparams(FILE *fp, DSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_DSAparams, PEM_STRING_DSAPARAMS, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_DSAparams);
+
+int
+PEM_write_DSAparams(FILE *fp, const DSA *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_DSAparams, PEM_STRING_DSAPARAMS, fp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_DSAparams);
+
+DSA *
+PEM_read_bio_DSAparams(BIO *bp, DSA **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_DSAparams, PEM_STRING_DSAPARAMS, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_DSAparams);
+
+int
+PEM_write_bio_DSAparams(BIO *bp, const DSA *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_DSAparams, PEM_STRING_DSAPARAMS, bp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_DSAparams);
+
+#endif
+
+
+#ifndef OPENSSL_NO_EC
+static EC_KEY *
+pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
+{
+	EC_KEY *dtmp;
+
+	if (!key)
+		return NULL;
+	dtmp = EVP_PKEY_get1_EC_KEY(key);
+	EVP_PKEY_free(key);
+	if (!dtmp)
+		return NULL;
+	if (eckey) {
+		EC_KEY_free(*eckey);
+		*eckey = dtmp;
+	}
+	return dtmp;
+}
+
+EC_GROUP *
+PEM_read_ECPKParameters(FILE *fp, EC_GROUP **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_ECPKParameters, PEM_STRING_ECPARAMETERS, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_ECPKParameters);
+
+int
+PEM_write_ECPKParameters(FILE *fp, const EC_GROUP *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_ECPKParameters, PEM_STRING_ECPARAMETERS, fp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_ECPKParameters);
+
+EC_GROUP *
+PEM_read_bio_ECPKParameters(BIO *bp, EC_GROUP **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_ECPKParameters, PEM_STRING_ECPARAMETERS, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_ECPKParameters);
+
+int
+PEM_write_bio_ECPKParameters(BIO *bp, const EC_GROUP *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_ECPKParameters, PEM_STRING_ECPARAMETERS, bp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_ECPKParameters);
+
+EC_KEY *
+PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+
+	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+	return pkey_get_eckey(pktmp, eckey);	/* will free pktmp */
+}
+LCRYPTO_ALIAS(PEM_read_ECPrivateKey);
+
+int
+PEM_write_ECPrivateKey(FILE *fp, EC_KEY *x, const EVP_CIPHER *enc,
+    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+        return PEM_ASN1_write((i2d_of_void *)i2d_ECPrivateKey, PEM_STRING_ECPRIVATEKEY, fp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_ECPrivateKey);
+
+EC_KEY *
+PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *pktmp;
+	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+	return pkey_get_eckey(pktmp, key);	/* will free pktmp */
+}
+LCRYPTO_ALIAS(PEM_read_bio_ECPrivateKey);
+
+int
+PEM_write_bio_ECPrivateKey(BIO *bp, EC_KEY *x,
+    const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb,
+    void *u)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_ECPrivateKey, PEM_STRING_ECPRIVATEKEY, bp,
+	    x, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_bio_ECPrivateKey);
+
+EC_KEY *
+PEM_read_EC_PUBKEY(FILE *fp, EC_KEY **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_EC_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_EC_PUBKEY);
+
+int
+PEM_write_EC_PUBKEY(FILE *fp, EC_KEY *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_EC_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_EC_PUBKEY);
+
+EC_KEY *
+PEM_read_bio_EC_PUBKEY(BIO *bp, EC_KEY **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_EC_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_EC_PUBKEY);
+
+int
+PEM_write_bio_EC_PUBKEY(BIO *bp, EC_KEY *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_EC_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_EC_PUBKEY);
+
+#endif
+
+#ifndef OPENSSL_NO_DH
+
+DH *
+PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_DHparams, PEM_STRING_DHPARAMS, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_DHparams);
+
+int
+PEM_write_DHparams(FILE *fp, const DH *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_DHparams, PEM_STRING_DHPARAMS, fp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_DHparams);
+
+DH *
+PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_DHparams, PEM_STRING_DHPARAMS, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_DHparams);
+
+int
+PEM_write_bio_DHparams(BIO *bp, const DH *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_DHparams, PEM_STRING_DHPARAMS, bp,
+	    (void *)x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_DHparams);
+
+#endif
+
+EVP_PKEY *
+PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_PUBKEY);
+
+int
+PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_PUBKEY, PEM_STRING_PUBLIC, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_PUBKEY);
+
+EVP_PKEY *
+PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_PUBKEY);
+
+int
+PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_PUBKEY, PEM_STRING_PUBLIC, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PUBKEY);
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
new file mode 100644
index 0000000..a94e2d5
--- /dev/null
+++ b/crypto/pem/pem_err.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: pem_err.c,v 1.14 2023/07/07 13:40:44 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_PEM,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_PEM,0,reason)
+
+static ERR_STRING_DATA PEM_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA PEM_str_reasons[] = {
+	{ERR_REASON(PEM_R_BAD_BASE64_DECODE)     , "bad base64 decode"},
+	{ERR_REASON(PEM_R_BAD_DECRYPT)           , "bad decrypt"},
+	{ERR_REASON(PEM_R_BAD_END_LINE)          , "bad end line"},
+	{ERR_REASON(PEM_R_BAD_IV_CHARS)          , "bad iv chars"},
+	{ERR_REASON(PEM_R_BAD_MAGIC_NUMBER)      , "bad magic number"},
+	{ERR_REASON(PEM_R_BAD_PASSWORD_READ)     , "bad password read"},
+	{ERR_REASON(PEM_R_BAD_VERSION_NUMBER)    , "bad version number"},
+	{ERR_REASON(PEM_R_BIO_WRITE_FAILURE)     , "bio write failure"},
+	{ERR_REASON(PEM_R_CIPHER_IS_NULL)        , "cipher is null"},
+	{ERR_REASON(PEM_R_ERROR_CONVERTING_PRIVATE_KEY), "error converting private key"},
+	{ERR_REASON(PEM_R_EXPECTING_PRIVATE_KEY_BLOB), "expecting private key blob"},
+	{ERR_REASON(PEM_R_EXPECTING_PUBLIC_KEY_BLOB), "expecting public key blob"},
+	{ERR_REASON(PEM_R_INCONSISTENT_HEADER)   , "inconsistent header"},
+	{ERR_REASON(PEM_R_KEYBLOB_HEADER_PARSE_ERROR), "keyblob header parse error"},
+	{ERR_REASON(PEM_R_KEYBLOB_TOO_SHORT)     , "keyblob too short"},
+	{ERR_REASON(PEM_R_NOT_DEK_INFO)          , "not dek info"},
+	{ERR_REASON(PEM_R_NOT_ENCRYPTED)         , "not encrypted"},
+	{ERR_REASON(PEM_R_NOT_PROC_TYPE)         , "not proc type"},
+	{ERR_REASON(PEM_R_NO_START_LINE)         , "no start line"},
+	{ERR_REASON(PEM_R_PROBLEMS_GETTING_PASSWORD), "problems getting password"},
+	{ERR_REASON(PEM_R_PUBLIC_KEY_NO_RSA)     , "public key no rsa"},
+	{ERR_REASON(PEM_R_PVK_DATA_TOO_SHORT)    , "pvk data too short"},
+	{ERR_REASON(PEM_R_PVK_TOO_SHORT)         , "pvk too short"},
+	{ERR_REASON(PEM_R_READ_KEY)              , "read key"},
+	{ERR_REASON(PEM_R_SHORT_HEADER)          , "short header"},
+	{ERR_REASON(PEM_R_UNSUPPORTED_CIPHER)    , "unsupported cipher"},
+	{ERR_REASON(PEM_R_UNSUPPORTED_ENCRYPTION), "unsupported encryption"},
+	{ERR_REASON(PEM_R_UNSUPPORTED_KEY_COMPONENTS), "unsupported key components"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_PEM_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(PEM_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, PEM_str_functs);
+		ERR_load_strings(0, PEM_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_PEM_strings);
diff --git a/crypto/pem/pem_info.c b/crypto/pem/pem_info.c
new file mode 100644
index 0000000..b979c79
--- /dev/null
+++ b/crypto/pem/pem_info.c
@@ -0,0 +1,387 @@
+/* $OpenBSD: pem_info.c,v 1.27 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DSA
+#include 
+#endif
+#ifndef OPENSSL_NO_RSA
+#include 
+#endif
+
+#include "evp_local.h"
+
+STACK_OF(X509_INFO) *
+PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
+    void *u)
+{
+	BIO *b;
+	STACK_OF(X509_INFO) *ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_X509_INFO_read);
+
+STACK_OF(X509_INFO) *
+PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb,
+    void *u)
+{
+	X509_INFO *xi = NULL;
+	char *name = NULL, *header = NULL;
+	void *pp;
+	unsigned char *data = NULL;
+	const unsigned char *p;
+	long len;
+	int ok = 0;
+	int num_in, ptype, raw;
+	STACK_OF(X509_INFO) *ret = sk;
+	d2i_of_void *d2i = NULL;
+
+	if (ret == NULL) {
+		if ((ret = sk_X509_INFO_new_null()) == NULL) {
+			PEMerror(ERR_R_MALLOC_FAILURE);
+			return NULL;
+		}
+	}
+	num_in = sk_X509_INFO_num(ret);
+
+	if ((xi = X509_INFO_new()) == NULL)
+		goto err;
+	for (;;) {
+		raw = 0;
+		ptype = 0;
+		if (!PEM_read_bio(bp, &name, &header, &data, &len)) {
+			if (ERR_GET_REASON(ERR_peek_last_error()) ==
+			    PEM_R_NO_START_LINE) {
+				ERR_clear_error();
+				break;
+			}
+			goto err;
+		}
+		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;
+			}
+			pp = &(xi->x509);
+		} else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
+			d2i = (D2I_OF(void))d2i_X509_AUX;
+			if (xi->x509 != NULL) {
+				if (!sk_X509_INFO_push(ret, xi))
+					goto err;
+				if ((xi = X509_INFO_new()) == NULL)
+					goto err;
+			}
+			pp = &(xi->x509);
+		} else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
+			d2i = (D2I_OF(void))d2i_X509_CRL;
+			if (xi->crl != NULL) {
+				if (!sk_X509_INFO_push(ret, xi))
+					goto err;
+				if ((xi = X509_INFO_new()) == NULL)
+					goto err;
+			}
+			pp = &(xi->crl);
+		} else
+#ifndef OPENSSL_NO_RSA
+		if (strcmp(name, PEM_STRING_RSA) == 0) {
+			d2i = (D2I_OF(void))d2i_RSAPrivateKey;
+			if (xi->x_pkey != NULL) {
+				if (!sk_X509_INFO_push(ret, xi))
+					goto err;
+				if ((xi = X509_INFO_new()) == NULL)
+					goto err;
+			}
+			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 (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;
+			}
+			xi->enc_data = NULL;
+			xi->enc_len = 0;
+			xi->x_pkey = X509_PKEY_new();
+			if (xi->x_pkey == NULL)
+				goto err;
+			ptype = EVP_PKEY_DSA;
+			pp = &xi->x_pkey->dec_pkey;
+			if (strlen(header) > 10) /* assume encrypted */
+				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;
+			}
+			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 (strlen(header) > 10) /* assume encrypted */
+				raw = 1;
+		} else
+#endif
+		{
+			d2i = NULL;
+			pp = NULL;
+		}
+
+		if (d2i != NULL) {
+			if (!raw) {
+				EVP_CIPHER_INFO cipher;
+
+				if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+					goto err;
+				if (!PEM_do_header(&cipher, data, &len, cb, u))
+					goto err;
+				p = data;
+				if (ptype) {
+					if (!d2i_PrivateKey(ptype, pp, &p,
+					    len)) {
+						PEMerror(ERR_R_ASN1_LIB);
+						goto err;
+					}
+				} else if (d2i(pp, &p, len) == NULL) {
+					PEMerror(ERR_R_ASN1_LIB);
+					goto err;
+				}
+			} else { /* encrypted RSA 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 */
+		}
+		free(name);
+		free(header);
+		free(data);
+		name = NULL;
+		header = NULL;
+		data = NULL;
+	}
+
+	/* if the last one hasn't been pushed yet and there is anything
+	 * in it then add it to the stack ...
+	 */
+	if ((xi->x509 != NULL) || (xi->crl != NULL) ||
+	    (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
+		if (!sk_X509_INFO_push(ret, xi))
+			goto err;
+		xi = NULL;
+	}
+	ok = 1;
+
+err:
+	if (!ok) {
+		while (sk_X509_INFO_num(ret) > num_in)
+			X509_INFO_free(sk_X509_INFO_pop(ret));
+		if (ret != sk)
+			sk_X509_INFO_free(ret);
+		ret = NULL;
+	}
+	X509_INFO_free(xi);
+	free(name);
+	free(header);
+	free(data);
+
+	return ret;
+}
+LCRYPTO_ALIAS(PEM_X509_INFO_read_bio);
+
+
+/* A TJH addition */
+int
+PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
+    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	EVP_CIPHER_CTX ctx;
+	int i, ret = 0;
+	unsigned char *data = NULL;
+	const char *objstr = NULL;
+	char buf[PEM_BUFSIZE];
+	unsigned char *iv = NULL;
+
+	if (enc != NULL) {
+		objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+		if (objstr == NULL) {
+			PEMerror(PEM_R_UNSUPPORTED_CIPHER);
+			goto err;
+		}
+	}
+
+	/* now for the fun part ... if we have a private key then
+	 * we have to be able to handle a not-yet-decrypted key
+	 * being written out correctly ... if it is decrypted or
+	 * it is non-encrypted then we use the base code
+	 */
+	if (xi->x_pkey != NULL) {
+		if ((xi->enc_data != NULL) && (xi->enc_len > 0) ) {
+			if (enc == NULL) {
+				PEMerror(PEM_R_CIPHER_IS_NULL);
+				goto err;
+			}
+
+			/* copy from weirdo names into more normal things */
+			iv = xi->enc_cipher.iv;
+			data = (unsigned char *)xi->enc_data;
+			i = xi->enc_len;
+
+			/* we take the encryption data from the
+			 * internal stuff rather 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));
+			if (objstr == NULL) {
+				PEMerror(PEM_R_UNSUPPORTED_CIPHER);
+				goto err;
+			}
+
+			/* create the right magic header stuff */
+			if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 >
+			    sizeof buf) {
+				PEMerror(ASN1_R_BUFFER_TOO_SMALL);
+				goto err;
+			}
+			buf[0] = '\0';
+			PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+			PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
+
+			/* use the normal code to write things out */
+			i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
+			if (i <= 0)
+				goto err;
+		} else {
+			/* Add DSA/DH */
+#ifndef OPENSSL_NO_RSA
+			/* normal optionally encrypted stuff */
+			if (PEM_write_bio_RSAPrivateKey(bp,
+			    xi->x_pkey->dec_pkey->pkey.rsa,
+			    enc, kstr, klen, cb, u) <= 0)
+				goto err;
+#endif
+		}
+	}
+
+	/* if we have a certificate then write it out now */
+	if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
+		goto err;
+
+	/* we are ignoring anything else that is loaded into the X509_INFO
+	 * structure for the moment ... as I don't need it so I'm not
+	 * coding it here and Eric can do it when this makes it into the
+	 * base library --tjh
+	 */
+
+	ret = 1;
+
+err:
+	explicit_bzero((char *)&ctx, sizeof(ctx));
+	explicit_bzero(buf, PEM_BUFSIZE);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_X509_INFO_write_bio);
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
new file mode 100644
index 0000000..3f23a01
--- /dev/null
+++ b/crypto/pem/pem_lib.c
@@ -0,0 +1,873 @@
+/* $OpenBSD: pem_lib.c,v 1.53 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_DES
+#include 
+#endif
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+#define MIN_LENGTH	4
+
+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);
+
+/* XXX LSSL ABI XXX return value and `num' ought to be size_t */
+int
+PEM_def_callback(char *buf, int num, int w, void *key)
+{
+	size_t l;
+	int i;
+	const char *prompt;
+
+	if (num < 0)
+		return -1;
+
+	if (key) {
+		l = strlen(key);
+		if (l > (size_t)num)
+			l = (size_t)num;
+		memcpy(buf, key, l);
+		return (int)l;
+	}
+
+	prompt = EVP_get_pw_prompt();
+	if (prompt == NULL)
+		prompt = "Enter PEM pass phrase:";
+
+	for (;;) {
+		i = EVP_read_pw_string_min(buf, MIN_LENGTH, num, prompt, w);
+		if (i != 0) {
+			PEMerror(PEM_R_PROBLEMS_GETTING_PASSWORD);
+			memset(buf, 0, num);
+			return (-1);
+		}
+		l = strlen(buf);
+		if (l < MIN_LENGTH) {
+			fprintf(stderr, "phrase is too short, "
+			    "needs to be at least %zu chars\n",
+			    (size_t)MIN_LENGTH);
+		} else
+			break;
+	}
+	return (int)l;
+}
+LCRYPTO_ALIAS(PEM_def_callback);
+
+void
+PEM_proc_type(char *buf, int type)
+{
+	const char *str;
+
+	if (type == PEM_TYPE_ENCRYPTED)
+		str = "ENCRYPTED";
+	else if (type == PEM_TYPE_MIC_CLEAR)
+		str = "MIC-CLEAR";
+	else if (type == PEM_TYPE_MIC_ONLY)
+		str = "MIC-ONLY";
+	else
+		str = "BAD-TYPE";
+
+	strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE);
+	strlcat(buf, str, PEM_BUFSIZE);
+	strlcat(buf, "\n", PEM_BUFSIZE);
+}
+LCRYPTO_ALIAS(PEM_proc_type);
+
+void
+PEM_dek_info(char *buf, const char *type, int len, char *str)
+{
+	static const unsigned char map[17] = "0123456789ABCDEF";
+	long i;
+	int j;
+
+	strlcat(buf, "DEK-Info: ", PEM_BUFSIZE);
+	strlcat(buf, type, PEM_BUFSIZE);
+	strlcat(buf, ",", PEM_BUFSIZE);
+	j = strlen(buf);
+	if (j + (len * 2) + 1 > PEM_BUFSIZE)
+		return;
+	for (i = 0; i < len; i++) {
+		buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
+		buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
+	}
+	buf[j + i * 2] = '\n';
+	buf[j + i * 2 + 1] = '\0';
+}
+LCRYPTO_ALIAS(PEM_dek_info);
+
+void *
+PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
+    pem_password_cb *cb, void *u)
+{
+	BIO *b;
+	void *ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_ASN1_read);
+
+static int
+check_pem(const char *nm, const char *name)
+{
+	/* Normal matching nm and name */
+	if (!strcmp(nm, name))
+		return 1;
+
+	/* Make PEM_STRING_EVP_PKEY match any private key */
+
+	if (!strcmp(name, PEM_STRING_EVP_PKEY)) {
+		int slen;
+		const EVP_PKEY_ASN1_METHOD *ameth;
+		if (!strcmp(nm, PEM_STRING_PKCS8))
+			return 1;
+		if (!strcmp(nm, PEM_STRING_PKCS8INF))
+			return 1;
+		slen = pem_check_suffix(nm, "PRIVATE KEY");
+		if (slen > 0) {
+			/* NB: ENGINE implementations wont contain
+			 * a deprecated old private key decode function
+			 * so don't look for them.
+			 */
+			ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
+			if (ameth && ameth->old_priv_decode)
+				return 1;
+		}
+		return 0;
+	}
+
+	if (!strcmp(name, PEM_STRING_PARAMETERS)) {
+		int slen;
+		const EVP_PKEY_ASN1_METHOD *ameth;
+		slen = pem_check_suffix(nm, "PARAMETERS");
+		if (slen > 0) {
+			ENGINE *e;
+			ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
+			if (ameth) {
+				int r;
+				if (ameth->param_decode)
+					r = 1;
+				else
+					r = 0;
+#ifndef OPENSSL_NO_ENGINE
+				ENGINE_finish(e);
+#endif
+				return r;
+			}
+		}
+		return 0;
+	}
+
+	/* Permit older strings */
+
+	if (!strcmp(nm, PEM_STRING_X509_OLD) &&
+	    !strcmp(name, PEM_STRING_X509))
+		return 1;
+
+	if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) &&
+	    !strcmp(name, PEM_STRING_X509_REQ))
+		return 1;
+
+	/* Allow normal certs to be read as trusted certs */
+	if (!strcmp(nm, PEM_STRING_X509) &&
+	    !strcmp(name, PEM_STRING_X509_TRUSTED))
+		return 1;
+
+	if (!strcmp(nm, PEM_STRING_X509_OLD) &&
+	    !strcmp(name, PEM_STRING_X509_TRUSTED))
+		return 1;
+
+	/* Some CAs use PKCS#7 with CERTIFICATE headers */
+	if (!strcmp(nm, PEM_STRING_X509) &&
+	    !strcmp(name, PEM_STRING_PKCS7))
+		return 1;
+
+	if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
+	    !strcmp(name, PEM_STRING_PKCS7))
+		return 1;
+
+#ifndef OPENSSL_NO_CMS
+	if (strcmp(nm, PEM_STRING_X509) == 0 &&
+	    strcmp(name, PEM_STRING_CMS) == 0)
+		return 1;
+
+	/* Allow CMS to be read from PKCS#7 headers */
+	if (strcmp(nm, PEM_STRING_PKCS7) == 0 &&
+	    strcmp(name, PEM_STRING_CMS) == 0)
+		return 1;
+#endif
+
+	return 0;
+}
+
+int
+PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
+    const char *name, BIO *bp, pem_password_cb *cb, void *u)
+{
+	EVP_CIPHER_INFO cipher;
+	char *nm = NULL, *header = NULL;
+	unsigned char *data = NULL;
+	long len;
+	int ret = 0;
+
+	for (;;) {
+		if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
+			if (ERR_GET_REASON(ERR_peek_error()) ==
+			    PEM_R_NO_START_LINE)
+				ERR_asprintf_error_data("Expecting: %s", name);
+			return 0;
+		}
+		if (check_pem(nm, name))
+			break;
+		free(nm);
+		free(header);
+		free(data);
+	}
+	if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+		goto err;
+	if (!PEM_do_header(&cipher, data, &len, cb, u))
+		goto err;
+
+	*pdata = data;
+	*plen = len;
+
+	if (pnm)
+		*pnm = nm;
+
+	ret = 1;
+
+err:
+	if (!ret || !pnm)
+		free(nm);
+	free(header);
+	if (!ret)
+		free(data);
+	return ret;
+}
+LCRYPTO_ALIAS(PEM_bytes_read_bio);
+
+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)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_ASN1_write);
+
+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)
+{
+	EVP_CIPHER_CTX ctx;
+	int dsize = 0, i, j, ret = 0;
+	unsigned char *p, *data = NULL;
+	const char *objstr = NULL;
+	char buf[PEM_BUFSIZE];
+	unsigned char key[EVP_MAX_KEY_LENGTH];
+	unsigned char iv[EVP_MAX_IV_LENGTH];
+
+	if (enc != NULL) {
+		objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+		if (objstr == NULL) {
+			PEMerror(PEM_R_UNSUPPORTED_CIPHER);
+			goto err;
+		}
+	}
+
+	if ((dsize = i2d(x, NULL)) < 0) {
+		PEMerror(ERR_R_ASN1_LIB);
+		dsize = 0;
+		goto err;
+	}
+	/* dzise + 8 bytes are needed */
+	/* actually it needs the cipher block size extra... */
+	data = malloc(dsize + 20);
+	if (data == NULL) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	p = data;
+	i = i2d(x, &p);
+
+	if (enc != NULL) {
+		if (kstr == NULL) {
+			if (callback == NULL)
+				klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
+			else
+				klen = (*callback)(buf, PEM_BUFSIZE, 1, u);
+			if (klen <= 0) {
+				PEMerror(PEM_R_READ_KEY);
+				goto err;
+			}
+			kstr = (unsigned char *)buf;
+		}
+		if ((size_t)enc->iv_len > sizeof(iv)) {
+			PEMerror(EVP_R_IV_TOO_LARGE);
+			goto err;
+		}
+		arc4random_buf(iv, enc->iv_len); /* Generate a salt */
+		/* The 'iv' is used as the iv and as a salt.  It is
+		 * NOT taken from the BytesToKey function */
+		if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1,
+		    key, NULL))
+			goto err;
+
+		if (kstr == (unsigned char *)buf)
+			explicit_bzero(buf, PEM_BUFSIZE);
+
+		if (strlen(objstr) + 23 + 2 * enc->iv_len + 13 > sizeof buf) {
+			PEMerror(ASN1_R_BUFFER_TOO_SMALL);
+			goto err;
+		}
+
+		buf[0] = '\0';
+		PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+		PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
+		/* k=strlen(buf); */
+
+		EVP_CIPHER_CTX_init(&ctx);
+		ret = 1;
+		if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) ||
+		    !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
+		    !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
+			ret = 0;
+		EVP_CIPHER_CTX_cleanup(&ctx);
+		if (ret == 0)
+			goto err;
+		i += j;
+	} else {
+		ret = 1;
+		buf[0] = '\0';
+	}
+	i = PEM_write_bio(bp, name, buf, data, i);
+	if (i <= 0)
+		ret = 0;
+err:
+	explicit_bzero(key, sizeof(key));
+	explicit_bzero(iv, sizeof(iv));
+	explicit_bzero((char *)&ctx, sizeof(ctx));
+	explicit_bzero(buf, PEM_BUFSIZE);
+	freezero(data, (unsigned int)dsize);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_ASN1_write_bio);
+
+int
+PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
+    pem_password_cb *callback, void *u)
+{
+	int i, j, o, klen;
+	long len;
+	EVP_CIPHER_CTX ctx;
+	unsigned char key[EVP_MAX_KEY_LENGTH];
+	char buf[PEM_BUFSIZE];
+
+	len = *plen;
+
+	if (cipher->cipher == NULL)
+		return (1);
+	if (callback == NULL)
+		klen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u);
+	else
+		klen = callback(buf, PEM_BUFSIZE, 0, u);
+	if (klen <= 0) {
+		PEMerror(PEM_R_BAD_PASSWORD_READ);
+		return (0);
+	}
+	if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]),
+	    (unsigned char *)buf, klen, 1, key, NULL))
+		return 0;
+
+	j = (int)len;
+	EVP_CIPHER_CTX_init(&ctx);
+	o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key,
+	    &(cipher->iv[0]));
+	if (o)
+		o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
+	if (o)
+		o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	explicit_bzero((char *)buf, sizeof(buf));
+	explicit_bzero((char *)key, sizeof(key));
+	if (!o) {
+		PEMerror(PEM_R_BAD_DECRYPT);
+		return (0);
+	}
+	*plen = j + i;
+	return (1);
+}
+LCRYPTO_ALIAS(PEM_do_header);
+
+int
+PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
+{
+	const EVP_CIPHER *enc = NULL;
+	char *p, c;
+	char **header_pp = &header;
+
+	cipher->cipher = NULL;
+	if ((header == NULL) || (*header == '\0') || (*header == '\n'))
+		return (1);
+	if (strncmp(header, "Proc-Type: ", 11) != 0) {
+		PEMerror(PEM_R_NOT_PROC_TYPE);
+		return (0);
+	}
+	header += 11;
+	if (*header != '4')
+		return (0);
+	header++;
+	if (*header != ',')
+		return (0);
+	header++;
+	if (strncmp(header, "ENCRYPTED", 9) != 0) {
+		PEMerror(PEM_R_NOT_ENCRYPTED);
+		return (0);
+	}
+	for (; (*header != '\n') && (*header != '\0'); header++)
+		;
+	if (*header == '\0') {
+		PEMerror(PEM_R_SHORT_HEADER);
+		return (0);
+	}
+	header++;
+	if (strncmp(header, "DEK-Info: ", 10) != 0) {
+		PEMerror(PEM_R_NOT_DEK_INFO);
+		return (0);
+	}
+	header += 10;
+
+	p = header;
+	for (;;) {
+		c= *header;
+		if (!(	((c >= 'A') && (c <= 'Z')) || (c == '-') ||
+		    ((c >= '0') && (c <= '9'))))
+			break;
+		header++;
+	}
+	*header = '\0';
+	cipher->cipher = enc = EVP_get_cipherbyname(p);
+	*header = c;
+	header++;
+
+	if (enc == NULL) {
+		PEMerror(PEM_R_UNSUPPORTED_ENCRYPTION);
+		return (0);
+	}
+	if (!load_iv(header_pp, &(cipher->iv[0]), enc->iv_len))
+		return (0);
+
+	return (1);
+}
+LCRYPTO_ALIAS(PEM_get_EVP_CIPHER_INFO);
+
+static int
+load_iv(char **fromp, unsigned char *to, int num)
+{
+	int v, i;
+	char *from;
+
+	from= *fromp;
+	for (i = 0; i < num; i++)
+		to[i] = 0;
+	num *= 2;
+	for (i = 0; i < num; i++) {
+		if ((*from >= '0') && (*from <= '9'))
+			v = *from - '0';
+		else if ((*from >= 'A') && (*from <= 'F'))
+			v = *from - 'A' + 10;
+		else if ((*from >= 'a') && (*from <= 'f'))
+			v = *from - 'a' + 10;
+		else {
+			PEMerror(PEM_R_BAD_IV_CHARS);
+			return (0);
+		}
+		from++;
+		to[i / 2] |= v << (long)((!(i & 1)) * 4);
+	}
+
+	*fromp = from;
+	return (1);
+}
+
+int
+PEM_write(FILE *fp, const char *name, const char *header,
+    const unsigned char *data, long len)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_write_bio(b, name, header, data, len);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_write);
+
+int
+PEM_write_bio(BIO *bp, const char *name, const char *header,
+    const unsigned char *data, long len)
+{
+	int nlen, n, i, j, outl;
+	unsigned char *buf = NULL;
+	EVP_ENCODE_CTX ctx;
+	int reason = ERR_R_BUF_LIB;
+
+	EVP_EncodeInit(&ctx);
+	nlen = strlen(name);
+
+	if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
+	    (BIO_write(bp, name, nlen) != nlen) ||
+	    (BIO_write(bp, "-----\n", 6) != 6))
+		goto err;
+
+	if (header != NULL && (i = strlen(header)) > 0) {
+		if ((BIO_write(bp, header, i) != i) ||
+		    (BIO_write(bp, "\n", 1) != 1))
+			goto err;
+	}
+
+	buf = reallocarray(NULL, PEM_BUFSIZE, 8);
+	if (buf == NULL) {
+		reason = ERR_R_MALLOC_FAILURE;
+		goto err;
+	}
+
+	i = j = 0;
+	while (len > 0) {
+		n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len);
+		if (!EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n))
+			goto err;
+		if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
+			goto err;
+		i += outl;
+		len -= n;
+		j += n;
+	}
+	EVP_EncodeFinal(&ctx, buf, &outl);
+	if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
+		goto err;
+	freezero(buf, PEM_BUFSIZE * 8);
+	buf = NULL;
+	if ((BIO_write(bp, "-----END ", 9) != 9) ||
+	    (BIO_write(bp, name, nlen) != nlen) ||
+	    (BIO_write(bp, "-----\n", 6) != 6))
+		goto err;
+	return (i + outl);
+
+err:
+	freezero(buf, PEM_BUFSIZE * 8);
+	PEMerror(reason);
+	return (0);
+}
+LCRYPTO_ALIAS(PEM_write_bio);
+
+int
+PEM_read(FILE *fp, char **name, char **header, unsigned char **data, long *len)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_read_bio(b, name, header, data, len);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_read);
+
+int
+PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
+    long *len)
+{
+	EVP_ENCODE_CTX ctx;
+	int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
+	char buf[256];
+	BUF_MEM *nameB;
+	BUF_MEM *headerB;
+	BUF_MEM *dataB, *tmpB;
+
+	nameB = BUF_MEM_new();
+	headerB = BUF_MEM_new();
+	dataB = BUF_MEM_new();
+	if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
+		BUF_MEM_free(nameB);
+		BUF_MEM_free(headerB);
+		BUF_MEM_free(dataB);
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		return (0);
+	}
+
+	buf[254] = '\0';
+	for (;;) {
+		i = BIO_gets(bp, buf, 254);
+
+		if (i <= 0) {
+			PEMerror(PEM_R_NO_START_LINE);
+			goto err;
+		}
+
+		while ((i >= 0) && (buf[i] <= ' '))
+			i--;
+		buf[++i] = '\n';
+		buf[++i] = '\0';
+
+		if (strncmp(buf, "-----BEGIN ", 11) == 0) {
+			i = strlen(&(buf[11]));
+
+			if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
+				continue;
+			if (!BUF_MEM_grow(nameB, i + 9)) {
+				PEMerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			memcpy(nameB->data, &(buf[11]), i - 6);
+			nameB->data[i - 6] = '\0';
+			break;
+		}
+	}
+	hl = 0;
+	if (!BUF_MEM_grow(headerB, 256)) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	headerB->data[0] = '\0';
+	for (;;) {
+		i = BIO_gets(bp, buf, 254);
+		if (i <= 0)
+			break;
+
+		while ((i >= 0) && (buf[i] <= ' '))
+			i--;
+		buf[++i] = '\n';
+		buf[++i] = '\0';
+
+		if (buf[0] == '\n')
+			break;
+		if (!BUF_MEM_grow(headerB, hl + i + 9)) {
+			PEMerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (strncmp(buf, "-----END ", 9) == 0) {
+			nohead = 1;
+			break;
+		}
+		memcpy(&(headerB->data[hl]), buf, i);
+		headerB->data[hl + i] = '\0';
+		hl += i;
+	}
+
+	bl = 0;
+	if (!BUF_MEM_grow(dataB, 1024)) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	dataB->data[0] = '\0';
+	if (!nohead) {
+		for (;;) {
+			i = BIO_gets(bp, buf, 254);
+			if (i <= 0)
+				break;
+
+			while ((i >= 0) && (buf[i] <= ' '))
+				i--;
+			buf[++i] = '\n';
+			buf[++i] = '\0';
+
+			if (i != 65)
+				end = 1;
+			if (strncmp(buf, "-----END ", 9) == 0)
+				break;
+			if (i > 65)
+				break;
+			if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
+				PEMerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			memcpy(&(dataB->data[bl]), buf, i);
+			dataB->data[bl + i] = '\0';
+			bl += i;
+			if (end) {
+				buf[0] = '\0';
+				i = BIO_gets(bp, buf, 254);
+				if (i <= 0)
+					break;
+
+				while ((i >= 0) && (buf[i] <= ' '))
+					i--;
+				buf[++i] = '\n';
+				buf[++i] = '\0';
+
+				break;
+			}
+		}
+	} else {
+		tmpB = headerB;
+		headerB = dataB;
+		dataB = tmpB;
+		bl = hl;
+	}
+	i = strlen(nameB->data);
+	if ((strncmp(buf, "-----END ", 9) != 0) ||
+	    (strncmp(nameB->data, &(buf[9]), i) != 0) ||
+	    (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
+		PEMerror(PEM_R_BAD_END_LINE);
+		goto err;
+	}
+
+	EVP_DecodeInit(&ctx);
+	i = EVP_DecodeUpdate(&ctx,
+	    (unsigned char *)dataB->data, &bl,
+	    (unsigned char *)dataB->data, bl);
+	if (i < 0) {
+		PEMerror(PEM_R_BAD_BASE64_DECODE);
+		goto err;
+	}
+	i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
+	if (i < 0) {
+		PEMerror(PEM_R_BAD_BASE64_DECODE);
+		goto err;
+	}
+	bl += k;
+
+	if (bl == 0)
+		goto err;
+	*name = nameB->data;
+	*header = headerB->data;
+	*data = (unsigned char *)dataB->data;
+	*len = bl;
+	free(nameB);
+	free(headerB);
+	free(dataB);
+	return (1);
+
+err:
+	BUF_MEM_free(nameB);
+	BUF_MEM_free(headerB);
+	BUF_MEM_free(dataB);
+	return (0);
+}
+LCRYPTO_ALIAS(PEM_read_bio);
+
+/* Check pem string and return prefix length.
+ * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
+ * the return value is 3 for the string "RSA".
+ */
+
+int
+pem_check_suffix(const char *pem_str, const char *suffix)
+{
+	int pem_len = strlen(pem_str);
+	int suffix_len = strlen(suffix);
+	const char *p;
+
+	if (suffix_len + 1 >= pem_len)
+		return 0;
+	p = pem_str + pem_len - suffix_len;
+	if (strcmp(p, suffix))
+		return 0;
+	p--;
+	if (*p != ' ')
+		return 0;
+	return p - pem_str;
+}
diff --git a/crypto/pem/pem_oth.c b/crypto/pem/pem_oth.c
new file mode 100644
index 0000000..2dca978
--- /dev/null
+++ b/crypto/pem/pem_oth.c
@@ -0,0 +1,88 @@
+/* $OpenBSD: pem_oth.c,v 1.9 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Handle 'other' PEMs: not private keys */
+
+void *
+PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
+    pem_password_cb *cb, void *u)
+{
+	const unsigned char *p = NULL;
+	unsigned char *data = NULL;
+	long len;
+	char *ret = NULL;
+
+	if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u))
+		return NULL;
+	p = data;
+	ret = d2i(x, &p, len);
+	if (ret == NULL)
+		PEMerror(ERR_R_ASN1_LIB);
+	free(data);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_ASN1_read_bio);
diff --git a/crypto/pem/pem_pk8.c b/crypto/pem/pem_pk8.c
new file mode 100644
index 0000000..6d0c0cb
--- /dev/null
+++ b/crypto/pem/pem_pk8.c
@@ -0,0 +1,324 @@
+/* $OpenBSD: pem_pk8.c,v 1.14 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+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_fp(FILE *bp, EVP_PKEY *x, int isder, int nid,
+    const EVP_CIPHER *enc, char *kstr, int klen, pem_password_cb *cb, void *u);
+
+/* These functions write a private key in PKCS#8 format: it is a "drop in"
+ * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
+ * is NULL then it uses the unencrypted private key form. The 'nid' versions
+ * 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, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS8PrivateKey_nid);
+
+int
+PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+    char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS8PrivateKey);
+
+int
+i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
+    char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(i2d_PKCS8PrivateKey_bio);
+
+int
+i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
+    char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(i2d_PKCS8PrivateKey_nid_bio);
+
+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)
+{
+	X509_SIG *p8;
+	PKCS8_PRIV_KEY_INFO *p8inf;
+	char buf[PEM_BUFSIZE];
+	int ret;
+
+	if (!(p8inf = EVP_PKEY2PKCS8(x))) {
+		PEMerror(PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+		return 0;
+	}
+	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) {
+				PEMerror(PEM_R_READ_KEY);
+				PKCS8_PRIV_KEY_INFO_free(p8inf);
+				return 0;
+			}
+
+			kstr = buf;
+		}
+		p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
+		if (kstr == buf)
+			explicit_bzero(buf, klen);
+		PKCS8_PRIV_KEY_INFO_free(p8inf);
+		if (isder)
+			ret = i2d_PKCS8_bio(bp, p8);
+		else
+			ret = PEM_write_bio_PKCS8(bp, p8);
+		X509_SIG_free(p8);
+		return ret;
+	} else {
+		if (isder)
+			ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+		else
+			ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+		PKCS8_PRIV_KEY_INFO_free(p8inf);
+		return ret;
+	}
+}
+
+EVP_PKEY *
+d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+	PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+	X509_SIG *p8 = NULL;
+	int klen;
+	EVP_PKEY *ret;
+	char psbuf[PEM_BUFSIZE];
+
+	p8 = d2i_PKCS8_bio(bp, NULL);
+	if (!p8)
+		return NULL;
+	if (cb)
+		klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+	else
+		klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
+	if (klen <= 0) {
+		PEMerror(PEM_R_BAD_PASSWORD_READ);
+		X509_SIG_free(p8);
+		return NULL;
+	}
+	p8inf = PKCS8_decrypt(p8, psbuf, klen);
+	X509_SIG_free(p8);
+	if (!p8inf)
+		return NULL;
+	ret = EVP_PKCS82PKEY(p8inf);
+	PKCS8_PRIV_KEY_INFO_free(p8inf);
+	if (!ret)
+		return NULL;
+	if (x) {
+		EVP_PKEY_free(*x);
+		*x = ret;
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(d2i_PKCS8PrivateKey_bio);
+
+
+int
+i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+    char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(i2d_PKCS8PrivateKey_fp);
+
+int
+i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid, char *kstr,
+    int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(i2d_PKCS8PrivateKey_nid_fp);
+
+int
+PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, char *kstr,
+    int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_PKCS8PrivateKey_nid);
+
+int
+PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+    char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
+}
+LCRYPTO_ALIAS(PEM_write_PKCS8PrivateKey);
+
+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)
+{
+	BIO *bp;
+	int ret;
+
+	if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
+	BIO_free(bp);
+	return ret;
+}
+
+EVP_PKEY *
+d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+	BIO *bp;
+	EVP_PKEY *ret;
+
+	if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+		PEMerror(ERR_R_BUF_LIB);
+		return NULL;
+	}
+	ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
+	BIO_free(bp);
+	return ret;
+}
+LCRYPTO_ALIAS(d2i_PKCS8PrivateKey_fp);
+
+X509_SIG *
+PEM_read_PKCS8(FILE *fp, X509_SIG **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_X509_SIG, PEM_STRING_PKCS8, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_PKCS8);
+
+int
+PEM_write_PKCS8(FILE *fp, X509_SIG *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509_SIG, PEM_STRING_PKCS8, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_PKCS8);
+
+X509_SIG *
+PEM_read_bio_PKCS8(BIO *bp, X509_SIG **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509_SIG, PEM_STRING_PKCS8, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_PKCS8);
+
+int
+PEM_write_bio_PKCS8(BIO *bp, X509_SIG *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_SIG, PEM_STRING_PKCS8, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS8);
+
+PKCS8_PRIV_KEY_INFO *
+PEM_read_PKCS8_PRIV_KEY_INFO(FILE *fp, PKCS8_PRIV_KEY_INFO **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_PKCS8_PRIV_KEY_INFO);
+
+int
+PEM_write_PKCS8_PRIV_KEY_INFO(FILE *fp, PKCS8_PRIV_KEY_INFO *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_PKCS8_PRIV_KEY_INFO);
+
+PKCS8_PRIV_KEY_INFO *
+PEM_read_bio_PKCS8_PRIV_KEY_INFO(BIO *bp, PKCS8_PRIV_KEY_INFO **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_PKCS8_PRIV_KEY_INFO);
+
+int
+PEM_write_bio_PKCS8_PRIV_KEY_INFO(BIO *bp, PKCS8_PRIV_KEY_INFO *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS8_PRIV_KEY_INFO);
diff --git a/crypto/pem/pem_pkey.c b/crypto/pem/pem_pkey.c
new file mode 100644
index 0000000..2961952
--- /dev/null
+++ b/crypto/pem/pem_pkey.c
@@ -0,0 +1,267 @@
+/* $OpenBSD: pem_pkey.c,v 1.27 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+#include "asn1_local.h"
+#include "evp_local.h"
+
+int 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)
+{
+	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_EVP_PKEY,
+	    bp, cb, u))
+		return NULL;
+	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)
+			goto p8err;
+		ret = EVP_PKCS82PKEY(p8inf);
+		if (x) {
+			EVP_PKEY_free(*x);
+			*x = ret;
+		}
+		PKCS8_PRIV_KEY_INFO_free(p8inf);
+	} else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
+		PKCS8_PRIV_KEY_INFO *p8inf;
+		X509_SIG *p8;
+		int klen;
+		char psbuf[PEM_BUFSIZE];
+		p8 = d2i_X509_SIG(NULL, &p, len);
+		if (!p8)
+			goto p8err;
+		if (cb)
+			klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+		else
+			klen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
+		if (klen <= 0) {
+			PEMerror(PEM_R_BAD_PASSWORD_READ);
+			X509_SIG_free(p8);
+			goto err;
+		}
+		p8inf = PKCS8_decrypt(p8, psbuf, klen);
+		X509_SIG_free(p8);
+		if (!p8inf)
+			goto p8err;
+		ret = EVP_PKCS82PKEY(p8inf);
+		if (x) {
+			EVP_PKEY_free(*x);
+			*x = ret;
+		}
+		PKCS8_PRIV_KEY_INFO_free(p8inf);
+	} else if ((slen = 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)
+			goto p8err;
+		ret = d2i_PrivateKey(ameth->pkey_id, x, &p, len);
+	}
+
+p8err:
+	if (ret == NULL)
+		PEMerror(ERR_R_ASN1_LIB);
+err:
+	free(nm);
+	freezero(data, len);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_read_bio_PrivateKey);
+
+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);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PrivateKey);
+
+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];
+
+	(void) snprintf(pem_str, sizeof(pem_str), "%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);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PrivateKey_traditional);
+
+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 = EVP_PKEY_new();
+		if (!ret)
+			goto err;
+		if (!EVP_PKEY_set_type_str(ret, nm, slen) ||
+		    !ret->ameth->param_decode ||
+		    !ret->ameth->param_decode(ret, &p, len)) {
+			EVP_PKEY_free(ret);
+			ret = NULL;
+			goto err;
+		}
+		if (x) {
+			EVP_PKEY_free(*x);
+			*x = ret;
+		}
+	}
+
+err:
+	if (ret == NULL)
+		PEMerror(ERR_R_ASN1_LIB);
+	free(nm);
+	free(data);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_read_bio_Parameters);
+
+int
+PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
+{
+	char pem_str[80];
+
+	if (!x->ameth || !x->ameth->param_encode)
+		return 0;
+
+	(void) snprintf(pem_str, sizeof(pem_str), "%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);
+}
+LCRYPTO_ALIAS(PEM_write_bio_Parameters);
+
+EVP_PKEY *
+PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+{
+	BIO *b;
+	EVP_PKEY *ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return (0);
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = PEM_read_bio_PrivateKey(b, x, cb, u);
+	BIO_free(b);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_read_PrivateKey);
+
+int
+PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
+    unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
+		PEMerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+	BIO_free(b);
+	return ret;
+}
+LCRYPTO_ALIAS(PEM_write_PrivateKey);
diff --git a/crypto/pem/pem_sign.c b/crypto/pem/pem_sign.c
new file mode 100644
index 0000000..461f957
--- /dev/null
+++ b/crypto/pem/pem_sign.c
@@ -0,0 +1,108 @@
+/* $OpenBSD: pem_sign.c,v 1.15 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type)
+{
+	return EVP_DigestInit_ex(ctx, type, NULL);
+}
+LCRYPTO_ALIAS(PEM_SignInit);
+
+int
+PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data,
+    unsigned int count)
+{
+	return EVP_DigestUpdate(ctx, data, count);
+}
+LCRYPTO_ALIAS(PEM_SignUpdate);
+
+int
+PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, unsigned int *siglen,
+    EVP_PKEY *pkey)
+{
+	unsigned char *m;
+	int i, ret = 0;
+	unsigned int m_len;
+
+	m = malloc(EVP_PKEY_size(pkey) + 2);
+	if (m == NULL) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_SignFinal(ctx, m, &m_len, pkey) <= 0)
+		goto err;
+
+	i = EVP_EncodeBlock(sigret, m, m_len);
+	*siglen = i;
+	ret = 1;
+
+err:
+	/* ctx has been zeroed by EVP_SignFinal() */
+	free(m);
+	return (ret);
+}
+LCRYPTO_ALIAS(PEM_SignFinal);
diff --git a/crypto/pem/pem_x509.c b/crypto/pem/pem_x509.c
new file mode 100644
index 0000000..0016413
--- /dev/null
+++ b/crypto/pem/pem_x509.c
@@ -0,0 +1,98 @@
+/* $OpenBSD: pem_x509.c,v 1.9 2023/07/07 13:40:44 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+X509 *
+PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_X509, PEM_STRING_X509, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_X509);
+
+int
+PEM_write_X509(FILE *fp, X509 *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509, PEM_STRING_X509, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_X509);
+
+X509 *
+PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509, PEM_STRING_X509, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_X509);
+
+int
+PEM_write_bio_X509(BIO *bp, X509 *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509, PEM_STRING_X509, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_X509);
diff --git a/crypto/pem/pem_xaux.c b/crypto/pem/pem_xaux.c
new file mode 100644
index 0000000..5f44a2b
--- /dev/null
+++ b/crypto/pem/pem_xaux.c
@@ -0,0 +1,98 @@
+/* $OpenBSD: pem_xaux.c,v 1.11 2023/07/07 13:40:44 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+X509 *
+PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read((d2i_of_void *)d2i_X509_AUX, PEM_STRING_X509_TRUSTED, fp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_X509_AUX);
+
+int
+PEM_write_X509_AUX(FILE *fp, X509 *x)
+{
+	return PEM_ASN1_write((i2d_of_void *)i2d_X509_AUX, PEM_STRING_X509_TRUSTED, fp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_X509_AUX);
+
+X509 *
+PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u)
+{
+	return PEM_ASN1_read_bio((d2i_of_void *)d2i_X509_AUX, PEM_STRING_X509_TRUSTED, bp,
+	    (void **)x, cb, u);
+}
+LCRYPTO_ALIAS(PEM_read_bio_X509_AUX);
+
+int
+PEM_write_bio_X509_AUX(BIO *bp, X509 *x)
+{
+	return PEM_ASN1_write_bio((i2d_of_void *)i2d_X509_AUX, PEM_STRING_X509_TRUSTED, bp,
+	    x, NULL, NULL, 0, NULL, NULL);
+}
+LCRYPTO_ALIAS(PEM_write_bio_X509_AUX);
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
new file mode 100644
index 0000000..816d8b7
--- /dev/null
+++ b/crypto/pem/pvkfmt.c
@@ -0,0 +1,944 @@
+/* $OpenBSD: pvkfmt.c,v 1.27 2023/07/07 13:40:44 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB
+ * and PRIVATEKEYBLOB).
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
+#include 
+#include 
+
+#include "bn_local.h"
+#include "dsa_local.h"
+#include "evp_local.h"
+#include "rsa_local.h"
+
+/* Utility function: read a DWORD (4 byte unsigned integer) in little endian
+ * format
+ */
+
+static unsigned int
+read_ledword(const unsigned char **in)
+{
+	const unsigned char *p = *in;
+	unsigned int ret;
+
+	ret = *p++;
+	ret |= (*p++ << 8);
+	ret |= (*p++ << 16);
+	ret |= (*p++ << 24);
+	*in = p;
+	return ret;
+}
+
+/* Read a BIGNUM in little endian format. The docs say that this should take up
+ * bitlen/8 bytes.
+ */
+
+static int
+read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
+{
+	const unsigned char *p;
+	unsigned char *tmpbuf, *q;
+	unsigned int i;
+
+	p = *in + nbyte - 1;
+	tmpbuf = malloc(nbyte);
+	if (!tmpbuf)
+		return 0;
+	q = tmpbuf;
+	for (i = 0; i < nbyte; i++)
+		*q++ = *p--;
+	*r = BN_bin2bn(tmpbuf, nbyte, NULL);
+	free(tmpbuf);
+	if (*r) {
+		*in += nbyte;
+		return 1;
+	} else
+		return 0;
+}
+
+
+/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */
+
+#define MS_PUBLICKEYBLOB	0x6
+#define MS_PRIVATEKEYBLOB	0x7
+#define MS_RSA1MAGIC		0x31415352L
+#define MS_RSA2MAGIC		0x32415352L
+#define MS_DSS1MAGIC		0x31535344L
+#define MS_DSS2MAGIC		0x32535344L
+
+#define MS_KEYALG_RSA_KEYX	0xa400
+#define MS_KEYALG_DSS_SIGN	0x2200
+
+#define MS_KEYTYPE_KEYX		0x1
+#define MS_KEYTYPE_SIGN		0x2
+
+/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
+#define MS_PVKMAGIC		0xb0b5f11eL
+/* Salt length for PVK files */
+#define PVK_SALTLEN		0x10
+
+static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
+    unsigned int bitlen, int ispub);
+static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
+    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)
+{
+	const unsigned char *p = *in;
+
+	if (length < 16)
+		return 0;
+	/* bType */
+	if (*p == MS_PUBLICKEYBLOB) {
+		if (*pispub == 0) {
+			PEMerror(PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+			return 0;
+		}
+		*pispub = 1;
+	} else if (*p == MS_PRIVATEKEYBLOB) {
+		if (*pispub == 1) {
+			PEMerror(PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+			return 0;
+		}
+		*pispub = 0;
+	} else
+		return 0;
+	p++;
+	/* Version */
+	if (*p++ != 0x2) {
+		PEMerror(PEM_R_BAD_VERSION_NUMBER);
+		return 0;
+	}
+	/* Ignore reserved, aiKeyAlg */
+	p += 6;
+	*pmagic = read_ledword(&p);
+	*pbitlen = read_ledword(&p);
+	if (*pbitlen > 65536) {
+		PEMerror(PEM_R_INCONSISTENT_HEADER);
+		return 0;
+	}
+	*pisdss = 0;
+	switch (*pmagic) {
+
+	case MS_DSS1MAGIC:
+		*pisdss = 1;
+	case MS_RSA1MAGIC:
+		if (*pispub == 0) {
+			PEMerror(PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
+			return 0;
+		}
+		break;
+
+	case MS_DSS2MAGIC:
+		*pisdss = 1;
+	case MS_RSA2MAGIC:
+		if (*pispub == 1) {
+			PEMerror(PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
+			return 0;
+		}
+		break;
+
+	default:
+		PEMerror(PEM_R_BAD_MAGIC_NUMBER);
+		return -1;
+	}
+	*in = p;
+	return 1;
+}
+
+static unsigned int
+blob_length(unsigned bitlen, int isdss, int ispub)
+{
+	unsigned int nbyte, hnbyte;
+
+	nbyte = (bitlen + 7) >> 3;
+	hnbyte = (bitlen + 15) >> 4;
+	if (isdss) {
+
+		/* Expected length: 20 for q + 3 components bitlen each + 24
+		 * for seed structure.
+		 */
+		if (ispub)
+			return 44 + 3 * nbyte;
+		/* Expected length: 20 for q, priv, 2 bitlen components + 24
+		 * for seed structure.
+		 */
+		else
+			return 64 + 2 * nbyte;
+	} else {
+		/* Expected length: 4 for 'e' + 'n' */
+		if (ispub)
+			return 4 + nbyte;
+		else
+		/* Expected length: 4 for 'e' and 7 other components.
+		 * 2 components are bitlen size, 5 are bitlen/2
+		 */
+				return 4 + 2*nbyte + 5*hnbyte;
+	}
+
+}
+
+static EVP_PKEY *
+do_b2i(const unsigned char **in, unsigned int length, int ispub)
+{
+	const unsigned char *p = *in;
+	unsigned int bitlen, magic;
+	int isdss;
+
+	if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0) {
+		PEMerror(PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
+		return NULL;
+	}
+	length -= 16;
+	if (length < blob_length(bitlen, isdss, ispub)) {
+		PEMerror(PEM_R_KEYBLOB_TOO_SHORT);
+		return NULL;
+	}
+	if (isdss)
+		return b2i_dss(&p, length, bitlen, ispub);
+	else
+		return b2i_rsa(&p, length, bitlen, ispub);
+}
+
+static EVP_PKEY *
+do_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;
+
+	if (BIO_read(in, hdr_buf, 16) != 16) {
+		PEMerror(PEM_R_KEYBLOB_TOO_SHORT);
+		return NULL;
+	}
+	p = hdr_buf;
+	if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
+		return NULL;
+
+	length = blob_length(bitlen, isdss, ispub);
+	buf = malloc(length);
+	if (!buf) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	p = buf;
+	if (BIO_read(in, buf, length) != (int)length) {
+		PEMerror(PEM_R_KEYBLOB_TOO_SHORT);
+		goto err;
+	}
+
+	if (isdss)
+		ret = b2i_dss(&p, length, bitlen, ispub);
+	else
+		ret = b2i_rsa(&p, length, bitlen, ispub);
+
+ err:
+	free(buf);
+	return ret;
+}
+
+static EVP_PKEY *
+b2i_dss(const unsigned char **in, unsigned int length, unsigned int bitlen,
+    int ispub)
+{
+	const unsigned char *p = *in;
+	EVP_PKEY *ret = NULL;
+	DSA *dsa = NULL;
+	BN_CTX *ctx = NULL;
+	unsigned int nbyte;
+
+	nbyte = (bitlen + 7) >> 3;
+
+	dsa = DSA_new();
+	ret = EVP_PKEY_new();
+	if (!dsa || !ret)
+		goto err;
+	if (!read_lebn(&p, nbyte, &dsa->p))
+		goto err;
+	if (!read_lebn(&p, 20, &dsa->q))
+		goto err;
+	if (!read_lebn(&p, nbyte, &dsa->g))
+		goto err;
+	if (ispub) {
+		if (!read_lebn(&p, nbyte, &dsa->pub_key))
+			goto err;
+	} else {
+		if (!read_lebn(&p, 20, &dsa->priv_key))
+			goto err;
+		/* Calculate public key */
+		if (!(dsa->pub_key = BN_new()))
+			goto err;
+		if (!(ctx = BN_CTX_new()))
+			goto err;
+		if (!BN_mod_exp_ct(dsa->pub_key, dsa->g,
+		    dsa->priv_key, dsa->p, ctx))
+			goto err;
+		BN_CTX_free(ctx);
+	}
+
+	EVP_PKEY_set1_DSA(ret, dsa);
+	DSA_free(dsa);
+	*in = p;
+	return ret;
+
+ err:
+	PEMerror(ERR_R_MALLOC_FAILURE);
+	DSA_free(dsa);
+	EVP_PKEY_free(ret);
+	BN_CTX_free(ctx);
+	return NULL;
+}
+
+static EVP_PKEY *
+b2i_rsa(const unsigned char **in, unsigned int length, unsigned int bitlen,
+    int ispub)
+{
+	const unsigned char *p = *in;
+	EVP_PKEY *ret = NULL;
+	RSA *rsa = NULL;
+	unsigned int nbyte, hnbyte;
+
+	nbyte = (bitlen + 7) >> 3;
+	hnbyte = (bitlen + 15) >> 4;
+	rsa = RSA_new();
+	ret = EVP_PKEY_new();
+	if (!rsa || !ret)
+		goto err;
+	rsa->e = BN_new();
+	if (!rsa->e)
+		goto err;
+	if (!BN_set_word(rsa->e, read_ledword(&p)))
+		goto err;
+	if (!read_lebn(&p, nbyte, &rsa->n))
+		goto err;
+	if (!ispub) {
+		if (!read_lebn(&p, hnbyte, &rsa->p))
+			goto err;
+		if (!read_lebn(&p, hnbyte, &rsa->q))
+			goto err;
+		if (!read_lebn(&p, hnbyte, &rsa->dmp1))
+			goto err;
+		if (!read_lebn(&p, hnbyte, &rsa->dmq1))
+			goto err;
+		if (!read_lebn(&p, hnbyte, &rsa->iqmp))
+			goto err;
+		if (!read_lebn(&p, nbyte, &rsa->d))
+			goto err;
+	}
+
+	EVP_PKEY_set1_RSA(ret, rsa);
+	RSA_free(rsa);
+	*in = p;
+	return ret;
+
+ err:
+	PEMerror(ERR_R_MALLOC_FAILURE);
+	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);
+}
+LCRYPTO_ALIAS(b2i_PrivateKey);
+
+EVP_PKEY *
+b2i_PublicKey(const unsigned char **in, long length)
+{
+	return do_b2i(in, length, 1);
+}
+LCRYPTO_ALIAS(b2i_PublicKey);
+
+EVP_PKEY *
+b2i_PrivateKey_bio(BIO *in)
+{
+	return do_b2i_bio(in, 0);
+}
+LCRYPTO_ALIAS(b2i_PrivateKey_bio);
+
+EVP_PKEY *
+b2i_PublicKey_bio(BIO *in)
+{
+	return do_b2i_bio(in, 1);
+}
+LCRYPTO_ALIAS(b2i_PublicKey_bio);
+
+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;
+	*p++ = (dw >> 24) & 0xff;
+	*out = p;
+}
+
+static void
+write_lebn(unsigned char **out, const BIGNUM *bn, int len)
+{
+	int nb, i;
+	unsigned char *p = *out, *q, c;
+
+	nb = BN_num_bytes(bn);
+	BN_bn2bin(bn, p);
+	q = p + nb - 1;
+	/* In place byte order reversal */
+	for (i = 0; i < nb / 2; i++) {
+		c = *p;
+		*p++ = *q;
+		*q-- = c;
+	}
+	*out += nb;
+	/* Pad with zeroes if we have to */
+	if (len > 0) {
+		len -= nb;
+		if (len > 0) {
+			memset(*out, 0, 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 void write_rsa(unsigned char **out, RSA *rsa, int ispub);
+static void write_dsa(unsigned char **out, DSA *dsa, int ispub);
+
+static int
+do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
+{
+	unsigned char *p;
+	unsigned int bitlen, magic = 0, keyalg;
+	int outlen, noinc = 0;
+
+	if (pk->type == EVP_PKEY_DSA) {
+		bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic);
+		keyalg = MS_KEYALG_DSS_SIGN;
+	} else if (pk->type == EVP_PKEY_RSA) {
+		bitlen = check_bitlen_rsa(pk->pkey.rsa, 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);
+	if (out == NULL)
+		return outlen;
+	if (*out)
+		p = *out;
+	else {
+		p = malloc(outlen);
+		if (!p)
+			return -1;
+		*out = p;
+		noinc = 1;
+	}
+	if (ispub)
+		*p++ = MS_PUBLICKEYBLOB;
+	else
+		*p++ = MS_PRIVATEKEYBLOB;
+	*p++ = 0x2;
+	*p++ = 0;
+	*p++ = 0;
+	write_ledword(&p, keyalg);
+	write_ledword(&p, magic);
+	write_ledword(&p, bitlen);
+	if (keyalg == MS_KEYALG_DSS_SIGN)
+		write_dsa(&p, pk->pkey.dsa, ispub);
+	else
+		write_rsa(&p, pk->pkey.rsa, ispub);
+	if (!noinc)
+		*out += outlen;
+	return outlen;
+}
+
+static int
+do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
+{
+	unsigned char *tmp = NULL;
+	int outlen, wrlen;
+
+	outlen = do_i2b(&tmp, pk, ispub);
+	if (outlen < 0)
+		return -1;
+	wrlen = BIO_write(out, tmp, outlen);
+	free(tmp);
+	if (wrlen == outlen)
+		return outlen;
+	return -1;
+}
+
+static int
+check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
+{
+	int bitlen;
+
+	bitlen = BN_num_bits(dsa->p);
+	if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160) ||
+	    (BN_num_bits(dsa->g) > bitlen))
+		goto err;
+	if (ispub) {
+		if (BN_num_bits(dsa->pub_key) > bitlen)
+			goto err;
+		*pmagic = MS_DSS1MAGIC;
+	} else {
+		if (BN_num_bits(dsa->priv_key) > 160)
+			goto err;
+		*pmagic = MS_DSS2MAGIC;
+	}
+
+	return bitlen;
+
+ err:
+	PEMerror(PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+	return 0;
+}
+
+static int
+check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
+{
+	int nbyte, hnbyte, bitlen;
+
+	if (BN_num_bits(rsa->e) > 32)
+		goto err;
+	bitlen = BN_num_bits(rsa->n);
+	nbyte = BN_num_bytes(rsa->n);
+	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
+	if (ispub) {
+		*pmagic = MS_RSA1MAGIC;
+		return bitlen;
+	} else {
+		*pmagic = MS_RSA2MAGIC;
+		/* For private key each component must fit within nbyte or
+		 * hnbyte.
+		 */
+		if (BN_num_bytes(rsa->d) > nbyte)
+			goto err;
+		if ((BN_num_bytes(rsa->iqmp) > hnbyte) ||
+		    (BN_num_bytes(rsa->p) > hnbyte) ||
+		    (BN_num_bytes(rsa->q) > hnbyte) ||
+		    (BN_num_bytes(rsa->dmp1) > hnbyte) ||
+		    (BN_num_bytes(rsa->dmq1) > hnbyte))
+			goto err;
+	}
+	return bitlen;
+
+ err:
+	PEMerror(PEM_R_UNSUPPORTED_KEY_COMPONENTS);
+	return 0;
+}
+
+static void
+write_rsa(unsigned char **out, RSA *rsa, int ispub)
+{
+	int nbyte, hnbyte;
+
+	nbyte = BN_num_bytes(rsa->n);
+	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
+	write_lebn(out, rsa->e, 4);
+	write_lebn(out, rsa->n, -1);
+	if (ispub)
+		return;
+	write_lebn(out, rsa->p, hnbyte);
+	write_lebn(out, rsa->q, hnbyte);
+	write_lebn(out, rsa->dmp1, hnbyte);
+	write_lebn(out, rsa->dmq1, hnbyte);
+	write_lebn(out, rsa->iqmp, hnbyte);
+	write_lebn(out, rsa->d, nbyte);
+}
+
+static void
+write_dsa(unsigned char **out, DSA *dsa, int ispub)
+{
+	int nbyte;
+
+	nbyte = BN_num_bytes(dsa->p);
+	write_lebn(out, dsa->p, nbyte);
+	write_lebn(out, dsa->q, 20);
+	write_lebn(out, dsa->g, nbyte);
+	if (ispub)
+		write_lebn(out, dsa->pub_key, nbyte);
+	else
+		write_lebn(out, dsa->priv_key, 20);
+	/* Set "invalid" for seed structure values */
+	memset(*out, 0xff, 24);
+	*out += 24;
+	return;
+}
+
+int
+i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
+{
+	return do_i2b_bio(out, pk, 0);
+}
+LCRYPTO_ALIAS(i2b_PrivateKey_bio);
+
+int
+i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
+{
+	return do_i2b_bio(out, pk, 1);
+}
+LCRYPTO_ALIAS(i2b_PublicKey_bio);
+
+#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)
+{
+	const unsigned char *p = *in;
+	unsigned int pvk_magic, is_encrypted;
+
+	if (skip_magic) {
+		if (length < 20) {
+			PEMerror(PEM_R_PVK_TOO_SHORT);
+			return 0;
+		}
+		length -= 20;
+	} else {
+		if (length < 24) {
+			PEMerror(PEM_R_PVK_TOO_SHORT);
+			return 0;
+		}
+		length -= 24;
+		pvk_magic = read_ledword(&p);
+		if (pvk_magic != MS_PVKMAGIC) {
+			PEMerror(PEM_R_BAD_MAGIC_NUMBER);
+			return 0;
+		}
+	}
+	/* Skip reserved */
+	p += 4;
+	/*keytype = */read_ledword(&p);
+	is_encrypted = read_ledword(&p);
+	*psaltlen = read_ledword(&p);
+	*pkeylen = read_ledword(&p);
+	if (*psaltlen > 65536 || *pkeylen > 65536) {
+		PEMerror(PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+		return 0;
+	}
+
+	if (is_encrypted && !*psaltlen) {
+		PEMerror(PEM_R_INCONSISTENT_HEADER);
+		return 0;
+	}
+
+	*in = p;
+	return 1;
+}
+
+static int
+derive_pvk_key(unsigned char *key, const unsigned char *salt,
+    unsigned int saltlen, const unsigned char *pass, int passlen)
+{
+	EVP_MD_CTX mctx;
+	int rv = 1;
+
+	EVP_MD_CTX_init(&mctx);
+	if (!EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL) ||
+	    !EVP_DigestUpdate(&mctx, salt, saltlen) ||
+	    !EVP_DigestUpdate(&mctx, pass, passlen) ||
+	    !EVP_DigestFinal_ex(&mctx, key, NULL))
+		rv = 0;
+
+	EVP_MD_CTX_cleanup(&mctx);
+	return rv;
+}
+
+static EVP_PKEY *
+do_PVK_body(const unsigned char **in, unsigned int saltlen,
+    unsigned int keylen, pem_password_cb *cb, void *u)
+{
+	EVP_PKEY *ret = NULL;
+	const unsigned char *p = *in;
+	unsigned int magic;
+	unsigned char *enctmp = NULL, *q;
+	EVP_CIPHER_CTX *cctx = NULL;
+
+	if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (saltlen) {
+		char psbuf[PEM_BUFSIZE];
+		unsigned char keybuf[20];
+		int enctmplen, inlen;
+
+		if (cb)
+			inlen = cb(psbuf, PEM_BUFSIZE, 0, u);
+		else
+			inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u);
+		if (inlen <= 0) {
+			PEMerror(PEM_R_BAD_PASSWORD_READ);
+			goto err;
+		}
+		enctmp = malloc(keylen + 8);
+		if (!enctmp) {
+			PEMerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!derive_pvk_key(keybuf, p, saltlen, (unsigned char *)psbuf,
+		    inlen)) {
+			goto err;
+		}
+		p += saltlen;
+		/* Copy BLOBHEADER across, decrypt rest */
+		memcpy(enctmp, p, 8);
+		p += 8;
+		if (keylen < 8) {
+			PEMerror(PEM_R_PVK_TOO_SHORT);
+			goto err;
+		}
+		inlen = keylen - 8;
+		q = enctmp + 8;
+		if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+			goto err;
+		if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
+			goto err;
+		if (!EVP_DecryptFinal_ex(cctx, q + enctmplen, &enctmplen))
+			goto err;
+		magic = read_ledword((const unsigned char **)&q);
+		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))
+				goto err;
+			explicit_bzero(keybuf, 20);
+			if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
+				goto err;
+			if (!EVP_DecryptFinal_ex(cctx, q + enctmplen,
+			    &enctmplen))
+				goto err;
+			magic = read_ledword((const unsigned char **)&q);
+			if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
+				PEMerror(PEM_R_BAD_DECRYPT);
+				goto err;
+			}
+		} else
+			explicit_bzero(keybuf, 20);
+		p = enctmp;
+	}
+
+	ret = b2i_PrivateKey(&p, keylen);
+
+ err:
+	EVP_CIPHER_CTX_free(cctx);
+	if (enctmp && saltlen)
+		free(enctmp);
+	return ret;
+}
+
+
+EVP_PKEY *
+b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+	unsigned char pvk_hdr[24], *buf = NULL;
+	const unsigned char *p;
+	size_t buflen;
+	EVP_PKEY *ret = NULL;
+	unsigned int saltlen, keylen;
+
+	if (BIO_read(in, pvk_hdr, 24) != 24) {
+		PEMerror(PEM_R_PVK_DATA_TOO_SHORT);
+		return NULL;
+	}
+	p = pvk_hdr;
+
+	if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
+		return 0;
+	buflen = keylen + saltlen;
+	buf = malloc(buflen);
+	if (!buf) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	p = buf;
+	if (BIO_read(in, buf, buflen) != buflen) {
+		PEMerror(PEM_R_PVK_DATA_TOO_SHORT);
+		goto err;
+	}
+	ret = do_PVK_body(&p, saltlen, keylen, cb, u);
+
+ err:
+	freezero(buf, buflen);
+	return ret;
+}
+LCRYPTO_ALIAS(b2i_PVK_bio);
+
+static int
+i2b_PVK(unsigned char **out, EVP_PKEY*pk, int enclevel, pem_password_cb *cb,
+    void *u)
+{
+	int outlen = 24, pklen;
+	unsigned char *p = NULL, *start = NULL, *salt = NULL;
+	EVP_CIPHER_CTX *cctx = NULL;
+
+	if ((cctx = EVP_CIPHER_CTX_new()) == NULL) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (enclevel != 0)
+		outlen += PVK_SALTLEN;
+	pklen = do_i2b(NULL, pk, 0);
+	if (pklen < 0)
+		goto err;
+	outlen += pklen;
+	start = p = malloc(outlen);
+	if (!p) {
+		PEMerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	write_ledword(&p, MS_PVKMAGIC);
+	write_ledword(&p, 0);
+	if (pk->type == EVP_PKEY_DSA)
+		write_ledword(&p, MS_KEYTYPE_SIGN);
+	else
+		write_ledword(&p, MS_KEYTYPE_KEYX);
+	write_ledword(&p, enclevel ? 1 : 0);
+	write_ledword(&p, enclevel ? PVK_SALTLEN : 0);
+	write_ledword(&p, pklen);
+	if (enclevel != 0) {
+		arc4random_buf(p, PVK_SALTLEN);
+		salt = p;
+		p += PVK_SALTLEN;
+	}
+	do_i2b(&p, pk, 0);
+	if (enclevel != 0) {
+		char psbuf[PEM_BUFSIZE];
+		unsigned char keybuf[20];
+		int enctmplen, inlen;
+		if (cb)
+			inlen = cb(psbuf, PEM_BUFSIZE, 1, u);
+		else
+			inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 1, u);
+		if (inlen <= 0) {
+			PEMerror(PEM_R_BAD_PASSWORD_READ);
+			goto err;
+		}
+		if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
+		    (unsigned char *)psbuf, inlen))
+			goto err;
+		if (enclevel == 1)
+			memset(keybuf + 5, 0, 11);
+		p = salt + PVK_SALTLEN + 8;
+		if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+			goto err;
+		explicit_bzero(keybuf, 20);
+		if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
+			goto err;
+		if (!EVP_EncryptFinal_ex(cctx, p + enctmplen, &enctmplen))
+			goto err;
+	}
+	EVP_CIPHER_CTX_free(cctx);
+	*out = start;
+	return outlen;
+
+ err:
+	EVP_CIPHER_CTX_free(cctx);
+	free(start);
+	return -1;
+}
+
+int
+i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, pem_password_cb *cb, void *u)
+{
+	unsigned char *tmp = NULL;
+	int outlen, wrlen;
+
+	outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
+	if (outlen < 0)
+		return -1;
+	wrlen = BIO_write(out, tmp, outlen);
+	free(tmp);
+	if (wrlen != outlen) {
+		PEMerror(PEM_R_BIO_WRITE_FAILURE);
+		return -1;
+	}
+	return outlen;
+}
+LCRYPTO_ALIAS(i2b_PVK_bio);
+
+#endif
+
+#endif
diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c
new file mode 100644
index 0000000..93c7c72
--- /dev/null
+++ b/crypto/pkcs12/p12_add.c
@@ -0,0 +1,220 @@
+/* $OpenBSD: p12_add.c,v 1.22 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+
+/* Pack an object into an OCTET STRING and turn into a safebag */
+
+PKCS12_SAFEBAG *
+PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, int nid1, int nid2)
+{
+	PKCS12_BAGS *bag;
+	PKCS12_SAFEBAG *safebag;
+
+	if (!(bag = PKCS12_BAGS_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	bag->type = OBJ_nid2obj(nid1);
+	if (!ASN1_item_pack(obj, it, &bag->value.octet)) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		PKCS12_BAGS_free(bag);
+		return NULL;
+	}
+	if (!(safebag = PKCS12_SAFEBAG_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		PKCS12_BAGS_free(bag);
+		return NULL;
+	}
+	safebag->value.bag = bag;
+	safebag->type = OBJ_nid2obj(nid2);
+	return safebag;
+}
+LCRYPTO_ALIAS(PKCS12_item_pack_safebag);
+
+/* Turn a stack of SAFEBAGS into a PKCS#7 data Contentinfo */
+PKCS7 *
+PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk)
+{
+	PKCS7 *p7;
+
+	if (!(p7 = PKCS7_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	p7->type = OBJ_nid2obj(NID_pkcs7_data);
+	if (!(p7->d.data = ASN1_OCTET_STRING_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!ASN1_item_pack(sk, &PKCS12_SAFEBAGS_it, &p7->d.data)) {
+		PKCS12error(PKCS12_R_CANT_PACK_STRUCTURE);
+		goto err;
+	}
+	return p7;
+
+err:
+	PKCS7_free(p7);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_pack_p7data);
+
+/* Unpack SAFEBAGS from PKCS#7 data ContentInfo */
+STACK_OF(PKCS12_SAFEBAG) *
+PKCS12_unpack_p7data(PKCS7 *p7)
+{
+	if (!PKCS7_type_is_data(p7)) {
+		PKCS12error(PKCS12_R_CONTENT_TYPE_NOT_DATA);
+		return NULL;
+	}
+	return ASN1_item_unpack(p7->d.data, &PKCS12_SAFEBAGS_it);
+}
+LCRYPTO_ALIAS(PKCS12_unpack_p7data);
+
+/* 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 *p7;
+	X509_ALGOR *pbe;
+	const EVP_CIPHER *pbe_ciph;
+
+	if (!(p7 = PKCS7_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	if (!PKCS7_set_type(p7, NID_pkcs7_encrypted)) {
+		PKCS12error(PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE);
+		goto err;
+	}
+
+	pbe_ciph = EVP_get_cipherbynid(pbe_nid);
+
+	if (pbe_ciph)
+		pbe = PKCS5_pbe2_set(pbe_ciph, iter, salt, saltlen);
+	else
+		pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+
+	if (!pbe) {
+		PKCS12error(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, &PKCS12_SAFEBAGS_it, pass, passlen, bags, 1))) {
+		PKCS12error(PKCS12_R_ENCRYPT_ERROR);
+		goto err;
+	}
+
+	return p7;
+
+err:
+	PKCS7_free(p7);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_pack_p7encdata);
+
+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,
+	    &PKCS12_SAFEBAGS_it, pass, passlen,
+	    p7->d.encrypted->enc_data->enc_data, 1);
+}
+LCRYPTO_ALIAS(PKCS12_unpack_p7encdata);
+
+PKCS8_PRIV_KEY_INFO *
+PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag, const char *pass, int passlen)
+{
+	return PKCS8_decrypt(bag->value.shkeybag, pass, passlen);
+}
+LCRYPTO_ALIAS(PKCS12_decrypt_skey);
+
+int
+PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes)
+{
+	if (ASN1_item_pack(safes, &PKCS12_AUTHSAFES_it,
+	    &p12->authsafes->d.data))
+		return 1;
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS12_pack_authsafes);
+
+STACK_OF(PKCS7) *
+PKCS12_unpack_authsafes(const PKCS12 *p12)
+{
+	if (!PKCS7_type_is_data(p12->authsafes)) {
+		PKCS12error(PKCS12_R_CONTENT_TYPE_NOT_DATA);
+		return NULL;
+	}
+	return ASN1_item_unpack(p12->authsafes->d.data,
+	    &PKCS12_AUTHSAFES_it);
+}
+LCRYPTO_ALIAS(PKCS12_unpack_authsafes);
diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c
new file mode 100644
index 0000000..a9deccc
--- /dev/null
+++ b/crypto/pkcs12/p12_asn.c
@@ -0,0 +1,491 @@
+/* $OpenBSD: p12_asn.c,v 1.14 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+
+/* PKCS#12 ASN1 module */
+
+static const ASN1_TEMPLATE PKCS12_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12, authsafes),
+		.field_name = "authsafes",
+		.item = &PKCS7_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS12, mac),
+		.field_name = "mac",
+		.item = &PKCS12_MAC_DATA_it,
+	},
+};
+
+const ASN1_ITEM PKCS12_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS12_seq_tt,
+	.tcount = sizeof(PKCS12_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS12),
+	.sname = "PKCS12",
+};
+
+
+PKCS12 *
+d2i_PKCS12(PKCS12 **a, const unsigned char **in, long len)
+{
+	return (PKCS12 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS12_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS12);
+
+int
+i2d_PKCS12(PKCS12 *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS12_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS12);
+
+PKCS12 *
+PKCS12_new(void)
+{
+	return (PKCS12 *)ASN1_item_new(&PKCS12_it);
+}
+LCRYPTO_ALIAS(PKCS12_new);
+
+void
+PKCS12_free(PKCS12 *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS12_it);
+}
+LCRYPTO_ALIAS(PKCS12_free);
+
+static const ASN1_TEMPLATE PKCS12_MAC_DATA_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12_MAC_DATA, dinfo),
+		.field_name = "dinfo",
+		.item = &X509_SIG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12_MAC_DATA, salt),
+		.field_name = "salt",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS12_MAC_DATA, iter),
+		.field_name = "iter",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM PKCS12_MAC_DATA_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS12_MAC_DATA_seq_tt,
+	.tcount = sizeof(PKCS12_MAC_DATA_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS12_MAC_DATA),
+	.sname = "PKCS12_MAC_DATA",
+};
+
+
+PKCS12_MAC_DATA *
+d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, const unsigned char **in, long len)
+{
+	return (PKCS12_MAC_DATA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS12_MAC_DATA_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS12_MAC_DATA);
+
+int
+i2d_PKCS12_MAC_DATA(PKCS12_MAC_DATA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS12_MAC_DATA_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS12_MAC_DATA);
+
+PKCS12_MAC_DATA *
+PKCS12_MAC_DATA_new(void)
+{
+	return (PKCS12_MAC_DATA *)ASN1_item_new(&PKCS12_MAC_DATA_it);
+}
+LCRYPTO_ALIAS(PKCS12_MAC_DATA_new);
+
+void
+PKCS12_MAC_DATA_free(PKCS12_MAC_DATA *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS12_MAC_DATA_it);
+}
+LCRYPTO_ALIAS(PKCS12_MAC_DATA_free);
+
+static const ASN1_TEMPLATE bag_default_tt = {
+	.flags = ASN1_TFLG_EXPLICIT,
+	.tag = 0,
+	.offset = offsetof(PKCS12_BAGS, value.other),
+	.field_name = "value.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE PKCS12_BAGS_adbtbl[] = {
+	{
+		.value = NID_x509Certificate,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_BAGS, value.x509cert),
+			.field_name = "value.x509cert",
+			.item = &ASN1_OCTET_STRING_it,
+		},
+	
+	},
+	{
+		.value = NID_x509Crl,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_BAGS, value.x509crl),
+			.field_name = "value.x509crl",
+			.item = &ASN1_OCTET_STRING_it,
+		},
+	
+	},
+	{
+		.value = NID_sdsiCertificate,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_BAGS, value.sdsicert),
+			.field_name = "value.sdsicert",
+			.item = &ASN1_IA5STRING_it,
+		},
+	
+	},
+};
+
+static const ASN1_ADB PKCS12_BAGS_adb = {
+	.flags = 0,
+	.offset = offsetof(PKCS12_BAGS, type),
+	.tbl = PKCS12_BAGS_adbtbl,
+	.tblcount = sizeof(PKCS12_BAGS_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &bag_default_tt,
+	.null_tt = NULL,
+};
+
+static const ASN1_TEMPLATE PKCS12_BAGS_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12_BAGS, type),
+		.field_name = "type",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "PKCS12_BAGS",
+		.item = (const ASN1_ITEM *)&PKCS12_BAGS_adb,
+	},
+};
+
+const ASN1_ITEM PKCS12_BAGS_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS12_BAGS_seq_tt,
+	.tcount = sizeof(PKCS12_BAGS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS12_BAGS),
+	.sname = "PKCS12_BAGS",
+};
+
+
+PKCS12_BAGS *
+d2i_PKCS12_BAGS(PKCS12_BAGS **a, const unsigned char **in, long len)
+{
+	return (PKCS12_BAGS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS12_BAGS_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS12_BAGS);
+
+int
+i2d_PKCS12_BAGS(PKCS12_BAGS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS12_BAGS_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS12_BAGS);
+
+PKCS12_BAGS *
+PKCS12_BAGS_new(void)
+{
+	return (PKCS12_BAGS *)ASN1_item_new(&PKCS12_BAGS_it);
+}
+LCRYPTO_ALIAS(PKCS12_BAGS_new);
+
+void
+PKCS12_BAGS_free(PKCS12_BAGS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS12_BAGS_it);
+}
+LCRYPTO_ALIAS(PKCS12_BAGS_free);
+
+static const ASN1_TEMPLATE safebag_default_tt = {
+	.flags = ASN1_TFLG_EXPLICIT,
+	.tag = 0,
+	.offset = offsetof(PKCS12_SAFEBAG, value.other),
+	.field_name = "value.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE PKCS12_SAFEBAG_adbtbl[] = {
+	{
+		.value = NID_keyBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.keybag),
+			.field_name = "value.keybag",
+			.item = &PKCS8_PRIV_KEY_INFO_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs8ShroudedKeyBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.shkeybag),
+			.field_name = "value.shkeybag",
+			.item = &X509_SIG_it,
+		},
+	
+	},
+	{
+		.value = NID_safeContentsBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.safes),
+			.field_name = "value.safes",
+			.item = &PKCS12_SAFEBAG_it,
+		},
+	},
+	{
+		.value = NID_certBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.bag),
+			.field_name = "value.bag",
+			.item = &PKCS12_BAGS_it,
+		},
+	
+	},
+	{
+		.value = NID_crlBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.bag),
+			.field_name = "value.bag",
+			.item = &PKCS12_BAGS_it,
+		},
+	
+	},
+	{
+		.value = NID_secretBag,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT,
+			.tag = 0,
+			.offset = offsetof(PKCS12_SAFEBAG, value.bag),
+			.field_name = "value.bag",
+			.item = &PKCS12_BAGS_it,
+		},
+	
+	},
+};
+
+static const ASN1_ADB PKCS12_SAFEBAG_adb = {
+	.flags = 0,
+	.offset = offsetof(PKCS12_SAFEBAG, type),
+	.tbl = PKCS12_SAFEBAG_adbtbl,
+	.tblcount = sizeof(PKCS12_SAFEBAG_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &safebag_default_tt,
+	.null_tt = NULL,
+};
+
+static const ASN1_TEMPLATE PKCS12_SAFEBAG_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS12_SAFEBAG, type),
+		.field_name = "type",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "PKCS12_SAFEBAG",
+		.item = (const ASN1_ITEM *)&PKCS12_SAFEBAG_adb,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS12_SAFEBAG, attrib),
+		.field_name = "attrib",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM PKCS12_SAFEBAG_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS12_SAFEBAG_seq_tt,
+	.tcount = sizeof(PKCS12_SAFEBAG_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS12_SAFEBAG),
+	.sname = "PKCS12_SAFEBAG",
+};
+
+
+PKCS12_SAFEBAG *
+d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, const unsigned char **in, long len)
+{
+	return (PKCS12_SAFEBAG *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS12_SAFEBAG_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS12_SAFEBAG);
+
+int
+i2d_PKCS12_SAFEBAG(PKCS12_SAFEBAG *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS12_SAFEBAG_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS12_SAFEBAG);
+
+PKCS12_SAFEBAG *
+PKCS12_SAFEBAG_new(void)
+{
+	return (PKCS12_SAFEBAG *)ASN1_item_new(&PKCS12_SAFEBAG_it);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_new);
+
+void
+PKCS12_SAFEBAG_free(PKCS12_SAFEBAG *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS12_SAFEBAG_it);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_free);
+
+/* SEQUENCE OF SafeBag */
+static const ASN1_TEMPLATE PKCS12_SAFEBAGS_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "PKCS12_SAFEBAGS",
+	.item = &PKCS12_SAFEBAG_it,
+};
+
+const ASN1_ITEM PKCS12_SAFEBAGS_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &PKCS12_SAFEBAGS_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "PKCS12_SAFEBAGS",
+};
+
+/* Authsafes: SEQUENCE OF PKCS7 */
+static const ASN1_TEMPLATE PKCS12_AUTHSAFES_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "PKCS12_AUTHSAFES",
+	.item = &PKCS7_it,
+};
+
+const ASN1_ITEM PKCS12_AUTHSAFES_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &PKCS12_AUTHSAFES_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "PKCS12_AUTHSAFES",
+};
diff --git a/crypto/pkcs12/p12_attr.c b/crypto/pkcs12/p12_attr.c
new file mode 100644
index 0000000..d43b205
--- /dev/null
+++ b/crypto/pkcs12/p12_attr.c
@@ -0,0 +1,164 @@
+/* $OpenBSD: p12_attr.c,v 1.20 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include "pkcs12_local.h"
+#include "x509_local.h"
+
+/* Add a local keyid to a safebag */
+
+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))
+		return 1;
+	else
+		return 0;
+}
+LCRYPTO_ALIAS(PKCS12_add_localkeyid);
+
+/* Add key usage to PKCS#8 structure */
+
+int
+PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage)
+{
+	unsigned char us_val = (unsigned char)usage;
+
+	return PKCS8_pkey_add1_attr_by_NID(p8, NID_key_usage, V_ASN1_BIT_STRING,
+	    &us_val, 1);
+}
+LCRYPTO_ALIAS(PKCS8_add_keyusage);
+
+/* Add a friendlyname to a safebag */
+
+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))
+		return 1;
+	else
+		return 0;
+}
+LCRYPTO_ALIAS(PKCS12_add_friendlyname_asc);
+
+
+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))
+		return 1;
+	else
+		return 0;
+}
+LCRYPTO_ALIAS(PKCS12_add_friendlyname_uni);
+
+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))
+		return 1;
+	else
+		return 0;
+}
+LCRYPTO_ALIAS(PKCS12_add_CSPName_asc);
+
+ASN1_TYPE *
+PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, int attr_nid)
+{
+	X509_ATTRIBUTE *attrib;
+	int i;
+
+	if (!attrs)
+		return NULL;
+	for (i = 0; i < sk_X509_ATTRIBUTE_num(attrs); i++) {
+		attrib = sk_X509_ATTRIBUTE_value(attrs, i);
+		if (OBJ_obj2nid(attrib->object) == attr_nid)
+			return sk_ASN1_TYPE_value(attrib->set, 0);
+	}
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_get_attr_gen);
+
+char *
+PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag)
+{
+	const ASN1_TYPE *atype;
+
+	if (!(atype = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)))
+		return NULL;
+	if (atype->type != V_ASN1_BMPSTRING)
+		return NULL;
+	return OPENSSL_uni2asc(atype->value.bmpstring->data,
+	    atype->value.bmpstring->length);
+}
+LCRYPTO_ALIAS(PKCS12_get_friendlyname);
+
+const STACK_OF(X509_ATTRIBUTE) *
+PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag)
+{
+	return bag->attrib;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_attrs);
diff --git a/crypto/pkcs12/p12_crpt.c b/crypto/pkcs12/p12_crpt.c
new file mode 100644
index 0000000..e7d3010
--- /dev/null
+++ b/crypto/pkcs12/p12_crpt.c
@@ -0,0 +1,123 @@
+/* $OpenBSD: p12_crpt.c,v 1.17 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+/* PKCS#12 PBE algorithms now in static table */
+
+void
+PKCS12_PBE_add(void)
+{
+}
+LCRYPTO_ALIAS(PKCS12_PBE_add);
+
+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)
+{
+	PBEPARAM *pbe;
+	int saltlen, iter, ret;
+	unsigned char *salt;
+	const unsigned char *pbuf;
+	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+
+	/* Extract useful info from parameter */
+	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
+	    param->value.sequence == NULL) {
+		PKCS12error(PKCS12_R_DECODE_ERROR);
+		return 0;
+	}
+
+	pbuf = param->value.sequence->data;
+	if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) {
+		PKCS12error(PKCS12_R_DECODE_ERROR);
+		return 0;
+	}
+
+	if (!pbe->iter)
+		iter = 1;
+	else if ((iter = ASN1_INTEGER_get(pbe->iter)) <= 0) {
+		PKCS12error(PKCS12_R_DECODE_ERROR);
+		PBEPARAM_free(pbe);
+		return 0;
+	}
+	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)) {
+		PKCS12error(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)) {
+		PKCS12error(PKCS12_R_IV_GEN_ERROR);
+		PBEPARAM_free(pbe);
+		return 0;
+	}
+	PBEPARAM_free(pbe);
+	ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, en_de);
+	explicit_bzero(key, EVP_MAX_KEY_LENGTH);
+	explicit_bzero(iv, EVP_MAX_IV_LENGTH);
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS12_PBE_keyivgen);
diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c
new file mode 100644
index 0000000..90a0cbe
--- /dev/null
+++ b/crypto/pkcs12/p12_crt.c
@@ -0,0 +1,357 @@
+/* $OpenBSD: p12_crt.c,v 1.23 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+
+static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags,
+    PKCS12_SAFEBAG *bag);
+
+static int
+copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid)
+{
+	int idx;
+	X509_ATTRIBUTE *attr;
+
+	idx = EVP_PKEY_get_attr_by_NID(pkey, nid, -1);
+	if (idx < 0)
+		return 1;
+	attr = EVP_PKEY_get_attr(pkey, idx);
+	if (!X509at_add1_attr(&bag->attrib, attr))
+		return 0;
+	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 *p12 = NULL;
+	STACK_OF(PKCS7) *safes = NULL;
+	STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
+	PKCS12_SAFEBAG *bag = NULL;
+	int i;
+	unsigned char keyid[EVP_MAX_MD_SIZE];
+	unsigned int keyidlen = 0;
+
+	/* Set defaults */
+	if (!nid_cert) {
+		nid_cert = NID_pbe_WithSHA1And40BitRC2_CBC;
+	}
+	if (!nid_key)
+		nid_key = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
+	if (!iter)
+		iter = PKCS12_DEFAULT_ITER;
+	if (!mac_iter)
+		mac_iter = 1;
+
+	if (!pkey && !cert && !ca) {
+		PKCS12error(PKCS12_R_INVALID_NULL_ARGUMENT);
+		return NULL;
+	}
+
+	if (pkey && cert) {
+		if (!X509_check_private_key(cert, pkey))
+			return NULL;
+		if (!X509_digest(cert, EVP_sha1(), keyid, &keyidlen))
+			return NULL;
+	}
+
+	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;
+	}
+
+	/* Add all other certificates */
+	for (i = 0; i < sk_X509_num(ca); i++) {
+		if (!PKCS12_add_cert(&bags, sk_X509_value(ca, i)))
+			goto err;
+	}
+
+	if (bags && !PKCS12_add_safe(&safes, bags, nid_cert, iter, pass))
+		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);
+
+		if (!bag)
+			goto err;
+
+		if (!copy_bag_attr(bag, pkey, NID_ms_csp_name))
+			goto err;
+		if (!copy_bag_attr(bag, pkey, NID_LocalKeySet))
+			goto err;
+
+		if (name && !PKCS12_add_friendlyname(bag, name, -1))
+			goto err;
+		if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+			goto err;
+	}
+
+	if (bags && !PKCS12_add_safe(&safes, bags, -1, 0, NULL))
+		goto err;
+
+	sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+	bags = NULL;
+
+	p12 = PKCS12_add_safes(safes, 0);
+
+	if (!p12)
+		goto err;
+
+	sk_PKCS7_pop_free(safes, PKCS7_free);
+
+	safes = NULL;
+
+	if ((mac_iter != -1) &&
+	    !PKCS12_set_mac(p12, pass, -1, NULL, 0, mac_iter, NULL))
+		goto err;
+
+	return p12;
+
+err:
+	if (p12)
+		PKCS12_free(p12);
+	if (safes)
+		sk_PKCS7_pop_free(safes, PKCS7_free);
+	if (bags)
+		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_create);
+
+PKCS12_SAFEBAG *
+PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert)
+{
+	PKCS12_SAFEBAG *bag = NULL;
+	char *name;
+	int namelen = -1;
+	unsigned char *keyid;
+	int keyidlen = -1;
+
+	/* Add user certificate */
+	if (!(bag = PKCS12_x5092certbag(cert)))
+		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))
+		goto err;
+
+	keyid = X509_keyid_get0(cert, &keyidlen);
+
+	if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen))
+		goto err;
+
+	if (!pkcs12_add_bag(pbags, bag))
+		goto err;
+
+	return bag;
+
+err:
+	if (bag)
+		PKCS12_SAFEBAG_free(bag);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_add_cert);
+
+PKCS12_SAFEBAG *
+PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key, int key_usage,
+    int iter, int nid_key, const char *pass)
+{
+	PKCS12_SAFEBAG *bag = NULL;
+	PKCS8_PRIV_KEY_INFO *p8 = NULL;
+
+	/* Make a PKCS#8 structure */
+	if (!(p8 = EVP_PKEY2PKCS8(key)))
+		goto err;
+	if (key_usage && !PKCS8_add_keyusage(p8, key_usage))
+		goto err;
+	if (nid_key != -1) {
+		bag = PKCS12_SAFEBAG_create_pkcs8_encrypt(nid_key, pass, -1,
+		    NULL, 0, iter, p8);
+		PKCS8_PRIV_KEY_INFO_free(p8);
+		p8 = NULL;
+	} else {
+		bag = PKCS12_SAFEBAG_create0_p8inf(p8);
+		if (bag != NULL)
+			p8 = NULL;
+	}
+
+	if (!bag)
+		goto err;
+
+	if (!pkcs12_add_bag(pbags, bag))
+		goto err;
+
+	return bag;
+
+err:
+	if (bag)
+		PKCS12_SAFEBAG_free(bag);
+	if (p8)
+		PKCS8_PRIV_KEY_INFO_free(p8);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_add_key);
+
+int
+PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags,
+    int nid_safe, int iter, const char *pass)
+{
+	PKCS7 *p7 = NULL;
+	int free_safes = 0;
+
+	if (!*psafes) {
+		*psafes = sk_PKCS7_new_null();
+		if (!*psafes)
+			return 0;
+		free_safes = 1;
+	} else
+		free_safes = 0;
+
+	if (nid_safe == 0)
+		nid_safe = NID_pbe_WithSHA1And40BitRC2_CBC;
+
+	if (nid_safe == -1)
+		p7 = PKCS12_pack_p7data(bags);
+	else
+		p7 = PKCS12_pack_p7encdata(nid_safe, pass, -1, NULL, 0,
+		    iter, bags);
+	if (!p7)
+		goto err;
+
+	if (!sk_PKCS7_push(*psafes, p7))
+		goto err;
+
+	return 1;
+
+err:
+	if (free_safes) {
+		sk_PKCS7_free(*psafes);
+		*psafes = NULL;
+	}
+
+	if (p7)
+		PKCS7_free(p7);
+
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS12_add_safe);
+
+static int
+pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag)
+{
+	int free_bags;
+
+	if (!pbags)
+		return 1;
+	if (!*pbags) {
+		*pbags = sk_PKCS12_SAFEBAG_new_null();
+		if (!*pbags)
+			return 0;
+		free_bags = 1;
+	} else
+		free_bags = 0;
+
+	if (!sk_PKCS12_SAFEBAG_push(*pbags, bag)) {
+		if (free_bags) {
+			sk_PKCS12_SAFEBAG_free(*pbags);
+			*pbags = NULL;
+		}
+		return 0;
+	}
+
+	return 1;
+}
+
+PKCS12 *
+PKCS12_add_safes(STACK_OF(PKCS7) *safes, int nid_p7)
+{
+	PKCS12 *p12;
+
+	if (nid_p7 <= 0)
+		nid_p7 = NID_pkcs7_data;
+	p12 = PKCS12_init(nid_p7);
+
+	if (!p12)
+		return NULL;
+
+	if (!PKCS12_pack_authsafes(p12, safes)) {
+		PKCS12_free(p12);
+		return NULL;
+	}
+
+	return p12;
+}
+LCRYPTO_ALIAS(PKCS12_add_safes);
diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c
new file mode 100644
index 0000000..ea7f6a5
--- /dev/null
+++ b/crypto/pkcs12/p12_decr.c
@@ -0,0 +1,189 @@
+/* $OpenBSD: p12_decr.c,v 1.24 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* Encrypt/Decrypt a buffer based on password and algor, result in a
+ * 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 *out;
+	int outlen, i;
+	EVP_CIPHER_CTX ctx;
+
+	EVP_CIPHER_CTX_init(&ctx);
+	/* Decrypt data */
+	if (!EVP_PBE_CipherInit(algor->algorithm, pass, passlen,
+	    algor->parameter, &ctx, en_de)) {
+		out = NULL;
+		PKCS12error(PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR);
+		goto err;
+	}
+
+	if (!(out = malloc(inlen + EVP_CIPHER_CTX_block_size(&ctx)))) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!EVP_CipherUpdate(&ctx, out, &i, in, inlen)) {
+		free(out);
+		out = NULL;
+		PKCS12error(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	outlen = i;
+	if (!EVP_CipherFinal_ex(&ctx, out + i, &i)) {
+		free(out);
+		out = NULL;
+		PKCS12error(PKCS12_R_PKCS12_CIPHERFINAL_ERROR);
+		goto err;
+	}
+	outlen += i;
+	if (datalen)
+		*datalen = outlen;
+	if (data)
+		*data = out;
+
+err:
+	EVP_CIPHER_CTX_cleanup(&ctx);
+	return out;
+
+}
+LCRYPTO_ALIAS(PKCS12_pbe_crypt);
+
+/* 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)
+{
+	unsigned char *out;
+	const unsigned char *p;
+	void *ret;
+	int outlen;
+
+	if (!PKCS12_pbe_crypt(algor, pass, passlen, oct->data, oct->length,
+	    &out, &outlen, 0)) {
+		PKCS12error(PKCS12_R_PKCS12_PBE_CRYPT_ERROR);
+		return NULL;
+	}
+	p = out;
+	ret = ASN1_item_d2i(NULL, &p, outlen, it);
+	if (zbuf)
+		explicit_bzero(out, outlen);
+	if (!ret)
+		PKCS12error(PKCS12_R_DECODE_ERROR);
+	free(out);
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS12_item_decrypt_d2i);
+
+/* 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 *oct;
+	unsigned char *in = NULL;
+	int inlen;
+
+	if (!(oct = ASN1_OCTET_STRING_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	inlen = ASN1_item_i2d(obj, &in, it);
+	if (!in) {
+		PKCS12error(PKCS12_R_ENCODE_ERROR);
+		goto err;
+	}
+	if (!PKCS12_pbe_crypt(algor, pass, passlen, in, inlen, &oct->data,
+	    &oct->length, 1)) {
+		PKCS12error(PKCS12_R_ENCRYPT_ERROR);
+		goto err;
+	}
+	if (zbuf)
+		explicit_bzero(in, inlen);
+	free(in);
+	return oct;
+
+err:
+	free(in);
+	ASN1_OCTET_STRING_free(oct);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_item_i2d_encrypt);
+
+IMPLEMENT_PKCS12_STACK_OF(PKCS7)
diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c
new file mode 100644
index 0000000..09ff0d5
--- /dev/null
+++ b/crypto/pkcs12/p12_init.c
@@ -0,0 +1,101 @@
+/* $OpenBSD: p12_init.c,v 1.16 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+
+/* Initialise a PKCS12 structure to take data */
+
+PKCS12 *
+PKCS12_init(int mode)
+{
+	PKCS12 *pkcs12;
+
+	if (!(pkcs12 = PKCS12_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	if (!ASN1_INTEGER_set(pkcs12->version, 3))
+		goto err;
+	if ((pkcs12->authsafes->type = OBJ_nid2obj(mode)) == NULL)
+		goto err;
+	switch (mode) {
+	case NID_pkcs7_data:
+		if (!(pkcs12->authsafes->d.data =
+		    ASN1_OCTET_STRING_new())) {
+			PKCS12error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		break;
+	default:
+		PKCS12error(PKCS12_R_UNSUPPORTED_PKCS12_MODE);
+		goto err;
+	}
+
+	return pkcs12;
+
+err:
+	if (pkcs12 != NULL)
+		PKCS12_free(pkcs12);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS12_init);
diff --git a/crypto/pkcs12/p12_key.c b/crypto/pkcs12/p12_key.c
new file mode 100644
index 0000000..8812f1c
--- /dev/null
+++ b/crypto/pkcs12/p12_key.c
@@ -0,0 +1,197 @@
+/* $OpenBSD: p12_key.c,v 1.34 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+
+/* 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 ret;
+	unsigned char *unipass;
+	int uniplen;
+
+	if (!pass) {
+		unipass = NULL;
+		uniplen = 0;
+	} else if (!OPENSSL_asc2uni(pass, passlen, &unipass, &uniplen)) {
+		PKCS12error(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;
+	freezero(unipass, uniplen);
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS12_key_gen_asc);
+
+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)
+{
+	EVP_MD_CTX *ctx = NULL;
+	unsigned char *B = NULL, *D = NULL, *I = NULL, *Ai = NULL;
+	unsigned char *p;
+	int Slen, Plen, Ilen;
+	int i, j, u, v;
+	int ret = 0;
+
+	if ((ctx = EVP_MD_CTX_new()) == NULL)
+		goto err;
+
+	if ((v = EVP_MD_block_size(md_type)) <= 0)
+		goto err;
+	if ((u = EVP_MD_size(md_type)) <= 0)
+		goto err;
+
+	if ((D = malloc(v)) == NULL)
+		goto err;
+	if ((Ai = malloc(u)) == NULL)
+		goto err;
+	if ((B = malloc(v + 1)) == NULL)
+		goto err;
+
+	Slen = v * ((saltlen + v - 1) / v);
+
+	Plen = 0;
+	if (passlen)
+		Plen = v * ((passlen + v - 1) / v);
+
+	Ilen = Slen + Plen;
+
+	if ((I = malloc(Ilen)) == 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))
+			goto err;
+		if (!EVP_DigestUpdate(ctx, D, v))
+			goto err;
+		if (!EVP_DigestUpdate(ctx, I, Ilen))
+			goto err;
+		if (!EVP_DigestFinal_ex(ctx, Ai, NULL))
+			goto err;
+		for (j = 1; j < iter; j++) {
+			if (!EVP_DigestInit_ex(ctx, md_type, NULL))
+				goto err;
+			if (!EVP_DigestUpdate(ctx, Ai, u))
+				goto err;
+			if (!EVP_DigestFinal_ex(ctx, Ai, NULL))
+				goto err;
+		}
+		memcpy(out, Ai, min(n, u));
+		if (u >= n) {
+			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) {
+			uint16_t c = 1;
+			int k;
+
+			/* Work out I[j] = I[j] + B + 1. */
+			for (k = v - 1; k >= 0; k--) {
+				c += I[j + k] + B[k];
+				I[j + k] = (unsigned char)c;
+				c >>= 8;
+			}
+		}
+	}
+
+ err:
+	PKCS12error(ERR_R_MALLOC_FAILURE);
+
+ end:
+	free(Ai);
+	free(B);
+	free(D);
+	free(I);
+	EVP_MD_CTX_free(ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS12_key_gen_uni);
diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c
new file mode 100644
index 0000000..48bbd13
--- /dev/null
+++ b/crypto/pkcs12/p12_kiss.c
@@ -0,0 +1,299 @@
+/* $OpenBSD: p12_kiss.c,v 1.27 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+
+/* Simplified PKCS#12 routines */
+
+static int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
+    EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
+
+static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
+    int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
+
+static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
+    EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
+
+/* 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 unitialised.
+ */
+
+int
+PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+    STACK_OF(X509) **ca)
+{
+	STACK_OF(X509) *ocerts = NULL;
+	X509 *x = NULL;
+
+	if (pkey != NULL)
+		*pkey = NULL;
+	if (cert != NULL)
+		*cert = NULL;
+
+	if (p12 == NULL) {
+		PKCS12error(PKCS12_R_INVALID_NULL_PKCS12_POINTER);
+		goto err;
+	}
+
+	/* Check the mac */
+
+	/* If password is zero length or NULL then try verifying both cases
+	 * to determine which password is correct. The reason for this is that
+	 * under PKCS#12 password based encryption no password and a zero length
+	 * password are two different things...
+	 */
+
+	if (pass == NULL || *pass == '\0') {
+		if (PKCS12_verify_mac(p12, NULL, 0))
+			pass = NULL;
+		else if (PKCS12_verify_mac(p12, "", 0))
+			pass = "";
+		else {
+			PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE);
+			goto err;
+		}
+	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
+		PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE);
+		goto err;
+	}
+
+	/* Allocate stack for other certificates */
+	if ((ocerts = sk_X509_new_null()) == NULL) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!parse_pk12(p12, pass, -1, pkey, ocerts)) {
+		PKCS12error(PKCS12_R_PARSE_ERROR);
+		goto err;
+	}
+
+	while ((x = sk_X509_pop(ocerts)) != NULL) {
+		if (pkey != NULL && *pkey != NULL &&
+		    cert != NULL && *cert == NULL) {
+			ERR_set_mark();
+			if (X509_check_private_key(x, *pkey)) {
+				*cert = x;
+				x = NULL;
+			}
+			ERR_pop_to_mark();
+		}
+
+		if (ca != NULL && x != NULL) {
+			if (*ca == NULL)
+				*ca = sk_X509_new_null();
+			if (*ca == NULL)
+				goto err;
+			if (!sk_X509_push(*ca, x))
+				goto err;
+			x = NULL;
+		}
+		X509_free(x);
+		x = NULL;
+	}
+
+	sk_X509_pop_free(ocerts, X509_free);
+
+	return 1;
+
+err:
+	if (pkey != NULL)
+		EVP_PKEY_free(*pkey);
+	if (cert != NULL)
+		X509_free(*cert);
+	X509_free(x);
+	sk_X509_pop_free(ocerts, X509_free);
+
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS12_parse);
+
+/* Parse the outer PKCS#12 structure */
+
+static int
+parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey,
+    STACK_OF(X509) *ocerts)
+{
+	STACK_OF(PKCS7) *asafes;
+	STACK_OF(PKCS12_SAFEBAG) *bags;
+	int i, bagnid;
+	PKCS7 *p7;
+
+	if (!(asafes = PKCS12_unpack_authsafes(p12)))
+		return 0;
+	for (i = 0; i < sk_PKCS7_num(asafes); i++) {
+		p7 = sk_PKCS7_value(asafes, i);
+		bagnid = OBJ_obj2nid(p7->type);
+		if (bagnid == NID_pkcs7_data) {
+			bags = PKCS12_unpack_p7data(p7);
+		} else if (bagnid == NID_pkcs7_encrypted) {
+			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
+		} else
+			continue;
+		if (!bags) {
+			sk_PKCS7_pop_free(asafes, PKCS7_free);
+			return 0;
+		}
+		if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
+			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+			sk_PKCS7_pop_free(asafes, PKCS7_free);
+			return 0;
+		}
+		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+	}
+	sk_PKCS7_pop_free(asafes, PKCS7_free);
+	return 1;
+}
+
+static int
+parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen,
+    EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
+{
+	int i;
+
+	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
+		if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), pass, passlen,
+		    pkey, ocerts))
+			return 0;
+	}
+	return 1;
+}
+
+static int
+parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey,
+    STACK_OF(X509) *ocerts)
+{
+	PKCS8_PRIV_KEY_INFO *p8;
+	X509 *x509;
+	const ASN1_TYPE *attrib;
+	ASN1_BMPSTRING *fname = NULL;
+	ASN1_OCTET_STRING *lkid = NULL;
+
+	if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)))
+		fname = attrib->value.bmpstring;
+
+	if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)))
+		lkid = attrib->value.octet_string;
+
+	switch (OBJ_obj2nid(bag->type)) {
+	case NID_keyBag:
+		if (!pkey || *pkey)
+			return 1;
+		if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag)))
+			return 0;
+		break;
+
+	case NID_pkcs8ShroudedKeyBag:
+		if (!pkey || *pkey)
+			return 1;
+		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
+			return 0;
+		*pkey = EVP_PKCS82PKEY(p8);
+		PKCS8_PRIV_KEY_INFO_free(p8);
+		if (!(*pkey))
+			return 0;
+		break;
+
+	case NID_certBag:
+		if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate )
+			return 1;
+		if (!(x509 = PKCS12_certbag2x509(bag)))
+			return 0;
+		if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) {
+			X509_free(x509);
+			return 0;
+		}
+		if (fname) {
+			int len, r;
+			unsigned char *data = NULL;
+			len = ASN1_STRING_to_UTF8(&data, fname);
+			if (len >= 0) {
+				r = X509_alias_set1(x509, data, len);
+				free(data);
+				if (!r) {
+					X509_free(x509);
+					return 0;
+				}
+			}
+		}
+
+		if (!sk_X509_push(ocerts, x509)) {
+			X509_free(x509);
+			return 0;
+		}
+
+		break;
+
+	case NID_safeContentsBag:
+		return parse_bags(bag->value.safes, pass, passlen,
+		    pkey, ocerts);
+		break;
+
+	default:
+		return 1;
+		break;
+	}
+	return 1;
+}
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
new file mode 100644
index 0000000..f0e6df9
--- /dev/null
+++ b/crypto/pkcs12/p12_mutl.c
@@ -0,0 +1,263 @@
+/* $OpenBSD: p12_mutl.c,v 1.35 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#ifndef OPENSSL_NO_HMAC
+
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "hmac_local.h"
+#include "pkcs12_local.h"
+#include "x509_local.h"
+
+int
+PKCS12_mac_present(const PKCS12 *p12)
+{
+	return p12->mac != NULL;
+}
+LCRYPTO_ALIAS(PKCS12_mac_present);
+
+void
+PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, const X509_ALGOR **pmacalg,
+    const ASN1_OCTET_STRING **psalt, const ASN1_INTEGER **piter,
+    const PKCS12 *p12)
+{
+	if (p12->mac == NULL) {
+		if (pmac != NULL)
+			*pmac = NULL;
+		if (pmacalg != NULL)
+			*pmacalg = NULL;
+		if (psalt != NULL)
+			*psalt = NULL;
+		if (piter != NULL)
+			*piter = NULL;
+		return;
+	}
+
+	if (pmac != NULL)
+		*pmac = p12->mac->dinfo->digest;
+	if (pmacalg != NULL)
+		*pmacalg = p12->mac->dinfo->algor;
+	if (psalt != NULL)
+		*psalt = p12->mac->salt;
+	if (piter != NULL)
+		*piter = p12->mac->iter;
+}
+LCRYPTO_ALIAS(PKCS12_get0_mac);
+
+/* Generate a MAC */
+int
+PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
+    unsigned char *mac, unsigned int *maclen)
+{
+	const EVP_MD *md_type;
+	HMAC_CTX *hmac = NULL;
+	unsigned char key[EVP_MAX_MD_SIZE], *salt;
+	int saltlen, iter;
+	int md_size;
+	int ret = 0;
+
+	if (!PKCS7_type_is_data(p12->authsafes)) {
+		PKCS12error(PKCS12_R_CONTENT_TYPE_NOT_DATA);
+		goto err;
+	}
+
+	salt = p12->mac->salt->data;
+	saltlen = p12->mac->salt->length;
+
+	iter = 1;
+	if (p12->mac->iter != NULL) {
+		if ((iter = ASN1_INTEGER_get(p12->mac->iter)) <= 0) {
+			PKCS12error(PKCS12_R_DECODE_ERROR);
+			goto err;
+		}
+	}
+
+	md_type = EVP_get_digestbyobj(p12->mac->dinfo->algor->algorithm);
+	if (md_type == NULL) {
+		PKCS12error(PKCS12_R_UNKNOWN_DIGEST_ALGORITHM);
+		goto err;
+	}
+
+	if ((md_size = EVP_MD_size(md_type)) < 0)
+		goto err;
+
+	if (!PKCS12_key_gen(pass, passlen, salt, saltlen, PKCS12_MAC_ID, iter,
+	    md_size, key, md_type)) {
+		PKCS12error(PKCS12_R_KEY_GEN_ERROR);
+		goto err;
+	}
+
+	if ((hmac = HMAC_CTX_new()) == NULL)
+		goto err;
+	if (!HMAC_Init_ex(hmac, key, md_size, md_type, NULL))
+		goto err;
+	if (!HMAC_Update(hmac, p12->authsafes->d.data->data,
+	    p12->authsafes->d.data->length))
+		goto err;
+	if (!HMAC_Final(hmac, mac, maclen))
+		goto err;
+
+	ret = 1;
+
+ err:
+	explicit_bzero(key, sizeof(key));
+	HMAC_CTX_free(hmac);
+
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS12_gen_mac);
+
+/* Verify the mac */
+int
+PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen)
+{
+	unsigned char mac[EVP_MAX_MD_SIZE];
+	unsigned int maclen;
+
+	if (p12->mac == NULL) {
+		PKCS12error(PKCS12_R_MAC_ABSENT);
+		return 0;
+	}
+	if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) {
+		PKCS12error(PKCS12_R_MAC_GENERATION_ERROR);
+		return 0;
+	}
+	if ((maclen != (unsigned int)p12->mac->dinfo->digest->length) ||
+	    memcmp(mac, p12->mac->dinfo->digest->data, maclen))
+		return 0;
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS12_verify_mac);
+
+/* Set a mac */
+
+int
+PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *salt,
+    int saltlen, int iter, const EVP_MD *md_type)
+{
+	unsigned char mac[EVP_MAX_MD_SIZE];
+	unsigned int maclen;
+
+	if (!md_type)
+		md_type = EVP_sha1();
+	if (PKCS12_setup_mac(p12, iter, salt, saltlen, md_type) ==
+	    PKCS12_ERROR) {
+		PKCS12error(PKCS12_R_MAC_SETUP_ERROR);
+		return 0;
+	}
+	if (!PKCS12_gen_mac(p12, pass, passlen, mac, &maclen)) {
+		PKCS12error(PKCS12_R_MAC_GENERATION_ERROR);
+		return 0;
+	}
+	if (!(ASN1_STRING_set(p12->mac->dinfo->digest, mac, maclen))) {
+		PKCS12error(PKCS12_R_MAC_STRING_SET_ERROR);
+		return 0;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS12_set_mac);
+
+/* Set up a mac structure */
+int
+PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
+    const EVP_MD *md_type)
+{
+	PKCS12_MAC_DATA_free(p12->mac);
+	if ((p12->mac = PKCS12_MAC_DATA_new()) == NULL)
+		return PKCS12_ERROR;
+	if (iter > 1) {
+		if (!(p12->mac->iter = ASN1_INTEGER_new())) {
+			PKCS12error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		if (!ASN1_INTEGER_set(p12->mac->iter, iter)) {
+			PKCS12error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+	if (!saltlen)
+		saltlen = PKCS12_SALT_LEN;
+	if (!(p12->mac->salt->data = malloc(saltlen))) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	p12->mac->salt->length = saltlen;
+	if (!salt)
+		arc4random_buf(p12->mac->salt->data, saltlen);
+	else
+		memcpy(p12->mac->salt->data, salt, saltlen);
+	p12->mac->dinfo->algor->algorithm = OBJ_nid2obj(EVP_MD_type(md_type));
+	if (!(p12->mac->dinfo->algor->parameter = ASN1_TYPE_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	p12->mac->dinfo->algor->parameter->type = V_ASN1_NULL;
+
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS12_setup_mac);
+#endif
diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c
new file mode 100644
index 0000000..30dd2ef
--- /dev/null
+++ b/crypto/pkcs12/p12_npas.c
@@ -0,0 +1,249 @@
+/* $OpenBSD: p12_npas.c,v 1.18 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pkcs12_local.h"
+#include "x509_local.h"
+
+/* PKCS#12 password change routine */
+
+static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass);
+static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass,
+    const char *newpass);
+static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass,
+    const char *newpass);
+static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen);
+
+/*
+ * Change the password on a PKCS#12 structure.
+ */
+
+int
+PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass)
+{
+	/* Check for NULL PKCS12 structure */
+
+	if (!p12) {
+		PKCS12error(PKCS12_R_INVALID_NULL_PKCS12_POINTER);
+		return 0;
+	}
+
+	/* Check the mac */
+
+	if (!PKCS12_verify_mac(p12, oldpass, -1)) {
+		PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE);
+		return 0;
+	}
+
+	if (!newpass_p12(p12, oldpass, newpass)) {
+		PKCS12error(PKCS12_R_PARSE_ERROR);
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS12_newpass);
+
+/* Parse the outer PKCS#12 structure */
+
+static int
+newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass)
+{
+	STACK_OF(PKCS7) *asafes, *newsafes;
+	STACK_OF(PKCS12_SAFEBAG) *bags;
+	int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0;
+	PKCS7 *p7, *p7new;
+	ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL;
+	unsigned char mac[EVP_MAX_MD_SIZE];
+	unsigned int maclen;
+
+	if (!(asafes = PKCS12_unpack_authsafes(p12)))
+		return 0;
+	if (!(newsafes = sk_PKCS7_new_null()))
+		return 0;
+	for (i = 0; i < sk_PKCS7_num(asafes); i++) {
+		p7 = sk_PKCS7_value(asafes, i);
+		bagnid = OBJ_obj2nid(p7->type);
+		if (bagnid == NID_pkcs7_data) {
+			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)) {
+				sk_PKCS12_SAFEBAG_pop_free(bags,
+				    PKCS12_SAFEBAG_free);
+				bags = NULL;
+			}
+		} else
+			continue;
+		if (bags == NULL)
+			goto err;
+		if (!newpass_bags(bags, oldpass, newpass)) {
+			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+			goto err;
+		}
+		/* Repack bag in same form with new password */
+		if (bagnid == NID_pkcs7_data)
+			p7new = PKCS12_pack_p7data(bags);
+		else
+			p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1,
+			    NULL, pbe_saltlen, pbe_iter, bags);
+		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+		if (p7new == NULL)
+			goto err;
+		if (sk_PKCS7_push(newsafes, p7new) == 0)
+			goto err;
+	}
+	sk_PKCS7_pop_free(asafes, PKCS7_free);
+
+	/* Repack safe: save old safe in case of error */
+
+	p12_data_tmp = p12->authsafes->d.data;
+	if (!(p12->authsafes->d.data = ASN1_OCTET_STRING_new())) {
+		p12->authsafes->d.data = p12_data_tmp;
+		goto err;
+	}
+	if (!PKCS12_pack_authsafes(p12, newsafes))
+		goto saferr;
+
+	if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen))
+		goto saferr;
+	if (!(macnew = ASN1_OCTET_STRING_new()))
+		goto saferr;
+	if (!ASN1_OCTET_STRING_set(macnew, mac, maclen))
+		goto saferr;
+	ASN1_OCTET_STRING_free(p12->mac->dinfo->digest);
+	p12->mac->dinfo->digest = macnew;
+	ASN1_OCTET_STRING_free(p12_data_tmp);
+
+	return 1;
+
+saferr:
+	/* Restore old safe */
+	ASN1_OCTET_STRING_free(p12->authsafes->d.data);
+	ASN1_OCTET_STRING_free(macnew);
+	p12->authsafes->d.data = p12_data_tmp;
+	return 0;
+
+err:
+	sk_PKCS7_pop_free(asafes, PKCS7_free);
+	sk_PKCS7_pop_free(newsafes, PKCS7_free);
+	return 0;
+}
+
+
+static int
+newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass,
+    const char *newpass)
+{
+	int i;
+
+	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
+		if (!newpass_bag(sk_PKCS12_SAFEBAG_value(bags, i),
+		    oldpass, newpass))
+			return 0;
+	}
+	return 1;
+}
+
+/* Change password of safebag: only needs handle shrouded keybags */
+
+static int
+newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass, const char *newpass)
+{
+	PKCS8_PRIV_KEY_INFO *p8;
+	X509_SIG *p8new;
+	int p8_nid, p8_saltlen, p8_iter;
+
+	if (OBJ_obj2nid(bag->type) != NID_pkcs8ShroudedKeyBag)
+		return 1;
+
+	if (!(p8 = PKCS8_decrypt(bag->value.shkeybag, oldpass, -1)))
+		return 0;
+	if (!alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter,
+	    &p8_saltlen))
+		return 0;
+	if (!(p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen,
+	    p8_iter, p8))) return 0;
+	X509_SIG_free(bag->value.shkeybag);
+	bag->value.shkeybag = p8new;
+	return 1;
+}
+
+static int
+alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen)
+{
+	PBEPARAM *pbe;
+	const unsigned char *p;
+
+	p = alg->parameter->value.sequence->data;
+	pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length);
+	if (!pbe)
+		return 0;
+	*pnid = OBJ_obj2nid(alg->algorithm);
+	*piter = ASN1_INTEGER_get(pbe->iter);
+	*psaltlen = pbe->salt->length;
+	PBEPARAM_free(pbe);
+	return 1;
+}
diff --git a/crypto/pkcs12/p12_p8d.c b/crypto/pkcs12/p12_p8d.c
new file mode 100644
index 0000000..dd5e8d9
--- /dev/null
+++ b/crypto/pkcs12/p12_p8d.c
@@ -0,0 +1,71 @@
+/* $OpenBSD: p12_p8d.c,v 1.11 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include "x509_local.h"
+
+PKCS8_PRIV_KEY_INFO *
+PKCS8_decrypt(const X509_SIG *p8, const char *pass, int passlen)
+{
+	return PKCS12_item_decrypt_d2i(p8->algor,
+	    &PKCS8_PRIV_KEY_INFO_it, pass, passlen, p8->digest, 1);
+}
+LCRYPTO_ALIAS(PKCS8_decrypt);
diff --git a/crypto/pkcs12/p12_p8e.c b/crypto/pkcs12/p12_p8e.c
new file mode 100644
index 0000000..87c4be5
--- /dev/null
+++ b/crypto/pkcs12/p12_p8e.c
@@ -0,0 +1,103 @@
+/* $OpenBSD: p12_p8e.c,v 1.12 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "x509_local.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 *p8 = NULL;
+	X509_ALGOR *pbe;
+
+	if (!(p8 = X509_SIG_new())) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (pbe_nid == -1)
+		pbe = PKCS5_pbe2_set(cipher, iter, salt, saltlen);
+	else
+		pbe = PKCS5_pbe_set(pbe_nid, iter, salt, saltlen);
+	if (!pbe) {
+		PKCS12error(ERR_R_ASN1_LIB);
+		goto err;
+	}
+	X509_ALGOR_free(p8->algor);
+	p8->algor = pbe;
+	ASN1_OCTET_STRING_free(p8->digest);
+	p8->digest = PKCS12_item_i2d_encrypt(pbe,
+	    &PKCS8_PRIV_KEY_INFO_it, pass, passlen, p8inf, 1);
+	if (!p8->digest) {
+		PKCS12error(PKCS12_R_ENCRYPT_ERROR);
+		goto err;
+	}
+
+	return p8;
+
+err:
+	X509_SIG_free(p8);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS8_encrypt);
diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c
new file mode 100644
index 0000000..b7772b6
--- /dev/null
+++ b/crypto/pkcs12/p12_sbag.c
@@ -0,0 +1,240 @@
+/* $OpenBSD: p12_sbag.c,v 1.8 2023/02/16 08:38:17 tb Exp $ */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999-2018.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+
+#include "pkcs12_local.h"
+#include "x509_local.h"
+
+const ASN1_TYPE *
+PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag, int attr_nid)
+{
+	return PKCS12_get_attr_gen(bag->attrib, attr_nid);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_attr);
+
+ASN1_TYPE *
+PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid)
+{
+	return PKCS12_get_attr_gen(p8->attributes, attr_nid);
+}
+LCRYPTO_ALIAS(PKCS8_get_attr);
+
+const PKCS8_PRIV_KEY_INFO *
+PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag)
+{
+	if (PKCS12_SAFEBAG_get_nid(bag) != NID_keyBag)
+		return NULL;
+
+	return bag->value.keybag;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_p8inf);
+
+const X509_SIG *
+PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag)
+{
+	if (PKCS12_SAFEBAG_get_nid(bag) != NID_pkcs8ShroudedKeyBag)
+		return NULL;
+
+	return bag->value.shkeybag;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_pkcs8);
+
+const STACK_OF(PKCS12_SAFEBAG) *
+PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag)
+{
+	if (PKCS12_SAFEBAG_get_nid(bag) != NID_safeContentsBag)
+		return NULL;
+
+	return bag->value.safes;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_safes);
+
+const ASN1_OBJECT *
+PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag)
+{
+	return bag->type;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get0_type);
+
+int
+PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag)
+{
+	return OBJ_obj2nid(bag->type);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get_nid);
+
+int
+PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag)
+{
+	int bag_type;
+
+	bag_type = PKCS12_SAFEBAG_get_nid(bag);
+
+	if (bag_type == NID_certBag || bag_type == NID_crlBag ||
+	    bag_type == NID_secretBag)
+		return OBJ_obj2nid(bag->value.bag->type);
+
+	return -1;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get_bag_nid);
+
+X509 *
+PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag)
+{
+	if (OBJ_obj2nid(bag->type) != NID_certBag)
+		return NULL;
+	if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate)
+		return NULL;
+	return ASN1_item_unpack(bag->value.bag->value.octet, &X509_it);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get1_cert);
+
+X509_CRL *
+PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag)
+{
+	if (OBJ_obj2nid(bag->type) != NID_crlBag)
+		return NULL;
+	if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl)
+		return NULL;
+	return ASN1_item_unpack(bag->value.bag->value.octet, &X509_CRL_it);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_get1_crl);
+
+PKCS12_SAFEBAG *
+PKCS12_SAFEBAG_create_cert(X509 *x509)
+{
+	return PKCS12_item_pack_safebag(x509, &X509_it,
+	    NID_x509Certificate, NID_certBag);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_create_cert);
+
+PKCS12_SAFEBAG *
+PKCS12_SAFEBAG_create_crl(X509_CRL *crl)
+{
+	return PKCS12_item_pack_safebag(crl, &X509_CRL_it,
+	    NID_x509Crl, NID_crlBag);
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_create_crl);
+
+/* Turn PKCS8 object into a keybag */
+
+PKCS12_SAFEBAG *
+PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8)
+{
+	PKCS12_SAFEBAG *bag;
+
+	if ((bag = PKCS12_SAFEBAG_new()) == NULL) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	bag->type = OBJ_nid2obj(NID_keyBag);
+	bag->value.keybag = p8;
+
+	return bag;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_create0_p8inf);
+
+/* Turn PKCS8 object into a shrouded keybag */
+
+PKCS12_SAFEBAG *
+PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8)
+{
+	PKCS12_SAFEBAG *bag;
+
+	/* Set up the safe bag */
+	if ((bag = PKCS12_SAFEBAG_new()) == NULL) {
+		PKCS12error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag);
+	bag->value.shkeybag = p8;
+
+	return bag;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_create0_pkcs8);
+
+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 *p8info)
+{
+	const EVP_CIPHER *pbe_ciph;
+	X509_SIG *p8;
+	PKCS12_SAFEBAG *bag;
+
+	if ((pbe_ciph = EVP_get_cipherbynid(pbe_nid)) != NULL)
+		pbe_nid = -1;
+
+	if ((p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen,
+	    iter, p8info)) == NULL)
+		return NULL;
+
+	if ((bag = PKCS12_SAFEBAG_create0_pkcs8(p8)) == NULL) {
+		X509_SIG_free(p8);
+		return NULL;
+	}
+
+	return bag;
+}
+LCRYPTO_ALIAS(PKCS12_SAFEBAG_create_pkcs8_encrypt);
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
new file mode 100644
index 0000000..72692a9
--- /dev/null
+++ b/crypto/pkcs12/p12_utl.c
@@ -0,0 +1,157 @@
+/* $OpenBSD: p12_utl.c,v 1.21 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include "pkcs12_local.h"
+
+/* Cheap and nasty Unicode stuff */
+
+unsigned char *
+OPENSSL_asc2uni(const char *asc, int asclen, unsigned char **uni, int *unilen)
+{
+	size_t ulen, i;
+	unsigned char *unitmp;
+
+	if (asclen < 0)
+		ulen = strlen(asc);
+	else
+		ulen = (size_t)asclen;
+	ulen++;
+	if (ulen == 0) /* unlikely overflow */
+		return NULL;
+	if ((unitmp = reallocarray(NULL, ulen, 2)) == NULL)
+		return NULL;
+	ulen *= 2;
+	/* XXX This interface ought to use unsigned types */
+	if (ulen > INT_MAX) {
+		free(unitmp);
+		return NULL;
+	}
+	for (i = 0; i < ulen - 2; i += 2) {
+		unitmp[i] = 0;
+		unitmp[i + 1] = *asc++;
+	}
+	/* Make result double-NUL terminated */
+	unitmp[ulen - 2] = 0;
+	unitmp[ulen - 1] = 0;
+	if (unilen)
+		*unilen = ulen;
+	if (uni)
+		*uni = unitmp;
+	return unitmp;
+}
+LCRYPTO_ALIAS(OPENSSL_asc2uni);
+
+char *
+OPENSSL_uni2asc(const unsigned char *uni, int unilen)
+{
+	size_t asclen, u16len, i;
+	char *asctmp;
+
+	if (unilen < 0)
+		return NULL;
+
+	asclen = u16len = (size_t)unilen / 2;
+	/* If no terminating NUL, allow for one */
+	if (unilen == 0 || uni[unilen - 1] != '\0')
+		asclen++;
+	if ((asctmp = malloc(asclen)) == NULL)
+		return NULL;
+	/* Skip first zero byte */
+	uni++;
+	for (i = 0; i < u16len; i++) {
+		asctmp[i] = *uni;
+		uni += 2;
+	}
+	asctmp[asclen - 1] = '\0';
+	return asctmp;
+}
+LCRYPTO_ALIAS(OPENSSL_uni2asc);
+
+int
+i2d_PKCS12_bio(BIO *bp, PKCS12 *p12)
+{
+	return ASN1_item_i2d_bio(&PKCS12_it, bp, p12);
+}
+LCRYPTO_ALIAS(i2d_PKCS12_bio);
+
+int
+i2d_PKCS12_fp(FILE *fp, PKCS12 *p12)
+{
+	return ASN1_item_i2d_fp(&PKCS12_it, fp, p12);
+}
+LCRYPTO_ALIAS(i2d_PKCS12_fp);
+
+PKCS12 *
+d2i_PKCS12_bio(BIO *bp, PKCS12 **p12)
+{
+	return ASN1_item_d2i_bio(&PKCS12_it, bp, p12);
+}
+LCRYPTO_ALIAS(d2i_PKCS12_bio);
+
+PKCS12 *
+d2i_PKCS12_fp(FILE *fp, PKCS12 **p12)
+{
+	    return ASN1_item_d2i_fp(&PKCS12_it, fp, p12);
+}
+LCRYPTO_ALIAS(d2i_PKCS12_fp);
diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c
new file mode 100644
index 0000000..3af0352
--- /dev/null
+++ b/crypto/pkcs12/pk12err.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: pk12err.c,v 1.14 2023/02/16 08:38:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_PKCS12,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_PKCS12,0,reason)
+
+static ERR_STRING_DATA PKCS12_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA PKCS12_str_reasons[]= {
+	{ERR_REASON(PKCS12_R_CANT_PACK_STRUCTURE), "cant pack structure"},
+	{ERR_REASON(PKCS12_R_CONTENT_TYPE_NOT_DATA), "content type not data"},
+	{ERR_REASON(PKCS12_R_DECODE_ERROR)       , "decode error"},
+	{ERR_REASON(PKCS12_R_ENCODE_ERROR)       , "encode error"},
+	{ERR_REASON(PKCS12_R_ENCRYPT_ERROR)      , "encrypt error"},
+	{ERR_REASON(PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE), "error setting encrypted data type"},
+	{ERR_REASON(PKCS12_R_INVALID_NULL_ARGUMENT), "invalid null argument"},
+	{ERR_REASON(PKCS12_R_INVALID_NULL_PKCS12_POINTER), "invalid null pkcs12 pointer"},
+	{ERR_REASON(PKCS12_R_IV_GEN_ERROR)       , "iv gen error"},
+	{ERR_REASON(PKCS12_R_KEY_GEN_ERROR)      , "key gen error"},
+	{ERR_REASON(PKCS12_R_MAC_ABSENT)         , "mac absent"},
+	{ERR_REASON(PKCS12_R_MAC_GENERATION_ERROR), "mac generation error"},
+	{ERR_REASON(PKCS12_R_MAC_SETUP_ERROR)    , "mac setup error"},
+	{ERR_REASON(PKCS12_R_MAC_STRING_SET_ERROR), "mac string set error"},
+	{ERR_REASON(PKCS12_R_MAC_VERIFY_ERROR)   , "mac verify error"},
+	{ERR_REASON(PKCS12_R_MAC_VERIFY_FAILURE) , "mac verify failure"},
+	{ERR_REASON(PKCS12_R_PARSE_ERROR)        , "parse error"},
+	{ERR_REASON(PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR), "pkcs12 algor cipherinit error"},
+	{ERR_REASON(PKCS12_R_PKCS12_CIPHERFINAL_ERROR), "pkcs12 cipherfinal error"},
+	{ERR_REASON(PKCS12_R_PKCS12_PBE_CRYPT_ERROR), "pkcs12 pbe crypt error"},
+	{ERR_REASON(PKCS12_R_UNKNOWN_DIGEST_ALGORITHM), "unknown digest algorithm"},
+	{ERR_REASON(PKCS12_R_UNSUPPORTED_PKCS12_MODE), "unsupported pkcs12 mode"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_PKCS12_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(PKCS12_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, PKCS12_str_functs);
+		ERR_load_strings(0, PKCS12_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_PKCS12_strings);
diff --git a/crypto/pkcs12/pkcs12_local.h b/crypto/pkcs12/pkcs12_local.h
new file mode 100644
index 0000000..1d6f055
--- /dev/null
+++ b/crypto/pkcs12/pkcs12_local.h
@@ -0,0 +1,101 @@
+/* $OpenBSD: pkcs12_local.h,v 1.3 2022/11/26 17:23:18 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_PKCS12_LOCAL_H
+#define HEADER_PKCS12_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+struct PKCS12_MAC_DATA_st {
+	X509_SIG *dinfo;
+	ASN1_OCTET_STRING *salt;
+	ASN1_INTEGER *iter;	/* defaults to 1 */
+};
+
+struct PKCS12_st {
+	ASN1_INTEGER *version;
+	PKCS12_MAC_DATA *mac;
+	PKCS7 *authsafes;
+};
+
+struct PKCS12_SAFEBAG_st {
+	ASN1_OBJECT *type;
+	union {
+	struct pkcs12_bag_st *bag; /* secret, crl and certbag */
+	struct pkcs8_priv_key_info_st	*keybag; /* keybag */
+	X509_SIG *shkeybag; /* shrouded key bag */
+		STACK_OF(PKCS12_SAFEBAG) *safes;
+		ASN1_TYPE *other;
+	} value;
+	STACK_OF(X509_ATTRIBUTE) *attrib;
+};
+
+struct pkcs12_bag_st {
+	ASN1_OBJECT *type;
+	union {
+		ASN1_OCTET_STRING *x509cert;
+		ASN1_OCTET_STRING *x509crl;
+		ASN1_OCTET_STRING *octet;
+		ASN1_IA5STRING *sdsicert;
+		ASN1_TYPE *other; /* Secret or other bag */
+	} value;
+};
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_PKCS12_LOCAL_H */
diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c
new file mode 100644
index 0000000..27f4103
--- /dev/null
+++ b/crypto/pkcs7/pk7_asn1.c
@@ -0,0 +1,1041 @@
+/* $OpenBSD: pk7_asn1.c,v 1.17 2023/04/25 18:04:03 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+/* PKCS#7 ASN1 module */
+
+/* This is the ANY DEFINED BY table for the top level PKCS#7 structure */
+
+static const ASN1_TEMPLATE p7default_tt = {
+	.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+	.tag = 0,
+	.offset = offsetof(PKCS7, d.other),
+	.field_name = "d.other",
+	.item = &ASN1_ANY_it,
+};
+
+static const ASN1_ADB_TABLE PKCS7_adbtbl[] = {
+	{
+		.value = NID_pkcs7_data,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.data),
+			.field_name = "d.data",
+			.item = &ASN1_OCTET_STRING_NDEF_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs7_signed,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.sign),
+			.field_name = "d.sign",
+			.item = &PKCS7_SIGNED_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs7_enveloped,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.enveloped),
+			.field_name = "d.enveloped",
+			.item = &PKCS7_ENVELOPE_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs7_signedAndEnveloped,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.signed_and_enveloped),
+			.field_name = "d.signed_and_enveloped",
+			.item = &PKCS7_SIGN_ENVELOPE_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs7_digest,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.digest),
+			.field_name = "d.digest",
+			.item = &PKCS7_DIGEST_it,
+		},
+	
+	},
+	{
+		.value = NID_pkcs7_encrypted,
+		.tt = {
+			.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL | ASN1_TFLG_NDEF,
+			.tag = 0,
+			.offset = offsetof(PKCS7, d.encrypted),
+			.field_name = "d.encrypted",
+			.item = &PKCS7_ENCRYPT_it,
+		},
+	
+	},
+};
+
+static const ASN1_ADB PKCS7_adb = {
+	.flags = 0,
+	.offset = offsetof(PKCS7, type),
+	.tbl = PKCS7_adbtbl,
+	.tblcount = sizeof(PKCS7_adbtbl) / sizeof(ASN1_ADB_TABLE),
+	.default_tt = &p7default_tt,
+	.null_tt = NULL,
+};
+
+/* PKCS#7 streaming support */
+static int
+pk7_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	ASN1_STREAM_ARG *sarg = exarg;
+	PKCS7 **pp7 = (PKCS7 **)pval;
+
+	switch (operation) {
+	case ASN1_OP_STREAM_PRE:
+		if (PKCS7_stream(&sarg->boundary, *pp7) <= 0)
+			return 0;
+		/* FALLTHROUGH */
+
+	case ASN1_OP_DETACHED_PRE:
+		sarg->ndef_bio = PKCS7_dataInit(*pp7, sarg->out);
+		if (!sarg->ndef_bio)
+			return 0;
+		break;
+
+	case ASN1_OP_STREAM_POST:
+	case ASN1_OP_DETACHED_POST:
+		if (PKCS7_dataFinal(*pp7, sarg->ndef_bio) <= 0)
+			return 0;
+		break;
+	}
+	return 1;
+}
+
+static const ASN1_AUX PKCS7_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = pk7_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE PKCS7_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7, type),
+		.field_name = "type",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_ADB_OID,
+		.tag = -1,
+		.offset = 0,
+		.field_name = "PKCS7",
+		.item = (const ASN1_ITEM *)&PKCS7_adb,
+	},
+};
+
+const ASN1_ITEM PKCS7_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_seq_tt,
+	.tcount = sizeof(PKCS7_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &PKCS7_aux,
+	.size = sizeof(PKCS7),
+	.sname = "PKCS7",
+};
+
+
+PKCS7 *
+d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len)
+{
+	return (PKCS7 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7);
+
+int
+i2d_PKCS7(PKCS7 *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7);
+
+PKCS7 *
+PKCS7_new(void)
+{
+	return (PKCS7 *)ASN1_item_new(&PKCS7_it);
+}
+LCRYPTO_ALIAS(PKCS7_new);
+
+void
+PKCS7_free(PKCS7 *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_it);
+}
+LCRYPTO_ALIAS(PKCS7_free);
+
+PKCS7 *
+PKCS7_dup(PKCS7 *x)
+{
+	return ASN1_item_dup(&PKCS7_it, x);
+}
+LCRYPTO_ALIAS(PKCS7_dup);
+
+static const ASN1_TEMPLATE PKCS7_SIGNED_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNED, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNED, md_algs),
+		.field_name = "md_algs",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNED, contents),
+		.field_name = "contents",
+		.item = &PKCS7_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNED, cert),
+		.field_name = "cert",
+		.item = &X509_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(PKCS7_SIGNED, crl),
+		.field_name = "crl",
+		.item = &X509_CRL_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNED, signer_info),
+		.field_name = "signer_info",
+		.item = &PKCS7_SIGNER_INFO_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_SIGNED_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_SIGNED_seq_tt,
+	.tcount = sizeof(PKCS7_SIGNED_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_SIGNED),
+	.sname = "PKCS7_SIGNED",
+};
+
+
+PKCS7_SIGNED *
+d2i_PKCS7_SIGNED(PKCS7_SIGNED **a, const unsigned char **in, long len)
+{
+	return (PKCS7_SIGNED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_SIGNED_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_SIGNED);
+
+int
+i2d_PKCS7_SIGNED(PKCS7_SIGNED *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_SIGNED_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_SIGNED);
+
+PKCS7_SIGNED *
+PKCS7_SIGNED_new(void)
+{
+	return (PKCS7_SIGNED *)ASN1_item_new(&PKCS7_SIGNED_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGNED_new);
+
+void
+PKCS7_SIGNED_free(PKCS7_SIGNED *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_SIGNED_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGNED_free);
+
+/* Minor tweak to operation: free up EVP_PKEY */
+static int
+si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_FREE_POST) {
+		PKCS7_SIGNER_INFO *si = (PKCS7_SIGNER_INFO *)*pval;
+		EVP_PKEY_free(si->pkey);
+	}
+	return 1;
+}
+
+static const ASN1_AUX PKCS7_SIGNER_INFO_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = si_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE PKCS7_SIGNER_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, issuer_and_serial),
+		.field_name = "issuer_and_serial",
+		.item = &PKCS7_ISSUER_AND_SERIAL_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, digest_alg),
+		.field_name = "digest_alg",
+		.item = &X509_ALGOR_it,
+	},
+	/* NB this should be a SET OF but we use a SEQUENCE OF so the
+	 * original order * is retained when the structure is reencoded.
+	 * Since the attributes are implicitly tagged this will not affect
+	 * the encoding.
+	 */
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, auth_attr),
+		.field_name = "auth_attr",
+		.item = &X509_ATTRIBUTE_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, digest_enc_alg),
+		.field_name = "digest_enc_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGNER_INFO, enc_digest),
+		.field_name = "enc_digest",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(PKCS7_SIGNER_INFO, unauth_attr),
+		.field_name = "unauth_attr",
+		.item = &X509_ATTRIBUTE_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_SIGNER_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_SIGNER_INFO_seq_tt,
+	.tcount = sizeof(PKCS7_SIGNER_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &PKCS7_SIGNER_INFO_aux,
+	.size = sizeof(PKCS7_SIGNER_INFO),
+	.sname = "PKCS7_SIGNER_INFO",
+};
+
+
+PKCS7_SIGNER_INFO *
+d2i_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO **a, const unsigned char **in, long len)
+{
+	return (PKCS7_SIGNER_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_SIGNER_INFO_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_SIGNER_INFO);
+
+int
+i2d_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_SIGNER_INFO_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_SIGNER_INFO);
+
+PKCS7_SIGNER_INFO *
+PKCS7_SIGNER_INFO_new(void)
+{
+	return (PKCS7_SIGNER_INFO *)ASN1_item_new(&PKCS7_SIGNER_INFO_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_new);
+
+void
+PKCS7_SIGNER_INFO_free(PKCS7_SIGNER_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_SIGNER_INFO_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_free);
+
+static const ASN1_TEMPLATE PKCS7_ISSUER_AND_SERIAL_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ISSUER_AND_SERIAL, issuer),
+		.field_name = "issuer",
+		.item = &X509_NAME_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ISSUER_AND_SERIAL, serial),
+		.field_name = "serial",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_ISSUER_AND_SERIAL_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_ISSUER_AND_SERIAL_seq_tt,
+	.tcount = sizeof(PKCS7_ISSUER_AND_SERIAL_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_ISSUER_AND_SERIAL),
+	.sname = "PKCS7_ISSUER_AND_SERIAL",
+};
+
+
+PKCS7_ISSUER_AND_SERIAL *
+d2i_PKCS7_ISSUER_AND_SERIAL(PKCS7_ISSUER_AND_SERIAL **a, const unsigned char **in, long len)
+{
+	return (PKCS7_ISSUER_AND_SERIAL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_ISSUER_AND_SERIAL_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_ISSUER_AND_SERIAL);
+
+int
+i2d_PKCS7_ISSUER_AND_SERIAL(PKCS7_ISSUER_AND_SERIAL *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_ISSUER_AND_SERIAL_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_ISSUER_AND_SERIAL);
+
+PKCS7_ISSUER_AND_SERIAL *
+PKCS7_ISSUER_AND_SERIAL_new(void)
+{
+	return (PKCS7_ISSUER_AND_SERIAL *)ASN1_item_new(&PKCS7_ISSUER_AND_SERIAL_it);
+}
+LCRYPTO_ALIAS(PKCS7_ISSUER_AND_SERIAL_new);
+
+void
+PKCS7_ISSUER_AND_SERIAL_free(PKCS7_ISSUER_AND_SERIAL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_ISSUER_AND_SERIAL_it);
+}
+LCRYPTO_ALIAS(PKCS7_ISSUER_AND_SERIAL_free);
+
+static const ASN1_TEMPLATE PKCS7_ENVELOPE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENVELOPE, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENVELOPE, recipientinfo),
+		.field_name = "recipientinfo",
+		.item = &PKCS7_RECIP_INFO_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENVELOPE, enc_data),
+		.field_name = "enc_data",
+		.item = &PKCS7_ENC_CONTENT_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_ENVELOPE_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_ENVELOPE_seq_tt,
+	.tcount = sizeof(PKCS7_ENVELOPE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_ENVELOPE),
+	.sname = "PKCS7_ENVELOPE",
+};
+
+
+PKCS7_ENVELOPE *
+d2i_PKCS7_ENVELOPE(PKCS7_ENVELOPE **a, const unsigned char **in, long len)
+{
+	return (PKCS7_ENVELOPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_ENVELOPE);
+
+int
+i2d_PKCS7_ENVELOPE(PKCS7_ENVELOPE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_ENVELOPE);
+
+PKCS7_ENVELOPE *
+PKCS7_ENVELOPE_new(void)
+{
+	return (PKCS7_ENVELOPE *)ASN1_item_new(&PKCS7_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENVELOPE_new);
+
+void
+PKCS7_ENVELOPE_free(PKCS7_ENVELOPE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENVELOPE_free);
+
+/* Minor tweak to operation: free up X509 */
+static int
+ri_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_FREE_POST) {
+		PKCS7_RECIP_INFO *ri = (PKCS7_RECIP_INFO *)*pval;
+		X509_free(ri->cert);
+	}
+	return 1;
+}
+
+static const ASN1_AUX PKCS7_RECIP_INFO_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = ri_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE PKCS7_RECIP_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_RECIP_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_RECIP_INFO, issuer_and_serial),
+		.field_name = "issuer_and_serial",
+		.item = &PKCS7_ISSUER_AND_SERIAL_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_RECIP_INFO, key_enc_algor),
+		.field_name = "key_enc_algor",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_RECIP_INFO, enc_key),
+		.field_name = "enc_key",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_RECIP_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_RECIP_INFO_seq_tt,
+	.tcount = sizeof(PKCS7_RECIP_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &PKCS7_RECIP_INFO_aux,
+	.size = sizeof(PKCS7_RECIP_INFO),
+	.sname = "PKCS7_RECIP_INFO",
+};
+
+
+PKCS7_RECIP_INFO *
+d2i_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO **a, const unsigned char **in, long len)
+{
+	return (PKCS7_RECIP_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_RECIP_INFO_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_RECIP_INFO);
+
+int
+i2d_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_RECIP_INFO_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_RECIP_INFO);
+
+PKCS7_RECIP_INFO *
+PKCS7_RECIP_INFO_new(void)
+{
+	return (PKCS7_RECIP_INFO *)ASN1_item_new(&PKCS7_RECIP_INFO_it);
+}
+LCRYPTO_ALIAS(PKCS7_RECIP_INFO_new);
+
+void
+PKCS7_RECIP_INFO_free(PKCS7_RECIP_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_RECIP_INFO_it);
+}
+LCRYPTO_ALIAS(PKCS7_RECIP_INFO_free);
+
+static const ASN1_TEMPLATE PKCS7_ENC_CONTENT_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENC_CONTENT, content_type),
+		.field_name = "content_type",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENC_CONTENT, algorithm),
+		.field_name = "algorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENC_CONTENT, enc_data),
+		.field_name = "enc_data",
+		.item = &ASN1_OCTET_STRING_NDEF_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_ENC_CONTENT_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_ENC_CONTENT_seq_tt,
+	.tcount = sizeof(PKCS7_ENC_CONTENT_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_ENC_CONTENT),
+	.sname = "PKCS7_ENC_CONTENT",
+};
+
+
+PKCS7_ENC_CONTENT *
+d2i_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT **a, const unsigned char **in, long len)
+{
+	return (PKCS7_ENC_CONTENT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_ENC_CONTENT_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_ENC_CONTENT);
+
+int
+i2d_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_ENC_CONTENT_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_ENC_CONTENT);
+
+PKCS7_ENC_CONTENT *
+PKCS7_ENC_CONTENT_new(void)
+{
+	return (PKCS7_ENC_CONTENT *)ASN1_item_new(&PKCS7_ENC_CONTENT_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENC_CONTENT_new);
+
+void
+PKCS7_ENC_CONTENT_free(PKCS7_ENC_CONTENT *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_ENC_CONTENT_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENC_CONTENT_free);
+
+static const ASN1_TEMPLATE PKCS7_SIGN_ENVELOPE_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, recipientinfo),
+		.field_name = "recipientinfo",
+		.item = &PKCS7_RECIP_INFO_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, md_algs),
+		.field_name = "md_algs",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, enc_data),
+		.field_name = "enc_data",
+		.item = &PKCS7_ENC_CONTENT_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, cert),
+		.field_name = "cert",
+		.item = &X509_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, crl),
+		.field_name = "crl",
+		.item = &X509_CRL_it,
+	},
+	{
+		.flags = ASN1_TFLG_SET_OF,
+		.tag = 0,
+		.offset = offsetof(PKCS7_SIGN_ENVELOPE, signer_info),
+		.field_name = "signer_info",
+		.item = &PKCS7_SIGNER_INFO_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_SIGN_ENVELOPE_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_SIGN_ENVELOPE_seq_tt,
+	.tcount = sizeof(PKCS7_SIGN_ENVELOPE_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_SIGN_ENVELOPE),
+	.sname = "PKCS7_SIGN_ENVELOPE",
+};
+
+
+PKCS7_SIGN_ENVELOPE *
+d2i_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE **a, const unsigned char **in, long len)
+{
+	return (PKCS7_SIGN_ENVELOPE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_SIGN_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_SIGN_ENVELOPE);
+
+int
+i2d_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_SIGN_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_SIGN_ENVELOPE);
+
+PKCS7_SIGN_ENVELOPE *
+PKCS7_SIGN_ENVELOPE_new(void)
+{
+	return (PKCS7_SIGN_ENVELOPE *)ASN1_item_new(&PKCS7_SIGN_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGN_ENVELOPE_new);
+
+void
+PKCS7_SIGN_ENVELOPE_free(PKCS7_SIGN_ENVELOPE *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_SIGN_ENVELOPE_it);
+}
+LCRYPTO_ALIAS(PKCS7_SIGN_ENVELOPE_free);
+
+static const ASN1_TEMPLATE PKCS7_ENCRYPT_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENCRYPT, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_ENCRYPT, enc_data),
+		.field_name = "enc_data",
+		.item = &PKCS7_ENC_CONTENT_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_ENCRYPT_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_ENCRYPT_seq_tt,
+	.tcount = sizeof(PKCS7_ENCRYPT_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_ENCRYPT),
+	.sname = "PKCS7_ENCRYPT",
+};
+
+
+PKCS7_ENCRYPT *
+d2i_PKCS7_ENCRYPT(PKCS7_ENCRYPT **a, const unsigned char **in, long len)
+{
+	return (PKCS7_ENCRYPT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_ENCRYPT_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_ENCRYPT);
+
+int
+i2d_PKCS7_ENCRYPT(PKCS7_ENCRYPT *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_ENCRYPT_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_ENCRYPT);
+
+PKCS7_ENCRYPT *
+PKCS7_ENCRYPT_new(void)
+{
+	return (PKCS7_ENCRYPT *)ASN1_item_new(&PKCS7_ENCRYPT_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENCRYPT_new);
+
+void
+PKCS7_ENCRYPT_free(PKCS7_ENCRYPT *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_ENCRYPT_it);
+}
+LCRYPTO_ALIAS(PKCS7_ENCRYPT_free);
+
+static const ASN1_TEMPLATE PKCS7_DIGEST_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_DIGEST, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_DIGEST, md),
+		.field_name = "md",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_DIGEST, contents),
+		.field_name = "contents",
+		.item = &PKCS7_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(PKCS7_DIGEST, digest),
+		.field_name = "digest",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM PKCS7_DIGEST_it = {
+	.itype = ASN1_ITYPE_NDEF_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = PKCS7_DIGEST_seq_tt,
+	.tcount = sizeof(PKCS7_DIGEST_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(PKCS7_DIGEST),
+	.sname = "PKCS7_DIGEST",
+};
+
+
+PKCS7_DIGEST *
+d2i_PKCS7_DIGEST(PKCS7_DIGEST **a, const unsigned char **in, long len)
+{
+	return (PKCS7_DIGEST *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &PKCS7_DIGEST_it);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_DIGEST);
+
+int
+i2d_PKCS7_DIGEST(PKCS7_DIGEST *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKCS7_DIGEST_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_DIGEST);
+
+PKCS7_DIGEST *
+PKCS7_DIGEST_new(void)
+{
+	return (PKCS7_DIGEST *)ASN1_item_new(&PKCS7_DIGEST_it);
+}
+LCRYPTO_ALIAS(PKCS7_DIGEST_new);
+
+void
+PKCS7_DIGEST_free(PKCS7_DIGEST *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &PKCS7_DIGEST_it);
+}
+LCRYPTO_ALIAS(PKCS7_DIGEST_free);
+
+/* Specials for authenticated attributes */
+
+/* When signing attributes we want to reorder them to match the sorted
+ * encoding.
+ */
+
+static const ASN1_TEMPLATE PKCS7_ATTR_SIGN_item_tt = {
+	.flags = ASN1_TFLG_SET_ORDER,
+	.tag = 0,
+	.offset = 0,
+	.field_name = "PKCS7_ATTRIBUTES",
+	.item = &X509_ATTRIBUTE_it,
+};
+
+const ASN1_ITEM PKCS7_ATTR_SIGN_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &PKCS7_ATTR_SIGN_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "PKCS7_ATTR_SIGN",
+};
+
+/* When verifying attributes we need to use the received order. So
+ * we use SEQUENCE OF and tag it to SET OF
+ */
+
+static const ASN1_TEMPLATE PKCS7_ATTR_VERIFY_item_tt = {
+	.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL,
+	.tag = V_ASN1_SET,
+	.offset = 0,
+	.field_name = "PKCS7_ATTRIBUTES",
+	.item = &X509_ATTRIBUTE_it,
+};
+
+const ASN1_ITEM PKCS7_ATTR_VERIFY_it = {
+	.itype = ASN1_ITYPE_PRIMITIVE,
+	.utype = -1,
+	.templates = &PKCS7_ATTR_VERIFY_item_tt,
+	.tcount = 0,
+	.funcs = NULL,
+	.size = 0,
+	.sname = "PKCS7_ATTR_VERIFY",
+};
+
+
+int
+PKCS7_print_ctx(BIO *out, PKCS7 *x, int indent, const ASN1_PCTX *pctx)
+{
+	return ASN1_item_print(out, (ASN1_VALUE *)x, indent,
+	    &PKCS7_it, pctx);
+}
+LCRYPTO_ALIAS(PKCS7_print_ctx);
+
+PKCS7 *
+d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
+{
+	return ASN1_item_d2i_bio(&PKCS7_it, bp, p7);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_bio);
+
+int
+i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
+{
+	return ASN1_item_i2d_bio(&PKCS7_it, bp, p7);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_bio);
+
+PKCS7 *
+d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
+{
+	return ASN1_item_d2i_fp(&PKCS7_it, fp, p7);
+}
+LCRYPTO_ALIAS(d2i_PKCS7_fp);
+
+int
+i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
+{
+	return ASN1_item_i2d_fp(&PKCS7_it, fp, p7);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_fp);
+
+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(&PKCS7_ISSUER_AND_SERIAL_it, type,
+	    (char *)data, md, len));
+}
+LCRYPTO_ALIAS(PKCS7_ISSUER_AND_SERIAL_digest);
diff --git a/crypto/pkcs7/pk7_attr.c b/crypto/pkcs7/pk7_attr.c
new file mode 100644
index 0000000..5eff524
--- /dev/null
+++ b/crypto/pkcs7/pk7_attr.c
@@ -0,0 +1,178 @@
+/* $OpenBSD: pk7_attr.c,v 1.14 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, STACK_OF(X509_ALGOR) *cap)
+{
+	ASN1_STRING *seq;
+	if (!(seq = ASN1_STRING_new())) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	seq->length = ASN1_item_i2d((ASN1_VALUE *)cap, &seq->data,
+	    &X509_ALGORS_it);
+	return PKCS7_add_signed_attribute(si, NID_SMIMECapabilities,
+	    V_ASN1_SEQUENCE, seq);
+}
+LCRYPTO_ALIAS(PKCS7_add_attrib_smimecap);
+
+STACK_OF(X509_ALGOR) *
+PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si)
+{
+	ASN1_TYPE *cap;
+	const unsigned char *p;
+
+	cap = PKCS7_get_signed_attribute(si, NID_SMIMECapabilities);
+	if (!cap || (cap->type != V_ASN1_SEQUENCE))
+		return NULL;
+	p = cap->value.sequence->data;
+	return (STACK_OF(X509_ALGOR) *)
+	ASN1_item_d2i(NULL, &p, cap->value.sequence->length,
+	    &X509_ALGORS_it);
+}
+LCRYPTO_ALIAS(PKCS7_get_smimecap);
+
+/* Basic smime-capabilities OID and optional integer arg */
+int
+PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
+{
+	X509_ALGOR *alg;
+
+	if (!(alg = X509_ALGOR_new())) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_OBJECT_free(alg->algorithm);
+	alg->algorithm = OBJ_nid2obj(nid);
+	if (arg > 0) {
+		ASN1_INTEGER *nbit;
+
+		if (!(alg->parameter = ASN1_TYPE_new()))
+			goto err;
+		if (!(nbit = ASN1_INTEGER_new()))
+			goto err;
+		if (!ASN1_INTEGER_set(nbit, arg)) {
+			ASN1_INTEGER_free(nbit);
+			goto err;
+		}
+		alg->parameter->value.integer = nbit;
+		alg->parameter->type = V_ASN1_INTEGER;
+	}
+	if (sk_X509_ALGOR_push(sk, alg) == 0)
+		goto err;
+	return 1;
+
+err:
+	PKCS7error(ERR_R_MALLOC_FAILURE);
+	X509_ALGOR_free(alg);
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS7_simple_smimecap);
+
+int
+PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid)
+{
+	if (PKCS7_get_signed_attribute(si, NID_pkcs9_contentType))
+		return 0;
+	if (!coid)
+		coid = OBJ_nid2obj(NID_pkcs7_data);
+	return PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
+	    V_ASN1_OBJECT, coid);
+}
+LCRYPTO_ALIAS(PKCS7_add_attrib_content_type);
+
+int
+PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t)
+{
+	if (!t && !(t = X509_gmtime_adj(NULL, 0))) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime,
+	    V_ASN1_UTCTIME, t);
+}
+LCRYPTO_ALIAS(PKCS7_add0_attrib_signing_time);
+
+int
+PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, const unsigned char *md,
+    int mdlen)
+{
+	ASN1_OCTET_STRING *os;
+
+	os = ASN1_OCTET_STRING_new();
+	if (!os)
+		return 0;
+	if (!ASN1_STRING_set(os, md, mdlen) ||
+	    !PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest,
+	    V_ASN1_OCTET_STRING, os)) {
+		ASN1_OCTET_STRING_free(os);
+		return 0;
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS7_add1_attrib_digest);
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
new file mode 100644
index 0000000..d5edaed
--- /dev/null
+++ b/crypto/pkcs7/pk7_doit.c
@@ -0,0 +1,1264 @@
+/* $OpenBSD: pk7_doit.c,v 1.52 2023/03/09 18:20:10 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "x509_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 int
+PKCS7_type_is_other(PKCS7* p7)
+{
+	int isOther = 1;
+
+	int nid = OBJ_obj2nid(p7->type);
+
+	switch (nid ) {
+	case NID_pkcs7_data:
+	case NID_pkcs7_signed:
+	case NID_pkcs7_enveloped:
+	case NID_pkcs7_signedAndEnveloped:
+	case NID_pkcs7_digest:
+	case NID_pkcs7_encrypted:
+		isOther = 0;
+		break;
+	default:
+		isOther = 1;
+	}
+
+	return isOther;
+
+}
+
+static ASN1_OCTET_STRING *
+PKCS7_get_octet_string(PKCS7 *p7)
+{
+	if (PKCS7_type_is_data(p7))
+		return p7->d.data;
+	if (PKCS7_type_is_other(p7) && p7->d.other &&
+	    (p7->d.other->type == V_ASN1_OCTET_STRING))
+		return p7->d.other->value.octet_string;
+	return NULL;
+}
+
+static int
+PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
+{
+	BIO *btmp;
+	const EVP_MD *md;
+
+	if ((btmp = BIO_new(BIO_f_md())) == NULL) {
+		PKCS7error(ERR_R_BIO_LIB);
+		goto err;
+	}
+
+	md = EVP_get_digestbyobj(alg->algorithm);
+	if (md == NULL) {
+		PKCS7error(PKCS7_R_UNKNOWN_DIGEST_TYPE);
+		goto err;
+	}
+
+	if (BIO_set_md(btmp, md) <= 0) {
+		PKCS7error(ERR_R_BIO_LIB);
+		goto err;
+	}
+
+	if (*pbio == NULL)
+		*pbio = btmp;
+	else if (!BIO_push(*pbio, btmp)) {
+		PKCS7error(ERR_R_BIO_LIB);
+		goto err;
+	}
+	btmp = NULL;
+
+	return 1;
+
+err:
+	BIO_free(btmp);
+	return 0;
+
+}
+
+static int
+pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *key, int keylen)
+{
+	EVP_PKEY_CTX *pctx = NULL;
+	EVP_PKEY *pkey = NULL;
+	unsigned char *ek = NULL;
+	int ret = 0;
+	size_t eklen;
+
+	pkey = X509_get_pubkey(ri->cert);
+	if (!pkey)
+		return 0;
+
+	pctx = EVP_PKEY_CTX_new(pkey, NULL);
+	if (!pctx)
+		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) {
+		PKCS7error(PKCS7_R_CTRL_ERROR);
+		goto err;
+	}
+
+	if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0)
+		goto err;
+
+	ek = malloc(eklen);
+
+	if (ek == NULL) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0)
+		goto err;
+
+	ASN1_STRING_set0(ri->enc_key, ek, eklen);
+	ek = NULL;
+
+	ret = 1;
+
+err:
+	EVP_PKEY_free(pkey);
+	EVP_PKEY_CTX_free(pctx);
+	free(ek);
+	return ret;
+}
+
+
+static int
+pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, PKCS7_RECIP_INFO *ri,
+    EVP_PKEY *pkey, size_t fixlen)
+{
+	EVP_PKEY_CTX *pctx = NULL;
+	unsigned char *ek = NULL;
+	size_t eklen;
+
+	int ret = -1;
+
+	pctx = EVP_PKEY_CTX_new(pkey, NULL);
+	if (!pctx)
+		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) {
+		PKCS7error(PKCS7_R_CTRL_ERROR);
+		goto err;
+	}
+
+	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
+	    ri->enc_key->data, ri->enc_key->length) <= 0)
+		goto err;
+
+	ek = malloc(eklen);
+	if (ek == NULL) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (EVP_PKEY_decrypt(pctx, ek, &eklen, ri->enc_key->data,
+	    ri->enc_key->length) <= 0 || eklen == 0 ||
+	    (fixlen != 0 && eklen != fixlen)) {
+		ret = 0;
+		PKCS7error(ERR_R_EVP_LIB);
+		goto err;
+	}
+
+	ret = 1;
+
+	freezero(*pek, *peklen);
+
+	*pek = ek;
+	*peklen = eklen;
+
+err:
+	EVP_PKEY_CTX_free(pctx);
+	if (!ret && ek)
+		free(ek);
+
+	return ret;
+}
+
+BIO *
+PKCS7_dataInit(PKCS7 *p7, BIO *bio)
+{
+	int i;
+	BIO *out = NULL, *btmp = NULL;
+	X509_ALGOR *xa = NULL;
+	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;
+
+	if (p7 == NULL) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return NULL;
+	}
+
+	/*
+	 * The content field in the PKCS7 ContentInfo is optional,
+	 * but that really only applies to inner content (precisely,
+	 * detached signatures).
+	 *
+	 * When reading content, missing outer content is therefore
+	 * treated as an error.
+	 *
+	 * When creating content, PKCS7_content_new() must be called
+	 * before calling this method, so a NULL p7->d is always
+	 * an error.
+	 */
+	if (p7->d.ptr == NULL) {
+		PKCS7error(PKCS7_R_NO_CONTENT);
+		return NULL;
+	}
+
+	i = OBJ_obj2nid(p7->type);
+	p7->state = PKCS7_S_HEADER;
+
+	switch (i) {
+	case NID_pkcs7_signed:
+		md_sk = p7->d.sign->md_algs;
+		os = PKCS7_get_octet_string(p7->d.sign->contents);
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		rsk = p7->d.signed_and_enveloped->recipientinfo;
+		md_sk = p7->d.signed_and_enveloped->md_algs;
+		xalg = p7->d.signed_and_enveloped->enc_data->algorithm;
+		evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher;
+		if (evp_cipher == NULL) {
+			PKCS7error(PKCS7_R_CIPHER_NOT_INITIALIZED);
+			goto err;
+		}
+		break;
+	case NID_pkcs7_enveloped:
+		rsk = p7->d.enveloped->recipientinfo;
+		xalg = p7->d.enveloped->enc_data->algorithm;
+		evp_cipher = p7->d.enveloped->enc_data->cipher;
+		if (evp_cipher == NULL) {
+			PKCS7error(PKCS7_R_CIPHER_NOT_INITIALIZED);
+			goto err;
+		}
+		break;
+	case NID_pkcs7_digest:
+		xa = p7->d.digest->md;
+		os = PKCS7_get_octet_string(p7->d.digest->contents);
+		break;
+	case NID_pkcs7_data:
+		break;
+	default:
+		PKCS7error(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)))
+			goto err;
+
+	if (xa && !PKCS7_bio_add_digest(&out, xa))
+		goto err;
+
+	if (evp_cipher != NULL) {
+		unsigned char key[EVP_MAX_KEY_LENGTH];
+		unsigned char iv[EVP_MAX_IV_LENGTH];
+		int keylen, ivlen;
+		EVP_CIPHER_CTX *ctx;
+
+		if ((btmp = BIO_new(BIO_f_cipher())) == NULL) {
+			PKCS7error(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));
+		if (ivlen > 0)
+			arc4random_buf(iv, ivlen);
+		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL,
+		    NULL, 1) <= 0)
+			goto err;
+		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
+			goto err;
+		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
+			goto err;
+
+		if (ivlen > 0) {
+			if (xalg->parameter == NULL) {
+				xalg->parameter = ASN1_TYPE_new();
+				if (xalg->parameter == NULL)
+					goto err;
+			}
+			if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
+				goto err;
+		}
+
+		/* Lets do the pub key stuff :-) */
+		for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+			ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
+			if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
+				goto err;
+		}
+		explicit_bzero(key, keylen);
+
+		if (out == NULL)
+			out = btmp;
+		else
+			BIO_push(out, btmp);
+		btmp = NULL;
+	}
+
+	if (bio == NULL) {
+		if (PKCS7_is_detached(p7))
+			bio = BIO_new(BIO_s_null());
+		else if (os && os->length > 0)
+			bio = BIO_new_mem_buf(os->data, os->length);
+		if (bio == NULL) {
+			bio = BIO_new(BIO_s_mem());
+			if (bio == NULL)
+				goto err;
+			BIO_set_mem_eof_return(bio, 0);
+		}
+	}
+	if (out)
+		BIO_push(out, bio);
+	else
+		out = bio;
+	bio = NULL;
+	if (0) {
+err:
+		if (out != NULL)
+			BIO_free_all(out);
+		if (btmp != NULL)
+			BIO_free_all(btmp);
+		out = NULL;
+	}
+	return (out);
+}
+LCRYPTO_ALIAS(PKCS7_dataInit);
+
+static int
+pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
+{
+	int ret;
+
+	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
+	    pcert->cert_info->issuer);
+	if (ret)
+		return ret;
+	return ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
+	    ri->issuer_and_serial->serial);
+}
+
+/* int */
+BIO *
+PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
+{
+	int i, j;
+	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_CIPHER_CTX *evp_ctx = NULL;
+	X509_ALGOR *enc_alg = NULL;
+	STACK_OF(X509_ALGOR) *md_sk = NULL;
+	STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
+	PKCS7_RECIP_INFO *ri = NULL;
+	unsigned char *ek = NULL, *tkey = NULL;
+	int eklen = 0, tkeylen = 0;
+
+	if (p7 == NULL) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return NULL;
+	}
+
+	if (p7->d.ptr == NULL) {
+		PKCS7error(PKCS7_R_NO_CONTENT);
+		return NULL;
+	}
+
+	i = OBJ_obj2nid(p7->type);
+	p7->state = PKCS7_S_HEADER;
+
+	switch (i) {
+	case NID_pkcs7_signed:
+		data_body = PKCS7_get_octet_string(p7->d.sign->contents);
+		md_sk = p7->d.sign->md_algs;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		rsk = p7->d.signed_and_enveloped->recipientinfo;
+		md_sk = p7->d.signed_and_enveloped->md_algs;
+		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) {
+			PKCS7error(PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+			goto err;
+		}
+		break;
+	case NID_pkcs7_enveloped:
+		rsk = p7->d.enveloped->recipientinfo;
+		enc_alg = p7->d.enveloped->enc_data->algorithm;
+		data_body = p7->d.enveloped->enc_data->enc_data;
+		evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
+		if (evp_cipher == NULL) {
+			PKCS7error(PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+			goto err;
+		}
+		break;
+	default:
+		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+		goto err;
+	}
+
+	/* We will be checking the signature */
+	if (md_sk != NULL) {
+		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) {
+				PKCS7error(ERR_R_BIO_LIB);
+				goto err;
+			}
+
+			j = OBJ_obj2nid(xa->algorithm);
+			evp_md = EVP_get_digestbynid(j);
+			if (evp_md == NULL) {
+				PKCS7error(PKCS7_R_UNKNOWN_DIGEST_TYPE);
+				goto err;
+			}
+
+			if (BIO_set_md(btmp, evp_md) <= 0) {
+				PKCS7error(ERR_R_BIO_LIB);
+				goto err;
+			}
+			if (out == NULL)
+				out = btmp;
+			else
+				BIO_push(out, btmp);
+			btmp = NULL;
+		}
+	}
+
+	if (evp_cipher != NULL) {
+		if ((etmp = BIO_new(BIO_f_cipher())) == NULL) {
+			PKCS7error(ERR_R_BIO_LIB);
+			goto err;
+		}
+
+		/* It was encrypted, we need to decrypt the secret key
+		 * with the private key */
+
+		/* Find the recipientInfo which matches the passed certificate
+		 * (if any)
+		 */
+		if (pcert) {
+			for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+				ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
+				if (!pkcs7_cmp_ri(ri, pcert))
+					break;
+				ri = NULL;
+			}
+			if (ri == NULL) {
+				PKCS7error(PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
+				goto err;
+			}
+		}
+
+		/* If we haven't got a certificate try each ri in turn */
+		if (pcert == NULL) {
+			/* Always attempt to decrypt all rinfo even
+			 * after success as a defence against MMA timing
+			 * attacks.
+			 */
+			for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+				ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
+
+				if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
+				    EVP_CIPHER_key_length(evp_cipher)) < 0)
+					goto err;
+				ERR_clear_error();
+			}
+		} else {
+			/* Only exit on fatal errors, not decrypt failure */
+			if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
+				goto err;
+			ERR_clear_error();
+		}
+
+		evp_ctx = NULL;
+		BIO_get_cipher_ctx(etmp, &evp_ctx);
+		if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL,
+		    NULL, 0) <= 0)
+			goto err;
+		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);
+		tkey = malloc(tkeylen);
+		if (!tkey)
+			goto err;
+		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
+			goto err;
+		if (ek == NULL) {
+			ek = tkey;
+			eklen = tkeylen;
+			tkey = NULL;
+		}
+
+		if (eklen != EVP_CIPHER_CTX_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)) {
+				/* Use random key as MMA defence */
+				freezero(ek, eklen);
+				ek = tkey;
+				eklen = tkeylen;
+				tkey = NULL;
+			}
+		}
+		/* Clear errors so we don't leak information useful in MMA */
+		ERR_clear_error();
+		if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0)
+			goto err;
+
+		freezero(ek, eklen);
+		ek = NULL;
+		freezero(tkey, tkeylen);
+		tkey = NULL;
+
+		if (out == NULL)
+			out = etmp;
+		else
+			BIO_push(out, etmp);
+		etmp = NULL;
+	}
+
+	if (PKCS7_is_detached(p7) || (in_bio != NULL)) {
+		bio = in_bio;
+	} else {
+		if (data_body != NULL && data_body->length > 0)
+			bio = BIO_new_mem_buf(data_body->data, data_body->length);
+		else {
+			bio = BIO_new(BIO_s_mem());
+			BIO_set_mem_eof_return(bio, 0);
+		}
+		if (bio == NULL)
+			goto err;
+	}
+	BIO_push(out, bio);
+
+	if (0) {
+err:
+		freezero(ek, eklen);
+		freezero(tkey, tkeylen);
+		if (out != NULL)
+			BIO_free_all(out);
+		if (btmp != NULL)
+			BIO_free_all(btmp);
+		if (etmp != NULL)
+			BIO_free_all(etmp);
+		out = NULL;
+	}
+	return (out);
+}
+LCRYPTO_ALIAS(PKCS7_dataDecode);
+
+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) {
+			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+			return NULL;
+		}
+		BIO_get_md_ctx(bio, pmd);
+		if (*pmd == NULL) {
+			PKCS7error(ERR_R_INTERNAL_ERROR);
+			return NULL;
+		}
+		if (EVP_MD_CTX_type(*pmd) == nid)
+			return bio;
+		bio = BIO_next(bio);
+	}
+	return NULL;
+}
+
+static int
+do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx)
+{
+	unsigned char md_data[EVP_MAX_MD_SIZE];
+	unsigned int md_len;
+
+	/* Add signing time if not already present */
+	if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) {
+		if (!PKCS7_add0_attrib_signing_time(si, NULL)) {
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+
+	/* Add digest */
+	if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) {
+		PKCS7error(ERR_R_EVP_LIB);
+		return 0;
+	}
+	if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	/* Now sign the attributes */
+	if (!PKCS7_SIGNER_INFO_sign(si))
+		return 0;
+
+	return 1;
+}
+
+
+int
+PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
+{
+	int ret = 0;
+	int i, j;
+	BIO *btmp;
+	PKCS7_SIGNER_INFO *si;
+	EVP_MD_CTX *mdc, ctx_tmp;
+	STACK_OF(X509_ATTRIBUTE) *sk;
+	STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
+	ASN1_OCTET_STRING *os = NULL;
+
+	if (p7 == NULL) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return 0;
+	}
+
+	if (p7->d.ptr == NULL) {
+		PKCS7error(PKCS7_R_NO_CONTENT);
+		return 0;
+	}
+
+	EVP_MD_CTX_init(&ctx_tmp);
+	i = OBJ_obj2nid(p7->type);
+	p7->state = PKCS7_S_HEADER;
+
+	switch (i) {
+	case NID_pkcs7_data:
+		os = p7->d.data;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		/* XXX */
+		si_sk = p7->d.signed_and_enveloped->signer_info;
+		os = p7->d.signed_and_enveloped->enc_data->enc_data;
+		if (!os) {
+			os = ASN1_OCTET_STRING_new();
+			if (!os) {
+				PKCS7error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			p7->d.signed_and_enveloped->enc_data->enc_data = os;
+		}
+		break;
+	case NID_pkcs7_enveloped:
+		/* XXX */
+		os = p7->d.enveloped->enc_data->enc_data;
+		if (!os) {
+			os = ASN1_OCTET_STRING_new();
+			if (!os) {
+				PKCS7error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			p7->d.enveloped->enc_data->enc_data = os;
+		}
+		break;
+	case NID_pkcs7_signed:
+		si_sk = p7->d.sign->signer_info;
+		os = PKCS7_get_octet_string(p7->d.sign->contents);
+		if (!PKCS7_is_detached(p7) && os == NULL) {
+			PKCS7error(PKCS7_R_DECODE_ERROR);
+			goto err;
+		}
+		/* If detached data then the content is excluded */
+		if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
+			ASN1_OCTET_STRING_free(os);
+			os = NULL;
+			p7->d.sign->contents->d.data = NULL;
+		}
+		break;
+
+	case NID_pkcs7_digest:
+		os = PKCS7_get_octet_string(p7->d.digest->contents);
+		if (os == NULL) {
+			PKCS7error(PKCS7_R_DECODE_ERROR);
+			goto err;
+		}
+		/* If detached data then the content is excluded */
+		if (PKCS7_type_is_data(p7->d.digest->contents) &&
+		    p7->detached) {
+			ASN1_OCTET_STRING_free(os);
+			os = NULL;
+			p7->d.digest->contents->d.data = NULL;
+		}
+		break;
+
+	default:
+		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+		goto err;
+	}
+
+	if (si_sk != NULL) {
+		for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) {
+			si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
+			if (si->pkey == NULL)
+				continue;
+
+			j = OBJ_obj2nid(si->digest_alg->algorithm);
+
+			if ((btmp = PKCS7_find_digest(&mdc, bio, j)) == NULL)
+				goto err;
+
+			/* We now have the EVP_MD_CTX, lets do the
+			 * signing. */
+			if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc))
+				goto err;
+
+			sk = si->auth_attr;
+
+			/* If there are attributes, we add the digest
+			 * attribute and only sign the attributes */
+			if (sk_X509_ATTRIBUTE_num(sk) > 0) {
+				if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
+					goto err;
+			} else {
+				unsigned char *abuf = NULL;
+				unsigned int abuflen;
+				abuflen = EVP_PKEY_size(si->pkey);
+				abuf = malloc(abuflen);
+				if (!abuf)
+					goto err;
+
+				if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen,
+				    si->pkey)) {
+					PKCS7error(ERR_R_EVP_LIB);
+					goto err;
+				}
+				ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
+			}
+		}
+	} else if (i == NID_pkcs7_digest) {
+		unsigned char md_data[EVP_MAX_MD_SIZE];
+		unsigned int md_len;
+
+		if (!PKCS7_find_digest(&mdc, bio,
+		    OBJ_obj2nid(p7->d.digest->md->algorithm)))
+			goto err;
+		if (!EVP_DigestFinal_ex(mdc, md_data, &md_len))
+			goto err;
+		if (ASN1_STRING_set(p7->d.digest->digest, md_data,
+		    md_len) == 0)
+			goto err;
+	}
+
+	if (!PKCS7_is_detached(p7)) {
+		/*
+		 * NOTE: only reach os == NULL here because detached
+		 * digested data support is broken?
+		 */
+		if (os == NULL)
+			goto err;
+		if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
+			char *cont;
+			long contlen;
+
+			btmp = BIO_find_type(bio, BIO_TYPE_MEM);
+			if (btmp == NULL) {
+				PKCS7error(PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
+				goto err;
+			}
+			contlen = BIO_get_mem_data(btmp, &cont);
+			/*
+			 * Mark the BIO read only then we can use its copy
+			 * of the data instead of making an extra copy.
+			 */
+			BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
+			BIO_set_mem_eof_return(btmp, 0);
+			ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
+		}
+	}
+	ret = 1;
+err:
+	EVP_MD_CTX_cleanup(&ctx_tmp);
+	return (ret);
+}
+LCRYPTO_ALIAS(PKCS7_dataFinal);
+
+int
+PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
+{
+	EVP_MD_CTX mctx;
+	EVP_PKEY_CTX *pctx;
+	unsigned char *abuf = NULL;
+	int alen;
+	size_t siglen;
+	const EVP_MD *md = NULL;
+
+	md = EVP_get_digestbyobj(si->digest_alg->algorithm);
+	if (md == NULL)
+		return 0;
+
+	EVP_MD_CTX_init(&mctx);
+	if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0)
+		goto err;
+
+	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN,
+	    EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) {
+		PKCS7error(PKCS7_R_CTRL_ERROR);
+		goto err;
+	}
+
+	alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf,
+	    &PKCS7_ATTR_SIGN_it);
+	if (!abuf)
+		goto err;
+	if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0)
+		goto err;
+	free(abuf);
+	abuf = NULL;
+	if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0)
+		goto err;
+	abuf = malloc(siglen);
+	if (!abuf)
+		goto err;
+	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) {
+		PKCS7error(PKCS7_R_CTRL_ERROR);
+		goto err;
+	}
+
+	EVP_MD_CTX_cleanup(&mctx);
+
+	ASN1_STRING_set0(si->enc_digest, abuf, siglen);
+
+	return 1;
+
+err:
+	free(abuf);
+	EVP_MD_CTX_cleanup(&mctx);
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_sign);
+
+int
+PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
+    PKCS7 *p7, PKCS7_SIGNER_INFO *si)
+{
+	PKCS7_ISSUER_AND_SERIAL *ias;
+	int ret = 0, i;
+	STACK_OF(X509) *cert;
+	X509 *x509;
+
+	if (p7 == NULL) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return 0;
+	}
+
+	if (p7->d.ptr == NULL) {
+		PKCS7error(PKCS7_R_NO_CONTENT);
+		return 0;
+	}
+
+	if (PKCS7_type_is_signed(p7)) {
+		cert = p7->d.sign->cert;
+	} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
+		cert = p7->d.signed_and_enveloped->cert;
+	} else {
+		PKCS7error(PKCS7_R_WRONG_PKCS7_TYPE);
+		goto err;
+	}
+	/* XXXX */
+	ias = si->issuer_and_serial;
+
+	x509 = X509_find_by_issuer_and_serial(cert, ias->issuer, ias->serial);
+
+	/* were we able to find the cert in passed to us */
+	if (x509 == NULL) {
+		PKCS7error(PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
+		goto err;
+	}
+
+	/* Lets verify */
+	if (!X509_STORE_CTX_init(ctx, cert_store, x509, cert)) {
+		PKCS7error(ERR_R_X509_LIB);
+		goto err;
+	}
+	if (X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN) == 0) {
+		X509_STORE_CTX_cleanup(ctx);
+		goto err;
+	}
+	i = X509_verify_cert(ctx);
+	if (i <= 0) {
+		PKCS7error(ERR_R_X509_LIB);
+		X509_STORE_CTX_cleanup(ctx);
+		goto err;
+	}
+	X509_STORE_CTX_cleanup(ctx);
+
+	return PKCS7_signatureVerify(bio, p7, si, x509);
+err:
+	
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS7_dataVerify);
+
+int
+PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509)
+{
+	ASN1_OCTET_STRING *os;
+	EVP_MD_CTX mdc_tmp, *mdc;
+	int ret = 0, i;
+	int md_type;
+	STACK_OF(X509_ATTRIBUTE) *sk;
+	BIO *btmp;
+	EVP_PKEY *pkey;
+
+	EVP_MD_CTX_init(&mdc_tmp);
+
+	if (!PKCS7_type_is_signed(p7) &&
+	    !PKCS7_type_is_signedAndEnveloped(p7)) {
+		PKCS7error(PKCS7_R_WRONG_PKCS7_TYPE);
+		goto err;
+	}
+
+	md_type = OBJ_obj2nid(si->digest_alg->algorithm);
+
+	btmp = bio;
+	for (;;) {
+		if ((btmp == NULL) ||
+		    ((btmp = BIO_find_type(btmp, BIO_TYPE_MD)) == NULL)) {
+			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+			goto err;
+		}
+		BIO_get_md_ctx(btmp, &mdc);
+		if (mdc == NULL) {
+			PKCS7error(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+		if (EVP_MD_CTX_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)
+			break;
+		btmp = BIO_next(btmp);
+	}
+
+	/* mdc is the digest ctx that we want, unless there are attributes,
+	 * in which case the digest is the signed attributes */
+	if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc))
+		goto err;
+
+	sk = si->auth_attr;
+	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) {
+		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
+		unsigned int md_len;
+		int alen;
+		ASN1_OCTET_STRING *message_digest;
+
+		if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len))
+			goto err;
+		message_digest = PKCS7_digest_from_attributes(sk);
+		if (!message_digest) {
+			PKCS7error(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
+			goto err;
+		}
+		if ((message_digest->length != (int)md_len) ||
+		    (memcmp(message_digest->data, md_dat, md_len))) {
+			PKCS7error(PKCS7_R_DIGEST_FAILURE);
+			ret = -1;
+			goto err;
+		}
+
+		if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type),
+		    NULL))
+			goto err;
+
+		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
+		    &PKCS7_ATTR_VERIFY_it);
+		if (alen <= 0) {
+			PKCS7error(ERR_R_ASN1_LIB);
+			ret = -1;
+			goto err;
+		}
+		if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen))
+			goto err;
+
+		free(abuf);
+	}
+
+	os = si->enc_digest;
+	pkey = X509_get_pubkey(x509);
+	if (!pkey) {
+		ret = -1;
+		goto err;
+	}
+
+	i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey);
+	EVP_PKEY_free(pkey);
+	if (i <= 0) {
+		PKCS7error(PKCS7_R_SIGNATURE_FAILURE);
+		ret = -1;
+		goto err;
+	} else
+		ret = 1;
+err:
+	EVP_MD_CTX_cleanup(&mdc_tmp);
+	return (ret);
+}
+LCRYPTO_ALIAS(PKCS7_signatureVerify);
+
+PKCS7_ISSUER_AND_SERIAL *
+PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
+{
+	STACK_OF(PKCS7_RECIP_INFO) *rsk;
+	PKCS7_RECIP_INFO *ri;
+	int i;
+
+	i = OBJ_obj2nid(p7->type);
+	if (i != NID_pkcs7_signedAndEnveloped)
+		return NULL;
+	if (p7->d.signed_and_enveloped == NULL)
+		return NULL;
+	rsk = p7->d.signed_and_enveloped->recipientinfo;
+	if (rsk == NULL)
+		return NULL;
+	ri = sk_PKCS7_RECIP_INFO_value(rsk, 0);
+	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx)
+		return (NULL);
+	ri = sk_PKCS7_RECIP_INFO_value(rsk, idx);
+	return (ri->issuer_and_serial);
+}
+LCRYPTO_ALIAS(PKCS7_get_issuer_and_serial);
+
+ASN1_TYPE *
+PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
+{
+	return (get_attribute(si->auth_attr, nid));
+}
+LCRYPTO_ALIAS(PKCS7_get_signed_attribute);
+
+ASN1_TYPE *
+PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
+{
+	return (get_attribute(si->unauth_attr, nid));
+}
+LCRYPTO_ALIAS(PKCS7_get_attribute);
+
+static ASN1_TYPE *
+get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
+{
+	int i;
+	X509_ATTRIBUTE *xa;
+	ASN1_OBJECT *o;
+
+	o = OBJ_nid2obj(nid);
+	if (!o || !sk)
+		return (NULL);
+	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
+		xa = sk_X509_ATTRIBUTE_value(sk, i);
+		if (OBJ_cmp(xa->object, o) == 0)
+			return (sk_ASN1_TYPE_value(xa->set, 0));
+	}
+	return (NULL);
+}
+
+ASN1_OCTET_STRING *
+PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
+{
+	ASN1_TYPE *astype;
+
+	if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest)))
+		return NULL;
+	if (astype->type != V_ASN1_OCTET_STRING)
+		return NULL;
+	return astype->value.octet_string;
+}
+LCRYPTO_ALIAS(PKCS7_digest_from_attributes);
+
+int
+PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
+    STACK_OF(X509_ATTRIBUTE) *sk)
+{
+	int i;
+
+	if (p7si->auth_attr != NULL)
+		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,
+		    X509_ATTRIBUTE_free);
+	p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk);
+	if (p7si->auth_attr == NULL)
+		return 0;
+	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
+		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr, i,
+		    X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk, i))))
+		    == NULL)
+			return (0);
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_set_signed_attributes);
+
+int
+PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
+{
+	int i;
+
+	if (p7si->unauth_attr != NULL)
+		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
+		    X509_ATTRIBUTE_free);
+	p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk);
+	if (p7si->unauth_attr == NULL)
+		return 0;
+	for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) {
+		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr, i,
+		    X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk, i))))
+		    == NULL)
+			return (0);
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_set_attributes);
+
+int
+PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
+    void *value)
+{
+	return (add_attribute(&(p7si->auth_attr), nid, atrtype, value));
+}
+LCRYPTO_ALIAS(PKCS7_add_signed_attribute);
+
+int
+PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, void *value)
+{
+	return (add_attribute(&(p7si->unauth_attr), nid, atrtype, value));
+}
+LCRYPTO_ALIAS(PKCS7_add_attribute);
+
+static int
+add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, void *value)
+{
+	X509_ATTRIBUTE *attr = NULL;
+
+	if (*sk == NULL) {
+		*sk = sk_X509_ATTRIBUTE_new_null();
+		if (*sk == NULL)
+			return 0;
+new_attrib:
+		if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value)))
+			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(attr->object) == 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;
+	}
+end:
+	return (1);
+}
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
new file mode 100644
index 0000000..6eda698
--- /dev/null
+++ b/crypto/pkcs7/pk7_lib.c
@@ -0,0 +1,674 @@
+/* $OpenBSD: pk7_lib.c,v 1.26 2023/02/16 08:38:17 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "evp_local.h"
+#include "x509_local.h"
+
+long
+PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg)
+{
+	int nid;
+	long ret;
+
+	nid = OBJ_obj2nid(p7->type);
+
+	switch (cmd) {
+	case PKCS7_OP_SET_DETACHED_SIGNATURE:
+		if (nid == NID_pkcs7_signed) {
+			ret = p7->detached = (int)larg;
+			if (ret && PKCS7_type_is_data(p7->d.sign->contents)) {
+				ASN1_OCTET_STRING *os;
+				os = p7->d.sign->contents->d.data;
+				ASN1_OCTET_STRING_free(os);
+				p7->d.sign->contents->d.data = NULL;
+			}
+		} else {
+			PKCS7error(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)
+				ret = 1;
+			else
+				ret = 0;
+
+			p7->detached = ret;
+		} else {
+			PKCS7error(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE);
+			ret = 0;
+		}
+
+		break;
+	default:
+		PKCS7error(PKCS7_R_UNKNOWN_OPERATION);
+		ret = 0;
+	}
+	return (ret);
+}
+LCRYPTO_ALIAS(PKCS7_ctrl);
+
+int
+PKCS7_content_new(PKCS7 *p7, int type)
+{
+	PKCS7 *ret = NULL;
+
+	if ((ret = PKCS7_new()) == NULL)
+		goto err;
+	if (!PKCS7_set_type(ret, type))
+		goto err;
+	if (!PKCS7_set_content(p7, ret))
+		goto err;
+
+	return (1);
+err:
+	if (ret != NULL)
+		PKCS7_free(ret);
+	return (0);
+}
+LCRYPTO_ALIAS(PKCS7_content_new);
+
+int
+PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data)
+{
+	int i;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signed:
+		if (p7->d.sign->contents != NULL)
+			PKCS7_free(p7->d.sign->contents);
+		p7->d.sign->contents = p7_data;
+		break;
+	case NID_pkcs7_digest:
+		if (p7->d.digest->contents != NULL)
+			PKCS7_free(p7->d.digest->contents);
+		p7->d.digest->contents = p7_data;
+		break;
+	case NID_pkcs7_data:
+	case NID_pkcs7_enveloped:
+	case NID_pkcs7_signedAndEnveloped:
+	case NID_pkcs7_encrypted:
+	default:
+		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+		goto err;
+	}
+	return (1);
+err:
+	return (0);
+}
+LCRYPTO_ALIAS(PKCS7_set_content);
+
+int
+PKCS7_set_type(PKCS7 *p7, int type)
+{
+	ASN1_OBJECT *obj;
+
+	/*PKCS7_content_free(p7);*/
+	obj=OBJ_nid2obj(type); /* will not fail */
+
+	switch (type) {
+	case NID_pkcs7_signed:
+		p7->type = obj;
+		if ((p7->d.sign = PKCS7_SIGNED_new()) == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(p7->d.sign->version, 1)) {
+			PKCS7_SIGNED_free(p7->d.sign);
+			p7->d.sign = NULL;
+			goto err;
+		}
+		break;
+	case NID_pkcs7_data:
+		p7->type = obj;
+		if ((p7->d.data = ASN1_OCTET_STRING_new()) == NULL)
+			goto err;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		p7->type = obj;
+		if ((p7->d.signed_and_enveloped =
+		    PKCS7_SIGN_ENVELOPE_new()) == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(p7->d.signed_and_enveloped->version, 1))
+			goto err;
+		p7->d.signed_and_enveloped->enc_data->content_type =
+		    OBJ_nid2obj(NID_pkcs7_data);
+		break;
+	case NID_pkcs7_enveloped:
+		p7->type = obj;
+		if ((p7->d.enveloped = PKCS7_ENVELOPE_new()) == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(p7->d.enveloped->version, 0))
+			goto err;
+		p7->d.enveloped->enc_data->content_type =
+		    OBJ_nid2obj(NID_pkcs7_data);
+		break;
+	case NID_pkcs7_encrypted:
+		p7->type = obj;
+		if ((p7->d.encrypted = PKCS7_ENCRYPT_new()) == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(p7->d.encrypted->version, 0))
+			goto err;
+		p7->d.encrypted->enc_data->content_type =
+		    OBJ_nid2obj(NID_pkcs7_data);
+		break;
+
+	case NID_pkcs7_digest:
+		p7->type = obj;
+		if ((p7->d.digest = PKCS7_DIGEST_new()) == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(p7->d.digest->version, 0))
+			goto err;
+		break;
+	default:
+		PKCS7error(PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
+		goto err;
+	}
+	return (1);
+err:
+	return (0);
+}
+LCRYPTO_ALIAS(PKCS7_set_type);
+
+int
+PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other)
+{
+	p7->type = OBJ_nid2obj(type);
+	p7->d.other = other;
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS7_set0_type_other);
+
+int
+PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi)
+{
+	int i, j, nid;
+	X509_ALGOR *alg;
+	STACK_OF(PKCS7_SIGNER_INFO) *signer_sk;
+	STACK_OF(X509_ALGOR) *md_sk;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signed:
+		signer_sk = p7->d.sign->signer_info;
+		md_sk = p7->d.sign->md_algs;
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		signer_sk = p7->d.signed_and_enveloped->signer_info;
+		md_sk = p7->d.signed_and_enveloped->md_algs;
+		break;
+	default:
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return (0);
+	}
+
+	nid = OBJ_obj2nid(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) {
+			j = 1;
+			break;
+		}
+	}
+	if (!j) /* we need to add another algorithm */
+	{
+		if (!(alg = X509_ALGOR_new()) ||
+		    !(alg->parameter = ASN1_TYPE_new())) {
+			X509_ALGOR_free(alg);
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			return (0);
+		}
+		alg->algorithm = OBJ_nid2obj(nid);
+		alg->parameter->type = V_ASN1_NULL;
+		if (!sk_X509_ALGOR_push(md_sk, alg)) {
+			X509_ALGOR_free(alg);
+			return 0;
+		}
+	}
+
+	if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi))
+		return 0;
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_add_signer);
+
+int
+PKCS7_add_certificate(PKCS7 *p7, X509 *x509)
+{
+	int i;
+	STACK_OF(X509) **sk;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signed:
+		sk = &(p7->d.sign->cert);
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		sk = &(p7->d.signed_and_enveloped->cert);
+		break;
+	default:
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return (0);
+	}
+
+	if (*sk == NULL)
+		*sk = sk_X509_new_null();
+	if (*sk == NULL) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
+	if (!sk_X509_push(*sk, x509)) {
+		X509_free(x509);
+		return 0;
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_add_certificate);
+
+int
+PKCS7_add_crl(PKCS7 *p7, X509_CRL *crl)
+{
+	int i;
+	STACK_OF(X509_CRL) **sk;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signed:
+		sk = &(p7->d.sign->crl);
+		break;
+	case NID_pkcs7_signedAndEnveloped:
+		sk = &(p7->d.signed_and_enveloped->crl);
+		break;
+	default:
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return (0);
+	}
+
+	if (*sk == NULL)
+		*sk = sk_X509_CRL_new_null();
+	if (*sk == NULL) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL);
+	if (!sk_X509_CRL_push(*sk, crl)) {
+		X509_CRL_free(crl);
+		return 0;
+	}
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_add_crl);
+
+int
+PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey,
+    const EVP_MD *dgst)
+{
+	int ret;
+
+	/* We now need to add another PKCS7_SIGNER_INFO entry */
+	if (!ASN1_INTEGER_set(p7i->version, 1))
+		goto err;
+	if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
+	    X509_get_issuer_name(x509)))
+		goto err;
+
+	/* because ASN1_INTEGER_set is used to set a 'long' we will do
+	 * things the ugly way. */
+	ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
+	if (!(p7i->issuer_and_serial->serial =
+	    ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+		goto err;
+
+	/* lets keep the pkey around for a while */
+	CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
+	p7i->pkey = pkey;
+
+	/* Set the algorithms */
+
+	X509_ALGOR_set0(p7i->digest_alg, OBJ_nid2obj(EVP_MD_type(dgst)),
+	    V_ASN1_NULL, NULL);
+
+	if (pkey->ameth && pkey->ameth->pkey_ctrl) {
+		ret = pkey->ameth->pkey_ctrl(pkey, ASN1_PKEY_CTRL_PKCS7_SIGN,
+		    0, p7i);
+		if (ret > 0)
+			return 1;
+		if (ret != -2) {
+			PKCS7error(PKCS7_R_SIGNING_CTRL_FAILURE);
+			return 0;
+		}
+	}
+	PKCS7error(PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+err:
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_set);
+
+PKCS7_SIGNER_INFO *
+PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, const EVP_MD *dgst)
+{
+	PKCS7_SIGNER_INFO *si = NULL;
+
+	if (dgst == NULL) {
+		int def_nid;
+		if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0)
+			goto err;
+		dgst = EVP_get_digestbynid(def_nid);
+		if (dgst == NULL) {
+			PKCS7error(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))
+		goto err;
+	if (!PKCS7_add_signer(p7, si))
+		goto err;
+	return (si);
+err:
+	if (si)
+		PKCS7_SIGNER_INFO_free(si);
+	return (NULL);
+}
+LCRYPTO_ALIAS(PKCS7_add_signature);
+
+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())) {
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+		p7->d.digest->md->parameter->type = V_ASN1_NULL;
+		p7->d.digest->md->algorithm = OBJ_nid2obj(EVP_MD_nid(md));
+		return 1;
+	}
+
+	PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS7_set_digest);
+
+STACK_OF(PKCS7_SIGNER_INFO) *
+PKCS7_get_signer_info(PKCS7 *p7)
+{
+	if (p7 == NULL || p7->d.ptr == NULL)
+		return (NULL);
+	if (PKCS7_type_is_signed(p7)) {
+		return (p7->d.sign->signer_info);
+	} else if (PKCS7_type_is_signedAndEnveloped(p7)) {
+		return (p7->d.signed_and_enveloped->signer_info);
+	} else
+		return (NULL);
+}
+LCRYPTO_ALIAS(PKCS7_get_signer_info);
+
+void
+PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk,
+    X509_ALGOR **pdig, X509_ALGOR **psig)
+{
+	if (pk)
+		*pk = si->pkey;
+	if (pdig)
+		*pdig = si->digest_alg;
+	if (psig)
+		*psig = si->digest_enc_alg;
+}
+LCRYPTO_ALIAS(PKCS7_SIGNER_INFO_get0_algs);
+
+void
+PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc)
+{
+	if (penc)
+		*penc = ri->key_enc_algor;
+}
+LCRYPTO_ALIAS(PKCS7_RECIP_INFO_get0_alg);
+
+PKCS7_RECIP_INFO *
+PKCS7_add_recipient(PKCS7 *p7, X509 *x509)
+{
+	PKCS7_RECIP_INFO *ri;
+
+	if ((ri = PKCS7_RECIP_INFO_new()) == NULL)
+		goto err;
+	if (!PKCS7_RECIP_INFO_set(ri, x509))
+		goto err;
+	if (!PKCS7_add_recipient_info(p7, ri))
+		goto err;
+	return ri;
+err:
+	if (ri)
+		PKCS7_RECIP_INFO_free(ri);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS7_add_recipient);
+
+int
+PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri)
+{
+	int i;
+	STACK_OF(PKCS7_RECIP_INFO) *sk;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signedAndEnveloped:
+		sk = p7->d.signed_and_enveloped->recipientinfo;
+		break;
+	case NID_pkcs7_enveloped:
+		sk = p7->d.enveloped->recipientinfo;
+		break;
+	default:
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return (0);
+	}
+
+	if (!sk_PKCS7_RECIP_INFO_push(sk, ri))
+		return 0;
+	return (1);
+}
+LCRYPTO_ALIAS(PKCS7_add_recipient_info);
+
+int
+PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509)
+{
+	int ret;
+	EVP_PKEY *pkey = NULL;
+	if (!ASN1_INTEGER_set(p7i->version, 0))
+		return 0;
+	if (!X509_NAME_set(&p7i->issuer_and_serial->issuer,
+	    X509_get_issuer_name(x509)))
+		return 0;
+
+	ASN1_INTEGER_free(p7i->issuer_and_serial->serial);
+	if (!(p7i->issuer_and_serial->serial =
+	    ASN1_INTEGER_dup(X509_get_serialNumber(x509))))
+		return 0;
+
+	pkey = X509_get_pubkey(x509);
+
+	if (!pkey || !pkey->ameth || !pkey->ameth->pkey_ctrl) {
+		PKCS7error(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) {
+		PKCS7error(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE);
+		goto err;
+	}
+	if (ret <= 0) {
+		PKCS7error(PKCS7_R_ENCRYPTION_CTRL_FAILURE);
+		goto err;
+	}
+
+	EVP_PKEY_free(pkey);
+
+	CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
+	p7i->cert = x509;
+
+	return 1;
+
+err:
+	EVP_PKEY_free(pkey);
+	return 0;
+}
+LCRYPTO_ALIAS(PKCS7_RECIP_INFO_set);
+
+X509 *
+PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
+{
+	if (PKCS7_type_is_signed(p7))
+		return(X509_find_by_issuer_and_serial(p7->d.sign->cert,
+		    si->issuer_and_serial->issuer,
+		    si->issuer_and_serial->serial));
+	else
+		return (NULL);
+}
+LCRYPTO_ALIAS(PKCS7_cert_from_signer_info);
+
+int
+PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher)
+{
+	int i;
+	PKCS7_ENC_CONTENT *ec;
+
+	i = OBJ_obj2nid(p7->type);
+	switch (i) {
+	case NID_pkcs7_signedAndEnveloped:
+		ec = p7->d.signed_and_enveloped->enc_data;
+		break;
+	case NID_pkcs7_enveloped:
+		ec = p7->d.enveloped->enc_data;
+		break;
+	default:
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return (0);
+	}
+
+	/* Check cipher OID exists and has data in it*/
+	i = EVP_CIPHER_type(cipher);
+	if (i == NID_undef) {
+		PKCS7error(PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+		return (0);
+	}
+
+	ec->cipher = cipher;
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS7_set_cipher);
+
+int
+PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
+{
+	ASN1_OCTET_STRING *os = NULL;
+
+	switch (OBJ_obj2nid(p7->type)) {
+	case NID_pkcs7_data:
+		os = p7->d.data;
+		break;
+
+	case NID_pkcs7_signedAndEnveloped:
+		os = p7->d.signed_and_enveloped->enc_data->enc_data;
+		if (os == NULL) {
+			os = ASN1_OCTET_STRING_new();
+			p7->d.signed_and_enveloped->enc_data->enc_data = os;
+		}
+		break;
+
+	case NID_pkcs7_enveloped:
+		os = p7->d.enveloped->enc_data->enc_data;
+		if (os == NULL) {
+			os = ASN1_OCTET_STRING_new();
+			p7->d.enveloped->enc_data->enc_data = os;
+		}
+		break;
+
+	case NID_pkcs7_signed:
+		os = p7->d.sign->contents->d.data;
+		break;
+
+	default:
+		os = NULL;
+		break;
+	}
+
+	if (os == NULL)
+		return 0;
+
+	os->flags |= ASN1_STRING_FLAG_NDEF;
+	*boundary = &os->data;
+
+	return 1;
+}
+LCRYPTO_ALIAS(PKCS7_stream);
diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c
new file mode 100644
index 0000000..f00e18c
--- /dev/null
+++ b/crypto/pkcs7/pk7_mime.c
@@ -0,0 +1,107 @@
+/* $OpenBSD: pk7_mime.c,v 1.19 2023/05/02 09:56:12 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "asn1_local.h"
+
+/* PKCS#7 wrappers round generalised stream and MIME routines */
+BIO *
+BIO_new_PKCS7(BIO *out, PKCS7 *p7)
+{
+	return BIO_new_NDEF(out, (ASN1_VALUE *)p7, &PKCS7_it);
+}
+LCRYPTO_ALIAS(BIO_new_PKCS7);
+
+int
+i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags)
+{
+	return i2d_ASN1_bio_stream(out, (ASN1_VALUE *)p7, in, flags, &PKCS7_it);
+}
+LCRYPTO_ALIAS(i2d_PKCS7_bio_stream);
+
+int
+PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags)
+{
+	return PEM_write_bio_ASN1_stream(out, (ASN1_VALUE *) p7, in, flags,
+	    "PKCS7", &PKCS7_it);
+}
+LCRYPTO_ALIAS(PEM_write_bio_PKCS7_stream);
+
+int
+SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
+{
+	STACK_OF(X509_ALGOR) *mdalgs = NULL;
+	int ctype_nid;
+
+	if ((ctype_nid = OBJ_obj2nid(p7->type)) == NID_pkcs7_signed)
+		mdalgs = p7->d.sign->md_algs;
+
+	flags ^= SMIME_OLDMIME;
+
+	return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags,
+	    ctype_nid, NID_undef, mdalgs, &PKCS7_it);
+}
+LCRYPTO_ALIAS(SMIME_write_PKCS7);
+
+PKCS7 *
+SMIME_read_PKCS7(BIO *bio, BIO **bcont)
+{
+	return (PKCS7 *)SMIME_read_ASN1(bio, bcont, &PKCS7_it);
+}
+LCRYPTO_ALIAS(SMIME_read_PKCS7);
diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c
new file mode 100644
index 0000000..c113ac3
--- /dev/null
+++ b/crypto/pkcs7/pk7_smime.c
@@ -0,0 +1,599 @@
+/* $OpenBSD: pk7_smime.c,v 1.26 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* Simple PKCS#7 processing functions */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "x509_local.h"
+
+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 *p7;
+	int i;
+
+	if (!(p7 = PKCS7_new())) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (!PKCS7_set_type(p7, NID_pkcs7_signed))
+		goto err;
+
+	if (!PKCS7_content_new(p7, NID_pkcs7_data))
+		goto err;
+
+	if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) {
+		PKCS7error(PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
+		goto err;
+	}
+
+	if (!(flags & PKCS7_NOCERTS)) {
+		for (i = 0; i < sk_X509_num(certs); i++) {
+			if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
+				goto err;
+		}
+	}
+
+	if (flags & PKCS7_DETACHED)
+		PKCS7_set_detached(p7, 1);
+
+	if (flags & (PKCS7_STREAM|PKCS7_PARTIAL))
+		return p7;
+
+	if (PKCS7_final(p7, data, flags))
+		return p7;
+
+err:
+	PKCS7_free(p7);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS7_sign);
+
+int
+PKCS7_final(PKCS7 *p7, BIO *data, int flags)
+{
+	BIO *p7bio;
+	int ret = 0;
+
+	if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+
+	SMIME_crlf_copy(data, p7bio, flags);
+
+	(void)BIO_flush(p7bio);
+
+	if (!PKCS7_dataFinal(p7, p7bio)) {
+		PKCS7error(PKCS7_R_PKCS7_DATASIGN);
+		goto err;
+	}
+
+	ret = 1;
+
+err:
+	BIO_free_all(p7bio);
+
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS7_final);
+
+/* Check to see if a cipher exists and if so add S/MIME capabilities */
+
+static int
+add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
+{
+	if (EVP_get_cipherbynid(nid))
+		return PKCS7_simple_smimecap(sk, nid, arg);
+	return 1;
+}
+
+static int
+add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg)
+{
+	if (EVP_get_digestbynid(nid))
+		return PKCS7_simple_smimecap(sk, nid, arg);
+	return 1;
+}
+
+PKCS7_SIGNER_INFO *
+PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, EVP_PKEY *pkey,
+    const EVP_MD *md, int flags)
+{
+	PKCS7_SIGNER_INFO *si = NULL;
+	STACK_OF(X509_ALGOR) *smcap = NULL;
+
+	if (!X509_check_private_key(signcert, pkey)) {
+		PKCS7error(PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+		return NULL;
+	}
+
+	if (!(si = PKCS7_add_signature(p7, signcert, pkey, md))) {
+		PKCS7error(PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
+		return NULL;
+	}
+
+	if (!(flags & PKCS7_NOCERTS)) {
+		if (!PKCS7_add_certificate(p7, signcert))
+			goto err;
+	}
+
+	if (!(flags & PKCS7_NOATTR)) {
+		if (!PKCS7_add_attrib_content_type(si, NULL))
+			goto err;
+		/* Add SMIMECapabilities */
+		if (!(flags & PKCS7_NOSMIMECAP)) {
+			if (!(smcap = sk_X509_ALGOR_new_null())) {
+				PKCS7error(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+			if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1) ||
+			    !add_digest_smcap(smcap, NID_id_GostR3411_94, -1) ||
+			    !add_digest_smcap(smcap, NID_id_tc26_gost3411_2012_256, -1) ||
+			    !add_digest_smcap(smcap, NID_id_tc26_gost3411_2012_512, -1) ||
+			    !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1) ||
+			    !add_cipher_smcap(smcap, NID_aes_192_cbc, -1) ||
+			    !add_cipher_smcap(smcap, NID_aes_128_cbc, -1) ||
+			    !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1) ||
+			    !add_cipher_smcap(smcap, NID_rc2_cbc, 128) ||
+			    !add_cipher_smcap(smcap, NID_rc2_cbc, 64) ||
+			    !add_cipher_smcap(smcap, NID_des_cbc, -1) ||
+			    !add_cipher_smcap(smcap, NID_rc2_cbc, 40) ||
+			    !PKCS7_add_attrib_smimecap(si, smcap))
+				goto err;
+			sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+			smcap = NULL;
+		}
+		if (flags & PKCS7_REUSE_DIGEST) {
+			if (!pkcs7_copy_existing_digest(p7, si))
+				goto err;
+			if (!(flags & PKCS7_PARTIAL) &&
+			    !PKCS7_SIGNER_INFO_sign(si))
+				goto err;
+		}
+	}
+	return si;
+
+err:
+	if (smcap)
+		sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS7_sign_add_signer);
+
+/* Search for a digest matching SignerInfo digest type and if found
+ * copy across.
+ */
+
+static int
+pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
+{
+	int i;
+	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+	PKCS7_SIGNER_INFO *sitmp;
+	ASN1_OCTET_STRING *osdig = NULL;
+
+	sinfos = PKCS7_get_signer_info(p7);
+	for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+		sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+		if (si == sitmp)
+			break;
+		if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0)
+			continue;
+		if (!OBJ_cmp(si->digest_alg->algorithm,
+		    sitmp->digest_alg->algorithm)) {
+			osdig = PKCS7_digest_from_attributes(sitmp->auth_attr);
+			break;
+		}
+
+	}
+
+	if (osdig)
+		return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length);
+
+	PKCS7error(PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND);
+	return 0;
+}
+
+int
+PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata,
+    BIO *out, int flags)
+{
+	STACK_OF(X509) *signers;
+	X509 *signer;
+	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+	PKCS7_SIGNER_INFO *si;
+	X509_STORE_CTX cert_ctx;
+	char buf[4096];
+	int i, j = 0, k, ret = 0;
+	BIO *p7bio;
+	BIO *tmpin, *tmpout;
+
+	if (!p7) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return 0;
+	}
+
+	if (!PKCS7_type_is_signed(p7)) {
+		PKCS7error(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) {
+		PKCS7error(PKCS7_R_NO_CONTENT);
+		return 0;
+	}
+
+	/*
+	 * Very old Netscape illegally included empty content with
+	 * a detached signature.  Very old users should upgrade.
+	 */
+	/* Check for data and content: two sets of data */
+	if (!PKCS7_get_detached(p7) && indata) {
+		PKCS7error(PKCS7_R_CONTENT_AND_DATA_PRESENT);
+		return 0;
+	}
+
+	sinfos = PKCS7_get_signer_info(p7);
+
+	if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
+		PKCS7error(PKCS7_R_NO_SIGNATURES_ON_DATA);
+		return 0;
+	}
+
+
+	signers = PKCS7_get0_signers(p7, certs, flags);
+
+	if (!signers)
+		return 0;
+
+	/* Now verify the certificates */
+
+	if (!(flags & PKCS7_NOVERIFY))
+		for (k = 0; k < sk_X509_num(signers); k++) {
+			signer = sk_X509_value (signers, k);
+			if  (!(flags & PKCS7_NOCHAIN)) {
+				if (!X509_STORE_CTX_init(&cert_ctx, store,
+				    signer, p7->d.sign->cert)) {
+					PKCS7error(ERR_R_X509_LIB);
+					sk_X509_free(signers);
+					return 0;
+				}
+				if (X509_STORE_CTX_set_default(&cert_ctx,
+				    "smime_sign") == 0) {
+					sk_X509_free(signers);
+					return 0;
+				}
+			} else if (!X509_STORE_CTX_init(&cert_ctx, store,
+			    signer, NULL)) {
+				PKCS7error(ERR_R_X509_LIB);
+				sk_X509_free(signers);
+				return 0;
+			}
+			if (!(flags & PKCS7_NOCRL))
+				X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
+			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) {
+				PKCS7error(PKCS7_R_CERTIFICATE_VERIFY_ERROR);
+				ERR_asprintf_error_data("Verify error:%s",
+				    X509_verify_cert_error_string(j));
+				sk_X509_free(signers);
+				return 0;
+			}
+			/* Check for revocation status here */
+		}
+
+	/*
+	 * Performance optimization: if the content is a memory BIO then
+	 * store its contents in a temporary read only memory BIO. This
+	 * avoids potentially large numbers of slow copies of data which will
+	 * occur when reading from a read write memory BIO when signatures
+	 * are calculated.
+	 */
+	if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM)) {
+		char *ptr;
+		long len;
+
+		len = BIO_get_mem_data(indata, &ptr);
+		tmpin = BIO_new_mem_buf(ptr, len);
+		if (tmpin == NULL) {
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	} else
+		tmpin = indata;
+
+
+	if (!(p7bio = PKCS7_dataInit(p7, tmpin)))
+		goto err;
+
+	if (flags & PKCS7_TEXT) {
+		if (!(tmpout = BIO_new(BIO_s_mem()))) {
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		BIO_set_mem_eof_return(tmpout, 0);
+	} else
+		tmpout = out;
+
+	/* We now have to 'read' from p7bio to calculate digests etc. */
+	for (;;) {
+		i = BIO_read(p7bio, buf, sizeof(buf));
+		if (i <= 0)
+			break;
+		if (tmpout)
+			BIO_write(tmpout, buf, i);
+	}
+
+	if (flags & PKCS7_TEXT) {
+		if (!SMIME_text(tmpout, out)) {
+			PKCS7error(PKCS7_R_SMIME_TEXT_ERROR);
+			BIO_free(tmpout);
+			goto err;
+		}
+		BIO_free(tmpout);
+	}
+
+	/* Now Verify All Signatures */
+	if (!(flags & PKCS7_NOSIGS))
+		for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+			si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+			signer = sk_X509_value (signers, i);
+			j = PKCS7_signatureVerify(p7bio, p7, si, signer);
+			if (j <= 0) {
+				PKCS7error(PKCS7_R_SIGNATURE_FAILURE);
+				goto err;
+			}
+		}
+
+	ret = 1;
+
+err:
+	if (tmpin == indata) {
+		if (indata)
+			BIO_pop(p7bio);
+	}
+	BIO_free_all(p7bio);
+	sk_X509_free(signers);
+
+	return ret;
+}
+LCRYPTO_ALIAS(PKCS7_verify);
+
+STACK_OF(X509) *
+PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
+{
+	STACK_OF(X509) *signers;
+	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+	PKCS7_SIGNER_INFO *si;
+	PKCS7_ISSUER_AND_SERIAL *ias;
+	X509 *signer;
+	int i;
+
+	if (!p7) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return NULL;
+	}
+
+	if (!PKCS7_type_is_signed(p7)) {
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return NULL;
+	}
+
+	/* Collect all the signers together */
+	sinfos = PKCS7_get_signer_info(p7);
+	if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
+		PKCS7error(PKCS7_R_NO_SIGNERS);
+		return 0;
+	}
+
+	if (!(signers = sk_X509_new_null())) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
+		si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+		ias = si->issuer_and_serial;
+		signer = NULL;
+		/* If any certificates passed they take priority */
+		if (certs)
+			signer = X509_find_by_issuer_and_serial (certs,
+			    ias->issuer, ias->serial);
+		if (!signer && !(flags & PKCS7_NOINTERN) && p7->d.sign->cert)
+			signer =
+			    X509_find_by_issuer_and_serial(p7->d.sign->cert,
+			      ias->issuer, ias->serial);
+		if (!signer) {
+			PKCS7error(PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
+			sk_X509_free(signers);
+			return 0;
+		}
+
+		if (!sk_X509_push(signers, signer)) {
+			sk_X509_free(signers);
+			return NULL;
+		}
+	}
+	return signers;
+}
+LCRYPTO_ALIAS(PKCS7_get0_signers);
+
+/* Build a complete PKCS#7 enveloped data */
+
+PKCS7 *
+PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
+    int flags)
+{
+	PKCS7 *p7;
+	BIO *p7bio = NULL;
+	int i;
+	X509 *x509;
+
+	if (!(p7 = PKCS7_new())) {
+		PKCS7error(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
+		goto err;
+	if (!PKCS7_set_cipher(p7, cipher)) {
+		PKCS7error(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)) {
+			PKCS7error(PKCS7_R_ERROR_ADDING_RECIPIENT);
+			goto err;
+		}
+	}
+
+	if (flags & PKCS7_STREAM)
+		return p7;
+
+	if (PKCS7_final(p7, in, flags))
+		return p7;
+
+err:
+	BIO_free_all(p7bio);
+	PKCS7_free(p7);
+	return NULL;
+}
+LCRYPTO_ALIAS(PKCS7_encrypt);
+
+int
+PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
+{
+	BIO *tmpmem;
+	int ret, i;
+	char buf[4096];
+
+	if (!p7) {
+		PKCS7error(PKCS7_R_INVALID_NULL_POINTER);
+		return 0;
+	}
+
+	if (!PKCS7_type_is_enveloped(p7)) {
+		PKCS7error(PKCS7_R_WRONG_CONTENT_TYPE);
+		return 0;
+	}
+
+	if (cert && !X509_check_private_key(cert, pkey)) {
+		PKCS7error(PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+		return 0;
+	}
+
+	if (!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) {
+		PKCS7error(PKCS7_R_DECRYPT_ERROR);
+		return 0;
+	}
+
+	if (flags & PKCS7_TEXT) {
+		BIO *tmpbuf;
+
+		/* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
+		if (!(tmpbuf = BIO_new(BIO_f_buffer()))) {
+			PKCS7error(ERR_R_MALLOC_FAILURE);
+			BIO_free_all(tmpmem);
+			return 0;
+		}
+		BIO_push(tmpbuf, tmpmem);
+		ret = SMIME_text(tmpbuf, data);
+		if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
+			if (!BIO_get_cipher_status(tmpmem))
+				ret = 0;
+		}
+		BIO_free_all(tmpbuf);
+		return ret;
+	} else {
+		for (;;) {
+			i = BIO_read(tmpmem, buf, sizeof(buf));
+			if (i <= 0) {
+				ret = 1;
+				if (BIO_method_type(tmpmem) ==
+				    BIO_TYPE_CIPHER) {
+					if (!BIO_get_cipher_status(tmpmem))
+						ret = 0;
+				}
+				break;
+			}
+			if (BIO_write(data, buf, i) != i) {
+				ret = 0;
+				break;
+			}
+		}
+		BIO_free_all(tmpmem);
+		return ret;
+	}
+}
+LCRYPTO_ALIAS(PKCS7_decrypt);
diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c
new file mode 100644
index 0000000..d3ca0ec
--- /dev/null
+++ b/crypto/pkcs7/pkcs7err.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: pkcs7err.c,v 1.15 2023/02/16 08:38:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_PKCS7,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_PKCS7,0,reason)
+
+static ERR_STRING_DATA PKCS7_str_functs[]= {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA PKCS7_str_reasons[]= {
+	{ERR_REASON(PKCS7_R_CERTIFICATE_VERIFY_ERROR), "certificate verify error"},
+	{ERR_REASON(PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), "cipher has no object identifier"},
+	{ERR_REASON(PKCS7_R_CIPHER_NOT_INITIALIZED), "cipher not initialized"},
+	{ERR_REASON(PKCS7_R_CONTENT_AND_DATA_PRESENT), "content and data present"},
+	{ERR_REASON(PKCS7_R_CTRL_ERROR)          , "ctrl error"},
+	{ERR_REASON(PKCS7_R_DECODE_ERROR)        , "decode error"},
+	{ERR_REASON(PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH), "decrypted key is wrong length"},
+	{ERR_REASON(PKCS7_R_DECRYPT_ERROR)       , "decrypt error"},
+	{ERR_REASON(PKCS7_R_DIGEST_FAILURE)      , "digest failure"},
+	{ERR_REASON(PKCS7_R_ENCRYPTION_CTRL_FAILURE), "encryption ctrl failure"},
+	{ERR_REASON(PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE), "encryption not supported for this key type"},
+	{ERR_REASON(PKCS7_R_ERROR_ADDING_RECIPIENT), "error adding recipient"},
+	{ERR_REASON(PKCS7_R_ERROR_SETTING_CIPHER), "error setting cipher"},
+	{ERR_REASON(PKCS7_R_INVALID_MIME_TYPE)   , "invalid mime type"},
+	{ERR_REASON(PKCS7_R_INVALID_NULL_POINTER), "invalid null pointer"},
+	{ERR_REASON(PKCS7_R_MIME_NO_CONTENT_TYPE), "mime no content type"},
+	{ERR_REASON(PKCS7_R_MIME_PARSE_ERROR)    , "mime parse error"},
+	{ERR_REASON(PKCS7_R_MIME_SIG_PARSE_ERROR), "mime sig parse error"},
+	{ERR_REASON(PKCS7_R_MISSING_CERIPEND_INFO), "missing ceripend info"},
+	{ERR_REASON(PKCS7_R_NO_CONTENT)          , "no content"},
+	{ERR_REASON(PKCS7_R_NO_CONTENT_TYPE)     , "no content type"},
+	{ERR_REASON(PKCS7_R_NO_DEFAULT_DIGEST)   , "no default digest"},
+	{ERR_REASON(PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND), "no matching digest type found"},
+	{ERR_REASON(PKCS7_R_NO_MULTIPART_BODY_FAILURE), "no multipart body failure"},
+	{ERR_REASON(PKCS7_R_NO_MULTIPART_BOUNDARY), "no multipart boundary"},
+	{ERR_REASON(PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE), "no recipient matches certificate"},
+	{ERR_REASON(PKCS7_R_NO_RECIPIENT_MATCHES_KEY), "no recipient matches key"},
+	{ERR_REASON(PKCS7_R_NO_SIGNATURES_ON_DATA), "no signatures on data"},
+	{ERR_REASON(PKCS7_R_NO_SIGNERS)          , "no signers"},
+	{ERR_REASON(PKCS7_R_NO_SIG_CONTENT_TYPE) , "no sig content type"},
+	{ERR_REASON(PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE), "operation not supported on this type"},
+	{ERR_REASON(PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR), "pkcs7 add signature error"},
+	{ERR_REASON(PKCS7_R_PKCS7_ADD_SIGNER_ERROR), "pkcs7 add signer error"},
+	{ERR_REASON(PKCS7_R_PKCS7_DATAFINAL)     , "pkcs7 datafinal"},
+	{ERR_REASON(PKCS7_R_PKCS7_DATAFINAL_ERROR), "pkcs7 datafinal error"},
+	{ERR_REASON(PKCS7_R_PKCS7_DATASIGN)      , "pkcs7 datasign"},
+	{ERR_REASON(PKCS7_R_PKCS7_PARSE_ERROR)   , "pkcs7 parse error"},
+	{ERR_REASON(PKCS7_R_PKCS7_SIG_PARSE_ERROR), "pkcs7 sig parse error"},
+	{ERR_REASON(PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), "private key does not match certificate"},
+	{ERR_REASON(PKCS7_R_SIGNATURE_FAILURE)   , "signature failure"},
+	{ERR_REASON(PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND), "signer certificate not found"},
+	{ERR_REASON(PKCS7_R_SIGNING_CTRL_FAILURE), "signing ctrl failure"},
+	{ERR_REASON(PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE), "signing not supported for this key type"},
+	{ERR_REASON(PKCS7_R_SIG_INVALID_MIME_TYPE), "sig invalid mime type"},
+	{ERR_REASON(PKCS7_R_SMIME_TEXT_ERROR)    , "smime text error"},
+	{ERR_REASON(PKCS7_R_UNABLE_TO_FIND_CERTIFICATE), "unable to find certificate"},
+	{ERR_REASON(PKCS7_R_UNABLE_TO_FIND_MEM_BIO), "unable to find mem bio"},
+	{ERR_REASON(PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST), "unable to find message digest"},
+	{ERR_REASON(PKCS7_R_UNKNOWN_DIGEST_TYPE) , "unknown digest type"},
+	{ERR_REASON(PKCS7_R_UNKNOWN_OPERATION)   , "unknown operation"},
+	{ERR_REASON(PKCS7_R_UNSUPPORTED_CIPHER_TYPE), "unsupported cipher type"},
+	{ERR_REASON(PKCS7_R_UNSUPPORTED_CONTENT_TYPE), "unsupported content type"},
+	{ERR_REASON(PKCS7_R_WRONG_CONTENT_TYPE)  , "wrong content type"},
+	{ERR_REASON(PKCS7_R_WRONG_PKCS7_TYPE)    , "wrong pkcs7 type"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_PKCS7_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(PKCS7_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, PKCS7_str_functs);
+		ERR_load_strings(0, PKCS7_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_PKCS7_strings);
diff --git a/crypto/poly1305/poly1305-donna.c b/crypto/poly1305/poly1305-donna.c
new file mode 100644
index 0000000..773ea4e
--- /dev/null
+++ b/crypto/poly1305/poly1305-donna.c
@@ -0,0 +1,321 @@
+/* $OpenBSD: poly1305-donna.c,v 1.3 2014/06/12 15:49:30 deraadt Exp $ */
+/*
+ * Public Domain poly1305 from Andrew Moon
+ * Based on poly1305-donna.c, poly1305-donna-32.h and poly1305-donna.h from:
+ *   https://github.com/floodyberry/poly1305-donna
+ */
+
+#include 
+
+static inline void poly1305_init(poly1305_context *ctx,
+    const unsigned char key[32]);
+static inline void poly1305_update(poly1305_context *ctx,
+    const unsigned char *m, size_t bytes);
+static inline void poly1305_finish(poly1305_context *ctx,
+    unsigned char mac[16]);
+
+/*
+ * poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication
+ * and 64 bit addition.
+ */
+
+#define poly1305_block_size 16
+
+/* 17 + sizeof(size_t) + 14*sizeof(unsigned long) */
+typedef struct poly1305_state_internal_t {
+	unsigned long r[5];
+	unsigned long h[5];
+	unsigned long pad[4];
+	size_t leftover;
+	unsigned char buffer[poly1305_block_size];
+	unsigned char final;
+} poly1305_state_internal_t;
+
+/* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */
+static unsigned long
+U8TO32(const unsigned char *p)
+{
+	return (((unsigned long)(p[0] & 0xff)) |
+	    ((unsigned long)(p[1] & 0xff) <<  8) |
+	    ((unsigned long)(p[2] & 0xff) << 16) |
+	    ((unsigned long)(p[3] & 0xff) << 24));
+}
+
+/* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */
+static void
+U32TO8(unsigned char *p, unsigned long v)
+{
+	p[0] = (v) & 0xff;
+	p[1] = (v >>  8) & 0xff;
+	p[2] = (v >> 16) & 0xff;
+	p[3] = (v >> 24) & 0xff;
+}
+
+static inline void
+poly1305_init(poly1305_context *ctx, const unsigned char key[32])
+{
+	poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
+
+	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+	st->r[0] = (U8TO32(&key[0])) & 0x3ffffff;
+	st->r[1] = (U8TO32(&key[3]) >> 2) & 0x3ffff03;
+	st->r[2] = (U8TO32(&key[6]) >> 4) & 0x3ffc0ff;
+	st->r[3] = (U8TO32(&key[9]) >> 6) & 0x3f03fff;
+	st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff;
+
+	/* h = 0 */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
+	st->h[3] = 0;
+	st->h[4] = 0;
+
+	/* save pad for later */
+	st->pad[0] = U8TO32(&key[16]);
+	st->pad[1] = U8TO32(&key[20]);
+	st->pad[2] = U8TO32(&key[24]);
+	st->pad[3] = U8TO32(&key[28]);
+
+	st->leftover = 0;
+	st->final = 0;
+}
+
+static void
+poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes)
+{
+	const unsigned long hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */
+	unsigned long r0, r1, r2, r3, r4;
+	unsigned long s1, s2, s3, s4;
+	unsigned long h0, h1, h2, h3, h4;
+	unsigned long long d0, d1, d2, d3, d4;
+	unsigned long c;
+
+	r0 = st->r[0];
+	r1 = st->r[1];
+	r2 = st->r[2];
+	r3 = st->r[3];
+	r4 = st->r[4];
+
+	s1 = r1 * 5;
+	s2 = r2 * 5;
+	s3 = r3 * 5;
+	s4 = r4 * 5;
+
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+	h3 = st->h[3];
+	h4 = st->h[4];
+
+	while (bytes >= poly1305_block_size) {
+		/* h += m[i] */
+		h0 += (U8TO32(m + 0)) & 0x3ffffff;
+		h1 += (U8TO32(m + 3) >> 2) & 0x3ffffff;
+		h2 += (U8TO32(m + 6) >> 4) & 0x3ffffff;
+		h3 += (U8TO32(m + 9) >> 6) & 0x3ffffff;
+		h4 += (U8TO32(m + 12) >> 8) | hibit;
+
+		/* h *= r */
+		d0 = ((unsigned long long)h0 * r0) +
+		    ((unsigned long long)h1 * s4) +
+		    ((unsigned long long)h2 * s3) +
+		    ((unsigned long long)h3 * s2) +
+		    ((unsigned long long)h4 * s1);
+		d1 = ((unsigned long long)h0 * r1) +
+		    ((unsigned long long)h1 * r0) +
+		    ((unsigned long long)h2 * s4) +
+		    ((unsigned long long)h3 * s3) +
+		    ((unsigned long long)h4 * s2);
+		d2 = ((unsigned long long)h0 * r2) +
+		    ((unsigned long long)h1 * r1) +
+		    ((unsigned long long)h2 * r0) +
+		    ((unsigned long long)h3 * s4) +
+		    ((unsigned long long)h4 * s3);
+		d3 = ((unsigned long long)h0 * r3) +
+		    ((unsigned long long)h1 * r2) +
+		    ((unsigned long long)h2 * r1) +
+		    ((unsigned long long)h3 * r0) +
+		    ((unsigned long long)h4 * s4);
+		d4 = ((unsigned long long)h0 * r4) +
+		    ((unsigned long long)h1 * r3) +
+		    ((unsigned long long)h2 * r2) +
+		    ((unsigned long long)h3 * r1) +
+		    ((unsigned long long)h4 * r0);
+
+		/* (partial) h %= p */
+		c = (unsigned long)(d0 >> 26);
+		h0 = (unsigned long)d0 & 0x3ffffff;
+		d1 += c;
+		c = (unsigned long)(d1 >> 26);
+		h1 = (unsigned long)d1 & 0x3ffffff;
+		d2 += c;
+		c = (unsigned long)(d2 >> 26);
+		h2 = (unsigned long)d2 & 0x3ffffff;
+		d3 += c;
+		c = (unsigned long)(d3 >> 26);
+		h3 = (unsigned long)d3 & 0x3ffffff;
+		d4 += c;
+		c = (unsigned long)(d4 >> 26);
+		h4 = (unsigned long)d4 & 0x3ffffff;
+		h0 += c * 5;
+		c = (h0 >> 26);
+		h0 = h0 & 0x3ffffff;
+		h1 += c;
+
+		m += poly1305_block_size;
+		bytes -= poly1305_block_size;
+	}
+
+	st->h[0] = h0;
+	st->h[1] = h1;
+	st->h[2] = h2;
+	st->h[3] = h3;
+	st->h[4] = h4;
+}
+
+static inline void
+poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes)
+{
+	poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
+	size_t i;
+
+	/* handle leftover */
+	if (st->leftover) {
+		size_t want = (poly1305_block_size - st->leftover);
+		if (want > bytes)
+			want = bytes;
+		for (i = 0; i < want; i++)
+			st->buffer[st->leftover + i] = m[i];
+		bytes -= want;
+		m += want;
+		st->leftover += want;
+		if (st->leftover < poly1305_block_size)
+			return;
+		poly1305_blocks(st, st->buffer, poly1305_block_size);
+		st->leftover = 0;
+	}
+
+	/* process full blocks */
+	if (bytes >= poly1305_block_size) {
+		size_t want = (bytes & ~(poly1305_block_size - 1));
+		poly1305_blocks(st, m, want);
+		m += want;
+		bytes -= want;
+	}
+
+	/* store leftover */
+	if (bytes) {
+		for (i = 0; i < bytes; i++)
+			st->buffer[st->leftover + i] = m[i];
+		st->leftover += bytes;
+	}
+}
+
+static inline void
+poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
+{
+	poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
+	unsigned long h0, h1, h2, h3, h4, c;
+	unsigned long g0, g1, g2, g3, g4;
+	unsigned long long f;
+	unsigned long mask;
+
+	/* process the remaining block */
+	if (st->leftover) {
+		size_t i = st->leftover;
+		st->buffer[i++] = 1;
+		for (; i < poly1305_block_size; i++)
+			st->buffer[i] = 0;
+		st->final = 1;
+		poly1305_blocks(st, st->buffer, poly1305_block_size);
+	}
+
+	/* fully carry h */
+	h0 = st->h[0];
+	h1 = st->h[1];
+	h2 = st->h[2];
+	h3 = st->h[3];
+	h4 = st->h[4];
+
+	c = h1 >> 26;
+	h1 = h1 & 0x3ffffff;
+	h2 += c;
+	c = h2 >> 26;
+	h2 = h2 & 0x3ffffff;
+	h3 += c;
+	c = h3 >> 26;
+	h3 = h3 & 0x3ffffff;
+	h4 += c;
+	c = h4 >> 26;
+	h4 = h4 & 0x3ffffff;
+	h0 += c * 5;
+	c = h0 >> 26;
+	h0 = h0 & 0x3ffffff;
+	h1 += c;
+
+	/* compute h + -p */
+	g0 = h0 + 5;
+	c = g0 >> 26;
+	g0 &= 0x3ffffff;
+	g1 = h1 + c;
+	c = g1 >> 26;
+	g1 &= 0x3ffffff;
+	g2 = h2 + c;
+	c = g2 >> 26;
+	g2 &= 0x3ffffff;
+	g3 = h3 + c;
+	c = g3 >> 26;
+	g3 &= 0x3ffffff;
+	g4 = h4 + c - (1 << 26);
+
+	/* select h if h < p, or h + -p if h >= p */
+	mask = (g4 >> ((sizeof(unsigned long) * 8) - 1)) - 1;
+	g0 &= mask;
+	g1 &= mask;
+	g2 &= mask;
+	g3 &= mask;
+	g4 &= mask;
+	mask = ~mask;
+	h0 = (h0 & mask) | g0;
+	h1 = (h1 & mask) | g1;
+	h2 = (h2 & mask) | g2;
+	h3 = (h3 & mask) | g3;
+	h4 = (h4 & mask) | g4;
+
+	/* h = h % (2^128) */
+	h0 = ((h0) | (h1 << 26)) & 0xffffffff;
+	h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
+	h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+	h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
+
+	/* mac = (h + pad) % (2^128) */
+	f = (unsigned long long)h0 + st->pad[0];
+	h0 = (unsigned long)f;
+	f = (unsigned long long)h1 + st->pad[1] + (f >> 32);
+	h1 = (unsigned long)f;
+	f = (unsigned long long)h2 + st->pad[2] + (f >> 32);
+	h2 = (unsigned long)f;
+	f = (unsigned long long)h3 + st->pad[3] + (f >> 32);
+	h3 = (unsigned long)f;
+
+	U32TO8(mac +  0, h0);
+	U32TO8(mac +  4, h1);
+	U32TO8(mac +  8, h2);
+	U32TO8(mac + 12, h3);
+
+	/* zero out the state */
+	st->h[0] = 0;
+	st->h[1] = 0;
+	st->h[2] = 0;
+	st->h[3] = 0;
+	st->h[4] = 0;
+	st->r[0] = 0;
+	st->r[1] = 0;
+	st->r[2] = 0;
+	st->r[3] = 0;
+	st->r[4] = 0;
+	st->pad[0] = 0;
+	st->pad[1] = 0;
+	st->pad[2] = 0;
+	st->pad[3] = 0;
+}
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
new file mode 100644
index 0000000..a34e8f8
--- /dev/null
+++ b/crypto/poly1305/poly1305.c
@@ -0,0 +1,41 @@
+/* $OpenBSD: poly1305.c,v 1.4 2023/07/07 12:01:32 beck Exp $ */
+/*
+ * Copyright (c) 2014 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include "poly1305-donna.c"
+
+void
+CRYPTO_poly1305_init(poly1305_context *ctx, const unsigned char key[32])
+{
+	poly1305_init(ctx, key);
+}
+LCRYPTO_ALIAS(CRYPTO_poly1305_init);
+
+void
+CRYPTO_poly1305_update(poly1305_context *ctx, const unsigned char *in,
+    size_t len)
+{
+	poly1305_update(ctx, in, len);
+}
+LCRYPTO_ALIAS(CRYPTO_poly1305_update);
+
+void
+CRYPTO_poly1305_finish(poly1305_context *ctx, unsigned char mac[16])
+{
+	poly1305_finish(ctx, mac);
+}
+LCRYPTO_ALIAS(CRYPTO_poly1305_finish);
diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c
new file mode 100644
index 0000000..b156c0c
--- /dev/null
+++ b/crypto/rand/rand_err.c
@@ -0,0 +1,94 @@
+/* $OpenBSD: rand_err.c,v 1.17 2023/07/07 12:01:32 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_RAND,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_RAND,0,reason)
+
+static ERR_STRING_DATA RAND_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA RAND_str_reasons[] = {
+	{ERR_REASON(RAND_R_DUAL_EC_DRBG_DISABLED), "dual ec drbg disabled"},
+	{ERR_REASON(RAND_R_ERROR_INITIALISING_DRBG), "error initialising drbg"},
+	{ERR_REASON(RAND_R_ERROR_INSTANTIATING_DRBG), "error instantiating drbg"},
+	{ERR_REASON(RAND_R_NO_FIPS_RANDOM_METHOD_SET), "no fips random method set"},
+	{ERR_REASON(RAND_R_PRNG_NOT_SEEDED)      , "PRNG not seeded"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_RAND_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(RAND_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, RAND_str_functs);
+		ERR_load_strings(0, RAND_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_RAND_strings);
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
new file mode 100644
index 0000000..5c5df98
--- /dev/null
+++ b/crypto/rand/rand_lib.c
@@ -0,0 +1,104 @@
+/* $OpenBSD: rand_lib.c,v 1.22 2023/07/07 19:37:54 beck Exp $ */
+/*
+ * Copyright (c) 2014 Ted Unangst 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#include 
+
+#include 
+
+/*
+ * The useful functions in this file are at the bottom.
+ */
+int
+RAND_set_rand_method(const RAND_METHOD *meth)
+{
+	return 1;
+}
+LCRYPTO_ALIAS(RAND_set_rand_method);
+
+const RAND_METHOD *
+RAND_get_rand_method(void)
+{
+	return NULL;
+}
+LCRYPTO_ALIAS(RAND_get_rand_method);
+
+RAND_METHOD *
+RAND_SSLeay(void)
+{
+	return NULL;
+}
+LCRYPTO_ALIAS(RAND_SSLeay);
+
+#ifndef OPENSSL_NO_ENGINE
+int
+RAND_set_rand_engine(ENGINE *engine)
+{
+	return 1;
+}
+LCRYPTO_ALIAS(RAND_set_rand_engine);
+#endif
+
+void
+RAND_cleanup(void)
+{
+
+}
+
+void
+RAND_seed(const void *buf, int num)
+{
+
+}
+
+void
+RAND_add(const void *buf, int num, double entropy)
+{
+
+}
+
+int
+RAND_status(void)
+{
+	return 1;
+}
+
+int
+RAND_poll(void)
+{
+	return 1;
+}
+
+/*
+ * Hurray. You've made it to the good parts.
+ */
+int
+RAND_bytes(unsigned char *buf, int num)
+{
+	if (num > 0)
+		arc4random_buf(buf, num);
+	return 1;
+}
+
+int
+RAND_pseudo_bytes(unsigned char *buf, int num)
+{
+	if (num > 0)
+		arc4random_buf(buf, num);
+	return 1;
+}
diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c
new file mode 100644
index 0000000..00008af
--- /dev/null
+++ b/crypto/rand/randfile.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: randfile.c,v 1.44 2023/07/07 19:37:54 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#undef BUFSIZE
+#define BUFSIZE	1024
+#define RAND_DATA 1024
+
+/* Note that these functions should not be used. */
+
+int
+RAND_load_file(const char *file, long bytes)
+{
+	/* the "whole" file */
+	if (bytes == -1)
+		return 123456;
+	else
+		return bytes;
+}
+
+int
+RAND_write_file(const char *file)
+{
+	unsigned char buf[BUFSIZE];
+	int i, ret = 0;
+	FILE *out = NULL;
+	int n, fd;
+	struct stat sb;
+
+	/*
+	 * If this file is a device, avoid opening it.
+	 * XXX TOCTOU
+	 */
+	if (stat(file, &sb) != -1 &&
+	    (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))) {
+		return (1);
+	}
+
+	fd = open(file, O_WRONLY|O_CREAT, 0600);
+	if (fd == -1)
+		return (1);
+	out = fdopen(fd, "wb");
+
+	if (out == NULL) {
+		close(fd);
+		return (1);
+	}
+
+	n = RAND_DATA;
+	for (;;) {
+		i = (n > BUFSIZE) ? BUFSIZE : n;
+		n -= BUFSIZE;
+		arc4random_buf(buf, i);
+		i = fwrite(buf, 1, i, out);
+		if (i <= 0) {
+			ret = 0;
+			break;
+		}
+		ret += i;
+		if (n <= 0)
+			break;
+	}
+
+	fclose(out);
+	explicit_bzero(buf, BUFSIZE);
+	return ret;
+}
+
+const char *
+RAND_file_name(char * buf, size_t size)
+{
+	if (strlcpy(buf, "/dev/urandom", size) >= size)
+		return (NULL);
+	return buf;
+}
diff --git a/crypto/rc2/rc2_cbc.c b/crypto/rc2/rc2_cbc.c
new file mode 100644
index 0000000..1d8e2de
--- /dev/null
+++ b/crypto/rc2/rc2_cbc.c
@@ -0,0 +1,236 @@
+/* $OpenBSD: rc2_cbc.c,v 1.8 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "rc2_local.h"
+
+void
+RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length,
+    RC2_KEY *ks, unsigned char *iv, int encrypt)
+{
+	unsigned long tin0, tin1;
+	unsigned long tout0, tout1, xor0, xor1;
+	long l = length;
+	unsigned long tin[2];
+
+	if (encrypt) {
+		c2l(iv, tout0);
+		c2l(iv, tout1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8)
+		{
+			c2l(in, tin0);
+			c2l(in, tin1);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			RC2_encrypt(tin, ks);
+			tout0 = tin[0];
+			l2c(tout0, out);
+			tout1 = tin[1];
+			l2c(tout1, out);
+		}
+		if (l != -8) {
+			c2ln(in, tin0, tin1, l + 8);
+			tin0 ^= tout0;
+			tin1 ^= tout1;
+			tin[0] = tin0;
+			tin[1] = tin1;
+			RC2_encrypt(tin, ks);
+			tout0 = tin[0];
+			l2c(tout0, out);
+			tout1 = tin[1];
+			l2c(tout1, out);
+		}
+		l2c(tout0, iv);
+		l2c(tout1, iv);
+	} else {
+		c2l(iv, xor0);
+		c2l(iv, xor1);
+		iv -= 8;
+		for (l -= 8; l >= 0; l -= 8)
+		{
+			c2l(in, tin0);
+			tin[0] = tin0;
+			c2l(in, tin1);
+			tin[1] = tin1;
+			RC2_decrypt(tin, ks);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2c(tout0, out);
+			l2c(tout1, out);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		if (l != -8) {
+			c2l(in, tin0);
+			tin[0] = tin0;
+			c2l(in, tin1);
+			tin[1] = tin1;
+			RC2_decrypt(tin, ks);
+			tout0 = tin[0] ^ xor0;
+			tout1 = tin[1] ^ xor1;
+			l2cn(tout0, tout1, out, l + 8);
+			xor0 = tin0;
+			xor1 = tin1;
+		}
+		l2c(xor0, iv);
+		l2c(xor1, iv);
+	}
+	tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
+	tin[0] = tin[1] = 0;
+}
+LCRYPTO_ALIAS(RC2_cbc_encrypt);
+
+void
+RC2_encrypt(unsigned long *d, RC2_KEY *key)
+{
+	int i, n;
+	RC2_INT *p0, *p1;
+	RC2_INT x0, x1, x2, x3, t;
+	unsigned long l;
+
+	l = d[0];
+	x0 = (RC2_INT)l & 0xffff;
+	x1 = (RC2_INT)(l >> 16L);
+	l = d[1];
+	x2 = (RC2_INT)l & 0xffff;
+	x3 = (RC2_INT)(l >> 16L);
+
+	n = 3;
+	i = 5;
+
+	p0 = p1 = &(key->data[0]);
+	for (;;) {
+		t = (x0 + (x1 & ~x3) + (x2 & x3) + *(p0++)) & 0xffff;
+		x0 = (t << 1)|(t >> 15);
+		t = (x1 + (x2 & ~x0) + (x3 & x0) + *(p0++)) & 0xffff;
+		x1 = (t << 2)|(t >> 14);
+		t = (x2 + (x3 & ~x1) + (x0 & x1) + *(p0++)) & 0xffff;
+		x2 = (t << 3)|(t >> 13);
+		t = (x3 + (x0 & ~x2) + (x1 & x2) + *(p0++)) & 0xffff;
+		x3 = (t << 5)|(t >> 11);
+
+		if (--i == 0) {
+			if (--n == 0)
+				break;
+			i = (n == 2) ? 6 : 5;
+
+			x0 += p1[x3 & 0x3f];
+			x1 += p1[x0 & 0x3f];
+			x2 += p1[x1 & 0x3f];
+			x3 += p1[x2 & 0x3f];
+		}
+	}
+
+	d[0] = (unsigned long)(x0 & 0xffff)|((unsigned long)(x1 & 0xffff) <<
+	    16L);
+	d[1] = (unsigned long)(x2 & 0xffff)|((unsigned long)(x3 & 0xffff) <<
+	    16L);
+}
+LCRYPTO_ALIAS(RC2_encrypt);
+
+void
+RC2_decrypt(unsigned long *d, RC2_KEY *key)
+{
+	int i, n;
+	RC2_INT *p0, *p1;
+	RC2_INT x0, x1, x2, x3, t;
+	unsigned long l;
+
+	l = d[0];
+	x0 = (RC2_INT)l & 0xffff;
+	x1 = (RC2_INT)(l >> 16L);
+	l = d[1];
+	x2 = (RC2_INT)l & 0xffff;
+	x3 = (RC2_INT)(l >> 16L);
+
+	n = 3;
+	i = 5;
+
+	p0 = &(key->data[63]);
+	p1 = &(key->data[0]);
+	for (;;) {
+		t = ((x3 << 11)|(x3 >> 5)) & 0xffff;
+		x3 = (t - (x0 & ~x2) - (x1 & x2) - *(p0--)) & 0xffff;
+		t = ((x2 << 13)|(x2 >> 3)) & 0xffff;
+		x2 = (t - (x3 & ~x1) - (x0 & x1) - *(p0--)) & 0xffff;
+		t = ((x1 << 14)|(x1 >> 2)) & 0xffff;
+		x1 = (t - (x2 & ~x0) - (x3 & x0) - *(p0--)) & 0xffff;
+		t = ((x0 << 15)|(x0 >> 1)) & 0xffff;
+		x0 = (t - (x1 & ~x3) - (x2 & x3) - *(p0--)) & 0xffff;
+
+		if (--i == 0) {
+			if (--n == 0)
+				break;
+			i = (n == 2) ? 6 : 5;
+
+			x3 = (x3 - p1[x2 & 0x3f]) & 0xffff;
+			x2 = (x2 - p1[x1 & 0x3f]) & 0xffff;
+			x1 = (x1 - p1[x0 & 0x3f]) & 0xffff;
+			x0 = (x0 - p1[x3 & 0x3f]) & 0xffff;
+		}
+	}
+
+	d[0] = (unsigned long)(x0 & 0xffff)|((unsigned long)(x1 & 0xffff) <<
+	    16L);
+	d[1] = (unsigned long)(x2 & 0xffff)|((unsigned long)(x3 & 0xffff) <<
+	    16L);
+}
+LCRYPTO_ALIAS(RC2_decrypt);
diff --git a/crypto/rc2/rc2_ecb.c b/crypto/rc2/rc2_ecb.c
new file mode 100644
index 0000000..6a3c809
--- /dev/null
+++ b/crypto/rc2/rc2_ecb.c
@@ -0,0 +1,91 @@
+/* $OpenBSD: rc2_ecb.c,v 1.9 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "rc2_local.h"
+#include 
+
+/* RC2 as implemented frm a posting from
+ * Newsgroups: sci.crypt
+ * Sender: pgut01@cs.auckland.ac.nz (Peter Gutmann)
+ * Subject: Specification for Ron Rivests Cipher No.2
+ * Message-ID: <4fk39f$f70@net.auckland.ac.nz>
+ * Date: 11 Feb 1996 06:45:03 GMT
+ */
+
+void
+RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, RC2_KEY *ks,
+    int encrypt)
+{
+	unsigned long l, d[2];
+
+	c2l(in, l);
+	d[0] = l;
+	c2l(in, l);
+	d[1] = l;
+	if (encrypt)
+		RC2_encrypt(d, ks);
+	else
+		RC2_decrypt(d, ks);
+	l = d[0];
+	l2c(l, out);
+	l = d[1];
+	l2c(l, out);
+	l = d[0] = d[1] = 0;
+}
+LCRYPTO_ALIAS(RC2_ecb_encrypt);
diff --git a/crypto/rc2/rc2_local.h b/crypto/rc2/rc2_local.h
new file mode 100644
index 0000000..64c9c53
--- /dev/null
+++ b/crypto/rc2/rc2_local.h
@@ -0,0 +1,155 @@
+/* $OpenBSD: rc2_local.h,v 1.2 2023/07/07 08:29:37 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#undef c2l
+#define c2l(c,l)	(l =((unsigned long)(*((c)++)))    ,		\
+			 l|=((unsigned long)(*((c)++)))<< 8L,		\
+			 l|=((unsigned long)(*((c)++)))<<16L,		\
+			 l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n)	{						\
+			c+=n;						\
+			l1=l2=0;					\
+			switch (n) {					\
+			case 8: l2 =((unsigned long)(*(--(c))))<<24L;	\
+			case 7: l2|=((unsigned long)(*(--(c))))<<16L;	\
+			case 6: l2|=((unsigned long)(*(--(c))))<< 8L;	\
+			case 5: l2|=((unsigned long)(*(--(c))));	\
+			case 4: l1 =((unsigned long)(*(--(c))))<<24L;	\
+			case 3: l1|=((unsigned long)(*(--(c))))<<16L;	\
+			case 2: l1|=((unsigned long)(*(--(c))))<< 8L;	\
+			case 1: l1|=((unsigned long)(*(--(c))));	\
+				}					\
+			}
+
+#undef l2c
+#define l2c(l,c)	(*((c)++)=(unsigned char)(((l)     )&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>> 8L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>16L)&0xff),	\
+			 *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n)	{						\
+			c+=n;						\
+			switch (n) {					\
+			case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff);\
+			case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff);\
+			case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff);\
+			case 5: *(--(c))=(unsigned char)(((l2)     )&0xff);\
+			case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff);\
+			case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff);\
+			case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff);\
+			case 1: *(--(c))=(unsigned char)(((l1)     )&0xff);\
+				}					\
+			}
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n)	{						\
+			c+=n;						\
+			l1=l2=0;					\
+			switch (n) {					\
+			case 8: l2 =((unsigned long)(*(--(c))))    ;	\
+			case 7: l2|=((unsigned long)(*(--(c))))<< 8;	\
+			case 6: l2|=((unsigned long)(*(--(c))))<<16;	\
+			case 5: l2|=((unsigned long)(*(--(c))))<<24;	\
+			case 4: l1 =((unsigned long)(*(--(c))))    ;	\
+			case 3: l1|=((unsigned long)(*(--(c))))<< 8;	\
+			case 2: l1|=((unsigned long)(*(--(c))))<<16;	\
+			case 1: l1|=((unsigned long)(*(--(c))))<<24;	\
+				}					\
+			}
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n)	{						\
+			c+=n;						\
+			switch (n) {					\
+			case 8: *(--(c))=(unsigned char)(((l2)    )&0xff);\
+			case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff);\
+			case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff);\
+			case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff);\
+			case 4: *(--(c))=(unsigned char)(((l1)    )&0xff);\
+			case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff);\
+			case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff);\
+			case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff);\
+				}					\
+			}
+
+#undef n2l
+#define n2l(c,l)        (l =((unsigned long)(*((c)++)))<<24L,		\
+                         l|=((unsigned long)(*((c)++)))<<16L,		\
+                         l|=((unsigned long)(*((c)++)))<< 8L,		\
+                         l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c)        (*((c)++)=(unsigned char)(((l)>>24L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)>>16L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)>> 8L)&0xff),	\
+                         *((c)++)=(unsigned char)(((l)     )&0xff))
+
+#define C_RC2(n)							\
+	t=(x0+(x1& ~x3)+(x2&x3)+ *(p0++))&0xffff;			\
+	x0=(t<<1)|(t>>15);						\
+	t=(x1+(x2& ~x0)+(x3&x0)+ *(p0++))&0xffff;			\
+	x1=(t<<2)|(t>>14);						\
+	t=(x2+(x3& ~x1)+(x0&x1)+ *(p0++))&0xffff;			\
+	x2=(t<<3)|(t>>13);						\
+	t=(x3+(x0& ~x2)+(x1&x2)+ *(p0++))&0xffff;			\
+	x3=(t<<5)|(t>>11);
diff --git a/crypto/rc2/rc2_skey.c b/crypto/rc2/rc2_skey.c
new file mode 100644
index 0000000..d33c02d
--- /dev/null
+++ b/crypto/rc2/rc2_skey.c
@@ -0,0 +1,142 @@
+/* $OpenBSD: rc2_skey.c,v 1.15 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include "rc2_local.h"
+
+static const unsigned char key_table[256]={
+	0xd9,0x78,0xf9,0xc4,0x19,0xdd,0xb5,0xed,0x28,0xe9,0xfd,0x79,
+	0x4a,0xa0,0xd8,0x9d,0xc6,0x7e,0x37,0x83,0x2b,0x76,0x53,0x8e,
+	0x62,0x4c,0x64,0x88,0x44,0x8b,0xfb,0xa2,0x17,0x9a,0x59,0xf5,
+	0x87,0xb3,0x4f,0x13,0x61,0x45,0x6d,0x8d,0x09,0x81,0x7d,0x32,
+	0xbd,0x8f,0x40,0xeb,0x86,0xb7,0x7b,0x0b,0xf0,0x95,0x21,0x22,
+	0x5c,0x6b,0x4e,0x82,0x54,0xd6,0x65,0x93,0xce,0x60,0xb2,0x1c,
+	0x73,0x56,0xc0,0x14,0xa7,0x8c,0xf1,0xdc,0x12,0x75,0xca,0x1f,
+	0x3b,0xbe,0xe4,0xd1,0x42,0x3d,0xd4,0x30,0xa3,0x3c,0xb6,0x26,
+	0x6f,0xbf,0x0e,0xda,0x46,0x69,0x07,0x57,0x27,0xf2,0x1d,0x9b,
+	0xbc,0x94,0x43,0x03,0xf8,0x11,0xc7,0xf6,0x90,0xef,0x3e,0xe7,
+	0x06,0xc3,0xd5,0x2f,0xc8,0x66,0x1e,0xd7,0x08,0xe8,0xea,0xde,
+	0x80,0x52,0xee,0xf7,0x84,0xaa,0x72,0xac,0x35,0x4d,0x6a,0x2a,
+	0x96,0x1a,0xd2,0x71,0x5a,0x15,0x49,0x74,0x4b,0x9f,0xd0,0x5e,
+	0x04,0x18,0xa4,0xec,0xc2,0xe0,0x41,0x6e,0x0f,0x51,0xcb,0xcc,
+	0x24,0x91,0xaf,0x50,0xa1,0xf4,0x70,0x39,0x99,0x7c,0x3a,0x85,
+	0x23,0xb8,0xb4,0x7a,0xfc,0x02,0x36,0x5b,0x25,0x55,0x97,0x31,
+	0x2d,0x5d,0xfa,0x98,0xe3,0x8a,0x92,0xae,0x05,0xdf,0x29,0x10,
+	0x67,0x6c,0xba,0xc9,0xd3,0x00,0xe6,0xcf,0xe1,0x9e,0xa8,0x2c,
+	0x63,0x16,0x01,0x3f,0x58,0xe2,0x89,0xa9,0x0d,0x38,0x34,0x1b,
+	0xab,0x33,0xff,0xb0,0xbb,0x48,0x0c,0x5f,0xb9,0xb1,0xcd,0x2e,
+	0xc5,0xf3,0xdb,0x47,0xe5,0xa5,0x9c,0x77,0x0a,0xa6,0x20,0x68,
+	0xfe,0x7f,0xc1,0xad,
+	};
+
+/* 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 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 */
+void
+RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
+{
+	int i, j;
+	unsigned char *k;
+	RC2_INT *ki;
+	unsigned int c, d;
+
+	k = (unsigned char *)&(key->data[0]);
+	*k = 0; /* for if there is a zero length key */
+
+	if (len > 128)
+		len = 128;
+	if (bits <= 0)
+		bits = 1024;
+	if (bits > 1024)
+		bits = 1024;
+
+	for (i = 0; i < len; i++)
+		k[i] = data[i];
+
+	/* expand table */
+	d = k[len - 1];
+	j = 0;
+	for (i = len; i < 128; i++, j++)
+	{
+		d = key_table[(k[j] + d) & 0xff];
+		k[i] = d;
+	}
+
+	/* hmm.... key reduction to 'bits' bits */
+
+	j = (bits + 7) >> 3;
+	i = 128 - j;
+	c = (0xff >> (-bits & 0x07));
+
+	d = key_table[k[i] & c];
+	k[i] = d;
+	while (i--) {
+		d = key_table[k[i + j] ^ d];
+		k[i] = d;
+	}
+
+	/* copy from bytes into RC2_INT's */
+	ki = &(key->data[63]);
+	for (i = 127; i >= 0; i -= 2)
+		*(ki--) = ((k[i] << 8)|k[i - 1]) & 0xffff;
+}
+LCRYPTO_ALIAS(RC2_set_key);
diff --git a/crypto/rc2/rc2cfb64.c b/crypto/rc2/rc2cfb64.c
new file mode 100644
index 0000000..21266c4
--- /dev/null
+++ b/crypto/rc2/rc2cfb64.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: rc2cfb64.c,v 1.8 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "rc2_local.h"
+
+/* The input and output encrypted as though 64bit cfb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+
+void
+RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, RC2_KEY *schedule, unsigned char *ivec,
+    int *num, int encrypt)
+{
+	unsigned long v0, v1, t;
+	int n = *num;
+	long l = length;
+	unsigned long ti[2];
+	unsigned char *iv, c, cc;
+
+	iv = (unsigned char *)ivec;
+	if (encrypt) {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				ti[0] = v0;
+				c2l(iv, v1);
+				ti[1] = v1;
+				RC2_encrypt((unsigned long *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2c(t, iv);
+				t = ti[1];
+				l2c(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			c = *(in++) ^ iv[n];
+			*(out++) = c;
+			iv[n] = c;
+			n = (n + 1) & 0x07;
+		}
+	} else {
+		while (l--) {
+			if (n == 0) {
+				c2l(iv, v0);
+				ti[0] = v0;
+				c2l(iv, v1);
+				ti[1] = v1;
+				RC2_encrypt((unsigned long *)ti, schedule);
+				iv = (unsigned char *)ivec;
+				t = ti[0];
+				l2c(t, iv);
+				t = ti[1];
+				l2c(t, iv);
+				iv = (unsigned char *)ivec;
+			}
+			cc = *(in++);
+			c = iv[n];
+			iv[n] = cc;
+			*(out++) = c ^ cc;
+			n = (n + 1) & 0x07;
+		}
+	}
+	v0 = v1 = ti[0] = ti[1] = t = c = cc = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(RC2_cfb64_encrypt);
diff --git a/crypto/rc2/rc2ofb64.c b/crypto/rc2/rc2ofb64.c
new file mode 100644
index 0000000..73d8323
--- /dev/null
+++ b/crypto/rc2/rc2ofb64.c
@@ -0,0 +1,111 @@
+/* $OpenBSD: rc2ofb64.c,v 1.8 2023/07/07 13:40:44 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include "rc2_local.h"
+
+/* The input and output encrypted as though 64bit ofb mode is being
+ * used.  The extra state information to record how much of the
+ * 64bit block we have used is contained in *num;
+ */
+void
+RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
+    long length, RC2_KEY *schedule, unsigned char *ivec,
+    int *num)
+{
+	unsigned long v0, v1, t;
+	int n = *num;
+	long l = length;
+	unsigned char d[8];
+	char *dp;
+	unsigned long ti[2];
+	unsigned char *iv;
+	int save = 0;
+
+	iv = (unsigned char *)ivec;
+	c2l(iv, v0);
+	c2l(iv, v1);
+	ti[0] = v0;
+	ti[1] = v1;
+	dp = (char *)d;
+	l2c(v0, dp);
+	l2c(v1, dp);
+	while (l--) {
+		if (n == 0) {
+			RC2_encrypt((unsigned long *)ti, schedule);
+			dp = (char *)d;
+			t = ti[0];
+			l2c(t, dp);
+			t = ti[1];
+			l2c(t, dp);
+			save++;
+		}
+		*(out++) = *(in++) ^ d[n];
+		n = (n + 1) & 0x07;
+	}
+	if (save) {
+		v0 = ti[0];
+		v1 = ti[1];
+		iv = (unsigned char *)ivec;
+		l2c(v0, iv);
+		l2c(v1, iv);
+	}
+	t = v0 = v1 = ti[0] = ti[1] = 0;
+	*num = n;
+}
+LCRYPTO_ALIAS(RC2_ofb64_encrypt);
diff --git a/crypto/rc4/rc4-elf-x86_64.S b/crypto/rc4/rc4-elf-x86_64.S
new file mode 100644
index 0000000..aa7f8ca
--- /dev/null
+++ b/crypto/rc4/rc4-elf-x86_64.S
@@ -0,0 +1,598 @@
+#include "x86_arch.h"
+.text	
+
+.hidden	OPENSSL_ia32cap_P
+
+.globl	RC4
+.type	RC4,@function
+.align	16
+RC4:
+	endbr64
+	orq	%rsi,%rsi
+	jne	.Lentry
+	retq
+.Lentry:
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+.Lprologue:
+	movq	%rsi,%r11
+	movq	%rdx,%r12
+	movq	%rcx,%r13
+	xorq	%r10,%r10
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%r10b
+	movb	-4(%rdi),%cl
+	cmpl	$-1,256(%rdi)
+	je	.LRC4_CHAR
+	movl	OPENSSL_ia32cap_P(%rip),%r8d
+	xorq	%rbx,%rbx
+	incb	%r10b
+	subq	%r10,%rbx
+	subq	%r12,%r13
+	movl	(%rdi,%r10,4),%eax
+	testq	$-16,%r11
+	jz	.Lloop1
+	btl	$IA32CAP_BIT0_INTEL,%r8d
+	jc	.Lintel
+	andq	$7,%rbx
+	leaq	1(%r10),%rsi
+	jz	.Loop8
+	subq	%rbx,%r11
+.Loop8_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	.Loop8_warmup
+
+	leaq	1(%r10),%rsi
+	jmp	.Loop8
+.align	16
+.Loop8:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	0(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,0(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,4(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	8(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,8(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	12(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,12(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	16(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,16(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	20(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,20(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	24(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,24(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%sil
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	-4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,28(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%r10b
+	rorq	$8,%r8
+	subq	$8,%r11
+
+	xorq	(%r12),%r8
+	movq	%r8,(%r13,%r12,1)
+	leaq	8(%r12),%r12
+
+	testq	$-8,%r11
+	jnz	.Loop8
+	cmpq	$0,%r11
+	jne	.Lloop1
+	jmp	.Lexit
+
+.align	16
+.Lintel:
+	testq	$-32,%r11
+	jz	.Lloop1
+	andq	$15,%rbx
+	jz	.Loop16_is_hot
+	subq	%rbx,%r11
+.Loop16_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	.Loop16_warmup
+
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	movb	%bl,%cl
+
+.Loop16_is_hot:
+	leaq	(%rdi,%r10,4),%rsi
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	jmp	.Loop16_enter
+.align	16
+.Loop16:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm2
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	pxor	%xmm1,%xmm2
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+.Loop16_enter:
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm1,%xmm1
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	pinsrw	$0,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+	addb	$16,%r10b
+	movdqu	(%r12),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	leaq	(%rdi,%r10,4),%rsi
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+	movl	(%rsi),%eax
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	subq	$16,%r11
+	movb	%bl,%cl
+	testq	$-16,%r11
+	jnz	.Loop16
+
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+
+	cmpq	$0,%r11
+	jne	.Lloop1
+	jmp	.Lexit
+
+.align	16
+.Lloop1:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%r11
+	jnz	.Lloop1
+	jmp	.Lexit
+
+.align	16
+.LRC4_CHAR:
+	addb	$1,%r10b
+	movzbl	(%rdi,%r10,1),%eax
+	testq	$-8,%r11
+	jz	.Lcloop1
+	jmp	.Lcloop8
+.align	16
+.Lcloop8:
+	movl	(%r12),%r8d
+	movl	4(%r12),%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov0			
+	movq	%rax,%rbx
+.Lcmov0:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov1			
+	movq	%rbx,%rax
+.Lcmov1:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov2			
+	movq	%rax,%rbx
+.Lcmov2:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov3			
+	movq	%rbx,%rax
+.Lcmov3:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov4			
+	movq	%rax,%rbx
+.Lcmov4:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov5			
+	movq	%rbx,%rax
+.Lcmov5:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov6			
+	movq	%rax,%rbx
+.Lcmov6:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov7			
+	movq	%rbx,%rax
+.Lcmov7:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	leaq	-8(%r11),%r11
+	movl	%r8d,(%r13)
+	leaq	8(%r12),%r12
+	movl	%r9d,4(%r13)
+	leaq	8(%r13),%r13
+
+	testq	$-8,%r11
+	jnz	.Lcloop8
+	cmpq	$0,%r11
+	jne	.Lcloop1
+	jmp	.Lexit
+.align	16
+.Lcloop1:
+	addb	%al,%cl
+	movzbl	%cl,%ecx
+	movzbl	(%rdi,%rcx,1),%edx
+	movb	%al,(%rdi,%rcx,1)
+	movb	%dl,(%rdi,%r10,1)
+	addb	%al,%dl
+	addb	$1,%r10b
+	movzbl	%dl,%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%rdx,1),%edx
+	movzbl	(%rdi,%r10,1),%eax
+	xorb	(%r12),%dl
+	leaq	1(%r12),%r12
+	movb	%dl,(%r13)
+	leaq	1(%r13),%r13
+	subq	$1,%r11
+	jnz	.Lcloop1
+	jmp	.Lexit
+
+.align	16
+.Lexit:
+	subb	$1,%r10b
+	movl	%r10d,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	(%rsp),%r13
+	movq	8(%rsp),%r12
+	movq	16(%rsp),%rbx
+	addq	$24,%rsp
+.Lepilogue:
+	retq
+.size	RC4,.-RC4
+.globl	RC4_set_key
+.type	RC4_set_key,@function
+.align	16
+RC4_set_key:
+	endbr64
+	leaq	8(%rdi),%rdi
+	leaq	(%rdx,%rsi,1),%rdx
+	negq	%rsi
+	movq	%rsi,%rcx
+	xorl	%eax,%eax
+	xorq	%r9,%r9
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+
+	movl	OPENSSL_ia32cap_P(%rip),%r8d
+	btl	$IA32CAP_BIT0_INTELP4,%r8d
+	jc	.Lc1stloop
+	jmp	.Lw1stloop
+
+.align	16
+.Lw1stloop:
+	movl	%eax,(%rdi,%rax,4)
+	addb	$1,%al
+	jnc	.Lw1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.align	16
+.Lw2ndloop:
+	movl	(%rdi,%r9,4),%r10d
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movl	(%rdi,%r8,4),%r11d
+	cmovzq	%rcx,%rsi
+	movl	%r10d,(%rdi,%r8,4)
+	movl	%r11d,(%rdi,%r9,4)
+	addb	$1,%r9b
+	jnc	.Lw2ndloop
+	jmp	.Lexit_key
+
+.align	16
+.Lc1stloop:
+	movb	%al,(%rdi,%rax,1)
+	addb	$1,%al
+	jnc	.Lc1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.align	16
+.Lc2ndloop:
+	movb	(%rdi,%r9,1),%r10b
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movb	(%rdi,%r8,1),%r11b
+	jnz	.Lcnowrap
+	movq	%rcx,%rsi
+.Lcnowrap:
+	movb	%r10b,(%rdi,%r8,1)
+	movb	%r11b,(%rdi,%r9,1)
+	addb	$1,%r9b
+	jnc	.Lc2ndloop
+	movl	$-1,256(%rdi)
+
+.align	16
+.Lexit_key:
+	xorl	%eax,%eax
+	movl	%eax,-8(%rdi)
+	movl	%eax,-4(%rdi)
+	retq
+.size	RC4_set_key,.-RC4_set_key
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/rc4/rc4-macosx-x86_64.S b/crypto/rc4/rc4-macosx-x86_64.S
new file mode 100644
index 0000000..50f40fd
--- /dev/null
+++ b/crypto/rc4/rc4-macosx-x86_64.S
@@ -0,0 +1,592 @@
+#include "x86_arch.h"
+.text	
+
+.private_extern	_OPENSSL_ia32cap_P
+
+.globl	_RC4
+
+.p2align	4
+_RC4:	orq	%rsi,%rsi
+	jne	L$entry
+	retq
+L$entry:
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+L$prologue:
+	movq	%rsi,%r11
+	movq	%rdx,%r12
+	movq	%rcx,%r13
+	xorq	%r10,%r10
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%r10b
+	movb	-4(%rdi),%cl
+	cmpl	$-1,256(%rdi)
+	je	L$RC4_CHAR
+	movl	_OPENSSL_ia32cap_P(%rip),%r8d
+	xorq	%rbx,%rbx
+	incb	%r10b
+	subq	%r10,%rbx
+	subq	%r12,%r13
+	movl	(%rdi,%r10,4),%eax
+	testq	$-16,%r11
+	jz	L$loop1
+	btl	$IA32CAP_BIT0_INTEL,%r8d
+	jc	L$intel
+	andq	$7,%rbx
+	leaq	1(%r10),%rsi
+	jz	L$oop8
+	subq	%rbx,%r11
+L$oop8_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	L$oop8_warmup
+
+	leaq	1(%r10),%rsi
+	jmp	L$oop8
+.p2align	4
+L$oop8:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	0(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,0(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,4(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	8(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,8(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	12(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,12(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	16(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,16(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	20(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,20(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	24(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,24(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%sil
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	-4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,28(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%r10b
+	rorq	$8,%r8
+	subq	$8,%r11
+
+	xorq	(%r12),%r8
+	movq	%r8,(%r13,%r12,1)
+	leaq	8(%r12),%r12
+
+	testq	$-8,%r11
+	jnz	L$oop8
+	cmpq	$0,%r11
+	jne	L$loop1
+	jmp	L$exit
+
+.p2align	4
+L$intel:
+	testq	$-32,%r11
+	jz	L$loop1
+	andq	$15,%rbx
+	jz	L$oop16_is_hot
+	subq	%rbx,%r11
+L$oop16_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	L$oop16_warmup
+
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	movb	%bl,%cl
+
+L$oop16_is_hot:
+	leaq	(%rdi,%r10,4),%rsi
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	jmp	L$oop16_enter
+.p2align	4
+L$oop16:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm2
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	pxor	%xmm1,%xmm2
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+L$oop16_enter:
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm1,%xmm1
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	pinsrw	$0,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+	addb	$16,%r10b
+	movdqu	(%r12),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	leaq	(%rdi,%r10,4),%rsi
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+	movl	(%rsi),%eax
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	subq	$16,%r11
+	movb	%bl,%cl
+	testq	$-16,%r11
+	jnz	L$oop16
+
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+
+	cmpq	$0,%r11
+	jne	L$loop1
+	jmp	L$exit
+
+.p2align	4
+L$loop1:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%r11
+	jnz	L$loop1
+	jmp	L$exit
+
+.p2align	4
+L$RC4_CHAR:
+	addb	$1,%r10b
+	movzbl	(%rdi,%r10,1),%eax
+	testq	$-8,%r11
+	jz	L$cloop1
+	jmp	L$cloop8
+.p2align	4
+L$cloop8:
+	movl	(%r12),%r8d
+	movl	4(%r12),%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	L$cmov0			
+	movq	%rax,%rbx
+L$cmov0:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	L$cmov1			
+	movq	%rbx,%rax
+L$cmov1:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	L$cmov2			
+	movq	%rax,%rbx
+L$cmov2:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	L$cmov3			
+	movq	%rbx,%rax
+L$cmov3:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	L$cmov4			
+	movq	%rax,%rbx
+L$cmov4:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	L$cmov5			
+	movq	%rbx,%rax
+L$cmov5:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	L$cmov6			
+	movq	%rax,%rbx
+L$cmov6:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	L$cmov7			
+	movq	%rbx,%rax
+L$cmov7:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	leaq	-8(%r11),%r11
+	movl	%r8d,(%r13)
+	leaq	8(%r12),%r12
+	movl	%r9d,4(%r13)
+	leaq	8(%r13),%r13
+
+	testq	$-8,%r11
+	jnz	L$cloop8
+	cmpq	$0,%r11
+	jne	L$cloop1
+	jmp	L$exit
+.p2align	4
+L$cloop1:
+	addb	%al,%cl
+	movzbl	%cl,%ecx
+	movzbl	(%rdi,%rcx,1),%edx
+	movb	%al,(%rdi,%rcx,1)
+	movb	%dl,(%rdi,%r10,1)
+	addb	%al,%dl
+	addb	$1,%r10b
+	movzbl	%dl,%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%rdx,1),%edx
+	movzbl	(%rdi,%r10,1),%eax
+	xorb	(%r12),%dl
+	leaq	1(%r12),%r12
+	movb	%dl,(%r13)
+	leaq	1(%r13),%r13
+	subq	$1,%r11
+	jnz	L$cloop1
+	jmp	L$exit
+
+.p2align	4
+L$exit:
+	subb	$1,%r10b
+	movl	%r10d,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	(%rsp),%r13
+	movq	8(%rsp),%r12
+	movq	16(%rsp),%rbx
+	addq	$24,%rsp
+L$epilogue:
+	retq
+
+.globl	_RC4_set_key
+
+.p2align	4
+_RC4_set_key:
+	leaq	8(%rdi),%rdi
+	leaq	(%rdx,%rsi,1),%rdx
+	negq	%rsi
+	movq	%rsi,%rcx
+	xorl	%eax,%eax
+	xorq	%r9,%r9
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+
+	movl	_OPENSSL_ia32cap_P(%rip),%r8d
+	btl	$IA32CAP_BIT0_INTELP4,%r8d
+	jc	L$c1stloop
+	jmp	L$w1stloop
+
+.p2align	4
+L$w1stloop:
+	movl	%eax,(%rdi,%rax,4)
+	addb	$1,%al
+	jnc	L$w1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.p2align	4
+L$w2ndloop:
+	movl	(%rdi,%r9,4),%r10d
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movl	(%rdi,%r8,4),%r11d
+	cmovzq	%rcx,%rsi
+	movl	%r10d,(%rdi,%r8,4)
+	movl	%r11d,(%rdi,%r9,4)
+	addb	$1,%r9b
+	jnc	L$w2ndloop
+	jmp	L$exit_key
+
+.p2align	4
+L$c1stloop:
+	movb	%al,(%rdi,%rax,1)
+	addb	$1,%al
+	jnc	L$c1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.p2align	4
+L$c2ndloop:
+	movb	(%rdi,%r9,1),%r10b
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movb	(%rdi,%r8,1),%r11b
+	jnz	L$cnowrap
+	movq	%rcx,%rsi
+L$cnowrap:
+	movb	%r10b,(%rdi,%r8,1)
+	movb	%r11b,(%rdi,%r9,1)
+	addb	$1,%r9b
+	jnc	L$c2ndloop
+	movl	$-1,256(%rdi)
+
+.p2align	4
+L$exit_key:
+	xorl	%eax,%eax
+	movl	%eax,-8(%rdi)
+	movl	%eax,-4(%rdi)
+	retq
+
diff --git a/crypto/rc4/rc4-masm-x86_64.S b/crypto/rc4/rc4-masm-x86_64.S
new file mode 100644
index 0000000..1b37cdf
--- /dev/null
+++ b/crypto/rc4/rc4-masm-x86_64.S
@@ -0,0 +1,691 @@
+; 1 "crypto/rc4/rc4-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/rc4/rc4-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/rc4/rc4-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+EXTERN	OPENSSL_ia32cap_P:NEAR
+
+
+PUBLIC	RC4
+
+ALIGN	16
+RC4	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_RC4::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+	or	rsi,rsi
+	jne	$L$entry
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$entry::
+	push	rbx
+	push	r12
+	push	r13
+$L$prologue::
+	mov	r11,rsi
+	mov	r12,rdx
+	mov	r13,rcx
+	xor	r10,r10
+	xor	rcx,rcx
+
+	lea	rdi,QWORD PTR[8+rdi]
+	mov	r10b,BYTE PTR[((-8))+rdi]
+	mov	cl,BYTE PTR[((-4))+rdi]
+	cmp	DWORD PTR[256+rdi],-1
+	je	$L$RC4_CHAR
+	mov	r8d,DWORD PTR[OPENSSL_ia32cap_P]
+	xor	rbx,rbx
+	inc	r10b
+	sub	rbx,r10
+	sub	r13,r12
+	mov	eax,DWORD PTR[r10*4+rdi]
+	test	r11,-16
+	jz	$L$loop1
+	bt	r8d,30
+	jc	$L$intel
+	and	rbx,7
+	lea	rsi,QWORD PTR[1+r10]
+	jz	$L$oop8
+	sub	r11,rbx
+$L$oop8_warmup::
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	DWORD PTR[r10*4+rdi],edx
+	add	al,dl
+	inc	r10b
+	mov	edx,DWORD PTR[rax*4+rdi]
+	mov	eax,DWORD PTR[r10*4+rdi]
+	xor	dl,BYTE PTR[r12]
+	mov	BYTE PTR[r12*1+r13],dl
+	lea	r12,QWORD PTR[1+r12]
+	dec	rbx
+	jnz	$L$oop8_warmup
+
+	lea	rsi,QWORD PTR[1+r10]
+	jmp	$L$oop8
+ALIGN	16
+$L$oop8::
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	ebx,DWORD PTR[rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[r10*4+rdi],edx
+	add	dl,al
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,bl
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	mov	eax,DWORD PTR[4+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[4+r10*4+rdi],edx
+	add	dl,bl
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	ebx,DWORD PTR[8+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[8+r10*4+rdi],edx
+	add	dl,al
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,bl
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	mov	eax,DWORD PTR[12+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[12+r10*4+rdi],edx
+	add	dl,bl
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	ebx,DWORD PTR[16+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[16+r10*4+rdi],edx
+	add	dl,al
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,bl
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	mov	eax,DWORD PTR[20+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[20+r10*4+rdi],edx
+	add	dl,bl
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	ebx,DWORD PTR[24+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[24+r10*4+rdi],edx
+	add	dl,al
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	sil,8
+	add	cl,bl
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	mov	eax,DWORD PTR[((-4))+rsi*4+rdi]
+	ror	r8,8
+	mov	DWORD PTR[28+r10*4+rdi],edx
+	add	dl,bl
+	mov	r8b,BYTE PTR[rdx*4+rdi]
+	add	r10b,8
+	ror	r8,8
+	sub	r11,8
+
+	xor	r8,QWORD PTR[r12]
+	mov	QWORD PTR[r12*1+r13],r8
+	lea	r12,QWORD PTR[8+r12]
+
+	test	r11,-8
+	jnz	$L$oop8
+	cmp	r11,0
+	jne	$L$loop1
+	jmp	$L$exit
+
+ALIGN	16
+$L$intel::
+	test	r11,-32
+	jz	$L$loop1
+	and	rbx,15
+	jz	$L$oop16_is_hot
+	sub	r11,rbx
+$L$oop16_warmup::
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	DWORD PTR[r10*4+rdi],edx
+	add	al,dl
+	inc	r10b
+	mov	edx,DWORD PTR[rax*4+rdi]
+	mov	eax,DWORD PTR[r10*4+rdi]
+	xor	dl,BYTE PTR[r12]
+	mov	BYTE PTR[r12*1+r13],dl
+	lea	r12,QWORD PTR[1+r12]
+	dec	rbx
+	jnz	$L$oop16_warmup
+
+	mov	rbx,rcx
+	xor	rcx,rcx
+	mov	cl,bl
+
+$L$oop16_is_hot::
+	lea	rsi,QWORD PTR[r10*4+rdi]
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	pxor	xmm0,xmm0
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[4+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],0
+	jmp	$L$oop16_enter
+ALIGN	16
+$L$oop16::
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	pxor	xmm2,xmm0
+	psllq	xmm1,8
+	pxor	xmm0,xmm0
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[4+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[rsi],edx
+	pxor	xmm2,xmm1
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],0
+	movdqu	XMMWORD PTR[r12*1+r13],xmm2
+	lea	r12,QWORD PTR[16+r12]
+$L$oop16_enter::
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	pxor	xmm1,xmm1
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[8+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[4+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],0
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[12+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[8+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[16+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[12+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[20+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[16+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],2
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[24+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[20+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],2
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[28+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[24+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],3
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[32+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[28+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],3
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[36+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[32+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],4
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[40+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[36+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],4
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[44+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[40+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],5
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[48+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[44+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],5
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[52+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[48+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],6
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	mov	eax,DWORD PTR[56+rsi]
+	movzx	ebx,bl
+	mov	DWORD PTR[52+rsi],edx
+	add	cl,al
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],6
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	add	al,dl
+	mov	ebx,DWORD PTR[60+rsi]
+	movzx	eax,al
+	mov	DWORD PTR[56+rsi],edx
+	add	cl,bl
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],7
+	add	r10b,16
+	movdqu	xmm2,XMMWORD PTR[r12]
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	add	bl,dl
+	movzx	ebx,bl
+	mov	DWORD PTR[60+rsi],edx
+	lea	rsi,QWORD PTR[r10*4+rdi]
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],7
+	mov	eax,DWORD PTR[rsi]
+	mov	rbx,rcx
+	xor	rcx,rcx
+	sub	r11,16
+	mov	cl,bl
+	test	r11,-16
+	jnz	$L$oop16
+
+	psllq	xmm1,8
+	pxor	xmm2,xmm0
+	pxor	xmm2,xmm1
+	movdqu	XMMWORD PTR[r12*1+r13],xmm2
+	lea	r12,QWORD PTR[16+r12]
+
+	cmp	r11,0
+	jne	$L$loop1
+	jmp	$L$exit
+
+ALIGN	16
+$L$loop1::
+	add	cl,al
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	mov	DWORD PTR[rcx*4+rdi],eax
+	mov	DWORD PTR[r10*4+rdi],edx
+	add	al,dl
+	inc	r10b
+	mov	edx,DWORD PTR[rax*4+rdi]
+	mov	eax,DWORD PTR[r10*4+rdi]
+	xor	dl,BYTE PTR[r12]
+	mov	BYTE PTR[r12*1+r13],dl
+	lea	r12,QWORD PTR[1+r12]
+	dec	r11
+	jnz	$L$loop1
+	jmp	$L$exit
+
+ALIGN	16
+$L$RC4_CHAR::
+	add	r10b,1
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	test	r11,-8
+	jz	$L$cloop1
+	jmp	$L$cloop8
+ALIGN	16
+$L$cloop8::
+	mov	r8d,DWORD PTR[r12]
+	mov	r9d,DWORD PTR[4+r12]
+	add	cl,al
+	lea	rsi,QWORD PTR[1+r10]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	esi,sil
+	movzx	ebx,BYTE PTR[rsi*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],al
+	cmp	rcx,rsi
+	mov	BYTE PTR[r10*1+rdi],dl
+	jne	$L$cmov0			
+	mov	rbx,rax
+$L$cmov0::
+	add	dl,al
+	xor	r8b,BYTE PTR[rdx*1+rdi]
+	ror	r8d,8
+	add	cl,bl
+	lea	r10,QWORD PTR[1+rsi]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	r10d,r10b
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],bl
+	cmp	rcx,r10
+	mov	BYTE PTR[rsi*1+rdi],dl
+	jne	$L$cmov1			
+	mov	rax,rbx
+$L$cmov1::
+	add	dl,bl
+	xor	r8b,BYTE PTR[rdx*1+rdi]
+	ror	r8d,8
+	add	cl,al
+	lea	rsi,QWORD PTR[1+r10]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	esi,sil
+	movzx	ebx,BYTE PTR[rsi*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],al
+	cmp	rcx,rsi
+	mov	BYTE PTR[r10*1+rdi],dl
+	jne	$L$cmov2			
+	mov	rbx,rax
+$L$cmov2::
+	add	dl,al
+	xor	r8b,BYTE PTR[rdx*1+rdi]
+	ror	r8d,8
+	add	cl,bl
+	lea	r10,QWORD PTR[1+rsi]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	r10d,r10b
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],bl
+	cmp	rcx,r10
+	mov	BYTE PTR[rsi*1+rdi],dl
+	jne	$L$cmov3			
+	mov	rax,rbx
+$L$cmov3::
+	add	dl,bl
+	xor	r8b,BYTE PTR[rdx*1+rdi]
+	ror	r8d,8
+	add	cl,al
+	lea	rsi,QWORD PTR[1+r10]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	esi,sil
+	movzx	ebx,BYTE PTR[rsi*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],al
+	cmp	rcx,rsi
+	mov	BYTE PTR[r10*1+rdi],dl
+	jne	$L$cmov4			
+	mov	rbx,rax
+$L$cmov4::
+	add	dl,al
+	xor	r9b,BYTE PTR[rdx*1+rdi]
+	ror	r9d,8
+	add	cl,bl
+	lea	r10,QWORD PTR[1+rsi]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	r10d,r10b
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],bl
+	cmp	rcx,r10
+	mov	BYTE PTR[rsi*1+rdi],dl
+	jne	$L$cmov5			
+	mov	rax,rbx
+$L$cmov5::
+	add	dl,bl
+	xor	r9b,BYTE PTR[rdx*1+rdi]
+	ror	r9d,8
+	add	cl,al
+	lea	rsi,QWORD PTR[1+r10]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	esi,sil
+	movzx	ebx,BYTE PTR[rsi*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],al
+	cmp	rcx,rsi
+	mov	BYTE PTR[r10*1+rdi],dl
+	jne	$L$cmov6			
+	mov	rbx,rax
+$L$cmov6::
+	add	dl,al
+	xor	r9b,BYTE PTR[rdx*1+rdi]
+	ror	r9d,8
+	add	cl,bl
+	lea	r10,QWORD PTR[1+rsi]
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	movzx	r10d,r10b
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],bl
+	cmp	rcx,r10
+	mov	BYTE PTR[rsi*1+rdi],dl
+	jne	$L$cmov7			
+	mov	rax,rbx
+$L$cmov7::
+	add	dl,bl
+	xor	r9b,BYTE PTR[rdx*1+rdi]
+	ror	r9d,8
+	lea	r11,QWORD PTR[((-8))+r11]
+	mov	DWORD PTR[r13],r8d
+	lea	r12,QWORD PTR[8+r12]
+	mov	DWORD PTR[4+r13],r9d
+	lea	r13,QWORD PTR[8+r13]
+
+	test	r11,-8
+	jnz	$L$cloop8
+	cmp	r11,0
+	jne	$L$cloop1
+	jmp	$L$exit
+ALIGN	16
+$L$cloop1::
+	add	cl,al
+	movzx	ecx,cl
+	movzx	edx,BYTE PTR[rcx*1+rdi]
+	mov	BYTE PTR[rcx*1+rdi],al
+	mov	BYTE PTR[r10*1+rdi],dl
+	add	dl,al
+	add	r10b,1
+	movzx	edx,dl
+	movzx	r10d,r10b
+	movzx	edx,BYTE PTR[rdx*1+rdi]
+	movzx	eax,BYTE PTR[r10*1+rdi]
+	xor	dl,BYTE PTR[r12]
+	lea	r12,QWORD PTR[1+r12]
+	mov	BYTE PTR[r13],dl
+	lea	r13,QWORD PTR[1+r13]
+	sub	r11,1
+	jnz	$L$cloop1
+	jmp	$L$exit
+
+ALIGN	16
+$L$exit::
+	sub	r10b,1
+	mov	DWORD PTR[((-8))+rdi],r10d
+	mov	DWORD PTR[((-4))+rdi],ecx
+
+	mov	r13,QWORD PTR[rsp]
+	mov	r12,QWORD PTR[8+rsp]
+	mov	rbx,QWORD PTR[16+rsp]
+	add	rsp,24
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_RC4::
+RC4	ENDP
+PUBLIC	RC4_set_key
+
+ALIGN	16
+RC4_set_key	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_RC4_set_key::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	lea	rdi,QWORD PTR[8+rdi]
+	lea	rdx,QWORD PTR[rsi*1+rdx]
+	neg	rsi
+	mov	rcx,rsi
+	xor	eax,eax
+	xor	r9,r9
+	xor	r10,r10
+	xor	r11,r11
+
+	mov	r8d,DWORD PTR[OPENSSL_ia32cap_P]
+	bt	r8d,20
+	jc	$L$c1stloop
+	jmp	$L$w1stloop
+
+ALIGN	16
+$L$w1stloop::
+	mov	DWORD PTR[rax*4+rdi],eax
+	add	al,1
+	jnc	$L$w1stloop
+
+	xor	r9,r9
+	xor	r8,r8
+ALIGN	16
+$L$w2ndloop::
+	mov	r10d,DWORD PTR[r9*4+rdi]
+	add	r8b,BYTE PTR[rsi*1+rdx]
+	add	r8b,r10b
+	add	rsi,1
+	mov	r11d,DWORD PTR[r8*4+rdi]
+	cmovz	rsi,rcx
+	mov	DWORD PTR[r8*4+rdi],r10d
+	mov	DWORD PTR[r9*4+rdi],r11d
+	add	r9b,1
+	jnc	$L$w2ndloop
+	jmp	$L$exit_key
+
+ALIGN	16
+$L$c1stloop::
+	mov	BYTE PTR[rax*1+rdi],al
+	add	al,1
+	jnc	$L$c1stloop
+
+	xor	r9,r9
+	xor	r8,r8
+ALIGN	16
+$L$c2ndloop::
+	mov	r10b,BYTE PTR[r9*1+rdi]
+	add	r8b,BYTE PTR[rsi*1+rdx]
+	add	r8b,r10b
+	add	rsi,1
+	mov	r11b,BYTE PTR[r8*1+rdi]
+	jnz	$L$cnowrap
+	mov	rsi,rcx
+$L$cnowrap::
+	mov	BYTE PTR[r8*1+rdi],r10b
+	mov	BYTE PTR[r9*1+rdi],r11b
+	add	r9b,1
+	jnc	$L$c2ndloop
+	mov	DWORD PTR[256+rdi],-1
+
+ALIGN	16
+$L$exit_key::
+	xor	eax,eax
+	mov	DWORD PTR[((-8))+rdi],eax
+	mov	DWORD PTR[((-4))+rdi],eax
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_RC4_set_key::
+RC4_set_key	ENDP
+
+.text$	ENDS
+END
+
diff --git a/crypto/rc4/rc4-md5-elf-x86_64.S b/crypto/rc4/rc4-md5-elf-x86_64.S
new file mode 100644
index 0000000..9381ff7
--- /dev/null
+++ b/crypto/rc4/rc4-md5-elf-x86_64.S
@@ -0,0 +1,1264 @@
+#include "x86_arch.h"
+.text	
+.align	16
+
+.globl	rc4_md5_enc
+.type	rc4_md5_enc,@function
+rc4_md5_enc:
+	endbr64
+	cmpq	$0,%r9
+	je	.Labort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$40,%rsp
+.Lbody:
+	movq	%rcx,%r11
+	movq	%r9,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%r8,%r15
+	xorq	%rbp,%rbp
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%bpl
+	movb	-4(%rdi),%cl
+
+	incb	%bpl
+	subq	%r13,%r14
+	movl	(%rdi,%rbp,4),%eax
+	addb	%al,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	shlq	$6,%r12
+	addq	%r15,%r12
+	movq	%r12,16(%rsp)
+
+	movq	%r11,24(%rsp)
+	movl	0(%r11),%r8d
+	movl	4(%r11),%r9d
+	movl	8(%r11),%r10d
+	movl	12(%r11),%r11d
+	jmp	.Loop
+
+.align	16
+.Loop:
+	movl	%r8d,0(%rsp)
+	movl	%r9d,4(%rsp)
+	movl	%r10d,8(%rsp)
+	movl	%r11d,%r12d
+	movl	%r11d,12(%rsp)
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$3614090360,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	4(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$3905402710,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$606105819,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	12(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$3250441966,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$4118548399,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	20(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1200080426,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$2821735955,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	28(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$4249261313,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$1770035416,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	36(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$2336552879,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$4294925233,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	44(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$2304563134,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$1804603682,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	52(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$4254626195,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$2792965006,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	(%r13),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	60(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$1236535329,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4129170786,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	24(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$3225465664,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$643717713,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	0(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$3921069994,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$3593408605,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	40(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$38016083,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$3634488961,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	16(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$3889429448,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$568446438,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	56(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$3275163606,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$4107603335,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	32(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1163531501,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$2850285829,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	8(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$4243563512,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$1735328473,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	16(%r13),%xmm3
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	48(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$2368359562,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$4294588738,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	32(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$2272392833,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$1839030562,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	56(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$4259657740,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$2763975236,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	16(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1272893353,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$4139469664,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	40(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$3200236656,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$681279174,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	0(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$3936430074,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$3572445317,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	24(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$76029189,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$3654602809,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	48(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$3873151461,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$530742520,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	32(%r13),%xmm4
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	8(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$3299628645,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,60(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm4
+	pxor	%xmm1,%xmm4
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4096336452,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	28(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$1126891415,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$2878612391,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	20(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$4237533241,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$1700485571,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	12(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$2399980690,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$4293915773,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	4(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$2240044497,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$1873313359,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	60(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$4264355552,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$2734768916,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	52(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1309151649,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$4149444226,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	44(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$3174756917,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$718787259,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	48(%r13),%xmm5
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	36(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$3951481745,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rbp,%rsi
+	xorq	%rbp,%rbp
+	movb	%sil,%bpl
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm5
+	pxor	%xmm1,%xmm5
+	addl	0(%rsp),%r8d
+	addl	4(%rsp),%r9d
+	addl	8(%rsp),%r10d
+	addl	12(%rsp),%r11d
+
+	movdqu	%xmm2,(%r14,%r13,1)
+	movdqu	%xmm3,16(%r14,%r13,1)
+	movdqu	%xmm4,32(%r14,%r13,1)
+	movdqu	%xmm5,48(%r14,%r13,1)
+	leaq	64(%r15),%r15
+	leaq	64(%r13),%r13
+	cmpq	16(%rsp),%r15
+	jb	.Loop
+
+	movq	24(%rsp),%r12
+	subb	%al,%cl
+	movl	%r8d,0(%r12)
+	movl	%r9d,4(%r12)
+	movl	%r10d,8(%r12)
+	movl	%r11d,12(%r12)
+	subb	$1,%bpl
+	movl	%ebp,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	40(%rsp),%r15
+	movq	48(%rsp),%r14
+	movq	56(%rsp),%r13
+	movq	64(%rsp),%r12
+	movq	72(%rsp),%rbp
+	movq	80(%rsp),%rbx
+	leaq	88(%rsp),%rsp
+.Lepilogue:
+.Labort:
+	retq
+.size	rc4_md5_enc,.-rc4_md5_enc
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/rc4/rc4-md5-macosx-x86_64.S b/crypto/rc4/rc4-md5-macosx-x86_64.S
new file mode 100644
index 0000000..a8f6955
--- /dev/null
+++ b/crypto/rc4/rc4-md5-macosx-x86_64.S
@@ -0,0 +1,1260 @@
+#include "x86_arch.h"
+.text	
+.p2align	4
+
+.globl	_rc4_md5_enc
+
+_rc4_md5_enc:
+	cmpq	$0,%r9
+	je	L$abort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$40,%rsp
+L$body:
+	movq	%rcx,%r11
+	movq	%r9,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%r8,%r15
+	xorq	%rbp,%rbp
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%bpl
+	movb	-4(%rdi),%cl
+
+	incb	%bpl
+	subq	%r13,%r14
+	movl	(%rdi,%rbp,4),%eax
+	addb	%al,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	shlq	$6,%r12
+	addq	%r15,%r12
+	movq	%r12,16(%rsp)
+
+	movq	%r11,24(%rsp)
+	movl	0(%r11),%r8d
+	movl	4(%r11),%r9d
+	movl	8(%r11),%r10d
+	movl	12(%r11),%r11d
+	jmp	L$oop
+
+.p2align	4
+L$oop:
+	movl	%r8d,0(%rsp)
+	movl	%r9d,4(%rsp)
+	movl	%r10d,8(%rsp)
+	movl	%r11d,%r12d
+	movl	%r11d,12(%rsp)
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$3614090360,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	4(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$3905402710,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$606105819,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	12(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$3250441966,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$4118548399,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	20(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1200080426,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$2821735955,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	28(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$4249261313,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$1770035416,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	36(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$2336552879,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$4294925233,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	44(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$2304563134,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$1804603682,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	52(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$4254626195,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$2792965006,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	(%r13),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	60(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$1236535329,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4129170786,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	24(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$3225465664,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$643717713,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	0(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$3921069994,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$3593408605,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	40(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$38016083,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$3634488961,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	16(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$3889429448,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$568446438,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	56(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$3275163606,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$4107603335,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	32(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1163531501,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$2850285829,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	8(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$4243563512,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$1735328473,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	16(%r13),%xmm3
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	48(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$2368359562,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$4294588738,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	32(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$2272392833,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$1839030562,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	56(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$4259657740,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$2763975236,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	16(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1272893353,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$4139469664,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	40(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$3200236656,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$681279174,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	0(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$3936430074,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$3572445317,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	24(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$76029189,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$3654602809,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	48(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$3873151461,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$530742520,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	32(%r13),%xmm4
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	8(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$3299628645,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,60(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm4
+	pxor	%xmm1,%xmm4
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4096336452,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	28(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$1126891415,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$2878612391,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	20(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$4237533241,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$1700485571,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	12(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$2399980690,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$4293915773,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	4(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$2240044497,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$1873313359,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	60(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$4264355552,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$2734768916,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	52(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1309151649,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$4149444226,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	44(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$3174756917,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$718787259,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	48(%r13),%xmm5
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	36(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$3951481745,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rbp,%rsi
+	xorq	%rbp,%rbp
+	movb	%sil,%bpl
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm5
+	pxor	%xmm1,%xmm5
+	addl	0(%rsp),%r8d
+	addl	4(%rsp),%r9d
+	addl	8(%rsp),%r10d
+	addl	12(%rsp),%r11d
+
+	movdqu	%xmm2,(%r14,%r13,1)
+	movdqu	%xmm3,16(%r14,%r13,1)
+	movdqu	%xmm4,32(%r14,%r13,1)
+	movdqu	%xmm5,48(%r14,%r13,1)
+	leaq	64(%r15),%r15
+	leaq	64(%r13),%r13
+	cmpq	16(%rsp),%r15
+	jb	L$oop
+
+	movq	24(%rsp),%r12
+	subb	%al,%cl
+	movl	%r8d,0(%r12)
+	movl	%r9d,4(%r12)
+	movl	%r10d,8(%r12)
+	movl	%r11d,12(%r12)
+	subb	$1,%bpl
+	movl	%ebp,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	40(%rsp),%r15
+	movq	48(%rsp),%r14
+	movq	56(%rsp),%r13
+	movq	64(%rsp),%r12
+	movq	72(%rsp),%rbp
+	movq	80(%rsp),%rbx
+	leaq	88(%rsp),%rsp
+L$epilogue:
+L$abort:
+	retq
+
diff --git a/crypto/rc4/rc4-md5-masm-x86_64.S b/crypto/rc4/rc4-md5-masm-x86_64.S
new file mode 100644
index 0000000..b360fe4
--- /dev/null
+++ b/crypto/rc4/rc4-md5-masm-x86_64.S
@@ -0,0 +1,1347 @@
+; 1 "crypto/rc4/rc4-md5-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/rc4/rc4-md5-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/rc4/rc4-md5-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+ALIGN	16
+
+PUBLIC	rc4_md5_enc
+
+rc4_md5_enc	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_rc4_md5_enc::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD PTR[40+rsp]
+	mov	r9,QWORD PTR[48+rsp]
+
+
+	cmp	r9,0
+	je	$L$abort
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	sub	rsp,40
+$L$body::
+	mov	r11,rcx
+	mov	r12,r9
+	mov	r13,rsi
+	mov	r14,rdx
+	mov	r15,r8
+	xor	rbp,rbp
+	xor	rcx,rcx
+
+	lea	rdi,QWORD PTR[8+rdi]
+	mov	bpl,BYTE PTR[((-8))+rdi]
+	mov	cl,BYTE PTR[((-4))+rdi]
+
+	inc	bpl
+	sub	r14,r13
+	mov	eax,DWORD PTR[rbp*4+rdi]
+	add	cl,al
+	lea	rsi,QWORD PTR[rbp*4+rdi]
+	shl	r12,6
+	add	r12,r15
+	mov	QWORD PTR[16+rsp],r12
+
+	mov	QWORD PTR[24+rsp],r11
+	mov	r8d,DWORD PTR[r11]
+	mov	r9d,DWORD PTR[4+r11]
+	mov	r10d,DWORD PTR[8+r11]
+	mov	r11d,DWORD PTR[12+r11]
+	jmp	$L$oop
+
+ALIGN	16
+$L$oop::
+	mov	DWORD PTR[rsp],r8d
+	mov	DWORD PTR[4+rsp],r9d
+	mov	DWORD PTR[8+rsp],r10d
+	mov	r12d,r11d
+	mov	DWORD PTR[12+rsp],r11d
+	pxor	xmm0,xmm0
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r8d,DWORD PTR[r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[4+rsi]
+	add	r8d,3614090360
+	xor	r12d,r11d
+	movzx	eax,al
+	mov	DWORD PTR[rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,7
+	mov	r12d,r10d
+	movd	xmm0,DWORD PTR[rax*4+rdi]
+
+	add	r8d,r9d
+	pxor	xmm1,xmm1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r11d,DWORD PTR[4+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[8+rsi]
+	add	r11d,3905402710
+	xor	r12d,r10d
+	movzx	ebx,bl
+	mov	DWORD PTR[4+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,12
+	mov	r12d,r9d
+	movd	xmm1,DWORD PTR[rbx*4+rdi]
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r10d,DWORD PTR[8+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[12+rsi]
+	add	r10d,606105819
+	xor	r12d,r9d
+	movzx	eax,al
+	mov	DWORD PTR[8+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,17
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],1
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r9d,DWORD PTR[12+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[16+rsi]
+	add	r9d,3250441966
+	xor	r12d,r8d
+	movzx	ebx,bl
+	mov	DWORD PTR[12+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,22
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],1
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r8d,DWORD PTR[16+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[20+rsi]
+	add	r8d,4118548399
+	xor	r12d,r11d
+	movzx	eax,al
+	mov	DWORD PTR[16+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,7
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],2
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r11d,DWORD PTR[20+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[24+rsi]
+	add	r11d,1200080426
+	xor	r12d,r10d
+	movzx	ebx,bl
+	mov	DWORD PTR[20+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,12
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],2
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r10d,DWORD PTR[24+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[28+rsi]
+	add	r10d,2821735955
+	xor	r12d,r9d
+	movzx	eax,al
+	mov	DWORD PTR[24+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,17
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],3
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r9d,DWORD PTR[28+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[32+rsi]
+	add	r9d,4249261313
+	xor	r12d,r8d
+	movzx	ebx,bl
+	mov	DWORD PTR[28+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,22
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],3
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r8d,DWORD PTR[32+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[36+rsi]
+	add	r8d,1770035416
+	xor	r12d,r11d
+	movzx	eax,al
+	mov	DWORD PTR[32+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,7
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],4
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r11d,DWORD PTR[36+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[40+rsi]
+	add	r11d,2336552879
+	xor	r12d,r10d
+	movzx	ebx,bl
+	mov	DWORD PTR[36+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,12
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],4
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r10d,DWORD PTR[40+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[44+rsi]
+	add	r10d,4294925233
+	xor	r12d,r9d
+	movzx	eax,al
+	mov	DWORD PTR[40+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,17
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],5
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r9d,DWORD PTR[44+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[48+rsi]
+	add	r9d,2304563134
+	xor	r12d,r8d
+	movzx	ebx,bl
+	mov	DWORD PTR[44+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,22
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],5
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r8d,DWORD PTR[48+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[52+rsi]
+	add	r8d,1804603682
+	xor	r12d,r11d
+	movzx	eax,al
+	mov	DWORD PTR[48+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,7
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],6
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r11d,DWORD PTR[52+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[56+rsi]
+	add	r11d,4254626195
+	xor	r12d,r10d
+	movzx	ebx,bl
+	mov	DWORD PTR[52+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,12
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],6
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r10d,DWORD PTR[56+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[60+rsi]
+	add	r10d,2792965006
+	xor	r12d,r9d
+	movzx	eax,al
+	mov	DWORD PTR[56+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,17
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],7
+
+	add	r10d,r11d
+	movdqu	xmm2,XMMWORD PTR[r13]
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r9d,DWORD PTR[60+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[64+rsi]
+	add	r9d,1236535329
+	xor	r12d,r8d
+	movzx	ebx,bl
+	mov	DWORD PTR[60+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,22
+	mov	r12d,r10d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],7
+
+	add	r9d,r10d
+	psllq	xmm1,8
+	pxor	xmm2,xmm0
+	pxor	xmm2,xmm1
+	pxor	xmm0,xmm0
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r8d,DWORD PTR[4+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[68+rsi]
+	add	r8d,4129170786
+	xor	r12d,r10d
+	movzx	eax,al
+	mov	DWORD PTR[64+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,5
+	mov	r12d,r9d
+	movd	xmm0,DWORD PTR[rax*4+rdi]
+
+	add	r8d,r9d
+	pxor	xmm1,xmm1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r11d,DWORD PTR[24+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[72+rsi]
+	add	r11d,3225465664
+	xor	r12d,r9d
+	movzx	ebx,bl
+	mov	DWORD PTR[68+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,9
+	mov	r12d,r8d
+	movd	xmm1,DWORD PTR[rbx*4+rdi]
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r10d,DWORD PTR[44+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[76+rsi]
+	add	r10d,643717713
+	xor	r12d,r8d
+	movzx	eax,al
+	mov	DWORD PTR[72+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,14
+	mov	r12d,r11d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],1
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r9d,DWORD PTR[r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[80+rsi]
+	add	r9d,3921069994
+	xor	r12d,r11d
+	movzx	ebx,bl
+	mov	DWORD PTR[76+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,20
+	mov	r12d,r10d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],1
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r8d,DWORD PTR[20+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[84+rsi]
+	add	r8d,3593408605
+	xor	r12d,r10d
+	movzx	eax,al
+	mov	DWORD PTR[80+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,5
+	mov	r12d,r9d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],2
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r11d,DWORD PTR[40+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[88+rsi]
+	add	r11d,38016083
+	xor	r12d,r9d
+	movzx	ebx,bl
+	mov	DWORD PTR[84+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,9
+	mov	r12d,r8d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],2
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r10d,DWORD PTR[60+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[92+rsi]
+	add	r10d,3634488961
+	xor	r12d,r8d
+	movzx	eax,al
+	mov	DWORD PTR[88+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,14
+	mov	r12d,r11d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],3
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r9d,DWORD PTR[16+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[96+rsi]
+	add	r9d,3889429448
+	xor	r12d,r11d
+	movzx	ebx,bl
+	mov	DWORD PTR[92+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,20
+	mov	r12d,r10d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],3
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r8d,DWORD PTR[36+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[100+rsi]
+	add	r8d,568446438
+	xor	r12d,r10d
+	movzx	eax,al
+	mov	DWORD PTR[96+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,5
+	mov	r12d,r9d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],4
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r11d,DWORD PTR[56+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[104+rsi]
+	add	r11d,3275163606
+	xor	r12d,r9d
+	movzx	ebx,bl
+	mov	DWORD PTR[100+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,9
+	mov	r12d,r8d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],4
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r10d,DWORD PTR[12+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[108+rsi]
+	add	r10d,4107603335
+	xor	r12d,r8d
+	movzx	eax,al
+	mov	DWORD PTR[104+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,14
+	mov	r12d,r11d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],5
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r9d,DWORD PTR[32+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[112+rsi]
+	add	r9d,1163531501
+	xor	r12d,r11d
+	movzx	ebx,bl
+	mov	DWORD PTR[108+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,20
+	mov	r12d,r10d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],5
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r11d
+	add	r8d,DWORD PTR[52+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[116+rsi]
+	add	r8d,2850285829
+	xor	r12d,r10d
+	movzx	eax,al
+	mov	DWORD PTR[112+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,5
+	mov	r12d,r9d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],6
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r10d
+	add	r11d,DWORD PTR[8+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[120+rsi]
+	add	r11d,4243563512
+	xor	r12d,r9d
+	movzx	ebx,bl
+	mov	DWORD PTR[116+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,9
+	mov	r12d,r8d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],6
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	and	r12d,r9d
+	add	r10d,DWORD PTR[28+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[124+rsi]
+	add	r10d,1735328473
+	xor	r12d,r8d
+	movzx	eax,al
+	mov	DWORD PTR[120+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,14
+	mov	r12d,r11d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],7
+
+	add	r10d,r11d
+	movdqu	xmm3,XMMWORD PTR[16+r13]
+	add	bpl,32
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	and	r12d,r8d
+	add	r9d,DWORD PTR[48+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[rbp*4+rdi]
+	add	r9d,2368359562
+	xor	r12d,r11d
+	movzx	ebx,bl
+	mov	DWORD PTR[124+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,20
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],7
+
+	add	r9d,r10d
+	mov	rsi,rcx
+	xor	rcx,rcx
+	mov	cl,sil
+	lea	rsi,QWORD PTR[rbp*4+rdi]
+	psllq	xmm1,8
+	pxor	xmm3,xmm0
+	pxor	xmm3,xmm1
+	pxor	xmm0,xmm0
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r9d
+	add	r8d,DWORD PTR[20+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[4+rsi]
+	add	r8d,4294588738
+	movzx	eax,al
+	add	r8d,r12d
+	mov	DWORD PTR[rsi],edx
+	add	cl,bl
+	rol	r8d,4
+	mov	r12d,r10d
+	movd	xmm0,DWORD PTR[rax*4+rdi]
+
+	add	r8d,r9d
+	pxor	xmm1,xmm1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r8d
+	add	r11d,DWORD PTR[32+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[8+rsi]
+	add	r11d,2272392833
+	movzx	ebx,bl
+	add	r11d,r12d
+	mov	DWORD PTR[4+rsi],edx
+	add	cl,al
+	rol	r11d,11
+	mov	r12d,r9d
+	movd	xmm1,DWORD PTR[rbx*4+rdi]
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r11d
+	add	r10d,DWORD PTR[44+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[12+rsi]
+	add	r10d,1839030562
+	movzx	eax,al
+	add	r10d,r12d
+	mov	DWORD PTR[8+rsi],edx
+	add	cl,bl
+	rol	r10d,16
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],1
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r10d
+	add	r9d,DWORD PTR[56+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[16+rsi]
+	add	r9d,4259657740
+	movzx	ebx,bl
+	add	r9d,r12d
+	mov	DWORD PTR[12+rsi],edx
+	add	cl,al
+	rol	r9d,23
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],1
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r9d
+	add	r8d,DWORD PTR[4+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[20+rsi]
+	add	r8d,2763975236
+	movzx	eax,al
+	add	r8d,r12d
+	mov	DWORD PTR[16+rsi],edx
+	add	cl,bl
+	rol	r8d,4
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],2
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r8d
+	add	r11d,DWORD PTR[16+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[24+rsi]
+	add	r11d,1272893353
+	movzx	ebx,bl
+	add	r11d,r12d
+	mov	DWORD PTR[20+rsi],edx
+	add	cl,al
+	rol	r11d,11
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],2
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r11d
+	add	r10d,DWORD PTR[28+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[28+rsi]
+	add	r10d,4139469664
+	movzx	eax,al
+	add	r10d,r12d
+	mov	DWORD PTR[24+rsi],edx
+	add	cl,bl
+	rol	r10d,16
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],3
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r10d
+	add	r9d,DWORD PTR[40+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[32+rsi]
+	add	r9d,3200236656
+	movzx	ebx,bl
+	add	r9d,r12d
+	mov	DWORD PTR[28+rsi],edx
+	add	cl,al
+	rol	r9d,23
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],3
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r9d
+	add	r8d,DWORD PTR[52+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[36+rsi]
+	add	r8d,681279174
+	movzx	eax,al
+	add	r8d,r12d
+	mov	DWORD PTR[32+rsi],edx
+	add	cl,bl
+	rol	r8d,4
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],4
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r8d
+	add	r11d,DWORD PTR[r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[40+rsi]
+	add	r11d,3936430074
+	movzx	ebx,bl
+	add	r11d,r12d
+	mov	DWORD PTR[36+rsi],edx
+	add	cl,al
+	rol	r11d,11
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],4
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r11d
+	add	r10d,DWORD PTR[12+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[44+rsi]
+	add	r10d,3572445317
+	movzx	eax,al
+	add	r10d,r12d
+	mov	DWORD PTR[40+rsi],edx
+	add	cl,bl
+	rol	r10d,16
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],5
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r10d
+	add	r9d,DWORD PTR[24+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[48+rsi]
+	add	r9d,76029189
+	movzx	ebx,bl
+	add	r9d,r12d
+	mov	DWORD PTR[44+rsi],edx
+	add	cl,al
+	rol	r9d,23
+	mov	r12d,r11d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],5
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r9d
+	add	r8d,DWORD PTR[36+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[52+rsi]
+	add	r8d,3654602809
+	movzx	eax,al
+	add	r8d,r12d
+	mov	DWORD PTR[48+rsi],edx
+	add	cl,bl
+	rol	r8d,4
+	mov	r12d,r10d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],6
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r8d
+	add	r11d,DWORD PTR[48+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[56+rsi]
+	add	r11d,3873151461
+	movzx	ebx,bl
+	add	r11d,r12d
+	mov	DWORD PTR[52+rsi],edx
+	add	cl,al
+	rol	r11d,11
+	mov	r12d,r9d
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],6
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	xor	r12d,r11d
+	add	r10d,DWORD PTR[60+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[60+rsi]
+	add	r10d,530742520
+	movzx	eax,al
+	add	r10d,r12d
+	mov	DWORD PTR[56+rsi],edx
+	add	cl,bl
+	rol	r10d,16
+	mov	r12d,r8d
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],7
+
+	add	r10d,r11d
+	movdqu	xmm4,XMMWORD PTR[32+r13]
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	xor	r12d,r10d
+	add	r9d,DWORD PTR[8+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[64+rsi]
+	add	r9d,3299628645
+	movzx	ebx,bl
+	add	r9d,r12d
+	mov	DWORD PTR[60+rsi],edx
+	add	cl,al
+	rol	r9d,23
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],7
+
+	add	r9d,r10d
+	psllq	xmm1,8
+	pxor	xmm4,xmm0
+	pxor	xmm4,xmm1
+	pxor	xmm0,xmm0
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r9d
+	add	r8d,DWORD PTR[r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[68+rsi]
+	add	r8d,4096336452
+	movzx	eax,al
+	xor	r12d,r10d
+	mov	DWORD PTR[64+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,6
+	mov	r12d,-1
+	movd	xmm0,DWORD PTR[rax*4+rdi]
+
+	add	r8d,r9d
+	pxor	xmm1,xmm1
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r8d
+	add	r11d,DWORD PTR[28+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[72+rsi]
+	add	r11d,1126891415
+	movzx	ebx,bl
+	xor	r12d,r9d
+	mov	DWORD PTR[68+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,10
+	mov	r12d,-1
+	movd	xmm1,DWORD PTR[rbx*4+rdi]
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r11d
+	add	r10d,DWORD PTR[56+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[76+rsi]
+	add	r10d,2878612391
+	movzx	eax,al
+	xor	r12d,r8d
+	mov	DWORD PTR[72+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,15
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],1
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r10d
+	add	r9d,DWORD PTR[20+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[80+rsi]
+	add	r9d,4237533241
+	movzx	ebx,bl
+	xor	r12d,r11d
+	mov	DWORD PTR[76+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,21
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],1
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r9d
+	add	r8d,DWORD PTR[48+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[84+rsi]
+	add	r8d,1700485571
+	movzx	eax,al
+	xor	r12d,r10d
+	mov	DWORD PTR[80+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,6
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],2
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r8d
+	add	r11d,DWORD PTR[12+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[88+rsi]
+	add	r11d,2399980690
+	movzx	ebx,bl
+	xor	r12d,r9d
+	mov	DWORD PTR[84+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,10
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],2
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r11d
+	add	r10d,DWORD PTR[40+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[92+rsi]
+	add	r10d,4293915773
+	movzx	eax,al
+	xor	r12d,r8d
+	mov	DWORD PTR[88+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,15
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],3
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r10d
+	add	r9d,DWORD PTR[4+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[96+rsi]
+	add	r9d,2240044497
+	movzx	ebx,bl
+	xor	r12d,r11d
+	mov	DWORD PTR[92+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,21
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],3
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r9d
+	add	r8d,DWORD PTR[32+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[100+rsi]
+	add	r8d,1873313359
+	movzx	eax,al
+	xor	r12d,r10d
+	mov	DWORD PTR[96+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,6
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],4
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r8d
+	add	r11d,DWORD PTR[60+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[104+rsi]
+	add	r11d,4264355552
+	movzx	ebx,bl
+	xor	r12d,r9d
+	mov	DWORD PTR[100+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,10
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],4
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r11d
+	add	r10d,DWORD PTR[24+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[108+rsi]
+	add	r10d,2734768916
+	movzx	eax,al
+	xor	r12d,r8d
+	mov	DWORD PTR[104+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,15
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],5
+
+	add	r10d,r11d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r10d
+	add	r9d,DWORD PTR[52+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[112+rsi]
+	add	r9d,1309151649
+	movzx	ebx,bl
+	xor	r12d,r11d
+	mov	DWORD PTR[108+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,21
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],5
+
+	add	r9d,r10d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r11d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r9d
+	add	r8d,DWORD PTR[16+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[116+rsi]
+	add	r8d,4149444226
+	movzx	eax,al
+	xor	r12d,r10d
+	mov	DWORD PTR[112+rsi],edx
+	add	r8d,r12d
+	add	cl,bl
+	rol	r8d,6
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],6
+
+	add	r8d,r9d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r10d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r8d
+	add	r11d,DWORD PTR[44+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[120+rsi]
+	add	r11d,3174756917
+	movzx	ebx,bl
+	xor	r12d,r9d
+	mov	DWORD PTR[116+rsi],edx
+	add	r11d,r12d
+	add	cl,al
+	rol	r11d,10
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],6
+
+	add	r11d,r8d
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r9d
+	mov	DWORD PTR[rcx*4+rdi],eax
+	or	r12d,r11d
+	add	r10d,DWORD PTR[8+r15]
+	add	al,dl
+	mov	ebx,DWORD PTR[124+rsi]
+	add	r10d,718787259
+	movzx	eax,al
+	xor	r12d,r8d
+	mov	DWORD PTR[120+rsi],edx
+	add	r10d,r12d
+	add	cl,bl
+	rol	r10d,15
+	mov	r12d,-1
+	pinsrw	xmm0,WORD PTR[rax*4+rdi],7
+
+	add	r10d,r11d
+	movdqu	xmm5,XMMWORD PTR[48+r13]
+	add	bpl,32
+	mov	edx,DWORD PTR[rcx*4+rdi]
+	xor	r12d,r8d
+	mov	DWORD PTR[rcx*4+rdi],ebx
+	or	r12d,r10d
+	add	r9d,DWORD PTR[36+r15]
+	add	bl,dl
+	mov	eax,DWORD PTR[rbp*4+rdi]
+	add	r9d,3951481745
+	movzx	ebx,bl
+	xor	r12d,r11d
+	mov	DWORD PTR[124+rsi],edx
+	add	r9d,r12d
+	add	cl,al
+	rol	r9d,21
+	mov	r12d,-1
+	pinsrw	xmm1,WORD PTR[rbx*4+rdi],7
+
+	add	r9d,r10d
+	mov	rsi,rbp
+	xor	rbp,rbp
+	mov	bpl,sil
+	mov	rsi,rcx
+	xor	rcx,rcx
+	mov	cl,sil
+	lea	rsi,QWORD PTR[rbp*4+rdi]
+	psllq	xmm1,8
+	pxor	xmm5,xmm0
+	pxor	xmm5,xmm1
+	add	r8d,DWORD PTR[rsp]
+	add	r9d,DWORD PTR[4+rsp]
+	add	r10d,DWORD PTR[8+rsp]
+	add	r11d,DWORD PTR[12+rsp]
+
+	movdqu	XMMWORD PTR[r13*1+r14],xmm2
+	movdqu	XMMWORD PTR[16+r13*1+r14],xmm3
+	movdqu	XMMWORD PTR[32+r13*1+r14],xmm4
+	movdqu	XMMWORD PTR[48+r13*1+r14],xmm5
+	lea	r15,QWORD PTR[64+r15]
+	lea	r13,QWORD PTR[64+r13]
+	cmp	r15,QWORD PTR[16+rsp]
+	jb	$L$oop
+
+	mov	r12,QWORD PTR[24+rsp]
+	sub	cl,al
+	mov	DWORD PTR[r12],r8d
+	mov	DWORD PTR[4+r12],r9d
+	mov	DWORD PTR[8+r12],r10d
+	mov	DWORD PTR[12+r12],r11d
+	sub	bpl,1
+	mov	DWORD PTR[((-8))+rdi],ebp
+	mov	DWORD PTR[((-4))+rdi],ecx
+
+	mov	r15,QWORD PTR[40+rsp]
+	mov	r14,QWORD PTR[48+rsp]
+	mov	r13,QWORD PTR[56+rsp]
+	mov	r12,QWORD PTR[64+rsp]
+	mov	rbp,QWORD PTR[72+rsp]
+	mov	rbx,QWORD PTR[80+rsp]
+	lea	rsp,QWORD PTR[88+rsp]
+$L$epilogue::
+$L$abort::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_rc4_md5_enc::
+rc4_md5_enc	ENDP
+
+.text$	ENDS
+END
+
diff --git a/crypto/rc4/rc4-md5-mingw64-x86_64.S b/crypto/rc4/rc4-md5-mingw64-x86_64.S
new file mode 100644
index 0000000..e11d314
--- /dev/null
+++ b/crypto/rc4/rc4-md5-mingw64-x86_64.S
@@ -0,0 +1,1273 @@
+#include "x86_arch.h"
+.text	
+.p2align	4
+
+.globl	rc4_md5_enc
+.def	rc4_md5_enc;	.scl 2;	.type 32;	.endef
+rc4_md5_enc:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_rc4_md5_enc:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	movq	40(%rsp),%r8
+	movq	48(%rsp),%r9
+
+	cmpq	$0,%r9
+	je	.Labort
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$40,%rsp
+.Lbody:
+	movq	%rcx,%r11
+	movq	%r9,%r12
+	movq	%rsi,%r13
+	movq	%rdx,%r14
+	movq	%r8,%r15
+	xorq	%rbp,%rbp
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%bpl
+	movb	-4(%rdi),%cl
+
+	incb	%bpl
+	subq	%r13,%r14
+	movl	(%rdi,%rbp,4),%eax
+	addb	%al,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	shlq	$6,%r12
+	addq	%r15,%r12
+	movq	%r12,16(%rsp)
+
+	movq	%r11,24(%rsp)
+	movl	0(%r11),%r8d
+	movl	4(%r11),%r9d
+	movl	8(%r11),%r10d
+	movl	12(%r11),%r11d
+	jmp	.Loop
+
+.p2align	4
+.Loop:
+	movl	%r8d,0(%rsp)
+	movl	%r9d,4(%rsp)
+	movl	%r10d,8(%rsp)
+	movl	%r11d,%r12d
+	movl	%r11d,12(%rsp)
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$3614090360,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	4(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$3905402710,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$606105819,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	12(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$3250441966,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$4118548399,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	20(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1200080426,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$2821735955,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	28(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$4249261313,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$1770035416,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	36(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$2336552879,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$4294925233,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	44(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$2304563134,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$1804603682,%r8d
+	xorl	%r11d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$7,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	52(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$4254626195,%r11d
+	xorl	%r10d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$12,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$2792965006,%r10d
+	xorl	%r9d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$17,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	(%r13),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	60(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$1236535329,%r9d
+	xorl	%r8d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$22,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4129170786,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	24(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$3225465664,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$643717713,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	0(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$3921069994,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$3593408605,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	40(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$38016083,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$3634488961,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	16(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$3889429448,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$568446438,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	56(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$3275163606,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$4107603335,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	32(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1163531501,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r10d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r11d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$2850285829,%r8d
+	xorl	%r10d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$5,%r8d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r10d,%r12d
+	addl	8(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$4243563512,%r11d
+	xorl	%r9d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$9,%r11d
+	movl	%r8d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	andl	%r9d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$1735328473,%r10d
+	xorl	%r8d,%r12d
+	movzbl	%al,%eax
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$14,%r10d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	16(%r13),%xmm3
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	andl	%r8d,%r12d
+	addl	48(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$2368359562,%r9d
+	xorl	%r11d,%r12d
+	movzbl	%bl,%ebx
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$20,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm3
+	pxor	%xmm1,%xmm3
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	20(%r15),%r8d
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	addl	$4294588738,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	32(%r15),%r11d
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	addl	$2272392833,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	44(%r15),%r10d
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	addl	$1839030562,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	56(%r15),%r9d
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	addl	$4259657740,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	4(%r15),%r8d
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	addl	$2763975236,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	16(%r15),%r11d
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	addl	$1272893353,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	28(%r15),%r10d
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	addl	$4139469664,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	40(%r15),%r9d
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	addl	$3200236656,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	52(%r15),%r8d
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	addl	$681279174,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	0(%r15),%r11d
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	addl	$3936430074,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	12(%r15),%r10d
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	addl	$3572445317,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	24(%r15),%r9d
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	addl	$76029189,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	%r11d,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r9d,%r12d
+	addl	36(%r15),%r8d
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	addl	$3654602809,%r8d
+	movzbl	%al,%eax
+	addl	%r12d,%r8d
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	roll	$4,%r8d
+	movl	%r10d,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r8d,%r12d
+	addl	48(%r15),%r11d
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	addl	$3873151461,%r11d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r11d
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	roll	$11,%r11d
+	movl	%r9d,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	xorl	%r11d,%r12d
+	addl	60(%r15),%r10d
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	addl	$530742520,%r10d
+	movzbl	%al,%eax
+	addl	%r12d,%r10d
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	roll	$16,%r10d
+	movl	%r8d,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	32(%r13),%xmm4
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	xorl	%r10d,%r12d
+	addl	8(%r15),%r9d
+	addb	%dl,%bl
+	movl	64(%rsi),%eax
+	addl	$3299628645,%r9d
+	movzbl	%bl,%ebx
+	addl	%r12d,%r9d
+	movl	%edx,60(%rsi)
+	addb	%al,%cl
+	roll	$23,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm4
+	pxor	%xmm1,%xmm4
+	pxor	%xmm0,%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	0(%r15),%r8d
+	addb	%dl,%al
+	movl	68(%rsi),%ebx
+	addl	$4096336452,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,64(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	movd	(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	pxor	%xmm1,%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	28(%r15),%r11d
+	addb	%dl,%bl
+	movl	72(%rsi),%eax
+	addl	$1126891415,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,68(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	movd	(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	56(%r15),%r10d
+	addb	%dl,%al
+	movl	76(%rsi),%ebx
+	addl	$2878612391,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,72(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	20(%r15),%r9d
+	addb	%dl,%bl
+	movl	80(%rsi),%eax
+	addl	$4237533241,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,76(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	48(%r15),%r8d
+	addb	%dl,%al
+	movl	84(%rsi),%ebx
+	addl	$1700485571,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,80(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	12(%r15),%r11d
+	addb	%dl,%bl
+	movl	88(%rsi),%eax
+	addl	$2399980690,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,84(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	40(%r15),%r10d
+	addb	%dl,%al
+	movl	92(%rsi),%ebx
+	addl	$4293915773,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,88(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	4(%r15),%r9d
+	addb	%dl,%bl
+	movl	96(%rsi),%eax
+	addl	$2240044497,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,92(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	32(%r15),%r8d
+	addb	%dl,%al
+	movl	100(%rsi),%ebx
+	addl	$1873313359,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,96(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	60(%r15),%r11d
+	addb	%dl,%bl
+	movl	104(%rsi),%eax
+	addl	$4264355552,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,100(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	24(%r15),%r10d
+	addb	%dl,%al
+	movl	108(%rsi),%ebx
+	addl	$2734768916,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,104(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	52(%r15),%r9d
+	addb	%dl,%bl
+	movl	112(%rsi),%eax
+	addl	$1309151649,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,108(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r11d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r9d,%r12d
+	addl	16(%r15),%r8d
+	addb	%dl,%al
+	movl	116(%rsi),%ebx
+	addl	$4149444226,%r8d
+	movzbl	%al,%eax
+	xorl	%r10d,%r12d
+	movl	%edx,112(%rsi)
+	addl	%r12d,%r8d
+	addb	%bl,%cl
+	roll	$6,%r8d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+
+	addl	%r9d,%r8d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r10d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r8d,%r12d
+	addl	44(%r15),%r11d
+	addb	%dl,%bl
+	movl	120(%rsi),%eax
+	addl	$3174756917,%r11d
+	movzbl	%bl,%ebx
+	xorl	%r9d,%r12d
+	movl	%edx,116(%rsi)
+	addl	%r12d,%r11d
+	addb	%al,%cl
+	roll	$10,%r11d
+	movl	$-1,%r12d
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+
+	addl	%r8d,%r11d
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r9d,%r12d
+	movl	%eax,(%rdi,%rcx,4)
+	orl	%r11d,%r12d
+	addl	8(%r15),%r10d
+	addb	%dl,%al
+	movl	124(%rsi),%ebx
+	addl	$718787259,%r10d
+	movzbl	%al,%eax
+	xorl	%r8d,%r12d
+	movl	%edx,120(%rsi)
+	addl	%r12d,%r10d
+	addb	%bl,%cl
+	roll	$15,%r10d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+
+	addl	%r11d,%r10d
+	movdqu	48(%r13),%xmm5
+	addb	$32,%bpl
+	movl	(%rdi,%rcx,4),%edx
+	xorl	%r8d,%r12d
+	movl	%ebx,(%rdi,%rcx,4)
+	orl	%r10d,%r12d
+	addl	36(%r15),%r9d
+	addb	%dl,%bl
+	movl	0(%rdi,%rbp,4),%eax
+	addl	$3951481745,%r9d
+	movzbl	%bl,%ebx
+	xorl	%r11d,%r12d
+	movl	%edx,124(%rsi)
+	addl	%r12d,%r9d
+	addb	%al,%cl
+	roll	$21,%r9d
+	movl	$-1,%r12d
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+
+	addl	%r10d,%r9d
+	movq	%rbp,%rsi
+	xorq	%rbp,%rbp
+	movb	%sil,%bpl
+	movq	%rcx,%rsi
+	xorq	%rcx,%rcx
+	movb	%sil,%cl
+	leaq	(%rdi,%rbp,4),%rsi
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm5
+	pxor	%xmm1,%xmm5
+	addl	0(%rsp),%r8d
+	addl	4(%rsp),%r9d
+	addl	8(%rsp),%r10d
+	addl	12(%rsp),%r11d
+
+	movdqu	%xmm2,(%r14,%r13,1)
+	movdqu	%xmm3,16(%r14,%r13,1)
+	movdqu	%xmm4,32(%r14,%r13,1)
+	movdqu	%xmm5,48(%r14,%r13,1)
+	leaq	64(%r15),%r15
+	leaq	64(%r13),%r13
+	cmpq	16(%rsp),%r15
+	jb	.Loop
+
+	movq	24(%rsp),%r12
+	subb	%al,%cl
+	movl	%r8d,0(%r12)
+	movl	%r9d,4(%r12)
+	movl	%r10d,8(%r12)
+	movl	%r11d,12(%r12)
+	subb	$1,%bpl
+	movl	%ebp,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	40(%rsp),%r15
+	movq	48(%rsp),%r14
+	movq	56(%rsp),%r13
+	movq	64(%rsp),%r12
+	movq	72(%rsp),%rbp
+	movq	80(%rsp),%rbx
+	leaq	88(%rsp),%rsp
+.Lepilogue:
+.Labort:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_rc4_md5_enc:
diff --git a/crypto/rc4/rc4-mingw64-x86_64.S b/crypto/rc4/rc4-mingw64-x86_64.S
new file mode 100644
index 0000000..4750a77
--- /dev/null
+++ b/crypto/rc4/rc4-mingw64-x86_64.S
@@ -0,0 +1,615 @@
+#include "x86_arch.h"
+.text	
+
+
+
+.globl	RC4
+.def	RC4;	.scl 2;	.type 32;	.endef
+.p2align	4
+RC4:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_RC4:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+	orq	%rsi,%rsi
+	jne	.Lentry
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.Lentry:
+	pushq	%rbx
+	pushq	%r12
+	pushq	%r13
+.Lprologue:
+	movq	%rsi,%r11
+	movq	%rdx,%r12
+	movq	%rcx,%r13
+	xorq	%r10,%r10
+	xorq	%rcx,%rcx
+
+	leaq	8(%rdi),%rdi
+	movb	-8(%rdi),%r10b
+	movb	-4(%rdi),%cl
+	cmpl	$-1,256(%rdi)
+	je	.LRC4_CHAR
+	movl	OPENSSL_ia32cap_P(%rip),%r8d
+	xorq	%rbx,%rbx
+	incb	%r10b
+	subq	%r10,%rbx
+	subq	%r12,%r13
+	movl	(%rdi,%r10,4),%eax
+	testq	$-16,%r11
+	jz	.Lloop1
+	btl	$IA32CAP_BIT0_INTEL,%r8d
+	jc	.Lintel
+	andq	$7,%rbx
+	leaq	1(%r10),%rsi
+	jz	.Loop8
+	subq	%rbx,%r11
+.Loop8_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	.Loop8_warmup
+
+	leaq	1(%r10),%rsi
+	jmp	.Loop8
+.p2align	4
+.Loop8:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	0(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,0(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,4(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	8(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,8(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	12(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,12(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	16(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,16(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	20(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,20(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	24(%rdi,%rsi,4),%ebx
+	rorq	$8,%r8
+	movl	%edx,24(%rdi,%r10,4)
+	addb	%al,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%sil
+	addb	%bl,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	movl	-4(%rdi,%rsi,4),%eax
+	rorq	$8,%r8
+	movl	%edx,28(%rdi,%r10,4)
+	addb	%bl,%dl
+	movb	(%rdi,%rdx,4),%r8b
+	addb	$8,%r10b
+	rorq	$8,%r8
+	subq	$8,%r11
+
+	xorq	(%r12),%r8
+	movq	%r8,(%r13,%r12,1)
+	leaq	8(%r12),%r12
+
+	testq	$-8,%r11
+	jnz	.Loop8
+	cmpq	$0,%r11
+	jne	.Lloop1
+	jmp	.Lexit
+
+.p2align	4
+.Lintel:
+	testq	$-32,%r11
+	jz	.Lloop1
+	andq	$15,%rbx
+	jz	.Loop16_is_hot
+	subq	%rbx,%r11
+.Loop16_warmup:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%rbx
+	jnz	.Loop16_warmup
+
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	movb	%bl,%cl
+
+.Loop16_is_hot:
+	leaq	(%rdi,%r10,4),%rsi
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	jmp	.Loop16_enter
+.p2align	4
+.Loop16:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm0,%xmm2
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm0
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	4(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,0(%rsi)
+	pxor	%xmm1,%xmm2
+	addb	%bl,%cl
+	pinsrw	$0,(%rdi,%rax,4),%xmm0
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+.Loop16_enter:
+	movl	(%rdi,%rcx,4),%edx
+	pxor	%xmm1,%xmm1
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	8(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,4(%rsi)
+	addb	%al,%cl
+	pinsrw	$0,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	12(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,8(%rsi)
+	addb	%bl,%cl
+	pinsrw	$1,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	16(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,12(%rsi)
+	addb	%al,%cl
+	pinsrw	$1,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	20(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,16(%rsi)
+	addb	%bl,%cl
+	pinsrw	$2,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	24(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,20(%rsi)
+	addb	%al,%cl
+	pinsrw	$2,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	28(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,24(%rsi)
+	addb	%bl,%cl
+	pinsrw	$3,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	32(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,28(%rsi)
+	addb	%al,%cl
+	pinsrw	$3,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	36(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,32(%rsi)
+	addb	%bl,%cl
+	pinsrw	$4,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	40(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,36(%rsi)
+	addb	%al,%cl
+	pinsrw	$4,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	44(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,40(%rsi)
+	addb	%bl,%cl
+	pinsrw	$5,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	48(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,44(%rsi)
+	addb	%al,%cl
+	pinsrw	$5,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	52(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,48(%rsi)
+	addb	%bl,%cl
+	pinsrw	$6,(%rdi,%rax,4),%xmm0
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movl	56(%rsi),%eax
+	movzbl	%bl,%ebx
+	movl	%edx,52(%rsi)
+	addb	%al,%cl
+	pinsrw	$6,(%rdi,%rbx,4),%xmm1
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	addb	%dl,%al
+	movl	60(%rsi),%ebx
+	movzbl	%al,%eax
+	movl	%edx,56(%rsi)
+	addb	%bl,%cl
+	pinsrw	$7,(%rdi,%rax,4),%xmm0
+	addb	$16,%r10b
+	movdqu	(%r12),%xmm2
+	movl	(%rdi,%rcx,4),%edx
+	movl	%ebx,(%rdi,%rcx,4)
+	addb	%dl,%bl
+	movzbl	%bl,%ebx
+	movl	%edx,60(%rsi)
+	leaq	(%rdi,%r10,4),%rsi
+	pinsrw	$7,(%rdi,%rbx,4),%xmm1
+	movl	(%rsi),%eax
+	movq	%rcx,%rbx
+	xorq	%rcx,%rcx
+	subq	$16,%r11
+	movb	%bl,%cl
+	testq	$-16,%r11
+	jnz	.Loop16
+
+	psllq	$8,%xmm1
+	pxor	%xmm0,%xmm2
+	pxor	%xmm1,%xmm2
+	movdqu	%xmm2,(%r13,%r12,1)
+	leaq	16(%r12),%r12
+
+	cmpq	$0,%r11
+	jne	.Lloop1
+	jmp	.Lexit
+
+.p2align	4
+.Lloop1:
+	addb	%al,%cl
+	movl	(%rdi,%rcx,4),%edx
+	movl	%eax,(%rdi,%rcx,4)
+	movl	%edx,(%rdi,%r10,4)
+	addb	%dl,%al
+	incb	%r10b
+	movl	(%rdi,%rax,4),%edx
+	movl	(%rdi,%r10,4),%eax
+	xorb	(%r12),%dl
+	movb	%dl,(%r13,%r12,1)
+	leaq	1(%r12),%r12
+	decq	%r11
+	jnz	.Lloop1
+	jmp	.Lexit
+
+.p2align	4
+.LRC4_CHAR:
+	addb	$1,%r10b
+	movzbl	(%rdi,%r10,1),%eax
+	testq	$-8,%r11
+	jz	.Lcloop1
+	jmp	.Lcloop8
+.p2align	4
+.Lcloop8:
+	movl	(%r12),%r8d
+	movl	4(%r12),%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov0			
+	movq	%rax,%rbx
+.Lcmov0:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov1			
+	movq	%rbx,%rax
+.Lcmov1:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov2			
+	movq	%rax,%rbx
+.Lcmov2:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov3			
+	movq	%rbx,%rax
+.Lcmov3:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r8b
+	rorl	$8,%r8d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov4			
+	movq	%rax,%rbx
+.Lcmov4:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov5			
+	movq	%rbx,%rax
+.Lcmov5:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%al,%cl
+	leaq	1(%r10),%rsi
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%sil,%esi
+	movzbl	(%rdi,%rsi,1),%ebx
+	movb	%al,(%rdi,%rcx,1)
+	cmpq	%rsi,%rcx
+	movb	%dl,(%rdi,%r10,1)
+	jne	.Lcmov6			
+	movq	%rax,%rbx
+.Lcmov6:
+	addb	%al,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	addb	%bl,%cl
+	leaq	1(%rsi),%r10
+	movzbl	(%rdi,%rcx,1),%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%r10,1),%eax
+	movb	%bl,(%rdi,%rcx,1)
+	cmpq	%r10,%rcx
+	movb	%dl,(%rdi,%rsi,1)
+	jne	.Lcmov7			
+	movq	%rbx,%rax
+.Lcmov7:
+	addb	%bl,%dl
+	xorb	(%rdi,%rdx,1),%r9b
+	rorl	$8,%r9d
+	leaq	-8(%r11),%r11
+	movl	%r8d,(%r13)
+	leaq	8(%r12),%r12
+	movl	%r9d,4(%r13)
+	leaq	8(%r13),%r13
+
+	testq	$-8,%r11
+	jnz	.Lcloop8
+	cmpq	$0,%r11
+	jne	.Lcloop1
+	jmp	.Lexit
+.p2align	4
+.Lcloop1:
+	addb	%al,%cl
+	movzbl	%cl,%ecx
+	movzbl	(%rdi,%rcx,1),%edx
+	movb	%al,(%rdi,%rcx,1)
+	movb	%dl,(%rdi,%r10,1)
+	addb	%al,%dl
+	addb	$1,%r10b
+	movzbl	%dl,%edx
+	movzbl	%r10b,%r10d
+	movzbl	(%rdi,%rdx,1),%edx
+	movzbl	(%rdi,%r10,1),%eax
+	xorb	(%r12),%dl
+	leaq	1(%r12),%r12
+	movb	%dl,(%r13)
+	leaq	1(%r13),%r13
+	subq	$1,%r11
+	jnz	.Lcloop1
+	jmp	.Lexit
+
+.p2align	4
+.Lexit:
+	subb	$1,%r10b
+	movl	%r10d,-8(%rdi)
+	movl	%ecx,-4(%rdi)
+
+	movq	(%rsp),%r13
+	movq	8(%rsp),%r12
+	movq	16(%rsp),%rbx
+	addq	$24,%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_RC4:
+.globl	RC4_set_key
+.def	RC4_set_key;	.scl 2;	.type 32;	.endef
+.p2align	4
+RC4_set_key:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_RC4_set_key:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	leaq	8(%rdi),%rdi
+	leaq	(%rdx,%rsi,1),%rdx
+	negq	%rsi
+	movq	%rsi,%rcx
+	xorl	%eax,%eax
+	xorq	%r9,%r9
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+
+	movl	OPENSSL_ia32cap_P(%rip),%r8d
+	btl	$IA32CAP_BIT0_INTELP4,%r8d
+	jc	.Lc1stloop
+	jmp	.Lw1stloop
+
+.p2align	4
+.Lw1stloop:
+	movl	%eax,(%rdi,%rax,4)
+	addb	$1,%al
+	jnc	.Lw1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.p2align	4
+.Lw2ndloop:
+	movl	(%rdi,%r9,4),%r10d
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movl	(%rdi,%r8,4),%r11d
+	cmovzq	%rcx,%rsi
+	movl	%r10d,(%rdi,%r8,4)
+	movl	%r11d,(%rdi,%r9,4)
+	addb	$1,%r9b
+	jnc	.Lw2ndloop
+	jmp	.Lexit_key
+
+.p2align	4
+.Lc1stloop:
+	movb	%al,(%rdi,%rax,1)
+	addb	$1,%al
+	jnc	.Lc1stloop
+
+	xorq	%r9,%r9
+	xorq	%r8,%r8
+.p2align	4
+.Lc2ndloop:
+	movb	(%rdi,%r9,1),%r10b
+	addb	(%rdx,%rsi,1),%r8b
+	addb	%r10b,%r8b
+	addq	$1,%rsi
+	movb	(%rdi,%r8,1),%r11b
+	jnz	.Lcnowrap
+	movq	%rcx,%rsi
+.Lcnowrap:
+	movb	%r10b,(%rdi,%r8,1)
+	movb	%r11b,(%rdi,%r9,1)
+	addb	$1,%r9b
+	jnc	.Lc2ndloop
+	movl	$-1,256(%rdi)
+
+.p2align	4
+.Lexit_key:
+	xorl	%eax,%eax
+	movl	%eax,-8(%rdi)
+	movl	%eax,-4(%rdi)
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_RC4_set_key:
diff --git a/crypto/rc4/rc4_enc.c b/crypto/rc4/rc4_enc.c
new file mode 100644
index 0000000..3763bfa
--- /dev/null
+++ b/crypto/rc4/rc4_enc.c
@@ -0,0 +1,254 @@
+/* $OpenBSD: rc4_enc.c,v 1.18 2022/11/26 16:08:54 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+#include "rc4_local.h"
+
+/* RC4 as implemented from a posting from
+ * Newsgroups: sci.crypt
+ * From: sterndark@netcom.com (David Sterndark)
+ * Subject: RC4 Algorithm revealed.
+ * Message-ID: 
+ * Date: Wed, 14 Sep 1994 06:35:31 GMT
+ */
+
+void
+RC4(RC4_KEY *key, size_t len, const unsigned char *indata,
+    unsigned char *outdata)
+{
+	RC4_INT *d;
+	RC4_INT x, y,tx, ty;
+	size_t i;
+
+	x = key->x;
+	y = key->y;
+	d = key->data;
+
+#if defined(RC4_CHUNK)
+	/*
+	 * The original reason for implementing this(*) was the fact that
+	 * pre-21164a Alpha CPUs don't have byte load/store instructions
+	 * and e.g. a byte store has to be done with 64-bit load, shift,
+	 * and, or and finally 64-bit store. Peaking data and operating
+	 * at natural word size made it possible to reduce amount of
+	 * instructions as well as to perform early read-ahead without
+	 * suffering from RAW (read-after-write) hazard. This resulted
+	 * in ~40%(**) performance improvement on 21064 box with gcc.
+	 * But it's not only Alpha users who win here:-) Thanks to the
+	 * early-n-wide read-ahead this implementation also exhibits
+	 * >40% speed-up on SPARC and 20-30% on 64-bit MIPS (depending
+	 * on sizeof(RC4_INT)).
+	 *
+	 * (*)	"this" means code which recognizes the case when input
+	 *	and output pointers appear to be aligned at natural CPU
+	 *	word boundary
+	 * (**)	i.e. according to 'apps/openssl speed rc4' benchmark,
+	 *	crypto/rc4/rc4speed.c exhibits almost 70% speed-up...
+	 *
+	 * Caveats.
+	 *
+	 * - RC4_CHUNK="unsigned long long" should be a #1 choice for
+	 *   UltraSPARC. Unfortunately gcc generates very slow code
+	 *   (2.5-3 times slower than one generated by Sun's WorkShop
+	 *   C) and therefore gcc (at least 2.95 and earlier) should
+	 *   always be told that RC4_CHUNK="unsigned long".
+	 *
+	 *					
+	 */
+
+# define RC4_STEP	( \
+			x=(x+1) &0xff,	\
+			tx=d[x],	\
+			y=(tx+y)&0xff,	\
+			ty=d[y],	\
+			d[y]=tx,	\
+			d[x]=ty,	\
+			(RC4_CHUNK)d[(tx+ty)&0xff]\
+			)
+
+	if ((((size_t)indata & (sizeof(RC4_CHUNK) - 1)) |
+	    ((size_t)outdata & (sizeof(RC4_CHUNK) - 1))) == 0 ) {
+		RC4_CHUNK ichunk, otp;
+
+		/*
+		 * I reckon we can afford to implement both endian
+		 * cases and to decide which way to take at run-time
+		 * because the machine code appears to be very compact
+		 * and redundant 1-2KB is perfectly tolerable (i.e.
+		 * in case the compiler fails to eliminate it:-). By
+		 * suggestion from Terrel Larson .
+		 *
+		 * Special notes.
+		 *
+		 * - compilers (those I've tried) don't seem to have
+		 *   problems eliminating either the operators guarded
+		 *   by "if (sizeof(RC4_CHUNK)==8)" or the condition
+		 *   expressions themselves so I've got 'em to replace
+		 *   corresponding #ifdefs from the previous version;
+		 * - I chose to let the redundant switch cases when
+		 *   sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
+		 *   before);
+		 * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
+		 *   [LB]ESHFT guards against "shift is out of range"
+		 *   warnings when sizeof(RC4_CHUNK)!=8
+		 *
+		 *			
+		 */
+#if BYTE_ORDER == BIG_ENDIAN
+# define BESHFT(c)	(((sizeof(RC4_CHUNK)-(c)-1)*8)&(sizeof(RC4_CHUNK)*8-1))
+		for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
+			ichunk  = *(RC4_CHUNK *)indata;
+			otp = RC4_STEP << BESHFT(0);
+			otp |= RC4_STEP << BESHFT(1);
+			otp |= RC4_STEP << BESHFT(2);
+			otp |= RC4_STEP << BESHFT(3);
+			if (sizeof(RC4_CHUNK) == 8) {
+				otp |= RC4_STEP << BESHFT(4);
+				otp |= RC4_STEP << BESHFT(5);
+				otp |= RC4_STEP << BESHFT(6);
+				otp |= RC4_STEP << BESHFT(7);
+			}
+			*(RC4_CHUNK *)outdata = otp^ichunk;
+			indata += sizeof(RC4_CHUNK);
+			outdata += sizeof(RC4_CHUNK);
+		}
+#else
+# define LESHFT(c)	(((c)*8)&(sizeof(RC4_CHUNK)*8-1))
+		for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
+			ichunk = *(RC4_CHUNK *)indata;
+			otp = RC4_STEP;
+			otp |= RC4_STEP << 8;
+			otp |= RC4_STEP << 16;
+			otp |= RC4_STEP << 24;
+			if (sizeof(RC4_CHUNK) == 8) {
+				otp |= RC4_STEP << LESHFT(4);
+				otp |= RC4_STEP << LESHFT(5);
+				otp |= RC4_STEP << LESHFT(6);
+				otp |= RC4_STEP << LESHFT(7);
+			}
+			*(RC4_CHUNK *)outdata = otp ^ ichunk;
+			indata += sizeof(RC4_CHUNK);
+			outdata += sizeof(RC4_CHUNK);
+		}
+#endif
+	}
+#endif
+#define LOOP(in,out) \
+		x=((x+1)&0xff); \
+		tx=d[x]; \
+		y=(tx+y)&0xff; \
+		d[x]=ty=d[y]; \
+		d[y]=tx; \
+		(out) = d[(tx+ty)&0xff]^ (in);
+
+#ifndef RC4_INDEX
+#define RC4_LOOP(a,b,i)	LOOP(*((a)++),*((b)++))
+#else
+#define RC4_LOOP(a,b,i)	LOOP(a[i],b[i])
+#endif
+
+	i = len >> 3;
+	if (i) {
+		for (;;) {
+			RC4_LOOP(indata, outdata, 0);
+			RC4_LOOP(indata, outdata, 1);
+			RC4_LOOP(indata, outdata, 2);
+			RC4_LOOP(indata, outdata, 3);
+			RC4_LOOP(indata, outdata, 4);
+			RC4_LOOP(indata, outdata, 5);
+			RC4_LOOP(indata, outdata, 6);
+			RC4_LOOP(indata, outdata, 7);
+#ifdef RC4_INDEX
+			indata += 8;
+			outdata += 8;
+#endif
+			if (--i == 0)
+				break;
+		}
+	}
+	i = len&0x07;
+	if (i) {
+		for (;;) {
+			RC4_LOOP(indata, outdata, 0);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 1);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 2);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 3);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 4);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 5);
+			if (--i == 0)
+				break;
+			RC4_LOOP(indata, outdata, 6);
+			if (--i == 0)
+				break;
+		}
+	}
+	key->x = x;
+	key->y = y;
+}
diff --git a/crypto/rc4/rc4_local.h b/crypto/rc4/rc4_local.h
new file mode 100644
index 0000000..61d08a4
--- /dev/null
+++ b/crypto/rc4/rc4_local.h
@@ -0,0 +1,5 @@
+/* $OpenBSD: rc4_local.h,v 1.1 2022/11/26 16:08:54 tb Exp $ */
+
+#ifndef HEADER_RC4_LOCL_H
+#define HEADER_RC4_LOCL_H
+#endif
diff --git a/crypto/rc4/rc4_skey.c b/crypto/rc4/rc4_skey.c
new file mode 100644
index 0000000..5833c7b
--- /dev/null
+++ b/crypto/rc4/rc4_skey.c
@@ -0,0 +1,99 @@
+/* $OpenBSD: rc4_skey.c,v 1.16 2023/07/28 10:35:14 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include "rc4_local.h"
+
+/* RC4 as implemented from a posting from
+ * Newsgroups: sci.crypt
+ * From: sterndark@netcom.com (David Sterndark)
+ * Subject: RC4 Algorithm revealed.
+ * Message-ID: 
+ * Date: Wed, 14 Sep 1994 06:35:31 GMT
+ */
+
+void
+RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
+{
+	RC4_INT tmp;
+	int id1, id2;
+	RC4_INT *d;
+	unsigned int i;
+
+	d = &(key->data[0]);
+	key->x = 0;
+	key->y = 0;
+	id1 = id2 = 0;
+
+#define SK_LOOP(d,n) { \
+		tmp=d[(n)]; \
+		id2 = (data[id1] + tmp + id2) & 0xff; \
+		if (++id1 == len) id1=0; \
+		d[(n)]=d[id2]; \
+		d[id2]=tmp; }
+
+	for (i = 0; i < 256; i++)
+		d[i] = i;
+	for (i = 0; i < 256; i += 4) {
+		SK_LOOP(d, i + 0);
+		SK_LOOP(d, i + 1);
+		SK_LOOP(d, i + 2);
+		SK_LOOP(d, i + 3);
+	}
+}
diff --git a/crypto/ripemd/ripemd.c b/crypto/ripemd/ripemd.c
new file mode 100644
index 0000000..344d9f6
--- /dev/null
+++ b/crypto/ripemd/ripemd.c
@@ -0,0 +1,442 @@
+/* $OpenBSD: ripemd.c,v 1.7 2023/08/10 12:27:35 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * DO EXAMINE COMMENTS IN crypto/md5/md5_locl.h & crypto/md5/md5_dgst.c
+ * FOR EXPLANATIONS ON FOLLOWING "CODE."
+ *					
+ */
+#ifdef RMD160_ASM
+# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__INTEL__)
+#  define ripemd160_block_data_order ripemd160_block_asm_data_order
+# endif
+#endif
+
+__BEGIN_HIDDEN_DECLS
+
+void ripemd160_block_data_order (RIPEMD160_CTX *c, const void *p, size_t num);
+
+__END_HIDDEN_DECLS
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG               RIPEMD160_LONG
+#define HASH_CTX                RIPEMD160_CTX
+#define HASH_CBLOCK             RIPEMD160_CBLOCK
+#define HASH_UPDATE             RIPEMD160_Update
+#define HASH_TRANSFORM          RIPEMD160_Transform
+#define HASH_FINAL              RIPEMD160_Final
+#define	HASH_MAKE_STRING(c,s)	do {	\
+	unsigned long ll;		\
+	ll=(c)->A; HOST_l2c(ll,(s));	\
+	ll=(c)->B; HOST_l2c(ll,(s));	\
+	ll=(c)->C; HOST_l2c(ll,(s));	\
+	ll=(c)->D; HOST_l2c(ll,(s));	\
+	ll=(c)->E; HOST_l2c(ll,(s));	\
+	} while (0)
+#define HASH_BLOCK_DATA_ORDER   ripemd160_block_data_order
+
+#include "md32_common.h"
+
+#if 0
+#define F1(x,y,z)	 ((x)^(y)^(z))
+#define F2(x,y,z)	(((x)&(y))|((~x)&z))
+#define F3(x,y,z)	(((x)|(~y))^(z))
+#define F4(x,y,z)	(((x)&(z))|((y)&(~(z))))
+#define F5(x,y,z)	 ((x)^((y)|(~(z))))
+#else
+/*
+ * Transformed F2 and F4 are courtesy of Wei Dai 
+ */
+#define F1(x,y,z)	((x) ^ (y) ^ (z))
+#define F2(x,y,z)	((((y) ^ (z)) & (x)) ^ (z))
+#define F3(x,y,z)	(((~(y)) | (x)) ^ (z))
+#define F4(x,y,z)	((((x) ^ (y)) & (z)) ^ (y))
+#define F5(x,y,z)	(((~(z)) | (y)) ^ (x))
+#endif
+
+#define RIPEMD160_A	0x67452301L
+#define RIPEMD160_B	0xEFCDAB89L
+#define RIPEMD160_C	0x98BADCFEL
+#define RIPEMD160_D	0x10325476L
+#define RIPEMD160_E	0xC3D2E1F0L
+
+#define KL0 0x00000000L
+#define KL1 0x5A827999L
+#define KL2 0x6ED9EBA1L
+#define KL3 0x8F1BBCDCL
+#define KL4 0xA953FD4EL
+
+#define KR0 0x50A28BE6L
+#define KR1 0x5C4DD124L
+#define KR2 0x6D703EF3L
+#define KR3 0x7A6D76E9L
+#define KR4 0x00000000L
+
+#define RIP1(a,b,c,d,e,w,s) { \
+	a+=F1(b,c,d)+w; \
+        a=ROTATE(a,s)+e; \
+        c=ROTATE(c,10); }
+
+#define RIP2(a,b,c,d,e,w,s,K) { \
+	a+=F2(b,c,d)+w+K; \
+        a=ROTATE(a,s)+e; \
+        c=ROTATE(c,10); }
+
+#define RIP3(a,b,c,d,e,w,s,K) { \
+	a+=F3(b,c,d)+w+K; \
+        a=ROTATE(a,s)+e; \
+        c=ROTATE(c,10); }
+
+#define RIP4(a,b,c,d,e,w,s,K) { \
+	a+=F4(b,c,d)+w+K; \
+        a=ROTATE(a,s)+e; \
+        c=ROTATE(c,10); }
+
+#define RIP5(a,b,c,d,e,w,s,K) { \
+	a+=F5(b,c,d)+w+K; \
+        a=ROTATE(a,s)+e; \
+        c=ROTATE(c,10); }
+
+#  ifdef RMD160_ASM
+void ripemd160_block_x86(RIPEMD160_CTX *c, unsigned long *p, size_t num);
+#    define ripemd160_block ripemd160_block_x86
+#  else
+void ripemd160_block(RIPEMD160_CTX *c, unsigned long *p, size_t num);
+#  endif
+
+int
+RIPEMD160_Init(RIPEMD160_CTX *c)
+{
+	memset (c, 0, sizeof(*c));
+	c->A = RIPEMD160_A;
+	c->B = RIPEMD160_B;
+	c->C = RIPEMD160_C;
+	c->D = RIPEMD160_D;
+	c->E = RIPEMD160_E;
+	return 1;
+}
+
+#ifndef ripemd160_block_data_order
+void
+ripemd160_block_data_order(RIPEMD160_CTX *ctx, const void *p, size_t num)
+{
+	const unsigned char *data = p;
+	unsigned int A, B, C, D, E;
+	unsigned int a, b, c, d, e, l;
+	unsigned int X0, X1, X2, X3, X4, X5, X6, X7,
+	    X8, X9, X10, X11, X12, X13, X14, X15;
+
+	for (; num--; ) {
+
+		A = ctx->A;
+		B = ctx->B;
+		C = ctx->C;
+		D = ctx->D;
+		E = ctx->E;
+
+		HOST_c2l(data, l);
+		X0 = l;
+		HOST_c2l(data, l);
+		X1 = l;
+		RIP1(A, B, C, D, E, X0, 11);
+		HOST_c2l(data, l);
+		X2 = l;
+		RIP1(E, A, B, C, D, X1, 14);
+		HOST_c2l(data, l);
+		X3 = l;
+		RIP1(D, E, A, B, C, X2, 15);
+		HOST_c2l(data, l);
+		X4 = l;
+		RIP1(C, D, E, A, B, X3, 12);
+		HOST_c2l(data, l);
+		X5 = l;
+		RIP1(B, C, D, E, A, X4, 5);
+		HOST_c2l(data, l);
+		X6 = l;
+		RIP1(A, B, C, D, E, X5, 8);
+		HOST_c2l(data, l);
+		X7 = l;
+		RIP1(E, A, B, C, D, X6, 7);
+		HOST_c2l(data, l);
+		X8 = l;
+		RIP1(D, E, A, B, C, X7, 9);
+		HOST_c2l(data, l);
+		X9 = l;
+		RIP1(C, D, E, A, B, X8, 11);
+		HOST_c2l(data, l);
+		X10 = l;
+		RIP1(B, C, D, E, A, X9, 13);
+		HOST_c2l(data, l);
+		X11 = l;
+		RIP1(A, B, C, D, E, X10, 14);
+		HOST_c2l(data, l);
+		X12 = l;
+		RIP1(E, A, B, C, D, X11, 15);
+		HOST_c2l(data, l);
+		X13 = l;
+		RIP1(D, E, A, B, C, X12, 6);
+		HOST_c2l(data, l);
+		X14 = l;
+		RIP1(C, D, E, A, B, X13, 7);
+		HOST_c2l(data, l);
+		X15 = l;
+		RIP1(B, C, D, E, A, X14, 9);
+		RIP1(A, B, C, D, E, X15, 8);
+
+		RIP2(E, A, B, C, D, X7, 7, KL1);
+		RIP2(D, E, A, B, C, X4, 6, KL1);
+		RIP2(C, D, E, A, B, X13, 8, KL1);
+		RIP2(B, C, D, E, A, X1, 13, KL1);
+		RIP2(A, B, C, D, E, X10, 11, KL1);
+		RIP2(E, A, B, C, D, X6, 9, KL1);
+		RIP2(D, E, A, B, C, X15, 7, KL1);
+		RIP2(C, D, E, A, B, X3, 15, KL1);
+		RIP2(B, C, D, E, A, X12, 7, KL1);
+		RIP2(A, B, C, D, E, X0, 12, KL1);
+		RIP2(E, A, B, C, D, X9, 15, KL1);
+		RIP2(D, E, A, B, C, X5, 9, KL1);
+		RIP2(C, D, E, A, B, X2, 11, KL1);
+		RIP2(B, C, D, E, A, X14, 7, KL1);
+		RIP2(A, B, C, D, E, X11, 13, KL1);
+		RIP2(E, A, B, C, D, X8, 12, KL1);
+
+		RIP3(D, E, A, B, C, X3, 11, KL2);
+		RIP3(C, D, E, A, B, X10, 13, KL2);
+		RIP3(B, C, D, E, A, X14, 6, KL2);
+		RIP3(A, B, C, D, E, X4, 7, KL2);
+		RIP3(E, A, B, C, D, X9, 14, KL2);
+		RIP3(D, E, A, B, C, X15, 9, KL2);
+		RIP3(C, D, E, A, B, X8, 13, KL2);
+		RIP3(B, C, D, E, A, X1, 15, KL2);
+		RIP3(A, B, C, D, E, X2, 14, KL2);
+		RIP3(E, A, B, C, D, X7, 8, KL2);
+		RIP3(D, E, A, B, C, X0, 13, KL2);
+		RIP3(C, D, E, A, B, X6, 6, KL2);
+		RIP3(B, C, D, E, A, X13, 5, KL2);
+		RIP3(A, B, C, D, E, X11, 12, KL2);
+		RIP3(E, A, B, C, D, X5, 7, KL2);
+		RIP3(D, E, A, B, C, X12, 5, KL2);
+
+		RIP4(C, D, E, A, B, X1, 11, KL3);
+		RIP4(B, C, D, E, A, X9, 12, KL3);
+		RIP4(A, B, C, D, E, X11, 14, KL3);
+		RIP4(E, A, B, C, D, X10, 15, KL3);
+		RIP4(D, E, A, B, C, X0, 14, KL3);
+		RIP4(C, D, E, A, B, X8, 15, KL3);
+		RIP4(B, C, D, E, A, X12, 9, KL3);
+		RIP4(A, B, C, D, E, X4, 8, KL3);
+		RIP4(E, A, B, C, D, X13, 9, KL3);
+		RIP4(D, E, A, B, C, X3, 14, KL3);
+		RIP4(C, D, E, A, B, X7, 5, KL3);
+		RIP4(B, C, D, E, A, X15, 6, KL3);
+		RIP4(A, B, C, D, E, X14, 8, KL3);
+		RIP4(E, A, B, C, D, X5, 6, KL3);
+		RIP4(D, E, A, B, C, X6, 5, KL3);
+		RIP4(C, D, E, A, B, X2, 12, KL3);
+
+		RIP5(B, C, D, E, A, X4, 9, KL4);
+		RIP5(A, B, C, D, E, X0, 15, KL4);
+		RIP5(E, A, B, C, D, X5, 5, KL4);
+		RIP5(D, E, A, B, C, X9, 11, KL4);
+		RIP5(C, D, E, A, B, X7, 6, KL4);
+		RIP5(B, C, D, E, A, X12, 8, KL4);
+		RIP5(A, B, C, D, E, X2, 13, KL4);
+		RIP5(E, A, B, C, D, X10, 12, KL4);
+		RIP5(D, E, A, B, C, X14, 5, KL4);
+		RIP5(C, D, E, A, B, X1, 12, KL4);
+		RIP5(B, C, D, E, A, X3, 13, KL4);
+		RIP5(A, B, C, D, E, X8, 14, KL4);
+		RIP5(E, A, B, C, D, X11, 11, KL4);
+		RIP5(D, E, A, B, C, X6, 8, KL4);
+		RIP5(C, D, E, A, B, X15, 5, KL4);
+		RIP5(B, C, D, E, A, X13, 6, KL4);
+
+		a = A;
+		b = B;
+		c = C;
+		d = D;
+		e = E;
+		/* Do other half */
+		A = ctx->A;
+		B = ctx->B;
+		C = ctx->C;
+		D = ctx->D;
+		E = ctx->E;
+
+		RIP5(A, B, C, D, E, X5, 8, KR0);
+		RIP5(E, A, B, C, D, X14, 9, KR0);
+		RIP5(D, E, A, B, C, X7, 9, KR0);
+		RIP5(C, D, E, A, B, X0, 11, KR0);
+		RIP5(B, C, D, E, A, X9, 13, KR0);
+		RIP5(A, B, C, D, E, X2, 15, KR0);
+		RIP5(E, A, B, C, D, X11, 15, KR0);
+		RIP5(D, E, A, B, C, X4, 5, KR0);
+		RIP5(C, D, E, A, B, X13, 7, KR0);
+		RIP5(B, C, D, E, A, X6, 7, KR0);
+		RIP5(A, B, C, D, E, X15, 8, KR0);
+		RIP5(E, A, B, C, D, X8, 11, KR0);
+		RIP5(D, E, A, B, C, X1, 14, KR0);
+		RIP5(C, D, E, A, B, X10, 14, KR0);
+		RIP5(B, C, D, E, A, X3, 12, KR0);
+		RIP5(A, B, C, D, E, X12, 6, KR0);
+
+		RIP4(E, A, B, C, D, X6, 9, KR1);
+		RIP4(D, E, A, B, C, X11, 13, KR1);
+		RIP4(C, D, E, A, B, X3, 15, KR1);
+		RIP4(B, C, D, E, A, X7, 7, KR1);
+		RIP4(A, B, C, D, E, X0, 12, KR1);
+		RIP4(E, A, B, C, D, X13, 8, KR1);
+		RIP4(D, E, A, B, C, X5, 9, KR1);
+		RIP4(C, D, E, A, B, X10, 11, KR1);
+		RIP4(B, C, D, E, A, X14, 7, KR1);
+		RIP4(A, B, C, D, E, X15, 7, KR1);
+		RIP4(E, A, B, C, D, X8, 12, KR1);
+		RIP4(D, E, A, B, C, X12, 7, KR1);
+		RIP4(C, D, E, A, B, X4, 6, KR1);
+		RIP4(B, C, D, E, A, X9, 15, KR1);
+		RIP4(A, B, C, D, E, X1, 13, KR1);
+		RIP4(E, A, B, C, D, X2, 11, KR1);
+
+		RIP3(D, E, A, B, C, X15, 9, KR2);
+		RIP3(C, D, E, A, B, X5, 7, KR2);
+		RIP3(B, C, D, E, A, X1, 15, KR2);
+		RIP3(A, B, C, D, E, X3, 11, KR2);
+		RIP3(E, A, B, C, D, X7, 8, KR2);
+		RIP3(D, E, A, B, C, X14, 6, KR2);
+		RIP3(C, D, E, A, B, X6, 6, KR2);
+		RIP3(B, C, D, E, A, X9, 14, KR2);
+		RIP3(A, B, C, D, E, X11, 12, KR2);
+		RIP3(E, A, B, C, D, X8, 13, KR2);
+		RIP3(D, E, A, B, C, X12, 5, KR2);
+		RIP3(C, D, E, A, B, X2, 14, KR2);
+		RIP3(B, C, D, E, A, X10, 13, KR2);
+		RIP3(A, B, C, D, E, X0, 13, KR2);
+		RIP3(E, A, B, C, D, X4, 7, KR2);
+		RIP3(D, E, A, B, C, X13, 5, KR2);
+
+		RIP2(C, D, E, A, B, X8, 15, KR3);
+		RIP2(B, C, D, E, A, X6, 5, KR3);
+		RIP2(A, B, C, D, E, X4, 8, KR3);
+		RIP2(E, A, B, C, D, X1, 11, KR3);
+		RIP2(D, E, A, B, C, X3, 14, KR3);
+		RIP2(C, D, E, A, B, X11, 14, KR3);
+		RIP2(B, C, D, E, A, X15, 6, KR3);
+		RIP2(A, B, C, D, E, X0, 14, KR3);
+		RIP2(E, A, B, C, D, X5, 6, KR3);
+		RIP2(D, E, A, B, C, X12, 9, KR3);
+		RIP2(C, D, E, A, B, X2, 12, KR3);
+		RIP2(B, C, D, E, A, X13, 9, KR3);
+		RIP2(A, B, C, D, E, X9, 12, KR3);
+		RIP2(E, A, B, C, D, X7, 5, KR3);
+		RIP2(D, E, A, B, C, X10, 15, KR3);
+		RIP2(C, D, E, A, B, X14, 8, KR3);
+
+		RIP1(B, C, D, E, A, X12, 8);
+		RIP1(A, B, C, D, E, X15, 5);
+		RIP1(E, A, B, C, D, X10, 12);
+		RIP1(D, E, A, B, C, X4, 9);
+		RIP1(C, D, E, A, B, X1, 12);
+		RIP1(B, C, D, E, A, X5, 5);
+		RIP1(A, B, C, D, E, X8, 14);
+		RIP1(E, A, B, C, D, X7, 6);
+		RIP1(D, E, A, B, C, X6, 8);
+		RIP1(C, D, E, A, B, X2, 13);
+		RIP1(B, C, D, E, A, X13, 6);
+		RIP1(A, B, C, D, E, X14, 5);
+		RIP1(E, A, B, C, D, X0, 15);
+		RIP1(D, E, A, B, C, X3, 13);
+		RIP1(C, D, E, A, B, X9, 11);
+		RIP1(B, C, D, E, A, X11, 11);
+
+		D = ctx->B + c + D;
+		ctx->B = ctx->C + d + E;
+		ctx->C = ctx->D + e + A;
+		ctx->D = ctx->E + a + B;
+		ctx->E = ctx->A + b + C;
+		ctx->A = D;
+
+	}
+}
+#endif
+
+unsigned char *
+RIPEMD160(const unsigned char *d, size_t n,
+    unsigned char *md)
+{
+	RIPEMD160_CTX c;
+	static unsigned char m[RIPEMD160_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+	if (!RIPEMD160_Init(&c))
+		return NULL;
+	RIPEMD160_Update(&c, d, n);
+	RIPEMD160_Final(md, &c);
+	explicit_bzero(&c, sizeof(c));
+	return (md);
+}
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
new file mode 100644
index 0000000..ae38c20
--- /dev/null
+++ b/crypto/rsa/rsa_ameth.c
@@ -0,0 +1,1143 @@
+/* $OpenBSD: rsa_ameth.c,v 1.33 2023/08/12 08:02:43 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "bn_local.h"
+#include "cryptlib.h"
+#include "evp_local.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)
+{
+	const RSA *rsa = pkey->pkey.rsa;
+
+	*pstr = NULL;
+
+	/* If RSA it's just NULL type */
+	if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) {
+		*pstrtype = V_ASN1_NULL;
+		return 1;
+	}
+
+	/* If no PSS parameters we omit parameters entirely */
+	if (rsa->pss == NULL) {
+		*pstrtype = V_ASN1_UNDEF;
+		return 1;
+	}
+
+	/* Encode PSS parameters */
+	if (ASN1_item_pack(rsa->pss, &RSA_PSS_PARAMS_it, pstr) == NULL)
+		return 0;
+
+	*pstrtype = V_ASN1_SEQUENCE;
+	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) {
+		RSAerror(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)
+{
+	ASN1_STRING *str = NULL;
+	int strtype;
+	unsigned char *penc = NULL;
+	int penclen = 0;
+	ASN1_OBJECT *aobj;
+
+	if (!rsa_param_encode(pkey, &str, &strtype))
+		goto err;
+	if ((penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc)) <= 0) {
+		penclen = 0;
+		goto err;
+	}
+	if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!X509_PUBKEY_set0_param(pk, aobj, strtype, str, penc, penclen))
+		goto err;
+
+	return 1;
+
+ err:
+	ASN1_STRING_free(str);
+	freezero(penc, penclen);
+
+	return 0;
+}
+
+static int
+rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
+{
+	const unsigned char *p;
+	int pklen;
+	X509_ALGOR *alg;
+	RSA *rsa = NULL;
+
+	if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey))
+		return 0;
+	if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) {
+		RSAerror(ERR_R_RSA_LIB);
+		return 0;
+	}
+	if (!rsa_param_decode(rsa, alg)) {
+		RSA_free(rsa);
+		return 0;
+	}
+	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) {
+		RSA_free(rsa);
+		return 0;
+	}
+	return 1;
+}
+
+static int
+rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+	if (BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) != 0 ||
+	    BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) != 0)
+		return 0;
+
+	return 1;
+}
+
+static int
+old_rsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
+{
+	RSA *rsa;
+
+	if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL) {
+		RSAerror(ERR_R_RSA_LIB);
+		return 0;
+	}
+	EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
+	return 1;
+}
+
+static int
+old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
+{
+	return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
+}
+
+static int
+rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
+{
+	ASN1_STRING *str = NULL;
+	ASN1_OBJECT *aobj;
+	int strtype;
+	unsigned char *rk = NULL;
+	int rklen = 0;
+
+	if (!rsa_param_encode(pkey, &str, &strtype))
+		goto err;
+	if ((rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk)) <= 0) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		rklen = 0;
+		goto err;
+	}
+	if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
+		goto err;
+	if (!PKCS8_pkey_set0(p8, aobj, 0, strtype, str, rk, rklen)) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	return 1;
+
+ err:
+	ASN1_STRING_free(str);
+	freezero(rk, rklen);
+
+	return 0;
+}
+
+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;
+
+	if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8))
+		return 0;
+	rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+	if (rsa == NULL) {
+		RSAerror(ERR_R_RSA_LIB);
+		return 0;
+	}
+	if (!rsa_param_decode(rsa, alg)) {
+		RSA_free(rsa);
+		return 0;
+	}
+	EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
+
+	return 1;
+}
+
+static int
+rsa_size(const EVP_PKEY *pkey)
+{
+	return RSA_size(pkey->pkey.rsa);
+}
+
+static int
+rsa_bits(const EVP_PKEY *pkey)
+{
+	return BN_num_bits(pkey->pkey.rsa->n);
+}
+
+static int
+rsa_security_bits(const EVP_PKEY *pkey)
+{
+	return RSA_security_bits(pkey->pkey.rsa);
+}
+
+static void
+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(&X509_ALGOR_it, alg->parameter);
+}
+
+static RSA_PSS_PARAMS *
+rsa_pss_decode(const X509_ALGOR *alg)
+{
+	RSA_PSS_PARAMS *pss;
+
+	pss = ASN1_TYPE_unpack_sequence(&RSA_PSS_PARAMS_it, 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_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss, int indent)
+{
+	int rv = 0;
+	X509_ALGOR *maskHash = NULL;
+
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+	if (pss_key) {
+		if (pss == NULL) {
+			if (BIO_puts(bp, "No PSS parameter restrictions\n") <= 0)
+				return 0;
+			return 1;
+		} else {
+			if (BIO_puts(bp, "PSS parameter restrictions:") <= 0)
+				return 0;
+		}
+	} else if (pss == NULL) {
+		if (BIO_puts(bp,"(INVALID PSS PARAMETERS)\n") <= 0)
+			return 0;
+		return 1;
+	}
+	if (BIO_puts(bp, "\n") <= 0)
+		goto err;
+	if (pss_key)
+		indent += 2;
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+	if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
+		goto err;
+
+	if (pss->hashAlgorithm) {
+		if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
+			goto err;
+	} else if (BIO_puts(bp, "sha1 (default)") <= 0) {
+		goto err;
+	}
+
+	if (BIO_puts(bp, "\n") <= 0)
+		goto err;
+
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+
+	if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
+		goto err;
+	if (pss->maskGenAlgorithm) {
+		if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0)
+			goto err;
+		if (BIO_puts(bp, " with ") <= 0)
+			goto err;
+		maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+		if (maskHash != NULL) {
+			if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
+				goto err;
+		} else if (BIO_puts(bp, "INVALID") <= 0) {
+			goto err;
+		}
+	} else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
+		goto err;
+	}
+	BIO_puts(bp, "\n");
+
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+	if (BIO_printf(bp, "%s Salt Length: 0x", pss_key ? "Minimum" : "") <= 0)
+		goto err;
+	if (pss->saltLength) {
+		if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
+			goto err;
+	} else if (BIO_puts(bp, "14 (default)") <= 0) {
+		goto err;
+	}
+	BIO_puts(bp, "\n");
+
+	if (!BIO_indent(bp, indent, 128))
+		goto err;
+	if (BIO_puts(bp, "Trailer Field: 0x") <= 0)
+		goto err;
+	if (pss->trailerField) {
+		if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
+			goto err;
+	} else if (BIO_puts(bp, "BC (default)") <= 0) {
+		goto err;
+	}
+	BIO_puts(bp, "\n");
+
+	rv = 1;
+
+ err:
+	X509_ALGOR_free(maskHash);
+	return rv;
+
+}
+
+static int
+pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
+{
+	const RSA *x = pkey->pkey.rsa;
+	char *str;
+	const char *s;
+	int ret = 0, mod_len = 0;
+
+	if (x->n != NULL)
+		mod_len = BN_num_bits(x->n);
+
+	if (!BIO_indent(bp, off, 128))
+		goto err;
+
+	if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ?  "RSA-PSS" : "RSA") <= 0)
+		goto err;
+
+	if (priv && x->d != NULL) {
+		if (BIO_printf(bp, "Private-Key: (%d bit)\n", mod_len) <= 0)
+			goto err;
+		str = "modulus:";
+		s = "publicExponent:";
+	} else {
+		if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
+			goto err;
+		str = "Modulus:";
+		s = "Exponent:";
+	}
+	if (!bn_printf(bp, x->n, off, "%s", str))
+		goto err;
+	if (!bn_printf(bp, x->e, off, "%s", s))
+		goto err;
+	if (priv) {
+		if (!bn_printf(bp, x->d, off, "privateExponent:"))
+			goto err;
+		if (!bn_printf(bp, x->p, off, "prime1:"))
+			goto err;
+		if (!bn_printf(bp, x->q, off, "prime2:"))
+			goto err;
+		if (!bn_printf(bp, x->dmp1, off, "exponent1:"))
+			goto err;
+		if (!bn_printf(bp, x->dmq1, off, "exponent2:"))
+			goto err;
+		if (!bn_printf(bp, x->iqmp, off, "coefficient:"))
+			goto err;
+	}
+	if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off))
+		goto err;
+	ret = 1;
+ err:
+	return ret;
+}
+
+static int
+rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return pkey_rsa_print(bp, pkey, indent, 0);
+}
+
+static int
+rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
+{
+	return pkey_rsa_print(bp, pkey, indent, 1);
+}
+
+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);
+
+		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) {
+		return 0;
+	}
+	if (sig)
+		return X509_signature_dump(bp, sig, indent);
+	return 1;
+}
+
+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)) {
+				RSAerror(ERR_R_INTERNAL_ERROR);
+				return 0;
+			}
+			*(int *)arg2 = EVP_MD_type(md);
+			/* Return of 2 indicates this MD is mandatory */
+			return 2;
+		}
+		*(int *)arg2 = NID_sha256;
+		return 1;
+
+	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, defaults to 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, &X509_ALGOR_it, &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, defaults to 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)
+		RSAerror(RSA_R_UNKNOWN_DIGEST);
+	return md;
+}
+
+/*
+ * Convert EVP_PKEY_CTX in PSS mode into corresponding algorithm parameter,
+ * suitable for setting an AlgorithmIdentifier.
+ */
+static RSA_PSS_PARAMS *
+rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
+{
+	const EVP_MD *sigmd, *mgf1md;
+	EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
+	int saltlen;
+
+	if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
+		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))
+		return NULL;
+	if (saltlen == -1) {
+		saltlen = EVP_MD_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--;
+		if (saltlen < 0)
+			return NULL;
+	}
+
+	return 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 *pss = RSA_PSS_PARAMS_new();
+
+	if (pss == NULL)
+		goto err;
+	if (saltlen != 20) {
+		pss->saltLength = ASN1_INTEGER_new();
+		if (pss->saltLength == NULL)
+			goto err;
+		if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
+			goto err;
+	}
+	if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
+		goto err;
+	if (mgf1md == NULL)
+		mgf1md = sigmd;
+	if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
+		goto err;
+	if (!rsa_md_to_algor(&pss->maskHash, mgf1md))
+		goto err;
+	return pss;
+ err:
+	RSA_PSS_PARAMS_free(pss);
+	return NULL;
+}
+
+static ASN1_STRING *
+rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
+{
+	RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
+	ASN1_STRING *os;
+
+	if (pss == NULL)
+		return NULL;
+
+	os = ASN1_item_pack(pss, &RSA_PSS_PARAMS_it, NULL);
+	RSA_PSS_PARAMS_free(pss);
+	return os;
+}
+
+/*
+ * From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL
+ * then the EVP_MD_CTX is setup and initialised. If it is NULL parameters are
+ * 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 rv = -1;
+	int saltlen;
+	const EVP_MD *mgf1md = NULL, *md = NULL;
+	RSA_PSS_PARAMS *pss;
+
+	/* Sanity check: make sure it is PSS */
+	if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
+		RSAerror(RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+		return -1;
+	}
+	/* Decode PSS parameters */
+	pss = rsa_pss_decode(sigalg);
+
+	if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
+		RSAerror(RSA_R_INVALID_PSS_PARAMETERS);
+		goto err;
+	}
+
+	/* We have all parameters now set up context */
+	if (pkey) {
+		if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
+			goto err;
+	} else {
+		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)) {
+			RSAerror(RSA_R_DIGEST_DOES_NOT_MATCH);
+			goto err;
+		}
+	}
+
+	if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
+		goto err;
+
+	if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
+		goto err;
+
+	if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
+		goto err;
+	/* Carry on */
+	rv = 1;
+
+ err:
+	RSA_PSS_PARAMS_free(pss);
+	return rv;
+}
+
+int
+rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
+    const EVP_MD **pmgf1md, int *psaltlen)
+{
+	if (pss == NULL)
+		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) {
+			RSAerror(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) {
+		RSAerror(RSA_R_INVALID_TRAILER);
+		return 0;
+	}
+
+	return 1;
+}
+
+#ifndef OPENSSL_NO_CMS
+static int
+rsa_cms_verify(CMS_SignerInfo *si)
+{
+	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)) {
+		RSAerror(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;
+}
+#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)
+{
+	/* Sanity check: make sure it is PSS */
+	if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
+		RSAerror(RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
+		return -1;
+	}
+	if (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,
+    X509_ALGOR *alg1, X509_ALGOR *alg2, ASN1_BIT_STRING *sig)
+{
+	EVP_PKEY_CTX *pkctx = ctx->pctx;
+	int pad_mode;
+
+	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);
+				return 0;
+			}
+			X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
+			    V_ASN1_SEQUENCE, os2);
+		}
+		X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
+		    V_ASN1_SEQUENCE, os1);
+		return 3;
+	}
+	return 2;
+}
+
+static int
+rsa_pkey_check(const EVP_PKEY *pkey)
+{
+	return RSA_check_key(pkey->pkey.rsa);
+}
+
+#ifndef OPENSSL_NO_CMS
+static RSA_OAEP_PARAMS *
+rsa_oaep_decode(const X509_ALGOR *alg)
+{
+	RSA_OAEP_PARAMS *oaep;
+
+	oaep = ASN1_TYPE_unpack_sequence(&RSA_OAEP_PARAMS_it, alg->parameter);
+	if (oaep == NULL)
+		return NULL;
+
+	if (oaep->maskGenFunc != NULL) {
+		oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc);
+		if (oaep->maskHash == NULL) {
+			RSA_OAEP_PARAMS_free(oaep);
+			return NULL;
+		}
+	}
+	return oaep;
+}
+
+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) {
+		RSAerror(RSA_R_UNSUPPORTED_ENCRYPTION_TYPE);
+		return -1;
+	}
+	/* Decode OAEP parameters */
+	oaep = rsa_oaep_decode(cmsalg);
+
+	if (oaep == NULL) {
+		RSAerror(RSA_R_INVALID_OAEP_PARAMETERS);
+		goto err;
+	}
+
+	mgf1md = rsa_algor_to_md(oaep->maskHash);
+	if (mgf1md == NULL)
+		goto err;
+	md = rsa_algor_to_md(oaep->hashFunc);
+	if (md == NULL)
+		goto err;
+
+	if (oaep->pSourceFunc != NULL) {
+		X509_ALGOR *plab = oaep->pSourceFunc;
+
+		if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
+			RSAerror(RSA_R_UNSUPPORTED_LABEL_SOURCE);
+			goto err;
+		}
+		if (plab->parameter->type != V_ASN1_OCTET_STRING) {
+			RSAerror(RSA_R_INVALID_LABEL);
+			goto err;
+		}
+
+		label = plab->parameter->value.octet_string->data;
+
+		/* Stop label being freed when OAEP parameters are freed */
+		/* XXX - this leaks label on error... */
+		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 (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
+		goto err;
+
+	rv = 1;
+
+ err:
+	RSA_OAEP_PARAMS_free(oaep);
+	return rv;
+}
+
+static int
+rsa_cms_encrypt(CMS_RecipientInfo *ri)
+{
+	const EVP_MD *md, *mgf1md;
+	RSA_OAEP_PARAMS *oaep = NULL;
+	ASN1_STRING *os = NULL;
+	X509_ALGOR *alg;
+	EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
+	int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
+	unsigned char *label;
+
+	if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
+		return 0;
+	if (pkctx) {
+		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))
+		goto err;
+	if (labellen > 0) {
+		ASN1_OCTET_STRING *los;
+		oaep->pSourceFunc = X509_ALGOR_new();
+		if (oaep->pSourceFunc == NULL)
+			goto err;
+		los = ASN1_OCTET_STRING_new();
+		if (los == NULL)
+			goto err;
+		if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
+			ASN1_OCTET_STRING_free(los);
+			goto err;
+		}
+		X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
+		    V_ASN1_OCTET_STRING, los);
+	}
+	/* create string with pss parameter encoding. */
+	if (!ASN1_item_pack(oaep, &RSA_OAEP_PARAMS_it, &os))
+		 goto err;
+	X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
+	os = NULL;
+	rv = 1;
+ err:
+	RSA_OAEP_PARAMS_free(oaep);
+	ASN1_STRING_free(os);
+	return rv;
+}
+#endif
+
+const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = {
+	{
+		.pkey_id = EVP_PKEY_RSA,
+		.pkey_base_id = EVP_PKEY_RSA,
+		.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
+
+		.pem_str = "RSA",
+		.info = "OpenSSL RSA method",
+
+		.pub_decode = rsa_pub_decode,
+		.pub_encode = rsa_pub_encode,
+		.pub_cmp = rsa_pub_cmp,
+		.pub_print = rsa_pub_print,
+
+		.priv_decode = rsa_priv_decode,
+		.priv_encode = rsa_priv_encode,
+		.priv_print = rsa_priv_print,
+
+		.pkey_size = rsa_size,
+		.pkey_bits = rsa_bits,
+		.pkey_security_bits = rsa_security_bits,
+
+		.sig_print = rsa_sig_print,
+
+		.pkey_free = rsa_free,
+		.pkey_ctrl = rsa_pkey_ctrl,
+		.old_priv_decode = old_rsa_priv_decode,
+		.old_priv_encode = old_rsa_priv_encode,
+		.item_verify = rsa_item_verify,
+		.item_sign = rsa_item_sign,
+
+		.pkey_check = rsa_pkey_check,
+	},
+
+	{
+		.pkey_id = EVP_PKEY_RSA2,
+		.pkey_base_id = EVP_PKEY_RSA,
+		.pkey_flags = ASN1_PKEY_ALIAS,
+
+		.pkey_check = rsa_pkey_check,
+	},
+};
+
+const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
+	.pkey_id = EVP_PKEY_RSA_PSS,
+	.pkey_base_id = EVP_PKEY_RSA_PSS,
+	.pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
+
+	.pem_str = "RSA-PSS",
+	.info = "OpenSSL RSA-PSS method",
+
+	.pub_decode = rsa_pub_decode,
+	.pub_encode = rsa_pub_encode,
+	.pub_cmp = rsa_pub_cmp,
+	.pub_print = rsa_pub_print,
+
+	.priv_decode = rsa_priv_decode,
+	.priv_encode = rsa_priv_encode,
+	.priv_print = rsa_priv_print,
+
+	.pkey_size = rsa_size,
+	.pkey_bits = rsa_bits,
+	.pkey_security_bits = rsa_security_bits,
+
+	.sig_print = rsa_sig_print,
+
+	.pkey_free = rsa_free,
+	.pkey_ctrl = rsa_pkey_ctrl,
+	.item_verify = rsa_item_verify,
+	.item_sign = rsa_item_sign
+};
diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c
new file mode 100644
index 0000000..0f6d8c4
--- /dev/null
+++ b/crypto/rsa/rsa_asn1.c
@@ -0,0 +1,422 @@
+/* $OpenBSD: rsa_asn1.c,v 1.17 2023/07/08 12:26:45 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "rsa_local.h"
+
+/* Override the default free and new methods */
+static int
+rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	if (operation == ASN1_OP_NEW_PRE) {
+		*pval = (ASN1_VALUE *)RSA_new();
+		if (*pval)
+			return 2;
+		return 0;
+	} else if (operation == ASN1_OP_FREE_PRE) {
+		RSA_free((RSA *)*pval);
+		*pval = NULL;
+		return 2;
+	}
+	return 1;
+}
+
+static const ASN1_AUX RSAPrivateKey_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = rsa_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE RSAPrivateKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, version),
+		.field_name = "version",
+		.item = &LONG_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, n),
+		.field_name = "n",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, e),
+		.field_name = "e",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, d),
+		.field_name = "d",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, p),
+		.field_name = "p",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, q),
+		.field_name = "q",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, dmp1),
+		.field_name = "dmp1",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, dmq1),
+		.field_name = "dmq1",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, iqmp),
+		.field_name = "iqmp",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM RSAPrivateKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = RSAPrivateKey_seq_tt,
+	.tcount = sizeof(RSAPrivateKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &RSAPrivateKey_aux,
+	.size = sizeof(RSA),
+	.sname = "RSA",
+};
+
+
+static const ASN1_AUX RSAPublicKey_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = rsa_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE RSAPublicKey_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, n),
+		.field_name = "n",
+		.item = &BIGNUM_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(RSA, e),
+		.field_name = "e",
+		.item = &BIGNUM_it,
+	},
+};
+
+const ASN1_ITEM RSAPublicKey_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = RSAPublicKey_seq_tt,
+	.tcount = sizeof(RSAPublicKey_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &RSAPublicKey_aux,
+	.size = sizeof(RSA),
+	.sname = "RSA",
+};
+
+static int
+rsa_pss_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	/* Free up maskHash */
+	if (operation == ASN1_OP_FREE_PRE) {
+		RSA_PSS_PARAMS *pss = (RSA_PSS_PARAMS *)*pval;
+		X509_ALGOR_free(pss->maskHash);
+	}
+	return 1;
+}
+
+static const ASN1_AUX RSA_PSS_PARAMS_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = rsa_pss_cb,
+	.enc_offset = 0,
+};
+
+static const ASN1_TEMPLATE RSA_PSS_PARAMS_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(RSA_PSS_PARAMS, hashAlgorithm),
+		.field_name = "hashAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(RSA_PSS_PARAMS, maskGenAlgorithm),
+		.field_name = "maskGenAlgorithm",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(RSA_PSS_PARAMS, saltLength),
+		.field_name = "saltLength",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 3,
+		.offset = offsetof(RSA_PSS_PARAMS, trailerField),
+		.field_name = "trailerField",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM RSA_PSS_PARAMS_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = RSA_PSS_PARAMS_seq_tt,
+	.tcount = sizeof(RSA_PSS_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &RSA_PSS_PARAMS_aux,
+	.size = sizeof(RSA_PSS_PARAMS),
+	.sname = "RSA_PSS_PARAMS",
+};
+
+RSA_PSS_PARAMS *
+d2i_RSA_PSS_PARAMS(RSA_PSS_PARAMS **a, const unsigned char **in, long len)
+{
+	return (RSA_PSS_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &RSA_PSS_PARAMS_it);
+}
+LCRYPTO_ALIAS(d2i_RSA_PSS_PARAMS);
+
+int
+i2d_RSA_PSS_PARAMS(RSA_PSS_PARAMS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSA_PSS_PARAMS_it);
+}
+LCRYPTO_ALIAS(i2d_RSA_PSS_PARAMS);
+
+RSA_PSS_PARAMS *
+RSA_PSS_PARAMS_new(void)
+{
+	return (RSA_PSS_PARAMS *)ASN1_item_new(&RSA_PSS_PARAMS_it);
+}
+LCRYPTO_ALIAS(RSA_PSS_PARAMS_new);
+
+void
+RSA_PSS_PARAMS_free(RSA_PSS_PARAMS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &RSA_PSS_PARAMS_it);
+}
+LCRYPTO_ALIAS(RSA_PSS_PARAMS_free);
+
+static int
+rsa_oaep_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	/* Free up maskHash */
+	if (operation == ASN1_OP_FREE_PRE) {
+		RSA_OAEP_PARAMS *oaep = (RSA_OAEP_PARAMS *)*pval;
+		X509_ALGOR_free(oaep->maskHash);
+	}
+	return 1;
+}
+
+static const ASN1_AUX RSA_OAEP_PARAMS_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = rsa_oaep_cb,
+	.enc_offset = 0,
+};
+
+static const ASN1_TEMPLATE RSA_OAEP_PARAMS_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(RSA_OAEP_PARAMS, hashFunc),
+		.field_name = "hashFunc",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(RSA_OAEP_PARAMS, maskGenFunc),
+		.field_name = "maskGenFunc",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 2,
+		.offset = offsetof(RSA_OAEP_PARAMS, pSourceFunc),
+		.field_name = "pSourceFunc",
+		.item = &X509_ALGOR_it,
+	},
+};
+
+const ASN1_ITEM RSA_OAEP_PARAMS_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = RSA_OAEP_PARAMS_seq_tt,
+	.tcount = sizeof(RSA_OAEP_PARAMS_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &RSA_OAEP_PARAMS_aux,
+	.size = sizeof(RSA_OAEP_PARAMS),
+	.sname = "RSA_OAEP_PARAMS",
+};
+
+
+RSA_OAEP_PARAMS *
+d2i_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS **a, const unsigned char **in, long len)
+{
+	return (RSA_OAEP_PARAMS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &RSA_OAEP_PARAMS_it);
+}
+LCRYPTO_ALIAS(d2i_RSA_OAEP_PARAMS);
+
+int
+i2d_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSA_OAEP_PARAMS_it);
+}
+LCRYPTO_ALIAS(i2d_RSA_OAEP_PARAMS);
+
+RSA_OAEP_PARAMS *
+RSA_OAEP_PARAMS_new(void)
+{
+	return (RSA_OAEP_PARAMS *)ASN1_item_new(&RSA_OAEP_PARAMS_it);
+}
+LCRYPTO_ALIAS(RSA_OAEP_PARAMS_new);
+
+void
+RSA_OAEP_PARAMS_free(RSA_OAEP_PARAMS *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &RSA_OAEP_PARAMS_it);
+}
+LCRYPTO_ALIAS(RSA_OAEP_PARAMS_free);
+
+RSA *
+d2i_RSAPrivateKey(RSA **a, const unsigned char **in, long len)
+{
+	return (RSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &RSAPrivateKey_it);
+}
+LCRYPTO_ALIAS(d2i_RSAPrivateKey);
+
+int
+i2d_RSAPrivateKey(const RSA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSAPrivateKey_it);
+}
+LCRYPTO_ALIAS(i2d_RSAPrivateKey);
+
+
+RSA *
+d2i_RSAPublicKey(RSA **a, const unsigned char **in, long len)
+{
+	return (RSA *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &RSAPublicKey_it);
+}
+LCRYPTO_ALIAS(d2i_RSAPublicKey);
+
+int
+i2d_RSAPublicKey(const RSA *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &RSAPublicKey_it);
+}
+LCRYPTO_ALIAS(i2d_RSAPublicKey);
+
+RSA *
+RSAPublicKey_dup(RSA *rsa)
+{
+	return ASN1_item_dup(&RSAPublicKey_it, rsa);
+}
+LCRYPTO_ALIAS(RSAPublicKey_dup);
+
+RSA *
+RSAPrivateKey_dup(RSA *rsa)
+{
+	return ASN1_item_dup(&RSAPrivateKey_it, rsa);
+}
+LCRYPTO_ALIAS(RSAPrivateKey_dup);
diff --git a/crypto/rsa/rsa_blinding.c b/crypto/rsa/rsa_blinding.c
new file mode 100644
index 0000000..cac5bd9
--- /dev/null
+++ b/crypto/rsa/rsa_blinding.c
@@ -0,0 +1,361 @@
+/* $OpenBSD: rsa_blinding.c,v 1.3 2023/08/09 12:09:06 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "bn_local.h"
+#include "rsa_local.h"
+
+#define BN_BLINDING_COUNTER	32
+
+struct bn_blinding_st {
+	BIGNUM *A;
+	BIGNUM *Ai;
+	BIGNUM *e;
+	BIGNUM *mod;
+	pthread_t tid;
+	int counter;
+	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);
+};
+
+BN_BLINDING *
+BN_BLINDING_new(const BIGNUM *e, const BIGNUM *mod, BN_CTX *ctx,
+    int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx)
+{
+	BN_BLINDING *ret = NULL;
+
+	if ((ret = calloc(1, sizeof(BN_BLINDING))) == NULL) {
+		BNerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if ((ret->A = BN_new()) == NULL)
+		goto err;
+	if ((ret->Ai = BN_new()) == NULL)
+		goto err;
+	if ((ret->e = BN_dup(e)) == NULL)
+		goto err;
+	if ((ret->mod = BN_dup(mod)) == NULL)
+		goto err;
+	if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
+		BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+
+	/* Update on first use. */
+	ret->counter = BN_BLINDING_COUNTER - 1;
+	ret->tid = pthread_self();
+
+	if (bn_mod_exp != NULL)
+		ret->bn_mod_exp = bn_mod_exp;
+	if (m_ctx != NULL)
+		ret->m_ctx = m_ctx;
+
+	return ret;
+
+ err:
+	BN_BLINDING_free(ret);
+
+	return NULL;
+}
+
+void
+BN_BLINDING_free(BN_BLINDING *r)
+{
+	if (r == NULL)
+		return;
+
+	BN_free(r->A);
+	BN_free(r->Ai);
+	BN_free(r->e);
+	BN_free(r->mod);
+	free(r);
+}
+
+static int
+BN_BLINDING_setup(BN_BLINDING *b, BN_CTX *ctx)
+{
+	if (!bn_rand_interval(b->A, 1, b->mod))
+		return 0;
+	if (BN_mod_inverse_ct(b->Ai, b->A, b->mod, ctx) == NULL)
+		return 0;
+
+	if (b->bn_mod_exp != NULL && b->m_ctx != NULL) {
+		if (!b->bn_mod_exp(b->A, b->A, b->e, b->mod, ctx, b->m_ctx))
+			return 0;
+	} else {
+		if (!BN_mod_exp_ct(b->A, b->A, b->e, b->mod, ctx))
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
+{
+	int ret = 0;
+
+	if (++b->counter >= BN_BLINDING_COUNTER) {
+		if (!BN_BLINDING_setup(b, ctx))
+			goto err;
+		b->counter = 0;
+	} else {
+		if (!BN_mod_sqr(b->A, b->A, b->mod, ctx))
+			goto err;
+		if (!BN_mod_sqr(b->Ai, b->Ai, b->mod, ctx))
+			goto err;
+	}
+
+	ret = 1;
+
+ err:
+	return ret;
+}
+
+int
+BN_BLINDING_convert(BIGNUM *n, BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx)
+{
+	int ret = 0;
+
+	if (!BN_BLINDING_update(b, ctx))
+		goto err;
+
+	if (inv != NULL) {
+		if (!bn_copy(inv, b->Ai))
+			goto err;
+	}
+
+	ret = BN_mod_mul(n, n, b->A, b->mod, ctx);
+
+ err:
+	return ret;
+}
+
+int
+BN_BLINDING_invert(BIGNUM *n, const BIGNUM *inv, BN_BLINDING *b, BN_CTX *ctx)
+{
+	if (inv == NULL)
+		inv = b->Ai;
+
+	return BN_mod_mul(n, n, inv, b->mod, ctx);
+}
+
+int
+BN_BLINDING_is_local(BN_BLINDING *b)
+{
+	return pthread_equal(pthread_self(), b->tid) != 0;
+}
+
+static BIGNUM *
+rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, const BIGNUM *q,
+    BN_CTX *ctx)
+{
+	BIGNUM *ret = NULL, *r0, *r1, *r2;
+
+	if (d == NULL || p == NULL || q == NULL)
+		return NULL;
+
+	BN_CTX_start(ctx);
+	if ((r0 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	if (!BN_sub(r1, p, BN_value_one()))
+		goto err;
+	if (!BN_sub(r2, q, BN_value_one()))
+		goto err;
+	if (!BN_mul(r0, r1, r2, ctx))
+		goto err;
+
+	ret = BN_mod_inverse_ct(NULL, d, r0, ctx);
+err:
+	BN_CTX_end(ctx);
+	return ret;
+}
+
+BN_BLINDING *
+RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
+{
+	BIGNUM *e = NULL;
+	BIGNUM n;
+	BN_CTX *ctx = NULL;
+	BN_BLINDING *ret = NULL;
+
+	if ((ctx = in_ctx) == NULL)
+		ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+
+	if ((e = rsa->e) == NULL)
+		e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
+	if (e == NULL) {
+		RSAerror(RSA_R_NO_PUBLIC_EXPONENT);
+		goto err;
+	}
+
+	BN_init(&n);
+	BN_with_flags(&n, rsa->n, BN_FLG_CONSTTIME);
+
+	if ((ret = BN_BLINDING_new(e, &n, ctx, rsa->meth->bn_mod_exp,
+	    rsa->_method_mod_n)) == NULL) {
+		RSAerror(ERR_R_BN_LIB);
+		goto err;
+	}
+
+ err:
+	BN_CTX_end(ctx);
+	if (ctx != in_ctx)
+		BN_CTX_free(ctx);
+	if (e != rsa->e)
+		BN_free(e);
+
+	return ret;
+}
+
+void
+RSA_blinding_off(RSA *rsa)
+{
+	BN_BLINDING_free(rsa->blinding);
+	rsa->blinding = NULL;
+	rsa->flags |= RSA_FLAG_NO_BLINDING;
+}
+LCRYPTO_ALIAS(RSA_blinding_off);
+
+int
+RSA_blinding_on(RSA *rsa, BN_CTX *ctx)
+{
+	int ret = 0;
+
+	if (rsa->blinding != NULL)
+		RSA_blinding_off(rsa);
+
+	rsa->blinding = RSA_setup_blinding(rsa, ctx);
+	if (rsa->blinding == NULL)
+		goto err;
+
+	rsa->flags &= ~RSA_FLAG_NO_BLINDING;
+	ret = 1;
+err:
+	return (ret);
+}
+LCRYPTO_ALIAS(RSA_blinding_on);
diff --git a/crypto/rsa/rsa_chk.c b/crypto/rsa/rsa_chk.c
new file mode 100644
index 0000000..b7666e0
--- /dev/null
+++ b/crypto/rsa/rsa_chk.c
@@ -0,0 +1,223 @@
+/* $OpenBSD: rsa_chk.c,v 1.18 2023/07/08 12:26:45 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "rsa_local.h"
+
+int
+RSA_check_key(const RSA *key)
+{
+	BIGNUM *i, *j, *k, *l, *m;
+	BN_CTX *ctx;
+	int r;
+	int ret = 1;
+
+	if (!key->p || !key->q || !key->n || !key->e || !key->d) {
+		RSAerror(RSA_R_VALUE_MISSING);
+		return 0;
+	}
+
+	i = BN_new();
+	j = BN_new();
+	k = BN_new();
+	l = BN_new();
+	m = BN_new();
+	ctx = BN_CTX_new();
+	if (i == NULL || j == NULL || k == NULL || l == NULL || m == NULL ||
+	    ctx == NULL) {
+		ret = -1;
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (BN_is_one(key->e)) {
+		ret = 0;
+		RSAerror(RSA_R_BAD_E_VALUE);
+	}
+	if (!BN_is_odd(key->e)) {
+		ret = 0;
+		RSAerror(RSA_R_BAD_E_VALUE);
+	}
+
+	/* p prime? */
+	r = BN_is_prime_ex(key->p, BN_prime_checks, NULL, NULL);
+	if (r != 1) {
+		ret = r;
+		if (r != 0)
+			goto err;
+		RSAerror(RSA_R_P_NOT_PRIME);
+	}
+
+	/* q prime? */
+	r = BN_is_prime_ex(key->q, BN_prime_checks, NULL, NULL);
+	if (r != 1) {
+		ret = r;
+		if (r != 0)
+			goto err;
+		RSAerror(RSA_R_Q_NOT_PRIME);
+	}
+
+	/* n = p*q? */
+	r = BN_mul(i, key->p, key->q, ctx);
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+
+	if (BN_cmp(i, key->n) != 0) {
+		ret = 0;
+		RSAerror(RSA_R_N_DOES_NOT_EQUAL_P_Q);
+	}
+
+	/* d*e = 1  mod lcm(p-1,q-1)? */
+
+	r = BN_sub(i, key->p, BN_value_one());
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+	r = BN_sub(j, key->q, BN_value_one());
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+
+	/* now compute k = lcm(i,j) */
+	r = BN_mul(l, i, j, ctx);
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+	r = BN_gcd_ct(m, i, j, ctx);
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+	r = BN_div_ct(k, NULL, l, m, ctx); /* remainder is 0 */
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+
+	r = BN_mod_mul(i, key->d, key->e, k, ctx);
+	if (!r) {
+		ret = -1;
+		goto err;
+	}
+
+	if (!BN_is_one(i)) {
+		ret = 0;
+		RSAerror(RSA_R_D_E_NOT_CONGRUENT_TO_1);
+	}
+
+	if (key->dmp1 != NULL && key->dmq1 != NULL && key->iqmp != NULL) {
+		/* dmp1 = d mod (p-1)? */
+		r = BN_sub(i, key->p, BN_value_one());
+		if (!r) {
+			ret = -1;
+			goto err;
+		}
+
+		r = BN_mod_ct(j, key->d, i, ctx);
+		if (!r) {
+			ret = -1;
+			goto err;
+		}
+
+		if (BN_cmp(j, key->dmp1) != 0) {
+			ret = 0;
+			RSAerror(RSA_R_DMP1_NOT_CONGRUENT_TO_D);
+		}
+
+		/* dmq1 = d mod (q-1)? */
+		r = BN_sub(i, key->q, BN_value_one());
+		if (!r) {
+			ret = -1;
+			goto err;
+		}
+
+		r = BN_mod_ct(j, key->d, i, ctx);
+		if (!r) {
+			ret = -1;
+			goto err;
+		}
+
+		if (BN_cmp(j, key->dmq1) != 0) {
+			ret = 0;
+			RSAerror(RSA_R_DMQ1_NOT_CONGRUENT_TO_D);
+		}
+
+		/* iqmp = q^-1 mod p? */
+		if (BN_mod_inverse_ct(i, key->q, key->p, ctx) == NULL) {
+			ret = -1;
+			goto err;
+		}
+
+		if (BN_cmp(i, key->iqmp) != 0) {
+			ret = 0;
+			RSAerror(RSA_R_IQMP_NOT_INVERSE_OF_Q);
+		}
+	}
+
+err:
+	BN_free(i);
+	BN_free(j);
+	BN_free(k);
+	BN_free(l);
+	BN_free(m);
+	BN_CTX_free(ctx);
+
+	return (ret);
+}
+LCRYPTO_ALIAS(RSA_check_key);
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
new file mode 100644
index 0000000..c2e1e22
--- /dev/null
+++ b/crypto/rsa/rsa_eay.c
@@ -0,0 +1,902 @@
+/* $OpenBSD: rsa_eay.c,v 1.65 2023/08/09 12:09:06 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "rsa_local.h"
+
+static int
+rsa_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	BIGNUM *f, *ret;
+	int i, j, k, num = 0, r = -1;
+	unsigned char *buf = NULL;
+	BN_CTX *ctx = NULL;
+
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
+		RSAerror(RSA_R_MODULUS_TOO_LARGE);
+		return -1;
+	}
+
+	if (BN_ucmp(rsa->n, rsa->e) <= 0) {
+		RSAerror(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) {
+			RSAerror(RSA_R_BAD_E_VALUE);
+			return -1;
+		}
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+	f = BN_CTX_get(ctx);
+	ret = BN_CTX_get(ctx);
+	num = BN_num_bytes(rsa->n);
+	buf = malloc(num);
+
+	if (f == NULL || ret == NULL || buf == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	switch (padding) {
+	case RSA_PKCS1_PADDING:
+		i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
+		break;
+#ifndef OPENSSL_NO_SHA
+	case RSA_PKCS1_OAEP_PADDING:
+		i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
+		break;
+#endif
+	case RSA_NO_PADDING:
+		i = RSA_padding_add_none(buf, num, from, flen);
+		break;
+	default:
+		RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
+		goto err;
+	}
+	if (i <= 0)
+		goto err;
+
+	if (BN_bin2bn(buf, num, f) == NULL)
+		goto err;
+
+	if (BN_ucmp(f, rsa->n) >= 0) {
+		/* usually the padding functions would catch this */
+		RSAerror(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,
+		    CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
+	}
+
+	if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
+	    rsa->_method_mod_n))
+		goto err;
+
+	/* put in leading 0 bytes if the number is less than the
+	 * length of the modulus */
+	j = BN_num_bytes(ret);
+	i = BN_bn2bin(ret, &(to[num - j]));
+	for (k = 0; k < num - i; k++)
+		to[k] = 0;
+
+	r = num;
+err:
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	freezero(buf, num);
+	return r;
+}
+
+static BN_BLINDING *
+rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
+{
+	BN_BLINDING *ret;
+	int got_write_lock = 0;
+
+	CRYPTO_r_lock(CRYPTO_LOCK_RSA);
+
+	if (rsa->blinding == NULL) {
+		CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+		CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+		got_write_lock = 1;
+
+		if (rsa->blinding == NULL)
+			rsa->blinding = RSA_setup_blinding(rsa, ctx);
+	}
+
+	if ((ret = rsa->blinding) == NULL)
+		goto err;
+
+	/*
+	 * We need a shared blinding. Accesses require locks and a copy of the
+	 * blinding factor needs to be retained on use.
+	 */
+	if ((*local = BN_BLINDING_is_local(ret)) == 0) {
+		if (rsa->mt_blinding == NULL) {
+			if (!got_write_lock) {
+				CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+				CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+				got_write_lock = 1;
+			}
+
+			if (rsa->mt_blinding == NULL)
+				rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
+		}
+		ret = rsa->mt_blinding;
+	}
+
+ err:
+	if (got_write_lock)
+		CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+	else
+		CRYPTO_r_unlock(CRYPTO_LOCK_RSA);
+
+	return ret;
+}
+
+static int
+rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, BN_CTX *ctx)
+{
+	if (unblind == NULL)
+		/*
+		 * Local blinding: store the unblinding factor
+		 * in BN_BLINDING.
+		 */
+		return BN_BLINDING_convert(f, NULL, b, ctx);
+	else {
+		/*
+		 * Shared blinding: store the unblinding factor
+		 * outside BN_BLINDING.
+		 */
+		int ret;
+		CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+		ret = BN_BLINDING_convert(f, unblind, b, ctx);
+		CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+		return ret;
+	}
+}
+
+static int
+rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind, BN_CTX *ctx)
+{
+	/*
+	 * For local blinding, unblind is set to NULL, and BN_BLINDING_invert()
+	 * will use the unblinding factor stored in BN_BLINDING.
+	 * If BN_BLINDING is shared between threads, unblind must be non-null:
+	 * BN_BLINDING_invert() will then use the local unblinding factor,
+	 * and will only read the modulus from BN_BLINDING.
+	 * In both cases it's safe to access the blinding without a lock.
+	 */
+	return BN_BLINDING_invert(f, unblind, b, ctx);
+}
+
+/* signing */
+static int
+rsa_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	BIGNUM *f, *ret, *res;
+	int i, j, k, num = 0, r = -1;
+	unsigned char *buf = NULL;
+	BN_CTX *ctx = NULL;
+	int local_blinding = 0;
+	/*
+	 * Used only if the blinding structure is shared. A non-NULL unblind
+	 * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
+	 * the unblinding factor outside the blinding structure.
+	 */
+	BIGNUM *unblind = NULL;
+	BN_BLINDING *blinding = NULL;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+	f = BN_CTX_get(ctx);
+	ret = BN_CTX_get(ctx);
+	num = BN_num_bytes(rsa->n);
+	buf = malloc(num);
+
+	if (f == NULL || ret == NULL || buf == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	switch (padding) {
+	case RSA_PKCS1_PADDING:
+		i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
+		break;
+	case RSA_X931_PADDING:
+		i = RSA_padding_add_X931(buf, num, from, flen);
+		break;
+	case RSA_NO_PADDING:
+		i = RSA_padding_add_none(buf, num, from, flen);
+		break;
+	default:
+		RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
+		goto err;
+	}
+	if (i <= 0)
+		goto err;
+
+	if (BN_bin2bn(buf, num, f) == NULL)
+		goto err;
+
+	if (BN_ucmp(f, rsa->n) >= 0) {
+		/* usually the padding functions would catch this */
+		RSAerror(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,
+		    CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
+	}
+
+	if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
+		if (blinding == NULL) {
+			RSAerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+
+	if (blinding != NULL) {
+		if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
+			RSAerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
+			goto err;
+	}
+
+	if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
+	    (rsa->p != NULL && rsa->q != NULL && rsa->dmp1 != NULL &&
+	    rsa->dmq1 != NULL && rsa->iqmp != NULL)) {
+		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
+			goto err;
+	} else {
+		BIGNUM d;
+
+		BN_init(&d);
+		BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME);
+
+		if (!rsa->meth->bn_mod_exp(ret, f, &d, rsa->n, ctx,
+		    rsa->_method_mod_n)) {
+			goto err;
+		}
+	}
+
+	if (blinding)
+		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
+			goto err;
+
+	if (padding == RSA_X931_PADDING) {
+		if (!BN_sub(f, rsa->n, ret))
+			goto err;
+		if (BN_cmp(ret, f) > 0)
+			res = f;
+		else
+			res = ret;
+	} else
+		res = ret;
+
+	/* put in leading 0 bytes if the number is less than the
+	 * length of the modulus */
+	j = BN_num_bytes(res);
+	i = BN_bn2bin(res, &(to[num - j]));
+	for (k = 0; k < num - i; k++)
+		to[k] = 0;
+
+	r = num;
+err:
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	freezero(buf, num);
+	return r;
+}
+
+static int
+rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	BIGNUM *f, *ret;
+	int j, num = 0, r = -1;
+	unsigned char *p;
+	unsigned char *buf = NULL;
+	BN_CTX *ctx = NULL;
+	int local_blinding = 0;
+	/*
+	 * Used only if the blinding structure is shared. A non-NULL unblind
+	 * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
+	 * the unblinding factor outside the blinding structure.
+	 */
+	BIGNUM *unblind = NULL;
+	BN_BLINDING *blinding = NULL;
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+	f = BN_CTX_get(ctx);
+	ret = BN_CTX_get(ctx);
+	num = BN_num_bytes(rsa->n);
+	buf = malloc(num);
+
+	if (!f || !ret || !buf) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* This check was for equality but PGP does evil things
+	 * and chops off the top '0' bytes */
+	if (flen > num) {
+		RSAerror(RSA_R_DATA_GREATER_THAN_MOD_LEN);
+		goto err;
+	}
+
+	/* make data into a big number */
+	if (BN_bin2bn(from, (int)flen, f) == NULL)
+		goto err;
+
+	if (BN_ucmp(f, rsa->n) >= 0) {
+		RSAerror(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,
+		    CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
+	}
+
+	if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
+		if (blinding == NULL) {
+			RSAerror(ERR_R_INTERNAL_ERROR);
+			goto err;
+		}
+	}
+
+	if (blinding != NULL) {
+		if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
+			RSAerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
+			goto err;
+	}
+
+	/* do the decrypt */
+	if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
+	    (rsa->p != NULL && rsa->q != NULL && rsa->dmp1 != NULL &&
+	    rsa->dmq1 != NULL && rsa->iqmp != NULL)) {
+		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
+			goto err;
+	} else {
+		BIGNUM d;
+
+		BN_init(&d);
+		BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME);
+
+		if (!rsa->meth->bn_mod_exp(ret, f, &d, rsa->n, ctx,
+		    rsa->_method_mod_n)) {
+			goto err;
+		}
+	}
+
+	if (blinding)
+		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
+			goto err;
+
+	p = buf;
+	j = BN_bn2bin(ret, p); /* j is only used with no-padding mode */
+
+	switch (padding) {
+	case RSA_PKCS1_PADDING:
+		r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
+		break;
+#ifndef OPENSSL_NO_SHA
+	case RSA_PKCS1_OAEP_PADDING:
+		r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
+		break;
+#endif
+	case RSA_NO_PADDING:
+		r = RSA_padding_check_none(to, num, buf, j, num);
+		break;
+	default:
+		RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
+		goto err;
+	}
+	if (r < 0)
+		RSAerror(RSA_R_PADDING_CHECK_FAILED);
+
+err:
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	freezero(buf, num);
+	return r;
+}
+
+/* signature verification */
+static int
+rsa_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	BIGNUM *f, *ret;
+	int i, num = 0, r = -1;
+	unsigned char *p;
+	unsigned char *buf = NULL;
+	BN_CTX *ctx = NULL;
+
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
+		RSAerror(RSA_R_MODULUS_TOO_LARGE);
+		return -1;
+	}
+
+	if (BN_ucmp(rsa->n, rsa->e) <= 0) {
+		RSAerror(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) {
+			RSAerror(RSA_R_BAD_E_VALUE);
+			return -1;
+		}
+	}
+
+	if ((ctx = BN_CTX_new()) == NULL)
+		goto err;
+
+	BN_CTX_start(ctx);
+	f = BN_CTX_get(ctx);
+	ret = BN_CTX_get(ctx);
+	num = BN_num_bytes(rsa->n);
+	buf = malloc(num);
+
+	if (!f || !ret || !buf) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* This check was for equality but PGP does evil things
+	 * and chops off the top '0' bytes */
+	if (flen > num) {
+		RSAerror(RSA_R_DATA_GREATER_THAN_MOD_LEN);
+		goto err;
+	}
+
+	if (BN_bin2bn(from, flen, f) == NULL)
+		goto err;
+
+	if (BN_ucmp(f, rsa->n) >= 0) {
+		RSAerror(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,
+		    CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
+	}
+
+	if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
+	    rsa->_method_mod_n))
+		goto err;
+
+	if (padding == RSA_X931_PADDING && (ret->d[0] & 0xf) != 12)
+		if (!BN_sub(ret, rsa->n, ret))
+			goto err;
+
+	p = buf;
+	i = BN_bn2bin(ret, p);
+
+	switch (padding) {
+	case RSA_PKCS1_PADDING:
+		r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
+		break;
+	case RSA_X931_PADDING:
+		r = RSA_padding_check_X931(to, num, buf, i, num);
+		break;
+	case RSA_NO_PADDING:
+		r = RSA_padding_check_none(to, num, buf, i, num);
+		break;
+	default:
+		RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
+		goto err;
+	}
+	if (r < 0)
+		RSAerror(RSA_R_PADDING_CHECK_FAILED);
+
+err:
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+	freezero(buf, num);
+	return r;
+}
+
+static int
+rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+{
+	BIGNUM *r1, *m1, *vrfy;
+	BIGNUM dmp1, dmq1, c, pr1;
+	int ret = 0;
+
+	BN_CTX_start(ctx);
+	r1 = BN_CTX_get(ctx);
+	m1 = BN_CTX_get(ctx);
+	vrfy = BN_CTX_get(ctx);
+	if (r1 == NULL || m1 == NULL || vrfy == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	{
+		BIGNUM p, q;
+
+		/*
+		 * Make sure BN_mod_inverse in Montgomery initialization uses the
+		 * BN_FLG_CONSTTIME flag
+		 */
+		BN_init(&p);
+		BN_init(&q);
+		BN_with_flags(&p, rsa->p, BN_FLG_CONSTTIME);
+		BN_with_flags(&q, rsa->q, BN_FLG_CONSTTIME);
+
+		if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
+			if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p,
+			     CRYPTO_LOCK_RSA, &p, ctx) ||
+			    !BN_MONT_CTX_set_locked(&rsa->_method_mod_q,
+			     CRYPTO_LOCK_RSA, &q, ctx)) {
+				goto err;
+			}
+		}
+	}
+
+	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
+		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n,
+		    CRYPTO_LOCK_RSA, rsa->n, ctx))
+			goto err;
+	}
+
+	/* compute I mod q */
+	BN_init(&c);
+	BN_with_flags(&c, I, BN_FLG_CONSTTIME);
+
+	if (!BN_mod_ct(r1, &c, rsa->q, ctx))
+		goto err;
+
+	/* compute r1^dmq1 mod q */
+	BN_init(&dmq1);
+	BN_with_flags(&dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
+
+	if (!rsa->meth->bn_mod_exp(m1, r1, &dmq1, rsa->q, ctx,
+	    rsa->_method_mod_q))
+		goto err;
+
+	/* compute I mod p */
+	BN_init(&c);
+	BN_with_flags(&c, I, BN_FLG_CONSTTIME);
+
+	if (!BN_mod_ct(r1, &c, rsa->p, ctx))
+		goto err;
+
+	/* compute r1^dmp1 mod p */
+	BN_init(&dmp1);
+	BN_with_flags(&dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
+
+	if (!rsa->meth->bn_mod_exp(r0, r1, &dmp1, rsa->p, ctx,
+	    rsa->_method_mod_p))
+		goto err;
+
+	if (!BN_sub(r0, r0, m1))
+		goto err;
+
+	/*
+	 * This will help stop the size of r0 increasing, which does
+	 * affect the multiply if it optimised for a power of 2 size
+	 */
+	if (BN_is_negative(r0))
+		if (!BN_add(r0, r0, rsa->p))
+			goto err;
+
+	if (!BN_mul(r1, r0, rsa->iqmp, ctx))
+		goto err;
+
+	/* Turn BN_FLG_CONSTTIME flag on before division operation */
+	BN_init(&pr1);
+	BN_with_flags(&pr1, r1, BN_FLG_CONSTTIME);
+
+	if (!BN_mod_ct(r0, &pr1, rsa->p, ctx))
+		goto err;
+
+	/*
+	 * If p < q it is occasionally possible for the correction of
+	 * adding 'p' if r0 is negative above to leave the result still
+	 * negative. This can break the private key operations: the following
+	 * second correction should *always* correct this rare occurrence.
+	 * This will *never* happen with OpenSSL generated keys because
+	 * they ensure p > q [steve]
+	 */
+	if (BN_is_negative(r0))
+		if (!BN_add(r0, r0, rsa->p))
+			goto err;
+	if (!BN_mul(r1, r0, rsa->q, ctx))
+		goto err;
+	if (!BN_add(r0, r1, m1))
+		goto err;
+
+	if (rsa->e && rsa->n) {
+		if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
+		    rsa->_method_mod_n))
+			goto err;
+		/*
+		 * If 'I' was greater than (or equal to) rsa->n, the operation
+		 * will be equivalent to using 'I mod n'. However, the result of
+		 * the verify will *always* be less than 'n' so we don't check
+		 * for absolute equality, just congruency.
+		 */
+		if (!BN_sub(vrfy, vrfy, I))
+			goto err;
+		if (!BN_mod_ct(vrfy, vrfy, rsa->n, ctx))
+			goto err;
+		if (BN_is_negative(vrfy))
+			if (!BN_add(vrfy, vrfy, rsa->n))
+				goto err;
+		if (!BN_is_zero(vrfy)) {
+			/*
+			 * 'I' and 'vrfy' aren't congruent mod n. Don't leak
+			 * miscalculated CRT output, just do a raw (slower)
+			 * mod_exp and return that instead.
+			 */
+			BIGNUM d;
+
+			BN_init(&d);
+			BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME);
+
+			if (!rsa->meth->bn_mod_exp(r0, I, &d, rsa->n, ctx,
+			    rsa->_method_mod_n)) {
+				goto err;
+			}
+		}
+	}
+	ret = 1;
+err:
+	BN_CTX_end(ctx);
+	return ret;
+}
+
+static int
+rsa_init(RSA *rsa)
+{
+	rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
+	return 1;
+}
+
+static int
+rsa_finish(RSA *rsa)
+{
+	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;
+}
+
+static const RSA_METHOD rsa_pkcs1_meth = {
+	.name = "OpenSSL PKCS#1 RSA",
+	.rsa_pub_enc = rsa_public_encrypt,
+	.rsa_pub_dec = rsa_public_decrypt, /* signature verification */
+	.rsa_priv_enc = rsa_private_encrypt, /* signing */
+	.rsa_priv_dec = rsa_private_decrypt,
+	.rsa_mod_exp = rsa_mod_exp,
+	.bn_mod_exp = BN_mod_exp_mont_ct, /* XXX probably we should not use Montgomery if  e == 3 */
+	.init = rsa_init,
+	.finish = rsa_finish,
+};
+
+const RSA_METHOD *
+RSA_PKCS1_OpenSSL(void)
+{
+	return &rsa_pkcs1_meth;
+}
+LCRYPTO_ALIAS(RSA_PKCS1_OpenSSL);
+
+const RSA_METHOD *
+RSA_PKCS1_SSLeay(void)
+{
+	return RSA_PKCS1_OpenSSL();
+}
+LCRYPTO_ALIAS(RSA_PKCS1_SSLeay);
+
+int
+RSA_bits(const RSA *r)
+{
+	return BN_num_bits(r->n);
+}
+LCRYPTO_ALIAS(RSA_bits);
+
+int
+RSA_size(const RSA *r)
+{
+	return BN_num_bytes(r->n);
+}
+LCRYPTO_ALIAS(RSA_size);
+
+int
+RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	return rsa->meth->rsa_pub_enc(flen, from, to, rsa, padding);
+}
+LCRYPTO_ALIAS(RSA_public_encrypt);
+
+int
+RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	return rsa->meth->rsa_priv_enc(flen, from, to, rsa, padding);
+}
+LCRYPTO_ALIAS(RSA_private_encrypt);
+
+int
+RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	return rsa->meth->rsa_priv_dec(flen, from, to, rsa, padding);
+}
+LCRYPTO_ALIAS(RSA_private_decrypt);
+
+int
+RSA_public_decrypt(int flen, const unsigned char *from, unsigned char *to,
+    RSA *rsa, int padding)
+{
+	return rsa->meth->rsa_pub_dec(flen, from, to, rsa, padding);
+}
+LCRYPTO_ALIAS(RSA_public_decrypt);
+
+int
+RSA_flags(const RSA *r)
+{
+	return r == NULL ? 0 : r->meth->flags;
+}
+LCRYPTO_ALIAS(RSA_flags);
diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c
new file mode 100644
index 0000000..8b54168
--- /dev/null
+++ b/crypto/rsa/rsa_err.c
@@ -0,0 +1,158 @@
+/* $OpenBSD: rsa_err.c,v 1.22 2023/07/08 12:26:45 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_RSA,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_RSA,0,reason)
+
+static ERR_STRING_DATA RSA_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA RSA_str_reasons[] = {
+	{ERR_REASON(RSA_R_ALGORITHM_MISMATCH)    , "algorithm mismatch"},
+	{ERR_REASON(RSA_R_BAD_E_VALUE)           , "bad e value"},
+	{ERR_REASON(RSA_R_BAD_FIXED_HEADER_DECRYPT), "bad fixed header decrypt"},
+	{ERR_REASON(RSA_R_BAD_PAD_BYTE_COUNT)    , "bad pad byte count"},
+	{ERR_REASON(RSA_R_BAD_SIGNATURE)         , "bad signature"},
+	{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_01)  , "block type is not 01"},
+	{ERR_REASON(RSA_R_BLOCK_TYPE_IS_NOT_02)  , "block type is not 02"},
+	{ERR_REASON(RSA_R_DATA_GREATER_THAN_MOD_LEN), "data greater than mod len"},
+	{ERR_REASON(RSA_R_DATA_TOO_LARGE)        , "data too large"},
+	{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE), "data too large for key size"},
+	{ERR_REASON(RSA_R_DATA_TOO_LARGE_FOR_MODULUS), "data too large for modulus"},
+	{ERR_REASON(RSA_R_DATA_TOO_SMALL)        , "data too small"},
+	{ERR_REASON(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE), "data too small for key size"},
+	{ERR_REASON(RSA_R_DIGEST_DOES_NOT_MATCH) , "digest does not match"},
+	{ERR_REASON(RSA_R_DIGEST_NOT_ALLOWED)    , "digest not allowed"},
+	{ERR_REASON(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY), "digest too big for rsa key"},
+	{ERR_REASON(RSA_R_DMP1_NOT_CONGRUENT_TO_D), "dmp1 not congruent to d"},
+	{ERR_REASON(RSA_R_DMQ1_NOT_CONGRUENT_TO_D), "dmq1 not congruent to d"},
+	{ERR_REASON(RSA_R_D_E_NOT_CONGRUENT_TO_1), "d e not congruent to 1"},
+	{ERR_REASON(RSA_R_FIRST_OCTET_INVALID)   , "first octet invalid"},
+	{ERR_REASON(RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"},
+	{ERR_REASON(RSA_R_INVALID_DIGEST)        , "invalid digest"},
+	{ERR_REASON(RSA_R_INVALID_DIGEST_LENGTH) , "invalid digest length"},
+	{ERR_REASON(RSA_R_INVALID_HEADER)        , "invalid header"},
+	{ERR_REASON(RSA_R_INVALID_LABEL)         , "invalid label"},
+	{ERR_REASON(RSA_R_INVALID_KEYBITS)       , "invalid keybits"},
+	{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH), "invalid message length"},
+	{ERR_REASON(RSA_R_INVALID_MGF1_MD)       , "invalid mgf1 md"},
+	{ERR_REASON(RSA_R_INVALID_OAEP_PARAMETERS), "invalid oaep parameters"},
+	{ERR_REASON(RSA_R_INVALID_PADDING)       , "invalid padding"},
+	{ERR_REASON(RSA_R_INVALID_PADDING_MODE)  , "invalid padding mode"},
+	{ERR_REASON(RSA_R_INVALID_PSS_PARAMETERS), "invalid pss parameters"},
+	{ERR_REASON(RSA_R_INVALID_PSS_SALTLEN)   , "invalid pss saltlen"},
+	{ERR_REASON(RSA_R_INVALID_SALT_LENGTH)   , "invalid salt length"},
+	{ERR_REASON(RSA_R_INVALID_TRAILER)       , "invalid trailer"},
+	{ERR_REASON(RSA_R_INVALID_X931_DIGEST)   , "invalid x931 digest"},
+	{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) , "iqmp not inverse of q"},
+	{ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL)    , "key size too small"},
+	{ERR_REASON(RSA_R_LAST_OCTET_INVALID)    , "last octet invalid"},
+	{ERR_REASON(RSA_R_MGF1_DIGEST_NOT_ALLOWED), "mgf1 digest not allowed"},
+	{ERR_REASON(RSA_R_MODULUS_TOO_LARGE)     , "modulus too large"},
+	{ERR_REASON(RSA_R_NON_FIPS_RSA_METHOD)   , "non fips rsa method"},
+	{ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT)    , "no public exponent"},
+	{ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING), "null before block missing"},
+	{ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q)  , "n does not equal p q"},
+	{ERR_REASON(RSA_R_OAEP_DECODING_ERROR)   , "oaep decoding error"},
+	{ERR_REASON(RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE), "operation not allowed in fips mode"},
+	{ERR_REASON(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), "operation not supported for this keytype"},
+	{ERR_REASON(RSA_R_PADDING_CHECK_FAILED)  , "padding check failed"},
+	{ERR_REASON(RSA_R_PSS_SALTLEN_TOO_SMALL) , "pss saltlen too small"},
+	{ERR_REASON(RSA_R_P_NOT_PRIME)           , "p not prime"},
+	{ERR_REASON(RSA_R_Q_NOT_PRIME)           , "q not prime"},
+	{ERR_REASON(RSA_R_RSA_OPERATIONS_NOT_SUPPORTED), "rsa operations not supported"},
+	{ERR_REASON(RSA_R_SLEN_CHECK_FAILED)     , "salt length check failed"},
+	{ERR_REASON(RSA_R_SLEN_RECOVERY_FAILED)  , "salt length recovery failed"},
+	{ERR_REASON(RSA_R_SSLV3_ROLLBACK_ATTACK) , "sslv3 rollback attack"},
+	{ERR_REASON(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"},
+	{ERR_REASON(RSA_R_UNKNOWN_ALGORITHM_TYPE), "unknown algorithm type"},
+	{ERR_REASON(RSA_R_UNKNOWN_DIGEST)        , "unknown digest"},
+	{ERR_REASON(RSA_R_UNKNOWN_MASK_DIGEST)   , "unknown mask digest"},
+	{ERR_REASON(RSA_R_UNKNOWN_PADDING_TYPE)  , "unknown padding type"},
+	{ERR_REASON(RSA_R_UNKNOWN_PSS_DIGEST)    , "unknown pss digest"},
+	{ERR_REASON(RSA_R_UNSUPPORTED_ENCRYPTION_TYPE), "unsupported encryption type"},
+	{ERR_REASON(RSA_R_UNSUPPORTED_LABEL_SOURCE), "unsupported label source"},
+	{ERR_REASON(RSA_R_UNSUPPORTED_MASK_ALGORITHM), "unsupported mask algorithm"},
+	{ERR_REASON(RSA_R_UNSUPPORTED_MASK_PARAMETER), "unsupported mask parameter"},
+	{ERR_REASON(RSA_R_UNSUPPORTED_SIGNATURE_TYPE), "unsupported signature type"},
+	{ERR_REASON(RSA_R_VALUE_MISSING)         , "value missing"},
+	{ERR_REASON(RSA_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_RSA_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(RSA_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, RSA_str_functs);
+		ERR_load_strings(0, RSA_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_RSA_strings);
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
new file mode 100644
index 0000000..ff64eb2
--- /dev/null
+++ b/crypto/rsa/rsa_gen.c
@@ -0,0 +1,257 @@
+/* $OpenBSD: rsa_gen.c,v 1.30 2023/07/08 12:26:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "rsa_local.h"
+
+static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
+
+int
+RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
+{
+	if (rsa->meth->rsa_keygen)
+		return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
+	return rsa_builtin_keygen(rsa, bits, e_value, cb);
+}
+LCRYPTO_ALIAS(RSA_generate_key_ex);
+
+static int
+rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
+{
+	BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
+	BIGNUM pr0, d, p;
+	int bitsp, bitsq, ok = -1, n = 0;
+	BN_CTX *ctx = NULL;
+
+	ctx = BN_CTX_new();
+	if (ctx == NULL)
+		goto err;
+	BN_CTX_start(ctx);
+	if ((r0 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r1 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r2 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+	if ((r3 = BN_CTX_get(ctx)) == NULL)
+		goto err;
+
+	bitsp = (bits + 1) / 2;
+	bitsq = bits - bitsp;
+
+	/* We need the RSA components non-NULL */
+	if (!rsa->n && ((rsa->n = BN_new()) == NULL))
+		goto err;
+	if (!rsa->d && ((rsa->d = BN_new()) == NULL))
+		goto err;
+	if (!rsa->e && ((rsa->e = BN_new()) == NULL))
+		goto err;
+	if (!rsa->p && ((rsa->p = BN_new()) == NULL))
+		goto err;
+	if (!rsa->q && ((rsa->q = BN_new()) == NULL))
+		goto err;
+	if (!rsa->dmp1 && ((rsa->dmp1 = BN_new()) == NULL))
+		goto err;
+	if (!rsa->dmq1 && ((rsa->dmq1 = BN_new()) == NULL))
+		goto err;
+	if (!rsa->iqmp && ((rsa->iqmp = BN_new()) == NULL))
+		goto err;
+
+	if (!bn_copy(rsa->e, e_value))
+		goto err;
+
+	/* generate p and q */
+	for (;;) {
+		if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb))
+			goto err;
+		if (!BN_sub(r2, rsa->p, BN_value_one()))
+			goto err;
+		if (!BN_gcd_ct(r1, r2, rsa->e, ctx))
+			goto err;
+		if (BN_is_one(r1))
+			break;
+		if (!BN_GENCB_call(cb, 2, n++))
+			goto err;
+	}
+	if (!BN_GENCB_call(cb, 3, 0))
+		goto err;
+	for (;;) {
+		/*
+		 * When generating ridiculously small keys, we can get stuck
+		 * continually regenerating the same prime values. Check for
+		 * this and bail if it happens 3 times.
+		 */
+		unsigned int degenerate = 0;
+		do {
+			if (!BN_generate_prime_ex(rsa->q, bitsq, 0, NULL, NULL,
+			    cb))
+				goto err;
+		} while (BN_cmp(rsa->p, rsa->q) == 0 &&
+		    ++degenerate < 3);
+		if (degenerate == 3) {
+			ok = 0; /* we set our own err */
+			RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
+			goto err;
+		}
+		if (!BN_sub(r2, rsa->q, BN_value_one()))
+			goto err;
+		if (!BN_gcd_ct(r1, r2, rsa->e, ctx))
+			goto err;
+		if (BN_is_one(r1))
+			break;
+		if (!BN_GENCB_call(cb, 2, n++))
+			goto err;
+	}
+	if (!BN_GENCB_call(cb, 3, 1))
+		goto err;
+	if (BN_cmp(rsa->p, rsa->q) < 0) {
+		tmp = rsa->p;
+		rsa->p = rsa->q;
+		rsa->q = tmp;
+	}
+
+	/* calculate n */
+	if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
+		goto err;
+
+	/* calculate d */
+	if (!BN_sub(r1, rsa->p, BN_value_one()))	/* p-1 */
+		goto err;
+	if (!BN_sub(r2, rsa->q, BN_value_one()))	/* q-1 */
+		goto err;
+	if (!BN_mul(r0, r1, r2, ctx))			/* (p-1)(q-1) */
+		goto err;
+
+	BN_init(&pr0);
+	BN_with_flags(&pr0, r0, BN_FLG_CONSTTIME);
+
+	if (BN_mod_inverse_ct(rsa->d, rsa->e, &pr0, ctx) == NULL) /* d */
+		goto err;
+
+	/* set up d for correct BN_FLG_CONSTTIME flag */
+	BN_init(&d);
+	BN_with_flags(&d, rsa->d, BN_FLG_CONSTTIME);
+
+	/* calculate d mod (p-1) */
+	if (!BN_mod_ct(rsa->dmp1, &d, r1, ctx))
+		goto err;
+
+	/* calculate d mod (q-1) */
+	if (!BN_mod_ct(rsa->dmq1, &d, r2, ctx))
+		goto err;
+
+	/* calculate inverse of q mod p */
+	BN_init(&p);
+	BN_with_flags(&p, rsa->p, BN_FLG_CONSTTIME);
+	if (BN_mod_inverse_ct(rsa->iqmp, rsa->q, &p, ctx) == NULL)
+		goto err;
+
+	ok = 1;
+err:
+	if (ok == -1) {
+		RSAerror(ERR_LIB_BN);
+		ok = 0;
+	}
+	if (ctx != NULL) {
+		BN_CTX_end(ctx);
+		BN_CTX_free(ctx);
+	}
+
+	return ok;
+}
+
+RSA *
+RSA_generate_key(int bits, unsigned long e_value,
+    void (*callback)(int, int, void *), void *cb_arg)
+{
+	BN_GENCB cb;
+	int i;
+	RSA *rsa = RSA_new();
+	BIGNUM *e = BN_new();
+
+	if (!rsa || !e)
+		goto err;
+
+	/* The problem is when building with 8, 16, or 32 BN_ULONG,
+	 * unsigned long can be larger */
+	for (i = 0; i < (int)sizeof(unsigned long) * 8; i++) {
+		if (e_value & (1UL << i))
+			if (BN_set_bit(e, i) == 0)
+				goto err;
+	}
+
+	BN_GENCB_set_old(&cb, callback, cb_arg);
+
+	if (RSA_generate_key_ex(rsa, bits, e, &cb)) {
+		BN_free(e);
+		return rsa;
+	}
+err:
+	BN_free(e);
+	RSA_free(rsa);
+
+	return 0;
+}
+LCRYPTO_ALIAS(RSA_generate_key);
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
new file mode 100644
index 0000000..fbd2c22
--- /dev/null
+++ b/crypto/rsa/rsa_lib.c
@@ -0,0 +1,460 @@
+/* $OpenBSD: rsa_lib.c,v 1.48 2023/07/28 10:05:16 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "evp_local.h"
+#include "rsa_local.h"
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+static const RSA_METHOD *default_RSA_meth = NULL;
+
+RSA *
+RSA_new(void)
+{
+	RSA *r = RSA_new_method(NULL);
+
+	return r;
+}
+LCRYPTO_ALIAS(RSA_new);
+
+void
+RSA_set_default_method(const RSA_METHOD *meth)
+{
+	default_RSA_meth = meth;
+}
+LCRYPTO_ALIAS(RSA_set_default_method);
+
+const RSA_METHOD *
+RSA_get_default_method(void)
+{
+	if (default_RSA_meth == NULL)
+		default_RSA_meth = RSA_PKCS1_SSLeay();
+
+	return default_RSA_meth;
+}
+LCRYPTO_ALIAS(RSA_get_default_method);
+
+const RSA_METHOD *
+RSA_get_method(const RSA *rsa)
+{
+	return rsa->meth;
+}
+LCRYPTO_ALIAS(RSA_get_method);
+
+int
+RSA_set_method(RSA *rsa, const RSA_METHOD *meth)
+{
+	/*
+	 * NB: The caller is specifically setting a method, so it's not up to us
+	 * to deal with which ENGINE it comes from.
+	 */
+	const RSA_METHOD *mtmp;
+
+	mtmp = rsa->meth;
+	if (mtmp->finish)
+		mtmp->finish(rsa);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(rsa->engine);
+	rsa->engine = NULL;
+#endif
+	rsa->meth = meth;
+	if (meth->init)
+		meth->init(rsa);
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_set_method);
+
+RSA *
+RSA_new_method(ENGINE *engine)
+{
+	RSA *ret;
+
+	if ((ret = calloc(1, sizeof(RSA))) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	ret->meth = RSA_get_default_method();
+
+#ifndef OPENSSL_NO_ENGINE
+	if (engine != NULL) {
+		if (!ENGINE_init(engine)) {
+			RSAerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+		ret->engine = engine;
+	} else {
+		ret->engine = ENGINE_get_default_RSA();
+	}
+
+	if (ret->engine != NULL) {
+		if ((ret->meth = ENGINE_get_RSA(ret->engine)) == NULL) {
+			RSAerror(ERR_R_ENGINE_LIB);
+			goto err;
+		}
+	}
+#endif
+
+	ret->references = 1;
+	ret->flags = ret->meth->flags & ~RSA_FLAG_NON_FIPS_ALLOW;
+
+	if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data))
+		goto err;
+
+	if (ret->meth->init != NULL && !ret->meth->init(ret)) {
+		CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
+		goto err;
+	}
+
+	return ret;
+
+ err:
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(ret->engine);
+#endif
+	free(ret);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(RSA_new_method);
+
+void
+RSA_free(RSA *r)
+{
+	int i;
+
+	if (r == NULL)
+		return;
+
+	i = CRYPTO_add(&r->references, -1, CRYPTO_LOCK_RSA);
+	if (i > 0)
+		return;
+
+	if (r->meth->finish)
+		r->meth->finish(r);
+#ifndef OPENSSL_NO_ENGINE
+	ENGINE_finish(r->engine);
+#endif
+
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_RSA, r, &r->ex_data);
+
+	BN_free(r->n);
+	BN_free(r->e);
+	BN_free(r->d);
+	BN_free(r->p);
+	BN_free(r->q);
+	BN_free(r->dmp1);
+	BN_free(r->dmq1);
+	BN_free(r->iqmp);
+	BN_BLINDING_free(r->blinding);
+	BN_BLINDING_free(r->mt_blinding);
+	RSA_PSS_PARAMS_free(r->pss);
+	free(r);
+}
+LCRYPTO_ALIAS(RSA_free);
+
+int
+RSA_up_ref(RSA *r)
+{
+	int i = CRYPTO_add(&r->references, 1, CRYPTO_LOCK_RSA);
+	return i > 1 ? 1 : 0;
+}
+LCRYPTO_ALIAS(RSA_up_ref);
+
+int
+RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_RSA, argl, argp,
+	    new_func, dup_func, free_func);
+}
+LCRYPTO_ALIAS(RSA_get_ex_new_index);
+
+int
+RSA_set_ex_data(RSA *r, int idx, void *arg)
+{
+	return CRYPTO_set_ex_data(&r->ex_data, idx, arg);
+}
+LCRYPTO_ALIAS(RSA_set_ex_data);
+
+void *
+RSA_get_ex_data(const RSA *r, int idx)
+{
+	return CRYPTO_get_ex_data(&r->ex_data, idx);
+}
+LCRYPTO_ALIAS(RSA_get_ex_data);
+
+int
+RSA_security_bits(const RSA *rsa)
+{
+	return BN_security_bits(RSA_bits(rsa), -1);
+}
+LCRYPTO_ALIAS(RSA_security_bits);
+
+void
+RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
+{
+	if (n != NULL)
+		*n = r->n;
+	if (e != NULL)
+		*e = r->e;
+	if (d != NULL)
+		*d = r->d;
+}
+LCRYPTO_ALIAS(RSA_get0_key);
+
+int
+RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
+{
+	if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL))
+		return 0;
+
+	if (n != NULL) {
+		BN_free(r->n);
+		r->n = n;
+	}
+	if (e != NULL) {
+		BN_free(r->e);
+		r->e = e;
+	}
+	if (d != NULL) {
+		BN_free(r->d);
+		r->d = d;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_set0_key);
+
+void
+RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1,
+    const BIGNUM **iqmp)
+{
+	if (dmp1 != NULL)
+		*dmp1 = r->dmp1;
+	if (dmq1 != NULL)
+		*dmq1 = r->dmq1;
+	if (iqmp != NULL)
+		*iqmp = r->iqmp;
+}
+LCRYPTO_ALIAS(RSA_get0_crt_params);
+
+int
+RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
+{
+	if ((r->dmp1 == NULL && dmp1 == NULL) ||
+	    (r->dmq1 == NULL && dmq1 == NULL) ||
+	    (r->iqmp == NULL && iqmp == NULL))
+		return 0;
+
+	if (dmp1 != NULL) {
+		BN_free(r->dmp1);
+		r->dmp1 = dmp1;
+	}
+	if (dmq1 != NULL) {
+		BN_free(r->dmq1);
+		r->dmq1 = dmq1;
+	}
+	if (iqmp != NULL) {
+		BN_free(r->iqmp);
+		r->iqmp = iqmp;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_set0_crt_params);
+
+void
+RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
+{
+	if (p != NULL)
+		*p = r->p;
+	if (q != NULL)
+		*q = r->q;
+}
+LCRYPTO_ALIAS(RSA_get0_factors);
+
+int
+RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
+{
+	if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL))
+		return 0;
+
+	if (p != NULL) {
+		BN_free(r->p);
+		r->p = p;
+	}
+	if (q != NULL) {
+		BN_free(r->q);
+		r->q = q;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_set0_factors);
+
+const BIGNUM *
+RSA_get0_n(const RSA *r)
+{
+	return r->n;
+}
+LCRYPTO_ALIAS(RSA_get0_n);
+
+const BIGNUM *
+RSA_get0_e(const RSA *r)
+{
+	return r->e;
+}
+LCRYPTO_ALIAS(RSA_get0_e);
+
+const BIGNUM *
+RSA_get0_d(const RSA *r)
+{
+	return r->d;
+}
+LCRYPTO_ALIAS(RSA_get0_d);
+
+const BIGNUM *
+RSA_get0_p(const RSA *r)
+{
+	return r->p;
+}
+LCRYPTO_ALIAS(RSA_get0_p);
+
+const BIGNUM *
+RSA_get0_q(const RSA *r)
+{
+	return r->q;
+}
+LCRYPTO_ALIAS(RSA_get0_q);
+
+const BIGNUM *
+RSA_get0_dmp1(const RSA *r)
+{
+	return r->dmp1;
+}
+LCRYPTO_ALIAS(RSA_get0_dmp1);
+
+const BIGNUM *
+RSA_get0_dmq1(const RSA *r)
+{
+	return r->dmq1;
+}
+LCRYPTO_ALIAS(RSA_get0_dmq1);
+
+const BIGNUM *
+RSA_get0_iqmp(const RSA *r)
+{
+	return r->iqmp;
+}
+LCRYPTO_ALIAS(RSA_get0_iqmp);
+
+const RSA_PSS_PARAMS *
+RSA_get0_pss_params(const RSA *r)
+{
+	return r->pss;
+}
+LCRYPTO_ALIAS(RSA_get0_pss_params);
+
+void
+RSA_clear_flags(RSA *r, int flags)
+{
+	r->flags &= ~flags;
+}
+LCRYPTO_ALIAS(RSA_clear_flags);
+
+int
+RSA_test_flags(const RSA *r, int flags)
+{
+	return r->flags & flags;
+}
+LCRYPTO_ALIAS(RSA_test_flags);
+
+void
+RSA_set_flags(RSA *r, int flags)
+{
+	r->flags |= flags;
+}
+LCRYPTO_ALIAS(RSA_set_flags);
+
+int
+RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2)
+{
+	/* Return an error if the key type is not RSA or RSA-PSS. */
+	if (ctx != NULL && ctx->pmeth != NULL &&
+	    ctx->pmeth->pkey_id != EVP_PKEY_RSA &&
+	    ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+		return -1;
+
+	return EVP_PKEY_CTX_ctrl(ctx, -1, optype, cmd, p1, p2);
+}
+LCRYPTO_ALIAS(RSA_pkey_ctx_ctrl);
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
new file mode 100644
index 0000000..51ed925
--- /dev/null
+++ b/crypto/rsa/rsa_local.h
@@ -0,0 +1,165 @@
+/* $OpenBSD: rsa_local.h,v 1.6 2023/08/09 12:09:06 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+__BEGIN_HIDDEN_DECLS
+
+#define RSA_MIN_MODULUS_BITS	512
+
+/* 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)
+
+struct rsa_meth_st {
+	char *name;
+	int (*rsa_pub_enc)(int flen, const unsigned char *from,
+	    unsigned char *to, RSA *rsa, int padding);
+	int (*rsa_pub_dec)(int flen, const unsigned char *from,
+	    unsigned char *to, RSA *rsa, int padding);
+	int (*rsa_priv_enc)(int flen, const unsigned char *from,
+	    unsigned char *to, RSA *rsa, int padding);
+	int (*rsa_priv_dec)(int flen, const unsigned char *from,
+	    unsigned char *to, RSA *rsa, int padding);
+	int (*rsa_mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+	    BN_CTX *ctx); /* Can be null */
+	int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+	    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); /* Can be null */
+	int (*init)(RSA *rsa);		/* called at new */
+	int (*finish)(RSA *rsa);	/* called at free */
+	int flags;			/* RSA_METHOD_FLAG_* things */
+	char *app_data;			/* may be needed! */
+/* 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. Note: for backwards
+ * compatibility this functionality is only enabled if the RSA_FLAG_SIGN_VER
+ * option is set in 'flags'.
+ */
+	int (*rsa_sign)(int type, const unsigned char *m, unsigned int m_length,
+	    unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+	int (*rsa_verify)(int dtype, const unsigned char *m,
+	    unsigned int m_length, const unsigned char *sigbuf,
+	    unsigned int siglen, const RSA *rsa);
+/* If this callback is NULL, the builtin software RSA key-gen will be used. This
+ * is for behavioural compatibility whilst the code gets rewired, but one day
+ * it would be nice to assume there are no such things as "builtin software"
+ * implementations. */
+	int (*rsa_keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
+};
+
+struct rsa_st {
+	/* The first parameter is used to pickup errors where
+	 * this is passed instead of aEVP_PKEY, it is set to 0 */
+	int pad;
+	long version;
+	const RSA_METHOD *meth;
+
+	/* functional reference if 'meth' is ENGINE-provided */
+	ENGINE *engine;
+	BIGNUM *n;
+	BIGNUM *e;
+	BIGNUM *d;
+	BIGNUM *p;
+	BIGNUM *q;
+	BIGNUM *dmp1;
+	BIGNUM *dmq1;
+	BIGNUM *iqmp;
+
+	/* Parameter restrictions for PSS only keys. */
+	RSA_PSS_PARAMS *pss;
+
+	/* be careful using this if the RSA structure is shared */
+	CRYPTO_EX_DATA ex_data;
+	int 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 */
+	BN_BLINDING *blinding;
+	BN_BLINDING *mt_blinding;
+};
+
+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);
+
+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);
+
+int RSA_padding_add_X931(unsigned char *to, int tlen,
+    const unsigned char *f, int fl);
+int RSA_padding_check_X931(unsigned char *to, int tlen,
+    const unsigned char *f, int fl, int rsa_len);
+int RSA_X931_hash_id(int nid);
+
+BN_BLINDING *BN_BLINDING_new(const BIGNUM *e, const BIGNUM *mod, BN_CTX *ctx,
+    int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), BN_MONT_CTX *m_ctx);
+void BN_BLINDING_free(BN_BLINDING *b);
+int BN_BLINDING_convert(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_invert(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
+int BN_BLINDING_is_local(BN_BLINDING *b);
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
+
+__END_HIDDEN_DECLS
diff --git a/crypto/rsa/rsa_meth.c b/crypto/rsa/rsa_meth.c
new file mode 100644
index 0000000..71608ca
--- /dev/null
+++ b/crypto/rsa/rsa_meth.c
@@ -0,0 +1,309 @@
+/*	$OpenBSD: rsa_meth.c,v 1.7 2023/07/08 12:26:45 beck Exp $	*/
+/*
+ * Copyright (c) 2018 Theo Buehler 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#include "rsa_local.h"
+
+RSA_METHOD *
+RSA_meth_new(const char *name, int flags)
+{
+	RSA_METHOD *meth;
+
+	if ((meth = calloc(1, sizeof(*meth))) == NULL)
+		return NULL;
+	if ((meth->name = strdup(name)) == NULL) {
+		free(meth);
+		return NULL;
+	}
+	meth->flags = flags;
+
+	return meth;
+}
+LCRYPTO_ALIAS(RSA_meth_new);
+
+void
+RSA_meth_free(RSA_METHOD *meth)
+{
+	if (meth == NULL)
+		return;
+
+	free(meth->name);
+	free(meth);
+}
+LCRYPTO_ALIAS(RSA_meth_free);
+
+RSA_METHOD *
+RSA_meth_dup(const RSA_METHOD *meth)
+{
+	RSA_METHOD *copy;
+
+	if ((copy = calloc(1, sizeof(*copy))) == NULL)
+		return NULL;
+	memcpy(copy, meth, sizeof(*copy));
+	if ((copy->name = strdup(meth->name)) == NULL) {
+		free(copy);
+		return NULL;
+	}
+
+	return copy;
+}
+LCRYPTO_ALIAS(RSA_meth_dup);
+
+int
+RSA_meth_set1_name(RSA_METHOD *meth, const char *name)
+{
+	char *new_name;
+
+	if ((new_name = strdup(name)) == NULL)
+		return 0;
+	free(meth->name);
+	meth->name = new_name;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set1_name);
+
+int
+(*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa)
+{
+	return meth->finish;
+}
+LCRYPTO_ALIAS(RSA_meth_get_finish);
+
+int
+RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+	meth->rsa_priv_enc = priv_enc;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_priv_enc);
+
+int
+RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+	meth->rsa_priv_dec = priv_dec;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_priv_dec);
+
+int
+RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa))
+{
+	meth->finish = finish;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_finish);
+
+int
+RSA_meth_set_pub_enc(RSA_METHOD *meth, int (*pub_enc)(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+	meth->rsa_pub_enc = pub_enc;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_pub_enc);
+
+int
+RSA_meth_set_pub_dec(RSA_METHOD *meth, int (*pub_dec)(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding))
+{
+	meth->rsa_pub_dec = pub_dec;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_pub_dec);
+
+int
+RSA_meth_set_mod_exp(RSA_METHOD *meth, int (*mod_exp)(BIGNUM *r0,
+    const BIGNUM *i, RSA *rsa, BN_CTX *ctx))
+{
+	meth->rsa_mod_exp = mod_exp;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_mod_exp);
+
+int
+RSA_meth_set_bn_mod_exp(RSA_METHOD *meth, int (*bn_mod_exp)(BIGNUM *r,
+    const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+	BN_MONT_CTX *m_ctx))
+{
+	meth->bn_mod_exp = bn_mod_exp;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_bn_mod_exp);
+
+int
+RSA_meth_set_init(RSA_METHOD *meth, int (*init)(RSA *rsa))
+{
+	meth->init = init;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_init);
+
+int
+RSA_meth_set_keygen(RSA_METHOD *meth, int (*keygen)(RSA *rsa, int bits,
+    BIGNUM *e, BN_GENCB *cb))
+{
+	meth->rsa_keygen = keygen;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_keygen);
+
+int
+RSA_meth_set_flags(RSA_METHOD *meth, int flags)
+{
+	meth->flags = flags;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_flags);
+
+int
+RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data)
+{
+	meth->app_data = app_data;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set0_app_data);
+
+const char *
+RSA_meth_get0_name(const RSA_METHOD *meth)
+{
+	return meth->name;
+}
+LCRYPTO_ALIAS(RSA_meth_get0_name);
+
+int
+(*RSA_meth_get_pub_enc(const RSA_METHOD *meth))(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
+{
+	return meth->rsa_pub_enc;
+}
+LCRYPTO_ALIAS(RSA_meth_get_pub_enc);
+
+int
+(*RSA_meth_get_pub_dec(const RSA_METHOD *meth))(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
+{
+	return meth->rsa_pub_dec;
+}
+LCRYPTO_ALIAS(RSA_meth_get_pub_dec);
+
+int
+(*RSA_meth_get_priv_enc(const RSA_METHOD *meth))(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
+{
+	return meth->rsa_priv_enc;
+}
+LCRYPTO_ALIAS(RSA_meth_get_priv_enc);
+
+int
+(*RSA_meth_get_priv_dec(const RSA_METHOD *meth))(int flen,
+    const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
+{
+	return meth->rsa_priv_dec;
+}
+LCRYPTO_ALIAS(RSA_meth_get_priv_dec);
+
+int
+(*RSA_meth_get_mod_exp(const RSA_METHOD *meth))(BIGNUM *r0, const BIGNUM *i,
+    RSA *rsa, BN_CTX *ctx)
+{
+	return meth->rsa_mod_exp;
+}
+LCRYPTO_ALIAS(RSA_meth_get_mod_exp);
+
+int
+(*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))(BIGNUM *r,
+    const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+    BN_MONT_CTX *m_ctx)
+{
+	return meth->bn_mod_exp;
+}
+LCRYPTO_ALIAS(RSA_meth_get_bn_mod_exp);
+
+int
+(*RSA_meth_get_init(const RSA_METHOD *meth))(RSA *rsa)
+{
+	return meth->init;
+}
+LCRYPTO_ALIAS(RSA_meth_get_init);
+
+int
+(*RSA_meth_get_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits, BIGNUM *e,
+    BN_GENCB *cb)
+{
+	return meth->rsa_keygen;
+}
+LCRYPTO_ALIAS(RSA_meth_get_keygen);
+
+int
+RSA_meth_get_flags(const RSA_METHOD *meth)
+{
+	return meth->flags;
+}
+LCRYPTO_ALIAS(RSA_meth_get_flags);
+
+void *
+RSA_meth_get0_app_data(const RSA_METHOD *meth)
+{
+	return meth->app_data;
+}
+LCRYPTO_ALIAS(RSA_meth_get0_app_data);
+
+int
+(*RSA_meth_get_sign(const RSA_METHOD *meth))(int type,
+    const unsigned char *m, unsigned int m_length,
+    unsigned char *sigret, unsigned int *siglen,
+    const RSA *rsa)
+{
+	return meth->rsa_sign;
+}
+LCRYPTO_ALIAS(RSA_meth_get_sign);
+
+int
+RSA_meth_set_sign(RSA_METHOD *meth, int (*sign)(int type,
+    const unsigned char *m, unsigned int m_length, unsigned char *sigret,
+    unsigned int *siglen, const RSA *rsa))
+{
+	meth->rsa_sign = sign;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_sign);
+
+int
+(*RSA_meth_get_verify(const RSA_METHOD *meth))(int dtype,
+    const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf,
+    unsigned int siglen, const RSA *rsa)
+{
+	return meth->rsa_verify;
+}
+LCRYPTO_ALIAS(RSA_meth_get_verify);
+
+int
+RSA_meth_set_verify(RSA_METHOD *meth, int (*verify)(int dtype,
+    const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf,
+    unsigned int siglen, const RSA *rsa))
+{
+	meth->rsa_verify = verify;
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_meth_set_verify);
diff --git a/crypto/rsa/rsa_none.c b/crypto/rsa/rsa_none.c
new file mode 100644
index 0000000..9c53dcf
--- /dev/null
+++ b/crypto/rsa/rsa_none.c
@@ -0,0 +1,98 @@
+/* $OpenBSD: rsa_none.c,v 1.12 2023/07/08 12:26:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+int
+RSA_padding_add_none(unsigned char *to, int tlen, const unsigned char *from,
+    int flen)
+{
+	if (flen > tlen) {
+		RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+		return 0;
+	}
+
+	if (flen < tlen) {
+		RSAerror(RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
+		return 0;
+	}
+
+	memcpy(to, from, flen);
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_padding_add_none);
+
+int
+RSA_padding_check_none(unsigned char *to, int tlen, const unsigned char *from,
+    int flen, int num)
+{
+	if (flen > tlen) {
+		RSAerror(RSA_R_DATA_TOO_LARGE);
+		return -1;
+	}
+
+	memset(to, 0, tlen - flen);
+	memcpy(to + tlen - flen, from, flen);
+	return tlen;
+}
+LCRYPTO_ALIAS(RSA_padding_check_none);
diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c
new file mode 100644
index 0000000..c2c3a61
--- /dev/null
+++ b/crypto/rsa/rsa_oaep.c
@@ -0,0 +1,363 @@
+/* $OpenBSD: rsa_oaep.c,v 1.37 2023/07/08 12:26:45 beck Exp $ */
+/*
+ * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
+
+/* See Victor Shoup, "OAEP reconsidered," Nov. 2000,
+ * 
+ * for problems with the security proof for the
+ * original OAEP scheme, which EME-OAEP is based on.
+ *
+ * A new proof can be found in E. Fujisaki, T. Okamoto,
+ * D. Pointcheval, J. Stern, "RSA-OEAP is Still Alive!",
+ * Dec. 2000, .
+ * The new proof has stronger requirements for the
+ * underlying permutation: "partial-one-wayness" instead
+ * of one-wayness.  For the RSA function, this is
+ * an equivalent notion.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "constant_time.h"
+#include "evp_local.h"
+#include "rsa_local.h"
+
+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);
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_OAEP);
+
+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)
+{
+	int i, emlen = tlen - 1;
+	unsigned char *db, *seed;
+	unsigned char *dbmask = NULL;
+	unsigned char seedmask[EVP_MAX_MD_SIZE];
+	int mdlen, dbmask_len = 0;
+	int rv = 0;
+
+	if (md == NULL)
+		md = EVP_sha1();
+	if (mgf1md == NULL)
+		mgf1md = md;
+
+	if ((mdlen = EVP_MD_size(md)) <= 0)
+		goto err;
+
+	if (flen > emlen - 2 * mdlen - 1) {
+		RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+		goto err;
+	}
+
+	if (emlen < 2 * mdlen + 1) {
+		RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
+		goto err;
+	}
+
+	to[0] = 0;
+	seed = to + 1;
+	db = to + mdlen + 1;
+
+	if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
+		goto err;
+
+	memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
+	db[emlen - flen - mdlen - 1] = 0x01;
+	memcpy(db + emlen - flen - mdlen, from, flen);
+	arc4random_buf(seed, mdlen);
+
+	dbmask_len = emlen - mdlen;
+	if ((dbmask = malloc(dbmask_len)) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0)
+		goto err;
+	for (i = 0; i < dbmask_len; i++)
+		db[i] ^= dbmask[i];
+	if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0)
+		goto err;
+	for (i = 0; i < mdlen; i++)
+		seed[i] ^= seedmask[i];
+
+	rv = 1;
+
+ err:
+	explicit_bzero(seedmask, sizeof(seedmask));
+	freezero(dbmask, dbmask_len);
+
+	return rv;
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_OAEP_mgf1);
+
+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)
+{
+	return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num,
+	    param, plen, NULL, NULL);
+}
+LCRYPTO_ALIAS(RSA_padding_check_PKCS1_OAEP);
+
+int
+RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+    const unsigned char *from, int flen, int num, const unsigned char *param,
+    int plen, const EVP_MD *md, const EVP_MD *mgf1md)
+{
+	int i, dblen = 0, mlen = -1, one_index = 0, msg_index;
+	unsigned int good = 0, found_one_byte, mask;
+	const unsigned char *maskedseed, *maskeddb;
+	unsigned char seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
+	unsigned char *db = NULL, *em = NULL;
+	int mdlen;
+
+	if (md == NULL)
+		md = EVP_sha1();
+	if (mgf1md == NULL)
+		mgf1md = md;
+
+	if ((mdlen = EVP_MD_size(md)) <= 0)
+		return -1;
+
+	if (tlen <= 0 || flen <= 0)
+		return -1;
+
+	/*
+	 * |num| is the length of the modulus; |flen| is the length of the
+	 * encoded message. Therefore, for any |from| that was obtained by
+	 * decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
+	 * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective
+	 * of the ciphertext, see PKCS #1 v2.2, section 7.1.2.
+	 * This does not leak any side-channel information.
+	 */
+	if (num < flen || num < 2 * mdlen + 2) {
+		RSAerror(RSA_R_OAEP_DECODING_ERROR);
+		return -1;
+	}
+
+	dblen = num - mdlen - 1;
+	if ((db = malloc(dblen)) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto cleanup;
+	}
+	if ((em = malloc(num)) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto cleanup;
+	}
+
+	/*
+	 * 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;
+	}
+
+	/*
+	 * The first byte must be zero, however we must not leak if this is
+	 * true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
+	 * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
+	 */
+	good = constant_time_is_zero(em[0]);
+
+	maskedseed = em + 1;
+	maskeddb = em + 1 + mdlen;
+
+	if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
+		goto cleanup;
+	for (i = 0; i < mdlen; i++)
+		seed[i] ^= maskedseed[i];
+
+	if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))
+		goto cleanup;
+	for (i = 0; i < dblen; i++)
+		db[i] ^= maskeddb[i];
+
+	if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))
+		goto cleanup;
+
+	good &= constant_time_is_zero(timingsafe_memcmp(db, phash, mdlen));
+
+	found_one_byte = 0;
+	for (i = mdlen; i < dblen; i++) {
+		/*
+		 * Padding consists of a number of 0-bytes, followed by a 1.
+		 */
+		unsigned int equals1 = constant_time_eq(db[i], 1);
+		unsigned int equals0 = constant_time_is_zero(db[i]);
+
+		one_index = constant_time_select_int(~found_one_byte & equals1,
+		    i, one_index);
+		found_one_byte |= equals1;
+		good &= (found_one_byte | equals0);
+	}
+
+	good &= found_one_byte;
+
+	/*
+	 * At this point |good| is zero unless the plaintext was valid,
+	 * so plaintext-awareness ensures timing side-channels are no longer a
+	 * concern.
+	 */
+	msg_index = one_index + 1;
+	mlen = dblen - msg_index;
+
+	/*
+	 * For good measure, do this check in constant time as well.
+	 */
+	good &= constant_time_ge(tlen, mlen);
+
+	/*
+	 * Even though we can't fake result's length, we can pretend copying
+	 * |tlen| bytes where |mlen| bytes would be real. The last |tlen| of
+	 * |dblen| bytes are viewed as a circular buffer starting at |tlen|-|mlen'|,
+	 * where |mlen'| is the "saturated" |mlen| value. Deducing information
+	 * about failure or |mlen| would require an attacker to observe
+	 * memory access patterns with byte granularity *as it occurs*. It
+	 * should be noted that failure is indistinguishable from normal
+	 * operation if |tlen| is fixed by protocol.
+	 */
+	tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen),
+	    dblen - mdlen - 1, tlen);
+	msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
+	mlen = dblen - msg_index;
+	for (mask = good, i = 0; i < tlen; i++) {
+		unsigned int equals = constant_time_eq(msg_index, dblen);
+
+		msg_index -= tlen & equals;	/* rewind at EOF */
+		mask &= ~equals;		/* mask = 0 at EOF */
+		to[i] = constant_time_select_8(mask, db[msg_index++], to[i]);
+	}
+
+	/*
+	 * To avoid chosen ciphertext attacks, the error message should not
+	 * reveal which kind of decoding error happened.
+	 */
+	RSAerror(RSA_R_OAEP_DECODING_ERROR);
+	err_clear_last_constant_time(1 & good);
+
+ cleanup:
+	explicit_bzero(seed, sizeof(seed));
+	freezero(db, dblen);
+	freezero(em, num);
+
+	return constant_time_select_int(good, mlen, -1);
+}
+LCRYPTO_ALIAS(RSA_padding_check_PKCS1_OAEP_mgf1);
+
+int
+PKCS1_MGF1(unsigned char *mask, long len, const unsigned char *seed,
+    long seedlen, const EVP_MD *dgst)
+{
+	long i, outlen = 0;
+	unsigned char cnt[4];
+	EVP_MD_CTX c;
+	unsigned char md[EVP_MAX_MD_SIZE];
+	int mdlen;
+	int rv = -1;
+
+	EVP_MD_CTX_init(&c);
+	mdlen = EVP_MD_size(dgst);
+	if (mdlen < 0)
+		goto err;
+	for (i = 0; outlen < len; i++) {
+		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);
+		if (!EVP_DigestInit_ex(&c, dgst, NULL) ||
+		    !EVP_DigestUpdate(&c, seed, seedlen) ||
+		    !EVP_DigestUpdate(&c, cnt, 4))
+			goto err;
+		if (outlen + mdlen <= len) {
+			if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL))
+				goto err;
+			outlen += mdlen;
+		} else {
+			if (!EVP_DigestFinal_ex(&c, md, NULL))
+				goto err;
+			memcpy(mask + outlen, md, len - outlen);
+			outlen = len;
+		}
+	}
+	rv = 0;
+ err:
+	EVP_MD_CTX_cleanup(&c);
+	return rv;
+}
+LCRYPTO_ALIAS(PKCS1_MGF1);
diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
new file mode 100644
index 0000000..38f7c0b
--- /dev/null
+++ b/crypto/rsa/rsa_pk1.c
@@ -0,0 +1,217 @@
+/* $OpenBSD: rsa_pk1.c,v 1.16 2023/07/08 12:26:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+int
+RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
+    const unsigned char *from, int flen)
+{
+	int j;
+	unsigned char *p;
+
+	if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
+		RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+		return 0;
+	}
+
+	p = (unsigned char *)to;
+
+	*(p++) = 0;
+	*(p++) = 1; /* Private Key BT (Block Type) */
+
+	/* pad out with 0xff data */
+	j = tlen - 3 - flen;
+	memset(p, 0xff, j);
+	p += j;
+	*(p++) = '\0';
+	memcpy(p, from, flen);
+
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_type_1);
+
+int
+RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
+    const unsigned char *from, int flen, int num)
+{
+	int i, j;
+	const unsigned char *p;
+
+	p = from;
+	if (num != flen + 1 || *(p++) != 01) {
+		RSAerror(RSA_R_BLOCK_TYPE_IS_NOT_01);
+		return -1;
+	}
+
+	/* scan over padding data */
+	j = flen - 1; /* one for type. */
+	for (i = 0; i < j; i++) {
+		if (*p != 0xff) {
+			/* should decrypt to 0xff */
+			if (*p == 0) {
+				p++;
+				break;
+			} else {
+				RSAerror(RSA_R_BAD_FIXED_HEADER_DECRYPT);
+				return -1;
+			}
+		}
+		p++;
+	}
+
+	if (i == j) {
+		RSAerror(RSA_R_NULL_BEFORE_BLOCK_MISSING);
+		return -1;
+	}
+
+	if (i < 8) {
+		RSAerror(RSA_R_BAD_PAD_BYTE_COUNT);
+		return -1;
+	}
+	i++; /* Skip over the '\0' */
+	j -= i;
+	if (j > tlen) {
+		RSAerror(RSA_R_DATA_TOO_LARGE);
+		return -1;
+	}
+	memcpy(to, p, j);
+
+	return j;
+}
+LCRYPTO_ALIAS(RSA_padding_check_PKCS1_type_1);
+
+int
+RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
+    const unsigned char *from, int flen)
+{
+	int i, j;
+	unsigned char *p;
+
+	if (flen > tlen - 11) {
+		RSAerror(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 - flen;
+
+	arc4random_buf(p, j);
+	for (i = 0; i < j; i++) {
+		while (*p == '\0')
+			arc4random_buf(p, 1);
+		p++;
+	}
+
+	*(p++) = '\0';
+
+	memcpy(p, from, flen);
+	return 1;
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_type_2);
+
+int
+RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
+    const unsigned char *from, int flen, int num)
+{
+	int i, j;
+	const unsigned char *p;
+
+	p = from;
+	if (num != flen + 1 || *(p++) != 02) {
+		RSAerror(RSA_R_BLOCK_TYPE_IS_NOT_02);
+		return -1;
+	}
+
+	/* scan over padding data */
+	j = flen - 1; /* one for type. */
+	for (i = 0; i < j; i++)
+		if (*(p++) == 0)
+			break;
+
+	if (i == j) {
+		RSAerror(RSA_R_NULL_BEFORE_BLOCK_MISSING);
+		return -1;
+	}
+
+	if (i < 8) {
+		RSAerror(RSA_R_BAD_PAD_BYTE_COUNT);
+		return -1;
+	}
+	i++; /* Skip over the '\0' */
+	j -= i;
+	if (j > tlen) {
+		RSAerror(RSA_R_DATA_TOO_LARGE);
+		return -1;
+	}
+	memcpy(to, p, j);
+
+	return j;
+}
+LCRYPTO_ALIAS(RSA_padding_check_PKCS1_type_2);
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
new file mode 100644
index 0000000..cb82b09
--- /dev/null
+++ b/crypto/rsa/rsa_pmeth.c
@@ -0,0 +1,879 @@
+/* $OpenBSD: rsa_pmeth.c,v 1.39 2023/07/08 12:26:45 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "evp_local.h"
+#include "rsa_local.h"
+
+/* RSA pkey context structure */
+
+typedef struct {
+	/* Key gen parameters */
+	int nbits;
+	BIGNUM *pub_exp;
+	/* Keygen callback info */
+	int gentmp[2];
+	/* RSA padding mode */
+	int pad_mode;
+	/* message digest */
+	const EVP_MD *md;
+	/* message digest for MGF1 */
+	const EVP_MD *mgf1md;
+	/* PSS salt length */
+	int saltlen;
+	/* Minimum salt length or -1 if no PSS parameter restriction */
+	int min_saltlen;
+	/* Temp buffer */
+	unsigned char *tbuf;
+	/* OAEP label */
+	unsigned char *oaep_label;
+	size_t oaep_labellen;
+} RSA_PKEY_CTX;
+
+/* True if PSS parameters are restricted */
+#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
+
+static int
+pkey_rsa_init(EVP_PKEY_CTX *ctx)
+{
+	RSA_PKEY_CTX *rctx;
+
+	if ((rctx = calloc(1, sizeof(RSA_PKEY_CTX))) == NULL)
+		return 0;
+
+	rctx->nbits = 2048;
+
+	if (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
+		rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
+	else
+		rctx->pad_mode = RSA_PKCS1_PADDING;
+
+	/* Maximum for sign, auto for verify */
+	rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
+	rctx->min_saltlen = -1;
+
+	ctx->data = rctx;
+	ctx->keygen_info = rctx->gentmp;
+	ctx->keygen_info_count = 2;
+
+	return 1;
+}
+
+static int
+pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+	RSA_PKEY_CTX *dctx, *sctx;
+
+	if (!pkey_rsa_init(dst))
+		return 0;
+
+	sctx = src->data;
+	dctx = dst->data;
+	dctx->nbits = sctx->nbits;
+	if (sctx->pub_exp != NULL) {
+		BN_free(dctx->pub_exp);
+		if ((dctx->pub_exp = BN_dup(sctx->pub_exp)) == NULL)
+			return 0;
+	}
+	dctx->pad_mode = sctx->pad_mode;
+	dctx->md = sctx->md;
+	dctx->mgf1md = sctx->mgf1md;
+	if (sctx->oaep_label != NULL) {
+		free(dctx->oaep_label);
+		if ((dctx->oaep_label = calloc(1, sctx->oaep_labellen)) == NULL)
+			return 0;
+		memcpy(dctx->oaep_label, sctx->oaep_label, sctx->oaep_labellen);
+		dctx->oaep_labellen = sctx->oaep_labellen;
+	}
+
+	return 1;
+}
+
+static int
+setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
+{
+	if (ctx->tbuf != NULL)
+		return 1;
+	if ((ctx->tbuf = calloc(1, EVP_PKEY_size(pk->pkey))) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	return 1;
+}
+
+static void
+pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
+{
+	RSA_PKEY_CTX *rctx = ctx->data;
+
+	if (rctx) {
+		BN_free(rctx->pub_exp);
+		free(rctx->tbuf);
+		free(rctx->oaep_label);
+		free(rctx);
+	}
+}
+
+static int
+pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	int ret;
+	RSA_PKEY_CTX *rctx = ctx->data;
+	RSA *rsa = ctx->pkey->pkey.rsa;
+
+	if (rctx->md) {
+		if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
+			RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
+			return -1;
+		}
+
+		if (rctx->pad_mode == RSA_X931_PADDING) {
+			if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) {
+				RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
+				return -1;
+			}
+			if (!setup_tbuf(rctx, ctx)) {
+				RSAerror(ERR_R_MALLOC_FAILURE);
+				return -1;
+			}
+			memcpy(rctx->tbuf, tbs, tbslen);
+			rctx->tbuf[tbslen] =
+			    RSA_X931_hash_id(EVP_MD_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), tbs, tbslen, sig,
+			    &sltmp, rsa);
+			if (ret <= 0)
+				return ret;
+			ret = sltmp;
+		} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
+			if (!setup_tbuf(rctx, ctx))
+				return -1;
+			if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa, rctx->tbuf,
+			    tbs, rctx->md, rctx->mgf1md, rctx->saltlen))
+				return -1;
+			ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
+			    sig, rsa, RSA_NO_PADDING);
+		} else {
+			return -1;
+		}
+	} else {
+		ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
+		    rctx->pad_mode);
+	}
+	if (ret < 0)
+		return ret;
+	*siglen = ret;
+	return 1;
+}
+
+static int
+pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx, unsigned char *rout, size_t *routlen,
+    const unsigned char *sig, size_t siglen)
+{
+	int ret;
+	RSA_PKEY_CTX *rctx = ctx->data;
+
+	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, RSA_X931_PADDING);
+			if (ret < 1)
+				return 0;
+			ret--;
+			if (rctx->tbuf[ret] !=
+			    RSA_X931_hash_id(EVP_MD_type(rctx->md))) {
+				RSAerror(RSA_R_ALGORITHM_MISMATCH);
+				return 0;
+			}
+			if (ret != EVP_MD_size(rctx->md)) {
+				RSAerror(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);
+			if (ret <= 0)
+				return 0;
+			ret = sltmp;
+		} else {
+			return -1;
+		}
+	} else {
+		ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
+		    rctx->pad_mode);
+	}
+	if (ret < 0)
+		return ret;
+	*routlen = ret;
+	return 1;
+}
+
+static int
+pkey_rsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
+    const unsigned char *tbs, size_t tbslen)
+{
+	RSA_PKEY_CTX *rctx = ctx->data;
+	RSA *rsa = ctx->pkey->pkey.rsa;
+	size_t rslen;
+
+	if (rctx->md) {
+		if (rctx->pad_mode == RSA_PKCS1_PADDING)
+			return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
+			    sig, siglen, rsa);
+		if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
+			RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
+			return -1;
+		}
+		if (rctx->pad_mode == RSA_X931_PADDING) {
+			if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig,
+			    siglen) <= 0)
+				return 0;
+		} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
+			int ret;
+
+			if (!setup_tbuf(rctx, ctx))
+				return -1;
+			ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
+			    rsa, RSA_NO_PADDING);
+			if (ret <= 0)
+				return 0;
+			ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs, rctx->md,
+			    rctx->mgf1md, rctx->tbuf, rctx->saltlen);
+			if (ret <= 0)
+				return 0;
+			return 1;
+		} else {
+			return -1;
+		}
+	} else {
+		int ret;
+
+		if (!setup_tbuf(rctx, ctx))
+			return -1;
+
+		if ((ret = RSA_public_decrypt(siglen, sig, rctx->tbuf, rsa,
+		    rctx->pad_mode)) <= 0)
+			return 0;
+
+		rslen = ret;
+	}
+
+	if (rslen != tbslen || timingsafe_bcmp(tbs, rctx->tbuf, rslen))
+		return 0;
+
+	return 1;
+}
+
+static int
+pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+    const unsigned char *in, size_t inlen)
+{
+	RSA_PKEY_CTX *rctx = ctx->data;
+	int ret;
+
+	if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
+		int klen = RSA_size(ctx->pkey->pkey.rsa);
+		if (!setup_tbuf(rctx, ctx))
+			return -1;
+		if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
+		    in, inlen, rctx->oaep_label, rctx->oaep_labellen,
+		    rctx->md, rctx->mgf1md))
+			return -1;
+		ret = RSA_public_encrypt(klen, rctx->tbuf, out,
+		    ctx->pkey->pkey.rsa, RSA_NO_PADDING);
+	} else {
+		ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
+		    rctx->pad_mode);
+	}
+	if (ret < 0)
+		return ret;
+	*outlen = ret;
+	return 1;
+}
+
+static int
+pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
+    const unsigned char *in, size_t inlen)
+{
+	int ret;
+	RSA_PKEY_CTX *rctx = ctx->data;
+
+	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);
+		if (ret <= 0)
+			return ret;
+		ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
+		    ret, ret, rctx->oaep_label, rctx->oaep_labellen, rctx->md,
+		    rctx->mgf1md);
+	} else {
+		ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
+		    rctx->pad_mode);
+	}
+	if (ret < 0)
+		return ret;
+	*outlen = ret;
+	return 1;
+}
+
+static int
+check_padding_md(const EVP_MD *md, int padding)
+{
+	if (md == NULL)
+		return 1;
+
+	if (padding == RSA_NO_PADDING) {
+		RSAerror(RSA_R_INVALID_PADDING_MODE);
+		return 0;
+	}
+
+	if (padding == RSA_X931_PADDING) {
+		if (RSA_X931_hash_id(EVP_MD_type(md)) == -1) {
+			RSAerror(RSA_R_INVALID_X931_DIGEST);
+			return 0;
+		}
+	} else {
+		/* List of all supported RSA digests. */
+		/* RFC 8017 and NIST CSOR. */
+		switch(EVP_MD_type(md)) {
+		case NID_sha1:
+		case NID_sha224:
+		case NID_sha256:
+		case NID_sha384:
+		case NID_sha512:
+		case NID_sha512_224:
+		case NID_sha512_256:
+		case NID_sha3_224:
+		case NID_sha3_256:
+		case NID_sha3_384:
+		case NID_sha3_512:
+		case NID_md5:
+		case NID_md5_sha1:
+		case NID_md4:
+		case NID_ripemd160:
+			return 1;
+
+		default:
+			RSAerror(RSA_R_INVALID_DIGEST);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+static int
+pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+	RSA_PKEY_CTX *rctx = ctx->data;
+
+	switch (type) {
+	case EVP_PKEY_CTRL_RSA_PADDING:
+		if (p1 >= RSA_PKCS1_PADDING && p1 <= RSA_PKCS1_PSS_PADDING) {
+			if (!check_padding_md(rctx->md, p1))
+				return 0;
+			if (p1 == RSA_PKCS1_PSS_PADDING) {
+				if (!(ctx->operation &
+				    (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
+					goto bad_pad;
+				if (!rctx->md)
+					rctx->md = EVP_sha1();
+			} else if (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) {
+				goto bad_pad;
+			}
+			if (p1 == RSA_PKCS1_OAEP_PADDING) {
+				if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
+					goto bad_pad;
+				if (!rctx->md)
+					rctx->md = EVP_sha1();
+			}
+			rctx->pad_mode = p1;
+			return 1;
+		}
+ bad_pad:
+		RSAerror(RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
+		return -2;
+
+	case EVP_PKEY_CTRL_GET_RSA_PADDING:
+		*(int *)p2 = rctx->pad_mode;
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
+	case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
+		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
+			RSAerror(RSA_R_INVALID_PSS_SALTLEN);
+			return -2;
+		}
+		if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
+			*(int *)p2 = rctx->saltlen;
+		} else {
+			if (p1 < RSA_PSS_SALTLEN_MAX)
+				return -2;
+			if (rsa_pss_restricted(rctx)) {
+				if (p1 == RSA_PSS_SALTLEN_AUTO &&
+				    ctx->operation == EVP_PKEY_OP_VERIFY) {
+					RSAerror(RSA_R_INVALID_PSS_SALTLEN);
+					return -2;
+				}
+				if ((p1 == RSA_PSS_SALTLEN_DIGEST &&
+				    rctx->min_saltlen > EVP_MD_size(rctx->md)) ||
+				    (p1 >= 0 && p1 < rctx->min_saltlen)) {
+					RSAerror(RSA_R_PSS_SALTLEN_TOO_SMALL);
+					return 0;
+				}
+			}
+			rctx->saltlen = p1;
+		}
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
+		if (p1 < RSA_MIN_MODULUS_BITS) {
+			RSAerror(RSA_R_KEY_SIZE_TOO_SMALL);
+			return -2;
+		}
+		rctx->nbits = p1;
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
+		if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) ||
+		    BN_is_one((BIGNUM *)p2)) {
+			RSAerror(RSA_R_BAD_E_VALUE);
+			return -2;
+		}
+		BN_free(rctx->pub_exp);
+		rctx->pub_exp = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_OAEP_MD:
+	case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
+		if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
+			RSAerror(RSA_R_INVALID_PADDING_MODE);
+			return -2;
+		}
+		if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
+			*(const EVP_MD **)p2 = rctx->md;
+		else
+			rctx->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_MD:
+		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))
+				return 1;
+			RSAerror(RSA_R_DIGEST_NOT_ALLOWED);
+			return 0;
+		}
+		rctx->md = p2;
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_MD:
+		*(const EVP_MD **)p2 = rctx->md;
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_MGF1_MD:
+	case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
+		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
+		    rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
+			RSAerror(RSA_R_INVALID_MGF1_MD);
+			return -2;
+		}
+		if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
+			if (rctx->mgf1md)
+				*(const EVP_MD **)p2 = rctx->mgf1md;
+			else
+				*(const EVP_MD **)p2 = rctx->md;
+		} else {
+			if (rsa_pss_restricted(rctx)) {
+				if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2))
+					return 1;
+				RSAerror(RSA_R_MGF1_DIGEST_NOT_ALLOWED);
+				return 0;
+			}
+			rctx->mgf1md = p2;
+		}
+		return 1;
+
+	case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
+		if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
+			RSAerror(RSA_R_INVALID_PADDING_MODE);
+			return -2;
+		}
+		free(rctx->oaep_label);
+		if (p2 != NULL && p1 > 0) {
+			rctx->oaep_label = p2;
+			rctx->oaep_labellen = p1;
+		} else {
+			rctx->oaep_label = NULL;
+			rctx->oaep_labellen = 0;
+		}
+		return 1;
+
+	case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
+		if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
+			RSAerror(RSA_R_INVALID_PADDING_MODE);
+			return -2;
+		}
+		*(unsigned char **)p2 = rctx->oaep_label;
+		return rctx->oaep_labellen;
+
+	case EVP_PKEY_CTRL_DIGESTINIT:
+	case EVP_PKEY_CTRL_PKCS7_SIGN:
+#ifndef OPENSSL_NO_CMS
+	case EVP_PKEY_CTRL_CMS_SIGN:
+#endif
+		return 1;
+
+	case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
+	case EVP_PKEY_CTRL_PKCS7_DECRYPT:
+#ifndef OPENSSL_NO_CMS
+	case EVP_PKEY_CTRL_CMS_DECRYPT:
+	case EVP_PKEY_CTRL_CMS_ENCRYPT:
+#endif
+		if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+			return 1;
+
+	/* fall through */
+	case EVP_PKEY_CTRL_PEER_KEY:
+		RSAerror(RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+		return -2;
+
+	default:
+		return -2;
+
+	}
+}
+
+static int
+pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
+{
+	if (!value) {
+		RSAerror(RSA_R_VALUE_MISSING);
+		return 0;
+	}
+	if (!strcmp(type, "rsa_padding_mode")) {
+		int pm;
+		if (!strcmp(value, "pkcs1"))
+			pm = RSA_PKCS1_PADDING;
+		else if (!strcmp(value, "none"))
+			pm = RSA_NO_PADDING;
+		else if (!strcmp(value, "oeap"))
+			pm = RSA_PKCS1_OAEP_PADDING;
+		else if (!strcmp(value, "oaep"))
+			pm = RSA_PKCS1_OAEP_PADDING;
+		else if (!strcmp(value, "x931"))
+			pm = RSA_X931_PADDING;
+		else if (!strcmp(value, "pss"))
+			pm = RSA_PKCS1_PSS_PADDING;
+		else {
+			RSAerror(RSA_R_UNKNOWN_PADDING_TYPE);
+			return -2;
+		}
+		return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
+	}
+
+	if (strcmp(type, "rsa_pss_saltlen") == 0) {
+		int saltlen;
+
+		if (!strcmp(value, "digest"))
+			saltlen = RSA_PSS_SALTLEN_DIGEST;
+		else if (!strcmp(value, "max"))
+			saltlen = RSA_PSS_SALTLEN_MAX;
+		else if (!strcmp(value, "auto"))
+			saltlen = RSA_PSS_SALTLEN_AUTO;
+		else
+			saltlen = atoi(value);
+		return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
+	}
+
+	if (strcmp(type, "rsa_keygen_bits") == 0) {
+		int nbits = atoi(value);
+
+		return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
+	}
+
+	if (strcmp(type, "rsa_keygen_pubexp") == 0) {
+		BIGNUM *pubexp = NULL;
+		int ret;
+
+		if (!BN_asc2bn(&pubexp, value))
+			return 0;
+		ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
+		if (ret <= 0)
+			BN_free(pubexp);
+		return ret;
+	}
+
+	if (strcmp(type, "rsa_mgf1_md") == 0)
+		return EVP_PKEY_CTX_md(ctx,
+		    EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
+		    EVP_PKEY_CTRL_RSA_MGF1_MD, value);
+
+	if (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) {
+		if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
+			return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
+			    EVP_PKEY_CTRL_RSA_MGF1_MD, value);
+
+		if (strcmp(type, "rsa_pss_keygen_md") == 0)
+			return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
+			    EVP_PKEY_CTRL_MD, value);
+
+		if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
+			int saltlen = atoi(value);
+
+			return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
+		}
+	}
+
+	if (strcmp(type, "rsa_oaep_md") == 0)
+		return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
+		    EVP_PKEY_CTRL_RSA_OAEP_MD, value);
+
+	if (strcmp(type, "rsa_oaep_label") == 0) {
+		unsigned char *lab;
+		long lablen;
+		int ret;
+
+		if ((lab = string_to_hex(value, &lablen)) == NULL)
+			return 0;
+		ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
+		if (ret <= 0)
+			free(lab);
+
+		return ret;
+	}
+
+	return -2;
+}
+
+/* Set PSS parameters when generating a key, if necessary. */
+static int
+rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
+{
+	RSA_PKEY_CTX *rctx = ctx->data;
+
+	if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+		return 1;
+
+	/* If all parameters are default values then do not set PSS. */
+	if (rctx->md == NULL && rctx->mgf1md == NULL &&
+	    rctx->saltlen == RSA_PSS_SALTLEN_AUTO)
+		return 1;
+
+	rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
+	    rctx->saltlen == RSA_PSS_SALTLEN_AUTO ? 0 : rctx->saltlen);
+	if (rsa->pss == NULL)
+		return 0;
+
+	return 1;
+}
+
+static int
+pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+	RSA *rsa = NULL;
+	RSA_PKEY_CTX *rctx = ctx->data;
+	BN_GENCB *pcb, cb;
+	int ret;
+
+	if (rctx->pub_exp == NULL) {
+		if ((rctx->pub_exp = BN_new()) == NULL)
+			return 0;
+		if (!BN_set_word(rctx->pub_exp, RSA_F4))
+			return 0;
+	}
+	if ((rsa = RSA_new()) == NULL)
+		return 0;
+	if (ctx->pkey_gencb != NULL) {
+		pcb = &cb;
+		evp_pkey_set_cb_translate(pcb, ctx);
+	} else {
+		pcb = NULL;
+	}
+	ret = RSA_generate_key_ex(rsa, rctx->nbits, rctx->pub_exp, pcb);
+	if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
+		RSA_free(rsa);
+		return 0;
+	}
+	if (ret > 0)
+		EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
+	else
+		RSA_free(rsa);
+	return ret;
+}
+
+const EVP_PKEY_METHOD rsa_pkey_meth = {
+	.pkey_id = EVP_PKEY_RSA,
+	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
+
+	.init = pkey_rsa_init,
+	.copy = pkey_rsa_copy,
+	.cleanup = pkey_rsa_cleanup,
+
+	.keygen = pkey_rsa_keygen,
+
+	.sign = pkey_rsa_sign,
+
+	.verify = pkey_rsa_verify,
+
+	.verify_recover = pkey_rsa_verifyrecover,
+
+	.encrypt = pkey_rsa_encrypt,
+
+	.decrypt = pkey_rsa_decrypt,
+
+	.ctrl = pkey_rsa_ctrl,
+	.ctrl_str = pkey_rsa_ctrl_str
+};
+
+/*
+ * Called for PSS sign or verify initialisation: checks PSS parameter
+ * sanity and sets any restrictions on key usage.
+ */
+
+static int
+pkey_pss_init(EVP_PKEY_CTX *ctx)
+{
+	RSA *rsa;
+	RSA_PKEY_CTX *rctx = ctx->data;
+	const EVP_MD *md;
+	const EVP_MD *mgf1md;
+	int min_saltlen, max_saltlen;
+
+	/* Should never happen */
+	if (ctx->pmeth->pkey_id != EVP_PKEY_RSA_PSS)
+		return 0;
+	rsa = ctx->pkey->pkey.rsa;
+
+	/* 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))
+		return 0;
+
+	/* See if minimum salt length exceeds maximum possible */
+	max_saltlen = RSA_size(rsa) - EVP_MD_size(md);
+	if ((RSA_bits(rsa) & 0x7) == 1)
+		max_saltlen--;
+	if (min_saltlen > max_saltlen) {
+		RSAerror(RSA_R_INVALID_SALT_LENGTH);
+		return 0;
+	}
+	rctx->min_saltlen = min_saltlen;
+
+	/*
+	 * Set PSS restrictions as defaults: we can then block any attempt to
+	 * use invalid values in pkey_rsa_ctrl
+	 */
+
+	rctx->md = md;
+	rctx->mgf1md = mgf1md;
+	rctx->saltlen = min_saltlen;
+
+	return 1;
+}
+
+const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
+	.pkey_id = EVP_PKEY_RSA_PSS,
+	.flags = EVP_PKEY_FLAG_AUTOARGLEN,
+
+	.init = pkey_rsa_init,
+	.copy = pkey_rsa_copy,
+	.cleanup = pkey_rsa_cleanup,
+
+	.keygen = pkey_rsa_keygen,
+
+	.sign_init = pkey_pss_init,
+	.sign = pkey_rsa_sign,
+
+	.verify_init = pkey_pss_init,
+	.verify = pkey_rsa_verify,
+
+	.ctrl = pkey_rsa_ctrl,
+	.ctrl_str = pkey_rsa_ctrl_str
+};
diff --git a/crypto/rsa/rsa_prn.c b/crypto/rsa/rsa_prn.c
new file mode 100644
index 0000000..1783563
--- /dev/null
+++ b/crypto/rsa/rsa_prn.c
@@ -0,0 +1,99 @@
+/* $OpenBSD: rsa_prn.c,v 1.10 2023/07/08 12:26:45 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+int
+RSA_print_fp(FILE *fp, const RSA *x, int off)
+{
+	BIO *b;
+	int ret;
+
+	if ((b = BIO_new(BIO_s_file())) == NULL) {
+		RSAerror(ERR_R_BUF_LIB);
+		return 0;
+	}
+	BIO_set_fp(b, fp, BIO_NOCLOSE);
+	ret = RSA_print(b, x, off);
+	BIO_free(b);
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_print_fp);
+
+int
+RSA_print(BIO *bp, const RSA *x, int off)
+{
+	EVP_PKEY *pk;
+	int ret = 0;
+
+	if ((pk = EVP_PKEY_new()) == NULL)
+		goto err;
+
+	if (!EVP_PKEY_set1_RSA(pk, (RSA *)x))
+		goto err;
+
+	ret = EVP_PKEY_print_private(bp, pk, off, NULL);
+ err:
+	EVP_PKEY_free(pk);
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_print);
diff --git a/crypto/rsa/rsa_pss.c b/crypto/rsa/rsa_pss.c
new file mode 100644
index 0000000..0860409
--- /dev/null
+++ b/crypto/rsa/rsa_pss.c
@@ -0,0 +1,288 @@
+/* $OpenBSD: rsa_pss.c,v 1.17 2023/07/08 12:26:45 beck Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "rsa_local.h"
+
+static const unsigned char zeroes[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+int
+RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, const EVP_MD *Hash,
+    const unsigned char *EM, int sLen)
+{
+	return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
+}
+LCRYPTO_ALIAS(RSA_verify_PKCS1_PSS);
+
+int
+RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash,
+    const EVP_MD *Hash, const EVP_MD *mgf1Hash, const unsigned char *EM,
+    int sLen)
+{
+	int i;
+	int ret = 0;
+	int hLen, maskedDBLen, MSBits, emLen;
+	const unsigned char *H;
+	unsigned char *DB = NULL;
+	EVP_MD_CTX ctx;
+	unsigned char H_[EVP_MAX_MD_SIZE];
+
+	EVP_MD_CTX_init(&ctx);
+
+	if (mgf1Hash == NULL)
+		mgf1Hash = Hash;
+
+	hLen = EVP_MD_size(Hash);
+	if (hLen < 0)
+		goto err;
+	/*
+	 * Negative sLen has special meanings:
+	 *	-1	sLen == hLen
+	 *	-2	salt length is autorecovered from signature
+	 *	-N	reserved
+	 */
+	if (sLen == -1)
+		sLen = hLen;
+	else if (sLen == -2)
+		sLen = -2;
+	else if (sLen < -2) {
+		RSAerror(RSA_R_SLEN_CHECK_FAILED);
+		goto err;
+	}
+
+	MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
+	emLen = RSA_size(rsa);
+	if (EM[0] & (0xFF << MSBits)) {
+		RSAerror(RSA_R_FIRST_OCTET_INVALID);
+		goto err;
+	}
+	if (MSBits == 0) {
+		EM++;
+		emLen--;
+	}
+	if (emLen < (hLen + sLen + 2)) {
+		/* sLen can be small negative */
+		RSAerror(RSA_R_DATA_TOO_LARGE);
+		goto err;
+	}
+	if (EM[emLen - 1] != 0xbc) {
+		RSAerror(RSA_R_LAST_OCTET_INVALID);
+		goto err;
+	}
+	maskedDBLen = emLen - hLen - 1;
+	H = EM + maskedDBLen;
+	DB = malloc(maskedDBLen);
+	if (!DB) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0)
+		goto err;
+	for (i = 0; i < maskedDBLen; i++)
+		DB[i] ^= EM[i];
+	if (MSBits)
+		DB[0] &= 0xFF >> (8 - MSBits);
+	for (i = 0; DB[i] == 0 && i < (maskedDBLen - 1); i++)
+		;
+	if (DB[i++] != 0x1) {
+		RSAerror(RSA_R_SLEN_RECOVERY_FAILED);
+		goto err;
+	}
+	if (sLen >= 0 && (maskedDBLen - i) != sLen) {
+		RSAerror(RSA_R_SLEN_CHECK_FAILED);
+		goto err;
+	}
+	if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
+	    !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
+	    !EVP_DigestUpdate(&ctx, mHash, hLen))
+		goto err;
+	if (maskedDBLen - i) {
+		if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i))
+			goto err;
+	}
+	if (!EVP_DigestFinal_ex(&ctx, H_, NULL))
+		goto err;
+	if (timingsafe_bcmp(H_, H, hLen)) {
+		RSAerror(RSA_R_BAD_SIGNATURE);
+		ret = 0;
+	} else
+		ret = 1;
+
+err:
+	free(DB);
+	EVP_MD_CTX_cleanup(&ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_verify_PKCS1_PSS_mgf1);
+
+int
+RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
+    const unsigned char *mHash, const EVP_MD *Hash, int sLen)
+{
+	return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_PSS);
+
+int
+RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
+    const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash,
+    int sLen)
+{
+	int i;
+	int ret = 0;
+	int hLen, maskedDBLen, MSBits, emLen;
+	unsigned char *H, *salt = NULL, *p;
+	EVP_MD_CTX ctx;
+
+	EVP_MD_CTX_init(&ctx);
+
+	if (mgf1Hash == NULL)
+		mgf1Hash = Hash;
+
+	hLen = EVP_MD_size(Hash);
+	if (hLen < 0)
+		goto err;
+	/*
+	 * Negative sLen has special meanings:
+	 *	-1	sLen == hLen
+	 *	-2	salt length is maximized
+	 *	-N	reserved
+	 */
+	if (sLen == -1)
+		sLen = hLen;
+	else if (sLen == -2)
+		sLen = -2;
+	else if (sLen < -2) {
+		RSAerror(RSA_R_SLEN_CHECK_FAILED);
+		goto err;
+	}
+
+	MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
+	emLen = RSA_size(rsa);
+	if (MSBits == 0) {
+		*EM++ = 0;
+		emLen--;
+	}
+	if (sLen == -2)
+		sLen = emLen - hLen - 2;
+	else if (emLen < (hLen + sLen + 2)) {
+		RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+		goto err;
+	}
+	if (sLen > 0) {
+		salt = malloc(sLen);
+		if (!salt) {
+			RSAerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		arc4random_buf(salt, sLen);
+	}
+	maskedDBLen = emLen - hLen - 1;
+	H = EM + maskedDBLen;
+	if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
+	    !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
+	    !EVP_DigestUpdate(&ctx, mHash, hLen))
+		goto err;
+	if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen))
+		goto err;
+	if (!EVP_DigestFinal_ex(&ctx, H, NULL))
+		goto err;
+
+	/* Generate dbMask in place then perform XOR on it */
+	if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash))
+		goto err;
+
+	p = EM;
+
+	/*
+	 * Initial PS XORs with all zeroes which is a NOP so just update
+	 * pointer. Note from a test above this value is guaranteed to
+	 * be non-negative.
+	 */
+	p += emLen - sLen - hLen - 2;
+	*p++ ^= 0x1;
+	if (sLen > 0) {
+		for (i = 0; i < sLen; i++)
+			*p++ ^= salt[i];
+	}
+	if (MSBits)
+		EM[0] &= 0xFF >> (8 - MSBits);
+
+	/* H is already in place so just set final 0xbc */
+	EM[emLen - 1] = 0xbc;
+
+	ret = 1;
+
+err:
+	free(salt);
+	EVP_MD_CTX_cleanup(&ctx);
+
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_padding_add_PKCS1_PSS_mgf1);
diff --git a/crypto/rsa/rsa_saos.c b/crypto/rsa/rsa_saos.c
new file mode 100644
index 0000000..07a4f5d
--- /dev/null
+++ b/crypto/rsa/rsa_saos.c
@@ -0,0 +1,143 @@
+/* $OpenBSD: rsa_saos.c,v 1.25 2023/07/08 12:26:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+RSA_sign_ASN1_OCTET_STRING(int type, const unsigned char *m, unsigned int m_len,
+    unsigned char *sigret, unsigned int *siglen, RSA *rsa)
+{
+	ASN1_OCTET_STRING sig;
+	int i, j, ret = 1;
+	unsigned char *p, *s;
+
+	sig.type = V_ASN1_OCTET_STRING;
+	sig.length = m_len;
+	sig.data = (unsigned char *)m;
+
+	i = i2d_ASN1_OCTET_STRING(&sig, NULL);
+	j = RSA_size(rsa);
+	if (i > (j - RSA_PKCS1_PADDING_SIZE)) {
+		RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+		return 0;
+	}
+	s = malloc(j + 1);
+	if (s == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	p = s;
+	i2d_ASN1_OCTET_STRING(&sig, &p);
+	i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING);
+	if (i <= 0)
+		ret = 0;
+	else
+		*siglen = i;
+
+	freezero(s, (unsigned int)j + 1);
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_sign_ASN1_OCTET_STRING);
+
+int
+RSA_verify_ASN1_OCTET_STRING(int dtype, const unsigned char *m,
+    unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
+{
+	int i, ret = 0;
+	unsigned char *s;
+	const unsigned char *p;
+	ASN1_OCTET_STRING *sig = NULL;
+
+	if (siglen != (unsigned int)RSA_size(rsa)) {
+		RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH);
+		return 0;
+	}
+
+	s = malloc(siglen);
+	if (s == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);
+
+	if (i <= 0)
+		goto err;
+
+	p = s;
+	sig = d2i_ASN1_OCTET_STRING(NULL, &p, (long)i);
+	if (sig == NULL)
+		goto err;
+
+	if ((unsigned int)sig->length != m_len ||
+	    timingsafe_bcmp(m, sig->data, m_len) != 0) {
+		RSAerror(RSA_R_BAD_SIGNATURE);
+	} else
+		ret = 1;
+err:
+	ASN1_OCTET_STRING_free(sig);
+	freezero(s, (unsigned int)siglen);
+	return ret;
+}
+LCRYPTO_ALIAS(RSA_verify_ASN1_OCTET_STRING);
diff --git a/crypto/rsa/rsa_sign.c b/crypto/rsa/rsa_sign.c
new file mode 100644
index 0000000..5356768
--- /dev/null
+++ b/crypto/rsa/rsa_sign.c
@@ -0,0 +1,280 @@
+/* $OpenBSD: rsa_sign.c,v 1.36 2023/07/08 12:26:45 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "asn1_local.h"
+#include "rsa_local.h"
+#include "x509_local.h"
+
+/* Size of an SSL signature: MD5+SHA1 */
+#define SSL_SIG_LENGTH	36
+
+static int encode_pkcs1(unsigned char **, int *, int , const unsigned char *,
+    unsigned int);
+
+/*
+ * encode_pkcs1 encodes a DigestInfo prefix of hash `type' and digest `m', as
+ * described in EMSA-PKCS-v1_5-ENCODE, RFC 8017 section 9. 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.  Freeing `*out' is
+ * the caller's responsibility. Failure is indicated by zero.
+ */
+static int
+encode_pkcs1(unsigned char **out, int *out_len, int type,
+    const unsigned char *m, unsigned int m_len)
+{
+	X509_SIG sig;
+	X509_ALGOR algor;
+	ASN1_TYPE parameter;
+	ASN1_OCTET_STRING digest;
+	uint8_t *der = NULL;
+	int len;
+
+	sig.algor = &algor;
+	if ((sig.algor->algorithm = OBJ_nid2obj(type)) == NULL) {
+		RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE);
+		return 0;
+	}
+	if (sig.algor->algorithm->length == 0) {
+		RSAerror(
+		    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 = ¶meter;
+
+	sig.digest = &digest;
+	sig.digest->data = (unsigned char *)m; /* TMP UGLY CAST */
+	sig.digest->length = m_len;
+
+	if ((len = i2d_X509_SIG(&sig, &der)) < 0)
+		return 0;
+
+	*out = der;
+	*out_len = len;
+
+	return 1;
+}
+
+int
+RSA_sign(int type, const unsigned char *m, unsigned int m_len,
+    unsigned char *sigret, unsigned int *siglen, RSA *rsa)
+{
+	const unsigned char *encoded = NULL;
+	unsigned char *tmps = NULL;
+	int encrypt_len, encoded_len = 0, ret = 0;
+
+	if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign != NULL)
+		return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa);
+
+	/* Compute the encoded digest. */
+	if (type == NID_md5_sha1) {
+		/*
+		 * NID_md5_sha1 corresponds to the MD5/SHA1 combination in
+		 * TLS 1.1 and earlier. It has no DigestInfo wrapper but
+		 * otherwise is RSASSA-PKCS-v1.5.
+		 */
+		if (m_len != SSL_SIG_LENGTH) {
+			RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
+			return 0;
+		}
+		encoded_len = SSL_SIG_LENGTH;
+		encoded = m;
+	} else {
+		if (!encode_pkcs1(&tmps, &encoded_len, type, m, m_len))
+			goto err;
+		encoded = tmps;
+	}
+	if (encoded_len > RSA_size(rsa) - RSA_PKCS1_PADDING_SIZE) {
+		RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+		goto err;
+	}
+	if ((encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret,
+	    rsa, RSA_PKCS1_PADDING)) <= 0)
+		goto err;
+
+	*siglen = encrypt_len;
+	ret = 1;
+
+ err:
+	freezero(tmps, (size_t)encoded_len);
+	return (ret);
+}
+LCRYPTO_ALIAS(RSA_sign);
+
+/*
+ * 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 the
+ * 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.
+ */
+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)
+{
+	unsigned char *decrypt_buf, *encoded = NULL;
+	int decrypt_len, encoded_len = 0, ret = 0;
+
+	if (siglen != (size_t)RSA_size(rsa)) {
+		RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH);
+		return 0;
+	}
+
+	/* Recover the encoded digest. */
+	if ((decrypt_buf = malloc(siglen)) == NULL) {
+		RSAerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if ((decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf,
+	    rsa, RSA_PKCS1_PADDING)) <= 0)
+		goto err;
+
+	if (type == NID_md5_sha1) {
+		/*
+		 * NID_md5_sha1 corresponds to the MD5/SHA1 combination in
+		 * TLS 1.1 and earlier. It has no DigestInfo wrapper but
+		 * otherwise is RSASSA-PKCS1-v1_5.
+		 */
+		if (decrypt_len != SSL_SIG_LENGTH) {
+			RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
+			goto err;
+		}
+
+		if (rm != NULL) {
+			memcpy(rm, decrypt_buf, SSL_SIG_LENGTH);
+			*prm_len = SSL_SIG_LENGTH;
+		} else {
+			if (m_len != SSL_SIG_LENGTH) {
+				RSAerror(RSA_R_INVALID_MESSAGE_LENGTH);
+				goto err;
+			}
+			if (timingsafe_bcmp(decrypt_buf,
+			    m, SSL_SIG_LENGTH) != 0) {
+				RSAerror(RSA_R_BAD_SIGNATURE);
+				goto err;
+			}
+		}
+	} else {
+		/*
+		 * 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;
+
+			if ((md = EVP_get_digestbynid(type)) == NULL) {
+				RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE);
+				goto err;
+			}
+			if ((m_len = EVP_MD_size(md)) > (size_t)decrypt_len) {
+				RSAerror(RSA_R_INVALID_DIGEST_LENGTH);
+				goto err;
+			}
+			m = decrypt_buf + decrypt_len - m_len;
+		}
+
+		/* Construct the encoded digest and ensure it matches */
+		if (!encode_pkcs1(&encoded, &encoded_len, type, m, m_len))
+			goto err;
+
+		if (encoded_len != decrypt_len ||
+		    timingsafe_bcmp(encoded, decrypt_buf, encoded_len) != 0) {
+			RSAerror(RSA_R_BAD_SIGNATURE);
+			goto err;
+		}
+
+		/* Output the recovered digest. */
+		if (rm != NULL) {
+			memcpy(rm, m, m_len);
+			*prm_len = m_len;
+		}
+	}
+
+	ret = 1;
+ err:
+	freezero(encoded, (size_t)encoded_len);
+	freezero(decrypt_buf, siglen);
+	return ret;
+}
+
+int
+RSA_verify(int dtype, const unsigned char *m, unsigned int m_len,
+    const unsigned char *sigbuf, unsigned int siglen, RSA *rsa)
+{
+	if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_verify)
+		return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen,
+		    rsa);
+
+	return int_rsa_verify(dtype, m, m_len, NULL, NULL, sigbuf, siglen, rsa);
+}
+LCRYPTO_ALIAS(RSA_verify);
diff --git a/crypto/rsa/rsa_x931.c b/crypto/rsa/rsa_x931.c
new file mode 100644
index 0000000..52f3f80
--- /dev/null
+++ b/crypto/rsa/rsa_x931.c
@@ -0,0 +1,164 @@
+/* $OpenBSD: rsa_x931.c,v 1.12 2023/05/05 12:19:37 tb Exp $ */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2005.
+ */
+/* ====================================================================
+ * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+int
+RSA_padding_add_X931(unsigned char *to, int tlen, const unsigned char *from,
+    int flen)
+{
+	int j;
+	unsigned char *p;
+
+	/*
+	 * Absolute minimum amount of padding is 1 header nibble, 1 padding
+	 * nibble and 2 trailer bytes: but 1 hash if is already in 'from'.
+	 */
+	j = tlen - flen - 2;
+
+	if (j < 0) {
+		RSAerror(RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+		return -1;
+	}
+
+	p = (unsigned char *)to;
+
+	/* If no padding start and end nibbles are in one byte */
+	if (j == 0)
+		*p++ = 0x6A;
+	else {
+		*p++ = 0x6B;
+		if (j > 1) {
+			memset(p, 0xBB, j - 1);
+			p += j - 1;
+		}
+		*p++ = 0xBA;
+	}
+	memcpy(p, from, flen);
+	p += flen;
+	*p = 0xCC;
+	return 1;
+}
+
+int
+RSA_padding_check_X931(unsigned char *to, int tlen, const unsigned char *from,
+    int flen, int num)
+{
+	int i = 0, j;
+	const unsigned char *p = from;
+
+	if (num != flen || (*p != 0x6A && *p != 0x6B)) {
+		RSAerror(RSA_R_INVALID_HEADER);
+		return -1;
+	}
+
+	if (*p++ == 0x6B) {
+		j = flen - 3;
+		for (i = 0; i < j; i++) {
+			unsigned char c = *p++;
+			if (c == 0xBA)
+				break;
+			if (c != 0xBB) {
+				RSAerror(RSA_R_INVALID_PADDING);
+				return -1;
+			}
+		}
+
+		if (i == 0) {
+			RSAerror(RSA_R_INVALID_PADDING);
+			return -1;
+		}
+
+		j -= i;
+	} else
+		j = flen - 2;
+
+	if (j < 0 || p[j] != 0xCC) {
+		RSAerror(RSA_R_INVALID_TRAILER);
+		return -1;
+	}
+
+	memcpy(to, p, j);
+
+	return j;
+}
+
+/* Translate between X931 hash ids and NIDs */
+
+int
+RSA_X931_hash_id(int nid)
+{
+	switch (nid) {
+	case NID_sha1:
+		return 0x33;
+	case NID_sha256:
+		return 0x34;
+	case NID_sha384:
+		return 0x36;
+	case NID_sha512:
+		return 0x35;
+	}
+
+	return -1;
+}
diff --git a/crypto/sha/sha1-elf-armv4.S b/crypto/sha/sha1-elf-armv4.S
new file mode 100644
index 0000000..5aeaf7c
--- /dev/null
+++ b/crypto/sha/sha1-elf-armv4.S
@@ -0,0 +1,455 @@
+#include "arm_arch.h"
+
+.text
+
+.global	sha1_block_data_order
+.type	sha1_block_data_order,%function
+
+.align	2
+sha1_block_data_order:
+	stmdb	sp!,{r4-r12,lr}
+	add	r2,r1,r2,lsl#6	@ r2 to point at the end of r1
+	ldmia	r0,{r3,r4,r5,r6,r7}
+.Lloop:
+	ldr	r8,.LK_00_19
+	mov	r14,sp
+	sub	sp,sp,#15*4
+	mov	r5,r5,ror#30
+	mov	r6,r6,ror#30
+	mov	r7,r7,ror#30		@ [6]
+.L_00_15:
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r4,r5			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r6,r8,r6,ror#2			@ E+=K_00_19
+	eor	r10,r4,r5			@ F_xx_xx
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r3,r10,ror#2
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r3,r4			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r5,r8,r5,ror#2			@ E+=K_00_19
+	eor	r10,r3,r4			@ F_xx_xx
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r7,r10,ror#2
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r7,r3			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r4,r8,r4,ror#2			@ E+=K_00_19
+	eor	r10,r7,r3			@ F_xx_xx
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r6,r10,ror#2
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r6,r7			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r3,r8,r3,ror#2			@ E+=K_00_19
+	eor	r10,r6,r7			@ F_xx_xx
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r5,r10,ror#2
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+	teq	r14,sp
+	bne	.L_00_15		@ [((11+4)*5+2)*3]
+	sub	sp,sp,#25*4
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r10,[r1,#2]
+	ldrb	r9,[r1,#3]
+	ldrb	r11,[r1,#1]
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	ldrb	r12,[r1],#4
+	orr	r9,r9,r10,lsl#8
+	eor	r10,r5,r6			@ F_xx_xx
+	orr	r9,r9,r11,lsl#16
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	orr	r9,r9,r12,lsl#24
+#else
+	ldr	r9,[r1],#4			@ handles unaligned
+	add	r7,r8,r7,ror#2			@ E+=K_00_19
+	eor	r10,r5,r6			@ F_xx_xx
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+#ifdef __ARMEL__
+	rev	r9,r9				@ byte swap
+#endif
+#endif
+	and	r10,r4,r10,ror#2
+	add	r7,r7,r9			@ E+=X[i]
+	eor	r10,r10,r6,ror#2		@ F_00_19(B,C,D)
+	str	r9,[r14,#-4]!
+	add	r7,r7,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	eor	r10,r10,r5,ror#2		@ F_00_19(B,C,D)
+	add	r6,r6,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	eor	r10,r10,r4,ror#2		@ F_00_19(B,C,D)
+	add	r5,r5,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	eor	r10,r10,r3,ror#2		@ F_00_19(B,C,D)
+	add	r4,r4,r10			@ E+=F_00_19(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	eor	r10,r10,r7,ror#2		@ F_00_19(B,C,D)
+	add	r3,r3,r10			@ E+=F_00_19(B,C,D)
+
+	ldr	r8,.LK_20_39		@ [+15+16*4]
+	cmn	sp,#0			@ [+3], clear carry to denote 20_39
+.L_20_39_or_60_79:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r4,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r3,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r7,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r6,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_20_39(B,C,D)
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	eor r10,r5,r10,ror#2					@ F_xx_xx
+						@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_20_39(B,C,D)
+	teq	r14,sp			@ preserve carry
+	bne	.L_20_39_or_60_79	@ [+((12+3)*5+2)*4]
+	bcs	.L_done			@ [+((12+3)*5+2)*4], spare 300 bytes
+
+	ldr	r8,.LK_40_59
+	sub	sp,sp,#20*4		@ [+2]
+.L_40_59:
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r7,r8,r7,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r5,r6			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r7,r7,r3,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r4,r10,ror#2					@ F_xx_xx
+	and r11,r5,r6					@ F_xx_xx
+	add	r7,r7,r9			@ E+=X[i]
+	add	r7,r7,r10			@ E+=F_40_59(B,C,D)
+	add	r7,r7,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r6,r8,r6,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r4,r5			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r6,r6,r7,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r3,r10,ror#2					@ F_xx_xx
+	and r11,r4,r5					@ F_xx_xx
+	add	r6,r6,r9			@ E+=X[i]
+	add	r6,r6,r10			@ E+=F_40_59(B,C,D)
+	add	r6,r6,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r5,r8,r5,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r3,r4			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r5,r5,r6,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r7,r10,ror#2					@ F_xx_xx
+	and r11,r3,r4					@ F_xx_xx
+	add	r5,r5,r9			@ E+=X[i]
+	add	r5,r5,r10			@ E+=F_40_59(B,C,D)
+	add	r5,r5,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r4,r8,r4,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r7,r3			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r4,r4,r5,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r6,r10,ror#2					@ F_xx_xx
+	and r11,r7,r3					@ F_xx_xx
+	add	r4,r4,r9			@ E+=X[i]
+	add	r4,r4,r10			@ E+=F_40_59(B,C,D)
+	add	r4,r4,r11,ror#2
+	ldr	r9,[r14,#15*4]
+	ldr	r10,[r14,#13*4]
+	ldr	r11,[r14,#7*4]
+	add	r3,r8,r3,ror#2			@ E+=K_xx_xx
+	ldr	r12,[r14,#2*4]
+	eor	r9,r9,r10
+	eor	r11,r11,r12			@ 1 cycle stall
+	eor	r10,r6,r7			@ F_xx_xx
+	mov	r9,r9,ror#31
+	add	r3,r3,r4,ror#27			@ E+=ROR(A,27)
+	eor	r9,r9,r11,ror#31
+	str	r9,[r14,#-4]!
+	and r10,r5,r10,ror#2					@ F_xx_xx
+	and r11,r6,r7					@ F_xx_xx
+	add	r3,r3,r9			@ E+=X[i]
+	add	r3,r3,r10			@ E+=F_40_59(B,C,D)
+	add	r3,r3,r11,ror#2
+	teq	r14,sp
+	bne	.L_40_59		@ [+((12+5)*5+2)*4]
+
+	ldr	r8,.LK_60_79
+	sub	sp,sp,#20*4
+	cmp	sp,#0			@ set carry to denote 60_79
+	b	.L_20_39_or_60_79	@ [+4], spare 300 bytes
+.L_done:
+	add	sp,sp,#80*4		@ "deallocate" stack frame
+	ldmia	r0,{r8,r9,r10,r11,r12}
+	add	r3,r8,r3
+	add	r4,r9,r4
+	add	r5,r10,r5,ror#2
+	add	r6,r11,r6,ror#2
+	add	r7,r12,r7,ror#2
+	stmia	r0,{r3,r4,r5,r6,r7}
+	teq	r1,r2
+	bne	.Lloop			@ [+18], total 1307
+
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.align	2
+.LK_00_19:	.word	0x5a827999
+.LK_20_39:	.word	0x6ed9eba1
+.LK_40_59:	.word	0x8f1bbcdc
+.LK_60_79:	.word	0xca62c1d6
+.size	sha1_block_data_order,.-sha1_block_data_order
+.asciz	"SHA1 block transform for ARMv4, CRYPTOGAMS by "
+.align	2
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha1-elf-x86_64.S b/crypto/sha/sha1-elf-x86_64.S
new file mode 100644
index 0000000..3240e9e
--- /dev/null
+++ b/crypto/sha/sha1-elf-x86_64.S
@@ -0,0 +1,2494 @@
+#include "x86_arch.h"
+.text	
+
+.hidden	OPENSSL_ia32cap_P
+
+.globl	sha1_block_data_order
+.type	sha1_block_data_order,@function
+.align	16
+sha1_block_data_order:
+	endbr64
+	movl	OPENSSL_ia32cap_P+0(%rip),%r9d
+	movl	OPENSSL_ia32cap_P+4(%rip),%r8d
+	testl	$IA32CAP_MASK1_SSSE3,%r8d
+	jz	.Lialu
+	jmp	_ssse3_shortcut
+
+.align	16
+.Lialu:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	movq	%rsp,%r11
+	movq	%rdi,%r8
+	subq	$72,%rsp
+	movq	%rsi,%r9
+	andq	$-64,%rsp
+	movq	%rdx,%r10
+	movq	%r11,64(%rsp)
+.Lprologue:
+
+	movl	0(%r8),%esi
+	movl	4(%r8),%edi
+	movl	8(%r8),%r11d
+	movl	12(%r8),%r12d
+	movl	16(%r8),%r13d
+	jmp	.Lloop
+
+.align	16
+.Lloop:
+	movl	0(%r9),%edx
+	bswapl	%edx
+	movl	%edx,0(%rsp)
+	movl	%r11d,%eax
+	movl	4(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	8(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,8(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	12(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	16(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,16(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	20(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	24(%r9),%edx
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%edx,24(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	28(%r9),%ebp
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	32(%r9),%edx
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	36(%r9),%ebp
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	40(%r9),%edx
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%edx,40(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	44(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	48(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,48(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	52(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	56(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,56(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	60(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	0(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	xorl	32(%rsp),%edx
+	andl	%edi,%eax
+	leal	1518500249(%rbp,%r13,1),%r13d
+	xorl	52(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$1,%edx
+	addl	%ecx,%r13d
+	roll	$30,%edi
+	movl	%edx,0(%rsp)
+	addl	%eax,%r13d
+	movl	4(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	xorl	36(%rsp),%ebp
+	andl	%esi,%eax
+	leal	1518500249(%rdx,%r12,1),%r12d
+	xorl	56(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$1,%ebp
+	addl	%ecx,%r12d
+	roll	$30,%esi
+	movl	%ebp,4(%rsp)
+	addl	%eax,%r12d
+	movl	8(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	xorl	40(%rsp),%edx
+	andl	%r13d,%eax
+	leal	1518500249(%rbp,%r11,1),%r11d
+	xorl	60(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$1,%edx
+	addl	%ecx,%r11d
+	roll	$30,%r13d
+	movl	%edx,8(%rsp)
+	addl	%eax,%r11d
+	movl	12(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	leal	1518500249(%rdx,%rdi,1),%edi
+	xorl	0(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$1,%ebp
+	addl	%ecx,%edi
+	roll	$30,%r12d
+	movl	%ebp,12(%rsp)
+	addl	%eax,%edi
+	movl	16(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	leal	1518500249(%rbp,%rsi,1),%esi
+	xorl	4(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$1,%edx
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	movl	%edx,16(%rsp)
+	addl	%eax,%esi
+	movl	20(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	52(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	8(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	56(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	12(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	16(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	20(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	24(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	28(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	32(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	36(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	40(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	44(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	48(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	52(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	56(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	60(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	0(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	4(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	8(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	12(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	16(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	20(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r13d
+	movl	40(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r12d
+	movl	44(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r11d
+	movl	48(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%edi
+	movl	52(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	60(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	40(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%esi
+	movl	56(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	0(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	44(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,56(%rsp)
+	addl	%ecx,%r13d
+	movl	60(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	4(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	48(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%r12d
+	movl	0(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	8(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	52(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,0(%rsp)
+	addl	%ecx,%r11d
+	movl	4(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	12(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	56(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%edi
+	movl	8(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	16(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	60(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,8(%rsp)
+	addl	%ecx,%esi
+	movl	12(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	20(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	0(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r13d
+	movl	16(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	24(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	4(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,16(%rsp)
+	addl	%ecx,%r12d
+	movl	20(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	28(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	8(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%r11d
+	movl	24(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	32(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	12(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,24(%rsp)
+	addl	%ecx,%edi
+	movl	28(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	36(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	16(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%esi
+	movl	32(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	40(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	20(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r13d
+	movl	36(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r12d
+	movl	40(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r11d
+	movl	44(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%edi
+	movl	48(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%esi
+	movl	52(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	20(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	40(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	24(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	44(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	48(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	52(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	56(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	60(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	0(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	4(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	8(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rsi,1),%esi
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	12(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	16(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	20(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	24(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	28(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	32(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	36(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	40(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	56(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	44(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	60(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	48(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	%r11d,%eax
+	leal	-899497514(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	addl	%eax,%esi
+	addl	0(%r8),%esi
+	addl	4(%r8),%edi
+	addl	8(%r8),%r11d
+	addl	12(%r8),%r12d
+	addl	16(%r8),%r13d
+	movl	%esi,0(%r8)
+	movl	%edi,4(%r8)
+	movl	%r11d,8(%r8)
+	movl	%r12d,12(%r8)
+	movl	%r13d,16(%r8)
+
+	subq	$1,%r10
+	leaq	64(%r9),%r9
+	jnz	.Lloop
+
+	movq	64(%rsp),%rsi
+	movq	(%rsi),%r13
+	movq	8(%rsi),%r12
+	movq	16(%rsi),%rbp
+	movq	24(%rsi),%rbx
+	leaq	32(%rsi),%rsp
+.Lepilogue:
+	retq
+.size	sha1_block_data_order,.-sha1_block_data_order
+.type	sha1_block_data_order_ssse3,@function
+.align	16
+sha1_block_data_order_ssse3:
+_ssse3_shortcut:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	leaq	-64(%rsp),%rsp
+	movq	%rdi,%r8
+	movq	%rsi,%r9
+	movq	%rdx,%r10
+
+	shlq	$6,%r10
+	addq	%r9,%r10
+	leaq	K_XX_XX(%rip),%r11
+
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movl	%ebx,%esi
+	movl	16(%r8),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	jmp	.Loop_ssse3
+.align	16
+.Loop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r10,%r9
+	je	.Ldone_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	addl	12(%r8),%edx
+	movl	%eax,0(%r8)
+	addl	16(%r8),%ebp
+	movl	%esi,4(%r8)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	jmp	.Loop_ssse3
+
+.align	16
+.Ldone_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	movl	%eax,0(%r8)
+	addl	12(%r8),%edx
+	movl	%esi,4(%r8)
+	addl	16(%r8),%ebp
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	leaq	64(%rsp),%rsi
+	movq	0(%rsi),%r12
+	movq	8(%rsi),%rbp
+	movq	16(%rsi),%rbx
+	leaq	24(%rsi),%rsp
+.Lepilogue_ssse3:
+	retq
+.size	sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
+.section	.rodata
+.align	64
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+.text	
+.align	64
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha1-macosx-x86_64.S b/crypto/sha/sha1-macosx-x86_64.S
new file mode 100644
index 0000000..04a8aff
--- /dev/null
+++ b/crypto/sha/sha1-macosx-x86_64.S
@@ -0,0 +1,2488 @@
+#include "x86_arch.h"
+.text	
+
+.private_extern	_OPENSSL_ia32cap_P
+
+.globl	_sha1_block_data_order
+
+.p2align	4
+_sha1_block_data_order:
+	movl	_OPENSSL_ia32cap_P+0(%rip),%r9d
+	movl	_OPENSSL_ia32cap_P+4(%rip),%r8d
+	testl	$IA32CAP_MASK1_SSSE3,%r8d
+	jz	L$ialu
+	jmp	_ssse3_shortcut
+
+.p2align	4
+L$ialu:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	movq	%rsp,%r11
+	movq	%rdi,%r8
+	subq	$72,%rsp
+	movq	%rsi,%r9
+	andq	$-64,%rsp
+	movq	%rdx,%r10
+	movq	%r11,64(%rsp)
+L$prologue:
+
+	movl	0(%r8),%esi
+	movl	4(%r8),%edi
+	movl	8(%r8),%r11d
+	movl	12(%r8),%r12d
+	movl	16(%r8),%r13d
+	jmp	L$loop
+
+.p2align	4
+L$loop:
+	movl	0(%r9),%edx
+	bswapl	%edx
+	movl	%edx,0(%rsp)
+	movl	%r11d,%eax
+	movl	4(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	8(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,8(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	12(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	16(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,16(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	20(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	24(%r9),%edx
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%edx,24(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	28(%r9),%ebp
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	32(%r9),%edx
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	36(%r9),%ebp
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	40(%r9),%edx
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%edx,40(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	44(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	48(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,48(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	52(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	56(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,56(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	60(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	0(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	xorl	32(%rsp),%edx
+	andl	%edi,%eax
+	leal	1518500249(%rbp,%r13,1),%r13d
+	xorl	52(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$1,%edx
+	addl	%ecx,%r13d
+	roll	$30,%edi
+	movl	%edx,0(%rsp)
+	addl	%eax,%r13d
+	movl	4(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	xorl	36(%rsp),%ebp
+	andl	%esi,%eax
+	leal	1518500249(%rdx,%r12,1),%r12d
+	xorl	56(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$1,%ebp
+	addl	%ecx,%r12d
+	roll	$30,%esi
+	movl	%ebp,4(%rsp)
+	addl	%eax,%r12d
+	movl	8(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	xorl	40(%rsp),%edx
+	andl	%r13d,%eax
+	leal	1518500249(%rbp,%r11,1),%r11d
+	xorl	60(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$1,%edx
+	addl	%ecx,%r11d
+	roll	$30,%r13d
+	movl	%edx,8(%rsp)
+	addl	%eax,%r11d
+	movl	12(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	leal	1518500249(%rdx,%rdi,1),%edi
+	xorl	0(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$1,%ebp
+	addl	%ecx,%edi
+	roll	$30,%r12d
+	movl	%ebp,12(%rsp)
+	addl	%eax,%edi
+	movl	16(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	leal	1518500249(%rbp,%rsi,1),%esi
+	xorl	4(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$1,%edx
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	movl	%edx,16(%rsp)
+	addl	%eax,%esi
+	movl	20(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	52(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	8(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	56(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	12(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	16(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	20(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	24(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	28(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	32(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	36(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	40(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	44(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	48(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	52(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	56(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	60(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	0(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	4(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	8(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	12(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	16(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	20(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r13d
+	movl	40(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r12d
+	movl	44(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r11d
+	movl	48(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%edi
+	movl	52(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	60(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	40(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%esi
+	movl	56(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	0(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	44(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,56(%rsp)
+	addl	%ecx,%r13d
+	movl	60(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	4(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	48(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%r12d
+	movl	0(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	8(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	52(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,0(%rsp)
+	addl	%ecx,%r11d
+	movl	4(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	12(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	56(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%edi
+	movl	8(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	16(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	60(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,8(%rsp)
+	addl	%ecx,%esi
+	movl	12(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	20(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	0(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r13d
+	movl	16(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	24(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	4(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,16(%rsp)
+	addl	%ecx,%r12d
+	movl	20(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	28(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	8(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%r11d
+	movl	24(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	32(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	12(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,24(%rsp)
+	addl	%ecx,%edi
+	movl	28(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	36(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	16(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%esi
+	movl	32(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	40(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	20(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r13d
+	movl	36(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r12d
+	movl	40(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r11d
+	movl	44(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%edi
+	movl	48(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%esi
+	movl	52(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	20(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	40(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	24(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	44(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	48(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	52(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	56(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	60(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	0(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	4(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	8(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rsi,1),%esi
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	12(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	16(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	20(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	24(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	28(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	32(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	36(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	40(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	56(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	44(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	60(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	48(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	%r11d,%eax
+	leal	-899497514(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	addl	%eax,%esi
+	addl	0(%r8),%esi
+	addl	4(%r8),%edi
+	addl	8(%r8),%r11d
+	addl	12(%r8),%r12d
+	addl	16(%r8),%r13d
+	movl	%esi,0(%r8)
+	movl	%edi,4(%r8)
+	movl	%r11d,8(%r8)
+	movl	%r12d,12(%r8)
+	movl	%r13d,16(%r8)
+
+	subq	$1,%r10
+	leaq	64(%r9),%r9
+	jnz	L$loop
+
+	movq	64(%rsp),%rsi
+	movq	(%rsi),%r13
+	movq	8(%rsi),%r12
+	movq	16(%rsi),%rbp
+	movq	24(%rsi),%rbx
+	leaq	32(%rsi),%rsp
+L$epilogue:
+	retq
+
+
+.p2align	4
+sha1_block_data_order_ssse3:
+_ssse3_shortcut:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	leaq	-64(%rsp),%rsp
+	movq	%rdi,%r8
+	movq	%rsi,%r9
+	movq	%rdx,%r10
+
+	shlq	$6,%r10
+	addq	%r9,%r10
+	leaq	K_XX_XX(%rip),%r11
+
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movl	%ebx,%esi
+	movl	16(%r8),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	jmp	L$oop_ssse3
+.p2align	4
+L$oop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r10,%r9
+	je	L$done_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	addl	12(%r8),%edx
+	movl	%eax,0(%r8)
+	addl	16(%r8),%ebp
+	movl	%esi,4(%r8)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	jmp	L$oop_ssse3
+
+.p2align	4
+L$done_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	movl	%eax,0(%r8)
+	addl	12(%r8),%edx
+	movl	%esi,4(%r8)
+	addl	16(%r8),%ebp
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	leaq	64(%rsp),%rsi
+	movq	0(%rsi),%r12
+	movq	8(%rsi),%rbp
+	movq	16(%rsi),%rbx
+	leaq	24(%rsi),%rsp
+L$epilogue_ssse3:
+	retq
+
+.p2align	6
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+.byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
diff --git a/crypto/sha/sha1-masm-x86_64.S b/crypto/sha/sha1-masm-x86_64.S
new file mode 100644
index 0000000..663bb98
--- /dev/null
+++ b/crypto/sha/sha1-masm-x86_64.S
@@ -0,0 +1,2746 @@
+; 1 "crypto/sha/sha1-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/sha/sha1-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/sha/sha1-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+EXTERN	OPENSSL_ia32cap_P:NEAR
+
+
+PUBLIC	sha1_block_data_order
+
+ALIGN	16
+sha1_block_data_order	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_sha1_block_data_order::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	mov	r9d,DWORD PTR[((OPENSSL_ia32cap_P+0))]
+	mov	r8d,DWORD PTR[((OPENSSL_ia32cap_P+4))]
+	test	r8d,(1 SHL 9)
+	jz	$L$ialu
+	jmp	_ssse3_shortcut
+
+ALIGN	16
+$L$ialu::
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	mov	r11,rsp
+	mov	r8,rdi
+	sub	rsp,72
+	mov	r9,rsi
+	and	rsp,-64
+	mov	r10,rdx
+	mov	QWORD PTR[64+rsp],r11
+$L$prologue::
+
+	mov	esi,DWORD PTR[r8]
+	mov	edi,DWORD PTR[4+r8]
+	mov	r11d,DWORD PTR[8+r8]
+	mov	r12d,DWORD PTR[12+r8]
+	mov	r13d,DWORD PTR[16+r8]
+	jmp	$L$loop
+
+ALIGN	16
+$L$loop::
+	mov	edx,DWORD PTR[r9]
+	bswap	edx
+	mov	DWORD PTR[rsp],edx
+	mov	eax,r11d
+	mov	ebp,DWORD PTR[4+r9]
+	mov	ecx,esi
+	xor	eax,r12d
+	bswap	ebp
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1518500249+r13*1+rdx]
+	and	eax,edi
+	mov	DWORD PTR[4+rsp],ebp
+	add	r13d,ecx
+	xor	eax,r12d
+	rol	edi,30
+	add	r13d,eax
+	mov	eax,edi
+	mov	edx,DWORD PTR[8+r9]
+	mov	ecx,r13d
+	xor	eax,r11d
+	bswap	edx
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1518500249+r12*1+rbp]
+	and	eax,esi
+	mov	DWORD PTR[8+rsp],edx
+	add	r12d,ecx
+	xor	eax,r11d
+	rol	esi,30
+	add	r12d,eax
+	mov	eax,esi
+	mov	ebp,DWORD PTR[12+r9]
+	mov	ecx,r12d
+	xor	eax,edi
+	bswap	ebp
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1518500249+r11*1+rdx]
+	and	eax,r13d
+	mov	DWORD PTR[12+rsp],ebp
+	add	r11d,ecx
+	xor	eax,edi
+	rol	r13d,30
+	add	r11d,eax
+	mov	eax,r13d
+	mov	edx,DWORD PTR[16+r9]
+	mov	ecx,r11d
+	xor	eax,esi
+	bswap	edx
+	rol	ecx,5
+	lea	edi,DWORD PTR[1518500249+rdi*1+rbp]
+	and	eax,r12d
+	mov	DWORD PTR[16+rsp],edx
+	add	edi,ecx
+	xor	eax,esi
+	rol	r12d,30
+	add	edi,eax
+	mov	eax,r12d
+	mov	ebp,DWORD PTR[20+r9]
+	mov	ecx,edi
+	xor	eax,r13d
+	bswap	ebp
+	rol	ecx,5
+	lea	esi,DWORD PTR[1518500249+rsi*1+rdx]
+	and	eax,r11d
+	mov	DWORD PTR[20+rsp],ebp
+	add	esi,ecx
+	xor	eax,r13d
+	rol	r11d,30
+	add	esi,eax
+	mov	eax,r11d
+	mov	edx,DWORD PTR[24+r9]
+	mov	ecx,esi
+	xor	eax,r12d
+	bswap	edx
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1518500249+r13*1+rbp]
+	and	eax,edi
+	mov	DWORD PTR[24+rsp],edx
+	add	r13d,ecx
+	xor	eax,r12d
+	rol	edi,30
+	add	r13d,eax
+	mov	eax,edi
+	mov	ebp,DWORD PTR[28+r9]
+	mov	ecx,r13d
+	xor	eax,r11d
+	bswap	ebp
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1518500249+r12*1+rdx]
+	and	eax,esi
+	mov	DWORD PTR[28+rsp],ebp
+	add	r12d,ecx
+	xor	eax,r11d
+	rol	esi,30
+	add	r12d,eax
+	mov	eax,esi
+	mov	edx,DWORD PTR[32+r9]
+	mov	ecx,r12d
+	xor	eax,edi
+	bswap	edx
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1518500249+r11*1+rbp]
+	and	eax,r13d
+	mov	DWORD PTR[32+rsp],edx
+	add	r11d,ecx
+	xor	eax,edi
+	rol	r13d,30
+	add	r11d,eax
+	mov	eax,r13d
+	mov	ebp,DWORD PTR[36+r9]
+	mov	ecx,r11d
+	xor	eax,esi
+	bswap	ebp
+	rol	ecx,5
+	lea	edi,DWORD PTR[1518500249+rdi*1+rdx]
+	and	eax,r12d
+	mov	DWORD PTR[36+rsp],ebp
+	add	edi,ecx
+	xor	eax,esi
+	rol	r12d,30
+	add	edi,eax
+	mov	eax,r12d
+	mov	edx,DWORD PTR[40+r9]
+	mov	ecx,edi
+	xor	eax,r13d
+	bswap	edx
+	rol	ecx,5
+	lea	esi,DWORD PTR[1518500249+rsi*1+rbp]
+	and	eax,r11d
+	mov	DWORD PTR[40+rsp],edx
+	add	esi,ecx
+	xor	eax,r13d
+	rol	r11d,30
+	add	esi,eax
+	mov	eax,r11d
+	mov	ebp,DWORD PTR[44+r9]
+	mov	ecx,esi
+	xor	eax,r12d
+	bswap	ebp
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1518500249+r13*1+rdx]
+	and	eax,edi
+	mov	DWORD PTR[44+rsp],ebp
+	add	r13d,ecx
+	xor	eax,r12d
+	rol	edi,30
+	add	r13d,eax
+	mov	eax,edi
+	mov	edx,DWORD PTR[48+r9]
+	mov	ecx,r13d
+	xor	eax,r11d
+	bswap	edx
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1518500249+r12*1+rbp]
+	and	eax,esi
+	mov	DWORD PTR[48+rsp],edx
+	add	r12d,ecx
+	xor	eax,r11d
+	rol	esi,30
+	add	r12d,eax
+	mov	eax,esi
+	mov	ebp,DWORD PTR[52+r9]
+	mov	ecx,r12d
+	xor	eax,edi
+	bswap	ebp
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1518500249+r11*1+rdx]
+	and	eax,r13d
+	mov	DWORD PTR[52+rsp],ebp
+	add	r11d,ecx
+	xor	eax,edi
+	rol	r13d,30
+	add	r11d,eax
+	mov	eax,r13d
+	mov	edx,DWORD PTR[56+r9]
+	mov	ecx,r11d
+	xor	eax,esi
+	bswap	edx
+	rol	ecx,5
+	lea	edi,DWORD PTR[1518500249+rdi*1+rbp]
+	and	eax,r12d
+	mov	DWORD PTR[56+rsp],edx
+	add	edi,ecx
+	xor	eax,esi
+	rol	r12d,30
+	add	edi,eax
+	mov	eax,r12d
+	mov	ebp,DWORD PTR[60+r9]
+	mov	ecx,edi
+	xor	eax,r13d
+	bswap	ebp
+	rol	ecx,5
+	lea	esi,DWORD PTR[1518500249+rsi*1+rdx]
+	and	eax,r11d
+	mov	DWORD PTR[60+rsp],ebp
+	add	esi,ecx
+	xor	eax,r13d
+	rol	r11d,30
+	add	esi,eax
+	mov	edx,DWORD PTR[rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[8+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	xor	edx,DWORD PTR[32+rsp]
+	and	eax,edi
+	lea	r13d,DWORD PTR[1518500249+r13*1+rbp]
+	xor	edx,DWORD PTR[52+rsp]
+	xor	eax,r12d
+	rol	edx,1
+	add	r13d,ecx
+	rol	edi,30
+	mov	DWORD PTR[rsp],edx
+	add	r13d,eax
+	mov	ebp,DWORD PTR[4+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	xor	ebp,DWORD PTR[36+rsp]
+	and	eax,esi
+	lea	r12d,DWORD PTR[1518500249+r12*1+rdx]
+	xor	ebp,DWORD PTR[56+rsp]
+	xor	eax,r11d
+	rol	ebp,1
+	add	r12d,ecx
+	rol	esi,30
+	mov	DWORD PTR[4+rsp],ebp
+	add	r12d,eax
+	mov	edx,DWORD PTR[8+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[16+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	xor	edx,DWORD PTR[40+rsp]
+	and	eax,r13d
+	lea	r11d,DWORD PTR[1518500249+r11*1+rbp]
+	xor	edx,DWORD PTR[60+rsp]
+	xor	eax,edi
+	rol	edx,1
+	add	r11d,ecx
+	rol	r13d,30
+	mov	DWORD PTR[8+rsp],edx
+	add	r11d,eax
+	mov	ebp,DWORD PTR[12+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	xor	ebp,DWORD PTR[44+rsp]
+	and	eax,r12d
+	lea	edi,DWORD PTR[1518500249+rdi*1+rdx]
+	xor	ebp,DWORD PTR[rsp]
+	xor	eax,esi
+	rol	ebp,1
+	add	edi,ecx
+	rol	r12d,30
+	mov	DWORD PTR[12+rsp],ebp
+	add	edi,eax
+	mov	edx,DWORD PTR[16+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	xor	edx,DWORD PTR[48+rsp]
+	and	eax,r11d
+	lea	esi,DWORD PTR[1518500249+rsi*1+rbp]
+	xor	edx,DWORD PTR[4+rsp]
+	xor	eax,r13d
+	rol	edx,1
+	add	esi,ecx
+	rol	r11d,30
+	mov	DWORD PTR[16+rsp],edx
+	add	esi,eax
+	mov	ebp,DWORD PTR[20+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1859775393+r13*1+rdx]
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	ebp,DWORD PTR[8+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	ebp,1
+	mov	DWORD PTR[20+rsp],ebp
+	mov	edx,DWORD PTR[24+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[32+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1859775393+r12*1+rbp]
+	xor	edx,DWORD PTR[56+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	edx,DWORD PTR[12+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	edx,1
+	mov	DWORD PTR[24+rsp],edx
+	mov	ebp,DWORD PTR[28+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1859775393+r11*1+rdx]
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	ebp,DWORD PTR[16+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	ebp,1
+	mov	DWORD PTR[28+rsp],ebp
+	mov	edx,DWORD PTR[32+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[40+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[1859775393+rdi*1+rbp]
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	edx,DWORD PTR[20+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	edx,1
+	mov	DWORD PTR[32+rsp],edx
+	mov	ebp,DWORD PTR[36+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[44+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[1859775393+rsi*1+rdx]
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	ebp,DWORD PTR[24+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	ebp,1
+	mov	DWORD PTR[36+rsp],ebp
+	mov	edx,DWORD PTR[40+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[48+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1859775393+r13*1+rbp]
+	xor	edx,DWORD PTR[8+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	edx,DWORD PTR[28+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	edx,1
+	mov	DWORD PTR[40+rsp],edx
+	mov	ebp,DWORD PTR[44+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1859775393+r12*1+rdx]
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	ebp,DWORD PTR[32+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	ebp,1
+	mov	DWORD PTR[44+rsp],ebp
+	mov	edx,DWORD PTR[48+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[56+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1859775393+r11*1+rbp]
+	xor	edx,DWORD PTR[16+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	edx,DWORD PTR[36+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	edx,1
+	mov	DWORD PTR[48+rsp],edx
+	mov	ebp,DWORD PTR[52+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[1859775393+rdi*1+rdx]
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	ebp,DWORD PTR[40+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	ebp,1
+	mov	DWORD PTR[52+rsp],ebp
+	mov	edx,DWORD PTR[56+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[1859775393+rsi*1+rbp]
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	edx,DWORD PTR[44+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	edx,1
+	mov	DWORD PTR[56+rsp],edx
+	mov	ebp,DWORD PTR[60+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1859775393+r13*1+rdx]
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	ebp,DWORD PTR[48+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	ebp,1
+	mov	DWORD PTR[60+rsp],ebp
+	mov	edx,DWORD PTR[rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[8+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1859775393+r12*1+rbp]
+	xor	edx,DWORD PTR[32+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	edx,DWORD PTR[52+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	edx,1
+	mov	DWORD PTR[rsp],edx
+	mov	ebp,DWORD PTR[4+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1859775393+r11*1+rdx]
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	ebp,DWORD PTR[56+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	ebp,1
+	mov	DWORD PTR[4+rsp],ebp
+	mov	edx,DWORD PTR[8+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[16+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[1859775393+rdi*1+rbp]
+	xor	edx,DWORD PTR[40+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	edx,DWORD PTR[60+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	edx,1
+	mov	DWORD PTR[8+rsp],edx
+	mov	ebp,DWORD PTR[12+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[1859775393+rsi*1+rdx]
+	xor	ebp,DWORD PTR[44+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	ebp,DWORD PTR[rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	ebp,1
+	mov	DWORD PTR[12+rsp],ebp
+	mov	edx,DWORD PTR[16+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[1859775393+r13*1+rbp]
+	xor	edx,DWORD PTR[48+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	edx,DWORD PTR[4+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	edx,1
+	mov	DWORD PTR[16+rsp],edx
+	mov	ebp,DWORD PTR[20+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[1859775393+r12*1+rdx]
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	ebp,DWORD PTR[8+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	ebp,1
+	mov	DWORD PTR[20+rsp],ebp
+	mov	edx,DWORD PTR[24+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[32+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[1859775393+r11*1+rbp]
+	xor	edx,DWORD PTR[56+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	edx,DWORD PTR[12+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	edx,1
+	mov	DWORD PTR[24+rsp],edx
+	mov	ebp,DWORD PTR[28+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[1859775393+rdi*1+rdx]
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	ebp,DWORD PTR[16+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	ebp,1
+	mov	DWORD PTR[28+rsp],ebp
+	mov	edx,DWORD PTR[32+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[40+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[1859775393+rsi*1+rbp]
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	edx,DWORD PTR[20+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	edx,1
+	mov	DWORD PTR[32+rsp],edx
+	mov	ebp,DWORD PTR[36+rsp]
+	mov	eax,r11d
+	mov	ebx,r11d
+	xor	ebp,DWORD PTR[44+rsp]
+	and	eax,r12d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	ebx,r12d
+	lea	r13d,DWORD PTR[((-1894007588))+r13*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[24+rsp]
+	add	r13d,eax
+	and	ebx,edi
+	rol	ebp,1
+	add	r13d,ebx
+	rol	edi,30
+	mov	DWORD PTR[36+rsp],ebp
+	add	r13d,ecx
+	mov	edx,DWORD PTR[40+rsp]
+	mov	eax,edi
+	mov	ebx,edi
+	xor	edx,DWORD PTR[48+rsp]
+	and	eax,r11d
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[8+rsp]
+	xor	ebx,r11d
+	lea	r12d,DWORD PTR[((-1894007588))+r12*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[28+rsp]
+	add	r12d,eax
+	and	ebx,esi
+	rol	edx,1
+	add	r12d,ebx
+	rol	esi,30
+	mov	DWORD PTR[40+rsp],edx
+	add	r12d,ecx
+	mov	ebp,DWORD PTR[44+rsp]
+	mov	eax,esi
+	mov	ebx,esi
+	xor	ebp,DWORD PTR[52+rsp]
+	and	eax,edi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	ebx,edi
+	lea	r11d,DWORD PTR[((-1894007588))+r11*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[32+rsp]
+	add	r11d,eax
+	and	ebx,r13d
+	rol	ebp,1
+	add	r11d,ebx
+	rol	r13d,30
+	mov	DWORD PTR[44+rsp],ebp
+	add	r11d,ecx
+	mov	edx,DWORD PTR[48+rsp]
+	mov	eax,r13d
+	mov	ebx,r13d
+	xor	edx,DWORD PTR[56+rsp]
+	and	eax,esi
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[16+rsp]
+	xor	ebx,esi
+	lea	edi,DWORD PTR[((-1894007588))+rdi*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[36+rsp]
+	add	edi,eax
+	and	ebx,r12d
+	rol	edx,1
+	add	edi,ebx
+	rol	r12d,30
+	mov	DWORD PTR[48+rsp],edx
+	add	edi,ecx
+	mov	ebp,DWORD PTR[52+rsp]
+	mov	eax,r12d
+	mov	ebx,r12d
+	xor	ebp,DWORD PTR[60+rsp]
+	and	eax,r13d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	ebx,r13d
+	lea	esi,DWORD PTR[((-1894007588))+rsi*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[40+rsp]
+	add	esi,eax
+	and	ebx,r11d
+	rol	ebp,1
+	add	esi,ebx
+	rol	r11d,30
+	mov	DWORD PTR[52+rsp],ebp
+	add	esi,ecx
+	mov	edx,DWORD PTR[56+rsp]
+	mov	eax,r11d
+	mov	ebx,r11d
+	xor	edx,DWORD PTR[rsp]
+	and	eax,r12d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[24+rsp]
+	xor	ebx,r12d
+	lea	r13d,DWORD PTR[((-1894007588))+r13*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[44+rsp]
+	add	r13d,eax
+	and	ebx,edi
+	rol	edx,1
+	add	r13d,ebx
+	rol	edi,30
+	mov	DWORD PTR[56+rsp],edx
+	add	r13d,ecx
+	mov	ebp,DWORD PTR[60+rsp]
+	mov	eax,edi
+	mov	ebx,edi
+	xor	ebp,DWORD PTR[4+rsp]
+	and	eax,r11d
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	ebx,r11d
+	lea	r12d,DWORD PTR[((-1894007588))+r12*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[48+rsp]
+	add	r12d,eax
+	and	ebx,esi
+	rol	ebp,1
+	add	r12d,ebx
+	rol	esi,30
+	mov	DWORD PTR[60+rsp],ebp
+	add	r12d,ecx
+	mov	edx,DWORD PTR[rsp]
+	mov	eax,esi
+	mov	ebx,esi
+	xor	edx,DWORD PTR[8+rsp]
+	and	eax,edi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[32+rsp]
+	xor	ebx,edi
+	lea	r11d,DWORD PTR[((-1894007588))+r11*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[52+rsp]
+	add	r11d,eax
+	and	ebx,r13d
+	rol	edx,1
+	add	r11d,ebx
+	rol	r13d,30
+	mov	DWORD PTR[rsp],edx
+	add	r11d,ecx
+	mov	ebp,DWORD PTR[4+rsp]
+	mov	eax,r13d
+	mov	ebx,r13d
+	xor	ebp,DWORD PTR[12+rsp]
+	and	eax,esi
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	ebx,esi
+	lea	edi,DWORD PTR[((-1894007588))+rdi*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[56+rsp]
+	add	edi,eax
+	and	ebx,r12d
+	rol	ebp,1
+	add	edi,ebx
+	rol	r12d,30
+	mov	DWORD PTR[4+rsp],ebp
+	add	edi,ecx
+	mov	edx,DWORD PTR[8+rsp]
+	mov	eax,r12d
+	mov	ebx,r12d
+	xor	edx,DWORD PTR[16+rsp]
+	and	eax,r13d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[40+rsp]
+	xor	ebx,r13d
+	lea	esi,DWORD PTR[((-1894007588))+rsi*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[60+rsp]
+	add	esi,eax
+	and	ebx,r11d
+	rol	edx,1
+	add	esi,ebx
+	rol	r11d,30
+	mov	DWORD PTR[8+rsp],edx
+	add	esi,ecx
+	mov	ebp,DWORD PTR[12+rsp]
+	mov	eax,r11d
+	mov	ebx,r11d
+	xor	ebp,DWORD PTR[20+rsp]
+	and	eax,r12d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[44+rsp]
+	xor	ebx,r12d
+	lea	r13d,DWORD PTR[((-1894007588))+r13*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[rsp]
+	add	r13d,eax
+	and	ebx,edi
+	rol	ebp,1
+	add	r13d,ebx
+	rol	edi,30
+	mov	DWORD PTR[12+rsp],ebp
+	add	r13d,ecx
+	mov	edx,DWORD PTR[16+rsp]
+	mov	eax,edi
+	mov	ebx,edi
+	xor	edx,DWORD PTR[24+rsp]
+	and	eax,r11d
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[48+rsp]
+	xor	ebx,r11d
+	lea	r12d,DWORD PTR[((-1894007588))+r12*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[4+rsp]
+	add	r12d,eax
+	and	ebx,esi
+	rol	edx,1
+	add	r12d,ebx
+	rol	esi,30
+	mov	DWORD PTR[16+rsp],edx
+	add	r12d,ecx
+	mov	ebp,DWORD PTR[20+rsp]
+	mov	eax,esi
+	mov	ebx,esi
+	xor	ebp,DWORD PTR[28+rsp]
+	and	eax,edi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	ebx,edi
+	lea	r11d,DWORD PTR[((-1894007588))+r11*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[8+rsp]
+	add	r11d,eax
+	and	ebx,r13d
+	rol	ebp,1
+	add	r11d,ebx
+	rol	r13d,30
+	mov	DWORD PTR[20+rsp],ebp
+	add	r11d,ecx
+	mov	edx,DWORD PTR[24+rsp]
+	mov	eax,r13d
+	mov	ebx,r13d
+	xor	edx,DWORD PTR[32+rsp]
+	and	eax,esi
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[56+rsp]
+	xor	ebx,esi
+	lea	edi,DWORD PTR[((-1894007588))+rdi*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[12+rsp]
+	add	edi,eax
+	and	ebx,r12d
+	rol	edx,1
+	add	edi,ebx
+	rol	r12d,30
+	mov	DWORD PTR[24+rsp],edx
+	add	edi,ecx
+	mov	ebp,DWORD PTR[28+rsp]
+	mov	eax,r12d
+	mov	ebx,r12d
+	xor	ebp,DWORD PTR[36+rsp]
+	and	eax,r13d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	ebx,r13d
+	lea	esi,DWORD PTR[((-1894007588))+rsi*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[16+rsp]
+	add	esi,eax
+	and	ebx,r11d
+	rol	ebp,1
+	add	esi,ebx
+	rol	r11d,30
+	mov	DWORD PTR[28+rsp],ebp
+	add	esi,ecx
+	mov	edx,DWORD PTR[32+rsp]
+	mov	eax,r11d
+	mov	ebx,r11d
+	xor	edx,DWORD PTR[40+rsp]
+	and	eax,r12d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[rsp]
+	xor	ebx,r12d
+	lea	r13d,DWORD PTR[((-1894007588))+r13*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[20+rsp]
+	add	r13d,eax
+	and	ebx,edi
+	rol	edx,1
+	add	r13d,ebx
+	rol	edi,30
+	mov	DWORD PTR[32+rsp],edx
+	add	r13d,ecx
+	mov	ebp,DWORD PTR[36+rsp]
+	mov	eax,edi
+	mov	ebx,edi
+	xor	ebp,DWORD PTR[44+rsp]
+	and	eax,r11d
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	ebx,r11d
+	lea	r12d,DWORD PTR[((-1894007588))+r12*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[24+rsp]
+	add	r12d,eax
+	and	ebx,esi
+	rol	ebp,1
+	add	r12d,ebx
+	rol	esi,30
+	mov	DWORD PTR[36+rsp],ebp
+	add	r12d,ecx
+	mov	edx,DWORD PTR[40+rsp]
+	mov	eax,esi
+	mov	ebx,esi
+	xor	edx,DWORD PTR[48+rsp]
+	and	eax,edi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[8+rsp]
+	xor	ebx,edi
+	lea	r11d,DWORD PTR[((-1894007588))+r11*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[28+rsp]
+	add	r11d,eax
+	and	ebx,r13d
+	rol	edx,1
+	add	r11d,ebx
+	rol	r13d,30
+	mov	DWORD PTR[40+rsp],edx
+	add	r11d,ecx
+	mov	ebp,DWORD PTR[44+rsp]
+	mov	eax,r13d
+	mov	ebx,r13d
+	xor	ebp,DWORD PTR[52+rsp]
+	and	eax,esi
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	ebx,esi
+	lea	edi,DWORD PTR[((-1894007588))+rdi*1+rdx]
+	rol	ecx,5
+	xor	ebp,DWORD PTR[32+rsp]
+	add	edi,eax
+	and	ebx,r12d
+	rol	ebp,1
+	add	edi,ebx
+	rol	r12d,30
+	mov	DWORD PTR[44+rsp],ebp
+	add	edi,ecx
+	mov	edx,DWORD PTR[48+rsp]
+	mov	eax,r12d
+	mov	ebx,r12d
+	xor	edx,DWORD PTR[56+rsp]
+	and	eax,r13d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[16+rsp]
+	xor	ebx,r13d
+	lea	esi,DWORD PTR[((-1894007588))+rsi*1+rbp]
+	rol	ecx,5
+	xor	edx,DWORD PTR[36+rsp]
+	add	esi,eax
+	and	ebx,r11d
+	rol	edx,1
+	add	esi,ebx
+	rol	r11d,30
+	mov	DWORD PTR[48+rsp],edx
+	add	esi,ecx
+	mov	ebp,DWORD PTR[52+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[((-899497514))+r13*1+rdx]
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	ebp,DWORD PTR[40+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	ebp,1
+	mov	DWORD PTR[52+rsp],ebp
+	mov	edx,DWORD PTR[56+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[((-899497514))+r12*1+rbp]
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	edx,DWORD PTR[44+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	edx,1
+	mov	DWORD PTR[56+rsp],edx
+	mov	ebp,DWORD PTR[60+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[((-899497514))+r11*1+rdx]
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	ebp,DWORD PTR[48+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	ebp,1
+	mov	DWORD PTR[60+rsp],ebp
+	mov	edx,DWORD PTR[rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[8+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[((-899497514))+rdi*1+rbp]
+	xor	edx,DWORD PTR[32+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	edx,DWORD PTR[52+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	edx,1
+	mov	DWORD PTR[rsp],edx
+	mov	ebp,DWORD PTR[4+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[((-899497514))+rsi*1+rdx]
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	ebp,DWORD PTR[56+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	ebp,1
+	mov	DWORD PTR[4+rsp],ebp
+	mov	edx,DWORD PTR[8+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[16+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[((-899497514))+r13*1+rbp]
+	xor	edx,DWORD PTR[40+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	edx,DWORD PTR[60+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	edx,1
+	mov	DWORD PTR[8+rsp],edx
+	mov	ebp,DWORD PTR[12+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[((-899497514))+r12*1+rdx]
+	xor	ebp,DWORD PTR[44+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	ebp,DWORD PTR[rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	ebp,1
+	mov	DWORD PTR[12+rsp],ebp
+	mov	edx,DWORD PTR[16+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[((-899497514))+r11*1+rbp]
+	xor	edx,DWORD PTR[48+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	edx,DWORD PTR[4+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	edx,1
+	mov	DWORD PTR[16+rsp],edx
+	mov	ebp,DWORD PTR[20+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[((-899497514))+rdi*1+rdx]
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	ebp,DWORD PTR[8+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	ebp,1
+	mov	DWORD PTR[20+rsp],ebp
+	mov	edx,DWORD PTR[24+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	edx,DWORD PTR[32+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[((-899497514))+rsi*1+rbp]
+	xor	edx,DWORD PTR[56+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	edx,DWORD PTR[12+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	edx,1
+	mov	DWORD PTR[24+rsp],edx
+	mov	ebp,DWORD PTR[28+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	ebp,DWORD PTR[36+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[((-899497514))+r13*1+rdx]
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	ebp,DWORD PTR[16+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	ebp,1
+	mov	DWORD PTR[28+rsp],ebp
+	mov	edx,DWORD PTR[32+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	edx,DWORD PTR[40+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[((-899497514))+r12*1+rbp]
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	edx,DWORD PTR[20+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	edx,1
+	mov	DWORD PTR[32+rsp],edx
+	mov	ebp,DWORD PTR[36+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	ebp,DWORD PTR[44+rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[((-899497514))+r11*1+rdx]
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	ebp,DWORD PTR[24+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	ebp,1
+	mov	DWORD PTR[36+rsp],ebp
+	mov	edx,DWORD PTR[40+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	edx,DWORD PTR[48+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[((-899497514))+rdi*1+rbp]
+	xor	edx,DWORD PTR[8+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	edx,DWORD PTR[28+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	edx,1
+	mov	DWORD PTR[40+rsp],edx
+	mov	ebp,DWORD PTR[44+rsp]
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	ebp,DWORD PTR[52+rsp]
+	xor	eax,r11d
+	rol	ecx,5
+	lea	esi,DWORD PTR[((-899497514))+rsi*1+rdx]
+	xor	ebp,DWORD PTR[12+rsp]
+	xor	eax,r13d
+	add	esi,ecx
+	xor	ebp,DWORD PTR[32+rsp]
+	rol	r11d,30
+	add	esi,eax
+	rol	ebp,1
+	mov	DWORD PTR[44+rsp],ebp
+	mov	edx,DWORD PTR[48+rsp]
+	mov	eax,r11d
+	mov	ecx,esi
+	xor	edx,DWORD PTR[56+rsp]
+	xor	eax,edi
+	rol	ecx,5
+	lea	r13d,DWORD PTR[((-899497514))+r13*1+rbp]
+	xor	edx,DWORD PTR[16+rsp]
+	xor	eax,r12d
+	add	r13d,ecx
+	xor	edx,DWORD PTR[36+rsp]
+	rol	edi,30
+	add	r13d,eax
+	rol	edx,1
+	mov	DWORD PTR[48+rsp],edx
+	mov	ebp,DWORD PTR[52+rsp]
+	mov	eax,edi
+	mov	ecx,r13d
+	xor	ebp,DWORD PTR[60+rsp]
+	xor	eax,esi
+	rol	ecx,5
+	lea	r12d,DWORD PTR[((-899497514))+r12*1+rdx]
+	xor	ebp,DWORD PTR[20+rsp]
+	xor	eax,r11d
+	add	r12d,ecx
+	xor	ebp,DWORD PTR[40+rsp]
+	rol	esi,30
+	add	r12d,eax
+	rol	ebp,1
+	mov	edx,DWORD PTR[56+rsp]
+	mov	eax,esi
+	mov	ecx,r12d
+	xor	edx,DWORD PTR[rsp]
+	xor	eax,r13d
+	rol	ecx,5
+	lea	r11d,DWORD PTR[((-899497514))+r11*1+rbp]
+	xor	edx,DWORD PTR[24+rsp]
+	xor	eax,edi
+	add	r11d,ecx
+	xor	edx,DWORD PTR[44+rsp]
+	rol	r13d,30
+	add	r11d,eax
+	rol	edx,1
+	mov	ebp,DWORD PTR[60+rsp]
+	mov	eax,r13d
+	mov	ecx,r11d
+	xor	ebp,DWORD PTR[4+rsp]
+	xor	eax,r12d
+	rol	ecx,5
+	lea	edi,DWORD PTR[((-899497514))+rdi*1+rdx]
+	xor	ebp,DWORD PTR[28+rsp]
+	xor	eax,esi
+	add	edi,ecx
+	xor	ebp,DWORD PTR[48+rsp]
+	rol	r12d,30
+	add	edi,eax
+	rol	ebp,1
+	mov	eax,r12d
+	mov	ecx,edi
+	xor	eax,r11d
+	lea	esi,DWORD PTR[((-899497514))+rsi*1+rbp]
+	rol	ecx,5
+	xor	eax,r13d
+	add	esi,ecx
+	rol	r11d,30
+	add	esi,eax
+	add	esi,DWORD PTR[r8]
+	add	edi,DWORD PTR[4+r8]
+	add	r11d,DWORD PTR[8+r8]
+	add	r12d,DWORD PTR[12+r8]
+	add	r13d,DWORD PTR[16+r8]
+	mov	DWORD PTR[r8],esi
+	mov	DWORD PTR[4+r8],edi
+	mov	DWORD PTR[8+r8],r11d
+	mov	DWORD PTR[12+r8],r12d
+	mov	DWORD PTR[16+r8],r13d
+
+	sub	r10,1
+	lea	r9,QWORD PTR[64+r9]
+	jnz	$L$loop
+
+	mov	rsi,QWORD PTR[64+rsp]
+	mov	r13,QWORD PTR[rsi]
+	mov	r12,QWORD PTR[8+rsi]
+	mov	rbp,QWORD PTR[16+rsi]
+	mov	rbx,QWORD PTR[24+rsi]
+	lea	rsp,QWORD PTR[32+rsi]
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_sha1_block_data_order::
+sha1_block_data_order	ENDP
+
+ALIGN	16
+sha1_block_data_order_ssse3	PROC PRIVATE
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_sha1_block_data_order_ssse3::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+_ssse3_shortcut::
+	push	rbx
+	push	rbp
+	push	r12
+	lea	rsp,QWORD PTR[((-144))+rsp]
+	movaps	XMMWORD PTR[(64+0)+rsp],xmm6
+	movaps	XMMWORD PTR[(64+16)+rsp],xmm7
+	movaps	XMMWORD PTR[(64+32)+rsp],xmm8
+	movaps	XMMWORD PTR[(64+48)+rsp],xmm9
+	movaps	XMMWORD PTR[(64+64)+rsp],xmm10
+$L$prologue_ssse3::
+	mov	r8,rdi
+	mov	r9,rsi
+	mov	r10,rdx
+
+	shl	r10,6
+	add	r10,r9
+	lea	r11,QWORD PTR[K_XX_XX]
+
+	mov	eax,DWORD PTR[r8]
+	mov	ebx,DWORD PTR[4+r8]
+	mov	ecx,DWORD PTR[8+r8]
+	mov	edx,DWORD PTR[12+r8]
+	mov	esi,ebx
+	mov	ebp,DWORD PTR[16+r8]
+
+	movdqa	xmm6,XMMWORD PTR[64+r11]
+	movdqa	xmm9,XMMWORD PTR[r11]
+	movdqu	xmm0,XMMWORD PTR[r9]
+	movdqu	xmm1,XMMWORD PTR[16+r9]
+	movdqu	xmm2,XMMWORD PTR[32+r9]
+	movdqu	xmm3,XMMWORD PTR[48+r9]
+DB	102,15,56,0,198
+	add	r9,64
+DB	102,15,56,0,206
+DB	102,15,56,0,214
+DB	102,15,56,0,222
+	paddd	xmm0,xmm9
+	paddd	xmm1,xmm9
+	paddd	xmm2,xmm9
+	movdqa	XMMWORD PTR[rsp],xmm0
+	psubd	xmm0,xmm9
+	movdqa	XMMWORD PTR[16+rsp],xmm1
+	psubd	xmm1,xmm9
+	movdqa	XMMWORD PTR[32+rsp],xmm2
+	psubd	xmm2,xmm9
+	jmp	$L$oop_ssse3
+ALIGN	16
+$L$oop_ssse3::
+	movdqa	xmm4,xmm1
+	add	ebp,DWORD PTR[rsp]
+	xor	ecx,edx
+	movdqa	xmm8,xmm3
+DB	102,15,58,15,224,8
+	mov	edi,eax
+	rol	eax,5
+	paddd	xmm9,xmm3
+	and	esi,ecx
+	xor	ecx,edx
+	psrldq	xmm8,4
+	xor	esi,edx
+	add	ebp,eax
+	pxor	xmm4,xmm0
+	ror	ebx,2
+	add	ebp,esi
+	pxor	xmm8,xmm2
+	add	edx,DWORD PTR[4+rsp]
+	xor	ebx,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	pxor	xmm4,xmm8
+	and	edi,ebx
+	xor	ebx,ecx
+	movdqa	XMMWORD PTR[48+rsp],xmm9
+	xor	edi,ecx
+	add	edx,ebp
+	movdqa	xmm10,xmm4
+	movdqa	xmm8,xmm4
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[8+rsp]
+	xor	eax,ebx
+	pslldq	xmm10,12
+	paddd	xmm4,xmm4
+	mov	edi,edx
+	rol	edx,5
+	and	esi,eax
+	xor	eax,ebx
+	psrld	xmm8,31
+	xor	esi,ebx
+	add	ecx,edx
+	movdqa	xmm9,xmm10
+	ror	ebp,7
+	add	ecx,esi
+	psrld	xmm10,30
+	por	xmm4,xmm8
+	add	ebx,DWORD PTR[12+rsp]
+	xor	ebp,eax
+	mov	esi,ecx
+	rol	ecx,5
+	pslld	xmm9,2
+	pxor	xmm4,xmm10
+	and	edi,ebp
+	xor	ebp,eax
+	movdqa	xmm10,XMMWORD PTR[r11]
+	xor	edi,eax
+	add	ebx,ecx
+	pxor	xmm4,xmm9
+	ror	edx,7
+	add	ebx,edi
+	movdqa	xmm5,xmm2
+	add	eax,DWORD PTR[16+rsp]
+	xor	edx,ebp
+	movdqa	xmm9,xmm4
+DB	102,15,58,15,233,8
+	mov	edi,ebx
+	rol	ebx,5
+	paddd	xmm10,xmm4
+	and	esi,edx
+	xor	edx,ebp
+	psrldq	xmm9,4
+	xor	esi,ebp
+	add	eax,ebx
+	pxor	xmm5,xmm1
+	ror	ecx,7
+	add	eax,esi
+	pxor	xmm9,xmm3
+	add	ebp,DWORD PTR[20+rsp]
+	xor	ecx,edx
+	mov	esi,eax
+	rol	eax,5
+	pxor	xmm5,xmm9
+	and	edi,ecx
+	xor	ecx,edx
+	movdqa	XMMWORD PTR[rsp],xmm10
+	xor	edi,edx
+	add	ebp,eax
+	movdqa	xmm8,xmm5
+	movdqa	xmm9,xmm5
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[24+rsp]
+	xor	ebx,ecx
+	pslldq	xmm8,12
+	paddd	xmm5,xmm5
+	mov	edi,ebp
+	rol	ebp,5
+	and	esi,ebx
+	xor	ebx,ecx
+	psrld	xmm9,31
+	xor	esi,ecx
+	add	edx,ebp
+	movdqa	xmm10,xmm8
+	ror	eax,7
+	add	edx,esi
+	psrld	xmm8,30
+	por	xmm5,xmm9
+	add	ecx,DWORD PTR[28+rsp]
+	xor	eax,ebx
+	mov	esi,edx
+	rol	edx,5
+	pslld	xmm10,2
+	pxor	xmm5,xmm8
+	and	edi,eax
+	xor	eax,ebx
+	movdqa	xmm8,XMMWORD PTR[16+r11]
+	xor	edi,ebx
+	add	ecx,edx
+	pxor	xmm5,xmm10
+	ror	ebp,7
+	add	ecx,edi
+	movdqa	xmm6,xmm3
+	add	ebx,DWORD PTR[32+rsp]
+	xor	ebp,eax
+	movdqa	xmm10,xmm5
+DB	102,15,58,15,242,8
+	mov	edi,ecx
+	rol	ecx,5
+	paddd	xmm8,xmm5
+	and	esi,ebp
+	xor	ebp,eax
+	psrldq	xmm10,4
+	xor	esi,eax
+	add	ebx,ecx
+	pxor	xmm6,xmm2
+	ror	edx,7
+	add	ebx,esi
+	pxor	xmm10,xmm4
+	add	eax,DWORD PTR[36+rsp]
+	xor	edx,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	pxor	xmm6,xmm10
+	and	edi,edx
+	xor	edx,ebp
+	movdqa	XMMWORD PTR[16+rsp],xmm8
+	xor	edi,ebp
+	add	eax,ebx
+	movdqa	xmm9,xmm6
+	movdqa	xmm10,xmm6
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[40+rsp]
+	xor	ecx,edx
+	pslldq	xmm9,12
+	paddd	xmm6,xmm6
+	mov	edi,eax
+	rol	eax,5
+	and	esi,ecx
+	xor	ecx,edx
+	psrld	xmm10,31
+	xor	esi,edx
+	add	ebp,eax
+	movdqa	xmm8,xmm9
+	ror	ebx,7
+	add	ebp,esi
+	psrld	xmm9,30
+	por	xmm6,xmm10
+	add	edx,DWORD PTR[44+rsp]
+	xor	ebx,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	pslld	xmm8,2
+	pxor	xmm6,xmm9
+	and	edi,ebx
+	xor	ebx,ecx
+	movdqa	xmm9,XMMWORD PTR[16+r11]
+	xor	edi,ecx
+	add	edx,ebp
+	pxor	xmm6,xmm8
+	ror	eax,7
+	add	edx,edi
+	movdqa	xmm7,xmm4
+	add	ecx,DWORD PTR[48+rsp]
+	xor	eax,ebx
+	movdqa	xmm8,xmm6
+DB	102,15,58,15,251,8
+	mov	edi,edx
+	rol	edx,5
+	paddd	xmm9,xmm6
+	and	esi,eax
+	xor	eax,ebx
+	psrldq	xmm8,4
+	xor	esi,ebx
+	add	ecx,edx
+	pxor	xmm7,xmm3
+	ror	ebp,7
+	add	ecx,esi
+	pxor	xmm8,xmm5
+	add	ebx,DWORD PTR[52+rsp]
+	xor	ebp,eax
+	mov	esi,ecx
+	rol	ecx,5
+	pxor	xmm7,xmm8
+	and	edi,ebp
+	xor	ebp,eax
+	movdqa	XMMWORD PTR[32+rsp],xmm9
+	xor	edi,eax
+	add	ebx,ecx
+	movdqa	xmm10,xmm7
+	movdqa	xmm8,xmm7
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[56+rsp]
+	xor	edx,ebp
+	pslldq	xmm10,12
+	paddd	xmm7,xmm7
+	mov	edi,ebx
+	rol	ebx,5
+	and	esi,edx
+	xor	edx,ebp
+	psrld	xmm8,31
+	xor	esi,ebp
+	add	eax,ebx
+	movdqa	xmm9,xmm10
+	ror	ecx,7
+	add	eax,esi
+	psrld	xmm10,30
+	por	xmm7,xmm8
+	add	ebp,DWORD PTR[60+rsp]
+	xor	ecx,edx
+	mov	esi,eax
+	rol	eax,5
+	pslld	xmm9,2
+	pxor	xmm7,xmm10
+	and	edi,ecx
+	xor	ecx,edx
+	movdqa	xmm10,XMMWORD PTR[16+r11]
+	xor	edi,edx
+	add	ebp,eax
+	pxor	xmm7,xmm9
+	ror	ebx,7
+	add	ebp,edi
+	movdqa	xmm9,xmm7
+	add	edx,DWORD PTR[rsp]
+	pxor	xmm0,xmm4
+DB	102,68,15,58,15,206,8
+	xor	ebx,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	pxor	xmm0,xmm1
+	and	esi,ebx
+	xor	ebx,ecx
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm7
+	xor	esi,ecx
+	add	edx,ebp
+	pxor	xmm0,xmm9
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[4+rsp]
+	xor	eax,ebx
+	movdqa	xmm9,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm10
+	mov	esi,edx
+	rol	edx,5
+	and	edi,eax
+	xor	eax,ebx
+	pslld	xmm0,2
+	xor	edi,ebx
+	add	ecx,edx
+	psrld	xmm9,30
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[8+rsp]
+	xor	ebp,eax
+	mov	edi,ecx
+	rol	ecx,5
+	por	xmm0,xmm9
+	and	esi,ebp
+	xor	ebp,eax
+	movdqa	xmm10,xmm0
+	xor	esi,eax
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[12+rsp]
+	xor	edx,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	and	edi,edx
+	xor	edx,ebp
+	xor	edi,ebp
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[16+rsp]
+	pxor	xmm1,xmm5
+DB	102,68,15,58,15,215,8
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	pxor	xmm1,xmm2
+	xor	esi,ecx
+	add	ebp,eax
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm0
+	ror	ebx,7
+	add	ebp,esi
+	pxor	xmm1,xmm10
+	add	edx,DWORD PTR[20+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	movdqa	xmm10,xmm1
+	movdqa	XMMWORD PTR[rsp],xmm8
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	pslld	xmm1,2
+	add	ecx,DWORD PTR[24+rsp]
+	xor	esi,ebx
+	psrld	xmm10,30
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	por	xmm1,xmm10
+	add	ebx,DWORD PTR[28+rsp]
+	xor	edi,eax
+	movdqa	xmm8,xmm1
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[32+rsp]
+	pxor	xmm2,xmm6
+DB	102,68,15,58,15,192,8
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	pxor	xmm2,xmm3
+	xor	esi,edx
+	add	eax,ebx
+	movdqa	xmm10,XMMWORD PTR[32+r11]
+	paddd	xmm9,xmm1
+	ror	ecx,7
+	add	eax,esi
+	pxor	xmm2,xmm8
+	add	ebp,DWORD PTR[36+rsp]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	movdqa	xmm8,xmm2
+	movdqa	XMMWORD PTR[16+rsp],xmm9
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	pslld	xmm2,2
+	add	edx,DWORD PTR[40+rsp]
+	xor	esi,ecx
+	psrld	xmm8,30
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	por	xmm2,xmm8
+	add	ecx,DWORD PTR[44+rsp]
+	xor	edi,ebx
+	movdqa	xmm9,xmm2
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[48+rsp]
+	pxor	xmm3,xmm7
+DB	102,68,15,58,15,201,8
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	pxor	xmm3,xmm4
+	xor	esi,ebp
+	add	ebx,ecx
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm2
+	ror	edx,7
+	add	ebx,esi
+	pxor	xmm3,xmm9
+	add	eax,DWORD PTR[52+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	movdqa	xmm9,xmm3
+	movdqa	XMMWORD PTR[32+rsp],xmm10
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	pslld	xmm3,2
+	add	ebp,DWORD PTR[56+rsp]
+	xor	esi,edx
+	psrld	xmm9,30
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	por	xmm3,xmm9
+	add	edx,DWORD PTR[60+rsp]
+	xor	edi,ecx
+	movdqa	xmm10,xmm3
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[rsp]
+	pxor	xmm4,xmm0
+DB	102,68,15,58,15,210,8
+	xor	esi,ebx
+	mov	edi,edx
+	rol	edx,5
+	pxor	xmm4,xmm5
+	xor	esi,eax
+	add	ecx,edx
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm3
+	ror	ebp,7
+	add	ecx,esi
+	pxor	xmm4,xmm10
+	add	ebx,DWORD PTR[4+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	movdqa	xmm10,xmm4
+	movdqa	XMMWORD PTR[48+rsp],xmm8
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	pslld	xmm4,2
+	add	eax,DWORD PTR[8+rsp]
+	xor	esi,ebp
+	psrld	xmm10,30
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	por	xmm4,xmm10
+	add	ebp,DWORD PTR[12+rsp]
+	xor	edi,edx
+	movdqa	xmm8,xmm4
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[16+rsp]
+	pxor	xmm5,xmm1
+DB	102,68,15,58,15,195,8
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	pxor	xmm5,xmm6
+	xor	esi,ebx
+	add	edx,ebp
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm4
+	ror	eax,7
+	add	edx,esi
+	pxor	xmm5,xmm8
+	add	ecx,DWORD PTR[20+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	movdqa	xmm8,xmm5
+	movdqa	XMMWORD PTR[rsp],xmm9
+	xor	edi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	pslld	xmm5,2
+	add	ebx,DWORD PTR[24+rsp]
+	xor	esi,eax
+	psrld	xmm8,30
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	por	xmm5,xmm8
+	add	eax,DWORD PTR[28+rsp]
+	xor	edi,ebp
+	movdqa	xmm9,xmm5
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	mov	edi,ecx
+	pxor	xmm6,xmm2
+DB	102,68,15,58,15,204,8
+	xor	ecx,edx
+	add	ebp,DWORD PTR[32+rsp]
+	and	edi,edx
+	pxor	xmm6,xmm7
+	and	esi,ecx
+	ror	ebx,7
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm5
+	add	ebp,edi
+	mov	edi,eax
+	pxor	xmm6,xmm9
+	rol	eax,5
+	add	ebp,esi
+	xor	ecx,edx
+	add	ebp,eax
+	movdqa	xmm9,xmm6
+	movdqa	XMMWORD PTR[16+rsp],xmm10
+	mov	esi,ebx
+	xor	ebx,ecx
+	add	edx,DWORD PTR[36+rsp]
+	and	esi,ecx
+	pslld	xmm6,2
+	and	edi,ebx
+	ror	eax,7
+	psrld	xmm9,30
+	add	edx,esi
+	mov	esi,ebp
+	rol	ebp,5
+	add	edx,edi
+	xor	ebx,ecx
+	add	edx,ebp
+	por	xmm6,xmm9
+	mov	edi,eax
+	xor	eax,ebx
+	movdqa	xmm10,xmm6
+	add	ecx,DWORD PTR[40+rsp]
+	and	edi,ebx
+	and	esi,eax
+	ror	ebp,7
+	add	ecx,edi
+	mov	edi,edx
+	rol	edx,5
+	add	ecx,esi
+	xor	eax,ebx
+	add	ecx,edx
+	mov	esi,ebp
+	xor	ebp,eax
+	add	ebx,DWORD PTR[44+rsp]
+	and	esi,eax
+	and	edi,ebp
+	ror	edx,7
+	add	ebx,esi
+	mov	esi,ecx
+	rol	ecx,5
+	add	ebx,edi
+	xor	ebp,eax
+	add	ebx,ecx
+	mov	edi,edx
+	pxor	xmm7,xmm3
+DB	102,68,15,58,15,213,8
+	xor	edx,ebp
+	add	eax,DWORD PTR[48+rsp]
+	and	edi,ebp
+	pxor	xmm7,xmm0
+	and	esi,edx
+	ror	ecx,7
+	movdqa	xmm9,XMMWORD PTR[48+r11]
+	paddd	xmm8,xmm6
+	add	eax,edi
+	mov	edi,ebx
+	pxor	xmm7,xmm10
+	rol	ebx,5
+	add	eax,esi
+	xor	edx,ebp
+	add	eax,ebx
+	movdqa	xmm10,xmm7
+	movdqa	XMMWORD PTR[32+rsp],xmm8
+	mov	esi,ecx
+	xor	ecx,edx
+	add	ebp,DWORD PTR[52+rsp]
+	and	esi,edx
+	pslld	xmm7,2
+	and	edi,ecx
+	ror	ebx,7
+	psrld	xmm10,30
+	add	ebp,esi
+	mov	esi,eax
+	rol	eax,5
+	add	ebp,edi
+	xor	ecx,edx
+	add	ebp,eax
+	por	xmm7,xmm10
+	mov	edi,ebx
+	xor	ebx,ecx
+	movdqa	xmm8,xmm7
+	add	edx,DWORD PTR[56+rsp]
+	and	edi,ecx
+	and	esi,ebx
+	ror	eax,7
+	add	edx,edi
+	mov	edi,ebp
+	rol	ebp,5
+	add	edx,esi
+	xor	ebx,ecx
+	add	edx,ebp
+	mov	esi,eax
+	xor	eax,ebx
+	add	ecx,DWORD PTR[60+rsp]
+	and	esi,ebx
+	and	edi,eax
+	ror	ebp,7
+	add	ecx,esi
+	mov	esi,edx
+	rol	edx,5
+	add	ecx,edi
+	xor	eax,ebx
+	add	ecx,edx
+	mov	edi,ebp
+	pxor	xmm0,xmm4
+DB	102,68,15,58,15,198,8
+	xor	ebp,eax
+	add	ebx,DWORD PTR[rsp]
+	and	edi,eax
+	pxor	xmm0,xmm1
+	and	esi,ebp
+	ror	edx,7
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm7
+	add	ebx,edi
+	mov	edi,ecx
+	pxor	xmm0,xmm8
+	rol	ecx,5
+	add	ebx,esi
+	xor	ebp,eax
+	add	ebx,ecx
+	movdqa	xmm8,xmm0
+	movdqa	XMMWORD PTR[48+rsp],xmm9
+	mov	esi,edx
+	xor	edx,ebp
+	add	eax,DWORD PTR[4+rsp]
+	and	esi,ebp
+	pslld	xmm0,2
+	and	edi,edx
+	ror	ecx,7
+	psrld	xmm8,30
+	add	eax,esi
+	mov	esi,ebx
+	rol	ebx,5
+	add	eax,edi
+	xor	edx,ebp
+	add	eax,ebx
+	por	xmm0,xmm8
+	mov	edi,ecx
+	xor	ecx,edx
+	movdqa	xmm9,xmm0
+	add	ebp,DWORD PTR[8+rsp]
+	and	edi,edx
+	and	esi,ecx
+	ror	ebx,7
+	add	ebp,edi
+	mov	edi,eax
+	rol	eax,5
+	add	ebp,esi
+	xor	ecx,edx
+	add	ebp,eax
+	mov	esi,ebx
+	xor	ebx,ecx
+	add	edx,DWORD PTR[12+rsp]
+	and	esi,ecx
+	and	edi,ebx
+	ror	eax,7
+	add	edx,esi
+	mov	esi,ebp
+	rol	ebp,5
+	add	edx,edi
+	xor	ebx,ecx
+	add	edx,ebp
+	mov	edi,eax
+	pxor	xmm1,xmm5
+DB	102,68,15,58,15,207,8
+	xor	eax,ebx
+	add	ecx,DWORD PTR[16+rsp]
+	and	edi,ebx
+	pxor	xmm1,xmm2
+	and	esi,eax
+	ror	ebp,7
+	movdqa	xmm8,xmm10
+	paddd	xmm10,xmm0
+	add	ecx,edi
+	mov	edi,edx
+	pxor	xmm1,xmm9
+	rol	edx,5
+	add	ecx,esi
+	xor	eax,ebx
+	add	ecx,edx
+	movdqa	xmm9,xmm1
+	movdqa	XMMWORD PTR[rsp],xmm10
+	mov	esi,ebp
+	xor	ebp,eax
+	add	ebx,DWORD PTR[20+rsp]
+	and	esi,eax
+	pslld	xmm1,2
+	and	edi,ebp
+	ror	edx,7
+	psrld	xmm9,30
+	add	ebx,esi
+	mov	esi,ecx
+	rol	ecx,5
+	add	ebx,edi
+	xor	ebp,eax
+	add	ebx,ecx
+	por	xmm1,xmm9
+	mov	edi,edx
+	xor	edx,ebp
+	movdqa	xmm10,xmm1
+	add	eax,DWORD PTR[24+rsp]
+	and	edi,ebp
+	and	esi,edx
+	ror	ecx,7
+	add	eax,edi
+	mov	edi,ebx
+	rol	ebx,5
+	add	eax,esi
+	xor	edx,ebp
+	add	eax,ebx
+	mov	esi,ecx
+	xor	ecx,edx
+	add	ebp,DWORD PTR[28+rsp]
+	and	esi,edx
+	and	edi,ecx
+	ror	ebx,7
+	add	ebp,esi
+	mov	esi,eax
+	rol	eax,5
+	add	ebp,edi
+	xor	ecx,edx
+	add	ebp,eax
+	mov	edi,ebx
+	pxor	xmm2,xmm6
+DB	102,68,15,58,15,208,8
+	xor	ebx,ecx
+	add	edx,DWORD PTR[32+rsp]
+	and	edi,ecx
+	pxor	xmm2,xmm3
+	and	esi,ebx
+	ror	eax,7
+	movdqa	xmm9,xmm8
+	paddd	xmm8,xmm1
+	add	edx,edi
+	mov	edi,ebp
+	pxor	xmm2,xmm10
+	rol	ebp,5
+	add	edx,esi
+	xor	ebx,ecx
+	add	edx,ebp
+	movdqa	xmm10,xmm2
+	movdqa	XMMWORD PTR[16+rsp],xmm8
+	mov	esi,eax
+	xor	eax,ebx
+	add	ecx,DWORD PTR[36+rsp]
+	and	esi,ebx
+	pslld	xmm2,2
+	and	edi,eax
+	ror	ebp,7
+	psrld	xmm10,30
+	add	ecx,esi
+	mov	esi,edx
+	rol	edx,5
+	add	ecx,edi
+	xor	eax,ebx
+	add	ecx,edx
+	por	xmm2,xmm10
+	mov	edi,ebp
+	xor	ebp,eax
+	movdqa	xmm8,xmm2
+	add	ebx,DWORD PTR[40+rsp]
+	and	edi,eax
+	and	esi,ebp
+	ror	edx,7
+	add	ebx,edi
+	mov	edi,ecx
+	rol	ecx,5
+	add	ebx,esi
+	xor	ebp,eax
+	add	ebx,ecx
+	mov	esi,edx
+	xor	edx,ebp
+	add	eax,DWORD PTR[44+rsp]
+	and	esi,ebp
+	and	edi,edx
+	ror	ecx,7
+	add	eax,esi
+	mov	esi,ebx
+	rol	ebx,5
+	add	eax,edi
+	xor	edx,ebp
+	add	eax,ebx
+	add	ebp,DWORD PTR[48+rsp]
+	pxor	xmm3,xmm7
+DB	102,68,15,58,15,193,8
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	pxor	xmm3,xmm4
+	xor	esi,ecx
+	add	ebp,eax
+	movdqa	xmm10,xmm9
+	paddd	xmm9,xmm2
+	ror	ebx,7
+	add	ebp,esi
+	pxor	xmm3,xmm8
+	add	edx,DWORD PTR[52+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	movdqa	xmm8,xmm3
+	movdqa	XMMWORD PTR[32+rsp],xmm9
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	pslld	xmm3,2
+	add	ecx,DWORD PTR[56+rsp]
+	xor	esi,ebx
+	psrld	xmm8,30
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	por	xmm3,xmm8
+	add	ebx,DWORD PTR[60+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[rsp]
+	paddd	xmm10,xmm3
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	movdqa	XMMWORD PTR[48+rsp],xmm10
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[4+rsp]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[8+rsp]
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[12+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	cmp	r9,r10
+	je	$L$done_ssse3
+	movdqa	xmm6,XMMWORD PTR[64+r11]
+	movdqa	xmm9,XMMWORD PTR[r11]
+	movdqu	xmm0,XMMWORD PTR[r9]
+	movdqu	xmm1,XMMWORD PTR[16+r9]
+	movdqu	xmm2,XMMWORD PTR[32+r9]
+	movdqu	xmm3,XMMWORD PTR[48+r9]
+DB	102,15,56,0,198
+	add	r9,64
+	add	ebx,DWORD PTR[16+rsp]
+	xor	esi,eax
+DB	102,15,56,0,206
+	mov	edi,ecx
+	rol	ecx,5
+	paddd	xmm0,xmm9
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	movdqa	XMMWORD PTR[rsp],xmm0
+	add	eax,DWORD PTR[20+rsp]
+	xor	edi,ebp
+	psubd	xmm0,xmm9
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[24+rsp]
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	add	edx,DWORD PTR[28+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[32+rsp]
+	xor	esi,ebx
+DB	102,15,56,0,214
+	mov	edi,edx
+	rol	edx,5
+	paddd	xmm1,xmm9
+	xor	esi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	movdqa	XMMWORD PTR[16+rsp],xmm1
+	add	ebx,DWORD PTR[36+rsp]
+	xor	edi,eax
+	psubd	xmm1,xmm9
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[40+rsp]
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[44+rsp]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[48+rsp]
+	xor	esi,ecx
+DB	102,15,56,0,222
+	mov	edi,ebp
+	rol	ebp,5
+	paddd	xmm2,xmm9
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	movdqa	XMMWORD PTR[32+rsp],xmm2
+	add	ecx,DWORD PTR[52+rsp]
+	xor	edi,ebx
+	psubd	xmm2,xmm9
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[56+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[60+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	eax,DWORD PTR[r8]
+	add	esi,DWORD PTR[4+r8]
+	add	ecx,DWORD PTR[8+r8]
+	add	edx,DWORD PTR[12+r8]
+	mov	DWORD PTR[r8],eax
+	add	ebp,DWORD PTR[16+r8]
+	mov	DWORD PTR[4+r8],esi
+	mov	ebx,esi
+	mov	DWORD PTR[8+r8],ecx
+	mov	DWORD PTR[12+r8],edx
+	mov	DWORD PTR[16+r8],ebp
+	jmp	$L$oop_ssse3
+
+ALIGN	16
+$L$done_ssse3::
+	add	ebx,DWORD PTR[16+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[20+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	ebp,DWORD PTR[24+rsp]
+	xor	esi,edx
+	mov	edi,eax
+	rol	eax,5
+	xor	esi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,esi
+	add	edx,DWORD PTR[28+rsp]
+	xor	edi,ecx
+	mov	esi,ebp
+	rol	ebp,5
+	xor	edi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,edi
+	add	ecx,DWORD PTR[32+rsp]
+	xor	esi,ebx
+	mov	edi,edx
+	rol	edx,5
+	xor	esi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,esi
+	add	ebx,DWORD PTR[36+rsp]
+	xor	edi,eax
+	mov	esi,ecx
+	rol	ecx,5
+	xor	edi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,edi
+	add	eax,DWORD PTR[40+rsp]
+	xor	esi,ebp
+	mov	edi,ebx
+	rol	ebx,5
+	xor	esi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,esi
+	add	ebp,DWORD PTR[44+rsp]
+	xor	edi,edx
+	mov	esi,eax
+	rol	eax,5
+	xor	edi,ecx
+	add	ebp,eax
+	ror	ebx,7
+	add	ebp,edi
+	add	edx,DWORD PTR[48+rsp]
+	xor	esi,ecx
+	mov	edi,ebp
+	rol	ebp,5
+	xor	esi,ebx
+	add	edx,ebp
+	ror	eax,7
+	add	edx,esi
+	add	ecx,DWORD PTR[52+rsp]
+	xor	edi,ebx
+	mov	esi,edx
+	rol	edx,5
+	xor	edi,eax
+	add	ecx,edx
+	ror	ebp,7
+	add	ecx,edi
+	add	ebx,DWORD PTR[56+rsp]
+	xor	esi,eax
+	mov	edi,ecx
+	rol	ecx,5
+	xor	esi,ebp
+	add	ebx,ecx
+	ror	edx,7
+	add	ebx,esi
+	add	eax,DWORD PTR[60+rsp]
+	xor	edi,ebp
+	mov	esi,ebx
+	rol	ebx,5
+	xor	edi,edx
+	add	eax,ebx
+	ror	ecx,7
+	add	eax,edi
+	add	eax,DWORD PTR[r8]
+	add	esi,DWORD PTR[4+r8]
+	add	ecx,DWORD PTR[8+r8]
+	mov	DWORD PTR[r8],eax
+	add	edx,DWORD PTR[12+r8]
+	mov	DWORD PTR[4+r8],esi
+	add	ebp,DWORD PTR[16+r8]
+	mov	DWORD PTR[8+r8],ecx
+	mov	DWORD PTR[12+r8],edx
+	mov	DWORD PTR[16+r8],ebp
+	movaps	xmm6,XMMWORD PTR[((64+0))+rsp]
+	movaps	xmm7,XMMWORD PTR[((64+16))+rsp]
+	movaps	xmm8,XMMWORD PTR[((64+32))+rsp]
+	movaps	xmm9,XMMWORD PTR[((64+48))+rsp]
+	movaps	xmm10,XMMWORD PTR[((64+64))+rsp]
+	lea	rsi,QWORD PTR[144+rsp]
+	mov	r12,QWORD PTR[rsi]
+	mov	rbp,QWORD PTR[8+rsi]
+	mov	rbx,QWORD PTR[16+rsi]
+	lea	rsp,QWORD PTR[24+rsi]
+$L$epilogue_ssse3::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_sha1_block_data_order_ssse3::
+sha1_block_data_order_ssse3	ENDP
+ALIGN	64
+K_XX_XX::
+	DD	05a827999h,05a827999h,05a827999h,05a827999h	
+	DD	06ed9eba1h,06ed9eba1h,06ed9eba1h,06ed9eba1h	
+	DD	08f1bbcdch,08f1bbcdch,08f1bbcdch,08f1bbcdch	
+	DD	0ca62c1d6h,0ca62c1d6h,0ca62c1d6h,0ca62c1d6h	
+	DD	000010203h,004050607h,008090a0bh,00c0d0e0fh	
+DB	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115
+DB	102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44
+DB	32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60
+DB	97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114
+DB	103,62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind:NEAR
+
+ALIGN	16
+se_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	lea	r10,QWORD PTR[$L$prologue]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	lea	r10,QWORD PTR[$L$epilogue]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[64+rax]
+	lea	rax,QWORD PTR[32+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	r13,QWORD PTR[((-32))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+	mov	QWORD PTR[224+r8],r13
+
+	jmp	$L$common_seh_tail
+se_handler	ENDP
+
+
+ALIGN	16
+ssse3_handler	PROC PRIVATE
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD PTR[120+r8]
+	mov	rbx,QWORD PTR[248+r8]
+
+	mov	rsi,QWORD PTR[8+r9]
+	mov	r11,QWORD PTR[56+r9]
+
+	mov	r10d,DWORD PTR[r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jb	$L$common_seh_tail
+
+	mov	rax,QWORD PTR[152+r8]
+
+	mov	r10d,DWORD PTR[4+r11]
+	lea	r10,QWORD PTR[r10*1+rsi]
+	cmp	rbx,r10
+	jae	$L$common_seh_tail
+
+	lea	rsi,QWORD PTR[64+rax]
+	lea	rdi,QWORD PTR[512+r8]
+	mov	ecx,10
+	DD	0a548f3fch		
+	lea	rax,QWORD PTR[168+rax]
+
+	mov	rbx,QWORD PTR[((-8))+rax]
+	mov	rbp,QWORD PTR[((-16))+rax]
+	mov	r12,QWORD PTR[((-24))+rax]
+	mov	QWORD PTR[144+r8],rbx
+	mov	QWORD PTR[160+r8],rbp
+	mov	QWORD PTR[216+r8],r12
+
+$L$common_seh_tail::
+	mov	rdi,QWORD PTR[8+rax]
+	mov	rsi,QWORD PTR[16+rax]
+	mov	QWORD PTR[152+r8],rax
+	mov	QWORD PTR[168+r8],rsi
+	mov	QWORD PTR[176+r8],rdi
+
+	mov	rdi,QWORD PTR[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0a548f3fch		
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD PTR[8+rsi]
+	mov	r8,QWORD PTR[rsi]
+	mov	r9,QWORD PTR[16+rsi]
+	mov	r10,QWORD PTR[40+rsi]
+	lea	r11,QWORD PTR[56+rsi]
+	lea	r12,QWORD PTR[24+rsi]
+	mov	QWORD PTR[32+rsp],r10
+	mov	QWORD PTR[40+rsp],r11
+	mov	QWORD PTR[48+rsp],r12
+	mov	QWORD PTR[56+rsp],rcx
+	call	QWORD PTR[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+ssse3_handler	ENDP
+
+.text$	ENDS
+.pdata	SEGMENT READONLY ALIGN(4)
+ALIGN	4
+	DD	imagerel $L$SEH_begin_sha1_block_data_order
+	DD	imagerel $L$SEH_end_sha1_block_data_order
+	DD	imagerel $L$SEH_info_sha1_block_data_order
+	DD	imagerel $L$SEH_begin_sha1_block_data_order_ssse3
+	DD	imagerel $L$SEH_end_sha1_block_data_order_ssse3
+	DD	imagerel $L$SEH_info_sha1_block_data_order_ssse3
+.pdata	ENDS
+.xdata	SEGMENT READONLY ALIGN(8)
+ALIGN	8
+$L$SEH_info_sha1_block_data_order::
+DB	9,0,0,0
+	DD	imagerel se_handler
+$L$SEH_info_sha1_block_data_order_ssse3::
+DB	9,0,0,0
+	DD	imagerel ssse3_handler
+	DD	imagerel $L$prologue_ssse3,imagerel $L$epilogue_ssse3	
+
+.xdata	ENDS
+END
+
diff --git a/crypto/sha/sha1-mingw64-x86_64.S b/crypto/sha/sha1-mingw64-x86_64.S
new file mode 100644
index 0000000..3ce9fc9
--- /dev/null
+++ b/crypto/sha/sha1-mingw64-x86_64.S
@@ -0,0 +1,2664 @@
+#include "x86_arch.h"
+.text	
+
+
+
+.globl	sha1_block_data_order
+.def	sha1_block_data_order;	.scl 2;	.type 32;	.endef
+.p2align	4
+sha1_block_data_order:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_sha1_block_data_order:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	movl	OPENSSL_ia32cap_P+0(%rip),%r9d
+	movl	OPENSSL_ia32cap_P+4(%rip),%r8d
+	testl	$IA32CAP_MASK1_SSSE3,%r8d
+	jz	.Lialu
+	jmp	_ssse3_shortcut
+
+.p2align	4
+.Lialu:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	movq	%rsp,%r11
+	movq	%rdi,%r8
+	subq	$72,%rsp
+	movq	%rsi,%r9
+	andq	$-64,%rsp
+	movq	%rdx,%r10
+	movq	%r11,64(%rsp)
+.Lprologue:
+
+	movl	0(%r8),%esi
+	movl	4(%r8),%edi
+	movl	8(%r8),%r11d
+	movl	12(%r8),%r12d
+	movl	16(%r8),%r13d
+	jmp	.Lloop
+
+.p2align	4
+.Lloop:
+	movl	0(%r9),%edx
+	bswapl	%edx
+	movl	%edx,0(%rsp)
+	movl	%r11d,%eax
+	movl	4(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	8(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,8(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	12(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	16(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,16(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	20(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	24(%r9),%edx
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%edx,24(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	28(%r9),%ebp
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	32(%r9),%edx
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	36(%r9),%ebp
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	40(%r9),%edx
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%edx,40(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	%r11d,%eax
+	movl	44(%r9),%ebp
+	movl	%esi,%ecx
+	xorl	%r12d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r13,1),%r13d
+	andl	%edi,%eax
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r13d
+	xorl	%r12d,%eax
+	roll	$30,%edi
+	addl	%eax,%r13d
+	movl	%edi,%eax
+	movl	48(%r9),%edx
+	movl	%r13d,%ecx
+	xorl	%r11d,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%r12,1),%r12d
+	andl	%esi,%eax
+	movl	%edx,48(%rsp)
+	addl	%ecx,%r12d
+	xorl	%r11d,%eax
+	roll	$30,%esi
+	addl	%eax,%r12d
+	movl	%esi,%eax
+	movl	52(%r9),%ebp
+	movl	%r12d,%ecx
+	xorl	%edi,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%r11,1),%r11d
+	andl	%r13d,%eax
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%r11d
+	xorl	%edi,%eax
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	movl	%r13d,%eax
+	movl	56(%r9),%edx
+	movl	%r11d,%ecx
+	xorl	%esi,%eax
+	bswapl	%edx
+	roll	$5,%ecx
+	leal	1518500249(%rbp,%rdi,1),%edi
+	andl	%r12d,%eax
+	movl	%edx,56(%rsp)
+	addl	%ecx,%edi
+	xorl	%esi,%eax
+	roll	$30,%r12d
+	addl	%eax,%edi
+	movl	%r12d,%eax
+	movl	60(%r9),%ebp
+	movl	%edi,%ecx
+	xorl	%r13d,%eax
+	bswapl	%ebp
+	roll	$5,%ecx
+	leal	1518500249(%rdx,%rsi,1),%esi
+	andl	%r11d,%eax
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%esi
+	xorl	%r13d,%eax
+	roll	$30,%r11d
+	addl	%eax,%esi
+	movl	0(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	xorl	32(%rsp),%edx
+	andl	%edi,%eax
+	leal	1518500249(%rbp,%r13,1),%r13d
+	xorl	52(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$1,%edx
+	addl	%ecx,%r13d
+	roll	$30,%edi
+	movl	%edx,0(%rsp)
+	addl	%eax,%r13d
+	movl	4(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	xorl	36(%rsp),%ebp
+	andl	%esi,%eax
+	leal	1518500249(%rdx,%r12,1),%r12d
+	xorl	56(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$1,%ebp
+	addl	%ecx,%r12d
+	roll	$30,%esi
+	movl	%ebp,4(%rsp)
+	addl	%eax,%r12d
+	movl	8(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	xorl	40(%rsp),%edx
+	andl	%r13d,%eax
+	leal	1518500249(%rbp,%r11,1),%r11d
+	xorl	60(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$1,%edx
+	addl	%ecx,%r11d
+	roll	$30,%r13d
+	movl	%edx,8(%rsp)
+	addl	%eax,%r11d
+	movl	12(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	leal	1518500249(%rdx,%rdi,1),%edi
+	xorl	0(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$1,%ebp
+	addl	%ecx,%edi
+	roll	$30,%r12d
+	movl	%ebp,12(%rsp)
+	addl	%eax,%edi
+	movl	16(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	leal	1518500249(%rbp,%rsi,1),%esi
+	xorl	4(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$1,%edx
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	movl	%edx,16(%rsp)
+	addl	%eax,%esi
+	movl	20(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	52(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	8(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	56(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	12(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	16(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	20(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	24(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	28(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	32(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	36(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	40(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	44(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r13,1),%r13d
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	48(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r12,1),%r12d
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	52(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r11,1),%r11d
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	56(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rdi,1),%edi
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	60(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rsi,1),%esi
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	0(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r13,1),%r13d
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	4(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%r12,1),%r12d
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	8(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%r11,1),%r11d
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	12(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rdx,%rdi,1),%edi
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	16(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	1859775393(%rbp,%rsi,1),%esi
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	20(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r13d
+	movl	40(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r12d
+	movl	44(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%r11d
+	movl	48(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%edi
+	movl	52(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	60(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	40(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,52(%rsp)
+	addl	%ecx,%esi
+	movl	56(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	0(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	44(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,56(%rsp)
+	addl	%ecx,%r13d
+	movl	60(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	4(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	48(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,60(%rsp)
+	addl	%ecx,%r12d
+	movl	0(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	8(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	52(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,0(%rsp)
+	addl	%ecx,%r11d
+	movl	4(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	12(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	56(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,4(%rsp)
+	addl	%ecx,%edi
+	movl	8(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	16(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	60(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,8(%rsp)
+	addl	%ecx,%esi
+	movl	12(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	20(%rsp),%ebp
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rdx,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	0(%rsp),%ebp
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%ebp,12(%rsp)
+	addl	%ecx,%r13d
+	movl	16(%rsp),%edx
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	24(%rsp),%edx
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rbp,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	4(%rsp),%edx
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%edx,16(%rsp)
+	addl	%ecx,%r12d
+	movl	20(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	28(%rsp),%ebp
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%edi,%ebx
+	leal	-1894007588(%rdx,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	8(%rsp),%ebp
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%ebp,20(%rsp)
+	addl	%ecx,%r11d
+	movl	24(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	32(%rsp),%edx
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%esi,%ebx
+	leal	-1894007588(%rbp,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	12(%rsp),%edx
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%edx,24(%rsp)
+	addl	%ecx,%edi
+	movl	28(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	36(%rsp),%ebp
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rdx,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	16(%rsp),%ebp
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%ebp,28(%rsp)
+	addl	%ecx,%esi
+	movl	32(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%r11d,%ebx
+	xorl	40(%rsp),%edx
+	andl	%r12d,%eax
+	movl	%esi,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r12d,%ebx
+	leal	-1894007588(%rbp,%r13,1),%r13d
+	roll	$5,%ecx
+	xorl	20(%rsp),%edx
+	addl	%eax,%r13d
+	andl	%edi,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r13d
+	roll	$30,%edi
+	movl	%edx,32(%rsp)
+	addl	%ecx,%r13d
+	movl	36(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%edi,%ebx
+	xorl	44(%rsp),%ebp
+	andl	%r11d,%eax
+	movl	%r13d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r11d,%ebx
+	leal	-1894007588(%rdx,%r12,1),%r12d
+	roll	$5,%ecx
+	xorl	24(%rsp),%ebp
+	addl	%eax,%r12d
+	andl	%esi,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%r12d
+	roll	$30,%esi
+	movl	%ebp,36(%rsp)
+	addl	%ecx,%r12d
+	movl	40(%rsp),%edx
+	movl	%esi,%eax
+	movl	%esi,%ebx
+	xorl	48(%rsp),%edx
+	andl	%edi,%eax
+	movl	%r12d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%edi,%ebx
+	leal	-1894007588(%rbp,%r11,1),%r11d
+	roll	$5,%ecx
+	xorl	28(%rsp),%edx
+	addl	%eax,%r11d
+	andl	%r13d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%r11d
+	roll	$30,%r13d
+	movl	%edx,40(%rsp)
+	addl	%ecx,%r11d
+	movl	44(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r13d,%ebx
+	xorl	52(%rsp),%ebp
+	andl	%esi,%eax
+	movl	%r11d,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%esi,%ebx
+	leal	-1894007588(%rdx,%rdi,1),%edi
+	roll	$5,%ecx
+	xorl	32(%rsp),%ebp
+	addl	%eax,%edi
+	andl	%r12d,%ebx
+	roll	$1,%ebp
+	addl	%ebx,%edi
+	roll	$30,%r12d
+	movl	%ebp,44(%rsp)
+	addl	%ecx,%edi
+	movl	48(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%r12d,%ebx
+	xorl	56(%rsp),%edx
+	andl	%r13d,%eax
+	movl	%edi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%r13d,%ebx
+	leal	-1894007588(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	36(%rsp),%edx
+	addl	%eax,%esi
+	andl	%r11d,%ebx
+	roll	$1,%edx
+	addl	%ebx,%esi
+	roll	$30,%r11d
+	movl	%edx,48(%rsp)
+	addl	%ecx,%esi
+	movl	52(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	20(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	40(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,52(%rsp)
+	movl	56(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	24(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	44(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,56(%rsp)
+	movl	60(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	28(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	48(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,60(%rsp)
+	movl	0(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	8(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	32(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	52(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,0(%rsp)
+	movl	4(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	12(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	36(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	56(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,4(%rsp)
+	movl	8(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	16(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	40(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	60(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,8(%rsp)
+	movl	12(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	20(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	44(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	0(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	%ebp,12(%rsp)
+	movl	16(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	24(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	48(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	4(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	%edx,16(%rsp)
+	movl	20(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	28(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	52(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	8(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%ebp,20(%rsp)
+	movl	24(%rsp),%edx
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	32(%rsp),%edx
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rsi,1),%esi
+	xorl	56(%rsp),%edx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	12(%rsp),%edx
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%edx
+	movl	%edx,24(%rsp)
+	movl	28(%rsp),%ebp
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	36(%rsp),%ebp
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r13,1),%r13d
+	xorl	60(%rsp),%ebp
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	16(%rsp),%ebp
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%ebp
+	movl	%ebp,28(%rsp)
+	movl	32(%rsp),%edx
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	40(%rsp),%edx
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r12,1),%r12d
+	xorl	0(%rsp),%edx
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	20(%rsp),%edx
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%edx
+	movl	%edx,32(%rsp)
+	movl	36(%rsp),%ebp
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	44(%rsp),%ebp
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r11,1),%r11d
+	xorl	4(%rsp),%ebp
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	24(%rsp),%ebp
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%ebp
+	movl	%ebp,36(%rsp)
+	movl	40(%rsp),%edx
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	48(%rsp),%edx
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%rdi,1),%edi
+	xorl	8(%rsp),%edx
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	28(%rsp),%edx
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%edx
+	movl	%edx,40(%rsp)
+	movl	44(%rsp),%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	52(%rsp),%ebp
+	xorl	%r11d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rsi,1),%esi
+	xorl	12(%rsp),%ebp
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	xorl	32(%rsp),%ebp
+	roll	$30,%r11d
+	addl	%eax,%esi
+	roll	$1,%ebp
+	movl	%ebp,44(%rsp)
+	movl	48(%rsp),%edx
+	movl	%r11d,%eax
+	movl	%esi,%ecx
+	xorl	56(%rsp),%edx
+	xorl	%edi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r13,1),%r13d
+	xorl	16(%rsp),%edx
+	xorl	%r12d,%eax
+	addl	%ecx,%r13d
+	xorl	36(%rsp),%edx
+	roll	$30,%edi
+	addl	%eax,%r13d
+	roll	$1,%edx
+	movl	%edx,48(%rsp)
+	movl	52(%rsp),%ebp
+	movl	%edi,%eax
+	movl	%r13d,%ecx
+	xorl	60(%rsp),%ebp
+	xorl	%esi,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%r12,1),%r12d
+	xorl	20(%rsp),%ebp
+	xorl	%r11d,%eax
+	addl	%ecx,%r12d
+	xorl	40(%rsp),%ebp
+	roll	$30,%esi
+	addl	%eax,%r12d
+	roll	$1,%ebp
+	movl	56(%rsp),%edx
+	movl	%esi,%eax
+	movl	%r12d,%ecx
+	xorl	0(%rsp),%edx
+	xorl	%r13d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rbp,%r11,1),%r11d
+	xorl	24(%rsp),%edx
+	xorl	%edi,%eax
+	addl	%ecx,%r11d
+	xorl	44(%rsp),%edx
+	roll	$30,%r13d
+	addl	%eax,%r11d
+	roll	$1,%edx
+	movl	60(%rsp),%ebp
+	movl	%r13d,%eax
+	movl	%r11d,%ecx
+	xorl	4(%rsp),%ebp
+	xorl	%r12d,%eax
+	roll	$5,%ecx
+	leal	-899497514(%rdx,%rdi,1),%edi
+	xorl	28(%rsp),%ebp
+	xorl	%esi,%eax
+	addl	%ecx,%edi
+	xorl	48(%rsp),%ebp
+	roll	$30,%r12d
+	addl	%eax,%edi
+	roll	$1,%ebp
+	movl	%r12d,%eax
+	movl	%edi,%ecx
+	xorl	%r11d,%eax
+	leal	-899497514(%rbp,%rsi,1),%esi
+	roll	$5,%ecx
+	xorl	%r13d,%eax
+	addl	%ecx,%esi
+	roll	$30,%r11d
+	addl	%eax,%esi
+	addl	0(%r8),%esi
+	addl	4(%r8),%edi
+	addl	8(%r8),%r11d
+	addl	12(%r8),%r12d
+	addl	16(%r8),%r13d
+	movl	%esi,0(%r8)
+	movl	%edi,4(%r8)
+	movl	%r11d,8(%r8)
+	movl	%r12d,12(%r8)
+	movl	%r13d,16(%r8)
+
+	subq	$1,%r10
+	leaq	64(%r9),%r9
+	jnz	.Lloop
+
+	movq	64(%rsp),%rsi
+	movq	(%rsi),%r13
+	movq	8(%rsi),%r12
+	movq	16(%rsi),%rbp
+	movq	24(%rsi),%rbx
+	leaq	32(%rsi),%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_sha1_block_data_order:
+.def	sha1_block_data_order_ssse3;	.scl 3;	.type 32;	.endef
+.p2align	4
+sha1_block_data_order_ssse3:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_sha1_block_data_order_ssse3:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+_ssse3_shortcut:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	leaq	-144(%rsp),%rsp
+	movaps	%xmm6,64+0(%rsp)
+	movaps	%xmm7,64+16(%rsp)
+	movaps	%xmm8,64+32(%rsp)
+	movaps	%xmm9,64+48(%rsp)
+	movaps	%xmm10,64+64(%rsp)
+.Lprologue_ssse3:
+	movq	%rdi,%r8
+	movq	%rsi,%r9
+	movq	%rdx,%r10
+
+	shlq	$6,%r10
+	addq	%r9,%r10
+	leaq	K_XX_XX(%rip),%r11
+
+	movl	0(%r8),%eax
+	movl	4(%r8),%ebx
+	movl	8(%r8),%ecx
+	movl	12(%r8),%edx
+	movl	%ebx,%esi
+	movl	16(%r8),%ebp
+
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm9,%xmm0
+	paddd	%xmm9,%xmm1
+	paddd	%xmm9,%xmm2
+	movdqa	%xmm0,0(%rsp)
+	psubd	%xmm9,%xmm0
+	movdqa	%xmm1,16(%rsp)
+	psubd	%xmm9,%xmm1
+	movdqa	%xmm2,32(%rsp)
+	psubd	%xmm9,%xmm2
+	jmp	.Loop_ssse3
+.p2align	4
+.Loop_ssse3:
+	movdqa	%xmm1,%xmm4
+	addl	0(%rsp),%ebp
+	xorl	%edx,%ecx
+	movdqa	%xmm3,%xmm8
+.byte	102,15,58,15,224,8
+	movl	%eax,%edi
+	roll	$5,%eax
+	paddd	%xmm3,%xmm9
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrldq	$4,%xmm8
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	pxor	%xmm0,%xmm4
+	rorl	$2,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm2,%xmm8
+	addl	4(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pxor	%xmm8,%xmm4
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm9,48(%rsp)
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm4,%xmm8
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	8(%rsp),%ecx
+	xorl	%ebx,%eax
+	pslldq	$12,%xmm10
+	paddd	%xmm4,%xmm4
+	movl	%edx,%edi
+	roll	$5,%edx
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrld	$31,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm4
+	addl	12(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm4
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	0(%r11),%xmm10
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	pxor	%xmm9,%xmm4
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movdqa	%xmm2,%xmm5
+	addl	16(%rsp),%eax
+	xorl	%ebp,%edx
+	movdqa	%xmm4,%xmm9
+.byte	102,15,58,15,233,8
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	paddd	%xmm4,%xmm10
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrldq	$4,%xmm9
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	pxor	%xmm1,%xmm5
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm3,%xmm9
+	addl	20(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pxor	%xmm9,%xmm5
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm10,0(%rsp)
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm5,%xmm9
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	24(%rsp),%edx
+	xorl	%ecx,%ebx
+	pslldq	$12,%xmm8
+	paddd	%xmm5,%xmm5
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	psrld	$31,%xmm9
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm8,%xmm10
+	rorl	$7,%eax
+	addl	%esi,%edx
+	psrld	$30,%xmm8
+	por	%xmm9,%xmm5
+	addl	28(%rsp),%ecx
+	xorl	%ebx,%eax
+	movl	%edx,%esi
+	roll	$5,%edx
+	pslld	$2,%xmm10
+	pxor	%xmm8,%xmm5
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	16(%r11),%xmm8
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	pxor	%xmm10,%xmm5
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movdqa	%xmm3,%xmm6
+	addl	32(%rsp),%ebx
+	xorl	%eax,%ebp
+	movdqa	%xmm5,%xmm10
+.byte	102,15,58,15,242,8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm5,%xmm8
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	psrldq	$4,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	pxor	%xmm2,%xmm6
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm4,%xmm10
+	addl	36(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	pxor	%xmm10,%xmm6
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm8,16(%rsp)
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm6,%xmm10
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	40(%rsp),%ebp
+	xorl	%edx,%ecx
+	pslldq	$12,%xmm9
+	paddd	%xmm6,%xmm6
+	movl	%eax,%edi
+	roll	$5,%eax
+	andl	%ecx,%esi
+	xorl	%edx,%ecx
+	psrld	$31,%xmm10
+	xorl	%edx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	psrld	$30,%xmm9
+	por	%xmm10,%xmm6
+	addl	44(%rsp),%edx
+	xorl	%ecx,%ebx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	pslld	$2,%xmm8
+	pxor	%xmm9,%xmm6
+	andl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	16(%r11),%xmm9
+	xorl	%ecx,%edi
+	addl	%ebp,%edx
+	pxor	%xmm8,%xmm6
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movdqa	%xmm4,%xmm7
+	addl	48(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm8
+.byte	102,15,58,15,251,8
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm6,%xmm9
+	andl	%eax,%esi
+	xorl	%ebx,%eax
+	psrldq	$4,%xmm8
+	xorl	%ebx,%esi
+	addl	%edx,%ecx
+	pxor	%xmm3,%xmm7
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm5,%xmm8
+	addl	52(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	pxor	%xmm8,%xmm7
+	andl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm9,32(%rsp)
+	xorl	%eax,%edi
+	addl	%ecx,%ebx
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm7,%xmm8
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	56(%rsp),%eax
+	xorl	%ebp,%edx
+	pslldq	$12,%xmm10
+	paddd	%xmm7,%xmm7
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	andl	%edx,%esi
+	xorl	%ebp,%edx
+	psrld	$31,%xmm8
+	xorl	%ebp,%esi
+	addl	%ebx,%eax
+	movdqa	%xmm10,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	psrld	$30,%xmm10
+	por	%xmm8,%xmm7
+	addl	60(%rsp),%ebp
+	xorl	%edx,%ecx
+	movl	%eax,%esi
+	roll	$5,%eax
+	pslld	$2,%xmm9
+	pxor	%xmm10,%xmm7
+	andl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	16(%r11),%xmm10
+	xorl	%edx,%edi
+	addl	%eax,%ebp
+	pxor	%xmm9,%xmm7
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movdqa	%xmm7,%xmm9
+	addl	0(%rsp),%edx
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,206,8
+	xorl	%ecx,%ebx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm1,%xmm0
+	andl	%ebx,%esi
+	xorl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm7,%xmm10
+	xorl	%ecx,%esi
+	addl	%ebp,%edx
+	pxor	%xmm9,%xmm0
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	4(%rsp),%ecx
+	xorl	%ebx,%eax
+	movdqa	%xmm0,%xmm9
+	movdqa	%xmm10,48(%rsp)
+	movl	%edx,%esi
+	roll	$5,%edx
+	andl	%eax,%edi
+	xorl	%ebx,%eax
+	pslld	$2,%xmm0
+	xorl	%ebx,%edi
+	addl	%edx,%ecx
+	psrld	$30,%xmm9
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	8(%rsp),%ebx
+	xorl	%eax,%ebp
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	por	%xmm9,%xmm0
+	andl	%ebp,%esi
+	xorl	%eax,%ebp
+	movdqa	%xmm0,%xmm10
+	xorl	%eax,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	12(%rsp),%eax
+	xorl	%ebp,%edx
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	andl	%edx,%edi
+	xorl	%ebp,%edx
+	xorl	%ebp,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	16(%rsp),%ebp
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,215,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm2,%xmm1
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm0,%xmm8
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm10,%xmm1
+	addl	20(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm1,%xmm10
+	movdqa	%xmm8,0(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm1
+	addl	24(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm10
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm10,%xmm1
+	addl	28(%rsp),%ebx
+	xorl	%eax,%edi
+	movdqa	%xmm1,%xmm8
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	32(%rsp),%eax
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,192,8
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	pxor	%xmm3,%xmm2
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	movdqa	32(%r11),%xmm10
+	paddd	%xmm1,%xmm9
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	pxor	%xmm8,%xmm2
+	addl	36(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	movdqa	%xmm2,%xmm8
+	movdqa	%xmm9,16(%rsp)
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	pslld	$2,%xmm2
+	addl	40(%rsp),%edx
+	xorl	%ecx,%esi
+	psrld	$30,%xmm8
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	por	%xmm8,%xmm2
+	addl	44(%rsp),%ecx
+	xorl	%ebx,%edi
+	movdqa	%xmm2,%xmm9
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	48(%rsp),%ebx
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,201,8
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	pxor	%xmm4,%xmm3
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm2,%xmm10
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	pxor	%xmm9,%xmm3
+	addl	52(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	movdqa	%xmm3,%xmm9
+	movdqa	%xmm10,32(%rsp)
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ebp
+	xorl	%edx,%esi
+	psrld	$30,%xmm9
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	por	%xmm9,%xmm3
+	addl	60(%rsp),%edx
+	xorl	%ecx,%edi
+	movdqa	%xmm3,%xmm10
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	0(%rsp),%ecx
+	pxor	%xmm0,%xmm4
+.byte	102,68,15,58,15,210,8
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	pxor	%xmm5,%xmm4
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm3,%xmm8
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	pxor	%xmm10,%xmm4
+	addl	4(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	movdqa	%xmm4,%xmm10
+	movdqa	%xmm8,48(%rsp)
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	pslld	$2,%xmm4
+	addl	8(%rsp),%eax
+	xorl	%ebp,%esi
+	psrld	$30,%xmm10
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	por	%xmm10,%xmm4
+	addl	12(%rsp),%ebp
+	xorl	%edx,%edi
+	movdqa	%xmm4,%xmm8
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	16(%rsp),%edx
+	pxor	%xmm1,%xmm5
+.byte	102,68,15,58,15,195,8
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	pxor	%xmm6,%xmm5
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm4,%xmm9
+	rorl	$7,%eax
+	addl	%esi,%edx
+	pxor	%xmm8,%xmm5
+	addl	20(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	movdqa	%xmm5,%xmm8
+	movdqa	%xmm9,0(%rsp)
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	pslld	$2,%xmm5
+	addl	24(%rsp),%ebx
+	xorl	%eax,%esi
+	psrld	$30,%xmm8
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	por	%xmm8,%xmm5
+	addl	28(%rsp),%eax
+	xorl	%ebp,%edi
+	movdqa	%xmm5,%xmm9
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ecx,%edi
+	pxor	%xmm2,%xmm6
+.byte	102,68,15,58,15,204,8
+	xorl	%edx,%ecx
+	addl	32(%rsp),%ebp
+	andl	%edx,%edi
+	pxor	%xmm7,%xmm6
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm5,%xmm10
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	pxor	%xmm9,%xmm6
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movdqa	%xmm6,%xmm9
+	movdqa	%xmm10,16(%rsp)
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	36(%rsp),%edx
+	andl	%ecx,%esi
+	pslld	$2,%xmm6
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	psrld	$30,%xmm9
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	por	%xmm9,%xmm6
+	movl	%eax,%edi
+	xorl	%ebx,%eax
+	movdqa	%xmm6,%xmm10
+	addl	40(%rsp),%ecx
+	andl	%ebx,%edi
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	44(%rsp),%ebx
+	andl	%eax,%esi
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%edi
+	pxor	%xmm3,%xmm7
+.byte	102,68,15,58,15,213,8
+	xorl	%ebp,%edx
+	addl	48(%rsp),%eax
+	andl	%ebp,%edi
+	pxor	%xmm0,%xmm7
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	movdqa	48(%r11),%xmm9
+	paddd	%xmm6,%xmm8
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	pxor	%xmm10,%xmm7
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movdqa	%xmm7,%xmm10
+	movdqa	%xmm8,32(%rsp)
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	52(%rsp),%ebp
+	andl	%edx,%esi
+	pslld	$2,%xmm7
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	psrld	$30,%xmm10
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	por	%xmm10,%xmm7
+	movl	%ebx,%edi
+	xorl	%ecx,%ebx
+	movdqa	%xmm7,%xmm8
+	addl	56(%rsp),%edx
+	andl	%ecx,%edi
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	60(%rsp),%ecx
+	andl	%ebx,%esi
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movl	%ebp,%edi
+	pxor	%xmm4,%xmm0
+.byte	102,68,15,58,15,198,8
+	xorl	%eax,%ebp
+	addl	0(%rsp),%ebx
+	andl	%eax,%edi
+	pxor	%xmm1,%xmm0
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm7,%xmm9
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	pxor	%xmm8,%xmm0
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movdqa	%xmm0,%xmm8
+	movdqa	%xmm9,48(%rsp)
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	4(%rsp),%eax
+	andl	%ebp,%esi
+	pslld	$2,%xmm0
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	psrld	$30,%xmm8
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	por	%xmm8,%xmm0
+	movl	%ecx,%edi
+	xorl	%edx,%ecx
+	movdqa	%xmm0,%xmm9
+	addl	8(%rsp),%ebp
+	andl	%edx,%edi
+	andl	%ecx,%esi
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	movl	%eax,%edi
+	roll	$5,%eax
+	addl	%esi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%esi
+	xorl	%ecx,%ebx
+	addl	12(%rsp),%edx
+	andl	%ecx,%esi
+	andl	%ebx,%edi
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	addl	%edi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movl	%eax,%edi
+	pxor	%xmm5,%xmm1
+.byte	102,68,15,58,15,207,8
+	xorl	%ebx,%eax
+	addl	16(%rsp),%ecx
+	andl	%ebx,%edi
+	pxor	%xmm2,%xmm1
+	andl	%eax,%esi
+	rorl	$7,%ebp
+	movdqa	%xmm10,%xmm8
+	paddd	%xmm0,%xmm10
+	addl	%edi,%ecx
+	movl	%edx,%edi
+	pxor	%xmm9,%xmm1
+	roll	$5,%edx
+	addl	%esi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	movdqa	%xmm1,%xmm9
+	movdqa	%xmm10,0(%rsp)
+	movl	%ebp,%esi
+	xorl	%eax,%ebp
+	addl	20(%rsp),%ebx
+	andl	%eax,%esi
+	pslld	$2,%xmm1
+	andl	%ebp,%edi
+	rorl	$7,%edx
+	psrld	$30,%xmm9
+	addl	%esi,%ebx
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	addl	%edi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	por	%xmm9,%xmm1
+	movl	%edx,%edi
+	xorl	%ebp,%edx
+	movdqa	%xmm1,%xmm10
+	addl	24(%rsp),%eax
+	andl	%ebp,%edi
+	andl	%edx,%esi
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	addl	%esi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	movl	%ecx,%esi
+	xorl	%edx,%ecx
+	addl	28(%rsp),%ebp
+	andl	%edx,%esi
+	andl	%ecx,%edi
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	movl	%eax,%esi
+	roll	$5,%eax
+	addl	%edi,%ebp
+	xorl	%edx,%ecx
+	addl	%eax,%ebp
+	movl	%ebx,%edi
+	pxor	%xmm6,%xmm2
+.byte	102,68,15,58,15,208,8
+	xorl	%ecx,%ebx
+	addl	32(%rsp),%edx
+	andl	%ecx,%edi
+	pxor	%xmm3,%xmm2
+	andl	%ebx,%esi
+	rorl	$7,%eax
+	movdqa	%xmm8,%xmm9
+	paddd	%xmm1,%xmm8
+	addl	%edi,%edx
+	movl	%ebp,%edi
+	pxor	%xmm10,%xmm2
+	roll	$5,%ebp
+	addl	%esi,%edx
+	xorl	%ecx,%ebx
+	addl	%ebp,%edx
+	movdqa	%xmm2,%xmm10
+	movdqa	%xmm8,16(%rsp)
+	movl	%eax,%esi
+	xorl	%ebx,%eax
+	addl	36(%rsp),%ecx
+	andl	%ebx,%esi
+	pslld	$2,%xmm2
+	andl	%eax,%edi
+	rorl	$7,%ebp
+	psrld	$30,%xmm10
+	addl	%esi,%ecx
+	movl	%edx,%esi
+	roll	$5,%edx
+	addl	%edi,%ecx
+	xorl	%ebx,%eax
+	addl	%edx,%ecx
+	por	%xmm10,%xmm2
+	movl	%ebp,%edi
+	xorl	%eax,%ebp
+	movdqa	%xmm2,%xmm8
+	addl	40(%rsp),%ebx
+	andl	%eax,%edi
+	andl	%ebp,%esi
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	addl	%esi,%ebx
+	xorl	%eax,%ebp
+	addl	%ecx,%ebx
+	movl	%edx,%esi
+	xorl	%ebp,%edx
+	addl	44(%rsp),%eax
+	andl	%ebp,%esi
+	andl	%edx,%edi
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	addl	%edi,%eax
+	xorl	%ebp,%edx
+	addl	%ebx,%eax
+	addl	48(%rsp),%ebp
+	pxor	%xmm7,%xmm3
+.byte	102,68,15,58,15,193,8
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	pxor	%xmm4,%xmm3
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	movdqa	%xmm9,%xmm10
+	paddd	%xmm2,%xmm9
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	pxor	%xmm8,%xmm3
+	addl	52(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	movdqa	%xmm3,%xmm8
+	movdqa	%xmm9,32(%rsp)
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	pslld	$2,%xmm3
+	addl	56(%rsp),%ecx
+	xorl	%ebx,%esi
+	psrld	$30,%xmm8
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	por	%xmm8,%xmm3
+	addl	60(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	0(%rsp),%eax
+	paddd	%xmm3,%xmm10
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	movdqa	%xmm10,48(%rsp)
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	4(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	8(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	12(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	cmpq	%r10,%r9
+	je	.Ldone_ssse3
+	movdqa	64(%r11),%xmm6
+	movdqa	0(%r11),%xmm9
+	movdqu	0(%r9),%xmm0
+	movdqu	16(%r9),%xmm1
+	movdqu	32(%r9),%xmm2
+	movdqu	48(%r9),%xmm3
+.byte	102,15,56,0,198
+	addq	$64,%r9
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+.byte	102,15,56,0,206
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	paddd	%xmm9,%xmm0
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	movdqa	%xmm0,0(%rsp)
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	psubd	%xmm9,%xmm0
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+.byte	102,15,56,0,214
+	movl	%edx,%edi
+	roll	$5,%edx
+	paddd	%xmm9,%xmm1
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	movdqa	%xmm1,16(%rsp)
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	psubd	%xmm9,%xmm1
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+.byte	102,15,56,0,222
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	paddd	%xmm9,%xmm2
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	movdqa	%xmm2,32(%rsp)
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	psubd	%xmm9,%xmm2
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	addl	12(%r8),%edx
+	movl	%eax,0(%r8)
+	addl	16(%r8),%ebp
+	movl	%esi,4(%r8)
+	movl	%esi,%ebx
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	jmp	.Loop_ssse3
+
+.p2align	4
+.Ldone_ssse3:
+	addl	16(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	20(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	24(%rsp),%ebp
+	xorl	%edx,%esi
+	movl	%eax,%edi
+	roll	$5,%eax
+	xorl	%ecx,%esi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%esi,%ebp
+	addl	28(%rsp),%edx
+	xorl	%ecx,%edi
+	movl	%ebp,%esi
+	roll	$5,%ebp
+	xorl	%ebx,%edi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%edi,%edx
+	addl	32(%rsp),%ecx
+	xorl	%ebx,%esi
+	movl	%edx,%edi
+	roll	$5,%edx
+	xorl	%eax,%esi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%esi,%ecx
+	addl	36(%rsp),%ebx
+	xorl	%eax,%edi
+	movl	%ecx,%esi
+	roll	$5,%ecx
+	xorl	%ebp,%edi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%edi,%ebx
+	addl	40(%rsp),%eax
+	xorl	%ebp,%esi
+	movl	%ebx,%edi
+	roll	$5,%ebx
+	xorl	%edx,%esi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%esi,%eax
+	addl	44(%rsp),%ebp
+	xorl	%edx,%edi
+	movl	%eax,%esi
+	roll	$5,%eax
+	xorl	%ecx,%edi
+	addl	%eax,%ebp
+	rorl	$7,%ebx
+	addl	%edi,%ebp
+	addl	48(%rsp),%edx
+	xorl	%ecx,%esi
+	movl	%ebp,%edi
+	roll	$5,%ebp
+	xorl	%ebx,%esi
+	addl	%ebp,%edx
+	rorl	$7,%eax
+	addl	%esi,%edx
+	addl	52(%rsp),%ecx
+	xorl	%ebx,%edi
+	movl	%edx,%esi
+	roll	$5,%edx
+	xorl	%eax,%edi
+	addl	%edx,%ecx
+	rorl	$7,%ebp
+	addl	%edi,%ecx
+	addl	56(%rsp),%ebx
+	xorl	%eax,%esi
+	movl	%ecx,%edi
+	roll	$5,%ecx
+	xorl	%ebp,%esi
+	addl	%ecx,%ebx
+	rorl	$7,%edx
+	addl	%esi,%ebx
+	addl	60(%rsp),%eax
+	xorl	%ebp,%edi
+	movl	%ebx,%esi
+	roll	$5,%ebx
+	xorl	%edx,%edi
+	addl	%ebx,%eax
+	rorl	$7,%ecx
+	addl	%edi,%eax
+	addl	0(%r8),%eax
+	addl	4(%r8),%esi
+	addl	8(%r8),%ecx
+	movl	%eax,0(%r8)
+	addl	12(%r8),%edx
+	movl	%esi,4(%r8)
+	addl	16(%r8),%ebp
+	movl	%ecx,8(%r8)
+	movl	%edx,12(%r8)
+	movl	%ebp,16(%r8)
+	movaps	64+0(%rsp),%xmm6
+	movaps	64+16(%rsp),%xmm7
+	movaps	64+32(%rsp),%xmm8
+	movaps	64+48(%rsp),%xmm9
+	movaps	64+64(%rsp),%xmm10
+	leaq	144(%rsp),%rsi
+	movq	0(%rsi),%r12
+	movq	8(%rsi),%rbp
+	movq	16(%rsi),%rbx
+	leaq	24(%rsi),%rsp
+.Lepilogue_ssse3:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_sha1_block_data_order_ssse3:
+.p2align	6
+K_XX_XX:
+.long	0x5a827999,0x5a827999,0x5a827999,0x5a827999	
+.long	0x6ed9eba1,0x6ed9eba1,0x6ed9eba1,0x6ed9eba1	
+.long	0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc,0x8f1bbcdc	
+.long	0xca62c1d6,0xca62c1d6,0xca62c1d6,0xca62c1d6	
+.long	0x00010203,0x04050607,0x08090a0b,0x0c0d0e0f	
+.byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
+
+.def	se_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+se_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	leaq	.Lprologue(%rip),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	leaq	.Lepilogue(%rip),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	movq	64(%rax),%rax
+	leaq	32(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	-32(%rax),%r13
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+	movq	%r13,224(%r8)
+
+	jmp	.Lcommon_seh_tail
+
+
+.def	ssse3_handler;	.scl 3;	.type 32;	.endef
+.p2align	4
+ssse3_handler:
+	pushq	%rsi
+	pushq	%rdi
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	pushfq
+	subq	$64,%rsp
+
+	movq	120(%r8),%rax
+	movq	248(%r8),%rbx
+
+	movq	8(%r9),%rsi
+	movq	56(%r9),%r11
+
+	movl	0(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jb	.Lcommon_seh_tail
+
+	movq	152(%r8),%rax
+
+	movl	4(%r11),%r10d
+	leaq	(%rsi,%r10,1),%r10
+	cmpq	%r10,%rbx
+	jae	.Lcommon_seh_tail
+
+	leaq	64(%rax),%rsi
+	leaq	512(%r8),%rdi
+	movl	$10,%ecx
+.long	0xa548f3fc		
+	leaq	168(%rax),%rax
+
+	movq	-8(%rax),%rbx
+	movq	-16(%rax),%rbp
+	movq	-24(%rax),%r12
+	movq	%rbx,144(%r8)
+	movq	%rbp,160(%r8)
+	movq	%r12,216(%r8)
+
+.Lcommon_seh_tail:
+	movq	8(%rax),%rdi
+	movq	16(%rax),%rsi
+	movq	%rax,152(%r8)
+	movq	%rsi,168(%r8)
+	movq	%rdi,176(%r8)
+
+	movq	40(%r9),%rdi
+	movq	%r8,%rsi
+	movl	$154,%ecx
+.long	0xa548f3fc		
+
+	movq	%r9,%rsi
+	xorq	%rcx,%rcx
+	movq	8(%rsi),%rdx
+	movq	0(%rsi),%r8
+	movq	16(%rsi),%r9
+	movq	40(%rsi),%r10
+	leaq	56(%rsi),%r11
+	leaq	24(%rsi),%r12
+	movq	%r10,32(%rsp)
+	movq	%r11,40(%rsp)
+	movq	%r12,48(%rsp)
+	movq	%rcx,56(%rsp)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	movl	$1,%eax
+	addq	$64,%rsp
+	popfq
+	popq	%r15
+	popq	%r14
+	popq	%r13
+	popq	%r12
+	popq	%rbp
+	popq	%rbx
+	popq	%rdi
+	popq	%rsi
+	retq
+
+
+.section	.pdata
+.p2align	2
+.rva	.LSEH_begin_sha1_block_data_order
+.rva	.LSEH_end_sha1_block_data_order
+.rva	.LSEH_info_sha1_block_data_order
+.rva	.LSEH_begin_sha1_block_data_order_ssse3
+.rva	.LSEH_end_sha1_block_data_order_ssse3
+.rva	.LSEH_info_sha1_block_data_order_ssse3
+.section	.xdata
+.p2align	3
+.LSEH_info_sha1_block_data_order:
+.byte	9,0,0,0
+.rva	se_handler
+.LSEH_info_sha1_block_data_order_ssse3:
+.byte	9,0,0,0
+.rva	ssse3_handler
+.rva	.Lprologue_ssse3,.Lepilogue_ssse3	
diff --git a/crypto/sha/sha1-mips.S b/crypto/sha/sha1-mips.S
new file mode 100644
index 0000000..dddb578
--- /dev/null
+++ b/crypto/sha/sha1-mips.S
@@ -0,0 +1,1663 @@
+.text
+
+.set	noat
+.set	noreorder
+.align	5
+.globl	sha1_block_data_order
+.ent	sha1_block_data_order
+sha1_block_data_order:
+	.frame	$29,16*4,$31
+	.mask	3237937152,-4
+	.set	noreorder
+	sub $29,16*4
+	sw	$31,(16-1)*4($29)
+	sw	$30,(16-2)*4($29)
+	sw	$23,(16-3)*4($29)
+	sw	$22,(16-4)*4($29)
+	sw	$21,(16-5)*4($29)
+	sw	$20,(16-6)*4($29)
+	sw	$19,(16-7)*4($29)
+	sw	$18,(16-8)*4($29)
+	sw	$17,(16-9)*4($29)
+	sw	$16,(16-10)*4($29)
+	sll $6,6
+	add $6,$5
+	sw	$6,0($29)
+	lw	$1,0($4)
+	lw	$2,4($4)
+	lw	$3,8($4)
+	lw	$7,12($4)
+	b	.Loop
+	lw	$24,16($4)
+.align	4
+.Loop:
+	.set	reorder
+	lwl	$8,3($5)
+	lui	$31,0x5a82
+	lwr	$8,0($5)
+	ori	$31,0x7999	# K_00_19
+	srl	$25,$8,24	# byte swap(0)
+	srl	$6,$8,8
+	andi	$30,$8,0xFF00
+	sll	$8,$8,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$8,$25
+	or	$6,$30
+	or	$8,$6
+	 lwl	$9,1*4+3($5)
+	sll	$25,$1,5	# 0
+	addu	$24,$31
+	 lwr	$9,1*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$8
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$9,24	# byte swap(1)
+	srl	$6,$9,8
+	andi	$30,$9,0xFF00
+	sll	$9,$9,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$9,$25
+	or	$6,$30
+	or	$9,$6
+	 lwl	$10,2*4+3($5)
+	sll	$25,$24,5	# 1
+	addu	$7,$31
+	 lwr	$10,2*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$9
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$10,24	# byte swap(2)
+	srl	$6,$10,8
+	andi	$30,$10,0xFF00
+	sll	$10,$10,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$10,$25
+	or	$6,$30
+	or	$10,$6
+	 lwl	$11,3*4+3($5)
+	sll	$25,$7,5	# 2
+	addu	$3,$31
+	 lwr	$11,3*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$10
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$11,24	# byte swap(3)
+	srl	$6,$11,8
+	andi	$30,$11,0xFF00
+	sll	$11,$11,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$11,$25
+	or	$6,$30
+	or	$11,$6
+	 lwl	$12,4*4+3($5)
+	sll	$25,$3,5	# 3
+	addu	$2,$31
+	 lwr	$12,4*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$11
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$12,24	# byte swap(4)
+	srl	$6,$12,8
+	andi	$30,$12,0xFF00
+	sll	$12,$12,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$12,$25
+	or	$6,$30
+	or	$12,$6
+	 lwl	$13,5*4+3($5)
+	sll	$25,$2,5	# 4
+	addu	$1,$31
+	 lwr	$13,5*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$12
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$13,24	# byte swap(5)
+	srl	$6,$13,8
+	andi	$30,$13,0xFF00
+	sll	$13,$13,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$13,$25
+	or	$6,$30
+	or	$13,$6
+	 lwl	$14,6*4+3($5)
+	sll	$25,$1,5	# 5
+	addu	$24,$31
+	 lwr	$14,6*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$13
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$14,24	# byte swap(6)
+	srl	$6,$14,8
+	andi	$30,$14,0xFF00
+	sll	$14,$14,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$14,$25
+	or	$6,$30
+	or	$14,$6
+	 lwl	$15,7*4+3($5)
+	sll	$25,$24,5	# 6
+	addu	$7,$31
+	 lwr	$15,7*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$14
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$15,24	# byte swap(7)
+	srl	$6,$15,8
+	andi	$30,$15,0xFF00
+	sll	$15,$15,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$15,$25
+	or	$6,$30
+	or	$15,$6
+	 lwl	$16,8*4+3($5)
+	sll	$25,$7,5	# 7
+	addu	$3,$31
+	 lwr	$16,8*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$15
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$16,24	# byte swap(8)
+	srl	$6,$16,8
+	andi	$30,$16,0xFF00
+	sll	$16,$16,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$16,$25
+	or	$6,$30
+	or	$16,$6
+	 lwl	$17,9*4+3($5)
+	sll	$25,$3,5	# 8
+	addu	$2,$31
+	 lwr	$17,9*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$16
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$17,24	# byte swap(9)
+	srl	$6,$17,8
+	andi	$30,$17,0xFF00
+	sll	$17,$17,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$17,$25
+	or	$6,$30
+	or	$17,$6
+	 lwl	$18,10*4+3($5)
+	sll	$25,$2,5	# 9
+	addu	$1,$31
+	 lwr	$18,10*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$17
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$18,24	# byte swap(10)
+	srl	$6,$18,8
+	andi	$30,$18,0xFF00
+	sll	$18,$18,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$18,$25
+	or	$6,$30
+	or	$18,$6
+	 lwl	$19,11*4+3($5)
+	sll	$25,$1,5	# 10
+	addu	$24,$31
+	 lwr	$19,11*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$18
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$19,24	# byte swap(11)
+	srl	$6,$19,8
+	andi	$30,$19,0xFF00
+	sll	$19,$19,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$19,$25
+	or	$6,$30
+	or	$19,$6
+	 lwl	$20,12*4+3($5)
+	sll	$25,$24,5	# 11
+	addu	$7,$31
+	 lwr	$20,12*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$19
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$20,24	# byte swap(12)
+	srl	$6,$20,8
+	andi	$30,$20,0xFF00
+	sll	$20,$20,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$20,$25
+	or	$6,$30
+	or	$20,$6
+	 lwl	$21,13*4+3($5)
+	sll	$25,$7,5	# 12
+	addu	$3,$31
+	 lwr	$21,13*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$20
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$21,24	# byte swap(13)
+	srl	$6,$21,8
+	andi	$30,$21,0xFF00
+	sll	$21,$21,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$21,$25
+	or	$6,$30
+	or	$21,$6
+	 lwl	$22,14*4+3($5)
+	sll	$25,$3,5	# 13
+	addu	$2,$31
+	 lwr	$22,14*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$21
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$22,24	# byte swap(14)
+	srl	$6,$22,8
+	andi	$30,$22,0xFF00
+	sll	$22,$22,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$22,$25
+	or	$6,$30
+	or	$22,$6
+	 lwl	$23,15*4+3($5)
+	sll	$25,$2,5	# 14
+	addu	$1,$31
+	 lwr	$23,15*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$22
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$23,24	# byte swap(15)
+	srl	$6,$23,8
+	andi	$30,$23,0xFF00
+	sll	$23,$23,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$23,$25
+	or	$23,$6
+	or	$23,$30
+	 xor	$8,$10
+	sll	$25,$1,5	# 15
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$8,$16
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$8,$21
+	sll	$30,$2,30
+	and	$25,$2
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$2,$2,2
+	xor	$25,$7
+	 or	$8,$6
+	addu	$24,$23
+	or	$2,$30
+	addu	$24,$25
+	 xor	$9,$11
+	sll	$25,$24,5	# 16
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$9,$17
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$9,$22
+	sll	$30,$1,30
+	and	$25,$1
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$1,$1,2
+	xor	$25,$3
+	 or	$9,$6
+	addu	$7,$8
+	or	$1,$30
+	addu	$7,$25
+	 xor	$10,$12
+	sll	$25,$7,5	# 17
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$10,$18
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$10,$23
+	sll	$30,$24,30
+	and	$25,$24
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$24,$24,2
+	xor	$25,$2
+	 or	$10,$6
+	addu	$3,$9
+	or	$24,$30
+	addu	$3,$25
+	 xor	$11,$13
+	sll	$25,$3,5	# 18
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$11,$19
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$11,$8
+	sll	$30,$7,30
+	and	$25,$7
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$7,$7,2
+	xor	$25,$1
+	 or	$11,$6
+	addu	$2,$10
+	or	$7,$30
+	addu	$2,$25
+	 xor	$12,$14
+	sll	$25,$2,5	# 19
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$12,$20
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$12,$9
+	sll	$30,$3,30
+	and	$25,$3
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$3,$3,2
+	xor	$25,$24
+	 or	$12,$6
+	addu	$1,$11
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0x6ed9
+	ori	$31,0xeba1	# K_20_39
+	 xor	$13,$15
+	sll	$25,$1,5	# 20
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$13,$21
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$13,$10
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$2,$2,2
+	addu	$24,$12
+	 or	$13,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$14,$16
+	sll	$25,$24,5	# 21
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$14,$22
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$14,$11
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$1,$1,2
+	addu	$7,$13
+	 or	$14,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$15,$17
+	sll	$25,$7,5	# 22
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$15,$23
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$15,$12
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$24,$24,2
+	addu	$3,$14
+	 or	$15,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$16,$18
+	sll	$25,$3,5	# 23
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$16,$8
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$16,$13
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$7,$7,2
+	addu	$2,$15
+	 or	$16,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$17,$19
+	sll	$25,$2,5	# 24
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$17,$9
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$17,$14
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$17,31
+	 addu	$17,$17
+	srl	$3,$3,2
+	addu	$1,$16
+	 or	$17,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$18,$20
+	sll	$25,$1,5	# 25
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$18,$10
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$18,$15
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$18,31
+	 addu	$18,$18
+	srl	$2,$2,2
+	addu	$24,$17
+	 or	$18,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$19,$21
+	sll	$25,$24,5	# 26
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$19,$11
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$19,$16
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$19,31
+	 addu	$19,$19
+	srl	$1,$1,2
+	addu	$7,$18
+	 or	$19,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$20,$22
+	sll	$25,$7,5	# 27
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$20,$12
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$20,$17
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$20,31
+	 addu	$20,$20
+	srl	$24,$24,2
+	addu	$3,$19
+	 or	$20,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$21,$23
+	sll	$25,$3,5	# 28
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$21,$13
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$21,$18
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$7,$7,2
+	addu	$2,$20
+	 or	$21,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$22,$8
+	sll	$25,$2,5	# 29
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$22,$14
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$22,$19
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$3,$3,2
+	addu	$1,$21
+	 or	$22,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$23,$9
+	sll	$25,$1,5	# 30
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$23,$15
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$23,$20
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$2,$2,2
+	addu	$24,$22
+	 or	$23,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$8,$10
+	sll	$25,$24,5	# 31
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$8,$16
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$8,$21
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$1,$1,2
+	addu	$7,$23
+	 or	$8,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$9,$11
+	sll	$25,$7,5	# 32
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$9,$17
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$9,$22
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$24,$24,2
+	addu	$3,$8
+	 or	$9,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$10,$12
+	sll	$25,$3,5	# 33
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$10,$18
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$10,$23
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$7,$7,2
+	addu	$2,$9
+	 or	$10,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$11,$13
+	sll	$25,$2,5	# 34
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$11,$19
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$11,$8
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$3,$3,2
+	addu	$1,$10
+	 or	$11,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$12,$14
+	sll	$25,$1,5	# 35
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$12,$20
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$12,$9
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$2,$2,2
+	addu	$24,$11
+	 or	$12,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$13,$15
+	sll	$25,$24,5	# 36
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$13,$21
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$13,$10
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$1,$1,2
+	addu	$7,$12
+	 or	$13,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$14,$16
+	sll	$25,$7,5	# 37
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$14,$22
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$14,$11
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$24,$24,2
+	addu	$3,$13
+	 or	$14,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$15,$17
+	sll	$25,$3,5	# 38
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$15,$23
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$15,$12
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$7,$7,2
+	addu	$2,$14
+	 or	$15,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$16,$18
+	sll	$25,$2,5	# 39
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$16,$8
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$16,$13
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$3,$3,2
+	addu	$1,$15
+	 or	$16,$6
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0x8f1b
+	ori	$31,0xbcdc	# K_40_59
+	 xor	$17,$19
+	sll	$25,$1,5	# 40
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$17,$9
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$17,$14
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$17,31
+	xor	$25,$3,$7
+	 addu	$17,$17
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$17,$6
+	addu	$24,$16
+	or	$2,$30
+	addu	$24,$25
+	 xor	$18,$20
+	sll	$25,$24,5	# 41
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$18,$10
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$18,$15
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$18,31
+	xor	$25,$2,$3
+	 addu	$18,$18
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$18,$6
+	addu	$7,$17
+	or	$1,$30
+	addu	$7,$25
+	 xor	$19,$21
+	sll	$25,$7,5	# 42
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$19,$11
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$19,$16
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$19,31
+	xor	$25,$1,$2
+	 addu	$19,$19
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$19,$6
+	addu	$3,$18
+	or	$24,$30
+	addu	$3,$25
+	 xor	$20,$22
+	sll	$25,$3,5	# 43
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$20,$12
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$20,$17
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$20,31
+	xor	$25,$24,$1
+	 addu	$20,$20
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$20,$6
+	addu	$2,$19
+	or	$7,$30
+	addu	$2,$25
+	 xor	$21,$23
+	sll	$25,$2,5	# 44
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$21,$13
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$21,$18
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$21,31
+	xor	$25,$7,$24
+	 addu	$21,$21
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$21,$6
+	addu	$1,$20
+	or	$3,$30
+	addu	$1,$25
+	 xor	$22,$8
+	sll	$25,$1,5	# 45
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$22,$14
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$22,$19
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$22,31
+	xor	$25,$3,$7
+	 addu	$22,$22
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$22,$6
+	addu	$24,$21
+	or	$2,$30
+	addu	$24,$25
+	 xor	$23,$9
+	sll	$25,$24,5	# 46
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$23,$15
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$23,$20
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$23,31
+	xor	$25,$2,$3
+	 addu	$23,$23
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$23,$6
+	addu	$7,$22
+	or	$1,$30
+	addu	$7,$25
+	 xor	$8,$10
+	sll	$25,$7,5	# 47
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$8,$16
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$8,$21
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$8,31
+	xor	$25,$1,$2
+	 addu	$8,$8
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$8,$6
+	addu	$3,$23
+	or	$24,$30
+	addu	$3,$25
+	 xor	$9,$11
+	sll	$25,$3,5	# 48
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$9,$17
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$9,$22
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$9,31
+	xor	$25,$24,$1
+	 addu	$9,$9
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$9,$6
+	addu	$2,$8
+	or	$7,$30
+	addu	$2,$25
+	 xor	$10,$12
+	sll	$25,$2,5	# 49
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$10,$18
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$10,$23
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$10,31
+	xor	$25,$7,$24
+	 addu	$10,$10
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$10,$6
+	addu	$1,$9
+	or	$3,$30
+	addu	$1,$25
+	 xor	$11,$13
+	sll	$25,$1,5	# 50
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$11,$19
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$11,$8
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$11,31
+	xor	$25,$3,$7
+	 addu	$11,$11
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$11,$6
+	addu	$24,$10
+	or	$2,$30
+	addu	$24,$25
+	 xor	$12,$14
+	sll	$25,$24,5	# 51
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$12,$20
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$12,$9
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$12,31
+	xor	$25,$2,$3
+	 addu	$12,$12
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$12,$6
+	addu	$7,$11
+	or	$1,$30
+	addu	$7,$25
+	 xor	$13,$15
+	sll	$25,$7,5	# 52
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$13,$21
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$13,$10
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$13,31
+	xor	$25,$1,$2
+	 addu	$13,$13
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$13,$6
+	addu	$3,$12
+	or	$24,$30
+	addu	$3,$25
+	 xor	$14,$16
+	sll	$25,$3,5	# 53
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$14,$22
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$14,$11
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$14,31
+	xor	$25,$24,$1
+	 addu	$14,$14
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$14,$6
+	addu	$2,$13
+	or	$7,$30
+	addu	$2,$25
+	 xor	$15,$17
+	sll	$25,$2,5	# 54
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$15,$23
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$15,$12
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$15,31
+	xor	$25,$7,$24
+	 addu	$15,$15
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$15,$6
+	addu	$1,$14
+	or	$3,$30
+	addu	$1,$25
+	 xor	$16,$18
+	sll	$25,$1,5	# 55
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$16,$8
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$16,$13
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$16,31
+	xor	$25,$3,$7
+	 addu	$16,$16
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$16,$6
+	addu	$24,$15
+	or	$2,$30
+	addu	$24,$25
+	 xor	$17,$19
+	sll	$25,$24,5	# 56
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$17,$9
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$17,$14
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$17,31
+	xor	$25,$2,$3
+	 addu	$17,$17
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$17,$6
+	addu	$7,$16
+	or	$1,$30
+	addu	$7,$25
+	 xor	$18,$20
+	sll	$25,$7,5	# 57
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$18,$10
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$18,$15
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$18,31
+	xor	$25,$1,$2
+	 addu	$18,$18
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$18,$6
+	addu	$3,$17
+	or	$24,$30
+	addu	$3,$25
+	 xor	$19,$21
+	sll	$25,$3,5	# 58
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$19,$11
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$19,$16
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$19,31
+	xor	$25,$24,$1
+	 addu	$19,$19
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$19,$6
+	addu	$2,$18
+	or	$7,$30
+	addu	$2,$25
+	 xor	$20,$22
+	sll	$25,$2,5	# 59
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$20,$12
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$20,$17
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$20,31
+	xor	$25,$7,$24
+	 addu	$20,$20
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$20,$6
+	addu	$1,$19
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0xca62
+	ori	$31,0xc1d6	# K_60_79
+	 xor	$21,$23
+	sll	$25,$1,5	# 60
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$21,$13
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$21,$18
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$2,$2,2
+	addu	$24,$20
+	 or	$21,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$22,$8
+	sll	$25,$24,5	# 61
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$22,$14
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$22,$19
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$1,$1,2
+	addu	$7,$21
+	 or	$22,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$23,$9
+	sll	$25,$7,5	# 62
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$23,$15
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$23,$20
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$24,$24,2
+	addu	$3,$22
+	 or	$23,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$8,$10
+	sll	$25,$3,5	# 63
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$8,$16
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$8,$21
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$7,$7,2
+	addu	$2,$23
+	 or	$8,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$9,$11
+	sll	$25,$2,5	# 64
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$9,$17
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$9,$22
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$3,$3,2
+	addu	$1,$8
+	 or	$9,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$10,$12
+	sll	$25,$1,5	# 65
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$10,$18
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$10,$23
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$2,$2,2
+	addu	$24,$9
+	 or	$10,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$11,$13
+	sll	$25,$24,5	# 66
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$11,$19
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$11,$8
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$1,$1,2
+	addu	$7,$10
+	 or	$11,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$12,$14
+	sll	$25,$7,5	# 67
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$12,$20
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$12,$9
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$24,$24,2
+	addu	$3,$11
+	 or	$12,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$13,$15
+	sll	$25,$3,5	# 68
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$13,$21
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$13,$10
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$7,$7,2
+	addu	$2,$12
+	 or	$13,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$14,$16
+	sll	$25,$2,5	# 69
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$14,$22
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$14,$11
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$3,$3,2
+	addu	$1,$13
+	 or	$14,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$15,$17
+	sll	$25,$1,5	# 70
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$15,$23
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$15,$12
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$2,$2,2
+	addu	$24,$14
+	 or	$15,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$16,$18
+	sll	$25,$24,5	# 71
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$16,$8
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$16,$13
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$1,$1,2
+	addu	$7,$15
+	 or	$16,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$17,$19
+	sll	$25,$7,5	# 72
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$17,$9
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$17,$14
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$17,31
+	 addu	$17,$17
+	srl	$24,$24,2
+	addu	$3,$16
+	 or	$17,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$18,$20
+	sll	$25,$3,5	# 73
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$18,$10
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$18,$15
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$18,31
+	 addu	$18,$18
+	srl	$7,$7,2
+	addu	$2,$17
+	 or	$18,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$19,$21
+	sll	$25,$2,5	# 74
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$19,$11
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$19,$16
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$19,31
+	 addu	$19,$19
+	srl	$3,$3,2
+	addu	$1,$18
+	 or	$19,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$20,$22
+	sll	$25,$1,5	# 75
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$20,$12
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$20,$17
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$20,31
+	 addu	$20,$20
+	srl	$2,$2,2
+	addu	$24,$19
+	 or	$20,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$21,$23
+	sll	$25,$24,5	# 76
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$21,$13
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$21,$18
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$1,$1,2
+	addu	$7,$20
+	 or	$21,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$22,$8
+	sll	$25,$7,5	# 77
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$22,$14
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$22,$19
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$24,$24,2
+	addu	$3,$21
+	 or	$22,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$23,$9
+	sll	$25,$3,5	# 78
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$23,$15
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$23,$20
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$7,$7,2
+	addu	$2,$22
+	 or	$23,$6
+	or	$7,$30
+	addu	$2,$25
+	 lw	$8,0($4)
+	sll	$25,$2,5	# 79
+	addu	$1,$31
+	 lw	$9,4($4)
+	srl	$6,$2,27
+	addu	$1,$25
+	 lw	$10,8($4)
+	xor	$25,$7,$24
+	addu	$1,$6
+	 lw	$11,12($4)
+	sll	$30,$3,30
+	xor	$25,$3
+	 lw	$12,16($4)
+	srl	$3,$3,2
+	addu	$1,$23
+	or	$3,$30
+	addu	$1,$25
+	add $5,64
+	lw	$6,0($29)
+
+	addu	$1,$8
+	addu	$2,$9
+	sw	$1,0($4)
+	addu	$3,$10
+	addu	$7,$11
+	sw	$2,4($4)
+	addu	$24,$12
+	sw	$3,8($4)
+	sw	$7,12($4)
+	sw	$24,16($4)
+	.set	noreorder
+	bne	$5,$6,.Loop
+	nop
+
+	.set	noreorder
+	lw	$31,(16-1)*4($29)
+	lw	$30,(16-2)*4($29)
+	lw	$23,(16-3)*4($29)
+	lw	$22,(16-4)*4($29)
+	lw	$21,(16-5)*4($29)
+	lw	$20,(16-6)*4($29)
+	lw	$19,(16-7)*4($29)
+	lw	$18,(16-8)*4($29)
+	lw	$17,(16-9)*4($29)
+	lw	$16,(16-10)*4($29)
+	jr	$31
+	add $29,16*4
+.end	sha1_block_data_order
+.rdata
+.asciiz	"SHA1 for MIPS, CRYPTOGAMS by "
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha1-mips64.S b/crypto/sha/sha1-mips64.S
new file mode 100644
index 0000000..c829583
--- /dev/null
+++ b/crypto/sha/sha1-mips64.S
@@ -0,0 +1,1663 @@
+.text
+
+.set	noat
+.set	noreorder
+.align	5
+.globl	sha1_block_data_order
+.ent	sha1_block_data_order
+sha1_block_data_order:
+	.frame	$29,16*8,$31
+	.mask	3237937152,-8
+	.set	noreorder
+	dsub $29,16*8
+	sd	$31,(16-1)*8($29)
+	sd	$30,(16-2)*8($29)
+	sd	$23,(16-3)*8($29)
+	sd	$22,(16-4)*8($29)
+	sd	$21,(16-5)*8($29)
+	sd	$20,(16-6)*8($29)
+	sd	$19,(16-7)*8($29)
+	sd	$18,(16-8)*8($29)
+	sd	$17,(16-9)*8($29)
+	sd	$16,(16-10)*8($29)
+	dsll $6,6
+	dadd $6,$5
+	sd	$6,0($29)
+	lw	$1,0($4)
+	lw	$2,4($4)
+	lw	$3,8($4)
+	lw	$7,12($4)
+	b	.Loop
+	lw	$24,16($4)
+.align	4
+.Loop:
+	.set	reorder
+	lwl	$8,3($5)
+	lui	$31,0x5a82
+	lwr	$8,0($5)
+	ori	$31,0x7999	# K_00_19
+	srl	$25,$8,24	# byte swap(0)
+	srl	$6,$8,8
+	andi	$30,$8,0xFF00
+	sll	$8,$8,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$8,$25
+	or	$6,$30
+	or	$8,$6
+	 lwl	$9,1*4+3($5)
+	sll	$25,$1,5	# 0
+	addu	$24,$31
+	 lwr	$9,1*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$8
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$9,24	# byte swap(1)
+	srl	$6,$9,8
+	andi	$30,$9,0xFF00
+	sll	$9,$9,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$9,$25
+	or	$6,$30
+	or	$9,$6
+	 lwl	$10,2*4+3($5)
+	sll	$25,$24,5	# 1
+	addu	$7,$31
+	 lwr	$10,2*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$9
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$10,24	# byte swap(2)
+	srl	$6,$10,8
+	andi	$30,$10,0xFF00
+	sll	$10,$10,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$10,$25
+	or	$6,$30
+	or	$10,$6
+	 lwl	$11,3*4+3($5)
+	sll	$25,$7,5	# 2
+	addu	$3,$31
+	 lwr	$11,3*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$10
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$11,24	# byte swap(3)
+	srl	$6,$11,8
+	andi	$30,$11,0xFF00
+	sll	$11,$11,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$11,$25
+	or	$6,$30
+	or	$11,$6
+	 lwl	$12,4*4+3($5)
+	sll	$25,$3,5	# 3
+	addu	$2,$31
+	 lwr	$12,4*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$11
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$12,24	# byte swap(4)
+	srl	$6,$12,8
+	andi	$30,$12,0xFF00
+	sll	$12,$12,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$12,$25
+	or	$6,$30
+	or	$12,$6
+	 lwl	$13,5*4+3($5)
+	sll	$25,$2,5	# 4
+	addu	$1,$31
+	 lwr	$13,5*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$12
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$13,24	# byte swap(5)
+	srl	$6,$13,8
+	andi	$30,$13,0xFF00
+	sll	$13,$13,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$13,$25
+	or	$6,$30
+	or	$13,$6
+	 lwl	$14,6*4+3($5)
+	sll	$25,$1,5	# 5
+	addu	$24,$31
+	 lwr	$14,6*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$13
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$14,24	# byte swap(6)
+	srl	$6,$14,8
+	andi	$30,$14,0xFF00
+	sll	$14,$14,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$14,$25
+	or	$6,$30
+	or	$14,$6
+	 lwl	$15,7*4+3($5)
+	sll	$25,$24,5	# 6
+	addu	$7,$31
+	 lwr	$15,7*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$14
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$15,24	# byte swap(7)
+	srl	$6,$15,8
+	andi	$30,$15,0xFF00
+	sll	$15,$15,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$15,$25
+	or	$6,$30
+	or	$15,$6
+	 lwl	$16,8*4+3($5)
+	sll	$25,$7,5	# 7
+	addu	$3,$31
+	 lwr	$16,8*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$15
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$16,24	# byte swap(8)
+	srl	$6,$16,8
+	andi	$30,$16,0xFF00
+	sll	$16,$16,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$16,$25
+	or	$6,$30
+	or	$16,$6
+	 lwl	$17,9*4+3($5)
+	sll	$25,$3,5	# 8
+	addu	$2,$31
+	 lwr	$17,9*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$16
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$17,24	# byte swap(9)
+	srl	$6,$17,8
+	andi	$30,$17,0xFF00
+	sll	$17,$17,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$17,$25
+	or	$6,$30
+	or	$17,$6
+	 lwl	$18,10*4+3($5)
+	sll	$25,$2,5	# 9
+	addu	$1,$31
+	 lwr	$18,10*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$17
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$18,24	# byte swap(10)
+	srl	$6,$18,8
+	andi	$30,$18,0xFF00
+	sll	$18,$18,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$18,$25
+	or	$6,$30
+	or	$18,$6
+	 lwl	$19,11*4+3($5)
+	sll	$25,$1,5	# 10
+	addu	$24,$31
+	 lwr	$19,11*4+0($5)
+	srl	$6,$1,27
+	addu	$24,$25
+	xor	$25,$3,$7
+	addu	$24,$6
+	sll	$30,$2,30
+	and	$25,$2
+	srl	$2,$2,2
+	xor	$25,$7
+	addu	$24,$18
+	or	$2,$30
+	addu	$24,$25
+	srl	$25,$19,24	# byte swap(11)
+	srl	$6,$19,8
+	andi	$30,$19,0xFF00
+	sll	$19,$19,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$19,$25
+	or	$6,$30
+	or	$19,$6
+	 lwl	$20,12*4+3($5)
+	sll	$25,$24,5	# 11
+	addu	$7,$31
+	 lwr	$20,12*4+0($5)
+	srl	$6,$24,27
+	addu	$7,$25
+	xor	$25,$2,$3
+	addu	$7,$6
+	sll	$30,$1,30
+	and	$25,$1
+	srl	$1,$1,2
+	xor	$25,$3
+	addu	$7,$19
+	or	$1,$30
+	addu	$7,$25
+	srl	$25,$20,24	# byte swap(12)
+	srl	$6,$20,8
+	andi	$30,$20,0xFF00
+	sll	$20,$20,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$20,$25
+	or	$6,$30
+	or	$20,$6
+	 lwl	$21,13*4+3($5)
+	sll	$25,$7,5	# 12
+	addu	$3,$31
+	 lwr	$21,13*4+0($5)
+	srl	$6,$7,27
+	addu	$3,$25
+	xor	$25,$1,$2
+	addu	$3,$6
+	sll	$30,$24,30
+	and	$25,$24
+	srl	$24,$24,2
+	xor	$25,$2
+	addu	$3,$20
+	or	$24,$30
+	addu	$3,$25
+	srl	$25,$21,24	# byte swap(13)
+	srl	$6,$21,8
+	andi	$30,$21,0xFF00
+	sll	$21,$21,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$21,$25
+	or	$6,$30
+	or	$21,$6
+	 lwl	$22,14*4+3($5)
+	sll	$25,$3,5	# 13
+	addu	$2,$31
+	 lwr	$22,14*4+0($5)
+	srl	$6,$3,27
+	addu	$2,$25
+	xor	$25,$24,$1
+	addu	$2,$6
+	sll	$30,$7,30
+	and	$25,$7
+	srl	$7,$7,2
+	xor	$25,$1
+	addu	$2,$21
+	or	$7,$30
+	addu	$2,$25
+	srl	$25,$22,24	# byte swap(14)
+	srl	$6,$22,8
+	andi	$30,$22,0xFF00
+	sll	$22,$22,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$22,$25
+	or	$6,$30
+	or	$22,$6
+	 lwl	$23,15*4+3($5)
+	sll	$25,$2,5	# 14
+	addu	$1,$31
+	 lwr	$23,15*4+0($5)
+	srl	$6,$2,27
+	addu	$1,$25
+	xor	$25,$7,$24
+	addu	$1,$6
+	sll	$30,$3,30
+	and	$25,$3
+	srl	$3,$3,2
+	xor	$25,$24
+	addu	$1,$22
+	or	$3,$30
+	addu	$1,$25
+	srl	$25,$23,24	# byte swap(15)
+	srl	$6,$23,8
+	andi	$30,$23,0xFF00
+	sll	$23,$23,24
+	andi	$6,0xFF00
+	sll	$30,$30,8
+	or	$23,$25
+	or	$23,$6
+	or	$23,$30
+	 xor	$8,$10
+	sll	$25,$1,5	# 15
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$8,$16
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$8,$21
+	sll	$30,$2,30
+	and	$25,$2
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$2,$2,2
+	xor	$25,$7
+	 or	$8,$6
+	addu	$24,$23
+	or	$2,$30
+	addu	$24,$25
+	 xor	$9,$11
+	sll	$25,$24,5	# 16
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$9,$17
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$9,$22
+	sll	$30,$1,30
+	and	$25,$1
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$1,$1,2
+	xor	$25,$3
+	 or	$9,$6
+	addu	$7,$8
+	or	$1,$30
+	addu	$7,$25
+	 xor	$10,$12
+	sll	$25,$7,5	# 17
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$10,$18
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$10,$23
+	sll	$30,$24,30
+	and	$25,$24
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$24,$24,2
+	xor	$25,$2
+	 or	$10,$6
+	addu	$3,$9
+	or	$24,$30
+	addu	$3,$25
+	 xor	$11,$13
+	sll	$25,$3,5	# 18
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$11,$19
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$11,$8
+	sll	$30,$7,30
+	and	$25,$7
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$7,$7,2
+	xor	$25,$1
+	 or	$11,$6
+	addu	$2,$10
+	or	$7,$30
+	addu	$2,$25
+	 xor	$12,$14
+	sll	$25,$2,5	# 19
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$12,$20
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$12,$9
+	sll	$30,$3,30
+	and	$25,$3
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$3,$3,2
+	xor	$25,$24
+	 or	$12,$6
+	addu	$1,$11
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0x6ed9
+	ori	$31,0xeba1	# K_20_39
+	 xor	$13,$15
+	sll	$25,$1,5	# 20
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$13,$21
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$13,$10
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$2,$2,2
+	addu	$24,$12
+	 or	$13,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$14,$16
+	sll	$25,$24,5	# 21
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$14,$22
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$14,$11
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$1,$1,2
+	addu	$7,$13
+	 or	$14,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$15,$17
+	sll	$25,$7,5	# 22
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$15,$23
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$15,$12
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$24,$24,2
+	addu	$3,$14
+	 or	$15,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$16,$18
+	sll	$25,$3,5	# 23
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$16,$8
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$16,$13
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$7,$7,2
+	addu	$2,$15
+	 or	$16,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$17,$19
+	sll	$25,$2,5	# 24
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$17,$9
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$17,$14
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$17,31
+	 addu	$17,$17
+	srl	$3,$3,2
+	addu	$1,$16
+	 or	$17,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$18,$20
+	sll	$25,$1,5	# 25
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$18,$10
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$18,$15
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$18,31
+	 addu	$18,$18
+	srl	$2,$2,2
+	addu	$24,$17
+	 or	$18,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$19,$21
+	sll	$25,$24,5	# 26
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$19,$11
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$19,$16
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$19,31
+	 addu	$19,$19
+	srl	$1,$1,2
+	addu	$7,$18
+	 or	$19,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$20,$22
+	sll	$25,$7,5	# 27
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$20,$12
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$20,$17
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$20,31
+	 addu	$20,$20
+	srl	$24,$24,2
+	addu	$3,$19
+	 or	$20,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$21,$23
+	sll	$25,$3,5	# 28
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$21,$13
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$21,$18
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$7,$7,2
+	addu	$2,$20
+	 or	$21,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$22,$8
+	sll	$25,$2,5	# 29
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$22,$14
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$22,$19
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$3,$3,2
+	addu	$1,$21
+	 or	$22,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$23,$9
+	sll	$25,$1,5	# 30
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$23,$15
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$23,$20
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$2,$2,2
+	addu	$24,$22
+	 or	$23,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$8,$10
+	sll	$25,$24,5	# 31
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$8,$16
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$8,$21
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$1,$1,2
+	addu	$7,$23
+	 or	$8,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$9,$11
+	sll	$25,$7,5	# 32
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$9,$17
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$9,$22
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$24,$24,2
+	addu	$3,$8
+	 or	$9,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$10,$12
+	sll	$25,$3,5	# 33
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$10,$18
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$10,$23
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$7,$7,2
+	addu	$2,$9
+	 or	$10,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$11,$13
+	sll	$25,$2,5	# 34
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$11,$19
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$11,$8
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$3,$3,2
+	addu	$1,$10
+	 or	$11,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$12,$14
+	sll	$25,$1,5	# 35
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$12,$20
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$12,$9
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$2,$2,2
+	addu	$24,$11
+	 or	$12,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$13,$15
+	sll	$25,$24,5	# 36
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$13,$21
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$13,$10
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$1,$1,2
+	addu	$7,$12
+	 or	$13,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$14,$16
+	sll	$25,$7,5	# 37
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$14,$22
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$14,$11
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$24,$24,2
+	addu	$3,$13
+	 or	$14,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$15,$17
+	sll	$25,$3,5	# 38
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$15,$23
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$15,$12
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$7,$7,2
+	addu	$2,$14
+	 or	$15,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$16,$18
+	sll	$25,$2,5	# 39
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$16,$8
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$16,$13
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$3,$3,2
+	addu	$1,$15
+	 or	$16,$6
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0x8f1b
+	ori	$31,0xbcdc	# K_40_59
+	 xor	$17,$19
+	sll	$25,$1,5	# 40
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$17,$9
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$17,$14
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$17,31
+	xor	$25,$3,$7
+	 addu	$17,$17
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$17,$6
+	addu	$24,$16
+	or	$2,$30
+	addu	$24,$25
+	 xor	$18,$20
+	sll	$25,$24,5	# 41
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$18,$10
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$18,$15
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$18,31
+	xor	$25,$2,$3
+	 addu	$18,$18
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$18,$6
+	addu	$7,$17
+	or	$1,$30
+	addu	$7,$25
+	 xor	$19,$21
+	sll	$25,$7,5	# 42
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$19,$11
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$19,$16
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$19,31
+	xor	$25,$1,$2
+	 addu	$19,$19
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$19,$6
+	addu	$3,$18
+	or	$24,$30
+	addu	$3,$25
+	 xor	$20,$22
+	sll	$25,$3,5	# 43
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$20,$12
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$20,$17
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$20,31
+	xor	$25,$24,$1
+	 addu	$20,$20
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$20,$6
+	addu	$2,$19
+	or	$7,$30
+	addu	$2,$25
+	 xor	$21,$23
+	sll	$25,$2,5	# 44
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$21,$13
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$21,$18
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$21,31
+	xor	$25,$7,$24
+	 addu	$21,$21
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$21,$6
+	addu	$1,$20
+	or	$3,$30
+	addu	$1,$25
+	 xor	$22,$8
+	sll	$25,$1,5	# 45
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$22,$14
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$22,$19
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$22,31
+	xor	$25,$3,$7
+	 addu	$22,$22
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$22,$6
+	addu	$24,$21
+	or	$2,$30
+	addu	$24,$25
+	 xor	$23,$9
+	sll	$25,$24,5	# 46
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$23,$15
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$23,$20
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$23,31
+	xor	$25,$2,$3
+	 addu	$23,$23
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$23,$6
+	addu	$7,$22
+	or	$1,$30
+	addu	$7,$25
+	 xor	$8,$10
+	sll	$25,$7,5	# 47
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$8,$16
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$8,$21
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$8,31
+	xor	$25,$1,$2
+	 addu	$8,$8
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$8,$6
+	addu	$3,$23
+	or	$24,$30
+	addu	$3,$25
+	 xor	$9,$11
+	sll	$25,$3,5	# 48
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$9,$17
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$9,$22
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$9,31
+	xor	$25,$24,$1
+	 addu	$9,$9
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$9,$6
+	addu	$2,$8
+	or	$7,$30
+	addu	$2,$25
+	 xor	$10,$12
+	sll	$25,$2,5	# 49
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$10,$18
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$10,$23
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$10,31
+	xor	$25,$7,$24
+	 addu	$10,$10
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$10,$6
+	addu	$1,$9
+	or	$3,$30
+	addu	$1,$25
+	 xor	$11,$13
+	sll	$25,$1,5	# 50
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$11,$19
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$11,$8
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$11,31
+	xor	$25,$3,$7
+	 addu	$11,$11
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$11,$6
+	addu	$24,$10
+	or	$2,$30
+	addu	$24,$25
+	 xor	$12,$14
+	sll	$25,$24,5	# 51
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$12,$20
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$12,$9
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$12,31
+	xor	$25,$2,$3
+	 addu	$12,$12
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$12,$6
+	addu	$7,$11
+	or	$1,$30
+	addu	$7,$25
+	 xor	$13,$15
+	sll	$25,$7,5	# 52
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$13,$21
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$13,$10
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$13,31
+	xor	$25,$1,$2
+	 addu	$13,$13
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$13,$6
+	addu	$3,$12
+	or	$24,$30
+	addu	$3,$25
+	 xor	$14,$16
+	sll	$25,$3,5	# 53
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$14,$22
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$14,$11
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$14,31
+	xor	$25,$24,$1
+	 addu	$14,$14
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$14,$6
+	addu	$2,$13
+	or	$7,$30
+	addu	$2,$25
+	 xor	$15,$17
+	sll	$25,$2,5	# 54
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$15,$23
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$15,$12
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$15,31
+	xor	$25,$7,$24
+	 addu	$15,$15
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$15,$6
+	addu	$1,$14
+	or	$3,$30
+	addu	$1,$25
+	 xor	$16,$18
+	sll	$25,$1,5	# 55
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$16,$8
+	and	$25,$3,$7
+	addu	$24,$6
+	 xor	$16,$13
+	sll	$30,$2,30
+	addu	$24,$25
+	 srl	$6,$16,31
+	xor	$25,$3,$7
+	 addu	$16,$16
+	and	$25,$2
+	srl	$2,$2,2
+	 or	$16,$6
+	addu	$24,$15
+	or	$2,$30
+	addu	$24,$25
+	 xor	$17,$19
+	sll	$25,$24,5	# 56
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$17,$9
+	and	$25,$2,$3
+	addu	$7,$6
+	 xor	$17,$14
+	sll	$30,$1,30
+	addu	$7,$25
+	 srl	$6,$17,31
+	xor	$25,$2,$3
+	 addu	$17,$17
+	and	$25,$1
+	srl	$1,$1,2
+	 or	$17,$6
+	addu	$7,$16
+	or	$1,$30
+	addu	$7,$25
+	 xor	$18,$20
+	sll	$25,$7,5	# 57
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$18,$10
+	and	$25,$1,$2
+	addu	$3,$6
+	 xor	$18,$15
+	sll	$30,$24,30
+	addu	$3,$25
+	 srl	$6,$18,31
+	xor	$25,$1,$2
+	 addu	$18,$18
+	and	$25,$24
+	srl	$24,$24,2
+	 or	$18,$6
+	addu	$3,$17
+	or	$24,$30
+	addu	$3,$25
+	 xor	$19,$21
+	sll	$25,$3,5	# 58
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$19,$11
+	and	$25,$24,$1
+	addu	$2,$6
+	 xor	$19,$16
+	sll	$30,$7,30
+	addu	$2,$25
+	 srl	$6,$19,31
+	xor	$25,$24,$1
+	 addu	$19,$19
+	and	$25,$7
+	srl	$7,$7,2
+	 or	$19,$6
+	addu	$2,$18
+	or	$7,$30
+	addu	$2,$25
+	 xor	$20,$22
+	sll	$25,$2,5	# 59
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$20,$12
+	and	$25,$7,$24
+	addu	$1,$6
+	 xor	$20,$17
+	sll	$30,$3,30
+	addu	$1,$25
+	 srl	$6,$20,31
+	xor	$25,$7,$24
+	 addu	$20,$20
+	and	$25,$3
+	srl	$3,$3,2
+	 or	$20,$6
+	addu	$1,$19
+	or	$3,$30
+	addu	$1,$25
+	lui	$31,0xca62
+	ori	$31,0xc1d6	# K_60_79
+	 xor	$21,$23
+	sll	$25,$1,5	# 60
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$21,$13
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$21,$18
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$2,$2,2
+	addu	$24,$20
+	 or	$21,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$22,$8
+	sll	$25,$24,5	# 61
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$22,$14
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$22,$19
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$1,$1,2
+	addu	$7,$21
+	 or	$22,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$23,$9
+	sll	$25,$7,5	# 62
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$23,$15
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$23,$20
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$24,$24,2
+	addu	$3,$22
+	 or	$23,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$8,$10
+	sll	$25,$3,5	# 63
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$8,$16
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$8,$21
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$8,31
+	 addu	$8,$8
+	srl	$7,$7,2
+	addu	$2,$23
+	 or	$8,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$9,$11
+	sll	$25,$2,5	# 64
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$9,$17
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$9,$22
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$9,31
+	 addu	$9,$9
+	srl	$3,$3,2
+	addu	$1,$8
+	 or	$9,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$10,$12
+	sll	$25,$1,5	# 65
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$10,$18
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$10,$23
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$10,31
+	 addu	$10,$10
+	srl	$2,$2,2
+	addu	$24,$9
+	 or	$10,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$11,$13
+	sll	$25,$24,5	# 66
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$11,$19
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$11,$8
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$11,31
+	 addu	$11,$11
+	srl	$1,$1,2
+	addu	$7,$10
+	 or	$11,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$12,$14
+	sll	$25,$7,5	# 67
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$12,$20
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$12,$9
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$12,31
+	 addu	$12,$12
+	srl	$24,$24,2
+	addu	$3,$11
+	 or	$12,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$13,$15
+	sll	$25,$3,5	# 68
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$13,$21
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$13,$10
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$13,31
+	 addu	$13,$13
+	srl	$7,$7,2
+	addu	$2,$12
+	 or	$13,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$14,$16
+	sll	$25,$2,5	# 69
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$14,$22
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$14,$11
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$14,31
+	 addu	$14,$14
+	srl	$3,$3,2
+	addu	$1,$13
+	 or	$14,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$15,$17
+	sll	$25,$1,5	# 70
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$15,$23
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$15,$12
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$15,31
+	 addu	$15,$15
+	srl	$2,$2,2
+	addu	$24,$14
+	 or	$15,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$16,$18
+	sll	$25,$24,5	# 71
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$16,$8
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$16,$13
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$16,31
+	 addu	$16,$16
+	srl	$1,$1,2
+	addu	$7,$15
+	 or	$16,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$17,$19
+	sll	$25,$7,5	# 72
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$17,$9
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$17,$14
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$17,31
+	 addu	$17,$17
+	srl	$24,$24,2
+	addu	$3,$16
+	 or	$17,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$18,$20
+	sll	$25,$3,5	# 73
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$18,$10
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$18,$15
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$18,31
+	 addu	$18,$18
+	srl	$7,$7,2
+	addu	$2,$17
+	 or	$18,$6
+	or	$7,$30
+	addu	$2,$25
+	 xor	$19,$21
+	sll	$25,$2,5	# 74
+	addu	$1,$31
+	srl	$6,$2,27
+	addu	$1,$25
+	 xor	$19,$11
+	xor	$25,$7,$24
+	addu	$1,$6
+	 xor	$19,$16
+	sll	$30,$3,30
+	xor	$25,$3
+	 srl	$6,$19,31
+	 addu	$19,$19
+	srl	$3,$3,2
+	addu	$1,$18
+	 or	$19,$6
+	or	$3,$30
+	addu	$1,$25
+	 xor	$20,$22
+	sll	$25,$1,5	# 75
+	addu	$24,$31
+	srl	$6,$1,27
+	addu	$24,$25
+	 xor	$20,$12
+	xor	$25,$3,$7
+	addu	$24,$6
+	 xor	$20,$17
+	sll	$30,$2,30
+	xor	$25,$2
+	 srl	$6,$20,31
+	 addu	$20,$20
+	srl	$2,$2,2
+	addu	$24,$19
+	 or	$20,$6
+	or	$2,$30
+	addu	$24,$25
+	 xor	$21,$23
+	sll	$25,$24,5	# 76
+	addu	$7,$31
+	srl	$6,$24,27
+	addu	$7,$25
+	 xor	$21,$13
+	xor	$25,$2,$3
+	addu	$7,$6
+	 xor	$21,$18
+	sll	$30,$1,30
+	xor	$25,$1
+	 srl	$6,$21,31
+	 addu	$21,$21
+	srl	$1,$1,2
+	addu	$7,$20
+	 or	$21,$6
+	or	$1,$30
+	addu	$7,$25
+	 xor	$22,$8
+	sll	$25,$7,5	# 77
+	addu	$3,$31
+	srl	$6,$7,27
+	addu	$3,$25
+	 xor	$22,$14
+	xor	$25,$1,$2
+	addu	$3,$6
+	 xor	$22,$19
+	sll	$30,$24,30
+	xor	$25,$24
+	 srl	$6,$22,31
+	 addu	$22,$22
+	srl	$24,$24,2
+	addu	$3,$21
+	 or	$22,$6
+	or	$24,$30
+	addu	$3,$25
+	 xor	$23,$9
+	sll	$25,$3,5	# 78
+	addu	$2,$31
+	srl	$6,$3,27
+	addu	$2,$25
+	 xor	$23,$15
+	xor	$25,$24,$1
+	addu	$2,$6
+	 xor	$23,$20
+	sll	$30,$7,30
+	xor	$25,$7
+	 srl	$6,$23,31
+	 addu	$23,$23
+	srl	$7,$7,2
+	addu	$2,$22
+	 or	$23,$6
+	or	$7,$30
+	addu	$2,$25
+	 lw	$8,0($4)
+	sll	$25,$2,5	# 79
+	addu	$1,$31
+	 lw	$9,4($4)
+	srl	$6,$2,27
+	addu	$1,$25
+	 lw	$10,8($4)
+	xor	$25,$7,$24
+	addu	$1,$6
+	 lw	$11,12($4)
+	sll	$30,$3,30
+	xor	$25,$3
+	 lw	$12,16($4)
+	srl	$3,$3,2
+	addu	$1,$23
+	or	$3,$30
+	addu	$1,$25
+	dadd $5,64
+	ld	$6,0($29)
+
+	addu	$1,$8
+	addu	$2,$9
+	sw	$1,0($4)
+	addu	$3,$10
+	addu	$7,$11
+	sw	$2,4($4)
+	addu	$24,$12
+	sw	$3,8($4)
+	sw	$7,12($4)
+	sw	$24,16($4)
+	.set	noreorder
+	bne	$5,$6,.Loop
+	nop
+
+	.set	noreorder
+	ld	$31,(16-1)*8($29)
+	ld	$30,(16-2)*8($29)
+	ld	$23,(16-3)*8($29)
+	ld	$22,(16-4)*8($29)
+	ld	$21,(16-5)*8($29)
+	ld	$20,(16-6)*8($29)
+	ld	$19,(16-7)*8($29)
+	ld	$18,(16-8)*8($29)
+	ld	$17,(16-9)*8($29)
+	ld	$16,(16-10)*8($29)
+	jr	$31
+	dadd $29,16*8
+.end	sha1_block_data_order
+.rdata
+.asciiz	"SHA1 for MIPS, CRYPTOGAMS by "
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha1.c b/crypto/sha/sha1.c
new file mode 100644
index 0000000..4b48653
--- /dev/null
+++ b/crypto/sha/sha1.c
@@ -0,0 +1,476 @@
+/* $OpenBSD: sha1.c,v 1.12 2023/08/10 07:15:23 jsing Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#if !defined(OPENSSL_NO_SHA1) && !defined(OPENSSL_NO_SHA)
+
+#define DATA_ORDER_IS_BIG_ENDIAN
+
+#define HASH_LONG               SHA_LONG
+#define HASH_CTX                SHA_CTX
+#define HASH_CBLOCK             SHA_CBLOCK
+
+#define HASH_BLOCK_DATA_ORDER   	sha1_block_data_order
+#define Xupdate(a, ix, ia, ib, ic, id)	( (a)=(ia^ib^ic^id),	\
+					  ix=(a)=ROTATE((a),1)	\
+					)
+
+#ifndef SHA1_ASM
+static
+#endif
+void sha1_block_data_order(SHA_CTX *c, const void *p, size_t num);
+
+#define HASH_NO_UPDATE
+#define HASH_NO_TRANSFORM
+#define HASH_NO_FINAL
+
+#include "md32_common.h"
+
+#define K_00_19	0x5a827999UL
+#define K_20_39 0x6ed9eba1UL
+#define K_40_59 0x8f1bbcdcUL
+#define K_60_79 0xca62c1d6UL
+
+/* As  pointed out by Wei Dai , F() below can be
+ * simplified to the code in F_00_19.  Wei attributes these optimisations
+ * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
+ * #define F(x,y,z) (((x) & (y))  |  ((~(x)) & (z)))
+ * I've just become aware of another tweak to be made, again from Wei Dai,
+ * in F_40_59, (x&a)|(y&a) -> (x|y)&a
+ */
+#define	F_00_19(b, c, d)	((((c) ^ (d)) & (b)) ^ (d))
+#define	F_20_39(b, c, d)	((b) ^ (c) ^ (d))
+#define F_40_59(b, c, d)	(((b) & (c)) | (((b)|(c)) & (d)))
+#define	F_60_79(b, c, d)	F_20_39(b, c, d)
+
+
+#define BODY_00_15(i, a, b, c, d, e, f, xi) \
+	(f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd) \
+	Xupdate(f, xi, xa, xb, xc, xd); \
+	(f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd) \
+	Xupdate(f, xi, xa, xb, xc, xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd) \
+	Xupdate(f, xa, xa, xb, xc, xd); \
+	(f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd) \
+	Xupdate(f, xa, xa, xb, xc, xd); \
+	(f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd) \
+	Xupdate(f, xa, xa, xb, xc, xd); \
+	(f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \
+	(b)=ROTATE((b),30);
+
+#if !defined(SHA1_ASM)
+#include 
+static void
+sha1_block_data_order(SHA_CTX *c, const void *p, size_t num)
+{
+	const unsigned char *data = p;
+	unsigned int A, B, C, D, E, T, l;
+	unsigned int X0, X1, X2, X3, X4, X5, X6, X7,
+	    X8, X9, X10, X11, X12, X13, X14, X15;
+
+	A = c->h0;
+	B = c->h1;
+	C = c->h2;
+	D = c->h3;
+	E = c->h4;
+
+	for (;;) {
+
+		if (BYTE_ORDER != LITTLE_ENDIAN &&
+		    sizeof(SHA_LONG) == 4 && ((size_t)p % 4) == 0) {
+			const SHA_LONG *W = (const SHA_LONG *)data;
+
+			X0 = W[0];
+			X1 = W[1];
+			BODY_00_15( 0, A, B, C, D, E, T, X0);
+			X2 = W[2];
+			BODY_00_15( 1, T, A, B, C, D, E, X1);
+			X3 = W[3];
+			BODY_00_15( 2, E, T, A, B, C, D, X2);
+			X4 = W[4];
+			BODY_00_15( 3, D, E, T, A, B, C, X3);
+			X5 = W[5];
+			BODY_00_15( 4, C, D, E, T, A, B, X4);
+			X6 = W[6];
+			BODY_00_15( 5, B, C, D, E, T, A, X5);
+			X7 = W[7];
+			BODY_00_15( 6, A, B, C, D, E, T, X6);
+			X8 = W[8];
+			BODY_00_15( 7, T, A, B, C, D, E, X7);
+			X9 = W[9];
+			BODY_00_15( 8, E, T, A, B, C, D, X8);
+			X10 = W[10];
+			BODY_00_15( 9, D, E, T, A, B, C, X9);
+			X11 = W[11];
+			BODY_00_15(10, C, D, E, T, A, B, X10);
+			X12 = W[12];
+			BODY_00_15(11, B, C, D, E, T, A, X11);
+			X13 = W[13];
+			BODY_00_15(12, A, B, C, D, E, T, X12);
+			X14 = W[14];
+			BODY_00_15(13, T, A, B, C, D, E, X13);
+			X15 = W[15];
+			BODY_00_15(14, E, T, A, B, C, D, X14);
+			BODY_00_15(15, D, E, T, A, B, C, X15);
+
+			data += SHA_CBLOCK;
+		} else {
+			HOST_c2l(data, l);
+			X0 = l;
+			HOST_c2l(data, l);
+			X1 = l;
+			BODY_00_15( 0, A, B, C, D, E, T, X0);
+			HOST_c2l(data, l);
+			X2 = l;
+			BODY_00_15( 1, T, A, B, C, D, E, X1);
+			HOST_c2l(data, l);
+			X3 = l;
+			BODY_00_15( 2, E, T, A, B, C, D, X2);
+			HOST_c2l(data, l);
+			X4 = l;
+			BODY_00_15( 3, D, E, T, A, B, C, X3);
+			HOST_c2l(data, l);
+			X5 = l;
+			BODY_00_15( 4, C, D, E, T, A, B, X4);
+			HOST_c2l(data, l);
+			X6 = l;
+			BODY_00_15( 5, B, C, D, E, T, A, X5);
+			HOST_c2l(data, l);
+			X7 = l;
+			BODY_00_15( 6, A, B, C, D, E, T, X6);
+			HOST_c2l(data, l);
+			X8 = l;
+			BODY_00_15( 7, T, A, B, C, D, E, X7);
+			HOST_c2l(data, l);
+			X9 = l;
+			BODY_00_15( 8, E, T, A, B, C, D, X8);
+			HOST_c2l(data, l);
+			X10 = l;
+			BODY_00_15( 9, D, E, T, A, B, C, X9);
+			HOST_c2l(data, l);
+			X11 = l;
+			BODY_00_15(10, C, D, E, T, A, B, X10);
+			HOST_c2l(data, l);
+			X12 = l;
+			BODY_00_15(11, B, C, D, E, T, A, X11);
+			HOST_c2l(data, l);
+			X13 = l;
+			BODY_00_15(12, A, B, C, D, E, T, X12);
+			HOST_c2l(data, l);
+			X14 = l;
+			BODY_00_15(13, T, A, B, C, D, E, X13);
+			HOST_c2l(data, l);
+			X15 = l;
+			BODY_00_15(14, E, T, A, B, C, D, X14);
+			BODY_00_15(15, D, E, T, A, B, C, X15);
+		}
+
+		BODY_16_19(16, C, D, E, T, A, B, X0, X0, X2, X8, X13);
+		BODY_16_19(17, B, C, D, E, T, A, X1, X1, X3, X9, X14);
+		BODY_16_19(18, A, B, C, D, E, T, X2, X2, X4, X10, X15);
+		BODY_16_19(19, T, A, B, C, D, E, X3, X3, X5, X11, X0);
+
+		BODY_20_31(20, E, T, A, B, C, D, X4, X4, X6, X12, X1);
+		BODY_20_31(21, D, E, T, A, B, C, X5, X5, X7, X13, X2);
+		BODY_20_31(22, C, D, E, T, A, B, X6, X6, X8, X14, X3);
+		BODY_20_31(23, B, C, D, E, T, A, X7, X7, X9, X15, X4);
+		BODY_20_31(24, A, B, C, D, E, T, X8, X8, X10, X0, X5);
+		BODY_20_31(25, T, A, B, C, D, E, X9, X9, X11, X1, X6);
+		BODY_20_31(26, E, T, A, B, C, D, X10, X10, X12, X2, X7);
+		BODY_20_31(27, D, E, T, A, B, C, X11, X11, X13, X3, X8);
+		BODY_20_31(28, C, D, E, T, A, B, X12, X12, X14, X4, X9);
+		BODY_20_31(29, B, C, D, E, T, A, X13, X13, X15, X5, X10);
+		BODY_20_31(30, A, B, C, D, E, T, X14, X14, X0, X6, X11);
+		BODY_20_31(31, T, A, B, C, D, E, X15, X15, X1, X7, X12);
+
+		BODY_32_39(32, E, T, A, B, C, D, X0, X2, X8, X13);
+		BODY_32_39(33, D, E, T, A, B, C, X1, X3, X9, X14);
+		BODY_32_39(34, C, D, E, T, A, B, X2, X4, X10, X15);
+		BODY_32_39(35, B, C, D, E, T, A, X3, X5, X11, X0);
+		BODY_32_39(36, A, B, C, D, E, T, X4, X6, X12, X1);
+		BODY_32_39(37, T, A, B, C, D, E, X5, X7, X13, X2);
+		BODY_32_39(38, E, T, A, B, C, D, X6, X8, X14, X3);
+		BODY_32_39(39, D, E, T, A, B, C, X7, X9, X15, X4);
+
+		BODY_40_59(40, C, D, E, T, A, B, X8, X10, X0, X5);
+		BODY_40_59(41, B, C, D, E, T, A, X9, X11, X1, X6);
+		BODY_40_59(42, A, B, C, D, E, T, X10, X12, X2, X7);
+		BODY_40_59(43, T, A, B, C, D, E, X11, X13, X3, X8);
+		BODY_40_59(44, E, T, A, B, C, D, X12, X14, X4, X9);
+		BODY_40_59(45, D, E, T, A, B, C, X13, X15, X5, X10);
+		BODY_40_59(46, C, D, E, T, A, B, X14, X0, X6, X11);
+		BODY_40_59(47, B, C, D, E, T, A, X15, X1, X7, X12);
+		BODY_40_59(48, A, B, C, D, E, T, X0, X2, X8, X13);
+		BODY_40_59(49, T, A, B, C, D, E, X1, X3, X9, X14);
+		BODY_40_59(50, E, T, A, B, C, D, X2, X4, X10, X15);
+		BODY_40_59(51, D, E, T, A, B, C, X3, X5, X11, X0);
+		BODY_40_59(52, C, D, E, T, A, B, X4, X6, X12, X1);
+		BODY_40_59(53, B, C, D, E, T, A, X5, X7, X13, X2);
+		BODY_40_59(54, A, B, C, D, E, T, X6, X8, X14, X3);
+		BODY_40_59(55, T, A, B, C, D, E, X7, X9, X15, X4);
+		BODY_40_59(56, E, T, A, B, C, D, X8, X10, X0, X5);
+		BODY_40_59(57, D, E, T, A, B, C, X9, X11, X1, X6);
+		BODY_40_59(58, C, D, E, T, A, B, X10, X12, X2, X7);
+		BODY_40_59(59, B, C, D, E, T, A, X11, X13, X3, X8);
+
+		BODY_60_79(60, A, B, C, D, E, T, X12, X14, X4, X9);
+		BODY_60_79(61, T, A, B, C, D, E, X13, X15, X5, X10);
+		BODY_60_79(62, E, T, A, B, C, D, X14, X0, X6, X11);
+		BODY_60_79(63, D, E, T, A, B, C, X15, X1, X7, X12);
+		BODY_60_79(64, C, D, E, T, A, B, X0, X2, X8, X13);
+		BODY_60_79(65, B, C, D, E, T, A, X1, X3, X9, X14);
+		BODY_60_79(66, A, B, C, D, E, T, X2, X4, X10, X15);
+		BODY_60_79(67, T, A, B, C, D, E, X3, X5, X11, X0);
+		BODY_60_79(68, E, T, A, B, C, D, X4, X6, X12, X1);
+		BODY_60_79(69, D, E, T, A, B, C, X5, X7, X13, X2);
+		BODY_60_79(70, C, D, E, T, A, B, X6, X8, X14, X3);
+		BODY_60_79(71, B, C, D, E, T, A, X7, X9, X15, X4);
+		BODY_60_79(72, A, B, C, D, E, T, X8, X10, X0, X5);
+		BODY_60_79(73, T, A, B, C, D, E, X9, X11, X1, X6);
+		BODY_60_79(74, E, T, A, B, C, D, X10, X12, X2, X7);
+		BODY_60_79(75, D, E, T, A, B, C, X11, X13, X3, X8);
+		BODY_60_79(76, C, D, E, T, A, B, X12, X14, X4, X9);
+		BODY_60_79(77, B, C, D, E, T, A, X13, X15, X5, X10);
+		BODY_60_79(78, A, B, C, D, E, T, X14, X0, X6, X11);
+		BODY_60_79(79, T, A, B, C, D, E, X15, X1, X7, X12);
+
+		c->h0 = (c->h0 + E)&0xffffffffL;
+		c->h1 = (c->h1 + T)&0xffffffffL;
+		c->h2 = (c->h2 + A)&0xffffffffL;
+		c->h3 = (c->h3 + B)&0xffffffffL;
+		c->h4 = (c->h4 + C)&0xffffffffL;
+
+		if (--num == 0)
+			break;
+
+		A = c->h0;
+		B = c->h1;
+		C = c->h2;
+		D = c->h3;
+		E = c->h4;
+
+	}
+}
+#endif
+
+
+int
+SHA1_Init(SHA_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->h0 = 0x67452301UL;
+	c->h1 = 0xefcdab89UL;
+	c->h2 = 0x98badcfeUL;
+	c->h3 = 0x10325476UL;
+	c->h4 = 0xc3d2e1f0UL;
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA1_Init);
+
+int
+SHA1_Update(SHA_CTX *c, const void *data_, size_t len)
+{
+	const unsigned char *data = data_;
+	unsigned char *p;
+	SHA_LONG l;
+	size_t n;
+
+	if (len == 0)
+		return 1;
+
+	l = (c->Nl + (((SHA_LONG)len) << 3))&0xffffffffUL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai  for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh+=(SHA_LONG)(len>>29);	/* might cause compiler warning on 16-bit */
+	c->Nl = l;
+
+	n = c->num;
+	if (n != 0) {
+		p = (unsigned char *)c->data;
+
+		if (len >= SHA_CBLOCK || len + n >= SHA_CBLOCK) {
+			memcpy(p + n, data, SHA_CBLOCK - n);
+			sha1_block_data_order(c, p, 1);
+			n = SHA_CBLOCK - n;
+			data += n;
+			len -= n;
+			c->num = 0;
+			memset(p,0,SHA_CBLOCK);	/* keep it zeroed */
+		} else {
+			memcpy(p + n, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		}
+	}
+
+	n = len/SHA_CBLOCK;
+	if (n > 0) {
+		sha1_block_data_order(c, data, n);
+		n    *= SHA_CBLOCK;
+		data += n;
+		len -= n;
+	}
+
+	if (len != 0) {
+		p = (unsigned char *)c->data;
+		c->num = (unsigned int)len;
+		memcpy(p, data, len);
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(SHA1_Update);
+
+void
+SHA1_Transform(SHA_CTX *c, const unsigned char *data)
+{
+	sha1_block_data_order(c, data, 1);
+}
+LCRYPTO_ALIAS(SHA1_Transform);
+
+int
+SHA1_Final(unsigned char *md, SHA_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	unsigned long ll;
+	size_t n = c->num;
+
+	p[n] = 0x80; /* there is always room for one */
+	n++;
+
+	if (n > (SHA_CBLOCK - 8)) {
+		memset(p + n, 0, SHA_CBLOCK - n);
+		n = 0;
+		sha1_block_data_order(c, p, 1);
+	}
+	memset(p + n, 0, SHA_CBLOCK - 8 - n);
+
+	p += SHA_CBLOCK - 8;
+#if   defined(DATA_ORDER_IS_BIG_ENDIAN)
+	HOST_l2c(c->Nh, p);
+	HOST_l2c(c->Nl, p);
+#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
+	HOST_l2c(c->Nl, p);
+	HOST_l2c(c->Nh, p);
+#endif
+	p -= SHA_CBLOCK;
+	sha1_block_data_order(c, p, 1);
+	c->num = 0;
+	memset(p, 0, SHA_CBLOCK);
+
+	ll = c->h0;
+	HOST_l2c(ll, md);
+	ll = c->h1;
+	HOST_l2c(ll, md);
+	ll = c->h2;
+	HOST_l2c(ll, md);
+	ll = c->h3;
+	HOST_l2c(ll, md);
+	ll = c->h4;
+	HOST_l2c(ll, md);
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA1_Final);
+
+unsigned char *
+SHA1(const unsigned char *d, size_t n, unsigned char *md)
+{
+	SHA_CTX c;
+	static unsigned char m[SHA_DIGEST_LENGTH];
+
+	if (md == NULL)
+		md = m;
+
+	if (!SHA1_Init(&c))
+		return NULL;
+	SHA1_Update(&c, d, n);
+	SHA1_Final(md, &c);
+
+	explicit_bzero(&c, sizeof(c));
+
+	return (md);
+}
+LCRYPTO_ALIAS(SHA1);
+
+#endif
diff --git a/crypto/sha/sha256-elf-armv4.S b/crypto/sha/sha256-elf-armv4.S
new file mode 100644
index 0000000..9b155c7
--- /dev/null
+++ b/crypto/sha/sha256-elf-armv4.S
@@ -0,0 +1,1520 @@
+#include "arm_arch.h"
+
+.text
+.code	32
+
+.type	K256,%object
+.align	5
+K256:
+.word	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.word	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.word	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.word	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.word	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.word	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.word	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.word	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.word	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.word	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.word	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.word	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.word	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.word	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.word	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.word	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.size	K256,.-K256
+
+.global	sha256_block_data_order
+.type	sha256_block_data_order,%function
+sha256_block_data_order:
+	sub	r3,pc,#8		@ sha256_block_data_order
+	add	r2,r1,r2,lsl#6	@ len to point at the end of inp
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+	ldmia	r0,{r4,r5,r6,r7,r8,r9,r10,r11}
+	sub	r14,r3,#256		@ K256
+	sub	sp,sp,#16*4		@ alloca(X[16])
+.Loop:
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 0
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r8,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r8,ror#11
+	eor	r2,r9,r10
+#if 0>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 0==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r8,ror#25	@ Sigma1(e)
+	and	r2,r2,r8
+	str	r3,[sp,#0*4]
+	add	r3,r3,r0
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	add	r3,r3,r11
+	mov	r11,r4,ror#2
+	add	r3,r3,r2
+	eor	r11,r11,r4,ror#13
+	add	r3,r3,r12
+	eor	r11,r11,r4,ror#22		@ Sigma0(a)
+#if 0>=15
+	ldr	r1,[sp,#2*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r4,r5
+	and	r2,r4,r5
+	and	r0,r0,r6
+	add	r11,r11,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r7,r7,r3
+	add	r11,r11,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 1
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r7,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r7,ror#11
+	eor	r2,r8,r9
+#if 1>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 1==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r7,ror#25	@ Sigma1(e)
+	and	r2,r2,r7
+	str	r3,[sp,#1*4]
+	add	r3,r3,r0
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	add	r3,r3,r10
+	mov	r10,r11,ror#2
+	add	r3,r3,r2
+	eor	r10,r10,r11,ror#13
+	add	r3,r3,r12
+	eor	r10,r10,r11,ror#22		@ Sigma0(a)
+#if 1>=15
+	ldr	r1,[sp,#3*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r11,r4
+	and	r2,r11,r4
+	and	r0,r0,r5
+	add	r10,r10,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r6,r6,r3
+	add	r10,r10,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 2
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r6,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r6,ror#11
+	eor	r2,r7,r8
+#if 2>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 2==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r6,ror#25	@ Sigma1(e)
+	and	r2,r2,r6
+	str	r3,[sp,#2*4]
+	add	r3,r3,r0
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	add	r3,r3,r9
+	mov	r9,r10,ror#2
+	add	r3,r3,r2
+	eor	r9,r9,r10,ror#13
+	add	r3,r3,r12
+	eor	r9,r9,r10,ror#22		@ Sigma0(a)
+#if 2>=15
+	ldr	r1,[sp,#4*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r10,r11
+	and	r2,r10,r11
+	and	r0,r0,r4
+	add	r9,r9,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r5,r5,r3
+	add	r9,r9,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 3
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r5,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r5,ror#11
+	eor	r2,r6,r7
+#if 3>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 3==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r5,ror#25	@ Sigma1(e)
+	and	r2,r2,r5
+	str	r3,[sp,#3*4]
+	add	r3,r3,r0
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	add	r3,r3,r8
+	mov	r8,r9,ror#2
+	add	r3,r3,r2
+	eor	r8,r8,r9,ror#13
+	add	r3,r3,r12
+	eor	r8,r8,r9,ror#22		@ Sigma0(a)
+#if 3>=15
+	ldr	r1,[sp,#5*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r9,r10
+	and	r2,r9,r10
+	and	r0,r0,r11
+	add	r8,r8,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r4,r4,r3
+	add	r8,r8,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 4
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r4,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r4,ror#11
+	eor	r2,r5,r6
+#if 4>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 4==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r4,ror#25	@ Sigma1(e)
+	and	r2,r2,r4
+	str	r3,[sp,#4*4]
+	add	r3,r3,r0
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	add	r3,r3,r7
+	mov	r7,r8,ror#2
+	add	r3,r3,r2
+	eor	r7,r7,r8,ror#13
+	add	r3,r3,r12
+	eor	r7,r7,r8,ror#22		@ Sigma0(a)
+#if 4>=15
+	ldr	r1,[sp,#6*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r8,r9
+	and	r2,r8,r9
+	and	r0,r0,r10
+	add	r7,r7,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r11,r11,r3
+	add	r7,r7,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 5
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r11,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r11,ror#11
+	eor	r2,r4,r5
+#if 5>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 5==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r11,ror#25	@ Sigma1(e)
+	and	r2,r2,r11
+	str	r3,[sp,#5*4]
+	add	r3,r3,r0
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	add	r3,r3,r6
+	mov	r6,r7,ror#2
+	add	r3,r3,r2
+	eor	r6,r6,r7,ror#13
+	add	r3,r3,r12
+	eor	r6,r6,r7,ror#22		@ Sigma0(a)
+#if 5>=15
+	ldr	r1,[sp,#7*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r7,r8
+	and	r2,r7,r8
+	and	r0,r0,r9
+	add	r6,r6,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r10,r10,r3
+	add	r6,r6,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 6
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r10,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r10,ror#11
+	eor	r2,r11,r4
+#if 6>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 6==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r10,ror#25	@ Sigma1(e)
+	and	r2,r2,r10
+	str	r3,[sp,#6*4]
+	add	r3,r3,r0
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	add	r3,r3,r5
+	mov	r5,r6,ror#2
+	add	r3,r3,r2
+	eor	r5,r5,r6,ror#13
+	add	r3,r3,r12
+	eor	r5,r5,r6,ror#22		@ Sigma0(a)
+#if 6>=15
+	ldr	r1,[sp,#8*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r6,r7
+	and	r2,r6,r7
+	and	r0,r0,r8
+	add	r5,r5,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r9,r9,r3
+	add	r5,r5,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 7
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r9,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r9,ror#11
+	eor	r2,r10,r11
+#if 7>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 7==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r9,ror#25	@ Sigma1(e)
+	and	r2,r2,r9
+	str	r3,[sp,#7*4]
+	add	r3,r3,r0
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	add	r3,r3,r4
+	mov	r4,r5,ror#2
+	add	r3,r3,r2
+	eor	r4,r4,r5,ror#13
+	add	r3,r3,r12
+	eor	r4,r4,r5,ror#22		@ Sigma0(a)
+#if 7>=15
+	ldr	r1,[sp,#9*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r5,r6
+	and	r2,r5,r6
+	and	r0,r0,r7
+	add	r4,r4,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r8,r8,r3
+	add	r4,r4,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 8
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r8,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r8,ror#11
+	eor	r2,r9,r10
+#if 8>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 8==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r8,ror#25	@ Sigma1(e)
+	and	r2,r2,r8
+	str	r3,[sp,#8*4]
+	add	r3,r3,r0
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	add	r3,r3,r11
+	mov	r11,r4,ror#2
+	add	r3,r3,r2
+	eor	r11,r11,r4,ror#13
+	add	r3,r3,r12
+	eor	r11,r11,r4,ror#22		@ Sigma0(a)
+#if 8>=15
+	ldr	r1,[sp,#10*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r4,r5
+	and	r2,r4,r5
+	and	r0,r0,r6
+	add	r11,r11,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r7,r7,r3
+	add	r11,r11,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 9
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r7,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r7,ror#11
+	eor	r2,r8,r9
+#if 9>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 9==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r7,ror#25	@ Sigma1(e)
+	and	r2,r2,r7
+	str	r3,[sp,#9*4]
+	add	r3,r3,r0
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	add	r3,r3,r10
+	mov	r10,r11,ror#2
+	add	r3,r3,r2
+	eor	r10,r10,r11,ror#13
+	add	r3,r3,r12
+	eor	r10,r10,r11,ror#22		@ Sigma0(a)
+#if 9>=15
+	ldr	r1,[sp,#11*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r11,r4
+	and	r2,r11,r4
+	and	r0,r0,r5
+	add	r10,r10,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r6,r6,r3
+	add	r10,r10,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 10
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r6,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r6,ror#11
+	eor	r2,r7,r8
+#if 10>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 10==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r6,ror#25	@ Sigma1(e)
+	and	r2,r2,r6
+	str	r3,[sp,#10*4]
+	add	r3,r3,r0
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	add	r3,r3,r9
+	mov	r9,r10,ror#2
+	add	r3,r3,r2
+	eor	r9,r9,r10,ror#13
+	add	r3,r3,r12
+	eor	r9,r9,r10,ror#22		@ Sigma0(a)
+#if 10>=15
+	ldr	r1,[sp,#12*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r10,r11
+	and	r2,r10,r11
+	and	r0,r0,r4
+	add	r9,r9,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r5,r5,r3
+	add	r9,r9,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 11
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r5,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r5,ror#11
+	eor	r2,r6,r7
+#if 11>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 11==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r5,ror#25	@ Sigma1(e)
+	and	r2,r2,r5
+	str	r3,[sp,#11*4]
+	add	r3,r3,r0
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	add	r3,r3,r8
+	mov	r8,r9,ror#2
+	add	r3,r3,r2
+	eor	r8,r8,r9,ror#13
+	add	r3,r3,r12
+	eor	r8,r8,r9,ror#22		@ Sigma0(a)
+#if 11>=15
+	ldr	r1,[sp,#13*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r9,r10
+	and	r2,r9,r10
+	and	r0,r0,r11
+	add	r8,r8,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r4,r4,r3
+	add	r8,r8,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 12
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r4,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r4,ror#11
+	eor	r2,r5,r6
+#if 12>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 12==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r4,ror#25	@ Sigma1(e)
+	and	r2,r2,r4
+	str	r3,[sp,#12*4]
+	add	r3,r3,r0
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	add	r3,r3,r7
+	mov	r7,r8,ror#2
+	add	r3,r3,r2
+	eor	r7,r7,r8,ror#13
+	add	r3,r3,r12
+	eor	r7,r7,r8,ror#22		@ Sigma0(a)
+#if 12>=15
+	ldr	r1,[sp,#14*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r8,r9
+	and	r2,r8,r9
+	and	r0,r0,r10
+	add	r7,r7,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r11,r11,r3
+	add	r7,r7,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 13
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r11,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r11,ror#11
+	eor	r2,r4,r5
+#if 13>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 13==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r11,ror#25	@ Sigma1(e)
+	and	r2,r2,r11
+	str	r3,[sp,#13*4]
+	add	r3,r3,r0
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	add	r3,r3,r6
+	mov	r6,r7,ror#2
+	add	r3,r3,r2
+	eor	r6,r6,r7,ror#13
+	add	r3,r3,r12
+	eor	r6,r6,r7,ror#22		@ Sigma0(a)
+#if 13>=15
+	ldr	r1,[sp,#15*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r7,r8
+	and	r2,r7,r8
+	and	r0,r0,r9
+	add	r6,r6,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r10,r10,r3
+	add	r6,r6,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 14
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r10,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r10,ror#11
+	eor	r2,r11,r4
+#if 14>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 14==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r10,ror#25	@ Sigma1(e)
+	and	r2,r2,r10
+	str	r3,[sp,#14*4]
+	add	r3,r3,r0
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	add	r3,r3,r5
+	mov	r5,r6,ror#2
+	add	r3,r3,r2
+	eor	r5,r5,r6,ror#13
+	add	r3,r3,r12
+	eor	r5,r5,r6,ror#22		@ Sigma0(a)
+#if 14>=15
+	ldr	r1,[sp,#0*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r6,r7
+	and	r2,r6,r7
+	and	r0,r0,r8
+	add	r5,r5,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r9,r9,r3
+	add	r5,r5,r0
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r3,[r1],#4
+#else
+	ldrb	r3,[r1,#3]			@ 15
+	ldrb	r12,[r1,#2]
+	ldrb	r2,[r1,#1]
+	ldrb	r0,[r1],#4
+	orr	r3,r3,r12,lsl#8
+	orr	r3,r3,r2,lsl#16
+	orr	r3,r3,r0,lsl#24
+#endif
+	mov	r0,r9,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r9,ror#11
+	eor	r2,r10,r11
+#if 15>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 15==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r9,ror#25	@ Sigma1(e)
+	and	r2,r2,r9
+	str	r3,[sp,#15*4]
+	add	r3,r3,r0
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	add	r3,r3,r4
+	mov	r4,r5,ror#2
+	add	r3,r3,r2
+	eor	r4,r4,r5,ror#13
+	add	r3,r3,r12
+	eor	r4,r4,r5,ror#22		@ Sigma0(a)
+#if 15>=15
+	ldr	r1,[sp,#1*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r5,r6
+	and	r2,r5,r6
+	and	r0,r0,r7
+	add	r4,r4,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r8,r8,r3
+	add	r4,r4,r0
+.Lrounds_16_xx:
+	@ ldr	r1,[sp,#1*4]		@ 16
+	ldr	r12,[sp,#14*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#0*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#9*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r8,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r8,ror#11
+	eor	r2,r9,r10
+#if 16>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 16==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r8,ror#25	@ Sigma1(e)
+	and	r2,r2,r8
+	str	r3,[sp,#0*4]
+	add	r3,r3,r0
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	add	r3,r3,r11
+	mov	r11,r4,ror#2
+	add	r3,r3,r2
+	eor	r11,r11,r4,ror#13
+	add	r3,r3,r12
+	eor	r11,r11,r4,ror#22		@ Sigma0(a)
+#if 16>=15
+	ldr	r1,[sp,#2*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r4,r5
+	and	r2,r4,r5
+	and	r0,r0,r6
+	add	r11,r11,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r7,r7,r3
+	add	r11,r11,r0
+	@ ldr	r1,[sp,#2*4]		@ 17
+	ldr	r12,[sp,#15*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#1*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#10*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r7,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r7,ror#11
+	eor	r2,r8,r9
+#if 17>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 17==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r7,ror#25	@ Sigma1(e)
+	and	r2,r2,r7
+	str	r3,[sp,#1*4]
+	add	r3,r3,r0
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	add	r3,r3,r10
+	mov	r10,r11,ror#2
+	add	r3,r3,r2
+	eor	r10,r10,r11,ror#13
+	add	r3,r3,r12
+	eor	r10,r10,r11,ror#22		@ Sigma0(a)
+#if 17>=15
+	ldr	r1,[sp,#3*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r11,r4
+	and	r2,r11,r4
+	and	r0,r0,r5
+	add	r10,r10,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r6,r6,r3
+	add	r10,r10,r0
+	@ ldr	r1,[sp,#3*4]		@ 18
+	ldr	r12,[sp,#0*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#2*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#11*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r6,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r6,ror#11
+	eor	r2,r7,r8
+#if 18>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 18==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r6,ror#25	@ Sigma1(e)
+	and	r2,r2,r6
+	str	r3,[sp,#2*4]
+	add	r3,r3,r0
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	add	r3,r3,r9
+	mov	r9,r10,ror#2
+	add	r3,r3,r2
+	eor	r9,r9,r10,ror#13
+	add	r3,r3,r12
+	eor	r9,r9,r10,ror#22		@ Sigma0(a)
+#if 18>=15
+	ldr	r1,[sp,#4*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r10,r11
+	and	r2,r10,r11
+	and	r0,r0,r4
+	add	r9,r9,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r5,r5,r3
+	add	r9,r9,r0
+	@ ldr	r1,[sp,#4*4]		@ 19
+	ldr	r12,[sp,#1*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#3*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#12*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r5,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r5,ror#11
+	eor	r2,r6,r7
+#if 19>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 19==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r5,ror#25	@ Sigma1(e)
+	and	r2,r2,r5
+	str	r3,[sp,#3*4]
+	add	r3,r3,r0
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	add	r3,r3,r8
+	mov	r8,r9,ror#2
+	add	r3,r3,r2
+	eor	r8,r8,r9,ror#13
+	add	r3,r3,r12
+	eor	r8,r8,r9,ror#22		@ Sigma0(a)
+#if 19>=15
+	ldr	r1,[sp,#5*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r9,r10
+	and	r2,r9,r10
+	and	r0,r0,r11
+	add	r8,r8,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r4,r4,r3
+	add	r8,r8,r0
+	@ ldr	r1,[sp,#5*4]		@ 20
+	ldr	r12,[sp,#2*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#4*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#13*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r4,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r4,ror#11
+	eor	r2,r5,r6
+#if 20>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 20==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r4,ror#25	@ Sigma1(e)
+	and	r2,r2,r4
+	str	r3,[sp,#4*4]
+	add	r3,r3,r0
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	add	r3,r3,r7
+	mov	r7,r8,ror#2
+	add	r3,r3,r2
+	eor	r7,r7,r8,ror#13
+	add	r3,r3,r12
+	eor	r7,r7,r8,ror#22		@ Sigma0(a)
+#if 20>=15
+	ldr	r1,[sp,#6*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r8,r9
+	and	r2,r8,r9
+	and	r0,r0,r10
+	add	r7,r7,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r11,r11,r3
+	add	r7,r7,r0
+	@ ldr	r1,[sp,#6*4]		@ 21
+	ldr	r12,[sp,#3*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#5*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#14*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r11,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r11,ror#11
+	eor	r2,r4,r5
+#if 21>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 21==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r11,ror#25	@ Sigma1(e)
+	and	r2,r2,r11
+	str	r3,[sp,#5*4]
+	add	r3,r3,r0
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	add	r3,r3,r6
+	mov	r6,r7,ror#2
+	add	r3,r3,r2
+	eor	r6,r6,r7,ror#13
+	add	r3,r3,r12
+	eor	r6,r6,r7,ror#22		@ Sigma0(a)
+#if 21>=15
+	ldr	r1,[sp,#7*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r7,r8
+	and	r2,r7,r8
+	and	r0,r0,r9
+	add	r6,r6,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r10,r10,r3
+	add	r6,r6,r0
+	@ ldr	r1,[sp,#7*4]		@ 22
+	ldr	r12,[sp,#4*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#6*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#15*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r10,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r10,ror#11
+	eor	r2,r11,r4
+#if 22>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 22==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r10,ror#25	@ Sigma1(e)
+	and	r2,r2,r10
+	str	r3,[sp,#6*4]
+	add	r3,r3,r0
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	add	r3,r3,r5
+	mov	r5,r6,ror#2
+	add	r3,r3,r2
+	eor	r5,r5,r6,ror#13
+	add	r3,r3,r12
+	eor	r5,r5,r6,ror#22		@ Sigma0(a)
+#if 22>=15
+	ldr	r1,[sp,#8*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r6,r7
+	and	r2,r6,r7
+	and	r0,r0,r8
+	add	r5,r5,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r9,r9,r3
+	add	r5,r5,r0
+	@ ldr	r1,[sp,#8*4]		@ 23
+	ldr	r12,[sp,#5*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#7*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#0*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r9,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r9,ror#11
+	eor	r2,r10,r11
+#if 23>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 23==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r9,ror#25	@ Sigma1(e)
+	and	r2,r2,r9
+	str	r3,[sp,#7*4]
+	add	r3,r3,r0
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	add	r3,r3,r4
+	mov	r4,r5,ror#2
+	add	r3,r3,r2
+	eor	r4,r4,r5,ror#13
+	add	r3,r3,r12
+	eor	r4,r4,r5,ror#22		@ Sigma0(a)
+#if 23>=15
+	ldr	r1,[sp,#9*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r5,r6
+	and	r2,r5,r6
+	and	r0,r0,r7
+	add	r4,r4,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r8,r8,r3
+	add	r4,r4,r0
+	@ ldr	r1,[sp,#9*4]		@ 24
+	ldr	r12,[sp,#6*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#8*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#1*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r8,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r8,ror#11
+	eor	r2,r9,r10
+#if 24>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 24==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r8,ror#25	@ Sigma1(e)
+	and	r2,r2,r8
+	str	r3,[sp,#8*4]
+	add	r3,r3,r0
+	eor	r2,r2,r10			@ Ch(e,f,g)
+	add	r3,r3,r11
+	mov	r11,r4,ror#2
+	add	r3,r3,r2
+	eor	r11,r11,r4,ror#13
+	add	r3,r3,r12
+	eor	r11,r11,r4,ror#22		@ Sigma0(a)
+#if 24>=15
+	ldr	r1,[sp,#10*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r4,r5
+	and	r2,r4,r5
+	and	r0,r0,r6
+	add	r11,r11,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r7,r7,r3
+	add	r11,r11,r0
+	@ ldr	r1,[sp,#10*4]		@ 25
+	ldr	r12,[sp,#7*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#9*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#2*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r7,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r7,ror#11
+	eor	r2,r8,r9
+#if 25>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 25==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r7,ror#25	@ Sigma1(e)
+	and	r2,r2,r7
+	str	r3,[sp,#9*4]
+	add	r3,r3,r0
+	eor	r2,r2,r9			@ Ch(e,f,g)
+	add	r3,r3,r10
+	mov	r10,r11,ror#2
+	add	r3,r3,r2
+	eor	r10,r10,r11,ror#13
+	add	r3,r3,r12
+	eor	r10,r10,r11,ror#22		@ Sigma0(a)
+#if 25>=15
+	ldr	r1,[sp,#11*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r11,r4
+	and	r2,r11,r4
+	and	r0,r0,r5
+	add	r10,r10,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r6,r6,r3
+	add	r10,r10,r0
+	@ ldr	r1,[sp,#11*4]		@ 26
+	ldr	r12,[sp,#8*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#10*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#3*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r6,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r6,ror#11
+	eor	r2,r7,r8
+#if 26>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 26==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r6,ror#25	@ Sigma1(e)
+	and	r2,r2,r6
+	str	r3,[sp,#10*4]
+	add	r3,r3,r0
+	eor	r2,r2,r8			@ Ch(e,f,g)
+	add	r3,r3,r9
+	mov	r9,r10,ror#2
+	add	r3,r3,r2
+	eor	r9,r9,r10,ror#13
+	add	r3,r3,r12
+	eor	r9,r9,r10,ror#22		@ Sigma0(a)
+#if 26>=15
+	ldr	r1,[sp,#12*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r10,r11
+	and	r2,r10,r11
+	and	r0,r0,r4
+	add	r9,r9,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r5,r5,r3
+	add	r9,r9,r0
+	@ ldr	r1,[sp,#12*4]		@ 27
+	ldr	r12,[sp,#9*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#11*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#4*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r5,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r5,ror#11
+	eor	r2,r6,r7
+#if 27>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 27==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r5,ror#25	@ Sigma1(e)
+	and	r2,r2,r5
+	str	r3,[sp,#11*4]
+	add	r3,r3,r0
+	eor	r2,r2,r7			@ Ch(e,f,g)
+	add	r3,r3,r8
+	mov	r8,r9,ror#2
+	add	r3,r3,r2
+	eor	r8,r8,r9,ror#13
+	add	r3,r3,r12
+	eor	r8,r8,r9,ror#22		@ Sigma0(a)
+#if 27>=15
+	ldr	r1,[sp,#13*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r9,r10
+	and	r2,r9,r10
+	and	r0,r0,r11
+	add	r8,r8,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r4,r4,r3
+	add	r8,r8,r0
+	@ ldr	r1,[sp,#13*4]		@ 28
+	ldr	r12,[sp,#10*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#12*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#5*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r4,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r4,ror#11
+	eor	r2,r5,r6
+#if 28>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 28==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r4,ror#25	@ Sigma1(e)
+	and	r2,r2,r4
+	str	r3,[sp,#12*4]
+	add	r3,r3,r0
+	eor	r2,r2,r6			@ Ch(e,f,g)
+	add	r3,r3,r7
+	mov	r7,r8,ror#2
+	add	r3,r3,r2
+	eor	r7,r7,r8,ror#13
+	add	r3,r3,r12
+	eor	r7,r7,r8,ror#22		@ Sigma0(a)
+#if 28>=15
+	ldr	r1,[sp,#14*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r8,r9
+	and	r2,r8,r9
+	and	r0,r0,r10
+	add	r7,r7,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r11,r11,r3
+	add	r7,r7,r0
+	@ ldr	r1,[sp,#14*4]		@ 29
+	ldr	r12,[sp,#11*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#13*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#6*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r11,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r11,ror#11
+	eor	r2,r4,r5
+#if 29>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 29==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r11,ror#25	@ Sigma1(e)
+	and	r2,r2,r11
+	str	r3,[sp,#13*4]
+	add	r3,r3,r0
+	eor	r2,r2,r5			@ Ch(e,f,g)
+	add	r3,r3,r6
+	mov	r6,r7,ror#2
+	add	r3,r3,r2
+	eor	r6,r6,r7,ror#13
+	add	r3,r3,r12
+	eor	r6,r6,r7,ror#22		@ Sigma0(a)
+#if 29>=15
+	ldr	r1,[sp,#15*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r7,r8
+	and	r2,r7,r8
+	and	r0,r0,r9
+	add	r6,r6,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r10,r10,r3
+	add	r6,r6,r0
+	@ ldr	r1,[sp,#15*4]		@ 30
+	ldr	r12,[sp,#12*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#14*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#7*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r10,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r10,ror#11
+	eor	r2,r11,r4
+#if 30>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 30==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r10,ror#25	@ Sigma1(e)
+	and	r2,r2,r10
+	str	r3,[sp,#14*4]
+	add	r3,r3,r0
+	eor	r2,r2,r4			@ Ch(e,f,g)
+	add	r3,r3,r5
+	mov	r5,r6,ror#2
+	add	r3,r3,r2
+	eor	r5,r5,r6,ror#13
+	add	r3,r3,r12
+	eor	r5,r5,r6,ror#22		@ Sigma0(a)
+#if 30>=15
+	ldr	r1,[sp,#0*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r6,r7
+	and	r2,r6,r7
+	and	r0,r0,r8
+	add	r5,r5,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r9,r9,r3
+	add	r5,r5,r0
+	@ ldr	r1,[sp,#0*4]		@ 31
+	ldr	r12,[sp,#13*4]
+	mov	r0,r1,ror#7
+	ldr	r3,[sp,#15*4]
+	eor	r0,r0,r1,ror#18
+	ldr	r2,[sp,#8*4]
+	eor	r0,r0,r1,lsr#3	@ sigma0(X[i+1])
+	mov	r1,r12,ror#17
+	add	r3,r3,r0
+	eor	r1,r1,r12,ror#19
+	add	r3,r3,r2
+	eor	r1,r1,r12,lsr#10	@ sigma1(X[i+14])
+	@ add	r3,r3,r1
+	mov	r0,r9,ror#6
+	ldr	r12,[r14],#4			@ *K256++
+	eor	r0,r0,r9,ror#11
+	eor	r2,r10,r11
+#if 31>=16
+	add	r3,r3,r1			@ from BODY_16_xx
+#elif __ARM_ARCH__>=7 && defined(__ARMEL__) && !defined(__STRICT_ALIGNMENT)
+	rev	r3,r3
+#endif
+#if 31==15
+	str	r1,[sp,#17*4]			@ leave room for r1
+#endif
+	eor	r0,r0,r9,ror#25	@ Sigma1(e)
+	and	r2,r2,r9
+	str	r3,[sp,#15*4]
+	add	r3,r3,r0
+	eor	r2,r2,r11			@ Ch(e,f,g)
+	add	r3,r3,r4
+	mov	r4,r5,ror#2
+	add	r3,r3,r2
+	eor	r4,r4,r5,ror#13
+	add	r3,r3,r12
+	eor	r4,r4,r5,ror#22		@ Sigma0(a)
+#if 31>=15
+	ldr	r1,[sp,#1*4]		@ from BODY_16_xx
+#endif
+	orr	r0,r5,r6
+	and	r2,r5,r6
+	and	r0,r0,r7
+	add	r4,r4,r3
+	orr	r0,r0,r2			@ Maj(a,b,c)
+	add	r8,r8,r3
+	add	r4,r4,r0
+	and	r12,r12,#0xff
+	cmp	r12,#0xf2
+	bne	.Lrounds_16_xx
+
+	ldr	r3,[sp,#16*4]		@ pull ctx
+	ldr	r0,[r3,#0]
+	ldr	r2,[r3,#4]
+	ldr	r12,[r3,#8]
+	add	r4,r4,r0
+	ldr	r0,[r3,#12]
+	add	r5,r5,r2
+	ldr	r2,[r3,#16]
+	add	r6,r6,r12
+	ldr	r12,[r3,#20]
+	add	r7,r7,r0
+	ldr	r0,[r3,#24]
+	add	r8,r8,r2
+	ldr	r2,[r3,#28]
+	add	r9,r9,r12
+	ldr	r1,[sp,#17*4]		@ pull inp
+	ldr	r12,[sp,#18*4]		@ pull inp+len
+	add	r10,r10,r0
+	add	r11,r11,r2
+	stmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}
+	cmp	r1,r12
+	sub	r14,r14,#256	@ rewind Ktbl
+	bne	.Loop
+
+	add	sp,sp,#19*4	@ destroy frame
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+.size   sha256_block_data_order,.-sha256_block_data_order
+.asciz  "SHA256 block transform for ARMv4, CRYPTOGAMS by "
+.align	2
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha256-elf-x86_64.S b/crypto/sha/sha256-elf-x86_64.S
new file mode 100644
index 0000000..b976181
--- /dev/null
+++ b/crypto/sha/sha256-elf-x86_64.S
@@ -0,0 +1,1785 @@
+#include "x86_arch.h"
+.text	
+
+.globl	sha256_block_data_order
+.type	sha256_block_data_order,@function
+.align	16
+sha256_block_data_order:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$64+32,%rsp
+	leaq	(%rsi,%rdx,4),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,64+0(%rsp)
+	movq	%rsi,64+8(%rsp)
+	movq	%rdx,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+.Lprologue:
+
+	leaq	K256(%rip),%rbp
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+	movl	16(%rdi),%r8d
+	movl	20(%rdi),%r9d
+	movl	24(%rdi),%r10d
+	movl	28(%rdi),%r11d
+	jmp	.Lloop
+
+.align	16
+.Lloop:
+	xorq	%rdi,%rdi
+	movl	0(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	4(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	8(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	12(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	16(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	20(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	24(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	28(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	32(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	36(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	40(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	44(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	48(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	52(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	56(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	60(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	jmp	.Lrounds_16_xx
+.align	16
+.Lrounds_16_xx:
+	movl	4(%rsp),%r13d
+	movl	56(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	36(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	0(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	8(%rsp),%r13d
+	movl	60(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	40(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	4(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	12(%rsp),%r13d
+	movl	0(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	44(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	8(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	16(%rsp),%r13d
+	movl	4(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	48(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	12(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	20(%rsp),%r13d
+	movl	8(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	52(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	16(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	24(%rsp),%r13d
+	movl	12(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	56(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	20(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	28(%rsp),%r13d
+	movl	16(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	60(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	24(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	32(%rsp),%r13d
+	movl	20(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	0(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	28(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	36(%rsp),%r13d
+	movl	24(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	4(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	32(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	40(%rsp),%r13d
+	movl	28(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	8(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	36(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	44(%rsp),%r13d
+	movl	32(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	12(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	40(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	48(%rsp),%r13d
+	movl	36(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	16(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	44(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	52(%rsp),%r13d
+	movl	40(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	20(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	48(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	56(%rsp),%r13d
+	movl	44(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	24(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	52(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	60(%rsp),%r13d
+	movl	48(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	28(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	56(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	0(%rsp),%r13d
+	movl	52(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	32(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	60(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	cmpq	$64,%rdi
+	jb	.Lrounds_16_xx
+
+	movq	64+0(%rsp),%rdi
+	leaq	64(%rsi),%rsi
+
+	addl	0(%rdi),%eax
+	addl	4(%rdi),%ebx
+	addl	8(%rdi),%ecx
+	addl	12(%rdi),%edx
+	addl	16(%rdi),%r8d
+	addl	20(%rdi),%r9d
+	addl	24(%rdi),%r10d
+	addl	28(%rdi),%r11d
+
+	cmpq	64+16(%rsp),%rsi
+
+	movl	%eax,0(%rdi)
+	movl	%ebx,4(%rdi)
+	movl	%ecx,8(%rdi)
+	movl	%edx,12(%rdi)
+	movl	%r8d,16(%rdi)
+	movl	%r9d,20(%rdi)
+	movl	%r10d,24(%rdi)
+	movl	%r11d,28(%rdi)
+	jb	.Lloop
+
+	movq	64+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	retq
+.size	sha256_block_data_order,.-sha256_block_data_order
+.section	.rodata
+.align	64
+.type	K256,@object
+K256:
+.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha256-macosx-x86_64.S b/crypto/sha/sha256-macosx-x86_64.S
new file mode 100644
index 0000000..4b468b7
--- /dev/null
+++ b/crypto/sha/sha256-macosx-x86_64.S
@@ -0,0 +1,1779 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_sha256_block_data_order
+
+.p2align	4
+_sha256_block_data_order:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$64+32,%rsp
+	leaq	(%rsi,%rdx,4),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,64+0(%rsp)
+	movq	%rsi,64+8(%rsp)
+	movq	%rdx,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+L$prologue:
+
+	leaq	K256(%rip),%rbp
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+	movl	16(%rdi),%r8d
+	movl	20(%rdi),%r9d
+	movl	24(%rdi),%r10d
+	movl	28(%rdi),%r11d
+	jmp	L$loop
+
+.p2align	4
+L$loop:
+	xorq	%rdi,%rdi
+	movl	0(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	4(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	8(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	12(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	16(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	20(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	24(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	28(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	32(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	36(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	40(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	44(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	48(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	52(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	56(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	60(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	jmp	L$rounds_16_xx
+.p2align	4
+L$rounds_16_xx:
+	movl	4(%rsp),%r13d
+	movl	56(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	36(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	0(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	8(%rsp),%r13d
+	movl	60(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	40(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	4(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	12(%rsp),%r13d
+	movl	0(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	44(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	8(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	16(%rsp),%r13d
+	movl	4(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	48(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	12(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	20(%rsp),%r13d
+	movl	8(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	52(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	16(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	24(%rsp),%r13d
+	movl	12(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	56(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	20(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	28(%rsp),%r13d
+	movl	16(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	60(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	24(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	32(%rsp),%r13d
+	movl	20(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	0(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	28(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	36(%rsp),%r13d
+	movl	24(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	4(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	32(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	40(%rsp),%r13d
+	movl	28(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	8(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	36(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	44(%rsp),%r13d
+	movl	32(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	12(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	40(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	48(%rsp),%r13d
+	movl	36(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	16(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	44(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	52(%rsp),%r13d
+	movl	40(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	20(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	48(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	56(%rsp),%r13d
+	movl	44(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	24(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	52(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	60(%rsp),%r13d
+	movl	48(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	28(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	56(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	0(%rsp),%r13d
+	movl	52(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	32(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	60(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	cmpq	$64,%rdi
+	jb	L$rounds_16_xx
+
+	movq	64+0(%rsp),%rdi
+	leaq	64(%rsi),%rsi
+
+	addl	0(%rdi),%eax
+	addl	4(%rdi),%ebx
+	addl	8(%rdi),%ecx
+	addl	12(%rdi),%edx
+	addl	16(%rdi),%r8d
+	addl	20(%rdi),%r9d
+	addl	24(%rdi),%r10d
+	addl	28(%rdi),%r11d
+
+	cmpq	64+16(%rsp),%rsi
+
+	movl	%eax,0(%rdi)
+	movl	%ebx,4(%rdi)
+	movl	%ecx,8(%rdi)
+	movl	%edx,12(%rdi)
+	movl	%r8d,16(%rdi)
+	movl	%r9d,20(%rdi)
+	movl	%r10d,24(%rdi)
+	movl	%r11d,28(%rdi)
+	jb	L$loop
+
+	movq	64+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$epilogue:
+	retq
+
+.p2align	6
+
+K256:
+.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
diff --git a/crypto/sha/sha256-masm-x86_64.S b/crypto/sha/sha256-masm-x86_64.S
new file mode 100644
index 0000000..ccaf8e3
--- /dev/null
+++ b/crypto/sha/sha256-masm-x86_64.S
@@ -0,0 +1,1864 @@
+; 1 "crypto/sha/sha256-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/sha/sha256-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/sha/sha256-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	sha256_block_data_order
+
+ALIGN	16
+sha256_block_data_order	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_sha256_block_data_order::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	mov	r11,rsp
+	shl	rdx,4
+	sub	rsp,16*4+4*8
+	lea	rdx,QWORD PTR[rdx*4+rsi]
+	and	rsp,-64
+	mov	QWORD PTR[((64+0))+rsp],rdi
+	mov	QWORD PTR[((64+8))+rsp],rsi
+	mov	QWORD PTR[((64+16))+rsp],rdx
+	mov	QWORD PTR[((64+24))+rsp],r11
+$L$prologue::
+
+	lea	rbp,QWORD PTR[K256]
+
+	mov	eax,DWORD PTR[rdi]
+	mov	ebx,DWORD PTR[4+rdi]
+	mov	ecx,DWORD PTR[8+rdi]
+	mov	edx,DWORD PTR[12+rdi]
+	mov	r8d,DWORD PTR[16+rdi]
+	mov	r9d,DWORD PTR[20+rdi]
+	mov	r10d,DWORD PTR[24+rdi]
+	mov	r11d,DWORD PTR[28+rdi]
+	jmp	$L$loop
+
+ALIGN	16
+$L$loop::
+	xor	rdi,rdi
+	mov	r12d,DWORD PTR[rsi]
+	mov	r13d,r8d
+	mov	r14d,eax
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r9d
+	mov	DWORD PTR[rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	ror	r13d,5
+	add	r12d,r11d
+	xor	r14d,eax
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r8d
+	mov	r11d,ebx
+
+	ror	r14d,11
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	xor	r11d,ecx
+	xor	r14d,eax
+	add	r12d,r15d
+	mov	r15d,ebx
+
+	ror	r13d,6
+	and	r11d,eax
+	and	r15d,ecx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r11d,r15d
+
+	add	edx,r12d
+	add	r11d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11d,r14d
+
+	mov	r12d,DWORD PTR[4+rsi]
+	mov	r13d,edx
+	mov	r14d,r11d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r8d
+	mov	DWORD PTR[4+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	ror	r13d,5
+	add	r12d,r10d
+	xor	r14d,r11d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,edx
+	mov	r10d,eax
+
+	ror	r14d,11
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	xor	r10d,ebx
+	xor	r14d,r11d
+	add	r12d,r15d
+	mov	r15d,eax
+
+	ror	r13d,6
+	and	r10d,r11d
+	and	r15d,ebx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r10d,r15d
+
+	add	ecx,r12d
+	add	r10d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10d,r14d
+
+	mov	r12d,DWORD PTR[8+rsi]
+	mov	r13d,ecx
+	mov	r14d,r10d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,edx
+	mov	DWORD PTR[8+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	ror	r13d,5
+	add	r12d,r9d
+	xor	r14d,r10d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ecx
+	mov	r9d,r11d
+
+	ror	r14d,11
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	xor	r9d,eax
+	xor	r14d,r10d
+	add	r12d,r15d
+	mov	r15d,r11d
+
+	ror	r13d,6
+	and	r9d,r10d
+	and	r15d,eax
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r9d,r15d
+
+	add	ebx,r12d
+	add	r9d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9d,r14d
+
+	mov	r12d,DWORD PTR[12+rsi]
+	mov	r13d,ebx
+	mov	r14d,r9d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,ecx
+	mov	DWORD PTR[12+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	ror	r13d,5
+	add	r12d,r8d
+	xor	r14d,r9d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ebx
+	mov	r8d,r10d
+
+	ror	r14d,11
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	xor	r8d,r11d
+	xor	r14d,r9d
+	add	r12d,r15d
+	mov	r15d,r10d
+
+	ror	r13d,6
+	and	r8d,r9d
+	and	r15d,r11d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r8d,r15d
+
+	add	eax,r12d
+	add	r8d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8d,r14d
+
+	mov	r12d,DWORD PTR[16+rsi]
+	mov	r13d,eax
+	mov	r14d,r8d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,ebx
+	mov	DWORD PTR[16+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	ror	r13d,5
+	add	r12d,edx
+	xor	r14d,r8d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,eax
+	mov	edx,r9d
+
+	ror	r14d,11
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	xor	edx,r10d
+	xor	r14d,r8d
+	add	r12d,r15d
+	mov	r15d,r9d
+
+	ror	r13d,6
+	and	edx,r8d
+	and	r15d,r10d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	edx,r15d
+
+	add	r11d,r12d
+	add	edx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	edx,r14d
+
+	mov	r12d,DWORD PTR[20+rsi]
+	mov	r13d,r11d
+	mov	r14d,edx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,eax
+	mov	DWORD PTR[20+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	ror	r13d,5
+	add	r12d,ecx
+	xor	r14d,edx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r11d
+	mov	ecx,r8d
+
+	ror	r14d,11
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	xor	ecx,r9d
+	xor	r14d,edx
+	add	r12d,r15d
+	mov	r15d,r8d
+
+	ror	r13d,6
+	and	ecx,edx
+	and	r15d,r9d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ecx,r15d
+
+	add	r10d,r12d
+	add	ecx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ecx,r14d
+
+	mov	r12d,DWORD PTR[24+rsi]
+	mov	r13d,r10d
+	mov	r14d,ecx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r11d
+	mov	DWORD PTR[24+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	ror	r13d,5
+	add	r12d,ebx
+	xor	r14d,ecx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r10d
+	mov	ebx,edx
+
+	ror	r14d,11
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	xor	ebx,r8d
+	xor	r14d,ecx
+	add	r12d,r15d
+	mov	r15d,edx
+
+	ror	r13d,6
+	and	ebx,ecx
+	and	r15d,r8d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ebx,r15d
+
+	add	r9d,r12d
+	add	ebx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ebx,r14d
+
+	mov	r12d,DWORD PTR[28+rsi]
+	mov	r13d,r9d
+	mov	r14d,ebx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r10d
+	mov	DWORD PTR[28+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	ror	r13d,5
+	add	r12d,eax
+	xor	r14d,ebx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r9d
+	mov	eax,ecx
+
+	ror	r14d,11
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	xor	eax,edx
+	xor	r14d,ebx
+	add	r12d,r15d
+	mov	r15d,ecx
+
+	ror	r13d,6
+	and	eax,ebx
+	and	r15d,edx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	eax,r15d
+
+	add	r8d,r12d
+	add	eax,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	eax,r14d
+
+	mov	r12d,DWORD PTR[32+rsi]
+	mov	r13d,r8d
+	mov	r14d,eax
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r9d
+	mov	DWORD PTR[32+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	ror	r13d,5
+	add	r12d,r11d
+	xor	r14d,eax
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r8d
+	mov	r11d,ebx
+
+	ror	r14d,11
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	xor	r11d,ecx
+	xor	r14d,eax
+	add	r12d,r15d
+	mov	r15d,ebx
+
+	ror	r13d,6
+	and	r11d,eax
+	and	r15d,ecx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r11d,r15d
+
+	add	edx,r12d
+	add	r11d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11d,r14d
+
+	mov	r12d,DWORD PTR[36+rsi]
+	mov	r13d,edx
+	mov	r14d,r11d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r8d
+	mov	DWORD PTR[36+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	ror	r13d,5
+	add	r12d,r10d
+	xor	r14d,r11d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,edx
+	mov	r10d,eax
+
+	ror	r14d,11
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	xor	r10d,ebx
+	xor	r14d,r11d
+	add	r12d,r15d
+	mov	r15d,eax
+
+	ror	r13d,6
+	and	r10d,r11d
+	and	r15d,ebx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r10d,r15d
+
+	add	ecx,r12d
+	add	r10d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10d,r14d
+
+	mov	r12d,DWORD PTR[40+rsi]
+	mov	r13d,ecx
+	mov	r14d,r10d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,edx
+	mov	DWORD PTR[40+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	ror	r13d,5
+	add	r12d,r9d
+	xor	r14d,r10d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ecx
+	mov	r9d,r11d
+
+	ror	r14d,11
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	xor	r9d,eax
+	xor	r14d,r10d
+	add	r12d,r15d
+	mov	r15d,r11d
+
+	ror	r13d,6
+	and	r9d,r10d
+	and	r15d,eax
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r9d,r15d
+
+	add	ebx,r12d
+	add	r9d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9d,r14d
+
+	mov	r12d,DWORD PTR[44+rsi]
+	mov	r13d,ebx
+	mov	r14d,r9d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,ecx
+	mov	DWORD PTR[44+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	ror	r13d,5
+	add	r12d,r8d
+	xor	r14d,r9d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ebx
+	mov	r8d,r10d
+
+	ror	r14d,11
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	xor	r8d,r11d
+	xor	r14d,r9d
+	add	r12d,r15d
+	mov	r15d,r10d
+
+	ror	r13d,6
+	and	r8d,r9d
+	and	r15d,r11d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r8d,r15d
+
+	add	eax,r12d
+	add	r8d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8d,r14d
+
+	mov	r12d,DWORD PTR[48+rsi]
+	mov	r13d,eax
+	mov	r14d,r8d
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,ebx
+	mov	DWORD PTR[48+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	ror	r13d,5
+	add	r12d,edx
+	xor	r14d,r8d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,eax
+	mov	edx,r9d
+
+	ror	r14d,11
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	xor	edx,r10d
+	xor	r14d,r8d
+	add	r12d,r15d
+	mov	r15d,r9d
+
+	ror	r13d,6
+	and	edx,r8d
+	and	r15d,r10d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	edx,r15d
+
+	add	r11d,r12d
+	add	edx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	edx,r14d
+
+	mov	r12d,DWORD PTR[52+rsi]
+	mov	r13d,r11d
+	mov	r14d,edx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,eax
+	mov	DWORD PTR[52+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	ror	r13d,5
+	add	r12d,ecx
+	xor	r14d,edx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r11d
+	mov	ecx,r8d
+
+	ror	r14d,11
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	xor	ecx,r9d
+	xor	r14d,edx
+	add	r12d,r15d
+	mov	r15d,r8d
+
+	ror	r13d,6
+	and	ecx,edx
+	and	r15d,r9d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ecx,r15d
+
+	add	r10d,r12d
+	add	ecx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ecx,r14d
+
+	mov	r12d,DWORD PTR[56+rsi]
+	mov	r13d,r10d
+	mov	r14d,ecx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r11d
+	mov	DWORD PTR[56+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	ror	r13d,5
+	add	r12d,ebx
+	xor	r14d,ecx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r10d
+	mov	ebx,edx
+
+	ror	r14d,11
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	xor	ebx,r8d
+	xor	r14d,ecx
+	add	r12d,r15d
+	mov	r15d,edx
+
+	ror	r13d,6
+	and	ebx,ecx
+	and	r15d,r8d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ebx,r15d
+
+	add	r9d,r12d
+	add	ebx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ebx,r14d
+
+	mov	r12d,DWORD PTR[60+rsi]
+	mov	r13d,r9d
+	mov	r14d,ebx
+	bswap	r12d
+	ror	r13d,14
+	mov	r15d,r10d
+	mov	DWORD PTR[60+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	ror	r13d,5
+	add	r12d,eax
+	xor	r14d,ebx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r9d
+	mov	eax,ecx
+
+	ror	r14d,11
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	xor	eax,edx
+	xor	r14d,ebx
+	add	r12d,r15d
+	mov	r15d,ecx
+
+	ror	r13d,6
+	and	eax,ebx
+	and	r15d,edx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	eax,r15d
+
+	add	r8d,r12d
+	add	eax,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	eax,r14d
+
+	jmp	$L$rounds_16_xx
+ALIGN	16
+$L$rounds_16_xx::
+	mov	r13d,DWORD PTR[4+rsp]
+	mov	r14d,DWORD PTR[56+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[36+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[rsp]
+	mov	r13d,r8d
+	add	r12d,r14d
+	mov	r14d,eax
+	ror	r13d,14
+	mov	r15d,r9d
+	mov	DWORD PTR[rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	ror	r13d,5
+	add	r12d,r11d
+	xor	r14d,eax
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r8d
+	mov	r11d,ebx
+
+	ror	r14d,11
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	xor	r11d,ecx
+	xor	r14d,eax
+	add	r12d,r15d
+	mov	r15d,ebx
+
+	ror	r13d,6
+	and	r11d,eax
+	and	r15d,ecx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r11d,r15d
+
+	add	edx,r12d
+	add	r11d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11d,r14d
+
+	mov	r13d,DWORD PTR[8+rsp]
+	mov	r14d,DWORD PTR[60+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[40+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[4+rsp]
+	mov	r13d,edx
+	add	r12d,r14d
+	mov	r14d,r11d
+	ror	r13d,14
+	mov	r15d,r8d
+	mov	DWORD PTR[4+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	ror	r13d,5
+	add	r12d,r10d
+	xor	r14d,r11d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,edx
+	mov	r10d,eax
+
+	ror	r14d,11
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	xor	r10d,ebx
+	xor	r14d,r11d
+	add	r12d,r15d
+	mov	r15d,eax
+
+	ror	r13d,6
+	and	r10d,r11d
+	and	r15d,ebx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r10d,r15d
+
+	add	ecx,r12d
+	add	r10d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10d,r14d
+
+	mov	r13d,DWORD PTR[12+rsp]
+	mov	r14d,DWORD PTR[rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[44+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[8+rsp]
+	mov	r13d,ecx
+	add	r12d,r14d
+	mov	r14d,r10d
+	ror	r13d,14
+	mov	r15d,edx
+	mov	DWORD PTR[8+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	ror	r13d,5
+	add	r12d,r9d
+	xor	r14d,r10d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ecx
+	mov	r9d,r11d
+
+	ror	r14d,11
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	xor	r9d,eax
+	xor	r14d,r10d
+	add	r12d,r15d
+	mov	r15d,r11d
+
+	ror	r13d,6
+	and	r9d,r10d
+	and	r15d,eax
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r9d,r15d
+
+	add	ebx,r12d
+	add	r9d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9d,r14d
+
+	mov	r13d,DWORD PTR[16+rsp]
+	mov	r14d,DWORD PTR[4+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[48+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[12+rsp]
+	mov	r13d,ebx
+	add	r12d,r14d
+	mov	r14d,r9d
+	ror	r13d,14
+	mov	r15d,ecx
+	mov	DWORD PTR[12+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	ror	r13d,5
+	add	r12d,r8d
+	xor	r14d,r9d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ebx
+	mov	r8d,r10d
+
+	ror	r14d,11
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	xor	r8d,r11d
+	xor	r14d,r9d
+	add	r12d,r15d
+	mov	r15d,r10d
+
+	ror	r13d,6
+	and	r8d,r9d
+	and	r15d,r11d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r8d,r15d
+
+	add	eax,r12d
+	add	r8d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8d,r14d
+
+	mov	r13d,DWORD PTR[20+rsp]
+	mov	r14d,DWORD PTR[8+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[52+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[16+rsp]
+	mov	r13d,eax
+	add	r12d,r14d
+	mov	r14d,r8d
+	ror	r13d,14
+	mov	r15d,ebx
+	mov	DWORD PTR[16+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	ror	r13d,5
+	add	r12d,edx
+	xor	r14d,r8d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,eax
+	mov	edx,r9d
+
+	ror	r14d,11
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	xor	edx,r10d
+	xor	r14d,r8d
+	add	r12d,r15d
+	mov	r15d,r9d
+
+	ror	r13d,6
+	and	edx,r8d
+	and	r15d,r10d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	edx,r15d
+
+	add	r11d,r12d
+	add	edx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	edx,r14d
+
+	mov	r13d,DWORD PTR[24+rsp]
+	mov	r14d,DWORD PTR[12+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[56+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[20+rsp]
+	mov	r13d,r11d
+	add	r12d,r14d
+	mov	r14d,edx
+	ror	r13d,14
+	mov	r15d,eax
+	mov	DWORD PTR[20+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	ror	r13d,5
+	add	r12d,ecx
+	xor	r14d,edx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r11d
+	mov	ecx,r8d
+
+	ror	r14d,11
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	xor	ecx,r9d
+	xor	r14d,edx
+	add	r12d,r15d
+	mov	r15d,r8d
+
+	ror	r13d,6
+	and	ecx,edx
+	and	r15d,r9d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ecx,r15d
+
+	add	r10d,r12d
+	add	ecx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ecx,r14d
+
+	mov	r13d,DWORD PTR[28+rsp]
+	mov	r14d,DWORD PTR[16+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[60+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[24+rsp]
+	mov	r13d,r10d
+	add	r12d,r14d
+	mov	r14d,ecx
+	ror	r13d,14
+	mov	r15d,r11d
+	mov	DWORD PTR[24+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	ror	r13d,5
+	add	r12d,ebx
+	xor	r14d,ecx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r10d
+	mov	ebx,edx
+
+	ror	r14d,11
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	xor	ebx,r8d
+	xor	r14d,ecx
+	add	r12d,r15d
+	mov	r15d,edx
+
+	ror	r13d,6
+	and	ebx,ecx
+	and	r15d,r8d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ebx,r15d
+
+	add	r9d,r12d
+	add	ebx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ebx,r14d
+
+	mov	r13d,DWORD PTR[32+rsp]
+	mov	r14d,DWORD PTR[20+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[28+rsp]
+	mov	r13d,r9d
+	add	r12d,r14d
+	mov	r14d,ebx
+	ror	r13d,14
+	mov	r15d,r10d
+	mov	DWORD PTR[28+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	ror	r13d,5
+	add	r12d,eax
+	xor	r14d,ebx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r9d
+	mov	eax,ecx
+
+	ror	r14d,11
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	xor	eax,edx
+	xor	r14d,ebx
+	add	r12d,r15d
+	mov	r15d,ecx
+
+	ror	r13d,6
+	and	eax,ebx
+	and	r15d,edx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	eax,r15d
+
+	add	r8d,r12d
+	add	eax,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	eax,r14d
+
+	mov	r13d,DWORD PTR[36+rsp]
+	mov	r14d,DWORD PTR[24+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[4+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[32+rsp]
+	mov	r13d,r8d
+	add	r12d,r14d
+	mov	r14d,eax
+	ror	r13d,14
+	mov	r15d,r9d
+	mov	DWORD PTR[32+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	ror	r13d,5
+	add	r12d,r11d
+	xor	r14d,eax
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r8d
+	mov	r11d,ebx
+
+	ror	r14d,11
+	xor	r13d,r8d
+	xor	r15d,r10d
+
+	xor	r11d,ecx
+	xor	r14d,eax
+	add	r12d,r15d
+	mov	r15d,ebx
+
+	ror	r13d,6
+	and	r11d,eax
+	and	r15d,ecx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r11d,r15d
+
+	add	edx,r12d
+	add	r11d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11d,r14d
+
+	mov	r13d,DWORD PTR[40+rsp]
+	mov	r14d,DWORD PTR[28+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[8+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[36+rsp]
+	mov	r13d,edx
+	add	r12d,r14d
+	mov	r14d,r11d
+	ror	r13d,14
+	mov	r15d,r8d
+	mov	DWORD PTR[36+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	ror	r13d,5
+	add	r12d,r10d
+	xor	r14d,r11d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,edx
+	mov	r10d,eax
+
+	ror	r14d,11
+	xor	r13d,edx
+	xor	r15d,r9d
+
+	xor	r10d,ebx
+	xor	r14d,r11d
+	add	r12d,r15d
+	mov	r15d,eax
+
+	ror	r13d,6
+	and	r10d,r11d
+	and	r15d,ebx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r10d,r15d
+
+	add	ecx,r12d
+	add	r10d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10d,r14d
+
+	mov	r13d,DWORD PTR[44+rsp]
+	mov	r14d,DWORD PTR[32+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[12+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[40+rsp]
+	mov	r13d,ecx
+	add	r12d,r14d
+	mov	r14d,r10d
+	ror	r13d,14
+	mov	r15d,edx
+	mov	DWORD PTR[40+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	ror	r13d,5
+	add	r12d,r9d
+	xor	r14d,r10d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ecx
+	mov	r9d,r11d
+
+	ror	r14d,11
+	xor	r13d,ecx
+	xor	r15d,r8d
+
+	xor	r9d,eax
+	xor	r14d,r10d
+	add	r12d,r15d
+	mov	r15d,r11d
+
+	ror	r13d,6
+	and	r9d,r10d
+	and	r15d,eax
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r9d,r15d
+
+	add	ebx,r12d
+	add	r9d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9d,r14d
+
+	mov	r13d,DWORD PTR[48+rsp]
+	mov	r14d,DWORD PTR[36+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[16+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[44+rsp]
+	mov	r13d,ebx
+	add	r12d,r14d
+	mov	r14d,r9d
+	ror	r13d,14
+	mov	r15d,ecx
+	mov	DWORD PTR[44+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	ror	r13d,5
+	add	r12d,r8d
+	xor	r14d,r9d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,ebx
+	mov	r8d,r10d
+
+	ror	r14d,11
+	xor	r13d,ebx
+	xor	r15d,edx
+
+	xor	r8d,r11d
+	xor	r14d,r9d
+	add	r12d,r15d
+	mov	r15d,r10d
+
+	ror	r13d,6
+	and	r8d,r9d
+	and	r15d,r11d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	r8d,r15d
+
+	add	eax,r12d
+	add	r8d,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8d,r14d
+
+	mov	r13d,DWORD PTR[52+rsp]
+	mov	r14d,DWORD PTR[40+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[20+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[48+rsp]
+	mov	r13d,eax
+	add	r12d,r14d
+	mov	r14d,r8d
+	ror	r13d,14
+	mov	r15d,ebx
+	mov	DWORD PTR[48+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	ror	r13d,5
+	add	r12d,edx
+	xor	r14d,r8d
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,eax
+	mov	edx,r9d
+
+	ror	r14d,11
+	xor	r13d,eax
+	xor	r15d,ecx
+
+	xor	edx,r10d
+	xor	r14d,r8d
+	add	r12d,r15d
+	mov	r15d,r9d
+
+	ror	r13d,6
+	and	edx,r8d
+	and	r15d,r10d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	edx,r15d
+
+	add	r11d,r12d
+	add	edx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	edx,r14d
+
+	mov	r13d,DWORD PTR[56+rsp]
+	mov	r14d,DWORD PTR[44+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[24+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[52+rsp]
+	mov	r13d,r11d
+	add	r12d,r14d
+	mov	r14d,edx
+	ror	r13d,14
+	mov	r15d,eax
+	mov	DWORD PTR[52+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	ror	r13d,5
+	add	r12d,ecx
+	xor	r14d,edx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r11d
+	mov	ecx,r8d
+
+	ror	r14d,11
+	xor	r13d,r11d
+	xor	r15d,ebx
+
+	xor	ecx,r9d
+	xor	r14d,edx
+	add	r12d,r15d
+	mov	r15d,r8d
+
+	ror	r13d,6
+	and	ecx,edx
+	and	r15d,r9d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ecx,r15d
+
+	add	r10d,r12d
+	add	ecx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ecx,r14d
+
+	mov	r13d,DWORD PTR[60+rsp]
+	mov	r14d,DWORD PTR[48+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[28+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[56+rsp]
+	mov	r13d,r10d
+	add	r12d,r14d
+	mov	r14d,ecx
+	ror	r13d,14
+	mov	r15d,r11d
+	mov	DWORD PTR[56+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	ror	r13d,5
+	add	r12d,ebx
+	xor	r14d,ecx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r10d
+	mov	ebx,edx
+
+	ror	r14d,11
+	xor	r13d,r10d
+	xor	r15d,eax
+
+	xor	ebx,r8d
+	xor	r14d,ecx
+	add	r12d,r15d
+	mov	r15d,edx
+
+	ror	r13d,6
+	and	ebx,ecx
+	and	r15d,r8d
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	ebx,r15d
+
+	add	r9d,r12d
+	add	ebx,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	ebx,r14d
+
+	mov	r13d,DWORD PTR[rsp]
+	mov	r14d,DWORD PTR[52+rsp]
+	mov	r12d,r13d
+	mov	r15d,r14d
+
+	ror	r12d,11
+	xor	r12d,r13d
+	shr	r13d,3
+
+	ror	r12d,7
+	xor	r13d,r12d
+	mov	r12d,DWORD PTR[32+rsp]
+
+	ror	r15d,2
+	xor	r15d,r14d
+	shr	r14d,10
+
+	ror	r15d,17
+	add	r12d,r13d
+	xor	r14d,r15d
+
+	add	r12d,DWORD PTR[60+rsp]
+	mov	r13d,r9d
+	add	r12d,r14d
+	mov	r14d,ebx
+	ror	r13d,14
+	mov	r15d,r10d
+	mov	DWORD PTR[60+rsp],r12d
+
+	ror	r14d,9
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	ror	r13d,5
+	add	r12d,eax
+	xor	r14d,ebx
+
+	add	r12d,DWORD PTR[rdi*4+rbp]
+	and	r15d,r9d
+	mov	eax,ecx
+
+	ror	r14d,11
+	xor	r13d,r9d
+	xor	r15d,r11d
+
+	xor	eax,edx
+	xor	r14d,ebx
+	add	r12d,r15d
+	mov	r15d,ecx
+
+	ror	r13d,6
+	and	eax,ebx
+	and	r15d,edx
+
+	ror	r14d,2
+	add	r12d,r13d
+	add	eax,r15d
+
+	add	r8d,r12d
+	add	eax,r12d
+	lea	rdi,QWORD PTR[1+rdi]
+	add	eax,r14d
+
+	cmp	rdi,64
+	jb	$L$rounds_16_xx
+
+	mov	rdi,QWORD PTR[((64+0))+rsp]
+	lea	rsi,QWORD PTR[64+rsi]
+
+	add	eax,DWORD PTR[rdi]
+	add	ebx,DWORD PTR[4+rdi]
+	add	ecx,DWORD PTR[8+rdi]
+	add	edx,DWORD PTR[12+rdi]
+	add	r8d,DWORD PTR[16+rdi]
+	add	r9d,DWORD PTR[20+rdi]
+	add	r10d,DWORD PTR[24+rdi]
+	add	r11d,DWORD PTR[28+rdi]
+
+	cmp	rsi,QWORD PTR[((64+16))+rsp]
+
+	mov	DWORD PTR[rdi],eax
+	mov	DWORD PTR[4+rdi],ebx
+	mov	DWORD PTR[8+rdi],ecx
+	mov	DWORD PTR[12+rdi],edx
+	mov	DWORD PTR[16+rdi],r8d
+	mov	DWORD PTR[20+rdi],r9d
+	mov	DWORD PTR[24+rdi],r10d
+	mov	DWORD PTR[28+rdi],r11d
+	jb	$L$loop
+
+	mov	rsi,QWORD PTR[((64+24))+rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_sha256_block_data_order::
+sha256_block_data_order	ENDP
+ALIGN	64
+
+K256::
+	DD	0428a2f98h,071374491h,0b5c0fbcfh,0e9b5dba5h
+	DD	03956c25bh,059f111f1h,0923f82a4h,0ab1c5ed5h
+	DD	0d807aa98h,012835b01h,0243185beh,0550c7dc3h
+	DD	072be5d74h,080deb1feh,09bdc06a7h,0c19bf174h
+	DD	0e49b69c1h,0efbe4786h,00fc19dc6h,0240ca1cch
+	DD	02de92c6fh,04a7484aah,05cb0a9dch,076f988dah
+	DD	0983e5152h,0a831c66dh,0b00327c8h,0bf597fc7h
+	DD	0c6e00bf3h,0d5a79147h,006ca6351h,014292967h
+	DD	027b70a85h,02e1b2138h,04d2c6dfch,053380d13h
+	DD	0650a7354h,0766a0abbh,081c2c92eh,092722c85h
+	DD	0a2bfe8a1h,0a81a664bh,0c24b8b70h,0c76c51a3h
+	DD	0d192e819h,0d6990624h,0f40e3585h,0106aa070h
+	DD	019a4c116h,01e376c08h,02748774ch,034b0bcb5h
+	DD	0391c0cb3h,04ed8aa4ah,05b9cca4fh,0682e6ff3h
+	DD	0748f82eeh,078a5636fh,084c87814h,08cc70208h
+	DD	090befffah,0a4506cebh,0bef9a3f7h,0c67178f2h
+
+.text$	ENDS
+END
+
diff --git a/crypto/sha/sha256-mingw64-x86_64.S b/crypto/sha/sha256-mingw64-x86_64.S
new file mode 100644
index 0000000..3de981b
--- /dev/null
+++ b/crypto/sha/sha256-mingw64-x86_64.S
@@ -0,0 +1,1790 @@
+#include "x86_arch.h"
+.text	
+
+.globl	sha256_block_data_order
+.def	sha256_block_data_order;	.scl 2;	.type 32;	.endef
+.p2align	4
+sha256_block_data_order:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_sha256_block_data_order:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$64+32,%rsp
+	leaq	(%rsi,%rdx,4),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,64+0(%rsp)
+	movq	%rsi,64+8(%rsp)
+	movq	%rdx,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+.Lprologue:
+
+	leaq	K256(%rip),%rbp
+
+	movl	0(%rdi),%eax
+	movl	4(%rdi),%ebx
+	movl	8(%rdi),%ecx
+	movl	12(%rdi),%edx
+	movl	16(%rdi),%r8d
+	movl	20(%rdi),%r9d
+	movl	24(%rdi),%r10d
+	movl	28(%rdi),%r11d
+	jmp	.Lloop
+
+.p2align	4
+.Lloop:
+	xorq	%rdi,%rdi
+	movl	0(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	4(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	8(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	12(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	16(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	20(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	24(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	28(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	32(%rsi),%r12d
+	movl	%r8d,%r13d
+	movl	%eax,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	36(%rsi),%r12d
+	movl	%edx,%r13d
+	movl	%r11d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	40(%rsi),%r12d
+	movl	%ecx,%r13d
+	movl	%r10d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	44(%rsi),%r12d
+	movl	%ebx,%r13d
+	movl	%r9d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	48(%rsi),%r12d
+	movl	%eax,%r13d
+	movl	%r8d,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	52(%rsi),%r12d
+	movl	%r11d,%r13d
+	movl	%edx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	56(%rsi),%r12d
+	movl	%r10d,%r13d
+	movl	%ecx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	60(%rsi),%r12d
+	movl	%r9d,%r13d
+	movl	%ebx,%r14d
+	bswapl	%r12d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	jmp	.Lrounds_16_xx
+.p2align	4
+.Lrounds_16_xx:
+	movl	4(%rsp),%r13d
+	movl	56(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	36(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	0(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,0(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	8(%rsp),%r13d
+	movl	60(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	40(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	4(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,4(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	12(%rsp),%r13d
+	movl	0(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	44(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	8(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,8(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	16(%rsp),%r13d
+	movl	4(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	48(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	12(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,12(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	20(%rsp),%r13d
+	movl	8(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	52(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	16(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,16(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	24(%rsp),%r13d
+	movl	12(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	56(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	20(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,20(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	28(%rsp),%r13d
+	movl	16(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	60(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	24(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,24(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	32(%rsp),%r13d
+	movl	20(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	0(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	28(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,28(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	movl	36(%rsp),%r13d
+	movl	24(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	4(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	32(%rsp),%r12d
+	movl	%r8d,%r13d
+	addl	%r14d,%r12d
+	movl	%eax,%r14d
+	rorl	$14,%r13d
+	movl	%r9d,%r15d
+	movl	%r12d,32(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r11d,%r12d
+	xorl	%eax,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r8d,%r15d
+	movl	%ebx,%r11d
+
+	rorl	$11,%r14d
+	xorl	%r8d,%r13d
+	xorl	%r10d,%r15d
+
+	xorl	%ecx,%r11d
+	xorl	%eax,%r14d
+	addl	%r15d,%r12d
+	movl	%ebx,%r15d
+
+	rorl	$6,%r13d
+	andl	%eax,%r11d
+	andl	%ecx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r11d
+
+	addl	%r12d,%edx
+	addl	%r12d,%r11d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r11d
+
+	movl	40(%rsp),%r13d
+	movl	28(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	8(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	36(%rsp),%r12d
+	movl	%edx,%r13d
+	addl	%r14d,%r12d
+	movl	%r11d,%r14d
+	rorl	$14,%r13d
+	movl	%r8d,%r15d
+	movl	%r12d,36(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r10d,%r12d
+	xorl	%r11d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%edx,%r15d
+	movl	%eax,%r10d
+
+	rorl	$11,%r14d
+	xorl	%edx,%r13d
+	xorl	%r9d,%r15d
+
+	xorl	%ebx,%r10d
+	xorl	%r11d,%r14d
+	addl	%r15d,%r12d
+	movl	%eax,%r15d
+
+	rorl	$6,%r13d
+	andl	%r11d,%r10d
+	andl	%ebx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r10d
+
+	addl	%r12d,%ecx
+	addl	%r12d,%r10d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r10d
+
+	movl	44(%rsp),%r13d
+	movl	32(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	12(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	40(%rsp),%r12d
+	movl	%ecx,%r13d
+	addl	%r14d,%r12d
+	movl	%r10d,%r14d
+	rorl	$14,%r13d
+	movl	%edx,%r15d
+	movl	%r12d,40(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	rorl	$5,%r13d
+	addl	%r9d,%r12d
+	xorl	%r10d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ecx,%r15d
+	movl	%r11d,%r9d
+
+	rorl	$11,%r14d
+	xorl	%ecx,%r13d
+	xorl	%r8d,%r15d
+
+	xorl	%eax,%r9d
+	xorl	%r10d,%r14d
+	addl	%r15d,%r12d
+	movl	%r11d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r10d,%r9d
+	andl	%eax,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r9d
+
+	addl	%r12d,%ebx
+	addl	%r12d,%r9d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r9d
+
+	movl	48(%rsp),%r13d
+	movl	36(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	16(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	44(%rsp),%r12d
+	movl	%ebx,%r13d
+	addl	%r14d,%r12d
+	movl	%r9d,%r14d
+	rorl	$14,%r13d
+	movl	%ecx,%r15d
+	movl	%r12d,44(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	rorl	$5,%r13d
+	addl	%r8d,%r12d
+	xorl	%r9d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%ebx,%r15d
+	movl	%r10d,%r8d
+
+	rorl	$11,%r14d
+	xorl	%ebx,%r13d
+	xorl	%edx,%r15d
+
+	xorl	%r11d,%r8d
+	xorl	%r9d,%r14d
+	addl	%r15d,%r12d
+	movl	%r10d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r9d,%r8d
+	andl	%r11d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%r8d
+
+	addl	%r12d,%eax
+	addl	%r12d,%r8d
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%r8d
+
+	movl	52(%rsp),%r13d
+	movl	40(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	20(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	48(%rsp),%r12d
+	movl	%eax,%r13d
+	addl	%r14d,%r12d
+	movl	%r8d,%r14d
+	rorl	$14,%r13d
+	movl	%ebx,%r15d
+	movl	%r12d,48(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	rorl	$5,%r13d
+	addl	%edx,%r12d
+	xorl	%r8d,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%eax,%r15d
+	movl	%r9d,%edx
+
+	rorl	$11,%r14d
+	xorl	%eax,%r13d
+	xorl	%ecx,%r15d
+
+	xorl	%r10d,%edx
+	xorl	%r8d,%r14d
+	addl	%r15d,%r12d
+	movl	%r9d,%r15d
+
+	rorl	$6,%r13d
+	andl	%r8d,%edx
+	andl	%r10d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%edx
+
+	addl	%r12d,%r11d
+	addl	%r12d,%edx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%edx
+
+	movl	56(%rsp),%r13d
+	movl	44(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	24(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	52(%rsp),%r12d
+	movl	%r11d,%r13d
+	addl	%r14d,%r12d
+	movl	%edx,%r14d
+	rorl	$14,%r13d
+	movl	%eax,%r15d
+	movl	%r12d,52(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	rorl	$5,%r13d
+	addl	%ecx,%r12d
+	xorl	%edx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r11d,%r15d
+	movl	%r8d,%ecx
+
+	rorl	$11,%r14d
+	xorl	%r11d,%r13d
+	xorl	%ebx,%r15d
+
+	xorl	%r9d,%ecx
+	xorl	%edx,%r14d
+	addl	%r15d,%r12d
+	movl	%r8d,%r15d
+
+	rorl	$6,%r13d
+	andl	%edx,%ecx
+	andl	%r9d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ecx
+
+	addl	%r12d,%r10d
+	addl	%r12d,%ecx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ecx
+
+	movl	60(%rsp),%r13d
+	movl	48(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	28(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	56(%rsp),%r12d
+	movl	%r10d,%r13d
+	addl	%r14d,%r12d
+	movl	%ecx,%r14d
+	rorl	$14,%r13d
+	movl	%r11d,%r15d
+	movl	%r12d,56(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	rorl	$5,%r13d
+	addl	%ebx,%r12d
+	xorl	%ecx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r10d,%r15d
+	movl	%edx,%ebx
+
+	rorl	$11,%r14d
+	xorl	%r10d,%r13d
+	xorl	%eax,%r15d
+
+	xorl	%r8d,%ebx
+	xorl	%ecx,%r14d
+	addl	%r15d,%r12d
+	movl	%edx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ecx,%ebx
+	andl	%r8d,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%ebx
+
+	addl	%r12d,%r9d
+	addl	%r12d,%ebx
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%ebx
+
+	movl	0(%rsp),%r13d
+	movl	52(%rsp),%r14d
+	movl	%r13d,%r12d
+	movl	%r14d,%r15d
+
+	rorl	$11,%r12d
+	xorl	%r13d,%r12d
+	shrl	$3,%r13d
+
+	rorl	$7,%r12d
+	xorl	%r12d,%r13d
+	movl	32(%rsp),%r12d
+
+	rorl	$2,%r15d
+	xorl	%r14d,%r15d
+	shrl	$10,%r14d
+
+	rorl	$17,%r15d
+	addl	%r13d,%r12d
+	xorl	%r15d,%r14d
+
+	addl	60(%rsp),%r12d
+	movl	%r9d,%r13d
+	addl	%r14d,%r12d
+	movl	%ebx,%r14d
+	rorl	$14,%r13d
+	movl	%r10d,%r15d
+	movl	%r12d,60(%rsp)
+
+	rorl	$9,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	rorl	$5,%r13d
+	addl	%eax,%r12d
+	xorl	%ebx,%r14d
+
+	addl	(%rbp,%rdi,4),%r12d
+	andl	%r9d,%r15d
+	movl	%ecx,%eax
+
+	rorl	$11,%r14d
+	xorl	%r9d,%r13d
+	xorl	%r11d,%r15d
+
+	xorl	%edx,%eax
+	xorl	%ebx,%r14d
+	addl	%r15d,%r12d
+	movl	%ecx,%r15d
+
+	rorl	$6,%r13d
+	andl	%ebx,%eax
+	andl	%edx,%r15d
+
+	rorl	$2,%r14d
+	addl	%r13d,%r12d
+	addl	%r15d,%eax
+
+	addl	%r12d,%r8d
+	addl	%r12d,%eax
+	leaq	1(%rdi),%rdi
+	addl	%r14d,%eax
+
+	cmpq	$64,%rdi
+	jb	.Lrounds_16_xx
+
+	movq	64+0(%rsp),%rdi
+	leaq	64(%rsi),%rsi
+
+	addl	0(%rdi),%eax
+	addl	4(%rdi),%ebx
+	addl	8(%rdi),%ecx
+	addl	12(%rdi),%edx
+	addl	16(%rdi),%r8d
+	addl	20(%rdi),%r9d
+	addl	24(%rdi),%r10d
+	addl	28(%rdi),%r11d
+
+	cmpq	64+16(%rsp),%rsi
+
+	movl	%eax,0(%rdi)
+	movl	%ebx,4(%rdi)
+	movl	%ecx,8(%rdi)
+	movl	%edx,12(%rdi)
+	movl	%r8d,16(%rdi)
+	movl	%r9d,20(%rdi)
+	movl	%r10d,24(%rdi)
+	movl	%r11d,28(%rdi)
+	jb	.Lloop
+
+	movq	64+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_sha256_block_data_order:
+.p2align	6
+
+K256:
+.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
diff --git a/crypto/sha/sha256-mips.S b/crypto/sha/sha256-mips.S
new file mode 100644
index 0000000..3070f55
--- /dev/null
+++ b/crypto/sha/sha256-mips.S
@@ -0,0 +1,1997 @@
+.text
+.set	noat
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+
+.align	5
+.globl	sha256_block_data_order
+.ent	sha256_block_data_order
+sha256_block_data_order:
+	.frame	$29,128,$31
+	.mask	3237937152,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,128
+	sw	$31,128-1*4($29)
+	sw	$30,128-2*4($29)
+	sw	$23,128-3*4($29)
+	sw	$22,128-4*4($29)
+	sw	$21,128-5*4($29)
+	sw	$20,128-6*4($29)
+	sw	$19,128-7*4($29)
+	sw	$18,128-8*4($29)
+	sw	$17,128-9*4($29)
+	sw	$16,128-10*4($29)
+	sll $23,$6,6
+	.set	reorder
+	la	$6,K256		# PIC-ified 'load address'
+
+	lw	$1,0*4($4)		# load context
+	lw	$2,1*4($4)
+	lw	$3,2*4($4)
+	lw	$7,3*4($4)
+	lw	$24,4*4($4)
+	lw	$25,5*4($4)
+	lw	$30,6*4($4)
+	lw	$31,7*4($4)
+
+	add $23,$5		# pointer to the end of input
+	sw	$23,16*4($29)
+	b	.Loop
+
+.align	5
+.Loop:
+	lwl	$8,3($5)
+	lwr	$8,0($5)
+	lwl	$9,7($5)
+	lwr	$9,4($5)
+	srl	$13,$8,24		# byte swap(0)
+	srl	$14,$8,8
+	andi	$15,$8,0xFF00
+	sll	$8,$8,24
+	andi	$14,0xFF00
+	sll	$15,$15,8
+	or	$8,$13
+	or	$14,$15
+	or	$8,$14
+	addu	$12,$8,$31			# 0
+	srl	$31,$24,6
+	xor	$15,$25,$30
+	sll	$14,$24,7
+	and	$15,$24
+	srl	$13,$24,11
+	xor	$31,$14
+	sll	$14,$24,21
+	xor	$31,$13
+	srl	$13,$24,25
+	xor	$31,$14
+	sll	$14,$24,26
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$12,$15
+	lw	$15,0($6)		# K[0]
+	sll	$14,$1,10
+	addu	$12,$13
+	srl	$13,$1,13
+	xor	$31,$14
+	sll	$14,$1,19
+	xor	$31,$13
+	srl	$13,$1,22
+	xor	$31,$14
+	sll	$14,$1,30
+	xor	$31,$13
+	sw	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	addu	$12,$15			# +=K[0]
+	addu	$31,$14
+
+	addu	$7,$12
+	addu	$31,$12
+	lwl	$10,11($5)
+	lwr	$10,8($5)
+	srl	$14,$9,24		# byte swap(1)
+	srl	$15,$9,8
+	andi	$16,$9,0xFF00
+	sll	$9,$9,24
+	andi	$15,0xFF00
+	sll	$16,$16,8
+	or	$9,$14
+	or	$15,$16
+	or	$9,$15
+	addu	$13,$9,$30			# 1
+	srl	$30,$7,6
+	xor	$16,$24,$25
+	sll	$15,$7,7
+	and	$16,$7
+	srl	$14,$7,11
+	xor	$30,$15
+	sll	$15,$7,21
+	xor	$30,$14
+	srl	$14,$7,25
+	xor	$30,$15
+	sll	$15,$7,26
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$13,$16
+	lw	$16,4($6)		# K[1]
+	sll	$15,$31,10
+	addu	$13,$14
+	srl	$14,$31,13
+	xor	$30,$15
+	sll	$15,$31,19
+	xor	$30,$14
+	srl	$14,$31,22
+	xor	$30,$15
+	sll	$15,$31,30
+	xor	$30,$14
+	sw	$9,4($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	addu	$13,$16			# +=K[1]
+	addu	$30,$15
+
+	addu	$3,$13
+	addu	$30,$13
+	lwl	$11,15($5)
+	lwr	$11,12($5)
+	srl	$15,$10,24		# byte swap(2)
+	srl	$16,$10,8
+	andi	$17,$10,0xFF00
+	sll	$10,$10,24
+	andi	$16,0xFF00
+	sll	$17,$17,8
+	or	$10,$15
+	or	$16,$17
+	or	$10,$16
+	addu	$14,$10,$25			# 2
+	srl	$25,$3,6
+	xor	$17,$7,$24
+	sll	$16,$3,7
+	and	$17,$3
+	srl	$15,$3,11
+	xor	$25,$16
+	sll	$16,$3,21
+	xor	$25,$15
+	srl	$15,$3,25
+	xor	$25,$16
+	sll	$16,$3,26
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$14,$17
+	lw	$17,8($6)		# K[2]
+	sll	$16,$30,10
+	addu	$14,$15
+	srl	$15,$30,13
+	xor	$25,$16
+	sll	$16,$30,19
+	xor	$25,$15
+	srl	$15,$30,22
+	xor	$25,$16
+	sll	$16,$30,30
+	xor	$25,$15
+	sw	$10,8($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	addu	$14,$17			# +=K[2]
+	addu	$25,$16
+
+	addu	$2,$14
+	addu	$25,$14
+	lwl	$12,19($5)
+	lwr	$12,16($5)
+	srl	$16,$11,24		# byte swap(3)
+	srl	$17,$11,8
+	andi	$18,$11,0xFF00
+	sll	$11,$11,24
+	andi	$17,0xFF00
+	sll	$18,$18,8
+	or	$11,$16
+	or	$17,$18
+	or	$11,$17
+	addu	$15,$11,$24			# 3
+	srl	$24,$2,6
+	xor	$18,$3,$7
+	sll	$17,$2,7
+	and	$18,$2
+	srl	$16,$2,11
+	xor	$24,$17
+	sll	$17,$2,21
+	xor	$24,$16
+	srl	$16,$2,25
+	xor	$24,$17
+	sll	$17,$2,26
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$15,$18
+	lw	$18,12($6)		# K[3]
+	sll	$17,$25,10
+	addu	$15,$16
+	srl	$16,$25,13
+	xor	$24,$17
+	sll	$17,$25,19
+	xor	$24,$16
+	srl	$16,$25,22
+	xor	$24,$17
+	sll	$17,$25,30
+	xor	$24,$16
+	sw	$11,12($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	addu	$15,$18			# +=K[3]
+	addu	$24,$17
+
+	addu	$1,$15
+	addu	$24,$15
+	lwl	$13,23($5)
+	lwr	$13,20($5)
+	srl	$17,$12,24		# byte swap(4)
+	srl	$18,$12,8
+	andi	$19,$12,0xFF00
+	sll	$12,$12,24
+	andi	$18,0xFF00
+	sll	$19,$19,8
+	or	$12,$17
+	or	$18,$19
+	or	$12,$18
+	addu	$16,$12,$7			# 4
+	srl	$7,$1,6
+	xor	$19,$2,$3
+	sll	$18,$1,7
+	and	$19,$1
+	srl	$17,$1,11
+	xor	$7,$18
+	sll	$18,$1,21
+	xor	$7,$17
+	srl	$17,$1,25
+	xor	$7,$18
+	sll	$18,$1,26
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$16,$19
+	lw	$19,16($6)		# K[4]
+	sll	$18,$24,10
+	addu	$16,$17
+	srl	$17,$24,13
+	xor	$7,$18
+	sll	$18,$24,19
+	xor	$7,$17
+	srl	$17,$24,22
+	xor	$7,$18
+	sll	$18,$24,30
+	xor	$7,$17
+	sw	$12,16($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	addu	$16,$19			# +=K[4]
+	addu	$7,$18
+
+	addu	$31,$16
+	addu	$7,$16
+	lwl	$14,27($5)
+	lwr	$14,24($5)
+	srl	$18,$13,24		# byte swap(5)
+	srl	$19,$13,8
+	andi	$20,$13,0xFF00
+	sll	$13,$13,24
+	andi	$19,0xFF00
+	sll	$20,$20,8
+	or	$13,$18
+	or	$19,$20
+	or	$13,$19
+	addu	$17,$13,$3			# 5
+	srl	$3,$31,6
+	xor	$20,$1,$2
+	sll	$19,$31,7
+	and	$20,$31
+	srl	$18,$31,11
+	xor	$3,$19
+	sll	$19,$31,21
+	xor	$3,$18
+	srl	$18,$31,25
+	xor	$3,$19
+	sll	$19,$31,26
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$17,$20
+	lw	$20,20($6)		# K[5]
+	sll	$19,$7,10
+	addu	$17,$18
+	srl	$18,$7,13
+	xor	$3,$19
+	sll	$19,$7,19
+	xor	$3,$18
+	srl	$18,$7,22
+	xor	$3,$19
+	sll	$19,$7,30
+	xor	$3,$18
+	sw	$13,20($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	addu	$17,$20			# +=K[5]
+	addu	$3,$19
+
+	addu	$30,$17
+	addu	$3,$17
+	lwl	$15,31($5)
+	lwr	$15,28($5)
+	srl	$19,$14,24		# byte swap(6)
+	srl	$20,$14,8
+	andi	$21,$14,0xFF00
+	sll	$14,$14,24
+	andi	$20,0xFF00
+	sll	$21,$21,8
+	or	$14,$19
+	or	$20,$21
+	or	$14,$20
+	addu	$18,$14,$2			# 6
+	srl	$2,$30,6
+	xor	$21,$31,$1
+	sll	$20,$30,7
+	and	$21,$30
+	srl	$19,$30,11
+	xor	$2,$20
+	sll	$20,$30,21
+	xor	$2,$19
+	srl	$19,$30,25
+	xor	$2,$20
+	sll	$20,$30,26
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$18,$21
+	lw	$21,24($6)		# K[6]
+	sll	$20,$3,10
+	addu	$18,$19
+	srl	$19,$3,13
+	xor	$2,$20
+	sll	$20,$3,19
+	xor	$2,$19
+	srl	$19,$3,22
+	xor	$2,$20
+	sll	$20,$3,30
+	xor	$2,$19
+	sw	$14,24($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	addu	$18,$21			# +=K[6]
+	addu	$2,$20
+
+	addu	$25,$18
+	addu	$2,$18
+	lwl	$16,35($5)
+	lwr	$16,32($5)
+	srl	$20,$15,24		# byte swap(7)
+	srl	$21,$15,8
+	andi	$22,$15,0xFF00
+	sll	$15,$15,24
+	andi	$21,0xFF00
+	sll	$22,$22,8
+	or	$15,$20
+	or	$21,$22
+	or	$15,$21
+	addu	$19,$15,$1			# 7
+	srl	$1,$25,6
+	xor	$22,$30,$31
+	sll	$21,$25,7
+	and	$22,$25
+	srl	$20,$25,11
+	xor	$1,$21
+	sll	$21,$25,21
+	xor	$1,$20
+	srl	$20,$25,25
+	xor	$1,$21
+	sll	$21,$25,26
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$19,$22
+	lw	$22,28($6)		# K[7]
+	sll	$21,$2,10
+	addu	$19,$20
+	srl	$20,$2,13
+	xor	$1,$21
+	sll	$21,$2,19
+	xor	$1,$20
+	srl	$20,$2,22
+	xor	$1,$21
+	sll	$21,$2,30
+	xor	$1,$20
+	sw	$15,28($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	addu	$19,$22			# +=K[7]
+	addu	$1,$21
+
+	addu	$24,$19
+	addu	$1,$19
+	lwl	$17,39($5)
+	lwr	$17,36($5)
+	srl	$21,$16,24		# byte swap(8)
+	srl	$22,$16,8
+	andi	$23,$16,0xFF00
+	sll	$16,$16,24
+	andi	$22,0xFF00
+	sll	$23,$23,8
+	or	$16,$21
+	or	$22,$23
+	or	$16,$22
+	addu	$20,$16,$31			# 8
+	srl	$31,$24,6
+	xor	$23,$25,$30
+	sll	$22,$24,7
+	and	$23,$24
+	srl	$21,$24,11
+	xor	$31,$22
+	sll	$22,$24,21
+	xor	$31,$21
+	srl	$21,$24,25
+	xor	$31,$22
+	sll	$22,$24,26
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$20,$23
+	lw	$23,32($6)		# K[8]
+	sll	$22,$1,10
+	addu	$20,$21
+	srl	$21,$1,13
+	xor	$31,$22
+	sll	$22,$1,19
+	xor	$31,$21
+	srl	$21,$1,22
+	xor	$31,$22
+	sll	$22,$1,30
+	xor	$31,$21
+	sw	$16,32($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	addu	$20,$23			# +=K[8]
+	addu	$31,$22
+
+	addu	$7,$20
+	addu	$31,$20
+	lwl	$18,43($5)
+	lwr	$18,40($5)
+	srl	$22,$17,24		# byte swap(9)
+	srl	$23,$17,8
+	andi	$8,$17,0xFF00
+	sll	$17,$17,24
+	andi	$23,0xFF00
+	sll	$8,$8,8
+	or	$17,$22
+	or	$23,$8
+	or	$17,$23
+	addu	$21,$17,$30			# 9
+	srl	$30,$7,6
+	xor	$8,$24,$25
+	sll	$23,$7,7
+	and	$8,$7
+	srl	$22,$7,11
+	xor	$30,$23
+	sll	$23,$7,21
+	xor	$30,$22
+	srl	$22,$7,25
+	xor	$30,$23
+	sll	$23,$7,26
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$21,$8
+	lw	$8,36($6)		# K[9]
+	sll	$23,$31,10
+	addu	$21,$22
+	srl	$22,$31,13
+	xor	$30,$23
+	sll	$23,$31,19
+	xor	$30,$22
+	srl	$22,$31,22
+	xor	$30,$23
+	sll	$23,$31,30
+	xor	$30,$22
+	sw	$17,36($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	addu	$21,$8			# +=K[9]
+	addu	$30,$23
+
+	addu	$3,$21
+	addu	$30,$21
+	lwl	$19,47($5)
+	lwr	$19,44($5)
+	srl	$23,$18,24		# byte swap(10)
+	srl	$8,$18,8
+	andi	$9,$18,0xFF00
+	sll	$18,$18,24
+	andi	$8,0xFF00
+	sll	$9,$9,8
+	or	$18,$23
+	or	$8,$9
+	or	$18,$8
+	addu	$22,$18,$25			# 10
+	srl	$25,$3,6
+	xor	$9,$7,$24
+	sll	$8,$3,7
+	and	$9,$3
+	srl	$23,$3,11
+	xor	$25,$8
+	sll	$8,$3,21
+	xor	$25,$23
+	srl	$23,$3,25
+	xor	$25,$8
+	sll	$8,$3,26
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$22,$9
+	lw	$9,40($6)		# K[10]
+	sll	$8,$30,10
+	addu	$22,$23
+	srl	$23,$30,13
+	xor	$25,$8
+	sll	$8,$30,19
+	xor	$25,$23
+	srl	$23,$30,22
+	xor	$25,$8
+	sll	$8,$30,30
+	xor	$25,$23
+	sw	$18,40($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	addu	$22,$9			# +=K[10]
+	addu	$25,$8
+
+	addu	$2,$22
+	addu	$25,$22
+	lwl	$20,51($5)
+	lwr	$20,48($5)
+	srl	$8,$19,24		# byte swap(11)
+	srl	$9,$19,8
+	andi	$10,$19,0xFF00
+	sll	$19,$19,24
+	andi	$9,0xFF00
+	sll	$10,$10,8
+	or	$19,$8
+	or	$9,$10
+	or	$19,$9
+	addu	$23,$19,$24			# 11
+	srl	$24,$2,6
+	xor	$10,$3,$7
+	sll	$9,$2,7
+	and	$10,$2
+	srl	$8,$2,11
+	xor	$24,$9
+	sll	$9,$2,21
+	xor	$24,$8
+	srl	$8,$2,25
+	xor	$24,$9
+	sll	$9,$2,26
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$23,$10
+	lw	$10,44($6)		# K[11]
+	sll	$9,$25,10
+	addu	$23,$8
+	srl	$8,$25,13
+	xor	$24,$9
+	sll	$9,$25,19
+	xor	$24,$8
+	srl	$8,$25,22
+	xor	$24,$9
+	sll	$9,$25,30
+	xor	$24,$8
+	sw	$19,44($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	addu	$23,$10			# +=K[11]
+	addu	$24,$9
+
+	addu	$1,$23
+	addu	$24,$23
+	lwl	$21,55($5)
+	lwr	$21,52($5)
+	srl	$9,$20,24		# byte swap(12)
+	srl	$10,$20,8
+	andi	$11,$20,0xFF00
+	sll	$20,$20,24
+	andi	$10,0xFF00
+	sll	$11,$11,8
+	or	$20,$9
+	or	$10,$11
+	or	$20,$10
+	addu	$8,$20,$7			# 12
+	srl	$7,$1,6
+	xor	$11,$2,$3
+	sll	$10,$1,7
+	and	$11,$1
+	srl	$9,$1,11
+	xor	$7,$10
+	sll	$10,$1,21
+	xor	$7,$9
+	srl	$9,$1,25
+	xor	$7,$10
+	sll	$10,$1,26
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$8,$11
+	lw	$11,48($6)		# K[12]
+	sll	$10,$24,10
+	addu	$8,$9
+	srl	$9,$24,13
+	xor	$7,$10
+	sll	$10,$24,19
+	xor	$7,$9
+	srl	$9,$24,22
+	xor	$7,$10
+	sll	$10,$24,30
+	xor	$7,$9
+	sw	$20,48($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	addu	$8,$11			# +=K[12]
+	addu	$7,$10
+
+	addu	$31,$8
+	addu	$7,$8
+	lwl	$22,59($5)
+	lwr	$22,56($5)
+	srl	$10,$21,24		# byte swap(13)
+	srl	$11,$21,8
+	andi	$12,$21,0xFF00
+	sll	$21,$21,24
+	andi	$11,0xFF00
+	sll	$12,$12,8
+	or	$21,$10
+	or	$11,$12
+	or	$21,$11
+	addu	$9,$21,$3			# 13
+	srl	$3,$31,6
+	xor	$12,$1,$2
+	sll	$11,$31,7
+	and	$12,$31
+	srl	$10,$31,11
+	xor	$3,$11
+	sll	$11,$31,21
+	xor	$3,$10
+	srl	$10,$31,25
+	xor	$3,$11
+	sll	$11,$31,26
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$9,$12
+	lw	$12,52($6)		# K[13]
+	sll	$11,$7,10
+	addu	$9,$10
+	srl	$10,$7,13
+	xor	$3,$11
+	sll	$11,$7,19
+	xor	$3,$10
+	srl	$10,$7,22
+	xor	$3,$11
+	sll	$11,$7,30
+	xor	$3,$10
+	sw	$21,52($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	addu	$9,$12			# +=K[13]
+	addu	$3,$11
+
+	addu	$30,$9
+	addu	$3,$9
+	lw	$8,0($29)	# prefetch from ring buffer
+	lwl	$23,63($5)
+	lwr	$23,60($5)
+	srl	$11,$22,24		# byte swap(14)
+	srl	$12,$22,8
+	andi	$13,$22,0xFF00
+	sll	$22,$22,24
+	andi	$12,0xFF00
+	sll	$13,$13,8
+	or	$22,$11
+	or	$12,$13
+	or	$22,$12
+	addu	$10,$22,$2			# 14
+	srl	$2,$30,6
+	xor	$13,$31,$1
+	sll	$12,$30,7
+	and	$13,$30
+	srl	$11,$30,11
+	xor	$2,$12
+	sll	$12,$30,21
+	xor	$2,$11
+	srl	$11,$30,25
+	xor	$2,$12
+	sll	$12,$30,26
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$10,$13
+	lw	$13,56($6)		# K[14]
+	sll	$12,$3,10
+	addu	$10,$11
+	srl	$11,$3,13
+	xor	$2,$12
+	sll	$12,$3,19
+	xor	$2,$11
+	srl	$11,$3,22
+	xor	$2,$12
+	sll	$12,$3,30
+	xor	$2,$11
+	sw	$22,56($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	addu	$10,$13			# +=K[14]
+	addu	$2,$12
+
+	addu	$25,$10
+	addu	$2,$10
+	lw	$9,4($29)	# prefetch from ring buffer
+	srl	$12,$23,24		# byte swap(15)
+	srl	$13,$23,8
+	andi	$14,$23,0xFF00
+	sll	$23,$23,24
+	andi	$13,0xFF00
+	sll	$14,$14,8
+	or	$23,$12
+	or	$13,$14
+	or	$23,$13
+	addu	$11,$23,$1			# 15
+	srl	$1,$25,6
+	xor	$14,$30,$31
+	sll	$13,$25,7
+	and	$14,$25
+	srl	$12,$25,11
+	xor	$1,$13
+	sll	$13,$25,21
+	xor	$1,$12
+	srl	$12,$25,25
+	xor	$1,$13
+	sll	$13,$25,26
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$11,$14
+	lw	$14,60($6)		# K[15]
+	sll	$13,$2,10
+	addu	$11,$12
+	srl	$12,$2,13
+	xor	$1,$13
+	sll	$13,$2,19
+	xor	$1,$12
+	srl	$12,$2,22
+	xor	$1,$13
+	sll	$13,$2,30
+	xor	$1,$12
+	sw	$23,60($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	addu	$11,$14			# +=K[15]
+	addu	$1,$13
+
+	addu	$24,$11
+	addu	$1,$11
+	lw	$10,8($29)	# prefetch from ring buffer
+	b	.L16_xx
+.align	4
+.L16_xx:
+	srl	$14,$9,3		# Xupdate(16)
+	addu	$8,$17			# +=X[i+9]
+	sll	$13,$9,14
+	srl	$12,$9,7
+	xor	$14,$13
+	sll	$13,11
+	xor	$14,$12
+	srl	$12,$9,18
+	xor	$14,$13
+
+	srl	$15,$22,10
+	xor	$14,$12			# sigma0(X[i+1])
+	sll	$13,$22,13
+	addu	$8,$14
+	srl	$12,$22,17
+	xor	$15,$13
+	sll	$13,2
+	xor	$15,$12
+	srl	$12,$22,19
+	xor	$15,$13
+
+	xor	$15,$12			# sigma1(X[i+14])
+	addu	$8,$15
+	addu	$12,$8,$31			# 16
+	srl	$31,$24,6
+	xor	$15,$25,$30
+	sll	$14,$24,7
+	and	$15,$24
+	srl	$13,$24,11
+	xor	$31,$14
+	sll	$14,$24,21
+	xor	$31,$13
+	srl	$13,$24,25
+	xor	$31,$14
+	sll	$14,$24,26
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$12,$15
+	lw	$15,64($6)		# K[16]
+	sll	$14,$1,10
+	addu	$12,$13
+	srl	$13,$1,13
+	xor	$31,$14
+	sll	$14,$1,19
+	xor	$31,$13
+	srl	$13,$1,22
+	xor	$31,$14
+	sll	$14,$1,30
+	xor	$31,$13
+	sw	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	addu	$12,$15			# +=K[16]
+	addu	$31,$14
+
+	addu	$7,$12
+	addu	$31,$12
+	lw	$11,12($29)	# prefetch from ring buffer
+	srl	$15,$10,3		# Xupdate(17)
+	addu	$9,$18			# +=X[i+9]
+	sll	$14,$10,14
+	srl	$13,$10,7
+	xor	$15,$14
+	sll	$14,11
+	xor	$15,$13
+	srl	$13,$10,18
+	xor	$15,$14
+
+	srl	$16,$23,10
+	xor	$15,$13			# sigma0(X[i+1])
+	sll	$14,$23,13
+	addu	$9,$15
+	srl	$13,$23,17
+	xor	$16,$14
+	sll	$14,2
+	xor	$16,$13
+	srl	$13,$23,19
+	xor	$16,$14
+
+	xor	$16,$13			# sigma1(X[i+14])
+	addu	$9,$16
+	addu	$13,$9,$30			# 17
+	srl	$30,$7,6
+	xor	$16,$24,$25
+	sll	$15,$7,7
+	and	$16,$7
+	srl	$14,$7,11
+	xor	$30,$15
+	sll	$15,$7,21
+	xor	$30,$14
+	srl	$14,$7,25
+	xor	$30,$15
+	sll	$15,$7,26
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$13,$16
+	lw	$16,68($6)		# K[17]
+	sll	$15,$31,10
+	addu	$13,$14
+	srl	$14,$31,13
+	xor	$30,$15
+	sll	$15,$31,19
+	xor	$30,$14
+	srl	$14,$31,22
+	xor	$30,$15
+	sll	$15,$31,30
+	xor	$30,$14
+	sw	$9,4($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	addu	$13,$16			# +=K[17]
+	addu	$30,$15
+
+	addu	$3,$13
+	addu	$30,$13
+	lw	$12,16($29)	# prefetch from ring buffer
+	srl	$16,$11,3		# Xupdate(18)
+	addu	$10,$19			# +=X[i+9]
+	sll	$15,$11,14
+	srl	$14,$11,7
+	xor	$16,$15
+	sll	$15,11
+	xor	$16,$14
+	srl	$14,$11,18
+	xor	$16,$15
+
+	srl	$17,$8,10
+	xor	$16,$14			# sigma0(X[i+1])
+	sll	$15,$8,13
+	addu	$10,$16
+	srl	$14,$8,17
+	xor	$17,$15
+	sll	$15,2
+	xor	$17,$14
+	srl	$14,$8,19
+	xor	$17,$15
+
+	xor	$17,$14			# sigma1(X[i+14])
+	addu	$10,$17
+	addu	$14,$10,$25			# 18
+	srl	$25,$3,6
+	xor	$17,$7,$24
+	sll	$16,$3,7
+	and	$17,$3
+	srl	$15,$3,11
+	xor	$25,$16
+	sll	$16,$3,21
+	xor	$25,$15
+	srl	$15,$3,25
+	xor	$25,$16
+	sll	$16,$3,26
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$14,$17
+	lw	$17,72($6)		# K[18]
+	sll	$16,$30,10
+	addu	$14,$15
+	srl	$15,$30,13
+	xor	$25,$16
+	sll	$16,$30,19
+	xor	$25,$15
+	srl	$15,$30,22
+	xor	$25,$16
+	sll	$16,$30,30
+	xor	$25,$15
+	sw	$10,8($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	addu	$14,$17			# +=K[18]
+	addu	$25,$16
+
+	addu	$2,$14
+	addu	$25,$14
+	lw	$13,20($29)	# prefetch from ring buffer
+	srl	$17,$12,3		# Xupdate(19)
+	addu	$11,$20			# +=X[i+9]
+	sll	$16,$12,14
+	srl	$15,$12,7
+	xor	$17,$16
+	sll	$16,11
+	xor	$17,$15
+	srl	$15,$12,18
+	xor	$17,$16
+
+	srl	$18,$9,10
+	xor	$17,$15			# sigma0(X[i+1])
+	sll	$16,$9,13
+	addu	$11,$17
+	srl	$15,$9,17
+	xor	$18,$16
+	sll	$16,2
+	xor	$18,$15
+	srl	$15,$9,19
+	xor	$18,$16
+
+	xor	$18,$15			# sigma1(X[i+14])
+	addu	$11,$18
+	addu	$15,$11,$24			# 19
+	srl	$24,$2,6
+	xor	$18,$3,$7
+	sll	$17,$2,7
+	and	$18,$2
+	srl	$16,$2,11
+	xor	$24,$17
+	sll	$17,$2,21
+	xor	$24,$16
+	srl	$16,$2,25
+	xor	$24,$17
+	sll	$17,$2,26
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$15,$18
+	lw	$18,76($6)		# K[19]
+	sll	$17,$25,10
+	addu	$15,$16
+	srl	$16,$25,13
+	xor	$24,$17
+	sll	$17,$25,19
+	xor	$24,$16
+	srl	$16,$25,22
+	xor	$24,$17
+	sll	$17,$25,30
+	xor	$24,$16
+	sw	$11,12($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	addu	$15,$18			# +=K[19]
+	addu	$24,$17
+
+	addu	$1,$15
+	addu	$24,$15
+	lw	$14,24($29)	# prefetch from ring buffer
+	srl	$18,$13,3		# Xupdate(20)
+	addu	$12,$21			# +=X[i+9]
+	sll	$17,$13,14
+	srl	$16,$13,7
+	xor	$18,$17
+	sll	$17,11
+	xor	$18,$16
+	srl	$16,$13,18
+	xor	$18,$17
+
+	srl	$19,$10,10
+	xor	$18,$16			# sigma0(X[i+1])
+	sll	$17,$10,13
+	addu	$12,$18
+	srl	$16,$10,17
+	xor	$19,$17
+	sll	$17,2
+	xor	$19,$16
+	srl	$16,$10,19
+	xor	$19,$17
+
+	xor	$19,$16			# sigma1(X[i+14])
+	addu	$12,$19
+	addu	$16,$12,$7			# 20
+	srl	$7,$1,6
+	xor	$19,$2,$3
+	sll	$18,$1,7
+	and	$19,$1
+	srl	$17,$1,11
+	xor	$7,$18
+	sll	$18,$1,21
+	xor	$7,$17
+	srl	$17,$1,25
+	xor	$7,$18
+	sll	$18,$1,26
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$16,$19
+	lw	$19,80($6)		# K[20]
+	sll	$18,$24,10
+	addu	$16,$17
+	srl	$17,$24,13
+	xor	$7,$18
+	sll	$18,$24,19
+	xor	$7,$17
+	srl	$17,$24,22
+	xor	$7,$18
+	sll	$18,$24,30
+	xor	$7,$17
+	sw	$12,16($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	addu	$16,$19			# +=K[20]
+	addu	$7,$18
+
+	addu	$31,$16
+	addu	$7,$16
+	lw	$15,28($29)	# prefetch from ring buffer
+	srl	$19,$14,3		# Xupdate(21)
+	addu	$13,$22			# +=X[i+9]
+	sll	$18,$14,14
+	srl	$17,$14,7
+	xor	$19,$18
+	sll	$18,11
+	xor	$19,$17
+	srl	$17,$14,18
+	xor	$19,$18
+
+	srl	$20,$11,10
+	xor	$19,$17			# sigma0(X[i+1])
+	sll	$18,$11,13
+	addu	$13,$19
+	srl	$17,$11,17
+	xor	$20,$18
+	sll	$18,2
+	xor	$20,$17
+	srl	$17,$11,19
+	xor	$20,$18
+
+	xor	$20,$17			# sigma1(X[i+14])
+	addu	$13,$20
+	addu	$17,$13,$3			# 21
+	srl	$3,$31,6
+	xor	$20,$1,$2
+	sll	$19,$31,7
+	and	$20,$31
+	srl	$18,$31,11
+	xor	$3,$19
+	sll	$19,$31,21
+	xor	$3,$18
+	srl	$18,$31,25
+	xor	$3,$19
+	sll	$19,$31,26
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$17,$20
+	lw	$20,84($6)		# K[21]
+	sll	$19,$7,10
+	addu	$17,$18
+	srl	$18,$7,13
+	xor	$3,$19
+	sll	$19,$7,19
+	xor	$3,$18
+	srl	$18,$7,22
+	xor	$3,$19
+	sll	$19,$7,30
+	xor	$3,$18
+	sw	$13,20($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	addu	$17,$20			# +=K[21]
+	addu	$3,$19
+
+	addu	$30,$17
+	addu	$3,$17
+	lw	$16,32($29)	# prefetch from ring buffer
+	srl	$20,$15,3		# Xupdate(22)
+	addu	$14,$23			# +=X[i+9]
+	sll	$19,$15,14
+	srl	$18,$15,7
+	xor	$20,$19
+	sll	$19,11
+	xor	$20,$18
+	srl	$18,$15,18
+	xor	$20,$19
+
+	srl	$21,$12,10
+	xor	$20,$18			# sigma0(X[i+1])
+	sll	$19,$12,13
+	addu	$14,$20
+	srl	$18,$12,17
+	xor	$21,$19
+	sll	$19,2
+	xor	$21,$18
+	srl	$18,$12,19
+	xor	$21,$19
+
+	xor	$21,$18			# sigma1(X[i+14])
+	addu	$14,$21
+	addu	$18,$14,$2			# 22
+	srl	$2,$30,6
+	xor	$21,$31,$1
+	sll	$20,$30,7
+	and	$21,$30
+	srl	$19,$30,11
+	xor	$2,$20
+	sll	$20,$30,21
+	xor	$2,$19
+	srl	$19,$30,25
+	xor	$2,$20
+	sll	$20,$30,26
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$18,$21
+	lw	$21,88($6)		# K[22]
+	sll	$20,$3,10
+	addu	$18,$19
+	srl	$19,$3,13
+	xor	$2,$20
+	sll	$20,$3,19
+	xor	$2,$19
+	srl	$19,$3,22
+	xor	$2,$20
+	sll	$20,$3,30
+	xor	$2,$19
+	sw	$14,24($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	addu	$18,$21			# +=K[22]
+	addu	$2,$20
+
+	addu	$25,$18
+	addu	$2,$18
+	lw	$17,36($29)	# prefetch from ring buffer
+	srl	$21,$16,3		# Xupdate(23)
+	addu	$15,$8			# +=X[i+9]
+	sll	$20,$16,14
+	srl	$19,$16,7
+	xor	$21,$20
+	sll	$20,11
+	xor	$21,$19
+	srl	$19,$16,18
+	xor	$21,$20
+
+	srl	$22,$13,10
+	xor	$21,$19			# sigma0(X[i+1])
+	sll	$20,$13,13
+	addu	$15,$21
+	srl	$19,$13,17
+	xor	$22,$20
+	sll	$20,2
+	xor	$22,$19
+	srl	$19,$13,19
+	xor	$22,$20
+
+	xor	$22,$19			# sigma1(X[i+14])
+	addu	$15,$22
+	addu	$19,$15,$1			# 23
+	srl	$1,$25,6
+	xor	$22,$30,$31
+	sll	$21,$25,7
+	and	$22,$25
+	srl	$20,$25,11
+	xor	$1,$21
+	sll	$21,$25,21
+	xor	$1,$20
+	srl	$20,$25,25
+	xor	$1,$21
+	sll	$21,$25,26
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$19,$22
+	lw	$22,92($6)		# K[23]
+	sll	$21,$2,10
+	addu	$19,$20
+	srl	$20,$2,13
+	xor	$1,$21
+	sll	$21,$2,19
+	xor	$1,$20
+	srl	$20,$2,22
+	xor	$1,$21
+	sll	$21,$2,30
+	xor	$1,$20
+	sw	$15,28($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	addu	$19,$22			# +=K[23]
+	addu	$1,$21
+
+	addu	$24,$19
+	addu	$1,$19
+	lw	$18,40($29)	# prefetch from ring buffer
+	srl	$22,$17,3		# Xupdate(24)
+	addu	$16,$9			# +=X[i+9]
+	sll	$21,$17,14
+	srl	$20,$17,7
+	xor	$22,$21
+	sll	$21,11
+	xor	$22,$20
+	srl	$20,$17,18
+	xor	$22,$21
+
+	srl	$23,$14,10
+	xor	$22,$20			# sigma0(X[i+1])
+	sll	$21,$14,13
+	addu	$16,$22
+	srl	$20,$14,17
+	xor	$23,$21
+	sll	$21,2
+	xor	$23,$20
+	srl	$20,$14,19
+	xor	$23,$21
+
+	xor	$23,$20			# sigma1(X[i+14])
+	addu	$16,$23
+	addu	$20,$16,$31			# 24
+	srl	$31,$24,6
+	xor	$23,$25,$30
+	sll	$22,$24,7
+	and	$23,$24
+	srl	$21,$24,11
+	xor	$31,$22
+	sll	$22,$24,21
+	xor	$31,$21
+	srl	$21,$24,25
+	xor	$31,$22
+	sll	$22,$24,26
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$20,$23
+	lw	$23,96($6)		# K[24]
+	sll	$22,$1,10
+	addu	$20,$21
+	srl	$21,$1,13
+	xor	$31,$22
+	sll	$22,$1,19
+	xor	$31,$21
+	srl	$21,$1,22
+	xor	$31,$22
+	sll	$22,$1,30
+	xor	$31,$21
+	sw	$16,32($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	addu	$20,$23			# +=K[24]
+	addu	$31,$22
+
+	addu	$7,$20
+	addu	$31,$20
+	lw	$19,44($29)	# prefetch from ring buffer
+	srl	$23,$18,3		# Xupdate(25)
+	addu	$17,$10			# +=X[i+9]
+	sll	$22,$18,14
+	srl	$21,$18,7
+	xor	$23,$22
+	sll	$22,11
+	xor	$23,$21
+	srl	$21,$18,18
+	xor	$23,$22
+
+	srl	$8,$15,10
+	xor	$23,$21			# sigma0(X[i+1])
+	sll	$22,$15,13
+	addu	$17,$23
+	srl	$21,$15,17
+	xor	$8,$22
+	sll	$22,2
+	xor	$8,$21
+	srl	$21,$15,19
+	xor	$8,$22
+
+	xor	$8,$21			# sigma1(X[i+14])
+	addu	$17,$8
+	addu	$21,$17,$30			# 25
+	srl	$30,$7,6
+	xor	$8,$24,$25
+	sll	$23,$7,7
+	and	$8,$7
+	srl	$22,$7,11
+	xor	$30,$23
+	sll	$23,$7,21
+	xor	$30,$22
+	srl	$22,$7,25
+	xor	$30,$23
+	sll	$23,$7,26
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$21,$8
+	lw	$8,100($6)		# K[25]
+	sll	$23,$31,10
+	addu	$21,$22
+	srl	$22,$31,13
+	xor	$30,$23
+	sll	$23,$31,19
+	xor	$30,$22
+	srl	$22,$31,22
+	xor	$30,$23
+	sll	$23,$31,30
+	xor	$30,$22
+	sw	$17,36($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	addu	$21,$8			# +=K[25]
+	addu	$30,$23
+
+	addu	$3,$21
+	addu	$30,$21
+	lw	$20,48($29)	# prefetch from ring buffer
+	srl	$8,$19,3		# Xupdate(26)
+	addu	$18,$11			# +=X[i+9]
+	sll	$23,$19,14
+	srl	$22,$19,7
+	xor	$8,$23
+	sll	$23,11
+	xor	$8,$22
+	srl	$22,$19,18
+	xor	$8,$23
+
+	srl	$9,$16,10
+	xor	$8,$22			# sigma0(X[i+1])
+	sll	$23,$16,13
+	addu	$18,$8
+	srl	$22,$16,17
+	xor	$9,$23
+	sll	$23,2
+	xor	$9,$22
+	srl	$22,$16,19
+	xor	$9,$23
+
+	xor	$9,$22			# sigma1(X[i+14])
+	addu	$18,$9
+	addu	$22,$18,$25			# 26
+	srl	$25,$3,6
+	xor	$9,$7,$24
+	sll	$8,$3,7
+	and	$9,$3
+	srl	$23,$3,11
+	xor	$25,$8
+	sll	$8,$3,21
+	xor	$25,$23
+	srl	$23,$3,25
+	xor	$25,$8
+	sll	$8,$3,26
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$22,$9
+	lw	$9,104($6)		# K[26]
+	sll	$8,$30,10
+	addu	$22,$23
+	srl	$23,$30,13
+	xor	$25,$8
+	sll	$8,$30,19
+	xor	$25,$23
+	srl	$23,$30,22
+	xor	$25,$8
+	sll	$8,$30,30
+	xor	$25,$23
+	sw	$18,40($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	addu	$22,$9			# +=K[26]
+	addu	$25,$8
+
+	addu	$2,$22
+	addu	$25,$22
+	lw	$21,52($29)	# prefetch from ring buffer
+	srl	$9,$20,3		# Xupdate(27)
+	addu	$19,$12			# +=X[i+9]
+	sll	$8,$20,14
+	srl	$23,$20,7
+	xor	$9,$8
+	sll	$8,11
+	xor	$9,$23
+	srl	$23,$20,18
+	xor	$9,$8
+
+	srl	$10,$17,10
+	xor	$9,$23			# sigma0(X[i+1])
+	sll	$8,$17,13
+	addu	$19,$9
+	srl	$23,$17,17
+	xor	$10,$8
+	sll	$8,2
+	xor	$10,$23
+	srl	$23,$17,19
+	xor	$10,$8
+
+	xor	$10,$23			# sigma1(X[i+14])
+	addu	$19,$10
+	addu	$23,$19,$24			# 27
+	srl	$24,$2,6
+	xor	$10,$3,$7
+	sll	$9,$2,7
+	and	$10,$2
+	srl	$8,$2,11
+	xor	$24,$9
+	sll	$9,$2,21
+	xor	$24,$8
+	srl	$8,$2,25
+	xor	$24,$9
+	sll	$9,$2,26
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$23,$10
+	lw	$10,108($6)		# K[27]
+	sll	$9,$25,10
+	addu	$23,$8
+	srl	$8,$25,13
+	xor	$24,$9
+	sll	$9,$25,19
+	xor	$24,$8
+	srl	$8,$25,22
+	xor	$24,$9
+	sll	$9,$25,30
+	xor	$24,$8
+	sw	$19,44($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	addu	$23,$10			# +=K[27]
+	addu	$24,$9
+
+	addu	$1,$23
+	addu	$24,$23
+	lw	$22,56($29)	# prefetch from ring buffer
+	srl	$10,$21,3		# Xupdate(28)
+	addu	$20,$13			# +=X[i+9]
+	sll	$9,$21,14
+	srl	$8,$21,7
+	xor	$10,$9
+	sll	$9,11
+	xor	$10,$8
+	srl	$8,$21,18
+	xor	$10,$9
+
+	srl	$11,$18,10
+	xor	$10,$8			# sigma0(X[i+1])
+	sll	$9,$18,13
+	addu	$20,$10
+	srl	$8,$18,17
+	xor	$11,$9
+	sll	$9,2
+	xor	$11,$8
+	srl	$8,$18,19
+	xor	$11,$9
+
+	xor	$11,$8			# sigma1(X[i+14])
+	addu	$20,$11
+	addu	$8,$20,$7			# 28
+	srl	$7,$1,6
+	xor	$11,$2,$3
+	sll	$10,$1,7
+	and	$11,$1
+	srl	$9,$1,11
+	xor	$7,$10
+	sll	$10,$1,21
+	xor	$7,$9
+	srl	$9,$1,25
+	xor	$7,$10
+	sll	$10,$1,26
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$8,$11
+	lw	$11,112($6)		# K[28]
+	sll	$10,$24,10
+	addu	$8,$9
+	srl	$9,$24,13
+	xor	$7,$10
+	sll	$10,$24,19
+	xor	$7,$9
+	srl	$9,$24,22
+	xor	$7,$10
+	sll	$10,$24,30
+	xor	$7,$9
+	sw	$20,48($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	addu	$8,$11			# +=K[28]
+	addu	$7,$10
+
+	addu	$31,$8
+	addu	$7,$8
+	lw	$23,60($29)	# prefetch from ring buffer
+	srl	$11,$22,3		# Xupdate(29)
+	addu	$21,$14			# +=X[i+9]
+	sll	$10,$22,14
+	srl	$9,$22,7
+	xor	$11,$10
+	sll	$10,11
+	xor	$11,$9
+	srl	$9,$22,18
+	xor	$11,$10
+
+	srl	$12,$19,10
+	xor	$11,$9			# sigma0(X[i+1])
+	sll	$10,$19,13
+	addu	$21,$11
+	srl	$9,$19,17
+	xor	$12,$10
+	sll	$10,2
+	xor	$12,$9
+	srl	$9,$19,19
+	xor	$12,$10
+
+	xor	$12,$9			# sigma1(X[i+14])
+	addu	$21,$12
+	addu	$9,$21,$3			# 29
+	srl	$3,$31,6
+	xor	$12,$1,$2
+	sll	$11,$31,7
+	and	$12,$31
+	srl	$10,$31,11
+	xor	$3,$11
+	sll	$11,$31,21
+	xor	$3,$10
+	srl	$10,$31,25
+	xor	$3,$11
+	sll	$11,$31,26
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$9,$12
+	lw	$12,116($6)		# K[29]
+	sll	$11,$7,10
+	addu	$9,$10
+	srl	$10,$7,13
+	xor	$3,$11
+	sll	$11,$7,19
+	xor	$3,$10
+	srl	$10,$7,22
+	xor	$3,$11
+	sll	$11,$7,30
+	xor	$3,$10
+	sw	$21,52($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	addu	$9,$12			# +=K[29]
+	addu	$3,$11
+
+	addu	$30,$9
+	addu	$3,$9
+	lw	$8,0($29)	# prefetch from ring buffer
+	srl	$12,$23,3		# Xupdate(30)
+	addu	$22,$15			# +=X[i+9]
+	sll	$11,$23,14
+	srl	$10,$23,7
+	xor	$12,$11
+	sll	$11,11
+	xor	$12,$10
+	srl	$10,$23,18
+	xor	$12,$11
+
+	srl	$13,$20,10
+	xor	$12,$10			# sigma0(X[i+1])
+	sll	$11,$20,13
+	addu	$22,$12
+	srl	$10,$20,17
+	xor	$13,$11
+	sll	$11,2
+	xor	$13,$10
+	srl	$10,$20,19
+	xor	$13,$11
+
+	xor	$13,$10			# sigma1(X[i+14])
+	addu	$22,$13
+	addu	$10,$22,$2			# 30
+	srl	$2,$30,6
+	xor	$13,$31,$1
+	sll	$12,$30,7
+	and	$13,$30
+	srl	$11,$30,11
+	xor	$2,$12
+	sll	$12,$30,21
+	xor	$2,$11
+	srl	$11,$30,25
+	xor	$2,$12
+	sll	$12,$30,26
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$10,$13
+	lw	$13,120($6)		# K[30]
+	sll	$12,$3,10
+	addu	$10,$11
+	srl	$11,$3,13
+	xor	$2,$12
+	sll	$12,$3,19
+	xor	$2,$11
+	srl	$11,$3,22
+	xor	$2,$12
+	sll	$12,$3,30
+	xor	$2,$11
+	sw	$22,56($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	addu	$10,$13			# +=K[30]
+	addu	$2,$12
+
+	addu	$25,$10
+	addu	$2,$10
+	lw	$9,4($29)	# prefetch from ring buffer
+	srl	$13,$8,3		# Xupdate(31)
+	addu	$23,$16			# +=X[i+9]
+	sll	$12,$8,14
+	srl	$11,$8,7
+	xor	$13,$12
+	sll	$12,11
+	xor	$13,$11
+	srl	$11,$8,18
+	xor	$13,$12
+
+	srl	$14,$21,10
+	xor	$13,$11			# sigma0(X[i+1])
+	sll	$12,$21,13
+	addu	$23,$13
+	srl	$11,$21,17
+	xor	$14,$12
+	sll	$12,2
+	xor	$14,$11
+	srl	$11,$21,19
+	xor	$14,$12
+
+	xor	$14,$11			# sigma1(X[i+14])
+	addu	$23,$14
+	addu	$11,$23,$1			# 31
+	srl	$1,$25,6
+	xor	$14,$30,$31
+	sll	$13,$25,7
+	and	$14,$25
+	srl	$12,$25,11
+	xor	$1,$13
+	sll	$13,$25,21
+	xor	$1,$12
+	srl	$12,$25,25
+	xor	$1,$13
+	sll	$13,$25,26
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$11,$14
+	lw	$14,124($6)		# K[31]
+	sll	$13,$2,10
+	addu	$11,$12
+	srl	$12,$2,13
+	xor	$1,$13
+	sll	$13,$2,19
+	xor	$1,$12
+	srl	$12,$2,22
+	xor	$1,$13
+	sll	$13,$2,30
+	xor	$1,$12
+	sw	$23,60($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	addu	$11,$14			# +=K[31]
+	addu	$1,$13
+
+	addu	$24,$11
+	addu	$1,$11
+	lw	$10,8($29)	# prefetch from ring buffer
+	and	$14,0xfff
+	li	$15,2290
+	.set	noreorder
+	bne	$14,$15,.L16_xx
+	add $6,16*4		# Ktbl+=16
+
+	lw	$23,16*4($29)	# restore pointer to the end of input
+	lw	$8,0*4($4)
+	lw	$9,1*4($4)
+	lw	$10,2*4($4)
+	add $5,16*4
+	lw	$11,3*4($4)
+	addu	$1,$8
+	lw	$12,4*4($4)
+	addu	$2,$9
+	lw	$13,5*4($4)
+	addu	$3,$10
+	lw	$14,6*4($4)
+	addu	$7,$11
+	lw	$15,7*4($4)
+	addu	$24,$12
+	sw	$1,0*4($4)
+	addu	$25,$13
+	sw	$2,1*4($4)
+	addu	$30,$14
+	sw	$3,2*4($4)
+	addu	$31,$15
+	sw	$7,3*4($4)
+	sw	$24,4*4($4)
+	sw	$25,5*4($4)
+	sw	$30,6*4($4)
+	sw	$31,7*4($4)
+
+	bne	$5,$23,.Loop
+	sub $6,192	# rewind $6
+
+	lw	$31,128-1*4($29)
+	lw	$30,128-2*4($29)
+	lw	$23,128-3*4($29)
+	lw	$22,128-4*4($29)
+	lw	$21,128-5*4($29)
+	lw	$20,128-6*4($29)
+	lw	$19,128-7*4($29)
+	lw	$18,128-8*4($29)
+	lw	$17,128-9*4($29)
+	lw	$16,128-10*4($29)
+	jr	$31
+	add $29,128
+.end	sha256_block_data_order
+
+.rdata
+.align	5
+K256:
+	.word	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
+	.word	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
+	.word	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
+	.word	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
+	.word	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
+	.word	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
+	.word	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
+	.word	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
+	.word	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
+	.word	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
+	.word	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
+	.word	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
+	.word	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
+	.word	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
+	.word	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
+	.word	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+.asciiz	"SHA256 for MIPS, CRYPTOGAMS by "
+.align	5
+
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha256-mips64.S b/crypto/sha/sha256-mips64.S
new file mode 100644
index 0000000..49cd2f0
--- /dev/null
+++ b/crypto/sha/sha256-mips64.S
@@ -0,0 +1,1998 @@
+.text
+.set	noat
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+
+.align	5
+.globl	sha256_block_data_order
+.ent	sha256_block_data_order
+sha256_block_data_order:
+	.frame	$29,192,$31
+	.mask	3237937152,-8
+	.set	noreorder
+	dsub $29,192
+	sd	$31,192-1*8($29)
+	sd	$30,192-2*8($29)
+	sd	$23,192-3*8($29)
+	sd	$22,192-4*8($29)
+	sd	$21,192-5*8($29)
+	sd	$20,192-6*8($29)
+	sd	$19,192-7*8($29)
+	sd	$18,192-8*8($29)
+	sd	$17,192-9*8($29)
+	sd	$16,192-10*8($29)
+	dsll $23,$6,6
+	.cplocal	$6
+	.cpsetup	$25,$0,sha256_block_data_order
+	.set	reorder
+	dla	$6,K256		# PIC-ified 'load address'
+
+	lw	$1,0*4($4)		# load context
+	lw	$2,1*4($4)
+	lw	$3,2*4($4)
+	lw	$7,3*4($4)
+	lw	$24,4*4($4)
+	lw	$25,5*4($4)
+	lw	$30,6*4($4)
+	lw	$31,7*4($4)
+
+	dadd $23,$5		# pointer to the end of input
+	sd	$23,16*4($29)
+	b	.Loop
+
+.align	5
+.Loop:
+	lwl	$8,3($5)
+	lwr	$8,0($5)
+	lwl	$9,7($5)
+	lwr	$9,4($5)
+	srl	$13,$8,24		# byte swap(0)
+	srl	$14,$8,8
+	andi	$15,$8,0xFF00
+	sll	$8,$8,24
+	andi	$14,0xFF00
+	sll	$15,$15,8
+	or	$8,$13
+	or	$14,$15
+	or	$8,$14
+	addu	$12,$8,$31			# 0
+	srl	$31,$24,6
+	xor	$15,$25,$30
+	sll	$14,$24,7
+	and	$15,$24
+	srl	$13,$24,11
+	xor	$31,$14
+	sll	$14,$24,21
+	xor	$31,$13
+	srl	$13,$24,25
+	xor	$31,$14
+	sll	$14,$24,26
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$12,$15
+	lw	$15,0($6)		# K[0]
+	sll	$14,$1,10
+	addu	$12,$13
+	srl	$13,$1,13
+	xor	$31,$14
+	sll	$14,$1,19
+	xor	$31,$13
+	srl	$13,$1,22
+	xor	$31,$14
+	sll	$14,$1,30
+	xor	$31,$13
+	sw	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	addu	$12,$15			# +=K[0]
+	addu	$31,$14
+
+	addu	$7,$12
+	addu	$31,$12
+	lwl	$10,11($5)
+	lwr	$10,8($5)
+	srl	$14,$9,24		# byte swap(1)
+	srl	$15,$9,8
+	andi	$16,$9,0xFF00
+	sll	$9,$9,24
+	andi	$15,0xFF00
+	sll	$16,$16,8
+	or	$9,$14
+	or	$15,$16
+	or	$9,$15
+	addu	$13,$9,$30			# 1
+	srl	$30,$7,6
+	xor	$16,$24,$25
+	sll	$15,$7,7
+	and	$16,$7
+	srl	$14,$7,11
+	xor	$30,$15
+	sll	$15,$7,21
+	xor	$30,$14
+	srl	$14,$7,25
+	xor	$30,$15
+	sll	$15,$7,26
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$13,$16
+	lw	$16,4($6)		# K[1]
+	sll	$15,$31,10
+	addu	$13,$14
+	srl	$14,$31,13
+	xor	$30,$15
+	sll	$15,$31,19
+	xor	$30,$14
+	srl	$14,$31,22
+	xor	$30,$15
+	sll	$15,$31,30
+	xor	$30,$14
+	sw	$9,4($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	addu	$13,$16			# +=K[1]
+	addu	$30,$15
+
+	addu	$3,$13
+	addu	$30,$13
+	lwl	$11,15($5)
+	lwr	$11,12($5)
+	srl	$15,$10,24		# byte swap(2)
+	srl	$16,$10,8
+	andi	$17,$10,0xFF00
+	sll	$10,$10,24
+	andi	$16,0xFF00
+	sll	$17,$17,8
+	or	$10,$15
+	or	$16,$17
+	or	$10,$16
+	addu	$14,$10,$25			# 2
+	srl	$25,$3,6
+	xor	$17,$7,$24
+	sll	$16,$3,7
+	and	$17,$3
+	srl	$15,$3,11
+	xor	$25,$16
+	sll	$16,$3,21
+	xor	$25,$15
+	srl	$15,$3,25
+	xor	$25,$16
+	sll	$16,$3,26
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$14,$17
+	lw	$17,8($6)		# K[2]
+	sll	$16,$30,10
+	addu	$14,$15
+	srl	$15,$30,13
+	xor	$25,$16
+	sll	$16,$30,19
+	xor	$25,$15
+	srl	$15,$30,22
+	xor	$25,$16
+	sll	$16,$30,30
+	xor	$25,$15
+	sw	$10,8($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	addu	$14,$17			# +=K[2]
+	addu	$25,$16
+
+	addu	$2,$14
+	addu	$25,$14
+	lwl	$12,19($5)
+	lwr	$12,16($5)
+	srl	$16,$11,24		# byte swap(3)
+	srl	$17,$11,8
+	andi	$18,$11,0xFF00
+	sll	$11,$11,24
+	andi	$17,0xFF00
+	sll	$18,$18,8
+	or	$11,$16
+	or	$17,$18
+	or	$11,$17
+	addu	$15,$11,$24			# 3
+	srl	$24,$2,6
+	xor	$18,$3,$7
+	sll	$17,$2,7
+	and	$18,$2
+	srl	$16,$2,11
+	xor	$24,$17
+	sll	$17,$2,21
+	xor	$24,$16
+	srl	$16,$2,25
+	xor	$24,$17
+	sll	$17,$2,26
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$15,$18
+	lw	$18,12($6)		# K[3]
+	sll	$17,$25,10
+	addu	$15,$16
+	srl	$16,$25,13
+	xor	$24,$17
+	sll	$17,$25,19
+	xor	$24,$16
+	srl	$16,$25,22
+	xor	$24,$17
+	sll	$17,$25,30
+	xor	$24,$16
+	sw	$11,12($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	addu	$15,$18			# +=K[3]
+	addu	$24,$17
+
+	addu	$1,$15
+	addu	$24,$15
+	lwl	$13,23($5)
+	lwr	$13,20($5)
+	srl	$17,$12,24		# byte swap(4)
+	srl	$18,$12,8
+	andi	$19,$12,0xFF00
+	sll	$12,$12,24
+	andi	$18,0xFF00
+	sll	$19,$19,8
+	or	$12,$17
+	or	$18,$19
+	or	$12,$18
+	addu	$16,$12,$7			# 4
+	srl	$7,$1,6
+	xor	$19,$2,$3
+	sll	$18,$1,7
+	and	$19,$1
+	srl	$17,$1,11
+	xor	$7,$18
+	sll	$18,$1,21
+	xor	$7,$17
+	srl	$17,$1,25
+	xor	$7,$18
+	sll	$18,$1,26
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$16,$19
+	lw	$19,16($6)		# K[4]
+	sll	$18,$24,10
+	addu	$16,$17
+	srl	$17,$24,13
+	xor	$7,$18
+	sll	$18,$24,19
+	xor	$7,$17
+	srl	$17,$24,22
+	xor	$7,$18
+	sll	$18,$24,30
+	xor	$7,$17
+	sw	$12,16($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	addu	$16,$19			# +=K[4]
+	addu	$7,$18
+
+	addu	$31,$16
+	addu	$7,$16
+	lwl	$14,27($5)
+	lwr	$14,24($5)
+	srl	$18,$13,24		# byte swap(5)
+	srl	$19,$13,8
+	andi	$20,$13,0xFF00
+	sll	$13,$13,24
+	andi	$19,0xFF00
+	sll	$20,$20,8
+	or	$13,$18
+	or	$19,$20
+	or	$13,$19
+	addu	$17,$13,$3			# 5
+	srl	$3,$31,6
+	xor	$20,$1,$2
+	sll	$19,$31,7
+	and	$20,$31
+	srl	$18,$31,11
+	xor	$3,$19
+	sll	$19,$31,21
+	xor	$3,$18
+	srl	$18,$31,25
+	xor	$3,$19
+	sll	$19,$31,26
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$17,$20
+	lw	$20,20($6)		# K[5]
+	sll	$19,$7,10
+	addu	$17,$18
+	srl	$18,$7,13
+	xor	$3,$19
+	sll	$19,$7,19
+	xor	$3,$18
+	srl	$18,$7,22
+	xor	$3,$19
+	sll	$19,$7,30
+	xor	$3,$18
+	sw	$13,20($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	addu	$17,$20			# +=K[5]
+	addu	$3,$19
+
+	addu	$30,$17
+	addu	$3,$17
+	lwl	$15,31($5)
+	lwr	$15,28($5)
+	srl	$19,$14,24		# byte swap(6)
+	srl	$20,$14,8
+	andi	$21,$14,0xFF00
+	sll	$14,$14,24
+	andi	$20,0xFF00
+	sll	$21,$21,8
+	or	$14,$19
+	or	$20,$21
+	or	$14,$20
+	addu	$18,$14,$2			# 6
+	srl	$2,$30,6
+	xor	$21,$31,$1
+	sll	$20,$30,7
+	and	$21,$30
+	srl	$19,$30,11
+	xor	$2,$20
+	sll	$20,$30,21
+	xor	$2,$19
+	srl	$19,$30,25
+	xor	$2,$20
+	sll	$20,$30,26
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$18,$21
+	lw	$21,24($6)		# K[6]
+	sll	$20,$3,10
+	addu	$18,$19
+	srl	$19,$3,13
+	xor	$2,$20
+	sll	$20,$3,19
+	xor	$2,$19
+	srl	$19,$3,22
+	xor	$2,$20
+	sll	$20,$3,30
+	xor	$2,$19
+	sw	$14,24($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	addu	$18,$21			# +=K[6]
+	addu	$2,$20
+
+	addu	$25,$18
+	addu	$2,$18
+	lwl	$16,35($5)
+	lwr	$16,32($5)
+	srl	$20,$15,24		# byte swap(7)
+	srl	$21,$15,8
+	andi	$22,$15,0xFF00
+	sll	$15,$15,24
+	andi	$21,0xFF00
+	sll	$22,$22,8
+	or	$15,$20
+	or	$21,$22
+	or	$15,$21
+	addu	$19,$15,$1			# 7
+	srl	$1,$25,6
+	xor	$22,$30,$31
+	sll	$21,$25,7
+	and	$22,$25
+	srl	$20,$25,11
+	xor	$1,$21
+	sll	$21,$25,21
+	xor	$1,$20
+	srl	$20,$25,25
+	xor	$1,$21
+	sll	$21,$25,26
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$19,$22
+	lw	$22,28($6)		# K[7]
+	sll	$21,$2,10
+	addu	$19,$20
+	srl	$20,$2,13
+	xor	$1,$21
+	sll	$21,$2,19
+	xor	$1,$20
+	srl	$20,$2,22
+	xor	$1,$21
+	sll	$21,$2,30
+	xor	$1,$20
+	sw	$15,28($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	addu	$19,$22			# +=K[7]
+	addu	$1,$21
+
+	addu	$24,$19
+	addu	$1,$19
+	lwl	$17,39($5)
+	lwr	$17,36($5)
+	srl	$21,$16,24		# byte swap(8)
+	srl	$22,$16,8
+	andi	$23,$16,0xFF00
+	sll	$16,$16,24
+	andi	$22,0xFF00
+	sll	$23,$23,8
+	or	$16,$21
+	or	$22,$23
+	or	$16,$22
+	addu	$20,$16,$31			# 8
+	srl	$31,$24,6
+	xor	$23,$25,$30
+	sll	$22,$24,7
+	and	$23,$24
+	srl	$21,$24,11
+	xor	$31,$22
+	sll	$22,$24,21
+	xor	$31,$21
+	srl	$21,$24,25
+	xor	$31,$22
+	sll	$22,$24,26
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$20,$23
+	lw	$23,32($6)		# K[8]
+	sll	$22,$1,10
+	addu	$20,$21
+	srl	$21,$1,13
+	xor	$31,$22
+	sll	$22,$1,19
+	xor	$31,$21
+	srl	$21,$1,22
+	xor	$31,$22
+	sll	$22,$1,30
+	xor	$31,$21
+	sw	$16,32($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	addu	$20,$23			# +=K[8]
+	addu	$31,$22
+
+	addu	$7,$20
+	addu	$31,$20
+	lwl	$18,43($5)
+	lwr	$18,40($5)
+	srl	$22,$17,24		# byte swap(9)
+	srl	$23,$17,8
+	andi	$8,$17,0xFF00
+	sll	$17,$17,24
+	andi	$23,0xFF00
+	sll	$8,$8,8
+	or	$17,$22
+	or	$23,$8
+	or	$17,$23
+	addu	$21,$17,$30			# 9
+	srl	$30,$7,6
+	xor	$8,$24,$25
+	sll	$23,$7,7
+	and	$8,$7
+	srl	$22,$7,11
+	xor	$30,$23
+	sll	$23,$7,21
+	xor	$30,$22
+	srl	$22,$7,25
+	xor	$30,$23
+	sll	$23,$7,26
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$21,$8
+	lw	$8,36($6)		# K[9]
+	sll	$23,$31,10
+	addu	$21,$22
+	srl	$22,$31,13
+	xor	$30,$23
+	sll	$23,$31,19
+	xor	$30,$22
+	srl	$22,$31,22
+	xor	$30,$23
+	sll	$23,$31,30
+	xor	$30,$22
+	sw	$17,36($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	addu	$21,$8			# +=K[9]
+	addu	$30,$23
+
+	addu	$3,$21
+	addu	$30,$21
+	lwl	$19,47($5)
+	lwr	$19,44($5)
+	srl	$23,$18,24		# byte swap(10)
+	srl	$8,$18,8
+	andi	$9,$18,0xFF00
+	sll	$18,$18,24
+	andi	$8,0xFF00
+	sll	$9,$9,8
+	or	$18,$23
+	or	$8,$9
+	or	$18,$8
+	addu	$22,$18,$25			# 10
+	srl	$25,$3,6
+	xor	$9,$7,$24
+	sll	$8,$3,7
+	and	$9,$3
+	srl	$23,$3,11
+	xor	$25,$8
+	sll	$8,$3,21
+	xor	$25,$23
+	srl	$23,$3,25
+	xor	$25,$8
+	sll	$8,$3,26
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$22,$9
+	lw	$9,40($6)		# K[10]
+	sll	$8,$30,10
+	addu	$22,$23
+	srl	$23,$30,13
+	xor	$25,$8
+	sll	$8,$30,19
+	xor	$25,$23
+	srl	$23,$30,22
+	xor	$25,$8
+	sll	$8,$30,30
+	xor	$25,$23
+	sw	$18,40($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	addu	$22,$9			# +=K[10]
+	addu	$25,$8
+
+	addu	$2,$22
+	addu	$25,$22
+	lwl	$20,51($5)
+	lwr	$20,48($5)
+	srl	$8,$19,24		# byte swap(11)
+	srl	$9,$19,8
+	andi	$10,$19,0xFF00
+	sll	$19,$19,24
+	andi	$9,0xFF00
+	sll	$10,$10,8
+	or	$19,$8
+	or	$9,$10
+	or	$19,$9
+	addu	$23,$19,$24			# 11
+	srl	$24,$2,6
+	xor	$10,$3,$7
+	sll	$9,$2,7
+	and	$10,$2
+	srl	$8,$2,11
+	xor	$24,$9
+	sll	$9,$2,21
+	xor	$24,$8
+	srl	$8,$2,25
+	xor	$24,$9
+	sll	$9,$2,26
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$23,$10
+	lw	$10,44($6)		# K[11]
+	sll	$9,$25,10
+	addu	$23,$8
+	srl	$8,$25,13
+	xor	$24,$9
+	sll	$9,$25,19
+	xor	$24,$8
+	srl	$8,$25,22
+	xor	$24,$9
+	sll	$9,$25,30
+	xor	$24,$8
+	sw	$19,44($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	addu	$23,$10			# +=K[11]
+	addu	$24,$9
+
+	addu	$1,$23
+	addu	$24,$23
+	lwl	$21,55($5)
+	lwr	$21,52($5)
+	srl	$9,$20,24		# byte swap(12)
+	srl	$10,$20,8
+	andi	$11,$20,0xFF00
+	sll	$20,$20,24
+	andi	$10,0xFF00
+	sll	$11,$11,8
+	or	$20,$9
+	or	$10,$11
+	or	$20,$10
+	addu	$8,$20,$7			# 12
+	srl	$7,$1,6
+	xor	$11,$2,$3
+	sll	$10,$1,7
+	and	$11,$1
+	srl	$9,$1,11
+	xor	$7,$10
+	sll	$10,$1,21
+	xor	$7,$9
+	srl	$9,$1,25
+	xor	$7,$10
+	sll	$10,$1,26
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$8,$11
+	lw	$11,48($6)		# K[12]
+	sll	$10,$24,10
+	addu	$8,$9
+	srl	$9,$24,13
+	xor	$7,$10
+	sll	$10,$24,19
+	xor	$7,$9
+	srl	$9,$24,22
+	xor	$7,$10
+	sll	$10,$24,30
+	xor	$7,$9
+	sw	$20,48($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	addu	$8,$11			# +=K[12]
+	addu	$7,$10
+
+	addu	$31,$8
+	addu	$7,$8
+	lwl	$22,59($5)
+	lwr	$22,56($5)
+	srl	$10,$21,24		# byte swap(13)
+	srl	$11,$21,8
+	andi	$12,$21,0xFF00
+	sll	$21,$21,24
+	andi	$11,0xFF00
+	sll	$12,$12,8
+	or	$21,$10
+	or	$11,$12
+	or	$21,$11
+	addu	$9,$21,$3			# 13
+	srl	$3,$31,6
+	xor	$12,$1,$2
+	sll	$11,$31,7
+	and	$12,$31
+	srl	$10,$31,11
+	xor	$3,$11
+	sll	$11,$31,21
+	xor	$3,$10
+	srl	$10,$31,25
+	xor	$3,$11
+	sll	$11,$31,26
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$9,$12
+	lw	$12,52($6)		# K[13]
+	sll	$11,$7,10
+	addu	$9,$10
+	srl	$10,$7,13
+	xor	$3,$11
+	sll	$11,$7,19
+	xor	$3,$10
+	srl	$10,$7,22
+	xor	$3,$11
+	sll	$11,$7,30
+	xor	$3,$10
+	sw	$21,52($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	addu	$9,$12			# +=K[13]
+	addu	$3,$11
+
+	addu	$30,$9
+	addu	$3,$9
+	lw	$8,0($29)	# prefetch from ring buffer
+	lwl	$23,63($5)
+	lwr	$23,60($5)
+	srl	$11,$22,24		# byte swap(14)
+	srl	$12,$22,8
+	andi	$13,$22,0xFF00
+	sll	$22,$22,24
+	andi	$12,0xFF00
+	sll	$13,$13,8
+	or	$22,$11
+	or	$12,$13
+	or	$22,$12
+	addu	$10,$22,$2			# 14
+	srl	$2,$30,6
+	xor	$13,$31,$1
+	sll	$12,$30,7
+	and	$13,$30
+	srl	$11,$30,11
+	xor	$2,$12
+	sll	$12,$30,21
+	xor	$2,$11
+	srl	$11,$30,25
+	xor	$2,$12
+	sll	$12,$30,26
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$10,$13
+	lw	$13,56($6)		# K[14]
+	sll	$12,$3,10
+	addu	$10,$11
+	srl	$11,$3,13
+	xor	$2,$12
+	sll	$12,$3,19
+	xor	$2,$11
+	srl	$11,$3,22
+	xor	$2,$12
+	sll	$12,$3,30
+	xor	$2,$11
+	sw	$22,56($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	addu	$10,$13			# +=K[14]
+	addu	$2,$12
+
+	addu	$25,$10
+	addu	$2,$10
+	lw	$9,4($29)	# prefetch from ring buffer
+	srl	$12,$23,24		# byte swap(15)
+	srl	$13,$23,8
+	andi	$14,$23,0xFF00
+	sll	$23,$23,24
+	andi	$13,0xFF00
+	sll	$14,$14,8
+	or	$23,$12
+	or	$13,$14
+	or	$23,$13
+	addu	$11,$23,$1			# 15
+	srl	$1,$25,6
+	xor	$14,$30,$31
+	sll	$13,$25,7
+	and	$14,$25
+	srl	$12,$25,11
+	xor	$1,$13
+	sll	$13,$25,21
+	xor	$1,$12
+	srl	$12,$25,25
+	xor	$1,$13
+	sll	$13,$25,26
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$11,$14
+	lw	$14,60($6)		# K[15]
+	sll	$13,$2,10
+	addu	$11,$12
+	srl	$12,$2,13
+	xor	$1,$13
+	sll	$13,$2,19
+	xor	$1,$12
+	srl	$12,$2,22
+	xor	$1,$13
+	sll	$13,$2,30
+	xor	$1,$12
+	sw	$23,60($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	addu	$11,$14			# +=K[15]
+	addu	$1,$13
+
+	addu	$24,$11
+	addu	$1,$11
+	lw	$10,8($29)	# prefetch from ring buffer
+	b	.L16_xx
+.align	4
+.L16_xx:
+	srl	$14,$9,3		# Xupdate(16)
+	addu	$8,$17			# +=X[i+9]
+	sll	$13,$9,14
+	srl	$12,$9,7
+	xor	$14,$13
+	sll	$13,11
+	xor	$14,$12
+	srl	$12,$9,18
+	xor	$14,$13
+
+	srl	$15,$22,10
+	xor	$14,$12			# sigma0(X[i+1])
+	sll	$13,$22,13
+	addu	$8,$14
+	srl	$12,$22,17
+	xor	$15,$13
+	sll	$13,2
+	xor	$15,$12
+	srl	$12,$22,19
+	xor	$15,$13
+
+	xor	$15,$12			# sigma1(X[i+14])
+	addu	$8,$15
+	addu	$12,$8,$31			# 16
+	srl	$31,$24,6
+	xor	$15,$25,$30
+	sll	$14,$24,7
+	and	$15,$24
+	srl	$13,$24,11
+	xor	$31,$14
+	sll	$14,$24,21
+	xor	$31,$13
+	srl	$13,$24,25
+	xor	$31,$14
+	sll	$14,$24,26
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$12,$15
+	lw	$15,64($6)		# K[16]
+	sll	$14,$1,10
+	addu	$12,$13
+	srl	$13,$1,13
+	xor	$31,$14
+	sll	$14,$1,19
+	xor	$31,$13
+	srl	$13,$1,22
+	xor	$31,$14
+	sll	$14,$1,30
+	xor	$31,$13
+	sw	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	addu	$12,$15			# +=K[16]
+	addu	$31,$14
+
+	addu	$7,$12
+	addu	$31,$12
+	lw	$11,12($29)	# prefetch from ring buffer
+	srl	$15,$10,3		# Xupdate(17)
+	addu	$9,$18			# +=X[i+9]
+	sll	$14,$10,14
+	srl	$13,$10,7
+	xor	$15,$14
+	sll	$14,11
+	xor	$15,$13
+	srl	$13,$10,18
+	xor	$15,$14
+
+	srl	$16,$23,10
+	xor	$15,$13			# sigma0(X[i+1])
+	sll	$14,$23,13
+	addu	$9,$15
+	srl	$13,$23,17
+	xor	$16,$14
+	sll	$14,2
+	xor	$16,$13
+	srl	$13,$23,19
+	xor	$16,$14
+
+	xor	$16,$13			# sigma1(X[i+14])
+	addu	$9,$16
+	addu	$13,$9,$30			# 17
+	srl	$30,$7,6
+	xor	$16,$24,$25
+	sll	$15,$7,7
+	and	$16,$7
+	srl	$14,$7,11
+	xor	$30,$15
+	sll	$15,$7,21
+	xor	$30,$14
+	srl	$14,$7,25
+	xor	$30,$15
+	sll	$15,$7,26
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$13,$16
+	lw	$16,68($6)		# K[17]
+	sll	$15,$31,10
+	addu	$13,$14
+	srl	$14,$31,13
+	xor	$30,$15
+	sll	$15,$31,19
+	xor	$30,$14
+	srl	$14,$31,22
+	xor	$30,$15
+	sll	$15,$31,30
+	xor	$30,$14
+	sw	$9,4($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	addu	$13,$16			# +=K[17]
+	addu	$30,$15
+
+	addu	$3,$13
+	addu	$30,$13
+	lw	$12,16($29)	# prefetch from ring buffer
+	srl	$16,$11,3		# Xupdate(18)
+	addu	$10,$19			# +=X[i+9]
+	sll	$15,$11,14
+	srl	$14,$11,7
+	xor	$16,$15
+	sll	$15,11
+	xor	$16,$14
+	srl	$14,$11,18
+	xor	$16,$15
+
+	srl	$17,$8,10
+	xor	$16,$14			# sigma0(X[i+1])
+	sll	$15,$8,13
+	addu	$10,$16
+	srl	$14,$8,17
+	xor	$17,$15
+	sll	$15,2
+	xor	$17,$14
+	srl	$14,$8,19
+	xor	$17,$15
+
+	xor	$17,$14			# sigma1(X[i+14])
+	addu	$10,$17
+	addu	$14,$10,$25			# 18
+	srl	$25,$3,6
+	xor	$17,$7,$24
+	sll	$16,$3,7
+	and	$17,$3
+	srl	$15,$3,11
+	xor	$25,$16
+	sll	$16,$3,21
+	xor	$25,$15
+	srl	$15,$3,25
+	xor	$25,$16
+	sll	$16,$3,26
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$14,$17
+	lw	$17,72($6)		# K[18]
+	sll	$16,$30,10
+	addu	$14,$15
+	srl	$15,$30,13
+	xor	$25,$16
+	sll	$16,$30,19
+	xor	$25,$15
+	srl	$15,$30,22
+	xor	$25,$16
+	sll	$16,$30,30
+	xor	$25,$15
+	sw	$10,8($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	addu	$14,$17			# +=K[18]
+	addu	$25,$16
+
+	addu	$2,$14
+	addu	$25,$14
+	lw	$13,20($29)	# prefetch from ring buffer
+	srl	$17,$12,3		# Xupdate(19)
+	addu	$11,$20			# +=X[i+9]
+	sll	$16,$12,14
+	srl	$15,$12,7
+	xor	$17,$16
+	sll	$16,11
+	xor	$17,$15
+	srl	$15,$12,18
+	xor	$17,$16
+
+	srl	$18,$9,10
+	xor	$17,$15			# sigma0(X[i+1])
+	sll	$16,$9,13
+	addu	$11,$17
+	srl	$15,$9,17
+	xor	$18,$16
+	sll	$16,2
+	xor	$18,$15
+	srl	$15,$9,19
+	xor	$18,$16
+
+	xor	$18,$15			# sigma1(X[i+14])
+	addu	$11,$18
+	addu	$15,$11,$24			# 19
+	srl	$24,$2,6
+	xor	$18,$3,$7
+	sll	$17,$2,7
+	and	$18,$2
+	srl	$16,$2,11
+	xor	$24,$17
+	sll	$17,$2,21
+	xor	$24,$16
+	srl	$16,$2,25
+	xor	$24,$17
+	sll	$17,$2,26
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$15,$18
+	lw	$18,76($6)		# K[19]
+	sll	$17,$25,10
+	addu	$15,$16
+	srl	$16,$25,13
+	xor	$24,$17
+	sll	$17,$25,19
+	xor	$24,$16
+	srl	$16,$25,22
+	xor	$24,$17
+	sll	$17,$25,30
+	xor	$24,$16
+	sw	$11,12($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	addu	$15,$18			# +=K[19]
+	addu	$24,$17
+
+	addu	$1,$15
+	addu	$24,$15
+	lw	$14,24($29)	# prefetch from ring buffer
+	srl	$18,$13,3		# Xupdate(20)
+	addu	$12,$21			# +=X[i+9]
+	sll	$17,$13,14
+	srl	$16,$13,7
+	xor	$18,$17
+	sll	$17,11
+	xor	$18,$16
+	srl	$16,$13,18
+	xor	$18,$17
+
+	srl	$19,$10,10
+	xor	$18,$16			# sigma0(X[i+1])
+	sll	$17,$10,13
+	addu	$12,$18
+	srl	$16,$10,17
+	xor	$19,$17
+	sll	$17,2
+	xor	$19,$16
+	srl	$16,$10,19
+	xor	$19,$17
+
+	xor	$19,$16			# sigma1(X[i+14])
+	addu	$12,$19
+	addu	$16,$12,$7			# 20
+	srl	$7,$1,6
+	xor	$19,$2,$3
+	sll	$18,$1,7
+	and	$19,$1
+	srl	$17,$1,11
+	xor	$7,$18
+	sll	$18,$1,21
+	xor	$7,$17
+	srl	$17,$1,25
+	xor	$7,$18
+	sll	$18,$1,26
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$16,$19
+	lw	$19,80($6)		# K[20]
+	sll	$18,$24,10
+	addu	$16,$17
+	srl	$17,$24,13
+	xor	$7,$18
+	sll	$18,$24,19
+	xor	$7,$17
+	srl	$17,$24,22
+	xor	$7,$18
+	sll	$18,$24,30
+	xor	$7,$17
+	sw	$12,16($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	addu	$16,$19			# +=K[20]
+	addu	$7,$18
+
+	addu	$31,$16
+	addu	$7,$16
+	lw	$15,28($29)	# prefetch from ring buffer
+	srl	$19,$14,3		# Xupdate(21)
+	addu	$13,$22			# +=X[i+9]
+	sll	$18,$14,14
+	srl	$17,$14,7
+	xor	$19,$18
+	sll	$18,11
+	xor	$19,$17
+	srl	$17,$14,18
+	xor	$19,$18
+
+	srl	$20,$11,10
+	xor	$19,$17			# sigma0(X[i+1])
+	sll	$18,$11,13
+	addu	$13,$19
+	srl	$17,$11,17
+	xor	$20,$18
+	sll	$18,2
+	xor	$20,$17
+	srl	$17,$11,19
+	xor	$20,$18
+
+	xor	$20,$17			# sigma1(X[i+14])
+	addu	$13,$20
+	addu	$17,$13,$3			# 21
+	srl	$3,$31,6
+	xor	$20,$1,$2
+	sll	$19,$31,7
+	and	$20,$31
+	srl	$18,$31,11
+	xor	$3,$19
+	sll	$19,$31,21
+	xor	$3,$18
+	srl	$18,$31,25
+	xor	$3,$19
+	sll	$19,$31,26
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$17,$20
+	lw	$20,84($6)		# K[21]
+	sll	$19,$7,10
+	addu	$17,$18
+	srl	$18,$7,13
+	xor	$3,$19
+	sll	$19,$7,19
+	xor	$3,$18
+	srl	$18,$7,22
+	xor	$3,$19
+	sll	$19,$7,30
+	xor	$3,$18
+	sw	$13,20($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	addu	$17,$20			# +=K[21]
+	addu	$3,$19
+
+	addu	$30,$17
+	addu	$3,$17
+	lw	$16,32($29)	# prefetch from ring buffer
+	srl	$20,$15,3		# Xupdate(22)
+	addu	$14,$23			# +=X[i+9]
+	sll	$19,$15,14
+	srl	$18,$15,7
+	xor	$20,$19
+	sll	$19,11
+	xor	$20,$18
+	srl	$18,$15,18
+	xor	$20,$19
+
+	srl	$21,$12,10
+	xor	$20,$18			# sigma0(X[i+1])
+	sll	$19,$12,13
+	addu	$14,$20
+	srl	$18,$12,17
+	xor	$21,$19
+	sll	$19,2
+	xor	$21,$18
+	srl	$18,$12,19
+	xor	$21,$19
+
+	xor	$21,$18			# sigma1(X[i+14])
+	addu	$14,$21
+	addu	$18,$14,$2			# 22
+	srl	$2,$30,6
+	xor	$21,$31,$1
+	sll	$20,$30,7
+	and	$21,$30
+	srl	$19,$30,11
+	xor	$2,$20
+	sll	$20,$30,21
+	xor	$2,$19
+	srl	$19,$30,25
+	xor	$2,$20
+	sll	$20,$30,26
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$18,$21
+	lw	$21,88($6)		# K[22]
+	sll	$20,$3,10
+	addu	$18,$19
+	srl	$19,$3,13
+	xor	$2,$20
+	sll	$20,$3,19
+	xor	$2,$19
+	srl	$19,$3,22
+	xor	$2,$20
+	sll	$20,$3,30
+	xor	$2,$19
+	sw	$14,24($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	addu	$18,$21			# +=K[22]
+	addu	$2,$20
+
+	addu	$25,$18
+	addu	$2,$18
+	lw	$17,36($29)	# prefetch from ring buffer
+	srl	$21,$16,3		# Xupdate(23)
+	addu	$15,$8			# +=X[i+9]
+	sll	$20,$16,14
+	srl	$19,$16,7
+	xor	$21,$20
+	sll	$20,11
+	xor	$21,$19
+	srl	$19,$16,18
+	xor	$21,$20
+
+	srl	$22,$13,10
+	xor	$21,$19			# sigma0(X[i+1])
+	sll	$20,$13,13
+	addu	$15,$21
+	srl	$19,$13,17
+	xor	$22,$20
+	sll	$20,2
+	xor	$22,$19
+	srl	$19,$13,19
+	xor	$22,$20
+
+	xor	$22,$19			# sigma1(X[i+14])
+	addu	$15,$22
+	addu	$19,$15,$1			# 23
+	srl	$1,$25,6
+	xor	$22,$30,$31
+	sll	$21,$25,7
+	and	$22,$25
+	srl	$20,$25,11
+	xor	$1,$21
+	sll	$21,$25,21
+	xor	$1,$20
+	srl	$20,$25,25
+	xor	$1,$21
+	sll	$21,$25,26
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$19,$22
+	lw	$22,92($6)		# K[23]
+	sll	$21,$2,10
+	addu	$19,$20
+	srl	$20,$2,13
+	xor	$1,$21
+	sll	$21,$2,19
+	xor	$1,$20
+	srl	$20,$2,22
+	xor	$1,$21
+	sll	$21,$2,30
+	xor	$1,$20
+	sw	$15,28($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	addu	$19,$22			# +=K[23]
+	addu	$1,$21
+
+	addu	$24,$19
+	addu	$1,$19
+	lw	$18,40($29)	# prefetch from ring buffer
+	srl	$22,$17,3		# Xupdate(24)
+	addu	$16,$9			# +=X[i+9]
+	sll	$21,$17,14
+	srl	$20,$17,7
+	xor	$22,$21
+	sll	$21,11
+	xor	$22,$20
+	srl	$20,$17,18
+	xor	$22,$21
+
+	srl	$23,$14,10
+	xor	$22,$20			# sigma0(X[i+1])
+	sll	$21,$14,13
+	addu	$16,$22
+	srl	$20,$14,17
+	xor	$23,$21
+	sll	$21,2
+	xor	$23,$20
+	srl	$20,$14,19
+	xor	$23,$21
+
+	xor	$23,$20			# sigma1(X[i+14])
+	addu	$16,$23
+	addu	$20,$16,$31			# 24
+	srl	$31,$24,6
+	xor	$23,$25,$30
+	sll	$22,$24,7
+	and	$23,$24
+	srl	$21,$24,11
+	xor	$31,$22
+	sll	$22,$24,21
+	xor	$31,$21
+	srl	$21,$24,25
+	xor	$31,$22
+	sll	$22,$24,26
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	srl	$31,$1,2
+	addu	$20,$23
+	lw	$23,96($6)		# K[24]
+	sll	$22,$1,10
+	addu	$20,$21
+	srl	$21,$1,13
+	xor	$31,$22
+	sll	$22,$1,19
+	xor	$31,$21
+	srl	$21,$1,22
+	xor	$31,$22
+	sll	$22,$1,30
+	xor	$31,$21
+	sw	$16,32($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	addu	$20,$23			# +=K[24]
+	addu	$31,$22
+
+	addu	$7,$20
+	addu	$31,$20
+	lw	$19,44($29)	# prefetch from ring buffer
+	srl	$23,$18,3		# Xupdate(25)
+	addu	$17,$10			# +=X[i+9]
+	sll	$22,$18,14
+	srl	$21,$18,7
+	xor	$23,$22
+	sll	$22,11
+	xor	$23,$21
+	srl	$21,$18,18
+	xor	$23,$22
+
+	srl	$8,$15,10
+	xor	$23,$21			# sigma0(X[i+1])
+	sll	$22,$15,13
+	addu	$17,$23
+	srl	$21,$15,17
+	xor	$8,$22
+	sll	$22,2
+	xor	$8,$21
+	srl	$21,$15,19
+	xor	$8,$22
+
+	xor	$8,$21			# sigma1(X[i+14])
+	addu	$17,$8
+	addu	$21,$17,$30			# 25
+	srl	$30,$7,6
+	xor	$8,$24,$25
+	sll	$23,$7,7
+	and	$8,$7
+	srl	$22,$7,11
+	xor	$30,$23
+	sll	$23,$7,21
+	xor	$30,$22
+	srl	$22,$7,25
+	xor	$30,$23
+	sll	$23,$7,26
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	srl	$30,$31,2
+	addu	$21,$8
+	lw	$8,100($6)		# K[25]
+	sll	$23,$31,10
+	addu	$21,$22
+	srl	$22,$31,13
+	xor	$30,$23
+	sll	$23,$31,19
+	xor	$30,$22
+	srl	$22,$31,22
+	xor	$30,$23
+	sll	$23,$31,30
+	xor	$30,$22
+	sw	$17,36($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	addu	$21,$8			# +=K[25]
+	addu	$30,$23
+
+	addu	$3,$21
+	addu	$30,$21
+	lw	$20,48($29)	# prefetch from ring buffer
+	srl	$8,$19,3		# Xupdate(26)
+	addu	$18,$11			# +=X[i+9]
+	sll	$23,$19,14
+	srl	$22,$19,7
+	xor	$8,$23
+	sll	$23,11
+	xor	$8,$22
+	srl	$22,$19,18
+	xor	$8,$23
+
+	srl	$9,$16,10
+	xor	$8,$22			# sigma0(X[i+1])
+	sll	$23,$16,13
+	addu	$18,$8
+	srl	$22,$16,17
+	xor	$9,$23
+	sll	$23,2
+	xor	$9,$22
+	srl	$22,$16,19
+	xor	$9,$23
+
+	xor	$9,$22			# sigma1(X[i+14])
+	addu	$18,$9
+	addu	$22,$18,$25			# 26
+	srl	$25,$3,6
+	xor	$9,$7,$24
+	sll	$8,$3,7
+	and	$9,$3
+	srl	$23,$3,11
+	xor	$25,$8
+	sll	$8,$3,21
+	xor	$25,$23
+	srl	$23,$3,25
+	xor	$25,$8
+	sll	$8,$3,26
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	srl	$25,$30,2
+	addu	$22,$9
+	lw	$9,104($6)		# K[26]
+	sll	$8,$30,10
+	addu	$22,$23
+	srl	$23,$30,13
+	xor	$25,$8
+	sll	$8,$30,19
+	xor	$25,$23
+	srl	$23,$30,22
+	xor	$25,$8
+	sll	$8,$30,30
+	xor	$25,$23
+	sw	$18,40($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	addu	$22,$9			# +=K[26]
+	addu	$25,$8
+
+	addu	$2,$22
+	addu	$25,$22
+	lw	$21,52($29)	# prefetch from ring buffer
+	srl	$9,$20,3		# Xupdate(27)
+	addu	$19,$12			# +=X[i+9]
+	sll	$8,$20,14
+	srl	$23,$20,7
+	xor	$9,$8
+	sll	$8,11
+	xor	$9,$23
+	srl	$23,$20,18
+	xor	$9,$8
+
+	srl	$10,$17,10
+	xor	$9,$23			# sigma0(X[i+1])
+	sll	$8,$17,13
+	addu	$19,$9
+	srl	$23,$17,17
+	xor	$10,$8
+	sll	$8,2
+	xor	$10,$23
+	srl	$23,$17,19
+	xor	$10,$8
+
+	xor	$10,$23			# sigma1(X[i+14])
+	addu	$19,$10
+	addu	$23,$19,$24			# 27
+	srl	$24,$2,6
+	xor	$10,$3,$7
+	sll	$9,$2,7
+	and	$10,$2
+	srl	$8,$2,11
+	xor	$24,$9
+	sll	$9,$2,21
+	xor	$24,$8
+	srl	$8,$2,25
+	xor	$24,$9
+	sll	$9,$2,26
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	srl	$24,$25,2
+	addu	$23,$10
+	lw	$10,108($6)		# K[27]
+	sll	$9,$25,10
+	addu	$23,$8
+	srl	$8,$25,13
+	xor	$24,$9
+	sll	$9,$25,19
+	xor	$24,$8
+	srl	$8,$25,22
+	xor	$24,$9
+	sll	$9,$25,30
+	xor	$24,$8
+	sw	$19,44($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	addu	$23,$10			# +=K[27]
+	addu	$24,$9
+
+	addu	$1,$23
+	addu	$24,$23
+	lw	$22,56($29)	# prefetch from ring buffer
+	srl	$10,$21,3		# Xupdate(28)
+	addu	$20,$13			# +=X[i+9]
+	sll	$9,$21,14
+	srl	$8,$21,7
+	xor	$10,$9
+	sll	$9,11
+	xor	$10,$8
+	srl	$8,$21,18
+	xor	$10,$9
+
+	srl	$11,$18,10
+	xor	$10,$8			# sigma0(X[i+1])
+	sll	$9,$18,13
+	addu	$20,$10
+	srl	$8,$18,17
+	xor	$11,$9
+	sll	$9,2
+	xor	$11,$8
+	srl	$8,$18,19
+	xor	$11,$9
+
+	xor	$11,$8			# sigma1(X[i+14])
+	addu	$20,$11
+	addu	$8,$20,$7			# 28
+	srl	$7,$1,6
+	xor	$11,$2,$3
+	sll	$10,$1,7
+	and	$11,$1
+	srl	$9,$1,11
+	xor	$7,$10
+	sll	$10,$1,21
+	xor	$7,$9
+	srl	$9,$1,25
+	xor	$7,$10
+	sll	$10,$1,26
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	srl	$7,$24,2
+	addu	$8,$11
+	lw	$11,112($6)		# K[28]
+	sll	$10,$24,10
+	addu	$8,$9
+	srl	$9,$24,13
+	xor	$7,$10
+	sll	$10,$24,19
+	xor	$7,$9
+	srl	$9,$24,22
+	xor	$7,$10
+	sll	$10,$24,30
+	xor	$7,$9
+	sw	$20,48($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	addu	$8,$11			# +=K[28]
+	addu	$7,$10
+
+	addu	$31,$8
+	addu	$7,$8
+	lw	$23,60($29)	# prefetch from ring buffer
+	srl	$11,$22,3		# Xupdate(29)
+	addu	$21,$14			# +=X[i+9]
+	sll	$10,$22,14
+	srl	$9,$22,7
+	xor	$11,$10
+	sll	$10,11
+	xor	$11,$9
+	srl	$9,$22,18
+	xor	$11,$10
+
+	srl	$12,$19,10
+	xor	$11,$9			# sigma0(X[i+1])
+	sll	$10,$19,13
+	addu	$21,$11
+	srl	$9,$19,17
+	xor	$12,$10
+	sll	$10,2
+	xor	$12,$9
+	srl	$9,$19,19
+	xor	$12,$10
+
+	xor	$12,$9			# sigma1(X[i+14])
+	addu	$21,$12
+	addu	$9,$21,$3			# 29
+	srl	$3,$31,6
+	xor	$12,$1,$2
+	sll	$11,$31,7
+	and	$12,$31
+	srl	$10,$31,11
+	xor	$3,$11
+	sll	$11,$31,21
+	xor	$3,$10
+	srl	$10,$31,25
+	xor	$3,$11
+	sll	$11,$31,26
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	srl	$3,$7,2
+	addu	$9,$12
+	lw	$12,116($6)		# K[29]
+	sll	$11,$7,10
+	addu	$9,$10
+	srl	$10,$7,13
+	xor	$3,$11
+	sll	$11,$7,19
+	xor	$3,$10
+	srl	$10,$7,22
+	xor	$3,$11
+	sll	$11,$7,30
+	xor	$3,$10
+	sw	$21,52($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	addu	$9,$12			# +=K[29]
+	addu	$3,$11
+
+	addu	$30,$9
+	addu	$3,$9
+	lw	$8,0($29)	# prefetch from ring buffer
+	srl	$12,$23,3		# Xupdate(30)
+	addu	$22,$15			# +=X[i+9]
+	sll	$11,$23,14
+	srl	$10,$23,7
+	xor	$12,$11
+	sll	$11,11
+	xor	$12,$10
+	srl	$10,$23,18
+	xor	$12,$11
+
+	srl	$13,$20,10
+	xor	$12,$10			# sigma0(X[i+1])
+	sll	$11,$20,13
+	addu	$22,$12
+	srl	$10,$20,17
+	xor	$13,$11
+	sll	$11,2
+	xor	$13,$10
+	srl	$10,$20,19
+	xor	$13,$11
+
+	xor	$13,$10			# sigma1(X[i+14])
+	addu	$22,$13
+	addu	$10,$22,$2			# 30
+	srl	$2,$30,6
+	xor	$13,$31,$1
+	sll	$12,$30,7
+	and	$13,$30
+	srl	$11,$30,11
+	xor	$2,$12
+	sll	$12,$30,21
+	xor	$2,$11
+	srl	$11,$30,25
+	xor	$2,$12
+	sll	$12,$30,26
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	srl	$2,$3,2
+	addu	$10,$13
+	lw	$13,120($6)		# K[30]
+	sll	$12,$3,10
+	addu	$10,$11
+	srl	$11,$3,13
+	xor	$2,$12
+	sll	$12,$3,19
+	xor	$2,$11
+	srl	$11,$3,22
+	xor	$2,$12
+	sll	$12,$3,30
+	xor	$2,$11
+	sw	$22,56($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	addu	$10,$13			# +=K[30]
+	addu	$2,$12
+
+	addu	$25,$10
+	addu	$2,$10
+	lw	$9,4($29)	# prefetch from ring buffer
+	srl	$13,$8,3		# Xupdate(31)
+	addu	$23,$16			# +=X[i+9]
+	sll	$12,$8,14
+	srl	$11,$8,7
+	xor	$13,$12
+	sll	$12,11
+	xor	$13,$11
+	srl	$11,$8,18
+	xor	$13,$12
+
+	srl	$14,$21,10
+	xor	$13,$11			# sigma0(X[i+1])
+	sll	$12,$21,13
+	addu	$23,$13
+	srl	$11,$21,17
+	xor	$14,$12
+	sll	$12,2
+	xor	$14,$11
+	srl	$11,$21,19
+	xor	$14,$12
+
+	xor	$14,$11			# sigma1(X[i+14])
+	addu	$23,$14
+	addu	$11,$23,$1			# 31
+	srl	$1,$25,6
+	xor	$14,$30,$31
+	sll	$13,$25,7
+	and	$14,$25
+	srl	$12,$25,11
+	xor	$1,$13
+	sll	$13,$25,21
+	xor	$1,$12
+	srl	$12,$25,25
+	xor	$1,$13
+	sll	$13,$25,26
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	srl	$1,$2,2
+	addu	$11,$14
+	lw	$14,124($6)		# K[31]
+	sll	$13,$2,10
+	addu	$11,$12
+	srl	$12,$2,13
+	xor	$1,$13
+	sll	$13,$2,19
+	xor	$1,$12
+	srl	$12,$2,22
+	xor	$1,$13
+	sll	$13,$2,30
+	xor	$1,$12
+	sw	$23,60($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	addu	$11,$14			# +=K[31]
+	addu	$1,$13
+
+	addu	$24,$11
+	addu	$1,$11
+	lw	$10,8($29)	# prefetch from ring buffer
+	and	$14,0xfff
+	li	$15,2290
+	.set	noreorder
+	bne	$14,$15,.L16_xx
+	dadd $6,16*4		# Ktbl+=16
+
+	ld	$23,16*4($29)	# restore pointer to the end of input
+	lw	$8,0*4($4)
+	lw	$9,1*4($4)
+	lw	$10,2*4($4)
+	dadd $5,16*4
+	lw	$11,3*4($4)
+	addu	$1,$8
+	lw	$12,4*4($4)
+	addu	$2,$9
+	lw	$13,5*4($4)
+	addu	$3,$10
+	lw	$14,6*4($4)
+	addu	$7,$11
+	lw	$15,7*4($4)
+	addu	$24,$12
+	sw	$1,0*4($4)
+	addu	$25,$13
+	sw	$2,1*4($4)
+	addu	$30,$14
+	sw	$3,2*4($4)
+	addu	$31,$15
+	sw	$7,3*4($4)
+	sw	$24,4*4($4)
+	sw	$25,5*4($4)
+	sw	$30,6*4($4)
+	sw	$31,7*4($4)
+
+	bne	$5,$23,.Loop
+	dsub $6,192	# rewind $6
+
+	ld	$31,192-1*8($29)
+	ld	$30,192-2*8($29)
+	ld	$23,192-3*8($29)
+	ld	$22,192-4*8($29)
+	ld	$21,192-5*8($29)
+	ld	$20,192-6*8($29)
+	ld	$19,192-7*8($29)
+	ld	$18,192-8*8($29)
+	ld	$17,192-9*8($29)
+	ld	$16,192-10*8($29)
+	jr	$31
+	dadd $29,192
+.end	sha256_block_data_order
+
+.rdata
+.align	5
+K256:
+	.word	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5
+	.word	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5
+	.word	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3
+	.word	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174
+	.word	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc
+	.word	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da
+	.word	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7
+	.word	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967
+	.word	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
+	.word	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85
+	.word	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3
+	.word	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070
+	.word	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5
+	.word	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
+	.word	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
+	.word	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+.asciiz	"SHA256 for MIPS, CRYPTOGAMS by "
+.align	5
+
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha256.c b/crypto/sha/sha256.c
new file mode 100644
index 0000000..00c9368
--- /dev/null
+++ b/crypto/sha/sha256.c
@@ -0,0 +1,499 @@
+/* $OpenBSD: sha256.c,v 1.30 2023/08/11 15:27:28 jsing Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "crypto_internal.h"
+
+#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA256)
+
+/* Ensure that SHA_LONG and uint32_t are equivalent. */
+CTASSERT(sizeof(SHA_LONG) == sizeof(uint32_t));
+
+#ifdef SHA256_ASM
+void sha256_block_data_order(SHA256_CTX *ctx, const void *_in, size_t num);
+#endif
+
+#ifndef SHA256_ASM
+static const SHA_LONG K256[64] = {
+	0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+	0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+	0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+	0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+	0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+	0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+	0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+	0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+	0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+	0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+	0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+	0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+	0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+	0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+	0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+	0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
+};
+
+static inline SHA_LONG
+Sigma0(SHA_LONG x)
+{
+	return crypto_ror_u32(x, 2) ^ crypto_ror_u32(x, 13) ^
+	    crypto_ror_u32(x, 22);
+}
+
+static inline SHA_LONG
+Sigma1(SHA_LONG x)
+{
+	return crypto_ror_u32(x, 6) ^ crypto_ror_u32(x, 11) ^
+	    crypto_ror_u32(x, 25);
+}
+
+static inline SHA_LONG
+sigma0(SHA_LONG x)
+{
+	return crypto_ror_u32(x, 7) ^ crypto_ror_u32(x, 18) ^ (x >> 3);
+}
+
+static inline SHA_LONG
+sigma1(SHA_LONG x)
+{
+	return crypto_ror_u32(x, 17) ^ crypto_ror_u32(x, 19) ^ (x >> 10);
+}
+
+static inline SHA_LONG
+Ch(SHA_LONG x, SHA_LONG y, SHA_LONG z)
+{
+	return (x & y) ^ (~x & z);
+}
+
+static inline SHA_LONG
+Maj(SHA_LONG x, SHA_LONG y, SHA_LONG z)
+{
+	return (x & y) ^ (x & z) ^ (y & z);
+}
+
+static inline void
+sha256_msg_schedule_update(SHA_LONG *W0, SHA_LONG W1,
+    SHA_LONG W9, SHA_LONG W14)
+{
+	*W0 = sigma1(W14) + W9 + sigma0(W1) + *W0;
+}
+
+static inline void
+sha256_round(SHA_LONG *a, SHA_LONG *b, SHA_LONG *c, SHA_LONG *d,
+    SHA_LONG *e, SHA_LONG *f, SHA_LONG *g, SHA_LONG *h,
+    SHA_LONG Kt, SHA_LONG Wt)
+{
+	SHA_LONG T1, T2;
+
+	T1 = *h + Sigma1(*e) + Ch(*e, *f, *g) + Kt + Wt;
+	T2 = Sigma0(*a) + Maj(*a, *b, *c);
+
+	*h = *g;
+	*g = *f;
+	*f = *e;
+	*e = *d + T1;
+	*d = *c;
+	*c = *b;
+	*b = *a;
+	*a = T1 + T2;
+}
+
+static void
+sha256_block_data_order(SHA256_CTX *ctx, const void *_in, size_t num)
+{
+	const uint8_t *in = _in;
+	const SHA_LONG *in32;
+	SHA_LONG a, b, c, d, e, f, g, h;
+	SHA_LONG X[16];
+	int i;
+
+	while (num--) {
+		a = ctx->h[0];
+		b = ctx->h[1];
+		c = ctx->h[2];
+		d = ctx->h[3];
+		e = ctx->h[4];
+		f = ctx->h[5];
+		g = ctx->h[6];
+		h = ctx->h[7];
+
+		if ((size_t)in % 4 == 0) {
+			/* Input is 32 bit aligned. */
+			in32 = (const SHA_LONG *)in;
+			X[0] = be32toh(in32[0]);
+			X[1] = be32toh(in32[1]);
+			X[2] = be32toh(in32[2]);
+			X[3] = be32toh(in32[3]);
+			X[4] = be32toh(in32[4]);
+			X[5] = be32toh(in32[5]);
+			X[6] = be32toh(in32[6]);
+			X[7] = be32toh(in32[7]);
+			X[8] = be32toh(in32[8]);
+			X[9] = be32toh(in32[9]);
+			X[10] = be32toh(in32[10]);
+			X[11] = be32toh(in32[11]);
+			X[12] = be32toh(in32[12]);
+			X[13] = be32toh(in32[13]);
+			X[14] = be32toh(in32[14]);
+			X[15] = be32toh(in32[15]);
+		} else {
+			/* Input is not 32 bit aligned. */
+			X[0] = crypto_load_be32toh(&in[0 * 4]);
+			X[1] = crypto_load_be32toh(&in[1 * 4]);
+			X[2] = crypto_load_be32toh(&in[2 * 4]);
+			X[3] = crypto_load_be32toh(&in[3 * 4]);
+			X[4] = crypto_load_be32toh(&in[4 * 4]);
+			X[5] = crypto_load_be32toh(&in[5 * 4]);
+			X[6] = crypto_load_be32toh(&in[6 * 4]);
+			X[7] = crypto_load_be32toh(&in[7 * 4]);
+			X[8] = crypto_load_be32toh(&in[8 * 4]);
+			X[9] = crypto_load_be32toh(&in[9 * 4]);
+			X[10] = crypto_load_be32toh(&in[10 * 4]);
+			X[11] = crypto_load_be32toh(&in[11 * 4]);
+			X[12] = crypto_load_be32toh(&in[12 * 4]);
+			X[13] = crypto_load_be32toh(&in[13 * 4]);
+			X[14] = crypto_load_be32toh(&in[14 * 4]);
+			X[15] = crypto_load_be32toh(&in[15 * 4]);
+		}
+		in += SHA256_CBLOCK;
+
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[0], X[0]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[1], X[1]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[2], X[2]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[3], X[3]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[4], X[4]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[5], X[5]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[6], X[6]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[7], X[7]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[8], X[8]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[9], X[9]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[10], X[10]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[11], X[11]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[12], X[12]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[13], X[13]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[14], X[14]);
+		sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[15], X[15]);
+
+		for (i = 16; i < 64; i += 16) {
+			sha256_msg_schedule_update(&X[0], X[1], X[9], X[14]);
+			sha256_msg_schedule_update(&X[1], X[2], X[10], X[15]);
+			sha256_msg_schedule_update(&X[2], X[3], X[11], X[0]);
+			sha256_msg_schedule_update(&X[3], X[4], X[12], X[1]);
+			sha256_msg_schedule_update(&X[4], X[5], X[13], X[2]);
+			sha256_msg_schedule_update(&X[5], X[6], X[14], X[3]);
+			sha256_msg_schedule_update(&X[6], X[7], X[15], X[4]);
+			sha256_msg_schedule_update(&X[7], X[8], X[0], X[5]);
+			sha256_msg_schedule_update(&X[8], X[9], X[1], X[6]);
+			sha256_msg_schedule_update(&X[9], X[10], X[2], X[7]);
+			sha256_msg_schedule_update(&X[10], X[11], X[3], X[8]);
+			sha256_msg_schedule_update(&X[11], X[12], X[4], X[9]);
+			sha256_msg_schedule_update(&X[12], X[13], X[5], X[10]);
+			sha256_msg_schedule_update(&X[13], X[14], X[6], X[11]);
+			sha256_msg_schedule_update(&X[14], X[15], X[7], X[12]);
+			sha256_msg_schedule_update(&X[15], X[0], X[8], X[13]);
+
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 0], X[0]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 1], X[1]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 2], X[2]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 3], X[3]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 4], X[4]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 5], X[5]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 6], X[6]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 7], X[7]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 8], X[8]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 9], X[9]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 10], X[10]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 11], X[11]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 12], X[12]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 13], X[13]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 14], X[14]);
+			sha256_round(&a, &b, &c, &d, &e, &f, &g, &h, K256[i + 15], X[15]);
+		}
+
+		ctx->h[0] += a;
+		ctx->h[1] += b;
+		ctx->h[2] += c;
+		ctx->h[3] += d;
+		ctx->h[4] += e;
+		ctx->h[5] += f;
+		ctx->h[6] += g;
+		ctx->h[7] += h;
+	}
+}
+#endif /* SHA256_ASM */
+
+int
+SHA224_Init(SHA256_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->h[0] = 0xc1059ed8UL;
+	c->h[1] = 0x367cd507UL;
+	c->h[2] = 0x3070dd17UL;
+	c->h[3] = 0xf70e5939UL;
+	c->h[4] = 0xffc00b31UL;
+	c->h[5] = 0x68581511UL;
+	c->h[6] = 0x64f98fa7UL;
+	c->h[7] = 0xbefa4fa4UL;
+
+	c->md_len = SHA224_DIGEST_LENGTH;
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA224_Init);
+
+int
+SHA224_Update(SHA256_CTX *c, const void *data, size_t len)
+{
+	return SHA256_Update(c, data, len);
+}
+LCRYPTO_ALIAS(SHA224_Update);
+
+int
+SHA224_Final(unsigned char *md, SHA256_CTX *c)
+{
+	return SHA256_Final(md, c);
+}
+LCRYPTO_ALIAS(SHA224_Final);
+
+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);
+
+	explicit_bzero(&c, sizeof(c));
+
+	return (md);
+}
+LCRYPTO_ALIAS(SHA224);
+
+int
+SHA256_Init(SHA256_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->h[0] = 0x6a09e667UL;
+	c->h[1] = 0xbb67ae85UL;
+	c->h[2] = 0x3c6ef372UL;
+	c->h[3] = 0xa54ff53aUL;
+	c->h[4] = 0x510e527fUL;
+	c->h[5] = 0x9b05688cUL;
+	c->h[6] = 0x1f83d9abUL;
+	c->h[7] = 0x5be0cd19UL;
+
+	c->md_len = SHA256_DIGEST_LENGTH;
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA256_Init);
+
+int
+SHA256_Update(SHA256_CTX *c, const void *data_, size_t len)
+{
+	const unsigned char *data = data_;
+	unsigned char *p;
+	SHA_LONG l;
+	size_t n;
+
+	if (len == 0)
+		return 1;
+
+	l = (c->Nl + (((SHA_LONG)len) << 3)) & 0xffffffffUL;
+	/* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
+	 * Wei Dai  for pointing it out. */
+	if (l < c->Nl) /* overflow */
+		c->Nh++;
+	c->Nh += (SHA_LONG)(len >> 29);	/* might cause compiler warning on 16-bit */
+	c->Nl = l;
+
+	n = c->num;
+	if (n != 0) {
+		p = (unsigned char *)c->data;
+
+		if (len >= SHA_CBLOCK || len + n >= SHA_CBLOCK) {
+			memcpy(p + n, data, SHA_CBLOCK - n);
+			sha256_block_data_order(c, p, 1);
+			n = SHA_CBLOCK - n;
+			data += n;
+			len -= n;
+			c->num = 0;
+			memset(p, 0, SHA_CBLOCK);	/* keep it zeroed */
+		} else {
+			memcpy(p + n, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		}
+	}
+
+	n = len/SHA_CBLOCK;
+	if (n > 0) {
+		sha256_block_data_order(c, data, n);
+		n *= SHA_CBLOCK;
+		data += n;
+		len -= n;
+	}
+
+	if (len != 0) {
+		p = (unsigned char *)c->data;
+		c->num = (unsigned int)len;
+		memcpy(p, data, len);
+	}
+	return 1;
+}
+LCRYPTO_ALIAS(SHA256_Update);
+
+void
+SHA256_Transform(SHA256_CTX *c, const unsigned char *data)
+{
+	sha256_block_data_order(c, data, 1);
+}
+LCRYPTO_ALIAS(SHA256_Transform);
+
+int
+SHA256_Final(unsigned char *md, SHA256_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->data;
+	size_t n = c->num;
+	unsigned int nn;
+
+	p[n] = 0x80; /* there is always room for one */
+	n++;
+
+	if (n > (SHA_CBLOCK - 8)) {
+		memset(p + n, 0, SHA_CBLOCK - n);
+		n = 0;
+		sha256_block_data_order(c, p, 1);
+	}
+
+	memset(p + n, 0, SHA_CBLOCK - 8 - n);
+	c->data[SHA_LBLOCK - 2] = htobe32(c->Nh);
+	c->data[SHA_LBLOCK - 1] = htobe32(c->Nl);
+
+	sha256_block_data_order(c, p, 1);
+	c->num = 0;
+	memset(p, 0, SHA_CBLOCK);
+
+	/*
+	 * Note that FIPS180-2 discusses "Truncation of the Hash Function Output."
+	 * default: case below covers for it. It's not clear however if it's
+	 * permitted to truncate to amount of bytes not divisible by 4. I bet not,
+	 * but if it is, then default: case shall be extended. For reference.
+	 * Idea behind separate cases for pre-defined lengths is to let the
+	 * compiler decide if it's appropriate to unroll small loops.
+	 */
+	switch (c->md_len) {
+	case SHA224_DIGEST_LENGTH:
+		for (nn = 0; nn < SHA224_DIGEST_LENGTH / 4; nn++) {
+			crypto_store_htobe32(md, c->h[nn]);
+			md += 4;
+		}
+		break;
+
+	case SHA256_DIGEST_LENGTH:
+		for (nn = 0; nn < SHA256_DIGEST_LENGTH / 4; nn++) {
+			crypto_store_htobe32(md, c->h[nn]);
+			md += 4;
+		}
+		break;
+
+	default:
+		if (c->md_len > SHA256_DIGEST_LENGTH)
+			return 0;
+		for (nn = 0; nn < c->md_len / 4; nn++) {
+			crypto_store_htobe32(md, c->h[nn]);
+			md += 4;
+		}
+		break;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA256_Final);
+
+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);
+
+	explicit_bzero(&c, sizeof(c));
+
+	return (md);
+}
+LCRYPTO_ALIAS(SHA256);
+
+#endif /* OPENSSL_NO_SHA256 */
diff --git a/crypto/sha/sha3.c b/crypto/sha/sha3.c
new file mode 100644
index 0000000..b070d71
--- /dev/null
+++ b/crypto/sha/sha3.c
@@ -0,0 +1,193 @@
+/*	$OpenBSD: sha3.c,v 1.15 2023/04/16 15:32:16 jsing Exp $	*/
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Markku-Juhani O. Saarinen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "sha3_internal.h"
+
+#define KECCAKF_ROUNDS 24
+
+#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
+
+static const uint64_t sha3_keccakf_rndc[24] = {
+	0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
+	0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
+	0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
+	0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
+	0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
+	0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
+	0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
+	0x8000000000008080, 0x0000000080000001, 0x8000000080008008
+};
+static const int sha3_keccakf_rotc[24] = {
+	1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
+	27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
+};
+static const int sha3_keccakf_piln[24] = {
+	10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
+	15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
+};
+
+static void
+sha3_keccakf(uint64_t st[25])
+{
+	uint64_t t, bc[5];
+	int i, j, r;
+
+#if BYTE_ORDER != LITTLE_ENDIAN
+	uint8_t *v;
+
+	for (i = 0; i < 25; i++) {
+		v = (uint8_t *) &st[i];
+		st[i] = ((uint64_t) v[0])	 | (((uint64_t) v[1]) << 8) |
+			(((uint64_t) v[2]) << 16) | (((uint64_t) v[3]) << 24) |
+			(((uint64_t) v[4]) << 32) | (((uint64_t) v[5]) << 40) |
+			(((uint64_t) v[6]) << 48) | (((uint64_t) v[7]) << 56);
+	}
+#endif
+
+	for (r = 0; r < KECCAKF_ROUNDS; r++) {
+
+		/* Theta */
+		for (i = 0; i < 5; i++)
+			bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
+
+		for (i = 0; i < 5; i++) {
+			t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
+			for (j = 0; j < 25; j += 5)
+				st[j + i] ^= t;
+		}
+
+		/* Rho Pi */
+		t = st[1];
+		for (i = 0; i < 24; i++) {
+			j = sha3_keccakf_piln[i];
+			bc[0] = st[j];
+			st[j] = ROTL64(t, sha3_keccakf_rotc[i]);
+			t = bc[0];
+		}
+
+		/* Chi */
+		for (j = 0; j < 25; j += 5) {
+			for (i = 0; i < 5; i++)
+				bc[i] = st[j + i];
+			for (i = 0; i < 5; i++)
+				st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
+		}
+
+		/* Iota */
+		st[0] ^= sha3_keccakf_rndc[r];
+	}
+
+#if BYTE_ORDER != LITTLE_ENDIAN
+	for (i = 0; i < 25; i++) {
+		v = (uint8_t *) &st[i];
+		t = st[i];
+		v[0] = t & 0xFF;
+		v[1] = (t >> 8) & 0xFF;
+		v[2] = (t >> 16) & 0xFF;
+		v[3] = (t >> 24) & 0xFF;
+		v[4] = (t >> 32) & 0xFF;
+		v[5] = (t >> 40) & 0xFF;
+		v[6] = (t >> 48) & 0xFF;
+		v[7] = (t >> 56) & 0xFF;
+	}
+#endif
+}
+
+int
+sha3_init(sha3_ctx *c, int mdlen)
+{
+	if (mdlen < 0 || mdlen >= KECCAK_BYTE_WIDTH / 2)
+		return 0;
+
+	memset(c, 0, sizeof(*c));
+
+	c->mdlen = mdlen;
+	c->rsize = KECCAK_BYTE_WIDTH - 2 * mdlen;
+
+	return 1;
+}
+
+int
+sha3_update(sha3_ctx *c, const void *data, size_t len)
+{
+	size_t i, j;
+
+	j = c->pt;
+	for (i = 0; i < len; i++) {
+		c->state.b[j++] ^= ((const uint8_t *) data)[i];
+		if (j >= c->rsize) {
+			sha3_keccakf(c->state.q);
+			j = 0;
+		}
+	}
+	c->pt = j;
+
+	return 1;
+}
+
+int
+sha3_final(void *md, sha3_ctx *c)
+{
+	int i;
+
+	c->state.b[c->pt] ^= 0x06;
+	c->state.b[c->rsize - 1] ^= 0x80;
+	sha3_keccakf(c->state.q);
+
+	for (i = 0; i < c->mdlen; i++) {
+		((uint8_t *) md)[i] = c->state.b[i];
+	}
+
+	return 1;
+}
+
+/* SHAKE128 and SHAKE256 extensible-output functionality. */
+void
+shake_xof(sha3_ctx *c)
+{
+	c->state.b[c->pt] ^= 0x1F;
+	c->state.b[c->rsize - 1] ^= 0x80;
+	sha3_keccakf(c->state.q);
+	c->pt = 0;
+}
+
+void
+shake_out(sha3_ctx *c, void *out, size_t len)
+{
+	size_t i, j;
+
+	j = c->pt;
+	for (i = 0; i < len; i++) {
+		if (j >= c->rsize) {
+			sha3_keccakf(c->state.q);
+			j = 0;
+		}
+		((uint8_t *) out)[i] = c->state.b[j++];
+	}
+	c->pt = j;
+}
diff --git a/crypto/sha/sha3_internal.h b/crypto/sha/sha3_internal.h
new file mode 100644
index 0000000..53a4980
--- /dev/null
+++ b/crypto/sha/sha3_internal.h
@@ -0,0 +1,81 @@
+/*	$OpenBSD: sha3_internal.h,v 1.15 2023/04/25 19:32:19 tb Exp $	*/
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Markku-Juhani O. Saarinen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include 
+#include 
+
+#ifndef HEADER_SHA3_INTERNAL_H
+#define HEADER_SHA3_INTERNAL_H
+
+#define KECCAK_BIT_WIDTH	1600
+#define KECCAK_BYTE_WIDTH	(KECCAK_BIT_WIDTH / 8)
+
+#define SHA3_224_BIT_LENGTH	224
+#define SHA3_224_BITRATE	(2 * SHA3_224_BIT_LENGTH)
+#define SHA3_224_CAPACITY	(KECCAK_BIT_WIDTH - SHA3_224_BITRATE)
+#define SHA3_224_BLOCK_SIZE	(SHA3_224_CAPACITY / 8)
+#define SHA3_224_DIGEST_LENGTH	(SHA3_224_BIT_LENGTH / 8)
+
+#define SHA3_256_BIT_LENGTH	256
+#define SHA3_256_BITRATE	(2 * SHA3_256_BIT_LENGTH)
+#define SHA3_256_CAPACITY	(KECCAK_BIT_WIDTH - SHA3_256_BITRATE)
+#define SHA3_256_BLOCK_SIZE	(SHA3_256_CAPACITY / 8)
+#define SHA3_256_DIGEST_LENGTH	(SHA3_256_BIT_LENGTH / 8)
+
+#define SHA3_384_BIT_LENGTH	384
+#define SHA3_384_BITRATE	(2 * SHA3_384_BIT_LENGTH)
+#define SHA3_384_CAPACITY	(KECCAK_BIT_WIDTH - SHA3_384_BITRATE)
+#define SHA3_384_BLOCK_SIZE	(SHA3_384_CAPACITY / 8)
+#define SHA3_384_DIGEST_LENGTH	(SHA3_384_BIT_LENGTH / 8)
+
+#define SHA3_512_BIT_LENGTH	512
+#define SHA3_512_BITRATE	(2 * SHA3_512_BIT_LENGTH)
+#define SHA3_512_CAPACITY	(KECCAK_BIT_WIDTH - SHA3_512_BITRATE)
+#define SHA3_512_BLOCK_SIZE	(SHA3_512_CAPACITY / 8)
+#define SHA3_512_DIGEST_LENGTH	(SHA3_512_BIT_LENGTH / 8)
+
+typedef struct sha3_ctx_st {
+	union {
+		uint8_t b[200];		/* State as 8 bit bytes. */
+		uint64_t q[25];		/* State as 64 bit words. */
+	} state;
+	size_t pt;
+	size_t rsize;
+	size_t mdlen;
+} sha3_ctx;
+
+int sha3_init(sha3_ctx *c, int mdlen);
+int sha3_update(sha3_ctx *c, const void *data, size_t len);
+int sha3_final(void *md, sha3_ctx *c);
+
+/* SHAKE128 and SHAKE256 extensible-output functions. */
+#define shake128_init(c) sha3_init(c, 16)
+#define shake256_init(c) sha3_init(c, 32)
+#define shake_update sha3_update
+
+void shake_xof(sha3_ctx *c);
+void shake_out(sha3_ctx *c, void *out, size_t len);
+
+#endif
diff --git a/crypto/sha/sha512-elf-armv4.S b/crypto/sha/sha512-elf-armv4.S
new file mode 100644
index 0000000..8abf8d5
--- /dev/null
+++ b/crypto/sha/sha512-elf-armv4.S
@@ -0,0 +1,1786 @@
+#include "arm_arch.h"
+#ifdef __ARMEL__
+# define LO 0
+# define HI 4
+# 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
+#endif
+
+.text
+.code	32
+.type	K512,%object
+.align	5
+K512:
+WORD64(0x428a2f98,0xd728ae22, 0x71374491,0x23ef65cd)
+WORD64(0xb5c0fbcf,0xec4d3b2f, 0xe9b5dba5,0x8189dbbc)
+WORD64(0x3956c25b,0xf348b538, 0x59f111f1,0xb605d019)
+WORD64(0x923f82a4,0xaf194f9b, 0xab1c5ed5,0xda6d8118)
+WORD64(0xd807aa98,0xa3030242, 0x12835b01,0x45706fbe)
+WORD64(0x243185be,0x4ee4b28c, 0x550c7dc3,0xd5ffb4e2)
+WORD64(0x72be5d74,0xf27b896f, 0x80deb1fe,0x3b1696b1)
+WORD64(0x9bdc06a7,0x25c71235, 0xc19bf174,0xcf692694)
+WORD64(0xe49b69c1,0x9ef14ad2, 0xefbe4786,0x384f25e3)
+WORD64(0x0fc19dc6,0x8b8cd5b5, 0x240ca1cc,0x77ac9c65)
+WORD64(0x2de92c6f,0x592b0275, 0x4a7484aa,0x6ea6e483)
+WORD64(0x5cb0a9dc,0xbd41fbd4, 0x76f988da,0x831153b5)
+WORD64(0x983e5152,0xee66dfab, 0xa831c66d,0x2db43210)
+WORD64(0xb00327c8,0x98fb213f, 0xbf597fc7,0xbeef0ee4)
+WORD64(0xc6e00bf3,0x3da88fc2, 0xd5a79147,0x930aa725)
+WORD64(0x06ca6351,0xe003826f, 0x14292967,0x0a0e6e70)
+WORD64(0x27b70a85,0x46d22ffc, 0x2e1b2138,0x5c26c926)
+WORD64(0x4d2c6dfc,0x5ac42aed, 0x53380d13,0x9d95b3df)
+WORD64(0x650a7354,0x8baf63de, 0x766a0abb,0x3c77b2a8)
+WORD64(0x81c2c92e,0x47edaee6, 0x92722c85,0x1482353b)
+WORD64(0xa2bfe8a1,0x4cf10364, 0xa81a664b,0xbc423001)
+WORD64(0xc24b8b70,0xd0f89791, 0xc76c51a3,0x0654be30)
+WORD64(0xd192e819,0xd6ef5218, 0xd6990624,0x5565a910)
+WORD64(0xf40e3585,0x5771202a, 0x106aa070,0x32bbd1b8)
+WORD64(0x19a4c116,0xb8d2d0c8, 0x1e376c08,0x5141ab53)
+WORD64(0x2748774c,0xdf8eeb99, 0x34b0bcb5,0xe19b48a8)
+WORD64(0x391c0cb3,0xc5c95a63, 0x4ed8aa4a,0xe3418acb)
+WORD64(0x5b9cca4f,0x7763e373, 0x682e6ff3,0xd6b2b8a3)
+WORD64(0x748f82ee,0x5defb2fc, 0x78a5636f,0x43172f60)
+WORD64(0x84c87814,0xa1f0ab72, 0x8cc70208,0x1a6439ec)
+WORD64(0x90befffa,0x23631e28, 0xa4506ceb,0xde82bde9)
+WORD64(0xbef9a3f7,0xb2c67915, 0xc67178f2,0xe372532b)
+WORD64(0xca273ece,0xea26619c, 0xd186b8c7,0x21c0c207)
+WORD64(0xeada7dd6,0xcde0eb1e, 0xf57d4f7f,0xee6ed178)
+WORD64(0x06f067aa,0x72176fba, 0x0a637dc5,0xa2c898a6)
+WORD64(0x113f9804,0xbef90dae, 0x1b710b35,0x131c471b)
+WORD64(0x28db77f5,0x23047d84, 0x32caab7b,0x40c72493)
+WORD64(0x3c9ebe0a,0x15c9bebc, 0x431d67c4,0x9c100d4c)
+WORD64(0x4cc5d4be,0xcb3e42b6, 0x597f299c,0xfc657e2a)
+WORD64(0x5fcb6fab,0x3ad6faec, 0x6c44198c,0x4a475817)
+.size	K512,.-K512
+.LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-sha512_block_data_order
+.skip	32-4
+
+.global	sha512_block_data_order
+.type	sha512_block_data_order,%function
+sha512_block_data_order:
+	sub	r3,pc,#8		@ sha512_block_data_order
+	add	r2,r1,r2,lsl#7	@ len to point at the end of inp
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+	ldr	r12,.LOPENSSL_armcap
+	ldr	r12,[r3,r12]		@ OPENSSL_armcap_P
+	tst	r12,#1
+	bne	.LNEON
+#endif
+	stmdb	sp!,{r4-r12,lr}
+	sub	r14,r3,#672		@ K512
+	sub	sp,sp,#9*8
+
+	ldr	r7,[r0,#32+LO]
+	ldr	r8,[r0,#32+HI]
+	ldr	r9, [r0,#48+LO]
+	ldr	r10, [r0,#48+HI]
+	ldr	r11, [r0,#56+LO]
+	ldr	r12, [r0,#56+HI]
+.Loop:
+	str	r9, [sp,#48+0]
+	str	r10, [sp,#48+4]
+	str	r11, [sp,#56+0]
+	str	r12, [sp,#56+4]
+	ldr	r5,[r0,#0+LO]
+	ldr	r6,[r0,#0+HI]
+	ldr	r3,[r0,#8+LO]
+	ldr	r4,[r0,#8+HI]
+	ldr	r9, [r0,#16+LO]
+	ldr	r10, [r0,#16+HI]
+	ldr	r11, [r0,#24+LO]
+	ldr	r12, [r0,#24+HI]
+	str	r3,[sp,#8+0]
+	str	r4,[sp,#8+4]
+	str	r9, [sp,#16+0]
+	str	r10, [sp,#16+4]
+	str	r11, [sp,#24+0]
+	str	r12, [sp,#24+4]
+	ldr	r3,[r0,#40+LO]
+	ldr	r4,[r0,#40+HI]
+	str	r3,[sp,#40+0]
+	str	r4,[sp,#40+4]
+
+.L00_15:
+#if __ARM_ARCH__<7 || defined(__STRICT_ALIGNMENT)
+	ldrb	r3,[r1,#7]
+	ldrb	r9, [r1,#6]
+	ldrb	r10, [r1,#5]
+	ldrb	r11, [r1,#4]
+	ldrb	r4,[r1,#3]
+	ldrb	r12, [r1,#2]
+	orr	r3,r3,r9,lsl#8
+	ldrb	r9, [r1,#1]
+	orr	r3,r3,r10,lsl#16
+	ldrb	r10, [r1],#8
+	orr	r3,r3,r11,lsl#24
+	orr	r4,r4,r12,lsl#8
+	orr	r4,r4,r9,lsl#16
+	orr	r4,r4,r10,lsl#24
+#else
+	ldr	r3,[r1,#4]
+	ldr	r4,[r1],#8
+#ifdef __ARMEL__
+	rev	r3,r3
+	rev	r4,r4
+#endif
+#endif
+	@ Sigma1(x)	(ROTR((x),14) ^ ROTR((x),18)  ^ ROTR((x),41))
+	@ LO		lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+	@ HI		hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+	mov	r9,r7,lsr#14
+	str	r3,[sp,#64+0]
+	mov	r10,r8,lsr#14
+	str	r4,[sp,#64+4]
+	eor	r9,r9,r8,lsl#18
+	ldr	r11,[sp,#56+0]	@ h.lo
+	eor	r10,r10,r7,lsl#18
+	ldr	r12,[sp,#56+4]	@ h.hi
+	eor	r9,r9,r7,lsr#18
+	eor	r10,r10,r8,lsr#18
+	eor	r9,r9,r8,lsl#14
+	eor	r10,r10,r7,lsl#14
+	eor	r9,r9,r8,lsr#9
+	eor	r10,r10,r7,lsr#9
+	eor	r9,r9,r7,lsl#23
+	eor	r10,r10,r8,lsl#23	@ Sigma1(e)
+	adds	r3,r3,r9
+	ldr	r9,[sp,#40+0]	@ f.lo
+	adc	r4,r4,r10		@ T += Sigma1(e)
+	ldr	r10,[sp,#40+4]	@ f.hi
+	adds	r3,r3,r11
+	ldr	r11,[sp,#48+0]	@ g.lo
+	adc	r4,r4,r12		@ T += h
+	ldr	r12,[sp,#48+4]	@ g.hi
+
+	eor	r9,r9,r11
+	str	r7,[sp,#32+0]
+	eor	r10,r10,r12
+	str	r8,[sp,#32+4]
+	and	r9,r9,r7
+	str	r5,[sp,#0+0]
+	and	r10,r10,r8
+	str	r6,[sp,#0+4]
+	eor	r9,r9,r11
+	ldr	r11,[r14,#LO]	@ K[i].lo
+	eor	r10,r10,r12		@ Ch(e,f,g)
+	ldr	r12,[r14,#HI]	@ K[i].hi
+
+	adds	r3,r3,r9
+	ldr	r7,[sp,#24+0]	@ d.lo
+	adc	r4,r4,r10		@ T += Ch(e,f,g)
+	ldr	r8,[sp,#24+4]	@ d.hi
+	adds	r3,r3,r11
+	and	r9,r11,#0xff
+	adc	r4,r4,r12		@ T += K[i]
+	adds	r7,r7,r3
+	ldr	r11,[sp,#8+0]	@ b.lo
+	adc	r8,r8,r4		@ d += T
+	teq	r9,#148
+
+	ldr	r12,[sp,#16+0]	@ c.lo
+	orreq	r14,r14,#1
+	@ Sigma0(x)	(ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+	@ LO		lo>>28^hi<<4  ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+	@ HI		hi>>28^lo<<4  ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+	mov	r9,r5,lsr#28
+	mov	r10,r6,lsr#28
+	eor	r9,r9,r6,lsl#4
+	eor	r10,r10,r5,lsl#4
+	eor	r9,r9,r6,lsr#2
+	eor	r10,r10,r5,lsr#2
+	eor	r9,r9,r5,lsl#30
+	eor	r10,r10,r6,lsl#30
+	eor	r9,r9,r6,lsr#7
+	eor	r10,r10,r5,lsr#7
+	eor	r9,r9,r5,lsl#25
+	eor	r10,r10,r6,lsl#25	@ Sigma0(a)
+	adds	r3,r3,r9
+	and	r9,r5,r11
+	adc	r4,r4,r10		@ T += Sigma0(a)
+
+	ldr	r10,[sp,#8+4]	@ b.hi
+	orr	r5,r5,r11
+	ldr	r11,[sp,#16+4]	@ c.hi
+	and	r5,r5,r12
+	and	r12,r6,r10
+	orr	r6,r6,r10
+	orr	r5,r5,r9		@ Maj(a,b,c).lo
+	and	r6,r6,r11
+	adds	r5,r5,r3
+	orr	r6,r6,r12		@ Maj(a,b,c).hi
+	sub	sp,sp,#8
+	adc	r6,r6,r4		@ h += T
+	tst	r14,#1
+	add	r14,r14,#8
+	tst	r14,#1
+	beq	.L00_15
+	ldr	r9,[sp,#184+0]
+	ldr	r10,[sp,#184+4]
+	bic	r14,r14,#1
+.L16_79:
+	@ sigma0(x)	(ROTR((x),1)  ^ ROTR((x),8)  ^ ((x)>>7))
+	@ LO		lo>>1^hi<<31  ^ lo>>8^hi<<24 ^ lo>>7^hi<<25
+	@ HI		hi>>1^lo<<31  ^ hi>>8^lo<<24 ^ hi>>7
+	mov	r3,r9,lsr#1
+	ldr	r11,[sp,#80+0]
+	mov	r4,r10,lsr#1
+	ldr	r12,[sp,#80+4]
+	eor	r3,r3,r10,lsl#31
+	eor	r4,r4,r9,lsl#31
+	eor	r3,r3,r9,lsr#8
+	eor	r4,r4,r10,lsr#8
+	eor	r3,r3,r10,lsl#24
+	eor	r4,r4,r9,lsl#24
+	eor	r3,r3,r9,lsr#7
+	eor	r4,r4,r10,lsr#7
+	eor	r3,r3,r10,lsl#25
+
+	@ sigma1(x)	(ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6))
+	@ LO		lo>>19^hi<<13 ^ hi>>29^lo<<3 ^ lo>>6^hi<<26
+	@ HI		hi>>19^lo<<13 ^ lo>>29^hi<<3 ^ hi>>6
+	mov	r9,r11,lsr#19
+	mov	r10,r12,lsr#19
+	eor	r9,r9,r12,lsl#13
+	eor	r10,r10,r11,lsl#13
+	eor	r9,r9,r12,lsr#29
+	eor	r10,r10,r11,lsr#29
+	eor	r9,r9,r11,lsl#3
+	eor	r10,r10,r12,lsl#3
+	eor	r9,r9,r11,lsr#6
+	eor	r10,r10,r12,lsr#6
+	ldr	r11,[sp,#120+0]
+	eor	r9,r9,r12,lsl#26
+
+	ldr	r12,[sp,#120+4]
+	adds	r3,r3,r9
+	ldr	r9,[sp,#192+0]
+	adc	r4,r4,r10
+
+	ldr	r10,[sp,#192+4]
+	adds	r3,r3,r11
+	adc	r4,r4,r12
+	adds	r3,r3,r9
+	adc	r4,r4,r10
+	@ Sigma1(x)	(ROTR((x),14) ^ ROTR((x),18)  ^ ROTR((x),41))
+	@ LO		lo>>14^hi<<18 ^ lo>>18^hi<<14 ^ hi>>9^lo<<23
+	@ HI		hi>>14^lo<<18 ^ hi>>18^lo<<14 ^ lo>>9^hi<<23
+	mov	r9,r7,lsr#14
+	str	r3,[sp,#64+0]
+	mov	r10,r8,lsr#14
+	str	r4,[sp,#64+4]
+	eor	r9,r9,r8,lsl#18
+	ldr	r11,[sp,#56+0]	@ h.lo
+	eor	r10,r10,r7,lsl#18
+	ldr	r12,[sp,#56+4]	@ h.hi
+	eor	r9,r9,r7,lsr#18
+	eor	r10,r10,r8,lsr#18
+	eor	r9,r9,r8,lsl#14
+	eor	r10,r10,r7,lsl#14
+	eor	r9,r9,r8,lsr#9
+	eor	r10,r10,r7,lsr#9
+	eor	r9,r9,r7,lsl#23
+	eor	r10,r10,r8,lsl#23	@ Sigma1(e)
+	adds	r3,r3,r9
+	ldr	r9,[sp,#40+0]	@ f.lo
+	adc	r4,r4,r10		@ T += Sigma1(e)
+	ldr	r10,[sp,#40+4]	@ f.hi
+	adds	r3,r3,r11
+	ldr	r11,[sp,#48+0]	@ g.lo
+	adc	r4,r4,r12		@ T += h
+	ldr	r12,[sp,#48+4]	@ g.hi
+
+	eor	r9,r9,r11
+	str	r7,[sp,#32+0]
+	eor	r10,r10,r12
+	str	r8,[sp,#32+4]
+	and	r9,r9,r7
+	str	r5,[sp,#0+0]
+	and	r10,r10,r8
+	str	r6,[sp,#0+4]
+	eor	r9,r9,r11
+	ldr	r11,[r14,#LO]	@ K[i].lo
+	eor	r10,r10,r12		@ Ch(e,f,g)
+	ldr	r12,[r14,#HI]	@ K[i].hi
+
+	adds	r3,r3,r9
+	ldr	r7,[sp,#24+0]	@ d.lo
+	adc	r4,r4,r10		@ T += Ch(e,f,g)
+	ldr	r8,[sp,#24+4]	@ d.hi
+	adds	r3,r3,r11
+	and	r9,r11,#0xff
+	adc	r4,r4,r12		@ T += K[i]
+	adds	r7,r7,r3
+	ldr	r11,[sp,#8+0]	@ b.lo
+	adc	r8,r8,r4		@ d += T
+	teq	r9,#23
+
+	ldr	r12,[sp,#16+0]	@ c.lo
+	orreq	r14,r14,#1
+	@ Sigma0(x)	(ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39))
+	@ LO		lo>>28^hi<<4  ^ hi>>2^lo<<30 ^ hi>>7^lo<<25
+	@ HI		hi>>28^lo<<4  ^ lo>>2^hi<<30 ^ lo>>7^hi<<25
+	mov	r9,r5,lsr#28
+	mov	r10,r6,lsr#28
+	eor	r9,r9,r6,lsl#4
+	eor	r10,r10,r5,lsl#4
+	eor	r9,r9,r6,lsr#2
+	eor	r10,r10,r5,lsr#2
+	eor	r9,r9,r5,lsl#30
+	eor	r10,r10,r6,lsl#30
+	eor	r9,r9,r6,lsr#7
+	eor	r10,r10,r5,lsr#7
+	eor	r9,r9,r5,lsl#25
+	eor	r10,r10,r6,lsl#25	@ Sigma0(a)
+	adds	r3,r3,r9
+	and	r9,r5,r11
+	adc	r4,r4,r10		@ T += Sigma0(a)
+
+	ldr	r10,[sp,#8+4]	@ b.hi
+	orr	r5,r5,r11
+	ldr	r11,[sp,#16+4]	@ c.hi
+	and	r5,r5,r12
+	and	r12,r6,r10
+	orr	r6,r6,r10
+	orr	r5,r5,r9		@ Maj(a,b,c).lo
+	and	r6,r6,r11
+	adds	r5,r5,r3
+	orr	r6,r6,r12		@ Maj(a,b,c).hi
+	sub	sp,sp,#8
+	adc	r6,r6,r4		@ h += T
+	tst	r14,#1
+	add	r14,r14,#8
+	ldreq	r9,[sp,#184+0]
+	ldreq	r10,[sp,#184+4]
+	beq	.L16_79
+	bic	r14,r14,#1
+
+	ldr	r3,[sp,#8+0]
+	ldr	r4,[sp,#8+4]
+	ldr	r9, [r0,#0+LO]
+	ldr	r10, [r0,#0+HI]
+	ldr	r11, [r0,#8+LO]
+	ldr	r12, [r0,#8+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#0+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#0+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#8+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#8+HI]
+
+	ldr	r5,[sp,#16+0]
+	ldr	r6,[sp,#16+4]
+	ldr	r3,[sp,#24+0]
+	ldr	r4,[sp,#24+4]
+	ldr	r9, [r0,#16+LO]
+	ldr	r10, [r0,#16+HI]
+	ldr	r11, [r0,#24+LO]
+	ldr	r12, [r0,#24+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#16+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#16+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#24+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#24+HI]
+
+	ldr	r3,[sp,#40+0]
+	ldr	r4,[sp,#40+4]
+	ldr	r9, [r0,#32+LO]
+	ldr	r10, [r0,#32+HI]
+	ldr	r11, [r0,#40+LO]
+	ldr	r12, [r0,#40+HI]
+	adds	r7,r7,r9
+	str	r7,[r0,#32+LO]
+	adc	r8,r8,r10
+	str	r8,[r0,#32+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#40+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#40+HI]
+
+	ldr	r5,[sp,#48+0]
+	ldr	r6,[sp,#48+4]
+	ldr	r3,[sp,#56+0]
+	ldr	r4,[sp,#56+4]
+	ldr	r9, [r0,#48+LO]
+	ldr	r10, [r0,#48+HI]
+	ldr	r11, [r0,#56+LO]
+	ldr	r12, [r0,#56+HI]
+	adds	r9,r5,r9
+	str	r9, [r0,#48+LO]
+	adc	r10,r6,r10
+	str	r10, [r0,#48+HI]
+	adds	r11,r3,r11
+	str	r11, [r0,#56+LO]
+	adc	r12,r4,r12
+	str	r12, [r0,#56+HI]
+
+	add	sp,sp,#640
+	sub	r14,r14,#640
+
+	teq	r1,r2
+	bne	.Loop
+
+	add	sp,sp,#8*9		@ destroy frame
+#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
+	.word	0xe12fff1e			@ interoperable with Thumb ISA:-)
+#endif
+#if __ARM_ARCH__>=7 && !defined(__STRICT_ALIGNMENT)
+.fpu	neon
+
+.align	4
+.LNEON:
+	dmb				@ errata #451034 on early Cortex A8
+	vstmdb	sp!,{d8-d15}		@ ABI specification says so
+	sub	r3,r3,#672		@ K512
+	vldmia	r0,{d16-d23}		@ load context
+.Loop_neon:
+	vshr.u64	d24,d20,#14	@ 0
+#if 0<16
+	vld1.64		{d0},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d20,#18
+	vshr.u64	d26,d20,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d20,#50
+	vsli.64		d25,d20,#46
+	vsli.64		d26,d20,#23
+#if 0<16 && defined(__ARMEL__)
+	vrev64.8	d0,d0
+#endif
+	vadd.i64	d27,d28,d23
+	veor		d29,d21,d22
+	veor		d24,d25
+	vand		d29,d20
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d22			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d16,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d16,#34
+	vshr.u64	d26,d16,#39
+	vsli.64		d24,d16,#36
+	vsli.64		d25,d16,#30
+	vsli.64		d26,d16,#25
+	vadd.i64	d27,d0
+	vorr		d30,d16,d18
+	vand		d29,d16,d18
+	veor		d23,d24,d25
+	vand		d30,d17
+	veor		d23,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d23,d27
+	vadd.i64	d19,d27
+	vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 1
+#if 1<16
+	vld1.64		{d1},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+	vshr.u64	d26,d19,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d19,#50
+	vsli.64		d25,d19,#46
+	vsli.64		d26,d19,#23
+#if 1<16 && defined(__ARMEL__)
+	vrev64.8	d1,d1
+#endif
+	vadd.i64	d27,d28,d22
+	veor		d29,d20,d21
+	veor		d24,d25
+	vand		d29,d19
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d21			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d23,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d23,#34
+	vshr.u64	d26,d23,#39
+	vsli.64		d24,d23,#36
+	vsli.64		d25,d23,#30
+	vsli.64		d26,d23,#25
+	vadd.i64	d27,d1
+	vorr		d30,d23,d17
+	vand		d29,d23,d17
+	veor		d22,d24,d25
+	vand		d30,d16
+	veor		d22,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d22,d27
+	vadd.i64	d18,d27
+	vadd.i64	d22,d30
+	vshr.u64	d24,d18,#14	@ 2
+#if 2<16
+	vld1.64		{d2},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d18,#18
+	vshr.u64	d26,d18,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d18,#50
+	vsli.64		d25,d18,#46
+	vsli.64		d26,d18,#23
+#if 2<16 && defined(__ARMEL__)
+	vrev64.8	d2,d2
+#endif
+	vadd.i64	d27,d28,d21
+	veor		d29,d19,d20
+	veor		d24,d25
+	vand		d29,d18
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d20			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d22,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d22,#34
+	vshr.u64	d26,d22,#39
+	vsli.64		d24,d22,#36
+	vsli.64		d25,d22,#30
+	vsli.64		d26,d22,#25
+	vadd.i64	d27,d2
+	vorr		d30,d22,d16
+	vand		d29,d22,d16
+	veor		d21,d24,d25
+	vand		d30,d23
+	veor		d21,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d21,d27
+	vadd.i64	d17,d27
+	vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 3
+#if 3<16
+	vld1.64		{d3},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+	vshr.u64	d26,d17,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d17,#50
+	vsli.64		d25,d17,#46
+	vsli.64		d26,d17,#23
+#if 3<16 && defined(__ARMEL__)
+	vrev64.8	d3,d3
+#endif
+	vadd.i64	d27,d28,d20
+	veor		d29,d18,d19
+	veor		d24,d25
+	vand		d29,d17
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d19			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d21,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d21,#34
+	vshr.u64	d26,d21,#39
+	vsli.64		d24,d21,#36
+	vsli.64		d25,d21,#30
+	vsli.64		d26,d21,#25
+	vadd.i64	d27,d3
+	vorr		d30,d21,d23
+	vand		d29,d21,d23
+	veor		d20,d24,d25
+	vand		d30,d22
+	veor		d20,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d20,d27
+	vadd.i64	d16,d27
+	vadd.i64	d20,d30
+	vshr.u64	d24,d16,#14	@ 4
+#if 4<16
+	vld1.64		{d4},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d16,#18
+	vshr.u64	d26,d16,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d16,#50
+	vsli.64		d25,d16,#46
+	vsli.64		d26,d16,#23
+#if 4<16 && defined(__ARMEL__)
+	vrev64.8	d4,d4
+#endif
+	vadd.i64	d27,d28,d19
+	veor		d29,d17,d18
+	veor		d24,d25
+	vand		d29,d16
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d18			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d20,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d20,#34
+	vshr.u64	d26,d20,#39
+	vsli.64		d24,d20,#36
+	vsli.64		d25,d20,#30
+	vsli.64		d26,d20,#25
+	vadd.i64	d27,d4
+	vorr		d30,d20,d22
+	vand		d29,d20,d22
+	veor		d19,d24,d25
+	vand		d30,d21
+	veor		d19,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d19,d27
+	vadd.i64	d23,d27
+	vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 5
+#if 5<16
+	vld1.64		{d5},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+	vshr.u64	d26,d23,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d23,#50
+	vsli.64		d25,d23,#46
+	vsli.64		d26,d23,#23
+#if 5<16 && defined(__ARMEL__)
+	vrev64.8	d5,d5
+#endif
+	vadd.i64	d27,d28,d18
+	veor		d29,d16,d17
+	veor		d24,d25
+	vand		d29,d23
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d17			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d19,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d19,#34
+	vshr.u64	d26,d19,#39
+	vsli.64		d24,d19,#36
+	vsli.64		d25,d19,#30
+	vsli.64		d26,d19,#25
+	vadd.i64	d27,d5
+	vorr		d30,d19,d21
+	vand		d29,d19,d21
+	veor		d18,d24,d25
+	vand		d30,d20
+	veor		d18,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d18,d27
+	vadd.i64	d22,d27
+	vadd.i64	d18,d30
+	vshr.u64	d24,d22,#14	@ 6
+#if 6<16
+	vld1.64		{d6},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d22,#18
+	vshr.u64	d26,d22,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d22,#50
+	vsli.64		d25,d22,#46
+	vsli.64		d26,d22,#23
+#if 6<16 && defined(__ARMEL__)
+	vrev64.8	d6,d6
+#endif
+	vadd.i64	d27,d28,d17
+	veor		d29,d23,d16
+	veor		d24,d25
+	vand		d29,d22
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d16			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d18,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d18,#34
+	vshr.u64	d26,d18,#39
+	vsli.64		d24,d18,#36
+	vsli.64		d25,d18,#30
+	vsli.64		d26,d18,#25
+	vadd.i64	d27,d6
+	vorr		d30,d18,d20
+	vand		d29,d18,d20
+	veor		d17,d24,d25
+	vand		d30,d19
+	veor		d17,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d17,d27
+	vadd.i64	d21,d27
+	vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 7
+#if 7<16
+	vld1.64		{d7},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+	vshr.u64	d26,d21,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d21,#50
+	vsli.64		d25,d21,#46
+	vsli.64		d26,d21,#23
+#if 7<16 && defined(__ARMEL__)
+	vrev64.8	d7,d7
+#endif
+	vadd.i64	d27,d28,d16
+	veor		d29,d22,d23
+	veor		d24,d25
+	vand		d29,d21
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d23			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d17,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d17,#34
+	vshr.u64	d26,d17,#39
+	vsli.64		d24,d17,#36
+	vsli.64		d25,d17,#30
+	vsli.64		d26,d17,#25
+	vadd.i64	d27,d7
+	vorr		d30,d17,d19
+	vand		d29,d17,d19
+	veor		d16,d24,d25
+	vand		d30,d18
+	veor		d16,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d16,d27
+	vadd.i64	d20,d27
+	vadd.i64	d16,d30
+	vshr.u64	d24,d20,#14	@ 8
+#if 8<16
+	vld1.64		{d8},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d20,#18
+	vshr.u64	d26,d20,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d20,#50
+	vsli.64		d25,d20,#46
+	vsli.64		d26,d20,#23
+#if 8<16 && defined(__ARMEL__)
+	vrev64.8	d8,d8
+#endif
+	vadd.i64	d27,d28,d23
+	veor		d29,d21,d22
+	veor		d24,d25
+	vand		d29,d20
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d22			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d16,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d16,#34
+	vshr.u64	d26,d16,#39
+	vsli.64		d24,d16,#36
+	vsli.64		d25,d16,#30
+	vsli.64		d26,d16,#25
+	vadd.i64	d27,d8
+	vorr		d30,d16,d18
+	vand		d29,d16,d18
+	veor		d23,d24,d25
+	vand		d30,d17
+	veor		d23,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d23,d27
+	vadd.i64	d19,d27
+	vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 9
+#if 9<16
+	vld1.64		{d9},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+	vshr.u64	d26,d19,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d19,#50
+	vsli.64		d25,d19,#46
+	vsli.64		d26,d19,#23
+#if 9<16 && defined(__ARMEL__)
+	vrev64.8	d9,d9
+#endif
+	vadd.i64	d27,d28,d22
+	veor		d29,d20,d21
+	veor		d24,d25
+	vand		d29,d19
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d21			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d23,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d23,#34
+	vshr.u64	d26,d23,#39
+	vsli.64		d24,d23,#36
+	vsli.64		d25,d23,#30
+	vsli.64		d26,d23,#25
+	vadd.i64	d27,d9
+	vorr		d30,d23,d17
+	vand		d29,d23,d17
+	veor		d22,d24,d25
+	vand		d30,d16
+	veor		d22,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d22,d27
+	vadd.i64	d18,d27
+	vadd.i64	d22,d30
+	vshr.u64	d24,d18,#14	@ 10
+#if 10<16
+	vld1.64		{d10},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d18,#18
+	vshr.u64	d26,d18,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d18,#50
+	vsli.64		d25,d18,#46
+	vsli.64		d26,d18,#23
+#if 10<16 && defined(__ARMEL__)
+	vrev64.8	d10,d10
+#endif
+	vadd.i64	d27,d28,d21
+	veor		d29,d19,d20
+	veor		d24,d25
+	vand		d29,d18
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d20			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d22,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d22,#34
+	vshr.u64	d26,d22,#39
+	vsli.64		d24,d22,#36
+	vsli.64		d25,d22,#30
+	vsli.64		d26,d22,#25
+	vadd.i64	d27,d10
+	vorr		d30,d22,d16
+	vand		d29,d22,d16
+	veor		d21,d24,d25
+	vand		d30,d23
+	veor		d21,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d21,d27
+	vadd.i64	d17,d27
+	vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 11
+#if 11<16
+	vld1.64		{d11},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+	vshr.u64	d26,d17,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d17,#50
+	vsli.64		d25,d17,#46
+	vsli.64		d26,d17,#23
+#if 11<16 && defined(__ARMEL__)
+	vrev64.8	d11,d11
+#endif
+	vadd.i64	d27,d28,d20
+	veor		d29,d18,d19
+	veor		d24,d25
+	vand		d29,d17
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d19			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d21,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d21,#34
+	vshr.u64	d26,d21,#39
+	vsli.64		d24,d21,#36
+	vsli.64		d25,d21,#30
+	vsli.64		d26,d21,#25
+	vadd.i64	d27,d11
+	vorr		d30,d21,d23
+	vand		d29,d21,d23
+	veor		d20,d24,d25
+	vand		d30,d22
+	veor		d20,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d20,d27
+	vadd.i64	d16,d27
+	vadd.i64	d20,d30
+	vshr.u64	d24,d16,#14	@ 12
+#if 12<16
+	vld1.64		{d12},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d16,#18
+	vshr.u64	d26,d16,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d16,#50
+	vsli.64		d25,d16,#46
+	vsli.64		d26,d16,#23
+#if 12<16 && defined(__ARMEL__)
+	vrev64.8	d12,d12
+#endif
+	vadd.i64	d27,d28,d19
+	veor		d29,d17,d18
+	veor		d24,d25
+	vand		d29,d16
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d18			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d20,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d20,#34
+	vshr.u64	d26,d20,#39
+	vsli.64		d24,d20,#36
+	vsli.64		d25,d20,#30
+	vsli.64		d26,d20,#25
+	vadd.i64	d27,d12
+	vorr		d30,d20,d22
+	vand		d29,d20,d22
+	veor		d19,d24,d25
+	vand		d30,d21
+	veor		d19,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d19,d27
+	vadd.i64	d23,d27
+	vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 13
+#if 13<16
+	vld1.64		{d13},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+	vshr.u64	d26,d23,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d23,#50
+	vsli.64		d25,d23,#46
+	vsli.64		d26,d23,#23
+#if 13<16 && defined(__ARMEL__)
+	vrev64.8	d13,d13
+#endif
+	vadd.i64	d27,d28,d18
+	veor		d29,d16,d17
+	veor		d24,d25
+	vand		d29,d23
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d17			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d19,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d19,#34
+	vshr.u64	d26,d19,#39
+	vsli.64		d24,d19,#36
+	vsli.64		d25,d19,#30
+	vsli.64		d26,d19,#25
+	vadd.i64	d27,d13
+	vorr		d30,d19,d21
+	vand		d29,d19,d21
+	veor		d18,d24,d25
+	vand		d30,d20
+	veor		d18,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d18,d27
+	vadd.i64	d22,d27
+	vadd.i64	d18,d30
+	vshr.u64	d24,d22,#14	@ 14
+#if 14<16
+	vld1.64		{d14},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d22,#18
+	vshr.u64	d26,d22,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d22,#50
+	vsli.64		d25,d22,#46
+	vsli.64		d26,d22,#23
+#if 14<16 && defined(__ARMEL__)
+	vrev64.8	d14,d14
+#endif
+	vadd.i64	d27,d28,d17
+	veor		d29,d23,d16
+	veor		d24,d25
+	vand		d29,d22
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d16			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d18,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d18,#34
+	vshr.u64	d26,d18,#39
+	vsli.64		d24,d18,#36
+	vsli.64		d25,d18,#30
+	vsli.64		d26,d18,#25
+	vadd.i64	d27,d14
+	vorr		d30,d18,d20
+	vand		d29,d18,d20
+	veor		d17,d24,d25
+	vand		d30,d19
+	veor		d17,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d17,d27
+	vadd.i64	d21,d27
+	vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 15
+#if 15<16
+	vld1.64		{d15},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+	vshr.u64	d26,d21,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d21,#50
+	vsli.64		d25,d21,#46
+	vsli.64		d26,d21,#23
+#if 15<16 && defined(__ARMEL__)
+	vrev64.8	d15,d15
+#endif
+	vadd.i64	d27,d28,d16
+	veor		d29,d22,d23
+	veor		d24,d25
+	vand		d29,d21
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d23			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d17,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d17,#34
+	vshr.u64	d26,d17,#39
+	vsli.64		d24,d17,#36
+	vsli.64		d25,d17,#30
+	vsli.64		d26,d17,#25
+	vadd.i64	d27,d15
+	vorr		d30,d17,d19
+	vand		d29,d17,d19
+	veor		d16,d24,d25
+	vand		d30,d18
+	veor		d16,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d16,d27
+	vadd.i64	d20,d27
+	vadd.i64	d16,d30
+	mov		r12,#4
+.L16_79_neon:
+	subs		r12,#1
+	vshr.u64	q12,q7,#19
+	vshr.u64	q13,q7,#61
+	vshr.u64	q15,q7,#6
+	vsli.64		q12,q7,#45
+	vext.8		q14,q0,q1,#8	@ X[i+1]
+	vsli.64		q13,q7,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q0,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q4,q5,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d20,#14		@ from NEON_00_15
+	vadd.i64	q0,q14
+	vshr.u64	d25,d20,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d20,#41		@ from NEON_00_15
+	vadd.i64	q0,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d20,#50
+	vsli.64		d25,d20,#46
+	vsli.64		d26,d20,#23
+#if 16<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d23
+	veor		d29,d21,d22
+	veor		d24,d25
+	vand		d29,d20
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d22			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d16,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d16,#34
+	vshr.u64	d26,d16,#39
+	vsli.64		d24,d16,#36
+	vsli.64		d25,d16,#30
+	vsli.64		d26,d16,#25
+	vadd.i64	d27,d0
+	vorr		d30,d16,d18
+	vand		d29,d16,d18
+	veor		d23,d24,d25
+	vand		d30,d17
+	veor		d23,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d23,d27
+	vadd.i64	d19,d27
+	vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 17
+#if 17<16
+	vld1.64		{d1},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+	vshr.u64	d26,d19,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d19,#50
+	vsli.64		d25,d19,#46
+	vsli.64		d26,d19,#23
+#if 17<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d22
+	veor		d29,d20,d21
+	veor		d24,d25
+	vand		d29,d19
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d21			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d23,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d23,#34
+	vshr.u64	d26,d23,#39
+	vsli.64		d24,d23,#36
+	vsli.64		d25,d23,#30
+	vsli.64		d26,d23,#25
+	vadd.i64	d27,d1
+	vorr		d30,d23,d17
+	vand		d29,d23,d17
+	veor		d22,d24,d25
+	vand		d30,d16
+	veor		d22,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d22,d27
+	vadd.i64	d18,d27
+	vadd.i64	d22,d30
+	vshr.u64	q12,q0,#19
+	vshr.u64	q13,q0,#61
+	vshr.u64	q15,q0,#6
+	vsli.64		q12,q0,#45
+	vext.8		q14,q1,q2,#8	@ X[i+1]
+	vsli.64		q13,q0,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q1,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q5,q6,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d18,#14		@ from NEON_00_15
+	vadd.i64	q1,q14
+	vshr.u64	d25,d18,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d18,#41		@ from NEON_00_15
+	vadd.i64	q1,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d18,#50
+	vsli.64		d25,d18,#46
+	vsli.64		d26,d18,#23
+#if 18<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d21
+	veor		d29,d19,d20
+	veor		d24,d25
+	vand		d29,d18
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d20			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d22,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d22,#34
+	vshr.u64	d26,d22,#39
+	vsli.64		d24,d22,#36
+	vsli.64		d25,d22,#30
+	vsli.64		d26,d22,#25
+	vadd.i64	d27,d2
+	vorr		d30,d22,d16
+	vand		d29,d22,d16
+	veor		d21,d24,d25
+	vand		d30,d23
+	veor		d21,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d21,d27
+	vadd.i64	d17,d27
+	vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 19
+#if 19<16
+	vld1.64		{d3},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+	vshr.u64	d26,d17,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d17,#50
+	vsli.64		d25,d17,#46
+	vsli.64		d26,d17,#23
+#if 19<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d20
+	veor		d29,d18,d19
+	veor		d24,d25
+	vand		d29,d17
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d19			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d21,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d21,#34
+	vshr.u64	d26,d21,#39
+	vsli.64		d24,d21,#36
+	vsli.64		d25,d21,#30
+	vsli.64		d26,d21,#25
+	vadd.i64	d27,d3
+	vorr		d30,d21,d23
+	vand		d29,d21,d23
+	veor		d20,d24,d25
+	vand		d30,d22
+	veor		d20,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d20,d27
+	vadd.i64	d16,d27
+	vadd.i64	d20,d30
+	vshr.u64	q12,q1,#19
+	vshr.u64	q13,q1,#61
+	vshr.u64	q15,q1,#6
+	vsli.64		q12,q1,#45
+	vext.8		q14,q2,q3,#8	@ X[i+1]
+	vsli.64		q13,q1,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q2,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q6,q7,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d16,#14		@ from NEON_00_15
+	vadd.i64	q2,q14
+	vshr.u64	d25,d16,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d16,#41		@ from NEON_00_15
+	vadd.i64	q2,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d16,#50
+	vsli.64		d25,d16,#46
+	vsli.64		d26,d16,#23
+#if 20<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d19
+	veor		d29,d17,d18
+	veor		d24,d25
+	vand		d29,d16
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d18			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d20,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d20,#34
+	vshr.u64	d26,d20,#39
+	vsli.64		d24,d20,#36
+	vsli.64		d25,d20,#30
+	vsli.64		d26,d20,#25
+	vadd.i64	d27,d4
+	vorr		d30,d20,d22
+	vand		d29,d20,d22
+	veor		d19,d24,d25
+	vand		d30,d21
+	veor		d19,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d19,d27
+	vadd.i64	d23,d27
+	vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 21
+#if 21<16
+	vld1.64		{d5},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+	vshr.u64	d26,d23,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d23,#50
+	vsli.64		d25,d23,#46
+	vsli.64		d26,d23,#23
+#if 21<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d18
+	veor		d29,d16,d17
+	veor		d24,d25
+	vand		d29,d23
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d17			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d19,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d19,#34
+	vshr.u64	d26,d19,#39
+	vsli.64		d24,d19,#36
+	vsli.64		d25,d19,#30
+	vsli.64		d26,d19,#25
+	vadd.i64	d27,d5
+	vorr		d30,d19,d21
+	vand		d29,d19,d21
+	veor		d18,d24,d25
+	vand		d30,d20
+	veor		d18,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d18,d27
+	vadd.i64	d22,d27
+	vadd.i64	d18,d30
+	vshr.u64	q12,q2,#19
+	vshr.u64	q13,q2,#61
+	vshr.u64	q15,q2,#6
+	vsli.64		q12,q2,#45
+	vext.8		q14,q3,q4,#8	@ X[i+1]
+	vsli.64		q13,q2,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q3,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q7,q0,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d22,#14		@ from NEON_00_15
+	vadd.i64	q3,q14
+	vshr.u64	d25,d22,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d22,#41		@ from NEON_00_15
+	vadd.i64	q3,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d22,#50
+	vsli.64		d25,d22,#46
+	vsli.64		d26,d22,#23
+#if 22<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d17
+	veor		d29,d23,d16
+	veor		d24,d25
+	vand		d29,d22
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d16			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d18,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d18,#34
+	vshr.u64	d26,d18,#39
+	vsli.64		d24,d18,#36
+	vsli.64		d25,d18,#30
+	vsli.64		d26,d18,#25
+	vadd.i64	d27,d6
+	vorr		d30,d18,d20
+	vand		d29,d18,d20
+	veor		d17,d24,d25
+	vand		d30,d19
+	veor		d17,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d17,d27
+	vadd.i64	d21,d27
+	vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 23
+#if 23<16
+	vld1.64		{d7},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+	vshr.u64	d26,d21,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d21,#50
+	vsli.64		d25,d21,#46
+	vsli.64		d26,d21,#23
+#if 23<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d16
+	veor		d29,d22,d23
+	veor		d24,d25
+	vand		d29,d21
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d23			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d17,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d17,#34
+	vshr.u64	d26,d17,#39
+	vsli.64		d24,d17,#36
+	vsli.64		d25,d17,#30
+	vsli.64		d26,d17,#25
+	vadd.i64	d27,d7
+	vorr		d30,d17,d19
+	vand		d29,d17,d19
+	veor		d16,d24,d25
+	vand		d30,d18
+	veor		d16,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d16,d27
+	vadd.i64	d20,d27
+	vadd.i64	d16,d30
+	vshr.u64	q12,q3,#19
+	vshr.u64	q13,q3,#61
+	vshr.u64	q15,q3,#6
+	vsli.64		q12,q3,#45
+	vext.8		q14,q4,q5,#8	@ X[i+1]
+	vsli.64		q13,q3,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q4,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q0,q1,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d20,#14		@ from NEON_00_15
+	vadd.i64	q4,q14
+	vshr.u64	d25,d20,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d20,#41		@ from NEON_00_15
+	vadd.i64	q4,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d20,#50
+	vsli.64		d25,d20,#46
+	vsli.64		d26,d20,#23
+#if 24<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d23
+	veor		d29,d21,d22
+	veor		d24,d25
+	vand		d29,d20
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d22			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d16,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d16,#34
+	vshr.u64	d26,d16,#39
+	vsli.64		d24,d16,#36
+	vsli.64		d25,d16,#30
+	vsli.64		d26,d16,#25
+	vadd.i64	d27,d8
+	vorr		d30,d16,d18
+	vand		d29,d16,d18
+	veor		d23,d24,d25
+	vand		d30,d17
+	veor		d23,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d23,d27
+	vadd.i64	d19,d27
+	vadd.i64	d23,d30
+	vshr.u64	d24,d19,#14	@ 25
+#if 25<16
+	vld1.64		{d9},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d19,#18
+	vshr.u64	d26,d19,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d19,#50
+	vsli.64		d25,d19,#46
+	vsli.64		d26,d19,#23
+#if 25<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d22
+	veor		d29,d20,d21
+	veor		d24,d25
+	vand		d29,d19
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d21			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d23,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d23,#34
+	vshr.u64	d26,d23,#39
+	vsli.64		d24,d23,#36
+	vsli.64		d25,d23,#30
+	vsli.64		d26,d23,#25
+	vadd.i64	d27,d9
+	vorr		d30,d23,d17
+	vand		d29,d23,d17
+	veor		d22,d24,d25
+	vand		d30,d16
+	veor		d22,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d22,d27
+	vadd.i64	d18,d27
+	vadd.i64	d22,d30
+	vshr.u64	q12,q4,#19
+	vshr.u64	q13,q4,#61
+	vshr.u64	q15,q4,#6
+	vsli.64		q12,q4,#45
+	vext.8		q14,q5,q6,#8	@ X[i+1]
+	vsli.64		q13,q4,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q5,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q1,q2,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d18,#14		@ from NEON_00_15
+	vadd.i64	q5,q14
+	vshr.u64	d25,d18,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d18,#41		@ from NEON_00_15
+	vadd.i64	q5,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d18,#50
+	vsli.64		d25,d18,#46
+	vsli.64		d26,d18,#23
+#if 26<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d21
+	veor		d29,d19,d20
+	veor		d24,d25
+	vand		d29,d18
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d20			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d22,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d22,#34
+	vshr.u64	d26,d22,#39
+	vsli.64		d24,d22,#36
+	vsli.64		d25,d22,#30
+	vsli.64		d26,d22,#25
+	vadd.i64	d27,d10
+	vorr		d30,d22,d16
+	vand		d29,d22,d16
+	veor		d21,d24,d25
+	vand		d30,d23
+	veor		d21,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d21,d27
+	vadd.i64	d17,d27
+	vadd.i64	d21,d30
+	vshr.u64	d24,d17,#14	@ 27
+#if 27<16
+	vld1.64		{d11},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d17,#18
+	vshr.u64	d26,d17,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d17,#50
+	vsli.64		d25,d17,#46
+	vsli.64		d26,d17,#23
+#if 27<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d20
+	veor		d29,d18,d19
+	veor		d24,d25
+	vand		d29,d17
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d19			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d21,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d21,#34
+	vshr.u64	d26,d21,#39
+	vsli.64		d24,d21,#36
+	vsli.64		d25,d21,#30
+	vsli.64		d26,d21,#25
+	vadd.i64	d27,d11
+	vorr		d30,d21,d23
+	vand		d29,d21,d23
+	veor		d20,d24,d25
+	vand		d30,d22
+	veor		d20,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d20,d27
+	vadd.i64	d16,d27
+	vadd.i64	d20,d30
+	vshr.u64	q12,q5,#19
+	vshr.u64	q13,q5,#61
+	vshr.u64	q15,q5,#6
+	vsli.64		q12,q5,#45
+	vext.8		q14,q6,q7,#8	@ X[i+1]
+	vsli.64		q13,q5,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q6,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q2,q3,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d16,#14		@ from NEON_00_15
+	vadd.i64	q6,q14
+	vshr.u64	d25,d16,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d16,#41		@ from NEON_00_15
+	vadd.i64	q6,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d16,#50
+	vsli.64		d25,d16,#46
+	vsli.64		d26,d16,#23
+#if 28<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d19
+	veor		d29,d17,d18
+	veor		d24,d25
+	vand		d29,d16
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d18			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d20,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d20,#34
+	vshr.u64	d26,d20,#39
+	vsli.64		d24,d20,#36
+	vsli.64		d25,d20,#30
+	vsli.64		d26,d20,#25
+	vadd.i64	d27,d12
+	vorr		d30,d20,d22
+	vand		d29,d20,d22
+	veor		d19,d24,d25
+	vand		d30,d21
+	veor		d19,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d19,d27
+	vadd.i64	d23,d27
+	vadd.i64	d19,d30
+	vshr.u64	d24,d23,#14	@ 29
+#if 29<16
+	vld1.64		{d13},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d23,#18
+	vshr.u64	d26,d23,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d23,#50
+	vsli.64		d25,d23,#46
+	vsli.64		d26,d23,#23
+#if 29<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d18
+	veor		d29,d16,d17
+	veor		d24,d25
+	vand		d29,d23
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d17			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d19,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d19,#34
+	vshr.u64	d26,d19,#39
+	vsli.64		d24,d19,#36
+	vsli.64		d25,d19,#30
+	vsli.64		d26,d19,#25
+	vadd.i64	d27,d13
+	vorr		d30,d19,d21
+	vand		d29,d19,d21
+	veor		d18,d24,d25
+	vand		d30,d20
+	veor		d18,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d18,d27
+	vadd.i64	d22,d27
+	vadd.i64	d18,d30
+	vshr.u64	q12,q6,#19
+	vshr.u64	q13,q6,#61
+	vshr.u64	q15,q6,#6
+	vsli.64		q12,q6,#45
+	vext.8		q14,q7,q0,#8	@ X[i+1]
+	vsli.64		q13,q6,#3
+	veor		q15,q12
+	vshr.u64	q12,q14,#1
+	veor		q15,q13				@ sigma1(X[i+14])
+	vshr.u64	q13,q14,#8
+	vadd.i64	q7,q15
+	vshr.u64	q15,q14,#7
+	vsli.64		q12,q14,#63
+	vsli.64		q13,q14,#56
+	vext.8		q14,q3,q4,#8	@ X[i+9]
+	veor		q15,q12
+	vshr.u64	d24,d22,#14		@ from NEON_00_15
+	vadd.i64	q7,q14
+	vshr.u64	d25,d22,#18		@ from NEON_00_15
+	veor		q15,q13				@ sigma0(X[i+1])
+	vshr.u64	d26,d22,#41		@ from NEON_00_15
+	vadd.i64	q7,q15
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d22,#50
+	vsli.64		d25,d22,#46
+	vsli.64		d26,d22,#23
+#if 30<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d17
+	veor		d29,d23,d16
+	veor		d24,d25
+	vand		d29,d22
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d16			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d18,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d18,#34
+	vshr.u64	d26,d18,#39
+	vsli.64		d24,d18,#36
+	vsli.64		d25,d18,#30
+	vsli.64		d26,d18,#25
+	vadd.i64	d27,d14
+	vorr		d30,d18,d20
+	vand		d29,d18,d20
+	veor		d17,d24,d25
+	vand		d30,d19
+	veor		d17,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d17,d27
+	vadd.i64	d21,d27
+	vadd.i64	d17,d30
+	vshr.u64	d24,d21,#14	@ 31
+#if 31<16
+	vld1.64		{d15},[r1]!	@ handles unaligned
+#endif
+	vshr.u64	d25,d21,#18
+	vshr.u64	d26,d21,#41
+	vld1.64		{d28},[r3,:64]!	@ K[i++]
+	vsli.64		d24,d21,#50
+	vsli.64		d25,d21,#46
+	vsli.64		d26,d21,#23
+#if 31<16 && defined(__ARMEL__)
+	vrev64.8	,
+#endif
+	vadd.i64	d27,d28,d16
+	veor		d29,d22,d23
+	veor		d24,d25
+	vand		d29,d21
+	veor		d24,d26			@ Sigma1(e)
+	veor		d29,d23			@ Ch(e,f,g)
+	vadd.i64	d27,d24
+	vshr.u64	d24,d17,#28
+	vadd.i64	d27,d29
+	vshr.u64	d25,d17,#34
+	vshr.u64	d26,d17,#39
+	vsli.64		d24,d17,#36
+	vsli.64		d25,d17,#30
+	vsli.64		d26,d17,#25
+	vadd.i64	d27,d15
+	vorr		d30,d17,d19
+	vand		d29,d17,d19
+	veor		d16,d24,d25
+	vand		d30,d18
+	veor		d16,d26			@ Sigma0(a)
+	vorr		d30,d29		@ Maj(a,b,c)
+	vadd.i64	d16,d27
+	vadd.i64	d20,d27
+	vadd.i64	d16,d30
+	bne		.L16_79_neon
+
+	vldmia		r0,{d24-d31}	@ load context to temp
+	vadd.i64	q8,q12		@ vectorized accumulate
+	vadd.i64	q9,q13
+	vadd.i64	q10,q14
+	vadd.i64	q11,q15
+	vstmia		r0,{d16-d23}	@ save context
+	teq		r1,r2
+	sub		r3,#640	@ rewind K512
+	bne		.Loop_neon
+
+	vldmia	sp!,{d8-d15}		@ epilogue
+	.word	0xe12fff1e
+#endif
+.size	sha512_block_data_order,.-sha512_block_data_order
+.asciz	"SHA512 block transform for ARMv4/NEON, CRYPTOGAMS by "
+.align	2
+.comm	OPENSSL_armcap_P,4,4
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha512-elf-x86_64.S b/crypto/sha/sha512-elf-x86_64.S
new file mode 100644
index 0000000..0581c7c
--- /dev/null
+++ b/crypto/sha/sha512-elf-x86_64.S
@@ -0,0 +1,1809 @@
+#include "x86_arch.h"
+.text	
+
+.globl	sha512_block_data_order
+.type	sha512_block_data_order,@function
+.align	16
+sha512_block_data_order:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$128+32,%rsp
+	leaq	(%rsi,%rdx,8),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,128+0(%rsp)
+	movq	%rsi,128+8(%rsp)
+	movq	%rdx,128+16(%rsp)
+	movq	%r11,128+24(%rsp)
+.Lprologue:
+
+	leaq	K512(%rip),%rbp
+
+	movq	0(%rdi),%rax
+	movq	8(%rdi),%rbx
+	movq	16(%rdi),%rcx
+	movq	24(%rdi),%rdx
+	movq	32(%rdi),%r8
+	movq	40(%rdi),%r9
+	movq	48(%rdi),%r10
+	movq	56(%rdi),%r11
+	jmp	.Lloop
+
+.align	16
+.Lloop:
+	xorq	%rdi,%rdi
+	movq	0(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	8(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	16(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	24(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	32(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	40(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	48(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	56(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	64(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	72(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	80(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	88(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	96(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	104(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	112(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	120(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	jmp	.Lrounds_16_xx
+.align	16
+.Lrounds_16_xx:
+	movq	8(%rsp),%r13
+	movq	112(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	72(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	0(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	16(%rsp),%r13
+	movq	120(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	80(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	8(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	24(%rsp),%r13
+	movq	0(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	88(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	16(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	32(%rsp),%r13
+	movq	8(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	96(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	24(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	40(%rsp),%r13
+	movq	16(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	104(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	32(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	48(%rsp),%r13
+	movq	24(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	112(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	40(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	56(%rsp),%r13
+	movq	32(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	120(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	48(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	64(%rsp),%r13
+	movq	40(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	0(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	56(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	72(%rsp),%r13
+	movq	48(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	8(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	64(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	80(%rsp),%r13
+	movq	56(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	16(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	72(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	88(%rsp),%r13
+	movq	64(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	24(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	80(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	96(%rsp),%r13
+	movq	72(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	32(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	88(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	104(%rsp),%r13
+	movq	80(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	40(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	96(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	112(%rsp),%r13
+	movq	88(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	48(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	104(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	120(%rsp),%r13
+	movq	96(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	56(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	112(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	0(%rsp),%r13
+	movq	104(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	64(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	120(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	cmpq	$80,%rdi
+	jb	.Lrounds_16_xx
+
+	movq	128+0(%rsp),%rdi
+	leaq	128(%rsi),%rsi
+
+	addq	0(%rdi),%rax
+	addq	8(%rdi),%rbx
+	addq	16(%rdi),%rcx
+	addq	24(%rdi),%rdx
+	addq	32(%rdi),%r8
+	addq	40(%rdi),%r9
+	addq	48(%rdi),%r10
+	addq	56(%rdi),%r11
+
+	cmpq	128+16(%rsp),%rsi
+
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+	movq	%r8,32(%rdi)
+	movq	%r9,40(%rdi)
+	movq	%r10,48(%rdi)
+	movq	%r11,56(%rdi)
+	jb	.Lloop
+
+	movq	128+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	retq
+.size	sha512_block_data_order,.-sha512_block_data_order
+.section	.rodata
+.align	64
+.type	K512,@object
+K512:
+.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad	0x3956c25bf348b538,0x59f111f1b605d019
+.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad	0xd807aa98a3030242,0x12835b0145706fbe
+.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad	0x06ca6351e003826f,0x142929670a0e6e70
+.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad	0x81c2c92e47edaee6,0x92722c851482353b
+.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad	0xd192e819d6ef5218,0xd69906245565a910
+.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad	0x90befffa23631e28,0xa4506cebde82bde9
+.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad	0xca273eceea26619c,0xd186b8c721c0c207
+.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad	0x113f9804bef90dae,0x1b710b35131c471b
+.quad	0x28db77f523047d84,0x32caab7b40c72493
+.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
+.text	
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha512-macosx-x86_64.S b/crypto/sha/sha512-macosx-x86_64.S
new file mode 100644
index 0000000..7581da4
--- /dev/null
+++ b/crypto/sha/sha512-macosx-x86_64.S
@@ -0,0 +1,1803 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_sha512_block_data_order
+
+.p2align	4
+_sha512_block_data_order:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$128+32,%rsp
+	leaq	(%rsi,%rdx,8),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,128+0(%rsp)
+	movq	%rsi,128+8(%rsp)
+	movq	%rdx,128+16(%rsp)
+	movq	%r11,128+24(%rsp)
+L$prologue:
+
+	leaq	K512(%rip),%rbp
+
+	movq	0(%rdi),%rax
+	movq	8(%rdi),%rbx
+	movq	16(%rdi),%rcx
+	movq	24(%rdi),%rdx
+	movq	32(%rdi),%r8
+	movq	40(%rdi),%r9
+	movq	48(%rdi),%r10
+	movq	56(%rdi),%r11
+	jmp	L$loop
+
+.p2align	4
+L$loop:
+	xorq	%rdi,%rdi
+	movq	0(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	8(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	16(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	24(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	32(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	40(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	48(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	56(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	64(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	72(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	80(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	88(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	96(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	104(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	112(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	120(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	jmp	L$rounds_16_xx
+.p2align	4
+L$rounds_16_xx:
+	movq	8(%rsp),%r13
+	movq	112(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	72(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	0(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	16(%rsp),%r13
+	movq	120(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	80(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	8(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	24(%rsp),%r13
+	movq	0(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	88(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	16(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	32(%rsp),%r13
+	movq	8(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	96(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	24(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	40(%rsp),%r13
+	movq	16(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	104(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	32(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	48(%rsp),%r13
+	movq	24(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	112(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	40(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	56(%rsp),%r13
+	movq	32(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	120(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	48(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	64(%rsp),%r13
+	movq	40(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	0(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	56(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	72(%rsp),%r13
+	movq	48(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	8(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	64(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	80(%rsp),%r13
+	movq	56(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	16(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	72(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	88(%rsp),%r13
+	movq	64(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	24(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	80(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	96(%rsp),%r13
+	movq	72(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	32(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	88(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	104(%rsp),%r13
+	movq	80(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	40(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	96(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	112(%rsp),%r13
+	movq	88(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	48(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	104(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	120(%rsp),%r13
+	movq	96(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	56(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	112(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	0(%rsp),%r13
+	movq	104(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	64(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	120(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	cmpq	$80,%rdi
+	jb	L$rounds_16_xx
+
+	movq	128+0(%rsp),%rdi
+	leaq	128(%rsi),%rsi
+
+	addq	0(%rdi),%rax
+	addq	8(%rdi),%rbx
+	addq	16(%rdi),%rcx
+	addq	24(%rdi),%rdx
+	addq	32(%rdi),%r8
+	addq	40(%rdi),%r9
+	addq	48(%rdi),%r10
+	addq	56(%rdi),%r11
+
+	cmpq	128+16(%rsp),%rsi
+
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+	movq	%r8,32(%rdi)
+	movq	%r9,40(%rdi)
+	movq	%r10,48(%rdi)
+	movq	%r11,56(%rdi)
+	jb	L$loop
+
+	movq	128+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$epilogue:
+	retq
+
+.p2align	6
+
+K512:
+.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad	0x3956c25bf348b538,0x59f111f1b605d019
+.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad	0xd807aa98a3030242,0x12835b0145706fbe
+.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad	0x06ca6351e003826f,0x142929670a0e6e70
+.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad	0x81c2c92e47edaee6,0x92722c851482353b
+.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad	0xd192e819d6ef5218,0xd69906245565a910
+.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad	0x90befffa23631e28,0xa4506cebde82bde9
+.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad	0xca273eceea26619c,0xd186b8c721c0c207
+.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad	0x113f9804bef90dae,0x1b710b35131c471b
+.quad	0x28db77f523047d84,0x32caab7b40c72493
+.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
diff --git a/crypto/sha/sha512-masm-x86_64.S b/crypto/sha/sha512-masm-x86_64.S
new file mode 100644
index 0000000..058b4b3
--- /dev/null
+++ b/crypto/sha/sha512-masm-x86_64.S
@@ -0,0 +1,1888 @@
+; 1 "crypto/sha/sha512-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/sha/sha512-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/sha/sha512-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	sha512_block_data_order
+
+ALIGN	16
+sha512_block_data_order	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_sha512_block_data_order::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	mov	r11,rsp
+	shl	rdx,4
+	sub	rsp,16*8+4*8
+	lea	rdx,QWORD PTR[rdx*8+rsi]
+	and	rsp,-64
+	mov	QWORD PTR[((128+0))+rsp],rdi
+	mov	QWORD PTR[((128+8))+rsp],rsi
+	mov	QWORD PTR[((128+16))+rsp],rdx
+	mov	QWORD PTR[((128+24))+rsp],r11
+$L$prologue::
+
+	lea	rbp,QWORD PTR[K512]
+
+	mov	rax,QWORD PTR[rdi]
+	mov	rbx,QWORD PTR[8+rdi]
+	mov	rcx,QWORD PTR[16+rdi]
+	mov	rdx,QWORD PTR[24+rdi]
+	mov	r8,QWORD PTR[32+rdi]
+	mov	r9,QWORD PTR[40+rdi]
+	mov	r10,QWORD PTR[48+rdi]
+	mov	r11,QWORD PTR[56+rdi]
+	jmp	$L$loop
+
+ALIGN	16
+$L$loop::
+	xor	rdi,rdi
+	mov	r12,QWORD PTR[rsi]
+	mov	r13,r8
+	mov	r14,rax
+	bswap	r12
+	ror	r13,23
+	mov	r15,r9
+	mov	QWORD PTR[rsp],r12
+
+	ror	r14,5
+	xor	r13,r8
+	xor	r15,r10
+
+	ror	r13,4
+	add	r12,r11
+	xor	r14,rax
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r8
+	mov	r11,rbx
+
+	ror	r14,6
+	xor	r13,r8
+	xor	r15,r10
+
+	xor	r11,rcx
+	xor	r14,rax
+	add	r12,r15
+	mov	r15,rbx
+
+	ror	r13,14
+	and	r11,rax
+	and	r15,rcx
+
+	ror	r14,28
+	add	r12,r13
+	add	r11,r15
+
+	add	rdx,r12
+	add	r11,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11,r14
+
+	mov	r12,QWORD PTR[8+rsi]
+	mov	r13,rdx
+	mov	r14,r11
+	bswap	r12
+	ror	r13,23
+	mov	r15,r8
+	mov	QWORD PTR[8+rsp],r12
+
+	ror	r14,5
+	xor	r13,rdx
+	xor	r15,r9
+
+	ror	r13,4
+	add	r12,r10
+	xor	r14,r11
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rdx
+	mov	r10,rax
+
+	ror	r14,6
+	xor	r13,rdx
+	xor	r15,r9
+
+	xor	r10,rbx
+	xor	r14,r11
+	add	r12,r15
+	mov	r15,rax
+
+	ror	r13,14
+	and	r10,r11
+	and	r15,rbx
+
+	ror	r14,28
+	add	r12,r13
+	add	r10,r15
+
+	add	rcx,r12
+	add	r10,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10,r14
+
+	mov	r12,QWORD PTR[16+rsi]
+	mov	r13,rcx
+	mov	r14,r10
+	bswap	r12
+	ror	r13,23
+	mov	r15,rdx
+	mov	QWORD PTR[16+rsp],r12
+
+	ror	r14,5
+	xor	r13,rcx
+	xor	r15,r8
+
+	ror	r13,4
+	add	r12,r9
+	xor	r14,r10
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rcx
+	mov	r9,r11
+
+	ror	r14,6
+	xor	r13,rcx
+	xor	r15,r8
+
+	xor	r9,rax
+	xor	r14,r10
+	add	r12,r15
+	mov	r15,r11
+
+	ror	r13,14
+	and	r9,r10
+	and	r15,rax
+
+	ror	r14,28
+	add	r12,r13
+	add	r9,r15
+
+	add	rbx,r12
+	add	r9,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9,r14
+
+	mov	r12,QWORD PTR[24+rsi]
+	mov	r13,rbx
+	mov	r14,r9
+	bswap	r12
+	ror	r13,23
+	mov	r15,rcx
+	mov	QWORD PTR[24+rsp],r12
+
+	ror	r14,5
+	xor	r13,rbx
+	xor	r15,rdx
+
+	ror	r13,4
+	add	r12,r8
+	xor	r14,r9
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rbx
+	mov	r8,r10
+
+	ror	r14,6
+	xor	r13,rbx
+	xor	r15,rdx
+
+	xor	r8,r11
+	xor	r14,r9
+	add	r12,r15
+	mov	r15,r10
+
+	ror	r13,14
+	and	r8,r9
+	and	r15,r11
+
+	ror	r14,28
+	add	r12,r13
+	add	r8,r15
+
+	add	rax,r12
+	add	r8,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8,r14
+
+	mov	r12,QWORD PTR[32+rsi]
+	mov	r13,rax
+	mov	r14,r8
+	bswap	r12
+	ror	r13,23
+	mov	r15,rbx
+	mov	QWORD PTR[32+rsp],r12
+
+	ror	r14,5
+	xor	r13,rax
+	xor	r15,rcx
+
+	ror	r13,4
+	add	r12,rdx
+	xor	r14,r8
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rax
+	mov	rdx,r9
+
+	ror	r14,6
+	xor	r13,rax
+	xor	r15,rcx
+
+	xor	rdx,r10
+	xor	r14,r8
+	add	r12,r15
+	mov	r15,r9
+
+	ror	r13,14
+	and	rdx,r8
+	and	r15,r10
+
+	ror	r14,28
+	add	r12,r13
+	add	rdx,r15
+
+	add	r11,r12
+	add	rdx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rdx,r14
+
+	mov	r12,QWORD PTR[40+rsi]
+	mov	r13,r11
+	mov	r14,rdx
+	bswap	r12
+	ror	r13,23
+	mov	r15,rax
+	mov	QWORD PTR[40+rsp],r12
+
+	ror	r14,5
+	xor	r13,r11
+	xor	r15,rbx
+
+	ror	r13,4
+	add	r12,rcx
+	xor	r14,rdx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r11
+	mov	rcx,r8
+
+	ror	r14,6
+	xor	r13,r11
+	xor	r15,rbx
+
+	xor	rcx,r9
+	xor	r14,rdx
+	add	r12,r15
+	mov	r15,r8
+
+	ror	r13,14
+	and	rcx,rdx
+	and	r15,r9
+
+	ror	r14,28
+	add	r12,r13
+	add	rcx,r15
+
+	add	r10,r12
+	add	rcx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rcx,r14
+
+	mov	r12,QWORD PTR[48+rsi]
+	mov	r13,r10
+	mov	r14,rcx
+	bswap	r12
+	ror	r13,23
+	mov	r15,r11
+	mov	QWORD PTR[48+rsp],r12
+
+	ror	r14,5
+	xor	r13,r10
+	xor	r15,rax
+
+	ror	r13,4
+	add	r12,rbx
+	xor	r14,rcx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r10
+	mov	rbx,rdx
+
+	ror	r14,6
+	xor	r13,r10
+	xor	r15,rax
+
+	xor	rbx,r8
+	xor	r14,rcx
+	add	r12,r15
+	mov	r15,rdx
+
+	ror	r13,14
+	and	rbx,rcx
+	and	r15,r8
+
+	ror	r14,28
+	add	r12,r13
+	add	rbx,r15
+
+	add	r9,r12
+	add	rbx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rbx,r14
+
+	mov	r12,QWORD PTR[56+rsi]
+	mov	r13,r9
+	mov	r14,rbx
+	bswap	r12
+	ror	r13,23
+	mov	r15,r10
+	mov	QWORD PTR[56+rsp],r12
+
+	ror	r14,5
+	xor	r13,r9
+	xor	r15,r11
+
+	ror	r13,4
+	add	r12,rax
+	xor	r14,rbx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r9
+	mov	rax,rcx
+
+	ror	r14,6
+	xor	r13,r9
+	xor	r15,r11
+
+	xor	rax,rdx
+	xor	r14,rbx
+	add	r12,r15
+	mov	r15,rcx
+
+	ror	r13,14
+	and	rax,rbx
+	and	r15,rdx
+
+	ror	r14,28
+	add	r12,r13
+	add	rax,r15
+
+	add	r8,r12
+	add	rax,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rax,r14
+
+	mov	r12,QWORD PTR[64+rsi]
+	mov	r13,r8
+	mov	r14,rax
+	bswap	r12
+	ror	r13,23
+	mov	r15,r9
+	mov	QWORD PTR[64+rsp],r12
+
+	ror	r14,5
+	xor	r13,r8
+	xor	r15,r10
+
+	ror	r13,4
+	add	r12,r11
+	xor	r14,rax
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r8
+	mov	r11,rbx
+
+	ror	r14,6
+	xor	r13,r8
+	xor	r15,r10
+
+	xor	r11,rcx
+	xor	r14,rax
+	add	r12,r15
+	mov	r15,rbx
+
+	ror	r13,14
+	and	r11,rax
+	and	r15,rcx
+
+	ror	r14,28
+	add	r12,r13
+	add	r11,r15
+
+	add	rdx,r12
+	add	r11,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11,r14
+
+	mov	r12,QWORD PTR[72+rsi]
+	mov	r13,rdx
+	mov	r14,r11
+	bswap	r12
+	ror	r13,23
+	mov	r15,r8
+	mov	QWORD PTR[72+rsp],r12
+
+	ror	r14,5
+	xor	r13,rdx
+	xor	r15,r9
+
+	ror	r13,4
+	add	r12,r10
+	xor	r14,r11
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rdx
+	mov	r10,rax
+
+	ror	r14,6
+	xor	r13,rdx
+	xor	r15,r9
+
+	xor	r10,rbx
+	xor	r14,r11
+	add	r12,r15
+	mov	r15,rax
+
+	ror	r13,14
+	and	r10,r11
+	and	r15,rbx
+
+	ror	r14,28
+	add	r12,r13
+	add	r10,r15
+
+	add	rcx,r12
+	add	r10,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10,r14
+
+	mov	r12,QWORD PTR[80+rsi]
+	mov	r13,rcx
+	mov	r14,r10
+	bswap	r12
+	ror	r13,23
+	mov	r15,rdx
+	mov	QWORD PTR[80+rsp],r12
+
+	ror	r14,5
+	xor	r13,rcx
+	xor	r15,r8
+
+	ror	r13,4
+	add	r12,r9
+	xor	r14,r10
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rcx
+	mov	r9,r11
+
+	ror	r14,6
+	xor	r13,rcx
+	xor	r15,r8
+
+	xor	r9,rax
+	xor	r14,r10
+	add	r12,r15
+	mov	r15,r11
+
+	ror	r13,14
+	and	r9,r10
+	and	r15,rax
+
+	ror	r14,28
+	add	r12,r13
+	add	r9,r15
+
+	add	rbx,r12
+	add	r9,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9,r14
+
+	mov	r12,QWORD PTR[88+rsi]
+	mov	r13,rbx
+	mov	r14,r9
+	bswap	r12
+	ror	r13,23
+	mov	r15,rcx
+	mov	QWORD PTR[88+rsp],r12
+
+	ror	r14,5
+	xor	r13,rbx
+	xor	r15,rdx
+
+	ror	r13,4
+	add	r12,r8
+	xor	r14,r9
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rbx
+	mov	r8,r10
+
+	ror	r14,6
+	xor	r13,rbx
+	xor	r15,rdx
+
+	xor	r8,r11
+	xor	r14,r9
+	add	r12,r15
+	mov	r15,r10
+
+	ror	r13,14
+	and	r8,r9
+	and	r15,r11
+
+	ror	r14,28
+	add	r12,r13
+	add	r8,r15
+
+	add	rax,r12
+	add	r8,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8,r14
+
+	mov	r12,QWORD PTR[96+rsi]
+	mov	r13,rax
+	mov	r14,r8
+	bswap	r12
+	ror	r13,23
+	mov	r15,rbx
+	mov	QWORD PTR[96+rsp],r12
+
+	ror	r14,5
+	xor	r13,rax
+	xor	r15,rcx
+
+	ror	r13,4
+	add	r12,rdx
+	xor	r14,r8
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rax
+	mov	rdx,r9
+
+	ror	r14,6
+	xor	r13,rax
+	xor	r15,rcx
+
+	xor	rdx,r10
+	xor	r14,r8
+	add	r12,r15
+	mov	r15,r9
+
+	ror	r13,14
+	and	rdx,r8
+	and	r15,r10
+
+	ror	r14,28
+	add	r12,r13
+	add	rdx,r15
+
+	add	r11,r12
+	add	rdx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rdx,r14
+
+	mov	r12,QWORD PTR[104+rsi]
+	mov	r13,r11
+	mov	r14,rdx
+	bswap	r12
+	ror	r13,23
+	mov	r15,rax
+	mov	QWORD PTR[104+rsp],r12
+
+	ror	r14,5
+	xor	r13,r11
+	xor	r15,rbx
+
+	ror	r13,4
+	add	r12,rcx
+	xor	r14,rdx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r11
+	mov	rcx,r8
+
+	ror	r14,6
+	xor	r13,r11
+	xor	r15,rbx
+
+	xor	rcx,r9
+	xor	r14,rdx
+	add	r12,r15
+	mov	r15,r8
+
+	ror	r13,14
+	and	rcx,rdx
+	and	r15,r9
+
+	ror	r14,28
+	add	r12,r13
+	add	rcx,r15
+
+	add	r10,r12
+	add	rcx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rcx,r14
+
+	mov	r12,QWORD PTR[112+rsi]
+	mov	r13,r10
+	mov	r14,rcx
+	bswap	r12
+	ror	r13,23
+	mov	r15,r11
+	mov	QWORD PTR[112+rsp],r12
+
+	ror	r14,5
+	xor	r13,r10
+	xor	r15,rax
+
+	ror	r13,4
+	add	r12,rbx
+	xor	r14,rcx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r10
+	mov	rbx,rdx
+
+	ror	r14,6
+	xor	r13,r10
+	xor	r15,rax
+
+	xor	rbx,r8
+	xor	r14,rcx
+	add	r12,r15
+	mov	r15,rdx
+
+	ror	r13,14
+	and	rbx,rcx
+	and	r15,r8
+
+	ror	r14,28
+	add	r12,r13
+	add	rbx,r15
+
+	add	r9,r12
+	add	rbx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rbx,r14
+
+	mov	r12,QWORD PTR[120+rsi]
+	mov	r13,r9
+	mov	r14,rbx
+	bswap	r12
+	ror	r13,23
+	mov	r15,r10
+	mov	QWORD PTR[120+rsp],r12
+
+	ror	r14,5
+	xor	r13,r9
+	xor	r15,r11
+
+	ror	r13,4
+	add	r12,rax
+	xor	r14,rbx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r9
+	mov	rax,rcx
+
+	ror	r14,6
+	xor	r13,r9
+	xor	r15,r11
+
+	xor	rax,rdx
+	xor	r14,rbx
+	add	r12,r15
+	mov	r15,rcx
+
+	ror	r13,14
+	and	rax,rbx
+	and	r15,rdx
+
+	ror	r14,28
+	add	r12,r13
+	add	rax,r15
+
+	add	r8,r12
+	add	rax,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rax,r14
+
+	jmp	$L$rounds_16_xx
+ALIGN	16
+$L$rounds_16_xx::
+	mov	r13,QWORD PTR[8+rsp]
+	mov	r14,QWORD PTR[112+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[72+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[rsp]
+	mov	r13,r8
+	add	r12,r14
+	mov	r14,rax
+	ror	r13,23
+	mov	r15,r9
+	mov	QWORD PTR[rsp],r12
+
+	ror	r14,5
+	xor	r13,r8
+	xor	r15,r10
+
+	ror	r13,4
+	add	r12,r11
+	xor	r14,rax
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r8
+	mov	r11,rbx
+
+	ror	r14,6
+	xor	r13,r8
+	xor	r15,r10
+
+	xor	r11,rcx
+	xor	r14,rax
+	add	r12,r15
+	mov	r15,rbx
+
+	ror	r13,14
+	and	r11,rax
+	and	r15,rcx
+
+	ror	r14,28
+	add	r12,r13
+	add	r11,r15
+
+	add	rdx,r12
+	add	r11,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11,r14
+
+	mov	r13,QWORD PTR[16+rsp]
+	mov	r14,QWORD PTR[120+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[80+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[8+rsp]
+	mov	r13,rdx
+	add	r12,r14
+	mov	r14,r11
+	ror	r13,23
+	mov	r15,r8
+	mov	QWORD PTR[8+rsp],r12
+
+	ror	r14,5
+	xor	r13,rdx
+	xor	r15,r9
+
+	ror	r13,4
+	add	r12,r10
+	xor	r14,r11
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rdx
+	mov	r10,rax
+
+	ror	r14,6
+	xor	r13,rdx
+	xor	r15,r9
+
+	xor	r10,rbx
+	xor	r14,r11
+	add	r12,r15
+	mov	r15,rax
+
+	ror	r13,14
+	and	r10,r11
+	and	r15,rbx
+
+	ror	r14,28
+	add	r12,r13
+	add	r10,r15
+
+	add	rcx,r12
+	add	r10,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10,r14
+
+	mov	r13,QWORD PTR[24+rsp]
+	mov	r14,QWORD PTR[rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[88+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[16+rsp]
+	mov	r13,rcx
+	add	r12,r14
+	mov	r14,r10
+	ror	r13,23
+	mov	r15,rdx
+	mov	QWORD PTR[16+rsp],r12
+
+	ror	r14,5
+	xor	r13,rcx
+	xor	r15,r8
+
+	ror	r13,4
+	add	r12,r9
+	xor	r14,r10
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rcx
+	mov	r9,r11
+
+	ror	r14,6
+	xor	r13,rcx
+	xor	r15,r8
+
+	xor	r9,rax
+	xor	r14,r10
+	add	r12,r15
+	mov	r15,r11
+
+	ror	r13,14
+	and	r9,r10
+	and	r15,rax
+
+	ror	r14,28
+	add	r12,r13
+	add	r9,r15
+
+	add	rbx,r12
+	add	r9,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9,r14
+
+	mov	r13,QWORD PTR[32+rsp]
+	mov	r14,QWORD PTR[8+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[96+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[24+rsp]
+	mov	r13,rbx
+	add	r12,r14
+	mov	r14,r9
+	ror	r13,23
+	mov	r15,rcx
+	mov	QWORD PTR[24+rsp],r12
+
+	ror	r14,5
+	xor	r13,rbx
+	xor	r15,rdx
+
+	ror	r13,4
+	add	r12,r8
+	xor	r14,r9
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rbx
+	mov	r8,r10
+
+	ror	r14,6
+	xor	r13,rbx
+	xor	r15,rdx
+
+	xor	r8,r11
+	xor	r14,r9
+	add	r12,r15
+	mov	r15,r10
+
+	ror	r13,14
+	and	r8,r9
+	and	r15,r11
+
+	ror	r14,28
+	add	r12,r13
+	add	r8,r15
+
+	add	rax,r12
+	add	r8,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8,r14
+
+	mov	r13,QWORD PTR[40+rsp]
+	mov	r14,QWORD PTR[16+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[104+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[32+rsp]
+	mov	r13,rax
+	add	r12,r14
+	mov	r14,r8
+	ror	r13,23
+	mov	r15,rbx
+	mov	QWORD PTR[32+rsp],r12
+
+	ror	r14,5
+	xor	r13,rax
+	xor	r15,rcx
+
+	ror	r13,4
+	add	r12,rdx
+	xor	r14,r8
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rax
+	mov	rdx,r9
+
+	ror	r14,6
+	xor	r13,rax
+	xor	r15,rcx
+
+	xor	rdx,r10
+	xor	r14,r8
+	add	r12,r15
+	mov	r15,r9
+
+	ror	r13,14
+	and	rdx,r8
+	and	r15,r10
+
+	ror	r14,28
+	add	r12,r13
+	add	rdx,r15
+
+	add	r11,r12
+	add	rdx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rdx,r14
+
+	mov	r13,QWORD PTR[48+rsp]
+	mov	r14,QWORD PTR[24+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[112+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[40+rsp]
+	mov	r13,r11
+	add	r12,r14
+	mov	r14,rdx
+	ror	r13,23
+	mov	r15,rax
+	mov	QWORD PTR[40+rsp],r12
+
+	ror	r14,5
+	xor	r13,r11
+	xor	r15,rbx
+
+	ror	r13,4
+	add	r12,rcx
+	xor	r14,rdx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r11
+	mov	rcx,r8
+
+	ror	r14,6
+	xor	r13,r11
+	xor	r15,rbx
+
+	xor	rcx,r9
+	xor	r14,rdx
+	add	r12,r15
+	mov	r15,r8
+
+	ror	r13,14
+	and	rcx,rdx
+	and	r15,r9
+
+	ror	r14,28
+	add	r12,r13
+	add	rcx,r15
+
+	add	r10,r12
+	add	rcx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rcx,r14
+
+	mov	r13,QWORD PTR[56+rsp]
+	mov	r14,QWORD PTR[32+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[120+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[48+rsp]
+	mov	r13,r10
+	add	r12,r14
+	mov	r14,rcx
+	ror	r13,23
+	mov	r15,r11
+	mov	QWORD PTR[48+rsp],r12
+
+	ror	r14,5
+	xor	r13,r10
+	xor	r15,rax
+
+	ror	r13,4
+	add	r12,rbx
+	xor	r14,rcx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r10
+	mov	rbx,rdx
+
+	ror	r14,6
+	xor	r13,r10
+	xor	r15,rax
+
+	xor	rbx,r8
+	xor	r14,rcx
+	add	r12,r15
+	mov	r15,rdx
+
+	ror	r13,14
+	and	rbx,rcx
+	and	r15,r8
+
+	ror	r14,28
+	add	r12,r13
+	add	rbx,r15
+
+	add	r9,r12
+	add	rbx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rbx,r14
+
+	mov	r13,QWORD PTR[64+rsp]
+	mov	r14,QWORD PTR[40+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[56+rsp]
+	mov	r13,r9
+	add	r12,r14
+	mov	r14,rbx
+	ror	r13,23
+	mov	r15,r10
+	mov	QWORD PTR[56+rsp],r12
+
+	ror	r14,5
+	xor	r13,r9
+	xor	r15,r11
+
+	ror	r13,4
+	add	r12,rax
+	xor	r14,rbx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r9
+	mov	rax,rcx
+
+	ror	r14,6
+	xor	r13,r9
+	xor	r15,r11
+
+	xor	rax,rdx
+	xor	r14,rbx
+	add	r12,r15
+	mov	r15,rcx
+
+	ror	r13,14
+	and	rax,rbx
+	and	r15,rdx
+
+	ror	r14,28
+	add	r12,r13
+	add	rax,r15
+
+	add	r8,r12
+	add	rax,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rax,r14
+
+	mov	r13,QWORD PTR[72+rsp]
+	mov	r14,QWORD PTR[48+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[8+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[64+rsp]
+	mov	r13,r8
+	add	r12,r14
+	mov	r14,rax
+	ror	r13,23
+	mov	r15,r9
+	mov	QWORD PTR[64+rsp],r12
+
+	ror	r14,5
+	xor	r13,r8
+	xor	r15,r10
+
+	ror	r13,4
+	add	r12,r11
+	xor	r14,rax
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r8
+	mov	r11,rbx
+
+	ror	r14,6
+	xor	r13,r8
+	xor	r15,r10
+
+	xor	r11,rcx
+	xor	r14,rax
+	add	r12,r15
+	mov	r15,rbx
+
+	ror	r13,14
+	and	r11,rax
+	and	r15,rcx
+
+	ror	r14,28
+	add	r12,r13
+	add	r11,r15
+
+	add	rdx,r12
+	add	r11,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r11,r14
+
+	mov	r13,QWORD PTR[80+rsp]
+	mov	r14,QWORD PTR[56+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[16+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[72+rsp]
+	mov	r13,rdx
+	add	r12,r14
+	mov	r14,r11
+	ror	r13,23
+	mov	r15,r8
+	mov	QWORD PTR[72+rsp],r12
+
+	ror	r14,5
+	xor	r13,rdx
+	xor	r15,r9
+
+	ror	r13,4
+	add	r12,r10
+	xor	r14,r11
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rdx
+	mov	r10,rax
+
+	ror	r14,6
+	xor	r13,rdx
+	xor	r15,r9
+
+	xor	r10,rbx
+	xor	r14,r11
+	add	r12,r15
+	mov	r15,rax
+
+	ror	r13,14
+	and	r10,r11
+	and	r15,rbx
+
+	ror	r14,28
+	add	r12,r13
+	add	r10,r15
+
+	add	rcx,r12
+	add	r10,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r10,r14
+
+	mov	r13,QWORD PTR[88+rsp]
+	mov	r14,QWORD PTR[64+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[24+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[80+rsp]
+	mov	r13,rcx
+	add	r12,r14
+	mov	r14,r10
+	ror	r13,23
+	mov	r15,rdx
+	mov	QWORD PTR[80+rsp],r12
+
+	ror	r14,5
+	xor	r13,rcx
+	xor	r15,r8
+
+	ror	r13,4
+	add	r12,r9
+	xor	r14,r10
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rcx
+	mov	r9,r11
+
+	ror	r14,6
+	xor	r13,rcx
+	xor	r15,r8
+
+	xor	r9,rax
+	xor	r14,r10
+	add	r12,r15
+	mov	r15,r11
+
+	ror	r13,14
+	and	r9,r10
+	and	r15,rax
+
+	ror	r14,28
+	add	r12,r13
+	add	r9,r15
+
+	add	rbx,r12
+	add	r9,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r9,r14
+
+	mov	r13,QWORD PTR[96+rsp]
+	mov	r14,QWORD PTR[72+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[32+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[88+rsp]
+	mov	r13,rbx
+	add	r12,r14
+	mov	r14,r9
+	ror	r13,23
+	mov	r15,rcx
+	mov	QWORD PTR[88+rsp],r12
+
+	ror	r14,5
+	xor	r13,rbx
+	xor	r15,rdx
+
+	ror	r13,4
+	add	r12,r8
+	xor	r14,r9
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rbx
+	mov	r8,r10
+
+	ror	r14,6
+	xor	r13,rbx
+	xor	r15,rdx
+
+	xor	r8,r11
+	xor	r14,r9
+	add	r12,r15
+	mov	r15,r10
+
+	ror	r13,14
+	and	r8,r9
+	and	r15,r11
+
+	ror	r14,28
+	add	r12,r13
+	add	r8,r15
+
+	add	rax,r12
+	add	r8,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	r8,r14
+
+	mov	r13,QWORD PTR[104+rsp]
+	mov	r14,QWORD PTR[80+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[40+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[96+rsp]
+	mov	r13,rax
+	add	r12,r14
+	mov	r14,r8
+	ror	r13,23
+	mov	r15,rbx
+	mov	QWORD PTR[96+rsp],r12
+
+	ror	r14,5
+	xor	r13,rax
+	xor	r15,rcx
+
+	ror	r13,4
+	add	r12,rdx
+	xor	r14,r8
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,rax
+	mov	rdx,r9
+
+	ror	r14,6
+	xor	r13,rax
+	xor	r15,rcx
+
+	xor	rdx,r10
+	xor	r14,r8
+	add	r12,r15
+	mov	r15,r9
+
+	ror	r13,14
+	and	rdx,r8
+	and	r15,r10
+
+	ror	r14,28
+	add	r12,r13
+	add	rdx,r15
+
+	add	r11,r12
+	add	rdx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rdx,r14
+
+	mov	r13,QWORD PTR[112+rsp]
+	mov	r14,QWORD PTR[88+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[48+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[104+rsp]
+	mov	r13,r11
+	add	r12,r14
+	mov	r14,rdx
+	ror	r13,23
+	mov	r15,rax
+	mov	QWORD PTR[104+rsp],r12
+
+	ror	r14,5
+	xor	r13,r11
+	xor	r15,rbx
+
+	ror	r13,4
+	add	r12,rcx
+	xor	r14,rdx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r11
+	mov	rcx,r8
+
+	ror	r14,6
+	xor	r13,r11
+	xor	r15,rbx
+
+	xor	rcx,r9
+	xor	r14,rdx
+	add	r12,r15
+	mov	r15,r8
+
+	ror	r13,14
+	and	rcx,rdx
+	and	r15,r9
+
+	ror	r14,28
+	add	r12,r13
+	add	rcx,r15
+
+	add	r10,r12
+	add	rcx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rcx,r14
+
+	mov	r13,QWORD PTR[120+rsp]
+	mov	r14,QWORD PTR[96+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[56+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[112+rsp]
+	mov	r13,r10
+	add	r12,r14
+	mov	r14,rcx
+	ror	r13,23
+	mov	r15,r11
+	mov	QWORD PTR[112+rsp],r12
+
+	ror	r14,5
+	xor	r13,r10
+	xor	r15,rax
+
+	ror	r13,4
+	add	r12,rbx
+	xor	r14,rcx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r10
+	mov	rbx,rdx
+
+	ror	r14,6
+	xor	r13,r10
+	xor	r15,rax
+
+	xor	rbx,r8
+	xor	r14,rcx
+	add	r12,r15
+	mov	r15,rdx
+
+	ror	r13,14
+	and	rbx,rcx
+	and	r15,r8
+
+	ror	r14,28
+	add	r12,r13
+	add	rbx,r15
+
+	add	r9,r12
+	add	rbx,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rbx,r14
+
+	mov	r13,QWORD PTR[rsp]
+	mov	r14,QWORD PTR[104+rsp]
+	mov	r12,r13
+	mov	r15,r14
+
+	ror	r12,7
+	xor	r12,r13
+	shr	r13,7
+
+	ror	r12,1
+	xor	r13,r12
+	mov	r12,QWORD PTR[64+rsp]
+
+	ror	r15,42
+	xor	r15,r14
+	shr	r14,6
+
+	ror	r15,19
+	add	r12,r13
+	xor	r14,r15
+
+	add	r12,QWORD PTR[120+rsp]
+	mov	r13,r9
+	add	r12,r14
+	mov	r14,rbx
+	ror	r13,23
+	mov	r15,r10
+	mov	QWORD PTR[120+rsp],r12
+
+	ror	r14,5
+	xor	r13,r9
+	xor	r15,r11
+
+	ror	r13,4
+	add	r12,rax
+	xor	r14,rbx
+
+	add	r12,QWORD PTR[rdi*8+rbp]
+	and	r15,r9
+	mov	rax,rcx
+
+	ror	r14,6
+	xor	r13,r9
+	xor	r15,r11
+
+	xor	rax,rdx
+	xor	r14,rbx
+	add	r12,r15
+	mov	r15,rcx
+
+	ror	r13,14
+	and	rax,rbx
+	and	r15,rdx
+
+	ror	r14,28
+	add	r12,r13
+	add	rax,r15
+
+	add	r8,r12
+	add	rax,r12
+	lea	rdi,QWORD PTR[1+rdi]
+	add	rax,r14
+
+	cmp	rdi,80
+	jb	$L$rounds_16_xx
+
+	mov	rdi,QWORD PTR[((128+0))+rsp]
+	lea	rsi,QWORD PTR[128+rsi]
+
+	add	rax,QWORD PTR[rdi]
+	add	rbx,QWORD PTR[8+rdi]
+	add	rcx,QWORD PTR[16+rdi]
+	add	rdx,QWORD PTR[24+rdi]
+	add	r8,QWORD PTR[32+rdi]
+	add	r9,QWORD PTR[40+rdi]
+	add	r10,QWORD PTR[48+rdi]
+	add	r11,QWORD PTR[56+rdi]
+
+	cmp	rsi,QWORD PTR[((128+16))+rsp]
+
+	mov	QWORD PTR[rdi],rax
+	mov	QWORD PTR[8+rdi],rbx
+	mov	QWORD PTR[16+rdi],rcx
+	mov	QWORD PTR[24+rdi],rdx
+	mov	QWORD PTR[32+rdi],r8
+	mov	QWORD PTR[40+rdi],r9
+	mov	QWORD PTR[48+rdi],r10
+	mov	QWORD PTR[56+rdi],r11
+	jb	$L$loop
+
+	mov	rsi,QWORD PTR[((128+24))+rsp]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_sha512_block_data_order::
+sha512_block_data_order	ENDP
+ALIGN	64
+
+K512::
+	DQ	0428a2f98d728ae22h,07137449123ef65cdh
+	DQ	0b5c0fbcfec4d3b2fh,0e9b5dba58189dbbch
+	DQ	03956c25bf348b538h,059f111f1b605d019h
+	DQ	0923f82a4af194f9bh,0ab1c5ed5da6d8118h
+	DQ	0d807aa98a3030242h,012835b0145706fbeh
+	DQ	0243185be4ee4b28ch,0550c7dc3d5ffb4e2h
+	DQ	072be5d74f27b896fh,080deb1fe3b1696b1h
+	DQ	09bdc06a725c71235h,0c19bf174cf692694h
+	DQ	0e49b69c19ef14ad2h,0efbe4786384f25e3h
+	DQ	00fc19dc68b8cd5b5h,0240ca1cc77ac9c65h
+	DQ	02de92c6f592b0275h,04a7484aa6ea6e483h
+	DQ	05cb0a9dcbd41fbd4h,076f988da831153b5h
+	DQ	0983e5152ee66dfabh,0a831c66d2db43210h
+	DQ	0b00327c898fb213fh,0bf597fc7beef0ee4h
+	DQ	0c6e00bf33da88fc2h,0d5a79147930aa725h
+	DQ	006ca6351e003826fh,0142929670a0e6e70h
+	DQ	027b70a8546d22ffch,02e1b21385c26c926h
+	DQ	04d2c6dfc5ac42aedh,053380d139d95b3dfh
+	DQ	0650a73548baf63deh,0766a0abb3c77b2a8h
+	DQ	081c2c92e47edaee6h,092722c851482353bh
+	DQ	0a2bfe8a14cf10364h,0a81a664bbc423001h
+	DQ	0c24b8b70d0f89791h,0c76c51a30654be30h
+	DQ	0d192e819d6ef5218h,0d69906245565a910h
+	DQ	0f40e35855771202ah,0106aa07032bbd1b8h
+	DQ	019a4c116b8d2d0c8h,01e376c085141ab53h
+	DQ	02748774cdf8eeb99h,034b0bcb5e19b48a8h
+	DQ	0391c0cb3c5c95a63h,04ed8aa4ae3418acbh
+	DQ	05b9cca4f7763e373h,0682e6ff3d6b2b8a3h
+	DQ	0748f82ee5defb2fch,078a5636f43172f60h
+	DQ	084c87814a1f0ab72h,08cc702081a6439ech
+	DQ	090befffa23631e28h,0a4506cebde82bde9h
+	DQ	0bef9a3f7b2c67915h,0c67178f2e372532bh
+	DQ	0ca273eceea26619ch,0d186b8c721c0c207h
+	DQ	0eada7dd6cde0eb1eh,0f57d4f7fee6ed178h
+	DQ	006f067aa72176fbah,00a637dc5a2c898a6h
+	DQ	0113f9804bef90daeh,01b710b35131c471bh
+	DQ	028db77f523047d84h,032caab7b40c72493h
+	DQ	03c9ebe0a15c9bebch,0431d67c49c100d4ch
+	DQ	04cc5d4becb3e42b6h,0597f299cfc657e2ah
+	DQ	05fcb6fab3ad6faech,06c44198c4a475817h
+
+.text$	ENDS
+END
+
diff --git a/crypto/sha/sha512-mingw64-x86_64.S b/crypto/sha/sha512-mingw64-x86_64.S
new file mode 100644
index 0000000..5153952
--- /dev/null
+++ b/crypto/sha/sha512-mingw64-x86_64.S
@@ -0,0 +1,1814 @@
+#include "x86_arch.h"
+.text	
+
+.globl	sha512_block_data_order
+.def	sha512_block_data_order;	.scl 2;	.type 32;	.endef
+.p2align	4
+sha512_block_data_order:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_sha512_block_data_order:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+	movq	%r9,%rcx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	movq	%rsp,%r11
+	shlq	$4,%rdx
+	subq	$128+32,%rsp
+	leaq	(%rsi,%rdx,8),%rdx
+	andq	$-64,%rsp
+	movq	%rdi,128+0(%rsp)
+	movq	%rsi,128+8(%rsp)
+	movq	%rdx,128+16(%rsp)
+	movq	%r11,128+24(%rsp)
+.Lprologue:
+
+	leaq	K512(%rip),%rbp
+
+	movq	0(%rdi),%rax
+	movq	8(%rdi),%rbx
+	movq	16(%rdi),%rcx
+	movq	24(%rdi),%rdx
+	movq	32(%rdi),%r8
+	movq	40(%rdi),%r9
+	movq	48(%rdi),%r10
+	movq	56(%rdi),%r11
+	jmp	.Lloop
+
+.p2align	4
+.Lloop:
+	xorq	%rdi,%rdi
+	movq	0(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	8(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	16(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	24(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	32(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	40(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	48(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	56(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	64(%rsi),%r12
+	movq	%r8,%r13
+	movq	%rax,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	72(%rsi),%r12
+	movq	%rdx,%r13
+	movq	%r11,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	80(%rsi),%r12
+	movq	%rcx,%r13
+	movq	%r10,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	88(%rsi),%r12
+	movq	%rbx,%r13
+	movq	%r9,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	96(%rsi),%r12
+	movq	%rax,%r13
+	movq	%r8,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	104(%rsi),%r12
+	movq	%r11,%r13
+	movq	%rdx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	112(%rsi),%r12
+	movq	%r10,%r13
+	movq	%rcx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	120(%rsi),%r12
+	movq	%r9,%r13
+	movq	%rbx,%r14
+	bswapq	%r12
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	jmp	.Lrounds_16_xx
+.p2align	4
+.Lrounds_16_xx:
+	movq	8(%rsp),%r13
+	movq	112(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	72(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	0(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,0(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	16(%rsp),%r13
+	movq	120(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	80(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	8(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,8(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	24(%rsp),%r13
+	movq	0(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	88(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	16(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,16(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	32(%rsp),%r13
+	movq	8(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	96(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	24(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,24(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	40(%rsp),%r13
+	movq	16(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	104(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	32(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,32(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	48(%rsp),%r13
+	movq	24(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	112(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	40(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,40(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	56(%rsp),%r13
+	movq	32(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	120(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	48(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,48(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	64(%rsp),%r13
+	movq	40(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	0(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	56(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,56(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	movq	72(%rsp),%r13
+	movq	48(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	8(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	64(%rsp),%r12
+	movq	%r8,%r13
+	addq	%r14,%r12
+	movq	%rax,%r14
+	rorq	$23,%r13
+	movq	%r9,%r15
+	movq	%r12,64(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	rorq	$4,%r13
+	addq	%r11,%r12
+	xorq	%rax,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r8,%r15
+	movq	%rbx,%r11
+
+	rorq	$6,%r14
+	xorq	%r8,%r13
+	xorq	%r10,%r15
+
+	xorq	%rcx,%r11
+	xorq	%rax,%r14
+	addq	%r15,%r12
+	movq	%rbx,%r15
+
+	rorq	$14,%r13
+	andq	%rax,%r11
+	andq	%rcx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r11
+
+	addq	%r12,%rdx
+	addq	%r12,%r11
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r11
+
+	movq	80(%rsp),%r13
+	movq	56(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	16(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	72(%rsp),%r12
+	movq	%rdx,%r13
+	addq	%r14,%r12
+	movq	%r11,%r14
+	rorq	$23,%r13
+	movq	%r8,%r15
+	movq	%r12,72(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	rorq	$4,%r13
+	addq	%r10,%r12
+	xorq	%r11,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rdx,%r15
+	movq	%rax,%r10
+
+	rorq	$6,%r14
+	xorq	%rdx,%r13
+	xorq	%r9,%r15
+
+	xorq	%rbx,%r10
+	xorq	%r11,%r14
+	addq	%r15,%r12
+	movq	%rax,%r15
+
+	rorq	$14,%r13
+	andq	%r11,%r10
+	andq	%rbx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r10
+
+	addq	%r12,%rcx
+	addq	%r12,%r10
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r10
+
+	movq	88(%rsp),%r13
+	movq	64(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	24(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	80(%rsp),%r12
+	movq	%rcx,%r13
+	addq	%r14,%r12
+	movq	%r10,%r14
+	rorq	$23,%r13
+	movq	%rdx,%r15
+	movq	%r12,80(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	rorq	$4,%r13
+	addq	%r9,%r12
+	xorq	%r10,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rcx,%r15
+	movq	%r11,%r9
+
+	rorq	$6,%r14
+	xorq	%rcx,%r13
+	xorq	%r8,%r15
+
+	xorq	%rax,%r9
+	xorq	%r10,%r14
+	addq	%r15,%r12
+	movq	%r11,%r15
+
+	rorq	$14,%r13
+	andq	%r10,%r9
+	andq	%rax,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r9
+
+	addq	%r12,%rbx
+	addq	%r12,%r9
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r9
+
+	movq	96(%rsp),%r13
+	movq	72(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	32(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	88(%rsp),%r12
+	movq	%rbx,%r13
+	addq	%r14,%r12
+	movq	%r9,%r14
+	rorq	$23,%r13
+	movq	%rcx,%r15
+	movq	%r12,88(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	rorq	$4,%r13
+	addq	%r8,%r12
+	xorq	%r9,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rbx,%r15
+	movq	%r10,%r8
+
+	rorq	$6,%r14
+	xorq	%rbx,%r13
+	xorq	%rdx,%r15
+
+	xorq	%r11,%r8
+	xorq	%r9,%r14
+	addq	%r15,%r12
+	movq	%r10,%r15
+
+	rorq	$14,%r13
+	andq	%r9,%r8
+	andq	%r11,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%r8
+
+	addq	%r12,%rax
+	addq	%r12,%r8
+	leaq	1(%rdi),%rdi
+	addq	%r14,%r8
+
+	movq	104(%rsp),%r13
+	movq	80(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	40(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	96(%rsp),%r12
+	movq	%rax,%r13
+	addq	%r14,%r12
+	movq	%r8,%r14
+	rorq	$23,%r13
+	movq	%rbx,%r15
+	movq	%r12,96(%rsp)
+
+	rorq	$5,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	rorq	$4,%r13
+	addq	%rdx,%r12
+	xorq	%r8,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%rax,%r15
+	movq	%r9,%rdx
+
+	rorq	$6,%r14
+	xorq	%rax,%r13
+	xorq	%rcx,%r15
+
+	xorq	%r10,%rdx
+	xorq	%r8,%r14
+	addq	%r15,%r12
+	movq	%r9,%r15
+
+	rorq	$14,%r13
+	andq	%r8,%rdx
+	andq	%r10,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rdx
+
+	addq	%r12,%r11
+	addq	%r12,%rdx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rdx
+
+	movq	112(%rsp),%r13
+	movq	88(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	48(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	104(%rsp),%r12
+	movq	%r11,%r13
+	addq	%r14,%r12
+	movq	%rdx,%r14
+	rorq	$23,%r13
+	movq	%rax,%r15
+	movq	%r12,104(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	rorq	$4,%r13
+	addq	%rcx,%r12
+	xorq	%rdx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r11,%r15
+	movq	%r8,%rcx
+
+	rorq	$6,%r14
+	xorq	%r11,%r13
+	xorq	%rbx,%r15
+
+	xorq	%r9,%rcx
+	xorq	%rdx,%r14
+	addq	%r15,%r12
+	movq	%r8,%r15
+
+	rorq	$14,%r13
+	andq	%rdx,%rcx
+	andq	%r9,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rcx
+
+	addq	%r12,%r10
+	addq	%r12,%rcx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rcx
+
+	movq	120(%rsp),%r13
+	movq	96(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	56(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	112(%rsp),%r12
+	movq	%r10,%r13
+	addq	%r14,%r12
+	movq	%rcx,%r14
+	rorq	$23,%r13
+	movq	%r11,%r15
+	movq	%r12,112(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	rorq	$4,%r13
+	addq	%rbx,%r12
+	xorq	%rcx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r10,%r15
+	movq	%rdx,%rbx
+
+	rorq	$6,%r14
+	xorq	%r10,%r13
+	xorq	%rax,%r15
+
+	xorq	%r8,%rbx
+	xorq	%rcx,%r14
+	addq	%r15,%r12
+	movq	%rdx,%r15
+
+	rorq	$14,%r13
+	andq	%rcx,%rbx
+	andq	%r8,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rbx
+
+	addq	%r12,%r9
+	addq	%r12,%rbx
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rbx
+
+	movq	0(%rsp),%r13
+	movq	104(%rsp),%r14
+	movq	%r13,%r12
+	movq	%r14,%r15
+
+	rorq	$7,%r12
+	xorq	%r13,%r12
+	shrq	$7,%r13
+
+	rorq	$1,%r12
+	xorq	%r12,%r13
+	movq	64(%rsp),%r12
+
+	rorq	$42,%r15
+	xorq	%r14,%r15
+	shrq	$6,%r14
+
+	rorq	$19,%r15
+	addq	%r13,%r12
+	xorq	%r15,%r14
+
+	addq	120(%rsp),%r12
+	movq	%r9,%r13
+	addq	%r14,%r12
+	movq	%rbx,%r14
+	rorq	$23,%r13
+	movq	%r10,%r15
+	movq	%r12,120(%rsp)
+
+	rorq	$5,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	rorq	$4,%r13
+	addq	%rax,%r12
+	xorq	%rbx,%r14
+
+	addq	(%rbp,%rdi,8),%r12
+	andq	%r9,%r15
+	movq	%rcx,%rax
+
+	rorq	$6,%r14
+	xorq	%r9,%r13
+	xorq	%r11,%r15
+
+	xorq	%rdx,%rax
+	xorq	%rbx,%r14
+	addq	%r15,%r12
+	movq	%rcx,%r15
+
+	rorq	$14,%r13
+	andq	%rbx,%rax
+	andq	%rdx,%r15
+
+	rorq	$28,%r14
+	addq	%r13,%r12
+	addq	%r15,%rax
+
+	addq	%r12,%r8
+	addq	%r12,%rax
+	leaq	1(%rdi),%rdi
+	addq	%r14,%rax
+
+	cmpq	$80,%rdi
+	jb	.Lrounds_16_xx
+
+	movq	128+0(%rsp),%rdi
+	leaq	128(%rsi),%rsi
+
+	addq	0(%rdi),%rax
+	addq	8(%rdi),%rbx
+	addq	16(%rdi),%rcx
+	addq	24(%rdi),%rdx
+	addq	32(%rdi),%r8
+	addq	40(%rdi),%r9
+	addq	48(%rdi),%r10
+	addq	56(%rdi),%r11
+
+	cmpq	128+16(%rsp),%rsi
+
+	movq	%rax,0(%rdi)
+	movq	%rbx,8(%rdi)
+	movq	%rcx,16(%rdi)
+	movq	%rdx,24(%rdi)
+	movq	%r8,32(%rdi)
+	movq	%r9,40(%rdi)
+	movq	%r10,48(%rdi)
+	movq	%r11,56(%rdi)
+	jb	.Lloop
+
+	movq	128+24(%rsp),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_sha512_block_data_order:
+.p2align	6
+
+K512:
+.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+.quad	0x3956c25bf348b538,0x59f111f1b605d019
+.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+.quad	0xd807aa98a3030242,0x12835b0145706fbe
+.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+.quad	0x06ca6351e003826f,0x142929670a0e6e70
+.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+.quad	0x81c2c92e47edaee6,0x92722c851482353b
+.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+.quad	0xd192e819d6ef5218,0xd69906245565a910
+.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+.quad	0x90befffa23631e28,0xa4506cebde82bde9
+.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+.quad	0xca273eceea26619c,0xd186b8c721c0c207
+.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+.quad	0x113f9804bef90dae,0x1b710b35131c471b
+.quad	0x28db77f523047d84,0x32caab7b40c72493
+.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
diff --git a/crypto/sha/sha512-mips.S b/crypto/sha/sha512-mips.S
new file mode 100644
index 0000000..da903b6
--- /dev/null
+++ b/crypto/sha/sha512-mips.S
@@ -0,0 +1,2165 @@
+.text
+.set	noat
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+
+.align	5
+.globl	sha512_block_data_order
+.ent	sha512_block_data_order
+sha512_block_data_order:
+	.frame	$29,192,$31
+	.mask	3237937152,-4
+	.set	noreorder
+	.cpload	$25
+	sub $29,192
+	sw	$31,192-1*4($29)
+	sw	$30,192-2*4($29)
+	sw	$23,192-3*4($29)
+	sw	$22,192-4*4($29)
+	sw	$21,192-5*4($29)
+	sw	$20,192-6*4($29)
+	sw	$19,192-7*4($29)
+	sw	$18,192-8*4($29)
+	sw	$17,192-9*4($29)
+	sw	$16,192-10*4($29)
+	sll $23,$6,7
+	.set	reorder
+	la	$6,K512		# PIC-ified 'load address'
+
+	ld	$1,0*8($4)		# load context
+	ld	$2,1*8($4)
+	ld	$3,2*8($4)
+	ld	$7,3*8($4)
+	ld	$24,4*8($4)
+	ld	$25,5*8($4)
+	ld	$30,6*8($4)
+	ld	$31,7*8($4)
+
+	add $23,$5		# pointer to the end of input
+	sw	$23,16*8($29)
+	b	.Loop
+
+.align	5
+.Loop:
+	ldl	$8,7($5)
+	ldr	$8,0($5)
+	ldl	$9,15($5)
+	ldr	$9,8($5)
+	ori	$13,$0,0xFF
+	dsll	$15,$13,32
+	or	$13,$15		# 0x000000FF000000FF
+	and	$14,$8,$13	# byte swap(0)
+	dsrl	$15,$8,24
+	dsll	$14,24
+	and	$15,$13
+	dsll	$13,8			# 0x0000FF000000FF00
+	or	$14,$15
+	and	$15,$8,$13
+	dsrl	$8,8
+	dsll	$15,8
+	and	$8,$13
+	or	$14,$15
+	or	$8,$14
+	dsrl	$14,$8,32
+	dsll	$8,32
+	or	$8,$14
+	daddu	$12,$8,$31			# 0
+	dsrl	$31,$24,14
+	xor	$15,$25,$30
+	dsll	$14,$24,23
+	and	$15,$24
+	dsrl	$13,$24,18
+	xor	$31,$14
+	dsll	$14,$24,46
+	xor	$31,$13
+	dsrl	$13,$24,41
+	xor	$31,$14
+	dsll	$14,$24,50
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$12,$15
+	ld	$15,0($6)		# K[0]
+	dsll	$14,$1,25
+	daddu	$12,$13
+	dsrl	$13,$1,34
+	xor	$31,$14
+	dsll	$14,$1,30
+	xor	$31,$13
+	dsrl	$13,$1,39
+	xor	$31,$14
+	dsll	$14,$1,36
+	xor	$31,$13
+	sd	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	daddu	$12,$15			# +=K[0]
+	daddu	$31,$14
+
+	daddu	$7,$12
+	daddu	$31,$12
+	ldl	$10,23($5)
+	ldr	$10,16($5)
+	ori	$14,$0,0xFF
+	dsll	$16,$14,32
+	or	$14,$16		# 0x000000FF000000FF
+	and	$15,$9,$14	# byte swap(1)
+	dsrl	$16,$9,24
+	dsll	$15,24
+	and	$16,$14
+	dsll	$14,8			# 0x0000FF000000FF00
+	or	$15,$16
+	and	$16,$9,$14
+	dsrl	$9,8
+	dsll	$16,8
+	and	$9,$14
+	or	$15,$16
+	or	$9,$15
+	dsrl	$15,$9,32
+	dsll	$9,32
+	or	$9,$15
+	daddu	$13,$9,$30			# 1
+	dsrl	$30,$7,14
+	xor	$16,$24,$25
+	dsll	$15,$7,23
+	and	$16,$7
+	dsrl	$14,$7,18
+	xor	$30,$15
+	dsll	$15,$7,46
+	xor	$30,$14
+	dsrl	$14,$7,41
+	xor	$30,$15
+	dsll	$15,$7,50
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$13,$16
+	ld	$16,8($6)		# K[1]
+	dsll	$15,$31,25
+	daddu	$13,$14
+	dsrl	$14,$31,34
+	xor	$30,$15
+	dsll	$15,$31,30
+	xor	$30,$14
+	dsrl	$14,$31,39
+	xor	$30,$15
+	dsll	$15,$31,36
+	xor	$30,$14
+	sd	$9,8($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	daddu	$13,$16			# +=K[1]
+	daddu	$30,$15
+
+	daddu	$3,$13
+	daddu	$30,$13
+	ldl	$11,31($5)
+	ldr	$11,24($5)
+	ori	$15,$0,0xFF
+	dsll	$17,$15,32
+	or	$15,$17		# 0x000000FF000000FF
+	and	$16,$10,$15	# byte swap(2)
+	dsrl	$17,$10,24
+	dsll	$16,24
+	and	$17,$15
+	dsll	$15,8			# 0x0000FF000000FF00
+	or	$16,$17
+	and	$17,$10,$15
+	dsrl	$10,8
+	dsll	$17,8
+	and	$10,$15
+	or	$16,$17
+	or	$10,$16
+	dsrl	$16,$10,32
+	dsll	$10,32
+	or	$10,$16
+	daddu	$14,$10,$25			# 2
+	dsrl	$25,$3,14
+	xor	$17,$7,$24
+	dsll	$16,$3,23
+	and	$17,$3
+	dsrl	$15,$3,18
+	xor	$25,$16
+	dsll	$16,$3,46
+	xor	$25,$15
+	dsrl	$15,$3,41
+	xor	$25,$16
+	dsll	$16,$3,50
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$14,$17
+	ld	$17,16($6)		# K[2]
+	dsll	$16,$30,25
+	daddu	$14,$15
+	dsrl	$15,$30,34
+	xor	$25,$16
+	dsll	$16,$30,30
+	xor	$25,$15
+	dsrl	$15,$30,39
+	xor	$25,$16
+	dsll	$16,$30,36
+	xor	$25,$15
+	sd	$10,16($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	daddu	$14,$17			# +=K[2]
+	daddu	$25,$16
+
+	daddu	$2,$14
+	daddu	$25,$14
+	ldl	$12,39($5)
+	ldr	$12,32($5)
+	ori	$16,$0,0xFF
+	dsll	$18,$16,32
+	or	$16,$18		# 0x000000FF000000FF
+	and	$17,$11,$16	# byte swap(3)
+	dsrl	$18,$11,24
+	dsll	$17,24
+	and	$18,$16
+	dsll	$16,8			# 0x0000FF000000FF00
+	or	$17,$18
+	and	$18,$11,$16
+	dsrl	$11,8
+	dsll	$18,8
+	and	$11,$16
+	or	$17,$18
+	or	$11,$17
+	dsrl	$17,$11,32
+	dsll	$11,32
+	or	$11,$17
+	daddu	$15,$11,$24			# 3
+	dsrl	$24,$2,14
+	xor	$18,$3,$7
+	dsll	$17,$2,23
+	and	$18,$2
+	dsrl	$16,$2,18
+	xor	$24,$17
+	dsll	$17,$2,46
+	xor	$24,$16
+	dsrl	$16,$2,41
+	xor	$24,$17
+	dsll	$17,$2,50
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$15,$18
+	ld	$18,24($6)		# K[3]
+	dsll	$17,$25,25
+	daddu	$15,$16
+	dsrl	$16,$25,34
+	xor	$24,$17
+	dsll	$17,$25,30
+	xor	$24,$16
+	dsrl	$16,$25,39
+	xor	$24,$17
+	dsll	$17,$25,36
+	xor	$24,$16
+	sd	$11,24($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	daddu	$15,$18			# +=K[3]
+	daddu	$24,$17
+
+	daddu	$1,$15
+	daddu	$24,$15
+	ldl	$13,47($5)
+	ldr	$13,40($5)
+	ori	$17,$0,0xFF
+	dsll	$19,$17,32
+	or	$17,$19		# 0x000000FF000000FF
+	and	$18,$12,$17	# byte swap(4)
+	dsrl	$19,$12,24
+	dsll	$18,24
+	and	$19,$17
+	dsll	$17,8			# 0x0000FF000000FF00
+	or	$18,$19
+	and	$19,$12,$17
+	dsrl	$12,8
+	dsll	$19,8
+	and	$12,$17
+	or	$18,$19
+	or	$12,$18
+	dsrl	$18,$12,32
+	dsll	$12,32
+	or	$12,$18
+	daddu	$16,$12,$7			# 4
+	dsrl	$7,$1,14
+	xor	$19,$2,$3
+	dsll	$18,$1,23
+	and	$19,$1
+	dsrl	$17,$1,18
+	xor	$7,$18
+	dsll	$18,$1,46
+	xor	$7,$17
+	dsrl	$17,$1,41
+	xor	$7,$18
+	dsll	$18,$1,50
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$16,$19
+	ld	$19,32($6)		# K[4]
+	dsll	$18,$24,25
+	daddu	$16,$17
+	dsrl	$17,$24,34
+	xor	$7,$18
+	dsll	$18,$24,30
+	xor	$7,$17
+	dsrl	$17,$24,39
+	xor	$7,$18
+	dsll	$18,$24,36
+	xor	$7,$17
+	sd	$12,32($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	daddu	$16,$19			# +=K[4]
+	daddu	$7,$18
+
+	daddu	$31,$16
+	daddu	$7,$16
+	ldl	$14,55($5)
+	ldr	$14,48($5)
+	ori	$18,$0,0xFF
+	dsll	$20,$18,32
+	or	$18,$20		# 0x000000FF000000FF
+	and	$19,$13,$18	# byte swap(5)
+	dsrl	$20,$13,24
+	dsll	$19,24
+	and	$20,$18
+	dsll	$18,8			# 0x0000FF000000FF00
+	or	$19,$20
+	and	$20,$13,$18
+	dsrl	$13,8
+	dsll	$20,8
+	and	$13,$18
+	or	$19,$20
+	or	$13,$19
+	dsrl	$19,$13,32
+	dsll	$13,32
+	or	$13,$19
+	daddu	$17,$13,$3			# 5
+	dsrl	$3,$31,14
+	xor	$20,$1,$2
+	dsll	$19,$31,23
+	and	$20,$31
+	dsrl	$18,$31,18
+	xor	$3,$19
+	dsll	$19,$31,46
+	xor	$3,$18
+	dsrl	$18,$31,41
+	xor	$3,$19
+	dsll	$19,$31,50
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$17,$20
+	ld	$20,40($6)		# K[5]
+	dsll	$19,$7,25
+	daddu	$17,$18
+	dsrl	$18,$7,34
+	xor	$3,$19
+	dsll	$19,$7,30
+	xor	$3,$18
+	dsrl	$18,$7,39
+	xor	$3,$19
+	dsll	$19,$7,36
+	xor	$3,$18
+	sd	$13,40($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	daddu	$17,$20			# +=K[5]
+	daddu	$3,$19
+
+	daddu	$30,$17
+	daddu	$3,$17
+	ldl	$15,63($5)
+	ldr	$15,56($5)
+	ori	$19,$0,0xFF
+	dsll	$21,$19,32
+	or	$19,$21		# 0x000000FF000000FF
+	and	$20,$14,$19	# byte swap(6)
+	dsrl	$21,$14,24
+	dsll	$20,24
+	and	$21,$19
+	dsll	$19,8			# 0x0000FF000000FF00
+	or	$20,$21
+	and	$21,$14,$19
+	dsrl	$14,8
+	dsll	$21,8
+	and	$14,$19
+	or	$20,$21
+	or	$14,$20
+	dsrl	$20,$14,32
+	dsll	$14,32
+	or	$14,$20
+	daddu	$18,$14,$2			# 6
+	dsrl	$2,$30,14
+	xor	$21,$31,$1
+	dsll	$20,$30,23
+	and	$21,$30
+	dsrl	$19,$30,18
+	xor	$2,$20
+	dsll	$20,$30,46
+	xor	$2,$19
+	dsrl	$19,$30,41
+	xor	$2,$20
+	dsll	$20,$30,50
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$18,$21
+	ld	$21,48($6)		# K[6]
+	dsll	$20,$3,25
+	daddu	$18,$19
+	dsrl	$19,$3,34
+	xor	$2,$20
+	dsll	$20,$3,30
+	xor	$2,$19
+	dsrl	$19,$3,39
+	xor	$2,$20
+	dsll	$20,$3,36
+	xor	$2,$19
+	sd	$14,48($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	daddu	$18,$21			# +=K[6]
+	daddu	$2,$20
+
+	daddu	$25,$18
+	daddu	$2,$18
+	ldl	$16,71($5)
+	ldr	$16,64($5)
+	ori	$20,$0,0xFF
+	dsll	$22,$20,32
+	or	$20,$22		# 0x000000FF000000FF
+	and	$21,$15,$20	# byte swap(7)
+	dsrl	$22,$15,24
+	dsll	$21,24
+	and	$22,$20
+	dsll	$20,8			# 0x0000FF000000FF00
+	or	$21,$22
+	and	$22,$15,$20
+	dsrl	$15,8
+	dsll	$22,8
+	and	$15,$20
+	or	$21,$22
+	or	$15,$21
+	dsrl	$21,$15,32
+	dsll	$15,32
+	or	$15,$21
+	daddu	$19,$15,$1			# 7
+	dsrl	$1,$25,14
+	xor	$22,$30,$31
+	dsll	$21,$25,23
+	and	$22,$25
+	dsrl	$20,$25,18
+	xor	$1,$21
+	dsll	$21,$25,46
+	xor	$1,$20
+	dsrl	$20,$25,41
+	xor	$1,$21
+	dsll	$21,$25,50
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$19,$22
+	ld	$22,56($6)		# K[7]
+	dsll	$21,$2,25
+	daddu	$19,$20
+	dsrl	$20,$2,34
+	xor	$1,$21
+	dsll	$21,$2,30
+	xor	$1,$20
+	dsrl	$20,$2,39
+	xor	$1,$21
+	dsll	$21,$2,36
+	xor	$1,$20
+	sd	$15,56($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	daddu	$19,$22			# +=K[7]
+	daddu	$1,$21
+
+	daddu	$24,$19
+	daddu	$1,$19
+	ldl	$17,79($5)
+	ldr	$17,72($5)
+	ori	$21,$0,0xFF
+	dsll	$23,$21,32
+	or	$21,$23		# 0x000000FF000000FF
+	and	$22,$16,$21	# byte swap(8)
+	dsrl	$23,$16,24
+	dsll	$22,24
+	and	$23,$21
+	dsll	$21,8			# 0x0000FF000000FF00
+	or	$22,$23
+	and	$23,$16,$21
+	dsrl	$16,8
+	dsll	$23,8
+	and	$16,$21
+	or	$22,$23
+	or	$16,$22
+	dsrl	$22,$16,32
+	dsll	$16,32
+	or	$16,$22
+	daddu	$20,$16,$31			# 8
+	dsrl	$31,$24,14
+	xor	$23,$25,$30
+	dsll	$22,$24,23
+	and	$23,$24
+	dsrl	$21,$24,18
+	xor	$31,$22
+	dsll	$22,$24,46
+	xor	$31,$21
+	dsrl	$21,$24,41
+	xor	$31,$22
+	dsll	$22,$24,50
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$20,$23
+	ld	$23,64($6)		# K[8]
+	dsll	$22,$1,25
+	daddu	$20,$21
+	dsrl	$21,$1,34
+	xor	$31,$22
+	dsll	$22,$1,30
+	xor	$31,$21
+	dsrl	$21,$1,39
+	xor	$31,$22
+	dsll	$22,$1,36
+	xor	$31,$21
+	sd	$16,64($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	daddu	$20,$23			# +=K[8]
+	daddu	$31,$22
+
+	daddu	$7,$20
+	daddu	$31,$20
+	ldl	$18,87($5)
+	ldr	$18,80($5)
+	ori	$22,$0,0xFF
+	dsll	$8,$22,32
+	or	$22,$8		# 0x000000FF000000FF
+	and	$23,$17,$22	# byte swap(9)
+	dsrl	$8,$17,24
+	dsll	$23,24
+	and	$8,$22
+	dsll	$22,8			# 0x0000FF000000FF00
+	or	$23,$8
+	and	$8,$17,$22
+	dsrl	$17,8
+	dsll	$8,8
+	and	$17,$22
+	or	$23,$8
+	or	$17,$23
+	dsrl	$23,$17,32
+	dsll	$17,32
+	or	$17,$23
+	daddu	$21,$17,$30			# 9
+	dsrl	$30,$7,14
+	xor	$8,$24,$25
+	dsll	$23,$7,23
+	and	$8,$7
+	dsrl	$22,$7,18
+	xor	$30,$23
+	dsll	$23,$7,46
+	xor	$30,$22
+	dsrl	$22,$7,41
+	xor	$30,$23
+	dsll	$23,$7,50
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$21,$8
+	ld	$8,72($6)		# K[9]
+	dsll	$23,$31,25
+	daddu	$21,$22
+	dsrl	$22,$31,34
+	xor	$30,$23
+	dsll	$23,$31,30
+	xor	$30,$22
+	dsrl	$22,$31,39
+	xor	$30,$23
+	dsll	$23,$31,36
+	xor	$30,$22
+	sd	$17,72($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	daddu	$21,$8			# +=K[9]
+	daddu	$30,$23
+
+	daddu	$3,$21
+	daddu	$30,$21
+	ldl	$19,95($5)
+	ldr	$19,88($5)
+	ori	$23,$0,0xFF
+	dsll	$9,$23,32
+	or	$23,$9		# 0x000000FF000000FF
+	and	$8,$18,$23	# byte swap(10)
+	dsrl	$9,$18,24
+	dsll	$8,24
+	and	$9,$23
+	dsll	$23,8			# 0x0000FF000000FF00
+	or	$8,$9
+	and	$9,$18,$23
+	dsrl	$18,8
+	dsll	$9,8
+	and	$18,$23
+	or	$8,$9
+	or	$18,$8
+	dsrl	$8,$18,32
+	dsll	$18,32
+	or	$18,$8
+	daddu	$22,$18,$25			# 10
+	dsrl	$25,$3,14
+	xor	$9,$7,$24
+	dsll	$8,$3,23
+	and	$9,$3
+	dsrl	$23,$3,18
+	xor	$25,$8
+	dsll	$8,$3,46
+	xor	$25,$23
+	dsrl	$23,$3,41
+	xor	$25,$8
+	dsll	$8,$3,50
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$22,$9
+	ld	$9,80($6)		# K[10]
+	dsll	$8,$30,25
+	daddu	$22,$23
+	dsrl	$23,$30,34
+	xor	$25,$8
+	dsll	$8,$30,30
+	xor	$25,$23
+	dsrl	$23,$30,39
+	xor	$25,$8
+	dsll	$8,$30,36
+	xor	$25,$23
+	sd	$18,80($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	daddu	$22,$9			# +=K[10]
+	daddu	$25,$8
+
+	daddu	$2,$22
+	daddu	$25,$22
+	ldl	$20,103($5)
+	ldr	$20,96($5)
+	ori	$8,$0,0xFF
+	dsll	$10,$8,32
+	or	$8,$10		# 0x000000FF000000FF
+	and	$9,$19,$8	# byte swap(11)
+	dsrl	$10,$19,24
+	dsll	$9,24
+	and	$10,$8
+	dsll	$8,8			# 0x0000FF000000FF00
+	or	$9,$10
+	and	$10,$19,$8
+	dsrl	$19,8
+	dsll	$10,8
+	and	$19,$8
+	or	$9,$10
+	or	$19,$9
+	dsrl	$9,$19,32
+	dsll	$19,32
+	or	$19,$9
+	daddu	$23,$19,$24			# 11
+	dsrl	$24,$2,14
+	xor	$10,$3,$7
+	dsll	$9,$2,23
+	and	$10,$2
+	dsrl	$8,$2,18
+	xor	$24,$9
+	dsll	$9,$2,46
+	xor	$24,$8
+	dsrl	$8,$2,41
+	xor	$24,$9
+	dsll	$9,$2,50
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$23,$10
+	ld	$10,88($6)		# K[11]
+	dsll	$9,$25,25
+	daddu	$23,$8
+	dsrl	$8,$25,34
+	xor	$24,$9
+	dsll	$9,$25,30
+	xor	$24,$8
+	dsrl	$8,$25,39
+	xor	$24,$9
+	dsll	$9,$25,36
+	xor	$24,$8
+	sd	$19,88($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	daddu	$23,$10			# +=K[11]
+	daddu	$24,$9
+
+	daddu	$1,$23
+	daddu	$24,$23
+	ldl	$21,111($5)
+	ldr	$21,104($5)
+	ori	$9,$0,0xFF
+	dsll	$11,$9,32
+	or	$9,$11		# 0x000000FF000000FF
+	and	$10,$20,$9	# byte swap(12)
+	dsrl	$11,$20,24
+	dsll	$10,24
+	and	$11,$9
+	dsll	$9,8			# 0x0000FF000000FF00
+	or	$10,$11
+	and	$11,$20,$9
+	dsrl	$20,8
+	dsll	$11,8
+	and	$20,$9
+	or	$10,$11
+	or	$20,$10
+	dsrl	$10,$20,32
+	dsll	$20,32
+	or	$20,$10
+	daddu	$8,$20,$7			# 12
+	dsrl	$7,$1,14
+	xor	$11,$2,$3
+	dsll	$10,$1,23
+	and	$11,$1
+	dsrl	$9,$1,18
+	xor	$7,$10
+	dsll	$10,$1,46
+	xor	$7,$9
+	dsrl	$9,$1,41
+	xor	$7,$10
+	dsll	$10,$1,50
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$8,$11
+	ld	$11,96($6)		# K[12]
+	dsll	$10,$24,25
+	daddu	$8,$9
+	dsrl	$9,$24,34
+	xor	$7,$10
+	dsll	$10,$24,30
+	xor	$7,$9
+	dsrl	$9,$24,39
+	xor	$7,$10
+	dsll	$10,$24,36
+	xor	$7,$9
+	sd	$20,96($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	daddu	$8,$11			# +=K[12]
+	daddu	$7,$10
+
+	daddu	$31,$8
+	daddu	$7,$8
+	ldl	$22,119($5)
+	ldr	$22,112($5)
+	ori	$10,$0,0xFF
+	dsll	$12,$10,32
+	or	$10,$12		# 0x000000FF000000FF
+	and	$11,$21,$10	# byte swap(13)
+	dsrl	$12,$21,24
+	dsll	$11,24
+	and	$12,$10
+	dsll	$10,8			# 0x0000FF000000FF00
+	or	$11,$12
+	and	$12,$21,$10
+	dsrl	$21,8
+	dsll	$12,8
+	and	$21,$10
+	or	$11,$12
+	or	$21,$11
+	dsrl	$11,$21,32
+	dsll	$21,32
+	or	$21,$11
+	daddu	$9,$21,$3			# 13
+	dsrl	$3,$31,14
+	xor	$12,$1,$2
+	dsll	$11,$31,23
+	and	$12,$31
+	dsrl	$10,$31,18
+	xor	$3,$11
+	dsll	$11,$31,46
+	xor	$3,$10
+	dsrl	$10,$31,41
+	xor	$3,$11
+	dsll	$11,$31,50
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$9,$12
+	ld	$12,104($6)		# K[13]
+	dsll	$11,$7,25
+	daddu	$9,$10
+	dsrl	$10,$7,34
+	xor	$3,$11
+	dsll	$11,$7,30
+	xor	$3,$10
+	dsrl	$10,$7,39
+	xor	$3,$11
+	dsll	$11,$7,36
+	xor	$3,$10
+	sd	$21,104($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	daddu	$9,$12			# +=K[13]
+	daddu	$3,$11
+
+	daddu	$30,$9
+	daddu	$3,$9
+	ld	$8,0($29)	# prefetch from ring buffer
+	ldl	$23,127($5)
+	ldr	$23,120($5)
+	ori	$11,$0,0xFF
+	dsll	$13,$11,32
+	or	$11,$13		# 0x000000FF000000FF
+	and	$12,$22,$11	# byte swap(14)
+	dsrl	$13,$22,24
+	dsll	$12,24
+	and	$13,$11
+	dsll	$11,8			# 0x0000FF000000FF00
+	or	$12,$13
+	and	$13,$22,$11
+	dsrl	$22,8
+	dsll	$13,8
+	and	$22,$11
+	or	$12,$13
+	or	$22,$12
+	dsrl	$12,$22,32
+	dsll	$22,32
+	or	$22,$12
+	daddu	$10,$22,$2			# 14
+	dsrl	$2,$30,14
+	xor	$13,$31,$1
+	dsll	$12,$30,23
+	and	$13,$30
+	dsrl	$11,$30,18
+	xor	$2,$12
+	dsll	$12,$30,46
+	xor	$2,$11
+	dsrl	$11,$30,41
+	xor	$2,$12
+	dsll	$12,$30,50
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$10,$13
+	ld	$13,112($6)		# K[14]
+	dsll	$12,$3,25
+	daddu	$10,$11
+	dsrl	$11,$3,34
+	xor	$2,$12
+	dsll	$12,$3,30
+	xor	$2,$11
+	dsrl	$11,$3,39
+	xor	$2,$12
+	dsll	$12,$3,36
+	xor	$2,$11
+	sd	$22,112($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	daddu	$10,$13			# +=K[14]
+	daddu	$2,$12
+
+	daddu	$25,$10
+	daddu	$2,$10
+	ld	$9,8($29)	# prefetch from ring buffer
+	ori	$12,$0,0xFF
+	dsll	$14,$12,32
+	or	$12,$14		# 0x000000FF000000FF
+	and	$13,$23,$12	# byte swap(15)
+	dsrl	$14,$23,24
+	dsll	$13,24
+	and	$14,$12
+	dsll	$12,8			# 0x0000FF000000FF00
+	or	$13,$14
+	and	$14,$23,$12
+	dsrl	$23,8
+	dsll	$14,8
+	and	$23,$12
+	or	$13,$14
+	or	$23,$13
+	dsrl	$13,$23,32
+	dsll	$23,32
+	or	$23,$13
+	daddu	$11,$23,$1			# 15
+	dsrl	$1,$25,14
+	xor	$14,$30,$31
+	dsll	$13,$25,23
+	and	$14,$25
+	dsrl	$12,$25,18
+	xor	$1,$13
+	dsll	$13,$25,46
+	xor	$1,$12
+	dsrl	$12,$25,41
+	xor	$1,$13
+	dsll	$13,$25,50
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$11,$14
+	ld	$14,120($6)		# K[15]
+	dsll	$13,$2,25
+	daddu	$11,$12
+	dsrl	$12,$2,34
+	xor	$1,$13
+	dsll	$13,$2,30
+	xor	$1,$12
+	dsrl	$12,$2,39
+	xor	$1,$13
+	dsll	$13,$2,36
+	xor	$1,$12
+	sd	$23,120($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	daddu	$11,$14			# +=K[15]
+	daddu	$1,$13
+
+	daddu	$24,$11
+	daddu	$1,$11
+	ld	$10,16($29)	# prefetch from ring buffer
+	b	.L16_xx
+.align	4
+.L16_xx:
+	dsrl	$14,$9,7		# Xupdate(16)
+	daddu	$8,$17			# +=X[i+9]
+	dsll	$13,$9,56
+	dsrl	$12,$9,1
+	xor	$14,$13
+	dsll	$13,7
+	xor	$14,$12
+	dsrl	$12,$9,8
+	xor	$14,$13
+
+	dsrl	$15,$22,6
+	xor	$14,$12			# sigma0(X[i+1])
+	dsll	$13,$22,3
+	daddu	$8,$14
+	dsrl	$12,$22,19
+	xor	$15,$13
+	dsll	$13,42
+	xor	$15,$12
+	dsrl	$12,$22,61
+	xor	$15,$13
+
+	xor	$15,$12			# sigma1(X[i+14])
+	daddu	$8,$15
+	daddu	$12,$8,$31			# 16
+	dsrl	$31,$24,14
+	xor	$15,$25,$30
+	dsll	$14,$24,23
+	and	$15,$24
+	dsrl	$13,$24,18
+	xor	$31,$14
+	dsll	$14,$24,46
+	xor	$31,$13
+	dsrl	$13,$24,41
+	xor	$31,$14
+	dsll	$14,$24,50
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$12,$15
+	ld	$15,128($6)		# K[16]
+	dsll	$14,$1,25
+	daddu	$12,$13
+	dsrl	$13,$1,34
+	xor	$31,$14
+	dsll	$14,$1,30
+	xor	$31,$13
+	dsrl	$13,$1,39
+	xor	$31,$14
+	dsll	$14,$1,36
+	xor	$31,$13
+	sd	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	daddu	$12,$15			# +=K[16]
+	daddu	$31,$14
+
+	daddu	$7,$12
+	daddu	$31,$12
+	ld	$11,24($29)	# prefetch from ring buffer
+	dsrl	$15,$10,7		# Xupdate(17)
+	daddu	$9,$18			# +=X[i+9]
+	dsll	$14,$10,56
+	dsrl	$13,$10,1
+	xor	$15,$14
+	dsll	$14,7
+	xor	$15,$13
+	dsrl	$13,$10,8
+	xor	$15,$14
+
+	dsrl	$16,$23,6
+	xor	$15,$13			# sigma0(X[i+1])
+	dsll	$14,$23,3
+	daddu	$9,$15
+	dsrl	$13,$23,19
+	xor	$16,$14
+	dsll	$14,42
+	xor	$16,$13
+	dsrl	$13,$23,61
+	xor	$16,$14
+
+	xor	$16,$13			# sigma1(X[i+14])
+	daddu	$9,$16
+	daddu	$13,$9,$30			# 17
+	dsrl	$30,$7,14
+	xor	$16,$24,$25
+	dsll	$15,$7,23
+	and	$16,$7
+	dsrl	$14,$7,18
+	xor	$30,$15
+	dsll	$15,$7,46
+	xor	$30,$14
+	dsrl	$14,$7,41
+	xor	$30,$15
+	dsll	$15,$7,50
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$13,$16
+	ld	$16,136($6)		# K[17]
+	dsll	$15,$31,25
+	daddu	$13,$14
+	dsrl	$14,$31,34
+	xor	$30,$15
+	dsll	$15,$31,30
+	xor	$30,$14
+	dsrl	$14,$31,39
+	xor	$30,$15
+	dsll	$15,$31,36
+	xor	$30,$14
+	sd	$9,8($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	daddu	$13,$16			# +=K[17]
+	daddu	$30,$15
+
+	daddu	$3,$13
+	daddu	$30,$13
+	ld	$12,32($29)	# prefetch from ring buffer
+	dsrl	$16,$11,7		# Xupdate(18)
+	daddu	$10,$19			# +=X[i+9]
+	dsll	$15,$11,56
+	dsrl	$14,$11,1
+	xor	$16,$15
+	dsll	$15,7
+	xor	$16,$14
+	dsrl	$14,$11,8
+	xor	$16,$15
+
+	dsrl	$17,$8,6
+	xor	$16,$14			# sigma0(X[i+1])
+	dsll	$15,$8,3
+	daddu	$10,$16
+	dsrl	$14,$8,19
+	xor	$17,$15
+	dsll	$15,42
+	xor	$17,$14
+	dsrl	$14,$8,61
+	xor	$17,$15
+
+	xor	$17,$14			# sigma1(X[i+14])
+	daddu	$10,$17
+	daddu	$14,$10,$25			# 18
+	dsrl	$25,$3,14
+	xor	$17,$7,$24
+	dsll	$16,$3,23
+	and	$17,$3
+	dsrl	$15,$3,18
+	xor	$25,$16
+	dsll	$16,$3,46
+	xor	$25,$15
+	dsrl	$15,$3,41
+	xor	$25,$16
+	dsll	$16,$3,50
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$14,$17
+	ld	$17,144($6)		# K[18]
+	dsll	$16,$30,25
+	daddu	$14,$15
+	dsrl	$15,$30,34
+	xor	$25,$16
+	dsll	$16,$30,30
+	xor	$25,$15
+	dsrl	$15,$30,39
+	xor	$25,$16
+	dsll	$16,$30,36
+	xor	$25,$15
+	sd	$10,16($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	daddu	$14,$17			# +=K[18]
+	daddu	$25,$16
+
+	daddu	$2,$14
+	daddu	$25,$14
+	ld	$13,40($29)	# prefetch from ring buffer
+	dsrl	$17,$12,7		# Xupdate(19)
+	daddu	$11,$20			# +=X[i+9]
+	dsll	$16,$12,56
+	dsrl	$15,$12,1
+	xor	$17,$16
+	dsll	$16,7
+	xor	$17,$15
+	dsrl	$15,$12,8
+	xor	$17,$16
+
+	dsrl	$18,$9,6
+	xor	$17,$15			# sigma0(X[i+1])
+	dsll	$16,$9,3
+	daddu	$11,$17
+	dsrl	$15,$9,19
+	xor	$18,$16
+	dsll	$16,42
+	xor	$18,$15
+	dsrl	$15,$9,61
+	xor	$18,$16
+
+	xor	$18,$15			# sigma1(X[i+14])
+	daddu	$11,$18
+	daddu	$15,$11,$24			# 19
+	dsrl	$24,$2,14
+	xor	$18,$3,$7
+	dsll	$17,$2,23
+	and	$18,$2
+	dsrl	$16,$2,18
+	xor	$24,$17
+	dsll	$17,$2,46
+	xor	$24,$16
+	dsrl	$16,$2,41
+	xor	$24,$17
+	dsll	$17,$2,50
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$15,$18
+	ld	$18,152($6)		# K[19]
+	dsll	$17,$25,25
+	daddu	$15,$16
+	dsrl	$16,$25,34
+	xor	$24,$17
+	dsll	$17,$25,30
+	xor	$24,$16
+	dsrl	$16,$25,39
+	xor	$24,$17
+	dsll	$17,$25,36
+	xor	$24,$16
+	sd	$11,24($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	daddu	$15,$18			# +=K[19]
+	daddu	$24,$17
+
+	daddu	$1,$15
+	daddu	$24,$15
+	ld	$14,48($29)	# prefetch from ring buffer
+	dsrl	$18,$13,7		# Xupdate(20)
+	daddu	$12,$21			# +=X[i+9]
+	dsll	$17,$13,56
+	dsrl	$16,$13,1
+	xor	$18,$17
+	dsll	$17,7
+	xor	$18,$16
+	dsrl	$16,$13,8
+	xor	$18,$17
+
+	dsrl	$19,$10,6
+	xor	$18,$16			# sigma0(X[i+1])
+	dsll	$17,$10,3
+	daddu	$12,$18
+	dsrl	$16,$10,19
+	xor	$19,$17
+	dsll	$17,42
+	xor	$19,$16
+	dsrl	$16,$10,61
+	xor	$19,$17
+
+	xor	$19,$16			# sigma1(X[i+14])
+	daddu	$12,$19
+	daddu	$16,$12,$7			# 20
+	dsrl	$7,$1,14
+	xor	$19,$2,$3
+	dsll	$18,$1,23
+	and	$19,$1
+	dsrl	$17,$1,18
+	xor	$7,$18
+	dsll	$18,$1,46
+	xor	$7,$17
+	dsrl	$17,$1,41
+	xor	$7,$18
+	dsll	$18,$1,50
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$16,$19
+	ld	$19,160($6)		# K[20]
+	dsll	$18,$24,25
+	daddu	$16,$17
+	dsrl	$17,$24,34
+	xor	$7,$18
+	dsll	$18,$24,30
+	xor	$7,$17
+	dsrl	$17,$24,39
+	xor	$7,$18
+	dsll	$18,$24,36
+	xor	$7,$17
+	sd	$12,32($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	daddu	$16,$19			# +=K[20]
+	daddu	$7,$18
+
+	daddu	$31,$16
+	daddu	$7,$16
+	ld	$15,56($29)	# prefetch from ring buffer
+	dsrl	$19,$14,7		# Xupdate(21)
+	daddu	$13,$22			# +=X[i+9]
+	dsll	$18,$14,56
+	dsrl	$17,$14,1
+	xor	$19,$18
+	dsll	$18,7
+	xor	$19,$17
+	dsrl	$17,$14,8
+	xor	$19,$18
+
+	dsrl	$20,$11,6
+	xor	$19,$17			# sigma0(X[i+1])
+	dsll	$18,$11,3
+	daddu	$13,$19
+	dsrl	$17,$11,19
+	xor	$20,$18
+	dsll	$18,42
+	xor	$20,$17
+	dsrl	$17,$11,61
+	xor	$20,$18
+
+	xor	$20,$17			# sigma1(X[i+14])
+	daddu	$13,$20
+	daddu	$17,$13,$3			# 21
+	dsrl	$3,$31,14
+	xor	$20,$1,$2
+	dsll	$19,$31,23
+	and	$20,$31
+	dsrl	$18,$31,18
+	xor	$3,$19
+	dsll	$19,$31,46
+	xor	$3,$18
+	dsrl	$18,$31,41
+	xor	$3,$19
+	dsll	$19,$31,50
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$17,$20
+	ld	$20,168($6)		# K[21]
+	dsll	$19,$7,25
+	daddu	$17,$18
+	dsrl	$18,$7,34
+	xor	$3,$19
+	dsll	$19,$7,30
+	xor	$3,$18
+	dsrl	$18,$7,39
+	xor	$3,$19
+	dsll	$19,$7,36
+	xor	$3,$18
+	sd	$13,40($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	daddu	$17,$20			# +=K[21]
+	daddu	$3,$19
+
+	daddu	$30,$17
+	daddu	$3,$17
+	ld	$16,64($29)	# prefetch from ring buffer
+	dsrl	$20,$15,7		# Xupdate(22)
+	daddu	$14,$23			# +=X[i+9]
+	dsll	$19,$15,56
+	dsrl	$18,$15,1
+	xor	$20,$19
+	dsll	$19,7
+	xor	$20,$18
+	dsrl	$18,$15,8
+	xor	$20,$19
+
+	dsrl	$21,$12,6
+	xor	$20,$18			# sigma0(X[i+1])
+	dsll	$19,$12,3
+	daddu	$14,$20
+	dsrl	$18,$12,19
+	xor	$21,$19
+	dsll	$19,42
+	xor	$21,$18
+	dsrl	$18,$12,61
+	xor	$21,$19
+
+	xor	$21,$18			# sigma1(X[i+14])
+	daddu	$14,$21
+	daddu	$18,$14,$2			# 22
+	dsrl	$2,$30,14
+	xor	$21,$31,$1
+	dsll	$20,$30,23
+	and	$21,$30
+	dsrl	$19,$30,18
+	xor	$2,$20
+	dsll	$20,$30,46
+	xor	$2,$19
+	dsrl	$19,$30,41
+	xor	$2,$20
+	dsll	$20,$30,50
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$18,$21
+	ld	$21,176($6)		# K[22]
+	dsll	$20,$3,25
+	daddu	$18,$19
+	dsrl	$19,$3,34
+	xor	$2,$20
+	dsll	$20,$3,30
+	xor	$2,$19
+	dsrl	$19,$3,39
+	xor	$2,$20
+	dsll	$20,$3,36
+	xor	$2,$19
+	sd	$14,48($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	daddu	$18,$21			# +=K[22]
+	daddu	$2,$20
+
+	daddu	$25,$18
+	daddu	$2,$18
+	ld	$17,72($29)	# prefetch from ring buffer
+	dsrl	$21,$16,7		# Xupdate(23)
+	daddu	$15,$8			# +=X[i+9]
+	dsll	$20,$16,56
+	dsrl	$19,$16,1
+	xor	$21,$20
+	dsll	$20,7
+	xor	$21,$19
+	dsrl	$19,$16,8
+	xor	$21,$20
+
+	dsrl	$22,$13,6
+	xor	$21,$19			# sigma0(X[i+1])
+	dsll	$20,$13,3
+	daddu	$15,$21
+	dsrl	$19,$13,19
+	xor	$22,$20
+	dsll	$20,42
+	xor	$22,$19
+	dsrl	$19,$13,61
+	xor	$22,$20
+
+	xor	$22,$19			# sigma1(X[i+14])
+	daddu	$15,$22
+	daddu	$19,$15,$1			# 23
+	dsrl	$1,$25,14
+	xor	$22,$30,$31
+	dsll	$21,$25,23
+	and	$22,$25
+	dsrl	$20,$25,18
+	xor	$1,$21
+	dsll	$21,$25,46
+	xor	$1,$20
+	dsrl	$20,$25,41
+	xor	$1,$21
+	dsll	$21,$25,50
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$19,$22
+	ld	$22,184($6)		# K[23]
+	dsll	$21,$2,25
+	daddu	$19,$20
+	dsrl	$20,$2,34
+	xor	$1,$21
+	dsll	$21,$2,30
+	xor	$1,$20
+	dsrl	$20,$2,39
+	xor	$1,$21
+	dsll	$21,$2,36
+	xor	$1,$20
+	sd	$15,56($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	daddu	$19,$22			# +=K[23]
+	daddu	$1,$21
+
+	daddu	$24,$19
+	daddu	$1,$19
+	ld	$18,80($29)	# prefetch from ring buffer
+	dsrl	$22,$17,7		# Xupdate(24)
+	daddu	$16,$9			# +=X[i+9]
+	dsll	$21,$17,56
+	dsrl	$20,$17,1
+	xor	$22,$21
+	dsll	$21,7
+	xor	$22,$20
+	dsrl	$20,$17,8
+	xor	$22,$21
+
+	dsrl	$23,$14,6
+	xor	$22,$20			# sigma0(X[i+1])
+	dsll	$21,$14,3
+	daddu	$16,$22
+	dsrl	$20,$14,19
+	xor	$23,$21
+	dsll	$21,42
+	xor	$23,$20
+	dsrl	$20,$14,61
+	xor	$23,$21
+
+	xor	$23,$20			# sigma1(X[i+14])
+	daddu	$16,$23
+	daddu	$20,$16,$31			# 24
+	dsrl	$31,$24,14
+	xor	$23,$25,$30
+	dsll	$22,$24,23
+	and	$23,$24
+	dsrl	$21,$24,18
+	xor	$31,$22
+	dsll	$22,$24,46
+	xor	$31,$21
+	dsrl	$21,$24,41
+	xor	$31,$22
+	dsll	$22,$24,50
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$20,$23
+	ld	$23,192($6)		# K[24]
+	dsll	$22,$1,25
+	daddu	$20,$21
+	dsrl	$21,$1,34
+	xor	$31,$22
+	dsll	$22,$1,30
+	xor	$31,$21
+	dsrl	$21,$1,39
+	xor	$31,$22
+	dsll	$22,$1,36
+	xor	$31,$21
+	sd	$16,64($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	daddu	$20,$23			# +=K[24]
+	daddu	$31,$22
+
+	daddu	$7,$20
+	daddu	$31,$20
+	ld	$19,88($29)	# prefetch from ring buffer
+	dsrl	$23,$18,7		# Xupdate(25)
+	daddu	$17,$10			# +=X[i+9]
+	dsll	$22,$18,56
+	dsrl	$21,$18,1
+	xor	$23,$22
+	dsll	$22,7
+	xor	$23,$21
+	dsrl	$21,$18,8
+	xor	$23,$22
+
+	dsrl	$8,$15,6
+	xor	$23,$21			# sigma0(X[i+1])
+	dsll	$22,$15,3
+	daddu	$17,$23
+	dsrl	$21,$15,19
+	xor	$8,$22
+	dsll	$22,42
+	xor	$8,$21
+	dsrl	$21,$15,61
+	xor	$8,$22
+
+	xor	$8,$21			# sigma1(X[i+14])
+	daddu	$17,$8
+	daddu	$21,$17,$30			# 25
+	dsrl	$30,$7,14
+	xor	$8,$24,$25
+	dsll	$23,$7,23
+	and	$8,$7
+	dsrl	$22,$7,18
+	xor	$30,$23
+	dsll	$23,$7,46
+	xor	$30,$22
+	dsrl	$22,$7,41
+	xor	$30,$23
+	dsll	$23,$7,50
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$21,$8
+	ld	$8,200($6)		# K[25]
+	dsll	$23,$31,25
+	daddu	$21,$22
+	dsrl	$22,$31,34
+	xor	$30,$23
+	dsll	$23,$31,30
+	xor	$30,$22
+	dsrl	$22,$31,39
+	xor	$30,$23
+	dsll	$23,$31,36
+	xor	$30,$22
+	sd	$17,72($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	daddu	$21,$8			# +=K[25]
+	daddu	$30,$23
+
+	daddu	$3,$21
+	daddu	$30,$21
+	ld	$20,96($29)	# prefetch from ring buffer
+	dsrl	$8,$19,7		# Xupdate(26)
+	daddu	$18,$11			# +=X[i+9]
+	dsll	$23,$19,56
+	dsrl	$22,$19,1
+	xor	$8,$23
+	dsll	$23,7
+	xor	$8,$22
+	dsrl	$22,$19,8
+	xor	$8,$23
+
+	dsrl	$9,$16,6
+	xor	$8,$22			# sigma0(X[i+1])
+	dsll	$23,$16,3
+	daddu	$18,$8
+	dsrl	$22,$16,19
+	xor	$9,$23
+	dsll	$23,42
+	xor	$9,$22
+	dsrl	$22,$16,61
+	xor	$9,$23
+
+	xor	$9,$22			# sigma1(X[i+14])
+	daddu	$18,$9
+	daddu	$22,$18,$25			# 26
+	dsrl	$25,$3,14
+	xor	$9,$7,$24
+	dsll	$8,$3,23
+	and	$9,$3
+	dsrl	$23,$3,18
+	xor	$25,$8
+	dsll	$8,$3,46
+	xor	$25,$23
+	dsrl	$23,$3,41
+	xor	$25,$8
+	dsll	$8,$3,50
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$22,$9
+	ld	$9,208($6)		# K[26]
+	dsll	$8,$30,25
+	daddu	$22,$23
+	dsrl	$23,$30,34
+	xor	$25,$8
+	dsll	$8,$30,30
+	xor	$25,$23
+	dsrl	$23,$30,39
+	xor	$25,$8
+	dsll	$8,$30,36
+	xor	$25,$23
+	sd	$18,80($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	daddu	$22,$9			# +=K[26]
+	daddu	$25,$8
+
+	daddu	$2,$22
+	daddu	$25,$22
+	ld	$21,104($29)	# prefetch from ring buffer
+	dsrl	$9,$20,7		# Xupdate(27)
+	daddu	$19,$12			# +=X[i+9]
+	dsll	$8,$20,56
+	dsrl	$23,$20,1
+	xor	$9,$8
+	dsll	$8,7
+	xor	$9,$23
+	dsrl	$23,$20,8
+	xor	$9,$8
+
+	dsrl	$10,$17,6
+	xor	$9,$23			# sigma0(X[i+1])
+	dsll	$8,$17,3
+	daddu	$19,$9
+	dsrl	$23,$17,19
+	xor	$10,$8
+	dsll	$8,42
+	xor	$10,$23
+	dsrl	$23,$17,61
+	xor	$10,$8
+
+	xor	$10,$23			# sigma1(X[i+14])
+	daddu	$19,$10
+	daddu	$23,$19,$24			# 27
+	dsrl	$24,$2,14
+	xor	$10,$3,$7
+	dsll	$9,$2,23
+	and	$10,$2
+	dsrl	$8,$2,18
+	xor	$24,$9
+	dsll	$9,$2,46
+	xor	$24,$8
+	dsrl	$8,$2,41
+	xor	$24,$9
+	dsll	$9,$2,50
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$23,$10
+	ld	$10,216($6)		# K[27]
+	dsll	$9,$25,25
+	daddu	$23,$8
+	dsrl	$8,$25,34
+	xor	$24,$9
+	dsll	$9,$25,30
+	xor	$24,$8
+	dsrl	$8,$25,39
+	xor	$24,$9
+	dsll	$9,$25,36
+	xor	$24,$8
+	sd	$19,88($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	daddu	$23,$10			# +=K[27]
+	daddu	$24,$9
+
+	daddu	$1,$23
+	daddu	$24,$23
+	ld	$22,112($29)	# prefetch from ring buffer
+	dsrl	$10,$21,7		# Xupdate(28)
+	daddu	$20,$13			# +=X[i+9]
+	dsll	$9,$21,56
+	dsrl	$8,$21,1
+	xor	$10,$9
+	dsll	$9,7
+	xor	$10,$8
+	dsrl	$8,$21,8
+	xor	$10,$9
+
+	dsrl	$11,$18,6
+	xor	$10,$8			# sigma0(X[i+1])
+	dsll	$9,$18,3
+	daddu	$20,$10
+	dsrl	$8,$18,19
+	xor	$11,$9
+	dsll	$9,42
+	xor	$11,$8
+	dsrl	$8,$18,61
+	xor	$11,$9
+
+	xor	$11,$8			# sigma1(X[i+14])
+	daddu	$20,$11
+	daddu	$8,$20,$7			# 28
+	dsrl	$7,$1,14
+	xor	$11,$2,$3
+	dsll	$10,$1,23
+	and	$11,$1
+	dsrl	$9,$1,18
+	xor	$7,$10
+	dsll	$10,$1,46
+	xor	$7,$9
+	dsrl	$9,$1,41
+	xor	$7,$10
+	dsll	$10,$1,50
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$8,$11
+	ld	$11,224($6)		# K[28]
+	dsll	$10,$24,25
+	daddu	$8,$9
+	dsrl	$9,$24,34
+	xor	$7,$10
+	dsll	$10,$24,30
+	xor	$7,$9
+	dsrl	$9,$24,39
+	xor	$7,$10
+	dsll	$10,$24,36
+	xor	$7,$9
+	sd	$20,96($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	daddu	$8,$11			# +=K[28]
+	daddu	$7,$10
+
+	daddu	$31,$8
+	daddu	$7,$8
+	ld	$23,120($29)	# prefetch from ring buffer
+	dsrl	$11,$22,7		# Xupdate(29)
+	daddu	$21,$14			# +=X[i+9]
+	dsll	$10,$22,56
+	dsrl	$9,$22,1
+	xor	$11,$10
+	dsll	$10,7
+	xor	$11,$9
+	dsrl	$9,$22,8
+	xor	$11,$10
+
+	dsrl	$12,$19,6
+	xor	$11,$9			# sigma0(X[i+1])
+	dsll	$10,$19,3
+	daddu	$21,$11
+	dsrl	$9,$19,19
+	xor	$12,$10
+	dsll	$10,42
+	xor	$12,$9
+	dsrl	$9,$19,61
+	xor	$12,$10
+
+	xor	$12,$9			# sigma1(X[i+14])
+	daddu	$21,$12
+	daddu	$9,$21,$3			# 29
+	dsrl	$3,$31,14
+	xor	$12,$1,$2
+	dsll	$11,$31,23
+	and	$12,$31
+	dsrl	$10,$31,18
+	xor	$3,$11
+	dsll	$11,$31,46
+	xor	$3,$10
+	dsrl	$10,$31,41
+	xor	$3,$11
+	dsll	$11,$31,50
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$9,$12
+	ld	$12,232($6)		# K[29]
+	dsll	$11,$7,25
+	daddu	$9,$10
+	dsrl	$10,$7,34
+	xor	$3,$11
+	dsll	$11,$7,30
+	xor	$3,$10
+	dsrl	$10,$7,39
+	xor	$3,$11
+	dsll	$11,$7,36
+	xor	$3,$10
+	sd	$21,104($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	daddu	$9,$12			# +=K[29]
+	daddu	$3,$11
+
+	daddu	$30,$9
+	daddu	$3,$9
+	ld	$8,0($29)	# prefetch from ring buffer
+	dsrl	$12,$23,7		# Xupdate(30)
+	daddu	$22,$15			# +=X[i+9]
+	dsll	$11,$23,56
+	dsrl	$10,$23,1
+	xor	$12,$11
+	dsll	$11,7
+	xor	$12,$10
+	dsrl	$10,$23,8
+	xor	$12,$11
+
+	dsrl	$13,$20,6
+	xor	$12,$10			# sigma0(X[i+1])
+	dsll	$11,$20,3
+	daddu	$22,$12
+	dsrl	$10,$20,19
+	xor	$13,$11
+	dsll	$11,42
+	xor	$13,$10
+	dsrl	$10,$20,61
+	xor	$13,$11
+
+	xor	$13,$10			# sigma1(X[i+14])
+	daddu	$22,$13
+	daddu	$10,$22,$2			# 30
+	dsrl	$2,$30,14
+	xor	$13,$31,$1
+	dsll	$12,$30,23
+	and	$13,$30
+	dsrl	$11,$30,18
+	xor	$2,$12
+	dsll	$12,$30,46
+	xor	$2,$11
+	dsrl	$11,$30,41
+	xor	$2,$12
+	dsll	$12,$30,50
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$10,$13
+	ld	$13,240($6)		# K[30]
+	dsll	$12,$3,25
+	daddu	$10,$11
+	dsrl	$11,$3,34
+	xor	$2,$12
+	dsll	$12,$3,30
+	xor	$2,$11
+	dsrl	$11,$3,39
+	xor	$2,$12
+	dsll	$12,$3,36
+	xor	$2,$11
+	sd	$22,112($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	daddu	$10,$13			# +=K[30]
+	daddu	$2,$12
+
+	daddu	$25,$10
+	daddu	$2,$10
+	ld	$9,8($29)	# prefetch from ring buffer
+	dsrl	$13,$8,7		# Xupdate(31)
+	daddu	$23,$16			# +=X[i+9]
+	dsll	$12,$8,56
+	dsrl	$11,$8,1
+	xor	$13,$12
+	dsll	$12,7
+	xor	$13,$11
+	dsrl	$11,$8,8
+	xor	$13,$12
+
+	dsrl	$14,$21,6
+	xor	$13,$11			# sigma0(X[i+1])
+	dsll	$12,$21,3
+	daddu	$23,$13
+	dsrl	$11,$21,19
+	xor	$14,$12
+	dsll	$12,42
+	xor	$14,$11
+	dsrl	$11,$21,61
+	xor	$14,$12
+
+	xor	$14,$11			# sigma1(X[i+14])
+	daddu	$23,$14
+	daddu	$11,$23,$1			# 31
+	dsrl	$1,$25,14
+	xor	$14,$30,$31
+	dsll	$13,$25,23
+	and	$14,$25
+	dsrl	$12,$25,18
+	xor	$1,$13
+	dsll	$13,$25,46
+	xor	$1,$12
+	dsrl	$12,$25,41
+	xor	$1,$13
+	dsll	$13,$25,50
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$11,$14
+	ld	$14,248($6)		# K[31]
+	dsll	$13,$2,25
+	daddu	$11,$12
+	dsrl	$12,$2,34
+	xor	$1,$13
+	dsll	$13,$2,30
+	xor	$1,$12
+	dsrl	$12,$2,39
+	xor	$1,$13
+	dsll	$13,$2,36
+	xor	$1,$12
+	sd	$23,120($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	daddu	$11,$14			# +=K[31]
+	daddu	$1,$13
+
+	daddu	$24,$11
+	daddu	$1,$11
+	ld	$10,16($29)	# prefetch from ring buffer
+	and	$14,0xfff
+	li	$15,2071
+	.set	noreorder
+	bne	$14,$15,.L16_xx
+	add $6,16*8		# Ktbl+=16
+
+	lw	$23,16*8($29)	# restore pointer to the end of input
+	ld	$8,0*8($4)
+	ld	$9,1*8($4)
+	ld	$10,2*8($4)
+	add $5,16*8
+	ld	$11,3*8($4)
+	daddu	$1,$8
+	ld	$12,4*8($4)
+	daddu	$2,$9
+	ld	$13,5*8($4)
+	daddu	$3,$10
+	ld	$14,6*8($4)
+	daddu	$7,$11
+	ld	$15,7*8($4)
+	daddu	$24,$12
+	sd	$1,0*8($4)
+	daddu	$25,$13
+	sd	$2,1*8($4)
+	daddu	$30,$14
+	sd	$3,2*8($4)
+	daddu	$31,$15
+	sd	$7,3*8($4)
+	sd	$24,4*8($4)
+	sd	$25,5*8($4)
+	sd	$30,6*8($4)
+	sd	$31,7*8($4)
+
+	bne	$5,$23,.Loop
+	sub $6,512	# rewind $6
+
+	lw	$31,192-1*4($29)
+	lw	$30,192-2*4($29)
+	lw	$23,192-3*4($29)
+	lw	$22,192-4*4($29)
+	lw	$21,192-5*4($29)
+	lw	$20,192-6*4($29)
+	lw	$19,192-7*4($29)
+	lw	$18,192-8*4($29)
+	lw	$17,192-9*4($29)
+	lw	$16,192-10*4($29)
+	jr	$31
+	add $29,192
+.end	sha512_block_data_order
+
+.rdata
+.align	5
+K512:
+	.dword	0x428a2f98d728ae22, 0x7137449123ef65cd
+	.dword	0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc
+	.dword	0x3956c25bf348b538, 0x59f111f1b605d019
+	.dword	0x923f82a4af194f9b, 0xab1c5ed5da6d8118
+	.dword	0xd807aa98a3030242, 0x12835b0145706fbe
+	.dword	0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2
+	.dword	0x72be5d74f27b896f, 0x80deb1fe3b1696b1
+	.dword	0x9bdc06a725c71235, 0xc19bf174cf692694
+	.dword	0xe49b69c19ef14ad2, 0xefbe4786384f25e3
+	.dword	0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65
+	.dword	0x2de92c6f592b0275, 0x4a7484aa6ea6e483
+	.dword	0x5cb0a9dcbd41fbd4, 0x76f988da831153b5
+	.dword	0x983e5152ee66dfab, 0xa831c66d2db43210
+	.dword	0xb00327c898fb213f, 0xbf597fc7beef0ee4
+	.dword	0xc6e00bf33da88fc2, 0xd5a79147930aa725
+	.dword	0x06ca6351e003826f, 0x142929670a0e6e70
+	.dword	0x27b70a8546d22ffc, 0x2e1b21385c26c926
+	.dword	0x4d2c6dfc5ac42aed, 0x53380d139d95b3df
+	.dword	0x650a73548baf63de, 0x766a0abb3c77b2a8
+	.dword	0x81c2c92e47edaee6, 0x92722c851482353b
+	.dword	0xa2bfe8a14cf10364, 0xa81a664bbc423001
+	.dword	0xc24b8b70d0f89791, 0xc76c51a30654be30
+	.dword	0xd192e819d6ef5218, 0xd69906245565a910
+	.dword	0xf40e35855771202a, 0x106aa07032bbd1b8
+	.dword	0x19a4c116b8d2d0c8, 0x1e376c085141ab53
+	.dword	0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8
+	.dword	0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb
+	.dword	0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3
+	.dword	0x748f82ee5defb2fc, 0x78a5636f43172f60
+	.dword	0x84c87814a1f0ab72, 0x8cc702081a6439ec
+	.dword	0x90befffa23631e28, 0xa4506cebde82bde9
+	.dword	0xbef9a3f7b2c67915, 0xc67178f2e372532b
+	.dword	0xca273eceea26619c, 0xd186b8c721c0c207
+	.dword	0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178
+	.dword	0x06f067aa72176fba, 0x0a637dc5a2c898a6
+	.dword	0x113f9804bef90dae, 0x1b710b35131c471b
+	.dword	0x28db77f523047d84, 0x32caab7b40c72493
+	.dword	0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c
+	.dword	0x4cc5d4becb3e42b6, 0x597f299cfc657e2a
+	.dword	0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+.asciiz	"SHA512 for MIPS, CRYPTOGAMS by "
+.align	5
+
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha512-mips64.S b/crypto/sha/sha512-mips64.S
new file mode 100644
index 0000000..7db141f
--- /dev/null
+++ b/crypto/sha/sha512-mips64.S
@@ -0,0 +1,2166 @@
+.text
+.set	noat
+#if !defined(__vxworks) || defined(__pic__)
+.option	pic2
+#endif
+
+.align	5
+.globl	sha512_block_data_order
+.ent	sha512_block_data_order
+sha512_block_data_order:
+	.frame	$29,256,$31
+	.mask	3237937152,-8
+	.set	noreorder
+	dsub $29,256
+	sd	$31,256-1*8($29)
+	sd	$30,256-2*8($29)
+	sd	$23,256-3*8($29)
+	sd	$22,256-4*8($29)
+	sd	$21,256-5*8($29)
+	sd	$20,256-6*8($29)
+	sd	$19,256-7*8($29)
+	sd	$18,256-8*8($29)
+	sd	$17,256-9*8($29)
+	sd	$16,256-10*8($29)
+	dsll $23,$6,7
+	.cplocal	$6
+	.cpsetup	$25,$0,sha512_block_data_order
+	.set	reorder
+	dla	$6,K512		# PIC-ified 'load address'
+
+	ld	$1,0*8($4)		# load context
+	ld	$2,1*8($4)
+	ld	$3,2*8($4)
+	ld	$7,3*8($4)
+	ld	$24,4*8($4)
+	ld	$25,5*8($4)
+	ld	$30,6*8($4)
+	ld	$31,7*8($4)
+
+	dadd $23,$5		# pointer to the end of input
+	sd	$23,16*8($29)
+	b	.Loop
+
+.align	5
+.Loop:
+	ldl	$8,7($5)
+	ldr	$8,0($5)
+	ldl	$9,15($5)
+	ldr	$9,8($5)
+	ori	$13,$0,0xFF
+	dsll	$15,$13,32
+	or	$13,$15		# 0x000000FF000000FF
+	and	$14,$8,$13	# byte swap(0)
+	dsrl	$15,$8,24
+	dsll	$14,24
+	and	$15,$13
+	dsll	$13,8			# 0x0000FF000000FF00
+	or	$14,$15
+	and	$15,$8,$13
+	dsrl	$8,8
+	dsll	$15,8
+	and	$8,$13
+	or	$14,$15
+	or	$8,$14
+	dsrl	$14,$8,32
+	dsll	$8,32
+	or	$8,$14
+	daddu	$12,$8,$31			# 0
+	dsrl	$31,$24,14
+	xor	$15,$25,$30
+	dsll	$14,$24,23
+	and	$15,$24
+	dsrl	$13,$24,18
+	xor	$31,$14
+	dsll	$14,$24,46
+	xor	$31,$13
+	dsrl	$13,$24,41
+	xor	$31,$14
+	dsll	$14,$24,50
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$12,$15
+	ld	$15,0($6)		# K[0]
+	dsll	$14,$1,25
+	daddu	$12,$13
+	dsrl	$13,$1,34
+	xor	$31,$14
+	dsll	$14,$1,30
+	xor	$31,$13
+	dsrl	$13,$1,39
+	xor	$31,$14
+	dsll	$14,$1,36
+	xor	$31,$13
+	sd	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	daddu	$12,$15			# +=K[0]
+	daddu	$31,$14
+
+	daddu	$7,$12
+	daddu	$31,$12
+	ldl	$10,23($5)
+	ldr	$10,16($5)
+	ori	$14,$0,0xFF
+	dsll	$16,$14,32
+	or	$14,$16		# 0x000000FF000000FF
+	and	$15,$9,$14	# byte swap(1)
+	dsrl	$16,$9,24
+	dsll	$15,24
+	and	$16,$14
+	dsll	$14,8			# 0x0000FF000000FF00
+	or	$15,$16
+	and	$16,$9,$14
+	dsrl	$9,8
+	dsll	$16,8
+	and	$9,$14
+	or	$15,$16
+	or	$9,$15
+	dsrl	$15,$9,32
+	dsll	$9,32
+	or	$9,$15
+	daddu	$13,$9,$30			# 1
+	dsrl	$30,$7,14
+	xor	$16,$24,$25
+	dsll	$15,$7,23
+	and	$16,$7
+	dsrl	$14,$7,18
+	xor	$30,$15
+	dsll	$15,$7,46
+	xor	$30,$14
+	dsrl	$14,$7,41
+	xor	$30,$15
+	dsll	$15,$7,50
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$13,$16
+	ld	$16,8($6)		# K[1]
+	dsll	$15,$31,25
+	daddu	$13,$14
+	dsrl	$14,$31,34
+	xor	$30,$15
+	dsll	$15,$31,30
+	xor	$30,$14
+	dsrl	$14,$31,39
+	xor	$30,$15
+	dsll	$15,$31,36
+	xor	$30,$14
+	sd	$9,8($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	daddu	$13,$16			# +=K[1]
+	daddu	$30,$15
+
+	daddu	$3,$13
+	daddu	$30,$13
+	ldl	$11,31($5)
+	ldr	$11,24($5)
+	ori	$15,$0,0xFF
+	dsll	$17,$15,32
+	or	$15,$17		# 0x000000FF000000FF
+	and	$16,$10,$15	# byte swap(2)
+	dsrl	$17,$10,24
+	dsll	$16,24
+	and	$17,$15
+	dsll	$15,8			# 0x0000FF000000FF00
+	or	$16,$17
+	and	$17,$10,$15
+	dsrl	$10,8
+	dsll	$17,8
+	and	$10,$15
+	or	$16,$17
+	or	$10,$16
+	dsrl	$16,$10,32
+	dsll	$10,32
+	or	$10,$16
+	daddu	$14,$10,$25			# 2
+	dsrl	$25,$3,14
+	xor	$17,$7,$24
+	dsll	$16,$3,23
+	and	$17,$3
+	dsrl	$15,$3,18
+	xor	$25,$16
+	dsll	$16,$3,46
+	xor	$25,$15
+	dsrl	$15,$3,41
+	xor	$25,$16
+	dsll	$16,$3,50
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$14,$17
+	ld	$17,16($6)		# K[2]
+	dsll	$16,$30,25
+	daddu	$14,$15
+	dsrl	$15,$30,34
+	xor	$25,$16
+	dsll	$16,$30,30
+	xor	$25,$15
+	dsrl	$15,$30,39
+	xor	$25,$16
+	dsll	$16,$30,36
+	xor	$25,$15
+	sd	$10,16($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	daddu	$14,$17			# +=K[2]
+	daddu	$25,$16
+
+	daddu	$2,$14
+	daddu	$25,$14
+	ldl	$12,39($5)
+	ldr	$12,32($5)
+	ori	$16,$0,0xFF
+	dsll	$18,$16,32
+	or	$16,$18		# 0x000000FF000000FF
+	and	$17,$11,$16	# byte swap(3)
+	dsrl	$18,$11,24
+	dsll	$17,24
+	and	$18,$16
+	dsll	$16,8			# 0x0000FF000000FF00
+	or	$17,$18
+	and	$18,$11,$16
+	dsrl	$11,8
+	dsll	$18,8
+	and	$11,$16
+	or	$17,$18
+	or	$11,$17
+	dsrl	$17,$11,32
+	dsll	$11,32
+	or	$11,$17
+	daddu	$15,$11,$24			# 3
+	dsrl	$24,$2,14
+	xor	$18,$3,$7
+	dsll	$17,$2,23
+	and	$18,$2
+	dsrl	$16,$2,18
+	xor	$24,$17
+	dsll	$17,$2,46
+	xor	$24,$16
+	dsrl	$16,$2,41
+	xor	$24,$17
+	dsll	$17,$2,50
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$15,$18
+	ld	$18,24($6)		# K[3]
+	dsll	$17,$25,25
+	daddu	$15,$16
+	dsrl	$16,$25,34
+	xor	$24,$17
+	dsll	$17,$25,30
+	xor	$24,$16
+	dsrl	$16,$25,39
+	xor	$24,$17
+	dsll	$17,$25,36
+	xor	$24,$16
+	sd	$11,24($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	daddu	$15,$18			# +=K[3]
+	daddu	$24,$17
+
+	daddu	$1,$15
+	daddu	$24,$15
+	ldl	$13,47($5)
+	ldr	$13,40($5)
+	ori	$17,$0,0xFF
+	dsll	$19,$17,32
+	or	$17,$19		# 0x000000FF000000FF
+	and	$18,$12,$17	# byte swap(4)
+	dsrl	$19,$12,24
+	dsll	$18,24
+	and	$19,$17
+	dsll	$17,8			# 0x0000FF000000FF00
+	or	$18,$19
+	and	$19,$12,$17
+	dsrl	$12,8
+	dsll	$19,8
+	and	$12,$17
+	or	$18,$19
+	or	$12,$18
+	dsrl	$18,$12,32
+	dsll	$12,32
+	or	$12,$18
+	daddu	$16,$12,$7			# 4
+	dsrl	$7,$1,14
+	xor	$19,$2,$3
+	dsll	$18,$1,23
+	and	$19,$1
+	dsrl	$17,$1,18
+	xor	$7,$18
+	dsll	$18,$1,46
+	xor	$7,$17
+	dsrl	$17,$1,41
+	xor	$7,$18
+	dsll	$18,$1,50
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$16,$19
+	ld	$19,32($6)		# K[4]
+	dsll	$18,$24,25
+	daddu	$16,$17
+	dsrl	$17,$24,34
+	xor	$7,$18
+	dsll	$18,$24,30
+	xor	$7,$17
+	dsrl	$17,$24,39
+	xor	$7,$18
+	dsll	$18,$24,36
+	xor	$7,$17
+	sd	$12,32($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	daddu	$16,$19			# +=K[4]
+	daddu	$7,$18
+
+	daddu	$31,$16
+	daddu	$7,$16
+	ldl	$14,55($5)
+	ldr	$14,48($5)
+	ori	$18,$0,0xFF
+	dsll	$20,$18,32
+	or	$18,$20		# 0x000000FF000000FF
+	and	$19,$13,$18	# byte swap(5)
+	dsrl	$20,$13,24
+	dsll	$19,24
+	and	$20,$18
+	dsll	$18,8			# 0x0000FF000000FF00
+	or	$19,$20
+	and	$20,$13,$18
+	dsrl	$13,8
+	dsll	$20,8
+	and	$13,$18
+	or	$19,$20
+	or	$13,$19
+	dsrl	$19,$13,32
+	dsll	$13,32
+	or	$13,$19
+	daddu	$17,$13,$3			# 5
+	dsrl	$3,$31,14
+	xor	$20,$1,$2
+	dsll	$19,$31,23
+	and	$20,$31
+	dsrl	$18,$31,18
+	xor	$3,$19
+	dsll	$19,$31,46
+	xor	$3,$18
+	dsrl	$18,$31,41
+	xor	$3,$19
+	dsll	$19,$31,50
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$17,$20
+	ld	$20,40($6)		# K[5]
+	dsll	$19,$7,25
+	daddu	$17,$18
+	dsrl	$18,$7,34
+	xor	$3,$19
+	dsll	$19,$7,30
+	xor	$3,$18
+	dsrl	$18,$7,39
+	xor	$3,$19
+	dsll	$19,$7,36
+	xor	$3,$18
+	sd	$13,40($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	daddu	$17,$20			# +=K[5]
+	daddu	$3,$19
+
+	daddu	$30,$17
+	daddu	$3,$17
+	ldl	$15,63($5)
+	ldr	$15,56($5)
+	ori	$19,$0,0xFF
+	dsll	$21,$19,32
+	or	$19,$21		# 0x000000FF000000FF
+	and	$20,$14,$19	# byte swap(6)
+	dsrl	$21,$14,24
+	dsll	$20,24
+	and	$21,$19
+	dsll	$19,8			# 0x0000FF000000FF00
+	or	$20,$21
+	and	$21,$14,$19
+	dsrl	$14,8
+	dsll	$21,8
+	and	$14,$19
+	or	$20,$21
+	or	$14,$20
+	dsrl	$20,$14,32
+	dsll	$14,32
+	or	$14,$20
+	daddu	$18,$14,$2			# 6
+	dsrl	$2,$30,14
+	xor	$21,$31,$1
+	dsll	$20,$30,23
+	and	$21,$30
+	dsrl	$19,$30,18
+	xor	$2,$20
+	dsll	$20,$30,46
+	xor	$2,$19
+	dsrl	$19,$30,41
+	xor	$2,$20
+	dsll	$20,$30,50
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$18,$21
+	ld	$21,48($6)		# K[6]
+	dsll	$20,$3,25
+	daddu	$18,$19
+	dsrl	$19,$3,34
+	xor	$2,$20
+	dsll	$20,$3,30
+	xor	$2,$19
+	dsrl	$19,$3,39
+	xor	$2,$20
+	dsll	$20,$3,36
+	xor	$2,$19
+	sd	$14,48($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	daddu	$18,$21			# +=K[6]
+	daddu	$2,$20
+
+	daddu	$25,$18
+	daddu	$2,$18
+	ldl	$16,71($5)
+	ldr	$16,64($5)
+	ori	$20,$0,0xFF
+	dsll	$22,$20,32
+	or	$20,$22		# 0x000000FF000000FF
+	and	$21,$15,$20	# byte swap(7)
+	dsrl	$22,$15,24
+	dsll	$21,24
+	and	$22,$20
+	dsll	$20,8			# 0x0000FF000000FF00
+	or	$21,$22
+	and	$22,$15,$20
+	dsrl	$15,8
+	dsll	$22,8
+	and	$15,$20
+	or	$21,$22
+	or	$15,$21
+	dsrl	$21,$15,32
+	dsll	$15,32
+	or	$15,$21
+	daddu	$19,$15,$1			# 7
+	dsrl	$1,$25,14
+	xor	$22,$30,$31
+	dsll	$21,$25,23
+	and	$22,$25
+	dsrl	$20,$25,18
+	xor	$1,$21
+	dsll	$21,$25,46
+	xor	$1,$20
+	dsrl	$20,$25,41
+	xor	$1,$21
+	dsll	$21,$25,50
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$19,$22
+	ld	$22,56($6)		# K[7]
+	dsll	$21,$2,25
+	daddu	$19,$20
+	dsrl	$20,$2,34
+	xor	$1,$21
+	dsll	$21,$2,30
+	xor	$1,$20
+	dsrl	$20,$2,39
+	xor	$1,$21
+	dsll	$21,$2,36
+	xor	$1,$20
+	sd	$15,56($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	daddu	$19,$22			# +=K[7]
+	daddu	$1,$21
+
+	daddu	$24,$19
+	daddu	$1,$19
+	ldl	$17,79($5)
+	ldr	$17,72($5)
+	ori	$21,$0,0xFF
+	dsll	$23,$21,32
+	or	$21,$23		# 0x000000FF000000FF
+	and	$22,$16,$21	# byte swap(8)
+	dsrl	$23,$16,24
+	dsll	$22,24
+	and	$23,$21
+	dsll	$21,8			# 0x0000FF000000FF00
+	or	$22,$23
+	and	$23,$16,$21
+	dsrl	$16,8
+	dsll	$23,8
+	and	$16,$21
+	or	$22,$23
+	or	$16,$22
+	dsrl	$22,$16,32
+	dsll	$16,32
+	or	$16,$22
+	daddu	$20,$16,$31			# 8
+	dsrl	$31,$24,14
+	xor	$23,$25,$30
+	dsll	$22,$24,23
+	and	$23,$24
+	dsrl	$21,$24,18
+	xor	$31,$22
+	dsll	$22,$24,46
+	xor	$31,$21
+	dsrl	$21,$24,41
+	xor	$31,$22
+	dsll	$22,$24,50
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$20,$23
+	ld	$23,64($6)		# K[8]
+	dsll	$22,$1,25
+	daddu	$20,$21
+	dsrl	$21,$1,34
+	xor	$31,$22
+	dsll	$22,$1,30
+	xor	$31,$21
+	dsrl	$21,$1,39
+	xor	$31,$22
+	dsll	$22,$1,36
+	xor	$31,$21
+	sd	$16,64($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	daddu	$20,$23			# +=K[8]
+	daddu	$31,$22
+
+	daddu	$7,$20
+	daddu	$31,$20
+	ldl	$18,87($5)
+	ldr	$18,80($5)
+	ori	$22,$0,0xFF
+	dsll	$8,$22,32
+	or	$22,$8		# 0x000000FF000000FF
+	and	$23,$17,$22	# byte swap(9)
+	dsrl	$8,$17,24
+	dsll	$23,24
+	and	$8,$22
+	dsll	$22,8			# 0x0000FF000000FF00
+	or	$23,$8
+	and	$8,$17,$22
+	dsrl	$17,8
+	dsll	$8,8
+	and	$17,$22
+	or	$23,$8
+	or	$17,$23
+	dsrl	$23,$17,32
+	dsll	$17,32
+	or	$17,$23
+	daddu	$21,$17,$30			# 9
+	dsrl	$30,$7,14
+	xor	$8,$24,$25
+	dsll	$23,$7,23
+	and	$8,$7
+	dsrl	$22,$7,18
+	xor	$30,$23
+	dsll	$23,$7,46
+	xor	$30,$22
+	dsrl	$22,$7,41
+	xor	$30,$23
+	dsll	$23,$7,50
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$21,$8
+	ld	$8,72($6)		# K[9]
+	dsll	$23,$31,25
+	daddu	$21,$22
+	dsrl	$22,$31,34
+	xor	$30,$23
+	dsll	$23,$31,30
+	xor	$30,$22
+	dsrl	$22,$31,39
+	xor	$30,$23
+	dsll	$23,$31,36
+	xor	$30,$22
+	sd	$17,72($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	daddu	$21,$8			# +=K[9]
+	daddu	$30,$23
+
+	daddu	$3,$21
+	daddu	$30,$21
+	ldl	$19,95($5)
+	ldr	$19,88($5)
+	ori	$23,$0,0xFF
+	dsll	$9,$23,32
+	or	$23,$9		# 0x000000FF000000FF
+	and	$8,$18,$23	# byte swap(10)
+	dsrl	$9,$18,24
+	dsll	$8,24
+	and	$9,$23
+	dsll	$23,8			# 0x0000FF000000FF00
+	or	$8,$9
+	and	$9,$18,$23
+	dsrl	$18,8
+	dsll	$9,8
+	and	$18,$23
+	or	$8,$9
+	or	$18,$8
+	dsrl	$8,$18,32
+	dsll	$18,32
+	or	$18,$8
+	daddu	$22,$18,$25			# 10
+	dsrl	$25,$3,14
+	xor	$9,$7,$24
+	dsll	$8,$3,23
+	and	$9,$3
+	dsrl	$23,$3,18
+	xor	$25,$8
+	dsll	$8,$3,46
+	xor	$25,$23
+	dsrl	$23,$3,41
+	xor	$25,$8
+	dsll	$8,$3,50
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$22,$9
+	ld	$9,80($6)		# K[10]
+	dsll	$8,$30,25
+	daddu	$22,$23
+	dsrl	$23,$30,34
+	xor	$25,$8
+	dsll	$8,$30,30
+	xor	$25,$23
+	dsrl	$23,$30,39
+	xor	$25,$8
+	dsll	$8,$30,36
+	xor	$25,$23
+	sd	$18,80($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	daddu	$22,$9			# +=K[10]
+	daddu	$25,$8
+
+	daddu	$2,$22
+	daddu	$25,$22
+	ldl	$20,103($5)
+	ldr	$20,96($5)
+	ori	$8,$0,0xFF
+	dsll	$10,$8,32
+	or	$8,$10		# 0x000000FF000000FF
+	and	$9,$19,$8	# byte swap(11)
+	dsrl	$10,$19,24
+	dsll	$9,24
+	and	$10,$8
+	dsll	$8,8			# 0x0000FF000000FF00
+	or	$9,$10
+	and	$10,$19,$8
+	dsrl	$19,8
+	dsll	$10,8
+	and	$19,$8
+	or	$9,$10
+	or	$19,$9
+	dsrl	$9,$19,32
+	dsll	$19,32
+	or	$19,$9
+	daddu	$23,$19,$24			# 11
+	dsrl	$24,$2,14
+	xor	$10,$3,$7
+	dsll	$9,$2,23
+	and	$10,$2
+	dsrl	$8,$2,18
+	xor	$24,$9
+	dsll	$9,$2,46
+	xor	$24,$8
+	dsrl	$8,$2,41
+	xor	$24,$9
+	dsll	$9,$2,50
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$23,$10
+	ld	$10,88($6)		# K[11]
+	dsll	$9,$25,25
+	daddu	$23,$8
+	dsrl	$8,$25,34
+	xor	$24,$9
+	dsll	$9,$25,30
+	xor	$24,$8
+	dsrl	$8,$25,39
+	xor	$24,$9
+	dsll	$9,$25,36
+	xor	$24,$8
+	sd	$19,88($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	daddu	$23,$10			# +=K[11]
+	daddu	$24,$9
+
+	daddu	$1,$23
+	daddu	$24,$23
+	ldl	$21,111($5)
+	ldr	$21,104($5)
+	ori	$9,$0,0xFF
+	dsll	$11,$9,32
+	or	$9,$11		# 0x000000FF000000FF
+	and	$10,$20,$9	# byte swap(12)
+	dsrl	$11,$20,24
+	dsll	$10,24
+	and	$11,$9
+	dsll	$9,8			# 0x0000FF000000FF00
+	or	$10,$11
+	and	$11,$20,$9
+	dsrl	$20,8
+	dsll	$11,8
+	and	$20,$9
+	or	$10,$11
+	or	$20,$10
+	dsrl	$10,$20,32
+	dsll	$20,32
+	or	$20,$10
+	daddu	$8,$20,$7			# 12
+	dsrl	$7,$1,14
+	xor	$11,$2,$3
+	dsll	$10,$1,23
+	and	$11,$1
+	dsrl	$9,$1,18
+	xor	$7,$10
+	dsll	$10,$1,46
+	xor	$7,$9
+	dsrl	$9,$1,41
+	xor	$7,$10
+	dsll	$10,$1,50
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$8,$11
+	ld	$11,96($6)		# K[12]
+	dsll	$10,$24,25
+	daddu	$8,$9
+	dsrl	$9,$24,34
+	xor	$7,$10
+	dsll	$10,$24,30
+	xor	$7,$9
+	dsrl	$9,$24,39
+	xor	$7,$10
+	dsll	$10,$24,36
+	xor	$7,$9
+	sd	$20,96($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	daddu	$8,$11			# +=K[12]
+	daddu	$7,$10
+
+	daddu	$31,$8
+	daddu	$7,$8
+	ldl	$22,119($5)
+	ldr	$22,112($5)
+	ori	$10,$0,0xFF
+	dsll	$12,$10,32
+	or	$10,$12		# 0x000000FF000000FF
+	and	$11,$21,$10	# byte swap(13)
+	dsrl	$12,$21,24
+	dsll	$11,24
+	and	$12,$10
+	dsll	$10,8			# 0x0000FF000000FF00
+	or	$11,$12
+	and	$12,$21,$10
+	dsrl	$21,8
+	dsll	$12,8
+	and	$21,$10
+	or	$11,$12
+	or	$21,$11
+	dsrl	$11,$21,32
+	dsll	$21,32
+	or	$21,$11
+	daddu	$9,$21,$3			# 13
+	dsrl	$3,$31,14
+	xor	$12,$1,$2
+	dsll	$11,$31,23
+	and	$12,$31
+	dsrl	$10,$31,18
+	xor	$3,$11
+	dsll	$11,$31,46
+	xor	$3,$10
+	dsrl	$10,$31,41
+	xor	$3,$11
+	dsll	$11,$31,50
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$9,$12
+	ld	$12,104($6)		# K[13]
+	dsll	$11,$7,25
+	daddu	$9,$10
+	dsrl	$10,$7,34
+	xor	$3,$11
+	dsll	$11,$7,30
+	xor	$3,$10
+	dsrl	$10,$7,39
+	xor	$3,$11
+	dsll	$11,$7,36
+	xor	$3,$10
+	sd	$21,104($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	daddu	$9,$12			# +=K[13]
+	daddu	$3,$11
+
+	daddu	$30,$9
+	daddu	$3,$9
+	ld	$8,0($29)	# prefetch from ring buffer
+	ldl	$23,127($5)
+	ldr	$23,120($5)
+	ori	$11,$0,0xFF
+	dsll	$13,$11,32
+	or	$11,$13		# 0x000000FF000000FF
+	and	$12,$22,$11	# byte swap(14)
+	dsrl	$13,$22,24
+	dsll	$12,24
+	and	$13,$11
+	dsll	$11,8			# 0x0000FF000000FF00
+	or	$12,$13
+	and	$13,$22,$11
+	dsrl	$22,8
+	dsll	$13,8
+	and	$22,$11
+	or	$12,$13
+	or	$22,$12
+	dsrl	$12,$22,32
+	dsll	$22,32
+	or	$22,$12
+	daddu	$10,$22,$2			# 14
+	dsrl	$2,$30,14
+	xor	$13,$31,$1
+	dsll	$12,$30,23
+	and	$13,$30
+	dsrl	$11,$30,18
+	xor	$2,$12
+	dsll	$12,$30,46
+	xor	$2,$11
+	dsrl	$11,$30,41
+	xor	$2,$12
+	dsll	$12,$30,50
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$10,$13
+	ld	$13,112($6)		# K[14]
+	dsll	$12,$3,25
+	daddu	$10,$11
+	dsrl	$11,$3,34
+	xor	$2,$12
+	dsll	$12,$3,30
+	xor	$2,$11
+	dsrl	$11,$3,39
+	xor	$2,$12
+	dsll	$12,$3,36
+	xor	$2,$11
+	sd	$22,112($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	daddu	$10,$13			# +=K[14]
+	daddu	$2,$12
+
+	daddu	$25,$10
+	daddu	$2,$10
+	ld	$9,8($29)	# prefetch from ring buffer
+	ori	$12,$0,0xFF
+	dsll	$14,$12,32
+	or	$12,$14		# 0x000000FF000000FF
+	and	$13,$23,$12	# byte swap(15)
+	dsrl	$14,$23,24
+	dsll	$13,24
+	and	$14,$12
+	dsll	$12,8			# 0x0000FF000000FF00
+	or	$13,$14
+	and	$14,$23,$12
+	dsrl	$23,8
+	dsll	$14,8
+	and	$23,$12
+	or	$13,$14
+	or	$23,$13
+	dsrl	$13,$23,32
+	dsll	$23,32
+	or	$23,$13
+	daddu	$11,$23,$1			# 15
+	dsrl	$1,$25,14
+	xor	$14,$30,$31
+	dsll	$13,$25,23
+	and	$14,$25
+	dsrl	$12,$25,18
+	xor	$1,$13
+	dsll	$13,$25,46
+	xor	$1,$12
+	dsrl	$12,$25,41
+	xor	$1,$13
+	dsll	$13,$25,50
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$11,$14
+	ld	$14,120($6)		# K[15]
+	dsll	$13,$2,25
+	daddu	$11,$12
+	dsrl	$12,$2,34
+	xor	$1,$13
+	dsll	$13,$2,30
+	xor	$1,$12
+	dsrl	$12,$2,39
+	xor	$1,$13
+	dsll	$13,$2,36
+	xor	$1,$12
+	sd	$23,120($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	daddu	$11,$14			# +=K[15]
+	daddu	$1,$13
+
+	daddu	$24,$11
+	daddu	$1,$11
+	ld	$10,16($29)	# prefetch from ring buffer
+	b	.L16_xx
+.align	4
+.L16_xx:
+	dsrl	$14,$9,7		# Xupdate(16)
+	daddu	$8,$17			# +=X[i+9]
+	dsll	$13,$9,56
+	dsrl	$12,$9,1
+	xor	$14,$13
+	dsll	$13,7
+	xor	$14,$12
+	dsrl	$12,$9,8
+	xor	$14,$13
+
+	dsrl	$15,$22,6
+	xor	$14,$12			# sigma0(X[i+1])
+	dsll	$13,$22,3
+	daddu	$8,$14
+	dsrl	$12,$22,19
+	xor	$15,$13
+	dsll	$13,42
+	xor	$15,$12
+	dsrl	$12,$22,61
+	xor	$15,$13
+
+	xor	$15,$12			# sigma1(X[i+14])
+	daddu	$8,$15
+	daddu	$12,$8,$31			# 16
+	dsrl	$31,$24,14
+	xor	$15,$25,$30
+	dsll	$14,$24,23
+	and	$15,$24
+	dsrl	$13,$24,18
+	xor	$31,$14
+	dsll	$14,$24,46
+	xor	$31,$13
+	dsrl	$13,$24,41
+	xor	$31,$14
+	dsll	$14,$24,50
+	xor	$31,$13
+	xor	$15,$30			# Ch(e,f,g)
+	xor	$13,$14,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$12,$15
+	ld	$15,128($6)		# K[16]
+	dsll	$14,$1,25
+	daddu	$12,$13
+	dsrl	$13,$1,34
+	xor	$31,$14
+	dsll	$14,$1,30
+	xor	$31,$13
+	dsrl	$13,$1,39
+	xor	$31,$14
+	dsll	$14,$1,36
+	xor	$31,$13
+	sd	$8,0($29)	# offload to ring buffer
+	xor	$31,$14			# Sigma0(a)
+
+	or	$13,$1,$2
+	and	$14,$1,$2
+	and	$13,$3
+	or	$14,$13			# Maj(a,b,c)
+	daddu	$12,$15			# +=K[16]
+	daddu	$31,$14
+
+	daddu	$7,$12
+	daddu	$31,$12
+	ld	$11,24($29)	# prefetch from ring buffer
+	dsrl	$15,$10,7		# Xupdate(17)
+	daddu	$9,$18			# +=X[i+9]
+	dsll	$14,$10,56
+	dsrl	$13,$10,1
+	xor	$15,$14
+	dsll	$14,7
+	xor	$15,$13
+	dsrl	$13,$10,8
+	xor	$15,$14
+
+	dsrl	$16,$23,6
+	xor	$15,$13			# sigma0(X[i+1])
+	dsll	$14,$23,3
+	daddu	$9,$15
+	dsrl	$13,$23,19
+	xor	$16,$14
+	dsll	$14,42
+	xor	$16,$13
+	dsrl	$13,$23,61
+	xor	$16,$14
+
+	xor	$16,$13			# sigma1(X[i+14])
+	daddu	$9,$16
+	daddu	$13,$9,$30			# 17
+	dsrl	$30,$7,14
+	xor	$16,$24,$25
+	dsll	$15,$7,23
+	and	$16,$7
+	dsrl	$14,$7,18
+	xor	$30,$15
+	dsll	$15,$7,46
+	xor	$30,$14
+	dsrl	$14,$7,41
+	xor	$30,$15
+	dsll	$15,$7,50
+	xor	$30,$14
+	xor	$16,$25			# Ch(e,f,g)
+	xor	$14,$15,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$13,$16
+	ld	$16,136($6)		# K[17]
+	dsll	$15,$31,25
+	daddu	$13,$14
+	dsrl	$14,$31,34
+	xor	$30,$15
+	dsll	$15,$31,30
+	xor	$30,$14
+	dsrl	$14,$31,39
+	xor	$30,$15
+	dsll	$15,$31,36
+	xor	$30,$14
+	sd	$9,8($29)	# offload to ring buffer
+	xor	$30,$15			# Sigma0(a)
+
+	or	$14,$31,$1
+	and	$15,$31,$1
+	and	$14,$2
+	or	$15,$14			# Maj(a,b,c)
+	daddu	$13,$16			# +=K[17]
+	daddu	$30,$15
+
+	daddu	$3,$13
+	daddu	$30,$13
+	ld	$12,32($29)	# prefetch from ring buffer
+	dsrl	$16,$11,7		# Xupdate(18)
+	daddu	$10,$19			# +=X[i+9]
+	dsll	$15,$11,56
+	dsrl	$14,$11,1
+	xor	$16,$15
+	dsll	$15,7
+	xor	$16,$14
+	dsrl	$14,$11,8
+	xor	$16,$15
+
+	dsrl	$17,$8,6
+	xor	$16,$14			# sigma0(X[i+1])
+	dsll	$15,$8,3
+	daddu	$10,$16
+	dsrl	$14,$8,19
+	xor	$17,$15
+	dsll	$15,42
+	xor	$17,$14
+	dsrl	$14,$8,61
+	xor	$17,$15
+
+	xor	$17,$14			# sigma1(X[i+14])
+	daddu	$10,$17
+	daddu	$14,$10,$25			# 18
+	dsrl	$25,$3,14
+	xor	$17,$7,$24
+	dsll	$16,$3,23
+	and	$17,$3
+	dsrl	$15,$3,18
+	xor	$25,$16
+	dsll	$16,$3,46
+	xor	$25,$15
+	dsrl	$15,$3,41
+	xor	$25,$16
+	dsll	$16,$3,50
+	xor	$25,$15
+	xor	$17,$24			# Ch(e,f,g)
+	xor	$15,$16,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$14,$17
+	ld	$17,144($6)		# K[18]
+	dsll	$16,$30,25
+	daddu	$14,$15
+	dsrl	$15,$30,34
+	xor	$25,$16
+	dsll	$16,$30,30
+	xor	$25,$15
+	dsrl	$15,$30,39
+	xor	$25,$16
+	dsll	$16,$30,36
+	xor	$25,$15
+	sd	$10,16($29)	# offload to ring buffer
+	xor	$25,$16			# Sigma0(a)
+
+	or	$15,$30,$31
+	and	$16,$30,$31
+	and	$15,$1
+	or	$16,$15			# Maj(a,b,c)
+	daddu	$14,$17			# +=K[18]
+	daddu	$25,$16
+
+	daddu	$2,$14
+	daddu	$25,$14
+	ld	$13,40($29)	# prefetch from ring buffer
+	dsrl	$17,$12,7		# Xupdate(19)
+	daddu	$11,$20			# +=X[i+9]
+	dsll	$16,$12,56
+	dsrl	$15,$12,1
+	xor	$17,$16
+	dsll	$16,7
+	xor	$17,$15
+	dsrl	$15,$12,8
+	xor	$17,$16
+
+	dsrl	$18,$9,6
+	xor	$17,$15			# sigma0(X[i+1])
+	dsll	$16,$9,3
+	daddu	$11,$17
+	dsrl	$15,$9,19
+	xor	$18,$16
+	dsll	$16,42
+	xor	$18,$15
+	dsrl	$15,$9,61
+	xor	$18,$16
+
+	xor	$18,$15			# sigma1(X[i+14])
+	daddu	$11,$18
+	daddu	$15,$11,$24			# 19
+	dsrl	$24,$2,14
+	xor	$18,$3,$7
+	dsll	$17,$2,23
+	and	$18,$2
+	dsrl	$16,$2,18
+	xor	$24,$17
+	dsll	$17,$2,46
+	xor	$24,$16
+	dsrl	$16,$2,41
+	xor	$24,$17
+	dsll	$17,$2,50
+	xor	$24,$16
+	xor	$18,$7			# Ch(e,f,g)
+	xor	$16,$17,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$15,$18
+	ld	$18,152($6)		# K[19]
+	dsll	$17,$25,25
+	daddu	$15,$16
+	dsrl	$16,$25,34
+	xor	$24,$17
+	dsll	$17,$25,30
+	xor	$24,$16
+	dsrl	$16,$25,39
+	xor	$24,$17
+	dsll	$17,$25,36
+	xor	$24,$16
+	sd	$11,24($29)	# offload to ring buffer
+	xor	$24,$17			# Sigma0(a)
+
+	or	$16,$25,$30
+	and	$17,$25,$30
+	and	$16,$31
+	or	$17,$16			# Maj(a,b,c)
+	daddu	$15,$18			# +=K[19]
+	daddu	$24,$17
+
+	daddu	$1,$15
+	daddu	$24,$15
+	ld	$14,48($29)	# prefetch from ring buffer
+	dsrl	$18,$13,7		# Xupdate(20)
+	daddu	$12,$21			# +=X[i+9]
+	dsll	$17,$13,56
+	dsrl	$16,$13,1
+	xor	$18,$17
+	dsll	$17,7
+	xor	$18,$16
+	dsrl	$16,$13,8
+	xor	$18,$17
+
+	dsrl	$19,$10,6
+	xor	$18,$16			# sigma0(X[i+1])
+	dsll	$17,$10,3
+	daddu	$12,$18
+	dsrl	$16,$10,19
+	xor	$19,$17
+	dsll	$17,42
+	xor	$19,$16
+	dsrl	$16,$10,61
+	xor	$19,$17
+
+	xor	$19,$16			# sigma1(X[i+14])
+	daddu	$12,$19
+	daddu	$16,$12,$7			# 20
+	dsrl	$7,$1,14
+	xor	$19,$2,$3
+	dsll	$18,$1,23
+	and	$19,$1
+	dsrl	$17,$1,18
+	xor	$7,$18
+	dsll	$18,$1,46
+	xor	$7,$17
+	dsrl	$17,$1,41
+	xor	$7,$18
+	dsll	$18,$1,50
+	xor	$7,$17
+	xor	$19,$3			# Ch(e,f,g)
+	xor	$17,$18,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$16,$19
+	ld	$19,160($6)		# K[20]
+	dsll	$18,$24,25
+	daddu	$16,$17
+	dsrl	$17,$24,34
+	xor	$7,$18
+	dsll	$18,$24,30
+	xor	$7,$17
+	dsrl	$17,$24,39
+	xor	$7,$18
+	dsll	$18,$24,36
+	xor	$7,$17
+	sd	$12,32($29)	# offload to ring buffer
+	xor	$7,$18			# Sigma0(a)
+
+	or	$17,$24,$25
+	and	$18,$24,$25
+	and	$17,$30
+	or	$18,$17			# Maj(a,b,c)
+	daddu	$16,$19			# +=K[20]
+	daddu	$7,$18
+
+	daddu	$31,$16
+	daddu	$7,$16
+	ld	$15,56($29)	# prefetch from ring buffer
+	dsrl	$19,$14,7		# Xupdate(21)
+	daddu	$13,$22			# +=X[i+9]
+	dsll	$18,$14,56
+	dsrl	$17,$14,1
+	xor	$19,$18
+	dsll	$18,7
+	xor	$19,$17
+	dsrl	$17,$14,8
+	xor	$19,$18
+
+	dsrl	$20,$11,6
+	xor	$19,$17			# sigma0(X[i+1])
+	dsll	$18,$11,3
+	daddu	$13,$19
+	dsrl	$17,$11,19
+	xor	$20,$18
+	dsll	$18,42
+	xor	$20,$17
+	dsrl	$17,$11,61
+	xor	$20,$18
+
+	xor	$20,$17			# sigma1(X[i+14])
+	daddu	$13,$20
+	daddu	$17,$13,$3			# 21
+	dsrl	$3,$31,14
+	xor	$20,$1,$2
+	dsll	$19,$31,23
+	and	$20,$31
+	dsrl	$18,$31,18
+	xor	$3,$19
+	dsll	$19,$31,46
+	xor	$3,$18
+	dsrl	$18,$31,41
+	xor	$3,$19
+	dsll	$19,$31,50
+	xor	$3,$18
+	xor	$20,$2			# Ch(e,f,g)
+	xor	$18,$19,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$17,$20
+	ld	$20,168($6)		# K[21]
+	dsll	$19,$7,25
+	daddu	$17,$18
+	dsrl	$18,$7,34
+	xor	$3,$19
+	dsll	$19,$7,30
+	xor	$3,$18
+	dsrl	$18,$7,39
+	xor	$3,$19
+	dsll	$19,$7,36
+	xor	$3,$18
+	sd	$13,40($29)	# offload to ring buffer
+	xor	$3,$19			# Sigma0(a)
+
+	or	$18,$7,$24
+	and	$19,$7,$24
+	and	$18,$25
+	or	$19,$18			# Maj(a,b,c)
+	daddu	$17,$20			# +=K[21]
+	daddu	$3,$19
+
+	daddu	$30,$17
+	daddu	$3,$17
+	ld	$16,64($29)	# prefetch from ring buffer
+	dsrl	$20,$15,7		# Xupdate(22)
+	daddu	$14,$23			# +=X[i+9]
+	dsll	$19,$15,56
+	dsrl	$18,$15,1
+	xor	$20,$19
+	dsll	$19,7
+	xor	$20,$18
+	dsrl	$18,$15,8
+	xor	$20,$19
+
+	dsrl	$21,$12,6
+	xor	$20,$18			# sigma0(X[i+1])
+	dsll	$19,$12,3
+	daddu	$14,$20
+	dsrl	$18,$12,19
+	xor	$21,$19
+	dsll	$19,42
+	xor	$21,$18
+	dsrl	$18,$12,61
+	xor	$21,$19
+
+	xor	$21,$18			# sigma1(X[i+14])
+	daddu	$14,$21
+	daddu	$18,$14,$2			# 22
+	dsrl	$2,$30,14
+	xor	$21,$31,$1
+	dsll	$20,$30,23
+	and	$21,$30
+	dsrl	$19,$30,18
+	xor	$2,$20
+	dsll	$20,$30,46
+	xor	$2,$19
+	dsrl	$19,$30,41
+	xor	$2,$20
+	dsll	$20,$30,50
+	xor	$2,$19
+	xor	$21,$1			# Ch(e,f,g)
+	xor	$19,$20,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$18,$21
+	ld	$21,176($6)		# K[22]
+	dsll	$20,$3,25
+	daddu	$18,$19
+	dsrl	$19,$3,34
+	xor	$2,$20
+	dsll	$20,$3,30
+	xor	$2,$19
+	dsrl	$19,$3,39
+	xor	$2,$20
+	dsll	$20,$3,36
+	xor	$2,$19
+	sd	$14,48($29)	# offload to ring buffer
+	xor	$2,$20			# Sigma0(a)
+
+	or	$19,$3,$7
+	and	$20,$3,$7
+	and	$19,$24
+	or	$20,$19			# Maj(a,b,c)
+	daddu	$18,$21			# +=K[22]
+	daddu	$2,$20
+
+	daddu	$25,$18
+	daddu	$2,$18
+	ld	$17,72($29)	# prefetch from ring buffer
+	dsrl	$21,$16,7		# Xupdate(23)
+	daddu	$15,$8			# +=X[i+9]
+	dsll	$20,$16,56
+	dsrl	$19,$16,1
+	xor	$21,$20
+	dsll	$20,7
+	xor	$21,$19
+	dsrl	$19,$16,8
+	xor	$21,$20
+
+	dsrl	$22,$13,6
+	xor	$21,$19			# sigma0(X[i+1])
+	dsll	$20,$13,3
+	daddu	$15,$21
+	dsrl	$19,$13,19
+	xor	$22,$20
+	dsll	$20,42
+	xor	$22,$19
+	dsrl	$19,$13,61
+	xor	$22,$20
+
+	xor	$22,$19			# sigma1(X[i+14])
+	daddu	$15,$22
+	daddu	$19,$15,$1			# 23
+	dsrl	$1,$25,14
+	xor	$22,$30,$31
+	dsll	$21,$25,23
+	and	$22,$25
+	dsrl	$20,$25,18
+	xor	$1,$21
+	dsll	$21,$25,46
+	xor	$1,$20
+	dsrl	$20,$25,41
+	xor	$1,$21
+	dsll	$21,$25,50
+	xor	$1,$20
+	xor	$22,$31			# Ch(e,f,g)
+	xor	$20,$21,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$19,$22
+	ld	$22,184($6)		# K[23]
+	dsll	$21,$2,25
+	daddu	$19,$20
+	dsrl	$20,$2,34
+	xor	$1,$21
+	dsll	$21,$2,30
+	xor	$1,$20
+	dsrl	$20,$2,39
+	xor	$1,$21
+	dsll	$21,$2,36
+	xor	$1,$20
+	sd	$15,56($29)	# offload to ring buffer
+	xor	$1,$21			# Sigma0(a)
+
+	or	$20,$2,$3
+	and	$21,$2,$3
+	and	$20,$7
+	or	$21,$20			# Maj(a,b,c)
+	daddu	$19,$22			# +=K[23]
+	daddu	$1,$21
+
+	daddu	$24,$19
+	daddu	$1,$19
+	ld	$18,80($29)	# prefetch from ring buffer
+	dsrl	$22,$17,7		# Xupdate(24)
+	daddu	$16,$9			# +=X[i+9]
+	dsll	$21,$17,56
+	dsrl	$20,$17,1
+	xor	$22,$21
+	dsll	$21,7
+	xor	$22,$20
+	dsrl	$20,$17,8
+	xor	$22,$21
+
+	dsrl	$23,$14,6
+	xor	$22,$20			# sigma0(X[i+1])
+	dsll	$21,$14,3
+	daddu	$16,$22
+	dsrl	$20,$14,19
+	xor	$23,$21
+	dsll	$21,42
+	xor	$23,$20
+	dsrl	$20,$14,61
+	xor	$23,$21
+
+	xor	$23,$20			# sigma1(X[i+14])
+	daddu	$16,$23
+	daddu	$20,$16,$31			# 24
+	dsrl	$31,$24,14
+	xor	$23,$25,$30
+	dsll	$22,$24,23
+	and	$23,$24
+	dsrl	$21,$24,18
+	xor	$31,$22
+	dsll	$22,$24,46
+	xor	$31,$21
+	dsrl	$21,$24,41
+	xor	$31,$22
+	dsll	$22,$24,50
+	xor	$31,$21
+	xor	$23,$30			# Ch(e,f,g)
+	xor	$21,$22,$31			# Sigma1(e)
+
+	dsrl	$31,$1,28
+	daddu	$20,$23
+	ld	$23,192($6)		# K[24]
+	dsll	$22,$1,25
+	daddu	$20,$21
+	dsrl	$21,$1,34
+	xor	$31,$22
+	dsll	$22,$1,30
+	xor	$31,$21
+	dsrl	$21,$1,39
+	xor	$31,$22
+	dsll	$22,$1,36
+	xor	$31,$21
+	sd	$16,64($29)	# offload to ring buffer
+	xor	$31,$22			# Sigma0(a)
+
+	or	$21,$1,$2
+	and	$22,$1,$2
+	and	$21,$3
+	or	$22,$21			# Maj(a,b,c)
+	daddu	$20,$23			# +=K[24]
+	daddu	$31,$22
+
+	daddu	$7,$20
+	daddu	$31,$20
+	ld	$19,88($29)	# prefetch from ring buffer
+	dsrl	$23,$18,7		# Xupdate(25)
+	daddu	$17,$10			# +=X[i+9]
+	dsll	$22,$18,56
+	dsrl	$21,$18,1
+	xor	$23,$22
+	dsll	$22,7
+	xor	$23,$21
+	dsrl	$21,$18,8
+	xor	$23,$22
+
+	dsrl	$8,$15,6
+	xor	$23,$21			# sigma0(X[i+1])
+	dsll	$22,$15,3
+	daddu	$17,$23
+	dsrl	$21,$15,19
+	xor	$8,$22
+	dsll	$22,42
+	xor	$8,$21
+	dsrl	$21,$15,61
+	xor	$8,$22
+
+	xor	$8,$21			# sigma1(X[i+14])
+	daddu	$17,$8
+	daddu	$21,$17,$30			# 25
+	dsrl	$30,$7,14
+	xor	$8,$24,$25
+	dsll	$23,$7,23
+	and	$8,$7
+	dsrl	$22,$7,18
+	xor	$30,$23
+	dsll	$23,$7,46
+	xor	$30,$22
+	dsrl	$22,$7,41
+	xor	$30,$23
+	dsll	$23,$7,50
+	xor	$30,$22
+	xor	$8,$25			# Ch(e,f,g)
+	xor	$22,$23,$30			# Sigma1(e)
+
+	dsrl	$30,$31,28
+	daddu	$21,$8
+	ld	$8,200($6)		# K[25]
+	dsll	$23,$31,25
+	daddu	$21,$22
+	dsrl	$22,$31,34
+	xor	$30,$23
+	dsll	$23,$31,30
+	xor	$30,$22
+	dsrl	$22,$31,39
+	xor	$30,$23
+	dsll	$23,$31,36
+	xor	$30,$22
+	sd	$17,72($29)	# offload to ring buffer
+	xor	$30,$23			# Sigma0(a)
+
+	or	$22,$31,$1
+	and	$23,$31,$1
+	and	$22,$2
+	or	$23,$22			# Maj(a,b,c)
+	daddu	$21,$8			# +=K[25]
+	daddu	$30,$23
+
+	daddu	$3,$21
+	daddu	$30,$21
+	ld	$20,96($29)	# prefetch from ring buffer
+	dsrl	$8,$19,7		# Xupdate(26)
+	daddu	$18,$11			# +=X[i+9]
+	dsll	$23,$19,56
+	dsrl	$22,$19,1
+	xor	$8,$23
+	dsll	$23,7
+	xor	$8,$22
+	dsrl	$22,$19,8
+	xor	$8,$23
+
+	dsrl	$9,$16,6
+	xor	$8,$22			# sigma0(X[i+1])
+	dsll	$23,$16,3
+	daddu	$18,$8
+	dsrl	$22,$16,19
+	xor	$9,$23
+	dsll	$23,42
+	xor	$9,$22
+	dsrl	$22,$16,61
+	xor	$9,$23
+
+	xor	$9,$22			# sigma1(X[i+14])
+	daddu	$18,$9
+	daddu	$22,$18,$25			# 26
+	dsrl	$25,$3,14
+	xor	$9,$7,$24
+	dsll	$8,$3,23
+	and	$9,$3
+	dsrl	$23,$3,18
+	xor	$25,$8
+	dsll	$8,$3,46
+	xor	$25,$23
+	dsrl	$23,$3,41
+	xor	$25,$8
+	dsll	$8,$3,50
+	xor	$25,$23
+	xor	$9,$24			# Ch(e,f,g)
+	xor	$23,$8,$25			# Sigma1(e)
+
+	dsrl	$25,$30,28
+	daddu	$22,$9
+	ld	$9,208($6)		# K[26]
+	dsll	$8,$30,25
+	daddu	$22,$23
+	dsrl	$23,$30,34
+	xor	$25,$8
+	dsll	$8,$30,30
+	xor	$25,$23
+	dsrl	$23,$30,39
+	xor	$25,$8
+	dsll	$8,$30,36
+	xor	$25,$23
+	sd	$18,80($29)	# offload to ring buffer
+	xor	$25,$8			# Sigma0(a)
+
+	or	$23,$30,$31
+	and	$8,$30,$31
+	and	$23,$1
+	or	$8,$23			# Maj(a,b,c)
+	daddu	$22,$9			# +=K[26]
+	daddu	$25,$8
+
+	daddu	$2,$22
+	daddu	$25,$22
+	ld	$21,104($29)	# prefetch from ring buffer
+	dsrl	$9,$20,7		# Xupdate(27)
+	daddu	$19,$12			# +=X[i+9]
+	dsll	$8,$20,56
+	dsrl	$23,$20,1
+	xor	$9,$8
+	dsll	$8,7
+	xor	$9,$23
+	dsrl	$23,$20,8
+	xor	$9,$8
+
+	dsrl	$10,$17,6
+	xor	$9,$23			# sigma0(X[i+1])
+	dsll	$8,$17,3
+	daddu	$19,$9
+	dsrl	$23,$17,19
+	xor	$10,$8
+	dsll	$8,42
+	xor	$10,$23
+	dsrl	$23,$17,61
+	xor	$10,$8
+
+	xor	$10,$23			# sigma1(X[i+14])
+	daddu	$19,$10
+	daddu	$23,$19,$24			# 27
+	dsrl	$24,$2,14
+	xor	$10,$3,$7
+	dsll	$9,$2,23
+	and	$10,$2
+	dsrl	$8,$2,18
+	xor	$24,$9
+	dsll	$9,$2,46
+	xor	$24,$8
+	dsrl	$8,$2,41
+	xor	$24,$9
+	dsll	$9,$2,50
+	xor	$24,$8
+	xor	$10,$7			# Ch(e,f,g)
+	xor	$8,$9,$24			# Sigma1(e)
+
+	dsrl	$24,$25,28
+	daddu	$23,$10
+	ld	$10,216($6)		# K[27]
+	dsll	$9,$25,25
+	daddu	$23,$8
+	dsrl	$8,$25,34
+	xor	$24,$9
+	dsll	$9,$25,30
+	xor	$24,$8
+	dsrl	$8,$25,39
+	xor	$24,$9
+	dsll	$9,$25,36
+	xor	$24,$8
+	sd	$19,88($29)	# offload to ring buffer
+	xor	$24,$9			# Sigma0(a)
+
+	or	$8,$25,$30
+	and	$9,$25,$30
+	and	$8,$31
+	or	$9,$8			# Maj(a,b,c)
+	daddu	$23,$10			# +=K[27]
+	daddu	$24,$9
+
+	daddu	$1,$23
+	daddu	$24,$23
+	ld	$22,112($29)	# prefetch from ring buffer
+	dsrl	$10,$21,7		# Xupdate(28)
+	daddu	$20,$13			# +=X[i+9]
+	dsll	$9,$21,56
+	dsrl	$8,$21,1
+	xor	$10,$9
+	dsll	$9,7
+	xor	$10,$8
+	dsrl	$8,$21,8
+	xor	$10,$9
+
+	dsrl	$11,$18,6
+	xor	$10,$8			# sigma0(X[i+1])
+	dsll	$9,$18,3
+	daddu	$20,$10
+	dsrl	$8,$18,19
+	xor	$11,$9
+	dsll	$9,42
+	xor	$11,$8
+	dsrl	$8,$18,61
+	xor	$11,$9
+
+	xor	$11,$8			# sigma1(X[i+14])
+	daddu	$20,$11
+	daddu	$8,$20,$7			# 28
+	dsrl	$7,$1,14
+	xor	$11,$2,$3
+	dsll	$10,$1,23
+	and	$11,$1
+	dsrl	$9,$1,18
+	xor	$7,$10
+	dsll	$10,$1,46
+	xor	$7,$9
+	dsrl	$9,$1,41
+	xor	$7,$10
+	dsll	$10,$1,50
+	xor	$7,$9
+	xor	$11,$3			# Ch(e,f,g)
+	xor	$9,$10,$7			# Sigma1(e)
+
+	dsrl	$7,$24,28
+	daddu	$8,$11
+	ld	$11,224($6)		# K[28]
+	dsll	$10,$24,25
+	daddu	$8,$9
+	dsrl	$9,$24,34
+	xor	$7,$10
+	dsll	$10,$24,30
+	xor	$7,$9
+	dsrl	$9,$24,39
+	xor	$7,$10
+	dsll	$10,$24,36
+	xor	$7,$9
+	sd	$20,96($29)	# offload to ring buffer
+	xor	$7,$10			# Sigma0(a)
+
+	or	$9,$24,$25
+	and	$10,$24,$25
+	and	$9,$30
+	or	$10,$9			# Maj(a,b,c)
+	daddu	$8,$11			# +=K[28]
+	daddu	$7,$10
+
+	daddu	$31,$8
+	daddu	$7,$8
+	ld	$23,120($29)	# prefetch from ring buffer
+	dsrl	$11,$22,7		# Xupdate(29)
+	daddu	$21,$14			# +=X[i+9]
+	dsll	$10,$22,56
+	dsrl	$9,$22,1
+	xor	$11,$10
+	dsll	$10,7
+	xor	$11,$9
+	dsrl	$9,$22,8
+	xor	$11,$10
+
+	dsrl	$12,$19,6
+	xor	$11,$9			# sigma0(X[i+1])
+	dsll	$10,$19,3
+	daddu	$21,$11
+	dsrl	$9,$19,19
+	xor	$12,$10
+	dsll	$10,42
+	xor	$12,$9
+	dsrl	$9,$19,61
+	xor	$12,$10
+
+	xor	$12,$9			# sigma1(X[i+14])
+	daddu	$21,$12
+	daddu	$9,$21,$3			# 29
+	dsrl	$3,$31,14
+	xor	$12,$1,$2
+	dsll	$11,$31,23
+	and	$12,$31
+	dsrl	$10,$31,18
+	xor	$3,$11
+	dsll	$11,$31,46
+	xor	$3,$10
+	dsrl	$10,$31,41
+	xor	$3,$11
+	dsll	$11,$31,50
+	xor	$3,$10
+	xor	$12,$2			# Ch(e,f,g)
+	xor	$10,$11,$3			# Sigma1(e)
+
+	dsrl	$3,$7,28
+	daddu	$9,$12
+	ld	$12,232($6)		# K[29]
+	dsll	$11,$7,25
+	daddu	$9,$10
+	dsrl	$10,$7,34
+	xor	$3,$11
+	dsll	$11,$7,30
+	xor	$3,$10
+	dsrl	$10,$7,39
+	xor	$3,$11
+	dsll	$11,$7,36
+	xor	$3,$10
+	sd	$21,104($29)	# offload to ring buffer
+	xor	$3,$11			# Sigma0(a)
+
+	or	$10,$7,$24
+	and	$11,$7,$24
+	and	$10,$25
+	or	$11,$10			# Maj(a,b,c)
+	daddu	$9,$12			# +=K[29]
+	daddu	$3,$11
+
+	daddu	$30,$9
+	daddu	$3,$9
+	ld	$8,0($29)	# prefetch from ring buffer
+	dsrl	$12,$23,7		# Xupdate(30)
+	daddu	$22,$15			# +=X[i+9]
+	dsll	$11,$23,56
+	dsrl	$10,$23,1
+	xor	$12,$11
+	dsll	$11,7
+	xor	$12,$10
+	dsrl	$10,$23,8
+	xor	$12,$11
+
+	dsrl	$13,$20,6
+	xor	$12,$10			# sigma0(X[i+1])
+	dsll	$11,$20,3
+	daddu	$22,$12
+	dsrl	$10,$20,19
+	xor	$13,$11
+	dsll	$11,42
+	xor	$13,$10
+	dsrl	$10,$20,61
+	xor	$13,$11
+
+	xor	$13,$10			# sigma1(X[i+14])
+	daddu	$22,$13
+	daddu	$10,$22,$2			# 30
+	dsrl	$2,$30,14
+	xor	$13,$31,$1
+	dsll	$12,$30,23
+	and	$13,$30
+	dsrl	$11,$30,18
+	xor	$2,$12
+	dsll	$12,$30,46
+	xor	$2,$11
+	dsrl	$11,$30,41
+	xor	$2,$12
+	dsll	$12,$30,50
+	xor	$2,$11
+	xor	$13,$1			# Ch(e,f,g)
+	xor	$11,$12,$2			# Sigma1(e)
+
+	dsrl	$2,$3,28
+	daddu	$10,$13
+	ld	$13,240($6)		# K[30]
+	dsll	$12,$3,25
+	daddu	$10,$11
+	dsrl	$11,$3,34
+	xor	$2,$12
+	dsll	$12,$3,30
+	xor	$2,$11
+	dsrl	$11,$3,39
+	xor	$2,$12
+	dsll	$12,$3,36
+	xor	$2,$11
+	sd	$22,112($29)	# offload to ring buffer
+	xor	$2,$12			# Sigma0(a)
+
+	or	$11,$3,$7
+	and	$12,$3,$7
+	and	$11,$24
+	or	$12,$11			# Maj(a,b,c)
+	daddu	$10,$13			# +=K[30]
+	daddu	$2,$12
+
+	daddu	$25,$10
+	daddu	$2,$10
+	ld	$9,8($29)	# prefetch from ring buffer
+	dsrl	$13,$8,7		# Xupdate(31)
+	daddu	$23,$16			# +=X[i+9]
+	dsll	$12,$8,56
+	dsrl	$11,$8,1
+	xor	$13,$12
+	dsll	$12,7
+	xor	$13,$11
+	dsrl	$11,$8,8
+	xor	$13,$12
+
+	dsrl	$14,$21,6
+	xor	$13,$11			# sigma0(X[i+1])
+	dsll	$12,$21,3
+	daddu	$23,$13
+	dsrl	$11,$21,19
+	xor	$14,$12
+	dsll	$12,42
+	xor	$14,$11
+	dsrl	$11,$21,61
+	xor	$14,$12
+
+	xor	$14,$11			# sigma1(X[i+14])
+	daddu	$23,$14
+	daddu	$11,$23,$1			# 31
+	dsrl	$1,$25,14
+	xor	$14,$30,$31
+	dsll	$13,$25,23
+	and	$14,$25
+	dsrl	$12,$25,18
+	xor	$1,$13
+	dsll	$13,$25,46
+	xor	$1,$12
+	dsrl	$12,$25,41
+	xor	$1,$13
+	dsll	$13,$25,50
+	xor	$1,$12
+	xor	$14,$31			# Ch(e,f,g)
+	xor	$12,$13,$1			# Sigma1(e)
+
+	dsrl	$1,$2,28
+	daddu	$11,$14
+	ld	$14,248($6)		# K[31]
+	dsll	$13,$2,25
+	daddu	$11,$12
+	dsrl	$12,$2,34
+	xor	$1,$13
+	dsll	$13,$2,30
+	xor	$1,$12
+	dsrl	$12,$2,39
+	xor	$1,$13
+	dsll	$13,$2,36
+	xor	$1,$12
+	sd	$23,120($29)	# offload to ring buffer
+	xor	$1,$13			# Sigma0(a)
+
+	or	$12,$2,$3
+	and	$13,$2,$3
+	and	$12,$7
+	or	$13,$12			# Maj(a,b,c)
+	daddu	$11,$14			# +=K[31]
+	daddu	$1,$13
+
+	daddu	$24,$11
+	daddu	$1,$11
+	ld	$10,16($29)	# prefetch from ring buffer
+	and	$14,0xfff
+	li	$15,2071
+	.set	noreorder
+	bne	$14,$15,.L16_xx
+	dadd $6,16*8		# Ktbl+=16
+
+	ld	$23,16*8($29)	# restore pointer to the end of input
+	ld	$8,0*8($4)
+	ld	$9,1*8($4)
+	ld	$10,2*8($4)
+	dadd $5,16*8
+	ld	$11,3*8($4)
+	daddu	$1,$8
+	ld	$12,4*8($4)
+	daddu	$2,$9
+	ld	$13,5*8($4)
+	daddu	$3,$10
+	ld	$14,6*8($4)
+	daddu	$7,$11
+	ld	$15,7*8($4)
+	daddu	$24,$12
+	sd	$1,0*8($4)
+	daddu	$25,$13
+	sd	$2,1*8($4)
+	daddu	$30,$14
+	sd	$3,2*8($4)
+	daddu	$31,$15
+	sd	$7,3*8($4)
+	sd	$24,4*8($4)
+	sd	$25,5*8($4)
+	sd	$30,6*8($4)
+	sd	$31,7*8($4)
+
+	bne	$5,$23,.Loop
+	dsub $6,512	# rewind $6
+
+	ld	$31,256-1*8($29)
+	ld	$30,256-2*8($29)
+	ld	$23,256-3*8($29)
+	ld	$22,256-4*8($29)
+	ld	$21,256-5*8($29)
+	ld	$20,256-6*8($29)
+	ld	$19,256-7*8($29)
+	ld	$18,256-8*8($29)
+	ld	$17,256-9*8($29)
+	ld	$16,256-10*8($29)
+	jr	$31
+	dadd $29,256
+.end	sha512_block_data_order
+
+.rdata
+.align	5
+K512:
+	.dword	0x428a2f98d728ae22, 0x7137449123ef65cd
+	.dword	0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc
+	.dword	0x3956c25bf348b538, 0x59f111f1b605d019
+	.dword	0x923f82a4af194f9b, 0xab1c5ed5da6d8118
+	.dword	0xd807aa98a3030242, 0x12835b0145706fbe
+	.dword	0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2
+	.dword	0x72be5d74f27b896f, 0x80deb1fe3b1696b1
+	.dword	0x9bdc06a725c71235, 0xc19bf174cf692694
+	.dword	0xe49b69c19ef14ad2, 0xefbe4786384f25e3
+	.dword	0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65
+	.dword	0x2de92c6f592b0275, 0x4a7484aa6ea6e483
+	.dword	0x5cb0a9dcbd41fbd4, 0x76f988da831153b5
+	.dword	0x983e5152ee66dfab, 0xa831c66d2db43210
+	.dword	0xb00327c898fb213f, 0xbf597fc7beef0ee4
+	.dword	0xc6e00bf33da88fc2, 0xd5a79147930aa725
+	.dword	0x06ca6351e003826f, 0x142929670a0e6e70
+	.dword	0x27b70a8546d22ffc, 0x2e1b21385c26c926
+	.dword	0x4d2c6dfc5ac42aed, 0x53380d139d95b3df
+	.dword	0x650a73548baf63de, 0x766a0abb3c77b2a8
+	.dword	0x81c2c92e47edaee6, 0x92722c851482353b
+	.dword	0xa2bfe8a14cf10364, 0xa81a664bbc423001
+	.dword	0xc24b8b70d0f89791, 0xc76c51a30654be30
+	.dword	0xd192e819d6ef5218, 0xd69906245565a910
+	.dword	0xf40e35855771202a, 0x106aa07032bbd1b8
+	.dword	0x19a4c116b8d2d0c8, 0x1e376c085141ab53
+	.dword	0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8
+	.dword	0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb
+	.dword	0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3
+	.dword	0x748f82ee5defb2fc, 0x78a5636f43172f60
+	.dword	0x84c87814a1f0ab72, 0x8cc702081a6439ec
+	.dword	0x90befffa23631e28, 0xa4506cebde82bde9
+	.dword	0xbef9a3f7b2c67915, 0xc67178f2e372532b
+	.dword	0xca273eceea26619c, 0xd186b8c721c0c207
+	.dword	0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178
+	.dword	0x06f067aa72176fba, 0x0a637dc5a2c898a6
+	.dword	0x113f9804bef90dae, 0x1b710b35131c471b
+	.dword	0x28db77f523047d84, 0x32caab7b40c72493
+	.dword	0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c
+	.dword	0x4cc5d4becb3e42b6, 0x597f299cfc657e2a
+	.dword	0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+.asciiz	"SHA512 for MIPS, CRYPTOGAMS by "
+.align	5
+
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/sha/sha512.c b/crypto/sha/sha512.c
new file mode 100644
index 0000000..360a5c2
--- /dev/null
+++ b/crypto/sha/sha512.c
@@ -0,0 +1,580 @@
+/* $OpenBSD: sha512.c,v 1.41 2023/07/08 12:24:10 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1998-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+
+#include 
+#include 
+
+#include "crypto_internal.h"
+#include "sha_internal.h"
+
+#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512)
+
+/* Ensure that SHA_LONG64 and uint64_t are equivalent. */
+CTASSERT(sizeof(SHA_LONG64) == sizeof(uint64_t));
+
+#ifdef SHA512_ASM
+void sha512_block_data_order(SHA512_CTX *ctx, const void *in, size_t num);
+#endif
+
+#ifndef SHA512_ASM
+static const SHA_LONG64 K512[80] = {
+	U64(0x428a2f98d728ae22), U64(0x7137449123ef65cd),
+	U64(0xb5c0fbcfec4d3b2f), U64(0xe9b5dba58189dbbc),
+	U64(0x3956c25bf348b538), U64(0x59f111f1b605d019),
+	U64(0x923f82a4af194f9b), U64(0xab1c5ed5da6d8118),
+	U64(0xd807aa98a3030242), U64(0x12835b0145706fbe),
+	U64(0x243185be4ee4b28c), U64(0x550c7dc3d5ffb4e2),
+	U64(0x72be5d74f27b896f), U64(0x80deb1fe3b1696b1),
+	U64(0x9bdc06a725c71235), U64(0xc19bf174cf692694),
+	U64(0xe49b69c19ef14ad2), U64(0xefbe4786384f25e3),
+	U64(0x0fc19dc68b8cd5b5), U64(0x240ca1cc77ac9c65),
+	U64(0x2de92c6f592b0275), U64(0x4a7484aa6ea6e483),
+	U64(0x5cb0a9dcbd41fbd4), U64(0x76f988da831153b5),
+	U64(0x983e5152ee66dfab), U64(0xa831c66d2db43210),
+	U64(0xb00327c898fb213f), U64(0xbf597fc7beef0ee4),
+	U64(0xc6e00bf33da88fc2), U64(0xd5a79147930aa725),
+	U64(0x06ca6351e003826f), U64(0x142929670a0e6e70),
+	U64(0x27b70a8546d22ffc), U64(0x2e1b21385c26c926),
+	U64(0x4d2c6dfc5ac42aed), U64(0x53380d139d95b3df),
+	U64(0x650a73548baf63de), U64(0x766a0abb3c77b2a8),
+	U64(0x81c2c92e47edaee6), U64(0x92722c851482353b),
+	U64(0xa2bfe8a14cf10364), U64(0xa81a664bbc423001),
+	U64(0xc24b8b70d0f89791), U64(0xc76c51a30654be30),
+	U64(0xd192e819d6ef5218), U64(0xd69906245565a910),
+	U64(0xf40e35855771202a), U64(0x106aa07032bbd1b8),
+	U64(0x19a4c116b8d2d0c8), U64(0x1e376c085141ab53),
+	U64(0x2748774cdf8eeb99), U64(0x34b0bcb5e19b48a8),
+	U64(0x391c0cb3c5c95a63), U64(0x4ed8aa4ae3418acb),
+	U64(0x5b9cca4f7763e373), U64(0x682e6ff3d6b2b8a3),
+	U64(0x748f82ee5defb2fc), U64(0x78a5636f43172f60),
+	U64(0x84c87814a1f0ab72), U64(0x8cc702081a6439ec),
+	U64(0x90befffa23631e28), U64(0xa4506cebde82bde9),
+	U64(0xbef9a3f7b2c67915), U64(0xc67178f2e372532b),
+	U64(0xca273eceea26619c), U64(0xd186b8c721c0c207),
+	U64(0xeada7dd6cde0eb1e), U64(0xf57d4f7fee6ed178),
+	U64(0x06f067aa72176fba), U64(0x0a637dc5a2c898a6),
+	U64(0x113f9804bef90dae), U64(0x1b710b35131c471b),
+	U64(0x28db77f523047d84), U64(0x32caab7b40c72493),
+	U64(0x3c9ebe0a15c9bebc), U64(0x431d67c49c100d4c),
+	U64(0x4cc5d4becb3e42b6), U64(0x597f299cfc657e2a),
+	U64(0x5fcb6fab3ad6faec), U64(0x6c44198c4a475817),
+};
+
+static inline SHA_LONG64
+Sigma0(SHA_LONG64 x)
+{
+	return crypto_ror_u64(x, 28) ^ crypto_ror_u64(x, 34) ^
+	    crypto_ror_u64(x, 39);
+}
+
+static inline SHA_LONG64
+Sigma1(SHA_LONG64 x)
+{
+	return crypto_ror_u64(x, 14) ^ crypto_ror_u64(x, 18) ^
+	    crypto_ror_u64(x, 41);
+}
+
+static inline SHA_LONG64
+sigma0(SHA_LONG64 x)
+{
+	return crypto_ror_u64(x, 1) ^ crypto_ror_u64(x, 8) ^ (x >> 7);
+}
+
+static inline SHA_LONG64
+sigma1(SHA_LONG64 x)
+{
+	return crypto_ror_u64(x, 19) ^ crypto_ror_u64(x, 61) ^ (x >> 6);
+}
+
+static inline SHA_LONG64
+Ch(SHA_LONG64 x, SHA_LONG64 y, SHA_LONG64 z)
+{
+	return (x & y) ^ (~x & z);
+}
+
+static inline SHA_LONG64
+Maj(SHA_LONG64 x, SHA_LONG64 y, SHA_LONG64 z)
+{
+	return (x & y) ^ (x & z) ^ (y & z);
+}
+
+static inline void
+sha512_msg_schedule_update(SHA_LONG64 *W0, SHA_LONG64 W1,
+    SHA_LONG64 W9, SHA_LONG64 W14)
+{
+	*W0 = sigma1(W14) + W9 + sigma0(W1) + *W0;
+}
+
+static inline void
+sha512_round(SHA_LONG64 *a, SHA_LONG64 *b, SHA_LONG64 *c, SHA_LONG64 *d,
+    SHA_LONG64 *e, SHA_LONG64 *f, SHA_LONG64 *g, SHA_LONG64 *h,
+    SHA_LONG64 Kt, SHA_LONG64 Wt)
+{
+	SHA_LONG64 T1, T2;
+
+	T1 = *h + Sigma1(*e) + Ch(*e, *f, *g) + Kt + Wt;
+	T2 = Sigma0(*a) + Maj(*a, *b, *c);
+
+	*h = *g;
+	*g = *f;
+	*f = *e;
+	*e = *d + T1;
+	*d = *c;
+	*c = *b;
+	*b = *a;
+	*a = T1 + T2;
+}
+
+static void
+sha512_block_data_order(SHA512_CTX *ctx, const void *_in, size_t num)
+{
+	const uint8_t *in = _in;
+	const SHA_LONG64 *in64;
+	SHA_LONG64 a, b, c, d, e, f, g, h;
+	SHA_LONG64 X[16];
+	int i;
+
+	while (num--) {
+		a = ctx->h[0];
+		b = ctx->h[1];
+		c = ctx->h[2];
+		d = ctx->h[3];
+		e = ctx->h[4];
+		f = ctx->h[5];
+		g = ctx->h[6];
+		h = ctx->h[7];
+
+		if ((size_t)in % sizeof(SHA_LONG64) == 0) {
+			/* Input is 64 bit aligned. */
+			in64 = (const SHA_LONG64 *)in;
+			X[0] = be64toh(in64[0]);
+			X[1] = be64toh(in64[1]);
+			X[2] = be64toh(in64[2]);
+			X[3] = be64toh(in64[3]);
+			X[4] = be64toh(in64[4]);
+			X[5] = be64toh(in64[5]);
+			X[6] = be64toh(in64[6]);
+			X[7] = be64toh(in64[7]);
+			X[8] = be64toh(in64[8]);
+			X[9] = be64toh(in64[9]);
+			X[10] = be64toh(in64[10]);
+			X[11] = be64toh(in64[11]);
+			X[12] = be64toh(in64[12]);
+			X[13] = be64toh(in64[13]);
+			X[14] = be64toh(in64[14]);
+			X[15] = be64toh(in64[15]);
+		} else {
+			/* Input is not 64 bit aligned. */
+			X[0] = crypto_load_be64toh(&in[0 * 8]);
+			X[1] = crypto_load_be64toh(&in[1 * 8]);
+			X[2] = crypto_load_be64toh(&in[2 * 8]);
+			X[3] = crypto_load_be64toh(&in[3 * 8]);
+			X[4] = crypto_load_be64toh(&in[4 * 8]);
+			X[5] = crypto_load_be64toh(&in[5 * 8]);
+			X[6] = crypto_load_be64toh(&in[6 * 8]);
+			X[7] = crypto_load_be64toh(&in[7 * 8]);
+			X[8] = crypto_load_be64toh(&in[8 * 8]);
+			X[9] = crypto_load_be64toh(&in[9 * 8]);
+			X[10] = crypto_load_be64toh(&in[10 * 8]);
+			X[11] = crypto_load_be64toh(&in[11 * 8]);
+			X[12] = crypto_load_be64toh(&in[12 * 8]);
+			X[13] = crypto_load_be64toh(&in[13 * 8]);
+			X[14] = crypto_load_be64toh(&in[14 * 8]);
+			X[15] = crypto_load_be64toh(&in[15 * 8]);
+		}
+		in += SHA512_CBLOCK;
+
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[0], X[0]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[1], X[1]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[2], X[2]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[3], X[3]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[4], X[4]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[5], X[5]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[6], X[6]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[7], X[7]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[8], X[8]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[9], X[9]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[10], X[10]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[11], X[11]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[12], X[12]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[13], X[13]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[14], X[14]);
+		sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[15], X[15]);
+
+		for (i = 16; i < 80; i += 16) {
+			sha512_msg_schedule_update(&X[0], X[1], X[9], X[14]);
+			sha512_msg_schedule_update(&X[1], X[2], X[10], X[15]);
+			sha512_msg_schedule_update(&X[2], X[3], X[11], X[0]);
+			sha512_msg_schedule_update(&X[3], X[4], X[12], X[1]);
+			sha512_msg_schedule_update(&X[4], X[5], X[13], X[2]);
+			sha512_msg_schedule_update(&X[5], X[6], X[14], X[3]);
+			sha512_msg_schedule_update(&X[6], X[7], X[15], X[4]);
+			sha512_msg_schedule_update(&X[7], X[8], X[0], X[5]);
+			sha512_msg_schedule_update(&X[8], X[9], X[1], X[6]);
+			sha512_msg_schedule_update(&X[9], X[10], X[2], X[7]);
+			sha512_msg_schedule_update(&X[10], X[11], X[3], X[8]);
+			sha512_msg_schedule_update(&X[11], X[12], X[4], X[9]);
+			sha512_msg_schedule_update(&X[12], X[13], X[5], X[10]);
+			sha512_msg_schedule_update(&X[13], X[14], X[6], X[11]);
+			sha512_msg_schedule_update(&X[14], X[15], X[7], X[12]);
+			sha512_msg_schedule_update(&X[15], X[0], X[8], X[13]);
+
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 0], X[0]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 1], X[1]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 2], X[2]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 3], X[3]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 4], X[4]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 5], X[5]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 6], X[6]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 7], X[7]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 8], X[8]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 9], X[9]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 10], X[10]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 11], X[11]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 12], X[12]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 13], X[13]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 14], X[14]);
+			sha512_round(&a, &b, &c, &d, &e, &f, &g, &h, K512[i + 15], X[15]);
+		}
+
+		ctx->h[0] += a;
+		ctx->h[1] += b;
+		ctx->h[2] += c;
+		ctx->h[3] += d;
+		ctx->h[4] += e;
+		ctx->h[5] += f;
+		ctx->h[6] += g;
+		ctx->h[7] += h;
+	}
+}
+
+#endif /* SHA512_ASM */
+
+int
+SHA384_Init(SHA512_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->h[0] = U64(0xcbbb9d5dc1059ed8);
+	c->h[1] = U64(0x629a292a367cd507);
+	c->h[2] = U64(0x9159015a3070dd17);
+	c->h[3] = U64(0x152fecd8f70e5939);
+	c->h[4] = U64(0x67332667ffc00b31);
+	c->h[5] = U64(0x8eb44a8768581511);
+	c->h[6] = U64(0xdb0c2e0d64f98fa7);
+	c->h[7] = U64(0x47b5481dbefa4fa4);
+
+	c->md_len = SHA384_DIGEST_LENGTH;
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA384_Init);
+
+int
+SHA384_Update(SHA512_CTX *c, const void *data, size_t len)
+{
+	return SHA512_Update(c, data, len);
+}
+LCRYPTO_ALIAS(SHA384_Update);
+
+int
+SHA384_Final(unsigned char *md, SHA512_CTX *c)
+{
+	return SHA512_Final(md, c);
+}
+LCRYPTO_ALIAS(SHA384_Final);
+
+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);
+
+	explicit_bzero(&c, sizeof(c));
+
+	return (md);
+}
+LCRYPTO_ALIAS(SHA384);
+
+int
+SHA512_Init(SHA512_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	c->h[0] = U64(0x6a09e667f3bcc908);
+	c->h[1] = U64(0xbb67ae8584caa73b);
+	c->h[2] = U64(0x3c6ef372fe94f82b);
+	c->h[3] = U64(0xa54ff53a5f1d36f1);
+	c->h[4] = U64(0x510e527fade682d1);
+	c->h[5] = U64(0x9b05688c2b3e6c1f);
+	c->h[6] = U64(0x1f83d9abfb41bd6b);
+	c->h[7] = U64(0x5be0cd19137e2179);
+
+	c->md_len = SHA512_DIGEST_LENGTH;
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA512_Init);
+
+void
+SHA512_Transform(SHA512_CTX *c, const unsigned char *data)
+{
+	sha512_block_data_order(c, data, 1);
+}
+LCRYPTO_ALIAS(SHA512_Transform);
+
+int
+SHA512_Update(SHA512_CTX *c, const void *_data, size_t len)
+{
+	const unsigned char *data = _data;
+	unsigned char *p = c->u.p;
+	SHA_LONG64 l;
+
+	if (len == 0)
+		return 1;
+
+	l = (c->Nl + (((SHA_LONG64)len) << 3))&U64(0xffffffffffffffff);
+	if (l < c->Nl)
+		c->Nh++;
+	if (sizeof(len) >= 8)
+		c->Nh += (((SHA_LONG64)len) >> 61);
+	c->Nl = l;
+
+	if (c->num != 0) {
+		size_t n = sizeof(c->u) - c->num;
+
+		if (len < n) {
+			memcpy(p + c->num, data, len);
+			c->num += (unsigned int)len;
+			return 1;
+		} else{
+			memcpy(p + c->num, data, n);
+			c->num = 0;
+			len -= n;
+			data += n;
+			sha512_block_data_order(c, p, 1);
+		}
+	}
+
+	if (len >= sizeof(c->u)) {
+		sha512_block_data_order(c, data, len/sizeof(c->u));
+		data += len;
+		len %= sizeof(c->u);
+		data -= len;
+	}
+
+	if (len != 0) {
+		memcpy(p, data, len);
+		c->num = (int)len;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA512_Update);
+
+int
+SHA512_Final(unsigned char *md, SHA512_CTX *c)
+{
+	unsigned char *p = (unsigned char *)c->u.p;
+	size_t n = c->num;
+
+	p[n]=0x80;	/* There always is a room for one */
+	n++;
+	if (n > (sizeof(c->u) - 16)) {
+		memset(p + n, 0, sizeof(c->u) - n);
+		n = 0;
+		sha512_block_data_order(c, p, 1);
+	}
+
+	memset(p + n, 0, sizeof(c->u) - 16 - n);
+	c->u.d[SHA_LBLOCK - 2] = htobe64(c->Nh);
+	c->u.d[SHA_LBLOCK - 1] = htobe64(c->Nl);
+
+	sha512_block_data_order(c, p, 1);
+
+	if (md == NULL)
+		return 0;
+
+	/* Let compiler decide if it's appropriate to unroll... */
+	switch (c->md_len) {
+	case SHA512_224_DIGEST_LENGTH:
+		for (n = 0; n < SHA512_224_DIGEST_LENGTH/8; n++) {
+			crypto_store_htobe64(md, c->h[n]);
+			md += 8;
+		}
+		crypto_store_htobe32(md, c->h[n] >> 32);
+		break;
+	case SHA512_256_DIGEST_LENGTH:
+		for (n = 0; n < SHA512_256_DIGEST_LENGTH/8; n++) {
+			crypto_store_htobe64(md, c->h[n]);
+			md += 8;
+		}
+		break;
+	case SHA384_DIGEST_LENGTH:
+		for (n = 0; n < SHA384_DIGEST_LENGTH/8; n++) {
+			crypto_store_htobe64(md, c->h[n]);
+			md += 8;
+		}
+		break;
+	case SHA512_DIGEST_LENGTH:
+		for (n = 0; n < SHA512_DIGEST_LENGTH/8; n++) {
+			crypto_store_htobe64(md, c->h[n]);
+			md += 8;
+		}
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(SHA512_Final);
+
+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);
+
+	explicit_bzero(&c, sizeof(c));
+
+	return (md);
+}
+LCRYPTO_ALIAS(SHA512);
+
+int
+SHA512_224_Init(SHA512_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	/* FIPS 180-4 section 5.3.6.1. */
+	c->h[0] = U64(0x8c3d37c819544da2);
+	c->h[1] = U64(0x73e1996689dcd4d6);
+	c->h[2] = U64(0x1dfab7ae32ff9c82);
+	c->h[3] = U64(0x679dd514582f9fcf);
+	c->h[4] = U64(0x0f6d2b697bd44da8);
+	c->h[5] = U64(0x77e36f7304c48942);
+	c->h[6] = U64(0x3f9d85a86a1d36c8);
+	c->h[7] = U64(0x1112e6ad91d692a1);
+
+	c->md_len = SHA512_224_DIGEST_LENGTH;
+
+	return 1;
+}
+
+int
+SHA512_224_Update(SHA512_CTX *c, const void *data, size_t len)
+{
+	return SHA512_Update(c, data, len);
+}
+
+int
+SHA512_224_Final(unsigned char *md, SHA512_CTX *c)
+{
+	return SHA512_Final(md, c);
+}
+
+int
+SHA512_256_Init(SHA512_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+
+	/* FIPS 180-4 section 5.3.6.2. */
+	c->h[0] = U64(0x22312194fc2bf72c);
+	c->h[1] = U64(0x9f555fa3c84c64c2);
+	c->h[2] = U64(0x2393b86b6f53b151);
+	c->h[3] = U64(0x963877195940eabd);
+	c->h[4] = U64(0x96283ee2a88effe3);
+	c->h[5] = U64(0xbe5e1e2553863992);
+	c->h[6] = U64(0x2b0199fc2c85b8aa);
+	c->h[7] = U64(0x0eb72ddc81c52ca2);
+
+	c->md_len = SHA512_256_DIGEST_LENGTH;
+
+	return 1;
+}
+
+int
+SHA512_256_Update(SHA512_CTX *c, const void *data, size_t len)
+{
+	return SHA512_Update(c, data, len);
+}
+
+int
+SHA512_256_Final(unsigned char *md, SHA512_CTX *c)
+{
+	return SHA512_Final(md, c);
+}
+
+#endif /* !OPENSSL_NO_SHA512 */
diff --git a/crypto/sha/sha_internal.h b/crypto/sha/sha_internal.h
new file mode 100644
index 0000000..63cae3d
--- /dev/null
+++ b/crypto/sha/sha_internal.h
@@ -0,0 +1,36 @@
+/*	$OpenBSD: sha_internal.h,v 1.3 2023/04/25 15:47:29 tb Exp $ */
+/*
+ * Copyright (c) 2023 Joel Sing 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef HEADER_SHA_INTERNAL_H
+#define HEADER_SHA_INTERNAL_H
+
+#define SHA512_224_DIGEST_LENGTH	28
+#define SHA512_256_DIGEST_LENGTH	32
+
+int SHA512_224_Init(SHA512_CTX *c);
+int SHA512_224_Update(SHA512_CTX *c, const void *data, size_t len)
+	__attribute__ ((__bounded__(__buffer__,2,3)));
+int SHA512_224_Final(unsigned char *md, SHA512_CTX *c);
+
+int SHA512_256_Init(SHA512_CTX *c);
+int SHA512_256_Update(SHA512_CTX *c, const void *data, size_t len)
+	__attribute__ ((__bounded__(__buffer__,2,3)));
+int SHA512_256_Final(unsigned char *md, SHA512_CTX *c);
+
+#endif
diff --git a/crypto/sm3/sm3.c b/crypto/sm3/sm3.c
new file mode 100644
index 0000000..80be935
--- /dev/null
+++ b/crypto/sm3/sm3.c
@@ -0,0 +1,277 @@
+/*	$OpenBSD: sm3.c,v 1.6 2023/07/08 06:36:55 jsing Exp $	*/
+/*
+ * Copyright (c) 2018, Ribose Inc
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef OPENSSL_NO_SM3
+
+#include 
+
+#include 
+
+#include 
+
+#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_MAKE_STRING(c, s) do {		\
+	unsigned long ll;			\
+	ll = (c)->A; HOST_l2c(ll, (s));		\
+	ll = (c)->B; HOST_l2c(ll, (s));		\
+	ll = (c)->C; HOST_l2c(ll, (s));		\
+	ll = (c)->D; HOST_l2c(ll, (s));		\
+	ll = (c)->E; HOST_l2c(ll, (s));		\
+	ll = (c)->F; HOST_l2c(ll, (s));		\
+	ll = (c)->G; HOST_l2c(ll, (s));		\
+	ll = (c)->H; HOST_l2c(ll, (s));		\
+} while (0)
+#define HASH_BLOCK_DATA_ORDER   SM3_block_data_order
+
+void SM3_block_data_order(SM3_CTX *c, const void *p, size_t num);
+void SM3_transform(SM3_CTX *c, const unsigned char *data);
+
+#include "md32_common.h"
+
+#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17))
+#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23))
+
+#define FF0(X, Y, Z) (X ^ Y ^ Z)
+#define GG0(X, Y, Z) (X ^ Y ^ Z)
+
+#define FF1(X, Y, Z) ((X & Y) | ((X | Y) & Z))
+#define GG1(X, Y, Z) ((Z ^ (X & (Y ^ Z))))
+
+#define EXPAND(W0, W7, W13, W3, W10) \
+	(P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10)
+
+#define ROUND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG)	do {	\
+	const SM3_WORD A12 = ROTATE(A, 12);				\
+	const SM3_WORD A12_SM = A12 + E + TJ;				\
+	const SM3_WORD SS1 = ROTATE(A12_SM, 7);				\
+	const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj);	\
+	const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi;		\
+	B = ROTATE(B, 9);						\
+	D = TT1;							\
+	F = ROTATE(F, 19);						\
+	H = P0(TT2);							\
+} while(0)
+
+#define R1(A, B, C, D, E, F, G, H, TJ, Wi, Wj) \
+	ROUND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF0, GG0)
+
+#define R2(A, B, C, D, E, F, G, H, TJ, Wi, Wj) \
+	ROUND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF1, GG1)
+
+#define SM3_A 0x7380166fUL
+#define SM3_B 0x4914b2b9UL
+#define SM3_C 0x172442d7UL
+#define SM3_D 0xda8a0600UL
+#define SM3_E 0xa96f30bcUL
+#define SM3_F 0x163138aaUL
+#define SM3_G 0xe38dee4dUL
+#define SM3_H 0xb0fb0e4eUL
+
+LCRYPTO_ALIAS(SM3_Update);
+LCRYPTO_ALIAS(SM3_Final);
+
+int
+SM3_Init(SM3_CTX *c)
+{
+	memset(c, 0, sizeof(*c));
+	c->A = SM3_A;
+	c->B = SM3_B;
+	c->C = SM3_C;
+	c->D = SM3_D;
+	c->E = SM3_E;
+	c->F = SM3_F;
+	c->G = SM3_G;
+	c->H = SM3_H;
+	return 1;
+}
+LCRYPTO_ALIAS(SM3_Init);
+
+void
+SM3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
+{
+	const unsigned char *data = p;
+	SM3_WORD A, B, C, D, E, F, G, H;
+	SM3_WORD W00, W01, W02, W03, W04, W05, W06, W07;
+	SM3_WORD W08, W09, W10, W11, W12, W13, W14, W15;
+
+	while (num-- != 0) {
+		A = ctx->A;
+		B = ctx->B;
+		C = ctx->C;
+		D = ctx->D;
+		E = ctx->E;
+		F = ctx->F;
+		G = ctx->G;
+		H = ctx->H;
+
+        	/*
+        	 * We have to load all message bytes immediately since SM3 reads
+        	 * them slightly out of order.
+        	 */
+		HOST_c2l(data, W00);
+		HOST_c2l(data, W01);
+		HOST_c2l(data, W02);
+		HOST_c2l(data, W03);
+		HOST_c2l(data, W04);
+		HOST_c2l(data, W05);
+		HOST_c2l(data, W06);
+		HOST_c2l(data, W07);
+		HOST_c2l(data, W08);
+		HOST_c2l(data, W09);
+		HOST_c2l(data, W10);
+		HOST_c2l(data, W11);
+		HOST_c2l(data, W12);
+		HOST_c2l(data, W13);
+		HOST_c2l(data, W14);
+		HOST_c2l(data, W15);
+
+		R1(A, B, C, D, E, F, G, H, 0x79cc4519, W00, W00 ^ W04);
+		W00 = EXPAND(W00, W07, W13, W03, W10);
+		R1(D, A, B, C, H, E, F, G, 0xf3988a32, W01, W01 ^ W05);
+		W01 = EXPAND(W01, W08, W14, W04, W11);
+		R1(C, D, A, B, G, H, E, F, 0xe7311465, W02, W02 ^ W06);
+		W02 = EXPAND(W02, W09, W15, W05, W12);
+		R1(B, C, D, A, F, G, H, E, 0xce6228cb, W03, W03 ^ W07);
+		W03 = EXPAND(W03, W10, W00, W06, W13);
+		R1(A, B, C, D, E, F, G, H, 0x9cc45197, W04, W04 ^ W08);
+		W04 = EXPAND(W04, W11, W01, W07, W14);
+		R1(D, A, B, C, H, E, F, G, 0x3988a32f, W05, W05 ^ W09);
+		W05 = EXPAND(W05, W12, W02, W08, W15);
+		R1(C, D, A, B, G, H, E, F, 0x7311465e, W06, W06 ^ W10);
+		W06 = EXPAND(W06, W13, W03, W09, W00);
+		R1(B, C, D, A, F, G, H, E, 0xe6228cbc, W07, W07 ^ W11);
+		W07 = EXPAND(W07, W14, W04, W10, W01);
+		R1(A, B, C, D, E, F, G, H, 0xcc451979, W08, W08 ^ W12);
+		W08 = EXPAND(W08, W15, W05, W11, W02);
+		R1(D, A, B, C, H, E, F, G, 0x988a32f3, W09, W09 ^ W13);
+		W09 = EXPAND(W09, W00, W06, W12, W03);
+		R1(C, D, A, B, G, H, E, F, 0x311465e7, W10, W10 ^ W14);
+		W10 = EXPAND(W10, W01, W07, W13, W04);
+		R1(B, C, D, A, F, G, H, E, 0x6228cbce, W11, W11 ^ W15);
+		W11 = EXPAND(W11, W02, W08, W14, W05);
+		R1(A, B, C, D, E, F, G, H, 0xc451979c, W12, W12 ^ W00);
+		W12 = EXPAND(W12, W03, W09, W15, W06);
+		R1(D, A, B, C, H, E, F, G, 0x88a32f39, W13, W13 ^ W01);
+		W13 = EXPAND(W13, W04, W10, W00, W07);
+		R1(C, D, A, B, G, H, E, F, 0x11465e73, W14, W14 ^ W02);
+		W14 = EXPAND(W14, W05, W11, W01, W08);
+		R1(B, C, D, A, F, G, H, E, 0x228cbce6, W15, W15 ^ W03);
+		W15 = EXPAND(W15, W06, W12, W02, W09);
+		R2(A, B, C, D, E, F, G, H, 0x9d8a7a87, W00, W00 ^ W04);
+		W00 = EXPAND(W00, W07, W13, W03, W10);
+		R2(D, A, B, C, H, E, F, G, 0x3b14f50f, W01, W01 ^ W05);
+		W01 = EXPAND(W01, W08, W14, W04, W11);
+		R2(C, D, A, B, G, H, E, F, 0x7629ea1e, W02, W02 ^ W06);
+		W02 = EXPAND(W02, W09, W15, W05, W12);
+		R2(B, C, D, A, F, G, H, E, 0xec53d43c, W03, W03 ^ W07);
+		W03 = EXPAND(W03, W10, W00, W06, W13);
+		R2(A, B, C, D, E, F, G, H, 0xd8a7a879, W04, W04 ^ W08);
+		W04 = EXPAND(W04, W11, W01, W07, W14);
+		R2(D, A, B, C, H, E, F, G, 0xb14f50f3, W05, W05 ^ W09);
+		W05 = EXPAND(W05, W12, W02, W08, W15);
+		R2(C, D, A, B, G, H, E, F, 0x629ea1e7, W06, W06 ^ W10);
+		W06 = EXPAND(W06, W13, W03, W09, W00);
+		R2(B, C, D, A, F, G, H, E, 0xc53d43ce, W07, W07 ^ W11);
+		W07 = EXPAND(W07, W14, W04, W10, W01);
+		R2(A, B, C, D, E, F, G, H, 0x8a7a879d, W08, W08 ^ W12);
+		W08 = EXPAND(W08, W15, W05, W11, W02);
+		R2(D, A, B, C, H, E, F, G, 0x14f50f3b, W09, W09 ^ W13);
+		W09 = EXPAND(W09, W00, W06, W12, W03);
+		R2(C, D, A, B, G, H, E, F, 0x29ea1e76, W10, W10 ^ W14);
+		W10 = EXPAND(W10, W01, W07, W13, W04);
+		R2(B, C, D, A, F, G, H, E, 0x53d43cec, W11, W11 ^ W15);
+		W11 = EXPAND(W11, W02, W08, W14, W05);
+		R2(A, B, C, D, E, F, G, H, 0xa7a879d8, W12, W12 ^ W00);
+		W12 = EXPAND(W12, W03, W09, W15, W06);
+		R2(D, A, B, C, H, E, F, G, 0x4f50f3b1, W13, W13 ^ W01);
+		W13 = EXPAND(W13, W04, W10, W00, W07);
+		R2(C, D, A, B, G, H, E, F, 0x9ea1e762, W14, W14 ^ W02);
+		W14 = EXPAND(W14, W05, W11, W01, W08);
+		R2(B, C, D, A, F, G, H, E, 0x3d43cec5, W15, W15 ^ W03);
+		W15 = EXPAND(W15, W06, W12, W02, W09);
+		R2(A, B, C, D, E, F, G, H, 0x7a879d8a, W00, W00 ^ W04);
+		W00 = EXPAND(W00, W07, W13, W03, W10);
+		R2(D, A, B, C, H, E, F, G, 0xf50f3b14, W01, W01 ^ W05);
+		W01 = EXPAND(W01, W08, W14, W04, W11);
+		R2(C, D, A, B, G, H, E, F, 0xea1e7629, W02, W02 ^ W06);
+		W02 = EXPAND(W02, W09, W15, W05, W12);
+		R2(B, C, D, A, F, G, H, E, 0xd43cec53, W03, W03 ^ W07);
+		W03 = EXPAND(W03, W10, W00, W06, W13);
+		R2(A, B, C, D, E, F, G, H, 0xa879d8a7, W04, W04 ^ W08);
+		W04 = EXPAND(W04, W11, W01, W07, W14);
+		R2(D, A, B, C, H, E, F, G, 0x50f3b14f, W05, W05 ^ W09);
+		W05 = EXPAND(W05, W12, W02, W08, W15);
+		R2(C, D, A, B, G, H, E, F, 0xa1e7629e, W06, W06 ^ W10);
+		W06 = EXPAND(W06, W13, W03, W09, W00);
+		R2(B, C, D, A, F, G, H, E, 0x43cec53d, W07, W07 ^ W11);
+		W07 = EXPAND(W07, W14, W04, W10, W01);
+		R2(A, B, C, D, E, F, G, H, 0x879d8a7a, W08, W08 ^ W12);
+		W08 = EXPAND(W08, W15, W05, W11, W02);
+		R2(D, A, B, C, H, E, F, G, 0x0f3b14f5, W09, W09 ^ W13);
+		W09 = EXPAND(W09, W00, W06, W12, W03);
+		R2(C, D, A, B, G, H, E, F, 0x1e7629ea, W10, W10 ^ W14);
+		W10 = EXPAND(W10, W01, W07, W13, W04);
+		R2(B, C, D, A, F, G, H, E, 0x3cec53d4, W11, W11 ^ W15);
+		W11 = EXPAND(W11, W02, W08, W14, W05);
+		R2(A, B, C, D, E, F, G, H, 0x79d8a7a8, W12, W12 ^ W00);
+		W12 = EXPAND(W12, W03, W09, W15, W06);
+		R2(D, A, B, C, H, E, F, G, 0xf3b14f50, W13, W13 ^ W01);
+		W13 = EXPAND(W13, W04, W10, W00, W07);
+		R2(C, D, A, B, G, H, E, F, 0xe7629ea1, W14, W14 ^ W02);
+		W14 = EXPAND(W14, W05, W11, W01, W08);
+		R2(B, C, D, A, F, G, H, E, 0xcec53d43, W15, W15 ^ W03);
+		W15 = EXPAND(W15, W06, W12, W02, W09);
+		R2(A, B, C, D, E, F, G, H, 0x9d8a7a87, W00, W00 ^ W04);
+		W00 = EXPAND(W00, W07, W13, W03, W10);
+		R2(D, A, B, C, H, E, F, G, 0x3b14f50f, W01, W01 ^ W05);
+		W01 = EXPAND(W01, W08, W14, W04, W11);
+		R2(C, D, A, B, G, H, E, F, 0x7629ea1e, W02, W02 ^ W06);
+		W02 = EXPAND(W02, W09, W15, W05, W12);
+		R2(B, C, D, A, F, G, H, E, 0xec53d43c, W03, W03 ^ W07);
+		W03 = EXPAND(W03, W10, W00, W06, W13);
+		R2(A, B, C, D, E, F, G, H, 0xd8a7a879, W04, W04 ^ W08);
+		R2(D, A, B, C, H, E, F, G, 0xb14f50f3, W05, W05 ^ W09);
+		R2(C, D, A, B, G, H, E, F, 0x629ea1e7, W06, W06 ^ W10);
+		R2(B, C, D, A, F, G, H, E, 0xc53d43ce, W07, W07 ^ W11);
+		R2(A, B, C, D, E, F, G, H, 0x8a7a879d, W08, W08 ^ W12);
+		R2(D, A, B, C, H, E, F, G, 0x14f50f3b, W09, W09 ^ W13);
+		R2(C, D, A, B, G, H, E, F, 0x29ea1e76, W10, W10 ^ W14);
+		R2(B, C, D, A, F, G, H, E, 0x53d43cec, W11, W11 ^ W15);
+		R2(A, B, C, D, E, F, G, H, 0xa7a879d8, W12, W12 ^ W00);
+		R2(D, A, B, C, H, E, F, G, 0x4f50f3b1, W13, W13 ^ W01);
+		R2(C, D, A, B, G, H, E, F, 0x9ea1e762, W14, W14 ^ W02);
+		R2(B, C, D, A, F, G, H, E, 0x3d43cec5, W15, W15 ^ W03);
+
+		ctx->A ^= A;
+		ctx->B ^= B;
+		ctx->C ^= C;
+		ctx->D ^= D;
+		ctx->E ^= E;
+		ctx->F ^= F;
+		ctx->G ^= G;
+		ctx->H ^= H;
+	}
+}
+
+#endif /* !OPENSSL_NO_SM3 */
diff --git a/crypto/sm4/sm4.c b/crypto/sm4/sm4.c
new file mode 100644
index 0000000..bd16899
--- /dev/null
+++ b/crypto/sm4/sm4.c
@@ -0,0 +1,266 @@
+/*	$OpenBSD: sm4.c,v 1.2 2023/07/07 12:01:32 beck Exp $	*/
+/*
+ * Copyright (c) 2017, 2019 Ribose Inc
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+
+#ifndef OPENSSL_NO_SM4
+#include 
+
+struct sm4_key {
+        uint32_t rk[SM4_KEY_SCHEDULE];
+};
+
+static const uint8_t SM4_S[256] = {
+	0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2,
+	0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3,
+	0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4,
+	0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62,
+	0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA,
+	0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA,
+	0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2,
+	0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35,
+	0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B,
+	0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52,
+	0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2,
+	0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1,
+	0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30,
+	0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60,
+	0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45,
+	0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51,
+	0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41,
+	0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD,
+	0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A,
+	0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84,
+	0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E,
+	0xD7, 0xCB, 0x39, 0x48,
+};
+
+/*
+ * SM4_SBOX_T[j] == L(SM4_SBOX[j]).
+ */
+static const uint32_t SM4_SBOX_T[256] = {
+	0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
+	0xC93DF4F4, 0x6BB5DEDE, 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B,
+	0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, 0x872BACAC, 0xFB669D9D,
+	0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F,
+	0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A,
+	0x1E061818, 0xFD9B6666, 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3,
+	0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, 0xFF33CCCC, 0x04555151,
+	0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989,
+	0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020,
+	0x48EBA3A3, 0xC1975656, 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB,
+	0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, 0x5B461D1D, 0x1B071C1C,
+	0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA,
+	0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616,
+	0x734E3D3D, 0x08AAA2A2, 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA,
+	0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, 0x18FBE3E3, 0x47E8AFAF,
+	0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4,
+	0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161,
+	0x95D24747, 0x2AA08A8A, 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC,
+	0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, 0x84D75353, 0x00000000,
+	0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949,
+	0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313,
+	0xE8CB2323, 0xE69C7A7A, 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B,
+	0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, 0x2FA18E8E, 0x2BF4DFDF,
+	0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686,
+	0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0,
+	0x721A6868, 0x01545555, 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0,
+	0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, 0x691D7474, 0x2EF5DBDB,
+	0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181,
+	0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D,
+	0x764F3939, 0xD36EBDBD, 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515,
+	0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, 0x0F030C0C, 0x03FCFFFF,
+	0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545,
+	0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777,
+	0x4CBEF2F2, 0x837EFDFD, 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505,
+	0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, 0x220A2828, 0xC5C20707,
+	0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6,
+	0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797,
+	0x64B6D2D2, 0x70B2C2C2, 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929,
+	0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, 0xF1649595, 0x5DBBE6E6,
+	0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212,
+	0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373,
+	0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
+	0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121,
+};
+
+static inline uint32_t
+rotl(uint32_t a, uint8_t n)
+{
+	return (a << n) | (a >> (32 - n));
+}
+
+static inline uint32_t
+load_u32_be(const uint8_t *b, uint32_t n)
+{
+	return ((uint32_t)b[4 * n] << 24) |
+	    ((uint32_t)b[4 * n + 1] << 16) |
+	    ((uint32_t)b[4 * n + 2] << 8) |
+	    ((uint32_t)b[4 * n + 3]);
+}
+
+static inline void
+store_u32_be(uint32_t v, uint8_t *b)
+{
+	b[0] = (uint8_t)(v >> 24);
+	b[1] = (uint8_t)(v >> 16);
+	b[2] = (uint8_t)(v >> 8);
+	b[3] = (uint8_t)(v);
+}
+
+static inline uint32_t
+SM4_T_slow(uint32_t X)
+{
+	uint32_t t = 0;
+
+	t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
+	t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
+	t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
+	t |= SM4_S[(uint8_t)X];
+
+	/*
+	 * L linear transform
+	 */
+	return t ^ rotl(t, 2) ^ rotl(t, 10) ^ rotl(t, 18) ^ rotl(t, 24);
+}
+
+static inline uint32_t
+SM4_T(uint32_t X)
+{
+	return SM4_SBOX_T[(uint8_t)(X >> 24)] ^
+	    rotl(SM4_SBOX_T[(uint8_t)(X >> 16)], 24) ^
+	    rotl(SM4_SBOX_T[(uint8_t)(X >> 8)], 16) ^
+	    rotl(SM4_SBOX_T[(uint8_t)X], 8);
+}
+
+int
+SM4_set_key(const uint8_t *key, SM4_KEY *k)
+{
+	struct sm4_key *ks = (struct sm4_key *)k;
+
+	/*
+	 * Family Key
+	 */
+	static const uint32_t FK[4] = {
+		0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc,
+	};
+
+	/*
+	 * Constant Key
+	 */
+	static const uint32_t CK[32] = {
+		0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
+		0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
+		0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
+		0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
+		0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
+		0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
+		0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
+		0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279,
+	};
+
+	uint32_t K[4];
+	int i;
+
+	K[0] = load_u32_be(key, 0) ^ FK[0];
+	K[1] = load_u32_be(key, 1) ^ FK[1];
+	K[2] = load_u32_be(key, 2) ^ FK[2];
+	K[3] = load_u32_be(key, 3) ^ FK[3];
+
+	for (i = 0; i < SM4_KEY_SCHEDULE; i++) {
+		uint32_t X;
+		uint32_t t = 0;
+
+		X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i];
+
+		t |= ((uint32_t)SM4_S[(uint8_t)(X >> 24)]) << 24;
+		t |= ((uint32_t)SM4_S[(uint8_t)(X >> 16)]) << 16;
+		t |= ((uint32_t)SM4_S[(uint8_t)(X >> 8)]) << 8;
+		t |= SM4_S[(uint8_t)X];
+
+		t = t ^ rotl(t, 13) ^ rotl(t, 23);
+		K[i % 4] ^= t;
+		ks->rk[i] = K[i % 4];
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(SM4_set_key);
+
+#define SM4_ROUNDS(k0, k1, k2, k3, F)			\
+	  do {						\
+		 B0 ^= F(B1 ^ B2 ^ B3 ^ ks->rk[k0]);	\
+		 B1 ^= F(B0 ^ B2 ^ B3 ^ ks->rk[k1]);	\
+		 B2 ^= F(B0 ^ B1 ^ B3 ^ ks->rk[k2]);	\
+		 B3 ^= F(B0 ^ B1 ^ B2 ^ ks->rk[k3]);	\
+	  } while(0)
+
+void
+SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k)
+{
+	struct sm4_key *ks = (struct sm4_key *)k;
+	uint32_t B0 = load_u32_be(in, 0);
+	uint32_t B1 = load_u32_be(in, 1);
+	uint32_t B2 = load_u32_be(in, 2);
+	uint32_t B3 = load_u32_be(in, 3);
+
+	/*
+	 * Uses byte-wise sbox in the first and last rounds to provide some
+	 * protection from cache based side channels.
+	 */
+	SM4_ROUNDS( 0,  1,  2,  3, SM4_T_slow);
+	SM4_ROUNDS( 4,  5,  6,  7, SM4_T);
+	SM4_ROUNDS( 8,  9, 10, 11, SM4_T);
+	SM4_ROUNDS(12, 13, 14, 15, SM4_T);
+	SM4_ROUNDS(16, 17, 18, 19, SM4_T);
+	SM4_ROUNDS(20, 21, 22, 23, SM4_T);
+	SM4_ROUNDS(24, 25, 26, 27, SM4_T);
+	SM4_ROUNDS(28, 29, 30, 31, SM4_T_slow);
+
+	store_u32_be(B3, out);
+	store_u32_be(B2, out + 4);
+	store_u32_be(B1, out + 8);
+	store_u32_be(B0, out + 12);
+}
+LCRYPTO_ALIAS(SM4_encrypt);
+
+void
+SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *k)
+{
+	struct sm4_key *ks = (struct sm4_key *)k;
+	uint32_t B0 = load_u32_be(in, 0);
+	uint32_t B1 = load_u32_be(in, 1);
+	uint32_t B2 = load_u32_be(in, 2);
+	uint32_t B3 = load_u32_be(in, 3);
+
+	SM4_ROUNDS(31, 30, 29, 28, SM4_T_slow);
+	SM4_ROUNDS(27, 26, 25, 24, SM4_T);
+	SM4_ROUNDS(23, 22, 21, 20, SM4_T);
+	SM4_ROUNDS(19, 18, 17, 16, SM4_T);
+	SM4_ROUNDS(15, 14, 13, 12, SM4_T);
+	SM4_ROUNDS(11, 10,  9,  8, SM4_T);
+	SM4_ROUNDS( 7,  6,  5,  4, SM4_T);
+	SM4_ROUNDS( 3,  2,  1,  0, SM4_T_slow);
+
+	store_u32_be(B3, out);
+	store_u32_be(B2, out + 4);
+	store_u32_be(B1, out + 8);
+	store_u32_be(B0, out + 12);
+}
+LCRYPTO_ALIAS(SM4_decrypt);
+
+#endif /* OPENSSL_NO_SM4 */
diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c
new file mode 100644
index 0000000..65bd321
--- /dev/null
+++ b/crypto/stack/stack.c
@@ -0,0 +1,372 @@
+/* $OpenBSD: stack.c,v 1.23 2023/04/24 15:35:22 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+#undef MIN_NODES
+#define MIN_NODES	4
+
+#include 
+
+int
+(*sk_set_cmp_func(_STACK *sk, int (*c)(const void *, const void *)))(
+    const void *, const void *)
+{
+	int (*old)(const void *, const void *) = sk->comp;
+
+	if (sk->comp != c)
+		sk->sorted = 0;
+	sk->comp = c;
+
+	return old;
+}
+LCRYPTO_ALIAS(sk_set_cmp_func);
+
+_STACK *
+sk_dup(_STACK *sk)
+{
+	_STACK *ret;
+	char **s;
+
+	if ((ret = sk_new(sk->comp)) == NULL)
+		goto err;
+	s = reallocarray(ret->data, sk->num_alloc, sizeof(char *));
+	if (s == NULL)
+		goto err;
+	ret->data = s;
+
+	ret->num = sk->num;
+	memcpy(ret->data, sk->data, sizeof(char *) * sk->num);
+	ret->sorted = sk->sorted;
+	ret->num_alloc = sk->num_alloc;
+	ret->comp = sk->comp;
+	return (ret);
+
+err:
+	if (ret)
+		sk_free(ret);
+	return (NULL);
+}
+LCRYPTO_ALIAS(sk_dup);
+
+_STACK *
+sk_new_null(void)
+{
+	return sk_new((int (*)(const void *, const void *))0);
+}
+LCRYPTO_ALIAS(sk_new_null);
+
+_STACK *
+sk_new(int (*c)(const void *, const void *))
+{
+	_STACK *ret;
+	int i;
+
+	if ((ret = malloc(sizeof(_STACK))) == NULL)
+		goto err;
+	if ((ret->data = reallocarray(NULL, MIN_NODES, sizeof(char *))) == NULL)
+		goto err;
+	for (i = 0; i < MIN_NODES; i++)
+		ret->data[i] = NULL;
+	ret->comp = c;
+	ret->num_alloc = MIN_NODES;
+	ret->num = 0;
+	ret->sorted = 0;
+	return (ret);
+
+err:
+	free(ret);
+	return (NULL);
+}
+LCRYPTO_ALIAS(sk_new);
+
+int
+sk_insert(_STACK *st, void *data, int loc)
+{
+	char **s;
+
+	if (st == NULL)
+		return 0;
+	if (st->num_alloc <= st->num + 1) {
+		s = reallocarray(st->data, st->num_alloc, 2 * sizeof(char *));
+		if (s == NULL)
+			return (0);
+		st->data = s;
+		st->num_alloc *= 2;
+	}
+	if ((loc >= (int)st->num) || (loc < 0))
+		st->data[st->num] = data;
+	else {
+		memmove(&(st->data[loc + 1]), &(st->data[loc]),
+		    sizeof(char *)*(st->num - loc));
+		st->data[loc] = data;
+	}
+	st->num++;
+	st->sorted = 0;
+	return (st->num);
+}
+LCRYPTO_ALIAS(sk_insert);
+
+void *
+sk_delete_ptr(_STACK *st, void *p)
+{
+	int i;
+
+	for (i = 0; i < st->num; i++)
+		if (st->data[i] == p)
+			return (sk_delete(st, i));
+	return (NULL);
+}
+LCRYPTO_ALIAS(sk_delete_ptr);
+
+void *
+sk_delete(_STACK *st, int loc)
+{
+	char *ret;
+
+	if (!st || (loc < 0) || (loc >= st->num))
+		return NULL;
+
+	ret = st->data[loc];
+	if (loc != st->num - 1) {
+		memmove(&(st->data[loc]), &(st->data[loc + 1]),
+		    sizeof(char *)*(st->num - 1 - loc));
+	}
+	st->num--;
+	return (ret);
+}
+LCRYPTO_ALIAS(sk_delete);
+
+static int
+internal_find(_STACK *st, void *data, int ret_val_options)
+{
+	const void * const *r;
+	int i;
+
+	if (st == NULL)
+		return -1;
+
+	if (st->comp == NULL) {
+		for (i = 0; i < st->num; i++)
+			if (st->data[i] == data)
+				return (i);
+		return (-1);
+	}
+	sk_sort(st);
+	if (data == NULL)
+		return (-1);
+	r = OBJ_bsearch_ex_(&data, st->data, st->num, sizeof(void *), st->comp,
+	    ret_val_options);
+	if (r == NULL)
+		return (-1);
+	return (int)((char **)r - st->data);
+}
+
+int
+sk_find(_STACK *st, void *data)
+{
+	return internal_find(st, data, OBJ_BSEARCH_FIRST_VALUE_ON_MATCH);
+}
+LCRYPTO_ALIAS(sk_find);
+
+int
+sk_find_ex(_STACK *st, void *data)
+{
+	return internal_find(st, data, OBJ_BSEARCH_VALUE_ON_NOMATCH);
+}
+LCRYPTO_ALIAS(sk_find_ex);
+
+int
+sk_push(_STACK *st, void *data)
+{
+	return (sk_insert(st, data, st->num));
+}
+LCRYPTO_ALIAS(sk_push);
+
+int
+sk_unshift(_STACK *st, void *data)
+{
+	return (sk_insert(st, data, 0));
+}
+LCRYPTO_ALIAS(sk_unshift);
+
+void *
+sk_shift(_STACK *st)
+{
+	if (st == NULL)
+		return (NULL);
+	if (st->num <= 0)
+		return (NULL);
+	return (sk_delete(st, 0));
+}
+LCRYPTO_ALIAS(sk_shift);
+
+void *
+sk_pop(_STACK *st)
+{
+	if (st == NULL)
+		return (NULL);
+	if (st->num <= 0)
+		return (NULL);
+	return (sk_delete(st, st->num - 1));
+}
+LCRYPTO_ALIAS(sk_pop);
+
+void
+sk_zero(_STACK *st)
+{
+	if (st == NULL)
+		return;
+	if (st->num <= 0)
+		return;
+	memset(st->data, 0, sizeof(st->data)*st->num);
+	st->num = 0;
+}
+LCRYPTO_ALIAS(sk_zero);
+
+void
+sk_pop_free(_STACK *st, void (*func)(void *))
+{
+	int i;
+
+	if (st == NULL)
+		return;
+	for (i = 0; i < st->num; i++)
+		if (st->data[i] != NULL)
+			func(st->data[i]);
+	sk_free(st);
+}
+LCRYPTO_ALIAS(sk_pop_free);
+
+void
+sk_free(_STACK *st)
+{
+	if (st == NULL)
+		return;
+	free(st->data);
+	free(st);
+}
+LCRYPTO_ALIAS(sk_free);
+
+int
+sk_num(const _STACK *st)
+{
+	if (st == NULL)
+		return -1;
+	return st->num;
+}
+LCRYPTO_ALIAS(sk_num);
+
+void *
+sk_value(const _STACK *st, int i)
+{
+	if (!st || (i < 0) || (i >= st->num))
+		return NULL;
+	return st->data[i];
+}
+LCRYPTO_ALIAS(sk_value);
+
+void *
+sk_set(_STACK *st, int i, void *value)
+{
+	if (!st || (i < 0) || (i >= st->num))
+		return NULL;
+	st->sorted = 0;
+	return (st->data[i] = value);
+}
+LCRYPTO_ALIAS(sk_set);
+
+void
+sk_sort(_STACK *st)
+{
+	if (st && !st->sorted) {
+		int (*comp_func)(const void *, const void *);
+
+		/* same comment as in sk_find ... previously st->comp was declared
+		 * as a (void*,void*) callback type, but this made the population
+		 * of the callback pointer illogical - our callbacks compare
+		 * type** with type**, so we leave the casting until absolutely
+		 * necessary (ie. "now"). */
+		comp_func = (int (*)(const void *, const void *))(st->comp);
+		qsort(st->data, st->num, sizeof(char *), comp_func);
+		st->sorted = 1;
+	}
+}
+LCRYPTO_ALIAS(sk_sort);
+
+int
+sk_is_sorted(const _STACK *st)
+{
+	if (st == NULL)
+		return 1;
+
+	if (st->sorted)
+		return 1;
+
+	/* If there is no comparison function we cannot sort. */
+	if (st->comp == NULL)
+		return 0;
+
+	/* Lists with zero or one elements are always sorted. */
+	return st->num <= 1;
+}
+LCRYPTO_ALIAS(sk_is_sorted);
diff --git a/crypto/ts/ts_asn1.c b/crypto/ts/ts_asn1.c
new file mode 100644
index 0000000..60ee0b8
--- /dev/null
+++ b/crypto/ts/ts_asn1.c
@@ -0,0 +1,1077 @@
+/* $OpenBSD: ts_asn1.c,v 1.14 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Nils Larsch for the OpenSSL project 2004.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "ts_local.h"
+
+static const ASN1_TEMPLATE TS_MSG_IMPRINT_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_MSG_IMPRINT, hash_algo),
+		.field_name = "hash_algo",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_MSG_IMPRINT, hashed_msg),
+		.field_name = "hashed_msg",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+};
+
+const ASN1_ITEM TS_MSG_IMPRINT_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_MSG_IMPRINT_seq_tt,
+	.tcount = sizeof(TS_MSG_IMPRINT_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(TS_MSG_IMPRINT),
+	.sname = "TS_MSG_IMPRINT",
+};
+
+
+TS_MSG_IMPRINT *
+d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a, const unsigned char **in, long len)
+{
+	return (TS_MSG_IMPRINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_MSG_IMPRINT_it);
+}
+LCRYPTO_ALIAS(d2i_TS_MSG_IMPRINT);
+
+int
+i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_MSG_IMPRINT_it);
+}
+LCRYPTO_ALIAS(i2d_TS_MSG_IMPRINT);
+
+TS_MSG_IMPRINT *
+TS_MSG_IMPRINT_new(void)
+{
+	return (TS_MSG_IMPRINT *)ASN1_item_new(&TS_MSG_IMPRINT_it);
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_new);
+
+void
+TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_MSG_IMPRINT_it);
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_free);
+
+TS_MSG_IMPRINT *
+TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *x)
+{
+	return ASN1_item_dup(&TS_MSG_IMPRINT_it, x);
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_dup);
+
+#ifndef OPENSSL_NO_BIO
+TS_MSG_IMPRINT *
+d2i_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT **a)
+{
+	return ASN1_item_d2i_bio(&TS_MSG_IMPRINT_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_MSG_IMPRINT_bio);
+
+int
+i2d_TS_MSG_IMPRINT_bio(BIO *bp, TS_MSG_IMPRINT *a)
+{
+	return ASN1_item_i2d_bio(&TS_MSG_IMPRINT_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_MSG_IMPRINT_bio);
+#endif
+
+TS_MSG_IMPRINT *
+d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a)
+{
+	return ASN1_item_d2i_fp(&TS_MSG_IMPRINT_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_MSG_IMPRINT_fp);
+
+int
+i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a)
+{
+	return ASN1_item_i2d_fp(&TS_MSG_IMPRINT_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_MSG_IMPRINT_fp);
+
+static const ASN1_TEMPLATE TS_REQ_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, msg_imprint),
+		.field_name = "msg_imprint",
+		.item = &TS_MSG_IMPRINT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, policy_id),
+		.field_name = "policy_id",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, nonce),
+		.field_name = "nonce",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, cert_req),
+		.field_name = "cert_req",
+		.item = &ASN1_FBOOLEAN_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_REQ, extensions),
+		.field_name = "extensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM TS_REQ_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_REQ_seq_tt,
+	.tcount = sizeof(TS_REQ_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(TS_REQ),
+	.sname = "TS_REQ",
+};
+
+
+TS_REQ *
+d2i_TS_REQ(TS_REQ **a, const unsigned char **in, long len)
+{
+	return (TS_REQ *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_REQ_it);
+}
+LCRYPTO_ALIAS(d2i_TS_REQ);
+
+int
+i2d_TS_REQ(const TS_REQ *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_REQ_it);
+}
+LCRYPTO_ALIAS(i2d_TS_REQ);
+
+TS_REQ *
+TS_REQ_new(void)
+{
+	return (TS_REQ *)ASN1_item_new(&TS_REQ_it);
+}
+LCRYPTO_ALIAS(TS_REQ_new);
+
+void
+TS_REQ_free(TS_REQ *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_REQ_it);
+}
+LCRYPTO_ALIAS(TS_REQ_free);
+
+TS_REQ *
+TS_REQ_dup(TS_REQ *x)
+{
+	return ASN1_item_dup(&TS_REQ_it, x);
+}
+LCRYPTO_ALIAS(TS_REQ_dup);
+
+#ifndef OPENSSL_NO_BIO
+TS_REQ *
+d2i_TS_REQ_bio(BIO *bp, TS_REQ **a)
+{
+	return ASN1_item_d2i_bio(&TS_REQ_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_REQ_bio);
+
+int
+i2d_TS_REQ_bio(BIO *bp, TS_REQ *a)
+{
+	return ASN1_item_i2d_bio(&TS_REQ_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_REQ_bio);
+#endif
+
+TS_REQ *
+d2i_TS_REQ_fp(FILE *fp, TS_REQ **a)
+{
+	return ASN1_item_d2i_fp(&TS_REQ_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_REQ_fp);
+
+int
+i2d_TS_REQ_fp(FILE *fp, TS_REQ *a)
+{
+	return ASN1_item_i2d_fp(&TS_REQ_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_REQ_fp);
+
+static const ASN1_TEMPLATE TS_ACCURACY_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_ACCURACY, seconds),
+		.field_name = "seconds",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_ACCURACY, millis),
+		.field_name = "millis",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(TS_ACCURACY, micros),
+		.field_name = "micros",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM TS_ACCURACY_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_ACCURACY_seq_tt,
+	.tcount = sizeof(TS_ACCURACY_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(TS_ACCURACY),
+	.sname = "TS_ACCURACY",
+};
+
+
+TS_ACCURACY *
+d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **in, long len)
+{
+	return (TS_ACCURACY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_ACCURACY_it);
+}
+LCRYPTO_ALIAS(d2i_TS_ACCURACY);
+
+int
+i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_ACCURACY_it);
+}
+LCRYPTO_ALIAS(i2d_TS_ACCURACY);
+
+TS_ACCURACY *
+TS_ACCURACY_new(void)
+{
+	return (TS_ACCURACY *)ASN1_item_new(&TS_ACCURACY_it);
+}
+LCRYPTO_ALIAS(TS_ACCURACY_new);
+
+void
+TS_ACCURACY_free(TS_ACCURACY *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_ACCURACY_it);
+}
+LCRYPTO_ALIAS(TS_ACCURACY_free);
+
+TS_ACCURACY *
+TS_ACCURACY_dup(TS_ACCURACY *x)
+{
+	return ASN1_item_dup(&TS_ACCURACY_it, x);
+}
+LCRYPTO_ALIAS(TS_ACCURACY_dup);
+
+static const ASN1_TEMPLATE TS_TST_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, version),
+		.field_name = "version",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, policy_id),
+		.field_name = "policy_id",
+		.item = &ASN1_OBJECT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, msg_imprint),
+		.field_name = "msg_imprint",
+		.item = &TS_MSG_IMPRINT_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, serial),
+		.field_name = "serial",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, time),
+		.field_name = "time",
+		.item = &ASN1_GENERALIZEDTIME_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, accuracy),
+		.field_name = "accuracy",
+		.item = &TS_ACCURACY_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, ordering),
+		.field_name = "ordering",
+		.item = &ASN1_FBOOLEAN_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, nonce),
+		.field_name = "nonce",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_TST_INFO, tsa),
+		.field_name = "tsa",
+		.item = &GENERAL_NAME_it,
+	},
+	{
+		.flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 1,
+		.offset = offsetof(TS_TST_INFO, extensions),
+		.field_name = "extensions",
+		.item = &X509_EXTENSION_it,
+	},
+};
+
+const ASN1_ITEM TS_TST_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_TST_INFO_seq_tt,
+	.tcount = sizeof(TS_TST_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(TS_TST_INFO),
+	.sname = "TS_TST_INFO",
+};
+
+
+TS_TST_INFO *
+d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **in, long len)
+{
+	return (TS_TST_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_TST_INFO_it);
+}
+LCRYPTO_ALIAS(d2i_TS_TST_INFO);
+
+int
+i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_TST_INFO_it);
+}
+LCRYPTO_ALIAS(i2d_TS_TST_INFO);
+
+TS_TST_INFO *
+TS_TST_INFO_new(void)
+{
+	return (TS_TST_INFO *)ASN1_item_new(&TS_TST_INFO_it);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_new);
+
+void
+TS_TST_INFO_free(TS_TST_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_TST_INFO_it);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_free);
+
+TS_TST_INFO *
+TS_TST_INFO_dup(TS_TST_INFO *x)
+{
+	return ASN1_item_dup(&TS_TST_INFO_it, x);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_dup);
+
+#ifndef OPENSSL_NO_BIO
+TS_TST_INFO *
+d2i_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO **a)
+{
+	return ASN1_item_d2i_bio(&TS_TST_INFO_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_TST_INFO_bio);
+
+int
+i2d_TS_TST_INFO_bio(BIO *bp, TS_TST_INFO *a)
+{
+	return ASN1_item_i2d_bio(&TS_TST_INFO_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_TST_INFO_bio);
+#endif
+
+TS_TST_INFO *
+d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a)
+{
+	return ASN1_item_d2i_fp(&TS_TST_INFO_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_TST_INFO_fp);
+
+int
+i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a)
+{
+	return ASN1_item_i2d_fp(&TS_TST_INFO_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_TST_INFO_fp);
+
+static const ASN1_TEMPLATE TS_STATUS_INFO_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_STATUS_INFO, status),
+		.field_name = "status",
+		.item = &ASN1_INTEGER_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_STATUS_INFO, text),
+		.field_name = "text",
+		.item = &ASN1_UTF8STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_STATUS_INFO, failure_info),
+		.field_name = "failure_info",
+		.item = &ASN1_BIT_STRING_it,
+	},
+};
+
+const ASN1_ITEM TS_STATUS_INFO_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_STATUS_INFO_seq_tt,
+	.tcount = sizeof(TS_STATUS_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(TS_STATUS_INFO),
+	.sname = "TS_STATUS_INFO",
+};
+
+
+TS_STATUS_INFO *
+d2i_TS_STATUS_INFO(TS_STATUS_INFO **a, const unsigned char **in, long len)
+{
+	return (TS_STATUS_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_STATUS_INFO_it);
+}
+LCRYPTO_ALIAS(d2i_TS_STATUS_INFO);
+
+int
+i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_STATUS_INFO_it);
+}
+LCRYPTO_ALIAS(i2d_TS_STATUS_INFO);
+
+TS_STATUS_INFO *
+TS_STATUS_INFO_new(void)
+{
+	return (TS_STATUS_INFO *)ASN1_item_new(&TS_STATUS_INFO_it);
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_new);
+
+void
+TS_STATUS_INFO_free(TS_STATUS_INFO *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_STATUS_INFO_it);
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_free);
+
+TS_STATUS_INFO *
+TS_STATUS_INFO_dup(TS_STATUS_INFO *x)
+{
+	return ASN1_item_dup(&TS_STATUS_INFO_it, x);
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_dup);
+
+static int
+ts_resp_set_tst_info(TS_RESP *a)
+{
+	long    status;
+
+	status = ASN1_INTEGER_get(a->status_info->status);
+
+	if (a->token) {
+		if (status != 0 && status != 1) {
+			TSerror(TS_R_TOKEN_PRESENT);
+			return 0;
+		}
+		if (a->tst_info != NULL)
+			TS_TST_INFO_free(a->tst_info);
+		a->tst_info = PKCS7_to_TS_TST_INFO(a->token);
+		if (!a->tst_info) {
+			TSerror(TS_R_PKCS7_TO_TS_TST_INFO_FAILED);
+			return 0;
+		}
+	} else if (status == 0 || status == 1) {
+		TSerror(TS_R_TOKEN_NOT_PRESENT);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+ts_resp_cb(int op, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
+{
+	TS_RESP *ts_resp = (TS_RESP *)*pval;
+
+	if (op == ASN1_OP_NEW_POST) {
+		ts_resp->tst_info = NULL;
+	} else if (op == ASN1_OP_FREE_POST) {
+		if (ts_resp->tst_info != NULL)
+			TS_TST_INFO_free(ts_resp->tst_info);
+	} else if (op == ASN1_OP_D2I_POST) {
+		if (ts_resp_set_tst_info(ts_resp) == 0)
+			return 0;
+	}
+	return 1;
+}
+
+static const ASN1_AUX TS_RESP_aux = {
+	.app_data = NULL,
+	.flags = 0,
+	.ref_offset = 0,
+	.ref_lock = 0,
+	.asn1_cb = ts_resp_cb,
+	.enc_offset = 0,
+};
+static const ASN1_TEMPLATE TS_RESP_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(TS_RESP, status_info),
+		.field_name = "status_info",
+		.item = &TS_STATUS_INFO_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(TS_RESP, token),
+		.field_name = "token",
+		.item = &PKCS7_it,
+	},
+};
+
+const ASN1_ITEM TS_RESP_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = TS_RESP_seq_tt,
+	.tcount = sizeof(TS_RESP_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = &TS_RESP_aux,
+	.size = sizeof(TS_RESP),
+	.sname = "TS_RESP",
+};
+
+
+TS_RESP *
+d2i_TS_RESP(TS_RESP **a, const unsigned char **in, long len)
+{
+	return (TS_RESP *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &TS_RESP_it);
+}
+LCRYPTO_ALIAS(d2i_TS_RESP);
+
+int
+i2d_TS_RESP(const TS_RESP *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &TS_RESP_it);
+}
+LCRYPTO_ALIAS(i2d_TS_RESP);
+
+TS_RESP *
+TS_RESP_new(void)
+{
+	return (TS_RESP *)ASN1_item_new(&TS_RESP_it);
+}
+LCRYPTO_ALIAS(TS_RESP_new);
+
+void
+TS_RESP_free(TS_RESP *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &TS_RESP_it);
+}
+LCRYPTO_ALIAS(TS_RESP_free);
+
+TS_RESP *
+TS_RESP_dup(TS_RESP *x)
+{
+	return ASN1_item_dup(&TS_RESP_it, x);
+}
+LCRYPTO_ALIAS(TS_RESP_dup);
+
+#ifndef OPENSSL_NO_BIO
+TS_RESP *
+d2i_TS_RESP_bio(BIO *bp, TS_RESP **a)
+{
+	return ASN1_item_d2i_bio(&TS_RESP_it, bp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_RESP_bio);
+
+int
+i2d_TS_RESP_bio(BIO *bp, TS_RESP *a)
+{
+	return ASN1_item_i2d_bio(&TS_RESP_it, bp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_RESP_bio);
+#endif
+
+TS_RESP *
+d2i_TS_RESP_fp(FILE *fp, TS_RESP **a)
+{
+	return ASN1_item_d2i_fp(&TS_RESP_it, fp, a);
+}
+LCRYPTO_ALIAS(d2i_TS_RESP_fp);
+
+int
+i2d_TS_RESP_fp(FILE *fp, TS_RESP *a)
+{
+	return ASN1_item_i2d_fp(&TS_RESP_it, fp, a);
+}
+LCRYPTO_ALIAS(i2d_TS_RESP_fp);
+
+static const ASN1_TEMPLATE ESS_ISSUER_SERIAL_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(ESS_ISSUER_SERIAL, issuer),
+		.field_name = "issuer",
+		.item = &GENERAL_NAME_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ESS_ISSUER_SERIAL, serial),
+		.field_name = "serial",
+		.item = &ASN1_INTEGER_it,
+	},
+};
+
+const ASN1_ITEM ESS_ISSUER_SERIAL_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ESS_ISSUER_SERIAL_seq_tt,
+	.tcount = sizeof(ESS_ISSUER_SERIAL_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ESS_ISSUER_SERIAL),
+	.sname = "ESS_ISSUER_SERIAL",
+};
+
+
+ESS_ISSUER_SERIAL *
+d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a, const unsigned char **in, long len)
+{
+	return (ESS_ISSUER_SERIAL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ESS_ISSUER_SERIAL_it);
+}
+LCRYPTO_ALIAS(d2i_ESS_ISSUER_SERIAL);
+
+int
+i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ESS_ISSUER_SERIAL_it);
+}
+LCRYPTO_ALIAS(i2d_ESS_ISSUER_SERIAL);
+
+ESS_ISSUER_SERIAL *
+ESS_ISSUER_SERIAL_new(void)
+{
+	return (ESS_ISSUER_SERIAL *)ASN1_item_new(&ESS_ISSUER_SERIAL_it);
+}
+LCRYPTO_ALIAS(ESS_ISSUER_SERIAL_new);
+
+void
+ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ESS_ISSUER_SERIAL_it);
+}
+LCRYPTO_ALIAS(ESS_ISSUER_SERIAL_free);
+
+ESS_ISSUER_SERIAL *
+ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *x)
+{
+	return ASN1_item_dup(&ESS_ISSUER_SERIAL_it, x);
+}
+LCRYPTO_ALIAS(ESS_ISSUER_SERIAL_dup);
+
+static const ASN1_TEMPLATE ESS_CERT_ID_seq_tt[] = {
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ESS_CERT_ID, hash),
+		.field_name = "hash",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ESS_CERT_ID, issuer_serial),
+		.field_name = "issuer_serial",
+		.item = &ESS_ISSUER_SERIAL_it,
+	},
+};
+
+const ASN1_ITEM ESS_CERT_ID_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ESS_CERT_ID_seq_tt,
+	.tcount = sizeof(ESS_CERT_ID_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ESS_CERT_ID),
+	.sname = "ESS_CERT_ID",
+};
+
+
+ESS_CERT_ID *
+d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **in, long len)
+{
+	return (ESS_CERT_ID *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ESS_CERT_ID_it);
+}
+LCRYPTO_ALIAS(d2i_ESS_CERT_ID);
+
+int
+i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ESS_CERT_ID_it);
+}
+LCRYPTO_ALIAS(i2d_ESS_CERT_ID);
+
+ESS_CERT_ID *
+ESS_CERT_ID_new(void)
+{
+	return (ESS_CERT_ID *)ASN1_item_new(&ESS_CERT_ID_it);
+}
+LCRYPTO_ALIAS(ESS_CERT_ID_new);
+
+void
+ESS_CERT_ID_free(ESS_CERT_ID *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ESS_CERT_ID_it);
+}
+LCRYPTO_ALIAS(ESS_CERT_ID_free);
+
+ESS_CERT_ID *
+ESS_CERT_ID_dup(ESS_CERT_ID *x)
+{
+	return ASN1_item_dup(&ESS_CERT_ID_it, x);
+}
+LCRYPTO_ALIAS(ESS_CERT_ID_dup);
+
+static const ASN1_TEMPLATE ESS_SIGNING_CERT_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(ESS_SIGNING_CERT, cert_ids),
+		.field_name = "cert_ids",
+		.item = &ESS_CERT_ID_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ESS_SIGNING_CERT, policy_info),
+		.field_name = "policy_info",
+		.item = &POLICYINFO_it,
+	},
+};
+
+const ASN1_ITEM ESS_SIGNING_CERT_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ESS_SIGNING_CERT_seq_tt,
+	.tcount = sizeof(ESS_SIGNING_CERT_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ESS_SIGNING_CERT),
+	.sname = "ESS_SIGNING_CERT",
+};
+
+
+ESS_SIGNING_CERT *
+d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, const unsigned char **in, long len)
+{
+	return (ESS_SIGNING_CERT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ESS_SIGNING_CERT_it);
+}
+LCRYPTO_ALIAS(d2i_ESS_SIGNING_CERT);
+
+int
+i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ESS_SIGNING_CERT_it);
+}
+LCRYPTO_ALIAS(i2d_ESS_SIGNING_CERT);
+
+ESS_SIGNING_CERT *
+ESS_SIGNING_CERT_new(void)
+{
+	return (ESS_SIGNING_CERT *)ASN1_item_new(&ESS_SIGNING_CERT_it);
+}
+LCRYPTO_ALIAS(ESS_SIGNING_CERT_new);
+
+void
+ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ESS_SIGNING_CERT_it);
+}
+LCRYPTO_ALIAS(ESS_SIGNING_CERT_free);
+
+ESS_SIGNING_CERT *
+ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *x)
+{
+	return ASN1_item_dup(&ESS_SIGNING_CERT_it, x);
+}
+LCRYPTO_ALIAS(ESS_SIGNING_CERT_dup);
+
+static const ASN1_TEMPLATE ESS_CERT_ID_V2_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ESS_CERT_ID_V2, hash_alg),
+		.field_name = "hash_alg",
+		.item = &X509_ALGOR_it,
+	},
+	{
+		.flags = 0,
+		.tag = 0,
+		.offset = offsetof(ESS_CERT_ID_V2, hash),
+		.field_name = "hash",
+		.item = &ASN1_OCTET_STRING_it,
+	},
+	{
+		.flags = ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ESS_CERT_ID_V2, issuer_serial),
+		.field_name = "issuer_serial",
+		.item = &ESS_ISSUER_SERIAL_it,
+	},
+};
+
+static const ASN1_ITEM ESS_CERT_ID_V2_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ESS_CERT_ID_V2_seq_tt,
+	.tcount = sizeof(ESS_CERT_ID_V2_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ESS_CERT_ID_V2),
+	.sname = "ESS_CERT_ID_V2",
+};
+
+ESS_CERT_ID_V2 *
+d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a, const unsigned char **in, long len)
+{
+	return (ESS_CERT_ID_V2 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ESS_CERT_ID_V2_it);
+}
+
+int
+i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ESS_CERT_ID_V2_it);
+}
+
+ESS_CERT_ID_V2 *
+ESS_CERT_ID_V2_new(void)
+{
+	return (ESS_CERT_ID_V2 *)ASN1_item_new(&ESS_CERT_ID_V2_it);
+}
+
+void
+ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ESS_CERT_ID_V2_it);
+}
+
+ESS_CERT_ID_V2 *
+ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *x)
+{
+	return ASN1_item_dup(&ESS_CERT_ID_V2_it, x);
+}
+
+static const ASN1_TEMPLATE ESS_SIGNING_CERT_V2_seq_tt[] = {
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF,
+		.tag = 0,
+		.offset = offsetof(ESS_SIGNING_CERT_V2, cert_ids),
+		.field_name = "cert_ids",
+		.item = &ESS_CERT_ID_V2_it,
+	},
+	{
+		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
+		.tag = 0,
+		.offset = offsetof(ESS_SIGNING_CERT_V2, policy_info),
+		.field_name = "policy_info",
+		.item = &POLICYINFO_it,
+	},
+};
+
+static const ASN1_ITEM ESS_SIGNING_CERT_V2_it = {
+	.itype = ASN1_ITYPE_SEQUENCE,
+	.utype = V_ASN1_SEQUENCE,
+	.templates = ESS_SIGNING_CERT_V2_seq_tt,
+	.tcount = sizeof(ESS_SIGNING_CERT_V2_seq_tt) / sizeof(ASN1_TEMPLATE),
+	.funcs = NULL,
+	.size = sizeof(ESS_SIGNING_CERT_V2),
+	.sname = "ESS_SIGNING_CERT_V2",
+};
+
+ESS_SIGNING_CERT_V2 *
+d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a, const unsigned char **in, long len)
+{
+	return (ESS_SIGNING_CERT_V2 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
+	    &ESS_SIGNING_CERT_V2_it);
+}
+
+int
+i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a, unsigned char **out)
+{
+	return ASN1_item_i2d((ASN1_VALUE *)a, out, &ESS_SIGNING_CERT_V2_it);
+}
+
+ESS_SIGNING_CERT_V2 *
+ESS_SIGNING_CERT_V2_new(void)
+{
+	return (ESS_SIGNING_CERT_V2 *)ASN1_item_new(&ESS_SIGNING_CERT_V2_it);
+}
+
+void
+ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a)
+{
+	ASN1_item_free((ASN1_VALUE *)a, &ESS_SIGNING_CERT_V2_it);
+}
+
+ESS_SIGNING_CERT_V2 *
+ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *x)
+{
+	return ASN1_item_dup(&ESS_SIGNING_CERT_V2_it, x);
+}
+
+/* Getting encapsulated TS_TST_INFO object from PKCS7. */
+TS_TST_INFO *
+PKCS7_to_TS_TST_INFO(PKCS7 *token)
+{
+	PKCS7_SIGNED *pkcs7_signed;
+	PKCS7 *enveloped;
+	ASN1_TYPE *tst_info_wrapper;
+	ASN1_OCTET_STRING *tst_info_der;
+	const unsigned char *p;
+
+	if (!PKCS7_type_is_signed(token)) {
+		TSerror(TS_R_BAD_PKCS7_TYPE);
+		return NULL;
+	}
+
+	/* Content must be present. */
+	if (PKCS7_get_detached(token)) {
+		TSerror(TS_R_DETACHED_CONTENT);
+		return NULL;
+	}
+
+	/* We have a signed data with content. */
+	pkcs7_signed = token->d.sign;
+	enveloped = pkcs7_signed->contents;
+	if (OBJ_obj2nid(enveloped->type) != NID_id_smime_ct_TSTInfo) {
+		TSerror(TS_R_BAD_PKCS7_TYPE);
+		return NULL;
+	}
+
+	/* We have a DER encoded TST_INFO as the signed data. */
+	tst_info_wrapper = enveloped->d.other;
+	if (tst_info_wrapper->type != V_ASN1_OCTET_STRING) {
+		TSerror(TS_R_BAD_TYPE);
+		return NULL;
+	}
+
+	/* We have the correct ASN1_OCTET_STRING type. */
+	tst_info_der = tst_info_wrapper->value.octet_string;
+	/* At last, decode the TST_INFO. */
+	p = tst_info_der->data;
+	return d2i_TS_TST_INFO(NULL, &p, tst_info_der->length);
+}
+LCRYPTO_ALIAS(PKCS7_to_TS_TST_INFO);
diff --git a/crypto/ts/ts_conf.c b/crypto/ts/ts_conf.c
new file mode 100644
index 0000000..103d430
--- /dev/null
+++ b/crypto/ts/ts_conf.c
@@ -0,0 +1,548 @@
+/* $OpenBSD: ts_conf.c,v 1.12 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ENGINE
+#include 
+#endif
+
+/* Macro definitions for the configuration file. */
+
+#define	BASE_SECTION			"tsa"
+#define	ENV_DEFAULT_TSA			"default_tsa"
+#define	ENV_SERIAL			"serial"
+#define ENV_CRYPTO_DEVICE		"crypto_device"
+#define	ENV_SIGNER_CERT			"signer_cert"
+#define	ENV_CERTS			"certs"
+#define	ENV_SIGNER_KEY			"signer_key"
+#define	ENV_DEFAULT_POLICY		"default_policy"
+#define	ENV_OTHER_POLICIES		"other_policies"
+#define	ENV_DIGESTS			"digests"
+#define	ENV_ACCURACY			"accuracy"
+#define	ENV_ORDERING			"ordering"
+#define	ENV_TSA_NAME			"tsa_name"
+#define	ENV_ESS_CERT_ID_CHAIN		"ess_cert_id_chain"
+#define	ENV_VALUE_SECS			"secs"
+#define	ENV_VALUE_MILLISECS		"millisecs"
+#define	ENV_VALUE_MICROSECS		"microsecs"
+#define	ENV_CLOCK_PRECISION_DIGITS	"clock_precision_digits"
+#define	ENV_VALUE_YES			"yes"
+#define	ENV_VALUE_NO			"no"
+
+/* Function definitions for certificate and key loading. */
+
+X509 *
+TS_CONF_load_cert(const char *file)
+{
+	BIO *cert = NULL;
+	X509 *x = NULL;
+
+	if ((cert = BIO_new_file(file, "r")) == NULL)
+		goto end;
+	x = PEM_read_bio_X509_AUX(cert, NULL, NULL, NULL);
+
+end:
+	if (x == NULL)
+		fprintf(stderr, "unable to load certificate: %s\n", file);
+	BIO_free(cert);
+	return x;
+}
+LCRYPTO_ALIAS(TS_CONF_load_cert);
+
+STACK_OF(X509) *
+TS_CONF_load_certs(const char *file)
+{
+	BIO *certs = NULL;
+	STACK_OF(X509) *othercerts = NULL;
+	STACK_OF(X509_INFO) *allcerts = NULL;
+	int i;
+
+	if (!(certs = BIO_new_file(file, "r")))
+		goto end;
+
+	if (!(othercerts = sk_X509_new_null()))
+		goto end;
+	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) {
+			if (sk_X509_push(othercerts, xi->x509) == 0) {
+				sk_X509_pop_free(othercerts, X509_free);
+				othercerts = NULL;
+				goto end;
+			}
+			xi->x509 = NULL;
+		}
+	}
+
+end:
+	if (othercerts == NULL)
+		fprintf(stderr, "unable to load certificates: %s\n", file);
+	sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
+	BIO_free(certs);
+	return othercerts;
+}
+LCRYPTO_ALIAS(TS_CONF_load_certs);
+
+EVP_PKEY *
+TS_CONF_load_key(const char *file, const char *pass)
+{
+	BIO *key = NULL;
+	EVP_PKEY *pkey = NULL;
+
+	if (!(key = BIO_new_file(file, "r")))
+		goto end;
+	pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, (char *) pass);
+
+end:
+	if (pkey == NULL)
+		fprintf(stderr, "unable to load private key: %s\n", file);
+	BIO_free(key);
+	return pkey;
+}
+LCRYPTO_ALIAS(TS_CONF_load_key);
+
+/* Function definitions for handling configuration options. */
+
+static void
+TS_CONF_lookup_fail(const char *name, const char *tag)
+{
+	fprintf(stderr, "variable lookup failed for %s::%s\n", name, tag);
+}
+
+static void
+TS_CONF_invalid(const char *name, const char *tag)
+{
+	fprintf(stderr, "invalid variable value for %s::%s\n", name, tag);
+}
+
+const char *
+TS_CONF_get_tsa_section(CONF *conf, const char *section)
+{
+	if (!section) {
+		section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_TSA);
+		if (!section)
+			TS_CONF_lookup_fail(BASE_SECTION, ENV_DEFAULT_TSA);
+	}
+	return section;
+}
+LCRYPTO_ALIAS(TS_CONF_get_tsa_section);
+
+int
+TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb,
+    TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	char *serial = NCONF_get_string(conf, section, ENV_SERIAL);
+
+	if (!serial) {
+		TS_CONF_lookup_fail(section, ENV_SERIAL);
+		goto err;
+	}
+	TS_RESP_CTX_set_serial_cb(ctx, cb, serial);
+
+	ret = 1;
+
+err:
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_serial);
+
+#ifndef OPENSSL_NO_ENGINE
+
+int
+TS_CONF_set_crypto_device(CONF *conf, const char *section, const char *device)
+{
+	int ret = 0;
+
+	if (!device)
+		device = NCONF_get_string(conf, section, ENV_CRYPTO_DEVICE);
+
+	if (device && !TS_CONF_set_default_engine(device)) {
+		TS_CONF_invalid(section, ENV_CRYPTO_DEVICE);
+		goto err;
+	}
+	ret = 1;
+
+err:
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_crypto_device);
+
+int
+TS_CONF_set_default_engine(const char *name)
+{
+	ENGINE *e = NULL;
+	int ret = 0;
+
+	/* Leave the default if builtin specified. */
+	if (strcmp(name, "builtin") == 0)
+		return 1;
+
+	if (!(e = ENGINE_by_id(name)))
+		goto err;
+	/* All the operations are going to be carried out by the engine. */
+	if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
+		goto err;
+	ret = 1;
+
+err:
+	if (!ret) {
+		TSerror(TS_R_COULD_NOT_SET_ENGINE);
+		ERR_asprintf_error_data("engine:%s", name);
+	}
+	ENGINE_free(e);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_default_engine);
+
+#endif
+
+int
+TS_CONF_set_signer_cert(CONF *conf, const char *section, const char *cert,
+    TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	X509 *cert_obj = NULL;
+
+	if (!cert)
+		cert = NCONF_get_string(conf, section, ENV_SIGNER_CERT);
+	if (!cert) {
+		TS_CONF_lookup_fail(section, ENV_SIGNER_CERT);
+		goto err;
+	}
+	if (!(cert_obj = TS_CONF_load_cert(cert)))
+		goto err;
+	if (!TS_RESP_CTX_set_signer_cert(ctx, cert_obj))
+		goto err;
+
+	ret = 1;
+
+err:
+	X509_free(cert_obj);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_signer_cert);
+
+int
+TS_CONF_set_certs(CONF *conf, const char *section, const char *certs,
+    TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	STACK_OF(X509) *certs_obj = NULL;
+
+	if (!certs)
+		certs = NCONF_get_string(conf, section, ENV_CERTS);
+	/* Certificate chain is optional. */
+	if (!certs)
+		goto end;
+	if (!(certs_obj = TS_CONF_load_certs(certs)))
+		goto err;
+	if (!TS_RESP_CTX_set_certs(ctx, certs_obj))
+		goto err;
+
+end:
+	ret = 1;
+err:
+	sk_X509_pop_free(certs_obj, X509_free);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_certs);
+
+int
+TS_CONF_set_signer_key(CONF *conf, const char *section, const char *key,
+    const char *pass, TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	EVP_PKEY *key_obj = NULL;
+
+	if (!key)
+		key = NCONF_get_string(conf, section, ENV_SIGNER_KEY);
+	if (!key) {
+		TS_CONF_lookup_fail(section, ENV_SIGNER_KEY);
+		goto err;
+	}
+	if (!(key_obj = TS_CONF_load_key(key, pass)))
+		goto err;
+	if (!TS_RESP_CTX_set_signer_key(ctx, key_obj))
+		goto err;
+
+	ret = 1;
+
+err:
+	EVP_PKEY_free(key_obj);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_signer_key);
+
+int
+TS_CONF_set_def_policy(CONF *conf, const char *section, const char *policy,
+    TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	ASN1_OBJECT *policy_obj = NULL;
+
+    	if (!policy)
+		policy = NCONF_get_string(conf, section, ENV_DEFAULT_POLICY);
+	if (!policy) {
+		TS_CONF_lookup_fail(section, ENV_DEFAULT_POLICY);
+		goto err;
+	}
+	if (!(policy_obj = OBJ_txt2obj(policy, 0))) {
+		TS_CONF_invalid(section, ENV_DEFAULT_POLICY);
+		goto err;
+	}
+	if (!TS_RESP_CTX_set_def_policy(ctx, policy_obj))
+		goto err;
+
+	ret = 1;
+
+err:
+	ASN1_OBJECT_free(policy_obj);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_def_policy);
+
+int
+TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	int i;
+	STACK_OF(CONF_VALUE) *list = NULL;
+	char *policies = NCONF_get_string(conf, section, ENV_OTHER_POLICIES);
+
+	/* If no other policy is specified, that's fine. */
+	if (policies && !(list = X509V3_parse_list(policies))) {
+		TS_CONF_invalid(section, ENV_OTHER_POLICIES);
+		goto err;
+	}
+	for (i = 0; i < sk_CONF_VALUE_num(list); ++i) {
+		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
+		const char *extval = val->value ? val->value : val->name;
+		ASN1_OBJECT *objtmp;
+		if (!(objtmp = OBJ_txt2obj(extval, 0))) {
+			TS_CONF_invalid(section, ENV_OTHER_POLICIES);
+			goto err;
+		}
+		if (!TS_RESP_CTX_add_policy(ctx, objtmp))
+			goto err;
+		ASN1_OBJECT_free(objtmp);
+	}
+
+	ret = 1;
+
+err:
+	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_policies);
+
+int
+TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	int i;
+	STACK_OF(CONF_VALUE) *list = NULL;
+	char *digests = NCONF_get_string(conf, section, ENV_DIGESTS);
+
+	if (!digests) {
+		TS_CONF_lookup_fail(section, ENV_DIGESTS);
+		goto err;
+	}
+	if (!(list = X509V3_parse_list(digests))) {
+		TS_CONF_invalid(section, ENV_DIGESTS);
+		goto err;
+	}
+	if (sk_CONF_VALUE_num(list) == 0) {
+		TS_CONF_invalid(section, ENV_DIGESTS);
+		goto err;
+	}
+	for (i = 0; i < sk_CONF_VALUE_num(list); ++i) {
+		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
+		const char *extval = val->value ? val->value : val->name;
+		const EVP_MD *md;
+		if (!(md = EVP_get_digestbyname(extval))) {
+			TS_CONF_invalid(section, ENV_DIGESTS);
+			goto err;
+		}
+		if (!TS_RESP_CTX_add_md(ctx, md))
+			goto err;
+	}
+
+	ret = 1;
+
+err:
+	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_digests);
+
+int
+TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	int i;
+	int secs = 0, millis = 0, micros = 0;
+	STACK_OF(CONF_VALUE) *list = NULL;
+	char *accuracy = NCONF_get_string(conf, section, ENV_ACCURACY);
+
+	if (accuracy && !(list = X509V3_parse_list(accuracy))) {
+		TS_CONF_invalid(section, ENV_ACCURACY);
+		goto err;
+	}
+	for (i = 0; i < sk_CONF_VALUE_num(list); ++i) {
+		CONF_VALUE *val = sk_CONF_VALUE_value(list, i);
+		if (strcmp(val->name, ENV_VALUE_SECS) == 0) {
+			if (val->value)
+				secs = atoi(val->value);
+		} else if (strcmp(val->name, ENV_VALUE_MILLISECS) == 0) {
+			if (val->value)
+				millis = atoi(val->value);
+		} else if (strcmp(val->name, ENV_VALUE_MICROSECS) == 0) {
+			if (val->value)
+				micros = atoi(val->value);
+		} else {
+			TS_CONF_invalid(section, ENV_ACCURACY);
+			goto err;
+		}
+	}
+	if (!TS_RESP_CTX_set_accuracy(ctx, secs, millis, micros))
+		goto err;
+
+	ret = 1;
+
+err:
+	sk_CONF_VALUE_pop_free(list, X509V3_conf_free);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_accuracy);
+
+int
+TS_CONF_set_clock_precision_digits(CONF *conf, const char *section,
+    TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	long digits = 0;
+
+	/* 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;
+	if (digits < 0 || digits > TS_MAX_CLOCK_PRECISION_DIGITS) {
+		TS_CONF_invalid(section, ENV_CLOCK_PRECISION_DIGITS);
+		goto err;
+	}
+
+	if (!TS_RESP_CTX_set_clock_precision_digits(ctx, digits))
+		goto err;
+
+	return 1;
+
+err:
+	return ret;
+}
+LCRYPTO_ALIAS(TS_CONF_set_clock_precision_digits);
+
+static int
+TS_CONF_add_flag(CONF *conf, const char *section, const char *field, int flag,
+    TS_RESP_CTX *ctx)
+{
+	/* Default is false. */
+	const char *value = NCONF_get_string(conf, section, field);
+
+	if (value) {
+		if (strcmp(value, ENV_VALUE_YES) == 0)
+			TS_RESP_CTX_add_flags(ctx, flag);
+		else if (strcmp(value, ENV_VALUE_NO) != 0) {
+			TS_CONF_invalid(section, field);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+int
+TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	return TS_CONF_add_flag(conf, section, ENV_ORDERING, TS_ORDERING, ctx);
+}
+LCRYPTO_ALIAS(TS_CONF_set_ordering);
+
+int
+TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	return TS_CONF_add_flag(conf, section, ENV_TSA_NAME, TS_TSA_NAME, ctx);
+}
+LCRYPTO_ALIAS(TS_CONF_set_tsa_name);
+
+int
+TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, TS_RESP_CTX *ctx)
+{
+	return TS_CONF_add_flag(conf, section, ENV_ESS_CERT_ID_CHAIN,
+	    TS_ESS_CERT_ID_CHAIN, ctx);
+}
+LCRYPTO_ALIAS(TS_CONF_set_ess_cert_id_chain);
diff --git a/crypto/ts/ts_err.c b/crypto/ts/ts_err.c
new file mode 100644
index 0000000..bb8209a
--- /dev/null
+++ b/crypto/ts/ts_err.c
@@ -0,0 +1,124 @@
+/* $OpenBSD: ts_err.c,v 1.7 2023/07/07 07:25:21 beck Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_TS,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_TS,0,reason)
+
+static ERR_STRING_DATA TS_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA TS_str_reasons[]= {
+	{ERR_REASON(TS_R_BAD_PKCS7_TYPE)         , "bad pkcs7 type"},
+	{ERR_REASON(TS_R_BAD_TYPE)               , "bad type"},
+	{ERR_REASON(TS_R_CERTIFICATE_VERIFY_ERROR), "certificate verify error"},
+	{ERR_REASON(TS_R_COULD_NOT_SET_ENGINE)   , "could not set engine"},
+	{ERR_REASON(TS_R_COULD_NOT_SET_TIME)     , "could not set time"},
+	{ERR_REASON(TS_R_D2I_TS_RESP_INT_FAILED) , "d2i ts resp int failed"},
+	{ERR_REASON(TS_R_DETACHED_CONTENT)       , "detached content"},
+	{ERR_REASON(TS_R_ESS_ADD_SIGNING_CERT_ERROR), "ess add signing cert error"},
+	{ERR_REASON(TS_R_ESS_SIGNING_CERTIFICATE_ERROR), "ess signing certificate error"},
+	{ERR_REASON(TS_R_INVALID_NULL_POINTER)   , "invalid null pointer"},
+	{ERR_REASON(TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE), "invalid signer certificate purpose"},
+	{ERR_REASON(TS_R_MESSAGE_IMPRINT_MISMATCH), "message imprint mismatch"},
+	{ERR_REASON(TS_R_NONCE_MISMATCH)         , "nonce mismatch"},
+	{ERR_REASON(TS_R_NONCE_NOT_RETURNED)     , "nonce not returned"},
+	{ERR_REASON(TS_R_NO_CONTENT)             , "no content"},
+	{ERR_REASON(TS_R_NO_TIME_STAMP_TOKEN)    , "no time stamp token"},
+	{ERR_REASON(TS_R_PKCS7_ADD_SIGNATURE_ERROR), "pkcs7 add signature error"},
+	{ERR_REASON(TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR), "pkcs7 add signed attr error"},
+	{ERR_REASON(TS_R_PKCS7_TO_TS_TST_INFO_FAILED), "pkcs7 to ts tst info failed"},
+	{ERR_REASON(TS_R_POLICY_MISMATCH)        , "policy mismatch"},
+	{ERR_REASON(TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE), "private key does not match certificate"},
+	{ERR_REASON(TS_R_RESPONSE_SETUP_ERROR)   , "response setup error"},
+	{ERR_REASON(TS_R_SIGNATURE_FAILURE)      , "signature failure"},
+	{ERR_REASON(TS_R_THERE_MUST_BE_ONE_SIGNER), "there must be one signer"},
+	{ERR_REASON(TS_R_TIME_SYSCALL_ERROR)     , "time syscall error"},
+	{ERR_REASON(TS_R_TOKEN_NOT_PRESENT)      , "token not present"},
+	{ERR_REASON(TS_R_TOKEN_PRESENT)          , "token present"},
+	{ERR_REASON(TS_R_TSA_NAME_MISMATCH)      , "tsa name mismatch"},
+	{ERR_REASON(TS_R_TSA_UNTRUSTED)          , "tsa untrusted"},
+	{ERR_REASON(TS_R_TST_INFO_SETUP_ERROR)   , "tst info setup error"},
+	{ERR_REASON(TS_R_TS_DATASIGN)            , "ts datasign"},
+	{ERR_REASON(TS_R_UNACCEPTABLE_POLICY)    , "unacceptable policy"},
+	{ERR_REASON(TS_R_UNSUPPORTED_MD_ALGORITHM), "unsupported md algorithm"},
+	{ERR_REASON(TS_R_UNSUPPORTED_VERSION)    , "unsupported version"},
+	{ERR_REASON(TS_R_WRONG_CONTENT_TYPE)     , "wrong content type"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_TS_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(TS_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, TS_str_functs);
+		ERR_load_strings(0, TS_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_TS_strings);
diff --git a/crypto/ts/ts_lib.c b/crypto/ts/ts_lib.c
new file mode 100644
index 0000000..1e94922
--- /dev/null
+++ b/crypto/ts/ts_lib.c
@@ -0,0 +1,158 @@
+/* $OpenBSD: ts_lib.c,v 1.14 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "bn_local.h"
+#include "x509_local.h"
+
+/* Local function declarations. */
+
+/* Function definitions. */
+
+int
+TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num)
+{
+	BIGNUM num_bn;
+	int result = 0;
+	char *hex;
+
+	BN_init(&num_bn);
+	ASN1_INTEGER_to_BN(num, &num_bn);
+	if ((hex = BN_bn2hex(&num_bn))) {
+		result = BIO_write(bio, "0x", 2) > 0;
+		result = result && BIO_write(bio, hex, strlen(hex)) > 0;
+		free(hex);
+	}
+	BN_free(&num_bn);
+
+	return result;
+}
+LCRYPTO_ALIAS(TS_ASN1_INTEGER_print_bio);
+
+int
+TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj)
+{
+	char obj_txt[128];
+
+	int len = OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
+	if (len >= sizeof(obj_txt))
+		len = sizeof(obj_txt) - 1;
+	BIO_write(bio, obj_txt, len);
+	BIO_write(bio, "\n", 1);
+	return 1;
+}
+LCRYPTO_ALIAS(TS_OBJ_print_bio);
+
+int
+TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions)
+{
+	int i, critical, n;
+	X509_EXTENSION *ex;
+	ASN1_OBJECT *obj;
+
+	BIO_printf(bio, "Extensions:\n");
+	n = X509v3_get_ext_count(extensions);
+	for (i = 0; i < n; i++) {
+		ex = X509v3_get_ext(extensions, i);
+		obj = X509_EXTENSION_get_object(ex);
+		i2a_ASN1_OBJECT(bio, obj);
+		critical = X509_EXTENSION_get_critical(ex);
+		BIO_printf(bio, ": %s\n", critical ? "critical" : "");
+		if (!X509V3_EXT_print(bio, ex, 0, 4)) {
+			BIO_printf(bio, "%4s", "");
+			ASN1_STRING_print(bio, ex->value);
+		}
+		BIO_write(bio, "\n", 1);
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_ext_print_bio);
+
+int
+TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg)
+{
+	int i = OBJ_obj2nid(alg->algorithm);
+
+	return BIO_printf(bio, "Hash Algorithm: %s\n",
+	    (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i));
+}
+LCRYPTO_ALIAS(TS_X509_ALGOR_print_bio);
+
+int
+TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *a)
+{
+	ASN1_OCTET_STRING *msg;
+
+	TS_X509_ALGOR_print_bio(bio, TS_MSG_IMPRINT_get_algo(a));
+
+	BIO_printf(bio, "Message data:\n");
+	msg = TS_MSG_IMPRINT_get_msg(a);
+	BIO_dump_indent(bio, (const char *)ASN1_STRING_data(msg),
+	    ASN1_STRING_length(msg), 4);
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_print_bio);
diff --git a/crypto/ts/ts_local.h b/crypto/ts/ts_local.h
new file mode 100644
index 0000000..07c9861
--- /dev/null
+++ b/crypto/ts/ts_local.h
@@ -0,0 +1,316 @@
+/* $OpenBSD: ts_local.h,v 1.3 2022/11/26 17:23:18 tb Exp $ */
+/* Written by Zoltan Glozik (zglozik@opentsa.org) for the OpenSSL
+ * project 2002, 2003, 2004.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_TS_LOCAL_H
+#define HEADER_TS_LOCAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+/*
+ * MessageImprint ::= SEQUENCE  {
+ *      hashAlgorithm                AlgorithmIdentifier,
+ *      hashedMessage                OCTET STRING  }
+ */
+
+struct TS_msg_imprint_st {
+	X509_ALGOR *hash_algo;
+	ASN1_OCTET_STRING *hashed_msg;
+};
+
+/*
+ * TimeStampReq ::= SEQUENCE  {
+ *    version                  INTEGER  { v1(1) },
+ *    messageImprint           MessageImprint,
+ *      --a hash algorithm OID and the hash value of the data to be
+ *      --time-stamped
+ *    reqPolicy                TSAPolicyId                OPTIONAL,
+ *    nonce                    INTEGER                    OPTIONAL,
+ *    certReq                  BOOLEAN                    DEFAULT FALSE,
+ *    extensions               [0] IMPLICIT Extensions    OPTIONAL  }
+ */
+
+struct TS_req_st {
+	ASN1_INTEGER *version;
+	TS_MSG_IMPRINT *msg_imprint;
+	ASN1_OBJECT *policy_id;		/* OPTIONAL */
+	ASN1_INTEGER *nonce;		/* OPTIONAL */
+	ASN1_BOOLEAN cert_req;		/* DEFAULT FALSE */
+	STACK_OF(X509_EXTENSION) *extensions;	/* [0] OPTIONAL */
+};
+
+/*
+ * Accuracy ::= SEQUENCE {
+ *                 seconds        INTEGER           OPTIONAL,
+ *                 millis     [0] INTEGER  (1..999) OPTIONAL,
+ *                 micros     [1] INTEGER  (1..999) OPTIONAL  }
+ */
+
+struct TS_accuracy_st {
+	ASN1_INTEGER *seconds;
+	ASN1_INTEGER *millis;
+	ASN1_INTEGER *micros;
+};
+
+/*
+ * TSTInfo ::= SEQUENCE  {
+ *     version                      INTEGER  { v1(1) },
+ *     policy                       TSAPolicyId,
+ *     messageImprint               MessageImprint,
+ *       -- MUST have the same value as the similar field in
+ *       -- TimeStampReq
+ *     serialNumber                 INTEGER,
+ *      -- Time-Stamping users MUST be ready to accommodate integers
+ *      -- up to 160 bits.
+ *     genTime                      GeneralizedTime,
+ *     accuracy                     Accuracy                 OPTIONAL,
+ *     ordering                     BOOLEAN             DEFAULT FALSE,
+ *     nonce                        INTEGER                  OPTIONAL,
+ *       -- MUST be present if the similar field was present
+ *       -- in TimeStampReq.  In that case it MUST have the same value.
+ *     tsa                          [0] GeneralName          OPTIONAL,
+ *     extensions                   [1] IMPLICIT Extensions  OPTIONAL   }
+ */
+
+struct TS_tst_info_st {
+	ASN1_INTEGER *version;
+	ASN1_OBJECT *policy_id;
+	TS_MSG_IMPRINT *msg_imprint;
+	ASN1_INTEGER *serial;
+	ASN1_GENERALIZEDTIME *time;
+	TS_ACCURACY *accuracy;
+	ASN1_BOOLEAN ordering;
+	ASN1_INTEGER *nonce;
+	GENERAL_NAME *tsa;
+	STACK_OF(X509_EXTENSION) *extensions;
+};
+
+/*
+ * PKIStatusInfo ::= SEQUENCE {
+ *     status        PKIStatus,
+ *     statusString  PKIFreeText     OPTIONAL,
+ *     failInfo      PKIFailureInfo  OPTIONAL  }
+ *
+ * From RFC 1510 - section 3.1.1:
+ * PKIFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+ *	-- text encoded as UTF-8 String (note:  each UTF8String SHOULD
+ *	-- include an RFC 1766 language tag to indicate the language
+ *	-- of the contained text)
+ */
+
+struct TS_status_info_st {
+	ASN1_INTEGER *status;
+	STACK_OF(ASN1_UTF8STRING) *text;
+	ASN1_BIT_STRING *failure_info;
+};
+
+/*
+ * TimeStampResp ::= SEQUENCE  {
+ *      status                  PKIStatusInfo,
+ *      timeStampToken          TimeStampToken     OPTIONAL }
+ */
+
+struct TS_resp_st {
+	TS_STATUS_INFO *status_info;
+	PKCS7 *token;
+	TS_TST_INFO *tst_info;
+};
+
+/* The structure below would belong to the ESS component. */
+
+/*
+ * 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 {
+	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 {
+	STACK_OF(ESS_CERT_ID_V2) *cert_ids;
+	STACK_OF(POLICYINFO) *policy_info;
+};
+
+struct TS_resp_ctx {
+	X509		*signer_cert;
+	EVP_PKEY	*signer_key;
+	STACK_OF(X509)	*certs;	/* Certs to include in signed data. */
+	STACK_OF(ASN1_OBJECT)	*policies;	/* Acceptable policies. */
+	ASN1_OBJECT	*default_policy; /* It may appear in policies, too. */
+	STACK_OF(EVP_MD)	*mds;	/* Acceptable message digests. */
+	ASN1_INTEGER	*seconds;	/* accuracy, 0 means not specified. */
+	ASN1_INTEGER	*millis;	/* accuracy, 0 means not specified. */
+	ASN1_INTEGER	*micros;	/* accuracy, 0 means not specified. */
+	unsigned	clock_precision_digits; /* fraction of seconds in
+						   time stamp token. */
+	unsigned	flags;		/* Optional info, see values above. */
+
+	/* Callback functions. */
+	TS_serial_cb serial_cb;
+	void *serial_cb_data;	/* User data for serial_cb. */
+
+	TS_time_cb time_cb;
+	void *time_cb_data;	/* User data for time_cb. */
+
+	TS_extension_cb extension_cb;
+	void *extension_cb_data;	/* User data for extension_cb. */
+
+	/* These members are used only while creating the response. */
+	TS_REQ		*request;
+	TS_RESP		*response;
+	TS_TST_INFO	*tst_info;
+};
+
+/* Context structure for the generic verify method. */
+
+struct TS_verify_ctx {
+	/* Set this to the union of TS_VFY_... flags you want to carry out. */
+	unsigned	flags;
+
+	/* Must be set only with TS_VFY_SIGNATURE. certs is optional. */
+	X509_STORE	*store;
+	STACK_OF(X509)	*certs;
+
+	/* Must be set only with TS_VFY_POLICY. */
+	ASN1_OBJECT	*policy;
+
+	/* Must be set only with TS_VFY_IMPRINT. If md_alg is NULL,
+	   the algorithm from the response is used. */
+	X509_ALGOR	*md_alg;
+	unsigned char	*imprint;
+	unsigned	imprint_len;
+
+	/* Must be set only with TS_VFY_DATA. */
+	BIO		*data;
+
+	/* Must be set only with TS_VFY_TSA_NAME. */
+	ASN1_INTEGER	*nonce;
+
+	/* Must be set only with TS_VFY_TSA_NAME. */
+	GENERAL_NAME	*tsa_name;
+};
+
+/*
+ * Public OpenSSL API that we do not currently want to expose.
+ */
+
+ESS_CERT_ID_V2 *ESS_CERT_ID_V2_new(void);
+void ESS_CERT_ID_V2_free(ESS_CERT_ID_V2 *a);
+int i2d_ESS_CERT_ID_V2(const ESS_CERT_ID_V2 *a, unsigned char **pp);
+ESS_CERT_ID_V2 *d2i_ESS_CERT_ID_V2(ESS_CERT_ID_V2 **a, const unsigned char **pp,
+    long length);
+ESS_CERT_ID_V2 *ESS_CERT_ID_V2_dup(ESS_CERT_ID_V2 *a);
+
+ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_new(void);
+void ESS_SIGNING_CERT_V2_free(ESS_SIGNING_CERT_V2 *a);
+int i2d_ESS_SIGNING_CERT_V2(const ESS_SIGNING_CERT_V2 *a,
+    unsigned char **pp);
+ESS_SIGNING_CERT_V2 *d2i_ESS_SIGNING_CERT_V2(ESS_SIGNING_CERT_V2 **a,
+    const unsigned char **pp, long length);
+ESS_SIGNING_CERT_V2 *ESS_SIGNING_CERT_V2_dup(ESS_SIGNING_CERT_V2 *a);
+
+__END_HIDDEN_DECLS
+
+#endif /* !HEADER_TS_LOCAL_H */
diff --git a/crypto/ts/ts_req_print.c b/crypto/ts/ts_req_print.c
new file mode 100644
index 0000000..ddcdda9
--- /dev/null
+++ b/crypto/ts/ts_req_print.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: ts_req_print.c,v 1.5 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+/* Function definitions. */
+
+int
+TS_REQ_print_bio(BIO *bio, TS_REQ *a)
+{
+	int v;
+	ASN1_OBJECT *policy_id;
+	const ASN1_INTEGER *nonce;
+
+	if (a == NULL)
+		return 0;
+
+	v = TS_REQ_get_version(a);
+	BIO_printf(bio, "Version: %d\n", v);
+
+	TS_MSG_IMPRINT_print_bio(bio, TS_REQ_get_msg_imprint(a));
+
+	BIO_printf(bio, "Policy OID: ");
+	policy_id = TS_REQ_get_policy_id(a);
+	if (policy_id == NULL)
+		BIO_printf(bio, "unspecified\n");
+	else
+		TS_OBJ_print_bio(bio, policy_id);
+
+	BIO_printf(bio, "Nonce: ");
+	nonce = TS_REQ_get_nonce(a);
+	if (nonce == NULL)
+		BIO_printf(bio, "unspecified");
+	else
+		TS_ASN1_INTEGER_print_bio(bio, nonce);
+	BIO_write(bio, "\n", 1);
+
+	BIO_printf(bio, "Certificate required: %s\n",
+	    TS_REQ_get_cert_req(a) ? "yes" : "no");
+
+	TS_ext_print_bio(bio, TS_REQ_get_exts(a));
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_REQ_print_bio);
diff --git a/crypto/ts/ts_req_utils.c b/crypto/ts/ts_req_utils.c
new file mode 100644
index 0000000..d679418
--- /dev/null
+++ b/crypto/ts/ts_req_utils.c
@@ -0,0 +1,281 @@
+/* $OpenBSD: ts_req_utils.c,v 1.9 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ts_local.h"
+
+int
+TS_REQ_set_version(TS_REQ *a, long version)
+{
+	return ASN1_INTEGER_set(a->version, version);
+}
+LCRYPTO_ALIAS(TS_REQ_set_version);
+
+long
+TS_REQ_get_version(const TS_REQ *a)
+{
+	return ASN1_INTEGER_get(a->version);
+}
+LCRYPTO_ALIAS(TS_REQ_get_version);
+
+int
+TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint)
+{
+	TS_MSG_IMPRINT *new_msg_imprint;
+
+	if (a->msg_imprint == msg_imprint)
+		return 1;
+	new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint);
+	if (new_msg_imprint == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	TS_MSG_IMPRINT_free(a->msg_imprint);
+	a->msg_imprint = new_msg_imprint;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_REQ_set_msg_imprint);
+
+TS_MSG_IMPRINT *
+TS_REQ_get_msg_imprint(TS_REQ *a)
+{
+	return a->msg_imprint;
+}
+LCRYPTO_ALIAS(TS_REQ_get_msg_imprint);
+
+int
+TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg)
+{
+	X509_ALGOR *new_alg;
+
+	if (a->hash_algo == alg)
+		return 1;
+	new_alg = X509_ALGOR_dup(alg);
+	if (new_alg == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	X509_ALGOR_free(a->hash_algo);
+	a->hash_algo = new_alg;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_set_algo);
+
+X509_ALGOR *
+TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a)
+{
+	return a->hash_algo;
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_get_algo);
+
+int
+TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len)
+{
+	return ASN1_OCTET_STRING_set(a->hashed_msg, d, len);
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_set_msg);
+
+ASN1_OCTET_STRING *
+TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a)
+{
+	return a->hashed_msg;
+}
+LCRYPTO_ALIAS(TS_MSG_IMPRINT_get_msg);
+
+int
+TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy)
+{
+	ASN1_OBJECT *new_policy;
+
+	if (a->policy_id == policy)
+		return 1;
+	new_policy = OBJ_dup(policy);
+	if (new_policy == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_OBJECT_free(a->policy_id);
+	a->policy_id = new_policy;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_REQ_set_policy_id);
+
+ASN1_OBJECT *
+TS_REQ_get_policy_id(TS_REQ *a)
+{
+	return a->policy_id;
+}
+LCRYPTO_ALIAS(TS_REQ_get_policy_id);
+
+int
+TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce)
+{
+	ASN1_INTEGER *new_nonce;
+
+	if (a->nonce == nonce)
+		return 1;
+	new_nonce = ASN1_INTEGER_dup(nonce);
+	if (new_nonce == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_INTEGER_free(a->nonce);
+	a->nonce = new_nonce;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_REQ_set_nonce);
+
+const ASN1_INTEGER *
+TS_REQ_get_nonce(const TS_REQ *a)
+{
+	return a->nonce;
+}
+LCRYPTO_ALIAS(TS_REQ_get_nonce);
+
+int
+TS_REQ_set_cert_req(TS_REQ *a, int cert_req)
+{
+	a->cert_req = cert_req ? 0xFF : 0x00;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_REQ_set_cert_req);
+
+int
+TS_REQ_get_cert_req(const TS_REQ *a)
+{
+	return a->cert_req ? 1 : 0;
+}
+LCRYPTO_ALIAS(TS_REQ_get_cert_req);
+
+STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a)
+{
+	return a->extensions;
+}
+LCRYPTO_ALIAS(TS_REQ_get_exts);
+
+void
+TS_REQ_ext_free(TS_REQ *a)
+{
+	if (!a)
+		return;
+	sk_X509_EXTENSION_pop_free(a->extensions, X509_EXTENSION_free);
+	a->extensions = NULL;
+}
+LCRYPTO_ALIAS(TS_REQ_ext_free);
+
+int
+TS_REQ_get_ext_count(TS_REQ *a)
+{
+	return X509v3_get_ext_count(a->extensions);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext_count);
+
+int
+TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(a->extensions, nid, lastpos);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext_by_NID);
+
+int
+TS_REQ_get_ext_by_OBJ(TS_REQ *a, const ASN1_OBJECT *obj, int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(a->extensions, obj, lastpos);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext_by_OBJ);
+
+int
+TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(a->extensions, crit, lastpos);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext_by_critical);
+
+X509_EXTENSION *
+TS_REQ_get_ext(TS_REQ *a, int loc)
+{
+	return X509v3_get_ext(a->extensions, loc);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext);
+
+X509_EXTENSION *
+TS_REQ_delete_ext(TS_REQ *a, int loc)
+{
+	return X509v3_delete_ext(a->extensions, loc);
+}
+LCRYPTO_ALIAS(TS_REQ_delete_ext);
+
+int
+TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&a->extensions, ex, loc) != NULL;
+}
+LCRYPTO_ALIAS(TS_REQ_add_ext);
+
+void *
+TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(a->extensions, nid, crit, idx);
+}
+LCRYPTO_ALIAS(TS_REQ_get_ext_d2i);
diff --git a/crypto/ts/ts_rsp_print.c b/crypto/ts/ts_rsp_print.c
new file mode 100644
index 0000000..c65d226
--- /dev/null
+++ b/crypto/ts/ts_rsp_print.c
@@ -0,0 +1,306 @@
+/* $OpenBSD: ts_rsp_print.c,v 1.7 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ts_local.h"
+
+struct status_map_st {
+	int bit;
+	const char *text;
+};
+
+/* Local function declarations. */
+
+static int TS_status_map_print(BIO *bio, struct status_map_st *a,
+    ASN1_BIT_STRING *v);
+static int TS_ACCURACY_print_bio(BIO *bio, const TS_ACCURACY *accuracy);
+
+/* Function definitions. */
+
+int
+TS_RESP_print_bio(BIO *bio, TS_RESP *a)
+{
+	TS_TST_INFO *tst_info;
+
+	BIO_printf(bio, "Status info:\n");
+	TS_STATUS_INFO_print_bio(bio, TS_RESP_get_status_info(a));
+
+	BIO_printf(bio, "\nTST info:\n");
+	tst_info = TS_RESP_get_tst_info(a);
+	if (tst_info != NULL)
+		TS_TST_INFO_print_bio(bio, TS_RESP_get_tst_info(a));
+	else
+		BIO_printf(bio, "Not included.\n");
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_print_bio);
+
+int
+TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a)
+{
+	static const char *status_map[] = {
+		"Granted.",
+		"Granted with modifications.",
+		"Rejected.",
+		"Waiting.",
+		"Revocation warning.",
+		"Revoked."
+	};
+	static struct status_map_st failure_map[] = {
+		{
+			TS_INFO_BAD_ALG,
+			"unrecognized or unsupported algorithm identifier"
+		},
+		{
+			TS_INFO_BAD_REQUEST,
+			"transaction not permitted or supported"
+		},
+		{
+			TS_INFO_BAD_DATA_FORMAT,
+			"the data submitted has the wrong format"
+		},
+		{
+			TS_INFO_TIME_NOT_AVAILABLE,
+			"the TSA's time source is not available"
+		},
+		{
+			TS_INFO_UNACCEPTED_POLICY,
+			"the requested TSA policy is not supported by the TSA"
+		},
+		{
+			TS_INFO_UNACCEPTED_EXTENSION,
+			"the requested extension is not supported by the TSA"
+		},
+		{
+			TS_INFO_ADD_INFO_NOT_AVAILABLE,
+			"the additional information requested could not be understood "
+			"or is not available"
+		},
+		{
+			TS_INFO_SYSTEM_FAILURE,
+			"the request cannot be handled due to system failure"
+		},
+		{ -1, NULL }
+	};
+	long status;
+	int i, lines = 0;
+
+	/* Printing status code. */
+	BIO_printf(bio, "Status: ");
+	status = ASN1_INTEGER_get(a->status);
+	if (0 <= status &&
+	    status < (long)(sizeof(status_map) / sizeof(status_map[0])))
+		BIO_printf(bio, "%s\n", status_map[status]);
+	else
+		BIO_printf(bio, "out of bounds\n");
+
+	/* Printing status description. */
+	BIO_printf(bio, "Status description: ");
+	for (i = 0; i < sk_ASN1_UTF8STRING_num(a->text); ++i) {
+		if (i > 0)
+			BIO_puts(bio, "\t");
+		ASN1_STRING_print_ex(bio, sk_ASN1_UTF8STRING_value(a->text, i),
+		    0);
+		BIO_puts(bio, "\n");
+	}
+	if (i == 0)
+		BIO_printf(bio, "unspecified\n");
+
+	/* Printing failure information. */
+	BIO_printf(bio, "Failure info: ");
+	if (a->failure_info != NULL)
+		lines = TS_status_map_print(bio, failure_map, a->failure_info);
+	if (lines == 0)
+		BIO_printf(bio, "unspecified");
+	BIO_printf(bio, "\n");
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_print_bio);
+
+static int
+TS_status_map_print(BIO *bio, struct status_map_st *a, ASN1_BIT_STRING *v)
+{
+	int lines = 0;
+
+	for (; a->bit >= 0; ++a) {
+		if (ASN1_BIT_STRING_get_bit(v, a->bit)) {
+			if (++lines > 1)
+				BIO_printf(bio, ", ");
+			BIO_printf(bio, "%s", a->text);
+		}
+	}
+
+	return lines;
+}
+
+int
+TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a)
+{
+	int v;
+	ASN1_OBJECT *policy_id;
+	const ASN1_INTEGER *serial;
+	const ASN1_GENERALIZEDTIME *gtime;
+	TS_ACCURACY *accuracy;
+	const ASN1_INTEGER *nonce;
+	GENERAL_NAME *tsa_name;
+
+	if (a == NULL)
+		return 0;
+
+	/* Print version. */
+	v = TS_TST_INFO_get_version(a);
+	BIO_printf(bio, "Version: %d\n", v);
+
+	/* Print policy id. */
+	BIO_printf(bio, "Policy OID: ");
+	policy_id = TS_TST_INFO_get_policy_id(a);
+	TS_OBJ_print_bio(bio, policy_id);
+
+	/* Print message imprint. */
+	TS_MSG_IMPRINT_print_bio(bio, TS_TST_INFO_get_msg_imprint(a));
+
+	/* Print serial number. */
+	BIO_printf(bio, "Serial number: ");
+	serial = TS_TST_INFO_get_serial(a);
+	if (serial == NULL)
+		BIO_printf(bio, "unspecified");
+	else
+		TS_ASN1_INTEGER_print_bio(bio, serial);
+	BIO_write(bio, "\n", 1);
+
+	/* Print time stamp. */
+	BIO_printf(bio, "Time stamp: ");
+	gtime = TS_TST_INFO_get_time(a);
+	ASN1_GENERALIZEDTIME_print(bio, gtime);
+	BIO_write(bio, "\n", 1);
+
+	/* Print accuracy. */
+	BIO_printf(bio, "Accuracy: ");
+	accuracy = TS_TST_INFO_get_accuracy(a);
+	if (accuracy == NULL)
+		BIO_printf(bio, "unspecified");
+	else
+		TS_ACCURACY_print_bio(bio, accuracy);
+	BIO_write(bio, "\n", 1);
+
+	/* Print ordering. */
+	BIO_printf(bio, "Ordering: %s\n",
+	    TS_TST_INFO_get_ordering(a) ? "yes" : "no");
+
+	/* Print nonce. */
+	BIO_printf(bio, "Nonce: ");
+	nonce = TS_TST_INFO_get_nonce(a);
+	if (nonce == NULL)
+		BIO_printf(bio, "unspecified");
+	else
+		TS_ASN1_INTEGER_print_bio(bio, nonce);
+	BIO_write(bio, "\n", 1);
+
+	/* Print TSA name. */
+	BIO_printf(bio, "TSA: ");
+	tsa_name = TS_TST_INFO_get_tsa(a);
+	if (tsa_name == NULL)
+		BIO_printf(bio, "unspecified");
+	else {
+		STACK_OF(CONF_VALUE) *nval;
+		if ((nval = i2v_GENERAL_NAME(NULL, tsa_name, NULL)))
+			X509V3_EXT_val_prn(bio, nval, 0, 0);
+		sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+	}
+	BIO_write(bio, "\n", 1);
+
+	/* Print extensions. */
+	TS_ext_print_bio(bio, TS_TST_INFO_get_exts(a));
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_print_bio);
+
+static int
+TS_ACCURACY_print_bio(BIO *bio, const TS_ACCURACY *accuracy)
+{
+	const ASN1_INTEGER *seconds = TS_ACCURACY_get_seconds(accuracy);
+	const ASN1_INTEGER *millis = TS_ACCURACY_get_millis(accuracy);
+	const ASN1_INTEGER *micros = TS_ACCURACY_get_micros(accuracy);
+
+	if (seconds != NULL)
+		TS_ASN1_INTEGER_print_bio(bio, seconds);
+	else
+		BIO_printf(bio, "unspecified");
+	BIO_printf(bio, " seconds, ");
+	if (millis != NULL)
+		TS_ASN1_INTEGER_print_bio(bio, millis);
+	else
+		BIO_printf(bio, "unspecified");
+	BIO_printf(bio, " millis, ");
+	if (micros != NULL)
+		TS_ASN1_INTEGER_print_bio(bio, micros);
+	else
+		BIO_printf(bio, "unspecified");
+	BIO_printf(bio, " micros");
+
+	return 1;
+}
diff --git a/crypto/ts/ts_rsp_sign.c b/crypto/ts/ts_rsp_sign.c
new file mode 100644
index 0000000..3013cff
--- /dev/null
+++ b/crypto/ts/ts_rsp_sign.c
@@ -0,0 +1,1058 @@
+/* $OpenBSD: ts_rsp_sign.c,v 1.32 2023/08/22 08:09:36 tb Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "ts_local.h"
+#include "x509_local.h"
+
+/* Private function declarations. */
+
+static ASN1_INTEGER *def_serial_cb(struct TS_resp_ctx *, void *);
+static int def_time_cb(struct TS_resp_ctx *, void *, time_t *sec, long *usec);
+static int def_extension_cb(struct TS_resp_ctx *, X509_EXTENSION *, void *);
+
+static void TS_RESP_CTX_init(TS_RESP_CTX *ctx);
+static void TS_RESP_CTX_cleanup(TS_RESP_CTX *ctx);
+static int TS_RESP_check_request(TS_RESP_CTX *ctx);
+static ASN1_OBJECT *TS_RESP_get_policy(TS_RESP_CTX *ctx);
+static TS_TST_INFO *TS_RESP_create_tst_info(TS_RESP_CTX *ctx,
+    ASN1_OBJECT *policy);
+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 ASN1_GENERALIZEDTIME *TS_RESP_set_genTime_with_precision(
+    ASN1_GENERALIZEDTIME *, time_t, long, unsigned);
+
+/* Default callbacks for response generation. */
+
+static ASN1_INTEGER *
+def_serial_cb(struct TS_resp_ctx *ctx, void *data)
+{
+	ASN1_INTEGER *serial;
+
+	if ((serial = ASN1_INTEGER_new()) == NULL)
+		goto err;
+	if (!ASN1_INTEGER_set(serial, 1))
+		goto err;
+
+	return serial;
+
+ err:
+	ASN1_INTEGER_free(serial);
+	TSerror(ERR_R_MALLOC_FAILURE);
+	TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+	    "Error during serial number generation.");
+
+	return NULL;
+}
+
+/* Use the gettimeofday function call. */
+static int
+def_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
+{
+	struct timeval tv;
+
+	if (gettimeofday(&tv, NULL) != 0) {
+		TSerror(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);
+		return 0;
+	}
+	/* Return time to caller. */
+	*sec = tv.tv_sec;
+	*usec = tv.tv_usec;
+
+	return 1;
+}
+
+static int
+def_extension_cb(struct TS_resp_ctx *ctx, X509_EXTENSION *ext, void *data)
+{
+	/* No extensions are processed here. */
+	TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+	    "Unsupported extension.");
+	TS_RESP_CTX_add_failure_info(ctx, TS_INFO_UNACCEPTED_EXTENSION);
+	return 0;
+}
+
+void
+TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data)
+{
+	ctx->time_cb = cb;
+	ctx->time_cb_data = data;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_time_cb);
+
+/* TS_RESP_CTX management functions. */
+
+TS_RESP_CTX *
+TS_RESP_CTX_new(void)
+{
+	TS_RESP_CTX *ctx;
+
+	if (!(ctx = calloc(1, sizeof(TS_RESP_CTX)))) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+
+	/* Setting default callbacks. */
+	ctx->serial_cb = def_serial_cb;
+	ctx->time_cb = def_time_cb;
+	ctx->extension_cb = def_extension_cb;
+
+	return ctx;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_new);
+
+void
+TS_RESP_CTX_free(TS_RESP_CTX *ctx)
+{
+	if (!ctx)
+		return;
+
+	X509_free(ctx->signer_cert);
+	EVP_PKEY_free(ctx->signer_key);
+	sk_X509_pop_free(ctx->certs, X509_free);
+	sk_ASN1_OBJECT_pop_free(ctx->policies, ASN1_OBJECT_free);
+	ASN1_OBJECT_free(ctx->default_policy);
+	sk_EVP_MD_free(ctx->mds);	/* No EVP_MD_free method exists. */
+	ASN1_INTEGER_free(ctx->seconds);
+	ASN1_INTEGER_free(ctx->millis);
+	ASN1_INTEGER_free(ctx->micros);
+	free(ctx);
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_free);
+
+int
+TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer)
+{
+	if (X509_check_purpose(signer, X509_PURPOSE_TIMESTAMP_SIGN, 0) != 1) {
+		TSerror(TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE);
+		return 0;
+	}
+	X509_free(ctx->signer_cert);
+	ctx->signer_cert = signer;
+	CRYPTO_add(&ctx->signer_cert->references, +1, CRYPTO_LOCK_X509);
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_signer_cert);
+
+int
+TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key)
+{
+	EVP_PKEY_free(ctx->signer_key);
+	ctx->signer_key = key;
+	CRYPTO_add(&ctx->signer_key->references, +1, CRYPTO_LOCK_EVP_PKEY);
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_signer_key);
+
+int
+TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy)
+{
+	if (ctx->default_policy)
+		ASN1_OBJECT_free(ctx->default_policy);
+	if (!(ctx->default_policy = OBJ_dup(def_policy)))
+		goto err;
+	return 1;
+
+err:
+	TSerror(ERR_R_MALLOC_FAILURE);
+	return 0;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_def_policy);
+
+int
+TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs)
+{
+	int i;
+
+	if (ctx->certs) {
+		sk_X509_pop_free(ctx->certs, X509_free);
+		ctx->certs = NULL;
+	}
+	if (!certs)
+		return 1;
+	if (!(ctx->certs = sk_X509_dup(certs))) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	for (i = 0; i < sk_X509_num(ctx->certs); ++i) {
+		X509 *cert = sk_X509_value(ctx->certs, i);
+		CRYPTO_add(&cert->references, +1, CRYPTO_LOCK_X509);
+	}
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_certs);
+
+int
+TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy)
+{
+	ASN1_OBJECT *copy = NULL;
+
+	/* Create new policy stack if necessary. */
+	if (!ctx->policies && !(ctx->policies = sk_ASN1_OBJECT_new_null()))
+		goto err;
+	if (!(copy = OBJ_dup(policy)))
+		goto err;
+	if (!sk_ASN1_OBJECT_push(ctx->policies, copy))
+		goto err;
+
+	return 1;
+
+err:
+	TSerror(ERR_R_MALLOC_FAILURE);
+	ASN1_OBJECT_free(copy);
+	return 0;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_add_policy);
+
+int
+TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md)
+{
+	/* Create new md stack if necessary. */
+	if (!ctx->mds && !(ctx->mds = sk_EVP_MD_new_null()))
+		goto err;
+	/* Add the shared md, no copy needed. */
+	if (!sk_EVP_MD_push(ctx->mds, (EVP_MD *)md))
+		goto err;
+
+	return 1;
+
+err:
+	TSerror(ERR_R_MALLOC_FAILURE);
+	return 0;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_add_md);
+
+#define TS_RESP_CTX_accuracy_free(ctx)		\
+	ASN1_INTEGER_free(ctx->seconds);	\
+	ctx->seconds = NULL;			\
+	ASN1_INTEGER_free(ctx->millis);		\
+	ctx->millis = NULL;			\
+	ASN1_INTEGER_free(ctx->micros);		\
+	ctx->micros = NULL;
+
+int
+TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, int secs, int millis, int micros)
+{
+	TS_RESP_CTX_accuracy_free(ctx);
+	if (secs && (!(ctx->seconds = ASN1_INTEGER_new()) ||
+	    !ASN1_INTEGER_set(ctx->seconds, secs)))
+		goto err;
+	if (millis && (!(ctx->millis = ASN1_INTEGER_new()) ||
+	    !ASN1_INTEGER_set(ctx->millis, millis)))
+		goto err;
+	if (micros && (!(ctx->micros = ASN1_INTEGER_new()) ||
+	    !ASN1_INTEGER_set(ctx->micros, micros)))
+		goto err;
+
+	return 1;
+
+err:
+	TS_RESP_CTX_accuracy_free(ctx);
+	TSerror(ERR_R_MALLOC_FAILURE);
+	return 0;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_accuracy);
+
+void
+TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags)
+{
+	ctx->flags |= flags;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_add_flags);
+
+void
+TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data)
+{
+	ctx->serial_cb = cb;
+	ctx->serial_cb_data = data;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_serial_cb);
+
+void
+TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, TS_extension_cb cb, void *data)
+{
+	ctx->extension_cb = cb;
+	ctx->extension_cb_data = data;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_extension_cb);
+
+int
+TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, int status, const char *text)
+{
+	TS_STATUS_INFO *si = NULL;
+	ASN1_UTF8STRING *utf8_text = NULL;
+	int ret = 0;
+
+	if (!(si = TS_STATUS_INFO_new()))
+		goto err;
+	if (!ASN1_INTEGER_set(si->status, status))
+		goto err;
+	if (text) {
+		if (!(utf8_text = ASN1_UTF8STRING_new()) ||
+		    !ASN1_STRING_set(utf8_text, text, strlen(text)))
+			goto err;
+		if (!si->text && !(si->text = sk_ASN1_UTF8STRING_new_null()))
+			goto err;
+		if (!sk_ASN1_UTF8STRING_push(si->text, utf8_text))
+			goto err;
+		utf8_text = NULL;	/* Ownership is lost. */
+	}
+	if (!TS_RESP_set_status_info(ctx->response, si))
+		goto err;
+	ret = 1;
+
+err:
+	if (!ret)
+		TSerror(ERR_R_MALLOC_FAILURE);
+	TS_STATUS_INFO_free(si);
+	ASN1_UTF8STRING_free(utf8_text);
+	return ret;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_status_info);
+
+int
+TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, int status, const char *text)
+{
+	int ret = 1;
+	TS_STATUS_INFO *si = TS_RESP_get_status_info(ctx->response);
+
+	if (ASN1_INTEGER_get(si->status) == TS_STATUS_GRANTED) {
+		/* Status has not been set, set it now. */
+		ret = TS_RESP_CTX_set_status_info(ctx, status, text);
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_status_info_cond);
+
+int
+TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure)
+{
+	TS_STATUS_INFO *si = TS_RESP_get_status_info(ctx->response);
+
+	if (!si->failure_info && !(si->failure_info = ASN1_BIT_STRING_new()))
+		goto err;
+	if (!ASN1_BIT_STRING_set_bit(si->failure_info, failure, 1))
+		goto err;
+	return 1;
+
+err:
+	TSerror(ERR_R_MALLOC_FAILURE);
+	return 0;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_add_failure_info);
+
+TS_REQ *
+TS_RESP_CTX_get_request(TS_RESP_CTX *ctx)
+{
+	return ctx->request;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_get_request);
+
+TS_TST_INFO *
+TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx)
+{
+	return ctx->tst_info;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_get_tst_info);
+
+int
+TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, unsigned precision)
+{
+	if (precision > TS_MAX_CLOCK_PRECISION_DIGITS)
+		return 0;
+	ctx->clock_precision_digits = precision;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_CTX_set_clock_precision_digits);
+
+/* Main entry method of the response generation. */
+TS_RESP *
+TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio)
+{
+	ASN1_OBJECT *policy;
+	TS_RESP *response;
+	int result = 0;
+
+	TS_RESP_CTX_init(ctx);
+
+	/* Creating the response object. */
+	if (!(ctx->response = TS_RESP_new())) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto end;
+	}
+
+	/* Parsing DER request. */
+	if (!(ctx->request = d2i_TS_REQ_bio(req_bio, NULL))) {
+		TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+		    "Bad request format or "
+		    "system error.");
+		TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_DATA_FORMAT);
+		goto end;
+	}
+
+	/* Setting default status info. */
+	if (!TS_RESP_CTX_set_status_info(ctx, TS_STATUS_GRANTED, NULL))
+		goto end;
+
+	/* Checking the request format. */
+	if (!TS_RESP_check_request(ctx))
+		goto end;
+
+	/* Checking acceptable policies. */
+	if (!(policy = TS_RESP_get_policy(ctx)))
+		goto end;
+
+	/* Creating the TS_TST_INFO object. */
+	if (!(ctx->tst_info = TS_RESP_create_tst_info(ctx, policy)))
+		goto end;
+
+	/* Processing extensions. */
+	if (!TS_RESP_process_extensions(ctx))
+		goto end;
+
+	/* Generating the signature. */
+	if (!TS_RESP_sign(ctx))
+		goto end;
+
+	/* Everything was successful. */
+	result = 1;
+
+end:
+	if (!result) {
+		TSerror(TS_R_RESPONSE_SETUP_ERROR);
+		if (ctx->response != NULL) {
+			if (TS_RESP_CTX_set_status_info_cond(ctx,
+			    TS_STATUS_REJECTION, "Error during response "
+			    "generation.") == 0) {
+				TS_RESP_free(ctx->response);
+				ctx->response = NULL;
+			}
+		}
+	}
+	response = ctx->response;
+	ctx->response = NULL;	/* Ownership will be returned to caller. */
+	TS_RESP_CTX_cleanup(ctx);
+	return response;
+}
+LCRYPTO_ALIAS(TS_RESP_create_response);
+
+/* Initializes the variable part of the context. */
+static void
+TS_RESP_CTX_init(TS_RESP_CTX *ctx)
+{
+	ctx->request = NULL;
+	ctx->response = NULL;
+	ctx->tst_info = NULL;
+}
+
+/* Cleans up the variable part of the context. */
+static void
+TS_RESP_CTX_cleanup(TS_RESP_CTX *ctx)
+{
+	TS_REQ_free(ctx->request);
+	ctx->request = NULL;
+	TS_RESP_free(ctx->response);
+	ctx->response = NULL;
+	TS_TST_INFO_free(ctx->tst_info);
+	ctx->tst_info = NULL;
+}
+
+/* Checks the format and content of the request. */
+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;
+	const ASN1_OCTET_STRING *digest;
+	EVP_MD *md = NULL;
+	int i;
+
+	/* Checking request version. */
+	if (TS_REQ_get_version(request) != 1) {
+		TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+		    "Bad request version.");
+		TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_REQUEST);
+		return 0;
+	}
+
+	/* Checking message digest algorithm. */
+	msg_imprint = TS_REQ_get_msg_imprint(request);
+	md_alg = TS_MSG_IMPRINT_get_algo(msg_imprint);
+	md_alg_id = OBJ_obj2nid(md_alg->algorithm);
+	for (i = 0; !md && i < sk_EVP_MD_num(ctx->mds); ++i) {
+		EVP_MD *current_md = sk_EVP_MD_value(ctx->mds, i);
+		if (md_alg_id == EVP_MD_type(current_md))
+			md = current_md;
+	}
+	if (!md) {
+		TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+		    "Message digest algorithm is "
+		    "not supported.");
+		TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG);
+		return 0;
+	}
+
+	/* No message digest takes parameter. */
+	if (md_alg->parameter &&
+	    ASN1_TYPE_get(md_alg->parameter) != V_ASN1_NULL) {
+		TS_RESP_CTX_set_status_info(ctx, TS_STATUS_REJECTION,
+		    "Superfluous message digest "
+		    "parameter.");
+		TS_RESP_CTX_add_failure_info(ctx, TS_INFO_BAD_ALG);
+		return 0;
+	}
+	/* Checking message digest size. */
+	digest = TS_MSG_IMPRINT_get_msg(msg_imprint);
+	if (digest->length != EVP_MD_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);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Returns the TSA policy based on the requested and acceptable policies. */
+static ASN1_OBJECT *
+TS_RESP_get_policy(TS_RESP_CTX *ctx)
+{
+	ASN1_OBJECT *requested = TS_REQ_get_policy_id(ctx->request);
+	ASN1_OBJECT *policy = NULL;
+	int i;
+
+	if (ctx->default_policy == NULL) {
+		TSerror(TS_R_INVALID_NULL_POINTER);
+		return NULL;
+	}
+	/* Return the default policy if none is requested or the default is
+	   requested. */
+	if (!requested || !OBJ_cmp(requested, ctx->default_policy))
+		policy = ctx->default_policy;
+
+	/* Check if the policy is acceptable. */
+	for (i = 0; !policy && i < sk_ASN1_OBJECT_num(ctx->policies); ++i) {
+		ASN1_OBJECT *current = sk_ASN1_OBJECT_value(ctx->policies, i);
+		if (!OBJ_cmp(requested, current))
+			policy = current;
+	}
+	if (!policy) {
+		TSerror(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);
+	}
+	return policy;
+}
+
+/* Creates the TS_TST_INFO object based on the settings of the context. */
+static TS_TST_INFO *
+TS_RESP_create_tst_info(TS_RESP_CTX *ctx, ASN1_OBJECT *policy)
+{
+	int result = 0;
+	TS_TST_INFO *tst_info = NULL;
+	ASN1_INTEGER *serial = NULL;
+	ASN1_GENERALIZEDTIME *asn1_time = NULL;
+	time_t sec;
+	long usec;
+	TS_ACCURACY *accuracy = NULL;
+	const ASN1_INTEGER *nonce;
+	GENERAL_NAME *tsa_name = NULL;
+
+	if (!(tst_info = TS_TST_INFO_new()))
+		goto end;
+	if (!TS_TST_INFO_set_version(tst_info, 1))
+		goto end;
+	if (!TS_TST_INFO_set_policy_id(tst_info, policy))
+		goto end;
+	if (!TS_TST_INFO_set_msg_imprint(tst_info, ctx->request->msg_imprint))
+		goto end;
+	if (!(serial = (*ctx->serial_cb)(ctx, ctx->serial_cb_data)) ||
+	    !TS_TST_INFO_set_serial(tst_info, serial))
+		goto end;
+	if (!(*ctx->time_cb)(ctx, ctx->time_cb_data, &sec, &usec) ||
+	    !(asn1_time = TS_RESP_set_genTime_with_precision(NULL, sec, usec,
+	    ctx->clock_precision_digits)) ||
+	    !TS_TST_INFO_set_time(tst_info, asn1_time))
+		goto end;
+
+	/* Setting accuracy if needed. */
+	if ((ctx->seconds || ctx->millis || ctx->micros) &&
+	    !(accuracy = TS_ACCURACY_new()))
+		goto end;
+
+	if (ctx->seconds && !TS_ACCURACY_set_seconds(accuracy, ctx->seconds))
+		goto end;
+	if (ctx->millis && !TS_ACCURACY_set_millis(accuracy, ctx->millis))
+		goto end;
+	if (ctx->micros && !TS_ACCURACY_set_micros(accuracy, ctx->micros))
+		goto end;
+	if (accuracy && !TS_TST_INFO_set_accuracy(tst_info, accuracy))
+		goto end;
+
+	/* Setting ordering. */
+	if ((ctx->flags & TS_ORDERING) &&
+	    !TS_TST_INFO_set_ordering(tst_info, 1))
+		goto end;
+
+	/* Setting nonce if needed. */
+	if ((nonce = TS_REQ_get_nonce(ctx->request)) != NULL &&
+	    !TS_TST_INFO_set_nonce(tst_info, nonce))
+		goto end;
+
+	/* Setting TSA name to subject of signer certificate. */
+	if (ctx->flags & TS_TSA_NAME) {
+		if (!(tsa_name = GENERAL_NAME_new()))
+			goto end;
+		tsa_name->type = GEN_DIRNAME;
+		tsa_name->d.dirn =
+		    X509_NAME_dup(X509_get_subject_name(ctx->signer_cert));
+		if (!tsa_name->d.dirn)
+			goto end;
+		if (!TS_TST_INFO_set_tsa(tst_info, tsa_name))
+			goto end;
+	}
+
+	result = 1;
+
+end:
+	if (!result) {
+		TS_TST_INFO_free(tst_info);
+		tst_info = NULL;
+		TSerror(TS_R_TST_INFO_SETUP_ERROR);
+		TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
+		    "Error during TSTInfo "
+		    "generation.");
+	}
+	GENERAL_NAME_free(tsa_name);
+	TS_ACCURACY_free(accuracy);
+	ASN1_GENERALIZEDTIME_free(asn1_time);
+	ASN1_INTEGER_free(serial);
+
+	return tst_info;
+}
+
+/* Processing the extensions of the request. */
+static int
+TS_RESP_process_extensions(TS_RESP_CTX *ctx)
+{
+	STACK_OF(X509_EXTENSION) *exts = TS_REQ_get_exts(ctx->request);
+	int i;
+	int ok = 1;
+
+	for (i = 0; ok && i < sk_X509_EXTENSION_num(exts); ++i) {
+		X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
+		/* XXXXX The last argument was previously
+		   (void *)ctx->extension_cb, but ISO C doesn't permit
+		   converting a function pointer to void *.  For lack of
+		   better information, I'm placing a NULL there instead.
+		   The callback can pick its own address out from the ctx
+		   anyway...
+		*/
+		ok = (*ctx->extension_cb)(ctx, ext, NULL);
+	}
+
+	return ok;
+}
+
+/* Functions for signing the TS_TST_INFO structure of the context. */
+static int
+TS_RESP_sign(TS_RESP_CTX *ctx)
+{
+	int ret = 0;
+	PKCS7 *p7 = NULL;
+	PKCS7_SIGNER_INFO *si;
+	STACK_OF(X509) *certs;	/* Certificates to include in sc. */
+	ESS_SIGNING_CERT *sc = NULL;
+	ASN1_OBJECT *oid;
+	BIO *p7bio = NULL;
+	int i;
+
+	/* Check if signcert and pkey match. */
+	if (!X509_check_private_key(ctx->signer_cert, ctx->signer_key)) {
+		TSerror(TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
+		goto err;
+	}
+
+	/* Create a new PKCS7 signed object. */
+	if (!(p7 = PKCS7_new())) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!PKCS7_set_type(p7, NID_pkcs7_signed))
+		goto err;
+
+	/* Force SignedData version to be 3 instead of the default 1. */
+	if (!ASN1_INTEGER_set(p7->d.sign->version, 3))
+		goto err;
+
+	/* Add signer certificate and optional certificate chain. */
+	if (TS_REQ_get_cert_req(ctx->request)) {
+		PKCS7_add_certificate(p7, ctx->signer_cert);
+		if (ctx->certs) {
+			for (i = 0; i < sk_X509_num(ctx->certs); ++i) {
+				X509 *cert = sk_X509_value(ctx->certs, i);
+				PKCS7_add_certificate(p7, cert);
+			}
+		}
+	}
+
+	/* Add a new signer info. */
+	if (!(si = PKCS7_add_signature(p7, ctx->signer_cert,
+	    ctx->signer_key, EVP_sha1()))) {
+		TSerror(TS_R_PKCS7_ADD_SIGNATURE_ERROR);
+		goto err;
+	}
+
+	/* Add content type signed attribute to the signer info. */
+	oid = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
+	if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
+	    V_ASN1_OBJECT, oid)) {
+		TSerror(TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR);
+		goto err;
+	}
+
+	/* Create the ESS SigningCertificate attribute which contains
+	   the signer certificate id and optionally the certificate chain. */
+	certs = ctx->flags & TS_ESS_CERT_ID_CHAIN ? ctx->certs : NULL;
+	if (!(sc = ESS_SIGNING_CERT_new_init(ctx->signer_cert, certs)))
+		goto err;
+
+	/* Add SigningCertificate signed attribute to the signer info. */
+	if (!ESS_add_signing_cert(si, sc)) {
+		TSerror(TS_R_ESS_ADD_SIGNING_CERT_ERROR);
+		goto err;
+	}
+
+	/* Add a new empty NID_id_smime_ct_TSTInfo encapsulated content. */
+	if (!TS_TST_INFO_content_new(p7))
+		goto err;
+
+	/* Add the DER encoded tst_info to the PKCS7 structure. */
+	if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	/* Convert tst_info to DER. */
+	if (!i2d_TS_TST_INFO_bio(p7bio, ctx->tst_info)) {
+		TSerror(TS_R_TS_DATASIGN);
+		goto err;
+	}
+
+	/* Create the signature and add it to the signer info. */
+	if (!PKCS7_dataFinal(p7, p7bio)) {
+		TSerror(TS_R_TS_DATASIGN);
+		goto err;
+	}
+
+	/* Set new PKCS7 and TST_INFO objects. */
+	TS_RESP_set_tst_info(ctx->response, p7, ctx->tst_info);
+	p7 = NULL;		/* Ownership is lost. */
+	ctx->tst_info = NULL;	/* Ownership is lost. */
+
+	ret = 1;
+
+err:
+	if (!ret)
+		TS_RESP_CTX_set_status_info_cond(ctx, TS_STATUS_REJECTION,
+	    "Error during signature "
+	    "generation.");
+	BIO_free_all(p7bio);
+	ESS_SIGNING_CERT_free(sc);
+	PKCS7_free(p7);
+	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;
+
+	/* Creating the ESS_CERT_ID stack. */
+	if (!(sc = ESS_SIGNING_CERT_new()))
+		goto err;
+	if (!sc->cert_ids && !(sc->cert_ids = sk_ESS_CERT_ID_new_null()))
+		goto err;
+
+	/* Adding the signing certificate id. */
+	if (!(cid = ESS_CERT_ID_new_init(signcert, 0)) ||
+	    !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+		goto err;
+	/* Adding the certificate chain ids. */
+	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)) ||
+		    !sk_ESS_CERT_ID_push(sc->cert_ids, cid))
+			goto err;
+	}
+
+	return sc;
+
+err:
+	ESS_SIGNING_CERT_free(sc);
+	TSerror(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_hash[TS_HASH_LEN];
+
+	/* Recompute SHA1 hash of certificate if necessary (side effect). */
+	X509_check_purpose(cert, -1, 0);
+
+	if (!(cid = ESS_CERT_ID_new()))
+		goto err;
+
+	if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL))
+		goto err;
+
+	if (!ASN1_OCTET_STRING_set(cid->hash, cert_hash, sizeof(cert_hash)))
+		goto err;
+
+	/* Setting the issuer/serial if requested. */
+	if (issuer_needed) {
+		/* Creating issuer/serial structure. */
+		if (!cid->issuer_serial &&
+		    !(cid->issuer_serial = ESS_ISSUER_SERIAL_new()))
+			goto err;
+		/* Creating general name from the certificate issuer. */
+		if (!(name = GENERAL_NAME_new()))
+			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. */
+		/* Setting the serial number. */
+		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);
+	TSerror(ERR_R_MALLOC_FAILURE);
+	return NULL;
+}
+
+static int
+TS_TST_INFO_content_new(PKCS7 *p7)
+{
+	PKCS7 *ret = NULL;
+	ASN1_OCTET_STRING *octet_string = NULL;
+
+	/* Create new encapsulated NID_id_smime_ct_TSTInfo content. */
+	if (!(ret = PKCS7_new()))
+		goto err;
+	if (!(ret->d.other = ASN1_TYPE_new()))
+		goto err;
+	ret->type = OBJ_nid2obj(NID_id_smime_ct_TSTInfo);
+	if (!(octet_string = ASN1_OCTET_STRING_new()))
+		goto err;
+	ASN1_TYPE_set(ret->d.other, V_ASN1_OCTET_STRING, octet_string);
+	octet_string = NULL;
+
+	/* Add encapsulated content to signed PKCS7 structure. */
+	if (!PKCS7_set_content(p7, ret))
+		goto err;
+
+	return 1;
+
+err:
+	ASN1_OCTET_STRING_free(octet_string);
+	PKCS7_free(ret);
+	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 = malloc(len))) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	p = pp;
+	i2d_ESS_SIGNING_CERT(sc, &p);
+	if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len)) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	free(pp);
+	pp = NULL;
+	return PKCS7_add_signed_attribute(si,
+	    NID_id_smime_aa_signingCertificate, V_ASN1_SEQUENCE, seq);
+
+err:
+	ASN1_STRING_free(seq);
+	free(pp);
+
+	return 0;
+}
+
+
+static ASN1_GENERALIZEDTIME *
+TS_RESP_set_genTime_with_precision(ASN1_GENERALIZEDTIME *asn1_time,
+    time_t sec, long usec, unsigned precision)
+{
+	struct tm *tm = NULL;
+	char genTime_str[17 + TS_MAX_CLOCK_PRECISION_DIGITS];
+	char usecstr[TS_MAX_CLOCK_PRECISION_DIGITS + 2];
+	char *p;
+	int rv;
+
+	if (precision > TS_MAX_CLOCK_PRECISION_DIGITS)
+		goto err;
+
+	if (!(tm = gmtime(&sec)))
+		goto err;
+
+	/*
+	 * Put "genTime_str" in GeneralizedTime format.  We work around the
+	 * restrictions imposed by rfc3280 (i.e. "GeneralizedTime values MUST
+	 * NOT include fractional seconds") and OpenSSL related functions to
+	 * meet the rfc3161 requirement: "GeneralizedTime syntax can include
+	 * fraction-of-second details".
+	 */
+	if (precision > 0) {
+		/* To make things a bit harder, X.690 | ISO/IEC 8825-1 provides
+		   the following restrictions for a DER-encoding, which OpenSSL
+		   (specifically ASN1_GENERALIZEDTIME_check() function) doesn't
+		   support:
+		   "The encoding MUST terminate with a "Z" (which means "Zulu"
+		   time). The decimal point element, if present, MUST be the
+		   point option ".". The fractional-seconds elements,
+		   if present, MUST omit all trailing 0's;
+		   if the elements correspond to 0, they MUST be wholly
+		   omitted, and the decimal point element also MUST be
+		   omitted." */
+		(void) snprintf(usecstr, sizeof(usecstr), ".%06ld", usec);
+		/* truncate and trim trailing 0 */
+		usecstr[precision + 1] = '\0';
+		p = usecstr + strlen(usecstr) - 1;
+		while (p > usecstr && *p == '0')
+			*p-- = '\0';
+		/* if we've reached the beginning, delete the . too */
+		if (p == usecstr)
+			*p = '\0';
+
+	} else {
+		/* empty */
+		usecstr[0] = '\0';
+	}
+	rv = snprintf(genTime_str, sizeof(genTime_str),
+	    "%04d%02d%02d%02d%02d%02d%sZ",
+	    tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+	    tm->tm_hour, tm->tm_min, tm->tm_sec, usecstr);
+	if (rv < 0 || rv >= sizeof(genTime_str))
+		goto err;
+
+	/* Now call OpenSSL to check and set our genTime value */
+	if (!asn1_time && !(asn1_time = ASN1_GENERALIZEDTIME_new()))
+		goto err;
+	if (!ASN1_GENERALIZEDTIME_set_string(asn1_time, genTime_str)) {
+		ASN1_GENERALIZEDTIME_free(asn1_time);
+		goto err;
+	}
+
+	return asn1_time;
+
+err:
+	TSerror(TS_R_COULD_NOT_SET_TIME);
+	return NULL;
+}
diff --git a/crypto/ts/ts_rsp_utils.c b/crypto/ts/ts_rsp_utils.c
new file mode 100644
index 0000000..34994ad
--- /dev/null
+++ b/crypto/ts/ts_rsp_utils.c
@@ -0,0 +1,503 @@
+/* $OpenBSD: ts_rsp_utils.c,v 1.11 2023/07/07 19:37:54 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ts_local.h"
+
+/* Function definitions. */
+
+int
+TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *status_info)
+{
+	TS_STATUS_INFO *new_status_info;
+
+	if (a->status_info == status_info)
+		return 1;
+	new_status_info = TS_STATUS_INFO_dup(status_info);
+	if (new_status_info == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	TS_STATUS_INFO_free(a->status_info);
+	a->status_info = new_status_info;
+
+	return 1;
+}
+LCRYPTO_ALIAS(TS_RESP_set_status_info);
+
+TS_STATUS_INFO *
+TS_RESP_get_status_info(TS_RESP *a)
+{
+	return a->status_info;
+}
+LCRYPTO_ALIAS(TS_RESP_get_status_info);
+
+const ASN1_UTF8STRING *
+TS_STATUS_INFO_get0_failure_info(const TS_STATUS_INFO *si)
+{
+	return si->failure_info;
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_get0_failure_info);
+
+const STACK_OF(ASN1_UTF8STRING) *
+TS_STATUS_INFO_get0_text(const TS_STATUS_INFO *si)
+{
+	return si->text;
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_get0_text);
+
+const ASN1_INTEGER *
+TS_STATUS_INFO_get0_status(const TS_STATUS_INFO *si)
+{
+	return si->status;
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_get0_status);
+
+int
+TS_STATUS_INFO_set_status(TS_STATUS_INFO *si, int i)
+{
+	return ASN1_INTEGER_set(si->status, i);
+}
+LCRYPTO_ALIAS(TS_STATUS_INFO_set_status);
+
+/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */
+void
+TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info)
+{
+	/* Set new PKCS7 and TST_INFO objects. */
+	PKCS7_free(a->token);
+	a->token = p7;
+	TS_TST_INFO_free(a->tst_info);
+	a->tst_info = tst_info;
+}
+LCRYPTO_ALIAS(TS_RESP_set_tst_info);
+
+PKCS7 *
+TS_RESP_get_token(TS_RESP *a)
+{
+	return a->token;
+}
+LCRYPTO_ALIAS(TS_RESP_get_token);
+
+TS_TST_INFO *
+TS_RESP_get_tst_info(TS_RESP *a)
+{
+	return a->tst_info;
+}
+LCRYPTO_ALIAS(TS_RESP_get_tst_info);
+
+int
+TS_TST_INFO_set_version(TS_TST_INFO *a, long version)
+{
+	return ASN1_INTEGER_set(a->version, version);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_version);
+
+long
+TS_TST_INFO_get_version(const TS_TST_INFO *a)
+{
+	return ASN1_INTEGER_get(a->version);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_version);
+
+int
+TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy)
+{
+	ASN1_OBJECT *new_policy;
+
+	if (a->policy_id == policy)
+		return 1;
+	new_policy = OBJ_dup(policy);
+	if (new_policy == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_OBJECT_free(a->policy_id);
+	a->policy_id = new_policy;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_policy_id);
+
+ASN1_OBJECT *
+TS_TST_INFO_get_policy_id(TS_TST_INFO *a)
+{
+	return a->policy_id;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_policy_id);
+
+int
+TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint)
+{
+	TS_MSG_IMPRINT *new_msg_imprint;
+
+	if (a->msg_imprint == msg_imprint)
+		return 1;
+	new_msg_imprint = TS_MSG_IMPRINT_dup(msg_imprint);
+	if (new_msg_imprint == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	TS_MSG_IMPRINT_free(a->msg_imprint);
+	a->msg_imprint = new_msg_imprint;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_msg_imprint);
+
+TS_MSG_IMPRINT *
+TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a)
+{
+	return a->msg_imprint;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_msg_imprint);
+
+int
+TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial)
+{
+	ASN1_INTEGER *new_serial;
+
+	if (a->serial == serial)
+		return 1;
+	new_serial = ASN1_INTEGER_dup(serial);
+	if (new_serial == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_INTEGER_free(a->serial);
+	a->serial = new_serial;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_serial);
+
+const ASN1_INTEGER *
+TS_TST_INFO_get_serial(const TS_TST_INFO *a)
+{
+	return a->serial;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_serial);
+
+int
+TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime)
+{
+	ASN1_GENERALIZEDTIME *new_time;
+
+	if (a->time == gtime)
+		return 1;
+	new_time = ASN1_STRING_dup(gtime);
+	if (new_time == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_GENERALIZEDTIME_free(a->time);
+	a->time = new_time;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_time);
+
+const ASN1_GENERALIZEDTIME *
+TS_TST_INFO_get_time(const TS_TST_INFO *a)
+{
+	return a->time;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_time);
+
+int
+TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy)
+{
+	TS_ACCURACY *new_accuracy;
+
+	if (a->accuracy == accuracy)
+		return 1;
+	new_accuracy = TS_ACCURACY_dup(accuracy);
+	if (new_accuracy == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	TS_ACCURACY_free(a->accuracy);
+	a->accuracy = new_accuracy;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_accuracy);
+
+TS_ACCURACY *
+TS_TST_INFO_get_accuracy(TS_TST_INFO *a)
+{
+	return a->accuracy;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_accuracy);
+
+int
+TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds)
+{
+	ASN1_INTEGER *new_seconds;
+
+	if (a->seconds == seconds)
+		return 1;
+	new_seconds = ASN1_INTEGER_dup(seconds);
+	if (new_seconds == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_INTEGER_free(a->seconds);
+	a->seconds = new_seconds;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_set_seconds);
+
+const ASN1_INTEGER *
+TS_ACCURACY_get_seconds(const TS_ACCURACY *a)
+{
+	return a->seconds;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_get_seconds);
+
+int
+TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis)
+{
+	ASN1_INTEGER *new_millis = NULL;
+
+	if (a->millis == millis)
+		return 1;
+	if (millis != NULL) {
+		new_millis = ASN1_INTEGER_dup(millis);
+		if (new_millis == NULL) {
+			TSerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+	ASN1_INTEGER_free(a->millis);
+	a->millis = new_millis;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_set_millis);
+
+const ASN1_INTEGER *
+TS_ACCURACY_get_millis(const TS_ACCURACY *a)
+{
+	return a->millis;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_get_millis);
+
+int
+TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros)
+{
+	ASN1_INTEGER *new_micros = NULL;
+
+	if (a->micros == micros)
+		return 1;
+	if (micros != NULL) {
+		new_micros = ASN1_INTEGER_dup(micros);
+		if (new_micros == NULL) {
+			TSerror(ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+	ASN1_INTEGER_free(a->micros);
+	a->micros = new_micros;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_set_micros);
+
+const ASN1_INTEGER *
+TS_ACCURACY_get_micros(const TS_ACCURACY *a)
+{
+	return a->micros;
+}
+LCRYPTO_ALIAS(TS_ACCURACY_get_micros);
+
+int
+TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering)
+{
+	a->ordering = ordering ? 0xFF : 0x00;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_ordering);
+
+int
+TS_TST_INFO_get_ordering(const TS_TST_INFO *a)
+{
+	return a->ordering ? 1 : 0;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ordering);
+
+int
+TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce)
+{
+	ASN1_INTEGER *new_nonce;
+
+	if (a->nonce == nonce)
+		return 1;
+	new_nonce = ASN1_INTEGER_dup(nonce);
+	if (new_nonce == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	ASN1_INTEGER_free(a->nonce);
+	a->nonce = new_nonce;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_nonce);
+
+const ASN1_INTEGER *
+TS_TST_INFO_get_nonce(const TS_TST_INFO *a)
+{
+	return a->nonce;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_nonce);
+
+int
+TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa)
+{
+	GENERAL_NAME *new_tsa;
+
+	if (a->tsa == tsa)
+		return 1;
+	new_tsa = GENERAL_NAME_dup(tsa);
+	if (new_tsa == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return 0;
+	}
+	GENERAL_NAME_free(a->tsa);
+	a->tsa = new_tsa;
+	return 1;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_set_tsa);
+
+GENERAL_NAME *
+TS_TST_INFO_get_tsa(TS_TST_INFO *a)
+{
+	return a->tsa;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_tsa);
+
+STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a)
+{
+	return a->extensions;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_exts);
+
+void
+TS_TST_INFO_ext_free(TS_TST_INFO *a)
+{
+	if (!a)
+		return;
+	sk_X509_EXTENSION_pop_free(a->extensions, X509_EXTENSION_free);
+	a->extensions = NULL;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_ext_free);
+
+int
+TS_TST_INFO_get_ext_count(TS_TST_INFO *a)
+{
+	return X509v3_get_ext_count(a->extensions);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext_count);
+
+int
+TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos)
+{
+	return X509v3_get_ext_by_NID(a->extensions, nid, lastpos);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext_by_NID);
+
+int
+TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, const ASN1_OBJECT *obj, int lastpos)
+{
+	return X509v3_get_ext_by_OBJ(a->extensions, obj, lastpos);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext_by_OBJ);
+
+int
+TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos)
+{
+	return X509v3_get_ext_by_critical(a->extensions, crit, lastpos);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext_by_critical);
+
+X509_EXTENSION *
+TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc)
+{
+	return X509v3_get_ext(a->extensions, loc);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext);
+
+X509_EXTENSION *
+TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc)
+{
+	return X509v3_delete_ext(a->extensions, loc);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_delete_ext);
+
+int
+TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc)
+{
+	return X509v3_add_ext(&a->extensions, ex, loc) != NULL;
+}
+LCRYPTO_ALIAS(TS_TST_INFO_add_ext);
+
+void *
+TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx)
+{
+	return X509V3_get_d2i(a->extensions, nid, crit, idx);
+}
+LCRYPTO_ALIAS(TS_TST_INFO_get_ext_d2i);
diff --git a/crypto/ts/ts_rsp_verify.c b/crypto/ts/ts_rsp_verify.c
new file mode 100644
index 0000000..69236f6
--- /dev/null
+++ b/crypto/ts/ts_rsp_verify.c
@@ -0,0 +1,847 @@
+/* $OpenBSD: ts_rsp_verify.c,v 1.30 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2002.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "evp_local.h"
+#include "ts_local.h"
+#include "x509_local.h"
+
+/* Private function declarations. */
+
+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 ESS_SIGNING_CERT_V2 *ESS_get_signing_cert_v2(PKCS7_SIGNER_INFO *si);
+static int TS_find_cert_v2(STACK_OF(ESS_CERT_ID_V2) *cert_ids, X509 *cert);
+static int TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert);
+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);
+static char *TS_get_status_text(STACK_OF(ASN1_UTF8STRING) *text);
+static int TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info);
+static int TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info,
+    X509_ALGOR **md_alg,
+    unsigned char **imprint, unsigned *imprint_len);
+static int TS_check_imprints(X509_ALGOR *algor_a,
+    unsigned char *imprint_a, unsigned len_a,
+    TS_TST_INFO *tst_info);
+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);
+
+/*
+ * Local mapping between response codes and descriptions.
+ * Don't forget to change TS_STATUS_BUF_SIZE when modifying
+ * the elements of this array.
+ */
+static const char *TS_status_text[] = {
+	"granted",
+	"grantedWithMods",
+	"rejection",
+	"waiting",
+	"revocationWarning",
+	"revocationNotification"
+};
+
+#define TS_STATUS_TEXT_SIZE	(sizeof(TS_status_text)/sizeof(*TS_status_text))
+
+/*
+ * This must be greater or equal to the sum of the strings in TS_status_text
+ * plus the number of its elements.
+ */
+#define TS_STATUS_BUF_SIZE	256
+
+static struct {
+	int code;
+	const char *text;
+} TS_failure_info[] = {
+	{ TS_INFO_BAD_ALG, "badAlg" },
+	{ TS_INFO_BAD_REQUEST, "badRequest" },
+	{ TS_INFO_BAD_DATA_FORMAT, "badDataFormat" },
+	{ TS_INFO_TIME_NOT_AVAILABLE, "timeNotAvailable" },
+	{ TS_INFO_UNACCEPTED_POLICY, "unacceptedPolicy" },
+	{ TS_INFO_UNACCEPTED_EXTENSION, "unacceptedExtension" },
+	{ TS_INFO_ADD_INFO_NOT_AVAILABLE, "addInfoNotAvailable" },
+	{ TS_INFO_SYSTEM_FAILURE, "systemFailure" }
+};
+
+#define TS_FAILURE_INFO_SIZE	(sizeof(TS_failure_info) / \
+				sizeof(*TS_failure_info))
+
+/* Functions for verifying a signed TS_TST_INFO structure. */
+
+/*
+ * This function carries out the following tasks:
+ *	- Checks if there is one and only one signer.
+ *	- Search for the signing certificate in 'certs' and in the response.
+ *	- Check the extended key usage and key usage fields of the signer
+ *	certificate (done by the path validation).
+ *	- Build and validate the certificate path.
+ *	- Check if the certificate path meets the requirements of the
+ *	SigningCertificate ESS signed attribute.
+ *	- Verify the signature value.
+ *	- Returns the signer certificate in 'signer', if 'signer' is not NULL.
+ */
+int
+TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs,
+    X509_STORE *store, X509 **signer_out)
+{
+	STACK_OF(PKCS7_SIGNER_INFO) *sinfos = NULL;
+	PKCS7_SIGNER_INFO *si;
+	STACK_OF(X509) *signers = NULL;
+	X509	*signer;
+	STACK_OF(X509) *chain = NULL;
+	char	buf[4096];
+	int	i, j = 0, ret = 0;
+	BIO	*p7bio = NULL;
+
+	/* Some sanity checks first. */
+	if (!token) {
+		TSerror(TS_R_INVALID_NULL_POINTER);
+		goto err;
+	}
+
+	/* Check for the correct content type */
+	if (!PKCS7_type_is_signed(token)) {
+		TSerror(TS_R_WRONG_CONTENT_TYPE);
+		goto err;
+	}
+
+	/* Check if there is one and only one signer. */
+	sinfos = PKCS7_get_signer_info(token);
+	if (!sinfos || sk_PKCS7_SIGNER_INFO_num(sinfos) != 1) {
+		TSerror(TS_R_THERE_MUST_BE_ONE_SIGNER);
+		goto err;
+	}
+	si = sk_PKCS7_SIGNER_INFO_value(sinfos, 0);
+
+	/* Check for no content: no data to verify signature. */
+	if (PKCS7_get_detached(token)) {
+		TSerror(TS_R_NO_CONTENT);
+		goto err;
+	}
+
+	/* Get hold of the signer certificate, search only internal
+	   certificates if it was requested. */
+	signers = PKCS7_get0_signers(token, certs, 0);
+	if (!signers || sk_X509_num(signers) != 1)
+		goto err;
+	signer = sk_X509_value(signers, 0);
+
+	/* Now verify the certificate. */
+	if (!TS_verify_cert(store, certs, signer, &chain))
+		goto err;
+
+	/* Check if the signer certificate is consistent with the
+	   ESS extension. */
+	if (!TS_check_signing_certs(si, chain))
+		goto err;
+
+	/* Creating the message digest. */
+	p7bio = PKCS7_dataInit(token, NULL);
+
+	/* We now have to 'read' from p7bio to calculate digests etc. */
+	while ((i = BIO_read(p7bio, buf, sizeof(buf))) > 0)
+		;
+
+	/* Verifying the signature. */
+	j = PKCS7_signatureVerify(p7bio, token, si, signer);
+	if (j <= 0) {
+		TSerror(TS_R_SIGNATURE_FAILURE);
+		goto err;
+	}
+
+	/* Return the signer certificate if needed. */
+	if (signer_out) {
+		*signer_out = signer;
+		CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509);
+	}
+
+	ret = 1;
+
+err:
+	BIO_free_all(p7bio);
+	sk_X509_pop_free(chain, X509_free);
+	sk_X509_free(signers);
+
+	return ret;
+}
+LCRYPTO_ALIAS(TS_RESP_verify_signature);
+
+/*
+ * The certificate chain is returned in chain. Caller is responsible for
+ * freeing the vector.
+ */
+static int
+TS_verify_cert(X509_STORE *store, STACK_OF(X509) *untrusted, X509 *signer,
+    STACK_OF(X509) **chain)
+{
+	X509_STORE_CTX cert_ctx;
+	int i;
+	int ret = 0;
+
+	/* chain is an out argument. */
+	*chain = NULL;
+	if (X509_STORE_CTX_init(&cert_ctx, store, signer, untrusted) == 0) {
+		TSerror(ERR_R_X509_LIB);
+		goto err;
+	}
+	if (X509_STORE_CTX_set_purpose(&cert_ctx,
+	    X509_PURPOSE_TIMESTAMP_SIGN) == 0)
+		goto err;
+	i = X509_verify_cert(&cert_ctx);
+	if (i <= 0) {
+		int j = X509_STORE_CTX_get_error(&cert_ctx);
+
+		TSerror(TS_R_CERTIFICATE_VERIFY_ERROR);
+		ERR_asprintf_error_data("Verify error:%s",
+		    X509_verify_cert_error_string(j));
+		goto err;
+	} else {
+		/* Get a copy of the certificate chain. */
+		*chain = X509_STORE_CTX_get1_chain(&cert_ctx);
+		ret = 1;
+	}
+
+err:
+	X509_STORE_CTX_cleanup(&cert_ctx);
+
+	return ret;
+}
+
+static int
+TS_check_signing_certs(PKCS7_SIGNER_INFO *si, STACK_OF(X509) *chain)
+{
+	ESS_SIGNING_CERT *ss = NULL;
+	STACK_OF(ESS_CERT_ID) *cert_ids;
+	ESS_SIGNING_CERT_V2 *ssv2 = NULL;
+	STACK_OF(ESS_CERT_ID_V2) *cert_ids_v2;
+	X509 *cert;
+	int i = 0;
+	int ret = 0;
+
+	if ((ss = ESS_get_signing_cert(si)) != NULL) {
+		cert_ids = ss->cert_ids;
+		/* The signer certificate must be the first in 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) {
+			/* All the certificates of the chain must be in cert_ids. */
+			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;
+			}
+		}
+	}
+
+	if ((ssv2 = ESS_get_signing_cert_v2(si)) != NULL) {
+		cert_ids_v2 = ssv2->cert_ids;
+		/* The signer certificate must be the first in cert_ids_v2. */
+		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_v2.
+		 */
+		if (sk_ESS_CERT_ID_V2_num(cert_ids_v2) > 1) {
+			/* All the certificates of the chain must be in cert_ids_v2. */
+			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;
+			}
+		}
+	}
+
+	ret = 1;
+
+err:
+	if (!ret)
+		TSerror(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)
+{
+	ASN1_TYPE *attr;
+	const unsigned char *p;
+
+	attr = PKCS7_get_signed_attribute(si,
+	    NID_id_smime_aa_signingCertificate);
+	if (!attr)
+		return NULL;
+	if (attr->type != V_ASN1_SEQUENCE)
+		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)
+{
+	ASN1_TYPE *attr;
+	const unsigned char *p;
+
+	attr = PKCS7_get_signed_attribute(si, NID_id_smime_aa_signingCertificateV2);
+	if (attr == NULL)
+		return NULL;
+	p = attr->value.sequence->data;
+	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)
+{
+	int i;
+	unsigned char cert_hash[TS_HASH_LEN];
+
+	if (!cert_ids || !cert)
+		return -1;
+
+	if (!X509_digest(cert, TS_HASH_EVP, cert_hash, NULL))
+		return -1;
+
+	/* Recompute SHA1 hash of certificate if necessary (side effect). */
+	if (X509_check_purpose(cert, -1, 0) == -1)
+		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);
+
+		/* Check the SHA-1 hash first. */
+		if (cid->hash->length == TS_HASH_LEN && !memcmp(cid->hash->data,
+		    cert_hash, TS_HASH_LEN)) {
+			/* Check the issuer/serial as well if specified. */
+			ESS_ISSUER_SERIAL *is = cid->issuer_serial;
+
+			if (is == NULL || TS_issuer_serial_cmp(is, cert) == 0)
+				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 = EVP_sha256();
+
+		if (cid->hash_alg != NULL)
+			md = EVP_get_digestbyobj(cid->hash_alg->algorithm);
+		if (md == NULL)
+			return -1;
+
+		if (!X509_digest(cert, md, cert_digest, &len))
+			return -1;
+
+		if ((unsigned int)cid->hash->length != 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) == 0)
+				return i;
+		}
+	}
+
+	return -1;
+}
+
+static int
+TS_issuer_serial_cmp(ESS_ISSUER_SERIAL *is, X509 *cert)
+{
+	GENERAL_NAME *issuer;
+
+	if (is == NULL || cert == NULL || sk_GENERAL_NAME_num(is->issuer) != 1)
+		return -1;
+
+	/* Check the issuer first. It must be a directory name. */
+	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;
+
+	/* Check the serial number, too. */
+	if (ASN1_INTEGER_cmp(is->serial, X509_get_serialNumber(cert)))
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Verifies whether 'response' contains a valid response with regards
+ * to the settings of the context:
+ *	- Gives an error message if the TS_TST_INFO is not present.
+ *	- Calls _TS_RESP_verify_token to verify the token content.
+ */
+int
+TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response)
+{
+	PKCS7 *token = TS_RESP_get_token(response);
+	TS_TST_INFO *tst_info = TS_RESP_get_tst_info(response);
+	int ret = 0;
+
+	/* Check if we have a successful TS_TST_INFO object in place. */
+	if (!TS_check_status_info(response))
+		goto err;
+
+	/* Check the contents of the time stamp token. */
+	if (!int_TS_RESP_verify_token(ctx, token, tst_info))
+		goto err;
+
+	ret = 1;
+
+err:
+	return ret;
+}
+LCRYPTO_ALIAS(TS_RESP_verify_response);
+
+/*
+ * Tries to extract a TS_TST_INFO structure from the PKCS7 token and
+ * calls the internal int_TS_RESP_verify_token function for verifying it.
+ */
+int
+TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token)
+{
+	TS_TST_INFO *tst_info = PKCS7_to_TS_TST_INFO(token);
+	int ret = 0;
+
+	if (tst_info) {
+		ret = int_TS_RESP_verify_token(ctx, token, tst_info);
+		TS_TST_INFO_free(tst_info);
+	}
+	return ret;
+}
+LCRYPTO_ALIAS(TS_RESP_verify_token);
+
+/*
+ * Verifies whether the 'token' contains a valid time stamp token
+ * with regards to the settings of the context. Only those checks are
+ * carried out that are specified in the context:
+ *	- Verifies the signature of the TS_TST_INFO.
+ *	- Checks the version number of the response.
+ *	- Check if the requested and returned policies math.
+ *	- Check if the message imprints are the same.
+ *	- Check if the nonces are the same.
+ *	- Check if the TSA name matches the signer.
+ *	- Check if the TSA name is the expected TSA.
+ */
+static int
+int_TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token,
+    TS_TST_INFO *tst_info)
+{
+	X509 *signer = NULL;
+	GENERAL_NAME *tsa_name = TS_TST_INFO_get_tsa(tst_info);
+	X509_ALGOR *md_alg = NULL;
+	unsigned char *imprint = NULL;
+	unsigned imprint_len = 0;
+	int ret = 0;
+
+	/* Verify the signature. */
+	if ((ctx->flags & TS_VFY_SIGNATURE) &&
+	    !TS_RESP_verify_signature(token, ctx->certs, ctx->store, &signer))
+		goto err;
+
+	/* Check version number of response. */
+	if ((ctx->flags & TS_VFY_VERSION) &&
+	    TS_TST_INFO_get_version(tst_info) != 1) {
+		TSerror(TS_R_UNSUPPORTED_VERSION);
+		goto err;
+	}
+
+	/* Check policies. */
+	if ((ctx->flags & TS_VFY_POLICY) &&
+	    !TS_check_policy(ctx->policy, tst_info))
+		goto err;
+
+	/* Check message imprints. */
+	if ((ctx->flags & TS_VFY_IMPRINT) &&
+	    !TS_check_imprints(ctx->md_alg, ctx->imprint, ctx->imprint_len,
+		tst_info))
+		goto err;
+
+	/* Compute and check message imprints. */
+	if ((ctx->flags & TS_VFY_DATA) &&
+	    (!TS_compute_imprint(ctx->data, tst_info,
+	    &md_alg, &imprint, &imprint_len) ||
+	    !TS_check_imprints(md_alg, imprint, imprint_len, tst_info)))
+		goto err;
+
+	/* Check nonces. */
+	if ((ctx->flags & TS_VFY_NONCE) &&
+	    !TS_check_nonces(ctx->nonce, tst_info))
+		goto err;
+
+	/* Check whether TSA name and signer certificate match. */
+	if ((ctx->flags & TS_VFY_SIGNER) &&
+	    tsa_name && !TS_check_signer_name(tsa_name, signer)) {
+		TSerror(TS_R_TSA_NAME_MISMATCH);
+		goto err;
+	}
+
+	/* Check whether the TSA is the expected one. */
+	if ((ctx->flags & TS_VFY_TSA_NAME) &&
+	    !TS_check_signer_name(ctx->tsa_name, signer)) {
+		TSerror(TS_R_TSA_UNTRUSTED);
+		goto err;
+	}
+
+	ret = 1;
+
+err:
+	X509_free(signer);
+	X509_ALGOR_free(md_alg);
+	free(imprint);
+	return ret;
+}
+
+static int
+TS_check_status_info(TS_RESP *response)
+{
+	TS_STATUS_INFO *info = TS_RESP_get_status_info(response);
+	long status = ASN1_INTEGER_get(info->status);
+	const char *status_text = NULL;
+	char *embedded_status_text = NULL;
+	char failure_text[TS_STATUS_BUF_SIZE] = "";
+
+	/* Check if everything went fine. */
+	if (status == 0 || status == 1)
+		return 1;
+
+	/* There was an error, get the description in status_text. */
+	if (0 <= status && status < (long)TS_STATUS_TEXT_SIZE)
+		status_text = TS_status_text[status];
+	else
+		status_text = "unknown code";
+
+	/* Set the embedded_status_text to the returned description. */
+	if (sk_ASN1_UTF8STRING_num(info->text) > 0 &&
+	    !(embedded_status_text = TS_get_status_text(info->text)))
+		return 0;
+
+	/* Filling in failure_text with the failure information. */
+	if (info->failure_info) {
+		int i;
+		int first = 1;
+		for (i = 0; i < (int)TS_FAILURE_INFO_SIZE; ++i) {
+			if (ASN1_BIT_STRING_get_bit(info->failure_info,
+			    TS_failure_info[i].code)) {
+				if (!first)
+					strlcat(failure_text, ",",
+					    TS_STATUS_BUF_SIZE);
+				else
+					first = 0;
+				strlcat(failure_text, TS_failure_info[i].text,
+				    TS_STATUS_BUF_SIZE);
+			}
+		}
+	}
+	if (failure_text[0] == '\0')
+		strlcpy(failure_text, "unspecified", TS_STATUS_BUF_SIZE);
+
+	/* Making up the error string. */
+	TSerror(TS_R_NO_TIME_STAMP_TOKEN);
+	ERR_asprintf_error_data
+	    ("status code: %s, status text: %s, failure codes: %s",
+	    status_text,
+	    embedded_status_text ? embedded_status_text : "unspecified",
+	    failure_text);
+	free(embedded_status_text);
+
+	return 0;
+}
+
+static char *
+TS_get_status_text(STACK_OF(ASN1_UTF8STRING) *text)
+{
+	int i;
+	unsigned int length = 0;
+	char *result = NULL;
+
+	/* Determine length first. */
+	for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) {
+		ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
+		length += ASN1_STRING_length(current);
+		length += 1;	/* separator character */
+	}
+	/* Allocate memory (closing '\0' included). */
+	if (!(result = malloc(length))) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	/* Concatenate the descriptions. */
+	result[0] = '\0';
+	for (i = 0; i < sk_ASN1_UTF8STRING_num(text); ++i) {
+		ASN1_UTF8STRING *current = sk_ASN1_UTF8STRING_value(text, i);
+		if (i > 0)
+			strlcat(result, "/", length);
+		strlcat(result, (const char *)ASN1_STRING_data(current), length);
+	}
+	return result;
+}
+
+static int
+TS_check_policy(ASN1_OBJECT *req_oid, TS_TST_INFO *tst_info)
+{
+	ASN1_OBJECT *resp_oid = TS_TST_INFO_get_policy_id(tst_info);
+
+	if (OBJ_cmp(req_oid, resp_oid) != 0) {
+		TSerror(TS_R_POLICY_MISMATCH);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int
+TS_compute_imprint(BIO *data, TS_TST_INFO *tst_info, X509_ALGOR **out_md_alg,
+    unsigned char **out_imprint, unsigned int *out_imprint_len)
+{
+	TS_MSG_IMPRINT *msg_imprint;
+	X509_ALGOR *md_alg_resp;
+	X509_ALGOR *md_alg = NULL;
+	unsigned char *imprint = NULL;
+	unsigned int imprint_len = 0;
+	const EVP_MD *md;
+	EVP_MD_CTX md_ctx;
+	unsigned char buffer[4096];
+	int length;
+
+	*out_md_alg = NULL;
+	*out_imprint = NULL;
+	*out_imprint_len = 0;
+
+	/* Retrieve the MD algorithm of the response. */
+	msg_imprint = TS_TST_INFO_get_msg_imprint(tst_info);
+	md_alg_resp = TS_MSG_IMPRINT_get_algo(msg_imprint);
+	if ((md_alg = X509_ALGOR_dup(md_alg_resp)) == NULL)
+		goto err;
+
+	/* Getting the MD object. */
+	if ((md = EVP_get_digestbyobj((md_alg)->algorithm)) == NULL) {
+		TSerror(TS_R_UNSUPPORTED_MD_ALGORITHM);
+		goto err;
+	}
+
+	/* Compute message digest. */
+	if ((length = EVP_MD_size(md)) < 0)
+		goto err;
+	imprint_len = length;
+	if ((imprint = malloc(imprint_len)) == NULL) {
+		TSerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!EVP_DigestInit(&md_ctx, md))
+		goto err;
+	while ((length = BIO_read(data, buffer, sizeof(buffer))) > 0) {
+		if (!EVP_DigestUpdate(&md_ctx, buffer, length))
+			goto err;
+	}
+	if (!EVP_DigestFinal(&md_ctx, imprint, NULL))
+		goto err;
+
+	*out_md_alg = md_alg;
+	md_alg = NULL;
+	*out_imprint = imprint;
+	imprint = NULL;
+	*out_imprint_len = imprint_len;
+
+	return 1;
+
+err:
+	X509_ALGOR_free(md_alg);
+	free(imprint);
+	return 0;
+}
+
+static int
+TS_check_imprints(X509_ALGOR *algor_a, unsigned char *imprint_a, unsigned len_a,
+    TS_TST_INFO *tst_info)
+{
+	TS_MSG_IMPRINT *b = TS_TST_INFO_get_msg_imprint(tst_info);
+	X509_ALGOR *algor_b = TS_MSG_IMPRINT_get_algo(b);
+	int ret = 0;
+
+	/* algor_a is optional. */
+	if (algor_a) {
+		/* Compare algorithm OIDs. */
+		if (OBJ_cmp(algor_a->algorithm, algor_b->algorithm))
+			goto err;
+
+		/* The parameter must be NULL in both. */
+		if ((algor_a->parameter &&
+		    ASN1_TYPE_get(algor_a->parameter) != V_ASN1_NULL) ||
+		    (algor_b->parameter &&
+		    ASN1_TYPE_get(algor_b->parameter) != V_ASN1_NULL))
+			goto err;
+	}
+
+	/* Compare octet strings. */
+	ret = len_a == (unsigned) ASN1_STRING_length(b->hashed_msg) &&
+	    memcmp(imprint_a, ASN1_STRING_data(b->hashed_msg), len_a) == 0;
+
+err:
+	if (!ret)
+		TSerror(TS_R_MESSAGE_IMPRINT_MISMATCH);
+	return ret;
+}
+
+static int
+TS_check_nonces(const ASN1_INTEGER *a, TS_TST_INFO *tst_info)
+{
+	const ASN1_INTEGER *b = TS_TST_INFO_get_nonce(tst_info);
+
+	/* Error if nonce is missing. */
+	if (!b) {
+		TSerror(TS_R_NONCE_NOT_RETURNED);
+		return 0;
+	}
+
+	/* No error if a nonce is returned without being requested. */
+	if (ASN1_INTEGER_cmp(a, b) != 0) {
+		TSerror(TS_R_NONCE_MISMATCH);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Check if the specified TSA name matches either the subject
+   or one of the subject alternative names of the TSA certificate. */
+static int
+TS_check_signer_name(GENERAL_NAME *tsa_name, X509 *signer)
+{
+	STACK_OF(GENERAL_NAME) *gen_names = NULL;
+	int idx = -1;
+	int found = 0;
+
+	if (signer == NULL)
+		return 0;
+
+	/* Check the subject name first. */
+	if (tsa_name->type == GEN_DIRNAME &&
+	    X509_name_cmp(tsa_name->d.dirn, X509_get_subject_name(signer)) == 0)
+		return 1;
+
+	/* Check all the alternative names. */
+	gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name,
+	    NULL, &idx);
+	while (gen_names != NULL &&
+	    !(found = (TS_find_name(gen_names, tsa_name) >= 0))) {
+		/* Get the next subject alternative name,
+		   although there should be no more than one. */
+		GENERAL_NAMES_free(gen_names);
+		gen_names = X509_get_ext_d2i(signer, NID_subject_alt_name,
+		    NULL, &idx);
+	}
+	if (gen_names)
+		GENERAL_NAMES_free(gen_names);
+
+	return found;
+}
+
+/* Returns 1 if name is in gen_names, 0 otherwise. */
+static int
+TS_find_name(STACK_OF(GENERAL_NAME) *gen_names, GENERAL_NAME *name)
+{
+	int i, found;
+	for (i = 0, found = 0; !found && i < sk_GENERAL_NAME_num(gen_names);
+	    ++i) {
+		GENERAL_NAME *current = sk_GENERAL_NAME_value(gen_names, i);
+		found = GENERAL_NAME_cmp(current, name) == 0;
+	}
+	return found ? i - 1 : -1;
+}
diff --git a/crypto/ts/ts_verify_ctx.c b/crypto/ts/ts_verify_ctx.c
new file mode 100644
index 0000000..5a2d95c
--- /dev/null
+++ b/crypto/ts/ts_verify_ctx.c
@@ -0,0 +1,236 @@
+/* $OpenBSD: ts_verify_ctx.c,v 1.14 2023/07/07 07:25:21 beck Exp $ */
+/* Written by Zoltan Glozik (zglozik@stones.com) for the OpenSSL
+ * project 2003.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "ts_local.h"
+
+TS_VERIFY_CTX *
+TS_VERIFY_CTX_new(void)
+{
+	TS_VERIFY_CTX *ctx = calloc(1, sizeof(TS_VERIFY_CTX));
+
+	if (!ctx)
+		TSerror(ERR_R_MALLOC_FAILURE);
+
+	return ctx;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_new);
+
+void
+TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx)
+{
+	if (!ctx)
+		return;
+
+	TS_VERIFY_CTX_cleanup(ctx);
+	free(ctx);
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_free);
+
+void
+TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx)
+{
+	if (!ctx)
+		return;
+
+	X509_STORE_free(ctx->store);
+	sk_X509_pop_free(ctx->certs, X509_free);
+
+	ASN1_OBJECT_free(ctx->policy);
+
+	X509_ALGOR_free(ctx->md_alg);
+	free(ctx->imprint);
+
+	BIO_free_all(ctx->data);
+
+	ASN1_INTEGER_free(ctx->nonce);
+
+	GENERAL_NAME_free(ctx->tsa_name);
+
+	memset(ctx, 0, sizeof(*ctx));
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_cleanup);
+
+/*
+ * XXX: The following accessors demonstrate the amount of care and thought that
+ * went into OpenSSL 1.1 API design and the review thereof: for whatever reason
+ * these functions return what was passed in. Correct memory management is left
+ * as an exercise for the reader... Unfortunately, careful consumers like
+ * openssl-ruby assume this behavior, so we're stuck with this insanity. The
+ * cherry on top is the TS_VERIFY_CTS_set_certs() [sic!] function that made it
+ * into the public API.
+ *
+ * Outstanding job, R$ and tjh, A+.
+ */
+
+int
+TS_VERIFY_CTX_add_flags(TS_VERIFY_CTX *ctx, int flags)
+{
+	ctx->flags |= flags;
+
+	return ctx->flags;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_add_flags);
+
+int
+TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int flags)
+{
+	ctx->flags = flags;
+
+	return ctx->flags;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_set_flags);
+
+BIO *
+TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *bio)
+{
+	ctx->data = bio;
+
+	return ctx->data;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_set_data);
+
+X509_STORE *
+TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *store)
+{
+	ctx->store = store;
+
+	return ctx->store;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_set_store);
+
+STACK_OF(X509) *
+TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx, STACK_OF(X509) *certs)
+{
+	ctx->certs = certs;
+
+	return ctx->certs;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_set_certs);
+
+unsigned char *
+TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, unsigned char *imprint,
+    long imprint_len)
+{
+	free(ctx->imprint);
+
+	ctx->imprint = imprint;
+	ctx->imprint_len = imprint_len;
+
+	return ctx->imprint;
+}
+LCRYPTO_ALIAS(TS_VERIFY_CTX_set_imprint);
+
+TS_VERIFY_CTX *
+TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx)
+{
+	TS_VERIFY_CTX *ret = ctx;
+	ASN1_OBJECT *policy;
+	TS_MSG_IMPRINT *imprint;
+	X509_ALGOR *md_alg;
+	ASN1_OCTET_STRING *msg;
+	const ASN1_INTEGER *nonce;
+
+	if (ret)
+		TS_VERIFY_CTX_cleanup(ret);
+	else if (!(ret = TS_VERIFY_CTX_new()))
+		return NULL;
+
+	/* Setting flags. */
+	ret->flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE);
+
+	/* Setting policy. */
+	if ((policy = TS_REQ_get_policy_id(req)) != NULL) {
+		if (!(ret->policy = OBJ_dup(policy)))
+			goto err;
+	} else
+		ret->flags &= ~TS_VFY_POLICY;
+
+	/* Setting md_alg, imprint and imprint_len. */
+	imprint = TS_REQ_get_msg_imprint(req);
+	md_alg = TS_MSG_IMPRINT_get_algo(imprint);
+	if (!(ret->md_alg = X509_ALGOR_dup(md_alg)))
+		goto err;
+	msg = TS_MSG_IMPRINT_get_msg(imprint);
+	ret->imprint_len = ASN1_STRING_length(msg);
+	if (!(ret->imprint = malloc(ret->imprint_len)))
+		goto err;
+	memcpy(ret->imprint, ASN1_STRING_data(msg), ret->imprint_len);
+
+	/* Setting nonce. */
+	if ((nonce = TS_REQ_get_nonce(req)) != NULL) {
+		if (!(ret->nonce = ASN1_INTEGER_dup(nonce)))
+			goto err;
+	} else
+		ret->flags &= ~TS_VFY_NONCE;
+
+	return ret;
+
+err:
+	if (ctx)
+		TS_VERIFY_CTX_cleanup(ctx);
+	else
+		TS_VERIFY_CTX_free(ret);
+	return NULL;
+}
+LCRYPTO_ALIAS(TS_REQ_to_TS_VERIFY_CTX);
diff --git a/crypto/txt_db/txt_db.c b/crypto/txt_db/txt_db.c
new file mode 100644
index 0000000..7d1f82c
--- /dev/null
+++ b/crypto/txt_db/txt_db.c
@@ -0,0 +1,378 @@
+/* $OpenBSD: txt_db.c,v 1.19 2023/07/08 11:28:03 beck Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#undef BUFSIZE
+#define BUFSIZE	512
+
+TXT_DB *
+TXT_DB_read(BIO *in, int num)
+{
+	TXT_DB *ret = NULL;
+	int er = 1;
+	int esc = 0;
+	long ln = 0;
+	int i, add, n;
+	int size = BUFSIZE;
+	int offset = 0;
+	char *p, *f;
+	OPENSSL_STRING *pp;
+	BUF_MEM *buf = NULL;
+
+	if ((buf = BUF_MEM_new()) == NULL)
+		goto err;
+	if (!BUF_MEM_grow(buf, size))
+		goto err;
+
+	if ((ret = malloc(sizeof(TXT_DB))) == NULL)
+		goto err;
+	ret->num_fields = num;
+	ret->index = NULL;
+	ret->qual = NULL;
+	if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
+		goto err;
+	if ((ret->index = reallocarray(NULL, num, sizeof(*ret->index))) == NULL)
+		goto err;
+	if ((ret->qual = reallocarray(NULL, num, sizeof(*(ret->qual)))) == NULL)
+		goto err;
+	for (i = 0; i < num; i++) {
+		ret->index[i] = NULL;
+		ret->qual[i] = NULL;
+	}
+
+	add = (num + 1)*sizeof(char *);
+	buf->data[size-1] = '\0';
+	offset = 0;
+	for (;;) {
+		if (offset != 0) {
+			size += BUFSIZE;
+			if (!BUF_MEM_grow_clean(buf, size))
+				goto err;
+		}
+		buf->data[offset] = '\0';
+		BIO_gets(in, &(buf->data[offset]), size - offset);
+		ln++;
+		if (buf->data[offset] == '\0')
+			break;
+		if ((offset == 0) && (buf->data[0] == '#'))
+			continue;
+		i = strlen(&(buf->data[offset]));
+		offset += i;
+		if (buf->data[offset-1] != '\n')
+			continue;
+		else {
+			buf->data[offset-1] = '\0'; /* blat the '\n' */
+			if (!(p = malloc(add + offset)))
+				goto err;
+			offset = 0;
+		}
+		pp = (char **)p;
+		p += add;
+		n = 0;
+		pp[n++] = p;
+		i = 0;
+		f = buf->data;
+
+		esc = 0;
+		for (;;) {
+			if (*f == '\0')
+				break;
+			if (*f == '\t') {
+				if (esc)
+					p--;
+				else {
+					*(p++)='\0';
+					f++;
+					if (n >= num)
+						break;
+					pp[n++] = p;
+					continue;
+				}
+			}
+			esc=(*f == '\\');
+			*(p++)= *(f++);
+		}
+		*(p++)='\0';
+		if ((n != num) || (*f != '\0')) {
+			fprintf(stderr, "wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",ln,num,n,f);
+			er = 2;
+			goto err;
+		}
+		pp[n] = p;
+		if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
+			fprintf(stderr, "failure in sk_push\n");
+			er = 2;
+			goto err;
+		}
+	}
+	er = 0;
+
+err:
+	BUF_MEM_free(buf);
+	if (er) {
+		if (er == 1)
+			fprintf(stderr, "malloc failure\n");
+		if (ret != NULL) {
+			if (ret->data != NULL)
+				sk_OPENSSL_PSTRING_free(ret->data);
+			free(ret->index);
+			free(ret->qual);
+			free(ret);
+		}
+		return (NULL);
+	} else
+		return (ret);
+}
+LCRYPTO_ALIAS(TXT_DB_read);
+
+OPENSSL_STRING *
+TXT_DB_get_by_index(TXT_DB *db, int idx, OPENSSL_STRING *value)
+{
+	OPENSSL_STRING *ret;
+	LHASH_OF(OPENSSL_STRING) *lh;
+
+	if (idx >= db->num_fields) {
+		db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
+		return (NULL);
+	}
+	lh = db->index[idx];
+	if (lh == NULL) {
+		db->error = DB_ERROR_NO_INDEX;
+		return (NULL);
+	}
+	ret = lh_OPENSSL_STRING_retrieve(lh, value);
+	db->error = DB_ERROR_OK;
+	return (ret);
+}
+LCRYPTO_ALIAS(TXT_DB_get_by_index);
+
+int
+TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(OPENSSL_STRING *),
+    LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
+{
+	LHASH_OF(OPENSSL_STRING) *idx;
+	OPENSSL_STRING *r;
+	int i, n;
+
+	if (field >= db->num_fields) {
+		db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
+		return (0);
+	}
+	/* FIXME: we lose type checking at this point */
+	if ((idx = (LHASH_OF(OPENSSL_STRING) *)lh_new(hash, cmp)) == NULL) {
+		db->error = DB_ERROR_MALLOC;
+		return (0);
+	}
+	n = sk_OPENSSL_PSTRING_num(db->data);
+	for (i = 0; i < n; i++) {
+		r = sk_OPENSSL_PSTRING_value(db->data, i);
+		if ((qual != NULL) && (qual(r) == 0))
+			continue;
+		if ((r = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
+			db->error = DB_ERROR_INDEX_CLASH;
+			db->arg1 = sk_OPENSSL_PSTRING_find(db->data, r);
+			db->arg2 = i;
+			lh_OPENSSL_STRING_free(idx);
+			return (0);
+		}
+	}
+	if (db->index[field] != NULL)
+		lh_OPENSSL_STRING_free(db->index[field]);
+	db->index[field] = idx;
+	db->qual[field] = qual;
+	return (1);
+}
+LCRYPTO_ALIAS(TXT_DB_create_index);
+
+long
+TXT_DB_write(BIO *out, TXT_DB *db)
+{
+	long i, j,n, nn, l, tot = 0;
+	char *p, **pp, *f;
+	BUF_MEM *buf = NULL;
+	long ret = -1;
+
+	if ((buf = BUF_MEM_new()) == NULL)
+		goto err;
+	n = sk_OPENSSL_PSTRING_num(db->data);
+	nn = db->num_fields;
+	for (i = 0; i < n; i++) {
+		pp = sk_OPENSSL_PSTRING_value(db->data, i);
+
+		l = 0;
+		for (j = 0; j < nn; j++) {
+			if (pp[j] != NULL)
+				l += strlen(pp[j]);
+		}
+		if (!BUF_MEM_grow_clean(buf, (int)(l*2 + nn)))
+			goto err;
+
+		p = buf->data;
+		for (j = 0; j < nn; j++) {
+			f = pp[j];
+			if (f != NULL)
+				for (;;) {
+					if (*f == '\0')
+						break;
+					if (*f == '\t')
+						*(p++) = '\\';
+					*(p++) = *(f++);
+				}
+			*(p++) = '\t';
+		}
+		p[-1] = '\n';
+		j = p - buf->data;
+		if (BIO_write(out, buf->data, (int)j) != j)
+			goto err;
+		tot += j;
+	}
+	ret = tot;
+
+err:
+	if (buf != NULL)
+		BUF_MEM_free(buf);
+	return (ret);
+}
+LCRYPTO_ALIAS(TXT_DB_write);
+
+int
+TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
+{
+	int i;
+	OPENSSL_STRING *r;
+
+	for (i = 0; i < db->num_fields; i++) {
+		if (db->index[i] != NULL) {
+			if ((db->qual[i] != NULL) && (db->qual[i](row) == 0))
+				continue;
+			r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
+			if (r != NULL) {
+				db->error = DB_ERROR_INDEX_CLASH;
+				db->arg1 = i;
+				db->arg_row = r;
+				goto err;
+			}
+		}
+	}
+	/* We have passed the index checks, now just append and insert */
+	if (!sk_OPENSSL_PSTRING_push(db->data, row)) {
+		db->error = DB_ERROR_MALLOC;
+		goto err;
+	}
+
+	for (i = 0; i < db->num_fields; i++) {
+		if (db->index[i] != NULL) {
+			if ((db->qual[i] != NULL) && (db->qual[i](row) == 0))
+				continue;
+			(void)lh_OPENSSL_STRING_insert(db->index[i], row);
+		}
+	}
+	return (1);
+
+err:
+	return (0);
+}
+LCRYPTO_ALIAS(TXT_DB_insert);
+
+void
+TXT_DB_free(TXT_DB *db)
+{
+	int i, n;
+	char **p, *max;
+
+	if (db == NULL)
+		return;
+
+	if (db->index != NULL) {
+		for (i = db->num_fields - 1; i >= 0; i--)
+			if (db->index[i] != NULL)
+				lh_OPENSSL_STRING_free(db->index[i]);
+		free(db->index);
+	}
+	free(db->qual);
+	if (db->data != NULL) {
+		for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
+			/* check if any 'fields' have been allocated
+			 * from outside of the initial block */
+			p = sk_OPENSSL_PSTRING_value(db->data, i);
+			max = p[db->num_fields]; /* last address */
+			if (max == NULL) /* new row */
+			{
+				for (n = 0; n < db->num_fields; n++)
+					free(p[n]);
+			} else {
+				for (n = 0; n < db->num_fields; n++) {
+					if (((p[n] < (char *)p) ||
+					    (p[n] > max)) &&
+					    (p[n] != NULL))
+						free(p[n]);
+				}
+			}
+			free(sk_OPENSSL_PSTRING_value(db->data, i));
+		}
+		sk_OPENSSL_PSTRING_free(db->data);
+	}
+	free(db);
+}
+LCRYPTO_ALIAS(TXT_DB_free);
diff --git a/crypto/ui/ui_err.c b/crypto/ui/ui_err.c
new file mode 100644
index 0000000..3f875da
--- /dev/null
+++ b/crypto/ui/ui_err.c
@@ -0,0 +1,96 @@
+/* $OpenBSD: ui_err.c,v 1.12 2023/02/16 08:38:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 1999-2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+
+#ifndef OPENSSL_NO_ERR
+
+#define ERR_FUNC(func) ERR_PACK(ERR_LIB_UI,func,0)
+#define ERR_REASON(reason) ERR_PACK(ERR_LIB_UI,0,reason)
+
+static ERR_STRING_DATA UI_str_functs[] = {
+	{ERR_FUNC(0xfff), "CRYPTO_internal"},
+	{0, NULL}
+};
+
+static ERR_STRING_DATA UI_str_reasons[] = {
+	{ERR_REASON(UI_R_COMMON_OK_AND_CANCEL_CHARACTERS), "common ok and cancel characters"},
+	{ERR_REASON(UI_R_INDEX_TOO_LARGE), "index too large"},
+	{ERR_REASON(UI_R_INDEX_TOO_SMALL), "index too small"},
+	{ERR_REASON(UI_R_NO_RESULT_BUFFER), "no result buffer"},
+	{ERR_REASON(UI_R_RESULT_TOO_LARGE), "result too large"},
+	{ERR_REASON(UI_R_RESULT_TOO_SMALL), "result too small"},
+	{ERR_REASON(UI_R_UNKNOWN_CONTROL_COMMAND), "unknown control command"},
+	{0, NULL}
+};
+
+#endif
+
+void
+ERR_load_UI_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+	if (ERR_func_error_string(UI_str_functs[0].error) == NULL) {
+		ERR_load_strings(0, UI_str_functs);
+		ERR_load_strings(0, UI_str_reasons);
+	}
+#endif
+}
+LCRYPTO_ALIAS(ERR_load_UI_strings);
diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c
new file mode 100644
index 0000000..73d899a
--- /dev/null
+++ b/crypto/ui/ui_lib.c
@@ -0,0 +1,907 @@
+/* $OpenBSD: ui_lib.c,v 1.51 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+
+#include "ui_local.h"
+
+static const UI_METHOD *default_UI_meth = NULL;
+
+UI *
+UI_new(void)
+{
+	return (UI_new_method(NULL));
+}
+LCRYPTO_ALIAS(UI_new);
+
+UI *
+UI_new_method(const UI_METHOD *method)
+{
+	UI *ret;
+
+	if ((ret = calloc(1, sizeof(UI))) == NULL) {
+		UIerror(ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	if ((ret->meth = method) == NULL)
+		ret->meth = UI_get_default_method();
+	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data);
+
+	return ret;
+}
+LCRYPTO_ALIAS(UI_new_method);
+
+static void
+free_string(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return;
+	if (uis->flags & OUT_STRING_FREEABLE) {
+		free((char *) uis->out_string);
+		switch (uis->type) {
+		case UIT_BOOLEAN:
+			free((char *)uis->_.boolean_data.action_desc);
+			free((char *)uis->_.boolean_data.ok_chars);
+			free((char *)uis->_.boolean_data.cancel_chars);
+			break;
+		default:
+			break;
+		}
+	}
+	free(uis);
+}
+
+void
+UI_free(UI *ui)
+{
+	if (ui == NULL)
+		return;
+
+	sk_UI_STRING_pop_free(ui->strings, free_string);
+	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
+	free(ui);
+}
+LCRYPTO_ALIAS(UI_free);
+
+static int
+allocate_string_stack(UI *ui)
+{
+	if (ui->strings == NULL) {
+		if ((ui->strings = sk_UI_STRING_new_null()) == NULL) {
+			UIerror(ERR_R_MALLOC_FAILURE);
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static UI_STRING *
+general_allocate_prompt(const char *prompt, int dup_prompt,
+    enum UI_string_types type, int input_flags, char *result_buf)
+{
+	UI_STRING *uis = NULL;
+
+	if (prompt == NULL) {
+		UIerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+	if ((type == UIT_PROMPT || type == UIT_VERIFY || type == UIT_BOOLEAN) &&
+	    result_buf == NULL) {
+		UIerror(UI_R_NO_RESULT_BUFFER);
+		goto err;
+	}
+
+	if ((uis = calloc(1, sizeof(UI_STRING))) == NULL) {
+		UIerror(ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	uis->out_string = prompt;
+	if (dup_prompt) {
+		if ((uis->out_string = strdup(prompt)) == NULL) {
+			UIerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		uis->flags = OUT_STRING_FREEABLE;
+	}
+	uis->input_flags = input_flags;
+	uis->type = type;
+	uis->result_buf = result_buf;
+
+	return uis;
+
+ err:
+	free_string(uis);
+	return NULL;
+}
+
+static int
+general_allocate_string(UI *ui, const char *prompt, int dup_prompt,
+    enum UI_string_types type, int input_flags, char *result_buf, int minsize,
+    int maxsize, const char *test_buf)
+{
+	UI_STRING *s;
+	int ret;
+
+	if ((s = general_allocate_prompt(prompt, dup_prompt, type, input_flags,
+	    result_buf)) == NULL)
+		goto err;
+	s->_.string_data.result_minsize = minsize;
+	s->_.string_data.result_maxsize = maxsize;
+	s->_.string_data.test_buf = test_buf;
+
+	if (allocate_string_stack(ui) < 0)
+		goto err;
+	if ((ret = sk_UI_STRING_push(ui->strings, s)) <= 0)
+		goto err;
+
+	return ret;
+
+ err:
+	free_string(s);
+	return -1;
+}
+
+static int
+general_allocate_boolean(UI *ui, const char *prompt, const char *action_desc,
+    const char *ok_chars, const char *cancel_chars, int dup_strings,
+    enum UI_string_types type, int input_flags, char *result_buf)
+{
+	UI_STRING *s = NULL;
+	int ret;
+
+	if (ok_chars == NULL || cancel_chars == NULL) {
+		UIerror(ERR_R_PASSED_NULL_PARAMETER);
+		goto err;
+	}
+	if (ok_chars[strcspn(ok_chars, cancel_chars)] != '\0') {
+		UIerror(UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
+		goto err;
+	}
+
+	if ((s = general_allocate_prompt(prompt, dup_strings, type, input_flags,
+	    result_buf)) == NULL)
+		goto err;
+
+	if (dup_strings) {
+		if (action_desc != NULL) {
+			if ((s->_.boolean_data.action_desc =
+			    strdup(action_desc)) == NULL) {
+				UIerror(ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+		}
+		if ((s->_.boolean_data.ok_chars = strdup(ok_chars)) == NULL) {
+			UIerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		if ((s->_.boolean_data.cancel_chars = strdup(cancel_chars)) ==
+		    NULL) {
+			UIerror(ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	} else {
+		s->_.boolean_data.action_desc = action_desc;
+		s->_.boolean_data.ok_chars = ok_chars;
+		s->_.boolean_data.cancel_chars = cancel_chars;
+	}
+
+	if (allocate_string_stack(ui) < 0)
+		goto err;
+	if ((ret = sk_UI_STRING_push(ui->strings, s)) <= 0)
+		goto err;
+
+	return ret;
+
+ err:
+	free_string(s);
+	return -1;
+}
+
+/*
+ * Returns the index to the place in the stack or -1 for error.  Uses a
+ * direct reference to the prompt.
+ */
+int
+UI_add_input_string(UI *ui, const char *prompt, int flags, char *result_buf,
+    int minsize, int maxsize)
+{
+	return general_allocate_string(ui, prompt, 0, UIT_PROMPT, flags,
+	    result_buf, minsize, maxsize, NULL);
+}
+LCRYPTO_ALIAS(UI_add_input_string);
+
+/* Same as UI_add_input_string(), excepts it takes a copy of the prompt. */
+int
+UI_dup_input_string(UI *ui, const char *prompt, int flags, char *result_buf,
+    int minsize, int maxsize)
+{
+	return general_allocate_string(ui, prompt, 1, UIT_PROMPT, flags,
+	    result_buf, minsize, maxsize, NULL);
+}
+LCRYPTO_ALIAS(UI_dup_input_string);
+
+int
+UI_add_verify_string(UI *ui, const char *prompt, int flags, char *result_buf,
+    int minsize, int maxsize, const char *test_buf)
+{
+	return general_allocate_string(ui, prompt, 0, UIT_VERIFY, flags,
+	    result_buf, minsize, maxsize, test_buf);
+}
+LCRYPTO_ALIAS(UI_add_verify_string);
+
+int
+UI_dup_verify_string(UI *ui, const char *prompt, int flags,
+    char *result_buf, int minsize, int maxsize, const char *test_buf)
+{
+	return general_allocate_string(ui, prompt, 1, UIT_VERIFY, flags,
+	    result_buf, minsize, maxsize, test_buf);
+}
+LCRYPTO_ALIAS(UI_dup_verify_string);
+
+int
+UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+    const char *ok_chars, const char *cancel_chars, int flags, char *result_buf)
+{
+	return general_allocate_boolean(ui, prompt, action_desc, ok_chars,
+	    cancel_chars, 0, UIT_BOOLEAN, flags, result_buf);
+}
+LCRYPTO_ALIAS(UI_add_input_boolean);
+
+int
+UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
+    const char *ok_chars, const char *cancel_chars, int flags, char *result_buf)
+{
+	return general_allocate_boolean(ui, prompt, action_desc, ok_chars,
+	    cancel_chars, 1, UIT_BOOLEAN, flags, result_buf);
+}
+LCRYPTO_ALIAS(UI_dup_input_boolean);
+
+int
+UI_add_info_string(UI *ui, const char *text)
+{
+	return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
+	    NULL);
+}
+LCRYPTO_ALIAS(UI_add_info_string);
+
+int
+UI_dup_info_string(UI *ui, const char *text)
+{
+	return general_allocate_string(ui, text, 1, UIT_INFO, 0, NULL, 0, 0,
+	    NULL);
+}
+LCRYPTO_ALIAS(UI_dup_info_string);
+
+int
+UI_add_error_string(UI *ui, const char *text)
+{
+	return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
+	    NULL);
+}
+LCRYPTO_ALIAS(UI_add_error_string);
+
+int
+UI_dup_error_string(UI *ui, const char *text)
+{
+	return general_allocate_string(ui, text, 1, UIT_ERROR, 0, NULL, 0, 0,
+	    NULL);
+}
+LCRYPTO_ALIAS(UI_dup_error_string);
+
+char *
+UI_construct_prompt(UI *ui, const char *object_desc, const char *object_name)
+{
+	char *prompt;
+
+	if (ui->meth->ui_construct_prompt)
+		return ui->meth->ui_construct_prompt(ui, object_desc,
+		    object_name);
+
+	if (object_desc == NULL)
+		return NULL;
+
+	if (object_name == NULL) {
+		if (asprintf(&prompt, "Enter %s:", object_desc) == -1)
+			return (NULL);
+	} else {
+		if (asprintf(&prompt, "Enter %s for %s:", object_desc,
+		    object_name) == -1)
+			return (NULL);
+	}
+
+	return prompt;
+}
+LCRYPTO_ALIAS(UI_construct_prompt);
+
+void *
+UI_add_user_data(UI *ui, void *user_data)
+{
+	void *old_data = ui->user_data;
+
+	ui->user_data = user_data;
+
+	return old_data;
+}
+LCRYPTO_ALIAS(UI_add_user_data);
+
+void *
+UI_get0_user_data(UI *ui)
+{
+	return ui->user_data;
+}
+LCRYPTO_ALIAS(UI_get0_user_data);
+
+const char *
+UI_get0_result(UI *ui, int i)
+{
+	if (i < 0) {
+		UIerror(UI_R_INDEX_TOO_SMALL);
+		return NULL;
+	}
+	if (i >= sk_UI_STRING_num(ui->strings)) {
+		UIerror(UI_R_INDEX_TOO_LARGE);
+		return NULL;
+	}
+	return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
+}
+LCRYPTO_ALIAS(UI_get0_result);
+
+static int
+print_error(const char *str, size_t len, void *arg)
+{
+	UI *ui = arg;
+	UI_STRING uis;
+
+	memset(&uis, 0, sizeof(uis));
+	uis.type = UIT_ERROR;
+	uis.out_string = str;
+
+	if (ui->meth->ui_write_string &&
+	    !ui->meth->ui_write_string(ui, &uis))
+		return -1;
+	return 0;
+}
+
+int
+UI_process(UI *ui)
+{
+	int i, ok = 0;
+
+	if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui))
+		return -1;
+
+	if (ui->flags & UI_FLAG_PRINT_ERRORS)
+		ERR_print_errors_cb(print_error, ui);
+
+	for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
+		if (ui->meth->ui_write_string &&
+		    !ui->meth->ui_write_string(ui,
+			sk_UI_STRING_value(ui->strings, i))) {
+			ok = -1;
+			goto err;
+		}
+	}
+
+	if (ui->meth->ui_flush)
+		switch (ui->meth->ui_flush(ui)) {
+		case -1:	/* Interrupt/Cancel/something... */
+			ok = -2;
+			goto err;
+		case 0:		/* Errors */
+			ok = -1;
+			goto err;
+		default:	/* Success */
+			ok = 0;
+			break;
+		}
+
+	for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) {
+		if (ui->meth->ui_read_string) {
+			switch (ui->meth->ui_read_string(ui,
+			    sk_UI_STRING_value(ui->strings, i))) {
+			case -1:	/* Interrupt/Cancel/something... */
+				ui->flags &= ~UI_FLAG_REDOABLE;
+				ok = -2;
+				goto err;
+			case 0:		/* Errors */
+				ok = -1;
+				goto err;
+			default:	/* Success */
+				ok = 0;
+				break;
+			}
+		}
+	}
+
+ err:
+	if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui))
+		return -1;
+	return ok;
+}
+LCRYPTO_ALIAS(UI_process);
+
+int
+UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void))
+{
+	if (ui == NULL) {
+		UIerror(ERR_R_PASSED_NULL_PARAMETER);
+		return -1;
+	}
+
+	switch (cmd) {
+	case UI_CTRL_PRINT_ERRORS:
+		{
+			int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS);
+			if (i)
+				ui->flags |= UI_FLAG_PRINT_ERRORS;
+			else
+				ui->flags &= ~UI_FLAG_PRINT_ERRORS;
+			return save_flag;
+		}
+	case UI_CTRL_IS_REDOABLE:
+		return !!(ui->flags & UI_FLAG_REDOABLE);
+	default:
+		break;
+	}
+	UIerror(UI_R_UNKNOWN_CONTROL_COMMAND);
+	return -1;
+}
+LCRYPTO_ALIAS(UI_ctrl);
+
+int
+UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+    CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp,
+	    new_func, dup_func, free_func);
+}
+LCRYPTO_ALIAS(UI_get_ex_new_index);
+
+int
+UI_set_ex_data(UI *r, int idx, void *arg)
+{
+	return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
+}
+LCRYPTO_ALIAS(UI_set_ex_data);
+
+void *
+UI_get_ex_data(UI *r, int idx)
+{
+	return (CRYPTO_get_ex_data(&r->ex_data, idx));
+}
+LCRYPTO_ALIAS(UI_get_ex_data);
+
+void
+UI_set_default_method(const UI_METHOD *method)
+{
+	default_UI_meth = method;
+}
+LCRYPTO_ALIAS(UI_set_default_method);
+
+const UI_METHOD *
+UI_get_default_method(void)
+{
+	if (default_UI_meth == NULL)
+		default_UI_meth = UI_OpenSSL();
+
+	return default_UI_meth;
+}
+LCRYPTO_ALIAS(UI_get_default_method);
+
+const UI_METHOD *
+UI_get_method(UI *ui)
+{
+	return ui->meth;
+}
+LCRYPTO_ALIAS(UI_get_method);
+
+const UI_METHOD *
+UI_set_method(UI *ui, const UI_METHOD *method)
+{
+	ui->meth = method;
+
+	return ui->meth;
+}
+LCRYPTO_ALIAS(UI_set_method);
+
+UI_METHOD *
+UI_create_method(const char *name)
+{
+	UI_METHOD *method = NULL;
+
+	if ((method = calloc(1, sizeof(UI_METHOD))) == NULL)
+		goto err;
+
+	if (name != NULL) {
+		if ((method->name = strdup(name)) == NULL)
+			goto err;
+	}
+
+	return method;
+
+ err:
+	UI_destroy_method(method);
+
+	return NULL;
+}
+LCRYPTO_ALIAS(UI_create_method);
+
+void
+UI_destroy_method(UI_METHOD *method)
+{
+	if (method == NULL)
+		return;
+
+	free(method->name);
+	free(method);
+}
+LCRYPTO_ALIAS(UI_destroy_method);
+
+int
+UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_open_session = opener;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_opener);
+
+int
+UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_write_string = writer;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_writer);
+
+int
+UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_flush = flusher;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_flusher);
+
+int
+UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_read_string = reader;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_reader);
+
+int
+UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_close_session = closer;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_closer);
+
+int
+UI_method_set_prompt_constructor(UI_METHOD *method,
+    char *(*prompt_constructor)(UI *ui, const char *object_desc,
+    const char *object_name))
+{
+	if (method == NULL)
+		return -1;
+
+	method->ui_construct_prompt = prompt_constructor;
+
+	return 0;
+}
+LCRYPTO_ALIAS(UI_method_set_prompt_constructor);
+
+int
+(*UI_method_get_opener(const UI_METHOD * method))(UI *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_open_session;
+}
+LCRYPTO_ALIAS(UI_method_get_opener);
+
+int
+(*UI_method_get_writer(const UI_METHOD *method))(UI *, UI_STRING *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_write_string;
+}
+LCRYPTO_ALIAS(UI_method_get_writer);
+
+int
+(*UI_method_get_flusher(const UI_METHOD *method)) (UI *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_flush;
+}
+LCRYPTO_ALIAS(UI_method_get_flusher);
+
+int
+(*UI_method_get_reader(const UI_METHOD *method))(UI *, UI_STRING *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_read_string;
+}
+LCRYPTO_ALIAS(UI_method_get_reader);
+
+int
+(*UI_method_get_closer(const UI_METHOD *method))(UI *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_close_session;
+}
+LCRYPTO_ALIAS(UI_method_get_closer);
+
+char *
+(*UI_method_get_prompt_constructor(const UI_METHOD *method))(UI *, const char *,
+    const char *)
+{
+	if (method == NULL)
+		return NULL;
+
+	return method->ui_construct_prompt;
+}
+LCRYPTO_ALIAS(UI_method_get_prompt_constructor);
+
+enum UI_string_types
+UI_get_string_type(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return UIT_NONE;
+
+	return uis->type;
+}
+LCRYPTO_ALIAS(UI_get_string_type);
+
+int
+UI_get_input_flags(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return 0;
+
+	return uis->input_flags;
+}
+LCRYPTO_ALIAS(UI_get_input_flags);
+
+const char *
+UI_get0_output_string(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return NULL;
+
+	return uis->out_string;
+}
+LCRYPTO_ALIAS(UI_get0_output_string);
+
+const char *
+UI_get0_action_string(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return NULL;
+
+	switch (uis->type) {
+	case UIT_PROMPT:
+	case UIT_BOOLEAN:
+		return uis->_.boolean_data.action_desc;
+	default:
+		return NULL;
+	}
+}
+LCRYPTO_ALIAS(UI_get0_action_string);
+
+const char *
+UI_get0_result_string(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return NULL;
+
+	switch (uis->type) {
+	case UIT_PROMPT:
+	case UIT_VERIFY:
+		return uis->result_buf;
+	default:
+		return NULL;
+	}
+}
+LCRYPTO_ALIAS(UI_get0_result_string);
+
+const char *
+UI_get0_test_string(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return NULL;
+
+	switch (uis->type) {
+	case UIT_VERIFY:
+		return uis->_.string_data.test_buf;
+	default:
+		return NULL;
+	}
+}
+LCRYPTO_ALIAS(UI_get0_test_string);
+
+int
+UI_get_result_minsize(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return -1;
+
+	switch (uis->type) {
+	case UIT_PROMPT:
+	case UIT_VERIFY:
+		return uis->_.string_data.result_minsize;
+	default:
+		return -1;
+	}
+}
+LCRYPTO_ALIAS(UI_get_result_minsize);
+
+int
+UI_get_result_maxsize(UI_STRING *uis)
+{
+	if (uis == NULL)
+		return -1;
+
+	switch (uis->type) {
+	case UIT_PROMPT:
+	case UIT_VERIFY:
+		return uis->_.string_data.result_maxsize;
+	default:
+		return -1;
+	}
+}
+LCRYPTO_ALIAS(UI_get_result_maxsize);
+
+int
+UI_set_result(UI *ui, UI_STRING *uis, const char *result)
+{
+	const char *p;
+	int l = strlen(result);
+
+	ui->flags &= ~UI_FLAG_REDOABLE;
+
+	if (uis == NULL)
+		return -1;
+
+	switch (uis->type) {
+	case UIT_PROMPT:
+	case UIT_VERIFY:
+		if (l < uis->_.string_data.result_minsize) {
+			ui->flags |= UI_FLAG_REDOABLE;
+			UIerror(UI_R_RESULT_TOO_SMALL);
+			ERR_asprintf_error_data
+			    ("You must type in %d to %d characters",
+				uis->_.string_data.result_minsize,
+				uis->_.string_data.result_maxsize);
+			return -1;
+		}
+		if (l > uis->_.string_data.result_maxsize) {
+			ui->flags |= UI_FLAG_REDOABLE;
+			UIerror(UI_R_RESULT_TOO_LARGE);
+			ERR_asprintf_error_data
+			    ("You must type in %d to %d characters",
+				uis->_.string_data.result_minsize,
+				uis->_.string_data.result_maxsize);
+			return -1;
+		}
+		if (!uis->result_buf) {
+			UIerror(UI_R_NO_RESULT_BUFFER);
+			return -1;
+		}
+		strlcpy(uis->result_buf, result,
+		    uis->_.string_data.result_maxsize + 1);
+		break;
+	case UIT_BOOLEAN:
+		if (!uis->result_buf) {
+			UIerror(UI_R_NO_RESULT_BUFFER);
+			return -1;
+		}
+		uis->result_buf[0] = '\0';
+		for (p = result; *p; p++) {
+			if (strchr(uis->_.boolean_data.ok_chars, *p)) {
+				uis->result_buf[0] =
+				    uis->_.boolean_data.ok_chars[0];
+				break;
+			}
+			if (strchr(uis->_.boolean_data.cancel_chars, *p)) {
+				uis->result_buf[0] =
+				    uis->_.boolean_data.cancel_chars[0];
+				break;
+			}
+		}
+	default:
+		break;
+	}
+	return 0;
+}
+LCRYPTO_ALIAS(UI_set_result);
diff --git a/crypto/ui/ui_local.h b/crypto/ui/ui_local.h
new file mode 100644
index 0000000..460b560
--- /dev/null
+++ b/crypto/ui/ui_local.h
@@ -0,0 +1,152 @@
+/* $OpenBSD: ui_local.h,v 1.2 2022/11/26 17:23:18 tb Exp $ */
+
+/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
+ * project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_UI_LOCAL_H
+#define HEADER_UI_LOCAL_H
+
+#include 
+#include 
+
+__BEGIN_HIDDEN_DECLS
+
+#ifdef _
+#undef _
+#endif
+
+struct ui_method_st {
+	char *name;
+
+	/* All the functions return 1 or non-NULL for success and 0 or NULL
+	   for failure */
+
+	/* Open whatever channel for this, be it the console, an X window
+	   or whatever.
+	   This function should use the ex_data structure to save
+	   intermediate data. */
+	int (*ui_open_session)(UI *ui);
+
+	int (*ui_write_string)(UI *ui, UI_STRING *uis);
+
+	/* Flush the output.  If a GUI dialog box is used, this function can
+	   be used to actually display it. */
+	int (*ui_flush)(UI *ui);
+
+	int (*ui_read_string)(UI *ui, UI_STRING *uis);
+
+	int (*ui_close_session)(UI *ui);
+
+	/* Construct a prompt in a user-defined manner.  object_desc is a
+	   textual short description of the object, for example "pass phrase",
+	   and object_name is the name of the object (might be a card name or
+	   a file name.
+	   The returned string shall always be allocated on the heap with
+	   malloc(), and need to be free'd with free(). */
+	char *(*ui_construct_prompt)(UI *ui, const char *object_desc,
+	    const char *object_name);
+};
+
+struct ui_string_st {
+	enum UI_string_types type; /* Input */
+	const char *out_string;	/* Input */
+	int input_flags;	/* Flags from the user */
+
+	/* The following parameters are completely irrelevant for UIT_INFO,
+	   and can therefore be set to 0 or NULL */
+	char *result_buf;	/* Input and Output: If not NULL, user-defined
+				   with size in result_maxsize.  Otherwise, it
+				   may be allocated by the UI routine, meaning
+				   result_minsize is going to be overwritten.*/
+	union {
+		struct {
+			int result_minsize;	/* Input: minimum required
+						   size of the result.
+						*/
+			int result_maxsize;	/* Input: maximum permitted
+						   size of the result */
+
+			const char *test_buf;	/* Input: test string to verify
+						   against */
+		} string_data;
+		struct {
+			const char *action_desc; /* Input */
+			const char *ok_chars; /* Input */
+			const char *cancel_chars; /* Input */
+		} boolean_data;
+	} _;
+
+#define OUT_STRING_FREEABLE 0x01
+	int flags;		/* flags for internal use */
+};
+
+struct ui_st {
+	const UI_METHOD *meth;
+	STACK_OF(UI_STRING) *strings; /* We might want to prompt for more
+					 than one thing at a time, and
+					 with different echoing status.  */
+	void *user_data;
+	CRYPTO_EX_DATA ex_data;
+
+#define UI_FLAG_REDOABLE	0x0001
+#define UI_FLAG_PRINT_ERRORS	0x0100
+	int flags;
+};
+
+__END_HIDDEN_DECLS
+
+#endif	/* !HEADER_UI_LOCAL_H */
diff --git a/crypto/ui/ui_null.c b/crypto/ui/ui_null.c
new file mode 100644
index 0000000..cbc9a50
--- /dev/null
+++ b/crypto/ui/ui_null.c
@@ -0,0 +1,18 @@
+/*	$OpenBSD: ui_null.c,v 1.2 2023/02/16 08:38:17 tb Exp $ */
+
+/*
+ * Written by Theo Buehler. Public domain.
+ */
+
+#include "ui_local.h"
+
+static const UI_METHOD ui_null = {
+	.name = "OpenSSL NULL UI",
+};
+
+const UI_METHOD *
+UI_null(void)
+{
+	return &ui_null;
+}
+LCRYPTO_ALIAS(UI_null);
diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c
new file mode 100644
index 0000000..0b91700
--- /dev/null
+++ b/crypto/ui/ui_openssl.c
@@ -0,0 +1,398 @@
+/* $OpenBSD: ui_openssl.c,v 1.28 2023/02/16 08:38:17 tb Exp $ */
+/* Written by Richard Levitte (richard@levitte.org) and others
+ * for the OpenSSL project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* The lowest level part of this file was previously in crypto/des/read_pwd.c,
+ * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ui_local.h"
+
+#ifndef NX509_SIG
+#define NX509_SIG 32
+#endif
+
+/* Define globals.  They are protected by a lock */
+static struct sigaction savsig[NX509_SIG];
+
+static struct termios tty_orig;
+static FILE *tty_in, *tty_out;
+static int is_a_tty;
+
+/* Declare static functions */
+static int read_till_nl(FILE *);
+static void recsig(int);
+static void pushsig(void);
+static void popsig(void);
+static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
+
+static int read_string(UI *ui, UI_STRING *uis);
+static int write_string(UI *ui, UI_STRING *uis);
+
+static int open_console(UI *ui);
+static int echo_console(UI *ui);
+static int noecho_console(UI *ui);
+static int close_console(UI *ui);
+
+static UI_METHOD ui_openssl = {
+	.name = "OpenSSL default user interface",
+	.ui_open_session = open_console,
+	.ui_write_string = write_string,
+	.ui_read_string = read_string,
+	.ui_close_session = close_console,
+};
+
+/* The method with all the built-in thingies */
+UI_METHOD *
+UI_OpenSSL(void)
+{
+	return &ui_openssl;
+}
+LCRYPTO_ALIAS(UI_OpenSSL);
+
+/* The following function makes sure that info and error strings are printed
+   before any prompt. */
+static int
+write_string(UI *ui, UI_STRING *uis)
+{
+	switch (UI_get_string_type(uis)) {
+	case UIT_ERROR:
+	case UIT_INFO:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fflush(tty_out);
+		break;
+	default:
+		break;
+	}
+	return 1;
+}
+
+static int
+read_string(UI *ui, UI_STRING *uis)
+{
+	int ok = 0;
+
+	switch (UI_get_string_type(uis)) {
+	case UIT_BOOLEAN:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fputs(UI_get0_action_string(uis), tty_out);
+		fflush(tty_out);
+		return read_string_inner(ui, uis,
+		    UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0);
+	case UIT_PROMPT:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fflush(tty_out);
+		return read_string_inner(ui, uis,
+		    UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1);
+	case UIT_VERIFY:
+		fprintf(tty_out, "Verifying - %s",
+		    UI_get0_output_string(uis));
+		fflush(tty_out);
+		if ((ok = read_string_inner(ui, uis, UI_get_input_flags(uis) &
+		    UI_INPUT_FLAG_ECHO, 1)) <= 0)
+			return ok;
+		if (strcmp(UI_get0_result_string(uis),
+		    UI_get0_test_string(uis)) != 0) {
+			fprintf(tty_out, "Verify failure\n");
+			fflush(tty_out);
+			return 0;
+		}
+		break;
+	default:
+		break;
+	}
+	return 1;
+}
+
+
+/* Internal functions to read a string without echoing */
+static int
+read_till_nl(FILE *in)
+{
+#define SIZE 4
+	char buf[SIZE + 1];
+
+	do {
+		if (!fgets(buf, SIZE, in))
+			return 0;
+	} while (strchr(buf, '\n') == NULL);
+	return 1;
+}
+
+static volatile sig_atomic_t intr_signal;
+
+static int
+read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
+{
+	static int ps;
+	int ok;
+	char result[BUFSIZ];
+	int maxsize = BUFSIZ - 1;
+	char *p;
+
+	intr_signal = 0;
+	ok = 0;
+	ps = 0;
+
+	pushsig();
+	ps = 1;
+
+	if (!echo && !noecho_console(ui))
+		goto error;
+	ps = 2;
+
+	result[0] = '\0';
+	p = fgets(result, maxsize, tty_in);
+	if (!p)
+		goto error;
+	if (feof(tty_in))
+		goto error;
+	if (ferror(tty_in))
+		goto error;
+	if ((p = strchr(result, '\n')) != NULL) {
+		if (strip_nl)
+			*p = '\0';
+	} else if (!read_till_nl(tty_in))
+		goto error;
+	if (UI_set_result(ui, uis, result) >= 0)
+		ok = 1;
+
+error:
+	if (intr_signal == SIGINT)
+		ok = -1;
+	if (!echo)
+		fprintf(tty_out, "\n");
+	if (ps >= 2 && !echo && !echo_console(ui))
+		ok = 0;
+
+	if (ps >= 1)
+		popsig();
+
+	explicit_bzero(result, BUFSIZ);
+	return ok;
+}
+
+
+/* Internal functions to open, handle and close a channel to the console.  */
+static int
+open_console(UI *ui)
+{
+	CRYPTO_w_lock(CRYPTO_LOCK_UI);
+	is_a_tty = 1;
+
+#define DEV_TTY "/dev/tty"
+	if ((tty_in = fopen(DEV_TTY, "r")) == NULL)
+		tty_in = stdin;
+	if ((tty_out = fopen(DEV_TTY, "w")) == NULL)
+		tty_out = stderr;
+
+	if (tcgetattr(fileno(tty_in), &tty_orig) == -1) {
+		if (errno == ENOTTY)
+			is_a_tty = 0;
+		else
+			/*
+			 * Ariel Glenn ariel@columbia.edu reports that
+			 * solaris can return EINVAL instead.  This should be
+			 * ok
+			 */
+			if (errno == EINVAL)
+				is_a_tty = 0;
+		else
+			return 0;
+	}
+
+	return 1;
+}
+
+static int
+noecho_console(UI *ui)
+{
+	struct termios tty_new = tty_orig;
+
+	tty_new.c_lflag &= ~ECHO;
+	if (is_a_tty && (tcsetattr(fileno(tty_in), TCSANOW, &tty_new) == -1))
+		return 0;
+	return 1;
+}
+
+static int
+echo_console(UI *ui)
+{
+	if (is_a_tty && (tcsetattr(fileno(tty_in), TCSANOW, &tty_orig) == -1))
+		return 0;
+	return 1;
+}
+
+static int
+close_console(UI *ui)
+{
+	if (tty_in != stdin)
+		fclose(tty_in);
+	if (tty_out != stderr)
+		fclose(tty_out);
+	CRYPTO_w_unlock(CRYPTO_LOCK_UI);
+
+	return 1;
+}
+
+
+/* Internal functions to handle signals and act on them */
+static void
+pushsig(void)
+{
+	int i;
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_handler = recsig;
+
+	for (i = 1; i < NX509_SIG; i++) {
+		if (i == SIGUSR1)
+			continue;
+		if (i == SIGUSR2)
+			continue;
+		if (i == SIGKILL)	/* We can't make any action on that. */
+			continue;
+		sigaction(i, &sa, &savsig[i]);
+	}
+
+	signal(SIGWINCH, SIG_DFL);
+}
+
+static void
+popsig(void)
+{
+	int i;
+	for (i = 1; i < NX509_SIG; i++) {
+		if (i == SIGUSR1)
+			continue;
+		if (i == SIGUSR2)
+			continue;
+		sigaction(i, &savsig[i], NULL);
+	}
+}
+
+static void
+recsig(int i)
+{
+	intr_signal = i;
+}
diff --git a/crypto/ui/ui_openssl_win.c b/crypto/ui/ui_openssl_win.c
new file mode 100644
index 0000000..b6a621f
--- /dev/null
+++ b/crypto/ui/ui_openssl_win.c
@@ -0,0 +1,337 @@
+/* $OpenBSD: ui_openssl.c,v 1.22 2014/07/11 08:44:49 jsing Exp $ */
+/* Written by Richard Levitte (richard@levitte.org) and others
+ * for the OpenSSL project 2001.
+ */
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* The lowest level part of this file was previously in crypto/des/read_pwd.c,
+ * Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include 
+
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "ui_local.h"
+
+#ifndef NX509_SIG
+#define NX509_SIG 32
+#endif
+
+/* Define globals.  They are protected by a lock */
+static void (*savsig[NX509_SIG])(int );
+
+DWORD console_mode;
+static FILE *tty_in, *tty_out;
+static int is_a_tty;
+
+/* Declare static functions */
+static int read_till_nl(FILE *);
+static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl);
+
+static int read_string(UI *ui, UI_STRING *uis);
+static int write_string(UI *ui, UI_STRING *uis);
+
+static int open_console(UI *ui);
+static int echo_console(UI *ui);
+static int noecho_console(UI *ui);
+static int close_console(UI *ui);
+
+static UI_METHOD ui_openssl = {
+	.name = "OpenSSL default user interface",
+	.ui_open_session = open_console,
+	.ui_write_string = write_string,
+	.ui_read_string = read_string,
+	.ui_close_session = close_console,
+};
+
+/* The method with all the built-in thingies */
+UI_METHOD *
+UI_OpenSSL(void)
+{
+	return &ui_openssl;
+}
+
+/* The following function makes sure that info and error strings are printed
+   before any prompt. */
+static int
+write_string(UI *ui, UI_STRING *uis)
+{
+	switch (UI_get_string_type(uis)) {
+	case UIT_ERROR:
+	case UIT_INFO:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fflush(tty_out);
+		break;
+	default:
+		break;
+	}
+	return 1;
+}
+
+static int
+read_string(UI *ui, UI_STRING *uis)
+{
+	int ok = 0;
+
+	switch (UI_get_string_type(uis)) {
+	case UIT_BOOLEAN:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fputs(UI_get0_action_string(uis), tty_out);
+		fflush(tty_out);
+		return read_string_inner(ui, uis,
+		    UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 0);
+	case UIT_PROMPT:
+		fputs(UI_get0_output_string(uis), tty_out);
+		fflush(tty_out);
+		return read_string_inner(ui, uis,
+		    UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO, 1);
+	case UIT_VERIFY:
+		fprintf(tty_out, "Verifying - %s",
+		    UI_get0_output_string(uis));
+		fflush(tty_out);
+		if ((ok = read_string_inner(ui, uis, UI_get_input_flags(uis) &
+		    UI_INPUT_FLAG_ECHO, 1)) <= 0)
+			return ok;
+		if (strcmp(UI_get0_result_string(uis),
+		    UI_get0_test_string(uis)) != 0) {
+			fprintf(tty_out, "Verify failure\n");
+			fflush(tty_out);
+			return 0;
+		}
+		break;
+	default:
+		break;
+	}
+	return 1;
+}
+
+
+/* Internal functions to read a string without echoing */
+static int
+read_till_nl(FILE *in)
+{
+#define SIZE 4
+	char buf[SIZE + 1];
+
+	do {
+		if (!fgets(buf, SIZE, in))
+			return 0;
+	} while (strchr(buf, '\n') == NULL);
+	return 1;
+}
+
+static int
+read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
+{
+	static int ps;
+	int ok;
+	char result[BUFSIZ];
+	int maxsize = BUFSIZ - 1;
+	char *p;
+
+	ok = 0;
+	ps = 0;
+
+	ps = 1;
+
+	if (!echo && !noecho_console(ui))
+		goto error;
+	ps = 2;
+
+	result[0] = '\0';
+	p = fgets(result, maxsize, tty_in);
+	if (!p)
+		goto error;
+	if (feof(tty_in))
+		goto error;
+	if (ferror(tty_in))
+		goto error;
+	if ((p = strchr(result, '\n')) != NULL) {
+		if (strip_nl)
+			*p = '\0';
+	} else if (!read_till_nl(tty_in))
+		goto error;
+	if (UI_set_result(ui, uis, result) >= 0)
+		ok = 1;
+
+error:
+	if (!echo)
+		fprintf(tty_out, "\n");
+	if (ps >= 2 && !echo && !echo_console(ui))
+		ok = 0;
+
+	explicit_bzero(result, BUFSIZ);
+	return ok;
+}
+
+
+/* Internal functions to open, handle and close a channel to the console.  */
+static int
+open_console(UI *ui)
+{
+	CRYPTO_w_lock(CRYPTO_LOCK_UI);
+	is_a_tty = 1;
+
+	tty_in = stdin;
+	tty_out = stderr;
+
+	HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
+	if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
+		if (GetFileType(handle) == FILE_TYPE_CHAR)
+			return GetConsoleMode(handle, &console_mode);
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int
+noecho_console(UI *ui)
+{
+	HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
+	if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
+		if (GetFileType(handle) == FILE_TYPE_CHAR)
+			return SetConsoleMode(handle, console_mode & ~ENABLE_ECHO_INPUT);
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int
+echo_console(UI *ui)
+{
+	HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
+	if (handle != NULL && handle != INVALID_HANDLE_VALUE) {
+		if (GetFileType(handle) == FILE_TYPE_CHAR)
+			return SetConsoleMode(handle, console_mode);
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int
+close_console(UI *ui)
+{
+	if (tty_in != stdin)
+		fclose(tty_in);
+	if (tty_out != stderr)
+		fclose(tty_out);
+	CRYPTO_w_unlock(CRYPTO_LOCK_UI);
+
+	return 1;
+}
diff --git a/crypto/ui/ui_util.c b/crypto/ui/ui_util.c
new file mode 100644
index 0000000..4fa4058
--- /dev/null
+++ b/crypto/ui/ui_util.c
@@ -0,0 +1,98 @@
+/* $OpenBSD: ui_util.c,v 1.14 2023/02/16 08:38:17 tb Exp $ */
+/* ====================================================================
+ * Copyright (c) 2001-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include 
+
+#include 
+
+#include "ui_local.h"
+
+int
+UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify)
+{
+	char buff[BUFSIZ];
+	int ret;
+
+	ret = UI_UTIL_read_pw(buf, buff, (length > BUFSIZ) ? BUFSIZ : length,
+	    prompt, verify);
+	explicit_bzero(buff, BUFSIZ);
+	return (ret);
+}
+LCRYPTO_ALIAS(UI_UTIL_read_pw_string);
+
+int
+UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, int verify)
+{
+	int ok = 0;
+	UI *ui;
+
+	if (size < 1)
+		return -1;
+
+	ui = UI_new();
+	if (ui) {
+		ok = UI_add_input_string(ui, prompt, 0, buf, 0, size - 1);
+		if (ok >= 0 && verify)
+			ok = UI_add_verify_string(ui, prompt, 0, buff, 0,
+			    size - 1, buf);
+		if (ok >= 0)
+			ok = UI_process(ui);
+		UI_free(ui);
+	}
+	if (ok > 0)
+		ok = 0;
+	return (ok);
+}
+LCRYPTO_ALIAS(UI_UTIL_read_pw);
diff --git a/crypto/whrlpool/wp-elf-x86_64.S b/crypto/whrlpool/wp-elf-x86_64.S
new file mode 100644
index 0000000..aba96ef
--- /dev/null
+++ b/crypto/whrlpool/wp-elf-x86_64.S
@@ -0,0 +1,864 @@
+#include "x86_arch.h"
+.text	
+
+.globl	whirlpool_block
+.type	whirlpool_block,@function
+.align	16
+whirlpool_block:
+	endbr64
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movq	%rsp,%r11
+	subq	$128+40,%rsp
+	andq	$-64,%rsp
+
+	leaq	128(%rsp),%r10
+	movq	%rdi,0(%r10)
+	movq	%rsi,8(%r10)
+	movq	%rdx,16(%r10)
+	movq	%r11,32(%r10)
+.Lprologue:
+
+	movq	%r10,%rbx
+	leaq	.Ltable(%rip),%rbp
+
+	xorq	%rcx,%rcx
+	xorq	%rdx,%rdx
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+	movq	32(%rdi),%r12
+	movq	40(%rdi),%r13
+	movq	48(%rdi),%r14
+	movq	56(%rdi),%r15
+.Louterloop:
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	xorq	%rsi,%rsi
+	movq	%rsi,24(%rbx)
+.align	16
+.Lround:
+	movq	4096(%rbp,%rsi,8),%r8
+	movl	0(%rsp),%eax
+	movl	4(%rsp),%ebx
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	movq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	6(%rbp,%rsi,8),%r10
+	movq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	movq	4(%rbp,%rsi,8),%r12
+	movq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	2(%rbp,%rsi,8),%r14
+	movq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	56+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	56+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	xorq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r10
+	xorq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r12
+	xorq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r14
+	xorq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	leaq	128(%rsp),%rbx
+	movq	24(%rbx),%rsi
+	addq	$1,%rsi
+	cmpq	$10,%rsi
+	je	.Lroundsdone
+
+	movq	%rsi,24(%rbx)
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	jmp	.Lround
+.align	16
+.Lroundsdone:
+	movq	0(%rbx),%rdi
+	movq	8(%rbx),%rsi
+	movq	16(%rbx),%rax
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	xorq	0(%rdi),%r8
+	xorq	8(%rdi),%r9
+	xorq	16(%rdi),%r10
+	xorq	24(%rdi),%r11
+	xorq	32(%rdi),%r12
+	xorq	40(%rdi),%r13
+	xorq	48(%rdi),%r14
+	xorq	56(%rdi),%r15
+	movq	%r8,0(%rdi)
+	movq	%r9,8(%rdi)
+	movq	%r10,16(%rdi)
+	movq	%r11,24(%rdi)
+	movq	%r12,32(%rdi)
+	movq	%r13,40(%rdi)
+	movq	%r14,48(%rdi)
+	movq	%r15,56(%rdi)
+	leaq	64(%rsi),%rsi
+	subq	$1,%rax
+	jz	.Lalldone
+	movq	%rsi,8(%rbx)
+	movq	%rax,16(%rbx)
+	jmp	.Louterloop
+.Lalldone:
+	movq	32(%rbx),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	retq
+.size	whirlpool_block,.-whirlpool_block
+
+.section	.rodata
+.align	64
+.type	.Ltable,@object
+.Ltable:
+.byte	24,24,96,24,192,120,48,216,24,24,96,24,192,120,48,216
+.byte	35,35,140,35,5,175,70,38,35,35,140,35,5,175,70,38
+.byte	198,198,63,198,126,249,145,184,198,198,63,198,126,249,145,184
+.byte	232,232,135,232,19,111,205,251,232,232,135,232,19,111,205,251
+.byte	135,135,38,135,76,161,19,203,135,135,38,135,76,161,19,203
+.byte	184,184,218,184,169,98,109,17,184,184,218,184,169,98,109,17
+.byte	1,1,4,1,8,5,2,9,1,1,4,1,8,5,2,9
+.byte	79,79,33,79,66,110,158,13,79,79,33,79,66,110,158,13
+.byte	54,54,216,54,173,238,108,155,54,54,216,54,173,238,108,155
+.byte	166,166,162,166,89,4,81,255,166,166,162,166,89,4,81,255
+.byte	210,210,111,210,222,189,185,12,210,210,111,210,222,189,185,12
+.byte	245,245,243,245,251,6,247,14,245,245,243,245,251,6,247,14
+.byte	121,121,249,121,239,128,242,150,121,121,249,121,239,128,242,150
+.byte	111,111,161,111,95,206,222,48,111,111,161,111,95,206,222,48
+.byte	145,145,126,145,252,239,63,109,145,145,126,145,252,239,63,109
+.byte	82,82,85,82,170,7,164,248,82,82,85,82,170,7,164,248
+.byte	96,96,157,96,39,253,192,71,96,96,157,96,39,253,192,71
+.byte	188,188,202,188,137,118,101,53,188,188,202,188,137,118,101,53
+.byte	155,155,86,155,172,205,43,55,155,155,86,155,172,205,43,55
+.byte	142,142,2,142,4,140,1,138,142,142,2,142,4,140,1,138
+.byte	163,163,182,163,113,21,91,210,163,163,182,163,113,21,91,210
+.byte	12,12,48,12,96,60,24,108,12,12,48,12,96,60,24,108
+.byte	123,123,241,123,255,138,246,132,123,123,241,123,255,138,246,132
+.byte	53,53,212,53,181,225,106,128,53,53,212,53,181,225,106,128
+.byte	29,29,116,29,232,105,58,245,29,29,116,29,232,105,58,245
+.byte	224,224,167,224,83,71,221,179,224,224,167,224,83,71,221,179
+.byte	215,215,123,215,246,172,179,33,215,215,123,215,246,172,179,33
+.byte	194,194,47,194,94,237,153,156,194,194,47,194,94,237,153,156
+.byte	46,46,184,46,109,150,92,67,46,46,184,46,109,150,92,67
+.byte	75,75,49,75,98,122,150,41,75,75,49,75,98,122,150,41
+.byte	254,254,223,254,163,33,225,93,254,254,223,254,163,33,225,93
+.byte	87,87,65,87,130,22,174,213,87,87,65,87,130,22,174,213
+.byte	21,21,84,21,168,65,42,189,21,21,84,21,168,65,42,189
+.byte	119,119,193,119,159,182,238,232,119,119,193,119,159,182,238,232
+.byte	55,55,220,55,165,235,110,146,55,55,220,55,165,235,110,146
+.byte	229,229,179,229,123,86,215,158,229,229,179,229,123,86,215,158
+.byte	159,159,70,159,140,217,35,19,159,159,70,159,140,217,35,19
+.byte	240,240,231,240,211,23,253,35,240,240,231,240,211,23,253,35
+.byte	74,74,53,74,106,127,148,32,74,74,53,74,106,127,148,32
+.byte	218,218,79,218,158,149,169,68,218,218,79,218,158,149,169,68
+.byte	88,88,125,88,250,37,176,162,88,88,125,88,250,37,176,162
+.byte	201,201,3,201,6,202,143,207,201,201,3,201,6,202,143,207
+.byte	41,41,164,41,85,141,82,124,41,41,164,41,85,141,82,124
+.byte	10,10,40,10,80,34,20,90,10,10,40,10,80,34,20,90
+.byte	177,177,254,177,225,79,127,80,177,177,254,177,225,79,127,80
+.byte	160,160,186,160,105,26,93,201,160,160,186,160,105,26,93,201
+.byte	107,107,177,107,127,218,214,20,107,107,177,107,127,218,214,20
+.byte	133,133,46,133,92,171,23,217,133,133,46,133,92,171,23,217
+.byte	189,189,206,189,129,115,103,60,189,189,206,189,129,115,103,60
+.byte	93,93,105,93,210,52,186,143,93,93,105,93,210,52,186,143
+.byte	16,16,64,16,128,80,32,144,16,16,64,16,128,80,32,144
+.byte	244,244,247,244,243,3,245,7,244,244,247,244,243,3,245,7
+.byte	203,203,11,203,22,192,139,221,203,203,11,203,22,192,139,221
+.byte	62,62,248,62,237,198,124,211,62,62,248,62,237,198,124,211
+.byte	5,5,20,5,40,17,10,45,5,5,20,5,40,17,10,45
+.byte	103,103,129,103,31,230,206,120,103,103,129,103,31,230,206,120
+.byte	228,228,183,228,115,83,213,151,228,228,183,228,115,83,213,151
+.byte	39,39,156,39,37,187,78,2,39,39,156,39,37,187,78,2
+.byte	65,65,25,65,50,88,130,115,65,65,25,65,50,88,130,115
+.byte	139,139,22,139,44,157,11,167,139,139,22,139,44,157,11,167
+.byte	167,167,166,167,81,1,83,246,167,167,166,167,81,1,83,246
+.byte	125,125,233,125,207,148,250,178,125,125,233,125,207,148,250,178
+.byte	149,149,110,149,220,251,55,73,149,149,110,149,220,251,55,73
+.byte	216,216,71,216,142,159,173,86,216,216,71,216,142,159,173,86
+.byte	251,251,203,251,139,48,235,112,251,251,203,251,139,48,235,112
+.byte	238,238,159,238,35,113,193,205,238,238,159,238,35,113,193,205
+.byte	124,124,237,124,199,145,248,187,124,124,237,124,199,145,248,187
+.byte	102,102,133,102,23,227,204,113,102,102,133,102,23,227,204,113
+.byte	221,221,83,221,166,142,167,123,221,221,83,221,166,142,167,123
+.byte	23,23,92,23,184,75,46,175,23,23,92,23,184,75,46,175
+.byte	71,71,1,71,2,70,142,69,71,71,1,71,2,70,142,69
+.byte	158,158,66,158,132,220,33,26,158,158,66,158,132,220,33,26
+.byte	202,202,15,202,30,197,137,212,202,202,15,202,30,197,137,212
+.byte	45,45,180,45,117,153,90,88,45,45,180,45,117,153,90,88
+.byte	191,191,198,191,145,121,99,46,191,191,198,191,145,121,99,46
+.byte	7,7,28,7,56,27,14,63,7,7,28,7,56,27,14,63
+.byte	173,173,142,173,1,35,71,172,173,173,142,173,1,35,71,172
+.byte	90,90,117,90,234,47,180,176,90,90,117,90,234,47,180,176
+.byte	131,131,54,131,108,181,27,239,131,131,54,131,108,181,27,239
+.byte	51,51,204,51,133,255,102,182,51,51,204,51,133,255,102,182
+.byte	99,99,145,99,63,242,198,92,99,99,145,99,63,242,198,92
+.byte	2,2,8,2,16,10,4,18,2,2,8,2,16,10,4,18
+.byte	170,170,146,170,57,56,73,147,170,170,146,170,57,56,73,147
+.byte	113,113,217,113,175,168,226,222,113,113,217,113,175,168,226,222
+.byte	200,200,7,200,14,207,141,198,200,200,7,200,14,207,141,198
+.byte	25,25,100,25,200,125,50,209,25,25,100,25,200,125,50,209
+.byte	73,73,57,73,114,112,146,59,73,73,57,73,114,112,146,59
+.byte	217,217,67,217,134,154,175,95,217,217,67,217,134,154,175,95
+.byte	242,242,239,242,195,29,249,49,242,242,239,242,195,29,249,49
+.byte	227,227,171,227,75,72,219,168,227,227,171,227,75,72,219,168
+.byte	91,91,113,91,226,42,182,185,91,91,113,91,226,42,182,185
+.byte	136,136,26,136,52,146,13,188,136,136,26,136,52,146,13,188
+.byte	154,154,82,154,164,200,41,62,154,154,82,154,164,200,41,62
+.byte	38,38,152,38,45,190,76,11,38,38,152,38,45,190,76,11
+.byte	50,50,200,50,141,250,100,191,50,50,200,50,141,250,100,191
+.byte	176,176,250,176,233,74,125,89,176,176,250,176,233,74,125,89
+.byte	233,233,131,233,27,106,207,242,233,233,131,233,27,106,207,242
+.byte	15,15,60,15,120,51,30,119,15,15,60,15,120,51,30,119
+.byte	213,213,115,213,230,166,183,51,213,213,115,213,230,166,183,51
+.byte	128,128,58,128,116,186,29,244,128,128,58,128,116,186,29,244
+.byte	190,190,194,190,153,124,97,39,190,190,194,190,153,124,97,39
+.byte	205,205,19,205,38,222,135,235,205,205,19,205,38,222,135,235
+.byte	52,52,208,52,189,228,104,137,52,52,208,52,189,228,104,137
+.byte	72,72,61,72,122,117,144,50,72,72,61,72,122,117,144,50
+.byte	255,255,219,255,171,36,227,84,255,255,219,255,171,36,227,84
+.byte	122,122,245,122,247,143,244,141,122,122,245,122,247,143,244,141
+.byte	144,144,122,144,244,234,61,100,144,144,122,144,244,234,61,100
+.byte	95,95,97,95,194,62,190,157,95,95,97,95,194,62,190,157
+.byte	32,32,128,32,29,160,64,61,32,32,128,32,29,160,64,61
+.byte	104,104,189,104,103,213,208,15,104,104,189,104,103,213,208,15
+.byte	26,26,104,26,208,114,52,202,26,26,104,26,208,114,52,202
+.byte	174,174,130,174,25,44,65,183,174,174,130,174,25,44,65,183
+.byte	180,180,234,180,201,94,117,125,180,180,234,180,201,94,117,125
+.byte	84,84,77,84,154,25,168,206,84,84,77,84,154,25,168,206
+.byte	147,147,118,147,236,229,59,127,147,147,118,147,236,229,59,127
+.byte	34,34,136,34,13,170,68,47,34,34,136,34,13,170,68,47
+.byte	100,100,141,100,7,233,200,99,100,100,141,100,7,233,200,99
+.byte	241,241,227,241,219,18,255,42,241,241,227,241,219,18,255,42
+.byte	115,115,209,115,191,162,230,204,115,115,209,115,191,162,230,204
+.byte	18,18,72,18,144,90,36,130,18,18,72,18,144,90,36,130
+.byte	64,64,29,64,58,93,128,122,64,64,29,64,58,93,128,122
+.byte	8,8,32,8,64,40,16,72,8,8,32,8,64,40,16,72
+.byte	195,195,43,195,86,232,155,149,195,195,43,195,86,232,155,149
+.byte	236,236,151,236,51,123,197,223,236,236,151,236,51,123,197,223
+.byte	219,219,75,219,150,144,171,77,219,219,75,219,150,144,171,77
+.byte	161,161,190,161,97,31,95,192,161,161,190,161,97,31,95,192
+.byte	141,141,14,141,28,131,7,145,141,141,14,141,28,131,7,145
+.byte	61,61,244,61,245,201,122,200,61,61,244,61,245,201,122,200
+.byte	151,151,102,151,204,241,51,91,151,151,102,151,204,241,51,91
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.byte	207,207,27,207,54,212,131,249,207,207,27,207,54,212,131,249
+.byte	43,43,172,43,69,135,86,110,43,43,172,43,69,135,86,110
+.byte	118,118,197,118,151,179,236,225,118,118,197,118,151,179,236,225
+.byte	130,130,50,130,100,176,25,230,130,130,50,130,100,176,25,230
+.byte	214,214,127,214,254,169,177,40,214,214,127,214,254,169,177,40
+.byte	27,27,108,27,216,119,54,195,27,27,108,27,216,119,54,195
+.byte	181,181,238,181,193,91,119,116,181,181,238,181,193,91,119,116
+.byte	175,175,134,175,17,41,67,190,175,175,134,175,17,41,67,190
+.byte	106,106,181,106,119,223,212,29,106,106,181,106,119,223,212,29
+.byte	80,80,93,80,186,13,160,234,80,80,93,80,186,13,160,234
+.byte	69,69,9,69,18,76,138,87,69,69,9,69,18,76,138,87
+.byte	243,243,235,243,203,24,251,56,243,243,235,243,203,24,251,56
+.byte	48,48,192,48,157,240,96,173,48,48,192,48,157,240,96,173
+.byte	239,239,155,239,43,116,195,196,239,239,155,239,43,116,195,196
+.byte	63,63,252,63,229,195,126,218,63,63,252,63,229,195,126,218
+.byte	85,85,73,85,146,28,170,199,85,85,73,85,146,28,170,199
+.byte	162,162,178,162,121,16,89,219,162,162,178,162,121,16,89,219
+.byte	234,234,143,234,3,101,201,233,234,234,143,234,3,101,201,233
+.byte	101,101,137,101,15,236,202,106,101,101,137,101,15,236,202,106
+.byte	186,186,210,186,185,104,105,3,186,186,210,186,185,104,105,3
+.byte	47,47,188,47,101,147,94,74,47,47,188,47,101,147,94,74
+.byte	192,192,39,192,78,231,157,142,192,192,39,192,78,231,157,142
+.byte	222,222,95,222,190,129,161,96,222,222,95,222,190,129,161,96
+.byte	28,28,112,28,224,108,56,252,28,28,112,28,224,108,56,252
+.byte	253,253,211,253,187,46,231,70,253,253,211,253,187,46,231,70
+.byte	77,77,41,77,82,100,154,31,77,77,41,77,82,100,154,31
+.byte	146,146,114,146,228,224,57,118,146,146,114,146,228,224,57,118
+.byte	117,117,201,117,143,188,234,250,117,117,201,117,143,188,234,250
+.byte	6,6,24,6,48,30,12,54,6,6,24,6,48,30,12,54
+.byte	138,138,18,138,36,152,9,174,138,138,18,138,36,152,9,174
+.byte	178,178,242,178,249,64,121,75,178,178,242,178,249,64,121,75
+.byte	230,230,191,230,99,89,209,133,230,230,191,230,99,89,209,133
+.byte	14,14,56,14,112,54,28,126,14,14,56,14,112,54,28,126
+.byte	31,31,124,31,248,99,62,231,31,31,124,31,248,99,62,231
+.byte	98,98,149,98,55,247,196,85,98,98,149,98,55,247,196,85
+.byte	212,212,119,212,238,163,181,58,212,212,119,212,238,163,181,58
+.byte	168,168,154,168,41,50,77,129,168,168,154,168,41,50,77,129
+.byte	150,150,98,150,196,244,49,82,150,150,98,150,196,244,49,82
+.byte	249,249,195,249,155,58,239,98,249,249,195,249,155,58,239,98
+.byte	197,197,51,197,102,246,151,163,197,197,51,197,102,246,151,163
+.byte	37,37,148,37,53,177,74,16,37,37,148,37,53,177,74,16
+.byte	89,89,121,89,242,32,178,171,89,89,121,89,242,32,178,171
+.byte	132,132,42,132,84,174,21,208,132,132,42,132,84,174,21,208
+.byte	114,114,213,114,183,167,228,197,114,114,213,114,183,167,228,197
+.byte	57,57,228,57,213,221,114,236,57,57,228,57,213,221,114,236
+.byte	76,76,45,76,90,97,152,22,76,76,45,76,90,97,152,22
+.byte	94,94,101,94,202,59,188,148,94,94,101,94,202,59,188,148
+.byte	120,120,253,120,231,133,240,159,120,120,253,120,231,133,240,159
+.byte	56,56,224,56,221,216,112,229,56,56,224,56,221,216,112,229
+.byte	140,140,10,140,20,134,5,152,140,140,10,140,20,134,5,152
+.byte	209,209,99,209,198,178,191,23,209,209,99,209,198,178,191,23
+.byte	165,165,174,165,65,11,87,228,165,165,174,165,65,11,87,228
+.byte	226,226,175,226,67,77,217,161,226,226,175,226,67,77,217,161
+.byte	97,97,153,97,47,248,194,78,97,97,153,97,47,248,194,78
+.byte	179,179,246,179,241,69,123,66,179,179,246,179,241,69,123,66
+.byte	33,33,132,33,21,165,66,52,33,33,132,33,21,165,66,52
+.byte	156,156,74,156,148,214,37,8,156,156,74,156,148,214,37,8
+.byte	30,30,120,30,240,102,60,238,30,30,120,30,240,102,60,238
+.byte	67,67,17,67,34,82,134,97,67,67,17,67,34,82,134,97
+.byte	199,199,59,199,118,252,147,177,199,199,59,199,118,252,147,177
+.byte	252,252,215,252,179,43,229,79,252,252,215,252,179,43,229,79
+.byte	4,4,16,4,32,20,8,36,4,4,16,4,32,20,8,36
+.byte	81,81,89,81,178,8,162,227,81,81,89,81,178,8,162,227
+.byte	153,153,94,153,188,199,47,37,153,153,94,153,188,199,47,37
+.byte	109,109,169,109,79,196,218,34,109,109,169,109,79,196,218,34
+.byte	13,13,52,13,104,57,26,101,13,13,52,13,104,57,26,101
+.byte	250,250,207,250,131,53,233,121,250,250,207,250,131,53,233,121
+.byte	223,223,91,223,182,132,163,105,223,223,91,223,182,132,163,105
+.byte	126,126,229,126,215,155,252,169,126,126,229,126,215,155,252,169
+.byte	36,36,144,36,61,180,72,25,36,36,144,36,61,180,72,25
+.byte	59,59,236,59,197,215,118,254,59,59,236,59,197,215,118,254
+.byte	171,171,150,171,49,61,75,154,171,171,150,171,49,61,75,154
+.byte	206,206,31,206,62,209,129,240,206,206,31,206,62,209,129,240
+.byte	17,17,68,17,136,85,34,153,17,17,68,17,136,85,34,153
+.byte	143,143,6,143,12,137,3,131,143,143,6,143,12,137,3,131
+.byte	78,78,37,78,74,107,156,4,78,78,37,78,74,107,156,4
+.byte	183,183,230,183,209,81,115,102,183,183,230,183,209,81,115,102
+.byte	235,235,139,235,11,96,203,224,235,235,139,235,11,96,203,224
+.byte	60,60,240,60,253,204,120,193,60,60,240,60,253,204,120,193
+.byte	129,129,62,129,124,191,31,253,129,129,62,129,124,191,31,253
+.byte	148,148,106,148,212,254,53,64,148,148,106,148,212,254,53,64
+.byte	247,247,251,247,235,12,243,28,247,247,251,247,235,12,243,28
+.byte	185,185,222,185,161,103,111,24,185,185,222,185,161,103,111,24
+.byte	19,19,76,19,152,95,38,139,19,19,76,19,152,95,38,139
+.byte	44,44,176,44,125,156,88,81,44,44,176,44,125,156,88,81
+.byte	211,211,107,211,214,184,187,5,211,211,107,211,214,184,187,5
+.byte	231,231,187,231,107,92,211,140,231,231,187,231,107,92,211,140
+.byte	110,110,165,110,87,203,220,57,110,110,165,110,87,203,220,57
+.byte	196,196,55,196,110,243,149,170,196,196,55,196,110,243,149,170
+.byte	3,3,12,3,24,15,6,27,3,3,12,3,24,15,6,27
+.byte	86,86,69,86,138,19,172,220,86,86,69,86,138,19,172,220
+.byte	68,68,13,68,26,73,136,94,68,68,13,68,26,73,136,94
+.byte	127,127,225,127,223,158,254,160,127,127,225,127,223,158,254,160
+.byte	169,169,158,169,33,55,79,136,169,169,158,169,33,55,79,136
+.byte	42,42,168,42,77,130,84,103,42,42,168,42,77,130,84,103
+.byte	187,187,214,187,177,109,107,10,187,187,214,187,177,109,107,10
+.byte	193,193,35,193,70,226,159,135,193,193,35,193,70,226,159,135
+.byte	83,83,81,83,162,2,166,241,83,83,81,83,162,2,166,241
+.byte	220,220,87,220,174,139,165,114,220,220,87,220,174,139,165,114
+.byte	11,11,44,11,88,39,22,83,11,11,44,11,88,39,22,83
+.byte	157,157,78,157,156,211,39,1,157,157,78,157,156,211,39,1
+.byte	108,108,173,108,71,193,216,43,108,108,173,108,71,193,216,43
+.byte	49,49,196,49,149,245,98,164,49,49,196,49,149,245,98,164
+.byte	116,116,205,116,135,185,232,243,116,116,205,116,135,185,232,243
+.byte	246,246,255,246,227,9,241,21,246,246,255,246,227,9,241,21
+.byte	70,70,5,70,10,67,140,76,70,70,5,70,10,67,140,76
+.byte	172,172,138,172,9,38,69,165,172,172,138,172,9,38,69,165
+.byte	137,137,30,137,60,151,15,181,137,137,30,137,60,151,15,181
+.byte	20,20,80,20,160,68,40,180,20,20,80,20,160,68,40,180
+.byte	225,225,163,225,91,66,223,186,225,225,163,225,91,66,223,186
+.byte	22,22,88,22,176,78,44,166,22,22,88,22,176,78,44,166
+.byte	58,58,232,58,205,210,116,247,58,58,232,58,205,210,116,247
+.byte	105,105,185,105,111,208,210,6,105,105,185,105,111,208,210,6
+.byte	9,9,36,9,72,45,18,65,9,9,36,9,72,45,18,65
+.byte	112,112,221,112,167,173,224,215,112,112,221,112,167,173,224,215
+.byte	182,182,226,182,217,84,113,111,182,182,226,182,217,84,113,111
+.byte	208,208,103,208,206,183,189,30,208,208,103,208,206,183,189,30
+.byte	237,237,147,237,59,126,199,214,237,237,147,237,59,126,199,214
+.byte	204,204,23,204,46,219,133,226,204,204,23,204,46,219,133,226
+.byte	66,66,21,66,42,87,132,104,66,66,21,66,42,87,132,104
+.byte	152,152,90,152,180,194,45,44,152,152,90,152,180,194,45,44
+.byte	164,164,170,164,73,14,85,237,164,164,170,164,73,14,85,237
+.byte	40,40,160,40,93,136,80,117,40,40,160,40,93,136,80,117
+.byte	92,92,109,92,218,49,184,134,92,92,109,92,218,49,184,134
+.byte	248,248,199,248,147,63,237,107,248,248,199,248,147,63,237,107
+.byte	134,134,34,134,68,164,17,194,134,134,34,134,68,164,17,194
+.byte	24,35,198,232,135,184,1,79
+.byte	54,166,210,245,121,111,145,82
+.byte	96,188,155,142,163,12,123,53
+.byte	29,224,215,194,46,75,254,87
+.byte	21,119,55,229,159,240,74,218
+.byte	88,201,41,10,177,160,107,133
+.byte	189,93,16,244,203,62,5,103
+.byte	228,39,65,139,167,125,149,216
+.byte	251,238,124,102,221,23,71,158
+.byte	202,45,191,7,173,90,131,51
+#if defined(HAVE_GNU_STACK)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/crypto/whrlpool/wp-macosx-x86_64.S b/crypto/whrlpool/wp-macosx-x86_64.S
new file mode 100644
index 0000000..6df325a
--- /dev/null
+++ b/crypto/whrlpool/wp-macosx-x86_64.S
@@ -0,0 +1,859 @@
+#include "x86_arch.h"
+.text	
+
+.globl	_whirlpool_block
+
+.p2align	4
+_whirlpool_block:
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movq	%rsp,%r11
+	subq	$128+40,%rsp
+	andq	$-64,%rsp
+
+	leaq	128(%rsp),%r10
+	movq	%rdi,0(%r10)
+	movq	%rsi,8(%r10)
+	movq	%rdx,16(%r10)
+	movq	%r11,32(%r10)
+L$prologue:
+
+	movq	%r10,%rbx
+	leaq	L$table(%rip),%rbp
+
+	xorq	%rcx,%rcx
+	xorq	%rdx,%rdx
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+	movq	32(%rdi),%r12
+	movq	40(%rdi),%r13
+	movq	48(%rdi),%r14
+	movq	56(%rdi),%r15
+L$outerloop:
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	xorq	%rsi,%rsi
+	movq	%rsi,24(%rbx)
+.p2align	4
+L$round:
+	movq	4096(%rbp,%rsi,8),%r8
+	movl	0(%rsp),%eax
+	movl	4(%rsp),%ebx
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	movq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	6(%rbp,%rsi,8),%r10
+	movq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	movq	4(%rbp,%rsi,8),%r12
+	movq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	2(%rbp,%rsi,8),%r14
+	movq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	56+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	56+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	xorq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r10
+	xorq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r12
+	xorq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r14
+	xorq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	leaq	128(%rsp),%rbx
+	movq	24(%rbx),%rsi
+	addq	$1,%rsi
+	cmpq	$10,%rsi
+	je	L$roundsdone
+
+	movq	%rsi,24(%rbx)
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	jmp	L$round
+.p2align	4
+L$roundsdone:
+	movq	0(%rbx),%rdi
+	movq	8(%rbx),%rsi
+	movq	16(%rbx),%rax
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	xorq	0(%rdi),%r8
+	xorq	8(%rdi),%r9
+	xorq	16(%rdi),%r10
+	xorq	24(%rdi),%r11
+	xorq	32(%rdi),%r12
+	xorq	40(%rdi),%r13
+	xorq	48(%rdi),%r14
+	xorq	56(%rdi),%r15
+	movq	%r8,0(%rdi)
+	movq	%r9,8(%rdi)
+	movq	%r10,16(%rdi)
+	movq	%r11,24(%rdi)
+	movq	%r12,32(%rdi)
+	movq	%r13,40(%rdi)
+	movq	%r14,48(%rdi)
+	movq	%r15,56(%rdi)
+	leaq	64(%rsi),%rsi
+	subq	$1,%rax
+	jz	L$alldone
+	movq	%rsi,8(%rbx)
+	movq	%rax,16(%rbx)
+	jmp	L$outerloop
+L$alldone:
+	movq	32(%rbx),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+L$epilogue:
+	retq
+
+
+.p2align	6
+
+L$table:
+.byte	24,24,96,24,192,120,48,216,24,24,96,24,192,120,48,216
+.byte	35,35,140,35,5,175,70,38,35,35,140,35,5,175,70,38
+.byte	198,198,63,198,126,249,145,184,198,198,63,198,126,249,145,184
+.byte	232,232,135,232,19,111,205,251,232,232,135,232,19,111,205,251
+.byte	135,135,38,135,76,161,19,203,135,135,38,135,76,161,19,203
+.byte	184,184,218,184,169,98,109,17,184,184,218,184,169,98,109,17
+.byte	1,1,4,1,8,5,2,9,1,1,4,1,8,5,2,9
+.byte	79,79,33,79,66,110,158,13,79,79,33,79,66,110,158,13
+.byte	54,54,216,54,173,238,108,155,54,54,216,54,173,238,108,155
+.byte	166,166,162,166,89,4,81,255,166,166,162,166,89,4,81,255
+.byte	210,210,111,210,222,189,185,12,210,210,111,210,222,189,185,12
+.byte	245,245,243,245,251,6,247,14,245,245,243,245,251,6,247,14
+.byte	121,121,249,121,239,128,242,150,121,121,249,121,239,128,242,150
+.byte	111,111,161,111,95,206,222,48,111,111,161,111,95,206,222,48
+.byte	145,145,126,145,252,239,63,109,145,145,126,145,252,239,63,109
+.byte	82,82,85,82,170,7,164,248,82,82,85,82,170,7,164,248
+.byte	96,96,157,96,39,253,192,71,96,96,157,96,39,253,192,71
+.byte	188,188,202,188,137,118,101,53,188,188,202,188,137,118,101,53
+.byte	155,155,86,155,172,205,43,55,155,155,86,155,172,205,43,55
+.byte	142,142,2,142,4,140,1,138,142,142,2,142,4,140,1,138
+.byte	163,163,182,163,113,21,91,210,163,163,182,163,113,21,91,210
+.byte	12,12,48,12,96,60,24,108,12,12,48,12,96,60,24,108
+.byte	123,123,241,123,255,138,246,132,123,123,241,123,255,138,246,132
+.byte	53,53,212,53,181,225,106,128,53,53,212,53,181,225,106,128
+.byte	29,29,116,29,232,105,58,245,29,29,116,29,232,105,58,245
+.byte	224,224,167,224,83,71,221,179,224,224,167,224,83,71,221,179
+.byte	215,215,123,215,246,172,179,33,215,215,123,215,246,172,179,33
+.byte	194,194,47,194,94,237,153,156,194,194,47,194,94,237,153,156
+.byte	46,46,184,46,109,150,92,67,46,46,184,46,109,150,92,67
+.byte	75,75,49,75,98,122,150,41,75,75,49,75,98,122,150,41
+.byte	254,254,223,254,163,33,225,93,254,254,223,254,163,33,225,93
+.byte	87,87,65,87,130,22,174,213,87,87,65,87,130,22,174,213
+.byte	21,21,84,21,168,65,42,189,21,21,84,21,168,65,42,189
+.byte	119,119,193,119,159,182,238,232,119,119,193,119,159,182,238,232
+.byte	55,55,220,55,165,235,110,146,55,55,220,55,165,235,110,146
+.byte	229,229,179,229,123,86,215,158,229,229,179,229,123,86,215,158
+.byte	159,159,70,159,140,217,35,19,159,159,70,159,140,217,35,19
+.byte	240,240,231,240,211,23,253,35,240,240,231,240,211,23,253,35
+.byte	74,74,53,74,106,127,148,32,74,74,53,74,106,127,148,32
+.byte	218,218,79,218,158,149,169,68,218,218,79,218,158,149,169,68
+.byte	88,88,125,88,250,37,176,162,88,88,125,88,250,37,176,162
+.byte	201,201,3,201,6,202,143,207,201,201,3,201,6,202,143,207
+.byte	41,41,164,41,85,141,82,124,41,41,164,41,85,141,82,124
+.byte	10,10,40,10,80,34,20,90,10,10,40,10,80,34,20,90
+.byte	177,177,254,177,225,79,127,80,177,177,254,177,225,79,127,80
+.byte	160,160,186,160,105,26,93,201,160,160,186,160,105,26,93,201
+.byte	107,107,177,107,127,218,214,20,107,107,177,107,127,218,214,20
+.byte	133,133,46,133,92,171,23,217,133,133,46,133,92,171,23,217
+.byte	189,189,206,189,129,115,103,60,189,189,206,189,129,115,103,60
+.byte	93,93,105,93,210,52,186,143,93,93,105,93,210,52,186,143
+.byte	16,16,64,16,128,80,32,144,16,16,64,16,128,80,32,144
+.byte	244,244,247,244,243,3,245,7,244,244,247,244,243,3,245,7
+.byte	203,203,11,203,22,192,139,221,203,203,11,203,22,192,139,221
+.byte	62,62,248,62,237,198,124,211,62,62,248,62,237,198,124,211
+.byte	5,5,20,5,40,17,10,45,5,5,20,5,40,17,10,45
+.byte	103,103,129,103,31,230,206,120,103,103,129,103,31,230,206,120
+.byte	228,228,183,228,115,83,213,151,228,228,183,228,115,83,213,151
+.byte	39,39,156,39,37,187,78,2,39,39,156,39,37,187,78,2
+.byte	65,65,25,65,50,88,130,115,65,65,25,65,50,88,130,115
+.byte	139,139,22,139,44,157,11,167,139,139,22,139,44,157,11,167
+.byte	167,167,166,167,81,1,83,246,167,167,166,167,81,1,83,246
+.byte	125,125,233,125,207,148,250,178,125,125,233,125,207,148,250,178
+.byte	149,149,110,149,220,251,55,73,149,149,110,149,220,251,55,73
+.byte	216,216,71,216,142,159,173,86,216,216,71,216,142,159,173,86
+.byte	251,251,203,251,139,48,235,112,251,251,203,251,139,48,235,112
+.byte	238,238,159,238,35,113,193,205,238,238,159,238,35,113,193,205
+.byte	124,124,237,124,199,145,248,187,124,124,237,124,199,145,248,187
+.byte	102,102,133,102,23,227,204,113,102,102,133,102,23,227,204,113
+.byte	221,221,83,221,166,142,167,123,221,221,83,221,166,142,167,123
+.byte	23,23,92,23,184,75,46,175,23,23,92,23,184,75,46,175
+.byte	71,71,1,71,2,70,142,69,71,71,1,71,2,70,142,69
+.byte	158,158,66,158,132,220,33,26,158,158,66,158,132,220,33,26
+.byte	202,202,15,202,30,197,137,212,202,202,15,202,30,197,137,212
+.byte	45,45,180,45,117,153,90,88,45,45,180,45,117,153,90,88
+.byte	191,191,198,191,145,121,99,46,191,191,198,191,145,121,99,46
+.byte	7,7,28,7,56,27,14,63,7,7,28,7,56,27,14,63
+.byte	173,173,142,173,1,35,71,172,173,173,142,173,1,35,71,172
+.byte	90,90,117,90,234,47,180,176,90,90,117,90,234,47,180,176
+.byte	131,131,54,131,108,181,27,239,131,131,54,131,108,181,27,239
+.byte	51,51,204,51,133,255,102,182,51,51,204,51,133,255,102,182
+.byte	99,99,145,99,63,242,198,92,99,99,145,99,63,242,198,92
+.byte	2,2,8,2,16,10,4,18,2,2,8,2,16,10,4,18
+.byte	170,170,146,170,57,56,73,147,170,170,146,170,57,56,73,147
+.byte	113,113,217,113,175,168,226,222,113,113,217,113,175,168,226,222
+.byte	200,200,7,200,14,207,141,198,200,200,7,200,14,207,141,198
+.byte	25,25,100,25,200,125,50,209,25,25,100,25,200,125,50,209
+.byte	73,73,57,73,114,112,146,59,73,73,57,73,114,112,146,59
+.byte	217,217,67,217,134,154,175,95,217,217,67,217,134,154,175,95
+.byte	242,242,239,242,195,29,249,49,242,242,239,242,195,29,249,49
+.byte	227,227,171,227,75,72,219,168,227,227,171,227,75,72,219,168
+.byte	91,91,113,91,226,42,182,185,91,91,113,91,226,42,182,185
+.byte	136,136,26,136,52,146,13,188,136,136,26,136,52,146,13,188
+.byte	154,154,82,154,164,200,41,62,154,154,82,154,164,200,41,62
+.byte	38,38,152,38,45,190,76,11,38,38,152,38,45,190,76,11
+.byte	50,50,200,50,141,250,100,191,50,50,200,50,141,250,100,191
+.byte	176,176,250,176,233,74,125,89,176,176,250,176,233,74,125,89
+.byte	233,233,131,233,27,106,207,242,233,233,131,233,27,106,207,242
+.byte	15,15,60,15,120,51,30,119,15,15,60,15,120,51,30,119
+.byte	213,213,115,213,230,166,183,51,213,213,115,213,230,166,183,51
+.byte	128,128,58,128,116,186,29,244,128,128,58,128,116,186,29,244
+.byte	190,190,194,190,153,124,97,39,190,190,194,190,153,124,97,39
+.byte	205,205,19,205,38,222,135,235,205,205,19,205,38,222,135,235
+.byte	52,52,208,52,189,228,104,137,52,52,208,52,189,228,104,137
+.byte	72,72,61,72,122,117,144,50,72,72,61,72,122,117,144,50
+.byte	255,255,219,255,171,36,227,84,255,255,219,255,171,36,227,84
+.byte	122,122,245,122,247,143,244,141,122,122,245,122,247,143,244,141
+.byte	144,144,122,144,244,234,61,100,144,144,122,144,244,234,61,100
+.byte	95,95,97,95,194,62,190,157,95,95,97,95,194,62,190,157
+.byte	32,32,128,32,29,160,64,61,32,32,128,32,29,160,64,61
+.byte	104,104,189,104,103,213,208,15,104,104,189,104,103,213,208,15
+.byte	26,26,104,26,208,114,52,202,26,26,104,26,208,114,52,202
+.byte	174,174,130,174,25,44,65,183,174,174,130,174,25,44,65,183
+.byte	180,180,234,180,201,94,117,125,180,180,234,180,201,94,117,125
+.byte	84,84,77,84,154,25,168,206,84,84,77,84,154,25,168,206
+.byte	147,147,118,147,236,229,59,127,147,147,118,147,236,229,59,127
+.byte	34,34,136,34,13,170,68,47,34,34,136,34,13,170,68,47
+.byte	100,100,141,100,7,233,200,99,100,100,141,100,7,233,200,99
+.byte	241,241,227,241,219,18,255,42,241,241,227,241,219,18,255,42
+.byte	115,115,209,115,191,162,230,204,115,115,209,115,191,162,230,204
+.byte	18,18,72,18,144,90,36,130,18,18,72,18,144,90,36,130
+.byte	64,64,29,64,58,93,128,122,64,64,29,64,58,93,128,122
+.byte	8,8,32,8,64,40,16,72,8,8,32,8,64,40,16,72
+.byte	195,195,43,195,86,232,155,149,195,195,43,195,86,232,155,149
+.byte	236,236,151,236,51,123,197,223,236,236,151,236,51,123,197,223
+.byte	219,219,75,219,150,144,171,77,219,219,75,219,150,144,171,77
+.byte	161,161,190,161,97,31,95,192,161,161,190,161,97,31,95,192
+.byte	141,141,14,141,28,131,7,145,141,141,14,141,28,131,7,145
+.byte	61,61,244,61,245,201,122,200,61,61,244,61,245,201,122,200
+.byte	151,151,102,151,204,241,51,91,151,151,102,151,204,241,51,91
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.byte	207,207,27,207,54,212,131,249,207,207,27,207,54,212,131,249
+.byte	43,43,172,43,69,135,86,110,43,43,172,43,69,135,86,110
+.byte	118,118,197,118,151,179,236,225,118,118,197,118,151,179,236,225
+.byte	130,130,50,130,100,176,25,230,130,130,50,130,100,176,25,230
+.byte	214,214,127,214,254,169,177,40,214,214,127,214,254,169,177,40
+.byte	27,27,108,27,216,119,54,195,27,27,108,27,216,119,54,195
+.byte	181,181,238,181,193,91,119,116,181,181,238,181,193,91,119,116
+.byte	175,175,134,175,17,41,67,190,175,175,134,175,17,41,67,190
+.byte	106,106,181,106,119,223,212,29,106,106,181,106,119,223,212,29
+.byte	80,80,93,80,186,13,160,234,80,80,93,80,186,13,160,234
+.byte	69,69,9,69,18,76,138,87,69,69,9,69,18,76,138,87
+.byte	243,243,235,243,203,24,251,56,243,243,235,243,203,24,251,56
+.byte	48,48,192,48,157,240,96,173,48,48,192,48,157,240,96,173
+.byte	239,239,155,239,43,116,195,196,239,239,155,239,43,116,195,196
+.byte	63,63,252,63,229,195,126,218,63,63,252,63,229,195,126,218
+.byte	85,85,73,85,146,28,170,199,85,85,73,85,146,28,170,199
+.byte	162,162,178,162,121,16,89,219,162,162,178,162,121,16,89,219
+.byte	234,234,143,234,3,101,201,233,234,234,143,234,3,101,201,233
+.byte	101,101,137,101,15,236,202,106,101,101,137,101,15,236,202,106
+.byte	186,186,210,186,185,104,105,3,186,186,210,186,185,104,105,3
+.byte	47,47,188,47,101,147,94,74,47,47,188,47,101,147,94,74
+.byte	192,192,39,192,78,231,157,142,192,192,39,192,78,231,157,142
+.byte	222,222,95,222,190,129,161,96,222,222,95,222,190,129,161,96
+.byte	28,28,112,28,224,108,56,252,28,28,112,28,224,108,56,252
+.byte	253,253,211,253,187,46,231,70,253,253,211,253,187,46,231,70
+.byte	77,77,41,77,82,100,154,31,77,77,41,77,82,100,154,31
+.byte	146,146,114,146,228,224,57,118,146,146,114,146,228,224,57,118
+.byte	117,117,201,117,143,188,234,250,117,117,201,117,143,188,234,250
+.byte	6,6,24,6,48,30,12,54,6,6,24,6,48,30,12,54
+.byte	138,138,18,138,36,152,9,174,138,138,18,138,36,152,9,174
+.byte	178,178,242,178,249,64,121,75,178,178,242,178,249,64,121,75
+.byte	230,230,191,230,99,89,209,133,230,230,191,230,99,89,209,133
+.byte	14,14,56,14,112,54,28,126,14,14,56,14,112,54,28,126
+.byte	31,31,124,31,248,99,62,231,31,31,124,31,248,99,62,231
+.byte	98,98,149,98,55,247,196,85,98,98,149,98,55,247,196,85
+.byte	212,212,119,212,238,163,181,58,212,212,119,212,238,163,181,58
+.byte	168,168,154,168,41,50,77,129,168,168,154,168,41,50,77,129
+.byte	150,150,98,150,196,244,49,82,150,150,98,150,196,244,49,82
+.byte	249,249,195,249,155,58,239,98,249,249,195,249,155,58,239,98
+.byte	197,197,51,197,102,246,151,163,197,197,51,197,102,246,151,163
+.byte	37,37,148,37,53,177,74,16,37,37,148,37,53,177,74,16
+.byte	89,89,121,89,242,32,178,171,89,89,121,89,242,32,178,171
+.byte	132,132,42,132,84,174,21,208,132,132,42,132,84,174,21,208
+.byte	114,114,213,114,183,167,228,197,114,114,213,114,183,167,228,197
+.byte	57,57,228,57,213,221,114,236,57,57,228,57,213,221,114,236
+.byte	76,76,45,76,90,97,152,22,76,76,45,76,90,97,152,22
+.byte	94,94,101,94,202,59,188,148,94,94,101,94,202,59,188,148
+.byte	120,120,253,120,231,133,240,159,120,120,253,120,231,133,240,159
+.byte	56,56,224,56,221,216,112,229,56,56,224,56,221,216,112,229
+.byte	140,140,10,140,20,134,5,152,140,140,10,140,20,134,5,152
+.byte	209,209,99,209,198,178,191,23,209,209,99,209,198,178,191,23
+.byte	165,165,174,165,65,11,87,228,165,165,174,165,65,11,87,228
+.byte	226,226,175,226,67,77,217,161,226,226,175,226,67,77,217,161
+.byte	97,97,153,97,47,248,194,78,97,97,153,97,47,248,194,78
+.byte	179,179,246,179,241,69,123,66,179,179,246,179,241,69,123,66
+.byte	33,33,132,33,21,165,66,52,33,33,132,33,21,165,66,52
+.byte	156,156,74,156,148,214,37,8,156,156,74,156,148,214,37,8
+.byte	30,30,120,30,240,102,60,238,30,30,120,30,240,102,60,238
+.byte	67,67,17,67,34,82,134,97,67,67,17,67,34,82,134,97
+.byte	199,199,59,199,118,252,147,177,199,199,59,199,118,252,147,177
+.byte	252,252,215,252,179,43,229,79,252,252,215,252,179,43,229,79
+.byte	4,4,16,4,32,20,8,36,4,4,16,4,32,20,8,36
+.byte	81,81,89,81,178,8,162,227,81,81,89,81,178,8,162,227
+.byte	153,153,94,153,188,199,47,37,153,153,94,153,188,199,47,37
+.byte	109,109,169,109,79,196,218,34,109,109,169,109,79,196,218,34
+.byte	13,13,52,13,104,57,26,101,13,13,52,13,104,57,26,101
+.byte	250,250,207,250,131,53,233,121,250,250,207,250,131,53,233,121
+.byte	223,223,91,223,182,132,163,105,223,223,91,223,182,132,163,105
+.byte	126,126,229,126,215,155,252,169,126,126,229,126,215,155,252,169
+.byte	36,36,144,36,61,180,72,25,36,36,144,36,61,180,72,25
+.byte	59,59,236,59,197,215,118,254,59,59,236,59,197,215,118,254
+.byte	171,171,150,171,49,61,75,154,171,171,150,171,49,61,75,154
+.byte	206,206,31,206,62,209,129,240,206,206,31,206,62,209,129,240
+.byte	17,17,68,17,136,85,34,153,17,17,68,17,136,85,34,153
+.byte	143,143,6,143,12,137,3,131,143,143,6,143,12,137,3,131
+.byte	78,78,37,78,74,107,156,4,78,78,37,78,74,107,156,4
+.byte	183,183,230,183,209,81,115,102,183,183,230,183,209,81,115,102
+.byte	235,235,139,235,11,96,203,224,235,235,139,235,11,96,203,224
+.byte	60,60,240,60,253,204,120,193,60,60,240,60,253,204,120,193
+.byte	129,129,62,129,124,191,31,253,129,129,62,129,124,191,31,253
+.byte	148,148,106,148,212,254,53,64,148,148,106,148,212,254,53,64
+.byte	247,247,251,247,235,12,243,28,247,247,251,247,235,12,243,28
+.byte	185,185,222,185,161,103,111,24,185,185,222,185,161,103,111,24
+.byte	19,19,76,19,152,95,38,139,19,19,76,19,152,95,38,139
+.byte	44,44,176,44,125,156,88,81,44,44,176,44,125,156,88,81
+.byte	211,211,107,211,214,184,187,5,211,211,107,211,214,184,187,5
+.byte	231,231,187,231,107,92,211,140,231,231,187,231,107,92,211,140
+.byte	110,110,165,110,87,203,220,57,110,110,165,110,87,203,220,57
+.byte	196,196,55,196,110,243,149,170,196,196,55,196,110,243,149,170
+.byte	3,3,12,3,24,15,6,27,3,3,12,3,24,15,6,27
+.byte	86,86,69,86,138,19,172,220,86,86,69,86,138,19,172,220
+.byte	68,68,13,68,26,73,136,94,68,68,13,68,26,73,136,94
+.byte	127,127,225,127,223,158,254,160,127,127,225,127,223,158,254,160
+.byte	169,169,158,169,33,55,79,136,169,169,158,169,33,55,79,136
+.byte	42,42,168,42,77,130,84,103,42,42,168,42,77,130,84,103
+.byte	187,187,214,187,177,109,107,10,187,187,214,187,177,109,107,10
+.byte	193,193,35,193,70,226,159,135,193,193,35,193,70,226,159,135
+.byte	83,83,81,83,162,2,166,241,83,83,81,83,162,2,166,241
+.byte	220,220,87,220,174,139,165,114,220,220,87,220,174,139,165,114
+.byte	11,11,44,11,88,39,22,83,11,11,44,11,88,39,22,83
+.byte	157,157,78,157,156,211,39,1,157,157,78,157,156,211,39,1
+.byte	108,108,173,108,71,193,216,43,108,108,173,108,71,193,216,43
+.byte	49,49,196,49,149,245,98,164,49,49,196,49,149,245,98,164
+.byte	116,116,205,116,135,185,232,243,116,116,205,116,135,185,232,243
+.byte	246,246,255,246,227,9,241,21,246,246,255,246,227,9,241,21
+.byte	70,70,5,70,10,67,140,76,70,70,5,70,10,67,140,76
+.byte	172,172,138,172,9,38,69,165,172,172,138,172,9,38,69,165
+.byte	137,137,30,137,60,151,15,181,137,137,30,137,60,151,15,181
+.byte	20,20,80,20,160,68,40,180,20,20,80,20,160,68,40,180
+.byte	225,225,163,225,91,66,223,186,225,225,163,225,91,66,223,186
+.byte	22,22,88,22,176,78,44,166,22,22,88,22,176,78,44,166
+.byte	58,58,232,58,205,210,116,247,58,58,232,58,205,210,116,247
+.byte	105,105,185,105,111,208,210,6,105,105,185,105,111,208,210,6
+.byte	9,9,36,9,72,45,18,65,9,9,36,9,72,45,18,65
+.byte	112,112,221,112,167,173,224,215,112,112,221,112,167,173,224,215
+.byte	182,182,226,182,217,84,113,111,182,182,226,182,217,84,113,111
+.byte	208,208,103,208,206,183,189,30,208,208,103,208,206,183,189,30
+.byte	237,237,147,237,59,126,199,214,237,237,147,237,59,126,199,214
+.byte	204,204,23,204,46,219,133,226,204,204,23,204,46,219,133,226
+.byte	66,66,21,66,42,87,132,104,66,66,21,66,42,87,132,104
+.byte	152,152,90,152,180,194,45,44,152,152,90,152,180,194,45,44
+.byte	164,164,170,164,73,14,85,237,164,164,170,164,73,14,85,237
+.byte	40,40,160,40,93,136,80,117,40,40,160,40,93,136,80,117
+.byte	92,92,109,92,218,49,184,134,92,92,109,92,218,49,184,134
+.byte	248,248,199,248,147,63,237,107,248,248,199,248,147,63,237,107
+.byte	134,134,34,134,68,164,17,194,134,134,34,134,68,164,17,194
+.byte	24,35,198,232,135,184,1,79
+.byte	54,166,210,245,121,111,145,82
+.byte	96,188,155,142,163,12,123,53
+.byte	29,224,215,194,46,75,254,87
+.byte	21,119,55,229,159,240,74,218
+.byte	88,201,41,10,177,160,107,133
+.byte	189,93,16,244,203,62,5,103
+.byte	228,39,65,139,167,125,149,216
+.byte	251,238,124,102,221,23,71,158
+.byte	202,45,191,7,173,90,131,51
diff --git a/crypto/whrlpool/wp-masm-x86_64.S b/crypto/whrlpool/wp-masm-x86_64.S
new file mode 100644
index 0000000..2f4bd73
--- /dev/null
+++ b/crypto/whrlpool/wp-masm-x86_64.S
@@ -0,0 +1,943 @@
+; 1 "crypto/whrlpool/wp-masm-x86_64.S.tmp"
+; 1 "" 1
+; 1 "" 3
+; 399 "" 3
+; 1 "" 1
+; 1 "" 2
+; 1 "crypto/whrlpool/wp-masm-x86_64.S.tmp" 2
+OPTION	DOTNAME
+
+; 1 "./crypto/x86_arch.h" 1
+
+
+; 16 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+   
+
+
+; 40 "./crypto/x86_arch.h"
+   
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+; 3 "crypto/whrlpool/wp-masm-x86_64.S.tmp" 2
+.text$	SEGMENT ALIGN(64) 'CODE'
+
+PUBLIC	whirlpool_block
+
+ALIGN	16
+whirlpool_block	PROC PUBLIC
+	mov	QWORD PTR[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD PTR[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_whirlpool_block::
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+
+	mov	r11,rsp
+	sub	rsp,128+40
+	and	rsp,-64
+
+	lea	r10,QWORD PTR[128+rsp]
+	mov	QWORD PTR[r10],rdi
+	mov	QWORD PTR[8+r10],rsi
+	mov	QWORD PTR[16+r10],rdx
+	mov	QWORD PTR[32+r10],r11
+$L$prologue::
+
+	mov	rbx,r10
+	lea	rbp,QWORD PTR[$L$table]
+
+	xor	rcx,rcx
+	xor	rdx,rdx
+	mov	r8,QWORD PTR[rdi]
+	mov	r9,QWORD PTR[8+rdi]
+	mov	r10,QWORD PTR[16+rdi]
+	mov	r11,QWORD PTR[24+rdi]
+	mov	r12,QWORD PTR[32+rdi]
+	mov	r13,QWORD PTR[40+rdi]
+	mov	r14,QWORD PTR[48+rdi]
+	mov	r15,QWORD PTR[56+rdi]
+$L$outerloop::
+	mov	QWORD PTR[rsp],r8
+	mov	QWORD PTR[8+rsp],r9
+	mov	QWORD PTR[16+rsp],r10
+	mov	QWORD PTR[24+rsp],r11
+	mov	QWORD PTR[32+rsp],r12
+	mov	QWORD PTR[40+rsp],r13
+	mov	QWORD PTR[48+rsp],r14
+	mov	QWORD PTR[56+rsp],r15
+	xor	r8,QWORD PTR[rsi]
+	xor	r9,QWORD PTR[8+rsi]
+	xor	r10,QWORD PTR[16+rsi]
+	xor	r11,QWORD PTR[24+rsi]
+	xor	r12,QWORD PTR[32+rsi]
+	xor	r13,QWORD PTR[40+rsi]
+	xor	r14,QWORD PTR[48+rsi]
+	xor	r15,QWORD PTR[56+rsi]
+	mov	QWORD PTR[((64+0))+rsp],r8
+	mov	QWORD PTR[((64+8))+rsp],r9
+	mov	QWORD PTR[((64+16))+rsp],r10
+	mov	QWORD PTR[((64+24))+rsp],r11
+	mov	QWORD PTR[((64+32))+rsp],r12
+	mov	QWORD PTR[((64+40))+rsp],r13
+	mov	QWORD PTR[((64+48))+rsp],r14
+	mov	QWORD PTR[((64+56))+rsp],r15
+	xor	rsi,rsi
+	mov	QWORD PTR[24+rbx],rsi
+ALIGN	16
+$L$round::
+	mov	r8,QWORD PTR[4096+rsi*8+rbp]
+	mov	eax,DWORD PTR[rsp]
+	mov	ebx,DWORD PTR[4+rsp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r8,QWORD PTR[rsi*8+rbp]
+	mov	r9,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((0+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	mov	r10,QWORD PTR[6+rsi*8+rbp]
+	mov	r11,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	mov	r12,QWORD PTR[4+rsi*8+rbp]
+	mov	r13,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((0+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	mov	r14,QWORD PTR[2+rsi*8+rbp]
+	mov	r15,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r9,QWORD PTR[rsi*8+rbp]
+	xor	r10,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((8+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r11,QWORD PTR[6+rsi*8+rbp]
+	xor	r12,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r13,QWORD PTR[4+rsi*8+rbp]
+	xor	r14,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((8+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r15,QWORD PTR[2+rsi*8+rbp]
+	xor	r8,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r10,QWORD PTR[rsi*8+rbp]
+	xor	r11,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((16+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r12,QWORD PTR[6+rsi*8+rbp]
+	xor	r13,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r14,QWORD PTR[4+rsi*8+rbp]
+	xor	r15,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((16+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r8,QWORD PTR[2+rsi*8+rbp]
+	xor	r9,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r11,QWORD PTR[rsi*8+rbp]
+	xor	r12,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((24+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r13,QWORD PTR[6+rsi*8+rbp]
+	xor	r14,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r15,QWORD PTR[4+rsi*8+rbp]
+	xor	r8,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((24+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r9,QWORD PTR[2+rsi*8+rbp]
+	xor	r10,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r12,QWORD PTR[rsi*8+rbp]
+	xor	r13,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((32+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r14,QWORD PTR[6+rsi*8+rbp]
+	xor	r15,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r8,QWORD PTR[4+rsi*8+rbp]
+	xor	r9,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((32+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r10,QWORD PTR[2+rsi*8+rbp]
+	xor	r11,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r13,QWORD PTR[rsi*8+rbp]
+	xor	r14,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((40+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r15,QWORD PTR[6+rsi*8+rbp]
+	xor	r8,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r9,QWORD PTR[4+rsi*8+rbp]
+	xor	r10,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((40+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r11,QWORD PTR[2+rsi*8+rbp]
+	xor	r12,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r14,QWORD PTR[rsi*8+rbp]
+	xor	r15,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((48+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r8,QWORD PTR[6+rsi*8+rbp]
+	xor	r9,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r10,QWORD PTR[4+rsi*8+rbp]
+	xor	r11,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((48+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r12,QWORD PTR[2+rsi*8+rbp]
+	xor	r13,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r15,QWORD PTR[rsi*8+rbp]
+	xor	r8,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((56+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r9,QWORD PTR[6+rsi*8+rbp]
+	xor	r10,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r11,QWORD PTR[4+rsi*8+rbp]
+	xor	r12,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((56+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r13,QWORD PTR[2+rsi*8+rbp]
+	xor	r14,QWORD PTR[1+rdi*8+rbp]
+	mov	QWORD PTR[rsp],r8
+	mov	QWORD PTR[8+rsp],r9
+	mov	QWORD PTR[16+rsp],r10
+	mov	QWORD PTR[24+rsp],r11
+	mov	QWORD PTR[32+rsp],r12
+	mov	QWORD PTR[40+rsp],r13
+	mov	QWORD PTR[48+rsp],r14
+	mov	QWORD PTR[56+rsp],r15
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r8,QWORD PTR[rsi*8+rbp]
+	xor	r9,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+0+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r10,QWORD PTR[6+rsi*8+rbp]
+	xor	r11,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r12,QWORD PTR[4+rsi*8+rbp]
+	xor	r13,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+0+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r14,QWORD PTR[2+rsi*8+rbp]
+	xor	r15,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r9,QWORD PTR[rsi*8+rbp]
+	xor	r10,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+8+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r11,QWORD PTR[6+rsi*8+rbp]
+	xor	r12,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r13,QWORD PTR[4+rsi*8+rbp]
+	xor	r14,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+8+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r15,QWORD PTR[2+rsi*8+rbp]
+	xor	r8,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r10,QWORD PTR[rsi*8+rbp]
+	xor	r11,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+16+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r12,QWORD PTR[6+rsi*8+rbp]
+	xor	r13,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r14,QWORD PTR[4+rsi*8+rbp]
+	xor	r15,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+16+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r8,QWORD PTR[2+rsi*8+rbp]
+	xor	r9,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r11,QWORD PTR[rsi*8+rbp]
+	xor	r12,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+24+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r13,QWORD PTR[6+rsi*8+rbp]
+	xor	r14,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r15,QWORD PTR[4+rsi*8+rbp]
+	xor	r8,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+24+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r9,QWORD PTR[2+rsi*8+rbp]
+	xor	r10,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r12,QWORD PTR[rsi*8+rbp]
+	xor	r13,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+32+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r14,QWORD PTR[6+rsi*8+rbp]
+	xor	r15,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r8,QWORD PTR[4+rsi*8+rbp]
+	xor	r9,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+32+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r10,QWORD PTR[2+rsi*8+rbp]
+	xor	r11,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r13,QWORD PTR[rsi*8+rbp]
+	xor	r14,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+40+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r15,QWORD PTR[6+rsi*8+rbp]
+	xor	r8,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r9,QWORD PTR[4+rsi*8+rbp]
+	xor	r10,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+40+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r11,QWORD PTR[2+rsi*8+rbp]
+	xor	r12,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r14,QWORD PTR[rsi*8+rbp]
+	xor	r15,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	mov	eax,DWORD PTR[((64+48+8))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r8,QWORD PTR[6+rsi*8+rbp]
+	xor	r9,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r10,QWORD PTR[4+rsi*8+rbp]
+	xor	r11,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	mov	ebx,DWORD PTR[((64+48+8+4))+rsp]
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r12,QWORD PTR[2+rsi*8+rbp]
+	xor	r13,QWORD PTR[1+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	eax,16
+	xor	r15,QWORD PTR[rsi*8+rbp]
+	xor	r8,QWORD PTR[7+rdi*8+rbp]
+	mov	cl,al
+	mov	dl,ah
+
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r9,QWORD PTR[6+rsi*8+rbp]
+	xor	r10,QWORD PTR[5+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	shr	ebx,16
+	xor	r11,QWORD PTR[4+rsi*8+rbp]
+	xor	r12,QWORD PTR[3+rdi*8+rbp]
+	mov	cl,bl
+	mov	dl,bh
+
+	lea	rsi,QWORD PTR[rcx*1+rcx]
+	lea	rdi,QWORD PTR[rdx*1+rdx]
+	xor	r13,QWORD PTR[2+rsi*8+rbp]
+	xor	r14,QWORD PTR[1+rdi*8+rbp]
+	lea	rbx,QWORD PTR[128+rsp]
+	mov	rsi,QWORD PTR[24+rbx]
+	add	rsi,1
+	cmp	rsi,10
+	je	$L$roundsdone
+
+	mov	QWORD PTR[24+rbx],rsi
+	mov	QWORD PTR[((64+0))+rsp],r8
+	mov	QWORD PTR[((64+8))+rsp],r9
+	mov	QWORD PTR[((64+16))+rsp],r10
+	mov	QWORD PTR[((64+24))+rsp],r11
+	mov	QWORD PTR[((64+32))+rsp],r12
+	mov	QWORD PTR[((64+40))+rsp],r13
+	mov	QWORD PTR[((64+48))+rsp],r14
+	mov	QWORD PTR[((64+56))+rsp],r15
+	jmp	$L$round
+ALIGN	16
+$L$roundsdone::
+	mov	rdi,QWORD PTR[rbx]
+	mov	rsi,QWORD PTR[8+rbx]
+	mov	rax,QWORD PTR[16+rbx]
+	xor	r8,QWORD PTR[rsi]
+	xor	r9,QWORD PTR[8+rsi]
+	xor	r10,QWORD PTR[16+rsi]
+	xor	r11,QWORD PTR[24+rsi]
+	xor	r12,QWORD PTR[32+rsi]
+	xor	r13,QWORD PTR[40+rsi]
+	xor	r14,QWORD PTR[48+rsi]
+	xor	r15,QWORD PTR[56+rsi]
+	xor	r8,QWORD PTR[rdi]
+	xor	r9,QWORD PTR[8+rdi]
+	xor	r10,QWORD PTR[16+rdi]
+	xor	r11,QWORD PTR[24+rdi]
+	xor	r12,QWORD PTR[32+rdi]
+	xor	r13,QWORD PTR[40+rdi]
+	xor	r14,QWORD PTR[48+rdi]
+	xor	r15,QWORD PTR[56+rdi]
+	mov	QWORD PTR[rdi],r8
+	mov	QWORD PTR[8+rdi],r9
+	mov	QWORD PTR[16+rdi],r10
+	mov	QWORD PTR[24+rdi],r11
+	mov	QWORD PTR[32+rdi],r12
+	mov	QWORD PTR[40+rdi],r13
+	mov	QWORD PTR[48+rdi],r14
+	mov	QWORD PTR[56+rdi],r15
+	lea	rsi,QWORD PTR[64+rsi]
+	sub	rax,1
+	jz	$L$alldone
+	mov	QWORD PTR[8+rbx],rsi
+	mov	QWORD PTR[16+rbx],rax
+	jmp	$L$outerloop
+$L$alldone::
+	mov	rsi,QWORD PTR[32+rbx]
+	mov	r15,QWORD PTR[rsi]
+	mov	r14,QWORD PTR[8+rsi]
+	mov	r13,QWORD PTR[16+rsi]
+	mov	r12,QWORD PTR[24+rsi]
+	mov	rbp,QWORD PTR[32+rsi]
+	mov	rbx,QWORD PTR[40+rsi]
+	lea	rsp,QWORD PTR[48+rsi]
+$L$epilogue::
+	mov	rdi,QWORD PTR[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD PTR[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_whirlpool_block::
+whirlpool_block	ENDP
+
+ALIGN	64
+
+$L$table::
+DB	24,24,96,24,192,120,48,216,24,24,96,24,192,120,48,216
+DB	35,35,140,35,5,175,70,38,35,35,140,35,5,175,70,38
+DB	198,198,63,198,126,249,145,184,198,198,63,198,126,249,145,184
+DB	232,232,135,232,19,111,205,251,232,232,135,232,19,111,205,251
+DB	135,135,38,135,76,161,19,203,135,135,38,135,76,161,19,203
+DB	184,184,218,184,169,98,109,17,184,184,218,184,169,98,109,17
+DB	1,1,4,1,8,5,2,9,1,1,4,1,8,5,2,9
+DB	79,79,33,79,66,110,158,13,79,79,33,79,66,110,158,13
+DB	54,54,216,54,173,238,108,155,54,54,216,54,173,238,108,155
+DB	166,166,162,166,89,4,81,255,166,166,162,166,89,4,81,255
+DB	210,210,111,210,222,189,185,12,210,210,111,210,222,189,185,12
+DB	245,245,243,245,251,6,247,14,245,245,243,245,251,6,247,14
+DB	121,121,249,121,239,128,242,150,121,121,249,121,239,128,242,150
+DB	111,111,161,111,95,206,222,48,111,111,161,111,95,206,222,48
+DB	145,145,126,145,252,239,63,109,145,145,126,145,252,239,63,109
+DB	82,82,85,82,170,7,164,248,82,82,85,82,170,7,164,248
+DB	96,96,157,96,39,253,192,71,96,96,157,96,39,253,192,71
+DB	188,188,202,188,137,118,101,53,188,188,202,188,137,118,101,53
+DB	155,155,86,155,172,205,43,55,155,155,86,155,172,205,43,55
+DB	142,142,2,142,4,140,1,138,142,142,2,142,4,140,1,138
+DB	163,163,182,163,113,21,91,210,163,163,182,163,113,21,91,210
+DB	12,12,48,12,96,60,24,108,12,12,48,12,96,60,24,108
+DB	123,123,241,123,255,138,246,132,123,123,241,123,255,138,246,132
+DB	53,53,212,53,181,225,106,128,53,53,212,53,181,225,106,128
+DB	29,29,116,29,232,105,58,245,29,29,116,29,232,105,58,245
+DB	224,224,167,224,83,71,221,179,224,224,167,224,83,71,221,179
+DB	215,215,123,215,246,172,179,33,215,215,123,215,246,172,179,33
+DB	194,194,47,194,94,237,153,156,194,194,47,194,94,237,153,156
+DB	46,46,184,46,109,150,92,67,46,46,184,46,109,150,92,67
+DB	75,75,49,75,98,122,150,41,75,75,49,75,98,122,150,41
+DB	254,254,223,254,163,33,225,93,254,254,223,254,163,33,225,93
+DB	87,87,65,87,130,22,174,213,87,87,65,87,130,22,174,213
+DB	21,21,84,21,168,65,42,189,21,21,84,21,168,65,42,189
+DB	119,119,193,119,159,182,238,232,119,119,193,119,159,182,238,232
+DB	55,55,220,55,165,235,110,146,55,55,220,55,165,235,110,146
+DB	229,229,179,229,123,86,215,158,229,229,179,229,123,86,215,158
+DB	159,159,70,159,140,217,35,19,159,159,70,159,140,217,35,19
+DB	240,240,231,240,211,23,253,35,240,240,231,240,211,23,253,35
+DB	74,74,53,74,106,127,148,32,74,74,53,74,106,127,148,32
+DB	218,218,79,218,158,149,169,68,218,218,79,218,158,149,169,68
+DB	88,88,125,88,250,37,176,162,88,88,125,88,250,37,176,162
+DB	201,201,3,201,6,202,143,207,201,201,3,201,6,202,143,207
+DB	41,41,164,41,85,141,82,124,41,41,164,41,85,141,82,124
+DB	10,10,40,10,80,34,20,90,10,10,40,10,80,34,20,90
+DB	177,177,254,177,225,79,127,80,177,177,254,177,225,79,127,80
+DB	160,160,186,160,105,26,93,201,160,160,186,160,105,26,93,201
+DB	107,107,177,107,127,218,214,20,107,107,177,107,127,218,214,20
+DB	133,133,46,133,92,171,23,217,133,133,46,133,92,171,23,217
+DB	189,189,206,189,129,115,103,60,189,189,206,189,129,115,103,60
+DB	93,93,105,93,210,52,186,143,93,93,105,93,210,52,186,143
+DB	16,16,64,16,128,80,32,144,16,16,64,16,128,80,32,144
+DB	244,244,247,244,243,3,245,7,244,244,247,244,243,3,245,7
+DB	203,203,11,203,22,192,139,221,203,203,11,203,22,192,139,221
+DB	62,62,248,62,237,198,124,211,62,62,248,62,237,198,124,211
+DB	5,5,20,5,40,17,10,45,5,5,20,5,40,17,10,45
+DB	103,103,129,103,31,230,206,120,103,103,129,103,31,230,206,120
+DB	228,228,183,228,115,83,213,151,228,228,183,228,115,83,213,151
+DB	39,39,156,39,37,187,78,2,39,39,156,39,37,187,78,2
+DB	65,65,25,65,50,88,130,115,65,65,25,65,50,88,130,115
+DB	139,139,22,139,44,157,11,167,139,139,22,139,44,157,11,167
+DB	167,167,166,167,81,1,83,246,167,167,166,167,81,1,83,246
+DB	125,125,233,125,207,148,250,178,125,125,233,125,207,148,250,178
+DB	149,149,110,149,220,251,55,73,149,149,110,149,220,251,55,73
+DB	216,216,71,216,142,159,173,86,216,216,71,216,142,159,173,86
+DB	251,251,203,251,139,48,235,112,251,251,203,251,139,48,235,112
+DB	238,238,159,238,35,113,193,205,238,238,159,238,35,113,193,205
+DB	124,124,237,124,199,145,248,187,124,124,237,124,199,145,248,187
+DB	102,102,133,102,23,227,204,113,102,102,133,102,23,227,204,113
+DB	221,221,83,221,166,142,167,123,221,221,83,221,166,142,167,123
+DB	23,23,92,23,184,75,46,175,23,23,92,23,184,75,46,175
+DB	71,71,1,71,2,70,142,69,71,71,1,71,2,70,142,69
+DB	158,158,66,158,132,220,33,26,158,158,66,158,132,220,33,26
+DB	202,202,15,202,30,197,137,212,202,202,15,202,30,197,137,212
+DB	45,45,180,45,117,153,90,88,45,45,180,45,117,153,90,88
+DB	191,191,198,191,145,121,99,46,191,191,198,191,145,121,99,46
+DB	7,7,28,7,56,27,14,63,7,7,28,7,56,27,14,63
+DB	173,173,142,173,1,35,71,172,173,173,142,173,1,35,71,172
+DB	90,90,117,90,234,47,180,176,90,90,117,90,234,47,180,176
+DB	131,131,54,131,108,181,27,239,131,131,54,131,108,181,27,239
+DB	51,51,204,51,133,255,102,182,51,51,204,51,133,255,102,182
+DB	99,99,145,99,63,242,198,92,99,99,145,99,63,242,198,92
+DB	2,2,8,2,16,10,4,18,2,2,8,2,16,10,4,18
+DB	170,170,146,170,57,56,73,147,170,170,146,170,57,56,73,147
+DB	113,113,217,113,175,168,226,222,113,113,217,113,175,168,226,222
+DB	200,200,7,200,14,207,141,198,200,200,7,200,14,207,141,198
+DB	25,25,100,25,200,125,50,209,25,25,100,25,200,125,50,209
+DB	73,73,57,73,114,112,146,59,73,73,57,73,114,112,146,59
+DB	217,217,67,217,134,154,175,95,217,217,67,217,134,154,175,95
+DB	242,242,239,242,195,29,249,49,242,242,239,242,195,29,249,49
+DB	227,227,171,227,75,72,219,168,227,227,171,227,75,72,219,168
+DB	91,91,113,91,226,42,182,185,91,91,113,91,226,42,182,185
+DB	136,136,26,136,52,146,13,188,136,136,26,136,52,146,13,188
+DB	154,154,82,154,164,200,41,62,154,154,82,154,164,200,41,62
+DB	38,38,152,38,45,190,76,11,38,38,152,38,45,190,76,11
+DB	50,50,200,50,141,250,100,191,50,50,200,50,141,250,100,191
+DB	176,176,250,176,233,74,125,89,176,176,250,176,233,74,125,89
+DB	233,233,131,233,27,106,207,242,233,233,131,233,27,106,207,242
+DB	15,15,60,15,120,51,30,119,15,15,60,15,120,51,30,119
+DB	213,213,115,213,230,166,183,51,213,213,115,213,230,166,183,51
+DB	128,128,58,128,116,186,29,244,128,128,58,128,116,186,29,244
+DB	190,190,194,190,153,124,97,39,190,190,194,190,153,124,97,39
+DB	205,205,19,205,38,222,135,235,205,205,19,205,38,222,135,235
+DB	52,52,208,52,189,228,104,137,52,52,208,52,189,228,104,137
+DB	72,72,61,72,122,117,144,50,72,72,61,72,122,117,144,50
+DB	255,255,219,255,171,36,227,84,255,255,219,255,171,36,227,84
+DB	122,122,245,122,247,143,244,141,122,122,245,122,247,143,244,141
+DB	144,144,122,144,244,234,61,100,144,144,122,144,244,234,61,100
+DB	95,95,97,95,194,62,190,157,95,95,97,95,194,62,190,157
+DB	32,32,128,32,29,160,64,61,32,32,128,32,29,160,64,61
+DB	104,104,189,104,103,213,208,15,104,104,189,104,103,213,208,15
+DB	26,26,104,26,208,114,52,202,26,26,104,26,208,114,52,202
+DB	174,174,130,174,25,44,65,183,174,174,130,174,25,44,65,183
+DB	180,180,234,180,201,94,117,125,180,180,234,180,201,94,117,125
+DB	84,84,77,84,154,25,168,206,84,84,77,84,154,25,168,206
+DB	147,147,118,147,236,229,59,127,147,147,118,147,236,229,59,127
+DB	34,34,136,34,13,170,68,47,34,34,136,34,13,170,68,47
+DB	100,100,141,100,7,233,200,99,100,100,141,100,7,233,200,99
+DB	241,241,227,241,219,18,255,42,241,241,227,241,219,18,255,42
+DB	115,115,209,115,191,162,230,204,115,115,209,115,191,162,230,204
+DB	18,18,72,18,144,90,36,130,18,18,72,18,144,90,36,130
+DB	64,64,29,64,58,93,128,122,64,64,29,64,58,93,128,122
+DB	8,8,32,8,64,40,16,72,8,8,32,8,64,40,16,72
+DB	195,195,43,195,86,232,155,149,195,195,43,195,86,232,155,149
+DB	236,236,151,236,51,123,197,223,236,236,151,236,51,123,197,223
+DB	219,219,75,219,150,144,171,77,219,219,75,219,150,144,171,77
+DB	161,161,190,161,97,31,95,192,161,161,190,161,97,31,95,192
+DB	141,141,14,141,28,131,7,145,141,141,14,141,28,131,7,145
+DB	61,61,244,61,245,201,122,200,61,61,244,61,245,201,122,200
+DB	151,151,102,151,204,241,51,91,151,151,102,151,204,241,51,91
+DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+DB	207,207,27,207,54,212,131,249,207,207,27,207,54,212,131,249
+DB	43,43,172,43,69,135,86,110,43,43,172,43,69,135,86,110
+DB	118,118,197,118,151,179,236,225,118,118,197,118,151,179,236,225
+DB	130,130,50,130,100,176,25,230,130,130,50,130,100,176,25,230
+DB	214,214,127,214,254,169,177,40,214,214,127,214,254,169,177,40
+DB	27,27,108,27,216,119,54,195,27,27,108,27,216,119,54,195
+DB	181,181,238,181,193,91,119,116,181,181,238,181,193,91,119,116
+DB	175,175,134,175,17,41,67,190,175,175,134,175,17,41,67,190
+DB	106,106,181,106,119,223,212,29,106,106,181,106,119,223,212,29
+DB	80,80,93,80,186,13,160,234,80,80,93,80,186,13,160,234
+DB	69,69,9,69,18,76,138,87,69,69,9,69,18,76,138,87
+DB	243,243,235,243,203,24,251,56,243,243,235,243,203,24,251,56
+DB	48,48,192,48,157,240,96,173,48,48,192,48,157,240,96,173
+DB	239,239,155,239,43,116,195,196,239,239,155,239,43,116,195,196
+DB	63,63,252,63,229,195,126,218,63,63,252,63,229,195,126,218
+DB	85,85,73,85,146,28,170,199,85,85,73,85,146,28,170,199
+DB	162,162,178,162,121,16,89,219,162,162,178,162,121,16,89,219
+DB	234,234,143,234,3,101,201,233,234,234,143,234,3,101,201,233
+DB	101,101,137,101,15,236,202,106,101,101,137,101,15,236,202,106
+DB	186,186,210,186,185,104,105,3,186,186,210,186,185,104,105,3
+DB	47,47,188,47,101,147,94,74,47,47,188,47,101,147,94,74
+DB	192,192,39,192,78,231,157,142,192,192,39,192,78,231,157,142
+DB	222,222,95,222,190,129,161,96,222,222,95,222,190,129,161,96
+DB	28,28,112,28,224,108,56,252,28,28,112,28,224,108,56,252
+DB	253,253,211,253,187,46,231,70,253,253,211,253,187,46,231,70
+DB	77,77,41,77,82,100,154,31,77,77,41,77,82,100,154,31
+DB	146,146,114,146,228,224,57,118,146,146,114,146,228,224,57,118
+DB	117,117,201,117,143,188,234,250,117,117,201,117,143,188,234,250
+DB	6,6,24,6,48,30,12,54,6,6,24,6,48,30,12,54
+DB	138,138,18,138,36,152,9,174,138,138,18,138,36,152,9,174
+DB	178,178,242,178,249,64,121,75,178,178,242,178,249,64,121,75
+DB	230,230,191,230,99,89,209,133,230,230,191,230,99,89,209,133
+DB	14,14,56,14,112,54,28,126,14,14,56,14,112,54,28,126
+DB	31,31,124,31,248,99,62,231,31,31,124,31,248,99,62,231
+DB	98,98,149,98,55,247,196,85,98,98,149,98,55,247,196,85
+DB	212,212,119,212,238,163,181,58,212,212,119,212,238,163,181,58
+DB	168,168,154,168,41,50,77,129,168,168,154,168,41,50,77,129
+DB	150,150,98,150,196,244,49,82,150,150,98,150,196,244,49,82
+DB	249,249,195,249,155,58,239,98,249,249,195,249,155,58,239,98
+DB	197,197,51,197,102,246,151,163,197,197,51,197,102,246,151,163
+DB	37,37,148,37,53,177,74,16,37,37,148,37,53,177,74,16
+DB	89,89,121,89,242,32,178,171,89,89,121,89,242,32,178,171
+DB	132,132,42,132,84,174,21,208,132,132,42,132,84,174,21,208
+DB	114,114,213,114,183,167,228,197,114,114,213,114,183,167,228,197
+DB	57,57,228,57,213,221,114,236,57,57,228,57,213,221,114,236
+DB	76,76,45,76,90,97,152,22,76,76,45,76,90,97,152,22
+DB	94,94,101,94,202,59,188,148,94,94,101,94,202,59,188,148
+DB	120,120,253,120,231,133,240,159,120,120,253,120,231,133,240,159
+DB	56,56,224,56,221,216,112,229,56,56,224,56,221,216,112,229
+DB	140,140,10,140,20,134,5,152,140,140,10,140,20,134,5,152
+DB	209,209,99,209,198,178,191,23,209,209,99,209,198,178,191,23
+DB	165,165,174,165,65,11,87,228,165,165,174,165,65,11,87,228
+DB	226,226,175,226,67,77,217,161,226,226,175,226,67,77,217,161
+DB	97,97,153,97,47,248,194,78,97,97,153,97,47,248,194,78
+DB	179,179,246,179,241,69,123,66,179,179,246,179,241,69,123,66
+DB	33,33,132,33,21,165,66,52,33,33,132,33,21,165,66,52
+DB	156,156,74,156,148,214,37,8,156,156,74,156,148,214,37,8
+DB	30,30,120,30,240,102,60,238,30,30,120,30,240,102,60,238
+DB	67,67,17,67,34,82,134,97,67,67,17,67,34,82,134,97
+DB	199,199,59,199,118,252,147,177,199,199,59,199,118,252,147,177
+DB	252,252,215,252,179,43,229,79,252,252,215,252,179,43,229,79
+DB	4,4,16,4,32,20,8,36,4,4,16,4,32,20,8,36
+DB	81,81,89,81,178,8,162,227,81,81,89,81,178,8,162,227
+DB	153,153,94,153,188,199,47,37,153,153,94,153,188,199,47,37
+DB	109,109,169,109,79,196,218,34,109,109,169,109,79,196,218,34
+DB	13,13,52,13,104,57,26,101,13,13,52,13,104,57,26,101
+DB	250,250,207,250,131,53,233,121,250,250,207,250,131,53,233,121
+DB	223,223,91,223,182,132,163,105,223,223,91,223,182,132,163,105
+DB	126,126,229,126,215,155,252,169,126,126,229,126,215,155,252,169
+DB	36,36,144,36,61,180,72,25,36,36,144,36,61,180,72,25
+DB	59,59,236,59,197,215,118,254,59,59,236,59,197,215,118,254
+DB	171,171,150,171,49,61,75,154,171,171,150,171,49,61,75,154
+DB	206,206,31,206,62,209,129,240,206,206,31,206,62,209,129,240
+DB	17,17,68,17,136,85,34,153,17,17,68,17,136,85,34,153
+DB	143,143,6,143,12,137,3,131,143,143,6,143,12,137,3,131
+DB	78,78,37,78,74,107,156,4,78,78,37,78,74,107,156,4
+DB	183,183,230,183,209,81,115,102,183,183,230,183,209,81,115,102
+DB	235,235,139,235,11,96,203,224,235,235,139,235,11,96,203,224
+DB	60,60,240,60,253,204,120,193,60,60,240,60,253,204,120,193
+DB	129,129,62,129,124,191,31,253,129,129,62,129,124,191,31,253
+DB	148,148,106,148,212,254,53,64,148,148,106,148,212,254,53,64
+DB	247,247,251,247,235,12,243,28,247,247,251,247,235,12,243,28
+DB	185,185,222,185,161,103,111,24,185,185,222,185,161,103,111,24
+DB	19,19,76,19,152,95,38,139,19,19,76,19,152,95,38,139
+DB	44,44,176,44,125,156,88,81,44,44,176,44,125,156,88,81
+DB	211,211,107,211,214,184,187,5,211,211,107,211,214,184,187,5
+DB	231,231,187,231,107,92,211,140,231,231,187,231,107,92,211,140
+DB	110,110,165,110,87,203,220,57,110,110,165,110,87,203,220,57
+DB	196,196,55,196,110,243,149,170,196,196,55,196,110,243,149,170
+DB	3,3,12,3,24,15,6,27,3,3,12,3,24,15,6,27
+DB	86,86,69,86,138,19,172,220,86,86,69,86,138,19,172,220
+DB	68,68,13,68,26,73,136,94,68,68,13,68,26,73,136,94
+DB	127,127,225,127,223,158,254,160,127,127,225,127,223,158,254,160
+DB	169,169,158,169,33,55,79,136,169,169,158,169,33,55,79,136
+DB	42,42,168,42,77,130,84,103,42,42,168,42,77,130,84,103
+DB	187,187,214,187,177,109,107,10,187,187,214,187,177,109,107,10
+DB	193,193,35,193,70,226,159,135,193,193,35,193,70,226,159,135
+DB	83,83,81,83,162,2,166,241,83,83,81,83,162,2,166,241
+DB	220,220,87,220,174,139,165,114,220,220,87,220,174,139,165,114
+DB	11,11,44,11,88,39,22,83,11,11,44,11,88,39,22,83
+DB	157,157,78,157,156,211,39,1,157,157,78,157,156,211,39,1
+DB	108,108,173,108,71,193,216,43,108,108,173,108,71,193,216,43
+DB	49,49,196,49,149,245,98,164,49,49,196,49,149,245,98,164
+DB	116,116,205,116,135,185,232,243,116,116,205,116,135,185,232,243
+DB	246,246,255,246,227,9,241,21,246,246,255,246,227,9,241,21
+DB	70,70,5,70,10,67,140,76,70,70,5,70,10,67,140,76
+DB	172,172,138,172,9,38,69,165,172,172,138,172,9,38,69,165
+DB	137,137,30,137,60,151,15,181,137,137,30,137,60,151,15,181
+DB	20,20,80,20,160,68,40,180,20,20,80,20,160,68,40,180
+DB	225,225,163,225,91,66,223,186,225,225,163,225,91,66,223,186
+DB	22,22,88,22,176,78,44,166,22,22,88,22,176,78,44,166
+DB	58,58,232,58,205,210,116,247,58,58,232,58,205,210,116,247
+DB	105,105,185,105,111,208,210,6,105,105,185,105,111,208,210,6
+DB	9,9,36,9,72,45,18,65,9,9,36,9,72,45,18,65
+DB	112,112,221,112,167,173,224,215,112,112,221,112,167,173,224,215
+DB	182,182,226,182,217,84,113,111,182,182,226,182,217,84,113,111
+DB	208,208,103,208,206,183,189,30,208,208,103,208,206,183,189,30
+DB	237,237,147,237,59,126,199,214,237,237,147,237,59,126,199,214
+DB	204,204,23,204,46,219,133,226,204,204,23,204,46,219,133,226
+DB	66,66,21,66,42,87,132,104,66,66,21,66,42,87,132,104
+DB	152,152,90,152,180,194,45,44,152,152,90,152,180,194,45,44
+DB	164,164,170,164,73,14,85,237,164,164,170,164,73,14,85,237
+DB	40,40,160,40,93,136,80,117,40,40,160,40,93,136,80,117
+DB	92,92,109,92,218,49,184,134,92,92,109,92,218,49,184,134
+DB	248,248,199,248,147,63,237,107,248,248,199,248,147,63,237,107
+DB	134,134,34,134,68,164,17,194,134,134,34,134,68,164,17,194
+DB	24,35,198,232,135,184,1,79
+DB	54,166,210,245,121,111,145,82
+DB	96,188,155,142,163,12,123,53
+DB	29,224,215,194,46,75,254,87
+DB	21,119,55,229,159,240,74,218
+DB	88,201,41,10,177,160,107,133
+DB	189,93,16,244,203,62,5,103
+DB	228,39,65,139,167,125,149,216
+DB	251,238,124,102,221,23,71,158
+DB	202,45,191,7,173,90,131,51
+
+.text$	ENDS
+END
+
diff --git a/crypto/whrlpool/wp-mingw64-x86_64.S b/crypto/whrlpool/wp-mingw64-x86_64.S
new file mode 100644
index 0000000..ea9f6cf
--- /dev/null
+++ b/crypto/whrlpool/wp-mingw64-x86_64.S
@@ -0,0 +1,869 @@
+#include "x86_arch.h"
+.text	
+
+.globl	whirlpool_block
+.def	whirlpool_block;	.scl 2;	.type 32;	.endef
+.p2align	4
+whirlpool_block:
+	movq	%rdi,8(%rsp)
+	movq	%rsi,16(%rsp)
+	movq	%rsp,%rax
+.LSEH_begin_whirlpool_block:
+	movq	%rcx,%rdi
+	movq	%rdx,%rsi
+	movq	%r8,%rdx
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+
+	movq	%rsp,%r11
+	subq	$128+40,%rsp
+	andq	$-64,%rsp
+
+	leaq	128(%rsp),%r10
+	movq	%rdi,0(%r10)
+	movq	%rsi,8(%r10)
+	movq	%rdx,16(%r10)
+	movq	%r11,32(%r10)
+.Lprologue:
+
+	movq	%r10,%rbx
+	leaq	.Ltable(%rip),%rbp
+
+	xorq	%rcx,%rcx
+	xorq	%rdx,%rdx
+	movq	0(%rdi),%r8
+	movq	8(%rdi),%r9
+	movq	16(%rdi),%r10
+	movq	24(%rdi),%r11
+	movq	32(%rdi),%r12
+	movq	40(%rdi),%r13
+	movq	48(%rdi),%r14
+	movq	56(%rdi),%r15
+.Louterloop:
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	xorq	%rsi,%rsi
+	movq	%rsi,24(%rbx)
+.p2align	4
+.Lround:
+	movq	4096(%rbp,%rsi,8),%r8
+	movl	0(%rsp),%eax
+	movl	4(%rsp),%ebx
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	movq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	6(%rbp,%rsi,8),%r10
+	movq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	movq	4(%rbp,%rsi,8),%r12
+	movq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	movq	2(%rbp,%rsi,8),%r14
+	movq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	56+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	56+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	movq	%r8,0(%rsp)
+	movq	%r9,8(%rsp)
+	movq	%r10,16(%rsp)
+	movq	%r11,24(%rsp)
+	movq	%r12,32(%rsp)
+	movq	%r13,40(%rsp)
+	movq	%r14,48(%rsp)
+	movq	%r15,56(%rsp)
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r8
+	xorq	7(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+0+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r10
+	xorq	5(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r12
+	xorq	3(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+0+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r14
+	xorq	1(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r9
+	xorq	7(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+8+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r11
+	xorq	5(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r13
+	xorq	3(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+8+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r15
+	xorq	1(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r10
+	xorq	7(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+16+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r12
+	xorq	5(%rbp,%rdi,8),%r13
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r14
+	xorq	3(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+16+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r8
+	xorq	1(%rbp,%rdi,8),%r9
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r11
+	xorq	7(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+24+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r13
+	xorq	5(%rbp,%rdi,8),%r14
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r15
+	xorq	3(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+24+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r9
+	xorq	1(%rbp,%rdi,8),%r10
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r12
+	xorq	7(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+32+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r14
+	xorq	5(%rbp,%rdi,8),%r15
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r8
+	xorq	3(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+32+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r10
+	xorq	1(%rbp,%rdi,8),%r11
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r13
+	xorq	7(%rbp,%rdi,8),%r14
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+40+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r15
+	xorq	5(%rbp,%rdi,8),%r8
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r9
+	xorq	3(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+40+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r11
+	xorq	1(%rbp,%rdi,8),%r12
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r14
+	xorq	7(%rbp,%rdi,8),%r15
+	movb	%al,%cl
+	movb	%ah,%dl
+	movl	64+48+8(%rsp),%eax
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r8
+	xorq	5(%rbp,%rdi,8),%r9
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r10
+	xorq	3(%rbp,%rdi,8),%r11
+	movb	%bl,%cl
+	movb	%bh,%dl
+	movl	64+48+8+4(%rsp),%ebx
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r12
+	xorq	1(%rbp,%rdi,8),%r13
+	movb	%al,%cl
+	movb	%ah,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%eax
+	xorq	0(%rbp,%rsi,8),%r15
+	xorq	7(%rbp,%rdi,8),%r8
+	movb	%al,%cl
+	movb	%ah,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	6(%rbp,%rsi,8),%r9
+	xorq	5(%rbp,%rdi,8),%r10
+	movb	%bl,%cl
+	movb	%bh,%dl
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	shrl	$16,%ebx
+	xorq	4(%rbp,%rsi,8),%r11
+	xorq	3(%rbp,%rdi,8),%r12
+	movb	%bl,%cl
+	movb	%bh,%dl
+
+	leaq	(%rcx,%rcx,1),%rsi
+	leaq	(%rdx,%rdx,1),%rdi
+	xorq	2(%rbp,%rsi,8),%r13
+	xorq	1(%rbp,%rdi,8),%r14
+	leaq	128(%rsp),%rbx
+	movq	24(%rbx),%rsi
+	addq	$1,%rsi
+	cmpq	$10,%rsi
+	je	.Lroundsdone
+
+	movq	%rsi,24(%rbx)
+	movq	%r8,64+0(%rsp)
+	movq	%r9,64+8(%rsp)
+	movq	%r10,64+16(%rsp)
+	movq	%r11,64+24(%rsp)
+	movq	%r12,64+32(%rsp)
+	movq	%r13,64+40(%rsp)
+	movq	%r14,64+48(%rsp)
+	movq	%r15,64+56(%rsp)
+	jmp	.Lround
+.p2align	4
+.Lroundsdone:
+	movq	0(%rbx),%rdi
+	movq	8(%rbx),%rsi
+	movq	16(%rbx),%rax
+	xorq	0(%rsi),%r8
+	xorq	8(%rsi),%r9
+	xorq	16(%rsi),%r10
+	xorq	24(%rsi),%r11
+	xorq	32(%rsi),%r12
+	xorq	40(%rsi),%r13
+	xorq	48(%rsi),%r14
+	xorq	56(%rsi),%r15
+	xorq	0(%rdi),%r8
+	xorq	8(%rdi),%r9
+	xorq	16(%rdi),%r10
+	xorq	24(%rdi),%r11
+	xorq	32(%rdi),%r12
+	xorq	40(%rdi),%r13
+	xorq	48(%rdi),%r14
+	xorq	56(%rdi),%r15
+	movq	%r8,0(%rdi)
+	movq	%r9,8(%rdi)
+	movq	%r10,16(%rdi)
+	movq	%r11,24(%rdi)
+	movq	%r12,32(%rdi)
+	movq	%r13,40(%rdi)
+	movq	%r14,48(%rdi)
+	movq	%r15,56(%rdi)
+	leaq	64(%rsi),%rsi
+	subq	$1,%rax
+	jz	.Lalldone
+	movq	%rsi,8(%rbx)
+	movq	%rax,16(%rbx)
+	jmp	.Louterloop
+.Lalldone:
+	movq	32(%rbx),%rsi
+	movq	(%rsi),%r15
+	movq	8(%rsi),%r14
+	movq	16(%rsi),%r13
+	movq	24(%rsi),%r12
+	movq	32(%rsi),%rbp
+	movq	40(%rsi),%rbx
+	leaq	48(%rsi),%rsp
+.Lepilogue:
+	movq	8(%rsp),%rdi
+	movq	16(%rsp),%rsi
+	retq
+.LSEH_end_whirlpool_block:
+
+.p2align	6
+
+.Ltable:
+.byte	24,24,96,24,192,120,48,216,24,24,96,24,192,120,48,216
+.byte	35,35,140,35,5,175,70,38,35,35,140,35,5,175,70,38
+.byte	198,198,63,198,126,249,145,184,198,198,63,198,126,249,145,184
+.byte	232,232,135,232,19,111,205,251,232,232,135,232,19,111,205,251
+.byte	135,135,38,135,76,161,19,203,135,135,38,135,76,161,19,203
+.byte	184,184,218,184,169,98,109,17,184,184,218,184,169,98,109,17
+.byte	1,1,4,1,8,5,2,9,1,1,4,1,8,5,2,9
+.byte	79,79,33,79,66,110,158,13,79,79,33,79,66,110,158,13
+.byte	54,54,216,54,173,238,108,155,54,54,216,54,173,238,108,155
+.byte	166,166,162,166,89,4,81,255,166,166,162,166,89,4,81,255
+.byte	210,210,111,210,222,189,185,12,210,210,111,210,222,189,185,12
+.byte	245,245,243,245,251,6,247,14,245,245,243,245,251,6,247,14
+.byte	121,121,249,121,239,128,242,150,121,121,249,121,239,128,242,150
+.byte	111,111,161,111,95,206,222,48,111,111,161,111,95,206,222,48
+.byte	145,145,126,145,252,239,63,109,145,145,126,145,252,239,63,109
+.byte	82,82,85,82,170,7,164,248,82,82,85,82,170,7,164,248
+.byte	96,96,157,96,39,253,192,71,96,96,157,96,39,253,192,71
+.byte	188,188,202,188,137,118,101,53,188,188,202,188,137,118,101,53
+.byte	155,155,86,155,172,205,43,55,155,155,86,155,172,205,43,55
+.byte	142,142,2,142,4,140,1,138,142,142,2,142,4,140,1,138
+.byte	163,163,182,163,113,21,91,210,163,163,182,163,113,21,91,210
+.byte	12,12,48,12,96,60,24,108,12,12,48,12,96,60,24,108
+.byte	123,123,241,123,255,138,246,132,123,123,241,123,255,138,246,132
+.byte	53,53,212,53,181,225,106,128,53,53,212,53,181,225,106,128
+.byte	29,29,116,29,232,105,58,245,29,29,116,29,232,105,58,245
+.byte	224,224,167,224,83,71,221,179,224,224,167,224,83,71,221,179
+.byte	215,215,123,215,246,172,179,33,215,215,123,215,246,172,179,33
+.byte	194,194,47,194,94,237,153,156,194,194,47,194,94,237,153,156
+.byte	46,46,184,46,109,150,92,67,46,46,184,46,109,150,92,67
+.byte	75,75,49,75,98,122,150,41,75,75,49,75,98,122,150,41
+.byte	254,254,223,254,163,33,225,93,254,254,223,254,163,33,225,93
+.byte	87,87,65,87,130,22,174,213,87,87,65,87,130,22,174,213
+.byte	21,21,84,21,168,65,42,189,21,21,84,21,168,65,42,189
+.byte	119,119,193,119,159,182,238,232,119,119,193,119,159,182,238,232
+.byte	55,55,220,55,165,235,110,146,55,55,220,55,165,235,110,146
+.byte	229,229,179,229,123,86,215,158,229,229,179,229,123,86,215,158
+.byte	159,159,70,159,140,217,35,19,159,159,70,159,140,217,35,19
+.byte	240,240,231,240,211,23,253,35,240,240,231,240,211,23,253,35
+.byte	74,74,53,74,106,127,148,32,74,74,53,74,106,127,148,32
+.byte	218,218,79,218,158,149,169,68,218,218,79,218,158,149,169,68
+.byte	88,88,125,88,250,37,176,162,88,88,125,88,250,37,176,162
+.byte	201,201,3,201,6,202,143,207,201,201,3,201,6,202,143,207
+.byte	41,41,164,41,85,141,82,124,41,41,164,41,85,141,82,124
+.byte	10,10,40,10,80,34,20,90,10,10,40,10,80,34,20,90
+.byte	177,177,254,177,225,79,127,80,177,177,254,177,225,79,127,80
+.byte	160,160,186,160,105,26,93,201,160,160,186,160,105,26,93,201
+.byte	107,107,177,107,127,218,214,20,107,107,177,107,127,218,214,20
+.byte	133,133,46,133,92,171,23,217,133,133,46,133,92,171,23,217
+.byte	189,189,206,189,129,115,103,60,189,189,206,189,129,115,103,60
+.byte	93,93,105,93,210,52,186,143,93,93,105,93,210,52,186,143
+.byte	16,16,64,16,128,80,32,144,16,16,64,16,128,80,32,144
+.byte	244,244,247,244,243,3,245,7,244,244,247,244,243,3,245,7
+.byte	203,203,11,203,22,192,139,221,203,203,11,203,22,192,139,221
+.byte	62,62,248,62,237,198,124,211,62,62,248,62,237,198,124,211
+.byte	5,5,20,5,40,17,10,45,5,5,20,5,40,17,10,45
+.byte	103,103,129,103,31,230,206,120,103,103,129,103,31,230,206,120
+.byte	228,228,183,228,115,83,213,151,228,228,183,228,115,83,213,151
+.byte	39,39,156,39,37,187,78,2,39,39,156,39,37,187,78,2
+.byte	65,65,25,65,50,88,130,115,65,65,25,65,50,88,130,115
+.byte	139,139,22,139,44,157,11,167,139,139,22,139,44,157,11,167
+.byte	167,167,166,167,81,1,83,246,167,167,166,167,81,1,83,246
+.byte	125,125,233,125,207,148,250,178,125,125,233,125,207,148,250,178
+.byte	149,149,110,149,220,251,55,73,149,149,110,149,220,251,55,73
+.byte	216,216,71,216,142,159,173,86,216,216,71,216,142,159,173,86
+.byte	251,251,203,251,139,48,235,112,251,251,203,251,139,48,235,112
+.byte	238,238,159,238,35,113,193,205,238,238,159,238,35,113,193,205
+.byte	124,124,237,124,199,145,248,187,124,124,237,124,199,145,248,187
+.byte	102,102,133,102,23,227,204,113,102,102,133,102,23,227,204,113
+.byte	221,221,83,221,166,142,167,123,221,221,83,221,166,142,167,123
+.byte	23,23,92,23,184,75,46,175,23,23,92,23,184,75,46,175
+.byte	71,71,1,71,2,70,142,69,71,71,1,71,2,70,142,69
+.byte	158,158,66,158,132,220,33,26,158,158,66,158,132,220,33,26
+.byte	202,202,15,202,30,197,137,212,202,202,15,202,30,197,137,212
+.byte	45,45,180,45,117,153,90,88,45,45,180,45,117,153,90,88
+.byte	191,191,198,191,145,121,99,46,191,191,198,191,145,121,99,46
+.byte	7,7,28,7,56,27,14,63,7,7,28,7,56,27,14,63
+.byte	173,173,142,173,1,35,71,172,173,173,142,173,1,35,71,172
+.byte	90,90,117,90,234,47,180,176,90,90,117,90,234,47,180,176
+.byte	131,131,54,131,108,181,27,239,131,131,54,131,108,181,27,239
+.byte	51,51,204,51,133,255,102,182,51,51,204,51,133,255,102,182
+.byte	99,99,145,99,63,242,198,92,99,99,145,99,63,242,198,92
+.byte	2,2,8,2,16,10,4,18,2,2,8,2,16,10,4,18
+.byte	170,170,146,170,57,56,73,147,170,170,146,170,57,56,73,147
+.byte	113,113,217,113,175,168,226,222,113,113,217,113,175,168,226,222
+.byte	200,200,7,200,14,207,141,198,200,200,7,200,14,207,141,198
+.byte	25,25,100,25,200,125,50,209,25,25,100,25,200,125,50,209
+.byte	73,73,57,73,114,112,146,59,73,73,57,73,114,112,146,59
+.byte	217,217,67,217,134,154,175,95,217,217,67,217,134,154,175,95
+.byte	242,242,239,242,195,29,249,49,242,242,239,242,195,29,249,49
+.byte	227,227,171,227,75,72,219,168,227,227,171,227,75,72,219,168
+.byte	91,91,113,91,226,42,182,185,91,91,113,91,226,42,182,185
+.byte	136,136,26,136,52,146,13,188,136,136,26,136,52,146,13,188
+.byte	154,154,82,154,164,200,41,62,154,154,82,154,164,200,41,62
+.byte	38,38,152,38,45,190,76,11,38,38,152,38,45,190,76,11
+.byte	50,50,200,50,141,250,100,191,50,50,200,50,141,250,100,191
+.byte	176,176,250,176,233,74,125,89,176,176,250,176,233,74,125,89
+.byte	233,233,131,233,27,106,207,242,233,233,131,233,27,106,207,242
+.byte	15,15,60,15,120,51,30,119,15,15,60,15,120,51,30,119
+.byte	213,213,115,213,230,166,183,51,213,213,115,213,230,166,183,51
+.byte	128,128,58,128,116,186,29,244,128,128,58,128,116,186,29,244
+.byte	190,190,194,190,153,124,97,39,190,190,194,190,153,124,97,39
+.byte	205,205,19,205,38,222,135,235,205,205,19,205,38,222,135,235
+.byte	52,52,208,52,189,228,104,137,52,52,208,52,189,228,104,137
+.byte	72,72,61,72,122,117,144,50,72,72,61,72,122,117,144,50
+.byte	255,255,219,255,171,36,227,84,255,255,219,255,171,36,227,84
+.byte	122,122,245,122,247,143,244,141,122,122,245,122,247,143,244,141
+.byte	144,144,122,144,244,234,61,100,144,144,122,144,244,234,61,100
+.byte	95,95,97,95,194,62,190,157,95,95,97,95,194,62,190,157
+.byte	32,32,128,32,29,160,64,61,32,32,128,32,29,160,64,61
+.byte	104,104,189,104,103,213,208,15,104,104,189,104,103,213,208,15
+.byte	26,26,104,26,208,114,52,202,26,26,104,26,208,114,52,202
+.byte	174,174,130,174,25,44,65,183,174,174,130,174,25,44,65,183
+.byte	180,180,234,180,201,94,117,125,180,180,234,180,201,94,117,125
+.byte	84,84,77,84,154,25,168,206,84,84,77,84,154,25,168,206
+.byte	147,147,118,147,236,229,59,127,147,147,118,147,236,229,59,127
+.byte	34,34,136,34,13,170,68,47,34,34,136,34,13,170,68,47
+.byte	100,100,141,100,7,233,200,99,100,100,141,100,7,233,200,99
+.byte	241,241,227,241,219,18,255,42,241,241,227,241,219,18,255,42
+.byte	115,115,209,115,191,162,230,204,115,115,209,115,191,162,230,204
+.byte	18,18,72,18,144,90,36,130,18,18,72,18,144,90,36,130
+.byte	64,64,29,64,58,93,128,122,64,64,29,64,58,93,128,122
+.byte	8,8,32,8,64,40,16,72,8,8,32,8,64,40,16,72
+.byte	195,195,43,195,86,232,155,149,195,195,43,195,86,232,155,149
+.byte	236,236,151,236,51,123,197,223,236,236,151,236,51,123,197,223
+.byte	219,219,75,219,150,144,171,77,219,219,75,219,150,144,171,77
+.byte	161,161,190,161,97,31,95,192,161,161,190,161,97,31,95,192
+.byte	141,141,14,141,28,131,7,145,141,141,14,141,28,131,7,145
+.byte	61,61,244,61,245,201,122,200,61,61,244,61,245,201,122,200
+.byte	151,151,102,151,204,241,51,91,151,151,102,151,204,241,51,91
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.byte	207,207,27,207,54,212,131,249,207,207,27,207,54,212,131,249
+.byte	43,43,172,43,69,135,86,110,43,43,172,43,69,135,86,110
+.byte	118,118,197,118,151,179,236,225,118,118,197,118,151,179,236,225
+.byte	130,130,50,130,100,176,25,230,130,130,50,130,100,176,25,230
+.byte	214,214,127,214,254,169,177,40,214,214,127,214,254,169,177,40
+.byte	27,27,108,27,216,119,54,195,27,27,108,27,216,119,54,195
+.byte	181,181,238,181,193,91,119,116,181,181,238,181,193,91,119,116
+.byte	175,175,134,175,17,41,67,190,175,175,134,175,17,41,67,190
+.byte	106,106,181,106,119,223,212,29,106,106,181,106,119,223,212,29
+.byte	80,80,93,80,186,13,160,234,80,80,93,80,186,13,160,234
+.byte	69,69,9,69,18,76,138,87,69,69,9,69,18,76,138,87
+.byte	243,243,235,243,203,24,251,56,243,243,235,243,203,24,251,56
+.byte	48,48,192,48,157,240,96,173,48,48,192,48,157,240,96,173
+.byte	239,239,155,239,43,116,195,196,239,239,155,239,43,116,195,196
+.byte	63,63,252,63,229,195,126,218,63,63,252,63,229,195,126,218
+.byte	85,85,73,85,146,28,170,199,85,85,73,85,146,28,170,199
+.byte	162,162,178,162,121,16,89,219,162,162,178,162,121,16,89,219
+.byte	234,234,143,234,3,101,201,233,234,234,143,234,3,101,201,233
+.byte	101,101,137,101,15,236,202,106,101,101,137,101,15,236,202,106
+.byte	186,186,210,186,185,104,105,3,186,186,210,186,185,104,105,3
+.byte	47,47,188,47,101,147,94,74,47,47,188,47,101,147,94,74
+.byte	192,192,39,192,78,231,157,142,192,192,39,192,78,231,157,142
+.byte	222,222,95,222,190,129,161,96,222,222,95,222,190,129,161,96
+.byte	28,28,112,28,224,108,56,252,28,28,112,28,224,108,56,252
+.byte	253,253,211,253,187,46,231,70,253,253,211,253,187,46,231,70
+.byte	77,77,41,77,82,100,154,31,77,77,41,77,82,100,154,31
+.byte	146,146,114,146,228,224,57,118,146,146,114,146,228,224,57,118
+.byte	117,117,201,117,143,188,234,250,117,117,201,117,143,188,234,250
+.byte	6,6,24,6,48,30,12,54,6,6,24,6,48,30,12,54
+.byte	138,138,18,138,36,152,9,174,138,138,18,138,36,152,9,174
+.byte	178,178,242,178,249,64,121,75,178,178,242,178,249,64,121,75
+.byte	230,230,191,230,99,89,209,133,230,230,191,230,99,89,209,133
+.byte	14,14,56,14,112,54,28,126,14,14,56,14,112,54,28,126
+.byte	31,31,124,31,248,99,62,231,31,31,124,31,248,99,62,231
+.byte	98,98,149,98,55,247,196,85,98,98,149,98,55,247,196,85
+.byte	212,212,119,212,238,163,181,58,212,212,119,212,238,163,181,58
+.byte	168,168,154,168,41,50,77,129,168,168,154,168,41,50,77,129
+.byte	150,150,98,150,196,244,49,82,150,150,98,150,196,244,49,82
+.byte	249,249,195,249,155,58,239,98,249,249,195,249,155,58,239,98
+.byte	197,197,51,197,102,246,151,163,197,197,51,197,102,246,151,163
+.byte	37,37,148,37,53,177,74,16,37,37,148,37,53,177,74,16
+.byte	89,89,121,89,242,32,178,171,89,89,121,89,242,32,178,171
+.byte	132,132,42,132,84,174,21,208,132,132,42,132,84,174,21,208
+.byte	114,114,213,114,183,167,228,197,114,114,213,114,183,167,228,197
+.byte	57,57,228,57,213,221,114,236,57,57,228,57,213,221,114,236
+.byte	76,76,45,76,90,97,152,22,76,76,45,76,90,97,152,22
+.byte	94,94,101,94,202,59,188,148,94,94,101,94,202,59,188,148
+.byte	120,120,253,120,231,133,240,159,120,120,253,120,231,133,240,159
+.byte	56,56,224,56,221,216,112,229,56,56,224,56,221,216,112,229
+.byte	140,140,10,140,20,134,5,152,140,140,10,140,20,134,5,152
+.byte	209,209,99,209,198,178,191,23,209,209,99,209,198,178,191,23
+.byte	165,165,174,165,65,11,87,228,165,165,174,165,65,11,87,228
+.byte	226,226,175,226,67,77,217,161,226,226,175,226,67,77,217,161
+.byte	97,97,153,97,47,248,194,78,97,97,153,97,47,248,194,78
+.byte	179,179,246,179,241,69,123,66,179,179,246,179,241,69,123,66
+.byte	33,33,132,33,21,165,66,52,33,33,132,33,21,165,66,52
+.byte	156,156,74,156,148,214,37,8,156,156,74,156,148,214,37,8
+.byte	30,30,120,30,240,102,60,238,30,30,120,30,240,102,60,238
+.byte	67,67,17,67,34,82,134,97,67,67,17,67,34,82,134,97
+.byte	199,199,59,199,118,252,147,177,199,199,59,199,118,252,147,177
+.byte	252,252,215,252,179,43,229,79,252,252,215,252,179,43,229,79
+.byte	4,4,16,4,32,20,8,36,4,4,16,4,32,20,8,36
+.byte	81,81,89,81,178,8,162,227,81,81,89,81,178,8,162,227
+.byte	153,153,94,153,188,199,47,37,153,153,94,153,188,199,47,37
+.byte	109,109,169,109,79,196,218,34,109,109,169,109,79,196,218,34
+.byte	13,13,52,13,104,57,26,101,13,13,52,13,104,57,26,101
+.byte	250,250,207,250,131,53,233,121,250,250,207,250,131,53,233,121
+.byte	223,223,91,223,182,132,163,105,223,223,91,223,182,132,163,105
+.byte	126,126,229,126,215,155,252,169,126,126,229,126,215,155,252,169
+.byte	36,36,144,36,61,180,72,25,36,36,144,36,61,180,72,25
+.byte	59,59,236,59,197,215,118,254,59,59,236,59,197,215,118,254
+.byte	171,171,150,171,49,61,75,154,171,171,150,171,49,61,75,154
+.byte	206,206,31,206,62,209,129,240,206,206,31,206,62,209,129,240
+.byte	17,17,68,17,136,85,34,153,17,17,68,17,136,85,34,153
+.byte	143,143,6,143,12,137,3,131,143,143,6,143,12,137,3,131
+.byte	78,78,37,78,74,107,156,4,78,78,37,78,74,107,156,4
+.byte	183,183,230,183,209,81,115,102,183,183,230,183,209,81,115,102
+.byte	235,235,139,235,11,96,203,224,235,235,139,235,11,96,203,224
+.byte	60,60,240,60,253,204,120,193,60,60,240,60,253,204,120,193
+.byte	129,129,62,129,124,191,31,253,129,129,62,129,124,191,31,253
+.byte	148,148,106,148,212,254,53,64,148,148,106,148,212,254,53,64
+.byte	247,247,251,247,235,12,243,28,247,247,251,247,235,12,243,28
+.byte	185,185,222,185,161,103,111,24,185,185,222,185,161,103,111,24
+.byte	19,19,76,19,152,95,38,139,19,19,76,19,152,95,38,139
+.byte	44,44,176,44,125,156,88,81,44,44,176,44,125,156,88,81
+.byte	211,211,107,211,214,184,187,5,211,211,107,211,214,184,187,5
+.byte	231,231,187,231,107,92,211,140,231,231,187,231,107,92,211,140
+.byte	110,110,165,110,87,203,220,57,110,110,165,110,87,203,220,57
+.byte	196,196,55,196,110,243,149,170,196,196,55,196,110,243,149,170
+.byte	3,3,12,3,24,15,6,27,3,3,12,3,24,15,6,27
+.byte	86,86,69,86,138,19,172,220,86,86,69,86,138,19,172,220
+.byte	68,68,13,68,26,73,136,94,68,68,13,68,26,73,136,94
+.byte	127,127,225,127,223,158,254,160,127,127,225,127,223,158,254,160
+.byte	169,169,158,169,33,55,79,136,169,169,158,169,33,55,79,136
+.byte	42,42,168,42,77,130,84,103,42,42,168,42,77,130,84,103
+.byte	187,187,214,187,177,109,107,10,187,187,214,187,177,109,107,10
+.byte	193,193,35,193,70,226,159,135,193,193,35,193,70,226,159,135
+.byte	83,83,81,83,162,2,166,241,83,83,81,83,162,2,166,241
+.byte	220,220,87,220,174,139,165,114,220,220,87,220,174,139,165,114
+.byte	11,11,44,11,88,39,22,83,11,11,44,11,88,39,22,83
+.byte	157,157,78,157,156,211,39,1,157,157,78,157,156,211,39,1
+.byte	108,108,173,108,71,193,216,43,108,108,173,108,71,193,216,43
+.byte	49,49,196,49,149,245,98,164,49,49,196,49,149,245,98,164
+.byte	116,116,205,116,135,185,232,243,116,116,205,116,135,185,232,243
+.byte	246,246,255,246,227,9,241,21,246,246,255,246,227,9,241,21
+.byte	70,70,5,70,10,67,140,76,70,70,5,70,10,67,140,76
+.byte	172,172,138,172,9,38,69,165,172,172,138,172,9,38,69,165
+.byte	137,137,30,137,60,151,15,181,137,137,30,137,60,151,15,181
+.byte	20,20,80,20,160,68,40,180,20,20,80,20,160,68,40,180
+.byte	225,225,163,225,91,66,223,186,225,225,163,225,91,66,223,186
+.byte	22,22,88,22,176,78,44,166,22,22,88,22,176,78,44,166
+.byte	58,58,232,58,205,210,116,247,58,58,232,58,205,210,116,247
+.byte	105,105,185,105,111,208,210,6,105,105,185,105,111,208,210,6
+.byte	9,9,36,9,72,45,18,65,9,9,36,9,72,45,18,65
+.byte	112,112,221,112,167,173,224,215,112,112,221,112,167,173,224,215
+.byte	182,182,226,182,217,84,113,111,182,182,226,182,217,84,113,111
+.byte	208,208,103,208,206,183,189,30,208,208,103,208,206,183,189,30
+.byte	237,237,147,237,59,126,199,214,237,237,147,237,59,126,199,214
+.byte	204,204,23,204,46,219,133,226,204,204,23,204,46,219,133,226
+.byte	66,66,21,66,42,87,132,104,66,66,21,66,42,87,132,104
+.byte	152,152,90,152,180,194,45,44,152,152,90,152,180,194,45,44
+.byte	164,164,170,164,73,14,85,237,164,164,170,164,73,14,85,237
+.byte	40,40,160,40,93,136,80,117,40,40,160,40,93,136,80,117
+.byte	92,92,109,92,218,49,184,134,92,92,109,92,218,49,184,134
+.byte	248,248,199,248,147,63,237,107,248,248,199,248,147,63,237,107
+.byte	134,134,34,134,68,164,17,194,134,134,34,134,68,164,17,194
+.byte	24,35,198,232,135,184,1,79
+.byte	54,166,210,245,121,111,145,82
+.byte	96,188,155,142,163,12,123,53
+.byte	29,224,215,194,46,75,254,87
+.byte	21,119,55,229,159,240,74,218
+.byte	88,201,41,10,177,160,107,133
+.byte	189,93,16,244,203,62,5,103
+.byte	228,39,65,139,167,125,149,216
+.byte	251,238,124,102,221,23,71,158
+.byte	202,45,191,7,173,90,131,51
diff --git a/crypto/whrlpool/wp_block.c b/crypto/whrlpool/wp_block.c
new file mode 100644
index 0000000..ad814a3
--- /dev/null
+++ b/crypto/whrlpool/wp_block.c
@@ -0,0 +1,629 @@
+/* $OpenBSD: wp_block.c,v 1.15 2022/11/26 16:08:54 tb Exp $ */
+/**
+ * The Whirlpool hashing function.
+ *
+ * 

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and + * Vincent Rijmen. Lookup "reference implementations" on + * + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 +#include +#include + +#include "wp_local.h" + +typedef unsigned char u8; +#if defined(_LP64) +typedef unsigned long u64; +#else +typedef unsigned long long u64; +#endif + +#define ROUNDS 10 + +#undef SMALL_REGISTER_BANK +#if defined(__i386) || defined(__i386__) || defined(_M_IX86) +# define SMALL_REGISTER_BANK +# if defined(WHIRLPOOL_ASM) +# ifndef OPENSSL_SMALL_FOOTPRINT +# define OPENSSL_SMALL_FOOTPRINT /* it appears that for elder non-MMX + CPUs this is actually faster! */ +# endif +#include "x86_arch.h" +# define GO_FOR_MMX(ctx,inp,num) \ +do { \ + void whirlpool_block_mmx(void *,const void *,size_t); \ + if ((OPENSSL_cpu_caps() & CPUCAP_MASK_MMX) == 0) \ + break; \ + whirlpool_block_mmx(ctx->H.c,inp,num); \ + return; \ +} while (0) +# endif +#elif defined(__arm__) +# define SMALL_REGISTER_BANK +#endif + +#undef ROTATE +#if defined(__GNUC__) && __GNUC__>=2 +# if defined(__x86_64) || defined(__x86_64__) +# define ROTATE(a,n) ({ u64 ret; asm ("rolq %1,%0" \ + : "=r"(ret) : "J"(n),"0"(a) : "cc"); ret; }) +# endif +#endif + +#if defined(OPENSSL_SMALL_FOOTPRINT) +# if !defined(ROTATE) +# if BYTE_ORDER == LITTLE_ENDIAN /* little-endians have to rotate left */ +# define ROTATE(i,n) ((i)<<(n) ^ (i)>>(64-n)) +# else /* big-endians have to rotate right */ +# define ROTATE(i,n) ((i)>>(n) ^ (i)<<(64-n)) +# endif +# endif +# if defined(ROTATE) && !defined(__STRICT_ALIGNMENT) +# define __STRICT_ALIGNMENT /* ensure smallest table size */ +# endif +#endif + +/* + * Table size depends on __STRICT_ALIGNMENT and whether or not endian- + * specific ROTATE macro is defined. If __STRICT_ALIGNMENT is not + * defined, which is normally the case on x86[_64] CPUs, the table is + * 4KB large unconditionally. Otherwise if ROTATE is defined, the + * table is 2KB large, and otherwise - 16KB. 2KB table requires a + * whole bunch of additional rotations, but I'm willing to "trade," + * because 16KB table certainly trashes L1 cache. I wish all CPUs + * could handle unaligned load as 4KB table doesn't trash the cache, + * nor does it require additional rotations. + */ +/* + * 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 + * 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 + * values in the register bank and issue a bunch of shifts and mask. + * It's a tradeoff: loads vs. shift and mask in big register bank[!]. + * On most CPUs eight single-byte loads are faster and I let other + * ones to depend on smart compiler to fold byte loads if beneficial. + * Hand-coded assembler would be another alternative:-) + */ +#ifdef __STRICT_ALIGNMENT +# if defined(ROTATE) +# define N 1 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7 +# define C0(K,i) (Cx.q[K.c[(i)*8+0]]) +# define C1(K,i) ROTATE(Cx.q[K.c[(i)*8+1]],8) +# define C2(K,i) ROTATE(Cx.q[K.c[(i)*8+2]],16) +# define C3(K,i) ROTATE(Cx.q[K.c[(i)*8+3]],24) +# define C4(K,i) ROTATE(Cx.q[K.c[(i)*8+4]],32) +# define C5(K,i) ROTATE(Cx.q[K.c[(i)*8+5]],40) +# define C6(K,i) ROTATE(Cx.q[K.c[(i)*8+6]],48) +# define C7(K,i) ROTATE(Cx.q[K.c[(i)*8+7]],56) +# else +# define N 8 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7, \ + c7,c0,c1,c2,c3,c4,c5,c6, \ + c6,c7,c0,c1,c2,c3,c4,c5, \ + c5,c6,c7,c0,c1,c2,c3,c4, \ + c4,c5,c6,c7,c0,c1,c2,c3, \ + c3,c4,c5,c6,c7,c0,c1,c2, \ + c2,c3,c4,c5,c6,c7,c0,c1, \ + c1,c2,c3,c4,c5,c6,c7,c0 +# define C0(K,i) (Cx.q[0+8*K.c[(i)*8+0]]) +# define C1(K,i) (Cx.q[1+8*K.c[(i)*8+1]]) +# define C2(K,i) (Cx.q[2+8*K.c[(i)*8+2]]) +# define C3(K,i) (Cx.q[3+8*K.c[(i)*8+3]]) +# define C4(K,i) (Cx.q[4+8*K.c[(i)*8+4]]) +# define C5(K,i) (Cx.q[5+8*K.c[(i)*8+5]]) +# define C6(K,i) (Cx.q[6+8*K.c[(i)*8+6]]) +# define C7(K,i) (Cx.q[7+8*K.c[(i)*8+7]]) +# endif +#else +# define N 2 +# define LL(c0,c1,c2,c3,c4,c5,c6,c7) c0,c1,c2,c3,c4,c5,c6,c7, \ + c0,c1,c2,c3,c4,c5,c6,c7 +# define C0(K,i) (((u64*)(Cx.c+0))[2*K.c[(i)*8+0]]) +# define C1(K,i) (((u64*)(Cx.c+7))[2*K.c[(i)*8+1]]) +# define C2(K,i) (((u64*)(Cx.c+6))[2*K.c[(i)*8+2]]) +# define C3(K,i) (((u64*)(Cx.c+5))[2*K.c[(i)*8+3]]) +# define C4(K,i) (((u64*)(Cx.c+4))[2*K.c[(i)*8+4]]) +# define C5(K,i) (((u64*)(Cx.c+3))[2*K.c[(i)*8+5]]) +# define C6(K,i) (((u64*)(Cx.c+2))[2*K.c[(i)*8+6]]) +# define C7(K,i) (((u64*)(Cx.c+1))[2*K.c[(i)*8+7]]) +#endif + +static const +union { + u8 c[(256*N+ROUNDS)*sizeof(u64)]; + u64 q[(256*N+ROUNDS)]; + } Cx = { { + /* Note endian-neutral representation:-) */ + LL(0x18,0x18,0x60,0x18,0xc0,0x78,0x30,0xd8), + LL(0x23,0x23,0x8c,0x23,0x05,0xaf,0x46,0x26), + LL(0xc6,0xc6,0x3f,0xc6,0x7e,0xf9,0x91,0xb8), + LL(0xe8,0xe8,0x87,0xe8,0x13,0x6f,0xcd,0xfb), + LL(0x87,0x87,0x26,0x87,0x4c,0xa1,0x13,0xcb), + LL(0xb8,0xb8,0xda,0xb8,0xa9,0x62,0x6d,0x11), + LL(0x01,0x01,0x04,0x01,0x08,0x05,0x02,0x09), + LL(0x4f,0x4f,0x21,0x4f,0x42,0x6e,0x9e,0x0d), + LL(0x36,0x36,0xd8,0x36,0xad,0xee,0x6c,0x9b), + LL(0xa6,0xa6,0xa2,0xa6,0x59,0x04,0x51,0xff), + LL(0xd2,0xd2,0x6f,0xd2,0xde,0xbd,0xb9,0x0c), + LL(0xf5,0xf5,0xf3,0xf5,0xfb,0x06,0xf7,0x0e), + LL(0x79,0x79,0xf9,0x79,0xef,0x80,0xf2,0x96), + LL(0x6f,0x6f,0xa1,0x6f,0x5f,0xce,0xde,0x30), + LL(0x91,0x91,0x7e,0x91,0xfc,0xef,0x3f,0x6d), + LL(0x52,0x52,0x55,0x52,0xaa,0x07,0xa4,0xf8), + LL(0x60,0x60,0x9d,0x60,0x27,0xfd,0xc0,0x47), + LL(0xbc,0xbc,0xca,0xbc,0x89,0x76,0x65,0x35), + LL(0x9b,0x9b,0x56,0x9b,0xac,0xcd,0x2b,0x37), + LL(0x8e,0x8e,0x02,0x8e,0x04,0x8c,0x01,0x8a), + LL(0xa3,0xa3,0xb6,0xa3,0x71,0x15,0x5b,0xd2), + LL(0x0c,0x0c,0x30,0x0c,0x60,0x3c,0x18,0x6c), + LL(0x7b,0x7b,0xf1,0x7b,0xff,0x8a,0xf6,0x84), + LL(0x35,0x35,0xd4,0x35,0xb5,0xe1,0x6a,0x80), + LL(0x1d,0x1d,0x74,0x1d,0xe8,0x69,0x3a,0xf5), + LL(0xe0,0xe0,0xa7,0xe0,0x53,0x47,0xdd,0xb3), + LL(0xd7,0xd7,0x7b,0xd7,0xf6,0xac,0xb3,0x21), + LL(0xc2,0xc2,0x2f,0xc2,0x5e,0xed,0x99,0x9c), + LL(0x2e,0x2e,0xb8,0x2e,0x6d,0x96,0x5c,0x43), + LL(0x4b,0x4b,0x31,0x4b,0x62,0x7a,0x96,0x29), + LL(0xfe,0xfe,0xdf,0xfe,0xa3,0x21,0xe1,0x5d), + LL(0x57,0x57,0x41,0x57,0x82,0x16,0xae,0xd5), + LL(0x15,0x15,0x54,0x15,0xa8,0x41,0x2a,0xbd), + LL(0x77,0x77,0xc1,0x77,0x9f,0xb6,0xee,0xe8), + LL(0x37,0x37,0xdc,0x37,0xa5,0xeb,0x6e,0x92), + LL(0xe5,0xe5,0xb3,0xe5,0x7b,0x56,0xd7,0x9e), + LL(0x9f,0x9f,0x46,0x9f,0x8c,0xd9,0x23,0x13), + LL(0xf0,0xf0,0xe7,0xf0,0xd3,0x17,0xfd,0x23), + LL(0x4a,0x4a,0x35,0x4a,0x6a,0x7f,0x94,0x20), + LL(0xda,0xda,0x4f,0xda,0x9e,0x95,0xa9,0x44), + LL(0x58,0x58,0x7d,0x58,0xfa,0x25,0xb0,0xa2), + LL(0xc9,0xc9,0x03,0xc9,0x06,0xca,0x8f,0xcf), + LL(0x29,0x29,0xa4,0x29,0x55,0x8d,0x52,0x7c), + LL(0x0a,0x0a,0x28,0x0a,0x50,0x22,0x14,0x5a), + LL(0xb1,0xb1,0xfe,0xb1,0xe1,0x4f,0x7f,0x50), + LL(0xa0,0xa0,0xba,0xa0,0x69,0x1a,0x5d,0xc9), + LL(0x6b,0x6b,0xb1,0x6b,0x7f,0xda,0xd6,0x14), + LL(0x85,0x85,0x2e,0x85,0x5c,0xab,0x17,0xd9), + LL(0xbd,0xbd,0xce,0xbd,0x81,0x73,0x67,0x3c), + LL(0x5d,0x5d,0x69,0x5d,0xd2,0x34,0xba,0x8f), + LL(0x10,0x10,0x40,0x10,0x80,0x50,0x20,0x90), + LL(0xf4,0xf4,0xf7,0xf4,0xf3,0x03,0xf5,0x07), + LL(0xcb,0xcb,0x0b,0xcb,0x16,0xc0,0x8b,0xdd), + LL(0x3e,0x3e,0xf8,0x3e,0xed,0xc6,0x7c,0xd3), + LL(0x05,0x05,0x14,0x05,0x28,0x11,0x0a,0x2d), + LL(0x67,0x67,0x81,0x67,0x1f,0xe6,0xce,0x78), + LL(0xe4,0xe4,0xb7,0xe4,0x73,0x53,0xd5,0x97), + LL(0x27,0x27,0x9c,0x27,0x25,0xbb,0x4e,0x02), + LL(0x41,0x41,0x19,0x41,0x32,0x58,0x82,0x73), + LL(0x8b,0x8b,0x16,0x8b,0x2c,0x9d,0x0b,0xa7), + LL(0xa7,0xa7,0xa6,0xa7,0x51,0x01,0x53,0xf6), + LL(0x7d,0x7d,0xe9,0x7d,0xcf,0x94,0xfa,0xb2), + LL(0x95,0x95,0x6e,0x95,0xdc,0xfb,0x37,0x49), + LL(0xd8,0xd8,0x47,0xd8,0x8e,0x9f,0xad,0x56), + LL(0xfb,0xfb,0xcb,0xfb,0x8b,0x30,0xeb,0x70), + LL(0xee,0xee,0x9f,0xee,0x23,0x71,0xc1,0xcd), + LL(0x7c,0x7c,0xed,0x7c,0xc7,0x91,0xf8,0xbb), + LL(0x66,0x66,0x85,0x66,0x17,0xe3,0xcc,0x71), + LL(0xdd,0xdd,0x53,0xdd,0xa6,0x8e,0xa7,0x7b), + LL(0x17,0x17,0x5c,0x17,0xb8,0x4b,0x2e,0xaf), + LL(0x47,0x47,0x01,0x47,0x02,0x46,0x8e,0x45), + LL(0x9e,0x9e,0x42,0x9e,0x84,0xdc,0x21,0x1a), + LL(0xca,0xca,0x0f,0xca,0x1e,0xc5,0x89,0xd4), + LL(0x2d,0x2d,0xb4,0x2d,0x75,0x99,0x5a,0x58), + LL(0xbf,0xbf,0xc6,0xbf,0x91,0x79,0x63,0x2e), + LL(0x07,0x07,0x1c,0x07,0x38,0x1b,0x0e,0x3f), + LL(0xad,0xad,0x8e,0xad,0x01,0x23,0x47,0xac), + LL(0x5a,0x5a,0x75,0x5a,0xea,0x2f,0xb4,0xb0), + LL(0x83,0x83,0x36,0x83,0x6c,0xb5,0x1b,0xef), + LL(0x33,0x33,0xcc,0x33,0x85,0xff,0x66,0xb6), + LL(0x63,0x63,0x91,0x63,0x3f,0xf2,0xc6,0x5c), + LL(0x02,0x02,0x08,0x02,0x10,0x0a,0x04,0x12), + LL(0xaa,0xaa,0x92,0xaa,0x39,0x38,0x49,0x93), + LL(0x71,0x71,0xd9,0x71,0xaf,0xa8,0xe2,0xde), + LL(0xc8,0xc8,0x07,0xc8,0x0e,0xcf,0x8d,0xc6), + LL(0x19,0x19,0x64,0x19,0xc8,0x7d,0x32,0xd1), + LL(0x49,0x49,0x39,0x49,0x72,0x70,0x92,0x3b), + LL(0xd9,0xd9,0x43,0xd9,0x86,0x9a,0xaf,0x5f), + LL(0xf2,0xf2,0xef,0xf2,0xc3,0x1d,0xf9,0x31), + LL(0xe3,0xe3,0xab,0xe3,0x4b,0x48,0xdb,0xa8), + LL(0x5b,0x5b,0x71,0x5b,0xe2,0x2a,0xb6,0xb9), + LL(0x88,0x88,0x1a,0x88,0x34,0x92,0x0d,0xbc), + LL(0x9a,0x9a,0x52,0x9a,0xa4,0xc8,0x29,0x3e), + LL(0x26,0x26,0x98,0x26,0x2d,0xbe,0x4c,0x0b), + LL(0x32,0x32,0xc8,0x32,0x8d,0xfa,0x64,0xbf), + LL(0xb0,0xb0,0xfa,0xb0,0xe9,0x4a,0x7d,0x59), + LL(0xe9,0xe9,0x83,0xe9,0x1b,0x6a,0xcf,0xf2), + LL(0x0f,0x0f,0x3c,0x0f,0x78,0x33,0x1e,0x77), + LL(0xd5,0xd5,0x73,0xd5,0xe6,0xa6,0xb7,0x33), + LL(0x80,0x80,0x3a,0x80,0x74,0xba,0x1d,0xf4), + LL(0xbe,0xbe,0xc2,0xbe,0x99,0x7c,0x61,0x27), + LL(0xcd,0xcd,0x13,0xcd,0x26,0xde,0x87,0xeb), + LL(0x34,0x34,0xd0,0x34,0xbd,0xe4,0x68,0x89), + LL(0x48,0x48,0x3d,0x48,0x7a,0x75,0x90,0x32), + LL(0xff,0xff,0xdb,0xff,0xab,0x24,0xe3,0x54), + LL(0x7a,0x7a,0xf5,0x7a,0xf7,0x8f,0xf4,0x8d), + LL(0x90,0x90,0x7a,0x90,0xf4,0xea,0x3d,0x64), + LL(0x5f,0x5f,0x61,0x5f,0xc2,0x3e,0xbe,0x9d), + LL(0x20,0x20,0x80,0x20,0x1d,0xa0,0x40,0x3d), + LL(0x68,0x68,0xbd,0x68,0x67,0xd5,0xd0,0x0f), + LL(0x1a,0x1a,0x68,0x1a,0xd0,0x72,0x34,0xca), + LL(0xae,0xae,0x82,0xae,0x19,0x2c,0x41,0xb7), + LL(0xb4,0xb4,0xea,0xb4,0xc9,0x5e,0x75,0x7d), + LL(0x54,0x54,0x4d,0x54,0x9a,0x19,0xa8,0xce), + LL(0x93,0x93,0x76,0x93,0xec,0xe5,0x3b,0x7f), + LL(0x22,0x22,0x88,0x22,0x0d,0xaa,0x44,0x2f), + LL(0x64,0x64,0x8d,0x64,0x07,0xe9,0xc8,0x63), + LL(0xf1,0xf1,0xe3,0xf1,0xdb,0x12,0xff,0x2a), + LL(0x73,0x73,0xd1,0x73,0xbf,0xa2,0xe6,0xcc), + LL(0x12,0x12,0x48,0x12,0x90,0x5a,0x24,0x82), + LL(0x40,0x40,0x1d,0x40,0x3a,0x5d,0x80,0x7a), + LL(0x08,0x08,0x20,0x08,0x40,0x28,0x10,0x48), + LL(0xc3,0xc3,0x2b,0xc3,0x56,0xe8,0x9b,0x95), + LL(0xec,0xec,0x97,0xec,0x33,0x7b,0xc5,0xdf), + LL(0xdb,0xdb,0x4b,0xdb,0x96,0x90,0xab,0x4d), + LL(0xa1,0xa1,0xbe,0xa1,0x61,0x1f,0x5f,0xc0), + LL(0x8d,0x8d,0x0e,0x8d,0x1c,0x83,0x07,0x91), + LL(0x3d,0x3d,0xf4,0x3d,0xf5,0xc9,0x7a,0xc8), + LL(0x97,0x97,0x66,0x97,0xcc,0xf1,0x33,0x5b), + LL(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00), + LL(0xcf,0xcf,0x1b,0xcf,0x36,0xd4,0x83,0xf9), + LL(0x2b,0x2b,0xac,0x2b,0x45,0x87,0x56,0x6e), + LL(0x76,0x76,0xc5,0x76,0x97,0xb3,0xec,0xe1), + LL(0x82,0x82,0x32,0x82,0x64,0xb0,0x19,0xe6), + LL(0xd6,0xd6,0x7f,0xd6,0xfe,0xa9,0xb1,0x28), + LL(0x1b,0x1b,0x6c,0x1b,0xd8,0x77,0x36,0xc3), + LL(0xb5,0xb5,0xee,0xb5,0xc1,0x5b,0x77,0x74), + LL(0xaf,0xaf,0x86,0xaf,0x11,0x29,0x43,0xbe), + LL(0x6a,0x6a,0xb5,0x6a,0x77,0xdf,0xd4,0x1d), + LL(0x50,0x50,0x5d,0x50,0xba,0x0d,0xa0,0xea), + LL(0x45,0x45,0x09,0x45,0x12,0x4c,0x8a,0x57), + LL(0xf3,0xf3,0xeb,0xf3,0xcb,0x18,0xfb,0x38), + LL(0x30,0x30,0xc0,0x30,0x9d,0xf0,0x60,0xad), + LL(0xef,0xef,0x9b,0xef,0x2b,0x74,0xc3,0xc4), + LL(0x3f,0x3f,0xfc,0x3f,0xe5,0xc3,0x7e,0xda), + LL(0x55,0x55,0x49,0x55,0x92,0x1c,0xaa,0xc7), + LL(0xa2,0xa2,0xb2,0xa2,0x79,0x10,0x59,0xdb), + LL(0xea,0xea,0x8f,0xea,0x03,0x65,0xc9,0xe9), + LL(0x65,0x65,0x89,0x65,0x0f,0xec,0xca,0x6a), + LL(0xba,0xba,0xd2,0xba,0xb9,0x68,0x69,0x03), + LL(0x2f,0x2f,0xbc,0x2f,0x65,0x93,0x5e,0x4a), + LL(0xc0,0xc0,0x27,0xc0,0x4e,0xe7,0x9d,0x8e), + LL(0xde,0xde,0x5f,0xde,0xbe,0x81,0xa1,0x60), + LL(0x1c,0x1c,0x70,0x1c,0xe0,0x6c,0x38,0xfc), + LL(0xfd,0xfd,0xd3,0xfd,0xbb,0x2e,0xe7,0x46), + LL(0x4d,0x4d,0x29,0x4d,0x52,0x64,0x9a,0x1f), + LL(0x92,0x92,0x72,0x92,0xe4,0xe0,0x39,0x76), + LL(0x75,0x75,0xc9,0x75,0x8f,0xbc,0xea,0xfa), + LL(0x06,0x06,0x18,0x06,0x30,0x1e,0x0c,0x36), + LL(0x8a,0x8a,0x12,0x8a,0x24,0x98,0x09,0xae), + LL(0xb2,0xb2,0xf2,0xb2,0xf9,0x40,0x79,0x4b), + LL(0xe6,0xe6,0xbf,0xe6,0x63,0x59,0xd1,0x85), + LL(0x0e,0x0e,0x38,0x0e,0x70,0x36,0x1c,0x7e), + LL(0x1f,0x1f,0x7c,0x1f,0xf8,0x63,0x3e,0xe7), + LL(0x62,0x62,0x95,0x62,0x37,0xf7,0xc4,0x55), + LL(0xd4,0xd4,0x77,0xd4,0xee,0xa3,0xb5,0x3a), + LL(0xa8,0xa8,0x9a,0xa8,0x29,0x32,0x4d,0x81), + LL(0x96,0x96,0x62,0x96,0xc4,0xf4,0x31,0x52), + LL(0xf9,0xf9,0xc3,0xf9,0x9b,0x3a,0xef,0x62), + LL(0xc5,0xc5,0x33,0xc5,0x66,0xf6,0x97,0xa3), + LL(0x25,0x25,0x94,0x25,0x35,0xb1,0x4a,0x10), + LL(0x59,0x59,0x79,0x59,0xf2,0x20,0xb2,0xab), + LL(0x84,0x84,0x2a,0x84,0x54,0xae,0x15,0xd0), + LL(0x72,0x72,0xd5,0x72,0xb7,0xa7,0xe4,0xc5), + LL(0x39,0x39,0xe4,0x39,0xd5,0xdd,0x72,0xec), + LL(0x4c,0x4c,0x2d,0x4c,0x5a,0x61,0x98,0x16), + LL(0x5e,0x5e,0x65,0x5e,0xca,0x3b,0xbc,0x94), + LL(0x78,0x78,0xfd,0x78,0xe7,0x85,0xf0,0x9f), + LL(0x38,0x38,0xe0,0x38,0xdd,0xd8,0x70,0xe5), + LL(0x8c,0x8c,0x0a,0x8c,0x14,0x86,0x05,0x98), + LL(0xd1,0xd1,0x63,0xd1,0xc6,0xb2,0xbf,0x17), + LL(0xa5,0xa5,0xae,0xa5,0x41,0x0b,0x57,0xe4), + LL(0xe2,0xe2,0xaf,0xe2,0x43,0x4d,0xd9,0xa1), + LL(0x61,0x61,0x99,0x61,0x2f,0xf8,0xc2,0x4e), + LL(0xb3,0xb3,0xf6,0xb3,0xf1,0x45,0x7b,0x42), + LL(0x21,0x21,0x84,0x21,0x15,0xa5,0x42,0x34), + LL(0x9c,0x9c,0x4a,0x9c,0x94,0xd6,0x25,0x08), + LL(0x1e,0x1e,0x78,0x1e,0xf0,0x66,0x3c,0xee), + LL(0x43,0x43,0x11,0x43,0x22,0x52,0x86,0x61), + LL(0xc7,0xc7,0x3b,0xc7,0x76,0xfc,0x93,0xb1), + LL(0xfc,0xfc,0xd7,0xfc,0xb3,0x2b,0xe5,0x4f), + LL(0x04,0x04,0x10,0x04,0x20,0x14,0x08,0x24), + LL(0x51,0x51,0x59,0x51,0xb2,0x08,0xa2,0xe3), + LL(0x99,0x99,0x5e,0x99,0xbc,0xc7,0x2f,0x25), + LL(0x6d,0x6d,0xa9,0x6d,0x4f,0xc4,0xda,0x22), + LL(0x0d,0x0d,0x34,0x0d,0x68,0x39,0x1a,0x65), + LL(0xfa,0xfa,0xcf,0xfa,0x83,0x35,0xe9,0x79), + LL(0xdf,0xdf,0x5b,0xdf,0xb6,0x84,0xa3,0x69), + LL(0x7e,0x7e,0xe5,0x7e,0xd7,0x9b,0xfc,0xa9), + LL(0x24,0x24,0x90,0x24,0x3d,0xb4,0x48,0x19), + LL(0x3b,0x3b,0xec,0x3b,0xc5,0xd7,0x76,0xfe), + LL(0xab,0xab,0x96,0xab,0x31,0x3d,0x4b,0x9a), + LL(0xce,0xce,0x1f,0xce,0x3e,0xd1,0x81,0xf0), + LL(0x11,0x11,0x44,0x11,0x88,0x55,0x22,0x99), + LL(0x8f,0x8f,0x06,0x8f,0x0c,0x89,0x03,0x83), + LL(0x4e,0x4e,0x25,0x4e,0x4a,0x6b,0x9c,0x04), + LL(0xb7,0xb7,0xe6,0xb7,0xd1,0x51,0x73,0x66), + LL(0xeb,0xeb,0x8b,0xeb,0x0b,0x60,0xcb,0xe0), + LL(0x3c,0x3c,0xf0,0x3c,0xfd,0xcc,0x78,0xc1), + LL(0x81,0x81,0x3e,0x81,0x7c,0xbf,0x1f,0xfd), + LL(0x94,0x94,0x6a,0x94,0xd4,0xfe,0x35,0x40), + LL(0xf7,0xf7,0xfb,0xf7,0xeb,0x0c,0xf3,0x1c), + LL(0xb9,0xb9,0xde,0xb9,0xa1,0x67,0x6f,0x18), + LL(0x13,0x13,0x4c,0x13,0x98,0x5f,0x26,0x8b), + LL(0x2c,0x2c,0xb0,0x2c,0x7d,0x9c,0x58,0x51), + LL(0xd3,0xd3,0x6b,0xd3,0xd6,0xb8,0xbb,0x05), + LL(0xe7,0xe7,0xbb,0xe7,0x6b,0x5c,0xd3,0x8c), + LL(0x6e,0x6e,0xa5,0x6e,0x57,0xcb,0xdc,0x39), + LL(0xc4,0xc4,0x37,0xc4,0x6e,0xf3,0x95,0xaa), + LL(0x03,0x03,0x0c,0x03,0x18,0x0f,0x06,0x1b), + LL(0x56,0x56,0x45,0x56,0x8a,0x13,0xac,0xdc), + LL(0x44,0x44,0x0d,0x44,0x1a,0x49,0x88,0x5e), + LL(0x7f,0x7f,0xe1,0x7f,0xdf,0x9e,0xfe,0xa0), + LL(0xa9,0xa9,0x9e,0xa9,0x21,0x37,0x4f,0x88), + LL(0x2a,0x2a,0xa8,0x2a,0x4d,0x82,0x54,0x67), + LL(0xbb,0xbb,0xd6,0xbb,0xb1,0x6d,0x6b,0x0a), + LL(0xc1,0xc1,0x23,0xc1,0x46,0xe2,0x9f,0x87), + LL(0x53,0x53,0x51,0x53,0xa2,0x02,0xa6,0xf1), + LL(0xdc,0xdc,0x57,0xdc,0xae,0x8b,0xa5,0x72), + LL(0x0b,0x0b,0x2c,0x0b,0x58,0x27,0x16,0x53), + LL(0x9d,0x9d,0x4e,0x9d,0x9c,0xd3,0x27,0x01), + LL(0x6c,0x6c,0xad,0x6c,0x47,0xc1,0xd8,0x2b), + LL(0x31,0x31,0xc4,0x31,0x95,0xf5,0x62,0xa4), + LL(0x74,0x74,0xcd,0x74,0x87,0xb9,0xe8,0xf3), + LL(0xf6,0xf6,0xff,0xf6,0xe3,0x09,0xf1,0x15), + LL(0x46,0x46,0x05,0x46,0x0a,0x43,0x8c,0x4c), + LL(0xac,0xac,0x8a,0xac,0x09,0x26,0x45,0xa5), + LL(0x89,0x89,0x1e,0x89,0x3c,0x97,0x0f,0xb5), + LL(0x14,0x14,0x50,0x14,0xa0,0x44,0x28,0xb4), + LL(0xe1,0xe1,0xa3,0xe1,0x5b,0x42,0xdf,0xba), + LL(0x16,0x16,0x58,0x16,0xb0,0x4e,0x2c,0xa6), + LL(0x3a,0x3a,0xe8,0x3a,0xcd,0xd2,0x74,0xf7), + LL(0x69,0x69,0xb9,0x69,0x6f,0xd0,0xd2,0x06), + LL(0x09,0x09,0x24,0x09,0x48,0x2d,0x12,0x41), + LL(0x70,0x70,0xdd,0x70,0xa7,0xad,0xe0,0xd7), + LL(0xb6,0xb6,0xe2,0xb6,0xd9,0x54,0x71,0x6f), + LL(0xd0,0xd0,0x67,0xd0,0xce,0xb7,0xbd,0x1e), + LL(0xed,0xed,0x93,0xed,0x3b,0x7e,0xc7,0xd6), + LL(0xcc,0xcc,0x17,0xcc,0x2e,0xdb,0x85,0xe2), + LL(0x42,0x42,0x15,0x42,0x2a,0x57,0x84,0x68), + LL(0x98,0x98,0x5a,0x98,0xb4,0xc2,0x2d,0x2c), + LL(0xa4,0xa4,0xaa,0xa4,0x49,0x0e,0x55,0xed), + LL(0x28,0x28,0xa0,0x28,0x5d,0x88,0x50,0x75), + LL(0x5c,0x5c,0x6d,0x5c,0xda,0x31,0xb8,0x86), + LL(0xf8,0xf8,0xc7,0xf8,0x93,0x3f,0xed,0x6b), + LL(0x86,0x86,0x22,0x86,0x44,0xa4,0x11,0xc2), +#define RC (&(Cx.q[256*N])) + 0x18,0x23,0xc6,0xe8,0x87,0xb8,0x01,0x4f, /* rc[ROUNDS] */ + 0x36,0xa6,0xd2,0xf5,0x79,0x6f,0x91,0x52, + 0x60,0xbc,0x9b,0x8e,0xa3,0x0c,0x7b,0x35, + 0x1d,0xe0,0xd7,0xc2,0x2e,0x4b,0xfe,0x57, + 0x15,0x77,0x37,0xe5,0x9f,0xf0,0x4a,0xda, + 0x58,0xc9,0x29,0x0a,0xb1,0xa0,0x6b,0x85, + 0xbd,0x5d,0x10,0xf4,0xcb,0x3e,0x05,0x67, + 0xe4,0x27,0x41,0x8b,0xa7,0x7d,0x95,0xd8, + 0xfb,0xee,0x7c,0x66,0xdd,0x17,0x47,0x9e, + 0xca,0x2d,0xbf,0x07,0xad,0x5a,0x83,0x33 + } +}; + +void whirlpool_block(WHIRLPOOL_CTX *ctx,const void *inp,size_t n) + { + int r; + const u8 *p=inp; + union { u64 q[8]; u8 c[64]; } S,K,*H=(void *)ctx->H.q; + +#ifdef GO_FOR_MMX + GO_FOR_MMX(ctx,inp,n); +#endif + do { +#ifdef OPENSSL_SMALL_FOOTPRINT + u64 L[8]; + int i; + + for (i=0;i<64;i++) S.c[i] = (K.c[i] = H->c[i]) ^ p[i]; + for (r=0;rc[i] ^= S.c[i] ^ p[i]; +#else + u64 L0,L1,L2,L3,L4,L5,L6,L7; + +#ifdef __STRICT_ALIGNMENT + if ((size_t)p & 7) + { + memcpy (S.c,p,64); + S.q[0] ^= (K.q[0] = H->q[0]); + S.q[1] ^= (K.q[1] = H->q[1]); + S.q[2] ^= (K.q[2] = H->q[2]); + S.q[3] ^= (K.q[3] = H->q[3]); + S.q[4] ^= (K.q[4] = H->q[4]); + S.q[5] ^= (K.q[5] = H->q[5]); + S.q[6] ^= (K.q[6] = H->q[6]); + S.q[7] ^= (K.q[7] = H->q[7]); + } + else +#endif + { + const u64 *pa = (const u64*)p; + S.q[0] = (K.q[0] = H->q[0]) ^ pa[0]; + S.q[1] = (K.q[1] = H->q[1]) ^ pa[1]; + S.q[2] = (K.q[2] = H->q[2]) ^ pa[2]; + S.q[3] = (K.q[3] = H->q[3]) ^ pa[3]; + S.q[4] = (K.q[4] = H->q[4]) ^ pa[4]; + S.q[5] = (K.q[5] = H->q[5]) ^ pa[5]; + S.q[6] = (K.q[6] = H->q[6]) ^ pa[6]; + S.q[7] = (K.q[7] = H->q[7]) ^ pa[7]; + } + + for(r=0;rc[i] ^= S.c[i] ^ p[i]; + } + else +#endif + { + const u64 *pa=(const u64 *)p; + H->q[0] ^= S.q[0] ^ pa[0]; + H->q[1] ^= S.q[1] ^ pa[1]; + H->q[2] ^= S.q[2] ^ pa[2]; + H->q[3] ^= S.q[3] ^ pa[3]; + H->q[4] ^= S.q[4] ^ pa[4]; + H->q[5] ^= S.q[5] ^ pa[5]; + H->q[6] ^= S.q[6] ^ pa[6]; + H->q[7] ^= S.q[7] ^ pa[7]; + } +#endif + p += 64; + } while(--n); + } diff --git a/crypto/whrlpool/wp_dgst.c b/crypto/whrlpool/wp_dgst.c new file mode 100644 index 0000000..71fd79c --- /dev/null +++ b/crypto/whrlpool/wp_dgst.c @@ -0,0 +1,268 @@ +/* $OpenBSD: wp_dgst.c,v 1.7 2023/09/04 08:43:41 tb Exp $ */ +/** + * The Whirlpool hashing function. + * + *

+ * References + * + *

+ * The Whirlpool algorithm was developed by + * Paulo S. L. M. Barreto and + * Vincent Rijmen. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * + * + * Based on "@version 3.0 (2003.03.12)" by Paulo S.L.M. Barreto and + * Vincent Rijmen. Lookup "reference implementations" on + * + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. + * + */ + +/* + * OpenSSL-specific implementation notes. + * + * WHIRLPOOL_Update as well as one-stroke WHIRLPOOL both expect + * number of *bytes* as input length argument. Bit-oriented routine + * as specified by authors is called WHIRLPOOL_BitUpdate[!] and + * does not have one-stroke counterpart. + * + * WHIRLPOOL_BitUpdate implements byte-oriented loop, essentially + * to serve WHIRLPOOL_Update. This is done for performance. + * + * Unlike authors' reference implementation, block processing + * routine whirlpool_block is designed to operate on multi-block + * input. This is done for performance. + */ + +#include + +#include + +#include "wp_local.h" + +int WHIRLPOOL_Init(WHIRLPOOL_CTX *c) + { + memset (c,0,sizeof(*c)); + return(1); + } + +int WHIRLPOOL_Update (WHIRLPOOL_CTX *c,const void *_inp,size_t bytes) + { + /* Well, largest suitable chunk size actually is + * (1<<(sizeof(size_t)*8-3))-64, but below number + * is large enough for not to care about excessive + * calls to WHIRLPOOL_BitUpdate... */ + size_t chunk = ((size_t)1)<<(sizeof(size_t)*8-4); + const unsigned char *inp = _inp; + + while (bytes>=chunk) + { + WHIRLPOOL_BitUpdate(c,inp,chunk*8); + bytes -= chunk; + inp += chunk; + } + if (bytes) + WHIRLPOOL_BitUpdate(c,inp,bytes*8); + + return(1); + } + +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,const void *_inp,size_t bits) + { + size_t n; + unsigned int bitoff = c->bitoff, + bitrem = bitoff%8, + inpgap = (8-(unsigned int)bits%8)&7; + const unsigned char *inp=_inp; + + /* This 256-bit increment procedure relies on the size_t + * being natural size of CPU register, so that we don't + * have to mask the value in order to detect overflows. */ + c->bitlen[0] += bits; + if (c->bitlen[0] < bits) /* overflow */ + { + n = 1; + do { c->bitlen[n]++; + } while(c->bitlen[n]==0 + && ++n<(WHIRLPOOL_COUNTER/sizeof(size_t))); + } + +#ifndef OPENSSL_SMALL_FOOTPRINT + reconsider: + if (inpgap==0 && bitrem==0) /* byte-oriented loop */ + { + while (bits) + { + if (bitoff==0 && (n=bits/WHIRLPOOL_BBLOCK)) + { + whirlpool_block(c,inp,n); + inp += n*WHIRLPOOL_BBLOCK/8; + bits %= WHIRLPOOL_BBLOCK; + } + else + { + unsigned int byteoff = bitoff/8; + + bitrem = WHIRLPOOL_BBLOCK - bitoff;/* re-use bitrem */ + if (bits >= bitrem) + { + bits -= bitrem; + bitrem /= 8; + memcpy(c->data+byteoff,inp,bitrem); + inp += bitrem; + whirlpool_block(c,c->data,1); + bitoff = 0; + } + else + { + memcpy(c->data+byteoff,inp,bits/8); + bitoff += (unsigned int)bits; + bits = 0; + } + c->bitoff = bitoff; + } + } + } + else /* bit-oriented loop */ +#endif + { + /* + inp + | + +-------+-------+------- + ||||||||||||||||||||| + +-------+-------+------- + +-------+-------+-------+-------+------- + |||||||||||||| c->data + +-------+-------+-------+-------+------- + | + c->bitoff/8 + */ + while (bits) + { + unsigned int byteoff = bitoff/8; + unsigned char b; + +#ifndef OPENSSL_SMALL_FOOTPRINT + if (bitrem==inpgap) + { + c->data[byteoff++] |= inp[0] & (0xff>>inpgap); + inpgap = 8-inpgap; + bitoff += inpgap; bitrem = 0; /* bitoff%8 */ + bits -= inpgap; inpgap = 0; /* bits%8 */ + inp++; + if (bitoff==WHIRLPOOL_BBLOCK) + { + whirlpool_block(c,c->data,1); + bitoff = 0; + } + c->bitoff = bitoff; + goto reconsider; + } + else +#endif + if (bits>=8) + { + b = ((inp[0]<>(8-inpgap))); + b &= 0xff; + if (bitrem) c->data[byteoff++] |= b>>bitrem; + else c->data[byteoff++] = b; + bitoff += 8; + bits -= 8; + inp++; + if (bitoff>=WHIRLPOOL_BBLOCK) + { + whirlpool_block(c,c->data,1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) c->data[byteoff] = b<<(8-bitrem); + } + else /* remaining less than 8 bits */ + { + b = (inp[0]<data[byteoff++] |= b>>bitrem; + else c->data[byteoff++] = b; + bitoff += (unsigned int)bits; + if (bitoff==WHIRLPOOL_BBLOCK) + { + whirlpool_block(c,c->data,1); + byteoff = 0; + bitoff %= WHIRLPOOL_BBLOCK; + } + if (bitrem) c->data[byteoff] = b<<(8-bitrem); + bits = 0; + } + c->bitoff = bitoff; + } + } + } + +int WHIRLPOOL_Final (unsigned char *md,WHIRLPOOL_CTX *c) + { + unsigned int bitoff = c->bitoff, + byteoff = bitoff/8; + size_t i,j,v; + unsigned char *p; + + bitoff %= 8; + if (bitoff) c->data[byteoff] |= 0x80>>bitoff; + else c->data[byteoff] = 0x80; + byteoff++; + + /* pad with zeros */ + if (byteoff > (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)) + { + if (byteoffdata[byteoff],0,WHIRLPOOL_BBLOCK/8-byteoff); + whirlpool_block(c,c->data,1); + byteoff = 0; + } + if (byteoff < (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)) + memset(&c->data[byteoff],0, + (WHIRLPOOL_BBLOCK/8-WHIRLPOOL_COUNTER)-byteoff); + /* smash 256-bit c->bitlen in big-endian order */ + p = &c->data[WHIRLPOOL_BBLOCK/8-1]; /* last byte in c->data */ + for(i=0;ibitlen[i],j=0;j>=8) + *p-- = (unsigned char)(v&0xff); + + whirlpool_block(c,c->data,1); + + if (md) { + memcpy(md,c->H.c,WHIRLPOOL_DIGEST_LENGTH); + memset(c,0,sizeof(*c)); + return(1); + } + return(0); + } + +unsigned char *WHIRLPOOL(const void *inp, size_t bytes,unsigned char *md) + { + WHIRLPOOL_CTX ctx; + static unsigned char m[WHIRLPOOL_DIGEST_LENGTH]; + + if (md == NULL) md=m; + WHIRLPOOL_Init(&ctx); + WHIRLPOOL_Update(&ctx,inp,bytes); + WHIRLPOOL_Final(md,&ctx); + return(md); + } diff --git a/crypto/whrlpool/wp_local.h b/crypto/whrlpool/wp_local.h new file mode 100644 index 0000000..892dce2 --- /dev/null +++ b/crypto/whrlpool/wp_local.h @@ -0,0 +1,11 @@ +/* $OpenBSD: wp_local.h,v 1.2 2023/09/04 08:43:41 tb Exp $ */ + +#include + +#include + +__BEGIN_HIDDEN_DECLS + +void whirlpool_block(WHIRLPOOL_CTX *,const void *,size_t); + +__END_HIDDEN_DECLS diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c new file mode 100644 index 0000000..9fa6a10 --- /dev/null +++ b/crypto/x509/by_dir.c @@ -0,0 +1,413 @@ +/* $OpenBSD: by_dir.c,v 1.44 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "x509_local.h" + +typedef struct lookup_dir_hashes_st { + unsigned long hash; + int suffix; +} BY_DIR_HASH; + +typedef struct lookup_dir_entry_st { + char *dir; + int dir_type; + STACK_OF(BY_DIR_HASH) *hashes; +} BY_DIR_ENTRY; + +typedef struct lookup_dir_st { + BUF_MEM *buffer; + STACK_OF(BY_DIR_ENTRY) *dirs; +} BY_DIR; + +DECLARE_STACK_OF(BY_DIR_HASH) +DECLARE_STACK_OF(BY_DIR_ENTRY) + +static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret); +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, int type, X509_NAME *name, + X509_OBJECT *ret); + +static X509_LOOKUP_METHOD x509_dir_lookup = { + .name = "Load certs from files in a directory", + .new_item = new_dir, + .free = free_dir, + .init = NULL, + .shutdown = NULL, + .ctrl = dir_ctrl, + .get_by_subject = get_cert_by_subject, + .get_by_issuer_serial = NULL, + .get_by_fingerprint = NULL, + .get_by_alias = NULL, +}; + +X509_LOOKUP_METHOD * +X509_LOOKUP_hash_dir(void) +{ + return &x509_dir_lookup; +} +LCRYPTO_ALIAS(X509_LOOKUP_hash_dir); + +static int +dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **retp) +{ + int ret = 0; + BY_DIR *ld; + + ld = (BY_DIR *)ctx->method_data; + + switch (cmd) { + case X509_L_ADD_DIR: + if (argl == X509_FILETYPE_DEFAULT) { + ret = add_cert_dir(ld, X509_get_default_cert_dir(), + X509_FILETYPE_PEM); + if (!ret) { + X509error(X509_R_LOADING_CERT_DIR); + } + } else + ret = add_cert_dir(ld, argp, (int)argl); + break; + } + return ret; +} + +static int +new_dir(X509_LOOKUP *lu) +{ + BY_DIR *a; + + if ((a = malloc(sizeof(*a))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + if ((a->buffer = BUF_MEM_new()) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + free(a); + return 0; + } + a->dirs = NULL; + lu->method_data = (char *)a; + return 1; +} + +static void +by_dir_hash_free(BY_DIR_HASH *hash) +{ + free(hash); +} + +static int +by_dir_hash_cmp(const BY_DIR_HASH * const *a, + const BY_DIR_HASH * const *b) +{ + if ((*a)->hash > (*b)->hash) + return 1; + if ((*a)->hash < (*b)->hash) + return -1; + return 0; +} + +static void +by_dir_entry_free(BY_DIR_ENTRY *ent) +{ + free(ent->dir); + sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free); + free(ent); +} + +static void +free_dir(X509_LOOKUP *lu) +{ + BY_DIR *a; + + a = (BY_DIR *)lu->method_data; + sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free); + BUF_MEM_free(a->buffer); + free(a); +} + +static int +add_cert_dir(BY_DIR *ctx, const char *dir, int type) +{ + int j; + const char *s, *ss, *p; + ptrdiff_t len; + + if (dir == NULL || !*dir) { + X509error(X509_R_INVALID_DIRECTORY); + return 0; + } + + s = dir; + p = s; + do { + if ((*p == ':') || (*p == '\0')) { + BY_DIR_ENTRY *ent; + + ss = s; + s = p + 1; + len = p - ss; + if (len == 0) + continue; + for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) { + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j); + if (strlen(ent->dir) == (size_t)len && + strncmp(ent->dir, ss, (size_t)len) == 0) + break; + } + if (j < sk_BY_DIR_ENTRY_num(ctx->dirs)) + continue; + if (ctx->dirs == NULL) { + ctx->dirs = sk_BY_DIR_ENTRY_new_null(); + if (ctx->dirs == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + } + ent = malloc(sizeof(*ent)); + if (ent == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + ent->dir_type = type; + ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp); + ent->dir = strndup(ss, (size_t)len); + if (ent->dir == NULL || ent->hashes == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + by_dir_entry_free(ent); + return 0; + } + if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) { + X509error(ERR_R_MALLOC_FAILURE); + by_dir_entry_free(ent); + return 0; + } + } + } while (*p++ != '\0'); + return 1; +} + +static int +get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, + X509_OBJECT *ret) +{ + BY_DIR *ctx; + union { + struct { + X509 st_x509; + X509_CINF st_x509_cinf; + } x509; + struct { + X509_CRL st_crl; + X509_CRL_INFO st_crl_info; + } crl; + } data; + int ok = 0; + int i, j, k; + unsigned long h; + BUF_MEM *b = NULL; + X509_OBJECT stmp, *tmp; + const char *postfix=""; + + if (name == NULL) + return 0; + + stmp.type = type; + if (type == X509_LU_X509) { + data.x509.st_x509.cert_info = &data.x509.st_x509_cinf; + data.x509.st_x509_cinf.subject = name; + stmp.data.x509 = &data.x509.st_x509; + postfix=""; + } else if (type == X509_LU_CRL) { + data.crl.st_crl.crl = &data.crl.st_crl_info; + data.crl.st_crl_info.issuer = name; + stmp.data.crl = &data.crl.st_crl; + postfix="r"; + } else { + X509error(X509_R_WRONG_LOOKUP_TYPE); + goto finish; + } + + if ((b = BUF_MEM_new()) == NULL) { + X509error(ERR_R_BUF_LIB); + goto finish; + } + + ctx = (BY_DIR *)xl->method_data; + + h = X509_NAME_hash(name); + for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) { + BY_DIR_ENTRY *ent; + int idx; + BY_DIR_HASH htmp, *hent; + + ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i); + j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1; + if (!BUF_MEM_grow(b, j)) { + X509error(ERR_R_MALLOC_FAILURE); + goto finish; + } + if (type == X509_LU_CRL) { + htmp.hash = h; + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); + if (idx >= 0) { + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + k = hent->suffix; + } else { + hent = NULL; + k = 0; + } + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + } else { + k = 0; + hent = NULL; + } + for (;;) { + (void) snprintf(b->data, b->max, "%s/%08lx.%s%d", + ent->dir, h, postfix, k); + + { + struct stat st; + if (stat(b->data, &st) < 0) + break; + } + /* found one. */ + if (type == X509_LU_X509) { + if ((X509_load_cert_file(xl, b->data, + ent->dir_type)) == 0) + break; + } else if (type == X509_LU_CRL) { + if ((X509_load_crl_file(xl, b->data, + ent->dir_type)) == 0) + break; + } + /* else case will caught higher up */ + k++; + } + + /* we have added it to the cache so now pull it out again */ + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + j = sk_X509_OBJECT_find(xl->store_ctx->objs, &stmp); + tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, j); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + /* If a CRL, update the last file suffix added for this */ + if (type == X509_LU_CRL) { + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + /* + * Look for entry again in case another thread added + * an entry first. + */ + if (hent == NULL) { + htmp.hash = h; + idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp); + hent = sk_BY_DIR_HASH_value(ent->hashes, idx); + } + if (hent == NULL) { + hent = malloc(sizeof(*hent)); + if (hent == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + ok = 0; + goto finish; + } + hent->hash = h; + hent->suffix = k; + if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) { + X509error(ERR_R_MALLOC_FAILURE); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + free(hent); + ok = 0; + goto finish; + } + } else if (hent->suffix < k) + hent->suffix = k; + + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + } + + if (tmp != NULL) { + ok = 1; + ret->type = tmp->type; + memcpy(&ret->data, &tmp->data, sizeof(ret->data)); + goto finish; + } + } +finish: + BUF_MEM_free(b); + return ok; +} diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c new file mode 100644 index 0000000..606f4c8 --- /dev/null +++ b/crypto/x509/by_file.c @@ -0,0 +1,273 @@ +/* $OpenBSD: by_file.c,v 1.28 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +static X509_LOOKUP_METHOD x509_file_lookup = { + .name = "Load file into cache", + .new_item = NULL, + .free = NULL, + .init = NULL, + .shutdown = NULL, + .ctrl = by_file_ctrl, + .get_by_subject = NULL, + .get_by_issuer_serial = NULL, + .get_by_fingerprint = NULL, + .get_by_alias = NULL, +}; + +X509_LOOKUP_METHOD * +X509_LOOKUP_file(void) +{ + return &x509_file_lookup; +} +LCRYPTO_ALIAS(X509_LOOKUP_file); + +static int +by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl, + char **ret) +{ + int ok = 0; + + switch (cmd) { + case X509_L_FILE_LOAD: + if (argl == X509_FILETYPE_DEFAULT) { + ok = (X509_load_cert_crl_file(ctx, + X509_get_default_cert_file(), + X509_FILETYPE_PEM) != 0); + if (!ok) { + X509error(X509_R_LOADING_DEFAULTS); + } + } else { + if (argl == X509_FILETYPE_PEM) + ok = (X509_load_cert_crl_file(ctx, argp, + X509_FILETYPE_PEM) != 0); + else + ok = (X509_load_cert_file(ctx, + argp, (int)argl) != 0); + } + break; + } + return ok; +} + +int +X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + X509error(ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_AUX(in, NULL, NULL, ""); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + X509error(ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_bio(in, NULL); + if (x == NULL) { + X509error(ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_cert(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + X509error(X509_R_BAD_X509_FILETYPE); + goto err; + } +err: + X509_free(x); + BIO_free(in); + return ret; +} +LCRYPTO_ALIAS(X509_load_cert_file); + +int +X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + int ret = 0; + BIO *in = NULL; + int i, count = 0; + X509_CRL *x = NULL; + + in = BIO_new(BIO_s_file()); + + if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) { + X509error(ERR_R_SYS_LIB); + goto err; + } + + if (type == X509_FILETYPE_PEM) { + for (;;) { + x = PEM_read_bio_X509_CRL(in, NULL, NULL, ""); + if (x == NULL) { + if ((ERR_GET_REASON(ERR_peek_last_error()) == + PEM_R_NO_START_LINE) && (count > 0)) { + ERR_clear_error(); + break; + } else { + X509error(ERR_R_PEM_LIB); + goto err; + } + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + count++; + X509_CRL_free(x); + x = NULL; + } + ret = count; + } else if (type == X509_FILETYPE_ASN1) { + x = d2i_X509_CRL_bio(in, NULL); + if (x == NULL) { + X509error(ERR_R_ASN1_LIB); + goto err; + } + i = X509_STORE_add_crl(ctx->store_ctx, x); + if (!i) + goto err; + ret = i; + } else { + X509error(X509_R_BAD_X509_FILETYPE); + goto err; + } +err: + X509_CRL_free(x); + BIO_free(in); + return ret; +} +LCRYPTO_ALIAS(X509_load_crl_file); + +int +X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type) +{ + STACK_OF(X509_INFO) *inf; + X509_INFO *itmp; + BIO *in; + int i, count = 0; + + if (type != X509_FILETYPE_PEM) + return X509_load_cert_file(ctx, file, type); + in = BIO_new_file(file, "r"); + if (!in) { + X509error(ERR_R_SYS_LIB); + return 0; + } + inf = PEM_X509_INFO_read_bio(in, NULL, NULL, ""); + BIO_free(in); + if (!inf) { + X509error(ERR_R_PEM_LIB); + return 0; + } + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + X509_STORE_add_cert(ctx->store_ctx, itmp->x509); + count++; + } + if (itmp->crl) { + X509_STORE_add_crl(ctx->store_ctx, itmp->crl); + count++; + } + } + if (count == 0) + X509error(X509_R_NO_CERTIFICATE_OR_CRL_FOUND); + sk_X509_INFO_pop_free(inf, X509_INFO_free); + return count; +} +LCRYPTO_ALIAS(X509_load_cert_crl_file); diff --git a/crypto/x509/by_mem.c b/crypto/x509/by_mem.c new file mode 100644 index 0000000..579eecd --- /dev/null +++ b/crypto/x509/by_mem.c @@ -0,0 +1,141 @@ +/* $OpenBSD: by_mem.c,v 1.8 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_local.h" + +static int by_mem_ctrl(X509_LOOKUP *, int, const char *, long, char **); + +static X509_LOOKUP_METHOD x509_mem_lookup = { + .name = "Load cert from memory", + .new_item = NULL, + .free = NULL, + .init = NULL, + .shutdown = NULL, + .ctrl = by_mem_ctrl, + .get_by_subject = NULL, + .get_by_issuer_serial = NULL, + .get_by_fingerprint = NULL, + .get_by_alias = NULL, +}; + +X509_LOOKUP_METHOD * +X509_LOOKUP_mem(void) +{ + return (&x509_mem_lookup); +} +LCRYPTO_ALIAS(X509_LOOKUP_mem); + +static int +by_mem_ctrl(X509_LOOKUP *lu, int cmd, const char *buf, + long type, char **ret) +{ + STACK_OF(X509_INFO) *inf = NULL; + const struct iovec *iov; + X509_INFO *itmp; + BIO *in = NULL; + int i, count = 0, ok = 0; + + iov = (const struct iovec *)buf; + + if (!(cmd == X509_L_MEM && type == X509_FILETYPE_PEM)) + goto done; + + if ((in = BIO_new_mem_buf(iov->iov_base, iov->iov_len)) == NULL) + goto done; + + if ((inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) + goto done; + + for (i = 0; i < sk_X509_INFO_num(inf); i++) { + itmp = sk_X509_INFO_value(inf, i); + if (itmp->x509) { + ok = X509_STORE_add_cert(lu->store_ctx, itmp->x509); + if (!ok) + goto done; + count++; + } + if (itmp->crl) { + ok = X509_STORE_add_crl(lu->store_ctx, itmp->crl); + if (!ok) + goto done; + count++; + } + } + + ok = count != 0; + done: + if (count == 0) + X509error(ERR_R_PEM_LIB); + if (inf != NULL) + sk_X509_INFO_pop_free(inf, X509_INFO_free); + if (in != NULL) + BIO_free(in); + return (ok); +} diff --git a/crypto/x509/x509_addr.c b/crypto/x509/x509_addr.c new file mode 100644 index 0000000..5e4223c --- /dev/null +++ b/crypto/x509/x509_addr.c @@ -0,0 +1,2061 @@ +/* $OpenBSD: x509_addr.c,v 1.90 2023/09/27 11:29:22 tb Exp $ */ +/* + * Contributed to the OpenSSL Project by the American Registry for + * Internet Numbers ("ARIN"). + */ +/* ==================================================================== + * Copyright (c) 2006-2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + */ + +/* + * Implementation of RFC 3779 section 2.2. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "asn1_local.h" +#include "bytestring.h" +#include "x509_local.h" + +#ifndef OPENSSL_NO_RFC3779 + +/* + * OpenSSL ASN.1 template translation of RFC 3779 2.2.3. + */ + +static const ASN1_TEMPLATE IPAddressRange_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressRange, min), + .field_name = "min", + .item = &ASN1_BIT_STRING_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressRange, max), + .field_name = "max", + .item = &ASN1_BIT_STRING_it, + }, +}; + +const ASN1_ITEM IPAddressRange_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = IPAddressRange_seq_tt, + .tcount = sizeof(IPAddressRange_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(IPAddressRange), + .sname = "IPAddressRange", +}; + +static const ASN1_TEMPLATE IPAddressOrRange_ch_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressOrRange, u.addressPrefix), + .field_name = "u.addressPrefix", + .item = &ASN1_BIT_STRING_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressOrRange, u.addressRange), + .field_name = "u.addressRange", + .item = &IPAddressRange_it, + }, +}; + +const ASN1_ITEM IPAddressOrRange_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(IPAddressOrRange, type), + .templates = IPAddressOrRange_ch_tt, + .tcount = sizeof(IPAddressOrRange_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(IPAddressOrRange), + .sname = "IPAddressOrRange", +}; + +static const ASN1_TEMPLATE IPAddressChoice_ch_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressChoice, u.inherit), + .field_name = "u.inherit", + .item = &ASN1_NULL_it, + }, + { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = offsetof(IPAddressChoice, u.addressesOrRanges), + .field_name = "u.addressesOrRanges", + .item = &IPAddressOrRange_it, + }, +}; + +const ASN1_ITEM IPAddressChoice_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(IPAddressChoice, type), + .templates = IPAddressChoice_ch_tt, + .tcount = sizeof(IPAddressChoice_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(IPAddressChoice), + .sname = "IPAddressChoice", +}; + +static const ASN1_TEMPLATE IPAddressFamily_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressFamily, addressFamily), + .field_name = "addressFamily", + .item = &ASN1_OCTET_STRING_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(IPAddressFamily, ipAddressChoice), + .field_name = "ipAddressChoice", + .item = &IPAddressChoice_it, + }, +}; + +const ASN1_ITEM IPAddressFamily_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = IPAddressFamily_seq_tt, + .tcount = sizeof(IPAddressFamily_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(IPAddressFamily), + .sname = "IPAddressFamily", +}; + +static const ASN1_TEMPLATE IPAddrBlocks_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "IPAddrBlocks", + .item = &IPAddressFamily_it, +}; + +static const ASN1_ITEM IPAddrBlocks_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &IPAddrBlocks_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "IPAddrBlocks", +}; + +IPAddressRange * +d2i_IPAddressRange(IPAddressRange **a, const unsigned char **in, long len) +{ + return (IPAddressRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &IPAddressRange_it); +} +LCRYPTO_ALIAS(d2i_IPAddressRange); + +int +i2d_IPAddressRange(IPAddressRange *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressRange_it); +} +LCRYPTO_ALIAS(i2d_IPAddressRange); + +IPAddressRange * +IPAddressRange_new(void) +{ + return (IPAddressRange *)ASN1_item_new(&IPAddressRange_it); +} +LCRYPTO_ALIAS(IPAddressRange_new); + +void +IPAddressRange_free(IPAddressRange *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &IPAddressRange_it); +} +LCRYPTO_ALIAS(IPAddressRange_free); + +IPAddressOrRange * +d2i_IPAddressOrRange(IPAddressOrRange **a, const unsigned char **in, long len) +{ + return (IPAddressOrRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &IPAddressOrRange_it); +} +LCRYPTO_ALIAS(d2i_IPAddressOrRange); + +int +i2d_IPAddressOrRange(IPAddressOrRange *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressOrRange_it); +} +LCRYPTO_ALIAS(i2d_IPAddressOrRange); + +IPAddressOrRange * +IPAddressOrRange_new(void) +{ + return (IPAddressOrRange *)ASN1_item_new(&IPAddressOrRange_it); +} +LCRYPTO_ALIAS(IPAddressOrRange_new); + +void +IPAddressOrRange_free(IPAddressOrRange *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &IPAddressOrRange_it); +} +LCRYPTO_ALIAS(IPAddressOrRange_free); + +IPAddressChoice * +d2i_IPAddressChoice(IPAddressChoice **a, const unsigned char **in, long len) +{ + return (IPAddressChoice *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &IPAddressChoice_it); +} +LCRYPTO_ALIAS(d2i_IPAddressChoice); + +int +i2d_IPAddressChoice(IPAddressChoice *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressChoice_it); +} +LCRYPTO_ALIAS(i2d_IPAddressChoice); + +IPAddressChoice * +IPAddressChoice_new(void) +{ + return (IPAddressChoice *)ASN1_item_new(&IPAddressChoice_it); +} +LCRYPTO_ALIAS(IPAddressChoice_new); + +void +IPAddressChoice_free(IPAddressChoice *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &IPAddressChoice_it); +} +LCRYPTO_ALIAS(IPAddressChoice_free); + +IPAddressFamily * +d2i_IPAddressFamily(IPAddressFamily **a, const unsigned char **in, long len) +{ + return (IPAddressFamily *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &IPAddressFamily_it); +} +LCRYPTO_ALIAS(d2i_IPAddressFamily); + +int +i2d_IPAddressFamily(IPAddressFamily *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressFamily_it); +} +LCRYPTO_ALIAS(i2d_IPAddressFamily); + +IPAddressFamily * +IPAddressFamily_new(void) +{ + return (IPAddressFamily *)ASN1_item_new(&IPAddressFamily_it); +} +LCRYPTO_ALIAS(IPAddressFamily_new); + +void +IPAddressFamily_free(IPAddressFamily *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &IPAddressFamily_it); +} +LCRYPTO_ALIAS(IPAddressFamily_free); + +/* + * Convenience accessors for IPAddressFamily. + */ + +static int +IPAddressFamily_type(IPAddressFamily *af) +{ + /* XXX - can af->ipAddressChoice == NULL actually happen? */ + if (af == NULL || af->ipAddressChoice == NULL) + return -1; + + switch (af->ipAddressChoice->type) { + case IPAddressChoice_inherit: + case IPAddressChoice_addressesOrRanges: + return af->ipAddressChoice->type; + default: + return -1; + } +} + +static IPAddressOrRanges * +IPAddressFamily_addressesOrRanges(IPAddressFamily *af) +{ + if (IPAddressFamily_type(af) == IPAddressChoice_addressesOrRanges) + return af->ipAddressChoice->u.addressesOrRanges; + + return NULL; +} + +static ASN1_NULL * +IPAddressFamily_inheritance(IPAddressFamily *af) +{ + if (IPAddressFamily_type(af) == IPAddressChoice_inherit) + return af->ipAddressChoice->u.inherit; + + return NULL; +} + +static int +IPAddressFamily_set_inheritance(IPAddressFamily *af) +{ + if (IPAddressFamily_addressesOrRanges(af) != NULL) + return 0; + + if (IPAddressFamily_inheritance(af) != NULL) + return 1; + + if ((af->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL) + return 0; + af->ipAddressChoice->type = IPAddressChoice_inherit; + + return 1; +} + +/* + * How much buffer space do we need for a raw address? + */ +#define ADDR_RAW_BUF_LEN 16 + +/* + * What's the address length associated with this AFI? + */ +static int +length_from_afi(const unsigned afi, int *length) +{ + switch (afi) { + case IANA_AFI_IPV4: + *length = 4; + return 1; + case IANA_AFI_IPV6: + *length = 16; + return 1; + default: + *length = 0; + return 0; + } +} + +/* + * Get AFI and optional SAFI from an IPAddressFamily. All three out arguments + * are optional; if |out_safi| is non-NULL, |safi_is_set| must be non-NULL. + */ +static int +IPAddressFamily_afi_safi(const IPAddressFamily *af, uint16_t *out_afi, + uint8_t *out_safi, int *safi_is_set) +{ + CBS cbs; + uint16_t afi; + uint8_t safi = 0; + int got_safi = 0; + + if (out_afi != NULL) + *out_afi = 0; + if (out_safi != NULL) { + *out_safi = 0; + *safi_is_set = 0; + } + + CBS_init(&cbs, af->addressFamily->data, af->addressFamily->length); + + if (!CBS_get_u16(&cbs, &afi)) + return 0; + + if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6) + return 0; + + /* Fetch the optional SAFI. */ + if (CBS_len(&cbs) != 0) { + if (!CBS_get_u8(&cbs, &safi)) + return 0; + got_safi = 1; + } + + /* If there's anything left, it's garbage. */ + if (CBS_len(&cbs) != 0) + return 0; + + /* XXX - error on reserved AFI/SAFI? */ + + if (out_afi != NULL) + *out_afi = afi; + + if (out_safi != NULL) { + *out_safi = safi; + *safi_is_set = got_safi; + } + + return 1; +} + +static int +IPAddressFamily_afi(const IPAddressFamily *af, uint16_t *out_afi) +{ + return IPAddressFamily_afi_safi(af, out_afi, NULL, NULL); +} + +static int +IPAddressFamily_afi_is_valid(const IPAddressFamily *af) +{ + return IPAddressFamily_afi_safi(af, NULL, NULL, NULL); +} + +static int +IPAddressFamily_afi_length(const IPAddressFamily *af, int *out_length) +{ + uint16_t afi; + + *out_length = 0; + + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + return length_from_afi(afi, out_length); +} + +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) + +/* + * Sort comparison function for a sequence of IPAddressFamily. + * + * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about + * the ordering: I can read it as meaning that IPv6 without a SAFI + * comes before IPv4 with a SAFI, which seems pretty weird. The + * examples in appendix B suggest that the author intended the + * null-SAFI rule to apply only within a single AFI, which is what I + * would have expected and is what the following code implements. + */ +static int +IPAddressFamily_cmp(const IPAddressFamily *const *a_, + const IPAddressFamily *const *b_) +{ + const ASN1_OCTET_STRING *a = (*a_)->addressFamily; + const ASN1_OCTET_STRING *b = (*b_)->addressFamily; + int len, cmp; + + len = MINIMUM(a->length, b->length); + + if ((cmp = memcmp(a->data, b->data, len)) != 0) + return cmp; + + return a->length - b->length; +} + +static IPAddressFamily * +IPAddressFamily_find_in_parent(IPAddrBlocks *parent, IPAddressFamily *child_af) +{ + int index; + + (void)sk_IPAddressFamily_set_cmp_func(parent, IPAddressFamily_cmp); + + if ((index = sk_IPAddressFamily_find(parent, child_af)) < 0) + return NULL; + + return sk_IPAddressFamily_value(parent, index); +} + +/* + * Extract the AFI from an IPAddressFamily. + * + * This is public API. It uses the reserved AFI 0 as an in-band error + * while it doesn't care about the reserved AFI 65535... + */ +unsigned int +X509v3_addr_get_afi(const IPAddressFamily *af) +{ + uint16_t afi; + + /* + * XXX are these NULL checks really sensible? If af is non-NULL, it + * should have both addressFamily and ipAddressChoice... + */ + if (af == NULL || af->addressFamily == NULL || + af->addressFamily->data == NULL) + return 0; + + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + return afi; +} +LCRYPTO_ALIAS(X509v3_addr_get_afi); + +/* + * Expand the bitstring form (RFC 3779, section 2.1.2) of an address into + * a raw byte array. At the moment this is coded for simplicity, not speed. + * + * Unused bits in the last octet of |bs| and all bits in subsequent bytes + * of |addr| are set to 0 or 1 depending on whether |fill| is 0 or not. + */ +static int +addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, + uint8_t fill) +{ + if (bs->length < 0 || bs->length > length) + return 0; + + if (fill != 0) + fill = 0xff; + + if (bs->length > 0) { + /* XXX - shouldn't this check ASN1_STRING_FLAG_BITS_LEFT? */ + uint8_t unused_bits = bs->flags & 7; + uint8_t mask = (1 << unused_bits) - 1; + + memcpy(addr, bs->data, bs->length); + + if (fill == 0) + addr[bs->length - 1] &= ~mask; + else + addr[bs->length - 1] |= mask; + } + + memset(addr + bs->length, fill, length - bs->length); + + return 1; +} + +/* + * Extract the prefix length from a bitstring: 8 * length - unused bits. + */ +#define addr_prefix_len(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7))) + +/* + * i2r handler for one address bitstring. + */ +static int +i2r_address(BIO *out, const unsigned afi, const unsigned char fill, + const ASN1_BIT_STRING *bs) +{ + unsigned char addr[ADDR_RAW_BUF_LEN]; + int i, n; + + if (bs->length < 0) + return 0; + switch (afi) { + case IANA_AFI_IPV4: + if (!addr_expand(addr, bs, 4, fill)) + return 0; + BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], + addr[3]); + break; + case IANA_AFI_IPV6: + if (!addr_expand(addr, bs, 16, fill)) + return 0; + for (n = 16; + n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00; n -= 2) + continue; + for (i = 0; i < n; i += 2) + BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1], + (i < 14 ? ":" : "")); + if (i < 16) + BIO_puts(out, ":"); + if (i == 0) + BIO_puts(out, ":"); + break; + default: + for (i = 0; i < bs->length; i++) + BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""), + bs->data[i]); + BIO_printf(out, "[%d]", (int)(bs->flags & 7)); + break; + } + return 1; +} + +/* + * i2r handler for a sequence of addresses and ranges. + */ +static int +i2r_IPAddressOrRanges(BIO *out, const int indent, + const IPAddressOrRanges *aors, const unsigned afi) +{ + const IPAddressOrRange *aor; + const ASN1_BIT_STRING *prefix; + const IPAddressRange *range; + int i; + + for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) { + aor = sk_IPAddressOrRange_value(aors, i); + + BIO_printf(out, "%*s", indent, ""); + + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + prefix = aor->u.addressPrefix; + + if (!i2r_address(out, afi, 0x00, prefix)) + return 0; + BIO_printf(out, "/%d\n", addr_prefix_len(prefix)); + continue; + case IPAddressOrRange_addressRange: + range = aor->u.addressRange; + + if (!i2r_address(out, afi, 0x00, range->min)) + return 0; + BIO_puts(out, "-"); + if (!i2r_address(out, afi, 0xff, range->max)) + return 0; + BIO_puts(out, "\n"); + continue; + } + } + + return 1; +} + +/* + * i2r handler for an IPAddrBlocks extension. + */ +static int +i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, void *ext, BIO *out, + int indent) +{ + const IPAddrBlocks *addr = ext; + IPAddressFamily *af; + uint16_t afi; + uint8_t safi; + int i, safi_is_set; + + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + af = sk_IPAddressFamily_value(addr, i); + + if (!IPAddressFamily_afi_safi(af, &afi, &safi, &safi_is_set)) + goto print_addresses; + + switch (afi) { + case IANA_AFI_IPV4: + BIO_printf(out, "%*sIPv4", indent, ""); + break; + case IANA_AFI_IPV6: + BIO_printf(out, "%*sIPv6", indent, ""); + break; + default: + BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi); + break; + } + if (safi_is_set) { + switch (safi) { + case 1: + BIO_puts(out, " (Unicast)"); + break; + case 2: + BIO_puts(out, " (Multicast)"); + break; + case 3: + BIO_puts(out, " (Unicast/Multicast)"); + break; + case 4: + BIO_puts(out, " (MPLS)"); + break; + case 64: + BIO_puts(out, " (Tunnel)"); + break; + case 65: + BIO_puts(out, " (VPLS)"); + break; + case 66: + BIO_puts(out, " (BGP MDT)"); + break; + case 128: + BIO_puts(out, " (MPLS-labeled VPN)"); + break; + default: + BIO_printf(out, " (Unknown SAFI %u)", safi); + break; + } + } + + print_addresses: + switch (IPAddressFamily_type(af)) { + case IPAddressChoice_inherit: + BIO_puts(out, ": inherit\n"); + break; + case IPAddressChoice_addressesOrRanges: + BIO_puts(out, ":\n"); + if (!i2r_IPAddressOrRanges(out, indent + 2, + IPAddressFamily_addressesOrRanges(af), afi)) + return 0; + break; + /* XXX - how should we handle -1 here? */ + } + } + return 1; +} + +/* + * Sort comparison function for a sequence of IPAddressOrRange + * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. + */ +static int +IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, + const int length) +{ + unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN]; + int prefix_len_a = 0, prefix_len_b = 0; + int r; + + switch (a->type) { + case IPAddressOrRange_addressPrefix: + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; + prefix_len_a = addr_prefix_len(a->u.addressPrefix); + break; + case IPAddressOrRange_addressRange: + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; + prefix_len_a = length * 8; + break; + } + + switch (b->type) { + case IPAddressOrRange_addressPrefix: + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; + prefix_len_b = addr_prefix_len(b->u.addressPrefix); + break; + case IPAddressOrRange_addressRange: + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; + prefix_len_b = length * 8; + break; + } + + if ((r = memcmp(addr_a, addr_b, length)) != 0) + return r; + else + return prefix_len_a - prefix_len_b; +} + +/* + * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort() + * comparison routines are only allowed two arguments. + */ +static int +v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a, + const IPAddressOrRange *const *b) +{ + return IPAddressOrRange_cmp(*a, *b, 4); +} + +/* + * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort() + * comparison routines are only allowed two arguments. + */ +static int +v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a, + const IPAddressOrRange *const *b) +{ + return IPAddressOrRange_cmp(*a, *b, 16); +} + +/* + * Calculate whether a range collapses to a prefix. + * See last paragraph of RFC 3779 2.2.3.7. + * + * It's the caller's responsibility to ensure that min <= max. + */ +static int +range_should_be_prefix(const unsigned char *min, const unsigned char *max, + const int length) +{ + unsigned char mask; + int i, j; + + for (i = 0; i < length && min[i] == max[i]; i++) + continue; + for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xff; j--) + continue; + if (i < j) + return -1; + if (i > j) + return i * 8; + mask = min[i] ^ max[i]; + switch (mask) { + case 0x01: + j = 7; + break; + case 0x03: + j = 6; + break; + case 0x07: + j = 5; + break; + case 0x0f: + j = 4; + break; + case 0x1f: + j = 3; + break; + case 0x3f: + j = 2; + break; + case 0x7f: + j = 1; + break; + default: + return -1; + } + if ((min[i] & mask) != 0 || (max[i] & mask) != mask) + return -1; + else + return i * 8 + j; +} + +/* + * Fill IPAddressOrRange with bit string encoding of a prefix - RFC 3779, 2.1.1. + */ +static int +make_addressPrefix(IPAddressOrRange **out_aor, uint8_t *addr, uint32_t afi, + int prefix_len) +{ + IPAddressOrRange *aor = NULL; + int afi_len, num_bits, num_octets; + uint8_t unused_bits; + + if (prefix_len < 0) + goto err; + + if (!length_from_afi(afi, &afi_len)) + goto err; + if (prefix_len > 8 * afi_len) + goto err; + + num_octets = (prefix_len + 7) / 8; + num_bits = prefix_len % 8; + + unused_bits = 0; + if (num_bits > 0) + unused_bits = 8 - num_bits; + + if ((aor = IPAddressOrRange_new()) == NULL) + goto err; + + aor->type = IPAddressOrRange_addressPrefix; + + if ((aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL) + goto err; + if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, num_octets)) + goto err; + if (!asn1_abs_set_unused_bits(aor->u.addressPrefix, unused_bits)) + goto err; + + *out_aor = aor; + return 1; + + err: + IPAddressOrRange_free(aor); + return 0; +} + +static uint8_t +count_trailing_zeroes(uint8_t octet) +{ + uint8_t count = 0; + + if (octet == 0) + return 8; + + while ((octet & (1 << count)) == 0) + count++; + + return count; +} + +static int +trim_end_u8(CBS *cbs, uint8_t trim) +{ + uint8_t octet; + + while (CBS_len(cbs) > 0) { + if (!CBS_peek_last_u8(cbs, &octet)) + return 0; + if (octet != trim) + return 1; + if (!CBS_get_last_u8(cbs, &octet)) + return 0; + } + + return 1; +} + +/* + * Populate IPAddressOrRange with bit string encoding of a range, see + * RFC 3779, 2.1.2. + */ +static int +make_addressRange(IPAddressOrRange **out_aor, uint8_t *min, uint8_t *max, + uint32_t afi, int length) +{ + IPAddressOrRange *aor = NULL; + IPAddressRange *range; + int prefix_len; + CBS cbs; + size_t max_len, min_len; + uint8_t unused_bits_min, unused_bits_max; + uint8_t octet; + + if (memcmp(min, max, length) > 0) + goto err; + + /* + * RFC 3779, 2.2.3.6 - a range that can be expressed as a prefix + * must be encoded as a prefix. + */ + + if ((prefix_len = range_should_be_prefix(min, max, length)) >= 0) + return make_addressPrefix(out_aor, min, afi, prefix_len); + + /* + * The bit string representing min is formed by removing all its + * trailing zero bits, so remove all trailing zero octets and count + * the trailing zero bits of the last octet. + */ + + CBS_init(&cbs, min, length); + + if (!trim_end_u8(&cbs, 0x00)) + goto err; + + unused_bits_min = 0; + if ((min_len = CBS_len(&cbs)) > 0) { + if (!CBS_peek_last_u8(&cbs, &octet)) + goto err; + + unused_bits_min = count_trailing_zeroes(octet); + } + + /* + * The bit string representing max is formed by removing all its + * trailing one bits, so remove all trailing 0xff octets and count + * the trailing ones of the last octet. + */ + + CBS_init(&cbs, max, length); + + if (!trim_end_u8(&cbs, 0xff)) + goto err; + + unused_bits_max = 0; + if ((max_len = CBS_len(&cbs)) > 0) { + if (!CBS_peek_last_u8(&cbs, &octet)) + goto err; + + unused_bits_max = count_trailing_zeroes(octet + 1); + } + + /* + * Populate IPAddressOrRange. + */ + + if ((aor = IPAddressOrRange_new()) == NULL) + goto err; + + aor->type = IPAddressOrRange_addressRange; + + if ((range = aor->u.addressRange = IPAddressRange_new()) == NULL) + goto err; + + if (!ASN1_BIT_STRING_set(range->min, min, min_len)) + goto err; + if (!asn1_abs_set_unused_bits(range->min, unused_bits_min)) + goto err; + + if (!ASN1_BIT_STRING_set(range->max, max, max_len)) + goto err; + if (!asn1_abs_set_unused_bits(range->max, unused_bits_max)) + goto err; + + *out_aor = aor; + + return 1; + + err: + IPAddressOrRange_free(aor); + return 0; +} + +/* + * Construct a new address family or find an existing one. + */ +static IPAddressFamily * +make_IPAddressFamily(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi) +{ + IPAddressFamily *af = NULL; + CBB cbb; + CBS cbs; + uint8_t *key = NULL; + size_t keylen; + int i; + + if (!CBB_init(&cbb, 0)) + goto err; + + if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6) + goto err; + if (!CBB_add_u16(&cbb, afi)) + goto err; + + if (safi != NULL) { + if (*safi > 255) + goto err; + if (!CBB_add_u8(&cbb, *safi)) + goto err; + } + + if (!CBB_finish(&cbb, &key, &keylen)) + goto err; + + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + af = sk_IPAddressFamily_value(addr, i); + + CBS_init(&cbs, af->addressFamily->data, + af->addressFamily->length); + if (CBS_mem_equal(&cbs, key, keylen)) + goto done; + } + + if ((af = IPAddressFamily_new()) == NULL) + goto err; + if (!ASN1_OCTET_STRING_set(af->addressFamily, key, keylen)) + goto err; + if (!sk_IPAddressFamily_push(addr, af)) + goto err; + + done: + free(key); + + return af; + + err: + CBB_cleanup(&cbb); + free(key); + IPAddressFamily_free(af); + + return NULL; +} + +/* + * Add an inheritance element. + */ +int +X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi) +{ + IPAddressFamily *af; + + if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL) + return 0; + + return IPAddressFamily_set_inheritance(af); +} +LCRYPTO_ALIAS(X509v3_addr_add_inherit); + +/* + * Construct an IPAddressOrRange sequence, or return an existing one. + */ +static IPAddressOrRanges * +make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi) +{ + IPAddressFamily *af; + IPAddressOrRanges *aors = NULL; + + if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL) + return NULL; + + if (IPAddressFamily_inheritance(af) != NULL) + return NULL; + + if ((aors = IPAddressFamily_addressesOrRanges(af)) != NULL) + return aors; + + if ((aors = sk_IPAddressOrRange_new_null()) == NULL) + return NULL; + + switch (afi) { + case IANA_AFI_IPV4: + (void)sk_IPAddressOrRange_set_cmp_func(aors, + v4IPAddressOrRange_cmp); + break; + case IANA_AFI_IPV6: + (void)sk_IPAddressOrRange_set_cmp_func(aors, + v6IPAddressOrRange_cmp); + break; + } + + af->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; + af->ipAddressChoice->u.addressesOrRanges = aors; + + return aors; +} + +/* + * Add a prefix. + */ +int +X509v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *a, const int prefix_len) +{ + IPAddressOrRanges *aors; + IPAddressOrRange *aor; + + if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL) + return 0; + + if (!make_addressPrefix(&aor, a, afi, prefix_len)) + return 0; + + if (sk_IPAddressOrRange_push(aors, aor) <= 0) { + IPAddressOrRange_free(aor); + return 0; + } + + return 1; +} +LCRYPTO_ALIAS(X509v3_addr_add_prefix); + +/* + * Add a range. + */ +int +X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *min, unsigned char *max) +{ + IPAddressOrRanges *aors; + IPAddressOrRange *aor; + int length; + + if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL) + return 0; + + if (!length_from_afi(afi, &length)) + return 0; + + if (!make_addressRange(&aor, min, max, afi, length)) + return 0; + + if (sk_IPAddressOrRange_push(aors, aor) <= 0) { + IPAddressOrRange_free(aor); + return 0; + } + + return 1; +} +LCRYPTO_ALIAS(X509v3_addr_add_range); + +static int +extract_min_max_bitstr(IPAddressOrRange *aor, ASN1_BIT_STRING **out_min, + ASN1_BIT_STRING **out_max) +{ + switch (aor->type) { + case IPAddressOrRange_addressPrefix: + *out_min = *out_max = aor->u.addressPrefix; + return 1; + case IPAddressOrRange_addressRange: + *out_min = aor->u.addressRange->min; + *out_max = aor->u.addressRange->max; + return 1; + default: + return 0; + } +} + +/* + * Extract min and max values from an IPAddressOrRange. + */ +static int +extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, + int length) +{ + ASN1_BIT_STRING *min_bitstr, *max_bitstr; + + if (aor == NULL || min == NULL || max == NULL) + return 0; + + if (!extract_min_max_bitstr(aor, &min_bitstr, &max_bitstr)) + return 0; + + if (!addr_expand(min, min_bitstr, length, 0)) + return 0; + + return addr_expand(max, max_bitstr, length, 1); +} + +/* + * Public wrapper for extract_min_max(). + */ +int +X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, + unsigned char *min, unsigned char *max, const int length) +{ + int afi_len; + + if (!length_from_afi(afi, &afi_len)) + return 0; + + if (length < afi_len) + return 0; + + if (!extract_min_max(aor, min, max, afi_len)) + return 0; + + return afi_len; +} +LCRYPTO_ALIAS(X509v3_addr_get_range); + +/* + * Check whether an IPAddrBLocks is in canonical form. + */ +int +X509v3_addr_is_canonical(IPAddrBlocks *addr) +{ + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + IPAddressFamily *af; + IPAddressOrRanges *aors; + IPAddressOrRange *aor, *aor_a, *aor_b; + int i, j, k, length; + + /* + * Empty extension is canonical. + */ + if (addr == NULL) + return 1; + + /* + * Check whether the top-level list is in order. + */ + for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) { + const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i); + const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1); + + /* Check that both have valid AFIs before comparing them. */ + if (!IPAddressFamily_afi_is_valid(a)) + return 0; + if (!IPAddressFamily_afi_is_valid(b)) + return 0; + + if (IPAddressFamily_cmp(&a, &b) >= 0) + return 0; + } + + /* + * Top level's ok, now check each address family. + */ + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + af = sk_IPAddressFamily_value(addr, i); + + if (!IPAddressFamily_afi_length(af, &length)) + return 0; + + /* + * If this family has an inheritance element, it is canonical. + */ + if (IPAddressFamily_inheritance(af) != NULL) + continue; + + /* + * If this family has neither an inheritance element nor an + * addressesOrRanges, we don't know what this is. + */ + if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL) + return 0; + + if (sk_IPAddressOrRange_num(aors) == 0) + return 0; + + for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) { + aor_a = sk_IPAddressOrRange_value(aors, j); + aor_b = sk_IPAddressOrRange_value(aors, j + 1); + + if (!extract_min_max(aor_a, a_min, a_max, length) || + !extract_min_max(aor_b, b_min, b_max, length)) + return 0; + + /* + * Punt misordered list, overlapping start, or inverted + * range. + */ + if (memcmp(a_min, b_min, length) >= 0 || + memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; + + /* + * Punt if adjacent or overlapping. Check for adjacency + * by subtracting one from b_min first. + */ + for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--) + continue; + if (memcmp(a_max, b_min, length) >= 0) + return 0; + + /* + * Check for range that should be expressed as a prefix. + */ + if (aor_a->type == IPAddressOrRange_addressPrefix) + continue; + + if (range_should_be_prefix(a_min, a_max, length) >= 0) + return 0; + } + + /* + * Check final range to see if it's inverted or should be a + * prefix. + */ + aor = sk_IPAddressOrRange_value(aors, j); + if (aor->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(aor, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; + if (range_should_be_prefix(a_min, a_max, length) >= 0) + return 0; + } + } + + /* + * If we made it through all that, we're happy. + */ + return 1; +} +LCRYPTO_ALIAS(X509v3_addr_is_canonical); + +/* + * Whack an IPAddressOrRanges into canonical form. + */ +static int +IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi) +{ + IPAddressOrRange *a, *b, *merged; + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; + int i, j, length; + + if (!length_from_afi(afi, &length)) + return 0; + + /* + * Sort the IPAddressOrRanges sequence. + */ + sk_IPAddressOrRange_sort(aors); + + /* + * Clean up representation issues, punt on duplicates or overlaps. + */ + for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) { + a = sk_IPAddressOrRange_value(aors, i); + b = sk_IPAddressOrRange_value(aors, i + 1); + + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; + + /* + * Punt overlaps. + */ + if (memcmp(a_max, b_min, length) >= 0) + return 0; + + /* + * Merge if a and b are adjacent. We check for + * adjacency by subtracting one from b_min first. + */ + for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--) + continue; + + if (memcmp(a_max, b_min, length) != 0) + continue; + + if (!make_addressRange(&merged, a_min, b_max, afi, length)) + return 0; + sk_IPAddressOrRange_set(aors, i, merged); + (void)sk_IPAddressOrRange_delete(aors, i + 1); + IPAddressOrRange_free(a); + IPAddressOrRange_free(b); + i--; + } + + /* + * Check for inverted final range. + */ + a = sk_IPAddressOrRange_value(aors, i); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + + return 1; +} + +/* + * Whack an IPAddrBlocks extension into canonical form. + */ +int +X509v3_addr_canonize(IPAddrBlocks *addr) +{ + IPAddressFamily *af; + IPAddressOrRanges *aors; + uint16_t afi; + int i; + + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + af = sk_IPAddressFamily_value(addr, i); + + /* Check AFI/SAFI here - IPAddressFamily_cmp() can't error. */ + if (!IPAddressFamily_afi(af, &afi)) + return 0; + + if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL) + continue; + + if (!IPAddressOrRanges_canonize(aors, afi)) + return 0; + } + + (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); + sk_IPAddressFamily_sort(addr); + + return X509v3_addr_is_canonical(addr); +} +LCRYPTO_ALIAS(X509v3_addr_canonize); + +/* + * v2i handler for the IPAddrBlocks extension. + */ +static void * +v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE)*values) +{ + static const char v4addr_chars[] = "0123456789."; + static const char v6addr_chars[] = "0123456789.:abcdefABCDEF"; + IPAddrBlocks *addr = NULL; + char *s = NULL, *t; + int i; + + if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + CONF_VALUE *val = sk_CONF_VALUE_value(values, i); + unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN]; + unsigned afi, *safi = NULL, safi_; + const char *addr_chars = NULL; + const char *errstr; + int prefix_len, i1, i2, delim, length; + + if (!name_cmp(val->name, "IPv4")) { + afi = IANA_AFI_IPV4; + } else if (!name_cmp(val->name, "IPv6")) { + afi = IANA_AFI_IPV6; + } else if (!name_cmp(val->name, "IPv4-SAFI")) { + afi = IANA_AFI_IPV4; + safi = &safi_; + } else if (!name_cmp(val->name, "IPv6-SAFI")) { + afi = IANA_AFI_IPV6; + safi = &safi_; + } else { + X509V3error(X509V3_R_EXTENSION_NAME_ERROR); + X509V3_conf_err(val); + goto err; + } + + switch (afi) { + case IANA_AFI_IPV4: + addr_chars = v4addr_chars; + break; + case IANA_AFI_IPV6: + addr_chars = v6addr_chars; + break; + } + + if (!length_from_afi(afi, &length)) + goto err; + + /* + * Handle SAFI, if any, and strdup() so we can null-terminate + * the other input values. + */ + if (safi != NULL) { + unsigned long parsed_safi; + int saved_errno = errno; + + errno = 0; + parsed_safi = strtoul(val->value, &t, 0); + + /* Value must be present, then a tab, space or colon. */ + if (val->value[0] == '\0' || + (*t != '\t' && *t != ' ' && *t != ':')) { + X509V3error(X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + /* Range and overflow check. */ + if ((errno == ERANGE && parsed_safi == ULONG_MAX) || + parsed_safi > 0xff) { + X509V3error(X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + errno = saved_errno; + + *safi = parsed_safi; + + /* Check possible whitespace is followed by a colon. */ + t += strspn(t, " \t"); + if (*t != ':') { + X509V3error(X509V3_R_INVALID_SAFI); + X509V3_conf_err(val); + goto err; + } + + /* Skip over colon. */ + t++; + + /* Then over any trailing whitespace. */ + t += strspn(t, " \t"); + + s = strdup(t); + } else { + s = strdup(val->value); + } + if (s == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Check for inheritance. Not worth additional complexity to + * optimize this (seldom-used) case. + */ + if (strcmp(s, "inherit") == 0) { + if (!X509v3_addr_add_inherit(addr, afi, safi)) { + X509V3error(X509V3_R_INVALID_INHERITANCE); + X509V3_conf_err(val); + goto err; + } + free(s); + s = NULL; + continue; + } + + i1 = strspn(s, addr_chars); + i2 = i1 + strspn(s + i1, " \t"); + delim = s[i2++]; + s[i1] = '\0'; + + if (a2i_ipadd(min, s) != length) { + X509V3error(X509V3_R_INVALID_IPADDRESS); + X509V3_conf_err(val); + goto err; + } + + switch (delim) { + case '/': + /* length contains the size of the address in bytes. */ + if (length != 4 && length != 16) + goto err; + prefix_len = strtonum(s + i2, 0, 8 * length, &errstr); + if (errstr != NULL) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (!X509v3_addr_add_prefix(addr, afi, safi, min, + prefix_len)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + break; + case '-': + i1 = i2 + strspn(s + i2, " \t"); + i2 = i1 + strspn(s + i1, addr_chars); + if (i1 == i2 || s[i2] != '\0') { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (a2i_ipadd(max, s + i1) != length) { + X509V3error(X509V3_R_INVALID_IPADDRESS); + X509V3_conf_err(val); + goto err; + } + if (memcmp(min, max, length) > 0) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + if (!X509v3_addr_add_range(addr, afi, safi, min, max)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + break; + case '\0': + if (!X509v3_addr_add_prefix(addr, afi, safi, min, + length * 8)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + break; + default: + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } + + free(s); + s = NULL; + } + + /* + * Canonize the result, then we're done. + */ + if (!X509v3_addr_canonize(addr)) + goto err; + return addr; + + err: + free(s); + sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); + return NULL; +} + +/* + * OpenSSL dispatch + */ +const X509V3_EXT_METHOD v3_addr = { + .ext_nid = NID_sbgp_ipAddrBlock, + .ext_flags = 0, + .it = &IPAddrBlocks_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_IPAddrBlocks, + .i2r = i2r_IPAddrBlocks, + .r2i = NULL, + .usr_data = NULL, +}; + +/* + * Figure out whether extension uses inheritance. + */ +int +X509v3_addr_inherits(IPAddrBlocks *addr) +{ + IPAddressFamily *af; + int i; + + if (addr == NULL) + return 0; + + for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { + af = sk_IPAddressFamily_value(addr, i); + + if (IPAddressFamily_inheritance(af) != NULL) + return 1; + } + + return 0; +} +LCRYPTO_ALIAS(X509v3_addr_inherits); + +/* + * Figure out whether parent contains child. + * + * This only works correctly if both parent and child are in canonical form. + */ +static int +addr_contains(IPAddressOrRanges *parent, IPAddressOrRanges *child, int length) +{ + IPAddressOrRange *child_aor, *parent_aor; + uint8_t parent_min[ADDR_RAW_BUF_LEN], parent_max[ADDR_RAW_BUF_LEN]; + uint8_t child_min[ADDR_RAW_BUF_LEN], child_max[ADDR_RAW_BUF_LEN]; + int p, c; + + if (child == NULL || parent == child) + return 1; + if (parent == NULL) + return 0; + + p = 0; + for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { + child_aor = sk_IPAddressOrRange_value(child, c); + + if (!extract_min_max(child_aor, child_min, child_max, length)) + return 0; + + for (;; p++) { + if (p >= sk_IPAddressOrRange_num(parent)) + return 0; + + parent_aor = sk_IPAddressOrRange_value(parent, p); + + if (!extract_min_max(parent_aor, parent_min, parent_max, + length)) + return 0; + + if (memcmp(parent_max, child_max, length) < 0) + continue; + if (memcmp(parent_min, child_min, length) > 0) + return 0; + break; + } + } + + return 1; +} + +/* + * Test whether |child| is a subset of |parent|. + */ +int +X509v3_addr_subset(IPAddrBlocks *child, IPAddrBlocks *parent) +{ + IPAddressFamily *child_af, *parent_af; + IPAddressOrRanges *child_aor, *parent_aor; + int i, length; + + if (child == NULL || child == parent) + return 1; + if (parent == NULL) + return 0; + + if (X509v3_addr_inherits(child) || X509v3_addr_inherits(parent)) + return 0; + + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + parent_af = IPAddressFamily_find_in_parent(parent, child_af); + if (parent_af == NULL) + return 0; + + if (!IPAddressFamily_afi_length(parent_af, &length)) + return 0; + + child_aor = IPAddressFamily_addressesOrRanges(child_af); + parent_aor = IPAddressFamily_addressesOrRanges(parent_af); + + if (!addr_contains(parent_aor, child_aor, length)) + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509v3_addr_subset); + +static int +verify_error(X509_STORE_CTX *ctx, X509 *cert, int error, int depth) +{ + if (ctx == NULL) + return 0; + + ctx->current_cert = cert; + ctx->error = error; + ctx->error_depth = depth; + + return ctx->verify_cb(0, ctx); +} + +/* + * Core code for RFC 3779 2.3 path validation. + * + * Returns 1 for success, 0 on error. + * + * When returning 0, ctx->error MUST be set to an appropriate value other than + * X509_V_OK. + */ +static int +addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, + IPAddrBlocks *ext) +{ + IPAddrBlocks *child = NULL, *parent = NULL; + IPAddressFamily *child_af, *parent_af; + IPAddressOrRanges *child_aor, *parent_aor; + X509 *cert = NULL; + int depth = -1; + int i; + unsigned int length; + int ret = 1; + + /* We need a non-empty chain to test against. */ + if (sk_X509_num(chain) <= 0) + goto err; + /* We need either a store ctx or an extension to work with. */ + if (ctx == NULL && ext == NULL) + goto err; + /* If there is a store ctx, it needs a verify_cb. */ + if (ctx != NULL && ctx->verify_cb == NULL) + goto err; + + /* + * Figure out where to start. If we don't have an extension to check, + * (either extracted from the leaf or passed by the caller), we're done. + * Otherwise, check canonical form and set up for walking up the chain. + */ + if (ext == NULL) { + depth = 0; + cert = sk_X509_value(chain, depth); + if ((X509_get_extension_flags(cert) & EXFLAG_INVALID) != 0) + goto done; + if ((ext = cert->rfc3779_addr) == NULL) + goto done; + } else if (!X509v3_addr_is_canonical(ext)) { + if ((ret = verify_error(ctx, cert, + X509_V_ERR_INVALID_EXTENSION, depth)) == 0) + goto done; + } + + (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); + if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + if (ctx != NULL) + ctx->error = X509_V_ERR_OUT_OF_MEM; + ret = 0; + goto done; + } + + /* + * Now walk up the chain. No cert may list resources that its parent + * doesn't list. + */ + for (depth++; depth < sk_X509_num(chain); depth++) { + cert = sk_X509_value(chain, depth); + + if ((X509_get_extension_flags(cert) & EXFLAG_INVALID) != 0) { + if ((ret = verify_error(ctx, cert, + X509_V_ERR_INVALID_EXTENSION, depth)) == 0) + goto done; + } + + if ((parent = cert->rfc3779_addr) == NULL) { + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + if (IPAddressFamily_inheritance(child_af) != + NULL) + continue; + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + break; + } + continue; + } + + /* + * Check that the child's resources are covered by the parent. + * Each covered resource is replaced with the parent's resource + * covering it, so the next iteration will check that the + * parent's resources are covered by the grandparent. + */ + for (i = 0; i < sk_IPAddressFamily_num(child); i++) { + child_af = sk_IPAddressFamily_value(child, i); + + if ((parent_af = IPAddressFamily_find_in_parent(parent, + child_af)) == NULL) { + /* + * If we have no match in the parent and the + * child inherits, that's fine. + */ + if (IPAddressFamily_inheritance(child_af) != + NULL) + continue; + + /* Otherwise the child isn't covered. */ + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + break; + } + + /* Parent inherits, nothing to do. */ + if (IPAddressFamily_inheritance(parent_af) != NULL) + continue; + + /* Child inherits. Use parent's address family. */ + if (IPAddressFamily_inheritance(child_af) != NULL) { + sk_IPAddressFamily_set(child, i, parent_af); + continue; + } + + child_aor = IPAddressFamily_addressesOrRanges(child_af); + parent_aor = + IPAddressFamily_addressesOrRanges(parent_af); + + /* + * Child and parent are canonical and neither inherits. + * If either addressesOrRanges is NULL, something's + * very wrong. + */ + if (child_aor == NULL || parent_aor == NULL) + goto err; + + if (!IPAddressFamily_afi_length(child_af, &length)) + goto err; + + /* Now check containment and replace or error. */ + if (addr_contains(parent_aor, child_aor, length)) { + sk_IPAddressFamily_set(child, i, parent_af); + continue; + } + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + } + } + + /* + * Trust anchor can't inherit. + */ + if ((parent = cert->rfc3779_addr) != NULL) { + for (i = 0; i < sk_IPAddressFamily_num(parent); i++) { + parent_af = sk_IPAddressFamily_value(parent, i); + + if (IPAddressFamily_inheritance(parent_af) == NULL) + continue; + + if ((ret = verify_error(ctx, cert, + X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0) + goto done; + } + } + + done: + sk_IPAddressFamily_free(child); + return ret; + + err: + sk_IPAddressFamily_free(child); + + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + + return 0; +} + +/* + * RFC 3779 2.3 path validation -- called from X509_verify_cert(). + */ +int +X509v3_addr_validate_path(X509_STORE_CTX *ctx) +{ + if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + return addr_validate_path_internal(ctx, ctx->chain, NULL); +} +LCRYPTO_ALIAS(X509v3_addr_validate_path); + +/* + * RFC 3779 2.3 path validation of an extension. + * Test whether chain covers extension. + */ +int +X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, IPAddrBlocks *ext, + int allow_inheritance) +{ + if (ext == NULL) + return 1; + if (sk_X509_num(chain) <= 0) + return 0; + if (!allow_inheritance && X509v3_addr_inherits(ext)) + return 0; + return addr_validate_path_internal(NULL, chain, ext); +} +LCRYPTO_ALIAS(X509v3_addr_validate_resource_set); + +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/crypto/x509/x509_akey.c b/crypto/x509/x509_akey.c new file mode 100644 index 0000000..f8c7113 --- /dev/null +++ b/crypto/x509/x509_akey.c @@ -0,0 +1,237 @@ +/* $OpenBSD: x509_akey.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist); +static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_akey_id = { + .ext_nid = NID_authority_key_identifier, + .ext_flags = X509V3_EXT_MULTILINE, + .it = &AUTHORITY_KEYID_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_AUTHORITY_KEYID, + .v2i = (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static STACK_OF(CONF_VALUE) * +i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, AUTHORITY_KEYID *akeyid, + STACK_OF(CONF_VALUE) *extlist) +{ + STACK_OF(CONF_VALUE) *free_extlist = NULL; + char *tmpstr = NULL; + + if (extlist == NULL) { + if ((free_extlist = extlist = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + if (akeyid->keyid != NULL) { + if ((tmpstr = hex_to_string(akeyid->keyid->data, + akeyid->keyid->length)) == NULL) + goto err; + if (!X509V3_add_value("keyid", tmpstr, &extlist)) + goto err; + free(tmpstr); + tmpstr = NULL; + } + + if (akeyid->issuer != NULL) { + if ((extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, + extlist)) == NULL) + goto err; + } + + if (akeyid->serial != NULL) { + if ((tmpstr = hex_to_string(akeyid->serial->data, + akeyid->serial->length)) == NULL) + goto err; + if (!X509V3_add_value("serial", tmpstr, &extlist)) + goto err; + free(tmpstr); + tmpstr = NULL; + } + + if (sk_CONF_VALUE_num(extlist) <= 0) + goto err; + + return extlist; + + err: + free(tmpstr); + sk_CONF_VALUE_pop_free(free_extlist, X509V3_conf_free); + + return NULL; +} + +/* + * Currently two options: + * keyid: use the issuers subject keyid, the value 'always' means its is + * an error if the issuer certificate doesn't have a key id. + * issuer: use the issuers cert issuer and serial number. The default is + * to only use this if keyid is not present. With the option 'always' + * this is always included. + */ +static AUTHORITY_KEYID * +v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + char keyid = 0, issuer = 0; + int i; + CONF_VALUE *cnf; + ASN1_OCTET_STRING *ikeyid = NULL; + X509_NAME *isname = NULL; + STACK_OF(GENERAL_NAME) *gens = NULL; + GENERAL_NAME *gen = NULL; + ASN1_INTEGER *serial = NULL; + X509_EXTENSION *ext; + X509 *cert; + AUTHORITY_KEYID *akeyid = NULL; + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + cnf = sk_CONF_VALUE_value(values, i); + if (!strcmp(cnf->name, "keyid")) { + keyid = 1; + if (cnf->value && !strcmp(cnf->value, "always")) + keyid = 2; + } else if (!strcmp(cnf->name, "issuer")) { + issuer = 1; + if (cnf->value && !strcmp(cnf->value, "always")) + issuer = 2; + } else { + X509V3error(X509V3_R_UNKNOWN_OPTION); + ERR_asprintf_error_data("name=%s", cnf->name); + return NULL; + } + } + + if (!ctx || !ctx->issuer_cert) { + if (ctx && (ctx->flags == CTX_TEST)) + return AUTHORITY_KEYID_new(); + X509V3error(X509V3_R_NO_ISSUER_CERTIFICATE); + return NULL; + } + + cert = ctx->issuer_cert; + + if (keyid) { + i = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1); + if ((i >= 0) && (ext = X509_get_ext(cert, i))) + ikeyid = X509V3_EXT_d2i(ext); + if (keyid == 2 && !ikeyid) { + X509V3error(X509V3_R_UNABLE_TO_GET_ISSUER_KEYID); + return NULL; + } + } + + if ((issuer && !ikeyid) || (issuer == 2)) { + isname = X509_NAME_dup(X509_get_issuer_name(cert)); + serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + if (!isname || !serial) { + X509V3error(X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS); + goto err; + } + } + + if (!(akeyid = AUTHORITY_KEYID_new())) + goto err; + + if (isname) { + if (!(gens = sk_GENERAL_NAME_new_null()) || + !(gen = GENERAL_NAME_new()) || + !sk_GENERAL_NAME_push(gens, gen)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + gen->type = GEN_DIRNAME; + gen->d.dirn = isname; + } + + akeyid->issuer = gens; + akeyid->serial = serial; + akeyid->keyid = ikeyid; + + return akeyid; + + err: + AUTHORITY_KEYID_free(akeyid); + GENERAL_NAME_free(gen); + sk_GENERAL_NAME_free(gens); + X509_NAME_free(isname); + ASN1_INTEGER_free(serial); + ASN1_OCTET_STRING_free(ikeyid); + return NULL; +} diff --git a/crypto/x509/x509_akeya.c b/crypto/x509/x509_akeya.c new file mode 100644 index 0000000..52eca42 --- /dev/null +++ b/crypto/x509/x509_akeya.c @@ -0,0 +1,128 @@ +/* $OpenBSD: x509_akeya.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include + +static const ASN1_TEMPLATE AUTHORITY_KEYID_seq_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(AUTHORITY_KEYID, keyid), + .field_name = "keyid", + .item = &ASN1_OCTET_STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(AUTHORITY_KEYID, issuer), + .field_name = "issuer", + .item = &GENERAL_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 2, + .offset = offsetof(AUTHORITY_KEYID, serial), + .field_name = "serial", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM AUTHORITY_KEYID_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = AUTHORITY_KEYID_seq_tt, + .tcount = sizeof(AUTHORITY_KEYID_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(AUTHORITY_KEYID), + .sname = "AUTHORITY_KEYID", +}; + + +AUTHORITY_KEYID * +d2i_AUTHORITY_KEYID(AUTHORITY_KEYID **a, const unsigned char **in, long len) +{ + return (AUTHORITY_KEYID *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &AUTHORITY_KEYID_it); +} +LCRYPTO_ALIAS(d2i_AUTHORITY_KEYID); + +int +i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &AUTHORITY_KEYID_it); +} +LCRYPTO_ALIAS(i2d_AUTHORITY_KEYID); + +AUTHORITY_KEYID * +AUTHORITY_KEYID_new(void) +{ + return (AUTHORITY_KEYID *)ASN1_item_new(&AUTHORITY_KEYID_it); +} +LCRYPTO_ALIAS(AUTHORITY_KEYID_new); + +void +AUTHORITY_KEYID_free(AUTHORITY_KEYID *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &AUTHORITY_KEYID_it); +} +LCRYPTO_ALIAS(AUTHORITY_KEYID_free); diff --git a/crypto/x509/x509_alt.c b/crypto/x509/x509_alt.c new file mode 100644 index 0000000..59fa39f --- /dev/null +++ b/crypto/x509/x509_alt.c @@ -0,0 +1,782 @@ +/* $OpenBSD: x509_alt.c,v 1.16 2023/08/30 00:49:32 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include + +#include "x509_internal.h" + +static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); +static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); +static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); +static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); + +const X509V3_EXT_METHOD v3_alt[] = { + { + .ext_nid = NID_subject_alt_name, + .ext_flags = 0, + .it = &GENERAL_NAMES_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES, + .v2i = (X509V3_EXT_V2I)v2i_subject_alt, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_issuer_alt_name, + .ext_flags = 0, + .it = &GENERAL_NAMES_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES, + .v2i = (X509V3_EXT_V2I)v2i_issuer_alt, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_certificate_issuer, + .ext_flags = 0, + .it = &GENERAL_NAMES_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, +}; + +STACK_OF(CONF_VALUE) * +i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, GENERAL_NAMES *gens, + STACK_OF(CONF_VALUE) *ret) +{ + STACK_OF(CONF_VALUE) *free_ret = NULL; + GENERAL_NAME *gen; + int i; + + if (ret == NULL) { + if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + if ((gen = sk_GENERAL_NAME_value(gens, i)) == NULL) + goto err; + if ((ret = i2v_GENERAL_NAME(method, gen, ret)) == NULL) + goto err; + } + + return ret; + + err: + sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free); + + return NULL; +} +LCRYPTO_ALIAS(i2v_GENERAL_NAMES); + +STACK_OF(CONF_VALUE) * +i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, + STACK_OF(CONF_VALUE) *ret) +{ + STACK_OF(CONF_VALUE) *free_ret = NULL; + unsigned char *p; + char oline[256], htmp[5]; + int i; + + if (ret == NULL) { + if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + switch (gen->type) { + case GEN_OTHERNAME: + if (!X509V3_add_value("othername", "", &ret)) + goto err; + break; + + case GEN_X400: + if (!X509V3_add_value("X400Name", "", &ret)) + goto err; + break; + + case GEN_EDIPARTY: + if (!X509V3_add_value("EdiPartyName", "", &ret)) + goto err; + break; + + case GEN_EMAIL: + if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret)) + goto err; + break; + + case GEN_DNS: + if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret)) + goto err; + break; + + case GEN_URI: + if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret)) + goto err; + break; + + case GEN_DIRNAME: + if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL) + goto err; + if (!X509V3_add_value("DirName", oline, &ret)) + goto err; + break; + + case GEN_IPADD: /* XXX */ + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + (void) 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++) { + (void) snprintf(htmp, sizeof htmp, + "%X", p[0] << 8 | p[1]); + p += 2; + strlcat(oline, htmp, sizeof(oline)); + if (i != 7) + strlcat(oline, ":", sizeof(oline)); + } + } else { + if (!X509V3_add_value("IP Address", "", &ret)) + goto err; + break; + } + if (!X509V3_add_value("IP Address", oline, &ret)) + goto err; + break; + + case GEN_RID: + if (!i2t_ASN1_OBJECT(oline, 256, gen->d.rid)) + goto err; + if (!X509V3_add_value("Registered ID", oline, &ret)) + goto err; + break; + } + + return ret; + + err: + sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free); + + return NULL; +} +LCRYPTO_ALIAS(i2v_GENERAL_NAME); + +int +GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) +{ + unsigned char *p; + int i; + + switch (gen->type) { + case GEN_OTHERNAME: + BIO_printf(out, "othername:"); + break; + + case GEN_X400: + BIO_printf(out, "X400Name:"); + break; + + case GEN_EDIPARTY: + /* Maybe fix this: it is supported now */ + BIO_printf(out, "EdiPartyName:"); + break; + + case GEN_EMAIL: + BIO_printf(out, "email:%.*s", gen->d.ia5->length, + gen->d.ia5->data); + break; + + case GEN_DNS: + BIO_printf(out, "DNS:%.*s", gen->d.ia5->length, + gen->d.ia5->data); + break; + + case GEN_URI: + BIO_printf(out, "URI:%.*s", gen->d.ia5->length, + gen->d.ia5->data); + break; + + case GEN_DIRNAME: + BIO_printf(out, "DirName: "); + X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); + break; + + case GEN_IPADD: + p = gen->d.ip->data; + if (gen->d.ip->length == 4) + BIO_printf(out, "IP Address:%d.%d.%d.%d", + p[0], p[1], p[2], p[3]); + else if (gen->d.ip->length == 16) { + BIO_printf(out, "IP Address"); + for (i = 0; i < 8; i++) { + BIO_printf(out, ":%X", p[0] << 8 | p[1]); + p += 2; + } + BIO_puts(out, "\n"); + } else { + BIO_printf(out, "IP Address:"); + break; + } + break; + + case GEN_RID: + BIO_printf(out, "Registered ID"); + i2a_ASN1_OBJECT(out, gen->d.rid); + break; + } + return 1; +} +LCRYPTO_ALIAS(GENERAL_NAME_print); + +static GENERAL_NAMES * +v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + int i; + + if ((gens = sk_GENERAL_NAME_new_null()) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (name_cmp(cnf->name, "issuer") == 0 && cnf->value != NULL && + strcmp(cnf->value, "copy") == 0) { + if (!copy_issuer(ctx, gens)) + goto err; + } else { + GENERAL_NAME *gen; + if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) + goto err; + if (sk_GENERAL_NAME_push(gens, gen) == 0) { + GENERAL_NAME_free(gen); + goto err; + } + } + } + return gens; + +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Append subject altname of issuer to issuer alt name of subject */ + +static int +copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) +{ + GENERAL_NAMES *ialt = NULL; + GENERAL_NAME *gen = NULL; + X509_EXTENSION *ext; + int i; + int ret = 0; + + if (ctx && (ctx->flags == CTX_TEST)) + return 1; + if (!ctx || !ctx->issuer_cert) { + X509V3error(X509V3_R_NO_ISSUER_DETAILS); + goto err; + } + i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); + if (i < 0) + return 1; + if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || + !(ialt = X509V3_EXT_d2i(ext))) { + X509V3error(X509V3_R_ISSUER_DECODE_ERROR); + goto err; + } + + for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) { + GENERAL_NAME *val = sk_GENERAL_NAME_value(ialt, i); + + if ((gen = GENERAL_NAME_dup(val)) == NULL) + goto err; + if (!sk_GENERAL_NAME_push(gens, gen)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } + + ret = 1; + + err: + sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free); + GENERAL_NAME_free(gen); + + return ret; +} + +static GENERAL_NAMES * +v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + int i; + + if (!(gens = sk_GENERAL_NAME_new_null())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "copy")) { + if (!copy_email(ctx, gens, 0)) + goto err; + } else if (!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "move")) { + if (!copy_email(ctx, gens, 1)) + goto err; + } else { + GENERAL_NAME *gen; + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + if (sk_GENERAL_NAME_push(gens, gen) == 0) { + GENERAL_NAME_free(gen); + goto err; + } + } + } + return gens; + +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} + +/* Copy any email addresses in a certificate or request to + * GENERAL_NAMES + */ + +static int +copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) +{ + X509_NAME *nm; + ASN1_IA5STRING *email = NULL; + X509_NAME_ENTRY *ne; + GENERAL_NAME *gen = NULL; + int i; + + if (ctx != NULL && ctx->flags == CTX_TEST) + return 1; + if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { + X509V3error(X509V3_R_NO_SUBJECT_DETAILS); + goto err; + } + /* Find the subject name */ + if (ctx->subject_cert) + nm = X509_get_subject_name(ctx->subject_cert); + else + nm = X509_REQ_get_subject_name(ctx->subject_req); + + /* Now add any email address(es) to STACK */ + i = -1; + while ((i = X509_NAME_get_index_by_NID(nm, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(nm, i); + email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) { + X509_NAME_delete_entry(nm, i); + X509_NAME_ENTRY_free(ne); + i--; + } + if (!email || !(gen = GENERAL_NAME_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + gen->d.ia5 = email; + email = NULL; + gen->type = GEN_EMAIL; + if (!sk_GENERAL_NAME_push(gens, gen)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + gen = NULL; + } + + return 1; + +err: + GENERAL_NAME_free(gen); + ASN1_IA5STRING_free(email); + return 0; +} + +GENERAL_NAMES * +v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + GENERAL_NAME *gen; + GENERAL_NAMES *gens = NULL; + CONF_VALUE *cnf; + int i; + + if (!(gens = sk_GENERAL_NAME_new_null())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + if (sk_GENERAL_NAME_push(gens, gen) == 0) { + GENERAL_NAME_free(gen); + goto err; + } + } + return gens; + +err: + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return NULL; +} +LCRYPTO_ALIAS(v2i_GENERAL_NAMES); + +GENERAL_NAME * +v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf) +{ + return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); +} +LCRYPTO_ALIAS(v2i_GENERAL_NAME); + +GENERAL_NAME * +a2i_GENERAL_NAME(GENERAL_NAME *out, const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, int gen_type, const char *value, int is_nc) +{ + char is_string = 0; + GENERAL_NAME *gen = NULL; + + if (!value) { + X509V3error(X509V3_R_MISSING_VALUE); + return NULL; + } + + if (out) + gen = out; + else { + gen = GENERAL_NAME_new(); + if (gen == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + } + + switch (gen_type) { + case GEN_URI: + case GEN_EMAIL: + case GEN_DNS: + is_string = 1; + break; + + case GEN_RID: + { + ASN1_OBJECT *obj; + if (!(obj = OBJ_txt2obj(value, 0))) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("value=%s", value); + goto err; + } + gen->d.rid = obj; + } + break; + + case GEN_IPADD: + if (is_nc) + gen->d.ip = a2i_IPADDRESS_NC(value); + else + gen->d.ip = a2i_IPADDRESS(value); + if (gen->d.ip == NULL) { + X509V3error(X509V3_R_BAD_IP_ADDRESS); + ERR_asprintf_error_data("value=%s", value); + goto err; + } + break; + + case GEN_DIRNAME: + if (!do_dirname(gen, value, ctx)) { + X509V3error(X509V3_R_DIRNAME_ERROR); + goto err; + } + break; + + case GEN_OTHERNAME: + if (!do_othername(gen, value, ctx)) { + X509V3error(X509V3_R_OTHERNAME_ERROR); + goto err; + } + break; + + default: + X509V3error(X509V3_R_UNSUPPORTED_TYPE); + goto err; + } + + if (is_string) { + if (!(gen->d.ia5 = ASN1_IA5STRING_new()) || + !ASN1_STRING_set(gen->d.ia5, value, strlen(value))) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + } + + gen->type = gen_type; + + return gen; + +err: + if (out == NULL) + GENERAL_NAME_free(gen); + return NULL; +} +LCRYPTO_ALIAS(a2i_GENERAL_NAME); + +GENERAL_NAME * +v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) +{ + uint8_t *bytes = NULL; + char *name, *value; + GENERAL_NAME *ret; + size_t len = 0; + int type; + CBS cbs; + + name = cnf->name; + value = cnf->value; + + if (!value) { + X509V3error(X509V3_R_MISSING_VALUE); + return NULL; + } + + if (!name_cmp(name, "email")) + type = GEN_EMAIL; + else if (!name_cmp(name, "URI")) + type = GEN_URI; + else if (!name_cmp(name, "DNS")) + type = GEN_DNS; + else if (!name_cmp(name, "RID")) + type = GEN_RID; + else if (!name_cmp(name, "IP")) + type = GEN_IPADD; + else if (!name_cmp(name, "dirName")) + type = GEN_DIRNAME; + else if (!name_cmp(name, "otherName")) + type = GEN_OTHERNAME; + else { + X509V3error(X509V3_R_UNSUPPORTED_OPTION); + ERR_asprintf_error_data("name=%s", name); + return NULL; + } + + ret = a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + if (ret == NULL) + return NULL; + + /* + * Validate what we have for sanity. + */ + + if (is_nc) { + struct x509_constraints_name *constraints_name = NULL; + + if (!x509_constraints_validate(ret, &constraints_name, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s", name); + goto err; + } + x509_constraints_name_free(constraints_name); + return ret; + } + + type = x509_constraints_general_to_bytes(ret, &bytes, &len); + CBS_init(&cbs, bytes, len); + switch (type) { + case GEN_DNS: + if (!x509_constraints_valid_sandns(&cbs)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_URI: + if (!x509_constraints_uri_host(bytes, len, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_EMAIL: + if (!x509_constraints_parse_mailbox(&cbs, NULL)) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("name=%s value='%.*s'", name, + (int)len, bytes); + goto err; + } + break; + case GEN_IPADD: + if (len != 4 && len != 16) { + X509V3error(X509V3_R_BAD_IP_ADDRESS); + ERR_asprintf_error_data("name=%s len=%zu", name, len); + goto err; + } + break; + default: + break; + } + return ret; + err: + if (out == NULL) + GENERAL_NAME_free(ret); + return NULL; +} +LCRYPTO_ALIAS(v2i_GENERAL_NAME_ex); + +static int +do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) +{ + char *objtmp = NULL, *p; + int objlen; + + if (!(p = strchr(value, ';'))) + return 0; + if (!(gen->d.otherName = OTHERNAME_new())) + return 0; + /* Free this up because we will overwrite it. + * no need to free type_id because it is static + */ + ASN1_TYPE_free(gen->d.otherName->value); + if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) + return 0; + objlen = p - value; + objtmp = malloc(objlen + 1); + if (objtmp) { + strlcpy(objtmp, value, objlen + 1); + gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); + free(objtmp); + } else + gen->d.otherName->type_id = NULL; + if (!gen->d.otherName->type_id) + return 0; + return 1; +} + +static int +do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) +{ + int ret; + STACK_OF(CONF_VALUE) *sk; + X509_NAME *nm; + + if (!(nm = X509_NAME_new())) + return 0; + sk = X509V3_get_section(ctx, value); + if (!sk) { + X509V3error(X509V3_R_SECTION_NOT_FOUND); + ERR_asprintf_error_data("section=%s", value); + X509_NAME_free(nm); + return 0; + } + /* FIXME: should allow other character types... */ + ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); + if (!ret) + X509_NAME_free(nm); + gen->d.dirn = nm; + X509V3_section_free(ctx, sk); + + return ret; +} diff --git a/crypto/x509/x509_asid.c b/crypto/x509/x509_asid.c new file mode 100644 index 0000000..95b1acb --- /dev/null +++ b/crypto/x509/x509_asid.c @@ -0,0 +1,1203 @@ +/* $OpenBSD: x509_asid.c,v 1.40 2023/04/19 12:30:09 jsg Exp $ */ +/* + * Contributed to the OpenSSL Project by the American Registry for + * Internet Numbers ("ARIN"). + */ +/* ==================================================================== + * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + */ + +/* + * Implementation of RFC 3779 section 3.2. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +#ifndef OPENSSL_NO_RFC3779 + +static const ASN1_TEMPLATE ASRange_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(ASRange, min), + .field_name = "min", + .item = &ASN1_INTEGER_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(ASRange, max), + .field_name = "max", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM ASRange_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = ASRange_seq_tt, + .tcount = sizeof(ASRange_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ASRange), + .sname = "ASRange", +}; + +static const ASN1_TEMPLATE ASIdOrRange_ch_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(ASIdOrRange, u.id), + .field_name = "u.id", + .item = &ASN1_INTEGER_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(ASIdOrRange, u.range), + .field_name = "u.range", + .item = &ASRange_it, + }, +}; + +const ASN1_ITEM ASIdOrRange_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(ASIdOrRange, type), + .templates = ASIdOrRange_ch_tt, + .tcount = sizeof(ASIdOrRange_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ASIdOrRange), + .sname = "ASIdOrRange", +}; + +static const ASN1_TEMPLATE ASIdentifierChoice_ch_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(ASIdentifierChoice, u.inherit), + .field_name = "u.inherit", + .item = &ASN1_NULL_it, + }, + { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = offsetof(ASIdentifierChoice, u.asIdsOrRanges), + .field_name = "u.asIdsOrRanges", + .item = &ASIdOrRange_it, + }, +}; + +const ASN1_ITEM ASIdentifierChoice_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(ASIdentifierChoice, type), + .templates = ASIdentifierChoice_ch_tt, + .tcount = sizeof(ASIdentifierChoice_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ASIdentifierChoice), + .sname = "ASIdentifierChoice", +}; + +static const ASN1_TEMPLATE ASIdentifiers_seq_tt[] = { + { + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(ASIdentifiers, asnum), + .field_name = "asnum", + .item = &ASIdentifierChoice_it, + }, + { + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(ASIdentifiers, rdi), + .field_name = "rdi", + .item = &ASIdentifierChoice_it, + }, +}; + +const ASN1_ITEM ASIdentifiers_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = ASIdentifiers_seq_tt, + .tcount = sizeof(ASIdentifiers_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ASIdentifiers), + .sname = "ASIdentifiers", +}; + +ASRange * +d2i_ASRange(ASRange **a, const unsigned char **in, long len) +{ + return (ASRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASRange_it); +} +LCRYPTO_ALIAS(d2i_ASRange); + +int +i2d_ASRange(ASRange *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASRange_it); +} +LCRYPTO_ALIAS(i2d_ASRange); + +ASRange * +ASRange_new(void) +{ + return (ASRange *)ASN1_item_new(&ASRange_it); +} +LCRYPTO_ALIAS(ASRange_new); + +void +ASRange_free(ASRange *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASRange_it); +} +LCRYPTO_ALIAS(ASRange_free); + +ASIdOrRange * +d2i_ASIdOrRange(ASIdOrRange **a, const unsigned char **in, long len) +{ + return (ASIdOrRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASIdOrRange_it); +} +LCRYPTO_ALIAS(d2i_ASIdOrRange); + +int +i2d_ASIdOrRange(ASIdOrRange *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdOrRange_it); +} +LCRYPTO_ALIAS(i2d_ASIdOrRange); + +ASIdOrRange * +ASIdOrRange_new(void) +{ + return (ASIdOrRange *)ASN1_item_new(&ASIdOrRange_it); +} +LCRYPTO_ALIAS(ASIdOrRange_new); + +void +ASIdOrRange_free(ASIdOrRange *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASIdOrRange_it); +} +LCRYPTO_ALIAS(ASIdOrRange_free); + +ASIdentifierChoice * +d2i_ASIdentifierChoice(ASIdentifierChoice **a, const unsigned char **in, + long len) +{ + return (ASIdentifierChoice *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASIdentifierChoice_it); +} +LCRYPTO_ALIAS(d2i_ASIdentifierChoice); + +int +i2d_ASIdentifierChoice(ASIdentifierChoice *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdentifierChoice_it); +} +LCRYPTO_ALIAS(i2d_ASIdentifierChoice); + +ASIdentifierChoice * +ASIdentifierChoice_new(void) +{ + return (ASIdentifierChoice *)ASN1_item_new(&ASIdentifierChoice_it); +} +LCRYPTO_ALIAS(ASIdentifierChoice_new); + +void +ASIdentifierChoice_free(ASIdentifierChoice *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASIdentifierChoice_it); +} +LCRYPTO_ALIAS(ASIdentifierChoice_free); + +ASIdentifiers * +d2i_ASIdentifiers(ASIdentifiers **a, const unsigned char **in, long len) +{ + return (ASIdentifiers *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ASIdentifiers_it); +} +LCRYPTO_ALIAS(d2i_ASIdentifiers); + +int +i2d_ASIdentifiers(ASIdentifiers *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdentifiers_it); +} +LCRYPTO_ALIAS(i2d_ASIdentifiers); + +ASIdentifiers * +ASIdentifiers_new(void) +{ + return (ASIdentifiers *)ASN1_item_new(&ASIdentifiers_it); +} +LCRYPTO_ALIAS(ASIdentifiers_new); + +void +ASIdentifiers_free(ASIdentifiers *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ASIdentifiers_it); +} +LCRYPTO_ALIAS(ASIdentifiers_free); + +/* + * i2r method for an ASIdentifierChoice. + */ +static int +i2r_ASIdentifierChoice(BIO *out, ASIdentifierChoice *choice, int indent, + const char *msg) +{ + int i; + char *s; + if (choice == NULL) + return 1; + BIO_printf(out, "%*s%s:\n", indent, "", msg); + switch (choice->type) { + case ASIdentifierChoice_inherit: + BIO_printf(out, "%*sinherit\n", indent + 2, ""); + break; + case ASIdentifierChoice_asIdsOrRanges: + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); + i++) { + ASIdOrRange *aor = + sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); + switch (aor->type) { + case ASIdOrRange_id: + if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == + NULL) + return 0; + BIO_printf(out, "%*s%s\n", indent + 2, "", s); + free(s); + break; + case ASIdOrRange_range: + if ((s = i2s_ASN1_INTEGER(NULL, + aor->u.range->min)) == NULL) + return 0; + BIO_printf(out, "%*s%s-", indent + 2, "", s); + free(s); + if ((s = i2s_ASN1_INTEGER(NULL, + aor->u.range->max)) == NULL) + return 0; + BIO_printf(out, "%s\n", s); + free(s); + break; + default: + return 0; + } + } + break; + default: + return 0; + } + return 1; +} + +/* + * i2r method for an ASIdentifier extension. + */ +static int +i2r_ASIdentifiers(const X509V3_EXT_METHOD *method, void *ext, BIO *out, + int indent) +{ + ASIdentifiers *asid = ext; + return (i2r_ASIdentifierChoice(out, asid->asnum, indent, + "Autonomous System Numbers") && + i2r_ASIdentifierChoice(out, asid->rdi, indent, + "Routing Domain Identifiers")); +} + +/* + * Sort comparison function for a sequence of ASIdOrRange elements. + */ +static int +ASIdOrRange_cmp(const ASIdOrRange *const *a_, const ASIdOrRange *const *b_) +{ + const ASIdOrRange *a = *a_, *b = *b_; + + /* XXX: these asserts need to be replaced */ + OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || + (a->type == ASIdOrRange_range && a->u.range != NULL && + a->u.range->min != NULL && a->u.range->max != NULL)); + + OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || + (b->type == ASIdOrRange_range && b->u.range != NULL && + b->u.range->min != NULL && b->u.range->max != NULL)); + + if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) + return ASN1_INTEGER_cmp(a->u.id, b->u.id); + + if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { + int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); + return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, + b->u.range->max); + } + + if (a->type == ASIdOrRange_id) + return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); + else + return ASN1_INTEGER_cmp(a->u.range->min, b->u.id); +} + +/* + * Add an inherit element. + */ +int +X509v3_asid_add_inherit(ASIdentifiers *asid, int which) +{ + ASIdentifierChoice **choice; + if (asid == NULL) + return 0; + switch (which) { + case V3_ASID_ASNUM: + choice = &asid->asnum; + break; + case V3_ASID_RDI: + choice = &asid->rdi; + break; + default: + return 0; + } + if (*choice == NULL) { + if ((*choice = ASIdentifierChoice_new()) == NULL) + return 0; + if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) + return 0; + (*choice)->type = ASIdentifierChoice_inherit; + } + return (*choice)->type == ASIdentifierChoice_inherit; +} +LCRYPTO_ALIAS(X509v3_asid_add_inherit); + +/* + * Add an ID or range to an ASIdentifierChoice. + */ +int +X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min, + ASN1_INTEGER *max) +{ + ASIdentifierChoice **choice; + ASIdOrRange *aor; + if (asid == NULL) + return 0; + switch (which) { + case V3_ASID_ASNUM: + choice = &asid->asnum; + break; + case V3_ASID_RDI: + choice = &asid->rdi; + break; + default: + return 0; + } + if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) + return 0; + if (*choice == NULL) { + if ((*choice = ASIdentifierChoice_new()) == NULL) + return 0; + (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); + if ((*choice)->u.asIdsOrRanges == NULL) + return 0; + (*choice)->type = ASIdentifierChoice_asIdsOrRanges; + } + if ((aor = ASIdOrRange_new()) == NULL) + return 0; + if (max == NULL) { + aor->type = ASIdOrRange_id; + aor->u.id = min; + } else { + aor->type = ASIdOrRange_range; + if ((aor->u.range = ASRange_new()) == NULL) + goto err; + ASN1_INTEGER_free(aor->u.range->min); + aor->u.range->min = min; + ASN1_INTEGER_free(aor->u.range->max); + aor->u.range->max = max; + } + if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) + goto err; + return 1; + + err: + ASIdOrRange_free(aor); + return 0; +} +LCRYPTO_ALIAS(X509v3_asid_add_id_or_range); + +/* + * Extract min and max values from an ASIdOrRange. + */ +static int +extract_min_max(ASIdOrRange *aor, ASN1_INTEGER **min, ASN1_INTEGER **max) +{ + switch (aor->type) { + case ASIdOrRange_id: + *min = aor->u.id; + *max = aor->u.id; + return 1; + case ASIdOrRange_range: + *min = aor->u.range->min; + *max = aor->u.range->max; + return 1; + } + + return 0; +} + +/* + * Check whether an ASIdentifierChoice is in canonical form. + */ +static int +ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) +{ + ASN1_INTEGER *a_max_plus_one = NULL; + ASN1_INTEGER *orig; + BIGNUM *bn = NULL; + int i, ret = 0; + + /* + * Empty element or inheritance is canonical. + */ + if (choice == NULL || choice->type == ASIdentifierChoice_inherit) + return 1; + + /* + * If not a list, or if empty list, it's broken. + */ + if (choice->type != ASIdentifierChoice_asIdsOrRanges || + sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) + return 0; + + /* + * It's a list, check it. + */ + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i + 1); + ASN1_INTEGER *a_min = NULL, + *a_max = NULL, + *b_min = NULL, + *b_max = + NULL; + + if (!extract_min_max(a, &a_min, &a_max) || + !extract_min_max(b, &b_min, &b_max)) + goto done; + + /* + * Punt misordered list, overlapping start, or inverted range. + */ + if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || + ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; + + /* + * Calculate a_max + 1 to check for adjacency. + */ + if ((bn == NULL && (bn = BN_new()) == NULL) || + ASN1_INTEGER_to_BN(a_max, bn) == NULL || + !BN_add_word(bn, 1)) { + X509V3error(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; + X509V3error(ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * Punt if adjacent or overlapping. + */ + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) + goto done; + } + + /* + * Check for inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + if (!extract_min_max(a, &a_min, &a_max) || + ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + ret = 1; + + done: + ASN1_INTEGER_free(a_max_plus_one); + BN_free(bn); + return ret; +} + +/* + * Check whether an ASIdentifier extension is in canonical form. + */ +int +X509v3_asid_is_canonical(ASIdentifiers *asid) +{ + return (asid == NULL || + (ASIdentifierChoice_is_canonical(asid->asnum) && + ASIdentifierChoice_is_canonical(asid->rdi))); +} +LCRYPTO_ALIAS(X509v3_asid_is_canonical); + +/* + * Whack an ASIdentifierChoice into canonical form. + */ +static int +ASIdentifierChoice_canonize(ASIdentifierChoice *choice) +{ + ASN1_INTEGER *a_max_plus_one = NULL; + ASN1_INTEGER *orig; + BIGNUM *bn = NULL; + int i, ret = 0; + + /* + * Nothing to do for empty element or inheritance. + */ + if (choice == NULL || choice->type == ASIdentifierChoice_inherit) + return 1; + + /* + * If not a list, or if empty list, it's broken. + */ + if (choice->type != ASIdentifierChoice_asIdsOrRanges || + sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + return 0; + } + + /* + * We have a non-empty list. Sort it. + */ + sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); + + /* + * Now check for errors and suboptimal encoding, rejecting the + * former and fixing the latter. + */ + for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i); + ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i + 1); + ASN1_INTEGER *a_min = NULL, + *a_max = NULL, + *b_min = NULL, + *b_max = + NULL; + + if (!extract_min_max(a, &a_min, &a_max) || + !extract_min_max(b, &b_min, &b_max)) + goto done; + + /* + * Make sure we're properly sorted (paranoia). + */ + if (ASN1_INTEGER_cmp(a_min, b_min) > 0) + goto done; + + /* + * Punt inverted ranges. + */ + if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || + ASN1_INTEGER_cmp(b_min, b_max) > 0) + goto done; + + /* + * Check for overlaps. + */ + if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + goto done; + } + + /* + * Calculate a_max + 1 to check for adjacency. + */ + if ((bn == NULL && (bn = BN_new()) == NULL) || + ASN1_INTEGER_to_BN(a_max, bn) == NULL || + !BN_add_word(bn, 1)) { + X509V3error(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; + X509V3error(ERR_R_MALLOC_FAILURE); + goto done; + } + + /* + * If a and b are adjacent, merge them. + */ + if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { + ASRange *r; + switch (a->type) { + case ASIdOrRange_id: + if ((r = calloc(1, sizeof(*r))) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto done; + } + r->min = a_min; + r->max = b_max; + a->type = ASIdOrRange_range; + a->u.range = r; + break; + case ASIdOrRange_range: + ASN1_INTEGER_free(a->u.range->max); + a->u.range->max = b_max; + break; + } + switch (b->type) { + case ASIdOrRange_id: + b->u.id = NULL; + break; + case ASIdOrRange_range: + b->u.range->max = NULL; + break; + } + ASIdOrRange_free(b); + (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, + i + 1); + i--; + continue; + } + } + + /* + * Check for final inverted range. + */ + i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; + { + ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, + i); + ASN1_INTEGER *a_min, *a_max; + if (a != NULL && a->type == ASIdOrRange_range) { + if (!extract_min_max(a, &a_min, &a_max) || + ASN1_INTEGER_cmp(a_min, a_max) > 0) + goto done; + } + } + + /* Paranoia */ + if (!ASIdentifierChoice_is_canonical(choice)) + goto done; + + ret = 1; + + done: + ASN1_INTEGER_free(a_max_plus_one); + BN_free(bn); + return ret; +} + +/* + * Whack an ASIdentifier extension into canonical form. + */ +int +X509v3_asid_canonize(ASIdentifiers *asid) +{ + if (asid == NULL) + return 1; + + if (!ASIdentifierChoice_canonize(asid->asnum)) + return 0; + + return ASIdentifierChoice_canonize(asid->rdi); +} +LCRYPTO_ALIAS(X509v3_asid_canonize); + +/* + * v2i method for an ASIdentifier extension. + */ +static void * +v2i_ASIdentifiers(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE)*values) +{ + ASN1_INTEGER *min = NULL, *max = NULL; + ASIdentifiers *asid = NULL; + int i; + + if ((asid = ASIdentifiers_new()) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + CONF_VALUE *val = sk_CONF_VALUE_value(values, i); + int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0; + + /* + * Figure out whether this is an AS or an RDI. + */ + if (!name_cmp(val->name, "AS")) { + which = V3_ASID_ASNUM; + } else if (!name_cmp(val->name, "RDI")) { + which = V3_ASID_RDI; + } else { + X509V3error(X509V3_R_EXTENSION_NAME_ERROR); + X509V3_conf_err(val); + goto err; + } + + /* + * Handle inheritance. + */ + if (strcmp(val->value, "inherit") == 0) { + if (X509v3_asid_add_inherit(asid, which)) + continue; + X509V3error(X509V3_R_INVALID_INHERITANCE); + X509V3_conf_err(val); + goto err; + } + + /* + * Number, range, or mistake, pick it apart and figure out which + */ + i1 = strspn(val->value, "0123456789"); + if (val->value[i1] == '\0') { + is_range = 0; + } else { + is_range = 1; + i2 = i1 + strspn(val->value + i1, " \t"); + if (val->value[i2] != '-') { + X509V3error(X509V3_R_INVALID_ASNUMBER); + X509V3_conf_err(val); + goto err; + } + i2++; + i2 = i2 + strspn(val->value + i2, " \t"); + i3 = i2 + strspn(val->value + i2, "0123456789"); + if (val->value[i3] != '\0') { + X509V3error(X509V3_R_INVALID_ASRANGE); + X509V3_conf_err(val); + goto err; + } + } + + /* + * Syntax is ok, read and add it. + */ + if (!is_range) { + if (!X509V3_get_value_int(val, &min)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + } else { + char *s = strdup(val->value); + if (s == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + s[i1] = '\0'; + min = s2i_ASN1_INTEGER(NULL, s); + max = s2i_ASN1_INTEGER(NULL, s + i2); + free(s); + if (min == NULL || max == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + if (ASN1_INTEGER_cmp(min, max) > 0) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + goto err; + } + } + if (!X509v3_asid_add_id_or_range(asid, which, min, max)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + min = max = NULL; + } + + /* + * Canonize the result, then we're done. + */ + if (!X509v3_asid_canonize(asid)) + goto err; + return asid; + + err: + ASIdentifiers_free(asid); + ASN1_INTEGER_free(min); + ASN1_INTEGER_free(max); + return NULL; +} + +/* + * OpenSSL dispatch. + */ +const X509V3_EXT_METHOD v3_asid = { + .ext_nid = NID_sbgp_autonomousSysNum, + .ext_flags = 0, + .it = &ASIdentifiers_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_ASIdentifiers, + .i2r = i2r_ASIdentifiers, + .r2i = NULL, + .usr_data = NULL, +}; + +/* + * Figure out whether extension uses inheritance. + */ +int +X509v3_asid_inherits(ASIdentifiers *asid) +{ + if (asid == NULL) + return 0; + + if (asid->asnum != NULL) { + if (asid->asnum->type == ASIdentifierChoice_inherit) + return 1; + } + + if (asid->rdi != NULL) { + if (asid->rdi->type == ASIdentifierChoice_inherit) + return 1; + } + + return 0; +} +LCRYPTO_ALIAS(X509v3_asid_inherits); + +/* + * Figure out whether parent contains child. + */ +static int +asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child) +{ + ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL; + int p, c; + + if (child == NULL || parent == child) + return 1; + + if (parent == NULL) + return 0; + + p = 0; + for (c = 0; c < sk_ASIdOrRange_num(child); c++) { + if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, + &c_max)) + return 0; + for (;; p++) { + if (p >= sk_ASIdOrRange_num(parent)) + return 0; + if (!extract_min_max(sk_ASIdOrRange_value(parent, p), + &p_min, &p_max)) + return 0; + if (ASN1_INTEGER_cmp(p_max, c_max) < 0) + continue; + if (ASN1_INTEGER_cmp(p_min, c_min) > 0) + return 0; + break; + } + } + + return 1; +} + +/* + * Test whether child is a subset of parent. + */ +int +X509v3_asid_subset(ASIdentifiers *child, ASIdentifiers *parent) +{ + if (child == NULL || child == parent) + return 1; + + if (parent == NULL) + return 0; + + if (X509v3_asid_inherits(child) || X509v3_asid_inherits(parent)) + return 0; + + if (child->asnum != NULL) { + if (parent->asnum == NULL) + return 0; + + if (!asid_contains(parent->asnum->u.asIdsOrRanges, + child->asnum->u.asIdsOrRanges)) + return 0; + } + + if (child->rdi != NULL) { + if (parent->rdi == NULL) + return 0; + + if (!asid_contains(parent->rdi->u.asIdsOrRanges, + child->rdi->u.asIdsOrRanges)) + return 0; + } + + return 1; +} +LCRYPTO_ALIAS(X509v3_asid_subset); + +/* + * Validation error handling via callback. + */ +#define validation_err(_err_) \ + do { \ + if (ctx != NULL) { \ + ctx->error = _err_; \ + ctx->error_depth = i; \ + ctx->current_cert = x; \ + ret = ctx->verify_cb(0, ctx); \ + } else { \ + ret = 0; \ + } \ + if (!ret) \ + goto done; \ + } while (0) + +/* + * Core code for RFC 3779 3.3 path validation. + */ +static int +asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, + ASIdentifiers *ext) +{ + ASIdOrRanges *child_as = NULL, *child_rdi = NULL; + int i, ret = 1, inherit_as = 0, inherit_rdi = 0; + X509 *x; + + /* We need a non-empty chain to test against. */ + if (sk_X509_num(chain) <= 0) + goto err; + /* We need either a store ctx or an extension to work with. */ + if (ctx == NULL && ext == NULL) + goto err; + /* If there is a store ctx, it needs a verify_cb. */ + if (ctx != NULL && ctx->verify_cb == NULL) + goto err; + + /* + * Figure out where to start. If we don't have an extension to check, + * (either extracted from the leaf or passed by the caller), we're done. + * Otherwise, check canonical form and set up for walking up the chain. + */ + if (ext != NULL) { + i = -1; + x = NULL; + if (!X509v3_asid_is_canonical(ext)) + validation_err(X509_V_ERR_INVALID_EXTENSION); + } else { + i = 0; + x = sk_X509_value(chain, i); + if ((X509_get_extension_flags(x) & EXFLAG_INVALID) != 0) + goto done; + if ((ext = x->rfc3779_asid) == NULL) + goto done; + } + if (ext->asnum != NULL) { + switch (ext->asnum->type) { + case ASIdentifierChoice_inherit: + inherit_as = 1; + break; + case ASIdentifierChoice_asIdsOrRanges: + child_as = ext->asnum->u.asIdsOrRanges; + break; + } + } + if (ext->rdi != NULL) { + switch (ext->rdi->type) { + case ASIdentifierChoice_inherit: + inherit_rdi = 1; + break; + case ASIdentifierChoice_asIdsOrRanges: + child_rdi = ext->rdi->u.asIdsOrRanges; + break; + } + } + + /* + * Now walk up the chain. Extensions must be in canonical form, no + * cert may list resources that its parent doesn't list. + */ + for (i++; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + + if ((X509_get_extension_flags(x) & EXFLAG_INVALID) != 0) + validation_err(X509_V_ERR_INVALID_EXTENSION); + if (x->rfc3779_asid == NULL) { + if (child_as != NULL || child_rdi != NULL) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + continue; + } + if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + child_as = NULL; + inherit_as = 0; + } + if (x->rfc3779_asid->asnum != NULL && + x->rfc3779_asid->asnum->type == + ASIdentifierChoice_asIdsOrRanges) { + if (inherit_as || + asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, + child_as)) { + child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; + inherit_as = 0; + } else { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + child_rdi = NULL; + inherit_rdi = 0; + } + if (x->rfc3779_asid->rdi != NULL && + x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { + if (inherit_rdi || + asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, + child_rdi)) { + child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; + inherit_rdi = 0; + } else { + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + } + } + + /* + * Trust anchor can't inherit. + */ + + if (x == NULL) + goto err; + + if (x->rfc3779_asid != NULL) { + if (x->rfc3779_asid->asnum != NULL && + x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + if (x->rfc3779_asid->rdi != NULL && + x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) + validation_err(X509_V_ERR_UNNESTED_RESOURCE); + } + + done: + return ret; + + err: + if (ctx != NULL) + ctx->error = X509_V_ERR_UNSPECIFIED; + + return 0; +} + +#undef validation_err + +/* + * RFC 3779 3.3 path validation -- called from X509_verify_cert(). + */ +int +X509v3_asid_validate_path(X509_STORE_CTX *ctx) +{ + if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + return asid_validate_path_internal(ctx, ctx->chain, NULL); +} +LCRYPTO_ALIAS(X509v3_asid_validate_path); + +/* + * RFC 3779 3.3 path validation of an extension. + * Test whether chain covers extension. + */ +int +X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, ASIdentifiers *ext, + int allow_inheritance) +{ + if (ext == NULL) + return 1; + if (sk_X509_num(chain) <= 0) + return 0; + if (!allow_inheritance && X509v3_asid_inherits(ext)) + return 0; + return asid_validate_path_internal(NULL, chain, ext); +} +LCRYPTO_ALIAS(X509v3_asid_validate_resource_set); + +#endif /* OPENSSL_NO_RFC3779 */ diff --git a/crypto/x509/x509_att.c b/crypto/x509/x509_att.c new file mode 100644 index 0000000..0c9d55f --- /dev/null +++ b/crypto/x509/x509_att.c @@ -0,0 +1,413 @@ +/* $OpenBSD: x509_att.c,v 1.22 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +int +X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x) +{ + return sk_X509_ATTRIBUTE_num(x); +} +LCRYPTO_ALIAS(X509at_get_attr_count); + +int +X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, int lastpos) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509at_get_attr_by_OBJ(x, obj, lastpos)); +} +LCRYPTO_ALIAS(X509at_get_attr_by_NID); + +int +X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_ATTRIBUTE *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_ATTRIBUTE_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_ATTRIBUTE_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return (lastpos); + } + return (-1); +} +LCRYPTO_ALIAS(X509at_get_attr_by_OBJ); + +X509_ATTRIBUTE * +X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return NULL; + else + return sk_X509_ATTRIBUTE_value(x, loc); +} +LCRYPTO_ALIAS(X509at_get_attr); + +X509_ATTRIBUTE * +X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc) +{ + X509_ATTRIBUTE *ret; + + if (x == NULL || sk_X509_ATTRIBUTE_num(x) <= loc || loc < 0) + return (NULL); + ret = sk_X509_ATTRIBUTE_delete(x, loc); + return (ret); +} +LCRYPTO_ALIAS(X509at_delete_attr); + +STACK_OF(X509_ATTRIBUTE) * +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) { + X509error(ERR_R_PASSED_NULL_PARAMETER); + return (NULL); + } + + if (*x == NULL) { + if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL) + goto err; + } else + sk = *x; + + if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL) + goto err2; + if (!sk_X509_ATTRIBUTE_push(sk, new_attr)) + goto err; + if (*x == NULL) + *x = sk; + return (sk); + +err: + X509error(ERR_R_MALLOC_FAILURE); +err2: + if (new_attr != NULL) + X509_ATTRIBUTE_free(new_attr); + if (sk != NULL && sk != *x) + sk_X509_ATTRIBUTE_free(sk); + return (NULL); +} +LCRYPTO_ALIAS(X509at_add1_attr); + +STACK_OF(X509_ATTRIBUTE) * +X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, const ASN1_OBJECT *obj, + int type, const unsigned char *bytes, int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + + attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} +LCRYPTO_ALIAS(X509at_add1_attr_by_OBJ); + +STACK_OF(X509_ATTRIBUTE) * +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_NID(NULL, nid, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} +LCRYPTO_ALIAS(X509at_add1_attr_by_NID); + +STACK_OF(X509_ATTRIBUTE) * +X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, const char *attrname, + int type, const unsigned char *bytes, int len) +{ + X509_ATTRIBUTE *attr; + STACK_OF(X509_ATTRIBUTE) *ret; + + attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len); + if (!attr) + return 0; + ret = X509at_add1_attr(x, attr); + X509_ATTRIBUTE_free(attr); + return ret; +} +LCRYPTO_ALIAS(X509at_add1_attr_by_txt); + +void * +X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, const ASN1_OBJECT *obj, + int lastpos, int type) +{ + int i; + X509_ATTRIBUTE *at; + + i = X509at_get_attr_by_OBJ(x, obj, lastpos); + if (i == -1) + return NULL; + if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1)) + return NULL; + at = X509at_get_attr(x, i); + if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1)) + return NULL; + return X509_ATTRIBUTE_get0_data(at, 0, type, NULL); +} +LCRYPTO_ALIAS(X509at_get0_data_by_OBJ); + +X509_ATTRIBUTE * +X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, int atrtype, + const void *data, int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *ret; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509error(X509_R_UNKNOWN_NID); + return (NULL); + } + ret = X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len); + if (ret == NULL) + ASN1_OBJECT_free(obj); + return (ret); +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_create_by_NID); + +X509_ATTRIBUTE * +X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, const ASN1_OBJECT *obj, + int atrtype, const void *data, int len) +{ + X509_ATTRIBUTE *ret; + + if ((attr == NULL) || (*attr == NULL)) { + if ((ret = X509_ATTRIBUTE_new()) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else + ret= *attr; + + if (!X509_ATTRIBUTE_set1_object(ret, obj)) + goto err; + if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len)) + goto err; + + if ((attr != NULL) && (*attr == NULL)) + *attr = ret; + return (ret); + +err: + if ((attr == NULL) || (ret != *attr)) + X509_ATTRIBUTE_free(ret); + return (NULL); +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_create_by_OBJ); + +X509_ATTRIBUTE * +X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, const char *atrname, + int type, const unsigned char *bytes, int len) +{ + ASN1_OBJECT *obj; + X509_ATTRIBUTE *nattr; + + obj = OBJ_txt2obj(atrname, 0); + if (obj == NULL) { + X509error(X509_R_INVALID_FIELD_NAME); + ERR_asprintf_error_data("name=%s", atrname); + return (NULL); + } + nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nattr; +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_create_by_txt); + +int +X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj) +{ + if ((attr == NULL) || (obj == NULL)) + return (0); + ASN1_OBJECT_free(attr->object); + attr->object = OBJ_dup(obj); + return attr->object != NULL; +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_set1_object); + +int +X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, + int len) +{ + ASN1_TYPE *ttmp = NULL; + ASN1_STRING *stmp = NULL; + int atype = 0; + + if (!attr) + return 0; + if (attrtype & MBSTRING_FLAG) { + stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype, + OBJ_obj2nid(attr->object)); + if (!stmp) { + X509error(ERR_R_ASN1_LIB); + return 0; + } + atype = stmp->type; + } else if (len != -1){ + if (!(stmp = ASN1_STRING_type_new(attrtype))) + goto err; + if (!ASN1_STRING_set(stmp, data, len)) + goto err; + atype = attrtype; + } + /* + * This is a bit naughty because the attribute should really have + * at least one value but some types use and zero length SET and + * require this. + */ + if (attrtype == 0) { + ASN1_STRING_free(stmp); + return 1; + } + + if (!(ttmp = ASN1_TYPE_new())) + goto err; + if ((len == -1) && !(attrtype & MBSTRING_FLAG)) { + if (!ASN1_TYPE_set1(ttmp, attrtype, data)) + goto err; + } else + ASN1_TYPE_set(ttmp, atype, stmp); + if (!sk_ASN1_TYPE_push(attr->set, ttmp)) + goto err; + return 1; + +err: + ASN1_TYPE_free(ttmp); + ASN1_STRING_free(stmp); + X509error(ERR_R_MALLOC_FAILURE); + return 0; +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_set1_data); + +int +X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr) +{ + if (attr == NULL) + return 0; + + return sk_ASN1_TYPE_num(attr->set); +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_count); + +ASN1_OBJECT * +X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr) +{ + if (attr == NULL) + return (NULL); + return (attr->object); +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_get0_object); + +void * +X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, int atrtype, void *data) +{ + ASN1_TYPE *ttmp; + + ttmp = X509_ATTRIBUTE_get0_type(attr, idx); + if (!ttmp) + return NULL; + if (atrtype != ASN1_TYPE_get(ttmp)){ + X509error(X509_R_WRONG_TYPE); + return NULL; + } + return ttmp->value.ptr; +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_get0_data); + +ASN1_TYPE * +X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx) +{ + if (attr == NULL) + return (NULL); + + return sk_ASN1_TYPE_value(attr->set, idx); +} +LCRYPTO_ALIAS(X509_ATTRIBUTE_get0_type); diff --git a/crypto/x509/x509_bcons.c b/crypto/x509/x509_bcons.c new file mode 100644 index 0000000..a39ae0a --- /dev/null +++ b/crypto/x509/x509_bcons.c @@ -0,0 +1,203 @@ +/* $OpenBSD: x509_bcons.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist); +static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_bcons = { + .ext_nid = NID_basic_constraints, + .ext_flags = 0, + .it = &BASIC_CONSTRAINTS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS, + .v2i = (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE BASIC_CONSTRAINTS_seq_tt[] = { + { + .flags = ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(BASIC_CONSTRAINTS, ca), + .field_name = "ca", + .item = &ASN1_FBOOLEAN_it, + }, + { + .flags = ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(BASIC_CONSTRAINTS, pathlen), + .field_name = "pathlen", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM BASIC_CONSTRAINTS_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = BASIC_CONSTRAINTS_seq_tt, + .tcount = sizeof(BASIC_CONSTRAINTS_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(BASIC_CONSTRAINTS), + .sname = "BASIC_CONSTRAINTS", +}; + + +BASIC_CONSTRAINTS * +d2i_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS **a, const unsigned char **in, long len) +{ + return (BASIC_CONSTRAINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &BASIC_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(d2i_BASIC_CONSTRAINTS); + +int +i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &BASIC_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(i2d_BASIC_CONSTRAINTS); + +BASIC_CONSTRAINTS * +BASIC_CONSTRAINTS_new(void) +{ + return (BASIC_CONSTRAINTS *)ASN1_item_new(&BASIC_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(BASIC_CONSTRAINTS_new); + +void +BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &BASIC_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(BASIC_CONSTRAINTS_free); + + +static STACK_OF(CONF_VALUE) * +i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, + STACK_OF(CONF_VALUE) *extlist) +{ + STACK_OF(CONF_VALUE) *free_extlist = NULL; + + if (extlist == NULL) { + if ((free_extlist = extlist = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + if (!X509V3_add_value_bool("CA", bcons->ca, &extlist)) + goto err; + if (!X509V3_add_value_int("pathlen", bcons->pathlen, &extlist)) + goto err; + + return extlist; + + err: + sk_CONF_VALUE_pop_free(free_extlist, X509V3_conf_free); + + return NULL; +} + +static BASIC_CONSTRAINTS * +v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + BASIC_CONSTRAINTS *bcons = NULL; + CONF_VALUE *val; + int i; + + if (!(bcons = BASIC_CONSTRAINTS_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "CA")) { + if (!X509V3_get_value_bool(val, &bcons->ca)) + goto err; + } else if (!strcmp(val->name, "pathlen")) { + if (!X509V3_get_value_int(val, &bcons->pathlen)) + goto err; + } else { + X509V3error(X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + return bcons; + +err: + BASIC_CONSTRAINTS_free(bcons); + return NULL; +} diff --git a/crypto/x509/x509_bitst.c b/crypto/x509/x509_bitst.c new file mode 100644 index 0000000..97c630d --- /dev/null +++ b/crypto/x509/x509_bitst.c @@ -0,0 +1,220 @@ +/* $OpenBSD: x509_bitst.c,v 1.4 2023/04/21 06:11:56 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include + +static BIT_STRING_BITNAME ns_cert_type_table[] = { + {0, "SSL Client", "client"}, + {1, "SSL Server", "server"}, + {2, "S/MIME", "email"}, + {3, "Object Signing", "objsign"}, + {4, "Unused", "reserved"}, + {5, "SSL CA", "sslCA"}, + {6, "S/MIME CA", "emailCA"}, + {7, "Object Signing CA", "objCA"}, + {-1, NULL, NULL} +}; + +static BIT_STRING_BITNAME key_usage_type_table[] = { + {0, "Digital Signature", "digitalSignature"}, + {1, "Non Repudiation", "nonRepudiation"}, + {2, "Key Encipherment", "keyEncipherment"}, + {3, "Data Encipherment", "dataEncipherment"}, + {4, "Key Agreement", "keyAgreement"}, + {5, "Certificate Sign", "keyCertSign"}, + {6, "CRL Sign", "cRLSign"}, + {7, "Encipher Only", "encipherOnly"}, + {8, "Decipher Only", "decipherOnly"}, + {-1, NULL, NULL} +}; + +static BIT_STRING_BITNAME crl_reasons[] = { + {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"}, + {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"}, + {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"}, + {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"}, + {CRL_REASON_SUPERSEDED, "Superseded", "superseded"}, + {CRL_REASON_CESSATION_OF_OPERATION, "Cessation Of Operation", "cessationOfOperation"}, + {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"}, + {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"}, + {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"}, + {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +const X509V3_EXT_METHOD v3_nscert = { + .ext_nid = NID_netscape_cert_type, + .ext_flags = 0, + .it = &ASN1_BIT_STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, + .v2i = (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, + .i2r = NULL, + .r2i = NULL, + .usr_data = ns_cert_type_table, +}; + +const X509V3_EXT_METHOD v3_key_usage = { + .ext_nid = NID_key_usage, + .ext_flags = 0, + .it = &ASN1_BIT_STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, + .v2i = (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, + .i2r = NULL, + .r2i = NULL, + .usr_data = key_usage_type_table, +}; + +const X509V3_EXT_METHOD v3_crl_reason = { + .ext_nid = NID_crl_reason, + .ext_flags = 0, + .it = &ASN1_ENUMERATED_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = crl_reasons, +}; + +STACK_OF(CONF_VALUE) * +i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *ret) +{ + BIT_STRING_BITNAME *bnam; + STACK_OF(CONF_VALUE) *free_ret = NULL; + + if (ret == NULL) { + if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + for (bnam = method->usr_data; bnam->lname != NULL; bnam++) { + if (!ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) + continue; + if (!X509V3_add_value(bnam->lname, NULL, &ret)) + goto err; + } + + return ret; + + err: + sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free); + + return NULL; +} +LCRYPTO_ALIAS(i2v_ASN1_BIT_STRING); + +ASN1_BIT_STRING * +v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + CONF_VALUE *val; + ASN1_BIT_STRING *bs; + int i; + BIT_STRING_BITNAME *bnam; + + if (!(bs = ASN1_BIT_STRING_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + for (bnam = method->usr_data; bnam->lname; bnam++) { + if (!strcmp(bnam->sname, val->name) || + !strcmp(bnam->lname, val->name) ) { + if (!ASN1_BIT_STRING_set_bit(bs, + bnam->bitnum, 1)) { + X509V3error(ERR_R_MALLOC_FAILURE); + ASN1_BIT_STRING_free(bs); + return NULL; + } + break; + } + } + if (!bnam->lname) { + X509V3error(X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT); + X509V3_conf_err(val); + ASN1_BIT_STRING_free(bs); + return NULL; + } + } + return bs; +} +LCRYPTO_ALIAS(v2i_ASN1_BIT_STRING); diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c new file mode 100644 index 0000000..3ee4fd4 --- /dev/null +++ b/crypto/x509/x509_cmp.c @@ -0,0 +1,425 @@ +/* $OpenBSD: x509_cmp.c,v 1.42 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "evp_local.h" +#include "x509_local.h" + +int +X509_issuer_and_serial_cmp(const X509 *a, const X509 *b) +{ + int i; + X509_CINF *ai, *bi; + + ai = a->cert_info; + bi = b->cert_info; + i = ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber); + if (i) + return (i); + return (X509_NAME_cmp(ai->issuer, bi->issuer)); +} +LCRYPTO_ALIAS(X509_issuer_and_serial_cmp); + +#ifndef OPENSSL_NO_MD5 +unsigned long +X509_issuer_and_serial_hash(X509 *a) +{ + unsigned long ret = 0; + EVP_MD_CTX ctx; + unsigned char md[16]; + char *f; + + EVP_MD_CTX_init(&ctx); + f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0); + if (f == NULL) + goto err; + if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL)) + goto err; + if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f))) + goto err; + free(f); + f = NULL; + if (!EVP_DigestUpdate(&ctx, + (unsigned char *)a->cert_info->serialNumber->data, + (unsigned long)a->cert_info->serialNumber->length)) + goto err; + if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL)) + goto err; + ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) | + ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) & + 0xffffffffL; + +err: + EVP_MD_CTX_cleanup(&ctx); + free(f); + return (ret); +} +LCRYPTO_ALIAS(X509_issuer_and_serial_hash); +#endif + +int +X509_issuer_name_cmp(const X509 *a, const X509 *b) +{ + return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer)); +} +LCRYPTO_ALIAS(X509_issuer_name_cmp); + +int +X509_subject_name_cmp(const X509 *a, const X509 *b) +{ + return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject)); +} +LCRYPTO_ALIAS(X509_subject_name_cmp); + +int +X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b) +{ + return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer)); +} +LCRYPTO_ALIAS(X509_CRL_cmp); + +#ifndef OPENSSL_NO_SHA +int +X509_CRL_match(const X509_CRL *a, const X509_CRL *b) +{ + return memcmp(a->hash, b->hash, X509_CRL_HASH_LEN); +} +LCRYPTO_ALIAS(X509_CRL_match); +#endif + +X509_NAME * +X509_get_issuer_name(const X509 *a) +{ + return (a->cert_info->issuer); +} +LCRYPTO_ALIAS(X509_get_issuer_name); + +unsigned long +X509_issuer_name_hash(X509 *x) +{ + return (X509_NAME_hash(x->cert_info->issuer)); +} +LCRYPTO_ALIAS(X509_issuer_name_hash); + +#ifndef OPENSSL_NO_MD5 +unsigned long +X509_issuer_name_hash_old(X509 *x) +{ + return (X509_NAME_hash_old(x->cert_info->issuer)); +} +LCRYPTO_ALIAS(X509_issuer_name_hash_old); +#endif + +X509_NAME * +X509_get_subject_name(const X509 *a) +{ + return (a->cert_info->subject); +} +LCRYPTO_ALIAS(X509_get_subject_name); + +ASN1_INTEGER * +X509_get_serialNumber(X509 *a) +{ + return (a->cert_info->serialNumber); +} +LCRYPTO_ALIAS(X509_get_serialNumber); + +const ASN1_INTEGER * +X509_get0_serialNumber(const X509 *a) +{ + return (a->cert_info->serialNumber); +} +LCRYPTO_ALIAS(X509_get0_serialNumber); + +unsigned long +X509_subject_name_hash(X509 *x) +{ + return (X509_NAME_hash(x->cert_info->subject)); +} +LCRYPTO_ALIAS(X509_subject_name_hash); + +#ifndef OPENSSL_NO_MD5 +unsigned long +X509_subject_name_hash_old(X509 *x) +{ + return (X509_NAME_hash_old(x->cert_info->subject)); +} +LCRYPTO_ALIAS(X509_subject_name_hash_old); +#endif + +#ifndef OPENSSL_NO_SHA +/* Compare two certificates: they must be identical for + * this to work. NB: Although "cmp" operations are generally + * prototyped to take "const" arguments (eg. for use in + * STACKs), the way X509 handling is - these operations may + * involve ensuring the hashes are up-to-date and ensuring + * certain cert information is cached. So this is the point + * where the "depth-first" constification tree has to halt + * with an evil cast. + */ +int +X509_cmp(const X509 *a, const X509 *b) +{ + /* ensure hash is valid */ + X509_check_purpose((X509 *)a, -1, 0); + X509_check_purpose((X509 *)b, -1, 0); + + return memcmp(a->hash, b->hash, X509_CERT_HASH_LEN); +} +LCRYPTO_ALIAS(X509_cmp); +#endif + +int +X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) +{ + int ret; + + /* Ensure canonical encoding is present and up to date */ + if (!a->canon_enc || a->modified) { + ret = i2d_X509_NAME((X509_NAME *)a, NULL); + if (ret < 0) + return -2; + } + if (!b->canon_enc || b->modified) { + ret = i2d_X509_NAME((X509_NAME *)b, NULL); + if (ret < 0) + return -2; + } + ret = a->canon_enclen - b->canon_enclen; + if (ret) + return ret; + return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); +} +LCRYPTO_ALIAS(X509_NAME_cmp); + +unsigned long +X509_NAME_hash(X509_NAME *x) +{ + unsigned long ret = 0; + unsigned char md[SHA_DIGEST_LENGTH]; + + /* 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; + return (ret); +} +LCRYPTO_ALIAS(X509_NAME_hash); + + +#ifndef OPENSSL_NO_MD5 +/* 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) +{ + EVP_MD_CTX md_ctx; + unsigned long ret = 0; + unsigned char md[16]; + + /* Make sure X509_NAME structure contains valid cached encoding */ + i2d_X509_NAME(x, NULL); + EVP_MD_CTX_init(&md_ctx); + if (EVP_DigestInit_ex(&md_ctx, EVP_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; + EVP_MD_CTX_cleanup(&md_ctx); + + return (ret); +} +LCRYPTO_ALIAS(X509_NAME_hash_old); +#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) +{ + int i; + X509_CINF cinf; + X509 x, *x509 = NULL; + + if (!sk) + return NULL; + + x.cert_info = &cinf; + cinf.serialNumber = serial; + cinf.issuer = name; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_issuer_and_serial_cmp(x509, &x) == 0) + return (x509); + } + return (NULL); +} +LCRYPTO_ALIAS(X509_find_by_issuer_and_serial); + +X509 * +X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name) +{ + X509 *x509; + int i; + + for (i = 0; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0) + return (x509); + } + return (NULL); +} +LCRYPTO_ALIAS(X509_find_by_subject); + +EVP_PKEY * +X509_get_pubkey(X509 *x) +{ + if (x == NULL || x->cert_info == NULL) + return (NULL); + return (X509_PUBKEY_get(x->cert_info->key)); +} +LCRYPTO_ALIAS(X509_get_pubkey); + +EVP_PKEY * +X509_get0_pubkey(const X509 *x) +{ + if (x == NULL || x->cert_info == NULL) + return (NULL); + return (X509_PUBKEY_get0(x->cert_info->key)); +} +LCRYPTO_ALIAS(X509_get0_pubkey); + +ASN1_BIT_STRING * +X509_get0_pubkey_bitstr(const X509 *x) +{ + if (!x) + return NULL; + return x->cert_info->key->public_key; +} +LCRYPTO_ALIAS(X509_get0_pubkey_bitstr); + +int +X509_check_private_key(const X509 *x, const EVP_PKEY *k) +{ + const EVP_PKEY *xk; + int ret; + + xk = X509_get0_pubkey(x); + + if (xk) + ret = EVP_PKEY_cmp(xk, k); + else + ret = -2; + + switch (ret) { + case 1: + break; + case 0: + X509error(X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + X509error(X509_R_KEY_TYPE_MISMATCH); + break; + case -2: + X509error(X509_R_UNKNOWN_KEY_TYPE); + } + if (ret > 0) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_check_private_key); + +/* + * 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 + * each X509 structure. + */ +STACK_OF(X509) * +X509_chain_up_ref(STACK_OF(X509) *chain) +{ + STACK_OF(X509) *ret; + size_t i; + + ret = sk_X509_dup(chain); + for (i = 0; i < sk_X509_num(ret); i++) + X509_up_ref(sk_X509_value(ret, i)); + + return ret; +} +LCRYPTO_ALIAS(X509_chain_up_ref); diff --git a/crypto/x509/x509_conf.c b/crypto/x509/x509_conf.c new file mode 100644 index 0000000..189bf64 --- /dev/null +++ b/crypto/x509/x509_conf.c @@ -0,0 +1,591 @@ +/* $OpenBSD: x509_conf.c,v 1.5 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* extension creation utilities */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +static int v3_check_critical(const char **value); +static int v3_check_generic(const char **value); +static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, + int crit, const char *value); +static X509_EXTENSION *v3_generic_extension(const char *ext, const char *value, + int crit, int type, X509V3_CTX *ctx); +static char *conf_lhash_get_string(void *db, const char *section, + const char *value); +static STACK_OF(CONF_VALUE) *conf_lhash_get_section(void *db, + const char *section); +static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, + int crit, void *ext_struc); +static unsigned char *generic_asn1(const char *value, X509V3_CTX *ctx, + long *ext_len); + +/* CONF *conf: Config file */ +/* char *name: Name */ +/* char *value: Value */ +X509_EXTENSION * +X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, + const char *value) +{ + int crit; + int ext_type; + X509_EXTENSION *ret; + + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(name, value, crit, ext_type, ctx); + ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value); + if (!ret) { + X509V3error(X509V3_R_ERROR_IN_EXTENSION); + ERR_asprintf_error_data("name=%s, value=%s", name, value); + } + return ret; +} +LCRYPTO_ALIAS(X509V3_EXT_nconf); + +/* CONF *conf: Config file */ +/* char *value: Value */ +X509_EXTENSION * +X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + const char *value) +{ + int crit; + int ext_type; + + crit = v3_check_critical(&value); + if ((ext_type = v3_check_generic(&value))) + return v3_generic_extension(OBJ_nid2sn(ext_nid), + value, crit, ext_type, ctx); + return do_ext_nconf(conf, ctx, ext_nid, crit, value); +} +LCRYPTO_ALIAS(X509V3_EXT_nconf_nid); + +/* CONF *conf: Config file */ +/* char *value: Value */ +static X509_EXTENSION * +do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, + const char *value) +{ + const X509V3_EXT_METHOD *method; + X509_EXTENSION *ext; + void *ext_struc; + + if (ext_nid == NID_undef) { + X509V3error(X509V3_R_UNKNOWN_EXTENSION_NAME); + return NULL; + } + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + X509V3error(X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + /* Now get internal extension representation based on type */ + if (method->v2i) { + STACK_OF(CONF_VALUE) *nval; + + if (*value == '@') + nval = NCONF_get_section(conf, value + 1); + else + nval = X509V3_parse_list(value); + if (sk_CONF_VALUE_num(nval) <= 0) { + X509V3error(X509V3_R_INVALID_EXTENSION_STRING); + ERR_asprintf_error_data("name=%s,section=%s", + OBJ_nid2sn(ext_nid), value); + if (*value != '@') + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + return NULL; + } + ext_struc = method->v2i(method, ctx, nval); + if (*value != '@') + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + } else if (method->s2i) { + ext_struc = method->s2i(method, ctx, value); + } else if (method->r2i) { + if (!ctx->db || !ctx->db_meth) { + X509V3error(X509V3_R_NO_CONFIG_DATABASE); + return NULL; + } + ext_struc = method->r2i(method, ctx, value); + } else { + X509V3error(X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED); + ERR_asprintf_error_data("name=%s", OBJ_nid2sn(ext_nid)); + return NULL; + } + if (ext_struc == NULL) + return NULL; + + ext = do_ext_i2d(method, ext_nid, crit, ext_struc); + if (method->it) + ASN1_item_free(ext_struc, method->it); + else + method->ext_free(ext_struc); + return ext; +} + +static X509_EXTENSION * +do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid, int crit, + void *ext_struc) +{ + unsigned char *ext_der; + int ext_len; + ASN1_OCTET_STRING *ext_oct = NULL; + X509_EXTENSION *ext; + + /* Convert internal representation to DER */ + if (method->it) { + ext_der = NULL; + ext_len = ASN1_item_i2d(ext_struc, &ext_der, + method->it); + if (ext_len < 0) + goto merr; + } else { + unsigned char *p; + ext_len = method->i2d(ext_struc, NULL); + if (!(ext_der = malloc(ext_len))) + goto merr; + p = ext_der; + method->i2d(ext_struc, &p); + } + if (!(ext_oct = ASN1_OCTET_STRING_new())) + goto merr; + ext_oct->data = ext_der; + ext_oct->length = ext_len; + + ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct); + if (!ext) + goto merr; + ASN1_OCTET_STRING_free(ext_oct); + + return ext; + +merr: + ASN1_OCTET_STRING_free(ext_oct); + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + +} + +/* Given an internal structure, nid and critical flag create an extension */ + +X509_EXTENSION * +X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc) +{ + const X509V3_EXT_METHOD *method; + + if (!(method = X509V3_EXT_get_nid(ext_nid))) { + X509V3error(X509V3_R_UNKNOWN_EXTENSION); + return NULL; + } + return do_ext_i2d(method, ext_nid, crit, ext_struc); +} +LCRYPTO_ALIAS(X509V3_EXT_i2d); + +/* Check the extension string for critical flag */ +static int +v3_check_critical(const char **value) +{ + const char *p = *value; + + if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) + return 0; + p += 9; + while (isspace((unsigned char)*p)) p++; + *value = p; + return 1; +} + +/* Check extension string for generic extension and return the type */ +static int +v3_check_generic(const char **value) +{ + int gen_type = 0; + const char *p = *value; + + if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) { + p += 4; + gen_type = 1; + } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) { + p += 5; + gen_type = 2; + } else + return 0; + + while (isspace((unsigned char)*p)) + p++; + *value = p; + return gen_type; +} + +/* Create a generic extension: for now just handle DER type */ +static X509_EXTENSION * +v3_generic_extension(const char *ext, const char *value, int crit, int gen_type, + X509V3_CTX *ctx) +{ + unsigned char *ext_der = NULL; + long ext_len = 0; + ASN1_OBJECT *obj = NULL; + ASN1_OCTET_STRING *oct = NULL; + X509_EXTENSION *extension = NULL; + + if (!(obj = OBJ_txt2obj(ext, 0))) { + X509V3error(X509V3_R_EXTENSION_NAME_ERROR); + ERR_asprintf_error_data("name=%s", ext); + goto err; + } + + if (gen_type == 1) + ext_der = string_to_hex(value, &ext_len); + else if (gen_type == 2) + ext_der = generic_asn1(value, ctx, &ext_len); + else { + ERR_asprintf_error_data("Unexpected generic extension type %d", gen_type); + goto err; + } + + if (ext_der == NULL) { + X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); + ERR_asprintf_error_data("value=%s", value); + goto err; + } + + if (!(oct = ASN1_OCTET_STRING_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + + oct->data = ext_der; + oct->length = ext_len; + ext_der = NULL; + + extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct); + +err: + ASN1_OBJECT_free(obj); + ASN1_OCTET_STRING_free(oct); + free(ext_der); + return extension; +} + +static unsigned char * +generic_asn1(const char *value, X509V3_CTX *ctx, long *ext_len) +{ + ASN1_TYPE *typ; + unsigned char *ext_der = NULL; + + typ = ASN1_generate_v3(value, ctx); + if (typ == NULL) + return NULL; + *ext_len = i2d_ASN1_TYPE(typ, &ext_der); + ASN1_TYPE_free(typ); + return ext_der; +} + +/* This is the main function: add a bunch of extensions based on a config file + * section to an extension STACK. + */ + +int +X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, + STACK_OF(X509_EXTENSION) **sk) +{ + X509_EXTENSION *ext; + STACK_OF(CONF_VALUE) *nval; + CONF_VALUE *val; + int i; + + if (!(nval = NCONF_get_section(conf, section))) + 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))) + return 0; + if (sk) + X509v3_add_ext(sk, ext, -1); + X509_EXTENSION_free(ext); + } + return 1; +} +LCRYPTO_ALIAS(X509V3_EXT_add_nconf_sk); + +/* Convenience functions to add extensions to a certificate, CRL and request */ + +int +X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509 *cert) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + + if (cert) + sk = &cert->cert_info->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} +LCRYPTO_ALIAS(X509V3_EXT_add_nconf); + +/* Same as above but for a CRL */ + +int +X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_CRL *crl) +{ + STACK_OF(X509_EXTENSION) **sk = NULL; + + if (crl) + sk = &crl->crl->extensions; + return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); +} +LCRYPTO_ALIAS(X509V3_EXT_CRL_add_nconf); + +/* Add extensions to certificate request */ + +int +X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_REQ *req) +{ + STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL; + int i; + + if (req) + sk = &extlist; + i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk); + if (!i || !sk) + return i; + i = X509_REQ_add_extensions(req, extlist); + sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free); + return i; +} +LCRYPTO_ALIAS(X509V3_EXT_REQ_add_nconf); + +/* Config database functions */ + +char * +X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) { + X509V3error(X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + return ctx->db_meth->get_string(ctx->db, name, section); +} +LCRYPTO_ALIAS(X509V3_get_string); + +STACK_OF(CONF_VALUE) * +X509V3_get_section(X509V3_CTX *ctx, const char *section) +{ + if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) { + X509V3error(X509V3_R_OPERATION_NOT_DEFINED); + return NULL; + } + return ctx->db_meth->get_section(ctx->db, section); +} +LCRYPTO_ALIAS(X509V3_get_section); + +void +X509V3_string_free(X509V3_CTX *ctx, char *str) +{ + if (!str) + return; + if (ctx->db_meth->free_string) + ctx->db_meth->free_string(ctx->db, str); +} +LCRYPTO_ALIAS(X509V3_string_free); + +void +X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section) +{ + if (!section) + return; + if (ctx->db_meth->free_section) + ctx->db_meth->free_section(ctx->db, section); +} +LCRYPTO_ALIAS(X509V3_section_free); + +static char * +nconf_get_string(void *db, const char *section, const char *value) +{ + return NCONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) * +nconf_get_section(void *db, const char *section) +{ + return NCONF_get_section(db, section); +} + +static X509V3_CONF_METHOD nconf_method = { + nconf_get_string, + nconf_get_section, + NULL, + NULL +}; + +void +X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf) +{ + ctx->db_meth = &nconf_method; + ctx->db = conf; +} +LCRYPTO_ALIAS(X509V3_set_nconf); + +void +X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req, + X509_CRL *crl, int flags) +{ + ctx->issuer_cert = issuer; + ctx->subject_cert = subj; + ctx->crl = crl; + ctx->subject_req = req; + ctx->flags = flags; +} +LCRYPTO_ALIAS(X509V3_set_ctx); + +/* Old conf compatibility functions */ + +X509_EXTENSION * +X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, const char *name, + const char *value) +{ + CONF ctmp; + + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_nconf(&ctmp, ctx, name, value); +} +LCRYPTO_ALIAS(X509V3_EXT_conf); + +/* 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); +} +LCRYPTO_ALIAS(X509V3_EXT_conf_nid); + +static char * +conf_lhash_get_string(void *db, const char *section, const char *value) +{ + return CONF_get_string(db, section, value); +} + +static STACK_OF(CONF_VALUE) * +conf_lhash_get_section(void *db, const char *section) +{ + return CONF_get_section(db, section); +} + +static X509V3_CONF_METHOD conf_lhash_method = { + conf_lhash_get_string, + conf_lhash_get_section, + NULL, + NULL +}; + +void +X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash) +{ + ctx->db_meth = &conf_lhash_method; + ctx->db = lhash; +} +LCRYPTO_ALIAS(X509V3_set_conf_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); +} +LCRYPTO_ALIAS(X509V3_EXT_add_conf); + +/* Same as above but for a CRL */ + +int +X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_CRL *crl) +{ + CONF ctmp; + + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_CRL_add_nconf(&ctmp, ctx, section, crl); +} +LCRYPTO_ALIAS(X509V3_EXT_CRL_add_conf); + +/* Add extensions to certificate request */ + +int +X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_REQ *req) +{ + CONF ctmp; + + CONF_set_nconf(&ctmp, conf); + return X509V3_EXT_REQ_add_nconf(&ctmp, ctx, section, req); +} +LCRYPTO_ALIAS(X509V3_EXT_REQ_add_conf); diff --git a/crypto/x509/x509_constraints.c b/crypto/x509/x509_constraints.c new file mode 100644 index 0000000..0773d2b --- /dev/null +++ b/crypto/x509/x509_constraints.c @@ -0,0 +1,1294 @@ +/* $OpenBSD: x509_constraints.c,v 1.32 2023/09/29 15:53:59 beck Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "bytestring.h" +#include "x509_internal.h" + +/* RFC 2821 section 4.5.3.1 */ +#define LOCAL_PART_MAX_LEN (size_t)64 +#define DOMAIN_PART_MAX_LEN (size_t)255 +#define MAX_IP_ADDRESS_LENGTH (size_t)46 + +static int +cbs_is_ip_address(CBS *cbs, int *is_ip) +{ + struct sockaddr_in6 sin6; + struct sockaddr_in sin4; + char *name = NULL; + + *is_ip = 0; + if (CBS_len(cbs) > MAX_IP_ADDRESS_LENGTH) + return 1; + if (!CBS_strdup(cbs, &name)) + return 0; + if (inet_pton(AF_INET, name, &sin4) == 1 || + inet_pton(AF_INET6, name, &sin6) == 1) + *is_ip = 1; + + free(name); + return 1; +} + +struct x509_constraints_name * +x509_constraints_name_new(void) +{ + return (calloc(1, sizeof(struct x509_constraints_name))); +} + +void +x509_constraints_name_clear(struct x509_constraints_name *name) +{ + free(name->name); + free(name->local); + free(name->der); + memset(name, 0, sizeof(*name)); +} + +void +x509_constraints_name_free(struct x509_constraints_name *name) +{ + if (name == NULL) + return; + x509_constraints_name_clear(name); + free(name); +} + +struct x509_constraints_name * +x509_constraints_name_dup(struct x509_constraints_name *name) +{ + struct x509_constraints_name *new; + + if ((new = x509_constraints_name_new()) == NULL) + goto err; + new->type = name->type; + new->af = name->af; + new->der_len = name->der_len; + if (name->der_len > 0) { + if ((new->der = malloc(name->der_len)) == NULL) + goto err; + memcpy(new->der, name->der, name->der_len); + } + if (name->name != NULL && (new->name = strdup(name->name)) == NULL) + goto err; + if (name->local != NULL && (new->local = strdup(name->local)) == NULL) + goto err; + memcpy(new->address, name->address, sizeof(name->address)); + return new; + err: + x509_constraints_name_free(new); + return NULL; +} + +struct x509_constraints_names * +x509_constraints_names_new(size_t names_max) +{ + struct x509_constraints_names *new; + + if ((new = calloc(1, sizeof(struct x509_constraints_names))) == NULL) + return NULL; + + new->names_max = names_max; + + return new; +} + +void +x509_constraints_names_clear(struct x509_constraints_names *names) +{ + size_t i; + + for (i = 0; i < names->names_count; i++) + x509_constraints_name_free(names->names[i]); + free(names->names); + memset(names, 0, sizeof(*names)); +} + +void +x509_constraints_names_free(struct x509_constraints_names *names) +{ + if (names == NULL) + return; + + x509_constraints_names_clear(names); + free(names); +} + +int +x509_constraints_names_add(struct x509_constraints_names *names, + struct x509_constraints_name *name) +{ + if (names->names_count >= names->names_max) + return 0; + if (names->names_count == names->names_len) { + struct x509_constraints_name **tmp; + if ((tmp = recallocarray(names->names, names->names_len, + names->names_len + 32, sizeof(*tmp))) == NULL) + return 0; + names->names_len += 32; + names->names = tmp; + } + names->names[names->names_count] = name; + names->names_count++; + return 1; +} + +struct x509_constraints_names * +x509_constraints_names_dup(struct x509_constraints_names *names) +{ + struct x509_constraints_names *new = NULL; + struct x509_constraints_name *name = NULL; + size_t i; + + if (names == NULL) + return NULL; + + if ((new = x509_constraints_names_new(names->names_max)) == NULL) + goto err; + + for (i = 0; i < names->names_count; i++) { + if ((name = x509_constraints_name_dup(names->names[i])) == NULL) + goto err; + if (!x509_constraints_names_add(new, name)) + goto err; + } + + return new; + err: + x509_constraints_names_free(new); + x509_constraints_name_free(name); + return NULL; +} + +/* + * Validate that the name contains only a hostname consisting of RFC + * 5890 compliant A-labels (see RFC 6066 section 3). This is more + * permissive to allow for a leading '.' for a subdomain based + * constraint, as well as allowing for '_' which is commonly accepted + * by nonconformant DNS implementations. + * + * if "wildcards" is set it allows '*' to occur in the string at the end of a + * component. + */ +static int +x509_constraints_valid_domain_internal(CBS *cbs, int wildcards) +{ + int first, component = 0; + uint8_t prev, c = 0; + size_t i, len; + CBS copy; + + CBS_dup(cbs, ©); + + len = CBS_len(cbs); + + if (len > DOMAIN_PART_MAX_LEN) + return 0; + for (i = 0; i < len; i++) { + prev = c; + if (!CBS_get_u8(©, &c)) + return 0; + + first = (i == 0); + + /* Everything has to be ASCII, with no NUL byte */ + if (!isascii(c) || c == '\0') + return 0; + /* It must be alphanumeric, a '-', '.', '_' or '*' */ + if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != '*') + return 0; + + /* if it is a '*', fail if not wildcards */ + if (!wildcards && c == '*') + return 0; + + /* '-' must not start a component or be at the end. */ + if (c == '-' && (component == 0 || i == len - 1)) + return 0; + + /* + * '.' must not be at the end. It may be first overall + * but must not otherwise start a component. + */ + if (c == '.' && ((component == 0 && !first) || i == len - 1)) + return 0; + + if (c == '.') { + /* Components can not end with a dash. */ + if (prev == '-') + return 0; + /* Start new component */ + component = 0; + continue; + } + /* + * Wildcards can only occur at the end of a component. + * c*.com is valid, c*c.com is not. + */ + if (prev == '*') + return 0; + + /* Components must be 63 chars or less. */ + if (++component > 63) + return 0; + } + + return 1; +} + +int +x509_constraints_valid_host(CBS *cbs, int permit_ip) +{ + uint8_t first; + int is_ip; + + if (!CBS_peek_u8(cbs, &first)) + return 0; + if (first == '.') + return 0; /* leading . not allowed in a host name or IP */ + if (!permit_ip) { + if (!cbs_is_ip_address(cbs, &is_ip)) + return 0; + if (is_ip) + return 0; + } + + return x509_constraints_valid_domain_internal(cbs, 0); +} + +int +x509_constraints_valid_sandns(CBS *cbs) +{ + uint8_t first; + + if (!CBS_peek_u8(cbs, &first)) + return 0; + if (first == '.') + return 0; /* leading . not allowed in a SAN DNS name */ + /* + * A domain may not be less than two characters, so you + * can't wildcard a single domain of less than that + */ + if (CBS_len(cbs) < 4 && first == '*') + return 0; + + return x509_constraints_valid_domain_internal(cbs, 1); +} + +static inline int +local_part_ok(char c) +{ + return (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || c == '!' || c == '#' || c == '$' || + c == '%' || c == '&' || c == '\'' || c == '*' || c == '+' || + c == '-' || c == '/' || c == '=' || c == '?' || c == '^' || + c == '_' || c == '`' || c == '{' || c == '|' || c == '}' || + c == '~' || c == '.'); +} + +/* + * Parse "candidate" as an RFC 2821 mailbox. + * Returns 0 if candidate is not a valid mailbox or if an error occurs. + * Returns 1 if candidate is a mailbox and adds newly allocated + * local and domain parts of the mailbox to "name->local" and name->name" + */ +int +x509_constraints_parse_mailbox(CBS *candidate, + struct x509_constraints_name *name) +{ + char working[DOMAIN_PART_MAX_LEN + 1] = { 0 }; + char *candidate_local = NULL; + char *candidate_domain = NULL; + CBS domain_cbs; + size_t i, len, wi = 0; + int accept = 0; + int quoted = 0; + CBS copy; + + /* XXX This should not be necessary - revisit and remove */ + if (candidate == NULL) + return 0; + + CBS_dup(candidate, ©); + + if ((len = CBS_len(©)) == 0) + return 0; + + /* It can't be bigger than the local part, domain part and the '@' */ + if (len > LOCAL_PART_MAX_LEN + DOMAIN_PART_MAX_LEN + 1) + return 0; + + for (i = 0; i < len; i++) { + char c; + if (!CBS_get_u8(©, &c)) + goto bad; + /* non ascii, cr, lf, or nul is never allowed */ + if (!isascii(c) || c == '\r' || c == '\n' || c == '\0') + goto bad; + if (i == 0) { + /* local part is quoted part */ + if (c == '"') + quoted = 1; + /* can not start with a . */ + if (c == '.') + goto bad; + } + if (accept) { + if (wi >= DOMAIN_PART_MAX_LEN) + goto bad; + working[wi++] = c; + accept = 0; + continue; + } + if (candidate_local != NULL) { + /* We are looking for the domain part */ + if (wi >= DOMAIN_PART_MAX_LEN) + goto bad; + working[wi++] = c; + if (i == len - 1) { + if (wi == 0) + goto bad; + if (candidate_domain != NULL) + goto bad; + candidate_domain = strdup(working); + if (candidate_domain == NULL) + goto bad; + } + continue; + } + /* We are looking for the local part */ + if (wi >= LOCAL_PART_MAX_LEN) + break; + + if (quoted) { + if (c == '\\') { + accept = 1; + continue; + } + if (c == '"' && i != 0) { + uint8_t next; + /* end the quoted part. @ must be next */ + if (!CBS_peek_u8(©, &next)) + goto bad; + if (next != '@') + goto bad; + quoted = 0; + } + /* + * XXX Go strangely permits sp but forbids ht + * mimic that for now + */ + if (c == 9) + goto bad; + if (wi >= LOCAL_PART_MAX_LEN) + goto bad; + working[wi++] = c; + continue; /* all's good inside our quoted string */ + } + if (c == '@') { + if (wi == 0) + goto bad; + if (candidate_local != NULL) + goto bad; + candidate_local = strdup(working); + if (candidate_local == NULL) + goto bad; + memset(working, 0, sizeof(working)); + wi = 0; + continue; + } + if (c == '\\') { + uint8_t next; + /* + * RFC 2821 hints these can happen outside of + * quoted string. Don't include the \ but + * next character must be ok. + */ + if (!CBS_peek_u8(©, &next)) + goto bad; + if (!local_part_ok(next)) + goto bad; + accept = 1; + } + if (!local_part_ok(c)) + goto bad; + if (wi >= LOCAL_PART_MAX_LEN) + goto bad; + working[wi++] = c; + } + if (candidate_local == NULL || candidate_domain == NULL) + goto bad; + CBS_init(&domain_cbs, candidate_domain, strlen(candidate_domain)); + if (!x509_constraints_valid_host(&domain_cbs, 0)) + goto bad; + + if (name != NULL) { + name->local = candidate_local; + name->name = candidate_domain; + name->type = GEN_EMAIL; + } else { + free(candidate_local); + free(candidate_domain); + } + return 1; + bad: + free(candidate_local); + free(candidate_domain); + return 0; +} + +int +x509_constraints_valid_domain_constraint(CBS *cbs) +{ + uint8_t first; + + if (CBS_len(cbs) == 0) + return 1; /* empty constraints match */ + + /* + * A domain may not be less than two characters, so you + * can't match a single domain of less than that + */ + if (CBS_len(cbs) < 3) { + if (!CBS_peek_u8(cbs, &first)) + return 0; + if (first == '.') + return 0; + } + return x509_constraints_valid_domain_internal(cbs, 0); +} + +/* + * Extract the host part of a URI. On failure to parse a valid host part of the + * URI, 0 is returned indicating an invalid URI. If the host part parses as + * valid, or is not present, 1 is returned indicating a possibly valid URI. + * + * In the case of a valid URI, *hostpart will be set to a copy of the host part + * of the URI, or the empty string if no URI is present. If memory allocation + * fails *hostpart will be set to NULL, even though we returned 1. It is the + * caller's responsibility to indicate an error for memory allocation failure, + * and the callers responsibility to free *hostpart. + * + * RFC 3986: + * the authority part of a uri starts with // and is terminated with + * the next '/', '?', '#' or end of the URI. + * + * The authority itself contains [userinfo '@'] host [: port] + * + * so the host starts at the start or after the '@', and ends + * with end of URI, '/', '?', "#', or ':'. + */ +int +x509_constraints_uri_host(uint8_t *uri, size_t len, char **hostpart) +{ + size_t i, hostlen = 0; + uint8_t *authority = NULL; + char *host = NULL; + CBS host_cbs; + + /* + * Find first '//'. there must be at least a '//' and + * something else. + */ + if (len < 3) + return 0; + for (i = 0; i < len - 1; i++) { + if (!isascii(uri[i])) + return 0; + if (uri[i] == '/' && uri[i + 1] == '/') { + authority = uri + i + 2; + break; + } + } + if (authority == NULL) { + /* + * There is no authority, so no host part in this + * URI. This might be ok or might not, but it must + * fail if we run into a name constraint later, so + * we indicate that we have a URI with an empty + * host part, and succeed. + */ + if (hostpart != NULL) + *hostpart = strdup(""); + return 1; + } + for (i = authority - uri; i < len; i++) { + if (!isascii(uri[i])) + return 0; + /* it has a userinfo part */ + if (uri[i] == '@') { + hostlen = 0; + /* it can only have one */ + if (host != NULL) + break; + /* start after the userinfo part */ + host = uri + i + 1; + continue; + } + /* did we find the end? */ + if (uri[i] == ':' || uri[i] == '/' || uri[i] == '?' || + uri[i] == '#') + break; + hostlen++; + } + if (hostlen == 0) + return 0; + if (host == NULL) + host = authority; + CBS_init(&host_cbs, host, hostlen); + if (!x509_constraints_valid_host(&host_cbs, 1)) + return 0; + if (hostpart != NULL && !CBS_strdup(&host_cbs, hostpart)) + return 0; + return 1; +} + +int +x509_constraints_sandns(char *sandns, size_t dlen, char *constraint, size_t len) +{ + char *suffix; + + if (len == 0) + return 1; /* an empty constraint matches everything */ + + /* match the end of the domain */ + if (dlen < len) + return 0; + suffix = sandns + (dlen - len); + return (strncasecmp(suffix, constraint, len) == 0); +} + +/* + * Validate a pre-validated domain of length dlen against a pre-validated + * constraint of length len. + * + * returns 1 if the domain and constraint match. + * returns 0 otherwise. + * + * an empty constraint matches everything. + * constraint will be matched against the domain as a suffix if it + * starts with a '.'. + * domain will be matched against the constraint as a suffix if it + * starts with a '.'. + */ +int +x509_constraints_domain(char *domain, size_t dlen, char *constraint, size_t len) +{ + if (len == 0) + return 1; /* an empty constraint matches everything */ + + if (constraint[0] == '.') { + /* match the end of the domain */ + char *suffix; + if (dlen < len) + return 0; + suffix = domain + (dlen - len); + return (strncasecmp(suffix, constraint, len) == 0); + } + if (domain[0] == '.') { + /* match the end of the constraint */ + char *suffix; + if (len < dlen) + return 0; + suffix = constraint + (len - dlen); + return (strncasecmp(suffix, domain, dlen) == 0); + } + /* otherwise we must exactly match the constraint */ + if (dlen != len) + return 0; + return (strncasecmp(domain, constraint, len) == 0); +} + +int +x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, + size_t len, + int *error) +{ + int ret = 0; + char *hostpart = NULL; + CBS cbs; + + CBS_init(&cbs, constraint, len); + if (!x509_constraints_uri_host(uri, ulen, &hostpart)) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + if (hostpart == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!x509_constraints_valid_domain_constraint(&cbs)) { + *error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; + goto err; + } + ret = x509_constraints_domain(hostpart, strlen(hostpart), constraint, + len); + err: + free(hostpart); + return ret; +} + +/* + * Verify a validated address of size alen with a validated constraint + * of size constraint_len. returns 1 if matching, 0 if not. + * Addresses are assumed to be pre-validated for a length of 4 and 8 + * respectively for ipv4 addresses and constraints, and a length of + * 16 and 32 respectively for ipv6 address constraints by the caller. + */ +int +x509_constraints_ipaddr(uint8_t *address, size_t alen, uint8_t *constraint, + size_t len) +{ + uint8_t *mask; + size_t i; + + if (alen * 2 != len) + return 0; + + mask = constraint + alen; + for (i = 0; i < alen; i++) { + if ((address[i] & mask[i]) != (constraint[i] & mask[i])) + return 0; + } + return 1; +} + +/* + * Verify a canonicalized der encoded constraint dirname + * a canonicalized der encoded constraint. + */ +int +x509_constraints_dirname(uint8_t *dirname, size_t dlen, + uint8_t *constraint, size_t len) +{ + /* + * The constraint must be a prefix in DER format, so it can't be + * longer than the name it is checked against. + */ + if (len > dlen) + return 0; + return (memcmp(constraint, dirname, len) == 0); +} + +/* + * De-obfuscate a GENERAL_NAME into useful bytes for a name or constraint. + */ +int +x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, + size_t *len) +{ + *bytes = NULL; + *len = 0; + + if (name->type == GEN_DNS) { + ASN1_IA5STRING *aname = name->d.dNSName; + + *bytes = aname->data; + *len = aname->length; + + return name->type; + } + if (name->type == GEN_EMAIL) { + ASN1_IA5STRING *aname = name->d.rfc822Name; + + *bytes = aname->data; + *len = aname->length; + + return name->type; + } + if (name->type == GEN_URI) { + ASN1_IA5STRING *aname = name->d.uniformResourceIdentifier; + + *bytes = aname->data; + *len = aname->length; + + return name->type; + } + if (name->type == GEN_DIRNAME) { + X509_NAME *dname = name->d.directoryName; + + if (!dname->modified || i2d_X509_NAME(dname, NULL) >= 0) { + *bytes = dname->canon_enc; + *len = dname->canon_enclen; + + return name->type; + } + } + if (name->type == GEN_IPADD) { + *bytes = name->d.ip->data; + *len = name->d.ip->length; + + return name->type; + } + + return 0; +} + +/* + * Extract the relevant names for constraint checking from "cert", + * validate them, and add them to the list of cert names for "chain". + * returns 1 on success sets error and returns 0 on failure. + */ +int +x509_constraints_extract_names(struct x509_constraints_names *names, + X509 *cert, int is_leaf, int *error) +{ + struct x509_constraints_name *vname = NULL; + X509_NAME *subject_name; + GENERAL_NAME *name; + ssize_t i = 0; + int name_type, include_cn = is_leaf, include_email = is_leaf; + + /* first grab the altnames */ + while ((name = sk_GENERAL_NAME_value(cert->altname, i++)) != NULL) { + uint8_t *bytes = NULL; + size_t len = 0; + CBS cbs; + + if ((vname = x509_constraints_name_new()) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + + name_type = x509_constraints_general_to_bytes(name, &bytes, + &len); + CBS_init(&cbs, bytes, len); + switch (name_type) { + case GEN_DNS: + if (!x509_constraints_valid_sandns(&cbs)) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + if (!CBS_strdup(&cbs, &vname->name)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname->type = GEN_DNS; + include_cn = 0; /* Don't use cn from subject */ + break; + case GEN_EMAIL: + if (!x509_constraints_parse_mailbox(&cbs, vname)) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + vname->type = GEN_EMAIL; + include_email = 0; /* Don't use email from subject */ + break; + case GEN_URI: + if (!x509_constraints_uri_host(bytes, len, + &vname->name)) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + if (vname->name == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname->type = GEN_URI; + break; + case GEN_DIRNAME: + if (len == 0) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + if (bytes == NULL || ((vname->der = malloc(len)) == + NULL)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + memcpy(vname->der, bytes, len); + vname->der_len = len; + vname->type = GEN_DIRNAME; + break; + case GEN_IPADD: + if (len == 4) + vname->af = AF_INET; + if (len == 16) + vname->af = AF_INET6; + if (vname->af != AF_INET && vname->af != AF_INET6) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + memcpy(vname->address, bytes, len); + vname->type = GEN_IPADD; + break; + default: + /* Ignore this name */ + x509_constraints_name_free(vname); + vname = NULL; + continue; + } + if (!x509_constraints_names_add(names, vname)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname = NULL; + } + + x509_constraints_name_free(vname); + vname = NULL; + + subject_name = X509_get_subject_name(cert); + if (X509_NAME_entry_count(subject_name) > 0) { + X509_NAME_ENTRY *email; + X509_NAME_ENTRY *cn; + /* + * This cert has a non-empty subject, so we must add + * the subject as a dirname to be compared against + * any dirname constraints + */ + if ((subject_name->modified && + i2d_X509_NAME(subject_name, NULL) < 0) || + (vname = x509_constraints_name_new()) == NULL || + (vname->der = malloc(subject_name->canon_enclen)) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + + memcpy(vname->der, subject_name->canon_enc, + subject_name->canon_enclen); + vname->der_len = subject_name->canon_enclen; + vname->type = GEN_DIRNAME; + if (!x509_constraints_names_add(names, vname)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname = NULL; + /* + * Get any email addresses from the subject line, and + * add them as mbox names to be compared against any + * email constraints + */ + while (include_email && + (i = X509_NAME_get_index_by_NID(subject_name, + NID_pkcs9_emailAddress, i)) >= 0) { + ASN1_STRING *aname; + CBS cbs; + if ((email = X509_NAME_get_entry(subject_name, i)) == + NULL || + (aname = X509_NAME_ENTRY_get_data(email)) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + CBS_init(&cbs, aname->data, aname->length); + if ((vname = x509_constraints_name_new()) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!x509_constraints_parse_mailbox(&cbs, vname)) { + *error = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + goto err; + } + vname->type = GEN_EMAIL; + if (!x509_constraints_names_add(names, vname)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname = NULL; + } + /* + * Include the CN as a hostname to be checked against + * name constraints if it looks like a hostname. + */ + while (include_cn && + (i = X509_NAME_get_index_by_NID(subject_name, + NID_commonName, i)) >= 0) { + CBS cbs; + ASN1_STRING *aname; + if ((cn = X509_NAME_get_entry(subject_name, i)) == + NULL || + (aname = X509_NAME_ENTRY_get_data(cn)) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + CBS_init(&cbs, aname->data, aname->length); + if (!x509_constraints_valid_host(&cbs, 0)) + continue; /* ignore it if not a hostname */ + if ((vname = x509_constraints_name_new()) == NULL) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!CBS_strdup(&cbs, &vname->name)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname->type = GEN_DNS; + if (!x509_constraints_names_add(names, vname)) { + *error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + vname = NULL; + } + } + return 1; + err: + x509_constraints_name_free(vname); + return 0; +} + +/* + * Validate a constraint in a general name, putting the relevant data + * into "name" if valid. returns 0, and sets error if the constraint is + * not valid. returns 1 if the constraint validated. name->type will be + * set to a valid type if there is constraint data in name, or unmodified + * if the GENERAL_NAME had a valid type but was ignored. + */ +int +x509_constraints_validate(GENERAL_NAME *constraint, + struct x509_constraints_name **out_name, int *out_error) +{ + uint8_t next, *bytes = NULL; + size_t len = 0; + struct x509_constraints_name *name; + int error = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX; + int name_type; + CBS cbs; + + if (out_name == NULL || *out_name != NULL) + return 0; + + if (out_error != NULL) + *out_error = 0; + + if ((name = x509_constraints_name_new()) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + + name_type = x509_constraints_general_to_bytes(constraint, &bytes, &len); + CBS_init(&cbs, bytes, len); + switch (name_type) { + case GEN_DIRNAME: + if (len == 0) + goto err; /* XXX The RFCs are delightfully vague */ + if (bytes == NULL || (name->der = malloc(len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + memcpy(name->der, bytes, len); + name->der_len = len; + name->type = GEN_DIRNAME; + break; + case GEN_DNS: + if (!x509_constraints_valid_domain_constraint(&cbs)) + goto err; + if ((name->name = strndup(bytes, len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + name->type = GEN_DNS; + break; + case GEN_EMAIL: + if (len > 0 && memchr(bytes + 1, '@', len - 1) != NULL) { + if (!x509_constraints_parse_mailbox(&cbs, name)) + goto err; + break; + } + /* + * Mail constraints of the form @domain.com are accepted by + * OpenSSL and Microsoft. + */ + if (CBS_len(&cbs) > 0) { + if (!CBS_peek_u8(&cbs, &next)) + goto err; + if (next == '@') { + if (!CBS_skip(&cbs, 1)) + goto err; + } + } + if (!x509_constraints_valid_domain_constraint(&cbs)) + goto err; + if (!CBS_strdup(&cbs, &name->name)) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + name->type = GEN_EMAIL; + break; + case GEN_IPADD: + /* Constraints are ip then mask */ + if (len == 8) + name->af = AF_INET; + else if (len == 32) + name->af = AF_INET6; + else + goto err; + memcpy(&name->address[0], bytes, len); + name->type = GEN_IPADD; + break; + case GEN_URI: + if (!x509_constraints_valid_domain_constraint(&cbs)) + goto err; + if ((name->name = strndup(bytes, len)) == NULL) { + error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + name->type = GEN_URI; + break; + default: + break; + } + + *out_name = name; + + return 1; + + err: + x509_constraints_name_free(name); + if (out_error != NULL) + *out_error = error; + + return 0; +} + +int +x509_constraints_extract_constraints(X509 *cert, + struct x509_constraints_names *permitted, + struct x509_constraints_names *excluded, + int *error) +{ + struct x509_constraints_name *vname = NULL; + NAME_CONSTRAINTS *nc = cert->nc; + GENERAL_SUBTREE *subtree; + int i; + + if (nc == NULL) + return 1; + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { + subtree = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); + if (subtree->minimum || subtree->maximum) { + *error = X509_V_ERR_SUBTREE_MINMAX; + return 0; + } + if (!x509_constraints_validate(subtree->base, &vname, error)) + return 0; + if (vname->type == 0) { + x509_constraints_name_free(vname); + vname = NULL; + continue; + } + if (!x509_constraints_names_add(permitted, vname)) { + x509_constraints_name_free(vname); + vname = NULL; + *error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + vname = NULL; + } + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { + subtree = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); + if (subtree->minimum || subtree->maximum) { + *error = X509_V_ERR_SUBTREE_MINMAX; + return 0; + } + if (!x509_constraints_validate(subtree->base, &vname, error)) + return 0; + if (vname->type == 0) { + x509_constraints_name_free(vname); + vname = NULL; + continue; + } + if (!x509_constraints_names_add(excluded, vname)) { + x509_constraints_name_free(vname); + vname = NULL; + *error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + vname = NULL; + } + + return 1; +} + +/* + * Match a validated name in "name" against a validated constraint in + * "constraint" return 1 if then name matches, 0 otherwise. + */ +int +x509_constraints_match(struct x509_constraints_name *name, + struct x509_constraints_name *constraint) +{ + if (name->type != constraint->type) + return 0; + if (name->type == GEN_DNS) + return x509_constraints_sandns(name->name, strlen(name->name), + constraint->name, strlen(constraint->name)); + if (name->type == GEN_URI) + return x509_constraints_domain(name->name, strlen(name->name), + constraint->name, strlen(constraint->name)); + if (name->type == GEN_IPADD) { + size_t nlen = name->af == AF_INET ? 4 : 16; + size_t clen = name->af == AF_INET ? 8 : 32; + if (name->af != AF_INET && name->af != AF_INET6) + return 0; + if (constraint->af != AF_INET && constraint->af != AF_INET6) + return 0; + if (name->af != constraint->af) + return 0; + return x509_constraints_ipaddr(name->address, nlen, + constraint->address, clen); + } + if (name->type == GEN_EMAIL) { + if (constraint->local) { + /* mailbox local and domain parts must exactly match */ + return (strcmp(name->local, constraint->local) == 0 && + strcmp(name->name, constraint->name) == 0); + } + /* otherwise match the constraint to the domain part */ + return x509_constraints_domain(name->name, strlen(name->name), + constraint->name, strlen(constraint->name)); + } + if (name->type == GEN_DIRNAME) + return x509_constraints_dirname(name->der, name->der_len, + constraint->der, constraint->der_len); + return 0; +} + +/* + * Make sure every name in names does not match any excluded + * constraints, and does match at least one permitted constraint if + * any are present. Returns 1 if ok, 0, and sets error if not. + */ +int +x509_constraints_check(struct x509_constraints_names *names, + struct x509_constraints_names *permitted, + struct x509_constraints_names *excluded, int *error) +{ + size_t i, j; + + for (i = 0; i < names->names_count; i++) { + int permitted_seen = 0; + int permitted_matched = 0; + + for (j = 0; j < excluded->names_count; j++) { + if (x509_constraints_match(names->names[i], + excluded->names[j])) { + *error = X509_V_ERR_EXCLUDED_VIOLATION; + return 0; + } + } + for (j = 0; j < permitted->names_count; j++) { + if (permitted->names[j]->type == names->names[i]->type) + permitted_seen++; + if (x509_constraints_match(names->names[i], + permitted->names[j])) { + permitted_matched++; + break; + } + } + if (permitted_seen && !permitted_matched) { + *error = X509_V_ERR_PERMITTED_VIOLATION; + return 0; + } + } + return 1; +} + +/* + * Walk a validated chain of X509 certs, starting at the leaf, and + * validate the name constraints in the chain. Intended for use with + * the legacy X509 validation code in x509_vfy.c + * + * returns 1 if the constraints are ok, 0 otherwise, setting error and + * depth + */ +int +x509_constraints_chain(STACK_OF(X509) *chain, int *error, int *depth) +{ + int chain_length, verify_err = X509_V_ERR_UNSPECIFIED, i = 0; + struct x509_constraints_names *names = NULL; + struct x509_constraints_names *excluded = NULL; + struct x509_constraints_names *permitted = NULL; + size_t constraints_count = 0; + X509 *cert; + + if (chain == NULL || (chain_length = sk_X509_num(chain)) == 0) + goto err; + if (chain_length == 1) + return 1; + if ((names = x509_constraints_names_new( + X509_VERIFY_MAX_CHAIN_NAMES)) == NULL) { + verify_err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + + if ((cert = sk_X509_value(chain, 0)) == NULL) + goto err; + if (!x509_constraints_extract_names(names, cert, 1, &verify_err)) + goto err; + for (i = 1; i < chain_length; i++) { + if ((cert = sk_X509_value(chain, i)) == NULL) + goto err; + if (cert->nc != NULL) { + if ((permitted = x509_constraints_names_new( + X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { + verify_err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if ((excluded = x509_constraints_names_new( + X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { + verify_err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!x509_constraints_extract_constraints(cert, + permitted, excluded, &verify_err)) + goto err; + constraints_count += permitted->names_count; + constraints_count += excluded->names_count; + if (constraints_count > + X509_VERIFY_MAX_CHAIN_CONSTRAINTS) { + verify_err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!x509_constraints_check(names, permitted, excluded, + &verify_err)) + goto err; + x509_constraints_names_free(excluded); + excluded = NULL; + x509_constraints_names_free(permitted); + permitted = NULL; + } + if (!x509_constraints_extract_names(names, cert, 0, + &verify_err)) + goto err; + } + + x509_constraints_names_free(names); + return 1; + + err: + *error = verify_err; + *depth = i; + x509_constraints_names_free(excluded); + x509_constraints_names_free(permitted); + x509_constraints_names_free(names); + return 0; +} diff --git a/crypto/x509/x509_cpols.c b/crypto/x509/x509_cpols.c new file mode 100644 index 0000000..bab2e99 --- /dev/null +++ b/crypto/x509/x509_cpols.c @@ -0,0 +1,764 @@ +/* $OpenBSD: x509_cpols.c,v 1.11 2023/04/26 20:54:21 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_local.h" + +/* Certificate policies extension support: this one is a bit complex... */ + +static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, + BIO *out, int indent); +static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *value); +static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, + int indent); +static void print_notice(BIO *out, USERNOTICE *notice, int indent); +static POLICYINFO *policy_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *polstrs, int ia5org); +static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *unot, int ia5org); +static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos); + +const X509V3_EXT_METHOD v3_cpols = { + .ext_nid = NID_certificate_policies, + .ext_flags = 0, + .it = &CERTIFICATEPOLICIES_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = (X509V3_EXT_I2R)i2r_certpol, + .r2i = (X509V3_EXT_R2I)r2i_certpol, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE CERTIFICATEPOLICIES_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "CERTIFICATEPOLICIES", + .item = &POLICYINFO_it, +}; + +const ASN1_ITEM CERTIFICATEPOLICIES_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &CERTIFICATEPOLICIES_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "CERTIFICATEPOLICIES", +}; + + +CERTIFICATEPOLICIES * +d2i_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES **a, const unsigned char **in, long len) +{ + return (CERTIFICATEPOLICIES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &CERTIFICATEPOLICIES_it); +} +LCRYPTO_ALIAS(d2i_CERTIFICATEPOLICIES); + +int +i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &CERTIFICATEPOLICIES_it); +} +LCRYPTO_ALIAS(i2d_CERTIFICATEPOLICIES); + +CERTIFICATEPOLICIES * +CERTIFICATEPOLICIES_new(void) +{ + return (CERTIFICATEPOLICIES *)ASN1_item_new(&CERTIFICATEPOLICIES_it); +} +LCRYPTO_ALIAS(CERTIFICATEPOLICIES_new); + +void +CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &CERTIFICATEPOLICIES_it); +} +LCRYPTO_ALIAS(CERTIFICATEPOLICIES_free); + +static const ASN1_TEMPLATE POLICYINFO_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICYINFO, policyid), + .field_name = "policyid", + .item = &ASN1_OBJECT_it, + }, + { + .flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(POLICYINFO, qualifiers), + .field_name = "qualifiers", + .item = &POLICYQUALINFO_it, + }, +}; + +const ASN1_ITEM POLICYINFO_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = POLICYINFO_seq_tt, + .tcount = sizeof(POLICYINFO_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(POLICYINFO), + .sname = "POLICYINFO", +}; + + +POLICYINFO * +d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len) +{ + return (POLICYINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &POLICYINFO_it); +} +LCRYPTO_ALIAS(d2i_POLICYINFO); + +int +i2d_POLICYINFO(POLICYINFO *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYINFO_it); +} +LCRYPTO_ALIAS(i2d_POLICYINFO); + +POLICYINFO * +POLICYINFO_new(void) +{ + return (POLICYINFO *)ASN1_item_new(&POLICYINFO_it); +} +LCRYPTO_ALIAS(POLICYINFO_new); + +void +POLICYINFO_free(POLICYINFO *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &POLICYINFO_it); +} +LCRYPTO_ALIAS(POLICYINFO_free); + +static const ASN1_TEMPLATE policydefault_tt = { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICYQUALINFO, d.other), + .field_name = "d.other", + .item = &ASN1_ANY_it, +}; + +static const ASN1_ADB_TABLE POLICYQUALINFO_adbtbl[] = { + { + .value = NID_id_qt_cps, + .tt = { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICYQUALINFO, d.cpsuri), + .field_name = "d.cpsuri", + .item = &ASN1_IA5STRING_it, + }, + }, + { + .value = NID_id_qt_unotice, + .tt = { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICYQUALINFO, d.usernotice), + .field_name = "d.usernotice", + .item = &USERNOTICE_it, + }, + }, +}; + +static const ASN1_ADB POLICYQUALINFO_adb = { + .flags = 0, + .offset = offsetof(POLICYQUALINFO, pqualid), + .tbl = POLICYQUALINFO_adbtbl, + .tblcount = sizeof(POLICYQUALINFO_adbtbl) / sizeof(ASN1_ADB_TABLE), + .default_tt = &policydefault_tt, + .null_tt = NULL, +}; + +static const ASN1_TEMPLATE POLICYQUALINFO_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICYQUALINFO, pqualid), + .field_name = "pqualid", + .item = &ASN1_OBJECT_it, + }, + { + .flags = ASN1_TFLG_ADB_OID, + .tag = -1, + .offset = 0, + .field_name = "POLICYQUALINFO", + .item = (const ASN1_ITEM *)&POLICYQUALINFO_adb, + }, +}; + +const ASN1_ITEM POLICYQUALINFO_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = POLICYQUALINFO_seq_tt, + .tcount = sizeof(POLICYQUALINFO_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(POLICYQUALINFO), + .sname = "POLICYQUALINFO", +}; + + +POLICYQUALINFO * +d2i_POLICYQUALINFO(POLICYQUALINFO **a, const unsigned char **in, long len) +{ + return (POLICYQUALINFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &POLICYQUALINFO_it); +} +LCRYPTO_ALIAS(d2i_POLICYQUALINFO); + +int +i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &POLICYQUALINFO_it); +} +LCRYPTO_ALIAS(i2d_POLICYQUALINFO); + +POLICYQUALINFO * +POLICYQUALINFO_new(void) +{ + return (POLICYQUALINFO *)ASN1_item_new(&POLICYQUALINFO_it); +} +LCRYPTO_ALIAS(POLICYQUALINFO_new); + +void +POLICYQUALINFO_free(POLICYQUALINFO *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &POLICYQUALINFO_it); +} +LCRYPTO_ALIAS(POLICYQUALINFO_free); + +static const ASN1_TEMPLATE USERNOTICE_seq_tt[] = { + { + .flags = ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(USERNOTICE, noticeref), + .field_name = "noticeref", + .item = &NOTICEREF_it, + }, + { + .flags = ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(USERNOTICE, exptext), + .field_name = "exptext", + .item = &DISPLAYTEXT_it, + }, +}; + +const ASN1_ITEM USERNOTICE_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = USERNOTICE_seq_tt, + .tcount = sizeof(USERNOTICE_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(USERNOTICE), + .sname = "USERNOTICE", +}; + + +USERNOTICE * +d2i_USERNOTICE(USERNOTICE **a, const unsigned char **in, long len) +{ + return (USERNOTICE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &USERNOTICE_it); +} +LCRYPTO_ALIAS(d2i_USERNOTICE); + +int +i2d_USERNOTICE(USERNOTICE *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &USERNOTICE_it); +} +LCRYPTO_ALIAS(i2d_USERNOTICE); + +USERNOTICE * +USERNOTICE_new(void) +{ + return (USERNOTICE *)ASN1_item_new(&USERNOTICE_it); +} +LCRYPTO_ALIAS(USERNOTICE_new); + +void +USERNOTICE_free(USERNOTICE *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &USERNOTICE_it); +} +LCRYPTO_ALIAS(USERNOTICE_free); + +static const ASN1_TEMPLATE NOTICEREF_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(NOTICEREF, organization), + .field_name = "organization", + .item = &DISPLAYTEXT_it, + }, + { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = offsetof(NOTICEREF, noticenos), + .field_name = "noticenos", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM NOTICEREF_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = NOTICEREF_seq_tt, + .tcount = sizeof(NOTICEREF_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(NOTICEREF), + .sname = "NOTICEREF", +}; + + +NOTICEREF * +d2i_NOTICEREF(NOTICEREF **a, const unsigned char **in, long len) +{ + return (NOTICEREF *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &NOTICEREF_it); +} +LCRYPTO_ALIAS(d2i_NOTICEREF); + +int +i2d_NOTICEREF(NOTICEREF *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &NOTICEREF_it); +} +LCRYPTO_ALIAS(i2d_NOTICEREF); + +NOTICEREF * +NOTICEREF_new(void) +{ + return (NOTICEREF *)ASN1_item_new(&NOTICEREF_it); +} +LCRYPTO_ALIAS(NOTICEREF_new); + +void +NOTICEREF_free(NOTICEREF *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &NOTICEREF_it); +} +LCRYPTO_ALIAS(NOTICEREF_free); + +static STACK_OF(POLICYINFO) * +r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value) +{ + STACK_OF(POLICYINFO) *pols = NULL; + char *pstr; + POLICYINFO *pol; + ASN1_OBJECT *pobj; + STACK_OF(CONF_VALUE) *vals; + CONF_VALUE *cnf; + int i, ia5org; + + pols = sk_POLICYINFO_new_null(); + if (pols == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + vals = X509V3_parse_list(value); + if (vals == NULL) { + X509V3error(ERR_R_X509V3_LIB); + goto err; + } + ia5org = 0; + for (i = 0; i < sk_CONF_VALUE_num(vals); i++) { + cnf = sk_CONF_VALUE_value(vals, i); + if (cnf->value || !cnf->name) { + X509V3error(X509V3_R_INVALID_POLICY_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pstr = cnf->name; + if (!strcmp(pstr, "ia5org")) { + ia5org = 1; + continue; + } else if (*pstr == '@') { + STACK_OF(CONF_VALUE) *polsect; + polsect = X509V3_get_section(ctx, pstr + 1); + if (!polsect) { + X509V3error(X509V3_R_INVALID_SECTION); + X509V3_conf_err(cnf); + goto err; + } + pol = policy_section(ctx, polsect, ia5org); + X509V3_section_free(ctx, polsect); + if (!pol) + goto err; + } else { + if (!(pobj = OBJ_txt2obj(cnf->name, 0))) { + X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol = POLICYINFO_new(); + pol->policyid = pobj; + } + if (!sk_POLICYINFO_push(pols, pol)){ + POLICYINFO_free(pol); + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + } + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + return pols; + +err: + sk_CONF_VALUE_pop_free(vals, X509V3_conf_free); + sk_POLICYINFO_pop_free(pols, POLICYINFO_free); + return NULL; +} + +static POLICYINFO * +policy_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *polstrs, int ia5org) +{ + int i; + CONF_VALUE *cnf; + POLICYINFO *pol; + POLICYQUALINFO *nqual = NULL; + + if ((pol = POLICYINFO_new()) == NULL) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) { + cnf = sk_CONF_VALUE_value(polstrs, i); + if (strcmp(cnf->name, "policyIdentifier") == 0) { + ASN1_OBJECT *pobj; + + if ((pobj = OBJ_txt2obj(cnf->value, 0)) == NULL) { + X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(cnf); + goto err; + } + pol->policyid = pobj; + } else if (name_cmp(cnf->name, "CPS") == 0) { + if ((nqual = POLICYQUALINFO_new()) == NULL) + goto merr; + nqual->pqualid = OBJ_nid2obj(NID_id_qt_cps); + nqual->d.cpsuri = ASN1_IA5STRING_new(); + if (nqual->d.cpsuri == NULL) + goto merr; + if (ASN1_STRING_set(nqual->d.cpsuri, cnf->value, + strlen(cnf->value)) == 0) + goto merr; + + if (pol->qualifiers == NULL) { + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if (pol->qualifiers == NULL) + goto merr; + } + if (sk_POLICYQUALINFO_push(pol->qualifiers, nqual) == 0) + goto merr; + nqual = NULL; + } else if (name_cmp(cnf->name, "userNotice") == 0) { + STACK_OF(CONF_VALUE) *unot; + POLICYQUALINFO *qual; + + if (*cnf->value != '@') { + X509V3error(X509V3_R_EXPECTED_A_SECTION_NAME); + X509V3_conf_err(cnf); + goto err; + } + unot = X509V3_get_section(ctx, cnf->value + 1); + if (unot == NULL) { + X509V3error(X509V3_R_INVALID_SECTION); + X509V3_conf_err(cnf); + goto err; + } + qual = notice_section(ctx, unot, ia5org); + X509V3_section_free(ctx, unot); + if (qual == NULL) + goto err; + + if (pol->qualifiers == NULL) { + pol->qualifiers = sk_POLICYQUALINFO_new_null(); + if (pol->qualifiers == NULL) + goto merr; + } + if (sk_POLICYQUALINFO_push(pol->qualifiers, qual) == 0) + goto merr; + } else { + X509V3error(X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; + } + } + if (pol->policyid == NULL) { + X509V3error(X509V3_R_NO_POLICY_IDENTIFIER); + goto err; + } + + return pol; + +merr: + X509V3error(ERR_R_MALLOC_FAILURE); + +err: + POLICYQUALINFO_free(nqual); + POLICYINFO_free(pol); + return NULL; +} + +static POLICYQUALINFO * +notice_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *unot, int ia5org) +{ + int i, ret; + CONF_VALUE *cnf; + USERNOTICE *not; + POLICYQUALINFO *qual; + + if (!(qual = POLICYQUALINFO_new())) + goto merr; + qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice); + if (!(not = USERNOTICE_new())) + goto merr; + qual->d.usernotice = not; + for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { + cnf = sk_CONF_VALUE_value(unot, i); + if (!strcmp(cnf->name, "explicitText")) { + if (not->exptext == NULL) { + not->exptext = ASN1_UTF8STRING_new(); + if (not->exptext == NULL) + goto merr; + } + if (!ASN1_STRING_set(not->exptext, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "organization")) { + NOTICEREF *nref; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + if (ia5org) + nref->organization->type = V_ASN1_IA5STRING; + else + nref->organization->type = V_ASN1_VISIBLESTRING; + if (!ASN1_STRING_set(nref->organization, cnf->value, + strlen(cnf->value))) + goto merr; + } else if (!strcmp(cnf->name, "noticeNumbers")) { + NOTICEREF *nref; + STACK_OF(CONF_VALUE) *nos; + if (!not->noticeref) { + if (!(nref = NOTICEREF_new())) + goto merr; + not->noticeref = nref; + } else + nref = not->noticeref; + nos = X509V3_parse_list(cnf->value); + if (!nos || !sk_CONF_VALUE_num(nos)) { + X509V3error(X509V3_R_INVALID_NUMBERS); + X509V3_conf_err(cnf); + if (nos != NULL) + sk_CONF_VALUE_pop_free(nos, + X509V3_conf_free); + goto err; + } + ret = nref_nos(nref->noticenos, nos); + sk_CONF_VALUE_pop_free(nos, X509V3_conf_free); + if (!ret) + goto err; + } else { + X509V3error(X509V3_R_INVALID_OPTION); + X509V3_conf_err(cnf); + goto err; + } + } + + if (not->noticeref && + (!not->noticeref->noticenos || !not->noticeref->organization)) { + X509V3error(X509V3_R_NEED_ORGANIZATION_AND_NUMBERS); + goto err; + } + + return qual; + +merr: + X509V3error(ERR_R_MALLOC_FAILURE); + +err: + POLICYQUALINFO_free(qual); + return NULL; +} + +static int +nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos) +{ + CONF_VALUE *cnf; + ASN1_INTEGER *aint; + int i; + + for (i = 0; i < sk_CONF_VALUE_num(nos); i++) { + cnf = sk_CONF_VALUE_value(nos, i); + if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) { + X509V3error(X509V3_R_INVALID_NUMBER); + goto err; + } + if (!sk_ASN1_INTEGER_push(nnums, aint)) + goto merr; + } + return 1; + +merr: + X509V3error(ERR_R_MALLOC_FAILURE); + +err: + sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free); + return 0; +} + +static int +i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, + int indent) +{ + int i; + POLICYINFO *pinfo; + + /* First print out the policy OIDs */ + for (i = 0; i < sk_POLICYINFO_num(pol); i++) { + pinfo = sk_POLICYINFO_value(pol, i); + BIO_printf(out, "%*sPolicy: ", indent, ""); + i2a_ASN1_OBJECT(out, pinfo->policyid); + BIO_puts(out, "\n"); + if (pinfo->qualifiers) + print_qualifiers(out, pinfo->qualifiers, indent + 2); + } + return 1; +} + +static void +print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent) +{ + POLICYQUALINFO *qualinfo; + int i; + + for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) { + qualinfo = sk_POLICYQUALINFO_value(quals, i); + switch (OBJ_obj2nid(qualinfo->pqualid)) { + case NID_id_qt_cps: + BIO_printf(out, "%*sCPS: %.*s\n", indent, "", + qualinfo->d.cpsuri->length, + qualinfo->d.cpsuri->data); + break; + + case NID_id_qt_unotice: + BIO_printf(out, "%*sUser Notice:\n", indent, ""); + print_notice(out, qualinfo->d.usernotice, indent + 2); + break; + + default: + BIO_printf(out, "%*sUnknown Qualifier: ", + indent + 2, ""); + + i2a_ASN1_OBJECT(out, qualinfo->pqualid); + BIO_puts(out, "\n"); + break; + } + } +} + +static void +print_notice(BIO *out, USERNOTICE *notice, int indent) +{ + int i; + + if (notice->noticeref) { + NOTICEREF *ref; + ref = notice->noticeref; + BIO_printf(out, "%*sOrganization: %.*s\n", indent, "", + ref->organization->length, ref->organization->data); + BIO_printf(out, "%*sNumber%s: ", indent, "", + sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : ""); + for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) { + ASN1_INTEGER *num; + char *tmp; + num = sk_ASN1_INTEGER_value(ref->noticenos, i); + if (i) + BIO_puts(out, ", "); + tmp = i2s_ASN1_INTEGER(NULL, num); + BIO_puts(out, tmp); + free(tmp); + } + BIO_puts(out, "\n"); + } + if (notice->exptext) + BIO_printf(out, "%*sExplicit Text: %.*s\n", indent, "", + notice->exptext->length, notice->exptext->data); +} diff --git a/crypto/x509/x509_crld.c b/crypto/x509/x509_crld.c new file mode 100644 index 0000000..7887ccd --- /dev/null +++ b/crypto/x509/x509_crld.c @@ -0,0 +1,828 @@ +/* $OpenBSD: x509_crld.c,v 1.5 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#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 = { + .ext_nid = NID_crl_distribution_points, + .ext_flags = 0, + .it = &CRL_DIST_POINTS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_crld, + .i2r = i2r_crldp, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_freshest_crl = { + .ext_nid = NID_freshest_crl, + .ext_flags = 0, + .it = &CRL_DIST_POINTS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_crld, + .i2r = i2r_crldp, + .r2i = NULL, + .usr_data = NULL, +}; + +static STACK_OF(GENERAL_NAME) * +gnames_from_sectname(X509V3_CTX *ctx, char *sect) +{ + STACK_OF(CONF_VALUE) *gnsect; + STACK_OF(GENERAL_NAME) *gens; + + if (*sect == '@') + gnsect = X509V3_get_section(ctx, sect + 1); + else + gnsect = X509V3_parse_list(sect); + if (!gnsect) { + X509V3error(X509V3_R_SECTION_NOT_FOUND); + return NULL; + } + gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect); + if (*sect == '@') + X509V3_section_free(ctx, gnsect); + else + sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free); + return gens; +} + +static int +set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, CONF_VALUE *cnf) +{ + STACK_OF(GENERAL_NAME) *fnm = NULL; + STACK_OF(X509_NAME_ENTRY) *rnm = NULL; + + if (!strncmp(cnf->name, "fullname", 9)) { + fnm = gnames_from_sectname(ctx, cnf->value); + if (!fnm) + goto err; + } else if (!strcmp(cnf->name, "relativename")) { + int ret; + STACK_OF(CONF_VALUE) *dnsect; + X509_NAME *nm; + nm = X509_NAME_new(); + if (!nm) + return -1; + dnsect = X509V3_get_section(ctx, cnf->value); + if (!dnsect) { + X509V3error(X509V3_R_SECTION_NOT_FOUND); + X509_NAME_free(nm); + return -1; + } + ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC); + X509V3_section_free(ctx, dnsect); + rnm = nm->entries; + nm->entries = NULL; + X509_NAME_free(nm); + if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) + goto err; + /* Since its a name fragment can't have more than one + * RDNSequence + */ + if (sk_X509_NAME_ENTRY_value(rnm, + sk_X509_NAME_ENTRY_num(rnm) - 1)->set) { + X509V3error(X509V3_R_INVALID_MULTIPLE_RDNS); + goto err; + } + } else + return 0; + + if (*pdp) { + X509V3error(X509V3_R_DISTPOINT_ALREADY_SET); + goto err; + } + + *pdp = DIST_POINT_NAME_new(); + if (!*pdp) + goto err; + if (fnm) { + (*pdp)->type = 0; + (*pdp)->name.fullname = fnm; + } else { + (*pdp)->type = 1; + (*pdp)->name.relativename = rnm; + } + + return 1; + +err: + sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free); + sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free); + return -1; +} + +static const BIT_STRING_BITNAME reason_flags[] = { + {0, "Unused", "unused"}, + {1, "Key Compromise", "keyCompromise"}, + {2, "CA Compromise", "CACompromise"}, + {3, "Affiliation Changed", "affiliationChanged"}, + {4, "Superseded", "superseded"}, + {5, "Cessation Of Operation", "cessationOfOperation"}, + {6, "Certificate Hold", "certificateHold"}, + {7, "Privilege Withdrawn", "privilegeWithdrawn"}, + {8, "AA Compromise", "AACompromise"}, + {-1, NULL, NULL} +}; + +static int +set_reasons(ASN1_BIT_STRING **preas, char *value) +{ + STACK_OF(CONF_VALUE) *rsk = NULL; + const BIT_STRING_BITNAME *pbn; + const char *bnam; + int i, ret = 0; + + if (*preas != NULL) + return 0; + rsk = X509V3_parse_list(value); + if (rsk == NULL) + return 0; + for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) { + bnam = sk_CONF_VALUE_value(rsk, i)->name; + if (!*preas) { + *preas = ASN1_BIT_STRING_new(); + if (!*preas) + goto err; + } + for (pbn = reason_flags; pbn->lname; pbn++) { + if (!strcmp(pbn->sname, bnam)) { + if (!ASN1_BIT_STRING_set_bit(*preas, + pbn->bitnum, 1)) + goto err; + break; + } + } + if (!pbn->lname) + goto err; + } + ret = 1; + +err: + sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free); + return ret; +} + +static int +print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags, int indent) +{ + int first = 1; + const BIT_STRING_BITNAME *pbn; + + BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, ""); + for (pbn = reason_flags; pbn->lname; pbn++) { + if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) { + if (first) + first = 0; + else + BIO_puts(out, ", "); + BIO_puts(out, pbn->lname); + } + } + if (first) + BIO_puts(out, "\n"); + else + BIO_puts(out, "\n"); + return 1; +} + +static DIST_POINT * +crldp_from_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +{ + int i; + CONF_VALUE *cnf; + DIST_POINT *point = NULL; + + point = DIST_POINT_new(); + if (!point) + goto err; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + int ret; + cnf = sk_CONF_VALUE_value(nval, i); + ret = set_dist_point_name(&point->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (!strcmp(cnf->name, "reasons")) { + if (!set_reasons(&point->reasons, cnf->value)) + goto err; + } + else if (!strcmp(cnf->name, "CRLissuer")) { + point->CRLissuer = + gnames_from_sectname(ctx, cnf->value); + if (!point->CRLissuer) + goto err; + } + } + + return point; + +err: + DIST_POINT_free(point); + return NULL; +} + +static void * +v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + STACK_OF(DIST_POINT) *crld = NULL; + GENERAL_NAMES *gens = NULL; + GENERAL_NAME *gen = NULL; + CONF_VALUE *cnf; + int i; + + if (!(crld = sk_DIST_POINT_new_null())) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + DIST_POINT *point; + cnf = sk_CONF_VALUE_value(nval, i); + if (!cnf->value) { + STACK_OF(CONF_VALUE) *dpsect; + dpsect = X509V3_get_section(ctx, cnf->name); + if (!dpsect) + goto err; + point = crldp_from_section(ctx, dpsect); + X509V3_section_free(ctx, dpsect); + if (!point) + goto err; + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + } else { + if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) + goto err; + if (!(gens = GENERAL_NAMES_new())) + goto merr; + if (!sk_GENERAL_NAME_push(gens, gen)) + goto merr; + gen = NULL; + if (!(point = DIST_POINT_new())) + goto merr; + if (!sk_DIST_POINT_push(crld, point)) { + DIST_POINT_free(point); + goto merr; + } + if (!(point->distpoint = DIST_POINT_NAME_new())) + goto merr; + point->distpoint->name.fullname = gens; + point->distpoint->type = 0; + gens = NULL; + } + } + return crld; + +merr: + X509V3error(ERR_R_MALLOC_FAILURE); +err: + GENERAL_NAME_free(gen); + GENERAL_NAMES_free(gens); + sk_DIST_POINT_pop_free(crld, DIST_POINT_free); + return NULL; +} + +static int +dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) +{ + DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval; + + switch (operation) { + case ASN1_OP_NEW_POST: + dpn->dpname = NULL; + break; + + case ASN1_OP_FREE_POST: + if (dpn->dpname) + X509_NAME_free(dpn->dpname); + break; + } + return 1; +} + + +static const ASN1_AUX DIST_POINT_NAME_aux = { + .app_data = NULL, + .flags = 0, + .ref_offset = 0, + .ref_lock = 0, + .asn1_cb = dpn_cb, + .enc_offset = 0, +}; +static const ASN1_TEMPLATE DIST_POINT_NAME_ch_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = offsetof(DIST_POINT_NAME, name.fullname), + .field_name = "name.fullname", + .item = &GENERAL_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF, + .tag = 1, + .offset = offsetof(DIST_POINT_NAME, name.relativename), + .field_name = "name.relativename", + .item = &X509_NAME_ENTRY_it, + }, +}; + +const ASN1_ITEM DIST_POINT_NAME_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(DIST_POINT_NAME, type), + .templates = DIST_POINT_NAME_ch_tt, + .tcount = sizeof(DIST_POINT_NAME_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = &DIST_POINT_NAME_aux, + .size = sizeof(DIST_POINT_NAME), + .sname = "DIST_POINT_NAME", +}; + + + +DIST_POINT_NAME * +d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, const unsigned char **in, long len) +{ + return (DIST_POINT_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &DIST_POINT_NAME_it); +} +LCRYPTO_ALIAS(d2i_DIST_POINT_NAME); + +int +i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_NAME_it); +} +LCRYPTO_ALIAS(i2d_DIST_POINT_NAME); + +DIST_POINT_NAME * +DIST_POINT_NAME_new(void) +{ + return (DIST_POINT_NAME *)ASN1_item_new(&DIST_POINT_NAME_it); +} +LCRYPTO_ALIAS(DIST_POINT_NAME_new); + +void +DIST_POINT_NAME_free(DIST_POINT_NAME *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_NAME_it); +} +LCRYPTO_ALIAS(DIST_POINT_NAME_free); + +static const ASN1_TEMPLATE DIST_POINT_seq_tt[] = { + { + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(DIST_POINT, distpoint), + .field_name = "distpoint", + .item = &DIST_POINT_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(DIST_POINT, reasons), + .field_name = "reasons", + .item = &ASN1_BIT_STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, + .tag = 2, + .offset = offsetof(DIST_POINT, CRLissuer), + .field_name = "CRLissuer", + .item = &GENERAL_NAME_it, + }, +}; + +const ASN1_ITEM DIST_POINT_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = DIST_POINT_seq_tt, + .tcount = sizeof(DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(DIST_POINT), + .sname = "DIST_POINT", +}; + + +DIST_POINT * +d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len) +{ + return (DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &DIST_POINT_it); +} +LCRYPTO_ALIAS(d2i_DIST_POINT); + +int +i2d_DIST_POINT(DIST_POINT *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_it); +} +LCRYPTO_ALIAS(i2d_DIST_POINT); + +DIST_POINT * +DIST_POINT_new(void) +{ + return (DIST_POINT *)ASN1_item_new(&DIST_POINT_it); +} +LCRYPTO_ALIAS(DIST_POINT_new); + +void +DIST_POINT_free(DIST_POINT *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_it); +} +LCRYPTO_ALIAS(DIST_POINT_free); + +static const ASN1_TEMPLATE CRL_DIST_POINTS_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "CRLDistributionPoints", + .item = &DIST_POINT_it, +}; + +const ASN1_ITEM CRL_DIST_POINTS_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &CRL_DIST_POINTS_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "CRL_DIST_POINTS", +}; + + +CRL_DIST_POINTS * +d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len) +{ + return (CRL_DIST_POINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &CRL_DIST_POINTS_it); +} +LCRYPTO_ALIAS(d2i_CRL_DIST_POINTS); + +int +i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &CRL_DIST_POINTS_it); +} +LCRYPTO_ALIAS(i2d_CRL_DIST_POINTS); + +CRL_DIST_POINTS * +CRL_DIST_POINTS_new(void) +{ + return (CRL_DIST_POINTS *)ASN1_item_new(&CRL_DIST_POINTS_it); +} +LCRYPTO_ALIAS(CRL_DIST_POINTS_new); + +void +CRL_DIST_POINTS_free(CRL_DIST_POINTS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &CRL_DIST_POINTS_it); +} +LCRYPTO_ALIAS(CRL_DIST_POINTS_free); + +static const ASN1_TEMPLATE ISSUING_DIST_POINT_seq_tt[] = { + { + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(ISSUING_DIST_POINT, distpoint), + .field_name = "distpoint", + .item = &DIST_POINT_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(ISSUING_DIST_POINT, onlyuser), + .field_name = "onlyuser", + .item = &ASN1_FBOOLEAN_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 2, + .offset = offsetof(ISSUING_DIST_POINT, onlyCA), + .field_name = "onlyCA", + .item = &ASN1_FBOOLEAN_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 3, + .offset = offsetof(ISSUING_DIST_POINT, onlysomereasons), + .field_name = "onlysomereasons", + .item = &ASN1_BIT_STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 4, + .offset = offsetof(ISSUING_DIST_POINT, indirectCRL), + .field_name = "indirectCRL", + .item = &ASN1_FBOOLEAN_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 5, + .offset = offsetof(ISSUING_DIST_POINT, onlyattr), + .field_name = "onlyattr", + .item = &ASN1_FBOOLEAN_it, + }, +}; + +const ASN1_ITEM ISSUING_DIST_POINT_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = ISSUING_DIST_POINT_seq_tt, + .tcount = sizeof(ISSUING_DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ISSUING_DIST_POINT), + .sname = "ISSUING_DIST_POINT", +}; + + +ISSUING_DIST_POINT * +d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len) +{ + return (ISSUING_DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ISSUING_DIST_POINT_it); +} +LCRYPTO_ALIAS(d2i_ISSUING_DIST_POINT); + +int +i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ISSUING_DIST_POINT_it); +} +LCRYPTO_ALIAS(i2d_ISSUING_DIST_POINT); + +ISSUING_DIST_POINT * +ISSUING_DIST_POINT_new(void) +{ + return (ISSUING_DIST_POINT *)ASN1_item_new(&ISSUING_DIST_POINT_it); +} +LCRYPTO_ALIAS(ISSUING_DIST_POINT_new); + +void +ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ISSUING_DIST_POINT_it); +} +LCRYPTO_ALIAS(ISSUING_DIST_POINT_free); + +static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, + int indent); +static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval); + +const X509V3_EXT_METHOD v3_idp = { + NID_issuing_distribution_point, X509V3_EXT_MULTILINE, + &ISSUING_DIST_POINT_it, + 0, 0, 0, 0, + 0, 0, + 0, + v2i_idp, + i2r_idp, 0, + NULL +}; + +static void * +v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + ISSUING_DIST_POINT *idp = NULL; + CONF_VALUE *cnf; + char *name, *val; + int i, ret; + + idp = ISSUING_DIST_POINT_new(); + if (!idp) + goto merr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + name = cnf->name; + val = cnf->value; + ret = set_dist_point_name(&idp->distpoint, ctx, cnf); + if (ret > 0) + continue; + if (ret < 0) + goto err; + if (!strcmp(name, "onlyuser")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) + goto err; + } + else if (!strcmp(name, "onlyCA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) + goto err; + } + else if (!strcmp(name, "onlyAA")) { + if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) + goto err; + } + else if (!strcmp(name, "indirectCRL")) { + if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) + goto err; + } + else if (!strcmp(name, "onlysomereasons")) { + if (!set_reasons(&idp->onlysomereasons, val)) + goto err; + } else { + X509V3error(X509V3_R_INVALID_NAME); + X509V3_conf_err(cnf); + goto err; + } + } + return idp; + +merr: + X509V3error(ERR_R_MALLOC_FAILURE); +err: + ISSUING_DIST_POINT_free(idp); + return NULL; +} + +static int +print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) +{ + int i; + + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + BIO_printf(out, "%*s", indent + 2, ""); + GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i)); + BIO_puts(out, "\n"); + } + return 1; +} + +static int +print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) +{ + if (dpn->type == 0) { + BIO_printf(out, "%*sFull Name:\n", indent, ""); + print_gens(out, dpn->name.fullname, indent); + } else { + X509_NAME ntmp; + ntmp.entries = dpn->name.relativename; + BIO_printf(out, "%*sRelative Name:\n%*s", + indent, "", indent + 2, ""); + X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE); + BIO_puts(out, "\n"); + } + return 1; +} + +static int +i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent) +{ + ISSUING_DIST_POINT *idp = pidp; + + if (idp->distpoint) + print_distpoint(out, idp->distpoint, indent); + if (idp->onlyuser > 0) + BIO_printf(out, "%*sOnly User Certificates\n", indent, ""); + if (idp->onlyCA > 0) + BIO_printf(out, "%*sOnly CA Certificates\n", indent, ""); + if (idp->indirectCRL > 0) + BIO_printf(out, "%*sIndirect CRL\n", indent, ""); + if (idp->onlysomereasons) + print_reasons(out, "Only Some Reasons", + idp->onlysomereasons, indent); + if (idp->onlyattr > 0) + BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, ""); + if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) && + (idp->indirectCRL <= 0) && !idp->onlysomereasons && + (idp->onlyattr <= 0)) + BIO_printf(out, "%*s\n", indent, ""); + + return 1; +} + +static int +i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent) +{ + STACK_OF(DIST_POINT) *crld = pcrldp; + DIST_POINT *point; + int i; + + for (i = 0; i < sk_DIST_POINT_num(crld); i++) { + BIO_puts(out, "\n"); + point = sk_DIST_POINT_value(crld, i); + if (point->distpoint) + print_distpoint(out, point->distpoint, indent); + if (point->reasons) + print_reasons(out, "Reasons", point->reasons, + indent); + if (point->CRLissuer) { + BIO_printf(out, "%*sCRL Issuer:\n", indent, ""); + print_gens(out, point->CRLissuer, indent); + } + } + return 1; +} + +int +DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) +{ + int i; + STACK_OF(X509_NAME_ENTRY) *frag; + X509_NAME_ENTRY *ne; + + if (!dpn || (dpn->type != 1)) + return 1; + frag = dpn->name.relativename; + dpn->dpname = X509_NAME_dup(iname); + if (!dpn->dpname) + return 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) { + ne = sk_X509_NAME_ENTRY_value(frag, i); + if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + } + /* generate cached encoding of name */ + if (i2d_X509_NAME(dpn->dpname, NULL) < 0) { + X509_NAME_free(dpn->dpname); + dpn->dpname = NULL; + return 0; + } + return 1; +} +LCRYPTO_ALIAS(DIST_POINT_set_dpname); diff --git a/crypto/x509/x509_d2.c b/crypto/x509/x509_d2.c new file mode 100644 index 0000000..bf358ec --- /dev/null +++ b/crypto/x509/x509_d2.c @@ -0,0 +1,131 @@ +/* $OpenBSD: x509_d2.c,v 1.12 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include +#include + +int +X509_STORE_set_default_paths(X509_STORE *ctx) +{ + 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); + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); + if (lookup == NULL) + return (0); + X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); + + /* clear any errors */ + ERR_clear_error(); + + return (1); +} +LCRYPTO_ALIAS(X509_STORE_set_default_paths); + +int +X509_STORE_load_locations(X509_STORE *ctx, const char *file, const char *path) +{ + 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)) + return (0); + return (1); +} +LCRYPTO_ALIAS(X509_STORE_load_locations); + +int +X509_STORE_load_mem(X509_STORE *ctx, void *buf, int len) +{ + X509_LOOKUP *lookup; + struct iovec iov; + + lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_mem()); + if (lookup == NULL) + return (0); + + iov.iov_base = buf; + iov.iov_len = len; + + if (X509_LOOKUP_add_mem(lookup, &iov, X509_FILETYPE_PEM) != 1) + return (0); + + return (1); +} +LCRYPTO_ALIAS(X509_STORE_load_mem); diff --git a/crypto/x509/x509_def.c b/crypto/x509/x509_def.c new file mode 100644 index 0000000..f85781a --- /dev/null +++ b/crypto/x509/x509_def.c @@ -0,0 +1,104 @@ +/* $OpenBSD: x509_def.c,v 1.7 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include "cryptlib.h" +#include +#include + +const char * +X509_get_default_private_dir(void) +{ + return (X509_PRIVATE_DIR); +} +LCRYPTO_ALIAS(X509_get_default_private_dir); + +const char * +X509_get_default_cert_area(void) +{ + return (X509_CERT_AREA); +} +LCRYPTO_ALIAS(X509_get_default_cert_area); + +const char * +X509_get_default_cert_dir(void) +{ + return (X509_CERT_DIR); +} +LCRYPTO_ALIAS(X509_get_default_cert_dir); + +const char * +X509_get_default_cert_file(void) +{ + return (X509_CERT_FILE); +} +LCRYPTO_ALIAS(X509_get_default_cert_file); + +const char * +X509_get_default_cert_dir_env(void) +{ + return (X509_CERT_DIR_EVP); +} +LCRYPTO_ALIAS(X509_get_default_cert_dir_env); + +const char * +X509_get_default_cert_file_env(void) +{ + return (X509_CERT_FILE_EVP); +} +LCRYPTO_ALIAS(X509_get_default_cert_file_env); diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c new file mode 100644 index 0000000..2cbd349 --- /dev/null +++ b/crypto/x509/x509_err.c @@ -0,0 +1,213 @@ +/* $OpenBSD: x509_err.c,v 1.22 2023/05/14 17:20:26 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include + +#include +#include +#include + +#ifndef OPENSSL_NO_ERR + +#define ERR_FUNC(func) ERR_PACK(ERR_LIB_X509,func,0) +#define ERR_REASON(reason) ERR_PACK(ERR_LIB_X509,0,reason) + +static ERR_STRING_DATA X509_str_functs[] = { + {ERR_FUNC(0xfff), "CRYPTO_internal"}, + {0, NULL} +}; + +static ERR_STRING_DATA X509_str_reasons[] = { + {ERR_REASON(X509_R_BAD_X509_FILETYPE) , "bad x509 filetype"}, + {ERR_REASON(X509_R_BASE64_DECODE_ERROR) , "base64 decode error"}, + {ERR_REASON(X509_R_CANT_CHECK_DH_KEY) , "cant check dh key"}, + {ERR_REASON(X509_R_CERT_ALREADY_IN_HASH_TABLE), "cert already in hash table"}, + {ERR_REASON(X509_R_ERR_ASN1_LIB) , "err asn1 lib"}, + {ERR_REASON(X509_R_INVALID_DIRECTORY) , "invalid directory"}, + {ERR_REASON(X509_R_INVALID_FIELD_NAME) , "invalid field name"}, + {ERR_REASON(X509_R_INVALID_TRUST) , "invalid trust"}, + {ERR_REASON(X509_R_INVALID_VERSION) , "invalid x509 version"}, + {ERR_REASON(X509_R_KEY_TYPE_MISMATCH) , "key type mismatch"}, + {ERR_REASON(X509_R_KEY_VALUES_MISMATCH) , "key values mismatch"}, + {ERR_REASON(X509_R_LOADING_CERT_DIR) , "loading cert dir"}, + {ERR_REASON(X509_R_LOADING_DEFAULTS) , "loading defaults"}, + {ERR_REASON(X509_R_METHOD_NOT_SUPPORTED) , "method not supported"}, + {ERR_REASON(X509_R_NO_CERTIFICATE_OR_CRL_FOUND), "no certificate or crl found"}, + {ERR_REASON(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), "no cert set for us to verify"}, + {ERR_REASON(X509_R_PUBLIC_KEY_DECODE_ERROR), "public key decode error"}, + {ERR_REASON(X509_R_PUBLIC_KEY_ENCODE_ERROR), "public key encode error"}, + {ERR_REASON(X509_R_SHOULD_RETRY) , "should retry"}, + {ERR_REASON(X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), "unable to find parameters in chain"}, + {ERR_REASON(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), "unable to get certs public key"}, + {ERR_REASON(X509_R_UNKNOWN_KEY_TYPE) , "unknown key type"}, + {ERR_REASON(X509_R_UNKNOWN_NID) , "unknown nid"}, + {ERR_REASON(X509_R_UNKNOWN_PURPOSE_ID) , "unknown purpose id"}, + {ERR_REASON(X509_R_UNKNOWN_TRUST_ID) , "unknown trust id"}, + {ERR_REASON(X509_R_UNSUPPORTED_ALGORITHM), "unsupported algorithm"}, + {ERR_REASON(X509_R_WRONG_LOOKUP_TYPE) , "wrong lookup type"}, + {ERR_REASON(X509_R_WRONG_TYPE) , "wrong type"}, + {0, NULL} +}; + +#undef ERR_FUNC +#undef ERR_REASON +#define ERR_FUNC(func) ERR_PACK(ERR_LIB_X509V3,func,0) +#define ERR_REASON(reason) ERR_PACK(ERR_LIB_X509V3,0,reason) + +static ERR_STRING_DATA X509V3_str_functs[] = { + {ERR_FUNC(0xfff), "CRYPTO_internal"}, + {0, NULL} +}; + +static ERR_STRING_DATA X509V3_str_reasons[] = { + {ERR_REASON(X509V3_R_BAD_IP_ADDRESS) , "bad ip address"}, + {ERR_REASON(X509V3_R_BAD_OBJECT) , "bad object"}, + {ERR_REASON(X509V3_R_BN_DEC2BN_ERROR) , "bn dec2bn error"}, + {ERR_REASON(X509V3_R_BN_TO_ASN1_INTEGER_ERROR), "bn to asn1 integer error"}, + {ERR_REASON(X509V3_R_DIRNAME_ERROR) , "dirname error"}, + {ERR_REASON(X509V3_R_DISTPOINT_ALREADY_SET), "distpoint already set"}, + {ERR_REASON(X509V3_R_DUPLICATE_ZONE_ID) , "duplicate zone id"}, + {ERR_REASON(X509V3_R_ERROR_CONVERTING_ZONE), "error converting zone"}, + {ERR_REASON(X509V3_R_ERROR_CREATING_EXTENSION), "error creating extension"}, + {ERR_REASON(X509V3_R_ERROR_IN_EXTENSION) , "error in extension"}, + {ERR_REASON(X509V3_R_EXPECTED_A_SECTION_NAME), "expected a section name"}, + {ERR_REASON(X509V3_R_EXTENSION_EXISTS) , "extension exists"}, + {ERR_REASON(X509V3_R_EXTENSION_NAME_ERROR), "extension name error"}, + {ERR_REASON(X509V3_R_EXTENSION_NOT_FOUND), "extension not found"}, + {ERR_REASON(X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED), "extension setting not supported"}, + {ERR_REASON(X509V3_R_EXTENSION_VALUE_ERROR), "extension value error"}, + {ERR_REASON(X509V3_R_ILLEGAL_EMPTY_EXTENSION), "illegal empty extension"}, + {ERR_REASON(X509V3_R_ILLEGAL_HEX_DIGIT) , "illegal hex digit"}, + {ERR_REASON(X509V3_R_INCORRECT_POLICY_SYNTAX_TAG), "incorrect policy syntax tag"}, + {ERR_REASON(X509V3_R_INVALID_MULTIPLE_RDNS), "invalid multiple rdns"}, + {ERR_REASON(X509V3_R_INVALID_ASNUMBER) , "invalid asnumber"}, + {ERR_REASON(X509V3_R_INVALID_ASRANGE) , "invalid asrange"}, + {ERR_REASON(X509V3_R_INVALID_BOOLEAN_STRING), "invalid boolean string"}, + {ERR_REASON(X509V3_R_INVALID_EXTENSION_STRING), "invalid extension string"}, + {ERR_REASON(X509V3_R_INVALID_INHERITANCE), "invalid inheritance"}, + {ERR_REASON(X509V3_R_INVALID_IPADDRESS) , "invalid ipaddress"}, + {ERR_REASON(X509V3_R_INVALID_NAME) , "invalid name"}, + {ERR_REASON(X509V3_R_INVALID_NULL_ARGUMENT), "invalid null argument"}, + {ERR_REASON(X509V3_R_INVALID_NULL_NAME) , "invalid null name"}, + {ERR_REASON(X509V3_R_INVALID_NULL_VALUE) , "invalid null value"}, + {ERR_REASON(X509V3_R_INVALID_NUMBER) , "invalid number"}, + {ERR_REASON(X509V3_R_INVALID_NUMBERS) , "invalid numbers"}, + {ERR_REASON(X509V3_R_INVALID_OBJECT_IDENTIFIER), "invalid object identifier"}, + {ERR_REASON(X509V3_R_INVALID_OPTION) , "invalid option"}, + {ERR_REASON(X509V3_R_INVALID_POLICY_IDENTIFIER), "invalid policy identifier"}, + {ERR_REASON(X509V3_R_INVALID_PROXY_POLICY_SETTING), "invalid proxy policy setting"}, + {ERR_REASON(X509V3_R_INVALID_PURPOSE) , "invalid purpose"}, + {ERR_REASON(X509V3_R_INVALID_SAFI) , "invalid safi"}, + {ERR_REASON(X509V3_R_INVALID_SECTION) , "invalid section"}, + {ERR_REASON(X509V3_R_INVALID_SYNTAX) , "invalid syntax"}, + {ERR_REASON(X509V3_R_ISSUER_DECODE_ERROR), "issuer decode error"}, + {ERR_REASON(X509V3_R_MISSING_VALUE) , "missing value"}, + {ERR_REASON(X509V3_R_NEED_ORGANIZATION_AND_NUMBERS), "need organization and numbers"}, + {ERR_REASON(X509V3_R_NO_CONFIG_DATABASE) , "no config database"}, + {ERR_REASON(X509V3_R_NO_ISSUER_CERTIFICATE), "no issuer certificate"}, + {ERR_REASON(X509V3_R_NO_ISSUER_DETAILS) , "no issuer details"}, + {ERR_REASON(X509V3_R_NO_POLICY_IDENTIFIER), "no policy identifier"}, + {ERR_REASON(X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED), "no proxy cert policy language defined"}, + {ERR_REASON(X509V3_R_NO_PUBLIC_KEY) , "no public key"}, + {ERR_REASON(X509V3_R_NO_SUBJECT_DETAILS) , "no subject details"}, + {ERR_REASON(X509V3_R_ODD_NUMBER_OF_DIGITS), "odd number of digits"}, + {ERR_REASON(X509V3_R_OPERATION_NOT_DEFINED), "operation not defined"}, + {ERR_REASON(X509V3_R_OTHERNAME_ERROR) , "othername error"}, + {ERR_REASON(X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED), "policy language already defined"}, + {ERR_REASON(X509V3_R_POLICY_PATH_LENGTH) , "policy path length"}, + {ERR_REASON(X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED), "policy path length already defined"}, + {ERR_REASON(X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED), "policy syntax not currently supported"}, + {ERR_REASON(X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY), "policy when proxy language requires no policy"}, + {ERR_REASON(X509V3_R_SECTION_NOT_FOUND) , "section not found"}, + {ERR_REASON(X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS), "unable to get issuer details"}, + {ERR_REASON(X509V3_R_UNABLE_TO_GET_ISSUER_KEYID), "unable to get issuer keyid"}, + {ERR_REASON(X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT), "unknown bit string argument"}, + {ERR_REASON(X509V3_R_UNKNOWN_EXTENSION) , "unknown extension"}, + {ERR_REASON(X509V3_R_UNKNOWN_EXTENSION_NAME), "unknown extension name"}, + {ERR_REASON(X509V3_R_UNKNOWN_OPTION) , "unknown option"}, + {ERR_REASON(X509V3_R_UNSUPPORTED_OPTION) , "unsupported option"}, + {ERR_REASON(X509V3_R_UNSUPPORTED_TYPE) , "unsupported type"}, + {ERR_REASON(X509V3_R_USER_TOO_LONG) , "user too long"}, + {0, NULL} +}; + +#endif + +void +ERR_load_X509_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(X509_str_functs[0].error) == NULL) { + ERR_load_strings(0, X509_str_functs); + ERR_load_strings(0, X509_str_reasons); + } +#endif +} +LCRYPTO_ALIAS(ERR_load_X509_strings); + + +void +ERR_load_X509V3_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(X509V3_str_functs[0].error) == NULL) { + ERR_load_strings(0, X509V3_str_functs); + ERR_load_strings(0, X509V3_str_reasons); + } +#endif +} +LCRYPTO_ALIAS(ERR_load_X509V3_strings); diff --git a/crypto/x509/x509_ext.c b/crypto/x509/x509_ext.c new file mode 100644 index 0000000..ce316d2 --- /dev/null +++ b/crypto/x509/x509_ext.c @@ -0,0 +1,262 @@ +/* $OpenBSD: x509_ext.c,v 1.16 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +int +X509_CRL_get_ext_count(const X509_CRL *x) +{ + return (X509v3_get_ext_count(x->crl->extensions)); +} +LCRYPTO_ALIAS(X509_CRL_get_ext_count); + +int +X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos)); +} +LCRYPTO_ALIAS(X509_CRL_get_ext_by_NID); + +int +X509_CRL_get_ext_by_OBJ(const X509_CRL *x, const ASN1_OBJECT *obj, int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos)); +} +LCRYPTO_ALIAS(X509_CRL_get_ext_by_OBJ); + +int +X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos)); +} +LCRYPTO_ALIAS(X509_CRL_get_ext_by_critical); + +X509_EXTENSION * +X509_CRL_get_ext(const X509_CRL *x, int loc) +{ + return (X509v3_get_ext(x->crl->extensions, loc)); +} +LCRYPTO_ALIAS(X509_CRL_get_ext); + +X509_EXTENSION * +X509_CRL_delete_ext(X509_CRL *x, int loc) +{ + return (X509v3_delete_ext(x->crl->extensions, loc)); +} +LCRYPTO_ALIAS(X509_CRL_delete_ext); + +void * +X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->crl->extensions, nid, crit, idx); +} +LCRYPTO_ALIAS(X509_CRL_get_ext_d2i); + +int +X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags); +} +LCRYPTO_ALIAS(X509_CRL_add1_ext_i2d); + +int +X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL); +} +LCRYPTO_ALIAS(X509_CRL_add_ext); + +int +X509_get_ext_count(const X509 *x) +{ + return (X509v3_get_ext_count(x->cert_info->extensions)); +} +LCRYPTO_ALIAS(X509_get_ext_count); + +int +X509_get_ext_by_NID(const X509 *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos)); +} +LCRYPTO_ALIAS(X509_get_ext_by_NID); + +int +X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos)); +} +LCRYPTO_ALIAS(X509_get_ext_by_OBJ); + +int +X509_get_ext_by_critical(const X509 *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical(x->cert_info->extensions, crit, + lastpos)); +} +LCRYPTO_ALIAS(X509_get_ext_by_critical); + +X509_EXTENSION * +X509_get_ext(const X509 *x, int loc) +{ + return (X509v3_get_ext(x->cert_info->extensions, loc)); +} +LCRYPTO_ALIAS(X509_get_ext); + +X509_EXTENSION * +X509_delete_ext(X509 *x, int loc) +{ + return (X509v3_delete_ext(x->cert_info->extensions, loc)); +} +LCRYPTO_ALIAS(X509_delete_ext); + +int +X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL); +} +LCRYPTO_ALIAS(X509_add_ext); + +void * +X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx); +} +LCRYPTO_ALIAS(X509_get_ext_d2i); + +int +X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, unsigned long flags) +{ + return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit, + flags); +} +LCRYPTO_ALIAS(X509_add1_ext_i2d); + +int +X509_REVOKED_get_ext_count(const X509_REVOKED *x) +{ + return (X509v3_get_ext_count(x->extensions)); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext_count); + +int +X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, int lastpos) +{ + return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos)); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext_by_NID); + +int +X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, const ASN1_OBJECT *obj, + int lastpos) +{ + return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos)); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext_by_OBJ); + +int +X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, int crit, int lastpos) +{ + return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos)); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext_by_critical); + +X509_EXTENSION * +X509_REVOKED_get_ext(const X509_REVOKED *x, int loc) +{ + return (X509v3_get_ext(x->extensions, loc)); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext); + +X509_EXTENSION * +X509_REVOKED_delete_ext(X509_REVOKED *x, int loc) +{ + return (X509v3_delete_ext(x->extensions, loc)); +} +LCRYPTO_ALIAS(X509_REVOKED_delete_ext); + +int +X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc) +{ + return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL); +} +LCRYPTO_ALIAS(X509_REVOKED_add_ext); + +void * +X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, int *crit, int *idx) +{ + return X509V3_get_d2i(x->extensions, nid, crit, idx); +} +LCRYPTO_ALIAS(X509_REVOKED_get_ext_d2i); + +int +X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit, + unsigned long flags) +{ + return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags); +} +LCRYPTO_ALIAS(X509_REVOKED_add1_ext_i2d); diff --git a/crypto/x509/x509_extku.c b/crypto/x509/x509_extku.c new file mode 100644 index 0000000..94032f6 --- /dev/null +++ b/crypto/x509/x509_extku.c @@ -0,0 +1,221 @@ +/* $OpenBSD: x509_extku.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include + +static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE( + const X509V3_EXT_METHOD *method, void *eku, STACK_OF(CONF_VALUE) *extlist); + +const X509V3_EXT_METHOD v3_ext_ku = { + .ext_nid = NID_ext_key_usage, + .ext_flags = 0, + .it = &EXTENDED_KEY_USAGE_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = i2v_EXTENDED_KEY_USAGE, + .v2i = v2i_EXTENDED_KEY_USAGE, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +/* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */ +const X509V3_EXT_METHOD v3_ocsp_accresp = { + .ext_nid = NID_id_pkix_OCSP_acceptableResponses, + .ext_flags = 0, + .it = &EXTENDED_KEY_USAGE_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = i2v_EXTENDED_KEY_USAGE, + .v2i = v2i_EXTENDED_KEY_USAGE, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE EXTENDED_KEY_USAGE_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "EXTENDED_KEY_USAGE", + .item = &ASN1_OBJECT_it, +}; + +const ASN1_ITEM EXTENDED_KEY_USAGE_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &EXTENDED_KEY_USAGE_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "EXTENDED_KEY_USAGE", +}; + + +EXTENDED_KEY_USAGE * +d2i_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE **a, const unsigned char **in, long len) +{ + return (EXTENDED_KEY_USAGE *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &EXTENDED_KEY_USAGE_it); +} +LCRYPTO_ALIAS(d2i_EXTENDED_KEY_USAGE); + +int +i2d_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &EXTENDED_KEY_USAGE_it); +} +LCRYPTO_ALIAS(i2d_EXTENDED_KEY_USAGE); + +EXTENDED_KEY_USAGE * +EXTENDED_KEY_USAGE_new(void) +{ + return (EXTENDED_KEY_USAGE *)ASN1_item_new(&EXTENDED_KEY_USAGE_it); +} +LCRYPTO_ALIAS(EXTENDED_KEY_USAGE_new); + +void +EXTENDED_KEY_USAGE_free(EXTENDED_KEY_USAGE *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &EXTENDED_KEY_USAGE_it); +} +LCRYPTO_ALIAS(EXTENDED_KEY_USAGE_free); + +static STACK_OF(CONF_VALUE) * +i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, void *a, + STACK_OF(CONF_VALUE) *extlist) +{ + ASN1_OBJECT *obj; + EXTENDED_KEY_USAGE *eku = a; + STACK_OF(CONF_VALUE) *free_extlist = NULL; + char obj_tmp[80]; + int i; + + if (extlist == NULL) { + if ((free_extlist = extlist = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + if ((obj = sk_ASN1_OBJECT_value(eku, i)) == NULL) + goto err; + if (!i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, obj)) + goto err; + if (!X509V3_add_value(NULL, obj_tmp, &extlist)) + goto err; + } + + return extlist; + + err: + sk_CONF_VALUE_pop_free(free_extlist, X509V3_conf_free); + + return NULL; +} + +static void * +v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + EXTENDED_KEY_USAGE *extku; + char *extval; + ASN1_OBJECT *objtmp; + CONF_VALUE *val; + int i; + + if (!(extku = sk_ASN1_OBJECT_new_null())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (val->value) + extval = val->value; + else + extval = val->name; + if (!(objtmp = OBJ_txt2obj(extval, 0))) { + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + X509V3error(X509V3_R_INVALID_OBJECT_IDENTIFIER); + X509V3_conf_err(val); + return NULL; + } + if (sk_ASN1_OBJECT_push(extku, objtmp) == 0) { + ASN1_OBJECT_free(objtmp); + sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free); + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + } + return extku; +} diff --git a/crypto/x509/x509_genn.c b/crypto/x509/x509_genn.c new file mode 100644 index 0000000..556ba81 --- /dev/null +++ b/crypto/x509/x509_genn.c @@ -0,0 +1,537 @@ +/* $OpenBSD: x509_genn.c,v 1.6 2023/04/25 15:51:04 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + +#include + +#include +#include +#include + +static const ASN1_TEMPLATE OTHERNAME_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(OTHERNAME, type_id), + .field_name = "type_id", + .item = &ASN1_OBJECT_it, + }, + /* Maybe have a true ANY DEFINED BY later */ + { + .flags = ASN1_TFLG_EXPLICIT, + .tag = 0, + .offset = offsetof(OTHERNAME, value), + .field_name = "value", + .item = &ASN1_ANY_it, + }, +}; + +const ASN1_ITEM OTHERNAME_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = OTHERNAME_seq_tt, + .tcount = sizeof(OTHERNAME_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(OTHERNAME), + .sname = "OTHERNAME", +}; + + +OTHERNAME * +d2i_OTHERNAME(OTHERNAME **a, const unsigned char **in, long len) +{ + return (OTHERNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &OTHERNAME_it); +} +LCRYPTO_ALIAS(d2i_OTHERNAME); + +int +i2d_OTHERNAME(OTHERNAME *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &OTHERNAME_it); +} +LCRYPTO_ALIAS(i2d_OTHERNAME); + +OTHERNAME * +OTHERNAME_new(void) +{ + return (OTHERNAME *)ASN1_item_new(&OTHERNAME_it); +} +LCRYPTO_ALIAS(OTHERNAME_new); + +void +OTHERNAME_free(OTHERNAME *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &OTHERNAME_it); +} +LCRYPTO_ALIAS(OTHERNAME_free); + +/* Uses explicit tagging since DIRECTORYSTRING is a CHOICE type */ +static const ASN1_TEMPLATE EDIPARTYNAME_seq_tt[] = { + { + .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(EDIPARTYNAME, nameAssigner), + .field_name = "nameAssigner", + .item = &DIRECTORYSTRING_it, + }, + { + .flags = ASN1_TFLG_EXPLICIT, + .tag = 1, + .offset = offsetof(EDIPARTYNAME, partyName), + .field_name = "partyName", + .item = &DIRECTORYSTRING_it, + }, +}; + +const ASN1_ITEM EDIPARTYNAME_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = EDIPARTYNAME_seq_tt, + .tcount = sizeof(EDIPARTYNAME_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(EDIPARTYNAME), + .sname = "EDIPARTYNAME", +}; + + +EDIPARTYNAME * +d2i_EDIPARTYNAME(EDIPARTYNAME **a, const unsigned char **in, long len) +{ + return (EDIPARTYNAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &EDIPARTYNAME_it); +} +LCRYPTO_ALIAS(d2i_EDIPARTYNAME); + +int +i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &EDIPARTYNAME_it); +} +LCRYPTO_ALIAS(i2d_EDIPARTYNAME); + +EDIPARTYNAME * +EDIPARTYNAME_new(void) +{ + return (EDIPARTYNAME *)ASN1_item_new(&EDIPARTYNAME_it); +} +LCRYPTO_ALIAS(EDIPARTYNAME_new); + +void +EDIPARTYNAME_free(EDIPARTYNAME *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &EDIPARTYNAME_it); +} +LCRYPTO_ALIAS(EDIPARTYNAME_free); + +static const ASN1_TEMPLATE GENERAL_NAME_ch_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_OTHERNAME, + .offset = offsetof(GENERAL_NAME, d.otherName), + .field_name = "d.otherName", + .item = &OTHERNAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_EMAIL, + .offset = offsetof(GENERAL_NAME, d.rfc822Name), + .field_name = "d.rfc822Name", + .item = &ASN1_IA5STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_DNS, + .offset = offsetof(GENERAL_NAME, d.dNSName), + .field_name = "d.dNSName", + .item = &ASN1_IA5STRING_it, + }, + /* Don't decode this */ + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_X400, + .offset = offsetof(GENERAL_NAME, d.x400Address), + .field_name = "d.x400Address", + .item = &ASN1_SEQUENCE_it, + }, + /* X509_NAME is a CHOICE type so use EXPLICIT */ + { + .flags = ASN1_TFLG_EXPLICIT, + .tag = GEN_DIRNAME, + .offset = offsetof(GENERAL_NAME, d.directoryName), + .field_name = "d.directoryName", + .item = &X509_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_EDIPARTY, + .offset = offsetof(GENERAL_NAME, d.ediPartyName), + .field_name = "d.ediPartyName", + .item = &EDIPARTYNAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_URI, + .offset = offsetof(GENERAL_NAME, d.uniformResourceIdentifier), + .field_name = "d.uniformResourceIdentifier", + .item = &ASN1_IA5STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_IPADD, + .offset = offsetof(GENERAL_NAME, d.iPAddress), + .field_name = "d.iPAddress", + .item = &ASN1_OCTET_STRING_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT, + .tag = GEN_RID, + .offset = offsetof(GENERAL_NAME, d.registeredID), + .field_name = "d.registeredID", + .item = &ASN1_OBJECT_it, + }, +}; + +const ASN1_ITEM GENERAL_NAME_it = { + .itype = ASN1_ITYPE_CHOICE, + .utype = offsetof(GENERAL_NAME, type), + .templates = GENERAL_NAME_ch_tt, + .tcount = sizeof(GENERAL_NAME_ch_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(GENERAL_NAME), + .sname = "GENERAL_NAME", +}; + + +GENERAL_NAME * +d2i_GENERAL_NAME(GENERAL_NAME **a, const unsigned char **in, long len) +{ + return (GENERAL_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &GENERAL_NAME_it); +} +LCRYPTO_ALIAS(d2i_GENERAL_NAME); + +int +i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAME_it); +} +LCRYPTO_ALIAS(i2d_GENERAL_NAME); + +GENERAL_NAME * +GENERAL_NAME_new(void) +{ + return (GENERAL_NAME *)ASN1_item_new(&GENERAL_NAME_it); +} +LCRYPTO_ALIAS(GENERAL_NAME_new); + +void +GENERAL_NAME_free(GENERAL_NAME *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAME_it); +} +LCRYPTO_ALIAS(GENERAL_NAME_free); + +static const ASN1_TEMPLATE GENERAL_NAMES_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "GeneralNames", + .item = &GENERAL_NAME_it, +}; + +const ASN1_ITEM GENERAL_NAMES_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &GENERAL_NAMES_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "GENERAL_NAMES", +}; + + +GENERAL_NAMES * +d2i_GENERAL_NAMES(GENERAL_NAMES **a, const unsigned char **in, long len) +{ + return (GENERAL_NAMES *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &GENERAL_NAMES_it); +} +LCRYPTO_ALIAS(d2i_GENERAL_NAMES); + +int +i2d_GENERAL_NAMES(GENERAL_NAMES *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &GENERAL_NAMES_it); +} +LCRYPTO_ALIAS(i2d_GENERAL_NAMES); + +GENERAL_NAMES * +GENERAL_NAMES_new(void) +{ + return (GENERAL_NAMES *)ASN1_item_new(&GENERAL_NAMES_it); +} +LCRYPTO_ALIAS(GENERAL_NAMES_new); + +void +GENERAL_NAMES_free(GENERAL_NAMES *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &GENERAL_NAMES_it); +} +LCRYPTO_ALIAS(GENERAL_NAMES_free); + +GENERAL_NAME * +GENERAL_NAME_dup(GENERAL_NAME *a) +{ + return ASN1_item_dup(&GENERAL_NAME_it, a); +} +LCRYPTO_ALIAS(GENERAL_NAME_dup); + +static int +EDIPARTYNAME_cmp(const EDIPARTYNAME *a, const EDIPARTYNAME *b) +{ + int res; + + /* + * Shouldn't be possible in a valid GENERAL_NAME, but we handle it + * anyway. OTHERNAME_cmp treats NULL != NULL, so we do the same here. + */ + if (a == NULL || b == NULL) + return -1; + if (a->nameAssigner == NULL && b->nameAssigner != NULL) + return -1; + if (a->nameAssigner != NULL && b->nameAssigner == NULL) + return 1; + /* If we get here, both have nameAssigner set or both unset. */ + if (a->nameAssigner != NULL) { + res = ASN1_STRING_cmp(a->nameAssigner, b->nameAssigner); + if (res != 0) + return res; + } + /* + * partyName is required, so these should never be NULL. We treat it in + * the same way as the a == NULL || b == NULL case above. + */ + if (a->partyName == NULL || b->partyName == NULL) + return -1; + + return ASN1_STRING_cmp(a->partyName, b->partyName); +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int +GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b) +{ + int result = -1; + + if (!a || !b || a->type != b->type) + return -1; + switch (a->type) { + case GEN_X400: + result = ASN1_STRING_cmp(a->d.x400Address, b->d.x400Address); + break; + + case GEN_EDIPARTY: + result = EDIPARTYNAME_cmp(a->d.ediPartyName, b->d.ediPartyName); + break; + + case GEN_OTHERNAME: + result = OTHERNAME_cmp(a->d.otherName, b->d.otherName); + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5); + break; + + case GEN_DIRNAME: + result = X509_NAME_cmp(a->d.dirn, b->d.dirn); + break; + + case GEN_IPADD: + result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip); + break; + + case GEN_RID: + result = OBJ_cmp(a->d.rid, b->d.rid); + break; + } + return result; +} +LCRYPTO_ALIAS(GENERAL_NAME_cmp); + +/* Returns 0 if they are equal, != 0 otherwise. */ +int +OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b) +{ + int result = -1; + + if (!a || !b) + return -1; + /* Check their type first. */ + if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0) + return result; + /* Check the value. */ + result = ASN1_TYPE_cmp(a->value, b->value); + return result; +} +LCRYPTO_ALIAS(OTHERNAME_cmp); + +void +GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value) +{ + switch (type) { + case GEN_X400: + a->d.x400Address = value; + break; + + case GEN_EDIPARTY: + a->d.ediPartyName = value; + break; + + case GEN_OTHERNAME: + a->d.otherName = value; + break; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + a->d.ia5 = value; + break; + + case GEN_DIRNAME: + a->d.dirn = value; + break; + + case GEN_IPADD: + a->d.ip = value; + break; + + case GEN_RID: + a->d.rid = value; + break; + } + a->type = type; +} +LCRYPTO_ALIAS(GENERAL_NAME_set0_value); + +void * +GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype) +{ + if (ptype) + *ptype = a->type; + switch (a->type) { + case GEN_X400: + return a->d.x400Address; + + case GEN_EDIPARTY: + return a->d.ediPartyName; + + case GEN_OTHERNAME: + return a->d.otherName; + + case GEN_EMAIL: + case GEN_DNS: + case GEN_URI: + return a->d.ia5; + + case GEN_DIRNAME: + return a->d.dirn; + + case GEN_IPADD: + return a->d.ip; + + case GEN_RID: + return a->d.rid; + + default: + return NULL; + } +} +LCRYPTO_ALIAS(GENERAL_NAME_get0_value); + +int +GENERAL_NAME_set0_othername(GENERAL_NAME *gen, ASN1_OBJECT *oid, + ASN1_TYPE *value) +{ + OTHERNAME *oth; + + oth = OTHERNAME_new(); + if (!oth) + return 0; + oth->type_id = oid; + oth->value = value; + GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth); + return 1; +} +LCRYPTO_ALIAS(GENERAL_NAME_set0_othername); + +int +GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, ASN1_OBJECT **poid, + ASN1_TYPE **pvalue) +{ + if (gen->type != GEN_OTHERNAME) + return 0; + if (poid) + *poid = gen->d.otherName->type_id; + if (pvalue) + *pvalue = gen->d.otherName->value; + return 1; +} +LCRYPTO_ALIAS(GENERAL_NAME_get0_otherName); diff --git a/crypto/x509/x509_ia5.c b/crypto/x509/x509_ia5.c new file mode 100644 index 0000000..4113c3d --- /dev/null +++ b/crypto/x509/x509_ia5.c @@ -0,0 +1,238 @@ +/* $OpenBSD: x509_ia5.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include + +static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5); +static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +const X509V3_EXT_METHOD v3_ns_ia5_list[] = { + { + .ext_nid = NID_netscape_base_url, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_revocation_url, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_ca_revocation_url, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_renewal_url, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_ca_policy_url, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_ssl_server_name, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = NID_netscape_comment, + .ext_flags = 0, + .it = &ASN1_IA5STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, + .s2i = (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, + { + .ext_nid = -1, + .ext_flags = 0, + .it = NULL, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, + }, +}; + +static char * +i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5) +{ + char *tmp; + + if (!ia5 || !ia5->length) + return NULL; + if (!(tmp = malloc(ia5->length + 1))) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + memcpy(tmp, ia5->data, ia5->length); + tmp[ia5->length] = 0; + return tmp; +} + +static ASN1_IA5STRING * +s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) +{ + ASN1_IA5STRING *ia5; + if (!str) { + X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); + return NULL; + } + if (!(ia5 = ASN1_IA5STRING_new())) + goto err; + if (!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str, + strlen(str))) { + ASN1_IA5STRING_free(ia5); + goto err; + } + return ia5; + +err: + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; +} diff --git a/crypto/x509/x509_info.c b/crypto/x509/x509_info.c new file mode 100644 index 0000000..a3d4d1b --- /dev/null +++ b/crypto/x509/x509_info.c @@ -0,0 +1,317 @@ +/* $OpenBSD: x509_info.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS( + X509V3_EXT_METHOD *method, AUTHORITY_INFO_ACCESS *ainfo, + STACK_OF(CONF_VALUE) *ret); +static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS( + X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +const X509V3_EXT_METHOD v3_info = { + .ext_nid = NID_info_access, + .ext_flags = X509V3_EXT_MULTILINE, + .it = &AUTHORITY_INFO_ACCESS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS, + .v2i = (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_sinfo = { + .ext_nid = NID_sinfo_access, + .ext_flags = X509V3_EXT_MULTILINE, + .it = &AUTHORITY_INFO_ACCESS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = (X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS, + .v2i = (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE ACCESS_DESCRIPTION_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(ACCESS_DESCRIPTION, method), + .field_name = "method", + .item = &ASN1_OBJECT_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(ACCESS_DESCRIPTION, location), + .field_name = "location", + .item = &GENERAL_NAME_it, + }, +}; + +const ASN1_ITEM ACCESS_DESCRIPTION_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = ACCESS_DESCRIPTION_seq_tt, + .tcount = sizeof(ACCESS_DESCRIPTION_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(ACCESS_DESCRIPTION), + .sname = "ACCESS_DESCRIPTION", +}; + + +ACCESS_DESCRIPTION * +d2i_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION **a, const unsigned char **in, long len) +{ + return (ACCESS_DESCRIPTION *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &ACCESS_DESCRIPTION_it); +} +LCRYPTO_ALIAS(d2i_ACCESS_DESCRIPTION); + +int +i2d_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &ACCESS_DESCRIPTION_it); +} +LCRYPTO_ALIAS(i2d_ACCESS_DESCRIPTION); + +ACCESS_DESCRIPTION * +ACCESS_DESCRIPTION_new(void) +{ + return (ACCESS_DESCRIPTION *)ASN1_item_new(&ACCESS_DESCRIPTION_it); +} +LCRYPTO_ALIAS(ACCESS_DESCRIPTION_new); + +void +ACCESS_DESCRIPTION_free(ACCESS_DESCRIPTION *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &ACCESS_DESCRIPTION_it); +} +LCRYPTO_ALIAS(ACCESS_DESCRIPTION_free); + +static const ASN1_TEMPLATE AUTHORITY_INFO_ACCESS_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "GeneralNames", + .item = &ACCESS_DESCRIPTION_it, +}; + +const ASN1_ITEM AUTHORITY_INFO_ACCESS_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &AUTHORITY_INFO_ACCESS_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "AUTHORITY_INFO_ACCESS", +}; + + +AUTHORITY_INFO_ACCESS * +d2i_AUTHORITY_INFO_ACCESS(AUTHORITY_INFO_ACCESS **a, const unsigned char **in, long len) +{ + return (AUTHORITY_INFO_ACCESS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &AUTHORITY_INFO_ACCESS_it); +} +LCRYPTO_ALIAS(d2i_AUTHORITY_INFO_ACCESS); + +int +i2d_AUTHORITY_INFO_ACCESS(AUTHORITY_INFO_ACCESS *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &AUTHORITY_INFO_ACCESS_it); +} +LCRYPTO_ALIAS(i2d_AUTHORITY_INFO_ACCESS); + +AUTHORITY_INFO_ACCESS * +AUTHORITY_INFO_ACCESS_new(void) +{ + return (AUTHORITY_INFO_ACCESS *)ASN1_item_new(&AUTHORITY_INFO_ACCESS_it); +} +LCRYPTO_ALIAS(AUTHORITY_INFO_ACCESS_new); + +void +AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &AUTHORITY_INFO_ACCESS_it); +} +LCRYPTO_ALIAS(AUTHORITY_INFO_ACCESS_free); + +static STACK_OF(CONF_VALUE) * +i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, + AUTHORITY_INFO_ACCESS *ainfo, STACK_OF(CONF_VALUE) *ret) +{ + ACCESS_DESCRIPTION *desc; + CONF_VALUE *vtmp; + STACK_OF(CONF_VALUE) *free_ret = NULL; + char objtmp[80], *ntmp; + int i; + + if (ret == NULL) { + if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) { + if ((desc = sk_ACCESS_DESCRIPTION_value(ainfo, i)) == NULL) + goto err; + if ((ret = i2v_GENERAL_NAME(method, desc->location, + ret)) == NULL) + goto err; + if ((vtmp = sk_CONF_VALUE_value(ret, i)) == NULL) + goto err; + if (!i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method)) + goto err; + if (asprintf(&ntmp, "%s - %s", objtmp, vtmp->name) == -1) { + ntmp = NULL; + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + free(vtmp->name); + vtmp->name = ntmp; + } + + return ret; + + err: + sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free); + + return NULL; +} + +static AUTHORITY_INFO_ACCESS * +v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + AUTHORITY_INFO_ACCESS *ainfo = NULL; + CONF_VALUE *cnf, ctmp; + ACCESS_DESCRIPTION *acc; + int i, objlen; + char *objtmp, *ptmp; + + if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + cnf = sk_CONF_VALUE_value(nval, i); + if ((acc = ACCESS_DESCRIPTION_new()) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + if (sk_ACCESS_DESCRIPTION_push(ainfo, acc) == 0) { + ACCESS_DESCRIPTION_free(acc); + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + ptmp = strchr(cnf->name, ';'); + if (!ptmp) { + X509V3error(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 = malloc(objlen + 1))) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + strlcpy(objtmp, cnf->name, objlen + 1); + acc->method = OBJ_txt2obj(objtmp, 0); + if (!acc->method) { + X509V3error(X509V3_R_BAD_OBJECT); + ERR_asprintf_error_data("value=%s", objtmp); + free(objtmp); + goto err; + } + free(objtmp); + } + return ainfo; + +err: + sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free); + return NULL; +} + +int +i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION* a) +{ + i2a_ASN1_OBJECT(bp, a->method); + return 2; +} +LCRYPTO_ALIAS(i2a_ACCESS_DESCRIPTION); diff --git a/crypto/x509/x509_int.c b/crypto/x509/x509_int.c new file mode 100644 index 0000000..35c8853 --- /dev/null +++ b/crypto/x509/x509_int.c @@ -0,0 +1,110 @@ +/* $OpenBSD: x509_int.c,v 1.1 2020/06/04 15:19:31 jsing Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include + +const X509V3_EXT_METHOD v3_crl_num = { + .ext_nid = NID_crl_number, + .ext_flags = 0, + .it = &ASN1_INTEGER_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_delta_crl = { + .ext_nid = NID_delta_crl, + .ext_flags = 0, + .it = &ASN1_INTEGER_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static void * +s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, char *value) +{ + return s2i_ASN1_INTEGER(meth, value); +} + +const X509V3_EXT_METHOD v3_inhibit_anyp = { + NID_inhibit_any_policy, 0, &ASN1_INTEGER_it, + 0, 0, 0, 0, + (X509V3_EXT_I2S)i2s_ASN1_INTEGER, + (X509V3_EXT_S2I)s2i_asn1_int, + 0, 0, 0, 0, + NULL +}; diff --git a/crypto/x509/x509_internal.h b/crypto/x509/x509_internal.h new file mode 100644 index 0000000..15efff6 --- /dev/null +++ b/crypto/x509/x509_internal.h @@ -0,0 +1,141 @@ +/* $OpenBSD: x509_internal.h,v 1.26 2023/09/29 15:53:59 beck Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef HEADER_X509_INTERNAL_H +#define HEADER_X509_INTERNAL_H + +/* Internal use only, not public API */ +#include + +#include "bytestring.h" +#include "x509_local.h" +#include "x509_verify.h" + +/* Hard limits on structure size and number of signature checks. */ +#define X509_VERIFY_MAX_CHAINS 8 /* Max validated chains */ +#define X509_VERIFY_MAX_CHAIN_CERTS 32 /* Max depth of a chain */ +#define X509_VERIFY_MAX_SIGCHECKS 256 /* Max signature checks */ + +/* + * Limit the number of names and constraints we will check in a chain + * to avoid a hostile input DOS + */ +#define X509_VERIFY_MAX_CHAIN_NAMES 512 +#define X509_VERIFY_MAX_CHAIN_CONSTRAINTS 512 + +/* + * Hold the parsed and validated result of names from a certificate. + * these typically come from a GENERALNAME, but we store the parsed + * and validated results, not the ASN1 bytes. + */ +struct x509_constraints_name { + int type; /* GEN_* types from GENERAL_NAME */ + char *name; /* Name to check */ + char *local; /* holds the local part of GEN_EMAIL */ + uint8_t *der; /* DER encoded value or NULL*/ + size_t der_len; + int af; /* INET and INET6 are supported */ + uint8_t address[32]; /* Must hold ipv6 + mask */ +}; + +struct x509_constraints_names { + struct x509_constraints_name **names; + size_t names_count; + size_t names_len; + size_t names_max; +}; + +struct x509_verify_chain { + STACK_OF(X509) *certs; /* Kept in chain order, includes leaf */ + int *cert_errors; /* Verify error for each cert in chain. */ + struct x509_constraints_names *names; /* All names from all certs */ +}; + +struct x509_verify_ctx { + X509_STORE_CTX *xsc; + struct x509_verify_chain **chains; /* Validated chains */ + STACK_OF(X509) *saved_error_chain; + int saved_error; + int saved_error_depth; + size_t chains_count; + STACK_OF(X509) *roots; /* Trusted roots for this validation */ + STACK_OF(X509) *intermediates; /* Intermediates provided by peer */ + time_t *check_time; /* Time for validity checks */ + int purpose; /* Cert purpose we are validating */ + size_t max_chains; /* Max chains to return */ + size_t max_depth; /* Max chain depth for validation */ + size_t max_sigs; /* Max number of signature checks */ + size_t sig_checks; /* Number of signature checks done */ + size_t error_depth; /* Depth of last error seen */ + int error; /* Last error seen */ +}; + +int ASN1_time_tm_clamp_notafter(struct tm *tm); + +__BEGIN_HIDDEN_DECLS + +int x509_vfy_check_id(X509_STORE_CTX *ctx); +int x509_vfy_check_revocation(X509_STORE_CTX *ctx); +int x509_vfy_check_policy(X509_STORE_CTX *ctx); +int x509_vfy_check_trust(X509_STORE_CTX *ctx); +int x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx); +int x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx); +int x509v3_cache_extensions(X509 *x); +X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); + +time_t x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notafter); + +struct x509_verify_ctx *x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc); + +void x509_constraints_name_clear(struct x509_constraints_name *name); +void x509_constraints_name_free(struct x509_constraints_name *name); +int x509_constraints_names_add(struct x509_constraints_names *names, + struct x509_constraints_name *name); +struct x509_constraints_names *x509_constraints_names_dup( + struct x509_constraints_names *names); +void x509_constraints_names_clear(struct x509_constraints_names *names); +struct x509_constraints_names *x509_constraints_names_new(size_t names_max); +int x509_constraints_general_to_bytes(GENERAL_NAME *name, uint8_t **bytes, + size_t *len); +void x509_constraints_names_free(struct x509_constraints_names *names); +int x509_constraints_valid_host(CBS *cbs, int permit_ip); +int x509_constraints_valid_sandns(CBS *cbs); +int x509_constraints_domain(char *domain, size_t dlen, char *constraint, + size_t len); +int x509_constraints_parse_mailbox(CBS *candidate, + struct x509_constraints_name *name); +int x509_constraints_valid_domain_constraint(CBS *cbs); +int x509_constraints_uri_host(uint8_t *uri, size_t len, char **hostp); +int x509_constraints_uri(uint8_t *uri, size_t ulen, uint8_t *constraint, + size_t len, int *error); +int x509_constraints_extract_names(struct x509_constraints_names *names, + X509 *cert, int include_cn, int *error); +int x509_constraints_extract_constraints(X509 *cert, + struct x509_constraints_names *permitted, + struct x509_constraints_names *excluded, int *error); +int x509_constraints_validate(GENERAL_NAME *constraint, + struct x509_constraints_name **out_name, int *error); +int x509_constraints_check(struct x509_constraints_names *names, + struct x509_constraints_names *permitted, + struct x509_constraints_names *excluded, int *error); +int x509_constraints_chain(STACK_OF(X509) *chain, int *error, + int *depth); +void x509_verify_cert_info_populate(X509 *cert); +int x509_vfy_check_security_level(X509_STORE_CTX *ctx); + +__END_HIDDEN_DECLS + +#endif diff --git a/crypto/x509/x509_issuer_cache.c b/crypto/x509/x509_issuer_cache.c new file mode 100644 index 0000000..f7fbd54 --- /dev/null +++ b/crypto/x509/x509_issuer_cache.c @@ -0,0 +1,193 @@ +/* $OpenBSD: x509_issuer_cache.c,v 1.4 2022/12/26 07:18:53 jmc Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* x509_issuer_cache */ + +/* + * The issuer cache is a cache of parent and child x509 certificate + * hashes with a signature validation result. + * + * Entries should only be added to the cache with a validation result + * from checking the public key math that "parent" signed "child". + * + * Finding an entry in the cache gets us the result of a previously + * performed validation of the signature of "parent" signing for the + * validity of "child". It allows us to skip doing the public key math + * when validating a certificate chain. It does not allow us to skip + * any other steps of validation (times, names, key usage, etc.) + */ + +#include +#include + +#include "x509_issuer_cache.h" + +static int +x509_issuer_cmp(struct x509_issuer *x1, struct x509_issuer *x2) +{ + int pcmp; + if ((pcmp = memcmp(x1->parent_md, x2->parent_md, EVP_MAX_MD_SIZE)) != 0) + return pcmp; + return memcmp(x1->child_md, x2->child_md, EVP_MAX_MD_SIZE); +} + +static size_t x509_issuer_cache_count; +static size_t x509_issuer_cache_max = X509_ISSUER_CACHE_MAX; +static RB_HEAD(x509_issuer_tree, x509_issuer) x509_issuer_cache = + RB_INITIALIZER(&x509_issuer_cache); +static TAILQ_HEAD(lruqueue, x509_issuer) x509_issuer_lru = + TAILQ_HEAD_INITIALIZER(x509_issuer_lru); +static pthread_mutex_t x509_issuer_tree_mutex = PTHREAD_MUTEX_INITIALIZER; + +RB_PROTOTYPE(x509_issuer_tree, x509_issuer, entry, x509_issuer_cmp); +RB_GENERATE(x509_issuer_tree, x509_issuer, entry, x509_issuer_cmp); + +/* + * Set the maximum number of cached entries. On additions to the cache + * the least recently used entries will be discarded so that the cache + * stays under the maximum number of entries. Setting a maximum of 0 + * disables the cache. + */ +int +x509_issuer_cache_set_max(size_t max) +{ + if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0) + return 0; + x509_issuer_cache_max = max; + (void) pthread_mutex_unlock(&x509_issuer_tree_mutex); + + return 1; +} + +/* + * Free the oldest entry in the issuer cache. Returns 1 + * if an entry was successfully freed, 0 otherwise. Must + * be called with x509_issuer_tree_mutex held. + */ +void +x509_issuer_cache_free_oldest() +{ + struct x509_issuer *old; + + if (x509_issuer_cache_count == 0) + return; + old = TAILQ_LAST(&x509_issuer_lru, lruqueue); + TAILQ_REMOVE(&x509_issuer_lru, old, queue); + RB_REMOVE(x509_issuer_tree, &x509_issuer_cache, old); + free(old->parent_md); + free(old->child_md); + free(old); + x509_issuer_cache_count--; +} + +/* + * Free the entire issuer cache, discarding all entries. + */ +void +x509_issuer_cache_free() +{ + if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0) + return; + while (x509_issuer_cache_count > 0) + x509_issuer_cache_free_oldest(); + (void) pthread_mutex_unlock(&x509_issuer_tree_mutex); +} + +/* + * Find a previous result of checking if parent signed child + * + * Returns: + * -1 : No entry exists in the cache. signature must be checked. + * 0 : The signature of parent signing child is invalid. + * 1 : The signature of parent signing child is valid. + */ +int +x509_issuer_cache_find(unsigned char *parent_md, unsigned char *child_md) +{ + struct x509_issuer candidate, *found; + int ret = -1; + + memset(&candidate, 0, sizeof(candidate)); + candidate.parent_md = parent_md; + candidate.child_md = child_md; + + if (x509_issuer_cache_max == 0) + return -1; + + if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0) + return -1; + if ((found = RB_FIND(x509_issuer_tree, &x509_issuer_cache, + &candidate)) != NULL) { + TAILQ_REMOVE(&x509_issuer_lru, found, queue); + TAILQ_INSERT_HEAD(&x509_issuer_lru, found, queue); + ret = found->valid; + } + (void) pthread_mutex_unlock(&x509_issuer_tree_mutex); + + return ret; +} + +/* + * Attempt to add a validation result to the cache. + * + * valid must be: + * 0: The signature of parent signing child is invalid. + * 1: The signature of parent signing child is valid. + * + * Previously added entries for the same parent and child are *not* replaced. + */ +void +x509_issuer_cache_add(unsigned char *parent_md, unsigned char *child_md, + int valid) +{ + struct x509_issuer *new; + + if (x509_issuer_cache_max == 0) + return; + if (valid != 0 && valid != 1) + return; + + if ((new = calloc(1, sizeof(struct x509_issuer))) == NULL) + return; + if ((new->parent_md = calloc(1, EVP_MAX_MD_SIZE)) == NULL) + goto err; + memcpy(new->parent_md, parent_md, EVP_MAX_MD_SIZE); + if ((new->child_md = calloc(1, EVP_MAX_MD_SIZE)) == NULL) + goto err; + memcpy(new->child_md, child_md, EVP_MAX_MD_SIZE); + + new->valid = valid; + + if (pthread_mutex_lock(&x509_issuer_tree_mutex) != 0) + goto err; + while (x509_issuer_cache_count >= x509_issuer_cache_max) + x509_issuer_cache_free_oldest(); + if (RB_INSERT(x509_issuer_tree, &x509_issuer_cache, new) == NULL) { + TAILQ_INSERT_HEAD(&x509_issuer_lru, new, queue); + x509_issuer_cache_count++; + new = NULL; + } + (void) pthread_mutex_unlock(&x509_issuer_tree_mutex); + + err: + if (new != NULL) { + free(new->parent_md); + free(new->child_md); + } + free(new); + return; +} diff --git a/crypto/x509/x509_issuer_cache.h b/crypto/x509/x509_issuer_cache.h new file mode 100644 index 0000000..3afe65b --- /dev/null +++ b/crypto/x509/x509_issuer_cache.h @@ -0,0 +1,48 @@ +/* $OpenBSD: x509_issuer_cache.h,v 1.2 2022/09/03 17:47:47 jsing Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* x509_issuer_cache */ +#ifndef HEADER_X509_ISSUER_CACHE_H +#define HEADER_X509_ISSUER_CACHE_H + +#include +#include + +#include + +__BEGIN_HIDDEN_DECLS + +struct x509_issuer { + RB_ENTRY(x509_issuer) entry; + TAILQ_ENTRY(x509_issuer) queue; /* LRU of entries */ + /* parent_md and child_md must point to EVP_MAX_MD_SIZE of memory */ + unsigned char *parent_md; + unsigned char *child_md; + int valid; /* Result of signature validation. */ +}; + +#define X509_ISSUER_CACHE_MAX 40000 /* Approx 7.5 MB, entries 200 bytes */ + +int x509_issuer_cache_set_max(size_t max); +int x509_issuer_cache_find(unsigned char *parent_md, unsigned char *child_md); +void x509_issuer_cache_add(unsigned char *parent_md, unsigned char *child_md, + int valid); +void x509_issuer_cache_free(); + +__END_HIDDEN_DECLS + +#endif diff --git a/crypto/x509/x509_lib.c b/crypto/x509/x509_lib.c new file mode 100644 index 0000000..93f8dc2 --- /dev/null +++ b/crypto/x509/x509_lib.c @@ -0,0 +1,436 @@ +/* $OpenBSD: x509_lib.c,v 1.14 2023/04/25 10:56:58 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* X509 v3 extension utilities */ + +#include + +#include +#include +#include + +#include "x509_local.h" + +static STACK_OF(X509V3_EXT_METHOD) *ext_list = NULL; + +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_info, v3_sinfo; +extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], 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; +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]; + +/* + * This table needs to be sorted by increasing ext_nid values for OBJ_bsearch_. + */ + +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_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_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 +}; + +#define STANDARD_EXTENSION_COUNT (sizeof(standard_exts) / sizeof(standard_exts[0])) + +static int +ext_cmp(const X509V3_EXT_METHOD * const *a, const X509V3_EXT_METHOD * const *b) +{ + return ((*a)->ext_nid - (*b)->ext_nid); +} + +int +X509V3_EXT_add(X509V3_EXT_METHOD *ext) +{ + if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_cmp))) { + X509V3error(ERR_R_MALLOC_FAILURE); + return 0; + } + if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) { + X509V3error(ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509V3_EXT_add); + +static int +ext_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) +{ + const X509V3_EXT_METHOD * const *a = a_; + const X509V3_EXT_METHOD * const *b = b_; + return ext_cmp(a, b); +} + +static const X509V3_EXT_METHOD ** +OBJ_bsearch_ext(const X509V3_EXT_METHOD **key, + const X509V3_EXT_METHOD *const *base, int num) +{ + return (const X509V3_EXT_METHOD **)OBJ_bsearch_(key, base, num, + sizeof(const X509V3_EXT_METHOD *), ext_cmp_BSEARCH_CMP_FN); +} + +const X509V3_EXT_METHOD * +X509V3_EXT_get_nid(int nid) +{ + X509V3_EXT_METHOD tmp; + const X509V3_EXT_METHOD *t = &tmp, * const *ret; + int idx; + + if (nid < 0) + return NULL; + tmp.ext_nid = nid; + ret = OBJ_bsearch_ext(&t, standard_exts, STANDARD_EXTENSION_COUNT); + if (ret) + return *ret; + if (!ext_list) + return NULL; + idx = sk_X509V3_EXT_METHOD_find(ext_list, &tmp); + if (idx == -1) + return NULL; + return sk_X509V3_EXT_METHOD_value(ext_list, idx); +} +LCRYPTO_ALIAS(X509V3_EXT_get_nid); + +const X509V3_EXT_METHOD * +X509V3_EXT_get(X509_EXTENSION *ext) +{ + int nid; + + if ((nid = OBJ_obj2nid(ext->object)) == NID_undef) + return NULL; + return X509V3_EXT_get_nid(nid); +} +LCRYPTO_ALIAS(X509V3_EXT_get); + +int +X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist) +{ + for (; extlist->ext_nid!=-1; extlist++) + if (!X509V3_EXT_add(extlist)) + return 0; + return 1; +} +LCRYPTO_ALIAS(X509V3_EXT_add_list); + +int +X509V3_EXT_add_alias(int nid_to, int nid_from) +{ + const X509V3_EXT_METHOD *ext; + X509V3_EXT_METHOD *tmpext; + + if (!(ext = X509V3_EXT_get_nid(nid_from))) { + X509V3error(X509V3_R_EXTENSION_NOT_FOUND); + return 0; + } + if (!(tmpext = malloc(sizeof(X509V3_EXT_METHOD)))) { + X509V3error(ERR_R_MALLOC_FAILURE); + return 0; + } + *tmpext = *ext; + tmpext->ext_nid = nid_to; + tmpext->ext_flags |= X509V3_EXT_DYNAMIC; + if (!X509V3_EXT_add(tmpext)) { + free(tmpext); + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509V3_EXT_add_alias); + +static void +ext_list_free(X509V3_EXT_METHOD *ext) +{ + if (ext->ext_flags & X509V3_EXT_DYNAMIC) + free(ext); +} + +void +X509V3_EXT_cleanup(void) +{ + sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free); + ext_list = NULL; +} +LCRYPTO_ALIAS(X509V3_EXT_cleanup); + +int +X509V3_add_standard_extensions(void) +{ + return 1; +} +LCRYPTO_ALIAS(X509V3_add_standard_extensions); + +/* Return an extension internal structure */ + +void * +X509V3_EXT_d2i(X509_EXTENSION *ext) +{ + const X509V3_EXT_METHOD *method; + const unsigned char *p; + + if (!(method = X509V3_EXT_get(ext))) + return NULL; + p = ext->value->data; + if (method->it) + return ASN1_item_d2i(NULL, &p, ext->value->length, + method->it); + return method->d2i(NULL, &p, ext->value->length); +} +LCRYPTO_ALIAS(X509V3_EXT_d2i); + +/* Get critical flag and decoded version of extension from a NID. + * The "idx" variable returns the last found extension and can + * be used to retrieve multiple extensions of the same NID. + * However multiple extensions with the same NID is usually + * due to a badly encoded certificate so if idx is NULL we + * choke if multiple extensions exist. + * The "crit" variable is set to the critical value. + * The return value is the decoded extension or NULL on + * error. The actual error can have several different causes, + * the value of *crit reflects the cause: + * >= 0, extension found but not decoded (reflects critical value). + * -1 extension not found. + * -2 extension occurs more than once. + */ + +void * +X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx) +{ + int lastpos, i; + X509_EXTENSION *ex, *found_ex = NULL; + + if (!x) { + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; + } + if (idx) + lastpos = *idx + 1; + else + lastpos = 0; + if (lastpos < 0) + lastpos = 0; + for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) { + ex = sk_X509_EXTENSION_value(x, i); + if (OBJ_obj2nid(ex->object) == nid) { + if (idx) { + *idx = i; + found_ex = ex; + break; + } else if (found_ex) { + /* Found more than one */ + if (crit) + *crit = -2; + return NULL; + } + found_ex = ex; + } + } + if (found_ex) { + /* Found it */ + if (crit) + *crit = X509_EXTENSION_get_critical(found_ex); + return X509V3_EXT_d2i(found_ex); + } + + /* Extension not found */ + if (idx) + *idx = -1; + if (crit) + *crit = -1; + return NULL; +} +LCRYPTO_ALIAS(X509V3_get_d2i); + +/* This function is a general extension append, replace and delete utility. + * The precise operation is governed by the 'flags' value. The 'crit' and + * 'value' arguments (if relevant) are the extensions internal structure. + */ + +int +X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, + int crit, unsigned long flags) +{ + int extidx = -1; + int errcode; + X509_EXTENSION *ext, *extmp; + unsigned long ext_op = flags & X509V3_ADD_OP_MASK; + + /* If appending we don't care if it exists, otherwise + * look for existing extension. + */ + if (ext_op != X509V3_ADD_APPEND) + extidx = X509v3_get_ext_by_NID(*x, nid, -1); + + /* See if extension exists */ + if (extidx >= 0) { + /* If keep existing, nothing to do */ + if (ext_op == X509V3_ADD_KEEP_EXISTING) + return 1; + /* If default then its an error */ + if (ext_op == X509V3_ADD_DEFAULT) { + errcode = X509V3_R_EXTENSION_EXISTS; + goto err; + } + /* If delete, just delete it */ + if (ext_op == X509V3_ADD_DELETE) { + if ((extmp = sk_X509_EXTENSION_delete(*x, extidx)) == NULL) + return -1; + X509_EXTENSION_free(extmp); + return 1; + } + } else { + /* If replace existing or delete, error since + * extension must exist + */ + if ((ext_op == X509V3_ADD_REPLACE_EXISTING) || + (ext_op == X509V3_ADD_DELETE)) { + errcode = X509V3_R_EXTENSION_NOT_FOUND; + goto err; + } + } + + /* If we get this far then we have to create an extension: + * could have some flags for alternative encoding schemes... + */ + + ext = X509V3_EXT_i2d(nid, crit, value); + + if (!ext) { + X509V3error(X509V3_R_ERROR_CREATING_EXTENSION); + return 0; + } + + /* If extension exists replace it.. */ + if (extidx >= 0) { + extmp = sk_X509_EXTENSION_value(*x, extidx); + X509_EXTENSION_free(extmp); + if (!sk_X509_EXTENSION_set(*x, extidx, ext)) + return -1; + return 1; + } + + if (!*x && !(*x = sk_X509_EXTENSION_new_null())) + return -1; + if (!sk_X509_EXTENSION_push(*x, ext)) + return -1; + + return 1; + +err: + if (!(flags & X509V3_ADD_SILENT)) + X509V3error(errcode); + return 0; +} +LCRYPTO_ALIAS(X509V3_add1_i2d); diff --git a/crypto/x509/x509_local.h b/crypto/x509/x509_local.h new file mode 100644 index 0000000..f00a55b --- /dev/null +++ b/crypto/x509/x509_local.h @@ -0,0 +1,388 @@ +/* $OpenBSD: x509_local.h,v 1.9 2023/05/28 05:25:24 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2013. + */ +/* ==================================================================== + * Copyright (c) 2013 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_X509_LOCAL_H +#define HEADER_X509_LOCAL_H + +__BEGIN_HIDDEN_DECLS + +#define TS_HASH_EVP EVP_sha1() +#define TS_HASH_LEN SHA_DIGEST_LENGTH + +#define X509_CERT_HASH_EVP EVP_sha512() +#define X509_CERT_HASH_LEN SHA512_DIGEST_LENGTH +#define X509_CRL_HASH_EVP EVP_sha512() +#define X509_CRL_HASH_LEN SHA512_DIGEST_LENGTH + +struct X509_pubkey_st { + X509_ALGOR *algor; + ASN1_BIT_STRING *public_key; + EVP_PKEY *pkey; +}; + +struct X509_sig_st { + X509_ALGOR *algor; + ASN1_OCTET_STRING *digest; +} /* X509_SIG */; + +struct X509_name_entry_st { + ASN1_OBJECT *object; + ASN1_STRING *value; + int set; + int size; /* temp variable */ +} /* X509_NAME_ENTRY */; + +/* we always keep X509_NAMEs in 2 forms. */ +struct X509_name_st { + STACK_OF(X509_NAME_ENTRY) *entries; + int modified; /* true if 'bytes' needs to be built */ +#ifndef OPENSSL_NO_BUFFER + BUF_MEM *bytes; +#else + char *bytes; +#endif +/* unsigned long hash; Keep the hash around for lookups */ + unsigned char *canon_enc; + int canon_enclen; +} /* X509_NAME */; + +struct X509_extension_st { + ASN1_OBJECT *object; + ASN1_BOOLEAN critical; + ASN1_OCTET_STRING *value; +} /* X509_EXTENSION */; + +struct x509_attributes_st { + ASN1_OBJECT *object; + STACK_OF(ASN1_TYPE) *set; +} /* X509_ATTRIBUTE */; + +struct X509_req_info_st { + ASN1_ENCODING enc; + ASN1_INTEGER *version; + X509_NAME *subject; + X509_PUBKEY *pubkey; + /* d=2 hl=2 l= 0 cons: cont: 00 */ + STACK_OF(X509_ATTRIBUTE) *attributes; /* [ 0 ] */ +} /* X509_REQ_INFO */; + +struct X509_req_st { + X509_REQ_INFO *req_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; +} /* X509_REQ */; + +/* + * This stuff is certificate "auxiliary info" it contains details which are + * useful in certificate stores and databases. When used this is tagged onto + * the end of the certificate itself. + */ +struct x509_cert_aux_st { + STACK_OF(ASN1_OBJECT) *trust; /* trusted uses */ + STACK_OF(ASN1_OBJECT) *reject; /* rejected uses */ + ASN1_UTF8STRING *alias; /* "friendly name" */ + ASN1_OCTET_STRING *keyid; /* key id of private key */ + STACK_OF(X509_ALGOR) *other; /* other unspecified info */ +} /* X509_CERT_AUX */; + +struct x509_cinf_st { + ASN1_INTEGER *version; /* [ 0 ] default of v1 */ + ASN1_INTEGER *serialNumber; + X509_ALGOR *signature; + X509_NAME *issuer; + X509_VAL *validity; + X509_NAME *subject; + X509_PUBKEY *key; + ASN1_BIT_STRING *issuerUID; /* [ 1 ] optional in v2 */ + ASN1_BIT_STRING *subjectUID; /* [ 2 ] optional in v2 */ + STACK_OF(X509_EXTENSION) *extensions; /* [ 3 ] optional in v3 */ + ASN1_ENCODING enc; +} /* X509_CINF */; + +struct x509_st { + X509_CINF *cert_info; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int valid; + int references; + char *name; + CRYPTO_EX_DATA ex_data; + /* These contain copies of various extension values */ + long ex_pathlen; + unsigned long ex_flags; + unsigned long ex_kusage; + unsigned long ex_xkusage; + unsigned long ex_nscert; + ASN1_OCTET_STRING *skid; + AUTHORITY_KEYID *akid; + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +#ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; +#endif + unsigned char hash[X509_CERT_HASH_LEN]; + time_t not_before; + time_t not_after; + X509_CERT_AUX *aux; +} /* X509 */; + +struct x509_revoked_st { + ASN1_INTEGER *serialNumber; + ASN1_TIME *revocationDate; + STACK_OF(X509_EXTENSION) /* optional */ *extensions; + /* Set up if indirect CRL */ + STACK_OF(GENERAL_NAME) *issuer; + /* Revocation reason */ + int reason; + int sequence; /* load sequence */ +}; + +struct X509_crl_info_st { + ASN1_INTEGER *version; + X509_ALGOR *sig_alg; + X509_NAME *issuer; + ASN1_TIME *lastUpdate; + ASN1_TIME *nextUpdate; + STACK_OF(X509_REVOKED) *revoked; + STACK_OF(X509_EXTENSION) /* [0] */ *extensions; + ASN1_ENCODING enc; +} /* X509_CRL_INFO */; + +struct X509_crl_st { + /* actual signature */ + X509_CRL_INFO *crl; + X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; + int references; + int flags; + /* Copies of various extensions */ + AUTHORITY_KEYID *akid; + ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; + /* CRL and base CRL numbers for delta processing */ + ASN1_INTEGER *crl_number; + ASN1_INTEGER *base_crl_number; + unsigned char hash[X509_CRL_HASH_LEN]; + STACK_OF(GENERAL_NAMES) *issuers; + const X509_CRL_METHOD *meth; + void *meth_data; +} /* X509_CRL */; + +struct pkcs8_priv_key_info_st { + ASN1_INTEGER *version; + X509_ALGOR *pkeyalg; + ASN1_OCTET_STRING *pkey; + STACK_OF(X509_ATTRIBUTE) *attributes; +}; + +struct x509_object_st { + /* one of the above types */ + int type; + union { + X509 *x509; + X509_CRL *crl; + } data; +} /* X509_OBJECT */; + +struct x509_lookup_method_st { + const char *name; + int (*new_item)(X509_LOOKUP *ctx); + void (*free)(X509_LOOKUP *ctx); + int (*init)(X509_LOOKUP *ctx); + int (*shutdown)(X509_LOOKUP *ctx); + int (*ctrl)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret); + int (*get_by_subject)(X509_LOOKUP *ctx, int type, X509_NAME *name, + X509_OBJECT *ret); + int (*get_by_issuer_serial)(X509_LOOKUP *ctx, int type, X509_NAME *name, + ASN1_INTEGER *serial,X509_OBJECT *ret); + int (*get_by_fingerprint)(X509_LOOKUP *ctx, int type, + const unsigned char *bytes, int len, X509_OBJECT *ret); + int (*get_by_alias)(X509_LOOKUP *ctx, int type, const char *str, + int len, X509_OBJECT *ret); +} /* X509_LOOKUP_METHOD */; + +struct X509_VERIFY_PARAM_st { + char *name; + time_t check_time; /* Time to use */ + unsigned long inh_flags; /* Inheritance flags */ + unsigned long flags; /* Various verify flags */ + int purpose; /* purpose to check untrusted certificates */ + int trust; /* trust setting to check */ + int depth; /* Verify depth */ + int security_level; /* 'Security level', see SP800-57. */ + STACK_OF(ASN1_OBJECT) *policies; /* Permissible policies */ + STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */ + unsigned int hostflags; /* Flags to control matching features */ + char *peername; /* Matching hostname in peer certificate */ + char *email; /* If not NULL email address to match */ + size_t emaillen; + unsigned char *ip; /* If not NULL IP address to match */ + size_t iplen; /* Length of IP address */ + int poisoned; +} /* X509_VERIFY_PARAM */; + +/* + * This is used to hold everything. It is used for all certificate + * validation. Once we have a certificate chain, the 'verify' + * function is then called to actually check the cert chain. + */ +struct x509_store_st { + /* The following is a cache of trusted certs */ + STACK_OF(X509_OBJECT) *objs; /* Cache of all objects */ + + /* These are external lookup methods */ + STACK_OF(X509_LOOKUP) *get_cert_methods; + + X509_VERIFY_PARAM *param; + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + 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); + int (*cleanup)(X509_STORE_CTX *ctx); + + CRYPTO_EX_DATA ex_data; + int references; +} /* X509_STORE */; + +/* This is the functions plus an instance of the local variables. */ +struct x509_lookup_st { + int init; /* have we been started */ + X509_LOOKUP_METHOD *method; /* the functions */ + char *method_data; /* method data */ + + X509_STORE *store_ctx; /* who owns us */ +} /* X509_LOOKUP */; + +/* + * This is used when verifying cert chains. Since the gathering of the cert + * chain can take some time (and has to be 'retried'), this needs to be kept + * and passed around. + */ +struct x509_store_ctx_st { + X509_STORE *store; + int current_method; /* used when looking up certs */ + + /* The following are set by the caller */ + X509 *cert; /* The cert to check */ + STACK_OF(X509) *untrusted; /* chain of X509s - untrusted - passed in */ + STACK_OF(X509) *trusted; /* trusted stack for use with get_issuer() */ + STACK_OF(X509_CRL) *crls; /* set of CRLs passed in */ + + X509_VERIFY_PARAM *param; + + /* Callbacks for various operations */ + int (*verify)(X509_STORE_CTX *ctx); /* called to verify a certificate */ + int (*verify_cb)(int ok,X509_STORE_CTX *ctx); /* error callback */ + int (*get_issuer)(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); /* get issuers cert from ctx */ + int (*check_issued)(X509_STORE_CTX *ctx, X509 *x, X509 *issuer); /* check issued */ + int (*check_revocation)(X509_STORE_CTX *ctx); /* Check revocation status of chain */ + int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ + int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ + int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + 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); + int (*cleanup)(X509_STORE_CTX *ctx); + + /* The following is built up */ + int valid; /* if 0, rebuild chain */ + int num_untrusted; /* number of untrusted certs in chain */ + STACK_OF(X509) *chain; /* chain of X509s - built up and trusted */ + + int explicit_policy; /* Require explicit policy value */ + + /* When something goes wrong, this is why */ + int error_depth; + int error; + X509 *current_cert; + X509 *current_issuer; /* cert currently being tested as valid issuer */ + X509_CRL *current_crl; /* current CRL */ + + int current_crl_score; /* score of current CRL */ + unsigned int current_reasons; /* Reason mask */ + + X509_STORE_CTX *parent; /* For CRL path validation: parent context */ + + CRYPTO_EX_DATA ex_data; +} /* X509_STORE_CTX */; + +int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); + +int name_cmp(const char *name, const char *cmp); + +int X509_policy_check(const STACK_OF(X509) *certs, + const STACK_OF(ASN1_OBJECT) *user_policies, unsigned long flags, + X509 **out_current_cert); + +__END_HIDDEN_DECLS + +#endif /* !HEADER_X509_LOCAL_H */ diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c new file mode 100644 index 0000000..05730f5 --- /dev/null +++ b/crypto/x509/x509_lu.c @@ -0,0 +1,880 @@ +/* $OpenBSD: x509_lu.c,v 1.60 2023/04/25 18:32:42 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include +#include +#include +#include "x509_local.h" + +X509_LOOKUP * +X509_LOOKUP_new(X509_LOOKUP_METHOD *method) +{ + X509_LOOKUP *lu; + + if ((lu = calloc(1, sizeof(*lu))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + lu->method = method; + + if (method->new_item != NULL && !method->new_item(lu)) { + free(lu); + return NULL; + } + + return lu; +} +LCRYPTO_ALIAS(X509_LOOKUP_new); + +void +X509_LOOKUP_free(X509_LOOKUP *ctx) +{ + if (ctx == NULL) + return; + if (ctx->method != NULL && ctx->method->free != NULL) + ctx->method->free(ctx); + free(ctx); +} +LCRYPTO_ALIAS(X509_LOOKUP_free); + +int +X509_LOOKUP_init(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->init == NULL) + return 1; + return ctx->method->init(ctx); +} +LCRYPTO_ALIAS(X509_LOOKUP_init); + +int +X509_LOOKUP_shutdown(X509_LOOKUP *ctx) +{ + if (ctx->method == NULL) + return 0; + if (ctx->method->shutdown == NULL) + return 1; + return ctx->method->shutdown(ctx); +} +LCRYPTO_ALIAS(X509_LOOKUP_shutdown); + +int +X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, + char **ret) +{ + if (ctx->method == NULL) + return -1; + if (ctx->method->ctrl == NULL) + return 1; + return ctx->method->ctrl(ctx, cmd, argc, argl, ret); +} +LCRYPTO_ALIAS(X509_LOOKUP_ctrl); + +int +X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, X509_NAME *name, + X509_OBJECT *ret) +{ + if (ctx->method == NULL || ctx->method->get_by_subject == NULL) + return 0; + return ctx->method->get_by_subject(ctx, type, name, ret); +} +LCRYPTO_ALIAS(X509_LOOKUP_by_subject); + +int +X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret) +{ + if (ctx->method == NULL || ctx->method->get_by_issuer_serial == NULL) + return 0; + return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret); +} +LCRYPTO_ALIAS(X509_LOOKUP_by_issuer_serial); + +int +X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, X509_OBJECT *ret) +{ + if (ctx->method == NULL || ctx->method->get_by_fingerprint == NULL) + return 0; + return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret); +} +LCRYPTO_ALIAS(X509_LOOKUP_by_fingerprint); + +int +X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, const char *str, + int len, X509_OBJECT *ret) +{ + if (ctx->method == NULL || ctx->method->get_by_alias == NULL) + return 0; + return ctx->method->get_by_alias(ctx, type, str, len, ret); +} +LCRYPTO_ALIAS(X509_LOOKUP_by_alias); + +static int +x509_object_cmp(const X509_OBJECT * const *a, const X509_OBJECT * const *b) +{ + int ret; + + if ((ret = (*a)->type - (*b)->type) != 0) + return ret; + + switch ((*a)->type) { + case X509_LU_X509: + return X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509); + case X509_LU_CRL: + return X509_CRL_cmp((*a)->data.crl, (*b)->data.crl); + } + return 0; +} + +X509_STORE * +X509_STORE_new(void) +{ + X509_STORE *store; + + if ((store = calloc(1, sizeof(*store))) == NULL) + goto err; + + if ((store->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) + goto err; + if ((store->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) + goto err; + if ((store->param = X509_VERIFY_PARAM_new()) == NULL) + goto err; + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, + &store->ex_data)) + goto err; + + store->references = 1; + + return store; + + err: + X509error(ERR_R_MALLOC_FAILURE); + X509_STORE_free(store); + + return NULL; +} +LCRYPTO_ALIAS(X509_STORE_new); + +X509_OBJECT * +X509_OBJECT_new(void) +{ + X509_OBJECT *obj; + + if ((obj = calloc(1, sizeof(*obj))) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + obj->type = X509_LU_NONE; + + return obj; +} +LCRYPTO_ALIAS(X509_OBJECT_new); + +void +X509_OBJECT_free(X509_OBJECT *a) +{ + if (a == NULL) + return; + + switch (a->type) { + case X509_LU_X509: + X509_free(a->data.x509); + break; + case X509_LU_CRL: + X509_CRL_free(a->data.crl); + break; + } + + free(a); +} +LCRYPTO_ALIAS(X509_OBJECT_free); + +void +X509_STORE_free(X509_STORE *store) +{ + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + int i; + + if (store == NULL) + return; + + if (CRYPTO_add(&store->references, -1, CRYPTO_LOCK_X509_STORE) > 0) + return; + + sk = store->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + X509_LOOKUP_shutdown(lu); + X509_LOOKUP_free(lu); + } + sk_X509_LOOKUP_free(sk); + sk_X509_OBJECT_pop_free(store->objs, X509_OBJECT_free); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, store, &store->ex_data); + X509_VERIFY_PARAM_free(store->param); + free(store); +} +LCRYPTO_ALIAS(X509_STORE_free); + +int +X509_STORE_up_ref(X509_STORE *store) +{ + return CRYPTO_add(&store->references, 1, CRYPTO_LOCK_X509_STORE) > 1; +} +LCRYPTO_ALIAS(X509_STORE_up_ref); + +X509_LOOKUP * +X509_STORE_add_lookup(X509_STORE *store, X509_LOOKUP_METHOD *method) +{ + STACK_OF(X509_LOOKUP) *sk; + X509_LOOKUP *lu; + int i; + + sk = store->get_cert_methods; + for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) { + lu = sk_X509_LOOKUP_value(sk, i); + if (method == lu->method) { + return lu; + } + } + + if ((lu = X509_LOOKUP_new(method)) == NULL) + return NULL; + + lu->store_ctx = store; + if (sk_X509_LOOKUP_push(store->get_cert_methods, lu) <= 0) { + X509error(ERR_R_MALLOC_FAILURE); + X509_LOOKUP_free(lu); + return NULL; + } + + return lu; +} +LCRYPTO_ALIAS(X509_STORE_add_lookup); + +X509_OBJECT * +X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + X509_OBJECT *obj; + + if ((obj = X509_OBJECT_new()) == NULL) + return NULL; + if (!X509_STORE_CTX_get_by_subject(vs, type, name, obj)) { + X509_OBJECT_free(obj); + return NULL; + } + + return obj; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_obj_by_subject); + +int +X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret) +{ + X509_STORE *ctx = vs->store; + X509_LOOKUP *lu; + X509_OBJECT stmp, *tmp; + int i; + + if (ctx == NULL) + return 0; + + memset(&stmp, 0, sizeof(stmp)); + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name); + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + if (tmp == NULL || type == X509_LU_CRL) { + for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) { + lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i); + if (X509_LOOKUP_by_subject(lu, type, name, &stmp) != 0) { + tmp = &stmp; + break; + } + } + if (tmp == NULL) + return 0; + } + + if (!X509_OBJECT_up_ref_count(tmp)) + return 0; + + *ret = *tmp; + + return 1; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_by_subject); + +/* Add obj to the store. Takes ownership of obj. */ +static int +X509_STORE_add_object(X509_STORE *store, X509_OBJECT *obj) +{ + int ret = 0; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + if (X509_OBJECT_retrieve_match(store->objs, obj) != NULL) { + /* Object is already present in the store. That's fine. */ + ret = 1; + goto out; + } + + if (sk_X509_OBJECT_push(store->objs, obj) <= 0) { + X509error(ERR_R_MALLOC_FAILURE); + goto out; + } + + obj = NULL; + ret = 1; + + out: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + X509_OBJECT_free(obj); + + return ret; +} + +int +X509_STORE_add_cert(X509_STORE *store, X509 *x) +{ + X509_OBJECT *obj; + + if (x == NULL) + return 0; + + if ((obj = X509_OBJECT_new()) == NULL) + return 0; + + if (!X509_up_ref(x)) { + X509_OBJECT_free(obj); + return 0; + } + + obj->type = X509_LU_X509; + obj->data.x509 = x; + + return X509_STORE_add_object(store, obj); +} +LCRYPTO_ALIAS(X509_STORE_add_cert); + +int +X509_STORE_add_crl(X509_STORE *store, X509_CRL *x) +{ + X509_OBJECT *obj; + + if (x == NULL) + return 0; + + if ((obj = X509_OBJECT_new()) == NULL) + return 0; + + if (!X509_CRL_up_ref(x)) { + X509_OBJECT_free(obj); + return 0; + } + + obj->type = X509_LU_CRL; + obj->data.crl = x; + + return X509_STORE_add_object(store, obj); +} +LCRYPTO_ALIAS(X509_STORE_add_crl); + +int +X509_OBJECT_up_ref_count(X509_OBJECT *a) +{ + switch (a->type) { + case X509_LU_X509: + return X509_up_ref(a->data.x509); + case X509_LU_CRL: + return X509_CRL_up_ref(a->data.crl); + } + return 1; +} +LCRYPTO_ALIAS(X509_OBJECT_up_ref_count); + +X509_LOOKUP_TYPE +X509_OBJECT_get_type(const X509_OBJECT *a) +{ + return a->type; +} +LCRYPTO_ALIAS(X509_OBJECT_get_type); + +static int +x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name, int *pnmatch) +{ + X509_OBJECT stmp; + X509 x509_s; + X509_CINF cinf_s; + X509_CRL crl_s; + X509_CRL_INFO crl_info_s; + int idx; + + stmp.type = type; + switch (type) { + case X509_LU_X509: + stmp.data.x509 = &x509_s; + x509_s.cert_info = &cinf_s; + cinf_s.subject = name; + break; + case X509_LU_CRL: + stmp.data.crl = &crl_s; + crl_s.crl = &crl_info_s; + crl_info_s.issuer = name; + break; + default: + 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)++; + } + } + return idx; +} + +int +X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + return x509_object_idx_cnt(h, type, name, NULL); +} +LCRYPTO_ALIAS(X509_OBJECT_idx_by_subject); + +X509_OBJECT * +X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name) +{ + int idx; + + idx = X509_OBJECT_idx_by_subject(h, type, name); + if (idx == -1) + return NULL; + return sk_X509_OBJECT_value(h, idx); +} +LCRYPTO_ALIAS(X509_OBJECT_retrieve_by_subject); + +X509 * +X509_OBJECT_get0_X509(const X509_OBJECT *xo) +{ + if (xo != NULL && xo->type == X509_LU_X509) + return xo->data.x509; + return NULL; +} +LCRYPTO_ALIAS(X509_OBJECT_get0_X509); + +X509_CRL * +X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo) +{ + if (xo != NULL && xo->type == X509_LU_CRL) + return xo->data.crl; + return NULL; +} +LCRYPTO_ALIAS(X509_OBJECT_get0_X509_CRL); + +static STACK_OF(X509) * +X509_get1_certs_from_cache(X509_STORE *store, X509_NAME *name) +{ + STACK_OF(X509) *sk = NULL; + X509 *x = NULL; + X509_OBJECT *obj; + int i, idx, cnt; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + + idx = x509_object_idx_cnt(store->objs, X509_LU_X509, name, &cnt); + if (idx < 0) + goto err; + + if ((sk = sk_X509_new_null()) == NULL) + goto err; + + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(store->objs, idx); + + x = obj->data.x509; + if (!X509_up_ref(x)) { + x = NULL; + goto err; + } + if (!sk_X509_push(sk, x)) + goto err; + } + + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + + return sk; + + err: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + sk_X509_pop_free(sk, X509_free); + X509_free(x); + + return NULL; +} + +STACK_OF(X509) * +X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *name) +{ + X509_STORE *store = ctx->store; + STACK_OF(X509) *sk; + X509_OBJECT *obj; + + if (store == NULL) + return NULL; + + if ((sk = X509_get1_certs_from_cache(store, name)) != NULL) + return sk; + + /* Nothing found: do lookup to possibly add new objects to cache. */ + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, name); + if (obj == NULL) + return NULL; + X509_OBJECT_free(obj); + + return X509_get1_certs_from_cache(store, name); +} +LCRYPTO_ALIAS(X509_STORE_CTX_get1_certs); + +STACK_OF(X509_CRL) * +X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *name) +{ + X509_STORE *store = ctx->store; + STACK_OF(X509_CRL) *sk = NULL; + X509_CRL *x = NULL; + X509_OBJECT *obj = NULL; + int i, idx, cnt; + + if (store == NULL) + return NULL; + + /* Always do lookup to possibly add new CRLs to cache */ + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_CRL, name); + if (obj == NULL) + return NULL; + + X509_OBJECT_free(obj); + obj = NULL; + + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + idx = x509_object_idx_cnt(store->objs, X509_LU_CRL, name, &cnt); + if (idx < 0) + goto err; + + if ((sk = sk_X509_CRL_new_null()) == NULL) + goto err; + + for (i = 0; i < cnt; i++, idx++) { + obj = sk_X509_OBJECT_value(store->objs, idx); + + x = obj->data.crl; + if (!X509_CRL_up_ref(x)) { + x = NULL; + goto err; + } + if (!sk_X509_CRL_push(sk, x)) + goto err; + } + + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + return sk; + + err: + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get1_crls); + +X509_OBJECT * +X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x) +{ + int idx, i; + X509_OBJECT *obj; + + idx = sk_X509_OBJECT_find(h, x); + if (idx == -1) + return NULL; + if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL)) + return sk_X509_OBJECT_value(h, idx); + for (i = idx; i < sk_X509_OBJECT_num(h); i++) { + obj = sk_X509_OBJECT_value(h, i); + if (x509_object_cmp((const X509_OBJECT **)&obj, + (const X509_OBJECT **)&x)) + return NULL; + if (x->type == X509_LU_X509) { + 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)) + return obj; + } else + return obj; + } + return NULL; +} +LCRYPTO_ALIAS(X509_OBJECT_retrieve_match); + +/* 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. + * + * Return values are: + * 1 lookup successful. + * 0 certificate not found. + * -1 some other error. + */ +int +X509_STORE_CTX_get1_issuer(X509 **out_issuer, X509_STORE_CTX *ctx, X509 *x) +{ + X509_NAME *xn; + X509_OBJECT *obj, *pobj; + X509 *issuer = NULL; + int i, idx, ret; + + *out_issuer = NULL; + + xn = X509_get_issuer_name(x); + obj = X509_STORE_CTX_get_obj_by_subject(ctx, X509_LU_X509, xn); + if (obj == NULL) + return 0; + + if ((issuer = X509_OBJECT_get0_X509(obj)) == NULL) { + X509_OBJECT_free(obj); + return 0; + } + if (!X509_up_ref(issuer)) { + X509_OBJECT_free(obj); + return -1; + } + + /* If certificate matches all OK */ + if (ctx->check_issued(ctx, x, issuer)) { + if (x509_check_cert_time(ctx, issuer, -1)) { + *out_issuer = issuer; + X509_OBJECT_free(obj); + return 1; + } + } + X509_free(issuer); + issuer = NULL; + X509_OBJECT_free(obj); + obj = NULL; + + if (ctx->store == NULL) + return 0; + + /* Else find index of first cert accepted by 'check_issued' */ + CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE); + idx = X509_OBJECT_idx_by_subject(ctx->store->objs, X509_LU_X509, xn); + 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(ctx->store->objs); i++) { + pobj = sk_X509_OBJECT_value(ctx->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; + /* + * 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. + */ + if (x509_check_cert_time(ctx, issuer, -1)) + break; + } + } + } + ret = 0; + if (issuer != NULL) { + if (!X509_up_ref(issuer)) { + ret = -1; + } else { + *out_issuer = issuer; + ret = 1; + } + } + CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE); + return ret; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get1_issuer); + +STACK_OF(X509_OBJECT) * +X509_STORE_get0_objects(X509_STORE *xs) +{ + return xs->objs; +} +LCRYPTO_ALIAS(X509_STORE_get0_objects); + +void * +X509_STORE_get_ex_data(X509_STORE *xs, int idx) +{ + return CRYPTO_get_ex_data(&xs->ex_data, idx); +} +LCRYPTO_ALIAS(X509_STORE_get_ex_data); + +int +X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data) +{ + return CRYPTO_set_ex_data(&xs->ex_data, idx, data); +} +LCRYPTO_ALIAS(X509_STORE_set_ex_data); + +int +X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags) +{ + return X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} +LCRYPTO_ALIAS(X509_STORE_set_flags); + +int +X509_STORE_set_depth(X509_STORE *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); + return 1; +} +LCRYPTO_ALIAS(X509_STORE_set_depth); + +int +X509_STORE_set_purpose(X509_STORE *ctx, int purpose) +{ + return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose); +} +LCRYPTO_ALIAS(X509_STORE_set_purpose); + +int +X509_STORE_set_trust(X509_STORE *ctx, int trust) +{ + return X509_VERIFY_PARAM_set_trust(ctx->param, trust); +} +LCRYPTO_ALIAS(X509_STORE_set_trust); + +int +X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param) +{ + return X509_VERIFY_PARAM_set1(ctx->param, param); +} +LCRYPTO_ALIAS(X509_STORE_set1_param); + +X509_VERIFY_PARAM * +X509_STORE_get0_param(X509_STORE *ctx) +{ + return ctx->param; +} +LCRYPTO_ALIAS(X509_STORE_get0_param); + +void +X509_STORE_set_verify(X509_STORE *store, X509_STORE_CTX_verify_fn verify) +{ + store->verify = verify; +} +LCRYPTO_ALIAS(X509_STORE_set_verify); + +X509_STORE_CTX_verify_fn +X509_STORE_get_verify(X509_STORE *store) +{ + return store->verify; +} +LCRYPTO_ALIAS(X509_STORE_get_verify); + +void +X509_STORE_set_verify_cb(X509_STORE *store, X509_STORE_CTX_verify_cb verify_cb) +{ + store->verify_cb = verify_cb; +} +LCRYPTO_ALIAS(X509_STORE_set_verify_cb); + +X509_STORE_CTX_verify_cb +X509_STORE_get_verify_cb(X509_STORE *store) +{ + return store->verify_cb; +} +LCRYPTO_ALIAS(X509_STORE_get_verify_cb); diff --git a/crypto/x509/x509_ncons.c b/crypto/x509/x509_ncons.c new file mode 100644 index 0000000..159e3c2 --- /dev/null +++ b/crypto/x509/x509_ncons.c @@ -0,0 +1,561 @@ +/* $OpenBSD: x509_ncons.c,v 1.9 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, + void *a, BIO *bp, int ind); +static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp, int ind, char *name); +static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip); + +static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc); +static int nc_match_single(GENERAL_NAME *sub, GENERAL_NAME *gen); +static int nc_dn(X509_NAME *sub, X509_NAME *nm); +static int nc_dns(ASN1_IA5STRING *sub, ASN1_IA5STRING *dns); +static int nc_email(ASN1_IA5STRING *sub, ASN1_IA5STRING *eml); +static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base); + +const X509V3_EXT_METHOD v3_name_constraints = { + .ext_nid = NID_name_constraints, + .ext_flags = 0, + .it = &NAME_CONSTRAINTS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = v2i_NAME_CONSTRAINTS, + .i2r = i2r_NAME_CONSTRAINTS, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE GENERAL_SUBTREE_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(GENERAL_SUBTREE, base), + .field_name = "base", + .item = &GENERAL_NAME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(GENERAL_SUBTREE, minimum), + .field_name = "minimum", + .item = &ASN1_INTEGER_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(GENERAL_SUBTREE, maximum), + .field_name = "maximum", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM GENERAL_SUBTREE_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = GENERAL_SUBTREE_seq_tt, + .tcount = sizeof(GENERAL_SUBTREE_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(GENERAL_SUBTREE), + .sname = "GENERAL_SUBTREE", +}; + +static const ASN1_TEMPLATE NAME_CONSTRAINTS_seq_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(NAME_CONSTRAINTS, permittedSubtrees), + .field_name = "permittedSubtrees", + .item = &GENERAL_SUBTREE_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(NAME_CONSTRAINTS, excludedSubtrees), + .field_name = "excludedSubtrees", + .item = &GENERAL_SUBTREE_it, + }, +}; + +const ASN1_ITEM NAME_CONSTRAINTS_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = NAME_CONSTRAINTS_seq_tt, + .tcount = sizeof(NAME_CONSTRAINTS_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(NAME_CONSTRAINTS), + .sname = "NAME_CONSTRAINTS", +}; + + +GENERAL_SUBTREE * +GENERAL_SUBTREE_new(void) +{ + return (GENERAL_SUBTREE*)ASN1_item_new(&GENERAL_SUBTREE_it); +} +LCRYPTO_ALIAS(GENERAL_SUBTREE_new); + +void +GENERAL_SUBTREE_free(GENERAL_SUBTREE *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &GENERAL_SUBTREE_it); +} +LCRYPTO_ALIAS(GENERAL_SUBTREE_free); + +NAME_CONSTRAINTS * +NAME_CONSTRAINTS_new(void) +{ + return (NAME_CONSTRAINTS*)ASN1_item_new(&NAME_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(NAME_CONSTRAINTS_new); + +void +NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &NAME_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(NAME_CONSTRAINTS_free); + +static void * +v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + int i; + CONF_VALUE tval, *val; + STACK_OF(GENERAL_SUBTREE) **ptree = NULL; + NAME_CONSTRAINTS *ncons = NULL; + GENERAL_SUBTREE *sub = NULL; + + ncons = NAME_CONSTRAINTS_new(); + if (!ncons) + goto memerr; + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!strncmp(val->name, "permitted", 9) && val->name[9]) { + ptree = &ncons->permittedSubtrees; + tval.name = val->name + 10; + } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) { + ptree = &ncons->excludedSubtrees; + tval.name = val->name + 9; + } else { + X509V3error(X509V3_R_INVALID_SYNTAX); + goto err; + } + tval.value = val->value; + sub = GENERAL_SUBTREE_new(); + if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1)) + goto err; + if (!*ptree) + *ptree = sk_GENERAL_SUBTREE_new_null(); + if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub)) + goto memerr; + sub = NULL; + } + + return ncons; + +memerr: + X509V3error(ERR_R_MALLOC_FAILURE); +err: + NAME_CONSTRAINTS_free(ncons); + GENERAL_SUBTREE_free(sub); + return NULL; +} + +static int +i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, BIO *bp, int ind) +{ + NAME_CONSTRAINTS *ncons = a; + + do_i2r_name_constraints(method, ncons->permittedSubtrees, + bp, ind, "Permitted"); + do_i2r_name_constraints(method, ncons->excludedSubtrees, + bp, ind, "Excluded"); + return 1; +} + +static int +do_i2r_name_constraints(const X509V3_EXT_METHOD *method, + STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp, int ind, char *name) +{ + GENERAL_SUBTREE *tree; + int i; + + if (sk_GENERAL_SUBTREE_num(trees) > 0) + BIO_printf(bp, "%*s%s:\n", ind, "", name); + for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) { + tree = sk_GENERAL_SUBTREE_value(trees, i); + BIO_printf(bp, "%*s", ind + 2, ""); + if (tree->base->type == GEN_IPADD) + print_nc_ipadd(bp, tree->base->d.ip); + else + GENERAL_NAME_print(bp, tree->base); + BIO_puts(bp, "\n"); + } + return 1; +} + +static int +print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip) +{ + int i, len; + unsigned char *p; + + p = ip->data; + len = ip->length; + BIO_puts(bp, "IP:"); + if (len == 8) { + BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + } else if (len == 32) { + for (i = 0; i < 16; i++) { + BIO_printf(bp, "%X", p[0] << 8 | p[1]); + p += 2; + if (i == 7) + BIO_puts(bp, "/"); + else if (i != 15) + BIO_puts(bp, ":"); + } + } else + BIO_printf(bp, "IP Address:"); + return 1; +} + +/* Check a certificate conforms to a specified set of constraints. + * Return values: + * X509_V_OK: All constraints obeyed. + * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation. + * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation. + * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type. + * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax. + * X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name + */ + +int +NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc) +{ + int r, i; + X509_NAME *nm; + + nm = X509_get_subject_name(x); + + if (X509_NAME_entry_count(nm) > 0) { + GENERAL_NAME gntmp; + gntmp.type = GEN_DIRNAME; + gntmp.d.directoryName = nm; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + + gntmp.type = GEN_EMAIL; + + /* Process any email address attributes in subject name */ + + for (i = -1;;) { + X509_NAME_ENTRY *ne; + i = X509_NAME_get_index_by_NID(nm, + NID_pkcs9_emailAddress, i); + if (i == -1) + break; + ne = X509_NAME_get_entry(nm, i); + gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne); + if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + r = nc_match(&gntmp, nc); + + if (r != X509_V_OK) + return r; + } + + } + + for (i = 0; i < sk_GENERAL_NAME_num(x->altname); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, i); + r = nc_match(gen, nc); + if (r != X509_V_OK) + return r; + } + return X509_V_OK; +} +LCRYPTO_ALIAS(NAME_CONSTRAINTS_check); +static int +nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc) +{ + GENERAL_SUBTREE *sub; + int i, r, match = 0; + + /* Permitted subtrees: if any subtrees exist of matching the type + * at least one subtree must match. + */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + /* If we already have a match don't bother trying any more */ + if (match == 2) + continue; + if (match == 0) + match = 1; + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + match = 2; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + } + + if (match == 1) + return X509_V_ERR_PERMITTED_VIOLATION; + + /* Excluded subtrees: must not match any of these */ + + for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) { + sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i); + if (gen->type != sub->base->type) + continue; + if (sub->minimum || sub->maximum) + return X509_V_ERR_SUBTREE_MINMAX; + + r = nc_match_single(gen, sub->base); + if (r == X509_V_OK) + return X509_V_ERR_EXCLUDED_VIOLATION; + else if (r != X509_V_ERR_PERMITTED_VIOLATION) + return r; + + } + + return X509_V_OK; +} + +static int +nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base) +{ + switch (base->type) { + case GEN_DIRNAME: + return nc_dn(gen->d.directoryName, base->d.directoryName); + + case GEN_DNS: + return nc_dns(gen->d.dNSName, base->d.dNSName); + + case GEN_EMAIL: + return nc_email(gen->d.rfc822Name, base->d.rfc822Name); + + case GEN_URI: + return nc_uri(gen->d.uniformResourceIdentifier, + base->d.uniformResourceIdentifier); + + default: + return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE; + } +} + +/* directoryName name constraint matching. + * The canonical encoding of X509_NAME makes this comparison easy. It is + * matched if the subtree is a subset of the name. + */ + +static int +nc_dn(X509_NAME *nm, X509_NAME *base) +{ + /* Ensure canonical encodings are up to date. */ + if (nm->modified && i2d_X509_NAME(nm, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->modified && i2d_X509_NAME(base, NULL) < 0) + return X509_V_ERR_OUT_OF_MEM; + if (base->canon_enclen > nm->canon_enclen) + return X509_V_ERR_PERMITTED_VIOLATION; + if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen)) + return X509_V_ERR_PERMITTED_VIOLATION; + return X509_V_OK; +} + +static int +nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base) +{ + char *baseptr = (char *)base->data; + char *dnsptr = (char *)dns->data; + + /* Empty matches everything */ + if (!*baseptr) + return X509_V_OK; + /* Otherwise can add zero or more components on the left so + * compare RHS and if dns is longer and expect '.' as preceding + * character. + */ + if (dns->length > base->length) { + dnsptr += dns->length - base->length; + if (baseptr[0] != '.' && dnsptr[-1] != '.') + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if (strcasecmp(baseptr, dnsptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; +} + +static int +nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *emlptr = (char *)eml->data; + const char *baseat = strchr(baseptr, '@'); + const char *emlat = strchr(emlptr, '@'); + + if (!emlat) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + /* Special case: initial '.' is RHS match */ + if (!baseat && (*baseptr == '.')) { + if (eml->length > base->length) { + emlptr += eml->length - base->length; + if (!strcasecmp(baseptr, emlptr)) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + /* If we have anything before '@' match local part */ + + if (baseat) { + if (baseat != baseptr) { + if ((baseat - baseptr) != (emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + /* Case sensitive match of local part */ + if (strncmp(baseptr, emlptr, emlat - emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + } + /* Position base after '@' */ + baseptr = baseat + 1; + } + emlptr = emlat + 1; + /* Just have hostname left to match: case insensitive */ + if (strcasecmp(baseptr, emlptr)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; +} + +static int +nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base) +{ + const char *baseptr = (char *)base->data; + const char *hostptr = (char *)uri->data; + const char *p = strchr(hostptr, ':'); + int hostlen; + + /* Check for foo:// and skip past it */ + if (!p || (p[1] != '/') || (p[2] != '/')) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + hostptr = p + 3; + + /* Determine length of hostname part of URI */ + + /* Look for a port indicator as end of hostname first */ + + p = strchr(hostptr, ':'); + /* Otherwise look for trailing slash */ + if (!p) + p = strchr(hostptr, '/'); + + if (!p) + hostlen = strlen(hostptr); + else + hostlen = p - hostptr; + + if (hostlen == 0) + return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX; + + /* Special case: initial '.' is RHS match */ + if (*baseptr == '.') { + if (hostlen > base->length) { + p = hostptr + hostlen - base->length; + if (!strncasecmp(p, baseptr, base->length)) + return X509_V_OK; + } + return X509_V_ERR_PERMITTED_VIOLATION; + } + + if ((base->length != (int)hostlen) || + strncasecmp(hostptr, baseptr, hostlen)) + return X509_V_ERR_PERMITTED_VIOLATION; + + return X509_V_OK; +} diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c new file mode 100644 index 0000000..ea4ae6b --- /dev/null +++ b/crypto/x509/x509_obj.c @@ -0,0 +1,182 @@ +/* $OpenBSD: x509_obj.c,v 1.22 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_local.h" + +char * +X509_NAME_oneline(const X509_NAME *a, char *buf, int len) +{ + X509_NAME_ENTRY *ne; + int i; + int n, lold, l, l1, l2, num, j, type; + const char *s; + char *p; + unsigned char *q; + BUF_MEM *b = NULL; + static const char hex[17] = "0123456789ABCDEF"; + int gs_doit[4]; + char tmp_buf[80]; + + if (buf == NULL) { + if ((b = BUF_MEM_new()) == NULL) + goto err; + if (!BUF_MEM_grow(b, 200)) + goto err; + b->data[0] = '\0'; + len = 200; + } + if (a == NULL) { + if (b) { + buf = b->data; + free(b); + } + strlcpy(buf, "NO X509_NAME", len); + return buf; + } + + len--; /* space for '\0' */ + l = 0; + for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { + ne = sk_X509_NAME_ENTRY_value(a->entries, i); + n = OBJ_obj2nid(ne->object); + if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { + i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); + s = tmp_buf; + } + l1 = strlen(s); + + type = ne->value->type; + num = ne->value->length; + q = ne->value->data; + if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; + for (j = 0; j < num; j++) + if (q[j] != 0) + gs_doit[j & 3] = 1; + + if (gs_doit[0]|gs_doit[1]|gs_doit[2]) + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + else { + gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; + gs_doit[3] = 1; + } + } else + gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; + + for (l2 = j=0; j < num; j++) { + if (!gs_doit[j&3]) + continue; + l2++; + if ((q[j] < ' ') || (q[j] > '~')) + l2 += 3; + } + + lold = l; + l += 1 + l1 + 1 + l2; + if (b != NULL) { + if (!BUF_MEM_grow(b, l + 1)) + goto err; + p = &(b->data[lold]); + } else if (l > len) { + break; + } else + p = &(buf[lold]); + *(p++) = '/'; + memcpy(p, s, l1); + p += l1; + *(p++) = '='; + q = ne->value->data; + for (j = 0; j < num; j++) { + if (!gs_doit[j & 3]) + continue; + n = q[j]; + if ((n < ' ') || (n > '~')) { + *(p++) = '\\'; + *(p++) = 'x'; + *(p++) = hex[(n >> 4) & 0x0f]; + *(p++) = hex[n & 0x0f]; + } else + *(p++) = n; + } + *p = '\0'; + } + if (b != NULL) { + p = b->data; + free(b); + } else + p = buf; + if (i == 0) + *p = '\0'; + return (p); + +err: + X509error(ERR_R_MALLOC_FAILURE); + if (b != NULL) + BUF_MEM_free(b); + return (NULL); +} +LCRYPTO_ALIAS(X509_NAME_oneline); diff --git a/crypto/x509/x509_ocsp.c b/crypto/x509/x509_ocsp.c new file mode 100644 index 0000000..cc55d93 --- /dev/null +++ b/crypto/x509/x509_ocsp.c @@ -0,0 +1,382 @@ +/* $OpenBSD: x509_ocsp.c,v 1.2 2022/01/07 09:45:52 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include + +#ifndef OPENSSL_NO_OCSP + +#include +#include +#include +#include +#include + +#include "ocsp_local.h" + +/* OCSP extensions and a couple of CRL entry extensions + */ + +static int i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent); +static int i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *nonce, + BIO *out, int indent); +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 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, + BIO *out, int indent); + +static int i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, + void *nocheck, BIO *out, int indent); +static void *s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + const char *str); +static int i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, + BIO *bp, int ind); + +const X509V3_EXT_METHOD v3_ocsp_crlid = { + .ext_nid = NID_id_pkix_OCSP_CrlID, + .ext_flags = 0, + .it = &OCSP_CRLID_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_crlid, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_ocsp_acutoff = { + .ext_nid = NID_id_pkix_OCSP_archiveCutoff, + .ext_flags = 0, + .it = &ASN1_GENERALIZEDTIME_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_acutoff, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_crl_invdate = { + .ext_nid = NID_invalidity_date, + .ext_flags = 0, + .it = &ASN1_GENERALIZEDTIME_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_acutoff, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_crl_hold = { + .ext_nid = NID_hold_instruction_code, + .ext_flags = 0, + .it = &ASN1_OBJECT_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_object, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_ocsp_nonce = { + .ext_nid = NID_id_pkix_OCSP_Nonce, + .ext_flags = 0, + .it = NULL, + .ext_new = ocsp_nonce_new, + .ext_free = ocsp_nonce_free, + .d2i = d2i_ocsp_nonce, + .i2d = i2d_ocsp_nonce, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_nonce, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_ocsp_nocheck = { + .ext_nid = NID_id_pkix_OCSP_noCheck, + .ext_flags = 0, + .it = &ASN1_NULL_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = s2i_ocsp_nocheck, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_nocheck, + .r2i = NULL, + .usr_data = NULL, +}; + +const X509V3_EXT_METHOD v3_ocsp_serviceloc = { + .ext_nid = NID_id_pkix_OCSP_serviceLocator, + .ext_flags = 0, + .it = &OCSP_SERVICELOC_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = i2r_ocsp_serviceloc, + .r2i = NULL, + .usr_data = NULL, +}; + +static int +i2r_ocsp_crlid(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) +{ + OCSP_CRLID *a = in; + if (a->crlUrl) { + if (BIO_printf(bp, "%*scrlUrl: ", ind, "") <= 0) + goto err; + if (!ASN1_STRING_print(bp, (ASN1_STRING*)a->crlUrl)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (a->crlNum) { + if (BIO_printf(bp, "%*scrlNum: ", ind, "") <= 0) + goto err; + if (i2a_ASN1_INTEGER(bp, a->crlNum) <= 0) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + if (a->crlTime) { + if (BIO_printf(bp, "%*scrlTime: ", ind, "") <= 0) + goto err; + if (!ASN1_GENERALIZEDTIME_print(bp, a->crlTime)) + goto err; + if (BIO_write(bp, "\n", 1) <= 0) + goto err; + } + return 1; + +err: + return 0; +} + +static int +i2r_ocsp_acutoff(const X509V3_EXT_METHOD *method, void *cutoff, BIO *bp, + int ind) +{ + if (BIO_printf(bp, "%*s", ind, "") <= 0) + return 0; + if (!ASN1_GENERALIZEDTIME_print(bp, cutoff)) + return 0; + return 1; +} + +static int +i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp, int ind) +{ + if (BIO_printf(bp, "%*s", ind, "") <= 0) + return 0; + if (i2a_ASN1_OBJECT(bp, oid) <= 0) + return 0; + return 1; +} + +/* OCSP nonce. This is needs special treatment because it doesn't have + * an ASN1 encoding at all: it just contains arbitrary data. + */ + +static void * +ocsp_nonce_new(void) +{ + return ASN1_OCTET_STRING_new(); +} + +static int +i2d_ocsp_nonce(void *a, unsigned char **pp) +{ + ASN1_OCTET_STRING *os = a; + + if (pp) { + memcpy(*pp, os->data, os->length); + *pp += os->length; + } + return os->length; +} + +static void * +d2i_ocsp_nonce(void *a, const unsigned char **pp, long length) +{ + ASN1_OCTET_STRING *os, **pos; + + pos = a; + if (pos == NULL || *pos == NULL) { + os = ASN1_OCTET_STRING_new(); + if (os == NULL) + goto err; + } else + os = *pos; + if (ASN1_OCTET_STRING_set(os, *pp, length) == 0) + goto err; + + *pp += length; + + if (pos != NULL) + *pos = os; + return os; + +err: + if (pos == NULL || *pos != os) + ASN1_OCTET_STRING_free(os); + OCSPerror(ERR_R_MALLOC_FAILURE); + return NULL; +} + +static void +ocsp_nonce_free(void *a) +{ + ASN1_OCTET_STRING_free(a); +} + +static int +i2r_ocsp_nonce(const X509V3_EXT_METHOD *method, void *nonce, BIO *out, + int indent) +{ + if (BIO_printf(out, "%*s", indent, "") <= 0) + return 0; + if (i2a_ASN1_STRING(out, nonce, V_ASN1_OCTET_STRING) <= 0) + return 0; + return 1; +} + +/* Nocheck is just a single NULL. Don't print anything and always set it */ + +static int +i2r_ocsp_nocheck(const X509V3_EXT_METHOD *method, void *nocheck, BIO *out, + int indent) +{ + return 1; +} + +static void * +s2i_ocsp_nocheck(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + const char *str) +{ + return ASN1_NULL_new(); +} + +static int +i2r_ocsp_serviceloc(const X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) +{ + int i; + OCSP_SERVICELOC *a = in; + ACCESS_DESCRIPTION *ad; + + if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) + goto err; + if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) + goto err; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { + ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); + if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) + goto err; + if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) + goto err; + if (BIO_puts(bp, " - ") <= 0) + goto err; + if (GENERAL_NAME_print(bp, ad->location) <= 0) + goto err; + } + return 1; + +err: + return 0; +} +#endif diff --git a/crypto/x509/x509_pcons.c b/crypto/x509/x509_pcons.c new file mode 100644 index 0000000..0ee9355 --- /dev/null +++ b/crypto/x509/x509_pcons.c @@ -0,0 +1,196 @@ +/* $OpenBSD: x509_pcons.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +static STACK_OF(CONF_VALUE) * +i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *bcons, + STACK_OF(CONF_VALUE) *extlist); +static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values); + +const X509V3_EXT_METHOD v3_policy_constraints = { + .ext_nid = NID_policy_constraints, + .ext_flags = 0, + .it = &POLICY_CONSTRAINTS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = i2v_POLICY_CONSTRAINTS, + .v2i = v2i_POLICY_CONSTRAINTS, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE POLICY_CONSTRAINTS_seq_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(POLICY_CONSTRAINTS, requireExplicitPolicy), + .field_name = "requireExplicitPolicy", + .item = &ASN1_INTEGER_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(POLICY_CONSTRAINTS, inhibitPolicyMapping), + .field_name = "inhibitPolicyMapping", + .item = &ASN1_INTEGER_it, + }, +}; + +const ASN1_ITEM POLICY_CONSTRAINTS_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = POLICY_CONSTRAINTS_seq_tt, + .tcount = sizeof(POLICY_CONSTRAINTS_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(POLICY_CONSTRAINTS), + .sname = "POLICY_CONSTRAINTS", +}; + + +POLICY_CONSTRAINTS * +POLICY_CONSTRAINTS_new(void) +{ + return (POLICY_CONSTRAINTS*)ASN1_item_new(&POLICY_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(POLICY_CONSTRAINTS_new); + +void +POLICY_CONSTRAINTS_free(POLICY_CONSTRAINTS *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &POLICY_CONSTRAINTS_it); +} +LCRYPTO_ALIAS(POLICY_CONSTRAINTS_free); + +static STACK_OF(CONF_VALUE) * +i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a, + STACK_OF(CONF_VALUE) *extlist) +{ + POLICY_CONSTRAINTS *pcons = a; + STACK_OF(CONF_VALUE) *free_extlist = NULL; + + if (extlist == NULL) { + if ((free_extlist = extlist = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + if (!X509V3_add_value_int("Require Explicit Policy", + pcons->requireExplicitPolicy, &extlist)) + goto err; + if (!X509V3_add_value_int("Inhibit Policy Mapping", + pcons->inhibitPolicyMapping, &extlist)) + goto err; + + return extlist; + + err: + sk_CONF_VALUE_pop_free(free_extlist, X509V3_conf_free); + + return NULL; +} + +static void * +v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *values) +{ + POLICY_CONSTRAINTS *pcons = NULL; + CONF_VALUE *val; + int i; + + if (!(pcons = POLICY_CONSTRAINTS_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + for (i = 0; i < sk_CONF_VALUE_num(values); i++) { + val = sk_CONF_VALUE_value(values, i); + if (!strcmp(val->name, "requireExplicitPolicy")) { + if (!X509V3_get_value_int(val, + &pcons->requireExplicitPolicy)) goto err; + } else if (!strcmp(val->name, "inhibitPolicyMapping")) { + if (!X509V3_get_value_int(val, + &pcons->inhibitPolicyMapping)) goto err; + } else { + X509V3error(X509V3_R_INVALID_NAME); + X509V3_conf_err(val); + goto err; + } + } + if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) { + X509V3error(X509V3_R_ILLEGAL_EMPTY_EXTENSION); + goto err; + } + + return pcons; + +err: + POLICY_CONSTRAINTS_free(pcons); + return NULL; +} diff --git a/crypto/x509/x509_pku.c b/crypto/x509/x509_pku.c new file mode 100644 index 0000000..dd28077 --- /dev/null +++ b/crypto/x509/x509_pku.c @@ -0,0 +1,158 @@ +/* $OpenBSD: x509_pku.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include + +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 = { + .ext_nid = NID_private_key_usage_period, + .ext_flags = 0, + .it = &PKEY_USAGE_PERIOD_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = NULL, + .v2i = NULL, + .i2r = (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE PKEY_USAGE_PERIOD_seq_tt[] = { + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 0, + .offset = offsetof(PKEY_USAGE_PERIOD, notBefore), + .field_name = "notBefore", + .item = &ASN1_GENERALIZEDTIME_it, + }, + { + .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL, + .tag = 1, + .offset = offsetof(PKEY_USAGE_PERIOD, notAfter), + .field_name = "notAfter", + .item = &ASN1_GENERALIZEDTIME_it, + }, +}; + +const ASN1_ITEM PKEY_USAGE_PERIOD_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = PKEY_USAGE_PERIOD_seq_tt, + .tcount = sizeof(PKEY_USAGE_PERIOD_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(PKEY_USAGE_PERIOD), + .sname = "PKEY_USAGE_PERIOD", +}; + + +PKEY_USAGE_PERIOD * +d2i_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD **a, const unsigned char **in, long len) +{ + return (PKEY_USAGE_PERIOD *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, + &PKEY_USAGE_PERIOD_it); +} +LCRYPTO_ALIAS(d2i_PKEY_USAGE_PERIOD); + +int +i2d_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD *a, unsigned char **out) +{ + return ASN1_item_i2d((ASN1_VALUE *)a, out, &PKEY_USAGE_PERIOD_it); +} +LCRYPTO_ALIAS(i2d_PKEY_USAGE_PERIOD); + +PKEY_USAGE_PERIOD * +PKEY_USAGE_PERIOD_new(void) +{ + return (PKEY_USAGE_PERIOD *)ASN1_item_new(&PKEY_USAGE_PERIOD_it); +} +LCRYPTO_ALIAS(PKEY_USAGE_PERIOD_new); + +void +PKEY_USAGE_PERIOD_free(PKEY_USAGE_PERIOD *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &PKEY_USAGE_PERIOD_it); +} +LCRYPTO_ALIAS(PKEY_USAGE_PERIOD_free); + +static int +i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, + BIO *out, int indent) +{ + BIO_printf(out, "%*s", indent, ""); + if (usage->notBefore) { + BIO_write(out, "Not Before: ", 12); + ASN1_GENERALIZEDTIME_print(out, usage->notBefore); + if (usage->notAfter) + BIO_write(out, ", ", 2); + } + if (usage->notAfter) { + BIO_write(out, "Not After: ", 11); + ASN1_GENERALIZEDTIME_print(out, usage->notAfter); + } + return 1; +} diff --git a/crypto/x509/x509_pmaps.c b/crypto/x509/x509_pmaps.c new file mode 100644 index 0000000..39aebfe --- /dev/null +++ b/crypto/x509/x509_pmaps.c @@ -0,0 +1,237 @@ +/* $OpenBSD: x509_pmaps.c,v 1.3 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + +#include + +#include +#include +#include +#include + +static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS( + const X509V3_EXT_METHOD *method, void *pmps, STACK_OF(CONF_VALUE) *extlist); + +const X509V3_EXT_METHOD v3_policy_mappings = { + .ext_nid = NID_policy_mappings, + .ext_flags = 0, + .it = &POLICY_MAPPINGS_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = NULL, + .s2i = NULL, + .i2v = i2v_POLICY_MAPPINGS, + .v2i = v2i_POLICY_MAPPINGS, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +static const ASN1_TEMPLATE POLICY_MAPPING_seq_tt[] = { + { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICY_MAPPING, issuerDomainPolicy), + .field_name = "issuerDomainPolicy", + .item = &ASN1_OBJECT_it, + }, + { + .flags = 0, + .tag = 0, + .offset = offsetof(POLICY_MAPPING, subjectDomainPolicy), + .field_name = "subjectDomainPolicy", + .item = &ASN1_OBJECT_it, + }, +}; + +const ASN1_ITEM POLICY_MAPPING_it = { + .itype = ASN1_ITYPE_SEQUENCE, + .utype = V_ASN1_SEQUENCE, + .templates = POLICY_MAPPING_seq_tt, + .tcount = sizeof(POLICY_MAPPING_seq_tt) / sizeof(ASN1_TEMPLATE), + .funcs = NULL, + .size = sizeof(POLICY_MAPPING), + .sname = "POLICY_MAPPING", +}; + +static const ASN1_TEMPLATE POLICY_MAPPINGS_item_tt = { + .flags = ASN1_TFLG_SEQUENCE_OF, + .tag = 0, + .offset = 0, + .field_name = "POLICY_MAPPINGS", + .item = &POLICY_MAPPING_it, +}; + +const ASN1_ITEM POLICY_MAPPINGS_it = { + .itype = ASN1_ITYPE_PRIMITIVE, + .utype = -1, + .templates = &POLICY_MAPPINGS_item_tt, + .tcount = 0, + .funcs = NULL, + .size = 0, + .sname = "POLICY_MAPPINGS", +}; + + +POLICY_MAPPING * +POLICY_MAPPING_new(void) +{ + return (POLICY_MAPPING*)ASN1_item_new(&POLICY_MAPPING_it); +} +LCRYPTO_ALIAS(POLICY_MAPPING_new); + +void +POLICY_MAPPING_free(POLICY_MAPPING *a) +{ + ASN1_item_free((ASN1_VALUE *)a, &POLICY_MAPPING_it); +} +LCRYPTO_ALIAS(POLICY_MAPPING_free); + +static STACK_OF(CONF_VALUE) * +i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *a, + STACK_OF(CONF_VALUE) *extlist) +{ + STACK_OF(CONF_VALUE) *free_extlist = NULL; + POLICY_MAPPINGS *pmaps = a; + POLICY_MAPPING *pmap; + char issuer[80], subject[80]; + int i; + + if (extlist == NULL) { + if ((free_extlist = extlist = sk_CONF_VALUE_new_null()) == NULL) + return NULL; + } + + for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) { + if ((pmap = sk_POLICY_MAPPING_value(pmaps, i)) == NULL) + goto err; + if (!i2t_ASN1_OBJECT(issuer, sizeof issuer, + pmap->issuerDomainPolicy)) + goto err; + if (!i2t_ASN1_OBJECT(subject, sizeof subject, + pmap->subjectDomainPolicy)) + goto err; + if (!X509V3_add_value(issuer, subject, &extlist)) + goto err; + } + + return extlist; + + err: + sk_CONF_VALUE_pop_free(free_extlist, X509V3_conf_free); + + return NULL; +} + +static void * +v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + STACK_OF(CONF_VALUE) *nval) +{ + POLICY_MAPPINGS *pmaps = NULL; + POLICY_MAPPING *pmap = NULL; + ASN1_OBJECT *obj1 = NULL, *obj2 = NULL; + CONF_VALUE *val; + int i, rc; + + if (!(pmaps = sk_POLICY_MAPPING_new_null())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { + val = sk_CONF_VALUE_value(nval, i); + if (!val->value || !val->name) { + rc = X509V3_R_INVALID_OBJECT_IDENTIFIER; + goto err; + } + obj1 = OBJ_txt2obj(val->name, 0); + obj2 = OBJ_txt2obj(val->value, 0); + if (!obj1 || !obj2) { + rc = X509V3_R_INVALID_OBJECT_IDENTIFIER; + goto err; + } + pmap = POLICY_MAPPING_new(); + if (!pmap) { + rc = ERR_R_MALLOC_FAILURE; + goto err; + } + pmap->issuerDomainPolicy = obj1; + pmap->subjectDomainPolicy = obj2; + obj1 = obj2 = NULL; + if (sk_POLICY_MAPPING_push(pmaps, pmap) == 0) { + rc = ERR_R_MALLOC_FAILURE; + goto err; + } + pmap = NULL; + } + return pmaps; + +err: + sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free); + X509V3error(rc); + if (rc == X509V3_R_INVALID_OBJECT_IDENTIFIER) + X509V3_conf_err(val); + ASN1_OBJECT_free(obj1); + ASN1_OBJECT_free(obj2); + POLICY_MAPPING_free(pmap); + return NULL; +} diff --git a/crypto/x509/x509_policy.c b/crypto/x509/x509_policy.c new file mode 100644 index 0000000..73f7154 --- /dev/null +++ b/crypto/x509/x509_policy.c @@ -0,0 +1,1019 @@ +/* $OpenBSD: x509_policy.c,v 1.25 2023/04/28 16:30:14 tb Exp $ */ +/* + * Copyright (c) 2022, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include "x509_internal.h" +#include "x509_local.h" + +/* XXX move to proper place */ +#define X509_R_INVALID_POLICY_EXTENSION 201 + +/* + * This file computes the X.509 policy tree, as described in RFC 5280, section + * 6.1. It differs in that: + * + * (1) It does not track "qualifier_set". This is not needed as it is not + * output by this implementation. + * + * (2) It builds a directed acyclic graph, rather than a tree. When a given + * policy matches multiple parents, RFC 5280 makes a separate node for + * each parent. This representation condenses them into one node with + * multiple parents. Thus we refer to this structure as a "policy graph", + * rather than a "policy tree". + * + * (3) "expected_policy_set" is not tracked explicitly and built temporarily + * as part of building the graph. + * + * (4) anyPolicy nodes are not tracked explicitly. + * + * (5) Some pruning steps are deferred to when policies are evaluated, as a + * reachability pass. + */ + +/* + * An X509_POLICY_NODE is a node in the policy graph. It corresponds to a node + * from RFC 5280, section 6.1.2, step (a), but we store some fields differently. + */ +typedef struct x509_policy_node_st { + /* policy is the "valid_policy" field from RFC 5280. */ + ASN1_OBJECT *policy; + + /* + * parent_policies, if non-empty, is the list of "valid_policy" values + * for all nodes which are a parent of this node. In this case, no entry + * in this list will be anyPolicy. This list is in no particular order + * and may contain duplicates if the corresponding certificate had + * duplicate mappings. + * + * If empty, this node has a single parent, anyPolicy. The node is then + * a root policies, and is in authorities-constrained-policy-set if it + * has a path to a leaf node. + * + * Note it is not possible for a policy to have both anyPolicy and a + * concrete policy as a parent. Section 6.1.3, step (d.1.ii) only runs + * if there was no match in step (d.1.i). We do not need to represent a + * parent list of, say, {anyPolicy, OID1, OID2}. + */ + STACK_OF(ASN1_OBJECT) *parent_policies; + + /* + * mapped is one if this node matches a policy mapping in the + * certificate and zero otherwise. + */ + int mapped; + + /* + * reachable is one if this node is reachable from some valid policy in + * the end-entity certificate. It is computed during |has_explicit_policy|. + */ + int reachable; +} X509_POLICY_NODE; + +DECLARE_STACK_OF(X509_POLICY_NODE) + +#define sk_X509_POLICY_NODE_new(cmp) SKM_sk_new(X509_POLICY_NODE, (cmp)) +#define sk_X509_POLICY_NODE_new_null() SKM_sk_new_null(X509_POLICY_NODE) +#define sk_X509_POLICY_NODE_free(st) SKM_sk_free(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_num(st) SKM_sk_num(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_value(st, i) SKM_sk_value(X509_POLICY_NODE, (st), (i)) +#define sk_X509_POLICY_NODE_set(st, i, val) SKM_sk_set(X509_POLICY_NODE, (st), (i), (val)) +#define sk_X509_POLICY_NODE_zero(st) SKM_sk_zero(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_push(st, val) SKM_sk_push(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_unshift(st, val) SKM_sk_unshift(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_find(st, val) SKM_sk_find(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_NODE, (st), (val)) +#define sk_X509_POLICY_NODE_delete(st, i) SKM_sk_delete(X509_POLICY_NODE, (st), (i)) +#define sk_X509_POLICY_NODE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_NODE, (st), (ptr)) +#define sk_X509_POLICY_NODE_insert(st, val, i) SKM_sk_insert(X509_POLICY_NODE, (st), (val), (i)) +#define sk_X509_POLICY_NODE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_NODE, (st), (cmp)) +#define sk_X509_POLICY_NODE_dup(st) SKM_sk_dup(X509_POLICY_NODE, st) +#define sk_X509_POLICY_NODE_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_NODE, (st), (free_func)) +#define sk_X509_POLICY_NODE_shift(st) SKM_sk_shift(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_pop(st) SKM_sk_pop(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_sort(st) SKM_sk_sort(X509_POLICY_NODE, (st)) +#define sk_X509_POLICY_NODE_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_NODE, (st)) + +/* + * An X509_POLICY_LEVEL is the collection of nodes at the same depth in the + * policy graph. This structure can also be used to represent a level's + * "expected_policy_set" values. See |process_policy_mappings|. + */ +typedef struct x509_policy_level_st { + /* + * nodes is the list of nodes at this depth, except for the anyPolicy + * node, if any. This list is sorted by policy OID for efficient lookup. + */ + STACK_OF(X509_POLICY_NODE) *nodes; + + /* + * has_any_policy is one if there is an anyPolicy node at this depth, + * and zero otherwise. + */ + int has_any_policy; +} X509_POLICY_LEVEL; + +DECLARE_STACK_OF(X509_POLICY_LEVEL) + +#define sk_X509_POLICY_LEVEL_new(cmp) SKM_sk_new(X509_POLICY_LEVEL, (cmp)) +#define sk_X509_POLICY_LEVEL_new_null() SKM_sk_new_null(X509_POLICY_LEVEL) +#define sk_X509_POLICY_LEVEL_free(st) SKM_sk_free(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_num(st) SKM_sk_num(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_value(st, i) SKM_sk_value(X509_POLICY_LEVEL, (st), (i)) +#define sk_X509_POLICY_LEVEL_set(st, i, val) SKM_sk_set(X509_POLICY_LEVEL, (st), (i), (val)) +#define sk_X509_POLICY_LEVEL_zero(st) SKM_sk_zero(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_push(st, val) SKM_sk_push(X509_POLICY_LEVEL, (st), (val)) +#define sk_X509_POLICY_LEVEL_unshift(st, val) SKM_sk_unshift(X509_POLICY_LEVEL, (st), (val)) +#define sk_X509_POLICY_LEVEL_find(st, val) SKM_sk_find(X509_POLICY_LEVEL, (st), (val)) +#define sk_X509_POLICY_LEVEL_find_ex(st, val) SKM_sk_find_ex(X509_POLICY_LEVEL, (st), (val)) +#define sk_X509_POLICY_LEVEL_delete(st, i) SKM_sk_delete(X509_POLICY_LEVEL, (st), (i)) +#define sk_X509_POLICY_LEVEL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_POLICY_LEVEL, (st), (ptr)) +#define sk_X509_POLICY_LEVEL_insert(st, val, i) SKM_sk_insert(X509_POLICY_LEVEL, (st), (val), (i)) +#define sk_X509_POLICY_LEVEL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_POLICY_LEVEL, (st), (cmp)) +#define sk_X509_POLICY_LEVEL_dup(st) SKM_sk_dup(X509_POLICY_LEVEL, st) +#define sk_X509_POLICY_LEVEL_pop_free(st, free_func) SKM_sk_pop_free(X509_POLICY_LEVEL, (st), (free_func)) +#define sk_X509_POLICY_LEVEL_shift(st) SKM_sk_shift(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_pop(st) SKM_sk_pop(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_sort(st) SKM_sk_sort(X509_POLICY_LEVEL, (st)) +#define sk_X509_POLICY_LEVEL_is_sorted(st) SKM_sk_is_sorted(X509_POLICY_LEVEL, (st)) + +/* + * Don't look Ethel, but you would really not want to look if we did + * this the OpenSSL way either, and we are not using this boringsslism + * anywhere else. Callers should ensure that the stack in data is sorted. + */ +void +sk_X509_POLICY_NODE_delete_if(STACK_OF(X509_POLICY_NODE) *nodes, + int (*delete_if)(X509_POLICY_NODE *, void *), void *data) +{ + _STACK *sk = (_STACK *)nodes; + X509_POLICY_NODE *node; + int new_num = 0; + int i; + + for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { + node = sk_X509_POLICY_NODE_value(nodes, i); + if (!delete_if(node, data)) + sk->data[new_num++] = (char *)node; + } + sk->num = new_num; +} + +static int +is_any_policy(const ASN1_OBJECT *obj) +{ + return OBJ_obj2nid(obj) == NID_any_policy; +} + +static void +x509_policy_node_free(X509_POLICY_NODE *node) +{ + if (node == NULL) + return; + + ASN1_OBJECT_free(node->policy); + sk_ASN1_OBJECT_pop_free(node->parent_policies, ASN1_OBJECT_free); + free(node); +} + +static X509_POLICY_NODE * +x509_policy_node_new(const ASN1_OBJECT *policy) +{ + X509_POLICY_NODE *node = NULL; + + if (is_any_policy(policy)) + goto err; + if ((node = calloc(1, sizeof(*node))) == NULL) + goto err; + if ((node->policy = OBJ_dup(policy)) == NULL) + goto err; + if ((node->parent_policies = sk_ASN1_OBJECT_new_null()) == NULL) + goto err; + + return node; + + err: + x509_policy_node_free(node); + return NULL; +} + +static int +x509_policy_node_cmp(const X509_POLICY_NODE *const *a, + const X509_POLICY_NODE *const *b) +{ + return OBJ_cmp((*a)->policy, (*b)->policy); +} + +static void +x509_policy_level_free(X509_POLICY_LEVEL *level) +{ + if (level == NULL) + return; + + sk_X509_POLICY_NODE_pop_free(level->nodes, x509_policy_node_free); + free(level); +} + +static X509_POLICY_LEVEL * +x509_policy_level_new(void) +{ + X509_POLICY_LEVEL *level; + + if ((level = calloc(1, sizeof(*level))) == NULL) + goto err; + level->nodes = sk_X509_POLICY_NODE_new(x509_policy_node_cmp); + if (level->nodes == NULL) + goto err; + + return level; + + err: + x509_policy_level_free(level); + return NULL; +} + +static int +x509_policy_level_is_empty(const X509_POLICY_LEVEL *level) +{ + if (level->has_any_policy) + return 0; + + return sk_X509_POLICY_NODE_num(level->nodes) == 0; +} + +static void +x509_policy_level_clear(X509_POLICY_LEVEL *level) +{ + X509_POLICY_NODE *node; + int i; + + level->has_any_policy = 0; + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { + node = sk_X509_POLICY_NODE_value(level->nodes, i); + x509_policy_node_free(node); + } + sk_X509_POLICY_NODE_zero(level->nodes); +} + +/* + * x509_policy_level_find returns the node in |level| corresponding to |policy|, + * or NULL if none exists. Callers should ensure that level->nodes is sorted + * to avoid the cost of sorting it in sk_find(). + */ +static X509_POLICY_NODE * +x509_policy_level_find(X509_POLICY_LEVEL *level, const ASN1_OBJECT *policy) +{ + X509_POLICY_NODE node; + node.policy = (ASN1_OBJECT *)policy; + int idx; + + if ((idx = sk_X509_POLICY_NODE_find(level->nodes, &node)) < 0) + return NULL; + return sk_X509_POLICY_NODE_value(level->nodes, idx); +} + +/* + * x509_policy_level_add_nodes adds the nodes in |nodes| to |level|. It returns + * one on success and zero on error. No policy in |nodes| may already be present + * in |level|. This function modifies |nodes| to avoid making a copy, but the + * caller is still responsible for releasing |nodes| itself. + * + * This function is used to add nodes to |level| in bulk, and avoid resorting + * |level| after each addition. + */ +static int +x509_policy_level_add_nodes(X509_POLICY_LEVEL *level, + STACK_OF(X509_POLICY_NODE) *nodes) +{ + int i; + + for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++) { + X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(nodes, i); + if (!sk_X509_POLICY_NODE_push(level->nodes, node)) + return 0; + sk_X509_POLICY_NODE_set(nodes, i, NULL); + } + sk_X509_POLICY_NODE_sort(level->nodes); + + return 1; +} + +static int +policyinfo_cmp(const POLICYINFO *const *a, + const POLICYINFO *const *b) +{ + return OBJ_cmp((*a)->policyid, (*b)->policyid); +} + +static int +delete_if_not_in_policies(X509_POLICY_NODE *node, void *data) +{ + const CERTIFICATEPOLICIES *policies = data; + POLICYINFO info; + info.policyid = node->policy; + + if (sk_POLICYINFO_find(policies, &info) >= 0) + return 0; + x509_policy_node_free(node); + return 1; +} + +/* + * process_certificate_policies updates |level| to incorporate |x509|'s + * certificate policies extension. This implements steps (d) and (e) of RFC + * 5280, section 6.1.3. |level| must contain the previous level's + * "expected_policy_set" information. For all but the top-most level, this is + * the output of |process_policy_mappings|. |any_policy_allowed| specifies + * whether anyPolicy is allowed or inhibited, taking into account the exception + * for self-issued certificates. + */ +static int +process_certificate_policies(const X509 *x509, X509_POLICY_LEVEL *level, + int any_policy_allowed) +{ + STACK_OF(X509_POLICY_NODE) *new_nodes = NULL; + CERTIFICATEPOLICIES *policies; + const POLICYINFO *policy; + X509_POLICY_NODE *node; + int cert_has_any_policy, critical, i, previous_level_has_any_policy; + int ret = 0; + + policies = X509_get_ext_d2i(x509, NID_certificate_policies, &critical, + NULL); + if (policies == NULL) { + if (critical != -1) + return 0; /* Syntax error in the extension. */ + + /* RFC 5280, section 6.1.3, step (e). */ + x509_policy_level_clear(level); + return 1; + } + + /* + * certificatePolicies may not be empty. See RFC 5280, section 4.2.1.4. + * TODO(https://crbug.com/boringssl/443): Move this check into the parser. + */ + if (sk_POLICYINFO_num(policies) == 0) { + X509error(X509_R_INVALID_POLICY_EXTENSION); + goto err; + } + + (void)sk_POLICYINFO_set_cmp_func(policies, policyinfo_cmp); + sk_POLICYINFO_sort(policies); + cert_has_any_policy = 0; + for (i = 0; i < sk_POLICYINFO_num(policies); i++) { + policy = sk_POLICYINFO_value(policies, i); + if (is_any_policy(policy->policyid)) + cert_has_any_policy = 1; + if (i > 0 && + OBJ_cmp(sk_POLICYINFO_value(policies, i - 1)->policyid, + policy->policyid) == 0) { + /* + * Per RFC 5280, section 4.2.1.4, |policies| may not + * have duplicates. + */ + X509error(X509_R_INVALID_POLICY_EXTENSION); + goto err; + } + } + + /* + * This does the same thing as RFC 5280, section 6.1.3, step (d), + * though in a slighty different order. |level| currently contains + * "expected_policy_set" values of the previous level. + * See |process_policy_mappings| for details. + */ + previous_level_has_any_policy = level->has_any_policy; + + /* + * First, we handle steps (d.1.i) and (d.2). The net effect of these + * two steps is to intersect |level| with |policies|, ignoring + * anyPolicy if it is inhibited. + */ + if (!cert_has_any_policy || !any_policy_allowed) { + if (!sk_POLICYINFO_is_sorted(policies)) + goto err; + sk_X509_POLICY_NODE_delete_if(level->nodes, + delete_if_not_in_policies, policies); + level->has_any_policy = 0; + } + + /* + * Step (d.1.ii) may attach new nodes to the previous level's anyPolicy + * node. + */ + if (previous_level_has_any_policy) { + new_nodes = sk_X509_POLICY_NODE_new_null(); + if (new_nodes == NULL) + goto err; + for (i = 0; i < sk_POLICYINFO_num(policies); i++) { + policy = sk_POLICYINFO_value(policies, i); + /* + * Though we've reordered the steps slightly, |policy| + * is in |level| if and only if it would have been a + * match in step (d.1.ii). + */ + if (is_any_policy(policy->policyid)) + continue; + if (!sk_X509_POLICY_NODE_is_sorted(level->nodes)) + goto err; + if (x509_policy_level_find(level, policy->policyid) != NULL) + continue; + node = x509_policy_node_new(policy->policyid); + if (node == NULL || + !sk_X509_POLICY_NODE_push(new_nodes, node)) { + x509_policy_node_free(node); + goto err; + } + } + if (!x509_policy_level_add_nodes(level, new_nodes)) + goto err; + } + + ret = 1; + +err: + sk_X509_POLICY_NODE_pop_free(new_nodes, x509_policy_node_free); + CERTIFICATEPOLICIES_free(policies); + return ret; +} + +static int +compare_issuer_policy(const POLICY_MAPPING *const *a, + const POLICY_MAPPING *const *b) +{ + return OBJ_cmp((*a)->issuerDomainPolicy, (*b)->issuerDomainPolicy); +} + +static int +compare_subject_policy(const POLICY_MAPPING *const *a, + const POLICY_MAPPING *const *b) +{ + return OBJ_cmp((*a)->subjectDomainPolicy, (*b)->subjectDomainPolicy); +} + +static int +delete_if_mapped(X509_POLICY_NODE *node, void *data) +{ + const POLICY_MAPPINGS *mappings = data; + POLICY_MAPPING mapping; + mapping.issuerDomainPolicy = node->policy; + if (sk_POLICY_MAPPING_find(mappings, &mapping) < 0) + return 0; + x509_policy_node_free(node); + return 1; +} + +/* + * process_policy_mappings processes the policy mappings extension of |cert|, + * whose corresponding graph level is |level|. |mapping_allowed| specifies + * whether policy mapping is inhibited at this point. On success, it returns an + * |X509_POLICY_LEVEL| containing the "expected_policy_set" for |level|. On + * error, it returns NULL. This implements steps (a) and (b) of RFC 5280, + * section 6.1.4. + * + * We represent the "expected_policy_set" as an |X509_POLICY_LEVEL|. + * |has_any_policy| indicates whether there is an anyPolicy node with + * "expected_policy_set" of {anyPolicy}. If a node with policy oid P1 contains + * P2 in its "expected_policy_set", the level will contain a node of policy P2 + * with P1 in |parent_policies|. + * + * This is equivalent to the |X509_POLICY_LEVEL| that would result if the next + * certificats contained anyPolicy. |process_certificate_policies| will filter + * this result down to compute the actual level. + */ +static X509_POLICY_LEVEL * +process_policy_mappings(const X509 *cert, + X509_POLICY_LEVEL *level, + int mapping_allowed) +{ + STACK_OF(X509_POLICY_NODE) *new_nodes = NULL; + POLICY_MAPPINGS *mappings; + const ASN1_OBJECT *last_policy; + POLICY_MAPPING *mapping; + X509_POLICY_LEVEL *next = NULL; + X509_POLICY_NODE *node; + int critical, i; + int ok = 0; + + mappings = X509_get_ext_d2i(cert, NID_policy_mappings, &critical, NULL); + if (mappings == NULL && critical != -1) { + /* Syntax error in the policy mappings extension. */ + goto err; + } + + if (mappings != NULL) { + /* + * PolicyMappings may not be empty. See RFC 5280, section 4.2.1.5. + * TODO(https://crbug.com/boringssl/443): Move this check into + * the parser. + */ + if (sk_POLICY_MAPPING_num(mappings) == 0) { + X509error(X509_R_INVALID_POLICY_EXTENSION); + goto err; + } + + /* RFC 5280, section 6.1.4, step (a). */ + for (i = 0; i < sk_POLICY_MAPPING_num(mappings); i++) { + mapping = sk_POLICY_MAPPING_value(mappings, i); + if (is_any_policy(mapping->issuerDomainPolicy) || + is_any_policy(mapping->subjectDomainPolicy)) + goto err; + } + + /* Sort to group by issuerDomainPolicy. */ + (void)sk_POLICY_MAPPING_set_cmp_func(mappings, + compare_issuer_policy); + sk_POLICY_MAPPING_sort(mappings); + + if (mapping_allowed) { + /* + * Mark nodes as mapped, and add any nodes to |level| + * which may be needed as part of RFC 5280, + * section 6.1.4, step (b.1). + */ + new_nodes = sk_X509_POLICY_NODE_new_null(); + if (new_nodes == NULL) + goto err; + last_policy = NULL; + for (i = 0; i < sk_POLICY_MAPPING_num(mappings); i++) { + mapping = sk_POLICY_MAPPING_value(mappings, i); + /* + * There may be multiple mappings with the same + * |issuerDomainPolicy|. + */ + if (last_policy != NULL && + OBJ_cmp(mapping->issuerDomainPolicy, + last_policy) == 0) + continue; + last_policy = mapping->issuerDomainPolicy; + + if (!sk_X509_POLICY_NODE_is_sorted(level->nodes)) + goto err; + node = x509_policy_level_find(level, + mapping->issuerDomainPolicy); + if (node == NULL) { + if (!level->has_any_policy) + continue; + node = x509_policy_node_new( + mapping->issuerDomainPolicy); + if (node == NULL || + !sk_X509_POLICY_NODE_push(new_nodes, + node)) { + x509_policy_node_free(node); + goto err; + } + } + node->mapped = 1; + } + if (!x509_policy_level_add_nodes(level, new_nodes)) + goto err; + } else { + /* + * RFC 5280, section 6.1.4, step (b.2). If mapping is + * inhibited, delete all mapped nodes. + */ + if (!sk_POLICY_MAPPING_is_sorted(mappings)) + goto err; + sk_X509_POLICY_NODE_delete_if(level->nodes, + delete_if_mapped, mappings); + sk_POLICY_MAPPING_pop_free(mappings, + POLICY_MAPPING_free); + mappings = NULL; + } + } + + /* + * If a node was not mapped, it retains the original "explicit_policy_set" + * value, itself. Add those to |mappings|. + */ + if (mappings == NULL) { + mappings = sk_POLICY_MAPPING_new_null(); + if (mappings == NULL) + goto err; + } + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) { + node = sk_X509_POLICY_NODE_value(level->nodes, i); + if (!node->mapped) { + mapping = POLICY_MAPPING_new(); + if (mapping == NULL) + goto err; + mapping->issuerDomainPolicy = OBJ_dup(node->policy); + mapping->subjectDomainPolicy = OBJ_dup(node->policy); + if (mapping->issuerDomainPolicy == NULL || + mapping->subjectDomainPolicy == NULL || + !sk_POLICY_MAPPING_push(mappings, mapping)) { + POLICY_MAPPING_free(mapping); + goto err; + } + } + } + + /* Sort to group by subjectDomainPolicy. */ + (void)sk_POLICY_MAPPING_set_cmp_func(mappings, compare_subject_policy); + sk_POLICY_MAPPING_sort(mappings); + + /* Convert |mappings| to our "expected_policy_set" representation. */ + next = x509_policy_level_new(); + if (next == NULL) + goto err; + next->has_any_policy = level->has_any_policy; + + X509_POLICY_NODE *last_node = NULL; + for (i = 0; i < sk_POLICY_MAPPING_num(mappings); i++) { + mapping = sk_POLICY_MAPPING_value(mappings, i); + /* + * Skip mappings where |issuerDomainPolicy| does not appear in + * the graph. + */ + if (!level->has_any_policy) { + if (!sk_X509_POLICY_NODE_is_sorted(level->nodes)) + goto err; + if (x509_policy_level_find(level, + mapping->issuerDomainPolicy) == NULL) + continue; + } + + if (last_node == NULL || + OBJ_cmp(last_node->policy, mapping->subjectDomainPolicy) != + 0) { + last_node = x509_policy_node_new( + mapping->subjectDomainPolicy); + if (last_node == NULL || + !sk_X509_POLICY_NODE_push(next->nodes, last_node)) { + x509_policy_node_free(last_node); + goto err; + } + } + + if (!sk_ASN1_OBJECT_push(last_node->parent_policies, + mapping->issuerDomainPolicy)) + goto err; + mapping->issuerDomainPolicy = NULL; + } + + sk_X509_POLICY_NODE_sort(next->nodes); + ok = 1; + +err: + if (!ok) { + x509_policy_level_free(next); + next = NULL; + } + + sk_POLICY_MAPPING_pop_free(mappings, POLICY_MAPPING_free); + sk_X509_POLICY_NODE_pop_free(new_nodes, x509_policy_node_free); + return next; +} + +/* + * apply_skip_certs, if |skip_certs| is non-NULL, sets |*value| to the minimum + * of its current value and |skip_certs|. It returns one on success and zero if + * |skip_certs| is negative. + */ +static int +apply_skip_certs(const ASN1_INTEGER *skip_certs, size_t *value) +{ + if (skip_certs == NULL) + return 1; + + /* TODO(https://crbug.com/boringssl/443): Move this check into the parser. */ + if (skip_certs->type & V_ASN1_NEG) { + X509error(X509_R_INVALID_POLICY_EXTENSION); + return 0; + } + + /* If |skip_certs| does not fit in |uint64_t|, it must exceed |*value|. */ + uint64_t u64; + if (ASN1_INTEGER_get_uint64(&u64, skip_certs) && u64 < *value) + *value = (size_t)u64; + ERR_clear_error(); + return 1; +} + +/* + * process_policy_constraints updates |*explicit_policy|, |*policy_mapping|, and + * |*inhibit_any_policy| according to |x509|'s policy constraints and inhibit + * anyPolicy extensions. It returns one on success and zero on error. This + * implements steps (i) and (j) of RFC 5280, section 6.1.4. + */ +static int +process_policy_constraints(const X509 *x509, size_t *explicit_policy, + size_t *policy_mapping, + size_t *inhibit_any_policy) +{ + ASN1_INTEGER *inhibit_any_policy_ext; + POLICY_CONSTRAINTS *constraints; + int critical; + int ok = 0; + + constraints = X509_get_ext_d2i(x509, NID_policy_constraints, &critical, + NULL); + if (constraints == NULL && critical != -1) + return 0; + if (constraints != NULL) { + if (constraints->requireExplicitPolicy == NULL && + constraints->inhibitPolicyMapping == NULL) { + /* + * Per RFC 5280, section 4.2.1.11, at least one of the + * fields must be + */ + X509error(X509_R_INVALID_POLICY_EXTENSION); + POLICY_CONSTRAINTS_free(constraints); + return 0; + } + ok = apply_skip_certs(constraints->requireExplicitPolicy, + explicit_policy) && + apply_skip_certs(constraints->inhibitPolicyMapping, + policy_mapping); + POLICY_CONSTRAINTS_free(constraints); + if (!ok) + return 0; + } + + inhibit_any_policy_ext = X509_get_ext_d2i(x509, NID_inhibit_any_policy, + &critical, NULL); + if (inhibit_any_policy_ext == NULL && critical != -1) + return 0; + ok = apply_skip_certs(inhibit_any_policy_ext, inhibit_any_policy); + ASN1_INTEGER_free(inhibit_any_policy_ext); + return ok; +} + +/* + * has_explicit_policy returns one if the set of authority-space policy OIDs + * |levels| has some non-empty intersection with |user_policies|, and zero + * otherwise. This mirrors the logic in RFC 5280, section 6.1.5, step (g). This + * function modifies |levels| and should only be called at the end of policy + * evaluation. + */ +static int +has_explicit_policy(STACK_OF(X509_POLICY_LEVEL) *levels, + const STACK_OF(ASN1_OBJECT) *user_policies) +{ + X509_POLICY_LEVEL *level, *prev; + X509_POLICY_NODE *node, *parent; + int num_levels, user_has_any_policy; + int i, j, k; + + if (!sk_ASN1_OBJECT_is_sorted(user_policies)) + return 0; + + /* Step (g.i). If the policy graph is empty, the intersection is empty. */ + num_levels = sk_X509_POLICY_LEVEL_num(levels); + level = sk_X509_POLICY_LEVEL_value(levels, num_levels - 1); + if (x509_policy_level_is_empty(level)) + return 0; + + /* + * If |user_policies| is empty, we interpret it as having a single + * anyPolicy value. The caller may also have supplied anyPolicy + * explicitly. + */ + user_has_any_policy = sk_ASN1_OBJECT_num(user_policies) <= 0; + for (i = 0; i < sk_ASN1_OBJECT_num(user_policies); i++) { + if (is_any_policy(sk_ASN1_OBJECT_value(user_policies, i))) { + user_has_any_policy = 1; + break; + } + } + + /* + * Step (g.ii). If the policy graph is not empty and the user set + * contains anyPolicy, the intersection is the entire (non-empty) graph. + */ + if (user_has_any_policy) + return 1; + + /* + * Step (g.iii) does not delete anyPolicy nodes, so if the graph has + * anyPolicy, some explicit policy will survive. The actual intersection + * may synthesize some nodes in step (g.iii.3), but we do not return the + * policy list itself, so we skip actually computing this. + */ + if (level->has_any_policy) + return 1; + + /* + * We defer pruning the tree, so as we look for nodes with parent + * anyPolicy, step (g.iii.1), we must limit to nodes reachable from the + * bottommost level. Start by marking each of those nodes as reachable. + */ + for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) + sk_X509_POLICY_NODE_value(level->nodes, i)->reachable = 1; + + for (i = num_levels - 1; i >= 0; i--) { + level = sk_X509_POLICY_LEVEL_value(levels, i); + for (j = 0; j < sk_X509_POLICY_NODE_num(level->nodes); j++) { + node = sk_X509_POLICY_NODE_value(level->nodes, j); + if (!node->reachable) + continue; + if (sk_ASN1_OBJECT_num(node->parent_policies) == 0) { + /* + * |node|'s parent is anyPolicy and is part of + * "valid_policy_node_set". If it exists in + * |user_policies|, the intersection is + * non-empty and we * can return immediately. + */ + if (sk_ASN1_OBJECT_find(user_policies, + node->policy) >= 0) + return 1; + } else if (i > 0) { + int num_parent_policies = + sk_ASN1_OBJECT_num(node->parent_policies); + /* + * |node|'s parents are concrete policies. Mark + * the parents reachable, to be inspected by the + * next loop iteration. + */ + prev = sk_X509_POLICY_LEVEL_value(levels, i - 1); + for (k = 0; k < num_parent_policies; k++) { + if (!sk_X509_POLICY_NODE_is_sorted(prev->nodes)) + return 0; + parent = x509_policy_level_find(prev, + sk_ASN1_OBJECT_value(node->parent_policies, + k)); + if (parent != NULL) + parent->reachable = 1; + } + } + } + } + + return 0; +} + +static int +asn1_object_cmp(const ASN1_OBJECT *const *a, const ASN1_OBJECT *const *b) +{ + return OBJ_cmp(*a, *b); +} + +int +X509_policy_check(const STACK_OF(X509) *certs, + const STACK_OF(ASN1_OBJECT) *user_policies, + unsigned long flags, X509 **out_current_cert) +{ + *out_current_cert = NULL; + int ret = X509_V_ERR_OUT_OF_MEM; + X509 *cert; + X509_POLICY_LEVEL *level = NULL; + X509_POLICY_LEVEL *current_level; + STACK_OF(X509_POLICY_LEVEL) *levels = NULL; + STACK_OF(ASN1_OBJECT) *user_policies_sorted = NULL; + int num_certs = sk_X509_num(certs); + int is_self_issued, any_policy_allowed; + int i; + + /* Skip policy checking if the chain is just the trust anchor. */ + if (num_certs <= 1) + return X509_V_OK; + + /* See RFC 5280, section 6.1.2, steps (d) through (f). */ + size_t explicit_policy = + (flags & X509_V_FLAG_EXPLICIT_POLICY) ? 0 : num_certs + 1; + size_t inhibit_any_policy = + (flags & X509_V_FLAG_INHIBIT_ANY) ? 0 : num_certs + 1; + size_t policy_mapping = + (flags & X509_V_FLAG_INHIBIT_MAP) ? 0 : num_certs + 1; + + levels = sk_X509_POLICY_LEVEL_new_null(); + if (levels == NULL) + goto err; + + for (i = num_certs - 2; i >= 0; i--) { + cert = sk_X509_value(certs, i); + if (!x509v3_cache_extensions(cert)) + goto err; + is_self_issued = (cert->ex_flags & EXFLAG_SI) != 0; + + if (level == NULL) { + if (i != num_certs - 2) + goto err; + level = x509_policy_level_new(); + if (level == NULL) + goto err; + level->has_any_policy = 1; + } + + /* + * RFC 5280, section 6.1.3, steps (d) and (e). |any_policy_allowed| + * is computed as in step (d.2). + */ + any_policy_allowed = + inhibit_any_policy > 0 || (i > 0 && is_self_issued); + if (!process_certificate_policies(cert, level, + any_policy_allowed)) { + ret = X509_V_ERR_INVALID_POLICY_EXTENSION; + *out_current_cert = cert; + goto err; + } + + /* RFC 5280, section 6.1.3, step (f). */ + if (explicit_policy == 0 && x509_policy_level_is_empty(level)) { + ret = X509_V_ERR_NO_EXPLICIT_POLICY; + goto err; + } + + /* Insert into the list. */ + if (!sk_X509_POLICY_LEVEL_push(levels, level)) + goto err; + current_level = level; + level = NULL; + + /* + * If this is not the leaf certificate, we go to section 6.1.4. + * If it is the leaf certificate, we go to section 6.1.5 instead. + */ + if (i != 0) { + /* RFC 5280, section 6.1.4, steps (a) and (b). */ + level = process_policy_mappings(cert, current_level, + policy_mapping > 0); + if (level == NULL) { + ret = X509_V_ERR_INVALID_POLICY_EXTENSION; + *out_current_cert = cert; + goto err; + } + } + + /* + * RFC 5280, section 6.1.4, step (h-j) for non-leaves, and + * section 6.1.5, step (a-b) for leaves. In the leaf case, + * RFC 5280 says only to update |explicit_policy|, but + * |policy_mapping| and |inhibit_any_policy| are no + * longer read at this point, so we use the same process. + */ + if (i == 0 || !is_self_issued) { + if (explicit_policy > 0) + explicit_policy--; + if (policy_mapping > 0) + policy_mapping--; + if (inhibit_any_policy > 0) + inhibit_any_policy--; + } + if (!process_policy_constraints(cert, &explicit_policy, + &policy_mapping, &inhibit_any_policy)) { + ret = X509_V_ERR_INVALID_POLICY_EXTENSION; + *out_current_cert = cert; + goto err; + } + } + + /* + * RFC 5280, section 6.1.5, step (g). We do not output the policy set, + * so it is only necessary to check if the user-constrained-policy-set + * is not empty. + */ + if (explicit_policy == 0) { + /* + * Build a sorted copy of |user_policies| for more efficient + * lookup. + */ + if (user_policies != NULL) { + user_policies_sorted = sk_ASN1_OBJECT_dup( + user_policies); + if (user_policies_sorted == NULL) + goto err; + (void)sk_ASN1_OBJECT_set_cmp_func(user_policies_sorted, + asn1_object_cmp); + sk_ASN1_OBJECT_sort(user_policies_sorted); + } + + if (!has_explicit_policy(levels, user_policies_sorted)) { + ret = X509_V_ERR_NO_EXPLICIT_POLICY; + goto err; + } + } + + ret = X509_V_OK; + +err: + x509_policy_level_free(level); + /* + * |user_policies_sorted|'s contents are owned by |user_policies|, so + * we do not use |sk_ASN1_OBJECT_pop_free|. + */ + sk_ASN1_OBJECT_free(user_policies_sorted); + sk_X509_POLICY_LEVEL_pop_free(levels, x509_policy_level_free); + return ret; +} diff --git a/crypto/x509/x509_prn.c b/crypto/x509/x509_prn.c new file mode 100644 index 0000000..3bf7c80 --- /dev/null +++ b/crypto/x509/x509_prn.c @@ -0,0 +1,231 @@ +/* $OpenBSD: x509_prn.c,v 1.6 2023/05/08 05:30:38 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* X509 v3 extension utilities */ + +#include + +#include +#include + +#include "x509_local.h" + +/* Extension printing routines */ + +static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent, int supported); + +/* Print out a name+value stack */ + +void +X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml) +{ + int i; + CONF_VALUE *nval; + + if (!val) + return; + if (!ml || !sk_CONF_VALUE_num(val)) { + BIO_printf(out, "%*s", indent, ""); + if (!sk_CONF_VALUE_num(val)) + BIO_puts(out, "\n"); + } + for (i = 0; i < sk_CONF_VALUE_num(val); i++) { + if (ml) + BIO_printf(out, "%*s", indent, ""); + else if (i > 0) BIO_printf(out, ", "); + nval = sk_CONF_VALUE_value(val, i); + if (!nval->name) + BIO_puts(out, nval->value); + else if (!nval->value) + BIO_puts(out, nval->name); + else + BIO_printf(out, "%s:%s", nval->name, nval->value); + if (ml) + BIO_puts(out, "\n"); + } +} +LCRYPTO_ALIAS(X509V3_EXT_val_prn); + +/* Main routine: print out a general extension */ + +int +X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent) +{ + void *ext_str = NULL; + char *value = NULL; + const unsigned char *p; + const X509V3_EXT_METHOD *method; + STACK_OF(CONF_VALUE) *nval = NULL; + int ok = 1; + + if (!(method = X509V3_EXT_get(ext))) + return unknown_ext_print(out, ext, flag, indent, 0); + p = ext->value->data; + if (method->it) + ext_str = ASN1_item_d2i(NULL, &p, ext->value->length, + method->it); + else + ext_str = method->d2i(NULL, &p, ext->value->length); + + if (!ext_str) + return unknown_ext_print(out, ext, flag, indent, 1); + + if (method->i2s) { + if (!(value = method->i2s(method, ext_str))) { + ok = 0; + goto err; + } + BIO_printf(out, "%*s%s", indent, "", value); + } else if (method->i2v) { + if (!(nval = method->i2v(method, ext_str, NULL))) { + ok = 0; + goto err; + } + X509V3_EXT_val_prn(out, nval, indent, + method->ext_flags & X509V3_EXT_MULTILINE); + } else if (method->i2r) { + if (!method->i2r(method, ext_str, out, indent)) + ok = 0; + } else + ok = 0; + +err: + sk_CONF_VALUE_pop_free(nval, X509V3_conf_free); + free(value); + if (method->it) + ASN1_item_free(ext_str, method->it); + else + method->ext_free(ext_str); + return ok; +} +LCRYPTO_ALIAS(X509V3_EXT_print); + +int +X509V3_extensions_print(BIO *bp, const char *title, + const STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent) +{ + int i, j; + + if (sk_X509_EXTENSION_num(exts) <= 0) + return 1; + + if (title) { + BIO_printf(bp, "%*s%s:\n",indent, "", title); + indent += 4; + } + + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { + ASN1_OBJECT *obj; + X509_EXTENSION *ex; + ex = sk_X509_EXTENSION_value(exts, i); + if (indent && BIO_printf(bp, "%*s",indent, "") <= 0) + return 0; + obj = X509_EXTENSION_get_object(ex); + i2a_ASN1_OBJECT(bp, obj); + j = X509_EXTENSION_get_critical(ex); + if (BIO_printf(bp, ":%s\n", j ? " critical" : "") <= 0) + return 0; + if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) { + BIO_printf(bp, "%*s", indent + 4, ""); + ASN1_STRING_print(bp, ex->value); + } + if (BIO_write(bp, "\n",1) <= 0) + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509V3_extensions_print); + +static int +unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, + int indent, int supported) +{ + switch (flag & X509V3_EXT_UNKNOWN_MASK) { + case X509V3_EXT_DEFAULT: + return 0; + case X509V3_EXT_ERROR_UNKNOWN: + if (supported) + BIO_printf(out, "%*s", indent, ""); + else + BIO_printf(out, "%*s", indent, ""); + return 1; + case X509V3_EXT_PARSE_UNKNOWN: + return ASN1_parse_dump(out, + ext->value->data, ext->value->length, indent, -1); + case X509V3_EXT_DUMP_UNKNOWN: + return BIO_dump_indent(out, (char *)ext->value->data, + ext->value->length, indent); + default: + return 1; + } +} + + +int +X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent) +{ + BIO *bio_tmp; + int ret; + + if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) + return 0; + ret = X509V3_EXT_print(bio_tmp, ext, flag, indent); + BIO_free(bio_tmp); + return ret; +} +LCRYPTO_ALIAS(X509V3_EXT_print_fp); diff --git a/crypto/x509/x509_purp.c b/crypto/x509/x509_purp.c new file mode 100644 index 0000000..0c92dfb --- /dev/null +++ b/crypto/x509/x509_purp.c @@ -0,0 +1,1077 @@ +/* $OpenBSD: x509_purp.c,v 1.29 2023/08/18 08:42:41 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include + +#include +#include +#include + +#include "x509_internal.h" +#include "x509_local.h" + +#define V1_ROOT (EXFLAG_V1|EXFLAG_SS) +#define ku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage))) +#define xku_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage))) +#define ns_reject(x, usage) \ + (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage))) + +static int check_ssl_ca(const X509 *x); +static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int purpose_smime(const X509 *x, int ca); +static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, + int ca); +static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca); +static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca); + +static int xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b); +static void xptable_free(X509_PURPOSE *p); + +static X509_PURPOSE xstandard[] = { + { + .purpose = X509_PURPOSE_SSL_CLIENT, + .trust = X509_TRUST_SSL_CLIENT, + .check_purpose = check_purpose_ssl_client, + .name = "SSL client", + .sname = "sslclient", + }, + { + .purpose = X509_PURPOSE_SSL_SERVER, + .trust = X509_TRUST_SSL_SERVER, + .check_purpose = check_purpose_ssl_server, + .name = "SSL server", + .sname = "sslserver", + }, + { + .purpose = X509_PURPOSE_NS_SSL_SERVER, + .trust = X509_TRUST_SSL_SERVER, + .check_purpose = check_purpose_ns_ssl_server, + .name = "Netscape SSL server", + .sname = "nssslserver", + }, + { + .purpose = X509_PURPOSE_SMIME_SIGN, + .trust = X509_TRUST_EMAIL, + .check_purpose = check_purpose_smime_sign, + .name = "S/MIME signing", + .sname = "smimesign", + }, + { + .purpose = X509_PURPOSE_SMIME_ENCRYPT, + .trust = X509_TRUST_EMAIL, + .check_purpose = check_purpose_smime_encrypt, + .name = "S/MIME encryption", + .sname = "smimeencrypt", + }, + { + .purpose = X509_PURPOSE_CRL_SIGN, + .trust = X509_TRUST_COMPAT, + .check_purpose = check_purpose_crl_sign, + .name = "CRL signing", + .sname = "crlsign", + }, + { + .purpose = X509_PURPOSE_ANY, + .trust = X509_TRUST_DEFAULT, + .check_purpose = no_check, + .name = "Any Purpose", + .sname = "any", + }, + { + .purpose = X509_PURPOSE_OCSP_HELPER, + .trust = X509_TRUST_COMPAT, + .check_purpose = ocsp_helper, + .name = "OCSP helper", + .sname = "ocsphelper", + }, + { + .purpose = X509_PURPOSE_TIMESTAMP_SIGN, + .trust = X509_TRUST_TSA, + .check_purpose = check_purpose_timestamp_sign, + .name = "Time Stamp signing", + .sname = "timestampsign", + }, +}; + +#define X509_PURPOSE_COUNT (sizeof(xstandard) / sizeof(xstandard[0])) + +static STACK_OF(X509_PURPOSE) *xptable = NULL; + +static int +xp_cmp(const X509_PURPOSE * const *a, const X509_PURPOSE * const *b) +{ + return (*a)->purpose - (*b)->purpose; +} + +/* As much as I'd like to make X509_check_purpose use a "const" X509* + * I really can't because it does recalculate hashes and do other non-const + * things. */ +int +X509_check_purpose(X509 *x, int id, int ca) +{ + int idx; + const X509_PURPOSE *pt; + + if (!x509v3_cache_extensions(x)) + return -1; + + if (id == -1) + return 1; + idx = X509_PURPOSE_get_by_id(id); + if (idx == -1) + return -1; + pt = X509_PURPOSE_get0(idx); + return pt->check_purpose(pt, x, ca); +} +LCRYPTO_ALIAS(X509_check_purpose); + +int +X509_PURPOSE_set(int *p, int purpose) +{ + if (X509_PURPOSE_get_by_id(purpose) == -1) { + X509V3error(X509V3_R_INVALID_PURPOSE); + return 0; + } + *p = purpose; + return 1; +} +LCRYPTO_ALIAS(X509_PURPOSE_set); + +int +X509_PURPOSE_get_count(void) +{ + if (!xptable) + return X509_PURPOSE_COUNT; + return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT; +} +LCRYPTO_ALIAS(X509_PURPOSE_get_count); + +X509_PURPOSE * +X509_PURPOSE_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_PURPOSE_COUNT) + return xstandard + idx; + return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT); +} +LCRYPTO_ALIAS(X509_PURPOSE_get0); + +int +X509_PURPOSE_get_by_sname(const char *sname) +{ + int i; + X509_PURPOSE *xptmp; + + for (i = 0; i < X509_PURPOSE_get_count(); i++) { + xptmp = X509_PURPOSE_get0(i); + if (!strcmp(xptmp->sname, sname)) + return i; + } + return -1; +} +LCRYPTO_ALIAS(X509_PURPOSE_get_by_sname); + +int +X509_PURPOSE_get_by_id(int purpose) +{ + X509_PURPOSE tmp; + int idx; + + if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX)) + return purpose - X509_PURPOSE_MIN; + tmp.purpose = purpose; + if (!xptable) + return -1; + idx = sk_X509_PURPOSE_find(xptable, &tmp); + if (idx == -1) + return -1; + return idx + X509_PURPOSE_COUNT; +} +LCRYPTO_ALIAS(X509_PURPOSE_get_by_id); + +int +X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(const X509_PURPOSE *, const X509 *, int), const char *name, + const char *sname, void *arg) +{ + int idx; + X509_PURPOSE *ptmp; + char *name_dup, *sname_dup; + + name_dup = sname_dup = NULL; + + if (name == NULL || sname == NULL) { + X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); + return 0; + } + + /* This is set according to what we change: application can't set it */ + flags &= ~X509_PURPOSE_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_PURPOSE_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_PURPOSE_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if ((ptmp = malloc(sizeof(X509_PURPOSE))) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return 0; + } + ptmp->flags = X509_PURPOSE_DYNAMIC; + } else + ptmp = X509_PURPOSE_get0(idx); + + if ((name_dup = strdup(name)) == NULL) + goto err; + if ((sname_dup = strdup(sname)) == NULL) + goto err; + + /* free existing name if dynamic */ + if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) { + free(ptmp->name); + free(ptmp->sname); + } + /* dup supplied name */ + ptmp->name = name_dup; + ptmp->sname = sname_dup; + /* Keep the dynamic flag of existing entry */ + ptmp->flags &= X509_PURPOSE_DYNAMIC; + /* Set all other flags */ + ptmp->flags |= flags; + + ptmp->purpose = id; + ptmp->trust = trust; + ptmp->check_purpose = ck; + ptmp->usr_data = arg; + + /* If its a new entry manage the dynamic table */ + if (idx == -1) { + if (xptable == NULL && + (xptable = sk_X509_PURPOSE_new(xp_cmp)) == NULL) + goto err; + if (sk_X509_PURPOSE_push(xptable, ptmp) == 0) + goto err; + } + return 1; + +err: + free(name_dup); + free(sname_dup); + if (idx == -1) + free(ptmp); + X509V3error(ERR_R_MALLOC_FAILURE); + return 0; +} +LCRYPTO_ALIAS(X509_PURPOSE_add); + +static void +xptable_free(X509_PURPOSE *p) +{ + if (!p) + return; + if (p->flags & X509_PURPOSE_DYNAMIC) { + if (p->flags & X509_PURPOSE_DYNAMIC_NAME) { + free(p->name); + free(p->sname); + } + free(p); + } +} + +void +X509_PURPOSE_cleanup(void) +{ + sk_X509_PURPOSE_pop_free(xptable, xptable_free); + xptable = NULL; +} +LCRYPTO_ALIAS(X509_PURPOSE_cleanup); + +int +X509_PURPOSE_get_id(const X509_PURPOSE *xp) +{ + return xp->purpose; +} +LCRYPTO_ALIAS(X509_PURPOSE_get_id); + +char * +X509_PURPOSE_get0_name(const X509_PURPOSE *xp) +{ + return xp->name; +} +LCRYPTO_ALIAS(X509_PURPOSE_get0_name); + +char * +X509_PURPOSE_get0_sname(const X509_PURPOSE *xp) +{ + return xp->sname; +} +LCRYPTO_ALIAS(X509_PURPOSE_get0_sname); + +int +X509_PURPOSE_get_trust(const X509_PURPOSE *xp) +{ + return xp->trust; +} +LCRYPTO_ALIAS(X509_PURPOSE_get_trust); + +static int +nid_cmp(const int *a, const int *b) +{ + return *a - *b; +} + +static int nid_cmp_BSEARCH_CMP_FN(const void *, const void *); +static int nid_cmp(int const *, int const *); +static int *OBJ_bsearch_nid(int *key, int const *base, int num); + +static int +nid_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) +{ + int const *a = a_; + int const *b = b_; + return nid_cmp(a, b); +} + +static int * +OBJ_bsearch_nid(int *key, int const *base, int num) +{ + return (int *)OBJ_bsearch_(key, base, num, sizeof(int), + nid_cmp_BSEARCH_CMP_FN); +} + +int +X509_supported_extension(X509_EXTENSION *ex) +{ + /* This table is a list of the NIDs of supported extensions: + * that is those which are used by the verify process. If + * an extension is critical and doesn't appear in this list + * then the verify process will normally reject the certificate. + * The list must be kept in numerical order because it will be + * searched using bsearch. + */ + + static const int supported_nids[] = { + NID_netscape_cert_type, /* 71 */ + NID_key_usage, /* 83 */ + NID_subject_alt_name, /* 85 */ + NID_basic_constraints, /* 87 */ + NID_certificate_policies, /* 89 */ + NID_ext_key_usage, /* 126 */ +#ifndef OPENSSL_NO_RFC3779 + NID_sbgp_ipAddrBlock, /* 290 */ + NID_sbgp_autonomousSysNum, /* 291 */ +#endif + NID_policy_constraints, /* 401 */ + NID_name_constraints, /* 666 */ + NID_policy_mappings, /* 747 */ + NID_inhibit_any_policy /* 748 */ + }; + + int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex)); + + if (ex_nid == NID_undef) + return 0; + + if (OBJ_bsearch_nid(&ex_nid, supported_nids, + sizeof(supported_nids) / sizeof(int))) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_supported_extension); + +static void +setup_dp(X509 *x, DIST_POINT *dp) +{ + X509_NAME *iname = NULL; + int i; + + if (dp->reasons) { + if (dp->reasons->length > 0) + dp->dp_reasons = dp->reasons->data[0]; + if (dp->reasons->length > 1) + dp->dp_reasons |= (dp->reasons->data[1] << 8); + dp->dp_reasons &= CRLDP_ALL_REASONS; + } else + dp->dp_reasons = CRLDP_ALL_REASONS; + if (!dp->distpoint || (dp->distpoint->type != 1)) + return; + for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) { + GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i); + if (gen->type == GEN_DIRNAME) { + iname = gen->d.directoryName; + break; + } + } + if (!iname) + iname = X509_get_issuer_name(x); + + DIST_POINT_set_dpname(dp->distpoint, iname); +} + +static void +setup_crldp(X509 *x) +{ + int i; + + x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &i, NULL); + if (x->crldp == NULL && i != -1) { + x->ex_flags |= EXFLAG_INVALID; + return; + } + + for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) + setup_dp(x, sk_DIST_POINT_value(x->crldp, i)); +} + +static int +x509_extension_oid_cmp(const X509_EXTENSION *const *a, + const X509_EXTENSION *const *b) +{ + return OBJ_cmp((*a)->object, (*b)->object); +} + +static int +x509_extension_oids_are_unique(X509 *x509) +{ + STACK_OF(X509_EXTENSION) *exts = NULL; + const X509_EXTENSION *prev_ext, *curr_ext; + int i; + int ret = 0; + + if (X509_get_ext_count(x509) <= 1) + goto done; + + if ((exts = sk_X509_EXTENSION_dup(x509->cert_info->extensions)) == NULL) + goto err; + + (void)sk_X509_EXTENSION_set_cmp_func(exts, x509_extension_oid_cmp); + sk_X509_EXTENSION_sort(exts); + + prev_ext = sk_X509_EXTENSION_value(exts, 0); + for (i = 1; i < sk_X509_EXTENSION_num(exts); i++) { + curr_ext = sk_X509_EXTENSION_value(exts, i); + if (x509_extension_oid_cmp(&prev_ext, &curr_ext) == 0) + goto err; + prev_ext = curr_ext; + } + + done: + ret = 1; + + err: + sk_X509_EXTENSION_free(exts); + + return ret; +} + +static void +x509v3_cache_extensions_internal(X509 *x) +{ + BASIC_CONSTRAINTS *bs; + ASN1_BIT_STRING *usage; + ASN1_BIT_STRING *ns; + EXTENDED_KEY_USAGE *extusage; + X509_EXTENSION *ex; + long version; + int i; + + if (x->ex_flags & EXFLAG_SET) + return; + + if (!X509_digest(x, X509_CERT_HASH_EVP, x->hash, NULL)) + x->ex_flags |= EXFLAG_INVALID; + + version = X509_get_version(x); + if (version < 0 || version > 2) + x->ex_flags |= EXFLAG_INVALID; + if (version == 0) { + x->ex_flags |= EXFLAG_V1; + /* UIDs may only appear in v2 or v3 certs */ + if (x->cert_info->issuerUID != NULL || + x->cert_info->subjectUID != NULL) + x->ex_flags |= EXFLAG_INVALID; + } + if (version != 2 && X509_get_ext_count(x) != 0) + x->ex_flags |= EXFLAG_INVALID; + + /* Handle basic constraints */ + if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, &i, NULL))) { + if (bs->ca) + x->ex_flags |= EXFLAG_CA; + if (bs->pathlen) { + if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) || + !bs->ca) { + x->ex_flags |= EXFLAG_INVALID; + x->ex_pathlen = 0; + } else + x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); + } else + x->ex_pathlen = -1; + BASIC_CONSTRAINTS_free(bs); + x->ex_flags |= EXFLAG_BCONS; + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + + /* Handle key usage */ + if ((usage = X509_get_ext_d2i(x, NID_key_usage, &i, NULL))) { + if (usage->length > 0) { + x->ex_kusage = usage->data[0]; + if (usage->length > 1) + x->ex_kusage |= usage->data[1] << 8; + } else + x->ex_kusage = 0; + x->ex_flags |= EXFLAG_KUSAGE; + ASN1_BIT_STRING_free(usage); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + + x->ex_xkusage = 0; + if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, &i, NULL))) { + x->ex_flags |= EXFLAG_XKUSAGE; + for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { + switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { + case NID_server_auth: + x->ex_xkusage |= XKU_SSL_SERVER; + break; + + case NID_client_auth: + x->ex_xkusage |= XKU_SSL_CLIENT; + break; + + case NID_email_protect: + x->ex_xkusage |= XKU_SMIME; + break; + + case NID_code_sign: + x->ex_xkusage |= XKU_CODE_SIGN; + break; + + case NID_ms_sgc: + case NID_ns_sgc: + x->ex_xkusage |= XKU_SGC; + break; + + case NID_OCSP_sign: + x->ex_xkusage |= XKU_OCSP_SIGN; + break; + + case NID_time_stamp: + x->ex_xkusage |= XKU_TIMESTAMP; + break; + + case NID_dvcs: + x->ex_xkusage |= XKU_DVCS; + break; + + case NID_anyExtendedKeyUsage: + x->ex_xkusage |= XKU_ANYEKU; + break; + } + } + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + + if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, &i, NULL))) { + if (ns->length > 0) + x->ex_nscert = ns->data[0]; + else + x->ex_nscert = 0; + x->ex_flags |= EXFLAG_NSCERT; + ASN1_BIT_STRING_free(ns); + } else if (i != -1) { + x->ex_flags |= EXFLAG_INVALID; + } + + x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, &i, NULL); + if (x->skid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &i, NULL); + if (x->akid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + + /* Does subject name match issuer? */ + if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { + x->ex_flags |= EXFLAG_SI; + /* If SKID matches AKID also indicate self signed. */ + if (X509_check_akid(x, x->akid) == X509_V_OK && + !ku_reject(x, KU_KEY_CERT_SIGN)) + x->ex_flags |= EXFLAG_SS; + } + + 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 && (i != -1)) + x->ex_flags |= EXFLAG_INVALID; + setup_crldp(x); + +#ifndef OPENSSL_NO_RFC3779 + x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &i, NULL); + if (x->rfc3779_addr == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + if (!X509v3_addr_is_canonical(x->rfc3779_addr)) + x->ex_flags |= EXFLAG_INVALID; + x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &i, NULL); + if (x->rfc3779_asid == NULL && i != -1) + x->ex_flags |= EXFLAG_INVALID; + if (!X509v3_asid_is_canonical(x->rfc3779_asid)) + x->ex_flags |= EXFLAG_INVALID; +#endif + + for (i = 0; i < X509_get_ext_count(x); i++) { + ex = X509_get_ext(x, i); + if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == + NID_freshest_crl) + x->ex_flags |= EXFLAG_FRESHEST; + if (!X509_EXTENSION_get_critical(ex)) + continue; + if (!X509_supported_extension(ex)) { + x->ex_flags |= EXFLAG_CRITICAL; + break; + } + } + + if (!x509_extension_oids_are_unique(x)) + x->ex_flags |= EXFLAG_INVALID; + + x509_verify_cert_info_populate(x); + + x->ex_flags |= EXFLAG_SET; +} + +int +x509v3_cache_extensions(X509 *x) +{ + if ((x->ex_flags & EXFLAG_SET) == 0) { + CRYPTO_w_lock(CRYPTO_LOCK_X509); + x509v3_cache_extensions_internal(x); + CRYPTO_w_unlock(CRYPTO_LOCK_X509); + } + + return (x->ex_flags & EXFLAG_INVALID) == 0; +} + +/* CA checks common to all purposes + * return codes: + * 0 not a CA + * 1 is a CA + * 2 basicConstraints absent so "maybe" a CA + * 3 basicConstraints absent but self signed V1. + * 4 basicConstraints absent but keyUsage present and keyCertSign asserted. + */ + +static int +check_ca(const X509 *x) +{ + /* keyUsage if present should allow cert signing */ + if (ku_reject(x, KU_KEY_CERT_SIGN)) + return 0; + if (x->ex_flags & EXFLAG_BCONS) { + if (x->ex_flags & EXFLAG_CA) + return 1; + /* If basicConstraints says not a CA then say so */ + else + return 0; + } else { + /* we support V1 roots for... uh, I don't really know why. */ + if ((x->ex_flags & V1_ROOT) == V1_ROOT) + return 3; + /* If key usage present it must have certSign so tolerate it */ + else if (x->ex_flags & EXFLAG_KUSAGE) + return 4; + /* Older certificates could have Netscape-specific CA types */ + else if (x->ex_flags & EXFLAG_NSCERT && + x->ex_nscert & NS_ANY_CA) + return 5; + /* can this still be regarded a CA certificate? I doubt it */ + return 0; + } +} + +int +X509_check_ca(X509 *x) +{ + x509v3_cache_extensions(x); + + return check_ca(x); +} +LCRYPTO_ALIAS(X509_check_ca); + +/* Check SSL CA: common checks for SSL client and server */ +static int +check_ssl_ca(const X509 *x) +{ + int ca_ret; + + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA) + return ca_ret; + else + return 0; +} + +static int +check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SSL_CLIENT)) + return 0; + if (ca) + return check_ssl_ca(x); + /* We need to do digital signatures with it */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE)) + return 0; + /* nsCertType if present should allow SSL client use */ + if (ns_reject(x, NS_SSL_CLIENT)) + return 0; + return 1; +} + +static int +check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SSL_SERVER|XKU_SGC)) + return 0; + if (ca) + return check_ssl_ca(x); + + if (ns_reject(x, NS_SSL_SERVER)) + return 0; + /* Now as for keyUsage: we'll at least need to sign OR encipher */ + if (ku_reject(x, KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT)) + return 0; + + return 1; +} + +static int +check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + int ret; + + ret = check_purpose_ssl_server(xp, x, ca); + if (!ret || ca) + return ret; + /* We need to encipher or Netscape complains */ + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +/* common S/MIME checks */ +static int +purpose_smime(const X509 *x, int ca) +{ + if (xku_reject(x, XKU_SMIME)) + return 0; + if (ca) { + int ca_ret; + ca_ret = check_ca(x); + if (!ca_ret) + return 0; + /* check nsCertType if present */ + if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) + return ca_ret; + else + return 0; + } + if (x->ex_flags & EXFLAG_NSCERT) { + if (x->ex_nscert & NS_SMIME) + return 1; + /* Workaround for some buggy certificates */ + if (x->ex_nscert & NS_SSL_CLIENT) + return 2; + return 0; + } + return 1; +} + +static int +check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + int ret; + + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) + return 0; + return ret; +} + +static int +check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + int ret; + + ret = purpose_smime(x, ca); + if (!ret || ca) + return ret; + if (ku_reject(x, KU_KEY_ENCIPHERMENT)) + return 0; + return ret; +} + +static int +check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + if (ca) { + int ca_ret; + if ((ca_ret = check_ca(x)) != 2) + return ca_ret; + else + return 0; + } + if (ku_reject(x, KU_CRL_SIGN)) + return 0; + return 1; +} + +/* OCSP helper: this is *not* a full OCSP check. It just checks that + * each CA is valid. Additional checks must be made on the chain. + */ +static int +ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + /* Must be a valid CA. Should we really support the "I don't know" + value (2)? */ + if (ca) + return check_ca(x); + /* leaf certificate is checked in OCSP_verify() */ + return 1; +} + +static int +check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + int i_ext; + + /* If ca is true we must return if this is a valid CA certificate. */ + if (ca) + return check_ca(x); + + /* + * Check the optional key usage field: + * if Key Usage is present, it must be one of digitalSignature + * and/or nonRepudiation (other values are not consistent and shall + * be rejected). + */ + if ((x->ex_flags & EXFLAG_KUSAGE) && + ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) || + !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)))) + return 0; + + /* Only time stamp key usage is permitted and it's required. */ + if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP) + return 0; + + /* Extended Key Usage MUST be critical */ + i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, -1); + if (i_ext >= 0) { + X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext); + if (!X509_EXTENSION_get_critical(ext)) + return 0; + } + + return 1; +} + +static int +no_check(const X509_PURPOSE *xp, const X509 *x, int ca) +{ + return 1; +} + +/* Various checks to see if one certificate issued the second. + * This can be used to prune a set of possible issuer certificates + * which have been looked up using some simple method such as by + * subject name. + * These are: + * 1. Check issuer_name(subject) == subject_name(issuer) + * 2. If akid(subject) exists check it matches issuer + * 3. If key_usage(issuer) exists check it supports certificate signing + * returns 0 for OK, positive for reason for mismatch, reasons match + * codes for X509_verify_cert() + */ + +int +X509_check_issued(X509 *issuer, X509 *subject) +{ + if (X509_NAME_cmp(X509_get_subject_name(issuer), + X509_get_issuer_name(subject))) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + if (!x509v3_cache_extensions(issuer)) + return X509_V_ERR_UNSPECIFIED; + if (!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; + } + + if (ku_reject(issuer, KU_KEY_CERT_SIGN)) + return X509_V_ERR_KEYUSAGE_NO_CERTSIGN; + return X509_V_OK; +} +LCRYPTO_ALIAS(X509_check_issued); + +int +X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid) +{ + if (!akid) + return X509_V_OK; + + /* Check key ids (if present) */ + if (akid->keyid && issuer->skid && + ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) ) + return X509_V_ERR_AKID_SKID_MISMATCH; + /* Check serial number */ + if (akid->serial && + ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial)) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + /* Check issuer name */ + if (akid->issuer) { + /* Ugh, for some peculiar reason AKID includes + * SEQUENCE OF GeneralName. So look for a DirName. + * There may be more than one but we only take any + * notice of the first. + */ + GENERAL_NAMES *gens; + GENERAL_NAME *gen; + X509_NAME *nm = NULL; + int i; + gens = akid->issuer; + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type == GEN_DIRNAME) { + nm = gen->d.dirn; + break; + } + } + if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer))) + return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + return X509_V_OK; +} +LCRYPTO_ALIAS(X509_check_akid); + +uint32_t +X509_get_extension_flags(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return EXFLAG_INVALID; + + return x->ex_flags; +} +LCRYPTO_ALIAS(X509_get_extension_flags); + +uint32_t +X509_get_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return 0; + + if (x->ex_flags & EXFLAG_KUSAGE) + return x->ex_kusage; + + return UINT32_MAX; +} +LCRYPTO_ALIAS(X509_get_key_usage); + +uint32_t +X509_get_extended_key_usage(X509 *x) +{ + /* Call for side-effect of computing hash and caching extensions */ + if (X509_check_purpose(x, -1, -1) != 1) + return 0; + + if (x->ex_flags & EXFLAG_XKUSAGE) + return x->ex_xkusage; + + return UINT32_MAX; +} +LCRYPTO_ALIAS(X509_get_extended_key_usage); diff --git a/crypto/x509/x509_r2x.c b/crypto/x509/x509_r2x.c new file mode 100644 index 0000000..39b3922 --- /dev/null +++ b/crypto/x509/x509_r2x.c @@ -0,0 +1,117 @@ +/* $OpenBSD: x509_r2x.c,v 1.17 2023/04/25 09:46:36 job Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +X509 * +X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) +{ + X509 *ret = NULL; + X509_CINF *xi = NULL; + X509_NAME *xn; + EVP_PKEY *pubkey; + + if ((ret = X509_new()) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + goto err; + } + + /* duplicate the request */ + xi = ret->cert_info; + + if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) { + if (!X509_set_version(ret, 2)) + goto err; + } + + xn = X509_REQ_get_subject_name(r); + if (X509_set_subject_name(ret, xn) == 0) + goto err; + if (X509_set_issuer_name(ret, xn) == 0) + goto err; + + if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL) + goto err; + if (X509_gmtime_adj(xi->validity->notAfter, + (long)60 * 60 * 24 * days) == NULL) + goto err; + + if ((pubkey = X509_REQ_get0_pubkey(r)) == NULL) + goto err; + if (!X509_set_pubkey(ret, pubkey)) + goto err; + + if (!X509_sign(ret, pkey, EVP_md5())) + goto err; + return ret; + +err: + X509_free(ret); + return NULL; +} +LCRYPTO_ALIAS(X509_REQ_to_X509); diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c new file mode 100644 index 0000000..7ed1062 --- /dev/null +++ b/crypto/x509/x509_req.c @@ -0,0 +1,356 @@ +/* $OpenBSD: x509_req.c,v 1.33 2023/04/25 09:46:36 job Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "evp_local.h" +#include "x509_local.h" + +X509_REQ * +X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + X509_REQ *ret; + int i; + EVP_PKEY *pktmp; + + ret = X509_REQ_new(); + if (ret == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!X509_REQ_set_version(ret, 0)) + goto err; + + if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x))) + goto err; + + if ((pktmp = X509_get_pubkey(x)) == NULL) + goto err; + + i = X509_REQ_set_pubkey(ret, pktmp); + EVP_PKEY_free(pktmp); + if (!i) + goto err; + + if (pkey != NULL) { + if (!X509_REQ_sign(ret, pkey, md)) + goto err; + } + return (ret); + +err: + X509_REQ_free(ret); + return (NULL); +} +LCRYPTO_ALIAS(X509_to_X509_REQ); + +EVP_PKEY * +X509_REQ_get_pubkey(X509_REQ *req) +{ + if ((req == NULL) || (req->req_info == NULL)) + return (NULL); + return (X509_PUBKEY_get(req->req_info->pubkey)); +} +LCRYPTO_ALIAS(X509_REQ_get_pubkey); + +EVP_PKEY * +X509_REQ_get0_pubkey(X509_REQ *req) +{ + if (req == NULL || req->req_info == NULL) + return NULL; + return X509_PUBKEY_get0(req->req_info->pubkey); +} +LCRYPTO_ALIAS(X509_REQ_get0_pubkey); + +int +X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k) +{ + EVP_PKEY *xk = NULL; + int ok = 0; + + if ((xk = X509_REQ_get0_pubkey(x)) == NULL) + return 0; + + switch (EVP_PKEY_cmp(xk, k)) { + case 1: + ok = 1; + break; + case 0: + X509error(X509_R_KEY_VALUES_MISMATCH); + break; + case -1: + X509error(X509_R_KEY_TYPE_MISMATCH); + break; + case -2: +#ifndef OPENSSL_NO_EC + if (k->type == EVP_PKEY_EC) { + X509error(ERR_R_EC_LIB); + break; + } +#endif +#ifndef OPENSSL_NO_DH + if (k->type == EVP_PKEY_DH) { + /* No idea */ + X509error(X509_R_CANT_CHECK_DH_KEY); + break; + } +#endif + X509error(X509_R_UNKNOWN_KEY_TYPE); + } + + return (ok); +} +LCRYPTO_ALIAS(X509_REQ_check_private_key); + +/* It seems several organisations had the same idea of including a list of + * extensions in a certificate request. There are at least two OIDs that are + * used and there may be more: so the list is configurable. + */ + +static int ext_nid_list[] = {NID_ext_req, NID_ms_ext_req, NID_undef}; + +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) + return 0; + else if (req_nid == nid) + return 1; + } +} +LCRYPTO_ALIAS(X509_REQ_extension_nid); + +int * +X509_REQ_get_extension_nids(void) +{ + return ext_nids; +} +LCRYPTO_ALIAS(X509_REQ_get_extension_nids); + +void +X509_REQ_set_extension_nids(int *nids) +{ + ext_nids = nids; +} +LCRYPTO_ALIAS(X509_REQ_set_extension_nids); + +STACK_OF(X509_EXTENSION) * +X509_REQ_get_extensions(X509_REQ *req) +{ + X509_ATTRIBUTE *attr; + ASN1_TYPE *ext = NULL; + int idx, *pnid; + const unsigned char *p; + + if (req == NULL || req->req_info == NULL || ext_nids == NULL) + return NULL; + for (pnid = ext_nids; *pnid != NID_undef; pnid++) { + idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); + if (idx == -1) + continue; + attr = X509_REQ_get_attr(req, idx); + ext = X509_ATTRIBUTE_get0_type(attr, 0); + break; + } + if (ext == NULL) + return sk_X509_EXTENSION_new_null(); + if (ext->type != V_ASN1_SEQUENCE) + return NULL; + p = ext->value.sequence->data; + return d2i_X509_EXTENSIONS(NULL, &p, ext->value.sequence->length); +} +LCRYPTO_ALIAS(X509_REQ_get_extensions); + +/* + * 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) +{ + unsigned char *ext = NULL; + int extlen; + int rv; + + extlen = i2d_X509_EXTENSIONS(exts, &ext); + if (extlen <= 0) + return 0; + + rv = X509_REQ_add1_attr_by_NID(req, nid, V_ASN1_SEQUENCE, ext, extlen); + free(ext); + + return rv; +} +LCRYPTO_ALIAS(X509_REQ_add_extensions_nid); + +/* This is the normal usage: use the "official" OID */ +int +X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts) +{ + return X509_REQ_add_extensions_nid(req, exts, NID_ext_req); +} +LCRYPTO_ALIAS(X509_REQ_add_extensions); + +/* Request attribute functions */ + +int +X509_REQ_get_attr_count(const X509_REQ *req) +{ + return X509at_get_attr_count(req->req_info->attributes); +} +LCRYPTO_ALIAS(X509_REQ_get_attr_count); + +int +X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos) +{ + return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos); +} +LCRYPTO_ALIAS(X509_REQ_get_attr_by_NID); + +int +X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, + int lastpos) +{ + return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos); +} +LCRYPTO_ALIAS(X509_REQ_get_attr_by_OBJ); + +X509_ATTRIBUTE * +X509_REQ_get_attr(const X509_REQ *req, int loc) +{ + return X509at_get_attr(req->req_info->attributes, loc); +} +LCRYPTO_ALIAS(X509_REQ_get_attr); + +X509_ATTRIBUTE * +X509_REQ_delete_attr(X509_REQ *req, int loc) +{ + return X509at_delete_attr(req->req_info->attributes, loc); +} +LCRYPTO_ALIAS(X509_REQ_delete_attr); + +int +X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) +{ + if (X509at_add1_attr(&req->req_info->attributes, attr)) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_REQ_add1_attr); + +int +X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj, + type, bytes, len)) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_REQ_add1_attr_by_OBJ); + +int +X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid, + type, bytes, len)) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_REQ_add1_attr_by_NID); + +int +X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int type, + const unsigned char *bytes, int len) +{ + if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname, + type, bytes, len)) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_REQ_add1_attr_by_txt); + +int +i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) +{ + req->req_info->enc.modified = 1; + return i2d_X509_REQ_INFO(req->req_info, pp); +} +LCRYPTO_ALIAS(i2d_re_X509_REQ_tbs); diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c new file mode 100644 index 0000000..b56d30a --- /dev/null +++ b/crypto/x509/x509_set.c @@ -0,0 +1,262 @@ +/* $OpenBSD: x509_set.c,v 1.26 2023/06/23 08:00:28 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +const STACK_OF(X509_EXTENSION) * +X509_get0_extensions(const X509 *x) +{ + return x->cert_info->extensions; +} +LCRYPTO_ALIAS(X509_get0_extensions); + +const X509_ALGOR * +X509_get0_tbs_sigalg(const X509 *x) +{ + return x->cert_info->signature; +} +LCRYPTO_ALIAS(X509_get0_tbs_sigalg); + +int +X509_set_version(X509 *x, long version) +{ + if (x == NULL) + return (0); + if (x->cert_info->version == NULL) { + if ((x->cert_info->version = ASN1_INTEGER_new()) == NULL) + return (0); + } + x->cert_info->enc.modified = 1; + return (ASN1_INTEGER_set(x->cert_info->version, version)); +} +LCRYPTO_ALIAS(X509_set_version); + +long +X509_get_version(const X509 *x) +{ + return ASN1_INTEGER_get(x->cert_info->version); +} +LCRYPTO_ALIAS(X509_get_version); + +int +X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return 0; + in = x->cert_info->serialNumber; + if (in != serial) { + in = ASN1_INTEGER_dup(serial); + if (in != NULL) { + x->cert_info->enc.modified = 1; + ASN1_INTEGER_free(x->cert_info->serialNumber); + x->cert_info->serialNumber = in; + } + } + return in != NULL; +} +LCRYPTO_ALIAS(X509_set_serialNumber); + +int +X509_set_issuer_name(X509 *x, X509_NAME *name) +{ + if (x == NULL || x->cert_info == NULL) + return 0; + x->cert_info->enc.modified = 1; + return X509_NAME_set(&x->cert_info->issuer, name); +} +LCRYPTO_ALIAS(X509_set_issuer_name); + +int +X509_set_subject_name(X509 *x, X509_NAME *name) +{ + if (x == NULL || x->cert_info == NULL) + return 0; + x->cert_info->enc.modified = 1; + return X509_NAME_set(&x->cert_info->subject, name); +} +LCRYPTO_ALIAS(X509_set_subject_name); + +const ASN1_TIME * +X509_get0_notBefore(const X509 *x) +{ + return X509_getm_notBefore(x); +} +LCRYPTO_ALIAS(X509_get0_notBefore); + +ASN1_TIME * +X509_getm_notBefore(const X509 *x) +{ + if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL) + return NULL; + return x->cert_info->validity->notBefore; +} +LCRYPTO_ALIAS(X509_getm_notBefore); + +int +X509_set_notBefore(X509 *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL || x->cert_info->validity == NULL) + return 0; + in = x->cert_info->validity->notBefore; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + x->cert_info->enc.modified = 1; + ASN1_TIME_free(x->cert_info->validity->notBefore); + x->cert_info->validity->notBefore = in; + } + } + return in != NULL; +} +LCRYPTO_ALIAS(X509_set_notBefore); + +int +X509_set1_notBefore(X509 *x, const ASN1_TIME *tm) +{ + return X509_set_notBefore(x, tm); +} +LCRYPTO_ALIAS(X509_set1_notBefore); + +const ASN1_TIME * +X509_get0_notAfter(const X509 *x) +{ + return X509_getm_notAfter(x); +} +LCRYPTO_ALIAS(X509_get0_notAfter); + +ASN1_TIME * +X509_getm_notAfter(const X509 *x) +{ + if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL) + return NULL; + return x->cert_info->validity->notAfter; +} +LCRYPTO_ALIAS(X509_getm_notAfter); + +int +X509_set_notAfter(X509 *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL || x->cert_info->validity == NULL) + return 0; + in = x->cert_info->validity->notAfter; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + x->cert_info->enc.modified = 1; + ASN1_TIME_free(x->cert_info->validity->notAfter); + x->cert_info->validity->notAfter = in; + } + } + return in != NULL; +} +LCRYPTO_ALIAS(X509_set_notAfter); + +int +X509_set1_notAfter(X509 *x, const ASN1_TIME *tm) +{ + return X509_set_notAfter(x, tm); +} +LCRYPTO_ALIAS(X509_set1_notAfter); + +int +X509_set_pubkey(X509 *x, EVP_PKEY *pkey) +{ + if (x == NULL || x->cert_info == NULL) + return 0; + x->cert_info->enc.modified = 1; + return X509_PUBKEY_set(&x->cert_info->key, pkey); +} +LCRYPTO_ALIAS(X509_set_pubkey); + +int +X509_get_signature_type(const X509 *x) +{ + return EVP_PKEY_type(OBJ_obj2nid(x->sig_alg->algorithm)); +} +LCRYPTO_ALIAS(X509_get_signature_type); + +X509_PUBKEY * +X509_get_X509_PUBKEY(const X509 *x) +{ + return x->cert_info->key; +} +LCRYPTO_ALIAS(X509_get_X509_PUBKEY); + +void +X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid) +{ + if (piuid != NULL) + *piuid = x->cert_info->issuerUID; + if (psuid != NULL) + *psuid = x->cert_info->subjectUID; +} +LCRYPTO_ALIAS(X509_get0_uids); diff --git a/crypto/x509/x509_skey.c b/crypto/x509/x509_skey.c new file mode 100644 index 0000000..245ba51 --- /dev/null +++ b/crypto/x509/x509_skey.c @@ -0,0 +1,165 @@ +/* $OpenBSD: x509_skey.c,v 1.5 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include + +#include "x509_local.h" + +static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, char *str); + +const X509V3_EXT_METHOD v3_skey_id = { + .ext_nid = NID_subject_key_identifier, + .ext_flags = 0, + .it = &ASN1_OCTET_STRING_it, + .ext_new = NULL, + .ext_free = NULL, + .d2i = NULL, + .i2d = NULL, + .i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING, + .s2i = (X509V3_EXT_S2I)s2i_skey_id, + .i2v = NULL, + .v2i = NULL, + .i2r = NULL, + .r2i = NULL, + .usr_data = NULL, +}; + +char * +i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, const ASN1_OCTET_STRING *oct) +{ + return hex_to_string(oct->data, oct->length); +} +LCRYPTO_ALIAS(i2s_ASN1_OCTET_STRING); + +ASN1_OCTET_STRING * +s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + const char *str) +{ + ASN1_OCTET_STRING *oct; + long length; + + if (!(oct = ASN1_OCTET_STRING_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (!(oct->data = string_to_hex(str, &length))) { + ASN1_OCTET_STRING_free(oct); + return NULL; + } + + oct->length = length; + + return oct; +} +LCRYPTO_ALIAS(s2i_ASN1_OCTET_STRING); + +static ASN1_OCTET_STRING * +s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str) +{ + ASN1_OCTET_STRING *oct; + ASN1_BIT_STRING *pk; + unsigned char pkey_dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + + if (strcmp(str, "hash")) + return s2i_ASN1_OCTET_STRING(method, ctx, str); + + if (!(oct = ASN1_OCTET_STRING_new())) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + + if (ctx && (ctx->flags == CTX_TEST)) + return oct; + + if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) { + X509V3error(X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (ctx->subject_req) + pk = ctx->subject_req->req_info->pubkey->public_key; + else + pk = ctx->subject_cert->cert_info->key->public_key; + + if (!pk) { + X509V3error(X509V3_R_NO_PUBLIC_KEY); + goto err; + } + + if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, + EVP_sha1(), NULL)) + goto err; + + if (!ASN1_STRING_set(oct, pkey_dig, diglen)) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + + return oct; + +err: + ASN1_OCTET_STRING_free(oct); + return NULL; +} diff --git a/crypto/x509/x509_trs.c b/crypto/x509/x509_trs.c new file mode 100644 index 0000000..6b935f8 --- /dev/null +++ b/crypto/x509/x509_trs.c @@ -0,0 +1,398 @@ +/* $OpenBSD: x509_trs.c,v 1.32 2023/07/02 17:12:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include + +#include "x509_local.h" + +static int tr_cmp(const X509_TRUST * const *a, const X509_TRUST * const *b); +static void trtable_free(X509_TRUST *p); + +static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags); +static int trust_1oid(X509_TRUST *trust, X509 *x, int flags); +static int trust_compat(X509_TRUST *trust, X509 *x, int flags); + +static int obj_trust(int id, X509 *x, int flags); +static int (*default_trust)(int id, X509 *x, int flags) = obj_trust; + +/* WARNING: the following table should be kept in order of trust + * and without any gaps so we can just subtract the minimum trust + * value to get an index into the table + */ + +static X509_TRUST trstandard[] = { + { + .trust = X509_TRUST_COMPAT, + .check_trust = trust_compat, + .name = "compatible", + }, + { + .trust = X509_TRUST_SSL_CLIENT, + .check_trust = trust_1oidany, + .name = "SSL Client", + .arg1 = NID_client_auth, + }, + { + .trust = X509_TRUST_SSL_SERVER, + .check_trust = trust_1oidany, + .name = "SSL Server", + .arg1 = NID_server_auth, + }, + { + .trust = X509_TRUST_EMAIL, + .check_trust = trust_1oidany, + .name = "S/MIME email", + .arg1 = NID_email_protect, + }, + { + .trust = X509_TRUST_OBJECT_SIGN, + .check_trust = trust_1oidany, + .name = "Object Signer", + .arg1 = NID_code_sign, + }, + { + .trust = X509_TRUST_OCSP_SIGN, + .check_trust = trust_1oid, + .name = "OCSP responder", + .arg1 = NID_OCSP_sign, + }, + { + .trust = X509_TRUST_OCSP_REQUEST, + .check_trust = trust_1oid, + .name = "OCSP request", + .arg1 = NID_ad_OCSP, + }, + { + .trust = X509_TRUST_TSA, + .check_trust = trust_1oidany, + .name = "TSA server", + .arg1 = NID_time_stamp, + }, +}; + +#define X509_TRUST_COUNT (sizeof(trstandard) / sizeof(trstandard[0])) + +static STACK_OF(X509_TRUST) *trtable = NULL; + +static int +tr_cmp(const X509_TRUST * const *a, const X509_TRUST * const *b) +{ + return (*a)->trust - (*b)->trust; +} + +int +(*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int) +{ + int (*oldtrust)(int , X509 *, int); + + oldtrust = default_trust; + default_trust = trust; + return oldtrust; +} +LCRYPTO_ALIAS(X509_TRUST_set_default); + +int +X509_check_trust(X509 *x, int id, int flags) +{ + X509_TRUST *pt; + int idx; + + if (id == -1) + return 1; + /* + * XXX beck/jsing This enables self signed certs to be trusted for + * an unspecified id/trust flag value (this is NOT the + * X509_TRUST_DEFAULT), which was the longstanding + * openssl behaviour. boringssl does not have this behaviour. + * + * This should be revisited, but changing the default "not default" + * may break things. + */ + if (id == 0) { + int rv; + rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); + if (rv != X509_TRUST_UNTRUSTED) + return rv; + return trust_compat(NULL, x, 0); + } + idx = X509_TRUST_get_by_id(id); + if (idx == -1) + return default_trust(id, x, flags); + pt = X509_TRUST_get0(idx); + return pt->check_trust(pt, x, flags); +} +LCRYPTO_ALIAS(X509_check_trust); + +int +X509_TRUST_get_count(void) +{ + if (!trtable) + return X509_TRUST_COUNT; + return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT; +} +LCRYPTO_ALIAS(X509_TRUST_get_count); + +X509_TRUST * +X509_TRUST_get0(int idx) +{ + if (idx < 0) + return NULL; + if (idx < (int)X509_TRUST_COUNT) + return trstandard + idx; + return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT); +} +LCRYPTO_ALIAS(X509_TRUST_get0); + +int +X509_TRUST_get_by_id(int id) +{ + X509_TRUST tmp; + int idx; + + if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX)) + return id - X509_TRUST_MIN; + tmp.trust = id; + if (!trtable) + return -1; + idx = sk_X509_TRUST_find(trtable, &tmp); + if (idx == -1) + return -1; + return idx + X509_TRUST_COUNT; +} +LCRYPTO_ALIAS(X509_TRUST_get_by_id); + +int +X509_TRUST_set(int *t, int trust) +{ + if (X509_TRUST_get_by_id(trust) == -1) { + X509error(X509_R_INVALID_TRUST); + return 0; + } + *t = trust; + return 1; +} +LCRYPTO_ALIAS(X509_TRUST_set); + +int +X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + const char *name, int arg1, void *arg2) +{ + int idx; + X509_TRUST *trtmp; + char *name_dup; + + /* This is set according to what we change: application can't set it */ + flags &= ~X509_TRUST_DYNAMIC; + /* This will always be set for application modified trust entries */ + flags |= X509_TRUST_DYNAMIC_NAME; + /* Get existing entry if any */ + idx = X509_TRUST_get_by_id(id); + /* Need a new entry */ + if (idx == -1) { + if (!(trtmp = malloc(sizeof(X509_TRUST)))) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + trtmp->flags = X509_TRUST_DYNAMIC; + } else { + trtmp = X509_TRUST_get0(idx); + if (trtmp == NULL) { + X509error(X509_R_INVALID_TRUST); + return 0; + } + } + + if ((name_dup = strdup(name)) == NULL) + goto err; + + /* free existing name if dynamic */ + if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) + free(trtmp->name); + /* dup supplied name */ + trtmp->name = name_dup; + /* Keep the dynamic flag of existing entry */ + trtmp->flags &= X509_TRUST_DYNAMIC; + /* Set all other flags */ + trtmp->flags |= flags; + + trtmp->trust = id; + trtmp->check_trust = ck; + trtmp->arg1 = arg1; + trtmp->arg2 = arg2; + + /* If it's a new entry, manage the dynamic table */ + if (idx == -1) { + if (trtable == NULL && + (trtable = sk_X509_TRUST_new(tr_cmp)) == NULL) + goto err; + if (sk_X509_TRUST_push(trtable, trtmp) == 0) + goto err; + } + return 1; + +err: + free(name_dup); + if (idx == -1) + free(trtmp); + X509error(ERR_R_MALLOC_FAILURE); + return 0; +} +LCRYPTO_ALIAS(X509_TRUST_add); + +static void +trtable_free(X509_TRUST *p) +{ + if (!p) + return; + if (p->flags & X509_TRUST_DYNAMIC) { + if (p->flags & X509_TRUST_DYNAMIC_NAME) + free(p->name); + free(p); + } +} + +void +X509_TRUST_cleanup(void) +{ + sk_X509_TRUST_pop_free(trtable, trtable_free); + trtable = NULL; +} +LCRYPTO_ALIAS(X509_TRUST_cleanup); + +int +X509_TRUST_get_flags(const X509_TRUST *xp) +{ + return xp->flags; +} +LCRYPTO_ALIAS(X509_TRUST_get_flags); + +char * +X509_TRUST_get0_name(const X509_TRUST *xp) +{ + return xp->name; +} +LCRYPTO_ALIAS(X509_TRUST_get0_name); + +int +X509_TRUST_get_trust(const X509_TRUST *xp) +{ + return xp->trust; +} +LCRYPTO_ALIAS(X509_TRUST_get_trust); + +static int +trust_1oidany(X509_TRUST *trust, X509 *x, int flags) +{ + if (x->aux && (x->aux->trust || x->aux->reject)) + return obj_trust(trust->arg1, x, flags); + /* we don't have any trust settings: for compatibility + * we return trusted if it is self signed + */ + return trust_compat(trust, x, flags); +} + +static int +trust_1oid(X509_TRUST *trust, X509 *x, int flags) +{ + if (x->aux) + return obj_trust(trust->arg1, x, flags); + return X509_TRUST_UNTRUSTED; +} + +static int +trust_compat(X509_TRUST *trust, X509 *x, int flags) +{ + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return X509_TRUST_TRUSTED; + else + return X509_TRUST_UNTRUSTED; +} + +static int +obj_trust(int id, X509 *x, int flags) +{ + ASN1_OBJECT *obj; + int i, nid; + X509_CERT_AUX *ax; + + ax = x->aux; + if (!ax) + return X509_TRUST_UNTRUSTED; + if (ax->reject) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) { + obj = sk_ASN1_OBJECT_value(ax->reject, i); + nid = OBJ_obj2nid(obj); + if (nid == id || nid == NID_anyExtendedKeyUsage) + return X509_TRUST_REJECTED; + } + } + if (ax->trust) { + for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) { + obj = sk_ASN1_OBJECT_value(ax->trust, i); + nid = OBJ_obj2nid(obj); + if (nid == id || nid == NID_anyExtendedKeyUsage) + return X509_TRUST_TRUSTED; + } + } + return X509_TRUST_UNTRUSTED; +} diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c new file mode 100644 index 0000000..5f5bc5a --- /dev/null +++ b/crypto/x509/x509_txt.c @@ -0,0 +1,196 @@ +/* $OpenBSD: x509_txt.c,v 1.28 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +const char * +X509_verify_cert_error_string(long n) +{ + switch ((int)n) { + case X509_V_OK: + return "ok"; + case X509_V_ERR_UNSPECIFIED: + return "Unspecified certificate verification error"; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + return "unable to get issuer certificate"; + case X509_V_ERR_UNABLE_TO_GET_CRL: + return "unable to get certificate CRL"; + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + return "unable to decrypt certificate's signature"; + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + return "unable to decrypt CRL's signature"; + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + return "unable to decode issuer public key"; + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + return "certificate signature failure"; + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + return "CRL signature failure"; + case X509_V_ERR_CERT_NOT_YET_VALID: + return "certificate is not yet valid"; + case X509_V_ERR_CERT_HAS_EXPIRED: + return "certificate has expired"; + case X509_V_ERR_CRL_NOT_YET_VALID: + return "CRL is not yet valid"; + case X509_V_ERR_CRL_HAS_EXPIRED: + return "CRL has expired"; + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return "format error in certificate's notBefore field"; + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return "format error in certificate's notAfter field"; + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + return "format error in CRL's lastUpdate field"; + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + return "format error in CRL's nextUpdate field"; + case X509_V_ERR_OUT_OF_MEM: + return "out of memory"; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + return "self signed certificate"; + case X509_V_ERR_SELF_SIGNED_CERT_IN_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: + return "unable to verify the first certificate"; + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + 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_PATH_LENGTH_EXCEEDED: + return "path length constraint exceeded"; + case X509_V_ERR_INVALID_PURPOSE: + return "unsupported certificate purpose"; + case X509_V_ERR_CERT_UNTRUSTED: + return "certificate not trusted"; + case X509_V_ERR_CERT_REJECTED: + return "certificate rejected"; + case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: + return "subject issuer mismatch"; + case X509_V_ERR_AKID_SKID_MISMATCH: + return "authority and subject key identifier mismatch"; + case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + return "authority and issuer serial number mismatch"; + case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + return "key usage does not include certificate signing"; + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + return "unable to get CRL issuer certificate"; + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + return "unhandled critical extension"; + case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN: + return "key usage does not include CRL signing"; + case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: + return "unhandled critical CRL extension"; + case X509_V_ERR_INVALID_NON_CA: + return "invalid non-CA certificate (has CA markings)"; + case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + return "proxy path length constraint exceeded"; + case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: + return "key usage does not include digital signature"; + case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: + return "proxy certificates not allowed, " + "please set the appropriate flag"; + case X509_V_ERR_INVALID_EXTENSION: + return "invalid or inconsistent certificate extension"; + case X509_V_ERR_INVALID_POLICY_EXTENSION: + return "invalid or inconsistent certificate policy extension"; + case X509_V_ERR_NO_EXPLICIT_POLICY: + return "no explicit policy"; + case X509_V_ERR_DIFFERENT_CRL_SCOPE: + return "Different CRL scope"; + case X509_V_ERR_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: + return "permitted subtree violation"; + case X509_V_ERR_EXCLUDED_VIOLATION: + return "excluded subtree violation"; + case X509_V_ERR_SUBTREE_MINMAX: + return "name constraints minimum and maximum not supported"; + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: + return "unsupported name constraint type"; + case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: + return "unsupported or invalid name constraint syntax"; + case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: + return "unsupported or invalid name syntax"; + case X509_V_ERR_CRL_PATH_VALIDATION_ERROR: + return "CRL path validation error"; + case X509_V_ERR_APPLICATION_VERIFICATION: + return "application verification failure"; + case X509_V_ERR_HOSTNAME_MISMATCH: + return "Hostname mismatch"; + case X509_V_ERR_EMAIL_MISMATCH: + return "Email address mismatch"; + case X509_V_ERR_IP_ADDRESS_MISMATCH: + return "IP address mismatch"; + case X509_V_ERR_INVALID_CALL: + return "Invalid certificate verification context"; + case X509_V_ERR_STORE_LOOKUP: + return "Issuer certificate lookup error"; + case X509_V_ERR_EE_KEY_TOO_SMALL: + return "EE certificate key too weak"; + case X509_V_ERR_CA_KEY_TOO_SMALL: + return "CA certificate key too weak"; + case X509_V_ERR_CA_MD_TOO_WEAK: + return "CA signature digest algorithm too weak"; + default: + return "Unknown certificate verification error"; + } +} +LCRYPTO_ALIAS(X509_verify_cert_error_string); diff --git a/crypto/x509/x509_utl.c b/crypto/x509/x509_utl.c new file mode 100644 index 0000000..14b43e8 --- /dev/null +++ b/crypto/x509/x509_utl.c @@ -0,0 +1,1486 @@ +/* $OpenBSD: x509_utl.c,v 1.17 2023/05/12 19:02:10 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "bytestring.h" + +static char *bn_to_string(const BIGNUM *bn); +static char *strip_spaces(char *name); +static int sk_strcmp(const char * const *a, const char * const *b); +static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, + GENERAL_NAMES *gens); +static void str_free(OPENSSL_STRING str); +static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); + +static int ipv4_from_asc(unsigned char *v4, const char *in); +static int ipv6_from_asc(unsigned char *v6, const char *in); +static int ipv6_cb(const char *elem, int len, void *usr); +static int ipv6_hex(unsigned char *out, const char *in, int inlen); + +/* Add a CONF_VALUE name-value pair to stack. */ +int +X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + CONF_VALUE *vtmp = NULL; + STACK_OF(CONF_VALUE) *free_exts = NULL; + + if ((vtmp = calloc(1, sizeof(CONF_VALUE))) == NULL) + goto err; + if (name != NULL) { + if ((vtmp->name = strdup(name)) == NULL) + goto err; + } + if (value != NULL) { + if ((vtmp->value = strdup(value)) == NULL) + goto err; + } + + if (*extlist == NULL) { + if ((free_exts = *extlist = sk_CONF_VALUE_new_null()) == NULL) + goto err; + } + + if (!sk_CONF_VALUE_push(*extlist, vtmp)) + goto err; + + return 1; + + err: + X509V3error(ERR_R_MALLOC_FAILURE); + X509V3_conf_free(vtmp); + if (free_exts != NULL) { + sk_CONF_VALUE_free(*extlist); + *extlist = NULL; + } + return 0; +} +LCRYPTO_ALIAS(X509V3_add_value); + +int +X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist) +{ + return X509V3_add_value(name, (const char *)value, extlist); +} +LCRYPTO_ALIAS(X509V3_add_value_uchar); + +/* Free function for STACK_OF(CONF_VALUE) */ + +void +X509V3_conf_free(CONF_VALUE *conf) +{ + if (!conf) + return; + free(conf->name); + free(conf->value); + free(conf->section); + free(conf); +} +LCRYPTO_ALIAS(X509V3_conf_free); + +int +X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return X509V3_add_value(name, "FALSE", extlist); +} +LCRYPTO_ALIAS(X509V3_add_value_bool); + +int +X509V3_add_value_bool_nf(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist) +{ + if (asn1_bool) + return X509V3_add_value(name, "TRUE", extlist); + return 1; +} +LCRYPTO_ALIAS(X509V3_add_value_bool_nf); + +static char * +bn_to_string(const BIGNUM *bn) +{ + const char *sign = ""; + char *bnstr, *hex; + char *ret = NULL; + + /* Only display small numbers in decimal, as conversion is quadratic. */ + if (BN_num_bits(bn) < 128) + return BN_bn2dec(bn); + + if ((hex = bnstr = BN_bn2hex(bn)) == NULL) + goto err; + + if (BN_is_negative(bn)) { + sign = "-"; + hex++; + } + + if (asprintf(&ret, "%s0x%s", sign, hex) == -1) + ret = NULL; + + err: + free(bnstr); + return ret; +} + +char * +i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) +{ + BIGNUM *bntmp; + char *strtmp = NULL; + + if (a == NULL) + return NULL; + if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL || + (strtmp = bn_to_string(bntmp)) == NULL) + X509V3error(ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} +LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED); + +char * +i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *e) +{ + BIT_STRING_BITNAME *enam; + long strval; + + strval = ASN1_ENUMERATED_get(e); + for (enam = method->usr_data; enam->lname; enam++) { + if (strval == enam->bitnum) + return strdup(enam->lname); + } + return i2s_ASN1_ENUMERATED(method, e); +} +LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED_TABLE); + +char * +i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) +{ + BIGNUM *bntmp; + char *strtmp = NULL; + + if (a == NULL) + return NULL; + if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL || + (strtmp = bn_to_string(bntmp)) == NULL) + X509V3error(ERR_R_MALLOC_FAILURE); + BN_free(bntmp); + return strtmp; +} +LCRYPTO_ALIAS(i2s_ASN1_INTEGER); + +ASN1_INTEGER * +s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) +{ + BIGNUM *bn = NULL; + ASN1_INTEGER *aint; + int isneg = 0, ishex = 0; + int ret; + + if (!value) { + X509V3error(X509V3_R_INVALID_NULL_VALUE); + return NULL; + } + if ((bn = BN_new()) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + return NULL; + } + if (value[0] == '-') { + value++; + isneg = 1; + } + + if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { + value += 2; + ishex = 1; + } + + if (ishex) + ret = BN_hex2bn(&bn, value); + else + ret = BN_dec2bn(&bn, value); + + if (!ret || value[ret]) { + BN_free(bn); + X509V3error(X509V3_R_BN_DEC2BN_ERROR); + return NULL; + } + + if (BN_is_zero(bn)) + isneg = 0; + + aint = BN_to_ASN1_INTEGER(bn, NULL); + BN_free(bn); + if (!aint) { + X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR); + return NULL; + } + if (isneg) + aint->type |= V_ASN1_NEG; + return aint; +} +LCRYPTO_ALIAS(s2i_ASN1_INTEGER); + +int +X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist) +{ + char *strtmp; + int ret; + + if (!aint) + return 1; + if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) + return 0; + ret = X509V3_add_value(name, strtmp, extlist); + free(strtmp); + return ret; +} +LCRYPTO_ALIAS(X509V3_add_value_int); + +int +X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) +{ + char *btmp; + + if (!(btmp = value->value)) + goto err; + if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || + !strcmp(btmp, "Y") || !strcmp(btmp, "y") || + !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { + *asn1_bool = 0xff; + return 1; + } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || + !strcmp(btmp, "N") || !strcmp(btmp, "n") || + !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { + *asn1_bool = 0; + return 1; + } + + err: + X509V3error(X509V3_R_INVALID_BOOLEAN_STRING); + X509V3_conf_err(value); + return 0; +} +LCRYPTO_ALIAS(X509V3_get_value_bool); + +int +X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) +{ + ASN1_INTEGER *itmp; + + if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { + X509V3_conf_err(value); + return 0; + } + *aint = itmp; + return 1; +} +LCRYPTO_ALIAS(X509V3_get_value_int); + +#define HDR_NAME 1 +#define HDR_VALUE 2 + +/*#define DEBUG*/ + +STACK_OF(CONF_VALUE) * +X509V3_parse_list(const char *line) +{ + char *p, *q, c; + char *ntmp, *vtmp; + STACK_OF(CONF_VALUE) *values = NULL; + char *linebuf; + int state; + + /* We are going to modify the line so copy it first */ + if ((linebuf = strdup(line)) == NULL) { + X509V3error(ERR_R_MALLOC_FAILURE); + goto err; + } + state = HDR_NAME; + ntmp = NULL; + + /* Go through all characters */ + for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && + (c != '\n'); p++) { + + switch (state) { + case HDR_NAME: + if (c == ':') { + state = HDR_VALUE; + *p = 0; + ntmp = strip_spaces(q); + if (!ntmp) { + X509V3error(X509V3_R_INVALID_NULL_NAME); + goto err; + } + q = p + 1; + } else if (c == ',') { + *p = 0; + ntmp = strip_spaces(q); + q = p + 1; + if (!ntmp) { + X509V3error(X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + break; + + case HDR_VALUE: + if (c == ',') { + state = HDR_NAME; + *p = 0; + vtmp = strip_spaces(q); + if (!vtmp) { + X509V3error(X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + ntmp = NULL; + q = p + 1; + } + + } + } + + if (state == HDR_VALUE) { + vtmp = strip_spaces(q); + if (!vtmp) { + X509V3error(X509V3_R_INVALID_NULL_VALUE); + goto err; + } + X509V3_add_value(ntmp, vtmp, &values); + } else { + ntmp = strip_spaces(q); + if (!ntmp) { + X509V3error(X509V3_R_INVALID_NULL_NAME); + goto err; + } + X509V3_add_value(ntmp, NULL, &values); + } + free(linebuf); + return values; + + err: + free(linebuf); + sk_CONF_VALUE_pop_free(values, X509V3_conf_free); + return NULL; + +} +LCRYPTO_ALIAS(X509V3_parse_list); + +/* Delete leading and trailing spaces from a string */ +static char * +strip_spaces(char *name) +{ + char *p, *q; + + /* Skip over leading spaces */ + p = name; + while (*p && isspace((unsigned char)*p)) + p++; + if (!*p) + return NULL; + q = p + strlen(p) - 1; + while ((q != p) && isspace((unsigned char)*q)) + q--; + if (p != q) + q[1] = 0; + if (!*p) + return NULL; + return p; +} + +static const char hex_digits[] = "0123456789ABCDEF"; + +char * +hex_to_string(const unsigned char *buffer, long len) +{ + CBB cbb; + CBS cbs; + uint8_t *out = NULL; + uint8_t c; + size_t out_len; + + if (!CBB_init(&cbb, 0)) + goto err; + + if (len < 0) + goto err; + + CBS_init(&cbs, buffer, len); + while (CBS_len(&cbs) > 0) { + if (!CBS_get_u8(&cbs, &c)) + goto err; + if (!CBB_add_u8(&cbb, hex_digits[c >> 4])) + goto err; + if (!CBB_add_u8(&cbb, hex_digits[c & 0xf])) + goto err; + if (CBS_len(&cbs) > 0) { + if (!CBB_add_u8(&cbb, ':')) + goto err; + } + } + + if (!CBB_add_u8(&cbb, '\0')) + goto err; + + if (!CBB_finish(&cbb, &out, &out_len)) + goto err; + + err: + CBB_cleanup(&cbb); + + return out; +} +LCRYPTO_ALIAS(hex_to_string); + +static int +x509_skip_colons_cbs(CBS *cbs) +{ + uint8_t c; + + while (CBS_len(cbs) > 0) { + if (!CBS_peek_u8(cbs, &c)) + return 0; + if (c != ':') + return 1; + if (!CBS_get_u8(cbs, &c)) + return 0; + } + + return 1; +} + +static int +x509_get_xdigit_nibble_cbs(CBS *cbs, uint8_t *out_nibble) +{ + uint8_t c; + + if (!CBS_get_u8(cbs, &c)) + return 0; + + if (c >= '0' && c <= '9') { + *out_nibble = c - '0'; + return 1; + } + if (c >= 'a' && c <= 'f') { + *out_nibble = c - 'a' + 10; + return 1; + } + if (c >= 'A' && c <= 'F') { + *out_nibble = c - 'A' + 10; + return 1; + } + + X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); + return 0; +} + +unsigned char * +string_to_hex(const char *str, long *len) +{ + CBB cbb; + CBS cbs; + uint8_t *out = NULL; + size_t out_len; + uint8_t hi, lo; + + *len = 0; + + if (!CBB_init(&cbb, 0)) + goto err; + + if (str == NULL) { + X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); + goto err; + } + + CBS_init(&cbs, str, strlen(str)); + while (CBS_len(&cbs) > 0) { + /* + * Skipping only a single colon between two pairs of digits + * would make more sense - history... + */ + if (!x509_skip_colons_cbs(&cbs)) + goto err; + /* Another historic idiocy. */ + if (CBS_len(&cbs) == 0) + break; + if (!x509_get_xdigit_nibble_cbs(&cbs, &hi)) + goto err; + if (CBS_len(&cbs) == 0) { + X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS); + goto err; + } + if (!x509_get_xdigit_nibble_cbs(&cbs, &lo)) + goto err; + if (!CBB_add_u8(&cbb, hi << 4 | lo)) + goto err; + } + + if (!CBB_finish(&cbb, &out, &out_len)) + goto err; + if (out_len > LONG_MAX) { + freezero(out, out_len); + out = NULL; + goto err; + } + + *len = out_len; + + err: + CBB_cleanup(&cbb); + + return out; +} +LCRYPTO_ALIAS(string_to_hex); + +/* V2I name comparison function: returns zero if 'name' matches + * cmp or cmp.* + */ + +int +name_cmp(const char *name, const char *cmp) +{ + int len, ret; + char c; + + len = strlen(cmp); + if ((ret = strncmp(name, cmp, len))) + return ret; + c = name[len]; + if (!c || (c=='.')) + return 0; + return 1; +} + +static int +sk_strcmp(const char * const *a, const char * const *b) +{ + return strcmp(*a, *b); +} + +STACK_OF(OPENSSL_STRING) * +X509_get1_email(X509 *x) +{ + GENERAL_NAMES *gens; + STACK_OF(OPENSSL_STRING) *ret; + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + return ret; +} +LCRYPTO_ALIAS(X509_get1_email); + +STACK_OF(OPENSSL_STRING) * +X509_get1_ocsp(X509 *x) +{ + AUTHORITY_INFO_ACCESS *info; + STACK_OF(OPENSSL_STRING) *ret = NULL; + int i; + + info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); + if (!info) + return NULL; + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { + ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); + if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { + if (ad->location->type == GEN_URI) { + if (!append_ia5(&ret, + ad->location->d.uniformResourceIdentifier)) + break; + } + } + } + AUTHORITY_INFO_ACCESS_free(info); + return ret; +} +LCRYPTO_ALIAS(X509_get1_ocsp); + +STACK_OF(OPENSSL_STRING) * +X509_REQ_get1_email(X509_REQ *x) +{ + GENERAL_NAMES *gens; + STACK_OF(X509_EXTENSION) *exts; + STACK_OF(OPENSSL_STRING) *ret; + + exts = X509_REQ_get_extensions(x); + gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); + ret = get_email(X509_REQ_get_subject_name(x), gens); + sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + return ret; +} +LCRYPTO_ALIAS(X509_REQ_get1_email); + + +static STACK_OF(OPENSSL_STRING) * +get_email(X509_NAME *name, GENERAL_NAMES *gens) +{ + STACK_OF(OPENSSL_STRING) *ret = NULL; + X509_NAME_ENTRY *ne; + ASN1_IA5STRING *email; + GENERAL_NAME *gen; + int i; + + /* Now add any email address(es) to STACK */ + i = -1; + + /* First supplied X509_NAME */ + while ((i = X509_NAME_get_index_by_NID(name, + NID_pkcs9_emailAddress, i)) >= 0) { + ne = X509_NAME_get_entry(name, i); + email = X509_NAME_ENTRY_get_data(ne); + if (!append_ia5(&ret, email)) + return NULL; + } + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != GEN_EMAIL) + continue; + if (!append_ia5(&ret, gen->d.ia5)) + return NULL; + } + return ret; +} + +static void +str_free(OPENSSL_STRING str) +{ + free(str); +} + +static int +append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) +{ + char *emtmp; + + /* First some sanity checks */ + if (email->type != V_ASN1_IA5STRING) + return 1; + if (!email->data || !email->length) + return 1; + if (!*sk) + *sk = sk_OPENSSL_STRING_new(sk_strcmp); + if (!*sk) + return 0; + /* Don't add duplicates */ + if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) + return 1; + emtmp = strdup((char *)email->data); + if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { + X509_email_free(*sk); + *sk = NULL; + return 0; + } + return 1; +} + +void +X509_email_free(STACK_OF(OPENSSL_STRING) *sk) +{ + sk_OPENSSL_STRING_pop_free(sk, str_free); +} +LCRYPTO_ALIAS(X509_email_free); + +typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, unsigned int flags); + +/* Skip pattern prefix to match "wildcard" subject */ +static void +skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject, + size_t subject_len, unsigned int flags) +{ + const unsigned char *pattern = *p; + size_t pattern_len = *plen; + + /* + * If subject starts with a leading '.' followed by more octets, and + * pattern is longer, compare just an equal-length suffix with the + * full subject (starting at the '.'), provided the prefix contains + * no NULs. + */ + if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) + return; + + while (pattern_len > subject_len && *pattern) { + if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && + *pattern == '.') + break; + ++pattern; + --pattern_len; + } + + /* Skip if entire prefix acceptable */ + if (pattern_len == subject_len) { + *p = pattern; + *plen = pattern_len; + } +} + +/* + * Open/BoringSSL uses memcmp for "equal_case" while their + * "equal_nocase" function is a hand-rolled strncasecmp that does not + * allow \0 in the pattern. Since an embedded \0 is likely a sign of + * problems, we simply don't allow it in either case, and then we use + * standard libc functions. + */ + +/* Compare using strncasecmp */ +static int +equal_nocase(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, unsigned int flags) +{ + if (memchr(pattern, '\0', pattern_len) != NULL) + return 0; + if (memchr(subject, '\0', subject_len) != NULL) + return 0; + skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); + if (pattern_len != subject_len) + return 0; + return (strncasecmp(pattern, subject, pattern_len) == 0); +} + +/* Compare using strncmp. */ +static int +equal_case(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, unsigned int flags) +{ + if (memchr(pattern, 0, pattern_len) != NULL) + return 0; + if (memchr(subject, 0, subject_len) != NULL) + return 0; + skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); + if (pattern_len != subject_len) + return 0; + return (strncmp(pattern, subject, pattern_len) == 0); +} + +/* + * RFC 5280, section 7.5, requires that only the domain is compared in a + * case-insensitive manner. + */ +static int +equal_email(const unsigned char *a, size_t a_len, const unsigned char *b, + size_t b_len, unsigned int unused_flags) +{ + size_t pos = a_len; + if (a_len != b_len) + return 0; + /* + * We search backwards for the '@' character, so that we do not have to + * deal with quoted local-parts. The domain part is compared in a + * case-insensitive manner. + */ + while (pos > 0) { + pos--; + if (a[pos] == '@' || b[pos] == '@') { + if (!equal_nocase(a + pos, a_len - pos, b + pos, + a_len - pos, 0)) + return 0; + break; + } + } + if (pos == 0) + pos = a_len; + return equal_case(a, pos, b, pos, 0); +} + +/* + * Compare the prefix and suffix with the subject, and check that the + * characters in-between are valid. + */ +static int +wildcard_match(const unsigned char *prefix, size_t prefix_len, + const unsigned char *suffix, size_t suffix_len, + const unsigned char *subject, size_t subject_len, unsigned int flags) +{ + const unsigned char *wildcard_start; + const unsigned char *wildcard_end; + const unsigned char *p; + int allow_multi = 0; + int allow_idna = 0; + + if (subject_len < prefix_len + suffix_len) + return 0; + if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) + return 0; + wildcard_start = subject + prefix_len; + wildcard_end = subject + (subject_len - suffix_len); + if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) + return 0; + /* + * If the wildcard makes up the entire first label, it must match at + * least one character. + */ + if (prefix_len == 0 && *suffix == '.') { + if (wildcard_start == wildcard_end) + return 0; + allow_idna = 1; + if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) + allow_multi = 1; + } + /* IDNA labels cannot match partial wildcards */ + if (!allow_idna && + subject_len >= 4 + && strncasecmp((char *)subject, "xn--", 4) == 0) + return 0; + /* The wildcard may match a literal '*' */ + if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') + return 1; + /* + * Check that the part matched by the wildcard contains only + * permitted characters and only matches a single label unless + * allow_multi is set. + */ + for (p = wildcard_start; p != wildcard_end; ++p) + if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || + ('a' <= *p && *p <= 'z') || *p == '-' || + (allow_multi && *p == '.'))) + return 0; + return 1; +} + +#define LABEL_START (1 << 0) +#define LABEL_END (1 << 1) +#define LABEL_HYPHEN (1 << 2) +#define LABEL_IDNA (1 << 3) + +static const unsigned char * +valid_star(const unsigned char *p, size_t len, unsigned int flags) +{ + const unsigned char *star = 0; + size_t i; + int state = LABEL_START; + int dots = 0; + for (i = 0; i < len; ++i) { + /* + * Locate first and only legal wildcard, either at the start + * or end of a non-IDNA first and not final label. + */ + if (p[i] == '*') { + int atstart = (state & LABEL_START); + int atend = (i == len - 1 || p[i + 1] == '.'); + /* + * At most one wildcard per pattern. + * No wildcards in IDNA labels. + * No wildcards after the first label. + */ + if (star != NULL || (state & LABEL_IDNA) != 0 || dots) + return NULL; + /* Only full-label '*.example.com' wildcards? */ + if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) + && (!atstart || !atend)) + return NULL; + /* No 'foo*bar' wildcards */ + if (!atstart && !atend) + return NULL; + star = &p[i]; + state &= ~LABEL_START; + } else if ((state & LABEL_START) != 0) { + /* + * At the start of a label, skip any "xn--" and + * remain in the LABEL_START state, but set the + * IDNA label state + */ + if ((state & LABEL_IDNA) == 0 && len - i >= 4 + && strncasecmp((char *)&p[i], "xn--", 4) == 0) { + i += 3; + state |= LABEL_IDNA; + continue; + } + /* Labels must start with a letter or digit */ + state &= ~LABEL_START; + if (('a' <= p[i] && p[i] <= 'z') + || ('A' <= p[i] && p[i] <= 'Z') + || ('0' <= p[i] && p[i] <= '9')) + continue; + return NULL; + } else if (('a' <= p[i] && p[i] <= 'z') + || ('A' <= p[i] && p[i] <= 'Z') + || ('0' <= p[i] && p[i] <= '9')) { + state &= LABEL_IDNA; + continue; + } else if (p[i] == '.') { + if (state & (LABEL_HYPHEN | LABEL_START)) + return NULL; + state = LABEL_START; + ++dots; + } else if (p[i] == '-') { + /* no domain/subdomain starts with '-' */ + if ((state & LABEL_START) != 0) + return NULL; + state |= LABEL_HYPHEN; + } else + return NULL; + } + + /* + * The final label must not end in a hyphen or ".", and + * there must be at least two dots after the star. + */ + if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) + return NULL; + return star; +} + +/* Compare using wildcards. */ +static int +equal_wildcard(const unsigned char *pattern, size_t pattern_len, + const unsigned char *subject, size_t subject_len, unsigned int flags) +{ + const unsigned char *star = NULL; + + /* + * Subject names starting with '.' can only match a wildcard pattern + * via a subject sub-domain pattern suffix match. + */ + if (!(subject_len > 1 && subject[0] == '.')) + star = valid_star(pattern, pattern_len, flags); + if (star == NULL) + return equal_nocase(pattern, pattern_len, + subject, subject_len, flags); + return wildcard_match(pattern, star - pattern, + star + 1, (pattern + pattern_len) - star - 1, + subject, subject_len, flags); +} + +/* + * Compare an ASN1_STRING to a supplied string. If they match return 1. If + * cmp_type > 0 only compare if string matches the type, otherwise convert it + * to UTF8. + */ + +static int +do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, + unsigned int flags, const char *b, size_t blen, char **peername) +{ + int rv = 0; + + if (!a->data || !a->length) + return 0; + if (cmp_type > 0) { + if (cmp_type != a->type) + return 0; + if (cmp_type == V_ASN1_IA5STRING) + rv = equal(a->data, a->length, (unsigned char *)b, + blen, flags); + else if (a->length == (int)blen && !memcmp(a->data, b, blen)) + rv = 1; + if (rv > 0 && peername && + (*peername = strndup((char *)a->data, a->length)) == NULL) + rv = -1; + } else { + int astrlen; + unsigned char *astr = NULL; + astrlen = ASN1_STRING_to_UTF8(&astr, a); + if (astrlen < 0) + return -1; + rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); + if (rv > 0 && peername && + (*peername = strndup((char *)astr, astrlen)) == NULL) + rv = -1; + free(astr); + } + return rv; +} + +static int +do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags, + int check_type, char **peername) +{ + GENERAL_NAMES *gens = NULL; + X509_NAME *name = NULL; + size_t i; + int j; + int cnid = NID_undef; + int alt_type; + int san_present = 0; + int rv = 0; + equal_fn equal; + + /* See below, this flag is internal-only */ + flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; + if (check_type == GEN_EMAIL) { + cnid = NID_pkcs9_emailAddress; + alt_type = V_ASN1_IA5STRING; + equal = equal_email; + } else if (check_type == GEN_DNS) { + if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) + cnid = NID_commonName; + /* Implicit client-side DNS sub-domain pattern */ + if (chklen > 1 && chk[0] == '.') + flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; + alt_type = V_ASN1_IA5STRING; + if (flags & X509_CHECK_FLAG_NO_WILDCARDS) + equal = equal_nocase; + else + equal = equal_wildcard; + } else { + alt_type = V_ASN1_OCTET_STRING; + equal = equal_case; + } + + gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); + if (gens != NULL) { + for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { + GENERAL_NAME *gen; + ASN1_STRING *cstr; + gen = sk_GENERAL_NAME_value(gens, i); + if (gen->type != check_type) + continue; + san_present = 1; + if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; + else if (check_type == GEN_DNS) + cstr = gen->d.dNSName; + else + cstr = gen->d.iPAddress; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, + chk, chklen, peername)) != 0) + break; + } + GENERAL_NAMES_free(gens); + if (rv != 0) + return rv; + if (cnid == NID_undef || + (san_present && + !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) + return 0; + } + + /* We're done if CN-ID is not pertinent */ + if (cnid == NID_undef) + return 0; + + j = -1; + name = X509_get_subject_name(x); + while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { + X509_NAME_ENTRY *ne; + ASN1_STRING *str; + if ((ne = X509_NAME_get_entry(name, j)) == NULL) + return -1; + if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL) + return -1; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(str, -1, equal, flags, + chk, chklen, peername)) != 0) + return rv; + } + return 0; +} + +int +X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, + char **peername) +{ + if (chk == NULL) + return -2; + if (chklen == 0) + chklen = strlen(chk); + else if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); +} +LCRYPTO_ALIAS(X509_check_host); + +int +X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags) +{ + if (chk == NULL) + return -2; + if (chklen == 0) + chklen = strlen(chk); + else if (memchr(chk, '\0', chklen)) + return -2; + return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); +} +LCRYPTO_ALIAS(X509_check_email); + +int +X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags) +{ + if (chk == NULL) + return -2; + return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); +} +LCRYPTO_ALIAS(X509_check_ip); + +int +X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) +{ + unsigned char ipout[16]; + size_t iplen; + + if (ipasc == NULL) + return -2; + iplen = (size_t)a2i_ipadd(ipout, ipasc); + if (iplen == 0) + return -2; + return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); +} +LCRYPTO_ALIAS(X509_check_ip_asc); + +/* Convert IP addresses both IPv4 and IPv6 into an + * OCTET STRING compatible with RFC3280. + */ + +ASN1_OCTET_STRING * +a2i_IPADDRESS(const char *ipasc) +{ + unsigned char ipout[16]; + ASN1_OCTET_STRING *ret; + int iplen; + + /* If string contains a ':' assume IPv6 */ + + iplen = a2i_ipadd(ipout, ipasc); + + if (!iplen) + return NULL; + + ret = ASN1_OCTET_STRING_new(); + if (!ret) + return NULL; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { + ASN1_OCTET_STRING_free(ret); + return NULL; + } + return ret; +} +LCRYPTO_ALIAS(a2i_IPADDRESS); + +ASN1_OCTET_STRING * +a2i_IPADDRESS_NC(const char *ipasc) +{ + ASN1_OCTET_STRING *ret = NULL; + unsigned char ipout[32]; + char *iptmp = NULL, *p; + int iplen1, iplen2; + + p = strchr(ipasc, '/'); + if (!p) + return NULL; + iptmp = strdup(ipasc); + if (!iptmp) + return NULL; + p = iptmp + (p - ipasc); + *p++ = 0; + + iplen1 = a2i_ipadd(ipout, iptmp); + + if (!iplen1) + goto err; + + iplen2 = a2i_ipadd(ipout + iplen1, p); + + free(iptmp); + iptmp = NULL; + + if (!iplen2 || (iplen1 != iplen2)) + goto err; + + ret = ASN1_OCTET_STRING_new(); + if (!ret) + goto err; + if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) + goto err; + + return ret; + + err: + free(iptmp); + if (ret) + ASN1_OCTET_STRING_free(ret); + return NULL; +} +LCRYPTO_ALIAS(a2i_IPADDRESS_NC); + + +int +a2i_ipadd(unsigned char *ipout, const char *ipasc) +{ + /* If string contains a ':' assume IPv6 */ + + if (strchr(ipasc, ':')) { + if (!ipv6_from_asc(ipout, ipasc)) + return 0; + return 16; + } else { + if (!ipv4_from_asc(ipout, ipasc)) + return 0; + return 4; + } +} +LCRYPTO_ALIAS(a2i_ipadd); + +static int +ipv4_from_asc(unsigned char *v4, const char *in) +{ + int a0, a1, a2, a3; + if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) + return 0; + if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || + (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) + return 0; + v4[0] = a0; + v4[1] = a1; + v4[2] = a2; + v4[3] = a3; + return 1; +} + +typedef struct { + /* Temporary store for IPV6 output */ + unsigned char tmp[16]; + /* Total number of bytes in tmp */ + int total; + /* The position of a zero (corresponding to '::') */ + int zero_pos; + /* Number of zeroes */ + int zero_cnt; +} IPV6_STAT; + + +static int +ipv6_from_asc(unsigned char *v6, const char *in) +{ + IPV6_STAT v6stat; + + v6stat.total = 0; + v6stat.zero_pos = -1; + v6stat.zero_cnt = 0; + + /* Treat the IPv6 representation as a list of values + * separated by ':'. The presence of a '::' will parse + * as one, two or three zero length elements. + */ + if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) + return 0; + + /* Now for some sanity checks */ + + if (v6stat.zero_pos == -1) { + /* If no '::' must have exactly 16 bytes */ + if (v6stat.total != 16) + return 0; + } else { + /* If '::' must have less than 16 bytes */ + if (v6stat.total == 16) + return 0; + /* More than three zeroes is an error */ + if (v6stat.zero_cnt > 3) + return 0; + /* Can only have three zeroes if nothing else present */ + else if (v6stat.zero_cnt == 3) { + if (v6stat.total > 0) + return 0; + } + /* Can only have two zeroes if at start or end */ + else if (v6stat.zero_cnt == 2) { + if ((v6stat.zero_pos != 0) && + (v6stat.zero_pos != v6stat.total)) + return 0; + } else + /* Can only have one zero if *not* start or end */ + { + if ((v6stat.zero_pos == 0) || + (v6stat.zero_pos == v6stat.total)) + return 0; + } + } + + /* Format result */ + + if (v6stat.zero_pos >= 0) { + /* Copy initial part */ + memcpy(v6, v6stat.tmp, v6stat.zero_pos); + /* Zero middle */ + memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); + /* Copy final part */ + if (v6stat.total != v6stat.zero_pos) + memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, + v6stat.tmp + v6stat.zero_pos, + v6stat.total - v6stat.zero_pos); + } else + memcpy(v6, v6stat.tmp, 16); + + return 1; +} + +static int +ipv6_cb(const char *elem, int len, void *usr) +{ + IPV6_STAT *s = usr; + + /* Error if 16 bytes written */ + if (s->total == 16) + return 0; + if (len == 0) { + /* Zero length element, corresponds to '::' */ + if (s->zero_pos == -1) + s->zero_pos = s->total; + /* If we've already got a :: its an error */ + else if (s->zero_pos != s->total) + return 0; + s->zero_cnt++; + } else { + /* If more than 4 characters could be final a.b.c.d form */ + if (len > 4) { + /* Need at least 4 bytes left */ + if (s->total > 12) + return 0; + /* Must be end of string */ + if (elem[len]) + return 0; + if (!ipv4_from_asc(s->tmp + s->total, elem)) + return 0; + s->total += 4; + } else { + if (!ipv6_hex(s->tmp + s->total, elem, len)) + return 0; + s->total += 2; + } + } + return 1; +} + +/* Convert a string of up to 4 hex digits into the corresponding + * IPv6 form. + */ + +static int +ipv6_hex(unsigned char *out, const char *in, int inlen) +{ + unsigned char c; + unsigned int num = 0; + + if (inlen > 4) + return 0; + while (inlen--) { + c = *in++; + num <<= 4; + if ((c >= '0') && (c <= '9')) + num |= c - '0'; + else if ((c >= 'A') && (c <= 'F')) + num |= c - 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + num |= c - 'a' + 10; + else + return 0; + } + out[0] = num >> 8; + out[1] = num & 0xff; + return 1; +} + +int +X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, + unsigned long chtype) +{ + CONF_VALUE *v; + int i, mval; + char *p, *type; + + if (!nm) + return 0; + + for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + v = sk_CONF_VALUE_value(dn_sk, i); + type = v->name; + /* Skip past any leading X. X: X, etc to allow for + * multiple instances + */ + for (p = type; *p; p++) + if ((*p == ':') || (*p == ',') || (*p == '.')) { + p++; + if (*p) + type = p; + break; + } + if (*type == '+') { + mval = -1; + type++; + } else + mval = 0; + if (!X509_NAME_add_entry_by_txt(nm, type, chtype, + (unsigned char *) v->value, -1, -1, mval)) + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509V3_NAME_from_section); diff --git a/crypto/x509/x509_v3.c b/crypto/x509/x509_v3.c new file mode 100644 index 0000000..8dddb46 --- /dev/null +++ b/crypto/x509/x509_v3.c @@ -0,0 +1,315 @@ +/* $OpenBSD: x509_v3.c,v 1.21 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +int +X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x) +{ + if (x == NULL) + return (0); + return (sk_X509_EXTENSION_num(x)); +} +LCRYPTO_ALIAS(X509v3_get_ext_count); + +int +X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid, int lastpos) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509v3_get_ext_by_OBJ(x, obj, lastpos)); +} +LCRYPTO_ALIAS(X509v3_get_ext_by_NID); + +int +X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, + const ASN1_OBJECT *obj, int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (OBJ_cmp(ex->object, obj) == 0) + return (lastpos); + } + return (-1); +} +LCRYPTO_ALIAS(X509v3_get_ext_by_OBJ); + +int +X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit, + int lastpos) +{ + int n; + X509_EXTENSION *ex; + + if (sk == NULL) + return (-1); + lastpos++; + if (lastpos < 0) + lastpos = 0; + n = sk_X509_EXTENSION_num(sk); + for (; lastpos < n; lastpos++) { + ex = sk_X509_EXTENSION_value(sk, lastpos); + if (((ex->critical > 0) && crit) || + ((ex->critical <= 0) && !crit)) + return (lastpos); + } + return (-1); +} +LCRYPTO_ALIAS(X509v3_get_ext_by_critical); + +X509_EXTENSION * +X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc) +{ + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) + return NULL; + else + return sk_X509_EXTENSION_value(x, loc); +} +LCRYPTO_ALIAS(X509v3_get_ext); + +X509_EXTENSION * +X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc) +{ + X509_EXTENSION *ret; + + if (x == NULL || sk_X509_EXTENSION_num(x) <= loc || loc < 0) + return (NULL); + ret = sk_X509_EXTENSION_delete(x, loc); + return (ret); +} +LCRYPTO_ALIAS(X509v3_delete_ext); + +STACK_OF(X509_EXTENSION) * +X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, X509_EXTENSION *ex, int loc) +{ + X509_EXTENSION *new_ex = NULL; + int n; + STACK_OF(X509_EXTENSION) *sk = NULL; + + if (x == NULL) { + X509error(ERR_R_PASSED_NULL_PARAMETER); + goto err2; + } + + if (*x == NULL) { + if ((sk = sk_X509_EXTENSION_new_null()) == NULL) + goto err; + } else + sk= *x; + + n = sk_X509_EXTENSION_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + + if ((new_ex = X509_EXTENSION_dup(ex)) == NULL) + goto err2; + if (!sk_X509_EXTENSION_insert(sk, new_ex, loc)) + goto err; + if (*x == NULL) + *x = sk; + return (sk); + +err: + X509error(ERR_R_MALLOC_FAILURE); +err2: + if (new_ex != NULL) + X509_EXTENSION_free(new_ex); + if (sk != NULL && (x != NULL && sk != *x)) + sk_X509_EXTENSION_free(sk); + return (NULL); +} +LCRYPTO_ALIAS(X509v3_add_ext); + +X509_EXTENSION * +X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit, + ASN1_OCTET_STRING *data) +{ + ASN1_OBJECT *obj; + X509_EXTENSION *ret; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509error(X509_R_UNKNOWN_NID); + return (NULL); + } + ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data); + if (ret == NULL) + ASN1_OBJECT_free(obj); + return (ret); +} +LCRYPTO_ALIAS(X509_EXTENSION_create_by_NID); + +X509_EXTENSION * +X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, const ASN1_OBJECT *obj, + int crit, ASN1_OCTET_STRING *data) +{ + X509_EXTENSION *ret; + + if ((ex == NULL) || (*ex == NULL)) { + if ((ret = X509_EXTENSION_new()) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + return (NULL); + } + } else + ret= *ex; + + if (!X509_EXTENSION_set_object(ret, obj)) + goto err; + if (!X509_EXTENSION_set_critical(ret, crit)) + goto err; + if (!X509_EXTENSION_set_data(ret, data)) + goto err; + + if ((ex != NULL) && (*ex == NULL)) + *ex = ret; + return (ret); + +err: + if ((ex == NULL) || (ret != *ex)) + X509_EXTENSION_free(ret); + return (NULL); +} +LCRYPTO_ALIAS(X509_EXTENSION_create_by_OBJ); + +int +X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj) +{ + if ((ex == NULL) || (obj == NULL)) + return (0); + ASN1_OBJECT_free(ex->object); + ex->object = OBJ_dup(obj); + return ex->object != NULL; +} +LCRYPTO_ALIAS(X509_EXTENSION_set_object); + +int +X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit) +{ + if (ex == NULL) + return (0); + ex->critical = (crit) ? 0xFF : -1; + return (1); +} +LCRYPTO_ALIAS(X509_EXTENSION_set_critical); + +int +X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data) +{ + int i; + + if (ex == NULL) + return (0); + i = ASN1_STRING_set(ex->value, data->data, data->length); + if (!i) + return (0); + return (1); +} +LCRYPTO_ALIAS(X509_EXTENSION_set_data); + +ASN1_OBJECT * +X509_EXTENSION_get_object(X509_EXTENSION *ex) +{ + if (ex == NULL) + return (NULL); + return (ex->object); +} +LCRYPTO_ALIAS(X509_EXTENSION_get_object); + +ASN1_OCTET_STRING * +X509_EXTENSION_get_data(X509_EXTENSION *ex) +{ + if (ex == NULL) + return (NULL); + return (ex->value); +} +LCRYPTO_ALIAS(X509_EXTENSION_get_data); + +int +X509_EXTENSION_get_critical(const X509_EXTENSION *ex) +{ + if (ex == NULL) + return (0); + if (ex->critical > 0) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_EXTENSION_get_critical); diff --git a/crypto/x509/x509_verify.c b/crypto/x509/x509_verify.c new file mode 100644 index 0000000..ca4814d --- /dev/null +++ b/crypto/x509/x509_verify.c @@ -0,0 +1,1282 @@ +/* $OpenBSD: x509_verify.c,v 1.66 2023/05/07 07:11:50 tb Exp $ */ +/* + * Copyright (c) 2020-2021 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* x509_verify - inspired by golang's crypto/x509.Verify */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "x509_internal.h" +#include "x509_issuer_cache.h" + +static int x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, + struct x509_verify_chain *current_chain); +static int x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, + char *name); +static void x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, + struct x509_verify_chain *current_chain, int full_chain, char *name); +static int x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, + size_t depth, int error, int ok); +static void x509_verify_chain_free(struct x509_verify_chain *chain); + +/* + * Parse an asn1 to a representable time_t as per RFC 5280 rules. + * Returns -1 if that can't be done for any reason. + */ +time_t +x509_verify_asn1_time_to_time_t(const ASN1_TIME *atime, int notAfter) +{ + struct tm tm = { 0 }; + int type; + + type = ASN1_time_parse(atime->data, atime->length, &tm, atime->type); + if (type == -1) + return -1; + + /* RFC 5280 section 4.1.2.5 */ + if (tm.tm_year < 150 && type != V_ASN1_UTCTIME) + return -1; + if (tm.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME) + return -1; + + if (notAfter) { + /* + * If we are a completely broken operating system with a + * 32 bit time_t, and we have been told this is a notAfter + * date, limit the date to a 32 bit representable value. + */ + if (!ASN1_time_tm_clamp_notafter(&tm)) + return -1; + } + + /* + * Defensively fail if the time string is not representable as + * a time_t. A time_t must be sane if you care about times after + * Jan 19 2038. + */ + return timegm(&tm); +} + +/* + * Cache certificate hash, and values parsed out of an X509. + * called from cache_extensions() + */ +void +x509_verify_cert_info_populate(X509 *cert) +{ + /* + * Parse and save the cert times, or remember that they + * are unacceptable/unparsable. + */ + cert->not_before = x509_verify_asn1_time_to_time_t(X509_get_notBefore(cert), 0); + cert->not_after = x509_verify_asn1_time_to_time_t(X509_get_notAfter(cert), 1); +} + +struct x509_verify_chain * +x509_verify_chain_new(void) +{ + struct x509_verify_chain *chain; + + if ((chain = calloc(1, sizeof(*chain))) == NULL) + goto err; + if ((chain->certs = sk_X509_new_null()) == NULL) + goto err; + if ((chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS, + sizeof(int))) == NULL) + goto err; + if ((chain->names = + x509_constraints_names_new(X509_VERIFY_MAX_CHAIN_NAMES)) == NULL) + goto err; + + return chain; + err: + x509_verify_chain_free(chain); + return NULL; +} + +static void +x509_verify_chain_clear(struct x509_verify_chain *chain) +{ + sk_X509_pop_free(chain->certs, X509_free); + chain->certs = NULL; + free(chain->cert_errors); + chain->cert_errors = NULL; + x509_constraints_names_free(chain->names); + chain->names = NULL; +} + +static void +x509_verify_chain_free(struct x509_verify_chain *chain) +{ + if (chain == NULL) + return; + x509_verify_chain_clear(chain); + free(chain); +} + +static struct x509_verify_chain * +x509_verify_chain_dup(struct x509_verify_chain *chain) +{ + struct x509_verify_chain *new_chain; + + if ((new_chain = calloc(1, sizeof(*chain))) == NULL) + goto err; + if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL) + goto err; + if ((new_chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS, + sizeof(int))) == NULL) + goto err; + memcpy(new_chain->cert_errors, chain->cert_errors, + X509_VERIFY_MAX_CHAIN_CERTS * sizeof(int)); + if ((new_chain->names = + x509_constraints_names_dup(chain->names)) == NULL) + goto err; + return(new_chain); + err: + x509_verify_chain_free(new_chain); + return NULL; +} + +static int +x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert, + int *error) +{ + int verify_err = X509_V_ERR_UNSPECIFIED; + size_t idx; + + if (!x509_constraints_extract_names(chain->names, cert, + sk_X509_num(chain->certs) == 0, &verify_err)) { + *error = verify_err; + return 0; + } + + X509_up_ref(cert); + if (!sk_X509_push(chain->certs, cert)) { + X509_free(cert); + *error = X509_V_ERR_OUT_OF_MEM; + return 0; + } + + idx = sk_X509_num(chain->certs) - 1; + chain->cert_errors[idx] = *error; + + /* + * We've just added the issuer for the previous certificate, + * clear its error if appropriate. + */ + if (idx > 1 && chain->cert_errors[idx - 1] == + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) + chain->cert_errors[idx - 1] = X509_V_OK; + + return 1; +} + +static X509 * +x509_verify_chain_last(struct x509_verify_chain *chain) +{ + int last; + + if (chain->certs == NULL) + return NULL; + if ((last = sk_X509_num(chain->certs) - 1) < 0) + return NULL; + return sk_X509_value(chain->certs, last); +} + +X509 * +x509_verify_chain_leaf(struct x509_verify_chain *chain) +{ + if (chain->certs == NULL) + return NULL; + return sk_X509_value(chain->certs, 0); +} + +static void +x509_verify_ctx_reset(struct x509_verify_ctx *ctx) +{ + size_t i; + + for (i = 0; i < ctx->chains_count; i++) + x509_verify_chain_free(ctx->chains[i]); + sk_X509_pop_free(ctx->saved_error_chain, X509_free); + ctx->saved_error = 0; + ctx->saved_error_depth = 0; + ctx->error = 0; + ctx->error_depth = 0; + ctx->chains_count = 0; + ctx->sig_checks = 0; + ctx->check_time = NULL; +} + +static void +x509_verify_ctx_clear(struct x509_verify_ctx *ctx) +{ + x509_verify_ctx_reset(ctx); + sk_X509_pop_free(ctx->intermediates, X509_free); + free(ctx->chains); + +} + +static int +x509_verify_cert_cache_extensions(X509 *cert) +{ + return x509v3_cache_extensions(cert); +} + +static int +x509_verify_cert_self_signed(X509 *cert) +{ + return (cert->ex_flags & EXFLAG_SS) ? 1 : 0; +} + +/* XXX beck - clean up this mess of is_root */ +static int +x509_verify_check_chain_end(X509 *cert, int full_chain) +{ + if (full_chain) + return x509_verify_cert_self_signed(cert); + return 1; +} + +static int +x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert, + int full_chain) +{ + X509 *match = NULL; + int i; + + if (!x509_verify_cert_cache_extensions(cert)) + return 0; + + /* Check by lookup if we have a legacy xsc */ + if (ctx->xsc != NULL) { + if ((match = x509_vfy_lookup_cert_match(ctx->xsc, + cert)) != NULL) { + X509_free(match); + return x509_verify_check_chain_end(cert, full_chain); + } + } else { + /* Check the provided roots */ + for (i = 0; i < sk_X509_num(ctx->roots); i++) { + if (X509_cmp(sk_X509_value(ctx->roots, i), cert) == 0) + return x509_verify_check_chain_end(cert, + full_chain); + } + } + + return 0; +} + +static int +x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, + struct x509_verify_chain *chain, int set_error, int is_trusted) +{ + size_t num_untrusted; + int i; + + if (ctx->xsc == NULL) + return 1; + + /* + * XXX num_untrusted is the number of untrusted certs at the + * bottom of the chain. This works now since we stop at the first + * trusted cert. This will need fixing once we allow more than one + * trusted certificate. + */ + num_untrusted = sk_X509_num(chain->certs); + if (is_trusted && num_untrusted > 0) + num_untrusted--; + ctx->xsc->num_untrusted = num_untrusted; + + sk_X509_pop_free(ctx->xsc->chain, X509_free); + ctx->xsc->chain = X509_chain_up_ref(chain->certs); + if (ctx->xsc->chain == NULL) + return x509_verify_cert_error(ctx, NULL, 0, + X509_V_ERR_OUT_OF_MEM, 0); + + if (set_error) { + ctx->xsc->error = X509_V_OK; + ctx->xsc->error_depth = 0; + for (i = 0; i < sk_X509_num(chain->certs); i++) { + if (chain->cert_errors[i] != X509_V_OK) { + ctx->xsc->error = chain->cert_errors[i]; + ctx->xsc->error_depth = i; + break; + } + } + } + + return 1; +} + + +/* + * Save the error state and unvalidated chain off of the xsc for + * later. + */ +static int +x509_verify_ctx_save_xsc_error(struct x509_verify_ctx *ctx) +{ + if (ctx->xsc != NULL && ctx->xsc->chain != NULL) { + sk_X509_pop_free(ctx->saved_error_chain, X509_free); + ctx->saved_error_chain = X509_chain_up_ref(ctx->xsc->chain); + if (ctx->saved_error_chain == NULL) + return x509_verify_cert_error(ctx, NULL, 0, + X509_V_ERR_OUT_OF_MEM, 0); + ctx->saved_error = ctx->xsc->error; + ctx->saved_error_depth = ctx->xsc->error_depth; + } + return 1; +} + +/* + * Restore the saved error state and unvalidated chain to the xsc + * if we do not have a validated chain. + */ +static int +x509_verify_ctx_restore_xsc_error(struct x509_verify_ctx *ctx) +{ + if (ctx->xsc != NULL && ctx->chains_count == 0 && + ctx->saved_error_chain != NULL) { + sk_X509_pop_free(ctx->xsc->chain, X509_free); + ctx->xsc->chain = X509_chain_up_ref(ctx->saved_error_chain); + if (ctx->xsc->chain == NULL) + return x509_verify_cert_error(ctx, NULL, 0, + X509_V_ERR_OUT_OF_MEM, 0); + ctx->xsc->error = ctx->saved_error; + ctx->xsc->error_depth = ctx->saved_error_depth; + } + return 1; +} + +/* Perform legacy style validation of a chain */ +static int +x509_verify_ctx_validate_legacy_chain(struct x509_verify_ctx *ctx, + struct x509_verify_chain *chain, size_t depth) +{ + int ret = 0, trust; + + if (ctx->xsc == NULL) + return 1; + + /* + * If we have a legacy xsc, choose a validated chain, and + * apply the extensions, revocation, and policy checks just + * like the legacy code did. We do this here instead of as + * building the chains to more easily support the callback and + * the bewildering array of VERIFY_PARAM knobs that are there + * for the fiddling. + */ + + /* These may be set in one of the following calls. */ + ctx->xsc->error = X509_V_OK; + ctx->xsc->error_depth = 0; + + if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0, 1)) + goto err; + + /* + * Call the legacy code to walk the chain and check trust + * in the legacy way to handle partial chains and get the + * callback fired correctly. + */ + trust = x509_vfy_check_trust(ctx->xsc); + if (trust == X509_TRUST_REJECTED) + goto err; /* callback was called in x509_vfy_check_trust */ + if (trust != X509_TRUST_TRUSTED) { + /* NOTREACHED */ + goto err; /* should not happen if we get in here - abort? */ + } + + /* + * XXX currently this duplicates some work done in chain + * build, but we keep it here until we have feature parity + */ + if (!x509_vfy_check_chain_extensions(ctx->xsc)) + goto err; + +#ifndef OPENSSL_NO_RFC3779 + if (!X509v3_asid_validate_path(ctx->xsc)) + goto err; + + if (!X509v3_addr_validate_path(ctx->xsc)) + goto err; +#endif + + if (!x509_vfy_check_security_level(ctx->xsc)) + goto err; + + if (!x509_constraints_chain(ctx->xsc->chain, + &ctx->xsc->error, &ctx->xsc->error_depth)) { + X509 *cert = sk_X509_value(ctx->xsc->chain, depth); + if (!x509_verify_cert_error(ctx, cert, + ctx->xsc->error_depth, ctx->xsc->error, 0)) + goto err; + } + + if (!x509_vfy_check_revocation(ctx->xsc)) + goto err; + + if (!x509_vfy_check_policy(ctx->xsc)) + goto err; + + ret = 1; + + err: + /* + * The above checks may have set ctx->xsc->error and + * ctx->xsc->error_depth - save these for later on. + */ + if (ctx->xsc->error != X509_V_OK) { + if (ctx->xsc->error_depth < 0 || + ctx->xsc->error_depth >= X509_VERIFY_MAX_CHAIN_CERTS) + return 0; + chain->cert_errors[ctx->xsc->error_depth] = + ctx->xsc->error; + ctx->error_depth = ctx->xsc->error_depth; + } + + return ret; +} + +/* Add a validated chain to our list of valid chains */ +static int +x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx, + struct x509_verify_chain *chain, char *name) +{ + size_t depth; + X509 *last = x509_verify_chain_last(chain); + X509 *leaf = x509_verify_chain_leaf(chain); + + depth = sk_X509_num(chain->certs); + if (depth > 0) + depth--; + + if (ctx->chains_count >= ctx->max_chains) + return x509_verify_cert_error(ctx, last, depth, + X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); + + /* Clear a get issuer failure for a root certificate. */ + if (chain->cert_errors[depth] == + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) + chain->cert_errors[depth] = X509_V_OK; + + if (!x509_verify_ctx_validate_legacy_chain(ctx, chain, depth)) + return 0; + + /* Verify the leaf certificate and store any resulting error. */ + if (!x509_verify_cert_valid(ctx, leaf, NULL)) + return 0; + if (!x509_verify_cert_hostname(ctx, leaf, name)) + return 0; + if (ctx->error_depth == 0 && + ctx->error != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) + chain->cert_errors[0] = ctx->error; + + /* + * In the non-legacy code, extensions and purpose are dealt + * with as the chain is built. + * + * The non-legacy api returns multiple chains but does not do + * any revocation checking (it must be done by the caller on + * any chain they wish to use) + */ + + if ((ctx->chains[ctx->chains_count] = x509_verify_chain_dup(chain)) == + NULL) { + return x509_verify_cert_error(ctx, last, depth, + X509_V_ERR_OUT_OF_MEM, 0); + } + ctx->chains_count++; + + ctx->error = X509_V_OK; + ctx->error_depth = depth; + + return 1; +} + +static int +x509_verify_potential_parent(struct x509_verify_ctx *ctx, X509 *parent, + X509 *child) +{ + if (!x509_verify_cert_cache_extensions(parent)) + return 0; + if (ctx->xsc != NULL) + return (ctx->xsc->check_issued(ctx->xsc, child, parent)); + + /* XXX key usage */ + return X509_check_issued(child, parent) != X509_V_OK; +} + +static int +x509_verify_parent_signature(X509 *parent, X509 *child, int *error) +{ + EVP_PKEY *pkey; + int cached; + int ret = 0; + + /* Use cached value if we have it */ + if ((cached = x509_issuer_cache_find(parent->hash, child->hash)) >= 0) + return cached; + + /* Check signature. Did parent sign child? */ + if ((pkey = X509_get_pubkey(parent)) == NULL) { + *error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + return 0; + } + if (X509_verify(child, pkey) <= 0) + *error = X509_V_ERR_CERT_SIGNATURE_FAILURE; + else + ret = 1; + + /* Add result to cache */ + x509_issuer_cache_add(parent->hash, child->hash, ret); + + EVP_PKEY_free(pkey); + + return ret; +} + +static int +x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert, + int is_root_cert, X509 *candidate, struct x509_verify_chain *current_chain, + int full_chain, char *name) +{ + int depth = sk_X509_num(current_chain->certs); + struct x509_verify_chain *new_chain; + int i; + + /* Fail if the certificate is already in the chain */ + for (i = 0; i < sk_X509_num(current_chain->certs); i++) { + if (X509_cmp(sk_X509_value(current_chain->certs, i), + candidate) == 0) + return 0; + } + + if (ctx->sig_checks++ > X509_VERIFY_MAX_SIGCHECKS) { + /* don't allow callback to override safety check */ + (void) x509_verify_cert_error(ctx, candidate, depth, + X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); + return 0; + } + + if (!x509_verify_parent_signature(candidate, cert, &ctx->error)) { + if (!x509_verify_cert_error(ctx, candidate, depth, + ctx->error, 0)) + return 0; + } + + if (!x509_verify_cert_valid(ctx, candidate, current_chain)) + return 0; + + /* candidate is good, add it to a copy of the current chain */ + if ((new_chain = x509_verify_chain_dup(current_chain)) == NULL) { + x509_verify_cert_error(ctx, candidate, depth, + X509_V_ERR_OUT_OF_MEM, 0); + return 0; + } + if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) { + x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0); + x509_verify_chain_free(new_chain); + return 0; + } + + /* + * If candidate is a trusted root, we have a validated chain, + * so we save it. Otherwise, recurse until we find a root or + * give up. + */ + if (is_root_cert) { + if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0, 1)) { + x509_verify_chain_free(new_chain); + return 0; + } + if (!x509_verify_ctx_add_chain(ctx, new_chain, name)) { + x509_verify_chain_free(new_chain); + return 0; + } + goto done; + } + + x509_verify_build_chains(ctx, candidate, new_chain, full_chain, name); + + done: + x509_verify_chain_free(new_chain); + return 1; +} + +static int +x509_verify_cert_error(struct x509_verify_ctx *ctx, X509 *cert, size_t depth, + int error, int ok) +{ + ctx->error = error; + ctx->error_depth = depth; + if (ctx->xsc != NULL) { + ctx->xsc->error = error; + ctx->xsc->error_depth = depth; + ctx->xsc->current_cert = cert; + return ctx->xsc->verify_cb(ok, ctx->xsc); + } + return ok; +} + +static void +x509_verify_build_chains(struct x509_verify_ctx *ctx, X509 *cert, + struct x509_verify_chain *current_chain, int full_chain, char *name) +{ + X509 *candidate; + int i, depth, count, ret, is_root; + + /* + * If we are finding chains with an xsc, just stop after we have + * one chain, there's no point in finding more, it just exercises + * the potentially buggy callback processing in the calling software. + */ + if (ctx->xsc != NULL && ctx->chains_count > 0) + return; + + depth = sk_X509_num(current_chain->certs); + if (depth > 0) + depth--; + + if (depth >= ctx->max_depth && + !x509_verify_cert_error(ctx, cert, depth, + X509_V_ERR_CERT_CHAIN_TOO_LONG, 0)) + return; + + count = ctx->chains_count; + + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; + ctx->error_depth = depth; + + if (ctx->saved_error != 0) + ctx->error = ctx->saved_error; + if (ctx->saved_error_depth != 0) + ctx->error_depth = ctx->saved_error_depth; + + if (ctx->xsc != NULL) { + /* + * Long ago experiments at Muppet labs resulted in a + * situation where software not only sees these errors + * but forced developers to expect them in certain cases. + * so we must mimic this awfulness for the legacy case. + */ + if (cert->ex_flags & EXFLAG_SS) + ctx->error = (depth == 0) ? + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; + } + + /* Check for legacy mode roots */ + if (ctx->xsc != NULL) { + if ((ret = ctx->xsc->get_issuer(&candidate, ctx->xsc, cert)) < 0) { + x509_verify_cert_error(ctx, cert, depth, + X509_V_ERR_STORE_LOOKUP, 0); + return; + } + if (ret > 0) { + if (x509_verify_potential_parent(ctx, candidate, cert)) { + is_root = x509_verify_check_chain_end(candidate, + full_chain); + x509_verify_consider_candidate(ctx, cert, + is_root, candidate, current_chain, + full_chain, name); + } + X509_free(candidate); + } + } else { + /* Check to see if we have a trusted root issuer. */ + for (i = 0; i < sk_X509_num(ctx->roots); i++) { + candidate = sk_X509_value(ctx->roots, i); + if (x509_verify_potential_parent(ctx, candidate, cert)) { + is_root = x509_verify_check_chain_end(candidate, + full_chain); + x509_verify_consider_candidate(ctx, cert, + is_root, candidate, current_chain, + full_chain, name); + } + } + } + + /* Check intermediates after checking roots */ + if (ctx->intermediates != NULL) { + for (i = 0; i < sk_X509_num(ctx->intermediates); i++) { + candidate = sk_X509_value(ctx->intermediates, i); + if (x509_verify_potential_parent(ctx, candidate, cert)) { + x509_verify_consider_candidate(ctx, cert, + 0, candidate, current_chain, + full_chain, name); + } + } + } + + if (ctx->chains_count > count) { + if (ctx->xsc != NULL) { + ctx->xsc->error = X509_V_OK; + ctx->xsc->error_depth = depth; + ctx->xsc->current_cert = cert; + } + } else if (ctx->error_depth == depth) { + if (!x509_verify_ctx_set_xsc_chain(ctx, current_chain, 0, 0)) + return; + } +} + +static int +x509_verify_cert_hostname(struct x509_verify_ctx *ctx, X509 *cert, char *name) +{ + char *candidate; + size_t len; + + if (name == NULL) { + if (ctx->xsc != NULL) { + int ret; + + if ((ret = x509_vfy_check_id(ctx->xsc)) == 0) + ctx->error = ctx->xsc->error; + return ret; + } + return 1; + } + if ((candidate = strdup(name)) == NULL) { + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if ((len = strlen(candidate)) < 1) { + ctx->error = X509_V_ERR_UNSPECIFIED; /* XXX */ + goto err; + } + + /* IP addresses may be written in [ ]. */ + if (candidate[0] == '[' && candidate[len - 1] == ']') { + candidate[len - 1] = '\0'; + if (X509_check_ip_asc(cert, candidate + 1, 0) <= 0) { + ctx->error = X509_V_ERR_IP_ADDRESS_MISMATCH; + goto err; + } + } else { + int flags = 0; + + if (ctx->xsc == NULL) + flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; + + if (X509_check_host(cert, candidate, len, flags, NULL) <= 0) { + ctx->error = X509_V_ERR_HOSTNAME_MISMATCH; + goto err; + } + } + free(candidate); + return 1; + err: + free(candidate); + return x509_verify_cert_error(ctx, cert, 0, ctx->error, 0); +} + +static int +x509_verify_set_check_time(struct x509_verify_ctx *ctx) +{ + if (ctx->xsc != NULL) { + if (ctx->xsc->param->flags & X509_V_FLAG_USE_CHECK_TIME) { + ctx->check_time = &ctx->xsc->param->check_time; + return 1; + } + if (ctx->xsc->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 0; + } + + ctx->check_time = NULL; + return 1; +} + +static int +x509_verify_cert_times(X509 *cert, time_t *cmp_time, int *error) +{ + time_t when; + + if (cmp_time == NULL) + when = time(NULL); + else + when = *cmp_time; + + if (cert->not_before == -1) { + *error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD; + return 0; + } + if (when < cert->not_before) { + *error = X509_V_ERR_CERT_NOT_YET_VALID; + return 0; + } + if (cert->not_after == -1) { + *error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD; + return 0; + } + if (when > cert->not_after) { + *error = X509_V_ERR_CERT_HAS_EXPIRED; + return 0; + } + + return 1; +} + +static int +x509_verify_validate_constraints(X509 *cert, + struct x509_verify_chain *current_chain, int *error) +{ + struct x509_constraints_names *excluded = NULL; + struct x509_constraints_names *permitted = NULL; + int err = X509_V_ERR_UNSPECIFIED; + + if (current_chain == NULL) + return 1; + + if (cert->nc != NULL) { + if ((permitted = x509_constraints_names_new( + X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { + err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if ((excluded = x509_constraints_names_new( + X509_VERIFY_MAX_CHAIN_CONSTRAINTS)) == NULL) { + err = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!x509_constraints_extract_constraints(cert, + permitted, excluded, &err)) + goto err; + if (!x509_constraints_check(current_chain->names, + permitted, excluded, &err)) + goto err; + x509_constraints_names_free(excluded); + x509_constraints_names_free(permitted); + } + + return 1; + err: + *error = err; + x509_constraints_names_free(excluded); + x509_constraints_names_free(permitted); + return 0; +} + +static int +x509_verify_cert_extensions(struct x509_verify_ctx *ctx, X509 *cert, int need_ca) +{ + if (!x509_verify_cert_cache_extensions(cert)) { + ctx->error = X509_V_ERR_UNSPECIFIED; + return 0; + } + + if (ctx->xsc != NULL) + return 1; /* legacy is checked after chain is built */ + + if (cert->ex_flags & EXFLAG_CRITICAL) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + return 0; + } + /* No we don't care about v1, netscape, and other ancient silliness */ + if (need_ca && (!(cert->ex_flags & EXFLAG_BCONS) && + (cert->ex_flags & EXFLAG_CA))) { + ctx->error = X509_V_ERR_INVALID_CA; + return 0; + } + if (ctx->purpose > 0 && X509_check_purpose(cert, ctx->purpose, need_ca)) { + ctx->error = X509_V_ERR_INVALID_PURPOSE; + return 0; + } + + return 1; +} + +/* Validate that cert is a possible candidate to append to current_chain */ +static int +x509_verify_cert_valid(struct x509_verify_ctx *ctx, X509 *cert, + struct x509_verify_chain *current_chain) +{ + X509 *issuer_candidate; + int should_be_ca = current_chain != NULL; + size_t depth = 0; + + if (current_chain != NULL) + depth = sk_X509_num(current_chain->certs); + + if (!x509_verify_cert_extensions(ctx, cert, should_be_ca)) + return 0; + + if (should_be_ca) { + issuer_candidate = x509_verify_chain_last(current_chain); + if (issuer_candidate != NULL && + !X509_check_issued(issuer_candidate, cert)) + if (!x509_verify_cert_error(ctx, cert, depth, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH, 0)) + return 0; + } + + if (x509_verify_set_check_time(ctx)) { + if (!x509_verify_cert_times(cert, ctx->check_time, + &ctx->error)) { + if (!x509_verify_cert_error(ctx, cert, depth, + ctx->error, 0)) + return 0; + } + } + + if (!x509_verify_validate_constraints(cert, current_chain, + &ctx->error) && !x509_verify_cert_error(ctx, cert, depth, + ctx->error, 0)) + return 0; + + return 1; +} + +struct x509_verify_ctx * +x509_verify_ctx_new_from_xsc(X509_STORE_CTX *xsc) +{ + struct x509_verify_ctx *ctx; + size_t max_depth; + + if (xsc == NULL) + return NULL; + + if ((ctx = x509_verify_ctx_new(NULL)) == NULL) + return NULL; + + ctx->xsc = xsc; + + if (xsc->untrusted && + (ctx->intermediates = X509_chain_up_ref(xsc->untrusted)) == NULL) + goto err; + + max_depth = X509_VERIFY_MAX_CHAIN_CERTS; + if (xsc->param->depth > 0 && xsc->param->depth < X509_VERIFY_MAX_CHAIN_CERTS) + max_depth = xsc->param->depth; + if (!x509_verify_ctx_set_max_depth(ctx, max_depth)) + goto err; + + return ctx; + err: + x509_verify_ctx_free(ctx); + return NULL; +} + +/* Public API */ + +struct x509_verify_ctx * +x509_verify_ctx_new(STACK_OF(X509) *roots) +{ + struct x509_verify_ctx *ctx; + + if ((ctx = calloc(1, sizeof(struct x509_verify_ctx))) == NULL) + return NULL; + + if (roots != NULL) { + if ((ctx->roots = X509_chain_up_ref(roots)) == NULL) + goto err; + } else { + if ((ctx->roots = sk_X509_new_null()) == NULL) + goto err; + } + + ctx->max_depth = X509_VERIFY_MAX_CHAIN_CERTS; + ctx->max_chains = X509_VERIFY_MAX_CHAINS; + ctx->max_sigs = X509_VERIFY_MAX_SIGCHECKS; + + if ((ctx->chains = calloc(X509_VERIFY_MAX_CHAINS, + sizeof(*ctx->chains))) == NULL) + goto err; + + return ctx; + err: + x509_verify_ctx_free(ctx); + return NULL; +} + +void +x509_verify_ctx_free(struct x509_verify_ctx *ctx) +{ + if (ctx == NULL) + return; + sk_X509_pop_free(ctx->roots, X509_free); + x509_verify_ctx_clear(ctx); + free(ctx); +} + +int +x509_verify_ctx_set_max_depth(struct x509_verify_ctx *ctx, size_t max) +{ + if (max < 1 || max > X509_VERIFY_MAX_CHAIN_CERTS) + return 0; + ctx->max_depth = max; + return 1; +} + +int +x509_verify_ctx_set_max_chains(struct x509_verify_ctx *ctx, size_t max) +{ + if (max < 1 || max > X509_VERIFY_MAX_CHAINS) + return 0; + ctx->max_chains = max; + return 1; +} + +int +x509_verify_ctx_set_max_signatures(struct x509_verify_ctx *ctx, size_t max) +{ + if (max < 1 || max > 100000) + return 0; + ctx->max_sigs = max; + return 1; +} + +int +x509_verify_ctx_set_purpose(struct x509_verify_ctx *ctx, int purpose) +{ + if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX) + return 0; + ctx->purpose = purpose; + return 1; +} + +int +x509_verify_ctx_set_intermediates(struct x509_verify_ctx *ctx, + STACK_OF(X509) *intermediates) +{ + if ((ctx->intermediates = X509_chain_up_ref(intermediates)) == NULL) + return 0; + return 1; +} + +const char * +x509_verify_ctx_error_string(struct x509_verify_ctx *ctx) +{ + return X509_verify_cert_error_string(ctx->error); +} + +size_t +x509_verify_ctx_error_depth(struct x509_verify_ctx *ctx) +{ + return ctx->error_depth; +} + +STACK_OF(X509) * +x509_verify_ctx_chain(struct x509_verify_ctx *ctx, size_t i) +{ + if (i >= ctx->chains_count) + return NULL; + return ctx->chains[i]->certs; +} + +size_t +x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) +{ + struct x509_verify_chain *current_chain; + int retry_chain_build, full_chain = 0; + + if (ctx->roots == NULL || ctx->max_depth == 0) { + ctx->error = X509_V_ERR_INVALID_CALL; + goto err; + } + + if (ctx->xsc != NULL) { + if (leaf != NULL || name != NULL) { + ctx->error = X509_V_ERR_INVALID_CALL; + goto err; + } + leaf = ctx->xsc->cert; + + /* XXX */ + full_chain = 1; + if (ctx->xsc->param->flags & X509_V_FLAG_PARTIAL_CHAIN) + full_chain = 0; + /* + * XXX + * The legacy code expects the top level cert to be + * there, even if we didn't find a chain. So put it + * there, we will clobber it later if we find a valid + * chain. + */ + if ((ctx->xsc->chain = sk_X509_new_null()) == NULL) { + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!X509_up_ref(leaf)) { + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + if (!sk_X509_push(ctx->xsc->chain, leaf)) { + X509_free(leaf); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + ctx->xsc->error_depth = 0; + ctx->xsc->current_cert = leaf; + } + + if ((current_chain = x509_verify_chain_new()) == NULL) { + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto err; + } + + /* + * Add the leaf to the chain and try to build chains from it. + * Note that unlike Go's verifier, we have not yet checked + * anything about the leaf, This is intentional, so that we + * report failures in chain building before we report problems + * with the leaf. + */ + if (!x509_verify_chain_append(current_chain, leaf, &ctx->error)) { + x509_verify_chain_free(current_chain); + goto err; + } + do { + retry_chain_build = 0; + if (x509_verify_ctx_cert_is_root(ctx, leaf, full_chain)) { + if (!x509_verify_ctx_add_chain(ctx, current_chain, + name)) { + x509_verify_chain_free(current_chain); + goto err; + } + } else { + x509_verify_build_chains(ctx, leaf, current_chain, + full_chain, name); + if (full_chain && ctx->chains_count == 0) { + /* + * Save the error state from the xsc + * at this point to put back on the + * xsc in case we do not find a chain + * that is trusted but not a full + * chain to a self signed root. This + * is because the unvalidated chain is + * used by the autochain batshittery + * on failure and will be needed for + * that. + */ + ctx->xsc->error_depth = ctx->error_depth; + if (!x509_verify_ctx_save_xsc_error(ctx)) { + x509_verify_chain_free(current_chain); + goto err; + } + full_chain = 0; + retry_chain_build = 1; + } + } + } while (retry_chain_build); + + x509_verify_chain_free(current_chain); + + /* + * Do the new verifier style return, where we don't have an xsc + * that allows a crazy callback to turn invalid things into valid. + */ + if (ctx->xsc == NULL) { + /* + * Safety net: + * We could not find a validated chain, and for some reason do not + * have an error set. + */ + if (ctx->chains_count == 0 && ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + + /* + * If we are not using an xsc, and have no possibility for the + * crazy OpenSSL callback API changing the results of + * validation steps (because the callback can make validation + * proceed in the presence of invalid certs), any chains we + * have here are correctly built and verified. + */ + if (ctx->chains_count > 0) + ctx->error = X509_V_OK; + + return ctx->chains_count; + } + + /* + * Otherwise we are doing compatibility with an xsc, which means that we + * will have one chain, which might actually be a bogus chain because + * the callback told us to ignore errors and proceed to build an invalid + * chain. Possible return values from this include returning 1 with an + * invalid chain and a value of xsc->error != X509_V_OK (It's tradition + * that makes it ok). + */ + + if (ctx->chains_count > 0) { + /* + * The chain we have using an xsc might not be a verified chain + * if the callback perverted things while we built it to ignore + * failures and proceed with chain building. We put this chain + * and the error associated with it on the xsc. + */ + if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1, 1)) + goto err; + + /* + * Call the callback for completion up our built + * chain. The callback could still tell us to + * fail. Since this chain might exist as the result of + * callback doing perversions, we could still return + * "success" with something other than X509_V_OK set + * as the error. + */ + if (!x509_vfy_callback_indicate_completion(ctx->xsc)) + goto err; + } else { + /* + * We did not find a chain. Bring back the failure + * case we wanted to the xsc if we saved one. If we + * did not we should have just the leaf on the xsc. + */ + if (!x509_verify_ctx_restore_xsc_error(ctx)) + goto err; + + /* + * Safety net, ensure we have an error set in the + * failing case. + */ + if (ctx->xsc->error == X509_V_OK) { + if (ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + ctx->xsc->error = ctx->error; + } + + /* + * Let the callback override the return value + * at depth 0 if it chooses to + */ + return ctx->xsc->verify_cb(0, ctx->xsc); + } + + /* We only ever find one chain in compat mode with an xsc. */ + return 1; + + err: + if (ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + + if (ctx->xsc != NULL) { + if (ctx->xsc->error == X509_V_OK) + ctx->xsc->error = X509_V_ERR_UNSPECIFIED; + ctx->error = ctx->xsc->error; + } + + return 0; +} diff --git a/crypto/x509/x509_verify.h b/crypto/x509/x509_verify.h new file mode 100644 index 0000000..d8d2cb0 --- /dev/null +++ b/crypto/x509/x509_verify.h @@ -0,0 +1,43 @@ +/* $OpenBSD: x509_verify.h,v 1.2 2021/11/04 23:52:34 beck Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef HEADER_X509_VERIFY_H +#define HEADER_X509_VERIFY_H + +#ifdef LIBRESSL_INTERNAL +struct x509_verify_ctx; +struct x509_verify_cert_info; +typedef struct x509_verify_ctx X509_VERIFY_CTX; + +X509_VERIFY_CTX *x509_verify_ctx_new(STACK_OF(X509) *roots); +void x509_verify_ctx_free(struct x509_verify_ctx *ctx); + +int x509_verify_ctx_set_max_depth(X509_VERIFY_CTX *ctx, size_t max); +int x509_verify_ctx_set_max_chains(X509_VERIFY_CTX *ctx, size_t max); +int x509_verify_ctx_set_max_signatures(X509_VERIFY_CTX *ctx, size_t max); +int x509_verify_ctx_set_purpose(X509_VERIFY_CTX *ctx, int purpose_id); +int x509_verify_ctx_set_intermediates(X509_VERIFY_CTX *ctx, + STACK_OF(X509) *intermediates); + +const char *x509_verify_ctx_error_string(X509_VERIFY_CTX *ctx); +size_t x509_verify_ctx_error_depth(X509_VERIFY_CTX *ctx); + +STACK_OF(X509) *x509_verify_ctx_chain(X509_VERIFY_CTX *ctx, size_t chain); + +size_t x509_verify(X509_VERIFY_CTX *ctx, X509 *leaf, char *name); +#endif + +#endif diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c new file mode 100644 index 0000000..c4ba3d5 --- /dev/null +++ b/crypto/x509/x509_vfy.c @@ -0,0 +1,2719 @@ +/* $OpenBSD: x509_vfy.c,v 1.125 2023/06/08 22:02:40 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "asn1_local.h" +#include "x509_internal.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 + +static int null_callback(int ok, X509_STORE_CTX *e); +static int check_issued(X509_STORE_CTX *ctx, X509 *subject, X509 *issuer); +static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x, + int allow_expired); +static int check_chain_extensions(X509_STORE_CTX *ctx); +static int check_name_constraints(X509_STORE_CTX *ctx); +static int check_trust(X509_STORE_CTX *ctx); +static int check_revocation(X509_STORE_CTX *ctx); +static int check_cert(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, int depth); +static int check_policy(X509_STORE_CTX *ctx); + +static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, + unsigned int *preasons, X509_CRL *crl, X509 *x); +static int get_crl_delta(X509_STORE_CTX *ctx, + X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x); +static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score, + X509_CRL *base, STACK_OF(X509_CRL) *crls); +static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer, + int *pcrl_score); +static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score, + unsigned int *preasons); +static int check_crl_path(X509_STORE_CTX *ctx, X509 *x); +static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *cert_path, + STACK_OF(X509) *crl_path); +static int X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, + int clamp_notafter); + +static int internal_verify(X509_STORE_CTX *ctx); +static int get_trusted_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); +static int check_key_level(X509_STORE_CTX *ctx, X509 *cert); +static int verify_cb_cert(X509_STORE_CTX *ctx, X509 *x, int depth, int err); + +int ASN1_time_tm_clamp_notafter(struct tm *tm); + +static int +null_callback(int ok, X509_STORE_CTX *e) +{ + return ok; +} + +/* Return 1 if a certificate is self signed */ +static int +cert_self_signed(X509 *x) +{ + X509_check_purpose(x, -1, 0); + if (x->ex_flags & EXFLAG_SS) + return 1; + else + return 0; +} + +static int +check_id_error(X509_STORE_CTX *ctx, int errcode) +{ + ctx->error = errcode; + ctx->current_cert = ctx->cert; + ctx->error_depth = 0; + return ctx->verify_cb(0, ctx); +} + +static int +check_hosts(X509 *x, X509_VERIFY_PARAM *vpm) +{ + int i, n; + char *name; + + n = sk_OPENSSL_STRING_num(vpm->hosts); + free(vpm->peername); + vpm->peername = NULL; + + for (i = 0; i < n; ++i) { + name = sk_OPENSSL_STRING_value(vpm->hosts, i); + if (X509_check_host(x, name, strlen(name), vpm->hostflags, + &vpm->peername) > 0) + return 1; + } + return n == 0; +} + +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 (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) + return 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 != 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; +} + +int +x509_vfy_check_id(X509_STORE_CTX *ctx) { + return check_id(ctx); +} + +/* + * This is the effectively broken legacy OpenSSL chain builder. It + * might find an unvalidated chain and leave it sitting in + * ctx->chain. It does not correctly handle many cases where multiple + * chains could exist. + * + * Oh no.. I know a dirty word... + * Oooooooh.. + */ +static int +X509_verify_cert_legacy_build_chain(X509_STORE_CTX *ctx, int *bad, int *out_ok) +{ + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; + int bad_chain = 0; + X509_VERIFY_PARAM *param = ctx->param; + int ok = 0, ret = 0; + int depth, i; + int num, j, retry, trust; + int (*cb) (int xok, X509_STORE_CTX *xctx); + STACK_OF(X509) *sktmp = NULL; + + cb = ctx->verify_cb; + + /* + * First we make sure the chain we are going to build is + * present and that the first entry is in place. + */ + ctx->chain = sk_X509_new_null(); + if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) { + X509error(ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + X509_up_ref(ctx->cert); + ctx->num_untrusted = 1; + + /* We use a temporary STACK so we can chop and hack at it */ + if (ctx->untrusted != NULL && + (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) { + X509error(ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + goto end; + } + + num = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, num - 1); + depth = param->depth; + + for (;;) { + /* If we have enough, we break */ + /* FIXME: If this happens, we should take + * note of it and, if appropriate, use the + * X509_V_ERR_CERT_CHAIN_TOO_LONG error code + * later. + */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + /* + * If asked see if we can find issuer in trusted store first + */ + if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + /* + * If successful for now free up cert so it + * will be picked up again later. + */ + if (ok > 0) { + X509_free(xtmp); + break; + } + } + /* If we were passed a cert chain, use it first */ + if (ctx->untrusted != NULL) { + /* + * If we do not find a non-expired untrusted cert, peek + * ahead and see if we can satisfy this from the trusted + * store. If not, see if we have an expired untrusted cert. + */ + xtmp = find_issuer(ctx, sktmp, x, 0); + if (xtmp == NULL && + !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)) { + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + if (ok > 0) { + X509_free(xtmp); + break; + } + xtmp = find_issuer(ctx, sktmp, x, 1); + } + if (xtmp != NULL) { + if (!sk_X509_push(ctx->chain, xtmp)) { + X509error(ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + X509_up_ref(xtmp); + (void)sk_X509_delete_ptr(sktmp, xtmp); + ctx->num_untrusted++; + x = xtmp; + num++; + /* + * reparse the full chain for the next one + */ + continue; + } + } + break; + } + /* Remember how many untrusted certs we have */ + j = num; + + /* + * At this point, chain should contain a list of untrusted + * certificates. We now need to add at least one trusted one, + * if possible, otherwise we complain. + */ + + do { + /* + * Examine last certificate in chain and see if it is + * self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (cert_self_signed(x)) { + /* we have a self signed certificate */ + if (i == 1) { + /* + * We have a single self signed + * certificate: see if we can find it + * in the store. We must have an exact + * match to avoid possible + * impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert = x; + ctx->error_depth = i - 1; + if (ok == 1) + X509_free(xtmp); + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } else { + /* + * We have a match: replace + * certificate with store + * version so we get any trust + * settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->num_untrusted = 0; + } + } else { + /* + * extract and save self signed + * certificate for later use + */ + chain_ss = sk_X509_pop(ctx->chain); + ctx->num_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); + } + } + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); + + if (ok < 0) { + ctx->error = X509_V_ERR_STORE_LOOKUP; + goto end; + } + if (ok == 0) + break; + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + X509error(ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + num++; + } + + /* we now have our chain, lets check it... */ + trust = check_trust(ctx); + + /* If explicitly rejected error */ + if (trust == X509_TRUST_REJECTED) { + ok = 0; + goto end; + } + /* + * If it's not explicitly trusted then check if there + * is an alternative chain that could be used. We only + * do this if we haven't already checked via + * TRUSTED_FIRST and the user hasn't switched off + * alternate chain checking + */ + retry = 0; + if (trust != X509_TRUST_TRUSTED && + !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) && + !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + xtmp2 = sk_X509_value(ctx->chain, j - 1); + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + if (ok < 0) + goto end; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert + * we'll add it again later + */ + X509_free(xtmp); + /* + * Dump all the certs above + * this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + } + ctx->num_untrusted = sk_X509_num(ctx->chain); + retry = 1; + break; + } + } + } + } while (retry); + + /* + * If not explicitly trusted then indicate error unless it's a single + * self signed certificate in which case we've indicated an error already + * and set bad_chain == 1 + */ + if (trust != X509_TRUST_TRUSTED && !bad_chain) { + if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) { + if (ctx->num_untrusted >= num) + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; + else + ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT; + ctx->current_cert = x; + } else { + if (!sk_X509_push(ctx->chain, chain_ss)) { + X509error(ERR_R_MALLOC_FAILURE); + ctx->error = X509_V_ERR_OUT_OF_MEM; + ok = 0; + goto end; + } + num++; + ctx->num_untrusted = num; + ctx->current_cert = chain_ss; + ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; + chain_ss = NULL; + } + + ctx->error_depth = num - 1; + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } + + ret = 1; + end: + sk_X509_free(sktmp); + X509_free(chain_ss); + *bad = bad_chain; + *out_ok = ok; + + return ret; +} + +static int +X509_verify_cert_legacy(X509_STORE_CTX *ctx) +{ + int ok = 0, bad_chain; + + ctx->error = X509_V_OK; /* Initialize to OK */ + + if (!X509_verify_cert_legacy_build_chain(ctx, &bad_chain, &ok)) + goto end; + + /* We have the chain complete: now we need to check its purpose */ + ok = check_chain_extensions(ctx); + if (!ok) + goto end; + + /* Check that the chain satisfies the security level. */ + ok = x509_vfy_check_security_level(ctx); + if (!ok) + goto end; + + /* Check name constraints */ + ok = check_name_constraints(ctx); + if (!ok) + goto end; + +#ifndef OPENSSL_NO_RFC3779 + ok = X509v3_asid_validate_path(ctx); + if (!ok) + goto end; + + ok = X509v3_addr_validate_path(ctx); + if (!ok) + goto end; +#endif + + ok = check_id(ctx); + if (!ok) + goto end; + + /* + * Check revocation status: we do this after copying parameters because + * they may be needed for CRL signature verification. + */ + ok = ctx->check_revocation(ctx); + if (!ok) + goto end; + + /* At this point, we have a chain and need to verify it */ + if (ctx->verify != NULL) + ok = ctx->verify(ctx); + else + ok = internal_verify(ctx); + if (!ok) + goto end; + + /* If we get this far evaluate policies */ + if (!bad_chain) + ok = ctx->check_policy(ctx); + + end: + /* Safety net, error returns must set ctx->error */ + if (ok <= 0 && ctx->error == X509_V_OK) + ctx->error = X509_V_ERR_UNSPECIFIED; + + return ok; +} + +int +X509_verify_cert(X509_STORE_CTX *ctx) +{ + struct x509_verify_ctx *vctx = NULL; + int chain_count = 0; + + if (ctx->cert == NULL) { + X509error(X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->chain != NULL) { + /* + * This X509_STORE_CTX has already been used to verify + * a cert. We cannot do another one. + */ + X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->param->poisoned) { + /* + * This X509_STORE_CTX had failures setting + * up verify parameters. We can not use it. + */ + X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + if (ctx->error != X509_V_ERR_INVALID_CALL) { + /* + * This X509_STORE_CTX has not been properly initialized. + */ + X509error(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + ctx->error = X509_V_ERR_INVALID_CALL; + return -1; + } + + /* + * If the certificate's public key is too weak, don't bother + * continuing. + */ + if (!check_key_level(ctx, ctx->cert) && + !verify_cb_cert(ctx, ctx->cert, 0, X509_V_ERR_EE_KEY_TOO_SMALL)) + return 0; + + /* + * If flags request legacy, use the legacy verifier. If we + * requested "no alt chains" from the age of hammer pants, use + * the legacy verifier because the multi chain verifier really + * does find all the "alt chains". + * + * XXX deprecate the NO_ALT_CHAINS flag? + */ + if ((ctx->param->flags & X509_V_FLAG_LEGACY_VERIFY) || + (ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) + return X509_verify_cert_legacy(ctx); + + /* Use the modern multi-chain verifier from x509_verify_cert */ + + if ((vctx = x509_verify_ctx_new_from_xsc(ctx)) != NULL) { + ctx->error = X509_V_OK; /* Initialize to OK */ + chain_count = x509_verify(vctx, NULL, NULL); + } + x509_verify_ctx_free(vctx); + + /* if we succeed we have a chain in ctx->chain */ + return (chain_count > 0 && ctx->chain != NULL); +} +LCRYPTO_ALIAS(X509_verify_cert); + +/* Given a STACK_OF(X509) find the issuer of cert (if any) + */ + +static X509 * +find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x, + int allow_expired) +{ + int i; + X509 *issuer, *rv = NULL; + + for (i = 0; i < sk_X509_num(sk); i++) { + issuer = sk_X509_value(sk, i); + if (ctx->check_issued(ctx, x, issuer)) { + if (x509_check_cert_time(ctx, issuer, -1)) + return issuer; + if (allow_expired) + rv = issuer; + } + } + return rv; +} + +/* Given a possible certificate and issuer check them */ + +static int +check_issued(X509_STORE_CTX *ctx, X509 *subject, X509 *issuer) +{ + /* + * Yes, the arguments of X509_STORE_CTX_check_issued_fn were exposed in + * reverse order compared to the already public X509_check_issued()... + */ + return X509_check_issued(issuer, subject) == X509_V_OK; +} + +/* Alternative lookup method: look from a STACK stored in ctx->trusted */ + +static int +get_trusted_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) +{ + *issuer = find_issuer(ctx, ctx->trusted, x, 1); + if (*issuer) { + CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509); + return 1; + } else + return 0; +} + +/* Check a certificate chains extensions for consistency + * with the supplied purpose + */ + +int +x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx) +{ +#ifdef OPENSSL_NO_CHAIN_VERIFY + return 1; +#else + int i, ok = 0, must_be_ca, plen = 0; + X509 *x; + int (*cb)(int xok, X509_STORE_CTX *xctx); + int proxy_path_length = 0; + int purpose; + + cb = ctx->verify_cb; + + /* must_be_ca can have 1 of 3 values: + -1: we accept both CA and non-CA certificates, to allow direct + use of self-signed certificates (which are marked as CA). + 0: we only accept non-CA certificates. This is currently not + used, but the possibility is present for future extensions. + 1: we only accept CA certificates. This is currently used for + all certificates in the chain except the leaf certificate. + */ + must_be_ca = -1; + + /* CRL path validation */ + if (ctx->parent) + purpose = X509_PURPOSE_CRL_SIGN; + else + purpose = ctx->param->purpose; + + /* Check all untrusted certificates */ + for (i = 0; i < ctx->num_untrusted; i++) { + int ret; + x = sk_X509_value(ctx->chain, i); + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && + (x->ex_flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + ret = X509_check_ca(x); + if (must_be_ca == -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; + } else { + if ((ret == 0) || + ((ctx->param->flags & X509_V_FLAG_X509_STRICT) && + (ret != 1))) { + ret = 0; + ctx->error = X509_V_ERR_INVALID_CA; + } else + ret = 1; + } + if (ret == 0) { + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + if (ctx->param->purpose > 0) { + ret = X509_check_purpose(x, purpose, must_be_ca > 0); + if ((ret == 0) || + ((ctx->param->flags & X509_V_FLAG_X509_STRICT) && + (ret != 1))) { + ctx->error = X509_V_ERR_INVALID_PURPOSE; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + } + /* Check pathlen if not self issued */ + if ((i > 1) && !(x->ex_flags & EXFLAG_SI) && + (x->ex_pathlen != -1) && + (plen > (x->ex_pathlen + proxy_path_length + 1))) { + ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED; + ctx->error_depth = i; + ctx->current_cert = x; + ok = cb(0, ctx); + if (!ok) + goto end; + } + /* Increment path length if not self issued */ + if (!(x->ex_flags & EXFLAG_SI)) + plen++; + must_be_ca = 1; + } + ok = 1; + +end: + return ok; +#endif +} + +static int +check_chain_extensions(X509_STORE_CTX *ctx) { + return x509_vfy_check_chain_extensions(ctx); +} + +static int +check_name_constraints(X509_STORE_CTX *ctx) +{ + if (!x509_constraints_chain(ctx->chain, &ctx->error, + &ctx->error_depth)) { + ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth); + if (!ctx->verify_cb(0, ctx)) + return 0; + } + return 1; +} + +/* Given a certificate try and find an exact match in the store */ + +static X509 * +lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) +{ + STACK_OF(X509) *certs; + X509 *xtmp = NULL; + size_t i; + + /* Lookup all certs with matching subject name */ + certs = ctx->lookup_certs(ctx, X509_get_subject_name(x)); + if (certs == NULL) + return NULL; + + /* Look for exact match */ + for (i = 0; i < sk_X509_num(certs); i++) { + xtmp = sk_X509_value(certs, i); + if (!X509_cmp(xtmp, x)) + break; + } + + if (i < sk_X509_num(certs)) + X509_up_ref(xtmp); + else + xtmp = NULL; + + sk_X509_pop_free(certs, X509_free); + return xtmp; +} + +X509 * +x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) +{ + if (ctx->lookup_certs == NULL || ctx->store == NULL || + ctx->store->objs == NULL) + return NULL; + return lookup_cert_match(ctx, x); +} + +static int +check_trust(X509_STORE_CTX *ctx) +{ + size_t i; + int ok; + X509 *x = NULL; + int (*cb) (int xok, X509_STORE_CTX *xctx); + + cb = ctx->verify_cb; + /* Check all trusted certificates in chain */ + for (i = ctx->num_untrusted; i < sk_X509_num(ctx->chain); i++) { + x = sk_X509_value(ctx->chain, i); + ok = X509_check_trust(x, ctx->param->trust, 0); + + /* If explicitly trusted return trusted */ + if (ok == X509_TRUST_TRUSTED) + return X509_TRUST_TRUSTED; + /* + * If explicitly rejected notify callback and reject if not + * overridden. + */ + if (ok == X509_TRUST_REJECTED) { + ctx->error_depth = i; + ctx->current_cert = x; + ctx->error = X509_V_ERR_CERT_REJECTED; + ok = cb(0, ctx); + if (!ok) + return X509_TRUST_REJECTED; + } + } + /* + * If we accept partial chains and have at least one trusted certificate + * return success. + */ + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + X509 *mx; + if (ctx->num_untrusted < (int)sk_X509_num(ctx->chain)) + return X509_TRUST_TRUSTED; + x = sk_X509_value(ctx->chain, 0); + mx = lookup_cert_match(ctx, x); + if (mx) { + (void)sk_X509_set(ctx->chain, 0, mx); + X509_free(x); + ctx->num_untrusted = 0; + return X509_TRUST_TRUSTED; + } + } + + /* + * If no trusted certs in chain at all return untrusted and allow + * standard (no issuer cert) etc errors to be indicated. + */ + return X509_TRUST_UNTRUSTED; +} + +int +x509_vfy_check_trust(X509_STORE_CTX *ctx) +{ + return check_trust(ctx); +} + +static int +check_revocation(X509_STORE_CTX *ctx) +{ + int i, last, ok; + + if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) + return 1; + if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) + last = sk_X509_num(ctx->chain) - 1; + else { + /* If checking CRL paths this isn't the EE certificate */ + if (ctx->parent) + return 1; + last = 0; + } + for (i = 0; i <= last; i++) { + ok = check_cert(ctx, ctx->chain, i); + if (!ok) + return ok; + } + return 1; +} + +int +x509_vfy_check_revocation(X509_STORE_CTX *ctx) +{ + return check_revocation(ctx); +} + +static int +check_cert(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, int depth) +{ + X509_CRL *crl = NULL, *dcrl = NULL; + X509 *x; + int ok = 0, cnum; + unsigned int last_reasons; + + cnum = ctx->error_depth = depth; + x = sk_X509_value(chain, cnum); + ctx->current_cert = x; + ctx->current_issuer = NULL; + ctx->current_crl_score = 0; + ctx->current_reasons = 0; + while (ctx->current_reasons != CRLDP_ALL_REASONS) { + last_reasons = ctx->current_reasons; + /* Try to retrieve relevant CRL */ + if (ctx->get_crl) + 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 (!ok) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + ctx->current_crl = crl; + ok = ctx->check_crl(ctx, crl); + if (!ok) + goto err; + + if (dcrl) { + ok = ctx->check_crl(ctx, dcrl); + if (!ok) + goto err; + ok = ctx->cert_crl(ctx, dcrl, x); + if (!ok) + goto err; + } else + ok = 1; + + /* Don't look in full CRL if delta reason is removefromCRL */ + if (ok != 2) { + ok = ctx->cert_crl(ctx, crl, x); + if (!ok) + goto err; + } + + ctx->current_crl = NULL; + X509_CRL_free(crl); + X509_CRL_free(dcrl); + crl = NULL; + dcrl = NULL; + /* If reasons not updated we wont get anywhere by + * another iteration, so exit loop. + */ + if (last_reasons == ctx->current_reasons) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL; + ok = ctx->verify_cb(0, ctx); + goto err; + } + } + +err: + ctx->current_crl = NULL; + X509_CRL_free(crl); + X509_CRL_free(dcrl); + return ok; +} + +/* 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 (notify) + ctx->current_crl = crl; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return (1); + else + ptime = NULL; + + i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime); + if (i == 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (i > 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_CRL_NOT_YET_VALID; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + + if (X509_CRL_get_nextUpdate(crl)) { + i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime); + + if (i == 0) { + if (!notify) + return 0; + ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD; + if (!ctx->verify_cb(0, ctx)) + 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; + ctx->error = X509_V_ERR_CRL_HAS_EXPIRED; + if (!ctx->verify_cb(0, ctx)) + return 0; + } + } + + if (notify) + ctx->current_crl = NULL; + + return 1; +} + +static int +get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, + X509 **pissuer, int *pscore, unsigned int *preasons, + STACK_OF(X509_CRL) *crls) +{ + int i, crl_score, best_score = *pscore; + unsigned int reasons, best_reasons = 0; + X509 *x = ctx->current_cert; + X509_CRL *crl, *best_crl = NULL; + X509 *crl_issuer = NULL, *best_crl_issuer = NULL; + + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + crl = sk_X509_CRL_value(crls, i); + reasons = *preasons; + crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x); + + if (crl_score > best_score) { + best_crl = crl; + best_crl_issuer = crl_issuer; + best_score = crl_score; + best_reasons = reasons; + } + } + + if (best_crl) { + if (*pcrl) + X509_CRL_free(*pcrl); + *pcrl = best_crl; + *pissuer = best_crl_issuer; + *pscore = best_score; + *preasons = best_reasons; + CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL); + if (*pdcrl) { + X509_CRL_free(*pdcrl); + *pdcrl = NULL; + } + get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); + } + + if (best_score >= CRL_SCORE_VALID) + return 1; + + return 0; +} + +/* 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); + 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) + return 1; + + if (!exta || !extb) + return 0; + + if (ASN1_OCTET_STRING_cmp(exta, extb)) + return 0; + + return 1; +} + +/* 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) + return 0; + /* Base must have a CRL number */ + if (!base->crl_number) + return 0; + /* Issuer names must match */ + if (X509_NAME_cmp(X509_CRL_get_issuer(base), + X509_CRL_get_issuer(delta))) + return 0; + /* AKID and IDP must match */ + if (!crl_extension_match(delta, base, NID_authority_key_identifier)) + return 0; + if (!crl_extension_match(delta, base, NID_issuing_distribution_point)) + return 0; + /* Delta CRL base number must not exceed Full CRL number. */ + 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; +} + +/* 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)) + return; + if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST)) + return; + for (i = 0; i < sk_X509_CRL_num(crls); i++) { + delta = sk_X509_CRL_value(crls, i); + if (check_delta_base(delta, base)) { + if (check_crl_time(ctx, delta, 0)) + *pscore |= CRL_SCORE_TIME_DELTA; + CRYPTO_add(&delta->references, 1, CRYPTO_LOCK_X509_CRL); + *dcrl = delta; + return; + } + } + *dcrl = NULL; +} + +/* For a given CRL return how suitable it is for the supplied certificate 'x'. + * The return value is a mask of several criteria. + * If the issuer is not the certificate issuer this is returned in *pissuer. + * The reasons mask is 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) + return 0; + /* Reason codes or indirect CRLs need extended CRL support */ + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) { + if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) + return 0; + } else if (crl->idp_flags & IDP_REASONS) { + /* If no new reasons reject */ + if (!(crl->idp_reasons & ~tmp_reasons)) + return 0; + } + /* Don't process deltas at this stage */ + else if (crl->base_crl_number) + 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)) + return 0; + } else + crl_score |= CRL_SCORE_ISSUER_NAME; + + if (!(crl->flags & EXFLAG_CRITICAL)) + crl_score |= CRL_SCORE_NOCRITICAL; + + /* Check expiry */ + if (check_crl_time(ctx, crl, 0)) + crl_score |= CRL_SCORE_TIME; + + /* Check authority key ID and locate certificate issuer */ + 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)) + 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)) + return 0; + tmp_reasons |= crl_reasons; + crl_score |= CRL_SCORE_SCOPE; + } + + *preasons = tmp_reasons; + + return crl_score; +} + +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); + int cidx = ctx->error_depth; + int i; + + if (cidx != sk_X509_num(ctx->chain) - 1) + cidx++; + + crl_issuer = sk_X509_value(ctx->chain, cidx); + + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + if (*pcrl_score & CRL_SCORE_ISSUER_NAME) { + *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT; + *pissuer = crl_issuer; + return; + } + } + + for (cidx++; cidx < sk_X509_num(ctx->chain); cidx++) { + crl_issuer = sk_X509_value(ctx->chain, cidx); + if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH; + *pissuer = crl_issuer; + return; + } + } + + /* Anything else needs extended CRL support */ + + if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) + return; + + /* Otherwise the CRL issuer is not on the path. Look for it in the + * set of untrusted certificates. + */ + 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)) + continue; + if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) { + *pissuer = crl_issuer; + *pcrl_score |= CRL_SCORE_AKID; + return; + } + } +} + +/* Check the path of a CRL issuer certificate. This creates a new + * X509_STORE_CTX and populates it with most of the parameters from the + * 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; + int ret; + + /* Don't allow recursive CRL path validation */ + if (ctx->parent) + return 0; + if (!X509_STORE_CTX_init(&crl_ctx, ctx->store, x, ctx->untrusted)) { + ret = -1; + goto err; + } + + crl_ctx.crls = ctx->crls; + /* Copy verify params across */ + X509_STORE_CTX_set0_param(&crl_ctx, ctx->param); + + crl_ctx.parent = ctx; + crl_ctx.verify_cb = ctx->verify_cb; + + /* Verify CRL issuer */ + ret = X509_verify_cert(&crl_ctx); + + if (ret <= 0) + goto err; + + /* Check chain is acceptable */ + ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain); + +err: + X509_STORE_CTX_cleanup(&crl_ctx); + return ret; +} + +/* 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 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; +} + +/* Check for match between two dist point names: three separate cases. + * 1. Both are relative names and compare X509_NAME types. + * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES. + * 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) + return 1; + if (a->type == 1) { + if (!a->dpname) + 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 + return 0; + } + /* Case 2: set name and GENERAL_NAMES appropriately */ + nm = a->dpname; + gens = b->name.fullname; + } else if (b->type == 1) { + if (!b->dpname) + return 0; + /* Case 2: set name and GENERAL_NAMES appropriately */ + gens = a->name.fullname; + nm = b->dpname; + } + + /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */ + if (nm) { + 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)) + return 1; + } + return 0; + } + + /* Else case 3: two GENERAL_NAMES */ + + for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) { + 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)) + return 1; + } + } + + return 0; +} + +static int +crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score) +{ + int i; + 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); + 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)) + 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) + return 0; + if (x->ex_flags & EXFLAG_CA) { + if (crl->idp_flags & IDP_ONLYUSER) + return 0; + } else { + if (crl->idp_flags & IDP_ONLYCA) + 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)) { + *preasons &= dp->dp_reasons; + return 1; + } + } + } + if ((!crl->idp || !crl->idp->distpoint) && + (crl_score & CRL_SCORE_ISSUER_NAME)) + return 1; + return 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) +{ + int ok; + X509 *issuer = NULL; + int crl_score = 0; + unsigned int reasons; + X509_CRL *crl = NULL, *dcrl = NULL; + STACK_OF(X509_CRL) *skcrl; + X509_NAME *nm = X509_get_issuer_name(x); + + reasons = ctx->current_reasons; + ok = get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, + ctx->crls); + if (ok) + 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) + goto done; + + get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl); + + sk_X509_CRL_pop_free(skcrl, X509_CRL_free); + +done: + + /* If we got any kind of CRL use it and return success */ + if (crl) { + ctx->current_issuer = issuer; + ctx->current_crl_score = crl_score; + ctx->current_reasons = reasons; + *pcrl = crl; + *pdcrl = dcrl; + return 1; + } + + return 0; +} + +/* Check CRL validity */ +static int +check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) +{ + X509 *issuer = NULL; + EVP_PKEY *ikey = NULL; + int ok = 0, chnum, cnum; + + cnum = ctx->error_depth; + chnum = sk_X509_num(ctx->chain) - 1; + /* if we have an alternative CRL issuer cert use that */ + if (ctx->current_issuer) { + issuer = ctx->current_issuer; + } else if (cnum < chnum) { + /* + * Else find CRL issuer: if not last certificate then issuer + * is next certificate in chain. + */ + issuer = sk_X509_value(ctx->chain, cnum + 1); + } else { + issuer = sk_X509_value(ctx->chain, chnum); + /* If not self signed, can't check signature */ + if (!ctx->check_issued(ctx, issuer, issuer)) { + ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + + if (issuer) { + /* Skip most tests for deltas because they have already + * been done + */ + if (!crl->base_crl_number) { + /* Check for cRLSign bit if keyUsage present */ + if ((issuer->ex_flags & EXFLAG_KUSAGE) && + !(issuer->ex_kusage & KU_CRL_SIGN)) { + ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) { + ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) { + if (check_crl_path(ctx, + ctx->current_issuer) <= 0) { + ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + + if (crl->idp_flags & IDP_INVALID) { + ctx->error = X509_V_ERR_INVALID_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + + + } + + if (!(ctx->current_crl_score & CRL_SCORE_TIME)) { + ok = check_crl_time(ctx, crl, 1); + if (!ok) + goto err; + } + + /* Attempt to get issuer certificate public key */ + ikey = X509_get_pubkey(issuer); + + if (!ikey) { + ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } else { + /* Verify CRL signature */ + if (X509_CRL_verify(crl, ikey) <= 0) { + ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE; + ok = ctx->verify_cb(0, ctx); + if (!ok) + goto err; + } + } + } + + ok = 1; + +err: + EVP_PKEY_free(ikey); + return ok; +} + +/* Check certificate against CRL */ +static int +cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) +{ + int ok; + X509_REVOKED *rev; + + /* The rules changed for this... previously if a CRL contained + * unhandled critical extensions it could still be used to indicate + * a certificate was revoked. This has since been changed since + * critical extension can change the meaning of CRL entries. + */ + if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && + (crl->flags & EXFLAG_CRITICAL)) { + ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; + ok = ctx->verify_cb(0, ctx); + if (!ok) + return 0; + } + /* Look for serial number of certificate in CRL + * If found make sure reason is not removeFromCRL. + */ + if (X509_CRL_get0_by_cert(crl, &rev, x)) { + if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) + return 2; + ctx->error = X509_V_ERR_CERT_REVOKED; + ok = ctx->verify_cb(0, ctx); + if (!ok) + return 0; + } + + return 1; +} + +int +x509_vfy_check_policy(X509_STORE_CTX *ctx) +{ + X509 *current_cert = NULL; + int ret; + + if (ctx->parent != NULL) + return 1; + + ret = X509_policy_check(ctx->chain, ctx->param->policies, + ctx->param->flags, ¤t_cert); + if (ret != X509_V_OK) { + ctx->current_cert = current_cert; + ctx->error = ret; + if (ret == X509_V_ERR_OUT_OF_MEM) + return 0; + return ctx->verify_cb(0, ctx); + } + + if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) { + ctx->current_cert = NULL; + /* + * Verification errors need to be "sticky", a callback may have + * allowed an SSL handshake to continue despite an error, and + * we must then remain in an error state. Therefore, we MUST + * NOT clear earlier verification errors by setting the error + * to X509_V_OK. + */ + if (!ctx->verify_cb(2, ctx)) + return 0; + } + + return 1; +} + +static int +check_policy(X509_STORE_CTX *ctx) +{ + return x509_vfy_check_policy(ctx); +} + +/* + * Inform the verify callback of an error. + * + * If x is not NULL it is the error cert, otherwise use the chain cert + * at depth. + * + * If err is not X509_V_OK, that's the error value, otherwise leave + * unchanged (presumably set by the caller). + * + * 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; + 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); +} + + +/* Mimic OpenSSL '0 for failure' ick */ +static int +time_t_bogocmp(time_t a, time_t b) +{ + if (a == -1 || b == -1) + return 0; + if (a <= b) + return -1; + return 1; +} + +/* + * Check certificate validity times. + * + * If depth >= 0, invoke verification callbacks on error, otherwise just return + * the validation status. + * + * Return 1 on success, 0 otherwise. + */ +int +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) + ptime = ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; + else + ptime = time(NULL); + + if (x->ex_flags & EXFLAG_SET) + i = time_t_bogocmp(x->not_before, ptime); + else + i = X509_cmp_time(X509_get_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; + + if (x->ex_flags & EXFLAG_SET) + i = time_t_bogocmp(x->not_after, ptime); + else + i = X509_cmp_time_internal(X509_get_notAfter(x), &ptime, 1); + + 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; + + return 1; +} + +static int +x509_vfy_internal_verify(X509_STORE_CTX *ctx, int chain_verified) +{ + int n = sk_X509_num(ctx->chain) - 1; + X509 *xi = sk_X509_value(ctx->chain, n); + X509 *xs; + + if (ctx->check_issued(ctx, xi, xi)) + xs = xi; + else { + if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) { + xs = xi; + goto check_cert; + } + if (n <= 0) + return verify_cb_cert(ctx, xi, 0, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); + n--; + ctx->error_depth = n; + xs = sk_X509_value(ctx->chain, n); + } + + /* + * Do not clear ctx->error=0, it must be "sticky", only the + * user's callback is allowed to reset errors (at its own + * peril). + */ + while (n >= 0) { + + /* + * Skip signature check for self signed certificates + * unless explicitly asked for. It doesn't add any + * security and just wastes time. If the issuer's + * public key is unusable, report the issuer + * certificate and its depth (rather than the depth of + * the subject). + */ + if (!chain_verified && ( xs != xi || + (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE))) { + EVP_PKEY *pkey; + if ((pkey = X509_get_pubkey(xi)) == NULL) { + if (!verify_cb_cert(ctx, xi, xi != xs ? n+1 : n, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)) + return 0; + } else if (X509_verify(xs, pkey) <= 0) { + if (!verify_cb_cert(ctx, xs, n, + X509_V_ERR_CERT_SIGNATURE_FAILURE)) { + EVP_PKEY_free(pkey); + return 0; + } + } + EVP_PKEY_free(pkey); + } +check_cert: + /* Calls verify callback as needed */ + if (!chain_verified && !x509_check_cert_time(ctx, xs, n)) + return 0; + + /* + * Signal success at this depth. However, the + * previous error (if any) is retained. + */ + ctx->current_issuer = xi; + ctx->current_cert = xs; + ctx->error_depth = n; + if (!ctx->verify_cb(1, ctx)) + return 0; + + if (--n >= 0) { + xi = xs; + xs = sk_X509_value(ctx->chain, n); + } + } + return 1; +} + +static int +internal_verify(X509_STORE_CTX *ctx) +{ + return x509_vfy_internal_verify(ctx, 0); +} + +/* + * Internal verify, but with a chain where the verification + * math has already been performed. + */ +int +x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx) +{ + return x509_vfy_internal_verify(ctx, 1); +} + +int +X509_cmp_current_time(const ASN1_TIME *ctm) +{ + return X509_cmp_time(ctm, NULL); +} +LCRYPTO_ALIAS(X509_cmp_current_time); + +/* + * Compare a possibly unvalidated ASN1_TIME string against a time_t + * using RFC 5280 rules for the time string. If *cmp_time is NULL + * the current system time is used. + * + * XXX NOTE that unlike what you expect a "cmp" function to do in C, + * XXX this one is "special", and returns 0 for error. + * + * Returns: + * -1 if the ASN1_time is earlier than OR the same as *cmp_time. + * 1 if the ASN1_time is later than *cmp_time. + * 0 on error. + */ +static int +X509_cmp_time_internal(const ASN1_TIME *ctm, time_t *cmp_time, int is_notafter) +{ + time_t compare, cert_time; + + if (cmp_time == NULL) + compare = time(NULL); + else + compare = *cmp_time; + + if ((cert_time = x509_verify_asn1_time_to_time_t(ctm, is_notafter)) == + -1) + return 0; /* invalid time */ + + if (cert_time <= compare) + return -1; /* 0 is used for error, so map same to less than */ + + return 1; +} + +int +X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) +{ + return X509_cmp_time_internal(ctm, cmp_time, 0); +} +LCRYPTO_ALIAS(X509_cmp_time); + + +ASN1_TIME * +X509_gmtime_adj(ASN1_TIME *s, long adj) +{ + return X509_time_adj(s, adj, NULL); +} +LCRYPTO_ALIAS(X509_gmtime_adj); + +ASN1_TIME * +X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_time) +{ + return X509_time_adj_ex(s, 0, offset_sec, in_time); +} +LCRYPTO_ALIAS(X509_time_adj); + +ASN1_TIME * +X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec, time_t *in_time) +{ + time_t t; + if (in_time == NULL) + t = time(NULL); + else + t = *in_time; + + return ASN1_TIME_adj(s, t, offset_day, offset_sec); +} +LCRYPTO_ALIAS(X509_time_adj_ex); + +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)) + return 1; + + for (i = 0; i < sk_X509_num(chain); i++) { + ktmp = X509_get0_pubkey(sk_X509_value(chain, i)); + if (ktmp == NULL) { + X509error(X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY); + return 0; + } + if (!EVP_PKEY_missing_parameters(ktmp)) + break; + else + ktmp = NULL; + } + if (ktmp == NULL) { + X509error(X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN); + return 0; + } + + /* first, populate the other certs */ + for (j = i - 1; j >= 0; j--) { + if ((ktmp2 = X509_get0_pubkey(sk_X509_value(chain, j))) == NULL) + return 0; + if (!EVP_PKEY_copy_parameters(ktmp2, ktmp)) + return 0; + } + + if (pkey != NULL) + if (!EVP_PKEY_copy_parameters(pkey, ktmp)) + return 0; + return 1; +} +LCRYPTO_ALIAS(X509_get_pubkey_parameters); + +int +X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + /* This function is (usually) called only once, by + * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */ + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, + argl, argp, new_func, dup_func, free_func); +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_ex_new_index); + +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); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_ex_data); + +void * +X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) +{ + return CRYPTO_get_ex_data(&ctx->ex_data, idx); +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_ex_data); + +int +X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) +{ + return ctx->error; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_error); + +void +X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) +{ + ctx->error = err; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_error); + +int +X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) +{ + return ctx->error_depth; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_error_depth); + +void +X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth) +{ + ctx->error_depth = depth; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_error_depth); + +X509 * +X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) +{ + return ctx->current_cert; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_current_cert); + +void +X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->current_cert = x; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_current_cert); + +STACK_OF(X509) * +X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) +{ + return ctx->chain; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_chain); + +STACK_OF(X509) * +X509_STORE_CTX_get0_chain(X509_STORE_CTX *xs) +{ + return xs->chain; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_chain); + +STACK_OF(X509) * +X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) +{ + int i; + X509 *x; + STACK_OF(X509) *chain; + + if (!ctx->chain || !(chain = sk_X509_dup(ctx->chain))) + return NULL; + for (i = 0; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + } + return chain; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get1_chain); + +X509 * +X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) +{ + return ctx->current_issuer; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_current_issuer); + +X509_CRL * +X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) +{ + return ctx->current_crl; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_current_crl); + +X509_STORE_CTX * +X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) +{ + return ctx->parent; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_parent_ctx); + +X509_STORE * +X509_STORE_CTX_get0_store(X509_STORE_CTX *xs) +{ + return xs->store; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_store); + +void +X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) +{ + ctx->cert = x; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_cert); + +void +X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->untrusted = sk; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_chain); + +void +X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) +{ + ctx->crls = sk; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set0_crls); + +int +X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) +{ + return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_purpose); + +int +X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) +{ + return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_trust); + +/* This function is used to set the X509_STORE_CTX purpose and trust + * values. This is intended to be used when another structure has its + * own trust and purpose values which (if set) will be inherited by + * the ctx. If they aren't set then we will usually have a default + * purpose in mind which should then be used to set the trust value. + * An example of this is SSL use: an SSL structure will have its own + * purpose and trust settings which the 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) + purpose = def_purpose; + /* If we have a purpose then check it is valid */ + if (purpose) { + X509_PURPOSE *ptmp; + idx = X509_PURPOSE_get_by_id(purpose); + if (idx == -1) { + X509error(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) { + X509error(X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = X509_PURPOSE_get0(idx); + } + /* If trust not set then get from purpose default */ + if (!trust) + trust = ptmp->trust; + } + if (trust) { + idx = X509_TRUST_get_by_id(trust); + if (idx == -1) { + X509error(X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if (purpose && !ctx->param->purpose) + ctx->param->purpose = purpose; + if (trust && !ctx->param->trust) + ctx->param->trust = trust; + return 1; +} +LCRYPTO_ALIAS(X509_STORE_CTX_purpose_inherit); + +X509_STORE_CTX * +X509_STORE_CTX_new(void) +{ + X509_STORE_CTX *ctx; + + ctx = calloc(1, sizeof(X509_STORE_CTX)); + if (!ctx) { + X509error(ERR_R_MALLOC_FAILURE); + return NULL; + } + return ctx; +} +LCRYPTO_ALIAS(X509_STORE_CTX_new); + +void +X509_STORE_CTX_free(X509_STORE_CTX *ctx) +{ + if (ctx == NULL) + return; + + X509_STORE_CTX_cleanup(ctx); + free(ctx); +} +LCRYPTO_ALIAS(X509_STORE_CTX_free); + +int +X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *leaf, + STACK_OF(X509) *untrusted) +{ + int param_ret = 1; + + /* + * Make sure everything is initialized properly even in case of an + * early return due to an error. + * + * While this 'ctx' can be reused, X509_STORE_CTX_cleanup() will have + * freed everything and memset ex_data anyway. This also allows us + * to safely use X509_STORE_CTX variables from the stack which will + * have uninitialized data. + */ + memset(ctx, 0, sizeof(*ctx)); + + /* + * Start with this set to not valid - it will be set to valid + * in X509_verify_cert. + */ + ctx->error = X509_V_ERR_INVALID_CALL; + + /* + * Set values other than 0. Keep this in the same order as + * X509_STORE_CTX except for values that may fail. All fields that + * may fail should go last to make sure 'ctx' is as consistent as + * possible even on early exits. + */ + ctx->store = store; + ctx->cert = leaf; + ctx->untrusted = untrusted; + + if (store && store->verify) + ctx->verify = store->verify; + else + ctx->verify = internal_verify; + + if (store && store->verify_cb) + ctx->verify_cb = store->verify_cb; + else + ctx->verify_cb = null_callback; + + if (store && store->get_issuer) + ctx->get_issuer = store->get_issuer; + else + ctx->get_issuer = X509_STORE_CTX_get1_issuer; + + if (store && store->check_issued) + ctx->check_issued = store->check_issued; + else + ctx->check_issued = check_issued; + + if (store && store->check_revocation) + ctx->check_revocation = store->check_revocation; + else + ctx->check_revocation = check_revocation; + + if (store && store->get_crl) + ctx->get_crl = store->get_crl; + else + ctx->get_crl = NULL; + + if (store && store->check_crl) + ctx->check_crl = store->check_crl; + else + ctx->check_crl = check_crl; + + if (store && store->cert_crl) + ctx->cert_crl = store->cert_crl; + else + ctx->cert_crl = cert_crl; + + ctx->check_policy = check_policy; + + if (store && store->lookup_certs) + ctx->lookup_certs = store->lookup_certs; + else + ctx->lookup_certs = X509_STORE_CTX_get1_certs; + + if (store && store->lookup_crls) + ctx->lookup_crls = store->lookup_crls; + else + ctx->lookup_crls = X509_STORE_CTX_get1_crls; + + if (store && store->cleanup) + ctx->cleanup = store->cleanup; + else + ctx->cleanup = NULL; + + ctx->param = X509_VERIFY_PARAM_new(); + if (!ctx->param) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Inherit callbacks and flags from X509_STORE if not set + * use defaults. + */ + if (store) + param_ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE; + + if (param_ret) + param_ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (param_ret == 0) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + + if (CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, + &(ctx->ex_data)) == 0) { + X509error(ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; +} +LCRYPTO_ALIAS(X509_STORE_CTX_init); + +/* Set alternative lookup method: just a STACK of trusted certificates. + * This avoids X509_STORE nastiness where it isn't needed. + */ + +void +X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *trusted) +{ + X509_STORE_CTX_set0_trusted_stack(ctx, trusted); +} +LCRYPTO_ALIAS(X509_STORE_CTX_trusted_stack); + +void +X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *trusted) +{ + ctx->trusted = trusted; + ctx->get_issuer = get_trusted_issuer; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set0_trusted_stack); + +void +X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) +{ + if (ctx->cleanup) + ctx->cleanup(ctx); + if (ctx->param != NULL) { + if (ctx->parent == NULL) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = NULL; + } + if (ctx->chain != NULL) { + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; + } + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, + ctx, &(ctx->ex_data)); + memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); +} +LCRYPTO_ALIAS(X509_STORE_CTX_cleanup); + +void +X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_depth); + +void +X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) +{ + X509_VERIFY_PARAM_set_flags(ctx->param, flags); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_flags); + +void +X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t) +{ + X509_VERIFY_PARAM_set_time(ctx->param, t); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_time); + +int +(*X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx))(int, X509_STORE_CTX *) +{ + return ctx->verify_cb; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_verify_cb); + +void +X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)) +{ + ctx->verify_cb = verify_cb; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_verify_cb); + +int +(*X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx))(X509_STORE_CTX *) +{ + return ctx->verify; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_verify); + +void +X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, int (*verify)(X509_STORE_CTX *)) +{ + ctx->verify = verify; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_verify); + +X509_STORE_CTX_check_issued_fn +X509_STORE_get_check_issued(X509_STORE *store) +{ + return store->check_issued; +} +LCRYPTO_ALIAS(X509_STORE_get_check_issued); + +void +X509_STORE_set_check_issued(X509_STORE *store, + X509_STORE_CTX_check_issued_fn check_issued) +{ + store->check_issued = check_issued; +} +LCRYPTO_ALIAS(X509_STORE_set_check_issued); + +X509_STORE_CTX_check_issued_fn +X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx) +{ + return ctx->check_issued; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_check_issued); + +X509 * +X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) +{ + return ctx->cert; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_cert); + +STACK_OF(X509) * +X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->untrusted; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_untrusted); + +void +X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + ctx->untrusted = sk; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set0_untrusted); + +void +X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) +{ + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = sk; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set0_verified_chain); + +int +X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->num_untrusted; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get_num_untrusted); + +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) + return 0; + return X509_VERIFY_PARAM_inherit(ctx->param, param); +} +LCRYPTO_ALIAS(X509_STORE_CTX_set_default); + +X509_VERIFY_PARAM * +X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) +{ + return ctx->param; +} +LCRYPTO_ALIAS(X509_STORE_CTX_get0_param); + +void +X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) +{ + if (ctx->param) + X509_VERIFY_PARAM_free(ctx->param); + ctx->param = param; +} +LCRYPTO_ALIAS(X509_STORE_CTX_set0_param); + +/* + * Check if |bits| are adequate for |security level|. + * Returns 1 if ok, 0 otherwise. + */ +static int +enough_bits_for_security_level(int bits, int level) +{ + /* + * Sigh. OpenSSL does this silly squashing, so we will + * too. Derp for Derp compatibility being important. + */ + if (level < 0) + level = 0; + if (level > 5) + level = 5; + + switch (level) { + case 0: + return 1; + case 1: + return bits >= 80; + case 2: + return bits >= 112; + case 3: + return bits >= 128; + case 4: + return bits >= 192; + case 5: + return bits >= 256; + default: + return 0; + } +} + +/* + * 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) +{ + EVP_PKEY *pkey; + int bits; + + /* Unsupported or malformed keys are not secure */ + if ((pkey = X509_get0_pubkey(cert)) == NULL) + return 0; + + if ((bits = EVP_PKEY_security_bits(pkey)) <= 0) + return 0; + + return enough_bits_for_security_level(bits, ctx->param->security_level); +} + +/* + * Check whether the signature digest algorithm of |cert| meets the security + * level of |ctx|. Do not check trust anchors (self-signed or not). + * + * Returns 1 on success, 0 otherwise. + */ +static int +check_sig_level(X509_STORE_CTX *ctx, X509 *cert) +{ + const EVP_MD *md; + int bits, nid, md_nid; + + if ((nid = X509_get_signature_nid(cert)) == NID_undef) + return 0; + + /* + * Look up signature algorithm digest. + */ + + if (!OBJ_find_sigid_algs(nid, &md_nid, NULL)) + return 0; + + if (md_nid == NID_undef) + return 0; + + if ((md = EVP_get_digestbynid(md_nid)) == NULL) + return 0; + + /* Assume 4 bits of collision resistance for each hash octet. */ + bits = EVP_MD_size(md) * 4; + + return enough_bits_for_security_level(bits, ctx->param->security_level); +} + +int +x509_vfy_check_security_level(X509_STORE_CTX *ctx) +{ + int num = sk_X509_num(ctx->chain); + int i; + + if (ctx->param->security_level <= 0) + return 1; + + for (i = 0; i < num; i++) { + X509 *cert = sk_X509_value(ctx->chain, i); + + /* + * We've already checked the security of the leaf key, so here + * we only check the security of issuer keys. + */ + if (i > 0) { + if (!check_key_level(ctx, cert) && + !verify_cb_cert(ctx, cert, i, + X509_V_ERR_CA_KEY_TOO_SMALL)) + return 0; + } + + /* + * We also check the signature algorithm security of all certs + * except those of the trust anchor at index num - 1. + */ + if (i == num - 1) + break; + + if (!check_sig_level(ctx, cert) && + !verify_cb_cert(ctx, cert, i, X509_V_ERR_CA_MD_TOO_WEAK)) + return 0; + } + return 1; +} diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c new file mode 100644 index 0000000..4ba697e --- /dev/null +++ b/crypto/x509/x509_vpm.c @@ -0,0 +1,729 @@ +/* $OpenBSD: x509_vpm.c,v 1.40 2023/05/28 05:25:24 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2004. + */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "x509_local.h" + +/* X509_VERIFY_PARAM functions */ + +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, + size_t emaillen); +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, + size_t iplen); + +#define SET_HOST 0 +#define ADD_HOST 1 + +static void +str_free(char *s) +{ + free(s); +} + +/* + * Post 1.0.1 sk function "deep_copy". For the moment we simply make + * these take void * and use them directly without a glorious blob of + * obfuscating macros of dubious value in front of them. All this in + * preparation for a rototilling of safestack.h (likely inspired by + * this). + */ +static void * +sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void) +{ + _STACK *sk = sk_void; + void *(*copy_func)(void *) = copy_func_void; + void (*free_func)(void *) = free_func_void; + _STACK *ret = sk_dup(sk); + size_t i; + + if (ret == NULL) + return NULL; + + for (i = 0; i < ret->num; i++) { + if (ret->data[i] == NULL) + continue; + ret->data[i] = copy_func(ret->data[i]); + if (ret->data[i] == NULL) { + size_t j; + for (j = 0; j < i; j++) { + if (ret->data[j] != NULL) + free_func(ret->data[j]); + } + sk_free(ret); + return NULL; + } + } + + return ret; +} + +static int +x509_param_set_hosts_internal(X509_VERIFY_PARAM *vpm, int mode, + const char *name, size_t namelen) +{ + char *copy; + + if (name != NULL && namelen == 0) + namelen = strlen(name); + /* + * Refuse names with embedded NUL bytes. + */ + if (name && memchr(name, '\0', namelen)) + return 0; + + if (mode == SET_HOST && vpm->hosts) { + sk_OPENSSL_STRING_pop_free(vpm->hosts, str_free); + vpm->hosts = NULL; + } + if (name == NULL || namelen == 0) + return 1; + copy = strndup(name, namelen); + if (copy == NULL) + return 0; + + if (vpm->hosts == NULL && + (vpm->hosts = sk_OPENSSL_STRING_new_null()) == NULL) { + free(copy); + return 0; + } + + if (!sk_OPENSSL_STRING_push(vpm->hosts, copy)) { + free(copy); + if (sk_OPENSSL_STRING_num(vpm->hosts) == 0) { + sk_OPENSSL_STRING_free(vpm->hosts); + vpm->hosts = NULL; + } + return 0; + } + + return 1; +} + +static void +x509_verify_param_zero(X509_VERIFY_PARAM *param) +{ + if (!param) + return; + + free(param->name); + param->name = NULL; + param->purpose = 0; + param->trust = 0; + /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/ + param->inh_flags = 0; + param->flags = 0; + param->depth = -1; + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + param->policies = NULL; + sk_OPENSSL_STRING_pop_free(param->hosts, str_free); + param->hosts = NULL; + free(param->peername); + param->peername = NULL; + free(param->email); + param->email = NULL; + param->emaillen = 0; + free(param->ip); + param->ip = NULL; + param->iplen = 0; + param->poisoned = 0; +} + +X509_VERIFY_PARAM * +X509_VERIFY_PARAM_new(void) +{ + X509_VERIFY_PARAM *param; + + param = calloc(1, sizeof(X509_VERIFY_PARAM)); + if (param == NULL) + return NULL; + x509_verify_param_zero(param); + return param; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_new); + +void +X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) +{ + if (param == NULL) + return; + x509_verify_param_zero(param); + free(param); +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_free); + +/* + * This function determines how parameters are "inherited" from one structure + * to another. There are several different ways this can happen. + * + * 1. If a child structure needs to have its values initialized from a parent + * they are simply copied across. For example SSL_CTX copied to SSL. + * 2. If the structure should take on values only if they are currently unset. + * For example the values in an SSL structure will take appropriate value + * for SSL servers or clients but only if the application has not set new + * ones. + * + * The "inh_flags" field determines how this function behaves. + * + * Normally any values which are set in the default are not copied from the + * destination and verify flags are ORed together. + * + * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied + * to the destination. Effectively the values in "to" become default values + * which will be used only if nothing new is set in "from". + * + * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether + * they are set or not. Flags is still Ored though. + * + * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead + * of ORed. + * + * If X509_VP_FLAG_LOCKED is set then no values are copied. + * + * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed + * after the next call. + */ + +/* 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)))) + +/* 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 + +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) + return 1; + inh_flags = dest->inh_flags | src->inh_flags; + + if (inh_flags & X509_VP_FLAG_ONCE) + dest->inh_flags = 0; + + if (inh_flags & X509_VP_FLAG_LOCKED) + 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; + + x509_verify_param_copy(purpose, 0); + x509_verify_param_copy(trust, 0); + x509_verify_param_copy(depth, -1); + + /* If overwrite or check time not set, copy across */ + + if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { + 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) + dest->flags = 0; + + dest->flags |= src->flags; + + if (test_x509_verify_param_copy(policies, NULL)) { + if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies)) + return 0; + } + + x509_verify_param_copy(hostflags, 0); + + if (test_x509_verify_param_copy(hosts, NULL)) { + if (dest->hosts) { + sk_OPENSSL_STRING_pop_free(dest->hosts, str_free); + dest->hosts = NULL; + } + if (src->hosts) { + dest->hosts = sk_deep_copy(src->hosts, strdup, str_free); + if (dest->hosts == NULL) + return 0; + } + } + + if (test_x509_verify_param_copy(email, NULL)) { + if (!X509_VERIFY_PARAM_set1_email(dest, src->email, + src->emaillen)) + return 0; + } + + if (test_x509_verify_param_copy(ip, NULL)) { + if (!X509_VERIFY_PARAM_set1_ip(dest, src->ip, src->iplen)) + return 0; + } + + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_inherit); + +int +X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from) +{ + unsigned long save_flags = to->inh_flags; + int ret; + + to->inh_flags |= X509_VP_FLAG_DEFAULT; + ret = X509_VERIFY_PARAM_inherit(to, from); + to->inh_flags = save_flags; + return ret; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1); + +static int +x509_param_set1_internal(char **pdest, size_t *pdestlen, const char *src, + size_t srclen, int nonul) +{ + char *tmp; + + if (src == NULL) + return 0; + + if (srclen == 0) { + srclen = strlen(src); + if (srclen == 0) + return 0; + if ((tmp = strdup(src)) == NULL) + return 0; + } else { + if (nonul && memchr(src, '\0', srclen)) + return 0; + if ((tmp = malloc(srclen)) == NULL) + return 0; + memcpy(tmp, src, srclen); + } + + if (*pdest) + free(*pdest); + *pdest = tmp; + if (pdestlen) + *pdestlen = srclen; + return 1; +} + +int +X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) +{ + free(param->name); + param->name = NULL; + if (name == NULL) + return 1; + param->name = strdup(name); + if (param->name) + return 1; + return 0; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_name); + +int +X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) +{ + param->flags |= flags; + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_flags); + +int +X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags) +{ + param->flags &= ~flags; + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_clear_flags); + +unsigned long +X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param) +{ + return param->flags; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_flags); + +int +X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose) +{ + return X509_PURPOSE_set(¶m->purpose, purpose); +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_purpose); + +int +X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust) +{ + return X509_TRUST_set(¶m->trust, trust); +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_trust); + +void +X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth) +{ + param->depth = depth; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_depth); + +void +X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level) +{ + param->security_level = auth_level; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_auth_level); + +time_t +X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param) +{ + return param->check_time; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_time); + +void +X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t) +{ + param->check_time = t; + param->flags |= X509_V_FLAG_USE_CHECK_TIME; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_time); + +int +X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy) +{ + if (!param->policies) { + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + return 0; + } + if (!sk_ASN1_OBJECT_push(param->policies, policy)) + return 0; + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_policy); + +int +X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies) +{ + int i; + ASN1_OBJECT *oid, *doid; + + if (!param) + return 0; + if (param->policies) + sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); + + if (!policies) { + param->policies = NULL; + return 1; + } + + param->policies = sk_ASN1_OBJECT_new_null(); + if (!param->policies) + 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) + return 0; + if (!sk_ASN1_OBJECT_push(param->policies, doid)) { + ASN1_OBJECT_free(doid); + return 0; + } + } + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_policies); + +int +X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + if (x509_param_set_hosts_internal(param, SET_HOST, name, namelen)) + return 1; + param->poisoned = 1; + return 0; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_host); + +int +X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, + const char *name, size_t namelen) +{ + if (x509_param_set_hosts_internal(param, ADD_HOST, name, namelen)) + return 1; + param->poisoned = 1; + return 0; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_add1_host); + +/* Public API in OpenSSL - nothing seems to use this. */ +unsigned int +X509_VERIFY_PARAM_get_hostflags(X509_VERIFY_PARAM *param) +{ + return param->hostflags; +} + +void +X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags) +{ + param->hostflags = flags; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set_hostflags); + +char * +X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param) +{ + return param->peername; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_peername); + +int +X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, + size_t emaillen) +{ + if (x509_param_set1_internal(¶m->email, ¶m->emaillen, + email, emaillen, 1)) + return 1; + param->poisoned = 1; + return 0; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_email); + +int +X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, + size_t iplen) +{ + if (iplen != 4 && iplen != 16) + goto err; + if (x509_param_set1_internal((char **)¶m->ip, ¶m->iplen, + (char *)ip, iplen, 0)) + return 1; + err: + param->poisoned = 1; + return 0; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip); + +int +X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) +{ + unsigned char ipout[16]; + size_t iplen; + + iplen = (size_t)a2i_ipadd(ipout, ipasc); + return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_set1_ip_asc); + +int +X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param) +{ + return param->depth; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_depth); + +const char * +X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param) +{ + return param->name; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0_name); + +/* + * Default verify parameters: these are used for various applications and can + * be overridden by the user specified table. + */ + +static const X509_VERIFY_PARAM default_table[] = { + { + .name = "default", + .flags = X509_V_FLAG_TRUSTED_FIRST, + .depth = 100, + .trust = 0, /* XXX This is not the default trust value */ + }, + { + .name = "pkcs7", + .purpose = X509_PURPOSE_SMIME_SIGN, + .trust = X509_TRUST_EMAIL, + .depth = -1, + }, + { + .name = "smime_sign", + .purpose = X509_PURPOSE_SMIME_SIGN, + .trust = X509_TRUST_EMAIL, + .depth = -1, + }, + { + .name = "ssl_client", + .purpose = X509_PURPOSE_SSL_CLIENT, + .trust = X509_TRUST_SSL_CLIENT, + .depth = -1, + }, + { + .name = "ssl_server", + .purpose = X509_PURPOSE_SSL_SERVER, + .trust = X509_TRUST_SSL_SERVER, + .depth = -1, + } +}; + +static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL; + +static int +param_cmp(const X509_VERIFY_PARAM * const *a, + const X509_VERIFY_PARAM * const *b) +{ + return strcmp((*a)->name, (*b)->name); +} + +int +X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) +{ + X509_VERIFY_PARAM *ptmp; + if (!param_table) { + param_table = sk_X509_VERIFY_PARAM_new(param_cmp); + if (!param_table) + return 0; + } else { + size_t idx; + + if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param)) + != -1) { + ptmp = sk_X509_VERIFY_PARAM_value(param_table, + idx); + X509_VERIFY_PARAM_free(ptmp); + (void)sk_X509_VERIFY_PARAM_delete(param_table, + idx); + } + } + if (!sk_X509_VERIFY_PARAM_push(param_table, param)) + return 0; + return 1; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_add0_table); + +int +X509_VERIFY_PARAM_get_count(void) +{ + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (param_table) + num += sk_X509_VERIFY_PARAM_num(param_table); + return num; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get_count); + +const X509_VERIFY_PARAM * +X509_VERIFY_PARAM_get0(int id) +{ + int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + if (id < num) + return default_table + id; + return sk_X509_VERIFY_PARAM_value(param_table, id - num); +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_get0); + +const X509_VERIFY_PARAM * +X509_VERIFY_PARAM_lookup(const char *name) +{ + X509_VERIFY_PARAM pm; + unsigned int i, limit; + + pm.name = (char *)name; + if (param_table) { + size_t idx; + if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1) + return sk_X509_VERIFY_PARAM_value(param_table, idx); + } + + limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM); + for (i = 0; i < limit; i++) { + if (strcmp(default_table[i].name, name) == 0) { + return &default_table[i]; + } + } + return NULL; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_lookup); + +void +X509_VERIFY_PARAM_table_cleanup(void) +{ + if (param_table) + sk_X509_VERIFY_PARAM_pop_free(param_table, + X509_VERIFY_PARAM_free); + param_table = NULL; +} +LCRYPTO_ALIAS(X509_VERIFY_PARAM_table_cleanup); diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c new file mode 100644 index 0000000..7904a7d --- /dev/null +++ b/crypto/x509/x509cset.c @@ -0,0 +1,233 @@ +/* $OpenBSD: x509cset.c,v 1.19 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +int +X509_CRL_up_ref(X509_CRL *x) +{ + int refs = CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + return (refs > 1) ? 1 : 0; +} +LCRYPTO_ALIAS(X509_CRL_up_ref); + +int +X509_CRL_set_version(X509_CRL *x, long version) +{ + if (x == NULL) + return (0); + if (x->crl->version == NULL) { + if ((x->crl->version = ASN1_INTEGER_new()) == NULL) + return (0); + } + return (ASN1_INTEGER_set(x->crl->version, version)); +} +LCRYPTO_ALIAS(X509_CRL_set_version); + +int +X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name) +{ + if ((x == NULL) || (x->crl == NULL)) + return (0); + return (X509_NAME_set(&x->crl->issuer, name)); +} +LCRYPTO_ALIAS(X509_CRL_set_issuer_name); + +int +X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->crl->lastUpdate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->crl->lastUpdate); + x->crl->lastUpdate = in; + } + } + return (in != NULL); +} +LCRYPTO_ALIAS(X509_CRL_set_lastUpdate); + +int +X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + return X509_CRL_set_lastUpdate(x, tm); +} +LCRYPTO_ALIAS(X509_CRL_set1_lastUpdate); + +int +X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->crl->nextUpdate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->crl->nextUpdate); + x->crl->nextUpdate = in; + } + } + return (in != NULL); +} +LCRYPTO_ALIAS(X509_CRL_set_nextUpdate); + +int +X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm) +{ + return X509_CRL_set_nextUpdate(x, tm); +} +LCRYPTO_ALIAS(X509_CRL_set1_nextUpdate); + +int +X509_CRL_sort(X509_CRL *c) +{ + int i; + X509_REVOKED *r; + + /* sort the data so it will be written in serial + * number order */ + sk_X509_REVOKED_sort(c->crl->revoked); + for (i = 0; i < sk_X509_REVOKED_num(c->crl->revoked); i++) { + r = sk_X509_REVOKED_value(c->crl->revoked, i); + r->sequence = i; + } + c->crl->enc.modified = 1; + return 1; +} +LCRYPTO_ALIAS(X509_CRL_sort); + +const STACK_OF(X509_EXTENSION) * +X509_REVOKED_get0_extensions(const X509_REVOKED *x) +{ + return x->extensions; +} +LCRYPTO_ALIAS(X509_REVOKED_get0_extensions); + +const ASN1_TIME * +X509_REVOKED_get0_revocationDate(const X509_REVOKED *x) +{ + return x->revocationDate; +} +LCRYPTO_ALIAS(X509_REVOKED_get0_revocationDate); + +const ASN1_INTEGER * +X509_REVOKED_get0_serialNumber(const X509_REVOKED *x) +{ + return x->serialNumber; +} +LCRYPTO_ALIAS(X509_REVOKED_get0_serialNumber); + +int +X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm) +{ + ASN1_TIME *in; + + if (x == NULL) + return (0); + in = x->revocationDate; + if (in != tm) { + in = ASN1_STRING_dup(tm); + if (in != NULL) { + ASN1_TIME_free(x->revocationDate); + x->revocationDate = in; + } + } + return (in != NULL); +} +LCRYPTO_ALIAS(X509_REVOKED_set_revocationDate); + +int +X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial) +{ + ASN1_INTEGER *in; + + if (x == NULL) + return (0); + in = x->serialNumber; + if (in != serial) { + in = ASN1_INTEGER_dup(serial); + if (in != NULL) { + ASN1_INTEGER_free(x->serialNumber); + x->serialNumber = in; + } + } + return (in != NULL); +} +LCRYPTO_ALIAS(X509_REVOKED_set_serialNumber); + +int +i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **pp) +{ + crl->crl->enc.modified = 1; + return i2d_X509_CRL_INFO(crl->crl, pp); +} +LCRYPTO_ALIAS(i2d_re_X509_CRL_tbs); diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c new file mode 100644 index 0000000..d2df06c --- /dev/null +++ b/crypto/x509/x509name.c @@ -0,0 +1,452 @@ +/* $OpenBSD: x509name.c,v 1.35 2023/05/29 11:54:50 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bytestring.h" +#include "x509_local.h" + +int +X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-1); + return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); +} +LCRYPTO_ALIAS(X509_NAME_get_text_by_NID); + +int +X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, + int len) +{ + unsigned char *text = NULL; + ASN1_STRING *data; + int i, text_len; + int ret = -1; + CBS cbs; + + i = X509_NAME_get_index_by_OBJ(name, obj, -1); + if (i < 0) + goto err; + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); + /* + * Fail if we cannot encode as UTF-8, or if the UTF-8 encoding of the + * string contains a 0 byte, because mortal callers seldom handle the + * length difference correctly. + */ + if ((text_len = ASN1_STRING_to_UTF8(&text, data)) < 0) + goto err; + CBS_init(&cbs, text, text_len); + if (CBS_contains_zero_byte(&cbs)) + goto err; + /* We still support the "pass NULL to find out how much" API */ + if (buf != NULL) { + if (len <= 0 || !CBS_write_bytes(&cbs, buf, len - 1, NULL)) + goto err; + /* It must be a C string */ + buf[text_len] = '\0'; + } + ret = text_len; + + err: + free(text); + return (ret); +} +LCRYPTO_ALIAS(X509_NAME_get_text_by_OBJ); + +int +X509_NAME_entry_count(const X509_NAME *name) +{ + if (name == NULL) + return (0); + return (sk_X509_NAME_ENTRY_num(name->entries)); +} +LCRYPTO_ALIAS(X509_NAME_entry_count); + +int +X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, int lastpos) +{ + ASN1_OBJECT *obj; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) + return (-2); + return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); +} +LCRYPTO_ALIAS(X509_NAME_get_index_by_NID); + +/* NOTE: you should be passing -1, not 0 as lastpos */ +int +X509_NAME_get_index_by_OBJ(const X509_NAME *name, const ASN1_OBJECT *obj, + int lastpos) +{ + int n; + X509_NAME_ENTRY *ne; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return (-1); + if (lastpos < 0) + lastpos = -1; + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + for (lastpos++; lastpos < n; lastpos++) { + ne = sk_X509_NAME_ENTRY_value(sk, lastpos); + if (OBJ_cmp(ne->object, obj) == 0) + return (lastpos); + } + return (-1); +} +LCRYPTO_ALIAS(X509_NAME_get_index_by_OBJ); + +X509_NAME_ENTRY * +X509_NAME_get_entry(const X509_NAME *name, int loc) +{ + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || + loc < 0) + return (NULL); + else + return (sk_X509_NAME_ENTRY_value(name->entries, loc)); +} +LCRYPTO_ALIAS(X509_NAME_get_entry); + +X509_NAME_ENTRY * +X509_NAME_delete_entry(X509_NAME *name, int loc) +{ + X509_NAME_ENTRY *ret; + int i, n, set_prev, set_next; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc || + loc < 0) + return (NULL); + sk = name->entries; + ret = sk_X509_NAME_ENTRY_delete(sk, loc); + n = sk_X509_NAME_ENTRY_num(sk); + name->modified = 1; + if (loc == n) + return (ret); + + /* else we need to fixup the set field */ + if (loc != 0) + set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; + else + set_prev = ret->set - 1; + set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; + + /* set_prev is the previous set + * set is the current set + * set_next is the following + * prev 1 1 1 1 1 1 1 1 + * set 1 1 2 2 + * next 1 1 2 2 2 2 3 2 + * so basically only if prev and next differ by 2, then + * re-number down by 1 */ + if (set_prev + 1 < set_next) + for (i = loc; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i)->set--; + return (ret); +} +LCRYPTO_ALIAS(X509_NAME_delete_entry); + +int +X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len, int loc, int set) +{ + X509_NAME_ENTRY *ne; + int ret; + + ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} +LCRYPTO_ALIAS(X509_NAME_add_entry_by_OBJ); + +int +X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + const unsigned char *bytes, int len, int loc, int set) +{ + X509_NAME_ENTRY *ne; + int ret; + + ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} +LCRYPTO_ALIAS(X509_NAME_add_entry_by_NID); + +int +X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, int set) +{ + X509_NAME_ENTRY *ne; + int ret; + + ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); + if (!ne) + return 0; + ret = X509_NAME_add_entry(name, ne, loc, set); + X509_NAME_ENTRY_free(ne); + return ret; +} +LCRYPTO_ALIAS(X509_NAME_add_entry_by_txt); + +/* if set is -1, append to previous set, 0 'a new one', and 1, + * prepend to the guy we are about to stomp on. */ +int +X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, + int set) +{ + X509_NAME_ENTRY *new_name = NULL; + int n, i, inc; + STACK_OF(X509_NAME_ENTRY) *sk; + + if (name == NULL) + return (0); + sk = name->entries; + n = sk_X509_NAME_ENTRY_num(sk); + if (loc > n) + loc = n; + else if (loc < 0) + loc = n; + inc = (set == 0); + name->modified = 1; + + if (set == -1) { + if (loc == 0) { + set = 0; + inc = 1; + } else + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; + } else /* if (set >= 0) */ { + if (loc >= n) { + if (loc != 0) + set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; + else + set = 0; + } else + set = sk_X509_NAME_ENTRY_value(sk, loc)->set; + } + + /* OpenSSL has ASN1-generated X509_NAME_ENTRY_dup() without const. */ + if ((new_name = X509_NAME_ENTRY_dup((X509_NAME_ENTRY *)ne)) == NULL) + goto err; + new_name->set = set; + if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { + X509error(ERR_R_MALLOC_FAILURE); + goto err; + } + if (inc) { + n = sk_X509_NAME_ENTRY_num(sk); + for (i = loc + 1; i < n; i++) + sk_X509_NAME_ENTRY_value(sk, i)->set += 1; + } + return (1); + +err: + if (new_name != NULL) + X509_NAME_ENTRY_free(new_name); + return (0); +} +LCRYPTO_ALIAS(X509_NAME_add_entry); + +X509_NAME_ENTRY * +X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, const unsigned char *bytes, int len) +{ + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_txt2obj(field, 0); + if (obj == NULL) { + X509error(X509_R_INVALID_FIELD_NAME); + ERR_asprintf_error_data("name=%s", field); + return (NULL); + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_txt); + +X509_NAME_ENTRY * +X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, int type, + const unsigned char *bytes, int len) +{ + ASN1_OBJECT *obj; + X509_NAME_ENTRY *nentry; + + obj = OBJ_nid2obj(nid); + if (obj == NULL) { + X509error(X509_R_UNKNOWN_NID); + return (NULL); + } + nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); + ASN1_OBJECT_free(obj); + return nentry; +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_NID); + +X509_NAME_ENTRY * +X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, const ASN1_OBJECT *obj, + int type, const unsigned char *bytes, int len) +{ + X509_NAME_ENTRY *ret; + + if ((ne == NULL) || (*ne == NULL)) { + if ((ret = X509_NAME_ENTRY_new()) == NULL) + return (NULL); + } else + ret= *ne; + + if (!X509_NAME_ENTRY_set_object(ret, obj)) + goto err; + if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) + goto err; + + if ((ne != NULL) && (*ne == NULL)) + *ne = ret; + return (ret); + +err: + if ((ne == NULL) || (ret != *ne)) + X509_NAME_ENTRY_free(ret); + return (NULL); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_create_by_OBJ); + +int +X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj) +{ + if ((ne == NULL) || (obj == NULL)) { + X509error(ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + ASN1_OBJECT_free(ne->object); + ne->object = OBJ_dup(obj); + return ((ne->object == NULL) ? 0 : 1); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_set_object); + +int +X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len) +{ + int i; + + if ((ne == NULL) || ((bytes == NULL) && (len != 0))) + return (0); + if ((type > 0) && (type & MBSTRING_FLAG)) + return ASN1_STRING_set_by_NID(&ne->value, bytes, len, type, + OBJ_obj2nid(ne->object)) ? 1 : 0; + if (len < 0) + len = strlen((const char *)bytes); + i = ASN1_STRING_set(ne->value, bytes, len); + if (!i) + return (0); + if (type != V_ASN1_UNDEF) { + if (type == V_ASN1_APP_CHOOSE) + ne->value->type = ASN1_PRINTABLE_type(bytes, len); + else + ne->value->type = type; + } + return (1); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_set_data); + +ASN1_OBJECT * +X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return (NULL); + return (ne->object); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_get_object); + +ASN1_STRING * +X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne) +{ + if (ne == NULL) + return (NULL); + return (ne->value); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_get_data); + +int +X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) +{ + return (ne->set); +} +LCRYPTO_ALIAS(X509_NAME_ENTRY_set); diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c new file mode 100644 index 0000000..f097a37 --- /dev/null +++ b/crypto/x509/x509rset.c @@ -0,0 +1,110 @@ +/* $OpenBSD: x509rset.c,v 1.12 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include + +#include "x509_local.h" + +int +X509_REQ_set_version(X509_REQ *x, long version) +{ + if (x == NULL) + return (0); + x->req_info->enc.modified = 1; + return (ASN1_INTEGER_set(x->req_info->version, version)); +} +LCRYPTO_ALIAS(X509_REQ_set_version); + +long +X509_REQ_get_version(const X509_REQ *x) +{ + return ASN1_INTEGER_get(x->req_info->version); +} +LCRYPTO_ALIAS(X509_REQ_get_version); + +int +X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name) +{ + if ((x == NULL) || (x->req_info == NULL)) + return (0); + x->req_info->enc.modified = 1; + return (X509_NAME_set(&x->req_info->subject, name)); +} +LCRYPTO_ALIAS(X509_REQ_set_subject_name); + +X509_NAME * +X509_REQ_get_subject_name(const X509_REQ *x) +{ + return x->req_info->subject; +} +LCRYPTO_ALIAS(X509_REQ_get_subject_name); + +int +X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->req_info == NULL)) + return (0); + x->req_info->enc.modified = 1; + return (X509_PUBKEY_set(&x->req_info->pubkey, pkey)); +} +LCRYPTO_ALIAS(X509_REQ_set_pubkey); diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c new file mode 100644 index 0000000..04c9a6f --- /dev/null +++ b/crypto/x509/x509spki.c @@ -0,0 +1,136 @@ +/* $OpenBSD: x509spki.c,v 1.16 2023/02/16 08:38:17 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include + +#include +#include + +int +NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) +{ + if ((x == NULL) || (x->spkac == NULL)) + return (0); + return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey)); +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_set_pubkey); + +EVP_PKEY * +NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x) +{ + if ((x == NULL) || (x->spkac == NULL)) + return (NULL); + return (X509_PUBKEY_get(x->spkac->pubkey)); +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_get_pubkey); + +/* Load a Netscape SPKI from a base64 encoded string */ + +NETSCAPE_SPKI * +NETSCAPE_SPKI_b64_decode(const char *str, int len) +{ + unsigned char *spki_der; + const unsigned char *p; + int spki_len; + NETSCAPE_SPKI *spki; + + if (len <= 0) + len = strlen(str); + if (!(spki_der = malloc(len + 1))) { + X509error(ERR_R_MALLOC_FAILURE); + return NULL; + } + spki_len = EVP_DecodeBlock(spki_der, (const unsigned char *)str, len); + if (spki_len < 0) { + X509error(X509_R_BASE64_DECODE_ERROR); + free(spki_der); + return NULL; + } + p = spki_der; + spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len); + free(spki_der); + return spki; +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_b64_decode); + +/* Generate a base64 encoded string from an SPKI */ + +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); + der_spki = malloc(der_len); + b64_str = reallocarray(NULL, der_len, 2); + if (!der_spki || !b64_str) { + X509error(ERR_R_MALLOC_FAILURE); + free(der_spki); + free(b64_str); + return NULL; + } + p = der_spki; + i2d_NETSCAPE_SPKI(spki, &p); + EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len); + free(der_spki); + return b64_str; +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_b64_encode); diff --git a/crypto/x509/x509type.c b/crypto/x509/x509type.c new file mode 100644 index 0000000..5da808c --- /dev/null +++ b/crypto/x509/x509type.c @@ -0,0 +1,130 @@ +/* $OpenBSD: x509type.c,v 1.19 2023/06/15 18:30:09 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include + +#include "evp_local.h" +#include "x509_local.h" + +int +X509_certificate_type(const X509 *x, const EVP_PKEY *pkey) +{ + const EVP_PKEY *pk = pkey; + int ret = 0, i; + + if (x == NULL) + return (0); + + if (pk == NULL) { + if ((pk = X509_get0_pubkey(x)) == NULL) + return (0); + } + + switch (pk->type) { + case EVP_PKEY_RSA: + ret = EVP_PK_RSA|EVP_PKT_SIGN|EVP_PKT_ENC; + break; + case EVP_PKEY_DSA: + ret = EVP_PK_DSA|EVP_PKT_SIGN; + break; + case EVP_PKEY_EC: + ret = EVP_PK_EC|EVP_PKT_SIGN|EVP_PKT_EXCH; + break; + case EVP_PKEY_ED25519: + ret = EVP_PKT_SIGN; + break; + case EVP_PKEY_DH: + ret = EVP_PK_DH|EVP_PKT_EXCH; + break; + case NID_id_GostR3410_94: + case NID_id_GostR3410_2001: + ret = EVP_PKT_EXCH|EVP_PKT_SIGN; + break; + default: + break; + } + + i = OBJ_obj2nid(x->sig_alg->algorithm); + if (i && OBJ_find_sigid_algs(i, NULL, &i)) { + switch (i) { + case NID_rsaEncryption: + case NID_rsa: + ret |= EVP_PKS_RSA; + break; + case NID_dsa: + case NID_dsa_2: + ret |= EVP_PKS_DSA; + break; + case NID_X9_62_id_ecPublicKey: + ret |= EVP_PKS_EC; + break; + default: + break; + } + } + + /* /8 because it's 1024 bits we look for, not bytes */ + if (EVP_PKEY_size(pk) <= 1024 / 8) + ret |= EVP_PKT_EXP; + return (ret); +} +LCRYPTO_ALIAS(X509_certificate_type); diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c new file mode 100644 index 0000000..cd6da9f --- /dev/null +++ b/crypto/x509/x_all.c @@ -0,0 +1,541 @@ +/* $OpenBSD: x_all.c,v 1.30 2023/02/16 08:38:17 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_RSA +#include +#endif + +#include "x509_local.h" + +X509 * +d2i_X509_bio(BIO *bp, X509 **x509) +{ + return ASN1_item_d2i_bio(&X509_it, bp, x509); +} +LCRYPTO_ALIAS(d2i_X509_bio); + +int +i2d_X509_bio(BIO *bp, X509 *x509) +{ + return ASN1_item_i2d_bio(&X509_it, bp, x509); +} +LCRYPTO_ALIAS(i2d_X509_bio); + +X509 * +d2i_X509_fp(FILE *fp, X509 **x509) +{ + return ASN1_item_d2i_fp(&X509_it, fp, x509); +} +LCRYPTO_ALIAS(d2i_X509_fp); + +int +i2d_X509_fp(FILE *fp, X509 *x509) +{ + return ASN1_item_i2d_fp(&X509_it, fp, x509); +} +LCRYPTO_ALIAS(i2d_X509_fp); + +X509_CRL * +d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl) +{ + return ASN1_item_d2i_bio(&X509_CRL_it, bp, crl); +} +LCRYPTO_ALIAS(d2i_X509_CRL_bio); + +int +i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl) +{ + return ASN1_item_i2d_bio(&X509_CRL_it, bp, crl); +} +LCRYPTO_ALIAS(i2d_X509_CRL_bio); + +X509_CRL * +d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl) +{ + return ASN1_item_d2i_fp(&X509_CRL_it, fp, crl); +} +LCRYPTO_ALIAS(d2i_X509_CRL_fp); + +int +i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl) +{ + return ASN1_item_i2d_fp(&X509_CRL_it, fp, crl); +} +LCRYPTO_ALIAS(i2d_X509_CRL_fp); + +X509_REQ * +d2i_X509_REQ_bio(BIO *bp, X509_REQ **req) +{ + return ASN1_item_d2i_bio(&X509_REQ_it, bp, req); +} +LCRYPTO_ALIAS(d2i_X509_REQ_bio); + +int +i2d_X509_REQ_bio(BIO *bp, X509_REQ *req) +{ + return ASN1_item_i2d_bio(&X509_REQ_it, bp, req); +} +LCRYPTO_ALIAS(i2d_X509_REQ_bio); + +X509_REQ * +d2i_X509_REQ_fp(FILE *fp, X509_REQ **req) +{ + return ASN1_item_d2i_fp(&X509_REQ_it, fp, req); +} +LCRYPTO_ALIAS(d2i_X509_REQ_fp); + +int +i2d_X509_REQ_fp(FILE *fp, X509_REQ *req) +{ + return ASN1_item_i2d_fp(&X509_REQ_it, fp, req); +} +LCRYPTO_ALIAS(i2d_X509_REQ_fp); + +#ifndef OPENSSL_NO_RSA +RSA * +d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_item_d2i_bio(&RSAPrivateKey_it, bp, rsa); +} +LCRYPTO_ALIAS(d2i_RSAPrivateKey_bio); + +int +i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_item_i2d_bio(&RSAPrivateKey_it, bp, rsa); +} +LCRYPTO_ALIAS(i2d_RSAPrivateKey_bio); + +RSA * +d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_item_d2i_fp(&RSAPrivateKey_it, fp, rsa); +} +LCRYPTO_ALIAS(d2i_RSAPrivateKey_fp); + +int +i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_item_i2d_fp(&RSAPrivateKey_it, fp, rsa); +} +LCRYPTO_ALIAS(i2d_RSAPrivateKey_fp); + +RSA * +d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) +{ + return ASN1_item_d2i_bio(&RSAPublicKey_it, bp, rsa); +} +LCRYPTO_ALIAS(d2i_RSAPublicKey_bio); + +int +i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) +{ + return ASN1_item_i2d_bio(&RSAPublicKey_it, bp, rsa); +} +LCRYPTO_ALIAS(i2d_RSAPublicKey_bio); + +RSA * +d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) +{ + return ASN1_item_d2i_fp(&RSAPublicKey_it, fp, rsa); +} +LCRYPTO_ALIAS(d2i_RSAPublicKey_fp); + +int +i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) +{ + return ASN1_item_i2d_fp(&RSAPublicKey_it, fp, rsa); +} +LCRYPTO_ALIAS(i2d_RSAPublicKey_fp); +#endif + +#ifndef OPENSSL_NO_DSA +DSA * +d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa) +{ + return ASN1_item_d2i_bio(&DSAPrivateKey_it, bp, dsa); +} +LCRYPTO_ALIAS(d2i_DSAPrivateKey_bio); + +int +i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa) +{ + return ASN1_item_i2d_bio(&DSAPrivateKey_it, bp, dsa); +} +LCRYPTO_ALIAS(i2d_DSAPrivateKey_bio); + +DSA * +d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa) +{ + return ASN1_item_d2i_fp(&DSAPrivateKey_it, fp, dsa); +} +LCRYPTO_ALIAS(d2i_DSAPrivateKey_fp); + +int +i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa) +{ + return ASN1_item_i2d_fp(&DSAPrivateKey_it, fp, dsa); +} +LCRYPTO_ALIAS(i2d_DSAPrivateKey_fp); +#endif + +#ifndef OPENSSL_NO_EC +EC_KEY * +d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey) +{ + return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey); +} +LCRYPTO_ALIAS(d2i_ECPrivateKey_bio); + +int +i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey) +{ + return ASN1_i2d_bio_of(EC_KEY, i2d_ECPrivateKey, bp, eckey); +} +LCRYPTO_ALIAS(i2d_ECPrivateKey_bio); + +EC_KEY * +d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey) +{ + return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey); +} +LCRYPTO_ALIAS(d2i_ECPrivateKey_fp); + +int +i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey) +{ + return ASN1_i2d_fp_of(EC_KEY, i2d_ECPrivateKey, fp, eckey); +} +LCRYPTO_ALIAS(i2d_ECPrivateKey_fp); +#endif + +X509_SIG * +d2i_PKCS8_bio(BIO *bp, X509_SIG **p8) +{ + return ASN1_item_d2i_bio(&X509_SIG_it, bp, p8); +} +LCRYPTO_ALIAS(d2i_PKCS8_bio); + +int +i2d_PKCS8_bio(BIO *bp, X509_SIG *p8) +{ + return ASN1_item_i2d_bio(&X509_SIG_it, bp, p8); +} +LCRYPTO_ALIAS(i2d_PKCS8_bio); + +X509_SIG * +d2i_PKCS8_fp(FILE *fp, X509_SIG **p8) +{ + return ASN1_item_d2i_fp(&X509_SIG_it, fp, p8); +} +LCRYPTO_ALIAS(d2i_PKCS8_fp); + +int +i2d_PKCS8_fp(FILE *fp, X509_SIG *p8) +{ + return ASN1_item_i2d_fp(&X509_SIG_it, fp, p8); +} +LCRYPTO_ALIAS(i2d_PKCS8_fp); + +PKCS8_PRIV_KEY_INFO * +d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_item_d2i_bio(&PKCS8_PRIV_KEY_INFO_it, bp, + p8inf); +} +LCRYPTO_ALIAS(d2i_PKCS8_PRIV_KEY_INFO_bio); + +int +i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_item_i2d_bio(&PKCS8_PRIV_KEY_INFO_it, bp, + p8inf); +} +LCRYPTO_ALIAS(i2d_PKCS8_PRIV_KEY_INFO_bio); + +PKCS8_PRIV_KEY_INFO * +d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO **p8inf) +{ + return ASN1_item_d2i_fp(&PKCS8_PRIV_KEY_INFO_it, fp, + p8inf); +} +LCRYPTO_ALIAS(d2i_PKCS8_PRIV_KEY_INFO_fp); + +int +i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf) +{ + return ASN1_item_i2d_fp(&PKCS8_PRIV_KEY_INFO_it, fp, + p8inf); +} +LCRYPTO_ALIAS(i2d_PKCS8_PRIV_KEY_INFO_fp); + +EVP_PKEY * +d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a) +{ + return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, + bp, a); +} +LCRYPTO_ALIAS(d2i_PrivateKey_bio); + +int +i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey) +{ + return ASN1_i2d_bio_of(EVP_PKEY, i2d_PrivateKey, bp, pkey); +} +LCRYPTO_ALIAS(i2d_PrivateKey_bio); + +EVP_PKEY * +d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a) +{ + return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, + fp, a); +} +LCRYPTO_ALIAS(d2i_PrivateKey_fp); + +int +i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey) +{ + return ASN1_i2d_fp_of(EVP_PKEY, i2d_PrivateKey, fp, pkey); +} +LCRYPTO_ALIAS(i2d_PrivateKey_fp); + +int +i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} +LCRYPTO_ALIAS(i2d_PKCS8PrivateKeyInfo_bio); + +int +i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key) +{ + PKCS8_PRIV_KEY_INFO *p8inf; + int ret; + p8inf = EVP_PKEY2PKCS8(key); + if (!p8inf) + return 0; + ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf); + PKCS8_PRIV_KEY_INFO_free(p8inf); + return ret; +} +LCRYPTO_ALIAS(i2d_PKCS8PrivateKeyInfo_fp); + +int +X509_verify(X509 *a, EVP_PKEY *r) +{ + if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature)) + return 0; + return (ASN1_item_verify(&X509_CINF_it, a->sig_alg, + a->signature, a->cert_info, r)); +} +LCRYPTO_ALIAS(X509_verify); + +int +X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) +{ + return (ASN1_item_verify(&X509_REQ_INFO_it, + a->sig_alg, a->signature, a->req_info, r)); +} +LCRYPTO_ALIAS(X509_REQ_verify); + +int +NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) +{ + return (ASN1_item_verify(&NETSCAPE_SPKAC_it, + a->sig_algor, a->signature, a->spkac, r)); +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_verify); + +int +X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->cert_info->enc.modified = 1; + return (ASN1_item_sign(&X509_CINF_it, + x->cert_info->signature, x->sig_alg, x->signature, + x->cert_info, pkey, md)); +} +LCRYPTO_ALIAS(X509_sign); + +int +X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) +{ + x->cert_info->enc.modified = 1; + return ASN1_item_sign_ctx(&X509_CINF_it, + x->cert_info->signature, x->sig_alg, x->signature, + x->cert_info, ctx); +} +LCRYPTO_ALIAS(X509_sign_ctx); + +int +X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(&X509_REQ_INFO_it, + x->sig_alg, NULL, x->signature, x->req_info, pkey, md)); +} +LCRYPTO_ALIAS(X509_REQ_sign); + +int +X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) +{ + return ASN1_item_sign_ctx(&X509_REQ_INFO_it, + x->sig_alg, NULL, x->signature, x->req_info, ctx); +} +LCRYPTO_ALIAS(X509_REQ_sign_ctx); + +int +X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + x->crl->enc.modified = 1; + return(ASN1_item_sign(&X509_CRL_INFO_it, x->crl->sig_alg, + x->sig_alg, x->signature, x->crl, pkey, md)); +} +LCRYPTO_ALIAS(X509_CRL_sign); + +int +X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) +{ + x->crl->enc.modified = 1; + return ASN1_item_sign_ctx(&X509_CRL_INFO_it, + x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx); +} +LCRYPTO_ALIAS(X509_CRL_sign_ctx); + +int +NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) +{ + return (ASN1_item_sign(&NETSCAPE_SPKAC_it, + x->sig_algor, NULL, x->signature, x->spkac, pkey, md)); +} +LCRYPTO_ALIAS(NETSCAPE_SPKI_sign); + +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) + return 0; + return EVP_Digest(key->data, key->length, md, len, type, NULL); +} +LCRYPTO_ALIAS(X509_pubkey_digest); + +int +X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest(&X509_it, type, (char *)data, + md, len)); +} +LCRYPTO_ALIAS(X509_digest); + +int +X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest(&X509_CRL_it, type, (char *)data, + md, len)); +} +LCRYPTO_ALIAS(X509_CRL_digest); + +int +X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest(&X509_REQ_it, type, (char *)data, + md, len)); +} +LCRYPTO_ALIAS(X509_REQ_digest); + +int +X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) +{ + return (ASN1_item_digest(&X509_NAME_it, type, (char *)data, + md, len)); +} +LCRYPTO_ALIAS(X509_NAME_digest); + +int +X509_up_ref(X509 *x) +{ + int i = CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + return i > 1 ? 1 : 0; +} +LCRYPTO_ALIAS(X509_up_ref); diff --git a/crypto/x86_arch.h b/crypto/x86_arch.h new file mode 100644 index 0000000..5b2cf97 --- /dev/null +++ b/crypto/x86_arch.h @@ -0,0 +1,90 @@ +/* $OpenBSD: x86_arch.h,v 1.1 2016/11/04 17:30:30 miod Exp $ */ +/* + * Copyright (c) 2016 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * The knowledge of the layout of OPENSSL_ia32cap_P is internal to libcrypto + * (and, to some extent, to libssl), and may change in the future without + * notice. + */ + +/* + * OPENSSL_ia32cap_P is computed at runtime by OPENSSL_ia32_cpuid(). + * + * On processors which lack the cpuid instruction, the value is always + * zero (this only matters on 32-bit processors, of course). + * + * On processors which support the cpuid instruction, after running + * "cpuid 1", the value of %edx is written to the low word of OPENSSL_ia32cap_P, + * and the value of %ecx is written to its high word. + * + * Further processing is done to set or clear specific bits, depending + * upon the exact processor type. + * + * Assembly routines usually address OPENSSL_ia32cap_P as two 32-bit words, + * hence two sets of bit numbers and masks. OPENSSL_cpu_caps() returns the + * complete 64-bit word. + */ + +/* bit numbers for the low word */ +#define IA32CAP_BIT0_FPU 0 +#define IA32CAP_BIT0_MMX 23 +#define IA32CAP_BIT0_FXSR 24 +#define IA32CAP_BIT0_SSE 25 +#define IA32CAP_BIT0_SSE2 26 +#define IA32CAP_BIT0_HT 28 + +/* the following bits are not obtained from cpuid */ +#define IA32CAP_BIT0_INTELP4 20 +#define IA32CAP_BIT0_INTEL 30 + +/* bit numbers for the high word */ +#define IA32CAP_BIT1_PCLMUL 1 +#define IA32CAP_BIT1_SSSE3 9 +#define IA32CAP_BIT1_FMA3 12 +#define IA32CAP_BIT1_AESNI 25 +#define IA32CAP_BIT1_OSXSAVE 27 +#define IA32CAP_BIT1_AVX 28 + +#define IA32CAP_BIT1_AMD_XOP 11 + +/* bit masks for the low word */ +#define IA32CAP_MASK0_MMX (1 << IA32CAP_BIT0_MMX) +#define IA32CAP_MASK0_FXSR (1 << IA32CAP_BIT0_FXSR) +#define IA32CAP_MASK0_SSE (1 << IA32CAP_BIT0_SSE) +#define IA32CAP_MASK0_SSE2 (1 << IA32CAP_BIT0_SSE2) +#define IA32CAP_MASK0_HT (1 << IA32CAP_BIT0_HT) + +#define IA32CAP_MASK0_INTELP4 (1 << IA32CAP_BIT0_INTELP4) +#define IA32CAP_MASK0_INTEL (1 << IA32CAP_BIT0_INTEL) + +/* bit masks for the high word */ +#define IA32CAP_MASK1_PCLMUL (1 << IA32CAP_BIT1_PCLMUL) +#define IA32CAP_MASK1_SSSE3 (1 << IA32CAP_BIT1_SSSE3) +#define IA32CAP_MASK1_FMA3 (1 << IA32CAP_BIT1_FMA3) +#define IA32CAP_MASK1_AESNI (1 << IA32CAP_BIT1_AESNI) +#define IA32CAP_MASK1_AVX (1 << IA32CAP_BIT1_AVX) + +#define IA32CAP_MASK1_AMD_XOP (1 << IA32CAP_BIT1_AMD_XOP) + +/* bit masks for OPENSSL_cpu_caps() */ +#define CPUCAP_MASK_MMX IA32CAP_MASK0_MMX +#define CPUCAP_MASK_FXSR IA32CAP_MASK0_FXSR +#define CPUCAP_MASK_SSE IA32CAP_MASK0_SSE +#define CPUCAP_MASK_INTELP4 IA32CAP_MASK0_INTELP4 +#define CPUCAP_MASK_PCLMUL (1ULL << (32 + IA32CAP_BIT1_PCLMUL)) +#define CPUCAP_MASK_SSSE3 (1ULL << (32 + IA32CAP_BIT1_SSSE3)) +#define CPUCAP_MASK_AESNI (1ULL << (32 + IA32CAP_BIT1_AESNI)) diff --git a/include/arch/aarch64/opensslconf.h b/include/arch/aarch64/opensslconf.h new file mode 100644 index 0000000..748ed8f --- /dev/null +++ b/include/arch/aarch64/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/alpha/opensslconf.h b/include/arch/alpha/opensslconf.h new file mode 100644 index 0000000..47f2aa8 --- /dev/null +++ b/include/arch/alpha/opensslconf.h @@ -0,0 +1,152 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#define DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#define DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#undef DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/amd64/opensslconf.h b/include/arch/amd64/opensslconf.h new file mode 100644 index 0000000..5cad089 --- /dev/null +++ b/include/arch/amd64/opensslconf.h @@ -0,0 +1,149 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/arm/opensslconf.h b/include/arch/arm/opensslconf.h new file mode 100644 index 0000000..f17d3d2 --- /dev/null +++ b/include/arch/arm/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/hppa/opensslconf.h b/include/arch/hppa/opensslconf.h new file mode 100644 index 0000000..f17d3d2 --- /dev/null +++ b/include/arch/hppa/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/i386/opensslconf.h b/include/arch/i386/opensslconf.h new file mode 100644 index 0000000..3b3827c --- /dev/null +++ b/include/arch/i386/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned long +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#define DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#define DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/m88k/opensslconf.h b/include/arch/m88k/opensslconf.h new file mode 100644 index 0000000..f17d3d2 --- /dev/null +++ b/include/arch/m88k/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/mips64/opensslconf.h b/include/arch/mips64/opensslconf.h new file mode 100644 index 0000000..ed1204c --- /dev/null +++ b/include/arch/mips64/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#define DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#define DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#undef DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/powerpc/opensslconf.h b/include/arch/powerpc/opensslconf.h new file mode 100644 index 0000000..f17d3d2 --- /dev/null +++ b/include/arch/powerpc/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/powerpc64/opensslconf.h b/include/arch/powerpc64/opensslconf.h new file mode 100644 index 0000000..5cad089 --- /dev/null +++ b/include/arch/powerpc64/opensslconf.h @@ -0,0 +1,149 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/riscv64/opensslconf.h b/include/arch/riscv64/opensslconf.h new file mode 100644 index 0000000..748ed8f --- /dev/null +++ b/include/arch/riscv64/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/sh/opensslconf.h b/include/arch/sh/opensslconf.h new file mode 100644 index 0000000..f17d3d2 --- /dev/null +++ b/include/arch/sh/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#undef RC4_CHUNK +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#define BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#undef SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#define THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#define RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#undef BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#undef DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#undef DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#define DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/arch/sparc64/opensslconf.h b/include/arch/sparc64/opensslconf.h new file mode 100644 index 0000000..ed1204c --- /dev/null +++ b/include/arch/sparc64/opensslconf.h @@ -0,0 +1,154 @@ +#include +/* crypto/opensslconf.h.in */ + +#if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) +#define OPENSSLDIR "/etc/ssl" +#endif + +#undef OPENSSL_UNISTD +#define OPENSSL_UNISTD + +#undef OPENSSL_EXPORT_VAR_AS_FUNCTION + +#if defined(HEADER_IDEA_H) && !defined(IDEA_INT) +#define IDEA_INT unsigned int +#endif + +#if defined(HEADER_MD2_H) && !defined(MD2_INT) +#define MD2_INT unsigned int +#endif + +#if defined(HEADER_RC2_H) && !defined(RC2_INT) +/* I need to put in a mod for the alpha - eay */ +#define RC2_INT unsigned int +#endif + +#if defined(HEADER_RC4_H) +#if !defined(RC4_INT) +/* using int types make the structure larger but make the code faster + * on most boxes I have tested - up to %20 faster. */ +/* + * I don't know what does "most" mean, but declaring "int" is a must on: + * - Intel P6 because partial register stalls are very expensive; + * - elder Alpha because it lacks byte load/store instructions; + */ +#define RC4_INT unsigned int +#endif +#if !defined(RC4_CHUNK) +/* + * This enables code handling data aligned at natural CPU word + * boundary. See crypto/rc4/rc4_enc.c for further details. + */ +#define RC4_CHUNK unsigned long +#endif +#endif + +#if (defined(HEADER_NEW_DES_H) || defined(HEADER_DES_H)) && !defined(DES_LONG) +/* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ +#ifndef DES_LONG +#define DES_LONG unsigned int +#endif +#endif + +#if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) +#define CONFIG_HEADER_BN_H +#undef BN_LLONG + +/* Should we define BN_DIV2W here? */ + +/* Only one for the following should be defined */ +/* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debugging the bignum libraries */ +#define SIXTY_FOUR_BIT_LONG +#undef SIXTY_FOUR_BIT +#undef THIRTY_TWO_BIT +#undef SIXTEEN_BIT +#undef EIGHT_BIT +#endif + +#if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) +#define CONFIG_HEADER_RC4_LOCL_H +/* if this is defined data[i] is used instead of *data, this is a %20 + * speedup on x86 */ +#undef RC4_INDEX +#endif + +#if defined(HEADER_BF_LOCL_H) && !defined(CONFIG_HEADER_BF_LOCL_H) +#define CONFIG_HEADER_BF_LOCL_H +#define BF_PTR +#endif /* HEADER_BF_LOCL_H */ + +#if defined(HEADER_DES_LOCL_H) && !defined(CONFIG_HEADER_DES_LOCL_H) +#define CONFIG_HEADER_DES_LOCL_H +#ifndef DES_DEFAULT_OPTIONS +/* the following is tweaked from a config script, that is why it is a + * protected undef/define */ +#ifndef DES_PTR +#define DES_PTR +#endif + +/* This helps C compiler generate the correct code for multiple functional + * units. It reduces register dependencies at the expense of 2 more + * registers */ +#ifndef DES_RISC1 +#undef DES_RISC1 +#endif + +#ifndef DES_RISC2 +#define DES_RISC2 +#endif + +#if defined(DES_RISC1) && defined(DES_RISC2) +YOU SHOULD NOT HAVE BOTH DES_RISC1 AND DES_RISC2 DEFINED!!!!! +#endif + +/* Unroll the inner loop, this sometimes helps, sometimes hinders. + * Very much CPU dependent */ +#ifndef DES_UNROLL +#undef DES_UNROLL +#endif + +/* These default values were supplied by + * Peter Gutman + * They are only used if nothing else has been defined */ +#if !defined(DES_PTR) && !defined(DES_RISC1) && !defined(DES_RISC2) && !defined(DES_UNROLL) +/* Special defines which change the way the code is built depending on the + CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find + even newer MIPS CPU's, but at the moment one size fits all for + optimization options. Older Sparc's work better with only UNROLL, but + there's no way to tell at compile time what it is you're running on */ + +#if defined( sun ) /* Newer Sparc's */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#elif defined( __ultrix ) /* Older MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined( __osf1__ ) /* Alpha */ +# define DES_PTR +# define DES_RISC2 +#elif defined ( _AIX ) /* RS6000 */ + /* Unknown */ +#elif defined( __hpux ) /* HP-PA */ + /* Unknown */ +#elif defined( __aux ) /* 68K */ + /* Unknown */ +#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */ +# define DES_UNROLL +#elif defined( __sgi ) /* Newer MIPS */ +# define DES_PTR +# define DES_RISC2 +# define DES_UNROLL +#elif defined(i386) || defined(__i386__) /* x86 boxes, should be gcc */ +# define DES_PTR +# define DES_RISC1 +# define DES_UNROLL +#endif /* Systems-specific speed defines */ +#endif + +#endif /* DES_DEFAULT_OPTIONS */ +#endif /* HEADER_DES_LOCL_H */ diff --git a/include/openssl/aes.h b/include/openssl/aes.h new file mode 100644 index 0000000..702873e --- /dev/null +++ b/include/openssl/aes.h @@ -0,0 +1,124 @@ +/* $OpenBSD: aes.h,v 1.15 2023/07/31 05:04:06 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#ifndef HEADER_AES_H +#define HEADER_AES_H + +#include + +#ifdef OPENSSL_NO_AES +#error AES is disabled. +#endif + +#include + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +/* Because array size can't be a const in C, the following two are macros. + Both sizes are in bytes. */ +#define AES_MAXNR 14 +#define AES_BLOCK_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ +struct aes_key_st { + unsigned int rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +}; +typedef struct aes_key_st AES_KEY; + +int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); +int AES_set_decrypt_key(const unsigned char *userKey, const int bits, + AES_KEY *key); + +void AES_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); +void AES_decrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key); + +void AES_ecb_encrypt(const unsigned char *in, unsigned char *out, + const AES_KEY *key, const int enc); +void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); +void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, int *num, + const int enc); +void AES_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, int *num, + const int enc); +void AES_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, int *num, + const int enc); +void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, int *num); +void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char ivec[AES_BLOCK_SIZE], + unsigned char ecount_buf[AES_BLOCK_SIZE], unsigned int *num); +/* NB: the IV is _two_ blocks long */ +void AES_ige_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); + +int AES_wrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out, + const unsigned char *in, unsigned int inlen); +int AES_unwrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out, + const unsigned char *in, unsigned int inlen); + + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_AES_H */ diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h new file mode 100644 index 0000000..5eeee33 --- /dev/null +++ b/include/openssl/asn1.h @@ -0,0 +1,1175 @@ +/* $OpenBSD: asn1.h,v 1.80 2023/07/28 10:33:13 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ASN1_H +#define HEADER_ASN1_H + +#include + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define V_ASN1_UNIVERSAL 0x00 +#define V_ASN1_APPLICATION 0x40 +#define V_ASN1_CONTEXT_SPECIFIC 0x80 +#define V_ASN1_PRIVATE 0xc0 + +#define V_ASN1_CONSTRUCTED 0x20 +#define V_ASN1_PRIMITIVE_TAG 0x1f +#define V_ASN1_PRIMATIVE_TAG 0x1f + +#define V_ASN1_APP_CHOOSE -2 /* let the recipient choose */ +#define V_ASN1_OTHER -3 /* used in ASN1_TYPE */ +#define V_ASN1_ANY -4 /* used in ASN1 template code */ + +#define V_ASN1_NEG 0x100 /* negative flag */ + +#define V_ASN1_UNDEF -1 +#define V_ASN1_EOC 0 +#define V_ASN1_BOOLEAN 1 /**/ +#define V_ASN1_INTEGER 2 +#define V_ASN1_NEG_INTEGER (2 | V_ASN1_NEG) +#define V_ASN1_BIT_STRING 3 +#define V_ASN1_OCTET_STRING 4 +#define V_ASN1_NULL 5 +#define V_ASN1_OBJECT 6 +#define V_ASN1_OBJECT_DESCRIPTOR 7 +#define V_ASN1_EXTERNAL 8 +#define V_ASN1_REAL 9 +#define V_ASN1_ENUMERATED 10 +#define V_ASN1_NEG_ENUMERATED (10 | V_ASN1_NEG) +#define V_ASN1_UTF8STRING 12 +#define V_ASN1_SEQUENCE 16 +#define V_ASN1_SET 17 +#define V_ASN1_NUMERICSTRING 18 /**/ +#define V_ASN1_PRINTABLESTRING 19 +#define V_ASN1_T61STRING 20 +#define V_ASN1_TELETEXSTRING 20 /* alias */ +#define V_ASN1_VIDEOTEXSTRING 21 /**/ +#define V_ASN1_IA5STRING 22 +#define V_ASN1_UTCTIME 23 +#define V_ASN1_GENERALIZEDTIME 24 /**/ +#define V_ASN1_GRAPHICSTRING 25 /**/ +#define V_ASN1_ISO64STRING 26 /**/ +#define V_ASN1_VISIBLESTRING 26 /* alias */ +#define V_ASN1_GENERALSTRING 27 /**/ +#define V_ASN1_UNIVERSALSTRING 28 /**/ +#define V_ASN1_BMPSTRING 30 + +#define B_ASN1_NUMERICSTRING 0x0001 +#define B_ASN1_PRINTABLESTRING 0x0002 +#define B_ASN1_T61STRING 0x0004 +#define B_ASN1_TELETEXSTRING 0x0004 +#define B_ASN1_VIDEOTEXSTRING 0x0008 +#define B_ASN1_IA5STRING 0x0010 +#define B_ASN1_GRAPHICSTRING 0x0020 +#define B_ASN1_ISO64STRING 0x0040 +#define B_ASN1_VISIBLESTRING 0x0040 +#define B_ASN1_GENERALSTRING 0x0080 +#define B_ASN1_UNIVERSALSTRING 0x0100 +#define B_ASN1_OCTET_STRING 0x0200 +#define B_ASN1_BIT_STRING 0x0400 +#define B_ASN1_BMPSTRING 0x0800 +#define B_ASN1_UNKNOWN 0x1000 +#define B_ASN1_UTF8STRING 0x2000 +#define B_ASN1_UTCTIME 0x4000 +#define B_ASN1_GENERALIZEDTIME 0x8000 +#define B_ASN1_SEQUENCE 0x10000 + +/* For use with ASN1_mbstring_copy() */ +#define MBSTRING_FLAG 0x1000 +#define MBSTRING_UTF8 (MBSTRING_FLAG) +#define MBSTRING_ASC (MBSTRING_FLAG|1) +#define MBSTRING_BMP (MBSTRING_FLAG|2) +#define MBSTRING_UNIV (MBSTRING_FLAG|4) + +#define SMIME_OLDMIME 0x400 +#define SMIME_CRLFEOL 0x800 +#define SMIME_STREAM 0x1000 + +struct X509_algor_st; +DECLARE_STACK_OF(X509_ALGOR) + +#define DECLARE_ASN1_SET_OF(type) /* filled in by mkstack.pl */ +#define IMPLEMENT_ASN1_SET_OF(type) /* nothing, no longer needed */ + +#define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */ +/* This indicates that the ASN1_STRING is not a real value but just a place + * holder for the location where indefinite length constructed data should + * be inserted in the memory buffer + */ +#define ASN1_STRING_FLAG_NDEF 0x010 + +/* This flag is used by the CMS code to indicate that a string is not + * complete and is a place holder for content when it had all been + * accessed. The flag will be reset when content has been written to it. + */ + +#define ASN1_STRING_FLAG_CONT 0x020 +/* This flag is used by ASN1 code to indicate an ASN1_STRING is an MSTRING + * type. + */ +#define ASN1_STRING_FLAG_MSTRING 0x040 +/* This is the base type that holds just about everything :-) */ +struct asn1_string_st { + int length; + int type; + unsigned char *data; + /* The value of the following field depends on the type being + * held. It is mostly being used for BIT_STRING so if the + * input data has a non-zero 'unused bits' value, it will be + * handled correctly */ + long flags; +}; + +/* ASN1_ENCODING structure: this is used to save the received + * encoding of an ASN1 type. This is useful to get round + * problems with invalid encodings which can break signatures. + */ + +typedef struct ASN1_ENCODING_st { + unsigned char *enc; /* DER encoding */ + long len; /* Length of encoding */ + int modified; /* set to 1 if 'enc' is invalid */ +} ASN1_ENCODING; + +/* Used with ASN1 LONG type: if a long is set to this it is omitted */ +#define ASN1_LONG_UNDEF 0x7fffffffL + +#define STABLE_FLAGS_MALLOC 0x01 +#define STABLE_NO_MASK 0x02 +#define DIRSTRING_TYPE \ + (B_ASN1_PRINTABLESTRING|B_ASN1_T61STRING|B_ASN1_BMPSTRING|B_ASN1_UTF8STRING) +#define PKCS9STRING_TYPE (DIRSTRING_TYPE|B_ASN1_IA5STRING) + +typedef struct asn1_string_table_st { + int nid; + long minsize; + long maxsize; + unsigned long mask; + unsigned long flags; +} ASN1_STRING_TABLE; + +DECLARE_STACK_OF(ASN1_STRING_TABLE) + +/* size limits: this stuff is taken straight from RFC2459 */ + +#define ub_name 32768 +#define ub_common_name 64 +#define ub_locality_name 128 +#define ub_state_name 128 +#define ub_organization_name 64 +#define ub_organization_unit_name 64 +#define ub_title 64 +#define ub_email_address 128 + +/* Declarations for template structures: for full definitions + * see asn1t.h + */ +typedef struct ASN1_TEMPLATE_st ASN1_TEMPLATE; +typedef struct ASN1_TLC_st ASN1_TLC; +/* This is just an opaque pointer */ +typedef struct ASN1_VALUE_st ASN1_VALUE; + +#ifndef LIBRESSL_INTERNAL + +/* Declare ASN1 functions: the implement macro in in asn1t.h */ + +#define DECLARE_ASN1_FUNCTIONS(type) DECLARE_ASN1_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS(type) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, type) + +#define DECLARE_ASN1_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) + +#define DECLARE_ASN1_FUNCTIONS_fname(type, itname, name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(itname) + +#define DECLARE_ASN1_ENCODE_FUNCTIONS_const(type, name) \ + type *d2i_##name(type **a, const unsigned char **in, long len); \ + int i2d_##name(const type *a, unsigned char **out); \ + DECLARE_ASN1_ITEM(name) + +#define DECLARE_ASN1_NDEF_FUNCTION(name) \ + int i2d_##name##_NDEF(name *a, unsigned char **out); + +#define DECLARE_ASN1_FUNCTIONS_const(name) \ + DECLARE_ASN1_ALLOC_FUNCTIONS(name) \ + DECLARE_ASN1_ENCODE_FUNCTIONS_const(name, name) + +#define DECLARE_ASN1_ALLOC_FUNCTIONS_name(type, name) \ + type *name##_new(void); \ + void name##_free(type *a); + +#define DECLARE_ASN1_PRINT_FUNCTION(stname) \ + DECLARE_ASN1_PRINT_FUNCTION_fname(stname, stname) + +#define DECLARE_ASN1_PRINT_FUNCTION_fname(stname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx); + +#endif /* !LIBRESSL_INTERNAL */ + +#define D2I_OF(type) type *(*)(type **,const unsigned char **,long) +#define I2D_OF(type) int (*)(type *,unsigned char **) +#define I2D_OF_const(type) int (*)(const type *,unsigned char **) + +#define CHECKED_D2I_OF(type, d2i) \ + ((d2i_of_void*) (1 ? d2i : ((D2I_OF(type))0))) +#define CHECKED_I2D_OF(type, i2d) \ + ((i2d_of_void*) (1 ? i2d : ((I2D_OF(type))0))) +#define CHECKED_NEW_OF(type, xnew) \ + ((void *(*)(void)) (1 ? xnew : ((type *(*)(void))0))) +#define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +#define CHECKED_PPTR_OF(type, p) \ + ((void**) (1 ? p : (type**)0)) + +#define TYPEDEF_D2I_OF(type) typedef type *d2i_of_##type(type **,const unsigned char **,long) +#define TYPEDEF_I2D_OF(type) typedef int i2d_of_##type(type *,unsigned char **) +#define TYPEDEF_D2I2D_OF(type) TYPEDEF_D2I_OF(type); TYPEDEF_I2D_OF(type) + +TYPEDEF_D2I2D_OF(void); + +/* The following macros and typedefs allow an ASN1_ITEM + * to be embedded in a structure and referenced. Since + * the ASN1_ITEM pointers need to be globally accessible + * (possibly from shared libraries) they may exist in + * different forms. On platforms that support it the + * ASN1_ITEM structure itself will be globally exported. + * Other platforms will export a function that returns + * an ASN1_ITEM pointer. + * + * To handle both cases transparently the macros below + * should be used instead of hard coding an ASN1_ITEM + * pointer in a structure. + * + * The structure will look like this: + * + * typedef struct SOMETHING_st { + * ... + * ASN1_ITEM_EXP *iptr; + * ... + * } SOMETHING; + * + * It would be initialised as e.g.: + * + * SOMETHING somevar = {...,ASN1_ITEM_ref(X509),...}; + * + * and the actual pointer extracted with: + * + * const ASN1_ITEM *it = ASN1_ITEM_ptr(somevar.iptr); + * + * Finally an ASN1_ITEM pointer can be extracted from an + * appropriate reference with: ASN1_ITEM_rptr(X509). This + * would be used when a function takes an ASN1_ITEM * argument. + * + */ + +/* ASN1_ITEM pointer exported type */ +typedef const ASN1_ITEM ASN1_ITEM_EXP; + +#ifndef LIBRESSL_INTERNAL + +/* Macro to obtain ASN1_ITEM pointer from exported type */ +#define ASN1_ITEM_ptr(iptr) (iptr) + +/* Macro to include ASN1_ITEM pointer from base type */ +#define ASN1_ITEM_ref(iptr) (&(iptr##_it)) + +#define ASN1_ITEM_rptr(ref) (&(ref##_it)) + +#define DECLARE_ASN1_ITEM(name) \ + extern const ASN1_ITEM name##_it; + +#endif /* !LIBRESSL_INTERNAL */ + +/* Parameters used by ASN1_STRING_print_ex() */ + +/* These determine which characters to escape: + * RFC2253 special characters, control characters and + * MSB set characters + */ + +#define ASN1_STRFLGS_ESC_2253 1 +#define ASN1_STRFLGS_ESC_CTRL 2 +#define ASN1_STRFLGS_ESC_MSB 4 + + +/* This flag determines how we do escaping: normally + * RC2253 backslash only, set this to use backslash and + * quote. + */ + +#define ASN1_STRFLGS_ESC_QUOTE 8 + + +/* These three flags are internal use only. */ + +/* Character is a valid PrintableString character */ +#define CHARTYPE_PRINTABLESTRING 0x10 +/* Character needs escaping if it is the first character */ +#define CHARTYPE_FIRST_ESC_2253 0x20 +/* Character needs escaping if it is the last character */ +#define CHARTYPE_LAST_ESC_2253 0x40 + +/* NB the internal flags are safely reused below by flags + * handled at the top level. + */ + +/* If this is set we convert all character strings + * to UTF8 first + */ + +#define ASN1_STRFLGS_UTF8_CONVERT 0x10 + +/* If this is set we don't attempt to interpret content: + * just assume all strings are 1 byte per character. This + * will produce some pretty odd looking output! + */ + +#define ASN1_STRFLGS_IGNORE_TYPE 0x20 + +/* If this is set we include the string type in the output */ +#define ASN1_STRFLGS_SHOW_TYPE 0x40 + +/* This determines which strings to display and which to + * 'dump' (hex dump of content octets or DER encoding). We can + * only dump non character strings or everything. If we + * don't dump 'unknown' they are interpreted as character + * strings with 1 octet per character and are subject to + * the usual escaping options. + */ + +#define ASN1_STRFLGS_DUMP_ALL 0x80 +#define ASN1_STRFLGS_DUMP_UNKNOWN 0x100 + +/* These determine what 'dumping' does, we can dump the + * content octets or the DER encoding: both use the + * RFC2253 #NNNNN notation. + */ + +#define ASN1_STRFLGS_DUMP_DER 0x200 + +/* All the string flags consistent with RFC2253, + * escaping control characters isn't essential in + * RFC2253 but it is advisable anyway. + */ + +#define ASN1_STRFLGS_RFC2253 (ASN1_STRFLGS_ESC_2253 | \ + ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + ASN1_STRFLGS_UTF8_CONVERT | \ + ASN1_STRFLGS_DUMP_UNKNOWN | \ + ASN1_STRFLGS_DUMP_DER) + +DECLARE_STACK_OF(ASN1_INTEGER) + +DECLARE_STACK_OF(ASN1_GENERALSTRING) + +typedef struct asn1_type_st { + int type; + union { + char *ptr; + ASN1_BOOLEAN boolean; + ASN1_STRING * asn1_string; + ASN1_OBJECT * object; + ASN1_INTEGER * integer; + ASN1_ENUMERATED * enumerated; + ASN1_BIT_STRING * bit_string; + ASN1_OCTET_STRING * octet_string; + ASN1_PRINTABLESTRING * printablestring; + ASN1_T61STRING * t61string; + ASN1_IA5STRING * ia5string; + ASN1_GENERALSTRING * generalstring; + ASN1_BMPSTRING * bmpstring; + ASN1_UNIVERSALSTRING * universalstring; + ASN1_UTCTIME * utctime; + ASN1_GENERALIZEDTIME * generalizedtime; + ASN1_VISIBLESTRING * visiblestring; + ASN1_UTF8STRING * utf8string; + /* set and sequence are left complete and still + * contain the set or sequence bytes */ + ASN1_STRING * set; + ASN1_STRING * sequence; + ASN1_VALUE * asn1_value; + } value; +} ASN1_TYPE; + +DECLARE_STACK_OF(ASN1_TYPE) + +typedef STACK_OF(ASN1_TYPE) ASN1_SEQUENCE_ANY; + +ASN1_SEQUENCE_ANY *d2i_ASN1_SEQUENCE_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len); +int i2d_ASN1_SEQUENCE_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out); +extern const ASN1_ITEM ASN1_SEQUENCE_ANY_it; +ASN1_SEQUENCE_ANY *d2i_ASN1_SET_ANY(ASN1_SEQUENCE_ANY **a, const unsigned char **in, long len); +int i2d_ASN1_SET_ANY(const ASN1_SEQUENCE_ANY *a, unsigned char **out); +extern const ASN1_ITEM ASN1_SET_ANY_it; + +/* This is used to contain a list of bit names */ +typedef struct BIT_STRING_BITNAME_st { + int bitnum; + const char *lname; + const char *sname; +} BIT_STRING_BITNAME; + +#define B_ASN1_TIME \ + B_ASN1_UTCTIME | \ + B_ASN1_GENERALIZEDTIME + +#define B_ASN1_PRINTABLE \ + B_ASN1_NUMERICSTRING| \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_T61STRING| \ + B_ASN1_IA5STRING| \ + B_ASN1_BIT_STRING| \ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING|\ + B_ASN1_SEQUENCE|\ + B_ASN1_UNKNOWN + +#define B_ASN1_DIRECTORYSTRING \ + B_ASN1_PRINTABLESTRING| \ + B_ASN1_TELETEXSTRING|\ + B_ASN1_BMPSTRING|\ + B_ASN1_UNIVERSALSTRING|\ + B_ASN1_UTF8STRING + +#define B_ASN1_DISPLAYTEXT \ + B_ASN1_IA5STRING| \ + B_ASN1_VISIBLESTRING| \ + B_ASN1_BMPSTRING|\ + B_ASN1_UTF8STRING + +#ifndef LIBRESSL_INTERNAL +#define M_ASN1_IA5STRING_new ASN1_IA5STRING_new + +#define M_ASN1_INTEGER_free ASN1_INTEGER_free +#define M_ASN1_ENUMERATED_free ASN1_ENUMERATED_free +#define M_ASN1_OCTET_STRING_free ASN1_OCTET_STRING_free + +#define M_ASN1_OCTET_STRING_print ASN1_STRING_print + +#define M_ASN1_STRING_data ASN1_STRING_data +#define M_ASN1_STRING_length ASN1_STRING_length +#endif + +ASN1_TYPE *ASN1_TYPE_new(void); +void ASN1_TYPE_free(ASN1_TYPE *a); +ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **a, const unsigned char **in, long len); +int i2d_ASN1_TYPE(ASN1_TYPE *a, unsigned char **out); +extern const ASN1_ITEM ASN1_ANY_it; + +int ASN1_TYPE_get(const ASN1_TYPE *a); +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value); +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value); +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b); + +ASN1_OBJECT *ASN1_OBJECT_new(void); +void ASN1_OBJECT_free(ASN1_OBJECT *a); +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp); +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, + long length); + +extern const ASN1_ITEM ASN1_OBJECT_it; + +DECLARE_STACK_OF(ASN1_OBJECT) + +ASN1_STRING *ASN1_STRING_new(void); +void ASN1_STRING_free(ASN1_STRING *a); +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str); +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *a); +ASN1_STRING *ASN1_STRING_type_new(int type); +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b); + /* Since this is used to store all sorts of things, via macros, for now, make + its data void * */ +int ASN1_STRING_set(ASN1_STRING *str, const void *data, int len); +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len); +int ASN1_STRING_length(const ASN1_STRING *x); +void ASN1_STRING_length_set(ASN1_STRING *x, int n); +int ASN1_STRING_type(const ASN1_STRING *x); +unsigned char *ASN1_STRING_data(ASN1_STRING *x); +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x); + +ASN1_BIT_STRING *ASN1_BIT_STRING_new(void); +void ASN1_BIT_STRING_free(ASN1_BIT_STRING *a); +ASN1_BIT_STRING *d2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, const unsigned char **in, long len); +int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_BIT_STRING_it; +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *a, unsigned char *d, int length); +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value); +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n); + +ASN1_INTEGER *ASN1_INTEGER_new(void); +void ASN1_INTEGER_free(ASN1_INTEGER *a); +ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **in, long len); +int i2d_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **out); +extern const ASN1_ITEM ASN1_INTEGER_it; +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, + long length); +ASN1_INTEGER * ASN1_INTEGER_dup(const ASN1_INTEGER *x); +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y); + +ASN1_ENUMERATED *ASN1_ENUMERATED_new(void); +void ASN1_ENUMERATED_free(ASN1_ENUMERATED *a); +ASN1_ENUMERATED *d2i_ASN1_ENUMERATED(ASN1_ENUMERATED **a, const unsigned char **in, long len); +int i2d_ASN1_ENUMERATED(ASN1_ENUMERATED *a, unsigned char **out); +extern const ASN1_ITEM ASN1_ENUMERATED_it; + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *a); +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t); +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, + int offset_day, long offset_sec); +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str); + +#ifndef LIBRESSL_INTERNAL +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t); +#endif /* !LIBRESSL_INTERNAL */ + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, + time_t t); +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, + time_t t, int offset_day, long offset_sec); +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str); + +ASN1_OCTET_STRING *ASN1_OCTET_STRING_new(void); +void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *a); +ASN1_OCTET_STRING *d2i_ASN1_OCTET_STRING(ASN1_OCTET_STRING **a, const unsigned char **in, long len); +int i2d_ASN1_OCTET_STRING(ASN1_OCTET_STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_OCTET_STRING_it; +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *a); +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, + const ASN1_OCTET_STRING *b); +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *str, const unsigned char *data, + int len); + +ASN1_VISIBLESTRING *ASN1_VISIBLESTRING_new(void); +void ASN1_VISIBLESTRING_free(ASN1_VISIBLESTRING *a); +ASN1_VISIBLESTRING *d2i_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING **a, const unsigned char **in, long len); +int i2d_ASN1_VISIBLESTRING(ASN1_VISIBLESTRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_VISIBLESTRING_it; +ASN1_UNIVERSALSTRING *ASN1_UNIVERSALSTRING_new(void); +void ASN1_UNIVERSALSTRING_free(ASN1_UNIVERSALSTRING *a); +ASN1_UNIVERSALSTRING *d2i_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING **a, const unsigned char **in, long len); +int i2d_ASN1_UNIVERSALSTRING(ASN1_UNIVERSALSTRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_UNIVERSALSTRING_it; +ASN1_UTF8STRING *ASN1_UTF8STRING_new(void); +void ASN1_UTF8STRING_free(ASN1_UTF8STRING *a); +ASN1_UTF8STRING *d2i_ASN1_UTF8STRING(ASN1_UTF8STRING **a, const unsigned char **in, long len); +int i2d_ASN1_UTF8STRING(ASN1_UTF8STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_UTF8STRING_it; +ASN1_NULL *ASN1_NULL_new(void); +void ASN1_NULL_free(ASN1_NULL *a); +ASN1_NULL *d2i_ASN1_NULL(ASN1_NULL **a, const unsigned char **in, long len); +int i2d_ASN1_NULL(ASN1_NULL *a, unsigned char **out); +extern const ASN1_ITEM ASN1_NULL_it; +ASN1_BMPSTRING *ASN1_BMPSTRING_new(void); +void ASN1_BMPSTRING_free(ASN1_BMPSTRING *a); +ASN1_BMPSTRING *d2i_ASN1_BMPSTRING(ASN1_BMPSTRING **a, const unsigned char **in, long len); +int i2d_ASN1_BMPSTRING(ASN1_BMPSTRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_BMPSTRING_it; + +ASN1_STRING *ASN1_PRINTABLE_new(void); +void ASN1_PRINTABLE_free(ASN1_STRING *a); +ASN1_STRING *d2i_ASN1_PRINTABLE(ASN1_STRING **a, const unsigned char **in, long len); +int i2d_ASN1_PRINTABLE(ASN1_STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_PRINTABLE_it; + +ASN1_STRING *DIRECTORYSTRING_new(void); +void DIRECTORYSTRING_free(ASN1_STRING *a); +ASN1_STRING *d2i_DIRECTORYSTRING(ASN1_STRING **a, const unsigned char **in, long len); +int i2d_DIRECTORYSTRING(ASN1_STRING *a, unsigned char **out); +extern const ASN1_ITEM DIRECTORYSTRING_it; +ASN1_STRING *DISPLAYTEXT_new(void); +void DISPLAYTEXT_free(ASN1_STRING *a); +ASN1_STRING *d2i_DISPLAYTEXT(ASN1_STRING **a, const unsigned char **in, long len); +int i2d_DISPLAYTEXT(ASN1_STRING *a, unsigned char **out); +extern const ASN1_ITEM DISPLAYTEXT_it; +ASN1_PRINTABLESTRING *ASN1_PRINTABLESTRING_new(void); +void ASN1_PRINTABLESTRING_free(ASN1_PRINTABLESTRING *a); +ASN1_PRINTABLESTRING *d2i_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING **a, const unsigned char **in, long len); +int i2d_ASN1_PRINTABLESTRING(ASN1_PRINTABLESTRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_PRINTABLESTRING_it; +ASN1_T61STRING *ASN1_T61STRING_new(void); +void ASN1_T61STRING_free(ASN1_T61STRING *a); +ASN1_T61STRING *d2i_ASN1_T61STRING(ASN1_T61STRING **a, const unsigned char **in, long len); +int i2d_ASN1_T61STRING(ASN1_T61STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_T61STRING_it; +ASN1_IA5STRING *ASN1_IA5STRING_new(void); +void ASN1_IA5STRING_free(ASN1_IA5STRING *a); +ASN1_IA5STRING *d2i_ASN1_IA5STRING(ASN1_IA5STRING **a, const unsigned char **in, long len); +int i2d_ASN1_IA5STRING(ASN1_IA5STRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_IA5STRING_it; +ASN1_GENERALSTRING *ASN1_GENERALSTRING_new(void); +void ASN1_GENERALSTRING_free(ASN1_GENERALSTRING *a); +ASN1_GENERALSTRING *d2i_ASN1_GENERALSTRING(ASN1_GENERALSTRING **a, const unsigned char **in, long len); +int i2d_ASN1_GENERALSTRING(ASN1_GENERALSTRING *a, unsigned char **out); +extern const ASN1_ITEM ASN1_GENERALSTRING_it; +ASN1_UTCTIME *ASN1_UTCTIME_new(void); +void ASN1_UTCTIME_free(ASN1_UTCTIME *a); +ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, const unsigned char **in, long len); +int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **out); +extern const ASN1_ITEM ASN1_UTCTIME_it; +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_new(void); +void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *a); +ASN1_GENERALIZEDTIME *d2i_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME **a, const unsigned char **in, long len); +int i2d_ASN1_GENERALIZEDTIME(ASN1_GENERALIZEDTIME *a, unsigned char **out); +extern const ASN1_ITEM ASN1_GENERALIZEDTIME_it; +ASN1_TIME *ASN1_TIME_new(void); +void ASN1_TIME_free(ASN1_TIME *a); +ASN1_TIME *d2i_ASN1_TIME(ASN1_TIME **a, const unsigned char **in, long len); +int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **out); +extern const ASN1_ITEM ASN1_TIME_it; + +int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm); +int ASN1_TIME_compare(const ASN1_TIME *t1, const ASN1_TIME *t2); +int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t2); +int ASN1_TIME_normalize(ASN1_TIME *t); +int ASN1_TIME_set_string_X509(ASN1_TIME *time, const char *str); +int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from, + const ASN1_TIME *to); + +extern const ASN1_ITEM ASN1_OCTET_STRING_NDEF_it; + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t); +ASN1_TIME *ASN1_TIME_set_tm(ASN1_TIME *s, struct tm *tm); +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, + long offset_sec); +int ASN1_TIME_check(const ASN1_TIME *t); +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, + ASN1_GENERALIZEDTIME **out); +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str); + +#ifndef OPENSSL_NO_BIO +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a); +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size); +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a); +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size); +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a); +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size); +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type); +#endif +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a); + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num); +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, + const char *sn, const char *ln); + +int ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint); +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val); +int ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint); +int ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val); +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); +long ASN1_INTEGER_get(const ASN1_INTEGER *a); +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn); + +int ASN1_ENUMERATED_get_int64(int64_t *out_val, const ASN1_ENUMERATED *aenum); +int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *aenum, int64_t val); +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v); +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a); +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai); +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn); + +/* General */ +/* given a string, return the correct type, max is the maximum length */ +int ASN1_PRINTABLE_type(const unsigned char *s, int max); + +/* SPECIALS */ +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, + int *pclass, long omax); +void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, + int xclass); +int ASN1_put_eoc(unsigned char **pp); +int ASN1_object_size(int constructed, int length, int tag); + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x); + +#ifndef LIBRESSL_INTERNAL + +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x); + +#endif /* !LIBRESSL_INTERNAL */ + +void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x); + +#define ASN1_d2i_fp_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_fp(CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x); +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x); + +#define ASN1_i2d_fp_of(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +#define ASN1_i2d_fp_of_const(type,i2d,out,x) \ + (ASN1_i2d_fp(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x); +int ASN1_STRING_print_ex_fp(FILE *fp, const ASN1_STRING *str, + unsigned long flags); + +int ASN1_STRING_to_UTF8(unsigned char **out, const ASN1_STRING *in); + +#ifndef OPENSSL_NO_BIO +void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x); + +#define ASN1_d2i_bio_of(type,xnew,d2i,in,x) \ + ((type*)ASN1_d2i_bio( CHECKED_NEW_OF(type, xnew), \ + CHECKED_D2I_OF(type, d2i), \ + in, \ + CHECKED_PPTR_OF(type, x))) + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x); +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x); + +#define ASN1_i2d_bio_of(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(type, i2d), \ + out, \ + CHECKED_PTR_OF(type, x))) + +#define ASN1_i2d_bio_of_const(type,i2d,out,x) \ + (ASN1_i2d_bio(CHECKED_I2D_OF(const type, i2d), \ + out, \ + CHECKED_PTR_OF(const type, x))) + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x); +int ASN1_UTCTIME_print(BIO *fp, const ASN1_UTCTIME *a); +int ASN1_GENERALIZEDTIME_print(BIO *fp, const ASN1_GENERALIZEDTIME *a); +int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a); +int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v); +int ASN1_STRING_print_ex(BIO *out, const ASN1_STRING *str, unsigned long flags); +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent); +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump); +#endif + +unsigned long ASN1_tag2bit(int tag); +const char *ASN1_tag2str(int tag); + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s); + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, const unsigned char *data, int len); +int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, + int max_len); +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, const unsigned char *data, + int len); +int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, + unsigned char *data, int max_len); + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, + ASN1_OCTET_STRING **oct); +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it); + +void ASN1_STRING_set_default_mask(unsigned long mask); +int ASN1_STRING_set_default_mask_asc(const char *p); +unsigned long ASN1_STRING_get_default_mask(void); +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask); +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, + int inform, unsigned long mask, long minsize, long maxsize); + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, + const unsigned char *in, int inlen, int inform, int nid); +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid); +int ASN1_STRING_TABLE_add(int, long, long, unsigned long, unsigned long); +void ASN1_STRING_TABLE_cleanup(void); + +/* ASN1 template functions */ + +/* Old API compatible functions */ +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it); +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **val, const unsigned char **in, + long len, const ASN1_ITEM *it); +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it); + +void ASN1_add_oid_module(void); + +ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf); +ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf); + +/* ASN1 Print flags */ + +/* Indicate missing OPTIONAL fields */ +#define ASN1_PCTX_FLAGS_SHOW_ABSENT 0x001 +/* Mark start and end of SEQUENCE */ +#define ASN1_PCTX_FLAGS_SHOW_SEQUENCE 0x002 +/* Mark start and end of SEQUENCE/SET OF */ +#define ASN1_PCTX_FLAGS_SHOW_SSOF 0x004 +/* Show the ASN1 type of primitives */ +#define ASN1_PCTX_FLAGS_SHOW_TYPE 0x008 +/* Don't show ASN1 type of ANY */ +#define ASN1_PCTX_FLAGS_NO_ANY_TYPE 0x010 +/* Don't show ASN1 type of MSTRINGs */ +#define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE 0x020 +/* Don't show field names in SEQUENCE */ +#define ASN1_PCTX_FLAGS_NO_FIELD_NAME 0x040 +/* Show structure names of each SEQUENCE field */ +#define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME 0x080 +/* Don't show structure name even at top level */ +#define ASN1_PCTX_FLAGS_NO_STRUCT_NAME 0x100 + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, + const ASN1_ITEM *it, const ASN1_PCTX *pctx); +ASN1_PCTX *ASN1_PCTX_new(void); +void ASN1_PCTX_free(ASN1_PCTX *p); +unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags); +unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p); +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags); + +int SMIME_crlf_copy(BIO *in, BIO *out, int flags); +int SMIME_text(BIO *in, BIO *out); + +void ERR_load_ASN1_strings(void); + +/* Error codes for the ASN1 functions. */ + +/* Function codes. */ +#define ASN1_F_A2D_ASN1_OBJECT 100 +#define ASN1_F_A2I_ASN1_ENUMERATED 101 +#define ASN1_F_A2I_ASN1_INTEGER 102 +#define ASN1_F_A2I_ASN1_STRING 103 +#define ASN1_F_APPEND_EXP 176 +#define ASN1_F_ASN1_BIT_STRING_SET_BIT 183 +#define ASN1_F_ASN1_CB 177 +#define ASN1_F_ASN1_CHECK_TLEN 104 +#define ASN1_F_ASN1_COLLATE_PRIMITIVE 105 +#define ASN1_F_ASN1_COLLECT 106 +#define ASN1_F_ASN1_D2I_EX_PRIMITIVE 108 +#define ASN1_F_ASN1_D2I_FP 109 +#define ASN1_F_ASN1_D2I_READ_BIO 107 +#define ASN1_F_ASN1_DIGEST 184 +#define ASN1_F_ASN1_DO_ADB 110 +#define ASN1_F_ASN1_DUP 111 +#define ASN1_F_ASN1_ENUMERATED_SET 112 +#define ASN1_F_ASN1_ENUMERATED_TO_BN 113 +#define ASN1_F_ASN1_EX_C2I 204 +#define ASN1_F_ASN1_FIND_END 190 +#define ASN1_F_ASN1_GENERALIZEDTIME_ADJ 216 +#define ASN1_F_ASN1_GENERALIZEDTIME_SET 185 +#define ASN1_F_ASN1_GENERATE_V3 178 +#define ASN1_F_ASN1_GET_OBJECT 114 +#define ASN1_F_ASN1_HEADER_NEW 115 +#define ASN1_F_ASN1_I2D_BIO 116 +#define ASN1_F_ASN1_I2D_FP 117 +#define ASN1_F_ASN1_INTEGER_SET 118 +#define ASN1_F_ASN1_INTEGER_TO_BN 119 +#define ASN1_F_ASN1_ITEM_D2I_FP 206 +#define ASN1_F_ASN1_ITEM_DUP 191 +#define ASN1_F_ASN1_ITEM_EX_COMBINE_NEW 121 +#define ASN1_F_ASN1_ITEM_EX_D2I 120 +#define ASN1_F_ASN1_ITEM_I2D_BIO 192 +#define ASN1_F_ASN1_ITEM_I2D_FP 193 +#define ASN1_F_ASN1_ITEM_PACK 198 +#define ASN1_F_ASN1_ITEM_SIGN 195 +#define ASN1_F_ASN1_ITEM_SIGN_CTX 220 +#define ASN1_F_ASN1_ITEM_UNPACK 199 +#define ASN1_F_ASN1_ITEM_VERIFY 197 +#define ASN1_F_ASN1_MBSTRING_NCOPY 122 +#define ASN1_F_ASN1_OBJECT_NEW 123 +#define ASN1_F_ASN1_OUTPUT_DATA 214 +#define ASN1_F_ASN1_PACK_STRING 124 +#define ASN1_F_ASN1_PCTX_NEW 205 +#define ASN1_F_ASN1_PKCS5_PBE_SET 125 +#define ASN1_F_ASN1_SEQ_PACK 126 +#define ASN1_F_ASN1_SEQ_UNPACK 127 +#define ASN1_F_ASN1_SIGN 128 +#define ASN1_F_ASN1_STR2TYPE 179 +#define ASN1_F_ASN1_STRING_SET 186 +#define ASN1_F_ASN1_STRING_TABLE_ADD 129 +#define ASN1_F_ASN1_STRING_TYPE_NEW 130 +#define ASN1_F_ASN1_TEMPLATE_EX_D2I 132 +#define ASN1_F_ASN1_TEMPLATE_NEW 133 +#define ASN1_F_ASN1_TEMPLATE_NOEXP_D2I 131 +#define ASN1_F_ASN1_TIME_ADJ 217 +#define ASN1_F_ASN1_TIME_SET 175 +#define ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING 134 +#define ASN1_F_ASN1_TYPE_GET_OCTETSTRING 135 +#define ASN1_F_ASN1_UNPACK_STRING 136 +#define ASN1_F_ASN1_UTCTIME_ADJ 218 +#define ASN1_F_ASN1_UTCTIME_SET 187 +#define ASN1_F_ASN1_VERIFY 137 +#define ASN1_F_B64_READ_ASN1 209 +#define ASN1_F_B64_WRITE_ASN1 210 +#define ASN1_F_BIO_NEW_NDEF 208 +#define ASN1_F_BITSTR_CB 180 +#define ASN1_F_BN_TO_ASN1_ENUMERATED 138 +#define ASN1_F_BN_TO_ASN1_INTEGER 139 +#define ASN1_F_C2I_ASN1_BIT_STRING 189 +#define ASN1_F_C2I_ASN1_INTEGER 194 +#define ASN1_F_C2I_ASN1_OBJECT 196 +#define ASN1_F_COLLECT_DATA 140 +#define ASN1_F_D2I_ASN1_BIT_STRING 141 +#define ASN1_F_D2I_ASN1_BOOLEAN 142 +#define ASN1_F_D2I_ASN1_BYTES 143 +#define ASN1_F_D2I_ASN1_GENERALIZEDTIME 144 +#define ASN1_F_D2I_ASN1_HEADER 145 +#define ASN1_F_D2I_ASN1_INTEGER 146 +#define ASN1_F_D2I_ASN1_OBJECT 147 +#define ASN1_F_D2I_ASN1_SET 148 +#define ASN1_F_D2I_ASN1_TYPE_BYTES 149 +#define ASN1_F_D2I_ASN1_UINTEGER 150 +#define ASN1_F_D2I_ASN1_UTCTIME 151 +#define ASN1_F_D2I_AUTOPRIVATEKEY 207 +#define ASN1_F_D2I_NETSCAPE_RSA 152 +#define ASN1_F_D2I_NETSCAPE_RSA_2 153 +#define ASN1_F_D2I_PRIVATEKEY 154 +#define ASN1_F_D2I_PUBLICKEY 155 +#define ASN1_F_D2I_RSA_NET 200 +#define ASN1_F_D2I_RSA_NET_2 201 +#define ASN1_F_D2I_X509 156 +#define ASN1_F_D2I_X509_CINF 157 +#define ASN1_F_D2I_X509_PKEY 159 +#define ASN1_F_I2D_ASN1_BIO_STREAM 211 +#define ASN1_F_I2D_ASN1_SET 188 +#define ASN1_F_I2D_ASN1_TIME 160 +#define ASN1_F_I2D_DSA_PUBKEY 161 +#define ASN1_F_I2D_EC_PUBKEY 181 +#define ASN1_F_I2D_PRIVATEKEY 163 +#define ASN1_F_I2D_PUBLICKEY 164 +#define ASN1_F_I2D_RSA_NET 162 +#define ASN1_F_I2D_RSA_PUBKEY 165 +#define ASN1_F_LONG_C2I 166 +#define ASN1_F_OID_MODULE_INIT 174 +#define ASN1_F_PARSE_TAGGING 182 +#define ASN1_F_PKCS5_PBE2_SET_IV 167 +#define ASN1_F_PKCS5_PBE_SET 202 +#define ASN1_F_PKCS5_PBE_SET0_ALGOR 215 +#define ASN1_F_PKCS5_PBKDF2_SET 219 +#define ASN1_F_SMIME_READ_ASN1 212 +#define ASN1_F_SMIME_TEXT 213 +#define ASN1_F_X509_CINF_NEW 168 +#define ASN1_F_X509_CRL_ADD0_REVOKED 169 +#define ASN1_F_X509_INFO_NEW 170 +#define ASN1_F_X509_NAME_ENCODE 203 +#define ASN1_F_X509_NAME_EX_D2I 158 +#define ASN1_F_X509_NAME_EX_NEW 171 +#define ASN1_F_X509_NEW 172 +#define ASN1_F_X509_PKEY_NEW 173 + +/* Reason codes. */ +#define ASN1_R_ADDING_OBJECT 171 +#define ASN1_R_ASN1_PARSE_ERROR 203 +#define ASN1_R_ASN1_SIG_PARSE_ERROR 204 +#define ASN1_R_AUX_ERROR 100 +#define ASN1_R_BAD_CLASS 101 +#define ASN1_R_BAD_OBJECT_HEADER 102 +#define ASN1_R_BAD_PASSWORD_READ 103 +#define ASN1_R_BAD_TAG 104 +#define ASN1_R_BAD_TEMPLATE 230 +#define ASN1_R_BMPSTRING_IS_WRONG_LENGTH 214 +#define ASN1_R_BN_LIB 105 +#define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106 +#define ASN1_R_BUFFER_TOO_SMALL 107 +#define ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 108 +#define ASN1_R_CONTEXT_NOT_INITIALISED 217 +#define ASN1_R_DATA_IS_WRONG 109 +#define ASN1_R_DECODE_ERROR 110 +#define ASN1_R_DECODING_ERROR 111 +#define ASN1_R_DEPTH_EXCEEDED 174 +#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 198 +#define ASN1_R_ENCODE_ERROR 112 +#define ASN1_R_ERROR_GETTING_TIME 173 +#define ASN1_R_ERROR_LOADING_SECTION 172 +#define ASN1_R_ERROR_PARSING_SET_ELEMENT 113 +#define ASN1_R_ERROR_SETTING_CIPHER_PARAMS 114 +#define ASN1_R_EXPECTING_AN_INTEGER 115 +#define ASN1_R_EXPECTING_AN_OBJECT 116 +#define ASN1_R_EXPECTING_A_BOOLEAN 117 +#define ASN1_R_EXPECTING_A_TIME 118 +#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119 +#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120 +#define ASN1_R_FIELD_MISSING 121 +#define ASN1_R_FIRST_NUM_TOO_LARGE 122 +#define ASN1_R_HEADER_TOO_LONG 123 +#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 175 +#define ASN1_R_ILLEGAL_BOOLEAN 176 +#define ASN1_R_ILLEGAL_CHARACTERS 124 +#define ASN1_R_ILLEGAL_FORMAT 177 +#define ASN1_R_ILLEGAL_HEX 178 +#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179 +#define ASN1_R_ILLEGAL_INTEGER 180 +#define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226 +#define ASN1_R_ILLEGAL_NESTED_TAGGING 181 +#define ASN1_R_ILLEGAL_NULL 125 +#define ASN1_R_ILLEGAL_NULL_VALUE 182 +#define ASN1_R_ILLEGAL_OBJECT 183 +#define ASN1_R_ILLEGAL_OPTIONAL_ANY 126 +#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 170 +#define ASN1_R_ILLEGAL_TAGGED_ANY 127 +#define ASN1_R_ILLEGAL_TIME_VALUE 184 +#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 185 +#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 128 +#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 220 +#define ASN1_R_INVALID_BMPSTRING_LENGTH 129 +#define ASN1_R_INVALID_DIGIT 130 +#define ASN1_R_INVALID_MIME_TYPE 205 +#define ASN1_R_INVALID_MODIFIER 186 +#define ASN1_R_INVALID_NUMBER 187 +#define ASN1_R_INVALID_OBJECT_ENCODING 216 +#define ASN1_R_INVALID_SEPARATOR 131 +#define ASN1_R_INVALID_TIME_FORMAT 132 +#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 133 +#define ASN1_R_INVALID_UTF8STRING 134 +#define ASN1_R_IV_TOO_LARGE 135 +#define ASN1_R_LENGTH_ERROR 136 +#define ASN1_R_LIST_ERROR 188 +#define ASN1_R_MIME_NO_CONTENT_TYPE 206 +#define ASN1_R_MIME_PARSE_ERROR 207 +#define ASN1_R_MIME_SIG_PARSE_ERROR 208 +#define ASN1_R_MISSING_EOC 137 +#define ASN1_R_MISSING_SECOND_NUMBER 138 +#define ASN1_R_MISSING_VALUE 189 +#define ASN1_R_MSTRING_NOT_UNIVERSAL 139 +#define ASN1_R_MSTRING_WRONG_TAG 140 +#define ASN1_R_NESTED_ASN1_STRING 197 +#define ASN1_R_NESTED_TOO_DEEP 219 +#define ASN1_R_NON_HEX_CHARACTERS 141 +#define ASN1_R_NOT_ASCII_FORMAT 190 +#define ASN1_R_NOT_ENOUGH_DATA 142 +#define ASN1_R_NO_CONTENT_TYPE 209 +#define ASN1_R_NO_DEFAULT_DIGEST 201 +#define ASN1_R_NO_MATCHING_CHOICE_TYPE 143 +#define ASN1_R_NO_MULTIPART_BODY_FAILURE 210 +#define ASN1_R_NO_MULTIPART_BOUNDARY 211 +#define ASN1_R_NO_SIG_CONTENT_TYPE 212 +#define ASN1_R_NULL_IS_WRONG_LENGTH 144 +#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 191 +#define ASN1_R_ODD_NUMBER_OF_CHARS 145 +#define ASN1_R_PRIVATE_KEY_HEADER_MISSING 146 +#define ASN1_R_SECOND_NUMBER_TOO_LARGE 147 +#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 148 +#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 149 +#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 192 +#define ASN1_R_SHORT_LINE 150 +#define ASN1_R_SIG_INVALID_MIME_TYPE 213 +#define ASN1_R_STREAMING_NOT_SUPPORTED 202 +#define ASN1_R_STRING_TOO_LONG 151 +#define ASN1_R_STRING_TOO_SHORT 152 +#define ASN1_R_TAG_VALUE_TOO_HIGH 153 +#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 +#define ASN1_R_TIME_NOT_ASCII_FORMAT 193 +#define ASN1_R_TOO_LARGE 223 +#define ASN1_R_TOO_LONG 155 +#define ASN1_R_TOO_SMALL 224 +#define ASN1_R_TYPE_NOT_CONSTRUCTED 156 +#define ASN1_R_TYPE_NOT_PRIMITIVE 231 +#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157 +#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158 +#define ASN1_R_UNEXPECTED_EOC 159 +#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 215 +#define ASN1_R_UNKNOWN_FORMAT 160 +#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 161 +#define ASN1_R_UNKNOWN_OBJECT_TYPE 162 +#define ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE 163 +#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 199 +#define ASN1_R_UNKNOWN_TAG 194 +#define ASN1_R_UNKOWN_FORMAT 195 +#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 164 +#define ASN1_R_UNSUPPORTED_CIPHER 165 +#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166 +#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 +#define ASN1_R_UNSUPPORTED_TYPE 196 +#define ASN1_R_WRONG_INTEGER_TYPE 225 +#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200 +#define ASN1_R_WRONG_TAG 168 +#define ASN1_R_WRONG_TYPE 169 + +int ASN1_time_parse(const char *_bytes, size_t _len, struct tm *_tm, int _mode); +int ASN1_time_tm_cmp(struct tm *_tm1, struct tm *_tm2); +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/asn1t.h b/include/openssl/asn1t.h new file mode 100644 index 0000000..4d79f82 --- /dev/null +++ b/include/openssl/asn1t.h @@ -0,0 +1,907 @@ +/* $OpenBSD: asn1t.h,v 1.23 2023/07/28 10:00:10 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_ASN1T_H +#define HEADER_ASN1T_H + +#include + +#include + +#include + +/* ASN1 template defines, structures and functions */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef LIBRESSL_INTERNAL + +/* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ +#define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) + + +/* Macros for start and end of ASN1_ITEM definition */ + +#define ASN1_ITEM_start(itname) \ + const ASN1_ITEM itname##_it = { + +#define static_ASN1_ITEM_start(itname) \ + static const ASN1_ITEM itname##_it = { + +#define ASN1_ITEM_end(itname) \ + }; + + + +/* Macros to aid ASN1 template writing */ + +#define ASN1_ITEM_TEMPLATE(tname) \ + static const ASN1_TEMPLATE tname##_item_tt + +#define ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + +#define static_ASN1_ITEM_TEMPLATE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_PRIMITIVE,\ + -1,\ + &tname##_item_tt,\ + 0,\ + NULL,\ + 0,\ + #tname \ + ASN1_ITEM_end(tname) + + +/* This is a ASN1 type which just embeds a template */ + +/* + * This pair helps declare a SEQUENCE. We can do: + * + * ASN1_SEQUENCE(stname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END(stname) + * + * This will produce an ASN1_ITEM called stname_it + * for a structure called stname. + * + * If you want the same structure but a different + * name then use: + * + * ASN1_SEQUENCE(itname) = { + * ... SEQUENCE components ... + * } ASN1_SEQUENCE_END_name(stname, itname) + * + * This will create an item called itname_it using + * a structure called stname. + */ + +#define ASN1_SEQUENCE(tname) \ + static const ASN1_TEMPLATE tname##_seq_tt[] + +#define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) + +#define static_ASN1_SEQUENCE_END(stname) static_ASN1_SEQUENCE_END_name(stname, stname) + +#define ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define static_ASN1_SEQUENCE_END_name(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_NDEF_SEQUENCE(tname) \ + ASN1_SEQUENCE(tname) + +#define ASN1_NDEF_SEQUENCE_cb(tname, cb) \ + ASN1_SEQUENCE_cb(tname, cb) + +#define ASN1_SEQUENCE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_ref(tname, cb, lck) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_SEQUENCE_enc(tname, enc, cb) \ + static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ + ASN1_SEQUENCE(tname) + +#define ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +#define static_ASN1_NDEF_SEQUENCE_END(tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(tname),\ + #tname \ + ASN1_ITEM_end(tname) + +#define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) + +#define static_ASN1_SEQUENCE_END_cb(stname, tname) static_ASN1_SEQUENCE_END_ref(stname, tname) + +#define ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define static_ASN1_SEQUENCE_END_ref(stname, tname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_NDEF_SEQUENCE_END_cb(stname, tname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_NDEF_SEQUENCE,\ + V_ASN1_SEQUENCE,\ + tname##_seq_tt,\ + sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + + +/* + * This pair helps declare a CHOICE type. We can do: + * + * ASN1_CHOICE(chname) = { + * ... CHOICE options ... + * ASN1_CHOICE_END(chname) + * + * This will produce an ASN1_ITEM called chname_it + * for a structure called chname. The structure + * definition must look like this: + * typedef struct { + * int type; + * union { + * ASN1_SOMETHING *opt1; + * ASN1_SOMEOTHER *opt2; + * } value; + * } chname; + * + * the name of the selector must be 'type'. + * to use an alternative selector name use the + * ASN1_CHOICE_END_selector() version. + */ + +#define ASN1_CHOICE(tname) \ + static const ASN1_TEMPLATE tname##_ch_tt[] + +#define ASN1_CHOICE_cb(tname, cb) \ + static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ + ASN1_CHOICE(tname) + +#define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) + +#define static_ASN1_CHOICE_END(stname) static_ASN1_CHOICE_END_name(stname, stname) + +#define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) + +#define static_ASN1_CHOICE_END_name(stname, tname) static_ASN1_CHOICE_END_selector(stname, tname, type) + +#define ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define static_ASN1_CHOICE_END_selector(stname, tname, selname) \ + ;\ + static_ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + NULL,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +#define ASN1_CHOICE_END_cb(stname, tname, selname) \ + ;\ + ASN1_ITEM_start(tname) \ + ASN1_ITYPE_CHOICE,\ + offsetof(stname,selname) ,\ + tname##_ch_tt,\ + sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ + &tname##_aux,\ + sizeof(stname),\ + #stname \ + ASN1_ITEM_end(tname) + +/* This helps with the template wrapper form of ASN1_ITEM */ + +#define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ + (flags), (tag), 0,\ + #name, ASN1_ITEM_ref(type) } + +/* These help with SEQUENCE or CHOICE components */ + +/* used to declare other types */ + +#define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ + (flags), (tag), offsetof(stname, field),\ + #field, ASN1_ITEM_ref(type) } + +/* implicit and explicit helper macros */ + +#define ASN1_IMP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) + +#define ASN1_EXP_EX(stname, field, type, tag, ex) \ + ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) + +/* Any defined by macros: the field used is in the table itself */ + +#define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +#define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } +/* Plain simple type */ +#define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) + +/* OPTIONAL simple type */ +#define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* IMPLICIT tagged simple type */ +#define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) + +/* IMPLICIT tagged OPTIONAL simple type */ +#define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* Same as above but EXPLICIT */ + +#define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) +#define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) + +/* SEQUENCE OF type */ +#define ASN1_SEQUENCE_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) + +/* OPTIONAL SEQUENCE OF */ +#define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Same as above but for SET OF */ + +#define ASN1_SET_OF(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) + +#define ASN1_SET_OF_OPT(stname, field, type) \ + ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) + +/* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ + +#define ASN1_IMP_SET_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_EXP_SET_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) + +#define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +#define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) + +#define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) + +/* EXPLICIT using indefinite length constructed form */ +#define ASN1_NDEF_EXP(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_NDEF) + +/* EXPLICIT OPTIONAL using indefinite length constructed form */ +#define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ + ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) + +/* Macros for the ASN1_ADB structure */ + +#define ASN1_ADB(name) \ + static const ASN1_ADB_TABLE name##_adbtbl[] + + +#define ASN1_ADB_END(name, flags, field, app_table, def, none) \ + ;\ + static const ASN1_ADB name##_adb = {\ + flags,\ + offsetof(name, field),\ + app_table,\ + name##_adbtbl,\ + sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ + def,\ + none\ + } + + +#define ADB_ENTRY(val, template) {val, template} + +#define ASN1_ADB_TEMPLATE(name) \ + static const ASN1_TEMPLATE name##_tt + +#endif /* !LIBRESSL_INTERNAL */ + +/* This is the ASN1 template structure that defines + * a wrapper round the actual type. It determines the + * actual position of the field in the value structure, + * various flags such as OPTIONAL and the field name. + */ + +struct ASN1_TEMPLATE_st { + unsigned long flags; /* Various flags */ + long tag; /* tag, not used if no tagging */ + unsigned long offset; /* Offset of this field in structure */ + const char *field_name; /* Field name */ + ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ +}; + +/* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ + +#define ASN1_TEMPLATE_item(t) (t->item_ptr) +#define ASN1_TEMPLATE_adb(t) (t->item_ptr) + +typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; +typedef struct ASN1_ADB_st ASN1_ADB; + +struct ASN1_ADB_st { + unsigned long flags; /* Various flags */ + unsigned long offset; /* Offset of selector field */ + const ASN1_ADB_TABLE *tbl; /* Table of possible types */ + long tblcount; /* Number of entries in tbl */ + const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ + const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ +}; + +struct ASN1_ADB_TABLE_st { + long value; /* NID for an object or value for an int */ + const ASN1_TEMPLATE tt; /* item for this value */ +}; + +/* template flags */ + +/* Field is optional */ +#define ASN1_TFLG_OPTIONAL (0x1) + +/* Field is a SET OF */ +#define ASN1_TFLG_SET_OF (0x1 << 1) + +/* Field is a SEQUENCE OF */ +#define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) + +/* Special case: this refers to a SET OF that + * will be sorted into DER order when encoded *and* + * the corresponding STACK will be modified to match + * the new order. + */ +#define ASN1_TFLG_SET_ORDER (0x3 << 1) + +/* Mask for SET OF or SEQUENCE OF */ +#define ASN1_TFLG_SK_MASK (0x3 << 1) + +/* These flags mean the tag should be taken from the + * tag field. If EXPLICIT then the underlying type + * is used for the inner tag. + */ + +/* IMPLICIT tagging */ +#define ASN1_TFLG_IMPTAG (0x1 << 3) + + +/* EXPLICIT tagging, inner tag from underlying type */ +#define ASN1_TFLG_EXPTAG (0x2 << 3) + +#define ASN1_TFLG_TAG_MASK (0x3 << 3) + +/* context specific IMPLICIT */ +#define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT + +/* context specific EXPLICIT */ +#define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT + +/* + * If tagging is in force these determine the type of tag to use. Otherwiser + * the tag is determined by the underlying type. These values reflect the + * actual octet format. + */ + +/* Universal tag */ +#define ASN1_TFLG_UNIVERSAL (0x0<<6) +/* Application tag */ +#define ASN1_TFLG_APPLICATION (0x1<<6) +/* Context specific tag */ +#define ASN1_TFLG_CONTEXT (0x2<<6) +/* Private tag */ +#define ASN1_TFLG_PRIVATE (0x3<<6) + +#define ASN1_TFLG_TAG_CLASS (0x3<<6) + +/* + * These are for ANY DEFINED BY type. In this case + * the 'item' field points to an ASN1_ADB structure + * which contains a table of values to decode the + * relevant type + */ + +#define ASN1_TFLG_ADB_MASK (0x3<<8) + +#define ASN1_TFLG_ADB_OID (0x1<<8) + +#define ASN1_TFLG_ADB_INT (0x1<<9) + +/* + * This flag when present in a SEQUENCE OF, SET OF + * or EXPLICIT causes indefinite length constructed + * encoding to be used if required. + */ + +#define ASN1_TFLG_NDEF (0x1<<11) + +/* This is the actual ASN1 item itself */ + +struct ASN1_ITEM_st { + char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ + long utype; /* underlying type */ + const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ + long tcount; /* Number of templates if SEQUENCE or CHOICE */ + const void *funcs; /* functions that handle this type */ + long size; /* Structure size (usually)*/ + const char *sname; /* Structure name */ +}; + +/* These are values for the itype field and + * determine how the type is interpreted. + * + * For PRIMITIVE types the underlying type + * determines the behaviour if items is NULL. + * + * Otherwise templates must contain a single + * template and the type is treated in the + * same way as the type specified in the template. + * + * For SEQUENCE types the templates field points + * to the members, the size field is the + * structure size. + * + * For CHOICE types the templates field points + * to each possible member (typically a union) + * and the 'size' field is the offset of the + * selector. + * + * The 'funcs' field is used for application + * specific functions. + * + * The EXTERN type uses a new style d2i/i2d. + * The new style should be used where possible + * because it avoids things like the d2i IMPLICIT + * hack. + * + * MSTRING is a multiple string type, it is used + * for a CHOICE of character strings where the + * actual strings all occupy an ASN1_STRING + * structure. In this case the 'utype' field + * has a special meaning, it is used as a mask + * of acceptable types using the B_ASN1 constants. + * + * NDEF_SEQUENCE is the same as SEQUENCE except + * that it will use indefinite length constructed + * encoding if requested. + * + */ + +#define ASN1_ITYPE_PRIMITIVE 0x0 + +#define ASN1_ITYPE_SEQUENCE 0x1 + +#define ASN1_ITYPE_CHOICE 0x2 + +#define ASN1_ITYPE_EXTERN 0x4 + +#define ASN1_ITYPE_MSTRING 0x5 + +#define ASN1_ITYPE_NDEF_SEQUENCE 0x6 + +/* Cache for ASN1 tag and length, so we + * don't keep re-reading it for things + * like CHOICE + */ + +struct ASN1_TLC_st { + char valid; /* Values below are valid */ + int ret; /* return value */ + long plen; /* length */ + int ptag; /* class value */ + int pclass; /* class value */ + int hdrlen; /* header length */ +}; + +/* Typedefs for ASN1 function pointers */ + +typedef ASN1_VALUE * ASN1_new_func(void); +typedef void ASN1_free_func(ASN1_VALUE *a); +typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length); +typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in); + +typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); +typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); +typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); + +typedef int ASN1_ex_print_func(BIO *out, ASN1_VALUE **pval, + int indent, const char *fname, + const ASN1_PCTX *pctx); + +typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); +typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); +typedef int ASN1_primitive_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx); + +typedef struct ASN1_EXTERN_FUNCS_st { + void *app_data; + ASN1_ex_new_func *asn1_ex_new; + ASN1_ex_free_func *asn1_ex_free; + ASN1_ex_free_func *asn1_ex_clear; + ASN1_ex_d2i *asn1_ex_d2i; + ASN1_ex_i2d *asn1_ex_i2d; + ASN1_ex_print_func *asn1_ex_print; +} ASN1_EXTERN_FUNCS; + +typedef struct ASN1_PRIMITIVE_FUNCS_st { + void *app_data; + unsigned long flags; + ASN1_ex_new_func *prim_new; + ASN1_ex_free_func *prim_free; + ASN1_ex_free_func *prim_clear; + ASN1_primitive_c2i *prim_c2i; + ASN1_primitive_i2c *prim_i2c; + ASN1_primitive_print *prim_print; +} ASN1_PRIMITIVE_FUNCS; + +/* This is the ASN1_AUX structure: it handles various + * miscellaneous requirements. For example the use of + * reference counts and an informational callback. + * + * The "informational callback" is called at various + * points during the ASN1 encoding and decoding. It can + * be used to provide minor customisation of the structures + * used. This is most useful where the supplied routines + * *almost* do the right thing but need some extra help + * at a few points. If the callback returns zero then + * it is assumed a fatal error has occurred and the + * main operation should be abandoned. + * + * If major changes in the default behaviour are required + * then an external type is more appropriate. + */ + +typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it, + void *exarg); + +typedef struct ASN1_AUX_st { + void *app_data; + int flags; + int ref_offset; /* Offset of reference value */ + int ref_lock; /* Lock type to use */ + ASN1_aux_cb *asn1_cb; + int enc_offset; /* Offset of ASN1_ENCODING structure */ +} ASN1_AUX; + +/* For print related callbacks exarg points to this structure */ +typedef struct ASN1_PRINT_ARG_st { + BIO *out; + int indent; + const ASN1_PCTX *pctx; +} ASN1_PRINT_ARG; + +/* For streaming related callbacks exarg points to this structure */ +typedef struct ASN1_STREAM_ARG_st { + /* BIO to stream through */ + BIO *out; + /* BIO with filters appended */ + BIO *ndef_bio; + /* Streaming I/O boundary */ + unsigned char **boundary; +} ASN1_STREAM_ARG; + +/* Flags in ASN1_AUX */ + +/* Use a reference count */ +#define ASN1_AFLG_REFCOUNT 1 +/* Save the encoding of structure (useful for signatures) */ +#define ASN1_AFLG_ENCODING 2 + +/* operation values for asn1_cb */ + +#define ASN1_OP_NEW_PRE 0 +#define ASN1_OP_NEW_POST 1 +#define ASN1_OP_FREE_PRE 2 +#define ASN1_OP_FREE_POST 3 +#define ASN1_OP_D2I_PRE 4 +#define ASN1_OP_D2I_POST 5 +#define ASN1_OP_I2D_PRE 6 +#define ASN1_OP_I2D_POST 7 +#define ASN1_OP_PRINT_PRE 8 +#define ASN1_OP_PRINT_POST 9 +#define ASN1_OP_STREAM_PRE 10 +#define ASN1_OP_STREAM_POST 11 +#define ASN1_OP_DETACHED_PRE 12 +#define ASN1_OP_DETACHED_POST 13 + +#ifndef LIBRESSL_INTERNAL + +/* Macro to implement a primitive type */ +#define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) +#define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ + ASN1_ITEM_end(itname) + +/* Macro to implement a multi string type */ +#define IMPLEMENT_ASN1_MSTRING(itname, mask) \ + ASN1_ITEM_start(itname) \ + ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ + ASN1_ITEM_end(itname) +#define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ + ASN1_ITEM_start(sname) \ + ASN1_ITYPE_EXTERN, \ + tag, \ + NULL, \ + 0, \ + &fptrs, \ + 0, \ + #sname \ + ASN1_ITEM_end(sname) + +/* Macro to implement standard functions in terms of ASN1_ITEM structures */ + +#define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) + +#define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ + IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) + +#define IMPLEMENT_STATIC_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(static, stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname(pre, stname, itname, fname) \ + pre stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + pre void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ + stname *fname##_new(void) \ + { \ + return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ + } \ + void fname##_free(stname *a) \ + { \ + ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ + int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ + { \ + return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ + } + +/* This includes evil casts to remove const: they will go away when full + * ASN1 constification is done. + */ +#define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ + { \ + return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ + } \ + int i2d_##fname(const stname *a, unsigned char **out) \ + { \ + return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ + } + +#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ + stname * stname##_dup(stname *x) \ + { \ + return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ + } + +#define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \ + IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname) + +#define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \ + int fname##_print_ctx(BIO *out, stname *x, int indent, \ + const ASN1_PCTX *pctx) \ + { \ + return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \ + ASN1_ITEM_rptr(itname), pctx); \ + } + +#define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ + IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) + +#define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ + IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) + +#endif /* !LIBRESSL_INTERNAL */ + +/* external definitions for primitive types */ + +extern const ASN1_ITEM ASN1_BOOLEAN_it; +extern const ASN1_ITEM ASN1_TBOOLEAN_it; +extern const ASN1_ITEM ASN1_FBOOLEAN_it; +extern const ASN1_ITEM ASN1_SEQUENCE_it; +extern const ASN1_ITEM BIGNUM_it; +extern const ASN1_ITEM LONG_it; +extern const ASN1_ITEM ZLONG_it; + +#ifndef LIBRESSL_INTERNAL +extern const ASN1_ITEM CBIGNUM_it; +#endif + +DECLARE_STACK_OF(ASN1_VALUE) + +/* Functions used internally by the ASN1 code */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, + int tag, int aclass, char opt, ASN1_TLC *ctx); + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/bio.h b/include/openssl/bio.h new file mode 100644 index 0000000..b955524 --- /dev/null +++ b/include/openssl/bio.h @@ -0,0 +1,747 @@ +/* $OpenBSD: bio.h,v 1.60 2023/08/25 12:37:33 schwarze Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BIO_H +#define HEADER_BIO_H +#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__OpenBSD__) +#define __bounded__(x, y, z) +#endif +#include + +# include +#include + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* These are the 'types' of BIOs */ +#define BIO_TYPE_NONE 0 +#define BIO_TYPE_MEM (1|0x0400) +#define BIO_TYPE_FILE (2|0x0400) + +#define BIO_TYPE_FD (4|0x0400|0x0100) +#define BIO_TYPE_SOCKET (5|0x0400|0x0100) +#define BIO_TYPE_NULL (6|0x0400) +#define BIO_TYPE_SSL (7|0x0200) +#define BIO_TYPE_MD (8|0x0200) /* passive filter */ +#define BIO_TYPE_BUFFER (9|0x0200) /* filter */ +#define BIO_TYPE_CIPHER (10|0x0200) /* filter */ +#define BIO_TYPE_BASE64 (11|0x0200) /* filter */ +#define BIO_TYPE_CONNECT (12|0x0400|0x0100) /* socket - connect */ +#define BIO_TYPE_ACCEPT (13|0x0400|0x0100) /* socket for accept */ +#define BIO_TYPE_PROXY_CLIENT (14|0x0200) /* client proxy BIO */ +#define BIO_TYPE_PROXY_SERVER (15|0x0200) /* server proxy BIO */ +#define BIO_TYPE_NBIO_TEST (16|0x0200) /* server proxy BIO */ +#define BIO_TYPE_NULL_FILTER (17|0x0200) +#define BIO_TYPE_BER (18|0x0200) /* BER -> bin filter */ +#define BIO_TYPE_BIO (19|0x0400) /* (half a) BIO pair */ +#define BIO_TYPE_LINEBUFFER (20|0x0200) /* filter */ +#define BIO_TYPE_DGRAM (21|0x0400|0x0100) +#define BIO_TYPE_ASN1 (22|0x0200) /* filter */ +#define BIO_TYPE_COMP (23|0x0200) /* filter */ + +#define BIO_TYPE_DESCRIPTOR 0x0100 /* socket, fd, connect or accept */ +#define BIO_TYPE_FILTER 0x0200 +#define BIO_TYPE_SOURCE_SINK 0x0400 + +/* + * BIO_TYPE_START is the first user-allocated BIO type. No pre-defined type, + * flag bits aside, may exceed this value. + */ +#define BIO_TYPE_START 128 + +/* BIO_FILENAME_READ|BIO_CLOSE to open or close on free. + * BIO_set_fp(in,stdin,BIO_NOCLOSE); */ +#define BIO_NOCLOSE 0x00 +#define BIO_CLOSE 0x01 + +/* These are used in the following macros and are passed to + * BIO_ctrl() */ +#define BIO_CTRL_RESET 1 /* opt - rewind/zero etc */ +#define BIO_CTRL_EOF 2 /* opt - are we at the eof */ +#define BIO_CTRL_INFO 3 /* opt - extra tit-bits */ +#define BIO_CTRL_SET 4 /* man - set the 'IO' type */ +#define BIO_CTRL_GET 5 /* man - get the 'IO' type */ +#define BIO_CTRL_PUSH 6 /* opt - internal, used to signify change */ +#define BIO_CTRL_POP 7 /* opt - internal, used to signify change */ +#define BIO_CTRL_GET_CLOSE 8 /* man - set the 'close' on free */ +#define BIO_CTRL_SET_CLOSE 9 /* man - set the 'close' on free */ +#define BIO_CTRL_PENDING 10 /* opt - is their more data buffered */ +#define BIO_CTRL_FLUSH 11 /* opt - 'flush' buffered output */ +#define BIO_CTRL_DUP 12 /* man - extra stuff for 'duped' BIO */ +#define BIO_CTRL_WPENDING 13 /* opt - number of bytes still to write */ +/* callback is int cb(BIO *bio,state,ret); */ +#define BIO_CTRL_SET_CALLBACK 14 /* opt - set callback function */ +#define BIO_CTRL_GET_CALLBACK 15 /* opt - set callback function */ + +#define BIO_CTRL_SET_FILENAME 30 /* BIO_s_file special */ + +/* dgram BIO stuff */ +#define BIO_CTRL_DGRAM_CONNECT 31 /* BIO dgram special */ +#define BIO_CTRL_DGRAM_SET_CONNECTED 32 /* allow for an externally + * connected socket to be + * passed in */ +#define BIO_CTRL_DGRAM_SET_RECV_TIMEOUT 33 /* setsockopt, essentially */ +#define BIO_CTRL_DGRAM_GET_RECV_TIMEOUT 34 /* getsockopt, essentially */ +#define BIO_CTRL_DGRAM_SET_SEND_TIMEOUT 35 /* setsockopt, essentially */ +#define BIO_CTRL_DGRAM_GET_SEND_TIMEOUT 36 /* getsockopt, essentially */ + +#define BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP 37 /* flag whether the last */ +#define BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP 38 /* I/O operation tiemd out */ + +/* #ifdef IP_MTU_DISCOVER */ +#define BIO_CTRL_DGRAM_MTU_DISCOVER 39 /* set DF bit on egress packets */ +/* #endif */ + +#define BIO_CTRL_DGRAM_QUERY_MTU 40 /* as kernel for current MTU */ +#define BIO_CTRL_DGRAM_GET_FALLBACK_MTU 47 +#define BIO_CTRL_DGRAM_GET_MTU 41 /* get cached value for MTU */ +#define BIO_CTRL_DGRAM_SET_MTU 42 /* set cached value for + * MTU. want to use this + * if asking the kernel + * fails */ + +#define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU + * was exceed in the + * previous write + * operation */ + +#define BIO_CTRL_DGRAM_GET_PEER 46 +#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the data */ + +#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake timeout to + * adjust socket timeouts */ + + +/* modifiers */ +#define BIO_FP_READ 0x02 +#define BIO_FP_WRITE 0x04 +#define BIO_FP_APPEND 0x08 +#define BIO_FP_TEXT 0x10 + +#define BIO_FLAGS_READ 0x01 +#define BIO_FLAGS_WRITE 0x02 +#define BIO_FLAGS_IO_SPECIAL 0x04 +#define BIO_FLAGS_RWS (BIO_FLAGS_READ|BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL) +#define BIO_FLAGS_SHOULD_RETRY 0x08 + +/* Used in BIO_gethostbyname() */ +#define BIO_GHBN_CTRL_HITS 1 +#define BIO_GHBN_CTRL_MISSES 2 +#define BIO_GHBN_CTRL_CACHE_SIZE 3 +#define BIO_GHBN_CTRL_GET_ENTRY 4 +#define BIO_GHBN_CTRL_FLUSH 5 + +/* Mostly used in the SSL BIO */ +/* Not used anymore + * #define BIO_FLAGS_PROTOCOL_DELAYED_READ 0x10 + * #define BIO_FLAGS_PROTOCOL_DELAYED_WRITE 0x20 + * #define BIO_FLAGS_PROTOCOL_STARTUP 0x40 + */ + +#define BIO_FLAGS_BASE64_NO_NL 0x100 + +/* This is used with memory BIOs: it means we shouldn't free up or change the + * data in any way. + */ +#define BIO_FLAGS_MEM_RDONLY 0x200 + +void BIO_set_flags(BIO *b, int flags); +int BIO_test_flags(const BIO *b, int flags); +void BIO_clear_flags(BIO *b, int flags); + +#define BIO_get_flags(b) BIO_test_flags(b, ~(0x0)) +#define BIO_set_retry_special(b) \ + BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_set_retry_read(b) \ + BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_set_retry_write(b) \ + BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY)) + +/* These are normally used internally in BIOs */ +#define BIO_clear_retry_flags(b) \ + BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) +#define BIO_get_retry_flags(b) \ + BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY)) + +/* These should be used by the application to tell why we should retry */ +#define BIO_should_read(a) BIO_test_flags(a, BIO_FLAGS_READ) +#define BIO_should_write(a) BIO_test_flags(a, BIO_FLAGS_WRITE) +#define BIO_should_io_special(a) BIO_test_flags(a, BIO_FLAGS_IO_SPECIAL) +#define BIO_retry_type(a) BIO_test_flags(a, BIO_FLAGS_RWS) +#define BIO_should_retry(a) BIO_test_flags(a, BIO_FLAGS_SHOULD_RETRY) + +/* The next three are used in conjunction with the + * BIO_should_io_special() condition. After this returns true, + * BIO *BIO_get_retry_BIO(BIO *bio, int *reason); will walk the BIO + * stack and return the 'reason' for the special and the offending BIO. + * Given a BIO, BIO_get_retry_reason(bio) will return the code. */ +/* Returned from the SSL bio when the certificate retrieval code had an error */ +#define BIO_RR_SSL_X509_LOOKUP 0x01 +/* Returned from the connect BIO when a connect would have blocked */ +#define BIO_RR_CONNECT 0x02 +/* Returned from the accept BIO when an accept would have blocked */ +#define BIO_RR_ACCEPT 0x03 + +/* These are passed by the BIO callback */ +#define BIO_CB_FREE 0x01 +#define BIO_CB_READ 0x02 +#define BIO_CB_WRITE 0x03 +#define BIO_CB_PUTS 0x04 +#define BIO_CB_GETS 0x05 +#define BIO_CB_CTRL 0x06 + +/* + * The callback is called before and after the underling operation, + * the BIO_CB_RETURN flag indicates if it is after the call. + */ +#define BIO_CB_RETURN 0x80 +#define BIO_CB_return(a) ((a)|BIO_CB_RETURN)) +#define BIO_cb_pre(a) (!((a)&BIO_CB_RETURN)) +#define BIO_cb_post(a) ((a)&BIO_CB_RETURN) + +typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi, + long argl, long ret); +typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp, + size_t len, int argi, long argl, int ret, size_t *processed); + +BIO_callback_fn BIO_get_callback(const BIO *b); +void BIO_set_callback(BIO *b, BIO_callback_fn callback); + +BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b); +void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback); + +char *BIO_get_callback_arg(const BIO *b); +void BIO_set_callback_arg(BIO *b, char *arg); + +const char *BIO_method_name(const BIO *b); +int BIO_method_type(const BIO *b); + +typedef int BIO_info_cb(BIO *, int, int); +/* Compatibility with OpenSSL's backward compatibility. */ +typedef BIO_info_cb bio_info_cb; + +typedef struct bio_method_st BIO_METHOD; + +DECLARE_STACK_OF(BIO) + +/* Prefix and suffix callback in ASN1 BIO */ +typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg); + +/* BIO_METHOD accessors */ +BIO_METHOD *BIO_meth_new(int type, const char *name); +void BIO_meth_free(BIO_METHOD *biom); +int (*BIO_meth_get_write(const BIO_METHOD *biom))(BIO *, const char *, int); +int BIO_meth_set_write(BIO_METHOD *biom, + int (*write)(BIO *, const char *, int)); +int (*BIO_meth_get_read(const BIO_METHOD *biom))(BIO *, char *, int); +int BIO_meth_set_read(BIO_METHOD *biom, int (*read)(BIO *, char *, int)); +int (*BIO_meth_get_puts(const BIO_METHOD *biom))(BIO *, const char *); +int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts)(BIO *, const char *)); +int (*BIO_meth_get_gets(const BIO_METHOD *biom))(BIO *, char *, int); +int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets)(BIO *, char *, int)); +long (*BIO_meth_get_ctrl(const BIO_METHOD *biom))(BIO *, int, long, void *); +int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl)(BIO *, int, long, void *)); +int (*BIO_meth_get_create(const BIO_METHOD *biom))(BIO *); +int BIO_meth_set_create(BIO_METHOD *biom, int (*create)(BIO *)); +int (*BIO_meth_get_destroy(const BIO_METHOD *biom))(BIO *); +int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy)(BIO *)); +long (*BIO_meth_get_callback_ctrl(const BIO_METHOD *biom))(BIO *, int, BIO_info_cb *); +int BIO_meth_set_callback_ctrl(BIO_METHOD *biom, + long (*callback_ctrl)(BIO *, int, BIO_info_cb *)); + +/* connect BIO stuff */ +#define BIO_CONN_S_BEFORE 1 +#define BIO_CONN_S_GET_IP 2 +#define BIO_CONN_S_GET_PORT 3 +#define BIO_CONN_S_CREATE_SOCKET 4 +#define BIO_CONN_S_CONNECT 5 +#define BIO_CONN_S_OK 6 +#define BIO_CONN_S_BLOCKED_CONNECT 7 +#define BIO_CONN_S_NBIO 8 +/*#define BIO_CONN_get_param_hostname BIO_ctrl */ + +#define BIO_C_SET_CONNECT 100 +#define BIO_C_DO_STATE_MACHINE 101 +#define BIO_C_SET_NBIO 102 +#define BIO_C_SET_PROXY_PARAM 103 +#define BIO_C_SET_FD 104 +#define BIO_C_GET_FD 105 +#define BIO_C_SET_FILE_PTR 106 +#define BIO_C_GET_FILE_PTR 107 +#define BIO_C_SET_FILENAME 108 +#define BIO_C_SET_SSL 109 +#define BIO_C_GET_SSL 110 +#define BIO_C_SET_MD 111 +#define BIO_C_GET_MD 112 +#define BIO_C_GET_CIPHER_STATUS 113 +#define BIO_C_SET_BUF_MEM 114 +#define BIO_C_GET_BUF_MEM_PTR 115 +#define BIO_C_GET_BUFF_NUM_LINES 116 +#define BIO_C_SET_BUFF_SIZE 117 +#define BIO_C_SET_ACCEPT 118 +#define BIO_C_SSL_MODE 119 +#define BIO_C_GET_MD_CTX 120 +#define BIO_C_GET_PROXY_PARAM 121 +#define BIO_C_SET_BUFF_READ_DATA 122 /* data to read first */ +#define BIO_C_GET_CONNECT 123 +#define BIO_C_GET_ACCEPT 124 +#define BIO_C_SET_SSL_RENEGOTIATE_BYTES 125 +#define BIO_C_GET_SSL_NUM_RENEGOTIATES 126 +#define BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT 127 +#define BIO_C_FILE_SEEK 128 +#define BIO_C_GET_CIPHER_CTX 129 +#define BIO_C_SET_BUF_MEM_EOF_RETURN 130/*return end of input value*/ +#define BIO_C_SET_BIND_MODE 131 +#define BIO_C_GET_BIND_MODE 132 +#define BIO_C_FILE_TELL 133 +#define BIO_C_GET_SOCKS 134 +#define BIO_C_SET_SOCKS 135 + +#define BIO_C_SET_WRITE_BUF_SIZE 136/* for BIO_s_bio */ +#define BIO_C_GET_WRITE_BUF_SIZE 137 +#define BIO_C_MAKE_BIO_PAIR 138 +#define BIO_C_DESTROY_BIO_PAIR 139 +#define BIO_C_GET_WRITE_GUARANTEE 140 +#define BIO_C_GET_READ_REQUEST 141 +#define BIO_C_SHUTDOWN_WR 142 +#define BIO_C_NREAD0 143 +#define BIO_C_NREAD 144 +#define BIO_C_NWRITE0 145 +#define BIO_C_NWRITE 146 +#define BIO_C_RESET_READ_REQUEST 147 +#define BIO_C_SET_MD_CTX 148 + +#define BIO_C_SET_EX_ARG 153 +#define BIO_C_GET_EX_ARG 154 + +#define BIO_set_app_data(s,arg) BIO_set_ex_data(s,0,arg) +#define BIO_get_app_data(s) BIO_get_ex_data(s,0) + +/* BIO_s_connect() and BIO_s_socks4a_connect() */ +#define BIO_set_conn_hostname(b,name) BIO_ctrl(b,BIO_C_SET_CONNECT,0,(char *)name) +#define BIO_set_conn_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,1,(char *)port) +#define BIO_set_conn_ip(b,ip) BIO_ctrl(b,BIO_C_SET_CONNECT,2,(char *)ip) +#define BIO_set_conn_int_port(b,port) BIO_ctrl(b,BIO_C_SET_CONNECT,3,(char *)port) +#define BIO_get_conn_hostname(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,0) +#define BIO_get_conn_port(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,1) +#define BIO_get_conn_ip(b) BIO_ptr_ctrl(b,BIO_C_GET_CONNECT,2) +#define BIO_get_conn_int_port(b) BIO_int_ctrl(b,BIO_C_GET_CONNECT,3,0) + + +#define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) + +/* BIO_s_accept_socket() */ +#define BIO_set_accept_port(b,name) BIO_ctrl(b,BIO_C_SET_ACCEPT,0,(char *)name) +#define BIO_get_accept_port(b) BIO_ptr_ctrl(b,BIO_C_GET_ACCEPT,0) +/* #define BIO_set_nbio(b,n) BIO_ctrl(b,BIO_C_SET_NBIO,(n),NULL) */ +#define BIO_set_nbio_accept(b,n) BIO_ctrl(b,BIO_C_SET_ACCEPT,1,(n)?(void *)"a":NULL) +#define BIO_set_accept_bios(b,bio) BIO_ctrl(b,BIO_C_SET_ACCEPT,2,(char *)bio) + +#define BIO_BIND_NORMAL 0 +#define BIO_BIND_REUSEADDR_IF_UNUSED 1 +#define BIO_BIND_REUSEADDR 2 +#define BIO_set_bind_mode(b,mode) BIO_ctrl(b,BIO_C_SET_BIND_MODE,mode,NULL) +#define BIO_get_bind_mode(b,mode) BIO_ctrl(b,BIO_C_GET_BIND_MODE,0,NULL) + +#define BIO_do_connect(b) BIO_do_handshake(b) +#define BIO_do_accept(b) BIO_do_handshake(b) +#define BIO_do_handshake(b) BIO_ctrl(b,BIO_C_DO_STATE_MACHINE,0,NULL) + +/* BIO_s_proxy_client() */ +#define BIO_set_url(b,url) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,0,(char *)(url)) +#define BIO_set_proxies(b,p) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,1,(char *)(p)) +/* BIO_set_nbio(b,n) */ +#define BIO_set_filter_bio(b,s) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,2,(char *)(s)) +/* BIO *BIO_get_filter_bio(BIO *bio); */ +#define BIO_set_proxy_cb(b,cb) BIO_callback_ctrl(b,BIO_C_SET_PROXY_PARAM,3,(void *(*cb)())) +#define BIO_set_proxy_header(b,sk) BIO_ctrl(b,BIO_C_SET_PROXY_PARAM,4,(char *)sk) +#define BIO_set_no_connect_return(b,bool) BIO_int_ctrl(b,BIO_C_SET_PROXY_PARAM,5,bool) + +#define BIO_get_proxy_header(b,skp) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,0,(char *)skp) +#define BIO_get_proxies(b,pxy_p) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,1,(char *)(pxy_p)) +#define BIO_get_url(b,url) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,2,(char *)(url)) +#define BIO_get_no_connect_return(b) BIO_ctrl(b,BIO_C_GET_PROXY_PARAM,5,NULL) + +#define BIO_set_fd(b,fd,c) BIO_int_ctrl(b,BIO_C_SET_FD,c,fd) +#define BIO_get_fd(b,c) BIO_ctrl(b,BIO_C_GET_FD,0,(char *)c) + +#define BIO_set_fp(b,fp,c) BIO_ctrl(b,BIO_C_SET_FILE_PTR,c,(char *)fp) +#define BIO_get_fp(b,fpp) BIO_ctrl(b,BIO_C_GET_FILE_PTR,0,(char *)fpp) + +#define BIO_seek(b,ofs) (int)BIO_ctrl(b,BIO_C_FILE_SEEK,ofs,NULL) +#define BIO_tell(b) (int)BIO_ctrl(b,BIO_C_FILE_TELL,0,NULL) + +/* name is cast to lose const, but might be better to route through a function + so we can do it safely */ +#define BIO_read_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ,(char *)name) +#define BIO_write_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_WRITE,name) +#define BIO_append_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_APPEND,name) +#define BIO_rw_filename(b,name) BIO_ctrl(b,BIO_C_SET_FILENAME, \ + BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name) + +/* WARNING WARNING, this ups the reference count on the read bio of the + * SSL structure. This is because the ssl read BIO is now pointed to by + * the next_bio field in the bio. So when you free the BIO, make sure + * you are doing a BIO_free_all() to catch the underlying BIO. */ +#define BIO_set_ssl(b,ssl,c) BIO_ctrl(b,BIO_C_SET_SSL,c,(char *)ssl) +#define BIO_get_ssl(b,sslp) BIO_ctrl(b,BIO_C_GET_SSL,0,(char *)sslp) +#define BIO_set_ssl_mode(b,client) BIO_ctrl(b,BIO_C_SSL_MODE,client,NULL) +#define BIO_set_ssl_renegotiate_bytes(b,num) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_BYTES,num,NULL) +#define BIO_get_num_renegotiates(b) \ + BIO_ctrl(b,BIO_C_GET_SSL_NUM_RENEGOTIATES,0,NULL) +#define BIO_set_ssl_renegotiate_timeout(b,seconds) \ + BIO_ctrl(b,BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT,seconds,NULL) + +/* defined in evp.h */ +/* #define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,1,(char *)md) */ + +#define BIO_get_mem_data(b,pp) BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp) +#define BIO_set_mem_buf(b,bm,c) BIO_ctrl(b,BIO_C_SET_BUF_MEM,c,(char *)bm) +#define BIO_get_mem_ptr(b,pp) BIO_ctrl(b,BIO_C_GET_BUF_MEM_PTR,0,(char *)pp) +#define BIO_set_mem_eof_return(b,v) \ + BIO_ctrl(b,BIO_C_SET_BUF_MEM_EOF_RETURN,v,NULL) + +/* For the BIO_f_buffer() type */ +#define BIO_get_buffer_num_lines(b) BIO_ctrl(b,BIO_C_GET_BUFF_NUM_LINES,0,NULL) +#define BIO_set_buffer_size(b,size) BIO_ctrl(b,BIO_C_SET_BUFF_SIZE,size,NULL) +#define BIO_set_read_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,0) +#define BIO_set_write_buffer_size(b,size) BIO_int_ctrl(b,BIO_C_SET_BUFF_SIZE,size,1) +#define BIO_set_buffer_read_data(b,buf,num) BIO_ctrl(b,BIO_C_SET_BUFF_READ_DATA,num,buf) + +/* Don't use the next one unless you know what you are doing :-) */ +#define BIO_dup_state(b,ret) BIO_ctrl(b,BIO_CTRL_DUP,0,(char *)(ret)) + +#define BIO_reset(b) (int)BIO_ctrl(b,BIO_CTRL_RESET,0,NULL) +#define BIO_eof(b) (int)BIO_ctrl(b,BIO_CTRL_EOF,0,NULL) +#define BIO_set_close(b,c) (int)BIO_ctrl(b,BIO_CTRL_SET_CLOSE,(c),NULL) +#define BIO_get_close(b) (int)BIO_ctrl(b,BIO_CTRL_GET_CLOSE,0,NULL) +#define BIO_pending(b) (int)BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) +#define BIO_wpending(b) (int)BIO_ctrl(b,BIO_CTRL_WPENDING,0,NULL) +/* ...pending macros have inappropriate return type */ +size_t BIO_ctrl_pending(BIO *b); +size_t BIO_ctrl_wpending(BIO *b); +#define BIO_flush(b) (int)BIO_ctrl(b,BIO_CTRL_FLUSH,0,NULL) +#define BIO_get_info_callback(b,cbp) (int)BIO_ctrl(b,BIO_CTRL_GET_CALLBACK,0, \ + cbp) +#define BIO_set_info_callback(b,cb) (int)BIO_callback_ctrl(b,BIO_CTRL_SET_CALLBACK,cb) + +/* For the BIO_f_buffer() type */ +#define BIO_buffer_get_num_lines(b) BIO_ctrl(b,BIO_CTRL_GET,0,NULL) + +/* For BIO_s_bio() */ +#define BIO_set_write_buf_size(b,size) (int)BIO_ctrl(b,BIO_C_SET_WRITE_BUF_SIZE,size,NULL) +#define BIO_get_write_buf_size(b,size) (size_t)BIO_ctrl(b,BIO_C_GET_WRITE_BUF_SIZE,size,NULL) +#define BIO_make_bio_pair(b1,b2) (int)BIO_ctrl(b1,BIO_C_MAKE_BIO_PAIR,0,b2) +#define BIO_destroy_bio_pair(b) (int)BIO_ctrl(b,BIO_C_DESTROY_BIO_PAIR,0,NULL) +#define BIO_shutdown_wr(b) (int)BIO_ctrl(b, BIO_C_SHUTDOWN_WR, 0, NULL) +/* macros with inappropriate type -- but ...pending macros use int too: */ +#define BIO_get_write_guarantee(b) (int)BIO_ctrl(b,BIO_C_GET_WRITE_GUARANTEE,0,NULL) +#define BIO_get_read_request(b) (int)BIO_ctrl(b,BIO_C_GET_READ_REQUEST,0,NULL) +size_t BIO_ctrl_get_write_guarantee(BIO *b); +size_t BIO_ctrl_get_read_request(BIO *b); +int BIO_ctrl_reset_read_request(BIO *b); + +/* ctrl macros for dgram */ +#define BIO_ctrl_dgram_connect(b,peer) \ + (int)BIO_ctrl(b,BIO_CTRL_DGRAM_CONNECT,0, (char *)peer) +#define BIO_ctrl_set_connected(b, state, peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_CONNECTED, state, (char *)peer) +#define BIO_dgram_recv_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP, 0, NULL) +#define BIO_dgram_send_timedout(b) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP, 0, NULL) +#define BIO_dgram_get_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_GET_PEER, 0, (char *)peer) +#define BIO_dgram_set_peer(b,peer) \ + (int)BIO_ctrl(b, BIO_CTRL_DGRAM_SET_PEER, 0, (char *)peer) + +/* These two aren't currently implemented */ +/* int BIO_get_ex_num(BIO *bio); */ +/* void BIO_set_ex_free_func(BIO *bio,int idx,void (*cb)()); */ +int BIO_set_ex_data(BIO *bio, int idx, void *data); +void *BIO_get_ex_data(BIO *bio, int idx); +int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +unsigned long BIO_number_read(BIO *bio); +unsigned long BIO_number_written(BIO *bio); + +int BIO_get_new_index(void); +const BIO_METHOD *BIO_s_file(void); +BIO *BIO_new_file(const char *filename, const char *mode); +BIO *BIO_new_fp(FILE *stream, int close_flag); +BIO *BIO_new(const BIO_METHOD *type); +int BIO_set(BIO *a, const BIO_METHOD *type); +int BIO_free(BIO *a); +int BIO_up_ref(BIO *bio); +void *BIO_get_data(BIO *a); +void BIO_set_data(BIO *a, void *ptr); +int BIO_get_init(BIO *a); +void BIO_set_init(BIO *a, int init); +int BIO_get_shutdown(BIO *a); +void BIO_set_shutdown(BIO *a, int shut); +void BIO_vfree(BIO *a); +int BIO_read(BIO *b, void *data, int len) + __attribute__((__bounded__(__buffer__,2,3))); +int BIO_gets(BIO *bp, char *buf, int size) + __attribute__((__bounded__ (__string__,2,3))); +int BIO_write(BIO *b, const void *data, int len) + __attribute__((__bounded__(__buffer__,2,3))); +int BIO_puts(BIO *bp, const char *buf); +int BIO_indent(BIO *b, int indent, int max); +long BIO_ctrl(BIO *bp, int cmd, long larg, void *parg); +long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp); +char * BIO_ptr_ctrl(BIO *bp, int cmd, long larg); +long BIO_int_ctrl(BIO *bp, int cmd, long larg, int iarg); +BIO * BIO_push(BIO *b, BIO *append); +BIO * BIO_pop(BIO *b); +void BIO_free_all(BIO *a); +BIO * BIO_find_type(BIO *b, int bio_type); +BIO * BIO_next(BIO *b); +void BIO_set_next(BIO *b, BIO *next); +BIO * BIO_get_retry_BIO(BIO *bio, int *reason); +int BIO_get_retry_reason(BIO *bio); +void BIO_set_retry_reason(BIO *bio, int reason); +BIO * BIO_dup_chain(BIO *in); + +int BIO_nread0(BIO *bio, char **buf); +int BIO_nread(BIO *bio, char **buf, int num); +int BIO_nwrite0(BIO *bio, char **buf); +int BIO_nwrite(BIO *bio, char **buf, int num); + +long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi, + long argl, long ret); + +const BIO_METHOD *BIO_s_mem(void); +BIO *BIO_new_mem_buf(const void *buf, int len); +const BIO_METHOD *BIO_s_socket(void); +const BIO_METHOD *BIO_s_connect(void); +const BIO_METHOD *BIO_s_accept(void); +const BIO_METHOD *BIO_s_fd(void); +const BIO_METHOD *BIO_s_log(void); +const BIO_METHOD *BIO_s_bio(void); +const BIO_METHOD *BIO_s_null(void); +const BIO_METHOD *BIO_f_null(void); +const BIO_METHOD *BIO_f_buffer(void); +const BIO_METHOD *BIO_f_nbio_test(void); +#ifndef OPENSSL_NO_DGRAM +const BIO_METHOD *BIO_s_datagram(void); +#endif + +/* BIO_METHOD *BIO_f_ber(void); */ + +int BIO_sock_should_retry(int i); +int BIO_sock_non_fatal_error(int _error); +int BIO_dgram_non_fatal_error(int _error); + +int BIO_fd_should_retry(int i); +int BIO_fd_non_fatal_error(int _error); +int BIO_dump_cb(int (*cb)(const void *data, size_t len, void *u), + void *u, const char *s, int len); +int BIO_dump_indent_cb(int (*cb)(const void *data, size_t len, void *u), + void *u, const char *s, int len, int indent); +int BIO_dump(BIO *b, const char *bytes, int len); +int BIO_dump_indent(BIO *b, const char *bytes, int len, int indent); +int BIO_dump_fp(FILE *fp, const char *s, int len); +int BIO_dump_indent_fp(FILE *fp, const char *s, int len, int indent); +struct hostent *BIO_gethostbyname(const char *name); +/* We might want a thread-safe interface too: + * struct hostent *BIO_gethostbyname_r(const char *name, + * struct hostent *result, void *buffer, size_t buflen); + * or something similar (caller allocates a struct hostent, + * pointed to by "result", and additional buffer space for the various + * substructures; if the buffer does not suffice, NULL is returned + * and an appropriate error code is set). + */ +int BIO_sock_error(int sock); +int BIO_socket_ioctl(int fd, long type, void *arg); +int BIO_socket_nbio(int fd, int mode); +int BIO_get_port(const char *str, unsigned short *port_ptr); +int BIO_get_host_ip(const char *str, unsigned char *ip); +int BIO_get_accept_socket(char *host_port, int mode); +int BIO_accept(int sock, char **ip_port); +int BIO_sock_init(void ); +void BIO_sock_cleanup(void); +int BIO_set_tcp_ndelay(int sock, int turn_on); + +BIO *BIO_new_socket(int sock, int close_flag); +BIO *BIO_new_dgram(int fd, int close_flag); +BIO *BIO_new_fd(int fd, int close_flag); +BIO *BIO_new_connect(const char *host_port); +BIO *BIO_new_accept(const char *host_port); + +int BIO_new_bio_pair(BIO **bio1, size_t writebuf1, + BIO **bio2, size_t writebuf2); +/* If successful, returns 1 and in *bio1, *bio2 two BIO pair endpoints. + * Otherwise returns 0 and sets *bio1 and *bio2 to NULL. + * Size 0 uses default value. + */ + +void BIO_copy_next_retry(BIO *b); + +/*long BIO_ghbn_ctrl(int cmd,int iarg,char *parg);*/ + +/* Needed for libressl-portable. */ +#ifndef __MINGW_PRINTF_FORMAT +int BIO_printf(BIO *bio, const char *format, ...) + __attribute__((__format__(__printf__, 2, 3), __nonnull__(2))); +int BIO_vprintf(BIO *bio, const char *format, va_list args) + __attribute__((__format__(__printf__, 2, 0), __nonnull__(2))); +int BIO_snprintf(char *buf, size_t n, const char *format, ...) + __attribute__((__deprecated__, __format__(__printf__, 3, 4), + __nonnull__(3))); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) + __attribute__((__deprecated__, __format__(__printf__, 3, 0), + __nonnull__(3))); +#else +int BIO_printf(BIO *bio, const char *format, ...) + __attribute__((__format__(__MINGW_PRINTF_FORMAT, 2, 3), __nonnull__(2))); +int BIO_vprintf(BIO *bio, const char *format, va_list args) + __attribute__((__format__(__MINGW_PRINTF_FORMAT, 2, 0), __nonnull__(2))); +int BIO_snprintf(char *buf, size_t n, const char *format, ...) + __attribute__((__deprecated__, __format__(__MINGW_PRINTF_FORMAT, 3, 4), + __nonnull__(3))); +int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) + __attribute__((__deprecated__, __format__(__MINGW_PRINTF_FORMAT, 3, 0), + __nonnull__(3))); +#endif + +void ERR_load_BIO_strings(void); + +/* Error codes for the BIO functions. */ + +/* Function codes. */ +#define BIO_F_ACPT_STATE 100 +#define BIO_F_BIO_ACCEPT 101 +#define BIO_F_BIO_BER_GET_HEADER 102 +#define BIO_F_BIO_CALLBACK_CTRL 131 +#define BIO_F_BIO_CTRL 103 +#define BIO_F_BIO_GETHOSTBYNAME 120 +#define BIO_F_BIO_GETS 104 +#define BIO_F_BIO_GET_ACCEPT_SOCKET 105 +#define BIO_F_BIO_GET_HOST_IP 106 +#define BIO_F_BIO_GET_PORT 107 +#define BIO_F_BIO_MAKE_PAIR 121 +#define BIO_F_BIO_NEW 108 +#define BIO_F_BIO_NEW_FILE 109 +#define BIO_F_BIO_NEW_MEM_BUF 126 +#define BIO_F_BIO_NREAD 123 +#define BIO_F_BIO_NREAD0 124 +#define BIO_F_BIO_NWRITE 125 +#define BIO_F_BIO_NWRITE0 122 +#define BIO_F_BIO_PUTS 110 +#define BIO_F_BIO_READ 111 +#define BIO_F_BIO_SOCK_INIT 112 +#define BIO_F_BIO_WRITE 113 +#define BIO_F_BUFFER_CTRL 114 +#define BIO_F_CONN_CTRL 127 +#define BIO_F_CONN_STATE 115 +#define BIO_F_DGRAM_SCTP_READ 132 +#define BIO_F_FILE_CTRL 116 +#define BIO_F_FILE_READ 130 +#define BIO_F_LINEBUFFER_CTRL 129 +#define BIO_F_MEM_READ 128 +#define BIO_F_MEM_WRITE 117 +#define BIO_F_SSL_NEW 118 +#define BIO_F_WSASTARTUP 119 + +/* Reason codes. */ +#define BIO_R_ACCEPT_ERROR 100 +#define BIO_R_BAD_FOPEN_MODE 101 +#define BIO_R_BAD_HOSTNAME_LOOKUP 102 +#define BIO_R_BROKEN_PIPE 124 +#define BIO_R_CONNECT_ERROR 103 +#define BIO_R_EOF_ON_MEMORY_BIO 127 +#define BIO_R_ERROR_SETTING_NBIO 104 +#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPTED_SOCKET 105 +#define BIO_R_ERROR_SETTING_NBIO_ON_ACCEPT_SOCKET 106 +#define BIO_R_GETHOSTBYNAME_ADDR_IS_NOT_AF_INET 107 +#define BIO_R_INVALID_ARGUMENT 125 +#define BIO_R_INVALID_IP_ADDRESS 108 +#define BIO_R_INVALID_PORT_NUMBER 129 +#define BIO_R_IN_USE 123 +#define BIO_R_KEEPALIVE 109 +#define BIO_R_LENGTH_TOO_LONG 130 +#define BIO_R_NBIO_CONNECT_ERROR 110 +#define BIO_R_NO_ACCEPT_PORT_SPECIFIED 111 +#define BIO_R_NO_HOSTNAME_SPECIFIED 112 +#define BIO_R_NO_PORT_DEFINED 113 +#define BIO_R_NO_PORT_SPECIFIED 114 +#define BIO_R_NO_SUCH_FILE 128 +#define BIO_R_NULL_PARAMETER 115 +#define BIO_R_TAG_MISMATCH 116 +#define BIO_R_UNABLE_TO_BIND_SOCKET 117 +#define BIO_R_UNABLE_TO_CREATE_SOCKET 118 +#define BIO_R_UNABLE_TO_LISTEN_SOCKET 119 +#define BIO_R_UNINITIALIZED 120 +#define BIO_R_UNSUPPORTED_METHOD 121 +#define BIO_R_WRITE_TO_READ_ONLY_BIO 126 +#define BIO_R_WSASTARTUP 122 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/blowfish.h b/include/openssl/blowfish.h new file mode 100644 index 0000000..b434e70 --- /dev/null +++ b/include/openssl/blowfish.h @@ -0,0 +1,110 @@ +/* $OpenBSD: blowfish.h,v 1.17 2023/07/31 05:04:06 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BLOWFISH_H +#define HEADER_BLOWFISH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_BF +#error BF is disabled. +#endif + +#define BF_ENCRYPT 1 +#define BF_DECRYPT 0 + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! BF_LONG has to be at least 32 bits wide. If it's wider, then ! + * ! BF_LONG_LOG2 has to be defined along. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#define BF_LONG unsigned int + +#define BF_ROUNDS 16 +#define BF_BLOCK 8 + +typedef struct bf_key_st { + BF_LONG P[BF_ROUNDS + 2]; + BF_LONG S[4*256]; +} BF_KEY; + +void BF_set_key(BF_KEY *key, int len, const unsigned char *data); + +void BF_encrypt(BF_LONG *data, const BF_KEY *key); +void BF_decrypt(BF_LONG *data, const BF_KEY *key); + +void BF_ecb_encrypt(const unsigned char *in, unsigned char *out, + const BF_KEY *key, int enc); +void BF_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int enc); +void BF_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num, int enc); +void BF_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, + const BF_KEY *schedule, unsigned char *ivec, int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/bn.h b/include/openssl/bn.h new file mode 100644 index 0000000..e00953e --- /dev/null +++ b/include/openssl/bn.h @@ -0,0 +1,534 @@ +/* $OpenBSD: bn.h,v 1.75 2023/07/31 05:04:06 tb Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#ifndef HEADER_BN_H +#define HEADER_BN_H + +#include +#include + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* This next option uses the C libraries (2 word)/(1 word) function. + * If it is not defined, I use my C version (which is slower). + * The reason for this flag is that when the particular C compiler + * library routine is used, and the library is linked with a different + * compiler, the library is missing. This mostly happens when the + * library is built with gcc and then linked using normal cc. This would + * be a common occurrence because gcc normally produces code that is + * 2 times faster than system compilers for the big number stuff. + * For machines with only one compiler (or shared libraries), this should + * be on. Again this in only really a problem on machines + * using "long long's", are 32bit, and are not using my assembler code. */ +/* #define BN_DIV2W */ + +#ifdef _LP64 +#undef BN_LLONG +#define BN_ULONG unsigned long +#define BN_LONG long +#define BN_BITS 128 +#define BN_BYTES 8 +#define BN_BITS2 64 +#define BN_BITS4 32 +#define BN_MASK2 (0xffffffffffffffffL) +#define BN_MASK2l (0xffffffffL) +#define BN_MASK2h (0xffffffff00000000L) +#define BN_MASK2h1 (0xffffffff80000000L) +#define BN_TBIT (0x8000000000000000L) +#define BN_DEC_CONV (10000000000000000000UL) +#define BN_DEC_FMT1 "%lu" +#define BN_DEC_FMT2 "%019lu" +#define BN_DEC_NUM 19 +#define BN_HEX_FMT1 "%lX" +#define BN_HEX_FMT2 "%016lX" +#else +#define BN_ULLONG unsigned long long +#define BN_LLONG +#define BN_ULONG unsigned int +#define BN_LONG int +#define BN_BITS 64 +#define BN_BYTES 4 +#define BN_BITS2 32 +#define BN_BITS4 16 +#define BN_MASK (0xffffffffffffffffLL) +#define BN_MASK2 (0xffffffffL) +#define BN_MASK2l (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_TBIT (0x80000000L) +#define BN_DEC_CONV (1000000000L) +#define BN_DEC_FMT1 "%u" +#define BN_DEC_FMT2 "%09u" +#define BN_DEC_NUM 9 +#define BN_HEX_FMT1 "%X" +#define BN_HEX_FMT2 "%08X" +#endif + +#define BN_FLG_MALLOCED 0x01 +#define BN_FLG_STATIC_DATA 0x02 +#define BN_FLG_CONSTTIME 0x04 /* avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ + +void BN_set_flags(BIGNUM *b, int n); +int BN_get_flags(const BIGNUM *b, int n); +void BN_with_flags(BIGNUM *dest, const BIGNUM *src, int flags); + +/* Values for |top| in BN_rand() */ +#define BN_RAND_TOP_ANY -1 +#define BN_RAND_TOP_ONE 0 +#define BN_RAND_TOP_TWO 1 + +/* Values for |bottom| in BN_rand() */ +#define BN_RAND_BOTTOM_ANY 0 +#define BN_RAND_BOTTOM_ODD 1 + +BN_GENCB *BN_GENCB_new(void); +void BN_GENCB_free(BN_GENCB *cb); + +/* Wrapper function to make using BN_GENCB easier, */ +int BN_GENCB_call(BN_GENCB *cb, int a, int b); + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback)(int, int, void *), + void *cb_arg); + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback)(int, int, BN_GENCB *), + void *cb_arg); + +void *BN_GENCB_get_arg(BN_GENCB *cb); + +#define BN_prime_checks 0 /* default: select number of iterations + based on the size of the number */ + +/* + * BN_prime_checks_for_size() returns the number of Miller-Rabin + * iterations that will be done for checking that a random number + * is probably prime. The error rate for accepting a composite + * number as prime depends on the size of the prime |b|. The error + * rates used are for calculating an RSA key with 2 primes, and so + * the level is what you would expect for a key of double the size + * of the prime. + * + * This table is generated using the algorithm of FIPS PUB 186-4 + * Digital Signature Standard (DSS), section F.1, page 117. + * (https://dx.doi.org/10.6028/NIST.FIPS.186-4) + * + * The following magma script was used to generate the output: + * securitybits:=125; + * k:=1024; + * for t:=1 to 65 do + * for M:=3 to Floor(2*Sqrt(k-1)-1) do + * S:=0; + * // Sum over m + * for m:=3 to M do + * s:=0; + * // Sum over j + * for j:=2 to m do + * s+:=(RealField(32)!2)^-(j+(k-1)/j); + * end for; + * S+:=2^(m-(m-1)*t)*s; + * end for; + * A:=2^(k-2-M*t); + * B:=8*(Pi(RealField(32))^2-6)/3*2^(k-2)*S; + * pkt:=2.00743*Log(2)*k*2^-k*(A+B); + * seclevel:=Floor(-Log(2,pkt)); + * if seclevel ge securitybits then + * printf "k: %5o, security: %o bits (t: %o, M: %o)\n",k,seclevel,t,M; + * break; + * end if; + * end for; + * if seclevel ge securitybits then break; end if; + * end for; + * + * It can be run online at: + * http://magma.maths.usyd.edu.au/calc + * + * And will output: + * k: 1024, security: 129 bits (t: 6, M: 23) + * + * k is the number of bits of the prime, securitybits is the level + * we want to reach. + * + * prime length | RSA key size | # MR tests | security level + * -------------+--------------|------------+--------------- + * (b) >= 6394 | >= 12788 | 3 | 256 bit + * (b) >= 3747 | >= 7494 | 3 | 192 bit + * (b) >= 1345 | >= 2690 | 4 | 128 bit + * (b) >= 1080 | >= 2160 | 5 | 128 bit + * (b) >= 852 | >= 1704 | 5 | 112 bit + * (b) >= 476 | >= 952 | 5 | 80 bit + * (b) >= 400 | >= 800 | 6 | 80 bit + * (b) >= 347 | >= 694 | 7 | 80 bit + * (b) >= 308 | >= 616 | 8 | 80 bit + * (b) >= 55 | >= 110 | 27 | 64 bit + * (b) >= 6 | >= 12 | 34 | 64 bit + */ + +#define BN_prime_checks_for_size(b) ((b) >= 3747 ? 3 : \ + (b) >= 1345 ? 4 : \ + (b) >= 476 ? 5 : \ + (b) >= 400 ? 6 : \ + (b) >= 347 ? 7 : \ + (b) >= 308 ? 8 : \ + (b) >= 55 ? 27 : \ + /* b >= 6 */ 34) + +#define BN_num_bytes(a) ((BN_num_bits(a)+7)/8) + +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_zero(const BIGNUM *a); +int BN_is_one(const BIGNUM *a); +int BN_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_odd(const BIGNUM *a); + +void BN_zero(BIGNUM *a); +int BN_one(BIGNUM *a); + +const BIGNUM *BN_value_one(void); +BN_CTX *BN_CTX_new(void); +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range); +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG); +BIGNUM *BN_new(void); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +void BN_swap(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_mpi2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2mpi(const BIGNUM *a, unsigned char *to); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +void BN_set_negative(BIGNUM *b, int n); + +int BN_is_negative(const BIGNUM *b); + +#ifndef LIBRESSL_INTERNAL +int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, + BN_CTX *ctx); +#define BN_mod(rem,m,d,ctx) BN_div(NULL,(rem),(m),(d),(ctx)) +#endif +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m); +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_set_word(BIGNUM *a, BN_ULONG w); +BN_ULONG BN_get_word(const BIGNUM *a); + +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_is_bit_set(const BIGNUM *a, int n); +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +#ifndef LIBRESSL_INTERNAL +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +#endif +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +int BN_mask_bits(BIGNUM *a, int n); +int BN_print_fp(FILE *fp, const BIGNUM *a); +int BN_print(BIO *fp, const BIGNUM *a); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); +void BN_clear(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); +int BN_set_bit(BIGNUM *a, int n); +int BN_clear_bit(BIGNUM *a, int n); +char * BN_bn2hex(const BIGNUM *a); +char * BN_bn2dec(const BIGNUM *a); +int BN_hex2bn(BIGNUM **a, const char *str); +int BN_dec2bn(BIGNUM **a, const char *str); +int BN_asc2bn(BIGNUM **a, const char *str); +#ifndef LIBRESSL_INTERNAL +int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +#endif +int BN_kronecker(const BIGNUM *a,const BIGNUM *b,BN_CTX *ctx); /* returns -2 for error */ +#ifndef LIBRESSL_INTERNAL +BIGNUM *BN_mod_inverse(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); +#endif +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +void BN_consttime_swap(BN_ULONG swap, BIGNUM *a, BIGNUM *b, int nwords); + +int BN_security_bits(int L, int N); + +int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add, + const BIGNUM *rem, BN_GENCB *cb); +int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb); +int BN_is_prime_fasttest_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, + int do_trial_division, BN_GENCB *cb); + +BN_MONT_CTX *BN_MONT_CTX_new(void ); +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, + BN_MONT_CTX *mont, BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from); +BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock, + const BIGNUM *mod, BN_CTX *ctx); + +/* Primes from RFC 2409 */ +BIGNUM *BN_get_rfc2409_prime_768(BIGNUM *bn); +BIGNUM *BN_get_rfc2409_prime_1024(BIGNUM *bn); + +/* Primes from RFC 3526 */ +BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_2048(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_3072(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_4096(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_6144(BIGNUM *bn); +BIGNUM *BN_get_rfc3526_prime_8192(BIGNUM *bn); + +void ERR_load_BN_strings(void); + +/* Error codes for the BN functions. */ + +/* Function codes. */ +#define BN_F_BNRAND 127 +#define BN_F_BN_BLINDING_CONVERT_EX 100 +#define BN_F_BN_BLINDING_CREATE_PARAM 128 +#define BN_F_BN_BLINDING_INVERT_EX 101 +#define BN_F_BN_BLINDING_NEW 102 +#define BN_F_BN_BLINDING_UPDATE 103 +#define BN_F_BN_BN2DEC 104 +#define BN_F_BN_BN2HEX 105 +#define BN_F_BN_CTX_GET 116 +#define BN_F_BN_CTX_NEW 106 +#define BN_F_BN_CTX_START 129 +#define BN_F_BN_DIV 107 +#define BN_F_BN_DIV_NO_BRANCH 138 +#define BN_F_BN_DIV_RECP 130 +#define BN_F_BN_EXP 123 +#define BN_F_BN_EXPAND2 108 +#define BN_F_BN_GENERATE_PRIME_EX 140 +#define BN_F_BN_EXPAND_INTERNAL 120 +#define BN_F_BN_GF2M_MOD 131 +#define BN_F_BN_GF2M_MOD_EXP 132 +#define BN_F_BN_GF2M_MOD_MUL 133 +#define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134 +#define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 +#define BN_F_BN_GF2M_MOD_SQR 136 +#define BN_F_BN_GF2M_MOD_SQRT 137 +#define BN_F_BN_MOD_EXP2_MONT 118 +#define BN_F_BN_MOD_EXP_MONT 109 +#define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 +#define BN_F_BN_MOD_EXP_MONT_WORD 117 +#define BN_F_BN_MOD_EXP_RECP 125 +#define BN_F_BN_MOD_EXP_SIMPLE 126 +#define BN_F_BN_MOD_INVERSE 110 +#define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 +#define BN_F_BN_MOD_LSHIFT_QUICK 119 +#define BN_F_BN_MOD_MUL_RECIPROCAL 111 +#define BN_F_BN_MOD_SQRT 121 +#define BN_F_BN_MPI2BN 112 +#define BN_F_BN_NEW 113 +#define BN_F_BN_RAND 114 +#define BN_F_BN_RAND_RANGE 122 +#define BN_F_BN_USUB 115 + +/* Reason codes. */ +#define BN_R_ARG2_LT_ARG3 100 +#define BN_R_BAD_RECIPROCAL 101 +#define BN_R_BIGNUM_TOO_LONG 114 +#define BN_R_BITS_TOO_SMALL 117 +#define BN_R_CALLED_WITH_EVEN_MODULUS 102 +#define BN_R_DIV_BY_ZERO 103 +#define BN_R_ENCODING_ERROR 104 +#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +#define BN_R_INPUT_NOT_REDUCED 110 +#define BN_R_INVALID_ARGUMENT 118 +#define BN_R_INVALID_LENGTH 106 +#define BN_R_INVALID_RANGE 115 +#define BN_R_NOT_A_SQUARE 111 +#define BN_R_NOT_INITIALIZED 107 +#define BN_R_NO_INVERSE 108 +#define BN_R_NO_SOLUTION 116 +#define BN_R_P_IS_NOT_PRIME 112 +#define BN_R_TOO_MANY_ITERATIONS 113 +#define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/buffer.h b/include/openssl/buffer.h new file mode 100644 index 0000000..d461d64 --- /dev/null +++ b/include/openssl/buffer.h @@ -0,0 +1,102 @@ +/* $OpenBSD: buffer.h,v 1.17 2023/07/28 10:17:21 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BUFFER_H +#define HEADER_BUFFER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Already declared in ossl_typ.h */ +/* typedef struct buf_mem_st BUF_MEM; */ + +struct buf_mem_st { + size_t length; /* current number of bytes */ + char *data; + size_t max; /* size of buffer */ +}; + +BUF_MEM *BUF_MEM_new(void); +void BUF_MEM_free(BUF_MEM *a); +int BUF_MEM_grow(BUF_MEM *str, size_t len); +int BUF_MEM_grow_clean(BUF_MEM *str, size_t len); + +void ERR_load_BUF_strings(void); + +/* Error codes for the BUF functions. */ + +/* Function codes. */ +#define BUF_F_BUF_MEMDUP 103 +#define BUF_F_BUF_MEM_GROW 100 +#define BUF_F_BUF_MEM_GROW_CLEAN 105 +#define BUF_F_BUF_MEM_NEW 101 +#define BUF_F_BUF_STRDUP 102 +#define BUF_F_BUF_STRNDUP 104 + +/* Reason codes. */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/camellia.h b/include/openssl/camellia.h new file mode 100644 index 0000000..b9b5f79 --- /dev/null +++ b/include/openssl/camellia.h @@ -0,0 +1,125 @@ +/* $OpenBSD: camellia.h,v 1.5 2014/11/13 20:01:58 miod Exp $ */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +#include + +#ifdef OPENSSL_NO_CAMELLIA +#error CAMELLIA is disabled. +#endif + +#include + +#define CAMELLIA_ENCRYPT 1 +#define CAMELLIA_DECRYPT 0 + +/* Because array size can't be a const in C, the following two are macros. + Both sizes are in bytes. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This should be a hidden type, but EVP requires that the size be known */ + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; /* to match with WORD */ + +struct camellia_key_st { + union { + double d; /* ensures 64-bit align */ + KEY_TABLE_TYPE rd_key; + } u; + int grand_rounds; +}; +typedef struct camellia_key_st CAMELLIA_KEY; + +int Camellia_set_key(const unsigned char *userKey, const int bits, + CAMELLIA_KEY *key); + +void Camellia_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); +void Camellia_decrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key); + +void Camellia_ecb_encrypt(const unsigned char *in, unsigned char *out, + const CAMELLIA_KEY *key, const int enc); +void Camellia_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, const int enc); +void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb1_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_cfb8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Camellia_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char *ivec, int *num); +void Camellia_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const CAMELLIA_KEY *key, + unsigned char ivec[CAMELLIA_BLOCK_SIZE], + unsigned char ecount_buf[CAMELLIA_BLOCK_SIZE], + unsigned int *num); + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_Camellia_H */ diff --git a/include/openssl/cast.h b/include/openssl/cast.h new file mode 100644 index 0000000..0936696 --- /dev/null +++ b/include/openssl/cast.h @@ -0,0 +1,103 @@ +/* $OpenBSD: cast.h,v 1.13 2023/07/08 07:25:43 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CAST_H +#define HEADER_CAST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_CAST +#error CAST is disabled. +#endif + +#define CAST_ENCRYPT 1 +#define CAST_DECRYPT 0 + +#define CAST_LONG unsigned int + +#define CAST_BLOCK 8 +#define CAST_KEY_LENGTH 16 + +typedef struct cast_key_st { + CAST_LONG data[32]; + int short_key; /* Use reduced rounds for short key */ +} CAST_KEY; + +void CAST_set_key(CAST_KEY *key, int len, const unsigned char *data); +void CAST_ecb_encrypt(const unsigned char *in, unsigned char *out, const CAST_KEY *key, + int enc); +void CAST_encrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_decrypt(CAST_LONG *data, const CAST_KEY *key); +void CAST_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + const CAST_KEY *ks, unsigned char *iv, int enc); +void CAST_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void CAST_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, const CAST_KEY *schedule, unsigned char *ivec, + int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/chacha.h b/include/openssl/chacha.h new file mode 100644 index 0000000..e2345b2 --- /dev/null +++ b/include/openssl/chacha.h @@ -0,0 +1,58 @@ +/* $OpenBSD: chacha.h,v 1.8 2019/01/22 00:59:21 dlg Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_CHACHA_H +#define HEADER_CHACHA_H + +#include + +#if defined(OPENSSL_NO_CHACHA) +#error ChaCha is disabled. +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned int input[16]; + unsigned char ks[64]; + unsigned char unused; +} ChaCha_ctx; + +void ChaCha_set_key(ChaCha_ctx *ctx, const unsigned char *key, + unsigned int keybits); +void ChaCha_set_iv(ChaCha_ctx *ctx, const unsigned char *iv, + const unsigned char *counter); +void ChaCha(ChaCha_ctx *ctx, unsigned char *out, const unsigned char *in, + size_t len); + +void CRYPTO_chacha_20(unsigned char *out, const unsigned char *in, size_t len, + const unsigned char key[32], const unsigned char iv[8], uint64_t counter); +void CRYPTO_xchacha_20(unsigned char *out, const unsigned char *in, size_t len, + const unsigned char key[32], const unsigned char iv[24]); +void CRYPTO_hchacha_20(unsigned char out[32], + const unsigned char key[32], const unsigned char iv[16]); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CHACHA_H */ diff --git a/include/openssl/cmac.h b/include/openssl/cmac.h new file mode 100644 index 0000000..cb6d64b --- /dev/null +++ b/include/openssl/cmac.h @@ -0,0 +1,82 @@ +/* $OpenBSD: cmac.h,v 1.3 2014/06/21 13:42:14 jsing Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2010 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + + +#ifndef HEADER_CMAC_H +#define HEADER_CMAC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Opaque */ +typedef struct CMAC_CTX_st CMAC_CTX; + +CMAC_CTX *CMAC_CTX_new(void); +void CMAC_CTX_cleanup(CMAC_CTX *ctx); +void CMAC_CTX_free(CMAC_CTX *ctx); +EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx); +int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in); + +int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen, + const EVP_CIPHER *cipher, ENGINE *impl); +int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen); +int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen); +int CMAC_resume(CMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/cms.h b/include/openssl/cms.h new file mode 100644 index 0000000..76672af --- /dev/null +++ b/include/openssl/cms.h @@ -0,0 +1,535 @@ +/* $OpenBSD: cms.h,v 1.16 2023/07/28 10:28:02 tb Exp $ */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_CMS_H +#define HEADER_CMS_H + +#include + +#ifndef OPENSSL_NO_CMS +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CMS_ContentInfo_st CMS_ContentInfo; +typedef struct CMS_SignerInfo_st CMS_SignerInfo; +typedef struct CMS_CertificateChoices CMS_CertificateChoices; +typedef struct CMS_RevocationInfoChoice_st CMS_RevocationInfoChoice; +typedef struct CMS_RecipientInfo_st CMS_RecipientInfo; +typedef struct CMS_ReceiptRequest_st CMS_ReceiptRequest; +typedef struct CMS_Receipt_st CMS_Receipt; +typedef struct CMS_RecipientEncryptedKey_st CMS_RecipientEncryptedKey; +typedef struct CMS_OtherKeyAttribute_st CMS_OtherKeyAttribute; + +DECLARE_STACK_OF(CMS_SignerInfo) +DECLARE_STACK_OF(CMS_RecipientEncryptedKey) +DECLARE_STACK_OF(CMS_RecipientInfo) +DECLARE_STACK_OF(CMS_RevocationInfoChoice) +CMS_ContentInfo *CMS_ContentInfo_new(void); +void CMS_ContentInfo_free(CMS_ContentInfo *a); +CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a, const unsigned char **in, long len); +int i2d_CMS_ContentInfo(CMS_ContentInfo *a, unsigned char **out); +extern const ASN1_ITEM CMS_ContentInfo_it; +CMS_ReceiptRequest *CMS_ReceiptRequest_new(void); +void CMS_ReceiptRequest_free(CMS_ReceiptRequest *a); +CMS_ReceiptRequest *d2i_CMS_ReceiptRequest(CMS_ReceiptRequest **a, const unsigned char **in, long len); +int i2d_CMS_ReceiptRequest(CMS_ReceiptRequest *a, unsigned char **out); +extern const ASN1_ITEM CMS_ReceiptRequest_it; +int CMS_ContentInfo_print_ctx(BIO *out, CMS_ContentInfo *x, int indent, const ASN1_PCTX *pctx); + +#define CMS_SIGNERINFO_ISSUER_SERIAL 0 +#define CMS_SIGNERINFO_KEYIDENTIFIER 1 + +#define CMS_RECIPINFO_NONE -1 +#define CMS_RECIPINFO_TRANS 0 +#define CMS_RECIPINFO_AGREE 1 +#define CMS_RECIPINFO_KEK 2 +#define CMS_RECIPINFO_PASS 3 +#define CMS_RECIPINFO_OTHER 4 + +/* S/MIME related flags */ + +#define CMS_TEXT 0x1 +#define CMS_NOCERTS 0x2 +#define CMS_NO_CONTENT_VERIFY 0x4 +#define CMS_NO_ATTR_VERIFY 0x8 +#define CMS_NOSIGS \ + (CMS_NO_CONTENT_VERIFY|CMS_NO_ATTR_VERIFY) +#define CMS_NOINTERN 0x10 +#define CMS_NO_SIGNER_CERT_VERIFY 0x20 +#define CMS_NOVERIFY 0x20 +#define CMS_DETACHED 0x40 +#define CMS_BINARY 0x80 +#define CMS_NOATTR 0x100 +#define CMS_NOSMIMECAP 0x200 +#define CMS_NOOLDMIMETYPE 0x400 +#define CMS_CRLFEOL 0x800 +#define CMS_STREAM 0x1000 +#define CMS_NOCRL 0x2000 +#define CMS_PARTIAL 0x4000 +#define CMS_REUSE_DIGEST 0x8000 +#define CMS_USE_KEYID 0x10000 +#define CMS_DEBUG_DECRYPT 0x20000 +#define CMS_KEY_PARAM 0x40000 +#define CMS_ASCIICRLF 0x80000 + +const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms); + +int CMS_get_version(const CMS_ContentInfo *cms, long *version); +int CMS_SignerInfo_get_version(const CMS_SignerInfo *si, long *version); + +BIO *CMS_dataInit(CMS_ContentInfo *cms, BIO *icont); +int CMS_dataFinal(CMS_ContentInfo *cms, BIO *bio); + +ASN1_OCTET_STRING **CMS_get0_content(CMS_ContentInfo *cms); +int CMS_is_detached(CMS_ContentInfo *cms); +int CMS_set_detached(CMS_ContentInfo *cms, int detached); + +#ifdef HEADER_PEM_H +CMS_ContentInfo *PEM_read_bio_CMS(BIO *bp, CMS_ContentInfo **x, + pem_password_cb *cb, void *u); +CMS_ContentInfo *PEM_read_CMS(FILE *fp, CMS_ContentInfo **x, + pem_password_cb *cb, void *u); +int PEM_write_bio_CMS(BIO *bp, const CMS_ContentInfo *x); +int PEM_write_CMS(FILE *fp, const CMS_ContentInfo *x); +#endif +int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms); +CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms); +int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms); + +BIO *BIO_new_CMS(BIO *out, CMS_ContentInfo *cms); +int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags); +int PEM_write_bio_CMS_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, + int flags); +CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont); +int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags); + +int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, unsigned int flags); + +CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, unsigned int flags); + +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, X509 *signcert, + EVP_PKEY *pkey, STACK_OF(X509) *certs, unsigned int flags); + +int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); +CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); + +int CMS_digest_verify(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_digest_create(BIO *in, const EVP_MD *md, + unsigned int flags); + +int CMS_EncryptedData_decrypt(CMS_ContentInfo *cms, const unsigned char *key, + size_t keylen, BIO *dcont, BIO *out, unsigned int flags); + +CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, + const unsigned char *key, size_t keylen, unsigned int flags); + +int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + X509_STORE *store, BIO *dcont, BIO *out, unsigned int flags); + +int CMS_verify_receipt(CMS_ContentInfo *rcms, CMS_ContentInfo *ocms, + STACK_OF(X509) *certs, X509_STORE *store, unsigned int flags); + +STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms); + +CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, unsigned int flags); + +int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pkey, X509 *cert, + BIO *dcont, BIO *out, unsigned int flags); + +int CMS_decrypt_set1_pkey(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert); +int CMS_decrypt_set1_key(CMS_ContentInfo *cms, unsigned char *key, + size_t keylen, const unsigned char *id, size_t idlen); +int CMS_decrypt_set1_password(CMS_ContentInfo *cms, unsigned char *pass, + ssize_t passlen); + +STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms); +int CMS_RecipientInfo_type(CMS_RecipientInfo *ri); +EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri); +CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher); +CMS_RecipientInfo *CMS_add1_recipient_cert(CMS_ContentInfo *cms, X509 *recip, + unsigned int flags); +int CMS_RecipientInfo_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pkey); +int CMS_RecipientInfo_ktri_cert_cmp(CMS_RecipientInfo *ri, X509 *cert); +int CMS_RecipientInfo_ktri_get0_algs(CMS_RecipientInfo *ri, EVP_PKEY **pk, + X509 **recip, X509_ALGOR **palg); +int CMS_RecipientInfo_ktri_get0_signer_id(CMS_RecipientInfo *ri, + ASN1_OCTET_STRING **keyid, X509_NAME **issuer, ASN1_INTEGER **sno); + +CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid, + unsigned char *key, size_t keylen, unsigned char *id, size_t idlen, + ASN1_GENERALIZEDTIME *date, ASN1_OBJECT *otherTypeId, ASN1_TYPE *otherType); + +int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri, X509_ALGOR **palg, + ASN1_OCTET_STRING **pid, ASN1_GENERALIZEDTIME **pdate, + ASN1_OBJECT **potherid, ASN1_TYPE **pothertype); + +int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, unsigned char *key, + size_t keylen); + +int CMS_RecipientInfo_kekri_id_cmp(CMS_RecipientInfo *ri, + const unsigned char *id, size_t idlen); + +int CMS_RecipientInfo_set0_password(CMS_RecipientInfo *ri, unsigned char *pass, + ssize_t passlen); + +CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms, int iter, + int wrap_nid, int pbe_nid, unsigned char *pass, ssize_t passlen, + const EVP_CIPHER *kekciph); + +int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); +int CMS_RecipientInfo_encrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri); + +int CMS_uncompress(CMS_ContentInfo *cms, BIO *dcont, BIO *out, + unsigned int flags); +CMS_ContentInfo *CMS_compress(BIO *in, int comp_nid, unsigned int flags); + +int CMS_set1_eContentType(CMS_ContentInfo *cms, const ASN1_OBJECT *oid); +const ASN1_OBJECT *CMS_get0_eContentType(CMS_ContentInfo *cms); + +CMS_CertificateChoices *CMS_add0_CertificateChoices(CMS_ContentInfo *cms); +int CMS_add0_cert(CMS_ContentInfo *cms, X509 *cert); +int CMS_add1_cert(CMS_ContentInfo *cms, X509 *cert); +STACK_OF(X509) *CMS_get1_certs(CMS_ContentInfo *cms); + +CMS_RevocationInfoChoice *CMS_add0_RevocationInfoChoice(CMS_ContentInfo *cms); +int CMS_add0_crl(CMS_ContentInfo *cms, X509_CRL *crl); +int CMS_add1_crl(CMS_ContentInfo *cms, X509_CRL *crl); +STACK_OF(X509_CRL) *CMS_get1_crls(CMS_ContentInfo *cms); + +int CMS_SignedData_init(CMS_ContentInfo *cms); +CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, + EVP_PKEY *pk, const EVP_MD *md, unsigned int flags); +EVP_PKEY_CTX *CMS_SignerInfo_get0_pkey_ctx(CMS_SignerInfo *si); +EVP_MD_CTX *CMS_SignerInfo_get0_md_ctx(CMS_SignerInfo *si); +STACK_OF(CMS_SignerInfo) *CMS_get0_SignerInfos(CMS_ContentInfo *cms); + +void CMS_SignerInfo_set1_signer_cert(CMS_SignerInfo *si, X509 *signer); +int CMS_SignerInfo_get0_signer_id(CMS_SignerInfo *si, ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_SignerInfo_cert_cmp(CMS_SignerInfo *si, X509 *cert); +int CMS_set1_signers_certs(CMS_ContentInfo *cms, STACK_OF(X509) *certs, + unsigned int flags); +void CMS_SignerInfo_get0_algs(CMS_SignerInfo *si, EVP_PKEY **pk, X509 **signer, + X509_ALGOR **pdig, X509_ALGOR **psig); +ASN1_OCTET_STRING *CMS_SignerInfo_get0_signature(CMS_SignerInfo *si); +int CMS_SignerInfo_sign(CMS_SignerInfo *si); +int CMS_SignerInfo_verify(CMS_SignerInfo *si); +int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain); + +int CMS_add_smimecap(CMS_SignerInfo *si, STACK_OF(X509_ALGOR) *algs); +int CMS_add_simple_smimecap(STACK_OF(X509_ALGOR) **algs, int algnid, + int keysize); +int CMS_add_standard_smimecap(STACK_OF(X509_ALGOR) **smcap); + +int CMS_signed_get_attr_count(const CMS_SignerInfo *si); +int CMS_signed_get_attr_by_NID(const CMS_SignerInfo *si, int nid, int lastpos); +int CMS_signed_get_attr_by_OBJ(const CMS_SignerInfo *si, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *CMS_signed_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_signed_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_signed_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_signed_add1_attr_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *obj, + int type, const void *bytes, int len); +int CMS_signed_add1_attr_by_NID(CMS_SignerInfo *si, int nid, int type, + const void *bytes, int len); +int CMS_signed_add1_attr_by_txt(CMS_SignerInfo *si, + const char *attrname, int type, const void *bytes, int len); +void *CMS_signed_get0_data_by_OBJ(CMS_SignerInfo *si, const ASN1_OBJECT *oid, + int lastpos, int type); + +int CMS_unsigned_get_attr_count(const CMS_SignerInfo *si); +int CMS_unsigned_get_attr_by_NID(const CMS_SignerInfo *si, int nid, + int lastpos); +int CMS_unsigned_get_attr_by_OBJ(const CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *CMS_unsigned_get_attr(const CMS_SignerInfo *si, int loc); +X509_ATTRIBUTE *CMS_unsigned_delete_attr(CMS_SignerInfo *si, int loc); +int CMS_unsigned_add1_attr(CMS_SignerInfo *si, X509_ATTRIBUTE *attr); +int CMS_unsigned_add1_attr_by_OBJ(CMS_SignerInfo *si, + const ASN1_OBJECT *obj, int type, const void *bytes, int len); +int CMS_unsigned_add1_attr_by_NID(CMS_SignerInfo *si, int nid, int type, + const void *bytes, int len); +int CMS_unsigned_add1_attr_by_txt(CMS_SignerInfo *si, const char *attrname, + int type, const void *bytes, int len); +void *CMS_unsigned_get0_data_by_OBJ(CMS_SignerInfo *si, ASN1_OBJECT *oid, + int lastpos, int type); + +#ifdef HEADER_X509V3_H + +int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr); +CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen, + int allorfirst, STACK_OF(GENERAL_NAMES) *receiptList, + STACK_OF(GENERAL_NAMES) *receiptsTo); +int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr); +void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, ASN1_STRING **pcid, + int *pallorfirst, STACK_OF(GENERAL_NAMES) **plist, + STACK_OF(GENERAL_NAMES) **prto); +#endif +int CMS_RecipientInfo_kari_get0_alg(CMS_RecipientInfo *ri, X509_ALGOR **palg, + ASN1_OCTET_STRING **pukm); +STACK_OF(CMS_RecipientEncryptedKey) * + CMS_RecipientInfo_kari_get0_reks(CMS_RecipientInfo *ri); + +int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri, + X509_ALGOR **pubalg, ASN1_BIT_STRING **pubkey, ASN1_OCTET_STRING **keyid, + X509_NAME **issuer, ASN1_INTEGER **sno); + +int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert); + +int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek, + ASN1_OCTET_STRING **keyid, ASN1_GENERALIZEDTIME **tm, + CMS_OtherKeyAttribute **other, X509_NAME **issuer, ASN1_INTEGER **sno); +int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek, + X509 *cert); +int CMS_RecipientInfo_kari_set0_pkey(CMS_RecipientInfo *ri, EVP_PKEY *pk); +EVP_CIPHER_CTX *CMS_RecipientInfo_kari_get0_ctx(CMS_RecipientInfo *ri); +int CMS_RecipientInfo_kari_decrypt(CMS_ContentInfo *cms, + CMS_RecipientInfo *ri, CMS_RecipientEncryptedKey *rek); + +int CMS_SharedInfo_encode(unsigned char **pder, X509_ALGOR *kekalg, + ASN1_OCTET_STRING *ukm, int keylen); + +/* Backward compatibility for spelling errors. */ +#define CMS_R_UNKNOWN_DIGEST_ALGORITM CMS_R_UNKNOWN_DIGEST_ALGORITHM +#define CMS_R_UNSUPPORTED_RECPIENTINFO_TYPE \ + CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE + +int ERR_load_CMS_strings(void); + +/* + * CMS function codes. + */ +#define CMS_F_CHECK_CONTENT 99 +#define CMS_F_CMS_ADD0_CERT 164 +#define CMS_F_CMS_ADD0_RECIPIENT_KEY 100 +#define CMS_F_CMS_ADD0_RECIPIENT_PASSWORD 165 +#define CMS_F_CMS_ADD1_RECEIPTREQUEST 158 +#define CMS_F_CMS_ADD1_RECIPIENT_CERT 101 +#define CMS_F_CMS_ADD1_SIGNER 102 +#define CMS_F_CMS_ADD1_SIGNINGTIME 103 +#define CMS_F_CMS_COMPRESS 104 +#define CMS_F_CMS_COMPRESSEDDATA_CREATE 105 +#define CMS_F_CMS_COMPRESSEDDATA_INIT_BIO 106 +#define CMS_F_CMS_COPY_CONTENT 107 +#define CMS_F_CMS_COPY_MESSAGEDIGEST 108 +#define CMS_F_CMS_DATA 109 +#define CMS_F_CMS_DATAFINAL 110 +#define CMS_F_CMS_DATAINIT 111 +#define CMS_F_CMS_DECRYPT 112 +#define CMS_F_CMS_DECRYPT_SET1_KEY 113 +#define CMS_F_CMS_DECRYPT_SET1_PASSWORD 166 +#define CMS_F_CMS_DECRYPT_SET1_PKEY 114 +#define CMS_F_CMS_DIGESTALGORITHM_FIND_CTX 115 +#define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 +#define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 +#define CMS_F_CMS_DIGEST_VERIFY 118 +#define CMS_F_CMS_ENCODE_RECEIPT 161 +#define CMS_F_CMS_ENCRYPT 119 +#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT 179 +#define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 +#define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 +#define CMS_F_CMS_ENCRYPTEDDATA_ENCRYPT 122 +#define CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY 123 +#define CMS_F_CMS_ENVELOPEDDATA_CREATE 124 +#define CMS_F_CMS_ENVELOPEDDATA_INIT_BIO 125 +#define CMS_F_CMS_ENVELOPED_DATA_INIT 126 +#define CMS_F_CMS_ENV_ASN1_CTRL 171 +#define CMS_F_CMS_FINAL 127 +#define CMS_F_CMS_GET0_CERTIFICATE_CHOICES 128 +#define CMS_F_CMS_GET0_CONTENT 129 +#define CMS_F_CMS_GET0_ECONTENT_TYPE 130 +#define CMS_F_CMS_GET0_ENVELOPED 131 +#define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 +#define CMS_F_CMS_GET0_SIGNED 133 +#define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 +#define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 +#define CMS_F_CMS_RECEIPT_VERIFY 160 +#define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 +#define CMS_F_CMS_RECIPIENTINFO_ENCRYPT 169 +#define CMS_F_CMS_RECIPIENTINFO_KARI_ENCRYPT 178 +#define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ALG 175 +#define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID 173 +#define CMS_F_CMS_RECIPIENTINFO_KARI_GET0_REKS 172 +#define CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP 174 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT 135 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT 136 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_GET0_ID 137 +#define CMS_F_CMS_RECIPIENTINFO_KEKRI_ID_CMP 138 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_CERT_CMP 139 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT 140 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_ENCRYPT 141 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_ALGS 142 +#define CMS_F_CMS_RECIPIENTINFO_KTRI_GET0_SIGNER_ID 143 +#define CMS_F_CMS_RECIPIENTINFO_PWRI_CRYPT 167 +#define CMS_F_CMS_RECIPIENTINFO_SET0_KEY 144 +#define CMS_F_CMS_RECIPIENTINFO_SET0_PASSWORD 168 +#define CMS_F_CMS_RECIPIENTINFO_SET0_PKEY 145 +#define CMS_F_CMS_SD_ASN1_CTRL 170 +#define CMS_F_CMS_SET1_IAS 176 +#define CMS_F_CMS_SET1_KEYID 177 +#define CMS_F_CMS_SET1_SIGNERIDENTIFIER 146 +#define CMS_F_CMS_SET_DETACHED 147 +#define CMS_F_CMS_SIGN 148 +#define CMS_F_CMS_SIGNED_DATA_INIT 149 +#define CMS_F_CMS_SIGNERINFO_CONTENT_SIGN 150 +#define CMS_F_CMS_SIGNERINFO_SIGN 151 +#define CMS_F_CMS_SIGNERINFO_VERIFY 152 +#define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 +#define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +#define CMS_F_CMS_SIGN_RECEIPT 163 +#define CMS_F_CMS_STREAM 155 +#define CMS_F_CMS_UNCOMPRESS 156 +#define CMS_F_CMS_VERIFY 157 +#define CMS_F_KEK_UNWRAP_KEY 180 + +/* + * CMS reason codes. + */ +#define CMS_R_ADD_SIGNER_ERROR 99 +#define CMS_R_CERTIFICATE_ALREADY_PRESENT 175 +#define CMS_R_CERTIFICATE_HAS_NO_KEYID 160 +#define CMS_R_CERTIFICATE_VERIFY_ERROR 100 +#define CMS_R_CIPHER_INITIALISATION_ERROR 101 +#define CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR 102 +#define CMS_R_CMS_DATAFINAL_ERROR 103 +#define CMS_R_CMS_LIB 104 +#define CMS_R_CONTENTIDENTIFIER_MISMATCH 170 +#define CMS_R_CONTENT_NOT_FOUND 105 +#define CMS_R_CONTENT_TYPE_MISMATCH 171 +#define CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA 106 +#define CMS_R_CONTENT_TYPE_NOT_ENVELOPED_DATA 107 +#define CMS_R_CONTENT_TYPE_NOT_SIGNED_DATA 108 +#define CMS_R_CONTENT_VERIFY_ERROR 109 +#define CMS_R_CTRL_ERROR 110 +#define CMS_R_CTRL_FAILURE 111 +#define CMS_R_DECRYPT_ERROR 112 +#define CMS_R_ERROR_GETTING_PUBLIC_KEY 113 +#define CMS_R_ERROR_READING_MESSAGEDIGEST_ATTRIBUTE 114 +#define CMS_R_ERROR_SETTING_KEY 115 +#define CMS_R_ERROR_SETTING_RECIPIENTINFO 116 +#define CMS_R_INVALID_ENCRYPTED_KEY_LENGTH 117 +#define CMS_R_INVALID_KEY_ENCRYPTION_PARAMETER 176 +#define CMS_R_INVALID_KEY_LENGTH 118 +#define CMS_R_MD_BIO_INIT_ERROR 119 +#define CMS_R_MESSAGEDIGEST_ATTRIBUTE_WRONG_LENGTH 120 +#define CMS_R_MESSAGEDIGEST_WRONG_LENGTH 121 +#define CMS_R_MSGSIGDIGEST_ERROR 172 +#define CMS_R_MSGSIGDIGEST_VERIFICATION_FAILURE 162 +#define CMS_R_MSGSIGDIGEST_WRONG_LENGTH 163 +#define CMS_R_NEED_ONE_SIGNER 164 +#define CMS_R_NOT_A_SIGNED_RECEIPT 165 +#define CMS_R_NOT_ENCRYPTED_DATA 122 +#define CMS_R_NOT_KEK 123 +#define CMS_R_NOT_KEY_AGREEMENT 181 +#define CMS_R_NOT_KEY_TRANSPORT 124 +#define CMS_R_NOT_PWRI 177 +#define CMS_R_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 125 +#define CMS_R_NO_CIPHER 126 +#define CMS_R_NO_CONTENT 127 +#define CMS_R_NO_CONTENT_TYPE 173 +#define CMS_R_NO_DEFAULT_DIGEST 128 +#define CMS_R_NO_DIGEST_SET 129 +#define CMS_R_NO_KEY 130 +#define CMS_R_NO_KEY_OR_CERT 174 +#define CMS_R_NO_MATCHING_DIGEST 131 +#define CMS_R_NO_MATCHING_RECIPIENT 132 +#define CMS_R_NO_MATCHING_SIGNATURE 166 +#define CMS_R_NO_MSGSIGDIGEST 167 +#define CMS_R_NO_PASSWORD 178 +#define CMS_R_NO_PRIVATE_KEY 133 +#define CMS_R_NO_PUBLIC_KEY 134 +#define CMS_R_NO_RECEIPT_REQUEST 168 +#define CMS_R_NO_SIGNERS 135 +#define CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 136 +#define CMS_R_RECEIPT_DECODE_ERROR 169 +#define CMS_R_RECIPIENT_ERROR 137 +#define CMS_R_SIGNER_CERTIFICATE_NOT_FOUND 138 +#define CMS_R_SIGNFINAL_ERROR 139 +#define CMS_R_SMIME_TEXT_ERROR 140 +#define CMS_R_STORE_INIT_ERROR 141 +#define CMS_R_TYPE_NOT_COMPRESSED_DATA 142 +#define CMS_R_TYPE_NOT_DATA 143 +#define CMS_R_TYPE_NOT_DIGESTED_DATA 144 +#define CMS_R_TYPE_NOT_ENCRYPTED_DATA 145 +#define CMS_R_TYPE_NOT_ENVELOPED_DATA 146 +#define CMS_R_UNABLE_TO_FINALIZE_CONTEXT 147 +#define CMS_R_UNKNOWN_CIPHER 148 +#define CMS_R_UNKNOWN_DIGEST_ALGORITHM 149 +#define CMS_R_UNKNOWN_ID 150 +#define CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM 151 +#define CMS_R_UNSUPPORTED_CONTENT_TYPE 152 +#define CMS_R_UNSUPPORTED_KEK_ALGORITHM 153 +#define CMS_R_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM 179 +#define CMS_R_UNSUPPORTED_RECIPIENTINFO_TYPE 155 +#define CMS_R_UNSUPPORTED_RECIPIENT_TYPE 154 +#define CMS_R_UNSUPPORTED_TYPE 156 +#define CMS_R_UNWRAP_ERROR 157 +#define CMS_R_UNWRAP_FAILURE 180 +#define CMS_R_VERIFICATION_FAILURE 158 +#define CMS_R_WRAP_ERROR 159 + +#ifdef __cplusplus +} +#endif +#endif +#endif diff --git a/include/openssl/comp.h b/include/openssl/comp.h new file mode 100644 index 0000000..f033027 --- /dev/null +++ b/include/openssl/comp.h @@ -0,0 +1,7 @@ +/* $OpenBSD: comp.h,v 1.13 2023/07/28 09:42:44 tb Exp $ */ + +/* + * Public domain. + * + * This header is intentionally left empty. Some software uses it unnecessarily. + */ diff --git a/include/openssl/conf.h b/include/openssl/conf.h new file mode 100644 index 0000000..5d10163 --- /dev/null +++ b/include/openssl/conf.h @@ -0,0 +1,246 @@ +/* $OpenBSD: conf.h,v 1.16 2022/07/12 14:42:48 kn Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CONF_H +#define HEADER_CONF_H + +#include + +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *section; + char *name; + char *value; +} CONF_VALUE; + +DECLARE_STACK_OF(CONF_VALUE) +DECLARE_LHASH_OF(CONF_VALUE); + +struct conf_st; +struct conf_method_st; +typedef struct conf_method_st CONF_METHOD; + +struct conf_method_st { + const char *name; + CONF *(*create)(CONF_METHOD *meth); + int (*init)(CONF *conf); + int (*destroy)(CONF *conf); + int (*destroy_data)(CONF *conf); + int (*load_bio)(CONF *conf, BIO *bp, long *eline); + int (*dump)(const CONF *conf, BIO *bp); + int (*is_number)(const CONF *conf, char c); + int (*to_int)(const CONF *conf, char c); + int (*load)(CONF *conf, const char *name, long *eline); +}; + +/* Module definitions */ + +typedef struct conf_imodule_st CONF_IMODULE; +typedef struct conf_module_st CONF_MODULE; + +DECLARE_STACK_OF(CONF_MODULE) +DECLARE_STACK_OF(CONF_IMODULE) + +/* DSO module function typedefs */ +typedef int conf_init_func(CONF_IMODULE *md, const CONF *cnf); +typedef void conf_finish_func(CONF_IMODULE *md); + +#define CONF_MFLAGS_IGNORE_ERRORS 0x1 +#define CONF_MFLAGS_IGNORE_RETURN_CODES 0x2 +#define CONF_MFLAGS_SILENT 0x4 +#define CONF_MFLAGS_NO_DSO 0x8 +#define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +#define CONF_MFLAGS_DEFAULT_SECTION 0x20 + +int CONF_set_default_method(CONF_METHOD *meth); +void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash); +LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file, + long *eline); +LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp, + long *eline); +LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp, long *eline); +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf, + const char *section); +char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +long CONF_get_number(LHASH_OF(CONF_VALUE) *conf, const char *group, + const char *name); +void CONF_free(LHASH_OF(CONF_VALUE) *conf); +int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out); +int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out); + +void OPENSSL_config(const char *config_name); +void OPENSSL_no_config(void); + +/* New conf code. The semantics are different from the functions above. + If that wasn't the case, the above functions would have been replaced */ + +struct conf_st { + CONF_METHOD *meth; + void *meth_data; + LHASH_OF(CONF_VALUE) *data; +}; + +CONF *NCONF_new(CONF_METHOD *meth); +CONF_METHOD *NCONF_default(void); +CONF_METHOD *NCONF_WIN32(void); +void NCONF_free(CONF *conf); +void NCONF_free_data(CONF *conf); + +int NCONF_load(CONF *conf, const char *file, long *eline); +int NCONF_load_fp(CONF *conf, FILE *fp, long *eline); +int NCONF_load_bio(CONF *conf, BIO *bp, long *eline); +STACK_OF(CONF_VALUE) *NCONF_get_section(const CONF *conf, const char *section); +char *NCONF_get_string(const CONF *conf, const char *group, const char *name); +int NCONF_get_number_e(const CONF *conf, const char *group, const char *name, + long *result); +int NCONF_dump_fp(const CONF *conf, FILE *out); +int NCONF_dump_bio(const CONF *conf, BIO *out); + +#define NCONF_get_number(c,g,n,r) NCONF_get_number_e(c,g,n,r) + +/* Module functions */ + +int CONF_modules_load(const CONF *cnf, const char *appname, + unsigned long flags); +int CONF_modules_load_file(const char *filename, const char *appname, + unsigned long flags); +void CONF_modules_unload(int all); +void CONF_modules_finish(void); +void CONF_modules_free(void); +int CONF_module_add(const char *name, conf_init_func *ifunc, + conf_finish_func *ffunc); + +const char *CONF_imodule_get_name(const CONF_IMODULE *md); +const char *CONF_imodule_get_value(const CONF_IMODULE *md); +void *CONF_imodule_get_usr_data(const CONF_IMODULE *md); +void CONF_imodule_set_usr_data(CONF_IMODULE *md, void *usr_data); +CONF_MODULE *CONF_imodule_get_module(const CONF_IMODULE *md); +unsigned long CONF_imodule_get_flags(const CONF_IMODULE *md); +void CONF_imodule_set_flags(CONF_IMODULE *md, unsigned long flags); +void *CONF_module_get_usr_data(CONF_MODULE *pmod); +void CONF_module_set_usr_data(CONF_MODULE *pmod, void *usr_data); + +char *CONF_get1_default_config_file(void); + +int CONF_parse_list(const char *list, int sep, int nospc, + int (*list_cb)(const char *elem, int len, void *usr), void *arg); + +void OPENSSL_load_builtin_modules(void); + +void ERR_load_CONF_strings(void); + +/* Error codes for the CONF functions. */ + +/* Function codes. */ +#define CONF_F_CONF_DUMP_FP 104 +#define CONF_F_CONF_LOAD 100 +#define CONF_F_CONF_LOAD_BIO 102 +#define CONF_F_CONF_LOAD_FP 103 +#define CONF_F_CONF_MODULES_LOAD 116 +#define CONF_F_CONF_PARSE_LIST 119 +#define CONF_F_DEF_LOAD 120 +#define CONF_F_DEF_LOAD_BIO 121 +#define CONF_F_MODULE_INIT 115 +#define CONF_F_MODULE_LOAD_DSO 117 +#define CONF_F_MODULE_RUN 118 +#define CONF_F_NCONF_DUMP_BIO 105 +#define CONF_F_NCONF_DUMP_FP 106 +#define CONF_F_NCONF_GET_NUMBER 107 +#define CONF_F_NCONF_GET_NUMBER_E 112 +#define CONF_F_NCONF_GET_SECTION 108 +#define CONF_F_NCONF_GET_STRING 109 +#define CONF_F_NCONF_LOAD 113 +#define CONF_F_NCONF_LOAD_BIO 110 +#define CONF_F_NCONF_LOAD_FP 114 +#define CONF_F_NCONF_NEW 111 +#define CONF_F_STR_COPY 101 + +/* Reason codes. */ +#define CONF_R_ERROR_LOADING_DSO 110 +#define CONF_R_LIST_CANNOT_BE_NULL 115 +#define CONF_R_MISSING_CLOSE_SQUARE_BRACKET 100 +#define CONF_R_MISSING_EQUAL_SIGN 101 +#define CONF_R_MISSING_FINISH_FUNCTION 111 +#define CONF_R_MISSING_INIT_FUNCTION 112 +#define CONF_R_MODULE_INITIALIZATION_ERROR 109 +#define CONF_R_NO_CLOSE_BRACE 102 +#define CONF_R_NO_CONF 105 +#define CONF_R_NO_CONF_OR_ENVIRONMENT_VARIABLE 106 +#define CONF_R_NO_SECTION 107 +#define CONF_R_NO_SUCH_FILE 114 +#define CONF_R_NO_VALUE 108 +#define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 103 +#define CONF_R_UNKNOWN_MODULE_NAME 113 +#define CONF_R_VARIABLE_EXPANSION_TOO_LONG 116 +#define CONF_R_VARIABLE_HAS_NO_VALUE 104 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/conf_api.h b/include/openssl/conf_api.h new file mode 100644 index 0000000..95f9386 --- /dev/null +++ b/include/openssl/conf_api.h @@ -0,0 +1,88 @@ +/* $OpenBSD: conf_api.h,v 1.4 2014/06/12 15:49:28 deraadt Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_CONF_API_H +#define HEADER_CONF_API_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Up until OpenSSL 0.9.5a, this was new_section */ +CONF_VALUE *_CONF_new_section(CONF *conf, const char *section); +/* Up until OpenSSL 0.9.5a, this was get_section */ +CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section); +/* 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); + +int _CONF_add_string(CONF *conf, CONF_VALUE *section, CONF_VALUE *value); +char *_CONF_get_string(const CONF *conf, const char *section, + const char *name); +long _CONF_get_number(const CONF *conf, const char *section, const char *name); + +int _CONF_new_data(CONF *conf); +void _CONF_free_data(CONF *conf); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h new file mode 100644 index 0000000..07a55ec --- /dev/null +++ b/include/openssl/crypto.h @@ -0,0 +1,548 @@ +/* $OpenBSD: crypto.h,v 1.63 2023/07/28 10:19:20 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#include +#include +#include + +#ifndef HEADER_CRYPTO_H +#define HEADER_CRYPTO_H + +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Backward compatibility to SSLeay */ +/* This is more to be used to check the correct DLL is being used + * in the MS world. */ +#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER +#define SSLEAY_VERSION 0 +/* #define SSLEAY_OPTIONS 1 no longer supported */ +#define SSLEAY_CFLAGS 2 +#define SSLEAY_BUILT_ON 3 +#define SSLEAY_PLATFORM 4 +#define SSLEAY_DIR 5 + +/* When changing the CRYPTO_LOCK_* list, be sure to maintain the text lock + * names in cryptlib.c + */ + +#define CRYPTO_LOCK_ERR 1 +#define CRYPTO_LOCK_EX_DATA 2 +#define CRYPTO_LOCK_X509 3 +#define CRYPTO_LOCK_X509_INFO 4 +#define CRYPTO_LOCK_X509_PKEY 5 +#define CRYPTO_LOCK_X509_CRL 6 +#define CRYPTO_LOCK_X509_REQ 7 +#define CRYPTO_LOCK_DSA 8 +#define CRYPTO_LOCK_RSA 9 +#define CRYPTO_LOCK_EVP_PKEY 10 +#define CRYPTO_LOCK_X509_STORE 11 +#define CRYPTO_LOCK_SSL_CTX 12 +#define CRYPTO_LOCK_SSL_CERT 13 +#define CRYPTO_LOCK_SSL_SESSION 14 +#define CRYPTO_LOCK_SSL_SESS_CERT 15 +#define CRYPTO_LOCK_SSL 16 +#define CRYPTO_LOCK_SSL_METHOD 17 +#define CRYPTO_LOCK_RAND 18 +#define CRYPTO_LOCK_RAND2 19 +#define CRYPTO_LOCK_MALLOC 20 +#define CRYPTO_LOCK_BIO 21 +#define CRYPTO_LOCK_GETHOSTBYNAME 22 +#define CRYPTO_LOCK_GETSERVBYNAME 23 +#define CRYPTO_LOCK_READDIR 24 +#define CRYPTO_LOCK_RSA_BLINDING 25 +#define CRYPTO_LOCK_DH 26 +#define CRYPTO_LOCK_MALLOC2 27 +#define CRYPTO_LOCK_DSO 28 +#define CRYPTO_LOCK_DYNLOCK 29 +#define CRYPTO_LOCK_ENGINE 30 +#define CRYPTO_LOCK_UI 31 +#define CRYPTO_LOCK_ECDSA 32 +#define CRYPTO_LOCK_EC 33 +#define CRYPTO_LOCK_ECDH 34 +#define CRYPTO_LOCK_BN 35 +#define CRYPTO_LOCK_EC_PRE_COMP 36 +#define CRYPTO_LOCK_STORE 37 +#define CRYPTO_LOCK_COMP 38 +#define CRYPTO_LOCK_FIPS 39 +#define CRYPTO_LOCK_FIPS2 40 +#define CRYPTO_NUM_LOCKS 41 + +#define CRYPTO_LOCK 1 +#define CRYPTO_UNLOCK 2 +#define CRYPTO_READ 4 +#define CRYPTO_WRITE 8 + +#ifndef CRYPTO_w_lock +#define CRYPTO_w_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,NULL,0) +#define CRYPTO_w_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,NULL,0) +#define CRYPTO_r_lock(type) \ + CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,NULL,0) +#define CRYPTO_r_unlock(type) \ + CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,NULL,0) +#define CRYPTO_add(addr,amount,type) \ + CRYPTO_add_lock(addr,amount,type,NULL,0) +#endif + +/* Some applications as well as some parts of OpenSSL need to allocate + and deallocate locks in a dynamic fashion. The following typedef + makes this possible in a type-safe manner. */ +/* struct CRYPTO_dynlock_value has to be defined by the application. */ +typedef struct { + int references; + struct CRYPTO_dynlock_value *data; +} CRYPTO_dynlock; + + +/* The following can be used to detect memory leaks in the SSLeay library. + * It used, it turns on malloc checking */ + +#define CRYPTO_MEM_CHECK_OFF 0x0 /* an enume */ +#define CRYPTO_MEM_CHECK_ON 0x1 /* a bit */ +#define CRYPTO_MEM_CHECK_ENABLE 0x2 /* a bit */ +#define CRYPTO_MEM_CHECK_DISABLE 0x3 /* an enume */ + +/* The following are bit values to turn on or off options connected to the + * malloc checking functionality */ + +/* Adds time to the memory checking information */ +#define V_CRYPTO_MDEBUG_TIME 0x1 /* a bit */ +/* Adds thread number to the memory checking information */ +#define V_CRYPTO_MDEBUG_THREAD 0x2 /* a bit */ + +#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD) + + +/* predec of the BIO type */ +typedef struct bio_st BIO_dummy; + +struct crypto_ex_data_st { + STACK_OF(void) *sk; +}; +DECLARE_STACK_OF(void) + +#define CRYPTO_EX_INDEX_SSL 0 +#define CRYPTO_EX_INDEX_SSL_CTX 1 +#define CRYPTO_EX_INDEX_SSL_SESSION 2 +#define CRYPTO_EX_INDEX_APP 3 +#define CRYPTO_EX_INDEX_BIO 4 +#define CRYPTO_EX_INDEX_DH 5 +#define CRYPTO_EX_INDEX_DSA 6 +#define CRYPTO_EX_INDEX_EC_KEY 7 +#define CRYPTO_EX_INDEX_ENGINE 8 +#define CRYPTO_EX_INDEX_RSA 9 +#define CRYPTO_EX_INDEX_UI 10 +#define CRYPTO_EX_INDEX_UI_METHOD 11 +#define CRYPTO_EX_INDEX_X509 12 +#define CRYPTO_EX_INDEX_X509_STORE 13 +#define CRYPTO_EX_INDEX_X509_STORE_CTX 14 +#define CRYPTO_EX_INDEX__COUNT 15 + +#ifndef LIBRESSL_INTERNAL +#define CRYPTO_malloc_init() (0) +#define CRYPTO_malloc_debug_init() (0) + +#if defined CRYPTO_MDEBUG_ALL || defined CRYPTO_MDEBUG_TIME || defined CRYPTO_MDEBUG_THREAD +# ifndef CRYPTO_MDEBUG /* avoid duplicate #define */ +# define CRYPTO_MDEBUG +# endif +#endif + +int CRYPTO_mem_ctrl(int mode); +int CRYPTO_is_mem_check_on(void); + +/* for applications */ +#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) +#define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) + +#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,NULL,0) +#define OPENSSL_strdup(str) CRYPTO_strdup((str),NULL,0) +#define OPENSSL_realloc(addr,num) \ + CRYPTO_realloc((char *)addr,(int)num,NULL,0) +#define OPENSSL_realloc_clean(addr,old_num,num) \ + CRYPTO_realloc_clean(addr,old_num,num,NULL,0) +#define OPENSSL_remalloc(addr,num) \ + CRYPTO_remalloc((char **)addr,(int)num,NULL,0) +#define OPENSSL_freeFunc CRYPTO_free +#define OPENSSL_free(addr) CRYPTO_free(addr) + +#define OPENSSL_malloc_locked(num) \ + CRYPTO_malloc_locked((int)num,NULL,0) +#define OPENSSL_free_locked(addr) CRYPTO_free_locked(addr) +#endif + +const char *OpenSSL_version(int type); +#define OPENSSL_VERSION 0 +#define OPENSSL_CFLAGS 1 +#define OPENSSL_BUILT_ON 2 +#define OPENSSL_PLATFORM 3 +#define OPENSSL_DIR 4 +#define OPENSSL_ENGINES_DIR 5 +unsigned long OpenSSL_version_num(void); + +const char *SSLeay_version(int type); +unsigned long SSLeay(void); + +/* Within a given class, get/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); +/* Initialise/duplicate/free CRYPTO_EX_DATA variables corresponding to a given + * class (invokes whatever per-class callbacks are applicable) */ +int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to, + CRYPTO_EX_DATA *from); +void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); +/* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular index + * (relative to the class type involved) */ +int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val); +void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx); +/* This function cleans up all "ex_data" state. It mustn't be called under + * potential race-conditions. */ +void CRYPTO_cleanup_all_ex_data(void); + +void CRYPTO_lock(int mode, int type, const char *file, int line); +int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, + int line); + +/* Don't use this structure directly. */ +typedef struct crypto_threadid_st { + void *ptr; + unsigned long val; +} CRYPTO_THREADID; +void CRYPTO_THREADID_current(CRYPTO_THREADID *id); +int CRYPTO_THREADID_cmp(const CRYPTO_THREADID *a, const CRYPTO_THREADID *b); +void CRYPTO_THREADID_cpy(CRYPTO_THREADID *dest, const CRYPTO_THREADID *src); +unsigned long CRYPTO_THREADID_hash(const CRYPTO_THREADID *id); + +#ifndef LIBRESSL_INTERNAL +/* These functions are deprecated no-op stubs */ +void CRYPTO_set_id_callback(unsigned long (*func)(void)); +unsigned long (*CRYPTO_get_id_callback(void))(void); +unsigned long CRYPTO_thread_id(void); + +int CRYPTO_get_new_lockid(char *name); +const char *CRYPTO_get_lock_name(int type); + +int CRYPTO_num_locks(void); +void CRYPTO_set_locking_callback(void (*func)(int mode, int type, + const char *file, int line)); +void (*CRYPTO_get_locking_callback(void))(int mode, int type, + const char *file, int line); +void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int type, + const char *file, int line)); +int (*CRYPTO_get_add_lock_callback(void))(int *num, int mount, int type, + const char *file, int line); + +void CRYPTO_THREADID_set_numeric(CRYPTO_THREADID *id, unsigned long val); +void CRYPTO_THREADID_set_pointer(CRYPTO_THREADID *id, void *ptr); +int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID *)); +void (*CRYPTO_THREADID_get_callback(void))(CRYPTO_THREADID *); + +int CRYPTO_get_new_dynlockid(void); +void CRYPTO_destroy_dynlockid(int i); +struct CRYPTO_dynlock_value *CRYPTO_get_dynlock_value(int i); +void CRYPTO_set_dynlock_create_callback(struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file, int line)); +void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)); +void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l, const char *file, int line)); +struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(const char *file, int line); +void (*CRYPTO_get_dynlock_lock_callback(void))(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line); +void (*CRYPTO_get_dynlock_destroy_callback(void))(struct CRYPTO_dynlock_value *l, const char *file, int line); +#endif + +/* CRYPTO_set_mem_functions includes CRYPTO_set_locked_mem_functions -- + * call the latter last if you need different functions */ +int CRYPTO_set_mem_functions(void *(*m)(size_t), void *(*r)(void *, size_t), void (*f)(void *)); +int CRYPTO_set_locked_mem_functions(void *(*m)(size_t), void (*free_func)(void *)); +int CRYPTO_set_mem_ex_functions(void *(*m)(size_t, const char *, int), + void *(*r)(void *, size_t, const char *, int), void (*f)(void *)); +int CRYPTO_set_locked_mem_ex_functions(void *(*m)(size_t, const char *, int), + void (*free_func)(void *)); +int CRYPTO_set_mem_debug_functions( + void (*m)(void *, int, const char *, int, int), + void (*r)(void *, void *, int, const char *, int, int), + void (*f)(void *, int), void (*so)(long), long (*go)(void)); +void CRYPTO_get_mem_functions(void *(**m)(size_t), void *(**r)(void *, size_t), + void (**f)(void *)); +void CRYPTO_get_locked_mem_functions(void *(**m)(size_t), void (**f)(void *)); +void CRYPTO_get_mem_ex_functions(void *(**m)(size_t, const char *, int), + void *(**r)(void *, size_t, const char *, int), void (**f)(void *)); +void CRYPTO_get_locked_mem_ex_functions(void *(**m)(size_t, const char *, int), + void (**f)(void *)); +void CRYPTO_get_mem_debug_functions( + void (**m)(void *, int, const char *, int, int), + void (**r)(void *, void *, int, const char *, int, int), + void (**f)(void *, int), void (**so)(long), long (**go)(void)); + +#ifndef LIBRESSL_INTERNAL +void *CRYPTO_malloc_locked(int num, const char *file, int line); +void CRYPTO_free_locked(void *ptr); +void *CRYPTO_malloc(int num, const char *file, int line); +char *CRYPTO_strdup(const char *str, const char *file, int line); +void CRYPTO_free(void *ptr); +void *CRYPTO_realloc(void *addr, int num, const char *file, int line); +#endif + +void *CRYPTO_realloc_clean(void *addr, int old_num, int num, + const char *file, int line); +void *CRYPTO_remalloc(void *addr, int num, const char *file, int line); + +#ifndef LIBRESSL_INTERNAL +void OPENSSL_cleanse(void *ptr, size_t len); +#endif + +void CRYPTO_set_mem_debug_options(long bits); +long CRYPTO_get_mem_debug_options(void); + +#define CRYPTO_push_info(info) \ + CRYPTO_push_info_(info, NULL, 0); +int CRYPTO_push_info_(const char *info, const char *file, int line); +int CRYPTO_pop_info(void); +int CRYPTO_remove_all_info(void); + + +/* Default debugging functions (enabled by CRYPTO_malloc_debug_init() macro; + * used as default in CRYPTO_MDEBUG compilations): */ +/* The last argument has the following significance: + * + * 0: called before the actual memory allocation has taken place + * 1: called after the actual memory allocation has taken place + */ +void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line, int before_p) + __attribute__ ((deprecated)); +void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num, const char *file, int line, int before_p) + __attribute__ ((deprecated)); +void CRYPTO_dbg_free(void *addr, int before_p) + __attribute__ ((deprecated)); +/* Tell the debugging code about options. By default, the following values + * apply: + * + * 0: Clear all options. + * V_CRYPTO_MDEBUG_TIME (1): Set the "Show Time" option. + * V_CRYPTO_MDEBUG_THREAD (2): Set the "Show Thread Number" option. + * V_CRYPTO_MDEBUG_ALL (3): 1 + 2 + */ +void CRYPTO_dbg_set_options(long bits) + __attribute__ ((deprecated)); +long CRYPTO_dbg_get_options(void) + __attribute__ ((deprecated)); + + +int CRYPTO_mem_leaks_fp(FILE *); +int CRYPTO_mem_leaks(struct bio_st *bio); +/* unsigned long order, char *file, int line, int num_bytes, char *addr */ +typedef int *CRYPTO_MEM_LEAK_CB(unsigned long, const char *, int, int, void *); +int CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb); + +/* + * Because this is a public header, use a portable method of indicating the + * function does not return, rather than __dead. + */ +#ifdef _MSC_VER +__declspec(noreturn) +#else +__attribute__((__noreturn__)) +#endif +void OpenSSLDie(const char *file, int line, const char *assertion); +#define OPENSSL_assert(e) (void)((e) ? 0 : (OpenSSLDie(__FILE__, __LINE__, #e),1)) + +uint64_t OPENSSL_cpu_caps(void); + +int OPENSSL_isservice(void); + +#ifndef LIBRESSL_INTERNAL +int FIPS_mode(void); +int FIPS_mode_set(int r); + +void OPENSSL_init(void); + +/* CRYPTO_memcmp returns zero iff the |len| bytes at |a| and |b| are equal. It + * takes an amount of time dependent on |len|, but independent of the contents + * of |a| and |b|. Unlike memcmp, it cannot be used to put elements into a + * defined order as the return value when a != b is undefined, other than to be + * non-zero. */ +int CRYPTO_memcmp(const void *a, const void *b, size_t len); +#endif + +/* + * OpenSSL compatible OPENSSL_INIT options. + */ + +#define OPENSSL_INIT_NO_LOAD_CONFIG 0x00000001L +#define OPENSSL_INIT_LOAD_CONFIG 0x00000002L + +/* LibreSSL specific */ +#define _OPENSSL_INIT_FLAG_NOOP 0x80000000L + +/* + * These are provided for compatibility, but have no effect + * on how LibreSSL is initialized. + */ +#define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ADD_ALL_CIPHERS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ADD_ALL_DIGESTS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_NO_ADD_ALL_CIPHERS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_NO_ADD_ALL_DIGESTS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ASYNC _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_RDRAND _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_DYNAMIC _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_OPENSSL _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_CRYPTODEV _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_CAPI _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_PADLOCK _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_AFALG _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_reserved_internal _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ATFORK _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_ENGINE_ALL_BUILTIN _OPENSSL_INIT_FLAG_NOOP + +int OPENSSL_init_crypto(uint64_t opts, const void *settings); +void OPENSSL_cleanup(void); + +void ERR_load_CRYPTO_strings(void); + +/* Error codes for the CRYPTO functions. */ + +/* Function codes. */ +#define CRYPTO_F_CRYPTO_GET_EX_NEW_INDEX 100 +#define CRYPTO_F_CRYPTO_GET_NEW_DYNLOCKID 103 +#define CRYPTO_F_CRYPTO_GET_NEW_LOCKID 101 +#define CRYPTO_F_CRYPTO_SET_EX_DATA 102 +#define CRYPTO_F_DEF_ADD_INDEX 104 +#define CRYPTO_F_DEF_GET_CLASS 105 +#define CRYPTO_F_FIPS_MODE_SET 109 +#define CRYPTO_F_INT_DUP_EX_DATA 106 +#define CRYPTO_F_INT_FREE_EX_DATA 107 +#define CRYPTO_F_INT_NEW_EX_DATA 108 + +/* Reason codes. */ +#define CRYPTO_R_FIPS_MODE_NOT_SUPPORTED 101 +#define CRYPTO_R_NO_DYNLOCK_CREATE_CALLBACK 100 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ct.h b/include/openssl/ct.h new file mode 100644 index 0000000..895046e --- /dev/null +++ b/include/openssl/ct.h @@ -0,0 +1,567 @@ +/* $OpenBSD: ct.h,v 1.7 2022/05/08 20:59:32 tb Exp $ */ +/* + * Public API for Certificate Transparency (CT). + * Written by Rob Percival (robpercival@google.com) for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2016 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_CT_H +#define HEADER_CT_H + +#include + +#ifndef OPENSSL_NO_CT +#include +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +/* Minimum RSA key size, from RFC6962 */ +#define SCT_MIN_RSA_BITS 2048 + +/* All hashes are SHA256 in v1 of Certificate Transparency */ +#define CT_V1_HASHLEN SHA256_DIGEST_LENGTH + +typedef enum { + CT_LOG_ENTRY_TYPE_NOT_SET = -1, + CT_LOG_ENTRY_TYPE_X509 = 0, + CT_LOG_ENTRY_TYPE_PRECERT = 1 +} ct_log_entry_type_t; + +typedef enum { + SCT_VERSION_NOT_SET = -1, + SCT_VERSION_V1 = 0 +} sct_version_t; + +typedef enum { + SCT_SOURCE_UNKNOWN, + SCT_SOURCE_TLS_EXTENSION, + SCT_SOURCE_X509V3_EXTENSION, + SCT_SOURCE_OCSP_STAPLED_RESPONSE +} sct_source_t; + +typedef enum { + SCT_VALIDATION_STATUS_NOT_SET, + SCT_VALIDATION_STATUS_UNKNOWN_LOG, + SCT_VALIDATION_STATUS_VALID, + SCT_VALIDATION_STATUS_INVALID, + SCT_VALIDATION_STATUS_UNVERIFIED, + SCT_VALIDATION_STATUS_UNKNOWN_VERSION +} sct_validation_status_t; + +DECLARE_STACK_OF(SCT) +DECLARE_STACK_OF(CTLOG) + +/****************************************** + * CT policy evaluation context functions * + ******************************************/ + +/* + * Creates a new, empty policy evaluation context. + * The caller is responsible for calling CT_POLICY_EVAL_CTX_free when finished + * with the CT_POLICY_EVAL_CTX. + */ +CT_POLICY_EVAL_CTX *CT_POLICY_EVAL_CTX_new(void); + +/* Deletes a policy evaluation context and anything it owns. */ +void CT_POLICY_EVAL_CTX_free(CT_POLICY_EVAL_CTX *ctx); + +/* Gets the peer certificate that the SCTs are for */ +X509* CT_POLICY_EVAL_CTX_get0_cert(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the certificate associated with the received SCTs. + * Increments the reference count of cert. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_cert(CT_POLICY_EVAL_CTX *ctx, X509 *cert); + +/* Gets the issuer of the aforementioned certificate */ +X509* CT_POLICY_EVAL_CTX_get0_issuer(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the issuer of the certificate associated with the received SCTs. + * Increments the reference count of issuer. + * Returns 1 on success, 0 otherwise. + */ +int CT_POLICY_EVAL_CTX_set1_issuer(CT_POLICY_EVAL_CTX *ctx, X509 *issuer); + +/* Gets the CT logs that are trusted sources of SCTs */ +const CTLOG_STORE *CT_POLICY_EVAL_CTX_get0_log_store(const CT_POLICY_EVAL_CTX *ctx); + +/* Sets the log store that is in use. It must outlive the CT_POLICY_EVAL_CTX. */ +void CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(CT_POLICY_EVAL_CTX *ctx, + CTLOG_STORE *log_store); + +/* + * Gets the time, in milliseconds since the Unix epoch, that will be used as the + * current time when checking whether an SCT was issued in the future. + * Such SCTs will fail validation, as required by RFC6962. + */ +uint64_t CT_POLICY_EVAL_CTX_get_time(const CT_POLICY_EVAL_CTX *ctx); + +/* + * Sets the time to evaluate SCTs against, in milliseconds since the Unix epoch. + * If an SCT's timestamp is after this time, it will be interpreted as having + * been issued in the future. RFC6962 states that "TLS clients MUST reject SCTs + * whose timestamp is in the future", so an SCT will not validate in this case. + */ +void CT_POLICY_EVAL_CTX_set_time(CT_POLICY_EVAL_CTX *ctx, uint64_t time_in_ms); + +/***************** + * SCT functions * + *****************/ + +/* + * Creates a new, blank SCT. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new(void); + +/* + * Creates a new SCT from some base64-encoded strings. + * The caller is responsible for calling SCT_free when finished with the SCT. + */ +SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, + ct_log_entry_type_t entry_type, uint64_t timestamp, + const char *extensions_base64, const char *signature_base64); + +/* + * Frees the SCT and the underlying data structures. + */ +void SCT_free(SCT *sct); + +/* + * Free a stack of SCTs, and the underlying SCTs themselves. + * Intended to be compatible with X509V3_EXT_FREE. + */ +void SCT_LIST_free(STACK_OF(SCT) *a); + +/* + * Returns the version of the SCT. + */ +sct_version_t SCT_get_version(const SCT *sct); + +/* + * Set the version of an SCT. + * Returns 1 on success, 0 if the version is unrecognized. + */ +int SCT_set_version(SCT *sct, sct_version_t version); + +/* + * Returns the log entry type of the SCT. + */ +ct_log_entry_type_t SCT_get_log_entry_type(const SCT *sct); + +/* + * Set the log entry type of an SCT. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_log_entry_type(SCT *sct, ct_log_entry_type_t entry_type); + +/* + * Gets the ID of the log that an SCT came from. + * Ownership of the log ID remains with the SCT. + * Returns the length of the log ID. + */ +size_t SCT_get0_log_id(const SCT *sct, unsigned char **log_id); + +/* + * Set the log ID of an SCT to point directly to the *log_id specified. + * The SCT takes ownership of the specified pointer. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set0_log_id(SCT *sct, unsigned char *log_id, size_t log_id_len); + +/* + * Set the log ID of an SCT. + * This makes a copy of the log_id. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_log_id(SCT *sct, const unsigned char *log_id, + size_t log_id_len); + +/* + * Returns the timestamp for the SCT (epoch time in milliseconds). + */ +uint64_t SCT_get_timestamp(const SCT *sct); + +/* + * Set the timestamp of an SCT (epoch time in milliseconds). + */ +void SCT_set_timestamp(SCT *sct, uint64_t timestamp); + +/* + * Return the NID for the signature used by the SCT. + * For CT v1, this will be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256 (or NID_undef if incorrect/unset). + */ +int SCT_get_signature_nid(const SCT *sct); + +/* + * Set the signature type of an SCT + * For CT v1, this should be either NID_sha256WithRSAEncryption or + * NID_ecdsa_with_SHA256. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_signature_nid(SCT *sct, int nid); + +/* + * Set *ext to point to the extension data for the SCT. ext must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_extensions(const SCT *sct, unsigned char **ext); + +/* + * Set the extensions of an SCT to point directly to the *ext specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_extensions(SCT *sct, unsigned char *ext, size_t ext_len); + +/* + * Set the extensions of an SCT. + * This takes a copy of the ext. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_extensions(SCT *sct, const unsigned char *ext, + size_t ext_len); + +/* + * Set *sig to point to the signature for the SCT. sig must not be NULL. + * The SCT retains ownership of this pointer. + * Returns length of the data pointed to. + */ +size_t SCT_get0_signature(const SCT *sct, unsigned char **sig); + +/* + * Set the signature of an SCT to point directly to the *sig specified. + * The SCT takes ownership of the specified pointer. + */ +void SCT_set0_signature(SCT *sct, unsigned char *sig, size_t sig_len); + +/* + * Set the signature of an SCT to be a copy of the *sig specified. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set1_signature(SCT *sct, const unsigned char *sig, + size_t sig_len); + +/* + * The origin of this SCT, e.g. TLS extension, OCSP response, etc. + */ +sct_source_t SCT_get_source(const SCT *sct); + +/* + * Set the origin of this SCT, e.g. TLS extension, OCSP response, etc. + * Returns 1 on success, 0 otherwise. + */ +int SCT_set_source(SCT *sct, sct_source_t source); + +/* + * Returns a text string describing the validation status of |sct|. + */ +const char *SCT_validation_status_string(const SCT *sct); + +/* + * Pretty-prints an |sct| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * If |logs| is not NULL, it will be used to lookup the CT log that the SCT came + * from, so that the log name can be printed. + */ +void SCT_print(const SCT *sct, BIO *out, int indent, const CTLOG_STORE *logs); + +/* + * Pretty-prints an |sct_list| to |out|. + * It will be indented by the number of spaces specified by |indent|. + * SCTs will be delimited by |separator|. + * If |logs| is not NULL, it will be used to lookup the CT log that each SCT + * came from, so that the log names can be printed. + */ +void SCT_LIST_print(const STACK_OF(SCT) *sct_list, BIO *out, int indent, + const char *separator, const CTLOG_STORE *logs); + +/* + * Gets the last result of validating this SCT. + * If it has not been validated yet, returns SCT_VALIDATION_STATUS_NOT_SET. + */ +sct_validation_status_t SCT_get_validation_status(const SCT *sct); + +/* + * Validates the given SCT with the provided context. + * Sets the "validation_status" field of the SCT. + * Returns 1 if the SCT is valid and the signature verifies. + * Returns 0 if the SCT is invalid or could not be verified. + * Returns -1 if an error occurs. + */ +int SCT_validate(SCT *sct, const CT_POLICY_EVAL_CTX *ctx); + +/* + * Validates the given list of SCTs with the provided context. + * Sets the "validation_status" field of each SCT. + * Returns 1 if there are no invalid SCTs and all signatures verify. + * Returns 0 if at least one SCT is invalid or could not be verified. + * Returns a negative integer if an error occurs. + */ +int SCT_LIST_validate(const STACK_OF(SCT) *scts, + CT_POLICY_EVAL_CTX *ctx); + + +/********************************* + * SCT parsing and serialisation * + *********************************/ + +/* + * Serialize (to TLS format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just return the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +int i2o_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Convert TLS format SCT list to a stack of SCTs. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *o2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + size_t len); + +/* + * Serialize (to DER format) a stack of SCTs and return the length. + * "a" must not be NULL. + * If "pp" is NULL, just returns the length of what would have been serialized. + * If "pp" is not NULL and "*pp" is null, function will allocate a new pointer + * for data that caller is responsible for freeing (only if function returns + * successfully). + * If "pp" is NULL and "*pp" is not NULL, caller is responsible for ensuring + * that "*pp" is large enough to accept all of the serialized data. + * Returns < 0 on error, >= 0 indicating bytes written (or would have been) + * on success. + */ +int i2d_SCT_LIST(const STACK_OF(SCT) *a, unsigned char **pp); + +/* + * Parses an SCT list in DER format and returns it. + * If "a" or "*a" is NULL, a new stack will be created that the caller is + * responsible for freeing (by calling SCT_LIST_free). + * "**pp" and "*pp" must not be NULL. + * Upon success, "*pp" will point to after the last bytes read, and a stack + * will be returned. + * Upon failure, a NULL pointer will be returned, and the position of "*pp" is + * not defined. + */ +STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp, + long len); + +/* + * Serialize (to TLS format) an |sct| and write it to |out|. + * If |out| is null, no SCT will be output but the length will still be returned. + * If |out| points to a null pointer, a string will be allocated to hold the + * TLS-format SCT. It is the responsibility of the caller to free it. + * If |out| points to an allocated string, the TLS-format SCT will be written + * to it. + * The length of the SCT in TLS format will be returned. + */ +int i2o_SCT(const SCT *sct, unsigned char **out); + +/* + * Parses an SCT in TLS format and returns it. + * If |psct| is not null, it will end up pointing to the parsed SCT. If it + * already points to a non-null pointer, the pointer will be free'd. + * |in| should be a pointer to a string containing the TLS-format SCT. + * |in| will be advanced to the end of the SCT if parsing succeeds. + * |len| should be the length of the SCT in |in|. + * Returns NULL if an error occurs. + * If the SCT is an unsupported version, only the SCT's 'sct' and 'sct_len' + * fields will be populated (with |in| and |len| respectively). + */ +SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len); + +/******************** + * CT log functions * + ********************/ + +/* + * Creates a new CT log instance with the given |public_key| and |name|. + * Takes ownership of |public_key| but copies |name|. + * Returns NULL if malloc fails or if |public_key| cannot be converted to DER. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +CTLOG *CTLOG_new(EVP_PKEY *public_key, const char *name); + +/* + * Creates a new CTLOG instance with the base64-encoded SubjectPublicKeyInfo DER + * in |pkey_base64|. The |name| is a string to help users identify this log. + * Returns 1 on success, 0 on failure. + * Should be deleted by the caller using CTLOG_free when no longer needed. + */ +int CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64, + const char *name); + +/* + * Deletes a CT log instance and its fields. + */ +void CTLOG_free(CTLOG *log); + +/* Gets the name of the CT log */ +const char *CTLOG_get0_name(const CTLOG *log); +/* Gets the ID of the CT log */ +void CTLOG_get0_log_id(const CTLOG *log, const uint8_t **log_id, + size_t *log_id_len); +/* Gets the public key of the CT log */ +EVP_PKEY *CTLOG_get0_public_key(const CTLOG *log); + +/************************** + * CT log store functions * + **************************/ + +/* + * Creates a new CT log store. + * Should be deleted by the caller using CTLOG_STORE_free when no longer needed. + */ +CTLOG_STORE *CTLOG_STORE_new(void); + +/* + * Deletes a CT log store and all of the CT log instances held within. + */ +void CTLOG_STORE_free(CTLOG_STORE *store); + +/* + * Finds a CT log in the store based on its log ID. + * Returns the CT log, or NULL if no match is found. + */ +const CTLOG *CTLOG_STORE_get0_log_by_id(const CTLOG_STORE *store, + const uint8_t *log_id, size_t log_id_len); + +/* + * Loads a CT log list into a |store| from a |file|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +int CTLOG_STORE_load_file(CTLOG_STORE *store, const char *file); + +/* + * Loads the default CT log list into a |store|. + * Returns 1 if loading is successful, or 0 otherwise. + */ +int CTLOG_STORE_load_default_file(CTLOG_STORE *store); + +int ERR_load_CT_strings(void); + +/* + * CT function codes. + */ +# define CT_F_CTLOG_NEW 117 +# define CT_F_CTLOG_NEW_FROM_BASE64 118 +# define CT_F_CTLOG_NEW_FROM_CONF 119 +# define CT_F_CTLOG_STORE_LOAD_CTX_NEW 122 +# define CT_F_CTLOG_STORE_LOAD_FILE 123 +# define CT_F_CTLOG_STORE_LOAD_LOG 130 +# define CT_F_CTLOG_STORE_NEW 131 +# define CT_F_CT_BASE64_DECODE 124 +# define CT_F_CT_POLICY_EVAL_CTX_NEW 133 +# define CT_F_CT_V1_LOG_ID_FROM_PKEY 125 +# define CT_F_I2O_SCT 107 +# define CT_F_I2O_SCT_LIST 108 +# define CT_F_I2O_SCT_SIGNATURE 109 +# define CT_F_O2I_SCT 110 +# define CT_F_O2I_SCT_LIST 111 +# define CT_F_O2I_SCT_SIGNATURE 112 +# define CT_F_SCT_CTX_NEW 126 +# define CT_F_SCT_CTX_VERIFY 128 +# define CT_F_SCT_NEW 100 +# define CT_F_SCT_NEW_FROM_BASE64 127 +# define CT_F_SCT_SET0_LOG_ID 101 +# define CT_F_SCT_SET1_EXTENSIONS 114 +# define CT_F_SCT_SET1_LOG_ID 115 +# define CT_F_SCT_SET1_SIGNATURE 116 +# define CT_F_SCT_SET_LOG_ENTRY_TYPE 102 +# define CT_F_SCT_SET_SIGNATURE_NID 103 +# define CT_F_SCT_SET_VERSION 104 + +/* + * CT reason codes. + */ +# define CT_R_BASE64_DECODE_ERROR 108 +# define CT_R_INVALID_LOG_ID_LENGTH 100 +# define CT_R_LOG_CONF_INVALID 109 +# define CT_R_LOG_CONF_INVALID_KEY 110 +# define CT_R_LOG_CONF_MISSING_DESCRIPTION 111 +# define CT_R_LOG_CONF_MISSING_KEY 112 +# define CT_R_LOG_KEY_INVALID 113 +# define CT_R_SCT_FUTURE_TIMESTAMP 116 +# define CT_R_SCT_INVALID 104 +# define CT_R_SCT_INVALID_SIGNATURE 107 +# define CT_R_SCT_LIST_INVALID 105 +# define CT_R_SCT_LOG_ID_MISMATCH 114 +# define CT_R_SCT_NOT_SET 106 +# define CT_R_SCT_UNSUPPORTED_VERSION 115 +# define CT_R_UNRECOGNIZED_SIGNATURE_NID 101 +# define CT_R_UNSUPPORTED_ENTRY_TYPE 102 +# define CT_R_UNSUPPORTED_VERSION 103 + +#ifdef __cplusplus +} +#endif +#endif +#endif diff --git a/include/openssl/curve25519.h b/include/openssl/curve25519.h new file mode 100644 index 0000000..e42bc22 --- /dev/null +++ b/include/openssl/curve25519.h @@ -0,0 +1,104 @@ +/* $OpenBSD: curve25519.h,v 1.7 2022/11/13 14:05:04 tb Exp $ */ +/* + * Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_CURVE25519_H +#define HEADER_CURVE25519_H + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Curve25519. + * + * Curve25519 is an elliptic curve. See https://tools.ietf.org/html/rfc7748. + */ + +/* + * X25519. + * + * X25519 is the Diffie-Hellman primitive built from curve25519. It is + * sometimes referred to as curve25519, but X25519 is a more precise name. + * See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748. + */ + +#define X25519_KEY_LENGTH 32 + +/* + * X25519_keypair sets |out_public_value| and |out_private_key| to a freshly + * generated, public/private key pair. + */ +void X25519_keypair(uint8_t out_public_value[X25519_KEY_LENGTH], + uint8_t out_private_key[X25519_KEY_LENGTH]); + +/* + * X25519 writes a shared key to |out_shared_key| that is calculated from the + * given private key and the peer's public value. It returns one on success and + * zero on error. + * + * Don't use the shared key directly, rather use a KDF and also include the two + * public values as inputs. + */ +int X25519(uint8_t out_shared_key[X25519_KEY_LENGTH], + const uint8_t private_key[X25519_KEY_LENGTH], + const uint8_t peers_public_value[X25519_KEY_LENGTH]); + +/* + * ED25519 + * + * Ed25519 is a signature scheme using a twisted Edwards curve that is + * birationally equivalent to curve25519. + */ + +#define ED25519_PRIVATE_KEY_LENGTH 32 +#define ED25519_PUBLIC_KEY_LENGTH 32 +#define ED25519_SIGNATURE_LENGTH 64 + +/* + * ED25519_keypair sets |out_public_key| and |out_private_key| to a freshly + * generated, public/private key pair. + */ +void ED25519_keypair(uint8_t out_public_key[ED25519_PUBLIC_KEY_LENGTH], + uint8_t out_private_key[ED25519_PRIVATE_KEY_LENGTH]); + +/* + * ED25519_sign sets |out_sig| to be a signature of |message_len| bytes from + * |message| using |public_key| and |private_key|. It returns one on success + * or zero on allocation failure. + */ +int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH], + const uint8_t private_key_seed[ED25519_PRIVATE_KEY_LENGTH]); + +/* + * ED25519_verify returns one iff |signature| is a valid signature by + * |public_key| of |message_len| bytes from |message|. It returns zero + * otherwise. + */ +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[ED25519_SIGNATURE_LENGTH], + const uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]); + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* HEADER_CURVE25519_H */ diff --git a/include/openssl/des.h b/include/openssl/des.h new file mode 100644 index 0000000..bc5d35f --- /dev/null +++ b/include/openssl/des.h @@ -0,0 +1,215 @@ +/* $OpenBSD: des.h,v 1.21 2023/07/31 05:04:06 tb Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_NEW_DES_H +#define HEADER_NEW_DES_H + +#include + +#ifdef OPENSSL_NO_DES +#error DES is disabled. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned char DES_cblock[8]; +typedef /* const */ unsigned char const_DES_cblock[8]; +/* With "const", gcc 2.8.1 on Solaris thinks that DES_cblock * + * and const_DES_cblock * are incompatible pointer types. */ + +typedef struct DES_ks { + union { + DES_cblock cblock; + /* make sure things are correct size on machines with + * 8 byte longs */ + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + +#define DES_KEY_SZ (sizeof(DES_cblock)) +#define DES_SCHEDULE_SZ (sizeof(DES_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +#define DES_ecb2_encrypt(i,o,k1,k2,e) \ + DES_ecb3_encrypt((i),(o),(k1),(k2),(k1),(e)) + +#define DES_ede2_cbc_encrypt(i,o,l,k1,k2,iv,e) \ + DES_ede3_cbc_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(e)) + +#define DES_ede2_cfb64_encrypt(i,o,l,k1,k2,iv,n,e) \ + DES_ede3_cfb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n),(e)) + +#define DES_ede2_ofb64_encrypt(i,o,l,k1,k2,iv,n) \ + DES_ede3_ofb64_encrypt((i),(o),(l),(k1),(k2),(k1),(iv),(n)) + +extern int DES_check_key; /* defaults to false */ +extern int DES_rw_mode; /* defaults to DES_PCBC_MODE */ + +void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, int enc); +DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output, + long length, DES_key_schedule *schedule, + const_DES_cblock *ivec); +/* DES_cbc_encrypt does not update the IV! Use DES_ncbc_encrypt instead. */ +void DES_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, DES_cblock *ivec, + int enc); +void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, DES_cblock *ivec, + int enc); +void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, DES_cblock *ivec, + const_DES_cblock *inw, const_DES_cblock *outw, int enc); +void DES_cfb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, DES_cblock *ivec, + int enc); +void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output, + DES_key_schedule *ks, int enc); + +/* This is the DES encryption function that gets called by just about + every other DES routine in the library. You should not use this + function except to implement 'modes' of DES. I say this because the + functions that call this routine do the conversion from 'char *' to + long, and this needs to be done to make sure 'non-aligned' memory + access do not occur. The characters are loaded 'little endian'. + Data is a pointer to 2 unsigned long's and ks is the + DES_key_schedule to use. enc, is non zero specifies encryption, + zero if decryption. */ +void DES_encrypt1(DES_LONG *data, DES_key_schedule *ks, int enc); + +/* This functions is the same as DES_encrypt1() except that the DES + initial permutation (IP) and final permutation (FP) have been left + out. As for DES_encrypt1(), you should not use this function. + It is used by the routines in the library that implement triple DES. + IP() DES_encrypt2() DES_encrypt2() DES_encrypt2() FP() is the same + as DES_encrypt1() DES_encrypt1() DES_encrypt1() except faster :-). */ +void DES_encrypt2(DES_LONG *data, DES_key_schedule *ks, int enc); + +void DES_encrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_decrypt3(DES_LONG *data, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3); +void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, DES_cblock *ivec, int enc); +void DES_ede3_cbcm_encrypt(const unsigned char *in, unsigned char *out, + long length, + DES_key_schedule *ks1, DES_key_schedule *ks2, + DES_key_schedule *ks3, + DES_cblock *ivec1, DES_cblock *ivec2, + int enc); +void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num, int enc); +void DES_ede3_cfb_encrypt(const unsigned char *in, unsigned char *out, + int numbits, long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int enc); +void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, DES_key_schedule *ks1, + DES_key_schedule *ks2, DES_key_schedule *ks3, + DES_cblock *ivec, int *num); +int DES_enc_read(int fd, void *buf, int len, DES_key_schedule *sched, + DES_cblock *iv); +int DES_enc_write(int fd, const void *buf, int len, DES_key_schedule *sched, + DES_cblock *iv); +char *DES_fcrypt(const char *buf, const char *salt, char *ret); +char *DES_crypt(const char *buf, const char *salt); +void DES_ofb_encrypt(const unsigned char *in, unsigned char *out, int numbits, + long length, DES_key_schedule *schedule, DES_cblock *ivec); +void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output, + long length, DES_key_schedule *schedule, DES_cblock *ivec, + int enc); +DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[], + long length, int out_count, DES_cblock *seed); +int DES_random_key(DES_cblock *ret); +void DES_set_odd_parity(DES_cblock *key); +int DES_check_key_parity(const_DES_cblock *key); +int DES_is_weak_key(const_DES_cblock *key); +/* DES_set_key (= set_key = DES_key_sched = key_sched) calls + * DES_set_key_checked if global variable DES_check_key is set, + * DES_set_key_unchecked otherwise. */ +int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule); +int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule); +void DES_string_to_key(const char *str, DES_cblock *key); +void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2); +void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, + DES_key_schedule *schedule, DES_cblock *ivec, int *num, + int enc); +void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out, long length, + DES_key_schedule *schedule, DES_cblock *ivec, int *num); + +#define DES_fixup_key_parity DES_set_odd_parity + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/dh.h b/include/openssl/dh.h new file mode 100644 index 0000000..65b4348 --- /dev/null +++ b/include/openssl/dh.h @@ -0,0 +1,249 @@ +/* $OpenBSD: dh.h,v 1.37 2023/04/18 08:33:43 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_DH_H +#define HEADER_DH_H + +#include + +#ifdef OPENSSL_NO_DH +#error DH is disabled. +#endif + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include + +#ifndef OPENSSL_DH_MAX_MODULUS_BITS +# define OPENSSL_DH_MAX_MODULUS_BITS 10000 +#endif + +#define DH_FLAG_CACHE_MONT_P 0x01 + +/* If this flag is set the DH method is FIPS compliant and can be used + * in FIPS mode. This is set in the validated module method. If an + * application sets this flag in its own methods it is its reposibility + * to ensure the result is compliant. + */ + +#define DH_FLAG_FIPS_METHOD 0x0400 + +/* If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +#define DH_FLAG_NON_FIPS_ALLOW 0x0400 + +#ifdef __cplusplus +extern "C" { +#endif + +#define DH_GENERATOR_2 2 +/* #define DH_GENERATOR_3 3 */ +#define DH_GENERATOR_5 5 + +/* DH_check error codes */ +#define DH_CHECK_P_NOT_PRIME 0x01 +#define DH_CHECK_P_NOT_SAFE_PRIME 0x02 +#define DH_UNABLE_TO_CHECK_GENERATOR 0x04 +#define DH_NOT_SUITABLE_GENERATOR 0x08 +#define DH_CHECK_Q_NOT_PRIME 0x10 +#define DH_CHECK_INVALID_Q_VALUE 0x20 +#define DH_CHECK_INVALID_J_VALUE 0x40 + +/* DH_check_pub_key error codes */ +#define DH_CHECK_PUBKEY_TOO_SMALL 0x01 +#define DH_CHECK_PUBKEY_TOO_LARGE 0x02 +#define DH_CHECK_PUBKEY_INVALID 0x04 + +/* primes p where (p-1)/2 is prime too are called "safe"; we define + this for backward compatibility: */ +#define DH_CHECK_P_NOT_STRONG_PRIME DH_CHECK_P_NOT_SAFE_PRIME + +DH *d2i_DHparams_bio(BIO *bp, DH **a); +int i2d_DHparams_bio(BIO *bp, DH *a); +DH *d2i_DHparams_fp(FILE *fp, DH **a); +int i2d_DHparams_fp(FILE *fp, DH *a); + +DH *DHparams_dup(DH *); + +const DH_METHOD *DH_OpenSSL(void); + +void DH_set_default_method(const DH_METHOD *meth); +const DH_METHOD *DH_get_default_method(void); +int DH_set_method(DH *dh, const DH_METHOD *meth); +DH *DH_new_method(ENGINE *engine); + +DH * DH_new(void); +void DH_free(DH *dh); +int DH_up_ref(DH *dh); +int DH_size(const DH *dh); +int DH_bits(const DH *dh); +int DH_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DH_set_ex_data(DH *d, int idx, void *arg); +void *DH_get_ex_data(DH *d, int idx); +int DH_security_bits(const DH *dh); + +ENGINE *DH_get0_engine(DH *d); +void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DH_get0_p(const DH *dh); +const BIGNUM *DH_get0_q(const DH *dh); +const BIGNUM *DH_get0_g(const DH *dh); +const BIGNUM *DH_get0_priv_key(const DH *dh); +const BIGNUM *DH_get0_pub_key(const DH *dh); +void DH_clear_flags(DH *dh, int flags); +int DH_test_flags(const DH *dh, int flags); +void DH_set_flags(DH *dh, int flags); +long DH_get_length(const DH *dh); +int DH_set_length(DH *dh, long length); + +/* + * Wrapped in OPENSSL_NO_DEPRECATED in 0.9.8, added to rust-openssl in 2020, + * for "advanced DH support". + */ +DH * DH_generate_parameters(int prime_len,int generator, + void (*callback)(int,int,void *),void *cb_arg); + +/* New version */ +int DH_generate_parameters_ex(DH *dh, int prime_len,int generator, BN_GENCB *cb); + +int DH_check(const DH *dh,int *codes); +int DH_check_pub_key(const DH *dh,const BIGNUM *pub_key, int *codes); +int DH_generate_key(DH *dh); +int DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh); +DH * d2i_DHparams(DH **a,const unsigned char **pp, long length); +int i2d_DHparams(const DH *a,unsigned char **pp); +int DHparams_print_fp(FILE *fp, const DH *x); +#ifndef OPENSSL_NO_BIO +int DHparams_print(BIO *bp, const DH *x); +#else +int DHparams_print(char *bp, const DH *x); +#endif + +#define EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, len, NULL) + +#define EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, gen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DH, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, gen, NULL) + +#define EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR (EVP_PKEY_ALG_CTRL + 2) + + +void ERR_load_DH_strings(void); + +/* Error codes for the DH functions. */ + +/* Function codes. */ +#define DH_F_COMPUTE_KEY 102 +#define DH_F_DHPARAMS_PRINT_FP 101 +#define DH_F_DH_BUILTIN_GENPARAMS 106 +#define DH_F_DH_COMPUTE_KEY 114 +#define DH_F_DH_GENERATE_KEY 115 +#define DH_F_DH_GENERATE_PARAMETERS_EX 116 +#define DH_F_DH_NEW_METHOD 105 +#define DH_F_DH_PARAM_DECODE 107 +#define DH_F_DH_PRIV_DECODE 110 +#define DH_F_DH_PRIV_ENCODE 111 +#define DH_F_DH_PUB_DECODE 108 +#define DH_F_DH_PUB_ENCODE 109 +#define DH_F_DO_DH_PRINT 100 +#define DH_F_GENERATE_KEY 103 +#define DH_F_GENERATE_PARAMETERS 104 +#define DH_F_PKEY_DH_DERIVE 112 +#define DH_F_PKEY_DH_KEYGEN 113 + +/* Reason codes. */ +#define DH_R_BAD_GENERATOR 101 +#define DH_R_BN_DECODE_ERROR 109 +#define DH_R_BN_ERROR 106 +#define DH_R_DECODE_ERROR 104 +#define DH_R_INVALID_PUBKEY 102 +#define DH_R_KEYS_NOT_SET 108 +#define DH_R_KEY_SIZE_TOO_SMALL 110 +#define DH_R_MODULUS_TOO_LARGE 103 +#define DH_R_NON_FIPS_METHOD 111 +#define DH_R_NO_PARAMETERS_SET 107 +#define DH_R_NO_PRIVATE_VALUE 100 +#define DH_R_PARAMETER_ENCODING_ERROR 105 +#define DH_R_CHECK_INVALID_J_VALUE 115 +#define DH_R_CHECK_INVALID_Q_VALUE 116 +#define DH_R_CHECK_PUBKEY_INVALID 122 +#define DH_R_CHECK_PUBKEY_TOO_LARGE 123 +#define DH_R_CHECK_PUBKEY_TOO_SMALL 124 +#define DH_R_CHECK_P_NOT_PRIME 117 +#define DH_R_CHECK_P_NOT_SAFE_PRIME 118 +#define DH_R_CHECK_Q_NOT_PRIME 119 +#define DH_R_MISSING_PUBKEY 125 +#define DH_R_NOT_SUITABLE_GENERATOR 120 +#define DH_R_UNABLE_TO_CHECK_GENERATOR 121 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h new file mode 100644 index 0000000..8029e7f --- /dev/null +++ b/include/openssl/dsa.h @@ -0,0 +1,282 @@ +/* $OpenBSD: dsa.h,v 1.43 2023/04/18 08:47:28 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* + * The DSS routines are based on patches supplied by + * Steven Schoch . He basically did the + * work and I have just tweaked them a little to fit into my + * stylistic vision for SSLeay :-) */ + +#ifndef HEADER_DSA_H +#define HEADER_DSA_H + +#include + +#ifdef OPENSSL_NO_DSA +#error DSA is disabled. +#endif + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#ifndef OPENSSL_NO_DH +# include +#endif + +#include + +#ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +#endif + +#define DSA_FLAG_CACHE_MONT_P 0x01 + +/* If this flag is set the DSA method is FIPS compliant and can be used + * in FIPS mode. This is set in the validated module method. If an + * application sets this flag in its own methods it is its reposibility + * to ensure the result is compliant. + */ + +#define DSA_FLAG_FIPS_METHOD 0x0400 + +/* If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +#define DSA_FLAG_NON_FIPS_ALLOW 0x0400 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DSA_SIG_st DSA_SIG; + +DSA *d2i_DSAparams_bio(BIO *bp, DSA **a); +int i2d_DSAparams_bio(BIO *bp, DSA *a); +DSA *d2i_DSAparams_fp(FILE *fp, DSA **a); +int i2d_DSAparams_fp(FILE *fp, DSA *a); + +DSA *DSAparams_dup(DSA *x); +DSA_SIG * DSA_SIG_new(void); +void DSA_SIG_free(DSA_SIG *a); +int i2d_DSA_SIG(const DSA_SIG *a, unsigned char **pp); +DSA_SIG * d2i_DSA_SIG(DSA_SIG **v, const unsigned char **pp, long length); +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +DSA_SIG * DSA_do_sign(const unsigned char *dgst,int dlen,DSA *dsa); +int DSA_do_verify(const unsigned char *dgst,int dgst_len, + DSA_SIG *sig,DSA *dsa); + +const DSA_METHOD *DSA_OpenSSL(void); + +void DSA_set_default_method(const DSA_METHOD *); +const DSA_METHOD *DSA_get_default_method(void); +int DSA_set_method(DSA *dsa, const DSA_METHOD *); + +DSA * DSA_new(void); +DSA * DSA_new_method(ENGINE *engine); +void DSA_free(DSA *r); +/* "up" the DSA object's reference count */ +int DSA_up_ref(DSA *r); +int DSA_size(const DSA *); +int DSA_bits(const DSA *d); + /* next 4 return -1 on error */ +int DSA_sign_setup( DSA *dsa,BN_CTX *ctx_in,BIGNUM **kinvp,BIGNUM **rp); +int DSA_sign(int type,const unsigned char *dgst,int dlen, + unsigned char *sig, unsigned int *siglen, DSA *dsa); +int DSA_verify(int type,const unsigned char *dgst,int dgst_len, + const unsigned char *sigbuf, int siglen, DSA *dsa); +int DSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int DSA_set_ex_data(DSA *d, int idx, void *arg); +void *DSA_get_ex_data(DSA *d, int idx); +int DSA_security_bits(const DSA *d); + +DSA *d2i_DSAPublicKey(DSA **a, const unsigned char **pp, long length); +int i2d_DSAPublicKey(const DSA *a, unsigned char **pp); +extern const ASN1_ITEM DSAPublicKey_it; + +DSA *d2i_DSAPrivateKey(DSA **a, const unsigned char **pp, long length); +int i2d_DSAPrivateKey(const DSA *a, unsigned char **pp); +extern const ASN1_ITEM DSAPrivateKey_it; + +DSA *d2i_DSAparams(DSA **a, const unsigned char **pp, long length); +int i2d_DSAparams(const DSA *a,unsigned char **pp); +extern const ASN1_ITEM DSAparams_it; + +/* Wrapped in OPENSSL_NO_DEPRECATED in 0.9.8. Still used in 2023. */ +DSA * DSA_generate_parameters(int bits, + unsigned char *seed,int seed_len, + int *counter_ret, unsigned long *h_ret,void + (*callback)(int, int, void *),void *cb_arg); + +/* New version */ +int DSA_generate_parameters_ex(DSA *dsa, int bits, + const unsigned char *seed,int seed_len, + int *counter_ret, unsigned long *h_ret, BN_GENCB *cb); + +int DSA_generate_key(DSA *a); + +#ifndef OPENSSL_NO_BIO +int DSAparams_print(BIO *bp, const DSA *x); +int DSA_print(BIO *bp, const DSA *x, int off); +#endif +int DSAparams_print_fp(FILE *fp, const DSA *x); +int DSA_print_fp(FILE *bp, const DSA *x, int off); + +/* + * Primality test according to FIPS PUB 186-4, Appendix C.3. Set the number + * to 64 rounds of Miller-Rabin, which corresponds to 128 bits of security. + * This is necessary for keys of size >= 3072. + */ +#define DSS_prime_checks 64 +#define DSA_is_prime(n, callback, cb_arg) \ + BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg) + +#ifndef OPENSSL_NO_DH +/* Convert DSA structure (key or just parameters) into DH structure + * (be careful to avoid small subgroup attacks when using this!) */ +DH *DSA_dup_DH(const DSA *r); +#endif + +void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, + const BIGNUM **g); +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); +const BIGNUM *DSA_get0_p(const DSA *d); +const BIGNUM *DSA_get0_q(const DSA *d); +const BIGNUM *DSA_get0_g(const DSA *d); +const BIGNUM *DSA_get0_pub_key(const DSA *d); +const BIGNUM *DSA_get0_priv_key(const DSA *d); +void DSA_clear_flags(DSA *d, int flags); +int DSA_test_flags(const DSA *d, int flags); +void DSA_set_flags(DSA *d, int flags); +ENGINE *DSA_get0_engine(DSA *d); + +DSA_METHOD *DSA_meth_new(const char *name, int flags); +void DSA_meth_free(DSA_METHOD *meth); +DSA_METHOD *DSA_meth_dup(const DSA_METHOD *meth); +const char *DSA_meth_get0_name(const DSA_METHOD *meth); +int DSA_meth_set1_name(DSA_METHOD *meth, const char *name); +int DSA_meth_set_sign(DSA_METHOD *meth, + DSA_SIG *(*sign)(const unsigned char *, int, DSA *)); +int DSA_meth_set_finish(DSA_METHOD *meth, int (*finish)(DSA *)); + +#define EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN, \ + EVP_PKEY_CTRL_DSA_PARAMGEN_BITS, nbits, NULL) + +#define EVP_PKEY_CTRL_DSA_PARAMGEN_BITS (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS (EVP_PKEY_ALG_CTRL + 2) +#define EVP_PKEY_CTRL_DSA_PARAMGEN_MD (EVP_PKEY_ALG_CTRL + 3) + +void ERR_load_DSA_strings(void); + +/* Error codes for the DSA functions. */ + +/* Function codes. */ +#define DSA_F_D2I_DSA_SIG 110 +#define DSA_F_DO_DSA_PRINT 104 +#define DSA_F_DSAPARAMS_PRINT 100 +#define DSA_F_DSAPARAMS_PRINT_FP 101 +#define DSA_F_DSA_DO_SIGN 112 +#define DSA_F_DSA_DO_VERIFY 113 +#define DSA_F_DSA_GENERATE_KEY 124 +#define DSA_F_DSA_GENERATE_PARAMETERS_EX 123 +#define DSA_F_DSA_NEW_METHOD 103 +#define DSA_F_DSA_PARAM_DECODE 119 +#define DSA_F_DSA_PRINT_FP 105 +#define DSA_F_DSA_PRIV_DECODE 115 +#define DSA_F_DSA_PRIV_ENCODE 116 +#define DSA_F_DSA_PUB_DECODE 117 +#define DSA_F_DSA_PUB_ENCODE 118 +#define DSA_F_DSA_SIGN 106 +#define DSA_F_DSA_SIGN_SETUP 107 +#define DSA_F_DSA_SIG_NEW 109 +#define DSA_F_DSA_SIG_PRINT 125 +#define DSA_F_DSA_VERIFY 108 +#define DSA_F_I2D_DSA_SIG 111 +#define DSA_F_OLD_DSA_PRIV_DECODE 122 +#define DSA_F_PKEY_DSA_CTRL 120 +#define DSA_F_PKEY_DSA_KEYGEN 121 +#define DSA_F_SIG_CB 114 + +/* Reason codes. */ +#define DSA_R_BAD_Q_VALUE 102 +#define DSA_R_BN_DECODE_ERROR 108 +#define DSA_R_BN_ERROR 109 +#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100 +#define DSA_R_DECODE_ERROR 104 +#define DSA_R_INVALID_DIGEST_TYPE 106 +#define DSA_R_INVALID_PARAMETERS 112 +#define DSA_R_MISSING_PARAMETERS 101 +#define DSA_R_MODULUS_TOO_LARGE 103 +#define DSA_R_NEED_NEW_SETUP_VALUES 110 +#define DSA_R_NON_FIPS_DSA_METHOD 111 +#define DSA_R_NO_PARAMETERS_SET 107 +#define DSA_R_PARAMETER_ENCODING_ERROR 105 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/dtls1.h b/include/openssl/dtls1.h new file mode 100644 index 0000000..79542c8 --- /dev/null +++ b/include/openssl/dtls1.h @@ -0,0 +1,107 @@ +/* $OpenBSD: dtls1.h,v 1.27 2021/05/16 13:56:30 jsing Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DTLS1_H +#define HEADER_DTLS1_H + +#if defined(_WIN32) +#include +#else +#include +#endif + +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DTLS1_VERSION 0xFEFF +#define DTLS1_2_VERSION 0xFEFD +#define DTLS1_VERSION_MAJOR 0xFE + +/* lengths of messages */ +#define DTLS1_COOKIE_LENGTH 256 + +#define DTLS1_RT_HEADER_LENGTH 13 + +#define DTLS1_HM_HEADER_LENGTH 12 + +#define DTLS1_HM_BAD_FRAGMENT -2 +#define DTLS1_HM_FRAGMENT_RETRY -3 + +#define DTLS1_CCS_HEADER_LENGTH 1 + +#define DTLS1_AL_HEADER_LENGTH 2 + +/* Timeout multipliers (timeout slice is defined in apps/timeouts.h */ +#define DTLS1_TMO_READ_COUNT 2 +#define DTLS1_TMO_WRITE_COUNT 2 + +#define DTLS1_TMO_ALERT_COUNT 12 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ec.h b/include/openssl/ec.h new file mode 100644 index 0000000..9e3354d --- /dev/null +++ b/include/openssl/ec.h @@ -0,0 +1,722 @@ +/* $OpenBSD: ec.h,v 1.46 2023/08/11 04:45:27 tb Exp $ */ +/* + * Originally written by Bodo Moeller for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + */ + +#ifndef HEADER_EC_H +#define HEADER_EC_H + +#include + +#ifdef OPENSSL_NO_EC +#error EC is disabled. +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#elif defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (off,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +#endif + +#ifndef OPENSSL_ECC_MAX_FIELD_BITS +#define OPENSSL_ECC_MAX_FIELD_BITS 661 +#endif + +/* Elliptic point conversion form as per X9.62, page 4 and section 4.4.2. */ +typedef enum { + POINT_CONVERSION_COMPRESSED = 2, + POINT_CONVERSION_UNCOMPRESSED = 4, + POINT_CONVERSION_HYBRID = 6 +} point_conversion_form_t; + +typedef struct ec_method_st EC_METHOD; +typedef struct ec_group_st EC_GROUP; +typedef struct ec_point_st EC_POINT; + +const EC_METHOD *EC_GFp_simple_method(void); +const EC_METHOD *EC_GFp_mont_method(void); + +EC_GROUP *EC_GROUP_new(const EC_METHOD *meth); +void EC_GROUP_free(EC_GROUP *group); +#ifndef LIBRESSL_INTERNAL +void EC_GROUP_clear_free(EC_GROUP *group); +#endif + +int EC_GROUP_copy(EC_GROUP *dst, const EC_GROUP *src); +EC_GROUP *EC_GROUP_dup(const EC_GROUP *src); + +const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group); +int EC_METHOD_get_field_type(const EC_METHOD *meth); + +int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, + const BIGNUM *order, const BIGNUM *cofactor); +const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group); + +int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx); +int EC_GROUP_order_bits(const EC_GROUP *group); +int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx); + +void EC_GROUP_set_curve_name(EC_GROUP *group, int nid); +int EC_GROUP_get_curve_name(const EC_GROUP *group); + +void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag); +int EC_GROUP_get_asn1_flag(const EC_GROUP *group); + +void EC_GROUP_set_point_conversion_form(EC_GROUP *group, + point_conversion_form_t form); +point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *); + +unsigned char *EC_GROUP_get0_seed(const EC_GROUP *x); +size_t EC_GROUP_get_seed_len(const EC_GROUP *); +size_t EC_GROUP_set_seed(EC_GROUP *, const unsigned char *, size_t len); + +int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, + BN_CTX *ctx); + +#if !defined(LIBRESSL_INTERNAL) +int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx); +#endif + +int EC_GROUP_get_degree(const EC_GROUP *group); + +int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx); +int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx); + +/* Compare two EC_GROUPs. Returns 0 if both groups are equal, 1 otherwise. */ +int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx); + +EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); +EC_GROUP *EC_GROUP_new_by_curve_name(int nid); + +typedef struct { + int nid; + const char *comment; +} EC_builtin_curve; + +size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); + +const char *EC_curve_nid2nist(int nid); +int EC_curve_nist2nid(const char *name); + +EC_POINT *EC_POINT_new(const EC_GROUP *group); +void EC_POINT_free(EC_POINT *point); +#ifndef LIBRESSL_INTERNAL +void EC_POINT_clear_free(EC_POINT *point); +#endif +int EC_POINT_copy(EC_POINT *dst, const EC_POINT *src); +EC_POINT *EC_POINT_dup(const EC_POINT *src, const EC_GROUP *group); + +const EC_METHOD *EC_POINT_method_of(const EC_POINT *point); + +int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point); + +int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx); +int EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *p, + BIGNUM *x, BIGNUM *y, BN_CTX *ctx); +int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, int y_bit, BN_CTX *ctx); + +#ifndef LIBRESSL_INTERNAL +int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx); +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx); +int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx); +int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); +int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *p, + const BIGNUM *x, int y_bit, BN_CTX *ctx); +#endif /* !LIBRESSL_INTERNAL */ +size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *p, + point_conversion_form_t form, unsigned char *buf, size_t len, BN_CTX *ctx); +int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *p, + const unsigned char *buf, size_t len, BN_CTX *ctx); + +BIGNUM *EC_POINT_point2bn(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BIGNUM *, BN_CTX *); +EC_POINT *EC_POINT_bn2point(const EC_GROUP *, const BIGNUM *, EC_POINT *, + BN_CTX *); +char *EC_POINT_point2hex(const EC_GROUP *, const EC_POINT *, + point_conversion_form_t form, BN_CTX *); +EC_POINT *EC_POINT_hex2point(const EC_GROUP *, const char *, EC_POINT *, + BN_CTX *); + +int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + const EC_POINT *b, BN_CTX *ctx); +int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, + BN_CTX *ctx); +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 *p); +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx); +int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, + BN_CTX *ctx); + +int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx); +int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], + BN_CTX *ctx); +int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + size_t num, const EC_POINT *p[], const BIGNUM *m[], BN_CTX *ctx); +int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, + const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx); +int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx); +int EC_GROUP_have_precompute_mult(const EC_GROUP *group); + +int EC_GROUP_get_basis_type(const EC_GROUP *); + +#define OPENSSL_EC_EXPLICIT_CURVE 0x000 +#define OPENSSL_EC_NAMED_CURVE 0x001 + +typedef struct ecpk_parameters_st ECPKPARAMETERS; + +EC_GROUP *d2i_ECPKParameters(EC_GROUP **, const unsigned char **in, long len); +int i2d_ECPKParameters(const EC_GROUP *, unsigned char **out); + +#define d2i_ECPKParameters_bio(bp,x) ASN1_d2i_bio_of(EC_GROUP,NULL,d2i_ECPKParameters,bp,x) +#define i2d_ECPKParameters_bio(bp,x) ASN1_i2d_bio_of_const(EC_GROUP,i2d_ECPKParameters,bp,x) +#define d2i_ECPKParameters_fp(fp,x) (EC_GROUP *)ASN1_d2i_fp(NULL, \ + (char *(*)())d2i_ECPKParameters,(fp),(unsigned char **)(x)) +#define i2d_ECPKParameters_fp(fp,x) ASN1_i2d_fp(i2d_ECPKParameters,(fp), \ + (unsigned char *)(x)) + +#ifndef OPENSSL_NO_BIO +int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off); +#endif +int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off); + +#define EC_PKEY_NO_PARAMETERS 0x001 +#define EC_PKEY_NO_PUBKEY 0x002 + +#define EC_FLAG_NON_FIPS_ALLOW 0x1 +#define EC_FLAG_FIPS_CHECKED 0x2 +#define EC_FLAG_COFACTOR_ECDH 0x1000 + +EC_KEY *EC_KEY_new(void); +int EC_KEY_get_flags(const EC_KEY *key); +void EC_KEY_set_flags(EC_KEY *key, int flags); +void EC_KEY_clear_flags(EC_KEY *key, int flags); +EC_KEY *EC_KEY_new_by_curve_name(int nid); +void EC_KEY_free(EC_KEY *key); +EC_KEY *EC_KEY_copy(EC_KEY *dst, const EC_KEY *src); +EC_KEY *EC_KEY_dup(const EC_KEY *src); +int EC_KEY_up_ref(EC_KEY *key); + +const EC_GROUP *EC_KEY_get0_group(const EC_KEY *key); +int EC_KEY_set_group(EC_KEY *key, const EC_GROUP *group); +const BIGNUM *EC_KEY_get0_private_key(const EC_KEY *key); +int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *prv); +const EC_POINT *EC_KEY_get0_public_key(const EC_KEY *key); +int EC_KEY_set_public_key(EC_KEY *key, const EC_POINT *pub); + +unsigned EC_KEY_get_enc_flags(const EC_KEY *key); +void EC_KEY_set_enc_flags(EC_KEY *eckey, unsigned int flags); +point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key); +void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); + +void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); +int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx); +int EC_KEY_generate_key(EC_KEY *key); +int EC_KEY_check_key(const EC_KEY *key); +int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x, BIGNUM *y); + +EC_KEY *d2i_ECPrivateKey(EC_KEY **key, const unsigned char **in, long len); +int i2d_ECPrivateKey(EC_KEY *key, unsigned char **out); +EC_KEY *d2i_ECParameters(EC_KEY **key, const unsigned char **in, long len); +int i2d_ECParameters(EC_KEY *key, unsigned char **out); + +EC_KEY *o2i_ECPublicKey(EC_KEY **key, const unsigned char **in, long len); +int i2o_ECPublicKey(const EC_KEY *key, unsigned char **out); + +#ifndef OPENSSL_NO_BIO +int ECParameters_print(BIO *bp, const EC_KEY *key); +int EC_KEY_print(BIO *bp, const EC_KEY *key, int off); +#endif +int ECParameters_print_fp(FILE *fp, const EC_KEY *key); +int EC_KEY_print_fp(FILE *fp, const EC_KEY *key, int off); + +#define EC_KEY_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_EC_KEY, l, p, newf, dupf, freef) +int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg); +void *EC_KEY_get_ex_data(const EC_KEY *key, int idx); + +const EC_KEY_METHOD *EC_KEY_OpenSSL(void); +const EC_KEY_METHOD *EC_KEY_get_default_method(void); +void EC_KEY_set_default_method(const EC_KEY_METHOD *meth); +const EC_KEY_METHOD *EC_KEY_get_method(const EC_KEY *key); +int EC_KEY_set_method(EC_KEY *key, const EC_KEY_METHOD *meth); +EC_KEY *EC_KEY_new_method(ENGINE *engine); + +int ECDH_size(const EC_KEY *ecdh); +int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, + EC_KEY *ecdh, + void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen)); + +typedef struct ECDSA_SIG_st ECDSA_SIG; + +ECDSA_SIG *ECDSA_SIG_new(void); +void ECDSA_SIG_free(ECDSA_SIG *sig); +int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp); +ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len); + +const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig); +const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig); +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +int ECDSA_size(const EC_KEY *eckey); + +ECDSA_SIG *ECDSA_do_sign(const unsigned char *digest, int digest_len, + EC_KEY *eckey); +int ECDSA_do_verify(const unsigned char *digest, int digest_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +int ECDSA_sign(int type, const unsigned char *digest, int digest_len, + unsigned char *signature, unsigned int *signature_len, EC_KEY *eckey); +int ECDSA_verify(int type, const unsigned char *digest, int digest_len, + const unsigned char *signature, int signature_len, EC_KEY *eckey); + +EC_KEY_METHOD *EC_KEY_METHOD_new(const EC_KEY_METHOD *meth); +void EC_KEY_METHOD_free(EC_KEY_METHOD *meth); +void EC_KEY_METHOD_set_init(EC_KEY_METHOD *meth, + int (*init)(EC_KEY *key), + void (*finish)(EC_KEY *key), + int (*copy)(EC_KEY *dest, const EC_KEY *src), + int (*set_group)(EC_KEY *key, const EC_GROUP *grp), + int (*set_private)(EC_KEY *key, const BIGNUM *priv_key), + int (*set_public)(EC_KEY *key, const EC_POINT *pub_key)); +void EC_KEY_METHOD_set_keygen(EC_KEY_METHOD *meth, + int (*keygen)(EC_KEY *key)); +void EC_KEY_METHOD_set_compute_key(EC_KEY_METHOD *meth, + int (*ckey)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key, + const EC_KEY *ecdh)); +void EC_KEY_METHOD_set_sign(EC_KEY_METHOD *meth, + int (*sign)(int type, const unsigned char *digest, int digest_len, + unsigned char *signature, unsigned int *signature_len, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey), + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(*sign_sig)(const unsigned char *digest, int digest_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)); +void EC_KEY_METHOD_set_verify(EC_KEY_METHOD *meth, + int (*verify)(int type, const unsigned char *digest, int digest_len, + const unsigned char *signature, int signature_len, EC_KEY *eckey), + int (*verify_sig)(const unsigned char *digest, int digest_len, + const ECDSA_SIG *sig, EC_KEY *eckey)); +void EC_KEY_METHOD_get_init(const EC_KEY_METHOD *meth, + int (**pinit)(EC_KEY *key), + void (**pfinish)(EC_KEY *key), + int (**pcopy)(EC_KEY *dest, const EC_KEY *src), + int (**pset_group)(EC_KEY *key, const EC_GROUP *grp), + int (**pset_private)(EC_KEY *key, const BIGNUM *priv_key), + int (**pset_public)(EC_KEY *key, const EC_POINT *pub_key)); +void EC_KEY_METHOD_get_keygen(const EC_KEY_METHOD *meth, + int (**pkeygen)(EC_KEY *key)); +void EC_KEY_METHOD_get_compute_key(const EC_KEY_METHOD *meth, + int (**pck)(unsigned char **out, size_t *out_len, const EC_POINT *pub_key, + const EC_KEY *ecdh)); +void EC_KEY_METHOD_get_sign(const EC_KEY_METHOD *meth, + int (**psign)(int type, const unsigned char *digest, int digest_len, + unsigned char *signature, unsigned int *signature_len, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey), + int (**psign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp), + ECDSA_SIG *(**psign_sig)(const unsigned char *digest, int digest_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)); +void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + int (**pverify)(int type, const unsigned char *digest, int digest_len, + const unsigned char *signature, int signature_len, EC_KEY *eckey), + int (**pverify_sig)(const unsigned char *digest, int digest_len, + const ECDSA_SIG *sig, EC_KEY *eckey)); + +EC_KEY *ECParameters_dup(EC_KEY *key); + +#ifndef __cplusplus +#if defined(__SUNPRO_C) +# if __SUNPRO_C >= 0x520 +# pragma error_messages (default,E_ARRAY_OF_INCOMPLETE_NONAME,E_ARRAY_OF_INCOMPLETE) +# endif +# endif +#endif + +#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL) + +#define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL) + +#define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL) + +#define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL) + +#define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL) + +#define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL) + +#define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md)) + +#define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd)) + +#define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL) + +#define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \ + (void *)(plen)) + +#define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p)) + +#define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \ + EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p)) + +/* SM2 will skip the operation check so no need to pass operation here */ +#define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) + +#define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) + +#define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len)) + +#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2) +#define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3) +#define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4) +#define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5) +#define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6) +#define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7) +#define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8) +#define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9) +#define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10) +#define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11) +#define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12) +#define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13) + +/* KDF types */ +#define EVP_PKEY_ECDH_KDF_NONE 1 +#define EVP_PKEY_ECDH_KDF_X9_63 2 + +void ERR_load_EC_strings(void); + +/* Error codes for the EC functions. */ + +/* Function codes. */ +#define EC_F_BN_TO_FELEM 224 +#define EC_F_COMPUTE_WNAF 143 +#define EC_F_D2I_ECPARAMETERS 144 +#define EC_F_D2I_ECPKPARAMETERS 145 +#define EC_F_D2I_ECPRIVATEKEY 146 +#define EC_F_DO_EC_KEY_PRINT 221 +#define EC_F_ECKEY_PARAM2TYPE 223 +#define EC_F_ECKEY_PARAM_DECODE 212 +#define EC_F_ECKEY_PRIV_DECODE 213 +#define EC_F_ECKEY_PRIV_ENCODE 214 +#define EC_F_ECKEY_PUB_DECODE 215 +#define EC_F_ECKEY_PUB_ENCODE 216 +#define EC_F_ECKEY_TYPE2PARAM 220 +#define EC_F_ECPARAMETERS_PRINT 147 +#define EC_F_ECPARAMETERS_PRINT_FP 148 +#define EC_F_ECPKPARAMETERS_PRINT 149 +#define EC_F_ECPKPARAMETERS_PRINT_FP 150 +#define EC_F_ECP_NIST_MOD_192 203 +#define EC_F_ECP_NIST_MOD_224 204 +#define EC_F_ECP_NIST_MOD_256 205 +#define EC_F_ECP_NIST_MOD_521 206 +#define EC_F_ECP_NISTZ256_GET_AFFINE 240 +#define EC_F_ECP_NISTZ256_MULT_PRECOMPUTE 243 +#define EC_F_ECP_NISTZ256_POINTS_MUL 241 +#define EC_F_ECP_NISTZ256_PRE_COMP_NEW 244 +#define EC_F_ECP_NISTZ256_SET_WORDS 245 +#define EC_F_ECP_NISTZ256_WINDOWED_MUL 242 +#define EC_F_EC_ASN1_GROUP2CURVE 153 +#define EC_F_EC_ASN1_GROUP2FIELDID 154 +#define EC_F_EC_ASN1_GROUP2PARAMETERS 155 +#define EC_F_EC_ASN1_GROUP2PKPARAMETERS 156 +#define EC_F_EC_ASN1_PARAMETERS2GROUP 157 +#define EC_F_EC_ASN1_PKPARAMETERS2GROUP 158 +#define EC_F_EC_EX_DATA_SET_DATA 211 +#define EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY 208 +#define EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT 159 +#define EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE 195 +#define EC_F_EC_GF2M_SIMPLE_OCT2POINT 160 +#define EC_F_EC_GF2M_SIMPLE_POINT2OCT 161 +#define EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES 162 +#define EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES 163 +#define EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES 164 +#define EC_F_EC_GFP_MONT_FIELD_DECODE 133 +#define EC_F_EC_GFP_MONT_FIELD_ENCODE 134 +#define EC_F_EC_GFP_MONT_FIELD_MUL 131 +#define EC_F_EC_GFP_MONT_FIELD_SET_TO_ONE 209 +#define EC_F_EC_GFP_MONT_FIELD_SQR 132 +#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE 189 +#define EC_F_EC_GFP_MONT_GROUP_SET_CURVE_GFP 135 +#define EC_F_EC_GFP_NISTP224_GROUP_SET_CURVE 225 +#define EC_F_EC_GFP_NISTP224_POINTS_MUL 228 +#define EC_F_EC_GFP_NISTP224_POINT_GET_AFFINE_COORDINATES 226 +#define EC_F_EC_GFP_NISTP256_GROUP_SET_CURVE 230 +#define EC_F_EC_GFP_NISTP256_POINTS_MUL 231 +#define EC_F_EC_GFP_NISTP256_POINT_GET_AFFINE_COORDINATES 232 +#define EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE 233 +#define EC_F_EC_GFP_NISTP521_POINTS_MUL 234 +#define EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES 235 +#define EC_F_EC_GFP_NIST_FIELD_MUL 200 +#define EC_F_EC_GFP_NIST_FIELD_SQR 201 +#define EC_F_EC_GFP_NIST_GROUP_SET_CURVE 202 +#define EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT 165 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE 166 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE_GFP 100 +#define EC_F_EC_GFP_SIMPLE_GROUP_SET_GENERATOR 101 +#define EC_F_EC_GFP_SIMPLE_MAKE_AFFINE 102 +#define EC_F_EC_GFP_SIMPLE_OCT2POINT 103 +#define EC_F_EC_GFP_SIMPLE_POINT2OCT 104 +#define EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE 137 +#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES 167 +#define EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES_GFP 105 +#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES 168 +#define EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES_GFP 128 +#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES 169 +#define EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES_GFP 129 +#define EC_F_EC_GROUP_CHECK 170 +#define EC_F_EC_GROUP_CHECK_DISCRIMINANT 171 +#define EC_F_EC_GROUP_COPY 106 +#define EC_F_EC_GROUP_GET0_GENERATOR 139 +#define EC_F_EC_GROUP_GET_COFACTOR 140 +#define EC_F_EC_GROUP_GET_CURVE_GF2M 172 +#define EC_F_EC_GROUP_GET_CURVE_GFP 130 +#define EC_F_EC_GROUP_GET_DEGREE 173 +#define EC_F_EC_GROUP_GET_ORDER 141 +#define EC_F_EC_GROUP_GET_PENTANOMIAL_BASIS 193 +#define EC_F_EC_GROUP_GET_TRINOMIAL_BASIS 194 +#define EC_F_EC_GROUP_NEW 108 +#define EC_F_EC_GROUP_NEW_BY_CURVE_NAME 174 +#define EC_F_EC_GROUP_NEW_FROM_DATA 175 +#define EC_F_EC_GROUP_PRECOMPUTE_MULT 142 +#define EC_F_EC_GROUP_SET_CURVE_GF2M 176 +#define EC_F_EC_GROUP_SET_CURVE_GFP 109 +#define EC_F_EC_GROUP_SET_EXTRA_DATA 110 +#define EC_F_EC_GROUP_SET_GENERATOR 111 +#define EC_F_EC_KEY_CHECK_KEY 177 +#define EC_F_EC_KEY_COPY 178 +#define EC_F_EC_KEY_GENERATE_KEY 179 +#define EC_F_EC_KEY_NEW 182 +#define EC_F_EC_KEY_PRINT 180 +#define EC_F_EC_KEY_PRINT_FP 181 +#define EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 229 +#define EC_F_EC_POINTS_MAKE_AFFINE 136 +#define EC_F_EC_POINT_ADD 112 +#define EC_F_EC_POINT_CMP 113 +#define EC_F_EC_POINT_COPY 114 +#define EC_F_EC_POINT_DBL 115 +#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M 183 +#define EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP 116 +#define EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP 117 +#define EC_F_EC_POINT_INVERT 210 +#define EC_F_EC_POINT_IS_AT_INFINITY 118 +#define EC_F_EC_POINT_IS_ON_CURVE 119 +#define EC_F_EC_POINT_MAKE_AFFINE 120 +#define EC_F_EC_POINT_MUL 184 +#define EC_F_EC_POINT_NEW 121 +#define EC_F_EC_POINT_OCT2POINT 122 +#define EC_F_EC_POINT_POINT2OCT 123 +#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M 185 +#define EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP 124 +#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M 186 +#define EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP 125 +#define EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP 126 +#define EC_F_EC_POINT_SET_TO_INFINITY 127 +#define EC_F_EC_PRE_COMP_DUP 207 +#define EC_F_EC_PRE_COMP_NEW 196 +#define EC_F_EC_WNAF_MUL 187 +#define EC_F_EC_WNAF_PRECOMPUTE_MULT 188 +#define EC_F_I2D_ECPARAMETERS 190 +#define EC_F_I2D_ECPKPARAMETERS 191 +#define EC_F_I2D_ECPRIVATEKEY 192 +#define EC_F_I2O_ECPUBLICKEY 151 +#define EC_F_NISTP224_PRE_COMP_NEW 227 +#define EC_F_NISTP256_PRE_COMP_NEW 236 +#define EC_F_NISTP521_PRE_COMP_NEW 237 +#define EC_F_O2I_ECPUBLICKEY 152 +#define EC_F_OLD_EC_PRIV_DECODE 222 +#define EC_F_PKEY_EC_CTRL 197 +#define EC_F_PKEY_EC_CTRL_STR 198 +#define EC_F_PKEY_EC_DERIVE 217 +#define EC_F_PKEY_EC_KEYGEN 199 +#define EC_F_PKEY_EC_PARAMGEN 219 +#define EC_F_PKEY_EC_SIGN 218 + +/* Reason codes. */ +#define EC_R_ASN1_ERROR 115 +#define EC_R_ASN1_UNKNOWN_FIELD 116 +#define EC_R_BAD_SIGNATURE 166 +#define EC_R_BIGNUM_OUT_OF_RANGE 144 +#define EC_R_BUFFER_TOO_SMALL 100 +#define EC_R_COORDINATES_OUT_OF_RANGE 146 +#define EC_R_D2I_ECPKPARAMETERS_FAILURE 117 +#define EC_R_DECODE_ERROR 142 +#define EC_R_DISCRIMINANT_IS_ZERO 118 +#define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 +#define EC_R_FIELD_TOO_LARGE 143 +#define EC_R_GF2M_NOT_SUPPORTED 147 +#define EC_R_GROUP2PKPARAMETERS_FAILURE 120 +#define EC_R_I2D_ECPKPARAMETERS_FAILURE 121 +#define EC_R_INCOMPATIBLE_OBJECTS 101 +#define EC_R_INVALID_ARGUMENT 112 +#define EC_R_INVALID_COMPRESSED_POINT 110 +#define EC_R_INVALID_COMPRESSION_BIT 109 +#define EC_R_INVALID_CURVE 141 +#define EC_R_INVALID_DIGEST 151 +#define EC_R_INVALID_DIGEST_TYPE 138 +#define EC_R_INVALID_ENCODING 102 +#define EC_R_INVALID_FIELD 103 +#define EC_R_INVALID_FORM 104 +#define EC_R_INVALID_GROUP_ORDER 122 +#define EC_R_INVALID_KEY 165 +#define EC_R_INVALID_OUTPUT_LENGTH 171 +#define EC_R_INVALID_PEER_KEY 152 +#define EC_R_INVALID_PENTANOMIAL_BASIS 132 +#define EC_R_INVALID_PRIVATE_KEY 123 +#define EC_R_INVALID_TRINOMIAL_BASIS 137 +#define EC_R_KDF_FAILED 167 +#define EC_R_KDF_PARAMETER_ERROR 148 +#define EC_R_KEY_TRUNCATION 168 +#define EC_R_KEYS_NOT_SET 140 +#define EC_R_MISSING_PARAMETERS 124 +#define EC_R_MISSING_PRIVATE_KEY 125 +#define EC_R_NEED_NEW_SETUP_VALUES 170 +#define EC_R_NOT_A_NIST_PRIME 135 +#define EC_R_NOT_A_SUPPORTED_NIST_PRIME 136 +#define EC_R_NOT_IMPLEMENTED 126 +#define EC_R_NOT_INITIALIZED 111 +#define EC_R_NO_FIELD_MOD 133 +#define EC_R_NO_PARAMETERS_SET 139 +#define EC_R_PASSED_NULL_PARAMETER 134 +#define EC_R_PEER_KEY_ERROR 149 +#define EC_R_PKPARAMETERS2GROUP_FAILURE 127 +#define EC_R_POINT_AT_INFINITY 106 +#define EC_R_POINT_ARITHMETIC_FAILURE 169 +#define EC_R_POINT_IS_NOT_ON_CURVE 107 +#define EC_R_SHARED_INFO_ERROR 150 +#define EC_R_SLOT_FULL 108 +#define EC_R_UNDEFINED_GENERATOR 113 +#define EC_R_UNDEFINED_ORDER 128 +#define EC_R_UNKNOWN_COFACTOR 164 +#define EC_R_UNKNOWN_GROUP 129 +#define EC_R_UNKNOWN_ORDER 114 +#define EC_R_UNSUPPORTED_FIELD 131 +#define EC_R_WRONG_CURVE_PARAMETERS 145 +#define EC_R_WRONG_ORDER 130 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ecdh.h b/include/openssl/ecdh.h new file mode 100644 index 0000000..0149d5c --- /dev/null +++ b/include/openssl/ecdh.h @@ -0,0 +1,6 @@ +/* $OpenBSD: ecdh.h,v 1.10 2023/07/28 09:25:12 tb Exp $ */ +/* + * Public domain. + */ + +#include diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h new file mode 100644 index 0000000..9f498eb --- /dev/null +++ b/include/openssl/ecdsa.h @@ -0,0 +1,6 @@ +/* $OpenBSD: ecdsa.h,v 1.20 2023/07/28 09:16:17 tb Exp $ */ +/* + * Public domain. + */ + +#include diff --git a/include/openssl/engine.h b/include/openssl/engine.h new file mode 100644 index 0000000..1e04b61 --- /dev/null +++ b/include/openssl/engine.h @@ -0,0 +1,817 @@ +/* $OpenBSD: engine.h,v 1.42 2023/08/04 05:44:51 tb Exp $ */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_ENGINE_H +#define HEADER_ENGINE_H + +#include + +#include +#ifndef OPENSSL_NO_DH +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_EC +#include +#endif +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* These flags are used to control combinations of algorithm (methods) + * by bitwise "OR"ing. */ +#define ENGINE_METHOD_RSA (unsigned int)0x0001 +#define ENGINE_METHOD_DSA (unsigned int)0x0002 +#define ENGINE_METHOD_DH (unsigned int)0x0004 +#define ENGINE_METHOD_RAND (unsigned int)0x0008 +#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040 +#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080 +#define ENGINE_METHOD_STORE (unsigned int)0x0100 +#define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200 +#define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400 +#define ENGINE_METHOD_EC (unsigned int)0x0800 +/* Obvious all-or-nothing cases. */ +#define ENGINE_METHOD_ALL (unsigned int)0xFFFF +#define ENGINE_METHOD_NONE (unsigned int)0x0000 + +/* This(ese) flag(s) controls behaviour of the ENGINE_TABLE mechanism used + * internally to control registration of ENGINE implementations, and can be set + * by ENGINE_set_table_flags(). The "NOINIT" flag prevents attempts to + * initialise registered ENGINEs if they are not already initialised. */ +#define ENGINE_TABLE_FLAG_NOINIT (unsigned int)0x0001 + +/* ENGINE flags that can be set by ENGINE_set_flags(). */ +/* #define ENGINE_FLAGS_MALLOCED 0x0001 */ /* Not used */ + +/* This flag is for ENGINEs that wish to handle the various 'CMD'-related + * control commands on their own. Without this flag, ENGINE_ctrl() handles these + * control commands on behalf of the ENGINE using their "cmd_defns" data. */ +#define ENGINE_FLAGS_MANUAL_CMD_CTRL (int)0x0002 + +/* This flag is for ENGINEs who return new duplicate structures when found via + * "ENGINE_by_id()". When an ENGINE must store state (eg. if ENGINE_ctrl() + * commands are called in sequence as part of some stateful process like + * key-generation setup and execution), it can set this flag - then each attempt + * to obtain the ENGINE will result in it being copied into a new structure. + * Normally, ENGINEs don't declare this flag so ENGINE_by_id() just increments + * the existing ENGINE's structural reference count. */ +#define ENGINE_FLAGS_BY_ID_COPY (int)0x0004 + +/* This flag if for an ENGINE that does not want its methods registered as + * part of ENGINE_register_all_complete() for example if the methods are + * not usable as default methods. + */ + +#define ENGINE_FLAGS_NO_REGISTER_ALL (int)0x0008 + +/* ENGINEs can support their own command types, and these flags are used in + * ENGINE_CTRL_GET_CMD_FLAGS to indicate to the caller what kind of input each + * command expects. Currently only numeric and string input is supported. If a + * control command supports none of the _NUMERIC, _STRING, or _NO_INPUT options, + * then it is regarded as an "internal" control command - and not for use in + * config setting situations. As such, they're not available to the + * ENGINE_ctrl_cmd_string() function, only raw ENGINE_ctrl() access. Changes to + * this list of 'command types' should be reflected carefully in + * ENGINE_cmd_is_executable() and ENGINE_ctrl_cmd_string(). */ + +/* accepts a 'long' input value (3rd parameter to ENGINE_ctrl) */ +#define ENGINE_CMD_FLAG_NUMERIC (unsigned int)0x0001 +/* accepts string input (cast from 'void*' to 'const char *', 4th parameter to + * ENGINE_ctrl) */ +#define ENGINE_CMD_FLAG_STRING (unsigned int)0x0002 +/* Indicates that the control command takes *no* input. Ie. the control command + * is unparameterised. */ +#define ENGINE_CMD_FLAG_NO_INPUT (unsigned int)0x0004 +/* Indicates that the control command is internal. This control command won't + * be shown in any output, and is only usable through the ENGINE_ctrl_cmd() + * function. */ +#define ENGINE_CMD_FLAG_INTERNAL (unsigned int)0x0008 + +/* NB: These 3 control commands are deprecated and should not be used. ENGINEs + * relying on these commands should compile conditional support for + * compatibility (eg. if these symbols are defined) but should also migrate the + * same functionality to their own ENGINE-specific control functions that can be + * "discovered" by calling applications. The fact these control commands + * wouldn't be "executable" (ie. usable by text-based config) doesn't change the + * fact that application code can find and use them without requiring per-ENGINE + * hacking. */ + +/* These flags are used to tell the ctrl function what should be done. + * All command numbers are shared between all engines, even if some don't + * make sense to some engines. In such a case, they do nothing but return + * the error ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED. */ +#define ENGINE_CTRL_SET_LOGSTREAM 1 +#define ENGINE_CTRL_SET_PASSWORD_CALLBACK 2 +#define ENGINE_CTRL_HUP 3 /* Close and reinitialise any + handles/connections etc. */ +#define ENGINE_CTRL_SET_USER_INTERFACE 4 /* Alternative to callback */ +#define ENGINE_CTRL_SET_CALLBACK_DATA 5 /* User-specific data, used + when calling the password + callback and the user + interface */ +#define ENGINE_CTRL_LOAD_CONFIGURATION 6 /* Load a configuration, given + a string that represents a + file name or so */ +#define ENGINE_CTRL_LOAD_SECTION 7 /* Load data from a given + section in the already loaded + configuration */ + +/* These control commands allow an application to deal with an arbitrary engine + * in a dynamic way. Warn: Negative return values indicate errors FOR THESE + * COMMANDS because zero is used to indicate 'end-of-list'. Other commands, + * including ENGINE-specific command types, return zero for an error. + * + * An ENGINE can choose to implement these ctrl functions, and can internally + * manage things however it chooses - it does so by setting the + * ENGINE_FLAGS_MANUAL_CMD_CTRL flag (using ENGINE_set_flags()). Otherwise the + * ENGINE_ctrl() code handles this on the ENGINE's behalf using the cmd_defns + * data (set using ENGINE_set_cmd_defns()). This means an ENGINE's ctrl() + * handler need only implement its own commands - the above "meta" commands will + * be taken care of. */ + +/* Returns non-zero if the supplied ENGINE has a ctrl() handler. If "not", then + * all the remaining control commands will return failure, so it is worth + * checking this first if the caller is trying to "discover" the engine's + * capabilities and doesn't want errors generated unnecessarily. */ +#define ENGINE_CTRL_HAS_CTRL_FUNCTION 10 +/* Returns a positive command number for the first command supported by the + * engine. Returns zero if no ctrl commands are supported. */ +#define ENGINE_CTRL_GET_FIRST_CMD_TYPE 11 +/* The 'long' argument specifies a command implemented by the engine, and the + * return value is the next command supported, or zero if there are no more. */ +#define ENGINE_CTRL_GET_NEXT_CMD_TYPE 12 +/* The 'void*' argument is a command name (cast from 'const char *'), and the + * return value is the command that corresponds to it. */ +#define ENGINE_CTRL_GET_CMD_FROM_NAME 13 +/* The next two allow a command to be converted into its corresponding string + * form. In each case, the 'long' argument supplies the command. In the NAME_LEN + * case, the return value is the length of the command name (not counting a + * trailing EOL). In the NAME case, the 'void*' argument must be a string buffer + * large enough, and it will be populated with the name of the command (WITH a + * trailing EOL). */ +#define ENGINE_CTRL_GET_NAME_LEN_FROM_CMD 14 +#define ENGINE_CTRL_GET_NAME_FROM_CMD 15 +/* The next two are similar but give a "short description" of a command. */ +#define ENGINE_CTRL_GET_DESC_LEN_FROM_CMD 16 +#define ENGINE_CTRL_GET_DESC_FROM_CMD 17 +/* With this command, the return value is the OR'd combination of + * ENGINE_CMD_FLAG_*** values that indicate what kind of input a given + * engine-specific ctrl command expects. */ +#define ENGINE_CTRL_GET_CMD_FLAGS 18 + +/* ENGINE implementations should start the numbering of their own control + * commands from this value. (ie. ENGINE_CMD_BASE, ENGINE_CMD_BASE + 1, etc). */ +#define ENGINE_CMD_BASE 200 + +/* + * Prototypes for the stub functions in engine_stubs.c. They are provided to + * build M2Crypto, Dovecot, apr-utils without patching. All the other garbage + * can hopefully go away soon. + */ +#ifdef OPENSSL_NO_ENGINE +void ENGINE_load_builtin_engines(void); +void ENGINE_load_dynamic(void); +void ENGINE_load_openssl(void); +int ENGINE_register_all_complete(void); + +void ENGINE_cleanup(void); + +ENGINE *ENGINE_new(void); +int ENGINE_free(ENGINE *engine); +int ENGINE_init(ENGINE *engine); +int ENGINE_finish(ENGINE *engine); + +ENGINE *ENGINE_by_id(const char *id); +const char *ENGINE_get_id(const ENGINE *engine); +const char *ENGINE_get_name(const ENGINE *engine); + +int ENGINE_set_default(ENGINE *engine, unsigned int flags); + +ENGINE *ENGINE_get_default_RSA(void); +int ENGINE_set_default_RSA(ENGINE *engine); + +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, long i, void *p, + void (*f)(void), int cmd_optional); +int ENGINE_ctrl_cmd_string(ENGINE *engine, const char *cmd, const char *arg, + int cmd_optional); + +EVP_PKEY *ENGINE_load_private_key(ENGINE *engine, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *ENGINE_load_public_key(ENGINE *engine, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +#else +/* If an ENGINE supports its own specific control commands and wishes the + * framework to handle the above 'ENGINE_CMD_***'-manipulation commands on its + * behalf, it should supply a null-terminated array of ENGINE_CMD_DEFN entries + * to ENGINE_set_cmd_defns(). It should also implement a ctrl() handler that + * supports the stated commands (ie. the "cmd_num" entries as described by the + * array). NB: The array must be ordered in increasing order of cmd_num. + * "null-terminated" means that the last ENGINE_CMD_DEFN element has cmd_num set + * to zero and/or cmd_name set to NULL. */ +typedef struct ENGINE_CMD_DEFN_st { + unsigned int cmd_num; /* The command number */ + const char *cmd_name; /* The command name itself */ + const char *cmd_desc; /* A short description of the command */ + unsigned int cmd_flags; /* The input the command expects */ +} ENGINE_CMD_DEFN; + +/* Generic function pointer */ +typedef int (*ENGINE_GEN_FUNC_PTR)(void); +/* Generic function pointer taking no arguments */ +typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *); +/* Specific control function pointer */ +typedef int (*ENGINE_CTRL_FUNC_PTR)(ENGINE *, int, long, void *, + void (*f)(void)); +/* Generic load_key function pointer */ +typedef EVP_PKEY * (*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, + UI_METHOD *ui_method, void *callback_data); +typedef int (*ENGINE_SSL_CLIENT_CERT_PTR)(ENGINE *, SSL *ssl, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey, + STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data); + +/* These callback types are for an ENGINE's handler for cipher and digest logic. + * These handlers have these prototypes; + * int foo(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid); + * int foo(ENGINE *e, const EVP_MD **digest, const int **nids, int nid); + * Looking at how to implement these handlers in the case of cipher support, if + * the framework wants the EVP_CIPHER for 'nid', it will call; + * foo(e, &p_evp_cipher, NULL, nid); (return zero for failure) + * If the framework wants a list of supported 'nid's, it will call; + * foo(e, NULL, &p_nids, 0); (returns number of 'nids' or -1 for error) + */ +/* Returns to a pointer to the array of supported cipher 'nid's. If the second + * parameter is non-NULL it is set to the size of the returned array. */ +typedef int (*ENGINE_CIPHERS_PTR)(ENGINE *, const EVP_CIPHER **, + const int **, int); +typedef int (*ENGINE_DIGESTS_PTR)(ENGINE *, const EVP_MD **, const int **, int); +typedef int (*ENGINE_PKEY_METHS_PTR)(ENGINE *, EVP_PKEY_METHOD **, + const int **, int); +typedef int (*ENGINE_PKEY_ASN1_METHS_PTR)(ENGINE *, EVP_PKEY_ASN1_METHOD **, + const int **, int); + +/* STRUCTURE functions ... all of these functions deal with pointers to ENGINE + * structures where the pointers have a "structural reference". This means that + * their reference is to allowed access to the structure but it does not imply + * that the structure is functional. To simply increment or decrement the + * structural reference count, use ENGINE_by_id and ENGINE_free. NB: This is not + * required when iterating using ENGINE_get_next as it will automatically + * decrement the structural reference count of the "current" ENGINE and + * increment the structural reference count of the ENGINE it returns (unless it + * is NULL). */ + +/* Get the first/last "ENGINE" type available. */ +ENGINE *ENGINE_get_first(void); +ENGINE *ENGINE_get_last(void); +/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */ +ENGINE *ENGINE_get_next(ENGINE *e); +ENGINE *ENGINE_get_prev(ENGINE *e); +/* Add another "ENGINE" type into the array. */ +int ENGINE_add(ENGINE *e); +/* Remove an existing "ENGINE" type from the array. */ +int ENGINE_remove(ENGINE *e); +/* Retrieve an engine from the list by its unique "id" value. */ +ENGINE *ENGINE_by_id(const char *id); +/* Add all the built-in engines. */ +void ENGINE_load_openssl(void); +void ENGINE_load_dynamic(void); +#ifndef OPENSSL_NO_STATIC_ENGINE +void ENGINE_load_padlock(void); +#endif +void ENGINE_load_builtin_engines(void); + +/* Get and set global flags (ENGINE_TABLE_FLAG_***) for the implementation + * "registry" handling. */ +unsigned int ENGINE_get_table_flags(void); +void ENGINE_set_table_flags(unsigned int flags); + +/* Manage registration of ENGINEs per "table". For each type, there are 3 + * functions; + * ENGINE_register_***(e) - registers the implementation from 'e' (if it has one) + * ENGINE_unregister_***(e) - unregister the implementation from 'e' + * ENGINE_register_all_***() - call ENGINE_register_***() for each 'e' in the list + * Cleanup is automatically registered from each table when required, so + * ENGINE_cleanup() will reverse any "register" operations. */ + +int ENGINE_register_RSA(ENGINE *e); +void ENGINE_unregister_RSA(ENGINE *e); +void ENGINE_register_all_RSA(void); + +int ENGINE_register_DSA(ENGINE *e); +void ENGINE_unregister_DSA(ENGINE *e); +void ENGINE_register_all_DSA(void); + +int ENGINE_register_EC(ENGINE *e); +void ENGINE_unregister_EC(ENGINE *e); +void ENGINE_register_all_EC(void); + +int ENGINE_register_DH(ENGINE *e); +void ENGINE_unregister_DH(ENGINE *e); +void ENGINE_register_all_DH(void); + +int ENGINE_register_RAND(ENGINE *e); +void ENGINE_unregister_RAND(ENGINE *e); +void ENGINE_register_all_RAND(void); + +int ENGINE_register_STORE(ENGINE *e); +void ENGINE_unregister_STORE(ENGINE *e); +void ENGINE_register_all_STORE(void); + +int ENGINE_register_ciphers(ENGINE *e); +void ENGINE_unregister_ciphers(ENGINE *e); +void ENGINE_register_all_ciphers(void); + +int ENGINE_register_digests(ENGINE *e); +void ENGINE_unregister_digests(ENGINE *e); +void ENGINE_register_all_digests(void); + +int ENGINE_register_pkey_meths(ENGINE *e); +void ENGINE_unregister_pkey_meths(ENGINE *e); +void ENGINE_register_all_pkey_meths(void); + +int ENGINE_register_pkey_asn1_meths(ENGINE *e); +void ENGINE_unregister_pkey_asn1_meths(ENGINE *e); +void ENGINE_register_all_pkey_asn1_meths(void); + +/* These functions register all support from the above categories. Note, use of + * these functions can result in static linkage of code your application may not + * need. If you only need a subset of functionality, consider using more + * selective initialisation. */ +int ENGINE_register_complete(ENGINE *e); +int ENGINE_register_all_complete(void); + +/* Send parametrised control commands to the engine. The possibilities to send + * down an integer, a pointer to data or a function pointer are provided. Any of + * the parameters may or may not be NULL, depending on the command number. In + * actuality, this function only requires a structural (rather than functional) + * reference to an engine, but many control commands may require the engine be + * functional. The caller should be aware of trying commands that require an + * operational ENGINE, and only use functional references in such situations. */ +int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); + +/* This function tests if an ENGINE-specific command is usable as a "setting". + * Eg. in an application's config file that gets processed through + * ENGINE_ctrl_cmd_string(). If this returns zero, it is not available to + * ENGINE_ctrl_cmd_string(), only ENGINE_ctrl(). */ +int ENGINE_cmd_is_executable(ENGINE *e, int cmd); + +/* This function works like ENGINE_ctrl() with the exception of taking a + * command name instead of a command number, and can handle optional commands. + * See the comment on ENGINE_ctrl_cmd_string() for an explanation on how to + * use the cmd_name and cmd_optional. */ +int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, + long i, void *p, void (*f)(void), int cmd_optional); + +/* This function passes a command-name and argument to an ENGINE. The cmd_name + * is converted to a command number and the control command is called using + * 'arg' as an argument (unless the ENGINE doesn't support such a command, in + * which case no control command is called). The command is checked for input + * flags, and if necessary the argument will be converted to a numeric value. If + * cmd_optional is non-zero, then if the ENGINE doesn't support the given + * cmd_name the return value will be success anyway. This function is intended + * for applications to use so that users (or config files) can supply + * engine-specific config data to the ENGINE at run-time to control behaviour of + * specific engines. As such, it shouldn't be used for calling ENGINE_ctrl() + * functions that return data, deal with binary data, or that are otherwise + * supposed to be used directly through ENGINE_ctrl() in application code. Any + * "return" data from an ENGINE_ctrl() operation in this function will be lost - + * the return value is interpreted as failure if the return value is zero, + * success otherwise, and this function returns a boolean value as a result. In + * other words, vendors of 'ENGINE'-enabled devices should write ENGINE + * implementations with parameterisations that work in this scheme, so that + * compliant ENGINE-based applications can work consistently with the same + * configuration for the same ENGINE-enabled devices, across applications. */ +int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, + int cmd_optional); + +/* These functions are useful for manufacturing new ENGINE structures. They + * don't address reference counting at all - one uses them to populate an ENGINE + * structure with personalised implementations of things prior to using it + * directly or adding it to the builtin ENGINE list in OpenSSL. These are also + * here so that the ENGINE structure doesn't have to be exposed and break binary + * compatibility! */ +ENGINE *ENGINE_new(void); +int ENGINE_free(ENGINE *e); +int ENGINE_up_ref(ENGINE *e); +int ENGINE_set_id(ENGINE *e, const char *id); +int ENGINE_set_name(ENGINE *e, const char *name); +int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth); +int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth); +int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ec_meth); +int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth); +int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth); +int ENGINE_set_STORE(ENGINE *e, const STORE_METHOD *store_meth); +int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f); +int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f); +int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f); +int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f); +int ENGINE_set_load_privkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpriv_f); +int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f); +int ENGINE_set_load_ssl_client_cert_function(ENGINE *e, + ENGINE_SSL_CLIENT_CERT_PTR loadssl_f); +int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f); +int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f); +int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f); +int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f); +int ENGINE_set_flags(ENGINE *e, int flags); +int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns); +/* These functions allow control over any per-structure ENGINE data. */ +int ENGINE_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg); +void *ENGINE_get_ex_data(const ENGINE *e, int idx); + +/* This function cleans up anything that needs it. Eg. the ENGINE_add() function + * automatically ensures the list cleanup function is registered to be called + * from ENGINE_cleanup(). Similarly, all ENGINE_register_*** functions ensure + * ENGINE_cleanup() will clean up after them. */ +void ENGINE_cleanup(void); + +/* These return values from within the ENGINE structure. These can be useful + * with functional references as well as structural references - it depends + * which you obtained. Using the result for functional purposes if you only + * obtained a structural reference may be problematic! */ +const char *ENGINE_get_id(const ENGINE *e); +const char *ENGINE_get_name(const ENGINE *e); +const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e); +const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e); +const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e); +const DH_METHOD *ENGINE_get_DH(const ENGINE *e); +const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e); +const STORE_METHOD *ENGINE_get_STORE(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e); +ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e); +ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e); +ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e); +ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE *e); +ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e); +ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e); +ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e); +ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e); +const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid); +const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid); +const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid); +const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e, + const char *str, int len); +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, int len); +const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e); +int ENGINE_get_flags(const ENGINE *e); + +/* FUNCTIONAL functions. These functions deal with ENGINE structures + * that have (or will) be initialised for use. Broadly speaking, the + * structural functions are useful for iterating the list of available + * engine types, creating new engine types, and other "list" operations. + * These functions actually deal with ENGINEs that are to be used. As + * such these functions can fail (if applicable) when particular + * engines are unavailable - eg. if a hardware accelerator is not + * attached or not functioning correctly. Each ENGINE has 2 reference + * counts; structural and functional. Every time a functional reference + * is obtained or released, a corresponding structural reference is + * automatically obtained or released too. */ + +/* Initialise a engine type for use (or up its reference count if it's + * already in use). This will fail if the engine is not currently + * operational and cannot initialise. */ +int ENGINE_init(ENGINE *e); +/* Free a functional reference to a engine type. This does not require + * a corresponding call to ENGINE_free as it also releases a structural + * reference. */ +int ENGINE_finish(ENGINE *e); + +/* The following functions handle keys that are stored in some secondary + * location, handled by the engine. The storage may be on a card or + * whatever. */ +EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, + UI_METHOD *ui_method, void *callback_data); +int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s, + STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **ppkey, + STACK_OF(X509) **pother, + UI_METHOD *ui_method, void *callback_data); + +/* This returns a pointer for the current ENGINE structure that + * is (by default) performing any RSA operations. The value returned + * is an incremented reference, so it should be free'd (ENGINE_finish) + * before it is discarded. */ +ENGINE *ENGINE_get_default_RSA(void); +/* Same for the other "methods" */ +ENGINE *ENGINE_get_default_DSA(void); +ENGINE *ENGINE_get_default_EC(void); +ENGINE *ENGINE_get_default_DH(void); +ENGINE *ENGINE_get_default_RAND(void); +/* These functions can be used to get a functional reference to perform + * ciphering or digesting corresponding to "nid". */ +ENGINE *ENGINE_get_cipher_engine(int nid); +ENGINE *ENGINE_get_digest_engine(int nid); +ENGINE *ENGINE_get_pkey_meth_engine(int nid); +ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid); + +/* This sets a new default ENGINE structure for performing RSA + * operations. If the result is non-zero (success) then the ENGINE + * structure will have had its reference count up'd so the caller + * should still free their own reference 'e'. */ +int ENGINE_set_default_RSA(ENGINE *e); +int ENGINE_set_default_string(ENGINE *e, const char *def_list); +/* Same for the other "methods" */ +int ENGINE_set_default_DSA(ENGINE *e); +int ENGINE_set_default_EC(ENGINE *e); +int ENGINE_set_default_DH(ENGINE *e); +int ENGINE_set_default_RAND(ENGINE *e); +int ENGINE_set_default_ciphers(ENGINE *e); +int ENGINE_set_default_digests(ENGINE *e); +int ENGINE_set_default_pkey_meths(ENGINE *e); +int ENGINE_set_default_pkey_asn1_meths(ENGINE *e); + +/* The combination "set" - the flags are bitwise "OR"d from the + * ENGINE_METHOD_*** defines above. As with the "ENGINE_register_complete()" + * function, this function can result in unnecessary static linkage. If your + * application requires only specific functionality, consider using more + * selective functions. */ +int ENGINE_set_default(ENGINE *e, unsigned int flags); + +void ENGINE_add_conf_module(void); + +/* Deprecated functions ... */ +/* int ENGINE_clear_defaults(void); */ + +/**************************/ +/* DYNAMIC ENGINE SUPPORT */ +/**************************/ + +/* Binary/behaviour compatibility levels */ +#define OSSL_DYNAMIC_VERSION (unsigned long)0x00020000 +/* Binary versions older than this are too old for us (whether we're a loader or + * a loadee) */ +#define OSSL_DYNAMIC_OLDEST (unsigned long)0x00020000 + +/* When compiling an ENGINE entirely as an external shared library, loadable by + * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure + * type provides the calling application's (or library's) error functionality + * and memory management function pointers to the loaded library. These should + * be used/set in the loaded library code so that the loading application's + * 'state' will be used/changed in all operations. The 'static_state' pointer + * allows the loaded library to know if it shares the same static data as the + * calling application (or library), and thus whether these callbacks need to be + * set or not. */ +typedef void *(*dyn_MEM_malloc_cb)(size_t); +typedef void *(*dyn_MEM_realloc_cb)(void *, size_t); +typedef void (*dyn_MEM_free_cb)(void *); +typedef struct st_dynamic_MEM_fns { + dyn_MEM_malloc_cb malloc_cb; + dyn_MEM_realloc_cb realloc_cb; + dyn_MEM_free_cb free_cb; +} dynamic_MEM_fns; +/* FIXME: Perhaps the memory and locking code (crypto.h) should declare and use + * these types so we (and any other dependent code) can simplify a bit?? */ +typedef void (*dyn_lock_locking_cb)(int, int, const char *, int); +typedef int (*dyn_lock_add_lock_cb)(int*, int, int, const char *, int); +typedef struct CRYPTO_dynlock_value *(*dyn_dynlock_create_cb)( + const char *, int); +typedef void (*dyn_dynlock_lock_cb)(int, struct CRYPTO_dynlock_value *, + const char *, int); +typedef void (*dyn_dynlock_destroy_cb)(struct CRYPTO_dynlock_value *, + const char *, int); +typedef struct st_dynamic_LOCK_fns { + dyn_lock_locking_cb lock_locking_cb; + dyn_lock_add_lock_cb lock_add_lock_cb; + dyn_dynlock_create_cb dynlock_create_cb; + dyn_dynlock_lock_cb dynlock_lock_cb; + dyn_dynlock_destroy_cb dynlock_destroy_cb; +} dynamic_LOCK_fns; +/* The top-level structure */ +typedef struct st_dynamic_fns { + void *static_state; + const ERR_FNS *err_fns; + const CRYPTO_EX_DATA_IMPL *ex_data_fns; + dynamic_MEM_fns mem_fns; + dynamic_LOCK_fns lock_fns; +} dynamic_fns; + +/* The version checking function should be of this prototype. NB: The + * ossl_version value passed in is the OSSL_DYNAMIC_VERSION of the loading code. + * If this function returns zero, it indicates a (potential) version + * incompatibility and the loaded library doesn't believe it can proceed. + * Otherwise, the returned value is the (latest) version supported by the + * loading library. The loader may still decide that the loaded code's version + * is unsatisfactory and could veto the load. The function is expected to + * be implemented with the symbol name "v_check", and a default implementation + * can be fully instantiated with IMPLEMENT_DYNAMIC_CHECK_FN(). */ +typedef unsigned long (*dynamic_v_check_fn)(unsigned long ossl_version); +#define IMPLEMENT_DYNAMIC_CHECK_FN() \ + extern unsigned long v_check(unsigned long v); \ + extern unsigned long v_check(unsigned long v) { \ + if(v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \ + return 0; } + +/* This function is passed the ENGINE structure to initialise with its own + * function and command settings. It should not adjust the structural or + * functional reference counts. If this function returns zero, (a) the load will + * be aborted, (b) the previous ENGINE state will be memcpy'd back onto the + * structure, and (c) the shared library will be unloaded. So implementations + * should do their own internal cleanup in failure circumstances otherwise they + * could leak. The 'id' parameter, if non-NULL, represents the ENGINE id that + * the loader is looking for. If this is NULL, the shared library can choose to + * return failure or to initialise a 'default' ENGINE. If non-NULL, the shared + * library must initialise only an ENGINE matching the passed 'id'. The function + * is expected to be implemented with the symbol name "bind_engine". A standard + * implementation can be instantiated with IMPLEMENT_DYNAMIC_BIND_FN(fn) where + * the parameter 'fn' is a callback function that populates the ENGINE structure + * and returns an int value (zero for failure). 'fn' should have prototype; + * [static] int fn(ENGINE *e, const char *id); */ +typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id, + const dynamic_fns *fns); +#define IMPLEMENT_DYNAMIC_BIND_FN(fn) \ + extern \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \ + extern \ + int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \ + if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \ + if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \ + fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \ + return 0; \ + if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \ + return 0; \ + if(!ERR_set_implementation(fns->err_fns)) return 0; \ + skip_cbs: \ + if(!fn(e,id)) return 0; \ + return 1; } + +/* If the loading application (or library) and the loaded ENGINE library share + * the same static data (eg. they're both dynamically linked to the same + * libcrypto.so) we need a way to avoid trying to set system callbacks - this + * would fail, and for the same reason that it's unnecessary to try. If the + * loaded ENGINE has (or gets from through the loader) its own copy of the + * libcrypto static data, we will need to set the callbacks. The easiest way to + * detect this is to have a function that returns a pointer to some static data + * and let the loading application and loaded ENGINE compare their respective + * values. */ + void *ENGINE_get_static_state(void); + +void ERR_load_ENGINE_strings(void); +#endif + +/* Error codes for the ENGINE functions. */ + +/* Function codes. */ +#define ENGINE_F_DYNAMIC_CTRL 180 +#define ENGINE_F_DYNAMIC_GET_DATA_CTX 181 +#define ENGINE_F_DYNAMIC_LOAD 182 +#define ENGINE_F_DYNAMIC_SET_DATA_CTX 183 +#define ENGINE_F_ENGINE_ADD 105 +#define ENGINE_F_ENGINE_BY_ID 106 +#define ENGINE_F_ENGINE_CMD_IS_EXECUTABLE 170 +#define ENGINE_F_ENGINE_CTRL 142 +#define ENGINE_F_ENGINE_CTRL_CMD 178 +#define ENGINE_F_ENGINE_CTRL_CMD_STRING 171 +#define ENGINE_F_ENGINE_FINISH 107 +#define ENGINE_F_ENGINE_FREE_UTIL 108 +#define ENGINE_F_ENGINE_GET_CIPHER 185 +#define ENGINE_F_ENGINE_GET_DEFAULT_TYPE 177 +#define ENGINE_F_ENGINE_GET_DIGEST 186 +#define ENGINE_F_ENGINE_GET_NEXT 115 +#define ENGINE_F_ENGINE_GET_PKEY_ASN1_METH 193 +#define ENGINE_F_ENGINE_GET_PKEY_METH 192 +#define ENGINE_F_ENGINE_GET_PREV 116 +#define ENGINE_F_ENGINE_INIT 119 +#define ENGINE_F_ENGINE_LIST_ADD 120 +#define ENGINE_F_ENGINE_LIST_REMOVE 121 +#define ENGINE_F_ENGINE_LOAD_PRIVATE_KEY 150 +#define ENGINE_F_ENGINE_LOAD_PUBLIC_KEY 151 +#define ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT 194 +#define ENGINE_F_ENGINE_NEW 122 +#define ENGINE_F_ENGINE_REMOVE 123 +#define ENGINE_F_ENGINE_SET_DEFAULT_STRING 189 +#define ENGINE_F_ENGINE_SET_DEFAULT_TYPE 126 +#define ENGINE_F_ENGINE_SET_ID 129 +#define ENGINE_F_ENGINE_SET_NAME 130 +#define ENGINE_F_ENGINE_TABLE_REGISTER 184 +#define ENGINE_F_ENGINE_UNLOAD_KEY 152 +#define ENGINE_F_ENGINE_UNLOCKED_FINISH 191 +#define ENGINE_F_ENGINE_UP_REF 190 +#define ENGINE_F_INT_CTRL_HELPER 172 +#define ENGINE_F_INT_ENGINE_CONFIGURE 188 +#define ENGINE_F_INT_ENGINE_MODULE_INIT 187 +#define ENGINE_F_LOG_MESSAGE 141 + +/* Reason codes. */ +#define ENGINE_R_ALREADY_LOADED 100 +#define ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER 133 +#define ENGINE_R_CMD_NOT_EXECUTABLE 134 +#define ENGINE_R_COMMAND_TAKES_INPUT 135 +#define ENGINE_R_COMMAND_TAKES_NO_INPUT 136 +#define ENGINE_R_CONFLICTING_ENGINE_ID 103 +#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 +#define ENGINE_R_DH_NOT_IMPLEMENTED 139 +#define ENGINE_R_DSA_NOT_IMPLEMENTED 140 +#define ENGINE_R_DSO_FAILURE 104 +#define ENGINE_R_DSO_NOT_FOUND 132 +#define ENGINE_R_ENGINES_SECTION_ERROR 148 +#define ENGINE_R_ENGINE_CONFIGURATION_ERROR 102 +#define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 +#define ENGINE_R_ENGINE_SECTION_ERROR 149 +#define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 +#define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 +#define ENGINE_R_FINISH_FAILED 106 +#define ENGINE_R_GET_HANDLE_FAILED 107 +#define ENGINE_R_ID_OR_NAME_MISSING 108 +#define ENGINE_R_INIT_FAILED 109 +#define ENGINE_R_INTERNAL_LIST_ERROR 110 +#define ENGINE_R_INVALID_ARGUMENT 143 +#define ENGINE_R_INVALID_CMD_NAME 137 +#define ENGINE_R_INVALID_CMD_NUMBER 138 +#define ENGINE_R_INVALID_INIT_VALUE 151 +#define ENGINE_R_INVALID_STRING 150 +#define ENGINE_R_NOT_INITIALISED 117 +#define ENGINE_R_NOT_LOADED 112 +#define ENGINE_R_NO_CONTROL_FUNCTION 120 +#define ENGINE_R_NO_INDEX 144 +#define ENGINE_R_NO_LOAD_FUNCTION 125 +#define ENGINE_R_NO_REFERENCE 130 +#define ENGINE_R_NO_SUCH_ENGINE 116 +#define ENGINE_R_NO_UNLOAD_FUNCTION 126 +#define ENGINE_R_PROVIDE_PARAMETERS 113 +#define ENGINE_R_RSA_NOT_IMPLEMENTED 141 +#define ENGINE_R_UNIMPLEMENTED_CIPHER 146 +#define ENGINE_R_UNIMPLEMENTED_DIGEST 147 +#define ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD 101 +#define ENGINE_R_VERSION_INCOMPATIBILITY 145 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/err.h b/include/openssl/err.h new file mode 100644 index 0000000..d85de24 --- /dev/null +++ b/include/openssl/err.h @@ -0,0 +1,411 @@ +/* $OpenBSD: err.h,v 1.31 2023/07/28 10:23:19 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_ERR_H +#define HEADER_ERR_H + +#include + +#include +#include + +#include +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_LHASH +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef OPENSSL_NO_ERR +#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e) +#else +#define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0) +#endif + +#include + +#define ERR_TXT_MALLOCED 0x01 +#define ERR_TXT_STRING 0x02 + +#define ERR_FLAG_MARK 0x01 + +#define ERR_NUM_ERRORS 16 +typedef struct err_state_st { + CRYPTO_THREADID tid; + int err_flags[ERR_NUM_ERRORS]; + unsigned long err_buffer[ERR_NUM_ERRORS]; + char *err_data[ERR_NUM_ERRORS]; + int err_data_flags[ERR_NUM_ERRORS]; + const char *err_file[ERR_NUM_ERRORS]; + int err_line[ERR_NUM_ERRORS]; + int top, bottom; +} ERR_STATE; + +/* library */ +#define ERR_LIB_NONE 1 +#define ERR_LIB_SYS 2 +#define ERR_LIB_BN 3 +#define ERR_LIB_RSA 4 +#define ERR_LIB_DH 5 +#define ERR_LIB_EVP 6 +#define ERR_LIB_BUF 7 +#define ERR_LIB_OBJ 8 +#define ERR_LIB_PEM 9 +#define ERR_LIB_DSA 10 +#define ERR_LIB_X509 11 +/* #define ERR_LIB_METH 12 */ +#define ERR_LIB_ASN1 13 +#define ERR_LIB_CONF 14 +#define ERR_LIB_CRYPTO 15 +#define ERR_LIB_EC 16 +#define ERR_LIB_SSL 20 +/* #define ERR_LIB_SSL23 21 */ +/* #define ERR_LIB_SSL2 22 */ +/* #define ERR_LIB_SSL3 23 */ +/* #define ERR_LIB_RSAREF 30 */ +/* #define ERR_LIB_PROXY 31 */ +#define ERR_LIB_BIO 32 +#define ERR_LIB_PKCS7 33 +#define ERR_LIB_X509V3 34 +#define ERR_LIB_PKCS12 35 +#define ERR_LIB_RAND 36 +#define ERR_LIB_DSO 37 +#define ERR_LIB_ENGINE 38 +#define ERR_LIB_OCSP 39 +#define ERR_LIB_UI 40 +#define ERR_LIB_COMP 41 +#define ERR_LIB_ECDSA 42 +#define ERR_LIB_ECDH 43 +#define ERR_LIB_STORE 44 +#define ERR_LIB_FIPS 45 +#define ERR_LIB_CMS 46 +#define ERR_LIB_TS 47 +#define ERR_LIB_HMAC 48 +#define ERR_LIB_JPAKE 49 +#define ERR_LIB_GOST 50 +#define ERR_LIB_CT 51 +#define ERR_LIB_KDF 52 + +#define ERR_LIB_USER 128 + +#ifndef LIBRESSL_INTERNAL +#define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),__FILE__,__LINE__) +#define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),__FILE__,__LINE__) +#define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),__FILE__,__LINE__) +#define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),__FILE__,__LINE__) +#define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),__FILE__,__LINE__) +#define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),__FILE__,__LINE__) +#define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),__FILE__,__LINE__) +#define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),__FILE__,__LINE__) +#define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),__FILE__,__LINE__) +#define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),__FILE__,__LINE__) +#define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),__FILE__,__LINE__) +#define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),__FILE__,__LINE__) +#define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),__FILE__,__LINE__) +#define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),__FILE__,__LINE__) +#define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),__FILE__,__LINE__) +#define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),__FILE__,__LINE__) +#define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),__FILE__,__LINE__) +#define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),__FILE__,__LINE__) +#define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),__FILE__,__LINE__) +#define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),__FILE__,__LINE__) +#define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),__FILE__,__LINE__) +#define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),__FILE__,__LINE__) +#define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),__FILE__,__LINE__) +#define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),__FILE__,__LINE__) +#define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),__FILE__,__LINE__) +#define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),__FILE__,__LINE__) +#define STOREerr(f,r) ERR_PUT_error(ERR_LIB_STORE,(f),(r),__FILE__,__LINE__) +#define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),__FILE__,__LINE__) +#define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),__FILE__,__LINE__) +#define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),__FILE__,__LINE__) +#define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),__FILE__,__LINE__) +#define JPAKEerr(f,r) ERR_PUT_error(ERR_LIB_JPAKE,(f),(r),__FILE__,__LINE__) +#define GOSTerr(f,r) ERR_PUT_error(ERR_LIB_GOST,(f),(r),__FILE__,__LINE__) +#define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),__FILE__,__LINE__) +#define CTerr(f, r) ERR_PUT_error(ERR_LIB_CT,(f),(r),__FILE__,__LINE__) +#define KDFerr(f, r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),__FILE__,__LINE__) +#endif + +#ifdef LIBRESSL_INTERNAL +#define SYSerror(r) ERR_PUT_error(ERR_LIB_SYS,(0xfff),(r),__FILE__,__LINE__) +#define BNerror(r) ERR_PUT_error(ERR_LIB_BN,(0xfff),(r),__FILE__,__LINE__) +#define RSAerror(r) ERR_PUT_error(ERR_LIB_RSA,(0xfff),(r),__FILE__,__LINE__) +#define DHerror(r) ERR_PUT_error(ERR_LIB_DH,(0xfff),(r),__FILE__,__LINE__) +#define EVPerror(r) ERR_PUT_error(ERR_LIB_EVP,(0xfff),(r),__FILE__,__LINE__) +#define BUFerror(r) ERR_PUT_error(ERR_LIB_BUF,(0xfff),(r),__FILE__,__LINE__) +#define OBJerror(r) ERR_PUT_error(ERR_LIB_OBJ,(0xfff),(r),__FILE__,__LINE__) +#define PEMerror(r) ERR_PUT_error(ERR_LIB_PEM,(0xfff),(r),__FILE__,__LINE__) +#define DSAerror(r) ERR_PUT_error(ERR_LIB_DSA,(0xfff),(r),__FILE__,__LINE__) +#define X509error(r) ERR_PUT_error(ERR_LIB_X509,(0xfff),(r),__FILE__,__LINE__) +#define ASN1error(r) ERR_PUT_error(ERR_LIB_ASN1,(0xfff),(r),__FILE__,__LINE__) +#define CONFerror(r) ERR_PUT_error(ERR_LIB_CONF,(0xfff),(r),__FILE__,__LINE__) +#define CRYPTOerror(r) ERR_PUT_error(ERR_LIB_CRYPTO,(0xfff),(r),__FILE__,__LINE__) +#define ECerror(r) ERR_PUT_error(ERR_LIB_EC,(0xfff),(r),__FILE__,__LINE__) +#define BIOerror(r) ERR_PUT_error(ERR_LIB_BIO,(0xfff),(r),__FILE__,__LINE__) +#define PKCS7error(r) ERR_PUT_error(ERR_LIB_PKCS7,(0xfff),(r),__FILE__,__LINE__) +#define X509V3error(r) ERR_PUT_error(ERR_LIB_X509V3,(0xfff),(r),__FILE__,__LINE__) +#define PKCS12error(r) ERR_PUT_error(ERR_LIB_PKCS12,(0xfff),(r),__FILE__,__LINE__) +#define RANDerror(r) ERR_PUT_error(ERR_LIB_RAND,(0xfff),(r),__FILE__,__LINE__) +#define DSOerror(r) ERR_PUT_error(ERR_LIB_DSO,(0xfff),(r),__FILE__,__LINE__) +#define ENGINEerror(r) ERR_PUT_error(ERR_LIB_ENGINE,(0xfff),(r),__FILE__,__LINE__) +#define OCSPerror(r) ERR_PUT_error(ERR_LIB_OCSP,(0xfff),(r),__FILE__,__LINE__) +#define UIerror(r) ERR_PUT_error(ERR_LIB_UI,(0xfff),(r),__FILE__,__LINE__) +#define COMPerror(r) ERR_PUT_error(ERR_LIB_COMP,(0xfff),(r),__FILE__,__LINE__) +#define ECDSAerror(r) ERR_PUT_error(ERR_LIB_ECDSA,(0xfff),(r),__FILE__,__LINE__) +#define ECDHerror(r) ERR_PUT_error(ERR_LIB_ECDH,(0xfff),(r),__FILE__,__LINE__) +#define STOREerror(r) ERR_PUT_error(ERR_LIB_STORE,(0xfff),(r),__FILE__,__LINE__) +#define FIPSerror(r) ERR_PUT_error(ERR_LIB_FIPS,(0xfff),(r),__FILE__,__LINE__) +#define CMSerror(r) ERR_PUT_error(ERR_LIB_CMS,(0xfff),(r),__FILE__,__LINE__) +#define TSerror(r) ERR_PUT_error(ERR_LIB_TS,(0xfff),(r),__FILE__,__LINE__) +#define HMACerror(r) ERR_PUT_error(ERR_LIB_HMAC,(0xfff),(r),__FILE__,__LINE__) +#define JPAKEerror(r) ERR_PUT_error(ERR_LIB_JPAKE,(0xfff),(r),__FILE__,__LINE__) +#define GOSTerror(r) ERR_PUT_error(ERR_LIB_GOST,(0xfff),(r),__FILE__,__LINE__) +#define CTerror(r) ERR_PUT_error(ERR_LIB_CT,(0xfff),(r),__FILE__,__LINE__) +#define KDFerror(r) ERR_PUT_error(ERR_LIB_KDF,(0xfff),(r),__FILE__,__LINE__) +#endif + +#define ERR_PACK(l,f,r) (((((unsigned long)l)&0xffL)<<24L)| \ + ((((unsigned long)f)&0xfffL)<<12L)| \ + ((((unsigned long)r)&0xfffL))) +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define ERR_GET_FUNC(l) (int)((((unsigned long)l)>>12L)&0xfffL) +#define ERR_GET_REASON(l) (int)((l)&0xfffL) +#define ERR_FATAL_ERROR(l) (int)((l)&ERR_R_FATAL) + + +/* OS functions */ +#define SYS_F_FOPEN 1 +#define SYS_F_CONNECT 2 +#define SYS_F_GETSERVBYNAME 3 +#define SYS_F_SOCKET 4 +#define SYS_F_IOCTLSOCKET 5 +#define SYS_F_BIND 6 +#define SYS_F_LISTEN 7 +#define SYS_F_ACCEPT 8 +#define SYS_F_WSASTARTUP 9 /* Winsock stuff */ +#define SYS_F_OPENDIR 10 +#define SYS_F_FREAD 11 + + +/* reasons */ +#define ERR_R_SYS_LIB ERR_LIB_SYS /* 2 */ +#define ERR_R_BN_LIB ERR_LIB_BN /* 3 */ +#define ERR_R_RSA_LIB ERR_LIB_RSA /* 4 */ +#define ERR_R_DH_LIB ERR_LIB_DH /* 5 */ +#define ERR_R_EVP_LIB ERR_LIB_EVP /* 6 */ +#define ERR_R_BUF_LIB ERR_LIB_BUF /* 7 */ +#define ERR_R_OBJ_LIB ERR_LIB_OBJ /* 8 */ +#define ERR_R_PEM_LIB ERR_LIB_PEM /* 9 */ +#define ERR_R_DSA_LIB ERR_LIB_DSA /* 10 */ +#define ERR_R_X509_LIB ERR_LIB_X509 /* 11 */ +#define ERR_R_ASN1_LIB ERR_LIB_ASN1 /* 13 */ +#define ERR_R_CONF_LIB ERR_LIB_CONF /* 14 */ +#define ERR_R_CRYPTO_LIB ERR_LIB_CRYPTO /* 15 */ +#define ERR_R_EC_LIB ERR_LIB_EC /* 16 */ +#define ERR_R_SSL_LIB ERR_LIB_SSL /* 20 */ +#define ERR_R_BIO_LIB ERR_LIB_BIO /* 32 */ +#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7 /* 33 */ +#define ERR_R_X509V3_LIB ERR_LIB_X509V3 /* 34 */ +#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12 /* 35 */ +#define ERR_R_RAND_LIB ERR_LIB_RAND /* 36 */ +#define ERR_R_DSO_LIB ERR_LIB_DSO /* 37 */ +#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE /* 38 */ +#define ERR_R_OCSP_LIB ERR_LIB_OCSP /* 39 */ +#define ERR_R_UI_LIB ERR_LIB_UI /* 40 */ +#define ERR_R_COMP_LIB ERR_LIB_COMP /* 41 */ +#define ERR_R_ECDSA_LIB ERR_LIB_ECDSA /* 42 */ +#define ERR_R_ECDH_LIB ERR_LIB_ECDH /* 43 */ +#define ERR_R_STORE_LIB ERR_LIB_STORE /* 44 */ +#define ERR_R_TS_LIB ERR_LIB_TS /* 45 */ + +#define ERR_R_NESTED_ASN1_ERROR 58 +#define ERR_R_BAD_ASN1_OBJECT_HEADER 59 +#define ERR_R_BAD_GET_ASN1_OBJECT_CALL 60 +#define ERR_R_EXPECTING_AN_ASN1_SEQUENCE 61 +#define ERR_R_ASN1_LENGTH_MISMATCH 62 +#define ERR_R_MISSING_ASN1_EOS 63 + +/* fatal error */ +#define ERR_R_FATAL 64 +#define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +#define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +#define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +#define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) +#define ERR_R_DISABLED (5|ERR_R_FATAL) +#define ERR_R_INIT_FAIL (6|ERR_R_FATAL) + +/* 99 is the maximum possible ERR_R_... code, higher values + * are reserved for the individual libraries */ + +typedef struct ERR_string_data_st { + unsigned long error; + const char *string; +} ERR_STRING_DATA; + +void ERR_put_error(int lib, int func, int reason, const char *file, int line); +void ERR_set_error_data(char *data, int flags); + +unsigned long ERR_get_error(void); +unsigned long ERR_get_error_line(const char **file, int *line); +unsigned long ERR_get_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_error(void); +unsigned long ERR_peek_error_line(const char **file, int *line); +unsigned long ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags); +unsigned long ERR_peek_last_error(void); +unsigned long ERR_peek_last_error_line(const char **file, int *line); +unsigned long ERR_peek_last_error_line_data(const char **file, int *line, + const char **data, int *flags); +void ERR_clear_error(void ); +char *ERR_error_string(unsigned long e, char *buf); +void ERR_error_string_n(unsigned long e, char *buf, size_t len); +const char *ERR_lib_error_string(unsigned long e); +const char *ERR_func_error_string(unsigned long e); +const char *ERR_reason_error_string(unsigned long e); +void ERR_print_errors_cb(int (*cb)(const char *str, size_t len, void *u), + void *u); +void ERR_print_errors_fp(FILE *fp); +#ifndef OPENSSL_NO_BIO +void ERR_print_errors(BIO *bp); +#endif +void ERR_asprintf_error_data(char * format, ...); +#ifndef LIBRESSL_INTERNAL +void ERR_add_error_data(int num, ...); +void ERR_add_error_vdata(int num, va_list args); +#endif +void ERR_load_strings(int lib, ERR_STRING_DATA str[]); +void ERR_unload_strings(int lib, ERR_STRING_DATA str[]); +void ERR_load_ERR_strings(void); +void ERR_load_crypto_strings(void); +void ERR_free_strings(void); + +void ERR_remove_thread_state(const CRYPTO_THREADID *tid); +/* Wrapped in OPENSSL_NO_DEPRECATED in 0.9.8. Still used in 2023. */ +void ERR_remove_state(unsigned long pid); +ERR_STATE *ERR_get_state(void); + +int ERR_get_next_error_library(void); + +int ERR_set_mark(void); +int ERR_pop_to_mark(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/evp.h b/include/openssl/evp.h new file mode 100644 index 0000000..381098b --- /dev/null +++ b/include/openssl/evp.h @@ -0,0 +1,1515 @@ +/* $OpenBSD: evp.h,v 1.119 2023/08/25 12:37:33 schwarze Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_ENVELOPE_H +#define HEADER_ENVELOPE_H + +#include + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif + +/* +#define EVP_RC2_KEY_SIZE 16 +#define EVP_RC4_KEY_SIZE 16 +#define EVP_BLOWFISH_KEY_SIZE 16 +#define EVP_CAST5_KEY_SIZE 16 +#define EVP_RC5_32_12_16_KEY_SIZE 16 +*/ +#define EVP_MAX_MD_SIZE 64 /* longest known is SHA512 */ +#define EVP_MAX_KEY_LENGTH 64 +#define EVP_MAX_IV_LENGTH 16 +#define EVP_MAX_BLOCK_LENGTH 32 + +#define PKCS5_SALT_LEN 8 +/* Default PKCS#5 iteration count */ +#define PKCS5_DEFAULT_ITER 2048 + +#include + +#define EVP_PK_RSA 0x0001 +#define EVP_PK_DSA 0x0002 +#define EVP_PK_DH 0x0004 +#define EVP_PK_EC 0x0008 +#define EVP_PKT_SIGN 0x0010 +#define EVP_PKT_ENC 0x0020 +#define EVP_PKT_EXCH 0x0040 +#define EVP_PKS_RSA 0x0100 +#define EVP_PKS_DSA 0x0200 +#define EVP_PKS_EC 0x0400 +#define EVP_PKT_EXP 0x1000 /* <= 512 bit key */ + +#define EVP_PKEY_NONE NID_undef +#define EVP_PKEY_RSA NID_rsaEncryption +#define EVP_PKEY_RSA_PSS NID_rsassaPss +#define EVP_PKEY_RSA2 NID_rsa +#define EVP_PKEY_DSA NID_dsa +#define EVP_PKEY_DSA1 NID_dsa_2 +#define EVP_PKEY_DSA2 NID_dsaWithSHA +#define EVP_PKEY_DSA3 NID_dsaWithSHA1 +#define EVP_PKEY_DSA4 NID_dsaWithSHA1_2 +#define EVP_PKEY_DH NID_dhKeyAgreement +#define EVP_PKEY_EC NID_X9_62_id_ecPublicKey +#define EVP_PKEY_GOSTR01 NID_id_GostR3410_2001 +#define EVP_PKEY_GOSTIMIT NID_id_Gost28147_89_MAC +#define EVP_PKEY_HMAC NID_hmac +#define EVP_PKEY_CMAC NID_cmac +#define EVP_PKEY_HKDF NID_hkdf +#define EVP_PKEY_GOSTR12_256 NID_id_tc26_gost3410_2012_256 +#define EVP_PKEY_GOSTR12_512 NID_id_tc26_gost3410_2012_512 +#define EVP_PKEY_ED25519 NID_ED25519 +#define EVP_PKEY_X25519 NID_X25519 + +#ifdef __cplusplus +extern "C" { +#endif + +#define EVP_PKEY_MO_SIGN 0x0001 +#define EVP_PKEY_MO_VERIFY 0x0002 +#define EVP_PKEY_MO_ENCRYPT 0x0004 +#define EVP_PKEY_MO_DECRYPT 0x0008 + +#ifndef EVP_MD +#define EVP_MD_FLAG_ONESHOT 0x0001 /* digest can only handle a single + * block */ + +/* DigestAlgorithmIdentifier flags... */ + +#define EVP_MD_FLAG_DIGALGID_MASK 0x0018 + +/* NULL or absent parameter accepted. Use NULL */ + +#define EVP_MD_FLAG_DIGALGID_NULL 0x0000 + +/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */ + +#define EVP_MD_FLAG_DIGALGID_ABSENT 0x0008 + +/* Custom handling via ctrl */ + +#define EVP_MD_FLAG_DIGALGID_CUSTOM 0x0018 + +#define EVP_MD_FLAG_FIPS 0x0400 /* Note if suitable for use in FIPS mode */ + +/* Digest ctrls */ + +#define EVP_MD_CTRL_DIGALGID 0x1 +#define EVP_MD_CTRL_MICALG 0x2 +#define EVP_MD_CTRL_SET_KEY 0x3 +#define EVP_MD_CTRL_GOST_SET_SBOX 0x4 + +/* Minimum Algorithm specific ctrl value */ + +#define EVP_MD_CTRL_ALG_CTRL 0x1000 + +#endif /* !EVP_MD */ + +/* values for EVP_MD_CTX flags */ + +#define EVP_MD_CTX_FLAG_ONESHOT 0x0001 /* digest update will be called + * once only */ +#define EVP_MD_CTX_FLAG_CLEANED 0x0002 /* context has already been + * cleaned */ +#define EVP_MD_CTX_FLAG_REUSE 0x0004 /* Don't free up ctx->md_data + * in EVP_MD_CTX_cleanup */ +/* FIPS and pad options are ignored in 1.0.0, definitions are here + * so we don't accidentally reuse the values for other purposes. + */ + +#define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008 /* Allow use of non FIPS digest + * in FIPS mode */ + +/* The following PAD options are also currently ignored in 1.0.0, digest + * parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*() + * instead. + */ +#define EVP_MD_CTX_FLAG_PAD_MASK 0xF0 /* RSA mode to use */ +#define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00 /* PKCS#1 v1.5 mode */ +#define EVP_MD_CTX_FLAG_PAD_PSS 0x20 /* PSS mode */ + +#define EVP_MD_CTX_FLAG_NO_INIT 0x0100 /* Don't initialize md_data */ + +/* Values for cipher flags */ + +/* Modes for ciphers */ + +#define EVP_CIPH_STREAM_CIPHER 0x0 +#define EVP_CIPH_ECB_MODE 0x1 +#define EVP_CIPH_CBC_MODE 0x2 +#define EVP_CIPH_CFB_MODE 0x3 +#define EVP_CIPH_OFB_MODE 0x4 +#define EVP_CIPH_CTR_MODE 0x5 +#define EVP_CIPH_GCM_MODE 0x6 +#define EVP_CIPH_CCM_MODE 0x7 +#define EVP_CIPH_XTS_MODE 0x10001 +#define EVP_CIPH_WRAP_MODE 0x10002 +#define EVP_CIPH_MODE 0xF0007 +/* Set if variable length cipher */ +#define EVP_CIPH_VARIABLE_LENGTH 0x8 +/* Set if the iv handling should be done by the cipher itself */ +#define EVP_CIPH_CUSTOM_IV 0x10 +/* Set if the cipher's init() function should be called if key is NULL */ +#define EVP_CIPH_ALWAYS_CALL_INIT 0x20 +/* Call ctrl() to init cipher parameters */ +#define EVP_CIPH_CTRL_INIT 0x40 +/* Don't use standard key length function */ +#define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80 +/* Don't use standard block padding */ +#define EVP_CIPH_NO_PADDING 0x100 +/* cipher handles random key generation */ +#define EVP_CIPH_RAND_KEY 0x200 +/* cipher has its own additional copying logic */ +#define EVP_CIPH_CUSTOM_COPY 0x400 +/* Allow use default ASN1 get/set iv */ +#define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 +/* Buffer length in bits not bytes: CFB1 mode only */ +#define EVP_CIPH_FLAG_LENGTH_BITS 0x2000 +/* Note if suitable for use in FIPS mode */ +#define EVP_CIPH_FLAG_FIPS 0x4000 +/* Allow non FIPS cipher in FIPS mode */ +#define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000 +/* Cipher handles any and all padding logic as well + * as finalisation. + */ +#define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000 +#define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000 + +/* + * Cipher context flag to indicate that we can handle wrap mode: if allowed in + * older applications, it could overflow buffers. + */ +#define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1 + +/* ctrl() values */ + +#define EVP_CTRL_INIT 0x0 +#define EVP_CTRL_SET_KEY_LENGTH 0x1 +#define EVP_CTRL_GET_RC2_KEY_BITS 0x2 +#define EVP_CTRL_SET_RC2_KEY_BITS 0x3 +#define EVP_CTRL_GET_RC5_ROUNDS 0x4 +#define EVP_CTRL_SET_RC5_ROUNDS 0x5 +#define EVP_CTRL_RAND_KEY 0x6 +#define EVP_CTRL_PBE_PRF_NID 0x7 +#define EVP_CTRL_COPY 0x8 +#define EVP_CTRL_AEAD_SET_IVLEN 0x9 +#define EVP_CTRL_AEAD_GET_TAG 0x10 +#define EVP_CTRL_AEAD_SET_TAG 0x11 +#define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +#define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +#define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED +#define EVP_CTRL_GCM_IV_GEN 0x13 +#define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN +#define EVP_CTRL_CCM_GET_TAG EVP_CTRL_AEAD_GET_TAG +#define EVP_CTRL_CCM_SET_TAG EVP_CTRL_AEAD_SET_TAG +#define EVP_CTRL_CCM_SET_L 0x14 +#define EVP_CTRL_CCM_SET_MSGLEN 0x15 +/* AEAD cipher deduces payload length and returns number of bytes + * required to store MAC and eventual padding. Subsequent call to + * EVP_Cipher even appends/verifies MAC. + */ +#define EVP_CTRL_AEAD_TLS1_AAD 0x16 +/* Used by composite AEAD ciphers, no-op in GCM, CCM... */ +#define EVP_CTRL_AEAD_SET_MAC_KEY 0x17 +/* Set the GCM invocation field, decrypt only */ +#define EVP_CTRL_GCM_SET_IV_INV 0x18 +/* Set the S-BOX NID for GOST ciphers */ +#define EVP_CTRL_GOST_SET_SBOX 0x19 + +/* GCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +#define EVP_GCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +#define EVP_GCM_TLS_EXPLICIT_IV_LEN 8 +/* Length of tag for TLS */ +#define EVP_GCM_TLS_TAG_LEN 16 + +/* CCM TLS constants */ +/* Length of fixed part of IV derived from PRF */ +#define EVP_CCM_TLS_FIXED_IV_LEN 4 +/* Length of explicit part of IV part of TLS records */ +#define EVP_CCM_TLS_EXPLICIT_IV_LEN 8 +/* Total length of CCM IV length for TLS */ +#define EVP_CCM_TLS_IV_LEN 12 +/* Length of tag for TLS */ +#define EVP_CCM_TLS_TAG_LEN 16 +/* Length of CCM8 tag for TLS */ +#define EVP_CCM8_TLS_TAG_LEN 8 + +/* Length of tag for TLS */ +#define EVP_CHACHAPOLY_TLS_TAG_LEN 16 + +/* XXX - do we want to expose these? */ +#if defined(LIBRESSL_INTERNAL) +#define ED25519_KEYLEN 32 +#define X25519_KEYLEN 32 +#endif + +typedef struct evp_cipher_info_st { + const EVP_CIPHER *cipher; + unsigned char iv[EVP_MAX_IV_LENGTH]; +} EVP_CIPHER_INFO; + +/* Password based encryption function */ +typedef int EVP_PBE_KEYGEN(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de); + +#ifndef OPENSSL_NO_RSA +#define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ + (char *)(rsa)) +#endif + +#ifndef OPENSSL_NO_DSA +#define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ + (char *)(dsa)) +#endif + +#ifndef OPENSSL_NO_DH +#define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\ + (char *)(dh)) +#endif + +#ifndef OPENSSL_NO_EC +#define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\ + (char *)(eckey)) +#endif + +#ifndef OPENSSL_NO_GOST +#define EVP_PKEY_assign_GOST(pkey,gostkey) EVP_PKEY_assign((pkey),EVP_PKEY_GOSTR01,\ + (char *)(gostkey)) +#endif + +/* Add some extra combinations */ +#define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a)) +#define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a)) +#define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a)) +#define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a)) + +int EVP_MD_type(const EVP_MD *md); +#define EVP_MD_nid(e) EVP_MD_type(e) +#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e)) +int EVP_MD_pkey_type(const EVP_MD *md); +int EVP_MD_size(const EVP_MD *md); +int EVP_MD_block_size(const EVP_MD *md); +unsigned long EVP_MD_flags(const EVP_MD *md); + +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type); +void EVP_MD_meth_free(EVP_MD *md); +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md); +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize); +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize); +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize); +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags); +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_update(EVP_MD *md, + int (*update)(EVP_MD_CTX *ctx, const void *data, size_t count)); +int EVP_MD_meth_set_final(EVP_MD *md, + int (*final)(EVP_MD_CTX *ctx, unsigned char *md)); +int EVP_MD_meth_set_copy(EVP_MD *md, + int (*copy)(EVP_MD_CTX *to, const EVP_MD_CTX *from)); +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)); +int EVP_MD_meth_set_ctrl(EVP_MD *md, + int (*ctrl)(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)); + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx); +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx); +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx); +void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx); +#define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e)) +#define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e)) +#define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e)) + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher); +#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) +int EVP_CIPHER_block_size(const EVP_CIPHER *cipher); +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher); +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher); +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher); +#define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE) + +const EVP_CIPHER * EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx); +int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, + unsigned char *iv, size_t len); +int EVP_CIPHER_CTX_set_iv(EVP_CIPHER_CTX *ctx, + const unsigned char *iv, size_t len); +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx); +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data); +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx); +#define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c)) +unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx); +#define EVP_CIPHER_CTX_mode(e) (EVP_CIPHER_CTX_flags(e) & EVP_CIPH_MODE) + +EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len); +EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher); +void EVP_CIPHER_meth_free(EVP_CIPHER *cipher); + +int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len); +int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags); +int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size); +int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher, + int (*init)(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc)); +int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher, + int (*do_cipher)(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl)); +int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher, + int (*cleanup)(EVP_CIPHER_CTX *)); +int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher, + int (*set_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *)); +int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher, + int (*get_asn1_parameters)(EVP_CIPHER_CTX *, ASN1_TYPE *)); +int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher, + int (*ctrl)(EVP_CIPHER_CTX *, int type, int arg, void *ptr)); + +EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *engine, + const unsigned char *private_key, size_t len); +EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *engine, + const unsigned char *public_key, size_t len); +int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, + unsigned char *out_private_key, size_t *out_len); +int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, + unsigned char *out_public_key, size_t *out_len); + +#define EVP_ENCODE_LENGTH(l) (((l+2)/3*4)+(l/48+1)*2+80) +#define EVP_DECODE_LENGTH(l) ((l+3)/4*3+80) + +#define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +#define EVP_SignInit(a,b) EVP_DigestInit(a,b) +#define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c) +#define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) +#define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) +#define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) +#define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) +#define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) + +#define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)md) +#define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)mdp) +#define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0,(char *)mdcp) +#define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0,(char *)mdcp) +#define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL) +#define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0,(char *)c_pp) + +int EVP_Cipher(EVP_CIPHER_CTX *c, unsigned char *out, const unsigned char *in, + unsigned int inl); + +#define EVP_add_cipher_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n)) +#define EVP_add_digest_alias(n,alias) \ + OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n)) +#define EVP_delete_cipher_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS); +#define EVP_delete_digest_alias(alias) \ + OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS); + +EVP_MD_CTX *EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); +void EVP_MD_CTX_init(EVP_MD_CTX *ctx); +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); +EVP_MD_CTX *EVP_MD_CTX_create(void); +void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx); +int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx); +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags); +int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr); +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags); + +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl); +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt); +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); +int EVP_Digest(const void *data, size_t count, unsigned char *md, + unsigned int *size, const EVP_MD *type, ENGINE *impl); + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in); +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); + +int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify); +int EVP_read_pw_string_min(char *buf, int minlen, int maxlen, + const char *prompt, int verify); +void EVP_set_pw_prompt(const char *prompt); +char *EVP_get_pw_prompt(void); + +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, + const unsigned char *salt, const unsigned char *data, int datal, int count, + unsigned char *key, unsigned char *iv); + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags); +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags); +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags); + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, const unsigned char *iv); +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +#ifndef LIBRESSL_INTERNAL +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +#endif + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv); +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, const unsigned char *iv); +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +#ifndef LIBRESSL_INTERNAL +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +#endif + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + const unsigned char *key, const unsigned char *iv, int enc); +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, + ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc); +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +#ifndef LIBRESSL_INTERNAL +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl); +#endif + +int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s, + EVP_PKEY *pkey); + +int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, + unsigned int siglen, EVP_PKEY *pkey); + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen); + +int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, + const unsigned char *tbs, size_t tbslen); + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, + const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey); +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, + size_t siglen); + +int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, + size_t siglen, const unsigned char *tbs, size_t tbslen); + +int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + const unsigned char *ek, int ekl, const unsigned char *iv, EVP_PKEY *priv); +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, + unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, + int npubk); +int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); + +EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void); +void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx); +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); +int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, + const unsigned char *in, int inl); +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl); +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n); + +void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *a); +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad); +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key); + +#ifndef OPENSSL_NO_BIO +const BIO_METHOD *BIO_f_md(void); +const BIO_METHOD *BIO_f_base64(void); +const BIO_METHOD *BIO_f_cipher(void); +int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, + const unsigned char *i, int enc); +#endif + +const EVP_MD *EVP_md_null(void); +#ifndef OPENSSL_NO_MD4 +const EVP_MD *EVP_md4(void); +#endif +#ifndef OPENSSL_NO_MD5 +const EVP_MD *EVP_md5(void); +const EVP_MD *EVP_md5_sha1(void); +#endif +#ifndef OPENSSL_NO_SHA +const EVP_MD *EVP_sha1(void); +#endif +#ifndef OPENSSL_NO_SHA256 +const EVP_MD *EVP_sha224(void); +const EVP_MD *EVP_sha256(void); +#endif +#ifndef OPENSSL_NO_SHA512 +const EVP_MD *EVP_sha384(void); +const EVP_MD *EVP_sha512(void); +const EVP_MD *EVP_sha512_224(void); +const EVP_MD *EVP_sha512_256(void); +#endif +#ifndef OPENSSL_NO_SHA3 +const EVP_MD *EVP_sha3_224(void); +const EVP_MD *EVP_sha3_256(void); +const EVP_MD *EVP_sha3_384(void); +const EVP_MD *EVP_sha3_512(void); +#endif +#ifndef OPENSSL_NO_SM3 +const EVP_MD *EVP_sm3(void); +#endif +#ifndef OPENSSL_NO_RIPEMD +const EVP_MD *EVP_ripemd160(void); +#endif +#ifndef OPENSSL_NO_WHIRLPOOL +const EVP_MD *EVP_whirlpool(void); +#endif +#ifndef OPENSSL_NO_GOST +const EVP_MD *EVP_gostr341194(void); +const EVP_MD *EVP_gost2814789imit(void); +const EVP_MD *EVP_streebog256(void); +const EVP_MD *EVP_streebog512(void); +#endif +const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */ +#ifndef OPENSSL_NO_DES +const EVP_CIPHER *EVP_des_ecb(void); +const EVP_CIPHER *EVP_des_ede(void); +const EVP_CIPHER *EVP_des_ede3(void); +const EVP_CIPHER *EVP_des_ede_ecb(void); +const EVP_CIPHER *EVP_des_ede3_ecb(void); +const EVP_CIPHER *EVP_des_cfb64(void); +# define EVP_des_cfb EVP_des_cfb64 +const EVP_CIPHER *EVP_des_cfb1(void); +const EVP_CIPHER *EVP_des_cfb8(void); +const EVP_CIPHER *EVP_des_ede_cfb64(void); +# define EVP_des_ede_cfb EVP_des_ede_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb64(void); +# define EVP_des_ede3_cfb EVP_des_ede3_cfb64 +const EVP_CIPHER *EVP_des_ede3_cfb1(void); +const EVP_CIPHER *EVP_des_ede3_cfb8(void); +const EVP_CIPHER *EVP_des_ofb(void); +const EVP_CIPHER *EVP_des_ede_ofb(void); +const EVP_CIPHER *EVP_des_ede3_ofb(void); +const EVP_CIPHER *EVP_des_cbc(void); +const EVP_CIPHER *EVP_des_ede_cbc(void); +const EVP_CIPHER *EVP_des_ede3_cbc(void); +const EVP_CIPHER *EVP_desx_cbc(void); +#endif +#ifndef OPENSSL_NO_RC4 +const EVP_CIPHER *EVP_rc4(void); +const EVP_CIPHER *EVP_rc4_40(void); +#ifndef OPENSSL_NO_MD5 +const EVP_CIPHER *EVP_rc4_hmac_md5(void); +#endif +#endif +#ifndef OPENSSL_NO_IDEA +const EVP_CIPHER *EVP_idea_ecb(void); +const EVP_CIPHER *EVP_idea_cfb64(void); +# define EVP_idea_cfb EVP_idea_cfb64 +const EVP_CIPHER *EVP_idea_ofb(void); +const EVP_CIPHER *EVP_idea_cbc(void); +#endif +#ifndef OPENSSL_NO_RC2 +const EVP_CIPHER *EVP_rc2_ecb(void); +const EVP_CIPHER *EVP_rc2_cbc(void); +const EVP_CIPHER *EVP_rc2_40_cbc(void); +const EVP_CIPHER *EVP_rc2_64_cbc(void); +const EVP_CIPHER *EVP_rc2_cfb64(void); +# define EVP_rc2_cfb EVP_rc2_cfb64 +const EVP_CIPHER *EVP_rc2_ofb(void); +#endif +#ifndef OPENSSL_NO_BF +const EVP_CIPHER *EVP_bf_ecb(void); +const EVP_CIPHER *EVP_bf_cbc(void); +const EVP_CIPHER *EVP_bf_cfb64(void); +# define EVP_bf_cfb EVP_bf_cfb64 +const EVP_CIPHER *EVP_bf_ofb(void); +#endif +#ifndef OPENSSL_NO_CAST +const EVP_CIPHER *EVP_cast5_ecb(void); +const EVP_CIPHER *EVP_cast5_cbc(void); +const EVP_CIPHER *EVP_cast5_cfb64(void); +# define EVP_cast5_cfb EVP_cast5_cfb64 +const EVP_CIPHER *EVP_cast5_ofb(void); +#endif +#ifndef OPENSSL_NO_AES +const EVP_CIPHER *EVP_aes_128_ecb(void); +const EVP_CIPHER *EVP_aes_128_cbc(void); +const EVP_CIPHER *EVP_aes_128_cfb1(void); +const EVP_CIPHER *EVP_aes_128_cfb8(void); +const EVP_CIPHER *EVP_aes_128_cfb128(void); +# define EVP_aes_128_cfb EVP_aes_128_cfb128 +const EVP_CIPHER *EVP_aes_128_ofb(void); +const EVP_CIPHER *EVP_aes_128_ctr(void); +const EVP_CIPHER *EVP_aes_128_ccm(void); +const EVP_CIPHER *EVP_aes_128_gcm(void); +const EVP_CIPHER *EVP_aes_128_wrap(void); +const EVP_CIPHER *EVP_aes_128_xts(void); +const EVP_CIPHER *EVP_aes_192_ecb(void); +const EVP_CIPHER *EVP_aes_192_cbc(void); +const EVP_CIPHER *EVP_aes_192_cfb1(void); +const EVP_CIPHER *EVP_aes_192_cfb8(void); +const EVP_CIPHER *EVP_aes_192_cfb128(void); +# define EVP_aes_192_cfb EVP_aes_192_cfb128 +const EVP_CIPHER *EVP_aes_192_ofb(void); +const EVP_CIPHER *EVP_aes_192_ctr(void); +const EVP_CIPHER *EVP_aes_192_ccm(void); +const EVP_CIPHER *EVP_aes_192_gcm(void); +const EVP_CIPHER *EVP_aes_192_wrap(void); +const EVP_CIPHER *EVP_aes_256_ecb(void); +const EVP_CIPHER *EVP_aes_256_cbc(void); +const EVP_CIPHER *EVP_aes_256_cfb1(void); +const EVP_CIPHER *EVP_aes_256_cfb8(void); +const EVP_CIPHER *EVP_aes_256_cfb128(void); +# define EVP_aes_256_cfb EVP_aes_256_cfb128 +const EVP_CIPHER *EVP_aes_256_ofb(void); +const EVP_CIPHER *EVP_aes_256_ctr(void); +const EVP_CIPHER *EVP_aes_256_ccm(void); +const EVP_CIPHER *EVP_aes_256_gcm(void); +const EVP_CIPHER *EVP_aes_256_wrap(void); +const EVP_CIPHER *EVP_aes_256_xts(void); +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +const EVP_CIPHER *EVP_chacha20_poly1305(void); +#endif +#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1) +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void); +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void); +#endif +#endif +#ifndef OPENSSL_NO_CAMELLIA +const EVP_CIPHER *EVP_camellia_128_ecb(void); +const EVP_CIPHER *EVP_camellia_128_cbc(void); +const EVP_CIPHER *EVP_camellia_128_cfb1(void); +const EVP_CIPHER *EVP_camellia_128_cfb8(void); +const EVP_CIPHER *EVP_camellia_128_cfb128(void); +# define EVP_camellia_128_cfb EVP_camellia_128_cfb128 +const EVP_CIPHER *EVP_camellia_128_ofb(void); +const EVP_CIPHER *EVP_camellia_192_ecb(void); +const EVP_CIPHER *EVP_camellia_192_cbc(void); +const EVP_CIPHER *EVP_camellia_192_cfb1(void); +const EVP_CIPHER *EVP_camellia_192_cfb8(void); +const EVP_CIPHER *EVP_camellia_192_cfb128(void); +# define EVP_camellia_192_cfb EVP_camellia_192_cfb128 +const EVP_CIPHER *EVP_camellia_192_ofb(void); +const EVP_CIPHER *EVP_camellia_256_ecb(void); +const EVP_CIPHER *EVP_camellia_256_cbc(void); +const EVP_CIPHER *EVP_camellia_256_cfb1(void); +const EVP_CIPHER *EVP_camellia_256_cfb8(void); +const EVP_CIPHER *EVP_camellia_256_cfb128(void); +# define EVP_camellia_256_cfb EVP_camellia_256_cfb128 +const EVP_CIPHER *EVP_camellia_256_ofb(void); +#endif + +#ifndef OPENSSL_NO_CHACHA +const EVP_CIPHER *EVP_chacha20(void); +#endif + +#ifndef OPENSSL_NO_GOST +const EVP_CIPHER *EVP_gost2814789_ecb(void); +const EVP_CIPHER *EVP_gost2814789_cfb64(void); +const EVP_CIPHER *EVP_gost2814789_cnt(void); +#endif + +#ifndef OPENSSL_NO_SM4 +const EVP_CIPHER *EVP_sm4_ecb(void); +const EVP_CIPHER *EVP_sm4_cbc(void); +const EVP_CIPHER *EVP_sm4_cfb128(void); +#define EVP_sm4_cfb EVP_sm4_cfb128 +const EVP_CIPHER *EVP_sm4_ofb(void); +const EVP_CIPHER *EVP_sm4_ctr(void); +#endif + +void OPENSSL_add_all_algorithms_noconf(void); +void OPENSSL_add_all_algorithms_conf(void); + +#ifdef OPENSSL_LOAD_CONF +#define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_conf() +#else +#define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_noconf() +#endif + +void OpenSSL_add_all_ciphers(void); +void OpenSSL_add_all_digests(void); + +#define SSLeay_add_all_algorithms() OpenSSL_add_all_algorithms() +#define SSLeay_add_all_ciphers() OpenSSL_add_all_ciphers() +#define SSLeay_add_all_digests() OpenSSL_add_all_digests() + +int EVP_add_cipher(const EVP_CIPHER *cipher); +int EVP_add_digest(const EVP_MD *digest); + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name); +const EVP_MD *EVP_get_digestbyname(const char *name); +void EVP_cleanup(void); + +void EVP_CIPHER_do_all(void (*fn)(const EVP_CIPHER *ciph, const char *from, + const char *to, void *x), void *arg); +void EVP_CIPHER_do_all_sorted(void (*fn)(const EVP_CIPHER *ciph, + const char *from, const char *to, void *x), void *arg); + +void EVP_MD_do_all(void (*fn)(const EVP_MD *ciph, const char *from, + const char *to, void *x), void *arg); +void EVP_MD_do_all_sorted(void (*fn)(const EVP_MD *ciph, const char *from, + const char *to, void *x), void *arg); + +int EVP_PKEY_decrypt_old(unsigned char *dec_key, const unsigned char *enc_key, + int enc_key_len, EVP_PKEY *private_key); +int EVP_PKEY_encrypt_old(unsigned char *enc_key, const unsigned char *key, + int key_len, EVP_PKEY *pub_key); +int EVP_PKEY_type(int type); +int EVP_PKEY_id(const EVP_PKEY *pkey); +int EVP_PKEY_base_id(const EVP_PKEY *pkey); +int EVP_PKEY_bits(const EVP_PKEY *pkey); +int EVP_PKEY_security_bits(const EVP_PKEY *pkey); +int EVP_PKEY_size(const EVP_PKEY *pkey); +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type); +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len); +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key); +void *EVP_PKEY_get0(const EVP_PKEY *pkey); +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len); + +#ifndef OPENSSL_NO_RSA +struct rsa_st; +struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); +struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey); +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key); +#endif +#ifndef OPENSSL_NO_DSA +struct dsa_st; +struct dsa_st *EVP_PKEY_get0_DSA(EVP_PKEY *pkey); +struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey); +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key); +#endif +#ifndef OPENSSL_NO_DH +struct dh_st; +struct dh_st *EVP_PKEY_get0_DH(EVP_PKEY *pkey); +struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey); +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key); +#endif +#ifndef OPENSSL_NO_EC +struct ec_key_st; +struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey); +struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey); +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key); +#endif +#ifndef OPENSSL_NO_GOST +struct gost_key_st; +#endif + +EVP_PKEY *EVP_PKEY_new(void); +void EVP_PKEY_free(EVP_PKEY *pkey); +int EVP_PKEY_up_ref(EVP_PKEY *pkey); + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, + long length); +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, + long length); +int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp); + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from); +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey); +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode); +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx); + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid); + +int EVP_CIPHER_type(const EVP_CIPHER *ctx); + +/* calls methods */ +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* These are used by EVP_CIPHER methods */ +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); + +/* PKCS5 password based encryption */ +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, int en_de); +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, int saltlen, int iter, int keylen, + unsigned char *out); +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 PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md, + int en_de); + +void PKCS5_PBE_add(void); + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); + +/* PBE type */ + +/* Can appear as the outermost AlgorithmIdentifier */ +#define EVP_PBE_TYPE_OUTER 0x0 +/* Is an PRF type OID */ +#define EVP_PBE_TYPE_PRF 0x1 + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, int md_nid, + EVP_PBE_KEYGEN *keygen); +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid, + EVP_PBE_KEYGEN **pkeygen); +void EVP_PBE_cleanup(void); + +#define ASN1_PKEY_ALIAS 0x1 +#define ASN1_PKEY_DYNAMIC 0x2 +#define ASN1_PKEY_SIGPARAM_NULL 0x4 + +#define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1 +#define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2 +#define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3 +#define ASN1_PKEY_CTRL_CMS_SIGN 0x5 +#define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7 +#define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8 + +int EVP_PKEY_asn1_get_count(void); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type); +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, + const char *str, int len); +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth); +int EVP_PKEY_asn1_add_alias(int to, int from); +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id, int *ppkey_flags, + const char **pinfo, const char **ppem_str, + const EVP_PKEY_ASN1_METHOD *ameth); + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey); +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, + const char *info); +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, + const EVP_PKEY_ASN1_METHOD *src); +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), + int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk), + int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), + int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx), + int (*pkey_size)(const EVP_PKEY *pk), + int (*pkey_bits)(const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, + int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf), + int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk), + int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx)); +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, + int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen), + int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder), + int (*param_missing)(const EVP_PKEY *pk), + int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from), + int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b), + int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent, + ASN1_PCTX *pctx)); + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, + void (*pkey_free)(EVP_PKEY *pkey)); +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2)); +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_security_bits)(const EVP_PKEY *pkey)); + +void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check)(const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_public_check)(const EVP_PKEY *pk)); +void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth, + int (*pkey_check)(const EVP_PKEY *pk)); + +#define EVP_PKEY_OP_UNDEFINED 0 +#define EVP_PKEY_OP_PARAMGEN (1<<1) +#define EVP_PKEY_OP_KEYGEN (1<<2) +#define EVP_PKEY_OP_SIGN (1<<3) +#define EVP_PKEY_OP_VERIFY (1<<4) +#define EVP_PKEY_OP_VERIFYRECOVER (1<<5) +#define EVP_PKEY_OP_SIGNCTX (1<<6) +#define EVP_PKEY_OP_VERIFYCTX (1<<7) +#define EVP_PKEY_OP_ENCRYPT (1<<8) +#define EVP_PKEY_OP_DECRYPT (1<<9) +#define EVP_PKEY_OP_DERIVE (1<<10) + +#define EVP_PKEY_OP_TYPE_SIG \ + (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \ + | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX) + +#define EVP_PKEY_OP_TYPE_CRYPT \ + (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT) + +#define EVP_PKEY_OP_TYPE_NOGEN \ + (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE) + +#define EVP_PKEY_OP_TYPE_GEN \ + (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN) + +#define EVP_PKEY_CTX_set_signature_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_MD, 0, (void *)md) + +#define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \ + EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd)) + +#define EVP_PKEY_CTRL_MD 1 +#define EVP_PKEY_CTRL_PEER_KEY 2 + +#define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3 +#define EVP_PKEY_CTRL_PKCS7_DECRYPT 4 + +#define EVP_PKEY_CTRL_PKCS7_SIGN 5 + +#define EVP_PKEY_CTRL_SET_MAC_KEY 6 + +#define EVP_PKEY_CTRL_DIGESTINIT 7 + +/* Used by GOST key encryption in TLS */ +#define EVP_PKEY_CTRL_SET_IV 8 + +#define EVP_PKEY_CTRL_CMS_ENCRYPT 9 +#define EVP_PKEY_CTRL_CMS_DECRYPT 10 +#define EVP_PKEY_CTRL_CMS_SIGN 11 + +#define EVP_PKEY_CTRL_CIPHER 12 + +#define EVP_PKEY_CTRL_GET_MD 13 + +#define EVP_PKEY_ALG_CTRL 0x1000 + + +#define EVP_PKEY_FLAG_AUTOARGLEN 2 +/* Method handles all operations: don't assume any digest related + * defaults. + */ +#define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4 + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type); +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags); +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, + const EVP_PKEY_METHOD *meth); +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src); +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth); +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth); + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e); +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd, + int p1, void *p2); +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, + const char *value); + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx); +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen); + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, const unsigned char *key, + int keylen); +EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv, + size_t len, const EVP_CIPHER *cipher); + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx); +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx); + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen); +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, unsigned char *rout, + size_t *routlen, const unsigned char *sig, size_t siglen); +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen); + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer); +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen); + +typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); +int EVP_PKEY_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx); +int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, + int (*init)(EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, + int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)); + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, + void (*cleanup)(EVP_PKEY_CTX *ctx)); + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, + int (*paramgen_init)(EVP_PKEY_CTX *ctx), + int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, + int (*keygen_init)(EVP_PKEY_CTX *ctx), + int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)); + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, + int (*sign_init)(EVP_PKEY_CTX *ctx), + int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen)); + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, + int (*verify_init)(EVP_PKEY_CTX *ctx), + int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen)); + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, + int (*verify_recover_init)(EVP_PKEY_CTX *ctx), + int (*verify_recover)(EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, size_t tbslen)); + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, + int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx), + int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, + int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx), + int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen, + EVP_MD_CTX *mctx)); + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, + int (*encrypt_init)(EVP_PKEY_CTX *ctx), + int (*encryptfn)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen)); + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, + int (*decrypt_init)(EVP_PKEY_CTX *ctx), + int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen)); + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, + int (*derive_init)(EVP_PKEY_CTX *ctx), + int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)); + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, + int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2), + int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value)); + +void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth, + int (*check)(EVP_PKEY *pkey)); +void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth, + int (*public_check)(EVP_PKEY *pkey)); +void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth, + int (*param_check)(EVP_PKEY *pkey)); + +/* Authenticated Encryption with Additional Data. + * + * AEAD couples confidentiality and integrity in a single primtive. AEAD + * algorithms take a key and then can seal and open individual messages. Each + * message has a unique, per-message nonce and, optionally, additional data + * which is authenticated but not included in the output. */ + +typedef struct evp_aead_st EVP_AEAD; + +#ifndef OPENSSL_NO_AES +/* EVP_aes_128_gcm is AES-128 in Galois Counter Mode. */ +const EVP_AEAD *EVP_aead_aes_128_gcm(void); +/* EVP_aes_256_gcm is AES-256 in Galois Counter Mode. */ +const EVP_AEAD *EVP_aead_aes_256_gcm(void); +#endif + +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +/* EVP_aead_chacha20_poly1305 is ChaCha20 with a Poly1305 authenticator. */ +const EVP_AEAD *EVP_aead_chacha20_poly1305(void); +/* EVP_aead_xchacha20_poly1305 is XChaCha20 with a Poly1305 authenticator. */ +const EVP_AEAD *EVP_aead_xchacha20_poly1305(void); +#endif + +/* EVP_AEAD_key_length returns the length of the keys used. */ +size_t EVP_AEAD_key_length(const EVP_AEAD *aead); + +/* EVP_AEAD_nonce_length returns the length of the per-message nonce. */ +size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead); + +/* EVP_AEAD_max_overhead returns the maximum number of additional bytes added + * by the act of sealing data with the AEAD. */ +size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead); + +/* EVP_AEAD_max_tag_len returns the maximum tag length when using this AEAD. + * This * is the largest value that can be passed as a tag length to + * EVP_AEAD_CTX_init. */ +size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead); + +/* An EVP_AEAD_CTX represents an AEAD algorithm configured with a specific key + * and message-independent IV. */ +typedef struct evp_aead_ctx_st EVP_AEAD_CTX; + +/* EVP_AEAD_MAX_TAG_LENGTH is the maximum tag length used by any AEAD + * defined in this header. */ +#define EVP_AEAD_MAX_TAG_LENGTH 16 + +/* EVP_AEAD_DEFAULT_TAG_LENGTH is a magic value that can be passed to + * EVP_AEAD_CTX_init to indicate that the default tag length for an AEAD + * should be used. */ +#define EVP_AEAD_DEFAULT_TAG_LENGTH 0 + +/* EVP_AEAD_CTX_new allocates a new context for use with EVP_AEAD_CTX_init. + * It can be cleaned up for reuse with EVP_AEAD_CTX_cleanup and must be freed + * with EVP_AEAD_CTX_free. */ +EVP_AEAD_CTX *EVP_AEAD_CTX_new(void); + +/* EVP_AEAD_CTX_free releases all memory owned by the context. */ +void EVP_AEAD_CTX_free(EVP_AEAD_CTX *ctx); + +/* EVP_AEAD_CTX_init initializes the context for the given AEAD algorithm. + * The implementation argument may be NULL to choose the default implementation. + * Authentication tags may be truncated by passing a tag length. A tag length + * of zero indicates the default tag length should be used. */ +int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, + const unsigned char *key, size_t key_len, size_t tag_len, ENGINE *impl); + +/* EVP_AEAD_CTX_cleanup frees any data allocated for this context. */ +void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx); + +/* EVP_AEAD_CTX_seal encrypts and authenticates the input and authenticates + * any additional data (AD), the result being written as output. One is + * returned on success, otherwise zero. + * + * This function may be called (with the same EVP_AEAD_CTX) concurrently with + * itself or EVP_AEAD_CTX_open. + * + * At most max_out_len bytes are written as output and, in order to ensure + * success, this value should be the length of the input plus the result of + * EVP_AEAD_overhead. On successful return, out_len is set to the actual + * number of bytes written. + * + * The length of the nonce is must be equal to the result of + * EVP_AEAD_nonce_length for this AEAD. + * + * EVP_AEAD_CTX_seal never results in a partial output. If max_out_len is + * insufficient, zero will be returned and out_len will be set to zero. + * + * If the input and output are aliased then out must be <= in. */ +int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, unsigned char *out, + size_t *out_len, size_t max_out_len, const unsigned char *nonce, + size_t nonce_len, const unsigned char *in, size_t in_len, + const unsigned char *ad, size_t ad_len); + +/* EVP_AEAD_CTX_open authenticates the input and additional data, decrypting + * the input and writing it as output. One is returned on success, otherwise + * zero. + * + * This function may be called (with the same EVP_AEAD_CTX) concurrently with + * itself or EVP_AEAD_CTX_seal. + * + * At most the number of input bytes are written as output. In order to ensure + * success, max_out_len should be at least the same as the input length. On + * successful return out_len is set to the actual number of bytes written. + * + * The length of nonce must be equal to the result of EVP_AEAD_nonce_length + * for this AEAD. + * + * EVP_AEAD_CTX_open never results in a partial output. If max_out_len is + * insufficient, zero will be returned and out_len will be set to zero. + * + * If the input and output are aliased then out must be <= in. */ +int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, unsigned char *out, + size_t *out_len, size_t max_out_len, const unsigned char *nonce, + size_t nonce_len, const unsigned char *in, size_t in_len, + const unsigned char *ad, size_t ad_len); + +void EVP_add_alg_module(void); + +void ERR_load_EVP_strings(void); + +/* Error codes for the EVP functions. */ + +/* Function codes. */ +#define EVP_F_AEAD_AES_GCM_INIT 187 +#define EVP_F_AEAD_AES_GCM_OPEN 188 +#define EVP_F_AEAD_AES_GCM_SEAL 189 +#define EVP_F_AEAD_CHACHA20_POLY1305_INIT 192 +#define EVP_F_AEAD_CHACHA20_POLY1305_OPEN 193 +#define EVP_F_AEAD_CHACHA20_POLY1305_SEAL 194 +#define EVP_F_AEAD_CTX_OPEN 185 +#define EVP_F_AEAD_CTX_SEAL 186 +#define EVP_F_AESNI_INIT_KEY 165 +#define EVP_F_AESNI_XTS_CIPHER 176 +#define EVP_F_AES_INIT_KEY 133 +#define EVP_F_AES_XTS 172 +#define EVP_F_AES_XTS_CIPHER 175 +#define EVP_F_ALG_MODULE_INIT 177 +#define EVP_F_CAMELLIA_INIT_KEY 159 +#define EVP_F_CMAC_INIT 173 +#define EVP_F_D2I_PKEY 100 +#define EVP_F_DO_SIGVER_INIT 161 +#define EVP_F_DSAPKEY2PKCS8 134 +#define EVP_F_DSA_PKEY2PKCS8 135 +#define EVP_F_ECDSA_PKEY2PKCS8 129 +#define EVP_F_ECKEY_PKEY2PKCS8 132 +#define EVP_F_EVP_AEAD_CTX_INIT 180 +#define EVP_F_EVP_AEAD_CTX_OPEN 190 +#define EVP_F_EVP_AEAD_CTX_SEAL 191 +#define EVP_F_EVP_BYTESTOKEY 200 +#define EVP_F_EVP_CIPHERINIT_EX 123 +#define EVP_F_EVP_CIPHER_CTX_COPY 163 +#define EVP_F_EVP_CIPHER_CTX_CTRL 124 +#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH 122 +#define EVP_F_EVP_CIPHER_GET_ASN1_IV 201 +#define EVP_F_EVP_CIPHER_SET_ASN1_IV 202 +#define EVP_F_EVP_DECRYPTFINAL_EX 101 +#define EVP_F_EVP_DECRYPTUPDATE 199 +#define EVP_F_EVP_DIGESTFINAL_EX 196 +#define EVP_F_EVP_DIGESTINIT_EX 128 +#define EVP_F_EVP_ENCRYPTFINAL_EX 127 +#define EVP_F_EVP_ENCRYPTUPDATE 198 +#define EVP_F_EVP_MD_CTX_COPY_EX 110 +#define EVP_F_EVP_MD_CTX_CTRL 195 +#define EVP_F_EVP_MD_SIZE 162 +#define EVP_F_EVP_OPENINIT 102 +#define EVP_F_EVP_PBE_ALG_ADD 115 +#define EVP_F_EVP_PBE_ALG_ADD_TYPE 160 +#define EVP_F_EVP_PBE_CIPHERINIT 116 +#define EVP_F_EVP_PKCS82PKEY 111 +#define EVP_F_EVP_PKCS82PKEY_BROKEN 136 +#define EVP_F_EVP_PKEY2PKCS8_BROKEN 113 +#define EVP_F_EVP_PKEY_COPY_PARAMETERS 103 +#define EVP_F_EVP_PKEY_CTX_CTRL 137 +#define EVP_F_EVP_PKEY_CTX_CTRL_STR 150 +#define EVP_F_EVP_PKEY_CTX_DUP 156 +#define EVP_F_EVP_PKEY_DECRYPT 104 +#define EVP_F_EVP_PKEY_DECRYPT_INIT 138 +#define EVP_F_EVP_PKEY_DECRYPT_OLD 151 +#define EVP_F_EVP_PKEY_DERIVE 153 +#define EVP_F_EVP_PKEY_DERIVE_INIT 154 +#define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155 +#define EVP_F_EVP_PKEY_ENCRYPT 105 +#define EVP_F_EVP_PKEY_ENCRYPT_INIT 139 +#define EVP_F_EVP_PKEY_ENCRYPT_OLD 152 +#define EVP_F_EVP_PKEY_GET1_DH 119 +#define EVP_F_EVP_PKEY_GET1_DSA 120 +#define EVP_F_EVP_PKEY_GET1_ECDSA 130 +#define EVP_F_EVP_PKEY_GET1_EC_KEY 131 +#define EVP_F_EVP_PKEY_GET1_RSA 121 +#define EVP_F_EVP_PKEY_KEYGEN 146 +#define EVP_F_EVP_PKEY_KEYGEN_INIT 147 +#define EVP_F_EVP_PKEY_NEW 106 +#define EVP_F_EVP_PKEY_PARAMGEN 148 +#define EVP_F_EVP_PKEY_PARAMGEN_INIT 149 +#define EVP_F_EVP_PKEY_SIGN 140 +#define EVP_F_EVP_PKEY_SIGN_INIT 141 +#define EVP_F_EVP_PKEY_VERIFY 142 +#define EVP_F_EVP_PKEY_VERIFY_INIT 143 +#define EVP_F_EVP_PKEY_VERIFY_RECOVER 144 +#define EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT 145 +#define EVP_F_EVP_RIJNDAEL 126 +#define EVP_F_EVP_SIGNFINAL 107 +#define EVP_F_EVP_VERIFYFINAL 108 +#define EVP_F_FIPS_CIPHERINIT 166 +#define EVP_F_FIPS_CIPHER_CTX_COPY 170 +#define EVP_F_FIPS_CIPHER_CTX_CTRL 167 +#define EVP_F_FIPS_CIPHER_CTX_SET_KEY_LENGTH 171 +#define EVP_F_FIPS_DIGESTINIT 168 +#define EVP_F_FIPS_MD_CTX_COPY 169 +#define EVP_F_HMAC_INIT_EX 174 +#define EVP_F_INT_CTX_NEW 157 +#define EVP_F_PKCS5_PBE_KEYIVGEN 117 +#define EVP_F_PKCS5_V2_PBE_KEYIVGEN 118 +#define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN 164 +#define EVP_F_PKCS8_SET_BROKEN 112 +#define EVP_F_PKEY_SET_TYPE 158 +#define EVP_F_RC2_GET_ASN1_TYPE_AND_IV 197 +#define EVP_F_RC2_MAGIC_TO_METH 109 +#define EVP_F_RC5_CTRL 125 + +/* Reason codes. */ +#define EVP_R_AES_IV_SETUP_FAILED 162 +#define EVP_R_AES_KEY_SETUP_FAILED 143 +#define EVP_R_ASN1_LIB 140 +#define EVP_R_BAD_BLOCK_LENGTH 136 +#define EVP_R_BAD_DECRYPT 100 +#define EVP_R_BAD_KEY_LENGTH 137 +#define EVP_R_BN_DECODE_ERROR 112 +#define EVP_R_BN_PUBKEY_ERROR 113 +#define EVP_R_BUFFER_TOO_SMALL 155 +#define EVP_R_CAMELLIA_KEY_SETUP_FAILED 157 +#define EVP_R_CIPHER_PARAMETER_ERROR 122 +#define EVP_R_COMMAND_NOT_SUPPORTED 147 +#define EVP_R_CTRL_NOT_IMPLEMENTED 132 +#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED 133 +#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138 +#define EVP_R_DECODE_ERROR 114 +#define EVP_R_DIFFERENT_KEY_TYPES 101 +#define EVP_R_DIFFERENT_PARAMETERS 153 +#define EVP_R_DISABLED_FOR_FIPS 163 +#define EVP_R_ENCODE_ERROR 115 +#define EVP_R_ERROR_LOADING_SECTION 165 +#define EVP_R_ERROR_SETTING_FIPS_MODE 166 +#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119 +#define EVP_R_EXPECTING_AN_HMAC_KEY 174 +#define EVP_R_EXPECTING_AN_RSA_KEY 127 +#define EVP_R_EXPECTING_A_DH_KEY 128 +#define EVP_R_EXPECTING_A_DSA_KEY 129 +#define EVP_R_EXPECTING_A_ECDSA_KEY 141 +#define EVP_R_EXPECTING_A_EC_KEY 142 +#define EVP_R_FIPS_MODE_NOT_SUPPORTED 167 +#define EVP_R_GET_RAW_KEY_FAILED 182 +#define EVP_R_INITIALIZATION_ERROR 134 +#define EVP_R_INPUT_NOT_INITIALIZED 111 +#define EVP_R_INVALID_DIGEST 152 +#define EVP_R_INVALID_FIPS_MODE 168 +#define EVP_R_INVALID_IV_LENGTH 194 +#define EVP_R_INVALID_KEY_LENGTH 130 +#define EVP_R_INVALID_OPERATION 148 +#define EVP_R_IV_TOO_LARGE 102 +#define EVP_R_KEYGEN_FAILURE 120 +#define EVP_R_KEY_SETUP_FAILED 180 +#define EVP_R_MESSAGE_DIGEST_IS_NULL 159 +#define EVP_R_METHOD_NOT_SUPPORTED 144 +#define EVP_R_MISSING_PARAMETERS 103 +#define EVP_R_NO_CIPHER_SET 131 +#define EVP_R_NO_DEFAULT_DIGEST 158 +#define EVP_R_NO_DIGEST_SET 139 +#define EVP_R_NO_DSA_PARAMETERS 116 +#define EVP_R_NO_KEY_SET 154 +#define EVP_R_NO_OPERATION_SET 149 +#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104 +#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105 +#define EVP_R_ONLY_ONESHOT_SUPPORTED 177 +#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 150 +#define EVP_R_OPERATON_NOT_INITIALIZED 151 +#define EVP_R_OUTPUT_ALIASES_INPUT 172 +#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE 117 +#define EVP_R_PRIVATE_KEY_DECODE_ERROR 145 +#define EVP_R_PRIVATE_KEY_ENCODE_ERROR 146 +#define EVP_R_PUBLIC_KEY_NOT_RSA 106 +#define EVP_R_TAG_TOO_LARGE 171 +#define EVP_R_TOO_LARGE 164 +#define EVP_R_UNKNOWN_CIPHER 160 +#define EVP_R_UNKNOWN_DIGEST 161 +#define EVP_R_UNKNOWN_OPTION 169 +#define EVP_R_UNKNOWN_PBE_ALGORITHM 121 +#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS 135 +#define EVP_R_UNSUPPORTED_ALGORITHM 156 +#define EVP_R_UNSUPPORTED_CIPHER 107 +#define EVP_R_UNSUPPORTED_KEYLENGTH 123 +#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION 124 +#define EVP_R_UNSUPPORTED_KEY_SIZE 108 +#define EVP_R_UNSUPPORTED_PRF 125 +#define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM 118 +#define EVP_R_WRAP_MODE_NOT_ALLOWED 170 +#define EVP_R_UNSUPPORTED_SALT_TYPE 126 +#define EVP_R_WRONG_FINAL_BLOCK_LENGTH 109 +#define EVP_R_WRONG_PUBLIC_KEY_TYPE 110 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/gost.h b/include/openssl/gost.h new file mode 100644 index 0000000..c7d9d25 --- /dev/null +++ b/include/openssl/gost.h @@ -0,0 +1,262 @@ +/* $OpenBSD: gost.h,v 1.4 2022/07/12 14:42:49 kn Exp $ */ +/* + * Copyright (c) 2014 Dmitry Eremin-Solenikov + * Copyright (c) 2005-2006 Cryptocom LTD + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_GOST_H +#define HEADER_GOST_H + +#include + +#ifdef OPENSSL_NO_GOST +#error GOST is disabled. +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct gost2814789_key_st { + unsigned int key[8]; + unsigned int k87[256],k65[256],k43[256],k21[256]; + unsigned int count; + unsigned key_meshing : 1; +} GOST2814789_KEY; + +int Gost2814789_set_sbox(GOST2814789_KEY *key, int nid); +int Gost2814789_set_key(GOST2814789_KEY *key, + const unsigned char *userKey, const int bits); +void Gost2814789_ecb_encrypt(const unsigned char *in, unsigned char *out, + GOST2814789_KEY *key, const int enc); +void Gost2814789_cfb64_encrypt(const unsigned char *in, unsigned char *out, + size_t length, GOST2814789_KEY *key, + unsigned char *ivec, int *num, const int enc); +void Gost2814789_cnt_encrypt(const unsigned char *in, unsigned char *out, + size_t length, GOST2814789_KEY *key, + unsigned char *ivec, unsigned char *cnt_buf, int *num); + +typedef struct { + ASN1_OCTET_STRING *iv; + ASN1_OBJECT *enc_param_set; +} GOST_CIPHER_PARAMS; + +GOST_CIPHER_PARAMS *GOST_CIPHER_PARAMS_new(void); +void GOST_CIPHER_PARAMS_free(GOST_CIPHER_PARAMS *a); +GOST_CIPHER_PARAMS *d2i_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS **a, const unsigned char **in, long len); +int i2d_GOST_CIPHER_PARAMS(GOST_CIPHER_PARAMS *a, unsigned char **out); +extern const ASN1_ITEM GOST_CIPHER_PARAMS_it; + +#define GOST2814789IMIT_LENGTH 4 +#define GOST2814789IMIT_CBLOCK 8 +#define GOST2814789IMIT_LONG unsigned int + +typedef struct GOST2814789IMITstate_st { + GOST2814789IMIT_LONG Nl, Nh; + unsigned char data[GOST2814789IMIT_CBLOCK]; + unsigned int num; + + GOST2814789_KEY cipher; + unsigned char mac[GOST2814789IMIT_CBLOCK]; +} GOST2814789IMIT_CTX; + +/* Note, also removed second parameter and removed dctx->cipher setting */ +int GOST2814789IMIT_Init(GOST2814789IMIT_CTX *c, int nid); +int GOST2814789IMIT_Update(GOST2814789IMIT_CTX *c, const void *data, size_t len); +int GOST2814789IMIT_Final(unsigned char *md, GOST2814789IMIT_CTX *c); +void GOST2814789IMIT_Transform(GOST2814789IMIT_CTX *c, const unsigned char *data); +unsigned char *GOST2814789IMIT(const unsigned char *d, size_t n, + unsigned char *md, int nid, + const unsigned char *key, const unsigned char *iv); + +#define GOSTR341194_LONG unsigned int + +#define GOSTR341194_LENGTH 32 +#define GOSTR341194_CBLOCK 32 +#define GOSTR341194_LBLOCK (GOSTR341194_CBLOCK/4) + +typedef struct GOSTR341194state_st { + GOSTR341194_LONG Nl, Nh; + GOSTR341194_LONG data[GOSTR341194_LBLOCK]; + unsigned int num; + + GOST2814789_KEY cipher; + unsigned char H[GOSTR341194_CBLOCK]; + unsigned char S[GOSTR341194_CBLOCK]; +} GOSTR341194_CTX; + +/* Note, also removed second parameter and removed dctx->cipher setting */ +int GOSTR341194_Init(GOSTR341194_CTX *c, int nid); +int GOSTR341194_Update(GOSTR341194_CTX *c, const void *data, size_t len); +int GOSTR341194_Final(unsigned char *md, GOSTR341194_CTX *c); +void GOSTR341194_Transform(GOSTR341194_CTX *c, const unsigned char *data); +unsigned char *GOSTR341194(const unsigned char *d, size_t n,unsigned char *md, int nid); + +#if defined(_LP64) +#define STREEBOG_LONG64 unsigned long +#define U64(C) C##UL +#else +#define STREEBOG_LONG64 unsigned long long +#define U64(C) C##ULL +#endif + +#define STREEBOG_LBLOCK 8 +#define STREEBOG_CBLOCK 64 +#define STREEBOG256_LENGTH 32 +#define STREEBOG512_LENGTH 64 + +typedef struct STREEBOGstate_st { + STREEBOG_LONG64 data[STREEBOG_LBLOCK]; + unsigned int num; + unsigned int md_len; + STREEBOG_LONG64 h[STREEBOG_LBLOCK]; + STREEBOG_LONG64 N[STREEBOG_LBLOCK]; + STREEBOG_LONG64 Sigma[STREEBOG_LBLOCK]; +} STREEBOG_CTX; + +int STREEBOG256_Init(STREEBOG_CTX *c); +int STREEBOG256_Update(STREEBOG_CTX *c, const void *data, size_t len); +int STREEBOG256_Final(unsigned char *md, STREEBOG_CTX *c); +void STREEBOG256_Transform(STREEBOG_CTX *c, const unsigned char *data); +unsigned char *STREEBOG256(const unsigned char *d, size_t n,unsigned char *md); + +int STREEBOG512_Init(STREEBOG_CTX *c); +int STREEBOG512_Update(STREEBOG_CTX *c, const void *data, size_t len); +int STREEBOG512_Final(unsigned char *md, STREEBOG_CTX *c); +void STREEBOG512_Transform(STREEBOG_CTX *c, const unsigned char *data); +unsigned char *STREEBOG512(const unsigned char *d, size_t n,unsigned char *md); + +typedef struct gost_key_st GOST_KEY; +GOST_KEY *GOST_KEY_new(void); +void GOST_KEY_free(GOST_KEY * r); +int GOST_KEY_check_key(const GOST_KEY * eckey); +int GOST_KEY_set_public_key_affine_coordinates(GOST_KEY * key, BIGNUM * x, BIGNUM * y); +const EC_GROUP * GOST_KEY_get0_group(const GOST_KEY * key); +int GOST_KEY_set_group(GOST_KEY * key, const EC_GROUP * group); +int GOST_KEY_get_digest(const GOST_KEY * key); +int GOST_KEY_set_digest(GOST_KEY * key, int digest_nid); +const BIGNUM * GOST_KEY_get0_private_key(const GOST_KEY * key); +int GOST_KEY_set_private_key(GOST_KEY * key, const BIGNUM * priv_key); +const EC_POINT * GOST_KEY_get0_public_key(const GOST_KEY * key); +int GOST_KEY_set_public_key(GOST_KEY * key, const EC_POINT * pub_key); +size_t GOST_KEY_get_size(const GOST_KEY * r); + +/* Gost-specific pmeth control-function parameters */ +/* For GOST R34.10 parameters */ +#define EVP_PKEY_CTRL_GOST_PARAMSET (EVP_PKEY_ALG_CTRL+1) +#define EVP_PKEY_CTRL_GOST_SIG_FORMAT (EVP_PKEY_ALG_CTRL+2) +#define EVP_PKEY_CTRL_GOST_SET_DIGEST (EVP_PKEY_ALG_CTRL+3) +#define EVP_PKEY_CTRL_GOST_GET_DIGEST (EVP_PKEY_ALG_CTRL+4) + +#define GOST_SIG_FORMAT_SR_BE 0 +#define GOST_SIG_FORMAT_RS_LE 1 + +void ERR_load_GOST_strings(void); + +/* Error codes for the GOST functions. */ + +/* Function codes. */ +#define GOST_F_DECODE_GOST01_ALGOR_PARAMS 104 +#define GOST_F_ENCODE_GOST01_ALGOR_PARAMS 105 +#define GOST_F_GOST2001_COMPUTE_PUBLIC 106 +#define GOST_F_GOST2001_DO_SIGN 107 +#define GOST_F_GOST2001_DO_VERIFY 108 +#define GOST_F_GOST2001_KEYGEN 109 +#define GOST_F_GOST89_GET_ASN1_PARAMETERS 102 +#define GOST_F_GOST89_SET_ASN1_PARAMETERS 103 +#define GOST_F_GOST_KEY_CHECK_KEY 124 +#define GOST_F_GOST_KEY_NEW 125 +#define GOST_F_GOST_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES 126 +#define GOST_F_PARAM_COPY_GOST01 110 +#define GOST_F_PARAM_DECODE_GOST01 111 +#define GOST_F_PKEY_GOST01_CTRL 116 +#define GOST_F_PKEY_GOST01_DECRYPT 112 +#define GOST_F_PKEY_GOST01_DERIVE 113 +#define GOST_F_PKEY_GOST01_ENCRYPT 114 +#define GOST_F_PKEY_GOST01_PARAMGEN 115 +#define GOST_F_PKEY_GOST01_SIGN 123 +#define GOST_F_PKEY_GOST_MAC_CTRL 100 +#define GOST_F_PKEY_GOST_MAC_KEYGEN 101 +#define GOST_F_PRIV_DECODE_GOST01 117 +#define GOST_F_PUB_DECODE_GOST01 118 +#define GOST_F_PUB_ENCODE_GOST01 119 +#define GOST_F_PUB_PRINT_GOST01 120 +#define GOST_F_UNPACK_SIGNATURE_CP 121 +#define GOST_F_UNPACK_SIGNATURE_LE 122 + +/* Reason codes. */ +#define GOST_R_BAD_KEY_PARAMETERS_FORMAT 104 +#define GOST_R_BAD_PKEY_PARAMETERS_FORMAT 105 +#define GOST_R_CANNOT_PACK_EPHEMERAL_KEY 106 +#define GOST_R_CTRL_CALL_FAILED 107 +#define GOST_R_ERROR_COMPUTING_SHARED_KEY 108 +#define GOST_R_ERROR_PARSING_KEY_TRANSPORT_INFO 109 +#define GOST_R_INCOMPATIBLE_ALGORITHMS 110 +#define GOST_R_INCOMPATIBLE_PEER_KEY 111 +#define GOST_R_INVALID_DIGEST_TYPE 100 +#define GOST_R_INVALID_IV_LENGTH 103 +#define GOST_R_INVALID_MAC_KEY_LENGTH 101 +#define GOST_R_KEY_IS_NOT_INITIALIZED 112 +#define GOST_R_KEY_PARAMETERS_MISSING 113 +#define GOST_R_MAC_KEY_NOT_SET 102 +#define GOST_R_NO_PARAMETERS_SET 115 +#define GOST_R_NO_PEER_KEY 116 +#define GOST_R_NO_PRIVATE_PART_OF_NON_EPHEMERAL_KEYPAIR 117 +#define GOST_R_PUBLIC_KEY_UNDEFINED 118 +#define GOST_R_RANDOM_NUMBER_GENERATOR_FAILED 120 +#define GOST_R_SIGNATURE_MISMATCH 121 +#define GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q 122 +#define GOST_R_UKM_NOT_SET 123 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/hkdf.h b/include/openssl/hkdf.h new file mode 100644 index 0000000..6cec526 --- /dev/null +++ b/include/openssl/hkdf.h @@ -0,0 +1,65 @@ +/* $OpenBSD: hkdf.h,v 1.3 2023/08/11 04:52:08 tb Exp $ */ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#ifndef OPENSSL_HEADER_HKDF_H +#define OPENSSL_HEADER_HKDF_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * HKDF computes HKDF (as specified by RFC 5869) of initial keying + * material |secret| with |salt| and |info| using |digest|, and + * outputs |out_len| bytes to |out_key|. It returns one on success and + * zero on error. + * + * HKDF is an Extract-and-Expand algorithm. It does not do any key + * stretching, and as such, is not suited to be used alone to generate + * a key from a password. + */ + +int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, const uint8_t *salt, + size_t salt_len, const uint8_t *info, size_t info_len); + +/* + * HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from + * initial keying material |secret| and salt |salt| using |digest|, + * and outputs |out_len| bytes to |out_key|. The maximum output size + * is |EVP_MAX_MD_SIZE|. It returns one on success and zero on error. + */ +int HKDF_extract(uint8_t *out_key, size_t *out_len, const EVP_MD *digest, + const uint8_t *secret, size_t secret_len, + const uint8_t *salt, size_t salt_len); + +/* + * HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of + * length |out_len| from the PRK |prk| and info |info| using |digest|, + * and outputs the result to |out_key|. It returns one on success and + * zero on error. + */ +int HKDF_expand(uint8_t *out_key, size_t out_len, + const EVP_MD *digest, const uint8_t *prk, size_t prk_len, + const uint8_t *info, size_t info_len); + + +#if defined(__cplusplus) +} /* extern C */ +#endif + +#endif /* OPENSSL_HEADER_HKDF_H */ diff --git a/include/openssl/hmac.h b/include/openssl/hmac.h new file mode 100644 index 0000000..1ce3652 --- /dev/null +++ b/include/openssl/hmac.h @@ -0,0 +1,98 @@ +/* $OpenBSD: hmac.h,v 1.17 2023/04/25 15:48:48 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#ifndef HEADER_HMAC_H +#define HEADER_HMAC_H + +#include + +#ifdef OPENSSL_NO_HMAC +#error HMAC is disabled. +#endif + +#include + +#define HMAC_MAX_MD_CBLOCK 144 /* largest known is SHA3-224 */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define HMAC_size(e) (EVP_MD_size(HMAC_CTX_get_md((e)))) + +HMAC_CTX *HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX *ctx); +int HMAC_CTX_reset(HMAC_CTX *ctx); + +int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, + const EVP_MD *md); /* deprecated */ +int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md, + ENGINE *impl); +int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len); +int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); +unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, + const unsigned char *d, size_t n, unsigned char *md, unsigned int *md_len); +int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx); + +void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags); +const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/idea.h b/include/openssl/idea.h new file mode 100644 index 0000000..e5ddd3a --- /dev/null +++ b/include/openssl/idea.h @@ -0,0 +1,99 @@ +/* $OpenBSD: idea.h,v 1.11 2023/07/07 12:51:58 beck Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_IDEA_H +#define HEADER_IDEA_H + +#include /* IDEA_INT, OPENSSL_NO_IDEA */ + +#ifdef OPENSSL_NO_IDEA +#error IDEA is disabled. +#endif + +#define IDEA_ENCRYPT 1 +#define IDEA_DECRYPT 0 + +#define IDEA_BLOCK 8 +#define IDEA_KEY_LENGTH 16 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct idea_key_st { + IDEA_INT data[9][6]; +} IDEA_KEY_SCHEDULE; + +const char *idea_options(void); +void idea_ecb_encrypt(const unsigned char *in, unsigned char *out, + IDEA_KEY_SCHEDULE *ks); +void idea_set_encrypt_key(const unsigned char *key, IDEA_KEY_SCHEDULE *ks); +void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *ek, IDEA_KEY_SCHEDULE *dk); +void idea_cbc_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int enc); +void idea_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, + int *num, int enc); +void idea_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, IDEA_KEY_SCHEDULE *ks, unsigned char *iv, int *num); +void idea_encrypt(unsigned long *in, IDEA_KEY_SCHEDULE *ks); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h new file mode 100644 index 0000000..f823bf9 --- /dev/null +++ b/include/openssl/kdf.h @@ -0,0 +1,111 @@ +/* $OpenBSD: kdf.h,v 1.8 2022/07/12 14:42:49 kn Exp $ */ +/* + * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2016-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_KDF_H +# define HEADER_KDF_H + +#ifdef __cplusplus +extern "C" { +#endif + +# define EVP_PKEY_CTRL_HKDF_MD (EVP_PKEY_ALG_CTRL + 3) +# define EVP_PKEY_CTRL_HKDF_SALT (EVP_PKEY_ALG_CTRL + 4) +# define EVP_PKEY_CTRL_HKDF_KEY (EVP_PKEY_ALG_CTRL + 5) +# define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 6) +# define EVP_PKEY_CTRL_HKDF_MODE (EVP_PKEY_ALG_CTRL + 7) + +# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0 +# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY 1 +# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY 2 + +# define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md)) + +# define EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt)) + +# define EVP_PKEY_CTX_set1_hkdf_key(pctx, key, keylen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key)) + +# define EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info)) + +# define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \ + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \ + EVP_PKEY_CTRL_HKDF_MODE, mode, NULL) + +int ERR_load_KDF_strings(void); + +/* + * KDF function codes. + */ +# define KDF_F_PKEY_HKDF_CTRL_STR 103 +# define KDF_F_PKEY_HKDF_DERIVE 102 +# define KDF_F_PKEY_HKDF_INIT 108 + +/* + * KDF reason codes. + */ +# define KDF_R_MISSING_KEY 104 +# define KDF_R_MISSING_MESSAGE_DIGEST 105 +# define KDF_R_UNKNOWN_PARAMETER_TYPE 103 + +# ifdef __cplusplus +} +# endif +#endif diff --git a/include/openssl/lhash.h b/include/openssl/lhash.h new file mode 100644 index 0000000..9c63657 --- /dev/null +++ b/include/openssl/lhash.h @@ -0,0 +1,235 @@ +/* $OpenBSD: lhash.h,v 1.12 2014/06/12 15:49:29 deraadt Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/* Header for dynamic hash table routines + * Author - Eric Young + */ + +#ifndef HEADER_LHASH_H +#define HEADER_LHASH_H + +#include + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct lhash_node_st { + void *data; + struct lhash_node_st *next; +#ifndef OPENSSL_NO_HASH_COMP + unsigned long hash; +#endif +} LHASH_NODE; + +typedef int (*LHASH_COMP_FN_TYPE)(const void *, const void *); +typedef unsigned long (*LHASH_HASH_FN_TYPE)(const void *); +typedef void (*LHASH_DOALL_FN_TYPE)(void *); +typedef void (*LHASH_DOALL_ARG_FN_TYPE)(void *, void *); + +/* Macros for declaring and implementing type-safe wrappers for LHASH callbacks. + * This way, callbacks can be provided to LHASH structures without function + * pointer casting and the macro-defined callbacks provide per-variable casting + * before deferring to the underlying type-specific callbacks. NB: It is + * possible to place a "static" in front of both the DECLARE and IMPLEMENT + * macros if the functions are strictly internal. */ + +/* First: "hash" functions */ +#define DECLARE_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *); +#define IMPLEMENT_LHASH_HASH_FN(name, o_type) \ + unsigned long name##_LHASH_HASH(const void *arg) { \ + const o_type *a = arg; \ + return name##_hash(a); } +#define LHASH_HASH_FN(name) name##_LHASH_HASH + +/* Second: "compare" functions */ +#define DECLARE_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *, const void *); +#define IMPLEMENT_LHASH_COMP_FN(name, o_type) \ + int name##_LHASH_COMP(const void *arg1, const void *arg2) { \ + const o_type *a = arg1; \ + const o_type *b = arg2; \ + return name##_cmp(a,b); } +#define LHASH_COMP_FN(name) name##_LHASH_COMP + +/* Third: "doall" functions */ +#define DECLARE_LHASH_DOALL_FN(name, o_type) \ + void name##_LHASH_DOALL(void *); +#define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \ + void name##_LHASH_DOALL(void *arg) { \ + o_type *a = arg; \ + name##_doall(a); } +#define LHASH_DOALL_FN(name) name##_LHASH_DOALL + +/* Fourth: "doall_arg" functions */ +#define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *, void *); +#define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \ + void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \ + o_type *a = arg1; \ + a_type *b = arg2; \ + name##_doall_arg(a, b); } +#define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG + +typedef struct lhash_st { + LHASH_NODE **b; + LHASH_COMP_FN_TYPE comp; + LHASH_HASH_FN_TYPE hash; + unsigned int num_nodes; + unsigned int num_alloc_nodes; + unsigned int p; + unsigned int pmax; + 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; + unsigned long num_hash_calls; + unsigned long num_comp_calls; + unsigned long num_insert; + unsigned long num_replace; + unsigned long num_delete; + unsigned long num_no_delete; + unsigned long num_retrieve; + unsigned long num_retrieve_miss; + unsigned long num_hash_comps; + + int error; +} _LHASH; /* Do not use _LHASH directly, use LHASH_OF + * and friends */ + +#define LH_LOAD_MULT 256 + +/* Indicates a malloc() error in the last call, this is only bad + * in lh_insert(). */ +#define lh_error(lh) ((lh)->error) + +_LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c); +void lh_free(_LHASH *lh); +void *lh_insert(_LHASH *lh, void *data); +void *lh_delete(_LHASH *lh, const void *data); +void *lh_retrieve(_LHASH *lh, const void *data); +void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func); +void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg); +unsigned long lh_strhash(const char *c); +unsigned long lh_num_items(const _LHASH *lh); + +void lh_stats(const _LHASH *lh, FILE *out); +void lh_node_stats(const _LHASH *lh, FILE *out); +void lh_node_usage_stats(const _LHASH *lh, FILE *out); + +#ifndef OPENSSL_NO_BIO +void lh_stats_bio(const _LHASH *lh, BIO *out); +void lh_node_stats_bio(const _LHASH *lh, BIO *out); +void lh_node_usage_stats_bio(const _LHASH *lh, BIO *out); +#endif + +/* Type checking... */ + +#define LHASH_OF(type) struct lhash_st_##type + +#define DECLARE_LHASH_OF(type) LHASH_OF(type) { int dummy; } + +#define CHECKED_LHASH_OF(type,lh) \ + ((_LHASH *)CHECKED_PTR_OF(LHASH_OF(type),lh)) + +/* Define wrapper functions. */ +#define LHM_lh_new(type, name) \ + ((LHASH_OF(type) *)lh_new(LHASH_HASH_FN(name), LHASH_COMP_FN(name))) +#define LHM_lh_error(type, lh) \ + lh_error(CHECKED_LHASH_OF(type,lh)) +#define LHM_lh_insert(type, lh, inst) \ + ((type *)lh_insert(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +#define LHM_lh_retrieve(type, lh, inst) \ + ((type *)lh_retrieve(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +#define LHM_lh_delete(type, lh, inst) \ + ((type *)lh_delete(CHECKED_LHASH_OF(type, lh), \ + CHECKED_PTR_OF(type, inst))) +#define LHM_lh_doall(type, lh,fn) lh_doall(CHECKED_LHASH_OF(type, lh), fn) +#define LHM_lh_doall_arg(type, lh, fn, arg_type, arg) \ + lh_doall_arg(CHECKED_LHASH_OF(type, lh), fn, CHECKED_PTR_OF(arg_type, arg)) +#define LHM_lh_num_items(type, lh) lh_num_items(CHECKED_LHASH_OF(type, lh)) +#define LHM_lh_down_load(type, lh) (CHECKED_LHASH_OF(type, lh)->down_load) +#define LHM_lh_node_stats_bio(type, lh, out) \ + lh_node_stats_bio(CHECKED_LHASH_OF(type, lh), out) +#define LHM_lh_node_usage_stats_bio(type, lh, out) \ + lh_node_usage_stats_bio(CHECKED_LHASH_OF(type, lh), out) +#define LHM_lh_stats_bio(type, lh, out) \ + lh_stats_bio(CHECKED_LHASH_OF(type, lh), out) +#define LHM_lh_free(type, lh) lh_free(CHECKED_LHASH_OF(type, lh)) + +DECLARE_LHASH_OF(OPENSSL_STRING); +DECLARE_LHASH_OF(OPENSSL_CSTRING); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/md4.h b/include/openssl/md4.h new file mode 100644 index 0000000..cb4f3cb --- /dev/null +++ b/include/openssl/md4.h @@ -0,0 +1,102 @@ +/* $OpenBSD: md4.h,v 1.17 2023/07/08 06:47:26 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#ifndef HEADER_MD4_H +#define HEADER_MD4_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_MD4 +#error MD4 is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD4_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#define MD4_LONG unsigned int + +#define MD4_CBLOCK 64 +#define MD4_LBLOCK (MD4_CBLOCK/4) +#define MD4_DIGEST_LENGTH 16 + +typedef struct MD4state_st { + MD4_LONG A, B,C, D; + MD4_LONG Nl, Nh; + MD4_LONG data[MD4_LBLOCK]; + unsigned int num; +} MD4_CTX; + +int MD4_Init(MD4_CTX *c); +int MD4_Update(MD4_CTX *c, const void *data, size_t len); +int MD4_Final(unsigned char *md, MD4_CTX *c); +unsigned char *MD4(const unsigned char *d, size_t n, unsigned char *md); +void MD4_Transform(MD4_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/md5.h b/include/openssl/md5.h new file mode 100644 index 0000000..d248c93 --- /dev/null +++ b/include/openssl/md5.h @@ -0,0 +1,107 @@ +/* $OpenBSD: md5.h,v 1.21 2023/07/08 06:50:38 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#ifndef HEADER_MD5_H +#define HEADER_MD5_H +#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__OpenBSD__) +#define __bounded__(x, y, z) +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_MD5 +#error MD5 is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! MD5_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#define MD5_LONG unsigned int + +#define MD5_CBLOCK 64 +#define MD5_LBLOCK (MD5_CBLOCK/4) +#define MD5_DIGEST_LENGTH 16 + +typedef struct MD5state_st { + MD5_LONG A, B,C, D; + MD5_LONG Nl, Nh; + MD5_LONG data[MD5_LBLOCK]; + unsigned int num; +} MD5_CTX; + +int MD5_Init(MD5_CTX *c); +int MD5_Update(MD5_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int MD5_Final(unsigned char *md, MD5_CTX *c); +unsigned char *MD5(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +void MD5_Transform(MD5_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/modes.h b/include/openssl/modes.h new file mode 100644 index 0000000..53fa9af --- /dev/null +++ b/include/openssl/modes.h @@ -0,0 +1,118 @@ +/* $OpenBSD: modes.h,v 1.6 2023/07/08 14:55:36 beck Exp $ */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Rights for redistribution and usage in source and binary + * forms are granted according to the OpenSSL license. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*block128_f)(const unsigned char in[16], + unsigned char out[16], + const void *key); + +typedef void (*cbc128_f)(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int enc); + +typedef void (*ctr128_f)(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16]); + +typedef void (*ccm128_f)(const unsigned char *in, unsigned char *out, + size_t blocks, const void *key, + const unsigned char ivec[16], unsigned char cmac[16]); + +void CRYPTO_cbc128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); +void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], block128_f block); + +void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], unsigned char ecount_buf[16], + unsigned int *num, block128_f block); + +void CRYPTO_ctr128_encrypt_ctr32(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], unsigned char ecount_buf[16], + unsigned int *num, ctr128_f ctr); + +void CRYPTO_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + block128_f block); + +void CRYPTO_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out, + size_t length, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); +void CRYPTO_cfb128_1_encrypt(const unsigned char *in, unsigned char *out, + size_t bits, const void *key, + unsigned char ivec[16], int *num, + int enc, block128_f block); + +typedef struct gcm128_context GCM128_CONTEXT; + +GCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block); +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); +int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const unsigned char *aad, + size_t len); +int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len); +int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, + const unsigned char *in, unsigned char *out, + size_t len, ctr128_f stream); +int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const unsigned char *tag, + size_t len); +void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len); +void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx); + +typedef struct ccm128_context CCM128_CONTEXT; + +void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, + unsigned int M, unsigned int L, void *key, block128_f block); +int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, + const unsigned char *nonce, size_t nlen, size_t mlen); +void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, + const unsigned char *aad, size_t alen); +int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len); +int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len); +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len, + ccm128_f stream); +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, size_t len, + ccm128_f stream); +size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len); + +typedef struct xts128_context XTS128_CONTEXT; + +int CRYPTO_xts128_encrypt(const XTS128_CONTEXT *ctx, const unsigned char iv[16], + const unsigned char *inp, unsigned char *out, size_t len, int enc); + +#ifdef __cplusplus +} +#endif diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h new file mode 100644 index 0000000..51cd083 --- /dev/null +++ b/include/openssl/obj_mac.h @@ -0,0 +1,4630 @@ +/* crypto/objects/obj_mac.h */ + +/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the + * following command: + * perl objects.pl objects.txt obj_mac.num obj_mac.h + */ + +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#define SN_undef "UNDEF" +#define LN_undef "undefined" +#define NID_undef 0 +#define OBJ_undef 0L + +#define SN_itu_t "ITU-T" +#define LN_itu_t "itu-t" +#define NID_itu_t 645 +#define OBJ_itu_t 0L + +#define NID_ccitt 404 +#define OBJ_ccitt OBJ_itu_t + +#define SN_iso "ISO" +#define LN_iso "iso" +#define NID_iso 181 +#define OBJ_iso 1L + +#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T" +#define LN_joint_iso_itu_t "joint-iso-itu-t" +#define NID_joint_iso_itu_t 646 +#define OBJ_joint_iso_itu_t 2L + +#define NID_joint_iso_ccitt 393 +#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t + +#define SN_member_body "member-body" +#define LN_member_body "ISO Member Body" +#define NID_member_body 182 +#define OBJ_member_body OBJ_iso,2L + +#define SN_identified_organization "identified-organization" +#define NID_identified_organization 676 +#define OBJ_identified_organization OBJ_iso,3L + +#define SN_hmac_md5 "HMAC-MD5" +#define LN_hmac_md5 "hmac-md5" +#define NID_hmac_md5 780 +#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L + +#define SN_hmac_sha1 "HMAC-SHA1" +#define LN_hmac_sha1 "hmac-sha1" +#define NID_hmac_sha1 781 +#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L + +#define SN_certicom_arc "certicom-arc" +#define NID_certicom_arc 677 +#define OBJ_certicom_arc OBJ_identified_organization,132L + +#define SN_international_organizations "international-organizations" +#define LN_international_organizations "International Organizations" +#define NID_international_organizations 647 +#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L + +#define SN_wap "wap" +#define NID_wap 678 +#define OBJ_wap OBJ_international_organizations,43L + +#define SN_wap_wsg "wap-wsg" +#define NID_wap_wsg 679 +#define OBJ_wap_wsg OBJ_wap,1L + +#define SN_selected_attribute_types "selected-attribute-types" +#define LN_selected_attribute_types "Selected Attribute Types" +#define NID_selected_attribute_types 394 +#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L + +#define SN_clearance "clearance" +#define NID_clearance 395 +#define OBJ_clearance OBJ_selected_attribute_types,55L + +#define SN_ISO_US "ISO-US" +#define LN_ISO_US "ISO US Member Body" +#define NID_ISO_US 183 +#define OBJ_ISO_US OBJ_member_body,840L + +#define SN_X9_57 "X9-57" +#define LN_X9_57 "X9.57" +#define NID_X9_57 184 +#define OBJ_X9_57 OBJ_ISO_US,10040L + +#define SN_X9cm "X9cm" +#define LN_X9cm "X9.57 CM ?" +#define NID_X9cm 185 +#define OBJ_X9cm OBJ_X9_57,4L + +#define SN_dsa "DSA" +#define LN_dsa "dsaEncryption" +#define NID_dsa 116 +#define OBJ_dsa OBJ_X9cm,1L + +#define SN_dsaWithSHA1 "DSA-SHA1" +#define LN_dsaWithSHA1 "dsaWithSHA1" +#define NID_dsaWithSHA1 113 +#define OBJ_dsaWithSHA1 OBJ_X9cm,3L + +#define SN_ansi_X9_62 "ansi-X9-62" +#define LN_ansi_X9_62 "ANSI X9.62" +#define NID_ansi_X9_62 405 +#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L + +#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L + +#define SN_X9_62_prime_field "prime-field" +#define NID_X9_62_prime_field 406 +#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L + +#define SN_X9_62_characteristic_two_field "characteristic-two-field" +#define NID_X9_62_characteristic_two_field 407 +#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L + +#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis" +#define NID_X9_62_id_characteristic_two_basis 680 +#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L + +#define SN_X9_62_onBasis "onBasis" +#define NID_X9_62_onBasis 681 +#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L + +#define SN_X9_62_tpBasis "tpBasis" +#define NID_X9_62_tpBasis 682 +#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L + +#define SN_X9_62_ppBasis "ppBasis" +#define NID_X9_62_ppBasis 683 +#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L + +#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L + +#define SN_X9_62_id_ecPublicKey "id-ecPublicKey" +#define NID_X9_62_id_ecPublicKey 408 +#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L + +#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L + +#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L + +#define SN_X9_62_c2pnb163v1 "c2pnb163v1" +#define NID_X9_62_c2pnb163v1 684 +#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L + +#define SN_X9_62_c2pnb163v2 "c2pnb163v2" +#define NID_X9_62_c2pnb163v2 685 +#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L + +#define SN_X9_62_c2pnb163v3 "c2pnb163v3" +#define NID_X9_62_c2pnb163v3 686 +#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L + +#define SN_X9_62_c2pnb176v1 "c2pnb176v1" +#define NID_X9_62_c2pnb176v1 687 +#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L + +#define SN_X9_62_c2tnb191v1 "c2tnb191v1" +#define NID_X9_62_c2tnb191v1 688 +#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L + +#define SN_X9_62_c2tnb191v2 "c2tnb191v2" +#define NID_X9_62_c2tnb191v2 689 +#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L + +#define SN_X9_62_c2tnb191v3 "c2tnb191v3" +#define NID_X9_62_c2tnb191v3 690 +#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L + +#define SN_X9_62_c2onb191v4 "c2onb191v4" +#define NID_X9_62_c2onb191v4 691 +#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L + +#define SN_X9_62_c2onb191v5 "c2onb191v5" +#define NID_X9_62_c2onb191v5 692 +#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L + +#define SN_X9_62_c2pnb208w1 "c2pnb208w1" +#define NID_X9_62_c2pnb208w1 693 +#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L + +#define SN_X9_62_c2tnb239v1 "c2tnb239v1" +#define NID_X9_62_c2tnb239v1 694 +#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L + +#define SN_X9_62_c2tnb239v2 "c2tnb239v2" +#define NID_X9_62_c2tnb239v2 695 +#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L + +#define SN_X9_62_c2tnb239v3 "c2tnb239v3" +#define NID_X9_62_c2tnb239v3 696 +#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L + +#define SN_X9_62_c2onb239v4 "c2onb239v4" +#define NID_X9_62_c2onb239v4 697 +#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L + +#define SN_X9_62_c2onb239v5 "c2onb239v5" +#define NID_X9_62_c2onb239v5 698 +#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L + +#define SN_X9_62_c2pnb272w1 "c2pnb272w1" +#define NID_X9_62_c2pnb272w1 699 +#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L + +#define SN_X9_62_c2pnb304w1 "c2pnb304w1" +#define NID_X9_62_c2pnb304w1 700 +#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L + +#define SN_X9_62_c2tnb359v1 "c2tnb359v1" +#define NID_X9_62_c2tnb359v1 701 +#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L + +#define SN_X9_62_c2pnb368w1 "c2pnb368w1" +#define NID_X9_62_c2pnb368w1 702 +#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L + +#define SN_X9_62_c2tnb431r1 "c2tnb431r1" +#define NID_X9_62_c2tnb431r1 703 +#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L + +#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L + +#define SN_X9_62_prime192v1 "prime192v1" +#define NID_X9_62_prime192v1 409 +#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L + +#define SN_X9_62_prime192v2 "prime192v2" +#define NID_X9_62_prime192v2 410 +#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L + +#define SN_X9_62_prime192v3 "prime192v3" +#define NID_X9_62_prime192v3 411 +#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L + +#define SN_X9_62_prime239v1 "prime239v1" +#define NID_X9_62_prime239v1 412 +#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L + +#define SN_X9_62_prime239v2 "prime239v2" +#define NID_X9_62_prime239v2 413 +#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L + +#define SN_X9_62_prime239v3 "prime239v3" +#define NID_X9_62_prime239v3 414 +#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L + +#define SN_X9_62_prime256v1 "prime256v1" +#define NID_X9_62_prime256v1 415 +#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L + +#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L + +#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1" +#define NID_ecdsa_with_SHA1 416 +#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L + +#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended" +#define NID_ecdsa_with_Recommended 791 +#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L + +#define SN_ecdsa_with_Specified "ecdsa-with-Specified" +#define NID_ecdsa_with_Specified 792 +#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L + +#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224" +#define NID_ecdsa_with_SHA224 793 +#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L + +#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256" +#define NID_ecdsa_with_SHA256 794 +#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L + +#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384" +#define NID_ecdsa_with_SHA384 795 +#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L + +#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512" +#define NID_ecdsa_with_SHA512 796 +#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L + +#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L + +#define SN_secp112r1 "secp112r1" +#define NID_secp112r1 704 +#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L + +#define SN_secp112r2 "secp112r2" +#define NID_secp112r2 705 +#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L + +#define SN_secp128r1 "secp128r1" +#define NID_secp128r1 706 +#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L + +#define SN_secp128r2 "secp128r2" +#define NID_secp128r2 707 +#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L + +#define SN_secp160k1 "secp160k1" +#define NID_secp160k1 708 +#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L + +#define SN_secp160r1 "secp160r1" +#define NID_secp160r1 709 +#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L + +#define SN_secp160r2 "secp160r2" +#define NID_secp160r2 710 +#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L + +#define SN_secp192k1 "secp192k1" +#define NID_secp192k1 711 +#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L + +#define SN_secp224k1 "secp224k1" +#define NID_secp224k1 712 +#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L + +#define SN_secp224r1 "secp224r1" +#define NID_secp224r1 713 +#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L + +#define SN_secp256k1 "secp256k1" +#define NID_secp256k1 714 +#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L + +#define SN_secp384r1 "secp384r1" +#define NID_secp384r1 715 +#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L + +#define SN_secp521r1 "secp521r1" +#define NID_secp521r1 716 +#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L + +#define SN_sect113r1 "sect113r1" +#define NID_sect113r1 717 +#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L + +#define SN_sect113r2 "sect113r2" +#define NID_sect113r2 718 +#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L + +#define SN_sect131r1 "sect131r1" +#define NID_sect131r1 719 +#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L + +#define SN_sect131r2 "sect131r2" +#define NID_sect131r2 720 +#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L + +#define SN_sect163k1 "sect163k1" +#define NID_sect163k1 721 +#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L + +#define SN_sect163r1 "sect163r1" +#define NID_sect163r1 722 +#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L + +#define SN_sect163r2 "sect163r2" +#define NID_sect163r2 723 +#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L + +#define SN_sect193r1 "sect193r1" +#define NID_sect193r1 724 +#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L + +#define SN_sect193r2 "sect193r2" +#define NID_sect193r2 725 +#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L + +#define SN_sect233k1 "sect233k1" +#define NID_sect233k1 726 +#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L + +#define SN_sect233r1 "sect233r1" +#define NID_sect233r1 727 +#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L + +#define SN_sect239k1 "sect239k1" +#define NID_sect239k1 728 +#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L + +#define SN_sect283k1 "sect283k1" +#define NID_sect283k1 729 +#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L + +#define SN_sect283r1 "sect283r1" +#define NID_sect283r1 730 +#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L + +#define SN_sect409k1 "sect409k1" +#define NID_sect409k1 731 +#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L + +#define SN_sect409r1 "sect409r1" +#define NID_sect409r1 732 +#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L + +#define SN_sect571k1 "sect571k1" +#define NID_sect571k1 733 +#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L + +#define SN_sect571r1 "sect571r1" +#define NID_sect571r1 734 +#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L + +#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L + +#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1" +#define NID_wap_wsg_idm_ecid_wtls1 735 +#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L + +#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3" +#define NID_wap_wsg_idm_ecid_wtls3 736 +#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L + +#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4" +#define NID_wap_wsg_idm_ecid_wtls4 737 +#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L + +#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5" +#define NID_wap_wsg_idm_ecid_wtls5 738 +#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L + +#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6" +#define NID_wap_wsg_idm_ecid_wtls6 739 +#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L + +#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7" +#define NID_wap_wsg_idm_ecid_wtls7 740 +#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L + +#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8" +#define NID_wap_wsg_idm_ecid_wtls8 741 +#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L + +#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9" +#define NID_wap_wsg_idm_ecid_wtls9 742 +#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L + +#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10" +#define NID_wap_wsg_idm_ecid_wtls10 743 +#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L + +#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11" +#define NID_wap_wsg_idm_ecid_wtls11 744 +#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L + +#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12" +#define NID_wap_wsg_idm_ecid_wtls12 745 +#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L + +#define SN_cast5_cbc "CAST5-CBC" +#define LN_cast5_cbc "cast5-cbc" +#define NID_cast5_cbc 108 +#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L + +#define SN_cast5_ecb "CAST5-ECB" +#define LN_cast5_ecb "cast5-ecb" +#define NID_cast5_ecb 109 + +#define SN_cast5_cfb64 "CAST5-CFB" +#define LN_cast5_cfb64 "cast5-cfb" +#define NID_cast5_cfb64 110 + +#define SN_cast5_ofb64 "CAST5-OFB" +#define LN_cast5_ofb64 "cast5-ofb" +#define NID_cast5_ofb64 111 + +#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC" +#define NID_pbeWithMD5AndCast5_CBC 112 +#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L + +#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC" +#define LN_id_PasswordBasedMAC "password based MAC" +#define NID_id_PasswordBasedMAC 782 +#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L + +#define SN_id_DHBasedMac "id-DHBasedMac" +#define LN_id_DHBasedMac "Diffie-Hellman based MAC" +#define NID_id_DHBasedMac 783 +#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L + +#define SN_rsadsi "rsadsi" +#define LN_rsadsi "RSA Data Security, Inc." +#define NID_rsadsi 1 +#define OBJ_rsadsi OBJ_ISO_US,113549L + +#define SN_pkcs "pkcs" +#define LN_pkcs "RSA Data Security, Inc. PKCS" +#define NID_pkcs 2 +#define OBJ_pkcs OBJ_rsadsi,1L + +#define SN_pkcs1 "pkcs1" +#define NID_pkcs1 186 +#define OBJ_pkcs1 OBJ_pkcs,1L + +#define LN_rsaEncryption "rsaEncryption" +#define NID_rsaEncryption 6 +#define OBJ_rsaEncryption OBJ_pkcs1,1L + +#define SN_md2WithRSAEncryption "RSA-MD2" +#define LN_md2WithRSAEncryption "md2WithRSAEncryption" +#define NID_md2WithRSAEncryption 7 +#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L + +#define SN_md4WithRSAEncryption "RSA-MD4" +#define LN_md4WithRSAEncryption "md4WithRSAEncryption" +#define NID_md4WithRSAEncryption 396 +#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L + +#define SN_md5WithRSAEncryption "RSA-MD5" +#define LN_md5WithRSAEncryption "md5WithRSAEncryption" +#define NID_md5WithRSAEncryption 8 +#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L + +#define SN_sha1WithRSAEncryption "RSA-SHA1" +#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption" +#define NID_sha1WithRSAEncryption 65 +#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L + +#define SN_rsaesOaep "RSAES-OAEP" +#define LN_rsaesOaep "rsaesOaep" +#define NID_rsaesOaep 919 +#define OBJ_rsaesOaep OBJ_pkcs1,7L + +#define SN_mgf1 "MGF1" +#define LN_mgf1 "mgf1" +#define NID_mgf1 911 +#define OBJ_mgf1 OBJ_pkcs1,8L + +#define SN_pSpecified "PSPECIFIED" +#define LN_pSpecified "pSpecified" +#define NID_pSpecified 992 +#define OBJ_pSpecified OBJ_pkcs1,9L + +#define SN_rsassaPss "RSASSA-PSS" +#define LN_rsassaPss "rsassaPss" +#define NID_rsassaPss 912 +#define OBJ_rsassaPss OBJ_pkcs1,10L + +#define SN_sha256WithRSAEncryption "RSA-SHA256" +#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption" +#define NID_sha256WithRSAEncryption 668 +#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L + +#define SN_sha384WithRSAEncryption "RSA-SHA384" +#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption" +#define NID_sha384WithRSAEncryption 669 +#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L + +#define SN_sha512WithRSAEncryption "RSA-SHA512" +#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption" +#define NID_sha512WithRSAEncryption 670 +#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L + +#define SN_sha224WithRSAEncryption "RSA-SHA224" +#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption" +#define NID_sha224WithRSAEncryption 671 +#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L + +#define SN_sha512_224WithRSAEncryption "RSA-SHA512/224" +#define LN_sha512_224WithRSAEncryption "sha512-224WithRSAEncryption" +#define NID_sha512_224WithRSAEncryption 1025 +#define OBJ_sha512_224WithRSAEncryption OBJ_pkcs1,15L + +#define SN_sha512_256WithRSAEncryption "RSA-SHA512/256" +#define LN_sha512_256WithRSAEncryption "sha512-256WithRSAEncryption" +#define NID_sha512_256WithRSAEncryption 1026 +#define OBJ_sha512_256WithRSAEncryption OBJ_pkcs1,16L + +#define SN_pkcs3 "pkcs3" +#define NID_pkcs3 27 +#define OBJ_pkcs3 OBJ_pkcs,3L + +#define LN_dhKeyAgreement "dhKeyAgreement" +#define NID_dhKeyAgreement 28 +#define OBJ_dhKeyAgreement OBJ_pkcs3,1L + +#define SN_pkcs5 "pkcs5" +#define NID_pkcs5 187 +#define OBJ_pkcs5 OBJ_pkcs,5L + +#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES" +#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC" +#define NID_pbeWithMD2AndDES_CBC 9 +#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L + +#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES" +#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC" +#define NID_pbeWithMD5AndDES_CBC 10 +#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L + +#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64" +#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC" +#define NID_pbeWithMD2AndRC2_CBC 168 +#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L + +#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64" +#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC" +#define NID_pbeWithMD5AndRC2_CBC 169 +#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L + +#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES" +#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC" +#define NID_pbeWithSHA1AndDES_CBC 170 +#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L + +#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64" +#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC" +#define NID_pbeWithSHA1AndRC2_CBC 68 +#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L + +#define LN_id_pbkdf2 "PBKDF2" +#define NID_id_pbkdf2 69 +#define OBJ_id_pbkdf2 OBJ_pkcs5,12L + +#define LN_pbes2 "PBES2" +#define NID_pbes2 161 +#define OBJ_pbes2 OBJ_pkcs5,13L + +#define LN_pbmac1 "PBMAC1" +#define NID_pbmac1 162 +#define OBJ_pbmac1 OBJ_pkcs5,14L + +#define SN_pkcs7 "pkcs7" +#define NID_pkcs7 20 +#define OBJ_pkcs7 OBJ_pkcs,7L + +#define LN_pkcs7_data "pkcs7-data" +#define NID_pkcs7_data 21 +#define OBJ_pkcs7_data OBJ_pkcs7,1L + +#define LN_pkcs7_signed "pkcs7-signedData" +#define NID_pkcs7_signed 22 +#define OBJ_pkcs7_signed OBJ_pkcs7,2L + +#define LN_pkcs7_enveloped "pkcs7-envelopedData" +#define NID_pkcs7_enveloped 23 +#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L + +#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData" +#define NID_pkcs7_signedAndEnveloped 24 +#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L + +#define LN_pkcs7_digest "pkcs7-digestData" +#define NID_pkcs7_digest 25 +#define OBJ_pkcs7_digest OBJ_pkcs7,5L + +#define LN_pkcs7_encrypted "pkcs7-encryptedData" +#define NID_pkcs7_encrypted 26 +#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L + +#define SN_pkcs9 "pkcs9" +#define NID_pkcs9 47 +#define OBJ_pkcs9 OBJ_pkcs,9L + +#define LN_pkcs9_emailAddress "emailAddress" +#define NID_pkcs9_emailAddress 48 +#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L + +#define LN_pkcs9_unstructuredName "unstructuredName" +#define NID_pkcs9_unstructuredName 49 +#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L + +#define LN_pkcs9_contentType "contentType" +#define NID_pkcs9_contentType 50 +#define OBJ_pkcs9_contentType OBJ_pkcs9,3L + +#define LN_pkcs9_messageDigest "messageDigest" +#define NID_pkcs9_messageDigest 51 +#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L + +#define LN_pkcs9_signingTime "signingTime" +#define NID_pkcs9_signingTime 52 +#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L + +#define LN_pkcs9_countersignature "countersignature" +#define NID_pkcs9_countersignature 53 +#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L + +#define LN_pkcs9_challengePassword "challengePassword" +#define NID_pkcs9_challengePassword 54 +#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L + +#define LN_pkcs9_unstructuredAddress "unstructuredAddress" +#define NID_pkcs9_unstructuredAddress 55 +#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L + +#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes" +#define NID_pkcs9_extCertAttributes 56 +#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L + +#define SN_ext_req "extReq" +#define LN_ext_req "Extension Request" +#define NID_ext_req 172 +#define OBJ_ext_req OBJ_pkcs9,14L + +#define SN_SMIMECapabilities "SMIME-CAPS" +#define LN_SMIMECapabilities "S/MIME Capabilities" +#define NID_SMIMECapabilities 167 +#define OBJ_SMIMECapabilities OBJ_pkcs9,15L + +#define SN_SMIME "SMIME" +#define LN_SMIME "S/MIME" +#define NID_SMIME 188 +#define OBJ_SMIME OBJ_pkcs9,16L + +#define SN_id_smime_mod "id-smime-mod" +#define NID_id_smime_mod 189 +#define OBJ_id_smime_mod OBJ_SMIME,0L + +#define SN_id_smime_ct "id-smime-ct" +#define NID_id_smime_ct 190 +#define OBJ_id_smime_ct OBJ_SMIME,1L + +#define SN_id_smime_aa "id-smime-aa" +#define NID_id_smime_aa 191 +#define OBJ_id_smime_aa OBJ_SMIME,2L + +#define SN_id_smime_alg "id-smime-alg" +#define NID_id_smime_alg 192 +#define OBJ_id_smime_alg OBJ_SMIME,3L + +#define SN_id_smime_cd "id-smime-cd" +#define NID_id_smime_cd 193 +#define OBJ_id_smime_cd OBJ_SMIME,4L + +#define SN_id_smime_spq "id-smime-spq" +#define NID_id_smime_spq 194 +#define OBJ_id_smime_spq OBJ_SMIME,5L + +#define SN_id_smime_cti "id-smime-cti" +#define NID_id_smime_cti 195 +#define OBJ_id_smime_cti OBJ_SMIME,6L + +#define SN_id_smime_mod_cms "id-smime-mod-cms" +#define NID_id_smime_mod_cms 196 +#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L + +#define SN_id_smime_mod_ess "id-smime-mod-ess" +#define NID_id_smime_mod_ess 197 +#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L + +#define SN_id_smime_mod_oid "id-smime-mod-oid" +#define NID_id_smime_mod_oid 198 +#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L + +#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3" +#define NID_id_smime_mod_msg_v3 199 +#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L + +#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88" +#define NID_id_smime_mod_ets_eSignature_88 200 +#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L + +#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97" +#define NID_id_smime_mod_ets_eSignature_97 201 +#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L + +#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88" +#define NID_id_smime_mod_ets_eSigPolicy_88 202 +#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L + +#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97" +#define NID_id_smime_mod_ets_eSigPolicy_97 203 +#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L + +#define SN_id_smime_ct_receipt "id-smime-ct-receipt" +#define NID_id_smime_ct_receipt 204 +#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L + +#define SN_id_smime_ct_authData "id-smime-ct-authData" +#define NID_id_smime_ct_authData 205 +#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L + +#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert" +#define NID_id_smime_ct_publishCert 206 +#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L + +#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo" +#define NID_id_smime_ct_TSTInfo 207 +#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L + +#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo" +#define NID_id_smime_ct_TDTInfo 208 +#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L + +#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo" +#define NID_id_smime_ct_contentInfo 209 +#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L + +#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData" +#define NID_id_smime_ct_DVCSRequestData 210 +#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L + +#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData" +#define NID_id_smime_ct_DVCSResponseData 211 +#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L + +#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData" +#define NID_id_smime_ct_compressedData 786 +#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L + +#define SN_id_ct_routeOriginAuthz "id-ct-routeOriginAuthz" +#define NID_id_ct_routeOriginAuthz 1001 +#define OBJ_id_ct_routeOriginAuthz OBJ_id_smime_ct,24L + +#define SN_id_ct_rpkiManifest "id-ct-rpkiManifest" +#define NID_id_ct_rpkiManifest 1002 +#define OBJ_id_ct_rpkiManifest OBJ_id_smime_ct,26L + +#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF" +#define NID_id_ct_asciiTextWithCRLF 787 +#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L + +#define SN_id_ct_rpkiGhostbusters "id-ct-rpkiGhostbusters" +#define NID_id_ct_rpkiGhostbusters 1003 +#define OBJ_id_ct_rpkiGhostbusters OBJ_id_smime_ct,35L + +#define SN_id_ct_resourceTaggedAttest "id-ct-resourceTaggedAttest" +#define NID_id_ct_resourceTaggedAttest 1004 +#define OBJ_id_ct_resourceTaggedAttest OBJ_id_smime_ct,36L + +#define SN_id_ct_geofeedCSVwithCRLF "id-ct-geofeedCSVwithCRLF" +#define NID_id_ct_geofeedCSVwithCRLF 1013 +#define OBJ_id_ct_geofeedCSVwithCRLF OBJ_id_smime_ct,47L + +#define SN_id_ct_signedChecklist "id-ct-signedChecklist" +#define NID_id_ct_signedChecklist 1014 +#define OBJ_id_ct_signedChecklist OBJ_id_smime_ct,48L + +#define SN_id_ct_ASPA "id-ct-ASPA" +#define NID_id_ct_ASPA 1017 +#define OBJ_id_ct_ASPA OBJ_id_smime_ct,49L + +#define SN_id_ct_signedTAL "id-ct-signedTAL" +#define NID_id_ct_signedTAL 1024 +#define OBJ_id_ct_signedTAL OBJ_id_smime_ct,50L + +#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest" +#define NID_id_smime_aa_receiptRequest 212 +#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L + +#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel" +#define NID_id_smime_aa_securityLabel 213 +#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L + +#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory" +#define NID_id_smime_aa_mlExpandHistory 214 +#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L + +#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint" +#define NID_id_smime_aa_contentHint 215 +#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L + +#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest" +#define NID_id_smime_aa_msgSigDigest 216 +#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L + +#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType" +#define NID_id_smime_aa_encapContentType 217 +#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L + +#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier" +#define NID_id_smime_aa_contentIdentifier 218 +#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L + +#define SN_id_smime_aa_macValue "id-smime-aa-macValue" +#define NID_id_smime_aa_macValue 219 +#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L + +#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels" +#define NID_id_smime_aa_equivalentLabels 220 +#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L + +#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference" +#define NID_id_smime_aa_contentReference 221 +#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L + +#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref" +#define NID_id_smime_aa_encrypKeyPref 222 +#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L + +#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate" +#define NID_id_smime_aa_signingCertificate 223 +#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L + +#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts" +#define NID_id_smime_aa_smimeEncryptCerts 224 +#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L + +#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken" +#define NID_id_smime_aa_timeStampToken 225 +#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L + +#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId" +#define NID_id_smime_aa_ets_sigPolicyId 226 +#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L + +#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType" +#define NID_id_smime_aa_ets_commitmentType 227 +#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L + +#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation" +#define NID_id_smime_aa_ets_signerLocation 228 +#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L + +#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr" +#define NID_id_smime_aa_ets_signerAttr 229 +#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L + +#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert" +#define NID_id_smime_aa_ets_otherSigCert 230 +#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L + +#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp" +#define NID_id_smime_aa_ets_contentTimestamp 231 +#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L + +#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs" +#define NID_id_smime_aa_ets_CertificateRefs 232 +#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L + +#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs" +#define NID_id_smime_aa_ets_RevocationRefs 233 +#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L + +#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues" +#define NID_id_smime_aa_ets_certValues 234 +#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L + +#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues" +#define NID_id_smime_aa_ets_revocationValues 235 +#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L + +#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp" +#define NID_id_smime_aa_ets_escTimeStamp 236 +#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L + +#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp" +#define NID_id_smime_aa_ets_certCRLTimestamp 237 +#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L + +#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp" +#define NID_id_smime_aa_ets_archiveTimeStamp 238 +#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L + +#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType" +#define NID_id_smime_aa_signatureType 239 +#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L + +#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc" +#define NID_id_smime_aa_dvcs_dvc 240 +#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L + +#define SN_id_smime_aa_signingCertificateV2 "id-smime-aa-signingCertificateV2" +#define NID_id_smime_aa_signingCertificateV2 1023 +#define OBJ_id_smime_aa_signingCertificateV2 OBJ_id_smime_aa,47L + +#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES" +#define NID_id_smime_alg_ESDHwith3DES 241 +#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L + +#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2" +#define NID_id_smime_alg_ESDHwithRC2 242 +#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L + +#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap" +#define NID_id_smime_alg_3DESwrap 243 +#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L + +#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap" +#define NID_id_smime_alg_RC2wrap 244 +#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L + +#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH" +#define NID_id_smime_alg_ESDH 245 +#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L + +#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap" +#define NID_id_smime_alg_CMS3DESwrap 246 +#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L + +#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap" +#define NID_id_smime_alg_CMSRC2wrap 247 +#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L + +#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK" +#define NID_id_alg_PWRI_KEK 893 +#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L + +#define SN_id_smime_cd_ldap "id-smime-cd-ldap" +#define NID_id_smime_cd_ldap 248 +#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L + +#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri" +#define NID_id_smime_spq_ets_sqt_uri 249 +#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L + +#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice" +#define NID_id_smime_spq_ets_sqt_unotice 250 +#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L + +#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin" +#define NID_id_smime_cti_ets_proofOfOrigin 251 +#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L + +#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt" +#define NID_id_smime_cti_ets_proofOfReceipt 252 +#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L + +#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery" +#define NID_id_smime_cti_ets_proofOfDelivery 253 +#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L + +#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender" +#define NID_id_smime_cti_ets_proofOfSender 254 +#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L + +#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval" +#define NID_id_smime_cti_ets_proofOfApproval 255 +#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L + +#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation" +#define NID_id_smime_cti_ets_proofOfCreation 256 +#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L + +#define LN_friendlyName "friendlyName" +#define NID_friendlyName 156 +#define OBJ_friendlyName OBJ_pkcs9,20L + +#define LN_localKeyID "localKeyID" +#define NID_localKeyID 157 +#define OBJ_localKeyID OBJ_pkcs9,21L + +#define SN_ms_csp_name "CSPName" +#define LN_ms_csp_name "Microsoft CSP Name" +#define NID_ms_csp_name 417 +#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L + +#define SN_LocalKeySet "LocalKeySet" +#define LN_LocalKeySet "Microsoft Local Key set" +#define NID_LocalKeySet 856 +#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L + +#define OBJ_certTypes OBJ_pkcs9,22L + +#define LN_x509Certificate "x509Certificate" +#define NID_x509Certificate 158 +#define OBJ_x509Certificate OBJ_certTypes,1L + +#define LN_sdsiCertificate "sdsiCertificate" +#define NID_sdsiCertificate 159 +#define OBJ_sdsiCertificate OBJ_certTypes,2L + +#define OBJ_crlTypes OBJ_pkcs9,23L + +#define LN_x509Crl "x509Crl" +#define NID_x509Crl 160 +#define OBJ_x509Crl OBJ_crlTypes,1L + +#define OBJ_pkcs12 OBJ_pkcs,12L + +#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L + +#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128" +#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4" +#define NID_pbe_WithSHA1And128BitRC4 144 +#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L + +#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40" +#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4" +#define NID_pbe_WithSHA1And40BitRC4 145 +#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L + +#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES" +#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146 +#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L + +#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES" +#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC" +#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147 +#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L + +#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128" +#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC" +#define NID_pbe_WithSHA1And128BitRC2_CBC 148 +#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L + +#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40" +#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC" +#define NID_pbe_WithSHA1And40BitRC2_CBC 149 +#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L + +#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L + +#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L + +#define LN_keyBag "keyBag" +#define NID_keyBag 150 +#define OBJ_keyBag OBJ_pkcs12_BagIds,1L + +#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag" +#define NID_pkcs8ShroudedKeyBag 151 +#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L + +#define LN_certBag "certBag" +#define NID_certBag 152 +#define OBJ_certBag OBJ_pkcs12_BagIds,3L + +#define LN_crlBag "crlBag" +#define NID_crlBag 153 +#define OBJ_crlBag OBJ_pkcs12_BagIds,4L + +#define LN_secretBag "secretBag" +#define NID_secretBag 154 +#define OBJ_secretBag OBJ_pkcs12_BagIds,5L + +#define LN_safeContentsBag "safeContentsBag" +#define NID_safeContentsBag 155 +#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L + +#define SN_md2 "MD2" +#define LN_md2 "md2" +#define NID_md2 3 +#define OBJ_md2 OBJ_rsadsi,2L,2L + +#define SN_md4 "MD4" +#define LN_md4 "md4" +#define NID_md4 257 +#define OBJ_md4 OBJ_rsadsi,2L,4L + +#define SN_md5 "MD5" +#define LN_md5 "md5" +#define NID_md5 4 +#define OBJ_md5 OBJ_rsadsi,2L,5L + +#define SN_md5_sha1 "MD5-SHA1" +#define LN_md5_sha1 "md5-sha1" +#define NID_md5_sha1 114 + +#define LN_hmacWithMD5 "hmacWithMD5" +#define NID_hmacWithMD5 797 +#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L + +#define LN_hmacWithSHA1 "hmacWithSHA1" +#define NID_hmacWithSHA1 163 +#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L + +#define LN_hmacWithSHA224 "hmacWithSHA224" +#define NID_hmacWithSHA224 798 +#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L + +#define LN_hmacWithSHA256 "hmacWithSHA256" +#define NID_hmacWithSHA256 799 +#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L + +#define LN_hmacWithSHA384 "hmacWithSHA384" +#define NID_hmacWithSHA384 800 +#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L + +#define LN_hmacWithSHA512 "hmacWithSHA512" +#define NID_hmacWithSHA512 801 +#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L + +#define LN_hmacWithSHA512_224 "hmacWithSHA512-224" +#define NID_hmacWithSHA512_224 1027 +#define OBJ_hmacWithSHA512_224 OBJ_rsadsi,2L,12L + +#define LN_hmacWithSHA512_256 "hmacWithSHA512-256" +#define NID_hmacWithSHA512_256 1028 +#define OBJ_hmacWithSHA512_256 OBJ_rsadsi,2L,13L + +#define SN_rc2_cbc "RC2-CBC" +#define LN_rc2_cbc "rc2-cbc" +#define NID_rc2_cbc 37 +#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L + +#define SN_rc2_ecb "RC2-ECB" +#define LN_rc2_ecb "rc2-ecb" +#define NID_rc2_ecb 38 + +#define SN_rc2_cfb64 "RC2-CFB" +#define LN_rc2_cfb64 "rc2-cfb" +#define NID_rc2_cfb64 39 + +#define SN_rc2_ofb64 "RC2-OFB" +#define LN_rc2_ofb64 "rc2-ofb" +#define NID_rc2_ofb64 40 + +#define SN_rc2_40_cbc "RC2-40-CBC" +#define LN_rc2_40_cbc "rc2-40-cbc" +#define NID_rc2_40_cbc 98 + +#define SN_rc2_64_cbc "RC2-64-CBC" +#define LN_rc2_64_cbc "rc2-64-cbc" +#define NID_rc2_64_cbc 166 + +#define SN_rc4 "RC4" +#define LN_rc4 "rc4" +#define NID_rc4 5 +#define OBJ_rc4 OBJ_rsadsi,3L,4L + +#define SN_rc4_40 "RC4-40" +#define LN_rc4_40 "rc4-40" +#define NID_rc4_40 97 + +#define SN_des_ede3_cbc "DES-EDE3-CBC" +#define LN_des_ede3_cbc "des-ede3-cbc" +#define NID_des_ede3_cbc 44 +#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L + +#define SN_rc5_cbc "RC5-CBC" +#define LN_rc5_cbc "rc5-cbc" +#define NID_rc5_cbc 120 +#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L + +#define SN_rc5_ecb "RC5-ECB" +#define LN_rc5_ecb "rc5-ecb" +#define NID_rc5_ecb 121 + +#define SN_rc5_cfb64 "RC5-CFB" +#define LN_rc5_cfb64 "rc5-cfb" +#define NID_rc5_cfb64 122 + +#define SN_rc5_ofb64 "RC5-OFB" +#define LN_rc5_ofb64 "rc5-ofb" +#define NID_rc5_ofb64 123 + +#define SN_ms_ext_req "msExtReq" +#define LN_ms_ext_req "Microsoft Extension Request" +#define NID_ms_ext_req 171 +#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L + +#define SN_ms_code_ind "msCodeInd" +#define LN_ms_code_ind "Microsoft Individual Code Signing" +#define NID_ms_code_ind 134 +#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L + +#define SN_ms_code_com "msCodeCom" +#define LN_ms_code_com "Microsoft Commercial Code Signing" +#define NID_ms_code_com 135 +#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L + +#define SN_ms_ctl_sign "msCTLSign" +#define LN_ms_ctl_sign "Microsoft Trust List Signing" +#define NID_ms_ctl_sign 136 +#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L + +#define SN_ms_sgc "msSGC" +#define LN_ms_sgc "Microsoft Server Gated Crypto" +#define NID_ms_sgc 137 +#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L + +#define SN_ms_efs "msEFS" +#define LN_ms_efs "Microsoft Encrypted File System" +#define NID_ms_efs 138 +#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L + +#define SN_ms_smartcard_login "msSmartcardLogin" +#define LN_ms_smartcard_login "Microsoft Smartcardlogin" +#define NID_ms_smartcard_login 648 +#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L + +#define SN_ms_upn "msUPN" +#define LN_ms_upn "Microsoft Universal Principal Name" +#define NID_ms_upn 649 +#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L + +#define SN_idea_cbc "IDEA-CBC" +#define LN_idea_cbc "idea-cbc" +#define NID_idea_cbc 34 +#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L + +#define SN_idea_ecb "IDEA-ECB" +#define LN_idea_ecb "idea-ecb" +#define NID_idea_ecb 36 + +#define SN_idea_cfb64 "IDEA-CFB" +#define LN_idea_cfb64 "idea-cfb" +#define NID_idea_cfb64 35 + +#define SN_idea_ofb64 "IDEA-OFB" +#define LN_idea_ofb64 "idea-ofb" +#define NID_idea_ofb64 46 + +#define SN_bf_cbc "BF-CBC" +#define LN_bf_cbc "bf-cbc" +#define NID_bf_cbc 91 +#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L + +#define SN_bf_ecb "BF-ECB" +#define LN_bf_ecb "bf-ecb" +#define NID_bf_ecb 92 + +#define SN_bf_cfb64 "BF-CFB" +#define LN_bf_cfb64 "bf-cfb" +#define NID_bf_cfb64 93 + +#define SN_bf_ofb64 "BF-OFB" +#define LN_bf_ofb64 "bf-ofb" +#define NID_bf_ofb64 94 + +#define SN_id_pkix "PKIX" +#define NID_id_pkix 127 +#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L + +#define SN_id_pkix_mod "id-pkix-mod" +#define NID_id_pkix_mod 258 +#define OBJ_id_pkix_mod OBJ_id_pkix,0L + +#define SN_id_pe "id-pe" +#define NID_id_pe 175 +#define OBJ_id_pe OBJ_id_pkix,1L + +#define SN_id_qt "id-qt" +#define NID_id_qt 259 +#define OBJ_id_qt OBJ_id_pkix,2L + +#define SN_id_kp "id-kp" +#define NID_id_kp 128 +#define OBJ_id_kp OBJ_id_pkix,3L + +#define SN_id_it "id-it" +#define NID_id_it 260 +#define OBJ_id_it OBJ_id_pkix,4L + +#define SN_id_pkip "id-pkip" +#define NID_id_pkip 261 +#define OBJ_id_pkip OBJ_id_pkix,5L + +#define SN_id_alg "id-alg" +#define NID_id_alg 262 +#define OBJ_id_alg OBJ_id_pkix,6L + +#define SN_id_cmc "id-cmc" +#define NID_id_cmc 263 +#define OBJ_id_cmc OBJ_id_pkix,7L + +#define SN_id_on "id-on" +#define NID_id_on 264 +#define OBJ_id_on OBJ_id_pkix,8L + +#define SN_id_pda "id-pda" +#define NID_id_pda 265 +#define OBJ_id_pda OBJ_id_pkix,9L + +#define SN_id_aca "id-aca" +#define NID_id_aca 266 +#define OBJ_id_aca OBJ_id_pkix,10L + +#define SN_id_qcs "id-qcs" +#define NID_id_qcs 267 +#define OBJ_id_qcs OBJ_id_pkix,11L + +#define SN_id_cct "id-cct" +#define NID_id_cct 268 +#define OBJ_id_cct OBJ_id_pkix,12L + +#define SN_id_cp "id-cp" +#define NID_id_cp 1005 +#define OBJ_id_cp OBJ_id_pkix,14L + +#define SN_id_ppl "id-ppl" +#define NID_id_ppl 662 +#define OBJ_id_ppl OBJ_id_pkix,21L + +#define SN_id_ad "id-ad" +#define NID_id_ad 176 +#define OBJ_id_ad OBJ_id_pkix,48L + +#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88" +#define NID_id_pkix1_explicit_88 269 +#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L + +#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88" +#define NID_id_pkix1_implicit_88 270 +#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L + +#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93" +#define NID_id_pkix1_explicit_93 271 +#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L + +#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93" +#define NID_id_pkix1_implicit_93 272 +#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L + +#define SN_id_mod_crmf "id-mod-crmf" +#define NID_id_mod_crmf 273 +#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L + +#define SN_id_mod_cmc "id-mod-cmc" +#define NID_id_mod_cmc 274 +#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L + +#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88" +#define NID_id_mod_kea_profile_88 275 +#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L + +#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93" +#define NID_id_mod_kea_profile_93 276 +#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L + +#define SN_id_mod_cmp "id-mod-cmp" +#define NID_id_mod_cmp 277 +#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L + +#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88" +#define NID_id_mod_qualified_cert_88 278 +#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L + +#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93" +#define NID_id_mod_qualified_cert_93 279 +#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L + +#define SN_id_mod_attribute_cert "id-mod-attribute-cert" +#define NID_id_mod_attribute_cert 280 +#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L + +#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol" +#define NID_id_mod_timestamp_protocol 281 +#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L + +#define SN_id_mod_ocsp "id-mod-ocsp" +#define NID_id_mod_ocsp 282 +#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L + +#define SN_id_mod_dvcs "id-mod-dvcs" +#define NID_id_mod_dvcs 283 +#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L + +#define SN_id_mod_cmp2000 "id-mod-cmp2000" +#define NID_id_mod_cmp2000 284 +#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L + +#define SN_info_access "authorityInfoAccess" +#define LN_info_access "Authority Information Access" +#define NID_info_access 177 +#define OBJ_info_access OBJ_id_pe,1L + +#define SN_biometricInfo "biometricInfo" +#define LN_biometricInfo "Biometric Info" +#define NID_biometricInfo 285 +#define OBJ_biometricInfo OBJ_id_pe,2L + +#define SN_qcStatements "qcStatements" +#define NID_qcStatements 286 +#define OBJ_qcStatements OBJ_id_pe,3L + +#define SN_ac_auditEntity "ac-auditEntity" +#define NID_ac_auditEntity 287 +#define OBJ_ac_auditEntity OBJ_id_pe,4L + +#define SN_ac_targeting "ac-targeting" +#define NID_ac_targeting 288 +#define OBJ_ac_targeting OBJ_id_pe,5L + +#define SN_aaControls "aaControls" +#define NID_aaControls 289 +#define OBJ_aaControls OBJ_id_pe,6L + +#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock" +#define NID_sbgp_ipAddrBlock 290 +#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L + +#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum" +#define NID_sbgp_autonomousSysNum 291 +#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L + +#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier" +#define NID_sbgp_routerIdentifier 292 +#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L + +#define SN_ac_proxying "ac-proxying" +#define NID_ac_proxying 397 +#define OBJ_ac_proxying OBJ_id_pe,10L + +#define SN_sinfo_access "subjectInfoAccess" +#define LN_sinfo_access "Subject Information Access" +#define NID_sinfo_access 398 +#define OBJ_sinfo_access OBJ_id_pe,11L + +#define SN_proxyCertInfo "proxyCertInfo" +#define LN_proxyCertInfo "Proxy Certificate Information" +#define NID_proxyCertInfo 663 +#define OBJ_proxyCertInfo OBJ_id_pe,14L + +#define SN_tlsfeature "tlsfeature" +#define LN_tlsfeature "TLS Feature" +#define NID_tlsfeature 1016 +#define OBJ_tlsfeature OBJ_id_pe,24L + +#define SN_sbgp_ipAddrBlockv2 "sbgp-ipAddrBlockv2" +#define NID_sbgp_ipAddrBlockv2 1006 +#define OBJ_sbgp_ipAddrBlockv2 OBJ_id_pe,28L + +#define SN_sbgp_autonomousSysNumv2 "sbgp-autonomousSysNumv2" +#define NID_sbgp_autonomousSysNumv2 1007 +#define OBJ_sbgp_autonomousSysNumv2 OBJ_id_pe,29L + +#define SN_id_qt_cps "id-qt-cps" +#define LN_id_qt_cps "Policy Qualifier CPS" +#define NID_id_qt_cps 164 +#define OBJ_id_qt_cps OBJ_id_qt,1L + +#define SN_id_qt_unotice "id-qt-unotice" +#define LN_id_qt_unotice "Policy Qualifier User Notice" +#define NID_id_qt_unotice 165 +#define OBJ_id_qt_unotice OBJ_id_qt,2L + +#define SN_textNotice "textNotice" +#define NID_textNotice 293 +#define OBJ_textNotice OBJ_id_qt,3L + +#define SN_server_auth "serverAuth" +#define LN_server_auth "TLS Web Server Authentication" +#define NID_server_auth 129 +#define OBJ_server_auth OBJ_id_kp,1L + +#define SN_client_auth "clientAuth" +#define LN_client_auth "TLS Web Client Authentication" +#define NID_client_auth 130 +#define OBJ_client_auth OBJ_id_kp,2L + +#define SN_code_sign "codeSigning" +#define LN_code_sign "Code Signing" +#define NID_code_sign 131 +#define OBJ_code_sign OBJ_id_kp,3L + +#define SN_email_protect "emailProtection" +#define LN_email_protect "E-mail Protection" +#define NID_email_protect 132 +#define OBJ_email_protect OBJ_id_kp,4L + +#define SN_ipsecEndSystem "ipsecEndSystem" +#define LN_ipsecEndSystem "IPSec End System" +#define NID_ipsecEndSystem 294 +#define OBJ_ipsecEndSystem OBJ_id_kp,5L + +#define SN_ipsecTunnel "ipsecTunnel" +#define LN_ipsecTunnel "IPSec Tunnel" +#define NID_ipsecTunnel 295 +#define OBJ_ipsecTunnel OBJ_id_kp,6L + +#define SN_ipsecUser "ipsecUser" +#define LN_ipsecUser "IPSec User" +#define NID_ipsecUser 296 +#define OBJ_ipsecUser OBJ_id_kp,7L + +#define SN_time_stamp "timeStamping" +#define LN_time_stamp "Time Stamping" +#define NID_time_stamp 133 +#define OBJ_time_stamp OBJ_id_kp,8L + +#define SN_OCSP_sign "OCSPSigning" +#define LN_OCSP_sign "OCSP Signing" +#define NID_OCSP_sign 180 +#define OBJ_OCSP_sign OBJ_id_kp,9L + +#define SN_dvcs "DVCS" +#define LN_dvcs "dvcs" +#define NID_dvcs 297 +#define OBJ_dvcs OBJ_id_kp,10L + +#define SN_id_kp_bgpsec_router "id-kp-bgpsec-router" +#define LN_id_kp_bgpsec_router "BGPsec Router" +#define NID_id_kp_bgpsec_router 1015 +#define OBJ_id_kp_bgpsec_router OBJ_id_kp,30L + +#define SN_id_it_caProtEncCert "id-it-caProtEncCert" +#define NID_id_it_caProtEncCert 298 +#define OBJ_id_it_caProtEncCert OBJ_id_it,1L + +#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes" +#define NID_id_it_signKeyPairTypes 299 +#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L + +#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes" +#define NID_id_it_encKeyPairTypes 300 +#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L + +#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg" +#define NID_id_it_preferredSymmAlg 301 +#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L + +#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo" +#define NID_id_it_caKeyUpdateInfo 302 +#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L + +#define SN_id_it_currentCRL "id-it-currentCRL" +#define NID_id_it_currentCRL 303 +#define OBJ_id_it_currentCRL OBJ_id_it,6L + +#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs" +#define NID_id_it_unsupportedOIDs 304 +#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L + +#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest" +#define NID_id_it_subscriptionRequest 305 +#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L + +#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse" +#define NID_id_it_subscriptionResponse 306 +#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L + +#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq" +#define NID_id_it_keyPairParamReq 307 +#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L + +#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep" +#define NID_id_it_keyPairParamRep 308 +#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L + +#define SN_id_it_revPassphrase "id-it-revPassphrase" +#define NID_id_it_revPassphrase 309 +#define OBJ_id_it_revPassphrase OBJ_id_it,12L + +#define SN_id_it_implicitConfirm "id-it-implicitConfirm" +#define NID_id_it_implicitConfirm 310 +#define OBJ_id_it_implicitConfirm OBJ_id_it,13L + +#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime" +#define NID_id_it_confirmWaitTime 311 +#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L + +#define SN_id_it_origPKIMessage "id-it-origPKIMessage" +#define NID_id_it_origPKIMessage 312 +#define OBJ_id_it_origPKIMessage OBJ_id_it,15L + +#define SN_id_it_suppLangTags "id-it-suppLangTags" +#define NID_id_it_suppLangTags 784 +#define OBJ_id_it_suppLangTags OBJ_id_it,16L + +#define SN_id_regCtrl "id-regCtrl" +#define NID_id_regCtrl 313 +#define OBJ_id_regCtrl OBJ_id_pkip,1L + +#define SN_id_regInfo "id-regInfo" +#define NID_id_regInfo 314 +#define OBJ_id_regInfo OBJ_id_pkip,2L + +#define SN_id_regCtrl_regToken "id-regCtrl-regToken" +#define NID_id_regCtrl_regToken 315 +#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L + +#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator" +#define NID_id_regCtrl_authenticator 316 +#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L + +#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo" +#define NID_id_regCtrl_pkiPublicationInfo 317 +#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L + +#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions" +#define NID_id_regCtrl_pkiArchiveOptions 318 +#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L + +#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID" +#define NID_id_regCtrl_oldCertID 319 +#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L + +#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey" +#define NID_id_regCtrl_protocolEncrKey 320 +#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L + +#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs" +#define NID_id_regInfo_utf8Pairs 321 +#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L + +#define SN_id_regInfo_certReq "id-regInfo-certReq" +#define NID_id_regInfo_certReq 322 +#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L + +#define SN_id_alg_des40 "id-alg-des40" +#define NID_id_alg_des40 323 +#define OBJ_id_alg_des40 OBJ_id_alg,1L + +#define SN_id_alg_noSignature "id-alg-noSignature" +#define NID_id_alg_noSignature 324 +#define OBJ_id_alg_noSignature OBJ_id_alg,2L + +#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1" +#define NID_id_alg_dh_sig_hmac_sha1 325 +#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L + +#define SN_id_alg_dh_pop "id-alg-dh-pop" +#define NID_id_alg_dh_pop 326 +#define OBJ_id_alg_dh_pop OBJ_id_alg,4L + +#define SN_id_cmc_statusInfo "id-cmc-statusInfo" +#define NID_id_cmc_statusInfo 327 +#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L + +#define SN_id_cmc_identification "id-cmc-identification" +#define NID_id_cmc_identification 328 +#define OBJ_id_cmc_identification OBJ_id_cmc,2L + +#define SN_id_cmc_identityProof "id-cmc-identityProof" +#define NID_id_cmc_identityProof 329 +#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L + +#define SN_id_cmc_dataReturn "id-cmc-dataReturn" +#define NID_id_cmc_dataReturn 330 +#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L + +#define SN_id_cmc_transactionId "id-cmc-transactionId" +#define NID_id_cmc_transactionId 331 +#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L + +#define SN_id_cmc_senderNonce "id-cmc-senderNonce" +#define NID_id_cmc_senderNonce 332 +#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L + +#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce" +#define NID_id_cmc_recipientNonce 333 +#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L + +#define SN_id_cmc_addExtensions "id-cmc-addExtensions" +#define NID_id_cmc_addExtensions 334 +#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L + +#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP" +#define NID_id_cmc_encryptedPOP 335 +#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L + +#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP" +#define NID_id_cmc_decryptedPOP 336 +#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L + +#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness" +#define NID_id_cmc_lraPOPWitness 337 +#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L + +#define SN_id_cmc_getCert "id-cmc-getCert" +#define NID_id_cmc_getCert 338 +#define OBJ_id_cmc_getCert OBJ_id_cmc,15L + +#define SN_id_cmc_getCRL "id-cmc-getCRL" +#define NID_id_cmc_getCRL 339 +#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L + +#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest" +#define NID_id_cmc_revokeRequest 340 +#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L + +#define SN_id_cmc_regInfo "id-cmc-regInfo" +#define NID_id_cmc_regInfo 341 +#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L + +#define SN_id_cmc_responseInfo "id-cmc-responseInfo" +#define NID_id_cmc_responseInfo 342 +#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L + +#define SN_id_cmc_queryPending "id-cmc-queryPending" +#define NID_id_cmc_queryPending 343 +#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L + +#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom" +#define NID_id_cmc_popLinkRandom 344 +#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L + +#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness" +#define NID_id_cmc_popLinkWitness 345 +#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L + +#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance" +#define NID_id_cmc_confirmCertAcceptance 346 +#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L + +#define SN_id_on_personalData "id-on-personalData" +#define NID_id_on_personalData 347 +#define OBJ_id_on_personalData OBJ_id_on,1L + +#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier" +#define LN_id_on_permanentIdentifier "Permanent Identifier" +#define NID_id_on_permanentIdentifier 858 +#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L + +#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth" +#define NID_id_pda_dateOfBirth 348 +#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L + +#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth" +#define NID_id_pda_placeOfBirth 349 +#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L + +#define SN_id_pda_gender "id-pda-gender" +#define NID_id_pda_gender 351 +#define OBJ_id_pda_gender OBJ_id_pda,3L + +#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship" +#define NID_id_pda_countryOfCitizenship 352 +#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L + +#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence" +#define NID_id_pda_countryOfResidence 353 +#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L + +#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo" +#define NID_id_aca_authenticationInfo 354 +#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L + +#define SN_id_aca_accessIdentity "id-aca-accessIdentity" +#define NID_id_aca_accessIdentity 355 +#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L + +#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity" +#define NID_id_aca_chargingIdentity 356 +#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L + +#define SN_id_aca_group "id-aca-group" +#define NID_id_aca_group 357 +#define OBJ_id_aca_group OBJ_id_aca,4L + +#define SN_id_aca_role "id-aca-role" +#define NID_id_aca_role 358 +#define OBJ_id_aca_role OBJ_id_aca,5L + +#define SN_id_aca_encAttrs "id-aca-encAttrs" +#define NID_id_aca_encAttrs 399 +#define OBJ_id_aca_encAttrs OBJ_id_aca,6L + +#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1" +#define NID_id_qcs_pkixQCSyntax_v1 359 +#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L + +#define SN_id_cct_crs "id-cct-crs" +#define NID_id_cct_crs 360 +#define OBJ_id_cct_crs OBJ_id_cct,1L + +#define SN_id_cct_PKIData "id-cct-PKIData" +#define NID_id_cct_PKIData 361 +#define OBJ_id_cct_PKIData OBJ_id_cct,2L + +#define SN_id_cct_PKIResponse "id-cct-PKIResponse" +#define NID_id_cct_PKIResponse 362 +#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L + +#define SN_ipAddr_asNumber "ipAddr-asNumber" +#define NID_ipAddr_asNumber 1008 +#define OBJ_ipAddr_asNumber OBJ_id_cp,2L + +#define SN_ipAddr_asNumberv2 "ipAddr-asNumberv2" +#define NID_ipAddr_asNumberv2 1009 +#define OBJ_ipAddr_asNumberv2 OBJ_id_cp,3L + +#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage" +#define LN_id_ppl_anyLanguage "Any language" +#define NID_id_ppl_anyLanguage 664 +#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L + +#define SN_id_ppl_inheritAll "id-ppl-inheritAll" +#define LN_id_ppl_inheritAll "Inherit all" +#define NID_id_ppl_inheritAll 665 +#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L + +#define SN_Independent "id-ppl-independent" +#define LN_Independent "Independent" +#define NID_Independent 667 +#define OBJ_Independent OBJ_id_ppl,2L + +#define SN_ad_OCSP "OCSP" +#define LN_ad_OCSP "OCSP" +#define NID_ad_OCSP 178 +#define OBJ_ad_OCSP OBJ_id_ad,1L + +#define SN_ad_ca_issuers "caIssuers" +#define LN_ad_ca_issuers "CA Issuers" +#define NID_ad_ca_issuers 179 +#define OBJ_ad_ca_issuers OBJ_id_ad,2L + +#define SN_ad_timeStamping "ad_timestamping" +#define LN_ad_timeStamping "AD Time Stamping" +#define NID_ad_timeStamping 363 +#define OBJ_ad_timeStamping OBJ_id_ad,3L + +#define SN_ad_dvcs "AD_DVCS" +#define LN_ad_dvcs "ad dvcs" +#define NID_ad_dvcs 364 +#define OBJ_ad_dvcs OBJ_id_ad,4L + +#define SN_caRepository "caRepository" +#define LN_caRepository "CA Repository" +#define NID_caRepository 785 +#define OBJ_caRepository OBJ_id_ad,5L + +#define SN_rpkiManifest "rpkiManifest" +#define LN_rpkiManifest "RPKI Manifest" +#define NID_rpkiManifest 1010 +#define OBJ_rpkiManifest OBJ_id_ad,10L + +#define SN_signedObject "signedObject" +#define LN_signedObject "Signed Object" +#define NID_signedObject 1011 +#define OBJ_signedObject OBJ_id_ad,11L + +#define SN_rpkiNotify "rpkiNotify" +#define LN_rpkiNotify "RPKI Notify" +#define NID_rpkiNotify 1012 +#define OBJ_rpkiNotify OBJ_id_ad,13L + +#define OBJ_id_pkix_OCSP OBJ_ad_OCSP + +#define SN_id_pkix_OCSP_basic "basicOCSPResponse" +#define LN_id_pkix_OCSP_basic "Basic OCSP Response" +#define NID_id_pkix_OCSP_basic 365 +#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L + +#define SN_id_pkix_OCSP_Nonce "Nonce" +#define LN_id_pkix_OCSP_Nonce "OCSP Nonce" +#define NID_id_pkix_OCSP_Nonce 366 +#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L + +#define SN_id_pkix_OCSP_CrlID "CrlID" +#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID" +#define NID_id_pkix_OCSP_CrlID 367 +#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L + +#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses" +#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses" +#define NID_id_pkix_OCSP_acceptableResponses 368 +#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L + +#define SN_id_pkix_OCSP_noCheck "noCheck" +#define LN_id_pkix_OCSP_noCheck "OCSP No Check" +#define NID_id_pkix_OCSP_noCheck 369 +#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L + +#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff" +#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff" +#define NID_id_pkix_OCSP_archiveCutoff 370 +#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L + +#define SN_id_pkix_OCSP_serviceLocator "serviceLocator" +#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator" +#define NID_id_pkix_OCSP_serviceLocator 371 +#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L + +#define SN_id_pkix_OCSP_extendedStatus "extendedStatus" +#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status" +#define NID_id_pkix_OCSP_extendedStatus 372 +#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L + +#define SN_id_pkix_OCSP_valid "valid" +#define NID_id_pkix_OCSP_valid 373 +#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L + +#define SN_id_pkix_OCSP_path "path" +#define NID_id_pkix_OCSP_path 374 +#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L + +#define SN_id_pkix_OCSP_trustRoot "trustRoot" +#define LN_id_pkix_OCSP_trustRoot "Trust Root" +#define NID_id_pkix_OCSP_trustRoot 375 +#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L + +#define SN_algorithm "algorithm" +#define LN_algorithm "algorithm" +#define NID_algorithm 376 +#define OBJ_algorithm 1L,3L,14L,3L,2L + +#define SN_md5WithRSA "RSA-NP-MD5" +#define LN_md5WithRSA "md5WithRSA" +#define NID_md5WithRSA 104 +#define OBJ_md5WithRSA OBJ_algorithm,3L + +#define SN_des_ecb "DES-ECB" +#define LN_des_ecb "des-ecb" +#define NID_des_ecb 29 +#define OBJ_des_ecb OBJ_algorithm,6L + +#define SN_des_cbc "DES-CBC" +#define LN_des_cbc "des-cbc" +#define NID_des_cbc 31 +#define OBJ_des_cbc OBJ_algorithm,7L + +#define SN_des_ofb64 "DES-OFB" +#define LN_des_ofb64 "des-ofb" +#define NID_des_ofb64 45 +#define OBJ_des_ofb64 OBJ_algorithm,8L + +#define SN_des_cfb64 "DES-CFB" +#define LN_des_cfb64 "des-cfb" +#define NID_des_cfb64 30 +#define OBJ_des_cfb64 OBJ_algorithm,9L + +#define SN_rsaSignature "rsaSignature" +#define NID_rsaSignature 377 +#define OBJ_rsaSignature OBJ_algorithm,11L + +#define SN_dsa_2 "DSA-old" +#define LN_dsa_2 "dsaEncryption-old" +#define NID_dsa_2 67 +#define OBJ_dsa_2 OBJ_algorithm,12L + +#define SN_dsaWithSHA "DSA-SHA" +#define LN_dsaWithSHA "dsaWithSHA" +#define NID_dsaWithSHA 66 +#define OBJ_dsaWithSHA OBJ_algorithm,13L + +#define SN_shaWithRSAEncryption "RSA-SHA" +#define LN_shaWithRSAEncryption "shaWithRSAEncryption" +#define NID_shaWithRSAEncryption 42 +#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L + +#define SN_des_ede_ecb "DES-EDE" +#define LN_des_ede_ecb "des-ede" +#define NID_des_ede_ecb 32 +#define OBJ_des_ede_ecb OBJ_algorithm,17L + +#define SN_des_ede3_ecb "DES-EDE3" +#define LN_des_ede3_ecb "des-ede3" +#define NID_des_ede3_ecb 33 + +#define SN_des_ede_cbc "DES-EDE-CBC" +#define LN_des_ede_cbc "des-ede-cbc" +#define NID_des_ede_cbc 43 + +#define SN_des_ede_cfb64 "DES-EDE-CFB" +#define LN_des_ede_cfb64 "des-ede-cfb" +#define NID_des_ede_cfb64 60 + +#define SN_des_ede3_cfb64 "DES-EDE3-CFB" +#define LN_des_ede3_cfb64 "des-ede3-cfb" +#define NID_des_ede3_cfb64 61 + +#define SN_des_ede_ofb64 "DES-EDE-OFB" +#define LN_des_ede_ofb64 "des-ede-ofb" +#define NID_des_ede_ofb64 62 + +#define SN_des_ede3_ofb64 "DES-EDE3-OFB" +#define LN_des_ede3_ofb64 "des-ede3-ofb" +#define NID_des_ede3_ofb64 63 + +#define SN_desx_cbc "DESX-CBC" +#define LN_desx_cbc "desx-cbc" +#define NID_desx_cbc 80 + +#define SN_sha "SHA" +#define LN_sha "sha" +#define NID_sha 41 +#define OBJ_sha OBJ_algorithm,18L + +#define SN_sha1 "SHA1" +#define LN_sha1 "sha1" +#define NID_sha1 64 +#define OBJ_sha1 OBJ_algorithm,26L + +#define SN_dsaWithSHA1_2 "DSA-SHA1-old" +#define LN_dsaWithSHA1_2 "dsaWithSHA1-old" +#define NID_dsaWithSHA1_2 70 +#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L + +#define SN_sha1WithRSA "RSA-SHA1-2" +#define LN_sha1WithRSA "sha1WithRSA" +#define NID_sha1WithRSA 115 +#define OBJ_sha1WithRSA OBJ_algorithm,29L + +#define SN_ripemd160 "RIPEMD160" +#define LN_ripemd160 "ripemd160" +#define NID_ripemd160 117 +#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L + +#define SN_ripemd160WithRSA "RSA-RIPEMD160" +#define LN_ripemd160WithRSA "ripemd160WithRSA" +#define NID_ripemd160WithRSA 119 +#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L + +#define SN_sxnet "SXNetID" +#define LN_sxnet "Strong Extranet ID" +#define NID_sxnet 143 +#define OBJ_sxnet 1L,3L,101L,1L,4L,1L + +#define SN_X500 "X500" +#define LN_X500 "directory services (X.500)" +#define NID_X500 11 +#define OBJ_X500 2L,5L + +#define SN_X509 "X509" +#define NID_X509 12 +#define OBJ_X509 OBJ_X500,4L + +#define SN_commonName "CN" +#define LN_commonName "commonName" +#define NID_commonName 13 +#define OBJ_commonName OBJ_X509,3L + +#define SN_surname "SN" +#define LN_surname "surname" +#define NID_surname 100 +#define OBJ_surname OBJ_X509,4L + +#define LN_serialNumber "serialNumber" +#define NID_serialNumber 105 +#define OBJ_serialNumber OBJ_X509,5L + +#define SN_countryName "C" +#define LN_countryName "countryName" +#define NID_countryName 14 +#define OBJ_countryName OBJ_X509,6L + +#define SN_localityName "L" +#define LN_localityName "localityName" +#define NID_localityName 15 +#define OBJ_localityName OBJ_X509,7L + +#define SN_stateOrProvinceName "ST" +#define LN_stateOrProvinceName "stateOrProvinceName" +#define NID_stateOrProvinceName 16 +#define OBJ_stateOrProvinceName OBJ_X509,8L + +#define SN_streetAddress "street" +#define LN_streetAddress "streetAddress" +#define NID_streetAddress 660 +#define OBJ_streetAddress OBJ_X509,9L + +#define SN_organizationName "O" +#define LN_organizationName "organizationName" +#define NID_organizationName 17 +#define OBJ_organizationName OBJ_X509,10L + +#define SN_organizationalUnitName "OU" +#define LN_organizationalUnitName "organizationalUnitName" +#define NID_organizationalUnitName 18 +#define OBJ_organizationalUnitName OBJ_X509,11L + +#define SN_title "title" +#define LN_title "title" +#define NID_title 106 +#define OBJ_title OBJ_X509,12L + +#define LN_description "description" +#define NID_description 107 +#define OBJ_description OBJ_X509,13L + +#define LN_searchGuide "searchGuide" +#define NID_searchGuide 859 +#define OBJ_searchGuide OBJ_X509,14L + +#define LN_businessCategory "businessCategory" +#define NID_businessCategory 860 +#define OBJ_businessCategory OBJ_X509,15L + +#define LN_postalAddress "postalAddress" +#define NID_postalAddress 861 +#define OBJ_postalAddress OBJ_X509,16L + +#define LN_postalCode "postalCode" +#define NID_postalCode 661 +#define OBJ_postalCode OBJ_X509,17L + +#define LN_postOfficeBox "postOfficeBox" +#define NID_postOfficeBox 862 +#define OBJ_postOfficeBox OBJ_X509,18L + +#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName" +#define NID_physicalDeliveryOfficeName 863 +#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L + +#define LN_telephoneNumber "telephoneNumber" +#define NID_telephoneNumber 864 +#define OBJ_telephoneNumber OBJ_X509,20L + +#define LN_telexNumber "telexNumber" +#define NID_telexNumber 865 +#define OBJ_telexNumber OBJ_X509,21L + +#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier" +#define NID_teletexTerminalIdentifier 866 +#define OBJ_teletexTerminalIdentifier OBJ_X509,22L + +#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber" +#define NID_facsimileTelephoneNumber 867 +#define OBJ_facsimileTelephoneNumber OBJ_X509,23L + +#define LN_x121Address "x121Address" +#define NID_x121Address 868 +#define OBJ_x121Address OBJ_X509,24L + +#define LN_internationaliSDNNumber "internationaliSDNNumber" +#define NID_internationaliSDNNumber 869 +#define OBJ_internationaliSDNNumber OBJ_X509,25L + +#define LN_registeredAddress "registeredAddress" +#define NID_registeredAddress 870 +#define OBJ_registeredAddress OBJ_X509,26L + +#define LN_destinationIndicator "destinationIndicator" +#define NID_destinationIndicator 871 +#define OBJ_destinationIndicator OBJ_X509,27L + +#define LN_preferredDeliveryMethod "preferredDeliveryMethod" +#define NID_preferredDeliveryMethod 872 +#define OBJ_preferredDeliveryMethod OBJ_X509,28L + +#define LN_presentationAddress "presentationAddress" +#define NID_presentationAddress 873 +#define OBJ_presentationAddress OBJ_X509,29L + +#define LN_supportedApplicationContext "supportedApplicationContext" +#define NID_supportedApplicationContext 874 +#define OBJ_supportedApplicationContext OBJ_X509,30L + +#define SN_member "member" +#define NID_member 875 +#define OBJ_member OBJ_X509,31L + +#define SN_owner "owner" +#define NID_owner 876 +#define OBJ_owner OBJ_X509,32L + +#define LN_roleOccupant "roleOccupant" +#define NID_roleOccupant 877 +#define OBJ_roleOccupant OBJ_X509,33L + +#define SN_seeAlso "seeAlso" +#define NID_seeAlso 878 +#define OBJ_seeAlso OBJ_X509,34L + +#define LN_userPassword "userPassword" +#define NID_userPassword 879 +#define OBJ_userPassword OBJ_X509,35L + +#define LN_userCertificate "userCertificate" +#define NID_userCertificate 880 +#define OBJ_userCertificate OBJ_X509,36L + +#define LN_cACertificate "cACertificate" +#define NID_cACertificate 881 +#define OBJ_cACertificate OBJ_X509,37L + +#define LN_authorityRevocationList "authorityRevocationList" +#define NID_authorityRevocationList 882 +#define OBJ_authorityRevocationList OBJ_X509,38L + +#define LN_certificateRevocationList "certificateRevocationList" +#define NID_certificateRevocationList 883 +#define OBJ_certificateRevocationList OBJ_X509,39L + +#define LN_crossCertificatePair "crossCertificatePair" +#define NID_crossCertificatePair 884 +#define OBJ_crossCertificatePair OBJ_X509,40L + +#define SN_name "name" +#define LN_name "name" +#define NID_name 173 +#define OBJ_name OBJ_X509,41L + +#define SN_givenName "GN" +#define LN_givenName "givenName" +#define NID_givenName 99 +#define OBJ_givenName OBJ_X509,42L + +#define SN_initials "initials" +#define LN_initials "initials" +#define NID_initials 101 +#define OBJ_initials OBJ_X509,43L + +#define LN_generationQualifier "generationQualifier" +#define NID_generationQualifier 509 +#define OBJ_generationQualifier OBJ_X509,44L + +#define LN_x500UniqueIdentifier "x500UniqueIdentifier" +#define NID_x500UniqueIdentifier 503 +#define OBJ_x500UniqueIdentifier OBJ_X509,45L + +#define SN_dnQualifier "dnQualifier" +#define LN_dnQualifier "dnQualifier" +#define NID_dnQualifier 174 +#define OBJ_dnQualifier OBJ_X509,46L + +#define LN_enhancedSearchGuide "enhancedSearchGuide" +#define NID_enhancedSearchGuide 885 +#define OBJ_enhancedSearchGuide OBJ_X509,47L + +#define LN_protocolInformation "protocolInformation" +#define NID_protocolInformation 886 +#define OBJ_protocolInformation OBJ_X509,48L + +#define LN_distinguishedName "distinguishedName" +#define NID_distinguishedName 887 +#define OBJ_distinguishedName OBJ_X509,49L + +#define LN_uniqueMember "uniqueMember" +#define NID_uniqueMember 888 +#define OBJ_uniqueMember OBJ_X509,50L + +#define LN_houseIdentifier "houseIdentifier" +#define NID_houseIdentifier 889 +#define OBJ_houseIdentifier OBJ_X509,51L + +#define LN_supportedAlgorithms "supportedAlgorithms" +#define NID_supportedAlgorithms 890 +#define OBJ_supportedAlgorithms OBJ_X509,52L + +#define LN_deltaRevocationList "deltaRevocationList" +#define NID_deltaRevocationList 891 +#define OBJ_deltaRevocationList OBJ_X509,53L + +#define SN_dmdName "dmdName" +#define NID_dmdName 892 +#define OBJ_dmdName OBJ_X509,54L + +#define LN_pseudonym "pseudonym" +#define NID_pseudonym 510 +#define OBJ_pseudonym OBJ_X509,65L + +#define SN_role "role" +#define LN_role "role" +#define NID_role 400 +#define OBJ_role OBJ_X509,72L + +#define SN_X500algorithms "X500algorithms" +#define LN_X500algorithms "directory services - algorithms" +#define NID_X500algorithms 378 +#define OBJ_X500algorithms OBJ_X500,8L + +#define SN_rsa "RSA" +#define LN_rsa "rsa" +#define NID_rsa 19 +#define OBJ_rsa OBJ_X500algorithms,1L,1L + +#define SN_mdc2WithRSA "RSA-MDC2" +#define LN_mdc2WithRSA "mdc2WithRSA" +#define NID_mdc2WithRSA 96 +#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L + +#define SN_mdc2 "MDC2" +#define LN_mdc2 "mdc2" +#define NID_mdc2 95 +#define OBJ_mdc2 OBJ_X500algorithms,3L,101L + +#define SN_id_ce "id-ce" +#define NID_id_ce 81 +#define OBJ_id_ce OBJ_X500,29L + +#define SN_subject_directory_attributes "subjectDirectoryAttributes" +#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes" +#define NID_subject_directory_attributes 769 +#define OBJ_subject_directory_attributes OBJ_id_ce,9L + +#define SN_subject_key_identifier "subjectKeyIdentifier" +#define LN_subject_key_identifier "X509v3 Subject Key Identifier" +#define NID_subject_key_identifier 82 +#define OBJ_subject_key_identifier OBJ_id_ce,14L + +#define SN_key_usage "keyUsage" +#define LN_key_usage "X509v3 Key Usage" +#define NID_key_usage 83 +#define OBJ_key_usage OBJ_id_ce,15L + +#define SN_private_key_usage_period "privateKeyUsagePeriod" +#define LN_private_key_usage_period "X509v3 Private Key Usage Period" +#define NID_private_key_usage_period 84 +#define OBJ_private_key_usage_period OBJ_id_ce,16L + +#define SN_subject_alt_name "subjectAltName" +#define LN_subject_alt_name "X509v3 Subject Alternative Name" +#define NID_subject_alt_name 85 +#define OBJ_subject_alt_name OBJ_id_ce,17L + +#define SN_issuer_alt_name "issuerAltName" +#define LN_issuer_alt_name "X509v3 Issuer Alternative Name" +#define NID_issuer_alt_name 86 +#define OBJ_issuer_alt_name OBJ_id_ce,18L + +#define SN_basic_constraints "basicConstraints" +#define LN_basic_constraints "X509v3 Basic Constraints" +#define NID_basic_constraints 87 +#define OBJ_basic_constraints OBJ_id_ce,19L + +#define SN_crl_number "crlNumber" +#define LN_crl_number "X509v3 CRL Number" +#define NID_crl_number 88 +#define OBJ_crl_number OBJ_id_ce,20L + +#define SN_crl_reason "CRLReason" +#define LN_crl_reason "X509v3 CRL Reason Code" +#define NID_crl_reason 141 +#define OBJ_crl_reason OBJ_id_ce,21L + +#define SN_invalidity_date "invalidityDate" +#define LN_invalidity_date "Invalidity Date" +#define NID_invalidity_date 142 +#define OBJ_invalidity_date OBJ_id_ce,24L + +#define SN_delta_crl "deltaCRL" +#define LN_delta_crl "X509v3 Delta CRL Indicator" +#define NID_delta_crl 140 +#define OBJ_delta_crl OBJ_id_ce,27L + +#define SN_issuing_distribution_point "issuingDistributionPoint" +#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point" +#define NID_issuing_distribution_point 770 +#define OBJ_issuing_distribution_point OBJ_id_ce,28L + +#define SN_certificate_issuer "certificateIssuer" +#define LN_certificate_issuer "X509v3 Certificate Issuer" +#define NID_certificate_issuer 771 +#define OBJ_certificate_issuer OBJ_id_ce,29L + +#define SN_name_constraints "nameConstraints" +#define LN_name_constraints "X509v3 Name Constraints" +#define NID_name_constraints 666 +#define OBJ_name_constraints OBJ_id_ce,30L + +#define SN_crl_distribution_points "crlDistributionPoints" +#define LN_crl_distribution_points "X509v3 CRL Distribution Points" +#define NID_crl_distribution_points 103 +#define OBJ_crl_distribution_points OBJ_id_ce,31L + +#define SN_certificate_policies "certificatePolicies" +#define LN_certificate_policies "X509v3 Certificate Policies" +#define NID_certificate_policies 89 +#define OBJ_certificate_policies OBJ_id_ce,32L + +#define SN_any_policy "anyPolicy" +#define LN_any_policy "X509v3 Any Policy" +#define NID_any_policy 746 +#define OBJ_any_policy OBJ_certificate_policies,0L + +#define SN_policy_mappings "policyMappings" +#define LN_policy_mappings "X509v3 Policy Mappings" +#define NID_policy_mappings 747 +#define OBJ_policy_mappings OBJ_id_ce,33L + +#define SN_authority_key_identifier "authorityKeyIdentifier" +#define LN_authority_key_identifier "X509v3 Authority Key Identifier" +#define NID_authority_key_identifier 90 +#define OBJ_authority_key_identifier OBJ_id_ce,35L + +#define SN_policy_constraints "policyConstraints" +#define LN_policy_constraints "X509v3 Policy Constraints" +#define NID_policy_constraints 401 +#define OBJ_policy_constraints OBJ_id_ce,36L + +#define SN_ext_key_usage "extendedKeyUsage" +#define LN_ext_key_usage "X509v3 Extended Key Usage" +#define NID_ext_key_usage 126 +#define OBJ_ext_key_usage OBJ_id_ce,37L + +#define SN_freshest_crl "freshestCRL" +#define LN_freshest_crl "X509v3 Freshest CRL" +#define NID_freshest_crl 857 +#define OBJ_freshest_crl OBJ_id_ce,46L + +#define SN_inhibit_any_policy "inhibitAnyPolicy" +#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy" +#define NID_inhibit_any_policy 748 +#define OBJ_inhibit_any_policy OBJ_id_ce,54L + +#define SN_target_information "targetInformation" +#define LN_target_information "X509v3 AC Targeting" +#define NID_target_information 402 +#define OBJ_target_information OBJ_id_ce,55L + +#define SN_no_rev_avail "noRevAvail" +#define LN_no_rev_avail "X509v3 No Revocation Available" +#define NID_no_rev_avail 403 +#define OBJ_no_rev_avail OBJ_id_ce,56L + +#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage" +#define LN_anyExtendedKeyUsage "Any Extended Key Usage" +#define NID_anyExtendedKeyUsage 910 +#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L + +#define SN_netscape "Netscape" +#define LN_netscape "Netscape Communications Corp." +#define NID_netscape 57 +#define OBJ_netscape 2L,16L,840L,1L,113730L + +#define SN_netscape_cert_extension "nsCertExt" +#define LN_netscape_cert_extension "Netscape Certificate Extension" +#define NID_netscape_cert_extension 58 +#define OBJ_netscape_cert_extension OBJ_netscape,1L + +#define SN_netscape_data_type "nsDataType" +#define LN_netscape_data_type "Netscape Data Type" +#define NID_netscape_data_type 59 +#define OBJ_netscape_data_type OBJ_netscape,2L + +#define SN_netscape_cert_type "nsCertType" +#define LN_netscape_cert_type "Netscape Cert Type" +#define NID_netscape_cert_type 71 +#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L + +#define SN_netscape_base_url "nsBaseUrl" +#define LN_netscape_base_url "Netscape Base Url" +#define NID_netscape_base_url 72 +#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L + +#define SN_netscape_revocation_url "nsRevocationUrl" +#define LN_netscape_revocation_url "Netscape Revocation Url" +#define NID_netscape_revocation_url 73 +#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L + +#define SN_netscape_ca_revocation_url "nsCaRevocationUrl" +#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url" +#define NID_netscape_ca_revocation_url 74 +#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L + +#define SN_netscape_renewal_url "nsRenewalUrl" +#define LN_netscape_renewal_url "Netscape Renewal Url" +#define NID_netscape_renewal_url 75 +#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L + +#define SN_netscape_ca_policy_url "nsCaPolicyUrl" +#define LN_netscape_ca_policy_url "Netscape CA Policy Url" +#define NID_netscape_ca_policy_url 76 +#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L + +#define SN_netscape_ssl_server_name "nsSslServerName" +#define LN_netscape_ssl_server_name "Netscape SSL Server Name" +#define NID_netscape_ssl_server_name 77 +#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L + +#define SN_netscape_comment "nsComment" +#define LN_netscape_comment "Netscape Comment" +#define NID_netscape_comment 78 +#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L + +#define SN_netscape_cert_sequence "nsCertSequence" +#define LN_netscape_cert_sequence "Netscape Certificate Sequence" +#define NID_netscape_cert_sequence 79 +#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L + +#define SN_ns_sgc "nsSGC" +#define LN_ns_sgc "Netscape Server Gated Crypto" +#define NID_ns_sgc 139 +#define OBJ_ns_sgc OBJ_netscape,4L,1L + +#define SN_org "ORG" +#define LN_org "org" +#define NID_org 379 +#define OBJ_org OBJ_iso,3L + +#define SN_dod "DOD" +#define LN_dod "dod" +#define NID_dod 380 +#define OBJ_dod OBJ_org,6L + +#define SN_iana "IANA" +#define LN_iana "iana" +#define NID_iana 381 +#define OBJ_iana OBJ_dod,1L + +#define OBJ_internet OBJ_iana + +#define SN_Directory "directory" +#define LN_Directory "Directory" +#define NID_Directory 382 +#define OBJ_Directory OBJ_internet,1L + +#define SN_Management "mgmt" +#define LN_Management "Management" +#define NID_Management 383 +#define OBJ_Management OBJ_internet,2L + +#define SN_Experimental "experimental" +#define LN_Experimental "Experimental" +#define NID_Experimental 384 +#define OBJ_Experimental OBJ_internet,3L + +#define SN_Private "private" +#define LN_Private "Private" +#define NID_Private 385 +#define OBJ_Private OBJ_internet,4L + +#define SN_Security "security" +#define LN_Security "Security" +#define NID_Security 386 +#define OBJ_Security OBJ_internet,5L + +#define SN_SNMPv2 "snmpv2" +#define LN_SNMPv2 "SNMPv2" +#define NID_SNMPv2 387 +#define OBJ_SNMPv2 OBJ_internet,6L + +#define LN_Mail "Mail" +#define NID_Mail 388 +#define OBJ_Mail OBJ_internet,7L + +#define SN_Enterprises "enterprises" +#define LN_Enterprises "Enterprises" +#define NID_Enterprises 389 +#define OBJ_Enterprises OBJ_Private,1L + +#define SN_dcObject "dcobject" +#define LN_dcObject "dcObject" +#define NID_dcObject 390 +#define OBJ_dcObject OBJ_Enterprises,1466L,344L + +#define OBJ_extendedValidation OBJ_Enterprises,311L,60L + +#define LN_jurisdictionLocalityName "jurisdictionLocalityName" +#define NID_jurisdictionLocalityName 956 +#define OBJ_jurisdictionLocalityName OBJ_extendedValidation,2L,1L,1L + +#define LN_jurisdictionStateOrProvinceName "jurisdictionStateOrProvinceName" +#define NID_jurisdictionStateOrProvinceName 957 +#define OBJ_jurisdictionStateOrProvinceName OBJ_extendedValidation,2L,1L,2L + +#define LN_jurisdictionCountryName "jurisdictionCountryName" +#define NID_jurisdictionCountryName 958 +#define OBJ_jurisdictionCountryName OBJ_extendedValidation,2L,1L,3L + +#define SN_mime_mhs "mime-mhs" +#define LN_mime_mhs "MIME MHS" +#define NID_mime_mhs 504 +#define OBJ_mime_mhs OBJ_Mail,1L + +#define SN_mime_mhs_headings "mime-mhs-headings" +#define LN_mime_mhs_headings "mime-mhs-headings" +#define NID_mime_mhs_headings 505 +#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L + +#define SN_mime_mhs_bodies "mime-mhs-bodies" +#define LN_mime_mhs_bodies "mime-mhs-bodies" +#define NID_mime_mhs_bodies 506 +#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L + +#define SN_id_hex_partial_message "id-hex-partial-message" +#define LN_id_hex_partial_message "id-hex-partial-message" +#define NID_id_hex_partial_message 507 +#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L + +#define SN_id_hex_multipart_message "id-hex-multipart-message" +#define LN_id_hex_multipart_message "id-hex-multipart-message" +#define NID_id_hex_multipart_message 508 +#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L + +#define SN_rle_compression "RLE" +#define LN_rle_compression "run length compression" +#define NID_rle_compression 124 +#define OBJ_rle_compression 1L,1L,1L,1L,666L,1L + +#define SN_zlib_compression "ZLIB" +#define LN_zlib_compression "zlib compression" +#define NID_zlib_compression 125 +#define OBJ_zlib_compression OBJ_id_smime_alg,8L + +#define OBJ_csor 2L,16L,840L,1L,101L,3L + +#define OBJ_nistAlgorithms OBJ_csor,4L + +#define OBJ_aes OBJ_nistAlgorithms,1L + +#define SN_aes_128_ecb "AES-128-ECB" +#define LN_aes_128_ecb "aes-128-ecb" +#define NID_aes_128_ecb 418 +#define OBJ_aes_128_ecb OBJ_aes,1L + +#define SN_aes_128_cbc "AES-128-CBC" +#define LN_aes_128_cbc "aes-128-cbc" +#define NID_aes_128_cbc 419 +#define OBJ_aes_128_cbc OBJ_aes,2L + +#define SN_aes_128_ofb128 "AES-128-OFB" +#define LN_aes_128_ofb128 "aes-128-ofb" +#define NID_aes_128_ofb128 420 +#define OBJ_aes_128_ofb128 OBJ_aes,3L + +#define SN_aes_128_cfb128 "AES-128-CFB" +#define LN_aes_128_cfb128 "aes-128-cfb" +#define NID_aes_128_cfb128 421 +#define OBJ_aes_128_cfb128 OBJ_aes,4L + +#define SN_id_aes128_wrap "id-aes128-wrap" +#define NID_id_aes128_wrap 788 +#define OBJ_id_aes128_wrap OBJ_aes,5L + +#define SN_aes_128_gcm "id-aes128-GCM" +#define LN_aes_128_gcm "aes-128-gcm" +#define NID_aes_128_gcm 895 +#define OBJ_aes_128_gcm OBJ_aes,6L + +#define SN_aes_128_ccm "id-aes128-CCM" +#define LN_aes_128_ccm "aes-128-ccm" +#define NID_aes_128_ccm 896 +#define OBJ_aes_128_ccm OBJ_aes,7L + +#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad" +#define NID_id_aes128_wrap_pad 897 +#define OBJ_id_aes128_wrap_pad OBJ_aes,8L + +#define SN_aes_192_ecb "AES-192-ECB" +#define LN_aes_192_ecb "aes-192-ecb" +#define NID_aes_192_ecb 422 +#define OBJ_aes_192_ecb OBJ_aes,21L + +#define SN_aes_192_cbc "AES-192-CBC" +#define LN_aes_192_cbc "aes-192-cbc" +#define NID_aes_192_cbc 423 +#define OBJ_aes_192_cbc OBJ_aes,22L + +#define SN_aes_192_ofb128 "AES-192-OFB" +#define LN_aes_192_ofb128 "aes-192-ofb" +#define NID_aes_192_ofb128 424 +#define OBJ_aes_192_ofb128 OBJ_aes,23L + +#define SN_aes_192_cfb128 "AES-192-CFB" +#define LN_aes_192_cfb128 "aes-192-cfb" +#define NID_aes_192_cfb128 425 +#define OBJ_aes_192_cfb128 OBJ_aes,24L + +#define SN_id_aes192_wrap "id-aes192-wrap" +#define NID_id_aes192_wrap 789 +#define OBJ_id_aes192_wrap OBJ_aes,25L + +#define SN_aes_192_gcm "id-aes192-GCM" +#define LN_aes_192_gcm "aes-192-gcm" +#define NID_aes_192_gcm 898 +#define OBJ_aes_192_gcm OBJ_aes,26L + +#define SN_aes_192_ccm "id-aes192-CCM" +#define LN_aes_192_ccm "aes-192-ccm" +#define NID_aes_192_ccm 899 +#define OBJ_aes_192_ccm OBJ_aes,27L + +#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad" +#define NID_id_aes192_wrap_pad 900 +#define OBJ_id_aes192_wrap_pad OBJ_aes,28L + +#define SN_aes_256_ecb "AES-256-ECB" +#define LN_aes_256_ecb "aes-256-ecb" +#define NID_aes_256_ecb 426 +#define OBJ_aes_256_ecb OBJ_aes,41L + +#define SN_aes_256_cbc "AES-256-CBC" +#define LN_aes_256_cbc "aes-256-cbc" +#define NID_aes_256_cbc 427 +#define OBJ_aes_256_cbc OBJ_aes,42L + +#define SN_aes_256_ofb128 "AES-256-OFB" +#define LN_aes_256_ofb128 "aes-256-ofb" +#define NID_aes_256_ofb128 428 +#define OBJ_aes_256_ofb128 OBJ_aes,43L + +#define SN_aes_256_cfb128 "AES-256-CFB" +#define LN_aes_256_cfb128 "aes-256-cfb" +#define NID_aes_256_cfb128 429 +#define OBJ_aes_256_cfb128 OBJ_aes,44L + +#define SN_id_aes256_wrap "id-aes256-wrap" +#define NID_id_aes256_wrap 790 +#define OBJ_id_aes256_wrap OBJ_aes,45L + +#define SN_aes_256_gcm "id-aes256-GCM" +#define LN_aes_256_gcm "aes-256-gcm" +#define NID_aes_256_gcm 901 +#define OBJ_aes_256_gcm OBJ_aes,46L + +#define SN_aes_256_ccm "id-aes256-CCM" +#define LN_aes_256_ccm "aes-256-ccm" +#define NID_aes_256_ccm 902 +#define OBJ_aes_256_ccm OBJ_aes,47L + +#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad" +#define NID_id_aes256_wrap_pad 903 +#define OBJ_id_aes256_wrap_pad OBJ_aes,48L + +#define SN_aes_128_cfb1 "AES-128-CFB1" +#define LN_aes_128_cfb1 "aes-128-cfb1" +#define NID_aes_128_cfb1 650 + +#define SN_aes_192_cfb1 "AES-192-CFB1" +#define LN_aes_192_cfb1 "aes-192-cfb1" +#define NID_aes_192_cfb1 651 + +#define SN_aes_256_cfb1 "AES-256-CFB1" +#define LN_aes_256_cfb1 "aes-256-cfb1" +#define NID_aes_256_cfb1 652 + +#define SN_aes_128_cfb8 "AES-128-CFB8" +#define LN_aes_128_cfb8 "aes-128-cfb8" +#define NID_aes_128_cfb8 653 + +#define SN_aes_192_cfb8 "AES-192-CFB8" +#define LN_aes_192_cfb8 "aes-192-cfb8" +#define NID_aes_192_cfb8 654 + +#define SN_aes_256_cfb8 "AES-256-CFB8" +#define LN_aes_256_cfb8 "aes-256-cfb8" +#define NID_aes_256_cfb8 655 + +#define SN_aes_128_ctr "AES-128-CTR" +#define LN_aes_128_ctr "aes-128-ctr" +#define NID_aes_128_ctr 904 + +#define SN_aes_192_ctr "AES-192-CTR" +#define LN_aes_192_ctr "aes-192-ctr" +#define NID_aes_192_ctr 905 + +#define SN_aes_256_ctr "AES-256-CTR" +#define LN_aes_256_ctr "aes-256-ctr" +#define NID_aes_256_ctr 906 + +#define SN_aes_128_xts "AES-128-XTS" +#define LN_aes_128_xts "aes-128-xts" +#define NID_aes_128_xts 913 + +#define SN_aes_256_xts "AES-256-XTS" +#define LN_aes_256_xts "aes-256-xts" +#define NID_aes_256_xts 914 + +#define SN_des_cfb1 "DES-CFB1" +#define LN_des_cfb1 "des-cfb1" +#define NID_des_cfb1 656 + +#define SN_des_cfb8 "DES-CFB8" +#define LN_des_cfb8 "des-cfb8" +#define NID_des_cfb8 657 + +#define SN_des_ede3_cfb1 "DES-EDE3-CFB1" +#define LN_des_ede3_cfb1 "des-ede3-cfb1" +#define NID_des_ede3_cfb1 658 + +#define SN_des_ede3_cfb8 "DES-EDE3-CFB8" +#define LN_des_ede3_cfb8 "des-ede3-cfb8" +#define NID_des_ede3_cfb8 659 + +#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L + +#define SN_sha256 "SHA256" +#define LN_sha256 "sha256" +#define NID_sha256 672 +#define OBJ_sha256 OBJ_nist_hashalgs,1L + +#define SN_sha384 "SHA384" +#define LN_sha384 "sha384" +#define NID_sha384 673 +#define OBJ_sha384 OBJ_nist_hashalgs,2L + +#define SN_sha512 "SHA512" +#define LN_sha512 "sha512" +#define NID_sha512 674 +#define OBJ_sha512 OBJ_nist_hashalgs,3L + +#define SN_sha224 "SHA224" +#define LN_sha224 "sha224" +#define NID_sha224 675 +#define OBJ_sha224 OBJ_nist_hashalgs,4L + +#define SN_sha512_224 "SHA512-224" +#define LN_sha512_224 "sha512-224" +#define NID_sha512_224 1029 +#define OBJ_sha512_224 OBJ_nist_hashalgs,5L + +#define SN_sha512_256 "SHA512-256" +#define LN_sha512_256 "sha512-256" +#define NID_sha512_256 1030 +#define OBJ_sha512_256 OBJ_nist_hashalgs,6L + +#define SN_sha3_224 "SHA3-224" +#define LN_sha3_224 "sha3-224" +#define NID_sha3_224 1031 +#define OBJ_sha3_224 OBJ_nist_hashalgs,7L + +#define SN_sha3_256 "SHA3-256" +#define LN_sha3_256 "sha3-256" +#define NID_sha3_256 1032 +#define OBJ_sha3_256 OBJ_nist_hashalgs,8L + +#define SN_sha3_384 "SHA3-384" +#define LN_sha3_384 "sha3-384" +#define NID_sha3_384 1033 +#define OBJ_sha3_384 OBJ_nist_hashalgs,9L + +#define SN_sha3_512 "SHA3-512" +#define LN_sha3_512 "sha3-512" +#define NID_sha3_512 1034 +#define OBJ_sha3_512 OBJ_nist_hashalgs,10L + +#define SN_hmac_sha3_224 "id-hmacWithSHA3-224" +#define LN_hmac_sha3_224 "hmac-sha3-224" +#define NID_hmac_sha3_224 1035 +#define OBJ_hmac_sha3_224 OBJ_nist_hashalgs,13L + +#define SN_hmac_sha3_256 "id-hmacWithSHA3-256" +#define LN_hmac_sha3_256 "hmac-sha3-256" +#define NID_hmac_sha3_256 1036 +#define OBJ_hmac_sha3_256 OBJ_nist_hashalgs,14L + +#define SN_hmac_sha3_384 "id-hmacWithSHA3-384" +#define LN_hmac_sha3_384 "hmac-sha3-384" +#define NID_hmac_sha3_384 1037 +#define OBJ_hmac_sha3_384 OBJ_nist_hashalgs,15L + +#define SN_hmac_sha3_512 "id-hmacWithSHA3-512" +#define LN_hmac_sha3_512 "hmac-sha3-512" +#define NID_hmac_sha3_512 1038 +#define OBJ_hmac_sha3_512 OBJ_nist_hashalgs,16L + +#define OBJ_nist_sigalgs OBJ_nistAlgorithms,3L + +#define SN_dsa_with_SHA224 "id-dsa-with-sha224" +#define LN_dsa_with_SHA224 "dsa_with_SHA224" +#define NID_dsa_with_SHA224 802 +#define OBJ_dsa_with_SHA224 OBJ_nist_sigalgs,1L + +#define SN_dsa_with_SHA256 "id-dsa-with-sha256" +#define LN_dsa_with_SHA256 "dsa_with_SHA256" +#define NID_dsa_with_SHA256 803 +#define OBJ_dsa_with_SHA256 OBJ_nist_sigalgs,2L + +#define SN_dsa_with_SHA384 "id-dsa-with-sha384" +#define LN_dsa_with_SHA384 "dsa_with_SHA384" +#define NID_dsa_with_SHA384 1039 +#define OBJ_dsa_with_SHA384 OBJ_nist_sigalgs,3L + +#define SN_dsa_with_SHA512 "id-dsa-with-sha512" +#define LN_dsa_with_SHA512 "dsa_with_SHA512" +#define NID_dsa_with_SHA512 1040 +#define OBJ_dsa_with_SHA512 OBJ_nist_sigalgs,4L + +#define SN_dsa_with_SHA3_224 "id-dsa-with-sha3-224" +#define LN_dsa_with_SHA3_224 "dsa_with_SHA3-224" +#define NID_dsa_with_SHA3_224 1041 +#define OBJ_dsa_with_SHA3_224 OBJ_nist_sigalgs,5L + +#define SN_dsa_with_SHA3_256 "id-dsa-with-sha3-256" +#define LN_dsa_with_SHA3_256 "dsa_with_SHA3-256" +#define NID_dsa_with_SHA3_256 1042 +#define OBJ_dsa_with_SHA3_256 OBJ_nist_sigalgs,6L + +#define SN_dsa_with_SHA3_384 "id-dsa-with-sha3-384" +#define LN_dsa_with_SHA3_384 "dsa_with_SHA3-384" +#define NID_dsa_with_SHA3_384 1043 +#define OBJ_dsa_with_SHA3_384 OBJ_nist_sigalgs,7L + +#define SN_dsa_with_SHA3_512 "id-dsa-with-sha3-512" +#define LN_dsa_with_SHA3_512 "dsa_with_SHA3-512" +#define NID_dsa_with_SHA3_512 1044 +#define OBJ_dsa_with_SHA3_512 OBJ_nist_sigalgs,8L + +#define SN_ecdsa_with_SHA3_224 "id-ecdsa-with-sha3-224" +#define LN_ecdsa_with_SHA3_224 "ecdsa_with_SHA3-224" +#define NID_ecdsa_with_SHA3_224 1045 +#define OBJ_ecdsa_with_SHA3_224 OBJ_nist_sigalgs,9L + +#define SN_ecdsa_with_SHA3_256 "id-ecdsa-with-sha3-256" +#define LN_ecdsa_with_SHA3_256 "ecdsa_with_SHA3-256" +#define NID_ecdsa_with_SHA3_256 1046 +#define OBJ_ecdsa_with_SHA3_256 OBJ_nist_sigalgs,10L + +#define SN_ecdsa_with_SHA3_384 "id-ecdsa-with-sha3-384" +#define LN_ecdsa_with_SHA3_384 "ecdsa_with_SHA3-384" +#define NID_ecdsa_with_SHA3_384 1047 +#define OBJ_ecdsa_with_SHA3_384 OBJ_nist_sigalgs,11L + +#define SN_ecdsa_with_SHA3_512 "id-ecdsa-with-sha3-512" +#define LN_ecdsa_with_SHA3_512 "ecdsa_with_SHA3-512" +#define NID_ecdsa_with_SHA3_512 1048 +#define OBJ_ecdsa_with_SHA3_512 OBJ_nist_sigalgs,12L + +#define SN_RSA_SHA3_224 "id-rsassa-pkcs1-v1_5-with-sha3-224" +#define LN_RSA_SHA3_224 "RSA-SHA3-224" +#define NID_RSA_SHA3_224 1049 +#define OBJ_RSA_SHA3_224 OBJ_nist_sigalgs,13L + +#define SN_RSA_SHA3_256 "id-rsassa-pkcs1-v1_5-with-sha3-256" +#define LN_RSA_SHA3_256 "RSA-SHA3-256" +#define NID_RSA_SHA3_256 1050 +#define OBJ_RSA_SHA3_256 OBJ_nist_sigalgs,14L + +#define SN_RSA_SHA3_384 "id-rsassa-pkcs1-v1_5-with-sha3-384" +#define LN_RSA_SHA3_384 "RSA-SHA3-384" +#define NID_RSA_SHA3_384 1051 +#define OBJ_RSA_SHA3_384 OBJ_nist_sigalgs,15L + +#define SN_RSA_SHA3_512 "id-rsassa-pkcs1-v1_5-with-sha3-512" +#define LN_RSA_SHA3_512 "RSA-SHA3-512" +#define NID_RSA_SHA3_512 1052 +#define OBJ_RSA_SHA3_512 OBJ_nist_sigalgs,16L + +#define SN_hold_instruction_code "holdInstructionCode" +#define LN_hold_instruction_code "Hold Instruction Code" +#define NID_hold_instruction_code 430 +#define OBJ_hold_instruction_code OBJ_id_ce,23L + +#define OBJ_holdInstruction OBJ_X9_57,2L + +#define SN_hold_instruction_none "holdInstructionNone" +#define LN_hold_instruction_none "Hold Instruction None" +#define NID_hold_instruction_none 431 +#define OBJ_hold_instruction_none OBJ_holdInstruction,1L + +#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer" +#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer" +#define NID_hold_instruction_call_issuer 432 +#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L + +#define SN_hold_instruction_reject "holdInstructionReject" +#define LN_hold_instruction_reject "Hold Instruction Reject" +#define NID_hold_instruction_reject 433 +#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L + +#define SN_data "data" +#define NID_data 434 +#define OBJ_data OBJ_itu_t,9L + +#define SN_pss "pss" +#define NID_pss 435 +#define OBJ_pss OBJ_data,2342L + +#define SN_ucl "ucl" +#define NID_ucl 436 +#define OBJ_ucl OBJ_pss,19200300L + +#define SN_pilot "pilot" +#define NID_pilot 437 +#define OBJ_pilot OBJ_ucl,100L + +#define LN_pilotAttributeType "pilotAttributeType" +#define NID_pilotAttributeType 438 +#define OBJ_pilotAttributeType OBJ_pilot,1L + +#define LN_pilotAttributeSyntax "pilotAttributeSyntax" +#define NID_pilotAttributeSyntax 439 +#define OBJ_pilotAttributeSyntax OBJ_pilot,3L + +#define LN_pilotObjectClass "pilotObjectClass" +#define NID_pilotObjectClass 440 +#define OBJ_pilotObjectClass OBJ_pilot,4L + +#define LN_pilotGroups "pilotGroups" +#define NID_pilotGroups 441 +#define OBJ_pilotGroups OBJ_pilot,10L + +#define LN_iA5StringSyntax "iA5StringSyntax" +#define NID_iA5StringSyntax 442 +#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L + +#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax" +#define NID_caseIgnoreIA5StringSyntax 443 +#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L + +#define LN_pilotObject "pilotObject" +#define NID_pilotObject 444 +#define OBJ_pilotObject OBJ_pilotObjectClass,3L + +#define LN_pilotPerson "pilotPerson" +#define NID_pilotPerson 445 +#define OBJ_pilotPerson OBJ_pilotObjectClass,4L + +#define SN_account "account" +#define NID_account 446 +#define OBJ_account OBJ_pilotObjectClass,5L + +#define SN_document "document" +#define NID_document 447 +#define OBJ_document OBJ_pilotObjectClass,6L + +#define SN_room "room" +#define NID_room 448 +#define OBJ_room OBJ_pilotObjectClass,7L + +#define LN_documentSeries "documentSeries" +#define NID_documentSeries 449 +#define OBJ_documentSeries OBJ_pilotObjectClass,9L + +#define SN_Domain "domain" +#define LN_Domain "Domain" +#define NID_Domain 392 +#define OBJ_Domain OBJ_pilotObjectClass,13L + +#define LN_rFC822localPart "rFC822localPart" +#define NID_rFC822localPart 450 +#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L + +#define LN_dNSDomain "dNSDomain" +#define NID_dNSDomain 451 +#define OBJ_dNSDomain OBJ_pilotObjectClass,15L + +#define LN_domainRelatedObject "domainRelatedObject" +#define NID_domainRelatedObject 452 +#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L + +#define LN_friendlyCountry "friendlyCountry" +#define NID_friendlyCountry 453 +#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L + +#define LN_simpleSecurityObject "simpleSecurityObject" +#define NID_simpleSecurityObject 454 +#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L + +#define LN_pilotOrganization "pilotOrganization" +#define NID_pilotOrganization 455 +#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L + +#define LN_pilotDSA "pilotDSA" +#define NID_pilotDSA 456 +#define OBJ_pilotDSA OBJ_pilotObjectClass,21L + +#define LN_qualityLabelledData "qualityLabelledData" +#define NID_qualityLabelledData 457 +#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L + +#define SN_userId "UID" +#define LN_userId "userId" +#define NID_userId 458 +#define OBJ_userId OBJ_pilotAttributeType,1L + +#define LN_textEncodedORAddress "textEncodedORAddress" +#define NID_textEncodedORAddress 459 +#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L + +#define SN_rfc822Mailbox "mail" +#define LN_rfc822Mailbox "rfc822Mailbox" +#define NID_rfc822Mailbox 460 +#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L + +#define SN_info "info" +#define NID_info 461 +#define OBJ_info OBJ_pilotAttributeType,4L + +#define LN_favouriteDrink "favouriteDrink" +#define NID_favouriteDrink 462 +#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L + +#define LN_roomNumber "roomNumber" +#define NID_roomNumber 463 +#define OBJ_roomNumber OBJ_pilotAttributeType,6L + +#define SN_photo "photo" +#define NID_photo 464 +#define OBJ_photo OBJ_pilotAttributeType,7L + +#define LN_userClass "userClass" +#define NID_userClass 465 +#define OBJ_userClass OBJ_pilotAttributeType,8L + +#define SN_host "host" +#define NID_host 466 +#define OBJ_host OBJ_pilotAttributeType,9L + +#define SN_manager "manager" +#define NID_manager 467 +#define OBJ_manager OBJ_pilotAttributeType,10L + +#define LN_documentIdentifier "documentIdentifier" +#define NID_documentIdentifier 468 +#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L + +#define LN_documentTitle "documentTitle" +#define NID_documentTitle 469 +#define OBJ_documentTitle OBJ_pilotAttributeType,12L + +#define LN_documentVersion "documentVersion" +#define NID_documentVersion 470 +#define OBJ_documentVersion OBJ_pilotAttributeType,13L + +#define LN_documentAuthor "documentAuthor" +#define NID_documentAuthor 471 +#define OBJ_documentAuthor OBJ_pilotAttributeType,14L + +#define LN_documentLocation "documentLocation" +#define NID_documentLocation 472 +#define OBJ_documentLocation OBJ_pilotAttributeType,15L + +#define LN_homeTelephoneNumber "homeTelephoneNumber" +#define NID_homeTelephoneNumber 473 +#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L + +#define SN_secretary "secretary" +#define NID_secretary 474 +#define OBJ_secretary OBJ_pilotAttributeType,21L + +#define LN_otherMailbox "otherMailbox" +#define NID_otherMailbox 475 +#define OBJ_otherMailbox OBJ_pilotAttributeType,22L + +#define LN_lastModifiedTime "lastModifiedTime" +#define NID_lastModifiedTime 476 +#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L + +#define LN_lastModifiedBy "lastModifiedBy" +#define NID_lastModifiedBy 477 +#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L + +#define SN_domainComponent "DC" +#define LN_domainComponent "domainComponent" +#define NID_domainComponent 391 +#define OBJ_domainComponent OBJ_pilotAttributeType,25L + +#define LN_aRecord "aRecord" +#define NID_aRecord 478 +#define OBJ_aRecord OBJ_pilotAttributeType,26L + +#define LN_pilotAttributeType27 "pilotAttributeType27" +#define NID_pilotAttributeType27 479 +#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L + +#define LN_mXRecord "mXRecord" +#define NID_mXRecord 480 +#define OBJ_mXRecord OBJ_pilotAttributeType,28L + +#define LN_nSRecord "nSRecord" +#define NID_nSRecord 481 +#define OBJ_nSRecord OBJ_pilotAttributeType,29L + +#define LN_sOARecord "sOARecord" +#define NID_sOARecord 482 +#define OBJ_sOARecord OBJ_pilotAttributeType,30L + +#define LN_cNAMERecord "cNAMERecord" +#define NID_cNAMERecord 483 +#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L + +#define LN_associatedDomain "associatedDomain" +#define NID_associatedDomain 484 +#define OBJ_associatedDomain OBJ_pilotAttributeType,37L + +#define LN_associatedName "associatedName" +#define NID_associatedName 485 +#define OBJ_associatedName OBJ_pilotAttributeType,38L + +#define LN_homePostalAddress "homePostalAddress" +#define NID_homePostalAddress 486 +#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L + +#define LN_personalTitle "personalTitle" +#define NID_personalTitle 487 +#define OBJ_personalTitle OBJ_pilotAttributeType,40L + +#define LN_mobileTelephoneNumber "mobileTelephoneNumber" +#define NID_mobileTelephoneNumber 488 +#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L + +#define LN_pagerTelephoneNumber "pagerTelephoneNumber" +#define NID_pagerTelephoneNumber 489 +#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L + +#define LN_friendlyCountryName "friendlyCountryName" +#define NID_friendlyCountryName 490 +#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L + +#define LN_organizationalStatus "organizationalStatus" +#define NID_organizationalStatus 491 +#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L + +#define LN_janetMailbox "janetMailbox" +#define NID_janetMailbox 492 +#define OBJ_janetMailbox OBJ_pilotAttributeType,46L + +#define LN_mailPreferenceOption "mailPreferenceOption" +#define NID_mailPreferenceOption 493 +#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L + +#define LN_buildingName "buildingName" +#define NID_buildingName 494 +#define OBJ_buildingName OBJ_pilotAttributeType,48L + +#define LN_dSAQuality "dSAQuality" +#define NID_dSAQuality 495 +#define OBJ_dSAQuality OBJ_pilotAttributeType,49L + +#define LN_singleLevelQuality "singleLevelQuality" +#define NID_singleLevelQuality 496 +#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L + +#define LN_subtreeMinimumQuality "subtreeMinimumQuality" +#define NID_subtreeMinimumQuality 497 +#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L + +#define LN_subtreeMaximumQuality "subtreeMaximumQuality" +#define NID_subtreeMaximumQuality 498 +#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L + +#define LN_personalSignature "personalSignature" +#define NID_personalSignature 499 +#define OBJ_personalSignature OBJ_pilotAttributeType,53L + +#define LN_dITRedirect "dITRedirect" +#define NID_dITRedirect 500 +#define OBJ_dITRedirect OBJ_pilotAttributeType,54L + +#define SN_audio "audio" +#define NID_audio 501 +#define OBJ_audio OBJ_pilotAttributeType,55L + +#define LN_documentPublisher "documentPublisher" +#define NID_documentPublisher 502 +#define OBJ_documentPublisher OBJ_pilotAttributeType,56L + +#define SN_id_set "id-set" +#define LN_id_set "Secure Electronic Transactions" +#define NID_id_set 512 +#define OBJ_id_set OBJ_international_organizations,42L + +#define SN_set_ctype "set-ctype" +#define LN_set_ctype "content types" +#define NID_set_ctype 513 +#define OBJ_set_ctype OBJ_id_set,0L + +#define SN_set_msgExt "set-msgExt" +#define LN_set_msgExt "message extensions" +#define NID_set_msgExt 514 +#define OBJ_set_msgExt OBJ_id_set,1L + +#define SN_set_attr "set-attr" +#define NID_set_attr 515 +#define OBJ_set_attr OBJ_id_set,3L + +#define SN_set_policy "set-policy" +#define NID_set_policy 516 +#define OBJ_set_policy OBJ_id_set,5L + +#define SN_set_certExt "set-certExt" +#define LN_set_certExt "certificate extensions" +#define NID_set_certExt 517 +#define OBJ_set_certExt OBJ_id_set,7L + +#define SN_set_brand "set-brand" +#define NID_set_brand 518 +#define OBJ_set_brand OBJ_id_set,8L + +#define SN_setct_PANData "setct-PANData" +#define NID_setct_PANData 519 +#define OBJ_setct_PANData OBJ_set_ctype,0L + +#define SN_setct_PANToken "setct-PANToken" +#define NID_setct_PANToken 520 +#define OBJ_setct_PANToken OBJ_set_ctype,1L + +#define SN_setct_PANOnly "setct-PANOnly" +#define NID_setct_PANOnly 521 +#define OBJ_setct_PANOnly OBJ_set_ctype,2L + +#define SN_setct_OIData "setct-OIData" +#define NID_setct_OIData 522 +#define OBJ_setct_OIData OBJ_set_ctype,3L + +#define SN_setct_PI "setct-PI" +#define NID_setct_PI 523 +#define OBJ_setct_PI OBJ_set_ctype,4L + +#define SN_setct_PIData "setct-PIData" +#define NID_setct_PIData 524 +#define OBJ_setct_PIData OBJ_set_ctype,5L + +#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned" +#define NID_setct_PIDataUnsigned 525 +#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L + +#define SN_setct_HODInput "setct-HODInput" +#define NID_setct_HODInput 526 +#define OBJ_setct_HODInput OBJ_set_ctype,7L + +#define SN_setct_AuthResBaggage "setct-AuthResBaggage" +#define NID_setct_AuthResBaggage 527 +#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L + +#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage" +#define NID_setct_AuthRevReqBaggage 528 +#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L + +#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage" +#define NID_setct_AuthRevResBaggage 529 +#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L + +#define SN_setct_CapTokenSeq "setct-CapTokenSeq" +#define NID_setct_CapTokenSeq 530 +#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L + +#define SN_setct_PInitResData "setct-PInitResData" +#define NID_setct_PInitResData 531 +#define OBJ_setct_PInitResData OBJ_set_ctype,12L + +#define SN_setct_PI_TBS "setct-PI-TBS" +#define NID_setct_PI_TBS 532 +#define OBJ_setct_PI_TBS OBJ_set_ctype,13L + +#define SN_setct_PResData "setct-PResData" +#define NID_setct_PResData 533 +#define OBJ_setct_PResData OBJ_set_ctype,14L + +#define SN_setct_AuthReqTBS "setct-AuthReqTBS" +#define NID_setct_AuthReqTBS 534 +#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L + +#define SN_setct_AuthResTBS "setct-AuthResTBS" +#define NID_setct_AuthResTBS 535 +#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L + +#define SN_setct_AuthResTBSX "setct-AuthResTBSX" +#define NID_setct_AuthResTBSX 536 +#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L + +#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS" +#define NID_setct_AuthTokenTBS 537 +#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L + +#define SN_setct_CapTokenData "setct-CapTokenData" +#define NID_setct_CapTokenData 538 +#define OBJ_setct_CapTokenData OBJ_set_ctype,20L + +#define SN_setct_CapTokenTBS "setct-CapTokenTBS" +#define NID_setct_CapTokenTBS 539 +#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L + +#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg" +#define NID_setct_AcqCardCodeMsg 540 +#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L + +#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS" +#define NID_setct_AuthRevReqTBS 541 +#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L + +#define SN_setct_AuthRevResData "setct-AuthRevResData" +#define NID_setct_AuthRevResData 542 +#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L + +#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS" +#define NID_setct_AuthRevResTBS 543 +#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L + +#define SN_setct_CapReqTBS "setct-CapReqTBS" +#define NID_setct_CapReqTBS 544 +#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L + +#define SN_setct_CapReqTBSX "setct-CapReqTBSX" +#define NID_setct_CapReqTBSX 545 +#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L + +#define SN_setct_CapResData "setct-CapResData" +#define NID_setct_CapResData 546 +#define OBJ_setct_CapResData OBJ_set_ctype,28L + +#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS" +#define NID_setct_CapRevReqTBS 547 +#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L + +#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX" +#define NID_setct_CapRevReqTBSX 548 +#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L + +#define SN_setct_CapRevResData "setct-CapRevResData" +#define NID_setct_CapRevResData 549 +#define OBJ_setct_CapRevResData OBJ_set_ctype,31L + +#define SN_setct_CredReqTBS "setct-CredReqTBS" +#define NID_setct_CredReqTBS 550 +#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L + +#define SN_setct_CredReqTBSX "setct-CredReqTBSX" +#define NID_setct_CredReqTBSX 551 +#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L + +#define SN_setct_CredResData "setct-CredResData" +#define NID_setct_CredResData 552 +#define OBJ_setct_CredResData OBJ_set_ctype,34L + +#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS" +#define NID_setct_CredRevReqTBS 553 +#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L + +#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX" +#define NID_setct_CredRevReqTBSX 554 +#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L + +#define SN_setct_CredRevResData "setct-CredRevResData" +#define NID_setct_CredRevResData 555 +#define OBJ_setct_CredRevResData OBJ_set_ctype,37L + +#define SN_setct_PCertReqData "setct-PCertReqData" +#define NID_setct_PCertReqData 556 +#define OBJ_setct_PCertReqData OBJ_set_ctype,38L + +#define SN_setct_PCertResTBS "setct-PCertResTBS" +#define NID_setct_PCertResTBS 557 +#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L + +#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData" +#define NID_setct_BatchAdminReqData 558 +#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L + +#define SN_setct_BatchAdminResData "setct-BatchAdminResData" +#define NID_setct_BatchAdminResData 559 +#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L + +#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS" +#define NID_setct_CardCInitResTBS 560 +#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L + +#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS" +#define NID_setct_MeAqCInitResTBS 561 +#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L + +#define SN_setct_RegFormResTBS "setct-RegFormResTBS" +#define NID_setct_RegFormResTBS 562 +#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L + +#define SN_setct_CertReqData "setct-CertReqData" +#define NID_setct_CertReqData 563 +#define OBJ_setct_CertReqData OBJ_set_ctype,45L + +#define SN_setct_CertReqTBS "setct-CertReqTBS" +#define NID_setct_CertReqTBS 564 +#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L + +#define SN_setct_CertResData "setct-CertResData" +#define NID_setct_CertResData 565 +#define OBJ_setct_CertResData OBJ_set_ctype,47L + +#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS" +#define NID_setct_CertInqReqTBS 566 +#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L + +#define SN_setct_ErrorTBS "setct-ErrorTBS" +#define NID_setct_ErrorTBS 567 +#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L + +#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE" +#define NID_setct_PIDualSignedTBE 568 +#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L + +#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE" +#define NID_setct_PIUnsignedTBE 569 +#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L + +#define SN_setct_AuthReqTBE "setct-AuthReqTBE" +#define NID_setct_AuthReqTBE 570 +#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L + +#define SN_setct_AuthResTBE "setct-AuthResTBE" +#define NID_setct_AuthResTBE 571 +#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L + +#define SN_setct_AuthResTBEX "setct-AuthResTBEX" +#define NID_setct_AuthResTBEX 572 +#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L + +#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE" +#define NID_setct_AuthTokenTBE 573 +#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L + +#define SN_setct_CapTokenTBE "setct-CapTokenTBE" +#define NID_setct_CapTokenTBE 574 +#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L + +#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX" +#define NID_setct_CapTokenTBEX 575 +#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L + +#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE" +#define NID_setct_AcqCardCodeMsgTBE 576 +#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L + +#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE" +#define NID_setct_AuthRevReqTBE 577 +#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L + +#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE" +#define NID_setct_AuthRevResTBE 578 +#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L + +#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB" +#define NID_setct_AuthRevResTBEB 579 +#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L + +#define SN_setct_CapReqTBE "setct-CapReqTBE" +#define NID_setct_CapReqTBE 580 +#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L + +#define SN_setct_CapReqTBEX "setct-CapReqTBEX" +#define NID_setct_CapReqTBEX 581 +#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L + +#define SN_setct_CapResTBE "setct-CapResTBE" +#define NID_setct_CapResTBE 582 +#define OBJ_setct_CapResTBE OBJ_set_ctype,64L + +#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE" +#define NID_setct_CapRevReqTBE 583 +#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L + +#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX" +#define NID_setct_CapRevReqTBEX 584 +#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L + +#define SN_setct_CapRevResTBE "setct-CapRevResTBE" +#define NID_setct_CapRevResTBE 585 +#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L + +#define SN_setct_CredReqTBE "setct-CredReqTBE" +#define NID_setct_CredReqTBE 586 +#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L + +#define SN_setct_CredReqTBEX "setct-CredReqTBEX" +#define NID_setct_CredReqTBEX 587 +#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L + +#define SN_setct_CredResTBE "setct-CredResTBE" +#define NID_setct_CredResTBE 588 +#define OBJ_setct_CredResTBE OBJ_set_ctype,70L + +#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE" +#define NID_setct_CredRevReqTBE 589 +#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L + +#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX" +#define NID_setct_CredRevReqTBEX 590 +#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L + +#define SN_setct_CredRevResTBE "setct-CredRevResTBE" +#define NID_setct_CredRevResTBE 591 +#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L + +#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE" +#define NID_setct_BatchAdminReqTBE 592 +#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L + +#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE" +#define NID_setct_BatchAdminResTBE 593 +#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L + +#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE" +#define NID_setct_RegFormReqTBE 594 +#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L + +#define SN_setct_CertReqTBE "setct-CertReqTBE" +#define NID_setct_CertReqTBE 595 +#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L + +#define SN_setct_CertReqTBEX "setct-CertReqTBEX" +#define NID_setct_CertReqTBEX 596 +#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L + +#define SN_setct_CertResTBE "setct-CertResTBE" +#define NID_setct_CertResTBE 597 +#define OBJ_setct_CertResTBE OBJ_set_ctype,79L + +#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS" +#define NID_setct_CRLNotificationTBS 598 +#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L + +#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS" +#define NID_setct_CRLNotificationResTBS 599 +#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L + +#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS" +#define NID_setct_BCIDistributionTBS 600 +#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L + +#define SN_setext_genCrypt "setext-genCrypt" +#define LN_setext_genCrypt "generic cryptogram" +#define NID_setext_genCrypt 601 +#define OBJ_setext_genCrypt OBJ_set_msgExt,1L + +#define SN_setext_miAuth "setext-miAuth" +#define LN_setext_miAuth "merchant initiated auth" +#define NID_setext_miAuth 602 +#define OBJ_setext_miAuth OBJ_set_msgExt,3L + +#define SN_setext_pinSecure "setext-pinSecure" +#define NID_setext_pinSecure 603 +#define OBJ_setext_pinSecure OBJ_set_msgExt,4L + +#define SN_setext_pinAny "setext-pinAny" +#define NID_setext_pinAny 604 +#define OBJ_setext_pinAny OBJ_set_msgExt,5L + +#define SN_setext_track2 "setext-track2" +#define NID_setext_track2 605 +#define OBJ_setext_track2 OBJ_set_msgExt,7L + +#define SN_setext_cv "setext-cv" +#define LN_setext_cv "additional verification" +#define NID_setext_cv 606 +#define OBJ_setext_cv OBJ_set_msgExt,8L + +#define SN_set_policy_root "set-policy-root" +#define NID_set_policy_root 607 +#define OBJ_set_policy_root OBJ_set_policy,0L + +#define SN_setCext_hashedRoot "setCext-hashedRoot" +#define NID_setCext_hashedRoot 608 +#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L + +#define SN_setCext_certType "setCext-certType" +#define NID_setCext_certType 609 +#define OBJ_setCext_certType OBJ_set_certExt,1L + +#define SN_setCext_merchData "setCext-merchData" +#define NID_setCext_merchData 610 +#define OBJ_setCext_merchData OBJ_set_certExt,2L + +#define SN_setCext_cCertRequired "setCext-cCertRequired" +#define NID_setCext_cCertRequired 611 +#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L + +#define SN_setCext_tunneling "setCext-tunneling" +#define NID_setCext_tunneling 612 +#define OBJ_setCext_tunneling OBJ_set_certExt,4L + +#define SN_setCext_setExt "setCext-setExt" +#define NID_setCext_setExt 613 +#define OBJ_setCext_setExt OBJ_set_certExt,5L + +#define SN_setCext_setQualf "setCext-setQualf" +#define NID_setCext_setQualf 614 +#define OBJ_setCext_setQualf OBJ_set_certExt,6L + +#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities" +#define NID_setCext_PGWYcapabilities 615 +#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L + +#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier" +#define NID_setCext_TokenIdentifier 616 +#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L + +#define SN_setCext_Track2Data "setCext-Track2Data" +#define NID_setCext_Track2Data 617 +#define OBJ_setCext_Track2Data OBJ_set_certExt,9L + +#define SN_setCext_TokenType "setCext-TokenType" +#define NID_setCext_TokenType 618 +#define OBJ_setCext_TokenType OBJ_set_certExt,10L + +#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities" +#define NID_setCext_IssuerCapabilities 619 +#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L + +#define SN_setAttr_Cert "setAttr-Cert" +#define NID_setAttr_Cert 620 +#define OBJ_setAttr_Cert OBJ_set_attr,0L + +#define SN_setAttr_PGWYcap "setAttr-PGWYcap" +#define LN_setAttr_PGWYcap "payment gateway capabilities" +#define NID_setAttr_PGWYcap 621 +#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L + +#define SN_setAttr_TokenType "setAttr-TokenType" +#define NID_setAttr_TokenType 622 +#define OBJ_setAttr_TokenType OBJ_set_attr,2L + +#define SN_setAttr_IssCap "setAttr-IssCap" +#define LN_setAttr_IssCap "issuer capabilities" +#define NID_setAttr_IssCap 623 +#define OBJ_setAttr_IssCap OBJ_set_attr,3L + +#define SN_set_rootKeyThumb "set-rootKeyThumb" +#define NID_set_rootKeyThumb 624 +#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L + +#define SN_set_addPolicy "set-addPolicy" +#define NID_set_addPolicy 625 +#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L + +#define SN_setAttr_Token_EMV "setAttr-Token-EMV" +#define NID_setAttr_Token_EMV 626 +#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L + +#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime" +#define NID_setAttr_Token_B0Prime 627 +#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L + +#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM" +#define NID_setAttr_IssCap_CVM 628 +#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L + +#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2" +#define NID_setAttr_IssCap_T2 629 +#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L + +#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig" +#define NID_setAttr_IssCap_Sig 630 +#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L + +#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm" +#define LN_setAttr_GenCryptgrm "generate cryptogram" +#define NID_setAttr_GenCryptgrm 631 +#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L + +#define SN_setAttr_T2Enc "setAttr-T2Enc" +#define LN_setAttr_T2Enc "encrypted track 2" +#define NID_setAttr_T2Enc 632 +#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L + +#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt" +#define LN_setAttr_T2cleartxt "cleartext track 2" +#define NID_setAttr_T2cleartxt 633 +#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L + +#define SN_setAttr_TokICCsig "setAttr-TokICCsig" +#define LN_setAttr_TokICCsig "ICC or token signature" +#define NID_setAttr_TokICCsig 634 +#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L + +#define SN_setAttr_SecDevSig "setAttr-SecDevSig" +#define LN_setAttr_SecDevSig "secure device signature" +#define NID_setAttr_SecDevSig 635 +#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L + +#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA" +#define NID_set_brand_IATA_ATA 636 +#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L + +#define SN_set_brand_Diners "set-brand-Diners" +#define NID_set_brand_Diners 637 +#define OBJ_set_brand_Diners OBJ_set_brand,30L + +#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress" +#define NID_set_brand_AmericanExpress 638 +#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L + +#define SN_set_brand_JCB "set-brand-JCB" +#define NID_set_brand_JCB 639 +#define OBJ_set_brand_JCB OBJ_set_brand,35L + +#define SN_set_brand_Visa "set-brand-Visa" +#define NID_set_brand_Visa 640 +#define OBJ_set_brand_Visa OBJ_set_brand,4L + +#define SN_set_brand_MasterCard "set-brand-MasterCard" +#define NID_set_brand_MasterCard 641 +#define OBJ_set_brand_MasterCard OBJ_set_brand,5L + +#define SN_set_brand_Novus "set-brand-Novus" +#define NID_set_brand_Novus 642 +#define OBJ_set_brand_Novus OBJ_set_brand,6011L + +#define SN_des_cdmf "DES-CDMF" +#define LN_des_cdmf "des-cdmf" +#define NID_des_cdmf 643 +#define OBJ_des_cdmf OBJ_rsadsi,3L,10L + +#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET" +#define NID_rsaOAEPEncryptionSET 644 +#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L + +#define SN_ipsec3 "Oakley-EC2N-3" +#define LN_ipsec3 "ipsec3" +#define NID_ipsec3 749 + +#define SN_ipsec4 "Oakley-EC2N-4" +#define LN_ipsec4 "ipsec4" +#define NID_ipsec4 750 + +#define SN_whirlpool "whirlpool" +#define NID_whirlpool 804 +#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L + +#define SN_cryptopro "cryptopro" +#define NID_cryptopro 805 +#define OBJ_cryptopro OBJ_member_body,643L,2L,2L + +#define SN_cryptocom "cryptocom" +#define NID_cryptocom 806 +#define OBJ_cryptocom OBJ_member_body,643L,2L,9L + +#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001" +#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001" +#define NID_id_GostR3411_94_with_GostR3410_2001 807 +#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L + +#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94" +#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94" +#define NID_id_GostR3411_94_with_GostR3410_94 808 +#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L + +#define SN_id_GostR3411_94 "md_gost94" +#define LN_id_GostR3411_94 "GOST R 34.11-94" +#define NID_id_GostR3411_94 809 +#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L + +#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94" +#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94" +#define NID_id_HMACGostR3411_94 810 +#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L + +#define SN_id_GostR3410_2001 "gost2001" +#define LN_id_GostR3410_2001 "GOST R 34.10-2001" +#define NID_id_GostR3410_2001 811 +#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L + +#define SN_id_GostR3410_94 "gost94" +#define LN_id_GostR3410_94 "GOST R 34.10-94" +#define NID_id_GostR3410_94 812 +#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L + +#define SN_id_Gost28147_89 "gost89" +#define LN_id_Gost28147_89 "GOST 28147-89" +#define NID_id_Gost28147_89 813 +#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L + +#define SN_gost89_cnt "gost89-cnt" +#define NID_gost89_cnt 814 + +#define SN_id_Gost28147_89_MAC "gost-mac" +#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC" +#define NID_id_Gost28147_89_MAC 815 +#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L + +#define SN_id_GostR3411_94_prf "prf-gostr3411-94" +#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF" +#define NID_id_GostR3411_94_prf 816 +#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L + +#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH" +#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH" +#define NID_id_GostR3410_2001DH 817 +#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L + +#define SN_id_GostR3410_94DH "id-GostR3410-94DH" +#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH" +#define NID_id_GostR3410_94DH 818 +#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L + +#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing" +#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819 +#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L + +#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing" +#define NID_id_Gost28147_89_None_KeyMeshing 820 +#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L + +#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet" +#define NID_id_GostR3411_94_TestParamSet 821 +#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L + +#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet" +#define NID_id_GostR3411_94_CryptoProParamSet 822 +#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L + +#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet" +#define NID_id_Gost28147_89_TestParamSet 823 +#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L + +#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824 +#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L + +#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825 +#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L + +#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826 +#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L + +#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827 +#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L + +#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829 +#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L + +#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" +#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830 +#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L + +#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet" +#define NID_id_GostR3410_94_TestParamSet 831 +#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L + +#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832 +#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L + +#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833 +#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L + +#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834 +#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L + +#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835 +#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L + +#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836 +#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L + +#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837 +#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L + +#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet" +#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838 +#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L + +#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet" +#define NID_id_GostR3410_2001_TestParamSet 839 +#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L + +#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840 +#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L + +#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841 +#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L + +#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842 +#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L + +#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843 +#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L + +#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet" +#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844 +#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L + +#define SN_id_GostR3410_94_a "id-GostR3410-94-a" +#define NID_id_GostR3410_94_a 845 +#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L + +#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis" +#define NID_id_GostR3410_94_aBis 846 +#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L + +#define SN_id_GostR3410_94_b "id-GostR3410-94-b" +#define NID_id_GostR3410_94_b 847 +#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L + +#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis" +#define NID_id_GostR3410_94_bBis 848 +#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L + +#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc" +#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet" +#define NID_id_Gost28147_89_cc 849 +#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L + +#define SN_id_GostR3410_94_cc "gost94cc" +#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom" +#define NID_id_GostR3410_94_cc 850 +#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L + +#define SN_id_GostR3410_2001_cc "gost2001cc" +#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom" +#define NID_id_GostR3410_2001_cc 851 +#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L + +#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc" +#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_94_cc 852 +#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L + +#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc" +#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" +#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853 +#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L + +#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc" +#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom" +#define NID_id_GostR3410_2001_ParamSet_cc 854 +#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L + +#define SN_sm3 "SM3" +#define LN_sm3 "sm3" +#define NID_sm3 968 +#define OBJ_sm3 1L,2L,156L,10197L,1L,401L + +#define SN_sm3WithRSAEncryption "RSA-SM3" +#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption" +#define NID_sm3WithRSAEncryption 969 +#define OBJ_sm3WithRSAEncryption 1L,2L,156L,10197L,1L,504L + +#define SN_camellia_128_cbc "CAMELLIA-128-CBC" +#define LN_camellia_128_cbc "camellia-128-cbc" +#define NID_camellia_128_cbc 751 +#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L + +#define SN_camellia_192_cbc "CAMELLIA-192-CBC" +#define LN_camellia_192_cbc "camellia-192-cbc" +#define NID_camellia_192_cbc 752 +#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L + +#define SN_camellia_256_cbc "CAMELLIA-256-CBC" +#define LN_camellia_256_cbc "camellia-256-cbc" +#define NID_camellia_256_cbc 753 +#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L + +#define SN_id_camellia128_wrap "id-camellia128-wrap" +#define NID_id_camellia128_wrap 907 +#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L + +#define SN_id_camellia192_wrap "id-camellia192-wrap" +#define NID_id_camellia192_wrap 908 +#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L + +#define SN_id_camellia256_wrap "id-camellia256-wrap" +#define NID_id_camellia256_wrap 909 +#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L + +#define OBJ_ntt_ds 0L,3L,4401L,5L + +#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L + +#define SN_camellia_128_ecb "CAMELLIA-128-ECB" +#define LN_camellia_128_ecb "camellia-128-ecb" +#define NID_camellia_128_ecb 754 +#define OBJ_camellia_128_ecb OBJ_camellia,1L + +#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB" +#define LN_camellia_128_ofb128 "camellia-128-ofb" +#define NID_camellia_128_ofb128 766 +#define OBJ_camellia_128_ofb128 OBJ_camellia,3L + +#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB" +#define LN_camellia_128_cfb128 "camellia-128-cfb" +#define NID_camellia_128_cfb128 757 +#define OBJ_camellia_128_cfb128 OBJ_camellia,4L + +#define SN_camellia_192_ecb "CAMELLIA-192-ECB" +#define LN_camellia_192_ecb "camellia-192-ecb" +#define NID_camellia_192_ecb 755 +#define OBJ_camellia_192_ecb OBJ_camellia,21L + +#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB" +#define LN_camellia_192_ofb128 "camellia-192-ofb" +#define NID_camellia_192_ofb128 767 +#define OBJ_camellia_192_ofb128 OBJ_camellia,23L + +#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB" +#define LN_camellia_192_cfb128 "camellia-192-cfb" +#define NID_camellia_192_cfb128 758 +#define OBJ_camellia_192_cfb128 OBJ_camellia,24L + +#define SN_camellia_256_ecb "CAMELLIA-256-ECB" +#define LN_camellia_256_ecb "camellia-256-ecb" +#define NID_camellia_256_ecb 756 +#define OBJ_camellia_256_ecb OBJ_camellia,41L + +#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB" +#define LN_camellia_256_ofb128 "camellia-256-ofb" +#define NID_camellia_256_ofb128 768 +#define OBJ_camellia_256_ofb128 OBJ_camellia,43L + +#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB" +#define LN_camellia_256_cfb128 "camellia-256-cfb" +#define NID_camellia_256_cfb128 759 +#define OBJ_camellia_256_cfb128 OBJ_camellia,44L + +#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1" +#define LN_camellia_128_cfb1 "camellia-128-cfb1" +#define NID_camellia_128_cfb1 760 + +#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1" +#define LN_camellia_192_cfb1 "camellia-192-cfb1" +#define NID_camellia_192_cfb1 761 + +#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1" +#define LN_camellia_256_cfb1 "camellia-256-cfb1" +#define NID_camellia_256_cfb1 762 + +#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8" +#define LN_camellia_128_cfb8 "camellia-128-cfb8" +#define NID_camellia_128_cfb8 763 + +#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8" +#define LN_camellia_192_cfb8 "camellia-192-cfb8" +#define NID_camellia_192_cfb8 764 + +#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8" +#define LN_camellia_256_cfb8 "camellia-256-cfb8" +#define NID_camellia_256_cfb8 765 + +#define SN_kisa "KISA" +#define LN_kisa "kisa" +#define NID_kisa 773 +#define OBJ_kisa OBJ_member_body,410L,200004L + +#define SN_seed_ecb "SEED-ECB" +#define LN_seed_ecb "seed-ecb" +#define NID_seed_ecb 776 +#define OBJ_seed_ecb OBJ_kisa,1L,3L + +#define SN_seed_cbc "SEED-CBC" +#define LN_seed_cbc "seed-cbc" +#define NID_seed_cbc 777 +#define OBJ_seed_cbc OBJ_kisa,1L,4L + +#define SN_seed_cfb128 "SEED-CFB" +#define LN_seed_cfb128 "seed-cfb" +#define NID_seed_cfb128 779 +#define OBJ_seed_cfb128 OBJ_kisa,1L,5L + +#define SN_seed_ofb128 "SEED-OFB" +#define LN_seed_ofb128 "seed-ofb" +#define NID_seed_ofb128 778 +#define OBJ_seed_ofb128 OBJ_kisa,1L,6L + +#define SN_ISO_CN "ISO-CN" +#define LN_ISO_CN "ISO CN Member Body" +#define NID_ISO_CN 970 +#define OBJ_ISO_CN OBJ_member_body,156L + +#define SN_oscca "oscca" +#define NID_oscca 971 +#define OBJ_oscca OBJ_ISO_CN,10197L + +#define SN_sm_scheme "sm-scheme" +#define NID_sm_scheme 972 +#define OBJ_sm_scheme OBJ_oscca,1L + +#define SN_sm4_ecb "SM4-ECB" +#define LN_sm4_ecb "sm4-ecb" +#define NID_sm4_ecb 973 +#define OBJ_sm4_ecb OBJ_sm_scheme,104L,1L + +#define SN_sm4_cbc "SM4-CBC" +#define LN_sm4_cbc "sm4-cbc" +#define NID_sm4_cbc 974 +#define OBJ_sm4_cbc OBJ_sm_scheme,104L,2L + +#define SN_sm4_ofb128 "SM4-OFB" +#define LN_sm4_ofb128 "sm4-ofb" +#define NID_sm4_ofb128 975 +#define OBJ_sm4_ofb128 OBJ_sm_scheme,104L,3L + +#define SN_sm4_cfb128 "SM4-CFB" +#define LN_sm4_cfb128 "sm4-cfb" +#define NID_sm4_cfb128 976 +#define OBJ_sm4_cfb128 OBJ_sm_scheme,104L,4L + +#define SN_sm4_cfb1 "SM4-CFB1" +#define LN_sm4_cfb1 "sm4-cfb1" +#define NID_sm4_cfb1 977 +#define OBJ_sm4_cfb1 OBJ_sm_scheme,104L,5L + +#define SN_sm4_cfb8 "SM4-CFB8" +#define LN_sm4_cfb8 "sm4-cfb8" +#define NID_sm4_cfb8 978 +#define OBJ_sm4_cfb8 OBJ_sm_scheme,104L,6L + +#define SN_sm4_ctr "SM4-CTR" +#define LN_sm4_ctr "sm4-ctr" +#define NID_sm4_ctr 979 +#define OBJ_sm4_ctr OBJ_sm_scheme,104L,7L + +#define SN_hmac "HMAC" +#define LN_hmac "hmac" +#define NID_hmac 855 + +#define SN_cmac "CMAC" +#define LN_cmac "cmac" +#define NID_cmac 894 + +#define SN_rc4_hmac_md5 "RC4-HMAC-MD5" +#define LN_rc4_hmac_md5 "rc4-hmac-md5" +#define NID_rc4_hmac_md5 915 + +#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1" +#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1" +#define NID_aes_128_cbc_hmac_sha1 916 + +#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1" +#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1" +#define NID_aes_192_cbc_hmac_sha1 917 + +#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1" +#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1" +#define NID_aes_256_cbc_hmac_sha1 918 + +#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L + +#define OBJ_secg_scheme OBJ_certicom_arc,1L + +#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme" +#define NID_dhSinglePass_stdDH_sha1kdf_scheme 980 +#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L + +#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme" +#define NID_dhSinglePass_stdDH_sha224kdf_scheme 981 +#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L + +#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme" +#define NID_dhSinglePass_stdDH_sha256kdf_scheme 982 +#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L + +#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme" +#define NID_dhSinglePass_stdDH_sha384kdf_scheme 983 +#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L + +#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme" +#define NID_dhSinglePass_stdDH_sha512kdf_scheme 984 +#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L + +#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 985 +#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L + +#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 986 +#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L + +#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 987 +#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L + +#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 988 +#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L + +#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme" +#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 989 +#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L + +#define SN_dh_std_kdf "dh-std-kdf" +#define NID_dh_std_kdf 990 + +#define SN_dh_cofactor_kdf "dh-cofactor-kdf" +#define NID_dh_cofactor_kdf 991 + +#define SN_ct_precert_scts "ct_precert_scts" +#define LN_ct_precert_scts "CT Precertificate SCTs" +#define NID_ct_precert_scts 1018 +#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L + +#define SN_ct_precert_poison "ct_precert_poison" +#define LN_ct_precert_poison "CT Precertificate Poison" +#define NID_ct_precert_poison 1019 +#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L + +#define SN_ct_precert_signer "ct_precert_signer" +#define LN_ct_precert_signer "CT Precertificate Signer" +#define NID_ct_precert_signer 1020 +#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L + +#define SN_ct_cert_scts "ct_cert_scts" +#define LN_ct_cert_scts "CT Certificate SCTs" +#define NID_ct_cert_scts 1021 +#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L + +#define SN_hkdf "HKDF" +#define LN_hkdf "hkdf" +#define NID_hkdf 1022 + +#define SN_teletrust "teletrust" +#define NID_teletrust 920 +#define OBJ_teletrust OBJ_identified_organization,36L + +#define SN_brainpool "brainpool" +#define NID_brainpool 921 +#define OBJ_brainpool OBJ_teletrust,3L,3L,2L,8L,1L + +#define SN_brainpoolP160r1 "brainpoolP160r1" +#define NID_brainpoolP160r1 922 +#define OBJ_brainpoolP160r1 OBJ_brainpool,1L,1L + +#define SN_brainpoolP160t1 "brainpoolP160t1" +#define NID_brainpoolP160t1 923 +#define OBJ_brainpoolP160t1 OBJ_brainpool,1L,2L + +#define SN_brainpoolP192r1 "brainpoolP192r1" +#define NID_brainpoolP192r1 924 +#define OBJ_brainpoolP192r1 OBJ_brainpool,1L,3L + +#define SN_brainpoolP192t1 "brainpoolP192t1" +#define NID_brainpoolP192t1 925 +#define OBJ_brainpoolP192t1 OBJ_brainpool,1L,4L + +#define SN_brainpoolP224r1 "brainpoolP224r1" +#define NID_brainpoolP224r1 926 +#define OBJ_brainpoolP224r1 OBJ_brainpool,1L,5L + +#define SN_brainpoolP224t1 "brainpoolP224t1" +#define NID_brainpoolP224t1 927 +#define OBJ_brainpoolP224t1 OBJ_brainpool,1L,6L + +#define SN_brainpoolP256r1 "brainpoolP256r1" +#define NID_brainpoolP256r1 928 +#define OBJ_brainpoolP256r1 OBJ_brainpool,1L,7L + +#define SN_brainpoolP256t1 "brainpoolP256t1" +#define NID_brainpoolP256t1 929 +#define OBJ_brainpoolP256t1 OBJ_brainpool,1L,8L + +#define SN_brainpoolP320r1 "brainpoolP320r1" +#define NID_brainpoolP320r1 930 +#define OBJ_brainpoolP320r1 OBJ_brainpool,1L,9L + +#define SN_brainpoolP320t1 "brainpoolP320t1" +#define NID_brainpoolP320t1 931 +#define OBJ_brainpoolP320t1 OBJ_brainpool,1L,10L + +#define SN_brainpoolP384r1 "brainpoolP384r1" +#define NID_brainpoolP384r1 932 +#define OBJ_brainpoolP384r1 OBJ_brainpool,1L,11L + +#define SN_brainpoolP384t1 "brainpoolP384t1" +#define NID_brainpoolP384t1 933 +#define OBJ_brainpoolP384t1 OBJ_brainpool,1L,12L + +#define SN_brainpoolP512r1 "brainpoolP512r1" +#define NID_brainpoolP512r1 934 +#define OBJ_brainpoolP512r1 OBJ_brainpool,1L,13L + +#define SN_brainpoolP512t1 "brainpoolP512t1" +#define NID_brainpoolP512t1 935 +#define OBJ_brainpoolP512t1 OBJ_brainpool,1L,14L + +#define SN_FRP256v1 "FRP256v1" +#define NID_FRP256v1 936 +#define OBJ_FRP256v1 1L,2L,250L,1L,223L,101L,256L,1L + +#define SN_chacha20 "ChaCha" +#define LN_chacha20 "chacha" +#define NID_chacha20 937 + +#define SN_chacha20_poly1305 "ChaCha20-Poly1305" +#define LN_chacha20_poly1305 "chacha20-poly1305" +#define NID_chacha20_poly1305 967 + +#define SN_gost89_ecb "gost89-ecb" +#define NID_gost89_ecb 938 + +#define SN_gost89_cbc "gost89-cbc" +#define NID_gost89_cbc 939 + +#define SN_tc26 "tc26" +#define NID_tc26 940 +#define OBJ_tc26 OBJ_member_body,643L,7L,1L + +#define SN_id_tc26_gost3411_2012_256 "streebog256" +#define LN_id_tc26_gost3411_2012_256 "GOST R 34.11-2012 (256 bit)" +#define NID_id_tc26_gost3411_2012_256 941 +#define OBJ_id_tc26_gost3411_2012_256 OBJ_tc26,1L,2L,2L + +#define SN_id_tc26_gost3411_2012_512 "streebog512" +#define LN_id_tc26_gost3411_2012_512 "GOST R 34-11-2012 (512 bit)" +#define NID_id_tc26_gost3411_2012_512 942 +#define OBJ_id_tc26_gost3411_2012_512 OBJ_tc26,1L,2L,3L + +#define SN_id_tc26_hmac_gost_3411_12_256 "id-tc26-hmac-gost-3411-12-256" +#define LN_id_tc26_hmac_gost_3411_12_256 "HMAC STREEBOG 256" +#define NID_id_tc26_hmac_gost_3411_12_256 999 +#define OBJ_id_tc26_hmac_gost_3411_12_256 OBJ_tc26,1L,4L,1L + +#define SN_id_tc26_hmac_gost_3411_12_512 "id-tc26-hmac-gost-3411-12-512" +#define LN_id_tc26_hmac_gost_3411_12_512 "HMAC STREEBOG 512" +#define NID_id_tc26_hmac_gost_3411_12_512 1000 +#define OBJ_id_tc26_hmac_gost_3411_12_512 OBJ_tc26,1L,4L,2L + +#define SN_id_tc26_gost_3410_12_256_paramSetA "id-tc26-gost-3410-12-256-paramSetA" +#define LN_id_tc26_gost_3410_12_256_paramSetA "GOST R 34.10-2012 (256 bit) ParamSet A" +#define NID_id_tc26_gost_3410_12_256_paramSetA 993 +#define OBJ_id_tc26_gost_3410_12_256_paramSetA OBJ_tc26,2L,1L,1L,1L + +#define SN_id_tc26_gost_3410_12_256_paramSetB "id-tc26-gost-3410-12-256-paramSetB" +#define LN_id_tc26_gost_3410_12_256_paramSetB "GOST R 34.10-2012 (256 bit) ParamSet B" +#define NID_id_tc26_gost_3410_12_256_paramSetB 994 +#define OBJ_id_tc26_gost_3410_12_256_paramSetB OBJ_tc26,2L,1L,1L,2L + +#define SN_id_tc26_gost_3410_12_256_paramSetC "id-tc26-gost-3410-12-256-paramSetC" +#define LN_id_tc26_gost_3410_12_256_paramSetC "GOST R 34.10-2012 (256 bit) ParamSet C" +#define NID_id_tc26_gost_3410_12_256_paramSetC 995 +#define OBJ_id_tc26_gost_3410_12_256_paramSetC OBJ_tc26,2L,1L,1L,3L + +#define SN_id_tc26_gost_3410_12_256_paramSetD "id-tc26-gost-3410-12-256-paramSetD" +#define LN_id_tc26_gost_3410_12_256_paramSetD "GOST R 34.10-2012 (256 bit) ParamSet D" +#define NID_id_tc26_gost_3410_12_256_paramSetD 996 +#define OBJ_id_tc26_gost_3410_12_256_paramSetD OBJ_tc26,2L,1L,1L,4L + +#define SN_id_tc26_gost_3410_12_512_paramSetTest "id-tc26-gost-3410-12-512-paramSetTest" +#define LN_id_tc26_gost_3410_12_512_paramSetTest "GOST R 34.10-2012 (512 bit) testing parameter set" +#define NID_id_tc26_gost_3410_12_512_paramSetTest 997 +#define OBJ_id_tc26_gost_3410_12_512_paramSetTest OBJ_tc26,2L,1L,2L,0L + +#define SN_id_tc26_gost_3410_12_512_paramSetA "id-tc26-gost-3410-12-512-paramSetA" +#define LN_id_tc26_gost_3410_12_512_paramSetA "GOST R 34.10-2012 (512 bit) ParamSet A" +#define NID_id_tc26_gost_3410_12_512_paramSetA 943 +#define OBJ_id_tc26_gost_3410_12_512_paramSetA OBJ_tc26,2L,1L,2L,1L + +#define SN_id_tc26_gost_3410_12_512_paramSetB "id-tc26-gost-3410-12-512-paramSetB" +#define LN_id_tc26_gost_3410_12_512_paramSetB "GOST R 34.10-2012 (512 bit) ParamSet B" +#define NID_id_tc26_gost_3410_12_512_paramSetB 944 +#define OBJ_id_tc26_gost_3410_12_512_paramSetB OBJ_tc26,2L,1L,2L,2L + +#define SN_id_tc26_gost_3410_12_512_paramSetC "id-tc26-gost-3410-12-512-paramSetC" +#define LN_id_tc26_gost_3410_12_512_paramSetC "GOST R 34.10-2012 (512 bit) ParamSet C" +#define NID_id_tc26_gost_3410_12_512_paramSetC 998 +#define OBJ_id_tc26_gost_3410_12_512_paramSetC OBJ_tc26,2L,1L,2L,3L + +#define SN_id_tc26_gost_28147_param_Z "id-tc26-gost-28147-param-Z" +#define NID_id_tc26_gost_28147_param_Z 945 +#define OBJ_id_tc26_gost_28147_param_Z OBJ_tc26,2L,5L,1L,1L + +#define SN_id_tc26_gost3410_2012_256 "id-tc26-gost3410-2012-256" +#define LN_id_tc26_gost3410_2012_256 "GOST R 34.10-2012 (256 bit)" +#define NID_id_tc26_gost3410_2012_256 946 +#define OBJ_id_tc26_gost3410_2012_256 OBJ_tc26,1L,1L,1L + +#define SN_id_tc26_gost3410_2012_512 "id-tc26-gost3410-2012-512" +#define LN_id_tc26_gost3410_2012_512 "GOST R 34.10-2012 (512 bit)" +#define NID_id_tc26_gost3410_2012_512 947 +#define OBJ_id_tc26_gost3410_2012_512 OBJ_tc26,1L,1L,2L + +#define SN_id_tc26_signwithdigest_gost3410_2012_256 "id-tc26-signwithdigest-gost3410-2012-256" +#define LN_id_tc26_signwithdigest_gost3410_2012_256 "GOST R 34.11-2012 with GOST R 34.10-2012 (256 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_256 948 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_256 OBJ_tc26,1L,3L,2L + +#define SN_id_tc26_signwithdigest_gost3410_2012_512 "id-tc26-signwithdigest-gost3410-2012-512" +#define LN_id_tc26_signwithdigest_gost3410_2012_512 "GOST R 34.11-2012 with GOST R 34.10-2012 (512 bit)" +#define NID_id_tc26_signwithdigest_gost3410_2012_512 949 +#define OBJ_id_tc26_signwithdigest_gost3410_2012_512 OBJ_tc26,1L,3L,3L + +#define SN_X25519 "X25519" +#define NID_X25519 950 +#define OBJ_X25519 1L,3L,101L,110L + +#define SN_X448 "X448" +#define NID_X448 951 +#define OBJ_X448 1L,3L,101L,111L + +#define SN_Ed25519 "Ed25519" +#define NID_Ed25519 952 +#define OBJ_Ed25519 1L,3L,101L,112L + +#define SN_Ed448 "Ed448" +#define NID_Ed448 953 +#define OBJ_Ed448 1L,3L,101L,113L + +#define SN_Ed25519ph "Ed25519ph" +#define NID_Ed25519ph 954 +#define OBJ_Ed25519ph 1L,3L,101L,114L + +#define SN_Ed448ph "Ed448ph" +#define NID_Ed448ph 955 +#define OBJ_Ed448ph 1L,3L,101L,115L + +#define SN_kx_rsa "KxRSA" +#define LN_kx_rsa "kx-rsa" +#define NID_kx_rsa 959 + +#define SN_kx_ecdhe "KxECDHE" +#define LN_kx_ecdhe "kx-ecdhe" +#define NID_kx_ecdhe 960 + +#define SN_kx_dhe "KxDHE" +#define LN_kx_dhe "kx-dhe" +#define NID_kx_dhe 961 + +#define SN_kx_gost "KxGOST" +#define LN_kx_gost "kx-gost" +#define NID_kx_gost 962 + +#define SN_auth_rsa "AuthRSA" +#define LN_auth_rsa "auth-rsa" +#define NID_auth_rsa 963 + +#define SN_auth_ecdsa "AuthECDSA" +#define LN_auth_ecdsa "auth-ecdsa" +#define NID_auth_ecdsa 964 + +#define SN_auth_gost01 "AuthGOST01" +#define LN_auth_gost01 "auth-gost01" +#define NID_auth_gost01 965 + +#define SN_auth_null "AuthNULL" +#define LN_auth_null "auth-null" +#define NID_auth_null 966 + diff --git a/include/openssl/objects.h b/include/openssl/objects.h new file mode 100644 index 0000000..451545e --- /dev/null +++ b/include/openssl/objects.h @@ -0,0 +1,163 @@ +/* $OpenBSD: objects.h,v 1.23 2023/07/28 10:25:05 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_OBJECTS_H +#define HEADER_OBJECTS_H + +#include + +#define SN_ED25519 SN_Ed25519 +#define NID_ED25519 NID_Ed25519 +#define OBJ_ED25519 OBJ_Ed25519 + +#include +#include + +#define OBJ_NAME_TYPE_UNDEF 0x00 +#define OBJ_NAME_TYPE_MD_METH 0x01 +#define OBJ_NAME_TYPE_CIPHER_METH 0x02 +#define OBJ_NAME_TYPE_PKEY_METH 0x03 +#define OBJ_NAME_TYPE_COMP_METH 0x04 +#define OBJ_NAME_TYPE_NUM 0x05 + +#define OBJ_NAME_ALIAS 0x8000 + +#define OBJ_BSEARCH_VALUE_ON_NOMATCH 0x01 +#define OBJ_BSEARCH_FIRST_VALUE_ON_MATCH 0x02 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct obj_name_st { + int type; + int alias; + const char *name; + const char *data; +} OBJ_NAME; + +#define OBJ_create_and_add_object(a,b,c) OBJ_create(a,b,c) + + +int OBJ_NAME_init(void); +int OBJ_NAME_new_index(unsigned long (*hash_func)(const char *), + int (*cmp_func)(const char *, const char *), + void (*free_func)(const char *, int, const char *)); +const char *OBJ_NAME_get(const char *name, int type); +int OBJ_NAME_add(const char *name, int type, const char *data); +int OBJ_NAME_remove(const char *name, int type); +void OBJ_NAME_cleanup(int type); /* -1 for everything */ +void OBJ_NAME_do_all(int type, void (*fn)(const OBJ_NAME *, void *arg), + void *arg); +void OBJ_NAME_do_all_sorted(int type, void (*fn)(const OBJ_NAME *, void *arg), + void *arg); + +ASN1_OBJECT * OBJ_dup(const ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_nid2obj(int n); +const char * OBJ_nid2ln(int n); +const char * OBJ_nid2sn(int n); +int OBJ_obj2nid(const ASN1_OBJECT *o); +ASN1_OBJECT * OBJ_txt2obj(const char *s, int no_name); +int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name); +int OBJ_txt2nid(const char *s); +int OBJ_ln2nid(const char *s); +int OBJ_sn2nid(const char *s); +int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b); + +#if defined(LIBRESSL_INTERNAL) +const void * OBJ_bsearch_(const void *key, const void *base, int num, + int size, int (*cmp)(const void *, const void *)); +const void * OBJ_bsearch_ex_(const void *key, const void *base, int num, + int size, int (*cmp)(const void *, const void *), + int flags); +#endif + +int OBJ_new_nid(int num); +int OBJ_add_object(const ASN1_OBJECT *obj); +int OBJ_create(const char *oid, const char *sn, const char *ln); +void OBJ_cleanup(void); +int OBJ_create_objects(BIO *in); + +size_t OBJ_length(const ASN1_OBJECT *obj); +const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj); + +int OBJ_find_sigid_algs(int signid, int *pdig_nid, int *ppkey_nid); +int OBJ_find_sigid_by_algs(int *psignid, int dig_nid, int pkey_nid); + +void ERR_load_OBJ_strings(void); + +/* Error codes for the OBJ functions. */ + +/* Function codes. */ +#define OBJ_F_OBJ_ADD_OBJECT 105 +#define OBJ_F_OBJ_CREATE 100 +#define OBJ_F_OBJ_DUP 101 +#define OBJ_F_OBJ_NAME_NEW_INDEX 106 +#define OBJ_F_OBJ_NID2LN 102 +#define OBJ_F_OBJ_NID2OBJ 103 +#define OBJ_F_OBJ_NID2SN 104 + +/* Reason codes. */ +#define OBJ_R_MALLOC_FAILURE 100 +#define OBJ_R_UNKNOWN_NID 101 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h new file mode 100644 index 0000000..691ee4a --- /dev/null +++ b/include/openssl/ocsp.h @@ -0,0 +1,484 @@ +/* $OpenBSD: ocsp.h,v 1.20 2022/07/12 14:42:49 kn Exp $ */ +/* Written by Tom Titchener for the OpenSSL + * project. */ + +/* History: + This file was transfered to Richard Levitte from CertCo by Kathy + Weinhold in mid-spring 2000 to be included in OpenSSL or released + as a patch kit. */ + +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_OCSP_H +#define HEADER_OCSP_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * CRLReason ::= ENUMERATED { + * unspecified (0), + * keyCompromise (1), + * cACompromise (2), + * affiliationChanged (3), + * superseded (4), + * cessationOfOperation (5), + * certificateHold (6), + * removeFromCRL (8) } + */ +#define OCSP_REVOKED_STATUS_NOSTATUS -1 +#define OCSP_REVOKED_STATUS_UNSPECIFIED 0 +#define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1 +#define OCSP_REVOKED_STATUS_CACOMPROMISE 2 +#define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3 +#define OCSP_REVOKED_STATUS_SUPERSEDED 4 +#define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5 +#define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6 +#define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8 + + +/* Various flags and values */ + +#define OCSP_DEFAULT_NONCE_LENGTH 16 + +#define OCSP_NOCERTS 0x1 +#define OCSP_NOINTERN 0x2 +#define OCSP_NOSIGS 0x4 +#define OCSP_NOCHAIN 0x8 +#define OCSP_NOVERIFY 0x10 +#define OCSP_NOEXPLICIT 0x20 +#define OCSP_NOCASIGN 0x40 +#define OCSP_NODELEGATED 0x80 +#define OCSP_NOCHECKS 0x100 +#define OCSP_TRUSTOTHER 0x200 +#define OCSP_RESPID_KEY 0x400 +#define OCSP_NOTIME 0x800 + +typedef struct ocsp_cert_id_st OCSP_CERTID; + +DECLARE_STACK_OF(OCSP_CERTID) + +typedef struct ocsp_one_request_st OCSP_ONEREQ; + +DECLARE_STACK_OF(OCSP_ONEREQ) + +typedef struct ocsp_req_info_st OCSP_REQINFO; +typedef struct ocsp_signature_st OCSP_SIGNATURE; +typedef struct ocsp_request_st OCSP_REQUEST; + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1 +#define OCSP_RESPONSE_STATUS_INTERNALERROR 2 +#define OCSP_RESPONSE_STATUS_TRYLATER 3 +#define OCSP_RESPONSE_STATUS_SIGREQUIRED 5 +#define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6 + +typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES; + +#define V_OCSP_RESPID_NAME 0 +#define V_OCSP_RESPID_KEY 1 + +DECLARE_STACK_OF(OCSP_RESPID) + +OCSP_RESPID *OCSP_RESPID_new(void); +void OCSP_RESPID_free(OCSP_RESPID *a); +OCSP_RESPID *d2i_OCSP_RESPID(OCSP_RESPID **a, const unsigned char **in, long len); +int i2d_OCSP_RESPID(OCSP_RESPID *a, unsigned char **out); +extern const ASN1_ITEM OCSP_RESPID_it; + +typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO; + +#define V_OCSP_CERTSTATUS_GOOD 0 +#define V_OCSP_CERTSTATUS_REVOKED 1 +#define V_OCSP_CERTSTATUS_UNKNOWN 2 + +typedef struct ocsp_cert_status_st OCSP_CERTSTATUS; +typedef struct ocsp_single_response_st OCSP_SINGLERESP; + +DECLARE_STACK_OF(OCSP_SINGLERESP) + +typedef struct ocsp_response_data_st OCSP_RESPDATA; + +typedef struct ocsp_basic_response_st OCSP_BASICRESP; + +typedef struct ocsp_crl_id_st OCSP_CRLID; +typedef struct ocsp_service_locator_st OCSP_SERVICELOC; + +#define PEM_STRING_OCSP_REQUEST "OCSP REQUEST" +#define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE" + +#define PEM_read_bio_OCSP_REQUEST(bp,x,cb) \ + (OCSP_REQUEST *)PEM_ASN1_read_bio((char *(*)())d2i_OCSP_REQUEST, \ + PEM_STRING_OCSP_REQUEST,bp,(char **)x,cb,NULL) + +#define PEM_read_bio_OCSP_RESPONSE(bp,x,cb) \ + (OCSP_RESPONSE *)PEM_ASN1_read_bio((char *(*)())d2i_OCSP_RESPONSE, \ + PEM_STRING_OCSP_RESPONSE,bp,(char **)x,cb,NULL) + +#define PEM_write_bio_OCSP_REQUEST(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +#define PEM_write_bio_OCSP_RESPONSE(bp,o) \ + PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\ + bp,(char *)o, NULL,NULL,0,NULL,NULL) + +#define ASN1_BIT_STRING_digest(data,type,md,len) \ + ASN1_item_digest(&ASN1_BIT_STRING_it,type,data,md,len) + +#define OCSP_CERTSTATUS_dup(cs) \ + ASN1_item_dup(&OCSP_CERTSTATUS_it, cs) + +OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id); + +OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req); +OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, + int maxline); +int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx); +void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx); +int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req); +int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, const char *name, + const char *value); + +OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject, + const X509 *issuer); + +OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, const X509_NAME *issuerName, + const ASN1_BIT_STRING *issuerKey, const ASN1_INTEGER *serialNumber); + +OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid); + +int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len); +int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len); +int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs); +int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req); + +int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm); +int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert); + +int OCSP_request_sign(OCSP_REQUEST *req, X509 *signer, EVP_PKEY *key, + const EVP_MD *dgst, STACK_OF(X509) *certs, unsigned long flags); + +int OCSP_response_status(OCSP_RESPONSE *resp); +OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp); + +const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs); +const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs); +const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, + STACK_OF(X509) *extra_certs); + +int OCSP_resp_count(OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx); +const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP *bs); +const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs); +int OCSP_resp_get0_id(const OCSP_BASICRESP *bs, + const ASN1_OCTET_STRING **pid, const X509_NAME **pname); + +int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last); +int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason, + ASN1_GENERALIZEDTIME **revtime, ASN1_GENERALIZEDTIME **thisupd, + ASN1_GENERALIZEDTIME **nextupd); +int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status, + int *reason, ASN1_GENERALIZEDTIME **revtime, + ASN1_GENERALIZEDTIME **thisupd, ASN1_GENERALIZEDTIME **nextupd); +int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, + ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec); + +int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, + X509_STORE *store, unsigned long flags); + +int OCSP_parse_url(const char *url, char **phost, char **pport, + char **ppath, int *pssl); + +int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b); +int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); + +int OCSP_request_onereq_count(OCSP_REQUEST *req); +OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i); +OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one); +int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, + ASN1_OCTET_STRING **pikeyHash, ASN1_INTEGER **pserial, + OCSP_CERTID *cid); +int OCSP_request_is_signed(OCSP_REQUEST *req); +OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs); +OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp, OCSP_CERTID *cid, + int status, int reason, ASN1_TIME *revtime, ASN1_TIME *thisupd, + ASN1_TIME *nextupd); +int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert); +int OCSP_basic_sign(OCSP_BASICRESP *brsp, X509 *signer, EVP_PKEY *key, + const EVP_MD *dgst, STACK_OF(X509) *certs, unsigned long flags); + +X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim); + +X509_EXTENSION *OCSP_accept_responses_new(char **oids); + +X509_EXTENSION *OCSP_archive_cutoff_new(char* tim); + +X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME* issuer, const char **urls); + +int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x); +int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos); +int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc); +X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc); +void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx); +int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc); + +int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x); +int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos); +int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos); +X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc); +X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc); +void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx); +int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit, + unsigned long flags); +int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc); + +int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x); +int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos); +int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj, + int lastpos); +int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc); +X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc); +void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit, + int *idx); +int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc); + +int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x); +int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, + int lastpos); +int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, + const ASN1_OBJECT *obj, int lastpos); +int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit, + int lastpos); +X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc); +X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc); +void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit, + int *idx); +int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value, + int crit, unsigned long flags); +int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, + int loc); +const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x); + +OCSP_SINGLERESP *OCSP_SINGLERESP_new(void); +void OCSP_SINGLERESP_free(OCSP_SINGLERESP *a); +OCSP_SINGLERESP *d2i_OCSP_SINGLERESP(OCSP_SINGLERESP **a, const unsigned char **in, long len); +int i2d_OCSP_SINGLERESP(OCSP_SINGLERESP *a, unsigned char **out); +extern const ASN1_ITEM OCSP_SINGLERESP_it; +OCSP_CERTSTATUS *OCSP_CERTSTATUS_new(void); +void OCSP_CERTSTATUS_free(OCSP_CERTSTATUS *a); +OCSP_CERTSTATUS *d2i_OCSP_CERTSTATUS(OCSP_CERTSTATUS **a, const unsigned char **in, long len); +int i2d_OCSP_CERTSTATUS(OCSP_CERTSTATUS *a, unsigned char **out); +extern const ASN1_ITEM OCSP_CERTSTATUS_it; +OCSP_REVOKEDINFO *OCSP_REVOKEDINFO_new(void); +void OCSP_REVOKEDINFO_free(OCSP_REVOKEDINFO *a); +OCSP_REVOKEDINFO *d2i_OCSP_REVOKEDINFO(OCSP_REVOKEDINFO **a, const unsigned char **in, long len); +int i2d_OCSP_REVOKEDINFO(OCSP_REVOKEDINFO *a, unsigned char **out); +extern const ASN1_ITEM OCSP_REVOKEDINFO_it; +OCSP_BASICRESP *OCSP_BASICRESP_new(void); +void OCSP_BASICRESP_free(OCSP_BASICRESP *a); +OCSP_BASICRESP *d2i_OCSP_BASICRESP(OCSP_BASICRESP **a, const unsigned char **in, long len); +int i2d_OCSP_BASICRESP(OCSP_BASICRESP *a, unsigned char **out); +extern const ASN1_ITEM OCSP_BASICRESP_it; +OCSP_RESPDATA *OCSP_RESPDATA_new(void); +void OCSP_RESPDATA_free(OCSP_RESPDATA *a); +OCSP_RESPDATA *d2i_OCSP_RESPDATA(OCSP_RESPDATA **a, const unsigned char **in, long len); +int i2d_OCSP_RESPDATA(OCSP_RESPDATA *a, unsigned char **out); +extern const ASN1_ITEM OCSP_RESPDATA_it; +OCSP_RESPID *OCSP_RESPID_new(void); +void OCSP_RESPID_free(OCSP_RESPID *a); +OCSP_RESPID *d2i_OCSP_RESPID(OCSP_RESPID **a, const unsigned char **in, long len); +int i2d_OCSP_RESPID(OCSP_RESPID *a, unsigned char **out); +extern const ASN1_ITEM OCSP_RESPID_it; +OCSP_RESPONSE *OCSP_RESPONSE_new(void); +void OCSP_RESPONSE_free(OCSP_RESPONSE *a); +OCSP_RESPONSE *d2i_OCSP_RESPONSE(OCSP_RESPONSE **a, const unsigned char **in, long len); +int i2d_OCSP_RESPONSE(OCSP_RESPONSE *a, unsigned char **out); +OCSP_RESPONSE *d2i_OCSP_RESPONSE_bio(BIO *bp, OCSP_RESPONSE **a); +int i2d_OCSP_RESPONSE_bio(BIO *bp, OCSP_RESPONSE *a); +extern const ASN1_ITEM OCSP_RESPONSE_it; +OCSP_RESPBYTES *OCSP_RESPBYTES_new(void); +void OCSP_RESPBYTES_free(OCSP_RESPBYTES *a); +OCSP_RESPBYTES *d2i_OCSP_RESPBYTES(OCSP_RESPBYTES **a, const unsigned char **in, long len); +int i2d_OCSP_RESPBYTES(OCSP_RESPBYTES *a, unsigned char **out); +extern const ASN1_ITEM OCSP_RESPBYTES_it; +OCSP_ONEREQ *OCSP_ONEREQ_new(void); +void OCSP_ONEREQ_free(OCSP_ONEREQ *a); +OCSP_ONEREQ *d2i_OCSP_ONEREQ(OCSP_ONEREQ **a, const unsigned char **in, long len); +int i2d_OCSP_ONEREQ(OCSP_ONEREQ *a, unsigned char **out); +extern const ASN1_ITEM OCSP_ONEREQ_it; +OCSP_CERTID *OCSP_CERTID_new(void); +void OCSP_CERTID_free(OCSP_CERTID *a); +OCSP_CERTID *d2i_OCSP_CERTID(OCSP_CERTID **a, const unsigned char **in, long len); +int i2d_OCSP_CERTID(OCSP_CERTID *a, unsigned char **out); +extern const ASN1_ITEM OCSP_CERTID_it; +OCSP_REQUEST *OCSP_REQUEST_new(void); +void OCSP_REQUEST_free(OCSP_REQUEST *a); +OCSP_REQUEST *d2i_OCSP_REQUEST(OCSP_REQUEST **a, const unsigned char **in, long len); +int i2d_OCSP_REQUEST(OCSP_REQUEST *a, unsigned char **out); +OCSP_REQUEST *d2i_OCSP_REQUEST_bio(BIO *bp, OCSP_REQUEST **a); +int i2d_OCSP_REQUEST_bio(BIO *bp, OCSP_REQUEST *a); +extern const ASN1_ITEM OCSP_REQUEST_it; +OCSP_SIGNATURE *OCSP_SIGNATURE_new(void); +void OCSP_SIGNATURE_free(OCSP_SIGNATURE *a); +OCSP_SIGNATURE *d2i_OCSP_SIGNATURE(OCSP_SIGNATURE **a, const unsigned char **in, long len); +int i2d_OCSP_SIGNATURE(OCSP_SIGNATURE *a, unsigned char **out); +extern const ASN1_ITEM OCSP_SIGNATURE_it; +OCSP_REQINFO *OCSP_REQINFO_new(void); +void OCSP_REQINFO_free(OCSP_REQINFO *a); +OCSP_REQINFO *d2i_OCSP_REQINFO(OCSP_REQINFO **a, const unsigned char **in, long len); +int i2d_OCSP_REQINFO(OCSP_REQINFO *a, unsigned char **out); +extern const ASN1_ITEM OCSP_REQINFO_it; +OCSP_CRLID *OCSP_CRLID_new(void); +void OCSP_CRLID_free(OCSP_CRLID *a); +OCSP_CRLID *d2i_OCSP_CRLID(OCSP_CRLID **a, const unsigned char **in, long len); +int i2d_OCSP_CRLID(OCSP_CRLID *a, unsigned char **out); +extern const ASN1_ITEM OCSP_CRLID_it; +OCSP_SERVICELOC *OCSP_SERVICELOC_new(void); +void OCSP_SERVICELOC_free(OCSP_SERVICELOC *a); +OCSP_SERVICELOC *d2i_OCSP_SERVICELOC(OCSP_SERVICELOC **a, const unsigned char **in, long len); +int i2d_OCSP_SERVICELOC(OCSP_SERVICELOC *a, unsigned char **out); +extern const ASN1_ITEM OCSP_SERVICELOC_it; + +const char *OCSP_response_status_str(long s); +const char *OCSP_cert_status_str(long s); +const char *OCSP_crl_reason_str(long s); + +int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST* a, unsigned long flags); +int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE* o, unsigned long flags); + +int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, + X509_STORE *st, unsigned long flags); + +void ERR_load_OCSP_strings(void); + +/* Error codes for the OCSP functions. */ + +/* Function codes. */ +#define OCSP_F_ASN1_STRING_ENCODE 100 +#define OCSP_F_D2I_OCSP_NONCE 102 +#define OCSP_F_OCSP_BASIC_ADD1_STATUS 103 +#define OCSP_F_OCSP_BASIC_SIGN 104 +#define OCSP_F_OCSP_BASIC_VERIFY 105 +#define OCSP_F_OCSP_CERT_ID_NEW 101 +#define OCSP_F_OCSP_CHECK_DELEGATED 106 +#define OCSP_F_OCSP_CHECK_IDS 107 +#define OCSP_F_OCSP_CHECK_ISSUER 108 +#define OCSP_F_OCSP_CHECK_VALIDITY 115 +#define OCSP_F_OCSP_MATCH_ISSUERID 109 +#define OCSP_F_OCSP_PARSE_URL 114 +#define OCSP_F_OCSP_REQUEST_SIGN 110 +#define OCSP_F_OCSP_REQUEST_VERIFY 116 +#define OCSP_F_OCSP_RESPONSE_GET1_BASIC 111 +#define OCSP_F_OCSP_SENDREQ_BIO 112 +#define OCSP_F_OCSP_SENDREQ_NBIO 117 +#define OCSP_F_PARSE_HTTP_LINE1 118 +#define OCSP_F_REQUEST_VERIFY 113 + +/* Reason codes. */ +#define OCSP_R_BAD_DATA 100 +#define OCSP_R_CERTIFICATE_VERIFY_ERROR 101 +#define OCSP_R_DIGEST_ERR 102 +#define OCSP_R_ERROR_IN_NEXTUPDATE_FIELD 122 +#define OCSP_R_ERROR_IN_THISUPDATE_FIELD 123 +#define OCSP_R_ERROR_PARSING_URL 121 +#define OCSP_R_MISSING_OCSPSIGNING_USAGE 103 +#define OCSP_R_NEXTUPDATE_BEFORE_THISUPDATE 124 +#define OCSP_R_NOT_BASIC_RESPONSE 104 +#define OCSP_R_NO_CERTIFICATES_IN_CHAIN 105 +#define OCSP_R_NO_CONTENT 106 +#define OCSP_R_NO_PUBLIC_KEY 107 +#define OCSP_R_NO_RESPONSE_DATA 108 +#define OCSP_R_NO_REVOKED_TIME 109 +#define OCSP_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 110 +#define OCSP_R_REQUEST_NOT_SIGNED 128 +#define OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA 111 +#define OCSP_R_ROOT_CA_NOT_TRUSTED 112 +#define OCSP_R_SERVER_READ_ERROR 113 +#define OCSP_R_SERVER_RESPONSE_ERROR 114 +#define OCSP_R_SERVER_RESPONSE_PARSE_ERROR 115 +#define OCSP_R_SERVER_WRITE_ERROR 116 +#define OCSP_R_SIGNATURE_FAILURE 117 +#define OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND 118 +#define OCSP_R_STATUS_EXPIRED 125 +#define OCSP_R_STATUS_NOT_YET_VALID 126 +#define OCSP_R_STATUS_TOO_OLD 127 +#define OCSP_R_UNKNOWN_MESSAGE_DIGEST 119 +#define OCSP_R_UNKNOWN_NID 120 +#define OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE 129 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/opensslfeatures.h b/include/openssl/opensslfeatures.h new file mode 100644 index 0000000..b00d7cf --- /dev/null +++ b/include/openssl/opensslfeatures.h @@ -0,0 +1,133 @@ +/* $OpenBSD: opensslfeatures.h,v 1.41 2023/07/28 09:53:55 tb Exp $ */ +/* + * Feature flags for LibreSSL... so you can actually tell when things + * are enabled, rather than not being able to tell when things are + * enabled (or possibly not yet not implemented, or removed!). + */ +#define LIBRESSL_HAS_QUIC +#define LIBRESSL_HAS_TLS1_3 +#define LIBRESSL_HAS_DTLS1_2 + +/* + * Used for compatibility with compilers lacking __attribute__ + */ +#if defined(_MSC_VER) && !defined(__clang__) && !defined(__attribute__) +#define __attribute__(a) +#endif + +#define OPENSSL_THREADS + +#define OPENSSL_NO_BUF_FREELISTS +#define OPENSSL_NO_DEPRECATED +#define OPENSSL_NO_EC2M +#define OPENSSL_NO_GMP +#define OPENSSL_NO_JPAKE +#define OPENSSL_NO_KRB5 +#define OPENSSL_NO_RSAX +#define OPENSSL_NO_SHA0 +#define OPENSSL_NO_SSL2 +#define OPENSSL_NO_STORE + +/* + * OPENSSL_NO_* flags that currently appear in OpenSSL. + */ + +/* #define OPENSSL_NO_AFALGENG */ +/* #define OPENSSL_NO_ALGORITHMS */ +/* #define OPENSSL_NO_ARIA */ +/* #define OPENSSL_NO_ASM */ +#define OPENSSL_NO_ASYNC +/* #define OPENSSL_NO_AUTOALGINIT */ +/* #define OPENSSL_NO_AUTOERRINIT */ +/* #define OPENSSL_NO_AUTOLOAD_CONFIG */ +/* #define OPENSSL_NO_BF */ +/* #define OPENSSL_NO_BLAKE2 */ +/* #define OPENSSL_NO_CAMELLIA */ +/* #define OPENSSL_NO_CAPIENG */ +/* #define OPENSSL_NO_CAST */ +/* #define OPENSSL_NO_CHACHA */ +/* #define OPENSSL_NO_CMAC */ +/* #define OPENSSL_NO_CMS */ +#define OPENSSL_NO_COMP /* XXX */ +/* #define OPENSSL_NO_CRYPTO_MDEBUG */ +/* #define OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE */ +/* #define OPENSSL_NO_CT */ +/* #define OPENSSL_NO_DECC_INIT */ +/* #define OPENSSL_NO_DES */ +/* #define OPENSSL_NO_DEVCRYPTOENG */ +/* #define OPENSSL_NO_DGRAM */ +/* #define OPENSSL_NO_DH */ +/* #define OPENSSL_NO_DSA */ +#define OPENSSL_NO_DSO +/* #define OPENSSL_NO_DTLS */ +#define OPENSSL_NO_DTLS1 +#ifndef LIBRESSL_HAS_DTLS1_2 +#define OPENSSL_NO_DTLS1_2 +#endif +/* #define OPENSSL_NO_DTLS1_2_METHOD */ +/* #define OPENSSL_NO_DTLS1_METHOD */ +#define OPENSSL_NO_DYNAMIC_ENGINE +/* #define OPENSSL_NO_EC */ +#define OPENSSL_NO_EC_NISTP_64_GCC_128 +#define OPENSSL_NO_EGD +#define OPENSSL_NO_ENGINE +/* #define OPENSSL_NO_ERR */ +/* #define OPENSSL_NO_FUZZ_AFL */ +/* #define OPENSSL_NO_FUZZ_LIBFUZZER */ +/* #define OPENSSL_NO_GOST */ +#define OPENSSL_NO_HEARTBEATS +/* #define OPENSSL_NO_HW */ +/* #define OPENSSL_NO_HW_PADLOCK */ +/* #define OPENSSL_NO_IDEA */ +/* #define OPENSSL_NO_INLINE_ASM */ +#define OPENSSL_NO_MD2 +/* #define OPENSSL_NO_MD4 */ +/* #define OPENSSL_NO_MD5 */ +#define OPENSSL_NO_MDC2 +/* #define OPENSSL_NO_MULTIBLOCK */ +/* #define OPENSSL_NO_NEXTPROTONEG */ +/* #define OPENSSL_NO_OCB */ +/* #define OPENSSL_NO_OCSP */ +/* #define OPENSSL_NO_PINSHARED */ +/* #define OPENSSL_NO_POLY1305 */ +/* #define OPENSSL_NO_POSIX_IO */ +#define OPENSSL_NO_PSK +/* #define OPENSSL_NO_RC2 */ +/* #define OPENSSL_NO_RC4 */ +#define OPENSSL_NO_RC5 +/* #define OPENSSL_NO_RDRAND */ +/* #define OPENSSL_NO_RFC3779 */ +/* #define OPENSSL_NO_RMD160 */ +/* #define OPENSSL_NO_RSA */ +/* #define OPENSSL_NO_SCRYPT */ +#define OPENSSL_NO_SCTP +/* #define OPENSSL_NO_SECURE_MEMORY */ +#define OPENSSL_NO_SEED +/* #define OPENSSL_NO_SIPHASH */ +/* #define OPENSSL_NO_SM2 */ +/* #define OPENSSL_NO_SM3 */ +/* #define OPENSSL_NO_SM4 */ +/* #define OPENSSL_NO_SOCK */ +#define OPENSSL_NO_SRP +/* #define OPENSSL_NO_SRTP */ +#define OPENSSL_NO_SSL3 +#define OPENSSL_NO_SSL3_METHOD +#define OPENSSL_NO_SSL_TRACE +/* #define OPENSSL_NO_STATIC_ENGINE */ +/* #define OPENSSL_NO_STDIO */ +/* #define OPENSSL_NO_TLS */ +#define OPENSSL_NO_TLS1 +#define OPENSSL_NO_TLS1_1 +#define OPENSSL_NO_TLS1_METHOD +#define OPENSSL_NO_TLS1_1_METHOD +/* #define OPENSSL_NO_TLS1_2 */ +/* #define OPENSSL_NO_TLS1_2_METHOD */ +#ifndef LIBRESSL_HAS_TLS1_3 +#define OPENSSL_NO_TLS1_3 +#endif +/* #define OPENSSL_NO_TLS1_METHOD */ +/* #define OPENSSL_NO_TS */ +/* #define OPENSSL_NO_UI_CONSOLE */ +/* #define OPENSSL_NO_UNIT_TEST */ +/* #define OPENSSL_NO_WEAK_SSL_CIPHERS */ +/* #define OPENSSL_NO_WHIRLPOOL */ diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h new file mode 100644 index 0000000..d7ce60f --- /dev/null +++ b/include/openssl/opensslv.h @@ -0,0 +1,18 @@ +/* $OpenBSD: opensslv.h,v 1.77 2023/09/20 11:42:25 tb Exp $ */ +#ifndef HEADER_OPENSSLV_H +#define HEADER_OPENSSLV_H + +/* These will change with each release of LibreSSL-portable */ +#define LIBRESSL_VERSION_NUMBER 0x3080200fL +/* ^ Patch starts here */ +#define LIBRESSL_VERSION_TEXT "LibreSSL 3.8.2" + +/* These will never change */ +#define OPENSSL_VERSION_NUMBER 0x20000000L +#define OPENSSL_VERSION_TEXT LIBRESSL_VERSION_TEXT +#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT + +#define SHLIB_VERSION_HISTORY "" +#define SHLIB_VERSION_NUMBER "1.0.0" + +#endif /* HEADER_OPENSSLV_H */ diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h new file mode 100644 index 0000000..4e0c518 --- /dev/null +++ b/include/openssl/ossl_typ.h @@ -0,0 +1,204 @@ +/* $OpenBSD: ossl_typ.h,v 1.30 2023/08/11 05:10:35 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_OPENSSL_TYPES_H +#define HEADER_OPENSSL_TYPES_H + +#include + +typedef struct asn1_string_st ASN1_INTEGER; +typedef struct asn1_string_st ASN1_ENUMERATED; +typedef struct asn1_string_st ASN1_BIT_STRING; +typedef struct asn1_string_st ASN1_OCTET_STRING; +typedef struct asn1_string_st ASN1_PRINTABLESTRING; +typedef struct asn1_string_st ASN1_T61STRING; +typedef struct asn1_string_st ASN1_IA5STRING; +typedef struct asn1_string_st ASN1_GENERALSTRING; +typedef struct asn1_string_st ASN1_UNIVERSALSTRING; +typedef struct asn1_string_st ASN1_BMPSTRING; +typedef struct asn1_string_st ASN1_UTCTIME; +typedef struct asn1_string_st ASN1_TIME; +typedef struct asn1_string_st ASN1_GENERALIZEDTIME; +typedef struct asn1_string_st ASN1_VISIBLESTRING; +typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_STRING; +typedef int ASN1_BOOLEAN; +typedef int ASN1_NULL; + +typedef struct asn1_object_st ASN1_OBJECT; + +typedef struct ASN1_ITEM_st ASN1_ITEM; +typedef struct asn1_pctx_st ASN1_PCTX; + +#if defined(_WIN32) && defined(__WINCRYPT_H__) +#if !defined(LIBRESSL_INTERNAL) && !defined(LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING) +#ifdef _MSC_VER +#pragma message("Warning, overriding WinCrypt defines") +#else +#warning overriding WinCrypt defines +#endif +#endif +#undef X509_NAME +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#undef OCSP_REQUEST +#undef OCSP_RESPONSE +#undef PKCS7_ISSUER_AND_SERIAL +#endif + +#ifdef BIGNUM +#undef BIGNUM +#endif +typedef struct bignum_st BIGNUM; +typedef struct bignum_ctx BN_CTX; +typedef struct bn_blinding_st BN_BLINDING; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_gencb_st BN_GENCB; + +typedef struct bio_st BIO; +typedef struct buf_mem_st BUF_MEM; + +typedef struct comp_ctx_st COMP_CTX; +typedef struct comp_method_st COMP_METHOD; + +typedef struct evp_cipher_st EVP_CIPHER; +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; +typedef struct evp_md_st EVP_MD; +typedef struct evp_md_ctx_st EVP_MD_CTX; +typedef struct evp_pkey_st EVP_PKEY; + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; + +typedef struct evp_pkey_method_st EVP_PKEY_METHOD; +typedef struct evp_pkey_ctx_st EVP_PKEY_CTX; + +typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX; + +typedef struct hmac_ctx_st HMAC_CTX; + +typedef struct dh_st DH; +typedef struct dh_method DH_METHOD; + +typedef struct dsa_st DSA; +typedef struct dsa_method DSA_METHOD; + +typedef struct ec_key_st EC_KEY; +typedef struct ec_key_method_st EC_KEY_METHOD; + +typedef struct rsa_st RSA; +typedef struct rsa_meth_st RSA_METHOD; +typedef struct rsa_pss_params_st RSA_PSS_PARAMS; + +typedef struct rand_meth_st RAND_METHOD; + +typedef struct x509_st X509; +typedef struct X509_algor_st X509_ALGOR; +typedef struct X509_crl_st X509_CRL; +typedef struct x509_crl_method_st X509_CRL_METHOD; +typedef struct x509_revoked_st X509_REVOKED; +typedef struct X509_name_st X509_NAME; +typedef struct X509_pubkey_st X509_PUBKEY; +typedef struct x509_store_st X509_STORE; +typedef struct x509_store_ctx_st X509_STORE_CTX; + +typedef struct x509_object_st X509_OBJECT; +typedef struct x509_lookup_st X509_LOOKUP; +typedef struct x509_lookup_method_st X509_LOOKUP_METHOD; +typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM; + +typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO; + +typedef struct v3_ext_ctx X509V3_CTX; +typedef struct conf_st CONF; + +typedef struct store_st STORE; +typedef struct store_method_st STORE_METHOD; + +typedef struct ui_st UI; +typedef struct ui_method_st UI_METHOD; + +typedef struct engine_st ENGINE; +typedef struct ssl_st SSL; +typedef struct ssl_ctx_st SSL_CTX; + +typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID; +typedef struct DIST_POINT_st DIST_POINT; +typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT; +typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS; + +/* If placed in pkcs12.h, we end up with a circular dependency with pkcs7.h */ +#define DECLARE_PKCS12_STACK_OF(type) /* Nothing */ +#define IMPLEMENT_PKCS12_STACK_OF(type) /* Nothing */ + +typedef struct crypto_ex_data_st CRYPTO_EX_DATA; +/* Callback types for crypto.h */ +typedef int CRYPTO_EX_new(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef void CRYPTO_EX_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, + int idx, long argl, void *argp); +typedef int CRYPTO_EX_dup(CRYPTO_EX_DATA *to, CRYPTO_EX_DATA *from, + void *from_d, int idx, long argl, void *argp); + +typedef struct ocsp_req_ctx_st OCSP_REQ_CTX; +typedef struct ocsp_response_st OCSP_RESPONSE; +typedef struct ocsp_responder_id_st OCSP_RESPID; + +typedef struct sct_st SCT; +typedef struct sct_ctx_st SCT_CTX; +typedef struct ctlog_st CTLOG; +typedef struct ctlog_store_st CTLOG_STORE; +typedef struct ct_policy_eval_ctx_st CT_POLICY_EVAL_CTX; + +#endif /* def HEADER_OPENSSL_TYPES_H */ diff --git a/include/openssl/pem.h b/include/openssl/pem.h new file mode 100644 index 0000000..130acbc --- /dev/null +++ b/include/openssl/pem.h @@ -0,0 +1,596 @@ +/* $OpenBSD: pem.h,v 1.26 2023/04/25 17:51:36 tb Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_PEM_H +#define HEADER_PEM_H + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_STACK +#include +#endif +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PEM_BUFSIZE 1024 + +#define PEM_OBJ_UNDEF 0 +#define PEM_OBJ_X509 1 +#define PEM_OBJ_X509_REQ 2 +#define PEM_OBJ_CRL 3 +#define PEM_OBJ_SSL_SESSION 4 +#define PEM_OBJ_PRIV_KEY 10 +#define PEM_OBJ_PRIV_RSA 11 +#define PEM_OBJ_PRIV_DSA 12 +#define PEM_OBJ_PRIV_DH 13 +#define PEM_OBJ_PUB_RSA 14 +#define PEM_OBJ_PUB_DSA 15 +#define PEM_OBJ_PUB_DH 16 +#define PEM_OBJ_DHPARAMS 17 +#define PEM_OBJ_DSAPARAMS 18 +#define PEM_OBJ_PRIV_RSA_PUBLIC 19 +#define PEM_OBJ_PRIV_ECDSA 20 +#define PEM_OBJ_PUB_ECDSA 21 +#define PEM_OBJ_ECPARAMETERS 22 + +#define PEM_ERROR 30 +#define PEM_DEK_DES_CBC 40 +#define PEM_DEK_IDEA_CBC 45 +#define PEM_DEK_DES_EDE 50 +#define PEM_DEK_DES_ECB 60 +#define PEM_DEK_RSA 70 +#define PEM_DEK_RSA_MD2 80 +#define PEM_DEK_RSA_MD5 90 + +#define PEM_MD_MD2 NID_md2 +#define PEM_MD_MD5 NID_md5 +#define PEM_MD_SHA NID_sha +#define PEM_MD_MD2_RSA NID_md2WithRSAEncryption +#define PEM_MD_MD5_RSA NID_md5WithRSAEncryption +#define PEM_MD_SHA_RSA NID_sha1WithRSAEncryption + +#define PEM_STRING_X509_OLD "X509 CERTIFICATE" +#define PEM_STRING_X509 "CERTIFICATE" +#define PEM_STRING_X509_TRUSTED "TRUSTED CERTIFICATE" +#define PEM_STRING_X509_REQ_OLD "NEW CERTIFICATE REQUEST" +#define PEM_STRING_X509_REQ "CERTIFICATE REQUEST" +#define PEM_STRING_X509_CRL "X509 CRL" +#define PEM_STRING_EVP_PKEY "ANY PRIVATE KEY" +#define PEM_STRING_PUBLIC "PUBLIC KEY" +#define PEM_STRING_RSA "RSA PRIVATE KEY" +#define PEM_STRING_RSA_PUBLIC "RSA PUBLIC KEY" +#define PEM_STRING_DSA "DSA PRIVATE KEY" +#define PEM_STRING_DSA_PUBLIC "DSA PUBLIC KEY" +#define PEM_STRING_PKCS7 "PKCS7" +#define PEM_STRING_PKCS7_SIGNED "PKCS #7 SIGNED DATA" +#define PEM_STRING_PKCS8 "ENCRYPTED PRIVATE KEY" +#define PEM_STRING_PKCS8INF "PRIVATE KEY" +#define PEM_STRING_DHPARAMS "DH PARAMETERS" +#define PEM_STRING_SSL_SESSION "SSL SESSION PARAMETERS" +#define PEM_STRING_DSAPARAMS "DSA PARAMETERS" +#define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY" +#define PEM_STRING_ECPARAMETERS "EC PARAMETERS" +#define PEM_STRING_ECPRIVATEKEY "EC PRIVATE KEY" +#define PEM_STRING_PARAMETERS "PARAMETERS" +#define PEM_STRING_CMS "CMS" + +/* enc_type is one off */ +#define PEM_TYPE_ENCRYPTED 10 +#define PEM_TYPE_MIC_ONLY 20 +#define PEM_TYPE_MIC_CLEAR 30 +#define PEM_TYPE_CLEAR 40 + +typedef struct pem_recip_st { + char *name; + X509_NAME *dn; + + int cipher; + int key_enc; + /* char iv[8]; unused and wrong size */ +} PEM_USER; + +typedef struct pem_ctx_st { + int type; /* what type of object */ + + struct { + int version; + int mode; + } proc_type; + + char *domain; + + struct { + int cipher; + /* unused, and wrong size + unsigned char iv[8]; */ + } DEK_info; + + PEM_USER *originator; + + int num_recipient; + PEM_USER **recipient; + + /* XXX(ben): don#t think this is used! + STACK *x509_chain; / * certificate chain */ + EVP_MD *md; /* signature type */ + + int md_enc; /* is the md encrypted or not? */ + int md_len; /* length of md_data */ + char *md_data; /* message digest, could be pkey encrypted */ + + EVP_CIPHER *dec; /* date encryption cipher */ + int key_len; /* key length */ + unsigned char *key; /* key */ + /* unused, and wrong size + unsigned char iv[8]; */ + + int data_enc; /* is the data encrypted */ + int data_len; + unsigned char *data; +} PEM_CTX; + +#ifndef LIBRESSL_INTERNAL +/* These macros make the PEM_read/PEM_write functions easier to maintain and + * write. Now they are all implemented with either: + * IMPLEMENT_PEM_rw(...) or IMPLEMENT_PEM_rw_cb(...) + */ + +#define IMPLEMENT_PEM_read_fp(name, type, str, asn1) \ +type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read((d2i_of_void *)d2i_##asn1, str,fp,(void **)x,cb,u); \ +} + +#define IMPLEMENT_PEM_write_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, const type *x) \ +{ \ +return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) \ +int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, \ + void *u) \ + { \ + return PEM_ASN1_write((i2d_of_void *)i2d_##asn1,str,fp,x,enc,kstr,klen,cb,u); \ + } + + +#define IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ +type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u)\ +{ \ +return PEM_ASN1_read_bio((d2i_of_void *)d2i_##asn1, str,bp,(void **)x,cb,u); \ +} + +#define IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, const type *x) \ +{ \ +return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,NULL,NULL,0,NULL,NULL); \ +} + +#define IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ +int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u) \ + { \ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_##asn1,str,bp,(void *)x,enc,kstr,klen,cb,u); \ + } + +#define IMPLEMENT_PEM_write(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_write_cb_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_bio_const(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb_fp_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_read_bio(name, type, str, asn1) \ + IMPLEMENT_PEM_read_fp(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_const(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_const(name, type, str, asn1) + +#define IMPLEMENT_PEM_rw_cb(name, type, str, asn1) \ + IMPLEMENT_PEM_read(name, type, str, asn1) \ + IMPLEMENT_PEM_write_cb(name, type, str, asn1) + +#endif + +/* These are the same except they are for the declarations */ + + +#define DECLARE_PEM_read_fp(name, type) \ + type *PEM_read_##name(FILE *fp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x); + +#define DECLARE_PEM_write_fp_const(name, type) \ + int PEM_write_##name(FILE *fp, const type *x); + +#define DECLARE_PEM_write_cb_fp(name, type) \ + int PEM_write_##name(FILE *fp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + + +#ifndef OPENSSL_NO_BIO +#define DECLARE_PEM_read_bio(name, type) \ + type *PEM_read_bio_##name(BIO *bp, type **x, pem_password_cb *cb, void *u); + +#define DECLARE_PEM_write_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x); + +#define DECLARE_PEM_write_bio_const(name, type) \ + int PEM_write_bio_##name(BIO *bp, const type *x); + +#define DECLARE_PEM_write_cb_bio(name, type) \ + int PEM_write_bio_##name(BIO *bp, type *x, const EVP_CIPHER *enc, \ + unsigned char *kstr, int klen, pem_password_cb *cb, void *u); + +#else + +#define DECLARE_PEM_read_bio(name, type) /**/ +#define DECLARE_PEM_write_bio(name, type) /**/ +#define DECLARE_PEM_write_bio_const(name, type) /**/ +#define DECLARE_PEM_write_cb_bio(name, type) /**/ + +#endif + +#define DECLARE_PEM_write(name, type) \ + DECLARE_PEM_write_bio(name, type) \ + DECLARE_PEM_write_fp(name, type) + +#define DECLARE_PEM_write_const(name, type) \ + DECLARE_PEM_write_bio_const(name, type) \ + DECLARE_PEM_write_fp_const(name, type) + +#define DECLARE_PEM_write_cb(name, type) \ + DECLARE_PEM_write_cb_bio(name, type) \ + DECLARE_PEM_write_cb_fp(name, type) + +#define DECLARE_PEM_read(name, type) \ + DECLARE_PEM_read_bio(name, type) \ + DECLARE_PEM_read_fp(name, type) + +#define DECLARE_PEM_rw(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write(name, type) + +#define DECLARE_PEM_rw_const(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_const(name, type) + +#define DECLARE_PEM_rw_cb(name, type) \ + DECLARE_PEM_read(name, type) \ + DECLARE_PEM_write_cb(name, type) + +typedef int pem_password_cb(char *buf, int size, int rwflag, void *userdata); + +int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher); +int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data, long *len, + pem_password_cb *callback, void *u); + +#ifndef OPENSSL_NO_BIO +int PEM_read_bio(BIO *bp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write_bio(BIO *bp, const char *name, const char *hdr, + const unsigned char *data, long len); +int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, + const char *name, BIO *bp, pem_password_cb *cb, void *u); +void * PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, + void **x, pem_password_cb *cb, void *u); +int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, + pem_password_cb *cb, void *u); + +STACK_OF(X509_INFO) * PEM_X509_INFO_read_bio(BIO *bp, + STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); +int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc, + unsigned char *kstr, int klen, pem_password_cb *cd, void *u); +#endif + +int PEM_read(FILE *fp, char **name, char **header, + unsigned char **data, long *len); +int PEM_write(FILE *fp, const char *name, const char *hdr, + const unsigned char *data, long len); +void * PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, + pem_password_cb *cb, void *u); +int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, + void *x, const EVP_CIPHER *enc, unsigned char *kstr, + int klen, pem_password_cb *callback, void *u); +STACK_OF(X509_INFO) * PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, + pem_password_cb *cb, void *u); + +int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type); +int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *d, unsigned int cnt); +int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, EVP_PKEY *pkey); + +int PEM_def_callback(char *buf, int num, int w, void *key); +void PEM_proc_type(char *buf, int type); +void PEM_dek_info(char *buf, const char *type, int len, char *str); + + +DECLARE_PEM_rw(X509, X509) + +DECLARE_PEM_rw(X509_AUX, X509) + +DECLARE_PEM_rw(X509_REQ, X509_REQ) +DECLARE_PEM_write(X509_REQ_NEW, X509_REQ) + +DECLARE_PEM_rw(X509_CRL, X509_CRL) + +DECLARE_PEM_rw(PKCS7, PKCS7) + +DECLARE_PEM_rw(PKCS8, X509_SIG) + +DECLARE_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +#ifndef OPENSSL_NO_RSA + +DECLARE_PEM_rw_cb(RSAPrivateKey, RSA) + +DECLARE_PEM_rw_const(RSAPublicKey, RSA) +DECLARE_PEM_rw(RSA_PUBKEY, RSA) + +#endif + +#ifndef OPENSSL_NO_DSA + +DECLARE_PEM_rw_cb(DSAPrivateKey, DSA) + +DECLARE_PEM_rw(DSA_PUBKEY, DSA) + +DECLARE_PEM_rw_const(DSAparams, DSA) + +#endif + +#ifndef OPENSSL_NO_EC +DECLARE_PEM_rw_const(ECPKParameters, EC_GROUP) +DECLARE_PEM_rw_cb(ECPrivateKey, EC_KEY) +DECLARE_PEM_rw(EC_PUBKEY, EC_KEY) +#endif + +#ifndef OPENSSL_NO_DH + +DECLARE_PEM_rw_const(DHparams, DH) + +#endif + +DECLARE_PEM_rw_cb(PrivateKey, EVP_PKEY) + +DECLARE_PEM_rw(PUBKEY, EVP_PKEY) + +int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x, + const EVP_CIPHER *enc, unsigned char *kstr, int klen, pem_password_cb *cb, + void *u); +int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_bio_PKCS8PrivateKey(BIO *, EVP_PKEY *, const EVP_CIPHER *, + char *, int, pem_password_cb *, void *); +int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +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_nid_fp(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); +int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid, + char *kstr, int klen, + pem_password_cb *cb, void *u); + +EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, + void *u); + +int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc, + char *kstr, int klen, pem_password_cb *cd, void *u); + +EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x); +int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x); + + +EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length); +EVP_PKEY *b2i_PrivateKey_bio(BIO *in); +EVP_PKEY *b2i_PublicKey_bio(BIO *in); +int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk); +int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk); +#ifndef OPENSSL_NO_RC4 +EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u); +int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel, pem_password_cb *cb, + void *u); +#endif + + +void ERR_load_PEM_strings(void); + +/* Error codes for the PEM functions. */ + +/* Function codes. */ +#define PEM_F_B2I_DSS 127 +#define PEM_F_B2I_PVK_BIO 128 +#define PEM_F_B2I_RSA 129 +#define PEM_F_CHECK_BITLEN_DSA 130 +#define PEM_F_CHECK_BITLEN_RSA 131 +#define PEM_F_D2I_PKCS8PRIVATEKEY_BIO 120 +#define PEM_F_D2I_PKCS8PRIVATEKEY_FP 121 +#define PEM_F_DO_B2I 132 +#define PEM_F_DO_B2I_BIO 133 +#define PEM_F_DO_BLOB_HEADER 134 +#define PEM_F_DO_PK8PKEY 126 +#define PEM_F_DO_PK8PKEY_FP 125 +#define PEM_F_DO_PVK_BODY 135 +#define PEM_F_DO_PVK_HEADER 136 +#define PEM_F_I2B_PVK 137 +#define PEM_F_I2B_PVK_BIO 138 +#define PEM_F_LOAD_IV 101 +#define PEM_F_PEM_ASN1_READ 102 +#define PEM_F_PEM_ASN1_READ_BIO 103 +#define PEM_F_PEM_ASN1_WRITE 104 +#define PEM_F_PEM_ASN1_WRITE_BIO 105 +#define PEM_F_PEM_DEF_CALLBACK 100 +#define PEM_F_PEM_DO_HEADER 106 +#define PEM_F_PEM_F_PEM_WRITE_PKCS8PRIVATEKEY 118 +#define PEM_F_PEM_GET_EVP_CIPHER_INFO 107 +#define PEM_F_PEM_PK8PKEY 119 +#define PEM_F_PEM_READ 108 +#define PEM_F_PEM_READ_BIO 109 +#define PEM_F_PEM_READ_BIO_PARAMETERS 140 +#define PEM_F_PEM_READ_BIO_PRIVATEKEY 123 +#define PEM_F_PEM_READ_PRIVATEKEY 124 +#define PEM_F_PEM_SEALFINAL 110 +#define PEM_F_PEM_SEALINIT 111 +#define PEM_F_PEM_SIGNFINAL 112 +#define PEM_F_PEM_WRITE 113 +#define PEM_F_PEM_WRITE_BIO 114 +#define PEM_F_PEM_WRITE_PRIVATEKEY 139 +#define PEM_F_PEM_X509_INFO_READ 115 +#define PEM_F_PEM_X509_INFO_READ_BIO 116 +#define PEM_F_PEM_X509_INFO_WRITE_BIO 117 + +/* Reason codes. */ +#define PEM_R_BAD_BASE64_DECODE 100 +#define PEM_R_BAD_DECRYPT 101 +#define PEM_R_BAD_END_LINE 102 +#define PEM_R_BAD_IV_CHARS 103 +#define PEM_R_BAD_MAGIC_NUMBER 116 +#define PEM_R_BAD_PASSWORD_READ 104 +#define PEM_R_BAD_VERSION_NUMBER 117 +#define PEM_R_BIO_WRITE_FAILURE 118 +#define PEM_R_CIPHER_IS_NULL 127 +#define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115 +#define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119 +#define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120 +#define PEM_R_INCONSISTENT_HEADER 121 +#define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122 +#define PEM_R_KEYBLOB_TOO_SHORT 123 +#define PEM_R_NOT_DEK_INFO 105 +#define PEM_R_NOT_ENCRYPTED 106 +#define PEM_R_NOT_PROC_TYPE 107 +#define PEM_R_NO_START_LINE 108 +#define PEM_R_PROBLEMS_GETTING_PASSWORD 109 +#define PEM_R_PUBLIC_KEY_NO_RSA 110 +#define PEM_R_PVK_DATA_TOO_SHORT 124 +#define PEM_R_PVK_TOO_SHORT 125 +#define PEM_R_READ_KEY 111 +#define PEM_R_SHORT_HEADER 112 +#define PEM_R_UNSUPPORTED_CIPHER 113 +#define PEM_R_UNSUPPORTED_ENCRYPTION 114 +#define PEM_R_UNSUPPORTED_KEY_COMPONENTS 126 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/pem2.h b/include/openssl/pem2.h new file mode 100644 index 0000000..19525b4 --- /dev/null +++ b/include/openssl/pem2.h @@ -0,0 +1,71 @@ +/* $OpenBSD: pem2.h,v 1.5 2014/06/12 15:49:30 deraadt Exp $ */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* + * This header only exists to break a circular dependency between pem and err + * Ben 30 Jan 1999. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HEADER_PEM_H +void ERR_load_PEM_strings(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/include/openssl/pkcs12.h b/include/openssl/pkcs12.h new file mode 100644 index 0000000..44dbb38 --- /dev/null +++ b/include/openssl/pkcs12.h @@ -0,0 +1,344 @@ +/* $OpenBSD: pkcs12.h,v 1.27 2022/09/11 17:30:13 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_PKCS12_H +#define HEADER_PKCS12_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PKCS12_KEY_ID 1 +#define PKCS12_IV_ID 2 +#define PKCS12_MAC_ID 3 + +/* Default iteration count */ +#ifndef PKCS12_DEFAULT_ITER +#define PKCS12_DEFAULT_ITER PKCS5_DEFAULT_ITER +#endif + +#define PKCS12_MAC_KEY_LENGTH 20 + +#define PKCS12_SALT_LEN 8 + +/* Uncomment out next line for unicode password and names, otherwise ASCII */ + +/*#define PBE_UNICODE*/ + +#ifdef PBE_UNICODE +#define PKCS12_key_gen PKCS12_key_gen_uni +#define PKCS12_add_friendlyname PKCS12_add_friendlyname_uni +#else +#define PKCS12_key_gen PKCS12_key_gen_asc +#define PKCS12_add_friendlyname PKCS12_add_friendlyname_asc +#endif + +/* MS key usage constants */ + +#define KEY_EX 0x10 +#define KEY_SIG 0x80 + +typedef struct PKCS12_MAC_DATA_st PKCS12_MAC_DATA; + +typedef struct PKCS12_st PKCS12; + +typedef struct PKCS12_SAFEBAG_st PKCS12_SAFEBAG; + +DECLARE_STACK_OF(PKCS12_SAFEBAG) +DECLARE_PKCS12_STACK_OF(PKCS12_SAFEBAG) + +typedef struct pkcs12_bag_st PKCS12_BAGS; + +#define PKCS12_ERROR 0 +#define PKCS12_OK 1 + +#ifndef LIBRESSL_INTERNAL + +/* Compatibility macros */ + +#define M_PKCS12_x5092certbag PKCS12_x5092certbag +#define M_PKCS12_x509crl2certbag PKCS12_x509crl2certbag + +#define M_PKCS12_certbag2x509 PKCS12_certbag2x509 +#define M_PKCS12_certbag2x509crl PKCS12_certbag2x509crl + +#define M_PKCS12_unpack_p7data PKCS12_unpack_p7data +#define M_PKCS12_pack_authsafes PKCS12_pack_authsafes +#define M_PKCS12_unpack_authsafes PKCS12_unpack_authsafes +#define M_PKCS12_unpack_p7encdata PKCS12_unpack_p7encdata + +#define M_PKCS12_decrypt_skey PKCS12_decrypt_skey +#define M_PKCS8_decrypt PKCS8_decrypt + +#endif /* !LIBRESSL_INTERNAL */ + +#define M_PKCS12_bag_type PKCS12_bag_type +#define M_PKCS12_cert_bag_type PKCS12_cert_bag_type +#define M_PKCS12_crl_bag_type PKCS12_cert_bag_type + +#define PKCS12_bag_type PKCS12_SAFEBAG_get_nid +#define PKCS12_cert_bag_type PKCS12_SAFEBAG_get_bag_nid + +#define PKCS12_certbag2x509 PKCS12_SAFEBAG_get1_cert +#define PKCS12_certbag2x509crl PKCS12_SAFEBAG_get1_crl + +#define PKCS12_x5092certbag PKCS12_SAFEBAG_create_cert +#define PKCS12_x509crl2certbag PKCS12_SAFEBAG_create_crl +#define PKCS12_MAKE_KEYBAG PKCS12_SAFEBAG_create0_p8inf +#define PKCS12_MAKE_SHKEYBAG PKCS12_SAFEBAG_create_pkcs8_encrypt + +const ASN1_TYPE *PKCS12_SAFEBAG_get0_attr(const PKCS12_SAFEBAG *bag, + int attr_nid); +const STACK_OF(X509_ATTRIBUTE) * + PKCS12_SAFEBAG_get0_attrs(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_nid(const PKCS12_SAFEBAG *bag); +int PKCS12_SAFEBAG_get_bag_nid(const PKCS12_SAFEBAG *bag); + +X509 *PKCS12_SAFEBAG_get1_cert(const PKCS12_SAFEBAG *bag); +X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag); + +ASN1_TYPE *PKCS8_get_attr(PKCS8_PRIV_KEY_INFO *p8, int attr_nid); +int PKCS12_mac_present(const PKCS12 *p12); +void PKCS12_get0_mac(const ASN1_OCTET_STRING **pmac, const X509_ALGOR **pmacalg, + const ASN1_OCTET_STRING **psalt, const ASN1_INTEGER **piter, + const PKCS12 *p12); + +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_crl(X509_CRL *crl); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_p8inf(PKCS8_PRIV_KEY_INFO *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create0_pkcs8(X509_SIG *p8); +PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid, + const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8); + +const PKCS8_PRIV_KEY_INFO *PKCS12_SAFEBAG_get0_p8inf(const PKCS12_SAFEBAG *bag); +const X509_SIG *PKCS12_SAFEBAG_get0_pkcs8(const PKCS12_SAFEBAG *bag); +const STACK_OF(PKCS12_SAFEBAG) * + PKCS12_SAFEBAG_get0_safes(const PKCS12_SAFEBAG *bag); +const ASN1_OBJECT *PKCS12_SAFEBAG_get0_type(const PKCS12_SAFEBAG *bag); + +PKCS12_SAFEBAG *PKCS12_item_pack_safebag(void *obj, const ASN1_ITEM *it, + int nid1, int nid2); +PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(const X509_SIG *p8, const char *pass, + int passlen); +PKCS8_PRIV_KEY_INFO *PKCS12_decrypt_skey(const PKCS12_SAFEBAG *bag, + const char *pass, int passlen); +X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, + const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, + PKCS8_PRIV_KEY_INFO *p8); +PKCS7 *PKCS12_pack_p7data(STACK_OF(PKCS12_SAFEBAG) *sk); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7); +PKCS7 *PKCS12_pack_p7encdata(int pbe_nid, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, STACK_OF(PKCS12_SAFEBAG) *bags); +STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass, + int passlen); + +int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes); +STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12); + +int PKCS12_add_localkeyid(PKCS12_SAFEBAG *bag, unsigned char *name, + int namelen); +int PKCS12_add_friendlyname_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_CSPName_asc(PKCS12_SAFEBAG *bag, const char *name, + int namelen); +int PKCS12_add_friendlyname_uni(PKCS12_SAFEBAG *bag, const unsigned char *name, + int namelen); +int PKCS8_add_keyusage(PKCS8_PRIV_KEY_INFO *p8, int usage); +ASN1_TYPE *PKCS12_get_attr_gen(const STACK_OF(X509_ATTRIBUTE) *attrs, + int attr_nid); +char *PKCS12_get_friendlyname(PKCS12_SAFEBAG *bag); +unsigned char *PKCS12_pbe_crypt(const X509_ALGOR *algor, const char *pass, + int passlen, const unsigned char *in, int inlen, unsigned char **data, + int *datalen, int en_de); +void *PKCS12_item_decrypt_d2i(const X509_ALGOR *algor, const ASN1_ITEM *it, + const char *pass, int passlen, const ASN1_OCTET_STRING *oct, int zbuf); +ASN1_OCTET_STRING *PKCS12_item_i2d_encrypt(X509_ALGOR *algor, + const ASN1_ITEM *it, const char *pass, int passlen, void *obj, int zbuf); +PKCS12 *PKCS12_init(int mode); +int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, unsigned char *out, + const EVP_MD *md_type); +int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, + int saltlen, int id, int iter, int n, unsigned char *out, + const EVP_MD *md_type); +int PKCS12_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, + ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md_type, + int en_de); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); +int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); +int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *salt, int saltlen, int iter, + const EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, const EVP_MD *md_type); +unsigned char *OPENSSL_asc2uni(const char *asc, int asclen, + unsigned char **uni, int *unilen); +char *OPENSSL_uni2asc(const unsigned char *uni, int unilen); + +PKCS12 *PKCS12_new(void); +void PKCS12_free(PKCS12 *a); +PKCS12 *d2i_PKCS12(PKCS12 **a, const unsigned char **in, long len); +int i2d_PKCS12(PKCS12 *a, unsigned char **out); +extern const ASN1_ITEM PKCS12_it; +PKCS12_MAC_DATA *PKCS12_MAC_DATA_new(void); +void PKCS12_MAC_DATA_free(PKCS12_MAC_DATA *a); +PKCS12_MAC_DATA *d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, const unsigned char **in, long len); +int i2d_PKCS12_MAC_DATA(PKCS12_MAC_DATA *a, unsigned char **out); +extern const ASN1_ITEM PKCS12_MAC_DATA_it; +PKCS12_SAFEBAG *PKCS12_SAFEBAG_new(void); +void PKCS12_SAFEBAG_free(PKCS12_SAFEBAG *a); +PKCS12_SAFEBAG *d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, const unsigned char **in, long len); +int i2d_PKCS12_SAFEBAG(PKCS12_SAFEBAG *a, unsigned char **out); +extern const ASN1_ITEM PKCS12_SAFEBAG_it; +PKCS12_BAGS *PKCS12_BAGS_new(void); +void PKCS12_BAGS_free(PKCS12_BAGS *a); +PKCS12_BAGS *d2i_PKCS12_BAGS(PKCS12_BAGS **a, const unsigned char **in, long len); +int i2d_PKCS12_BAGS(PKCS12_BAGS *a, unsigned char **out); +extern const ASN1_ITEM PKCS12_BAGS_it; + +extern const ASN1_ITEM PKCS12_SAFEBAGS_it; +extern const ASN1_ITEM PKCS12_AUTHSAFES_it; + +void PKCS12_PBE_add(void); +int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, + STACK_OF(X509) **ca); +PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, + X509 *cert, STACK_OF(X509) *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype); + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert); +PKCS12_SAFEBAG *PKCS12_add_key(STACK_OF(PKCS12_SAFEBAG) **pbags, EVP_PKEY *key, + int key_usage, int iter, int key_nid, const char *pass); +int PKCS12_add_safe(STACK_OF(PKCS7) **psafes, STACK_OF(PKCS12_SAFEBAG) *bags, + int safe_nid, int iter, const char *pass); +PKCS12 *PKCS12_add_safes(STACK_OF(PKCS7) *safes, int p7_nid); + +int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); +int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); +PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); +PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); +int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass); + +void ERR_load_PKCS12_strings(void); + +/* Error codes for the PKCS12 functions. */ + +/* Function codes. */ +#define PKCS12_F_PARSE_BAG 129 +#define PKCS12_F_PARSE_BAGS 103 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME 100 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_ASC 127 +#define PKCS12_F_PKCS12_ADD_FRIENDLYNAME_UNI 102 +#define PKCS12_F_PKCS12_ADD_LOCALKEYID 104 +#define PKCS12_F_PKCS12_CREATE 105 +#define PKCS12_F_PKCS12_GEN_MAC 107 +#define PKCS12_F_PKCS12_INIT 109 +#define PKCS12_F_PKCS12_ITEM_DECRYPT_D2I 106 +#define PKCS12_F_PKCS12_ITEM_I2D_ENCRYPT 108 +#define PKCS12_F_PKCS12_ITEM_PACK_SAFEBAG 117 +#define PKCS12_F_PKCS12_KEY_GEN_ASC 110 +#define PKCS12_F_PKCS12_KEY_GEN_UNI 111 +#define PKCS12_F_PKCS12_MAKE_KEYBAG 112 +#define PKCS12_F_PKCS12_MAKE_SHKEYBAG 113 +#define PKCS12_F_PKCS12_NEWPASS 128 +#define PKCS12_F_PKCS12_PACK_P7DATA 114 +#define PKCS12_F_PKCS12_PACK_P7ENCDATA 115 +#define PKCS12_F_PKCS12_PARSE 118 +#define PKCS12_F_PKCS12_PBE_CRYPT 119 +#define PKCS12_F_PKCS12_PBE_KEYIVGEN 120 +#define PKCS12_F_PKCS12_SETUP_MAC 122 +#define PKCS12_F_PKCS12_SET_MAC 123 +#define PKCS12_F_PKCS12_UNPACK_AUTHSAFES 130 +#define PKCS12_F_PKCS12_UNPACK_P7DATA 131 +#define PKCS12_F_PKCS12_VERIFY_MAC 126 +#define PKCS12_F_PKCS8_ADD_KEYUSAGE 124 +#define PKCS12_F_PKCS8_ENCRYPT 125 + +/* Reason codes. */ +#define PKCS12_R_CANT_PACK_STRUCTURE 100 +#define PKCS12_R_CONTENT_TYPE_NOT_DATA 121 +#define PKCS12_R_DECODE_ERROR 101 +#define PKCS12_R_ENCODE_ERROR 102 +#define PKCS12_R_ENCRYPT_ERROR 103 +#define PKCS12_R_ERROR_SETTING_ENCRYPTED_DATA_TYPE 120 +#define PKCS12_R_INVALID_NULL_ARGUMENT 104 +#define PKCS12_R_INVALID_NULL_PKCS12_POINTER 105 +#define PKCS12_R_IV_GEN_ERROR 106 +#define PKCS12_R_KEY_GEN_ERROR 107 +#define PKCS12_R_MAC_ABSENT 108 +#define PKCS12_R_MAC_GENERATION_ERROR 109 +#define PKCS12_R_MAC_SETUP_ERROR 110 +#define PKCS12_R_MAC_STRING_SET_ERROR 111 +#define PKCS12_R_MAC_VERIFY_ERROR 112 +#define PKCS12_R_MAC_VERIFY_FAILURE 113 +#define PKCS12_R_PARSE_ERROR 114 +#define PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR 115 +#define PKCS12_R_PKCS12_CIPHERFINAL_ERROR 116 +#define PKCS12_R_PKCS12_PBE_CRYPT_ERROR 117 +#define PKCS12_R_UNKNOWN_DIGEST_ALGORITHM 118 +#define PKCS12_R_UNSUPPORTED_PKCS12_MODE 119 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h new file mode 100644 index 0000000..bea1a20 --- /dev/null +++ b/include/openssl/pkcs7.h @@ -0,0 +1,524 @@ +/* $OpenBSD: pkcs7.h,v 1.21 2023/04/25 18:04:03 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_PKCS7_H +#define HEADER_PKCS7_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) && defined(__WINCRYPT_H__) +#if !defined(LIBRESSL_INTERNAL) && !defined(LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING) +#ifdef _MSC_VER +#pragma message("Warning, overriding WinCrypt defines") +#else +#warning overriding WinCrypt defines +#endif +#endif +#undef PKCS7_ISSUER_AND_SERIAL +#undef PKCS7_SIGNER_INFO +#endif + +/* +Encryption_ID DES-CBC +Digest_ID MD5 +Digest_Encryption_ID rsaEncryption +Key_Encryption_ID rsaEncryption +*/ + +typedef struct pkcs7_issuer_and_serial_st { + X509_NAME *issuer; + ASN1_INTEGER *serial; +} PKCS7_ISSUER_AND_SERIAL; + +typedef struct pkcs7_signer_info_st { + ASN1_INTEGER *version; /* version 1 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *digest_alg; + STACK_OF(X509_ATTRIBUTE) *auth_attr; /* [ 0 ] */ + X509_ALGOR *digest_enc_alg; + ASN1_OCTET_STRING *enc_digest; + STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */ + + /* The private key to sign with */ + EVP_PKEY *pkey; +} PKCS7_SIGNER_INFO; + +DECLARE_STACK_OF(PKCS7_SIGNER_INFO) + +typedef struct pkcs7_recip_info_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ISSUER_AND_SERIAL *issuer_and_serial; + X509_ALGOR *key_enc_algor; + ASN1_OCTET_STRING *enc_key; + X509 *cert; /* get the pub-key from this */ +} PKCS7_RECIP_INFO; + +DECLARE_STACK_OF(PKCS7_RECIP_INFO) + +typedef struct pkcs7_signed_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + + struct pkcs7_st *contents; +} PKCS7_SIGNED; +/* The above structure is very very similar to PKCS7_SIGN_ENVELOPE. + * How about merging the two */ + +typedef struct pkcs7_enc_content_st { + ASN1_OBJECT *content_type; + X509_ALGOR *algorithm; + ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; +} PKCS7_ENC_CONTENT; + +typedef struct pkcs7_enveloped_st { + ASN1_INTEGER *version; /* version 0 */ + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENVELOPE; + +typedef struct pkcs7_signedandenveloped_st { + ASN1_INTEGER *version; /* version 1 */ + STACK_OF(X509_ALGOR) *md_algs; /* md used */ + STACK_OF(X509) *cert; /* [ 0 ] */ + STACK_OF(X509_CRL) *crl; /* [ 1 ] */ + STACK_OF(PKCS7_SIGNER_INFO) *signer_info; + + PKCS7_ENC_CONTENT *enc_data; + STACK_OF(PKCS7_RECIP_INFO) *recipientinfo; +} PKCS7_SIGN_ENVELOPE; + +typedef struct pkcs7_digest_st { + ASN1_INTEGER *version; /* version 0 */ + X509_ALGOR *md; /* md used */ + struct pkcs7_st *contents; + ASN1_OCTET_STRING *digest; +} PKCS7_DIGEST; + +typedef struct pkcs7_encrypted_st { + ASN1_INTEGER *version; /* version 0 */ + PKCS7_ENC_CONTENT *enc_data; +} PKCS7_ENCRYPT; + +typedef struct pkcs7_st { + /* The following is non NULL if it contains ASN1 encoding of + * this structure */ + unsigned char *asn1; + long length; + +#define PKCS7_S_HEADER 0 +#define PKCS7_S_BODY 1 +#define PKCS7_S_TAIL 2 + int state; /* used during processing */ + + int detached; + + ASN1_OBJECT *type; + /* content as defined by the type */ + /* all encryption/message digests are applied to the 'contents', + * leaving out the 'type' field. */ + union { + char *ptr; + + /* NID_pkcs7_data */ + ASN1_OCTET_STRING *data; + + /* NID_pkcs7_signed */ + PKCS7_SIGNED *sign; + + /* NID_pkcs7_enveloped */ + PKCS7_ENVELOPE *enveloped; + + /* NID_pkcs7_signedAndEnveloped */ + PKCS7_SIGN_ENVELOPE *signed_and_enveloped; + + /* NID_pkcs7_digest */ + PKCS7_DIGEST *digest; + + /* NID_pkcs7_encrypted */ + PKCS7_ENCRYPT *encrypted; + + /* Anything else */ + ASN1_TYPE *other; + } d; +} PKCS7; + +DECLARE_STACK_OF(PKCS7) +DECLARE_PKCS12_STACK_OF(PKCS7) + +#define PKCS7_OP_SET_DETACHED_SIGNATURE 1 +#define PKCS7_OP_GET_DETACHED_SIGNATURE 2 + +#define PKCS7_get_signed_attributes(si) ((si)->auth_attr) +#define PKCS7_get_attributes(si) ((si)->unauth_attr) + +#define PKCS7_type_is_signed(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_signed) +#define PKCS7_type_is_encrypted(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) +#define PKCS7_type_is_enveloped(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_enveloped) +#define PKCS7_type_is_signedAndEnveloped(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_signedAndEnveloped) +#define PKCS7_type_is_data(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_data) +#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) +#define PKCS7_type_is_encrypted(a) \ + (OBJ_obj2nid((a)->type) == NID_pkcs7_encrypted) + +#define PKCS7_type_is_digest(a) (OBJ_obj2nid((a)->type) == NID_pkcs7_digest) + +#define PKCS7_set_detached(p,v) \ + PKCS7_ctrl(p,PKCS7_OP_SET_DETACHED_SIGNATURE,v,NULL) +#define PKCS7_get_detached(p) \ + PKCS7_ctrl(p,PKCS7_OP_GET_DETACHED_SIGNATURE,0,NULL) + +#define PKCS7_is_detached(p7) (PKCS7_type_is_signed(p7) && PKCS7_get_detached(p7)) + +/* S/MIME related flags */ + +#define PKCS7_TEXT 0x1 +#define PKCS7_NOCERTS 0x2 +#define PKCS7_NOSIGS 0x4 +#define PKCS7_NOCHAIN 0x8 +#define PKCS7_NOINTERN 0x10 +#define PKCS7_NOVERIFY 0x20 +#define PKCS7_DETACHED 0x40 +#define PKCS7_BINARY 0x80 +#define PKCS7_NOATTR 0x100 +#define PKCS7_NOSMIMECAP 0x200 +#define PKCS7_NOOLDMIMETYPE 0x400 +#define PKCS7_CRLFEOL 0x800 +#define PKCS7_STREAM 0x1000 +#define PKCS7_NOCRL 0x2000 +#define PKCS7_PARTIAL 0x4000 +#define PKCS7_REUSE_DIGEST 0x8000 + +/* Flags: for compatibility with older code */ + +#define SMIME_TEXT PKCS7_TEXT +#define SMIME_NOCERTS PKCS7_NOCERTS +#define SMIME_NOSIGS PKCS7_NOSIGS +#define SMIME_NOCHAIN PKCS7_NOCHAIN +#define SMIME_NOINTERN PKCS7_NOINTERN +#define SMIME_NOVERIFY PKCS7_NOVERIFY +#define SMIME_DETACHED PKCS7_DETACHED +#define SMIME_BINARY PKCS7_BINARY +#define SMIME_NOATTR PKCS7_NOATTR + +PKCS7_ISSUER_AND_SERIAL *PKCS7_ISSUER_AND_SERIAL_new(void); +void PKCS7_ISSUER_AND_SERIAL_free(PKCS7_ISSUER_AND_SERIAL *a); +PKCS7_ISSUER_AND_SERIAL *d2i_PKCS7_ISSUER_AND_SERIAL(PKCS7_ISSUER_AND_SERIAL **a, const unsigned char **in, long len); +int i2d_PKCS7_ISSUER_AND_SERIAL(PKCS7_ISSUER_AND_SERIAL *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_ISSUER_AND_SERIAL_it; + +int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, + const EVP_MD *type, unsigned char *md, unsigned int *len); +PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7); +int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7); +PKCS7 *PKCS7_dup(PKCS7 *p7); +PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7); +int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7); +int i2d_PKCS7_bio_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); +int PEM_write_bio_PKCS7_stream(BIO *out, PKCS7 *p7, BIO *in, int flags); + +PKCS7_SIGNER_INFO *PKCS7_SIGNER_INFO_new(void); +void PKCS7_SIGNER_INFO_free(PKCS7_SIGNER_INFO *a); +PKCS7_SIGNER_INFO *d2i_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO **a, const unsigned char **in, long len); +int i2d_PKCS7_SIGNER_INFO(PKCS7_SIGNER_INFO *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_SIGNER_INFO_it; +PKCS7_RECIP_INFO *PKCS7_RECIP_INFO_new(void); +void PKCS7_RECIP_INFO_free(PKCS7_RECIP_INFO *a); +PKCS7_RECIP_INFO *d2i_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO **a, const unsigned char **in, long len); +int i2d_PKCS7_RECIP_INFO(PKCS7_RECIP_INFO *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_RECIP_INFO_it; +PKCS7_SIGNED *PKCS7_SIGNED_new(void); +void PKCS7_SIGNED_free(PKCS7_SIGNED *a); +PKCS7_SIGNED *d2i_PKCS7_SIGNED(PKCS7_SIGNED **a, const unsigned char **in, long len); +int i2d_PKCS7_SIGNED(PKCS7_SIGNED *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_SIGNED_it; +PKCS7_ENC_CONTENT *PKCS7_ENC_CONTENT_new(void); +void PKCS7_ENC_CONTENT_free(PKCS7_ENC_CONTENT *a); +PKCS7_ENC_CONTENT *d2i_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT **a, const unsigned char **in, long len); +int i2d_PKCS7_ENC_CONTENT(PKCS7_ENC_CONTENT *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_ENC_CONTENT_it; +PKCS7_ENVELOPE *PKCS7_ENVELOPE_new(void); +void PKCS7_ENVELOPE_free(PKCS7_ENVELOPE *a); +PKCS7_ENVELOPE *d2i_PKCS7_ENVELOPE(PKCS7_ENVELOPE **a, const unsigned char **in, long len); +int i2d_PKCS7_ENVELOPE(PKCS7_ENVELOPE *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_ENVELOPE_it; +PKCS7_SIGN_ENVELOPE *PKCS7_SIGN_ENVELOPE_new(void); +void PKCS7_SIGN_ENVELOPE_free(PKCS7_SIGN_ENVELOPE *a); +PKCS7_SIGN_ENVELOPE *d2i_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE **a, const unsigned char **in, long len); +int i2d_PKCS7_SIGN_ENVELOPE(PKCS7_SIGN_ENVELOPE *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_SIGN_ENVELOPE_it; +PKCS7_DIGEST *PKCS7_DIGEST_new(void); +void PKCS7_DIGEST_free(PKCS7_DIGEST *a); +PKCS7_DIGEST *d2i_PKCS7_DIGEST(PKCS7_DIGEST **a, const unsigned char **in, long len); +int i2d_PKCS7_DIGEST(PKCS7_DIGEST *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_DIGEST_it; +PKCS7_ENCRYPT *PKCS7_ENCRYPT_new(void); +void PKCS7_ENCRYPT_free(PKCS7_ENCRYPT *a); +PKCS7_ENCRYPT *d2i_PKCS7_ENCRYPT(PKCS7_ENCRYPT **a, const unsigned char **in, long len); +int i2d_PKCS7_ENCRYPT(PKCS7_ENCRYPT *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_ENCRYPT_it; +PKCS7 *PKCS7_new(void); +void PKCS7_free(PKCS7 *a); +PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len); +int i2d_PKCS7(PKCS7 *a, unsigned char **out); +extern const ASN1_ITEM PKCS7_it; + +extern const ASN1_ITEM PKCS7_ATTR_SIGN_it; +extern const ASN1_ITEM PKCS7_ATTR_VERIFY_it; + +int PKCS7_print_ctx(BIO *out, PKCS7 *x, int indent, const ASN1_PCTX *pctx); + +long PKCS7_ctrl(PKCS7 *p7, int cmd, long larg, char *parg); + +int PKCS7_set_type(PKCS7 *p7, int type); +int PKCS7_set0_type_other(PKCS7 *p7, int type, ASN1_TYPE *other); +int PKCS7_set_content(PKCS7 *p7, PKCS7 *p7_data); +int PKCS7_SIGNER_INFO_set(PKCS7_SIGNER_INFO *p7i, X509 *x509, EVP_PKEY *pkey, + const EVP_MD *dgst); +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si); +int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *p7i); +int PKCS7_add_certificate(PKCS7 *p7, X509 *x509); +int PKCS7_add_crl(PKCS7 *p7, X509_CRL *x509); +int PKCS7_content_new(PKCS7 *p7, int nid); +int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, + BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, + X509 *x509); + +BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); +int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); + + +PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, + EVP_PKEY *pkey, const EVP_MD *dgst); +X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si); +int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md); +STACK_OF(PKCS7_SIGNER_INFO) *PKCS7_get_signer_info(PKCS7 *p7); + +PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); +void PKCS7_SIGNER_INFO_get0_algs(PKCS7_SIGNER_INFO *si, EVP_PKEY **pk, + X509_ALGOR **pdig, X509_ALGOR **psig); +void PKCS7_RECIP_INFO_get0_alg(PKCS7_RECIP_INFO *ri, X509_ALGOR **penc); +int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); +int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); +int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7); + +PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); +ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int type, + void *data); +int PKCS7_add_attribute (PKCS7_SIGNER_INFO *p7si, int nid, int atrtype, + void *value); +ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid); +ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid); +int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, + STACK_OF(X509_ATTRIBUTE) *sk); +int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk); + + +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags); + +PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, + X509 *signcert, EVP_PKEY *pkey, const EVP_MD *md, + int flags); + +int PKCS7_final(PKCS7 *p7, BIO *data, int flags); +int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, + BIO *indata, BIO *out, int flags); +STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags); +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags); +int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags); + +int PKCS7_add_attrib_smimecap(PKCS7_SIGNER_INFO *si, + STACK_OF(X509_ALGOR) *cap); +STACK_OF(X509_ALGOR) *PKCS7_get_smimecap(PKCS7_SIGNER_INFO *si); +int PKCS7_simple_smimecap(STACK_OF(X509_ALGOR) *sk, int nid, int arg); + +int PKCS7_add_attrib_content_type(PKCS7_SIGNER_INFO *si, ASN1_OBJECT *coid); +int PKCS7_add0_attrib_signing_time(PKCS7_SIGNER_INFO *si, ASN1_TIME *t); +int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si, + const unsigned char *md, int mdlen); + +int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags); +PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont); + +BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7); + + +void ERR_load_PKCS7_strings(void); + +/* Error codes for the PKCS7 functions. */ + +/* Function codes. */ +#define PKCS7_F_B64_READ_PKCS7 120 +#define PKCS7_F_B64_WRITE_PKCS7 121 +#define PKCS7_F_DO_PKCS7_SIGNED_ATTRIB 136 +#define PKCS7_F_I2D_PKCS7_BIO_STREAM 140 +#define PKCS7_F_PKCS7_ADD0_ATTRIB_SIGNING_TIME 135 +#define PKCS7_F_PKCS7_ADD_ATTRIB_SMIMECAP 118 +#define PKCS7_F_PKCS7_ADD_CERTIFICATE 100 +#define PKCS7_F_PKCS7_ADD_CRL 101 +#define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 +#define PKCS7_F_PKCS7_ADD_SIGNATURE 131 +#define PKCS7_F_PKCS7_ADD_SIGNER 103 +#define PKCS7_F_PKCS7_BIO_ADD_DIGEST 125 +#define PKCS7_F_PKCS7_COPY_EXISTING_DIGEST 138 +#define PKCS7_F_PKCS7_CTRL 104 +#define PKCS7_F_PKCS7_DATADECODE 112 +#define PKCS7_F_PKCS7_DATAFINAL 128 +#define PKCS7_F_PKCS7_DATAINIT 105 +#define PKCS7_F_PKCS7_DATASIGN 106 +#define PKCS7_F_PKCS7_DATAVERIFY 107 +#define PKCS7_F_PKCS7_DECRYPT 114 +#define PKCS7_F_PKCS7_DECRYPT_RINFO 133 +#define PKCS7_F_PKCS7_ENCODE_RINFO 132 +#define PKCS7_F_PKCS7_ENCRYPT 115 +#define PKCS7_F_PKCS7_FINAL 134 +#define PKCS7_F_PKCS7_FIND_DIGEST 127 +#define PKCS7_F_PKCS7_GET0_SIGNERS 124 +#define PKCS7_F_PKCS7_RECIP_INFO_SET 130 +#define PKCS7_F_PKCS7_SET_CIPHER 108 +#define PKCS7_F_PKCS7_SET_CONTENT 109 +#define PKCS7_F_PKCS7_SET_DIGEST 126 +#define PKCS7_F_PKCS7_SET_TYPE 110 +#define PKCS7_F_PKCS7_SIGN 116 +#define PKCS7_F_PKCS7_SIGNATUREVERIFY 113 +#define PKCS7_F_PKCS7_SIGNER_INFO_SET 129 +#define PKCS7_F_PKCS7_SIGNER_INFO_SIGN 139 +#define PKCS7_F_PKCS7_SIGN_ADD_SIGNER 137 +#define PKCS7_F_PKCS7_SIMPLE_SMIMECAP 119 +#define PKCS7_F_PKCS7_VERIFY 117 +#define PKCS7_F_SMIME_READ_PKCS7 122 +#define PKCS7_F_SMIME_TEXT 123 + +/* Reason codes. */ +#define PKCS7_R_CERTIFICATE_VERIFY_ERROR 117 +#define PKCS7_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER 144 +#define PKCS7_R_CIPHER_NOT_INITIALIZED 116 +#define PKCS7_R_CONTENT_AND_DATA_PRESENT 118 +#define PKCS7_R_CTRL_ERROR 152 +#define PKCS7_R_DECODE_ERROR 130 +#define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100 +#define PKCS7_R_DECRYPT_ERROR 119 +#define PKCS7_R_DIGEST_FAILURE 101 +#define PKCS7_R_ENCRYPTION_CTRL_FAILURE 149 +#define PKCS7_R_ENCRYPTION_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 150 +#define PKCS7_R_ERROR_ADDING_RECIPIENT 120 +#define PKCS7_R_ERROR_SETTING_CIPHER 121 +#define PKCS7_R_INVALID_MIME_TYPE 131 +#define PKCS7_R_INVALID_NULL_POINTER 143 +#define PKCS7_R_MIME_NO_CONTENT_TYPE 132 +#define PKCS7_R_MIME_PARSE_ERROR 133 +#define PKCS7_R_MIME_SIG_PARSE_ERROR 134 +#define PKCS7_R_MISSING_CERIPEND_INFO 103 +#define PKCS7_R_NO_CONTENT 122 +#define PKCS7_R_NO_CONTENT_TYPE 135 +#define PKCS7_R_NO_DEFAULT_DIGEST 151 +#define PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND 154 +#define PKCS7_R_NO_MULTIPART_BODY_FAILURE 136 +#define PKCS7_R_NO_MULTIPART_BOUNDARY 137 +#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 +#define PKCS7_R_NO_RECIPIENT_MATCHES_KEY 146 +#define PKCS7_R_NO_SIGNATURES_ON_DATA 123 +#define PKCS7_R_NO_SIGNERS 142 +#define PKCS7_R_NO_SIG_CONTENT_TYPE 138 +#define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 +#define PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR 124 +#define PKCS7_R_PKCS7_ADD_SIGNER_ERROR 153 +#define PKCS7_R_PKCS7_DATAFINAL 126 +#define PKCS7_R_PKCS7_DATAFINAL_ERROR 125 +#define PKCS7_R_PKCS7_DATASIGN 145 +#define PKCS7_R_PKCS7_PARSE_ERROR 139 +#define PKCS7_R_PKCS7_SIG_PARSE_ERROR 140 +#define PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 127 +#define PKCS7_R_SIGNATURE_FAILURE 105 +#define PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND 128 +#define PKCS7_R_SIGNING_CTRL_FAILURE 147 +#define PKCS7_R_SIGNING_NOT_SUPPORTED_FOR_THIS_KEY_TYPE 148 +#define PKCS7_R_SIG_INVALID_MIME_TYPE 141 +#define PKCS7_R_SMIME_TEXT_ERROR 129 +#define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 +#define PKCS7_R_UNABLE_TO_FIND_MEM_BIO 107 +#define PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST 108 +#define PKCS7_R_UNKNOWN_DIGEST_TYPE 109 +#define PKCS7_R_UNKNOWN_OPERATION 110 +#define PKCS7_R_UNSUPPORTED_CIPHER_TYPE 111 +#define PKCS7_R_UNSUPPORTED_CONTENT_TYPE 112 +#define PKCS7_R_WRONG_CONTENT_TYPE 113 +#define PKCS7_R_WRONG_PKCS7_TYPE 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/poly1305.h b/include/openssl/poly1305.h new file mode 100644 index 0000000..00ab0bf --- /dev/null +++ b/include/openssl/poly1305.h @@ -0,0 +1,49 @@ +/* $OpenBSD: poly1305.h,v 1.3 2014/07/25 14:04:51 jsing Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_POLY1305_H +#define HEADER_POLY1305_H + +#include + +#if defined(OPENSSL_NO_POLY1305) +#error Poly1305 is disabled. +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct poly1305_context { + size_t aligner; + unsigned char opaque[136]; +} poly1305_context; + +typedef struct poly1305_context poly1305_state; + +void CRYPTO_poly1305_init(poly1305_context *ctx, const unsigned char key[32]); +void CRYPTO_poly1305_update(poly1305_context *ctx, const unsigned char *in, + size_t len); +void CRYPTO_poly1305_finish(poly1305_context *ctx, unsigned char mac[16]); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_POLY1305_H */ diff --git a/include/openssl/rand.h b/include/openssl/rand.h new file mode 100644 index 0000000..a0e9b47 --- /dev/null +++ b/include/openssl/rand.h @@ -0,0 +1,123 @@ +/* $OpenBSD: rand.h,v 1.23 2022/07/12 14:42:50 kn Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#ifndef HEADER_RAND_H +#define HEADER_RAND_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Already defined in ossl_typ.h */ +/* typedef struct rand_meth_st RAND_METHOD; */ + +struct rand_meth_st { + void (*seed)(const void *buf, int num); + int (*bytes)(unsigned char *buf, int num); + void (*cleanup)(void); + void (*add)(const void *buf, int num, double entropy); + int (*pseudorand)(unsigned char *buf, int num); + int (*status)(void); +}; + +int RAND_set_rand_method(const RAND_METHOD *meth); +const RAND_METHOD *RAND_get_rand_method(void); +#ifndef OPENSSL_NO_ENGINE +int RAND_set_rand_engine(ENGINE *engine); +#endif +RAND_METHOD *RAND_SSLeay(void); + +#ifndef LIBRESSL_INTERNAL +void RAND_cleanup(void ); +int RAND_bytes(unsigned char *buf, int num); +int RAND_pseudo_bytes(unsigned char *buf, int num); +void RAND_seed(const void *buf, int num); +void RAND_add(const void *buf, int num, double entropy); +int RAND_load_file(const char *file, long max_bytes); +int RAND_write_file(const char *file); +const char *RAND_file_name(char *file, size_t num); +int RAND_status(void); +int RAND_poll(void); +#endif + +void ERR_load_RAND_strings(void); + +/* Error codes for the RAND functions. (no longer used) */ + +/* Function codes. */ +#define RAND_F_RAND_GET_RAND_METHOD 101 +#define RAND_F_RAND_INIT_FIPS 102 +#define RAND_F_SSLEAY_RAND_BYTES 100 + +/* Reason codes. */ +#define RAND_R_DUAL_EC_DRBG_DISABLED 104 +#define RAND_R_ERROR_INITIALISING_DRBG 102 +#define RAND_R_ERROR_INSTANTIATING_DRBG 103 +#define RAND_R_NO_FIPS_RANDOM_METHOD_SET 101 +#define RAND_R_PRNG_NOT_SEEDED 100 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/rc2.h b/include/openssl/rc2.h new file mode 100644 index 0000000..09c6c08 --- /dev/null +++ b/include/openssl/rc2.h @@ -0,0 +1,100 @@ +/* $OpenBSD: rc2.h,v 1.12 2023/07/07 08:29:37 beck Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC2_H +#define HEADER_RC2_H + +#include /* OPENSSL_NO_RC2, RC2_INT */ + +#ifdef OPENSSL_NO_RC2 +#error RC2 is disabled. +#endif + +#define RC2_ENCRYPT 1 +#define RC2_DECRYPT 0 + +#define RC2_BLOCK 8 +#define RC2_KEY_LENGTH 16 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc2_key_st { + RC2_INT data[64]; +} RC2_KEY; + +void RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits); +void RC2_ecb_encrypt(const unsigned char *in, unsigned char *out, RC2_KEY *key, + int enc); +void RC2_encrypt(unsigned long *data, RC2_KEY *key); +void RC2_decrypt(unsigned long *data, RC2_KEY *key); +void RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long length, + RC2_KEY *ks, unsigned char *iv, int enc); +void RC2_cfb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num, int enc); +void RC2_ofb64_encrypt(const unsigned char *in, unsigned char *out, + long length, RC2_KEY *schedule, unsigned char *ivec, + int *num); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/rc4.h b/include/openssl/rc4.h new file mode 100644 index 0000000..7ebe232 --- /dev/null +++ b/include/openssl/rc4.h @@ -0,0 +1,88 @@ +/* $OpenBSD: rc4.h,v 1.14 2023/07/28 10:35:14 tb Exp $ */ +/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RC4_H +#define HEADER_RC4_H + +#include /* OPENSSL_NO_RC4, RC4_INT */ + +#ifdef OPENSSL_NO_RC4 +#error RC4 is disabled. +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct rc4_key_st { + RC4_INT x, y; + RC4_INT data[256]; +} RC4_KEY; + +void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void private_RC4_set_key(RC4_KEY *key, int len, const unsigned char *data); +void RC4(RC4_KEY *key, size_t len, const unsigned char *indata, + unsigned char *outdata); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/ripemd.h b/include/openssl/ripemd.h new file mode 100644 index 0000000..03ba781 --- /dev/null +++ b/include/openssl/ripemd.h @@ -0,0 +1,104 @@ +/* $OpenBSD: ripemd.h,v 1.15 2023/07/08 06:52:56 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#ifndef HEADER_RIPEMD_H +#define HEADER_RIPEMD_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_RIPEMD +#error RIPEMD is disabled. +#endif + +#if defined(__LP32__) +#define RIPEMD160_LONG unsigned long +#elif defined(__ILP64__) +#define RIPEMD160_LONG unsigned long +#define RIPEMD160_LONG_LOG2 3 +#else +#define RIPEMD160_LONG unsigned int +#endif + +#define RIPEMD160_CBLOCK 64 +#define RIPEMD160_LBLOCK (RIPEMD160_CBLOCK/4) +#define RIPEMD160_DIGEST_LENGTH 20 + +typedef struct RIPEMD160state_st { + RIPEMD160_LONG A, B,C, D, E; + RIPEMD160_LONG Nl, Nh; + RIPEMD160_LONG data[RIPEMD160_LBLOCK]; + unsigned int num; +} RIPEMD160_CTX; + +int RIPEMD160_Init(RIPEMD160_CTX *c); +int RIPEMD160_Update(RIPEMD160_CTX *c, const void *data, size_t len); +int RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *c); +unsigned char *RIPEMD160(const unsigned char *d, size_t n, + unsigned char *md); +void RIPEMD160_Transform(RIPEMD160_CTX *c, const unsigned char *b); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h new file mode 100644 index 0000000..4fcef3a --- /dev/null +++ b/include/openssl/rsa.h @@ -0,0 +1,609 @@ +/* $OpenBSD: rsa.h,v 1.65 2023/07/28 10:05:16 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_RSA_H +#define HEADER_RSA_H + +#include + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include + +#include + +#ifdef OPENSSL_NO_RSA +#error RSA is disabled. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct rsa_pss_params_st { + X509_ALGOR *hashAlgorithm; + X509_ALGOR *maskGenAlgorithm; + ASN1_INTEGER *saltLength; + ASN1_INTEGER *trailerField; + + /* Hash algorithm decoded from maskGenAlgorithm. */ + X509_ALGOR *maskHash; +} /* RSA_PSS_PARAMS */; + +typedef struct rsa_oaep_params_st { + X509_ALGOR *hashFunc; + X509_ALGOR *maskGenFunc; + X509_ALGOR *pSourceFunc; + + /* Hash algorithm decoded from maskGenFunc. */ + X509_ALGOR *maskHash; +} RSA_OAEP_PARAMS; + +#ifndef OPENSSL_RSA_MAX_MODULUS_BITS +# define OPENSSL_RSA_MAX_MODULUS_BITS 16384 +#endif + +#ifndef OPENSSL_RSA_SMALL_MODULUS_BITS +# define OPENSSL_RSA_SMALL_MODULUS_BITS 3072 +#endif +#ifndef OPENSSL_RSA_MAX_PUBEXP_BITS +# define OPENSSL_RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */ +#endif + +#define RSA_3 0x3L +#define RSA_F4 0x10001L + +/* Don't check pub/private match. */ +#define RSA_METHOD_FLAG_NO_CHECK 0x0001 + +#define RSA_FLAG_CACHE_PUBLIC 0x0002 +#define RSA_FLAG_CACHE_PRIVATE 0x0004 +#define RSA_FLAG_BLINDING 0x0008 +#define RSA_FLAG_THREAD_SAFE 0x0010 + +/* + * This flag means the private key operations will be handled by rsa_mod_exp + * and that they do not depend on the private key components being present: + * for example a key stored in external hardware. Without this flag bn_mod_exp + * gets called when private key components are absent. + */ +#define RSA_FLAG_EXT_PKEY 0x0020 + +/* + * This flag in the RSA_METHOD enables the new rsa_sign, rsa_verify functions. + */ +#define RSA_FLAG_SIGN_VER 0x0040 + +/* + * The built-in RSA implementation uses blinding by default, but other engines + * might not need it. + */ +#define RSA_FLAG_NO_BLINDING 0x0080 + +/* Salt length matches digest */ +#define RSA_PSS_SALTLEN_DIGEST -1 +/* Verify only: auto detect salt length */ +#define RSA_PSS_SALTLEN_AUTO -2 +/* Set salt length to maximum possible */ +#define RSA_PSS_SALTLEN_MAX -3 + +#define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL) + +#define EVP_PKEY_CTX_get_rsa_padding(ctx, ppad) \ + RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_GET_RSA_PADDING, 0, ppad) + +#define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) + +#define EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, len) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL) + +#define EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, plen) \ + RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), \ + EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN, 0, plen) + +#define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL) + +#define EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pubexp) + +#define EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +#define EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, EVP_PKEY_OP_KEYGEN, \ + EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)(md)) + +#define EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)(md)) + +#define EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, pmd) \ + RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void *)(pmd)) + +#define EVP_PKEY_CTX_get_rsa_oaep_md(ctx, pmd) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_MD, 0, (void *)(pmd)) + +#define EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, l, llen) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)(l)) + +#define EVP_PKEY_CTX_get0_rsa_oaep_label(ctx, l) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, \ + EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL, 0, (void *)(l)) + +#define EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx, md) \ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA_PSS, \ + EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_MD, 0, (void *)(md)) + +#define EVP_PKEY_CTRL_RSA_PADDING (EVP_PKEY_ALG_CTRL + 1) +#define EVP_PKEY_CTRL_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 2) + +#define EVP_PKEY_CTRL_RSA_KEYGEN_BITS (EVP_PKEY_ALG_CTRL + 3) +#define EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP (EVP_PKEY_ALG_CTRL + 4) +#define EVP_PKEY_CTRL_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 5) + +#define EVP_PKEY_CTRL_GET_RSA_PADDING (EVP_PKEY_ALG_CTRL + 6) +#define EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN (EVP_PKEY_ALG_CTRL + 7) +#define EVP_PKEY_CTRL_GET_RSA_MGF1_MD (EVP_PKEY_ALG_CTRL + 8) + +#define EVP_PKEY_CTRL_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 9) +#define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 10) + +#define EVP_PKEY_CTRL_GET_RSA_OAEP_MD (EVP_PKEY_ALG_CTRL + 11) +#define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12) + +#define RSA_PKCS1_PADDING 1 +#define RSA_SSLV23_PADDING 2 +#define RSA_NO_PADDING 3 +#define RSA_PKCS1_OAEP_PADDING 4 +/* rust-openssl and erlang expose this and salt even uses it. */ +#define RSA_X931_PADDING 5 +/* EVP_PKEY_ only */ +#define RSA_PKCS1_PSS_PADDING 6 + +#define RSA_PKCS1_PADDING_SIZE 11 + +#define RSA_set_app_data(s,arg) RSA_set_ex_data(s,0,arg) +#define RSA_get_app_data(s) RSA_get_ex_data(s,0) + +RSA *RSA_new(void); +RSA *RSA_new_method(ENGINE *engine); +int RSA_bits(const RSA *rsa); +int RSA_size(const RSA *rsa); + +/* + * Wrapped in OPENSSL_NO_DEPRECATED in 0.9.8. Still used for libressl bindings + * in rust-openssl. + */ +RSA *RSA_generate_key(int bits, unsigned long e, + void (*callback)(int, int, void *), void *cb_arg); + +/* New version */ +int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb); + +int RSA_check_key(const RSA *); +/* next 4 return -1 on error */ +int RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +int RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +void RSA_free(RSA *r); +/* "up" the RSA object's reference count */ +int RSA_up_ref(RSA *r); + +int RSA_flags(const RSA *r); + +void RSA_set_default_method(const RSA_METHOD *meth); +const RSA_METHOD *RSA_get_default_method(void); +const RSA_METHOD *RSA_get_method(const RSA *rsa); +int RSA_set_method(RSA *rsa, const RSA_METHOD *meth); + +const RSA_METHOD *RSA_PKCS1_OpenSSL(void); +const RSA_METHOD *RSA_PKCS1_SSLeay(void); + +const RSA_METHOD *RSA_null_method(void); + +int RSA_pkey_ctx_ctrl(EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2); + +RSA *d2i_RSAPublicKey(RSA **a, const unsigned char **in, long len); +int i2d_RSAPublicKey(const RSA *a, unsigned char **out); +extern const ASN1_ITEM RSAPublicKey_it; +RSA *d2i_RSAPrivateKey(RSA **a, const unsigned char **in, long len); +int i2d_RSAPrivateKey(const RSA *a, unsigned char **out); +extern const ASN1_ITEM RSAPrivateKey_it; + +RSA_PSS_PARAMS *RSA_PSS_PARAMS_new(void); +void RSA_PSS_PARAMS_free(RSA_PSS_PARAMS *a); +RSA_PSS_PARAMS *d2i_RSA_PSS_PARAMS(RSA_PSS_PARAMS **a, const unsigned char **in, long len); +int i2d_RSA_PSS_PARAMS(RSA_PSS_PARAMS *a, unsigned char **out); +extern const ASN1_ITEM RSA_PSS_PARAMS_it; + +RSA_OAEP_PARAMS *RSA_OAEP_PARAMS_new(void); +void RSA_OAEP_PARAMS_free(RSA_OAEP_PARAMS *a); +RSA_OAEP_PARAMS *d2i_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS **a, const unsigned char **in, long len); +int i2d_RSA_OAEP_PARAMS(RSA_OAEP_PARAMS *a, unsigned char **out); +extern const ASN1_ITEM RSA_OAEP_PARAMS_it; + +int RSA_print_fp(FILE *fp, const RSA *r, int offset); + +#ifndef OPENSSL_NO_BIO +int RSA_print(BIO *bp, const RSA *r, int offset); +#endif + +/* The following 2 functions sign and verify a X509_SIG ASN1 object + * inside PKCS#1 padded RSA encryption */ +int RSA_sign(int type, const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, RSA *rsa); +int RSA_verify(int type, const unsigned char *m, unsigned int m_length, + const unsigned char *sigbuf, unsigned int siglen, RSA *rsa); + +/* The following 2 function sign and verify a ASN1_OCTET_STRING + * object inside PKCS#1 padded RSA encryption */ +int RSA_sign_ASN1_OCTET_STRING(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigret, unsigned int *siglen, + RSA *rsa); +int RSA_verify_ASN1_OCTET_STRING(int type, const unsigned char *m, + unsigned int m_length, unsigned char *sigbuf, unsigned int siglen, + RSA *rsa); + +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); +void RSA_blinding_off(RSA *rsa); + +int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); +int PKCS1_MGF1(unsigned char *mask, long len, + const unsigned char *seed, long seedlen, const EVP_MD *dgst); +int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, + const unsigned char *p, int pl); +int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len, + const unsigned char *p, int pl); +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); +int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen, + const unsigned char *from, int flen, int num, const unsigned char *param, + int plen, const EVP_MD *md, const EVP_MD *mgf1md); +int RSA_padding_add_none(unsigned char *to, int tlen, + const unsigned char *f, int fl); +int RSA_padding_check_none(unsigned char *to, int tlen, + const unsigned char *f, int fl, int rsa_len); + +int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const unsigned char *EM, int sLen); +int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, const EVP_MD *Hash, int sLen); + +int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const unsigned char *mHash, + const EVP_MD *Hash, const EVP_MD *mgf1Hash, const unsigned char *EM, + int sLen); + +int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM, + const unsigned char *mHash, const EVP_MD *Hash, const EVP_MD *mgf1Hash, + int sLen); + +int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int RSA_set_ex_data(RSA *r, int idx, void *arg); +void *RSA_get_ex_data(const RSA *r, int idx); + +int RSA_security_bits(const RSA *rsa); + +void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, + const BIGNUM **d); +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +const BIGNUM *RSA_get0_n(const RSA *r); +const BIGNUM *RSA_get0_e(const RSA *r); +const BIGNUM *RSA_get0_d(const RSA *r); +const BIGNUM *RSA_get0_p(const RSA *r); +const BIGNUM *RSA_get0_q(const RSA *r); +const BIGNUM *RSA_get0_dmp1(const RSA *r); +const BIGNUM *RSA_get0_dmq1(const RSA *r); +const BIGNUM *RSA_get0_iqmp(const RSA *r); +const RSA_PSS_PARAMS *RSA_get0_pss_params(const RSA *r); +void RSA_clear_flags(RSA *r, int flags); +int RSA_test_flags(const RSA *r, int flags); +void RSA_set_flags(RSA *r, int flags); + +RSA *RSAPublicKey_dup(RSA *rsa); +RSA *RSAPrivateKey_dup(RSA *rsa); + +/* If this flag is set the RSA method is FIPS compliant and can be used + * in FIPS mode. This is set in the validated module method. If an + * application sets this flag in its own methods it is its responsibility + * to ensure the result is compliant. + */ + +#define RSA_FLAG_FIPS_METHOD 0x0400 + +/* If this flag is set the operations normally disabled in FIPS mode are + * permitted it is then the applications responsibility to ensure that the + * usage is compliant. + */ + +#define RSA_FLAG_NON_FIPS_ALLOW 0x0400 +/* Application has decided PRNG is good enough to generate a key: don't + * check. + */ +#define RSA_FLAG_CHECKED 0x0800 + +RSA_METHOD *RSA_meth_new(const char *name, int flags); +void RSA_meth_free(RSA_METHOD *meth); +RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth); +int RSA_meth_set1_name(RSA_METHOD *meth, const char *name); +int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc)(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); +int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec)(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); +int (*RSA_meth_get_finish(const RSA_METHOD *meth))(RSA *rsa); +int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish)(RSA *rsa)); +int RSA_meth_set_pub_enc(RSA_METHOD *meth, int (*pub_enc)(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); +int RSA_meth_set_pub_dec(RSA_METHOD *meth, int (*pub_dec)(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); +int RSA_meth_set_mod_exp(RSA_METHOD *meth, int (*mod_exp)(BIGNUM *r0, + const BIGNUM *i, RSA *rsa, BN_CTX *ctx)); +int RSA_meth_set_bn_mod_exp(RSA_METHOD *meth, int (*bn_mod_exp)(BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx)); +int RSA_meth_set_init(RSA_METHOD *meth, int (*init)(RSA *rsa)); +int RSA_meth_set_keygen(RSA_METHOD *meth, int (*keygen)(RSA *rsa, int bits, + BIGNUM *e, BN_GENCB *cb)); +int RSA_meth_set_flags(RSA_METHOD *meth, int flags); +int RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data); +const char *RSA_meth_get0_name(const RSA_METHOD *); +int (*RSA_meth_get_pub_enc(const RSA_METHOD *meth))(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding); +int (*RSA_meth_get_pub_dec(const RSA_METHOD *meth))(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding); +int (*RSA_meth_get_priv_enc(const RSA_METHOD *meth))(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding); +int (*RSA_meth_get_priv_dec(const RSA_METHOD *meth))(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa, int padding); +int (*RSA_meth_get_mod_exp(const RSA_METHOD *meth))(BIGNUM *r0, const BIGNUM *i, + RSA *rsa, BN_CTX *ctx); +int (*RSA_meth_get_bn_mod_exp(const RSA_METHOD *meth))(BIGNUM *r, + const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); +int (*RSA_meth_get_init(const RSA_METHOD *meth))(RSA *rsa); +int (*RSA_meth_get_keygen(const RSA_METHOD *meth))(RSA *rsa, int bits, BIGNUM *e, + BN_GENCB *cb); +int RSA_meth_get_flags(const RSA_METHOD *meth); +void *RSA_meth_get0_app_data(const RSA_METHOD *meth); +int (*RSA_meth_get_sign(const RSA_METHOD *meth))(int type, + const unsigned char *m, unsigned int m_length, + unsigned char *sigret, unsigned int *siglen, + const RSA *rsa); +int RSA_meth_set_sign(RSA_METHOD *rsa, int (*sign)(int type, + const unsigned char *m, unsigned int m_length, unsigned char *sigret, + unsigned int *siglen, const RSA *rsa)); +int (*RSA_meth_get_verify(const RSA_METHOD *meth))(int dtype, + const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa); +int RSA_meth_set_verify(RSA_METHOD *rsa, int (*verify)(int dtype, + const unsigned char *m, unsigned int m_length, const unsigned char *sigbuf, + unsigned int siglen, const RSA *rsa)); + + +void ERR_load_RSA_strings(void); + +/* Error codes for the RSA functions. */ + +/* Function codes. */ +#define RSA_F_CHECK_PADDING_MD 140 +#define RSA_F_DO_RSA_PRINT 146 +#define RSA_F_INT_RSA_VERIFY 145 +#define RSA_F_MEMORY_LOCK 100 +#define RSA_F_OLD_RSA_PRIV_DECODE 147 +#define RSA_F_PKEY_RSA_CTRL 143 +#define RSA_F_PKEY_RSA_CTRL_STR 144 +#define RSA_F_PKEY_RSA_SIGN 142 +#define RSA_F_PKEY_RSA_VERIFY 154 +#define RSA_F_PKEY_RSA_VERIFYRECOVER 141 +#define RSA_F_RSA_BUILTIN_KEYGEN 129 +#define RSA_F_RSA_CHECK_KEY 123 +#define RSA_F_RSA_EAY_MOD_EXP 157 +#define RSA_F_RSA_EAY_PRIVATE_DECRYPT 101 +#define RSA_F_RSA_EAY_PRIVATE_ENCRYPT 102 +#define RSA_F_RSA_EAY_PUBLIC_DECRYPT 103 +#define RSA_F_RSA_EAY_PUBLIC_ENCRYPT 104 +#define RSA_F_RSA_GENERATE_KEY 105 +#define RSA_F_RSA_GENERATE_KEY_EX 155 +#define RSA_F_RSA_ITEM_VERIFY 156 +#define RSA_F_RSA_MEMORY_LOCK 130 +#define RSA_F_RSA_NEW_METHOD 106 +#define RSA_F_RSA_NULL 124 +#define RSA_F_RSA_NULL_MOD_EXP 131 +#define RSA_F_RSA_NULL_PRIVATE_DECRYPT 132 +#define RSA_F_RSA_NULL_PRIVATE_ENCRYPT 133 +#define RSA_F_RSA_NULL_PUBLIC_DECRYPT 134 +#define RSA_F_RSA_NULL_PUBLIC_ENCRYPT 135 +#define RSA_F_RSA_PADDING_ADD_NONE 107 +#define RSA_F_RSA_PADDING_ADD_PKCS1_OAEP 121 +#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS 125 +#define RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1 148 +#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1 108 +#define RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2 109 +#define RSA_F_RSA_PADDING_ADD_X931 127 +#define RSA_F_RSA_PADDING_CHECK_NONE 111 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP 122 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1 112 +#define RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2 113 +#define RSA_F_RSA_PADDING_CHECK_X931 128 +#define RSA_F_RSA_PRINT 115 +#define RSA_F_RSA_PRINT_FP 116 +#define RSA_F_RSA_PRIVATE_DECRYPT 150 +#define RSA_F_RSA_PRIVATE_ENCRYPT 151 +#define RSA_F_RSA_PRIV_DECODE 137 +#define RSA_F_RSA_PRIV_ENCODE 138 +#define RSA_F_RSA_PUBLIC_DECRYPT 152 +#define RSA_F_RSA_PUBLIC_ENCRYPT 153 +#define RSA_F_RSA_PUB_DECODE 139 +#define RSA_F_RSA_SETUP_BLINDING 136 +#define RSA_F_RSA_SIGN 117 +#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 +#define RSA_F_RSA_VERIFY 119 +#define RSA_F_RSA_VERIFY_ASN1_OCTET_STRING 120 +#define RSA_F_RSA_VERIFY_PKCS1_PSS 126 +#define RSA_F_RSA_VERIFY_PKCS1_PSS_MGF1 149 + +/* Reason codes. */ +#define RSA_R_ALGORITHM_MISMATCH 100 +#define RSA_R_BAD_E_VALUE 101 +#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102 +#define RSA_R_BAD_PAD_BYTE_COUNT 103 +#define RSA_R_BAD_SIGNATURE 104 +#define RSA_R_BLOCK_TYPE_IS_NOT_01 106 +#define RSA_R_BLOCK_TYPE_IS_NOT_02 107 +#define RSA_R_DATA_GREATER_THAN_MOD_LEN 108 +#define RSA_R_DATA_TOO_LARGE 109 +#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 110 +#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 132 +#define RSA_R_DATA_TOO_SMALL 111 +#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 122 +#define RSA_R_DIGEST_DOES_NOT_MATCH 158 +#define RSA_R_DIGEST_NOT_ALLOWED 145 +#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 112 +#define RSA_R_DMP1_NOT_CONGRUENT_TO_D 124 +#define RSA_R_DMQ1_NOT_CONGRUENT_TO_D 125 +#define RSA_R_D_E_NOT_CONGRUENT_TO_1 123 +#define RSA_R_FIRST_OCTET_INVALID 133 +#define RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 144 +#define RSA_R_INVALID_DIGEST 157 +#define RSA_R_INVALID_DIGEST_LENGTH 143 +#define RSA_R_INVALID_HEADER 137 +#define RSA_R_INVALID_KEYBITS 145 +#define RSA_R_INVALID_LABEL 160 +#define RSA_R_INVALID_MESSAGE_LENGTH 131 +#define RSA_R_INVALID_MGF1_MD 156 +#define RSA_R_INVALID_OAEP_PARAMETERS 161 +#define RSA_R_INVALID_PADDING 138 +#define RSA_R_INVALID_PADDING_MODE 141 +#define RSA_R_INVALID_PSS_PARAMETERS 149 +#define RSA_R_INVALID_PSS_SALTLEN 146 +#define RSA_R_INVALID_SALT_LENGTH 150 +#define RSA_R_INVALID_TRAILER 139 +#define RSA_R_INVALID_X931_DIGEST 142 +#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 +#define RSA_R_KEY_SIZE_TOO_SMALL 120 +#define RSA_R_LAST_OCTET_INVALID 134 +#define RSA_R_MODULUS_TOO_LARGE 105 +#define RSA_R_MGF1_DIGEST_NOT_ALLOWED 152 +#define RSA_R_NON_FIPS_RSA_METHOD 157 +#define RSA_R_NO_PUBLIC_EXPONENT 140 +#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 +#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 +#define RSA_R_OAEP_DECODING_ERROR 121 +#define RSA_R_OPERATION_NOT_ALLOWED_IN_FIPS_MODE 158 +#define RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 148 +#define RSA_R_PADDING_CHECK_FAILED 114 +#define RSA_R_PSS_SALTLEN_TOO_SMALL 164 +#define RSA_R_P_NOT_PRIME 128 +#define RSA_R_Q_NOT_PRIME 129 +#define RSA_R_RSA_OPERATIONS_NOT_SUPPORTED 130 +#define RSA_R_SLEN_CHECK_FAILED 136 +#define RSA_R_SLEN_RECOVERY_FAILED 135 +#define RSA_R_SSLV3_ROLLBACK_ATTACK 115 +#define RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 116 +#define RSA_R_UNKNOWN_ALGORITHM_TYPE 117 +#define RSA_R_UNKNOWN_DIGEST 166 +#define RSA_R_UNKNOWN_MASK_DIGEST 151 +#define RSA_R_UNKNOWN_PADDING_TYPE 118 +#define RSA_R_UNKNOWN_PSS_DIGEST 152 +#define RSA_R_UNSUPPORTED_ENCRYPTION_TYPE 162 +#define RSA_R_UNSUPPORTED_LABEL_SOURCE 163 +#define RSA_R_UNSUPPORTED_MASK_ALGORITHM 153 +#define RSA_R_UNSUPPORTED_MASK_PARAMETER 154 +#define RSA_R_UNSUPPORTED_SIGNATURE_TYPE 155 +#define RSA_R_VALUE_MISSING 147 +#define RSA_R_WRONG_SIGNATURE_LENGTH 119 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/safestack.h b/include/openssl/safestack.h new file mode 100644 index 0000000..4f575ba --- /dev/null +++ b/include/openssl/safestack.h @@ -0,0 +1,1971 @@ +/* $OpenBSD: safestack.h,v 1.29 2023/08/03 16:32:15 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_SAFESTACK_H +#define HEADER_SAFESTACK_H + +#include + +#ifndef CHECKED_PTR_OF +#define CHECKED_PTR_OF(type, p) \ + ((void*) (1 ? p : (type*)0)) +#endif + +/* In C++ we get problems because an explicit cast is needed from (void *) + * we use CHECKED_STACK_OF to ensure the correct type is passed in the macros + * below. + */ + +#define CHECKED_STACK_OF(type, p) \ + ((_STACK*) (1 ? p : (STACK_OF(type)*)0)) + +#define CHECKED_SK_FREE_FUNC(type, p) \ + ((void (*)(void *)) ((1 ? p : (void (*)(type *))0))) + +#define CHECKED_SK_FREE_FUNC2(type, p) \ + ((void (*)(void *)) ((1 ? p : (void (*)(type))0))) + +#define CHECKED_SK_CMP_FUNC(type, p) \ + ((int (*)(const void *, const void *)) \ + ((1 ? p : (int (*)(const type * const *, const type * const *))0))) + +#define STACK_OF(type) struct stack_st_##type +#define PREDECLARE_STACK_OF(type) STACK_OF(type); + +#define DECLARE_STACK_OF(type) \ +STACK_OF(type) \ + { \ + _STACK stack; \ + }; +#define DECLARE_SPECIAL_STACK_OF(type, type2) \ +STACK_OF(type) \ + { \ + _STACK stack; \ + }; + +#define IMPLEMENT_STACK_OF(type) /* nada (obsolete in new safestack approach)*/ + + +/* Strings are special: normally an lhash entry will point to a single + * (somewhat) mutable object. In the case of strings: + * + * a) Instead of a single char, there is an array of chars, NUL-terminated. + * b) The string may have be immutable. + * + * So, they need their own declarations. Especially important for + * type-checking tools, such as Deputy. + * +o * In practice, however, it appears to be hard to have a const + * string. For now, I'm settling for dealing with the fact it is a + * string at all. + */ +typedef char *OPENSSL_STRING; + +typedef const char *OPENSSL_CSTRING; + +/* Confusingly, LHASH_OF(STRING) deals with char ** throughout, but + * STACK_OF(STRING) is really more like STACK_OF(char), only, as + * mentioned above, instead of a single char each entry is a + * NUL-terminated array of chars. So, we have to implement STRING + * specially for STACK_OF. This is dealt with in the autogenerated + * macros below. + */ + +DECLARE_SPECIAL_STACK_OF(OPENSSL_STRING, char) + +/* SKM_sk_... stack macros are internal to safestack.h: + * never use them directly, use sk__... instead */ +#define SKM_sk_new(type, cmp) \ + ((STACK_OF(type) *)sk_new(CHECKED_SK_CMP_FUNC(type, cmp))) +#define SKM_sk_new_null(type) \ + ((STACK_OF(type) *)sk_new_null()) +#define SKM_sk_free(type, st) \ + sk_free(CHECKED_STACK_OF(type, st)) +#define SKM_sk_num(type, st) \ + sk_num(CHECKED_STACK_OF(type, st)) +#define SKM_sk_value(type, st,i) \ + ((type *)sk_value(CHECKED_STACK_OF(type, st), i)) +#define SKM_sk_set(type, st,i,val) \ + sk_set(CHECKED_STACK_OF(type, st), i, CHECKED_PTR_OF(type, val)) +#define SKM_sk_zero(type, st) \ + sk_zero(CHECKED_STACK_OF(type, st)) +#define SKM_sk_push(type, st, val) \ + sk_push(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +#define SKM_sk_unshift(type, st, val) \ + sk_unshift(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +#define SKM_sk_find(type, st, val) \ + sk_find(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val)) +#define SKM_sk_find_ex(type, st, val) \ + sk_find_ex(CHECKED_STACK_OF(type, st), \ + CHECKED_PTR_OF(type, val)) +#define SKM_sk_delete(type, st, i) \ + (type *)sk_delete(CHECKED_STACK_OF(type, st), i) +#define SKM_sk_delete_ptr(type, st, ptr) \ + (type *)sk_delete_ptr(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, ptr)) +#define SKM_sk_insert(type, st,val, i) \ + sk_insert(CHECKED_STACK_OF(type, st), CHECKED_PTR_OF(type, val), i) +#define SKM_sk_set_cmp_func(type, st, cmp) \ + ((int (*)(const type * const *,const type * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(type, st), CHECKED_SK_CMP_FUNC(type, cmp))) +#define SKM_sk_dup(type, st) \ + (STACK_OF(type) *)sk_dup(CHECKED_STACK_OF(type, st)) +#define SKM_sk_pop_free(type, st, free_func) \ + sk_pop_free(CHECKED_STACK_OF(type, st), CHECKED_SK_FREE_FUNC(type, free_func)) +#define SKM_sk_shift(type, st) \ + (type *)sk_shift(CHECKED_STACK_OF(type, st)) +#define SKM_sk_pop(type, st) \ + (type *)sk_pop(CHECKED_STACK_OF(type, st)) +#define SKM_sk_sort(type, st) \ + sk_sort(CHECKED_STACK_OF(type, st)) +#define SKM_sk_is_sorted(type, st) \ + sk_is_sorted(CHECKED_STACK_OF(type, st)) + +#define sk_ACCESS_DESCRIPTION_new(cmp) SKM_sk_new(ACCESS_DESCRIPTION, (cmp)) +#define sk_ACCESS_DESCRIPTION_new_null() SKM_sk_new_null(ACCESS_DESCRIPTION) +#define sk_ACCESS_DESCRIPTION_free(st) SKM_sk_free(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_num(st) SKM_sk_num(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_value(st, i) SKM_sk_value(ACCESS_DESCRIPTION, (st), (i)) +#define sk_ACCESS_DESCRIPTION_set(st, i, val) SKM_sk_set(ACCESS_DESCRIPTION, (st), (i), (val)) +#define sk_ACCESS_DESCRIPTION_zero(st) SKM_sk_zero(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_push(st, val) SKM_sk_push(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_unshift(st, val) SKM_sk_unshift(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_find(st, val) SKM_sk_find(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_find_ex(st, val) SKM_sk_find_ex(ACCESS_DESCRIPTION, (st), (val)) +#define sk_ACCESS_DESCRIPTION_delete(st, i) SKM_sk_delete(ACCESS_DESCRIPTION, (st), (i)) +#define sk_ACCESS_DESCRIPTION_delete_ptr(st, ptr) SKM_sk_delete_ptr(ACCESS_DESCRIPTION, (st), (ptr)) +#define sk_ACCESS_DESCRIPTION_insert(st, val, i) SKM_sk_insert(ACCESS_DESCRIPTION, (st), (val), (i)) +#define sk_ACCESS_DESCRIPTION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ACCESS_DESCRIPTION, (st), (cmp)) +#define sk_ACCESS_DESCRIPTION_dup(st) SKM_sk_dup(ACCESS_DESCRIPTION, st) +#define sk_ACCESS_DESCRIPTION_pop_free(st, free_func) SKM_sk_pop_free(ACCESS_DESCRIPTION, (st), (free_func)) +#define sk_ACCESS_DESCRIPTION_shift(st) SKM_sk_shift(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_pop(st) SKM_sk_pop(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_sort(st) SKM_sk_sort(ACCESS_DESCRIPTION, (st)) +#define sk_ACCESS_DESCRIPTION_is_sorted(st) SKM_sk_is_sorted(ACCESS_DESCRIPTION, (st)) + +#define sk_ASIdOrRange_new(cmp) SKM_sk_new(ASIdOrRange, (cmp)) +#define sk_ASIdOrRange_new_null() SKM_sk_new_null(ASIdOrRange) +#define sk_ASIdOrRange_free(st) SKM_sk_free(ASIdOrRange, (st)) +#define sk_ASIdOrRange_num(st) SKM_sk_num(ASIdOrRange, (st)) +#define sk_ASIdOrRange_value(st, i) SKM_sk_value(ASIdOrRange, (st), (i)) +#define sk_ASIdOrRange_set(st, i, val) SKM_sk_set(ASIdOrRange, (st), (i), (val)) +#define sk_ASIdOrRange_zero(st) SKM_sk_zero(ASIdOrRange, (st)) +#define sk_ASIdOrRange_push(st, val) SKM_sk_push(ASIdOrRange, (st), (val)) +#define sk_ASIdOrRange_unshift(st, val) SKM_sk_unshift(ASIdOrRange, (st), (val)) +#define sk_ASIdOrRange_find(st, val) SKM_sk_find(ASIdOrRange, (st), (val)) +#define sk_ASIdOrRange_find_ex(st, val) SKM_sk_find_ex(ASIdOrRange, (st), (val)) +#define sk_ASIdOrRange_delete(st, i) SKM_sk_delete(ASIdOrRange, (st), (i)) +#define sk_ASIdOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASIdOrRange, (st), (ptr)) +#define sk_ASIdOrRange_insert(st, val, i) SKM_sk_insert(ASIdOrRange, (st), (val), (i)) +#define sk_ASIdOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASIdOrRange, (st), (cmp)) +#define sk_ASIdOrRange_dup(st) SKM_sk_dup(ASIdOrRange, st) +#define sk_ASIdOrRange_pop_free(st, free_func) SKM_sk_pop_free(ASIdOrRange, (st), (free_func)) +#define sk_ASIdOrRange_shift(st) SKM_sk_shift(ASIdOrRange, (st)) +#define sk_ASIdOrRange_pop(st) SKM_sk_pop(ASIdOrRange, (st)) +#define sk_ASIdOrRange_sort(st) SKM_sk_sort(ASIdOrRange, (st)) +#define sk_ASIdOrRange_is_sorted(st) SKM_sk_is_sorted(ASIdOrRange, (st)) + +#define sk_ASN1_GENERALSTRING_new(cmp) SKM_sk_new(ASN1_GENERALSTRING, (cmp)) +#define sk_ASN1_GENERALSTRING_new_null() SKM_sk_new_null(ASN1_GENERALSTRING) +#define sk_ASN1_GENERALSTRING_free(st) SKM_sk_free(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_num(st) SKM_sk_num(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_value(st, i) SKM_sk_value(ASN1_GENERALSTRING, (st), (i)) +#define sk_ASN1_GENERALSTRING_set(st, i, val) SKM_sk_set(ASN1_GENERALSTRING, (st), (i), (val)) +#define sk_ASN1_GENERALSTRING_zero(st) SKM_sk_zero(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_push(st, val) SKM_sk_push(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_unshift(st, val) SKM_sk_unshift(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_find(st, val) SKM_sk_find(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_find_ex(st, val) SKM_sk_find_ex(ASN1_GENERALSTRING, (st), (val)) +#define sk_ASN1_GENERALSTRING_delete(st, i) SKM_sk_delete(ASN1_GENERALSTRING, (st), (i)) +#define sk_ASN1_GENERALSTRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_GENERALSTRING, (st), (ptr)) +#define sk_ASN1_GENERALSTRING_insert(st, val, i) SKM_sk_insert(ASN1_GENERALSTRING, (st), (val), (i)) +#define sk_ASN1_GENERALSTRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_GENERALSTRING, (st), (cmp)) +#define sk_ASN1_GENERALSTRING_dup(st) SKM_sk_dup(ASN1_GENERALSTRING, st) +#define sk_ASN1_GENERALSTRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_GENERALSTRING, (st), (free_func)) +#define sk_ASN1_GENERALSTRING_shift(st) SKM_sk_shift(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_pop(st) SKM_sk_pop(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_sort(st) SKM_sk_sort(ASN1_GENERALSTRING, (st)) +#define sk_ASN1_GENERALSTRING_is_sorted(st) SKM_sk_is_sorted(ASN1_GENERALSTRING, (st)) + +#define sk_ASN1_INTEGER_new(cmp) SKM_sk_new(ASN1_INTEGER, (cmp)) +#define sk_ASN1_INTEGER_new_null() SKM_sk_new_null(ASN1_INTEGER) +#define sk_ASN1_INTEGER_free(st) SKM_sk_free(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_num(st) SKM_sk_num(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_value(st, i) SKM_sk_value(ASN1_INTEGER, (st), (i)) +#define sk_ASN1_INTEGER_set(st, i, val) SKM_sk_set(ASN1_INTEGER, (st), (i), (val)) +#define sk_ASN1_INTEGER_zero(st) SKM_sk_zero(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_push(st, val) SKM_sk_push(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_unshift(st, val) SKM_sk_unshift(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_find(st, val) SKM_sk_find(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_find_ex(st, val) SKM_sk_find_ex(ASN1_INTEGER, (st), (val)) +#define sk_ASN1_INTEGER_delete(st, i) SKM_sk_delete(ASN1_INTEGER, (st), (i)) +#define sk_ASN1_INTEGER_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_INTEGER, (st), (ptr)) +#define sk_ASN1_INTEGER_insert(st, val, i) SKM_sk_insert(ASN1_INTEGER, (st), (val), (i)) +#define sk_ASN1_INTEGER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_INTEGER, (st), (cmp)) +#define sk_ASN1_INTEGER_dup(st) SKM_sk_dup(ASN1_INTEGER, st) +#define sk_ASN1_INTEGER_pop_free(st, free_func) SKM_sk_pop_free(ASN1_INTEGER, (st), (free_func)) +#define sk_ASN1_INTEGER_shift(st) SKM_sk_shift(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_pop(st) SKM_sk_pop(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_sort(st) SKM_sk_sort(ASN1_INTEGER, (st)) +#define sk_ASN1_INTEGER_is_sorted(st) SKM_sk_is_sorted(ASN1_INTEGER, (st)) + +#define sk_ASN1_OBJECT_new(cmp) SKM_sk_new(ASN1_OBJECT, (cmp)) +#define sk_ASN1_OBJECT_new_null() SKM_sk_new_null(ASN1_OBJECT) +#define sk_ASN1_OBJECT_free(st) SKM_sk_free(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_num(st) SKM_sk_num(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_value(st, i) SKM_sk_value(ASN1_OBJECT, (st), (i)) +#define sk_ASN1_OBJECT_set(st, i, val) SKM_sk_set(ASN1_OBJECT, (st), (i), (val)) +#define sk_ASN1_OBJECT_zero(st) SKM_sk_zero(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_push(st, val) SKM_sk_push(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_unshift(st, val) SKM_sk_unshift(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_find(st, val) SKM_sk_find(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_find_ex(st, val) SKM_sk_find_ex(ASN1_OBJECT, (st), (val)) +#define sk_ASN1_OBJECT_delete(st, i) SKM_sk_delete(ASN1_OBJECT, (st), (i)) +#define sk_ASN1_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_OBJECT, (st), (ptr)) +#define sk_ASN1_OBJECT_insert(st, val, i) SKM_sk_insert(ASN1_OBJECT, (st), (val), (i)) +#define sk_ASN1_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_OBJECT, (st), (cmp)) +#define sk_ASN1_OBJECT_dup(st) SKM_sk_dup(ASN1_OBJECT, st) +#define sk_ASN1_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(ASN1_OBJECT, (st), (free_func)) +#define sk_ASN1_OBJECT_shift(st) SKM_sk_shift(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_pop(st) SKM_sk_pop(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_sort(st) SKM_sk_sort(ASN1_OBJECT, (st)) +#define sk_ASN1_OBJECT_is_sorted(st) SKM_sk_is_sorted(ASN1_OBJECT, (st)) + +#define sk_ASN1_STRING_TABLE_new(cmp) SKM_sk_new(ASN1_STRING_TABLE, (cmp)) +#define sk_ASN1_STRING_TABLE_new_null() SKM_sk_new_null(ASN1_STRING_TABLE) +#define sk_ASN1_STRING_TABLE_free(st) SKM_sk_free(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_num(st) SKM_sk_num(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_value(st, i) SKM_sk_value(ASN1_STRING_TABLE, (st), (i)) +#define sk_ASN1_STRING_TABLE_set(st, i, val) SKM_sk_set(ASN1_STRING_TABLE, (st), (i), (val)) +#define sk_ASN1_STRING_TABLE_zero(st) SKM_sk_zero(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_push(st, val) SKM_sk_push(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_unshift(st, val) SKM_sk_unshift(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_find(st, val) SKM_sk_find(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_find_ex(st, val) SKM_sk_find_ex(ASN1_STRING_TABLE, (st), (val)) +#define sk_ASN1_STRING_TABLE_delete(st, i) SKM_sk_delete(ASN1_STRING_TABLE, (st), (i)) +#define sk_ASN1_STRING_TABLE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_STRING_TABLE, (st), (ptr)) +#define sk_ASN1_STRING_TABLE_insert(st, val, i) SKM_sk_insert(ASN1_STRING_TABLE, (st), (val), (i)) +#define sk_ASN1_STRING_TABLE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_STRING_TABLE, (st), (cmp)) +#define sk_ASN1_STRING_TABLE_dup(st) SKM_sk_dup(ASN1_STRING_TABLE, st) +#define sk_ASN1_STRING_TABLE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_STRING_TABLE, (st), (free_func)) +#define sk_ASN1_STRING_TABLE_shift(st) SKM_sk_shift(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_pop(st) SKM_sk_pop(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_sort(st) SKM_sk_sort(ASN1_STRING_TABLE, (st)) +#define sk_ASN1_STRING_TABLE_is_sorted(st) SKM_sk_is_sorted(ASN1_STRING_TABLE, (st)) + +#define sk_ASN1_TYPE_new(cmp) SKM_sk_new(ASN1_TYPE, (cmp)) +#define sk_ASN1_TYPE_new_null() SKM_sk_new_null(ASN1_TYPE) +#define sk_ASN1_TYPE_free(st) SKM_sk_free(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_num(st) SKM_sk_num(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_value(st, i) SKM_sk_value(ASN1_TYPE, (st), (i)) +#define sk_ASN1_TYPE_set(st, i, val) SKM_sk_set(ASN1_TYPE, (st), (i), (val)) +#define sk_ASN1_TYPE_zero(st) SKM_sk_zero(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_push(st, val) SKM_sk_push(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_unshift(st, val) SKM_sk_unshift(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_find(st, val) SKM_sk_find(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_find_ex(st, val) SKM_sk_find_ex(ASN1_TYPE, (st), (val)) +#define sk_ASN1_TYPE_delete(st, i) SKM_sk_delete(ASN1_TYPE, (st), (i)) +#define sk_ASN1_TYPE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_TYPE, (st), (ptr)) +#define sk_ASN1_TYPE_insert(st, val, i) SKM_sk_insert(ASN1_TYPE, (st), (val), (i)) +#define sk_ASN1_TYPE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_TYPE, (st), (cmp)) +#define sk_ASN1_TYPE_dup(st) SKM_sk_dup(ASN1_TYPE, st) +#define sk_ASN1_TYPE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_TYPE, (st), (free_func)) +#define sk_ASN1_TYPE_shift(st) SKM_sk_shift(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_pop(st) SKM_sk_pop(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_sort(st) SKM_sk_sort(ASN1_TYPE, (st)) +#define sk_ASN1_TYPE_is_sorted(st) SKM_sk_is_sorted(ASN1_TYPE, (st)) + +#define sk_ASN1_UTF8STRING_new(cmp) SKM_sk_new(ASN1_UTF8STRING, (cmp)) +#define sk_ASN1_UTF8STRING_new_null() SKM_sk_new_null(ASN1_UTF8STRING) +#define sk_ASN1_UTF8STRING_free(st) SKM_sk_free(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_num(st) SKM_sk_num(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_value(st, i) SKM_sk_value(ASN1_UTF8STRING, (st), (i)) +#define sk_ASN1_UTF8STRING_set(st, i, val) SKM_sk_set(ASN1_UTF8STRING, (st), (i), (val)) +#define sk_ASN1_UTF8STRING_zero(st) SKM_sk_zero(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_push(st, val) SKM_sk_push(ASN1_UTF8STRING, (st), (val)) +#define sk_ASN1_UTF8STRING_unshift(st, val) SKM_sk_unshift(ASN1_UTF8STRING, (st), (val)) +#define sk_ASN1_UTF8STRING_find(st, val) SKM_sk_find(ASN1_UTF8STRING, (st), (val)) +#define sk_ASN1_UTF8STRING_find_ex(st, val) SKM_sk_find_ex(ASN1_UTF8STRING, (st), (val)) +#define sk_ASN1_UTF8STRING_delete(st, i) SKM_sk_delete(ASN1_UTF8STRING, (st), (i)) +#define sk_ASN1_UTF8STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_UTF8STRING, (st), (ptr)) +#define sk_ASN1_UTF8STRING_insert(st, val, i) SKM_sk_insert(ASN1_UTF8STRING, (st), (val), (i)) +#define sk_ASN1_UTF8STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_UTF8STRING, (st), (cmp)) +#define sk_ASN1_UTF8STRING_dup(st) SKM_sk_dup(ASN1_UTF8STRING, st) +#define sk_ASN1_UTF8STRING_pop_free(st, free_func) SKM_sk_pop_free(ASN1_UTF8STRING, (st), (free_func)) +#define sk_ASN1_UTF8STRING_shift(st) SKM_sk_shift(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_pop(st) SKM_sk_pop(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_sort(st) SKM_sk_sort(ASN1_UTF8STRING, (st)) +#define sk_ASN1_UTF8STRING_is_sorted(st) SKM_sk_is_sorted(ASN1_UTF8STRING, (st)) + +#define sk_ASN1_VALUE_new(cmp) SKM_sk_new(ASN1_VALUE, (cmp)) +#define sk_ASN1_VALUE_new_null() SKM_sk_new_null(ASN1_VALUE) +#define sk_ASN1_VALUE_free(st) SKM_sk_free(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_num(st) SKM_sk_num(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_value(st, i) SKM_sk_value(ASN1_VALUE, (st), (i)) +#define sk_ASN1_VALUE_set(st, i, val) SKM_sk_set(ASN1_VALUE, (st), (i), (val)) +#define sk_ASN1_VALUE_zero(st) SKM_sk_zero(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_push(st, val) SKM_sk_push(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_unshift(st, val) SKM_sk_unshift(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_find(st, val) SKM_sk_find(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_find_ex(st, val) SKM_sk_find_ex(ASN1_VALUE, (st), (val)) +#define sk_ASN1_VALUE_delete(st, i) SKM_sk_delete(ASN1_VALUE, (st), (i)) +#define sk_ASN1_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASN1_VALUE, (st), (ptr)) +#define sk_ASN1_VALUE_insert(st, val, i) SKM_sk_insert(ASN1_VALUE, (st), (val), (i)) +#define sk_ASN1_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASN1_VALUE, (st), (cmp)) +#define sk_ASN1_VALUE_dup(st) SKM_sk_dup(ASN1_VALUE, st) +#define sk_ASN1_VALUE_pop_free(st, free_func) SKM_sk_pop_free(ASN1_VALUE, (st), (free_func)) +#define sk_ASN1_VALUE_shift(st) SKM_sk_shift(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_pop(st) SKM_sk_pop(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st)) +#define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st)) + +#define sk_BIO_new(cmp) SKM_sk_new(BIO, (cmp)) +#define sk_BIO_new_null() SKM_sk_new_null(BIO) +#define sk_BIO_free(st) SKM_sk_free(BIO, (st)) +#define sk_BIO_num(st) SKM_sk_num(BIO, (st)) +#define sk_BIO_value(st, i) SKM_sk_value(BIO, (st), (i)) +#define sk_BIO_set(st, i, val) SKM_sk_set(BIO, (st), (i), (val)) +#define sk_BIO_zero(st) SKM_sk_zero(BIO, (st)) +#define sk_BIO_push(st, val) SKM_sk_push(BIO, (st), (val)) +#define sk_BIO_unshift(st, val) SKM_sk_unshift(BIO, (st), (val)) +#define sk_BIO_find(st, val) SKM_sk_find(BIO, (st), (val)) +#define sk_BIO_find_ex(st, val) SKM_sk_find_ex(BIO, (st), (val)) +#define sk_BIO_delete(st, i) SKM_sk_delete(BIO, (st), (i)) +#define sk_BIO_delete_ptr(st, ptr) SKM_sk_delete_ptr(BIO, (st), (ptr)) +#define sk_BIO_insert(st, val, i) SKM_sk_insert(BIO, (st), (val), (i)) +#define sk_BIO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BIO, (st), (cmp)) +#define sk_BIO_dup(st) SKM_sk_dup(BIO, st) +#define sk_BIO_pop_free(st, free_func) SKM_sk_pop_free(BIO, (st), (free_func)) +#define sk_BIO_shift(st) SKM_sk_shift(BIO, (st)) +#define sk_BIO_pop(st) SKM_sk_pop(BIO, (st)) +#define sk_BIO_sort(st) SKM_sk_sort(BIO, (st)) +#define sk_BIO_is_sorted(st) SKM_sk_is_sorted(BIO, (st)) + +#define sk_BY_DIR_ENTRY_new(cmp) SKM_sk_new(BY_DIR_ENTRY, (cmp)) +#define sk_BY_DIR_ENTRY_new_null() SKM_sk_new_null(BY_DIR_ENTRY) +#define sk_BY_DIR_ENTRY_free(st) SKM_sk_free(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_num(st) SKM_sk_num(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_value(st, i) SKM_sk_value(BY_DIR_ENTRY, (st), (i)) +#define sk_BY_DIR_ENTRY_set(st, i, val) SKM_sk_set(BY_DIR_ENTRY, (st), (i), (val)) +#define sk_BY_DIR_ENTRY_zero(st) SKM_sk_zero(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_push(st, val) SKM_sk_push(BY_DIR_ENTRY, (st), (val)) +#define sk_BY_DIR_ENTRY_unshift(st, val) SKM_sk_unshift(BY_DIR_ENTRY, (st), (val)) +#define sk_BY_DIR_ENTRY_find(st, val) SKM_sk_find(BY_DIR_ENTRY, (st), (val)) +#define sk_BY_DIR_ENTRY_find_ex(st, val) SKM_sk_find_ex(BY_DIR_ENTRY, (st), (val)) +#define sk_BY_DIR_ENTRY_delete(st, i) SKM_sk_delete(BY_DIR_ENTRY, (st), (i)) +#define sk_BY_DIR_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(BY_DIR_ENTRY, (st), (ptr)) +#define sk_BY_DIR_ENTRY_insert(st, val, i) SKM_sk_insert(BY_DIR_ENTRY, (st), (val), (i)) +#define sk_BY_DIR_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BY_DIR_ENTRY, (st), (cmp)) +#define sk_BY_DIR_ENTRY_dup(st) SKM_sk_dup(BY_DIR_ENTRY, st) +#define sk_BY_DIR_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(BY_DIR_ENTRY, (st), (free_func)) +#define sk_BY_DIR_ENTRY_shift(st) SKM_sk_shift(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_pop(st) SKM_sk_pop(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_sort(st) SKM_sk_sort(BY_DIR_ENTRY, (st)) +#define sk_BY_DIR_ENTRY_is_sorted(st) SKM_sk_is_sorted(BY_DIR_ENTRY, (st)) + +#define sk_BY_DIR_HASH_new(cmp) SKM_sk_new(BY_DIR_HASH, (cmp)) +#define sk_BY_DIR_HASH_new_null() SKM_sk_new_null(BY_DIR_HASH) +#define sk_BY_DIR_HASH_free(st) SKM_sk_free(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_num(st) SKM_sk_num(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_value(st, i) SKM_sk_value(BY_DIR_HASH, (st), (i)) +#define sk_BY_DIR_HASH_set(st, i, val) SKM_sk_set(BY_DIR_HASH, (st), (i), (val)) +#define sk_BY_DIR_HASH_zero(st) SKM_sk_zero(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_push(st, val) SKM_sk_push(BY_DIR_HASH, (st), (val)) +#define sk_BY_DIR_HASH_unshift(st, val) SKM_sk_unshift(BY_DIR_HASH, (st), (val)) +#define sk_BY_DIR_HASH_find(st, val) SKM_sk_find(BY_DIR_HASH, (st), (val)) +#define sk_BY_DIR_HASH_find_ex(st, val) SKM_sk_find_ex(BY_DIR_HASH, (st), (val)) +#define sk_BY_DIR_HASH_delete(st, i) SKM_sk_delete(BY_DIR_HASH, (st), (i)) +#define sk_BY_DIR_HASH_delete_ptr(st, ptr) SKM_sk_delete_ptr(BY_DIR_HASH, (st), (ptr)) +#define sk_BY_DIR_HASH_insert(st, val, i) SKM_sk_insert(BY_DIR_HASH, (st), (val), (i)) +#define sk_BY_DIR_HASH_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(BY_DIR_HASH, (st), (cmp)) +#define sk_BY_DIR_HASH_dup(st) SKM_sk_dup(BY_DIR_HASH, st) +#define sk_BY_DIR_HASH_pop_free(st, free_func) SKM_sk_pop_free(BY_DIR_HASH, (st), (free_func)) +#define sk_BY_DIR_HASH_shift(st) SKM_sk_shift(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_pop(st) SKM_sk_pop(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_sort(st) SKM_sk_sort(BY_DIR_HASH, (st)) +#define sk_BY_DIR_HASH_is_sorted(st) SKM_sk_is_sorted(BY_DIR_HASH, (st)) + +#define sk_CMS_CertificateChoices_new(cmp) SKM_sk_new(CMS_CertificateChoices, (cmp)) +#define sk_CMS_CertificateChoices_new_null() SKM_sk_new_null(CMS_CertificateChoices) +#define sk_CMS_CertificateChoices_free(st) SKM_sk_free(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_num(st) SKM_sk_num(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_value(st, i) SKM_sk_value(CMS_CertificateChoices, (st), (i)) +#define sk_CMS_CertificateChoices_set(st, i, val) SKM_sk_set(CMS_CertificateChoices, (st), (i), (val)) +#define sk_CMS_CertificateChoices_zero(st) SKM_sk_zero(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_push(st, val) SKM_sk_push(CMS_CertificateChoices, (st), (val)) +#define sk_CMS_CertificateChoices_unshift(st, val) SKM_sk_unshift(CMS_CertificateChoices, (st), (val)) +#define sk_CMS_CertificateChoices_find(st, val) SKM_sk_find(CMS_CertificateChoices, (st), (val)) +#define sk_CMS_CertificateChoices_find_ex(st, val) SKM_sk_find_ex(CMS_CertificateChoices, (st), (val)) +#define sk_CMS_CertificateChoices_delete(st, i) SKM_sk_delete(CMS_CertificateChoices, (st), (i)) +#define sk_CMS_CertificateChoices_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_CertificateChoices, (st), (ptr)) +#define sk_CMS_CertificateChoices_insert(st, val, i) SKM_sk_insert(CMS_CertificateChoices, (st), (val), (i)) +#define sk_CMS_CertificateChoices_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_CertificateChoices, (st), (cmp)) +#define sk_CMS_CertificateChoices_dup(st) SKM_sk_dup(CMS_CertificateChoices, st) +#define sk_CMS_CertificateChoices_pop_free(st, free_func) SKM_sk_pop_free(CMS_CertificateChoices, (st), (free_func)) +#define sk_CMS_CertificateChoices_shift(st) SKM_sk_shift(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_pop(st) SKM_sk_pop(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_sort(st) SKM_sk_sort(CMS_CertificateChoices, (st)) +#define sk_CMS_CertificateChoices_is_sorted(st) SKM_sk_is_sorted(CMS_CertificateChoices, (st)) + +#define sk_CMS_RecipientEncryptedKey_new(cmp) SKM_sk_new(CMS_RecipientEncryptedKey, (cmp)) +#define sk_CMS_RecipientEncryptedKey_new_null() SKM_sk_new_null(CMS_RecipientEncryptedKey) +#define sk_CMS_RecipientEncryptedKey_free(st) SKM_sk_free(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_num(st) SKM_sk_num(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_value(st, i) SKM_sk_value(CMS_RecipientEncryptedKey, (st), (i)) +#define sk_CMS_RecipientEncryptedKey_set(st, i, val) SKM_sk_set(CMS_RecipientEncryptedKey, (st), (i), (val)) +#define sk_CMS_RecipientEncryptedKey_zero(st) SKM_sk_zero(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_push(st, val) SKM_sk_push(CMS_RecipientEncryptedKey, (st), (val)) +#define sk_CMS_RecipientEncryptedKey_unshift(st, val) SKM_sk_unshift(CMS_RecipientEncryptedKey, (st), (val)) +#define sk_CMS_RecipientEncryptedKey_find(st, val) SKM_sk_find(CMS_RecipientEncryptedKey, (st), (val)) +#define sk_CMS_RecipientEncryptedKey_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientEncryptedKey, (st), (val)) +#define sk_CMS_RecipientEncryptedKey_delete(st, i) SKM_sk_delete(CMS_RecipientEncryptedKey, (st), (i)) +#define sk_CMS_RecipientEncryptedKey_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientEncryptedKey, (st), (ptr)) +#define sk_CMS_RecipientEncryptedKey_insert(st, val, i) SKM_sk_insert(CMS_RecipientEncryptedKey, (st), (val), (i)) +#define sk_CMS_RecipientEncryptedKey_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientEncryptedKey, (st), (cmp)) +#define sk_CMS_RecipientEncryptedKey_dup(st) SKM_sk_dup(CMS_RecipientEncryptedKey, st) +#define sk_CMS_RecipientEncryptedKey_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientEncryptedKey, (st), (free_func)) +#define sk_CMS_RecipientEncryptedKey_shift(st) SKM_sk_shift(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_pop(st) SKM_sk_pop(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_sort(st) SKM_sk_sort(CMS_RecipientEncryptedKey, (st)) +#define sk_CMS_RecipientEncryptedKey_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientEncryptedKey, (st)) + +#define sk_CMS_RecipientInfo_new(cmp) SKM_sk_new(CMS_RecipientInfo, (cmp)) +#define sk_CMS_RecipientInfo_new_null() SKM_sk_new_null(CMS_RecipientInfo) +#define sk_CMS_RecipientInfo_free(st) SKM_sk_free(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_num(st) SKM_sk_num(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_value(st, i) SKM_sk_value(CMS_RecipientInfo, (st), (i)) +#define sk_CMS_RecipientInfo_set(st, i, val) SKM_sk_set(CMS_RecipientInfo, (st), (i), (val)) +#define sk_CMS_RecipientInfo_zero(st) SKM_sk_zero(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_push(st, val) SKM_sk_push(CMS_RecipientInfo, (st), (val)) +#define sk_CMS_RecipientInfo_unshift(st, val) SKM_sk_unshift(CMS_RecipientInfo, (st), (val)) +#define sk_CMS_RecipientInfo_find(st, val) SKM_sk_find(CMS_RecipientInfo, (st), (val)) +#define sk_CMS_RecipientInfo_find_ex(st, val) SKM_sk_find_ex(CMS_RecipientInfo, (st), (val)) +#define sk_CMS_RecipientInfo_delete(st, i) SKM_sk_delete(CMS_RecipientInfo, (st), (i)) +#define sk_CMS_RecipientInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RecipientInfo, (st), (ptr)) +#define sk_CMS_RecipientInfo_insert(st, val, i) SKM_sk_insert(CMS_RecipientInfo, (st), (val), (i)) +#define sk_CMS_RecipientInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RecipientInfo, (st), (cmp)) +#define sk_CMS_RecipientInfo_dup(st) SKM_sk_dup(CMS_RecipientInfo, st) +#define sk_CMS_RecipientInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_RecipientInfo, (st), (free_func)) +#define sk_CMS_RecipientInfo_shift(st) SKM_sk_shift(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_pop(st) SKM_sk_pop(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_sort(st) SKM_sk_sort(CMS_RecipientInfo, (st)) +#define sk_CMS_RecipientInfo_is_sorted(st) SKM_sk_is_sorted(CMS_RecipientInfo, (st)) + +#define sk_CMS_RevocationInfoChoice_new(cmp) SKM_sk_new(CMS_RevocationInfoChoice, (cmp)) +#define sk_CMS_RevocationInfoChoice_new_null() SKM_sk_new_null(CMS_RevocationInfoChoice) +#define sk_CMS_RevocationInfoChoice_free(st) SKM_sk_free(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_num(st) SKM_sk_num(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_value(st, i) SKM_sk_value(CMS_RevocationInfoChoice, (st), (i)) +#define sk_CMS_RevocationInfoChoice_set(st, i, val) SKM_sk_set(CMS_RevocationInfoChoice, (st), (i), (val)) +#define sk_CMS_RevocationInfoChoice_zero(st) SKM_sk_zero(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_push(st, val) SKM_sk_push(CMS_RevocationInfoChoice, (st), (val)) +#define sk_CMS_RevocationInfoChoice_unshift(st, val) SKM_sk_unshift(CMS_RevocationInfoChoice, (st), (val)) +#define sk_CMS_RevocationInfoChoice_find(st, val) SKM_sk_find(CMS_RevocationInfoChoice, (st), (val)) +#define sk_CMS_RevocationInfoChoice_find_ex(st, val) SKM_sk_find_ex(CMS_RevocationInfoChoice, (st), (val)) +#define sk_CMS_RevocationInfoChoice_delete(st, i) SKM_sk_delete(CMS_RevocationInfoChoice, (st), (i)) +#define sk_CMS_RevocationInfoChoice_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_RevocationInfoChoice, (st), (ptr)) +#define sk_CMS_RevocationInfoChoice_insert(st, val, i) SKM_sk_insert(CMS_RevocationInfoChoice, (st), (val), (i)) +#define sk_CMS_RevocationInfoChoice_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_RevocationInfoChoice, (st), (cmp)) +#define sk_CMS_RevocationInfoChoice_dup(st) SKM_sk_dup(CMS_RevocationInfoChoice, st) +#define sk_CMS_RevocationInfoChoice_pop_free(st, free_func) SKM_sk_pop_free(CMS_RevocationInfoChoice, (st), (free_func)) +#define sk_CMS_RevocationInfoChoice_shift(st) SKM_sk_shift(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_pop(st) SKM_sk_pop(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_sort(st) SKM_sk_sort(CMS_RevocationInfoChoice, (st)) +#define sk_CMS_RevocationInfoChoice_is_sorted(st) SKM_sk_is_sorted(CMS_RevocationInfoChoice, (st)) + +#define sk_CMS_SignerInfo_new(cmp) SKM_sk_new(CMS_SignerInfo, (cmp)) +#define sk_CMS_SignerInfo_new_null() SKM_sk_new_null(CMS_SignerInfo) +#define sk_CMS_SignerInfo_free(st) SKM_sk_free(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_num(st) SKM_sk_num(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_value(st, i) SKM_sk_value(CMS_SignerInfo, (st), (i)) +#define sk_CMS_SignerInfo_set(st, i, val) SKM_sk_set(CMS_SignerInfo, (st), (i), (val)) +#define sk_CMS_SignerInfo_zero(st) SKM_sk_zero(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_push(st, val) SKM_sk_push(CMS_SignerInfo, (st), (val)) +#define sk_CMS_SignerInfo_unshift(st, val) SKM_sk_unshift(CMS_SignerInfo, (st), (val)) +#define sk_CMS_SignerInfo_find(st, val) SKM_sk_find(CMS_SignerInfo, (st), (val)) +#define sk_CMS_SignerInfo_find_ex(st, val) SKM_sk_find_ex(CMS_SignerInfo, (st), (val)) +#define sk_CMS_SignerInfo_delete(st, i) SKM_sk_delete(CMS_SignerInfo, (st), (i)) +#define sk_CMS_SignerInfo_delete_ptr(st, ptr) SKM_sk_delete_ptr(CMS_SignerInfo, (st), (ptr)) +#define sk_CMS_SignerInfo_insert(st, val, i) SKM_sk_insert(CMS_SignerInfo, (st), (val), (i)) +#define sk_CMS_SignerInfo_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CMS_SignerInfo, (st), (cmp)) +#define sk_CMS_SignerInfo_dup(st) SKM_sk_dup(CMS_SignerInfo, st) +#define sk_CMS_SignerInfo_pop_free(st, free_func) SKM_sk_pop_free(CMS_SignerInfo, (st), (free_func)) +#define sk_CMS_SignerInfo_shift(st) SKM_sk_shift(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_pop(st) SKM_sk_pop(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_sort(st) SKM_sk_sort(CMS_SignerInfo, (st)) +#define sk_CMS_SignerInfo_is_sorted(st) SKM_sk_is_sorted(CMS_SignerInfo, (st)) + +#define sk_CONF_IMODULE_new(cmp) SKM_sk_new(CONF_IMODULE, (cmp)) +#define sk_CONF_IMODULE_new_null() SKM_sk_new_null(CONF_IMODULE) +#define sk_CONF_IMODULE_free(st) SKM_sk_free(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_num(st) SKM_sk_num(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_value(st, i) SKM_sk_value(CONF_IMODULE, (st), (i)) +#define sk_CONF_IMODULE_set(st, i, val) SKM_sk_set(CONF_IMODULE, (st), (i), (val)) +#define sk_CONF_IMODULE_zero(st) SKM_sk_zero(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_push(st, val) SKM_sk_push(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_unshift(st, val) SKM_sk_unshift(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_find(st, val) SKM_sk_find(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_find_ex(st, val) SKM_sk_find_ex(CONF_IMODULE, (st), (val)) +#define sk_CONF_IMODULE_delete(st, i) SKM_sk_delete(CONF_IMODULE, (st), (i)) +#define sk_CONF_IMODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_IMODULE, (st), (ptr)) +#define sk_CONF_IMODULE_insert(st, val, i) SKM_sk_insert(CONF_IMODULE, (st), (val), (i)) +#define sk_CONF_IMODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_IMODULE, (st), (cmp)) +#define sk_CONF_IMODULE_dup(st) SKM_sk_dup(CONF_IMODULE, st) +#define sk_CONF_IMODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_IMODULE, (st), (free_func)) +#define sk_CONF_IMODULE_shift(st) SKM_sk_shift(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_pop(st) SKM_sk_pop(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_sort(st) SKM_sk_sort(CONF_IMODULE, (st)) +#define sk_CONF_IMODULE_is_sorted(st) SKM_sk_is_sorted(CONF_IMODULE, (st)) + +#define sk_CONF_MODULE_new(cmp) SKM_sk_new(CONF_MODULE, (cmp)) +#define sk_CONF_MODULE_new_null() SKM_sk_new_null(CONF_MODULE) +#define sk_CONF_MODULE_free(st) SKM_sk_free(CONF_MODULE, (st)) +#define sk_CONF_MODULE_num(st) SKM_sk_num(CONF_MODULE, (st)) +#define sk_CONF_MODULE_value(st, i) SKM_sk_value(CONF_MODULE, (st), (i)) +#define sk_CONF_MODULE_set(st, i, val) SKM_sk_set(CONF_MODULE, (st), (i), (val)) +#define sk_CONF_MODULE_zero(st) SKM_sk_zero(CONF_MODULE, (st)) +#define sk_CONF_MODULE_push(st, val) SKM_sk_push(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_unshift(st, val) SKM_sk_unshift(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_find(st, val) SKM_sk_find(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_find_ex(st, val) SKM_sk_find_ex(CONF_MODULE, (st), (val)) +#define sk_CONF_MODULE_delete(st, i) SKM_sk_delete(CONF_MODULE, (st), (i)) +#define sk_CONF_MODULE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_MODULE, (st), (ptr)) +#define sk_CONF_MODULE_insert(st, val, i) SKM_sk_insert(CONF_MODULE, (st), (val), (i)) +#define sk_CONF_MODULE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_MODULE, (st), (cmp)) +#define sk_CONF_MODULE_dup(st) SKM_sk_dup(CONF_MODULE, st) +#define sk_CONF_MODULE_pop_free(st, free_func) SKM_sk_pop_free(CONF_MODULE, (st), (free_func)) +#define sk_CONF_MODULE_shift(st) SKM_sk_shift(CONF_MODULE, (st)) +#define sk_CONF_MODULE_pop(st) SKM_sk_pop(CONF_MODULE, (st)) +#define sk_CONF_MODULE_sort(st) SKM_sk_sort(CONF_MODULE, (st)) +#define sk_CONF_MODULE_is_sorted(st) SKM_sk_is_sorted(CONF_MODULE, (st)) + +#define sk_CONF_VALUE_new(cmp) SKM_sk_new(CONF_VALUE, (cmp)) +#define sk_CONF_VALUE_new_null() SKM_sk_new_null(CONF_VALUE) +#define sk_CONF_VALUE_free(st) SKM_sk_free(CONF_VALUE, (st)) +#define sk_CONF_VALUE_num(st) SKM_sk_num(CONF_VALUE, (st)) +#define sk_CONF_VALUE_value(st, i) SKM_sk_value(CONF_VALUE, (st), (i)) +#define sk_CONF_VALUE_set(st, i, val) SKM_sk_set(CONF_VALUE, (st), (i), (val)) +#define sk_CONF_VALUE_zero(st) SKM_sk_zero(CONF_VALUE, (st)) +#define sk_CONF_VALUE_push(st, val) SKM_sk_push(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_unshift(st, val) SKM_sk_unshift(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_find(st, val) SKM_sk_find(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_find_ex(st, val) SKM_sk_find_ex(CONF_VALUE, (st), (val)) +#define sk_CONF_VALUE_delete(st, i) SKM_sk_delete(CONF_VALUE, (st), (i)) +#define sk_CONF_VALUE_delete_ptr(st, ptr) SKM_sk_delete_ptr(CONF_VALUE, (st), (ptr)) +#define sk_CONF_VALUE_insert(st, val, i) SKM_sk_insert(CONF_VALUE, (st), (val), (i)) +#define sk_CONF_VALUE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CONF_VALUE, (st), (cmp)) +#define sk_CONF_VALUE_dup(st) SKM_sk_dup(CONF_VALUE, st) +#define sk_CONF_VALUE_pop_free(st, free_func) SKM_sk_pop_free(CONF_VALUE, (st), (free_func)) +#define sk_CONF_VALUE_shift(st) SKM_sk_shift(CONF_VALUE, (st)) +#define sk_CONF_VALUE_pop(st) SKM_sk_pop(CONF_VALUE, (st)) +#define sk_CONF_VALUE_sort(st) SKM_sk_sort(CONF_VALUE, (st)) +#define sk_CONF_VALUE_is_sorted(st) SKM_sk_is_sorted(CONF_VALUE, (st)) + +#define sk_CRYPTO_dynlock_new(cmp) SKM_sk_new(CRYPTO_dynlock, (cmp)) +#define sk_CRYPTO_dynlock_new_null() SKM_sk_new_null(CRYPTO_dynlock) +#define sk_CRYPTO_dynlock_free(st) SKM_sk_free(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_num(st) SKM_sk_num(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_value(st, i) SKM_sk_value(CRYPTO_dynlock, (st), (i)) +#define sk_CRYPTO_dynlock_set(st, i, val) SKM_sk_set(CRYPTO_dynlock, (st), (i), (val)) +#define sk_CRYPTO_dynlock_zero(st) SKM_sk_zero(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_push(st, val) SKM_sk_push(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_unshift(st, val) SKM_sk_unshift(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_find(st, val) SKM_sk_find(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_find_ex(st, val) SKM_sk_find_ex(CRYPTO_dynlock, (st), (val)) +#define sk_CRYPTO_dynlock_delete(st, i) SKM_sk_delete(CRYPTO_dynlock, (st), (i)) +#define sk_CRYPTO_dynlock_delete_ptr(st, ptr) SKM_sk_delete_ptr(CRYPTO_dynlock, (st), (ptr)) +#define sk_CRYPTO_dynlock_insert(st, val, i) SKM_sk_insert(CRYPTO_dynlock, (st), (val), (i)) +#define sk_CRYPTO_dynlock_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CRYPTO_dynlock, (st), (cmp)) +#define sk_CRYPTO_dynlock_dup(st) SKM_sk_dup(CRYPTO_dynlock, st) +#define sk_CRYPTO_dynlock_pop_free(st, free_func) SKM_sk_pop_free(CRYPTO_dynlock, (st), (free_func)) +#define sk_CRYPTO_dynlock_shift(st) SKM_sk_shift(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_pop(st) SKM_sk_pop(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_sort(st) SKM_sk_sort(CRYPTO_dynlock, (st)) +#define sk_CRYPTO_dynlock_is_sorted(st) SKM_sk_is_sorted(CRYPTO_dynlock, (st)) + +#define sk_CTLOG_new(cmp) SKM_sk_new(CTLOG, (cmp)) +#define sk_CTLOG_new_null() SKM_sk_new_null(CTLOG) +#define sk_CTLOG_free(st) SKM_sk_free(CTLOG, (st)) +#define sk_CTLOG_num(st) SKM_sk_num(CTLOG, (st)) +#define sk_CTLOG_value(st, i) SKM_sk_value(CTLOG, (st), (i)) +#define sk_CTLOG_set(st, i, val) SKM_sk_set(CTLOG, (st), (i), (val)) +#define sk_CTLOG_zero(st) SKM_sk_zero(CTLOG, (st)) +#define sk_CTLOG_push(st, val) SKM_sk_push(CTLOG, (st), (val)) +#define sk_CTLOG_unshift(st, val) SKM_sk_unshift(CTLOG, (st), (val)) +#define sk_CTLOG_find(st, val) SKM_sk_find(CTLOG, (st), (val)) +#define sk_CTLOG_find_ex(st, val) SKM_sk_find_ex(CTLOG, (st), (val)) +#define sk_CTLOG_delete(st, i) SKM_sk_delete(CTLOG, (st), (i)) +#define sk_CTLOG_delete_ptr(st, ptr) SKM_sk_delete_ptr(CTLOG, (st), (ptr)) +#define sk_CTLOG_insert(st, val, i) SKM_sk_insert(CTLOG, (st), (val), (i)) +#define sk_CTLOG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(CTLOG, (st), (cmp)) +#define sk_CTLOG_dup(st) SKM_sk_dup(CTLOG, st) +#define sk_CTLOG_pop_free(st, free_func) SKM_sk_pop_free(CTLOG, (st), (free_func)) +#define sk_CTLOG_shift(st) SKM_sk_shift(CTLOG, (st)) +#define sk_CTLOG_pop(st) SKM_sk_pop(CTLOG, (st)) +#define sk_CTLOG_sort(st) SKM_sk_sort(CTLOG, (st)) +#define sk_CTLOG_is_sorted(st) SKM_sk_is_sorted(CTLOG, (st)) + +#define sk_DIST_POINT_new(cmp) SKM_sk_new(DIST_POINT, (cmp)) +#define sk_DIST_POINT_new_null() SKM_sk_new_null(DIST_POINT) +#define sk_DIST_POINT_free(st) SKM_sk_free(DIST_POINT, (st)) +#define sk_DIST_POINT_num(st) SKM_sk_num(DIST_POINT, (st)) +#define sk_DIST_POINT_value(st, i) SKM_sk_value(DIST_POINT, (st), (i)) +#define sk_DIST_POINT_set(st, i, val) SKM_sk_set(DIST_POINT, (st), (i), (val)) +#define sk_DIST_POINT_zero(st) SKM_sk_zero(DIST_POINT, (st)) +#define sk_DIST_POINT_push(st, val) SKM_sk_push(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_unshift(st, val) SKM_sk_unshift(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_find(st, val) SKM_sk_find(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_find_ex(st, val) SKM_sk_find_ex(DIST_POINT, (st), (val)) +#define sk_DIST_POINT_delete(st, i) SKM_sk_delete(DIST_POINT, (st), (i)) +#define sk_DIST_POINT_delete_ptr(st, ptr) SKM_sk_delete_ptr(DIST_POINT, (st), (ptr)) +#define sk_DIST_POINT_insert(st, val, i) SKM_sk_insert(DIST_POINT, (st), (val), (i)) +#define sk_DIST_POINT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(DIST_POINT, (st), (cmp)) +#define sk_DIST_POINT_dup(st) SKM_sk_dup(DIST_POINT, st) +#define sk_DIST_POINT_pop_free(st, free_func) SKM_sk_pop_free(DIST_POINT, (st), (free_func)) +#define sk_DIST_POINT_shift(st) SKM_sk_shift(DIST_POINT, (st)) +#define sk_DIST_POINT_pop(st) SKM_sk_pop(DIST_POINT, (st)) +#define sk_DIST_POINT_sort(st) SKM_sk_sort(DIST_POINT, (st)) +#define sk_DIST_POINT_is_sorted(st) SKM_sk_is_sorted(DIST_POINT, (st)) + +#define sk_ESS_CERT_ID_new(cmp) SKM_sk_new(ESS_CERT_ID, (cmp)) +#define sk_ESS_CERT_ID_new_null() SKM_sk_new_null(ESS_CERT_ID) +#define sk_ESS_CERT_ID_free(st) SKM_sk_free(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_num(st) SKM_sk_num(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_value(st, i) SKM_sk_value(ESS_CERT_ID, (st), (i)) +#define sk_ESS_CERT_ID_set(st, i, val) SKM_sk_set(ESS_CERT_ID, (st), (i), (val)) +#define sk_ESS_CERT_ID_zero(st) SKM_sk_zero(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_push(st, val) SKM_sk_push(ESS_CERT_ID, (st), (val)) +#define sk_ESS_CERT_ID_unshift(st, val) SKM_sk_unshift(ESS_CERT_ID, (st), (val)) +#define sk_ESS_CERT_ID_find(st, val) SKM_sk_find(ESS_CERT_ID, (st), (val)) +#define sk_ESS_CERT_ID_find_ex(st, val) SKM_sk_find_ex(ESS_CERT_ID, (st), (val)) +#define sk_ESS_CERT_ID_delete(st, i) SKM_sk_delete(ESS_CERT_ID, (st), (i)) +#define sk_ESS_CERT_ID_delete_ptr(st, ptr) SKM_sk_delete_ptr(ESS_CERT_ID, (st), (ptr)) +#define sk_ESS_CERT_ID_insert(st, val, i) SKM_sk_insert(ESS_CERT_ID, (st), (val), (i)) +#define sk_ESS_CERT_ID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ESS_CERT_ID, (st), (cmp)) +#define sk_ESS_CERT_ID_dup(st) SKM_sk_dup(ESS_CERT_ID, st) +#define sk_ESS_CERT_ID_pop_free(st, free_func) SKM_sk_pop_free(ESS_CERT_ID, (st), (free_func)) +#define sk_ESS_CERT_ID_shift(st) SKM_sk_shift(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_pop(st) SKM_sk_pop(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_sort(st) SKM_sk_sort(ESS_CERT_ID, (st)) +#define sk_ESS_CERT_ID_is_sorted(st) SKM_sk_is_sorted(ESS_CERT_ID, (st)) + +#ifdef LIBRESSL_INTERNAL +#define sk_ESS_CERT_ID_V2_new(cmp) SKM_sk_new(ESS_CERT_ID_V2, (cmp)) +#define sk_ESS_CERT_ID_V2_new_null() SKM_sk_new_null(ESS_CERT_ID_V2) +#define sk_ESS_CERT_ID_V2_free(st) SKM_sk_free(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_num(st) SKM_sk_num(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_value(st, i) SKM_sk_value(ESS_CERT_ID_V2, (st), (i)) +#define sk_ESS_CERT_ID_V2_set(st, i, val) SKM_sk_set(ESS_CERT_ID_V2, (st), (i), (val)) +#define sk_ESS_CERT_ID_V2_zero(st) SKM_sk_zero(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_push(st, val) SKM_sk_push(ESS_CERT_ID_V2, (st), (val)) +#define sk_ESS_CERT_ID_V2_unshift(st, val) SKM_sk_unshift(ESS_CERT_ID_V2, (st), (val)) +#define sk_ESS_CERT_ID_V2_find(st, val) SKM_sk_find(ESS_CERT_ID_V2, (st), (val)) +#define sk_ESS_CERT_ID_V2_find_ex(st, val) SKM_sk_find_ex(ESS_CERT_ID_V2, (st), (val)) +#define sk_ESS_CERT_ID_V2_delete(st, i) SKM_sk_delete(ESS_CERT_ID_V2, (st), (i)) +#define sk_ESS_CERT_ID_V2_delete_ptr(st, ptr) SKM_sk_delete_ptr(ESS_CERT_ID_V2, (st), (ptr)) +#define sk_ESS_CERT_ID_V2_insert(st, val, i) SKM_sk_insert(ESS_CERT_ID_V2, (st), (val), (i)) +#define sk_ESS_CERT_ID_V2_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ESS_CERT_ID_V2, (st), (cmp)) +#define sk_ESS_CERT_ID_V2_dup(st) SKM_sk_dup(ESS_CERT_ID_V2, st) +#define sk_ESS_CERT_ID_V2_pop_free(st, free_func) SKM_sk_pop_free(ESS_CERT_ID_V2, (st), (free_func)) +#define sk_ESS_CERT_ID_V2_shift(st) SKM_sk_shift(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_pop(st) SKM_sk_pop(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_sort(st) SKM_sk_sort(ESS_CERT_ID_V2, (st)) +#define sk_ESS_CERT_ID_V2_is_sorted(st) SKM_sk_is_sorted(ESS_CERT_ID_V2, (st)) +#endif /* LIBRESSL_INTERNAL */ + +#define sk_EVP_MD_new(cmp) SKM_sk_new(EVP_MD, (cmp)) +#define sk_EVP_MD_new_null() SKM_sk_new_null(EVP_MD) +#define sk_EVP_MD_free(st) SKM_sk_free(EVP_MD, (st)) +#define sk_EVP_MD_num(st) SKM_sk_num(EVP_MD, (st)) +#define sk_EVP_MD_value(st, i) SKM_sk_value(EVP_MD, (st), (i)) +#define sk_EVP_MD_set(st, i, val) SKM_sk_set(EVP_MD, (st), (i), (val)) +#define sk_EVP_MD_zero(st) SKM_sk_zero(EVP_MD, (st)) +#define sk_EVP_MD_push(st, val) SKM_sk_push(EVP_MD, (st), (val)) +#define sk_EVP_MD_unshift(st, val) SKM_sk_unshift(EVP_MD, (st), (val)) +#define sk_EVP_MD_find(st, val) SKM_sk_find(EVP_MD, (st), (val)) +#define sk_EVP_MD_find_ex(st, val) SKM_sk_find_ex(EVP_MD, (st), (val)) +#define sk_EVP_MD_delete(st, i) SKM_sk_delete(EVP_MD, (st), (i)) +#define sk_EVP_MD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_MD, (st), (ptr)) +#define sk_EVP_MD_insert(st, val, i) SKM_sk_insert(EVP_MD, (st), (val), (i)) +#define sk_EVP_MD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_MD, (st), (cmp)) +#define sk_EVP_MD_dup(st) SKM_sk_dup(EVP_MD, st) +#define sk_EVP_MD_pop_free(st, free_func) SKM_sk_pop_free(EVP_MD, (st), (free_func)) +#define sk_EVP_MD_shift(st) SKM_sk_shift(EVP_MD, (st)) +#define sk_EVP_MD_pop(st) SKM_sk_pop(EVP_MD, (st)) +#define sk_EVP_MD_sort(st) SKM_sk_sort(EVP_MD, (st)) +#define sk_EVP_MD_is_sorted(st) SKM_sk_is_sorted(EVP_MD, (st)) + +#define sk_EVP_PBE_CTL_new(cmp) SKM_sk_new(EVP_PBE_CTL, (cmp)) +#define sk_EVP_PBE_CTL_new_null() SKM_sk_new_null(EVP_PBE_CTL) +#define sk_EVP_PBE_CTL_free(st) SKM_sk_free(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_num(st) SKM_sk_num(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_value(st, i) SKM_sk_value(EVP_PBE_CTL, (st), (i)) +#define sk_EVP_PBE_CTL_set(st, i, val) SKM_sk_set(EVP_PBE_CTL, (st), (i), (val)) +#define sk_EVP_PBE_CTL_zero(st) SKM_sk_zero(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_push(st, val) SKM_sk_push(EVP_PBE_CTL, (st), (val)) +#define sk_EVP_PBE_CTL_unshift(st, val) SKM_sk_unshift(EVP_PBE_CTL, (st), (val)) +#define sk_EVP_PBE_CTL_find(st, val) SKM_sk_find(EVP_PBE_CTL, (st), (val)) +#define sk_EVP_PBE_CTL_find_ex(st, val) SKM_sk_find_ex(EVP_PBE_CTL, (st), (val)) +#define sk_EVP_PBE_CTL_delete(st, i) SKM_sk_delete(EVP_PBE_CTL, (st), (i)) +#define sk_EVP_PBE_CTL_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PBE_CTL, (st), (ptr)) +#define sk_EVP_PBE_CTL_insert(st, val, i) SKM_sk_insert(EVP_PBE_CTL, (st), (val), (i)) +#define sk_EVP_PBE_CTL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PBE_CTL, (st), (cmp)) +#define sk_EVP_PBE_CTL_dup(st) SKM_sk_dup(EVP_PBE_CTL, st) +#define sk_EVP_PBE_CTL_pop_free(st, free_func) SKM_sk_pop_free(EVP_PBE_CTL, (st), (free_func)) +#define sk_EVP_PBE_CTL_shift(st) SKM_sk_shift(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_pop(st) SKM_sk_pop(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_sort(st) SKM_sk_sort(EVP_PBE_CTL, (st)) +#define sk_EVP_PBE_CTL_is_sorted(st) SKM_sk_is_sorted(EVP_PBE_CTL, (st)) + +#define sk_EVP_PKEY_ASN1_METHOD_new(cmp) SKM_sk_new(EVP_PKEY_ASN1_METHOD, (cmp)) +#define sk_EVP_PKEY_ASN1_METHOD_new_null() SKM_sk_new_null(EVP_PKEY_ASN1_METHOD) +#define sk_EVP_PKEY_ASN1_METHOD_free(st) SKM_sk_free(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_num(st) SKM_sk_num(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_value(st, i) SKM_sk_value(EVP_PKEY_ASN1_METHOD, (st), (i)) +#define sk_EVP_PKEY_ASN1_METHOD_set(st, i, val) SKM_sk_set(EVP_PKEY_ASN1_METHOD, (st), (i), (val)) +#define sk_EVP_PKEY_ASN1_METHOD_zero(st) SKM_sk_zero(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_push(st, val) SKM_sk_push(EVP_PKEY_ASN1_METHOD, (st), (val)) +#define sk_EVP_PKEY_ASN1_METHOD_unshift(st, val) SKM_sk_unshift(EVP_PKEY_ASN1_METHOD, (st), (val)) +#define sk_EVP_PKEY_ASN1_METHOD_find(st, val) SKM_sk_find(EVP_PKEY_ASN1_METHOD, (st), (val)) +#define sk_EVP_PKEY_ASN1_METHOD_find_ex(st, val) SKM_sk_find_ex(EVP_PKEY_ASN1_METHOD, (st), (val)) +#define sk_EVP_PKEY_ASN1_METHOD_delete(st, i) SKM_sk_delete(EVP_PKEY_ASN1_METHOD, (st), (i)) +#define sk_EVP_PKEY_ASN1_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PKEY_ASN1_METHOD, (st), (ptr)) +#define sk_EVP_PKEY_ASN1_METHOD_insert(st, val, i) SKM_sk_insert(EVP_PKEY_ASN1_METHOD, (st), (val), (i)) +#define sk_EVP_PKEY_ASN1_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PKEY_ASN1_METHOD, (st), (cmp)) +#define sk_EVP_PKEY_ASN1_METHOD_dup(st) SKM_sk_dup(EVP_PKEY_ASN1_METHOD, st) +#define sk_EVP_PKEY_ASN1_METHOD_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY_ASN1_METHOD, (st), (free_func)) +#define sk_EVP_PKEY_ASN1_METHOD_shift(st) SKM_sk_shift(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_pop(st) SKM_sk_pop(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_sort(st) SKM_sk_sort(EVP_PKEY_ASN1_METHOD, (st)) +#define sk_EVP_PKEY_ASN1_METHOD_is_sorted(st) SKM_sk_is_sorted(EVP_PKEY_ASN1_METHOD, (st)) + +#define sk_EVP_PKEY_METHOD_new(cmp) SKM_sk_new(EVP_PKEY_METHOD, (cmp)) +#define sk_EVP_PKEY_METHOD_new_null() SKM_sk_new_null(EVP_PKEY_METHOD) +#define sk_EVP_PKEY_METHOD_free(st) SKM_sk_free(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_num(st) SKM_sk_num(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_value(st, i) SKM_sk_value(EVP_PKEY_METHOD, (st), (i)) +#define sk_EVP_PKEY_METHOD_set(st, i, val) SKM_sk_set(EVP_PKEY_METHOD, (st), (i), (val)) +#define sk_EVP_PKEY_METHOD_zero(st) SKM_sk_zero(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_push(st, val) SKM_sk_push(EVP_PKEY_METHOD, (st), (val)) +#define sk_EVP_PKEY_METHOD_unshift(st, val) SKM_sk_unshift(EVP_PKEY_METHOD, (st), (val)) +#define sk_EVP_PKEY_METHOD_find(st, val) SKM_sk_find(EVP_PKEY_METHOD, (st), (val)) +#define sk_EVP_PKEY_METHOD_find_ex(st, val) SKM_sk_find_ex(EVP_PKEY_METHOD, (st), (val)) +#define sk_EVP_PKEY_METHOD_delete(st, i) SKM_sk_delete(EVP_PKEY_METHOD, (st), (i)) +#define sk_EVP_PKEY_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(EVP_PKEY_METHOD, (st), (ptr)) +#define sk_EVP_PKEY_METHOD_insert(st, val, i) SKM_sk_insert(EVP_PKEY_METHOD, (st), (val), (i)) +#define sk_EVP_PKEY_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(EVP_PKEY_METHOD, (st), (cmp)) +#define sk_EVP_PKEY_METHOD_dup(st) SKM_sk_dup(EVP_PKEY_METHOD, st) +#define sk_EVP_PKEY_METHOD_pop_free(st, free_func) SKM_sk_pop_free(EVP_PKEY_METHOD, (st), (free_func)) +#define sk_EVP_PKEY_METHOD_shift(st) SKM_sk_shift(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_pop(st) SKM_sk_pop(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_sort(st) SKM_sk_sort(EVP_PKEY_METHOD, (st)) +#define sk_EVP_PKEY_METHOD_is_sorted(st) SKM_sk_is_sorted(EVP_PKEY_METHOD, (st)) + +#define sk_GENERAL_NAME_new(cmp) SKM_sk_new(GENERAL_NAME, (cmp)) +#define sk_GENERAL_NAME_new_null() SKM_sk_new_null(GENERAL_NAME) +#define sk_GENERAL_NAME_free(st) SKM_sk_free(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_num(st) SKM_sk_num(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_value(st, i) SKM_sk_value(GENERAL_NAME, (st), (i)) +#define sk_GENERAL_NAME_set(st, i, val) SKM_sk_set(GENERAL_NAME, (st), (i), (val)) +#define sk_GENERAL_NAME_zero(st) SKM_sk_zero(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_push(st, val) SKM_sk_push(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_unshift(st, val) SKM_sk_unshift(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_find(st, val) SKM_sk_find(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAME, (st), (val)) +#define sk_GENERAL_NAME_delete(st, i) SKM_sk_delete(GENERAL_NAME, (st), (i)) +#define sk_GENERAL_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAME, (st), (ptr)) +#define sk_GENERAL_NAME_insert(st, val, i) SKM_sk_insert(GENERAL_NAME, (st), (val), (i)) +#define sk_GENERAL_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAME, (st), (cmp)) +#define sk_GENERAL_NAME_dup(st) SKM_sk_dup(GENERAL_NAME, st) +#define sk_GENERAL_NAME_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAME, (st), (free_func)) +#define sk_GENERAL_NAME_shift(st) SKM_sk_shift(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_pop(st) SKM_sk_pop(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_sort(st) SKM_sk_sort(GENERAL_NAME, (st)) +#define sk_GENERAL_NAME_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAME, (st)) + +#define sk_GENERAL_NAMES_new(cmp) SKM_sk_new(GENERAL_NAMES, (cmp)) +#define sk_GENERAL_NAMES_new_null() SKM_sk_new_null(GENERAL_NAMES) +#define sk_GENERAL_NAMES_free(st) SKM_sk_free(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_num(st) SKM_sk_num(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_value(st, i) SKM_sk_value(GENERAL_NAMES, (st), (i)) +#define sk_GENERAL_NAMES_set(st, i, val) SKM_sk_set(GENERAL_NAMES, (st), (i), (val)) +#define sk_GENERAL_NAMES_zero(st) SKM_sk_zero(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_push(st, val) SKM_sk_push(GENERAL_NAMES, (st), (val)) +#define sk_GENERAL_NAMES_unshift(st, val) SKM_sk_unshift(GENERAL_NAMES, (st), (val)) +#define sk_GENERAL_NAMES_find(st, val) SKM_sk_find(GENERAL_NAMES, (st), (val)) +#define sk_GENERAL_NAMES_find_ex(st, val) SKM_sk_find_ex(GENERAL_NAMES, (st), (val)) +#define sk_GENERAL_NAMES_delete(st, i) SKM_sk_delete(GENERAL_NAMES, (st), (i)) +#define sk_GENERAL_NAMES_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_NAMES, (st), (ptr)) +#define sk_GENERAL_NAMES_insert(st, val, i) SKM_sk_insert(GENERAL_NAMES, (st), (val), (i)) +#define sk_GENERAL_NAMES_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_NAMES, (st), (cmp)) +#define sk_GENERAL_NAMES_dup(st) SKM_sk_dup(GENERAL_NAMES, st) +#define sk_GENERAL_NAMES_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_NAMES, (st), (free_func)) +#define sk_GENERAL_NAMES_shift(st) SKM_sk_shift(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_pop(st) SKM_sk_pop(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_sort(st) SKM_sk_sort(GENERAL_NAMES, (st)) +#define sk_GENERAL_NAMES_is_sorted(st) SKM_sk_is_sorted(GENERAL_NAMES, (st)) + +#define sk_GENERAL_SUBTREE_new(cmp) SKM_sk_new(GENERAL_SUBTREE, (cmp)) +#define sk_GENERAL_SUBTREE_new_null() SKM_sk_new_null(GENERAL_SUBTREE) +#define sk_GENERAL_SUBTREE_free(st) SKM_sk_free(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_num(st) SKM_sk_num(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_value(st, i) SKM_sk_value(GENERAL_SUBTREE, (st), (i)) +#define sk_GENERAL_SUBTREE_set(st, i, val) SKM_sk_set(GENERAL_SUBTREE, (st), (i), (val)) +#define sk_GENERAL_SUBTREE_zero(st) SKM_sk_zero(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_push(st, val) SKM_sk_push(GENERAL_SUBTREE, (st), (val)) +#define sk_GENERAL_SUBTREE_unshift(st, val) SKM_sk_unshift(GENERAL_SUBTREE, (st), (val)) +#define sk_GENERAL_SUBTREE_find(st, val) SKM_sk_find(GENERAL_SUBTREE, (st), (val)) +#define sk_GENERAL_SUBTREE_find_ex(st, val) SKM_sk_find_ex(GENERAL_SUBTREE, (st), (val)) +#define sk_GENERAL_SUBTREE_delete(st, i) SKM_sk_delete(GENERAL_SUBTREE, (st), (i)) +#define sk_GENERAL_SUBTREE_delete_ptr(st, ptr) SKM_sk_delete_ptr(GENERAL_SUBTREE, (st), (ptr)) +#define sk_GENERAL_SUBTREE_insert(st, val, i) SKM_sk_insert(GENERAL_SUBTREE, (st), (val), (i)) +#define sk_GENERAL_SUBTREE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(GENERAL_SUBTREE, (st), (cmp)) +#define sk_GENERAL_SUBTREE_dup(st) SKM_sk_dup(GENERAL_SUBTREE, st) +#define sk_GENERAL_SUBTREE_pop_free(st, free_func) SKM_sk_pop_free(GENERAL_SUBTREE, (st), (free_func)) +#define sk_GENERAL_SUBTREE_shift(st) SKM_sk_shift(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_pop(st) SKM_sk_pop(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_sort(st) SKM_sk_sort(GENERAL_SUBTREE, (st)) +#define sk_GENERAL_SUBTREE_is_sorted(st) SKM_sk_is_sorted(GENERAL_SUBTREE, (st)) + +#define sk_IPAddressFamily_new(cmp) SKM_sk_new(IPAddressFamily, (cmp)) +#define sk_IPAddressFamily_new_null() SKM_sk_new_null(IPAddressFamily) +#define sk_IPAddressFamily_free(st) SKM_sk_free(IPAddressFamily, (st)) +#define sk_IPAddressFamily_num(st) SKM_sk_num(IPAddressFamily, (st)) +#define sk_IPAddressFamily_value(st, i) SKM_sk_value(IPAddressFamily, (st), (i)) +#define sk_IPAddressFamily_set(st, i, val) SKM_sk_set(IPAddressFamily, (st), (i), (val)) +#define sk_IPAddressFamily_zero(st) SKM_sk_zero(IPAddressFamily, (st)) +#define sk_IPAddressFamily_push(st, val) SKM_sk_push(IPAddressFamily, (st), (val)) +#define sk_IPAddressFamily_unshift(st, val) SKM_sk_unshift(IPAddressFamily, (st), (val)) +#define sk_IPAddressFamily_find(st, val) SKM_sk_find(IPAddressFamily, (st), (val)) +#define sk_IPAddressFamily_find_ex(st, val) SKM_sk_find_ex(IPAddressFamily, (st), (val)) +#define sk_IPAddressFamily_delete(st, i) SKM_sk_delete(IPAddressFamily, (st), (i)) +#define sk_IPAddressFamily_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressFamily, (st), (ptr)) +#define sk_IPAddressFamily_insert(st, val, i) SKM_sk_insert(IPAddressFamily, (st), (val), (i)) +#define sk_IPAddressFamily_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressFamily, (st), (cmp)) +#define sk_IPAddressFamily_dup(st) SKM_sk_dup(IPAddressFamily, st) +#define sk_IPAddressFamily_pop_free(st, free_func) SKM_sk_pop_free(IPAddressFamily, (st), (free_func)) +#define sk_IPAddressFamily_shift(st) SKM_sk_shift(IPAddressFamily, (st)) +#define sk_IPAddressFamily_pop(st) SKM_sk_pop(IPAddressFamily, (st)) +#define sk_IPAddressFamily_sort(st) SKM_sk_sort(IPAddressFamily, (st)) +#define sk_IPAddressFamily_is_sorted(st) SKM_sk_is_sorted(IPAddressFamily, (st)) + +#define sk_IPAddressOrRange_new(cmp) SKM_sk_new(IPAddressOrRange, (cmp)) +#define sk_IPAddressOrRange_new_null() SKM_sk_new_null(IPAddressOrRange) +#define sk_IPAddressOrRange_free(st) SKM_sk_free(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_num(st) SKM_sk_num(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_value(st, i) SKM_sk_value(IPAddressOrRange, (st), (i)) +#define sk_IPAddressOrRange_set(st, i, val) SKM_sk_set(IPAddressOrRange, (st), (i), (val)) +#define sk_IPAddressOrRange_zero(st) SKM_sk_zero(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_push(st, val) SKM_sk_push(IPAddressOrRange, (st), (val)) +#define sk_IPAddressOrRange_unshift(st, val) SKM_sk_unshift(IPAddressOrRange, (st), (val)) +#define sk_IPAddressOrRange_find(st, val) SKM_sk_find(IPAddressOrRange, (st), (val)) +#define sk_IPAddressOrRange_find_ex(st, val) SKM_sk_find_ex(IPAddressOrRange, (st), (val)) +#define sk_IPAddressOrRange_delete(st, i) SKM_sk_delete(IPAddressOrRange, (st), (i)) +#define sk_IPAddressOrRange_delete_ptr(st, ptr) SKM_sk_delete_ptr(IPAddressOrRange, (st), (ptr)) +#define sk_IPAddressOrRange_insert(st, val, i) SKM_sk_insert(IPAddressOrRange, (st), (val), (i)) +#define sk_IPAddressOrRange_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(IPAddressOrRange, (st), (cmp)) +#define sk_IPAddressOrRange_dup(st) SKM_sk_dup(IPAddressOrRange, st) +#define sk_IPAddressOrRange_pop_free(st, free_func) SKM_sk_pop_free(IPAddressOrRange, (st), (free_func)) +#define sk_IPAddressOrRange_shift(st) SKM_sk_shift(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_pop(st) SKM_sk_pop(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_sort(st) SKM_sk_sort(IPAddressOrRange, (st)) +#define sk_IPAddressOrRange_is_sorted(st) SKM_sk_is_sorted(IPAddressOrRange, (st)) + +#define sk_MIME_HEADER_new(cmp) SKM_sk_new(MIME_HEADER, (cmp)) +#define sk_MIME_HEADER_new_null() SKM_sk_new_null(MIME_HEADER) +#define sk_MIME_HEADER_free(st) SKM_sk_free(MIME_HEADER, (st)) +#define sk_MIME_HEADER_num(st) SKM_sk_num(MIME_HEADER, (st)) +#define sk_MIME_HEADER_value(st, i) SKM_sk_value(MIME_HEADER, (st), (i)) +#define sk_MIME_HEADER_set(st, i, val) SKM_sk_set(MIME_HEADER, (st), (i), (val)) +#define sk_MIME_HEADER_zero(st) SKM_sk_zero(MIME_HEADER, (st)) +#define sk_MIME_HEADER_push(st, val) SKM_sk_push(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_unshift(st, val) SKM_sk_unshift(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_find(st, val) SKM_sk_find(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_find_ex(st, val) SKM_sk_find_ex(MIME_HEADER, (st), (val)) +#define sk_MIME_HEADER_delete(st, i) SKM_sk_delete(MIME_HEADER, (st), (i)) +#define sk_MIME_HEADER_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_HEADER, (st), (ptr)) +#define sk_MIME_HEADER_insert(st, val, i) SKM_sk_insert(MIME_HEADER, (st), (val), (i)) +#define sk_MIME_HEADER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_HEADER, (st), (cmp)) +#define sk_MIME_HEADER_dup(st) SKM_sk_dup(MIME_HEADER, st) +#define sk_MIME_HEADER_pop_free(st, free_func) SKM_sk_pop_free(MIME_HEADER, (st), (free_func)) +#define sk_MIME_HEADER_shift(st) SKM_sk_shift(MIME_HEADER, (st)) +#define sk_MIME_HEADER_pop(st) SKM_sk_pop(MIME_HEADER, (st)) +#define sk_MIME_HEADER_sort(st) SKM_sk_sort(MIME_HEADER, (st)) +#define sk_MIME_HEADER_is_sorted(st) SKM_sk_is_sorted(MIME_HEADER, (st)) + +#define sk_MIME_PARAM_new(cmp) SKM_sk_new(MIME_PARAM, (cmp)) +#define sk_MIME_PARAM_new_null() SKM_sk_new_null(MIME_PARAM) +#define sk_MIME_PARAM_free(st) SKM_sk_free(MIME_PARAM, (st)) +#define sk_MIME_PARAM_num(st) SKM_sk_num(MIME_PARAM, (st)) +#define sk_MIME_PARAM_value(st, i) SKM_sk_value(MIME_PARAM, (st), (i)) +#define sk_MIME_PARAM_set(st, i, val) SKM_sk_set(MIME_PARAM, (st), (i), (val)) +#define sk_MIME_PARAM_zero(st) SKM_sk_zero(MIME_PARAM, (st)) +#define sk_MIME_PARAM_push(st, val) SKM_sk_push(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_unshift(st, val) SKM_sk_unshift(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_find(st, val) SKM_sk_find(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_find_ex(st, val) SKM_sk_find_ex(MIME_PARAM, (st), (val)) +#define sk_MIME_PARAM_delete(st, i) SKM_sk_delete(MIME_PARAM, (st), (i)) +#define sk_MIME_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(MIME_PARAM, (st), (ptr)) +#define sk_MIME_PARAM_insert(st, val, i) SKM_sk_insert(MIME_PARAM, (st), (val), (i)) +#define sk_MIME_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(MIME_PARAM, (st), (cmp)) +#define sk_MIME_PARAM_dup(st) SKM_sk_dup(MIME_PARAM, st) +#define sk_MIME_PARAM_pop_free(st, free_func) SKM_sk_pop_free(MIME_PARAM, (st), (free_func)) +#define sk_MIME_PARAM_shift(st) SKM_sk_shift(MIME_PARAM, (st)) +#define sk_MIME_PARAM_pop(st) SKM_sk_pop(MIME_PARAM, (st)) +#define sk_MIME_PARAM_sort(st) SKM_sk_sort(MIME_PARAM, (st)) +#define sk_MIME_PARAM_is_sorted(st) SKM_sk_is_sorted(MIME_PARAM, (st)) + +#define sk_NAME_FUNCS_new(cmp) SKM_sk_new(NAME_FUNCS, (cmp)) +#define sk_NAME_FUNCS_new_null() SKM_sk_new_null(NAME_FUNCS) +#define sk_NAME_FUNCS_free(st) SKM_sk_free(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_num(st) SKM_sk_num(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_value(st, i) SKM_sk_value(NAME_FUNCS, (st), (i)) +#define sk_NAME_FUNCS_set(st, i, val) SKM_sk_set(NAME_FUNCS, (st), (i), (val)) +#define sk_NAME_FUNCS_zero(st) SKM_sk_zero(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_push(st, val) SKM_sk_push(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_unshift(st, val) SKM_sk_unshift(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_find(st, val) SKM_sk_find(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_find_ex(st, val) SKM_sk_find_ex(NAME_FUNCS, (st), (val)) +#define sk_NAME_FUNCS_delete(st, i) SKM_sk_delete(NAME_FUNCS, (st), (i)) +#define sk_NAME_FUNCS_delete_ptr(st, ptr) SKM_sk_delete_ptr(NAME_FUNCS, (st), (ptr)) +#define sk_NAME_FUNCS_insert(st, val, i) SKM_sk_insert(NAME_FUNCS, (st), (val), (i)) +#define sk_NAME_FUNCS_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(NAME_FUNCS, (st), (cmp)) +#define sk_NAME_FUNCS_dup(st) SKM_sk_dup(NAME_FUNCS, st) +#define sk_NAME_FUNCS_pop_free(st, free_func) SKM_sk_pop_free(NAME_FUNCS, (st), (free_func)) +#define sk_NAME_FUNCS_shift(st) SKM_sk_shift(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_pop(st) SKM_sk_pop(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_sort(st) SKM_sk_sort(NAME_FUNCS, (st)) +#define sk_NAME_FUNCS_is_sorted(st) SKM_sk_is_sorted(NAME_FUNCS, (st)) + +#define sk_OCSP_CERTID_new(cmp) SKM_sk_new(OCSP_CERTID, (cmp)) +#define sk_OCSP_CERTID_new_null() SKM_sk_new_null(OCSP_CERTID) +#define sk_OCSP_CERTID_free(st) SKM_sk_free(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_num(st) SKM_sk_num(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_value(st, i) SKM_sk_value(OCSP_CERTID, (st), (i)) +#define sk_OCSP_CERTID_set(st, i, val) SKM_sk_set(OCSP_CERTID, (st), (i), (val)) +#define sk_OCSP_CERTID_zero(st) SKM_sk_zero(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_push(st, val) SKM_sk_push(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_unshift(st, val) SKM_sk_unshift(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_find(st, val) SKM_sk_find(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_find_ex(st, val) SKM_sk_find_ex(OCSP_CERTID, (st), (val)) +#define sk_OCSP_CERTID_delete(st, i) SKM_sk_delete(OCSP_CERTID, (st), (i)) +#define sk_OCSP_CERTID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_CERTID, (st), (ptr)) +#define sk_OCSP_CERTID_insert(st, val, i) SKM_sk_insert(OCSP_CERTID, (st), (val), (i)) +#define sk_OCSP_CERTID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_CERTID, (st), (cmp)) +#define sk_OCSP_CERTID_dup(st) SKM_sk_dup(OCSP_CERTID, st) +#define sk_OCSP_CERTID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_CERTID, (st), (free_func)) +#define sk_OCSP_CERTID_shift(st) SKM_sk_shift(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_pop(st) SKM_sk_pop(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_sort(st) SKM_sk_sort(OCSP_CERTID, (st)) +#define sk_OCSP_CERTID_is_sorted(st) SKM_sk_is_sorted(OCSP_CERTID, (st)) + +#define sk_OCSP_ONEREQ_new(cmp) SKM_sk_new(OCSP_ONEREQ, (cmp)) +#define sk_OCSP_ONEREQ_new_null() SKM_sk_new_null(OCSP_ONEREQ) +#define sk_OCSP_ONEREQ_free(st) SKM_sk_free(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_num(st) SKM_sk_num(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_value(st, i) SKM_sk_value(OCSP_ONEREQ, (st), (i)) +#define sk_OCSP_ONEREQ_set(st, i, val) SKM_sk_set(OCSP_ONEREQ, (st), (i), (val)) +#define sk_OCSP_ONEREQ_zero(st) SKM_sk_zero(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_push(st, val) SKM_sk_push(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_unshift(st, val) SKM_sk_unshift(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_find(st, val) SKM_sk_find(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_find_ex(st, val) SKM_sk_find_ex(OCSP_ONEREQ, (st), (val)) +#define sk_OCSP_ONEREQ_delete(st, i) SKM_sk_delete(OCSP_ONEREQ, (st), (i)) +#define sk_OCSP_ONEREQ_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_ONEREQ, (st), (ptr)) +#define sk_OCSP_ONEREQ_insert(st, val, i) SKM_sk_insert(OCSP_ONEREQ, (st), (val), (i)) +#define sk_OCSP_ONEREQ_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_ONEREQ, (st), (cmp)) +#define sk_OCSP_ONEREQ_dup(st) SKM_sk_dup(OCSP_ONEREQ, st) +#define sk_OCSP_ONEREQ_pop_free(st, free_func) SKM_sk_pop_free(OCSP_ONEREQ, (st), (free_func)) +#define sk_OCSP_ONEREQ_shift(st) SKM_sk_shift(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_pop(st) SKM_sk_pop(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_sort(st) SKM_sk_sort(OCSP_ONEREQ, (st)) +#define sk_OCSP_ONEREQ_is_sorted(st) SKM_sk_is_sorted(OCSP_ONEREQ, (st)) + +#define sk_OCSP_RESPID_new(cmp) SKM_sk_new(OCSP_RESPID, (cmp)) +#define sk_OCSP_RESPID_new_null() SKM_sk_new_null(OCSP_RESPID) +#define sk_OCSP_RESPID_free(st) SKM_sk_free(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_num(st) SKM_sk_num(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_value(st, i) SKM_sk_value(OCSP_RESPID, (st), (i)) +#define sk_OCSP_RESPID_set(st, i, val) SKM_sk_set(OCSP_RESPID, (st), (i), (val)) +#define sk_OCSP_RESPID_zero(st) SKM_sk_zero(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_push(st, val) SKM_sk_push(OCSP_RESPID, (st), (val)) +#define sk_OCSP_RESPID_unshift(st, val) SKM_sk_unshift(OCSP_RESPID, (st), (val)) +#define sk_OCSP_RESPID_find(st, val) SKM_sk_find(OCSP_RESPID, (st), (val)) +#define sk_OCSP_RESPID_find_ex(st, val) SKM_sk_find_ex(OCSP_RESPID, (st), (val)) +#define sk_OCSP_RESPID_delete(st, i) SKM_sk_delete(OCSP_RESPID, (st), (i)) +#define sk_OCSP_RESPID_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_RESPID, (st), (ptr)) +#define sk_OCSP_RESPID_insert(st, val, i) SKM_sk_insert(OCSP_RESPID, (st), (val), (i)) +#define sk_OCSP_RESPID_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_RESPID, (st), (cmp)) +#define sk_OCSP_RESPID_dup(st) SKM_sk_dup(OCSP_RESPID, st) +#define sk_OCSP_RESPID_pop_free(st, free_func) SKM_sk_pop_free(OCSP_RESPID, (st), (free_func)) +#define sk_OCSP_RESPID_shift(st) SKM_sk_shift(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_pop(st) SKM_sk_pop(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_sort(st) SKM_sk_sort(OCSP_RESPID, (st)) +#define sk_OCSP_RESPID_is_sorted(st) SKM_sk_is_sorted(OCSP_RESPID, (st)) + +#define sk_OCSP_SINGLERESP_new(cmp) SKM_sk_new(OCSP_SINGLERESP, (cmp)) +#define sk_OCSP_SINGLERESP_new_null() SKM_sk_new_null(OCSP_SINGLERESP) +#define sk_OCSP_SINGLERESP_free(st) SKM_sk_free(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_num(st) SKM_sk_num(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_value(st, i) SKM_sk_value(OCSP_SINGLERESP, (st), (i)) +#define sk_OCSP_SINGLERESP_set(st, i, val) SKM_sk_set(OCSP_SINGLERESP, (st), (i), (val)) +#define sk_OCSP_SINGLERESP_zero(st) SKM_sk_zero(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_push(st, val) SKM_sk_push(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_unshift(st, val) SKM_sk_unshift(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_find(st, val) SKM_sk_find(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_find_ex(st, val) SKM_sk_find_ex(OCSP_SINGLERESP, (st), (val)) +#define sk_OCSP_SINGLERESP_delete(st, i) SKM_sk_delete(OCSP_SINGLERESP, (st), (i)) +#define sk_OCSP_SINGLERESP_delete_ptr(st, ptr) SKM_sk_delete_ptr(OCSP_SINGLERESP, (st), (ptr)) +#define sk_OCSP_SINGLERESP_insert(st, val, i) SKM_sk_insert(OCSP_SINGLERESP, (st), (val), (i)) +#define sk_OCSP_SINGLERESP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(OCSP_SINGLERESP, (st), (cmp)) +#define sk_OCSP_SINGLERESP_dup(st) SKM_sk_dup(OCSP_SINGLERESP, st) +#define sk_OCSP_SINGLERESP_pop_free(st, free_func) SKM_sk_pop_free(OCSP_SINGLERESP, (st), (free_func)) +#define sk_OCSP_SINGLERESP_shift(st) SKM_sk_shift(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_pop(st) SKM_sk_pop(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_sort(st) SKM_sk_sort(OCSP_SINGLERESP, (st)) +#define sk_OCSP_SINGLERESP_is_sorted(st) SKM_sk_is_sorted(OCSP_SINGLERESP, (st)) + +#define sk_PKCS12_SAFEBAG_new(cmp) SKM_sk_new(PKCS12_SAFEBAG, (cmp)) +#define sk_PKCS12_SAFEBAG_new_null() SKM_sk_new_null(PKCS12_SAFEBAG) +#define sk_PKCS12_SAFEBAG_free(st) SKM_sk_free(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_num(st) SKM_sk_num(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_value(st, i) SKM_sk_value(PKCS12_SAFEBAG, (st), (i)) +#define sk_PKCS12_SAFEBAG_set(st, i, val) SKM_sk_set(PKCS12_SAFEBAG, (st), (i), (val)) +#define sk_PKCS12_SAFEBAG_zero(st) SKM_sk_zero(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_push(st, val) SKM_sk_push(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_unshift(st, val) SKM_sk_unshift(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_find(st, val) SKM_sk_find(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_find_ex(st, val) SKM_sk_find_ex(PKCS12_SAFEBAG, (st), (val)) +#define sk_PKCS12_SAFEBAG_delete(st, i) SKM_sk_delete(PKCS12_SAFEBAG, (st), (i)) +#define sk_PKCS12_SAFEBAG_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS12_SAFEBAG, (st), (ptr)) +#define sk_PKCS12_SAFEBAG_insert(st, val, i) SKM_sk_insert(PKCS12_SAFEBAG, (st), (val), (i)) +#define sk_PKCS12_SAFEBAG_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS12_SAFEBAG, (st), (cmp)) +#define sk_PKCS12_SAFEBAG_dup(st) SKM_sk_dup(PKCS12_SAFEBAG, st) +#define sk_PKCS12_SAFEBAG_pop_free(st, free_func) SKM_sk_pop_free(PKCS12_SAFEBAG, (st), (free_func)) +#define sk_PKCS12_SAFEBAG_shift(st) SKM_sk_shift(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_pop(st) SKM_sk_pop(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_sort(st) SKM_sk_sort(PKCS12_SAFEBAG, (st)) +#define sk_PKCS12_SAFEBAG_is_sorted(st) SKM_sk_is_sorted(PKCS12_SAFEBAG, (st)) + +#define sk_PKCS7_new(cmp) SKM_sk_new(PKCS7, (cmp)) +#define sk_PKCS7_new_null() SKM_sk_new_null(PKCS7) +#define sk_PKCS7_free(st) SKM_sk_free(PKCS7, (st)) +#define sk_PKCS7_num(st) SKM_sk_num(PKCS7, (st)) +#define sk_PKCS7_value(st, i) SKM_sk_value(PKCS7, (st), (i)) +#define sk_PKCS7_set(st, i, val) SKM_sk_set(PKCS7, (st), (i), (val)) +#define sk_PKCS7_zero(st) SKM_sk_zero(PKCS7, (st)) +#define sk_PKCS7_push(st, val) SKM_sk_push(PKCS7, (st), (val)) +#define sk_PKCS7_unshift(st, val) SKM_sk_unshift(PKCS7, (st), (val)) +#define sk_PKCS7_find(st, val) SKM_sk_find(PKCS7, (st), (val)) +#define sk_PKCS7_find_ex(st, val) SKM_sk_find_ex(PKCS7, (st), (val)) +#define sk_PKCS7_delete(st, i) SKM_sk_delete(PKCS7, (st), (i)) +#define sk_PKCS7_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7, (st), (ptr)) +#define sk_PKCS7_insert(st, val, i) SKM_sk_insert(PKCS7, (st), (val), (i)) +#define sk_PKCS7_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7, (st), (cmp)) +#define sk_PKCS7_dup(st) SKM_sk_dup(PKCS7, st) +#define sk_PKCS7_pop_free(st, free_func) SKM_sk_pop_free(PKCS7, (st), (free_func)) +#define sk_PKCS7_shift(st) SKM_sk_shift(PKCS7, (st)) +#define sk_PKCS7_pop(st) SKM_sk_pop(PKCS7, (st)) +#define sk_PKCS7_sort(st) SKM_sk_sort(PKCS7, (st)) +#define sk_PKCS7_is_sorted(st) SKM_sk_is_sorted(PKCS7, (st)) + +#define sk_PKCS7_RECIP_INFO_new(cmp) SKM_sk_new(PKCS7_RECIP_INFO, (cmp)) +#define sk_PKCS7_RECIP_INFO_new_null() SKM_sk_new_null(PKCS7_RECIP_INFO) +#define sk_PKCS7_RECIP_INFO_free(st) SKM_sk_free(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_num(st) SKM_sk_num(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_value(st, i) SKM_sk_value(PKCS7_RECIP_INFO, (st), (i)) +#define sk_PKCS7_RECIP_INFO_set(st, i, val) SKM_sk_set(PKCS7_RECIP_INFO, (st), (i), (val)) +#define sk_PKCS7_RECIP_INFO_zero(st) SKM_sk_zero(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_push(st, val) SKM_sk_push(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_find(st, val) SKM_sk_find(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_RECIP_INFO, (st), (val)) +#define sk_PKCS7_RECIP_INFO_delete(st, i) SKM_sk_delete(PKCS7_RECIP_INFO, (st), (i)) +#define sk_PKCS7_RECIP_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_RECIP_INFO, (st), (ptr)) +#define sk_PKCS7_RECIP_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_RECIP_INFO, (st), (val), (i)) +#define sk_PKCS7_RECIP_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_RECIP_INFO, (st), (cmp)) +#define sk_PKCS7_RECIP_INFO_dup(st) SKM_sk_dup(PKCS7_RECIP_INFO, st) +#define sk_PKCS7_RECIP_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_RECIP_INFO, (st), (free_func)) +#define sk_PKCS7_RECIP_INFO_shift(st) SKM_sk_shift(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_pop(st) SKM_sk_pop(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_sort(st) SKM_sk_sort(PKCS7_RECIP_INFO, (st)) +#define sk_PKCS7_RECIP_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_RECIP_INFO, (st)) + +#define sk_PKCS7_SIGNER_INFO_new(cmp) SKM_sk_new(PKCS7_SIGNER_INFO, (cmp)) +#define sk_PKCS7_SIGNER_INFO_new_null() SKM_sk_new_null(PKCS7_SIGNER_INFO) +#define sk_PKCS7_SIGNER_INFO_free(st) SKM_sk_free(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_num(st) SKM_sk_num(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_value(st, i) SKM_sk_value(PKCS7_SIGNER_INFO, (st), (i)) +#define sk_PKCS7_SIGNER_INFO_set(st, i, val) SKM_sk_set(PKCS7_SIGNER_INFO, (st), (i), (val)) +#define sk_PKCS7_SIGNER_INFO_zero(st) SKM_sk_zero(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_push(st, val) SKM_sk_push(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_unshift(st, val) SKM_sk_unshift(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_find(st, val) SKM_sk_find(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_find_ex(st, val) SKM_sk_find_ex(PKCS7_SIGNER_INFO, (st), (val)) +#define sk_PKCS7_SIGNER_INFO_delete(st, i) SKM_sk_delete(PKCS7_SIGNER_INFO, (st), (i)) +#define sk_PKCS7_SIGNER_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(PKCS7_SIGNER_INFO, (st), (ptr)) +#define sk_PKCS7_SIGNER_INFO_insert(st, val, i) SKM_sk_insert(PKCS7_SIGNER_INFO, (st), (val), (i)) +#define sk_PKCS7_SIGNER_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(PKCS7_SIGNER_INFO, (st), (cmp)) +#define sk_PKCS7_SIGNER_INFO_dup(st) SKM_sk_dup(PKCS7_SIGNER_INFO, st) +#define sk_PKCS7_SIGNER_INFO_pop_free(st, free_func) SKM_sk_pop_free(PKCS7_SIGNER_INFO, (st), (free_func)) +#define sk_PKCS7_SIGNER_INFO_shift(st) SKM_sk_shift(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_pop(st) SKM_sk_pop(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_sort(st) SKM_sk_sort(PKCS7_SIGNER_INFO, (st)) +#define sk_PKCS7_SIGNER_INFO_is_sorted(st) SKM_sk_is_sorted(PKCS7_SIGNER_INFO, (st)) + +#define sk_POLICYINFO_new(cmp) SKM_sk_new(POLICYINFO, (cmp)) +#define sk_POLICYINFO_new_null() SKM_sk_new_null(POLICYINFO) +#define sk_POLICYINFO_free(st) SKM_sk_free(POLICYINFO, (st)) +#define sk_POLICYINFO_num(st) SKM_sk_num(POLICYINFO, (st)) +#define sk_POLICYINFO_value(st, i) SKM_sk_value(POLICYINFO, (st), (i)) +#define sk_POLICYINFO_set(st, i, val) SKM_sk_set(POLICYINFO, (st), (i), (val)) +#define sk_POLICYINFO_zero(st) SKM_sk_zero(POLICYINFO, (st)) +#define sk_POLICYINFO_push(st, val) SKM_sk_push(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_unshift(st, val) SKM_sk_unshift(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_find(st, val) SKM_sk_find(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_find_ex(st, val) SKM_sk_find_ex(POLICYINFO, (st), (val)) +#define sk_POLICYINFO_delete(st, i) SKM_sk_delete(POLICYINFO, (st), (i)) +#define sk_POLICYINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYINFO, (st), (ptr)) +#define sk_POLICYINFO_insert(st, val, i) SKM_sk_insert(POLICYINFO, (st), (val), (i)) +#define sk_POLICYINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYINFO, (st), (cmp)) +#define sk_POLICYINFO_dup(st) SKM_sk_dup(POLICYINFO, st) +#define sk_POLICYINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYINFO, (st), (free_func)) +#define sk_POLICYINFO_shift(st) SKM_sk_shift(POLICYINFO, (st)) +#define sk_POLICYINFO_pop(st) SKM_sk_pop(POLICYINFO, (st)) +#define sk_POLICYINFO_sort(st) SKM_sk_sort(POLICYINFO, (st)) +#define sk_POLICYINFO_is_sorted(st) SKM_sk_is_sorted(POLICYINFO, (st)) + +#define sk_POLICYQUALINFO_new(cmp) SKM_sk_new(POLICYQUALINFO, (cmp)) +#define sk_POLICYQUALINFO_new_null() SKM_sk_new_null(POLICYQUALINFO) +#define sk_POLICYQUALINFO_free(st) SKM_sk_free(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_num(st) SKM_sk_num(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_value(st, i) SKM_sk_value(POLICYQUALINFO, (st), (i)) +#define sk_POLICYQUALINFO_set(st, i, val) SKM_sk_set(POLICYQUALINFO, (st), (i), (val)) +#define sk_POLICYQUALINFO_zero(st) SKM_sk_zero(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_push(st, val) SKM_sk_push(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_unshift(st, val) SKM_sk_unshift(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_find(st, val) SKM_sk_find(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_find_ex(st, val) SKM_sk_find_ex(POLICYQUALINFO, (st), (val)) +#define sk_POLICYQUALINFO_delete(st, i) SKM_sk_delete(POLICYQUALINFO, (st), (i)) +#define sk_POLICYQUALINFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICYQUALINFO, (st), (ptr)) +#define sk_POLICYQUALINFO_insert(st, val, i) SKM_sk_insert(POLICYQUALINFO, (st), (val), (i)) +#define sk_POLICYQUALINFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICYQUALINFO, (st), (cmp)) +#define sk_POLICYQUALINFO_dup(st) SKM_sk_dup(POLICYQUALINFO, st) +#define sk_POLICYQUALINFO_pop_free(st, free_func) SKM_sk_pop_free(POLICYQUALINFO, (st), (free_func)) +#define sk_POLICYQUALINFO_shift(st) SKM_sk_shift(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_pop(st) SKM_sk_pop(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_sort(st) SKM_sk_sort(POLICYQUALINFO, (st)) +#define sk_POLICYQUALINFO_is_sorted(st) SKM_sk_is_sorted(POLICYQUALINFO, (st)) + +#define sk_POLICY_MAPPING_new(cmp) SKM_sk_new(POLICY_MAPPING, (cmp)) +#define sk_POLICY_MAPPING_new_null() SKM_sk_new_null(POLICY_MAPPING) +#define sk_POLICY_MAPPING_free(st) SKM_sk_free(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_num(st) SKM_sk_num(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_value(st, i) SKM_sk_value(POLICY_MAPPING, (st), (i)) +#define sk_POLICY_MAPPING_set(st, i, val) SKM_sk_set(POLICY_MAPPING, (st), (i), (val)) +#define sk_POLICY_MAPPING_zero(st) SKM_sk_zero(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_push(st, val) SKM_sk_push(POLICY_MAPPING, (st), (val)) +#define sk_POLICY_MAPPING_unshift(st, val) SKM_sk_unshift(POLICY_MAPPING, (st), (val)) +#define sk_POLICY_MAPPING_find(st, val) SKM_sk_find(POLICY_MAPPING, (st), (val)) +#define sk_POLICY_MAPPING_find_ex(st, val) SKM_sk_find_ex(POLICY_MAPPING, (st), (val)) +#define sk_POLICY_MAPPING_delete(st, i) SKM_sk_delete(POLICY_MAPPING, (st), (i)) +#define sk_POLICY_MAPPING_delete_ptr(st, ptr) SKM_sk_delete_ptr(POLICY_MAPPING, (st), (ptr)) +#define sk_POLICY_MAPPING_insert(st, val, i) SKM_sk_insert(POLICY_MAPPING, (st), (val), (i)) +#define sk_POLICY_MAPPING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(POLICY_MAPPING, (st), (cmp)) +#define sk_POLICY_MAPPING_dup(st) SKM_sk_dup(POLICY_MAPPING, st) +#define sk_POLICY_MAPPING_pop_free(st, free_func) SKM_sk_pop_free(POLICY_MAPPING, (st), (free_func)) +#define sk_POLICY_MAPPING_shift(st) SKM_sk_shift(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_pop(st) SKM_sk_pop(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_sort(st) SKM_sk_sort(POLICY_MAPPING, (st)) +#define sk_POLICY_MAPPING_is_sorted(st) SKM_sk_is_sorted(POLICY_MAPPING, (st)) + +#define sk_SCT_new(cmp) SKM_sk_new(SCT, (cmp)) +#define sk_SCT_new_null() SKM_sk_new_null(SCT) +#define sk_SCT_free(st) SKM_sk_free(SCT, (st)) +#define sk_SCT_num(st) SKM_sk_num(SCT, (st)) +#define sk_SCT_value(st, i) SKM_sk_value(SCT, (st), (i)) +#define sk_SCT_set(st, i, val) SKM_sk_set(SCT, (st), (i), (val)) +#define sk_SCT_zero(st) SKM_sk_zero(SCT, (st)) +#define sk_SCT_push(st, val) SKM_sk_push(SCT, (st), (val)) +#define sk_SCT_unshift(st, val) SKM_sk_unshift(SCT, (st), (val)) +#define sk_SCT_find(st, val) SKM_sk_find(SCT, (st), (val)) +#define sk_SCT_find_ex(st, val) SKM_sk_find_ex(SCT, (st), (val)) +#define sk_SCT_delete(st, i) SKM_sk_delete(SCT, (st), (i)) +#define sk_SCT_delete_ptr(st, ptr) SKM_sk_delete_ptr(SCT, (st), (ptr)) +#define sk_SCT_insert(st, val, i) SKM_sk_insert(SCT, (st), (val), (i)) +#define sk_SCT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SCT, (st), (cmp)) +#define sk_SCT_dup(st) SKM_sk_dup(SCT, st) +#define sk_SCT_pop_free(st, free_func) SKM_sk_pop_free(SCT, (st), (free_func)) +#define sk_SCT_shift(st) SKM_sk_shift(SCT, (st)) +#define sk_SCT_pop(st) SKM_sk_pop(SCT, (st)) +#define sk_SCT_sort(st) SKM_sk_sort(SCT, (st)) +#define sk_SCT_is_sorted(st) SKM_sk_is_sorted(SCT, (st)) + +#define sk_SRTP_PROTECTION_PROFILE_new(cmp) SKM_sk_new(SRTP_PROTECTION_PROFILE, (cmp)) +#define sk_SRTP_PROTECTION_PROFILE_new_null() SKM_sk_new_null(SRTP_PROTECTION_PROFILE) +#define sk_SRTP_PROTECTION_PROFILE_free(st) SKM_sk_free(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_num(st) SKM_sk_num(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_value(st, i) SKM_sk_value(SRTP_PROTECTION_PROFILE, (st), (i)) +#define sk_SRTP_PROTECTION_PROFILE_set(st, i, val) SKM_sk_set(SRTP_PROTECTION_PROFILE, (st), (i), (val)) +#define sk_SRTP_PROTECTION_PROFILE_zero(st) SKM_sk_zero(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_push(st, val) SKM_sk_push(SRTP_PROTECTION_PROFILE, (st), (val)) +#define sk_SRTP_PROTECTION_PROFILE_unshift(st, val) SKM_sk_unshift(SRTP_PROTECTION_PROFILE, (st), (val)) +#define sk_SRTP_PROTECTION_PROFILE_find(st, val) SKM_sk_find(SRTP_PROTECTION_PROFILE, (st), (val)) +#define sk_SRTP_PROTECTION_PROFILE_find_ex(st, val) SKM_sk_find_ex(SRTP_PROTECTION_PROFILE, (st), (val)) +#define sk_SRTP_PROTECTION_PROFILE_delete(st, i) SKM_sk_delete(SRTP_PROTECTION_PROFILE, (st), (i)) +#define sk_SRTP_PROTECTION_PROFILE_delete_ptr(st, ptr) SKM_sk_delete_ptr(SRTP_PROTECTION_PROFILE, (st), (ptr)) +#define sk_SRTP_PROTECTION_PROFILE_insert(st, val, i) SKM_sk_insert(SRTP_PROTECTION_PROFILE, (st), (val), (i)) +#define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SRTP_PROTECTION_PROFILE, (st), (cmp)) +#define sk_SRTP_PROTECTION_PROFILE_dup(st) SKM_sk_dup(SRTP_PROTECTION_PROFILE, st) +#define sk_SRTP_PROTECTION_PROFILE_pop_free(st, free_func) SKM_sk_pop_free(SRTP_PROTECTION_PROFILE, (st), (free_func)) +#define sk_SRTP_PROTECTION_PROFILE_shift(st) SKM_sk_shift(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_pop(st) SKM_sk_pop(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_sort(st) SKM_sk_sort(SRTP_PROTECTION_PROFILE, (st)) +#define sk_SRTP_PROTECTION_PROFILE_is_sorted(st) SKM_sk_is_sorted(SRTP_PROTECTION_PROFILE, (st)) + +#define sk_SSL_CIPHER_new(cmp) SKM_sk_new(SSL_CIPHER, (cmp)) +#define sk_SSL_CIPHER_new_null() SKM_sk_new_null(SSL_CIPHER) +#define sk_SSL_CIPHER_free(st) SKM_sk_free(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_num(st) SKM_sk_num(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_value(st, i) SKM_sk_value(SSL_CIPHER, (st), (i)) +#define sk_SSL_CIPHER_set(st, i, val) SKM_sk_set(SSL_CIPHER, (st), (i), (val)) +#define sk_SSL_CIPHER_zero(st) SKM_sk_zero(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_push(st, val) SKM_sk_push(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_unshift(st, val) SKM_sk_unshift(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_find(st, val) SKM_sk_find(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_find_ex(st, val) SKM_sk_find_ex(SSL_CIPHER, (st), (val)) +#define sk_SSL_CIPHER_delete(st, i) SKM_sk_delete(SSL_CIPHER, (st), (i)) +#define sk_SSL_CIPHER_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_CIPHER, (st), (ptr)) +#define sk_SSL_CIPHER_insert(st, val, i) SKM_sk_insert(SSL_CIPHER, (st), (val), (i)) +#define sk_SSL_CIPHER_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_CIPHER, (st), (cmp)) +#define sk_SSL_CIPHER_dup(st) SKM_sk_dup(SSL_CIPHER, st) +#define sk_SSL_CIPHER_pop_free(st, free_func) SKM_sk_pop_free(SSL_CIPHER, (st), (free_func)) +#define sk_SSL_CIPHER_shift(st) SKM_sk_shift(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_pop(st) SKM_sk_pop(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_sort(st) SKM_sk_sort(SSL_CIPHER, (st)) +#define sk_SSL_CIPHER_is_sorted(st) SKM_sk_is_sorted(SSL_CIPHER, (st)) + +#define sk_SSL_COMP_new(cmp) SKM_sk_new(SSL_COMP, (cmp)) +#define sk_SSL_COMP_new_null() SKM_sk_new_null(SSL_COMP) +#define sk_SSL_COMP_free(st) SKM_sk_free(SSL_COMP, (st)) +#define sk_SSL_COMP_num(st) SKM_sk_num(SSL_COMP, (st)) +#define sk_SSL_COMP_value(st, i) SKM_sk_value(SSL_COMP, (st), (i)) +#define sk_SSL_COMP_set(st, i, val) SKM_sk_set(SSL_COMP, (st), (i), (val)) +#define sk_SSL_COMP_zero(st) SKM_sk_zero(SSL_COMP, (st)) +#define sk_SSL_COMP_push(st, val) SKM_sk_push(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_unshift(st, val) SKM_sk_unshift(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_find(st, val) SKM_sk_find(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_find_ex(st, val) SKM_sk_find_ex(SSL_COMP, (st), (val)) +#define sk_SSL_COMP_delete(st, i) SKM_sk_delete(SSL_COMP, (st), (i)) +#define sk_SSL_COMP_delete_ptr(st, ptr) SKM_sk_delete_ptr(SSL_COMP, (st), (ptr)) +#define sk_SSL_COMP_insert(st, val, i) SKM_sk_insert(SSL_COMP, (st), (val), (i)) +#define sk_SSL_COMP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(SSL_COMP, (st), (cmp)) +#define sk_SSL_COMP_dup(st) SKM_sk_dup(SSL_COMP, st) +#define sk_SSL_COMP_pop_free(st, free_func) SKM_sk_pop_free(SSL_COMP, (st), (free_func)) +#define sk_SSL_COMP_shift(st) SKM_sk_shift(SSL_COMP, (st)) +#define sk_SSL_COMP_pop(st) SKM_sk_pop(SSL_COMP, (st)) +#define sk_SSL_COMP_sort(st) SKM_sk_sort(SSL_COMP, (st)) +#define sk_SSL_COMP_is_sorted(st) SKM_sk_is_sorted(SSL_COMP, (st)) + +#define sk_STACK_OF_X509_NAME_ENTRY_new(cmp) SKM_sk_new(STACK_OF_X509_NAME_ENTRY, (cmp)) +#define sk_STACK_OF_X509_NAME_ENTRY_new_null() SKM_sk_new_null(STACK_OF_X509_NAME_ENTRY) +#define sk_STACK_OF_X509_NAME_ENTRY_free(st) SKM_sk_free(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_num(st) SKM_sk_num(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_value(st, i) SKM_sk_value(STACK_OF_X509_NAME_ENTRY, (st), (i)) +#define sk_STACK_OF_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(STACK_OF_X509_NAME_ENTRY, (st), (i), (val)) +#define sk_STACK_OF_X509_NAME_ENTRY_zero(st) SKM_sk_zero(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_push(st, val) SKM_sk_push(STACK_OF_X509_NAME_ENTRY, (st), (val)) +#define sk_STACK_OF_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(STACK_OF_X509_NAME_ENTRY, (st), (val)) +#define sk_STACK_OF_X509_NAME_ENTRY_find(st, val) SKM_sk_find(STACK_OF_X509_NAME_ENTRY, (st), (val)) +#define sk_STACK_OF_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(STACK_OF_X509_NAME_ENTRY, (st), (val)) +#define sk_STACK_OF_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(STACK_OF_X509_NAME_ENTRY, (st), (i)) +#define sk_STACK_OF_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(STACK_OF_X509_NAME_ENTRY, (st), (ptr)) +#define sk_STACK_OF_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(STACK_OF_X509_NAME_ENTRY, (st), (val), (i)) +#define sk_STACK_OF_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STACK_OF_X509_NAME_ENTRY, (st), (cmp)) +#define sk_STACK_OF_X509_NAME_ENTRY_dup(st) SKM_sk_dup(STACK_OF_X509_NAME_ENTRY, st) +#define sk_STACK_OF_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(STACK_OF_X509_NAME_ENTRY, (st), (free_func)) +#define sk_STACK_OF_X509_NAME_ENTRY_shift(st) SKM_sk_shift(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_pop(st) SKM_sk_pop(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_sort(st) SKM_sk_sort(STACK_OF_X509_NAME_ENTRY, (st)) +#define sk_STACK_OF_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(STACK_OF_X509_NAME_ENTRY, (st)) + +#define sk_STORE_ATTR_INFO_new(cmp) SKM_sk_new(STORE_ATTR_INFO, (cmp)) +#define sk_STORE_ATTR_INFO_new_null() SKM_sk_new_null(STORE_ATTR_INFO) +#define sk_STORE_ATTR_INFO_free(st) SKM_sk_free(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_num(st) SKM_sk_num(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_value(st, i) SKM_sk_value(STORE_ATTR_INFO, (st), (i)) +#define sk_STORE_ATTR_INFO_set(st, i, val) SKM_sk_set(STORE_ATTR_INFO, (st), (i), (val)) +#define sk_STORE_ATTR_INFO_zero(st) SKM_sk_zero(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_push(st, val) SKM_sk_push(STORE_ATTR_INFO, (st), (val)) +#define sk_STORE_ATTR_INFO_unshift(st, val) SKM_sk_unshift(STORE_ATTR_INFO, (st), (val)) +#define sk_STORE_ATTR_INFO_find(st, val) SKM_sk_find(STORE_ATTR_INFO, (st), (val)) +#define sk_STORE_ATTR_INFO_find_ex(st, val) SKM_sk_find_ex(STORE_ATTR_INFO, (st), (val)) +#define sk_STORE_ATTR_INFO_delete(st, i) SKM_sk_delete(STORE_ATTR_INFO, (st), (i)) +#define sk_STORE_ATTR_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_ATTR_INFO, (st), (ptr)) +#define sk_STORE_ATTR_INFO_insert(st, val, i) SKM_sk_insert(STORE_ATTR_INFO, (st), (val), (i)) +#define sk_STORE_ATTR_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_ATTR_INFO, (st), (cmp)) +#define sk_STORE_ATTR_INFO_dup(st) SKM_sk_dup(STORE_ATTR_INFO, st) +#define sk_STORE_ATTR_INFO_pop_free(st, free_func) SKM_sk_pop_free(STORE_ATTR_INFO, (st), (free_func)) +#define sk_STORE_ATTR_INFO_shift(st) SKM_sk_shift(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_pop(st) SKM_sk_pop(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_sort(st) SKM_sk_sort(STORE_ATTR_INFO, (st)) +#define sk_STORE_ATTR_INFO_is_sorted(st) SKM_sk_is_sorted(STORE_ATTR_INFO, (st)) + +#define sk_STORE_OBJECT_new(cmp) SKM_sk_new(STORE_OBJECT, (cmp)) +#define sk_STORE_OBJECT_new_null() SKM_sk_new_null(STORE_OBJECT) +#define sk_STORE_OBJECT_free(st) SKM_sk_free(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_num(st) SKM_sk_num(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_value(st, i) SKM_sk_value(STORE_OBJECT, (st), (i)) +#define sk_STORE_OBJECT_set(st, i, val) SKM_sk_set(STORE_OBJECT, (st), (i), (val)) +#define sk_STORE_OBJECT_zero(st) SKM_sk_zero(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_push(st, val) SKM_sk_push(STORE_OBJECT, (st), (val)) +#define sk_STORE_OBJECT_unshift(st, val) SKM_sk_unshift(STORE_OBJECT, (st), (val)) +#define sk_STORE_OBJECT_find(st, val) SKM_sk_find(STORE_OBJECT, (st), (val)) +#define sk_STORE_OBJECT_find_ex(st, val) SKM_sk_find_ex(STORE_OBJECT, (st), (val)) +#define sk_STORE_OBJECT_delete(st, i) SKM_sk_delete(STORE_OBJECT, (st), (i)) +#define sk_STORE_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(STORE_OBJECT, (st), (ptr)) +#define sk_STORE_OBJECT_insert(st, val, i) SKM_sk_insert(STORE_OBJECT, (st), (val), (i)) +#define sk_STORE_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(STORE_OBJECT, (st), (cmp)) +#define sk_STORE_OBJECT_dup(st) SKM_sk_dup(STORE_OBJECT, st) +#define sk_STORE_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(STORE_OBJECT, (st), (free_func)) +#define sk_STORE_OBJECT_shift(st) SKM_sk_shift(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_pop(st) SKM_sk_pop(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_sort(st) SKM_sk_sort(STORE_OBJECT, (st)) +#define sk_STORE_OBJECT_is_sorted(st) SKM_sk_is_sorted(STORE_OBJECT, (st)) + +#define sk_UI_STRING_new(cmp) SKM_sk_new(UI_STRING, (cmp)) +#define sk_UI_STRING_new_null() SKM_sk_new_null(UI_STRING) +#define sk_UI_STRING_free(st) SKM_sk_free(UI_STRING, (st)) +#define sk_UI_STRING_num(st) SKM_sk_num(UI_STRING, (st)) +#define sk_UI_STRING_value(st, i) SKM_sk_value(UI_STRING, (st), (i)) +#define sk_UI_STRING_set(st, i, val) SKM_sk_set(UI_STRING, (st), (i), (val)) +#define sk_UI_STRING_zero(st) SKM_sk_zero(UI_STRING, (st)) +#define sk_UI_STRING_push(st, val) SKM_sk_push(UI_STRING, (st), (val)) +#define sk_UI_STRING_unshift(st, val) SKM_sk_unshift(UI_STRING, (st), (val)) +#define sk_UI_STRING_find(st, val) SKM_sk_find(UI_STRING, (st), (val)) +#define sk_UI_STRING_find_ex(st, val) SKM_sk_find_ex(UI_STRING, (st), (val)) +#define sk_UI_STRING_delete(st, i) SKM_sk_delete(UI_STRING, (st), (i)) +#define sk_UI_STRING_delete_ptr(st, ptr) SKM_sk_delete_ptr(UI_STRING, (st), (ptr)) +#define sk_UI_STRING_insert(st, val, i) SKM_sk_insert(UI_STRING, (st), (val), (i)) +#define sk_UI_STRING_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(UI_STRING, (st), (cmp)) +#define sk_UI_STRING_dup(st) SKM_sk_dup(UI_STRING, st) +#define sk_UI_STRING_pop_free(st, free_func) SKM_sk_pop_free(UI_STRING, (st), (free_func)) +#define sk_UI_STRING_shift(st) SKM_sk_shift(UI_STRING, (st)) +#define sk_UI_STRING_pop(st) SKM_sk_pop(UI_STRING, (st)) +#define sk_UI_STRING_sort(st) SKM_sk_sort(UI_STRING, (st)) +#define sk_UI_STRING_is_sorted(st) SKM_sk_is_sorted(UI_STRING, (st)) + +#define sk_X509_new(cmp) SKM_sk_new(X509, (cmp)) +#define sk_X509_new_null() SKM_sk_new_null(X509) +#define sk_X509_free(st) SKM_sk_free(X509, (st)) +#define sk_X509_num(st) SKM_sk_num(X509, (st)) +#define sk_X509_value(st, i) SKM_sk_value(X509, (st), (i)) +#define sk_X509_set(st, i, val) SKM_sk_set(X509, (st), (i), (val)) +#define sk_X509_zero(st) SKM_sk_zero(X509, (st)) +#define sk_X509_push(st, val) SKM_sk_push(X509, (st), (val)) +#define sk_X509_unshift(st, val) SKM_sk_unshift(X509, (st), (val)) +#define sk_X509_find(st, val) SKM_sk_find(X509, (st), (val)) +#define sk_X509_find_ex(st, val) SKM_sk_find_ex(X509, (st), (val)) +#define sk_X509_delete(st, i) SKM_sk_delete(X509, (st), (i)) +#define sk_X509_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509, (st), (ptr)) +#define sk_X509_insert(st, val, i) SKM_sk_insert(X509, (st), (val), (i)) +#define sk_X509_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509, (st), (cmp)) +#define sk_X509_dup(st) SKM_sk_dup(X509, st) +#define sk_X509_pop_free(st, free_func) SKM_sk_pop_free(X509, (st), (free_func)) +#define sk_X509_shift(st) SKM_sk_shift(X509, (st)) +#define sk_X509_pop(st) SKM_sk_pop(X509, (st)) +#define sk_X509_sort(st) SKM_sk_sort(X509, (st)) +#define sk_X509_is_sorted(st) SKM_sk_is_sorted(X509, (st)) + +#define sk_X509V3_EXT_METHOD_new(cmp) SKM_sk_new(X509V3_EXT_METHOD, (cmp)) +#define sk_X509V3_EXT_METHOD_new_null() SKM_sk_new_null(X509V3_EXT_METHOD) +#define sk_X509V3_EXT_METHOD_free(st) SKM_sk_free(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_num(st) SKM_sk_num(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_value(st, i) SKM_sk_value(X509V3_EXT_METHOD, (st), (i)) +#define sk_X509V3_EXT_METHOD_set(st, i, val) SKM_sk_set(X509V3_EXT_METHOD, (st), (i), (val)) +#define sk_X509V3_EXT_METHOD_zero(st) SKM_sk_zero(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_push(st, val) SKM_sk_push(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_unshift(st, val) SKM_sk_unshift(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_find(st, val) SKM_sk_find(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_find_ex(st, val) SKM_sk_find_ex(X509V3_EXT_METHOD, (st), (val)) +#define sk_X509V3_EXT_METHOD_delete(st, i) SKM_sk_delete(X509V3_EXT_METHOD, (st), (i)) +#define sk_X509V3_EXT_METHOD_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509V3_EXT_METHOD, (st), (ptr)) +#define sk_X509V3_EXT_METHOD_insert(st, val, i) SKM_sk_insert(X509V3_EXT_METHOD, (st), (val), (i)) +#define sk_X509V3_EXT_METHOD_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509V3_EXT_METHOD, (st), (cmp)) +#define sk_X509V3_EXT_METHOD_dup(st) SKM_sk_dup(X509V3_EXT_METHOD, st) +#define sk_X509V3_EXT_METHOD_pop_free(st, free_func) SKM_sk_pop_free(X509V3_EXT_METHOD, (st), (free_func)) +#define sk_X509V3_EXT_METHOD_shift(st) SKM_sk_shift(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_pop(st) SKM_sk_pop(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_sort(st) SKM_sk_sort(X509V3_EXT_METHOD, (st)) +#define sk_X509V3_EXT_METHOD_is_sorted(st) SKM_sk_is_sorted(X509V3_EXT_METHOD, (st)) + +#define sk_X509_ALGOR_new(cmp) SKM_sk_new(X509_ALGOR, (cmp)) +#define sk_X509_ALGOR_new_null() SKM_sk_new_null(X509_ALGOR) +#define sk_X509_ALGOR_free(st) SKM_sk_free(X509_ALGOR, (st)) +#define sk_X509_ALGOR_num(st) SKM_sk_num(X509_ALGOR, (st)) +#define sk_X509_ALGOR_value(st, i) SKM_sk_value(X509_ALGOR, (st), (i)) +#define sk_X509_ALGOR_set(st, i, val) SKM_sk_set(X509_ALGOR, (st), (i), (val)) +#define sk_X509_ALGOR_zero(st) SKM_sk_zero(X509_ALGOR, (st)) +#define sk_X509_ALGOR_push(st, val) SKM_sk_push(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_unshift(st, val) SKM_sk_unshift(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_find(st, val) SKM_sk_find(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_find_ex(st, val) SKM_sk_find_ex(X509_ALGOR, (st), (val)) +#define sk_X509_ALGOR_delete(st, i) SKM_sk_delete(X509_ALGOR, (st), (i)) +#define sk_X509_ALGOR_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ALGOR, (st), (ptr)) +#define sk_X509_ALGOR_insert(st, val, i) SKM_sk_insert(X509_ALGOR, (st), (val), (i)) +#define sk_X509_ALGOR_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ALGOR, (st), (cmp)) +#define sk_X509_ALGOR_dup(st) SKM_sk_dup(X509_ALGOR, st) +#define sk_X509_ALGOR_pop_free(st, free_func) SKM_sk_pop_free(X509_ALGOR, (st), (free_func)) +#define sk_X509_ALGOR_shift(st) SKM_sk_shift(X509_ALGOR, (st)) +#define sk_X509_ALGOR_pop(st) SKM_sk_pop(X509_ALGOR, (st)) +#define sk_X509_ALGOR_sort(st) SKM_sk_sort(X509_ALGOR, (st)) +#define sk_X509_ALGOR_is_sorted(st) SKM_sk_is_sorted(X509_ALGOR, (st)) + +#define sk_X509_ATTRIBUTE_new(cmp) SKM_sk_new(X509_ATTRIBUTE, (cmp)) +#define sk_X509_ATTRIBUTE_new_null() SKM_sk_new_null(X509_ATTRIBUTE) +#define sk_X509_ATTRIBUTE_free(st) SKM_sk_free(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_num(st) SKM_sk_num(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_value(st, i) SKM_sk_value(X509_ATTRIBUTE, (st), (i)) +#define sk_X509_ATTRIBUTE_set(st, i, val) SKM_sk_set(X509_ATTRIBUTE, (st), (i), (val)) +#define sk_X509_ATTRIBUTE_zero(st) SKM_sk_zero(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_push(st, val) SKM_sk_push(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_unshift(st, val) SKM_sk_unshift(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_find(st, val) SKM_sk_find(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_find_ex(st, val) SKM_sk_find_ex(X509_ATTRIBUTE, (st), (val)) +#define sk_X509_ATTRIBUTE_delete(st, i) SKM_sk_delete(X509_ATTRIBUTE, (st), (i)) +#define sk_X509_ATTRIBUTE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_ATTRIBUTE, (st), (ptr)) +#define sk_X509_ATTRIBUTE_insert(st, val, i) SKM_sk_insert(X509_ATTRIBUTE, (st), (val), (i)) +#define sk_X509_ATTRIBUTE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_ATTRIBUTE, (st), (cmp)) +#define sk_X509_ATTRIBUTE_dup(st) SKM_sk_dup(X509_ATTRIBUTE, st) +#define sk_X509_ATTRIBUTE_pop_free(st, free_func) SKM_sk_pop_free(X509_ATTRIBUTE, (st), (free_func)) +#define sk_X509_ATTRIBUTE_shift(st) SKM_sk_shift(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_pop(st) SKM_sk_pop(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_sort(st) SKM_sk_sort(X509_ATTRIBUTE, (st)) +#define sk_X509_ATTRIBUTE_is_sorted(st) SKM_sk_is_sorted(X509_ATTRIBUTE, (st)) + +#define sk_X509_CRL_new(cmp) SKM_sk_new(X509_CRL, (cmp)) +#define sk_X509_CRL_new_null() SKM_sk_new_null(X509_CRL) +#define sk_X509_CRL_free(st) SKM_sk_free(X509_CRL, (st)) +#define sk_X509_CRL_num(st) SKM_sk_num(X509_CRL, (st)) +#define sk_X509_CRL_value(st, i) SKM_sk_value(X509_CRL, (st), (i)) +#define sk_X509_CRL_set(st, i, val) SKM_sk_set(X509_CRL, (st), (i), (val)) +#define sk_X509_CRL_zero(st) SKM_sk_zero(X509_CRL, (st)) +#define sk_X509_CRL_push(st, val) SKM_sk_push(X509_CRL, (st), (val)) +#define sk_X509_CRL_unshift(st, val) SKM_sk_unshift(X509_CRL, (st), (val)) +#define sk_X509_CRL_find(st, val) SKM_sk_find(X509_CRL, (st), (val)) +#define sk_X509_CRL_find_ex(st, val) SKM_sk_find_ex(X509_CRL, (st), (val)) +#define sk_X509_CRL_delete(st, i) SKM_sk_delete(X509_CRL, (st), (i)) +#define sk_X509_CRL_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_CRL, (st), (ptr)) +#define sk_X509_CRL_insert(st, val, i) SKM_sk_insert(X509_CRL, (st), (val), (i)) +#define sk_X509_CRL_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_CRL, (st), (cmp)) +#define sk_X509_CRL_dup(st) SKM_sk_dup(X509_CRL, st) +#define sk_X509_CRL_pop_free(st, free_func) SKM_sk_pop_free(X509_CRL, (st), (free_func)) +#define sk_X509_CRL_shift(st) SKM_sk_shift(X509_CRL, (st)) +#define sk_X509_CRL_pop(st) SKM_sk_pop(X509_CRL, (st)) +#define sk_X509_CRL_sort(st) SKM_sk_sort(X509_CRL, (st)) +#define sk_X509_CRL_is_sorted(st) SKM_sk_is_sorted(X509_CRL, (st)) + +#define sk_X509_EXTENSION_new(cmp) SKM_sk_new(X509_EXTENSION, (cmp)) +#define sk_X509_EXTENSION_new_null() SKM_sk_new_null(X509_EXTENSION) +#define sk_X509_EXTENSION_free(st) SKM_sk_free(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_num(st) SKM_sk_num(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_value(st, i) SKM_sk_value(X509_EXTENSION, (st), (i)) +#define sk_X509_EXTENSION_set(st, i, val) SKM_sk_set(X509_EXTENSION, (st), (i), (val)) +#define sk_X509_EXTENSION_zero(st) SKM_sk_zero(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_push(st, val) SKM_sk_push(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_unshift(st, val) SKM_sk_unshift(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_find(st, val) SKM_sk_find(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_find_ex(st, val) SKM_sk_find_ex(X509_EXTENSION, (st), (val)) +#define sk_X509_EXTENSION_delete(st, i) SKM_sk_delete(X509_EXTENSION, (st), (i)) +#define sk_X509_EXTENSION_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_EXTENSION, (st), (ptr)) +#define sk_X509_EXTENSION_insert(st, val, i) SKM_sk_insert(X509_EXTENSION, (st), (val), (i)) +#define sk_X509_EXTENSION_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_EXTENSION, (st), (cmp)) +#define sk_X509_EXTENSION_dup(st) SKM_sk_dup(X509_EXTENSION, st) +#define sk_X509_EXTENSION_pop_free(st, free_func) SKM_sk_pop_free(X509_EXTENSION, (st), (free_func)) +#define sk_X509_EXTENSION_shift(st) SKM_sk_shift(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_pop(st) SKM_sk_pop(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_sort(st) SKM_sk_sort(X509_EXTENSION, (st)) +#define sk_X509_EXTENSION_is_sorted(st) SKM_sk_is_sorted(X509_EXTENSION, (st)) + +#define sk_X509_INFO_new(cmp) SKM_sk_new(X509_INFO, (cmp)) +#define sk_X509_INFO_new_null() SKM_sk_new_null(X509_INFO) +#define sk_X509_INFO_free(st) SKM_sk_free(X509_INFO, (st)) +#define sk_X509_INFO_num(st) SKM_sk_num(X509_INFO, (st)) +#define sk_X509_INFO_value(st, i) SKM_sk_value(X509_INFO, (st), (i)) +#define sk_X509_INFO_set(st, i, val) SKM_sk_set(X509_INFO, (st), (i), (val)) +#define sk_X509_INFO_zero(st) SKM_sk_zero(X509_INFO, (st)) +#define sk_X509_INFO_push(st, val) SKM_sk_push(X509_INFO, (st), (val)) +#define sk_X509_INFO_unshift(st, val) SKM_sk_unshift(X509_INFO, (st), (val)) +#define sk_X509_INFO_find(st, val) SKM_sk_find(X509_INFO, (st), (val)) +#define sk_X509_INFO_find_ex(st, val) SKM_sk_find_ex(X509_INFO, (st), (val)) +#define sk_X509_INFO_delete(st, i) SKM_sk_delete(X509_INFO, (st), (i)) +#define sk_X509_INFO_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_INFO, (st), (ptr)) +#define sk_X509_INFO_insert(st, val, i) SKM_sk_insert(X509_INFO, (st), (val), (i)) +#define sk_X509_INFO_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_INFO, (st), (cmp)) +#define sk_X509_INFO_dup(st) SKM_sk_dup(X509_INFO, st) +#define sk_X509_INFO_pop_free(st, free_func) SKM_sk_pop_free(X509_INFO, (st), (free_func)) +#define sk_X509_INFO_shift(st) SKM_sk_shift(X509_INFO, (st)) +#define sk_X509_INFO_pop(st) SKM_sk_pop(X509_INFO, (st)) +#define sk_X509_INFO_sort(st) SKM_sk_sort(X509_INFO, (st)) +#define sk_X509_INFO_is_sorted(st) SKM_sk_is_sorted(X509_INFO, (st)) + +#define sk_X509_LOOKUP_new(cmp) SKM_sk_new(X509_LOOKUP, (cmp)) +#define sk_X509_LOOKUP_new_null() SKM_sk_new_null(X509_LOOKUP) +#define sk_X509_LOOKUP_free(st) SKM_sk_free(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_num(st) SKM_sk_num(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_value(st, i) SKM_sk_value(X509_LOOKUP, (st), (i)) +#define sk_X509_LOOKUP_set(st, i, val) SKM_sk_set(X509_LOOKUP, (st), (i), (val)) +#define sk_X509_LOOKUP_zero(st) SKM_sk_zero(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_push(st, val) SKM_sk_push(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_unshift(st, val) SKM_sk_unshift(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_find(st, val) SKM_sk_find(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_find_ex(st, val) SKM_sk_find_ex(X509_LOOKUP, (st), (val)) +#define sk_X509_LOOKUP_delete(st, i) SKM_sk_delete(X509_LOOKUP, (st), (i)) +#define sk_X509_LOOKUP_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_LOOKUP, (st), (ptr)) +#define sk_X509_LOOKUP_insert(st, val, i) SKM_sk_insert(X509_LOOKUP, (st), (val), (i)) +#define sk_X509_LOOKUP_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_LOOKUP, (st), (cmp)) +#define sk_X509_LOOKUP_dup(st) SKM_sk_dup(X509_LOOKUP, st) +#define sk_X509_LOOKUP_pop_free(st, free_func) SKM_sk_pop_free(X509_LOOKUP, (st), (free_func)) +#define sk_X509_LOOKUP_shift(st) SKM_sk_shift(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_pop(st) SKM_sk_pop(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_sort(st) SKM_sk_sort(X509_LOOKUP, (st)) +#define sk_X509_LOOKUP_is_sorted(st) SKM_sk_is_sorted(X509_LOOKUP, (st)) + +#define sk_X509_NAME_new(cmp) SKM_sk_new(X509_NAME, (cmp)) +#define sk_X509_NAME_new_null() SKM_sk_new_null(X509_NAME) +#define sk_X509_NAME_free(st) SKM_sk_free(X509_NAME, (st)) +#define sk_X509_NAME_num(st) SKM_sk_num(X509_NAME, (st)) +#define sk_X509_NAME_value(st, i) SKM_sk_value(X509_NAME, (st), (i)) +#define sk_X509_NAME_set(st, i, val) SKM_sk_set(X509_NAME, (st), (i), (val)) +#define sk_X509_NAME_zero(st) SKM_sk_zero(X509_NAME, (st)) +#define sk_X509_NAME_push(st, val) SKM_sk_push(X509_NAME, (st), (val)) +#define sk_X509_NAME_unshift(st, val) SKM_sk_unshift(X509_NAME, (st), (val)) +#define sk_X509_NAME_find(st, val) SKM_sk_find(X509_NAME, (st), (val)) +#define sk_X509_NAME_find_ex(st, val) SKM_sk_find_ex(X509_NAME, (st), (val)) +#define sk_X509_NAME_delete(st, i) SKM_sk_delete(X509_NAME, (st), (i)) +#define sk_X509_NAME_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME, (st), (ptr)) +#define sk_X509_NAME_insert(st, val, i) SKM_sk_insert(X509_NAME, (st), (val), (i)) +#define sk_X509_NAME_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME, (st), (cmp)) +#define sk_X509_NAME_dup(st) SKM_sk_dup(X509_NAME, st) +#define sk_X509_NAME_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME, (st), (free_func)) +#define sk_X509_NAME_shift(st) SKM_sk_shift(X509_NAME, (st)) +#define sk_X509_NAME_pop(st) SKM_sk_pop(X509_NAME, (st)) +#define sk_X509_NAME_sort(st) SKM_sk_sort(X509_NAME, (st)) +#define sk_X509_NAME_is_sorted(st) SKM_sk_is_sorted(X509_NAME, (st)) + +#define sk_X509_NAME_ENTRY_new(cmp) SKM_sk_new(X509_NAME_ENTRY, (cmp)) +#define sk_X509_NAME_ENTRY_new_null() SKM_sk_new_null(X509_NAME_ENTRY) +#define sk_X509_NAME_ENTRY_free(st) SKM_sk_free(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_num(st) SKM_sk_num(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_value(st, i) SKM_sk_value(X509_NAME_ENTRY, (st), (i)) +#define sk_X509_NAME_ENTRY_set(st, i, val) SKM_sk_set(X509_NAME_ENTRY, (st), (i), (val)) +#define sk_X509_NAME_ENTRY_zero(st) SKM_sk_zero(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_push(st, val) SKM_sk_push(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_unshift(st, val) SKM_sk_unshift(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_find(st, val) SKM_sk_find(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_find_ex(st, val) SKM_sk_find_ex(X509_NAME_ENTRY, (st), (val)) +#define sk_X509_NAME_ENTRY_delete(st, i) SKM_sk_delete(X509_NAME_ENTRY, (st), (i)) +#define sk_X509_NAME_ENTRY_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_NAME_ENTRY, (st), (ptr)) +#define sk_X509_NAME_ENTRY_insert(st, val, i) SKM_sk_insert(X509_NAME_ENTRY, (st), (val), (i)) +#define sk_X509_NAME_ENTRY_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_NAME_ENTRY, (st), (cmp)) +#define sk_X509_NAME_ENTRY_dup(st) SKM_sk_dup(X509_NAME_ENTRY, st) +#define sk_X509_NAME_ENTRY_pop_free(st, free_func) SKM_sk_pop_free(X509_NAME_ENTRY, (st), (free_func)) +#define sk_X509_NAME_ENTRY_shift(st) SKM_sk_shift(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_pop(st) SKM_sk_pop(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_sort(st) SKM_sk_sort(X509_NAME_ENTRY, (st)) +#define sk_X509_NAME_ENTRY_is_sorted(st) SKM_sk_is_sorted(X509_NAME_ENTRY, (st)) + +#define sk_X509_OBJECT_new(cmp) SKM_sk_new(X509_OBJECT, (cmp)) +#define sk_X509_OBJECT_new_null() SKM_sk_new_null(X509_OBJECT) +#define sk_X509_OBJECT_free(st) SKM_sk_free(X509_OBJECT, (st)) +#define sk_X509_OBJECT_num(st) SKM_sk_num(X509_OBJECT, (st)) +#define sk_X509_OBJECT_value(st, i) SKM_sk_value(X509_OBJECT, (st), (i)) +#define sk_X509_OBJECT_set(st, i, val) SKM_sk_set(X509_OBJECT, (st), (i), (val)) +#define sk_X509_OBJECT_zero(st) SKM_sk_zero(X509_OBJECT, (st)) +#define sk_X509_OBJECT_push(st, val) SKM_sk_push(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_unshift(st, val) SKM_sk_unshift(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_find(st, val) SKM_sk_find(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_find_ex(st, val) SKM_sk_find_ex(X509_OBJECT, (st), (val)) +#define sk_X509_OBJECT_delete(st, i) SKM_sk_delete(X509_OBJECT, (st), (i)) +#define sk_X509_OBJECT_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_OBJECT, (st), (ptr)) +#define sk_X509_OBJECT_insert(st, val, i) SKM_sk_insert(X509_OBJECT, (st), (val), (i)) +#define sk_X509_OBJECT_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_OBJECT, (st), (cmp)) +#define sk_X509_OBJECT_dup(st) SKM_sk_dup(X509_OBJECT, st) +#define sk_X509_OBJECT_pop_free(st, free_func) SKM_sk_pop_free(X509_OBJECT, (st), (free_func)) +#define sk_X509_OBJECT_shift(st) SKM_sk_shift(X509_OBJECT, (st)) +#define sk_X509_OBJECT_pop(st) SKM_sk_pop(X509_OBJECT, (st)) +#define sk_X509_OBJECT_sort(st) SKM_sk_sort(X509_OBJECT, (st)) +#define sk_X509_OBJECT_is_sorted(st) SKM_sk_is_sorted(X509_OBJECT, (st)) + +#define sk_X509_PURPOSE_new(cmp) SKM_sk_new(X509_PURPOSE, (cmp)) +#define sk_X509_PURPOSE_new_null() SKM_sk_new_null(X509_PURPOSE) +#define sk_X509_PURPOSE_free(st) SKM_sk_free(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_num(st) SKM_sk_num(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_value(st, i) SKM_sk_value(X509_PURPOSE, (st), (i)) +#define sk_X509_PURPOSE_set(st, i, val) SKM_sk_set(X509_PURPOSE, (st), (i), (val)) +#define sk_X509_PURPOSE_zero(st) SKM_sk_zero(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_push(st, val) SKM_sk_push(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_unshift(st, val) SKM_sk_unshift(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_find(st, val) SKM_sk_find(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_find_ex(st, val) SKM_sk_find_ex(X509_PURPOSE, (st), (val)) +#define sk_X509_PURPOSE_delete(st, i) SKM_sk_delete(X509_PURPOSE, (st), (i)) +#define sk_X509_PURPOSE_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_PURPOSE, (st), (ptr)) +#define sk_X509_PURPOSE_insert(st, val, i) SKM_sk_insert(X509_PURPOSE, (st), (val), (i)) +#define sk_X509_PURPOSE_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_PURPOSE, (st), (cmp)) +#define sk_X509_PURPOSE_dup(st) SKM_sk_dup(X509_PURPOSE, st) +#define sk_X509_PURPOSE_pop_free(st, free_func) SKM_sk_pop_free(X509_PURPOSE, (st), (free_func)) +#define sk_X509_PURPOSE_shift(st) SKM_sk_shift(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_pop(st) SKM_sk_pop(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_sort(st) SKM_sk_sort(X509_PURPOSE, (st)) +#define sk_X509_PURPOSE_is_sorted(st) SKM_sk_is_sorted(X509_PURPOSE, (st)) + +#define sk_X509_REVOKED_new(cmp) SKM_sk_new(X509_REVOKED, (cmp)) +#define sk_X509_REVOKED_new_null() SKM_sk_new_null(X509_REVOKED) +#define sk_X509_REVOKED_free(st) SKM_sk_free(X509_REVOKED, (st)) +#define sk_X509_REVOKED_num(st) SKM_sk_num(X509_REVOKED, (st)) +#define sk_X509_REVOKED_value(st, i) SKM_sk_value(X509_REVOKED, (st), (i)) +#define sk_X509_REVOKED_set(st, i, val) SKM_sk_set(X509_REVOKED, (st), (i), (val)) +#define sk_X509_REVOKED_zero(st) SKM_sk_zero(X509_REVOKED, (st)) +#define sk_X509_REVOKED_push(st, val) SKM_sk_push(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_unshift(st, val) SKM_sk_unshift(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_find(st, val) SKM_sk_find(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_find_ex(st, val) SKM_sk_find_ex(X509_REVOKED, (st), (val)) +#define sk_X509_REVOKED_delete(st, i) SKM_sk_delete(X509_REVOKED, (st), (i)) +#define sk_X509_REVOKED_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_REVOKED, (st), (ptr)) +#define sk_X509_REVOKED_insert(st, val, i) SKM_sk_insert(X509_REVOKED, (st), (val), (i)) +#define sk_X509_REVOKED_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_REVOKED, (st), (cmp)) +#define sk_X509_REVOKED_dup(st) SKM_sk_dup(X509_REVOKED, st) +#define sk_X509_REVOKED_pop_free(st, free_func) SKM_sk_pop_free(X509_REVOKED, (st), (free_func)) +#define sk_X509_REVOKED_shift(st) SKM_sk_shift(X509_REVOKED, (st)) +#define sk_X509_REVOKED_pop(st) SKM_sk_pop(X509_REVOKED, (st)) +#define sk_X509_REVOKED_sort(st) SKM_sk_sort(X509_REVOKED, (st)) +#define sk_X509_REVOKED_is_sorted(st) SKM_sk_is_sorted(X509_REVOKED, (st)) + +#define sk_X509_TRUST_new(cmp) SKM_sk_new(X509_TRUST, (cmp)) +#define sk_X509_TRUST_new_null() SKM_sk_new_null(X509_TRUST) +#define sk_X509_TRUST_free(st) SKM_sk_free(X509_TRUST, (st)) +#define sk_X509_TRUST_num(st) SKM_sk_num(X509_TRUST, (st)) +#define sk_X509_TRUST_value(st, i) SKM_sk_value(X509_TRUST, (st), (i)) +#define sk_X509_TRUST_set(st, i, val) SKM_sk_set(X509_TRUST, (st), (i), (val)) +#define sk_X509_TRUST_zero(st) SKM_sk_zero(X509_TRUST, (st)) +#define sk_X509_TRUST_push(st, val) SKM_sk_push(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_unshift(st, val) SKM_sk_unshift(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_find(st, val) SKM_sk_find(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_find_ex(st, val) SKM_sk_find_ex(X509_TRUST, (st), (val)) +#define sk_X509_TRUST_delete(st, i) SKM_sk_delete(X509_TRUST, (st), (i)) +#define sk_X509_TRUST_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_TRUST, (st), (ptr)) +#define sk_X509_TRUST_insert(st, val, i) SKM_sk_insert(X509_TRUST, (st), (val), (i)) +#define sk_X509_TRUST_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_TRUST, (st), (cmp)) +#define sk_X509_TRUST_dup(st) SKM_sk_dup(X509_TRUST, st) +#define sk_X509_TRUST_pop_free(st, free_func) SKM_sk_pop_free(X509_TRUST, (st), (free_func)) +#define sk_X509_TRUST_shift(st) SKM_sk_shift(X509_TRUST, (st)) +#define sk_X509_TRUST_pop(st) SKM_sk_pop(X509_TRUST, (st)) +#define sk_X509_TRUST_sort(st) SKM_sk_sort(X509_TRUST, (st)) +#define sk_X509_TRUST_is_sorted(st) SKM_sk_is_sorted(X509_TRUST, (st)) + +#define sk_X509_VERIFY_PARAM_new(cmp) SKM_sk_new(X509_VERIFY_PARAM, (cmp)) +#define sk_X509_VERIFY_PARAM_new_null() SKM_sk_new_null(X509_VERIFY_PARAM) +#define sk_X509_VERIFY_PARAM_free(st) SKM_sk_free(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_num(st) SKM_sk_num(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_value(st, i) SKM_sk_value(X509_VERIFY_PARAM, (st), (i)) +#define sk_X509_VERIFY_PARAM_set(st, i, val) SKM_sk_set(X509_VERIFY_PARAM, (st), (i), (val)) +#define sk_X509_VERIFY_PARAM_zero(st) SKM_sk_zero(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_push(st, val) SKM_sk_push(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_unshift(st, val) SKM_sk_unshift(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_find(st, val) SKM_sk_find(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_find_ex(st, val) SKM_sk_find_ex(X509_VERIFY_PARAM, (st), (val)) +#define sk_X509_VERIFY_PARAM_delete(st, i) SKM_sk_delete(X509_VERIFY_PARAM, (st), (i)) +#define sk_X509_VERIFY_PARAM_delete_ptr(st, ptr) SKM_sk_delete_ptr(X509_VERIFY_PARAM, (st), (ptr)) +#define sk_X509_VERIFY_PARAM_insert(st, val, i) SKM_sk_insert(X509_VERIFY_PARAM, (st), (val), (i)) +#define sk_X509_VERIFY_PARAM_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(X509_VERIFY_PARAM, (st), (cmp)) +#define sk_X509_VERIFY_PARAM_dup(st) SKM_sk_dup(X509_VERIFY_PARAM, st) +#define sk_X509_VERIFY_PARAM_pop_free(st, free_func) SKM_sk_pop_free(X509_VERIFY_PARAM, (st), (free_func)) +#define sk_X509_VERIFY_PARAM_shift(st) SKM_sk_shift(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_pop(st) SKM_sk_pop(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_sort(st) SKM_sk_sort(X509_VERIFY_PARAM, (st)) +#define sk_X509_VERIFY_PARAM_is_sorted(st) SKM_sk_is_sorted(X509_VERIFY_PARAM, (st)) + +#define sk_void_new(cmp) SKM_sk_new(void, (cmp)) +#define sk_void_new_null() SKM_sk_new_null(void) +#define sk_void_free(st) SKM_sk_free(void, (st)) +#define sk_void_num(st) SKM_sk_num(void, (st)) +#define sk_void_value(st, i) SKM_sk_value(void, (st), (i)) +#define sk_void_set(st, i, val) SKM_sk_set(void, (st), (i), (val)) +#define sk_void_zero(st) SKM_sk_zero(void, (st)) +#define sk_void_push(st, val) SKM_sk_push(void, (st), (val)) +#define sk_void_unshift(st, val) SKM_sk_unshift(void, (st), (val)) +#define sk_void_find(st, val) SKM_sk_find(void, (st), (val)) +#define sk_void_find_ex(st, val) SKM_sk_find_ex(void, (st), (val)) +#define sk_void_delete(st, i) SKM_sk_delete(void, (st), (i)) +#define sk_void_delete_ptr(st, ptr) SKM_sk_delete_ptr(void, (st), (ptr)) +#define sk_void_insert(st, val, i) SKM_sk_insert(void, (st), (val), (i)) +#define sk_void_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(void, (st), (cmp)) +#define sk_void_dup(st) SKM_sk_dup(void, st) +#define sk_void_pop_free(st, free_func) SKM_sk_pop_free(void, (st), (free_func)) +#define sk_void_shift(st) SKM_sk_shift(void, (st)) +#define sk_void_pop(st) SKM_sk_pop(void, (st)) +#define sk_void_sort(st) SKM_sk_sort(void, (st)) +#define sk_void_is_sorted(st) SKM_sk_is_sorted(void, (st)) + +#define sk_OPENSSL_STRING_new(cmp) ((STACK_OF(OPENSSL_STRING) *)sk_new(CHECKED_SK_CMP_FUNC(char, cmp))) +#define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null()) +#define sk_OPENSSL_STRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +#define sk_OPENSSL_STRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +#define sk_OPENSSL_STRING_value(st, i) ((OPENSSL_STRING)sk_value(CHECKED_STACK_OF(OPENSSL_STRING, st), i)) +#define sk_OPENSSL_STRING_num(st) SKM_sk_num(OPENSSL_STRING, st) +#define sk_OPENSSL_STRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_FREE_FUNC2(OPENSSL_STRING, free_func)) +#define sk_OPENSSL_STRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val), i) +#define sk_OPENSSL_STRING_free(st) SKM_sk_free(OPENSSL_STRING, st) +#define sk_OPENSSL_STRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_STRING, st), i, CHECKED_PTR_OF(char, val)) +#define sk_OPENSSL_STRING_zero(st) SKM_sk_zero(OPENSSL_STRING, (st)) +#define sk_OPENSSL_STRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, val)) +#define sk_OPENSSL_STRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_STRING), st), CHECKED_CONST_PTR_OF(char, val)) +#define sk_OPENSSL_STRING_delete(st, i) SKM_sk_delete(OPENSSL_STRING, (st), (i)) +#define sk_OPENSSL_STRING_delete_ptr(st, ptr) (OPENSSL_STRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_PTR_OF(char, ptr)) +#define sk_OPENSSL_STRING_set_cmp_func(st, cmp) \ + ((int (*)(const char * const *,const char * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_STRING, st), CHECKED_SK_CMP_FUNC(char, cmp))) +#define sk_OPENSSL_STRING_dup(st) SKM_sk_dup(OPENSSL_STRING, st) +#define sk_OPENSSL_STRING_shift(st) SKM_sk_shift(OPENSSL_STRING, (st)) +#define sk_OPENSSL_STRING_pop(st) (char *)sk_pop(CHECKED_STACK_OF(OPENSSL_STRING, st)) +#define sk_OPENSSL_STRING_sort(st) SKM_sk_sort(OPENSSL_STRING, (st)) +#define sk_OPENSSL_STRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_STRING, (st)) + +#define sk_OPENSSL_PSTRING_new(cmp) ((STACK_OF(OPENSSL_PSTRING) *)sk_new(CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp))) +#define sk_OPENSSL_PSTRING_new_null() ((STACK_OF(OPENSSL_PSTRING) *)sk_new_null()) +#define sk_OPENSSL_PSTRING_push(st, val) sk_push(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +#define sk_OPENSSL_PSTRING_find(st, val) sk_find(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +#define sk_OPENSSL_PSTRING_value(st, i) ((OPENSSL_PSTRING)sk_value(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i)) +#define sk_OPENSSL_PSTRING_num(st) SKM_sk_num(OPENSSL_PSTRING, st) +#define sk_OPENSSL_PSTRING_pop_free(st, free_func) sk_pop_free(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_FREE_FUNC2(OPENSSL_PSTRING, free_func)) +#define sk_OPENSSL_PSTRING_insert(st, val, i) sk_insert(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val), i) +#define sk_OPENSSL_PSTRING_free(st) SKM_sk_free(OPENSSL_PSTRING, st) +#define sk_OPENSSL_PSTRING_set(st, i, val) sk_set(CHECKED_STACK_OF(OPENSSL_PSTRING, st), i, CHECKED_PTR_OF(OPENSSL_STRING, val)) +#define sk_OPENSSL_PSTRING_zero(st) SKM_sk_zero(OPENSSL_PSTRING, (st)) +#define sk_OPENSSL_PSTRING_unshift(st, val) sk_unshift(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, val)) +#define sk_OPENSSL_PSTRING_find_ex(st, val) sk_find_ex((_STACK *)CHECKED_CONST_PTR_OF(STACK_OF(OPENSSL_PSTRING), st), CHECKED_CONST_PTR_OF(OPENSSL_STRING, val)) +#define sk_OPENSSL_PSTRING_delete(st, i) SKM_sk_delete(OPENSSL_PSTRING, (st), (i)) +#define sk_OPENSSL_PSTRING_delete_ptr(st, ptr) (OPENSSL_PSTRING *)sk_delete_ptr(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_PTR_OF(OPENSSL_STRING, ptr)) +#define sk_OPENSSL_PSTRING_set_cmp_func(st, cmp) \ + ((int (*)(const OPENSSL_STRING * const *,const OPENSSL_STRING * const *)) \ + sk_set_cmp_func(CHECKED_STACK_OF(OPENSSL_PSTRING, st), CHECKED_SK_CMP_FUNC(OPENSSL_STRING, cmp))) +#define sk_OPENSSL_PSTRING_dup(st) SKM_sk_dup(OPENSSL_PSTRING, st) +#define sk_OPENSSL_PSTRING_shift(st) SKM_sk_shift(OPENSSL_PSTRING, (st)) +#define sk_OPENSSL_PSTRING_pop(st) (OPENSSL_STRING *)sk_pop(CHECKED_STACK_OF(OPENSSL_PSTRING, st)) +#define sk_OPENSSL_PSTRING_sort(st) SKM_sk_sort(OPENSSL_PSTRING, (st)) +#define sk_OPENSSL_PSTRING_is_sorted(st) SKM_sk_is_sorted(OPENSSL_PSTRING, (st)) + +#define lh_ADDED_OBJ_new() LHM_lh_new(ADDED_OBJ,added_obj) +#define lh_ADDED_OBJ_insert(lh,inst) LHM_lh_insert(ADDED_OBJ,lh,inst) +#define lh_ADDED_OBJ_retrieve(lh,inst) LHM_lh_retrieve(ADDED_OBJ,lh,inst) +#define lh_ADDED_OBJ_delete(lh,inst) LHM_lh_delete(ADDED_OBJ,lh,inst) +#define lh_ADDED_OBJ_doall(lh,fn) LHM_lh_doall(ADDED_OBJ,lh,fn) +#define lh_ADDED_OBJ_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ADDED_OBJ,lh,fn,arg_type,arg) +#define lh_ADDED_OBJ_error(lh) LHM_lh_error(ADDED_OBJ,lh) +#define lh_ADDED_OBJ_num_items(lh) LHM_lh_num_items(ADDED_OBJ,lh) +#define lh_ADDED_OBJ_down_load(lh) LHM_lh_down_load(ADDED_OBJ,lh) +#define lh_ADDED_OBJ_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ADDED_OBJ,lh,out) +#define lh_ADDED_OBJ_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ADDED_OBJ,lh,out) +#define lh_ADDED_OBJ_stats_bio(lh,out) \ + LHM_lh_stats_bio(ADDED_OBJ,lh,out) +#define lh_ADDED_OBJ_free(lh) LHM_lh_free(ADDED_OBJ,lh) + +#define lh_CONF_VALUE_new() LHM_lh_new(CONF_VALUE,conf_value) +#define lh_CONF_VALUE_insert(lh,inst) LHM_lh_insert(CONF_VALUE,lh,inst) +#define lh_CONF_VALUE_retrieve(lh,inst) LHM_lh_retrieve(CONF_VALUE,lh,inst) +#define lh_CONF_VALUE_delete(lh,inst) LHM_lh_delete(CONF_VALUE,lh,inst) +#define lh_CONF_VALUE_doall(lh,fn) LHM_lh_doall(CONF_VALUE,lh,fn) +#define lh_CONF_VALUE_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(CONF_VALUE,lh,fn,arg_type,arg) +#define lh_CONF_VALUE_error(lh) LHM_lh_error(CONF_VALUE,lh) +#define lh_CONF_VALUE_num_items(lh) LHM_lh_num_items(CONF_VALUE,lh) +#define lh_CONF_VALUE_down_load(lh) LHM_lh_down_load(CONF_VALUE,lh) +#define lh_CONF_VALUE_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(CONF_VALUE,lh,out) +#define lh_CONF_VALUE_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(CONF_VALUE,lh,out) +#define lh_CONF_VALUE_stats_bio(lh,out) \ + LHM_lh_stats_bio(CONF_VALUE,lh,out) +#define lh_CONF_VALUE_free(lh) LHM_lh_free(CONF_VALUE,lh) + +#define lh_ERR_STATE_new() LHM_lh_new(ERR_STATE,err_state) +#define lh_ERR_STATE_insert(lh,inst) LHM_lh_insert(ERR_STATE,lh,inst) +#define lh_ERR_STATE_retrieve(lh,inst) LHM_lh_retrieve(ERR_STATE,lh,inst) +#define lh_ERR_STATE_delete(lh,inst) LHM_lh_delete(ERR_STATE,lh,inst) +#define lh_ERR_STATE_doall(lh,fn) LHM_lh_doall(ERR_STATE,lh,fn) +#define lh_ERR_STATE_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ERR_STATE,lh,fn,arg_type,arg) +#define lh_ERR_STATE_error(lh) LHM_lh_error(ERR_STATE,lh) +#define lh_ERR_STATE_num_items(lh) LHM_lh_num_items(ERR_STATE,lh) +#define lh_ERR_STATE_down_load(lh) LHM_lh_down_load(ERR_STATE,lh) +#define lh_ERR_STATE_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ERR_STATE,lh,out) +#define lh_ERR_STATE_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ERR_STATE,lh,out) +#define lh_ERR_STATE_stats_bio(lh,out) \ + LHM_lh_stats_bio(ERR_STATE,lh,out) +#define lh_ERR_STATE_free(lh) LHM_lh_free(ERR_STATE,lh) + +#define lh_ERR_STRING_DATA_new() LHM_lh_new(ERR_STRING_DATA,err_string_data) +#define lh_ERR_STRING_DATA_insert(lh,inst) LHM_lh_insert(ERR_STRING_DATA,lh,inst) +#define lh_ERR_STRING_DATA_retrieve(lh,inst) LHM_lh_retrieve(ERR_STRING_DATA,lh,inst) +#define lh_ERR_STRING_DATA_delete(lh,inst) LHM_lh_delete(ERR_STRING_DATA,lh,inst) +#define lh_ERR_STRING_DATA_doall(lh,fn) LHM_lh_doall(ERR_STRING_DATA,lh,fn) +#define lh_ERR_STRING_DATA_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(ERR_STRING_DATA,lh,fn,arg_type,arg) +#define lh_ERR_STRING_DATA_error(lh) LHM_lh_error(ERR_STRING_DATA,lh) +#define lh_ERR_STRING_DATA_num_items(lh) LHM_lh_num_items(ERR_STRING_DATA,lh) +#define lh_ERR_STRING_DATA_down_load(lh) LHM_lh_down_load(ERR_STRING_DATA,lh) +#define lh_ERR_STRING_DATA_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(ERR_STRING_DATA,lh,out) +#define lh_ERR_STRING_DATA_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(ERR_STRING_DATA,lh,out) +#define lh_ERR_STRING_DATA_stats_bio(lh,out) \ + LHM_lh_stats_bio(ERR_STRING_DATA,lh,out) +#define lh_ERR_STRING_DATA_free(lh) LHM_lh_free(ERR_STRING_DATA,lh) + +#define lh_EX_CLASS_ITEM_new() LHM_lh_new(EX_CLASS_ITEM,ex_class_item) +#define lh_EX_CLASS_ITEM_insert(lh,inst) LHM_lh_insert(EX_CLASS_ITEM,lh,inst) +#define lh_EX_CLASS_ITEM_retrieve(lh,inst) LHM_lh_retrieve(EX_CLASS_ITEM,lh,inst) +#define lh_EX_CLASS_ITEM_delete(lh,inst) LHM_lh_delete(EX_CLASS_ITEM,lh,inst) +#define lh_EX_CLASS_ITEM_doall(lh,fn) LHM_lh_doall(EX_CLASS_ITEM,lh,fn) +#define lh_EX_CLASS_ITEM_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(EX_CLASS_ITEM,lh,fn,arg_type,arg) +#define lh_EX_CLASS_ITEM_error(lh) LHM_lh_error(EX_CLASS_ITEM,lh) +#define lh_EX_CLASS_ITEM_num_items(lh) LHM_lh_num_items(EX_CLASS_ITEM,lh) +#define lh_EX_CLASS_ITEM_down_load(lh) LHM_lh_down_load(EX_CLASS_ITEM,lh) +#define lh_EX_CLASS_ITEM_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(EX_CLASS_ITEM,lh,out) +#define lh_EX_CLASS_ITEM_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(EX_CLASS_ITEM,lh,out) +#define lh_EX_CLASS_ITEM_stats_bio(lh,out) \ + LHM_lh_stats_bio(EX_CLASS_ITEM,lh,out) +#define lh_EX_CLASS_ITEM_free(lh) LHM_lh_free(EX_CLASS_ITEM,lh) + +#define lh_FUNCTION_new() LHM_lh_new(FUNCTION,function) +#define lh_FUNCTION_insert(lh,inst) LHM_lh_insert(FUNCTION,lh,inst) +#define lh_FUNCTION_retrieve(lh,inst) LHM_lh_retrieve(FUNCTION,lh,inst) +#define lh_FUNCTION_delete(lh,inst) LHM_lh_delete(FUNCTION,lh,inst) +#define lh_FUNCTION_doall(lh,fn) LHM_lh_doall(FUNCTION,lh,fn) +#define lh_FUNCTION_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(FUNCTION,lh,fn,arg_type,arg) +#define lh_FUNCTION_error(lh) LHM_lh_error(FUNCTION,lh) +#define lh_FUNCTION_num_items(lh) LHM_lh_num_items(FUNCTION,lh) +#define lh_FUNCTION_down_load(lh) LHM_lh_down_load(FUNCTION,lh) +#define lh_FUNCTION_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(FUNCTION,lh,out) +#define lh_FUNCTION_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(FUNCTION,lh,out) +#define lh_FUNCTION_stats_bio(lh,out) \ + LHM_lh_stats_bio(FUNCTION,lh,out) +#define lh_FUNCTION_free(lh) LHM_lh_free(FUNCTION,lh) + +#define lh_OBJ_NAME_new() LHM_lh_new(OBJ_NAME,obj_name) +#define lh_OBJ_NAME_insert(lh,inst) LHM_lh_insert(OBJ_NAME,lh,inst) +#define lh_OBJ_NAME_retrieve(lh,inst) LHM_lh_retrieve(OBJ_NAME,lh,inst) +#define lh_OBJ_NAME_delete(lh,inst) LHM_lh_delete(OBJ_NAME,lh,inst) +#define lh_OBJ_NAME_doall(lh,fn) LHM_lh_doall(OBJ_NAME,lh,fn) +#define lh_OBJ_NAME_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(OBJ_NAME,lh,fn,arg_type,arg) +#define lh_OBJ_NAME_error(lh) LHM_lh_error(OBJ_NAME,lh) +#define lh_OBJ_NAME_num_items(lh) LHM_lh_num_items(OBJ_NAME,lh) +#define lh_OBJ_NAME_down_load(lh) LHM_lh_down_load(OBJ_NAME,lh) +#define lh_OBJ_NAME_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(OBJ_NAME,lh,out) +#define lh_OBJ_NAME_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(OBJ_NAME,lh,out) +#define lh_OBJ_NAME_stats_bio(lh,out) \ + LHM_lh_stats_bio(OBJ_NAME,lh,out) +#define lh_OBJ_NAME_free(lh) LHM_lh_free(OBJ_NAME,lh) + +#define lh_OPENSSL_STRING_new() LHM_lh_new(OPENSSL_STRING,openssl_string) +#define lh_OPENSSL_STRING_insert(lh,inst) LHM_lh_insert(OPENSSL_STRING,lh,inst) +#define lh_OPENSSL_STRING_retrieve(lh,inst) LHM_lh_retrieve(OPENSSL_STRING,lh,inst) +#define lh_OPENSSL_STRING_delete(lh,inst) LHM_lh_delete(OPENSSL_STRING,lh,inst) +#define lh_OPENSSL_STRING_doall(lh,fn) LHM_lh_doall(OPENSSL_STRING,lh,fn) +#define lh_OPENSSL_STRING_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(OPENSSL_STRING,lh,fn,arg_type,arg) +#define lh_OPENSSL_STRING_error(lh) LHM_lh_error(OPENSSL_STRING,lh) +#define lh_OPENSSL_STRING_num_items(lh) LHM_lh_num_items(OPENSSL_STRING,lh) +#define lh_OPENSSL_STRING_down_load(lh) LHM_lh_down_load(OPENSSL_STRING,lh) +#define lh_OPENSSL_STRING_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(OPENSSL_STRING,lh,out) +#define lh_OPENSSL_STRING_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(OPENSSL_STRING,lh,out) +#define lh_OPENSSL_STRING_stats_bio(lh,out) \ + LHM_lh_stats_bio(OPENSSL_STRING,lh,out) +#define lh_OPENSSL_STRING_free(lh) LHM_lh_free(OPENSSL_STRING,lh) + +#define lh_SSL_SESSION_new() LHM_lh_new(SSL_SESSION,ssl_session) +#define lh_SSL_SESSION_insert(lh,inst) LHM_lh_insert(SSL_SESSION,lh,inst) +#define lh_SSL_SESSION_retrieve(lh,inst) LHM_lh_retrieve(SSL_SESSION,lh,inst) +#define lh_SSL_SESSION_delete(lh,inst) LHM_lh_delete(SSL_SESSION,lh,inst) +#define lh_SSL_SESSION_doall(lh,fn) LHM_lh_doall(SSL_SESSION,lh,fn) +#define lh_SSL_SESSION_doall_arg(lh,fn,arg_type,arg) \ + LHM_lh_doall_arg(SSL_SESSION,lh,fn,arg_type,arg) +#define lh_SSL_SESSION_error(lh) LHM_lh_error(SSL_SESSION,lh) +#define lh_SSL_SESSION_num_items(lh) LHM_lh_num_items(SSL_SESSION,lh) +#define lh_SSL_SESSION_down_load(lh) LHM_lh_down_load(SSL_SESSION,lh) +#define lh_SSL_SESSION_node_stats_bio(lh,out) \ + LHM_lh_node_stats_bio(SSL_SESSION,lh,out) +#define lh_SSL_SESSION_node_usage_stats_bio(lh,out) \ + LHM_lh_node_usage_stats_bio(SSL_SESSION,lh,out) +#define lh_SSL_SESSION_stats_bio(lh,out) \ + LHM_lh_stats_bio(SSL_SESSION,lh,out) +#define lh_SSL_SESSION_free(lh) LHM_lh_free(SSL_SESSION,lh) + +#endif /* !defined HEADER_SAFESTACK_H */ diff --git a/include/openssl/sha.h b/include/openssl/sha.h new file mode 100644 index 0000000..e1de79f --- /dev/null +++ b/include/openssl/sha.h @@ -0,0 +1,189 @@ +/* $OpenBSD: sha.h,v 1.22 2023/07/08 07:08:11 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#ifndef HEADER_SHA_H +#define HEADER_SHA_H +#if !defined(HAVE_ATTRIBUTE__BOUNDED__) && !defined(__OpenBSD__) +#define __bounded__(x, y, z) +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(OPENSSL_NO_SHA) || defined(OPENSSL_NO_SHA1) +#error SHA is disabled. +#endif + +/* + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * ! SHA_LONG has to be at least 32 bits wide. ! + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ + +#define SHA_LONG unsigned int + +#define SHA_LBLOCK 16 +#define SHA_CBLOCK (SHA_LBLOCK*4) /* SHA treats input data as a + * contiguous array of 32 bit + * wide big-endian values. */ +#define SHA_LAST_BLOCK (SHA_CBLOCK-8) +#define SHA_DIGEST_LENGTH 20 + +typedef struct SHAstate_st { + SHA_LONG h0, h1, h2, h3, h4; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num; +} SHA_CTX; + +#ifndef OPENSSL_NO_SHA1 +int SHA1_Init(SHA_CTX *c); +int SHA1_Update(SHA_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int SHA1_Final(unsigned char *md, SHA_CTX *c); +unsigned char *SHA1(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +void SHA1_Transform(SHA_CTX *c, const unsigned char *data); +#endif + +#define SHA256_CBLOCK (SHA_LBLOCK*4) /* SHA-256 treats input data as a + * contiguous array of 32 bit + * wide big-endian values. */ +#define SHA224_DIGEST_LENGTH 28 +#define SHA256_DIGEST_LENGTH 32 + +typedef struct SHA256state_st { + SHA_LONG h[8]; + SHA_LONG Nl, Nh; + SHA_LONG data[SHA_LBLOCK]; + unsigned int num, md_len; +} SHA256_CTX; + +#ifndef OPENSSL_NO_SHA256 +int SHA224_Init(SHA256_CTX *c); +int SHA224_Update(SHA256_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int SHA224_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA224(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +int SHA256_Init(SHA256_CTX *c); +int SHA256_Update(SHA256_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int SHA256_Final(unsigned char *md, SHA256_CTX *c); +unsigned char *SHA256(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +void SHA256_Transform(SHA256_CTX *c, const unsigned char *data); +#endif + +#define SHA384_DIGEST_LENGTH 48 +#define SHA512_DIGEST_LENGTH 64 + +#ifndef OPENSSL_NO_SHA512 +/* + * Unlike 32-bit digest algorithms, SHA-512 *relies* on SHA_LONG64 + * being exactly 64-bit wide. See Implementation Notes in sha512.c + * for further details. + */ +#define SHA512_CBLOCK (SHA_LBLOCK*8) /* SHA-512 treats input data as a + * contiguous array of 64 bit + * wide big-endian values. */ +#if defined(_LP64) +#define SHA_LONG64 unsigned long +#define U64(C) C##UL +#else +#define SHA_LONG64 unsigned long long +#define U64(C) C##ULL +#endif + +typedef struct SHA512state_st { + SHA_LONG64 h[8]; + SHA_LONG64 Nl, Nh; + union { + SHA_LONG64 d[SHA_LBLOCK]; + unsigned char p[SHA512_CBLOCK]; + } u; + unsigned int num, md_len; +} SHA512_CTX; +#endif + +#ifndef OPENSSL_NO_SHA512 +int SHA384_Init(SHA512_CTX *c); +int SHA384_Update(SHA512_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int SHA384_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA384(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +int SHA512_Init(SHA512_CTX *c); +int SHA512_Update(SHA512_CTX *c, const void *data, size_t len) + __attribute__ ((__bounded__(__buffer__, 2, 3))); +int SHA512_Final(unsigned char *md, SHA512_CTX *c); +unsigned char *SHA512(const unsigned char *d, size_t n, unsigned char *md) + __attribute__ ((__bounded__(__buffer__, 1, 2))); +void SHA512_Transform(SHA512_CTX *c, const unsigned char *data); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/sm3.h b/include/openssl/sm3.h new file mode 100644 index 0000000..553c64d --- /dev/null +++ b/include/openssl/sm3.h @@ -0,0 +1,53 @@ +/* $OpenBSD: sm3.h,v 1.1 2018/11/11 06:53:31 tb Exp $ */ +/* + * Copyright (c) 2018, Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_SM3_H +#define HEADER_SM3_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_SM3 +#error SM3 is disabled. +#endif + +#define SM3_DIGEST_LENGTH 32 +#define SM3_WORD unsigned int + +#define SM3_CBLOCK 64 +#define SM3_LBLOCK (SM3_CBLOCK / 4) + +typedef struct SM3state_st { + SM3_WORD A, B, C, D, E, F, G, H; + SM3_WORD Nl, Nh; + SM3_WORD data[SM3_LBLOCK]; + unsigned int num; +} SM3_CTX; + +int SM3_Init(SM3_CTX *c); +int SM3_Update(SM3_CTX *c, const void *data, size_t len); +int SM3_Final(unsigned char *md, SM3_CTX *c); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_SM3_H */ diff --git a/include/openssl/sm4.h b/include/openssl/sm4.h new file mode 100644 index 0000000..5931ac7 --- /dev/null +++ b/include/openssl/sm4.h @@ -0,0 +1,51 @@ +/* $OpenBSD: sm4.h,v 1.1 2019/03/17 17:42:37 tb Exp $ */ +/* + * Copyright (c) 2017, 2019 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_SM4_H +#define HEADER_SM4_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef OPENSSL_NO_SM4 +#error SM4 is disabled. +#endif + +#define SM4_DECRYPT 0 +#define SM4_ENCRYPT 1 + +#define SM4_BLOCK_SIZE 16 +#define SM4_KEY_SCHEDULE 32 + +typedef struct sm4_key_st { + unsigned char opaque[128]; +} SM4_KEY; + +int SM4_set_key(const uint8_t *key, SM4_KEY *ks); +void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); +void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_SM4_H */ diff --git a/include/openssl/srtp.h b/include/openssl/srtp.h new file mode 100644 index 0000000..89ce862 --- /dev/null +++ b/include/openssl/srtp.h @@ -0,0 +1,146 @@ +/* $OpenBSD: srtp.h,v 1.7 2021/06/11 15:28:13 landry Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. + * Copyright (C) 2011, RTFM, Inc. + */ + +#ifndef HEADER_D1_SRTP_H +#define HEADER_D1_SRTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRTP_AES128_CM_SHA1_80 0x0001 +#define SRTP_AES128_CM_SHA1_32 0x0002 +#define SRTP_AES128_F8_SHA1_80 0x0003 +#define SRTP_AES128_F8_SHA1_32 0x0004 +#define SRTP_NULL_SHA1_80 0x0005 +#define SRTP_NULL_SHA1_32 0x0006 + +/* AEAD SRTP protection profiles from RFC 7714 */ +#define SRTP_AEAD_AES_128_GCM 0x0007 +#define SRTP_AEAD_AES_256_GCM 0x0008 + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); +int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles); + +STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); +SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h new file mode 100644 index 0000000..acde94c --- /dev/null +++ b/include/openssl/ssl.h @@ -0,0 +1,2362 @@ +/* $OpenBSD: ssl.h,v 1.230 2022/12/26 07:31:44 jmc Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_SSL_H +#define HEADER_SSL_H + +#include + +#include + +#include +#include +#include + +#include + +#ifndef OPENSSL_NO_DEPRECATED +#include +#include +#include + +#ifndef OPENSSL_NO_X509 +#include +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* SSLeay version number for ASN.1 encoding of the session information */ +/* Version 0 - initial version + * Version 1 - added the optional peer certificate + */ +#define SSL_SESSION_ASN1_VERSION 0x0001 + +/* text strings for the ciphers */ +#define SSL_TXT_NULL_WITH_MD5 SSL2_TXT_NULL_WITH_MD5 +#define SSL_TXT_RC4_128_WITH_MD5 SSL2_TXT_RC4_128_WITH_MD5 +#define SSL_TXT_RC4_128_EXPORT40_WITH_MD5 SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 +#define SSL_TXT_RC2_128_CBC_WITH_MD5 SSL2_TXT_RC2_128_CBC_WITH_MD5 +#define SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 +#define SSL_TXT_IDEA_128_CBC_WITH_MD5 SSL2_TXT_IDEA_128_CBC_WITH_MD5 +#define SSL_TXT_DES_64_CBC_WITH_MD5 SSL2_TXT_DES_64_CBC_WITH_MD5 +#define SSL_TXT_DES_64_CBC_WITH_SHA SSL2_TXT_DES_64_CBC_WITH_SHA +#define SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 +#define SSL_TXT_DES_192_EDE3_CBC_WITH_SHA SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA + +/* VRS Additional Kerberos5 entries + */ +#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_RC4_128_SHA SSL3_TXT_KRB5_RC4_128_SHA +#define SSL_TXT_KRB5_IDEA_128_CBC_SHA SSL3_TXT_KRB5_IDEA_128_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +#define SSL_TXT_KRB5_RC4_128_MD5 SSL3_TXT_KRB5_RC4_128_MD5 +#define SSL_TXT_KRB5_IDEA_128_CBC_MD5 SSL3_TXT_KRB5_IDEA_128_CBC_MD5 + +#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +#define SSL_TXT_KRB5_RC2_40_CBC_SHA SSL3_TXT_KRB5_RC2_40_CBC_SHA +#define SSL_TXT_KRB5_RC4_40_SHA SSL3_TXT_KRB5_RC4_40_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +#define SSL_TXT_KRB5_RC2_40_CBC_MD5 SSL3_TXT_KRB5_RC2_40_CBC_MD5 +#define SSL_TXT_KRB5_RC4_40_MD5 SSL3_TXT_KRB5_RC4_40_MD5 + +#define SSL_TXT_KRB5_DES_40_CBC_SHA SSL3_TXT_KRB5_DES_40_CBC_SHA +#define SSL_TXT_KRB5_DES_40_CBC_MD5 SSL3_TXT_KRB5_DES_40_CBC_MD5 +#define SSL_TXT_KRB5_DES_64_CBC_SHA SSL3_TXT_KRB5_DES_64_CBC_SHA +#define SSL_TXT_KRB5_DES_64_CBC_MD5 SSL3_TXT_KRB5_DES_64_CBC_MD5 +#define SSL_TXT_KRB5_DES_192_CBC3_SHA SSL3_TXT_KRB5_DES_192_CBC3_SHA +#define SSL_TXT_KRB5_DES_192_CBC3_MD5 SSL3_TXT_KRB5_DES_192_CBC3_MD5 +#define SSL_MAX_KRB5_PRINCIPAL_LENGTH 256 + +#define SSL_MAX_SSL_SESSION_ID_LENGTH 32 +#define SSL_MAX_SID_CTX_LENGTH 32 + +#define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8) +#define SSL_MAX_KEY_ARG_LENGTH 8 +#define SSL_MAX_MASTER_KEY_LENGTH 48 + + +/* These are used to specify which ciphers to use and not to use */ + +#define SSL_TXT_LOW "LOW" +#define SSL_TXT_MEDIUM "MEDIUM" +#define SSL_TXT_HIGH "HIGH" + +#define SSL_TXT_kFZA "kFZA" /* unused! */ +#define SSL_TXT_aFZA "aFZA" /* unused! */ +#define SSL_TXT_eFZA "eFZA" /* unused! */ +#define SSL_TXT_FZA "FZA" /* unused! */ + +#define SSL_TXT_aNULL "aNULL" +#define SSL_TXT_eNULL "eNULL" +#define SSL_TXT_NULL "NULL" + +#define SSL_TXT_kRSA "kRSA" +#define SSL_TXT_kDHr "kDHr" /* no such ciphersuites supported! */ +#define SSL_TXT_kDHd "kDHd" /* no such ciphersuites supported! */ +#define SSL_TXT_kDH "kDH" /* no such ciphersuites supported! */ +#define SSL_TXT_kEDH "kEDH" +#define SSL_TXT_kKRB5 "kKRB5" +#define SSL_TXT_kECDHr "kECDHr" +#define SSL_TXT_kECDHe "kECDHe" +#define SSL_TXT_kECDH "kECDH" +#define SSL_TXT_kEECDH "kEECDH" +#define SSL_TXT_kPSK "kPSK" +#define SSL_TXT_kGOST "kGOST" +#define SSL_TXT_kSRP "kSRP" + +#define SSL_TXT_aRSA "aRSA" +#define SSL_TXT_aDSS "aDSS" +#define SSL_TXT_aDH "aDH" /* no such ciphersuites supported! */ +#define SSL_TXT_aECDH "aECDH" +#define SSL_TXT_aKRB5 "aKRB5" +#define SSL_TXT_aECDSA "aECDSA" +#define SSL_TXT_aPSK "aPSK" +#define SSL_TXT_aGOST94 "aGOST94" +#define SSL_TXT_aGOST01 "aGOST01" +#define SSL_TXT_aGOST "aGOST" + +#define SSL_TXT_DSS "DSS" +#define SSL_TXT_DH "DH" +#define SSL_TXT_DHE "DHE" /* same as "kDHE:-ADH" */ +#define SSL_TXT_EDH "EDH" /* previous name for DHE */ +#define SSL_TXT_ADH "ADH" +#define SSL_TXT_RSA "RSA" +#define SSL_TXT_ECDH "ECDH" +#define SSL_TXT_ECDHE "ECDHE" /* same as "kECDHE:-AECDH" */ +#define SSL_TXT_EECDH "EECDH" /* previous name for ECDHE */ +#define SSL_TXT_AECDH "AECDH" +#define SSL_TXT_ECDSA "ECDSA" +#define SSL_TXT_KRB5 "KRB5" +#define SSL_TXT_PSK "PSK" +#define SSL_TXT_SRP "SRP" + +#define SSL_TXT_DES "DES" +#define SSL_TXT_3DES "3DES" +#define SSL_TXT_RC4 "RC4" +#define SSL_TXT_RC2 "RC2" +#define SSL_TXT_IDEA "IDEA" +#define SSL_TXT_SEED "SEED" +#define SSL_TXT_AES128 "AES128" +#define SSL_TXT_AES256 "AES256" +#define SSL_TXT_AES "AES" +#define SSL_TXT_AES_GCM "AESGCM" +#define SSL_TXT_CAMELLIA128 "CAMELLIA128" +#define SSL_TXT_CAMELLIA256 "CAMELLIA256" +#define SSL_TXT_CAMELLIA "CAMELLIA" +#define SSL_TXT_CHACHA20 "CHACHA20" + +#define SSL_TXT_AEAD "AEAD" +#define SSL_TXT_MD5 "MD5" +#define SSL_TXT_SHA1 "SHA1" +#define SSL_TXT_SHA "SHA" /* same as "SHA1" */ +#define SSL_TXT_GOST94 "GOST94" +#define SSL_TXT_GOST89MAC "GOST89MAC" +#define SSL_TXT_SHA256 "SHA256" +#define SSL_TXT_SHA384 "SHA384" +#define SSL_TXT_STREEBOG256 "STREEBOG256" +#define SSL_TXT_STREEBOG512 "STREEBOG512" + +#define SSL_TXT_DTLS1 "DTLSv1" +#define SSL_TXT_DTLS1_2 "DTLSv1.2" +#define SSL_TXT_SSLV2 "SSLv2" +#define SSL_TXT_SSLV3 "SSLv3" +#define SSL_TXT_TLSV1 "TLSv1" +#define SSL_TXT_TLSV1_1 "TLSv1.1" +#define SSL_TXT_TLSV1_2 "TLSv1.2" +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_TXT_TLSV1_3 "TLSv1.3" +#endif + +#define SSL_TXT_EXP "EXP" +#define SSL_TXT_EXPORT "EXPORT" + +#define SSL_TXT_ALL "ALL" + +/* + * COMPLEMENTOF* definitions. These identifiers are used to (de-select) + * ciphers normally not being used. + * Example: "RC4" will activate all ciphers using RC4 including ciphers + * without authentication, which would normally disabled by DEFAULT (due + * the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT" + * will make sure that it is also disabled in the specific selection. + * COMPLEMENTOF* identifiers are portable between version, as adjustments + * to the default cipher setup will also be included here. + * + * COMPLEMENTOFDEFAULT does not experience the same special treatment that + * DEFAULT gets, as only selection is being done and no sorting as needed + * for DEFAULT. + */ +#define SSL_TXT_CMPALL "COMPLEMENTOFALL" +#define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT" + +/* The following cipher list is used by default. + * It also is substituted when an application-defined cipher list string + * starts with 'DEFAULT'. */ +#define SSL_DEFAULT_CIPHER_LIST "ALL:!aNULL:!eNULL:!SSLv2" +/* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always + * starts with a reasonable order, and all we have to do for DEFAULT is + * throwing out anonymous and unencrypted ciphersuites! + * (The latter are not actually enabled by ALL, but "ALL:RSA" would enable + * some of them.) + */ + +/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */ +#define SSL_SENT_SHUTDOWN 1 +#define SSL_RECEIVED_SHUTDOWN 2 + + +#define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1 +#define SSL_FILETYPE_PEM X509_FILETYPE_PEM + +/* This is needed to stop compilers complaining about the + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ +typedef struct ssl_st *ssl_crock_st; + +typedef struct ssl_method_st SSL_METHOD; +typedef struct ssl_cipher_st SSL_CIPHER; +typedef struct ssl_session_st SSL_SESSION; + +#if defined(LIBRESSL_HAS_QUIC) || defined(LIBRESSL_INTERNAL) +typedef struct ssl_quic_method_st SSL_QUIC_METHOD; +#endif + +DECLARE_STACK_OF(SSL_CIPHER) + +/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/ +typedef struct srtp_protection_profile_st { + const char *name; + unsigned long id; +} SRTP_PROTECTION_PROFILE; + +DECLARE_STACK_OF(SRTP_PROTECTION_PROFILE) + +typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, + int len, void *arg); +typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, + STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); + +/* Allow initial connection to servers that don't support RI */ +#define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004L + +/* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added + * in OpenSSL 0.9.6d. Usually (depending on the application protocol) + * the workaround is not needed. + * Unfortunately some broken SSL/TLS implementations cannot handle it + * at all, which is why it was previously included in SSL_OP_ALL. + * Now it's not. + */ +#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800L + +/* DTLS options */ +#define SSL_OP_NO_QUERY_MTU 0x00001000L +/* Turn on Cookie Exchange (on relevant for servers) */ +#define SSL_OP_COOKIE_EXCHANGE 0x00002000L +/* Don't use RFC4507 ticket extension */ +#define SSL_OP_NO_TICKET 0x00004000L + +/* As server, disallow session resumption on renegotiation */ +#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000L +/* Disallow client initiated renegotiation. */ +#define SSL_OP_NO_CLIENT_RENEGOTIATION 0x00020000L +/* If set, always create a new key when using tmp_dh parameters */ +#define SSL_OP_SINGLE_DH_USE 0x00100000L +/* Set on servers to choose the cipher according to the server's + * preferences */ +#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L + +#define SSL_OP_NO_TLSv1 0x04000000L +#define SSL_OP_NO_TLSv1_2 0x08000000L +#define SSL_OP_NO_TLSv1_1 0x10000000L + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_OP_NO_TLSv1_3 0x20000000L +#endif + +#define SSL_OP_NO_DTLSv1 0x40000000L +#define SSL_OP_NO_DTLSv1_2 0x80000000L + +/* SSL_OP_ALL: various bug workarounds that should be rather harmless. */ +#define SSL_OP_ALL \ + (SSL_OP_LEGACY_SERVER_CONNECT) + +/* Obsolete flags kept for compatibility. No sane code should use them. */ +#define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x0 +#define SSL_OP_CISCO_ANYCONNECT 0x0 +#define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x0 +#define SSL_OP_EPHEMERAL_RSA 0x0 +#define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0 +#define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0 +#define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0 +#define SSL_OP_NETSCAPE_CA_DN_BUG 0x0 +#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0 +#define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0 +#define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0 +#define SSL_OP_NO_COMPRESSION 0x0 +#define SSL_OP_NO_SSLv2 0x0 +#define SSL_OP_NO_SSLv3 0x0 +#define SSL_OP_PKCS1_CHECK_1 0x0 +#define SSL_OP_PKCS1_CHECK_2 0x0 +#define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x0 +#define SSL_OP_SINGLE_ECDH_USE 0x0 +#define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0 +#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0 +#define SSL_OP_TLSEXT_PADDING 0x0 +#define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0 +#define SSL_OP_TLS_D5_BUG 0x0 +#define SSL_OP_TLS_ROLLBACK_BUG 0x0 + +/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success + * when just a single record has been written): */ +#define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001L +/* Make it possible to retry SSL_write() with changed buffer location + * (buffer contents must stay the same!); this is not the default to avoid + * the misconception that non-blocking SSL_write() behaves like + * non-blocking write(): */ +#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L +/* Never bother the application with retries if the transport + * is blocking: */ +#define SSL_MODE_AUTO_RETRY 0x00000004L +/* Don't attempt to automatically build certificate chain */ +#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L +/* Save RAM by releasing read and write buffers when they're empty. (SSL3 and + * TLS only.) "Released" buffers are put onto a free-list in the context + * or just freed (depending on the context's setting for freelist_max_len). */ +#define SSL_MODE_RELEASE_BUFFERS 0x00000010L + +/* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, + * they cannot be used to clear bits. */ + +#define SSL_CTX_set_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_CTX_clear_options(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +#define SSL_CTX_get_options(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,0,NULL) +#define SSL_set_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL) +#define SSL_clear_options(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_OPTIONS,(op),NULL) +#define SSL_get_options(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_OPTIONS,0,NULL) + +#define SSL_CTX_set_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +#define SSL_CTX_clear_mode(ctx,op) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL) +#define SSL_CTX_get_mode(ctx) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL) +#define SSL_clear_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL) +#define SSL_set_mode(ssl,op) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) +#define SSL_get_mode(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL) +#define SSL_set_mtu(ssl, mtu) \ + SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL) + +#define SSL_get_secure_renegotiation_support(ssl) \ + SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL) + +void SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, + int version, int content_type, const void *buf, size_t len, SSL *ssl, + void *arg)); +void SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, + int content_type, const void *buf, size_t len, SSL *ssl, void *arg)); +#define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +#define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg)) +typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line); +void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb); +SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx); +int SSL_set_num_tickets(SSL *s, size_t num_tickets); +size_t SSL_get_num_tickets(const SSL *s); +int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets); +size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx); +STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s); + +#ifndef LIBRESSL_INTERNAL +struct ssl_aead_ctx_st; +typedef struct ssl_aead_ctx_st SSL_AEAD_CTX; +#endif + +#define SSL_MAX_CERT_LIST_DEFAULT 1024*100 /* 100k max cert list :-) */ + +#define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20) + +/* This callback type is used inside SSL_CTX, SSL, and in the functions that set + * them. It is used to override the generation of SSL/TLS session IDs in a + * server. Return value should be zero on an error, non-zero to proceed. Also, + * callbacks should themselves check if the id they generate is unique otherwise + * the SSL handshake will fail with an error - callbacks can do this using the + * 'ssl' value they're passed by; + * SSL_has_matching_session_id(ssl, id, *id_len) + * The length value passed in is set at the maximum size the session ID can be. + * In SSLv2 this is 16 bytes, whereas SSLv3/TLSv1 it is 32 bytes. The callback + * can alter this length to be less if desired, but under SSLv2 session IDs are + * supposed to be fixed at 16 bytes so the id will be padded after the callback + * returns in this case. It is also an error for the callback to set the size to + * zero. */ +typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id, + unsigned int *id_len); + +typedef struct ssl_comp_st SSL_COMP; + +#ifdef LIBRESSL_INTERNAL +DECLARE_STACK_OF(SSL_COMP) +struct lhash_st_SSL_SESSION { + int dummy; +}; +#endif + +#define SSL_SESS_CACHE_OFF 0x0000 +#define SSL_SESS_CACHE_CLIENT 0x0001 +#define SSL_SESS_CACHE_SERVER 0x0002 +#define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER) +#define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080 +/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */ +#define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100 +#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200 +#define SSL_SESS_CACHE_NO_INTERNAL \ + (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE) + +struct lhash_st_SSL_SESSION *SSL_CTX_sessions(SSL_CTX *ctx); +#define SSL_CTX_sess_number(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL) +#define SSL_CTX_sess_connect(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL) +#define SSL_CTX_sess_connect_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL) +#define SSL_CTX_sess_connect_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL) +#define SSL_CTX_sess_accept_renegotiate(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL) +#define SSL_CTX_sess_accept_good(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL) +#define SSL_CTX_sess_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL) +#define SSL_CTX_sess_cb_hits(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL) +#define SSL_CTX_sess_misses(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL) +#define SSL_CTX_sess_timeouts(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL) +#define SSL_CTX_sess_cache_full(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL) + +void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*new_session_cb)(struct ssl_st *ssl, SSL_SESSION *sess)); +int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st *ssl, + SSL_SESSION *sess); +void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*remove_session_cb)(struct ssl_ctx_st *ctx, SSL_SESSION *sess)); +void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st *ctx, + SSL_SESSION *sess); +void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, + SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, + const unsigned char *data, int len, int *copy)); +SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st *ssl, + const unsigned char *data, int len, int *copy); +void SSL_CTX_set_info_callback(SSL_CTX *ctx, void (*cb)(const SSL *ssl, + int type, int val)); +void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, + int val); +void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)); +int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **x509, + EVP_PKEY **pkey); +#ifndef OPENSSL_NO_ENGINE +int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e); +#endif +void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len)); +void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*app_verify_cookie_cb)(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len)); +void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s, int (*cb)(SSL *ssl, + const unsigned char **out, unsigned int *outlen, void *arg), void *arg); +void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, int (*cb)(SSL *ssl, + unsigned char **out, unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg), void *arg); + +int SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, const unsigned char *client, + unsigned int client_len); +void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned int *len); + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + +int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned int protos_len); +int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned int protos_len); +void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg), void *arg); +void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned int *len); + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md, + const unsigned char **id, size_t *idlen, SSL_SESSION **sess); +void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb); +#endif + +#define SSL_NOTHING 1 +#define SSL_WRITING 2 +#define SSL_READING 3 +#define SSL_X509_LOOKUP 4 + +/* These will only be used when doing non-blocking IO */ +#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING) +#define SSL_want_read(s) (SSL_want(s) == SSL_READING) +#define SSL_want_write(s) (SSL_want(s) == SSL_WRITING) +#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP) + +#define SSL_MAC_FLAG_READ_MAC_STREAM 1 +#define SSL_MAC_FLAG_WRITE_MAC_STREAM 2 + +#ifdef __cplusplus +} +#endif + +#include +#include +#include /* This is mostly sslv3 with a few tweaks */ +#include /* Datagram TLS */ +#include +#include /* Support for the use_srtp extension */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* compatibility */ +#define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)arg)) +#define SSL_get_app_data(s) (SSL_get_ex_data(s,0)) +#define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0,(char *)a)) +#define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0)) +#define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0)) +#define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0,(char *)arg)) + +/* The following are the possible values for ssl->state are are + * used to indicate where we are up to in the SSL connection establishment. + * The macros that follow are about the only things you should need to use + * and even then, only when using non-blocking IO. + * It can also be useful to work out where you were when the connection + * failed */ + +#define SSL_ST_CONNECT 0x1000 +#define SSL_ST_ACCEPT 0x2000 +#define SSL_ST_MASK 0x0FFF +#define SSL_ST_INIT (SSL_ST_CONNECT|SSL_ST_ACCEPT) +#define SSL_ST_BEFORE 0x4000 +#define SSL_ST_OK 0x03 +#define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT) + +#define SSL_CB_LOOP 0x01 +#define SSL_CB_EXIT 0x02 +#define SSL_CB_READ 0x04 +#define SSL_CB_WRITE 0x08 +#define SSL_CB_ALERT 0x4000 /* used in callback */ +#define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ) +#define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE) +#define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP) +#define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT) +#define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP) +#define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT) +#define SSL_CB_HANDSHAKE_START 0x10 +#define SSL_CB_HANDSHAKE_DONE 0x20 + +/* Is the SSL_connection established? */ +#define SSL_get_state(a) (SSL_state((a))) +#define SSL_is_init_finished(a) (SSL_state((a)) == SSL_ST_OK) +#define SSL_in_init(a) (SSL_state((a))&SSL_ST_INIT) +#define SSL_in_before(a) (SSL_state((a))&SSL_ST_BEFORE) +#define SSL_in_connect_init(a) (SSL_state((a))&SSL_ST_CONNECT) +#define SSL_in_accept_init(a) (SSL_state((a))&SSL_ST_ACCEPT) + +/* The following 2 states are kept in ssl->rstate when reads fail, + * you should not need these */ +#define SSL_ST_READ_HEADER 0xF0 +#define SSL_ST_READ_BODY 0xF1 +#define SSL_ST_READ_DONE 0xF2 + +/* Obtain latest Finished message + * -- that we sent (SSL_get_finished) + * -- that we expected from peer (SSL_get_peer_finished). + * Returns length (0 == no Finished so far), copies up to 'count' bytes. */ +size_t SSL_get_finished(const SSL *s, void *buf, size_t count); +size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); + +/* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 2 options + * are 'ored' with SSL_VERIFY_PEER if they are desired */ +#define SSL_VERIFY_NONE 0x00 +#define SSL_VERIFY_PEER 0x01 +#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02 +#define SSL_VERIFY_CLIENT_ONCE 0x04 +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_VERIFY_POST_HANDSHAKE 0x08 + +int SSL_verify_client_post_handshake(SSL *s); +void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val); +void SSL_set_post_handshake_auth(SSL *s, int val); +#endif + +#define OpenSSL_add_ssl_algorithms() SSL_library_init() +#define SSLeay_add_ssl_algorithms() SSL_library_init() + +/* More backward compatibility */ +#define SSL_get_cipher(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +#define SSL_get_cipher_bits(s,np) \ + SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np) +#define SSL_get_cipher_version(s) \ + SSL_CIPHER_get_version(SSL_get_current_cipher(s)) +#define SSL_get_cipher_name(s) \ + SSL_CIPHER_get_name(SSL_get_current_cipher(s)) +#define SSL_get_time(a) SSL_SESSION_get_time(a) +#define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b)) +#define SSL_get_timeout(a) SSL_SESSION_get_timeout(a) +#define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b)) + +#define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id) +#define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id) + +SSL_SESSION *PEM_read_bio_SSL_SESSION(BIO *bp, SSL_SESSION **x, + pem_password_cb *cb, void *u); +SSL_SESSION *PEM_read_SSL_SESSION(FILE *fp, SSL_SESSION **x, + pem_password_cb *cb, void *u); +int PEM_write_bio_SSL_SESSION(BIO *bp, SSL_SESSION *x); +int PEM_write_SSL_SESSION(FILE *fp, SSL_SESSION *x); + +/* + * TLS Alerts. + * + * https://www.iana.org/assignments/tls-parameters/#tls-parameters-6 + */ + +/* Obsolete alerts. */ +#ifndef LIBRESSL_INTERNAL +#define SSL_AD_DECRYPTION_FAILED 21 /* Removed in TLSv1.1 */ +#define SSL_AD_NO_CERTIFICATE 41 /* Removed in TLSv1.0 */ +#define SSL_AD_EXPORT_RESTRICTION 60 /* Removed in TLSv1.1 */ +#endif + +#define SSL_AD_CLOSE_NOTIFY 0 +#define SSL_AD_UNEXPECTED_MESSAGE 10 +#define SSL_AD_BAD_RECORD_MAC 20 +#define SSL_AD_RECORD_OVERFLOW 22 +#define SSL_AD_DECOMPRESSION_FAILURE 30 /* Removed in TLSv1.3 */ +#define SSL_AD_HANDSHAKE_FAILURE 40 +#define SSL_AD_BAD_CERTIFICATE 42 +#define SSL_AD_UNSUPPORTED_CERTIFICATE 43 +#define SSL_AD_CERTIFICATE_REVOKED 44 +#define SSL_AD_CERTIFICATE_EXPIRED 45 +#define SSL_AD_CERTIFICATE_UNKNOWN 46 +#define SSL_AD_ILLEGAL_PARAMETER 47 +#define SSL_AD_UNKNOWN_CA 48 +#define SSL_AD_ACCESS_DENIED 49 +#define SSL_AD_DECODE_ERROR 50 +#define SSL_AD_DECRYPT_ERROR 51 +#define SSL_AD_PROTOCOL_VERSION 70 +#define SSL_AD_INSUFFICIENT_SECURITY 71 +#define SSL_AD_INTERNAL_ERROR 80 +#define SSL_AD_INAPPROPRIATE_FALLBACK 86 +#define SSL_AD_USER_CANCELLED 90 +#define SSL_AD_NO_RENEGOTIATION 100 /* Removed in TLSv1.3 */ +#define SSL_AD_MISSING_EXTENSION 109 /* Added in TLSv1.3. */ +#define SSL_AD_UNSUPPORTED_EXTENSION 110 +#define SSL_AD_CERTIFICATE_UNOBTAINABLE 111 /* Removed in TLSv1.3 */ +#define SSL_AD_UNRECOGNIZED_NAME 112 +#define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define SSL_AD_BAD_CERTIFICATE_HASH_VALUE 114 /* Removed in TLSv1.3 */ +#define SSL_AD_UNKNOWN_PSK_IDENTITY 115 +#define SSL_AD_CERTIFICATE_REQUIRED 116 +#define SSL_AD_NO_APPLICATION_PROTOCOL 120 + +/* Offset to get an SSL_R_... value from an SSL_AD_... value. */ +#define SSL_AD_REASON_OFFSET 1000 + +#define SSL_ERROR_NONE 0 +#define SSL_ERROR_SSL 1 +#define SSL_ERROR_WANT_READ 2 +#define SSL_ERROR_WANT_WRITE 3 +#define SSL_ERROR_WANT_X509_LOOKUP 4 +#define SSL_ERROR_SYSCALL 5 +#define SSL_ERROR_ZERO_RETURN 6 +#define SSL_ERROR_WANT_CONNECT 7 +#define SSL_ERROR_WANT_ACCEPT 8 +#define SSL_ERROR_WANT_ASYNC 9 +#define SSL_ERROR_WANT_ASYNC_JOB 10 +#define SSL_ERROR_WANT_CLIENT_HELLO_CB 11 + +#define SSL_CTRL_NEED_TMP_RSA 1 +#define SSL_CTRL_SET_TMP_RSA 2 +#define SSL_CTRL_SET_TMP_DH 3 +#define SSL_CTRL_SET_TMP_ECDH 4 +#define SSL_CTRL_SET_TMP_RSA_CB 5 +#define SSL_CTRL_SET_TMP_DH_CB 6 +#define SSL_CTRL_SET_TMP_ECDH_CB 7 + +#define SSL_CTRL_GET_SESSION_REUSED 8 +#define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9 +#define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10 +#define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11 +#define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12 +#define SSL_CTRL_GET_FLAGS 13 +#define SSL_CTRL_EXTRA_CHAIN_CERT 14 + +#define SSL_CTRL_SET_MSG_CALLBACK 15 +#define SSL_CTRL_SET_MSG_CALLBACK_ARG 16 + +/* only applies to datagram connections */ +#define SSL_CTRL_SET_MTU 17 +/* Stats */ +#define SSL_CTRL_SESS_NUMBER 20 +#define SSL_CTRL_SESS_CONNECT 21 +#define SSL_CTRL_SESS_CONNECT_GOOD 22 +#define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23 +#define SSL_CTRL_SESS_ACCEPT 24 +#define SSL_CTRL_SESS_ACCEPT_GOOD 25 +#define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26 +#define SSL_CTRL_SESS_HIT 27 +#define SSL_CTRL_SESS_CB_HIT 28 +#define SSL_CTRL_SESS_MISSES 29 +#define SSL_CTRL_SESS_TIMEOUTS 30 +#define SSL_CTRL_SESS_CACHE_FULL 31 +#define SSL_CTRL_OPTIONS 32 +#define SSL_CTRL_MODE 33 + +#define SSL_CTRL_GET_READ_AHEAD 40 +#define SSL_CTRL_SET_READ_AHEAD 41 +#define SSL_CTRL_SET_SESS_CACHE_SIZE 42 +#define SSL_CTRL_GET_SESS_CACHE_SIZE 43 +#define SSL_CTRL_SET_SESS_CACHE_MODE 44 +#define SSL_CTRL_GET_SESS_CACHE_MODE 45 + +#define SSL_CTRL_GET_MAX_CERT_LIST 50 +#define SSL_CTRL_SET_MAX_CERT_LIST 51 + +#define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52 + +/* see tls1.h for macros based on these */ +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53 +#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54 +#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55 +#define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56 +#define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57 +#define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58 +#define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 +#define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 + +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 + +#define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75 +#define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76 +#define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77 + +#define SSL_CTRL_SET_SRP_ARG 78 +#define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79 +#define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80 +#define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81 + +#define DTLS_CTRL_GET_TIMEOUT 73 +#define DTLS_CTRL_HANDLE_TIMEOUT 74 +#define DTLS_CTRL_LISTEN 75 + +#define SSL_CTRL_GET_RI_SUPPORT 76 +#define SSL_CTRL_CLEAR_OPTIONS 77 +#define SSL_CTRL_CLEAR_MODE 78 + +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 +#define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83 + +#define SSL_CTRL_CHAIN 88 +#define SSL_CTRL_CHAIN_CERT 89 + +#define SSL_CTRL_SET_GROUPS 91 +#define SSL_CTRL_SET_GROUPS_LIST 92 +#define SSL_CTRL_GET_SHARED_GROUP 93 +#define SSL_CTRL_SET_ECDH_AUTO 94 + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_CTRL_GET_PEER_SIGNATURE_NID 108 +#define SSL_CTRL_GET_PEER_TMP_KEY 109 +#define SSL_CTRL_GET_SERVER_TMP_KEY SSL_CTRL_GET_PEER_TMP_KEY +#else +#define SSL_CTRL_GET_SERVER_TMP_KEY 109 +#endif + +#define SSL_CTRL_GET_CHAIN_CERTS 115 + +#define SSL_CTRL_SET_DH_AUTO 118 + +#define SSL_CTRL_SET_MIN_PROTO_VERSION 123 +#define SSL_CTRL_SET_MAX_PROTO_VERSION 124 +#define SSL_CTRL_GET_MIN_PROTO_VERSION 130 +#define SSL_CTRL_GET_MAX_PROTO_VERSION 131 + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_CTRL_GET_SIGNATURE_NID 132 +#endif + +#define DTLSv1_get_timeout(ssl, arg) \ + SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg) +#define DTLSv1_handle_timeout(ssl) \ + SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL) +#define DTLSv1_listen(ssl, peer) \ + SSL_ctrl(ssl,DTLS_CTRL_LISTEN,0, (void *)peer) + +#define SSL_session_reused(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_SESSION_REUSED,0,NULL) +#define SSL_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL) +#define SSL_clear_num_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL) +#define SSL_total_renegotiations(ssl) \ + SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL) + +#define SSL_CTX_need_tmp_RSA(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_CTX_set_tmp_rsa(ctx,rsa) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_CTX_set_tmp_dh(ctx,dh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)dh) +#define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +#define SSL_CTX_set_dh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +#define SSL_CTX_set_ecdh_auto(ctx, onoff) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) + +#define SSL_need_tmp_RSA(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_NEED_TMP_RSA,0,NULL) +#define SSL_set_tmp_rsa(ssl,rsa) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_RSA,0,(char *)rsa) +#define SSL_set_tmp_dh(ssl,dh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)dh) +#define SSL_set_tmp_ecdh(ssl,ecdh) \ + SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)ecdh) +#define SSL_set_dh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL) +#define SSL_set_ecdh_auto(s, onoff) \ + SSL_ctrl(s,SSL_CTRL_SET_ECDH_AUTO,onoff,NULL) + +int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain); +int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain); +int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509); +int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509); +int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain); +int SSL_CTX_clear_chain_certs(SSL_CTX *ctx); + +int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain); +int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain); +int SSL_add0_chain_cert(SSL *ssl, X509 *x509); +int SSL_add1_chain_cert(SSL *ssl, X509 *x509); +int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain); +int SSL_clear_chain_certs(SSL *ssl); + +int SSL_CTX_set1_groups(SSL_CTX *ctx, const int *groups, size_t groups_len); +int SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups); + +int SSL_set1_groups(SSL *ssl, const int *groups, size_t groups_len); +int SSL_set1_groups_list(SSL *ssl, const char *groups); + +int SSL_CTX_get_min_proto_version(SSL_CTX *ctx); +int SSL_CTX_get_max_proto_version(SSL_CTX *ctx); +int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version); +int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version); + +int SSL_get_min_proto_version(SSL *ssl); +int SSL_get_max_proto_version(SSL *ssl); +int SSL_set_min_proto_version(SSL *ssl, uint16_t version); +int SSL_set_max_proto_version(SSL *ssl, uint16_t version); + +const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx); + +#ifndef LIBRESSL_INTERNAL +#define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS +#define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST + +#define SSL_CTX_set1_curves SSL_CTX_set1_groups +#define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list +#define SSL_set1_curves SSL_set1_groups +#define SSL_set1_curves_list SSL_set1_groups_list +#endif + +#define SSL_CTX_add_extra_chain_cert(ctx, x509) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, (char *)x509) +#define SSL_CTX_get_extra_chain_certs(ctx, px509) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_EXTRA_CHAIN_CERTS, 0, px509) +#define SSL_CTX_get_extra_chain_certs_only(ctx, px509) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_GET_EXTRA_CHAIN_CERTS, 1, px509) +#define SSL_CTX_clear_extra_chain_certs(ctx) \ + SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS, 0, NULL) + +#define SSL_get_shared_group(s, n) \ + SSL_ctrl((s), SSL_CTRL_GET_SHARED_GROUP, (n), NULL) +#define SSL_get_shared_curve SSL_get_shared_group + +#define SSL_get_server_tmp_key(s, pk) \ + SSL_ctrl(s,SSL_CTRL_GET_SERVER_TMP_KEY,0,pk) + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define SSL_get_signature_nid(s, pn) \ + SSL_ctrl(s, SSL_CTRL_GET_SIGNATURE_NID, 0, pn) + +#define SSL_get_peer_signature_nid(s, pn) \ + SSL_ctrl(s, SSL_CTRL_GET_PEER_SIGNATURE_NID, 0, pn) +#define SSL_get_peer_tmp_key(s, pk) \ + SSL_ctrl(s, SSL_CTRL_GET_PEER_TMP_KEY, 0, pk) + +int SSL_get_signature_type_nid(const SSL *ssl, int *nid); +int SSL_get_peer_signature_type_nid(const SSL *ssl, int *nid); + +#endif /* LIBRESSL_HAS_TLS1_3 || LIBRESSL_INTERNAL */ + +#ifndef LIBRESSL_INTERNAL +/* + * Also provide those functions as macros for compatibility with + * existing users. + */ +#define SSL_CTX_set0_chain SSL_CTX_set0_chain +#define SSL_CTX_set1_chain SSL_CTX_set1_chain +#define SSL_CTX_add0_chain_cert SSL_CTX_add0_chain_cert +#define SSL_CTX_add1_chain_cert SSL_CTX_add1_chain_cert +#define SSL_CTX_get0_chain_certs SSL_CTX_get0_chain_certs +#define SSL_CTX_clear_chain_certs SSL_CTX_clear_chain_certs + +#define SSL_add0_chain_cert SSL_add0_chain_cert +#define SSL_add1_chain_cert SSL_add1_chain_cert +#define SSL_set0_chain SSL_set0_chain +#define SSL_set1_chain SSL_set1_chain +#define SSL_get0_chain_certs SSL_get0_chain_certs +#define SSL_clear_chain_certs SSL_clear_chain_certs + +#define SSL_CTX_set1_groups SSL_CTX_set1_groups +#define SSL_CTX_set1_groups_list SSL_CTX_set1_groups_list +#define SSL_set1_groups SSL_set1_groups +#define SSL_set1_groups_list SSL_set1_groups_list + +#define SSL_CTX_get_min_proto_version SSL_CTX_get_min_proto_version +#define SSL_CTX_get_max_proto_version SSL_CTX_get_max_proto_version +#define SSL_CTX_set_min_proto_version SSL_CTX_set_min_proto_version +#define SSL_CTX_set_max_proto_version SSL_CTX_set_max_proto_version + +#define SSL_get_min_proto_version SSL_get_min_proto_version +#define SSL_get_max_proto_version SSL_get_max_proto_version +#define SSL_set_min_proto_version SSL_set_min_proto_version +#define SSL_set_max_proto_version SSL_set_max_proto_version +#endif + +const BIO_METHOD *BIO_f_ssl(void); +BIO *BIO_new_ssl(SSL_CTX *ctx, int client); +BIO *BIO_new_ssl_connect(SSL_CTX *ctx); +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx); +int BIO_ssl_copy_session_id(BIO *to, BIO *from); +void BIO_ssl_shutdown(BIO *ssl_bio); + +STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx); +int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str); +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str); +#endif +SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth); +void SSL_CTX_free(SSL_CTX *); +int SSL_CTX_up_ref(SSL_CTX *ctx); +long SSL_CTX_set_timeout(SSL_CTX *ctx, long t); +long SSL_CTX_get_timeout(const SSL_CTX *ctx); +X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *); +void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *); +X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx); +EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx); +int SSL_want(const SSL *s); +int SSL_clear(SSL *s); + +void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm); + +const SSL_CIPHER *SSL_get_current_cipher(const SSL *s); +const SSL_CIPHER *SSL_CIPHER_get_by_id(unsigned int id); +const SSL_CIPHER *SSL_CIPHER_get_by_value(uint16_t value); +int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits); +const char * SSL_CIPHER_get_version(const SSL_CIPHER *c); +const char * SSL_CIPHER_get_name(const SSL_CIPHER *c); +unsigned long SSL_CIPHER_get_id(const SSL_CIPHER *c); +uint16_t SSL_CIPHER_get_value(const SSL_CIPHER *c); +const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr); +int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c); +int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c); +int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c); +int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c); +int SSL_CIPHER_is_aead(const SSL_CIPHER *c); + +int SSL_get_fd(const SSL *s); +int SSL_get_rfd(const SSL *s); +int SSL_get_wfd(const SSL *s); +const char * SSL_get_cipher_list(const SSL *s, int n); +char * SSL_get_shared_ciphers(const SSL *s, char *buf, int len); +int SSL_get_read_ahead(const SSL * s); +int SSL_pending(const SSL *s); +int SSL_set_fd(SSL *s, int fd); +int SSL_set_rfd(SSL *s, int fd); +int SSL_set_wfd(SSL *s, int fd); +void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio); +BIO * SSL_get_rbio(const SSL *s); +void SSL_set0_rbio(SSL *s, BIO *rbio); +BIO * SSL_get_wbio(const SSL *s); +int SSL_set_cipher_list(SSL *s, const char *str); +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +int SSL_set_ciphersuites(SSL *s, const char *str); +#endif +void SSL_set_read_ahead(SSL *s, int yes); +int SSL_get_verify_mode(const SSL *s); +int SSL_get_verify_depth(const SSL *s); +int (*SSL_get_verify_callback(const SSL *s))(int, X509_STORE_CTX *); +void SSL_set_verify(SSL *s, int mode, + int (*callback)(int ok, X509_STORE_CTX *ctx)); +void SSL_set_verify_depth(SSL *s, int depth); +int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa); +int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len); +int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey); +int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d, long len); +int SSL_use_certificate(SSL *ssl, X509 *x); +int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len); + +int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type); +int SSL_use_certificate_file(SSL *ssl, const char *file, int type); +int SSL_use_certificate_chain_file(SSL *ssl, const char *file); +int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type); +int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file); /* PEM type */ +int SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len); +STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); +int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *file); +int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs, + const char *dir); + +void SSL_load_error_strings(void ); +const char *SSL_state_string(const SSL *s); +const char *SSL_rstate_string(const SSL *s); +const char *SSL_state_string_long(const SSL *s); +const char *SSL_rstate_string_long(const SSL *s); +const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *ss); +size_t SSL_SESSION_get_master_key(const SSL_SESSION *ss, + unsigned char *out, size_t max_out); +int SSL_SESSION_get_protocol_version(const SSL_SESSION *s); +long SSL_SESSION_get_time(const SSL_SESSION *s); +long SSL_SESSION_set_time(SSL_SESSION *s, long t); +long SSL_SESSION_get_timeout(const SSL_SESSION *s); +long SSL_SESSION_set_timeout(SSL_SESSION *s, long t); +int SSL_copy_session_id(SSL *to, const SSL *from); +X509 *SSL_SESSION_get0_peer(SSL_SESSION *s); +int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, + unsigned int sid_len); +int SSL_SESSION_set1_id_context(SSL_SESSION *s, + const unsigned char *sid_ctx, unsigned int sid_ctx_len); +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +int SSL_SESSION_is_resumable(const SSL_SESSION *s); +#endif + +SSL_SESSION *SSL_SESSION_new(void); +void SSL_SESSION_free(SSL_SESSION *ses); +int SSL_SESSION_up_ref(SSL_SESSION *ss); +const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *ss, + unsigned int *len); +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *ss, + unsigned int *len); +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *sess); +int SSL_SESSION_set_max_early_data(SSL_SESSION *sess, uint32_t max_early_data); +#endif +unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s); +int SSL_SESSION_has_ticket(const SSL_SESSION *s); +unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *ss); +int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses); +int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses); +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); +int SSL_set_session(SSL *to, SSL_SESSION *session); +int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c); +int SSL_CTX_remove_session(SSL_CTX *, SSL_SESSION *c); +int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB); +int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB); +int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length); + +#ifdef HEADER_X509_H +X509 * SSL_get_peer_certificate(const SSL *s); +#endif + +STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s); + +int SSL_CTX_get_verify_mode(const SSL_CTX *ctx); +int SSL_CTX_get_verify_depth(const SSL_CTX *ctx); +int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int, X509_STORE_CTX *); +void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, + int (*callback)(int, X509_STORE_CTX *)); +void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth); +void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, int (*cb)(X509_STORE_CTX *, void *), void *arg); +int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa); +int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len); +int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); +int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, const unsigned char *d, long len); +int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); +int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d); + +pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx); +void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb); +void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx); +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u); + +int SSL_CTX_check_private_key(const SSL_CTX *ctx); +int SSL_check_private_key(const SSL *ctx); + +int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, unsigned int sid_ctx_len); + +int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, unsigned int sid_ctx_len); + +int SSL_CTX_set_purpose(SSL_CTX *s, int purpose); +int SSL_set_purpose(SSL *s, int purpose); +int SSL_CTX_set_trust(SSL_CTX *s, int trust); +int SSL_set_trust(SSL *s, int trust); +int SSL_set1_host(SSL *s, const char *hostname); +void SSL_set_hostflags(SSL *s, unsigned int flags); +const char *SSL_get0_peername(SSL *s); + +X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx); +int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm); +X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl); +int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm); + +SSL *SSL_new(SSL_CTX *ctx); +void SSL_free(SSL *ssl); +int SSL_up_ref(SSL *ssl); +int SSL_accept(SSL *ssl); +int SSL_connect(SSL *ssl); +int SSL_is_dtls(const SSL *s); +int SSL_is_server(const SSL *s); +int SSL_read(SSL *ssl, void *buf, int num); +int SSL_peek(SSL *ssl, void *buf, int num); +int SSL_write(SSL *ssl, const void *buf, int num); +int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *bytes_read); +int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *bytes_peeked); +int SSL_write_ex(SSL *ssl, const void *buf, size_t num, size_t *bytes_written); + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx); +int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data); + +uint32_t SSL_get_max_early_data(const SSL *s); +int SSL_set_max_early_data(SSL *s, uint32_t max_early_data); + +#define SSL_EARLY_DATA_NOT_SENT 0 +#define SSL_EARLY_DATA_REJECTED 1 +#define SSL_EARLY_DATA_ACCEPTED 2 +int SSL_get_early_data_status(const SSL *s); + +#define SSL_READ_EARLY_DATA_ERROR 0 +#define SSL_READ_EARLY_DATA_SUCCESS 1 +#define SSL_READ_EARLY_DATA_FINISH 2 +int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes); +int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written); +#endif + +long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); +long SSL_callback_ctrl(SSL *, int, void (*)(void)); +long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg); +long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void)); + +int SSL_get_error(const SSL *s, int ret_code); +const char *SSL_get_version(const SSL *s); + +/* This sets the 'default' SSL version that SSL_new() will create */ +int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth); + +const SSL_METHOD *SSLv23_method(void); /* SSLv3 or TLSv1.* */ +const SSL_METHOD *SSLv23_server_method(void); /* SSLv3 or TLSv1.* */ +const SSL_METHOD *SSLv23_client_method(void); /* SSLv3 or TLSv1.* */ + +const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */ +const SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */ +const SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */ + +const SSL_METHOD *TLSv1_1_method(void); /* TLSv1.1 */ +const SSL_METHOD *TLSv1_1_server_method(void); /* TLSv1.1 */ +const SSL_METHOD *TLSv1_1_client_method(void); /* TLSv1.1 */ + +const SSL_METHOD *TLSv1_2_method(void); /* TLSv1.2 */ +const SSL_METHOD *TLSv1_2_server_method(void); /* TLSv1.2 */ +const SSL_METHOD *TLSv1_2_client_method(void); /* TLSv1.2 */ + +const SSL_METHOD *TLS_method(void); /* TLS v1.0 or later */ +const SSL_METHOD *TLS_server_method(void); /* TLS v1.0 or later */ +const SSL_METHOD *TLS_client_method(void); /* TLS v1.0 or later */ + +const SSL_METHOD *DTLSv1_method(void); /* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_server_method(void); /* DTLSv1.0 */ +const SSL_METHOD *DTLSv1_client_method(void); /* DTLSv1.0 */ + +const SSL_METHOD *DTLSv1_2_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_server_method(void); /* DTLSv1.2 */ +const SSL_METHOD *DTLSv1_2_client_method(void); /* DTLSv1.2 */ + +const SSL_METHOD *DTLS_method(void); /* DTLS v1.0 or later */ +const SSL_METHOD *DTLS_server_method(void); /* DTLS v1.0 or later */ +const SSL_METHOD *DTLS_client_method(void); /* DTLS v1.0 or later */ + +STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s); +STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s); +STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s); + +int SSL_do_handshake(SSL *s); +int SSL_renegotiate(SSL *s); +int SSL_renegotiate_abbreviated(SSL *s); +int SSL_renegotiate_pending(SSL *s); +int SSL_shutdown(SSL *s); + +const SSL_METHOD *SSL_get_ssl_method(SSL *s); +int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); +const char *SSL_alert_type_string_long(int value); +const char *SSL_alert_type_string(int value); +const char *SSL_alert_desc_string_long(int value); +const char *SSL_alert_desc_string(int value); + +void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list); +void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list); +STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s); +STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s); +int SSL_add_client_CA(SSL *ssl, X509 *x); +int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x); + +void SSL_set_connect_state(SSL *s); +void SSL_set_accept_state(SSL *s); + +long SSL_get_default_timeout(const SSL *s); + +int SSL_library_init(void ); + +char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size); +STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk); + +SSL *SSL_dup(SSL *ssl); + +X509 *SSL_get_certificate(const SSL *ssl); +/* EVP_PKEY */ struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl); + +void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx,int mode); +int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx); +void SSL_set_quiet_shutdown(SSL *ssl,int mode); +int SSL_get_quiet_shutdown(const SSL *ssl); +void SSL_set_shutdown(SSL *ssl,int mode); +int SSL_get_shutdown(const SSL *ssl); +int SSL_version(const SSL *ssl); +int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx); +int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath); +int SSL_CTX_load_verify_mem(SSL_CTX *ctx, void *buf, int len); +#define SSL_get0_session SSL_get_session /* just peek at pointer */ +SSL_SESSION *SSL_get_session(const SSL *ssl); +SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */ +SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl); +SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx); +void SSL_set_info_callback(SSL *ssl, + void (*cb)(const SSL *ssl, int type, int val)); +void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, int type, int val); +int SSL_state(const SSL *ssl); +void SSL_set_state(SSL *ssl, int state); + +void SSL_set_verify_result(SSL *ssl, long v); +long SSL_get_verify_result(const SSL *ssl); + +int SSL_set_ex_data(SSL *ssl, int idx, void *data); +void *SSL_get_ex_data(const SSL *ssl, int idx); +int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data); +void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx); +int SSL_SESSION_get_ex_new_index(long argl, void *argp, + CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, + CRYPTO_EX_free *free_func); + +int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data); +void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx); +int SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); + +int SSL_get_ex_data_X509_STORE_CTX_idx(void ); + +#define SSL_CTX_sess_set_cache_size(ctx,t) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL) +#define SSL_CTX_sess_get_cache_size(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL) +#define SSL_CTX_set_session_cache_mode(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL) +#define SSL_CTX_get_session_cache_mode(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL) + +#define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx) +#define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m) +#define SSL_CTX_get_read_ahead(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL) +#define SSL_CTX_set_read_ahead(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL) +#define SSL_CTX_get_max_cert_list(ctx) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_CTX_set_max_cert_list(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) +#define SSL_get_max_cert_list(ssl) \ + SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL) +#define SSL_set_max_cert_list(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL) + +#define SSL_CTX_set_max_send_fragment(ctx,m) \ + SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) +#define SSL_set_max_send_fragment(ssl,m) \ + SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL) + +/* NB: the keylength is only applicable when is_export is true */ +void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, + RSA *(*cb)(SSL *ssl, int is_export, int keylength)); + +void SSL_set_tmp_rsa_callback(SSL *ssl, + RSA *(*cb)(SSL *ssl, int is_export, int keylength)); +void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, + DH *(*dh)(SSL *ssl, int is_export, int keylength)); +void SSL_set_tmp_dh_callback(SSL *ssl, + DH *(*dh)(SSL *ssl, int is_export, int keylength)); +void SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, + EC_KEY *(*ecdh)(SSL *ssl, int is_export, int keylength)); +void SSL_set_tmp_ecdh_callback(SSL *ssl, + EC_KEY *(*ecdh)(SSL *ssl, int is_export, int keylength)); + +size_t SSL_get_client_random(const SSL *s, unsigned char *out, size_t max_out); +size_t SSL_get_server_random(const SSL *s, unsigned char *out, size_t max_out); + +const void *SSL_get_current_compression(SSL *s); +const void *SSL_get_current_expansion(SSL *s); + +const char *SSL_COMP_get_name(const void *comp); +void *SSL_COMP_get_compression_methods(void); +int SSL_COMP_add_compression_method(int id, void *cm); + +/* TLS extensions functions */ +int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); + +int SSL_set_session_ticket_ext_cb(SSL *s, + tls_session_ticket_ext_cb_fn cb, void *arg); + +/* Pre-shared secret session resumption functions */ +int SSL_set_session_secret_cb(SSL *s, + tls_session_secret_cb_fn tls_session_secret_cb, void *arg); + +void SSL_set_debug(SSL *s, int debug); +int SSL_cache_hit(SSL *s); + +/* What the "other" parameter contains in security callback */ +/* Mask for type */ +#define SSL_SECOP_OTHER_TYPE 0xffff0000 +#define SSL_SECOP_OTHER_NONE 0 +#define SSL_SECOP_OTHER_CIPHER (1 << 16) +#define SSL_SECOP_OTHER_CURVE (2 << 16) +#define SSL_SECOP_OTHER_DH (3 << 16) +#define SSL_SECOP_OTHER_PKEY (4 << 16) +#define SSL_SECOP_OTHER_SIGALG (5 << 16) +#define SSL_SECOP_OTHER_CERT (6 << 16) + +/* Indicated operation refers to peer key or certificate */ +#define SSL_SECOP_PEER 0x1000 + +/* Values for "op" parameter in security callback */ + +/* Called to filter ciphers */ +/* Ciphers client supports */ +#define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER) +/* Cipher shared by client/server */ +#define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER) +/* Sanity check of cipher server selects */ +#define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER) +/* Curves supported by client */ +#define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE) +/* Curves shared by client/server */ +#define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE) +/* Sanity check of curve server selects */ +#define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE) +/* Temporary DH key */ +/* + * XXX: changed in OpenSSL e2b420fdd70 to (7 | SSL_SECOP_OTHER_PKEY) + * Needs switching internal use of DH to EVP_PKEY. The code is not reachable + * from outside the library as long as we do not expose the callback in the API. + */ +#define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_DH) +/* SSL/TLS version */ +#define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE) +/* Session tickets */ +#define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE) +/* Supported signature algorithms sent to peer */ +#define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG) +/* Shared signature algorithm */ +#define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG) +/* Sanity check signature algorithm allowed */ +#define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG) +/* Used to get mask of supported public key signature algorithms */ +#define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG) +/* Use to see if compression is allowed */ +#define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE) +/* EE key in certificate */ +#define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT) +/* CA key in certificate */ +#define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT) +/* CA digest algorithm in certificate */ +#define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT) +/* Peer EE key in certificate */ +#define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER) +/* Peer CA key in certificate */ +#define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER) +/* Peer CA digest algorithm in certificate */ +#define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER) + +void SSL_set_security_level(SSL *ssl, int level); +int SSL_get_security_level(const SSL *ssl); + +void SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +int SSL_CTX_get_security_level(const SSL_CTX *ctx); + +#if defined(LIBRESSL_HAS_QUIC) || defined(LIBRESSL_INTERNAL) +/* + * QUIC integration. + * + * QUIC acts as an underlying transport for the TLS 1.3 handshake. The following + * functions allow a QUIC implementation to serve as the underlying transport as + * described in RFC 9001. + * + * When configured for QUIC, |SSL_do_handshake| will drive the handshake as + * before, but it will not use the configured |BIO|. It will call functions on + * |SSL_QUIC_METHOD| to configure secrets and send data. If data is needed from + * the peer, it will return |SSL_ERROR_WANT_READ|. As the caller receives data + * it can decrypt, it calls |SSL_provide_quic_data|. Subsequent + * |SSL_do_handshake| calls will then consume that data and progress the + * handshake. After the handshake is complete, the caller should continue to + * call |SSL_provide_quic_data| for any post-handshake data, followed by + * |SSL_process_quic_post_handshake| to process it. It is an error to call + * |SSL_peek|, |SSL_read| and |SSL_write| in QUIC. + * + * To avoid DoS attacks, the QUIC implementation must limit the amount of data + * being queued up. The implementation can call + * |SSL_quic_max_handshake_flight_len| to get the maximum buffer length at each + * encryption level. + * + * QUIC implementations must additionally configure transport parameters with + * |SSL_set_quic_transport_params|. |SSL_get_peer_quic_transport_params| may be + * used to query the value received from the peer. This extension is handled + * as an opaque byte string, which the caller is responsible for serializing + * and parsing. See RFC 9000 section 7.4 for further details. + */ + +/* + * ssl_encryption_level_t specifies the QUIC encryption level used to transmit + * handshake messages. + */ +typedef enum ssl_encryption_level_t { + ssl_encryption_initial = 0, + ssl_encryption_early_data, + ssl_encryption_handshake, + ssl_encryption_application, +} OSSL_ENCRYPTION_LEVEL; + +/* + * ssl_quic_method_st (aka |SSL_QUIC_METHOD|) describes custom QUIC hooks. + * + * Note that we provide both the new (BoringSSL) secrets interface + * (set_read_secret/set_write_secret) along with the old interface + * (set_encryption_secrets), which quictls is still using. + * + * Since some consumers fail to use named initialisers, the order of these + * functions is important. Hopefully all of these consumers use the old version. + */ +struct ssl_quic_method_st { + /* + * set_encryption_secrets configures the read and write secrets for the + * given encryption level. This function will always be called before an + * encryption level other than |ssl_encryption_initial| is used. + * + * When reading packets at a given level, the QUIC implementation must + * send ACKs at the same level, so this function provides read and write + * secrets together. The exception is |ssl_encryption_early_data|, where + * secrets are only available in the client to server direction. The + * other secret will be NULL. The server acknowledges such data at + * |ssl_encryption_application|, which will be configured in the same + * |SSL_do_handshake| call. + * + * This function should use |SSL_get_current_cipher| to determine the TLS + * cipher suite. + */ + int (*set_encryption_secrets)(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *read_secret, const uint8_t *write_secret, + size_t secret_len); + + /* + * add_handshake_data adds handshake data to the current flight at the + * given encryption level. It returns one on success and zero on error. + * Callers should defer writing data to the network until |flush_flight| + * to better pack QUIC packets into transport datagrams. + * + * If |level| is not |ssl_encryption_initial|, this function will not be + * called before |level| is initialized with |set_write_secret|. + */ + int (*add_handshake_data)(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len); + + /* + * flush_flight is called when the current flight is complete and should + * be written to the transport. Note a flight may contain data at + * several encryption levels. It returns one on success and zero on + * error. + */ + int (*flush_flight)(SSL *ssl); + + /* + * send_alert sends a fatal alert at the specified encryption level. It + * returns one on success and zero on error. + * + * If |level| is not |ssl_encryption_initial|, this function will not be + * called before |level| is initialized with |set_write_secret|. + */ + int (*send_alert)(SSL *ssl, enum ssl_encryption_level_t level, + uint8_t alert); + + /* + * set_read_secret configures the read secret and cipher suite for the + * given encryption level. It returns one on success and zero to + * terminate the handshake with an error. It will be called at most once + * per encryption level. + * + * Read keys will not be released before QUIC may use them. Once a level + * has been initialized, QUIC may begin processing data from it. + * Handshake data should be passed to |SSL_provide_quic_data| and + * application data (if |level| is |ssl_encryption_early_data| or + * |ssl_encryption_application|) may be processed according to the rules + * of the QUIC protocol. + */ + int (*set_read_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len); + + /* + * set_write_secret behaves like |set_read_secret| but configures the + * write secret and cipher suite for the given encryption level. It will + * be called at most once per encryption level. + * + * Write keys will not be released before QUIC may use them. If |level| + * is |ssl_encryption_early_data| or |ssl_encryption_application|, QUIC + * may begin sending application data at |level|. + */ + int (*set_write_secret)(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len); +}; + +/* + * SSL_CTX_set_quic_method configures the QUIC hooks. This should only be + * configured with a minimum version of TLS 1.3. |quic_method| must remain valid + * for the lifetime of |ctx|. It returns one on success and zero on error. + */ +int SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method); + +/* + * SSL_set_quic_method configures the QUIC hooks. This should only be + * configured with a minimum version of TLS 1.3. |quic_method| must remain valid + * for the lifetime of |ssl|. It returns one on success and zero on error. + */ +int SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method); + +/* SSL_is_quic returns true if an SSL has been configured for use with QUIC. */ +int SSL_is_quic(const SSL *ssl); + +/* + * SSL_quic_max_handshake_flight_len returns returns the maximum number of bytes + * that may be received at the given encryption level. This function should be + * used to limit buffering in the QUIC implementation. See RFC 9000 section 7.5. + */ +size_t SSL_quic_max_handshake_flight_len(const SSL *ssl, + enum ssl_encryption_level_t level); + +/* + * SSL_quic_read_level returns the current read encryption level. + */ +enum ssl_encryption_level_t SSL_quic_read_level(const SSL *ssl); + +/* + * SSL_quic_write_level returns the current write encryption level. + */ +enum ssl_encryption_level_t SSL_quic_write_level(const SSL *ssl); + +/* + * SSL_provide_quic_data provides data from QUIC at a particular encryption + * level |level|. It returns one on success and zero on error. Note this + * function will return zero if the handshake is not expecting data from |level| + * at this time. The QUIC implementation should then close the connection with + * an error. + */ +int SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len); + +/* + * SSL_process_quic_post_handshake processes any data that QUIC has provided + * after the handshake has completed. This includes NewSessionTicket messages + * sent by the server. It returns one on success and zero on error. + */ +int SSL_process_quic_post_handshake(SSL *ssl); + +/* + * SSL_set_quic_transport_params configures |ssl| to send |params| (of length + * |params_len|) in the quic_transport_parameters extension in either the + * ClientHello or EncryptedExtensions handshake message. It is an error to set + * transport parameters if |ssl| is not configured for QUIC. The buffer pointed + * to by |params| only need be valid for the duration of the call to this + * function. This function returns 1 on success and 0 on failure. + */ +int SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params, + size_t params_len); + +/* + * SSL_get_peer_quic_transport_params provides the caller with the value of the + * quic_transport_parameters extension sent by the peer. A pointer to the buffer + * containing the TransportParameters will be put in |*out_params|, and its + * length in |*params_len|. This buffer will be valid for the lifetime of the + * |SSL|. If no params were received from the peer, |*out_params_len| will be 0. + */ +void SSL_get_peer_quic_transport_params(const SSL *ssl, + const uint8_t **out_params, size_t *out_params_len); + +/* + * SSL_set_quic_use_legacy_codepoint configures whether to use the legacy QUIC + * extension codepoint 0xffa5 as opposed to the official value 57. This is + * unsupported in LibreSSL. + */ +void SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy); + +#endif + +void ERR_load_SSL_strings(void); + +/* Error codes for the SSL functions. */ + +/* Function codes. */ +#define SSL_F_CLIENT_CERTIFICATE 100 +#define SSL_F_CLIENT_FINISHED 167 +#define SSL_F_CLIENT_HELLO 101 +#define SSL_F_CLIENT_MASTER_KEY 102 +#define SSL_F_D2I_SSL_SESSION 103 +#define SSL_F_DO_DTLS1_WRITE 245 +#define SSL_F_DO_SSL3_WRITE 104 +#define SSL_F_DTLS1_ACCEPT 246 +#define SSL_F_DTLS1_ADD_CERT_TO_BUF 295 +#define SSL_F_DTLS1_BUFFER_RECORD 247 +#define SSL_F_DTLS1_CHECK_TIMEOUT_NUM 316 +#define SSL_F_DTLS1_CLIENT_HELLO 248 +#define SSL_F_DTLS1_CONNECT 249 +#define SSL_F_DTLS1_ENC 250 +#define SSL_F_DTLS1_GET_HELLO_VERIFY 251 +#define SSL_F_DTLS1_GET_MESSAGE 252 +#define SSL_F_DTLS1_GET_MESSAGE_FRAGMENT 253 +#define SSL_F_DTLS1_GET_RECORD 254 +#define SSL_F_DTLS1_HANDLE_TIMEOUT 297 +#define SSL_F_DTLS1_HEARTBEAT 305 +#define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 +#define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288 +#define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 +#define SSL_F_DTLS1_PROCESS_RECORD 257 +#define SSL_F_DTLS1_READ_BYTES 258 +#define SSL_F_DTLS1_READ_FAILED 259 +#define SSL_F_DTLS1_SEND_CERTIFICATE_REQUEST 260 +#define SSL_F_DTLS1_SEND_CLIENT_CERTIFICATE 261 +#define SSL_F_DTLS1_SEND_CLIENT_KEY_EXCHANGE 262 +#define SSL_F_DTLS1_SEND_CLIENT_VERIFY 263 +#define SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST 264 +#define SSL_F_DTLS1_SEND_SERVER_CERTIFICATE 265 +#define SSL_F_DTLS1_SEND_SERVER_HELLO 266 +#define SSL_F_DTLS1_SEND_SERVER_KEY_EXCHANGE 267 +#define SSL_F_DTLS1_WRITE_APP_DATA_BYTES 268 +#define SSL_F_GET_CLIENT_FINISHED 105 +#define SSL_F_GET_CLIENT_HELLO 106 +#define SSL_F_GET_CLIENT_MASTER_KEY 107 +#define SSL_F_GET_SERVER_FINISHED 108 +#define SSL_F_GET_SERVER_HELLO 109 +#define SSL_F_GET_SERVER_VERIFY 110 +#define SSL_F_I2D_SSL_SESSION 111 +#define SSL_F_READ_N 112 +#define SSL_F_REQUEST_CERTIFICATE 113 +#define SSL_F_SERVER_FINISH 239 +#define SSL_F_SERVER_HELLO 114 +#define SSL_F_SERVER_VERIFY 240 +#define SSL_F_SSL23_ACCEPT 115 +#define SSL_F_SSL23_CLIENT_HELLO 116 +#define SSL_F_SSL23_CONNECT 117 +#define SSL_F_SSL23_GET_CLIENT_HELLO 118 +#define SSL_F_SSL23_GET_SERVER_HELLO 119 +#define SSL_F_SSL23_PEEK 237 +#define SSL_F_SSL23_READ 120 +#define SSL_F_SSL23_WRITE 121 +#define SSL_F_SSL2_ACCEPT 122 +#define SSL_F_SSL2_CONNECT 123 +#define SSL_F_SSL2_ENC_INIT 124 +#define SSL_F_SSL2_GENERATE_KEY_MATERIAL 241 +#define SSL_F_SSL2_PEEK 234 +#define SSL_F_SSL2_READ 125 +#define SSL_F_SSL2_READ_INTERNAL 236 +#define SSL_F_SSL2_SET_CERTIFICATE 126 +#define SSL_F_SSL2_WRITE 127 +#define SSL_F_SSL3_ACCEPT 128 +#define SSL_F_SSL3_ADD_CERT_TO_BUF 296 +#define SSL_F_SSL3_CALLBACK_CTRL 233 +#define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 +#define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +#define SSL_F_SSL3_CHECK_CLIENT_HELLO 304 +#define SSL_F_SSL3_CLIENT_HELLO 131 +#define SSL_F_SSL3_CONNECT 132 +#define SSL_F_SSL3_CTRL 213 +#define SSL_F_SSL3_CTX_CTRL 133 +#define SSL_F_SSL3_DIGEST_CACHED_RECORDS 293 +#define SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC 292 +#define SSL_F_SSL3_ENC 134 +#define SSL_F_SSL3_GENERATE_KEY_BLOCK 238 +#define SSL_F_SSL3_GET_CERTIFICATE_REQUEST 135 +#define SSL_F_SSL3_GET_CERT_STATUS 289 +#define SSL_F_SSL3_GET_CERT_VERIFY 136 +#define SSL_F_SSL3_GET_CLIENT_CERTIFICATE 137 +#define SSL_F_SSL3_GET_CLIENT_HELLO 138 +#define SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE 139 +#define SSL_F_SSL3_GET_FINISHED 140 +#define SSL_F_SSL3_GET_KEY_EXCHANGE 141 +#define SSL_F_SSL3_GET_MESSAGE 142 +#define SSL_F_SSL3_GET_NEW_SESSION_TICKET 283 +#define SSL_F_SSL3_GET_NEXT_PROTO 306 +#define SSL_F_SSL3_GET_RECORD 143 +#define SSL_F_SSL3_GET_SERVER_CERTIFICATE 144 +#define SSL_F_SSL3_GET_SERVER_DONE 145 +#define SSL_F_SSL3_GET_SERVER_HELLO 146 +#define SSL_F_SSL3_HANDSHAKE_MAC 285 +#define SSL_F_SSL3_NEW_SESSION_TICKET 287 +#define SSL_F_SSL3_OUTPUT_CERT_CHAIN 147 +#define SSL_F_SSL3_PEEK 235 +#define SSL_F_SSL3_READ_BYTES 148 +#define SSL_F_SSL3_READ_N 149 +#define SSL_F_SSL3_SEND_CERTIFICATE_REQUEST 150 +#define SSL_F_SSL3_SEND_CLIENT_CERTIFICATE 151 +#define SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE 152 +#define SSL_F_SSL3_SEND_CLIENT_VERIFY 153 +#define SSL_F_SSL3_SEND_SERVER_CERTIFICATE 154 +#define SSL_F_SSL3_SEND_SERVER_HELLO 242 +#define SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE 155 +#define SSL_F_SSL3_SETUP_KEY_BLOCK 157 +#define SSL_F_SSL3_SETUP_READ_BUFFER 156 +#define SSL_F_SSL3_SETUP_WRITE_BUFFER 291 +#define SSL_F_SSL3_WRITE_BYTES 158 +#define SSL_F_SSL3_WRITE_PENDING 159 +#define SSL_F_SSL_ADD_CLIENTHELLO_RENEGOTIATE_EXT 298 +#define SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT 277 +#define SSL_F_SSL_ADD_CLIENTHELLO_USE_SRTP_EXT 307 +#define SSL_F_SSL_ADD_DIR_CERT_SUBJECTS_TO_STACK 215 +#define SSL_F_SSL_ADD_FILE_CERT_SUBJECTS_TO_STACK 216 +#define SSL_F_SSL_ADD_SERVERHELLO_RENEGOTIATE_EXT 299 +#define SSL_F_SSL_ADD_SERVERHELLO_TLSEXT 278 +#define SSL_F_SSL_ADD_SERVERHELLO_USE_SRTP_EXT 308 +#define SSL_F_SSL_BAD_METHOD 160 +#define SSL_F_SSL_BYTES_TO_CIPHER_LIST 161 +#define SSL_F_SSL_CERT_DUP 221 +#define SSL_F_SSL_CERT_INST 222 +#define SSL_F_SSL_CERT_INSTANTIATE 214 +#define SSL_F_SSL_CERT_NEW 162 +#define SSL_F_SSL_CHECK_PRIVATE_KEY 163 +#define SSL_F_SSL_CHECK_SERVERHELLO_TLSEXT 280 +#define SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG 279 +#define SSL_F_SSL_CIPHER_PROCESS_RULESTR 230 +#define SSL_F_SSL_CIPHER_STRENGTH_SORT 231 +#define SSL_F_SSL_CLEAR 164 +#define SSL_F_SSL_COMP_ADD_COMPRESSION_METHOD 165 +#define SSL_F_SSL_CREATE_CIPHER_LIST 166 +#define SSL_F_SSL_CTRL 232 +#define SSL_F_SSL_CTX_CHECK_PRIVATE_KEY 168 +#define SSL_F_SSL_CTX_MAKE_PROFILES 309 +#define SSL_F_SSL_CTX_NEW 169 +#define SSL_F_SSL_CTX_SET_CIPHER_LIST 269 +#define SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE 290 +#define SSL_F_SSL_CTX_SET_PURPOSE 226 +#define SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT 219 +#define SSL_F_SSL_CTX_SET_SSL_VERSION 170 +#define SSL_F_SSL_CTX_SET_TRUST 229 +#define SSL_F_SSL_CTX_USE_CERTIFICATE 171 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_ASN1 172 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_CHAIN_FILE 220 +#define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 173 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY 174 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_ASN1 175 +#define SSL_F_SSL_CTX_USE_PRIVATEKEY_FILE 176 +#define SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT 272 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY 177 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1 178 +#define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE 179 +#define SSL_F_SSL_DO_HANDSHAKE 180 +#define SSL_F_SSL_GET_NEW_SESSION 181 +#define SSL_F_SSL_GET_PREV_SESSION 217 +#define SSL_F_SSL_GET_SERVER_SEND_CERT 182 +#define SSL_F_SSL_GET_SERVER_SEND_PKEY 317 +#define SSL_F_SSL_GET_SIGN_PKEY 183 +#define SSL_F_SSL_INIT_WBIO_BUFFER 184 +#define SSL_F_SSL_LOAD_CLIENT_CA_FILE 185 +#define SSL_F_SSL_NEW 186 +#define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT 300 +#define SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT 302 +#define SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT 310 +#define SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT 301 +#define SSL_F_SSL_PARSE_SERVERHELLO_TLSEXT 303 +#define SSL_F_SSL_PARSE_SERVERHELLO_USE_SRTP_EXT 311 +#define SSL_F_SSL_PEEK 270 +#define SSL_F_SSL_PREPARE_CLIENTHELLO_TLSEXT 281 +#define SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT 282 +#define SSL_F_SSL_READ 223 +#define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 +#define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +#define SSL_F_SSL_SESSION_NEW 189 +#define SSL_F_SSL_SESSION_PRINT_FP 190 +#define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312 +#define SSL_F_SSL_SESS_CERT_NEW 225 +#define SSL_F_SSL_SET_CERT 191 +#define SSL_F_SSL_SET_CIPHER_LIST 271 +#define SSL_F_SSL_SET_FD 192 +#define SSL_F_SSL_SET_PKEY 193 +#define SSL_F_SSL_SET_PURPOSE 227 +#define SSL_F_SSL_SET_RFD 194 +#define SSL_F_SSL_SET_SESSION 195 +#define SSL_F_SSL_SET_SESSION_ID_CONTEXT 218 +#define SSL_F_SSL_SET_SESSION_TICKET_EXT 294 +#define SSL_F_SSL_SET_TRUST 228 +#define SSL_F_SSL_SET_WFD 196 +#define SSL_F_SSL_SHUTDOWN 224 +#define SSL_F_SSL_SRP_CTX_INIT 313 +#define SSL_F_SSL_UNDEFINED_CONST_FUNCTION 243 +#define SSL_F_SSL_UNDEFINED_FUNCTION 197 +#define SSL_F_SSL_UNDEFINED_VOID_FUNCTION 244 +#define SSL_F_SSL_USE_CERTIFICATE 198 +#define SSL_F_SSL_USE_CERTIFICATE_ASN1 199 +#define SSL_F_SSL_USE_CERTIFICATE_FILE 200 +#define SSL_F_SSL_USE_PRIVATEKEY 201 +#define SSL_F_SSL_USE_PRIVATEKEY_ASN1 202 +#define SSL_F_SSL_USE_PRIVATEKEY_FILE 203 +#define SSL_F_SSL_USE_PSK_IDENTITY_HINT 273 +#define SSL_F_SSL_USE_RSAPRIVATEKEY 204 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_ASN1 205 +#define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE 206 +#define SSL_F_SSL_VERIFY_CERT_CHAIN 207 +#define SSL_F_SSL_WRITE 208 +#define SSL_F_TLS1_AEAD_CTX_INIT 339 +#define SSL_F_TLS1_CERT_VERIFY_MAC 286 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE 209 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE_AEAD 340 +#define SSL_F_TLS1_CHANGE_CIPHER_STATE_CIPHER 338 +#define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT 274 +#define SSL_F_TLS1_ENC 210 +#define SSL_F_TLS1_EXPORT_KEYING_MATERIAL 314 +#define SSL_F_TLS1_HEARTBEAT 315 +#define SSL_F_TLS1_PREPARE_CLIENTHELLO_TLSEXT 275 +#define SSL_F_TLS1_PREPARE_SERVERHELLO_TLSEXT 276 +#define SSL_F_TLS1_PRF 284 +#define SSL_F_TLS1_SETUP_KEY_BLOCK 211 +#define SSL_F_WRITE_PENDING 212 + +/* Reason codes. */ +#define SSL_R_APP_DATA_IN_HANDSHAKE 100 +#define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272 +#define SSL_R_BAD_ALERT_RECORD 101 +#define SSL_R_BAD_AUTHENTICATION_TYPE 102 +#define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 +#define SSL_R_BAD_CHECKSUM 104 +#define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 +#define SSL_R_BAD_DECOMPRESSION 107 +#define SSL_R_BAD_DH_G_LENGTH 108 +#define SSL_R_BAD_DH_PUB_KEY_LENGTH 109 +#define SSL_R_BAD_DH_P_LENGTH 110 +#define SSL_R_BAD_DIGEST_LENGTH 111 +#define SSL_R_BAD_DSA_SIGNATURE 112 +#define SSL_R_BAD_ECC_CERT 304 +#define SSL_R_BAD_ECDSA_SIGNATURE 305 +#define SSL_R_BAD_ECPOINT 306 +#define SSL_R_BAD_HANDSHAKE_LENGTH 332 +#define SSL_R_BAD_HELLO_REQUEST 105 +#define SSL_R_BAD_LENGTH 271 +#define SSL_R_BAD_MAC_DECODE 113 +#define SSL_R_BAD_MAC_LENGTH 333 +#define SSL_R_BAD_MESSAGE_TYPE 114 +#define SSL_R_BAD_PACKET_LENGTH 115 +#define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 116 +#define SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH 316 +#define SSL_R_BAD_RESPONSE_ARGUMENT 117 +#define SSL_R_BAD_RSA_DECRYPT 118 +#define SSL_R_BAD_RSA_ENCRYPT 119 +#define SSL_R_BAD_RSA_E_LENGTH 120 +#define SSL_R_BAD_RSA_MODULUS_LENGTH 121 +#define SSL_R_BAD_RSA_SIGNATURE 122 +#define SSL_R_BAD_SIGNATURE 123 +#define SSL_R_BAD_SRP_A_LENGTH 347 +#define SSL_R_BAD_SRP_B_LENGTH 348 +#define SSL_R_BAD_SRP_G_LENGTH 349 +#define SSL_R_BAD_SRP_N_LENGTH 350 +#define SSL_R_BAD_SRP_S_LENGTH 351 +#define SSL_R_BAD_SRTP_MKI_VALUE 352 +#define SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST 353 +#define SSL_R_BAD_SSL_FILETYPE 124 +#define SSL_R_BAD_SSL_SESSION_ID_LENGTH 125 +#define SSL_R_BAD_STATE 126 +#define SSL_R_BAD_WRITE_RETRY 127 +#define SSL_R_BIO_NOT_SET 128 +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 129 +#define SSL_R_BN_LIB 130 +#define SSL_R_CA_DN_LENGTH_MISMATCH 131 +#define SSL_R_CA_DN_TOO_LONG 132 +#define SSL_R_CA_KEY_TOO_SMALL 397 +#define SSL_R_CA_MD_TOO_WEAK 398 +#define SSL_R_CCS_RECEIVED_EARLY 133 +#define SSL_R_CERTIFICATE_VERIFY_FAILED 134 +#define SSL_R_CERT_LENGTH_MISMATCH 135 +#define SSL_R_CHALLENGE_IS_DIFFERENT 136 +#define SSL_R_CIPHER_CODE_WRONG_LENGTH 137 +#define SSL_R_CIPHER_COMPRESSION_UNAVAILABLE 371 +#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138 +#define SSL_R_CIPHER_TABLE_SRC_ERROR 139 +#define SSL_R_CLIENTHELLO_TLSEXT 226 +#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140 +#define SSL_R_COMPRESSION_DISABLED 343 +#define SSL_R_COMPRESSION_FAILURE 141 +#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 307 +#define SSL_R_COMPRESSION_LIBRARY_ERROR 142 +#define SSL_R_CONNECTION_ID_IS_DIFFERENT 143 +#define SSL_R_CONNECTION_TYPE_NOT_SET 144 +#define SSL_R_COOKIE_MISMATCH 308 +#define SSL_R_DATA_BETWEEN_CCS_AND_FINISHED 145 +#define SSL_R_DATA_LENGTH_TOO_LONG 146 +#define SSL_R_DECRYPTION_FAILED 147 +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +#define SSL_R_DH_KEY_TOO_SMALL 394 +#define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 +#define SSL_R_DIGEST_CHECK_FAILED 149 +#define SSL_R_DTLS_MESSAGE_TOO_BIG 334 +#define SSL_R_DUPLICATE_COMPRESSION_ID 309 +#define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT 317 +#define SSL_R_ECC_CERT_NOT_FOR_SIGNING 318 +#define SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE 322 +#define SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE 323 +#define SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER 310 +#define SSL_R_EE_KEY_TOO_SMALL 399 +#define SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST 354 +#define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 150 +#define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 282 +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST 151 +#define SSL_R_EXCESSIVE_MESSAGE_SIZE 152 +#define SSL_R_EXTRA_DATA_IN_MESSAGE 153 +#define SSL_R_GOT_A_FIN_BEFORE_A_CCS 154 +#define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS 355 +#define SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION 356 +#define SSL_R_HTTPS_PROXY_REQUEST 155 +#define SSL_R_HTTP_REQUEST 156 +#define SSL_R_ILLEGAL_PADDING 283 +#define SSL_R_INAPPROPRIATE_FALLBACK 373 +#define SSL_R_INCONSISTENT_COMPRESSION 340 +#define SSL_R_INVALID_CHALLENGE_LENGTH 158 +#define SSL_R_INVALID_COMMAND 280 +#define SSL_R_INVALID_COMPRESSION_ALGORITHM 341 +#define SSL_R_INVALID_PURPOSE 278 +#define SSL_R_INVALID_SRP_USERNAME 357 +#define SSL_R_INVALID_STATUS_RESPONSE 328 +#define SSL_R_INVALID_TICKET_KEYS_LENGTH 325 +#define SSL_R_INVALID_TRUST 279 +#define SSL_R_KEY_ARG_TOO_LONG 284 +#define SSL_R_KRB5 285 +#define SSL_R_KRB5_C_CC_PRINC 286 +#define SSL_R_KRB5_C_GET_CRED 287 +#define SSL_R_KRB5_C_INIT 288 +#define SSL_R_KRB5_C_MK_REQ 289 +#define SSL_R_KRB5_S_BAD_TICKET 290 +#define SSL_R_KRB5_S_INIT 291 +#define SSL_R_KRB5_S_RD_REQ 292 +#define SSL_R_KRB5_S_TKT_EXPIRED 293 +#define SSL_R_KRB5_S_TKT_NYV 294 +#define SSL_R_KRB5_S_TKT_SKEW 295 +#define SSL_R_LENGTH_MISMATCH 159 +#define SSL_R_LENGTH_TOO_SHORT 160 +#define SSL_R_LIBRARY_BUG 274 +#define SSL_R_LIBRARY_HAS_NO_CIPHERS 161 +#define SSL_R_MESSAGE_TOO_LONG 296 +#define SSL_R_MISSING_DH_DSA_CERT 162 +#define SSL_R_MISSING_DH_KEY 163 +#define SSL_R_MISSING_DH_RSA_CERT 164 +#define SSL_R_MISSING_DSA_SIGNING_CERT 165 +#define SSL_R_MISSING_EXPORT_TMP_DH_KEY 166 +#define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 167 +#define SSL_R_MISSING_RSA_CERTIFICATE 168 +#define SSL_R_MISSING_RSA_ENCRYPTING_CERT 169 +#define SSL_R_MISSING_RSA_SIGNING_CERT 170 +#define SSL_R_MISSING_SRP_PARAM 358 +#define SSL_R_MISSING_TMP_DH_KEY 171 +#define SSL_R_MISSING_TMP_ECDH_KEY 311 +#define SSL_R_MISSING_TMP_RSA_KEY 172 +#define SSL_R_MISSING_TMP_RSA_PKEY 173 +#define SSL_R_MISSING_VERIFY_MESSAGE 174 +#define SSL_R_MULTIPLE_SGC_RESTARTS 346 +#define SSL_R_NON_SSLV2_INITIAL_PACKET 175 +#define SSL_R_NO_APPLICATION_PROTOCOL 235 +#define SSL_R_NO_CERTIFICATES_RETURNED 176 +#define SSL_R_NO_CERTIFICATE_ASSIGNED 177 +#define SSL_R_NO_CERTIFICATE_RETURNED 178 +#define SSL_R_NO_CERTIFICATE_SET 179 +#define SSL_R_NO_CERTIFICATE_SPECIFIED 180 +#define SSL_R_NO_CIPHERS_AVAILABLE 181 +#define SSL_R_NO_CIPHERS_PASSED 182 +#define SSL_R_NO_CIPHERS_SPECIFIED 183 +#define SSL_R_NO_CIPHER_LIST 184 +#define SSL_R_NO_CIPHER_MATCH 185 +#define SSL_R_NO_CLIENT_CERT_METHOD 331 +#define SSL_R_NO_CLIENT_CERT_RECEIVED 186 +#define SSL_R_NO_COMPRESSION_SPECIFIED 187 +#define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 330 +#define SSL_R_NO_METHOD_SPECIFIED 188 +#define SSL_R_NO_PRIVATEKEY 189 +#define SSL_R_NO_PRIVATE_KEY_ASSIGNED 190 +#define SSL_R_NO_PROTOCOLS_AVAILABLE 191 +#define SSL_R_NO_PUBLICKEY 192 +#define SSL_R_NO_RENEGOTIATION 339 +#define SSL_R_NO_REQUIRED_DIGEST 324 +#define SSL_R_NO_SHARED_CIPHER 193 +#define SSL_R_NO_SRTP_PROFILES 359 +#define SSL_R_NO_VERIFY_CALLBACK 194 +#define SSL_R_NULL_SSL_CTX 195 +#define SSL_R_NULL_SSL_METHOD_PASSED 196 +#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197 +#define SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED 344 +#define SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE 297 +#define SSL_R_PACKET_LENGTH_TOO_LONG 198 +#define SSL_R_PARSE_TLSEXT 227 +#define SSL_R_PATH_TOO_LONG 270 +#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199 +#define SSL_R_PEER_ERROR 200 +#define SSL_R_PEER_ERROR_CERTIFICATE 201 +#define SSL_R_PEER_ERROR_NO_CERTIFICATE 202 +#define SSL_R_PEER_ERROR_NO_CIPHER 203 +#define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 204 +#define SSL_R_PRE_MAC_LENGTH_TOO_LONG 205 +#define SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS 206 +#define SSL_R_PROTOCOL_IS_SHUTDOWN 207 +#define SSL_R_PSK_IDENTITY_NOT_FOUND 223 +#define SSL_R_PSK_NO_CLIENT_CB 224 +#define SSL_R_PSK_NO_SERVER_CB 225 +#define SSL_R_PUBLIC_KEY_ENCRYPT_ERROR 208 +#define SSL_R_PUBLIC_KEY_IS_NOT_RSA 209 +#define SSL_R_PUBLIC_KEY_NOT_RSA 210 +#define SSL_R_READ_BIO_NOT_SET 211 +#define SSL_R_READ_TIMEOUT_EXPIRED 312 +#define SSL_R_READ_WRONG_PACKET_TYPE 212 +#define SSL_R_RECORD_LENGTH_MISMATCH 213 +#define SSL_R_RECORD_TOO_LARGE 214 +#define SSL_R_RECORD_TOO_SMALL 298 +#define SSL_R_RENEGOTIATE_EXT_TOO_LONG 335 +#define SSL_R_RENEGOTIATION_ENCODING_ERR 336 +#define SSL_R_RENEGOTIATION_MISMATCH 337 +#define SSL_R_REQUIRED_CIPHER_MISSING 215 +#define SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING 342 +#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216 +#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217 +#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218 +#define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 345 +#define SSL_R_SERVERHELLO_TLSEXT 275 +#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277 +#define SSL_R_SHORT_READ 219 +#define SSL_R_SIGNATURE_ALGORITHMS_ERROR 360 +#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220 +#define SSL_R_SRP_A_CALC 361 +#define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 362 +#define SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG 363 +#define SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE 364 +#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221 +#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 299 +#define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT 321 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319 +#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320 +#define SSL_R_SSL3_SESSION_ID_TOO_LONG 300 +#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222 +#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042 +#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044 +#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046 +#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030 +#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040 +#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047 +#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041 +#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 +#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043 +#define SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION 228 +#define SSL_R_SSL_HANDSHAKE_FAILURE 229 +#define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 230 +#define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 301 +#define SSL_R_SSL_SESSION_ID_CONFLICT 302 +#define SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG 273 +#define SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH 303 +#define SSL_R_SSL_SESSION_ID_IS_DIFFERENT 231 +#define SSL_R_SSL_SESSION_ID_TOO_LONG 408 +#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049 +#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050 +#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021 +#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051 +#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060 +#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086 +#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071 +#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080 +#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100 +#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070 +#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022 +#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048 +#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090 +#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114 +#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113 +#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111 +#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112 +#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 +#define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 +#define SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT 365 +#define SSL_R_TLS_HEARTBEAT_PENDING 366 +#define SSL_R_TLS_ILLEGAL_EXPORTER_LABEL 367 +#define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 157 +#define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 +#define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 +#define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 +#define SSL_R_UNABLE_TO_DECODE_DH_CERTS 236 +#define SSL_R_UNABLE_TO_DECODE_ECDH_CERTS 313 +#define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 237 +#define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 238 +#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 314 +#define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239 +#define SSL_R_UNABLE_TO_FIND_SSL_METHOD 240 +#define SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES 241 +#define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242 +#define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243 +#define SSL_R_UNEXPECTED_MESSAGE 244 +#define SSL_R_UNEXPECTED_RECORD 245 +#define SSL_R_UNINITIALIZED 276 +#define SSL_R_UNKNOWN_ALERT_TYPE 246 +#define SSL_R_UNKNOWN_CERTIFICATE_TYPE 247 +#define SSL_R_UNKNOWN_CIPHER_RETURNED 248 +#define SSL_R_UNKNOWN_CIPHER_TYPE 249 +#define SSL_R_UNKNOWN_DIGEST 368 +#define SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE 250 +#define SSL_R_UNKNOWN_PKEY_TYPE 251 +#define SSL_R_UNKNOWN_PROTOCOL 252 +#define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 253 +#define SSL_R_UNKNOWN_SSL_VERSION 254 +#define SSL_R_UNKNOWN_STATE 255 +#define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 338 +#define SSL_R_UNSUPPORTED_CIPHER 256 +#define SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM 257 +#define SSL_R_UNSUPPORTED_DIGEST_TYPE 326 +#define SSL_R_UNSUPPORTED_ELLIPTIC_CURVE 315 +#define SSL_R_UNSUPPORTED_PROTOCOL 258 +#define SSL_R_UNSUPPORTED_SSL_VERSION 259 +#define SSL_R_UNSUPPORTED_STATUS_TYPE 329 +#define SSL_R_USE_SRTP_NOT_NEGOTIATED 369 +#define SSL_R_VERSION_TOO_LOW 396 +#define SSL_R_WRITE_BIO_NOT_SET 260 +#define SSL_R_WRONG_CIPHER_RETURNED 261 +#define SSL_R_WRONG_CURVE 378 +#define SSL_R_WRONG_MESSAGE_TYPE 262 +#define SSL_R_WRONG_NUMBER_OF_KEY_BITS 263 +#define SSL_R_WRONG_SIGNATURE_LENGTH 264 +#define SSL_R_WRONG_SIGNATURE_SIZE 265 +#define SSL_R_WRONG_SIGNATURE_TYPE 370 +#define SSL_R_WRONG_SSL_VERSION 266 +#define SSL_R_WRONG_VERSION_NUMBER 267 +#define SSL_R_X509_LIB 268 +#define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 269 +#define SSL_R_PEER_BEHAVING_BADLY 666 +#define SSL_R_QUIC_INTERNAL_ERROR 667 +#define SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED 668 +#define SSL_R_UNKNOWN 999 + +/* + * OpenSSL compatible OPENSSL_INIT options + */ + +/* + * These are provided for compatibility, but have no effect + * on how LibreSSL is initialized. + */ +#define OPENSSL_INIT_LOAD_SSL_STRINGS _OPENSSL_INIT_FLAG_NOOP +#define OPENSSL_INIT_SSL_DEFAULT _OPENSSL_INIT_FLAG_NOOP + +int OPENSSL_init_ssl(uint64_t opts, const void *settings); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ssl2.h b/include/openssl/ssl2.h new file mode 100644 index 0000000..3a8d300 --- /dev/null +++ b/include/openssl/ssl2.h @@ -0,0 +1,153 @@ +/* $OpenBSD: ssl2.h,v 1.12 2014/12/14 15:30:50 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL2_H +#define HEADER_SSL2_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Protocol Version Codes */ +#define SSL2_VERSION 0x0002 +#define SSL2_VERSION_MAJOR 0x00 +#define SSL2_VERSION_MINOR 0x02 +/* #define SSL2_CLIENT_VERSION 0x0002 */ +/* #define SSL2_SERVER_VERSION 0x0002 */ + +/* Protocol Message Codes */ +#define SSL2_MT_ERROR 0 +#define SSL2_MT_CLIENT_HELLO 1 +#define SSL2_MT_CLIENT_MASTER_KEY 2 +#define SSL2_MT_CLIENT_FINISHED 3 +#define SSL2_MT_SERVER_HELLO 4 +#define SSL2_MT_SERVER_VERIFY 5 +#define SSL2_MT_SERVER_FINISHED 6 +#define SSL2_MT_REQUEST_CERTIFICATE 7 +#define SSL2_MT_CLIENT_CERTIFICATE 8 + +/* Error Message Codes */ +#define SSL2_PE_UNDEFINED_ERROR 0x0000 +#define SSL2_PE_NO_CIPHER 0x0001 +#define SSL2_PE_NO_CERTIFICATE 0x0002 +#define SSL2_PE_BAD_CERTIFICATE 0x0004 +#define SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE 0x0006 + +/* Cipher Kind Values */ +#define SSL2_CK_NULL_WITH_MD5 0x02000000 /* v3 */ +#define SSL2_CK_RC4_128_WITH_MD5 0x02010080 +#define SSL2_CK_RC4_128_EXPORT40_WITH_MD5 0x02020080 +#define SSL2_CK_RC2_128_CBC_WITH_MD5 0x02030080 +#define SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5 0x02040080 +#define SSL2_CK_IDEA_128_CBC_WITH_MD5 0x02050080 +#define SSL2_CK_DES_64_CBC_WITH_MD5 0x02060040 +#define SSL2_CK_DES_64_CBC_WITH_SHA 0x02060140 /* v3 */ +#define SSL2_CK_DES_192_EDE3_CBC_WITH_MD5 0x020700c0 +#define SSL2_CK_DES_192_EDE3_CBC_WITH_SHA 0x020701c0 /* v3 */ +#define SSL2_CK_RC4_64_WITH_MD5 0x02080080 /* MS hack */ + +#define SSL2_CK_DES_64_CFB64_WITH_MD5_1 0x02ff0800 /* SSLeay */ +#define SSL2_CK_NULL 0x02ff0810 /* SSLeay */ + +#define SSL2_TXT_DES_64_CFB64_WITH_MD5_1 "DES-CFB-M1" +#define SSL2_TXT_NULL_WITH_MD5 "NULL-MD5" +#define SSL2_TXT_RC4_128_WITH_MD5 "RC4-MD5" +#define SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 "EXP-RC4-MD5" +#define SSL2_TXT_RC2_128_CBC_WITH_MD5 "RC2-CBC-MD5" +#define SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 "EXP-RC2-CBC-MD5" +#define SSL2_TXT_IDEA_128_CBC_WITH_MD5 "IDEA-CBC-MD5" +#define SSL2_TXT_DES_64_CBC_WITH_MD5 "DES-CBC-MD5" +#define SSL2_TXT_DES_64_CBC_WITH_SHA "DES-CBC-SHA" +#define SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 "DES-CBC3-MD5" +#define SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA "DES-CBC3-SHA" +#define SSL2_TXT_RC4_64_WITH_MD5 "RC4-64-MD5" + +#define SSL2_TXT_NULL "NULL" + +/* Flags for the SSL_CIPHER.algorithm2 field */ +#define SSL2_CF_5_BYTE_ENC 0x01 +#define SSL2_CF_8_BYTE_ENC 0x02 + +/* Certificate Type Codes */ +#define SSL2_CT_X509_CERTIFICATE 0x01 + +/* Authentication Type Code */ +#define SSL2_AT_MD5_WITH_RSA_ENCRYPTION 0x01 + +#define SSL2_MAX_SSL_SESSION_ID_LENGTH 32 + +/* Upper/Lower Bounds */ +#define SSL2_MAX_MASTER_KEY_LENGTH_IN_BITS 256 +#define SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER 32767u /* 2^15-1 */ +#define SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER 16383 /* 2^14-1 */ + +#define SSL2_CHALLENGE_LENGTH 16 +/*#define SSL2_CHALLENGE_LENGTH 32 */ +#define SSL2_MIN_CHALLENGE_LENGTH 16 +#define SSL2_MAX_CHALLENGE_LENGTH 32 +#define SSL2_CONNECTION_ID_LENGTH 16 +#define SSL2_MAX_CONNECTION_ID_LENGTH 16 +#define SSL2_SSL_SESSION_ID_LENGTH 16 +#define SSL2_MAX_CERT_CHALLENGE_LENGTH 32 +#define SSL2_MIN_CERT_CHALLENGE_LENGTH 16 +#define SSL2_MAX_KEY_MATERIAL_LENGTH 24 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ssl23.h b/include/openssl/ssl23.h new file mode 100644 index 0000000..570e4b0 --- /dev/null +++ b/include/openssl/ssl23.h @@ -0,0 +1,82 @@ +/* $OpenBSD: ssl23.h,v 1.4 2014/12/14 15:30:50 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SSL23_H +#define HEADER_SSL23_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*client */ +/* write to server */ +#define SSL23_ST_CW_CLNT_HELLO_A (0x210|SSL_ST_CONNECT) +#define SSL23_ST_CW_CLNT_HELLO_B (0x211|SSL_ST_CONNECT) +/* read from server */ +#define SSL23_ST_CR_SRVR_HELLO_A (0x220|SSL_ST_CONNECT) +#define SSL23_ST_CR_SRVR_HELLO_B (0x221|SSL_ST_CONNECT) + +/* server */ +/* read from client */ +#define SSL23_ST_SR_CLNT_HELLO_A (0x210|SSL_ST_ACCEPT) +#define SSL23_ST_SR_CLNT_HELLO_B (0x211|SSL_ST_ACCEPT) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h new file mode 100644 index 0000000..6c6cc2a --- /dev/null +++ b/include/openssl/ssl3.h @@ -0,0 +1,455 @@ +/* $OpenBSD: ssl3.h,v 1.57 2021/09/10 14:49:13 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_SSL3_H +#define HEADER_SSL3_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* TLS_EMPTY_RENEGOTIATION_INFO_SCSV from RFC 5746. */ +#define SSL3_CK_SCSV 0x030000FF + +/* TLS_FALLBACK_SCSV from draft-ietf-tls-downgrade-scsv-03. */ +#define SSL3_CK_FALLBACK_SCSV 0x03005600 + +#define SSL3_CK_RSA_NULL_MD5 0x03000001 +#define SSL3_CK_RSA_NULL_SHA 0x03000002 +#define SSL3_CK_RSA_RC4_40_MD5 0x03000003 +#define SSL3_CK_RSA_RC4_128_MD5 0x03000004 +#define SSL3_CK_RSA_RC4_128_SHA 0x03000005 +#define SSL3_CK_RSA_RC2_40_MD5 0x03000006 +#define SSL3_CK_RSA_IDEA_128_SHA 0x03000007 +#define SSL3_CK_RSA_DES_40_CBC_SHA 0x03000008 +#define SSL3_CK_RSA_DES_64_CBC_SHA 0x03000009 +#define SSL3_CK_RSA_DES_192_CBC3_SHA 0x0300000A + +#define SSL3_CK_DH_DSS_DES_40_CBC_SHA 0x0300000B +#define SSL3_CK_DH_DSS_DES_64_CBC_SHA 0x0300000C +#define SSL3_CK_DH_DSS_DES_192_CBC3_SHA 0x0300000D +#define SSL3_CK_DH_RSA_DES_40_CBC_SHA 0x0300000E +#define SSL3_CK_DH_RSA_DES_64_CBC_SHA 0x0300000F +#define SSL3_CK_DH_RSA_DES_192_CBC3_SHA 0x03000010 + +#define SSL3_CK_EDH_DSS_DES_40_CBC_SHA 0x03000011 +#define SSL3_CK_EDH_DSS_DES_64_CBC_SHA 0x03000012 +#define SSL3_CK_EDH_DSS_DES_192_CBC3_SHA 0x03000013 +#define SSL3_CK_EDH_RSA_DES_40_CBC_SHA 0x03000014 +#define SSL3_CK_EDH_RSA_DES_64_CBC_SHA 0x03000015 +#define SSL3_CK_EDH_RSA_DES_192_CBC3_SHA 0x03000016 + +#define SSL3_CK_ADH_RC4_40_MD5 0x03000017 +#define SSL3_CK_ADH_RC4_128_MD5 0x03000018 +#define SSL3_CK_ADH_DES_40_CBC_SHA 0x03000019 +#define SSL3_CK_ADH_DES_64_CBC_SHA 0x0300001A +#define SSL3_CK_ADH_DES_192_CBC_SHA 0x0300001B + +/* VRS Additional Kerberos5 entries + */ +#define SSL3_CK_KRB5_DES_64_CBC_SHA 0x0300001E +#define SSL3_CK_KRB5_DES_192_CBC3_SHA 0x0300001F +#define SSL3_CK_KRB5_RC4_128_SHA 0x03000020 +#define SSL3_CK_KRB5_IDEA_128_CBC_SHA 0x03000021 +#define SSL3_CK_KRB5_DES_64_CBC_MD5 0x03000022 +#define SSL3_CK_KRB5_DES_192_CBC3_MD5 0x03000023 +#define SSL3_CK_KRB5_RC4_128_MD5 0x03000024 +#define SSL3_CK_KRB5_IDEA_128_CBC_MD5 0x03000025 + +#define SSL3_CK_KRB5_DES_40_CBC_SHA 0x03000026 +#define SSL3_CK_KRB5_RC2_40_CBC_SHA 0x03000027 +#define SSL3_CK_KRB5_RC4_40_SHA 0x03000028 +#define SSL3_CK_KRB5_DES_40_CBC_MD5 0x03000029 +#define SSL3_CK_KRB5_RC2_40_CBC_MD5 0x0300002A +#define SSL3_CK_KRB5_RC4_40_MD5 0x0300002B + +#define SSL3_TXT_RSA_NULL_MD5 "NULL-MD5" +#define SSL3_TXT_RSA_NULL_SHA "NULL-SHA" +#define SSL3_TXT_RSA_RC4_40_MD5 "EXP-RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_MD5 "RC4-MD5" +#define SSL3_TXT_RSA_RC4_128_SHA "RC4-SHA" +#define SSL3_TXT_RSA_RC2_40_MD5 "EXP-RC2-CBC-MD5" +#define SSL3_TXT_RSA_IDEA_128_SHA "IDEA-CBC-SHA" +#define SSL3_TXT_RSA_DES_40_CBC_SHA "EXP-DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_64_CBC_SHA "DES-CBC-SHA" +#define SSL3_TXT_RSA_DES_192_CBC3_SHA "DES-CBC3-SHA" + +#define SSL3_TXT_DH_DSS_DES_40_CBC_SHA "EXP-DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_64_CBC_SHA "DH-DSS-DES-CBC-SHA" +#define SSL3_TXT_DH_DSS_DES_192_CBC3_SHA "DH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_DH_RSA_DES_40_CBC_SHA "EXP-DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_64_CBC_SHA "DH-RSA-DES-CBC-SHA" +#define SSL3_TXT_DH_RSA_DES_192_CBC3_SHA "DH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_EDH_DSS_DES_40_CBC_SHA "EXP-EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_64_CBC_SHA "EDH-DSS-DES-CBC-SHA" +#define SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA "EDH-DSS-DES-CBC3-SHA" +#define SSL3_TXT_EDH_RSA_DES_40_CBC_SHA "EXP-EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_64_CBC_SHA "EDH-RSA-DES-CBC-SHA" +#define SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA "EDH-RSA-DES-CBC3-SHA" + +#define SSL3_TXT_ADH_RC4_40_MD5 "EXP-ADH-RC4-MD5" +#define SSL3_TXT_ADH_RC4_128_MD5 "ADH-RC4-MD5" +#define SSL3_TXT_ADH_DES_40_CBC_SHA "EXP-ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_64_CBC_SHA "ADH-DES-CBC-SHA" +#define SSL3_TXT_ADH_DES_192_CBC_SHA "ADH-DES-CBC3-SHA" + +#define SSL3_TXT_KRB5_DES_64_CBC_SHA "KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_DES_192_CBC3_SHA "KRB5-DES-CBC3-SHA" +#define SSL3_TXT_KRB5_RC4_128_SHA "KRB5-RC4-SHA" +#define SSL3_TXT_KRB5_IDEA_128_CBC_SHA "KRB5-IDEA-CBC-SHA" +#define SSL3_TXT_KRB5_DES_64_CBC_MD5 "KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_DES_192_CBC3_MD5 "KRB5-DES-CBC3-MD5" +#define SSL3_TXT_KRB5_RC4_128_MD5 "KRB5-RC4-MD5" +#define SSL3_TXT_KRB5_IDEA_128_CBC_MD5 "KRB5-IDEA-CBC-MD5" + +#define SSL3_TXT_KRB5_DES_40_CBC_SHA "EXP-KRB5-DES-CBC-SHA" +#define SSL3_TXT_KRB5_RC2_40_CBC_SHA "EXP-KRB5-RC2-CBC-SHA" +#define SSL3_TXT_KRB5_RC4_40_SHA "EXP-KRB5-RC4-SHA" +#define SSL3_TXT_KRB5_DES_40_CBC_MD5 "EXP-KRB5-DES-CBC-MD5" +#define SSL3_TXT_KRB5_RC2_40_CBC_MD5 "EXP-KRB5-RC2-CBC-MD5" +#define SSL3_TXT_KRB5_RC4_40_MD5 "EXP-KRB5-RC4-MD5" + +#define SSL3_SSL_SESSION_ID_LENGTH 32 +#define SSL3_MAX_SSL_SESSION_ID_LENGTH 32 + +#define SSL3_MASTER_SECRET_SIZE 48 +#define SSL3_RANDOM_SIZE 32 +#define SSL3_SEQUENCE_SIZE 8 +#define SSL3_SESSION_ID_SIZE 32 +#define SSL3_CIPHER_VALUE_SIZE 2 + +#define SSL3_RT_HEADER_LENGTH 5 +#define SSL3_HM_HEADER_LENGTH 4 + +#define SSL3_ALIGN_PAYLOAD 8 + +/* This is the maximum MAC (digest) size used by the SSL library. + * Currently maximum of 20 is used by SHA1, but we reserve for + * future extension for 512-bit hashes. + */ + +#define SSL3_RT_MAX_MD_SIZE 64 + +/* Maximum block size used in all ciphersuites. Currently 16 for AES. + */ + +#define SSL_RT_MAX_CIPHER_BLOCK_SIZE 16 + +#define SSL3_RT_MAX_EXTRA (16384) + +/* Maximum plaintext length: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_PLAIN_LENGTH 16384 +/* Maximum compression overhead: defined by SSL/TLS standards */ +#define SSL3_RT_MAX_COMPRESSED_OVERHEAD 1024 + +/* The standards give a maximum encryption overhead of 1024 bytes. + * In practice the value is lower than this. The overhead is the maximum + * number of padding bytes (256) plus the mac size. + */ +#define SSL3_RT_MAX_ENCRYPTED_OVERHEAD (256 + SSL3_RT_MAX_MD_SIZE) + +/* OpenSSL currently only uses a padding length of at most one block so + * the send overhead is smaller. + */ + +#define SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD \ + (SSL_RT_MAX_CIPHER_BLOCK_SIZE + SSL3_RT_MAX_MD_SIZE) + +/* If compression isn't used don't include the compression overhead */ +#define SSL3_RT_MAX_COMPRESSED_LENGTH SSL3_RT_MAX_PLAIN_LENGTH +#define SSL3_RT_MAX_ENCRYPTED_LENGTH \ + (SSL3_RT_MAX_ENCRYPTED_OVERHEAD+SSL3_RT_MAX_COMPRESSED_LENGTH) +#define SSL3_RT_MAX_PACKET_SIZE \ + (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) + +#define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" +#define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" + +#define SSL3_VERSION 0x0300 +#define SSL3_VERSION_MAJOR 0x03 +#define SSL3_VERSION_MINOR 0x00 + +#define SSL3_RT_CHANGE_CIPHER_SPEC 20 +#define SSL3_RT_ALERT 21 +#define SSL3_RT_HANDSHAKE 22 +#define SSL3_RT_APPLICATION_DATA 23 + +#define SSL3_AL_WARNING 1 +#define SSL3_AL_FATAL 2 + +#ifndef LIBRESSL_INTERNAL +#define SSL3_AD_CLOSE_NOTIFY 0 +#define SSL3_AD_UNEXPECTED_MESSAGE 10 /* fatal */ +#define SSL3_AD_BAD_RECORD_MAC 20 /* fatal */ +#define SSL3_AD_DECOMPRESSION_FAILURE 30 /* fatal */ +#define SSL3_AD_HANDSHAKE_FAILURE 40 /* fatal */ +#define SSL3_AD_NO_CERTIFICATE 41 +#define SSL3_AD_BAD_CERTIFICATE 42 +#define SSL3_AD_UNSUPPORTED_CERTIFICATE 43 +#define SSL3_AD_CERTIFICATE_REVOKED 44 +#define SSL3_AD_CERTIFICATE_EXPIRED 45 +#define SSL3_AD_CERTIFICATE_UNKNOWN 46 +#define SSL3_AD_ILLEGAL_PARAMETER 47 /* fatal */ +#endif + +#define TLS1_HB_REQUEST 1 +#define TLS1_HB_RESPONSE 2 + +#define SSL3_CT_RSA_SIGN 1 +#define SSL3_CT_DSS_SIGN 2 +#define SSL3_CT_RSA_FIXED_DH 3 +#define SSL3_CT_DSS_FIXED_DH 4 +#define SSL3_CT_RSA_EPHEMERAL_DH 5 +#define SSL3_CT_DSS_EPHEMERAL_DH 6 +#define SSL3_CT_FORTEZZA_DMS 20 +/* SSL3_CT_NUMBER is used to size arrays and it must be large + * enough to contain all of the cert types defined either for + * SSLv3 and TLSv1. + */ +#define SSL3_CT_NUMBER 13 + +#define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 +#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 +#define TLS1_FLAGS_FREEZE_TRANSCRIPT 0x0020 +#define SSL3_FLAGS_CCS_OK 0x0080 + +/* SSLv3 */ +/*client */ +/* extra state */ +#define SSL3_ST_CW_FLUSH (0x100|SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CLNT_HELLO_A (0x110|SSL_ST_CONNECT) +#define SSL3_ST_CW_CLNT_HELLO_B (0x111|SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_SRVR_HELLO_A (0x120|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_HELLO_B (0x121|SSL_ST_CONNECT) +#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126|SSL_ST_CONNECT) +#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_A (0x130|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_B (0x131|SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_A (0x140|SSL_ST_CONNECT) +#define SSL3_ST_CR_KEY_EXCH_B (0x141|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_REQ_A (0x150|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_REQ_B (0x151|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_DONE_A (0x160|SSL_ST_CONNECT) +#define SSL3_ST_CR_SRVR_DONE_B (0x161|SSL_ST_CONNECT) +/* write to server */ +#define SSL3_ST_CW_CERT_A (0x170|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_B (0x171|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_C (0x172|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_D (0x173|SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_A (0x180|SSL_ST_CONNECT) +#define SSL3_ST_CW_KEY_EXCH_B (0x181|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_A (0x190|SSL_ST_CONNECT) +#define SSL3_ST_CW_CERT_VRFY_B (0x191|SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_A (0x1A0|SSL_ST_CONNECT) +#define SSL3_ST_CW_CHANGE_B (0x1A1|SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_A (0x1B0|SSL_ST_CONNECT) +#define SSL3_ST_CW_FINISHED_B (0x1B1|SSL_ST_CONNECT) +/* read from server */ +#define SSL3_ST_CR_CHANGE_A (0x1C0|SSL_ST_CONNECT) +#define SSL3_ST_CR_CHANGE_B (0x1C1|SSL_ST_CONNECT) +#define SSL3_ST_CR_FINISHED_A (0x1D0|SSL_ST_CONNECT) +#define SSL3_ST_CR_FINISHED_B (0x1D1|SSL_ST_CONNECT) +#define SSL3_ST_CR_SESSION_TICKET_A (0x1E0|SSL_ST_CONNECT) +#define SSL3_ST_CR_SESSION_TICKET_B (0x1E1|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_STATUS_A (0x1F0|SSL_ST_CONNECT) +#define SSL3_ST_CR_CERT_STATUS_B (0x1F1|SSL_ST_CONNECT) + +/* server */ +/* extra state */ +#define SSL3_ST_SW_FLUSH (0x100|SSL_ST_ACCEPT) +/* read from client */ +/* Do not change the number values, they do matter */ +#define SSL3_ST_SR_CLNT_HELLO_A (0x110|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_B (0x111|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CLNT_HELLO_C (0x112|SSL_ST_ACCEPT) +/* write to client */ +#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A (0x113|SSL_ST_ACCEPT) +#define DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B (0x114|SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_A (0x120|SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_B (0x121|SSL_ST_ACCEPT) +#define SSL3_ST_SW_HELLO_REQ_C (0x122|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_A (0x130|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_HELLO_B (0x131|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_A (0x140|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_B (0x141|SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_A (0x150|SSL_ST_ACCEPT) +#define SSL3_ST_SW_KEY_EXCH_B (0x151|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_A (0x160|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_REQ_B (0x161|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_A (0x170|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SRVR_DONE_B (0x171|SSL_ST_ACCEPT) +/* read from client */ +#define SSL3_ST_SR_CERT_A (0x180|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_B (0x181|SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_A (0x190|SSL_ST_ACCEPT) +#define SSL3_ST_SR_KEY_EXCH_B (0x191|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_VRFY_A (0x1A0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CERT_VRFY_B (0x1A1|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANGE_A (0x1B0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_CHANGE_B (0x1B1|SSL_ST_ACCEPT) +#define SSL3_ST_SR_FINISHED_A (0x1C0|SSL_ST_ACCEPT) +#define SSL3_ST_SR_FINISHED_B (0x1C1|SSL_ST_ACCEPT) +/* write to client */ +#define SSL3_ST_SW_CHANGE_A (0x1D0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CHANGE_B (0x1D1|SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SESSION_TICKET_A (0x1F0|SSL_ST_ACCEPT) +#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_A (0x200|SSL_ST_ACCEPT) +#define SSL3_ST_SW_CERT_STATUS_B (0x201|SSL_ST_ACCEPT) + +#define SSL3_MT_HELLO_REQUEST 0 +#define SSL3_MT_CLIENT_HELLO 1 +#define SSL3_MT_SERVER_HELLO 2 +#define SSL3_MT_NEWSESSION_TICKET 4 +#define SSL3_MT_CERTIFICATE 11 +#define SSL3_MT_SERVER_KEY_EXCHANGE 12 +#define SSL3_MT_CERTIFICATE_REQUEST 13 +#define SSL3_MT_SERVER_DONE 14 +#define SSL3_MT_CERTIFICATE_VERIFY 15 +#define SSL3_MT_CLIENT_KEY_EXCHANGE 16 +#define SSL3_MT_FINISHED 20 +#define SSL3_MT_CERTIFICATE_STATUS 22 + +#define DTLS1_MT_HELLO_VERIFY_REQUEST 3 + +#define SSL3_MT_CCS 1 + +#ifndef LIBRESSL_INTERNAL +/* These are used when changing over to a new cipher */ +#define SSL3_CC_READ 0x01 +#define SSL3_CC_WRITE 0x02 +#define SSL3_CC_CLIENT 0x10 +#define SSL3_CC_SERVER 0x20 +#define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE) +#define SSL3_CHANGE_CIPHER_SERVER_READ (SSL3_CC_SERVER|SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ) +#define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE) +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/stack.h b/include/openssl/stack.h new file mode 100644 index 0000000..6bea634 --- /dev/null +++ b/include/openssl/stack.h @@ -0,0 +1,107 @@ +/* $OpenBSD: stack.h,v 1.9 2014/06/12 15:49:30 deraadt Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_STACK_H +#define HEADER_STACK_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stack_st { + int num; + char **data; + int sorted; + + int num_alloc; + int (*comp)(const void *, const void *); +} _STACK; /* Use STACK_OF(...) instead */ + +#define M_sk_num(sk) ((sk) ? (sk)->num:-1) +#define M_sk_value(sk,n) ((sk) ? (sk)->data[n] : NULL) + +int sk_num(const _STACK *); +void *sk_value(const _STACK *, int); + +void *sk_set(_STACK *, int, void *); + +_STACK *sk_new(int (*cmp)(const void *, const void *)); +_STACK *sk_new_null(void); +void sk_free(_STACK *); +void sk_pop_free(_STACK *st, void (*func)(void *)); +int sk_insert(_STACK *sk, void *data, int where); +void *sk_delete(_STACK *st, int loc); +void *sk_delete_ptr(_STACK *st, void *p); +int sk_find(_STACK *st, void *data); +int sk_find_ex(_STACK *st, void *data); +int sk_push(_STACK *st, void *data); +int sk_unshift(_STACK *st, void *data); +void *sk_shift(_STACK *st); +void *sk_pop(_STACK *st); +void sk_zero(_STACK *st); +int (*sk_set_cmp_func(_STACK *sk, int (*c)(const void *, const void *)))( + const void *, const void *); +_STACK *sk_dup(_STACK *st); +void sk_sort(_STACK *st); +int sk_is_sorted(const _STACK *st); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h new file mode 100644 index 0000000..2bdbd3c --- /dev/null +++ b/include/openssl/tls1.h @@ -0,0 +1,780 @@ +/* $OpenBSD: tls1.h,v 1.56 2022/07/17 14:39:09 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_TLS1_H +#define HEADER_TLS1_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OPENSSL_TLS_SECURITY_LEVEL 1 + +#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0 + +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define TLS1_3_VERSION 0x0304 +#endif + +#define TLS1_2_VERSION 0x0303 +#define TLS1_2_VERSION_MAJOR 0x03 +#define TLS1_2_VERSION_MINOR 0x03 + +#define TLS1_1_VERSION 0x0302 +#define TLS1_1_VERSION_MAJOR 0x03 +#define TLS1_1_VERSION_MINOR 0x02 + +#define TLS1_VERSION 0x0301 +#define TLS1_VERSION_MAJOR 0x03 +#define TLS1_VERSION_MINOR 0x01 + +#ifndef LIBRESSL_INTERNAL +#define TLS1_AD_DECRYPTION_FAILED 21 +#define TLS1_AD_RECORD_OVERFLOW 22 +#define TLS1_AD_UNKNOWN_CA 48 /* fatal */ +#define TLS1_AD_ACCESS_DENIED 49 /* fatal */ +#define TLS1_AD_DECODE_ERROR 50 /* fatal */ +#define TLS1_AD_DECRYPT_ERROR 51 +#define TLS1_AD_EXPORT_RESTRICTION 60 /* fatal */ +#define TLS1_AD_PROTOCOL_VERSION 70 /* fatal */ +#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */ +#define TLS1_AD_INTERNAL_ERROR 80 /* fatal */ +/* Code 86 from RFC 7507. */ +#define TLS1_AD_INAPPROPRIATE_FALLBACK 86 /* fatal */ +#define TLS1_AD_USER_CANCELLED 90 +#define TLS1_AD_NO_RENEGOTIATION 100 +/* Codes 110-114 from RFC 3546. */ +#define TLS1_AD_UNSUPPORTED_EXTENSION 110 +#define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111 +#define TLS1_AD_UNRECOGNIZED_NAME 112 +#define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114 +/* Code 115 from RFC 4279. */ +#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */ +#endif + +/* + * TLS ExtensionType values. + * + * https://www.iana.org/assignments/tls-extensiontype-values/ + */ + +/* ExtensionType values from RFC 3546, RFC 4366 and RFC 6066. */ +#define TLSEXT_TYPE_server_name 0 +#define TLSEXT_TYPE_max_fragment_length 1 +#define TLSEXT_TYPE_client_certificate_url 2 +#define TLSEXT_TYPE_trusted_ca_keys 3 +#define TLSEXT_TYPE_truncated_hmac 4 +#define TLSEXT_TYPE_status_request 5 + +/* ExtensionType values from RFC 4681. */ +#define TLSEXT_TYPE_user_mapping 6 + +/* ExtensionType values from RFC 5878. */ +#define TLSEXT_TYPE_client_authz 7 +#define TLSEXT_TYPE_server_authz 8 + +/* ExtensionType values from RFC 6091. */ +#define TLSEXT_TYPE_cert_type 9 + +/* ExtensionType values from RFC 7919. */ +#define TLSEXT_TYPE_supported_groups 10 + +/* ExtensionType values from RFC 4492. */ +#ifndef LIBRESSL_INTERNAL +#define TLSEXT_TYPE_elliptic_curves TLSEXT_TYPE_supported_groups +#endif +#define TLSEXT_TYPE_ec_point_formats 11 + +/* ExtensionType value from RFC 5054. */ +#define TLSEXT_TYPE_srp 12 + +/* ExtensionType value from RFC 5246/RFC 8446. */ +#define TLSEXT_TYPE_signature_algorithms 13 + +/* ExtensionType value from RFC 5764. */ +#define TLSEXT_TYPE_use_srtp 14 + +/* ExtensionType value from RFC 5620. */ +#define TLSEXT_TYPE_heartbeat 15 + +/* ExtensionType value from RFC 7301. */ +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +/* ExtensionType value from RFC 7685. */ +#define TLSEXT_TYPE_padding 21 + +/* ExtensionType value from RFC 4507. */ +#define TLSEXT_TYPE_session_ticket 35 + +/* ExtensionType values from RFC 8446 section 4.2 */ +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define TLSEXT_TYPE_pre_shared_key 41 +#define TLSEXT_TYPE_early_data 42 +#define TLSEXT_TYPE_supported_versions 43 +#define TLSEXT_TYPE_cookie 44 +#define TLSEXT_TYPE_psk_key_exchange_modes 45 +#define TLSEXT_TYPE_certificate_authorities 47 +#define TLSEXT_TYPE_oid_filters 48 +#define TLSEXT_TYPE_post_handshake_auth 49 +#define TLSEXT_TYPE_signature_algorithms_cert 50 +#define TLSEXT_TYPE_key_share 51 +#endif + +/* ExtensionType value from RFC 9001 section 8.2 */ +#if defined(LIBRESSL_HAS_QUIC) || defined(LIBRESSL_INTERNAL) +#define TLSEXT_TYPE_quic_transport_parameters 57 +#endif + +/* + * TLS 1.3 extension names from OpenSSL, where they decided to use a different + * name from that given in RFC 8446. + */ +#if defined(LIBRESSL_HAS_TLS1_3) +#define TLSEXT_TYPE_psk TLSEXT_TYPE_pre_shared_key +#define TLSEXT_TYPE_psk_kex_modes TLSEXT_TYPE_psk_key_exchange_modes +#endif + +/* Temporary extension type */ +#define TLSEXT_TYPE_renegotiate 0xff01 + +/* NameType value from RFC 3546. */ +#define TLSEXT_NAMETYPE_host_name 0 +/* status request value from RFC 3546 */ +#define TLSEXT_STATUSTYPE_ocsp 1 + +/* ECPointFormat values from RFC 4492. */ +#define TLSEXT_ECPOINTFORMAT_first 0 +#define TLSEXT_ECPOINTFORMAT_uncompressed 0 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1 +#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2 +#define TLSEXT_ECPOINTFORMAT_last 2 + +#define TLSEXT_MAXLEN_host_name 255 + +const char *SSL_get_servername(const SSL *s, const int type); +int SSL_get_servername_type(const SSL *s); +/* SSL_export_keying_material exports a value derived from the master secret, + * as specified in RFC 5705. It writes |olen| bytes to |out| given a label and + * optional context. (Since a zero length context is allowed, the |use_context| + * flag controls whether a context is included.) + * + * It returns 1 on success and zero otherwise. + */ +int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, + const char *label, size_t llen, const unsigned char *p, size_t plen, + int use_context); + +#define SSL_set_tlsext_host_name(s,name) \ +SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name) + +#define SSL_set_tlsext_debug_callback(ssl, cb) \ +SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb) + +#define SSL_set_tlsext_debug_arg(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_ARG,0, (void *)arg) + +#define SSL_get_tlsext_status_type(ssl) \ +SSL_ctrl(ssl, SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE, 0, NULL) + +#define SSL_set_tlsext_status_type(ssl, type) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE,type, NULL) + +#define SSL_get_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +#define SSL_set_tlsext_status_exts(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS,0, (void *)arg) + +#define SSL_get_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +#define SSL_set_tlsext_status_ids(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS,0, (void *)arg) + +#define SSL_get_tlsext_status_ocsp_resp(ssl, arg) \ +SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg) + +#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \ +SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg) + +#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \ +SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb) + +#define SSL_TLSEXT_ERR_OK 0 +#define SSL_TLSEXT_ERR_ALERT_WARNING 1 +#define SSL_TLSEXT_ERR_ALERT_FATAL 2 +#define SSL_TLSEXT_ERR_NOACK 3 + +#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \ +SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg) + +#define SSL_CTX_get_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_GET_TLSEXT_TICKET_KEYS,(keylen),(keys)) +#define SSL_CTX_set_tlsext_ticket_keys(ctx, keys, keylen) \ + SSL_CTX_ctrl((ctx),SSL_CTRL_SET_TLSEXT_TICKET_KEYS,(keylen),(keys)) + +#define SSL_CTX_get_tlsext_status_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb) +#define SSL_CTX_set_tlsext_status_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb) + +#define SSL_CTX_get_tlsext_status_arg(ssl, arg) \ +SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG,0,(void *)arg) +#define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ +SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0,(void *)arg) + +#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) + +/* PSK ciphersuites from RFC 4279. */ +#define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A +#define TLS1_CK_PSK_WITH_3DES_EDE_CBC_SHA 0x0300008B +#define TLS1_CK_PSK_WITH_AES_128_CBC_SHA 0x0300008C +#define TLS1_CK_PSK_WITH_AES_256_CBC_SHA 0x0300008D + +/* Additional TLS ciphersuites from expired Internet Draft + * draft-ietf-tls-56-bit-ciphersuites-01.txt + * (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see + * s3_lib.c). We actually treat them like SSL 3.0 ciphers, which we probably + * shouldn't. Note that the first two are actually not in the IDs. */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 0x03000060 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 0x03000061 /* not in ID */ +#define TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA 0x03000062 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA 0x03000063 +#define TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA 0x03000064 +#define TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA 0x03000065 +#define TLS1_CK_DHE_DSS_WITH_RC4_128_SHA 0x03000066 + +/* AES ciphersuites from RFC 3268. */ + +#define TLS1_CK_RSA_WITH_AES_128_SHA 0x0300002F +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA 0x03000030 +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA 0x03000031 +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA 0x03000032 +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA 0x03000033 +#define TLS1_CK_ADH_WITH_AES_128_SHA 0x03000034 + +#define TLS1_CK_RSA_WITH_AES_256_SHA 0x03000035 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA 0x03000036 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA 0x03000037 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA 0x03000038 +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA 0x03000039 +#define TLS1_CK_ADH_WITH_AES_256_SHA 0x0300003A + +/* TLS v1.2 ciphersuites */ +#define TLS1_CK_RSA_WITH_NULL_SHA256 0x0300003B +#define TLS1_CK_RSA_WITH_AES_128_SHA256 0x0300003C +#define TLS1_CK_RSA_WITH_AES_256_SHA256 0x0300003D +#define TLS1_CK_DH_DSS_WITH_AES_128_SHA256 0x0300003E +#define TLS1_CK_DH_RSA_WITH_AES_128_SHA256 0x0300003F +#define TLS1_CK_DHE_DSS_WITH_AES_128_SHA256 0x03000040 + +/* Camellia ciphersuites from RFC 4132. */ +#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000041 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000042 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000043 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x03000044 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x03000045 +#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA 0x03000046 + +/* TLS v1.2 ciphersuites */ +#define TLS1_CK_DHE_RSA_WITH_AES_128_SHA256 0x03000067 +#define TLS1_CK_DH_DSS_WITH_AES_256_SHA256 0x03000068 +#define TLS1_CK_DH_RSA_WITH_AES_256_SHA256 0x03000069 +#define TLS1_CK_DHE_DSS_WITH_AES_256_SHA256 0x0300006A +#define TLS1_CK_DHE_RSA_WITH_AES_256_SHA256 0x0300006B +#define TLS1_CK_ADH_WITH_AES_128_SHA256 0x0300006C +#define TLS1_CK_ADH_WITH_AES_256_SHA256 0x0300006D + +/* Camellia ciphersuites from RFC 4132. */ +#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000084 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000085 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000086 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x03000087 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x03000088 +#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA 0x03000089 + +/* SEED ciphersuites from RFC 4162. */ +#define TLS1_CK_RSA_WITH_SEED_SHA 0x03000096 +#define TLS1_CK_DH_DSS_WITH_SEED_SHA 0x03000097 +#define TLS1_CK_DH_RSA_WITH_SEED_SHA 0x03000098 +#define TLS1_CK_DHE_DSS_WITH_SEED_SHA 0x03000099 +#define TLS1_CK_DHE_RSA_WITH_SEED_SHA 0x0300009A +#define TLS1_CK_ADH_WITH_SEED_SHA 0x0300009B + +/* TLS v1.2 GCM ciphersuites from RFC 5288. */ +#define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256 0x0300009C +#define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384 0x0300009D +#define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256 0x0300009E +#define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384 0x0300009F +#define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256 0x030000A0 +#define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384 0x030000A1 +#define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256 0x030000A2 +#define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384 0x030000A3 +#define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256 0x030000A4 +#define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384 0x030000A5 +#define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256 0x030000A6 +#define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384 0x030000A7 + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +#define TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BA +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BB +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BC +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 0x030000BD +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0x030000BE +#define TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256 0x030000BF + +#define TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C0 +#define TLS1_CK_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C1 +#define TLS1_CK_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C2 +#define TLS1_CK_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 0x030000C3 +#define TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0x030000C4 +#define TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256 0x030000C5 + +/* TLS 1.3 cipher suites from RFC 8446 appendix B.4. */ +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define TLS1_3_CK_AES_128_GCM_SHA256 0x03001301 +#define TLS1_3_CK_AES_256_GCM_SHA384 0x03001302 +#define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303 +#define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304 +#define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305 +#endif + +/* ECC ciphersuites from RFC 4492. */ +#define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA 0x0300C001 +#define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA 0x0300C002 +#define TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C003 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0x0300C004 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0x0300C005 + +#define TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA 0x0300C006 +#define TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA 0x0300C007 +#define TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA 0x0300C008 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0x0300C009 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0x0300C00A + +#define TLS1_CK_ECDH_RSA_WITH_NULL_SHA 0x0300C00B +#define TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA 0x0300C00C +#define TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA 0x0300C00D +#define TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA 0x0300C00E +#define TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0300C00F + +#define TLS1_CK_ECDHE_RSA_WITH_NULL_SHA 0x0300C010 +#define TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA 0x0300C011 +#define TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA 0x0300C012 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA 0x0300C013 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA 0x0300C014 + +#define TLS1_CK_ECDH_anon_WITH_NULL_SHA 0x0300C015 +#define TLS1_CK_ECDH_anon_WITH_RC4_128_SHA 0x0300C016 +#define TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA 0x0300C017 +#define TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA 0x0300C018 +#define TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA 0x0300C019 + +/* SRP ciphersuites from RFC 5054. */ +#define TLS1_CK_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0x0300C01A +#define TLS1_CK_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0x0300C01B +#define TLS1_CK_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0x0300C01C +#define TLS1_CK_SRP_SHA_WITH_AES_128_CBC_SHA 0x0300C01D +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0x0300C01E +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0x0300C01F +#define TLS1_CK_SRP_SHA_WITH_AES_256_CBC_SHA 0x0300C020 +#define TLS1_CK_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0x0300C021 +#define TLS1_CK_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0x0300C022 + +/* ECDH HMAC based ciphersuites from RFC 5289. */ +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256 0x0300C023 +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384 0x0300C024 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_SHA256 0x0300C025 +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_SHA384 0x0300C026 +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256 0x0300C027 +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384 0x0300C028 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256 0x0300C029 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384 0x0300C02A + +/* ECDH GCM based ciphersuites from RFC 5289. */ +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02B +#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02C +#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0x0300C02D +#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0x0300C02E +#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0x0300C02F +#define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0x0300C030 +#define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031 +#define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032 + +/* ChaCha20-Poly1305 based ciphersuites. */ +#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 0x0300CCA8 +#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305 0x0300CCA9 +#define TLS1_CK_DHE_RSA_CHACHA20_POLY1305 0x0300CCAA + +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 "EXP1024-RC4-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 "EXP1024-RC2-CBC-MD5" +#define TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DES-CBC-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA "EXP1024-DHE-DSS-DES-CBC-SHA" +#define TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA "EXP1024-RC4-SHA" +#define TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA "EXP1024-DHE-DSS-RC4-SHA" +#define TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA "DHE-DSS-RC4-SHA" + +/* AES ciphersuites from RFC 3268. */ +#define TLS1_TXT_RSA_WITH_AES_128_SHA "AES128-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA "DH-DSS-AES128-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA "DH-RSA-AES128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA "DHE-DSS-AES128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA "DHE-RSA-AES128-SHA" +#define TLS1_TXT_ADH_WITH_AES_128_SHA "ADH-AES128-SHA" + +#define TLS1_TXT_RSA_WITH_AES_256_SHA "AES256-SHA" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA "DH-DSS-AES256-SHA" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA "DH-RSA-AES256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA "DHE-DSS-AES256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA "DHE-RSA-AES256-SHA" +#define TLS1_TXT_ADH_WITH_AES_256_SHA "ADH-AES256-SHA" + +/* ECC ciphersuites from draft-ietf-tls-ecc-01.txt (Mar 15, 2001) */ +#define TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA "ECDH-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA "ECDH-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA "ECDH-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA "ECDH-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA "ECDH-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA "ECDHE-ECDSA-NULL-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA "ECDHE-ECDSA-RC4-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "ECDHE-ECDSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "ECDHE-ECDSA-AES128-SHA" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA "ECDHE-ECDSA-AES256-SHA" + +#define TLS1_TXT_ECDH_RSA_WITH_NULL_SHA "ECDH-RSA-NULL-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA "ECDH-RSA-RC4-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA "ECDH-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA "ECDH-RSA-AES128-SHA" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA "ECDH-RSA-AES256-SHA" + +#define TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA "ECDHE-RSA-NULL-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA "ECDHE-RSA-RC4-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA "ECDHE-RSA-DES-CBC3-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA "ECDHE-RSA-AES128-SHA" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA "ECDHE-RSA-AES256-SHA" + +#define TLS1_TXT_ECDH_anon_WITH_NULL_SHA "AECDH-NULL-SHA" +#define TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA "AECDH-RC4-SHA" +#define TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA "AECDH-DES-CBC3-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA "AECDH-AES128-SHA" +#define TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA "AECDH-AES256-SHA" + +/* PSK ciphersuites from RFC 4279. */ +#define TLS1_TXT_PSK_WITH_RC4_128_SHA "PSK-RC4-SHA" +#define TLS1_TXT_PSK_WITH_3DES_EDE_CBC_SHA "PSK-3DES-EDE-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_128_CBC_SHA "PSK-AES128-CBC-SHA" +#define TLS1_TXT_PSK_WITH_AES_256_CBC_SHA "PSK-AES256-CBC-SHA" + +/* SRP ciphersuite from RFC 5054. */ +#define TLS1_TXT_SRP_SHA_WITH_3DES_EDE_CBC_SHA "SRP-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA "SRP-RSA-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA "SRP-DSS-3DES-EDE-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_128_CBC_SHA "SRP-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_128_CBC_SHA "SRP-RSA-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_128_CBC_SHA "SRP-DSS-AES-128-CBC-SHA" +#define TLS1_TXT_SRP_SHA_WITH_AES_256_CBC_SHA "SRP-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_RSA_WITH_AES_256_CBC_SHA "SRP-RSA-AES-256-CBC-SHA" +#define TLS1_TXT_SRP_SHA_DSS_WITH_AES_256_CBC_SHA "SRP-DSS-AES-256-CBC-SHA" + +/* Camellia ciphersuites from RFC 4132. */ +#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA "CAMELLIA128-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA "DH-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA "DH-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA "DHE-DSS-CAMELLIA128-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA "DHE-RSA-CAMELLIA128-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA "ADH-CAMELLIA128-SHA" + +#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA "CAMELLIA256-SHA" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA "DH-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA "DH-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA "DHE-DSS-CAMELLIA256-SHA" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA "DHE-RSA-CAMELLIA256-SHA" +#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA "ADH-CAMELLIA256-SHA" + +/* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ +#define TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256 "CAMELLIA128-SHA256" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DH-DSS-CAMELLIA128-SHA256" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DH-RSA-CAMELLIA128-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 "DHE-DSS-CAMELLIA128-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 "DHE-RSA-CAMELLIA128-SHA256" +#define TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256 "ADH-CAMELLIA128-SHA256" + +#define TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256 "CAMELLIA256-SHA256" +#define TLS1_TXT_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DH-DSS-CAMELLIA256-SHA256" +#define TLS1_TXT_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DH-RSA-CAMELLIA256-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 "DHE-DSS-CAMELLIA256-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 "DHE-RSA-CAMELLIA256-SHA256" +#define TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256 "ADH-CAMELLIA256-SHA256" + +/* SEED ciphersuites from RFC 4162. */ +#define TLS1_TXT_RSA_WITH_SEED_SHA "SEED-SHA" +#define TLS1_TXT_DH_DSS_WITH_SEED_SHA "DH-DSS-SEED-SHA" +#define TLS1_TXT_DH_RSA_WITH_SEED_SHA "DH-RSA-SEED-SHA" +#define TLS1_TXT_DHE_DSS_WITH_SEED_SHA "DHE-DSS-SEED-SHA" +#define TLS1_TXT_DHE_RSA_WITH_SEED_SHA "DHE-RSA-SEED-SHA" +#define TLS1_TXT_ADH_WITH_SEED_SHA "ADH-SEED-SHA" + +/* TLS v1.2 ciphersuites. */ +#define TLS1_TXT_RSA_WITH_NULL_SHA256 "NULL-SHA256" +#define TLS1_TXT_RSA_WITH_AES_128_SHA256 "AES128-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_SHA256 "AES256-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_128_SHA256 "DH-DSS-AES128-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_128_SHA256 "DH-RSA-AES128-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_SHA256 "DHE-DSS-AES128-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256 "DHE-RSA-AES128-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_SHA256 "DH-DSS-AES256-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_SHA256 "DH-RSA-AES256-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_SHA256 "DHE-DSS-AES256-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256 "DHE-RSA-AES256-SHA256" +#define TLS1_TXT_ADH_WITH_AES_128_SHA256 "ADH-AES128-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_SHA256 "ADH-AES256-SHA256" + +/* TLS v1.2 GCM ciphersuites from RFC 5288. */ +#define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256 "AES128-GCM-SHA256" +#define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384 "AES256-GCM-SHA384" +#define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256 "DHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384 "DHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256 "DH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384 "DH-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256 "DHE-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384 "DHE-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256 "DH-DSS-AES128-GCM-SHA256" +#define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384 "DH-DSS-AES256-GCM-SHA384" +#define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256 "ADH-AES128-GCM-SHA256" +#define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384 "ADH-AES256-GCM-SHA384" + +/* ECDH HMAC based ciphersuites from RFC 5289. */ +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256 "ECDHE-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384 "ECDHE-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_SHA256 "ECDH-ECDSA-AES128-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_SHA384 "ECDH-ECDSA-AES256-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256 "ECDHE-RSA-AES128-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384 "ECDHE-RSA-AES256-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256 "ECDH-RSA-AES128-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384 "ECDH-RSA-AES256-SHA384" + +/* ECDH GCM based ciphersuites from RFC 5289. */ +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 "ECDHE-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 "ECDHE-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 "ECDH-ECDSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 "ECDH-ECDSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256 "ECDHE-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384 "ECDHE-RSA-AES256-GCM-SHA384" +#define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256" +#define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384" + +/* ChaCha20-Poly1305 based ciphersuites. */ +#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305" +#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305" +#define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305" + +/* TLS 1.3 cipher suites from RFC 8446 appendix B.4. */ +#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL) +#define TLS1_3_TXT_AES_128_GCM_SHA256 "AEAD-AES128-GCM-SHA256" +#define TLS1_3_TXT_AES_256_GCM_SHA384 "AEAD-AES256-GCM-SHA384" +#define TLS1_3_TXT_CHACHA20_POLY1305_SHA256 "AEAD-CHACHA20-POLY1305-SHA256" +#define TLS1_3_TXT_AES_128_CCM_SHA256 "AEAD-AES128-CCM-SHA256" +#define TLS1_3_TXT_AES_128_CCM_8_SHA256 "AEAD-AES128-CCM-8-SHA256" + +#define TLS1_3_RFC_AES_128_GCM_SHA256 "TLS_AES_128_GCM_SHA256" +#define TLS1_3_RFC_AES_256_GCM_SHA384 "TLS_AES_256_GCM_SHA384" +#define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256" +#define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256" +#define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256" +#endif + +#define TLS_CT_RSA_SIGN 1 +#define TLS_CT_DSS_SIGN 2 +#define TLS_CT_RSA_FIXED_DH 3 +#define TLS_CT_DSS_FIXED_DH 4 +#define TLS_CT_GOST94_SIGN 21 +#define TLS_CT_GOST01_SIGN 22 +#define TLS_CT_ECDSA_SIGN 64 +#define TLS_CT_RSA_FIXED_ECDH 65 +#define TLS_CT_ECDSA_FIXED_ECDH 66 +#define TLS_CT_GOST12_256_SIGN 67 +#define TLS_CT_GOST12_512_SIGN 68 +#define TLS_CT_GOST12_256_SIGN_COMPAT 238 /* pre-IANA, for compat */ +#define TLS_CT_GOST12_512_SIGN_COMPAT 239 /* pre-IANA, for compat */ +/* when correcting this number, correct also SSL3_CT_NUMBER in ssl3.h (see + * comment there) */ +#define TLS_CT_NUMBER 13 + +#define TLS1_FINISH_MAC_LENGTH 12 + +#define TLS_MD_MAX_CONST_SIZE 20 +#define TLS_MD_CLIENT_FINISH_CONST "client finished" +#define TLS_MD_CLIENT_FINISH_CONST_SIZE 15 +#define TLS_MD_SERVER_FINISH_CONST "server finished" +#define TLS_MD_SERVER_FINISH_CONST_SIZE 15 +#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +#define TLS_MD_KEY_EXPANSION_CONST "key expansion" +#define TLS_MD_KEY_EXPANSION_CONST_SIZE 13 +#define TLS_MD_CLIENT_WRITE_KEY_CONST "client write key" +#define TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE 16 +#define TLS_MD_SERVER_WRITE_KEY_CONST "server write key" +#define TLS_MD_SERVER_WRITE_KEY_CONST_SIZE 16 +#define TLS_MD_IV_BLOCK_CONST "IV block" +#define TLS_MD_IV_BLOCK_CONST_SIZE 8 +#define TLS_MD_MASTER_SECRET_CONST "master secret" +#define TLS_MD_MASTER_SECRET_CONST_SIZE 13 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ts.h b/include/openssl/ts.h new file mode 100644 index 0000000..0d5de62 --- /dev/null +++ b/include/openssl/ts.h @@ -0,0 +1,665 @@ +/* $OpenBSD: ts.h,v 1.22 2023/07/28 09:53:55 tb Exp $ */ +/* Written by Zoltan Glozik (zglozik@opentsa.org) for the OpenSSL + * project 2002, 2003, 2004. + */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_TS_H +#define HEADER_TS_H + +#include + +#ifndef OPENSSL_NO_BUFFER +#include +#endif +#ifndef OPENSSL_NO_EVP +#include +#endif +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include +#include + +#ifndef OPENSSL_NO_RSA +#include +#endif + +#ifndef OPENSSL_NO_DSA +#include +#endif + +#ifndef OPENSSL_NO_DH +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef struct TS_msg_imprint_st TS_MSG_IMPRINT; +typedef struct TS_req_st TS_REQ; +typedef struct TS_accuracy_st TS_ACCURACY; +typedef struct TS_tst_info_st TS_TST_INFO; + +/* Possible values for status. */ +#define TS_STATUS_GRANTED 0 +#define TS_STATUS_GRANTED_WITH_MODS 1 +#define TS_STATUS_REJECTION 2 +#define TS_STATUS_WAITING 3 +#define TS_STATUS_REVOCATION_WARNING 4 +#define TS_STATUS_REVOCATION_NOTIFICATION 5 + +/* Possible values for failure_info. */ +#define TS_INFO_BAD_ALG 0 +#define TS_INFO_BAD_REQUEST 2 +#define TS_INFO_BAD_DATA_FORMAT 5 +#define TS_INFO_TIME_NOT_AVAILABLE 14 +#define TS_INFO_UNACCEPTED_POLICY 15 +#define TS_INFO_UNACCEPTED_EXTENSION 16 +#define TS_INFO_ADD_INFO_NOT_AVAILABLE 17 +#define TS_INFO_SYSTEM_FAILURE 25 + +typedef struct TS_status_info_st TS_STATUS_INFO; + +DECLARE_STACK_OF(ASN1_UTF8STRING) + +typedef struct ESS_issuer_serial ESS_ISSUER_SERIAL; +typedef struct ESS_cert_id ESS_CERT_ID; +DECLARE_STACK_OF(ESS_CERT_ID) +typedef struct ESS_signing_cert ESS_SIGNING_CERT; + +typedef struct ESS_cert_id_v2 ESS_CERT_ID_V2; +DECLARE_STACK_OF(ESS_CERT_ID_V2) + +typedef struct ESS_signing_cert_v2 ESS_SIGNING_CERT_V2; + +typedef struct TS_resp_st TS_RESP; + +TS_REQ *TS_REQ_new(void); +void TS_REQ_free(TS_REQ *a); +int i2d_TS_REQ(const TS_REQ *a, unsigned char **pp); +TS_REQ *d2i_TS_REQ(TS_REQ **a, const unsigned char **pp, long length); + +TS_REQ *TS_REQ_dup(TS_REQ *a); + +TS_REQ *d2i_TS_REQ_fp(FILE *fp, TS_REQ **a); +int i2d_TS_REQ_fp(FILE *fp, TS_REQ *a); +TS_REQ *d2i_TS_REQ_bio(BIO *fp, TS_REQ **a); +int i2d_TS_REQ_bio(BIO *fp, TS_REQ *a); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_new(void); +void TS_MSG_IMPRINT_free(TS_MSG_IMPRINT *a); +int i2d_TS_MSG_IMPRINT(const TS_MSG_IMPRINT *a, unsigned char **pp); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT(TS_MSG_IMPRINT **a, + const unsigned char **pp, long length); + +TS_MSG_IMPRINT *TS_MSG_IMPRINT_dup(TS_MSG_IMPRINT *a); + +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_fp(FILE *fp, TS_MSG_IMPRINT *a); +TS_MSG_IMPRINT *d2i_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT **a); +int i2d_TS_MSG_IMPRINT_bio(BIO *fp, TS_MSG_IMPRINT *a); + +TS_RESP *TS_RESP_new(void); +void TS_RESP_free(TS_RESP *a); +int i2d_TS_RESP(const TS_RESP *a, unsigned char **pp); +TS_RESP *d2i_TS_RESP(TS_RESP **a, const unsigned char **pp, long length); +TS_TST_INFO *PKCS7_to_TS_TST_INFO(PKCS7 *token); +TS_RESP *TS_RESP_dup(TS_RESP *a); + +TS_RESP *d2i_TS_RESP_fp(FILE *fp, TS_RESP **a); +int i2d_TS_RESP_fp(FILE *fp, TS_RESP *a); +TS_RESP *d2i_TS_RESP_bio(BIO *fp, TS_RESP **a); +int i2d_TS_RESP_bio(BIO *fp, TS_RESP *a); + +TS_STATUS_INFO *TS_STATUS_INFO_new(void); +void TS_STATUS_INFO_free(TS_STATUS_INFO *a); +int i2d_TS_STATUS_INFO(const TS_STATUS_INFO *a, unsigned char **pp); +TS_STATUS_INFO *d2i_TS_STATUS_INFO(TS_STATUS_INFO **a, + const unsigned char **pp, long length); +TS_STATUS_INFO *TS_STATUS_INFO_dup(TS_STATUS_INFO *a); + +TS_TST_INFO *TS_TST_INFO_new(void); +void TS_TST_INFO_free(TS_TST_INFO *a); +int i2d_TS_TST_INFO(const TS_TST_INFO *a, unsigned char **pp); +TS_TST_INFO *d2i_TS_TST_INFO(TS_TST_INFO **a, const unsigned char **pp, + long length); +TS_TST_INFO *TS_TST_INFO_dup(TS_TST_INFO *a); + +TS_TST_INFO *d2i_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_fp(FILE *fp, TS_TST_INFO *a); +TS_TST_INFO *d2i_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO **a); +int i2d_TS_TST_INFO_bio(BIO *fp, TS_TST_INFO *a); + +TS_ACCURACY *TS_ACCURACY_new(void); +void TS_ACCURACY_free(TS_ACCURACY *a); +int i2d_TS_ACCURACY(const TS_ACCURACY *a, unsigned char **pp); +TS_ACCURACY *d2i_TS_ACCURACY(TS_ACCURACY **a, const unsigned char **pp, + long length); +TS_ACCURACY *TS_ACCURACY_dup(TS_ACCURACY *a); + +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_new(void); +void ESS_ISSUER_SERIAL_free(ESS_ISSUER_SERIAL *a); +int i2d_ESS_ISSUER_SERIAL(const ESS_ISSUER_SERIAL *a, + unsigned char **pp); +ESS_ISSUER_SERIAL *d2i_ESS_ISSUER_SERIAL(ESS_ISSUER_SERIAL **a, + const unsigned char **pp, long length); +ESS_ISSUER_SERIAL *ESS_ISSUER_SERIAL_dup(ESS_ISSUER_SERIAL *a); + +ESS_CERT_ID *ESS_CERT_ID_new(void); +void ESS_CERT_ID_free(ESS_CERT_ID *a); +int i2d_ESS_CERT_ID(const ESS_CERT_ID *a, unsigned char **pp); +ESS_CERT_ID *d2i_ESS_CERT_ID(ESS_CERT_ID **a, const unsigned char **pp, + long length); +ESS_CERT_ID *ESS_CERT_ID_dup(ESS_CERT_ID *a); + +ESS_SIGNING_CERT *ESS_SIGNING_CERT_new(void); +void ESS_SIGNING_CERT_free(ESS_SIGNING_CERT *a); +int i2d_ESS_SIGNING_CERT(const ESS_SIGNING_CERT *a, + unsigned char **pp); +ESS_SIGNING_CERT *d2i_ESS_SIGNING_CERT(ESS_SIGNING_CERT **a, + const unsigned char **pp, long length); +ESS_SIGNING_CERT *ESS_SIGNING_CERT_dup(ESS_SIGNING_CERT *a); + +int TS_REQ_set_version(TS_REQ *a, long version); +long TS_REQ_get_version(const TS_REQ *a); + +int TS_REQ_set_msg_imprint(TS_REQ *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_REQ_get_msg_imprint(TS_REQ *a); + +int TS_MSG_IMPRINT_set_algo(TS_MSG_IMPRINT *a, X509_ALGOR *alg); +X509_ALGOR *TS_MSG_IMPRINT_get_algo(TS_MSG_IMPRINT *a); + +int TS_MSG_IMPRINT_set_msg(TS_MSG_IMPRINT *a, unsigned char *d, int len); +ASN1_OCTET_STRING *TS_MSG_IMPRINT_get_msg(TS_MSG_IMPRINT *a); + +int TS_REQ_set_policy_id(TS_REQ *a, const ASN1_OBJECT *policy); +ASN1_OBJECT *TS_REQ_get_policy_id(TS_REQ *a); + +int TS_REQ_set_nonce(TS_REQ *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_REQ_get_nonce(const TS_REQ *a); + +int TS_REQ_set_cert_req(TS_REQ *a, int cert_req); +int TS_REQ_get_cert_req(const TS_REQ *a); + +STACK_OF(X509_EXTENSION) *TS_REQ_get_exts(TS_REQ *a); +void TS_REQ_ext_free(TS_REQ *a); +int TS_REQ_get_ext_count(TS_REQ *a); +int TS_REQ_get_ext_by_NID(TS_REQ *a, int nid, int lastpos); +int TS_REQ_get_ext_by_OBJ(TS_REQ *a, const ASN1_OBJECT *obj, int lastpos); +int TS_REQ_get_ext_by_critical(TS_REQ *a, int crit, int lastpos); +X509_EXTENSION *TS_REQ_get_ext(TS_REQ *a, int loc); +X509_EXTENSION *TS_REQ_delete_ext(TS_REQ *a, int loc); +int TS_REQ_add_ext(TS_REQ *a, X509_EXTENSION *ex, int loc); +void *TS_REQ_get_ext_d2i(TS_REQ *a, int nid, int *crit, int *idx); + +/* Function declarations for TS_REQ defined in ts/ts_req_print.c */ + +int TS_REQ_print_bio(BIO *bio, TS_REQ *a); + +/* Function declarations for TS_RESP defined in ts/ts_rsp_utils.c */ + +int TS_RESP_set_status_info(TS_RESP *a, TS_STATUS_INFO *info); +TS_STATUS_INFO *TS_RESP_get_status_info(TS_RESP *a); + +const ASN1_UTF8STRING *TS_STATUS_INFO_get0_failure_info(const TS_STATUS_INFO *si); +const STACK_OF(ASN1_UTF8STRING) * + TS_STATUS_INFO_get0_text(const TS_STATUS_INFO *si); +const ASN1_INTEGER *TS_STATUS_INFO_get0_status(const TS_STATUS_INFO *si); +int TS_STATUS_INFO_set_status(TS_STATUS_INFO *si, int i); + +/* Caller loses ownership of PKCS7 and TS_TST_INFO objects. */ +void TS_RESP_set_tst_info(TS_RESP *a, PKCS7 *p7, TS_TST_INFO *tst_info); +PKCS7 *TS_RESP_get_token(TS_RESP *a); +TS_TST_INFO *TS_RESP_get_tst_info(TS_RESP *a); + +int TS_TST_INFO_set_version(TS_TST_INFO *a, long version); +long TS_TST_INFO_get_version(const TS_TST_INFO *a); + +int TS_TST_INFO_set_policy_id(TS_TST_INFO *a, ASN1_OBJECT *policy_id); +ASN1_OBJECT *TS_TST_INFO_get_policy_id(TS_TST_INFO *a); + +int TS_TST_INFO_set_msg_imprint(TS_TST_INFO *a, TS_MSG_IMPRINT *msg_imprint); +TS_MSG_IMPRINT *TS_TST_INFO_get_msg_imprint(TS_TST_INFO *a); + +int TS_TST_INFO_set_serial(TS_TST_INFO *a, const ASN1_INTEGER *serial); +const ASN1_INTEGER *TS_TST_INFO_get_serial(const TS_TST_INFO *a); + +int TS_TST_INFO_set_time(TS_TST_INFO *a, const ASN1_GENERALIZEDTIME *gtime); +const ASN1_GENERALIZEDTIME *TS_TST_INFO_get_time(const TS_TST_INFO *a); + +int TS_TST_INFO_set_accuracy(TS_TST_INFO *a, TS_ACCURACY *accuracy); +TS_ACCURACY *TS_TST_INFO_get_accuracy(TS_TST_INFO *a); + +int TS_ACCURACY_set_seconds(TS_ACCURACY *a, const ASN1_INTEGER *seconds); +const ASN1_INTEGER *TS_ACCURACY_get_seconds(const TS_ACCURACY *a); + +int TS_ACCURACY_set_millis(TS_ACCURACY *a, const ASN1_INTEGER *millis); +const ASN1_INTEGER *TS_ACCURACY_get_millis(const TS_ACCURACY *a); + +int TS_ACCURACY_set_micros(TS_ACCURACY *a, const ASN1_INTEGER *micros); +const ASN1_INTEGER *TS_ACCURACY_get_micros(const TS_ACCURACY *a); + +int TS_TST_INFO_set_ordering(TS_TST_INFO *a, int ordering); +int TS_TST_INFO_get_ordering(const TS_TST_INFO *a); + +int TS_TST_INFO_set_nonce(TS_TST_INFO *a, const ASN1_INTEGER *nonce); +const ASN1_INTEGER *TS_TST_INFO_get_nonce(const TS_TST_INFO *a); + +int TS_TST_INFO_set_tsa(TS_TST_INFO *a, GENERAL_NAME *tsa); +GENERAL_NAME *TS_TST_INFO_get_tsa(TS_TST_INFO *a); + +STACK_OF(X509_EXTENSION) *TS_TST_INFO_get_exts(TS_TST_INFO *a); +void TS_TST_INFO_ext_free(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_count(TS_TST_INFO *a); +int TS_TST_INFO_get_ext_by_NID(TS_TST_INFO *a, int nid, int lastpos); +int TS_TST_INFO_get_ext_by_OBJ(TS_TST_INFO *a, const ASN1_OBJECT *obj, + int lastpos); +int TS_TST_INFO_get_ext_by_critical(TS_TST_INFO *a, int crit, int lastpos); +X509_EXTENSION *TS_TST_INFO_get_ext(TS_TST_INFO *a, int loc); +X509_EXTENSION *TS_TST_INFO_delete_ext(TS_TST_INFO *a, int loc); +int TS_TST_INFO_add_ext(TS_TST_INFO *a, X509_EXTENSION *ex, int loc); +void *TS_TST_INFO_get_ext_d2i(TS_TST_INFO *a, int nid, int *crit, int *idx); + +/* Declarations related to response generation, defined in ts/ts_rsp_sign.c. */ + +/* Optional flags for response generation. */ + +/* Don't include the TSA name in response. */ +#define TS_TSA_NAME 0x01 + +/* Set ordering to true in response. */ +#define TS_ORDERING 0x02 + +/* + * Include the signer certificate and the other specified certificates in + * the ESS signing certificate attribute beside the PKCS7 signed data. + * Only the signer certificates is included by default. + */ +#define TS_ESS_CERT_ID_CHAIN 0x04 + +/* Forward declaration. */ +struct TS_resp_ctx; + +/* This must return a unique number less than 160 bits long. */ +typedef ASN1_INTEGER *(*TS_serial_cb)(struct TS_resp_ctx *, void *); + +/* This must return the seconds and microseconds since Jan 1, 1970 in + the sec and usec variables allocated by the caller. + Return non-zero for success and zero for failure. */ +typedef int (*TS_time_cb)(struct TS_resp_ctx *, void *, time_t *sec, long *usec); + +/* This must process the given extension. + * It can modify the TS_TST_INFO object of the context. + * Return values: !0 (processed), 0 (error, it must set the + * status info/failure info of the response). + */ +typedef int (*TS_extension_cb)(struct TS_resp_ctx *, X509_EXTENSION *, void *); + +typedef struct TS_resp_ctx TS_RESP_CTX; + +DECLARE_STACK_OF(EVP_MD) + +/* Creates a response context that can be used for generating responses. */ +TS_RESP_CTX *TS_RESP_CTX_new(void); +void TS_RESP_CTX_free(TS_RESP_CTX *ctx); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_cert(TS_RESP_CTX *ctx, X509 *signer); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_signer_key(TS_RESP_CTX *ctx, EVP_PKEY *key); + +/* This parameter must be set. */ +int TS_RESP_CTX_set_def_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *def_policy); + +/* No additional certs are included in the response by default. */ +int TS_RESP_CTX_set_certs(TS_RESP_CTX *ctx, STACK_OF(X509) *certs); + +/* Adds a new acceptable policy, only the default policy + is accepted by default. */ +int TS_RESP_CTX_add_policy(TS_RESP_CTX *ctx, const ASN1_OBJECT *policy); + +/* Adds a new acceptable message digest. Note that no message digests + are accepted by default. The md argument is shared with the caller. */ +int TS_RESP_CTX_add_md(TS_RESP_CTX *ctx, const EVP_MD *md); + +/* Accuracy is not included by default. */ +int TS_RESP_CTX_set_accuracy(TS_RESP_CTX *ctx, + int secs, int millis, int micros); + +/* Clock precision digits, i.e. the number of decimal digits: + '0' means sec, '3' msec, '6' usec, and so on. Default is 0. */ +int TS_RESP_CTX_set_clock_precision_digits(TS_RESP_CTX *ctx, + unsigned clock_precision_digits); +/* At most we accept usec precision. */ +#define TS_MAX_CLOCK_PRECISION_DIGITS 6 + +/* No flags are set by default. */ +void TS_RESP_CTX_add_flags(TS_RESP_CTX *ctx, int flags); + +/* Default callback always returns a constant. */ +void TS_RESP_CTX_set_serial_cb(TS_RESP_CTX *ctx, TS_serial_cb cb, void *data); + +/* Default callback uses gettimeofday() and gmtime(). */ +void TS_RESP_CTX_set_time_cb(TS_RESP_CTX *ctx, TS_time_cb cb, void *data); + +/* Default callback rejects all extensions. The extension callback is called + * when the TS_TST_INFO object is already set up and not signed yet. */ +/* FIXME: extension handling is not tested yet. */ +void TS_RESP_CTX_set_extension_cb(TS_RESP_CTX *ctx, + TS_extension_cb cb, void *data); + +/* The following methods can be used in the callbacks. */ +int TS_RESP_CTX_set_status_info(TS_RESP_CTX *ctx, + int status, const char *text); + +/* Sets the status info only if it is still TS_STATUS_GRANTED. */ +int TS_RESP_CTX_set_status_info_cond(TS_RESP_CTX *ctx, + int status, const char *text); + +int TS_RESP_CTX_add_failure_info(TS_RESP_CTX *ctx, int failure); + +/* The get methods below can be used in the extension callback. */ +TS_REQ *TS_RESP_CTX_get_request(TS_RESP_CTX *ctx); + +TS_TST_INFO *TS_RESP_CTX_get_tst_info(TS_RESP_CTX *ctx); + +/* + * Creates the signed TS_TST_INFO and puts it in TS_RESP. + * In case of errors it sets the status info properly. + * Returns NULL only in case of memory allocation/fatal error. + */ +TS_RESP *TS_RESP_create_response(TS_RESP_CTX *ctx, BIO *req_bio); + +/* + * Declarations related to response verification, + * they are defined in ts/ts_rsp_verify.c. + */ + +int TS_RESP_verify_signature(PKCS7 *token, STACK_OF(X509) *certs, + X509_STORE *store, X509 **signer_out); + +/* Context structure for the generic verify method. */ + +/* Verify the signer's certificate and the signature of the response. */ +#define TS_VFY_SIGNATURE (1u << 0) +/* Verify the version number of the response. */ +#define TS_VFY_VERSION (1u << 1) +/* Verify if the policy supplied by the user matches the policy of the TSA. */ +#define TS_VFY_POLICY (1u << 2) +/* Verify the message imprint provided by the user. This flag should not be + specified with TS_VFY_DATA. */ +#define TS_VFY_IMPRINT (1u << 3) +/* Verify the message imprint computed by the verify method from the user + provided data and the MD algorithm of the response. This flag should not be + specified with TS_VFY_IMPRINT. */ +#define TS_VFY_DATA (1u << 4) +/* Verify the nonce value. */ +#define TS_VFY_NONCE (1u << 5) +/* Verify if the TSA name field matches the signer certificate. */ +#define TS_VFY_SIGNER (1u << 6) +/* Verify if the TSA name field equals to the user provided name. */ +#define TS_VFY_TSA_NAME (1u << 7) + +/* You can use the following convenience constants. */ +#define TS_VFY_ALL_IMPRINT (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_IMPRINT \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) +#define TS_VFY_ALL_DATA (TS_VFY_SIGNATURE \ + | TS_VFY_VERSION \ + | TS_VFY_POLICY \ + | TS_VFY_DATA \ + | TS_VFY_NONCE \ + | TS_VFY_SIGNER \ + | TS_VFY_TSA_NAME) + +typedef struct TS_verify_ctx TS_VERIFY_CTX; + +int TS_RESP_verify_response(TS_VERIFY_CTX *ctx, TS_RESP *response); +int TS_RESP_verify_token(TS_VERIFY_CTX *ctx, PKCS7 *token); + +/* + * Declarations related to response verification context, + * they are defined in ts/ts_verify_ctx.c. + */ + +/* Set all fields to zero. */ +TS_VERIFY_CTX *TS_VERIFY_CTX_new(void); +void TS_VERIFY_CTX_free(TS_VERIFY_CTX *ctx); +void TS_VERIFY_CTX_cleanup(TS_VERIFY_CTX *ctx); + +int TS_VERIFY_CTX_add_flags(TS_VERIFY_CTX *ctx, int flags); +int TS_VERIFY_CTX_set_flags(TS_VERIFY_CTX *ctx, int flags); +BIO *TS_VERIFY_CTX_set_data(TS_VERIFY_CTX *ctx, BIO *bio); +X509_STORE *TS_VERIFY_CTX_set_store(TS_VERIFY_CTX *ctx, X509_STORE *store); +/* R$ special */ +#define TS_VERIFY_CTS_set_certs TS_VERIFY_CTX_set_certs +STACK_OF(X509) *TS_VERIFY_CTX_set_certs(TS_VERIFY_CTX *ctx, + STACK_OF(X509) *certs); +unsigned char *TS_VERIFY_CTX_set_imprint(TS_VERIFY_CTX *ctx, + unsigned char *imprint, long imprint_len); + +/* + * If ctx is NULL, it allocates and returns a new object, otherwise + * it returns ctx. It initialises all the members as follows: + * flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE) + * certs = NULL + * store = NULL + * policy = policy from the request or NULL if absent (in this case + * TS_VFY_POLICY is cleared from flags as well) + * md_alg = MD algorithm from request + * imprint, imprint_len = imprint from request + * data = NULL + * nonce, nonce_len = nonce from the request or NULL if absent (in this case + * TS_VFY_NONCE is cleared from flags as well) + * tsa_name = NULL + * Important: after calling this method TS_VFY_SIGNATURE should be added! + */ +TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx); + +/* Function declarations for TS_RESP defined in ts/ts_rsp_print.c */ + +int TS_RESP_print_bio(BIO *bio, TS_RESP *a); +int TS_STATUS_INFO_print_bio(BIO *bio, TS_STATUS_INFO *a); +int TS_TST_INFO_print_bio(BIO *bio, TS_TST_INFO *a); + +/* Common utility functions defined in ts/ts_lib.c */ + +int TS_ASN1_INTEGER_print_bio(BIO *bio, const ASN1_INTEGER *num); +int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj); +int TS_ext_print_bio(BIO *bio, const STACK_OF(X509_EXTENSION) *extensions); +int TS_X509_ALGOR_print_bio(BIO *bio, const X509_ALGOR *alg); +int TS_MSG_IMPRINT_print_bio(BIO *bio, TS_MSG_IMPRINT *msg); + +/* Function declarations for handling configuration options, + defined in ts/ts_conf.c */ + +X509 *TS_CONF_load_cert(const char *file); +STACK_OF(X509) *TS_CONF_load_certs(const char *file); +EVP_PKEY *TS_CONF_load_key(const char *file, const char *pass); +const char *TS_CONF_get_tsa_section(CONF *conf, const char *section); +int TS_CONF_set_serial(CONF *conf, const char *section, TS_serial_cb cb, + TS_RESP_CTX *ctx); +#ifndef OPENSSL_NO_ENGINE +int TS_CONF_set_crypto_device(CONF *conf, const char *section, + const char *device); +int TS_CONF_set_default_engine(const char *name); +#endif +int TS_CONF_set_signer_cert(CONF *conf, const char *section, + const char *cert, TS_RESP_CTX *ctx); +int TS_CONF_set_certs(CONF *conf, const char *section, const char *certs, + TS_RESP_CTX *ctx); +int TS_CONF_set_signer_key(CONF *conf, const char *section, + const char *key, const char *pass, TS_RESP_CTX *ctx); +int TS_CONF_set_def_policy(CONF *conf, const char *section, + const char *policy, TS_RESP_CTX *ctx); +int TS_CONF_set_policies(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_digests(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_accuracy(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_clock_precision_digits(CONF *conf, const char *section, + TS_RESP_CTX *ctx); +int TS_CONF_set_ordering(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_tsa_name(CONF *conf, const char *section, TS_RESP_CTX *ctx); +int TS_CONF_set_ess_cert_id_chain(CONF *conf, const char *section, + TS_RESP_CTX *ctx); + +void ERR_load_TS_strings(void); + +/* Error codes for the TS functions. */ + +/* Function codes. */ +#define TS_F_D2I_TS_RESP 147 +#define TS_F_DEF_SERIAL_CB 110 +#define TS_F_DEF_TIME_CB 111 +#define TS_F_ESS_ADD_SIGNING_CERT 112 +#define TS_F_ESS_CERT_ID_NEW_INIT 113 +#define TS_F_ESS_SIGNING_CERT_NEW_INIT 114 +#define TS_F_INT_TS_RESP_VERIFY_TOKEN 149 +#define TS_F_PKCS7_TO_TS_TST_INFO 148 +#define TS_F_TS_ACCURACY_SET_MICROS 115 +#define TS_F_TS_ACCURACY_SET_MILLIS 116 +#define TS_F_TS_ACCURACY_SET_SECONDS 117 +#define TS_F_TS_CHECK_IMPRINTS 100 +#define TS_F_TS_CHECK_NONCES 101 +#define TS_F_TS_CHECK_POLICY 102 +#define TS_F_TS_CHECK_SIGNING_CERTS 103 +#define TS_F_TS_CHECK_STATUS_INFO 104 +#define TS_F_TS_COMPUTE_IMPRINT 145 +#define TS_F_TS_CONF_SET_DEFAULT_ENGINE 146 +#define TS_F_TS_GET_STATUS_TEXT 105 +#define TS_F_TS_MSG_IMPRINT_SET_ALGO 118 +#define TS_F_TS_REQ_SET_MSG_IMPRINT 119 +#define TS_F_TS_REQ_SET_NONCE 120 +#define TS_F_TS_REQ_SET_POLICY_ID 121 +#define TS_F_TS_RESP_CREATE_RESPONSE 122 +#define TS_F_TS_RESP_CREATE_TST_INFO 123 +#define TS_F_TS_RESP_CTX_ADD_FAILURE_INFO 124 +#define TS_F_TS_RESP_CTX_ADD_MD 125 +#define TS_F_TS_RESP_CTX_ADD_POLICY 126 +#define TS_F_TS_RESP_CTX_NEW 127 +#define TS_F_TS_RESP_CTX_SET_ACCURACY 128 +#define TS_F_TS_RESP_CTX_SET_CERTS 129 +#define TS_F_TS_RESP_CTX_SET_DEF_POLICY 130 +#define TS_F_TS_RESP_CTX_SET_SIGNER_CERT 131 +#define TS_F_TS_RESP_CTX_SET_STATUS_INFO 132 +#define TS_F_TS_RESP_GET_POLICY 133 +#define TS_F_TS_RESP_SET_GENTIME_WITH_PRECISION 134 +#define TS_F_TS_RESP_SET_STATUS_INFO 135 +#define TS_F_TS_RESP_SET_TST_INFO 150 +#define TS_F_TS_RESP_SIGN 136 +#define TS_F_TS_RESP_VERIFY_SIGNATURE 106 +#define TS_F_TS_RESP_VERIFY_TOKEN 107 +#define TS_F_TS_TST_INFO_SET_ACCURACY 137 +#define TS_F_TS_TST_INFO_SET_MSG_IMPRINT 138 +#define TS_F_TS_TST_INFO_SET_NONCE 139 +#define TS_F_TS_TST_INFO_SET_POLICY_ID 140 +#define TS_F_TS_TST_INFO_SET_SERIAL 141 +#define TS_F_TS_TST_INFO_SET_TIME 142 +#define TS_F_TS_TST_INFO_SET_TSA 143 +#define TS_F_TS_VERIFY 108 +#define TS_F_TS_VERIFY_CERT 109 +#define TS_F_TS_VERIFY_CTX_NEW 144 + +/* Reason codes. */ +#define TS_R_BAD_PKCS7_TYPE 132 +#define TS_R_BAD_TYPE 133 +#define TS_R_CERTIFICATE_VERIFY_ERROR 100 +#define TS_R_COULD_NOT_SET_ENGINE 127 +#define TS_R_COULD_NOT_SET_TIME 115 +#define TS_R_D2I_TS_RESP_INT_FAILED 128 +#define TS_R_DETACHED_CONTENT 134 +#define TS_R_ESS_ADD_SIGNING_CERT_ERROR 116 +#define TS_R_ESS_SIGNING_CERTIFICATE_ERROR 101 +#define TS_R_INVALID_NULL_POINTER 102 +#define TS_R_INVALID_SIGNER_CERTIFICATE_PURPOSE 117 +#define TS_R_MESSAGE_IMPRINT_MISMATCH 103 +#define TS_R_NONCE_MISMATCH 104 +#define TS_R_NONCE_NOT_RETURNED 105 +#define TS_R_NO_CONTENT 106 +#define TS_R_NO_TIME_STAMP_TOKEN 107 +#define TS_R_PKCS7_ADD_SIGNATURE_ERROR 118 +#define TS_R_PKCS7_ADD_SIGNED_ATTR_ERROR 119 +#define TS_R_PKCS7_TO_TS_TST_INFO_FAILED 129 +#define TS_R_POLICY_MISMATCH 108 +#define TS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE 120 +#define TS_R_RESPONSE_SETUP_ERROR 121 +#define TS_R_SIGNATURE_FAILURE 109 +#define TS_R_THERE_MUST_BE_ONE_SIGNER 110 +#define TS_R_TIME_SYSCALL_ERROR 122 +#define TS_R_TOKEN_NOT_PRESENT 130 +#define TS_R_TOKEN_PRESENT 131 +#define TS_R_TSA_NAME_MISMATCH 111 +#define TS_R_TSA_UNTRUSTED 112 +#define TS_R_TST_INFO_SETUP_ERROR 123 +#define TS_R_TS_DATASIGN 124 +#define TS_R_UNACCEPTABLE_POLICY 125 +#define TS_R_UNSUPPORTED_MD_ALGORITHM 126 +#define TS_R_UNSUPPORTED_VERSION 113 +#define TS_R_WRONG_CONTENT_TYPE 114 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/txt_db.h b/include/openssl/txt_db.h new file mode 100644 index 0000000..56b6b42 --- /dev/null +++ b/include/openssl/txt_db.h @@ -0,0 +1,112 @@ +/* $OpenBSD: txt_db.h,v 1.9 2014/07/10 22:45:58 jsing Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_TXT_DB_H +#define HEADER_TXT_DB_H + +#include + +#ifndef OPENSSL_NO_BIO +#include +#endif +#include +#include + +#define DB_ERROR_OK 0 +#define DB_ERROR_MALLOC 1 +#define DB_ERROR_INDEX_CLASH 2 +#define DB_ERROR_INDEX_OUT_OF_RANGE 3 +#define DB_ERROR_NO_INDEX 4 +#define DB_ERROR_INSERT_INDEX_CLASH 5 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef OPENSSL_STRING *OPENSSL_PSTRING; +DECLARE_SPECIAL_STACK_OF(OPENSSL_PSTRING, OPENSSL_STRING) + +typedef struct txt_db_st { + int num_fields; + STACK_OF(OPENSSL_PSTRING) *data; + LHASH_OF(OPENSSL_STRING) **index; + int (**qual)(OPENSSL_STRING *); + long error; + long arg1; + long arg2; + OPENSSL_STRING *arg_row; +} TXT_DB; + +#ifndef OPENSSL_NO_BIO +TXT_DB *TXT_DB_read(BIO *in, int num); +long TXT_DB_write(BIO *out, TXT_DB *db); +#else +TXT_DB *TXT_DB_read(char *in, int num); +long TXT_DB_write(char *out, TXT_DB *db); +#endif +int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(OPENSSL_STRING *), + LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp); +void TXT_DB_free(TXT_DB *db); +OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, OPENSSL_STRING *value); +int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/ui.h b/include/openssl/ui.h new file mode 100644 index 0000000..c688431 --- /dev/null +++ b/include/openssl/ui.h @@ -0,0 +1,403 @@ +/* $OpenBSD: ui.h,v 1.18 2023/04/18 08:33:43 tb Exp $ */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_UI_H +#define HEADER_UI_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Declared already in ossl_typ.h */ +/* typedef struct ui_st UI; */ +/* typedef struct ui_method_st UI_METHOD; */ + + +/* + * All the following functions return -1 or NULL on error and in some cases + * (UI_process()) -2 if interrupted or in some other way cancelled. + * When everything is fine, they return 0, a positive value or a non-NULL + * pointer, all depending on their purpose. + */ + +/* Creators and destructor. */ +UI *UI_new(void); +UI *UI_new_method(const UI_METHOD *method); +void UI_free(UI *ui); + +/* + * The following functions are used to add strings to be printed and prompt + * strings to prompt for data. The names are UI_{add,dup}__string + * and UI_{add,dup}_input_boolean. + * + * UI_{add,dup}__string have the following meanings: + * add add a text or prompt string. The pointers given to these + * functions are used verbatim, no copying is done. + * dup make a copy of the text or prompt string, then add the copy + * to the collection of strings in the user interface. + * + * The function is a name for the functionality that the given + * string shall be used for. It can be one of: + * input use the string as data prompt. + * verify use the string as verification prompt. This + * is used to verify a previous input. + * info use the string for informational output. + * error use the string for error output. + * Honestly, there's currently no difference between info and error for the + * moment. + * + * UI_{add,dup}_input_boolean have the same semantics for "add" and "dup", + * and are typically used when one wants to prompt for a yes/no response. + * + * All of the functions in this group take a UI and a prompt string. + * The string input and verify addition functions also take a flag argument, + * a buffer for the result to end up in, a minimum input size and a maximum + * input size (the result buffer MUST be large enough to be able to contain + * the maximum number of characters). Additionally, the verify addition + * functions takes another buffer to compare the result against. + * The boolean input functions take an action description string (which should + * be safe to ignore if the expected user action is obvious, for example with + * a dialog box with an OK button and a Cancel button), a string of acceptable + * characters to mean OK and to mean Cancel. The two last strings are checked + * to make sure they don't have common characters. Additionally, the same + * flag argument as for the string input is taken, as well as a result buffer. + * The result buffer is required to be at least one byte long. Depending on + * the answer, the first character from the OK or the Cancel character strings + * will be stored in the first byte of the result buffer. No NUL will be + * added, so the result is *not* a string. + * + * On success, the functions all return an index of the added information. + * That index is useful when retrieving results with UI_get0_result(). + */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize); +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf); +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, const char *test_buf); +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf); +int UI_add_info_string(UI *ui, const char *text); +int UI_dup_info_string(UI *ui, const char *text); +int UI_add_error_string(UI *ui, const char *text); +int UI_dup_error_string(UI *ui, const char *text); + +/* These are the possible flags. They can be or'ed together. */ +/* Use to have echoing of input */ +#define UI_INPUT_FLAG_ECHO 0x01 +/* + * Use a default password. Where that password is found is completely + * up to the application, it might for example be in the user data set + * with UI_add_user_data(). It is not recommended to have more than + * one input in each UI being marked with this flag, or the application + * might get confused. + */ +#define UI_INPUT_FLAG_DEFAULT_PWD 0x02 + +/* + * Users of these routines may want to define flags of their own. The core + * UI won't look at those, but will pass them on to the method routines. They + * must use higher bits so they don't get confused with the UI bits above. + * UI_INPUT_FLAG_USER_BASE tells which is the lowest bit to use. A good + * example of use is this: + * + * #define MY_UI_FLAG1 (0x01 << UI_INPUT_FLAG_USER_BASE) + */ +#define UI_INPUT_FLAG_USER_BASE 16 + + +/* + * The following function helps construct a prompt. object_desc is a + * textual short description of the object, for example "pass phrase", + * and object_name is the name of the object (might be a card name or + * a file name. + * The returned string shall always be allocated on the heap with + * malloc(), and need to be free'd with free(). + * + * If the ui_method doesn't contain a pointer to a user-defined prompt + * constructor, a default string is built, looking like this: + * + * "Enter {object_desc} for {object_name}:" + * + * So, if object_desc has the value "pass phrase" and object_name has + * the value "foo.key", the resulting string is: + * + * "Enter pass phrase for foo.key:" + */ +char *UI_construct_prompt(UI *ui_method, const char *object_desc, + const char *object_name); + + +/* + * The following function is used to store a pointer to user-specific data. + * Any previous such pointer will be returned and replaced. + * + * For callback purposes, this function makes a lot more sense than using + * ex_data, since the latter requires that different parts of OpenSSL or + * applications share the same ex_data index. + * + * Note that the UI_OpenSSL() method completely ignores the user data. + * Other methods may not, however. + */ +void *UI_add_user_data(UI *ui, void *user_data); +/* We need a user data retrieving function as well. */ +void *UI_get0_user_data(UI *ui); + +/* Return the result associated with a prompt given with the index i. */ +const char *UI_get0_result(UI *ui, int i); + +/* When all strings have been added, process the whole thing. */ +int UI_process(UI *ui); + +/* + * Give a user interface parametrised control commands. This can be used to + * send down an integer, a data pointer or a function pointer, as well as + * be used to get information from a UI. + */ +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void)); + +/* The commands */ +/* + * Use UI_CONTROL_PRINT_ERRORS with the value 1 to have UI_process print the + * OpenSSL error stack before printing any info or added error messages and + * before any prompting. + */ +#define UI_CTRL_PRINT_ERRORS 1 +/* + * Check if a UI_process() is possible to do again with the same instance of + * a user interface. This makes UI_ctrl() return 1 if it is redoable, and 0 + * if not. + */ +#define UI_CTRL_IS_REDOABLE 2 + + +/* Some methods may use extra data */ +#define UI_set_app_data(s,arg) UI_set_ex_data(s,0,arg) +#define UI_get_app_data(s) UI_get_ex_data(s,0) +int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int UI_set_ex_data(UI *r, int idx, void *arg); +void *UI_get_ex_data(UI *r, int idx); + +/* Use specific methods instead of the built-in one */ +void UI_set_default_method(const UI_METHOD *meth); +const UI_METHOD *UI_get_default_method(void); +const UI_METHOD *UI_get_method(UI *ui); +const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth); + +/* The method with all the built-in thingies */ +UI_METHOD *UI_OpenSSL(void); + +const UI_METHOD *UI_null(void); + +/* + * ---------- For method writers ---------- + * A method contains a number of functions that implement the low level + * of the User Interface. The functions are: + * + * an opener This function starts a session, maybe by opening + * a channel to a tty, or by opening a window. + * a writer This function is called to write a given string, + * maybe to the tty, maybe as a field label in a + * window. + * a flusher This function is called to flush everything that + * has been output so far. It can be used to actually + * display a dialog box after it has been built. + * a reader This function is called to read a given prompt, + * maybe from the tty, maybe from a field in a + * window. Note that it's called with all string + * structures, not only the prompt ones, so it must + * check such things itself. + * a closer This function closes the session, maybe by closing + * the channel to the tty, or closing the window. + * + * All these functions are expected to return: + * + * 0 on error. + * 1 on success. + * -1 on out-of-band events, for example if some prompting has + * been canceled (by pressing Ctrl-C, for example). This is + * only checked when returned by the flusher or the reader. + * + * The way this is used, the opener is first called, then the writer for all + * strings, then the flusher, then the reader for all strings and finally the + * closer. Note that if you want to prompt from a terminal or other command + * line interface, the best is to have the reader also write the prompts + * instead of having the writer do it. If you want to prompt from a dialog + * box, the writer can be used to build up the contents of the box, and the + * flusher to actually display the box and run the event loop until all data + * has been given, after which the reader only grabs the given data and puts + * them back into the UI strings. + * + * All method functions take a UI as argument. Additionally, the writer and + * the reader take a UI_STRING. + */ + +/* + * The UI_STRING type is the data structure that contains all the needed info + * about a string or a prompt, including test data for a verification prompt. + */ +typedef struct ui_string_st UI_STRING; +DECLARE_STACK_OF(UI_STRING) + +/* + * The different types of strings that are currently supported. + * This is only needed by method authors. + */ +enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, /* Prompt for a string */ + UIT_VERIFY, /* Prompt for a string and verify */ + UIT_BOOLEAN, /* Prompt for a yes/no response */ + UIT_INFO, /* Send info to the user */ + UIT_ERROR /* Send an error message to the user */ +}; + +/* Create and manipulate methods */ +UI_METHOD *UI_create_method(const char *name); +void UI_destroy_method(UI_METHOD *ui_method); +int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)); +int UI_method_set_writer(UI_METHOD *method, + int (*writer)(UI *ui, UI_STRING *uis)); +int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)); +int UI_method_set_reader(UI_METHOD *method, + int (*reader)(UI *ui, UI_STRING *uis)); +int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)); +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor)(UI *ui, const char *object_desc, + const char *object_name)); +int (*UI_method_get_opener(const UI_METHOD *method))(UI *); +int (*UI_method_get_writer(const UI_METHOD *method))(UI *, UI_STRING *); +int (*UI_method_get_flusher(const UI_METHOD *method))(UI *); +int (*UI_method_get_reader(const UI_METHOD *method))(UI *, UI_STRING *); +int (*UI_method_get_closer(const UI_METHOD *method))(UI *); +char *(*UI_method_get_prompt_constructor(const UI_METHOD *method))(UI *, + const char *, const char *); + +/* + * The following functions are helpers for method writers to access relevant + * data from a UI_STRING. + */ +/* Return type of the UI_STRING */ +enum UI_string_types UI_get_string_type(UI_STRING *uis); +/* Return input flags of the UI_STRING */ +int UI_get_input_flags(UI_STRING *uis); +/* Return the actual string to output (the prompt, info or error) */ +const char *UI_get0_output_string(UI_STRING *uis); +/* Return the optional action string to output (boolean prompt instruction) */ +const char *UI_get0_action_string(UI_STRING *uis); +/* Return the result of a prompt */ +const char *UI_get0_result_string(UI_STRING *uis); +/* Return the string to test the result against. Only useful with verifies. */ +const char *UI_get0_test_string(UI_STRING *uis); +/* Return the required minimum size of the result */ +int UI_get_result_minsize(UI_STRING *uis); +/* Return the required maximum size of the result */ +int UI_get_result_maxsize(UI_STRING *uis); +/* Set the result of a UI_STRING. */ +int UI_set_result(UI *ui, UI_STRING *uis, const char *result); + +/* A couple of popular utility functions */ +int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, + int verify); +int UI_UTIL_read_pw(char *buf, char *buff, int size, const char *prompt, + int verify); + +void ERR_load_UI_strings(void); + +/* Error codes for the UI functions. */ + +/* Function codes. */ +#define UI_F_GENERAL_ALLOCATE_BOOLEAN 108 +#define UI_F_GENERAL_ALLOCATE_PROMPT 109 +#define UI_F_GENERAL_ALLOCATE_STRING 100 +#define UI_F_UI_CTRL 111 +#define UI_F_UI_DUP_ERROR_STRING 101 +#define UI_F_UI_DUP_INFO_STRING 102 +#define UI_F_UI_DUP_INPUT_BOOLEAN 110 +#define UI_F_UI_DUP_INPUT_STRING 103 +#define UI_F_UI_DUP_VERIFY_STRING 106 +#define UI_F_UI_GET0_RESULT 107 +#define UI_F_UI_NEW_METHOD 104 +#define UI_F_UI_SET_RESULT 105 + +/* Reason codes. */ +#define UI_R_COMMON_OK_AND_CANCEL_CHARACTERS 104 +#define UI_R_INDEX_TOO_LARGE 102 +#define UI_R_INDEX_TOO_SMALL 103 +#define UI_R_NO_RESULT_BUFFER 105 +#define UI_R_RESULT_TOO_LARGE 100 +#define UI_R_RESULT_TOO_SMALL 101 +#define UI_R_UNKNOWN_CONTROL_COMMAND 106 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/ui_compat.h b/include/openssl/ui_compat.h new file mode 100644 index 0000000..6484bf6 --- /dev/null +++ b/include/openssl/ui_compat.h @@ -0,0 +1,65 @@ +/* $OpenBSD: ui_compat.h,v 1.5 2022/12/23 02:20:28 jsing Exp $ */ +/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL + * project 2001. + */ +/* ==================================================================== + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_UI_COMPAT_H +#define HEADER_UI_COMPAT_H + +#include +#include + +#endif diff --git a/include/openssl/whrlpool.h b/include/openssl/whrlpool.h new file mode 100644 index 0000000..875d34f --- /dev/null +++ b/include/openssl/whrlpool.h @@ -0,0 +1,41 @@ +/* $OpenBSD: whrlpool.h,v 1.5 2014/07/10 22:45:58 jsing Exp $ */ + +#include + +#ifndef HEADER_WHRLPOOL_H +#define HEADER_WHRLPOOL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define WHIRLPOOL_DIGEST_LENGTH (512/8) +#define WHIRLPOOL_BBLOCK 512 +#define WHIRLPOOL_COUNTER (256/8) + +typedef struct { + union { + unsigned char c[WHIRLPOOL_DIGEST_LENGTH]; + /* double q is here to ensure 64-bit alignment */ + double q[WHIRLPOOL_DIGEST_LENGTH/sizeof(double)]; + } H; + unsigned char data[WHIRLPOOL_BBLOCK/8]; + unsigned int bitoff; + size_t bitlen[WHIRLPOOL_COUNTER/sizeof(size_t)]; + } WHIRLPOOL_CTX; + +#ifndef OPENSSL_NO_WHIRLPOOL +int WHIRLPOOL_Init (WHIRLPOOL_CTX *c); +int WHIRLPOOL_Update (WHIRLPOOL_CTX *c,const void *inp,size_t bytes); +void WHIRLPOOL_BitUpdate(WHIRLPOOL_CTX *c,const void *inp,size_t bits); +int WHIRLPOOL_Final (unsigned char *md,WHIRLPOOL_CTX *c); +unsigned char *WHIRLPOOL(const void *inp,size_t bytes,unsigned char *md); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/openssl/x509.h b/include/openssl/x509.h new file mode 100644 index 0000000..7980761 --- /dev/null +++ b/include/openssl/x509.h @@ -0,0 +1,1203 @@ +/* $OpenBSD: x509.h,v 1.101 2023/07/28 15:50:33 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECDH support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#ifndef HEADER_X509_H +#define HEADER_X509_H + +#include + +#include +#ifndef OPENSSL_NO_BIO +#include +#endif +#ifndef OPENSSL_NO_BUFFER +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_EC +#include +#endif +#ifndef OPENSSL_NO_EVP +#include +#endif +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_SHA +#include +#endif +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_WIN32) && defined(__WINCRYPT_H__) +#if !defined(LIBRESSL_INTERNAL) && !defined(LIBRESSL_DISABLE_OVERRIDE_WINCRYPT_DEFINES_WARNING) +#ifdef _MSC_VER +#pragma message("Warning, overriding WinCrypt defines") +#else +#warning overriding WinCrypt defines +#endif +#endif +#undef X509_NAME +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS +#endif + +#define X509_FILETYPE_PEM 1 +#define X509_FILETYPE_ASN1 2 +#define X509_FILETYPE_DEFAULT 3 + +#define X509v3_KU_DIGITAL_SIGNATURE 0x0080 +#define X509v3_KU_NON_REPUDIATION 0x0040 +#define X509v3_KU_KEY_ENCIPHERMENT 0x0020 +#define X509v3_KU_DATA_ENCIPHERMENT 0x0010 +#define X509v3_KU_KEY_AGREEMENT 0x0008 +#define X509v3_KU_KEY_CERT_SIGN 0x0004 +#define X509v3_KU_CRL_SIGN 0x0002 +#define X509v3_KU_ENCIPHER_ONLY 0x0001 +#define X509v3_KU_DECIPHER_ONLY 0x8000 +#define X509v3_KU_UNDEF 0xffff + +struct X509_algor_st { + ASN1_OBJECT *algorithm; + ASN1_TYPE *parameter; +} /* X509_ALGOR */; + +typedef STACK_OF(X509_ALGOR) X509_ALGORS; + +typedef struct X509_val_st { + ASN1_TIME *notBefore; + ASN1_TIME *notAfter; +} X509_VAL; + +typedef struct X509_sig_st X509_SIG; + +typedef struct X509_name_entry_st X509_NAME_ENTRY; + +DECLARE_STACK_OF(X509_NAME_ENTRY) + +DECLARE_STACK_OF(X509_NAME) + +typedef struct X509_extension_st X509_EXTENSION; + +typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS; + +DECLARE_STACK_OF(X509_EXTENSION) + +typedef struct x509_attributes_st X509_ATTRIBUTE; + +DECLARE_STACK_OF(X509_ATTRIBUTE) + +typedef struct X509_req_info_st X509_REQ_INFO; + +typedef struct X509_req_st X509_REQ; + +typedef struct x509_cert_aux_st X509_CERT_AUX; + +typedef struct x509_cinf_st X509_CINF; + +DECLARE_STACK_OF(X509) + +/* This is used for a table of trust checking functions */ + +typedef struct x509_trust_st { + int trust; + int flags; + int (*check_trust)(struct x509_trust_st *, X509 *, int); + char *name; + int arg1; + void *arg2; +} X509_TRUST; + +DECLARE_STACK_OF(X509_TRUST) + +/* standard trust ids */ + +/* OpenSSL changed this to 0 */ +#define X509_TRUST_DEFAULT -1 /* Only valid in purpose settings */ + +#define X509_TRUST_COMPAT 1 +#define X509_TRUST_SSL_CLIENT 2 +#define X509_TRUST_SSL_SERVER 3 +#define X509_TRUST_EMAIL 4 +#define X509_TRUST_OBJECT_SIGN 5 +#define X509_TRUST_OCSP_SIGN 6 +#define X509_TRUST_OCSP_REQUEST 7 +#define X509_TRUST_TSA 8 + +/* Keep these up to date! */ +#define X509_TRUST_MIN 1 +#define X509_TRUST_MAX 8 + + +/* trust_flags values */ +#define X509_TRUST_DYNAMIC 1 +#define X509_TRUST_DYNAMIC_NAME 2 + +/* check_trust return codes */ + +#define X509_TRUST_TRUSTED 1 +#define X509_TRUST_REJECTED 2 +#define X509_TRUST_UNTRUSTED 3 + +/* Flags for X509_print_ex() */ + +#define X509_FLAG_COMPAT 0 +#define X509_FLAG_NO_HEADER 1L +#define X509_FLAG_NO_VERSION (1L << 1) +#define X509_FLAG_NO_SERIAL (1L << 2) +#define X509_FLAG_NO_SIGNAME (1L << 3) +#define X509_FLAG_NO_ISSUER (1L << 4) +#define X509_FLAG_NO_VALIDITY (1L << 5) +#define X509_FLAG_NO_SUBJECT (1L << 6) +#define X509_FLAG_NO_PUBKEY (1L << 7) +#define X509_FLAG_NO_EXTENSIONS (1L << 8) +#define X509_FLAG_NO_SIGDUMP (1L << 9) +#define X509_FLAG_NO_AUX (1L << 10) +#define X509_FLAG_NO_ATTRIBUTES (1L << 11) + +/* Flags specific to X509_NAME_print_ex() */ + +/* The field separator information */ + +#define XN_FLAG_SEP_MASK (0xf << 16) + +#define XN_FLAG_COMPAT 0 /* Traditional SSLeay: use old X509_NAME_print */ +#define XN_FLAG_SEP_COMMA_PLUS (1 << 16) /* RFC2253 ,+ */ +#define XN_FLAG_SEP_CPLUS_SPC (2 << 16) /* ,+ spaced: more readable */ +#define XN_FLAG_SEP_SPLUS_SPC (3 << 16) /* ;+ spaced */ +#define XN_FLAG_SEP_MULTILINE (4 << 16) /* One line per field */ + +#define XN_FLAG_DN_REV (1 << 20) /* Reverse DN order */ + +/* How the field name is shown */ + +#define XN_FLAG_FN_MASK (0x3 << 21) + +#define XN_FLAG_FN_SN 0 /* Object short name */ +#define XN_FLAG_FN_LN (1 << 21) /* Object long name */ +#define XN_FLAG_FN_OID (2 << 21) /* Always use OIDs */ +#define XN_FLAG_FN_NONE (3 << 21) /* No field names */ + +#define XN_FLAG_SPC_EQ (1 << 23) /* Put spaces round '=' */ + +/* This determines if we dump fields we don't recognise: + * RFC2253 requires this. + */ + +#define XN_FLAG_DUMP_UNKNOWN_FIELDS (1 << 24) + +#define XN_FLAG_FN_ALIGN (1 << 25) /* Align field names to 20 characters */ + +/* Complete set of RFC2253 flags */ + +#define XN_FLAG_RFC2253 (ASN1_STRFLGS_RFC2253 | \ + XN_FLAG_SEP_COMMA_PLUS | \ + XN_FLAG_DN_REV | \ + XN_FLAG_FN_SN | \ + XN_FLAG_DUMP_UNKNOWN_FIELDS) + +/* readable oneline form */ + +#define XN_FLAG_ONELINE (ASN1_STRFLGS_RFC2253 | \ + ASN1_STRFLGS_ESC_QUOTE | \ + XN_FLAG_SEP_CPLUS_SPC | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_SN) + +/* readable multiline form */ + +#define XN_FLAG_MULTILINE (ASN1_STRFLGS_ESC_CTRL | \ + ASN1_STRFLGS_ESC_MSB | \ + XN_FLAG_SEP_MULTILINE | \ + XN_FLAG_SPC_EQ | \ + XN_FLAG_FN_LN | \ + XN_FLAG_FN_ALIGN) + +DECLARE_STACK_OF(X509_REVOKED) + +typedef struct X509_crl_info_st X509_CRL_INFO; + +DECLARE_STACK_OF(X509_CRL) + +typedef struct private_key_st { + int version; + /* The PKCS#8 data types */ + X509_ALGOR *enc_algor; + ASN1_OCTET_STRING *enc_pkey; /* encrypted pub key */ + + /* When decrypted, the following will not be NULL */ + EVP_PKEY *dec_pkey; + + /* used to encrypt and decrypt */ + int key_length; + char *key_data; + int key_free; /* true if we should auto free key_data */ + + /* expanded version of 'enc_algor' */ + EVP_CIPHER_INFO cipher; + + int references; +} X509_PKEY; + +#ifndef OPENSSL_NO_EVP +typedef struct X509_info_st { + X509 *x509; + X509_CRL *crl; + X509_PKEY *x_pkey; + + EVP_CIPHER_INFO enc_cipher; + int enc_len; + char *enc_data; + + int references; +} X509_INFO; + +DECLARE_STACK_OF(X509_INFO) +#endif + +/* The next 2 structures and their 8 routines were sent to me by + * Pat Richard and are used to manipulate + * Netscapes spki structures - useful if you are writing a CA web page + */ +typedef struct Netscape_spkac_st { + X509_PUBKEY *pubkey; + ASN1_IA5STRING *challenge; /* challenge sent in atlas >= PR2 */ +} NETSCAPE_SPKAC; + +typedef struct Netscape_spki_st { + NETSCAPE_SPKAC *spkac; /* signed public key and challenge */ + X509_ALGOR *sig_algor; + ASN1_BIT_STRING *signature; +} NETSCAPE_SPKI; + +/* Password based encryption structure */ + +typedef struct PBEPARAM_st { + ASN1_OCTET_STRING *salt; + ASN1_INTEGER *iter; +} PBEPARAM; + +/* Password based encryption V2 structures */ + +typedef struct PBE2PARAM_st { + X509_ALGOR *keyfunc; + X509_ALGOR *encryption; +} PBE2PARAM; + +typedef struct PBKDF2PARAM_st { + /* Usually OCTET STRING but could be anything */ + ASN1_TYPE *salt; + ASN1_INTEGER *iter; + ASN1_INTEGER *keylength; + X509_ALGOR *prf; +} PBKDF2PARAM; + +#ifdef __cplusplus +} +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define X509_extract_key(x) X509_get_pubkey(x) /*****/ +#define X509_REQ_extract_key(a) X509_REQ_get_pubkey(a) +#define X509_name_cmp(a,b) X509_NAME_cmp((a),(b)) + +int X509_CRL_up_ref(X509_CRL *x); +int X509_CRL_get_signature_nid(const X509_CRL *crl); + +int i2d_re_X509_CRL_tbs(X509_CRL *req, unsigned char **pp); + +const STACK_OF(X509_EXTENSION) *X509_CRL_get0_extensions(const X509_CRL *crl); +long X509_CRL_get_version(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_lastUpdate(const X509_CRL *crl); +const ASN1_TIME *X509_CRL_get0_nextUpdate(const X509_CRL *crl); +ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *crl); +ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *crl); +X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl); +STACK_OF(X509_REVOKED) *X509_CRL_get_REVOKED(X509_CRL *crl); +void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); + +const X509_ALGOR *X509_CRL_get0_tbs_sigalg(const X509_CRL *crl); + +int X509_REQ_get_signature_nid(const X509_REQ *req); + +void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg); + +void X509_CRL_set_default_method(const X509_CRL_METHOD *meth); +X509_CRL_METHOD *X509_CRL_METHOD_new( + int (*crl_init)(X509_CRL *crl), + int (*crl_free)(X509_CRL *crl), + int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret, + ASN1_INTEGER *ser, X509_NAME *issuer), + int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk)); +void X509_CRL_METHOD_free(X509_CRL_METHOD *m); + +void X509_CRL_set_meth_data(X509_CRL *crl, void *dat); +void *X509_CRL_get_meth_data(X509_CRL *crl); + +X509_PUBKEY *X509_get_X509_PUBKEY(const X509 *x); + +const char *X509_verify_cert_error_string(long n); + +#ifndef OPENSSL_NO_EVP +int X509_verify(X509 *a, EVP_PKEY *r); + +int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r); +int X509_CRL_verify(X509_CRL *a, EVP_PKEY *r); +int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r); + +NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len); +char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *x); +EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x); +int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent); +int X509_signature_print(BIO *bp, const X509_ALGOR *alg, + const ASN1_STRING *sig); + +int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx); +int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx); +int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx); +int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); + +int X509_pubkey_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_REQ_digest(const X509_REQ *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +int X509_NAME_digest(const X509_NAME *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); +#endif + +X509 *d2i_X509_fp(FILE *fp, X509 **x509); +int i2d_X509_fp(FILE *fp,X509 *x509); +X509_CRL *d2i_X509_CRL_fp(FILE *fp,X509_CRL **crl); +int i2d_X509_CRL_fp(FILE *fp,X509_CRL *crl); +X509_REQ *d2i_X509_REQ_fp(FILE *fp,X509_REQ **req); +int i2d_X509_REQ_fp(FILE *fp,X509_REQ *req); +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_fp(FILE *fp,RSA **rsa); +int i2d_RSAPrivateKey_fp(FILE *fp,RSA *rsa); +RSA *d2i_RSAPublicKey_fp(FILE *fp,RSA **rsa); +int i2d_RSAPublicKey_fp(FILE *fp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_fp(FILE *fp,RSA **rsa); +int i2d_RSA_PUBKEY_fp(FILE *fp,RSA *rsa); +#endif +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa); +int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa); +DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa); +int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa); +#endif +#ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey); +int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey); +int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey); +#endif +X509_SIG *d2i_PKCS8_fp(FILE *fp,X509_SIG **p8); +int i2d_PKCS8_fp(FILE *fp,X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key); +int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a); +int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a); + +#ifndef OPENSSL_NO_BIO +X509 *d2i_X509_bio(BIO *bp,X509 **x509); +int i2d_X509_bio(BIO *bp,X509 *x509); +X509_CRL *d2i_X509_CRL_bio(BIO *bp,X509_CRL **crl); +int i2d_X509_CRL_bio(BIO *bp,X509_CRL *crl); +X509_REQ *d2i_X509_REQ_bio(BIO *bp,X509_REQ **req); +int i2d_X509_REQ_bio(BIO *bp,X509_REQ *req); +#ifndef OPENSSL_NO_RSA +RSA *d2i_RSAPrivateKey_bio(BIO *bp,RSA **rsa); +int i2d_RSAPrivateKey_bio(BIO *bp,RSA *rsa); +RSA *d2i_RSAPublicKey_bio(BIO *bp,RSA **rsa); +int i2d_RSAPublicKey_bio(BIO *bp,RSA *rsa); +RSA *d2i_RSA_PUBKEY_bio(BIO *bp,RSA **rsa); +int i2d_RSA_PUBKEY_bio(BIO *bp,RSA *rsa); +#endif +#ifndef OPENSSL_NO_DSA +DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa); +int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa); +DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa); +int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa); +#endif +#ifndef OPENSSL_NO_EC +EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey); +int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *eckey); +EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey); +int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey); +#endif +X509_SIG *d2i_PKCS8_bio(BIO *bp,X509_SIG **p8); +int i2d_PKCS8_bio(BIO *bp,X509_SIG *p8); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, + PKCS8_PRIV_KEY_INFO **p8inf); +int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,PKCS8_PRIV_KEY_INFO *p8inf); +int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key); +int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a); +int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey); +EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a); +#endif + +X509 *X509_dup(X509 *x509); +X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa); +X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex); +X509_CRL *X509_CRL_dup(X509_CRL *crl); +X509_REQ *X509_REQ_dup(X509_REQ *req); +X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn); +int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval); +void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, const void **ppval, + const X509_ALGOR *algor); +void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md); +int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b); + +X509_NAME *X509_NAME_dup(X509_NAME *xn); +int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder, size_t *pderlen); +X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne); + +int X509_cmp_time(const ASN1_TIME *s, time_t *t); +int X509_cmp_current_time(const ASN1_TIME *s); +ASN1_TIME * X509_time_adj(ASN1_TIME *s, long adj, time_t *t); +ASN1_TIME * X509_time_adj_ex(ASN1_TIME *s, + int offset_day, long offset_sec, time_t *t); +ASN1_TIME * X509_gmtime_adj(ASN1_TIME *s, long adj); + +const char * X509_get_default_cert_area(void ); +const char * X509_get_default_cert_dir(void ); +const char * X509_get_default_cert_file(void ); +const char * X509_get_default_cert_dir_env(void ); +const char * X509_get_default_cert_file_env(void ); +const char * X509_get_default_private_dir(void ); + +X509_REQ * X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); +X509 * X509_REQ_to_X509(X509_REQ *r, int days,EVP_PKEY *pkey); + +X509_ALGOR *X509_ALGOR_new(void); +void X509_ALGOR_free(X509_ALGOR *a); +X509_ALGOR *d2i_X509_ALGOR(X509_ALGOR **a, const unsigned char **in, long len); +int i2d_X509_ALGOR(X509_ALGOR *a, unsigned char **out); +extern const ASN1_ITEM X509_ALGOR_it; +X509_ALGORS *d2i_X509_ALGORS(X509_ALGORS **a, const unsigned char **in, long len); +int i2d_X509_ALGORS(X509_ALGORS *a, unsigned char **out); +extern const ASN1_ITEM X509_ALGORS_it; +X509_VAL *X509_VAL_new(void); +void X509_VAL_free(X509_VAL *a); +X509_VAL *d2i_X509_VAL(X509_VAL **a, const unsigned char **in, long len); +int i2d_X509_VAL(X509_VAL *a, unsigned char **out); +extern const ASN1_ITEM X509_VAL_it; + +X509_PUBKEY *X509_PUBKEY_new(void); +void X509_PUBKEY_free(X509_PUBKEY *a); +X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len); +int i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **out); +extern const ASN1_ITEM X509_PUBKEY_it; + +int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey); +EVP_PKEY * X509_PUBKEY_get(X509_PUBKEY *key); +EVP_PKEY * X509_PUBKEY_get0(X509_PUBKEY *key); +int X509_get_pubkey_parameters(EVP_PKEY *pkey, + STACK_OF(X509) *chain); +int i2d_PUBKEY(EVP_PKEY *a,unsigned char **pp); +EVP_PKEY * d2i_PUBKEY(EVP_PKEY **a,const unsigned char **pp, + long length); +#ifndef OPENSSL_NO_RSA +int i2d_RSA_PUBKEY(RSA *a,unsigned char **pp); +RSA * d2i_RSA_PUBKEY(RSA **a,const unsigned char **pp, + long length); +#endif +#ifndef OPENSSL_NO_DSA +int i2d_DSA_PUBKEY(DSA *a,unsigned char **pp); +DSA * d2i_DSA_PUBKEY(DSA **a,const unsigned char **pp, + long length); +#endif +#ifndef OPENSSL_NO_EC +int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp); +EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, + long length); +#endif + +X509_SIG *X509_SIG_new(void); +void X509_SIG_free(X509_SIG *a); +X509_SIG *d2i_X509_SIG(X509_SIG **a, const unsigned char **in, long len); +int i2d_X509_SIG(X509_SIG *a, unsigned char **out); +extern const ASN1_ITEM X509_SIG_it; +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, + const ASN1_OCTET_STRING **pdigest); +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, + ASN1_OCTET_STRING **pdigest); + +X509_REQ_INFO *X509_REQ_INFO_new(void); +void X509_REQ_INFO_free(X509_REQ_INFO *a); +X509_REQ_INFO *d2i_X509_REQ_INFO(X509_REQ_INFO **a, const unsigned char **in, long len); +int i2d_X509_REQ_INFO(X509_REQ_INFO *a, unsigned char **out); +extern const ASN1_ITEM X509_REQ_INFO_it; +X509_REQ *X509_REQ_new(void); +void X509_REQ_free(X509_REQ *a); +X509_REQ *d2i_X509_REQ(X509_REQ **a, const unsigned char **in, long len); +int i2d_X509_REQ(X509_REQ *a, unsigned char **out); +extern const ASN1_ITEM X509_REQ_it; + +X509_ATTRIBUTE *X509_ATTRIBUTE_new(void); +void X509_ATTRIBUTE_free(X509_ATTRIBUTE *a); +X509_ATTRIBUTE *d2i_X509_ATTRIBUTE(X509_ATTRIBUTE **a, const unsigned char **in, long len); +int i2d_X509_ATTRIBUTE(X509_ATTRIBUTE *a, unsigned char **out); +extern const ASN1_ITEM X509_ATTRIBUTE_it; +X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value); + +X509_EXTENSION *X509_EXTENSION_new(void); +void X509_EXTENSION_free(X509_EXTENSION *a); +X509_EXTENSION *d2i_X509_EXTENSION(X509_EXTENSION **a, const unsigned char **in, long len); +int i2d_X509_EXTENSION(X509_EXTENSION *a, unsigned char **out); +extern const ASN1_ITEM X509_EXTENSION_it; +X509_EXTENSIONS *d2i_X509_EXTENSIONS(X509_EXTENSIONS **a, const unsigned char **in, long len); +int i2d_X509_EXTENSIONS(X509_EXTENSIONS *a, unsigned char **out); +extern const ASN1_ITEM X509_EXTENSIONS_it; + +X509_NAME_ENTRY *X509_NAME_ENTRY_new(void); +void X509_NAME_ENTRY_free(X509_NAME_ENTRY *a); +X509_NAME_ENTRY *d2i_X509_NAME_ENTRY(X509_NAME_ENTRY **a, const unsigned char **in, long len); +int i2d_X509_NAME_ENTRY(X509_NAME_ENTRY *a, unsigned char **out); +extern const ASN1_ITEM X509_NAME_ENTRY_it; + +X509_NAME *X509_NAME_new(void); +void X509_NAME_free(X509_NAME *a); +X509_NAME *d2i_X509_NAME(X509_NAME **a, const unsigned char **in, long len); +int i2d_X509_NAME(X509_NAME *a, unsigned char **out); +extern const ASN1_ITEM X509_NAME_it; + +int X509_NAME_set(X509_NAME **xn, X509_NAME *name); + +X509_CINF *X509_CINF_new(void); +void X509_CINF_free(X509_CINF *a); +X509_CINF *d2i_X509_CINF(X509_CINF **a, const unsigned char **in, long len); +int i2d_X509_CINF(X509_CINF *a, unsigned char **out); +extern const ASN1_ITEM X509_CINF_it; + +X509 *X509_new(void); +void X509_free(X509 *a); +X509 *d2i_X509(X509 **a, const unsigned char **in, long len); +int i2d_X509(X509 *a, unsigned char **out); +extern const ASN1_ITEM X509_it; +X509_CERT_AUX *X509_CERT_AUX_new(void); +void X509_CERT_AUX_free(X509_CERT_AUX *a); +X509_CERT_AUX *d2i_X509_CERT_AUX(X509_CERT_AUX **a, const unsigned char **in, long len); +int i2d_X509_CERT_AUX(X509_CERT_AUX *a, unsigned char **out); +extern const ASN1_ITEM X509_CERT_AUX_it; + +int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int X509_set_ex_data(X509 *r, int idx, void *arg); +void *X509_get_ex_data(X509 *r, int idx); +int i2d_X509_AUX(X509 *a,unsigned char **pp); +X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length); + +int i2d_re_X509_tbs(X509 *x, unsigned char **pp); + +void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); +int X509_get_signature_nid(const X509 *x); + +int X509_alias_set1(X509 *x, const unsigned char *name, int len); +int X509_keyid_set1(X509 *x, const unsigned char *id, int len); +unsigned char *X509_alias_get0(X509 *x, int *len); +unsigned char *X509_keyid_get0(X509 *x, int *len); +int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int); +int X509_TRUST_set(int *t, int trust); +int X509_add1_trust_object(X509 *x, const ASN1_OBJECT *obj); +int X509_add1_reject_object(X509 *x, const ASN1_OBJECT *obj); +void X509_trust_clear(X509 *x); +void X509_reject_clear(X509 *x); + +X509_REVOKED *X509_REVOKED_new(void); +void X509_REVOKED_free(X509_REVOKED *a); +X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *a); +X509_REVOKED *d2i_X509_REVOKED(X509_REVOKED **a, const unsigned char **in, long len); +int i2d_X509_REVOKED(X509_REVOKED *a, unsigned char **out); +extern const ASN1_ITEM X509_REVOKED_it; + +X509_CRL_INFO *X509_CRL_INFO_new(void); +void X509_CRL_INFO_free(X509_CRL_INFO *a); +X509_CRL_INFO *d2i_X509_CRL_INFO(X509_CRL_INFO **a, const unsigned char **in, long len); +int i2d_X509_CRL_INFO(X509_CRL_INFO *a, unsigned char **out); +extern const ASN1_ITEM X509_CRL_INFO_it; + +X509_CRL *X509_CRL_new(void); +void X509_CRL_free(X509_CRL *a); +X509_CRL *d2i_X509_CRL(X509_CRL **a, const unsigned char **in, long len); +int i2d_X509_CRL(X509_CRL *a, unsigned char **out); +extern const ASN1_ITEM X509_CRL_it; + +int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev); +int X509_CRL_get0_by_serial(X509_CRL *crl, + X509_REVOKED **ret, ASN1_INTEGER *serial); +int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x); + +X509_PKEY * X509_PKEY_new(void ); +void X509_PKEY_free(X509_PKEY *a); + +NETSCAPE_SPKI *NETSCAPE_SPKI_new(void); +void NETSCAPE_SPKI_free(NETSCAPE_SPKI *a); +NETSCAPE_SPKI *d2i_NETSCAPE_SPKI(NETSCAPE_SPKI **a, const unsigned char **in, long len); +int i2d_NETSCAPE_SPKI(NETSCAPE_SPKI *a, unsigned char **out); +extern const ASN1_ITEM NETSCAPE_SPKI_it; +NETSCAPE_SPKAC *NETSCAPE_SPKAC_new(void); +void NETSCAPE_SPKAC_free(NETSCAPE_SPKAC *a); +NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **a, const unsigned char **in, long len); +int i2d_NETSCAPE_SPKAC(NETSCAPE_SPKAC *a, unsigned char **out); +extern const ASN1_ITEM NETSCAPE_SPKAC_it; + +#ifndef OPENSSL_NO_EVP +X509_INFO * X509_INFO_new(void); +void X509_INFO_free(X509_INFO *a); +char * X509_NAME_oneline(const X509_NAME *a, char *buf, int size); + +int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data, + unsigned char *md,unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, + void *data, EVP_PKEY *pkey, const EVP_MD *type); +int ASN1_item_sign_ctx(const ASN1_ITEM *it, + X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx); +#endif + +const STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x); +void X509_get0_uids(const X509 *x, const ASN1_BIT_STRING **piuid, + const ASN1_BIT_STRING **psuid); +const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x); +int X509_set_version(X509 *x, long version); +long X509_get_version(const X509 *x); +int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial); +ASN1_INTEGER * X509_get_serialNumber(X509 *x); +const ASN1_INTEGER *X509_get0_serialNumber(const X509 *x); +int X509_set_issuer_name(X509 *x, X509_NAME *name); +X509_NAME * X509_get_issuer_name(const X509 *a); +int X509_set_subject_name(X509 *x, X509_NAME *name); +X509_NAME * X509_get_subject_name(const X509 *a); +int X509_set_notBefore(X509 *x, const ASN1_TIME *tm); +int X509_set1_notBefore(X509 *x, const ASN1_TIME *tm); +int X509_set_notAfter(X509 *x, const ASN1_TIME *tm); +int X509_set1_notAfter(X509 *x, const ASN1_TIME *tm); +const ASN1_TIME *X509_get0_notBefore(const X509 *x); +ASN1_TIME *X509_getm_notBefore(const X509 *x); +const ASN1_TIME *X509_get0_notAfter(const X509 *x); +ASN1_TIME *X509_getm_notAfter(const X509 *x); +int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); +EVP_PKEY * X509_get_pubkey(X509 *x); +EVP_PKEY * X509_get0_pubkey(const X509 *x); +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x); +int X509_certificate_type(const X509 *x, const EVP_PKEY *pubkey); +int X509_get_signature_type(const X509 *x); + +#define X509_get_notBefore X509_getm_notBefore +#define X509_get_notAfter X509_getm_notAfter + +int X509_REQ_set_version(X509_REQ *x,long version); +long X509_REQ_get_version(const X509_REQ *x); +int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name); +X509_NAME *X509_REQ_get_subject_name(const X509_REQ *x); +int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); +EVP_PKEY * X509_REQ_get_pubkey(X509_REQ *req); +int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp); +EVP_PKEY * X509_REQ_get0_pubkey(X509_REQ *req); +int X509_REQ_extension_nid(int nid); +int * X509_REQ_get_extension_nids(void); +void X509_REQ_set_extension_nids(int *nids); +STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req); +int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts, + int nid); +int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts); +int X509_REQ_get_attr_count(const X509_REQ *req); +int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, + int lastpos); +int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc); +X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc); +int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr); +int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len); +int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_CRL_set_version(X509_CRL *x, long version); +int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name); +int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set1_lastUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_set1_nextUpdate(X509_CRL *x, const ASN1_TIME *tm); +int X509_CRL_sort(X509_CRL *crl); + +const STACK_OF(X509_EXTENSION) *X509_REVOKED_get0_extensions(const X509_REVOKED *x); +const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x); +const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x); +int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm); +int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial); + +int X509_REQ_check_private_key(X509_REQ *x509,EVP_PKEY *pkey); + +int X509_check_private_key(const X509 *x509, const EVP_PKEY *pkey); + +int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_and_serial_hash(X509 *a); + +int X509_issuer_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_issuer_name_hash(X509 *a); + +int X509_subject_name_cmp(const X509 *a, const X509 *b); +unsigned long X509_subject_name_hash(X509 *x); + +#ifndef OPENSSL_NO_MD5 +unsigned long X509_issuer_name_hash_old(X509 *a); +unsigned long X509_subject_name_hash_old(X509 *x); +#endif + +int X509_cmp(const X509 *a, const X509 *b); +int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b); +unsigned long X509_NAME_hash(X509_NAME *x); +unsigned long X509_NAME_hash_old(X509_NAME *x); + +int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b); +int X509_CRL_match(const X509_CRL *a, const X509_CRL *b); +int X509_print_ex_fp(FILE *bp,X509 *x, unsigned long nmflag, unsigned long cflag); +int X509_print_fp(FILE *bp,X509 *x); +int X509_CRL_print_fp(FILE *bp,X509_CRL *x); +int X509_REQ_print_fp(FILE *bp,X509_REQ *req); +int X509_NAME_print_ex_fp(FILE *fp, const X509_NAME *nm, int indent, + unsigned long flags); + +#ifndef OPENSSL_NO_BIO +int X509_NAME_print(BIO *bp, const X509_NAME *name, int obase); +int X509_NAME_print_ex(BIO *out, const X509_NAME *nm, int indent, + unsigned long flags); +int X509_print_ex(BIO *bp,X509 *x, unsigned long nmflag, unsigned long cflag); +int X509_print(BIO *bp,X509 *x); +int X509_ocspid_print(BIO *bp,X509 *x); +int X509_CERT_AUX_print(BIO *bp,X509_CERT_AUX *x, int indent); +int X509_CRL_print(BIO *bp,X509_CRL *x); +int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflag, unsigned long cflag); +int X509_REQ_print(BIO *bp,X509_REQ *req); +#endif + +int X509_NAME_entry_count(const X509_NAME *name); +int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, + char *buf,int len); +int X509_NAME_get_text_by_OBJ(X509_NAME *name, + const ASN1_OBJECT *obj, char *buf,int len); + +/* NOTE: you should be passing -1, not 0 as lastpos. The functions that use + * lastpos, search after that position on. */ +int X509_NAME_get_index_by_NID(const X509_NAME *name, int nid, + int lastpos); +int X509_NAME_get_index_by_OBJ(const X509_NAME *name, + const ASN1_OBJECT *obj, int lastpos); +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc); +X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc); +int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, + int loc, int set); +int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, + int type, const unsigned char *bytes, int len, int loc, int set); +int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, + const unsigned char *bytes, int len, int loc, int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, + const char *field, int type, const unsigned char *bytes, int len); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, + int type, const unsigned char *bytes, int len); +int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, + const unsigned char *bytes, int len, int loc, int set); +X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, + const ASN1_OBJECT *obj); +int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, + const unsigned char *bytes, int len); +ASN1_OBJECT * X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *ne); +ASN1_STRING * X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *ne); +int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne); + +int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x); +int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, + int nid, int lastpos); +int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *x, + const ASN1_OBJECT *obj, int lastpos); +int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *x, + int crit, int lastpos); +X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc); +X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc); +STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x, + X509_EXTENSION *ex, int loc); + +int X509_get_ext_count(const X509 *x); +int X509_get_ext_by_NID(const X509 *x, int nid, int lastpos); +int X509_get_ext_by_OBJ(const X509 *x, const ASN1_OBJECT *obj, + int lastpos); +int X509_get_ext_by_critical(const X509 *x, int crit, int lastpos); +X509_EXTENSION *X509_get_ext(const X509 *x, int loc); +X509_EXTENSION *X509_delete_ext(X509 *x, int loc); +int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); +void * X509_get_ext_d2i(const X509 *x, int nid, int *crit, int *idx); +int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit, + unsigned long flags); + +int X509_CRL_get_ext_count(const X509_CRL *x); +int X509_CRL_get_ext_by_NID(const X509_CRL *x, int nid, + int lastpos); +int X509_CRL_get_ext_by_OBJ(const X509_CRL *x, + const ASN1_OBJECT *obj, int lastpos); +int X509_CRL_get_ext_by_critical(const X509_CRL *x, int crit, + int lastpos); +X509_EXTENSION *X509_CRL_get_ext(const X509_CRL *x, int loc); +X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc); +int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc); +void * X509_CRL_get_ext_d2i(const X509_CRL *x, int nid, int *crit, + int *idx); +int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, + int crit, unsigned long flags); + +int X509_REVOKED_get_ext_count(const X509_REVOKED *x); +int X509_REVOKED_get_ext_by_NID(const X509_REVOKED *x, int nid, + int lastpos); +int X509_REVOKED_get_ext_by_OBJ(const X509_REVOKED *x, + const ASN1_OBJECT *obj, int lastpos); +int X509_REVOKED_get_ext_by_critical(const X509_REVOKED *x, + int crit, int lastpos); +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *x, int loc); +X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc); +int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, + int loc); +void * X509_REVOKED_get_ext_d2i(const X509_REVOKED *x, int nid, + int *crit, int *idx); +int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, + int crit, unsigned long flags); + +X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, + int nid, int crit, ASN1_OCTET_STRING *data); +X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex, + const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data); +int X509_EXTENSION_set_object(X509_EXTENSION *ex, + const ASN1_OBJECT *obj); +int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit); +int X509_EXTENSION_set_data(X509_EXTENSION *ex, + ASN1_OCTET_STRING *data); +ASN1_OBJECT * X509_EXTENSION_get_object(X509_EXTENSION *ex); +ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ne); +int X509_EXTENSION_get_critical(const X509_EXTENSION *ex); + +int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x); +int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid, + int lastpos); +int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, + const ASN1_OBJECT *obj, int lastpos); +X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc); +X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x, + X509_ATTRIBUTE *attr); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x, + int nid, int type, + const unsigned char *bytes, int len); +STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x, + const char *attrname, int type, + const unsigned char *bytes, int len); +void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x, + const ASN1_OBJECT *obj, int lastpos, int type); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid, + int atrtype, const void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr, + const ASN1_OBJECT *obj, int atrtype, const void *data, int len); +X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr, + const char *atrname, int type, const unsigned char *bytes, int len); +int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj); +int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len); +void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx, + int atrtype, void *data); +int X509_ATTRIBUTE_count(const X509_ATTRIBUTE *attr); +ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr); +ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx); + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key); +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, + int lastpos); +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, + int lastpos); +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc); +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc); +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr); +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, + int nid, int type, + const unsigned char *bytes, int len); +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, + const char *attrname, int type, + const unsigned char *bytes, int len); + +int X509_verify_cert(X509_STORE_CTX *ctx); + +/* lookup a cert from a X509 STACK */ +X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk,X509_NAME *name, + ASN1_INTEGER *serial); +X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name); + +PBEPARAM *PBEPARAM_new(void); +void PBEPARAM_free(PBEPARAM *a); +PBEPARAM *d2i_PBEPARAM(PBEPARAM **a, const unsigned char **in, long len); +int i2d_PBEPARAM(PBEPARAM *a, unsigned char **out); +extern const ASN1_ITEM PBEPARAM_it; +PBE2PARAM *PBE2PARAM_new(void); +void PBE2PARAM_free(PBE2PARAM *a); +PBE2PARAM *d2i_PBE2PARAM(PBE2PARAM **a, const unsigned char **in, long len); +int i2d_PBE2PARAM(PBE2PARAM *a, unsigned char **out); +extern const ASN1_ITEM PBE2PARAM_it; +PBKDF2PARAM *PBKDF2PARAM_new(void); +void PBKDF2PARAM_free(PBKDF2PARAM *a); +PBKDF2PARAM *d2i_PBKDF2PARAM(PBKDF2PARAM **a, const unsigned char **in, long len); +int i2d_PBKDF2PARAM(PBKDF2PARAM *a, unsigned char **out); +extern const ASN1_ITEM PBKDF2PARAM_it; + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, + const unsigned char *salt, int saltlen); + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, + const unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen); +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, + unsigned char *salt, int saltlen, + unsigned char *aiv, int prf_nid); + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, + int prf_nid, int keylen); + +/* PKCS#8 utilities */ + +PKCS8_PRIV_KEY_INFO *PKCS8_PRIV_KEY_INFO_new(void); +void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *a); +PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a, const unsigned char **in, long len); +int i2d_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO *a, unsigned char **out); +extern const ASN1_ITEM PKCS8_PRIV_KEY_INFO_it; + +EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8); +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version, + int ptype, void *pval, unsigned char *penc, int penclen); +int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, const unsigned char **pk, + int *ppklen, const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8); + +const STACK_OF(X509_ATTRIBUTE) *PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8); +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, + const unsigned char *bytes, int len); + +int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, + int ptype, void *pval, + unsigned char *penc, int penclen); +int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, + const unsigned char **pk, int *ppklen, + X509_ALGOR **pa, + X509_PUBKEY *pub); + +int X509_check_trust(X509 *x, int id, int flags); +int X509_TRUST_get_count(void); +X509_TRUST * X509_TRUST_get0(int idx); +int X509_TRUST_get_by_id(int id); +int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int), + const char *name, int arg1, void *arg2); +void X509_TRUST_cleanup(void); +int X509_TRUST_get_flags(const X509_TRUST *xp); +char *X509_TRUST_get0_name(const X509_TRUST *xp); +int X509_TRUST_get_trust(const X509_TRUST *xp); + +int X509_up_ref(X509 *x); +STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain); + +void ERR_load_X509_strings(void); + +/* Error codes for the X509 functions. */ + +/* Function codes. */ +#define X509_F_ADD_CERT_DIR 100 +#define X509_F_BY_FILE_CTRL 101 +#define X509_F_CHECK_POLICY 145 +#define X509_F_DIR_CTRL 102 +#define X509_F_GET_CERT_BY_SUBJECT 103 +#define X509_F_NETSCAPE_SPKI_B64_DECODE 129 +#define X509_F_NETSCAPE_SPKI_B64_ENCODE 130 +#define X509_F_X509AT_ADD1_ATTR 135 +#define X509_F_X509V3_ADD_EXT 104 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_NID 136 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_OBJ 137 +#define X509_F_X509_ATTRIBUTE_CREATE_BY_TXT 140 +#define X509_F_X509_ATTRIBUTE_GET0_DATA 139 +#define X509_F_X509_ATTRIBUTE_SET1_DATA 138 +#define X509_F_X509_CHECK_PRIVATE_KEY 128 +#define X509_F_X509_CRL_PRINT_FP 147 +#define X509_F_X509_EXTENSION_CREATE_BY_NID 108 +#define X509_F_X509_EXTENSION_CREATE_BY_OBJ 109 +#define X509_F_X509_GET_PUBKEY_PARAMETERS 110 +#define X509_F_X509_LOAD_CERT_CRL_FILE 132 +#define X509_F_X509_LOAD_CERT_FILE 111 +#define X509_F_X509_LOAD_CRL_FILE 112 +#define X509_F_X509_NAME_ADD_ENTRY 113 +#define X509_F_X509_NAME_ENTRY_CREATE_BY_NID 114 +#define X509_F_X509_NAME_ENTRY_CREATE_BY_TXT 131 +#define X509_F_X509_NAME_ENTRY_SET_OBJECT 115 +#define X509_F_X509_NAME_ONELINE 116 +#define X509_F_X509_NAME_PRINT 117 +#define X509_F_X509_PRINT_EX_FP 118 +#define X509_F_X509_PUBKEY_GET 119 +#define X509_F_X509_PUBKEY_SET 120 +#define X509_F_X509_REQ_CHECK_PRIVATE_KEY 144 +#define X509_F_X509_REQ_PRINT_EX 121 +#define X509_F_X509_REQ_PRINT_FP 122 +#define X509_F_X509_REQ_TO_X509 123 +#define X509_F_X509_STORE_ADD_CERT 124 +#define X509_F_X509_STORE_ADD_CRL 125 +#define X509_F_X509_STORE_CTX_GET1_ISSUER 146 +#define X509_F_X509_STORE_CTX_INIT 143 +#define X509_F_X509_STORE_CTX_NEW 142 +#define X509_F_X509_STORE_CTX_PURPOSE_INHERIT 134 +#define X509_F_X509_TO_X509_REQ 126 +#define X509_F_X509_TRUST_ADD 133 +#define X509_F_X509_TRUST_SET 141 +#define X509_F_X509_VERIFY_CERT 127 + +/* Reason codes. */ +#define X509_R_BAD_X509_FILETYPE 100 +#define X509_R_BASE64_DECODE_ERROR 118 +#define X509_R_CANT_CHECK_DH_KEY 114 +#define X509_R_CERT_ALREADY_IN_HASH_TABLE 101 +#define X509_R_ERR_ASN1_LIB 102 +#define X509_R_INVALID_DIRECTORY 113 +#define X509_R_INVALID_FIELD_NAME 119 +#define X509_R_INVALID_TRUST 123 +#define X509_R_INVALID_VERSION 137 +#define X509_R_KEY_TYPE_MISMATCH 115 +#define X509_R_KEY_VALUES_MISMATCH 116 +#define X509_R_LOADING_CERT_DIR 103 +#define X509_R_LOADING_DEFAULTS 104 +#define X509_R_METHOD_NOT_SUPPORTED 124 +#define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 136 +#define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 105 +#define X509_R_PUBLIC_KEY_DECODE_ERROR 125 +#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126 +#define X509_R_SHOULD_RETRY 106 +#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 107 +#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 108 +#define X509_R_UNKNOWN_KEY_TYPE 117 +#define X509_R_UNKNOWN_NID 109 +#define X509_R_UNKNOWN_PURPOSE_ID 121 +#define X509_R_UNKNOWN_TRUST_ID 120 +#define X509_R_UNSUPPORTED_ALGORITHM 111 +#define X509_R_WRONG_LOOKUP_TYPE 112 +#define X509_R_WRONG_TYPE 122 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h new file mode 100644 index 0000000..1aa29ab --- /dev/null +++ b/include/openssl/x509_vfy.h @@ -0,0 +1,477 @@ +/* $OpenBSD: x509_vfy.h,v 1.64 2023/05/28 05:25:24 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_X509_H +#include +/* openssl/x509.h ends up #include-ing this file at about the only + * appropriate moment. */ +#endif + +#ifndef HEADER_X509_VFY_H +#define HEADER_X509_VFY_H + +#include + +#ifndef OPENSSL_NO_LHASH +#include +#endif +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL_CTX -> X509_STORE + * -> X509_LOOKUP + * ->X509_LOOKUP_METHOD + * -> X509_LOOKUP + * ->X509_LOOKUP_METHOD + * + * SSL -> X509_STORE_CTX + * ->X509_STORE + * + * The X509_STORE holds the tables etc for verification stuff. + * A X509_STORE_CTX is used while validating a single certificate. + * The X509_STORE has X509_LOOKUPs for looking up certs. + * The X509_STORE then calls a function to actually verify the + * certificate chain. + */ + +typedef enum { + X509_LU_NONE, + X509_LU_X509, + X509_LU_CRL, +} X509_LOOKUP_TYPE; + + +DECLARE_STACK_OF(X509_LOOKUP) +DECLARE_STACK_OF(X509_OBJECT) +DECLARE_STACK_OF(X509_VERIFY_PARAM) + +/* XXX - unused in OpenSSL. Can we remove this? */ +typedef struct X509_VERIFY_PARAM_ID_st X509_VERIFY_PARAM_ID; + + +int X509_STORE_set_depth(X509_STORE *store, int depth); + +void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); + +#define X509_STORE_CTX_set_app_data(ctx,data) \ + X509_STORE_CTX_set_ex_data(ctx,0,data) +#define X509_STORE_CTX_get_app_data(ctx) \ + X509_STORE_CTX_get_ex_data(ctx,0) + +#define X509_L_FILE_LOAD 1 +#define X509_L_ADD_DIR 2 +#define X509_L_MEM 3 + +#define X509_LOOKUP_load_file(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_FILE_LOAD,(name),(long)(type),NULL) + +#define X509_LOOKUP_add_dir(x,name,type) \ + X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL) + +#define X509_LOOKUP_add_mem(x,iov,type) \ + X509_LOOKUP_ctrl((x),X509_L_MEM,(const char *)(iov),\ + (long)(type),NULL) + +#define X509_V_OK 0 +#define X509_V_ERR_UNSPECIFIED 1 +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2 +#define X509_V_ERR_UNABLE_TO_GET_CRL 3 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE 4 +#define X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE 5 +#define X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY 6 +#define X509_V_ERR_CERT_SIGNATURE_FAILURE 7 +#define X509_V_ERR_CRL_SIGNATURE_FAILURE 8 +#define X509_V_ERR_CERT_NOT_YET_VALID 9 +#define X509_V_ERR_CERT_HAS_EXPIRED 10 +#define X509_V_ERR_CRL_NOT_YET_VALID 11 +#define X509_V_ERR_CRL_HAS_EXPIRED 12 +#define X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD 13 +#define X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD 14 +#define X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD 15 +#define X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD 16 +#define X509_V_ERR_OUT_OF_MEM 17 +#define X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18 +#define X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19 +#define X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20 +#define X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21 +#define X509_V_ERR_CERT_CHAIN_TOO_LONG 22 +#define X509_V_ERR_CERT_REVOKED 23 +#define X509_V_ERR_INVALID_CA 24 +#define X509_V_ERR_PATH_LENGTH_EXCEEDED 25 +#define X509_V_ERR_INVALID_PURPOSE 26 +#define X509_V_ERR_CERT_UNTRUSTED 27 +#define X509_V_ERR_CERT_REJECTED 28 +/* These are 'informational' when looking for issuer cert */ +#define X509_V_ERR_SUBJECT_ISSUER_MISMATCH 29 +#define X509_V_ERR_AKID_SKID_MISMATCH 30 +#define X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH 31 +#define X509_V_ERR_KEYUSAGE_NO_CERTSIGN 32 + +#define X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER 33 +#define X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION 34 +#define X509_V_ERR_KEYUSAGE_NO_CRL_SIGN 35 +#define X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION 36 +#define X509_V_ERR_INVALID_NON_CA 37 +#define X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED 38 +#define X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE 39 +#define X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED 40 + +#define X509_V_ERR_INVALID_EXTENSION 41 +#define X509_V_ERR_INVALID_POLICY_EXTENSION 42 +#define X509_V_ERR_NO_EXPLICIT_POLICY 43 +#define X509_V_ERR_DIFFERENT_CRL_SCOPE 44 +#define X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE 45 + +#define X509_V_ERR_UNNESTED_RESOURCE 46 + +#define X509_V_ERR_PERMITTED_VIOLATION 47 +#define X509_V_ERR_EXCLUDED_VIOLATION 48 +#define X509_V_ERR_SUBTREE_MINMAX 49 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51 +#define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52 +#define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53 +#define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54 + +/* The application is not happy */ +#define X509_V_ERR_APPLICATION_VERIFICATION 50 + +/* Host, email and IP check errors */ +#define X509_V_ERR_HOSTNAME_MISMATCH 62 +#define X509_V_ERR_EMAIL_MISMATCH 63 +#define X509_V_ERR_IP_ADDRESS_MISMATCH 64 + +/* Caller error */ +#define X509_V_ERR_INVALID_CALL 65 +/* Issuer lookup error */ +#define X509_V_ERR_STORE_LOOKUP 66 + +/* Security level errors */ +#define X509_V_ERR_EE_KEY_TOO_SMALL 67 +#define X509_V_ERR_CA_KEY_TOO_SMALL 68 +#define X509_V_ERR_CA_MD_TOO_WEAK 69 + +/* Certificate verify flags */ + +/* Deprecated in 1.1.0, has no effect. Various FFI bindings still expose it. */ +#define X509_V_FLAG_CB_ISSUER_CHECK 0x0 +/* Use check time instead of current time */ +#define X509_V_FLAG_USE_CHECK_TIME 0x2 +/* Lookup CRLs */ +#define X509_V_FLAG_CRL_CHECK 0x4 +/* Lookup CRLs for whole chain */ +#define X509_V_FLAG_CRL_CHECK_ALL 0x8 +/* Ignore unhandled critical extensions */ +#define X509_V_FLAG_IGNORE_CRITICAL 0x10 +/* Disable workarounds for broken certificates */ +#define X509_V_FLAG_X509_STRICT 0x20 +/* Enable proxy certificate validation */ +#define X509_V_FLAG_ALLOW_PROXY_CERTS 0x40 +/* Does nothing as its functionality has been enabled by default */ +#define X509_V_FLAG_POLICY_CHECK 0x80 +/* Policy variable require-explicit-policy */ +#define X509_V_FLAG_EXPLICIT_POLICY 0x100 +/* Policy variable inhibit-any-policy */ +#define X509_V_FLAG_INHIBIT_ANY 0x200 +/* Policy variable inhibit-policy-mapping */ +#define X509_V_FLAG_INHIBIT_MAP 0x400 +/* Notify callback that policy is OK */ +#define X509_V_FLAG_NOTIFY_POLICY 0x800 +/* Extended CRL features such as indirect CRLs, alternate CRL signing keys */ +#define X509_V_FLAG_EXTENDED_CRL_SUPPORT 0x1000 +/* Delta CRL support */ +#define X509_V_FLAG_USE_DELTAS 0x2000 +/* Check selfsigned CA signature */ +#define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* Use trusted store first */ +#define X509_V_FLAG_TRUSTED_FIRST 0x8000 +/* Allow partial chains if at least one certificate is in trusted store */ +#define X509_V_FLAG_PARTIAL_CHAIN 0x80000 + +/* If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag + * will force the behaviour to match that of previous versions. */ +#define X509_V_FLAG_NO_ALT_CHAINS 0x100000 + +/* Do not check certificate or CRL validity against current time. */ +#define X509_V_FLAG_NO_CHECK_TIME 0x200000 + +/* Force the use of the legacy certificate verification */ +#define X509_V_FLAG_LEGACY_VERIFY 0x400000 + +#define X509_VP_FLAG_DEFAULT 0x1 +#define X509_VP_FLAG_OVERWRITE 0x2 +#define X509_VP_FLAG_RESET_FLAGS 0x4 +#define X509_VP_FLAG_LOCKED 0x8 +#define X509_VP_FLAG_ONCE 0x10 + +/* + * Obsolete internal use: mask of policy related options. + * This should really go away. + */ +#define X509_V_FLAG_POLICY_MASK (X509_V_FLAG_POLICY_CHECK \ + | X509_V_FLAG_EXPLICIT_POLICY \ + | X509_V_FLAG_INHIBIT_ANY \ + | X509_V_FLAG_INHIBIT_MAP) + +X509_OBJECT *X509_OBJECT_new(void); +void X509_OBJECT_free(X509_OBJECT *a); +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type, + X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, + X509_LOOKUP_TYPE type, X509_NAME *name); +X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x); +int X509_OBJECT_up_ref_count(X509_OBJECT *a); +X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a); +X509 *X509_OBJECT_get0_X509(const X509_OBJECT *xo); +X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *xo); + +X509_STORE *X509_STORE_new(void); +void X509_STORE_free(X509_STORE *v); +int X509_STORE_up_ref(X509_STORE *x); +#define X509_STORE_get1_certs X509_STORE_CTX_get1_certs +#define X509_STORE_get1_crls X509_STORE_CTX_get1_crls +STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *st, X509_NAME *nm); +STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *xs); +void *X509_STORE_get_ex_data(X509_STORE *xs, int idx); +int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data); + +#define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ + CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \ + (newf), (dupf), (freef)) + +int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); +int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); +int X509_STORE_set_trust(X509_STORE *ctx, int trust); +int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm); +X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx); + +typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *); + +X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *); + +void X509_STORE_set_verify_cb(X509_STORE *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)); +#define X509_STORE_set_verify_cb_func(ctx, func) \ + X509_STORE_set_verify_cb((ctx), (func)) + +typedef int (*X509_STORE_CTX_check_issued_fn)(X509_STORE_CTX *ctx, + X509 *subject, X509 *issuer); + +X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *store); +void X509_STORE_set_check_issued(X509_STORE *store, + X509_STORE_CTX_check_issued_fn check_issued); +X509_STORE_CTX_check_issued_fn + X509_STORE_CTX_get_check_issued(X509_STORE_CTX *ctx); + +X509_STORE_CTX *X509_STORE_CTX_new(void); + +int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x); + +void X509_STORE_CTX_free(X509_STORE_CTX *ctx); +int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, + X509 *x509, STACK_OF(X509) *chain); +X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *xs); +X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *xs); +STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_untrusted(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx); + +X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); + +X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void); +X509_LOOKUP_METHOD *X509_LOOKUP_file(void); +X509_LOOKUP_METHOD *X509_LOOKUP_mem(void); + +int X509_STORE_add_cert(X509_STORE *ctx, X509 *x); +int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); + +int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +#define X509_STORE_get_by_subject X509_STORE_CTX_get_by_subject +X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs, + X509_LOOKUP_TYPE type, X509_NAME *name); + +int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, + long argl, char **ret); + +int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type); +int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type); + + +X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method); +void X509_LOOKUP_free(X509_LOOKUP *ctx); +int X509_LOOKUP_init(X509_LOOKUP *ctx); +int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, X509_OBJECT *ret); +int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + X509_NAME *name, ASN1_INTEGER *serial, X509_OBJECT *ret); +int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const unsigned char *bytes, int len, X509_OBJECT *ret); +int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type, + const char *str, int len, X509_OBJECT *ret); +int X509_LOOKUP_shutdown(X509_LOOKUP *ctx); + +int X509_STORE_load_locations(X509_STORE *ctx, + const char *file, const char *dir); +int X509_STORE_load_mem(X509_STORE *ctx, void *buf, int len); +int X509_STORE_set_default_paths(X509_STORE *ctx); + +int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func); +int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx,int idx,void *data); +void * X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx,int idx); +int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx,int s); +int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_error_depth(X509_STORE_CTX *ctx, int depth); +X509 * X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_current_cert(X509_STORE_CTX *ctx, X509 *x); +X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx); +X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx); +X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); +STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x); +void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk); +void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk); +int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose); +int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust); +int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, + int purpose, int trust); +void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags); +void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, + time_t t); +void X509_STORE_CTX_set0_verified_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk); +int (*X509_STORE_CTX_get_verify(X509_STORE_CTX *ctx))(X509_STORE_CTX *); +void X509_STORE_CTX_set_verify(X509_STORE_CTX *ctx, + int (*verify)(X509_STORE_CTX *)); +int (*X509_STORE_CTX_get_verify_cb(X509_STORE_CTX *ctx))(int, X509_STORE_CTX *); +void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx, + int (*verify_cb)(int, X509_STORE_CTX *)); + +typedef int (*X509_STORE_CTX_verify_fn)(X509_STORE_CTX *); + +void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify); +X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx); +#define X509_STORE_set_verify_func(ctx, func) \ + X509_STORE_set_verify((ctx), (func)) + +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx); + +X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx); +void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param); +int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name); + +/* X509_VERIFY_PARAM functions */ + +X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void); +void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, + const X509_VERIFY_PARAM *from); +int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name); +int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags); +int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, + unsigned long flags); +unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose); +int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust); +void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth); +void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level); +time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param); +void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t); +int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, + ASN1_OBJECT *policy); +int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, + STACK_OF(ASN1_OBJECT) *policies); +int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param, const char *name, + size_t namelen); +int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param, const char *name, + size_t namelen); +void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, + unsigned int flags); +char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param); +int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email, + size_t emaillen); +int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, + size_t iplen); +int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc); +const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id); +int X509_VERIFY_PARAM_get_count(void); + +int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param); +const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name); +void X509_VERIFY_PARAM_table_cleanup(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h new file mode 100644 index 0000000..f867cc3 --- /dev/null +++ b/include/openssl/x509v3.h @@ -0,0 +1,1119 @@ +/* $OpenBSD: x509v3.h,v 1.25 2023/06/25 18:15:21 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project 1999. + */ +/* ==================================================================== + * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#ifndef HEADER_X509V3_H +#define HEADER_X509V3_H + +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward reference */ +struct v3_ext_method; +struct v3_ext_ctx; + +/* Useful typedefs */ + +typedef void * (*X509V3_EXT_NEW)(void); +typedef void (*X509V3_EXT_FREE)(void *); +typedef void * (*X509V3_EXT_D2I)(void *, const unsigned char ** , long); +typedef int (*X509V3_EXT_I2D)(void *, unsigned char **); +typedef STACK_OF(CONF_VALUE) * + (*X509V3_EXT_I2V)(const struct v3_ext_method *method, void *ext, + STACK_OF(CONF_VALUE) *extlist); +typedef void * (*X509V3_EXT_V2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, + STACK_OF(CONF_VALUE) *values); +typedef char * (*X509V3_EXT_I2S)(const struct v3_ext_method *method, void *ext); +typedef void * (*X509V3_EXT_S2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); +typedef int (*X509V3_EXT_I2R)(const struct v3_ext_method *method, void *ext, + BIO *out, int indent); +typedef void * (*X509V3_EXT_R2I)(const struct v3_ext_method *method, + struct v3_ext_ctx *ctx, const char *str); + +/* V3 extension structure */ + +struct v3_ext_method { + int ext_nid; + int ext_flags; + /* If this is set the following four fields are ignored */ + ASN1_ITEM_EXP *it; + /* Old style ASN1 calls */ + X509V3_EXT_NEW ext_new; + X509V3_EXT_FREE ext_free; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2D i2d; + + /* The following pair is used for string extensions */ + X509V3_EXT_I2S i2s; + X509V3_EXT_S2I s2i; + + /* The following pair is used for multi-valued extensions */ + X509V3_EXT_I2V i2v; + X509V3_EXT_V2I v2i; + + /* The following are used for raw extensions */ + X509V3_EXT_I2R i2r; + X509V3_EXT_R2I r2i; + + void *usr_data; /* Any extension specific data */ +}; + +typedef struct X509V3_CONF_METHOD_st { + char *(*get_string)(void *db, const char *section, const char *value); + STACK_OF(CONF_VALUE) *(*get_section)(void *db, const char *section); + void (*free_string)(void *db, char *string); + void (*free_section)(void *db, STACK_OF(CONF_VALUE) *section); +} X509V3_CONF_METHOD; + +/* Context specific info */ +struct v3_ext_ctx { + #define CTX_TEST 0x1 + int flags; + X509 *issuer_cert; + X509 *subject_cert; + X509_REQ *subject_req; + X509_CRL *crl; + X509V3_CONF_METHOD *db_meth; + void *db; + /* Maybe more here */ +}; + +typedef struct v3_ext_method X509V3_EXT_METHOD; + +DECLARE_STACK_OF(X509V3_EXT_METHOD) + +/* ext_flags values */ +#define X509V3_EXT_DYNAMIC 0x1 +#define X509V3_EXT_CTX_DEP 0x2 +#define X509V3_EXT_MULTILINE 0x4 + +typedef BIT_STRING_BITNAME ENUMERATED_NAMES; + +typedef struct BASIC_CONSTRAINTS_st { + int ca; + ASN1_INTEGER *pathlen; +} BASIC_CONSTRAINTS; + + +typedef struct PKEY_USAGE_PERIOD_st { + ASN1_GENERALIZEDTIME *notBefore; + ASN1_GENERALIZEDTIME *notAfter; +} PKEY_USAGE_PERIOD; + +typedef struct otherName_st { + ASN1_OBJECT *type_id; + ASN1_TYPE *value; +} OTHERNAME; + +typedef struct EDIPartyName_st { + ASN1_STRING *nameAssigner; + ASN1_STRING *partyName; +} EDIPARTYNAME; + +typedef struct GENERAL_NAME_st { + + #define GEN_OTHERNAME 0 + #define GEN_EMAIL 1 + #define GEN_DNS 2 + #define GEN_X400 3 + #define GEN_DIRNAME 4 + #define GEN_EDIPARTY 5 + #define GEN_URI 6 + #define GEN_IPADD 7 + #define GEN_RID 8 + + int type; + union { + char *ptr; + OTHERNAME *otherName; /* otherName */ + ASN1_IA5STRING *rfc822Name; + ASN1_IA5STRING *dNSName; + ASN1_STRING *x400Address; + X509_NAME *directoryName; + EDIPARTYNAME *ediPartyName; + ASN1_IA5STRING *uniformResourceIdentifier; + ASN1_OCTET_STRING *iPAddress; + ASN1_OBJECT *registeredID; + + /* Old names */ + ASN1_OCTET_STRING *ip; /* iPAddress */ + X509_NAME *dirn; /* dirn */ + ASN1_IA5STRING *ia5; /* rfc822Name, dNSName, uniformResourceIdentifier */ + ASN1_OBJECT *rid; /* registeredID */ + } d; +} GENERAL_NAME; + +typedef struct ACCESS_DESCRIPTION_st { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} ACCESS_DESCRIPTION; + +typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; + +typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE; + +DECLARE_STACK_OF(GENERAL_NAME) + +typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES; +DECLARE_STACK_OF(GENERAL_NAMES) + +DECLARE_STACK_OF(ACCESS_DESCRIPTION) + +typedef struct DIST_POINT_NAME_st { + int type; + union { + GENERAL_NAMES *fullname; + STACK_OF(X509_NAME_ENTRY) *relativename; + } name; + /* If relativename then this contains the full distribution point name */ + X509_NAME *dpname; +} DIST_POINT_NAME; +/* All existing reasons */ +#define CRLDP_ALL_REASONS 0x807f + +#define CRL_REASON_NONE -1 +#define CRL_REASON_UNSPECIFIED 0 +#define CRL_REASON_KEY_COMPROMISE 1 +#define CRL_REASON_CA_COMPROMISE 2 +#define CRL_REASON_AFFILIATION_CHANGED 3 +#define CRL_REASON_SUPERSEDED 4 +#define CRL_REASON_CESSATION_OF_OPERATION 5 +#define CRL_REASON_CERTIFICATE_HOLD 6 +#define CRL_REASON_REMOVE_FROM_CRL 8 +#define CRL_REASON_PRIVILEGE_WITHDRAWN 9 +#define CRL_REASON_AA_COMPROMISE 10 + +struct DIST_POINT_st { + DIST_POINT_NAME *distpoint; + ASN1_BIT_STRING *reasons; + GENERAL_NAMES *CRLissuer; + int dp_reasons; +}; + +typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS; + +DECLARE_STACK_OF(DIST_POINT) + +struct AUTHORITY_KEYID_st { + ASN1_OCTET_STRING *keyid; + GENERAL_NAMES *issuer; + ASN1_INTEGER *serial; +}; + +typedef struct NOTICEREF_st { + ASN1_STRING *organization; + STACK_OF(ASN1_INTEGER) *noticenos; +} NOTICEREF; + +typedef struct USERNOTICE_st { + NOTICEREF *noticeref; + ASN1_STRING *exptext; +} USERNOTICE; + +typedef struct POLICYQUALINFO_st { + ASN1_OBJECT *pqualid; + union { + ASN1_IA5STRING *cpsuri; + USERNOTICE *usernotice; + ASN1_TYPE *other; + } d; +} POLICYQUALINFO; + +DECLARE_STACK_OF(POLICYQUALINFO) + +typedef struct POLICYINFO_st { + ASN1_OBJECT *policyid; + STACK_OF(POLICYQUALINFO) *qualifiers; +} POLICYINFO; + +typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES; + +DECLARE_STACK_OF(POLICYINFO) + +typedef struct POLICY_MAPPING_st { + ASN1_OBJECT *issuerDomainPolicy; + ASN1_OBJECT *subjectDomainPolicy; +} POLICY_MAPPING; + +DECLARE_STACK_OF(POLICY_MAPPING) + +typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS; + +typedef struct GENERAL_SUBTREE_st { + GENERAL_NAME *base; + ASN1_INTEGER *minimum; + ASN1_INTEGER *maximum; +} GENERAL_SUBTREE; + +DECLARE_STACK_OF(GENERAL_SUBTREE) + +struct NAME_CONSTRAINTS_st { + STACK_OF(GENERAL_SUBTREE) *permittedSubtrees; + STACK_OF(GENERAL_SUBTREE) *excludedSubtrees; +}; + +typedef struct POLICY_CONSTRAINTS_st { + ASN1_INTEGER *requireExplicitPolicy; + ASN1_INTEGER *inhibitPolicyMapping; +} POLICY_CONSTRAINTS; + +struct ISSUING_DIST_POINT_st { + DIST_POINT_NAME *distpoint; + int onlyuser; + int onlyCA; + ASN1_BIT_STRING *onlysomereasons; + int indirectCRL; + int onlyattr; +}; + +/* Values in idp_flags field */ +/* IDP present */ +#define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +#define IDP_INVALID 0x2 +/* onlyuser true */ +#define IDP_ONLYUSER 0x4 +/* onlyCA true */ +#define IDP_ONLYCA 0x8 +/* onlyattr true */ +#define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +#define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +#define IDP_REASONS 0x40 + +#define X509V3_conf_err(val) ERR_asprintf_error_data( \ + "section:%s,name:%s,value:%s", val->section, \ + val->name, val->value); + +#define X509V3_set_ctx_test(ctx) \ + X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST) +#define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL; + +#define EXT_BITSTRING(nid, table) { nid, 0, &ASN1_BIT_STRING_it, \ + 0,0,0,0, \ + 0,0, \ + (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \ + (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \ + NULL, NULL, \ + table} + +#define EXT_IA5STRING(nid) { nid, 0, &ASN1_IA5STRING_it, \ + 0,0,0,0, \ + (X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \ + (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \ + 0,0,0,0, \ + NULL} + +#define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + + +/* X509_PURPOSE stuff */ + +#define EXFLAG_BCONS 0x0001 +#define EXFLAG_KUSAGE 0x0002 +#define EXFLAG_XKUSAGE 0x0004 +#define EXFLAG_NSCERT 0x0008 + +#define EXFLAG_CA 0x0010 +#define EXFLAG_SI 0x0020 /* Self issued. */ +#define EXFLAG_V1 0x0040 +#define EXFLAG_INVALID 0x0080 +#define EXFLAG_SET 0x0100 +#define EXFLAG_CRITICAL 0x0200 +#if !defined(LIBRESSL_INTERNAL) +#define EXFLAG_PROXY 0x0400 +#endif +#define EXFLAG_INVALID_POLICY 0x0800 +#define EXFLAG_FRESHEST 0x1000 +#define EXFLAG_SS 0x2000 /* Self signed. */ + +#define KU_DIGITAL_SIGNATURE 0x0080 +#define KU_NON_REPUDIATION 0x0040 +#define KU_KEY_ENCIPHERMENT 0x0020 +#define KU_DATA_ENCIPHERMENT 0x0010 +#define KU_KEY_AGREEMENT 0x0008 +#define KU_KEY_CERT_SIGN 0x0004 +#define KU_CRL_SIGN 0x0002 +#define KU_ENCIPHER_ONLY 0x0001 +#define KU_DECIPHER_ONLY 0x8000 + +#define NS_SSL_CLIENT 0x80 +#define NS_SSL_SERVER 0x40 +#define NS_SMIME 0x20 +#define NS_OBJSIGN 0x10 +#define NS_SSL_CA 0x04 +#define NS_SMIME_CA 0x02 +#define NS_OBJSIGN_CA 0x01 +#define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA) + +#define XKU_SSL_SERVER 0x1 +#define XKU_SSL_CLIENT 0x2 +#define XKU_SMIME 0x4 +#define XKU_CODE_SIGN 0x8 +#define XKU_SGC 0x10 +#define XKU_OCSP_SIGN 0x20 +#define XKU_TIMESTAMP 0x40 +#define XKU_DVCS 0x80 +#define XKU_ANYEKU 0x100 + +#define X509_PURPOSE_DYNAMIC 0x1 +#define X509_PURPOSE_DYNAMIC_NAME 0x2 + +typedef struct x509_purpose_st { + int purpose; + int trust; /* Default trust ID */ + int flags; + int (*check_purpose)(const struct x509_purpose_st *, const X509 *, int); + char *name; + char *sname; + void *usr_data; +} X509_PURPOSE; + +#define X509_PURPOSE_SSL_CLIENT 1 +#define X509_PURPOSE_SSL_SERVER 2 +#define X509_PURPOSE_NS_SSL_SERVER 3 +#define X509_PURPOSE_SMIME_SIGN 4 +#define X509_PURPOSE_SMIME_ENCRYPT 5 +#define X509_PURPOSE_CRL_SIGN 6 +#define X509_PURPOSE_ANY 7 +#define X509_PURPOSE_OCSP_HELPER 8 +#define X509_PURPOSE_TIMESTAMP_SIGN 9 + +#define X509_PURPOSE_MIN 1 +#define X509_PURPOSE_MAX 9 + +/* Flags for X509V3_EXT_print() */ + +#define X509V3_EXT_UNKNOWN_MASK (0xfL << 16) +/* Return error for unknown extensions */ +#define X509V3_EXT_DEFAULT 0 +/* Print error for unknown extensions */ +#define X509V3_EXT_ERROR_UNKNOWN (1L << 16) +/* ASN1 parse unknown extensions */ +#define X509V3_EXT_PARSE_UNKNOWN (2L << 16) +/* BIO_dump unknown extensions */ +#define X509V3_EXT_DUMP_UNKNOWN (3L << 16) + +/* Flags for X509V3_add1_i2d */ + +#define X509V3_ADD_OP_MASK 0xfL +#define X509V3_ADD_DEFAULT 0L +#define X509V3_ADD_APPEND 1L +#define X509V3_ADD_REPLACE 2L +#define X509V3_ADD_REPLACE_EXISTING 3L +#define X509V3_ADD_KEEP_EXISTING 4L +#define X509V3_ADD_DELETE 5L +#define X509V3_ADD_SILENT 0x10 + +DECLARE_STACK_OF(X509_PURPOSE) + +BASIC_CONSTRAINTS *BASIC_CONSTRAINTS_new(void); +void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a); +BASIC_CONSTRAINTS *d2i_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS **a, const unsigned char **in, long len); +int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *a, unsigned char **out); +extern const ASN1_ITEM BASIC_CONSTRAINTS_it; + +AUTHORITY_KEYID *AUTHORITY_KEYID_new(void); +void AUTHORITY_KEYID_free(AUTHORITY_KEYID *a); +AUTHORITY_KEYID *d2i_AUTHORITY_KEYID(AUTHORITY_KEYID **a, const unsigned char **in, long len); +int i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *a, unsigned char **out); +extern const ASN1_ITEM AUTHORITY_KEYID_it; + +PKEY_USAGE_PERIOD *PKEY_USAGE_PERIOD_new(void); +void PKEY_USAGE_PERIOD_free(PKEY_USAGE_PERIOD *a); +PKEY_USAGE_PERIOD *d2i_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD **a, const unsigned char **in, long len); +int i2d_PKEY_USAGE_PERIOD(PKEY_USAGE_PERIOD *a, unsigned char **out); +extern const ASN1_ITEM PKEY_USAGE_PERIOD_it; + +GENERAL_NAME *GENERAL_NAME_new(void); +void GENERAL_NAME_free(GENERAL_NAME *a); +GENERAL_NAME *d2i_GENERAL_NAME(GENERAL_NAME **a, const unsigned char **in, long len); +int i2d_GENERAL_NAME(GENERAL_NAME *a, unsigned char **out); +extern const ASN1_ITEM GENERAL_NAME_it; +GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a); +int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b); + + + +ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); +STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method, + ASN1_BIT_STRING *bits, + STACK_OF(CONF_VALUE) *extlist); + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret); +int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen); + +GENERAL_NAMES *GENERAL_NAMES_new(void); +void GENERAL_NAMES_free(GENERAL_NAMES *a); +GENERAL_NAMES *d2i_GENERAL_NAMES(GENERAL_NAMES **a, const unsigned char **in, long len); +int i2d_GENERAL_NAMES(GENERAL_NAMES *a, unsigned char **out); +extern const ASN1_ITEM GENERAL_NAMES_it; + +STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, + GENERAL_NAMES *gen, STACK_OF(CONF_VALUE) *extlist); +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); + +OTHERNAME *OTHERNAME_new(void); +void OTHERNAME_free(OTHERNAME *a); +OTHERNAME *d2i_OTHERNAME(OTHERNAME **a, const unsigned char **in, long len); +int i2d_OTHERNAME(OTHERNAME *a, unsigned char **out); +extern const ASN1_ITEM OTHERNAME_it; +EDIPARTYNAME *EDIPARTYNAME_new(void); +void EDIPARTYNAME_free(EDIPARTYNAME *a); +EDIPARTYNAME *d2i_EDIPARTYNAME(EDIPARTYNAME **a, const unsigned char **in, long len); +int i2d_EDIPARTYNAME(EDIPARTYNAME *a, unsigned char **out); +extern const ASN1_ITEM EDIPARTYNAME_it; +int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b); +void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value); +void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype); +int GENERAL_NAME_set0_othername(GENERAL_NAME *gen, + ASN1_OBJECT *oid, ASN1_TYPE *value); +int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, + ASN1_OBJECT **poid, ASN1_TYPE **pvalue); + +char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + const ASN1_OCTET_STRING *ia5); +ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, const char *str); + +EXTENDED_KEY_USAGE *EXTENDED_KEY_USAGE_new(void); +void EXTENDED_KEY_USAGE_free(EXTENDED_KEY_USAGE *a); +EXTENDED_KEY_USAGE *d2i_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE **a, const unsigned char **in, long len); +int i2d_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE *a, unsigned char **out); +extern const ASN1_ITEM EXTENDED_KEY_USAGE_it; +int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION* a); + +CERTIFICATEPOLICIES *CERTIFICATEPOLICIES_new(void); +void CERTIFICATEPOLICIES_free(CERTIFICATEPOLICIES *a); +CERTIFICATEPOLICIES *d2i_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES **a, const unsigned char **in, long len); +int i2d_CERTIFICATEPOLICIES(CERTIFICATEPOLICIES *a, unsigned char **out); +extern const ASN1_ITEM CERTIFICATEPOLICIES_it; +POLICYINFO *POLICYINFO_new(void); +void POLICYINFO_free(POLICYINFO *a); +POLICYINFO *d2i_POLICYINFO(POLICYINFO **a, const unsigned char **in, long len); +int i2d_POLICYINFO(POLICYINFO *a, unsigned char **out); +extern const ASN1_ITEM POLICYINFO_it; +POLICYQUALINFO *POLICYQUALINFO_new(void); +void POLICYQUALINFO_free(POLICYQUALINFO *a); +POLICYQUALINFO *d2i_POLICYQUALINFO(POLICYQUALINFO **a, const unsigned char **in, long len); +int i2d_POLICYQUALINFO(POLICYQUALINFO *a, unsigned char **out); +extern const ASN1_ITEM POLICYQUALINFO_it; +USERNOTICE *USERNOTICE_new(void); +void USERNOTICE_free(USERNOTICE *a); +USERNOTICE *d2i_USERNOTICE(USERNOTICE **a, const unsigned char **in, long len); +int i2d_USERNOTICE(USERNOTICE *a, unsigned char **out); +extern const ASN1_ITEM USERNOTICE_it; +NOTICEREF *NOTICEREF_new(void); +void NOTICEREF_free(NOTICEREF *a); +NOTICEREF *d2i_NOTICEREF(NOTICEREF **a, const unsigned char **in, long len); +int i2d_NOTICEREF(NOTICEREF *a, unsigned char **out); +extern const ASN1_ITEM NOTICEREF_it; + +CRL_DIST_POINTS *CRL_DIST_POINTS_new(void); +void CRL_DIST_POINTS_free(CRL_DIST_POINTS *a); +CRL_DIST_POINTS *d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len); +int i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out); +extern const ASN1_ITEM CRL_DIST_POINTS_it; +DIST_POINT *DIST_POINT_new(void); +void DIST_POINT_free(DIST_POINT *a); +DIST_POINT *d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len); +int i2d_DIST_POINT(DIST_POINT *a, unsigned char **out); +extern const ASN1_ITEM DIST_POINT_it; +DIST_POINT_NAME *DIST_POINT_NAME_new(void); +void DIST_POINT_NAME_free(DIST_POINT_NAME *a); +DIST_POINT_NAME *d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, const unsigned char **in, long len); +int i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out); +extern const ASN1_ITEM DIST_POINT_NAME_it; +ISSUING_DIST_POINT *ISSUING_DIST_POINT_new(void); +void ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a); +ISSUING_DIST_POINT *d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len); +int i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out); +extern const ASN1_ITEM ISSUING_DIST_POINT_it; + +int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname); + +int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc); + +ACCESS_DESCRIPTION *ACCESS_DESCRIPTION_new(void); +void ACCESS_DESCRIPTION_free(ACCESS_DESCRIPTION *a); +ACCESS_DESCRIPTION *d2i_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION **a, const unsigned char **in, long len); +int i2d_ACCESS_DESCRIPTION(ACCESS_DESCRIPTION *a, unsigned char **out); +extern const ASN1_ITEM ACCESS_DESCRIPTION_it; +AUTHORITY_INFO_ACCESS *AUTHORITY_INFO_ACCESS_new(void); +void AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a); +AUTHORITY_INFO_ACCESS *d2i_AUTHORITY_INFO_ACCESS(AUTHORITY_INFO_ACCESS **a, const unsigned char **in, long len); +int i2d_AUTHORITY_INFO_ACCESS(AUTHORITY_INFO_ACCESS *a, unsigned char **out); +extern const ASN1_ITEM AUTHORITY_INFO_ACCESS_it; + +extern const ASN1_ITEM POLICY_MAPPING_it; +POLICY_MAPPING *POLICY_MAPPING_new(void); +void POLICY_MAPPING_free(POLICY_MAPPING *a); +extern const ASN1_ITEM POLICY_MAPPINGS_it; + +extern const ASN1_ITEM GENERAL_SUBTREE_it; +GENERAL_SUBTREE *GENERAL_SUBTREE_new(void); +void GENERAL_SUBTREE_free(GENERAL_SUBTREE *a); + +extern const ASN1_ITEM NAME_CONSTRAINTS_it; +NAME_CONSTRAINTS *NAME_CONSTRAINTS_new(void); +void NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *a); + +POLICY_CONSTRAINTS *POLICY_CONSTRAINTS_new(void); +void POLICY_CONSTRAINTS_free(POLICY_CONSTRAINTS *a); +extern const ASN1_ITEM POLICY_CONSTRAINTS_it; + +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + int gen_type, const char *value, int is_nc); + +#ifdef HEADER_CONF_H +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf); +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc); +void X509V3_conf_free(CONF_VALUE *val); + +X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, + const char *value); +X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name, + const char *value); +int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section, + STACK_OF(X509_EXTENSION) **sk); +int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509 *cert); +int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_REQ *req); +int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section, + X509_CRL *crl); + +X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + int ext_nid, const char *value); +X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *name, const char *value); +int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509 *cert); +int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_REQ *req); +int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, + const char *section, X509_CRL *crl); + +int X509V3_add_value_bool_nf(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool); +int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint); +void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf); +void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash); +#endif + +char *X509V3_get_string(X509V3_CTX *ctx, const char *name, + const char *section); +STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section); +void X509V3_string_free(X509V3_CTX *ctx, char *str); +void X509V3_section_free( X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section); +void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject, + X509_REQ *req, X509_CRL *crl, int flags); + +int X509V3_add_value(const char *name, const char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_uchar(const char *name, const unsigned char *value, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_bool(const char *name, int asn1_bool, + STACK_OF(CONF_VALUE) **extlist); +int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, + STACK_OF(CONF_VALUE) **extlist); +char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint); +ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value); +char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint); +char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth, + const ASN1_ENUMERATED *aint); +int X509V3_EXT_add(X509V3_EXT_METHOD *ext); +int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist); +int X509V3_EXT_add_alias(int nid_to, int nid_from); +void X509V3_EXT_cleanup(void); + +const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext); +const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid); +int X509V3_add_standard_extensions(void); +STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line); +void *X509V3_EXT_d2i(X509_EXTENSION *ext); +void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit, + int *idx); + + +X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc); +int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value, int crit, unsigned long flags); + +char *hex_to_string(const unsigned char *buffer, long len); +unsigned char *string_to_hex(const char *str, long *len); + +void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, + int ml); +int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent); +int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent); + +int X509V3_extensions_print(BIO *out, const char *title, + const STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent); + +int X509_check_ca(X509 *x); +int X509_check_purpose(X509 *x, int id, int ca); +int X509_supported_extension(X509_EXTENSION *ex); +int X509_PURPOSE_set(int *p, int purpose); +int X509_check_issued(X509 *issuer, X509 *subject); +int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid); +int X509_PURPOSE_get_count(void); +X509_PURPOSE * X509_PURPOSE_get0(int idx); +int X509_PURPOSE_get_by_sname(const char *sname); +int X509_PURPOSE_get_by_id(int id); +int X509_PURPOSE_add(int id, int trust, int flags, + int (*ck)(const X509_PURPOSE *, const X509 *, int), + const char *name, const char *sname, void *arg); +char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp); +char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp); +int X509_PURPOSE_get_trust(const X509_PURPOSE *xp); +void X509_PURPOSE_cleanup(void); +int X509_PURPOSE_get_id(const X509_PURPOSE *); +uint32_t X509_get_extension_flags(X509 *x); +uint32_t X509_get_key_usage(X509 *x); +uint32_t X509_get_extended_key_usage(X509 *x); + +STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x); +STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x); +void X509_email_free(STACK_OF(OPENSSL_STRING) *sk); +STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x); + +/* Flags for X509_check_* functions */ +/* Always check subject name for host match even if subject alt names present */ +#define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1 +/* Disable wildcard matching for dnsName fields and common name. */ +#define X509_CHECK_FLAG_NO_WILDCARDS 0x2 +/* Wildcards must not match a partial label. */ +#define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4 +/* Allow (non-partial) wildcards to match multiple labels. */ +#define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8 +/* Constraint verifier subdomain patterns to match a single labels. */ +#define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10 +/* Disable checking the CN for a hostname, to support modern validation */ +#define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20 + +/* + * Match reference identifiers starting with "." to any sub-domain. + * This is a non-public flag, turned on implicitly when the subject + * reference identity is a DNS name. + */ +#define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 + +int X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername); +int X509_check_email(X509 *x, const char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, + unsigned int flags); +int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags); + +ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc); +ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc); +int a2i_ipadd(unsigned char *ipout, const char *ipasc); +int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, + unsigned long chtype); + +#ifndef OPENSSL_NO_RFC3779 +typedef struct ASRange_st { + ASN1_INTEGER *min; + ASN1_INTEGER *max; +} ASRange; + +#define ASIdOrRange_id 0 +#define ASIdOrRange_range 1 + +typedef struct ASIdOrRange_st { + int type; + union { + ASN1_INTEGER *id; + ASRange *range; + } u; +} ASIdOrRange; + +typedef STACK_OF(ASIdOrRange) ASIdOrRanges; +DECLARE_STACK_OF(ASIdOrRange) + +#define ASIdentifierChoice_inherit 0 +#define ASIdentifierChoice_asIdsOrRanges 1 + +typedef struct ASIdentifierChoice_st { + int type; + union { + ASN1_NULL *inherit; + ASIdOrRanges *asIdsOrRanges; + } u; +} ASIdentifierChoice; + +typedef struct ASIdentifiers_st { + ASIdentifierChoice *asnum; + ASIdentifierChoice *rdi; +} ASIdentifiers; + +ASRange *ASRange_new(void); +void ASRange_free(ASRange *a); +ASRange *d2i_ASRange(ASRange **a, const unsigned char **in, long len); +int i2d_ASRange(ASRange *a, unsigned char **out); +extern const ASN1_ITEM ASRange_it; + +ASIdOrRange *ASIdOrRange_new(void); +void ASIdOrRange_free(ASIdOrRange *a); +ASIdOrRange *d2i_ASIdOrRange(ASIdOrRange **a, const unsigned char **in, + long len); +int i2d_ASIdOrRange(ASIdOrRange *a, unsigned char **out); +extern const ASN1_ITEM ASIdOrRange_it; + +ASIdentifierChoice *ASIdentifierChoice_new(void); +void ASIdentifierChoice_free(ASIdentifierChoice *a); +ASIdentifierChoice *d2i_ASIdentifierChoice(ASIdentifierChoice **a, + const unsigned char **in, long len); +int i2d_ASIdentifierChoice(ASIdentifierChoice *a, unsigned char **out); +extern const ASN1_ITEM ASIdentifierChoice_it; + +ASIdentifiers *ASIdentifiers_new(void); +void ASIdentifiers_free(ASIdentifiers *a); +ASIdentifiers *d2i_ASIdentifiers(ASIdentifiers **a, const unsigned char **in, + long len); +int i2d_ASIdentifiers(ASIdentifiers *a, unsigned char **out); +extern const ASN1_ITEM ASIdentifiers_it; + +typedef struct IPAddressRange_st { + ASN1_BIT_STRING *min; + ASN1_BIT_STRING *max; +} IPAddressRange; + +#define IPAddressOrRange_addressPrefix 0 +#define IPAddressOrRange_addressRange 1 + +typedef struct IPAddressOrRange_st { + int type; + union { + ASN1_BIT_STRING *addressPrefix; + IPAddressRange *addressRange; + } u; +} IPAddressOrRange; + +typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges; +DECLARE_STACK_OF(IPAddressOrRange) + +#define IPAddressChoice_inherit 0 +#define IPAddressChoice_addressesOrRanges 1 + +typedef struct IPAddressChoice_st { + int type; + union { + ASN1_NULL *inherit; + IPAddressOrRanges *addressesOrRanges; + } u; +} IPAddressChoice; + +typedef struct IPAddressFamily_st { + ASN1_OCTET_STRING *addressFamily; + IPAddressChoice *ipAddressChoice; +} IPAddressFamily; + +typedef STACK_OF(IPAddressFamily) IPAddrBlocks; +DECLARE_STACK_OF(IPAddressFamily) + +IPAddressRange *IPAddressRange_new(void); +void IPAddressRange_free(IPAddressRange *a); +IPAddressRange *d2i_IPAddressRange(IPAddressRange **a, + const unsigned char **in, long len); +int i2d_IPAddressRange(IPAddressRange *a, unsigned char **out); +extern const ASN1_ITEM IPAddressRange_it; + +IPAddressOrRange *IPAddressOrRange_new(void); +void IPAddressOrRange_free(IPAddressOrRange *a); +IPAddressOrRange *d2i_IPAddressOrRange(IPAddressOrRange **a, + const unsigned char **in, long len); +int i2d_IPAddressOrRange(IPAddressOrRange *a, unsigned char **out); +extern const ASN1_ITEM IPAddressOrRange_it; + +IPAddressChoice *IPAddressChoice_new(void); +void IPAddressChoice_free(IPAddressChoice *a); +IPAddressChoice *d2i_IPAddressChoice(IPAddressChoice **a, + const unsigned char **in, long len); +int i2d_IPAddressChoice(IPAddressChoice *a, unsigned char **out); +extern const ASN1_ITEM IPAddressChoice_it; + +IPAddressFamily *IPAddressFamily_new(void); +void IPAddressFamily_free(IPAddressFamily *a); +IPAddressFamily *d2i_IPAddressFamily(IPAddressFamily **a, + const unsigned char **in, long len); +int i2d_IPAddressFamily(IPAddressFamily *a, unsigned char **out); +extern const ASN1_ITEM IPAddressFamily_it; + +/* + * API tag for elements of the ASIdentifer SEQUENCE. + */ +#define V3_ASID_ASNUM 0 +#define V3_ASID_RDI 1 + +/* + * AFI values, assigned by IANA. It'd be nice to make the AFI + * handling code totally generic, but there are too many little things + * that would need to be defined for other address families for it to + * be worth the trouble. + */ +#define IANA_AFI_IPV4 1 +#define IANA_AFI_IPV6 2 + +/* + * Utilities to construct and extract values from RFC3779 extensions, + * since some of the encodings (particularly for IP address prefixes + * and ranges) are a bit tedious to work with directly. + */ +int X509v3_asid_add_inherit(ASIdentifiers *asid, int which); +int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, + ASN1_INTEGER *min, ASN1_INTEGER *max); +int X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi); +int X509v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *a, const int prefixlen); +int X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi, + const unsigned *safi, unsigned char *min, unsigned char *max); +unsigned X509v3_addr_get_afi(const IPAddressFamily *f); +int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi, + unsigned char *min, unsigned char *max, const int length); + +/* + * Canonical forms. + */ +int X509v3_asid_is_canonical(ASIdentifiers *asid); +int X509v3_addr_is_canonical(IPAddrBlocks *addr); +int X509v3_asid_canonize(ASIdentifiers *asid); +int X509v3_addr_canonize(IPAddrBlocks *addr); + +/* + * Tests for inheritance and containment. + */ +int X509v3_asid_inherits(ASIdentifiers *asid); +int X509v3_addr_inherits(IPAddrBlocks *addr); +int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b); +int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b); + +/* + * Check whether RFC 3779 extensions nest properly in chains. + */ +int X509v3_asid_validate_path(X509_STORE_CTX *); +int X509v3_addr_validate_path(X509_STORE_CTX *); +int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, ASIdentifiers *ext, + int allow_inheritance); +int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, IPAddrBlocks *ext, + int allow_inheritance); + +#endif /* !OPENSSL_NO_RFC3779 */ + +void ERR_load_X509V3_strings(void); + +/* Error codes for the X509V3 functions. */ + +/* Function codes. */ +#define X509V3_F_A2I_GENERAL_NAME 164 +#define X509V3_F_ASIDENTIFIERCHOICE_CANONIZE 161 +#define X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL 162 +#define X509V3_F_COPY_EMAIL 122 +#define X509V3_F_COPY_ISSUER 123 +#define X509V3_F_DO_DIRNAME 144 +#define X509V3_F_DO_EXT_CONF 124 +#define X509V3_F_DO_EXT_I2D 135 +#define X509V3_F_DO_EXT_NCONF 151 +#define X509V3_F_DO_I2V_NAME_CONSTRAINTS 148 +#define X509V3_F_GNAMES_FROM_SECTNAME 156 +#define X509V3_F_HEX_TO_STRING 111 +#define X509V3_F_I2S_ASN1_ENUMERATED 121 +#define X509V3_F_I2S_ASN1_IA5STRING 149 +#define X509V3_F_I2S_ASN1_INTEGER 120 +#define X509V3_F_I2V_AUTHORITY_INFO_ACCESS 138 +#define X509V3_F_NOTICE_SECTION 132 +#define X509V3_F_NREF_NOS 133 +#define X509V3_F_POLICY_SECTION 131 +#define X509V3_F_PROCESS_PCI_VALUE 150 +#define X509V3_F_R2I_CERTPOL 130 +#define X509V3_F_R2I_PCI 155 +#define X509V3_F_S2I_ASN1_IA5STRING 100 +#define X509V3_F_S2I_ASN1_INTEGER 108 +#define X509V3_F_S2I_ASN1_OCTET_STRING 112 +#define X509V3_F_S2I_ASN1_SKEY_ID 114 +#define X509V3_F_S2I_SKEY_ID 115 +#define X509V3_F_SET_DIST_POINT_NAME 158 +#define X509V3_F_STRING_TO_HEX 113 +#define X509V3_F_SXNET_ADD_ID_ASC 125 +#define X509V3_F_SXNET_ADD_ID_INTEGER 126 +#define X509V3_F_SXNET_ADD_ID_ULONG 127 +#define X509V3_F_SXNET_GET_ID_ASC 128 +#define X509V3_F_SXNET_GET_ID_ULONG 129 +#define X509V3_F_V2I_ASIDENTIFIERS 163 +#define X509V3_F_V2I_ASN1_BIT_STRING 101 +#define X509V3_F_V2I_AUTHORITY_INFO_ACCESS 139 +#define X509V3_F_V2I_AUTHORITY_KEYID 119 +#define X509V3_F_V2I_BASIC_CONSTRAINTS 102 +#define X509V3_F_V2I_CRLD 134 +#define X509V3_F_V2I_EXTENDED_KEY_USAGE 103 +#define X509V3_F_V2I_GENERAL_NAMES 118 +#define X509V3_F_V2I_GENERAL_NAME_EX 117 +#define X509V3_F_V2I_IDP 157 +#define X509V3_F_V2I_IPADDRBLOCKS 159 +#define X509V3_F_V2I_ISSUER_ALT 153 +#define X509V3_F_V2I_NAME_CONSTRAINTS 147 +#define X509V3_F_V2I_POLICY_CONSTRAINTS 146 +#define X509V3_F_V2I_POLICY_MAPPINGS 145 +#define X509V3_F_V2I_SUBJECT_ALT 154 +#define X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL 160 +#define X509V3_F_V3_GENERIC_EXTENSION 116 +#define X509V3_F_X509V3_ADD1_I2D 140 +#define X509V3_F_X509V3_ADD_VALUE 105 +#define X509V3_F_X509V3_EXT_ADD 104 +#define X509V3_F_X509V3_EXT_ADD_ALIAS 106 +#define X509V3_F_X509V3_EXT_CONF 107 +#define X509V3_F_X509V3_EXT_I2D 136 +#define X509V3_F_X509V3_EXT_NCONF 152 +#define X509V3_F_X509V3_GET_SECTION 142 +#define X509V3_F_X509V3_GET_STRING 143 +#define X509V3_F_X509V3_GET_VALUE_BOOL 110 +#define X509V3_F_X509V3_PARSE_LIST 109 +#define X509V3_F_X509_PURPOSE_ADD 137 +#define X509V3_F_X509_PURPOSE_SET 141 + +/* Reason codes. */ +#define X509V3_R_BAD_IP_ADDRESS 118 +#define X509V3_R_BAD_OBJECT 119 +#define X509V3_R_BN_DEC2BN_ERROR 100 +#define X509V3_R_BN_TO_ASN1_INTEGER_ERROR 101 +#define X509V3_R_DIRNAME_ERROR 149 +#define X509V3_R_DISTPOINT_ALREADY_SET 160 +#define X509V3_R_DUPLICATE_ZONE_ID 133 +#define X509V3_R_ERROR_CONVERTING_ZONE 131 +#define X509V3_R_ERROR_CREATING_EXTENSION 144 +#define X509V3_R_ERROR_IN_EXTENSION 128 +#define X509V3_R_EXPECTED_A_SECTION_NAME 137 +#define X509V3_R_EXTENSION_EXISTS 145 +#define X509V3_R_EXTENSION_NAME_ERROR 115 +#define X509V3_R_EXTENSION_NOT_FOUND 102 +#define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED 103 +#define X509V3_R_EXTENSION_VALUE_ERROR 116 +#define X509V3_R_ILLEGAL_EMPTY_EXTENSION 151 +#define X509V3_R_ILLEGAL_HEX_DIGIT 113 +#define X509V3_R_INCORRECT_POLICY_SYNTAX_TAG 152 +#define X509V3_R_INVALID_MULTIPLE_RDNS 161 +#define X509V3_R_INVALID_ASNUMBER 162 +#define X509V3_R_INVALID_ASRANGE 163 +#define X509V3_R_INVALID_BOOLEAN_STRING 104 +#define X509V3_R_INVALID_EXTENSION_STRING 105 +#define X509V3_R_INVALID_INHERITANCE 165 +#define X509V3_R_INVALID_IPADDRESS 166 +#define X509V3_R_INVALID_NAME 106 +#define X509V3_R_INVALID_NULL_ARGUMENT 107 +#define X509V3_R_INVALID_NULL_NAME 108 +#define X509V3_R_INVALID_NULL_VALUE 109 +#define X509V3_R_INVALID_NUMBER 140 +#define X509V3_R_INVALID_NUMBERS 141 +#define X509V3_R_INVALID_OBJECT_IDENTIFIER 110 +#define X509V3_R_INVALID_OPTION 138 +#define X509V3_R_INVALID_POLICY_IDENTIFIER 134 +#define X509V3_R_INVALID_PROXY_POLICY_SETTING 153 +#define X509V3_R_INVALID_PURPOSE 146 +#define X509V3_R_INVALID_SAFI 164 +#define X509V3_R_INVALID_SECTION 135 +#define X509V3_R_INVALID_SYNTAX 143 +#define X509V3_R_ISSUER_DECODE_ERROR 126 +#define X509V3_R_MISSING_VALUE 124 +#define X509V3_R_NEED_ORGANIZATION_AND_NUMBERS 142 +#define X509V3_R_NO_CONFIG_DATABASE 136 +#define X509V3_R_NO_ISSUER_CERTIFICATE 121 +#define X509V3_R_NO_ISSUER_DETAILS 127 +#define X509V3_R_NO_POLICY_IDENTIFIER 139 +#define X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED 154 +#define X509V3_R_NO_PUBLIC_KEY 114 +#define X509V3_R_NO_SUBJECT_DETAILS 125 +#define X509V3_R_ODD_NUMBER_OF_DIGITS 112 +#define X509V3_R_OPERATION_NOT_DEFINED 148 +#define X509V3_R_OTHERNAME_ERROR 147 +#define X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED 155 +#define X509V3_R_POLICY_PATH_LENGTH 156 +#define X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED 157 +#define X509V3_R_POLICY_SYNTAX_NOT_CURRENTLY_SUPPORTED 158 +#define X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY 159 +#define X509V3_R_SECTION_NOT_FOUND 150 +#define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS 122 +#define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID 123 +#define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT 111 +#define X509V3_R_UNKNOWN_EXTENSION 129 +#define X509V3_R_UNKNOWN_EXTENSION_NAME 130 +#define X509V3_R_UNKNOWN_OPTION 120 +#define X509V3_R_UNSUPPORTED_OPTION 117 +#define X509V3_R_UNSUPPORTED_TYPE 167 +#define X509V3_R_USER_TOO_LONG 132 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/pqueue.h b/include/pqueue.h new file mode 100644 index 0000000..cdda4a3 --- /dev/null +++ b/include/pqueue.h @@ -0,0 +1,93 @@ +/* $OpenBSD: pqueue.h,v 1.4 2016/11/04 18:28:58 guenther Exp $ */ + +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_PQUEUE_H +#define HEADER_PQUEUE_H + +__BEGIN_HIDDEN_DECLS + +typedef struct _pqueue *pqueue; + +typedef struct _pitem { + unsigned char priority[8]; /* 64-bit value in big-endian encoding */ + void *data; + struct _pitem *next; +} pitem; + +typedef struct _pitem *piterator; + +pitem *pitem_new(unsigned char *prio64be, void *data); +void pitem_free(pitem *item); + +pqueue pqueue_new(void); +void pqueue_free(pqueue pq); + +pitem *pqueue_insert(pqueue pq, pitem *item); +pitem *pqueue_peek(pqueue pq); +pitem *pqueue_pop(pqueue pq); +pitem *pqueue_find(pqueue pq, unsigned char *prio64be); +pitem *pqueue_iterator(pqueue pq); +pitem *pqueue_next(piterator *iter); + +int pqueue_size(pqueue pq); + +__END_HIDDEN_DECLS + +#endif /* ! HEADER_PQUEUE_H */ diff --git a/include/tls.h b/include/tls.h new file mode 100644 index 0000000..59b2c4c --- /dev/null +++ b/include/tls.h @@ -0,0 +1,230 @@ +/* $OpenBSD: tls.h,v 1.63 2023/07/02 06:37:27 beck Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS_H +#define HEADER_TLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _MSC_VER +#ifndef LIBRESSL_INTERNAL +#include +typedef SSIZE_T ssize_t; +#endif +#endif + +#include + +#include +#include + +#define TLS_API 20200120 + +/* + * Deprecated versions of TLS. Using these effectively selects + * the minimum supported version. + */ +#define TLS_PROTOCOL_TLSv1_0 (1 << 3) +#define TLS_PROTOCOL_TLSv1_1 (1 << 3) +/* Supported versions of TLS */ +#define TLS_PROTOCOL_TLSv1_2 (1 << 3) +#define TLS_PROTOCOL_TLSv1_3 (1 << 4) + +#define TLS_PROTOCOL_TLSv1 \ + (TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3) + +#define TLS_PROTOCOLS_ALL TLS_PROTOCOL_TLSv1 +#define TLS_PROTOCOLS_DEFAULT (TLS_PROTOCOL_TLSv1_2|TLS_PROTOCOL_TLSv1_3) + +#define TLS_WANT_POLLIN -2 +#define TLS_WANT_POLLOUT -3 + +/* RFC 6960 Section 2.3 */ +#define TLS_OCSP_RESPONSE_SUCCESSFUL 0 +#define TLS_OCSP_RESPONSE_MALFORMED 1 +#define TLS_OCSP_RESPONSE_INTERNALERROR 2 +#define TLS_OCSP_RESPONSE_TRYLATER 3 +#define TLS_OCSP_RESPONSE_SIGREQUIRED 4 +#define TLS_OCSP_RESPONSE_UNAUTHORIZED 5 + +/* RFC 6960 Section 2.2 */ +#define TLS_OCSP_CERT_GOOD 0 +#define TLS_OCSP_CERT_REVOKED 1 +#define TLS_OCSP_CERT_UNKNOWN 2 + +/* RFC 5280 Section 5.3.1 */ +#define TLS_CRL_REASON_UNSPECIFIED 0 +#define TLS_CRL_REASON_KEY_COMPROMISE 1 +#define TLS_CRL_REASON_CA_COMPROMISE 2 +#define TLS_CRL_REASON_AFFILIATION_CHANGED 3 +#define TLS_CRL_REASON_SUPERSEDED 4 +#define TLS_CRL_REASON_CESSATION_OF_OPERATION 5 +#define TLS_CRL_REASON_CERTIFICATE_HOLD 6 +#define TLS_CRL_REASON_REMOVE_FROM_CRL 8 +#define TLS_CRL_REASON_PRIVILEGE_WITHDRAWN 9 +#define TLS_CRL_REASON_AA_COMPROMISE 10 + +#define TLS_MAX_SESSION_ID_LENGTH 32 +#define TLS_TICKET_KEY_SIZE 48 + +struct tls; +struct tls_config; + +typedef ssize_t (*tls_read_cb)(struct tls *_ctx, void *_buf, size_t _buflen, + void *_cb_arg); +typedef ssize_t (*tls_write_cb)(struct tls *_ctx, const void *_buf, + size_t _buflen, void *_cb_arg); + +int tls_init(void); + +const char *tls_config_error(struct tls_config *_config); +const char *tls_error(struct tls *_ctx); + +struct tls_config *tls_config_new(void); +void tls_config_free(struct tls_config *_config); + +const char *tls_default_ca_cert_file(void); + +int tls_config_add_keypair_file(struct tls_config *_config, + const char *_cert_file, const char *_key_file); +int tls_config_add_keypair_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); +int tls_config_add_keypair_ocsp_file(struct tls_config *_config, + const char *_cert_file, const char *_key_file, + const char *_ocsp_staple_file); +int tls_config_add_keypair_ocsp_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len, + const uint8_t *_staple, size_t _staple_len); +int tls_config_set_alpn(struct tls_config *_config, const char *_alpn); +int tls_config_set_ca_file(struct tls_config *_config, const char *_ca_file); +int tls_config_set_ca_path(struct tls_config *_config, const char *_ca_path); +int tls_config_set_ca_mem(struct tls_config *_config, const uint8_t *_ca, + size_t _len); +int tls_config_set_cert_file(struct tls_config *_config, + const char *_cert_file); +int tls_config_set_cert_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _len); +int tls_config_set_ciphers(struct tls_config *_config, const char *_ciphers); +int tls_config_set_crl_file(struct tls_config *_config, const char *_crl_file); +int tls_config_set_crl_mem(struct tls_config *_config, const uint8_t *_crl, + size_t _len); +int tls_config_set_dheparams(struct tls_config *_config, const char *_params); +int tls_config_set_ecdhecurve(struct tls_config *_config, const char *_curve); +int tls_config_set_ecdhecurves(struct tls_config *_config, const char *_curves); +int tls_config_set_key_file(struct tls_config *_config, const char *_key_file); +int tls_config_set_key_mem(struct tls_config *_config, const uint8_t *_key, + size_t _len); +int tls_config_set_keypair_file(struct tls_config *_config, + const char *_cert_file, const char *_key_file); +int tls_config_set_keypair_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); +int tls_config_set_keypair_ocsp_file(struct tls_config *_config, + const char *_cert_file, const char *_key_file, const char *_staple_file); +int tls_config_set_keypair_ocsp_mem(struct tls_config *_config, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len, + const uint8_t *_staple, size_t staple_len); +int tls_config_set_ocsp_staple_mem(struct tls_config *_config, + const uint8_t *_staple, size_t _len); +int tls_config_set_ocsp_staple_file(struct tls_config *_config, + const char *_staple_file); +int tls_config_set_protocols(struct tls_config *_config, uint32_t _protocols); +int tls_config_set_session_fd(struct tls_config *_config, int _session_fd); +int tls_config_set_verify_depth(struct tls_config *_config, int _verify_depth); + +void tls_config_prefer_ciphers_client(struct tls_config *_config); +void tls_config_prefer_ciphers_server(struct tls_config *_config); + +void tls_config_insecure_noverifycert(struct tls_config *_config); +void tls_config_insecure_noverifyname(struct tls_config *_config); +void tls_config_insecure_noverifytime(struct tls_config *_config); +void tls_config_verify(struct tls_config *_config); + +void tls_config_ocsp_require_stapling(struct tls_config *_config); +void tls_config_verify_client(struct tls_config *_config); +void tls_config_verify_client_optional(struct tls_config *_config); + +void tls_config_clear_keys(struct tls_config *_config); +int tls_config_parse_protocols(uint32_t *_protocols, const char *_protostr); + +int tls_config_set_session_id(struct tls_config *_config, + const unsigned char *_session_id, size_t _len); +int tls_config_set_session_lifetime(struct tls_config *_config, int _lifetime); +int tls_config_add_ticket_key(struct tls_config *_config, uint32_t _keyrev, + unsigned char *_key, size_t _keylen); + +struct tls *tls_client(void); +struct tls *tls_server(void); +int tls_configure(struct tls *_ctx, struct tls_config *_config); +void tls_reset(struct tls *_ctx); +void tls_free(struct tls *_ctx); + +int tls_accept_fds(struct tls *_ctx, struct tls **_cctx, int _fd_read, + int _fd_write); +int tls_accept_socket(struct tls *_ctx, struct tls **_cctx, int _socket); +int tls_accept_cbs(struct tls *_ctx, struct tls **_cctx, + tls_read_cb _read_cb, tls_write_cb _write_cb, void *_cb_arg); +int tls_connect(struct tls *_ctx, const char *_host, const char *_port); +int tls_connect_fds(struct tls *_ctx, int _fd_read, int _fd_write, + const char *_servername); +int tls_connect_servername(struct tls *_ctx, const char *_host, + const char *_port, const char *_servername); +int tls_connect_socket(struct tls *_ctx, int _s, const char *_servername); +int tls_connect_cbs(struct tls *_ctx, tls_read_cb _read_cb, + tls_write_cb _write_cb, void *_cb_arg, const char *_servername); +int tls_handshake(struct tls *_ctx); +ssize_t tls_read(struct tls *_ctx, void *_buf, size_t _buflen); +ssize_t tls_write(struct tls *_ctx, const void *_buf, size_t _buflen); +int tls_close(struct tls *_ctx); + +int tls_peer_cert_provided(struct tls *_ctx); +int tls_peer_cert_contains_name(struct tls *_ctx, const char *_name); + +const char *tls_peer_cert_hash(struct tls *_ctx); +const char *tls_peer_cert_issuer(struct tls *_ctx); +const char *tls_peer_cert_subject(struct tls *_ctx); +time_t tls_peer_cert_notbefore(struct tls *_ctx); +time_t tls_peer_cert_notafter(struct tls *_ctx); +const uint8_t *tls_peer_cert_chain_pem(struct tls *_ctx, size_t *_len); + +const char *tls_conn_alpn_selected(struct tls *_ctx); +const char *tls_conn_cipher(struct tls *_ctx); +int tls_conn_cipher_strength(struct tls *_ctx); +const char *tls_conn_servername(struct tls *_ctx); +int tls_conn_session_resumed(struct tls *_ctx); +const char *tls_conn_version(struct tls *_ctx); + +uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); +void tls_unload_file(uint8_t *_buf, size_t len); + +int tls_ocsp_process_response(struct tls *_ctx, const unsigned char *_response, + size_t _size); +int tls_peer_ocsp_cert_status(struct tls *_ctx); +int tls_peer_ocsp_crl_reason(struct tls *_ctx); +time_t tls_peer_ocsp_next_update(struct tls *_ctx); +int tls_peer_ocsp_response_status(struct tls *_ctx); +const char *tls_peer_ocsp_result(struct tls *_ctx); +time_t tls_peer_ocsp_revocation_time(struct tls *_ctx); +time_t tls_peer_ocsp_this_update(struct tls *_ctx); +const char *tls_peer_ocsp_url(struct tls *_ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_TLS_H */ diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c new file mode 100644 index 0000000..6dd1699 --- /dev/null +++ b/ssl/bio_ssl.c @@ -0,0 +1,596 @@ +/* $OpenBSD: bio_ssl.c,v 1.40 2023/07/19 13:34:33 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "bio_local.h" +#include "ssl_local.h" + +static int ssl_write(BIO *h, const char *buf, int num); +static int ssl_read(BIO *h, char *buf, int size); +static int ssl_puts(BIO *h, const char *str); +static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int ssl_new(BIO *h); +static int ssl_free(BIO *data); +static long ssl_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +typedef struct bio_ssl_st { + SSL *ssl; /* The ssl handle :-) */ + /* re-negotiate every time the total number of bytes is this size */ + int num_renegotiates; + unsigned long renegotiate_count; + unsigned long byte_count; + unsigned long renegotiate_timeout; + time_t last_time; +} BIO_SSL; + +static const BIO_METHOD methods_sslp = { + .type = BIO_TYPE_SSL, + .name = "ssl", + .bwrite = ssl_write, + .bread = ssl_read, + .bputs = ssl_puts, + .ctrl = ssl_ctrl, + .create = ssl_new, + .destroy = ssl_free, + .callback_ctrl = ssl_callback_ctrl, +}; + +const BIO_METHOD * +BIO_f_ssl(void) +{ + return (&methods_sslp); +} +LSSL_ALIAS(BIO_f_ssl); + +static int +ssl_new(BIO *bi) +{ + BIO_SSL *bs; + + bs = calloc(1, sizeof(BIO_SSL)); + if (bs == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (0); + } + bi->init = 0; + bi->ptr = (char *)bs; + bi->flags = 0; + return (1); +} +LSSL_ALIAS(BIO_f_ssl); + +static int +ssl_free(BIO *a) +{ + BIO_SSL *bs; + + if (a == NULL) + return (0); + bs = (BIO_SSL *)a->ptr; + if (bs->ssl != NULL) + SSL_shutdown(bs->ssl); + if (a->shutdown) { + if (a->init && (bs->ssl != NULL)) + SSL_free(bs->ssl); + a->init = 0; + a->flags = 0; + } + free(a->ptr); + return (1); +} + +static int +ssl_read(BIO *b, char *out, int outl) +{ + int ret = 1; + BIO_SSL *sb; + SSL *ssl; + int retry_reason = 0; + int r = 0; + + if (out == NULL) + return (0); + sb = (BIO_SSL *)b->ptr; + ssl = sb->ssl; + + BIO_clear_retry_flags(b); + + ret = SSL_read(ssl, out, outl); + + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_NONE: + if (ret <= 0) + break; + if (sb->renegotiate_count > 0) { + sb->byte_count += ret; + if (sb->byte_count > sb->renegotiate_count) { + sb->byte_count = 0; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + r = 1; + } + } + if ((sb->renegotiate_timeout > 0) && (!r)) { + time_t tm; + + tm = time(NULL); + if (tm > sb->last_time + sb->renegotiate_timeout) { + sb->last_time = tm; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + } + } + + break; + case SSL_ERROR_WANT_READ: + BIO_set_retry_read(b); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_retry_write(b); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_set_retry_special(b); + retry_reason = BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_ACCEPT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_ACCEPT; + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_CONNECT; + break; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + case SSL_ERROR_ZERO_RETURN: + default: + break; + } + + b->retry_reason = retry_reason; + return (ret); +} + +static int +ssl_write(BIO *b, const char *out, int outl) +{ + int ret, r = 0; + int retry_reason = 0; + SSL *ssl; + BIO_SSL *bs; + + if (out == NULL) + return (0); + bs = (BIO_SSL *)b->ptr; + ssl = bs->ssl; + + BIO_clear_retry_flags(b); + +/* ret=SSL_do_handshake(ssl); + if (ret > 0) */ + ret = SSL_write(ssl, out, outl); + + switch (SSL_get_error(ssl, ret)) { + case SSL_ERROR_NONE: + if (ret <= 0) + break; + if (bs->renegotiate_count > 0) { + bs->byte_count += ret; + if (bs->byte_count > bs->renegotiate_count) { + bs->byte_count = 0; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + r = 1; + } + } + if ((bs->renegotiate_timeout > 0) && (!r)) { + time_t tm; + + tm = time(NULL); + if (tm > bs->last_time + bs->renegotiate_timeout) { + bs->last_time = tm; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + } + } + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_retry_write(b); + break; + case SSL_ERROR_WANT_READ: + BIO_set_retry_read(b); + break; + case SSL_ERROR_WANT_X509_LOOKUP: + BIO_set_retry_special(b); + retry_reason = BIO_RR_SSL_X509_LOOKUP; + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_retry_special(b); + retry_reason = BIO_RR_CONNECT; + case SSL_ERROR_SYSCALL: + case SSL_ERROR_SSL: + default: + break; + } + + b->retry_reason = retry_reason; + return (ret); +} + +static long +ssl_ctrl(BIO *b, int cmd, long num, void *ptr) +{ + SSL **sslp, *ssl; + BIO_SSL *bs; + BIO *dbio, *bio; + long ret = 1; + + bs = (BIO_SSL *)b->ptr; + ssl = bs->ssl; + if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) + return (0); + switch (cmd) { + case BIO_CTRL_RESET: + SSL_shutdown(ssl); + + if (ssl->handshake_func == ssl->method->ssl_connect) + SSL_set_connect_state(ssl); + else if (ssl->handshake_func == ssl->method->ssl_accept) + SSL_set_accept_state(ssl); + + SSL_clear(ssl); + + if (b->next_bio != NULL) + ret = BIO_ctrl(b->next_bio, cmd, num, ptr); + else if (ssl->rbio != NULL) + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + else + ret = 1; + break; + case BIO_CTRL_INFO: + ret = 0; + break; + case BIO_C_SSL_MODE: + if (num) /* client mode */ + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + break; + case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: + ret = bs->renegotiate_timeout; + if (num < 60) + num = 5; + bs->renegotiate_timeout = (unsigned long)num; + bs->last_time = time(NULL); + break; + case BIO_C_SET_SSL_RENEGOTIATE_BYTES: + ret = bs->renegotiate_count; + if ((long)num >=512) + bs->renegotiate_count = (unsigned long)num; + break; + case BIO_C_GET_SSL_NUM_RENEGOTIATES: + ret = bs->num_renegotiates; + break; + case BIO_C_SET_SSL: + if (ssl != NULL) { + ssl_free(b); + if (!ssl_new(b)) + return 0; + } + b->shutdown = (int)num; + ssl = (SSL *)ptr; + ((BIO_SSL *)b->ptr)->ssl = ssl; + bio = SSL_get_rbio(ssl); + if (bio != NULL) { + if (b->next_bio != NULL) + BIO_push(bio, b->next_bio); + b->next_bio = bio; + CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO); + } + b->init = 1; + break; + case BIO_C_GET_SSL: + if (ptr != NULL) { + sslp = (SSL **)ptr; + *sslp = ssl; + } else + ret = 0; + break; + case BIO_CTRL_GET_CLOSE: + ret = b->shutdown; + break; + case BIO_CTRL_SET_CLOSE: + b->shutdown = (int)num; + break; + case BIO_CTRL_WPENDING: + ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + break; + case BIO_CTRL_PENDING: + ret = SSL_pending(ssl); + if (ret == 0) + ret = BIO_pending(ssl->rbio); + break; + case BIO_CTRL_FLUSH: + BIO_clear_retry_flags(b); + ret = BIO_ctrl(ssl->wbio, cmd, num, ptr); + BIO_copy_next_retry(b); + break; + case BIO_CTRL_PUSH: + if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) { + SSL_set_bio(ssl, b->next_bio, b->next_bio); + CRYPTO_add(&b->next_bio->references, 1, + CRYPTO_LOCK_BIO); + } + break; + case BIO_CTRL_POP: + /* Only detach if we are the BIO explicitly being popped */ + if (b == ptr) { + /* Shouldn't happen in practice because the + * rbio and wbio are the same when pushed. + */ + if (ssl->rbio != ssl->wbio) + BIO_free_all(ssl->wbio); + if (b->next_bio != NULL) + CRYPTO_add(&b->next_bio->references, -1, CRYPTO_LOCK_BIO); + ssl->wbio = NULL; + ssl->rbio = NULL; + } + break; + case BIO_C_DO_STATE_MACHINE: + BIO_clear_retry_flags(b); + + b->retry_reason = 0; + ret = (int)SSL_do_handshake(ssl); + + switch (SSL_get_error(ssl, (int)ret)) { + case SSL_ERROR_WANT_READ: + BIO_set_flags(b, + BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_WRITE: + BIO_set_flags(b, + BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + break; + case SSL_ERROR_WANT_CONNECT: + BIO_set_flags(b, + BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + b->retry_reason = b->next_bio->retry_reason; + break; + default: + break; + } + break; + case BIO_CTRL_DUP: + dbio = (BIO *)ptr; + if (((BIO_SSL *)dbio->ptr)->ssl != NULL) + SSL_free(((BIO_SSL *)dbio->ptr)->ssl); + ((BIO_SSL *)dbio->ptr)->ssl = SSL_dup(ssl); + ((BIO_SSL *)dbio->ptr)->renegotiate_count = + ((BIO_SSL *)b->ptr)->renegotiate_count; + ((BIO_SSL *)dbio->ptr)->byte_count = + ((BIO_SSL *)b->ptr)->byte_count; + ((BIO_SSL *)dbio->ptr)->renegotiate_timeout = + ((BIO_SSL *)b->ptr)->renegotiate_timeout; + ((BIO_SSL *)dbio->ptr)->last_time = + ((BIO_SSL *)b->ptr)->last_time; + ret = (((BIO_SSL *)dbio->ptr)->ssl != NULL); + break; + case BIO_C_GET_FD: + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + break; + case BIO_CTRL_SET_CALLBACK: + { + ret = 0; + } + break; + case BIO_CTRL_GET_CALLBACK: + { + void (**fptr)(const SSL *xssl, int type, int val); + + fptr = (void (**)(const SSL *xssl, int type, int val)) + ptr; + *fptr = SSL_get_info_callback(ssl); + } + break; + default: + ret = BIO_ctrl(ssl->rbio, cmd, num, ptr); + break; + } + return (ret); +} + +static long +ssl_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ + SSL *ssl; + BIO_SSL *bs; + long ret = 1; + + bs = (BIO_SSL *)b->ptr; + ssl = bs->ssl; + switch (cmd) { + case BIO_CTRL_SET_CALLBACK: + { + /* FIXME: setting this via a completely different prototype + seems like a crap idea */ + SSL_set_info_callback(ssl, + (void (*)(const SSL *, int, int))fp); + } + break; + default: + ret = BIO_callback_ctrl(ssl->rbio, cmd, fp); + break; + } + return (ret); +} + +static int +ssl_puts(BIO *bp, const char *str) +{ + int n, ret; + + n = strlen(str); + ret = BIO_write(bp, str, n); + return (ret); +} + +BIO * +BIO_new_buffer_ssl_connect(SSL_CTX *ctx) +{ + BIO *ret = NULL, *buf = NULL, *ssl = NULL; + + if ((buf = BIO_new(BIO_f_buffer())) == NULL) + goto err; + if ((ssl = BIO_new_ssl_connect(ctx)) == NULL) + goto err; + if ((ret = BIO_push(buf, ssl)) == NULL) + goto err; + return (ret); + + err: + BIO_free(buf); + BIO_free(ssl); + return (NULL); +} +LSSL_ALIAS(BIO_new_buffer_ssl_connect); + +BIO * +BIO_new_ssl_connect(SSL_CTX *ctx) +{ + BIO *ret = NULL, *con = NULL, *ssl = NULL; + + if ((con = BIO_new(BIO_s_connect())) == NULL) + goto err; + if ((ssl = BIO_new_ssl(ctx, 1)) == NULL) + goto err; + if ((ret = BIO_push(ssl, con)) == NULL) + goto err; + return (ret); + + err: + BIO_free(con); + BIO_free(ssl); + return (NULL); +} +LSSL_ALIAS(BIO_new_ssl_connect); + +BIO * +BIO_new_ssl(SSL_CTX *ctx, int client) +{ + BIO *ret; + SSL *ssl; + + if ((ret = BIO_new(BIO_f_ssl())) == NULL) + goto err; + if ((ssl = SSL_new(ctx)) == NULL) + goto err; + + if (client) + SSL_set_connect_state(ssl); + else + SSL_set_accept_state(ssl); + + BIO_set_ssl(ret, ssl, BIO_CLOSE); + return (ret); + + err: + BIO_free(ret); + return (NULL); +} +LSSL_ALIAS(BIO_new_ssl); + +int +BIO_ssl_copy_session_id(BIO *t, BIO *f) +{ + t = BIO_find_type(t, BIO_TYPE_SSL); + f = BIO_find_type(f, BIO_TYPE_SSL); + if ((t == NULL) || (f == NULL)) + return (0); + if ((((BIO_SSL *)t->ptr)->ssl == NULL) || + (((BIO_SSL *)f->ptr)->ssl == NULL)) + return (0); + if (!SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl, + ((BIO_SSL *)f->ptr)->ssl)) + return (0); + return (1); +} +LSSL_ALIAS(BIO_ssl_copy_session_id); + +void +BIO_ssl_shutdown(BIO *b) +{ + SSL *s; + + while (b != NULL) { + if (b->method->type == BIO_TYPE_SSL) { + s = ((BIO_SSL *)b->ptr)->ssl; + SSL_shutdown(s); + break; + } + b = b->next_bio; + } +} +LSSL_ALIAS(BIO_ssl_shutdown); diff --git a/ssl/bs_ber.c b/ssl/bs_ber.c new file mode 100644 index 0000000..5cace24 --- /dev/null +++ b/ssl/bs_ber.c @@ -0,0 +1,269 @@ +/* $OpenBSD: bs_ber.c,v 1.11 2021/05/16 10:58:27 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "bytestring.h" + +/* + * kMaxDepth is a just a sanity limit. The code should be such that the length + * of the input being processes always decreases. None the less, a very large + * input could otherwise cause the stack to overflow. + */ +static const unsigned int kMaxDepth = 2048; + +/* Non-strict version that allows a relaxed DER with indefinite form. */ +static int +cbs_nonstrict_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len) +{ + return cbs_get_any_asn1_element_internal(cbs, out, + out_tag, out_header_len, 0); +} + +/* + * cbs_find_indefinite walks an ASN.1 structure in |orig_in| and sets + * |*indefinite_found| depending on whether an indefinite length element was + * found. The value of |orig_in| is not modified. + * + * Returns one on success (i.e. |*indefinite_found| was set) and zero on error. + */ +static int +cbs_find_indefinite(const CBS *orig_in, char *indefinite_found, + unsigned int depth) +{ + CBS in; + + if (depth > kMaxDepth) + return 0; + + CBS_init(&in, CBS_data(orig_in), CBS_len(orig_in)); + + while (CBS_len(&in) > 0) { + CBS contents; + unsigned int tag; + size_t header_len; + + if (!cbs_nonstrict_get_any_asn1_element(&in, &contents, &tag, + &header_len)) + return 0; + + /* Indefinite form not allowed by DER. */ + if (CBS_len(&contents) == header_len && header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + *indefinite_found = 1; + return 1; + } + if (tag & CBS_ASN1_CONSTRUCTED) { + if (!CBS_skip(&contents, header_len) || + !cbs_find_indefinite(&contents, indefinite_found, + depth + 1)) + return 0; + } + } + + *indefinite_found = 0; + return 1; +} + +/* + * is_primitive_type returns true if |tag| likely a primitive type. Normally + * one can just test the "constructed" bit in the tag but, in BER, even + * primitive tags can have the constructed bit if they have indefinite + * length. + */ +static char +is_primitive_type(unsigned int tag) +{ + return (tag & 0xc0) == 0 && + (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) && + (tag & 0x1f) != (CBS_ASN1_SET & 0x1f); +} + +/* + * is_eoc returns true if |header_len| and |contents|, as returned by + * |cbs_nonstrict_get_any_asn1_element|, indicate an "end of contents" (EOC) + * value. + */ +static char +is_eoc(size_t header_len, CBS *contents) +{ + const unsigned char eoc[] = {0x0, 0x0}; + + return header_len == 2 && CBS_mem_equal(contents, eoc, 2); +} + +/* + * cbs_convert_indefinite reads data with DER encoding (but relaxed to allow + * indefinite form) from |in| and writes definite form DER data to |out|. If + * |squash_header| is set then the top-level of elements from |in| will not + * have their headers written. This is used when concatenating the fragments of + * an indefinite length, primitive value. If |looking_for_eoc| is set then any + * EOC elements found will cause the function to return after consuming it. + * It returns one on success and zero on error. + */ +static int +cbs_convert_indefinite(CBS *in, CBB *out, char squash_header, + char looking_for_eoc, unsigned int depth) +{ + if (depth > kMaxDepth) + return 0; + + while (CBS_len(in) > 0) { + CBS contents; + unsigned int tag; + size_t header_len; + CBB *out_contents, out_contents_storage; + + if (!cbs_nonstrict_get_any_asn1_element(in, &contents, &tag, + &header_len)) + return 0; + + out_contents = out; + + if (CBS_len(&contents) == header_len) { + if (is_eoc(header_len, &contents)) + return looking_for_eoc; + + if (header_len > 0 && + CBS_data(&contents)[header_len - 1] == 0x80) { + /* + * This is an indefinite length element. If + * it's a SEQUENCE or SET then we just need to + * write the out the contents as normal, but + * with a concrete length prefix. + * + * If it's a something else then the contents + * will be a series of DER elements of the same + * type which need to be concatenated. + */ + const char context_specific = (tag & 0xc0) + == 0x80; + char squash_child_headers = + is_primitive_type(tag); + + /* + * This is a hack, but it sufficies to handle + * NSS's output. If we find an indefinite + * length, context-specific tag with a definite, + * primtive tag inside it, then we assume that + * the context-specific tag is implicit and the + * tags within are fragments of a primitive type + * that need to be concatenated. + */ + if (context_specific && + (tag & CBS_ASN1_CONSTRUCTED)) { + CBS in_copy, inner_contents; + unsigned int inner_tag; + size_t inner_header_len; + + CBS_init(&in_copy, CBS_data(in), + CBS_len(in)); + if (!cbs_nonstrict_get_any_asn1_element( + &in_copy, &inner_contents, + &inner_tag, &inner_header_len)) + return 0; + + if (CBS_len(&inner_contents) > + inner_header_len && + is_primitive_type(inner_tag)) + squash_child_headers = 1; + } + + if (!squash_header) { + unsigned int out_tag = tag; + + if (squash_child_headers) + out_tag &= + ~CBS_ASN1_CONSTRUCTED; + + if (!CBB_add_asn1(out, + &out_contents_storage, out_tag)) + return 0; + + out_contents = &out_contents_storage; + } + + if (!cbs_convert_indefinite(in, out_contents, + squash_child_headers, + 1 /* looking for eoc */, depth + 1)) + return 0; + + if (out_contents != out && !CBB_flush(out)) + return 0; + + continue; + } + } + + if (!squash_header) { + if (!CBB_add_asn1(out, &out_contents_storage, tag)) + return 0; + + out_contents = &out_contents_storage; + } + + if (!CBS_skip(&contents, header_len)) + return 0; + + if (tag & CBS_ASN1_CONSTRUCTED) { + if (!cbs_convert_indefinite(&contents, out_contents, + 0 /* don't squash header */, + 0 /* not looking for eoc */, depth + 1)) + return 0; + } else { + if (!CBB_add_bytes(out_contents, CBS_data(&contents), + CBS_len(&contents))) + return 0; + } + + if (out_contents != out && !CBB_flush(out)) + return 0; + } + + return looking_for_eoc == 0; +} + +int +CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len) +{ + CBB cbb; + + /* + * First, do a quick walk to find any indefinite-length elements. Most + * of the time we hope that there aren't any and thus we can quickly + * return. + */ + char conversion_needed; + if (!cbs_find_indefinite(in, &conversion_needed, 0)) + return 0; + + if (!conversion_needed) { + *out = NULL; + *out_len = 0; + return 1; + } + + if (!CBB_init(&cbb, CBS_len(in))) + return 0; + if (!cbs_convert_indefinite(in, &cbb, 0, 0, 0)) { + CBB_cleanup(&cbb); + return 0; + } + + return CBB_finish(&cbb, out, out_len); +} diff --git a/ssl/bs_cbb.c b/ssl/bs_cbb.c new file mode 100644 index 0000000..e2f87be --- /dev/null +++ b/ssl/bs_cbb.c @@ -0,0 +1,483 @@ +/* $OpenBSD: bs_cbb.c,v 1.28 2022/07/07 17:12:15 tb Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bytestring.h" + +#define CBB_INITIAL_SIZE 64 + +static int +cbb_init(CBB *cbb, uint8_t *buf, size_t cap) +{ + struct cbb_buffer_st *base; + + if ((base = calloc(1, sizeof(struct cbb_buffer_st))) == NULL) + return 0; + + base->buf = buf; + base->len = 0; + base->cap = cap; + base->can_resize = 1; + + cbb->base = base; + cbb->is_top_level = 1; + + return 1; +} + +int +CBB_init(CBB *cbb, size_t initial_capacity) +{ + uint8_t *buf = NULL; + + memset(cbb, 0, sizeof(*cbb)); + + if (initial_capacity == 0) + initial_capacity = CBB_INITIAL_SIZE; + + if ((buf = calloc(1, initial_capacity)) == NULL) + return 0; + + if (!cbb_init(cbb, buf, initial_capacity)) { + free(buf); + return 0; + } + + return 1; +} + +int +CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) +{ + memset(cbb, 0, sizeof(*cbb)); + + if (!cbb_init(cbb, buf, len)) + return 0; + + cbb->base->can_resize = 0; + + return 1; +} + +void +CBB_cleanup(CBB *cbb) +{ + if (cbb->base) { + if (cbb->base->can_resize) + freezero(cbb->base->buf, cbb->base->cap); + free(cbb->base); + } + cbb->base = NULL; + cbb->child = NULL; +} + +static int +cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out, size_t len) +{ + size_t newlen; + + if (base == NULL) + return 0; + + newlen = base->len + len; + if (newlen < base->len) + /* Overflow */ + return 0; + + if (newlen > base->cap) { + size_t newcap = base->cap * 2; + uint8_t *newbuf; + + if (!base->can_resize) + return 0; + + if (newcap < base->cap || newcap < newlen) + newcap = newlen; + + newbuf = recallocarray(base->buf, base->cap, newcap, 1); + if (newbuf == NULL) + return 0; + + base->buf = newbuf; + base->cap = newcap; + } + + if (out) + *out = base->buf + base->len; + + base->len = newlen; + return 1; +} + +static int +cbb_add_u(CBB *cbb, uint32_t v, size_t len_len) +{ + uint8_t *buf; + size_t i; + + if (len_len == 0) + return 1; + + if (len_len > 4) + return 0; + + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &buf, len_len)) + return 0; + + for (i = len_len - 1; i < len_len; i--) { + buf[i] = v; + v >>= 8; + } + return 1; +} + +int +CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) +{ + if (!cbb->is_top_level) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) + /* + * |out_data| and |out_len| can only be NULL if the CBB is + * fixed. + */ + return 0; + + if (out_data != NULL && *out_data != NULL) + return 0; + + if (out_data != NULL) + *out_data = cbb->base->buf; + + if (out_len != NULL) + *out_len = cbb->base->len; + + cbb->base->buf = NULL; + CBB_cleanup(cbb); + return 1; +} + +/* + * CBB_flush recurses and then writes out any pending length prefix. The current + * length of the underlying base is taken to be the length of the + * length-prefixed data. + */ +int +CBB_flush(CBB *cbb) +{ + size_t child_start, i, len; + + if (cbb->base == NULL) + return 0; + + if (cbb->child == NULL || cbb->pending_len_len == 0) + return 1; + + child_start = cbb->offset + cbb->pending_len_len; + + if (!CBB_flush(cbb->child) || child_start < cbb->offset || + cbb->base->len < child_start) + return 0; + + len = cbb->base->len - child_start; + + if (cbb->pending_is_asn1) { + /* + * For ASN.1, we assumed that we were using short form which + * only requires a single byte for the length octet. + * + * If it turns out that we need long form, we have to move + * the contents along in order to make space for more length + * octets. + */ + size_t len_len = 1; /* total number of length octets */ + uint8_t initial_length_byte; + + /* We already wrote 1 byte for the length. */ + if (cbb->pending_len_len != 1) + return 0; + + /* Check for long form */ + if (len > 0xfffffffe) + return 0; /* 0xffffffff is reserved */ + else if (len > 0xffffff) + len_len = 5; + else if (len > 0xffff) + len_len = 4; + else if (len > 0xff) + len_len = 3; + else if (len > 0x7f) + len_len = 2; + + if (len_len == 1) { + /* For short form, the initial byte is the length. */ + initial_length_byte = len; + len = 0; + + } else { + /* + * For long form, the initial byte is the number of + * subsequent length octets (plus bit 8 set). + */ + initial_length_byte = 0x80 | (len_len - 1); + + /* + * We need to move the contents along in order to make + * space for the long form length octets. + */ + size_t extra_bytes = len_len - 1; + if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) + return 0; + + memmove(cbb->base->buf + child_start + extra_bytes, + cbb->base->buf + child_start, len); + } + cbb->base->buf[cbb->offset++] = initial_length_byte; + cbb->pending_len_len = len_len - 1; + } + + for (i = cbb->pending_len_len - 1; i < cbb->pending_len_len; i--) { + cbb->base->buf[cbb->offset + i] = len; + len >>= 8; + } + if (len != 0) + return 0; + + cbb->child->base = NULL; + cbb->child = NULL; + cbb->pending_len_len = 0; + cbb->pending_is_asn1 = 0; + cbb->offset = 0; + + return 1; +} + +void +CBB_discard_child(CBB *cbb) +{ + if (cbb->child == NULL) + return; + + cbb->base->len = cbb->offset; + + cbb->child->base = NULL; + cbb->child = NULL; + cbb->pending_len_len = 0; + cbb->pending_is_asn1 = 0; + cbb->offset = 0; +} + +static int +cbb_add_length_prefixed(CBB *cbb, CBB *out_contents, size_t len_len) +{ + uint8_t *prefix_bytes; + + if (!CBB_flush(cbb)) + return 0; + + cbb->offset = cbb->base->len; + if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) + return 0; + + memset(prefix_bytes, 0, len_len); + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->pending_len_len = len_len; + cbb->pending_is_asn1 = 0; + + return 1; +} + +int +CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 1); +} + +int +CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 2); +} + +int +CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) +{ + return cbb_add_length_prefixed(cbb, out_contents, 3); +} + +int +CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag) +{ + if (tag > UINT8_MAX) + return 0; + + /* Long form identifier octets are not supported. */ + if ((tag & 0x1f) == 0x1f) + return 0; + + /* Short-form identifier octet only needs a single byte */ + if (!CBB_flush(cbb) || !CBB_add_u8(cbb, tag)) + return 0; + + /* + * Add 1 byte to cover the short-form length octet case. If it turns + * out we need long-form, it will be extended later. + */ + cbb->offset = cbb->base->len; + if (!CBB_add_u8(cbb, 0)) + return 0; + + memset(out_contents, 0, sizeof(CBB)); + out_contents->base = cbb->base; + cbb->child = out_contents; + cbb->pending_len_len = 1; + cbb->pending_is_asn1 = 1; + + return 1; +} + +int +CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) +{ + uint8_t *dest; + + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, &dest, len)) + return 0; + + memcpy(dest, data, len); + return 1; +} + +int +CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) +{ + if (!CBB_flush(cbb) || !cbb_buffer_add(cbb->base, out_data, len)) + return 0; + + memset(*out_data, 0, len); + return 1; +} + +int +CBB_add_u8(CBB *cbb, size_t value) +{ + if (value > UINT8_MAX) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 1); +} + +int +CBB_add_u16(CBB *cbb, size_t value) +{ + if (value > UINT16_MAX) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 2); +} + +int +CBB_add_u24(CBB *cbb, size_t value) +{ + if (value > 0xffffffUL) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 3); +} + +int +CBB_add_u32(CBB *cbb, size_t value) +{ + if (value > 0xffffffffUL) + return 0; + + return cbb_add_u(cbb, (uint32_t)value, 4); +} + +int +CBB_add_u64(CBB *cbb, uint64_t value) +{ + uint32_t a, b; + + a = value >> 32; + b = value & 0xffffffff; + + if (!CBB_add_u32(cbb, a)) + return 0; + return CBB_add_u32(cbb, b); +} + +int +CBB_add_asn1_uint64(CBB *cbb, uint64_t value) +{ + CBB child; + size_t i; + int started = 0; + + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) + return 0; + + for (i = 0; i < 8; i++) { + uint8_t byte = (value >> 8 * (7 - i)) & 0xff; + + /* + * ASN.1 restriction: first 9 bits cannot be all zeroes or + * all ones. Since this function only encodes unsigned + * integers, the only concerns are not encoding leading + * zeros and adding a padding byte if necessary. + * + * In practice, this means: + * 1) Skip leading octets of all zero bits in the value + * 2) After skipping the leading zero octets, if the next 9 + * bits are all ones, add an all zero prefix octet (and + * set the high bit of the prefix octet if negative). + * + * Additionally, for an unsigned value, add an all zero + * prefix if the high bit of the first octet would be one. + */ + if (!started) { + if (byte == 0) + /* Don't encode leading zeros. */ + continue; + + /* + * If the high bit is set, add a padding byte to make it + * unsigned. + */ + if ((byte & 0x80) && !CBB_add_u8(&child, 0)) + return 0; + + started = 1; + } + if (!CBB_add_u8(&child, byte)) + return 0; + } + + /* 0 is encoded as a single 0, not the empty string. */ + if (!started && !CBB_add_u8(&child, 0)) + return 0; + + return CBB_flush(cbb); +} diff --git a/ssl/bs_cbs.c b/ssl/bs_cbs.c new file mode 100644 index 0000000..63c078c --- /dev/null +++ b/ssl/bs_cbs.c @@ -0,0 +1,615 @@ +/* $OpenBSD: bs_cbs.c,v 1.24 2021/12/15 17:36:49 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bytestring.h" + +void +CBS_init(CBS *cbs, const uint8_t *data, size_t len) +{ + cbs->data = data; + cbs->initial_len = len; + cbs->len = len; +} + +void +CBS_dup(const CBS *cbs, CBS *out) +{ + CBS_init(out, CBS_data(cbs), CBS_len(cbs)); + out->initial_len = cbs->initial_len; +} + +static int +cbs_get(CBS *cbs, const uint8_t **p, size_t n) +{ + if (cbs->len < n) + return 0; + + *p = cbs->data; + cbs->data += n; + cbs->len -= n; + return 1; +} + +static int +cbs_peek(CBS *cbs, const uint8_t **p, size_t n) +{ + if (cbs->len < n) + return 0; + + *p = cbs->data; + return 1; +} + +size_t +CBS_offset(const CBS *cbs) +{ + return cbs->initial_len - cbs->len; +} + +int +CBS_skip(CBS *cbs, size_t len) +{ + const uint8_t *dummy; + return cbs_get(cbs, &dummy, len); +} + +const uint8_t * +CBS_data(const CBS *cbs) +{ + return cbs->data; +} + +size_t +CBS_len(const CBS *cbs) +{ + return cbs->len; +} + +int +CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) +{ + free(*out_ptr); + *out_ptr = NULL; + *out_len = 0; + + if (cbs->len == 0) + return 1; + + if ((*out_ptr = malloc(cbs->len)) == NULL) + return 0; + + memcpy(*out_ptr, cbs->data, cbs->len); + + *out_len = cbs->len; + return 1; +} + +int +CBS_strdup(const CBS *cbs, char **out_ptr) +{ + free(*out_ptr); + *out_ptr = NULL; + + if (CBS_contains_zero_byte(cbs)) + return 0; + + *out_ptr = strndup((const char *)cbs->data, cbs->len); + return (*out_ptr != NULL); +} + +int +CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied) +{ + if (dst_len < cbs->len) + return 0; + + memmove(dst, cbs->data, cbs->len); + + if (copied != NULL) + *copied = cbs->len; + + return 1; +} + +int +CBS_contains_zero_byte(const CBS *cbs) +{ + return memchr(cbs->data, 0, cbs->len) != NULL; +} + +int +CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) +{ + if (len != cbs->len) + return 0; + + return timingsafe_memcmp(cbs->data, data, len) == 0; +} + +static int +cbs_get_u(CBS *cbs, uint32_t *out, size_t len) +{ + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (len < 1 || len > 4) + return 0; + + if (!cbs_get(cbs, &data, len)) + return 0; + + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int +CBS_get_u8(CBS *cbs, uint8_t *out) +{ + const uint8_t *v; + + if (!cbs_get(cbs, &v, 1)) + return 0; + + *out = *v; + return 1; +} + +int +CBS_get_u16(CBS *cbs, uint16_t *out) +{ + uint32_t v; + + if (!cbs_get_u(cbs, &v, 2)) + return 0; + + *out = v; + return 1; +} + +int +CBS_get_u24(CBS *cbs, uint32_t *out) +{ + return cbs_get_u(cbs, out, 3); +} + +int +CBS_get_u32(CBS *cbs, uint32_t *out) +{ + return cbs_get_u(cbs, out, 4); +} + +int +CBS_get_u64(CBS *cbs, uint64_t *out) +{ + uint32_t a, b; + + if (cbs->len < 8) + return 0; + + if (!CBS_get_u32(cbs, &a)) + return 0; + if (!CBS_get_u32(cbs, &b)) + return 0; + + *out = (uint64_t)a << 32 | b; + return 1; +} + +int +CBS_get_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + cbs->len--; + return 1; +} + +int +CBS_get_bytes(CBS *cbs, CBS *out, size_t len) +{ + const uint8_t *v; + + if (!cbs_get(cbs, &v, len)) + return 0; + + CBS_init(out, v, len); + return 1; +} + +static int +cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) +{ + uint32_t len; + + if (!cbs_get_u(cbs, &len, len_len)) + return 0; + + return CBS_get_bytes(cbs, out, len); +} + +int +CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 1); +} + +int +CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 2); +} + +int +CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) +{ + return cbs_get_length_prefixed(cbs, out, 3); +} + +static int +cbs_peek_u(CBS *cbs, uint32_t *out, size_t len) +{ + uint32_t result = 0; + size_t i; + const uint8_t *data; + + if (len < 1 || len > 4) + return 0; + + if (!cbs_peek(cbs, &data, len)) + return 0; + + for (i = 0; i < len; i++) { + result <<= 8; + result |= data[i]; + } + *out = result; + return 1; +} + +int +CBS_peek_u8(CBS *cbs, uint8_t *out) +{ + const uint8_t *v; + + if (!cbs_peek(cbs, &v, 1)) + return 0; + + *out = *v; + return 1; +} + +int +CBS_peek_u16(CBS *cbs, uint16_t *out) +{ + uint32_t v; + + if (!cbs_peek_u(cbs, &v, 2)) + return 0; + + *out = v; + return 1; +} + +int +CBS_peek_u24(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 3); +} + +int +CBS_peek_u32(CBS *cbs, uint32_t *out) +{ + return cbs_peek_u(cbs, out, 4); +} + +int +CBS_peek_last_u8(CBS *cbs, uint8_t *out) +{ + if (cbs->len == 0) + return 0; + + *out = cbs->data[cbs->len - 1]; + return 1; +} + +int +CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len) +{ + return cbs_get_any_asn1_element_internal(cbs, out, out_tag, + out_header_len, 1); +} + +/* + * Review X.690 for details on ASN.1 DER encoding. + * + * If non-strict mode is enabled, then DER rules are relaxed + * for indefinite constructs (violates DER but a little closer to BER). + * Non-strict mode should only be used by bs_ber.c + * + * Sections 8, 10 and 11 for DER encoding + */ +int +cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len, int strict) +{ + uint8_t tag, length_byte; + CBS header = *cbs; + CBS throwaway; + size_t len; + + if (out == NULL) + out = &throwaway; + + /* + * Get identifier octet and length octet. Only 1 octet for each + * is a CBS limitation. + */ + if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte)) + return 0; + + /* CBS limitation: long form tags are not supported. */ + if ((tag & 0x1f) == 0x1f) + return 0; + + if (out_tag != NULL) + *out_tag = tag; + + if ((length_byte & 0x80) == 0) { + /* Short form length. */ + len = ((size_t) length_byte) + 2; + if (out_header_len != NULL) + *out_header_len = 2; + + } else { + /* Long form length. */ + const size_t num_bytes = length_byte & 0x7f; + uint32_t len32; + + /* ASN.1 reserved value for future extensions */ + if (num_bytes == 0x7f) + return 0; + + /* Handle indefinite form length */ + if (num_bytes == 0) { + /* DER encoding doesn't allow for indefinite form. */ + if (strict) + return 0; + + /* Primitive cannot use indefinite in BER or DER. */ + if ((tag & CBS_ASN1_CONSTRUCTED) == 0) + return 0; + + /* Constructed, indefinite length allowed in BER. */ + if (out_header_len != NULL) + *out_header_len = 2; + return CBS_get_bytes(cbs, out, 2); + } + + /* CBS limitation. */ + if (num_bytes > 4) + return 0; + + if (!cbs_get_u(&header, &len32, num_bytes)) + return 0; + + /* DER has a minimum length octet requirement. */ + if (len32 < 128) + /* Should have used short form instead */ + return 0; + + if ((len32 >> ((num_bytes - 1) * 8)) == 0) + /* Length should have been at least one byte shorter. */ + return 0; + + len = len32; + if (len + 2 + num_bytes < len) + /* Overflow. */ + return 0; + + len += 2 + num_bytes; + if (out_header_len != NULL) + *out_header_len = 2 + num_bytes; + } + + return CBS_get_bytes(cbs, out, len); +} + +static int +cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header) +{ + size_t header_len; + unsigned int tag; + CBS throwaway; + + if (out == NULL) + out = &throwaway; + + if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || + tag != tag_value) + return 0; + + if (skip_header && !CBS_skip(out, header_len)) + return 0; + + return 1; +} + +int +CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value) +{ + return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); +} + +int +CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value) +{ + return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); +} + +int +CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value) +{ + if (CBS_len(cbs) < 1) + return 0; + + /* + * Tag number 31 indicates the start of a long form number. + * This is valid in ASN.1, but CBS only supports short form. + */ + if ((tag_value & 0x1f) == 0x1f) + return 0; + + return CBS_data(cbs)[0] == tag_value; +} + +/* Encoding details are in ASN.1: X.690 section 8.3 */ +int +CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) +{ + CBS bytes; + const uint8_t *data; + size_t i, len; + + if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) + return 0; + + *out = 0; + data = CBS_data(&bytes); + len = CBS_len(&bytes); + + if (len == 0) + /* An INTEGER is encoded with at least one content octet. */ + return 0; + + if ((data[0] & 0x80) != 0) + /* Negative number. */ + return 0; + + if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) + /* Violates smallest encoding rule: excessive leading zeros. */ + return 0; + + for (i = 0; i < len; i++) { + if ((*out >> 56) != 0) + /* Too large to represent as a uint64_t. */ + return 0; + + *out <<= 8; + *out |= data[i]; + } + + return 1; +} + +int +CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag) +{ + if (CBS_peek_asn1_tag(cbs, tag)) { + if (!CBS_get_asn1(cbs, out, tag)) + return 0; + + *out_present = 1; + } else { + *out_present = 0; + } + return 1; +} + +int +CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, + unsigned int tag) +{ + CBS child; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || + CBS_len(&child) != 0) + return 0; + } else { + CBS_init(out, NULL, 0); + } + if (out_present) + *out_present = present; + + return 1; +} + +int +CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, + uint64_t default_value) +{ + CBS child; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + if (!CBS_get_asn1_uint64(&child, out) || + CBS_len(&child) != 0) + return 0; + } else { + *out = default_value; + } + return 1; +} + +int +CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, + int default_value) +{ + CBS child, child2; + int present; + + if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) + return 0; + + if (present) { + uint8_t boolean; + + if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || + CBS_len(&child2) != 1 || CBS_len(&child) != 0) + return 0; + + boolean = CBS_data(&child2)[0]; + if (boolean == 0) + *out = 0; + else if (boolean == 0xff) + *out = 1; + else + return 0; + + } else { + *out = default_value; + } + return 1; +} diff --git a/ssl/bytestring.h b/ssl/bytestring.h new file mode 100644 index 0000000..51284da --- /dev/null +++ b/ssl/bytestring.h @@ -0,0 +1,564 @@ +/* $OpenBSD: bytestring.h,v 1.24 2022/11/09 23:14:51 jsing Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef OPENSSL_HEADER_BYTESTRING_H +#define OPENSSL_HEADER_BYTESTRING_H + +#include +#include + +__BEGIN_HIDDEN_DECLS + +/* + * Bytestrings are used for parsing and building TLS and ASN.1 messages. + * + * A "CBS" (CRYPTO ByteString) represents a string of bytes in memory and + * provides utility functions for safely parsing length-prefixed structures + * like TLS and ASN.1 from it. + * + * A "CBB" (CRYPTO ByteBuilder) is a memory buffer that grows as needed and + * provides utility functions for building length-prefixed messages. + */ + +/* CRYPTO ByteString */ +typedef struct cbs_st { + const uint8_t *data; + size_t initial_len; + size_t len; +} CBS; + +/* + * CBS_init sets |cbs| to point to |data|. It does not take ownership of + * |data|. + */ +void CBS_init(CBS *cbs, const uint8_t *data, size_t len); + +/* + * CBS_skip advances |cbs| by |len| bytes. It returns one on success and zero + * otherwise. + */ +int CBS_skip(CBS *cbs, size_t len); + +/* + * CBS_data returns a pointer to the contents of |cbs|. + */ +const uint8_t *CBS_data(const CBS *cbs); + +/* + * CBS_len returns the number of bytes remaining in |cbs|. + */ +size_t CBS_len(const CBS *cbs); + +/* + * CBS_offset returns the current offset into the original data of |cbs|. + */ +size_t CBS_offset(const CBS *cbs); + +/* + * CBS_stow copies the current contents of |cbs| into |*out_ptr| and + * |*out_len|. If |*out_ptr| is not NULL, the contents are freed with + * free. It returns one on success and zero on allocation failure. On + * success, |*out_ptr| should be freed with free. If |cbs| is empty, + * |*out_ptr| will be NULL. + */ +int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len); + +/* + * CBS_strdup copies the current contents of |cbs| into |*out_ptr| as a + * NUL-terminated C string. If |*out_ptr| is not NULL, the contents are freed + * with free. It returns one on success and zero on failure. On success, + * |*out_ptr| should be freed with free. If |cbs| contains NUL bytes, + * CBS_strdup will fail. + */ +int CBS_strdup(const CBS *cbs, char **out_ptr); + +/* + * CBS_write_bytes writes all of the remaining data from |cbs| into |dst| + * if it is at most |dst_len| bytes. If |copied| is not NULL, it will be set + * to the amount copied. It returns one on success and zero otherwise. + */ +int CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, + size_t *copied); + +/* + * CBS_contains_zero_byte returns one if the current contents of |cbs| contains + * a NUL byte and zero otherwise. + */ +int CBS_contains_zero_byte(const CBS *cbs); + +/* + * CBS_mem_equal compares the current contents of |cbs| with the |len| bytes + * starting at |data|. If they're equal, it returns one, otherwise zero. If the + * lengths match, it uses a constant-time comparison. + */ +int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len); + +/* + * CBS_get_u8 sets |*out| to the next uint8_t from |cbs| and advances |cbs|. It + * returns one on success and zero on error. + */ +int CBS_get_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_get_u16 sets |*out| to the next, big-endian uint16_t from |cbs| and + * advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u16(CBS *cbs, uint16_t *out); + +/* + * CBS_get_u24 sets |*out| to the next, big-endian 24-bit value from |cbs| and + * advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u24(CBS *cbs, uint32_t *out); + +/* + * CBS_get_u32 sets |*out| to the next, big-endian uint32_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u32(CBS *cbs, uint32_t *out); + +/* + * CBS_get_u64 sets |*out| to the next, big-endian uint64_t value from |cbs| + * and advances |cbs|. It returns one on success and zero on error. + */ +int CBS_get_u64(CBS *cbs, uint64_t *out); + +/* + * CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens + * |cbs|. It returns one on success and zero on error. + */ +int CBS_get_last_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances + * |cbs|. It returns one on success and zero on error. + */ +int CBS_get_bytes(CBS *cbs, CBS *out, size_t len); + +/* + * CBS_get_u8_length_prefixed sets |*out| to the contents of an 8-bit, + * length-prefixed value from |cbs| and advances |cbs| over it. It returns one + * on success and zero on error. + */ +int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_get_u16_length_prefixed sets |*out| to the contents of a 16-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. + */ +int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_get_u24_length_prefixed sets |*out| to the contents of a 24-bit, + * big-endian, length-prefixed value from |cbs| and advances |cbs| over it. It + * returns one on success and zero on error. + */ +int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out); + +/* + * CBS_peek_u8 sets |*out| to the next uint8_t from |cbs|, but does not advance + * |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u8(CBS *cbs, uint8_t *out); + +/* + * CBS_peek_u16 sets |*out| to the next, big-endian uint16_t from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u16(CBS *cbs, uint16_t *out); + +/* + * CBS_peek_u24 sets |*out| to the next, big-endian 24-bit value from |cbs|, but + * does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u24(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_u32 sets |*out| to the next, big-endian uint32_t value from |cbs|, + * but does not advance |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_u32(CBS *cbs, uint32_t *out); + +/* + * CBS_peek_last_u8 sets |*out| to the last uint8_t from |cbs|, but does not + * shorten |cbs|. It returns one on success and zero on error. + */ +int CBS_peek_last_u8(CBS *cbs, uint8_t *out); + + +/* Parsing ASN.1 */ + +/* + * While an identifier can be multiple octets, this library only handles the + * single octet variety currently. This limits support up to tag number 30 + * since tag number 31 is a reserved value to indicate multiple octets. + */ + +/* Bits 8 and 7: class tag type: See X.690 section 8.1.2.2. */ +#define CBS_ASN1_UNIVERSAL 0x00 +#define CBS_ASN1_APPLICATION 0x40 +#define CBS_ASN1_CONTEXT_SPECIFIC 0x80 +#define CBS_ASN1_PRIVATE 0xc0 + +/* Bit 6: Primitive or constructed: See X.690 section 8.1.2.3. */ +#define CBS_ASN1_PRIMITIVE 0x00 +#define CBS_ASN1_CONSTRUCTED 0x20 + +/* + * Bits 5 to 1 are the tag number. See X.680 section 8.6 for tag numbers of + * the universal class. + */ + +/* + * Common universal identifier octets. + * See X.690 section 8.1 and X.680 section 8.6 for universal tag numbers. + * + * Note: These definitions are the cause of some of the strange behavior in + * CBS's bs_ber.c. + * + * In BER, it is the sender's option to use primitive or constructed for + * bitstring (X.690 section 8.6.1) and octetstring (X.690 section 8.7.1). + * + * In DER, bitstring and octetstring are required to be primitive + * (X.690 section 10.2). + */ +#define CBS_ASN1_BOOLEAN (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x1) +#define CBS_ASN1_INTEGER (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x2) +#define CBS_ASN1_BITSTRING (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x3) +#define CBS_ASN1_OCTETSTRING (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x4) +#define CBS_ASN1_OBJECT (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0x6) +#define CBS_ASN1_ENUMERATED (CBS_ASN1_UNIVERSAL | CBS_ASN1_PRIMITIVE | 0xa) +#define CBS_ASN1_SEQUENCE (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x10) +#define CBS_ASN1_SET (CBS_ASN1_UNIVERSAL | CBS_ASN1_CONSTRUCTED | 0x11) + +/* + * CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not + * including tag and length bytes) and advances |cbs| over it. The ASN.1 + * element must match |tag_value|. It returns one on success and zero + * on error. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value); + +/* + * CBS_get_asn1_element acts like |CBS_get_asn1| but |out| will include the + * ASN.1 header bytes too. + */ +int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value); + +/* + * CBS_peek_asn1_tag looks ahead at the next ASN.1 tag and returns one + * if the next ASN.1 element on |cbs| would have tag |tag_value|. If + * |cbs| is empty or the tag does not match, it returns zero. Note: if + * it returns one, CBS_get_asn1 may still fail if the rest of the + * element is malformed. + */ +int CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value); + +/* + * CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from + * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to + * the tag number and |*out_header_len| to the length of the ASN.1 header. + * Each of |out|, |out_tag|, and |out_header_len| may be NULL to ignore + * the value. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len); + +/* + * CBS_get_asn1_uint64 gets an ASN.1 INTEGER from |cbs| using |CBS_get_asn1| + * and sets |*out| to its value. It returns one on success and zero on error, + * where error includes the integer being negative, or too large to represent + * in 64 bits. + */ +int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out); + +/* + * CBS_get_optional_asn1 gets an optional explicitly-tagged element + * from |cbs| tagged with |tag| and sets |*out| to its contents. If + * present, it sets |*out_present| to one, otherwise zero. It returns + * one on success, whether or not the element was present, and zero on + * decode failure. + */ +int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, + unsigned int tag); + +/* + * CBS_get_optional_asn1_octet_string gets an optional + * explicitly-tagged OCTET STRING from |cbs|. If present, it sets + * |*out| to the string and |*out_present| to one. Otherwise, it sets + * |*out| to empty and |*out_present| to zero. |out_present| may be + * NULL. It returns one on success, whether or not the element was + * present, and zero on decode failure. + */ +int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, + unsigned int tag); + +/* + * CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged + * INTEGER from |cbs|. If present, it sets |*out| to the + * value. Otherwise, it sets |*out| to |default_value|. It returns one + * on success, whether or not the element was present, and zero on + * decode failure. + */ +int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, + uint64_t default_value); + +/* + * CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from + * |cbs|. If present, it sets |*out| to either zero or one, based on the + * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on + * success, whether or not the element was present, and zero on decode + * failure. + */ +int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, + int default_value); + + +/* + * CRYPTO ByteBuilder. + * + * |CBB| objects allow one to build length-prefixed serialisations. A |CBB| + * object is associated with a buffer and new buffers are created with + * |CBB_init|. Several |CBB| objects can point at the same buffer when a + * length-prefix is pending, however only a single |CBB| can be 'current' at + * any one time. For example, if one calls |CBB_add_u8_length_prefixed| then + * the new |CBB| points at the same buffer as the original. But if the original + * |CBB| is used then the length prefix is written out and the new |CBB| must + * not be used again. + * + * If one needs to force a length prefix to be written out because a |CBB| is + * going out of scope, use |CBB_flush|. + */ + +struct cbb_buffer_st { + uint8_t *buf; + + /* The number of valid bytes. */ + size_t len; + + /* The size of buf. */ + size_t cap; + + /* + * One iff |buf| is owned by this object. If not then |buf| cannot be + * resized. + */ + char can_resize; +}; + +typedef struct cbb_st { + struct cbb_buffer_st *base; + + /* + * offset is the offset from the start of |base->buf| to the position of any + * pending length-prefix. + */ + size_t offset; + + /* child points to a child CBB if a length-prefix is pending. */ + struct cbb_st *child; + + /* + * pending_len_len contains the number of bytes in a pending length-prefix, + * or zero if no length-prefix is pending. + */ + uint8_t pending_len_len; + + char pending_is_asn1; + + /* + * is_top_level is true iff this is a top-level |CBB| (as opposed to a child + * |CBB|). Top-level objects are valid arguments for |CBB_finish|. + */ + char is_top_level; +} CBB; + +/* + * CBB_init initialises |cbb| with |initial_capacity|. Since a |CBB| grows as + * needed, the |initial_capacity| is just a hint. It returns one on success or + * zero on error. + */ +int CBB_init(CBB *cbb, size_t initial_capacity); + +/* + * CBB_init_fixed initialises |cbb| to write to |len| bytes at |buf|. Since + * |buf| cannot grow, trying to write more than |len| bytes will cause CBB + * functions to fail. It returns one on success or zero on error. + */ +int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len); + +/* + * CBB_cleanup frees all resources owned by |cbb| and other |CBB| objects + * writing to the same buffer. This should be used in an error case where a + * serialisation is abandoned. + */ +void CBB_cleanup(CBB *cbb); + +/* + * CBB_finish completes any pending length prefix and sets |*out_data| to a + * malloced buffer and |*out_len| to the length of that buffer. The caller + * takes ownership of the buffer and, unless the buffer was fixed with + * |CBB_init_fixed|, must call |free| when done. + * + * It can only be called on a "top level" |CBB|, i.e. one initialised with + * |CBB_init| or |CBB_init_fixed|. It returns one on success and zero on + * error. + */ +int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len); + +/* + * CBB_flush causes any pending length prefixes to be written out and any child + * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero + * on error. + */ +int CBB_flush(CBB *cbb); + +/* + * CBB_discard_child discards the current unflushed child of |cbb|. Neither the + * child's contents nor the length prefix will be included in the output. + */ +void CBB_discard_child(CBB *cbb); + +/* + * CBB_add_u8_length_prefixed sets |*out_contents| to a new child of |cbb|. The + * data written to |*out_contents| will be prefixed in |cbb| with an 8-bit + * length. It returns one on success or zero on error. + */ +int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_u16_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 16-bit, + * big-endian length. It returns one on success or zero on error. + */ +int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_u24_length_prefixed sets |*out_contents| to a new child of |cbb|. + * The data written to |*out_contents| will be prefixed in |cbb| with a 24-bit, + * big-endian length. It returns one on success or zero on error. + */ +int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents); + +/* + * CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an + * ASN.1 object can be written. The |tag| argument will be used as the tag for + * the object. Passing in |tag| number 31 will return in an error since only + * single octet identifiers are supported. It returns one on success or zero + * on error. + */ +int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned int tag); + +/* + * CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on + * success and zero otherwise. + */ +int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len); + +/* + * CBB_add_space appends |len| bytes to |cbb| and sets |*out_data| to point to + * the beginning of that space. The caller must then write |len| bytes of + * actual contents to |*out_data|. It returns one on success and zero + * otherwise. + */ +int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len); + +/* + * CBB_add_u8 appends an 8-bit number from |value| to |cbb|. It returns one on + * success and zero otherwise. + */ +int CBB_add_u8(CBB *cbb, size_t value); + +/* + * CBB_add_u8 appends a 16-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u16(CBB *cbb, size_t value); + +/* + * CBB_add_u24 appends a 24-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u24(CBB *cbb, size_t value); + +/* + * CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u32(CBB *cbb, size_t value); + +/* + * CBB_add_u64 appends a 64-bit, big-endian number from |value| to |cbb|. It + * returns one on success and zero otherwise. + */ +int CBB_add_u64(CBB *cbb, uint64_t value); + +/* + * CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1| + * and writes |value| in its contents. It returns one on success and zero on + * error. + */ +int CBB_add_asn1_uint64(CBB *cbb, uint64_t value); + +#ifdef LIBRESSL_INTERNAL +/* + * CBS_dup sets |out| to point to cbs's |data| and |len|. It results in two + * CBS that point to the same buffer. + */ +void CBS_dup(const CBS *cbs, CBS *out); + +/* + * cbs_get_any_asn1_element sets |*out| to contain the next ASN.1 element from + * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to + * the tag number and |*out_header_len| to the length of the ASN.1 header. If + * strict mode is disabled and the element has indefinite length then |*out| + * will only contain the header. Each of |out|, |out_tag|, and + * |out_header_len| may be NULL to ignore the value. + * + * Tag numbers greater than 30 are not supported (i.e. short form only). + */ +int cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, + size_t *out_header_len, int strict); + +/* + * CBS_asn1_indefinite_to_definite reads an ASN.1 structure from |in|. If it + * finds indefinite-length elements that otherwise appear to be valid DER, it + * attempts to convert the DER-like data to DER and sets |*out| and + * |*out_length| to describe a malloced buffer containing the DER data. + * Additionally, |*in| will be advanced over the ASN.1 data. + * + * If it doesn't find any indefinite-length elements then it sets |*out| to + * NULL and |*in| is unmodified. + * + * This is NOT a conversion from BER to DER. There are many restrictions when + * dealing with DER data. This is only concerned with one: indefinite vs. + * definite form. However, this suffices to handle the PKCS#7 and PKCS#12 output + * from NSS. + * + * It returns one on success and zero otherwise. + */ +int CBS_asn1_indefinite_to_definite(CBS *in, uint8_t **out, size_t *out_len); +#endif /* LIBRESSL_INTERNAL */ + +__END_HIDDEN_DECLS + +#endif /* OPENSSL_HEADER_BYTESTRING_H */ diff --git a/ssl/d1_both.c b/ssl/d1_both.c new file mode 100644 index 0000000..b5c68a1 --- /dev/null +++ b/ssl/d1_both.c @@ -0,0 +1,1198 @@ +/* $OpenBSD: d1_both.c,v 1.84 2022/12/26 07:31:44 jmc Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "dtls_local.h" +#include "pqueue.h" +#include "ssl_local.h" + +#define RSMBLY_BITMASK_SIZE(msg_len) (((msg_len) + 7) / 8) + +#define RSMBLY_BITMASK_MARK(bitmask, start, end) { \ + if ((end) - (start) <= 8) { \ + long ii; \ + for (ii = (start); ii < (end); ii++) bitmask[((ii) >> 3)] |= (1 << ((ii) & 7)); \ + } else { \ + long ii; \ + bitmask[((start) >> 3)] |= bitmask_start_values[((start) & 7)]; \ + for (ii = (((start) >> 3) + 1); ii < ((((end) - 1)) >> 3); ii++) bitmask[ii] = 0xff; \ + bitmask[(((end) - 1) >> 3)] |= bitmask_end_values[((end) & 7)]; \ + } } + +#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \ + long ii; \ + OPENSSL_assert((msg_len) > 0); \ + is_complete = 1; \ + if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \ + if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \ + if (bitmask[ii] != 0xff) { is_complete = 0; break; } } + +static const unsigned char bitmask_start_values[] = { + 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 +}; +static const unsigned char bitmask_end_values[] = { + 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f +}; + +/* XDTLS: figure out the right values */ +static const unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; + +static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); +static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, + unsigned long frag_len); +static int dtls1_write_message_header(const struct hm_header_st *msg_hdr, + unsigned long frag_off, unsigned long frag_len, unsigned char *p); +static long dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, + int *ok); + +void dtls1_hm_fragment_free(hm_fragment *frag); + +static hm_fragment * +dtls1_hm_fragment_new(unsigned long frag_len, int reassembly) +{ + hm_fragment *frag; + + if ((frag = calloc(1, sizeof(*frag))) == NULL) + goto err; + + if (frag_len > 0) { + if ((frag->fragment = calloc(1, frag_len)) == NULL) + goto err; + } + + /* Initialize reassembly bitmask if necessary. */ + if (reassembly) { + if ((frag->reassembly = calloc(1, + RSMBLY_BITMASK_SIZE(frag_len))) == NULL) + goto err; + } + + return frag; + + err: + dtls1_hm_fragment_free(frag); + return NULL; +} + +void +dtls1_hm_fragment_free(hm_fragment *frag) +{ + if (frag == NULL) + return; + + free(frag->fragment); + free(frag->reassembly); + free(frag); +} + +/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */ +int +dtls1_do_write(SSL *s, int type) +{ + int ret; + int curr_mtu; + unsigned int len, frag_off; + size_t overhead; + + /* AHA! Figure out the MTU, and stick to the right size */ + if (s->d1->mtu < dtls1_min_mtu() && + !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) { + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + + /* + * I've seen the kernel return bogus numbers when it + * doesn't know the MTU (ie., the initial write), so just + * make sure we have a reasonable number + */ + if (s->d1->mtu < dtls1_min_mtu()) { + s->d1->mtu = 0; + s->d1->mtu = dtls1_guess_mtu(s->d1->mtu); + BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, + s->d1->mtu, NULL); + } + } + + OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); + /* should have something reasonable now */ + + if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) + OPENSSL_assert(s->init_num == + (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); + + if (!tls12_record_layer_write_overhead(s->rl, &overhead)) + return -1; + + frag_off = 0; + while (s->init_num) { + curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - + DTLS1_RT_HEADER_LENGTH - overhead; + + if (curr_mtu <= DTLS1_HM_HEADER_LENGTH) { + /* grr.. we could get an error if MTU picked was wrong */ + ret = BIO_flush(SSL_get_wbio(s)); + if (ret <= 0) + return ret; + curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH - + overhead; + } + + if (s->init_num > curr_mtu) + len = curr_mtu; + else + len = s->init_num; + + /* XDTLS: this function is too long. split out the CCS part */ + if (type == SSL3_RT_HANDSHAKE) { + if (s->init_off != 0) { + OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH); + s->init_off -= DTLS1_HM_HEADER_LENGTH; + s->init_num += DTLS1_HM_HEADER_LENGTH; + + if (s->init_num > curr_mtu) + len = curr_mtu; + else + len = s->init_num; + } + + dtls1_fix_message_header(s, frag_off, + len - DTLS1_HM_HEADER_LENGTH); + + if (!dtls1_write_message_header(&s->d1->w_msg_hdr, + s->d1->w_msg_hdr.frag_off, s->d1->w_msg_hdr.frag_len, + (unsigned char *)&s->init_buf->data[s->init_off])) + return -1; + + OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH); + } + + ret = dtls1_write_bytes(s, type, + &s->init_buf->data[s->init_off], len); + if (ret < 0) { + /* + * Might need to update MTU here, but we don't know + * which previous packet caused the failure -- so + * can't really retransmit anything. continue as + * if everything is fine and wait for an alert to + * handle the retransmit + */ + if (BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL) > 0) + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL); + else + return (-1); + } else { + + /* + * Bad if this assert fails, only part of the + * handshake message got sent. but why would + * this happen? + */ + OPENSSL_assert(len == (unsigned int)ret); + + if (type == SSL3_RT_HANDSHAKE && + !s->d1->retransmitting) { + /* + * Should not be done for 'Hello Request's, + * but in that case we'll ignore the result + * anyway + */ + unsigned char *p = (unsigned char *)&s->init_buf->data[s->init_off]; + const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + int xlen; + + if (frag_off == 0) { + /* + * Reconstruct message header is if it + * is being sent in single fragment + */ + if (!dtls1_write_message_header(msg_hdr, + 0, msg_hdr->msg_len, p)) + return (-1); + xlen = ret; + } else { + p += DTLS1_HM_HEADER_LENGTH; + xlen = ret - DTLS1_HM_HEADER_LENGTH; + } + + tls1_transcript_record(s, p, xlen); + } + + if (ret == s->init_num) { + if (s->msg_callback) + s->msg_callback(1, s->version, type, + s->init_buf->data, + (size_t)(s->init_off + s->init_num), + s, s->msg_callback_arg); + + s->init_off = 0; + /* done writing this message */ + s->init_num = 0; + + return (1); + } + s->init_off += ret; + s->init_num -= ret; + frag_off += (ret -= DTLS1_HM_HEADER_LENGTH); + } + } + return (0); +} + + +/* + * Obtain handshake message of message type 'mt' (any if mt == -1), + * maximum acceptable body length 'max'. + * Read an entire handshake message. Handshake messages arrive in + * fragments. + */ +int +dtls1_get_message(SSL *s, int st1, int stn, int mt, long max) +{ + struct hm_header_st *msg_hdr; + unsigned char *p; + unsigned long msg_len; + int i, al, ok; + + /* + * s3->tmp is used to store messages that are unexpected, caused + * by the absence of an optional handshake message + */ + if (s->s3->hs.tls12.reuse_message) { + s->s3->hs.tls12.reuse_message = 0; + if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + s->init_num = (int)s->s3->hs.tls12.message_size; + return 1; + } + + msg_hdr = &s->d1->r_msg_hdr; + memset(msg_hdr, 0, sizeof(struct hm_header_st)); + + again: + i = dtls1_get_message_fragment(s, st1, stn, max, &ok); + if (i == DTLS1_HM_BAD_FRAGMENT || + i == DTLS1_HM_FRAGMENT_RETRY) /* bad fragment received */ + goto again; + else if (i <= 0 && !ok) + return i; + + p = (unsigned char *)s->init_buf->data; + msg_len = msg_hdr->msg_len; + + /* reconstruct message header */ + if (!dtls1_write_message_header(msg_hdr, 0, msg_len, p)) + return -1; + + msg_len += DTLS1_HM_HEADER_LENGTH; + + tls1_transcript_record(s, p, msg_len); + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len, + s, s->msg_callback_arg); + + memset(msg_hdr, 0, sizeof(struct hm_header_st)); + + /* Don't change sequence numbers while listening */ + if (!s->d1->listen) + s->d1->handshake_read_seq++; + + s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + return 1; + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; +} + +static int +dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr, int max) +{ + size_t frag_off, frag_len, msg_len; + + msg_len = msg_hdr->msg_len; + frag_off = msg_hdr->frag_off; + frag_len = msg_hdr->frag_len; + + /* sanity checking */ + if ((frag_off + frag_len) > msg_len) { + SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SSL_AD_ILLEGAL_PARAMETER; + } + + if ((frag_off + frag_len) > (unsigned long)max) { + SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SSL_AD_ILLEGAL_PARAMETER; + } + + if ( s->d1->r_msg_hdr.frag_off == 0) /* first fragment */ + { + /* + * msg_len is limited to 2^24, but is effectively checked + * against max above + */ + if (!BUF_MEM_grow_clean(s->init_buf, + msg_len + DTLS1_HM_HEADER_LENGTH)) { + SSLerror(s, ERR_R_BUF_LIB); + return SSL_AD_INTERNAL_ERROR; + } + + s->s3->hs.tls12.message_size = msg_len; + s->d1->r_msg_hdr.msg_len = msg_len; + s->s3->hs.tls12.message_type = msg_hdr->type; + s->d1->r_msg_hdr.type = msg_hdr->type; + s->d1->r_msg_hdr.seq = msg_hdr->seq; + } else if (msg_len != s->d1->r_msg_hdr.msg_len) { + /* + * They must be playing with us! BTW, failure to enforce + * upper limit would open possibility for buffer overrun. + */ + SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); + return SSL_AD_ILLEGAL_PARAMETER; + } + + return 0; /* no error */ +} + +static int +dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) +{ + /* + * (0) check whether the desired fragment is available + * if so: + * (1) copy over the fragment to s->init_buf->data[] + * (2) update s->init_num + */ + pitem *item; + hm_fragment *frag; + int al; + + *ok = 0; + item = pqueue_peek(s->d1->buffered_messages); + if (item == NULL) + return 0; + + frag = (hm_fragment *)item->data; + + /* Don't return if reassembly still in progress */ + if (frag->reassembly != NULL) + return 0; + + if (s->d1->handshake_read_seq == frag->msg_header.seq) { + unsigned long frag_len = frag->msg_header.frag_len; + pqueue_pop(s->d1->buffered_messages); + + al = dtls1_preprocess_fragment(s, &frag->msg_header, max); + + if (al == 0) /* no alert */ + { + unsigned char *p = (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + memcpy(&p[frag->msg_header.frag_off], + frag->fragment, frag->msg_header.frag_len); + } + + dtls1_hm_fragment_free(frag); + pitem_free(item); + + if (al == 0) { + *ok = 1; + return frag_len; + } + + ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->init_num = 0; + *ok = 0; + return -1; + } else + return 0; +} + +/* + * dtls1_max_handshake_message_len returns the maximum number of bytes + * permitted in a DTLS handshake message for |s|. The minimum is 16KB, + * but may be greater if the maximum certificate list size requires it. + */ +static unsigned long +dtls1_max_handshake_message_len(const SSL *s) +{ + unsigned long max_len; + + max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH; + if (max_len < (unsigned long)s->max_cert_list) + return s->max_cert_list; + return max_len; +} + +static int +dtls1_reassemble_fragment(SSL *s, struct hm_header_st* msg_hdr, int *ok) +{ + hm_fragment *frag = NULL; + pitem *item = NULL; + int i = -1, is_complete; + unsigned char seq64be[8]; + unsigned long frag_len = msg_hdr->frag_len; + + if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len || + msg_hdr->msg_len > dtls1_max_handshake_message_len(s)) + goto err; + + if (frag_len == 0) { + i = DTLS1_HM_FRAGMENT_RETRY; + goto err; + } + + /* Try to find item in queue */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); + seq64be[7] = (unsigned char)msg_hdr->seq; + item = pqueue_find(s->d1->buffered_messages, seq64be); + + if (item == NULL) { + frag = dtls1_hm_fragment_new(msg_hdr->msg_len, 1); + if (frag == NULL) + goto err; + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + frag->msg_header.frag_len = frag->msg_header.msg_len; + frag->msg_header.frag_off = 0; + } else { + frag = (hm_fragment*)item->data; + if (frag->msg_header.msg_len != msg_hdr->msg_len) { + item = NULL; + frag = NULL; + goto err; + } + } + + /* + * If message is already reassembled, this must be a + * retransmit and can be dropped. + */ + if (frag->reassembly == NULL) { + unsigned char devnull [256]; + + while (frag_len) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + devnull, frag_len > sizeof(devnull) ? + sizeof(devnull) : frag_len, 0); + if (i <= 0) + goto err; + frag_len -= i; + } + i = DTLS1_HM_FRAGMENT_RETRY; + goto err; + } + + /* read the body of the fragment (header has already been read */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + frag->fragment + msg_hdr->frag_off, frag_len, 0); + if (i <= 0 || (unsigned long)i != frag_len) + goto err; + + RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off, + (long)(msg_hdr->frag_off + frag_len)); + + RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len, + is_complete); + + if (is_complete) { + free(frag->reassembly); + frag->reassembly = NULL; + } + + if (item == NULL) { + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); + seq64be[7] = (unsigned char)(msg_hdr->seq); + + item = pitem_new(seq64be, frag); + if (item == NULL) { + i = -1; + goto err; + } + + pqueue_insert(s->d1->buffered_messages, item); + } + + return DTLS1_HM_FRAGMENT_RETRY; + + err: + if (item == NULL && frag != NULL) + dtls1_hm_fragment_free(frag); + *ok = 0; + return i; +} + + +static int +dtls1_process_out_of_seq_message(SSL *s, struct hm_header_st* msg_hdr, int *ok) +{ + int i = -1; + hm_fragment *frag = NULL; + pitem *item = NULL; + unsigned char seq64be[8]; + unsigned long frag_len = msg_hdr->frag_len; + + if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len) + goto err; + + /* Try to find item in queue, to prevent duplicate entries */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char) (msg_hdr->seq >> 8); + seq64be[7] = (unsigned char) msg_hdr->seq; + item = pqueue_find(s->d1->buffered_messages, seq64be); + + /* + * If we already have an entry and this one is a fragment, + * don't discard it and rather try to reassemble it. + */ + if (item != NULL && frag_len < msg_hdr->msg_len) + item = NULL; + + /* + * Discard the message if sequence number was already there, is + * too far in the future, already in the queue or if we received + * a FINISHED before the SERVER_HELLO, which then must be a stale + * retransmit. + */ + if (msg_hdr->seq <= s->d1->handshake_read_seq || + msg_hdr->seq > s->d1->handshake_read_seq + 10 || item != NULL || + (s->d1->handshake_read_seq == 0 && + msg_hdr->type == SSL3_MT_FINISHED)) { + unsigned char devnull [256]; + + while (frag_len) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + devnull, frag_len > sizeof(devnull) ? + sizeof(devnull) : frag_len, 0); + if (i <= 0) + goto err; + frag_len -= i; + } + } else { + if (frag_len < msg_hdr->msg_len) + return dtls1_reassemble_fragment(s, msg_hdr, ok); + + if (frag_len > dtls1_max_handshake_message_len(s)) + goto err; + + frag = dtls1_hm_fragment_new(frag_len, 0); + if (frag == NULL) + goto err; + + memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr)); + + if (frag_len) { + /* read the body of the fragment (header has already been read */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + frag->fragment, frag_len, 0); + if (i <= 0 || (unsigned long)i != frag_len) + goto err; + } + + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(msg_hdr->seq >> 8); + seq64be[7] = (unsigned char)(msg_hdr->seq); + + item = pitem_new(seq64be, frag); + if (item == NULL) + goto err; + + pqueue_insert(s->d1->buffered_messages, item); + } + + return DTLS1_HM_FRAGMENT_RETRY; + + err: + if (item == NULL && frag != NULL) + dtls1_hm_fragment_free(frag); + *ok = 0; + return i; +} + + +static long +dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) +{ + unsigned char wire[DTLS1_HM_HEADER_LENGTH]; + unsigned long len, frag_off, frag_len; + struct hm_header_st msg_hdr; + int i, al; + CBS cbs; + + again: + /* see if we have the required fragment already */ + if ((frag_len = dtls1_retrieve_buffered_fragment(s, max, ok)) || *ok) { + if (*ok) + s->init_num = frag_len; + return frag_len; + } + + /* read handshake message header */ + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, wire, + DTLS1_HM_HEADER_LENGTH, 0); + if (i <= 0) { + /* nbio, or an error */ + s->rwstate = SSL_READING; + *ok = 0; + return i; + } + + CBS_init(&cbs, wire, i); + if (!dtls1_get_message_header(&cbs, &msg_hdr)) { + /* Handshake fails if message header is incomplete. */ + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + + /* + * if this is a future (or stale) message it gets buffered + * (or dropped)--no further processing at this time + * While listening, we accept seq 1 (ClientHello with cookie) + * although we're still expecting seq 0 (ClientHello) + */ + if (msg_hdr.seq != s->d1->handshake_read_seq && + !(s->d1->listen && msg_hdr.seq == 1)) + return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); + + len = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; + frag_len = msg_hdr.frag_len; + + if (frag_len && frag_len < len) + return dtls1_reassemble_fragment(s, &msg_hdr, ok); + + if (!s->server && s->d1->r_msg_hdr.frag_off == 0 && + wire[0] == SSL3_MT_HELLO_REQUEST) { + /* + * The server may always send 'Hello Request' messages -- + * we are doing a handshake anyway now, so ignore them + * if their format is correct. Does not count for + * 'Finished' MAC. + */ + if (wire[1] == 0 && wire[2] == 0 && wire[3] == 0) { + if (s->msg_callback) + s->msg_callback(0, s->version, + SSL3_RT_HANDSHAKE, wire, + DTLS1_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + + s->init_num = 0; + goto again; + } + else /* Incorrectly formatted Hello request */ + { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + } + + if ((al = dtls1_preprocess_fragment(s, &msg_hdr, max))) + goto fatal_err; + + /* XDTLS: resurrect this when restart is in place */ + s->s3->hs.state = stn; + + if (frag_len > 0) { + unsigned char *p = (unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH; + + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + &p[frag_off], frag_len, 0); + /* XDTLS: fix this--message fragments cannot span multiple packets */ + if (i <= 0) { + s->rwstate = SSL_READING; + *ok = 0; + return i; + } + } else + i = 0; + + /* + * XDTLS: an incorrectly formatted fragment should cause the + * handshake to fail + */ + if (i != (int)frag_len) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER); + goto fatal_err; + } + + /* + * Note that s->init_num is *not* used as current offset in + * s->init_buf->data, but as a counter summing up fragments' + * lengths: as soon as they sum up to handshake packet + * length, we assume we have got all the fragments. + */ + s->init_num = frag_len; + *ok = 1; + return frag_len; + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->init_num = 0; + + *ok = 0; + return (-1); +} + +int +dtls1_read_failed(SSL *s, int code) +{ + if (code > 0) { +#ifdef DEBUG + fprintf(stderr, "invalid state reached %s:%d", + __FILE__, __LINE__); +#endif + return 1; + } + + if (!dtls1_is_timer_expired(s)) { + /* + * not a timeout, none of our business, let higher layers + * handle this. in fact it's probably an error + */ + return code; + } + + if (!SSL_in_init(s)) /* done, no need to send a retransmit */ + { + BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ); + return code; + } + + return dtls1_handle_timeout(s); +} + +int +dtls1_get_queue_priority(unsigned short seq, int is_ccs) +{ + /* + * The index of the retransmission queue actually is the message + * sequence number, since the queue only contains messages of a + * single handshake. However, the ChangeCipherSpec has no message + * sequence number and so using only the sequence will result in + * the CCS and Finished having the same index. To prevent this, the + * sequence number is multiplied by 2. In case of a CCS 1 is + * subtracted. This does not only differ CSS and Finished, it also + * maintains the order of the index (important for priority queues) + * and fits in the unsigned short variable. + */ + return seq * 2 - is_ccs; +} + +int +dtls1_retransmit_buffered_messages(SSL *s) +{ + pqueue sent = s->d1->sent_messages; + piterator iter; + pitem *item; + hm_fragment *frag; + int found = 0; + + iter = pqueue_iterator(sent); + + for (item = pqueue_next(&iter); item != NULL; + item = pqueue_next(&iter)) { + frag = (hm_fragment *)item->data; + if (dtls1_retransmit_message(s, + (unsigned short)dtls1_get_queue_priority( + frag->msg_header.seq, frag->msg_header.is_ccs), 0, + &found) <= 0 && found) { +#ifdef DEBUG + fprintf(stderr, "dtls1_retransmit_message() failed\n"); +#endif + return -1; + } + } + + return 1; +} + +int +dtls1_buffer_message(SSL *s, int is_ccs) +{ + pitem *item; + hm_fragment *frag; + unsigned char seq64be[8]; + + /* Buffer the message in order to handle DTLS retransmissions. */ + + /* + * This function is called immediately after a message has + * been serialized + */ + OPENSSL_assert(s->init_off == 0); + + frag = dtls1_hm_fragment_new(s->init_num, 0); + if (frag == NULL) + return 0; + + memcpy(frag->fragment, s->init_buf->data, s->init_num); + + OPENSSL_assert(s->d1->w_msg_hdr.msg_len + + (is_ccs ? DTLS1_CCS_HEADER_LENGTH : DTLS1_HM_HEADER_LENGTH) == + (unsigned int)s->init_num); + + frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.seq = s->d1->w_msg_hdr.seq; + frag->msg_header.type = s->d1->w_msg_hdr.type; + frag->msg_header.frag_off = 0; + frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len; + frag->msg_header.is_ccs = is_ccs; + + /* save current state*/ + frag->msg_header.saved_retransmit_state.session = s->session; + frag->msg_header.saved_retransmit_state.epoch = + tls12_record_layer_write_epoch(s->rl); + + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(dtls1_get_queue_priority( + frag->msg_header.seq, frag->msg_header.is_ccs) >> 8); + seq64be[7] = (unsigned char)(dtls1_get_queue_priority( + frag->msg_header.seq, frag->msg_header.is_ccs)); + + item = pitem_new(seq64be, frag); + if (item == NULL) { + dtls1_hm_fragment_free(frag); + return 0; + } + + pqueue_insert(s->d1->sent_messages, item); + return 1; +} + +int +dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, + int *found) +{ + int ret; + /* XDTLS: for now assuming that read/writes are blocking */ + pitem *item; + hm_fragment *frag; + unsigned long header_length; + unsigned char seq64be[8]; + struct dtls1_retransmit_state saved_state; + + /* + OPENSSL_assert(s->init_num == 0); + OPENSSL_assert(s->init_off == 0); + */ + + /* XDTLS: the requested message ought to be found, otherwise error */ + memset(seq64be, 0, sizeof(seq64be)); + seq64be[6] = (unsigned char)(seq >> 8); + seq64be[7] = (unsigned char)seq; + + item = pqueue_find(s->d1->sent_messages, seq64be); + if (item == NULL) { +#ifdef DEBUG + fprintf(stderr, "retransmit: message %d non-existent\n", seq); +#endif + *found = 0; + return 0; + } + + *found = 1; + frag = (hm_fragment *)item->data; + + if (frag->msg_header.is_ccs) + header_length = DTLS1_CCS_HEADER_LENGTH; + else + header_length = DTLS1_HM_HEADER_LENGTH; + + memcpy(s->init_buf->data, frag->fragment, + frag->msg_header.msg_len + header_length); + s->init_num = frag->msg_header.msg_len + header_length; + + dtls1_set_message_header_int(s, frag->msg_header.type, + frag->msg_header.msg_len, frag->msg_header.seq, 0, + frag->msg_header.frag_len); + + /* save current state */ + saved_state.session = s->session; + saved_state.epoch = tls12_record_layer_write_epoch(s->rl); + + s->d1->retransmitting = 1; + + /* restore state in which the message was originally sent */ + s->session = frag->msg_header.saved_retransmit_state.session; + if (!tls12_record_layer_use_write_epoch(s->rl, + frag->msg_header.saved_retransmit_state.epoch)) + return 0; + + ret = dtls1_do_write(s, frag->msg_header.is_ccs ? + SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE); + + /* restore current state */ + s->session = saved_state.session; + if (!tls12_record_layer_use_write_epoch(s->rl, + saved_state.epoch)) + return 0; + + s->d1->retransmitting = 0; + + (void)BIO_flush(SSL_get_wbio(s)); + return ret; +} + +/* call this function when the buffered messages are no longer needed */ +void +dtls1_clear_record_buffer(SSL *s) +{ + hm_fragment *frag; + pitem *item; + + for(item = pqueue_pop(s->d1->sent_messages); item != NULL; + item = pqueue_pop(s->d1->sent_messages)) { + frag = item->data; + if (frag->msg_header.is_ccs) + tls12_record_layer_write_epoch_done(s->rl, + frag->msg_header.saved_retransmit_state.epoch); + dtls1_hm_fragment_free(frag); + pitem_free(item); + } +} + +void +dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, + unsigned long frag_off, unsigned long frag_len) +{ + /* Don't change sequence numbers while listening */ + if (frag_off == 0 && !s->d1->listen) { + s->d1->handshake_write_seq = s->d1->next_handshake_write_seq; + s->d1->next_handshake_write_seq++; + } + + dtls1_set_message_header_int(s, mt, len, s->d1->handshake_write_seq, + frag_off, frag_len); +} + +/* don't actually do the writing, wait till the MTU has been retrieved */ +void +dtls1_set_message_header_int(SSL *s, unsigned char mt, unsigned long len, + unsigned short seq_num, unsigned long frag_off, unsigned long frag_len) +{ + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->type = mt; + msg_hdr->msg_len = len; + msg_hdr->seq = seq_num; + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; +} + +static void +dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len) +{ + struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr; + + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; +} + +static int +dtls1_write_message_header(const struct hm_header_st *msg_hdr, + unsigned long frag_off, unsigned long frag_len, unsigned char *p) +{ + CBB cbb; + + /* We assume DTLS1_HM_HEADER_LENGTH bytes are available for now... */ + if (!CBB_init_fixed(&cbb, p, DTLS1_HM_HEADER_LENGTH)) + return 0; + if (!CBB_add_u8(&cbb, msg_hdr->type)) + goto err; + if (!CBB_add_u24(&cbb, msg_hdr->msg_len)) + goto err; + if (!CBB_add_u16(&cbb, msg_hdr->seq)) + goto err; + if (!CBB_add_u24(&cbb, frag_off)) + goto err; + if (!CBB_add_u24(&cbb, frag_len)) + goto err; + if (!CBB_finish(&cbb, NULL, NULL)) + goto err; + + return 1; + + err: + CBB_cleanup(&cbb); + return 0; +} + +unsigned int +dtls1_min_mtu(void) +{ + return (g_probable_mtu[(sizeof(g_probable_mtu) / + sizeof(g_probable_mtu[0])) - 1]); +} + +static unsigned int +dtls1_guess_mtu(unsigned int curr_mtu) +{ + unsigned int i; + + if (curr_mtu == 0) + return g_probable_mtu[0]; + + for (i = 0; i < sizeof(g_probable_mtu) / sizeof(g_probable_mtu[0]); i++) + if (curr_mtu > g_probable_mtu[i]) + return g_probable_mtu[i]; + + return curr_mtu; +} + +int +dtls1_get_message_header(CBS *header, struct hm_header_st *msg_hdr) +{ + uint32_t msg_len, frag_off, frag_len; + uint16_t seq; + uint8_t type; + + memset(msg_hdr, 0, sizeof(*msg_hdr)); + + if (!CBS_get_u8(header, &type)) + return 0; + if (!CBS_get_u24(header, &msg_len)) + return 0; + if (!CBS_get_u16(header, &seq)) + return 0; + if (!CBS_get_u24(header, &frag_off)) + return 0; + if (!CBS_get_u24(header, &frag_len)) + return 0; + + msg_hdr->type = type; + msg_hdr->msg_len = msg_len; + msg_hdr->seq = seq; + msg_hdr->frag_off = frag_off; + msg_hdr->frag_len = frag_len; + + return 1; +} diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c new file mode 100644 index 0000000..ae6a665 --- /dev/null +++ b/ssl/d1_lib.c @@ -0,0 +1,435 @@ +/* $OpenBSD: d1_lib.c,v 1.64 2022/11/26 16:08:55 tb Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include + +#include + +#include + +#include + +#include "dtls_local.h" +#include "pqueue.h" +#include "ssl_local.h" + +void dtls1_hm_fragment_free(hm_fragment *frag); + +static int dtls1_listen(SSL *s, struct sockaddr *client); + +int +dtls1_new(SSL *s) +{ + if (!ssl3_new(s)) + goto err; + + if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL) + goto err; + + if ((s->d1->unprocessed_rcds.q = pqueue_new()) == NULL) + goto err; + if ((s->d1->buffered_messages = pqueue_new()) == NULL) + goto err; + if ((s->d1->sent_messages = pqueue_new()) == NULL) + goto err; + if ((s->d1->buffered_app_data.q = pqueue_new()) == NULL) + goto err; + + if (s->server) + s->d1->cookie_len = sizeof(s->d1->cookie); + + s->method->ssl_clear(s); + return (1); + + err: + dtls1_free(s); + return (0); +} + +static void +dtls1_drain_rcontents(pqueue queue) +{ + DTLS1_RCONTENT_DATA_INTERNAL *rdata; + pitem *item; + + if (queue == NULL) + return; + + while ((item = pqueue_pop(queue)) != NULL) { + rdata = (DTLS1_RCONTENT_DATA_INTERNAL *)item->data; + tls_content_free(rdata->rcontent); + free(item->data); + pitem_free(item); + } +} + +static void +dtls1_drain_records(pqueue queue) +{ + pitem *item; + DTLS1_RECORD_DATA_INTERNAL *rdata; + + if (queue == NULL) + return; + + while ((item = pqueue_pop(queue)) != NULL) { + rdata = (DTLS1_RECORD_DATA_INTERNAL *)item->data; + ssl3_release_buffer(&rdata->rbuf); + free(item->data); + pitem_free(item); + } +} + +static void +dtls1_drain_fragments(pqueue queue) +{ + pitem *item; + + if (queue == NULL) + return; + + while ((item = pqueue_pop(queue)) != NULL) { + dtls1_hm_fragment_free(item->data); + pitem_free(item); + } +} + +static void +dtls1_clear_queues(SSL *s) +{ + dtls1_drain_records(s->d1->unprocessed_rcds.q); + dtls1_drain_fragments(s->d1->buffered_messages); + dtls1_drain_fragments(s->d1->sent_messages); + dtls1_drain_rcontents(s->d1->buffered_app_data.q); +} + +void +dtls1_free(SSL *s) +{ + if (s == NULL) + return; + + ssl3_free(s); + + if (s->d1 == NULL) + return; + + dtls1_clear_queues(s); + + pqueue_free(s->d1->unprocessed_rcds.q); + pqueue_free(s->d1->buffered_messages); + pqueue_free(s->d1->sent_messages); + pqueue_free(s->d1->buffered_app_data.q); + + freezero(s->d1, sizeof(*s->d1)); + s->d1 = NULL; +} + +void +dtls1_clear(SSL *s) +{ + pqueue unprocessed_rcds; + pqueue buffered_messages; + pqueue sent_messages; + pqueue buffered_app_data; + unsigned int mtu; + + if (s->d1) { + unprocessed_rcds = s->d1->unprocessed_rcds.q; + buffered_messages = s->d1->buffered_messages; + sent_messages = s->d1->sent_messages; + buffered_app_data = s->d1->buffered_app_data.q; + mtu = s->d1->mtu; + + dtls1_clear_queues(s); + + memset(s->d1, 0, sizeof(*s->d1)); + + s->d1->unprocessed_rcds.epoch = + tls12_record_layer_read_epoch(s->rl) + 1; + + if (s->server) { + s->d1->cookie_len = sizeof(s->d1->cookie); + } + + if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { + s->d1->mtu = mtu; + } + + s->d1->unprocessed_rcds.q = unprocessed_rcds; + s->d1->buffered_messages = buffered_messages; + s->d1->sent_messages = sent_messages; + s->d1->buffered_app_data.q = buffered_app_data; + } + + ssl3_clear(s); + + s->version = DTLS1_VERSION; +} + +long +dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + int ret = 0; + + switch (cmd) { + case DTLS_CTRL_GET_TIMEOUT: + if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) { + ret = 1; + } + break; + case DTLS_CTRL_HANDLE_TIMEOUT: + ret = dtls1_handle_timeout(s); + break; + case DTLS_CTRL_LISTEN: + ret = dtls1_listen(s, parg); + break; + + default: + ret = ssl3_ctrl(s, cmd, larg, parg); + break; + } + return (ret); +} + +/* + * As it's impossible to use stream ciphers in "datagram" mode, this + * simple filter is designed to disengage them in DTLS. Unfortunately + * there is no universal way to identify stream SSL_CIPHER, so we have + * to explicitly list their SSL_* codes. Currently RC4 is the only one + * available, but if new ones emerge, they will have to be added... + */ +const SSL_CIPHER * +dtls1_get_cipher(unsigned int u) +{ + const SSL_CIPHER *cipher; + + if ((cipher = ssl3_get_cipher(u)) == NULL) + return NULL; + + if (cipher->algorithm_enc == SSL_RC4) + return NULL; + + return cipher; +} + +void +dtls1_start_timer(SSL *s) +{ + + /* If timer is not set, initialize duration with 1 second */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { + s->d1->timeout_duration = 1; + } + + /* Set timeout to current time */ + gettimeofday(&(s->d1->next_timeout), NULL); + + /* Add duration to current time */ + s->d1->next_timeout.tv_sec += s->d1->timeout_duration; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &s->d1->next_timeout); +} + +struct timeval* +dtls1_get_timeout(SSL *s, struct timeval* timeleft) +{ + struct timeval timenow; + + /* If no timeout is set, just return NULL */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { + return NULL; + } + + /* Get current time */ + gettimeofday(&timenow, NULL); + + /* If timer already expired, set remaining time to 0 */ + if (s->d1->next_timeout.tv_sec < timenow.tv_sec || + (s->d1->next_timeout.tv_sec == timenow.tv_sec && + s->d1->next_timeout.tv_usec <= timenow.tv_usec)) { + memset(timeleft, 0, sizeof(struct timeval)); + return timeleft; + } + + /* Calculate time left until timer expires */ + memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval)); + timeleft->tv_sec -= timenow.tv_sec; + timeleft->tv_usec -= timenow.tv_usec; + if (timeleft->tv_usec < 0) { + timeleft->tv_sec--; + timeleft->tv_usec += 1000000; + } + + /* If remaining time is less than 15 ms, set it to 0 + * to prevent issues because of small devergences with + * socket timeouts. + */ + if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) { + memset(timeleft, 0, sizeof(struct timeval)); + } + + + return timeleft; +} + +int +dtls1_is_timer_expired(SSL *s) +{ + struct timeval timeleft; + + /* Get time left until timeout, return false if no timer running */ + if (dtls1_get_timeout(s, &timeleft) == NULL) { + return 0; + } + + /* Return false if timer is not expired yet */ + if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) { + return 0; + } + + /* Timer expired, so return true */ + return 1; +} + +void +dtls1_double_timeout(SSL *s) +{ + s->d1->timeout_duration *= 2; + if (s->d1->timeout_duration > 60) + s->d1->timeout_duration = 60; + dtls1_start_timer(s); +} + +void +dtls1_stop_timer(SSL *s) +{ + /* Reset everything */ + memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st)); + memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); + s->d1->timeout_duration = 1; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, + &(s->d1->next_timeout)); + /* Clear retransmission buffer */ + dtls1_clear_record_buffer(s); +} + +int +dtls1_check_timeout_num(SSL *s) +{ + s->d1->timeout.num_alerts++; + + /* Reduce MTU after 2 unsuccessful retransmissions */ + if (s->d1->timeout.num_alerts > 2) { + s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), + BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); + + } + + if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { + /* fail the connection, enough alerts have been sent */ + SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED); + return -1; + } + + return 0; +} + +int +dtls1_handle_timeout(SSL *s) +{ + /* if no timer is expired, don't do anything */ + if (!dtls1_is_timer_expired(s)) { + return 0; + } + + dtls1_double_timeout(s); + + if (dtls1_check_timeout_num(s) < 0) + return -1; + + s->d1->timeout.read_timeouts++; + if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { + s->d1->timeout.read_timeouts = 1; + } + + dtls1_start_timer(s); + return dtls1_retransmit_buffered_messages(s); +} + +int +dtls1_listen(SSL *s, struct sockaddr *client) +{ + int ret; + + /* Ensure there is no state left over from a previous invocation */ + SSL_clear(s); + + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); + s->d1->listen = 1; + + ret = SSL_accept(s); + if (ret <= 0) + return ret; + + (void)BIO_dgram_get_peer(SSL_get_rbio(s), client); + return 1; +} diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c new file mode 100644 index 0000000..df9581a --- /dev/null +++ b/ssl/d1_pkt.c @@ -0,0 +1,1116 @@ +/* $OpenBSD: d1_pkt.c,v 1.128 2023/07/02 20:16:47 tb Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include +#include + +#include "bytestring.h" +#include "dtls_local.h" +#include "pqueue.h" +#include "ssl_local.h" +#include "tls_content.h" + +/* mod 128 saturating subtract of two 64-bit values in big-endian order */ +static int +satsub64be(const unsigned char *v1, const unsigned char *v2) +{ + int ret, sat, brw, i; + + if (sizeof(long) == 8) + do { + long l; + + if (BYTE_ORDER == LITTLE_ENDIAN) + break; + /* not reached on little-endians */ + /* following test is redundant, because input is + * always aligned, but I take no chances... */ + if (((size_t)v1 | (size_t)v2) & 0x7) + break; + + l = *((long *)v1); + l -= *((long *)v2); + if (l > 128) + return 128; + else if (l<-128) + return -128; + else + return (int)l; + } while (0); + + ret = (int)v1[7] - (int)v2[7]; + sat = 0; + brw = ret >> 8; /* brw is either 0 or -1 */ + if (ret & 0x80) { + for (i = 6; i >= 0; i--) { + brw += (int)v1[i]-(int)v2[i]; + sat |= ~brw; + brw >>= 8; + } + } else { + for (i = 6; i >= 0; i--) { + brw += (int)v1[i]-(int)v2[i]; + sat |= brw; + brw >>= 8; + } + } + brw <<= 8; /* brw is either 0 or -256 */ + + if (sat & 0xff) + return brw | 0x80; + else + return brw + (ret & 0xFF); +} + +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, + const unsigned char *seq); +static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap, + const unsigned char *seq); +static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD_INTERNAL *rr, + unsigned int *is_next_epoch); +static int dtls1_buffer_record(SSL *s, record_pqueue *q, + unsigned char *priority); +static int dtls1_process_record(SSL *s); + +/* copy buffered record into SSL structure */ +static int +dtls1_copy_record(SSL *s, DTLS1_RECORD_DATA_INTERNAL *rdata) +{ + ssl3_release_buffer(&s->s3->rbuf); + + s->packet = rdata->packet; + s->packet_length = rdata->packet_length; + memcpy(&(s->s3->rbuf), &(rdata->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); + memcpy(&(s->s3->rrec), &(rdata->rrec), sizeof(SSL3_RECORD_INTERNAL)); + + return (1); +} + +static int +dtls1_buffer_record(SSL *s, record_pqueue *queue, unsigned char *priority) +{ + DTLS1_RECORD_DATA_INTERNAL *rdata = NULL; + pitem *item = NULL; + + /* Limit the size of the queue to prevent DOS attacks */ + if (pqueue_size(queue->q) >= 100) + return 0; + + if ((rdata = malloc(sizeof(*rdata))) == NULL) + goto init_err; + if ((item = pitem_new(priority, rdata)) == NULL) + goto init_err; + + rdata->packet = s->packet; + rdata->packet_length = s->packet_length; + memcpy(&(rdata->rbuf), &(s->s3->rbuf), sizeof(SSL3_BUFFER_INTERNAL)); + memcpy(&(rdata->rrec), &(s->s3->rrec), sizeof(SSL3_RECORD_INTERNAL)); + + item->data = rdata; + + s->packet = NULL; + s->packet_length = 0; + memset(&(s->s3->rbuf), 0, sizeof(SSL3_BUFFER_INTERNAL)); + memset(&(s->s3->rrec), 0, sizeof(SSL3_RECORD_INTERNAL)); + + if (!ssl3_setup_buffers(s)) + goto err; + + /* insert should not fail, since duplicates are dropped */ + if (pqueue_insert(queue->q, item) == NULL) + goto err; + + return (1); + + err: + ssl3_release_buffer(&rdata->rbuf); + + init_err: + SSLerror(s, ERR_R_INTERNAL_ERROR); + free(rdata); + pitem_free(item); + return (-1); +} + +static int +dtls1_buffer_rcontent(SSL *s, rcontent_pqueue *queue, unsigned char *priority) +{ + DTLS1_RCONTENT_DATA_INTERNAL *rdata = NULL; + pitem *item = NULL; + + /* Limit the size of the queue to prevent DOS attacks */ + if (pqueue_size(queue->q) >= 100) + return 0; + + if ((rdata = malloc(sizeof(*rdata))) == NULL) + goto init_err; + if ((item = pitem_new(priority, rdata)) == NULL) + goto init_err; + + rdata->rcontent = s->s3->rcontent; + s->s3->rcontent = NULL; + + item->data = rdata; + + /* insert should not fail, since duplicates are dropped */ + if (pqueue_insert(queue->q, item) == NULL) + goto err; + + if ((s->s3->rcontent = tls_content_new()) == NULL) + goto err; + + return (1); + + err: + tls_content_free(rdata->rcontent); + + init_err: + SSLerror(s, ERR_R_INTERNAL_ERROR); + free(rdata); + pitem_free(item); + return (-1); +} + +static int +dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) +{ + pitem *item; + + item = pqueue_pop(queue->q); + if (item) { + dtls1_copy_record(s, item->data); + + free(item->data); + pitem_free(item); + + return (1); + } + + return (0); +} + +static int +dtls1_retrieve_buffered_rcontent(SSL *s, rcontent_pqueue *queue) +{ + DTLS1_RCONTENT_DATA_INTERNAL *rdata; + pitem *item; + + item = pqueue_pop(queue->q); + if (item) { + rdata = item->data; + + tls_content_free(s->s3->rcontent); + s->s3->rcontent = rdata->rcontent; + s->s3->rrec.epoch = tls_content_epoch(s->s3->rcontent); + + free(item->data); + pitem_free(item); + + return (1); + } + + return (0); +} + +static int +dtls1_process_buffered_record(SSL *s) +{ + /* Check if epoch is current. */ + if (s->d1->unprocessed_rcds.epoch != + tls12_record_layer_read_epoch(s->rl)) + return (0); + + /* Update epoch once all unprocessed records have been processed. */ + if (pqueue_peek(s->d1->unprocessed_rcds.q) == NULL) { + s->d1->unprocessed_rcds.epoch = + tls12_record_layer_read_epoch(s->rl) + 1; + return (0); + } + + /* Process one of the records. */ + if (!dtls1_retrieve_buffered_record(s, &s->d1->unprocessed_rcds)) + return (-1); + if (!dtls1_process_record(s)) + return (-1); + + return (1); +} + +static int +dtls1_process_record(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); + uint8_t alert_desc; + + tls12_record_layer_set_version(s->rl, s->version); + + if (!tls12_record_layer_open_record(s->rl, s->packet, s->packet_length, + s->s3->rcontent)) { + tls12_record_layer_alert(s->rl, &alert_desc); + + if (alert_desc == 0) + goto err; + + /* + * DTLS should silently discard invalid records, including those + * with a bad MAC, as per RFC 6347 section 4.1.2.1. + */ + if (alert_desc == SSL_AD_BAD_RECORD_MAC) + goto done; + + if (alert_desc == SSL_AD_RECORD_OVERFLOW) + SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + + goto fatal_err; + } + + /* XXX move to record layer. */ + tls_content_set_epoch(s->s3->rcontent, rr->epoch); + + done: + s->packet_length = 0; + + return (1); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, alert_desc); + err: + return (0); +} + +/* Call this to get a new input record. + * It will return <= 0 if more data is needed, normally due to an error + * or non-blocking IO. + * When it finishes, one packet has been decoded and can be found in + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data + * ssl->s3->rrec.length, - number of bytes + */ +/* used only by dtls1_read_bytes */ +int +dtls1_get_record(SSL *s) +{ + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); + unsigned char *p = NULL; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int ret, n; + + /* See if there are pending records that can now be processed. */ + if ((ret = dtls1_process_buffered_record(s)) != 0) + return (ret); + + /* get something from the wire */ + if (0) { + again: + /* dump this record on all retries */ + rr->length = 0; + s->packet_length = 0; + } + + /* check if we have the header */ + if ((s->rstate != SSL_ST_READ_BODY) || + (s->packet_length < DTLS1_RT_HEADER_LENGTH)) { + CBS header, seq_no; + uint16_t epoch, len, ssl_version; + uint8_t type; + + n = ssl3_packet_read(s, DTLS1_RT_HEADER_LENGTH); + if (n <= 0) + return (n); + + /* If this packet contained a partial record, dump it. */ + if (n != DTLS1_RT_HEADER_LENGTH) + goto again; + + s->rstate = SSL_ST_READ_BODY; + + CBS_init(&header, s->packet, s->packet_length); + + /* Pull apart the header into the DTLS1_RECORD */ + if (!CBS_get_u8(&header, &type)) + goto again; + if (!CBS_get_u16(&header, &ssl_version)) + goto again; + + /* Sequence number is 64 bits, with top 2 bytes = epoch. */ + if (!CBS_get_bytes(&header, &seq_no, SSL3_SEQUENCE_SIZE)) + goto again; + if (!CBS_get_u16(&seq_no, &epoch)) + goto again; + if (!CBS_write_bytes(&seq_no, &rr->seq_num[2], + sizeof(rr->seq_num) - 2, NULL)) + goto again; + + if (!CBS_get_u16(&header, &len)) + goto again; + + rr->type = type; + rr->epoch = epoch; + rr->length = len; + + /* unexpected version, silently discard */ + if (!s->first_packet && ssl_version != s->version) + goto again; + + /* wrong version, silently discard record */ + if ((ssl_version & 0xff00) != (s->version & 0xff00)) + goto again; + + /* record too long, silently discard it */ + if (rr->length > SSL3_RT_MAX_ENCRYPTED_LENGTH) + goto again; + + /* now s->rstate == SSL_ST_READ_BODY */ + p = (unsigned char *)CBS_data(&header); + } + + /* s->rstate == SSL_ST_READ_BODY, get and decode the data */ + + n = ssl3_packet_extend(s, DTLS1_RT_HEADER_LENGTH + rr->length); + if (n <= 0) + return (n); + + /* If this packet contained a partial record, dump it. */ + if (n != DTLS1_RT_HEADER_LENGTH + rr->length) + goto again; + + s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */ + + /* match epochs. NULL means the packet is dropped on the floor */ + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) + goto again; + + /* + * Check whether this is a repeat, or aged record. + * Don't check if we're listening and this message is + * a ClientHello. They can look as if they're replayed, + * since they arrive from different connections and + * would be dropped unnecessarily. + */ + if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE && + p != NULL && *p == SSL3_MT_CLIENT_HELLO) && + !dtls1_record_replay_check(s, bitmap, rr->seq_num)) + goto again; + + /* just read a 0 length packet */ + if (rr->length == 0) + goto again; + + /* If this record is from the next epoch (either HM or ALERT), + * and a handshake is currently in progress, buffer it since it + * cannot be processed at this time. However, do not buffer + * anything while listening. + */ + if (is_next_epoch) { + if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) { + if (dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), + rr->seq_num) < 0) + return (-1); + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap, rr->seq_num); + } + goto again; + } + + if (!dtls1_process_record(s)) + goto again; + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap, rr->seq_num); + + return (1); +} + +static int +dtls1_read_handshake_unexpected(SSL *s) +{ + struct hm_header_st hs_msg_hdr; + CBS cbs; + int ret; + + if (s->in_handshake) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Parse handshake message header. */ + CBS_dup(tls_content_cbs(s->s3->rcontent), &cbs); + if (!dtls1_get_message_header(&cbs, &hs_msg_hdr)) + return -1; /* XXX - probably should drop/continue. */ + + /* This may just be a stale retransmit. */ + if (tls_content_epoch(s->s3->rcontent) != + tls12_record_layer_read_epoch(s->rl)) { + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + return 1; + } + + if (hs_msg_hdr.type == SSL3_MT_HELLO_REQUEST) { + /* + * Incoming HelloRequest messages should only be received by a + * client. A server may send these at any time - a client should + * ignore the message if received in the middle of a handshake. + * See RFC 5246 sections 7.4 and 7.4.1.1. + */ + if (s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* XXX - should also check frag offset/length. */ + if (hs_msg_hdr.msg_len != 0) { + SSLerror(s, SSL_R_BAD_HELLO_REQUEST); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + + ssl_msg_callback_cbs(s, 0, SSL3_RT_HANDSHAKE, + tls_content_cbs(s->s3->rcontent)); + + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + + /* + * It should be impossible to hit this, but keep the safety + * harness for now... + */ + if (s->session == NULL || s->session->cipher == NULL) + return 1; + + /* + * Ignore this message if we're currently handshaking, + * renegotiation is already pending or renegotiation is disabled + * via flags. + */ + if (!SSL_is_init_finished(s) || s->s3->renegotiate || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) + return 1; + + s->d1->handshake_read_seq++; + + /* XXX - why is this set here but not in ssl3? */ + s->new_session = 1; + + if (!ssl3_renegotiate(s)) + return 1; + if (!ssl3_renegotiate_check(s)) + return 1; + + } else if (hs_msg_hdr.type == SSL3_MT_CLIENT_HELLO) { + /* + * Incoming ClientHello messages should only be received by a + * server. A client may send these in response to server + * initiated renegotiation (HelloRequest) or in order to + * initiate renegotiation by the client. See RFC 5246 section + * 7.4.1.2. + */ + if (!s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* + * A client should not be sending a ClientHello unless we're not + * currently handshaking. + */ + if (!SSL_is_init_finished(s)) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((s->options & SSL_OP_NO_CLIENT_RENEGOTIATION) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_NO_RENEGOTIATION); + return -1; + } + + if (s->session == NULL || s->session->cipher == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Client requested renegotiation but it is not permitted. */ + if (!s->s3->send_connection_binding || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) { + ssl3_send_alert(s, SSL3_AL_WARNING, + SSL_AD_NO_RENEGOTIATION); + return 1; + } + + s->s3->hs.state = SSL_ST_ACCEPT; + s->renegotiate = 1; + s->new_session = 1; + + } else if (hs_msg_hdr.type == SSL3_MT_FINISHED && s->server) { + /* + * If we are server, we may have a repeated FINISHED of the + * client here, then retransmit our CCS and FINISHED. + */ + if (dtls1_check_timeout_num(s) < 0) + return -1; + + /* XXX - should this be calling ssl_msg_callback()? */ + + dtls1_retransmit_buffered_messages(s); + + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + + return 1; + + } else { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((ret = s->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (s->s3->rbuf.left == 0) { + ssl_force_want_read(s); + return -1; + } + } + + /* + * We either finished a handshake or ignored the request, now try again + * to obtain the (application) data we were asked for. + */ + return 1; +} + +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + * - 0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify), ChangeCipherSpec records (not really + * a surprise, but handled as if it were), or renegotiation requests. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + * Change cipher spec protocol + * just 1 byte needed, no need for keeping anything stored + * Alert protocol + * 2 bytes needed (AlertLevel, AlertDescription) + * Handshake protocol + * 4 bytes needed (HandshakeType, uint24 length) -- we just have + * to detect unexpected Client Hello and Hello Request messages + * here, anything else is handled by higher layers + * Application data protocol + * none of our business + */ +int +dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) +{ + int rrcount = 0; + ssize_t ssret; + int ret; + + if (s->s3->rbuf.buf == NULL) { + if (!ssl3_setup_buffers(s)) + return -1; + } + + if (s->s3->rcontent == NULL) { + if ((s->s3->rcontent = tls_content_new()) == NULL) + return -1; + } + + if (len < 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (type != 0 && type != SSL3_RT_APPLICATION_DATA && + type != SSL3_RT_HANDSHAKE) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + if (peek && type != SSL3_RT_APPLICATION_DATA) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (SSL_in_init(s) && !s->in_handshake) { + if ((ret = s->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + start: + /* + * Do not process more than three consecutive records, otherwise the + * peer can cause us to loop indefinitely. Instead, return with an + * SSL_ERROR_WANT_READ so the caller can choose when to handle further + * processing. In the future, the total number of non-handshake and + * non-application data records per connection should probably also be + * limited... + */ + if (rrcount++ >= 3) { + ssl_force_want_read(s); + return -1; + } + + s->rwstate = SSL_NOTHING; + + /* + * We are not handshaking and have no data yet, so process data buffered + * during the last handshake in advance, if any. + */ + if (s->s3->hs.state == SSL_ST_OK && + tls_content_remaining(s->s3->rcontent) == 0) + dtls1_retrieve_buffered_rcontent(s, &s->d1->buffered_app_data); + + if (dtls1_handle_timeout(s) > 0) + goto start; + + if (tls_content_remaining(s->s3->rcontent) == 0) { + if ((ret = dtls1_get_record(s)) <= 0) { + /* Anything other than a timeout is an error. */ + if ((ret = dtls1_read_failed(s, ret)) <= 0) + return ret; + goto start; + } + } + + if (s->d1->listen && + tls_content_type(s->s3->rcontent) != SSL3_RT_HANDSHAKE) { + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + goto start; + } + + /* We now have a packet which can be read and processed. */ + + if (s->s3->change_cipher_spec && + tls_content_type(s->s3->rcontent) != SSL3_RT_HANDSHAKE) { + /* + * We now have application data between CCS and Finished. + * Most likely the packets were reordered on their way, so + * buffer the application data for later processing rather + * than dropping the connection. + */ + if (dtls1_buffer_rcontent(s, &s->d1->buffered_app_data, + s->s3->rrec.seq_num) < 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return (-1); + } + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + goto start; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode). + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + return 0; + } + + /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ + if (tls_content_type(s->s3->rcontent) == type) { + /* + * Make sure that we are not getting application data when we + * are doing a handshake for the first time. + */ + if (SSL_in_init(s) && type == SSL3_RT_APPLICATION_DATA && + !tls12_record_layer_read_protected(s->rl)) { + SSLerror(s, SSL_R_APP_DATA_IN_HANDSHAKE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if (len <= 0) + return len; + + if (peek) { + ssret = tls_content_peek(s->s3->rcontent, buf, len); + } else { + ssret = tls_content_read(s->s3->rcontent, buf, len); + } + if (ssret < INT_MIN || ssret > INT_MAX) + return -1; + if (ssret < 0) + return (int)ssret; + + if (tls_content_remaining(s->s3->rcontent) == 0) + s->rstate = SSL_ST_READ_HEADER; + + return (int)ssret; + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_ALERT) { + if ((ret = ssl3_read_alert(s)) <= 0) + return ret; + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + return (0); + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_APPLICATION_DATA) { + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside + * ssl3_read() (i.e. in_read_app_data is set) and it makes + * sense to read application data at this point (session + * renegotiation not yet started), we will indulge it. + */ + if (s->s3->in_read_app_data != 0 && + s->s3->total_renegotiations != 0 && + (((s->s3->hs.state & SSL_ST_CONNECT) && + (s->s3->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && + (s->s3->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || ( + (s->s3->hs.state & SSL_ST_ACCEPT) && + (s->s3->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && + (s->s3->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_CHANGE_CIPHER_SPEC) { + if ((ret = ssl3_read_change_cipher_spec(s)) <= 0) + return ret; + goto start; + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_HANDSHAKE) { + if ((ret = dtls1_read_handshake_unexpected(s)) <= 0) + return ret; + goto start; + } + + /* Unknown record type. */ + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; +} + +int +dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, int len) +{ + int i; + + if (SSL_in_init(s) && !s->in_handshake) { + i = s->handshake_func(s); + if (i < 0) + return (i); + if (i == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + if (len > SSL3_RT_MAX_PLAIN_LENGTH) { + SSLerror(s, SSL_R_DTLS_MESSAGE_TOO_BIG); + return -1; + } + + i = dtls1_write_bytes(s, type, buf_, len); + return i; +} + +/* Call this to write data in records of type 'type' + * It will return <= 0 if not all data has been sent or non-blocking IO. + */ +int +dtls1_write_bytes(SSL *s, int type, const void *buf, int len) +{ + int i; + + OPENSSL_assert(len <= SSL3_RT_MAX_PLAIN_LENGTH); + s->rwstate = SSL_NOTHING; + i = do_dtls1_write(s, type, buf, len); + return i; +} + +int +do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len) +{ + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); + size_t out_len; + CBB cbb; + int ret; + + memset(&cbb, 0, sizeof(cbb)); + + /* + * First check if there is a SSL3_BUFFER_INTERNAL still being written + * out. This will happen with non blocking IO. + */ + if (wb->left != 0) { + OPENSSL_assert(0); /* XDTLS: want to see if we ever get here */ + return (ssl3_write_pending(s, type, buf, len)); + } + + /* If we have an alert to send, let's send it */ + if (s->s3->alert_dispatch) { + if ((ret = ssl3_dispatch_alert(s)) <= 0) + return (ret); + /* If it went, fall through and send more stuff. */ + } + + if (len == 0) + return 0; + + wb->offset = 0; + + if (!CBB_init_fixed(&cbb, wb->buf, wb->len)) + goto err; + + tls12_record_layer_set_version(s->rl, s->version); + + if (!tls12_record_layer_seal_record(s->rl, type, buf, len, &cbb)) + goto err; + + if (!CBB_finish(&cbb, NULL, &out_len)) + goto err; + + wb->left = out_len; + + /* + * Memorize arguments so that ssl3_write_pending can detect + * bad write retries later. + */ + s->s3->wpend_tot = len; + s->s3->wpend_buf = buf; + s->s3->wpend_type = type; + s->s3->wpend_ret = len; + + /* We now just need to write the buffer. */ + return ssl3_write_pending(s, type, buf, len); + + err: + CBB_cleanup(&cbb); + + return -1; +} + +static int +dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, + const unsigned char *seq) +{ + unsigned int shift; + int cmp; + + cmp = satsub64be(seq, bitmap->max_seq_num); + if (cmp > 0) + return 1; /* this record in new */ + shift = -cmp; + if (shift >= sizeof(bitmap->map)*8) + return 0; /* stale, outside the window */ + else if (bitmap->map & (1UL << shift)) + return 0; /* record previously received */ + + return 1; +} + +static void +dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap, + const unsigned char *seq) +{ + unsigned int shift; + int cmp; + + cmp = satsub64be(seq, bitmap->max_seq_num); + if (cmp > 0) { + shift = cmp; + if (shift < sizeof(bitmap->map)*8) + bitmap->map <<= shift, bitmap->map |= 1UL; + else + bitmap->map = 1UL; + memcpy(bitmap->max_seq_num, seq, 8); + } else { + shift = -cmp; + if (shift < sizeof(bitmap->map) * 8) + bitmap->map |= 1UL << shift; + } +} + +static DTLS1_BITMAP * +dtls1_get_bitmap(SSL *s, SSL3_RECORD_INTERNAL *rr, unsigned int *is_next_epoch) +{ + uint16_t read_epoch, read_epoch_next; + + *is_next_epoch = 0; + + read_epoch = tls12_record_layer_read_epoch(s->rl); + read_epoch_next = read_epoch + 1; + + /* In current epoch, accept HM, CCS, DATA, & ALERT */ + if (rr->epoch == read_epoch) + return &s->d1->bitmap; + + /* Only HM and ALERT messages can be from the next epoch */ + if (rr->epoch == read_epoch_next && + (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { + *is_next_epoch = 1; + return &s->d1->next_bitmap; + } + + return NULL; +} + +void +dtls1_reset_read_seq_numbers(SSL *s) +{ + memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP)); + memset(&(s->d1->next_bitmap), 0, sizeof(DTLS1_BITMAP)); +} diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c new file mode 100644 index 0000000..67c4495 --- /dev/null +++ b/ssl/d1_srtp.c @@ -0,0 +1,266 @@ +/* $OpenBSD: d1_srtp.c,v 1.33 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. + * Copyright (C) 2011, RTFM, Inc. + */ + +#include + +#include +#include + +#ifndef OPENSSL_NO_SRTP + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "srtp.h" + +static const SRTP_PROTECTION_PROFILE srtp_known_profiles[] = { + { + "SRTP_AES128_CM_SHA1_80", + SRTP_AES128_CM_SHA1_80, + }, + { + "SRTP_AES128_CM_SHA1_32", + SRTP_AES128_CM_SHA1_32, + }, + { + "SRTP_AEAD_AES_128_GCM", + SRTP_AEAD_AES_128_GCM, + }, + { + "SRTP_AEAD_AES_256_GCM", + SRTP_AEAD_AES_256_GCM, + }, + {0} +}; + +int +srtp_find_profile_by_name(const char *profile_name, + const SRTP_PROTECTION_PROFILE **pptr, unsigned int len) +{ + const SRTP_PROTECTION_PROFILE *p; + + p = srtp_known_profiles; + while (p->name) { + if ((len == strlen(p->name)) && + !strncmp(p->name, profile_name, len)) { + *pptr = p; + return 0; + } + + p++; + } + + return 1; +} + +int +srtp_find_profile_by_num(unsigned int profile_num, + const SRTP_PROTECTION_PROFILE **pptr) +{ + const SRTP_PROTECTION_PROFILE *p; + + p = srtp_known_profiles; + while (p->name) { + if (p->id == profile_num) { + *pptr = p; + return 0; + } + p++; + } + + return 1; +} + +static int +ssl_ctx_make_profiles(const char *profiles_string, + STACK_OF(SRTP_PROTECTION_PROFILE) **out) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *profiles; + char *col; + const char *ptr = profiles_string; + const SRTP_PROTECTION_PROFILE *p; + + if (!(profiles = sk_SRTP_PROTECTION_PROFILE_new_null())) { + SSLerrorx(SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES); + return 1; + } + + do { + col = strchr(ptr, ':'); + + if (!srtp_find_profile_by_name(ptr, &p, + col ? col - ptr : (int)strlen(ptr))) { + if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, p)) { + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; + } + } else { + SSLerrorx(SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE); + sk_SRTP_PROTECTION_PROFILE_free(profiles); + return 1; + } + + if (col) + ptr = col + 1; + } while (col); + + sk_SRTP_PROTECTION_PROFILE_free(*out); + *out = profiles; + + return 0; +} + +int +SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles); +} +LSSL_ALIAS(SSL_CTX_set_tlsext_use_srtp); + +int +SSL_set_tlsext_use_srtp(SSL *s, const char *profiles) +{ + return ssl_ctx_make_profiles(profiles, &s->srtp_profiles); +} +LSSL_ALIAS(SSL_set_tlsext_use_srtp); + + +STACK_OF(SRTP_PROTECTION_PROFILE) * +SSL_get_srtp_profiles(SSL *s) +{ + if (s != NULL) { + if (s->srtp_profiles != NULL) { + return s->srtp_profiles; + } else if ((s->ctx != NULL) && + (s->ctx->srtp_profiles != NULL)) { + return s->ctx->srtp_profiles; + } + } + + return NULL; +} +LSSL_ALIAS(SSL_get_srtp_profiles); + +SRTP_PROTECTION_PROFILE * +SSL_get_selected_srtp_profile(SSL *s) +{ + /* XXX cast away the const */ + return (SRTP_PROTECTION_PROFILE *)s->srtp_profile; +} +LSSL_ALIAS(SSL_get_selected_srtp_profile); + +#endif diff --git a/ssl/dtls_local.h b/ssl/dtls_local.h new file mode 100644 index 0000000..c7c413f --- /dev/null +++ b/ssl/dtls_local.h @@ -0,0 +1,232 @@ +/* $OpenBSD: dtls_local.h,v 1.2 2022/11/26 17:23:18 tb Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_DTLS_LOCL_H +#define HEADER_DTLS_LOCL_H + +#include + +#include + +#include "ssl_local.h" +#include "tls_content.h" + +__BEGIN_HIDDEN_DECLS + +typedef struct dtls1_bitmap_st { + unsigned long map; /* track 32 packets on 32-bit systems + and 64 - on 64-bit systems */ + unsigned char max_seq_num[8]; /* max record number seen so far, + 64-bit value in big-endian + encoding */ +} DTLS1_BITMAP; + +struct dtls1_retransmit_state { + SSL_SESSION *session; + unsigned short epoch; +}; + +struct hm_header_st { + unsigned char type; + unsigned long msg_len; + unsigned short seq; + unsigned long frag_off; + unsigned long frag_len; + unsigned int is_ccs; + struct dtls1_retransmit_state saved_retransmit_state; +}; + +struct dtls1_timeout_st { + /* Number of read timeouts so far */ + unsigned int read_timeouts; + + /* Number of write timeouts so far */ + unsigned int write_timeouts; + + /* Number of alerts received so far */ + unsigned int num_alerts; +}; + +struct _pqueue; + +typedef struct record_pqueue_st { + unsigned short epoch; + struct _pqueue *q; +} record_pqueue; + +typedef struct rcontent_pqueue_st { + unsigned short epoch; + struct _pqueue *q; +} rcontent_pqueue; + +typedef struct hm_fragment_st { + struct hm_header_st msg_header; + unsigned char *fragment; + unsigned char *reassembly; +} hm_fragment; + +typedef struct dtls1_record_data_internal_st { + unsigned char *packet; + unsigned int packet_length; + SSL3_BUFFER_INTERNAL rbuf; + SSL3_RECORD_INTERNAL rrec; +} DTLS1_RECORD_DATA_INTERNAL; + +typedef struct dtls1_rcontent_data_internal_st { + struct tls_content *rcontent; +} DTLS1_RCONTENT_DATA_INTERNAL; + +struct dtls1_state_st { + /* Buffered (sent) handshake records */ + struct _pqueue *sent_messages; + + /* Indicates when the last handshake msg or heartbeat sent will timeout */ + struct timeval next_timeout; + + /* Timeout duration */ + unsigned short timeout_duration; + + unsigned int send_cookie; + unsigned char cookie[DTLS1_COOKIE_LENGTH]; + unsigned char rcvd_cookie[DTLS1_COOKIE_LENGTH]; + unsigned int cookie_len; + + /* records being received in the current epoch */ + DTLS1_BITMAP bitmap; + + /* renegotiation starts a new set of sequence numbers */ + DTLS1_BITMAP next_bitmap; + + /* handshake message numbers */ + unsigned short handshake_write_seq; + unsigned short next_handshake_write_seq; + + unsigned short handshake_read_seq; + + /* Received handshake records (unprocessed) */ + record_pqueue unprocessed_rcds; + + /* Buffered handshake messages */ + struct _pqueue *buffered_messages; + + /* Buffered application records. + * Only for records between CCS and Finished + * to prevent either protocol violation or + * unnecessary message loss. + */ + rcontent_pqueue buffered_app_data; + + /* Is set when listening for new connections with dtls1_listen() */ + unsigned int listen; + + unsigned int mtu; /* max DTLS packet size */ + + struct hm_header_st w_msg_hdr; + struct hm_header_st r_msg_hdr; + + struct dtls1_timeout_st timeout; + + unsigned int retransmitting; + unsigned int change_cipher_spec_ok; +}; + +int dtls1_do_write(SSL *s, int type); +int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +void dtls1_set_message_header(SSL *s, unsigned char mt, unsigned long len, + unsigned long frag_off, unsigned long frag_len); +void dtls1_set_message_header_int(SSL *s, unsigned char mt, + unsigned long len, unsigned short seq_num, unsigned long frag_off, + unsigned long frag_len); + +int do_dtls1_write(SSL *s, int type, const unsigned char *buf, + unsigned int len); + +int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf, int len); +int dtls1_write_bytes(SSL *s, int type, const void *buf, int len); + +int dtls1_read_failed(SSL *s, int code); +int dtls1_buffer_message(SSL *s, int ccs); +int dtls1_retransmit_message(SSL *s, unsigned short seq, + unsigned long frag_off, int *found); +int dtls1_get_queue_priority(unsigned short seq, int is_ccs); +int dtls1_retransmit_buffered_messages(SSL *s); +void dtls1_clear_record_buffer(SSL *s); +int dtls1_get_message_header(CBS *header, struct hm_header_st *msg_hdr); +void dtls1_reset_read_seq_numbers(SSL *s); +struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft); +int dtls1_check_timeout_num(SSL *s); +int dtls1_handle_timeout(SSL *s); +const SSL_CIPHER *dtls1_get_cipher(unsigned int u); +void dtls1_start_timer(SSL *s); +void dtls1_stop_timer(SSL *s); +int dtls1_is_timer_expired(SSL *s); +void dtls1_double_timeout(SSL *s); +unsigned int dtls1_min_mtu(void); + +int dtls1_new(SSL *s); +void dtls1_free(SSL *s); +void dtls1_clear(SSL *s); +long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg); + +int dtls1_get_message(SSL *s, int st1, int stn, int mt, long max); +int dtls1_get_record(SSL *s); + +__END_HIDDEN_DECLS + +#endif /* !HEADER_DTLS_LOCL_H */ diff --git a/ssl/empty.c b/ssl/empty.c new file mode 100644 index 0000000..e69de29 diff --git a/ssl/hidden/openssl/srtp.h b/ssl/hidden/openssl/srtp.h new file mode 100644 index 0000000..2440fc9 --- /dev/null +++ b/ssl/hidden/openssl/srtp.h @@ -0,0 +1,33 @@ +/* $OpenBSD: srtp.h,v 1.1 2023/07/08 16:40:14 beck Exp $ */ +/* + * Copyright (c) 2023 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_SRTP_H +#define _LIBSSL_SRTP_H + +#ifndef _MSC_VER +#include_next +#else +#include "../include/openssl/srtp.h" +#endif +#include "ssl_namespace.h" + +LSSL_USED(SSL_CTX_set_tlsext_use_srtp); +LSSL_USED(SSL_set_tlsext_use_srtp); +LSSL_USED(SSL_get_srtp_profiles); +LSSL_USED(SSL_get_selected_srtp_profile); + +#endif /* _LIBSSL_SRTP_H */ diff --git a/ssl/hidden/openssl/ssl.h b/ssl/hidden/openssl/ssl.h new file mode 100644 index 0000000..e4ec6d6 --- /dev/null +++ b/ssl/hidden/openssl/ssl.h @@ -0,0 +1,384 @@ +/* $OpenBSD: ssl.h,v 1.4 2023/07/28 09:53:55 tb Exp $ */ +/* + * Copyright (c) 2023 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_SSL_H +#define _LIBSSL_SSL_H + +#ifndef _MSC_VER +#include_next +#else +#include "../include/openssl/ssl.h" +#endif +#include "ssl_namespace.h" + +LSSL_USED(SSL_CTX_set_msg_callback); +LSSL_USED(SSL_set_msg_callback); +LSSL_USED(SSL_CTX_set_keylog_callback); +LSSL_USED(SSL_CTX_get_keylog_callback); +LSSL_USED(SSL_set_num_tickets); +LSSL_USED(SSL_get_num_tickets); +LSSL_USED(SSL_CTX_set_num_tickets); +LSSL_USED(SSL_CTX_get_num_tickets); +LSSL_USED(SSL_get0_verified_chain); +LSSL_USED(SSL_CTX_sessions); +LSSL_USED(SSL_CTX_sess_set_new_cb); +LSSL_USED(SSL_CTX_sess_get_new_cb); +LSSL_USED(SSL_CTX_sess_set_remove_cb); +LSSL_USED(SSL_CTX_sess_get_remove_cb); +LSSL_USED(SSL_CTX_sess_set_get_cb); +LSSL_USED(SSL_CTX_set_info_callback); +LSSL_USED(SSL_CTX_get_info_callback); +LSSL_USED(SSL_CTX_set_client_cert_cb); +LSSL_USED(SSL_CTX_get_client_cert_cb); +LSSL_USED(SSL_CTX_set_cookie_generate_cb); +LSSL_USED(SSL_CTX_set_cookie_verify_cb); +LSSL_USED(SSL_CTX_set_next_protos_advertised_cb); +LSSL_USED(SSL_CTX_set_next_proto_select_cb); +LSSL_USED(SSL_select_next_proto); +LSSL_USED(SSL_get0_next_proto_negotiated); +LSSL_USED(SSL_CTX_set_alpn_protos); +LSSL_USED(SSL_set_alpn_protos); +LSSL_USED(SSL_CTX_set_alpn_select_cb); +LSSL_USED(SSL_get0_alpn_selected); +LSSL_USED(SSL_set_psk_use_session_callback); +LSSL_USED(SSL_get_finished); +LSSL_USED(SSL_get_peer_finished); +LSSL_USED(SSL_verify_client_post_handshake); +LSSL_USED(SSL_CTX_set_post_handshake_auth); +LSSL_USED(SSL_set_post_handshake_auth); +LSSL_USED(PEM_read_bio_SSL_SESSION); +LSSL_USED(PEM_read_SSL_SESSION); +LSSL_USED(PEM_write_bio_SSL_SESSION); +LSSL_USED(PEM_write_SSL_SESSION); +LSSL_USED(SSL_CTX_set0_chain); +LSSL_USED(SSL_CTX_set1_chain); +LSSL_USED(SSL_CTX_add0_chain_cert); +LSSL_USED(SSL_CTX_add1_chain_cert); +LSSL_USED(SSL_CTX_get0_chain_certs); +LSSL_USED(SSL_CTX_clear_chain_certs); +LSSL_USED(SSL_set0_chain); +LSSL_USED(SSL_set1_chain); +LSSL_USED(SSL_add0_chain_cert); +LSSL_USED(SSL_add1_chain_cert); +LSSL_USED(SSL_get0_chain_certs); +LSSL_USED(SSL_clear_chain_certs); +LSSL_USED(SSL_CTX_set1_groups); +LSSL_USED(SSL_CTX_set1_groups_list); +LSSL_USED(SSL_set1_groups); +LSSL_USED(SSL_set1_groups_list); +LSSL_USED(SSL_CTX_get_min_proto_version); +LSSL_USED(SSL_CTX_get_max_proto_version); +LSSL_USED(SSL_CTX_set_min_proto_version); +LSSL_USED(SSL_CTX_set_max_proto_version); +LSSL_USED(SSL_get_min_proto_version); +LSSL_USED(SSL_get_max_proto_version); +LSSL_USED(SSL_set_min_proto_version); +LSSL_USED(SSL_set_max_proto_version); +LSSL_USED(SSL_CTX_get_ssl_method); +LSSL_USED(BIO_f_ssl); +LSSL_USED(BIO_new_ssl); +LSSL_USED(BIO_new_ssl_connect); +LSSL_USED(BIO_new_buffer_ssl_connect); +LSSL_USED(BIO_ssl_copy_session_id); +LSSL_USED(BIO_ssl_shutdown); +LSSL_USED(SSL_CTX_get_ciphers); +LSSL_USED(SSL_CTX_set_cipher_list); +LSSL_USED(SSL_CTX_set_ciphersuites); +LSSL_USED(SSL_CTX_new); +LSSL_USED(SSL_CTX_free); +LSSL_USED(SSL_CTX_up_ref); +LSSL_USED(SSL_CTX_set_timeout); +LSSL_USED(SSL_CTX_get_timeout); +LSSL_USED(SSL_CTX_get_cert_store); +LSSL_USED(SSL_CTX_set_cert_store); +LSSL_USED(SSL_CTX_get0_certificate); +LSSL_USED(SSL_CTX_get0_privatekey); +LSSL_USED(SSL_want); +LSSL_USED(SSL_clear); +LSSL_USED(SSL_CTX_flush_sessions); +LSSL_USED(SSL_get_current_cipher); +LSSL_USED(SSL_CIPHER_get_by_id); +LSSL_USED(SSL_CIPHER_get_by_value); +LSSL_USED(SSL_CIPHER_get_bits); +LSSL_USED(SSL_CIPHER_get_version); +LSSL_USED(SSL_CIPHER_get_name); +LSSL_USED(SSL_CIPHER_get_id); +LSSL_USED(SSL_CIPHER_get_value); +LSSL_USED(SSL_CIPHER_find); +LSSL_USED(SSL_CIPHER_get_cipher_nid); +LSSL_USED(SSL_CIPHER_get_digest_nid); +LSSL_USED(SSL_CIPHER_get_kx_nid); +LSSL_USED(SSL_CIPHER_get_auth_nid); +LSSL_USED(SSL_CIPHER_is_aead); +LSSL_USED(SSL_get_fd); +LSSL_USED(SSL_get_rfd); +LSSL_USED(SSL_get_wfd); +LSSL_USED(SSL_get_cipher_list); +LSSL_USED(SSL_get_shared_ciphers); +LSSL_USED(SSL_get_read_ahead); +LSSL_USED(SSL_pending); +LSSL_USED(SSL_set_fd); +LSSL_USED(SSL_set_rfd); +LSSL_USED(SSL_set_wfd); +LSSL_USED(SSL_set_bio); +LSSL_USED(SSL_get_rbio); +LSSL_USED(SSL_set0_rbio); +LSSL_USED(SSL_get_wbio); +LSSL_USED(SSL_set_cipher_list); +LSSL_USED(SSL_set_ciphersuites); +LSSL_USED(SSL_set_read_ahead); +LSSL_USED(SSL_get_verify_mode); +LSSL_USED(SSL_get_verify_depth); +LSSL_USED(SSL_get_verify_callback); +LSSL_USED(SSL_set_verify); +LSSL_USED(SSL_set_verify_depth); +LSSL_USED(SSL_use_RSAPrivateKey); +LSSL_USED(SSL_use_RSAPrivateKey_ASN1); +LSSL_USED(SSL_use_PrivateKey); +LSSL_USED(SSL_use_PrivateKey_ASN1); +LSSL_USED(SSL_use_certificate); +LSSL_USED(SSL_use_certificate_ASN1); +LSSL_USED(SSL_use_RSAPrivateKey_file); +LSSL_USED(SSL_use_PrivateKey_file); +LSSL_USED(SSL_use_certificate_file); +LSSL_USED(SSL_use_certificate_chain_file); +LSSL_USED(SSL_CTX_use_RSAPrivateKey_file); +LSSL_USED(SSL_CTX_use_PrivateKey_file); +LSSL_USED(SSL_CTX_use_certificate_file); +LSSL_USED(SSL_CTX_use_certificate_chain_file); +LSSL_USED(SSL_CTX_use_certificate_chain_mem); +LSSL_USED(SSL_load_client_CA_file); +LSSL_USED(SSL_add_file_cert_subjects_to_stack); +LSSL_USED(SSL_add_dir_cert_subjects_to_stack); +LSSL_USED(SSL_load_error_strings); +LSSL_USED(SSL_state_string); +LSSL_USED(SSL_rstate_string); +LSSL_USED(SSL_state_string_long); +LSSL_USED(SSL_rstate_string_long); +LSSL_USED(SSL_SESSION_get0_cipher); +LSSL_USED(SSL_SESSION_get_master_key); +LSSL_USED(SSL_SESSION_get_protocol_version); +LSSL_USED(SSL_SESSION_get_time); +LSSL_USED(SSL_SESSION_set_time); +LSSL_USED(SSL_SESSION_get_timeout); +LSSL_USED(SSL_SESSION_set_timeout); +LSSL_USED(SSL_copy_session_id); +LSSL_USED(SSL_SESSION_get0_peer); +LSSL_USED(SSL_SESSION_set1_id); +LSSL_USED(SSL_SESSION_set1_id_context); +LSSL_USED(SSL_SESSION_is_resumable); +LSSL_USED(SSL_SESSION_new); +LSSL_USED(SSL_SESSION_free); +LSSL_USED(SSL_SESSION_up_ref); +LSSL_USED(SSL_SESSION_get_id); +LSSL_USED(SSL_SESSION_get0_id_context); +LSSL_USED(SSL_SESSION_get_max_early_data); +LSSL_USED(SSL_SESSION_set_max_early_data); +LSSL_USED(SSL_SESSION_get_ticket_lifetime_hint); +LSSL_USED(SSL_SESSION_has_ticket); +LSSL_USED(SSL_SESSION_get_compress_id); +LSSL_USED(SSL_SESSION_print_fp); +LSSL_USED(SSL_SESSION_print); +LSSL_USED(i2d_SSL_SESSION); +LSSL_USED(SSL_set_session); +LSSL_USED(SSL_CTX_add_session); +LSSL_USED(SSL_CTX_remove_session); +LSSL_USED(SSL_CTX_set_generate_session_id); +LSSL_USED(SSL_set_generate_session_id); +LSSL_USED(SSL_has_matching_session_id); +LSSL_USED(d2i_SSL_SESSION); +LSSL_USED(SSL_get_peer_cert_chain); +LSSL_USED(SSL_CTX_get_verify_mode); +LSSL_USED(SSL_CTX_get_verify_depth); +LSSL_USED(SSL_CTX_get_verify_callback); +LSSL_USED(SSL_CTX_set_verify); +LSSL_USED(SSL_CTX_set_verify_depth); +LSSL_USED(SSL_CTX_set_cert_verify_callback); +LSSL_USED(SSL_CTX_use_RSAPrivateKey); +LSSL_USED(SSL_CTX_use_RSAPrivateKey_ASN1); +LSSL_USED(SSL_CTX_use_PrivateKey); +LSSL_USED(SSL_CTX_use_PrivateKey_ASN1); +LSSL_USED(SSL_CTX_use_certificate); +LSSL_USED(SSL_CTX_use_certificate_ASN1); +LSSL_USED(SSL_CTX_get_default_passwd_cb); +LSSL_USED(SSL_CTX_set_default_passwd_cb); +LSSL_USED(SSL_CTX_get_default_passwd_cb_userdata); +LSSL_USED(SSL_CTX_set_default_passwd_cb_userdata); +LSSL_USED(SSL_CTX_check_private_key); +LSSL_USED(SSL_check_private_key); +LSSL_USED(SSL_CTX_set_session_id_context); +LSSL_USED(SSL_set_session_id_context); +LSSL_USED(SSL_CTX_set_purpose); +LSSL_USED(SSL_set_purpose); +LSSL_USED(SSL_CTX_set_trust); +LSSL_USED(SSL_set_trust); +LSSL_USED(SSL_set1_host); +LSSL_USED(SSL_set_hostflags); +LSSL_USED(SSL_get0_peername); +LSSL_USED(SSL_CTX_get0_param); +LSSL_USED(SSL_CTX_set1_param); +LSSL_USED(SSL_get0_param); +LSSL_USED(SSL_set1_param); +LSSL_USED(SSL_new); +LSSL_USED(SSL_free); +LSSL_USED(SSL_up_ref); +LSSL_USED(SSL_accept); +LSSL_USED(SSL_connect); +LSSL_USED(SSL_is_dtls); +LSSL_USED(SSL_is_server); +LSSL_USED(SSL_read); +LSSL_USED(SSL_peek); +LSSL_USED(SSL_write); +LSSL_USED(SSL_read_ex); +LSSL_USED(SSL_peek_ex); +LSSL_USED(SSL_write_ex); +LSSL_USED(SSL_CTX_get_max_early_data); +LSSL_USED(SSL_CTX_set_max_early_data); +LSSL_USED(SSL_get_max_early_data); +LSSL_USED(SSL_set_max_early_data); +LSSL_USED(SSL_get_early_data_status); +LSSL_USED(SSL_read_early_data); +LSSL_USED(SSL_write_early_data); +LSSL_USED(SSL_ctrl); +LSSL_USED(SSL_callback_ctrl); +LSSL_USED(SSL_CTX_ctrl); +LSSL_USED(SSL_CTX_callback_ctrl); +LSSL_USED(SSL_get_error); +LSSL_USED(SSL_get_version); +LSSL_USED(SSL_CTX_set_ssl_version); +LSSL_USED(SSLv23_method); +LSSL_USED(SSLv23_server_method); +LSSL_USED(SSLv23_client_method); +LSSL_USED(TLSv1_method); +LSSL_USED(TLSv1_server_method); +LSSL_USED(TLSv1_client_method); +LSSL_USED(TLSv1_1_method); +LSSL_USED(TLSv1_1_server_method); +LSSL_USED(TLSv1_1_client_method); +LSSL_USED(TLSv1_2_method); +LSSL_USED(TLSv1_2_server_method); +LSSL_USED(TLSv1_2_client_method); +LSSL_USED(TLS_method); +LSSL_USED(TLS_server_method); +LSSL_USED(TLS_client_method); +LSSL_USED(DTLSv1_method); +LSSL_USED(DTLSv1_server_method); +LSSL_USED(DTLSv1_client_method); +LSSL_USED(DTLSv1_2_method); +LSSL_USED(DTLSv1_2_server_method); +LSSL_USED(DTLSv1_2_client_method); +LSSL_USED(DTLS_method); +LSSL_USED(DTLS_server_method); +LSSL_USED(DTLS_client_method); +LSSL_USED(SSL_get_ciphers); +LSSL_USED(SSL_get_client_ciphers); +LSSL_USED(SSL_get1_supported_ciphers); +LSSL_USED(SSL_do_handshake); +LSSL_USED(SSL_renegotiate); +LSSL_USED(SSL_renegotiate_abbreviated); +LSSL_USED(SSL_renegotiate_pending); +LSSL_USED(SSL_shutdown); +LSSL_USED(SSL_get_ssl_method); +LSSL_USED(SSL_set_ssl_method); +LSSL_USED(SSL_alert_type_string_long); +LSSL_USED(SSL_alert_type_string); +LSSL_USED(SSL_alert_desc_string_long); +LSSL_USED(SSL_alert_desc_string); +LSSL_USED(SSL_set_client_CA_list); +LSSL_USED(SSL_CTX_set_client_CA_list); +LSSL_USED(SSL_get_client_CA_list); +LSSL_USED(SSL_CTX_get_client_CA_list); +LSSL_USED(SSL_add_client_CA); +LSSL_USED(SSL_CTX_add_client_CA); +LSSL_USED(SSL_set_connect_state); +LSSL_USED(SSL_set_accept_state); +LSSL_USED(SSL_get_default_timeout); +LSSL_USED(SSL_library_init); +LSSL_USED(SSL_CIPHER_description); +LSSL_USED(SSL_dup_CA_list); +LSSL_USED(SSL_dup); +LSSL_USED(SSL_get_certificate); +LSSL_USED(SSL_get_privatekey); +LSSL_USED(SSL_CTX_set_quiet_shutdown); +LSSL_USED(SSL_CTX_get_quiet_shutdown); +LSSL_USED(SSL_set_quiet_shutdown); +LSSL_USED(SSL_get_quiet_shutdown); +LSSL_USED(SSL_set_shutdown); +LSSL_USED(SSL_get_shutdown); +LSSL_USED(SSL_version); +LSSL_USED(SSL_CTX_set_default_verify_paths); +LSSL_USED(SSL_CTX_load_verify_locations); +LSSL_USED(SSL_CTX_load_verify_mem); +LSSL_USED(SSL_get_session); +LSSL_USED(SSL_get1_session); +LSSL_USED(SSL_get_SSL_CTX); +LSSL_USED(SSL_set_SSL_CTX); +LSSL_USED(SSL_set_info_callback); +LSSL_USED(SSL_get_info_callback); +LSSL_USED(SSL_state); +LSSL_USED(SSL_set_state); +LSSL_USED(SSL_set_verify_result); +LSSL_USED(SSL_get_verify_result); +LSSL_USED(SSL_set_ex_data); +LSSL_USED(SSL_get_ex_data); +LSSL_USED(SSL_get_ex_new_index); +LSSL_USED(SSL_SESSION_set_ex_data); +LSSL_USED(SSL_SESSION_get_ex_data); +LSSL_USED(SSL_SESSION_get_ex_new_index); +LSSL_USED(SSL_CTX_set_ex_data); +LSSL_USED(SSL_CTX_get_ex_data); +LSSL_USED(SSL_CTX_get_ex_new_index); +LSSL_USED(SSL_get_ex_data_X509_STORE_CTX_idx); +LSSL_USED(SSL_CTX_set_tmp_rsa_callback); +LSSL_USED(SSL_set_tmp_rsa_callback); +LSSL_USED(SSL_CTX_set_tmp_dh_callback); +LSSL_USED(SSL_set_tmp_dh_callback); +LSSL_USED(SSL_CTX_set_tmp_ecdh_callback); +LSSL_USED(SSL_set_tmp_ecdh_callback); +LSSL_USED(SSL_get_client_random); +LSSL_USED(SSL_get_server_random); +LSSL_USED(SSL_get_current_compression); +LSSL_USED(SSL_get_current_expansion); +LSSL_USED(SSL_get_peer_certificate); +LSSL_USED(SSL_COMP_get_name); +LSSL_USED(SSL_COMP_get_compression_methods); +LSSL_USED(SSL_COMP_add_compression_method); +LSSL_USED(SSL_set_session_ticket_ext); +LSSL_USED(SSL_set_session_ticket_ext_cb); +LSSL_USED(SSL_set_session_secret_cb); +LSSL_USED(SSL_set_debug); +LSSL_USED(SSL_cache_hit); +LSSL_USED(SSL_set_security_level); +LSSL_USED(SSL_get_security_level); +LSSL_USED(SSL_CTX_set_security_level); +LSSL_USED(SSL_CTX_get_security_level); +LSSL_USED(SSL_CTX_set_quic_method); +LSSL_USED(SSL_CTX_sess_get_get_cb); +LSSL_USED(SSL_set_quic_method); +LSSL_USED(SSL_is_quic); +LSSL_USED(SSL_quic_max_handshake_flight_len); +LSSL_USED(SSL_quic_read_level); +LSSL_USED(SSL_quic_write_level); +LSSL_USED(SSL_provide_quic_data); +LSSL_USED(SSL_process_quic_post_handshake); +LSSL_USED(SSL_set_quic_transport_params); +LSSL_USED(SSL_get_peer_quic_transport_params); +LSSL_USED(SSL_set_quic_use_legacy_codepoint); +LSSL_USED(ERR_load_SSL_strings); +LSSL_USED(OPENSSL_init_ssl); + +#endif /* _LIBSSL_SSL_H */ diff --git a/ssl/hidden/openssl/tls1.h b/ssl/hidden/openssl/tls1.h new file mode 100644 index 0000000..de93f9a --- /dev/null +++ b/ssl/hidden/openssl/tls1.h @@ -0,0 +1,32 @@ +/* $OpenBSD: tls1.h,v 1.1 2023/07/08 16:40:14 beck Exp $ */ +/* + * Copyright (c) 2023 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_TLS1_H +#define _LIBSSL_TLS1_H + +#ifndef _MSC_VER +#include_next +#else +#include "../include/openssl/tls1.h" +#endif +#include "ssl_namespace.h" + +LSSL_USED(SSL_get_servername); +LSSL_USED(SSL_get_servername_type); +LSSL_USED(SSL_export_keying_material); + +#endif /* _LIBSSL_TLS1_H */ diff --git a/ssl/hidden/ssl_namespace.h b/ssl/hidden/ssl_namespace.h new file mode 100644 index 0000000..b79f7cc --- /dev/null +++ b/ssl/hidden/ssl_namespace.h @@ -0,0 +1,43 @@ +/* $OpenBSD: ssl_namespace.h,v 1.2 2023/02/16 08:38:17 tb Exp $ */ +/* + * Copyright (c) 2016 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBSSL_SSL_NAMESPACE_H_ +#define _LIBSSL_SSL_NAMESPACE_H_ + +/* + * If marked as 'used', then internal calls use the name with prefix "_lssl_" + * and we alias that to the normal name. + */ + +#ifdef _MSC_VER +#define LSSL_UNUSED(x) +#define LSSL_USED(x) +#define LSSL_ALIAS(x) +#else +#ifdef LIBRESSL_NAMESPACE +#define LSSL_UNUSED(x) typeof(x) x __attribute__((deprecated)) +#define LSSL_USED(x) __attribute__((visibility("hidden"))) \ + typeof(x) x asm("_lssl_"#x) +#define LSSL_ALIAS(x) asm(".global "#x"; "#x" = _lssl_"#x) +#else +#define LSSL_UNUSED(x) +#define LSSL_USED(x) +#define LSSL_ALIAS(x) asm("") +#endif +#endif /* _MSC_VER */ + +#endif /* _LIBSSL_SSL_NAMESPACE_H_ */ diff --git a/ssl/pqueue.c b/ssl/pqueue.c new file mode 100644 index 0000000..602969d --- /dev/null +++ b/ssl/pqueue.c @@ -0,0 +1,201 @@ +/* $OpenBSD: pqueue.c,v 1.5 2014/06/12 15:49:31 deraadt Exp $ */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "pqueue.h" + +typedef struct _pqueue { + pitem *items; + int count; +} pqueue_s; + +pitem * +pitem_new(unsigned char *prio64be, void *data) +{ + pitem *item = malloc(sizeof(pitem)); + + if (item == NULL) + return NULL; + + memcpy(item->priority, prio64be, sizeof(item->priority)); + + item->data = data; + item->next = NULL; + + return item; +} + +void +pitem_free(pitem *item) +{ + free(item); +} + +pqueue_s * +pqueue_new(void) +{ + return calloc(1, sizeof(pqueue_s)); +} + +void +pqueue_free(pqueue_s *pq) +{ + free(pq); +} + +pitem * +pqueue_insert(pqueue_s *pq, pitem *item) +{ + pitem *curr, *next; + + if (pq->items == NULL) { + pq->items = item; + return item; + } + + for (curr = NULL, next = pq->items; next != NULL; + curr = next, next = next->next) { + /* we can compare 64-bit value in big-endian encoding + * with memcmp:-) */ + int cmp = memcmp(next->priority, item->priority, + sizeof(item->priority)); + if (cmp > 0) { /* next > item */ + item->next = next; + + if (curr == NULL) + pq->items = item; + else + curr->next = item; + + return item; + } else if (cmp == 0) /* duplicates not allowed */ + return NULL; + } + + item->next = NULL; + curr->next = item; + + return item; +} + +pitem * +pqueue_peek(pqueue_s *pq) +{ + return pq->items; +} + +pitem * +pqueue_pop(pqueue_s *pq) +{ + pitem *item = pq->items; + + if (pq->items != NULL) + pq->items = pq->items->next; + + return item; +} + +pitem * +pqueue_find(pqueue_s *pq, unsigned char *prio64be) +{ + pitem *next; + + for (next = pq->items; next != NULL; next = next->next) + if (memcmp(next->priority, prio64be, + sizeof(next->priority)) == 0) + return next; + + return NULL; +} + +pitem * +pqueue_iterator(pqueue_s *pq) +{ + return pqueue_peek(pq); +} + +pitem * +pqueue_next(pitem **item) +{ + pitem *ret; + + if (item == NULL || *item == NULL) + return NULL; + + /* *item != NULL */ + ret = *item; + *item = (*item)->next; + + return ret; +} + +int +pqueue_size(pqueue_s *pq) +{ + pitem *item = pq->items; + int count = 0; + + while (item != NULL) { + count++; + item = item->next; + } + return count; +} diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c new file mode 100644 index 0000000..32b7460 --- /dev/null +++ b/ssl/s3_cbc.c @@ -0,0 +1,628 @@ +/* $OpenBSD: s3_cbc.c,v 1.26 2022/11/26 16:08:55 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 2012 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include "ssl_local.h" + +/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length + * field. (SHA-384/512 have 128-bit length.) */ +#define MAX_HASH_BIT_COUNT_BYTES 16 + +/* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support. + * Currently SHA-384/512 has a 128-byte block size and that's the largest + * supported by TLS.) */ +#define MAX_HASH_BLOCK_SIZE 128 + +/* Some utility functions are needed: + * + * These macros return the given value with the MSB copied to all the other + * bits. They use the fact that arithmetic shift shifts-in the sign bit. + * However, this is not ensured by the C standard so you may need to replace + * them with something else on odd CPUs. */ +#define DUPLICATE_MSB_TO_ALL(x) ((unsigned int)((int)(x) >> (sizeof(int) * 8 - 1))) +#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x))) + +/* constant_time_lt returns 0xff if a=b and 0x00 otherwise. */ +static unsigned int +constant_time_ge(unsigned int a, unsigned int b) +{ + a -= b; + return DUPLICATE_MSB_TO_ALL(~a); +} + +/* constant_time_eq_8 returns 0xff if a==b and 0x00 otherwise. */ +static unsigned char +constant_time_eq_8(unsigned int a, unsigned int b) +{ + unsigned int c = a ^ b; + c--; + return DUPLICATE_MSB_TO_ALL_8(c); +} + +/* ssl3_cbc_remove_padding removes the CBC padding from the decrypted, TLS, CBC + * record in |rec| in constant time and returns 1 if the padding is valid and + * -1 otherwise. It also removes any explicit IV from the start of the record + * without leaking any timing about whether there was enough space after the + * padding was removed. + * + * block_size: the block size of the cipher used to encrypt the record. + * returns: + * 0: (in non-constant time) if the record is publicly invalid. + * 1: if the padding was valid + * -1: otherwise. */ +int +ssl3_cbc_remove_padding(SSL3_RECORD_INTERNAL *rec, unsigned int eiv_len, + unsigned int mac_size) +{ + unsigned int padding_length, good, to_check, i; + const unsigned int overhead = 1 /* padding length byte */ + mac_size; + + /* + * These lengths are all public so we can test them in + * non-constant time. + */ + if (overhead + eiv_len > rec->length) + return 0; + + /* We can now safely skip explicit IV, if any. */ + rec->data += eiv_len; + rec->input += eiv_len; + rec->length -= eiv_len; + + padding_length = rec->data[rec->length - 1]; + + good = constant_time_ge(rec->length, overhead + padding_length); + /* The padding consists of a length byte at the end of the record and + * then that many bytes of padding, all with the same value as the + * length byte. Thus, with the length byte included, there are i+1 + * bytes of padding. + * + * We can't check just |padding_length+1| bytes because that leaks + * decrypted information. Therefore we always have to check the maximum + * amount of padding possible. (Again, the length of the record is + * public information so we can use it.) */ + to_check = 256; /* maximum amount of padding, inc length byte. */ + if (to_check > rec->length) + to_check = rec->length; + + for (i = 0; i < to_check; i++) { + unsigned char mask = constant_time_ge(padding_length, i); + unsigned char b = rec->data[rec->length - 1 - i]; + /* The final |padding_length+1| bytes should all have the value + * |padding_length|. Therefore the XOR should be zero. */ + good &= ~(mask&(padding_length ^ b)); + } + + /* If any of the final |padding_length+1| bytes had the wrong value, + * one or more of the lower eight bits of |good| will be cleared. We + * AND the bottom 8 bits together and duplicate the result to all the + * bits. */ + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + good <<= sizeof(good)*8 - 1; + good = DUPLICATE_MSB_TO_ALL(good); + + padding_length = good & (padding_length + 1); + rec->length -= padding_length; + rec->padding_length = padding_length; + + return (int)((good & 1) | (~good & -1)); +} + +/* ssl3_cbc_copy_mac copies |md_size| bytes from the end of |rec| to |out| in + * constant time (independent of the concrete value of rec->length, which may + * vary within a 256-byte window). + * + * ssl3_cbc_remove_padding or tls1_cbc_remove_padding must be called prior to + * this function. + * + * On entry: + * rec->orig_len >= md_size + * md_size <= EVP_MAX_MD_SIZE + * + * If CBC_MAC_ROTATE_IN_PLACE is defined then the rotation is performed with + * variable accesses in a 64-byte-aligned buffer. Assuming that this fits into + * a single or pair of cache-lines, then the variable memory accesses don't + * actually affect the timing. CPUs with smaller cache-lines [if any] are + * not multi-core and are not considered vulnerable to cache-timing attacks. + */ +#define CBC_MAC_ROTATE_IN_PLACE + +void +ssl3_cbc_copy_mac(unsigned char* out, const SSL3_RECORD_INTERNAL *rec, + unsigned int md_size, unsigned int orig_len) +{ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + unsigned char rotated_mac_buf[64 + EVP_MAX_MD_SIZE]; + unsigned char *rotated_mac; +#else + unsigned char rotated_mac[EVP_MAX_MD_SIZE]; +#endif + + /* mac_end is the index of |rec->data| just after the end of the MAC. */ + unsigned int mac_end = rec->length; + unsigned int mac_start = mac_end - md_size; + /* scan_start contains the number of bytes that we can ignore because + * the MAC's position can only vary by 255 bytes. */ + unsigned int scan_start = 0; + unsigned int i, j; + unsigned int div_spoiler; + unsigned int rotate_offset; + + OPENSSL_assert(orig_len >= md_size); + OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); + +#if defined(CBC_MAC_ROTATE_IN_PLACE) + rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf)&63); +#endif + + /* This information is public so it's safe to branch based on it. */ + if (orig_len > md_size + 255 + 1) + scan_start = orig_len - (md_size + 255 + 1); + /* div_spoiler contains a multiple of md_size that is used to cause the + * modulo operation to be constant time. Without this, the time varies + * based on the amount of padding when running on Intel chips at least. + * + * The aim of right-shifting md_size is so that the compiler doesn't + * figure out that it can remove div_spoiler as that would require it + * to prove that md_size is always even, which I hope is beyond it. */ + div_spoiler = md_size >> 1; + div_spoiler <<= (sizeof(div_spoiler) - 1) * 8; + rotate_offset = (div_spoiler + mac_start - scan_start) % md_size; + + memset(rotated_mac, 0, md_size); + for (i = scan_start, j = 0; i < orig_len; i++) { + unsigned char mac_started = constant_time_ge(i, mac_start); + unsigned char mac_ended = constant_time_ge(i, mac_end); + unsigned char b = rec->data[i]; + rotated_mac[j++] |= b & mac_started & ~mac_ended; + j &= constant_time_lt(j, md_size); + } + + /* Now rotate the MAC */ +#if defined(CBC_MAC_ROTATE_IN_PLACE) + j = 0; + for (i = 0; i < md_size; i++) { + /* in case cache-line is 32 bytes, touch second line */ + ((volatile unsigned char *)rotated_mac)[rotate_offset^32]; + out[j++] = rotated_mac[rotate_offset++]; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + } +#else + memset(out, 0, md_size); + rotate_offset = md_size - rotate_offset; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + for (i = 0; i < md_size; i++) { + for (j = 0; j < md_size; j++) + out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset); + rotate_offset++; + rotate_offset &= constant_time_lt(rotate_offset, md_size); + } +#endif +} + +#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +#define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \ + *((c)++)=(unsigned char)(((l)>>48)&0xff), \ + *((c)++)=(unsigned char)(((l)>>40)&0xff), \ + *((c)++)=(unsigned char)(((l)>>32)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l) )&0xff)) + +/* u32toLE serialises an unsigned, 32-bit number (n) as four bytes at (p) in + * little-endian order. The value of p is advanced by four. */ +#define u32toLE(n, p) \ + (*((p)++)=(unsigned char)(n), \ + *((p)++)=(unsigned char)(n>>8), \ + *((p)++)=(unsigned char)(n>>16), \ + *((p)++)=(unsigned char)(n>>24)) + +/* These functions serialize the state of a hash and thus perform the standard + * "final" operation without adding the padding and length that such a function + * typically does. */ +static void +tls1_md5_final_raw(void* ctx, unsigned char *md_out) +{ + MD5_CTX *md5 = ctx; + u32toLE(md5->A, md_out); + u32toLE(md5->B, md_out); + u32toLE(md5->C, md_out); + u32toLE(md5->D, md_out); +} + +static void +tls1_sha1_final_raw(void* ctx, unsigned char *md_out) +{ + SHA_CTX *sha1 = ctx; + l2n(sha1->h0, md_out); + l2n(sha1->h1, md_out); + l2n(sha1->h2, md_out); + l2n(sha1->h3, md_out); + l2n(sha1->h4, md_out); +} + +static void +tls1_sha256_final_raw(void* ctx, unsigned char *md_out) +{ + SHA256_CTX *sha256 = ctx; + unsigned int i; + + for (i = 0; i < 8; i++) { + l2n(sha256->h[i], md_out); + } +} + +static void +tls1_sha512_final_raw(void* ctx, unsigned char *md_out) +{ + SHA512_CTX *sha512 = ctx; + unsigned int i; + + for (i = 0; i < 8; i++) { + l2n8(sha512->h[i], md_out); + } +} + +/* Largest hash context ever used by the functions above. */ +#define LARGEST_DIGEST_CTX SHA512_CTX + +/* Type giving the alignment needed by the above */ +#define LARGEST_DIGEST_CTX_ALIGNMENT SHA_LONG64 + +/* ssl3_cbc_record_digest_supported returns 1 iff |ctx| uses a hash function + * which ssl3_cbc_digest_record supports. */ +char +ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx) +{ + switch (EVP_MD_CTX_type(ctx)) { + case NID_md5: + case NID_sha1: + case NID_sha224: + case NID_sha256: + case NID_sha384: + case NID_sha512: + return 1; + default: + return 0; + } +} + +/* ssl3_cbc_digest_record computes the MAC of a decrypted, padded TLS + * record. + * + * ctx: the EVP_MD_CTX from which we take the hash function. + * ssl3_cbc_record_digest_supported must return true for this EVP_MD_CTX. + * md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written. + * md_out_size: if non-NULL, the number of output bytes is written here. + * header: the 13-byte, TLS record header. + * data: the record data itself, less any preceeding explicit IV. + * data_plus_mac_size: the secret, reported length of the data and MAC + * once the padding has been removed. + * data_plus_mac_plus_padding_size: the public length of the whole + * record, including padding. + * + * On entry: by virtue of having been through one of the remove_padding + * functions, above, we know that data_plus_mac_size is large enough to contain + * a padding byte and MAC. (If the padding was invalid, it might contain the + * padding too. ) + */ +int +ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char* md_out, + size_t* md_out_size, const unsigned char header[13], + const unsigned char *data, size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, const unsigned char *mac_secret, + unsigned int mac_secret_length) +{ + union { + /* + * Alignment here is to allow this to be cast as SHA512_CTX + * without losing alignment required by the 64-bit SHA_LONG64 + * integer it contains. + */ + LARGEST_DIGEST_CTX_ALIGNMENT align; + unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; + } md_state; + void (*md_final_raw)(void *ctx, unsigned char *md_out); + void (*md_transform)(void *ctx, const unsigned char *block); + unsigned int md_size, md_block_size = 64; + unsigned int header_length, variance_blocks, + len, max_mac_bytes, num_blocks, + num_starting_blocks, k, mac_end_offset, c, index_a, index_b; + unsigned int bits; /* at most 18 bits */ + unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES]; + /* hmac_pad is the masked HMAC key. */ + unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE]; + unsigned char first_block[MAX_HASH_BLOCK_SIZE]; + unsigned char mac_out[EVP_MAX_MD_SIZE]; + unsigned int i, j, md_out_size_u; + EVP_MD_CTX *md_ctx; + /* mdLengthSize is the number of bytes in the length field that terminates + * the hash. */ + unsigned int md_length_size = 8; + char length_is_big_endian = 1; + + /* This is a, hopefully redundant, check that allows us to forget about + * many possible overflows later in this function. */ + OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024); + + switch (EVP_MD_CTX_type(ctx)) { + case NID_md5: + MD5_Init((MD5_CTX*)md_state.c); + md_final_raw = tls1_md5_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform; + md_size = 16; + length_is_big_endian = 0; + break; + case NID_sha1: + SHA1_Init((SHA_CTX*)md_state.c); + md_final_raw = tls1_sha1_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform; + md_size = 20; + break; + case NID_sha224: + SHA224_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 224/8; + break; + case NID_sha256: + SHA256_Init((SHA256_CTX*)md_state.c); + md_final_raw = tls1_sha256_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform; + md_size = 32; + break; + case NID_sha384: + SHA384_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 384/8; + md_block_size = 128; + md_length_size = 16; + break; + case NID_sha512: + SHA512_Init((SHA512_CTX*)md_state.c); + md_final_raw = tls1_sha512_final_raw; + md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform; + md_size = 64; + md_block_size = 128; + md_length_size = 16; + break; + default: + /* ssl3_cbc_record_digest_supported should have been + * called first to check that the hash function is + * supported. */ + OPENSSL_assert(0); + if (md_out_size) + *md_out_size = 0; + return 0; + } + + OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES); + OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE); + OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE); + + header_length = 13; + + /* variance_blocks is the number of blocks of the hash that we have to + * calculate in constant time because they could be altered by the + * padding value. + * + * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not + * required to be minimal. Therefore we say that the final six blocks + * can vary based on the padding. + * + * Later in the function, if the message is short and there obviously + * cannot be this many blocks then variance_blocks can be reduced. */ + variance_blocks = 6; + /* From now on we're dealing with the MAC, which conceptually has 13 + * bytes of `header' before the start of the data (TLS) */ + len = data_plus_mac_plus_padding_size + header_length; + /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including + * |header|, assuming that there's no padding. */ + max_mac_bytes = len - md_size - 1; + /* num_blocks is the maximum number of hash blocks. */ + num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size; + /* In order to calculate the MAC in constant time we have to handle + * the final blocks specially because the padding value could cause the + * end to appear somewhere in the final |variance_blocks| blocks and we + * can't leak where. However, |num_starting_blocks| worth of data can + * be hashed right away because no padding value can affect whether + * they are plaintext. */ + num_starting_blocks = 0; + /* k is the starting byte offset into the conceptual header||data where + * we start processing. */ + k = 0; + /* mac_end_offset is the index just past the end of the data to be + * MACed. */ + mac_end_offset = data_plus_mac_size + header_length - md_size; + /* c is the index of the 0x80 byte in the final hash block that + * contains application data. */ + c = mac_end_offset % md_block_size; + /* index_a is the hash block number that contains the 0x80 terminating + * value. */ + index_a = mac_end_offset / md_block_size; + /* index_b is the hash block number that contains the 64-bit hash + * length, in bits. */ + index_b = (mac_end_offset + md_length_size) / md_block_size; + /* bits is the hash-length in bits. It includes the additional hash + * block for the masked HMAC key. */ + + if (num_blocks > variance_blocks) { + num_starting_blocks = num_blocks - variance_blocks; + k = md_block_size*num_starting_blocks; + } + + bits = 8*mac_end_offset; + /* Compute the initial HMAC block. */ + bits += 8*md_block_size; + memset(hmac_pad, 0, md_block_size); + OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad)); + memcpy(hmac_pad, mac_secret, mac_secret_length); + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x36; + + md_transform(md_state.c, hmac_pad); + + if (length_is_big_endian) { + memset(length_bytes, 0, md_length_size - 4); + length_bytes[md_length_size - 4] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 3] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 2] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 1] = (unsigned char)bits; + } else { + memset(length_bytes, 0, md_length_size); + length_bytes[md_length_size - 5] = (unsigned char)(bits >> 24); + length_bytes[md_length_size - 6] = (unsigned char)(bits >> 16); + length_bytes[md_length_size - 7] = (unsigned char)(bits >> 8); + length_bytes[md_length_size - 8] = (unsigned char)bits; + } + + if (k > 0) { + /* k is a multiple of md_block_size. */ + memcpy(first_block, header, 13); + memcpy(first_block + 13, data, md_block_size - 13); + md_transform(md_state.c, first_block); + for (i = 1; i < k/md_block_size; i++) + md_transform(md_state.c, data + md_block_size*i - 13); + } + + memset(mac_out, 0, sizeof(mac_out)); + + /* We now process the final hash blocks. For each block, we construct + * it in constant time. If the |i==index_a| then we'll include the 0x80 + * bytes and zero pad etc. For each block we selectively copy it, in + * constant time, to |mac_out|. */ + for (i = num_starting_blocks; i <= num_starting_blocks + variance_blocks; i++) { + unsigned char block[MAX_HASH_BLOCK_SIZE]; + unsigned char is_block_a = constant_time_eq_8(i, index_a); + unsigned char is_block_b = constant_time_eq_8(i, index_b); + for (j = 0; j < md_block_size; j++) { + unsigned char b = 0, is_past_c, is_past_cp1; + if (k < header_length) + b = header[k]; + else if (k < data_plus_mac_plus_padding_size + header_length) + b = data[k - header_length]; + k++; + + is_past_c = is_block_a & constant_time_ge(j, c); + is_past_cp1 = is_block_a & constant_time_ge(j, c + 1); + /* If this is the block containing the end of the + * application data, and we are at the offset for the + * 0x80 value, then overwrite b with 0x80. */ + b = (b&~is_past_c) | (0x80&is_past_c); + /* If this is the block containing the end of the + * application data and we're past the 0x80 value then + * just write zero. */ + b = b&~is_past_cp1; + /* If this is index_b (the final block), but not + * index_a (the end of the data), then the 64-bit + * length didn't fit into index_a and we're having to + * add an extra block of zeros. */ + b &= ~is_block_b | is_block_a; + + /* The final bytes of one of the blocks contains the + * length. */ + if (j >= md_block_size - md_length_size) { + /* If this is index_b, write a length byte. */ + b = (b&~is_block_b) | (is_block_b&length_bytes[j - (md_block_size - md_length_size)]); + } + block[j] = b; + } + + md_transform(md_state.c, block); + md_final_raw(md_state.c, block); + /* If this is index_b, copy the hash value to |mac_out|. */ + for (j = 0; j < md_size; j++) + mac_out[j] |= block[j]&is_block_b; + } + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + return 0; + if (!EVP_DigestInit_ex(md_ctx, EVP_MD_CTX_md(ctx), NULL /* engine */)) { + EVP_MD_CTX_free(md_ctx); + return 0; + } + + /* Complete the HMAC in the standard manner. */ + for (i = 0; i < md_block_size; i++) + hmac_pad[i] ^= 0x6a; + + EVP_DigestUpdate(md_ctx, hmac_pad, md_block_size); + EVP_DigestUpdate(md_ctx, mac_out, md_size); + + EVP_DigestFinal(md_ctx, md_out, &md_out_size_u); + if (md_out_size) + *md_out_size = md_out_size_u; + EVP_MD_CTX_free(md_ctx); + + return 1; +} diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c new file mode 100644 index 0000000..7ab6880 --- /dev/null +++ b/ssl/s3_lib.c @@ -0,0 +1,2827 @@ +/* $OpenBSD: s3_lib.c,v 1.246 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" +#include "tls_content.h" + +#define SSL3_NUM_CIPHERS (sizeof(ssl3_ciphers) / sizeof(SSL_CIPHER)) + +/* + * FIXED_NONCE_LEN is a macro that provides in the correct value to set the + * fixed nonce length in algorithms2. It is the inverse of the + * SSL_CIPHER_AEAD_FIXED_NONCE_LEN macro. + */ +#define FIXED_NONCE_LEN(x) (((x / 2) & 0xf) << 24) + +/* list of available SSLv3 ciphers (sorted by id) */ +const SSL_CIPHER ssl3_ciphers[] = { + + /* The RSA ciphers */ + /* Cipher 01 */ + { + .valid = 1, + .name = SSL3_TXT_RSA_NULL_MD5, + .id = SSL3_CK_RSA_NULL_MD5, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_MD5, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher 02 */ + { + .valid = 1, + .name = SSL3_TXT_RSA_NULL_SHA, + .id = SSL3_CK_RSA_NULL_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher 04 */ + { + .valid = 1, + .name = SSL3_TXT_RSA_RC4_128_MD5, + .id = SSL3_CK_RSA_RC4_128_MD5, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_MD5, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 05 */ + { + .valid = 1, + .name = SSL3_TXT_RSA_RC4_128_SHA, + .id = SSL3_CK_RSA_RC4_128_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 0A */ + { + .valid = 1, + .name = SSL3_TXT_RSA_DES_192_CBC3_SHA, + .id = SSL3_CK_RSA_DES_192_CBC3_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* + * Ephemeral DH (DHE) ciphers. + */ + + /* Cipher 16 */ + { + .valid = 1, + .name = SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, + .id = SSL3_CK_EDH_RSA_DES_192_CBC3_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* Cipher 18 */ + { + .valid = 1, + .name = SSL3_TXT_ADH_RC4_128_MD5, + .id = SSL3_CK_ADH_RC4_128_MD5, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_MD5, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 1B */ + { + .valid = 1, + .name = SSL3_TXT_ADH_DES_192_CBC_SHA, + .id = SSL3_CK_ADH_DES_192_CBC_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_SSLV3, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* + * AES ciphersuites. + */ + + /* Cipher 2F */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_128_SHA, + .id = TLS1_CK_RSA_WITH_AES_128_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 33 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, + .id = TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 34 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_128_SHA, + .id = TLS1_CK_ADH_WITH_AES_128_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 35 */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_256_SHA, + .id = TLS1_CK_RSA_WITH_AES_256_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 39 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, + .id = TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 3A */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_256_SHA, + .id = TLS1_CK_ADH_WITH_AES_256_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* TLS v1.2 ciphersuites */ + /* Cipher 3B */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_NULL_SHA256, + .id = TLS1_CK_RSA_WITH_NULL_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher 3C */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_128_SHA256, + .id = TLS1_CK_RSA_WITH_AES_128_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 3D */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_256_SHA256, + .id = TLS1_CK_RSA_WITH_AES_256_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, + +#ifndef OPENSSL_NO_CAMELLIA + /* Camellia ciphersuites from RFC4132 (128-bit portion) */ + + /* Cipher 41 */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA, + .id = TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 45 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + .id = TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 46 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA, + .id = TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, +#endif /* OPENSSL_NO_CAMELLIA */ + + /* TLS v1.2 ciphersuites */ + /* Cipher 67 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256, + .id = TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 6B */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_256_SHA256, + .id = TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 6C */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_128_SHA256, + .id = TLS1_CK_ADH_WITH_AES_128_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 6D */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_256_SHA256, + .id = TLS1_CK_ADH_WITH_AES_256_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* GOST Ciphersuites */ + + /* Cipher 81 */ + { + .valid = 1, + .name = "GOST2001-GOST89-GOST89", + .id = 0x3000081, + .algorithm_mkey = SSL_kGOST, + .algorithm_auth = SSL_aGOST01, + .algorithm_enc = SSL_eGOST2814789CNT, + .algorithm_mac = SSL_GOST89MAC, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94| + TLS1_STREAM_MAC, + .strength_bits = 256, + .alg_bits = 256 + }, + + /* Cipher 83 */ + { + .valid = 1, + .name = "GOST2001-NULL-GOST94", + .id = 0x3000083, + .algorithm_mkey = SSL_kGOST, + .algorithm_auth = SSL_aGOST01, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_GOST94, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_GOST94|TLS1_PRF_GOST94, + .strength_bits = 0, + .alg_bits = 0 + }, + +#ifndef OPENSSL_NO_CAMELLIA + /* Camellia ciphersuites from RFC4132 (256-bit portion) */ + + /* Cipher 84 */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA, + .id = TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 88 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + .id = TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 89 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA, + .id = TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, +#endif /* OPENSSL_NO_CAMELLIA */ + + /* + * GCM ciphersuites from RFC5288. + */ + + /* Cipher 9C */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256, + .id = TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 9D */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384, + .id = TLS1_CK_RSA_WITH_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 9E */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256, + .id = TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 9F */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384, + .id = TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher A6 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256, + .id = TLS1_CK_ADH_WITH_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher A7 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384, + .id = TLS1_CK_ADH_WITH_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 256, + .alg_bits = 256, + }, + +#ifndef OPENSSL_NO_CAMELLIA + /* TLS 1.2 Camellia SHA-256 ciphersuites from RFC5932 */ + + /* Cipher BA */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_CAMELLIA_128_CBC_SHA256, + .id = TLS1_CK_RSA_WITH_CAMELLIA_128_CBC_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher BE */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + .id = TLS1_CK_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher BF */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_CAMELLIA_128_CBC_SHA256, + .id = TLS1_CK_ADH_WITH_CAMELLIA_128_CBC_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_CAMELLIA128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C0 */ + { + .valid = 1, + .name = TLS1_TXT_RSA_WITH_CAMELLIA_256_CBC_SHA256, + .id = TLS1_CK_RSA_WITH_CAMELLIA_256_CBC_SHA256, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C4 */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + .id = TLS1_CK_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C5 */ + { + .valid = 1, + .name = TLS1_TXT_ADH_WITH_CAMELLIA_256_CBC_SHA256, + .id = TLS1_CK_ADH_WITH_CAMELLIA_256_CBC_SHA256, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_CAMELLIA256, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 256, + .alg_bits = 256, + }, +#endif /* OPENSSL_NO_CAMELLIA */ + + /* + * TLSv1.3 cipher suites. + */ + +#ifdef LIBRESSL_HAS_TLS1_3 + /* Cipher 1301 */ + { + .valid = 1, + .name = TLS1_3_RFC_AES_128_GCM_SHA256, + .id = TLS1_3_CK_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kTLS1_3, + .algorithm_auth = SSL_aTLS1_3, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_3, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256, /* XXX */ + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher 1302 */ + { + .valid = 1, + .name = TLS1_3_RFC_AES_256_GCM_SHA384, + .id = TLS1_3_CK_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kTLS1_3, + .algorithm_auth = SSL_aTLS1_3, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_3, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384, /* XXX */ + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher 1303 */ + { + .valid = 1, + .name = TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + .id = TLS1_3_CK_CHACHA20_POLY1305_SHA256, + .algorithm_mkey = SSL_kTLS1_3, + .algorithm_auth = SSL_aTLS1_3, + .algorithm_enc = SSL_CHACHA20POLY1305, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_3, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256, /* XXX */ + .strength_bits = 256, + .alg_bits = 256, + }, +#endif + + /* Cipher C006 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA, + .id = TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher C007 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA, + .id = TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C008 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + .id = TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* Cipher C009 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C00A */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C010 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA, + .id = TLS1_CK_ECDHE_RSA_WITH_NULL_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher C011 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, + .id = TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C012 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + .id = TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* Cipher C013 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C014 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C015 */ + { + .valid = 1, + .name = TLS1_TXT_ECDH_anon_WITH_NULL_SHA, + .id = TLS1_CK_ECDH_anon_WITH_NULL_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 0, + .alg_bits = 0, + }, + + /* Cipher C016 */ + { + .valid = 1, + .name = TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA, + .id = TLS1_CK_ECDH_anon_WITH_RC4_128_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_RC4, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_LOW, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C017 */ + { + .valid = 1, + .name = TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA, + .id = TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_3DES, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_MEDIUM, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 112, + .alg_bits = 168, + }, + + /* Cipher C018 */ + { + .valid = 1, + .name = TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA, + .id = TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C019 */ + { + .valid = 1, + .name = TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA, + .id = TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA1, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF, + .strength_bits = 256, + .alg_bits = 256, + }, + + + /* HMAC based TLS v1.2 ciphersuites from RFC5289 */ + + /* Cipher C023 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C024 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA384, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C027 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128, + .algorithm_mac = SSL_SHA256, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C028 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256, + .algorithm_mac = SSL_SHA384, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* GCM based TLS v1.2 ciphersuites from RFC5289 */ + + /* Cipher C02B */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C02C */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + .id = TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher C02F */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES128GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 128, + .alg_bits = 128, + }, + + /* Cipher C030 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + .id = TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_AES256GCM, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384| + FIXED_NONCE_LEN(4)| + SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD, + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher CCA8 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305, + .id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CHACHA20POLY1305, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(12), + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher CCA9 */ + { + .valid = 1, + .name = TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + .id = TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aECDSA, + .algorithm_enc = SSL_CHACHA20POLY1305, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(12), + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher CCAA */ + { + .valid = 1, + .name = TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305, + .id = TLS1_CK_DHE_RSA_CHACHA20_POLY1305, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aRSA, + .algorithm_enc = SSL_CHACHA20POLY1305, + .algorithm_mac = SSL_AEAD, + .algorithm_ssl = SSL_TLSV1_2, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256| + FIXED_NONCE_LEN(12), + .strength_bits = 256, + .alg_bits = 256, + }, + + /* Cipher FF85 FIXME IANA */ + { + .valid = 1, + .name = "GOST2012256-GOST89-GOST89", + .id = 0x300ff85, /* FIXME IANA */ + .algorithm_mkey = SSL_kGOST, + .algorithm_auth = SSL_aGOST01, + .algorithm_enc = SSL_eGOST2814789CNT, + .algorithm_mac = SSL_GOST89MAC, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_HIGH, + .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256| + TLS1_STREAM_MAC, + .strength_bits = 256, + .alg_bits = 256 + }, + + /* Cipher FF87 FIXME IANA */ + { + .valid = 1, + .name = "GOST2012256-NULL-STREEBOG256", + .id = 0x300ff87, /* FIXME IANA */ + .algorithm_mkey = SSL_kGOST, + .algorithm_auth = SSL_aGOST01, + .algorithm_enc = SSL_eNULL, + .algorithm_mac = SSL_STREEBOG256, + .algorithm_ssl = SSL_TLSV1, + .algo_strength = SSL_STRONG_NONE, + .algorithm2 = SSL_HANDSHAKE_MAC_STREEBOG256|TLS1_PRF_STREEBOG256, + .strength_bits = 0, + .alg_bits = 0 + }, + + + /* end of list */ +}; + +int +ssl3_num_ciphers(void) +{ + return (SSL3_NUM_CIPHERS); +} + +const SSL_CIPHER * +ssl3_get_cipher(unsigned int u) +{ + if (u < SSL3_NUM_CIPHERS) + return (&(ssl3_ciphers[SSL3_NUM_CIPHERS - 1 - u])); + else + return (NULL); +} + +const SSL_CIPHER * +ssl3_get_cipher_by_id(unsigned int id) +{ + const SSL_CIPHER *cp; + SSL_CIPHER c; + + c.id = id; + cp = OBJ_bsearch_ssl_cipher_id(&c, ssl3_ciphers, SSL3_NUM_CIPHERS); + if (cp != NULL && cp->valid == 1) + return (cp); + + return (NULL); +} + +const SSL_CIPHER * +ssl3_get_cipher_by_value(uint16_t value) +{ + return ssl3_get_cipher_by_id(SSL3_CK_ID | value); +} + +uint16_t +ssl3_cipher_get_value(const SSL_CIPHER *c) +{ + return (c->id & SSL3_CK_VALUE_MASK); +} + +int +ssl3_pending(const SSL *s) +{ + if (s->s3->rcontent == NULL) + return 0; + if (tls_content_type(s->s3->rcontent) != SSL3_RT_APPLICATION_DATA) + return 0; + + return tls_content_remaining(s->s3->rcontent); +} + +int +ssl3_handshake_msg_hdr_len(SSL *s) +{ + return (SSL_is_dtls(s) ? DTLS1_HM_HEADER_LENGTH : + SSL3_HM_HEADER_LENGTH); +} + +int +ssl3_handshake_msg_start(SSL *s, CBB *handshake, CBB *body, uint8_t msg_type) +{ + int ret = 0; + + if (!CBB_init(handshake, SSL3_RT_MAX_PLAIN_LENGTH)) + goto err; + if (!CBB_add_u8(handshake, msg_type)) + goto err; + if (SSL_is_dtls(s)) { + unsigned char *data; + + if (!CBB_add_space(handshake, &data, DTLS1_HM_HEADER_LENGTH - + SSL3_HM_HEADER_LENGTH)) + goto err; + } + if (!CBB_add_u24_length_prefixed(handshake, body)) + goto err; + + ret = 1; + + err: + return (ret); +} + +int +ssl3_handshake_msg_finish(SSL *s, CBB *handshake) +{ + unsigned char *data = NULL; + size_t outlen; + int ret = 0; + + if (!CBB_finish(handshake, &data, &outlen)) + goto err; + + if (outlen > INT_MAX) + goto err; + + if (!BUF_MEM_grow_clean(s->init_buf, outlen)) + goto err; + + memcpy(s->init_buf->data, data, outlen); + + s->init_num = (int)outlen; + s->init_off = 0; + + if (SSL_is_dtls(s)) { + unsigned long len; + uint8_t msg_type; + CBS cbs; + + CBS_init(&cbs, data, outlen); + if (!CBS_get_u8(&cbs, &msg_type)) + goto err; + + len = outlen - ssl3_handshake_msg_hdr_len(s); + + dtls1_set_message_header(s, msg_type, len, 0, len); + dtls1_buffer_message(s, 0); + } + + ret = 1; + + err: + free(data); + + return (ret); +} + +int +ssl3_handshake_write(SSL *s) +{ + return ssl3_record_write(s, SSL3_RT_HANDSHAKE); +} + +int +ssl3_record_write(SSL *s, int type) +{ + if (SSL_is_dtls(s)) + return dtls1_do_write(s, type); + + return ssl3_do_write(s, type); +} + +int +ssl3_new(SSL *s) +{ + if ((s->s3 = calloc(1, sizeof(*s->s3))) == NULL) + return (0); + + s->method->ssl_clear(s); + + return (1); +} + +void +ssl3_free(SSL *s) +{ + if (s == NULL) + return; + + tls1_cleanup_key_block(s); + ssl3_release_read_buffer(s); + ssl3_release_write_buffer(s); + + tls_content_free(s->s3->rcontent); + + tls_buffer_free(s->s3->alert_fragment); + tls_buffer_free(s->s3->handshake_fragment); + + freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); + sk_X509_pop_free(s->s3->hs.peer_certs, X509_free); + sk_X509_pop_free(s->s3->hs.peer_certs_no_leaf, X509_free); + sk_X509_pop_free(s->s3->hs.verified_chain, X509_free); + tls_key_share_free(s->s3->hs.key_share); + + tls13_secrets_destroy(s->s3->hs.tls13.secrets); + freezero(s->s3->hs.tls13.cookie, s->s3->hs.tls13.cookie_len); + tls13_clienthello_hash_clear(&s->s3->hs.tls13); + + tls_buffer_free(s->s3->hs.tls13.quic_read_buffer); + + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + + tls1_transcript_free(s); + tls1_transcript_hash_free(s); + + free(s->s3->alpn_selected); + + freezero(s->s3->peer_quic_transport_params, + s->s3->peer_quic_transport_params_len); + + freezero(s->s3, sizeof(*s->s3)); + + s->s3 = NULL; +} + +void +ssl3_clear(SSL *s) +{ + unsigned char *rp, *wp; + size_t rlen, wlen; + + tls1_cleanup_key_block(s); + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + + tls_buffer_free(s->s3->alert_fragment); + s->s3->alert_fragment = NULL; + tls_buffer_free(s->s3->handshake_fragment); + s->s3->handshake_fragment = NULL; + + freezero(s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); + s->s3->hs.sigalgs = NULL; + s->s3->hs.sigalgs_len = 0; + + sk_X509_pop_free(s->s3->hs.peer_certs, X509_free); + s->s3->hs.peer_certs = NULL; + sk_X509_pop_free(s->s3->hs.peer_certs_no_leaf, X509_free); + s->s3->hs.peer_certs_no_leaf = NULL; + sk_X509_pop_free(s->s3->hs.verified_chain, X509_free); + s->s3->hs.verified_chain = NULL; + + tls_key_share_free(s->s3->hs.key_share); + s->s3->hs.key_share = NULL; + + tls13_secrets_destroy(s->s3->hs.tls13.secrets); + s->s3->hs.tls13.secrets = NULL; + freezero(s->s3->hs.tls13.cookie, s->s3->hs.tls13.cookie_len); + s->s3->hs.tls13.cookie = NULL; + s->s3->hs.tls13.cookie_len = 0; + tls13_clienthello_hash_clear(&s->s3->hs.tls13); + + tls_buffer_free(s->s3->hs.tls13.quic_read_buffer); + s->s3->hs.tls13.quic_read_buffer = NULL; + s->s3->hs.tls13.quic_read_level = ssl_encryption_initial; + s->s3->hs.tls13.quic_write_level = ssl_encryption_initial; + + s->s3->hs.extensions_seen = 0; + + rp = s->s3->rbuf.buf; + wp = s->s3->wbuf.buf; + rlen = s->s3->rbuf.len; + wlen = s->s3->wbuf.len; + + tls_content_free(s->s3->rcontent); + s->s3->rcontent = NULL; + + tls1_transcript_free(s); + tls1_transcript_hash_free(s); + + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; + + freezero(s->s3->peer_quic_transport_params, + s->s3->peer_quic_transport_params_len); + s->s3->peer_quic_transport_params = NULL; + s->s3->peer_quic_transport_params_len = 0; + + memset(s->s3, 0, sizeof(*s->s3)); + + s->s3->rbuf.buf = rp; + s->s3->wbuf.buf = wp; + s->s3->rbuf.len = rlen; + s->s3->wbuf.len = wlen; + + ssl_free_wbio_buffer(s); + + /* Not needed... */ + s->s3->renegotiate = 0; + s->s3->total_renegotiations = 0; + s->s3->num_renegotiations = 0; + s->s3->in_read_app_data = 0; + + s->packet_length = 0; + s->version = TLS1_2_VERSION; + + s->s3->hs.state = SSL_ST_BEFORE|((s->server) ? SSL_ST_ACCEPT : SSL_ST_CONNECT); +} + +long +_SSL_get_shared_group(SSL *s, long n) +{ + size_t count; + int nid; + + /* OpenSSL document that they return -1 for clients. They return 0. */ + if (!s->server) + return 0; + + if (n == -1) { + if (!tls1_count_shared_groups(s, &count)) + return 0; + + if (count > LONG_MAX) + count = LONG_MAX; + + return count; + } + + /* Undocumented special case added for Suite B profile support. */ + if (n == -2) + n = 0; + + if (n < 0) + return 0; + + if (!tls1_get_shared_group_by_index(s, n, &nid)) + return NID_undef; + + return nid; +} + +long +_SSL_get_peer_tmp_key(SSL *s, EVP_PKEY **key) +{ + EVP_PKEY *pkey = NULL; + int ret = 0; + + *key = NULL; + + if (s->s3->hs.key_share == NULL) + goto err; + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + if (!tls_key_share_peer_pkey(s->s3->hs.key_share, pkey)) + goto err; + + *key = pkey; + pkey = NULL; + + ret = 1; + + err: + EVP_PKEY_free(pkey); + + return (ret); +} + +static int +_SSL_session_reused(SSL *s) +{ + return s->hit; +} + +static int +_SSL_num_renegotiations(SSL *s) +{ + return s->s3->num_renegotiations; +} + +static int +_SSL_clear_num_renegotiations(SSL *s) +{ + int renegs; + + renegs = s->s3->num_renegotiations; + s->s3->num_renegotiations = 0; + + return renegs; +} + +static int +_SSL_total_renegotiations(SSL *s) +{ + return s->s3->total_renegotiations; +} + +static int +_SSL_set_tmp_dh(SSL *s, DH *dh) +{ + DH *dhe_params; + + if (dh == NULL) { + SSLerror(s, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_security_dh(s, dh)) { + SSLerror(s, SSL_R_DH_KEY_TOO_SMALL); + return 0; + } + + if ((dhe_params = DHparams_dup(dh)) == NULL) { + SSLerror(s, ERR_R_DH_LIB); + return 0; + } + + DH_free(s->cert->dhe_params); + s->cert->dhe_params = dhe_params; + + return 1; +} + +static int +_SSL_set_dh_auto(SSL *s, int state) +{ + s->cert->dhe_params_auto = state; + return 1; +} + +static int +_SSL_set_tmp_ecdh(SSL *s, EC_KEY *ecdh) +{ + const EC_GROUP *group; + int nid; + + if (ecdh == NULL) + return 0; + if ((group = EC_KEY_get0_group(ecdh)) == NULL) + return 0; + + nid = EC_GROUP_get_curve_name(group); + return SSL_set1_groups(s, &nid, 1); +} + +static int +_SSL_set_ecdh_auto(SSL *s, int state) +{ + return 1; +} + +static int +_SSL_set_tlsext_host_name(SSL *s, const char *name) +{ + int is_ip; + CBS cbs; + + free(s->tlsext_hostname); + s->tlsext_hostname = NULL; + + if (name == NULL) + return 1; + + CBS_init(&cbs, name, strlen(name)); + + if (!tlsext_sni_is_valid_hostname(&cbs, &is_ip)) { + SSLerror(s, SSL_R_SSL3_EXT_INVALID_SERVERNAME); + return 0; + } + if ((s->tlsext_hostname = strdup(name)) == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return 0; + } + + return 1; +} + +static int +_SSL_set_tlsext_debug_arg(SSL *s, void *arg) +{ + s->tlsext_debug_arg = arg; + return 1; +} + +static int +_SSL_get_tlsext_status_type(SSL *s) +{ + return s->tlsext_status_type; +} + +static int +_SSL_set_tlsext_status_type(SSL *s, int type) +{ + s->tlsext_status_type = type; + return 1; +} + +static int +_SSL_get_tlsext_status_exts(SSL *s, STACK_OF(X509_EXTENSION) **exts) +{ + *exts = s->tlsext_ocsp_exts; + return 1; +} + +static int +_SSL_set_tlsext_status_exts(SSL *s, STACK_OF(X509_EXTENSION) *exts) +{ + /* XXX - leak... */ + s->tlsext_ocsp_exts = exts; + return 1; +} + +static int +_SSL_get_tlsext_status_ids(SSL *s, STACK_OF(OCSP_RESPID) **ids) +{ + *ids = s->tlsext_ocsp_ids; + return 1; +} + +static int +_SSL_set_tlsext_status_ids(SSL *s, STACK_OF(OCSP_RESPID) *ids) +{ + /* XXX - leak... */ + s->tlsext_ocsp_ids = ids; + return 1; +} + +static int +_SSL_get_tlsext_status_ocsp_resp(SSL *s, unsigned char **resp) +{ + if (s->tlsext_ocsp_resp != NULL && + s->tlsext_ocsp_resp_len < INT_MAX) { + *resp = s->tlsext_ocsp_resp; + return (int)s->tlsext_ocsp_resp_len; + } + + *resp = NULL; + + return -1; +} + +static int +_SSL_set_tlsext_status_ocsp_resp(SSL *s, unsigned char *resp, int resp_len) +{ + free(s->tlsext_ocsp_resp); + s->tlsext_ocsp_resp = NULL; + s->tlsext_ocsp_resp_len = 0; + + if (resp_len < 0) + return 0; + + s->tlsext_ocsp_resp = resp; + s->tlsext_ocsp_resp_len = (size_t)resp_len; + + return 1; +} + +int +SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) +{ + return ssl_cert_set0_chain(NULL, ssl, chain); +} +LSSL_ALIAS(SSL_set0_chain); + +int +SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) +{ + return ssl_cert_set1_chain(NULL, ssl, chain); +} +LSSL_ALIAS(SSL_set1_chain); + +int +SSL_add0_chain_cert(SSL *ssl, X509 *x509) +{ + return ssl_cert_add0_chain_cert(NULL, ssl, x509); +} +LSSL_ALIAS(SSL_add0_chain_cert); + +int +SSL_add1_chain_cert(SSL *ssl, X509 *x509) +{ + return ssl_cert_add1_chain_cert(NULL, ssl, x509); +} +LSSL_ALIAS(SSL_add1_chain_cert); + +int +SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) +{ + *out_chain = NULL; + + if (ssl->cert->key != NULL) + *out_chain = ssl->cert->key->chain; + + return 1; +} +LSSL_ALIAS(SSL_get0_chain_certs); + +int +SSL_clear_chain_certs(SSL *ssl) +{ + return ssl_cert_set0_chain(NULL, ssl, NULL); +} +LSSL_ALIAS(SSL_clear_chain_certs); + +int +SSL_set1_groups(SSL *s, const int *groups, size_t groups_len) +{ + return tls1_set_groups(&s->tlsext_supportedgroups, + &s->tlsext_supportedgroups_length, groups, groups_len); +} +LSSL_ALIAS(SSL_set1_groups); + +int +SSL_set1_groups_list(SSL *s, const char *groups) +{ + return tls1_set_group_list(&s->tlsext_supportedgroups, + &s->tlsext_supportedgroups_length, groups); +} +LSSL_ALIAS(SSL_set1_groups_list); + +static int +_SSL_get_signature_nid(SSL *s, int *nid) +{ + const struct ssl_sigalg *sigalg; + + if ((sigalg = s->s3->hs.our_sigalg) == NULL) + return 0; + + *nid = EVP_MD_type(sigalg->md()); + + return 1; +} + +static int +_SSL_get_peer_signature_nid(SSL *s, int *nid) +{ + const struct ssl_sigalg *sigalg; + + if ((sigalg = s->s3->hs.peer_sigalg) == NULL) + return 0; + + *nid = EVP_MD_type(sigalg->md()); + + return 1; +} + +int +SSL_get_signature_type_nid(const SSL *s, int *nid) +{ + const struct ssl_sigalg *sigalg; + + if ((sigalg = s->s3->hs.our_sigalg) == NULL) + return 0; + + *nid = sigalg->key_type; + if (sigalg->key_type == EVP_PKEY_RSA && + (sigalg->flags & SIGALG_FLAG_RSA_PSS)) + *nid = EVP_PKEY_RSA_PSS; + + return 1; +} + +int +SSL_get_peer_signature_type_nid(const SSL *s, int *nid) +{ + const struct ssl_sigalg *sigalg; + + if ((sigalg = s->s3->hs.peer_sigalg) == NULL) + return 0; + + *nid = sigalg->key_type; + if (sigalg->key_type == EVP_PKEY_RSA && + (sigalg->flags & SIGALG_FLAG_RSA_PSS)) + *nid = EVP_PKEY_RSA_PSS; + + return 1; +} + +long +ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + switch (cmd) { + case SSL_CTRL_GET_SESSION_REUSED: + return _SSL_session_reused(s); + + case SSL_CTRL_GET_NUM_RENEGOTIATIONS: + return _SSL_num_renegotiations(s); + + case SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS: + return _SSL_clear_num_renegotiations(s); + + case SSL_CTRL_GET_TOTAL_RENEGOTIATIONS: + return _SSL_total_renegotiations(s); + + case SSL_CTRL_SET_TMP_DH: + return _SSL_set_tmp_dh(s, parg); + + case SSL_CTRL_SET_TMP_DH_CB: + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_DH_AUTO: + return _SSL_set_dh_auto(s, larg); + + case SSL_CTRL_SET_TMP_ECDH: + return _SSL_set_tmp_ecdh(s, parg); + + case SSL_CTRL_SET_TMP_ECDH_CB: + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_ECDH_AUTO: + return _SSL_set_ecdh_auto(s, larg); + + case SSL_CTRL_SET_TLSEXT_HOSTNAME: + if (larg != TLSEXT_NAMETYPE_host_name) { + SSLerror(s, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE); + return 0; + } + return _SSL_set_tlsext_host_name(s, parg); + + case SSL_CTRL_SET_TLSEXT_DEBUG_ARG: + return _SSL_set_tlsext_debug_arg(s, parg); + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE: + return _SSL_get_tlsext_status_type(s); + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE: + return _SSL_set_tlsext_status_type(s, larg); + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS: + return _SSL_get_tlsext_status_exts(s, parg); + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS: + return _SSL_set_tlsext_status_exts(s, parg); + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS: + return _SSL_get_tlsext_status_ids(s, parg); + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS: + return _SSL_set_tlsext_status_ids(s, parg); + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP: + return _SSL_get_tlsext_status_ocsp_resp(s, parg); + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP: + return _SSL_set_tlsext_status_ocsp_resp(s, parg, larg); + + case SSL_CTRL_CHAIN: + if (larg == 0) + return SSL_set0_chain(s, (STACK_OF(X509) *)parg); + else + return SSL_set1_chain(s, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg == 0) + return SSL_add0_chain_cert(s, (X509 *)parg); + else + return SSL_add1_chain_cert(s, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + return SSL_get0_chain_certs(s, (STACK_OF(X509) **)parg); + + case SSL_CTRL_SET_GROUPS: + return SSL_set1_groups(s, parg, larg); + + case SSL_CTRL_SET_GROUPS_LIST: + return SSL_set1_groups_list(s, parg); + + case SSL_CTRL_GET_SHARED_GROUP: + return _SSL_get_shared_group(s, larg); + + /* XXX - rename to SSL_CTRL_GET_PEER_TMP_KEY and remove server check. */ + case SSL_CTRL_GET_SERVER_TMP_KEY: + if (s->server != 0) + return 0; + return _SSL_get_peer_tmp_key(s, parg); + + case SSL_CTRL_GET_MIN_PROTO_VERSION: + return SSL_get_min_proto_version(s); + + case SSL_CTRL_GET_MAX_PROTO_VERSION: + return SSL_get_max_proto_version(s); + + case SSL_CTRL_SET_MIN_PROTO_VERSION: + if (larg < 0 || larg > UINT16_MAX) + return 0; + return SSL_set_min_proto_version(s, larg); + + case SSL_CTRL_SET_MAX_PROTO_VERSION: + if (larg < 0 || larg > UINT16_MAX) + return 0; + return SSL_set_max_proto_version(s, larg); + + case SSL_CTRL_GET_SIGNATURE_NID: + return _SSL_get_signature_nid(s, parg); + + case SSL_CTRL_GET_PEER_SIGNATURE_NID: + return _SSL_get_peer_signature_nid(s, parg); + + /* + * Legacy controls that should eventually be removed. + */ + case SSL_CTRL_GET_CLIENT_CERT_REQUEST: + return 0; + + case SSL_CTRL_GET_FLAGS: + return (int)(s->s3->flags); + + case SSL_CTRL_NEED_TMP_RSA: + return 0; + + case SSL_CTRL_SET_TMP_RSA: + case SSL_CTRL_SET_TMP_RSA_CB: + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return 0; +} + +long +ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) +{ + switch (cmd) { + case SSL_CTRL_SET_TMP_RSA_CB: + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_TMP_DH_CB: + s->cert->dhe_params_cb = (DH *(*)(SSL *, int, int))fp; + return 1; + + case SSL_CTRL_SET_TMP_ECDH_CB: + return 1; + + case SSL_CTRL_SET_TLSEXT_DEBUG_CB: + s->tlsext_debug_cb = (void (*)(SSL *, int , int, + unsigned char *, int, void *))fp; + return 1; + } + + return 0; +} + +static int +_SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh) +{ + DH *dhe_params; + + if (dh == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + if (!ssl_ctx_security_dh(ctx, dh)) { + SSLerrorx(SSL_R_DH_KEY_TOO_SMALL); + return 0; + } + + if ((dhe_params = DHparams_dup(dh)) == NULL) { + SSLerrorx(ERR_R_DH_LIB); + return 0; + } + + DH_free(ctx->cert->dhe_params); + ctx->cert->dhe_params = dhe_params; + + return 1; +} + +static int +_SSL_CTX_set_dh_auto(SSL_CTX *ctx, int state) +{ + ctx->cert->dhe_params_auto = state; + return 1; +} + +static int +_SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, EC_KEY *ecdh) +{ + const EC_GROUP *group; + int nid; + + if (ecdh == NULL) + return 0; + if ((group = EC_KEY_get0_group(ecdh)) == NULL) + return 0; + + nid = EC_GROUP_get_curve_name(group); + return SSL_CTX_set1_groups(ctx, &nid, 1); +} + +static int +_SSL_CTX_set_ecdh_auto(SSL_CTX *ctx, int state) +{ + return 1; +} + +static int +_SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) +{ + ctx->tlsext_servername_arg = arg; + return 1; +} + +static int +_SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, unsigned char *keys, int keys_len) +{ + if (keys == NULL) + return 48; + + if (keys_len != 48) { + SSLerrorx(SSL_R_INVALID_TICKET_KEYS_LENGTH); + return 0; + } + + memcpy(keys, ctx->tlsext_tick_key_name, 16); + memcpy(keys + 16, ctx->tlsext_tick_hmac_key, 16); + memcpy(keys + 32, ctx->tlsext_tick_aes_key, 16); + + return 1; +} + +static int +_SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, unsigned char *keys, int keys_len) +{ + if (keys == NULL) + return 48; + + if (keys_len != 48) { + SSLerrorx(SSL_R_INVALID_TICKET_KEYS_LENGTH); + return 0; + } + + memcpy(ctx->tlsext_tick_key_name, keys, 16); + memcpy(ctx->tlsext_tick_hmac_key, keys + 16, 16); + memcpy(ctx->tlsext_tick_aes_key, keys + 32, 16); + + return 1; +} + +static int +_SSL_CTX_get_tlsext_status_arg(SSL_CTX *ctx, void **arg) +{ + *arg = ctx->tlsext_status_arg; + return 1; +} + +static int +_SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg) +{ + ctx->tlsext_status_arg = arg; + return 1; +} + +int +SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) +{ + return ssl_cert_set0_chain(ctx, NULL, chain); +} +LSSL_ALIAS(SSL_CTX_set0_chain); + +int +SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) +{ + return ssl_cert_set1_chain(ctx, NULL, chain); +} +LSSL_ALIAS(SSL_CTX_set1_chain); + +int +SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) +{ + return ssl_cert_add0_chain_cert(ctx, NULL, x509); +} +LSSL_ALIAS(SSL_CTX_add0_chain_cert); + +int +SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) +{ + return ssl_cert_add1_chain_cert(ctx, NULL, x509); +} +LSSL_ALIAS(SSL_CTX_add1_chain_cert); + +int +SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) +{ + *out_chain = NULL; + + if (ctx->cert->key != NULL) + *out_chain = ctx->cert->key->chain; + + return 1; +} +LSSL_ALIAS(SSL_CTX_get0_chain_certs); + +int +SSL_CTX_clear_chain_certs(SSL_CTX *ctx) +{ + return ssl_cert_set0_chain(ctx, NULL, NULL); +} +LSSL_ALIAS(SSL_CTX_clear_chain_certs); + +static int +_SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *cert) +{ + if (ctx->extra_certs == NULL) { + if ((ctx->extra_certs = sk_X509_new_null()) == NULL) + return 0; + } + if (sk_X509_push(ctx->extra_certs, cert) == 0) + return 0; + + return 1; +} + +static int +_SSL_CTX_get_extra_chain_certs(SSL_CTX *ctx, STACK_OF(X509) **certs) +{ + *certs = ctx->extra_certs; + if (*certs == NULL) + *certs = ctx->cert->key->chain; + + return 1; +} + +static int +_SSL_CTX_get_extra_chain_certs_only(SSL_CTX *ctx, STACK_OF(X509) **certs) +{ + *certs = ctx->extra_certs; + return 1; +} + +static int +_SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) +{ + sk_X509_pop_free(ctx->extra_certs, X509_free); + ctx->extra_certs = NULL; + return 1; +} + +int +SSL_CTX_set1_groups(SSL_CTX *ctx, const int *groups, size_t groups_len) +{ + return tls1_set_groups(&ctx->tlsext_supportedgroups, + &ctx->tlsext_supportedgroups_length, groups, groups_len); +} +LSSL_ALIAS(SSL_CTX_set1_groups); + +int +SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups) +{ + return tls1_set_group_list(&ctx->tlsext_supportedgroups, + &ctx->tlsext_supportedgroups_length, groups); +} +LSSL_ALIAS(SSL_CTX_set1_groups_list); + +long +ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +{ + switch (cmd) { + case SSL_CTRL_SET_TMP_DH: + return _SSL_CTX_set_tmp_dh(ctx, parg); + + case SSL_CTRL_SET_TMP_DH_CB: + SSLerrorx(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_DH_AUTO: + return _SSL_CTX_set_dh_auto(ctx, larg); + + case SSL_CTRL_SET_TMP_ECDH: + return _SSL_CTX_set_tmp_ecdh(ctx, parg); + + case SSL_CTRL_SET_TMP_ECDH_CB: + SSLerrorx(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_ECDH_AUTO: + return _SSL_CTX_set_ecdh_auto(ctx, larg); + + case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: + return _SSL_CTX_set_tlsext_servername_arg(ctx, parg); + + case SSL_CTRL_GET_TLSEXT_TICKET_KEYS: + return _SSL_CTX_get_tlsext_ticket_keys(ctx, parg, larg); + + case SSL_CTRL_SET_TLSEXT_TICKET_KEYS: + return _SSL_CTX_set_tlsext_ticket_keys(ctx, parg, larg); + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG: + return _SSL_CTX_get_tlsext_status_arg(ctx, parg); + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG: + return _SSL_CTX_set_tlsext_status_arg(ctx, parg); + + case SSL_CTRL_CHAIN: + if (larg == 0) + return SSL_CTX_set0_chain(ctx, (STACK_OF(X509) *)parg); + else + return SSL_CTX_set1_chain(ctx, (STACK_OF(X509) *)parg); + + case SSL_CTRL_CHAIN_CERT: + if (larg == 0) + return SSL_CTX_add0_chain_cert(ctx, (X509 *)parg); + else + return SSL_CTX_add1_chain_cert(ctx, (X509 *)parg); + + case SSL_CTRL_GET_CHAIN_CERTS: + return SSL_CTX_get0_chain_certs(ctx, (STACK_OF(X509) **)parg); + + case SSL_CTRL_EXTRA_CHAIN_CERT: + return _SSL_CTX_add_extra_chain_cert(ctx, parg); + + case SSL_CTRL_GET_EXTRA_CHAIN_CERTS: + if (larg == 0) + return _SSL_CTX_get_extra_chain_certs(ctx, parg); + else + return _SSL_CTX_get_extra_chain_certs_only(ctx, parg); + + case SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS: + return _SSL_CTX_clear_extra_chain_certs(ctx); + + case SSL_CTRL_SET_GROUPS: + return SSL_CTX_set1_groups(ctx, parg, larg); + + case SSL_CTRL_SET_GROUPS_LIST: + return SSL_CTX_set1_groups_list(ctx, parg); + + case SSL_CTRL_GET_MIN_PROTO_VERSION: + return SSL_CTX_get_min_proto_version(ctx); + + case SSL_CTRL_GET_MAX_PROTO_VERSION: + return SSL_CTX_get_max_proto_version(ctx); + + case SSL_CTRL_SET_MIN_PROTO_VERSION: + if (larg < 0 || larg > UINT16_MAX) + return 0; + return SSL_CTX_set_min_proto_version(ctx, larg); + + case SSL_CTRL_SET_MAX_PROTO_VERSION: + if (larg < 0 || larg > UINT16_MAX) + return 0; + return SSL_CTX_set_max_proto_version(ctx, larg); + + /* + * Legacy controls that should eventually be removed. + */ + case SSL_CTRL_NEED_TMP_RSA: + return 0; + + case SSL_CTRL_SET_TMP_RSA: + case SSL_CTRL_SET_TMP_RSA_CB: + SSLerrorx(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + return 0; +} + +long +ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) +{ + switch (cmd) { + case SSL_CTRL_SET_TMP_RSA_CB: + SSLerrorx(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + + case SSL_CTRL_SET_TMP_DH_CB: + ctx->cert->dhe_params_cb = + (DH *(*)(SSL *, int, int))fp; + return 1; + + case SSL_CTRL_SET_TMP_ECDH_CB: + return 1; + + case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: + ctx->tlsext_servername_callback = + (int (*)(SSL *, int *, void *))fp; + return 1; + + case SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB: + *(int (**)(SSL *, void *))fp = ctx->tlsext_status_cb; + return 1; + + case SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB: + ctx->tlsext_status_cb = (int (*)(SSL *, void *))fp; + return 1; + + case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: + ctx->tlsext_ticket_key_cb = (int (*)(SSL *, unsigned char *, + unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int))fp; + return 1; + } + + return 0; +} + +SSL_CIPHER * +ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr) +{ + unsigned long alg_k, alg_a, mask_k, mask_a; + STACK_OF(SSL_CIPHER) *prio, *allow; + SSL_CIPHER *c, *ret = NULL; + int can_use_ecc; + int i, ii, nid, ok; + SSL_CERT *cert; + + /* Let's see which ciphers we can support */ + cert = s->cert; + + can_use_ecc = tls1_get_supported_group(s, &nid); + + /* + * Do not set the compare functions, because this may lead to a + * reordering by "id". We want to keep the original ordering. + * We may pay a price in performance during sk_SSL_CIPHER_find(), + * but would have to pay with the price of sk_SSL_CIPHER_dup(). + */ + + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { + prio = srvr; + allow = clnt; + } else { + prio = clnt; + allow = srvr; + } + + for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) { + c = sk_SSL_CIPHER_value(prio, i); + + /* Skip TLS v1.2 only ciphersuites if not supported. */ + if ((c->algorithm_ssl & SSL_TLSV1_2) && + !SSL_USE_TLS1_2_CIPHERS(s)) + continue; + + /* Skip TLS v1.3 only ciphersuites if not supported. */ + if ((c->algorithm_ssl & SSL_TLSV1_3) && + !SSL_USE_TLS1_3_CIPHERS(s)) + continue; + + /* If TLS v1.3, only allow TLS v1.3 ciphersuites. */ + if (SSL_USE_TLS1_3_CIPHERS(s) && + !(c->algorithm_ssl & SSL_TLSV1_3)) + continue; + + if (!ssl_security_shared_cipher(s, c)) + continue; + + ssl_set_cert_masks(cert, c); + mask_k = cert->mask_k; + mask_a = cert->mask_a; + + alg_k = c->algorithm_mkey; + alg_a = c->algorithm_auth; + + ok = (alg_k & mask_k) && (alg_a & mask_a); + + /* + * If we are considering an ECC cipher suite that uses our + * certificate check it. + */ + if (alg_a & SSL_aECDSA) + ok = ok && tls1_check_ec_server_key(s); + /* + * If we are considering an ECC cipher suite that uses + * an ephemeral EC key check it. + */ + if (alg_k & SSL_kECDHE) + ok = ok && can_use_ecc; + + if (!ok) + continue; + ii = sk_SSL_CIPHER_find(allow, c); + if (ii >= 0) { + ret = sk_SSL_CIPHER_value(allow, ii); + break; + } + } + return (ret); +} + +int +ssl3_get_req_cert_types(SSL *s, CBB *cbb) +{ + unsigned long alg_k; + + alg_k = s->s3->hs.cipher->algorithm_mkey; + +#ifndef OPENSSL_NO_GOST + if ((alg_k & SSL_kGOST) != 0) { + if (!CBB_add_u8(cbb, TLS_CT_GOST01_SIGN)) + return 0; + if (!CBB_add_u8(cbb, TLS_CT_GOST12_256_SIGN)) + return 0; + if (!CBB_add_u8(cbb, TLS_CT_GOST12_512_SIGN)) + return 0; + if (!CBB_add_u8(cbb, TLS_CT_GOST12_256_SIGN_COMPAT)) + return 0; + if (!CBB_add_u8(cbb, TLS_CT_GOST12_512_SIGN_COMPAT)) + return 0; + } +#endif + + if ((alg_k & SSL_kDHE) != 0) { + if (!CBB_add_u8(cbb, SSL3_CT_RSA_FIXED_DH)) + return 0; + } + + if (!CBB_add_u8(cbb, SSL3_CT_RSA_SIGN)) + return 0; + + /* + * ECDSA certs can be used with RSA cipher suites as well + * so we don't need to check for SSL_kECDH or SSL_kECDHE. + */ + if (!CBB_add_u8(cbb, TLS_CT_ECDSA_SIGN)) + return 0; + + return 1; +} + +int +ssl3_shutdown(SSL *s) +{ + int ret; + + /* + * Don't do anything much if we have not done the handshake or + * we don't want to send messages :-) + */ + if ((s->quiet_shutdown) || (s->s3->hs.state == SSL_ST_BEFORE)) { + s->shutdown = (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); + return (1); + } + + if (!(s->shutdown & SSL_SENT_SHUTDOWN)) { + s->shutdown|=SSL_SENT_SHUTDOWN; + ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY); + /* + * Our shutdown alert has been sent now, and if it still needs + * to be written, s->s3->alert_dispatch will be true + */ + if (s->s3->alert_dispatch) + return (-1); /* return WANT_WRITE */ + } else if (s->s3->alert_dispatch) { + /* resend it if not sent */ + ret = ssl3_dispatch_alert(s); + if (ret == -1) { + /* + * We only get to return -1 here the 2nd/Nth + * invocation, we must have already signalled + * return 0 upon a previous invoation, + * return WANT_WRITE + */ + return (ret); + } + } else if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { + /* If we are waiting for a close from our peer, we are closed */ + s->method->ssl_read_bytes(s, 0, NULL, 0, 0); + if (!(s->shutdown & SSL_RECEIVED_SHUTDOWN)) { + return (-1); /* return WANT_READ */ + } + } + + if ((s->shutdown == (SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN)) && + !s->s3->alert_dispatch) + return (1); + else + return (0); +} + +int +ssl3_write(SSL *s, const void *buf, int len) +{ + errno = 0; + + if (s->s3->renegotiate) + ssl3_renegotiate_check(s); + + return s->method->ssl_write_bytes(s, SSL3_RT_APPLICATION_DATA, + buf, len); +} + +static int +ssl3_read_internal(SSL *s, void *buf, int len, int peek) +{ + int ret; + + errno = 0; + if (s->s3->renegotiate) + ssl3_renegotiate_check(s); + s->s3->in_read_app_data = 1; + + ret = s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, buf, len, + peek); + if ((ret == -1) && (s->s3->in_read_app_data == 2)) { + /* + * ssl3_read_bytes decided to call s->handshake_func, + * which called ssl3_read_bytes to read handshake data. + * However, ssl3_read_bytes actually found application data + * and thinks that application data makes sense here; so disable + * handshake processing and try to read application data again. + */ + s->in_handshake++; + ret = s->method->ssl_read_bytes(s, SSL3_RT_APPLICATION_DATA, + buf, len, peek); + s->in_handshake--; + } else + s->s3->in_read_app_data = 0; + + return (ret); +} + +int +ssl3_read(SSL *s, void *buf, int len) +{ + return ssl3_read_internal(s, buf, len, 0); +} + +int +ssl3_peek(SSL *s, void *buf, int len) +{ + return ssl3_read_internal(s, buf, len, 1); +} + +int +ssl3_renegotiate(SSL *s) +{ + if (s->handshake_func == NULL) + return 1; + + if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) + return 0; + + s->s3->renegotiate = 1; + + return 1; +} + +int +ssl3_renegotiate_check(SSL *s) +{ + if (!s->s3->renegotiate) + return 0; + if (SSL_in_init(s) || s->s3->rbuf.left != 0 || s->s3->wbuf.left != 0) + return 0; + + s->s3->hs.state = SSL_ST_RENEGOTIATE; + s->s3->renegotiate = 0; + s->s3->num_renegotiations++; + s->s3->total_renegotiations++; + + return 1; +} diff --git a/ssl/srtp.h b/ssl/srtp.h new file mode 100644 index 0000000..89ce862 --- /dev/null +++ b/ssl/srtp.h @@ -0,0 +1,146 @@ +/* $OpenBSD: srtp.h,v 1.7 2021/06/11 15:28:13 landry Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* + * DTLS code by Eric Rescorla + * + * Copyright (C) 2006, Network Resonance, Inc. + * Copyright (C) 2011, RTFM, Inc. + */ + +#ifndef HEADER_D1_SRTP_H +#define HEADER_D1_SRTP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SRTP_AES128_CM_SHA1_80 0x0001 +#define SRTP_AES128_CM_SHA1_32 0x0002 +#define SRTP_AES128_F8_SHA1_80 0x0003 +#define SRTP_AES128_F8_SHA1_32 0x0004 +#define SRTP_NULL_SHA1_80 0x0005 +#define SRTP_NULL_SHA1_32 0x0006 + +/* AEAD SRTP protection profiles from RFC 7714 */ +#define SRTP_AEAD_AES_128_GCM 0x0007 +#define SRTP_AEAD_AES_256_GCM 0x0008 + +int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles); +int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles); + +STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *ssl); +SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c new file mode 100644 index 0000000..684697d --- /dev/null +++ b/ssl/ssl_algs.c @@ -0,0 +1,125 @@ +/* $OpenBSD: ssl_algs.c,v 1.32 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include + +#include "ssl_local.h" + +int +SSL_library_init(void) +{ + +#ifndef OPENSSL_NO_DES + EVP_add_cipher(EVP_des_cbc()); + EVP_add_cipher(EVP_des_ede3_cbc()); +#endif +#ifndef OPENSSL_NO_RC4 + EVP_add_cipher(EVP_rc4()); +#if !defined(OPENSSL_NO_MD5) && (defined(__x86_64) || defined(__x86_64__)) + EVP_add_cipher(EVP_rc4_hmac_md5()); +#endif +#endif +#ifndef OPENSSL_NO_RC2 + EVP_add_cipher(EVP_rc2_cbc()); + /* Not actually used for SSL/TLS but this makes PKCS#12 work + * if an application only calls SSL_library_init(). + */ + EVP_add_cipher(EVP_rc2_40_cbc()); +#endif + EVP_add_cipher(EVP_aes_128_cbc()); + EVP_add_cipher(EVP_aes_192_cbc()); + EVP_add_cipher(EVP_aes_256_cbc()); + EVP_add_cipher(EVP_aes_128_gcm()); + EVP_add_cipher(EVP_aes_256_gcm()); + EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); + EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); +#ifndef OPENSSL_NO_CAMELLIA + EVP_add_cipher(EVP_camellia_128_cbc()); + EVP_add_cipher(EVP_camellia_256_cbc()); +#endif +#ifndef OPENSSL_NO_GOST + EVP_add_cipher(EVP_gost2814789_cfb64()); + EVP_add_cipher(EVP_gost2814789_cnt()); +#endif + + EVP_add_digest(EVP_md5()); + EVP_add_digest(EVP_md5_sha1()); + EVP_add_digest_alias(SN_md5, "ssl2-md5"); + EVP_add_digest_alias(SN_md5, "ssl3-md5"); + + EVP_add_digest(EVP_sha1()); /* RSA with sha1 */ + EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); + EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); + EVP_add_digest(EVP_sha224()); + EVP_add_digest(EVP_sha256()); + EVP_add_digest(EVP_sha384()); + EVP_add_digest(EVP_sha512()); +#ifndef OPENSSL_NO_GOST + EVP_add_digest(EVP_gostr341194()); + EVP_add_digest(EVP_gost2814789imit()); + EVP_add_digest(EVP_streebog256()); + EVP_add_digest(EVP_streebog512()); +#endif + + return (1); +} +LSSL_ALIAS(SSL_library_init); diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c new file mode 100644 index 0000000..f4552f1 --- /dev/null +++ b/ssl/ssl_asn1.c @@ -0,0 +1,420 @@ +/* $OpenBSD: ssl_asn1.c,v 1.67 2023/07/08 16:40:13 beck Exp $ */ +/* + * Copyright (c) 2016 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" + +#define SSLASN1_TAG (CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC) +#define SSLASN1_TIME_TAG (SSLASN1_TAG | 1) +#define SSLASN1_TIMEOUT_TAG (SSLASN1_TAG | 2) +#define SSLASN1_PEER_CERT_TAG (SSLASN1_TAG | 3) +#define SSLASN1_SESSION_ID_CTX_TAG (SSLASN1_TAG | 4) +#define SSLASN1_VERIFY_RESULT_TAG (SSLASN1_TAG | 5) +#define SSLASN1_HOSTNAME_TAG (SSLASN1_TAG | 6) +#define SSLASN1_LIFETIME_TAG (SSLASN1_TAG | 9) +#define SSLASN1_TICKET_TAG (SSLASN1_TAG | 10) + +static uint64_t +time_max(void) +{ + if (sizeof(time_t) == sizeof(int32_t)) + return INT32_MAX; + if (sizeof(time_t) == sizeof(int64_t)) + return INT64_MAX; + return 0; +} + +static int +SSL_SESSION_encode(SSL_SESSION *s, unsigned char **out, size_t *out_len, + int ticket_encoding) +{ + CBB cbb, session, cipher_suite, session_id, master_key, time, timeout; + CBB peer_cert, sidctx, verify_result, hostname, lifetime, ticket, value; + unsigned char *peer_cert_bytes = NULL; + int len, rv = 0; + uint16_t cid; + + if (!CBB_init(&cbb, 0)) + goto err; + + if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE)) + goto err; + + /* Session ASN1 version. */ + if (!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION)) + goto err; + + /* TLS/SSL protocol version. */ + if (s->ssl_version < 0) + goto err; + if (!CBB_add_asn1_uint64(&session, s->ssl_version)) + goto err; + + /* Cipher suite ID. */ + /* XXX - require cipher to be non-NULL or always/only use cipher_id. */ + cid = (uint16_t)(s->cipher_id & SSL3_CK_VALUE_MASK); + if (s->cipher != NULL) + cid = ssl3_cipher_get_value(s->cipher); + if (!CBB_add_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_u16(&cipher_suite, cid)) + goto err; + + /* Session ID - zero length for a ticket. */ + if (!CBB_add_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_bytes(&session_id, s->session_id, + ticket_encoding ? 0 : s->session_id_length)) + goto err; + + /* Master key. */ + if (!CBB_add_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_bytes(&master_key, s->master_key, s->master_key_length)) + goto err; + + /* Time [1]. */ + if (s->time != 0) { + if (s->time < 0) + goto err; + if (!CBB_add_asn1(&session, &time, SSLASN1_TIME_TAG)) + goto err; + if (!CBB_add_asn1_uint64(&time, s->time)) + goto err; + } + + /* Timeout [2]. */ + if (s->timeout != 0) { + if (s->timeout < 0) + goto err; + if (!CBB_add_asn1(&session, &timeout, SSLASN1_TIMEOUT_TAG)) + goto err; + if (!CBB_add_asn1_uint64(&timeout, s->timeout)) + goto err; + } + + /* Peer certificate [3]. */ + if (s->peer_cert != NULL) { + if ((len = i2d_X509(s->peer_cert, &peer_cert_bytes)) <= 0) + goto err; + if (!CBB_add_asn1(&session, &peer_cert, SSLASN1_PEER_CERT_TAG)) + goto err; + if (!CBB_add_bytes(&peer_cert, peer_cert_bytes, len)) + goto err; + } + + /* Session ID context [4]. */ + /* XXX - Actually handle this as optional? */ + if (!CBB_add_asn1(&session, &sidctx, SSLASN1_SESSION_ID_CTX_TAG)) + goto err; + if (!CBB_add_asn1(&sidctx, &value, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_bytes(&value, s->sid_ctx, s->sid_ctx_length)) + goto err; + + /* Verify result [5]. */ + if (s->verify_result != X509_V_OK) { + if (s->verify_result < 0) + goto err; + if (!CBB_add_asn1(&session, &verify_result, + SSLASN1_VERIFY_RESULT_TAG)) + goto err; + if (!CBB_add_asn1_uint64(&verify_result, s->verify_result)) + goto err; + } + + /* Hostname [6]. */ + if (s->tlsext_hostname != NULL) { + if (!CBB_add_asn1(&session, &hostname, SSLASN1_HOSTNAME_TAG)) + goto err; + if (!CBB_add_asn1(&hostname, &value, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_bytes(&value, (const uint8_t *)s->tlsext_hostname, + strlen(s->tlsext_hostname))) + goto err; + } + + /* PSK identity hint [7]. */ + /* PSK identity [8]. */ + + /* Ticket lifetime hint [9]. */ + if (s->tlsext_tick_lifetime_hint > 0) { + if (!CBB_add_asn1(&session, &lifetime, SSLASN1_LIFETIME_TAG)) + goto err; + if (!CBB_add_asn1_uint64(&lifetime, + s->tlsext_tick_lifetime_hint)) + goto err; + } + + /* Ticket [10]. */ + if (s->tlsext_tick != NULL) { + if (!CBB_add_asn1(&session, &ticket, SSLASN1_TICKET_TAG)) + goto err; + if (!CBB_add_asn1(&ticket, &value, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBB_add_bytes(&value, s->tlsext_tick, s->tlsext_ticklen)) + goto err; + } + + /* Compression method [11]. */ + /* SRP username [12]. */ + + if (!CBB_finish(&cbb, out, out_len)) + goto err; + + rv = 1; + + err: + CBB_cleanup(&cbb); + free(peer_cert_bytes); + + return rv; +} + +int +SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len) +{ + if (ss == NULL) + return 0; + + if (ss->cipher == NULL && ss->cipher_id == 0) + return 0; + + return SSL_SESSION_encode(ss, out, out_len, 1); +} + +int +i2d_SSL_SESSION(SSL_SESSION *ss, unsigned char **pp) +{ + unsigned char *data = NULL; + size_t data_len = 0; + int rv = -1; + + if (ss == NULL) + return 0; + + if (ss->cipher == NULL && ss->cipher_id == 0) + return 0; + + if (!SSL_SESSION_encode(ss, &data, &data_len, 0)) + goto err; + + if (data_len > INT_MAX) + goto err; + + if (pp != NULL) { + if (*pp == NULL) { + *pp = data; + data = NULL; + } else { + memcpy(*pp, data, data_len); + *pp += data_len; + } + } + + rv = (int)data_len; + + err: + freezero(data, data_len); + + return rv; +} +LSSL_ALIAS(i2d_SSL_SESSION); + +SSL_SESSION * +d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length) +{ + CBS cbs, session, cipher_suite, session_id, master_key, peer_cert; + CBS hostname, ticket; + uint64_t version, tls_version, stime, timeout, verify_result, lifetime; + const unsigned char *peer_cert_bytes; + uint16_t cipher_value; + SSL_SESSION *s = NULL; + size_t data_len; + int present; + + if (a != NULL) + s = *a; + + if (s == NULL) { + if ((s = SSL_SESSION_new()) == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); + } + } + + CBS_init(&cbs, *pp, length); + + if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE)) + goto err; + + /* Session ASN1 version. */ + if (!CBS_get_asn1_uint64(&session, &version)) + goto err; + if (version != SSL_SESSION_ASN1_VERSION) + goto err; + + /* TLS/SSL Protocol Version. */ + if (!CBS_get_asn1_uint64(&session, &tls_version)) + goto err; + if (tls_version > INT_MAX) + goto err; + s->ssl_version = (int)tls_version; + + /* Cipher suite. */ + if (!CBS_get_asn1(&session, &cipher_suite, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBS_get_u16(&cipher_suite, &cipher_value)) + goto err; + if (CBS_len(&cipher_suite) != 0) + goto err; + + /* XXX - populate cipher instead? */ + s->cipher = NULL; + s->cipher_id = SSL3_CK_ID | cipher_value; + + /* Session ID. */ + if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBS_write_bytes(&session_id, s->session_id, sizeof(s->session_id), + &s->session_id_length)) + goto err; + + /* Master key. */ + if (!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING)) + goto err; + if (!CBS_write_bytes(&master_key, s->master_key, sizeof(s->master_key), + &s->master_key_length)) + goto err; + + /* Time [1]. */ + s->time = time(NULL); + if (!CBS_get_optional_asn1_uint64(&session, &stime, SSLASN1_TIME_TAG, + 0)) + goto err; + if (stime > time_max()) + goto err; + if (stime != 0) + s->time = (time_t)stime; + + /* Timeout [2]. */ + s->timeout = 3; + if (!CBS_get_optional_asn1_uint64(&session, &timeout, + SSLASN1_TIMEOUT_TAG, 0)) + goto err; + if (timeout > LONG_MAX) + goto err; + if (timeout != 0) + s->timeout = (long)timeout; + + /* Peer certificate [3]. */ + X509_free(s->peer_cert); + s->peer_cert = NULL; + if (!CBS_get_optional_asn1(&session, &peer_cert, &present, + SSLASN1_PEER_CERT_TAG)) + goto err; + if (present) { + data_len = CBS_len(&peer_cert); + if (data_len > LONG_MAX) + goto err; + peer_cert_bytes = CBS_data(&peer_cert); + if (d2i_X509(&s->peer_cert, &peer_cert_bytes, + (long)data_len) == NULL) + goto err; + } + + /* Session ID context [4]. */ + s->sid_ctx_length = 0; + if (!CBS_get_optional_asn1_octet_string(&session, &session_id, &present, + SSLASN1_SESSION_ID_CTX_TAG)) + goto err; + if (present) { + if (!CBS_write_bytes(&session_id, (uint8_t *)&s->sid_ctx, + sizeof(s->sid_ctx), &s->sid_ctx_length)) + goto err; + } + + /* Verify result [5]. */ + s->verify_result = X509_V_OK; + if (!CBS_get_optional_asn1_uint64(&session, &verify_result, + SSLASN1_VERIFY_RESULT_TAG, X509_V_OK)) + goto err; + if (verify_result > LONG_MAX) + goto err; + s->verify_result = (long)verify_result; + + /* Hostname [6]. */ + free(s->tlsext_hostname); + s->tlsext_hostname = NULL; + if (!CBS_get_optional_asn1_octet_string(&session, &hostname, &present, + SSLASN1_HOSTNAME_TAG)) + goto err; + if (present) { + if (CBS_contains_zero_byte(&hostname)) + goto err; + if (!CBS_strdup(&hostname, &s->tlsext_hostname)) + goto err; + } + + /* PSK identity hint [7]. */ + /* PSK identity [8]. */ + + /* Ticket lifetime [9]. */ + s->tlsext_tick_lifetime_hint = 0; + if (!CBS_get_optional_asn1_uint64(&session, &lifetime, + SSLASN1_LIFETIME_TAG, 0)) + goto err; + if (lifetime > UINT32_MAX) + goto err; + if (lifetime > 0) + s->tlsext_tick_lifetime_hint = (uint32_t)lifetime; + + /* Ticket [10]. */ + free(s->tlsext_tick); + s->tlsext_tick = NULL; + if (!CBS_get_optional_asn1_octet_string(&session, &ticket, &present, + SSLASN1_TICKET_TAG)) + goto err; + if (present) { + if (!CBS_stow(&ticket, &s->tlsext_tick, &s->tlsext_ticklen)) + goto err; + } + + /* Compression method [11]. */ + /* SRP username [12]. */ + + *pp = CBS_data(&cbs); + + if (a != NULL) + *a = s; + + return (s); + + err: + ERR_asprintf_error_data("offset=%d", (int)(CBS_data(&cbs) - *pp)); + + if (s != NULL && (a == NULL || *a != s)) + SSL_SESSION_free(s); + + return (NULL); +} +LSSL_ALIAS(d2i_SSL_SESSION); diff --git a/ssl/ssl_both.c b/ssl/ssl_both.c new file mode 100644 index 0000000..14d9aa8 --- /dev/null +++ b/ssl/ssl_both.c @@ -0,0 +1,580 @@ +/* $OpenBSD: ssl_both.c,v 1.46 2023/07/07 08:53:55 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" + +/* + * Send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or + * SSL3_RT_CHANGE_CIPHER_SPEC). + */ +int +ssl3_do_write(SSL *s, int type) +{ + int ret; + + ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off], + s->init_num); + if (ret < 0) + return (-1); + + if (type == SSL3_RT_HANDSHAKE) + /* + * Should not be done for 'Hello Request's, but in that case + * we'll ignore the result anyway. + */ + tls1_transcript_record(s, + (unsigned char *)&s->init_buf->data[s->init_off], ret); + + if (ret == s->init_num) { + ssl_msg_callback(s, 1, type, s->init_buf->data, + (size_t)(s->init_off + s->init_num)); + return (1); + } + + s->init_off += ret; + s->init_num -= ret; + + return (0); +} + +static int +ssl3_add_cert(CBB *cbb, X509 *x) +{ + unsigned char *data; + int cert_len; + int ret = 0; + CBB cert; + + if ((cert_len = i2d_X509(x, NULL)) < 0) + goto err; + + if (!CBB_add_u24_length_prefixed(cbb, &cert)) + goto err; + if (!CBB_add_space(&cert, &data, cert_len)) + goto err; + if (i2d_X509(x, &data) < 0) + goto err; + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + return (ret); +} + +int +ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk) +{ + X509_STORE_CTX *xs_ctx = NULL; + STACK_OF(X509) *chain; + CBB cert_list; + X509 *x; + int ret = 0; + int i; + + if (!CBB_add_u24_length_prefixed(cbb, &cert_list)) + goto err; + + /* Send an empty certificate list when no certificate is available. */ + if (cpk == NULL) + goto done; + + if ((chain = cpk->chain) == NULL) + chain = s->ctx->extra_certs; + + if (chain != NULL || (s->mode & SSL_MODE_NO_AUTO_CHAIN)) { + if (!ssl3_add_cert(&cert_list, cpk->x509)) + goto err; + } else { + if ((xs_ctx = X509_STORE_CTX_new()) == NULL) + goto err; + if (!X509_STORE_CTX_init(xs_ctx, s->ctx->cert_store, + cpk->x509, NULL)) { + SSLerror(s, ERR_R_X509_LIB); + goto err; + } + X509_VERIFY_PARAM_set_flags(X509_STORE_CTX_get0_param(xs_ctx), + X509_V_FLAG_LEGACY_VERIFY); + X509_verify_cert(xs_ctx); + ERR_clear_error(); + chain = X509_STORE_CTX_get0_chain(xs_ctx); + } + + for (i = 0; i < sk_X509_num(chain); i++) { + x = sk_X509_value(chain, i); + if (!ssl3_add_cert(&cert_list, x)) + goto err; + } + + done: + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + X509_STORE_CTX_free(xs_ctx); + + return (ret); +} + +/* + * Obtain handshake message of message type 'mt' (any if mt == -1), + * maximum acceptable body length 'max'. + * The first four bytes (msg_type and length) are read in state 'st1', + * the body is read in state 'stn'. + */ +int +ssl3_get_message(SSL *s, int st1, int stn, int mt, long max) +{ + unsigned char *p; + uint32_t l; + long n; + int i, al; + CBS cbs; + uint8_t u8; + + if (SSL_is_dtls(s)) + return dtls1_get_message(s, st1, stn, mt, max); + + if (s->s3->hs.tls12.reuse_message) { + s->s3->hs.tls12.reuse_message = 0; + if ((mt >= 0) && (s->s3->hs.tls12.message_type != mt)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + s->init_msg = s->init_buf->data + + SSL3_HM_HEADER_LENGTH; + s->init_num = (int)s->s3->hs.tls12.message_size; + return 1; + } + + p = (unsigned char *)s->init_buf->data; + + if (s->s3->hs.state == st1) { + int skip_message; + + do { + while (s->init_num < SSL3_HM_HEADER_LENGTH) { + i = s->method->ssl_read_bytes(s, + SSL3_RT_HANDSHAKE, &p[s->init_num], + SSL3_HM_HEADER_LENGTH - s->init_num, 0); + if (i <= 0) { + s->rwstate = SSL_READING; + return i; + } + s->init_num += i; + } + + skip_message = 0; + if (!s->server && p[0] == SSL3_MT_HELLO_REQUEST) { + /* + * The server may always send 'Hello Request' + * messages -- we are doing a handshake anyway + * now, so ignore them if their format is + * correct. Does not count for 'Finished' MAC. + */ + if (p[1] == 0 && p[2] == 0 &&p[3] == 0) { + s->init_num = 0; + skip_message = 1; + + ssl_msg_callback(s, 0, + SSL3_RT_HANDSHAKE, p, + SSL3_HM_HEADER_LENGTH); + } + } + } while (skip_message); + + if ((mt >= 0) && (*p != mt)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + + CBS_init(&cbs, p, SSL3_HM_HEADER_LENGTH); + if (!CBS_get_u8(&cbs, &u8) || + !CBS_get_u24(&cbs, &l)) { + SSLerror(s, ERR_R_BUF_LIB); + goto err; + } + s->s3->hs.tls12.message_type = u8; + + if (l > (unsigned long)max) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto fatal_err; + } + if (l && !BUF_MEM_grow_clean(s->init_buf, + l + SSL3_HM_HEADER_LENGTH)) { + SSLerror(s, ERR_R_BUF_LIB); + goto err; + } + s->s3->hs.tls12.message_size = l; + s->s3->hs.state = stn; + + s->init_msg = s->init_buf->data + + SSL3_HM_HEADER_LENGTH; + s->init_num = 0; + } + + /* next state (stn) */ + p = s->init_msg; + n = s->s3->hs.tls12.message_size - s->init_num; + while (n > 0) { + i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, + &p[s->init_num], n, 0); + if (i <= 0) { + s->rwstate = SSL_READING; + return i; + } + s->init_num += i; + n -= i; + } + + /* Feed this message into MAC computation. */ + if (s->mac_packet) { + tls1_transcript_record(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH); + + ssl_msg_callback(s, 0, SSL3_RT_HANDSHAKE, + s->init_buf->data, + (size_t)s->init_num + SSL3_HM_HEADER_LENGTH); + } + + return 1; + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return -1; +} + +int +ssl_cert_type(EVP_PKEY *pkey) +{ + if (pkey == NULL) + return -1; + + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_EC: + return SSL_PKEY_ECC; + case NID_id_GostR3410_2001: + case NID_id_GostR3410_2001_cc: + return SSL_PKEY_GOST01; + case EVP_PKEY_RSA: + case EVP_PKEY_RSA_PSS: + return SSL_PKEY_RSA; + } + + return -1; +} + +int +ssl_verify_alarm_type(long type) +{ + int al; + + switch (type) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_GET_CRL: + case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: + al = SSL_AD_UNKNOWN_CA; + break; + case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CRL_NOT_YET_VALID: + case X509_V_ERR_CERT_UNTRUSTED: + case X509_V_ERR_CERT_REJECTED: + al = SSL_AD_BAD_CERTIFICATE; + break; + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_CRL_SIGNATURE_FAILURE: + al = SSL_AD_DECRYPT_ERROR; + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_CRL_HAS_EXPIRED: + al = SSL_AD_CERTIFICATE_EXPIRED; + break; + case X509_V_ERR_CERT_REVOKED: + al = SSL_AD_CERTIFICATE_REVOKED; + break; + case X509_V_ERR_OUT_OF_MEM: + al = SSL_AD_INTERNAL_ERROR; + break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_INVALID_CA: + al = SSL_AD_UNKNOWN_CA; + break; + case X509_V_ERR_APPLICATION_VERIFICATION: + al = SSL_AD_HANDSHAKE_FAILURE; + break; + case X509_V_ERR_INVALID_PURPOSE: + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + break; + default: + al = SSL_AD_CERTIFICATE_UNKNOWN; + break; + } + return (al); +} + +int +ssl3_setup_init_buffer(SSL *s) +{ + BUF_MEM *buf = NULL; + + if (s->init_buf != NULL) + return (1); + + if ((buf = BUF_MEM_new()) == NULL) + goto err; + if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) + goto err; + + s->init_buf = buf; + return (1); + + err: + BUF_MEM_free(buf); + return (0); +} + +void +ssl3_release_init_buffer(SSL *s) +{ + BUF_MEM_free(s->init_buf); + s->init_buf = NULL; + s->init_msg = NULL; + s->init_num = 0; + s->init_off = 0; +} + +int +ssl3_setup_read_buffer(SSL *s) +{ + unsigned char *p; + size_t len, align, headerlen; + + if (SSL_is_dtls(s)) + headerlen = DTLS1_RT_HEADER_LENGTH; + else + headerlen = SSL3_RT_HEADER_LENGTH; + + align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); + + if (s->s3->rbuf.buf == NULL) { + len = SSL3_RT_MAX_PLAIN_LENGTH + + SSL3_RT_MAX_ENCRYPTED_OVERHEAD + headerlen + align; + if ((p = calloc(1, len)) == NULL) + goto err; + s->s3->rbuf.buf = p; + s->s3->rbuf.len = len; + } + + s->packet = s->s3->rbuf.buf; + return 1; + + err: + SSLerror(s, ERR_R_MALLOC_FAILURE); + return 0; +} + +int +ssl3_setup_write_buffer(SSL *s) +{ + unsigned char *p; + size_t len, align, headerlen; + + if (SSL_is_dtls(s)) + headerlen = DTLS1_RT_HEADER_LENGTH + 1; + else + headerlen = SSL3_RT_HEADER_LENGTH; + + align = (-SSL3_RT_HEADER_LENGTH) & (SSL3_ALIGN_PAYLOAD - 1); + + if (s->s3->wbuf.buf == NULL) { + len = s->max_send_fragment + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) + len += headerlen + align + + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; + + if ((p = calloc(1, len)) == NULL) + goto err; + s->s3->wbuf.buf = p; + s->s3->wbuf.len = len; + } + + return 1; + + err: + SSLerror(s, ERR_R_MALLOC_FAILURE); + return 0; +} + +int +ssl3_setup_buffers(SSL *s) +{ + if (!ssl3_setup_read_buffer(s)) + return 0; + if (!ssl3_setup_write_buffer(s)) + return 0; + return 1; +} + +void +ssl3_release_buffer(SSL3_BUFFER_INTERNAL *b) +{ + freezero(b->buf, b->len); + b->buf = NULL; + b->len = 0; +} + +void +ssl3_release_read_buffer(SSL *s) +{ + ssl3_release_buffer(&s->s3->rbuf); +} + +void +ssl3_release_write_buffer(SSL *s) +{ + ssl3_release_buffer(&s->s3->wbuf); +} diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c new file mode 100644 index 0000000..a288050 --- /dev/null +++ b/ssl/ssl_cert.c @@ -0,0 +1,741 @@ +/* $OpenBSD: ssl_cert.c,v 1.107 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ssl_local.h" + +int +SSL_get_ex_data_X509_STORE_CTX_idx(void) +{ + static volatile int ssl_x509_store_ctx_idx = -1; + int got_write_lock = 0; + + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + + if (ssl_x509_store_ctx_idx < 0) { + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + got_write_lock = 1; + + if (ssl_x509_store_ctx_idx < 0) { + ssl_x509_store_ctx_idx = + X509_STORE_CTX_get_ex_new_index( + 0, "SSL for verify callback", NULL, NULL, NULL); + } + } + + if (got_write_lock) + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + else + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + return ssl_x509_store_ctx_idx; +} +LSSL_ALIAS(SSL_get_ex_data_X509_STORE_CTX_idx); + +SSL_CERT * +ssl_cert_new(void) +{ + SSL_CERT *ret; + + ret = calloc(1, sizeof(SSL_CERT)); + if (ret == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); + } + ret->key = &(ret->pkeys[SSL_PKEY_RSA]); + ret->references = 1; + ret->security_cb = ssl_security_default_cb; + ret->security_level = OPENSSL_TLS_SECURITY_LEVEL; + ret->security_ex_data = NULL; + return (ret); +} + +SSL_CERT * +ssl_cert_dup(SSL_CERT *cert) +{ + SSL_CERT *ret; + int i; + + ret = calloc(1, sizeof(SSL_CERT)); + if (ret == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); + } + + /* + * same as ret->key = ret->pkeys + (cert->key - cert->pkeys), + * if you find that more readable + */ + ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; + + ret->valid = cert->valid; + ret->mask_k = cert->mask_k; + ret->mask_a = cert->mask_a; + + if (cert->dhe_params != NULL) { + ret->dhe_params = DHparams_dup(cert->dhe_params); + if (ret->dhe_params == NULL) { + SSLerrorx(ERR_R_DH_LIB); + goto err; + } + } + ret->dhe_params_cb = cert->dhe_params_cb; + ret->dhe_params_auto = cert->dhe_params_auto; + + for (i = 0; i < SSL_PKEY_NUM; i++) { + if (cert->pkeys[i].x509 != NULL) { + ret->pkeys[i].x509 = cert->pkeys[i].x509; + X509_up_ref(ret->pkeys[i].x509); + } + + if (cert->pkeys[i].privatekey != NULL) { + ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; + EVP_PKEY_up_ref(ret->pkeys[i].privatekey); + switch (i) { + /* + * If there was anything special to do for + * certain types of keys, we'd do it here. + * (Nothing at the moment, I think.) + */ + + case SSL_PKEY_RSA: + /* We have an RSA key. */ + break; + + case SSL_PKEY_ECC: + /* We have an ECC key */ + break; + + case SSL_PKEY_GOST01: + /* We have a GOST key */ + break; + + default: + /* Can't happen. */ + SSLerrorx(SSL_R_LIBRARY_BUG); + } + } + + if (cert->pkeys[i].chain != NULL) { + if ((ret->pkeys[i].chain = + X509_chain_up_ref(cert->pkeys[i].chain)) == NULL) + goto err; + } + } + + ret->security_cb = cert->security_cb; + ret->security_level = cert->security_level; + ret->security_ex_data = cert->security_ex_data; + + /* + * ret->extra_certs *should* exist, but currently the own certificate + * chain is held inside SSL_CTX + */ + + ret->references = 1; + + return (ret); + + err: + DH_free(ret->dhe_params); + + for (i = 0; i < SSL_PKEY_NUM; i++) { + X509_free(ret->pkeys[i].x509); + EVP_PKEY_free(ret->pkeys[i].privatekey); + sk_X509_pop_free(ret->pkeys[i].chain, X509_free); + } + free (ret); + return NULL; +} + + +void +ssl_cert_free(SSL_CERT *c) +{ + int i; + + if (c == NULL) + return; + + i = CRYPTO_add(&c->references, -1, CRYPTO_LOCK_SSL_CERT); + if (i > 0) + return; + + DH_free(c->dhe_params); + + for (i = 0; i < SSL_PKEY_NUM; i++) { + X509_free(c->pkeys[i].x509); + EVP_PKEY_free(c->pkeys[i].privatekey); + sk_X509_pop_free(c->pkeys[i].chain, X509_free); + } + + free(c); +} + +SSL_CERT * +ssl_get0_cert(SSL_CTX *ctx, SSL *ssl) +{ + if (ssl != NULL) + return ssl->cert; + + return ctx->cert; +} + +int +ssl_cert_set0_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain) +{ + SSL_CERT *ssl_cert; + SSL_CERT_PKEY *cpk; + X509 *x509; + int ssl_err; + int i; + + if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL) + return 0; + + if ((cpk = ssl_cert->key) == NULL) + return 0; + + for (i = 0; i < sk_X509_num(chain); i++) { + x509 = sk_X509_value(chain, i); + if (!ssl_security_cert(ctx, ssl, x509, 0, &ssl_err)) { + SSLerrorx(ssl_err); + return 0; + } + } + + sk_X509_pop_free(cpk->chain, X509_free); + cpk->chain = chain; + + return 1; +} + +int +ssl_cert_set1_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain) +{ + STACK_OF(X509) *new_chain = NULL; + + if (chain != NULL) { + if ((new_chain = X509_chain_up_ref(chain)) == NULL) + return 0; + } + if (!ssl_cert_set0_chain(ctx, ssl, new_chain)) { + sk_X509_pop_free(new_chain, X509_free); + return 0; + } + + return 1; +} + +int +ssl_cert_add0_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert) +{ + SSL_CERT *ssl_cert; + SSL_CERT_PKEY *cpk; + int ssl_err; + + if ((ssl_cert = ssl_get0_cert(ctx, ssl)) == NULL) + return 0; + + if ((cpk = ssl_cert->key) == NULL) + return 0; + + if (!ssl_security_cert(ctx, ssl, cert, 0, &ssl_err)) { + SSLerrorx(ssl_err); + return 0; + } + + if (cpk->chain == NULL) { + if ((cpk->chain = sk_X509_new_null()) == NULL) + return 0; + } + if (!sk_X509_push(cpk->chain, cert)) + return 0; + + return 1; +} + +int +ssl_cert_add1_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert) +{ + if (!ssl_cert_add0_chain_cert(ctx, ssl, cert)) + return 0; + + X509_up_ref(cert); + + return 1; +} + +int +ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *certs) +{ + X509_STORE_CTX *ctx = NULL; + X509_VERIFY_PARAM *param; + X509 *cert; + int ret = 0; + + if (sk_X509_num(certs) < 1) + goto err; + + if ((ctx = X509_STORE_CTX_new()) == NULL) + goto err; + + cert = sk_X509_value(certs, 0); + if (!X509_STORE_CTX_init(ctx, s->ctx->cert_store, cert, certs)) { + SSLerror(s, ERR_R_X509_LIB); + goto err; + } + X509_STORE_CTX_set_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx(), s); + + /* + * We need to inherit the verify parameters. These can be + * determined by the context: if its a server it will verify + * SSL client certificates or vice versa. + */ + X509_STORE_CTX_set_default(ctx, s->server ? "ssl_client" : "ssl_server"); + + param = X509_STORE_CTX_get0_param(ctx); + + X509_VERIFY_PARAM_set_auth_level(param, SSL_get_security_level(s)); + + /* + * Anything non-default in "param" should overwrite anything + * in the ctx. + */ + X509_VERIFY_PARAM_set1(param, s->param); + + if (s->verify_callback) + X509_STORE_CTX_set_verify_cb(ctx, s->verify_callback); + + if (s->ctx->app_verify_callback != NULL) + ret = s->ctx->app_verify_callback(ctx, + s->ctx->app_verify_arg); + else + ret = X509_verify_cert(ctx); + + s->verify_result = X509_STORE_CTX_get_error(ctx); + sk_X509_pop_free(s->s3->hs.verified_chain, X509_free); + s->s3->hs.verified_chain = NULL; + if (X509_STORE_CTX_get0_chain(ctx) != NULL) { + s->s3->hs.verified_chain = X509_STORE_CTX_get1_chain(ctx); + if (s->s3->hs.verified_chain == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + ret = 0; + } + } + + err: + X509_STORE_CTX_free(ctx); + + return (ret); +} + +static void +set_client_CA_list(STACK_OF(X509_NAME) **ca_list, + STACK_OF(X509_NAME) *name_list) +{ + sk_X509_NAME_pop_free(*ca_list, X509_NAME_free); + *ca_list = name_list; +} + +STACK_OF(X509_NAME) * +SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk) +{ + int i; + STACK_OF(X509_NAME) *ret; + X509_NAME *name = NULL; + + if ((ret = sk_X509_NAME_new_null()) == NULL) + goto err; + + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + if ((name = X509_NAME_dup(sk_X509_NAME_value(sk, i))) == NULL) + goto err; + if (!sk_X509_NAME_push(ret, name)) + goto err; + } + return (ret); + + err: + X509_NAME_free(name); + sk_X509_NAME_pop_free(ret, X509_NAME_free); + return NULL; +} +LSSL_ALIAS(SSL_dup_CA_list); + +void +SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list) +{ + set_client_CA_list(&(s->client_CA), name_list); +} +LSSL_ALIAS(SSL_set_client_CA_list); + +void +SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) +{ + set_client_CA_list(&(ctx->client_CA), name_list); +} +LSSL_ALIAS(SSL_CTX_set_client_CA_list); + +STACK_OF(X509_NAME) * +SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) +{ + return (ctx->client_CA); +} +LSSL_ALIAS(SSL_CTX_get_client_CA_list); + +STACK_OF(X509_NAME) * +SSL_get_client_CA_list(const SSL *s) +{ + if (!s->server) { + /* We are in the client. */ + if ((s->version >> 8) == SSL3_VERSION_MAJOR) + return (s->s3->hs.tls12.ca_names); + else + return (NULL); + } else { + if (s->client_CA != NULL) + return (s->client_CA); + else + return (s->ctx->client_CA); + } +} +LSSL_ALIAS(SSL_get_client_CA_list); + +static int +add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x) +{ + X509_NAME *name; + + if (x == NULL) + return (0); + if ((*sk == NULL) && ((*sk = sk_X509_NAME_new_null()) == NULL)) + return (0); + + if ((name = X509_NAME_dup(X509_get_subject_name(x))) == NULL) + return (0); + + if (!sk_X509_NAME_push(*sk, name)) { + X509_NAME_free(name); + return (0); + } + return (1); +} + +int +SSL_add_client_CA(SSL *ssl, X509 *x) +{ + return (add_client_CA(&(ssl->client_CA), x)); +} +LSSL_ALIAS(SSL_add_client_CA); + +int +SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x) +{ + return (add_client_CA(&(ctx->client_CA), x)); +} +LSSL_ALIAS(SSL_CTX_add_client_CA); + +static int +xname_cmp(const X509_NAME * const *a, const X509_NAME * const *b) +{ + return (X509_NAME_cmp(*a, *b)); +} + +/*! + * Load CA certs from a file into a ::STACK. Note that it is somewhat misnamed; + * it doesn't really have anything to do with clients (except that a common use + * for a stack of CAs is to send it to the client). Actually, it doesn't have + * much to do with CAs, either, since it will load any old cert. + * \param file the file containing one or more certs. + * \return a ::STACK containing the certs. + */ +STACK_OF(X509_NAME) * +SSL_load_client_CA_file(const char *file) +{ + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + STACK_OF(X509_NAME) *ret = NULL, *sk; + + sk = sk_X509_NAME_new(xname_cmp); + + in = BIO_new(BIO_s_file()); + + if ((sk == NULL) || (in == NULL)) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) + goto err; + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + if (ret == NULL) { + ret = sk_X509_NAME_new_null(); + if (ret == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + } + if ((xn = X509_get_subject_name(x)) == NULL) + goto err; + /* check for duplicates */ + xn = X509_NAME_dup(xn); + if (xn == NULL) + goto err; + if (sk_X509_NAME_find(sk, xn) >= 0) + X509_NAME_free(xn); + else { + if (!sk_X509_NAME_push(sk, xn)) + goto err; + if (!sk_X509_NAME_push(ret, xn)) + goto err; + } + } + + if (0) { + err: + sk_X509_NAME_pop_free(ret, X509_NAME_free); + ret = NULL; + } + sk_X509_NAME_free(sk); + BIO_free(in); + X509_free(x); + if (ret != NULL) + ERR_clear_error(); + + return (ret); +} +LSSL_ALIAS(SSL_load_client_CA_file); + +/*! + * Add a file of certs to a stack. + * \param stack the stack to add to. + * \param file the file to add from. All certs in this file that are not + * already in the stack will be added. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int +SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, + const char *file) +{ + BIO *in; + X509 *x = NULL; + X509_NAME *xn = NULL; + int ret = 1; + int (*oldcmp)(const X509_NAME * const *a, const X509_NAME * const *b); + + oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp); + + in = BIO_new(BIO_s_file()); + + if (in == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!BIO_read_filename(in, file)) + goto err; + + for (;;) { + if (PEM_read_bio_X509(in, &x, NULL, NULL) == NULL) + break; + if ((xn = X509_get_subject_name(x)) == NULL) + goto err; + xn = X509_NAME_dup(xn); + if (xn == NULL) + goto err; + if (sk_X509_NAME_find(stack, xn) >= 0) + X509_NAME_free(xn); + else + if (!sk_X509_NAME_push(stack, xn)) + goto err; + } + + ERR_clear_error(); + + if (0) { + err: + ret = 0; + } + BIO_free(in); + X509_free(x); + + (void)sk_X509_NAME_set_cmp_func(stack, oldcmp); + + return ret; +} +LSSL_ALIAS(SSL_add_file_cert_subjects_to_stack); + +/*! + * Add a directory of certs to a stack. + * \param stack the stack to append to. + * \param dir the directory to append from. All files in this directory will be + * examined as potential certs. Any that are acceptable to + * SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will + * be included. + * \return 1 for success, 0 for failure. Note that in the case of failure some + * certs may have been added to \c stack. + */ + +int +SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, const char *dir) +{ + DIR *dirp = NULL; + char *path = NULL; + int ret = 0; + + dirp = opendir(dir); + if (dirp) { + struct dirent *dp; + while ((dp = readdir(dirp)) != NULL) { + if (asprintf(&path, "%s/%s", dir, dp->d_name) != -1) { + ret = SSL_add_file_cert_subjects_to_stack( + stack, path); + free(path); + } + if (!ret) + break; + } + (void) closedir(dirp); + } + if (!ret) { + SYSerror(errno); + ERR_asprintf_error_data("opendir ('%s')", dir); + SSLerrorx(ERR_R_SYS_LIB); + } + return ret; +} +LSSL_ALIAS(SSL_add_dir_cert_subjects_to_stack); diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c new file mode 100644 index 0000000..b735cd7 --- /dev/null +++ b/ssl/ssl_ciph.c @@ -0,0 +1,1768 @@ +/* $OpenBSD: ssl_ciph.c,v 1.136 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include + +#include +#include + +#ifndef OPENSSL_NO_ENGINE +#include +#endif + +#include "ssl_local.h" + +#define CIPHER_ADD 1 +#define CIPHER_KILL 2 +#define CIPHER_DEL 3 +#define CIPHER_ORD 4 +#define CIPHER_SPECIAL 5 + +typedef struct cipher_order_st { + const SSL_CIPHER *cipher; + int active; + int dead; + struct cipher_order_st *next, *prev; +} CIPHER_ORDER; + +static const SSL_CIPHER cipher_aliases[] = { + + /* "ALL" doesn't include eNULL (must be specifically enabled) */ + { + .name = SSL_TXT_ALL, + .algorithm_enc = ~SSL_eNULL, + }, + + /* "COMPLEMENTOFALL" */ + { + .name = SSL_TXT_CMPALL, + .algorithm_enc = SSL_eNULL, + }, + + /* + * "COMPLEMENTOFDEFAULT" + * (does *not* include ciphersuites not found in ALL!) + */ + { + .name = SSL_TXT_CMPDEF, + .algorithm_mkey = SSL_kDHE|SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + .algorithm_enc = ~SSL_eNULL, + }, + + /* + * key exchange aliases + * (some of those using only a single bit here combine multiple key + * exchange algs according to the RFCs, e.g. kEDH combines DHE_DSS + * and DHE_RSA) + */ + { + .name = SSL_TXT_kRSA, + .algorithm_mkey = SSL_kRSA, + }, + { + .name = SSL_TXT_kEDH, + .algorithm_mkey = SSL_kDHE, + }, + { + .name = SSL_TXT_DH, + .algorithm_mkey = SSL_kDHE, + }, + { + .name = SSL_TXT_kEECDH, + .algorithm_mkey = SSL_kECDHE, + }, + { + .name = SSL_TXT_ECDH, + .algorithm_mkey = SSL_kECDHE, + }, + { + .name = SSL_TXT_kGOST, + .algorithm_mkey = SSL_kGOST, + }, + + /* server authentication aliases */ + { + .name = SSL_TXT_aRSA, + .algorithm_auth = SSL_aRSA, + }, + { + .name = SSL_TXT_aDSS, + .algorithm_auth = SSL_aDSS, + }, + { + .name = SSL_TXT_DSS, + .algorithm_auth = SSL_aDSS, + }, + { + .name = SSL_TXT_aNULL, + .algorithm_auth = SSL_aNULL, + }, + { + .name = SSL_TXT_aECDSA, + .algorithm_auth = SSL_aECDSA, + }, + { + .name = SSL_TXT_ECDSA, + .algorithm_auth = SSL_aECDSA, + }, + { + .name = SSL_TXT_aGOST01, + .algorithm_auth = SSL_aGOST01, + }, + { + .name = SSL_TXT_aGOST, + .algorithm_auth = SSL_aGOST01, + }, + + /* aliases combining key exchange and server authentication */ + { + .name = SSL_TXT_DHE, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = ~SSL_aNULL, + }, + { + .name = SSL_TXT_EDH, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = ~SSL_aNULL, + }, + { + .name = SSL_TXT_ECDHE, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = ~SSL_aNULL, + }, + { + .name = SSL_TXT_EECDH, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = ~SSL_aNULL, + }, + { + .name = SSL_TXT_NULL, + .algorithm_enc = SSL_eNULL, + }, + { + .name = SSL_TXT_RSA, + .algorithm_mkey = SSL_kRSA, + .algorithm_auth = SSL_aRSA, + }, + { + .name = SSL_TXT_ADH, + .algorithm_mkey = SSL_kDHE, + .algorithm_auth = SSL_aNULL, + }, + { + .name = SSL_TXT_AECDH, + .algorithm_mkey = SSL_kECDHE, + .algorithm_auth = SSL_aNULL, + }, + + /* symmetric encryption aliases */ + { + .name = SSL_TXT_3DES, + .algorithm_enc = SSL_3DES, + }, + { + .name = SSL_TXT_RC4, + .algorithm_enc = SSL_RC4, + }, + { + .name = SSL_TXT_eNULL, + .algorithm_enc = SSL_eNULL, + }, + { + .name = SSL_TXT_AES128, + .algorithm_enc = SSL_AES128|SSL_AES128GCM, + }, + { + .name = SSL_TXT_AES256, + .algorithm_enc = SSL_AES256|SSL_AES256GCM, + }, + { + .name = SSL_TXT_AES, + .algorithm_enc = SSL_AES, + }, + { + .name = SSL_TXT_AES_GCM, + .algorithm_enc = SSL_AES128GCM|SSL_AES256GCM, + }, + { + .name = SSL_TXT_CAMELLIA128, + .algorithm_enc = SSL_CAMELLIA128, + }, + { + .name = SSL_TXT_CAMELLIA256, + .algorithm_enc = SSL_CAMELLIA256, + }, + { + .name = SSL_TXT_CAMELLIA, + .algorithm_enc = SSL_CAMELLIA128|SSL_CAMELLIA256, + }, + { + .name = SSL_TXT_CHACHA20, + .algorithm_enc = SSL_CHACHA20POLY1305, + }, + + /* MAC aliases */ + { + .name = SSL_TXT_AEAD, + .algorithm_mac = SSL_AEAD, + }, + { + .name = SSL_TXT_MD5, + .algorithm_mac = SSL_MD5, + }, + { + .name = SSL_TXT_SHA1, + .algorithm_mac = SSL_SHA1, + }, + { + .name = SSL_TXT_SHA, + .algorithm_mac = SSL_SHA1, + }, + { + .name = SSL_TXT_GOST94, + .algorithm_mac = SSL_GOST94, + }, + { + .name = SSL_TXT_GOST89MAC, + .algorithm_mac = SSL_GOST89MAC, + }, + { + .name = SSL_TXT_SHA256, + .algorithm_mac = SSL_SHA256, + }, + { + .name = SSL_TXT_SHA384, + .algorithm_mac = SSL_SHA384, + }, + { + .name = SSL_TXT_STREEBOG256, + .algorithm_mac = SSL_STREEBOG256, + }, + + /* protocol version aliases */ + { + .name = SSL_TXT_SSLV3, + .algorithm_ssl = SSL_SSLV3, + }, + { + .name = SSL_TXT_TLSV1, + .algorithm_ssl = SSL_TLSV1, + }, + { + .name = SSL_TXT_TLSV1_2, + .algorithm_ssl = SSL_TLSV1_2, + }, + { + .name = SSL_TXT_TLSV1_3, + .algorithm_ssl = SSL_TLSV1_3, + }, + + /* cipher suite aliases */ +#ifdef LIBRESSL_HAS_TLS1_3 + { + .valid = 1, + .name = "TLS_AES_128_GCM_SHA256", + .id = TLS1_3_CK_AES_128_GCM_SHA256, + .algorithm_ssl = SSL_TLSV1_3, + }, + { + .valid = 1, + .name = "TLS_AES_256_GCM_SHA384", + .id = TLS1_3_CK_AES_256_GCM_SHA384, + .algorithm_ssl = SSL_TLSV1_3, + }, + { + .valid = 1, + .name = "TLS_CHACHA20_POLY1305_SHA256", + .id = TLS1_3_CK_CHACHA20_POLY1305_SHA256, + .algorithm_ssl = SSL_TLSV1_3, + }, +#endif + + /* strength classes */ + { + .name = SSL_TXT_LOW, + .algo_strength = SSL_LOW, + }, + { + .name = SSL_TXT_MEDIUM, + .algo_strength = SSL_MEDIUM, + }, + { + .name = SSL_TXT_HIGH, + .algo_strength = SSL_HIGH, + }, +}; + +int +ssl_cipher_get_evp(const SSL_SESSION *ss, const EVP_CIPHER **enc, + const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size) +{ + *enc = NULL; + *md = NULL; + *mac_pkey_type = NID_undef; + *mac_secret_size = 0; + + if (ss->cipher == NULL) + return 0; + + /* + * This function does not handle EVP_AEAD. + * See ssl_cipher_get_evp_aead instead. + */ + if (ss->cipher->algorithm_mac & SSL_AEAD) + return 0; + + switch (ss->cipher->algorithm_enc) { + case SSL_3DES: + *enc = EVP_des_ede3_cbc(); + break; + case SSL_RC4: + *enc = EVP_rc4(); + break; + case SSL_eNULL: + *enc = EVP_enc_null(); + break; + case SSL_AES128: + *enc = EVP_aes_128_cbc(); + break; + case SSL_AES256: + *enc = EVP_aes_256_cbc(); + break; + case SSL_CAMELLIA128: + *enc = EVP_camellia_128_cbc(); + break; + case SSL_CAMELLIA256: + *enc = EVP_camellia_256_cbc(); + break; +#ifndef OPENSSL_NO_GOST + case SSL_eGOST2814789CNT: + *enc = EVP_gost2814789_cnt(); + break; +#endif + } + + switch (ss->cipher->algorithm_mac) { + case SSL_MD5: + *md = EVP_md5(); + break; + case SSL_SHA1: + *md = EVP_sha1(); + break; + case SSL_SHA256: + *md = EVP_sha256(); + break; + case SSL_SHA384: + *md = EVP_sha384(); + break; +#ifndef OPENSSL_NO_GOST + case SSL_GOST89MAC: + *md = EVP_gost2814789imit(); + break; + case SSL_GOST94: + *md = EVP_gostr341194(); + break; + case SSL_STREEBOG256: + *md = EVP_streebog256(); + break; +#endif + } + if (*enc == NULL || *md == NULL) + return 0; + + /* + * EVP_CIPH_FLAG_AEAD_CIPHER and EVP_CIPH_GCM_MODE ciphers are not + * supported via EVP_CIPHER (they should be using EVP_AEAD instead). + */ + if (EVP_CIPHER_flags(*enc) & EVP_CIPH_FLAG_AEAD_CIPHER) + return 0; + if (EVP_CIPHER_mode(*enc) == EVP_CIPH_GCM_MODE) + return 0; +#ifndef OPENSSL_NO_GOST + /* XXX JFC. die in fire already */ + if (ss->cipher->algorithm_mac == SSL_GOST89MAC) { + *mac_pkey_type = EVP_PKEY_GOSTIMIT; + *mac_secret_size = 32; /* XXX */ + } else { +#endif + *mac_pkey_type = EVP_PKEY_HMAC; + *mac_secret_size = EVP_MD_size(*md); +#ifndef OPENSSL_NO_GOST + } +#endif + return 1; +} + +/* + * ssl_cipher_get_evp_aead sets aead to point to the correct EVP_AEAD object + * for s->cipher. It returns 1 on success and 0 on error. + */ +int +ssl_cipher_get_evp_aead(const SSL_SESSION *ss, const EVP_AEAD **aead) +{ + *aead = NULL; + + if (ss->cipher == NULL) + return 0; + if ((ss->cipher->algorithm_mac & SSL_AEAD) == 0) + return 0; + + switch (ss->cipher->algorithm_enc) { + case SSL_AES128GCM: + *aead = EVP_aead_aes_128_gcm(); + return 1; + case SSL_AES256GCM: + *aead = EVP_aead_aes_256_gcm(); + return 1; + case SSL_CHACHA20POLY1305: + *aead = EVP_aead_chacha20_poly1305(); + return 1; + default: + break; + } + return 0; +} + +int +ssl_get_handshake_evp_md(SSL *s, const EVP_MD **md) +{ + unsigned long handshake_mac; + + *md = NULL; + + if (s->s3->hs.cipher == NULL) + return 0; + + handshake_mac = s->s3->hs.cipher->algorithm2 & + SSL_HANDSHAKE_MAC_MASK; + + /* For TLSv1.2 we upgrade the default MD5+SHA1 MAC to SHA256. */ + if (SSL_USE_SHA256_PRF(s) && handshake_mac == SSL_HANDSHAKE_MAC_DEFAULT) + handshake_mac = SSL_HANDSHAKE_MAC_SHA256; + + switch (handshake_mac) { + case SSL_HANDSHAKE_MAC_DEFAULT: + *md = EVP_md5_sha1(); + return 1; +#ifndef OPENSSL_NO_GOST + case SSL_HANDSHAKE_MAC_GOST94: + *md = EVP_gostr341194(); + return 1; + case SSL_HANDSHAKE_MAC_STREEBOG256: + *md = EVP_streebog256(); + return 1; +#endif + case SSL_HANDSHAKE_MAC_SHA256: + *md = EVP_sha256(); + return 1; + case SSL_HANDSHAKE_MAC_SHA384: + *md = EVP_sha384(); + return 1; + default: + break; + } + + return 0; +} + +#define ITEM_SEP(a) \ + (((a) == ':') || ((a) == ' ') || ((a) == ';') || ((a) == ',')) + +static void +ll_append_tail(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) +{ + if (curr == *tail) + return; + if (curr == *head) + *head = curr->next; + if (curr->prev != NULL) + curr->prev->next = curr->next; + if (curr->next != NULL) + curr->next->prev = curr->prev; + (*tail)->next = curr; + curr->prev= *tail; + curr->next = NULL; + *tail = curr; +} + +static void +ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr, + CIPHER_ORDER **tail) +{ + if (curr == *head) + return; + if (curr == *tail) + *tail = curr->prev; + if (curr->next != NULL) + curr->next->prev = curr->prev; + if (curr->prev != NULL) + curr->prev->next = curr->next; + (*head)->prev = curr; + curr->next= *head; + curr->prev = NULL; + *head = curr; +} + +static void +ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, + unsigned long *enc, unsigned long *mac, unsigned long *ssl) +{ + *mkey = 0; + *auth = 0; + *enc = 0; + *mac = 0; + *ssl = 0; + + /* + * Check for the availability of GOST 34.10 public/private key + * algorithms. If they are not available disable the associated + * authentication and key exchange algorithms. + */ + if (EVP_PKEY_meth_find(NID_id_GostR3410_2001) == NULL) { + *auth |= SSL_aGOST01; + *mkey |= SSL_kGOST; + } + +#ifdef SSL_FORBID_ENULL + *enc |= SSL_eNULL; +#endif +} + +static void +ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, int num_of_ciphers, + unsigned long disabled_mkey, unsigned long disabled_auth, + unsigned long disabled_enc, unsigned long disabled_mac, + unsigned long disabled_ssl, CIPHER_ORDER *co_list, + CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) +{ + int i, co_list_num; + const SSL_CIPHER *c; + + /* + * We have num_of_ciphers descriptions compiled in, depending on the + * method selected (SSLv3, TLSv1, etc). These will later be sorted in + * a linked list with at most num entries. + */ + + /* Get the initial list of ciphers */ + co_list_num = 0; /* actual count of ciphers */ + for (i = 0; i < num_of_ciphers; i++) { + c = ssl_method->get_cipher(i); + /* + * Drop any invalid ciphers and any which use unavailable + * algorithms. + */ + if ((c != NULL) && c->valid && + !(c->algorithm_mkey & disabled_mkey) && + !(c->algorithm_auth & disabled_auth) && + !(c->algorithm_enc & disabled_enc) && + !(c->algorithm_mac & disabled_mac) && + !(c->algorithm_ssl & disabled_ssl)) { + co_list[co_list_num].cipher = c; + co_list[co_list_num].next = NULL; + co_list[co_list_num].prev = NULL; + co_list[co_list_num].active = 0; + co_list_num++; + } + } + + /* + * Prepare linked list from list entries + */ + if (co_list_num > 0) { + co_list[0].prev = NULL; + + if (co_list_num > 1) { + co_list[0].next = &co_list[1]; + + for (i = 1; i < co_list_num - 1; i++) { + co_list[i].prev = &co_list[i - 1]; + co_list[i].next = &co_list[i + 1]; + } + + co_list[co_list_num - 1].prev = + &co_list[co_list_num - 2]; + } + + co_list[co_list_num - 1].next = NULL; + + *head_p = &co_list[0]; + *tail_p = &co_list[co_list_num - 1]; + } +} + +static void +ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list, int num_of_group_aliases, + unsigned long disabled_mkey, unsigned long disabled_auth, + unsigned long disabled_enc, unsigned long disabled_mac, + unsigned long disabled_ssl, CIPHER_ORDER *head) +{ + CIPHER_ORDER *ciph_curr; + const SSL_CIPHER **ca_curr; + int i; + unsigned long mask_mkey = ~disabled_mkey; + unsigned long mask_auth = ~disabled_auth; + unsigned long mask_enc = ~disabled_enc; + unsigned long mask_mac = ~disabled_mac; + unsigned long mask_ssl = ~disabled_ssl; + + /* + * First, add the real ciphers as already collected + */ + ciph_curr = head; + ca_curr = ca_list; + while (ciph_curr != NULL) { + *ca_curr = ciph_curr->cipher; + ca_curr++; + ciph_curr = ciph_curr->next; + } + + /* + * Now we add the available ones from the cipher_aliases[] table. + * They represent either one or more algorithms, some of which + * in any affected category must be supported (set in enabled_mask), + * or represent a cipher strength value (will be added in any case because algorithms=0). + */ + for (i = 0; i < num_of_group_aliases; i++) { + unsigned long algorithm_mkey = cipher_aliases[i].algorithm_mkey; + unsigned long algorithm_auth = cipher_aliases[i].algorithm_auth; + unsigned long algorithm_enc = cipher_aliases[i].algorithm_enc; + unsigned long algorithm_mac = cipher_aliases[i].algorithm_mac; + unsigned long algorithm_ssl = cipher_aliases[i].algorithm_ssl; + + if (algorithm_mkey) + if ((algorithm_mkey & mask_mkey) == 0) + continue; + + if (algorithm_auth) + if ((algorithm_auth & mask_auth) == 0) + continue; + + if (algorithm_enc) + if ((algorithm_enc & mask_enc) == 0) + continue; + + if (algorithm_mac) + if ((algorithm_mac & mask_mac) == 0) + continue; + + if (algorithm_ssl) + if ((algorithm_ssl & mask_ssl) == 0) + continue; + + *ca_curr = (SSL_CIPHER *)(cipher_aliases + i); + ca_curr++; + } + + *ca_curr = NULL; /* end of list */ +} + +static void +ssl_cipher_apply_rule(unsigned long cipher_id, unsigned long alg_mkey, + unsigned long alg_auth, unsigned long alg_enc, unsigned long alg_mac, + unsigned long alg_ssl, unsigned long algo_strength, int rule, + int strength_bits, CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) +{ + CIPHER_ORDER *head, *tail, *curr, *next, *last; + const SSL_CIPHER *cp; + int reverse = 0; + + if (rule == CIPHER_DEL) + reverse = 1; /* needed to maintain sorting between currently deleted ciphers */ + + head = *head_p; + tail = *tail_p; + + if (reverse) { + next = tail; + last = head; + } else { + next = head; + last = tail; + } + + curr = NULL; + for (;;) { + if (curr == last) + break; + curr = next; + next = reverse ? curr->prev : curr->next; + + cp = curr->cipher; + + if (cipher_id && cp->id != cipher_id) + continue; + + /* + * Selection criteria is either the value of strength_bits + * or the algorithms used. + */ + if (strength_bits >= 0) { + if (strength_bits != cp->strength_bits) + continue; + } else { + if (alg_mkey && !(alg_mkey & cp->algorithm_mkey)) + continue; + if (alg_auth && !(alg_auth & cp->algorithm_auth)) + continue; + if (alg_enc && !(alg_enc & cp->algorithm_enc)) + continue; + if (alg_mac && !(alg_mac & cp->algorithm_mac)) + continue; + if (alg_ssl && !(alg_ssl & cp->algorithm_ssl)) + continue; + if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength)) + continue; + } + + /* add the cipher if it has not been added yet. */ + if (rule == CIPHER_ADD) { + /* reverse == 0 */ + if (!curr->active) { + ll_append_tail(&head, curr, &tail); + curr->active = 1; + } + } + /* Move the added cipher to this location */ + else if (rule == CIPHER_ORD) { + /* reverse == 0 */ + if (curr->active) { + ll_append_tail(&head, curr, &tail); + } + } else if (rule == CIPHER_DEL) { + /* reverse == 1 */ + if (curr->active) { + /* most recently deleted ciphersuites get best positions + * for any future CIPHER_ADD (note that the CIPHER_DEL loop + * works in reverse to maintain the order) */ + ll_append_head(&head, curr, &tail); + curr->active = 0; + } + } else if (rule == CIPHER_KILL) { + /* reverse == 0 */ + if (head == curr) + head = curr->next; + else + curr->prev->next = curr->next; + if (tail == curr) + tail = curr->prev; + curr->active = 0; + if (curr->next != NULL) + curr->next->prev = curr->prev; + if (curr->prev != NULL) + curr->prev->next = curr->next; + curr->next = NULL; + curr->prev = NULL; + } + } + + *head_p = head; + *tail_p = tail; +} + +static int +ssl_cipher_strength_sort(CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p) +{ + int max_strength_bits, i, *number_uses; + CIPHER_ORDER *curr; + + /* + * This routine sorts the ciphers with descending strength. The sorting + * must keep the pre-sorted sequence, so we apply the normal sorting + * routine as '+' movement to the end of the list. + */ + max_strength_bits = 0; + curr = *head_p; + while (curr != NULL) { + if (curr->active && + (curr->cipher->strength_bits > max_strength_bits)) + max_strength_bits = curr->cipher->strength_bits; + curr = curr->next; + } + + number_uses = calloc((max_strength_bits + 1), sizeof(int)); + if (!number_uses) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (0); + } + + /* + * Now find the strength_bits values actually used + */ + curr = *head_p; + while (curr != NULL) { + if (curr->active) + number_uses[curr->cipher->strength_bits]++; + curr = curr->next; + } + /* + * Go through the list of used strength_bits values in descending + * order. + */ + for (i = max_strength_bits; i >= 0; i--) + if (number_uses[i] > 0) + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p, tail_p); + + free(number_uses); + return (1); +} + +static int +ssl_cipher_process_rulestr(const char *rule_str, CIPHER_ORDER **head_p, + CIPHER_ORDER **tail_p, const SSL_CIPHER **ca_list, SSL_CERT *cert, + int *tls13_seen) +{ + unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl; + unsigned long algo_strength; + int j, multi, found, rule, retval, ok, buflen; + unsigned long cipher_id = 0; + const char *l, *buf; + char ch; + + *tls13_seen = 0; + + retval = 1; + l = rule_str; + for (;;) { + ch = *l; + + if (ch == '\0') + break; + + if (ch == '-') { + rule = CIPHER_DEL; + l++; + } else if (ch == '+') { + rule = CIPHER_ORD; + l++; + } else if (ch == '!') { + rule = CIPHER_KILL; + l++; + } else if (ch == '@') { + rule = CIPHER_SPECIAL; + l++; + } else { + rule = CIPHER_ADD; + } + + if (ITEM_SEP(ch)) { + l++; + continue; + } + + alg_mkey = 0; + alg_auth = 0; + alg_enc = 0; + alg_mac = 0; + alg_ssl = 0; + algo_strength = 0; + + for (;;) { + ch = *l; + buf = l; + buflen = 0; + while (((ch >= 'A') && (ch <= 'Z')) || + ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || + (ch == '-') || (ch == '.') || + (ch == '_') || (ch == '=')) { + ch = *(++l); + buflen++; + } + + if (buflen == 0) { + /* + * We hit something we cannot deal with, + * it is no command or separator nor + * alphanumeric, so we call this an error. + */ + SSLerrorx(SSL_R_INVALID_COMMAND); + return 0; + } + + if (rule == CIPHER_SPECIAL) { + /* unused -- avoid compiler warning */ + found = 0; + /* special treatment */ + break; + } + + /* check for multi-part specification */ + if (ch == '+') { + multi = 1; + l++; + } else + multi = 0; + + /* + * Now search for the cipher alias in the ca_list. + * Be careful with the strncmp, because the "buflen" + * limitation will make the rule "ADH:SOME" and the + * cipher "ADH-MY-CIPHER" look like a match for + * buflen=3. So additionally check whether the cipher + * name found has the correct length. We can save a + * strlen() call: just checking for the '\0' at the + * right place is sufficient, we have to strncmp() + * anyway (we cannot use strcmp(), because buf is not + * '\0' terminated.) + */ + j = found = 0; + cipher_id = 0; + while (ca_list[j]) { + if (!strncmp(buf, ca_list[j]->name, buflen) && + (ca_list[j]->name[buflen] == '\0')) { + found = 1; + break; + } else + j++; + } + + if (!found) + break; /* ignore this entry */ + + if (ca_list[j]->algorithm_mkey) { + if (alg_mkey) { + alg_mkey &= ca_list[j]->algorithm_mkey; + if (!alg_mkey) { + found = 0; + break; + } + } else + alg_mkey = ca_list[j]->algorithm_mkey; + } + + if (ca_list[j]->algorithm_auth) { + if (alg_auth) { + alg_auth &= ca_list[j]->algorithm_auth; + if (!alg_auth) { + found = 0; + break; + } + } else + alg_auth = ca_list[j]->algorithm_auth; + } + + if (ca_list[j]->algorithm_enc) { + if (alg_enc) { + alg_enc &= ca_list[j]->algorithm_enc; + if (!alg_enc) { + found = 0; + break; + } + } else + alg_enc = ca_list[j]->algorithm_enc; + } + + if (ca_list[j]->algorithm_mac) { + if (alg_mac) { + alg_mac &= ca_list[j]->algorithm_mac; + if (!alg_mac) { + found = 0; + break; + } + } else + alg_mac = ca_list[j]->algorithm_mac; + } + + if (ca_list[j]->algo_strength & SSL_STRONG_MASK) { + if (algo_strength & SSL_STRONG_MASK) { + algo_strength &= + (ca_list[j]->algo_strength & + SSL_STRONG_MASK) | ~SSL_STRONG_MASK; + if (!(algo_strength & + SSL_STRONG_MASK)) { + found = 0; + break; + } + } else + algo_strength |= + ca_list[j]->algo_strength & + SSL_STRONG_MASK; + } + + if (ca_list[j]->valid) { + /* + * explicit ciphersuite found; its protocol + * version does not become part of the search + * pattern! + */ + cipher_id = ca_list[j]->id; + if (ca_list[j]->algorithm_ssl == SSL_TLSV1_3) + *tls13_seen = 1; + } else { + /* + * not an explicit ciphersuite; only in this + * case, the protocol version is considered + * part of the search pattern + */ + if (ca_list[j]->algorithm_ssl) { + if (alg_ssl) { + alg_ssl &= + ca_list[j]->algorithm_ssl; + if (!alg_ssl) { + found = 0; + break; + } + } else + alg_ssl = + ca_list[j]->algorithm_ssl; + } + } + + if (!multi) + break; + } + + /* + * Ok, we have the rule, now apply it + */ + if (rule == CIPHER_SPECIAL) { + /* special command */ + ok = 0; + if (buflen == 8 && strncmp(buf, "STRENGTH", 8) == 0) { + ok = ssl_cipher_strength_sort(head_p, tail_p); + } else if (buflen == 10 && + strncmp(buf, "SECLEVEL=", 9) == 0) { + int level = buf[9] - '0'; + + if (level >= 0 && level <= 5) { + cert->security_level = level; + ok = 1; + } else { + SSLerrorx(SSL_R_INVALID_COMMAND); + } + } else { + SSLerrorx(SSL_R_INVALID_COMMAND); + } + if (ok == 0) + retval = 0; + + while ((*l != '\0') && !ITEM_SEP(*l)) + l++; + } else if (found) { + if (alg_ssl == SSL_TLSV1_3) + *tls13_seen = 1; + ssl_cipher_apply_rule(cipher_id, alg_mkey, alg_auth, + alg_enc, alg_mac, alg_ssl, algo_strength, rule, + -1, head_p, tail_p); + } else { + while ((*l != '\0') && !ITEM_SEP(*l)) + l++; + } + if (*l == '\0') + break; /* done */ + } + + return (retval); +} + +static inline int +ssl_aes_is_accelerated(void) +{ +#if defined(__i386__) || defined(__x86_64__) + return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); +#else + return (0); +#endif +} + +STACK_OF(SSL_CIPHER) * +ssl_create_cipher_list(const SSL_METHOD *ssl_method, + STACK_OF(SSL_CIPHER) **cipher_list, + STACK_OF(SSL_CIPHER) *cipher_list_tls13, + const char *rule_str, SSL_CERT *cert) +{ + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases; + unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl; + STACK_OF(SSL_CIPHER) *cipherstack = NULL, *ret = NULL; + const char *rule_p; + CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; + const SSL_CIPHER **ca_list = NULL; + const SSL_CIPHER *cipher; + int tls13_seen = 0; + int any_active; + int i; + + /* + * Return with error if nothing to do. + */ + if (rule_str == NULL || cipher_list == NULL) + goto err; + + /* + * To reduce the work to do we only want to process the compiled + * in algorithms, so we first get the mask of disabled ciphers. + */ + ssl_cipher_get_disabled(&disabled_mkey, &disabled_auth, &disabled_enc, &disabled_mac, &disabled_ssl); + + /* + * Now we have to collect the available ciphers from the compiled + * in ciphers. We cannot get more than the number compiled in, so + * it is used for allocation. + */ + num_of_ciphers = ssl3_num_ciphers(); + co_list = reallocarray(NULL, num_of_ciphers, sizeof(CIPHER_ORDER)); + if (co_list == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + + ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers, + disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl, + co_list, &head, &tail); + + + /* Now arrange all ciphers by preference: */ + + /* Everything else being equal, prefer ephemeral ECDH over other key exchange mechanisms */ + ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); + + if (ssl_aes_is_accelerated()) { + /* + * We have hardware assisted AES - prefer AES as a symmetric + * cipher, with CHACHA20 second. + */ + ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, + CIPHER_ADD, -1, &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, + 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + } else { + /* + * CHACHA20 is fast and safe on all hardware and is thus our + * preferred symmetric cipher, with AES second. + */ + ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20POLY1305, + 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, SSL_AES, 0, 0, 0, + CIPHER_ADD, -1, &head, &tail); + } + + /* Temporarily enable everything else for sorting */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail); + + /* Low priority for MD5 */ + ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* Move anonymous ciphers to the end. Usually, these will remain disabled. + * (For applications that allow them, they aren't too bad, but we prefer + * authenticated ciphers.) */ + ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* Move ciphers without forward secrecy to the end */ + ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* RC4 is sort of broken - move it to the end */ + ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head, &tail); + + /* Now sort by symmetric encryption strength. The above ordering remains + * in force within each class */ + if (!ssl_cipher_strength_sort(&head, &tail)) + goto err; + + /* Now disable everything (maintaining the ordering!) */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail); + + /* TLSv1.3 first. */ + ssl_cipher_apply_rule(0, 0, 0, 0, 0, SSL_TLSV1_3, 0, CIPHER_ADD, -1, &head, &tail); + ssl_cipher_apply_rule(0, 0, 0, 0, 0, SSL_TLSV1_3, 0, CIPHER_DEL, -1, &head, &tail); + + /* + * We also need cipher aliases for selecting based on the rule_str. + * There might be two types of entries in the rule_str: 1) names + * of ciphers themselves 2) aliases for groups of ciphers. + * For 1) we need the available ciphers and for 2) the cipher + * groups of cipher_aliases added together in one list (otherwise + * we would be happy with just the cipher_aliases table). + */ + num_of_group_aliases = sizeof(cipher_aliases) / sizeof(SSL_CIPHER); + num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1; + ca_list = reallocarray(NULL, num_of_alias_max, sizeof(SSL_CIPHER *)); + if (ca_list == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, disabled_mkey, + disabled_auth, disabled_enc, disabled_mac, disabled_ssl, head); + + /* + * If the rule_string begins with DEFAULT, apply the default rule + * before using the (possibly available) additional rules. + */ + ok = 1; + rule_p = rule_str; + if (strncmp(rule_str, "DEFAULT", 7) == 0) { + ok = ssl_cipher_process_rulestr(SSL_DEFAULT_CIPHER_LIST, + &head, &tail, ca_list, cert, &tls13_seen); + rule_p += 7; + if (*rule_p == ':') + rule_p++; + } + + if (ok && (strlen(rule_p) > 0)) + ok = ssl_cipher_process_rulestr(rule_p, &head, &tail, ca_list, + cert, &tls13_seen); + + if (!ok) { + /* Rule processing failure */ + goto err; + } + + /* + * Allocate new "cipherstack" for the result, return with error + * if we cannot get one. + */ + if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Prefer TLSv1.3 cipher suites. */ + if (cipher_list_tls13 != NULL) { + for (i = 0; i < sk_SSL_CIPHER_num(cipher_list_tls13); i++) { + cipher = sk_SSL_CIPHER_value(cipher_list_tls13, i); + if (!sk_SSL_CIPHER_push(cipherstack, cipher)) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + } + tls13_seen = 1; + } + + /* + * The cipher selection for the list is done. The ciphers are added + * to the resulting precedence to the STACK_OF(SSL_CIPHER). + * + * If the rule string did not contain any references to TLSv1.3 and + * TLSv1.3 cipher suites have not been configured separately, + * include inactive TLSv1.3 cipher suites. This avoids attempts to + * use TLSv1.3 with an older rule string that does not include + * TLSv1.3 cipher suites. If the rule string resulted in no active + * cipher suites then we return an empty stack. + */ + any_active = 0; + for (curr = head; curr != NULL; curr = curr->next) { + if (curr->active || + (!tls13_seen && curr->cipher->algorithm_ssl == SSL_TLSV1_3)) { + if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + } + any_active |= curr->active; + } + if (!any_active) + sk_SSL_CIPHER_zero(cipherstack); + + sk_SSL_CIPHER_free(*cipher_list); + *cipher_list = cipherstack; + cipherstack = NULL; + + ret = *cipher_list; + + err: + sk_SSL_CIPHER_free(cipherstack); + free((void *)ca_list); + free(co_list); + + return ret; +} + +const SSL_CIPHER * +SSL_CIPHER_get_by_id(unsigned int id) +{ + return ssl3_get_cipher_by_id(id); +} +LSSL_ALIAS(SSL_CIPHER_get_by_id); + +const SSL_CIPHER * +SSL_CIPHER_get_by_value(uint16_t value) +{ + return ssl3_get_cipher_by_value(value); +} +LSSL_ALIAS(SSL_CIPHER_get_by_value); + +char * +SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len) +{ + unsigned long alg_mkey, alg_auth, alg_enc, alg_mac, alg_ssl, alg2; + const char *ver, *kx, *au, *enc, *mac; + char *ret; + int l; + + alg_mkey = cipher->algorithm_mkey; + alg_auth = cipher->algorithm_auth; + alg_enc = cipher->algorithm_enc; + alg_mac = cipher->algorithm_mac; + alg_ssl = cipher->algorithm_ssl; + + alg2 = cipher->algorithm2; + + if (alg_ssl & SSL_SSLV3) + ver = "SSLv3"; + else if (alg_ssl & SSL_TLSV1_2) + ver = "TLSv1.2"; + else if (alg_ssl & SSL_TLSV1_3) + ver = "TLSv1.3"; + else + ver = "unknown"; + + switch (alg_mkey) { + case SSL_kRSA: + kx = "RSA"; + break; + case SSL_kDHE: + kx = "DH"; + break; + case SSL_kECDHE: + kx = "ECDH"; + break; + case SSL_kGOST: + kx = "GOST"; + break; + case SSL_kTLS1_3: + kx = "TLSv1.3"; + break; + default: + kx = "unknown"; + } + + switch (alg_auth) { + case SSL_aRSA: + au = "RSA"; + break; + case SSL_aDSS: + au = "DSS"; + break; + case SSL_aNULL: + au = "None"; + break; + case SSL_aECDSA: + au = "ECDSA"; + break; + case SSL_aGOST01: + au = "GOST01"; + break; + case SSL_aTLS1_3: + au = "TLSv1.3"; + break; + default: + au = "unknown"; + break; + } + + switch (alg_enc) { + case SSL_3DES: + enc = "3DES(168)"; + break; + case SSL_RC4: + enc = alg2 & SSL2_CF_8_BYTE_ENC ? "RC4(64)" : "RC4(128)"; + break; + case SSL_eNULL: + enc = "None"; + break; + case SSL_AES128: + enc = "AES(128)"; + break; + case SSL_AES256: + enc = "AES(256)"; + break; + case SSL_AES128GCM: + enc = "AESGCM(128)"; + break; + case SSL_AES256GCM: + enc = "AESGCM(256)"; + break; + case SSL_CAMELLIA128: + enc = "Camellia(128)"; + break; + case SSL_CAMELLIA256: + enc = "Camellia(256)"; + break; + case SSL_CHACHA20POLY1305: + enc = "ChaCha20-Poly1305"; + break; + case SSL_eGOST2814789CNT: + enc = "GOST-28178-89-CNT"; + break; + default: + enc = "unknown"; + break; + } + + switch (alg_mac) { + case SSL_MD5: + mac = "MD5"; + break; + case SSL_SHA1: + mac = "SHA1"; + break; + case SSL_SHA256: + mac = "SHA256"; + break; + case SSL_SHA384: + mac = "SHA384"; + break; + case SSL_AEAD: + mac = "AEAD"; + break; + case SSL_GOST94: + mac = "GOST94"; + break; + case SSL_GOST89MAC: + mac = "GOST89IMIT"; + break; + case SSL_STREEBOG256: + mac = "STREEBOG256"; + break; + default: + mac = "unknown"; + break; + } + + if (asprintf(&ret, "%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n", + cipher->name, ver, kx, au, enc, mac) == -1) + return "OPENSSL_malloc Error"; + + if (buf != NULL) { + l = strlcpy(buf, ret, len); + free(ret); + ret = buf; + if (l >= len) + ret = "Buffer too small"; + } + + return (ret); +} +LSSL_ALIAS(SSL_CIPHER_description); + +const char * +SSL_CIPHER_get_version(const SSL_CIPHER *c) +{ + if (c == NULL) + return("(NONE)"); + if ((c->id >> 24) == 3) + return("TLSv1/SSLv3"); + else + return("unknown"); +} +LSSL_ALIAS(SSL_CIPHER_get_version); + +/* return the actual cipher being used */ +const char * +SSL_CIPHER_get_name(const SSL_CIPHER *c) +{ + if (c != NULL) + return (c->name); + return("(NONE)"); +} +LSSL_ALIAS(SSL_CIPHER_get_name); + +/* number of bits for symmetric cipher */ +int +SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits) +{ + int ret = 0; + + if (c != NULL) { + if (alg_bits != NULL) + *alg_bits = c->alg_bits; + ret = c->strength_bits; + } + return (ret); +} +LSSL_ALIAS(SSL_CIPHER_get_bits); + +unsigned long +SSL_CIPHER_get_id(const SSL_CIPHER *c) +{ + return c->id; +} +LSSL_ALIAS(SSL_CIPHER_get_id); + +uint16_t +SSL_CIPHER_get_value(const SSL_CIPHER *c) +{ + return ssl3_cipher_get_value(c); +} +LSSL_ALIAS(SSL_CIPHER_get_value); + +const SSL_CIPHER * +SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr) +{ + uint16_t cipher_value; + CBS cbs; + + /* This API is documented with ptr being an array of length two. */ + CBS_init(&cbs, ptr, 2); + if (!CBS_get_u16(&cbs, &cipher_value)) + return NULL; + + return ssl3_get_cipher_by_value(cipher_value); +} +LSSL_ALIAS(SSL_CIPHER_find); + +int +SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c) +{ + switch (c->algorithm_enc) { + case SSL_eNULL: + return NID_undef; + case SSL_3DES: + return NID_des_ede3_cbc; + case SSL_AES128: + return NID_aes_128_cbc; + case SSL_AES128GCM: + return NID_aes_128_gcm; + case SSL_AES256: + return NID_aes_256_cbc; + case SSL_AES256GCM: + return NID_aes_256_gcm; + case SSL_CAMELLIA128: + return NID_camellia_128_cbc; + case SSL_CAMELLIA256: + return NID_camellia_256_cbc; + case SSL_CHACHA20POLY1305: + return NID_chacha20_poly1305; + case SSL_DES: + return NID_des_cbc; + case SSL_RC4: + return NID_rc4; + case SSL_eGOST2814789CNT: + return NID_gost89_cnt; + default: + return NID_undef; + } +} +LSSL_ALIAS(SSL_CIPHER_get_cipher_nid); + +int +SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c) +{ + switch (c->algorithm_mac) { + case SSL_AEAD: + return NID_undef; + case SSL_GOST89MAC: + return NID_id_Gost28147_89_MAC; + case SSL_GOST94: + return NID_id_GostR3411_94; + case SSL_MD5: + return NID_md5; + case SSL_SHA1: + return NID_sha1; + case SSL_SHA256: + return NID_sha256; + case SSL_SHA384: + return NID_sha384; + case SSL_STREEBOG256: + return NID_id_tc26_gost3411_2012_256; + default: + return NID_undef; + } +} +LSSL_ALIAS(SSL_CIPHER_get_digest_nid); + +int +SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c) +{ + switch (c->algorithm_mkey) { + case SSL_kDHE: + return NID_kx_dhe; + case SSL_kECDHE: + return NID_kx_ecdhe; + case SSL_kGOST: + return NID_kx_gost; + case SSL_kRSA: + return NID_kx_rsa; + default: + return NID_undef; + } +} +LSSL_ALIAS(SSL_CIPHER_get_kx_nid); + +int +SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c) +{ + switch (c->algorithm_auth) { + case SSL_aNULL: + return NID_auth_null; + case SSL_aECDSA: + return NID_auth_ecdsa; + case SSL_aGOST01: + return NID_auth_gost01; + case SSL_aRSA: + return NID_auth_rsa; + default: + return NID_undef; + } +} +LSSL_ALIAS(SSL_CIPHER_get_auth_nid); + +int +SSL_CIPHER_is_aead(const SSL_CIPHER *c) +{ + return (c->algorithm_mac & SSL_AEAD) == SSL_AEAD; +} +LSSL_ALIAS(SSL_CIPHER_is_aead); + +void * +SSL_COMP_get_compression_methods(void) +{ + return NULL; +} +LSSL_ALIAS(SSL_COMP_get_compression_methods); + +int +SSL_COMP_add_compression_method(int id, void *cm) +{ + return 1; +} +LSSL_ALIAS(SSL_COMP_add_compression_method); + +const char * +SSL_COMP_get_name(const void *comp) +{ + return NULL; +} +LSSL_ALIAS(SSL_COMP_get_name); diff --git a/ssl/ssl_ciphers.c b/ssl/ssl_ciphers.c new file mode 100644 index 0000000..4ec1b09 --- /dev/null +++ b/ssl/ssl_ciphers.c @@ -0,0 +1,286 @@ +/* $OpenBSD: ssl_ciphers.c,v 1.17 2022/11/26 16:08:55 tb Exp $ */ +/* + * Copyright (c) 2015-2017 Doug Hogan + * Copyright (c) 2015-2018, 2020 Joel Sing + * Copyright (c) 2019 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "bytestring.h" +#include "ssl_local.h" + +int +ssl_cipher_in_list(STACK_OF(SSL_CIPHER) *ciphers, const SSL_CIPHER *cipher) +{ + int i; + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + if (sk_SSL_CIPHER_value(ciphers, i)->id == cipher->id) + return 1; + } + + return 0; +} + +int +ssl_cipher_allowed_in_tls_version_range(const SSL_CIPHER *cipher, uint16_t min_ver, + uint16_t max_ver) +{ + switch(cipher->algorithm_ssl) { + case SSL_SSLV3: + return (min_ver <= TLS1_2_VERSION); + case SSL_TLSV1_2: + return (min_ver <= TLS1_2_VERSION && TLS1_2_VERSION <= max_ver); + case SSL_TLSV1_3: + return (min_ver <= TLS1_3_VERSION && TLS1_3_VERSION <= max_ver); + } + return 0; +} + +int +ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *ciphers, CBB *cbb) +{ + SSL_CIPHER *cipher; + int num_ciphers = 0; + uint16_t min_vers, max_vers; + int i; + + if (ciphers == NULL) + return 0; + + if (!ssl_supported_tls_version_range(s, &min_vers, &max_vers)) + return 0; + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + if ((cipher = sk_SSL_CIPHER_value(ciphers, i)) == NULL) + return 0; + if (!ssl_cipher_allowed_in_tls_version_range(cipher, min_vers, + max_vers)) + continue; + if (!ssl_security_cipher_check(s, cipher)) + continue; + if (!CBB_add_u16(cbb, ssl3_cipher_get_value(cipher))) + return 0; + + num_ciphers++; + } + + /* Add SCSV if there are other ciphers and we're not renegotiating. */ + if (num_ciphers > 0 && !s->renegotiate) { + if (!CBB_add_u16(cbb, SSL3_CK_SCSV & SSL3_CK_VALUE_MASK)) + return 0; + } + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +STACK_OF(SSL_CIPHER) * +ssl_bytes_to_cipher_list(SSL *s, CBS *cbs) +{ + STACK_OF(SSL_CIPHER) *ciphers = NULL; + const SSL_CIPHER *cipher; + uint16_t cipher_value; + unsigned long cipher_id; + + s->s3->send_connection_binding = 0; + + if ((ciphers = sk_SSL_CIPHER_new_null()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + while (CBS_len(cbs) > 0) { + if (!CBS_get_u16(cbs, &cipher_value)) { + SSLerror(s, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); + goto err; + } + + cipher_id = SSL3_CK_ID | cipher_value; + + if (cipher_id == SSL3_CK_SCSV) { + /* + * TLS_EMPTY_RENEGOTIATION_INFO_SCSV is fatal if + * renegotiating. + */ + if (s->renegotiate) { + SSLerror(s, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + + goto err; + } + s->s3->send_connection_binding = 1; + continue; + } + + if (cipher_id == SSL3_CK_FALLBACK_SCSV) { + /* + * TLS_FALLBACK_SCSV indicates that the client + * previously tried a higher protocol version. + * Fail if the current version is an unexpected + * downgrade. + */ + if (s->s3->hs.negotiated_tls_version < + s->s3->hs.our_max_tls_version) { + SSLerror(s, SSL_R_INAPPROPRIATE_FALLBACK); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_INAPPROPRIATE_FALLBACK); + goto err; + } + continue; + } + + if ((cipher = ssl3_get_cipher_by_value(cipher_value)) != NULL) { + if (!sk_SSL_CIPHER_push(ciphers, cipher)) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + } + } + + return (ciphers); + + err: + sk_SSL_CIPHER_free(ciphers); + + return (NULL); +} + +struct ssl_tls13_ciphersuite { + const char *name; + const char *alias; + unsigned long cid; +}; + +static const struct ssl_tls13_ciphersuite ssl_tls13_ciphersuites[] = { + { + .name = TLS1_3_RFC_AES_128_GCM_SHA256, + .alias = TLS1_3_TXT_AES_128_GCM_SHA256, + .cid = TLS1_3_CK_AES_128_GCM_SHA256, + }, + { + .name = TLS1_3_RFC_AES_256_GCM_SHA384, + .alias = TLS1_3_TXT_AES_256_GCM_SHA384, + .cid = TLS1_3_CK_AES_256_GCM_SHA384, + }, + { + .name = TLS1_3_RFC_CHACHA20_POLY1305_SHA256, + .alias = TLS1_3_TXT_CHACHA20_POLY1305_SHA256, + .cid = TLS1_3_CK_CHACHA20_POLY1305_SHA256, + }, + { + .name = TLS1_3_RFC_AES_128_CCM_SHA256, + .alias = TLS1_3_TXT_AES_128_CCM_SHA256, + .cid = TLS1_3_CK_AES_128_CCM_SHA256, + }, + { + .name = TLS1_3_RFC_AES_128_CCM_8_SHA256, + .alias = TLS1_3_TXT_AES_128_CCM_8_SHA256, + .cid = TLS1_3_CK_AES_128_CCM_8_SHA256, + }, + { + .name = NULL, + }, +}; + +int +ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str) +{ + const struct ssl_tls13_ciphersuite *ciphersuite; + STACK_OF(SSL_CIPHER) *ciphers; + const SSL_CIPHER *cipher; + char *s = NULL; + char *p, *q; + int i; + int ret = 0; + + if ((ciphers = sk_SSL_CIPHER_new_null()) == NULL) + goto err; + + /* An empty string is valid and means no ciphers. */ + if (strcmp(str, "") == 0) + goto done; + + if ((s = strdup(str)) == NULL) + goto err; + + q = s; + while ((p = strsep(&q, ":")) != NULL) { + ciphersuite = &ssl_tls13_ciphersuites[0]; + for (i = 0; ciphersuite->name != NULL; i++) { + if (strcmp(p, ciphersuite->name) == 0) + break; + if (strcmp(p, ciphersuite->alias) == 0) + break; + ciphersuite = &ssl_tls13_ciphersuites[i]; + } + if (ciphersuite->name == NULL) + goto err; + + /* We know about the cipher suite, but it is not supported. */ + if ((cipher = ssl3_get_cipher_by_id(ciphersuite->cid)) == NULL) + continue; + + if (!sk_SSL_CIPHER_push(ciphers, cipher)) + goto err; + } + + done: + sk_SSL_CIPHER_free(*out_ciphers); + *out_ciphers = ciphers; + ciphers = NULL; + ret = 1; + + err: + sk_SSL_CIPHER_free(ciphers); + free(s); + + return ret; +} + +int +ssl_merge_cipherlists(STACK_OF(SSL_CIPHER) *cipherlist, + STACK_OF(SSL_CIPHER) *cipherlist_tls13, + STACK_OF(SSL_CIPHER) **out_cipherlist) +{ + STACK_OF(SSL_CIPHER) *ciphers = NULL; + const SSL_CIPHER *cipher; + int i, ret = 0; + + if ((ciphers = sk_SSL_CIPHER_dup(cipherlist_tls13)) == NULL) + goto err; + for (i = 0; i < sk_SSL_CIPHER_num(cipherlist); i++) { + cipher = sk_SSL_CIPHER_value(cipherlist, i); + if (cipher->algorithm_ssl == SSL_TLSV1_3) + continue; + if (!sk_SSL_CIPHER_push(ciphers, cipher)) + goto err; + } + + sk_SSL_CIPHER_free(*out_cipherlist); + *out_cipherlist = ciphers; + ciphers = NULL; + + ret = 1; + + err: + sk_SSL_CIPHER_free(ciphers); + + return ret; +} diff --git a/ssl/ssl_clnt.c b/ssl/ssl_clnt.c new file mode 100644 index 0000000..441da64 --- /dev/null +++ b/ssl/ssl_clnt.c @@ -0,0 +1,2678 @@ +/* $OpenBSD: ssl_clnt.c,v 1.161 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#ifndef OPENSSL_NO_GOST +#include +#endif + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" + +static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b); + +static int ssl3_send_client_hello(SSL *s); +static int ssl3_get_dtls_hello_verify(SSL *s); +static int ssl3_get_server_hello(SSL *s); +static int ssl3_get_certificate_request(SSL *s); +static int ssl3_get_new_session_ticket(SSL *s); +static int ssl3_get_cert_status(SSL *s); +static int ssl3_get_server_done(SSL *s); +static int ssl3_send_client_verify(SSL *s); +static int ssl3_send_client_certificate(SSL *s); +static int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey); +static int ssl3_send_client_key_exchange(SSL *s); +static int ssl3_get_server_key_exchange(SSL *s); +static int ssl3_get_server_certificate(SSL *s); +static int ssl3_check_cert_and_algorithm(SSL *s); +static int ssl3_check_finished(SSL *s); +static int ssl3_send_client_change_cipher_spec(SSL *s); +static int ssl3_send_client_finished(SSL *s); +static int ssl3_get_server_finished(SSL *s); + +int +ssl3_connect(SSL *s) +{ + int new_state, state, skip = 0; + int ret = -1; + + ERR_clear_error(); + errno = 0; + + s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) + SSL_clear(s); + + for (;;) { + state = s->s3->hs.state; + + switch (s->s3->hs.state) { + case SSL_ST_RENEGOTIATE: + s->renegotiate = 1; + s->s3->hs.state = SSL_ST_CONNECT; + s->ctx->stats.sess_connect_renegotiate++; + /* break */ + case SSL_ST_BEFORE: + case SSL_ST_CONNECT: + case SSL_ST_BEFORE|SSL_ST_CONNECT: + case SSL_ST_OK|SSL_ST_CONNECT: + + s->server = 0; + + ssl_info_callback(s, SSL_CB_HANDSHAKE_START, 1); + + if (!ssl_legacy_stack_version(s, s->version)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!ssl_supported_tls_version_range(s, + &s->s3->hs.our_min_tls_version, + &s->s3->hs.our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + ret = -1; + goto end; + } + + if (!ssl_security_version(s, + s->s3->hs.our_min_tls_version)) { + SSLerror(s, SSL_R_VERSION_TOO_LOW); + ret = -1; + goto end; + } + + if (!ssl3_setup_init_buffer(s)) { + ret = -1; + goto end; + } + if (!ssl3_setup_buffers(s)) { + ret = -1; + goto end; + } + if (!ssl_init_wbio_buffer(s, 0)) { + ret = -1; + goto end; + } + + /* don't push the buffering BIO quite yet */ + + if (!tls1_transcript_init(s)) { + ret = -1; + goto end; + } + + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_A; + s->ctx->stats.sess_connect++; + s->init_num = 0; + + if (SSL_is_dtls(s)) { + /* mark client_random uninitialized */ + memset(s->s3->client_random, 0, + sizeof(s->s3->client_random)); + s->d1->send_cookie = 0; + s->hit = 0; + } + break; + + case SSL3_ST_CW_CLNT_HELLO_A: + case SSL3_ST_CW_CLNT_HELLO_B: + s->shutdown = 0; + + if (SSL_is_dtls(s)) { + /* every DTLS ClientHello resets Finished MAC */ + tls1_transcript_reset(s); + + dtls1_start_timer(s); + } + + ret = ssl3_send_client_hello(s); + if (ret <= 0) + goto end; + + if (SSL_is_dtls(s) && s->d1->send_cookie) { + s->s3->hs.state = SSL3_ST_CW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_CR_SRVR_HELLO_A; + } else + s->s3->hs.state = SSL3_ST_CR_SRVR_HELLO_A; + + s->init_num = 0; + + /* turn on buffering for the next lot of output */ + if (s->bbio != s->wbio) + s->wbio = BIO_push(s->bbio, s->wbio); + + break; + + case SSL3_ST_CR_SRVR_HELLO_A: + case SSL3_ST_CR_SRVR_HELLO_B: + ret = ssl3_get_server_hello(s); + if (ret <= 0) + goto end; + + if (s->hit) { + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; + if (!SSL_is_dtls(s)) { + if (s->tlsext_ticket_expected) { + /* receive renewed session ticket */ + s->s3->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + } + + /* No client certificate verification. */ + tls1_transcript_free(s); + } + } else if (SSL_is_dtls(s)) { + s->s3->hs.state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A; + } else { + s->s3->hs.state = SSL3_ST_CR_CERT_A; + } + s->init_num = 0; + break; + + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + ret = ssl3_get_dtls_hello_verify(s); + if (ret <= 0) + goto end; + dtls1_stop_timer(s); + if (s->d1->send_cookie) /* start again, with a cookie */ + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_A; + else + s->s3->hs.state = SSL3_ST_CR_CERT_A; + s->init_num = 0; + break; + + case SSL3_ST_CR_CERT_A: + case SSL3_ST_CR_CERT_B: + ret = ssl3_check_finished(s); + if (ret <= 0) + goto end; + if (ret == 2) { + s->hit = 1; + if (s->tlsext_ticket_expected) + s->s3->hs.state = SSL3_ST_CR_SESSION_TICKET_A; + else + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; + s->init_num = 0; + break; + } + /* Check if it is anon DH/ECDH. */ + if (!(s->s3->hs.cipher->algorithm_auth & + SSL_aNULL)) { + ret = ssl3_get_server_certificate(s); + if (ret <= 0) + goto end; + if (s->tlsext_status_expected) + s->s3->hs.state = SSL3_ST_CR_CERT_STATUS_A; + else + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; + } else { + skip = 1; + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; + } + s->init_num = 0; + break; + + case SSL3_ST_CR_KEY_EXCH_A: + case SSL3_ST_CR_KEY_EXCH_B: + ret = ssl3_get_server_key_exchange(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CR_CERT_REQ_A; + s->init_num = 0; + + /* + * At this point we check that we have the + * required stuff from the server. + */ + if (!ssl3_check_cert_and_algorithm(s)) { + ret = -1; + goto end; + } + break; + + case SSL3_ST_CR_CERT_REQ_A: + case SSL3_ST_CR_CERT_REQ_B: + ret = ssl3_get_certificate_request(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CR_SRVR_DONE_A; + s->init_num = 0; + break; + + case SSL3_ST_CR_SRVR_DONE_A: + case SSL3_ST_CR_SRVR_DONE_B: + ret = ssl3_get_server_done(s); + if (ret <= 0) + goto end; + if (SSL_is_dtls(s)) + dtls1_stop_timer(s); + if (s->s3->hs.tls12.cert_request) + s->s3->hs.state = SSL3_ST_CW_CERT_A; + else + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_A; + s->init_num = 0; + + break; + + case SSL3_ST_CW_CERT_A: + case SSL3_ST_CW_CERT_B: + case SSL3_ST_CW_CERT_C: + case SSL3_ST_CW_CERT_D: + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_client_certificate(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_A; + s->init_num = 0; + break; + + case SSL3_ST_CW_KEY_EXCH_A: + case SSL3_ST_CW_KEY_EXCH_B: + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_client_key_exchange(s); + if (ret <= 0) + goto end; + /* + * EAY EAY EAY need to check for DH fix cert + * sent back + */ + /* + * For TLS, cert_req is set to 2, so a cert chain + * of nothing is sent, but no verify packet is sent + */ + /* + * XXX: For now, we do not support client + * authentication in ECDH cipher suites with + * ECDH (rather than ECDSA) certificates. + * We need to skip the certificate verify + * message when client's ECDH public key is sent + * inside the client certificate. + */ + if (s->s3->hs.tls12.cert_request == 1) { + s->s3->hs.state = SSL3_ST_CW_CERT_VRFY_A; + } else { + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->change_cipher_spec = 0; + } + if (!SSL_is_dtls(s)) { + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + s->s3->change_cipher_spec = 0; + } + } + + s->init_num = 0; + break; + + case SSL3_ST_CW_CERT_VRFY_A: + case SSL3_ST_CW_CERT_VRFY_B: + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_client_verify(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + s->init_num = 0; + s->s3->change_cipher_spec = 0; + break; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_CW_CHANGE_B: + if (SSL_is_dtls(s) && !s->hit) + dtls1_start_timer(s); + ret = ssl3_send_client_change_cipher_spec(s); + if (ret <= 0) + goto end; + + s->s3->hs.state = SSL3_ST_CW_FINISHED_A; + s->init_num = 0; + s->session->cipher = s->s3->hs.cipher; + + if (!tls1_setup_key_block(s)) { + ret = -1; + goto end; + } + if (!tls1_change_write_cipher_state(s)) { + ret = -1; + goto end; + } + break; + + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_CW_FINISHED_B: + if (SSL_is_dtls(s) && !s->hit) + dtls1_start_timer(s); + ret = ssl3_send_client_finished(s); + if (ret <= 0) + goto end; + if (!SSL_is_dtls(s)) + s->s3->flags |= SSL3_FLAGS_CCS_OK; + s->s3->hs.state = SSL3_ST_CW_FLUSH; + + /* clear flags */ + if (s->hit) { + s->s3->hs.tls12.next_state = SSL_ST_OK; + } else { + /* Allow NewSessionTicket if ticket expected */ + if (s->tlsext_ticket_expected) + s->s3->hs.tls12.next_state = + SSL3_ST_CR_SESSION_TICKET_A; + else + s->s3->hs.tls12.next_state = + SSL3_ST_CR_FINISHED_A; + } + s->init_num = 0; + break; + + case SSL3_ST_CR_SESSION_TICKET_A: + case SSL3_ST_CR_SESSION_TICKET_B: + ret = ssl3_get_new_session_ticket(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CR_FINISHED_A; + s->init_num = 0; + break; + + case SSL3_ST_CR_CERT_STATUS_A: + case SSL3_ST_CR_CERT_STATUS_B: + ret = ssl3_get_cert_status(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_CR_KEY_EXCH_A; + s->init_num = 0; + break; + + case SSL3_ST_CR_FINISHED_A: + case SSL3_ST_CR_FINISHED_B: + if (SSL_is_dtls(s)) + s->d1->change_cipher_spec_ok = 1; + else + s->s3->flags |= SSL3_FLAGS_CCS_OK; + ret = ssl3_get_server_finished(s); + if (ret <= 0) + goto end; + if (SSL_is_dtls(s)) + dtls1_stop_timer(s); + + if (s->hit) + s->s3->hs.state = SSL3_ST_CW_CHANGE_A; + else + s->s3->hs.state = SSL_ST_OK; + s->init_num = 0; + break; + + case SSL3_ST_CW_FLUSH: + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + if (SSL_is_dtls(s)) { + /* If the write error was fatal, stop trying */ + if (!BIO_should_retry(s->wbio)) { + s->rwstate = SSL_NOTHING; + s->s3->hs.state = s->s3->hs.tls12.next_state; + } + } + ret = -1; + goto end; + } + s->rwstate = SSL_NOTHING; + s->s3->hs.state = s->s3->hs.tls12.next_state; + break; + + case SSL_ST_OK: + /* clean a few things up */ + tls1_cleanup_key_block(s); + + if (s->s3->handshake_transcript != NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!SSL_is_dtls(s)) + ssl3_release_init_buffer(s); + + ssl_free_wbio_buffer(s); + + s->init_num = 0; + s->renegotiate = 0; + s->new_session = 0; + + ssl_update_cache(s, SSL_SESS_CACHE_CLIENT); + if (s->hit) + s->ctx->stats.sess_hit++; + + ret = 1; + /* s->server=0; */ + s->handshake_func = ssl3_connect; + s->ctx->stats.sess_connect_good++; + + ssl_info_callback(s, SSL_CB_HANDSHAKE_DONE, 1); + + if (SSL_is_dtls(s)) { + /* done with handshaking */ + s->d1->handshake_read_seq = 0; + s->d1->next_handshake_write_seq = 0; + } + + goto end; + /* break; */ + + default: + SSLerror(s, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + /* break; */ + } + + /* did we do anything */ + if (!s->s3->hs.tls12.reuse_message && !skip) { + if (s->debug) { + if ((ret = BIO_flush(s->wbio)) <= 0) + goto end; + } + + if (s->s3->hs.state != state) { + new_state = s->s3->hs.state; + s->s3->hs.state = state; + ssl_info_callback(s, SSL_CB_CONNECT_LOOP, 1); + s->s3->hs.state = new_state; + } + } + skip = 0; + } + + end: + s->in_handshake--; + ssl_info_callback(s, SSL_CB_CONNECT_EXIT, ret); + + return (ret); +} + +static int +ssl3_send_client_hello(SSL *s) +{ + CBB cbb, client_hello, session_id, cookie, cipher_suites; + CBB compression_methods; + uint16_t max_version; + size_t sl; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_CLNT_HELLO_A) { + SSL_SESSION *sess = s->session; + + if (!ssl_max_supported_version(s, &max_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + return (-1); + } + s->version = max_version; + + if (sess == NULL || sess->ssl_version != s->version || + (sess->session_id_length == 0 && sess->tlsext_tick == NULL) || + sess->not_resumable) { + if (!ssl_get_new_session(s, 0)) + goto err; + } + /* else use the pre-loaded session */ + + /* + * If a DTLS ClientHello message is being resent after a + * HelloVerifyRequest, we must retain the original client + * random value. + */ + if (!SSL_is_dtls(s) || s->d1->send_cookie == 0) + arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); + + if (!ssl3_handshake_msg_start(s, &cbb, &client_hello, + SSL3_MT_CLIENT_HELLO)) + goto err; + + if (!CBB_add_u16(&client_hello, s->version)) + goto err; + + /* Random stuff */ + if (!CBB_add_bytes(&client_hello, s->s3->client_random, + sizeof(s->s3->client_random))) + goto err; + + /* Session ID */ + if (!CBB_add_u8_length_prefixed(&client_hello, &session_id)) + goto err; + if (!s->new_session && + s->session->session_id_length > 0) { + sl = s->session->session_id_length; + if (sl > sizeof(s->session->session_id)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!CBB_add_bytes(&session_id, + s->session->session_id, sl)) + goto err; + } + + /* DTLS Cookie. */ + if (SSL_is_dtls(s)) { + if (s->d1->cookie_len > sizeof(s->d1->cookie)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!CBB_add_u8_length_prefixed(&client_hello, &cookie)) + goto err; + if (!CBB_add_bytes(&cookie, s->d1->cookie, + s->d1->cookie_len)) + goto err; + } + + /* Ciphers supported */ + if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites)) + return 0; + if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), + &cipher_suites)) { + SSLerror(s, SSL_R_NO_CIPHERS_AVAILABLE); + goto err; + } + + /* Add in compression methods (null) */ + if (!CBB_add_u8_length_prefixed(&client_hello, + &compression_methods)) + goto err; + if (!CBB_add_u8(&compression_methods, 0)) + goto err; + + /* TLS extensions */ + if (!tlsext_client_build(s, SSL_TLSEXT_MSG_CH, &client_hello)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_CLNT_HELLO_B; + } + + /* SSL3_ST_CW_CLNT_HELLO_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_get_dtls_hello_verify(SSL *s) +{ + CBS hello_verify_request, cookie; + size_t cookie_len; + uint16_t ssl_version; + int al, ret; + + if ((ret = ssl3_get_message(s, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A, + DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1, s->max_cert_list)) <= 0) + return ret; + + if (s->s3->hs.tls12.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) { + s->d1->send_cookie = 0; + s->s3->hs.tls12.reuse_message = 1; + return (1); + } + + if (s->init_num < 0) + goto decode_err; + + CBS_init(&hello_verify_request, s->init_msg, + s->init_num); + + if (!CBS_get_u16(&hello_verify_request, &ssl_version)) + goto decode_err; + if (!CBS_get_u8_length_prefixed(&hello_verify_request, &cookie)) + goto decode_err; + if (CBS_len(&hello_verify_request) != 0) + goto decode_err; + + /* + * Per RFC 6347 section 4.2.1, the HelloVerifyRequest should always + * contain DTLSv1.0 the version that is going to be negotiated. + * Tolerate DTLSv1.2 just in case. + */ + if (ssl_version != DTLS1_VERSION && ssl_version != DTLS1_2_VERSION) { + SSLerror(s, SSL_R_WRONG_SSL_VERSION); + s->version = (s->version & 0xff00) | (ssl_version & 0xff); + al = SSL_AD_PROTOCOL_VERSION; + goto fatal_err; + } + + if (!CBS_write_bytes(&cookie, s->d1->cookie, + sizeof(s->d1->cookie), &cookie_len)) { + s->d1->cookie_len = 0; + al = SSL_AD_ILLEGAL_PARAMETER; + goto fatal_err; + } + s->d1->cookie_len = cookie_len; + s->d1->send_cookie = 1; + + return 1; + + decode_err: + al = SSL_AD_DECODE_ERROR; + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; +} + +static int +ssl3_get_server_hello(SSL *s) +{ + CBS cbs, server_random, session_id; + uint16_t server_version, cipher_suite; + uint8_t compression_method; + const SSL_CIPHER *cipher; + const SSL_METHOD *method; + unsigned long alg_k; + int al, ret; + + s->first_packet = 1; + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SRVR_HELLO_A, + SSL3_ST_CR_SRVR_HELLO_B, -1, 20000 /* ?? */)) <= 0) + return ret; + s->first_packet = 0; + + if (s->init_num < 0) + goto decode_err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (SSL_is_dtls(s)) { + if (s->s3->hs.tls12.message_type == DTLS1_MT_HELLO_VERIFY_REQUEST) { + if (s->d1->send_cookie == 0) { + s->s3->hs.tls12.reuse_message = 1; + return (1); + } else { + /* Already sent a cookie. */ + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); + goto fatal_err; + } + } + } + + if (s->s3->hs.tls12.message_type != SSL3_MT_SERVER_HELLO) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); + goto fatal_err; + } + + if (!CBS_get_u16(&cbs, &server_version)) + goto decode_err; + + if (!ssl_check_version_from_server(s, server_version)) { + SSLerror(s, SSL_R_WRONG_SSL_VERSION); + s->version = (s->version & 0xff00) | (server_version & 0xff); + al = SSL_AD_PROTOCOL_VERSION; + goto fatal_err; + } + s->s3->hs.peer_legacy_version = server_version; + s->version = server_version; + + s->s3->hs.negotiated_tls_version = ssl_tls_version(server_version); + if (s->s3->hs.negotiated_tls_version == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if ((method = ssl_get_method(server_version)) == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + s->method = method; + + /* Server random. */ + if (!CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE)) + goto decode_err; + if (!CBS_write_bytes(&server_random, s->s3->server_random, + sizeof(s->s3->server_random), NULL)) + goto err; + + if (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION && + s->s3->hs.negotiated_tls_version < s->s3->hs.our_max_tls_version) { + /* + * RFC 8446 section 4.1.3. We must not downgrade if the server + * random value contains the TLS 1.2 or TLS 1.1 magical value. + */ + if (!CBS_skip(&server_random, + CBS_len(&server_random) - sizeof(tls13_downgrade_12))) + goto err; + if (s->s3->hs.negotiated_tls_version == TLS1_2_VERSION && + CBS_mem_equal(&server_random, tls13_downgrade_12, + sizeof(tls13_downgrade_12))) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_INAPPROPRIATE_FALLBACK); + goto fatal_err; + } + if (CBS_mem_equal(&server_random, tls13_downgrade_11, + sizeof(tls13_downgrade_11))) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_INAPPROPRIATE_FALLBACK); + goto fatal_err; + } + } + + /* Session ID. */ + if (!CBS_get_u8_length_prefixed(&cbs, &session_id)) + goto decode_err; + + if (CBS_len(&session_id) > SSL3_SESSION_ID_SIZE) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_SSL3_SESSION_ID_TOO_LONG); + goto fatal_err; + } + + /* Cipher suite. */ + if (!CBS_get_u16(&cbs, &cipher_suite)) + goto decode_err; + + /* + * Check if we want to resume the session based on external + * pre-shared secret. + */ + if (s->tls_session_secret_cb != NULL) { + SSL_CIPHER *pref_cipher = NULL; + int master_key_length = sizeof(s->session->master_key); + + if (!s->tls_session_secret_cb(s, + s->session->master_key, &master_key_length, NULL, + &pref_cipher, s->tls_session_secret_cb_arg)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (master_key_length <= 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + s->session->master_key_length = master_key_length; + + if ((s->session->cipher = pref_cipher) == NULL) + s->session->cipher = + ssl3_get_cipher_by_value(cipher_suite); + s->s3->flags |= SSL3_FLAGS_CCS_OK; + } + + if (s->session->session_id_length != 0 && + CBS_mem_equal(&session_id, s->session->session_id, + s->session->session_id_length)) { + if (s->sid_ctx_length != s->session->sid_ctx_length || + timingsafe_memcmp(s->session->sid_ctx, + s->sid_ctx, s->sid_ctx_length) != 0) { + /* actually a client application bug */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); + goto fatal_err; + } + s->s3->flags |= SSL3_FLAGS_CCS_OK; + s->hit = 1; + } else { + /* a miss or crap from the other end */ + + /* If we were trying for session-id reuse, make a new + * SSL_SESSION so we don't stuff up other people */ + s->hit = 0; + if (s->session->session_id_length > 0) { + if (!ssl_get_new_session(s, 0)) { + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + } + + /* + * XXX - improve the handling for the case where there is a + * zero length session identifier. + */ + if (!CBS_write_bytes(&session_id, s->session->session_id, + sizeof(s->session->session_id), + &s->session->session_id_length)) + goto err; + + s->session->ssl_version = s->version; + } + + if ((cipher = ssl3_get_cipher_by_value(cipher_suite)) == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_UNKNOWN_CIPHER_RETURNED); + goto fatal_err; + } + + /* TLS v1.2 only ciphersuites require v1.2 or later. */ + if ((cipher->algorithm_ssl & SSL_TLSV1_2) && + s->s3->hs.negotiated_tls_version < TLS1_2_VERSION) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_WRONG_CIPHER_RETURNED); + goto fatal_err; + } + + if (!ssl_cipher_in_list(SSL_get_ciphers(s), cipher)) { + /* we did not say we would use this cipher */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_WRONG_CIPHER_RETURNED); + goto fatal_err; + } + + /* + * Depending on the session caching (internal/external), the cipher + * and/or cipher_id values may not be set. Make sure that + * cipher_id is set and use it for comparison. + */ + if (s->session->cipher) + s->session->cipher_id = s->session->cipher->id; + if (s->hit && (s->session->cipher_id != cipher->id)) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED); + goto fatal_err; + } + s->s3->hs.cipher = cipher; + + if (!tls1_transcript_hash_init(s)) + goto err; + + /* + * Don't digest cached records if no sigalgs: we may need them for + * client authentication. + */ + alg_k = s->s3->hs.cipher->algorithm_mkey; + if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST))) + tls1_transcript_free(s); + + if (!CBS_get_u8(&cbs, &compression_method)) + goto decode_err; + + if (compression_method != 0) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM); + goto fatal_err; + } + + if (!tlsext_client_parse(s, SSL_TLSEXT_MSG_SH, &cbs, &al)) { + SSLerror(s, SSL_R_PARSE_TLSEXT); + goto fatal_err; + } + + if (CBS_len(&cbs) != 0) + goto decode_err; + + /* + * Determine if we need to see RI. Strictly speaking if we want to + * avoid an attack we should *always* see RI even on initial server + * hello because the client doesn't see any renegotiation during an + * attack. However this would mean we could not connect to any server + * which doesn't support RI so for the immediate future tolerate RI + * absence on initial connect only. + */ + if (!s->s3->renegotiate_seen && + !(s->options & SSL_OP_LEGACY_SERVER_CONNECT)) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + goto fatal_err; + } + + if (ssl_check_serverhello_tlsext(s) <= 0) { + SSLerror(s, SSL_R_SERVERHELLO_TLSEXT); + goto err; + } + + return (1); + + decode_err: + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (-1); +} + +static int +ssl3_get_server_certificate(SSL *s) +{ + CBS cbs, cert_list, cert_data; + STACK_OF(X509) *certs = NULL; + X509 *cert = NULL; + const uint8_t *p; + int al, ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, -1, s->max_cert_list)) <= 0) + return ret; + + ret = -1; + + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { + s->s3->hs.tls12.reuse_message = 1; + return (1); + } + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); + goto fatal_err; + } + + if ((certs = sk_X509_new_null()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (s->init_num < 0) + goto decode_err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (!CBS_get_u24_length_prefixed(&cbs, &cert_list)) + goto decode_err; + if (CBS_len(&cbs) != 0) + goto decode_err; + + while (CBS_len(&cert_list) > 0) { + if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) + goto decode_err; + p = CBS_data(&cert_data); + if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) { + al = SSL_AD_BAD_CERTIFICATE; + SSLerror(s, ERR_R_ASN1_LIB); + goto fatal_err; + } + if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) + goto decode_err; + if (!sk_X509_push(certs, cert)) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + cert = NULL; + } + + /* A server must always provide a non-empty certificate list. */ + if (sk_X509_num(certs) < 1) { + SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + goto decode_err; + } + + if (ssl_verify_cert_chain(s, certs) <= 0 && + s->verify_mode != SSL_VERIFY_NONE) { + al = ssl_verify_alarm_type(s->verify_result); + SSLerror(s, SSL_R_CERTIFICATE_VERIFY_FAILED); + goto fatal_err; + } + s->session->verify_result = s->verify_result; + ERR_clear_error(); + + if (!tls_process_peer_certs(s, certs)) + goto err; + + ret = 1; + + if (0) { + decode_err: + /* wrong packet length */ + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: + sk_X509_pop_free(certs, X509_free); + X509_free(cert); + + return (ret); +} + +static int +ssl3_get_server_kex_dhe(SSL *s, CBS *cbs) +{ + int decode_error, invalid_params, invalid_key; + int nid = NID_dhKeyAgreement; + + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; + + if (!tls_key_share_peer_params(s->s3->hs.key_share, cbs, + &decode_error, &invalid_params)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, + &decode_error, &invalid_key)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + + if (invalid_params) { + SSLerror(s, SSL_R_BAD_DH_P_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + if (invalid_key) { + SSLerror(s, SSL_R_BAD_DH_PUB_KEY_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + + if (!tls_key_share_peer_security(s, s->s3->hs.key_share)) { + SSLerror(s, SSL_R_DH_KEY_TOO_SMALL); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + return 0; + } + + return 1; + + err: + return 0; +} + +static int +ssl3_get_server_kex_ecdhe(SSL *s, CBS *cbs) +{ + uint8_t curve_type; + uint16_t group_id; + int decode_error; + CBS public; + + if (!CBS_get_u8(cbs, &curve_type)) + goto decode_err; + if (!CBS_get_u16(cbs, &group_id)) + goto decode_err; + + /* Only named curves are supported. */ + if (curve_type != NAMED_CURVE_TYPE) { + SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + + if (!CBS_get_u8_length_prefixed(cbs, &public)) + goto decode_err; + + /* + * Check that the group is one of our preferences - if it is not, + * the server has sent us an invalid group. + */ + if (!tls1_check_group(s, group_id)) { + SSLerror(s, SSL_R_WRONG_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new(group_id)) == NULL) + goto err; + + if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, + &decode_error, NULL)) { + if (decode_error) + goto decode_err; + goto err; + } + + return 1; + + decode_err: + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + err: + return 0; +} + +static int +ssl3_get_server_key_exchange(SSL *s) +{ + CBB cbb; + CBS cbs, params, signature; + EVP_MD_CTX *md_ctx; + unsigned char *signed_params = NULL; + size_t signed_params_len; + size_t params_len; + long alg_k, alg_a; + int al, ret; + + memset(&cbb, 0, sizeof(cbb)); + + alg_k = s->s3->hs.cipher->algorithm_mkey; + alg_a = s->s3->hs.cipher->algorithm_auth; + + /* + * Use same message size as in ssl3_get_certificate_request() + * as ServerKeyExchange message may be skipped. + */ + if ((ret = ssl3_get_message(s, SSL3_ST_CR_KEY_EXCH_A, + SSL3_ST_CR_KEY_EXCH_B, -1, s->max_cert_list)) <= 0) + return ret; + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + + if (s->init_num < 0) + goto err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (s->s3->hs.tls12.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) { + /* + * Do not skip server key exchange if this cipher suite uses + * ephemeral keys. + */ + if (alg_k & (SSL_kDHE|SSL_kECDHE)) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto fatal_err; + } + + s->s3->hs.tls12.reuse_message = 1; + EVP_MD_CTX_free(md_ctx); + return (1); + } + + if (!CBB_init(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, s->s3->client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBB_add_bytes(&cbb, s->s3->server_random, SSL3_RANDOM_SIZE)) + goto err; + + CBS_dup(&cbs, ¶ms); + + if (alg_k & SSL_kDHE) { + if (!ssl3_get_server_kex_dhe(s, &cbs)) + goto err; + } else if (alg_k & SSL_kECDHE) { + if (!ssl3_get_server_kex_ecdhe(s, &cbs)) + goto err; + } else if (alg_k != 0) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + goto fatal_err; + } + + if ((params_len = CBS_offset(&cbs)) > CBS_len(¶ms)) + goto err; + if (!CBB_add_bytes(&cbb, CBS_data(¶ms), params_len)) + goto err; + if (!CBB_finish(&cbb, &signed_params, &signed_params_len)) + goto err; + + /* if it was signed, check the signature */ + if ((alg_a & SSL_aNULL) == 0) { + uint16_t sigalg_value = SIGALG_NONE; + const struct ssl_sigalg *sigalg; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey = NULL; + + if ((alg_a & SSL_aRSA) != 0 && + s->session->peer_cert_type == SSL_PKEY_RSA) { + pkey = X509_get0_pubkey(s->session->peer_cert); + } else if ((alg_a & SSL_aECDSA) != 0 && + s->session->peer_cert_type == SSL_PKEY_ECC) { + pkey = X509_get0_pubkey(s->session->peer_cert); + } + if (pkey == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto fatal_err; + } + + if (SSL_USE_SIGALGS(s)) { + if (!CBS_get_u16(&cbs, &sigalg_value)) + goto decode_err; + } + if (!CBS_get_u16_length_prefixed(&cbs, &signature)) + goto decode_err; + if (CBS_len(&signature) > EVP_PKEY_size(pkey)) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_WRONG_SIGNATURE_LENGTH); + goto fatal_err; + } + + if ((sigalg = ssl_sigalg_for_peer(s, pkey, + sigalg_value)) == NULL) { + al = SSL_AD_DECODE_ERROR; + goto fatal_err; + } + s->s3->hs.peer_sigalg = sigalg; + + if (!EVP_DigestVerifyInit(md_ctx, &pctx, sigalg->md(), + NULL, pkey)) + goto err; + if ((sigalg->flags & SIGALG_FLAG_RSA_PSS) && + (!EVP_PKEY_CTX_set_rsa_padding(pctx, + RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))) + goto err; + if (EVP_DigestVerify(md_ctx, CBS_data(&signature), + CBS_len(&signature), signed_params, signed_params_len) <= 0) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_BAD_SIGNATURE); + goto fatal_err; + } + } + + if (CBS_len(&cbs) != 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_EXTRA_DATA_IN_MESSAGE); + goto fatal_err; + } + + EVP_MD_CTX_free(md_ctx); + free(signed_params); + + return (1); + + decode_err: + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + + err: + CBB_cleanup(&cbb); + EVP_MD_CTX_free(md_ctx); + free(signed_params); + + return (-1); +} + +static int +ssl3_get_certificate_request(SSL *s) +{ + CBS cert_request, cert_types, rdn_list; + X509_NAME *xn = NULL; + const unsigned char *q; + STACK_OF(X509_NAME) *ca_sk = NULL; + int ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_REQ_A, + SSL3_ST_CR_CERT_REQ_B, -1, s->max_cert_list)) <= 0) + return ret; + + ret = 0; + + s->s3->hs.tls12.cert_request = 0; + + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_DONE) { + s->s3->hs.tls12.reuse_message = 1; + /* + * If we get here we don't need any cached handshake records + * as we wont be doing client auth. + */ + tls1_transcript_free(s); + return (1); + } + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_REQUEST) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + SSLerror(s, SSL_R_WRONG_MESSAGE_TYPE); + goto err; + } + + /* TLS does not like anon-DH with client cert */ + if (s->s3->hs.cipher->algorithm_auth & SSL_aNULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + SSLerror(s, SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER); + goto err; + } + + if (s->init_num < 0) + goto decode_err; + CBS_init(&cert_request, s->init_msg, s->init_num); + + if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (!CBS_get_u8_length_prefixed(&cert_request, &cert_types)) + goto decode_err; + + if (SSL_USE_SIGALGS(s)) { + CBS sigalgs; + + if (CBS_len(&cert_request) < 2) { + SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + if (!CBS_get_u16_length_prefixed(&cert_request, &sigalgs)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + if (CBS_len(&sigalgs) % 2 != 0 || CBS_len(&sigalgs) > 64) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); + goto err; + } + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, + &s->s3->hs.sigalgs_len)) + goto err; + } + + /* get the CA RDNs */ + if (CBS_len(&cert_request) < 2) { + SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + + if (!CBS_get_u16_length_prefixed(&cert_request, &rdn_list) || + CBS_len(&cert_request) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto err; + } + + while (CBS_len(&rdn_list) > 0) { + CBS rdn; + + if (CBS_len(&rdn_list) < 2) { + SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + + if (!CBS_get_u16_length_prefixed(&rdn_list, &rdn)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_CA_DN_TOO_LONG); + goto err; + } + + q = CBS_data(&rdn); + if ((xn = d2i_X509_NAME(NULL, &q, CBS_len(&rdn))) == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_DECODE_ERROR); + SSLerror(s, ERR_R_ASN1_LIB); + goto err; + } + + if (q != CBS_data(&rdn) + CBS_len(&rdn)) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_CA_DN_LENGTH_MISMATCH); + goto err; + } + if (!sk_X509_NAME_push(ca_sk, xn)) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + xn = NULL; /* avoid free in err block */ + } + + /* we should setup a certificate to return.... */ + s->s3->hs.tls12.cert_request = 1; + sk_X509_NAME_pop_free(s->s3->hs.tls12.ca_names, X509_NAME_free); + s->s3->hs.tls12.ca_names = ca_sk; + ca_sk = NULL; + + ret = 1; + if (0) { + decode_err: + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + } + err: + X509_NAME_free(xn); + sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); + return (ret); +} + +static int +ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b) +{ + return (X509_NAME_cmp(*a, *b)); +} + +static int +ssl3_get_new_session_ticket(SSL *s) +{ + uint32_t lifetime_hint; + CBS cbs, session_ticket; + unsigned int session_id_length = 0; + int al, ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SESSION_TICKET_A, + SSL3_ST_CR_SESSION_TICKET_B, -1, 16384)) <= 0) + return ret; + + if (s->s3->hs.tls12.message_type == SSL3_MT_FINISHED) { + s->s3->hs.tls12.reuse_message = 1; + return (1); + } + if (s->s3->hs.tls12.message_type != SSL3_MT_NEWSESSION_TICKET) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); + goto fatal_err; + } + + if (s->init_num < 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto fatal_err; + } + + CBS_init(&cbs, s->init_msg, s->init_num); + if (!CBS_get_u32(&cbs, &lifetime_hint) || + !CBS_get_u16_length_prefixed(&cbs, &session_ticket) || + CBS_len(&cbs) != 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto fatal_err; + } + s->session->tlsext_tick_lifetime_hint = lifetime_hint; + + if (!CBS_stow(&session_ticket, &s->session->tlsext_tick, + &s->session->tlsext_ticklen)) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * There are two ways to detect a resumed ticket session. + * One is to set an appropriate session ID and then the server + * must return a match in ServerHello. This allows the normal + * client session ID matching to work and we know much + * earlier that the ticket has been accepted. + * + * The other way is to set zero length session ID when the + * ticket is presented and rely on the handshake to determine + * session resumption. + * + * We choose the former approach because this fits in with + * assumptions elsewhere in OpenSSL. The session ID is set + * to the SHA256 hash of the ticket. + */ + /* XXX - ensure this doesn't overflow session_id if hash is changed. */ + if (!EVP_Digest(CBS_data(&session_ticket), CBS_len(&session_ticket), + s->session->session_id, &session_id_length, EVP_sha256(), NULL)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_EVP_LIB); + goto fatal_err; + } + s->session->session_id_length = session_id_length; + + return (1); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (-1); +} + +static int +ssl3_get_cert_status(SSL *s) +{ + CBS cert_status, response; + uint8_t status_type; + int al, ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_STATUS_A, + SSL3_ST_CR_CERT_STATUS_B, -1, 16384)) <= 0) + return ret; + + if (s->s3->hs.tls12.message_type == SSL3_MT_SERVER_KEY_EXCHANGE) { + /* + * Tell the callback the server did not send us an OSCP + * response, and has decided to head directly to key exchange. + */ + if (s->ctx->tlsext_status_cb) { + free(s->tlsext_ocsp_resp); + s->tlsext_ocsp_resp = NULL; + s->tlsext_ocsp_resp_len = 0; + + ret = s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg); + if (ret == 0) { + al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; + SSLerror(s, SSL_R_INVALID_STATUS_RESPONSE); + goto fatal_err; + } + if (ret < 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto fatal_err; + } + } + s->s3->hs.tls12.reuse_message = 1; + return (1); + } + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE && + s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_STATUS) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_BAD_MESSAGE_TYPE); + goto fatal_err; + } + + if (s->init_num < 0) { + /* need at least status type + length */ + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto fatal_err; + } + + CBS_init(&cert_status, s->init_msg, s->init_num); + if (!CBS_get_u8(&cert_status, &status_type) || + CBS_len(&cert_status) < 3) { + /* need at least status type + length */ + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto fatal_err; + } + + if (status_type != TLSEXT_STATUSTYPE_ocsp) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_UNSUPPORTED_STATUS_TYPE); + goto fatal_err; + } + + if (!CBS_get_u24_length_prefixed(&cert_status, &response) || + CBS_len(&cert_status) != 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_LENGTH_MISMATCH); + goto fatal_err; + } + + if (!CBS_stow(&response, &s->tlsext_ocsp_resp, + &s->tlsext_ocsp_resp_len)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto fatal_err; + } + + if (s->ctx->tlsext_status_cb) { + ret = s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg); + if (ret == 0) { + al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; + SSLerror(s, SSL_R_INVALID_STATUS_RESPONSE); + goto fatal_err; + } + if (ret < 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto fatal_err; + } + } + return (1); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return (-1); +} + +static int +ssl3_get_server_done(SSL *s) +{ + int ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_CR_SRVR_DONE_A, + SSL3_ST_CR_SRVR_DONE_B, SSL3_MT_SERVER_DONE, + 30 /* should be very small, like 0 :-) */)) <= 0) + return ret; + + if (s->init_num != 0) { + /* should contain no data */ + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerror(s, SSL_R_LENGTH_MISMATCH); + return -1; + } + + return 1; +} + +static int +ssl3_send_client_kex_rsa(SSL *s, CBB *cbb) +{ + unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char *enc_pms = NULL; + uint16_t max_legacy_version; + EVP_PKEY *pkey; + RSA *rsa; + int ret = 0; + int enc_len; + CBB epms; + + /* + * RSA-Encrypted Premaster Secret Message - RFC 5246 section 7.4.7.1. + */ + + pkey = X509_get0_pubkey(s->session->peer_cert); + if (pkey == NULL || (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + /* + * Our maximum legacy protocol version - while RFC 5246 section 7.4.7.1 + * says "The latest (newest) version supported by the client", if we're + * doing RSA key exchange then we have to presume that we're talking to + * a server that does not understand the supported versions extension + * and therefore our maximum version is that sent in the ClientHello. + */ + if (!ssl_max_legacy_version(s, &max_legacy_version)) + goto err; + pms[0] = max_legacy_version >> 8; + pms[1] = max_legacy_version & 0xff; + arc4random_buf(&pms[2], sizeof(pms) - 2); + + if ((enc_pms = malloc(RSA_size(rsa))) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + enc_len = RSA_public_encrypt(sizeof(pms), pms, enc_pms, rsa, + RSA_PKCS1_PADDING); + if (enc_len <= 0) { + SSLerror(s, SSL_R_BAD_RSA_ENCRYPT); + goto err; + } + + if (!CBB_add_u16_length_prefixed(cbb, &epms)) + goto err; + if (!CBB_add_bytes(&epms, enc_pms, enc_len)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + if (!tls12_derive_master_secret(s, pms, sizeof(pms))) + goto err; + + ret = 1; + + err: + explicit_bzero(pms, sizeof(pms)); + free(enc_pms); + + return ret; +} + +static int +ssl3_send_client_kex_dhe(SSL *s, CBB *cbb) +{ + uint8_t *key = NULL; + size_t key_len = 0; + int ret = 0; + + /* Ensure that we have an ephemeral key from the server for DHE. */ + if (s->s3->hs.key_share == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerror(s, SSL_R_UNABLE_TO_FIND_DH_PARAMETERS); + goto err; + } + + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + if (!tls_key_share_public(s->s3->hs.key_share, cbb)) + goto err; + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls_key_share_peer_security(s, s->s3->hs.key_share)) { + SSLerror(s, SSL_R_DH_KEY_TOO_SMALL); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + return 0; + } + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + +static int +ssl3_send_client_kex_ecdhe(SSL *s, CBB *cbb) +{ + uint8_t *key = NULL; + size_t key_len = 0; + CBB public; + int ret = 0; + + /* Ensure that we have an ephemeral key for ECDHE. */ + if (s->s3->hs.key_share == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + + if (!CBB_add_u8_length_prefixed(cbb, &public)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &public)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + +static int +ssl3_send_client_kex_gost(SSL *s, CBB *cbb) +{ + unsigned char premaster_secret[32], shared_ukm[32], tmp[256]; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_MD_CTX *ukm_hash = NULL; + EVP_PKEY *pkey; + size_t msglen; + unsigned int md_len; + CBB gostblob; + int nid; + int ret = 0; + + /* Get server certificate PKEY and create ctx from it */ + pkey = X509_get0_pubkey(s->session->peer_cert); + if (pkey == NULL || s->session->peer_cert_type != SSL_PKEY_GOST01) { + SSLerror(s, SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER); + goto err; + } + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * If we have send a certificate, and certificate key parameters match + * those of server certificate, use certificate key for key exchange. + * Otherwise, generate ephemeral key pair. + */ + if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0) + goto err; + + /* Generate session key. */ + arc4random_buf(premaster_secret, sizeof(premaster_secret)); + + /* + * If we have client certificate, use its secret as peer key. + * XXX - this presumably lacks PFS. + */ + if (s->s3->hs.tls12.cert_request != 0 && + s->cert->key->privatekey != NULL) { + if (EVP_PKEY_derive_set_peer(pkey_ctx, + s->cert->key->privatekey) <=0) { + /* + * If there was an error - just ignore it. + * Ephemeral key would be used. + */ + ERR_clear_error(); + } + } + + /* + * Compute shared IV and store it in algorithm-specific context data. + */ + if ((ukm_hash = EVP_MD_CTX_new()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* XXX check handshake hash instead. */ + if (s->s3->hs.cipher->algorithm2 & SSL_HANDSHAKE_MAC_GOST94) + nid = NID_id_GostR3411_94; + else + nid = NID_id_tc26_gost3411_2012_256; + if (!EVP_DigestInit(ukm_hash, EVP_get_digestbynid(nid))) + goto err; + if (!EVP_DigestUpdate(ukm_hash, s->s3->client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!EVP_DigestUpdate(ukm_hash, s->s3->server_random, SSL3_RANDOM_SIZE)) + goto err; + if (!EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len)) + goto err; + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) { + SSLerror(s, SSL_R_LIBRARY_BUG); + goto err; + } + + /* + * Make GOST keytransport blob message, encapsulate it into sequence. + */ + msglen = 255; + if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, premaster_secret, + sizeof(premaster_secret)) < 0) { + SSLerror(s, SSL_R_LIBRARY_BUG); + goto err; + } + + if (!CBB_add_asn1(cbb, &gostblob, CBS_ASN1_SEQUENCE)) + goto err; + if (!CBB_add_bytes(&gostblob, tmp, msglen)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + /* Check if pubkey from client certificate was used. */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, + NULL) > 0) + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + + if (!tls12_derive_master_secret(s, premaster_secret, 32)) + goto err; + + ret = 1; + + err: + explicit_bzero(premaster_secret, sizeof(premaster_secret)); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_MD_CTX_free(ukm_hash); + + return ret; +} + +static int +ssl3_send_client_key_exchange(SSL *s) +{ + unsigned long alg_k; + CBB cbb, kex; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_KEY_EXCH_A) { + alg_k = s->s3->hs.cipher->algorithm_mkey; + + if (!ssl3_handshake_msg_start(s, &cbb, &kex, + SSL3_MT_CLIENT_KEY_EXCHANGE)) + goto err; + + if (alg_k & SSL_kRSA) { + if (!ssl3_send_client_kex_rsa(s, &kex)) + goto err; + } else if (alg_k & SSL_kDHE) { + if (!ssl3_send_client_kex_dhe(s, &kex)) + goto err; + } else if (alg_k & SSL_kECDHE) { + if (!ssl3_send_client_kex_ecdhe(s, &kex)) + goto err; + } else if (alg_k & SSL_kGOST) { + if (!ssl3_send_client_kex_gost(s, &kex)) + goto err; + } else { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_KEY_EXCH_B; + } + + /* SSL3_ST_CW_KEY_EXCH_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_client_verify_sigalgs(SSL *s, EVP_PKEY *pkey, + const struct ssl_sigalg *sigalg, CBB *cert_verify) +{ + CBB cbb_signature; + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + const unsigned char *hdata; + unsigned char *signature = NULL; + size_t signature_len, hdata_len; + int ret = 0; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; + + if (!tls1_transcript_data(s, &hdata, &hdata_len)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!EVP_DigestSignInit(mctx, &pctx, sigalg->md(), NULL, pkey)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } +#ifndef OPENSSL_NO_GOST + if (sigalg->key_type == EVP_PKEY_GOSTR01 && + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_GOST_SIG_FORMAT, GOST_SIG_FORMAT_RS_LE, NULL) <= 0) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } +#endif + if ((sigalg->flags & SIGALG_FLAG_RSA_PSS) && + (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (!EVP_DigestSign(mctx, NULL, &signature_len, hdata, hdata_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if ((signature = calloc(1, signature_len)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestSign(mctx, signature, &signature_len, hdata, hdata_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + if (!CBB_add_u16(cert_verify, sigalg->value)) + goto err; + if (!CBB_add_u16_length_prefixed(cert_verify, &cbb_signature)) + goto err; + if (!CBB_add_bytes(&cbb_signature, signature, signature_len)) + goto err; + if (!CBB_flush(cert_verify)) + goto err; + + ret = 1; + + err: + EVP_MD_CTX_free(mctx); + free(signature); + return ret; +} + +static int +ssl3_send_client_verify_rsa(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) +{ + CBB cbb_signature; + RSA *rsa; + unsigned char data[EVP_MAX_MD_SIZE]; + unsigned char *signature = NULL; + unsigned int signature_len; + size_t data_len; + int ret = 0; + + if (!tls1_transcript_hash_value(s, data, sizeof(data), &data_len)) + goto err; + if ((signature = calloc(1, EVP_PKEY_size(pkey))) == NULL) + goto err; + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) + goto err; + if (RSA_sign(NID_md5_sha1, data, data_len, signature, &signature_len, + rsa) <= 0 ) { + SSLerror(s, ERR_R_RSA_LIB); + goto err; + } + + if (!CBB_add_u16_length_prefixed(cert_verify, &cbb_signature)) + goto err; + if (!CBB_add_bytes(&cbb_signature, signature, signature_len)) + goto err; + if (!CBB_flush(cert_verify)) + goto err; + + ret = 1; + err: + free(signature); + return ret; +} + +static int +ssl3_send_client_verify_ec(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) +{ + CBB cbb_signature; + EC_KEY *eckey; + unsigned char data[EVP_MAX_MD_SIZE]; + unsigned char *signature = NULL; + unsigned int signature_len; + int ret = 0; + + if (!tls1_transcript_hash_value(s, data, sizeof(data), NULL)) + goto err; + if ((signature = calloc(1, EVP_PKEY_size(pkey))) == NULL) + goto err; + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) + goto err; + if (!ECDSA_sign(0, &data[MD5_DIGEST_LENGTH], SHA_DIGEST_LENGTH, + signature, &signature_len, eckey)) { + SSLerror(s, ERR_R_ECDSA_LIB); + goto err; + } + + if (!CBB_add_u16_length_prefixed(cert_verify, &cbb_signature)) + goto err; + if (!CBB_add_bytes(&cbb_signature, signature, signature_len)) + goto err; + if (!CBB_flush(cert_verify)) + goto err; + + ret = 1; + err: + free(signature); + return ret; +} + +#ifndef OPENSSL_NO_GOST +static int +ssl3_send_client_verify_gost(SSL *s, EVP_PKEY *pkey, CBB *cert_verify) +{ + CBB cbb_signature; + EVP_MD_CTX *mctx; + EVP_PKEY_CTX *pctx; + const EVP_MD *md; + const unsigned char *hdata; + unsigned char *signature = NULL; + size_t signature_len; + size_t hdata_len; + int nid; + int ret = 0; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; + + if (!tls1_transcript_data(s, &hdata, &hdata_len)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!EVP_PKEY_get_default_digest_nid(pkey, &nid) || + (md = EVP_get_digestbynid(nid)) == NULL) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (!EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } +#ifndef OPENSSL_NO_GOST + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_GOST_SIG_FORMAT, GOST_SIG_FORMAT_RS_LE, NULL) <= 0) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } +#endif + if (!EVP_DigestSign(mctx, NULL, &signature_len, hdata, hdata_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if ((signature = calloc(1, signature_len)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestSign(mctx, signature, &signature_len, hdata, hdata_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + if (!CBB_add_u16_length_prefixed(cert_verify, &cbb_signature)) + goto err; + if (!CBB_add_bytes(&cbb_signature, signature, signature_len)) + goto err; + if (!CBB_flush(cert_verify)) + goto err; + + ret = 1; + err: + EVP_MD_CTX_free(mctx); + free(signature); + return ret; +} +#endif + +static int +ssl3_send_client_verify(SSL *s) +{ + const struct ssl_sigalg *sigalg; + CBB cbb, cert_verify; + EVP_PKEY *pkey; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_CERT_VRFY_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &cert_verify, + SSL3_MT_CERTIFICATE_VERIFY)) + goto err; + + pkey = s->cert->key->privatekey; + if ((sigalg = ssl_sigalg_select(s, pkey)) == NULL) { + SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); + goto err; + } + s->s3->hs.our_sigalg = sigalg; + + /* + * For TLS v1.2 send signature algorithm and signature using + * agreed digest and cached handshake records. + */ + if (SSL_USE_SIGALGS(s)) { + if (!ssl3_send_client_verify_sigalgs(s, pkey, sigalg, + &cert_verify)) + goto err; + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + if (!ssl3_send_client_verify_rsa(s, pkey, &cert_verify)) + goto err; + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { + if (!ssl3_send_client_verify_ec(s, pkey, &cert_verify)) + goto err; +#ifndef OPENSSL_NO_GOST + } else if (EVP_PKEY_id(pkey) == NID_id_GostR3410_94 || + EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) { + if (!ssl3_send_client_verify_gost(s, pkey, &cert_verify)) + goto err; +#endif + } else { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + tls1_transcript_free(s); + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_CERT_VRFY_B; + } + + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_client_certificate(SSL *s) +{ + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + CBB cbb, client_cert; + int i; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_CERT_A) { + if (s->cert->key->x509 == NULL || + s->cert->key->privatekey == NULL) + s->s3->hs.state = SSL3_ST_CW_CERT_B; + else + s->s3->hs.state = SSL3_ST_CW_CERT_C; + } + + /* We need to get a client cert */ + if (s->s3->hs.state == SSL3_ST_CW_CERT_B) { + /* + * If we get an error, we need to + * ssl->rwstate = SSL_X509_LOOKUP; return(-1); + * We then get retried later. + */ + i = ssl_do_client_cert_cb(s, &x509, &pkey); + if (i < 0) { + s->rwstate = SSL_X509_LOOKUP; + return (-1); + } + s->rwstate = SSL_NOTHING; + if ((i == 1) && (pkey != NULL) && (x509 != NULL)) { + s->s3->hs.state = SSL3_ST_CW_CERT_B; + if (!SSL_use_certificate(s, x509) || + !SSL_use_PrivateKey(s, pkey)) + i = 0; + } else if (i == 1) { + i = 0; + SSLerror(s, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK); + } + + X509_free(x509); + EVP_PKEY_free(pkey); + if (i == 0) { + s->s3->hs.tls12.cert_request = 2; + + /* There is no client certificate to verify. */ + tls1_transcript_free(s); + } + + /* Ok, we have a cert */ + s->s3->hs.state = SSL3_ST_CW_CERT_C; + } + + if (s->s3->hs.state == SSL3_ST_CW_CERT_C) { + if (!ssl3_handshake_msg_start(s, &cbb, &client_cert, + SSL3_MT_CERTIFICATE)) + goto err; + if (!ssl3_output_cert_chain(s, &client_cert, + (s->s3->hs.tls12.cert_request == 2) ? NULL : s->cert->key)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_CERT_D; + } + + /* SSL3_ST_CW_CERT_D */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (0); +} + +#define has_bits(i,m) (((i)&(m)) == (m)) + +static int +ssl3_check_cert_and_algorithm(SSL *s) +{ + long alg_k, alg_a; + int nid = NID_undef; + int i; + + alg_k = s->s3->hs.cipher->algorithm_mkey; + alg_a = s->s3->hs.cipher->algorithm_auth; + + /* We don't have a certificate. */ + if (alg_a & SSL_aNULL) + return (1); + + if (s->s3->hs.key_share != NULL) + nid = tls_key_share_nid(s->s3->hs.key_share); + + /* This is the passed certificate. */ + + if (s->session->peer_cert_type == SSL_PKEY_ECC) { + if (!ssl_check_srvr_ecc_cert_and_alg(s, s->session->peer_cert)) { + SSLerror(s, SSL_R_BAD_ECC_CERT); + goto fatal_err; + } + return (1); + } + + i = X509_certificate_type(s->session->peer_cert, NULL); + + /* Check that we have a certificate if we require one. */ + if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA|EVP_PKT_SIGN)) { + SSLerror(s, SSL_R_MISSING_RSA_SIGNING_CERT); + goto fatal_err; + } + if ((alg_k & SSL_kRSA) && !has_bits(i, EVP_PK_RSA|EVP_PKT_ENC)) { + SSLerror(s, SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto fatal_err; + } + if ((alg_k & SSL_kDHE) && + !(has_bits(i, EVP_PK_DH|EVP_PKT_EXCH) || (nid == NID_dhKeyAgreement))) { + SSLerror(s, SSL_R_MISSING_DH_KEY); + goto fatal_err; + } + + return (1); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + + return (0); +} + +/* + * Check to see if handshake is full or resumed. Usually this is just a + * case of checking to see if a cache hit has occurred. In the case of + * session tickets we have to check the next message to be sure. + */ + +static int +ssl3_check_finished(SSL *s) +{ + int ret; + + /* If we have no ticket it cannot be a resumed session. */ + if (!s->session->tlsext_tick) + return (1); + /* this function is called when we really expect a Certificate + * message, so permit appropriate message length */ + if ((ret = ssl3_get_message(s, SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, -1, s->max_cert_list)) <= 0) + return ret; + + s->s3->hs.tls12.reuse_message = 1; + if ((s->s3->hs.tls12.message_type == SSL3_MT_FINISHED) || + (s->s3->hs.tls12.message_type == SSL3_MT_NEWSESSION_TICKET)) + return (2); + + return (1); +} + +static int +ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) +{ + int i = 0; + +#ifndef OPENSSL_NO_ENGINE + if (s->ctx->client_cert_engine) { + i = ENGINE_load_ssl_client_cert( + s->ctx->client_cert_engine, s, + SSL_get_client_CA_list(s), px509, ppkey, NULL, NULL, NULL); + if (i != 0) + return (i); + } +#endif + if (s->ctx->client_cert_cb) + i = s->ctx->client_cert_cb(s, px509, ppkey); + return (i); +} + +static int +ssl3_send_client_change_cipher_spec(SSL *s) +{ + size_t outlen; + CBB cbb; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_CHANGE_A) { + if (!CBB_init_fixed(&cbb, s->init_buf->data, + s->init_buf->length)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_MT_CCS)) + goto err; + if (!CBB_finish(&cbb, NULL, &outlen)) + goto err; + + if (outlen > INT_MAX) + goto err; + + s->init_num = (int)outlen; + s->init_off = 0; + + if (SSL_is_dtls(s)) { + s->d1->handshake_write_seq = + s->d1->next_handshake_write_seq; + dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, + s->d1->handshake_write_seq, 0, 0); + dtls1_buffer_message(s, 1); + } + + s->s3->hs.state = SSL3_ST_CW_CHANGE_B; + } + + /* SSL3_ST_CW_CHANGE_B */ + return ssl3_record_write(s, SSL3_RT_CHANGE_CIPHER_SPEC); + + err: + CBB_cleanup(&cbb); + + return -1; +} + +static int +ssl3_send_client_finished(SSL *s) +{ + CBB cbb, finished; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_CW_FINISHED_A) { + if (!tls12_derive_finished(s)) + goto err; + + /* Copy finished so we can use it for renegotiation checks. */ + memcpy(s->s3->previous_client_finished, + s->s3->hs.finished, s->s3->hs.finished_len); + s->s3->previous_client_finished_len = + s->s3->hs.finished_len; + + if (!ssl3_handshake_msg_start(s, &cbb, &finished, + SSL3_MT_FINISHED)) + goto err; + if (!CBB_add_bytes(&finished, s->s3->hs.finished, + s->s3->hs.finished_len)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_CW_FINISHED_B; + } + + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_get_server_finished(SSL *s) +{ + int al, md_len, ret; + CBS cbs; + + /* should actually be 36+4 :-) */ + if ((ret = ssl3_get_message(s, SSL3_ST_CR_FINISHED_A, + SSL3_ST_CR_FINISHED_B, SSL3_MT_FINISHED, 64)) <= 0) + return ret; + + /* If this occurs, we have missed a message */ + if (!s->s3->change_cipher_spec) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_GOT_A_FIN_BEFORE_A_CCS); + goto fatal_err; + } + s->s3->change_cipher_spec = 0; + + md_len = TLS1_FINISH_MAC_LENGTH; + + if (s->init_num < 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (s->s3->hs.peer_finished_len != md_len || + CBS_len(&cbs) != md_len) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + if (!CBS_mem_equal(&cbs, s->s3->hs.peer_finished, CBS_len(&cbs))) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_DIGEST_CHECK_FAILED); + goto fatal_err; + } + + /* Copy finished so we can use it for renegotiation checks. */ + OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_server_finished, + s->s3->hs.peer_finished, md_len); + s->s3->previous_server_finished_len = md_len; + + return (1); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return (0); +} diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c new file mode 100644 index 0000000..28097ea --- /dev/null +++ b/ssl/ssl_err.c @@ -0,0 +1,673 @@ +/* $OpenBSD: ssl_err.c,v 1.46 2023/07/08 16:40:13 beck Exp $ */ +/* ==================================================================== + * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include + +#include "ssl_local.h" + +#ifndef OPENSSL_NO_ERR + +#define ERR_FUNC(func) ERR_PACK(ERR_LIB_SSL,func,0) +#define ERR_REASON(reason) ERR_PACK(ERR_LIB_SSL,0,reason) + +/* See SSL_state_func_code below */ +static ERR_STRING_DATA SSL_str_functs[]= { + {ERR_FUNC(1), "CONNECT_CW_FLUSH"}, + {ERR_FUNC(2), "CONNECT_CW_CLNT_HELLO"}, + {ERR_FUNC(3), "CONNECT_CW_CLNT_HELLO"}, + {ERR_FUNC(4), "CONNECT_CR_SRVR_HELLO"}, + {ERR_FUNC(5), "CONNECT_CR_SRVR_HELLO"}, + {ERR_FUNC(6), "CONNECT_CR_CERT"}, + {ERR_FUNC(7), "CONNECT_CR_CERT"}, + {ERR_FUNC(8), "CONNECT_CR_KEY_EXCH"}, + {ERR_FUNC(9), "CONNECT_CR_KEY_EXCH"}, + {ERR_FUNC(10), "CONNECT_CR_CERT_REQ"}, + {ERR_FUNC(11), "CONNECT_CR_CERT_REQ"}, + {ERR_FUNC(12), "CONNECT_CR_SRVR_DONE"}, + {ERR_FUNC(13), "CONNECT_CR_SRVR_DONE"}, + {ERR_FUNC(14), "CONNECT_CW_CERT"}, + {ERR_FUNC(15), "CONNECT_CW_CERT"}, + {ERR_FUNC(16), "CONNECT_CW_CERT_C"}, + {ERR_FUNC(17), "CONNECT_CW_CERT_D"}, + {ERR_FUNC(18), "CONNECT_CW_KEY_EXCH"}, + {ERR_FUNC(19), "CONNECT_CW_KEY_EXCH"}, + {ERR_FUNC(20), "CONNECT_CW_CERT_VRFY"}, + {ERR_FUNC(21), "CONNECT_CW_CERT_VRFY"}, + {ERR_FUNC(22), "CONNECT_CW_CHANGE"}, + {ERR_FUNC(23), "CONNECT_CW_CHANGE"}, + {ERR_FUNC(26), "CONNECT_CW_FINISHED"}, + {ERR_FUNC(27), "CONNECT_CW_FINISHED"}, + {ERR_FUNC(28), "CONNECT_CR_CHANGE"}, + {ERR_FUNC(29), "CONNECT_CR_CHANGE"}, + {ERR_FUNC(30), "CONNECT_CR_FINISHED"}, + {ERR_FUNC(31), "CONNECT_CR_FINISHED"}, + {ERR_FUNC(32), "CONNECT_CR_SESSION_TICKET"}, + {ERR_FUNC(33), "CONNECT_CR_SESSION_TICKET"}, + {ERR_FUNC(34), "CONNECT_CR_CERT_STATUS"}, + {ERR_FUNC(35), "CONNECT_CR_CERT_STATUS"}, + {ERR_FUNC(36), "ACCEPT_SW_FLUSH"}, + {ERR_FUNC(37), "ACCEPT_SR_CLNT_HELLO"}, + {ERR_FUNC(38), "ACCEPT_SR_CLNT_HELLO"}, + {ERR_FUNC(39), "ACCEPT_SR_CLNT_HELLO_C"}, + {ERR_FUNC(40), "ACCEPT_SW_HELLO_REQ"}, + {ERR_FUNC(41), "ACCEPT_SW_HELLO_REQ"}, + {ERR_FUNC(42), "ACCEPT_SW_HELLO_REQ_C"}, + {ERR_FUNC(43), "ACCEPT_SW_SRVR_HELLO"}, + {ERR_FUNC(44), "ACCEPT_SW_SRVR_HELLO"}, + {ERR_FUNC(45), "ACCEPT_SW_CERT"}, + {ERR_FUNC(46), "ACCEPT_SW_CERT"}, + {ERR_FUNC(47), "ACCEPT_SW_KEY_EXCH"}, + {ERR_FUNC(48), "ACCEPT_SW_KEY_EXCH"}, + {ERR_FUNC(49), "ACCEPT_SW_CERT_REQ"}, + {ERR_FUNC(50), "ACCEPT_SW_CERT_REQ"}, + {ERR_FUNC(51), "ACCEPT_SW_SRVR_DONE"}, + {ERR_FUNC(52), "ACCEPT_SW_SRVR_DONE"}, + {ERR_FUNC(53), "ACCEPT_SR_CERT"}, + {ERR_FUNC(54), "ACCEPT_SR_CERT"}, + {ERR_FUNC(55), "ACCEPT_SR_KEY_EXCH"}, + {ERR_FUNC(56), "ACCEPT_SR_KEY_EXCH"}, + {ERR_FUNC(57), "ACCEPT_SR_CERT_VRFY"}, + {ERR_FUNC(58), "ACCEPT_SR_CERT_VRFY"}, + {ERR_FUNC(59), "ACCEPT_SR_CHANGE"}, + {ERR_FUNC(60), "ACCEPT_SR_CHANGE"}, + {ERR_FUNC(63), "ACCEPT_SR_FINISHED"}, + {ERR_FUNC(64), "ACCEPT_SR_FINISHED"}, + {ERR_FUNC(65), "ACCEPT_SW_CHANGE"}, + {ERR_FUNC(66), "ACCEPT_SW_CHANGE"}, + {ERR_FUNC(67), "ACCEPT_SW_FINISHED"}, + {ERR_FUNC(68), "ACCEPT_SW_FINISHED"}, + {ERR_FUNC(69), "ACCEPT_SW_SESSION_TICKET"}, + {ERR_FUNC(70), "ACCEPT_SW_SESSION_TICKET"}, + {ERR_FUNC(71), "ACCEPT_SW_CERT_STATUS"}, + {ERR_FUNC(72), "ACCEPT_SW_CERT_STATUS"}, + {ERR_FUNC(73), "ST_BEFORE"}, + {ERR_FUNC(74), "ST_ACCEPT"}, + {ERR_FUNC(75), "ST_CONNECT"}, + {ERR_FUNC(76), "ST_OK"}, + {ERR_FUNC(77), "ST_RENEGOTIATE"}, + {ERR_FUNC(78), "ST_BEFORE_CONNECT"}, + {ERR_FUNC(79), "ST_OK_CONNECT"}, + {ERR_FUNC(80), "ST_BEFORE_ACCEPT"}, + {ERR_FUNC(81), "ST_OK_ACCEPT"}, + {ERR_FUNC(83), "DTLS1_ST_CR_HELLO_VERIFY_REQUEST"}, + {ERR_FUNC(84), "DTLS1_ST_CR_HELLO_VERIFY_REQUEST"}, + {ERR_FUNC(85), "DTLS1_ST_SW_HELLO_VERIFY_REQUEST"}, + {ERR_FUNC(86), "DTLS1_ST_SW_HELLO_VERIFY_REQUEST"}, + {ERR_FUNC(0xfff), "(UNKNOWN)SSL_internal"}, + {0, NULL} +}; + +static ERR_STRING_DATA SSL_str_reasons[]= { + {ERR_REASON(SSL_R_APP_DATA_IN_HANDSHAKE) , "app data in handshake"}, + {ERR_REASON(SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT), "attempt to reuse session in different context"}, + {ERR_REASON(SSL_R_BAD_ALERT_RECORD) , "bad alert record"}, + {ERR_REASON(SSL_R_BAD_AUTHENTICATION_TYPE), "bad authentication type"}, + {ERR_REASON(SSL_R_BAD_CHANGE_CIPHER_SPEC), "bad change cipher spec"}, + {ERR_REASON(SSL_R_BAD_CHECKSUM) , "bad checksum"}, + {ERR_REASON(SSL_R_BAD_DATA_RETURNED_BY_CALLBACK), "bad data returned by callback"}, + {ERR_REASON(SSL_R_BAD_DECOMPRESSION) , "bad decompression"}, + {ERR_REASON(SSL_R_BAD_DH_G_LENGTH) , "bad dh g length"}, + {ERR_REASON(SSL_R_BAD_DH_PUB_KEY_LENGTH) , "bad dh pub key length"}, + {ERR_REASON(SSL_R_BAD_DH_P_LENGTH) , "bad dh p length"}, + {ERR_REASON(SSL_R_BAD_DIGEST_LENGTH) , "bad digest length"}, + {ERR_REASON(SSL_R_BAD_DSA_SIGNATURE) , "bad dsa signature"}, + {ERR_REASON(SSL_R_BAD_ECC_CERT) , "bad ecc cert"}, + {ERR_REASON(SSL_R_BAD_ECDSA_SIGNATURE) , "bad ecdsa signature"}, + {ERR_REASON(SSL_R_BAD_ECPOINT) , "bad ecpoint"}, + {ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH) , "bad handshake length"}, + {ERR_REASON(SSL_R_BAD_HELLO_REQUEST) , "bad hello request"}, + {ERR_REASON(SSL_R_BAD_LENGTH) , "bad length"}, + {ERR_REASON(SSL_R_BAD_MAC_DECODE) , "bad mac decode"}, + {ERR_REASON(SSL_R_BAD_MAC_LENGTH) , "bad mac length"}, + {ERR_REASON(SSL_R_BAD_MESSAGE_TYPE) , "bad message type"}, + {ERR_REASON(SSL_R_BAD_PACKET_LENGTH) , "bad packet length"}, + {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER), "bad protocol version number"}, + {ERR_REASON(SSL_R_BAD_PSK_IDENTITY_HINT_LENGTH), "bad psk identity hint length"}, + {ERR_REASON(SSL_R_BAD_RESPONSE_ARGUMENT) , "bad response argument"}, + {ERR_REASON(SSL_R_BAD_RSA_DECRYPT) , "bad rsa decrypt"}, + {ERR_REASON(SSL_R_BAD_RSA_ENCRYPT) , "bad rsa encrypt"}, + {ERR_REASON(SSL_R_BAD_RSA_E_LENGTH) , "bad rsa e length"}, + {ERR_REASON(SSL_R_BAD_RSA_MODULUS_LENGTH), "bad rsa modulus length"}, + {ERR_REASON(SSL_R_BAD_RSA_SIGNATURE) , "bad rsa signature"}, + {ERR_REASON(SSL_R_BAD_SIGNATURE) , "bad signature"}, + {ERR_REASON(SSL_R_BAD_SRP_A_LENGTH) , "bad srp a length"}, + {ERR_REASON(SSL_R_BAD_SRP_B_LENGTH) , "bad srp b length"}, + {ERR_REASON(SSL_R_BAD_SRP_G_LENGTH) , "bad srp g length"}, + {ERR_REASON(SSL_R_BAD_SRP_N_LENGTH) , "bad srp n length"}, + {ERR_REASON(SSL_R_BAD_SRP_S_LENGTH) , "bad srp s length"}, + {ERR_REASON(SSL_R_BAD_SRTP_MKI_VALUE) , "bad srtp mki value"}, + {ERR_REASON(SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST), "bad srtp protection profile list"}, + {ERR_REASON(SSL_R_BAD_SSL_FILETYPE) , "bad ssl filetype"}, + {ERR_REASON(SSL_R_BAD_SSL_SESSION_ID_LENGTH), "bad ssl session id length"}, + {ERR_REASON(SSL_R_BAD_STATE) , "bad state"}, + {ERR_REASON(SSL_R_BAD_WRITE_RETRY) , "bad write retry"}, + {ERR_REASON(SSL_R_BIO_NOT_SET) , "bio not set"}, + {ERR_REASON(SSL_R_BLOCK_CIPHER_PAD_IS_WRONG), "block cipher pad is wrong"}, + {ERR_REASON(SSL_R_BN_LIB) , "bn lib"}, + {ERR_REASON(SSL_R_CA_DN_LENGTH_MISMATCH) , "ca dn length mismatch"}, + {ERR_REASON(SSL_R_CA_DN_TOO_LONG) , "ca dn too long"}, + {ERR_REASON(SSL_R_CA_KEY_TOO_SMALL) , "ca key too small"}, + {ERR_REASON(SSL_R_CA_MD_TOO_WEAK) , "ca md too weak"}, + {ERR_REASON(SSL_R_CCS_RECEIVED_EARLY) , "ccs received early"}, + {ERR_REASON(SSL_R_CERTIFICATE_VERIFY_FAILED), "certificate verify failed"}, + {ERR_REASON(SSL_R_CERT_LENGTH_MISMATCH) , "cert length mismatch"}, + {ERR_REASON(SSL_R_CHALLENGE_IS_DIFFERENT), "challenge is different"}, + {ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH), "cipher code wrong length"}, + {ERR_REASON(SSL_R_CIPHER_COMPRESSION_UNAVAILABLE), "cipher compression unavailable"}, + {ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE), "cipher or hash unavailable"}, + {ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR), "cipher table src error"}, + {ERR_REASON(SSL_R_CLIENTHELLO_TLSEXT) , "clienthello tlsext"}, + {ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG), "compressed length too long"}, + {ERR_REASON(SSL_R_COMPRESSION_DISABLED) , "compression disabled"}, + {ERR_REASON(SSL_R_COMPRESSION_FAILURE) , "compression failure"}, + {ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE), "compression id not within private range"}, + {ERR_REASON(SSL_R_COMPRESSION_LIBRARY_ERROR), "compression library error"}, + {ERR_REASON(SSL_R_CONNECTION_ID_IS_DIFFERENT), "connection id is different"}, + {ERR_REASON(SSL_R_CONNECTION_TYPE_NOT_SET), "connection type not set"}, + {ERR_REASON(SSL_R_COOKIE_MISMATCH) , "cookie mismatch"}, + {ERR_REASON(SSL_R_DATA_BETWEEN_CCS_AND_FINISHED), "data between ccs and finished"}, + {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG) , "data length too long"}, + {ERR_REASON(SSL_R_DECRYPTION_FAILED) , "decryption failed"}, + {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC), "decryption failed or bad record mac"}, + {ERR_REASON(SSL_R_DH_KEY_TOO_SMALL) , "dh key too small"}, + {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG), "dh public value length is wrong"}, + {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED) , "digest check failed"}, + {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG) , "dtls message too big"}, + {ERR_REASON(SSL_R_DUPLICATE_COMPRESSION_ID), "duplicate compression id"}, + {ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT), "ecc cert not for key agreement"}, + {ERR_REASON(SSL_R_ECC_CERT_NOT_FOR_SIGNING), "ecc cert not for signing"}, + {ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_RSA_SIGNATURE), "ecc cert should have rsa signature"}, + {ERR_REASON(SSL_R_ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE), "ecc cert should have sha1 signature"}, + {ERR_REASON(SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER), "ecgroup too large for cipher"}, + {ERR_REASON(SSL_R_EE_KEY_TOO_SMALL) , "ee key too small"}, + {ERR_REASON(SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST), "empty srtp protection profile list"}, + {ERR_REASON(SSL_R_ENCRYPTED_LENGTH_TOO_LONG), "encrypted length too long"}, + {ERR_REASON(SSL_R_ERROR_GENERATING_TMP_RSA_KEY), "error generating tmp rsa key"}, + {ERR_REASON(SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST), "error in received cipher list"}, + {ERR_REASON(SSL_R_EXCESSIVE_MESSAGE_SIZE), "excessive message size"}, + {ERR_REASON(SSL_R_EXTRA_DATA_IN_MESSAGE) , "extra data in message"}, + {ERR_REASON(SSL_R_GOT_A_FIN_BEFORE_A_CCS), "got a fin before a ccs"}, + {ERR_REASON(SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS), "got next proto before a ccs"}, + {ERR_REASON(SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION), "got next proto without seeing extension"}, + {ERR_REASON(SSL_R_HTTPS_PROXY_REQUEST) , "https proxy request"}, + {ERR_REASON(SSL_R_HTTP_REQUEST) , "http request"}, + {ERR_REASON(SSL_R_ILLEGAL_PADDING) , "illegal padding"}, + {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK), "inappropriate fallback"}, + {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION), "inconsistent compression"}, + {ERR_REASON(SSL_R_INVALID_CHALLENGE_LENGTH), "invalid challenge length"}, + {ERR_REASON(SSL_R_INVALID_COMMAND) , "invalid command"}, + {ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM), "invalid compression algorithm"}, + {ERR_REASON(SSL_R_INVALID_PURPOSE) , "invalid purpose"}, + {ERR_REASON(SSL_R_INVALID_SRP_USERNAME) , "invalid srp username"}, + {ERR_REASON(SSL_R_INVALID_STATUS_RESPONSE), "invalid status response"}, + {ERR_REASON(SSL_R_INVALID_TICKET_KEYS_LENGTH), "invalid ticket keys length"}, + {ERR_REASON(SSL_R_INVALID_TRUST) , "invalid trust"}, + {ERR_REASON(SSL_R_KEY_ARG_TOO_LONG) , "key arg too long"}, + {ERR_REASON(SSL_R_KRB5) , "krb5"}, + {ERR_REASON(SSL_R_KRB5_C_CC_PRINC) , "krb5 client cc principal (no tkt?)"}, + {ERR_REASON(SSL_R_KRB5_C_GET_CRED) , "krb5 client get cred"}, + {ERR_REASON(SSL_R_KRB5_C_INIT) , "krb5 client init"}, + {ERR_REASON(SSL_R_KRB5_C_MK_REQ) , "krb5 client mk_req (expired tkt?)"}, + {ERR_REASON(SSL_R_KRB5_S_BAD_TICKET) , "krb5 server bad ticket"}, + {ERR_REASON(SSL_R_KRB5_S_INIT) , "krb5 server init"}, + {ERR_REASON(SSL_R_KRB5_S_RD_REQ) , "krb5 server rd_req (keytab perms?)"}, + {ERR_REASON(SSL_R_KRB5_S_TKT_EXPIRED) , "krb5 server tkt expired"}, + {ERR_REASON(SSL_R_KRB5_S_TKT_NYV) , "krb5 server tkt not yet valid"}, + {ERR_REASON(SSL_R_KRB5_S_TKT_SKEW) , "krb5 server tkt skew"}, + {ERR_REASON(SSL_R_LENGTH_MISMATCH) , "length mismatch"}, + {ERR_REASON(SSL_R_LENGTH_TOO_SHORT) , "length too short"}, + {ERR_REASON(SSL_R_LIBRARY_BUG) , "library bug"}, + {ERR_REASON(SSL_R_LIBRARY_HAS_NO_CIPHERS), "library has no ciphers"}, + {ERR_REASON(SSL_R_MESSAGE_TOO_LONG) , "message too long"}, + {ERR_REASON(SSL_R_MISSING_DH_DSA_CERT) , "missing dh dsa cert"}, + {ERR_REASON(SSL_R_MISSING_DH_KEY) , "missing dh key"}, + {ERR_REASON(SSL_R_MISSING_DH_RSA_CERT) , "missing dh rsa cert"}, + {ERR_REASON(SSL_R_MISSING_DSA_SIGNING_CERT), "missing dsa signing cert"}, + {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_DH_KEY), "missing export tmp dh key"}, + {ERR_REASON(SSL_R_MISSING_EXPORT_TMP_RSA_KEY), "missing export tmp rsa key"}, + {ERR_REASON(SSL_R_MISSING_RSA_CERTIFICATE), "missing rsa certificate"}, + {ERR_REASON(SSL_R_MISSING_RSA_ENCRYPTING_CERT), "missing rsa encrypting cert"}, + {ERR_REASON(SSL_R_MISSING_RSA_SIGNING_CERT), "missing rsa signing cert"}, + {ERR_REASON(SSL_R_MISSING_SRP_PARAM) , "can't find SRP server param"}, + {ERR_REASON(SSL_R_MISSING_TMP_DH_KEY) , "missing tmp dh key"}, + {ERR_REASON(SSL_R_MISSING_TMP_ECDH_KEY) , "missing tmp ecdh key"}, + {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY) , "missing tmp rsa key"}, + {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY) , "missing tmp rsa pkey"}, + {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE), "missing verify message"}, + {ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) , "multiple sgc restarts"}, + {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET), "non sslv2 initial packet"}, + {ERR_REASON(SSL_R_NO_APPLICATION_PROTOCOL), "no application protocol"}, + {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED), "no certificates returned"}, + {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED), "no certificate assigned"}, + {ERR_REASON(SSL_R_NO_CERTIFICATE_RETURNED), "no certificate returned"}, + {ERR_REASON(SSL_R_NO_CERTIFICATE_SET) , "no certificate set"}, + {ERR_REASON(SSL_R_NO_CERTIFICATE_SPECIFIED), "no certificate specified"}, + {ERR_REASON(SSL_R_NO_CIPHERS_AVAILABLE) , "no ciphers available"}, + {ERR_REASON(SSL_R_NO_CIPHERS_PASSED) , "no ciphers passed"}, + {ERR_REASON(SSL_R_NO_CIPHERS_SPECIFIED) , "no ciphers specified"}, + {ERR_REASON(SSL_R_NO_CIPHER_LIST) , "no cipher list"}, + {ERR_REASON(SSL_R_NO_CIPHER_MATCH) , "no cipher match"}, + {ERR_REASON(SSL_R_NO_CLIENT_CERT_METHOD) , "no client cert method"}, + {ERR_REASON(SSL_R_NO_CLIENT_CERT_RECEIVED), "no client cert received"}, + {ERR_REASON(SSL_R_NO_COMPRESSION_SPECIFIED), "no compression specified"}, + {ERR_REASON(SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER), "Peer haven't sent GOST certificate, required for selected ciphersuite"}, + {ERR_REASON(SSL_R_NO_METHOD_SPECIFIED) , "no method specified"}, + {ERR_REASON(SSL_R_NO_PRIVATEKEY) , "no privatekey"}, + {ERR_REASON(SSL_R_NO_PRIVATE_KEY_ASSIGNED), "no private key assigned"}, + {ERR_REASON(SSL_R_NO_PROTOCOLS_AVAILABLE), "no protocols available"}, + {ERR_REASON(SSL_R_NO_PUBLICKEY) , "no publickey"}, + {ERR_REASON(SSL_R_NO_RENEGOTIATION) , "no renegotiation"}, + {ERR_REASON(SSL_R_NO_REQUIRED_DIGEST) , "digest requred for handshake isn't computed"}, + {ERR_REASON(SSL_R_NO_SHARED_CIPHER) , "no shared cipher"}, + {ERR_REASON(SSL_R_NO_SRTP_PROFILES) , "no srtp profiles"}, + {ERR_REASON(SSL_R_NO_VERIFY_CALLBACK) , "no verify callback"}, + {ERR_REASON(SSL_R_NULL_SSL_CTX) , "null ssl ctx"}, + {ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED), "null ssl method passed"}, + {ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED), "old session cipher not returned"}, + {ERR_REASON(SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED), "old session compression algorithm not returned"}, + {ERR_REASON(SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE), "only tls allowed in fips mode"}, + {ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG), "packet length too long"}, + {ERR_REASON(SSL_R_PARSE_TLSEXT) , "parse tlsext"}, + {ERR_REASON(SSL_R_PATH_TOO_LONG) , "path too long"}, + {ERR_REASON(SSL_R_PEER_BEHAVING_BADLY) , "peer is doing strange or hostile things"}, + {ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE), "peer did not return a certificate"}, + {ERR_REASON(SSL_R_PEER_ERROR) , "peer error"}, + {ERR_REASON(SSL_R_PEER_ERROR_CERTIFICATE), "peer error certificate"}, + {ERR_REASON(SSL_R_PEER_ERROR_NO_CERTIFICATE), "peer error no certificate"}, + {ERR_REASON(SSL_R_PEER_ERROR_NO_CIPHER) , "peer error no cipher"}, + {ERR_REASON(SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE), "peer error unsupported certificate type"}, + {ERR_REASON(SSL_R_PRE_MAC_LENGTH_TOO_LONG), "pre mac length too long"}, + {ERR_REASON(SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS), "problems mapping cipher functions"}, + {ERR_REASON(SSL_R_PROTOCOL_IS_SHUTDOWN) , "protocol is shutdown"}, + {ERR_REASON(SSL_R_PSK_IDENTITY_NOT_FOUND), "psk identity not found"}, + {ERR_REASON(SSL_R_PSK_NO_CLIENT_CB) , "psk no client cb"}, + {ERR_REASON(SSL_R_PSK_NO_SERVER_CB) , "psk no server cb"}, + {ERR_REASON(SSL_R_PUBLIC_KEY_ENCRYPT_ERROR), "public key encrypt error"}, + {ERR_REASON(SSL_R_PUBLIC_KEY_IS_NOT_RSA) , "public key is not rsa"}, + {ERR_REASON(SSL_R_PUBLIC_KEY_NOT_RSA) , "public key not rsa"}, + {ERR_REASON(SSL_R_QUIC_INTERNAL_ERROR) , "QUIC: internal error"}, + {ERR_REASON(SSL_R_READ_BIO_NOT_SET) , "read bio not set"}, + {ERR_REASON(SSL_R_READ_TIMEOUT_EXPIRED) , "read timeout expired"}, + {ERR_REASON(SSL_R_READ_WRONG_PACKET_TYPE), "read wrong packet type"}, + {ERR_REASON(SSL_R_RECORD_LENGTH_MISMATCH), "record length mismatch"}, + {ERR_REASON(SSL_R_RECORD_TOO_LARGE) , "record too large"}, + {ERR_REASON(SSL_R_RECORD_TOO_SMALL) , "record too small"}, + {ERR_REASON(SSL_R_RENEGOTIATE_EXT_TOO_LONG), "renegotiate ext too long"}, + {ERR_REASON(SSL_R_RENEGOTIATION_ENCODING_ERR), "renegotiation encoding err"}, + {ERR_REASON(SSL_R_RENEGOTIATION_MISMATCH), "renegotiation mismatch"}, + {ERR_REASON(SSL_R_REQUIRED_CIPHER_MISSING), "required cipher missing"}, + {ERR_REASON(SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING), "required compresssion algorithm missing"}, + {ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO), "reuse cert length not zero"}, + {ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO), "reuse cert type not zero"}, + {ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO), "reuse cipher list not zero"}, + {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING), "scsv received when renegotiating"}, + {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT) , "serverhello tlsext"}, + {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED), "session id context uninitialized"}, + {ERR_REASON(SSL_R_SHORT_READ) , "short read"}, + {ERR_REASON(SSL_R_SIGNATURE_ALGORITHMS_ERROR), "signature algorithms error"}, + {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE), "signature for non signing certificate"}, + {ERR_REASON(SSL_R_SRP_A_CALC) , "error with the srp params"}, + {ERR_REASON(SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES), "srtp could not allocate profiles"}, + {ERR_REASON(SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG), "srtp protection profile list too long"}, + {ERR_REASON(SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE), "srtp unknown protection profile"}, + {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE), "ssl23 doing session id reuse"}, + {ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG), "ssl2 connection id too long"}, + {ERR_REASON(SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT), "ssl3 ext invalid ecpointformat"}, + {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME), "ssl3 ext invalid servername"}, + {ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE), "ssl3 ext invalid servername type"}, + {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG), "ssl3 session id too long"}, + {ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT), "ssl3 session id too short"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE), "sslv3 alert bad certificate"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_BAD_RECORD_MAC), "sslv3 alert bad record mac"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED), "sslv3 alert certificate expired"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED), "sslv3 alert certificate revoked"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN), "sslv3 alert certificate unknown"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE), "sslv3 alert decompression failure"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE), "sslv3 alert handshake failure"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER), "sslv3 alert illegal parameter"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_NO_CERTIFICATE), "sslv3 alert no certificate"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE), "sslv3 alert unexpected message"}, + {ERR_REASON(SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE), "sslv3 alert unsupported certificate"}, + {ERR_REASON(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION), "ssl ctx has no default ssl version"}, + {ERR_REASON(SSL_R_SSL_HANDSHAKE_FAILURE) , "ssl handshake failure"}, + {ERR_REASON(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS), "ssl library has no ciphers"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_CALLBACK_FAILED), "ssl session id callback failed"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_CONFLICT), "ssl session id conflict"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG), "ssl session id context too long"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH), "ssl session id has bad length"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_IS_DIFFERENT), "ssl session id is different"}, + {ERR_REASON(SSL_R_SSL_SESSION_ID_TOO_LONG), "ssl session id is too long"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_ACCESS_DENIED), "tlsv1 alert access denied"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_DECODE_ERROR), "tlsv1 alert decode error"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPTION_FAILED), "tlsv1 alert decryption failed"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_DECRYPT_ERROR), "tlsv1 alert decrypt error"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION), "tlsv1 alert export restriction"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK), "tlsv1 alert inappropriate fallback"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY), "tlsv1 alert insufficient security"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_INTERNAL_ERROR), "tlsv1 alert internal error"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION), "tlsv1 alert no renegotiation"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_PROTOCOL_VERSION), "tlsv1 alert protocol version"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_RECORD_OVERFLOW), "tlsv1 alert record overflow"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_UNKNOWN_CA), "tlsv1 alert unknown ca"}, + {ERR_REASON(SSL_R_TLSV1_ALERT_USER_CANCELLED), "tlsv1 alert user cancelled"}, + {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE), "tlsv1 bad certificate hash value"}, + {ERR_REASON(SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE), "tlsv1 bad certificate status response"}, + {ERR_REASON(SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE), "tlsv1 certificate unobtainable"}, + {ERR_REASON(SSL_R_TLSV1_UNRECOGNIZED_NAME), "tlsv1 unrecognized name"}, + {ERR_REASON(SSL_R_TLSV1_UNSUPPORTED_EXTENSION), "tlsv1 unsupported extension"}, + {ERR_REASON(SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER), "tls client cert req with anon cipher"}, + {ERR_REASON(SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT), "peer does not accept heartbeats"}, + {ERR_REASON(SSL_R_TLS_HEARTBEAT_PENDING) , "heartbeat request already pending"}, + {ERR_REASON(SSL_R_TLS_ILLEGAL_EXPORTER_LABEL), "tls illegal exporter label"}, + {ERR_REASON(SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST), "tls invalid ecpointformat list"}, + {ERR_REASON(SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST), "tls peer did not respond with certificate list"}, + {ERR_REASON(SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG), "tls rsa encrypted value length is wrong"}, + {ERR_REASON(SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER), "tried to use unsupported cipher"}, + {ERR_REASON(SSL_R_UNABLE_TO_DECODE_DH_CERTS), "unable to decode dh certs"}, + {ERR_REASON(SSL_R_UNABLE_TO_DECODE_ECDH_CERTS), "unable to decode ecdh certs"}, + {ERR_REASON(SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY), "unable to extract public key"}, + {ERR_REASON(SSL_R_UNABLE_TO_FIND_DH_PARAMETERS), "unable to find dh parameters"}, + {ERR_REASON(SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS), "unable to find ecdh parameters"}, + {ERR_REASON(SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS), "unable to find public key parameters"}, + {ERR_REASON(SSL_R_UNABLE_TO_FIND_SSL_METHOD), "unable to find ssl method"}, + {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL2_MD5_ROUTINES), "unable to load ssl2 md5 routines"}, + {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES), "unable to load ssl3 md5 routines"}, + {ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES), "unable to load ssl3 sha1 routines"}, + {ERR_REASON(SSL_R_UNEXPECTED_MESSAGE) , "unexpected message"}, + {ERR_REASON(SSL_R_UNEXPECTED_RECORD) , "unexpected record"}, + {ERR_REASON(SSL_R_UNINITIALIZED) , "uninitialized"}, + {ERR_REASON(SSL_R_UNKNOWN), "unknown failure occurred"}, + {ERR_REASON(SSL_R_UNKNOWN_ALERT_TYPE) , "unknown alert type"}, + {ERR_REASON(SSL_R_UNKNOWN_CERTIFICATE_TYPE), "unknown certificate type"}, + {ERR_REASON(SSL_R_UNKNOWN_CIPHER_RETURNED), "unknown cipher returned"}, + {ERR_REASON(SSL_R_UNKNOWN_CIPHER_TYPE) , "unknown cipher type"}, + {ERR_REASON(SSL_R_UNKNOWN_DIGEST) , "unknown digest"}, + {ERR_REASON(SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE), "unknown key exchange type"}, + {ERR_REASON(SSL_R_UNKNOWN_PKEY_TYPE) , "unknown pkey type"}, + {ERR_REASON(SSL_R_UNKNOWN_PROTOCOL) , "unknown protocol"}, + {ERR_REASON(SSL_R_UNKNOWN_REMOTE_ERROR_TYPE), "unknown remote error type"}, + {ERR_REASON(SSL_R_UNKNOWN_SSL_VERSION) , "unknown ssl version"}, + {ERR_REASON(SSL_R_UNKNOWN_STATE) , "unknown state"}, + {ERR_REASON(SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED), "unsafe legacy renegotiation disabled"}, + {ERR_REASON(SSL_R_UNSUPPORTED_CIPHER) , "unsupported cipher"}, + {ERR_REASON(SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM), "unsupported compression algorithm"}, + {ERR_REASON(SSL_R_UNSUPPORTED_DIGEST_TYPE), "unsupported digest type"}, + {ERR_REASON(SSL_R_UNSUPPORTED_ELLIPTIC_CURVE), "unsupported elliptic curve"}, + {ERR_REASON(SSL_R_UNSUPPORTED_PROTOCOL) , "unsupported protocol"}, + {ERR_REASON(SSL_R_UNSUPPORTED_SSL_VERSION), "unsupported ssl version"}, + {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE), "unsupported status type"}, + {ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED), "use srtp not negotiated"}, + {ERR_REASON(SSL_R_VERSION_TOO_LOW) , "version too low"}, + {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET) , "write bio not set"}, + {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) , "wrong cipher returned"}, + {ERR_REASON(SSL_R_WRONG_CURVE) , "wrong curve"}, + {ERR_REASON(SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED), "QUIC: wrong encryption level received"}, + {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE) , "wrong message type"}, + {ERR_REASON(SSL_R_WRONG_NUMBER_OF_KEY_BITS), "wrong number of key bits"}, + {ERR_REASON(SSL_R_WRONG_SIGNATURE_LENGTH), "wrong signature length"}, + {ERR_REASON(SSL_R_WRONG_SIGNATURE_SIZE) , "wrong signature size"}, + {ERR_REASON(SSL_R_WRONG_SIGNATURE_TYPE) , "wrong signature type"}, + {ERR_REASON(SSL_R_WRONG_SSL_VERSION) , "wrong ssl version"}, + {ERR_REASON(SSL_R_WRONG_VERSION_NUMBER) , "wrong version number"}, + {ERR_REASON(SSL_R_X509_LIB) , "x509 lib"}, + {ERR_REASON(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS), "x509 verification setup problems"}, + {0, NULL} +}; + +#endif + +void +ERR_load_SSL_strings(void) +{ +#ifndef OPENSSL_NO_ERR + if (ERR_func_error_string(SSL_str_functs[0].error) == NULL) { + ERR_load_strings(0, SSL_str_functs); + ERR_load_strings(0, SSL_str_reasons); + } +#endif +} +LSSL_ALIAS(ERR_load_SSL_strings); + +void +SSL_load_error_strings(void) +{ +#ifndef OPENSSL_NO_ERR + ERR_load_crypto_strings(); + ERR_load_SSL_strings(); +#endif +} +LSSL_ALIAS(SSL_load_error_strings); + +int +SSL_state_func_code(int state) { + switch (state) { + case SSL3_ST_CW_FLUSH: + return 1; + case SSL3_ST_CW_CLNT_HELLO_A: + return 2; + case SSL3_ST_CW_CLNT_HELLO_B: + return 3; + case SSL3_ST_CR_SRVR_HELLO_A: + return 4; + case SSL3_ST_CR_SRVR_HELLO_B: + return 5; + case SSL3_ST_CR_CERT_A: + return 6; + case SSL3_ST_CR_CERT_B: + return 7; + case SSL3_ST_CR_KEY_EXCH_A: + return 8; + case SSL3_ST_CR_KEY_EXCH_B: + return 9; + case SSL3_ST_CR_CERT_REQ_A: + return 10; + case SSL3_ST_CR_CERT_REQ_B: + return 11; + case SSL3_ST_CR_SRVR_DONE_A: + return 12; + case SSL3_ST_CR_SRVR_DONE_B: + return 13; + case SSL3_ST_CW_CERT_A: + return 14; + case SSL3_ST_CW_CERT_B: + return 15; + case SSL3_ST_CW_CERT_C: + return 16; + case SSL3_ST_CW_CERT_D: + return 17; + case SSL3_ST_CW_KEY_EXCH_A: + return 18; + case SSL3_ST_CW_KEY_EXCH_B: + return 19; + case SSL3_ST_CW_CERT_VRFY_A: + return 20; + case SSL3_ST_CW_CERT_VRFY_B: + return 21; + case SSL3_ST_CW_CHANGE_A: + return 22; + case SSL3_ST_CW_CHANGE_B: + return 23; + case SSL3_ST_CW_FINISHED_A: + return 26; + case SSL3_ST_CW_FINISHED_B: + return 27; + case SSL3_ST_CR_CHANGE_A: + return 28; + case SSL3_ST_CR_CHANGE_B: + return 29; + case SSL3_ST_CR_FINISHED_A: + return 30; + case SSL3_ST_CR_FINISHED_B: + return 31; + case SSL3_ST_CR_SESSION_TICKET_A: + return 32; + case SSL3_ST_CR_SESSION_TICKET_B: + return 33; + case SSL3_ST_CR_CERT_STATUS_A: + return 34; + case SSL3_ST_CR_CERT_STATUS_B: + return 35; + case SSL3_ST_SW_FLUSH: + return 36; + case SSL3_ST_SR_CLNT_HELLO_A: + return 37; + case SSL3_ST_SR_CLNT_HELLO_B: + return 38; + case SSL3_ST_SR_CLNT_HELLO_C: + return 39; + case SSL3_ST_SW_HELLO_REQ_A: + return 40; + case SSL3_ST_SW_HELLO_REQ_B: + return 41; + case SSL3_ST_SW_HELLO_REQ_C: + return 42; + case SSL3_ST_SW_SRVR_HELLO_A: + return 43; + case SSL3_ST_SW_SRVR_HELLO_B: + return 44; + case SSL3_ST_SW_CERT_A: + return 45; + case SSL3_ST_SW_CERT_B: + return 46; + case SSL3_ST_SW_KEY_EXCH_A: + return 47; + case SSL3_ST_SW_KEY_EXCH_B: + return 48; + case SSL3_ST_SW_CERT_REQ_A: + return 49; + case SSL3_ST_SW_CERT_REQ_B: + return 50; + case SSL3_ST_SW_SRVR_DONE_A: + return 51; + case SSL3_ST_SW_SRVR_DONE_B: + return 52; + case SSL3_ST_SR_CERT_A: + return 53; + case SSL3_ST_SR_CERT_B: + return 54; + case SSL3_ST_SR_KEY_EXCH_A: + return 55; + case SSL3_ST_SR_KEY_EXCH_B: + return 56; + case SSL3_ST_SR_CERT_VRFY_A: + return 57; + case SSL3_ST_SR_CERT_VRFY_B: + return 58; + case SSL3_ST_SR_CHANGE_A: + return 59; + case SSL3_ST_SR_CHANGE_B: + return 60; + case SSL3_ST_SR_FINISHED_A: + return 63; + case SSL3_ST_SR_FINISHED_B: + return 64; + case SSL3_ST_SW_CHANGE_A: + return 65; + case SSL3_ST_SW_CHANGE_B: + return 66; + case SSL3_ST_SW_FINISHED_A: + return 67; + case SSL3_ST_SW_FINISHED_B: + return 68; + case SSL3_ST_SW_SESSION_TICKET_A: + return 69; + case SSL3_ST_SW_SESSION_TICKET_B: + return 70; + case SSL3_ST_SW_CERT_STATUS_A: + return 71; + case SSL3_ST_SW_CERT_STATUS_B: + return 72; + case SSL_ST_BEFORE: + return 73; + case SSL_ST_ACCEPT: + return 74; + case SSL_ST_CONNECT: + return 75; + case SSL_ST_OK: + return 76; + case SSL_ST_RENEGOTIATE: + return 77; + case SSL_ST_BEFORE|SSL_ST_CONNECT: + return 78; + case SSL_ST_OK|SSL_ST_CONNECT: + return 79; + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + return 80; + case SSL_ST_OK|SSL_ST_ACCEPT: + return 81; + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + return 83; + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + return 84; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + return 85; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + return 86; + default: + break; + } + return 0xfff; +} + +void +SSL_error_internal(const SSL *s, int r, char *f, int l) +{ + ERR_PUT_error(ERR_LIB_SSL, + (SSL_state_func_code(s->s3->hs.state)), r, f, l); +} diff --git a/ssl/ssl_init.c b/ssl/ssl_init.c new file mode 100644 index 0000000..a8646cc --- /dev/null +++ b/ssl/ssl_init.c @@ -0,0 +1,52 @@ +/* $OpenBSD: ssl_init.c,v 1.4 2023/07/08 16:40:13 beck Exp $ */ +/* + * Copyright (c) 2018 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* OpenSSL style init */ + +#include +#include + +#include + +#include "ssl_local.h" + +static pthread_t ssl_init_thread; + +static void +OPENSSL_init_ssl_internal(void) +{ + ssl_init_thread = pthread_self(); + SSL_load_error_strings(); + SSL_library_init(); +} + +int +OPENSSL_init_ssl(uint64_t opts, const void *settings) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + + if (pthread_equal(pthread_self(), ssl_init_thread)) + return 1; /* don't recurse */ + + OPENSSL_init_crypto(opts, settings); + + if (pthread_once(&once, OPENSSL_init_ssl_internal) != 0) + return 0; + + return 1; +} +LSSL_ALIAS(OPENSSL_init_ssl); diff --git a/ssl/ssl_kex.c b/ssl/ssl_kex.c new file mode 100644 index 0000000..fa420a3 --- /dev/null +++ b/ssl/ssl_kex.c @@ -0,0 +1,422 @@ +/* $OpenBSD: ssl_kex.c,v 1.12 2023/07/28 16:02:34 tb Exp $ */ +/* + * Copyright (c) 2020, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include "bytestring.h" + +#define DHE_MINIMUM_BITS 1024 + +int +ssl_kex_generate_dhe(DH *dh, DH *dh_params) +{ + BIGNUM *p = NULL, *g = NULL; + int ret = 0; + + if ((p = BN_dup(DH_get0_p(dh_params))) == NULL) + goto err; + if ((g = BN_dup(DH_get0_g(dh_params))) == NULL) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + if (!DH_generate_key(dh)) + goto err; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_generate_dhe_params_auto(DH *dh, size_t key_bits) +{ + BIGNUM *p = NULL, *g = NULL; + int ret = 0; + + if (key_bits >= 8192) + p = BN_get_rfc3526_prime_8192(NULL); + else if (key_bits >= 4096) + p = BN_get_rfc3526_prime_4096(NULL); + else if (key_bits >= 3072) + p = BN_get_rfc3526_prime_3072(NULL); + else if (key_bits >= 2048) + p = BN_get_rfc3526_prime_2048(NULL); + else if (key_bits >= 1536) + p = BN_get_rfc3526_prime_1536(NULL); + else + p = BN_get_rfc2409_prime_1024(NULL); + + if (p == NULL) + goto err; + + if ((g = BN_new()) == NULL) + goto err; + if (!BN_set_word(g, 2)) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + if (!DH_generate_key(dh)) + goto err; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_params_dhe(DH *dh, CBB *cbb) +{ + int dh_p_len, dh_g_len; + CBB dh_p, dh_g; + uint8_t *data; + + if ((dh_p_len = BN_num_bytes(DH_get0_p(dh))) <= 0) + return 0; + if ((dh_g_len = BN_num_bytes(DH_get0_g(dh))) <= 0) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_p)) + return 0; + if (!CBB_add_space(&dh_p, &data, dh_p_len)) + return 0; + if (BN_bn2bin(DH_get0_p(dh), data) != dh_p_len) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_g)) + return 0; + if (!CBB_add_space(&dh_g, &data, dh_g_len)) + return 0; + if (BN_bn2bin(DH_get0_g(dh), data) != dh_g_len) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +ssl_kex_public_dhe(DH *dh, CBB *cbb) +{ + uint8_t *data; + int dh_y_len; + CBB dh_y; + + if ((dh_y_len = BN_num_bytes(DH_get0_pub_key(dh))) <= 0) + return 0; + + if (!CBB_add_u16_length_prefixed(cbb, &dh_y)) + return 0; + if (!CBB_add_space(&dh_y, &data, dh_y_len)) + return 0; + if (BN_bn2bin(DH_get0_pub_key(dh), data) != dh_y_len) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +ssl_kex_peer_params_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_params) +{ + BIGNUM *p = NULL, *g = NULL; + CBS dh_p, dh_g; + int ret = 0; + + *decode_error = 0; + *invalid_params = 0; + + if (!CBS_get_u16_length_prefixed(cbs, &dh_p)) { + *decode_error = 1; + goto err; + } + if (!CBS_get_u16_length_prefixed(cbs, &dh_g)) { + *decode_error = 1; + goto err; + } + + if ((p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL)) == NULL) + goto err; + if ((g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL)) == NULL) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = NULL; + g = NULL; + + /* XXX - consider calling DH_check(). */ + + if (DH_bits(dh) < DHE_MINIMUM_BITS) + *invalid_params = 1; + + ret = 1; + + err: + BN_free(p); + BN_free(g); + + return ret; +} + +int +ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_key) +{ + BIGNUM *pub_key = NULL; + int check_flags; + CBS dh_y; + int ret = 0; + + *decode_error = 0; + *invalid_key = 0; + + if (!CBS_get_u16_length_prefixed(cbs, &dh_y)) { + *decode_error = 1; + goto err; + } + + if ((pub_key = BN_bin2bn(CBS_data(&dh_y), CBS_len(&dh_y), + NULL)) == NULL) + goto err; + + if (!DH_set0_key(dh, pub_key, NULL)) + goto err; + pub_key = NULL; + + if (!DH_check_pub_key(dh, DH_get0_pub_key(dh), &check_flags)) + goto err; + if (check_flags != 0) + *invalid_key = 1; + + ret = 1; + + err: + BN_free(pub_key); + + return ret; +} + +int +ssl_kex_derive_dhe(DH *dh, DH *dh_peer, + uint8_t **shared_key, size_t *shared_key_len) +{ + uint8_t *key = NULL; + int key_len = 0; + int ret = 0; + + if ((key_len = DH_size(dh)) <= 0) + goto err; + if ((key = calloc(1, key_len)) == NULL) + goto err; + + if ((key_len = DH_compute_key(key, DH_get0_pub_key(dh_peer), dh)) <= 0) + goto err; + + *shared_key = key; + *shared_key_len = key_len; + key = NULL; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + +int +ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey) +{ + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + EC_KEY *ec_key = NULL; + BIGNUM *order = NULL; + int ret = 0; + + /* Fudge up an EC_KEY that looks like X25519... */ + if ((group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) + goto err; + if ((point = EC_POINT_new(group)) == NULL) + goto err; + if ((order = BN_new()) == NULL) + goto err; + if (!BN_set_bit(order, 252)) + goto err; + if (!EC_GROUP_set_generator(group, point, order, NULL)) + goto err; + EC_GROUP_set_curve_name(group, NID_X25519); + if ((ec_key = EC_KEY_new()) == NULL) + goto err; + if (!EC_KEY_set_group(ec_key, group)) + goto err; + if (!EVP_PKEY_set1_EC_KEY(pkey, ec_key)) + goto err; + + ret = 1; + + err: + EC_GROUP_free(group); + EC_POINT_free(point); + EC_KEY_free(ec_key); + BN_free(order); + + return ret; +} + +int +ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid) +{ + EC_GROUP *group; + int ret = 0; + + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) + goto err; + + if (!EC_KEY_set_group(ecdh, group)) + goto err; + if (!EC_KEY_generate_key(ecdh)) + goto err; + + ret = 1; + + err: + EC_GROUP_free(group); + + return ret; +} + +int +ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb) +{ + const EC_GROUP *group; + const EC_POINT *point; + uint8_t *ecp; + size_t ecp_len; + int ret = 0; + + if ((group = EC_KEY_get0_group(ecdh)) == NULL) + goto err; + if ((point = EC_KEY_get0_public_key(ecdh)) == NULL) + goto err; + + if ((ecp_len = EC_POINT_point2oct(group, point, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL)) == 0) + goto err; + if (!CBB_add_space(cbb, &ecp, ecp_len)) + goto err; + if ((EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + ecp, ecp_len, NULL)) == 0) + goto err; + + ret = 1; + + err: + return ret; +} + +int +ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs) +{ + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + int ret = 0; + + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) + goto err; + + if (!EC_KEY_set_group(ecdh, group)) + goto err; + + if ((point = EC_POINT_new(group)) == NULL) + goto err; + if (EC_POINT_oct2point(group, point, CBS_data(cbs), CBS_len(cbs), + NULL) == 0) + goto err; + if (!EC_KEY_set_public_key(ecdh, point)) + goto err; + + ret = 1; + + err: + EC_GROUP_free(group); + EC_POINT_free(point); + + return ret; +} + +int +ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, + uint8_t **shared_key, size_t *shared_key_len) +{ + const EC_POINT *point; + uint8_t *key = NULL; + int key_len = 0; + int ret = 0; + + if (!EC_GROUP_check(EC_KEY_get0_group(ecdh), NULL)) + goto err; + if (!EC_GROUP_check(EC_KEY_get0_group(ecdh_peer), NULL)) + goto err; + + if ((point = EC_KEY_get0_public_key(ecdh_peer)) == NULL) + goto err; + + if ((key_len = ECDH_size(ecdh)) <= 0) + goto err; + if ((key = calloc(1, key_len)) == NULL) + goto err; + + if (ECDH_compute_key(key, key_len, point, ecdh, NULL) <= 0) + goto err; + + *shared_key = key; + *shared_key_len = key_len; + key = NULL; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c new file mode 100644 index 0000000..0ac393f --- /dev/null +++ b/ssl/ssl_lib.c @@ -0,0 +1,3695 @@ +/* $OpenBSD: ssl_lib.c,v 1.314 2023/09/19 01:22:31 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_ENGINE +#include +#endif + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" +#include "tls12_internal.h" + +const char *SSL_version_str = OPENSSL_VERSION_TEXT; + +int +SSL_clear(SSL *s) +{ + if (s->method == NULL) { + SSLerror(s, SSL_R_NO_METHOD_SPECIFIED); + return (0); + } + + if (ssl_clear_bad_session(s)) { + SSL_SESSION_free(s->session); + s->session = NULL; + } + + s->error = 0; + s->hit = 0; + s->shutdown = 0; + + if (s->renegotiate) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return (0); + } + + s->version = s->method->version; + s->client_version = s->version; + s->rwstate = SSL_NOTHING; + s->rstate = SSL_ST_READ_HEADER; + + tls13_ctx_free(s->tls13); + s->tls13 = NULL; + + ssl3_release_init_buffer(s); + + ssl_clear_cipher_state(s); + + s->first_packet = 0; + + /* + * Check to see if we were changed into a different method, if + * so, revert back if we are not doing session-id reuse. + */ + if (!s->in_handshake && (s->session == NULL) && + (s->method != s->ctx->method)) { + s->method->ssl_free(s); + s->method = s->ctx->method; + if (!s->method->ssl_new(s)) + return (0); + } else + s->method->ssl_clear(s); + + return (1); +} +LSSL_ALIAS(SSL_clear); + +/* Used to change an SSL_CTXs default SSL method type */ +int +SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth) +{ + STACK_OF(SSL_CIPHER) *ciphers; + + ctx->method = meth; + + ciphers = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, + ctx->cipher_list_tls13, SSL_DEFAULT_CIPHER_LIST, + ctx->cert); + if (ciphers == NULL || sk_SSL_CIPHER_num(ciphers) <= 0) { + SSLerrorx(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS); + return (0); + } + return (1); +} +LSSL_ALIAS(SSL_CTX_set_ssl_version); + +SSL * +SSL_new(SSL_CTX *ctx) +{ + SSL *s; + CBS cbs; + + if (ctx == NULL) { + SSLerrorx(SSL_R_NULL_SSL_CTX); + return (NULL); + } + if (ctx->method == NULL) { + SSLerrorx(SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION); + return (NULL); + } + + if ((s = calloc(1, sizeof(*s))) == NULL) + goto err; + + if ((s->rl = tls12_record_layer_new()) == NULL) + goto err; + + s->min_tls_version = ctx->min_tls_version; + s->max_tls_version = ctx->max_tls_version; + s->min_proto_version = ctx->min_proto_version; + s->max_proto_version = ctx->max_proto_version; + + s->options = ctx->options; + s->mode = ctx->mode; + s->max_cert_list = ctx->max_cert_list; + s->num_tickets = ctx->num_tickets; + + if ((s->cert = ssl_cert_dup(ctx->cert)) == NULL) + goto err; + + s->read_ahead = ctx->read_ahead; + s->msg_callback = ctx->msg_callback; + s->msg_callback_arg = ctx->msg_callback_arg; + s->verify_mode = ctx->verify_mode; + s->sid_ctx_length = ctx->sid_ctx_length; + OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx); + memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx)); + s->verify_callback = ctx->default_verify_callback; + s->generate_session_id = ctx->generate_session_id; + + s->param = X509_VERIFY_PARAM_new(); + if (!s->param) + goto err; + X509_VERIFY_PARAM_inherit(s->param, ctx->param); + s->quiet_shutdown = ctx->quiet_shutdown; + s->max_send_fragment = ctx->max_send_fragment; + + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + s->ctx = ctx; + s->tlsext_debug_cb = NULL; + s->tlsext_debug_arg = NULL; + s->tlsext_ticket_expected = 0; + s->tlsext_status_type = -1; + s->tlsext_status_expected = 0; + s->tlsext_ocsp_ids = NULL; + s->tlsext_ocsp_exts = NULL; + s->tlsext_ocsp_resp = NULL; + s->tlsext_ocsp_resp_len = 0; + CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + s->initial_ctx = ctx; + + if (!tlsext_randomize_build_order(s)) + goto err; + + if (ctx->tlsext_ecpointformatlist != NULL) { + s->tlsext_ecpointformatlist = + calloc(ctx->tlsext_ecpointformatlist_length, + sizeof(ctx->tlsext_ecpointformatlist[0])); + if (s->tlsext_ecpointformatlist == NULL) + goto err; + memcpy(s->tlsext_ecpointformatlist, + ctx->tlsext_ecpointformatlist, + ctx->tlsext_ecpointformatlist_length * + sizeof(ctx->tlsext_ecpointformatlist[0])); + s->tlsext_ecpointformatlist_length = + ctx->tlsext_ecpointformatlist_length; + } + if (ctx->tlsext_supportedgroups != NULL) { + s->tlsext_supportedgroups = + calloc(ctx->tlsext_supportedgroups_length, + sizeof(ctx->tlsext_supportedgroups[0])); + if (s->tlsext_supportedgroups == NULL) + goto err; + memcpy(s->tlsext_supportedgroups, + ctx->tlsext_supportedgroups, + ctx->tlsext_supportedgroups_length * + sizeof(ctx->tlsext_supportedgroups[0])); + s->tlsext_supportedgroups_length = + ctx->tlsext_supportedgroups_length; + } + + CBS_init(&cbs, ctx->alpn_client_proto_list, + ctx->alpn_client_proto_list_len); + if (!CBS_stow(&cbs, &s->alpn_client_proto_list, + &s->alpn_client_proto_list_len)) + goto err; + + s->verify_result = X509_V_OK; + + s->method = ctx->method; + s->quic_method = ctx->quic_method; + + if (!s->method->ssl_new(s)) + goto err; + + s->references = 1; + s->server = ctx->method->server; + + SSL_clear(s); + + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + + return (s); + + err: + SSL_free(s); + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); +} +LSSL_ALIAS(SSL_new); + +int +SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > sizeof ctx->sid_ctx) { + SSLerrorx(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return (0); + } + ctx->sid_ctx_length = sid_ctx_len; + memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len); + + return (1); +} +LSSL_ALIAS(SSL_CTX_set_session_id_context); + +int +SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + SSLerror(ssl, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return (0); + } + ssl->sid_ctx_length = sid_ctx_len; + memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len); + + return (1); +} +LSSL_ALIAS(SSL_set_session_id_context); + +int +SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb) +{ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + ctx->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return (1); +} +LSSL_ALIAS(SSL_CTX_set_generate_session_id); + +int +SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb) +{ + CRYPTO_w_lock(CRYPTO_LOCK_SSL); + ssl->generate_session_id = cb; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL); + return (1); +} +LSSL_ALIAS(SSL_set_generate_session_id); + +int +SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, + unsigned int id_len) +{ + /* + * A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp + * shows how we can "construct" a session to give us the desired + * check - ie. to find if there's a session in the hash table + * that would conflict with any new session built out of this + * id/id_len and the ssl_version in use by this SSL. + */ + SSL_SESSION r, *p; + + if (id_len > sizeof r.session_id) + return (0); + + r.ssl_version = ssl->version; + r.session_id_length = id_len; + memcpy(r.session_id, id, id_len); + + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + p = lh_SSL_SESSION_retrieve(ssl->ctx->sessions, &r); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + return (p != NULL); +} +LSSL_ALIAS(SSL_has_matching_session_id); + +int +SSL_CTX_set_purpose(SSL_CTX *s, int purpose) +{ + return (X509_VERIFY_PARAM_set_purpose(s->param, purpose)); +} +LSSL_ALIAS(SSL_CTX_set_purpose); + +int +SSL_set_purpose(SSL *s, int purpose) +{ + return (X509_VERIFY_PARAM_set_purpose(s->param, purpose)); +} +LSSL_ALIAS(SSL_set_purpose); + +int +SSL_CTX_set_trust(SSL_CTX *s, int trust) +{ + return (X509_VERIFY_PARAM_set_trust(s->param, trust)); +} +LSSL_ALIAS(SSL_CTX_set_trust); + +int +SSL_set_trust(SSL *s, int trust) +{ + return (X509_VERIFY_PARAM_set_trust(s->param, trust)); +} +LSSL_ALIAS(SSL_set_trust); + +int +SSL_set1_host(SSL *s, const char *hostname) +{ + struct in_addr ina; + struct in6_addr in6a; + + if (hostname != NULL && *hostname != '\0' && + (inet_pton(AF_INET, hostname, &ina) == 1 || + inet_pton(AF_INET6, hostname, &in6a) == 1)) + return X509_VERIFY_PARAM_set1_ip_asc(s->param, hostname); + else + return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0); +} +LSSL_ALIAS(SSL_set1_host); + +void +SSL_set_hostflags(SSL *s, unsigned int flags) +{ + X509_VERIFY_PARAM_set_hostflags(s->param, flags); +} +LSSL_ALIAS(SSL_set_hostflags); + +const char * +SSL_get0_peername(SSL *s) +{ + return X509_VERIFY_PARAM_get0_peername(s->param); +} +LSSL_ALIAS(SSL_get0_peername); + +X509_VERIFY_PARAM * +SSL_CTX_get0_param(SSL_CTX *ctx) +{ + return (ctx->param); +} +LSSL_ALIAS(SSL_CTX_get0_param); + +int +SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) +{ + return (X509_VERIFY_PARAM_set1(ctx->param, vpm)); +} +LSSL_ALIAS(SSL_CTX_set1_param); + +X509_VERIFY_PARAM * +SSL_get0_param(SSL *ssl) +{ + return (ssl->param); +} +LSSL_ALIAS(SSL_get0_param); + +int +SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) +{ + return (X509_VERIFY_PARAM_set1(ssl->param, vpm)); +} +LSSL_ALIAS(SSL_set1_param); + +void +SSL_free(SSL *s) +{ + int i; + + if (s == NULL) + return; + + i = CRYPTO_add(&s->references, -1, CRYPTO_LOCK_SSL); + if (i > 0) + return; + + X509_VERIFY_PARAM_free(s->param); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data); + + if (s->bbio != NULL) { + /* If the buffering BIO is in place, pop it off */ + if (s->bbio == s->wbio) { + s->wbio = BIO_pop(s->wbio); + } + BIO_free(s->bbio); + s->bbio = NULL; + } + + if (s->rbio != s->wbio) + BIO_free_all(s->rbio); + BIO_free_all(s->wbio); + + tls13_ctx_free(s->tls13); + + ssl3_release_init_buffer(s); + + sk_SSL_CIPHER_free(s->cipher_list); + sk_SSL_CIPHER_free(s->cipher_list_tls13); + + /* Make the next call work :-) */ + if (s->session != NULL) { + ssl_clear_bad_session(s); + SSL_SESSION_free(s->session); + } + + ssl_clear_cipher_state(s); + + ssl_cert_free(s->cert); + + free(s->tlsext_build_order); + + free(s->tlsext_hostname); + SSL_CTX_free(s->initial_ctx); + + free(s->tlsext_ecpointformatlist); + free(s->tlsext_supportedgroups); + + sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, + X509_EXTENSION_free); + sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); + free(s->tlsext_ocsp_resp); + + sk_X509_NAME_pop_free(s->client_CA, X509_NAME_free); + + if (s->method != NULL) + s->method->ssl_free(s); + + SSL_CTX_free(s->ctx); + + free(s->alpn_client_proto_list); + + free(s->quic_transport_params); + +#ifndef OPENSSL_NO_SRTP + sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles); +#endif + + tls12_record_layer_free(s->rl); + + free(s); +} +LSSL_ALIAS(SSL_free); + +int +SSL_up_ref(SSL *s) +{ + int refs = CRYPTO_add(&s->references, 1, CRYPTO_LOCK_SSL); + return (refs > 1) ? 1 : 0; +} +LSSL_ALIAS(SSL_up_ref); + +void +SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio) +{ + /* If the output buffering BIO is still in place, remove it */ + if (s->bbio != NULL) { + if (s->wbio == s->bbio) { + s->wbio = BIO_next(s->wbio); + BIO_set_next(s->bbio, NULL); + } + } + + if (s->rbio != rbio && s->rbio != s->wbio) + BIO_free_all(s->rbio); + if (s->wbio != wbio) + BIO_free_all(s->wbio); + s->rbio = rbio; + s->wbio = wbio; +} +LSSL_ALIAS(SSL_set_bio); + +BIO * +SSL_get_rbio(const SSL *s) +{ + return (s->rbio); +} +LSSL_ALIAS(SSL_get_rbio); + +void +SSL_set0_rbio(SSL *s, BIO *rbio) +{ + BIO_free_all(s->rbio); + s->rbio = rbio; +} +LSSL_ALIAS(SSL_set0_rbio); + +BIO * +SSL_get_wbio(const SSL *s) +{ + return (s->wbio); +} +LSSL_ALIAS(SSL_get_wbio); + +int +SSL_get_fd(const SSL *s) +{ + return (SSL_get_rfd(s)); +} +LSSL_ALIAS(SSL_get_fd); + +int +SSL_get_rfd(const SSL *s) +{ + int ret = -1; + BIO *b, *r; + + b = SSL_get_rbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r, &ret); + return (ret); +} +LSSL_ALIAS(SSL_get_rfd); + +int +SSL_get_wfd(const SSL *s) +{ + int ret = -1; + BIO *b, *r; + + b = SSL_get_wbio(s); + r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR); + if (r != NULL) + BIO_get_fd(r, &ret); + return (ret); +} +LSSL_ALIAS(SSL_get_wfd); + +int +SSL_set_fd(SSL *s, int fd) +{ + int ret = 0; + BIO *bio = NULL; + + bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerror(s, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, bio); + ret = 1; + err: + return (ret); +} +LSSL_ALIAS(SSL_set_fd); + +int +SSL_set_wfd(SSL *s, int fd) +{ + int ret = 0; + BIO *bio = NULL; + + if ((s->rbio == NULL) || (BIO_method_type(s->rbio) != BIO_TYPE_SOCKET) + || ((int)BIO_get_fd(s->rbio, NULL) != fd)) { + bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerror(s, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, SSL_get_rbio(s), bio); + } else + SSL_set_bio(s, SSL_get_rbio(s), SSL_get_rbio(s)); + ret = 1; + err: + return (ret); +} +LSSL_ALIAS(SSL_set_wfd); + +int +SSL_set_rfd(SSL *s, int fd) +{ + int ret = 0; + BIO *bio = NULL; + + if ((s->wbio == NULL) || (BIO_method_type(s->wbio) != BIO_TYPE_SOCKET) + || ((int)BIO_get_fd(s->wbio, NULL) != fd)) { + bio = BIO_new(BIO_s_socket()); + + if (bio == NULL) { + SSLerror(s, ERR_R_BUF_LIB); + goto err; + } + BIO_set_fd(bio, fd, BIO_NOCLOSE); + SSL_set_bio(s, bio, SSL_get_wbio(s)); + } else + SSL_set_bio(s, SSL_get_wbio(s), SSL_get_wbio(s)); + ret = 1; + err: + return (ret); +} +LSSL_ALIAS(SSL_set_rfd); + + +/* return length of latest Finished message we sent, copy to 'buf' */ +size_t +SSL_get_finished(const SSL *s, void *buf, size_t count) +{ + size_t ret; + + ret = s->s3->hs.finished_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->hs.finished, count); + return (ret); +} +LSSL_ALIAS(SSL_get_finished); + +/* return length of latest Finished message we expected, copy to 'buf' */ +size_t +SSL_get_peer_finished(const SSL *s, void *buf, size_t count) +{ + size_t ret; + + ret = s->s3->hs.peer_finished_len; + if (count > ret) + count = ret; + memcpy(buf, s->s3->hs.peer_finished, count); + return (ret); +} +LSSL_ALIAS(SSL_get_peer_finished); + + +int +SSL_get_verify_mode(const SSL *s) +{ + return (s->verify_mode); +} +LSSL_ALIAS(SSL_get_verify_mode); + +int +SSL_get_verify_depth(const SSL *s) +{ + return (X509_VERIFY_PARAM_get_depth(s->param)); +} +LSSL_ALIAS(SSL_get_verify_depth); + +int +(*SSL_get_verify_callback(const SSL *s))(int, X509_STORE_CTX *) +{ + return (s->verify_callback); +} +LSSL_ALIAS(SSL_get_verify_callback); + +void +SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb) +{ + ctx->keylog_callback = cb; +} +LSSL_ALIAS(SSL_CTX_set_keylog_callback); + +SSL_CTX_keylog_cb_func +SSL_CTX_get_keylog_callback(const SSL_CTX *ctx) +{ + return (ctx->keylog_callback); +} +LSSL_ALIAS(SSL_CTX_get_keylog_callback); + +int +SSL_set_num_tickets(SSL *s, size_t num_tickets) +{ + s->num_tickets = num_tickets; + + return 1; +} +LSSL_ALIAS(SSL_set_num_tickets); + +size_t +SSL_get_num_tickets(const SSL *s) +{ + return s->num_tickets; +} +LSSL_ALIAS(SSL_get_num_tickets); + +int +SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets) +{ + ctx->num_tickets = num_tickets; + + return 1; +} +LSSL_ALIAS(SSL_CTX_set_num_tickets); + +size_t +SSL_CTX_get_num_tickets(const SSL_CTX *ctx) +{ + return ctx->num_tickets; +} +LSSL_ALIAS(SSL_CTX_get_num_tickets); + +int +SSL_CTX_get_verify_mode(const SSL_CTX *ctx) +{ + return (ctx->verify_mode); +} +LSSL_ALIAS(SSL_CTX_get_verify_mode); + +int +SSL_CTX_get_verify_depth(const SSL_CTX *ctx) +{ + return (X509_VERIFY_PARAM_get_depth(ctx->param)); +} +LSSL_ALIAS(SSL_CTX_get_verify_depth); + +int +(*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(int, X509_STORE_CTX *) +{ + return (ctx->default_verify_callback); +} +LSSL_ALIAS(SSL_CTX_get_verify_callback); + +void +SSL_set_verify(SSL *s, int mode, + int (*callback)(int ok, X509_STORE_CTX *ctx)) +{ + s->verify_mode = mode; + if (callback != NULL) + s->verify_callback = callback; +} +LSSL_ALIAS(SSL_set_verify); + +void +SSL_set_verify_depth(SSL *s, int depth) +{ + X509_VERIFY_PARAM_set_depth(s->param, depth); +} +LSSL_ALIAS(SSL_set_verify_depth); + +void +SSL_set_read_ahead(SSL *s, int yes) +{ + s->read_ahead = yes; +} +LSSL_ALIAS(SSL_set_read_ahead); + +int +SSL_get_read_ahead(const SSL *s) +{ + return (s->read_ahead); +} +LSSL_ALIAS(SSL_get_read_ahead); + +int +SSL_pending(const SSL *s) +{ + return (s->method->ssl_pending(s)); +} +LSSL_ALIAS(SSL_pending); + +X509 * +SSL_get_peer_certificate(const SSL *s) +{ + X509 *cert; + + if (s == NULL || s->session == NULL) + return NULL; + + if ((cert = s->session->peer_cert) == NULL) + return NULL; + + X509_up_ref(cert); + + return cert; +} +LSSL_ALIAS(SSL_get_peer_certificate); + +STACK_OF(X509) * +SSL_get_peer_cert_chain(const SSL *s) +{ + if (s == NULL) + return NULL; + + /* + * Achtung! Due to API inconsistency, a client includes the peer's leaf + * certificate in the peer certificate chain, while a server does not. + */ + if (!s->server) + return s->s3->hs.peer_certs; + + return s->s3->hs.peer_certs_no_leaf; +} +LSSL_ALIAS(SSL_get_peer_cert_chain); + +STACK_OF(X509) * +SSL_get0_verified_chain(const SSL *s) +{ + if (s->s3 == NULL) + return NULL; + return s->s3->hs.verified_chain; +} +LSSL_ALIAS(SSL_get0_verified_chain); + +/* + * Now in theory, since the calling process own 't' it should be safe to + * modify. We need to be able to read f without being hassled + */ +int +SSL_copy_session_id(SSL *t, const SSL *f) +{ + SSL_CERT *tmp; + + /* Do we need to do SSL locking? */ + if (!SSL_set_session(t, SSL_get_session(f))) + return 0; + + /* What if we are set up for one protocol but want to talk another? */ + if (t->method != f->method) { + t->method->ssl_free(t); + t->method = f->method; + if (!t->method->ssl_new(t)) + return 0; + } + + tmp = t->cert; + if (f->cert != NULL) { + CRYPTO_add(&f->cert->references, 1, CRYPTO_LOCK_SSL_CERT); + t->cert = f->cert; + } else + t->cert = NULL; + ssl_cert_free(tmp); + + if (!SSL_set_session_id_context(t, f->sid_ctx, f->sid_ctx_length)) + return 0; + + return 1; +} +LSSL_ALIAS(SSL_copy_session_id); + +/* Fix this so it checks all the valid key/cert options */ +int +SSL_CTX_check_private_key(const SSL_CTX *ctx) +{ + if ((ctx == NULL) || (ctx->cert == NULL) || + (ctx->cert->key->x509 == NULL)) { + SSLerrorx(SSL_R_NO_CERTIFICATE_ASSIGNED); + return (0); + } + if (ctx->cert->key->privatekey == NULL) { + SSLerrorx(SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return (0); + } + return (X509_check_private_key(ctx->cert->key->x509, + ctx->cert->key->privatekey)); +} +LSSL_ALIAS(SSL_CTX_check_private_key); + +/* Fix this function so that it takes an optional type parameter */ +int +SSL_check_private_key(const SSL *ssl) +{ + if (ssl == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + if (ssl->cert == NULL) { + SSLerror(ssl, SSL_R_NO_CERTIFICATE_ASSIGNED); + return (0); + } + if (ssl->cert->key->x509 == NULL) { + SSLerror(ssl, SSL_R_NO_CERTIFICATE_ASSIGNED); + return (0); + } + if (ssl->cert->key->privatekey == NULL) { + SSLerror(ssl, SSL_R_NO_PRIVATE_KEY_ASSIGNED); + return (0); + } + return (X509_check_private_key(ssl->cert->key->x509, + ssl->cert->key->privatekey)); +} +LSSL_ALIAS(SSL_check_private_key); + +int +SSL_accept(SSL *s) +{ + if (s->handshake_func == NULL) + SSL_set_accept_state(s); /* Not properly initialized yet */ + + return (s->method->ssl_accept(s)); +} +LSSL_ALIAS(SSL_accept); + +int +SSL_connect(SSL *s) +{ + if (s->handshake_func == NULL) + SSL_set_connect_state(s); /* Not properly initialized yet */ + + return (s->method->ssl_connect(s)); +} +LSSL_ALIAS(SSL_connect); + +int +SSL_is_dtls(const SSL *s) +{ + return s->method->dtls; +} +LSSL_ALIAS(SSL_is_dtls); + +int +SSL_is_server(const SSL *s) +{ + return s->server; +} +LSSL_ALIAS(SSL_is_server); + +static long +ssl_get_default_timeout() +{ + /* + * 2 hours, the 24 hours mentioned in the TLSv1 spec + * is way too long for http, the cache would over fill. + */ + return (2 * 60 * 60); +} + +long +SSL_get_default_timeout(const SSL *s) +{ + return (ssl_get_default_timeout()); +} +LSSL_ALIAS(SSL_get_default_timeout); + +int +SSL_read(SSL *s, void *buf, int num) +{ + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + + if (SSL_is_quic(s)) { + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (-1); + } + + if (s->handshake_func == NULL) { + SSLerror(s, SSL_R_UNINITIALIZED); + return (-1); + } + + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + return (0); + } + return ssl3_read(s, buf, num); +} +LSSL_ALIAS(SSL_read); + +int +SSL_read_ex(SSL *s, void *buf, size_t num, size_t *bytes_read) +{ + int ret; + + /* We simply don't bother supporting enormous reads */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + ret = SSL_read(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_read = ret; + + return ret > 0; +} +LSSL_ALIAS(SSL_read_ex); + +int +SSL_peek(SSL *s, void *buf, int num) +{ + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + + if (SSL_is_quic(s)) { + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (-1); + } + + if (s->handshake_func == NULL) { + SSLerror(s, SSL_R_UNINITIALIZED); + return (-1); + } + + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + return (0); + } + return ssl3_peek(s, buf, num); +} +LSSL_ALIAS(SSL_peek); + +int +SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *bytes_peeked) +{ + int ret; + + /* We simply don't bother supporting enormous peeks */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + ret = SSL_peek(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_peeked = ret; + + return ret > 0; +} +LSSL_ALIAS(SSL_peek_ex); + +int +SSL_write(SSL *s, const void *buf, int num) +{ + if (num < 0) { + SSLerror(s, SSL_R_BAD_LENGTH); + return -1; + } + + if (SSL_is_quic(s)) { + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (-1); + } + + if (s->handshake_func == NULL) { + SSLerror(s, SSL_R_UNINITIALIZED); + return (-1); + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + SSLerror(s, SSL_R_PROTOCOL_IS_SHUTDOWN); + return (-1); + } + return ssl3_write(s, buf, num); +} +LSSL_ALIAS(SSL_write); + +int +SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *bytes_written) +{ + int ret; + + /* We simply don't bother supporting enormous writes */ + if (num > INT_MAX) { + SSLerror(s, SSL_R_BAD_LENGTH); + return 0; + } + + if (num == 0) { + /* This API is special */ + bytes_written = 0; + return 1; + } + + ret = SSL_write(s, buf, (int)num); + if (ret < 0) + ret = 0; + *bytes_written = ret; + + return ret > 0; +} +LSSL_ALIAS(SSL_write_ex); + +uint32_t +SSL_CTX_get_max_early_data(const SSL_CTX *ctx) +{ + return 0; +} +LSSL_ALIAS(SSL_CTX_get_max_early_data); + +int +SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data) +{ + return 1; +} +LSSL_ALIAS(SSL_CTX_set_max_early_data); + +uint32_t +SSL_get_max_early_data(const SSL *s) +{ + return 0; +} +LSSL_ALIAS(SSL_get_max_early_data); + +int +SSL_set_max_early_data(SSL *s, uint32_t max_early_data) +{ + return 1; +} +LSSL_ALIAS(SSL_set_max_early_data); + +int +SSL_get_early_data_status(const SSL *s) +{ + return SSL_EARLY_DATA_REJECTED; +} +LSSL_ALIAS(SSL_get_early_data_status); + +int +SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes) +{ + *readbytes = 0; + + if (!s->server) { + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return SSL_READ_EARLY_DATA_ERROR; + } + + return SSL_READ_EARLY_DATA_FINISH; +} +LSSL_ALIAS(SSL_read_early_data); + +int +SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written) +{ + *written = 0; + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; +} +LSSL_ALIAS(SSL_write_early_data); + +int +SSL_shutdown(SSL *s) +{ + /* + * Note that this function behaves differently from what one might + * expect. Return values are 0 for no success (yet), + * 1 for success; but calling it once is usually not enough, + * even if blocking I/O is used (see ssl3_shutdown). + */ + + if (s->handshake_func == NULL) { + SSLerror(s, SSL_R_UNINITIALIZED); + return (-1); + } + + if (s != NULL && !SSL_in_init(s)) + return (s->method->ssl_shutdown(s)); + + return (1); +} +LSSL_ALIAS(SSL_shutdown); + +int +SSL_renegotiate(SSL *s) +{ + if (s->renegotiate == 0) + s->renegotiate = 1; + + s->new_session = 1; + + return (s->method->ssl_renegotiate(s)); +} +LSSL_ALIAS(SSL_renegotiate); + +int +SSL_renegotiate_abbreviated(SSL *s) +{ + if (s->renegotiate == 0) + s->renegotiate = 1; + + s->new_session = 0; + + return (s->method->ssl_renegotiate(s)); +} +LSSL_ALIAS(SSL_renegotiate_abbreviated); + +int +SSL_renegotiate_pending(SSL *s) +{ + /* + * Becomes true when negotiation is requested; + * false again once a handshake has finished. + */ + return (s->renegotiate != 0); +} +LSSL_ALIAS(SSL_renegotiate_pending); + +long +SSL_ctrl(SSL *s, int cmd, long larg, void *parg) +{ + long l; + + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return (s->read_ahead); + case SSL_CTRL_SET_READ_AHEAD: + l = s->read_ahead; + s->read_ahead = larg; + return (l); + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + s->msg_callback_arg = parg; + return (1); + + case SSL_CTRL_OPTIONS: + return (s->options|=larg); + case SSL_CTRL_CLEAR_OPTIONS: + return (s->options&=~larg); + case SSL_CTRL_MODE: + return (s->mode|=larg); + case SSL_CTRL_CLEAR_MODE: + return (s->mode &=~larg); + case SSL_CTRL_GET_MAX_CERT_LIST: + return (s->max_cert_list); + case SSL_CTRL_SET_MAX_CERT_LIST: + l = s->max_cert_list; + s->max_cert_list = larg; + return (l); + case SSL_CTRL_SET_MTU: +#ifndef OPENSSL_NO_DTLS1 + if (larg < (long)dtls1_min_mtu()) + return (0); +#endif + if (SSL_is_dtls(s)) { + s->d1->mtu = larg; + return (larg); + } + return (0); + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) + return (0); + s->max_send_fragment = larg; + return (1); + case SSL_CTRL_GET_RI_SUPPORT: + if (s->s3) + return (s->s3->send_connection_binding); + else return (0); + default: + if (SSL_is_dtls(s)) + return dtls1_ctrl(s, cmd, larg, parg); + return ssl3_ctrl(s, cmd, larg, parg); + } +} +LSSL_ALIAS(SSL_ctrl); + +long +SSL_callback_ctrl(SSL *s, int cmd, void (*fp)(void)) +{ + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + s->msg_callback = (ssl_msg_callback_fn *)(fp); + return (1); + + default: + return (ssl3_callback_ctrl(s, cmd, fp)); + } +} +LSSL_ALIAS(SSL_callback_ctrl); + +struct lhash_st_SSL_SESSION * +SSL_CTX_sessions(SSL_CTX *ctx) +{ + return (ctx->sessions); +} +LSSL_ALIAS(SSL_CTX_sessions); + +long +SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg) +{ + long l; + + switch (cmd) { + case SSL_CTRL_GET_READ_AHEAD: + return (ctx->read_ahead); + case SSL_CTRL_SET_READ_AHEAD: + l = ctx->read_ahead; + ctx->read_ahead = larg; + return (l); + + case SSL_CTRL_SET_MSG_CALLBACK_ARG: + ctx->msg_callback_arg = parg; + return (1); + + case SSL_CTRL_GET_MAX_CERT_LIST: + return (ctx->max_cert_list); + case SSL_CTRL_SET_MAX_CERT_LIST: + l = ctx->max_cert_list; + ctx->max_cert_list = larg; + return (l); + + case SSL_CTRL_SET_SESS_CACHE_SIZE: + l = ctx->session_cache_size; + ctx->session_cache_size = larg; + return (l); + case SSL_CTRL_GET_SESS_CACHE_SIZE: + return (ctx->session_cache_size); + case SSL_CTRL_SET_SESS_CACHE_MODE: + l = ctx->session_cache_mode; + ctx->session_cache_mode = larg; + return (l); + case SSL_CTRL_GET_SESS_CACHE_MODE: + return (ctx->session_cache_mode); + + case SSL_CTRL_SESS_NUMBER: + return (lh_SSL_SESSION_num_items(ctx->sessions)); + case SSL_CTRL_SESS_CONNECT: + return (ctx->stats.sess_connect); + case SSL_CTRL_SESS_CONNECT_GOOD: + return (ctx->stats.sess_connect_good); + case SSL_CTRL_SESS_CONNECT_RENEGOTIATE: + return (ctx->stats.sess_connect_renegotiate); + case SSL_CTRL_SESS_ACCEPT: + return (ctx->stats.sess_accept); + case SSL_CTRL_SESS_ACCEPT_GOOD: + return (ctx->stats.sess_accept_good); + case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE: + return (ctx->stats.sess_accept_renegotiate); + case SSL_CTRL_SESS_HIT: + return (ctx->stats.sess_hit); + case SSL_CTRL_SESS_CB_HIT: + return (ctx->stats.sess_cb_hit); + case SSL_CTRL_SESS_MISSES: + return (ctx->stats.sess_miss); + case SSL_CTRL_SESS_TIMEOUTS: + return (ctx->stats.sess_timeout); + case SSL_CTRL_SESS_CACHE_FULL: + return (ctx->stats.sess_cache_full); + case SSL_CTRL_OPTIONS: + return (ctx->options|=larg); + case SSL_CTRL_CLEAR_OPTIONS: + return (ctx->options&=~larg); + case SSL_CTRL_MODE: + return (ctx->mode|=larg); + case SSL_CTRL_CLEAR_MODE: + return (ctx->mode&=~larg); + case SSL_CTRL_SET_MAX_SEND_FRAGMENT: + if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH) + return (0); + ctx->max_send_fragment = larg; + return (1); + default: + return (ssl3_ctx_ctrl(ctx, cmd, larg, parg)); + } +} +LSSL_ALIAS(SSL_CTX_ctrl); + +long +SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) +{ + switch (cmd) { + case SSL_CTRL_SET_MSG_CALLBACK: + ctx->msg_callback = (ssl_msg_callback_fn *)fp; + return (1); + + default: + return (ssl3_ctx_callback_ctrl(ctx, cmd, fp)); + } +} +LSSL_ALIAS(SSL_CTX_callback_ctrl); + +int +ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b) +{ + long l; + + l = a->id - b->id; + if (l == 0L) + return (0); + else + return ((l > 0) ? 1:-1); +} + +STACK_OF(SSL_CIPHER) * +SSL_get_ciphers(const SSL *s) +{ + if (s == NULL) + return (NULL); + if (s->cipher_list != NULL) + return (s->cipher_list); + + return (s->ctx->cipher_list); +} +LSSL_ALIAS(SSL_get_ciphers); + +STACK_OF(SSL_CIPHER) * +SSL_get_client_ciphers(const SSL *s) +{ + if (s == NULL || s->session == NULL || !s->server) + return NULL; + return s->session->ciphers; +} +LSSL_ALIAS(SSL_get_client_ciphers); + +STACK_OF(SSL_CIPHER) * +SSL_get1_supported_ciphers(SSL *s) +{ + STACK_OF(SSL_CIPHER) *supported_ciphers = NULL, *ciphers; + SSL_CIPHER *cipher; + uint16_t min_vers, max_vers; + int i; + + if (s == NULL) + return NULL; + if (!ssl_supported_tls_version_range(s, &min_vers, &max_vers)) + return NULL; + if ((ciphers = SSL_get_ciphers(s)) == NULL) + return NULL; + if ((supported_ciphers = sk_SSL_CIPHER_new_null()) == NULL) + return NULL; + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + if ((cipher = sk_SSL_CIPHER_value(ciphers, i)) == NULL) + goto err; + if (!ssl_cipher_allowed_in_tls_version_range(cipher, min_vers, + max_vers)) + continue; + if (!ssl_security_supported_cipher(s, cipher)) + continue; + if (!sk_SSL_CIPHER_push(supported_ciphers, cipher)) + goto err; + } + + if (sk_SSL_CIPHER_num(supported_ciphers) > 0) + return supported_ciphers; + + err: + sk_SSL_CIPHER_free(supported_ciphers); + return NULL; +} +LSSL_ALIAS(SSL_get1_supported_ciphers); + +/* See if we have any ECC cipher suites. */ +int +ssl_has_ecc_ciphers(SSL *s) +{ + STACK_OF(SSL_CIPHER) *ciphers; + unsigned long alg_k, alg_a; + SSL_CIPHER *cipher; + int i; + + if ((ciphers = SSL_get_ciphers(s)) == NULL) + return 0; + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + cipher = sk_SSL_CIPHER_value(ciphers, i); + + alg_k = cipher->algorithm_mkey; + alg_a = cipher->algorithm_auth; + + if ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) + return 1; + } + + return 0; +} + +/* The old interface to get the same thing as SSL_get_ciphers(). */ +const char * +SSL_get_cipher_list(const SSL *s, int n) +{ + STACK_OF(SSL_CIPHER) *ciphers; + const SSL_CIPHER *cipher; + + if ((ciphers = SSL_get_ciphers(s)) == NULL) + return (NULL); + if ((cipher = sk_SSL_CIPHER_value(ciphers, n)) == NULL) + return (NULL); + + return (cipher->name); +} +LSSL_ALIAS(SSL_get_cipher_list); + +STACK_OF(SSL_CIPHER) * +SSL_CTX_get_ciphers(const SSL_CTX *ctx) +{ + if (ctx == NULL) + return NULL; + return ctx->cipher_list; +} +LSSL_ALIAS(SSL_CTX_get_ciphers); + +/* Specify the ciphers to be used by default by the SSL_CTX. */ +int +SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) +{ + STACK_OF(SSL_CIPHER) *ciphers; + + /* + * ssl_create_cipher_list may return an empty stack if it was unable to + * find a cipher matching the given rule string (for example if the + * rule string specifies a cipher which has been disabled). This is not + * an error as far as ssl_create_cipher_list is concerned, and hence + * ctx->cipher_list has been updated. + */ + ciphers = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, + ctx->cipher_list_tls13, str, ctx->cert); + if (ciphers == NULL) { + return (0); + } else if (sk_SSL_CIPHER_num(ciphers) == 0) { + SSLerrorx(SSL_R_NO_CIPHER_MATCH); + return (0); + } + return (1); +} +LSSL_ALIAS(SSL_CTX_set_cipher_list); + +int +SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) +{ + if (!ssl_parse_ciphersuites(&ctx->cipher_list_tls13, str)) { + SSLerrorx(SSL_R_NO_CIPHER_MATCH); + return 0; + } + if (!ssl_merge_cipherlists(ctx->cipher_list, + ctx->cipher_list_tls13, &ctx->cipher_list)) + return 0; + + return 1; +} +LSSL_ALIAS(SSL_CTX_set_ciphersuites); + +/* Specify the ciphers to be used by the SSL. */ +int +SSL_set_cipher_list(SSL *s, const char *str) +{ + STACK_OF(SSL_CIPHER) *ciphers, *ciphers_tls13; + + if ((ciphers_tls13 = s->cipher_list_tls13) == NULL) + ciphers_tls13 = s->ctx->cipher_list_tls13; + + /* See comment in SSL_CTX_set_cipher_list. */ + ciphers = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, + ciphers_tls13, str, s->cert); + if (ciphers == NULL) { + return (0); + } else if (sk_SSL_CIPHER_num(ciphers) == 0) { + SSLerror(s, SSL_R_NO_CIPHER_MATCH); + return (0); + } + return (1); +} +LSSL_ALIAS(SSL_set_cipher_list); + +int +SSL_set_ciphersuites(SSL *s, const char *str) +{ + STACK_OF(SSL_CIPHER) *ciphers; + + if ((ciphers = s->cipher_list) == NULL) + ciphers = s->ctx->cipher_list; + + if (!ssl_parse_ciphersuites(&s->cipher_list_tls13, str)) { + SSLerrorx(SSL_R_NO_CIPHER_MATCH); + return (0); + } + if (!ssl_merge_cipherlists(ciphers, s->cipher_list_tls13, + &s->cipher_list)) + return 0; + + return 1; +} +LSSL_ALIAS(SSL_set_ciphersuites); + +char * +SSL_get_shared_ciphers(const SSL *s, char *buf, int len) +{ + STACK_OF(SSL_CIPHER) *client_ciphers, *server_ciphers; + const SSL_CIPHER *cipher; + size_t curlen = 0; + char *end; + int i; + + if (!s->server || s->session == NULL || len < 2) + return NULL; + + if ((client_ciphers = s->session->ciphers) == NULL) + return NULL; + if ((server_ciphers = SSL_get_ciphers(s)) == NULL) + return NULL; + if (sk_SSL_CIPHER_num(client_ciphers) == 0 || + sk_SSL_CIPHER_num(server_ciphers) == 0) + return NULL; + + buf[0] = '\0'; + for (i = 0; i < sk_SSL_CIPHER_num(client_ciphers); i++) { + cipher = sk_SSL_CIPHER_value(client_ciphers, i); + + if (sk_SSL_CIPHER_find(server_ciphers, cipher) < 0) + continue; + + end = buf + curlen; + if (strlcat(buf, cipher->name, len) >= len || + (curlen = strlcat(buf, ":", len)) >= len) { + /* remove truncated cipher from list */ + *end = '\0'; + break; + } + } + /* remove trailing colon */ + if ((end = strrchr(buf, ':')) != NULL) + *end = '\0'; + return buf; +} +LSSL_ALIAS(SSL_get_shared_ciphers); + +/* + * Return a servername extension value if provided in Client Hello, or NULL. + * So far, only host_name types are defined (RFC 3546). + */ +const char * +SSL_get_servername(const SSL *s, const int type) +{ + if (type != TLSEXT_NAMETYPE_host_name) + return (NULL); + + return (s->session && !s->tlsext_hostname ? + s->session->tlsext_hostname : + s->tlsext_hostname); +} +LSSL_ALIAS(SSL_get_servername); + +int +SSL_get_servername_type(const SSL *s) +{ + if (s->session && + (!s->tlsext_hostname ? + s->session->tlsext_hostname : s->tlsext_hostname)) + return (TLSEXT_NAMETYPE_host_name); + return (-1); +} +LSSL_ALIAS(SSL_get_servername_type); + +/* + * SSL_select_next_proto implements standard protocol selection. It is + * expected that this function is called from the callback set by + * SSL_CTX_set_alpn_select_cb. + * + * The protocol data is assumed to be a vector of 8-bit, length prefixed byte + * strings. The length byte itself is not included in the length. A byte + * string of length 0 is invalid. No byte string may be truncated. + * + * It returns either: + * OPENSSL_NPN_NEGOTIATED if a common protocol was found, or + * OPENSSL_NPN_NO_OVERLAP if the fallback case was reached. + */ +int +SSL_select_next_proto(unsigned char **out, unsigned char *outlen, + const unsigned char *server, unsigned int server_len, + const unsigned char *client, unsigned int client_len) +{ + unsigned int i, j; + const unsigned char *result; + int status = OPENSSL_NPN_UNSUPPORTED; + + /* + * For each protocol in server preference order, + * see if we support it. + */ + for (i = 0; i < server_len; ) { + for (j = 0; j < client_len; ) { + if (server[i] == client[j] && + memcmp(&server[i + 1], + &client[j + 1], server[i]) == 0) { + /* We found a match */ + result = &server[i]; + status = OPENSSL_NPN_NEGOTIATED; + goto found; + } + j += client[j]; + j++; + } + i += server[i]; + i++; + } + + /* There's no overlap between our protocols and the server's list. */ + result = client; + status = OPENSSL_NPN_NO_OVERLAP; + + found: + *out = (unsigned char *) result + 1; + *outlen = result[0]; + return (status); +} +LSSL_ALIAS(SSL_select_next_proto); + +/* SSL_get0_next_proto_negotiated is deprecated. */ +void +SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, + unsigned int *len) +{ + *data = NULL; + *len = 0; +} +LSSL_ALIAS(SSL_get0_next_proto_negotiated); + +/* SSL_CTX_set_next_protos_advertised_cb is deprecated. */ +void +SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *ctx, int (*cb) (SSL *ssl, + const unsigned char **out, unsigned int *outlen, void *arg), void *arg) +{ +} +LSSL_ALIAS(SSL_CTX_set_next_protos_advertised_cb); + +/* SSL_CTX_set_next_proto_select_cb is deprecated. */ +void +SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, + unsigned char **out, unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg), void *arg) +{ +} +LSSL_ALIAS(SSL_CTX_set_next_proto_select_cb); + +/* + * SSL_CTX_set_alpn_protos sets the ALPN protocol list to the specified + * protocols, which must be in wire-format (i.e. a series of non-empty, + * 8-bit length-prefixed strings). Returns 0 on success. + */ +int +SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos, + unsigned int protos_len) +{ + CBS cbs; + int failed = 1; + + if (protos == NULL) + protos_len = 0; + + CBS_init(&cbs, protos, protos_len); + + if (protos_len > 0) { + if (!tlsext_alpn_check_format(&cbs)) + goto err; + } + + if (!CBS_stow(&cbs, &ctx->alpn_client_proto_list, + &ctx->alpn_client_proto_list_len)) + goto err; + + failed = 0; + + err: + /* NOTE: Return values are the reverse of what you expect. */ + return failed; +} +LSSL_ALIAS(SSL_CTX_set_alpn_protos); + +/* + * SSL_set_alpn_protos sets the ALPN protocol list to the specified + * protocols, which must be in wire-format (i.e. a series of non-empty, + * 8-bit length-prefixed strings). Returns 0 on success. + */ +int +SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned int protos_len) +{ + CBS cbs; + int failed = 1; + + if (protos == NULL) + protos_len = 0; + + CBS_init(&cbs, protos, protos_len); + + if (protos_len > 0) { + if (!tlsext_alpn_check_format(&cbs)) + goto err; + } + + if (!CBS_stow(&cbs, &ssl->alpn_client_proto_list, + &ssl->alpn_client_proto_list_len)) + goto err; + + failed = 0; + + err: + /* NOTE: Return values are the reverse of what you expect. */ + return failed; +} +LSSL_ALIAS(SSL_set_alpn_protos); + +/* + * SSL_CTX_set_alpn_select_cb sets a callback function that is called during + * ClientHello processing in order to select an ALPN protocol from the + * client's list of offered protocols. + */ +void +SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, + int (*cb) (SSL *ssl, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg), void *arg) +{ + ctx->alpn_select_cb = cb; + ctx->alpn_select_cb_arg = arg; +} +LSSL_ALIAS(SSL_CTX_set_alpn_select_cb); + +/* + * SSL_get0_alpn_selected gets the selected ALPN protocol (if any). On return + * it sets data to point to len bytes of protocol name (not including the + * leading length-prefix byte). If the server didn't respond with* a negotiated + * protocol then len will be zero. + */ +void +SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned int *len) +{ + *data = ssl->s3->alpn_selected; + *len = ssl->s3->alpn_selected_len; +} +LSSL_ALIAS(SSL_get0_alpn_selected); + +void +SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb) +{ + return; +} +LSSL_ALIAS(SSL_set_psk_use_session_callback); + +int +SSL_export_keying_material(SSL *s, unsigned char *out, size_t out_len, + const char *label, size_t label_len, const unsigned char *context, + size_t context_len, int use_context) +{ + if (s->tls13 != NULL && s->version == TLS1_3_VERSION) { + if (!use_context) { + context = NULL; + context_len = 0; + } + return tls13_exporter(s->tls13, label, label_len, context, + context_len, out, out_len); + } + + return tls12_exporter(s, label, label_len, context, context_len, + use_context, out, out_len); +} +LSSL_ALIAS(SSL_export_keying_material); + +static unsigned long +ssl_session_hash(const SSL_SESSION *a) +{ + unsigned long l; + + l = (unsigned long) + ((unsigned int) a->session_id[0] )| + ((unsigned int) a->session_id[1]<< 8L)| + ((unsigned long)a->session_id[2]<<16L)| + ((unsigned long)a->session_id[3]<<24L); + return (l); +} + +/* + * NB: If this function (or indeed the hash function which uses a sort of + * coarser function than this one) is changed, ensure + * SSL_CTX_has_matching_session_id() is checked accordingly. It relies on being + * able to construct an SSL_SESSION that will collide with any existing session + * with a matching session ID. + */ +static int +ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b) +{ + if (a->ssl_version != b->ssl_version) + return (1); + if (a->session_id_length != b->session_id_length) + return (1); + if (timingsafe_memcmp(a->session_id, b->session_id, a->session_id_length) != 0) + return (1); + return (0); +} + +/* + * These wrapper functions should remain rather than redeclaring + * SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each + * variable. The reason is that the functions aren't static, they're exposed via + * ssl.h. + */ +static unsigned long +ssl_session_LHASH_HASH(const void *arg) +{ + const SSL_SESSION *a = arg; + + return ssl_session_hash(a); +} + +static int +ssl_session_LHASH_COMP(const void *arg1, const void *arg2) +{ + const SSL_SESSION *a = arg1; + const SSL_SESSION *b = arg2; + + return ssl_session_cmp(a, b); +} + +SSL_CTX * +SSL_CTX_new(const SSL_METHOD *meth) +{ + SSL_CTX *ret; + + if (!OPENSSL_init_ssl(0, NULL)) { + SSLerrorx(SSL_R_LIBRARY_BUG); + return (NULL); + } + + if (meth == NULL) { + SSLerrorx(SSL_R_NULL_SSL_METHOD_PASSED); + return (NULL); + } + + if ((ret = calloc(1, sizeof(*ret))) == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); + } + + if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) { + SSLerrorx(SSL_R_X509_VERIFICATION_SETUP_PROBLEMS); + goto err; + } + + ret->method = meth; + ret->min_tls_version = meth->min_tls_version; + ret->max_tls_version = meth->max_tls_version; + ret->min_proto_version = 0; + ret->max_proto_version = 0; + ret->mode = SSL_MODE_AUTO_RETRY; + + ret->cert_store = NULL; + ret->session_cache_mode = SSL_SESS_CACHE_SERVER; + ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT; + ret->session_cache_head = NULL; + ret->session_cache_tail = NULL; + + /* We take the system default */ + ret->session_timeout = ssl_get_default_timeout(); + + ret->new_session_cb = NULL; + ret->remove_session_cb = NULL; + ret->get_session_cb = NULL; + ret->generate_session_id = NULL; + + memset((char *)&ret->stats, 0, sizeof(ret->stats)); + + ret->references = 1; + ret->quiet_shutdown = 0; + + ret->info_callback = NULL; + + ret->app_verify_callback = NULL; + ret->app_verify_arg = NULL; + + ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT; + ret->read_ahead = 0; + ret->msg_callback = NULL; + ret->msg_callback_arg = NULL; + ret->verify_mode = SSL_VERIFY_NONE; + ret->sid_ctx_length = 0; + ret->default_verify_callback = NULL; + + if ((ret->cert = ssl_cert_new()) == NULL) + goto err; + + ret->default_passwd_callback = NULL; + ret->default_passwd_callback_userdata = NULL; + ret->client_cert_cb = NULL; + ret->app_gen_cookie_cb = NULL; + ret->app_verify_cookie_cb = NULL; + + ret->sessions = lh_SSL_SESSION_new(); + if (ret->sessions == NULL) + goto err; + ret->cert_store = X509_STORE_new(); + if (ret->cert_store == NULL) + goto err; + + ssl_create_cipher_list(ret->method, &ret->cipher_list, + NULL, SSL_DEFAULT_CIPHER_LIST, ret->cert); + if (ret->cipher_list == NULL || + sk_SSL_CIPHER_num(ret->cipher_list) <= 0) { + SSLerrorx(SSL_R_LIBRARY_HAS_NO_CIPHERS); + goto err2; + } + + ret->param = X509_VERIFY_PARAM_new(); + if (!ret->param) + goto err; + + if ((ret->client_CA = sk_X509_NAME_new_null()) == NULL) + goto err; + + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data); + + ret->extra_certs = NULL; + + ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH; + + ret->tlsext_servername_callback = 0; + ret->tlsext_servername_arg = NULL; + + /* Setup RFC4507 ticket keys */ + arc4random_buf(ret->tlsext_tick_key_name, 16); + arc4random_buf(ret->tlsext_tick_hmac_key, 16); + arc4random_buf(ret->tlsext_tick_aes_key, 16); + + ret->tlsext_status_cb = 0; + ret->tlsext_status_arg = NULL; + +#ifndef OPENSSL_NO_ENGINE + ret->client_cert_engine = NULL; +#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO +#define eng_strx(x) #x +#define eng_str(x) eng_strx(x) + /* Use specific client engine automatically... ignore errors */ + { + ENGINE *eng; + eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + if (!eng) { + ERR_clear_error(); + ENGINE_load_builtin_engines(); + eng = ENGINE_by_id(eng_str( + OPENSSL_SSL_CLIENT_ENGINE_AUTO)); + } + if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng)) + ERR_clear_error(); + } +#endif +#endif + /* + * Default is to connect to non-RI servers. When RI is more widely + * deployed might change this. + */ + ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + + return (ret); + err: + SSLerrorx(ERR_R_MALLOC_FAILURE); + err2: + SSL_CTX_free(ret); + return (NULL); +} +LSSL_ALIAS(SSL_CTX_new); + +void +SSL_CTX_free(SSL_CTX *ctx) +{ + int i; + + if (ctx == NULL) + return; + + i = CRYPTO_add(&ctx->references, -1, CRYPTO_LOCK_SSL_CTX); + if (i > 0) + return; + + X509_VERIFY_PARAM_free(ctx->param); + + /* + * Free internal session cache. However: the remove_cb() may reference + * the ex_data of SSL_CTX, thus the ex_data store can only be removed + * after the sessions were flushed. + * As the ex_data handling routines might also touch the session cache, + * the most secure solution seems to be: empty (flush) the cache, then + * free ex_data, then finally free the cache. + * (See ticket [openssl.org #212].) + */ + if (ctx->sessions != NULL) + SSL_CTX_flush_sessions(ctx, 0); + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ctx, &ctx->ex_data); + + lh_SSL_SESSION_free(ctx->sessions); + + X509_STORE_free(ctx->cert_store); + sk_SSL_CIPHER_free(ctx->cipher_list); + sk_SSL_CIPHER_free(ctx->cipher_list_tls13); + ssl_cert_free(ctx->cert); + sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free); + sk_X509_pop_free(ctx->extra_certs, X509_free); + +#ifndef OPENSSL_NO_SRTP + if (ctx->srtp_profiles) + sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles); +#endif + +#ifndef OPENSSL_NO_ENGINE + ENGINE_finish(ctx->client_cert_engine); +#endif + + free(ctx->tlsext_ecpointformatlist); + free(ctx->tlsext_supportedgroups); + + free(ctx->alpn_client_proto_list); + + free(ctx); +} +LSSL_ALIAS(SSL_CTX_free); + +int +SSL_CTX_up_ref(SSL_CTX *ctx) +{ + int refs = CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX); + return ((refs > 1) ? 1 : 0); +} +LSSL_ALIAS(SSL_CTX_up_ref); + +pem_password_cb * +SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) +{ + return (ctx->default_passwd_callback); +} +LSSL_ALIAS(SSL_CTX_get_default_passwd_cb); + +void +SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) +{ + ctx->default_passwd_callback = cb; +} +LSSL_ALIAS(SSL_CTX_set_default_passwd_cb); + +void * +SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx) +{ + return ctx->default_passwd_callback_userdata; +} +LSSL_ALIAS(SSL_CTX_get_default_passwd_cb_userdata); + +void +SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u) +{ + ctx->default_passwd_callback_userdata = u; +} +LSSL_ALIAS(SSL_CTX_set_default_passwd_cb_userdata); + +void +SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx, + int (*cb)(X509_STORE_CTX *, void *), void *arg) +{ + ctx->app_verify_callback = cb; + ctx->app_verify_arg = arg; +} +LSSL_ALIAS(SSL_CTX_set_cert_verify_callback); + +void +SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*cb)(int, X509_STORE_CTX *)) +{ + ctx->verify_mode = mode; + ctx->default_verify_callback = cb; +} +LSSL_ALIAS(SSL_CTX_set_verify); + +void +SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) +{ + X509_VERIFY_PARAM_set_depth(ctx->param, depth); +} +LSSL_ALIAS(SSL_CTX_set_verify_depth); + +void +ssl_set_cert_masks(SSL_CERT *c, const SSL_CIPHER *cipher) +{ + unsigned long mask_a, mask_k; + SSL_CERT_PKEY *cpk; + + if (c == NULL) + return; + + mask_a = SSL_aNULL | SSL_aTLS1_3; + mask_k = SSL_kECDHE | SSL_kTLS1_3; + + if (c->dhe_params != NULL || c->dhe_params_cb != NULL || + c->dhe_params_auto != 0) + mask_k |= SSL_kDHE; + + cpk = &(c->pkeys[SSL_PKEY_ECC]); + if (cpk->x509 != NULL && cpk->privatekey != NULL) { + /* Key usage, if present, must allow signing. */ + if (X509_get_key_usage(cpk->x509) & X509v3_KU_DIGITAL_SIGNATURE) + mask_a |= SSL_aECDSA; + } + + cpk = &(c->pkeys[SSL_PKEY_GOST01]); + if (cpk->x509 != NULL && cpk->privatekey != NULL) { + mask_k |= SSL_kGOST; + mask_a |= SSL_aGOST01; + } + + cpk = &(c->pkeys[SSL_PKEY_RSA]); + if (cpk->x509 != NULL && cpk->privatekey != NULL) { + mask_a |= SSL_aRSA; + mask_k |= SSL_kRSA; + } + + c->mask_k = mask_k; + c->mask_a = mask_a; + c->valid = 1; +} + +/* See if this handshake is using an ECC cipher suite. */ +int +ssl_using_ecc_cipher(SSL *s) +{ + unsigned long alg_a, alg_k; + + alg_a = s->s3->hs.cipher->algorithm_auth; + alg_k = s->s3->hs.cipher->algorithm_mkey; + + return s->session->tlsext_ecpointformatlist != NULL && + s->session->tlsext_ecpointformatlist_length > 0 && + ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)); +} + +int +ssl_check_srvr_ecc_cert_and_alg(SSL *s, X509 *x) +{ + const SSL_CIPHER *cs = s->s3->hs.cipher; + unsigned long alg_a; + + alg_a = cs->algorithm_auth; + + if (alg_a & SSL_aECDSA) { + /* Key usage, if present, must allow signing. */ + if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) { + SSLerror(s, SSL_R_ECC_CERT_NOT_FOR_SIGNING); + return (0); + } + } + + return (1); +} + +SSL_CERT_PKEY * +ssl_get_server_send_pkey(const SSL *s) +{ + unsigned long alg_a; + SSL_CERT *c; + int i; + + c = s->cert; + ssl_set_cert_masks(c, s->s3->hs.cipher); + + alg_a = s->s3->hs.cipher->algorithm_auth; + + if (alg_a & SSL_aECDSA) { + i = SSL_PKEY_ECC; + } else if (alg_a & SSL_aRSA) { + i = SSL_PKEY_RSA; + } else if (alg_a & SSL_aGOST01) { + i = SSL_PKEY_GOST01; + } else { /* if (alg_a & SSL_aNULL) */ + SSLerror(s, ERR_R_INTERNAL_ERROR); + return (NULL); + } + + return (c->pkeys + i); +} + +EVP_PKEY * +ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *cipher, const EVP_MD **pmd, + const struct ssl_sigalg **sap) +{ + const struct ssl_sigalg *sigalg = NULL; + EVP_PKEY *pkey = NULL; + unsigned long alg_a; + SSL_CERT *c; + int idx = -1; + + alg_a = cipher->algorithm_auth; + c = s->cert; + + if (alg_a & SSL_aRSA) { + idx = SSL_PKEY_RSA; + } else if ((alg_a & SSL_aECDSA) && + (c->pkeys[SSL_PKEY_ECC].privatekey != NULL)) + idx = SSL_PKEY_ECC; + if (idx == -1) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return (NULL); + } + + pkey = c->pkeys[idx].privatekey; + if ((sigalg = ssl_sigalg_select(s, pkey)) == NULL) { + SSLerror(s, SSL_R_SIGNATURE_ALGORITHMS_ERROR); + return (NULL); + } + *pmd = sigalg->md(); + *sap = sigalg; + + return (pkey); +} + +size_t +ssl_dhe_params_auto_key_bits(SSL *s) +{ + SSL_CERT_PKEY *cpk; + int key_bits; + + if (s->cert->dhe_params_auto == 2) { + key_bits = 1024; + } else if (s->s3->hs.cipher->algorithm_auth & SSL_aNULL) { + key_bits = 1024; + if (s->s3->hs.cipher->strength_bits == 256) + key_bits = 3072; + } else { + if ((cpk = ssl_get_server_send_pkey(s)) == NULL) + return 0; + if (cpk->privatekey == NULL || + EVP_PKEY_get0_RSA(cpk->privatekey) == NULL) + return 0; + if ((key_bits = EVP_PKEY_bits(cpk->privatekey)) <= 0) + return 0; + } + + return key_bits; +} + +static int +ssl_should_update_external_cache(SSL *s, int mode) +{ + int cache_mode; + + cache_mode = s->session_ctx->session_cache_mode; + + /* Don't cache if mode says not to */ + if ((cache_mode & mode) == 0) + return 0; + + /* if it is not already cached, cache it */ + if (!s->hit) + return 1; + + /* If it's TLS 1.3, do it to match OpenSSL */ + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) + return 1; + + return 0; +} + +static int +ssl_should_update_internal_cache(SSL *s, int mode) +{ + int cache_mode; + + cache_mode = s->session_ctx->session_cache_mode; + + /* Don't cache if mode says not to */ + if ((cache_mode & mode) == 0) + return 0; + + /* If it is already cached, don't cache it again */ + if (s->hit) + return 0; + + if ((cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + return 0; + + /* If we are lesser than TLS 1.3, Cache it. */ + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION) + return 1; + + /* Below this we consider TLS 1.3 or later */ + + /* If it's not a server, add it? OpenSSL does this. */ + if (!s->server) + return 1; + + /* XXX if we support early data / PSK need to add */ + + /* + * If we have the remove session callback, we will want + * to know about this even if it's a stateless ticket + * from 1.3 so we can know when it is removed. + */ + if (s->session_ctx->remove_session_cb != NULL) + return 1; + + /* If we have set OP_NO_TICKET, cache it. */ + if ((s->options & SSL_OP_NO_TICKET) != 0) + return 1; + + /* Otherwise do not cache */ + return 0; +} + +void +ssl_update_cache(SSL *s, int mode) +{ + int cache_mode, do_callback; + + if (s->session->session_id_length == 0) + return; + + cache_mode = s->session_ctx->session_cache_mode; + do_callback = ssl_should_update_external_cache(s, mode); + + if (ssl_should_update_internal_cache(s, mode)) { + /* + * XXX should we fail if the add to the internal cache + * fails? OpenSSL doesn't care.. + */ + (void) SSL_CTX_add_session(s->session_ctx, s->session); + } + + /* + * Update the "external cache" by calling the new session + * callback if present, even with TLS 1.3 without early data + * "because some application just want to know about the + * creation of a session and aren't doing a full cache". + * Apparently, if they are doing a full cache, they'll have + * some fun, but we endeavour to give application writers the + * same glorious experience they expect from OpenSSL which + * does it this way. + */ + if (do_callback && s->session_ctx->new_session_cb != NULL) { + CRYPTO_add(&s->session->references, 1, CRYPTO_LOCK_SSL_SESSION); + if (!s->session_ctx->new_session_cb(s, s->session)) + SSL_SESSION_free(s->session); + } + + /* Auto flush every 255 connections. */ + if (!(cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) && + (cache_mode & mode) != 0) { + int connections; + if (mode & SSL_SESS_CACHE_CLIENT) + connections = s->session_ctx->stats.sess_connect_good; + else + connections = s->session_ctx->stats.sess_accept_good; + if ((connections & 0xff) == 0xff) + SSL_CTX_flush_sessions(s->session_ctx, time(NULL)); + } +} + +const SSL_METHOD * +SSL_get_ssl_method(SSL *s) +{ + return (s->method); +} +LSSL_ALIAS(SSL_get_ssl_method); + +int +SSL_set_ssl_method(SSL *s, const SSL_METHOD *method) +{ + int (*handshake_func)(SSL *) = NULL; + int ret = 1; + + if (s->method == method) + return (ret); + + if (s->handshake_func == s->method->ssl_connect) + handshake_func = method->ssl_connect; + else if (s->handshake_func == s->method->ssl_accept) + handshake_func = method->ssl_accept; + + if (s->method->version == method->version) { + s->method = method; + } else { + s->method->ssl_free(s); + s->method = method; + ret = s->method->ssl_new(s); + } + s->handshake_func = handshake_func; + + return (ret); +} +LSSL_ALIAS(SSL_set_ssl_method); + +int +SSL_get_error(const SSL *s, int i) +{ + unsigned long l; + int reason; + BIO *bio; + + if (i > 0) + return (SSL_ERROR_NONE); + + /* + * Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake + * etc, where we do encode the error. + */ + if ((l = ERR_peek_error()) != 0) { + if (ERR_GET_LIB(l) == ERR_LIB_SYS) + return (SSL_ERROR_SYSCALL); + else + return (SSL_ERROR_SSL); + } + + if (SSL_want_read(s)) { + bio = SSL_get_rbio(s); + if (BIO_should_read(bio)) { + return (SSL_ERROR_WANT_READ); + } else if (BIO_should_write(bio)) { + /* + * This one doesn't make too much sense... We never + * try to write to the rbio, and an application + * program where rbio and wbio are separate couldn't + * even know what it should wait for. However if we + * ever set s->rwstate incorrectly (so that we have + * SSL_want_read(s) instead of SSL_want_write(s)) + * and rbio and wbio *are* the same, this test works + * around that bug; so it might be safer to keep it. + */ + return (SSL_ERROR_WANT_WRITE); + } else if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return (SSL_ERROR_WANT_CONNECT); + else if (reason == BIO_RR_ACCEPT) + return (SSL_ERROR_WANT_ACCEPT); + else + return (SSL_ERROR_SYSCALL); /* unknown */ + } + } + + if (SSL_want_write(s)) { + bio = SSL_get_wbio(s); + if (BIO_should_write(bio)) { + return (SSL_ERROR_WANT_WRITE); + } else if (BIO_should_read(bio)) { + /* + * See above (SSL_want_read(s) with + * BIO_should_write(bio)) + */ + return (SSL_ERROR_WANT_READ); + } else if (BIO_should_io_special(bio)) { + reason = BIO_get_retry_reason(bio); + if (reason == BIO_RR_CONNECT) + return (SSL_ERROR_WANT_CONNECT); + else if (reason == BIO_RR_ACCEPT) + return (SSL_ERROR_WANT_ACCEPT); + else + return (SSL_ERROR_SYSCALL); + } + } + + if (SSL_want_x509_lookup(s)) + return (SSL_ERROR_WANT_X509_LOOKUP); + + if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) && + (s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) + return (SSL_ERROR_ZERO_RETURN); + + return (SSL_ERROR_SYSCALL); +} +LSSL_ALIAS(SSL_get_error); + +int +SSL_CTX_set_quic_method(SSL_CTX *ctx, const SSL_QUIC_METHOD *quic_method) +{ + if (ctx->method->dtls) + return 0; + + ctx->quic_method = quic_method; + + return 1; +} +LSSL_ALIAS(SSL_CTX_set_quic_method); + +int +SSL_set_quic_method(SSL *ssl, const SSL_QUIC_METHOD *quic_method) +{ + if (ssl->method->dtls) + return 0; + + ssl->quic_method = quic_method; + + return 1; +} +LSSL_ALIAS(SSL_set_quic_method); + +size_t +SSL_quic_max_handshake_flight_len(const SSL *ssl, + enum ssl_encryption_level_t level) +{ + size_t flight_len; + + /* Limit flights to 16K when there are no large certificate messages. */ + flight_len = 16384; + + switch (level) { + case ssl_encryption_initial: + return flight_len; + + case ssl_encryption_early_data: + /* QUIC does not send EndOfEarlyData. */ + return 0; + + case ssl_encryption_handshake: + if (ssl->server) { + /* + * Servers may receive Certificate message if configured + * to request client certificates. + */ + if ((SSL_get_verify_mode(ssl) & SSL_VERIFY_PEER) != 0 && + ssl->max_cert_list > flight_len) + flight_len = ssl->max_cert_list; + } else { + /* + * Clients may receive both Certificate message and a + * CertificateRequest message. + */ + if (ssl->max_cert_list * 2 > flight_len) + flight_len = ssl->max_cert_list * 2; + } + return flight_len; + case ssl_encryption_application: + /* + * Note there is not actually a bound on the number of + * NewSessionTickets one may send in a row. This level may need + * more involved flow control. + */ + return flight_len; + } + + return 0; +} +LSSL_ALIAS(SSL_quic_max_handshake_flight_len); + +enum ssl_encryption_level_t +SSL_quic_read_level(const SSL *ssl) +{ + return ssl->s3->hs.tls13.quic_read_level; +} +LSSL_ALIAS(SSL_quic_read_level); + +enum ssl_encryption_level_t +SSL_quic_write_level(const SSL *ssl) +{ + return ssl->s3->hs.tls13.quic_write_level; +} +LSSL_ALIAS(SSL_quic_write_level); + +int +SSL_provide_quic_data(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len) +{ + if (!SSL_is_quic(ssl)) { + SSLerror(ssl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + if (level != SSL_quic_read_level(ssl)) { + SSLerror(ssl, SSL_R_WRONG_ENCRYPTION_LEVEL_RECEIVED); + return 0; + } + + if (ssl->s3->hs.tls13.quic_read_buffer == NULL) { + ssl->s3->hs.tls13.quic_read_buffer = tls_buffer_new(0); + if (ssl->s3->hs.tls13.quic_read_buffer == NULL) { + SSLerror(ssl, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + /* XXX - note that this does not currently downsize. */ + tls_buffer_set_capacity_limit(ssl->s3->hs.tls13.quic_read_buffer, + SSL_quic_max_handshake_flight_len(ssl, level)); + + /* + * XXX - an append that fails due to exceeding capacity should set + * SSL_R_EXCESSIVE_MESSAGE_SIZE. + */ + return tls_buffer_append(ssl->s3->hs.tls13.quic_read_buffer, data, len); +} +LSSL_ALIAS(SSL_provide_quic_data); + +int +SSL_process_quic_post_handshake(SSL *ssl) +{ + /* XXX - this needs to run PHH received. */ + return 1; +} +LSSL_ALIAS(SSL_process_quic_post_handshake); + +int +SSL_do_handshake(SSL *s) +{ + if (s->handshake_func == NULL) { + SSLerror(s, SSL_R_CONNECTION_TYPE_NOT_SET); + return (-1); + } + + s->method->ssl_renegotiate_check(s); + + if (!SSL_in_init(s) && !SSL_in_before(s)) + return 1; + + return s->handshake_func(s); +} +LSSL_ALIAS(SSL_do_handshake); + +/* + * For the next 2 functions, SSL_clear() sets shutdown and so + * one of these calls will reset it + */ +void +SSL_set_accept_state(SSL *s) +{ + s->server = 1; + s->shutdown = 0; + s->s3->hs.state = SSL_ST_ACCEPT|SSL_ST_BEFORE; + s->handshake_func = s->method->ssl_accept; + ssl_clear_cipher_state(s); +} +LSSL_ALIAS(SSL_set_accept_state); + +void +SSL_set_connect_state(SSL *s) +{ + s->server = 0; + s->shutdown = 0; + s->s3->hs.state = SSL_ST_CONNECT|SSL_ST_BEFORE; + s->handshake_func = s->method->ssl_connect; + ssl_clear_cipher_state(s); +} +LSSL_ALIAS(SSL_set_connect_state); + +int +ssl_undefined_function(SSL *s) +{ + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (0); +} + +int +ssl_undefined_void_function(void) +{ + SSLerrorx(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (0); +} + +int +ssl_undefined_const_function(const SSL *s) +{ + SSLerror(s, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return (0); +} + +const char * +ssl_version_string(int ver) +{ + switch (ver) { + case TLS1_VERSION: + return (SSL_TXT_TLSV1); + case TLS1_1_VERSION: + return (SSL_TXT_TLSV1_1); + case TLS1_2_VERSION: + return (SSL_TXT_TLSV1_2); + case TLS1_3_VERSION: + return (SSL_TXT_TLSV1_3); + case DTLS1_VERSION: + return (SSL_TXT_DTLS1); + case DTLS1_2_VERSION: + return (SSL_TXT_DTLS1_2); + default: + return ("unknown"); + } +} + +const char * +SSL_get_version(const SSL *s) +{ + return ssl_version_string(s->version); +} +LSSL_ALIAS(SSL_get_version); + +SSL * +SSL_dup(SSL *s) +{ + STACK_OF(X509_NAME) *sk; + X509_NAME *xn; + SSL *ret; + int i; + + if ((ret = SSL_new(SSL_get_SSL_CTX(s))) == NULL) + goto err; + + ret->version = s->version; + ret->method = s->method; + + if (s->session != NULL) { + if (!SSL_copy_session_id(ret, s)) + goto err; + } else { + /* + * No session has been established yet, so we have to expect + * that s->cert or ret->cert will be changed later -- + * they should not both point to the same object, + * and thus we can't use SSL_copy_session_id. + */ + + ret->method->ssl_free(ret); + ret->method = s->method; + ret->method->ssl_new(ret); + + ssl_cert_free(ret->cert); + if ((ret->cert = ssl_cert_dup(s->cert)) == NULL) + goto err; + + if (!SSL_set_session_id_context(ret, s->sid_ctx, + s->sid_ctx_length)) + goto err; + } + + ret->options = s->options; + ret->mode = s->mode; + SSL_set_max_cert_list(ret, SSL_get_max_cert_list(s)); + SSL_set_read_ahead(ret, SSL_get_read_ahead(s)); + ret->msg_callback = s->msg_callback; + ret->msg_callback_arg = s->msg_callback_arg; + SSL_set_verify(ret, SSL_get_verify_mode(s), + SSL_get_verify_callback(s)); + SSL_set_verify_depth(ret, SSL_get_verify_depth(s)); + ret->generate_session_id = s->generate_session_id; + + SSL_set_info_callback(ret, SSL_get_info_callback(s)); + + ret->debug = s->debug; + + /* copy app data, a little dangerous perhaps */ + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, + &ret->ex_data, &s->ex_data)) + goto err; + + /* setup rbio, and wbio */ + if (s->rbio != NULL) { + if (!BIO_dup_state(s->rbio,(char *)&ret->rbio)) + goto err; + } + if (s->wbio != NULL) { + if (s->wbio != s->rbio) { + if (!BIO_dup_state(s->wbio,(char *)&ret->wbio)) + goto err; + } else + ret->wbio = ret->rbio; + } + ret->rwstate = s->rwstate; + ret->in_handshake = s->in_handshake; + ret->handshake_func = s->handshake_func; + ret->server = s->server; + ret->renegotiate = s->renegotiate; + ret->new_session = s->new_session; + ret->quiet_shutdown = s->quiet_shutdown; + ret->shutdown = s->shutdown; + /* SSL_dup does not really work at any state, though */ + ret->s3->hs.state = s->s3->hs.state; + ret->rstate = s->rstate; + + /* + * Would have to copy ret->init_buf, ret->init_msg, ret->init_num, + * ret->init_off + */ + ret->init_num = 0; + + ret->hit = s->hit; + + X509_VERIFY_PARAM_inherit(ret->param, s->param); + + if (s->cipher_list != NULL) { + if ((ret->cipher_list = + sk_SSL_CIPHER_dup(s->cipher_list)) == NULL) + goto err; + } + if (s->cipher_list_tls13 != NULL) { + if ((ret->cipher_list_tls13 = + sk_SSL_CIPHER_dup(s->cipher_list_tls13)) == NULL) + goto err; + } + + /* Dup the client_CA list */ + if (s->client_CA != NULL) { + if ((sk = sk_X509_NAME_dup(s->client_CA)) == NULL) goto err; + ret->client_CA = sk; + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + xn = sk_X509_NAME_value(sk, i); + if (sk_X509_NAME_set(sk, i, + X509_NAME_dup(xn)) == NULL) { + X509_NAME_free(xn); + goto err; + } + } + } + + return ret; + err: + SSL_free(ret); + return NULL; +} +LSSL_ALIAS(SSL_dup); + +void +ssl_clear_cipher_state(SSL *s) +{ + tls12_record_layer_clear_read_state(s->rl); + tls12_record_layer_clear_write_state(s->rl); +} + +void +ssl_info_callback(const SSL *s, int type, int value) +{ + ssl_info_callback_fn *cb; + + if ((cb = s->info_callback) == NULL) + cb = s->ctx->info_callback; + if (cb != NULL) + cb(s, type, value); +} + +void +ssl_msg_callback(SSL *s, int is_write, int content_type, + const void *msg_buf, size_t msg_len) +{ + if (s->msg_callback == NULL) + return; + + s->msg_callback(is_write, s->version, content_type, + msg_buf, msg_len, s, s->msg_callback_arg); +} + +void +ssl_msg_callback_cbs(SSL *s, int is_write, int content_type, CBS *cbs) +{ + ssl_msg_callback(s, is_write, content_type, CBS_data(cbs), CBS_len(cbs)); +} + +/* Fix this function so that it takes an optional type parameter */ +X509 * +SSL_get_certificate(const SSL *s) +{ + return (s->cert->key->x509); +} +LSSL_ALIAS(SSL_get_certificate); + +/* Fix this function so that it takes an optional type parameter */ +EVP_PKEY * +SSL_get_privatekey(const SSL *s) +{ + return (s->cert->key->privatekey); +} +LSSL_ALIAS(SSL_get_privatekey); + +const SSL_CIPHER * +SSL_get_current_cipher(const SSL *s) +{ + if ((s->session != NULL) && (s->session->cipher != NULL)) + return (s->session->cipher); + return (NULL); +} +LSSL_ALIAS(SSL_get_current_cipher); +const void * +SSL_get_current_compression(SSL *s) +{ + return (NULL); +} +LSSL_ALIAS(SSL_get_current_compression); + +const void * +SSL_get_current_expansion(SSL *s) +{ + return (NULL); +} +LSSL_ALIAS(SSL_get_current_expansion); + +size_t +SSL_get_client_random(const SSL *s, unsigned char *out, size_t max_out) +{ + size_t len = sizeof(s->s3->client_random); + + if (out == NULL) + return len; + + if (len > max_out) + len = max_out; + + memcpy(out, s->s3->client_random, len); + + return len; +} +LSSL_ALIAS(SSL_get_client_random); + +size_t +SSL_get_server_random(const SSL *s, unsigned char *out, size_t max_out) +{ + size_t len = sizeof(s->s3->server_random); + + if (out == NULL) + return len; + + if (len > max_out) + len = max_out; + + memcpy(out, s->s3->server_random, len); + + return len; +} +LSSL_ALIAS(SSL_get_server_random); + +int +ssl_init_wbio_buffer(SSL *s, int push) +{ + BIO *bbio; + + if (s->bbio == NULL) { + bbio = BIO_new(BIO_f_buffer()); + if (bbio == NULL) + return (0); + s->bbio = bbio; + } else { + bbio = s->bbio; + if (s->bbio == s->wbio) + s->wbio = BIO_pop(s->wbio); + } + (void)BIO_reset(bbio); +/* if (!BIO_set_write_buffer_size(bbio,16*1024)) */ + if (!BIO_set_read_buffer_size(bbio, 1)) { + SSLerror(s, ERR_R_BUF_LIB); + return (0); + } + if (push) { + if (s->wbio != bbio) + s->wbio = BIO_push(bbio, s->wbio); + } else { + if (s->wbio == bbio) + s->wbio = BIO_pop(bbio); + } + return (1); +} + +void +ssl_free_wbio_buffer(SSL *s) +{ + if (s == NULL) + return; + + if (s->bbio == NULL) + return; + + if (s->bbio == s->wbio) { + /* remove buffering */ + s->wbio = BIO_pop(s->wbio); + } + BIO_free(s->bbio); + s->bbio = NULL; +} + +void +SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) +{ + ctx->quiet_shutdown = mode; +} +LSSL_ALIAS(SSL_CTX_set_quiet_shutdown); + +int +SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx) +{ + return (ctx->quiet_shutdown); +} +LSSL_ALIAS(SSL_CTX_get_quiet_shutdown); + +void +SSL_set_quiet_shutdown(SSL *s, int mode) +{ + s->quiet_shutdown = mode; +} +LSSL_ALIAS(SSL_set_quiet_shutdown); + +int +SSL_get_quiet_shutdown(const SSL *s) +{ + return (s->quiet_shutdown); +} +LSSL_ALIAS(SSL_get_quiet_shutdown); + +void +SSL_set_shutdown(SSL *s, int mode) +{ + s->shutdown = mode; +} +LSSL_ALIAS(SSL_set_shutdown); + +int +SSL_get_shutdown(const SSL *s) +{ + return (s->shutdown); +} +LSSL_ALIAS(SSL_get_shutdown); + +int +SSL_version(const SSL *s) +{ + return (s->version); +} +LSSL_ALIAS(SSL_version); + +SSL_CTX * +SSL_get_SSL_CTX(const SSL *ssl) +{ + return (ssl->ctx); +} +LSSL_ALIAS(SSL_get_SSL_CTX); + +SSL_CTX * +SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx) +{ + SSL_CERT *new_cert; + + if (ctx == NULL) + ctx = ssl->initial_ctx; + if (ssl->ctx == ctx) + return (ssl->ctx); + + if ((new_cert = ssl_cert_dup(ctx->cert)) == NULL) + return NULL; + ssl_cert_free(ssl->cert); + ssl->cert = new_cert; + + SSL_CTX_up_ref(ctx); + SSL_CTX_free(ssl->ctx); /* decrement reference count */ + ssl->ctx = ctx; + + return (ssl->ctx); +} +LSSL_ALIAS(SSL_set_SSL_CTX); + +int +SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) +{ + return (X509_STORE_set_default_paths(ctx->cert_store)); +} +LSSL_ALIAS(SSL_CTX_set_default_verify_paths); + +int +SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, + const char *CApath) +{ + return (X509_STORE_load_locations(ctx->cert_store, CAfile, CApath)); +} +LSSL_ALIAS(SSL_CTX_load_verify_locations); + +int +SSL_CTX_load_verify_mem(SSL_CTX *ctx, void *buf, int len) +{ + return (X509_STORE_load_mem(ctx->cert_store, buf, len)); +} +LSSL_ALIAS(SSL_CTX_load_verify_mem); + +void +SSL_set_info_callback(SSL *ssl, void (*cb)(const SSL *ssl, int type, int val)) +{ + ssl->info_callback = cb; +} +LSSL_ALIAS(SSL_set_info_callback); + +void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl, int type, int val) +{ + return (ssl->info_callback); +} +LSSL_ALIAS(SSL_get_info_callback); + +int +SSL_state(const SSL *ssl) +{ + return (ssl->s3->hs.state); +} +LSSL_ALIAS(SSL_state); + +void +SSL_set_state(SSL *ssl, int state) +{ + ssl->s3->hs.state = state; +} +LSSL_ALIAS(SSL_set_state); + +void +SSL_set_verify_result(SSL *ssl, long arg) +{ + ssl->verify_result = arg; +} +LSSL_ALIAS(SSL_set_verify_result); + +long +SSL_get_verify_result(const SSL *ssl) +{ + return (ssl->verify_result); +} +LSSL_ALIAS(SSL_get_verify_result); + +int +SSL_verify_client_post_handshake(SSL *ssl) +{ + return 0; +} +LSSL_ALIAS(SSL_verify_client_post_handshake); + +void +SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val) +{ + return; +} +LSSL_ALIAS(SSL_CTX_set_post_handshake_auth); + +void +SSL_set_post_handshake_auth(SSL *ssl, int val) +{ + return; +} +LSSL_ALIAS(SSL_set_post_handshake_auth); + +int +SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + return (CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, argl, argp, + new_func, dup_func, free_func)); +} +LSSL_ALIAS(SSL_get_ex_new_index); + +int +SSL_set_ex_data(SSL *s, int idx, void *arg) +{ + return (CRYPTO_set_ex_data(&s->ex_data, idx, arg)); +} +LSSL_ALIAS(SSL_set_ex_data); + +void * +SSL_get_ex_data(const SSL *s, int idx) +{ + return (CRYPTO_get_ex_data(&s->ex_data, idx)); +} +LSSL_ALIAS(SSL_get_ex_data); + +int +SSL_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + return (CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, argl, argp, + new_func, dup_func, free_func)); +} +LSSL_ALIAS(SSL_CTX_get_ex_new_index); + +int +SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg) +{ + return (CRYPTO_set_ex_data(&s->ex_data, idx, arg)); +} +LSSL_ALIAS(SSL_CTX_set_ex_data); + +void * +SSL_CTX_get_ex_data(const SSL_CTX *s, int idx) +{ + return (CRYPTO_get_ex_data(&s->ex_data, idx)); +} +LSSL_ALIAS(SSL_CTX_get_ex_data); + +int +ssl_ok(SSL *s) +{ + return (1); +} + +X509_STORE * +SSL_CTX_get_cert_store(const SSL_CTX *ctx) +{ + return (ctx->cert_store); +} +LSSL_ALIAS(SSL_CTX_get_cert_store); + +void +SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) +{ + X509_STORE_free(ctx->cert_store); + ctx->cert_store = store; +} +LSSL_ALIAS(SSL_CTX_set_cert_store); + +X509 * +SSL_CTX_get0_certificate(const SSL_CTX *ctx) +{ + if (ctx->cert == NULL) + return NULL; + + return ctx->cert->key->x509; +} +LSSL_ALIAS(SSL_CTX_get0_certificate); + +EVP_PKEY * +SSL_CTX_get0_privatekey(const SSL_CTX *ctx) +{ + if (ctx->cert == NULL) + return NULL; + + return ctx->cert->key->privatekey; +} +LSSL_ALIAS(SSL_CTX_get0_privatekey); + +int +SSL_want(const SSL *s) +{ + return (s->rwstate); +} +LSSL_ALIAS(SSL_want); + +void +SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx, RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); +} +LSSL_ALIAS(SSL_CTX_set_tmp_rsa_callback); + +void +SSL_set_tmp_rsa_callback(SSL *ssl, RSA *(*cb)(SSL *ssl, int is_export, + int keylength)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_RSA_CB,(void (*)(void))cb); +} +LSSL_ALIAS(SSL_set_tmp_rsa_callback); + +void +SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx, DH *(*dh)(SSL *ssl, int is_export, + int keylength)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); +} +LSSL_ALIAS(SSL_CTX_set_tmp_dh_callback); + +void +SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh)(SSL *ssl, int is_export, + int keylength)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB,(void (*)(void))dh); +} +LSSL_ALIAS(SSL_set_tmp_dh_callback); + +void +SSL_CTX_set_tmp_ecdh_callback(SSL_CTX *ctx, EC_KEY *(*ecdh)(SSL *ssl, + int is_export, int keylength)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH_CB, + (void (*)(void))ecdh); +} +LSSL_ALIAS(SSL_CTX_set_tmp_ecdh_callback); + +void +SSL_set_tmp_ecdh_callback(SSL *ssl, EC_KEY *(*ecdh)(SSL *ssl, int is_export, + int keylength)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_ECDH_CB,(void (*)(void))ecdh); +} +LSSL_ALIAS(SSL_set_tmp_ecdh_callback); + + +void +SSL_CTX_set_msg_callback(SSL_CTX *ctx, void (*cb)(int write_p, int version, + int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) +{ + SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, + (void (*)(void))cb); +} +LSSL_ALIAS(SSL_CTX_set_msg_callback); + +void +SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, + int content_type, const void *buf, size_t len, SSL *ssl, void *arg)) +{ + SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb); +} +LSSL_ALIAS(SSL_set_msg_callback); + +void +SSL_set_debug(SSL *s, int debug) +{ + s->debug = debug; +} +LSSL_ALIAS(SSL_set_debug); + +int +SSL_cache_hit(SSL *s) +{ + return (s->hit); +} +LSSL_ALIAS(SSL_cache_hit); + +int +SSL_CTX_get_min_proto_version(SSL_CTX *ctx) +{ + return ctx->min_proto_version; +} +LSSL_ALIAS(SSL_CTX_get_min_proto_version); + +int +SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) +{ + return ssl_version_set_min(ctx->method, version, + ctx->max_tls_version, &ctx->min_tls_version, + &ctx->min_proto_version); +} +LSSL_ALIAS(SSL_CTX_set_min_proto_version); + +int +SSL_CTX_get_max_proto_version(SSL_CTX *ctx) +{ + return ctx->max_proto_version; +} +LSSL_ALIAS(SSL_CTX_get_max_proto_version); + +int +SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) +{ + return ssl_version_set_max(ctx->method, version, + ctx->min_tls_version, &ctx->max_tls_version, + &ctx->max_proto_version); +} +LSSL_ALIAS(SSL_CTX_set_max_proto_version); + +int +SSL_get_min_proto_version(SSL *ssl) +{ + return ssl->min_proto_version; +} +LSSL_ALIAS(SSL_get_min_proto_version); + +int +SSL_set_min_proto_version(SSL *ssl, uint16_t version) +{ + return ssl_version_set_min(ssl->method, version, + ssl->max_tls_version, &ssl->min_tls_version, + &ssl->min_proto_version); +} +LSSL_ALIAS(SSL_set_min_proto_version); +int +SSL_get_max_proto_version(SSL *ssl) +{ + return ssl->max_proto_version; +} +LSSL_ALIAS(SSL_get_max_proto_version); + +int +SSL_set_max_proto_version(SSL *ssl, uint16_t version) +{ + return ssl_version_set_max(ssl->method, version, + ssl->min_tls_version, &ssl->max_tls_version, + &ssl->max_proto_version); +} +LSSL_ALIAS(SSL_set_max_proto_version); + +const SSL_METHOD * +SSL_CTX_get_ssl_method(const SSL_CTX *ctx) +{ + return ctx->method; +} +LSSL_ALIAS(SSL_CTX_get_ssl_method); + +int +SSL_CTX_get_security_level(const SSL_CTX *ctx) +{ + return ctx->cert->security_level; +} +LSSL_ALIAS(SSL_CTX_get_security_level); + +void +SSL_CTX_set_security_level(SSL_CTX *ctx, int level) +{ + ctx->cert->security_level = level; +} +LSSL_ALIAS(SSL_CTX_set_security_level); + +int +SSL_get_security_level(const SSL *ssl) +{ + return ssl->cert->security_level; +} +LSSL_ALIAS(SSL_get_security_level); + +void +SSL_set_security_level(SSL *ssl, int level) +{ + ssl->cert->security_level = level; +} +LSSL_ALIAS(SSL_set_security_level); + +int +SSL_is_quic(const SSL *ssl) +{ + return ssl->quic_method != NULL; +} +LSSL_ALIAS(SSL_is_quic); + +int +SSL_set_quic_transport_params(SSL *ssl, const uint8_t *params, + size_t params_len) +{ + freezero(ssl->quic_transport_params, + ssl->quic_transport_params_len); + ssl->quic_transport_params = NULL; + ssl->quic_transport_params_len = 0; + + if ((ssl->quic_transport_params = malloc(params_len)) == NULL) + return 0; + + memcpy(ssl->quic_transport_params, params, params_len); + ssl->quic_transport_params_len = params_len; + + return 1; +} +LSSL_ALIAS(SSL_set_quic_transport_params); + +void +SSL_get_peer_quic_transport_params(const SSL *ssl, const uint8_t **out_params, + size_t *out_params_len) +{ + *out_params = ssl->s3->peer_quic_transport_params; + *out_params_len = ssl->s3->peer_quic_transport_params_len; +} +LSSL_ALIAS(SSL_get_peer_quic_transport_params); + +void +SSL_set_quic_use_legacy_codepoint(SSL *ssl, int use_legacy) +{ + /* Not supported. */ +} +LSSL_ALIAS(SSL_set_quic_use_legacy_codepoint); + +static int +ssl_cipher_id_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_) +{ + SSL_CIPHER const *a = a_; + SSL_CIPHER const *b = b_; + return ssl_cipher_id_cmp(a, b); +} + +SSL_CIPHER * +OBJ_bsearch_ssl_cipher_id(SSL_CIPHER *key, SSL_CIPHER const *base, int num) +{ + return (SSL_CIPHER *)OBJ_bsearch_(key, base, num, sizeof(SSL_CIPHER), + ssl_cipher_id_cmp_BSEARCH_CMP_FN); +} diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h new file mode 100644 index 0000000..9666f38 --- /dev/null +++ b/ssl/ssl_local.h @@ -0,0 +1,1531 @@ +/* $OpenBSD: ssl_local.h,v 1.7 2023/07/06 07:56:32 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#ifndef HEADER_SSL_LOCL_H +#define HEADER_SSL_LOCL_H + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "bytestring.h" +#include "tls_content.h" +#include "tls13_internal.h" + +__BEGIN_HIDDEN_DECLS + +#define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ + __attribute__((__unused__)) + +#ifndef LIBRESSL_HAS_DTLS1_2 +#define LIBRESSL_HAS_DTLS1_2 +#endif + +/* LOCAL STUFF */ + +#define SSL_DECRYPT 0 +#define SSL_ENCRYPT 1 + +/* + * Define the Bitmasks for SSL_CIPHER.algorithms. + * This bits are used packed as dense as possible. If new methods/ciphers + * etc will be added, the bits a likely to change, so this information + * is for internal library use only, even though SSL_CIPHER.algorithms + * can be publicly accessed. + * Use the according functions for cipher management instead. + * + * The bit mask handling in the selection and sorting scheme in + * ssl_create_cipher_list() has only limited capabilities, reflecting + * that the different entities within are mutually exclusive: + * ONLY ONE BIT PER MASK CAN BE SET AT A TIME. + */ + +/* Bits for algorithm_mkey (key exchange algorithm) */ +#define SSL_kRSA 0x00000001L /* RSA key exchange */ +#define SSL_kDHE 0x00000008L /* tmp DH key no DH cert */ +#define SSL_kECDHE 0x00000080L /* ephemeral ECDH */ +#define SSL_kGOST 0x00000200L /* GOST key exchange */ +#define SSL_kTLS1_3 0x00000400L /* TLSv1.3 key exchange */ + +/* Bits for algorithm_auth (server authentication) */ +#define SSL_aRSA 0x00000001L /* RSA auth */ +#define SSL_aDSS 0x00000002L /* DSS auth */ +#define SSL_aNULL 0x00000004L /* no auth (i.e. use ADH or AECDH) */ +#define SSL_aECDSA 0x00000040L /* ECDSA auth*/ +#define SSL_aGOST01 0x00000200L /* GOST R 34.10-2001 signature auth */ +#define SSL_aTLS1_3 0x00000400L /* TLSv1.3 authentication */ + +/* Bits for algorithm_enc (symmetric encryption) */ +#define SSL_DES 0x00000001L +#define SSL_3DES 0x00000002L +#define SSL_RC4 0x00000004L +#define SSL_IDEA 0x00000008L +#define SSL_eNULL 0x00000010L +#define SSL_AES128 0x00000020L +#define SSL_AES256 0x00000040L +#define SSL_CAMELLIA128 0x00000080L +#define SSL_CAMELLIA256 0x00000100L +#define SSL_eGOST2814789CNT 0x00000200L +#define SSL_AES128GCM 0x00000400L +#define SSL_AES256GCM 0x00000800L +#define SSL_CHACHA20POLY1305 0x00001000L + +#define SSL_AES (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM) +#define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256) + + +/* Bits for algorithm_mac (symmetric authentication) */ + +#define SSL_MD5 0x00000001L +#define SSL_SHA1 0x00000002L +#define SSL_GOST94 0x00000004L +#define SSL_GOST89MAC 0x00000008L +#define SSL_SHA256 0x00000010L +#define SSL_SHA384 0x00000020L +/* Not a real MAC, just an indication it is part of cipher */ +#define SSL_AEAD 0x00000040L +#define SSL_STREEBOG256 0x00000080L + +/* Bits for algorithm_ssl (protocol version) */ +#define SSL_SSLV3 0x00000002L +#define SSL_TLSV1 SSL_SSLV3 /* for now */ +#define SSL_TLSV1_2 0x00000004L +#define SSL_TLSV1_3 0x00000008L + + +/* Bits for algorithm2 (handshake digests and other extra flags) */ + +#define SSL_HANDSHAKE_MAC_MASK 0xff0 +#define SSL_HANDSHAKE_MAC_MD5 0x010 +#define SSL_HANDSHAKE_MAC_SHA 0x020 +#define SSL_HANDSHAKE_MAC_GOST94 0x040 +#define SSL_HANDSHAKE_MAC_SHA256 0x080 +#define SSL_HANDSHAKE_MAC_SHA384 0x100 +#define SSL_HANDSHAKE_MAC_STREEBOG256 0x200 +#define SSL_HANDSHAKE_MAC_DEFAULT (SSL_HANDSHAKE_MAC_MD5 | SSL_HANDSHAKE_MAC_SHA) + +#define SSL3_CK_ID 0x03000000 +#define SSL3_CK_VALUE_MASK 0x0000ffff + +#define TLS1_PRF_DGST_MASK (0xff << TLS1_PRF_DGST_SHIFT) + +#define TLS1_PRF_DGST_SHIFT 10 +#define TLS1_PRF_MD5 (SSL_HANDSHAKE_MAC_MD5 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_SHA1 (SSL_HANDSHAKE_MAC_SHA << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_SHA256 (SSL_HANDSHAKE_MAC_SHA256 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_SHA384 (SSL_HANDSHAKE_MAC_SHA384 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_GOST94 (SSL_HANDSHAKE_MAC_GOST94 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF_STREEBOG256 (SSL_HANDSHAKE_MAC_STREEBOG256 << TLS1_PRF_DGST_SHIFT) +#define TLS1_PRF (TLS1_PRF_MD5 | TLS1_PRF_SHA1) + +/* + * Stream MAC for GOST ciphersuites from cryptopro draft + * (currently this also goes into algorithm2). + */ +#define TLS1_STREAM_MAC 0x04 + +/* + * SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD is an algorithm2 flag that + * indicates that the variable part of the nonce is included as a prefix of + * the record (AES-GCM, for example, does this with an 8-byte variable nonce.) + */ +#define SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_IN_RECORD (1 << 22) + +/* + * SSL_CIPHER_AEAD_FIXED_NONCE_LEN returns the number of bytes of fixed nonce + * for an SSL_CIPHER with an algorithm_mac of SSL_AEAD. + */ +#define SSL_CIPHER_AEAD_FIXED_NONCE_LEN(ssl_cipher) \ + (((ssl_cipher->algorithm2 >> 24) & 0xf) * 2) + +/* + * Cipher strength information. + */ +#define SSL_STRONG_MASK 0x000001fcL +#define SSL_STRONG_NONE 0x00000004L +#define SSL_LOW 0x00000020L +#define SSL_MEDIUM 0x00000040L +#define SSL_HIGH 0x00000080L + +/* + * The keylength (measured in RSA key bits, I guess) for temporary keys. + * Cipher argument is so that this can be variable in the future. + */ +#define SSL_C_PKEYLENGTH(c) 1024 + +/* See if we use signature algorithms extension. */ +#define SSL_USE_SIGALGS(s) \ + (s->method->enc_flags & SSL_ENC_FLAG_SIGALGS) + +/* See if we use SHA256 default PRF. */ +#define SSL_USE_SHA256_PRF(s) \ + (s->method->enc_flags & SSL_ENC_FLAG_SHA256_PRF) + +/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2. */ +#define SSL_USE_TLS1_2_CIPHERS(s) \ + (s->method->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) + +/* Allow TLS 1.3 ciphersuites only. */ +#define SSL_USE_TLS1_3_CIPHERS(s) \ + (s->method->enc_flags & SSL_ENC_FLAG_TLS1_3_CIPHERS) + +#define SSL_PKEY_RSA 0 +#define SSL_PKEY_ECC 1 +#define SSL_PKEY_GOST01 2 +#define SSL_PKEY_NUM 3 + +#define SSL_MAX_EMPTY_RECORDS 32 + +/* SSL_kRSA <- RSA_ENC | (RSA_TMP & RSA_SIGN) | + * <- (EXPORT & (RSA_ENC | RSA_TMP) & RSA_SIGN) + * SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN) + * SSL_kDHE <- RSA_ENC | RSA_SIGN | DSA_SIGN + * SSL_aRSA <- RSA_ENC | RSA_SIGN + * SSL_aDSS <- DSA_SIGN + */ + +/* From ECC-TLS draft, used in encoding the curve type in + * ECParameters + */ +#define EXPLICIT_PRIME_CURVE_TYPE 1 +#define EXPLICIT_CHAR2_CURVE_TYPE 2 +#define NAMED_CURVE_TYPE 3 + +typedef struct ssl_cert_pkey_st { + X509 *x509; + EVP_PKEY *privatekey; + STACK_OF(X509) *chain; +} SSL_CERT_PKEY; + +typedef struct ssl_cert_st { + /* Current active set */ + /* ALWAYS points to an element of the pkeys array + * Probably it would make more sense to store + * an index, not a pointer. */ + SSL_CERT_PKEY *key; + + SSL_CERT_PKEY pkeys[SSL_PKEY_NUM]; + + /* The following masks are for the key and auth + * algorithms that are supported by the certs below */ + int valid; + unsigned long mask_k; + unsigned long mask_a; + + DH *dhe_params; + DH *(*dhe_params_cb)(SSL *ssl, int is_export, int keysize); + int dhe_params_auto; + + int (*security_cb)(const SSL *s, const SSL_CTX *ctx, int op, int bits, + int nid, void *other, void *ex_data); /* Not exposed in API. */ + int security_level; + void *security_ex_data; /* Not exposed in API. */ + + int references; /* >1 only if SSL_copy_session_id is used */ +} SSL_CERT; + +struct ssl_comp_st { + int id; + const char *name; +}; + +struct ssl_cipher_st { + int valid; + const char *name; /* text name */ + unsigned long id; /* id, 4 bytes, first is version */ + + unsigned long algorithm_mkey; /* key exchange algorithm */ + unsigned long algorithm_auth; /* server authentication */ + unsigned long algorithm_enc; /* symmetric encryption */ + unsigned long algorithm_mac; /* symmetric authentication */ + unsigned long algorithm_ssl; /* (major) protocol version */ + + unsigned long algo_strength; /* strength and export flags */ + unsigned long algorithm2; /* Extra flags */ + int strength_bits; /* Number of bits really used */ + int alg_bits; /* Number of bits for algorithm */ +}; + +struct ssl_method_st { + int dtls; + int server; + int version; + + uint16_t min_tls_version; + uint16_t max_tls_version; + + int (*ssl_new)(SSL *s); + void (*ssl_clear)(SSL *s); + void (*ssl_free)(SSL *s); + + int (*ssl_accept)(SSL *s); + int (*ssl_connect)(SSL *s); + int (*ssl_shutdown)(SSL *s); + + int (*ssl_renegotiate)(SSL *s); + int (*ssl_renegotiate_check)(SSL *s); + + int (*ssl_pending)(const SSL *s); + int (*ssl_read_bytes)(SSL *s, int type, unsigned char *buf, int len, + int peek); + int (*ssl_write_bytes)(SSL *s, int type, const void *buf_, int len); + + const SSL_CIPHER *(*get_cipher)(unsigned int ncipher); + + unsigned int enc_flags; /* SSL_ENC_FLAG_* */ +}; + +/* + * Let's make this into an ASN.1 type structure as follows + * SSL_SESSION_ID ::= SEQUENCE { + * version INTEGER, -- structure version number + * SSLversion INTEGER, -- SSL version number + * Cipher OCTET STRING, -- the 2 byte cipher ID + * Session_ID OCTET STRING, -- the Session ID + * Master_key OCTET STRING, -- the master key + * KRB5_principal OCTET STRING -- optional Kerberos principal + * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time + * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds + * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate + * Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context + * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer' + * HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension + * PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint + * PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity + * Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket + * Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only) + * Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method + * SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username + * } + * Look in ssl/ssl_asn1.c for more details + * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-). + */ +struct ssl_session_st { + int ssl_version; /* what ssl version session info is + * being kept in here? */ + + size_t master_key_length; + unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; + + /* session_id - valid? */ + size_t session_id_length; + unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + + /* this is used to determine whether the session is being reused in + * the appropriate context. It is up to the application to set this, + * via SSL_new */ + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + + /* Peer provided leaf (end-entity) certificate. */ + X509 *peer_cert; + int peer_cert_type; + + /* when app_verify_callback accepts a session where the peer's certificate + * is not ok, we must remember the error for session reuse: */ + long verify_result; /* only for servers */ + + long timeout; + time_t time; + int references; + + const SSL_CIPHER *cipher; + unsigned long cipher_id; /* when ASN.1 loaded, this + * needs to be used to load + * the 'cipher' structure */ + + STACK_OF(SSL_CIPHER) *ciphers; /* shared ciphers? */ + + char *tlsext_hostname; + + /* Session resumption - RFC 5077 and RFC 8446. */ + unsigned char *tlsext_tick; /* Session ticket */ + size_t tlsext_ticklen; /* Session ticket length */ + uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */ + uint32_t tlsext_tick_age_add; /* TLSv1.3 ticket age obfuscation (in ms) */ + struct tls13_secret resumption_master_secret; + + CRYPTO_EX_DATA ex_data; /* application specific data */ + + /* These are used to make removal of session-ids more + * efficient and to implement a maximum cache size. */ + struct ssl_session_st *prev, *next; + + /* Used to indicate that session resumption is not allowed. + * Applications can also set this bit for a new session via + * not_resumable_session_cb to disable session caching and tickets. */ + int not_resumable; + + size_t tlsext_ecpointformatlist_length; + uint8_t *tlsext_ecpointformatlist; /* peer's list */ + size_t tlsext_supportedgroups_length; + uint16_t *tlsext_supportedgroups; /* peer's list */ +}; + +struct ssl_sigalg; + +typedef struct ssl_handshake_tls12_st { + /* Used when SSL_ST_FLUSH_DATA is entered. */ + int next_state; + + /* Handshake message type and size. */ + int message_type; + unsigned long message_size; + + /* Reuse current handshake message. */ + int reuse_message; + + /* Client certificate requests. */ + int cert_request; + STACK_OF(X509_NAME) *ca_names; + + /* Record-layer key block for TLS 1.2 and earlier. */ + struct tls12_key_block *key_block; + + /* Transcript hash prior to sending certificate verify message. */ + uint8_t cert_verify[EVP_MAX_MD_SIZE]; +} SSL_HANDSHAKE_TLS12; + +typedef struct ssl_handshake_tls13_st { + int use_legacy; + int hrr; + + /* Client indicates psk_dhe_ke support in PskKeyExchangeMode. */ + int use_psk_dhe_ke; + + /* Certificate selected for use (static pointer). */ + const SSL_CERT_PKEY *cpk; + + /* Version proposed by peer server. */ + uint16_t server_version; + + uint16_t server_group; + struct tls13_secrets *secrets; + + uint8_t *cookie; + size_t cookie_len; + + /* Preserved transcript hash. */ + uint8_t transcript_hash[EVP_MAX_MD_SIZE]; + size_t transcript_hash_len; + + /* Legacy session ID. */ + uint8_t legacy_session_id[SSL_MAX_SSL_SESSION_ID_LENGTH]; + size_t legacy_session_id_len; + + /* ClientHello hash, used to validate following HelloRetryRequest */ + EVP_MD_CTX *clienthello_md_ctx; + unsigned char *clienthello_hash; + unsigned int clienthello_hash_len; + + /* QUIC read buffer and read/write encryption levels. */ + struct tls_buffer *quic_read_buffer; + enum ssl_encryption_level_t quic_read_level; + enum ssl_encryption_level_t quic_write_level; +} SSL_HANDSHAKE_TLS13; + +typedef struct ssl_handshake_st { + /* + * Minimum and maximum versions supported for this handshake. These are + * initialised at the start of a handshake based on the method in use + * and the current protocol version configuration. + */ + uint16_t our_min_tls_version; + uint16_t our_max_tls_version; + + /* + * Version negotiated for this session. For a client this is set once + * the server selected version is parsed from the ServerHello (either + * from the legacy version or supported versions extension). For a + * server this is set once we select the version we will use with the + * client. + */ + uint16_t negotiated_tls_version; + + /* + * Legacy version advertised by our peer. For a server this is the + * version specified by the client in the ClientHello message. For a + * client, this is the version provided in the ServerHello message. + */ + uint16_t peer_legacy_version; + + /* + * Current handshake state - contains one of the SSL3_ST_* values and + * is used by the TLSv1.2 state machine, as well as being updated by + * the TLSv1.3 stack due to it being exposed externally. + */ + int state; + + /* Cipher being negotiated in this handshake. */ + const SSL_CIPHER *cipher; + + /* Extensions seen in this handshake. */ + uint32_t extensions_seen; + + /* Signature algorithms selected for use (static pointers). */ + const struct ssl_sigalg *our_sigalg; + const struct ssl_sigalg *peer_sigalg; + + /* sigalgs offered in this handshake in wire form */ + uint8_t *sigalgs; + size_t sigalgs_len; + + /* Key share for ephemeral key exchange. */ + struct tls_key_share *key_share; + + /* + * Copies of the verify data sent in our finished message and the + * verify data received in the finished message sent by our peer. + */ + uint8_t finished[EVP_MAX_MD_SIZE]; + size_t finished_len; + uint8_t peer_finished[EVP_MAX_MD_SIZE]; + size_t peer_finished_len; + + /* List of certificates received from our peer. */ + STACK_OF(X509) *peer_certs; + STACK_OF(X509) *peer_certs_no_leaf; + + /* Certificate chain resulting from X.509 verification. */ + STACK_OF(X509) *verified_chain; + + SSL_HANDSHAKE_TLS12 tls12; + SSL_HANDSHAKE_TLS13 tls13; +} SSL_HANDSHAKE; + +typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; + +/* TLS Session Ticket extension struct. */ +struct tls_session_ticket_ext_st { + unsigned short length; + void *data; +}; + +struct tls12_key_block; + +struct tls12_key_block *tls12_key_block_new(void); +void tls12_key_block_free(struct tls12_key_block *kb); +void tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key, + CBS *key, CBS *iv); +void tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key, + CBS *key, CBS *iv); +int tls12_key_block_generate(struct tls12_key_block *kb, SSL *s, + const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash); + +struct tls12_record_layer; + +struct tls12_record_layer *tls12_record_layer_new(void); +void tls12_record_layer_free(struct tls12_record_layer *rl); +void tls12_record_layer_alert(struct tls12_record_layer *rl, + uint8_t *alert_desc); +int tls12_record_layer_write_overhead(struct tls12_record_layer *rl, + size_t *overhead); +int tls12_record_layer_read_protected(struct tls12_record_layer *rl); +int tls12_record_layer_write_protected(struct tls12_record_layer *rl); +void tls12_record_layer_set_aead(struct tls12_record_layer *rl, + const EVP_AEAD *aead); +void tls12_record_layer_set_cipher_hash(struct tls12_record_layer *rl, + const EVP_CIPHER *cipher, const EVP_MD *handshake_hash, + const EVP_MD *mac_hash); +void tls12_record_layer_set_version(struct tls12_record_layer *rl, + uint16_t version); +void tls12_record_layer_set_initial_epoch(struct tls12_record_layer *rl, + uint16_t epoch); +uint16_t tls12_record_layer_read_epoch(struct tls12_record_layer *rl); +uint16_t tls12_record_layer_write_epoch(struct tls12_record_layer *rl); +int tls12_record_layer_use_write_epoch(struct tls12_record_layer *rl, + uint16_t epoch); +void tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, + uint16_t epoch); +void tls12_record_layer_clear_read_state(struct tls12_record_layer *rl); +void tls12_record_layer_clear_write_state(struct tls12_record_layer *rl); +void tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl); +int tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl, + CBS *mac_key, CBS *key, CBS *iv); +int tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl, + CBS *mac_key, CBS *key, CBS *iv); +int tls12_record_layer_open_record(struct tls12_record_layer *rl, + uint8_t *buf, size_t buf_len, struct tls_content *out); +int tls12_record_layer_seal_record(struct tls12_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len, + CBB *out); + +typedef void (ssl_info_callback_fn)(const SSL *s, int type, int val); +typedef void (ssl_msg_callback_fn)(int is_write, int version, int content_type, + const void *buf, size_t len, SSL *ssl, void *arg); + +struct ssl_ctx_st { + const SSL_METHOD *method; + const SSL_QUIC_METHOD *quic_method; + + STACK_OF(SSL_CIPHER) *cipher_list; + + struct x509_store_st /* X509_STORE */ *cert_store; + + /* If timeout is not 0, it is the default timeout value set + * when SSL_new() is called. This has been put in to make + * life easier to set things up */ + long session_timeout; + + int references; + + /* Default values to use in SSL structures follow (these are copied by SSL_new) */ + + STACK_OF(X509) *extra_certs; + + int verify_mode; + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + + X509_VERIFY_PARAM *param; + + /* + * XXX + * default_passwd_cb used by python and openvpn, need to keep it until we + * add an accessor + */ + /* Default password callback. */ + pem_password_cb *default_passwd_callback; + + /* Default password callback user data. */ + void *default_passwd_callback_userdata; + + uint16_t min_tls_version; + uint16_t max_tls_version; + + /* + * These may be zero to imply minimum or maximum version supported by + * the method. + */ + uint16_t min_proto_version; + uint16_t max_proto_version; + + unsigned long options; + unsigned long mode; + + /* If this callback is not null, it will be called each + * time a session id is added to the cache. If this function + * returns 1, it means that the callback will do a + * SSL_SESSION_free() when it has finished using it. Otherwise, + * on 0, it means the callback has finished with it. + * If remove_session_cb is not null, it will be called when + * a session-id is removed from the cache. After the call, + * OpenSSL will SSL_SESSION_free() it. */ + int (*new_session_cb)(struct ssl_st *ssl, SSL_SESSION *sess); + void (*remove_session_cb)(struct ssl_ctx_st *ctx, SSL_SESSION *sess); + SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, + const unsigned char *data, int len, int *copy); + + /* if defined, these override the X509_verify_cert() calls */ + int (*app_verify_callback)(X509_STORE_CTX *, void *); + void *app_verify_arg; + + /* get client cert callback */ + int (*client_cert_cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey); + + /* cookie generate callback */ + int (*app_gen_cookie_cb)(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len); + + /* verify cookie callback */ + int (*app_verify_cookie_cb)(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len); + + ssl_info_callback_fn *info_callback; + + /* callback that allows applications to peek at protocol messages */ + ssl_msg_callback_fn *msg_callback; + void *msg_callback_arg; + + int (*default_verify_callback)(int ok,X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */ + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + /* TLS extensions servername callback */ + int (*tlsext_servername_callback)(SSL*, int *, void *); + void *tlsext_servername_arg; + + /* Callback to support customisation of ticket key setting */ + int (*tlsext_ticket_key_cb)(SSL *ssl, unsigned char *name, + unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc); + + /* certificate status request info */ + /* Callback for status request */ + int (*tlsext_status_cb)(SSL *ssl, void *arg); + void *tlsext_status_arg; + + struct lhash_st_SSL_SESSION *sessions; + + /* Most session-ids that will be cached, default is + * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited. */ + unsigned long session_cache_size; + struct ssl_session_st *session_cache_head; + struct ssl_session_st *session_cache_tail; + + /* This can have one of 2 values, ored together, + * SSL_SESS_CACHE_CLIENT, + * SSL_SESS_CACHE_SERVER, + * Default is SSL_SESSION_CACHE_SERVER, which means only + * SSL_accept which cache SSL_SESSIONS. */ + int session_cache_mode; + + struct { + int sess_connect; /* SSL new conn - started */ + int sess_connect_renegotiate;/* SSL reneg - requested */ + int sess_connect_good; /* SSL new conne/reneg - finished */ + int sess_accept; /* SSL new accept - started */ + int sess_accept_renegotiate;/* SSL reneg - requested */ + int sess_accept_good; /* SSL accept/reneg - finished */ + int sess_miss; /* session lookup misses */ + int sess_timeout; /* reuse attempt on timeouted session */ + int sess_cache_full; /* session removed due to full cache */ + int sess_hit; /* session reuse actually done */ + int sess_cb_hit; /* session-id that was not + * in the cache was + * passed back via the callback. This + * indicates that the application is + * supplying session-id's from other + * processes - spooky :-) */ + } stats; + + CRYPTO_EX_DATA ex_data; + + STACK_OF(SSL_CIPHER) *cipher_list_tls13; + + SSL_CERT *cert; + + /* Default values used when no per-SSL value is defined follow */ + + /* what we put in client cert requests */ + STACK_OF(X509_NAME) *client_CA; + + long max_cert_list; + + int read_ahead; + + int quiet_shutdown; + + /* Maximum amount of data to send in one fragment. + * actual record size can be more than this due to + * padding and MAC overheads. + */ + unsigned int max_send_fragment; + +#ifndef OPENSSL_NO_ENGINE + /* Engine to pass requests for client certs to + */ + ENGINE *client_cert_engine; +#endif + + /* RFC 4507 session ticket keys */ + unsigned char tlsext_tick_key_name[16]; + unsigned char tlsext_tick_hmac_key[16]; + unsigned char tlsext_tick_aes_key[16]; + + /* SRTP profiles we are willing to do from RFC 5764 */ + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; + + /* + * ALPN information. + */ + + /* + * Server callback function that allows the server to select the + * protocol for the connection. + * out: on successful return, this must point to the raw protocol + * name (without the length prefix). + * outlen: on successful return, this contains the length of out. + * in: points to the client's list of supported protocols in + * wire-format. + * inlen: the length of in. + */ + int (*alpn_select_cb)(SSL *s, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg); + void *alpn_select_cb_arg; + + /* Client list of supported protocols in wire format. */ + uint8_t *alpn_client_proto_list; + size_t alpn_client_proto_list_len; + + size_t tlsext_ecpointformatlist_length; + uint8_t *tlsext_ecpointformatlist; /* our list */ + size_t tlsext_supportedgroups_length; + uint16_t *tlsext_supportedgroups; /* our list */ + SSL_CTX_keylog_cb_func keylog_callback; /* Unused. For OpenSSL compatibility. */ + size_t num_tickets; /* Unused, for OpenSSL compatibility */ +}; + +struct ssl_st { + /* protocol version + * (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION, DTLS1_VERSION) + */ + int version; + + const SSL_METHOD *method; + const SSL_QUIC_METHOD *quic_method; + + /* There are 2 BIO's even though they are normally both the + * same. This is so data can be read and written to different + * handlers */ + + BIO *rbio; /* used by SSL_read */ + BIO *wbio; /* used by SSL_write */ + BIO *bbio; /* used during session-id reuse to concatenate + * messages */ + int server; /* are we the server side? - mostly used by SSL_clear*/ + + struct ssl3_state_st *s3; /* SSLv3 variables */ + struct dtls1_state_st *d1; /* DTLSv1 variables */ + + X509_VERIFY_PARAM *param; + + /* crypto */ + STACK_OF(SSL_CIPHER) *cipher_list; + + /* This is used to hold the server certificate used */ + SSL_CERT *cert; + + /* the session_id_context is used to ensure sessions are only reused + * in the appropriate context */ + size_t sid_ctx_length; + unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH]; + + /* This can also be in the session once a session is established */ + SSL_SESSION *session; + + /* Used in SSL2 and SSL3 */ + int verify_mode; /* 0 don't care about verify failure. + * 1 fail if verify fails */ + int error; /* error bytes to be written */ + int error_code; /* actual code */ + + SSL_CTX *ctx; + + long verify_result; + + int references; + + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ + + unsigned int max_send_fragment; + + const struct tls_extension **tlsext_build_order; + size_t tlsext_build_order_len; + + char *tlsext_hostname; + + /* certificate status request info */ + /* Status type or -1 if no status type */ + int tlsext_status_type; + + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ +#define session_ctx initial_ctx + + struct tls13_ctx *tls13; + + uint16_t min_tls_version; + uint16_t max_tls_version; + + /* + * These may be zero to imply minimum or maximum version supported by + * the method. + */ + uint16_t min_proto_version; + uint16_t max_proto_version; + + unsigned long options; /* protocol behaviour */ + unsigned long mode; /* API behaviour */ + + /* Client list of supported protocols in wire format. */ + uint8_t *alpn_client_proto_list; + size_t alpn_client_proto_list_len; + + /* QUIC transport params we will send */ + uint8_t *quic_transport_params; + size_t quic_transport_params_len; + + /* XXX Callbacks */ + + /* true when we are actually in SSL_accept() or SSL_connect() */ + int in_handshake; + int (*handshake_func)(SSL *); + + ssl_info_callback_fn *info_callback; + + /* callback that allows applications to peek at protocol messages */ + ssl_msg_callback_fn *msg_callback; + void *msg_callback_arg; + + int (*verify_callback)(int ok,X509_STORE_CTX *ctx); /* fail if callback returns 0 */ + + /* Default generate session ID callback. */ + GEN_SESSION_CB generate_session_id; + + /* TLS extension debug callback */ + void (*tlsext_debug_cb)(SSL *s, int client_server, int type, + unsigned char *data, int len, void *arg); + void *tlsext_debug_arg; + + /* TLS Session Ticket extension callback */ + tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb; + void *tls_session_ticket_ext_cb_arg; + + /* TLS pre-shared secret session resumption */ + tls_session_secret_cb_fn tls_session_secret_cb; + void *tls_session_secret_cb_arg; + + /* XXX non-callback */ + + /* This holds a variable that indicates what we were doing + * when a 0 or -1 is returned. This is needed for + * non-blocking IO so we know what request needs re-doing when + * in SSL_accept or SSL_connect */ + int rwstate; + + /* Imagine that here's a boolean member "init" that is + * switched as soon as SSL_set_{accept/connect}_state + * is called for the first time, so that "state" and + * "handshake_func" are properly initialized. But as + * handshake_func is == 0 until then, we use this + * test instead of an "init" member. + */ + + int new_session;/* Generate a new session or reuse an old one. + * NB: For servers, the 'new' session may actually be a previously + * cached session or even the previous session unless + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ + int quiet_shutdown;/* don't send shutdown packets */ + int shutdown; /* we have shut things down, 0x01 sent, 0x02 + * for received */ + BUF_MEM *init_buf; /* buffer used during init */ + void *init_msg; /* pointer to handshake message body, set by ssl3_get_message() */ + int init_num; /* amount read/written */ + int init_off; /* amount read/written */ + + /* used internally to point at a raw packet */ + unsigned char *packet; + unsigned int packet_length; + + int read_ahead; /* Read as many input bytes as possible + * (for non-blocking reads) */ + + int hit; /* reusing a previous session */ + + STACK_OF(SSL_CIPHER) *cipher_list_tls13; + + struct tls12_record_layer *rl; + + /* session info */ + + /* extra application data */ + CRYPTO_EX_DATA ex_data; + + /* client cert? */ + /* for server side, keep the list of CA_dn we can use */ + STACK_OF(X509_NAME) *client_CA; + + /* set this flag to 1 and a sleep(1) is put into all SSL_read() + * and SSL_write() calls, good for nbio debugging :-) */ + int debug; + long max_cert_list; + int first_packet; + + /* Expect OCSP CertificateStatus message */ + int tlsext_status_expected; + /* OCSP status request only */ + STACK_OF(OCSP_RESPID) *tlsext_ocsp_ids; + X509_EXTENSIONS *tlsext_ocsp_exts; + + /* OCSP response received or to be sent */ + unsigned char *tlsext_ocsp_resp; + size_t tlsext_ocsp_resp_len; + + /* RFC4507 session ticket expected to be received or sent */ + int tlsext_ticket_expected; + + size_t tlsext_ecpointformatlist_length; + uint8_t *tlsext_ecpointformatlist; /* our list */ + size_t tlsext_supportedgroups_length; + uint16_t *tlsext_supportedgroups; /* our list */ + + /* TLS Session Ticket extension override */ + TLS_SESSION_TICKET_EXT *tlsext_session_ticket; + + STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles; /* What we'll do */ + const SRTP_PROTECTION_PROFILE *srtp_profile; /* What's been chosen */ + + int renegotiate;/* 1 if we are renegotiating. + * 2 if we are a server and are inside a handshake + * (i.e. not just sending a HelloRequest) */ + + int rstate; /* where we are when reading */ + + int mac_packet; + + int empty_record_count; + + size_t num_tickets; /* Unused, for OpenSSL compatibility */ +}; + +typedef struct ssl3_record_internal_st { + int type; /* type of record */ + unsigned int length; /* How many bytes available */ + unsigned int padding_length; /* Number of padding bytes. */ + unsigned int off; /* read/write offset into 'buf' */ + unsigned char *data; /* pointer to the record data */ + unsigned char *input; /* where the decode bytes are */ + uint16_t epoch; /* epoch number, needed by DTLS1 */ + unsigned char seq_num[8]; /* sequence number, needed by DTLS1 */ +} SSL3_RECORD_INTERNAL; + +typedef struct ssl3_buffer_internal_st { + unsigned char *buf; /* at least SSL3_RT_MAX_PACKET_SIZE bytes, + * see ssl3_setup_buffers() */ + size_t len; /* buffer size */ + int offset; /* where to 'copy from' */ + int left; /* how many bytes left */ +} SSL3_BUFFER_INTERNAL; + +typedef struct ssl3_state_st { + long flags; + + unsigned char server_random[SSL3_RANDOM_SIZE]; + unsigned char client_random[SSL3_RANDOM_SIZE]; + + SSL3_BUFFER_INTERNAL rbuf; /* read IO goes into here */ + SSL3_BUFFER_INTERNAL wbuf; /* write IO goes into here */ + + SSL3_RECORD_INTERNAL rrec; /* each decoded record goes in here */ + + struct tls_content *rcontent; /* Content from opened TLS records. */ + + /* we allow one fatal and one warning alert to be outstanding, + * send close alert via the warning alert */ + int alert_dispatch; + unsigned char send_alert[2]; + + /* flags for countermeasure against known-IV weakness */ + int need_empty_fragments; + int empty_fragment_done; + + /* Unprocessed Alert/Handshake protocol data. */ + struct tls_buffer *alert_fragment; + struct tls_buffer *handshake_fragment; + + /* partial write - check the numbers match */ + unsigned int wnum; /* number of bytes sent so far */ + int wpend_tot; /* number bytes written */ + int wpend_type; + int wpend_ret; /* number of bytes submitted */ + const unsigned char *wpend_buf; + + /* Transcript of handshake messages that have been sent and received. */ + struct tls_buffer *handshake_transcript; + + /* Rolling hash of handshake messages. */ + EVP_MD_CTX *handshake_hash; + + /* this is set whenerver we see a change_cipher_spec message + * come in when we are not looking for one */ + int change_cipher_spec; + + int warn_alert; + int fatal_alert; + + /* This flag is set when we should renegotiate ASAP, basically when + * there is no more data in the read or write buffers */ + int renegotiate; + int total_renegotiations; + int num_renegotiations; + + int in_read_app_data; + + SSL_HANDSHAKE hs; + + /* Connection binding to prevent renegotiation attacks */ + unsigned char previous_client_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_client_finished_len; + unsigned char previous_server_finished[EVP_MAX_MD_SIZE]; + unsigned char previous_server_finished_len; + int send_connection_binding; /* TODOEKR */ + + /* Set if we saw a Renegotiation Indication extension from our peer. */ + int renegotiate_seen; + + /* + * ALPN information. + * + * In a server these point to the selected ALPN protocol after the + * ClientHello has been processed. In a client these contain the + * protocol that the server selected once the ServerHello has been + * processed. + */ + uint8_t *alpn_selected; + size_t alpn_selected_len; + + /* Contains the QUIC transport params received from our peer. */ + uint8_t *peer_quic_transport_params; + size_t peer_quic_transport_params_len; +} SSL3_STATE; + +/* + * Flag values for enc_flags. + */ + +/* Uses signature algorithms extension. */ +#define SSL_ENC_FLAG_SIGALGS (1 << 1) + +/* Uses SHA256 default PRF. */ +#define SSL_ENC_FLAG_SHA256_PRF (1 << 2) + +/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2. */ +#define SSL_ENC_FLAG_TLS1_2_CIPHERS (1 << 4) + +/* Allow TLS 1.3 ciphersuites only. */ +#define SSL_ENC_FLAG_TLS1_3_CIPHERS (1 << 5) + +#define TLSV1_ENC_FLAGS 0 +#define TLSV1_1_ENC_FLAGS 0 +#define TLSV1_2_ENC_FLAGS (SSL_ENC_FLAG_SIGALGS | \ + SSL_ENC_FLAG_SHA256_PRF | \ + SSL_ENC_FLAG_TLS1_2_CIPHERS) +#define TLSV1_3_ENC_FLAGS (SSL_ENC_FLAG_SIGALGS | \ + SSL_ENC_FLAG_TLS1_3_CIPHERS) + +extern const SSL_CIPHER ssl3_ciphers[]; + +const char *ssl_version_string(int ver); +int ssl_version_set_min(const SSL_METHOD *meth, uint16_t proto_ver, + uint16_t max_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver); +int ssl_version_set_max(const SSL_METHOD *meth, uint16_t proto_ver, + uint16_t min_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver); +int ssl_enabled_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver); +int ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver); +uint16_t ssl_tls_version(uint16_t version); +uint16_t ssl_effective_tls_version(SSL *s); +int ssl_max_supported_version(SSL *s, uint16_t *max_ver); +int ssl_max_legacy_version(SSL *s, uint16_t *max_ver); +int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver); +int ssl_check_version_from_server(SSL *s, uint16_t server_version); +int ssl_legacy_stack_version(SSL *s, uint16_t version); +int ssl_cipher_in_list(STACK_OF(SSL_CIPHER) *ciphers, const SSL_CIPHER *cipher); +int ssl_cipher_allowed_in_tls_version_range(const SSL_CIPHER *cipher, + uint16_t min_ver, uint16_t max_ver); + +const SSL_METHOD *tls_legacy_method(void); +const SSL_METHOD *ssl_get_method(uint16_t version); + +void ssl_clear_cipher_state(SSL *s); +int ssl_clear_bad_session(SSL *s); + +void ssl_info_callback(const SSL *s, int type, int value); +void ssl_msg_callback(SSL *s, int is_write, int content_type, + const void *msg_buf, size_t msg_len); +void ssl_msg_callback_cbs(SSL *s, int is_write, int content_type, CBS *cbs); + +SSL_CERT *ssl_cert_new(void); +SSL_CERT *ssl_cert_dup(SSL_CERT *cert); +void ssl_cert_free(SSL_CERT *c); +SSL_CERT *ssl_get0_cert(SSL_CTX *ctx, SSL *ssl); +int ssl_cert_set0_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain); +int ssl_cert_set1_chain(SSL_CTX *ctx, SSL *ssl, STACK_OF(X509) *chain); +int ssl_cert_add0_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert); +int ssl_cert_add1_chain_cert(SSL_CTX *ctx, SSL *ssl, X509 *cert); + +int ssl_security_default_cb(const SSL *ssl, const SSL_CTX *ctx, int op, + int bits, int nid, void *other, void *ex_data); + +int ssl_security_cipher_check(const SSL *ssl, SSL_CIPHER *cipher); +int ssl_security_shared_cipher(const SSL *ssl, SSL_CIPHER *cipher); +int ssl_security_supported_cipher(const SSL *ssl, SSL_CIPHER *cipher); +int ssl_ctx_security_dh(const SSL_CTX *ctx, DH *dh); +int ssl_security_dh(const SSL *ssl, DH *dh); +int ssl_security_sigalg_check(const SSL *ssl, const EVP_PKEY *pkey); +int ssl_security_tickets(const SSL *ssl); +int ssl_security_version(const SSL *ssl, int version); +int ssl_security_cert(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, + int is_peer, int *out_error); +int ssl_security_cert_chain(const SSL *ssl, STACK_OF(X509) *sk, + X509 *x509, int *out_error); +int ssl_security_shared_group(const SSL *ssl, uint16_t group_id); +int ssl_security_supported_group(const SSL *ssl, uint16_t group_id); + +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int include_ticket); +int ssl_get_new_session(SSL *s, int session); +int ssl_get_prev_session(SSL *s, CBS *session_id, CBS *ext_block, + int *alert); +int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b); +SSL_CIPHER *OBJ_bsearch_ssl_cipher_id(SSL_CIPHER *key, SSL_CIPHER const *base, + int num); +int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *ciphers, CBB *cbb); +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, CBS *cbs); +STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth, + STACK_OF(SSL_CIPHER) **pref, STACK_OF(SSL_CIPHER) *tls13, + const char *rule_str, SSL_CERT *cert); +int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str); +int ssl_merge_cipherlists(STACK_OF(SSL_CIPHER) *cipherlist, + STACK_OF(SSL_CIPHER) *cipherlist_tls13, + STACK_OF(SSL_CIPHER) **out_cipherlist); +void ssl_update_cache(SSL *s, int mode); +int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, + const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size); +int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead); +int ssl_get_handshake_evp_md(SSL *s, const EVP_MD **md); + +int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk); +int ssl_undefined_function(SSL *s); +int ssl_undefined_void_function(void); +int ssl_undefined_const_function(const SSL *s); +SSL_CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); +EVP_PKEY *ssl_get_sign_pkey(SSL *s, const SSL_CIPHER *c, const EVP_MD **pmd, + const struct ssl_sigalg **sap); +size_t ssl_dhe_params_auto_key_bits(SSL *s); +int ssl_cert_type(EVP_PKEY *pkey); +void ssl_set_cert_masks(SSL_CERT *c, const SSL_CIPHER *cipher); +STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s); +int ssl_has_ecc_ciphers(SSL *s); +int ssl_verify_alarm_type(long type); + +int SSL_SESSION_ticket(SSL_SESSION *ss, unsigned char **out, size_t *out_len); + +const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p); +int ssl3_do_write(SSL *s, int type); +int ssl3_send_alert(SSL *s, int level, int desc); +int ssl3_get_req_cert_types(SSL *s, CBB *cbb); +int ssl3_get_message(SSL *s, int st1, int stn, int mt, long max); +int ssl3_num_ciphers(void); +const SSL_CIPHER *ssl3_get_cipher(unsigned int u); +const SSL_CIPHER *ssl3_get_cipher_by_id(unsigned int id); +const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value); +uint16_t ssl3_cipher_get_value(const SSL_CIPHER *c); +int ssl3_renegotiate(SSL *ssl); + +int ssl3_renegotiate_check(SSL *ssl); + +void ssl_force_want_read(SSL *s); + +int ssl3_dispatch_alert(SSL *s); +int ssl3_read_alert(SSL *s); +int ssl3_read_change_cipher_spec(SSL *s); +int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek); +int ssl3_write_bytes(SSL *s, int type, const void *buf, int len); +int ssl3_output_cert_chain(SSL *s, CBB *cbb, SSL_CERT_PKEY *cpk); +SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, STACK_OF(SSL_CIPHER) *clnt, + STACK_OF(SSL_CIPHER) *srvr); +int ssl3_setup_buffers(SSL *s); +int ssl3_setup_init_buffer(SSL *s); +void ssl3_release_init_buffer(SSL *s); +int ssl3_setup_read_buffer(SSL *s); +int ssl3_setup_write_buffer(SSL *s); +void ssl3_release_buffer(SSL3_BUFFER_INTERNAL *b); +void ssl3_release_read_buffer(SSL *s); +void ssl3_release_write_buffer(SSL *s); +int ssl3_new(SSL *s); +void ssl3_free(SSL *s); +int ssl3_accept(SSL *s); +int ssl3_connect(SSL *s); +int ssl3_read(SSL *s, void *buf, int len); +int ssl3_peek(SSL *s, void *buf, int len); +int ssl3_write(SSL *s, const void *buf, int len); +int ssl3_shutdown(SSL *s); +void ssl3_clear(SSL *s); +long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg); +long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg); +long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp)(void)); +long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp)(void)); +int ssl3_pending(const SSL *s); + +int ssl3_handshake_msg_hdr_len(SSL *s); +int ssl3_handshake_msg_start(SSL *s, CBB *handshake, CBB *body, + uint8_t msg_type); +int ssl3_handshake_msg_finish(SSL *s, CBB *handshake); +int ssl3_handshake_write(SSL *s); +int ssl3_record_write(SSL *s, int type); + +int ssl3_do_change_cipher_spec(SSL *ssl); + +int ssl3_packet_read(SSL *s, int plen); +int ssl3_packet_extend(SSL *s, int plen); +int ssl_server_legacy_first_packet(SSL *s); +int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, + unsigned int len); + +int ssl_kex_generate_dhe(DH *dh, DH *dh_params); +int ssl_kex_generate_dhe_params_auto(DH *dh, size_t key_len); +int ssl_kex_params_dhe(DH *dh, CBB *cbb); +int ssl_kex_public_dhe(DH *dh, CBB *cbb); +int ssl_kex_peer_params_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_params); +int ssl_kex_peer_public_dhe(DH *dh, CBS *cbs, int *decode_error, + int *invalid_key); +int ssl_kex_derive_dhe(DH *dh, DH *dh_peer, + uint8_t **shared_key, size_t *shared_key_len); + +int ssl_kex_dummy_ecdhe_x25519(EVP_PKEY *pkey); +int ssl_kex_generate_ecdhe_ecp(EC_KEY *ecdh, int nid); +int ssl_kex_public_ecdhe_ecp(EC_KEY *ecdh, CBB *cbb); +int ssl_kex_peer_public_ecdhe_ecp(EC_KEY *ecdh, int nid, CBS *cbs); +int ssl_kex_derive_ecdhe_ecp(EC_KEY *ecdh, EC_KEY *ecdh_peer, + uint8_t **shared_key, size_t *shared_key_len); + +int tls1_new(SSL *s); +void tls1_free(SSL *s); +void tls1_clear(SSL *s); + +int ssl_init_wbio_buffer(SSL *s, int push); +void ssl_free_wbio_buffer(SSL *s); + +int tls1_transcript_hash_init(SSL *s); +int tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len); +int tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len, + size_t *outlen); +void tls1_transcript_hash_free(SSL *s); + +int tls1_transcript_init(SSL *s); +void tls1_transcript_free(SSL *s); +void tls1_transcript_reset(SSL *s); +int tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len); +int tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len); +void tls1_transcript_freeze(SSL *s); +void tls1_transcript_unfreeze(SSL *s); +int tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len); + +int tls1_PRF(SSL *s, const unsigned char *secret, size_t secret_len, + const void *seed1, size_t seed1_len, const void *seed2, size_t seed2_len, + const void *seed3, size_t seed3_len, const void *seed4, size_t seed4_len, + const void *seed5, size_t seed5_len, unsigned char *out, size_t out_len); + +void tls1_cleanup_key_block(SSL *s); +int tls1_change_read_cipher_state(SSL *s); +int tls1_change_write_cipher_state(SSL *s); +int tls1_setup_key_block(SSL *s); +int tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len); +int ssl_ok(SSL *s); + +int tls12_derive_finished(SSL *s); +int tls12_derive_peer_finished(SSL *s); +int tls12_derive_master_secret(SSL *s, uint8_t *premaster_secret, + size_t premaster_secret_len); + +int ssl_using_ecc_cipher(SSL *s); +int ssl_check_srvr_ecc_cert_and_alg(SSL *s, X509 *x); + +void tls1_get_formatlist(const SSL *s, int client_formats, + const uint8_t **pformats, size_t *pformatslen); +void tls1_get_group_list(const SSL *s, int client_groups, + const uint16_t **pgroups, size_t *pgroupslen); + +int tls1_set_groups(uint16_t **out_group_ids, size_t *out_group_ids_len, + const int *groups, size_t ngroups); +int tls1_set_group_list(uint16_t **out_group_ids, size_t *out_group_ids_len, + const char *groups); + +int tls1_ec_group_id2nid(uint16_t group_id, int *out_nid); +int tls1_ec_group_id2bits(uint16_t group_id, int *out_bits); +int tls1_ec_nid2group_id(int nid, uint16_t *out_group_id); +int tls1_check_group(SSL *s, uint16_t group_id); +int tls1_count_shared_groups(const SSL *ssl, size_t *out_count); +int tls1_get_shared_group_by_index(const SSL *ssl, size_t index, int *out_nid); +int tls1_get_supported_group(const SSL *s, int *out_nid); + +int ssl_check_clienthello_tlsext_early(SSL *s); +int ssl_check_clienthello_tlsext_late(SSL *s); +int ssl_check_serverhello_tlsext(SSL *s); + +#define TLS1_TICKET_FATAL_ERROR -1 +#define TLS1_TICKET_NONE 0 +#define TLS1_TICKET_EMPTY 1 +#define TLS1_TICKET_NOT_DECRYPTED 2 +#define TLS1_TICKET_DECRYPTED 3 + +int tls1_process_ticket(SSL *s, CBS *ext_block, int *alert, SSL_SESSION **ret); + +int tls1_check_ec_server_key(SSL *s); + +/* s3_cbc.c */ +void ssl3_cbc_copy_mac(unsigned char *out, const SSL3_RECORD_INTERNAL *rec, + unsigned int md_size, unsigned int orig_len); +int ssl3_cbc_remove_padding(SSL3_RECORD_INTERNAL *rec, unsigned int eiv_len, + unsigned int mac_size); +char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx); +int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, unsigned char *md_out, + size_t *md_out_size, const unsigned char header[13], + const unsigned char *data, size_t data_plus_mac_size, + size_t data_plus_mac_plus_padding_size, const unsigned char *mac_secret, + unsigned int mac_secret_length); +int SSL_state_func_code(int _state); + +#define SSLerror(s, r) SSL_error_internal(s, r, __FILE__, __LINE__) +#define SSLerrorx(r) ERR_PUT_error(ERR_LIB_SSL,(0xfff),(r),__FILE__,__LINE__) +void SSL_error_internal(const SSL *s, int r, char *f, int l); + +#ifndef OPENSSL_NO_SRTP + +int srtp_find_profile_by_name(const char *profile_name, + const SRTP_PROTECTION_PROFILE **pptr, unsigned int len); +int srtp_find_profile_by_num(unsigned int profile_num, + const SRTP_PROTECTION_PROFILE **pptr); + +#endif /* OPENSSL_NO_SRTP */ + +int tls_process_peer_certs(SSL *s, STACK_OF(X509) *peer_certs); + +__END_HIDDEN_DECLS + +#endif /* !HEADER_SSL_LOCL_H */ diff --git a/ssl/ssl_methods.c b/ssl/ssl_methods.c new file mode 100644 index 0000000..ca80da6 --- /dev/null +++ b/ssl/ssl_methods.c @@ -0,0 +1,569 @@ +/* $OpenBSD: ssl_methods.c,v 1.31 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include "dtls_local.h" +#include "ssl_local.h" +#include "tls13_internal.h" + +static const SSL_METHOD DTLS_method_data = { + .dtls = 1, + .server = 1, + .version = DTLS1_2_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +static const SSL_METHOD DTLS_client_method_data = { + .dtls = 1, + .server = 0, + .version = DTLS1_2_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +static const SSL_METHOD DTLSv1_method_data = { + .dtls = 1, + .server = 1, + .version = DTLS1_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_1_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_1_ENC_FLAGS, +}; + +static const SSL_METHOD DTLSv1_client_method_data = { + .dtls = 1, + .server = 0, + .version = DTLS1_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_1_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_1_ENC_FLAGS, +}; + +static const SSL_METHOD DTLSv1_2_method_data = { + .dtls = 1, + .server = 1, + .version = DTLS1_2_VERSION, + .min_tls_version = TLS1_2_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +static const SSL_METHOD DTLSv1_2_client_method_data = { + .dtls = 1, + .server = 0, + .version = DTLS1_2_VERSION, + .min_tls_version = TLS1_2_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = dtls1_new, + .ssl_clear = dtls1_clear, + .ssl_free = dtls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = dtls1_read_bytes, + .ssl_write_bytes = dtls1_write_app_data_bytes, + .get_cipher = dtls1_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +const SSL_METHOD * +DTLSv1_client_method(void) +{ + return &DTLSv1_client_method_data; +} +LSSL_ALIAS(DTLSv1_client_method); + +const SSL_METHOD * +DTLSv1_method(void) +{ + return &DTLSv1_method_data; +} +LSSL_ALIAS(DTLSv1_method); + +const SSL_METHOD * +DTLSv1_server_method(void) +{ + return &DTLSv1_method_data; +} +LSSL_ALIAS(DTLSv1_server_method); + +const SSL_METHOD * +DTLSv1_2_client_method(void) +{ + return &DTLSv1_2_client_method_data; +} +LSSL_ALIAS(DTLSv1_2_client_method); + +const SSL_METHOD * +DTLSv1_2_method(void) +{ + return &DTLSv1_2_method_data; +} +LSSL_ALIAS(DTLSv1_2_method); + +const SSL_METHOD * +DTLSv1_2_server_method(void) +{ + return &DTLSv1_2_method_data; +} +LSSL_ALIAS(DTLSv1_2_server_method); + +const SSL_METHOD * +DTLS_client_method(void) +{ + return &DTLS_client_method_data; +} +LSSL_ALIAS(DTLS_client_method); + +const SSL_METHOD * +DTLS_method(void) +{ + return &DTLS_method_data; +} +LSSL_ALIAS(DTLS_method); + +const SSL_METHOD * +DTLS_server_method(void) +{ + return &DTLS_method_data; +} +LSSL_ALIAS(DTLS_server_method); + +static const SSL_METHOD TLS_method_data = { + .dtls = 0, + .server = 1, + .version = TLS1_3_VERSION, + .min_tls_version = TLS1_VERSION, + .max_tls_version = TLS1_3_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = tls13_legacy_accept, + .ssl_connect = tls13_legacy_connect, + .ssl_shutdown = tls13_legacy_shutdown, + .ssl_renegotiate = ssl_undefined_function, + .ssl_renegotiate_check = ssl_ok, + .ssl_pending = tls13_legacy_pending, + .ssl_read_bytes = tls13_legacy_read_bytes, + .ssl_write_bytes = tls13_legacy_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_3_ENC_FLAGS, +}; + +static const SSL_METHOD TLS_legacy_method_data = { + .dtls = 0, + .server = 1, + .version = TLS1_2_VERSION, + .min_tls_version = TLS1_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl_undefined_function, + .ssl_renegotiate_check = ssl_ok, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +static const SSL_METHOD TLS_client_method_data = { + .dtls = 0, + .server = 0, + .version = TLS1_3_VERSION, + .min_tls_version = TLS1_VERSION, + .max_tls_version = TLS1_3_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = tls13_legacy_accept, + .ssl_connect = tls13_legacy_connect, + .ssl_shutdown = tls13_legacy_shutdown, + .ssl_renegotiate = ssl_undefined_function, + .ssl_renegotiate_check = ssl_ok, + .ssl_pending = tls13_legacy_pending, + .ssl_read_bytes = tls13_legacy_read_bytes, + .ssl_write_bytes = tls13_legacy_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_3_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_method_data = { + .dtls = 0, + .server = 1, + .version = TLS1_VERSION, + .min_tls_version = TLS1_VERSION, + .max_tls_version = TLS1_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_client_method_data = { + .dtls = 0, + .server = 0, + .version = TLS1_VERSION, + .min_tls_version = TLS1_VERSION, + .max_tls_version = TLS1_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_1_method_data = { + .dtls = 0, + .server = 1, + .version = TLS1_1_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_1_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_1_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_1_client_method_data = { + .dtls = 0, + .server = 0, + .version = TLS1_1_VERSION, + .min_tls_version = TLS1_1_VERSION, + .max_tls_version = TLS1_1_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_1_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_2_method_data = { + .dtls = 0, + .server = 1, + .version = TLS1_2_VERSION, + .min_tls_version = TLS1_2_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl3_accept, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +static const SSL_METHOD TLSv1_2_client_method_data = { + .dtls = 0, + .server = 0, + .version = TLS1_2_VERSION, + .min_tls_version = TLS1_2_VERSION, + .max_tls_version = TLS1_2_VERSION, + .ssl_new = tls1_new, + .ssl_clear = tls1_clear, + .ssl_free = tls1_free, + .ssl_accept = ssl_undefined_function, + .ssl_connect = ssl3_connect, + .ssl_shutdown = ssl3_shutdown, + .ssl_renegotiate = ssl3_renegotiate, + .ssl_renegotiate_check = ssl3_renegotiate_check, + .ssl_pending = ssl3_pending, + .ssl_read_bytes = ssl3_read_bytes, + .ssl_write_bytes = ssl3_write_bytes, + .get_cipher = ssl3_get_cipher, + .enc_flags = TLSV1_2_ENC_FLAGS, +}; + +const SSL_METHOD * +TLS_client_method(void) +{ + return (&TLS_client_method_data); +} +LSSL_ALIAS(TLS_client_method); + +const SSL_METHOD * +TLS_method(void) +{ + return (&TLS_method_data); +} +LSSL_ALIAS(TLS_method); + +const SSL_METHOD * +TLS_server_method(void) +{ + return TLS_method(); +} +LSSL_ALIAS(TLS_server_method); + +const SSL_METHOD * +tls_legacy_method(void) +{ + return (&TLS_legacy_method_data); +} + +const SSL_METHOD * +SSLv23_client_method(void) +{ + return TLS_client_method(); +} +LSSL_ALIAS(SSLv23_client_method); + +const SSL_METHOD * +SSLv23_method(void) +{ + return TLS_method(); +} +LSSL_ALIAS(SSLv23_method); + +const SSL_METHOD * +SSLv23_server_method(void) +{ + return TLS_method(); +} +LSSL_ALIAS(SSLv23_server_method); + +const SSL_METHOD * +TLSv1_client_method(void) +{ + return (&TLSv1_client_method_data); +} +LSSL_ALIAS(TLSv1_client_method); + +const SSL_METHOD * +TLSv1_method(void) +{ + return (&TLSv1_method_data); +} +LSSL_ALIAS(TLSv1_method); + +const SSL_METHOD * +TLSv1_server_method(void) +{ + return (&TLSv1_method_data); +} +LSSL_ALIAS(TLSv1_server_method); + +const SSL_METHOD * +TLSv1_1_client_method(void) +{ + return (&TLSv1_1_client_method_data); +} +LSSL_ALIAS(TLSv1_1_client_method); + +const SSL_METHOD * +TLSv1_1_method(void) +{ + return (&TLSv1_1_method_data); +} +LSSL_ALIAS(TLSv1_1_method); + +const SSL_METHOD * +TLSv1_1_server_method(void) +{ + return (&TLSv1_1_method_data); +} +LSSL_ALIAS(TLSv1_1_server_method); + +const SSL_METHOD * +TLSv1_2_client_method(void) +{ + return (&TLSv1_2_client_method_data); +} +LSSL_ALIAS(TLSv1_2_client_method); + +const SSL_METHOD * +TLSv1_2_method(void) +{ + return (&TLSv1_2_method_data); +} +LSSL_ALIAS(TLSv1_2_method); + +const SSL_METHOD * +TLSv1_2_server_method(void) +{ + return (&TLSv1_2_method_data); +} +LSSL_ALIAS(TLSv1_2_server_method); + +const SSL_METHOD * +ssl_get_method(uint16_t version) +{ + if (version == TLS1_3_VERSION) + return (TLS_method()); + if (version == TLS1_2_VERSION) + return (TLSv1_2_method()); + if (version == TLS1_1_VERSION) + return (TLSv1_1_method()); + if (version == TLS1_VERSION) + return (TLSv1_method()); + if (version == DTLS1_VERSION) + return (DTLSv1_method()); + if (version == DTLS1_2_VERSION) + return (DTLSv1_2_method()); + + return (NULL); +} diff --git a/ssl/ssl_packet.c b/ssl/ssl_packet.c new file mode 100644 index 0000000..70017b4 --- /dev/null +++ b/ssl/ssl_packet.c @@ -0,0 +1,292 @@ +/* $OpenBSD: ssl_packet.c,v 1.15 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2016, 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bytestring.h" +#include "ssl_local.h" + +static int +ssl_is_sslv2_client_hello(CBS *header) +{ + uint16_t record_length; + uint8_t message_type; + CBS cbs; + + CBS_dup(header, &cbs); + + if (!CBS_get_u16(&cbs, &record_length) || + !CBS_get_u8(&cbs, &message_type)) + return 0; + + /* + * The SSLv2 record length field uses variable length (2 or 3 byte) + * encoding. Given the size of a client hello, we expect/require the + * 2-byte form which is indicated by a one in the most significant bit. + */ + if ((record_length & 0x8000) == 0) + return 0; + if ((record_length & ~0x8000) < 3) + return 0; + if (message_type != SSL2_MT_CLIENT_HELLO) + return 0; + + return 1; +} + +static int +ssl_is_sslv3_handshake(CBS *header) +{ + uint16_t record_version; + uint8_t record_type; + CBS cbs; + + CBS_dup(header, &cbs); + + if (!CBS_get_u8(&cbs, &record_type) || + !CBS_get_u16(&cbs, &record_version)) + return 0; + + if (record_type != SSL3_RT_HANDSHAKE) + return 0; + if ((record_version >> 8) != SSL3_VERSION_MAJOR) + return 0; + + return 1; +} + +static int +ssl_convert_sslv2_client_hello(SSL *s) +{ + CBB cbb, handshake, client_hello, cipher_suites, compression, session_id; + CBS cbs, challenge, cipher_specs, session; + uint16_t record_length, client_version, cipher_specs_length; + uint16_t session_id_length, challenge_length; + unsigned char *client_random = NULL, *data = NULL; + size_t data_len, pad_len, len; + uint32_t cipher_spec; + uint8_t message_type; + unsigned char *pad; + int ret = -1; + int n; + + memset(&cbb, 0, sizeof(cbb)); + + CBS_init(&cbs, s->packet, SSL3_RT_HEADER_LENGTH); + + if (!CBS_get_u16(&cbs, &record_length) || + !CBS_get_u8(&cbs, &message_type) || + !CBS_get_u16(&cbs, &client_version)) + return -1; + + /* + * The SSLv2 record length field uses variable length (2 or 3 byte) + * encoding. Given the size of a client hello, we expect/require the + * 2-byte form which is indicated by a one in the most significant bit. + * Also note that the record length value does not include the bytes + * used for the record length field. + */ + if ((record_length & 0x8000) == 0) + return -1; + record_length &= ~0x8000; + if (record_length < SSL3_RT_HEADER_LENGTH - 2) + return -1; + if (message_type != SSL2_MT_CLIENT_HELLO) + return -1; + + if (record_length < 9) { + SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH); + return -1; + } + if (record_length > 4096) { + SSLerror(s, SSL_R_RECORD_TOO_LARGE); + return -1; + } + + n = ssl3_packet_extend(s, record_length + 2); + if (n != record_length + 2) + return n; + + tls1_transcript_record(s, s->packet + 2, + s->packet_length - 2); + s->mac_packet = 0; + + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, + s->packet + 2, s->packet_length - 2, s, + s->msg_callback_arg); + + /* Decode the SSLv2 record containing the client hello. */ + CBS_init(&cbs, s->packet, s->packet_length); + + if (!CBS_get_u16(&cbs, &record_length)) + return -1; + if (!CBS_get_u8(&cbs, &message_type)) + return -1; + if (!CBS_get_u16(&cbs, &client_version)) + return -1; + if (!CBS_get_u16(&cbs, &cipher_specs_length)) + return -1; + if (!CBS_get_u16(&cbs, &session_id_length)) + return -1; + if (!CBS_get_u16(&cbs, &challenge_length)) + return -1; + if (!CBS_get_bytes(&cbs, &cipher_specs, cipher_specs_length)) + return -1; + if (!CBS_get_bytes(&cbs, &session, session_id_length)) + return -1; + if (!CBS_get_bytes(&cbs, &challenge, challenge_length)) + return -1; + if (CBS_len(&cbs) != 0) { + SSLerror(s, SSL_R_RECORD_LENGTH_MISMATCH); + return -1; + } + + /* + * Convert SSLv2 challenge to SSLv3/TLS client random, by truncating or + * left-padding with zero bytes. + */ + if ((client_random = malloc(SSL3_RANDOM_SIZE)) == NULL) + goto err; + if (!CBB_init_fixed(&cbb, client_random, SSL3_RANDOM_SIZE)) + goto err; + if ((len = CBS_len(&challenge)) > SSL3_RANDOM_SIZE) + len = SSL3_RANDOM_SIZE; + pad_len = SSL3_RANDOM_SIZE - len; + if (!CBB_add_space(&cbb, &pad, pad_len)) + goto err; + memset(pad, 0, pad_len); + if (!CBB_add_bytes(&cbb, CBS_data(&challenge), len)) + goto err; + if (!CBB_finish(&cbb, NULL, NULL)) + goto err; + + /* Build SSLv3/TLS record with client hello. */ + if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE)) + goto err; + if (!CBB_add_u16(&cbb, 0x0301)) + goto err; + if (!CBB_add_u16_length_prefixed(&cbb, &handshake)) + goto err; + if (!CBB_add_u8(&handshake, SSL3_MT_CLIENT_HELLO)) + goto err; + if (!CBB_add_u24_length_prefixed(&handshake, &client_hello)) + goto err; + if (!CBB_add_u16(&client_hello, client_version)) + goto err; + if (!CBB_add_bytes(&client_hello, client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBB_add_u8_length_prefixed(&client_hello, &session_id)) + goto err; + if (!CBB_add_u16_length_prefixed(&client_hello, &cipher_suites)) + goto err; + while (CBS_len(&cipher_specs) > 0) { + if (!CBS_get_u24(&cipher_specs, &cipher_spec)) + goto err; + if ((cipher_spec & 0xff0000) != 0) + continue; + if (!CBB_add_u16(&cipher_suites, cipher_spec & 0xffff)) + goto err; + } + if (!CBB_add_u8_length_prefixed(&client_hello, &compression)) + goto err; + if (!CBB_add_u8(&compression, 0)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (data_len > s->s3->rbuf.len) + goto err; + + s->packet = s->s3->rbuf.buf; + s->packet_length = data_len; + memcpy(s->packet, data, data_len); + ret = 1; + + err: + CBB_cleanup(&cbb); + free(client_random); + free(data); + + return (ret); +} + +/* + * Potentially do legacy processing on the first packet received by a TLS + * server. We return 1 if we want SSLv3/TLS record processing to continue + * normally, otherwise we must set an SSLerr and return -1. + */ +int +ssl_server_legacy_first_packet(SSL *s) +{ + uint16_t min_version; + const char *data; + CBS header; + + if (SSL_is_dtls(s)) + return 1; + + CBS_init(&header, s->packet, SSL3_RT_HEADER_LENGTH); + + if (ssl_is_sslv3_handshake(&header) == 1) + return 1; + + /* Only continue if this is not a version locked method. */ + if (s->method->min_tls_version == s->method->max_tls_version) + return 1; + + if (ssl_is_sslv2_client_hello(&header) == 1) { + /* Only permit SSLv2 client hellos if TLSv1.0 is enabled. */ + if (ssl_enabled_tls_version_range(s, &min_version, NULL) != 1) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + return -1; + } + if (min_version > TLS1_VERSION) + return 1; + + if (ssl_convert_sslv2_client_hello(s) != 1) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + return -1; + } + + return 1; + } + + /* Ensure that we have SSL3_RT_HEADER_LENGTH (5 bytes) of the packet. */ + if (CBS_len(&header) != SSL3_RT_HEADER_LENGTH) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + data = (const char *)CBS_data(&header); + + /* Is this a cleartext protocol? */ + if (strncmp("GET ", data, 4) == 0 || + strncmp("POST ", data, 5) == 0 || + strncmp("HEAD ", data, 5) == 0 || + strncmp("PUT ", data, 4) == 0) { + SSLerror(s, SSL_R_HTTP_REQUEST); + return -1; + } + if (strncmp("CONNE", data, 5) == 0) { + SSLerror(s, SSL_R_HTTPS_PROXY_REQUEST); + return -1; + } + + SSLerror(s, SSL_R_UNKNOWN_PROTOCOL); + + return -1; +} diff --git a/ssl/ssl_pkt.c b/ssl/ssl_pkt.c new file mode 100644 index 0000000..2c33c45 --- /dev/null +++ b/ssl/ssl_pkt.c @@ -0,0 +1,1313 @@ +/* $OpenBSD: ssl_pkt.c,v 1.66 2023/07/11 17:02:47 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include + +#include +#include + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "tls_content.h" + +static int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + unsigned int len); +static int ssl3_get_record(SSL *s); + +/* + * Force a WANT_READ return for certain error conditions where + * we don't want to spin internally. + */ +void +ssl_force_want_read(SSL *s) +{ + BIO *bio; + + bio = SSL_get_rbio(s); + BIO_clear_retry_flags(bio); + BIO_set_retry_read(bio); + + s->rwstate = SSL_READING; +} + +/* + * If extend == 0, obtain new n-byte packet; if extend == 1, increase + * packet by another n bytes. + * The packet will be in the sub-array of s->s3->rbuf.buf specified + * by s->packet and s->packet_length. + * (If s->read_ahead is set, 'max' bytes may be stored in rbuf + * [plus s->packet_length bytes if extend == 1].) + */ +static int +ssl3_read_n(SSL *s, int n, int max, int extend) +{ + SSL3_BUFFER_INTERNAL *rb = &(s->s3->rbuf); + int i, len, left; + size_t align; + unsigned char *pkt; + + if (n <= 0) + return n; + + if (rb->buf == NULL) { + if (!ssl3_setup_read_buffer(s)) + return -1; + } + if (rb->buf == NULL) + return -1; + + left = rb->left; + align = (size_t)rb->buf + SSL3_RT_HEADER_LENGTH; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); + + if (!extend) { + /* start with empty packet ... */ + if (left == 0) + rb->offset = align; + else if (align != 0 && left >= SSL3_RT_HEADER_LENGTH) { + /* check if next packet length is large + * enough to justify payload alignment... */ + pkt = rb->buf + rb->offset; + if (pkt[0] == SSL3_RT_APPLICATION_DATA && + (pkt[3]<<8|pkt[4]) >= 128) { + /* Note that even if packet is corrupted + * and its length field is insane, we can + * only be led to wrong decision about + * whether memmove will occur or not. + * Header values has no effect on memmove + * arguments and therefore no buffer + * overrun can be triggered. */ + memmove(rb->buf + align, pkt, left); + rb->offset = align; + } + } + s->packet = rb->buf + rb->offset; + s->packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + /* For DTLS/UDP reads should not span multiple packets + * because the read operation returns the whole packet + * at once (as long as it fits into the buffer). */ + if (SSL_is_dtls(s)) { + if (left > 0 && n > left) + n = left; + } + + /* if there is enough in the buffer from a previous read, take some */ + if (left >= n) { + s->packet_length += n; + rb->left = left - n; + rb->offset += n; + return (n); + } + + /* else we need to read more data */ + + len = s->packet_length; + pkt = rb->buf + align; + /* Move any available bytes to front of buffer: + * 'len' bytes already pointed to by 'packet', + * 'left' extra ones at the end */ + if (s->packet != pkt) { + /* len > 0 */ + memmove(pkt, s->packet, len + left); + s->packet = pkt; + rb->offset = len + align; + } + + if (n > (int)(rb->len - rb->offset)) { + /* does not happen */ + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (s->read_ahead || SSL_is_dtls(s)) { + if (max < n) + max = n; + if (max > (int)(rb->len - rb->offset)) + max = rb->len - rb->offset; + } else { + /* ignore max parameter */ + max = n; + } + + while (left < n) { + /* Now we have len+left bytes at the front of s->s3->rbuf.buf + * and need to read in more until we have len+n (up to + * len+max if possible) */ + + errno = 0; + if (s->rbio != NULL) { + s->rwstate = SSL_READING; + i = BIO_read(s->rbio, pkt + len + left, max - left); + } else { + SSLerror(s, SSL_R_READ_BIO_NOT_SET); + i = -1; + } + + if (i <= 0) { + rb->left = left; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && + !SSL_is_dtls(s)) { + if (len + left == 0) + ssl3_release_read_buffer(s); + } + return (i); + } + left += i; + + /* + * reads should *never* span multiple packets for DTLS because + * the underlying transport protocol is message oriented as + * opposed to byte oriented as in the TLS case. + */ + if (SSL_is_dtls(s)) { + if (n > left) + n = left; /* makes the while condition false */ + } + } + + /* done reading, now the book-keeping */ + rb->offset += n; + rb->left = left - n; + s->packet_length += n; + s->rwstate = SSL_NOTHING; + + return (n); +} + +int +ssl3_packet_read(SSL *s, int plen) +{ + int n; + + n = ssl3_read_n(s, plen, s->s3->rbuf.len, 0); + if (n <= 0) + return n; + if (s->packet_length < plen) + return s->packet_length; + + return plen; +} + +int +ssl3_packet_extend(SSL *s, int plen) +{ + int rlen, n; + + if (s->packet_length >= plen) + return plen; + rlen = plen - s->packet_length; + + n = ssl3_read_n(s, rlen, rlen, 1); + if (n <= 0) + return n; + if (s->packet_length < plen) + return s->packet_length; + + return plen; +} + +/* Call this to get a new input record. + * It will return <= 0 if more data is needed, normally due to an error + * or non-blocking IO. + * When it finishes, one packet has been decoded and can be found in + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data + * ssl->s3->rrec.length, - number of bytes + */ +/* used only by ssl3_read_bytes */ +static int +ssl3_get_record(SSL *s) +{ + SSL3_BUFFER_INTERNAL *rb = &(s->s3->rbuf); + SSL3_RECORD_INTERNAL *rr = &(s->s3->rrec); + uint8_t alert_desc; + int al, n; + int ret = -1; + + again: + /* check if we have the header */ + if ((s->rstate != SSL_ST_READ_BODY) || + (s->packet_length < SSL3_RT_HEADER_LENGTH)) { + CBS header; + uint16_t len, ssl_version; + uint8_t type; + + n = ssl3_packet_read(s, SSL3_RT_HEADER_LENGTH); + if (n <= 0) + return (n); + + s->mac_packet = 1; + s->rstate = SSL_ST_READ_BODY; + + if (s->server && s->first_packet) { + if ((ret = ssl_server_legacy_first_packet(s)) != 1) + return (ret); + ret = -1; + } + + CBS_init(&header, s->packet, SSL3_RT_HEADER_LENGTH); + + /* Pull apart the header into the SSL3_RECORD_INTERNAL */ + if (!CBS_get_u8(&header, &type) || + !CBS_get_u16(&header, &ssl_version) || + !CBS_get_u16(&header, &len)) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + goto err; + } + + rr->type = type; + rr->length = len; + + /* Lets check version */ + if (!s->first_packet && ssl_version != s->version) { + if ((s->version & 0xFF00) == (ssl_version & 0xFF00) && + !tls12_record_layer_write_protected(s->rl)) { + /* Send back error using their minor version number :-) */ + s->version = ssl_version; + } + SSLerror(s, SSL_R_WRONG_VERSION_NUMBER); + al = SSL_AD_PROTOCOL_VERSION; + goto fatal_err; + } + + if ((ssl_version >> 8) != SSL3_VERSION_MAJOR) { + SSLerror(s, SSL_R_WRONG_VERSION_NUMBER); + goto err; + } + + if (rr->length > rb->len - SSL3_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerror(s, SSL_R_PACKET_LENGTH_TOO_LONG); + goto fatal_err; + } + } + + n = ssl3_packet_extend(s, SSL3_RT_HEADER_LENGTH + rr->length); + if (n <= 0) + return (n); + if (n != SSL3_RT_HEADER_LENGTH + rr->length) + return (n); + + s->rstate = SSL_ST_READ_HEADER; /* set state for later operations */ + + /* + * A full record has now been read from the wire, which now needs + * to be processed. + */ + tls12_record_layer_set_version(s->rl, s->version); + + if (!tls12_record_layer_open_record(s->rl, s->packet, s->packet_length, + s->s3->rcontent)) { + tls12_record_layer_alert(s->rl, &alert_desc); + + if (alert_desc == 0) + goto err; + + if (alert_desc == SSL_AD_RECORD_OVERFLOW) + SSLerror(s, SSL_R_ENCRYPTED_LENGTH_TOO_LONG); + else if (alert_desc == SSL_AD_BAD_RECORD_MAC) + SSLerror(s, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC); + + al = alert_desc; + goto fatal_err; + } + + /* we have pulled in a full packet so zero things */ + s->packet_length = 0; + + if (tls_content_remaining(s->s3->rcontent) == 0) { + /* + * Zero-length fragments are only permitted for application + * data, as per RFC 5246 section 6.2.1. + */ + if (rr->type != SSL3_RT_APPLICATION_DATA) { + SSLerror(s, SSL_R_BAD_LENGTH); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto fatal_err; + } + + tls_content_clear(s->s3->rcontent); + + /* + * CBC countermeasures for known IV weaknesses can legitimately + * insert a single empty record, so we allow ourselves to read + * once past a single empty record without forcing want_read. + */ + if (s->empty_record_count++ > SSL_MAX_EMPTY_RECORDS) { + SSLerror(s, SSL_R_PEER_BEHAVING_BADLY); + return -1; + } + if (s->empty_record_count > 1) { + ssl_force_want_read(s); + return -1; + } + goto again; + } + + s->empty_record_count = 0; + + return (1); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (ret); +} + +/* Call this to write data in records of type 'type' + * It will return <= 0 if not all data has been sent or non-blocking IO. + */ +int +ssl3_write_bytes(SSL *s, int type, const void *buf_, int len) +{ + const unsigned char *buf = buf_; + unsigned int tot, n, nw; + int i; + + if (len < 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + s->rwstate = SSL_NOTHING; + tot = s->s3->wnum; + s->s3->wnum = 0; + + if (SSL_in_init(s) && !s->in_handshake) { + i = s->handshake_func(s); + if (i < 0) + return (i); + if (i == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + if (len < tot) + len = tot; + n = (len - tot); + for (;;) { + if (n > s->max_send_fragment) + nw = s->max_send_fragment; + else + nw = n; + + i = do_ssl3_write(s, type, &(buf[tot]), nw); + if (i <= 0) { + s->s3->wnum = tot; + return i; + } + + if ((i == (int)n) || (type == SSL3_RT_APPLICATION_DATA && + (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) { + /* + * Next chunk of data should get another prepended + * empty fragment in ciphersuites with known-IV + * weakness. + */ + s->s3->empty_fragment_done = 0; + + return tot + i; + } + + n -= i; + tot += i; + } +} + +static int +do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) +{ + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); + SSL_SESSION *sess = s->session; + int need_empty_fragment = 0; + size_t align, out_len; + CBB cbb; + int ret; + + memset(&cbb, 0, sizeof(cbb)); + + if (wb->buf == NULL) + if (!ssl3_setup_write_buffer(s)) + return -1; + + /* + * First check if there is a SSL3_BUFFER_INTERNAL still being written + * out. This will happen with non blocking IO. + */ + if (wb->left != 0) + return (ssl3_write_pending(s, type, buf, len)); + + /* If we have an alert to send, let's send it. */ + if (s->s3->alert_dispatch) { + if ((ret = ssl3_dispatch_alert(s)) <= 0) + return (ret); + /* If it went, fall through and send more stuff. */ + + /* We may have released our buffer, if so get it again. */ + if (wb->buf == NULL) + if (!ssl3_setup_write_buffer(s)) + return -1; + } + + if (len == 0) + return 0; + + /* + * Countermeasure against known-IV weakness in CBC ciphersuites + * (see http://www.openssl.org/~bodo/tls-cbc.txt). Note that this + * is unnecessary for AEAD. + */ + if (sess != NULL && tls12_record_layer_write_protected(s->rl)) { + if (s->s3->need_empty_fragments && + !s->s3->empty_fragment_done && + type == SSL3_RT_APPLICATION_DATA) + need_empty_fragment = 1; + } + + /* + * An extra fragment would be a couple of cipher blocks, which would + * be a multiple of SSL3_ALIGN_PAYLOAD, so if we want to align the real + * payload, then we can just simply pretend we have two headers. + */ + align = (size_t)wb->buf + SSL3_RT_HEADER_LENGTH; + if (need_empty_fragment) + align += SSL3_RT_HEADER_LENGTH; + align = (-align) & (SSL3_ALIGN_PAYLOAD - 1); + wb->offset = align; + + if (!CBB_init_fixed(&cbb, wb->buf + align, wb->len - align)) + goto err; + + tls12_record_layer_set_version(s->rl, s->version); + + if (need_empty_fragment) { + if (!tls12_record_layer_seal_record(s->rl, type, + buf, 0, &cbb)) + goto err; + s->s3->empty_fragment_done = 1; + } + + if (!tls12_record_layer_seal_record(s->rl, type, buf, len, &cbb)) + goto err; + + if (!CBB_finish(&cbb, NULL, &out_len)) + goto err; + + wb->left = out_len; + + /* + * Memorize arguments so that ssl3_write_pending can detect + * bad write retries later. + */ + s->s3->wpend_tot = len; + s->s3->wpend_buf = buf; + s->s3->wpend_type = type; + s->s3->wpend_ret = len; + + /* We now just need to write the buffer. */ + return ssl3_write_pending(s, type, buf, len); + + err: + CBB_cleanup(&cbb); + + return -1; +} + +/* if s->s3->wbuf.left != 0, we need to call this */ +int +ssl3_write_pending(SSL *s, int type, const unsigned char *buf, unsigned int len) +{ + int i; + SSL3_BUFFER_INTERNAL *wb = &(s->s3->wbuf); + + /* XXXX */ + if ((s->s3->wpend_tot > (int)len) || ((s->s3->wpend_buf != buf) && + !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) || + (s->s3->wpend_type != type)) { + SSLerror(s, SSL_R_BAD_WRITE_RETRY); + return (-1); + } + + for (;;) { + errno = 0; + if (s->wbio != NULL) { + s->rwstate = SSL_WRITING; + i = BIO_write(s->wbio, (char *)&(wb->buf[wb->offset]), + (unsigned int)wb->left); + } else { + SSLerror(s, SSL_R_BIO_NOT_SET); + i = -1; + } + if (i == wb->left) { + wb->left = 0; + wb->offset += i; + if (s->mode & SSL_MODE_RELEASE_BUFFERS && + !SSL_is_dtls(s)) + ssl3_release_write_buffer(s); + s->rwstate = SSL_NOTHING; + return (s->s3->wpend_ret); + } else if (i <= 0) { + /* + * For DTLS, just drop it. That's kind of the + * whole point in using a datagram service. + */ + if (SSL_is_dtls(s)) + wb->left = 0; + return (i); + } + wb->offset += i; + wb->left -= i; + } +} + +static ssize_t +ssl3_read_cb(void *buf, size_t n, void *cb_arg) +{ + SSL *s = cb_arg; + + return tls_content_read(s->s3->rcontent, buf, n); +} + +#define SSL3_ALERT_LENGTH 2 + +int +ssl3_read_alert(SSL *s) +{ + uint8_t alert_level, alert_descr; + ssize_t ret; + CBS cbs; + + /* + * TLSv1.2 permits an alert to be fragmented across multiple records or + * for multiple alerts to be be coalesced into a single alert record. + * In the case of DTLS, there is no way to reassemble an alert + * fragmented across multiple records, hence a full alert must be + * available in the record. + */ + if (s->s3->alert_fragment == NULL) { + if ((s->s3->alert_fragment = tls_buffer_new(0)) == NULL) + return -1; + tls_buffer_set_capacity_limit(s->s3->alert_fragment, + SSL3_ALERT_LENGTH); + } + ret = tls_buffer_extend(s->s3->alert_fragment, SSL3_ALERT_LENGTH, + ssl3_read_cb, s); + if (ret <= 0 && ret != TLS_IO_WANT_POLLIN) + return -1; + if (ret != SSL3_ALERT_LENGTH) { + if (SSL_is_dtls(s)) { + SSLerror(s, SSL_R_BAD_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + return 1; + } + + if (!tls_buffer_data(s->s3->alert_fragment, &cbs)) + return -1; + + ssl_msg_callback_cbs(s, 0, SSL3_RT_ALERT, &cbs); + + if (!CBS_get_u8(&cbs, &alert_level)) + return -1; + if (!CBS_get_u8(&cbs, &alert_descr)) + return -1; + + tls_buffer_free(s->s3->alert_fragment); + s->s3->alert_fragment = NULL; + + ssl_info_callback(s, SSL_CB_READ_ALERT, + (alert_level << 8) | alert_descr); + + if (alert_level == SSL3_AL_WARNING) { + s->s3->warn_alert = alert_descr; + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + return 0; + } + /* We requested renegotiation and the peer rejected it. */ + if (alert_descr == SSL_AD_NO_RENEGOTIATION) { + SSLerror(s, SSL_R_NO_RENEGOTIATION); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + return -1; + } + } else if (alert_level == SSL3_AL_FATAL) { + s->rwstate = SSL_NOTHING; + s->s3->fatal_alert = alert_descr; + SSLerror(s, SSL_AD_REASON_OFFSET + alert_descr); + ERR_asprintf_error_data("SSL alert number %d", alert_descr); + s->shutdown |= SSL_RECEIVED_SHUTDOWN; + SSL_CTX_remove_session(s->ctx, s->session); + return 0; + } else { + SSLerror(s, SSL_R_UNKNOWN_ALERT_TYPE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + return 1; +} + +int +ssl3_read_change_cipher_spec(SSL *s) +{ + const uint8_t ccs[1] = { SSL3_MT_CCS }; + + /* + * 'Change Cipher Spec' is just a single byte, so we know exactly what + * the record payload has to look like. + */ + if (tls_content_remaining(s->s3->rcontent) != sizeof(ccs)) { + SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + if (!tls_content_equal(s->s3->rcontent, ccs, sizeof(ccs))) { + SSLerror(s, SSL_R_BAD_CHANGE_CIPHER_SPEC); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + return -1; + } + + /* XDTLS: check that epoch is consistent */ + + ssl_msg_callback_cbs(s, 0, SSL3_RT_CHANGE_CIPHER_SPEC, + tls_content_cbs(s->s3->rcontent)); + + /* Check that we have a cipher to change to. */ + if (s->s3->hs.cipher == NULL) { + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* Check that we should be receiving a Change Cipher Spec. */ + if (SSL_is_dtls(s)) { + if (!s->d1->change_cipher_spec_ok) { + /* + * We can't process a CCS now, because previous + * handshake messages are still missing, so just + * drop it. + */ + tls_content_clear(s->s3->rcontent); + return 1; + } + s->d1->change_cipher_spec_ok = 0; + } else { + if ((s->s3->flags & SSL3_FLAGS_CCS_OK) == 0) { + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + } + + tls_content_clear(s->s3->rcontent); + + s->s3->change_cipher_spec = 1; + if (!ssl3_do_change_cipher_spec(s)) + return -1; + + return 1; +} + +static int +ssl3_read_handshake_unexpected(SSL *s) +{ + uint32_t hs_msg_length; + uint8_t hs_msg_type; + ssize_t ssret; + CBS cbs; + int ret; + + /* + * We need four bytes of handshake data so we have a handshake message + * header - this may be in the same record or fragmented across multiple + * records. + */ + if (s->s3->handshake_fragment == NULL) { + if ((s->s3->handshake_fragment = tls_buffer_new(0)) == NULL) + return -1; + tls_buffer_set_capacity_limit(s->s3->handshake_fragment, + SSL3_HM_HEADER_LENGTH); + } + ssret = tls_buffer_extend(s->s3->handshake_fragment, SSL3_HM_HEADER_LENGTH, + ssl3_read_cb, s); + if (ssret <= 0 && ssret != TLS_IO_WANT_POLLIN) + return -1; + if (ssret != SSL3_HM_HEADER_LENGTH) + return 1; + + if (s->in_handshake) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* + * This code currently deals with HelloRequest and ClientHello messages - + * anything else is pushed to the handshake_func. Almost all of this + * belongs in the client/server handshake code. + */ + + /* Parse handshake message header. */ + if (!tls_buffer_data(s->s3->handshake_fragment, &cbs)) + return -1; + if (!CBS_get_u8(&cbs, &hs_msg_type)) + return -1; + if (!CBS_get_u24(&cbs, &hs_msg_length)) + return -1; + + if (hs_msg_type == SSL3_MT_HELLO_REQUEST) { + /* + * Incoming HelloRequest messages should only be received by a + * client. A server may send these at any time - a client should + * ignore the message if received in the middle of a handshake. + * See RFC 5246 sections 7.4 and 7.4.1.1. + */ + if (s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if (hs_msg_length != 0) { + SSLerror(s, SSL_R_BAD_HELLO_REQUEST); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + return -1; + } + + if (!tls_buffer_data(s->s3->handshake_fragment, &cbs)) + return -1; + ssl_msg_callback_cbs(s, 0, SSL3_RT_HANDSHAKE, &cbs); + + tls_buffer_free(s->s3->handshake_fragment); + s->s3->handshake_fragment = NULL; + + /* + * It should be impossible to hit this, but keep the safety + * harness for now... + */ + if (s->session == NULL || s->session->cipher == NULL) + return 1; + + /* + * Ignore this message if we're currently handshaking, + * renegotiation is already pending or renegotiation is disabled + * via flags. + */ + if (!SSL_is_init_finished(s) || s->s3->renegotiate || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) + return 1; + + if (!ssl3_renegotiate(s)) + return 1; + if (!ssl3_renegotiate_check(s)) + return 1; + + } else if (hs_msg_type == SSL3_MT_CLIENT_HELLO) { + /* + * Incoming ClientHello messages should only be received by a + * server. A client may send these in response to server + * initiated renegotiation (HelloRequest) or in order to + * initiate renegotiation by the client. See RFC 5246 section + * 7.4.1.2. + */ + if (!s->server) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* + * A client should not be sending a ClientHello unless we're not + * currently handshaking. + */ + if (!SSL_is_init_finished(s)) { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((s->options & SSL_OP_NO_CLIENT_RENEGOTIATION) != 0) { + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_NO_RENEGOTIATION); + return -1; + } + + if (s->session == NULL || s->session->cipher == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* Client requested renegotiation but it is not permitted. */ + if (!s->s3->send_connection_binding || + (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) != 0) { + ssl3_send_alert(s, SSL3_AL_WARNING, + SSL_AD_NO_RENEGOTIATION); + return 1; + } + + s->s3->hs.state = SSL_ST_ACCEPT; + s->renegotiate = 1; + s->new_session = 1; + + } else { + SSLerror(s, SSL_R_UNEXPECTED_MESSAGE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if ((ret = s->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + + if (!(s->mode & SSL_MODE_AUTO_RETRY)) { + if (s->s3->rbuf.left == 0) { + ssl_force_want_read(s); + return -1; + } + } + + /* + * We either finished a handshake or ignored the request, now try again + * to obtain the (application) data we were asked for. + */ + return 1; +} + +/* Return up to 'len' payload bytes received in 'type' records. + * 'type' is one of the following: + * + * - SSL3_RT_HANDSHAKE (when ssl3_get_message calls us) + * - SSL3_RT_APPLICATION_DATA (when ssl3_read calls us) + * - 0 (during a shutdown, no data has to be returned) + * + * If we don't have stored data to work from, read a SSL/TLS record first + * (possibly multiple records if we still don't have anything to return). + * + * This function must handle any surprises the peer may have for us, such as + * Alert records (e.g. close_notify), ChangeCipherSpec records (not really + * a surprise, but handled as if it were), or renegotiation requests. + * Also if record payloads contain fragments too small to process, we store + * them until there is enough for the respective protocol (the record protocol + * may use arbitrary fragmentation and even interleaving): + * Change cipher spec protocol + * just 1 byte needed, no need for keeping anything stored + * Alert protocol + * 2 bytes needed (AlertLevel, AlertDescription) + * Handshake protocol + * 4 bytes needed (HandshakeType, uint24 length) -- we just have + * to detect unexpected Client Hello and Hello Request messages + * here, anything else is handled by higher layers + * Application data protocol + * none of our business + */ +int +ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) +{ + int rrcount = 0; + ssize_t ssret; + int ret; + + if (s->s3->rbuf.buf == NULL) { + if (!ssl3_setup_read_buffer(s)) + return -1; + } + + if (s->s3->rcontent == NULL) { + if ((s->s3->rcontent = tls_content_new()) == NULL) + return -1; + } + + if (len < 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (type != 0 && type != SSL3_RT_APPLICATION_DATA && + type != SSL3_RT_HANDSHAKE) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + if (peek && type != SSL3_RT_APPLICATION_DATA) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (type == SSL3_RT_HANDSHAKE && + s->s3->handshake_fragment != NULL && + tls_buffer_remaining(s->s3->handshake_fragment) > 0) { + ssize_t ssn; + + if ((ssn = tls_buffer_read(s->s3->handshake_fragment, buf, + len)) <= 0) + return -1; + + if (tls_buffer_remaining(s->s3->handshake_fragment) == 0) { + tls_buffer_free(s->s3->handshake_fragment); + s->s3->handshake_fragment = NULL; + } + + return (int)ssn; + } + + if (SSL_in_init(s) && !s->in_handshake) { + if ((ret = s->handshake_func(s)) < 0) + return ret; + if (ret == 0) { + SSLerror(s, SSL_R_SSL_HANDSHAKE_FAILURE); + return -1; + } + } + + start: + /* + * Do not process more than three consecutive records, otherwise the + * peer can cause us to loop indefinitely. Instead, return with an + * SSL_ERROR_WANT_READ so the caller can choose when to handle further + * processing. In the future, the total number of non-handshake and + * non-application data records per connection should probably also be + * limited... + */ + if (rrcount++ >= 3) { + ssl_force_want_read(s); + return -1; + } + + s->rwstate = SSL_NOTHING; + + if (tls_content_remaining(s->s3->rcontent) == 0) { + if ((ret = ssl3_get_record(s)) <= 0) + return ret; + } + + /* We now have a packet which can be read and processed. */ + + if (s->s3->change_cipher_spec && + tls_content_type(s->s3->rcontent) != SSL3_RT_HANDSHAKE) { + SSLerror(s, SSL_R_DATA_BETWEEN_CCS_AND_FINISHED); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + /* + * If the other end has shut down, throw anything we read away (even in + * 'peek' mode). + */ + if (s->shutdown & SSL_RECEIVED_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + return 0; + } + + /* SSL3_RT_APPLICATION_DATA or SSL3_RT_HANDSHAKE */ + if (tls_content_type(s->s3->rcontent) == type) { + /* + * Make sure that we are not getting application data when we + * are doing a handshake for the first time. + */ + if (SSL_in_init(s) && type == SSL3_RT_APPLICATION_DATA && + !tls12_record_layer_read_protected(s->rl)) { + SSLerror(s, SSL_R_APP_DATA_IN_HANDSHAKE); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + if (len <= 0) + return len; + + if (peek) { + ssret = tls_content_peek(s->s3->rcontent, buf, len); + } else { + ssret = tls_content_read(s->s3->rcontent, buf, len); + } + if (ssret < INT_MIN || ssret > INT_MAX) + return -1; + if (ssret < 0) + return (int)ssret; + + if (tls_content_remaining(s->s3->rcontent) == 0) { + s->rstate = SSL_ST_READ_HEADER; + + if (s->mode & SSL_MODE_RELEASE_BUFFERS && + s->s3->rbuf.left == 0) + ssl3_release_read_buffer(s); + } + + return ssret; + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_ALERT) { + if ((ret = ssl3_read_alert(s)) <= 0) + return ret; + goto start; + } + + if (s->shutdown & SSL_SENT_SHUTDOWN) { + s->rwstate = SSL_NOTHING; + tls_content_clear(s->s3->rcontent); + s->s3->rrec.length = 0; + return 0; + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_APPLICATION_DATA) { + /* + * At this point, we were expecting handshake data, but have + * application data. If the library was running inside + * ssl3_read() (i.e. in_read_app_data is set) and it makes + * sense to read application data at this point (session + * renegotiation not yet started), we will indulge it. + */ + if (s->s3->in_read_app_data != 0 && + s->s3->total_renegotiations != 0 && + (((s->s3->hs.state & SSL_ST_CONNECT) && + (s->s3->hs.state >= SSL3_ST_CW_CLNT_HELLO_A) && + (s->s3->hs.state <= SSL3_ST_CR_SRVR_HELLO_A)) || ( + (s->s3->hs.state & SSL_ST_ACCEPT) && + (s->s3->hs.state <= SSL3_ST_SW_HELLO_REQ_A) && + (s->s3->hs.state >= SSL3_ST_SR_CLNT_HELLO_A)))) { + s->s3->in_read_app_data = 2; + return -1; + } else { + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_CHANGE_CIPHER_SPEC) { + if ((ret = ssl3_read_change_cipher_spec(s)) <= 0) + return ret; + goto start; + } + + if (tls_content_type(s->s3->rcontent) == SSL3_RT_HANDSHAKE) { + if ((ret = ssl3_read_handshake_unexpected(s)) <= 0) + return ret; + goto start; + } + + /* + * Unknown record type - TLSv1.2 sends an unexpected message alert while + * earlier versions silently ignore the record. + */ + if (ssl_effective_tls_version(s) <= TLS1_1_VERSION) { + tls_content_clear(s->s3->rcontent); + goto start; + } + SSLerror(s, SSL_R_UNEXPECTED_RECORD); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; +} + +int +ssl3_do_change_cipher_spec(SSL *s) +{ + if (s->s3->hs.tls12.key_block == NULL) { + if (s->session == NULL || s->session->master_key_length == 0) { + /* might happen if dtls1_read_bytes() calls this */ + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + return (0); + } + + s->session->cipher = s->s3->hs.cipher; + if (!tls1_setup_key_block(s)) + return (0); + } + + if (!tls1_change_read_cipher_state(s)) + return (0); + + /* + * We have to record the message digest at this point so we can get it + * before we read the finished message. + */ + if (!tls12_derive_peer_finished(s)) + return (0); + + return (1); +} + +static int +ssl3_write_alert(SSL *s) +{ + if (SSL_is_dtls(s)) + return do_dtls1_write(s, SSL3_RT_ALERT, s->s3->send_alert, + sizeof(s->s3->send_alert)); + + return do_ssl3_write(s, SSL3_RT_ALERT, s->s3->send_alert, + sizeof(s->s3->send_alert)); +} + +int +ssl3_send_alert(SSL *s, int level, int desc) +{ + /* If alert is fatal, remove session from cache. */ + if (level == SSL3_AL_FATAL) + SSL_CTX_remove_session(s->ctx, s->session); + + s->s3->alert_dispatch = 1; + s->s3->send_alert[0] = level; + s->s3->send_alert[1] = desc; + + /* + * If data is still being written out, the alert will be dispatched at + * some point in the future. + */ + if (s->s3->wbuf.left != 0) + return -1; + + return ssl3_dispatch_alert(s); +} + +int +ssl3_dispatch_alert(SSL *s) +{ + int ret; + + s->s3->alert_dispatch = 0; + if ((ret = ssl3_write_alert(s)) <= 0) { + s->s3->alert_dispatch = 1; + return ret; + } + + /* + * Alert sent to BIO. If it is important, flush it now. + * If the message does not get sent due to non-blocking IO, + * we will not worry too much. + */ + if (s->s3->send_alert[0] == SSL3_AL_FATAL) + (void)BIO_flush(s->wbio); + + ssl_msg_callback(s, 1, SSL3_RT_ALERT, s->s3->send_alert, 2); + + ssl_info_callback(s, SSL_CB_WRITE_ALERT, + (s->s3->send_alert[0] << 8) | s->s3->send_alert[1]); + + return ret; +} diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c new file mode 100644 index 0000000..68137bc --- /dev/null +++ b/ssl/ssl_rsa.c @@ -0,0 +1,769 @@ +/* $OpenBSD: ssl_rsa.c,v 1.50 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include + +#include +#include +#include +#include +#include + +#include "ssl_local.h" + +static int ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl, + pem_password_cb **passwd_cb, void **passwd_arg); +static int ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x509); +static int ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey); +static int ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in); +static int ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, + const char *file); + +int +SSL_use_certificate(SSL *ssl, X509 *x) +{ + if (x == NULL) { + SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + return ssl_set_cert(NULL, ssl, x); +} +LSSL_ALIAS(SSL_use_certificate); + +int +SSL_use_certificate_file(SSL *ssl, const char *file, int type) +{ + int j; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerror(ssl, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerror(ssl, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, + ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + SSLerror(ssl, j); + goto end; + } + + ret = SSL_use_certificate(ssl, x); + end: + X509_free(x); + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_use_certificate_file); + +int +SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len) +{ + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + SSLerror(ssl, ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_use_certificate(ssl, x); + X509_free(x); + return (ret); +} +LSSL_ALIAS(SSL_use_certificate_ASN1); + +int +SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) +{ + EVP_PKEY *pkey; + int ret; + + if (rsa == NULL) { + SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + if ((pkey = EVP_PKEY_new()) == NULL) { + SSLerror(ssl, ERR_R_EVP_LIB); + return (0); + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(NULL, ssl, pkey); + EVP_PKEY_free(pkey); + return (ret); +} +LSSL_ALIAS(SSL_use_RSAPrivateKey); + +static int +ssl_set_pkey(SSL_CTX *ctx, SSL *ssl, EVP_PKEY *pkey) +{ + SSL_CERT *c; + int i; + + i = ssl_cert_type(pkey); + if (i < 0) { + SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE); + return (0); + } + + if ((c = ssl_get0_cert(ctx, ssl)) == NULL) + return (0); + + if (c->pkeys[i].x509 != NULL) { + EVP_PKEY *pktmp; + + if ((pktmp = X509_get0_pubkey(c->pkeys[i].x509)) == NULL) + return 0; + + /* + * Callers of EVP_PKEY_copy_parameters() can't distinguish + * errors from the absence of a param_copy() method. So + * pretend it can never fail. + */ + EVP_PKEY_copy_parameters(pktmp, pkey); + + ERR_clear_error(); + + /* + * Don't check the public/private key, this is mostly + * for smart cards. + */ + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA || + !(RSA_flags(EVP_PKEY_get0_RSA(pkey)) & RSA_METHOD_FLAG_NO_CHECK)) { + if (!X509_check_private_key(c->pkeys[i].x509, pkey)) { + X509_free(c->pkeys[i].x509); + c->pkeys[i].x509 = NULL; + return 0; + } + } + } + + EVP_PKEY_free(c->pkeys[i].privatekey); + EVP_PKEY_up_ref(pkey); + c->pkeys[i].privatekey = pkey; + c->key = &(c->pkeys[i]); + + c->valid = 0; + return 1; +} + +int +SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerror(ssl, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerror(ssl, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, + ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else { + SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) { + SSLerror(ssl, j); + goto end; + } + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + end: + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_use_RSAPrivateKey_file); + +int +SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d, long len) +{ + int ret; + RSA *rsa; + + if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) { + SSLerror(ssl, ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_use_RSAPrivateKey(ssl, rsa); + RSA_free(rsa); + return (ret); +} +LSSL_ALIAS(SSL_use_RSAPrivateKey_ASN1); + +int +SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) +{ + int ret; + + if (pkey == NULL) { + SSLerror(ssl, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + ret = ssl_set_pkey(NULL, ssl, pkey); + return (ret); +} +LSSL_ALIAS(SSL_use_PrivateKey); + +int +SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerror(ssl, ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerror(ssl, ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ssl->ctx->default_passwd_callback, + ssl->ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerror(ssl, SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerror(ssl, j); + goto end; + } + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + end: + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_use_PrivateKey_file); + +int +SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const unsigned char *d, long len) +{ + int ret; + EVP_PKEY *pkey; + + if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) { + SSLerror(ssl, ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_use_PrivateKey(ssl, pkey); + EVP_PKEY_free(pkey); + return (ret); +} +LSSL_ALIAS(SSL_use_PrivateKey_ASN1); + +int +SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) +{ + if (x == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + return ssl_set_cert(ctx, NULL, x); +} +LSSL_ALIAS(SSL_CTX_use_certificate); + +static int +ssl_get_password_cb_and_arg(SSL_CTX *ctx, SSL *ssl, + pem_password_cb **passwd_cb, void **passwd_arg) +{ + if (ssl != NULL) + ctx = ssl->ctx; + + *passwd_cb = ctx->default_passwd_callback; + *passwd_arg = ctx->default_passwd_callback_userdata; + + return 1; +} + +static int +ssl_set_cert(SSL_CTX *ctx, SSL *ssl, X509 *x) +{ + SSL_CERT *c; + EVP_PKEY *pkey; + int ssl_err; + int i; + + if (!ssl_security_cert(ctx, ssl, x, 1, &ssl_err)) { + SSLerrorx(ssl_err); + return (0); + } + + if ((c = ssl_get0_cert(ctx, ssl)) == NULL) + return (0); + + pkey = X509_get_pubkey(x); + if (pkey == NULL) { + SSLerrorx(SSL_R_X509_LIB); + return (0); + } + + i = ssl_cert_type(pkey); + if (i < 0) { + SSLerrorx(SSL_R_UNKNOWN_CERTIFICATE_TYPE); + EVP_PKEY_free(pkey); + return (0); + } + + if (c->pkeys[i].privatekey != NULL) { + EVP_PKEY *priv_key = c->pkeys[i].privatekey; + + EVP_PKEY_copy_parameters(pkey, priv_key); + ERR_clear_error(); + + /* + * Don't check the public/private key, this is mostly + * for smart cards. + */ + if (EVP_PKEY_id(priv_key) != EVP_PKEY_RSA || + !(RSA_flags(EVP_PKEY_get0_RSA(priv_key)) & RSA_METHOD_FLAG_NO_CHECK)) { + if (!X509_check_private_key(x, priv_key)) { + /* + * don't fail for a cert/key mismatch, just free + * current private key (when switching to a + * different cert & key, first this function + * should be used, then ssl_set_pkey. + */ + EVP_PKEY_free(c->pkeys[i].privatekey); + c->pkeys[i].privatekey = NULL; + ERR_clear_error(); + } + } + } + + EVP_PKEY_free(pkey); + + X509_free(c->pkeys[i].x509); + X509_up_ref(x); + c->pkeys[i].x509 = x; + c->key = &(c->pkeys[i]); + + c->valid = 0; + return (1); +} + +int +SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type) +{ + int j; + BIO *in; + int ret = 0; + X509 *x = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerrorx(ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + x = d2i_X509_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + x = PEM_read_bio_X509(in, NULL, ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + SSLerrorx(SSL_R_BAD_SSL_FILETYPE); + goto end; + } + + if (x == NULL) { + SSLerrorx(j); + goto end; + } + + ret = SSL_CTX_use_certificate(ctx, x); + end: + X509_free(x); + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_certificate_file); + +int +SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, const unsigned char *d) +{ + X509 *x; + int ret; + + x = d2i_X509(NULL, &d, (long)len); + if (x == NULL) { + SSLerrorx(ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_CTX_use_certificate(ctx, x); + X509_free(x); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_certificate_ASN1); + +int +SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) +{ + int ret; + EVP_PKEY *pkey; + + if (rsa == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + if ((pkey = EVP_PKEY_new()) == NULL) { + SSLerrorx(ERR_R_EVP_LIB); + return (0); + } + + RSA_up_ref(rsa); + EVP_PKEY_assign_RSA(pkey, rsa); + + ret = ssl_set_pkey(ctx, NULL, pkey); + EVP_PKEY_free(pkey); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey); + +int +SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + RSA *rsa = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerrorx(ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + rsa = d2i_RSAPrivateKey_bio(in, NULL); + } else if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + rsa = PEM_read_bio_RSAPrivateKey(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else { + SSLerrorx(SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (rsa == NULL) { + SSLerrorx(j); + goto end; + } + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + end: + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey_file); + +int +SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d, long len) +{ + int ret; + RSA *rsa; + + if ((rsa = d2i_RSAPrivateKey(NULL, &d, (long)len)) == NULL) { + SSLerrorx(ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); + RSA_free(rsa); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_RSAPrivateKey_ASN1); + +int +SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) +{ + if (pkey == NULL) { + SSLerrorx(ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + return ssl_set_pkey(ctx, NULL, pkey); +} +LSSL_ALIAS(SSL_CTX_use_PrivateKey); + +int +SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type) +{ + int j, ret = 0; + BIO *in; + EVP_PKEY *pkey = NULL; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerrorx(ERR_R_SYS_LIB); + goto end; + } + if (type == SSL_FILETYPE_PEM) { + j = ERR_R_PEM_LIB; + pkey = PEM_read_bio_PrivateKey(in, NULL, + ctx->default_passwd_callback, + ctx->default_passwd_callback_userdata); + } else if (type == SSL_FILETYPE_ASN1) { + j = ERR_R_ASN1_LIB; + pkey = d2i_PrivateKey_bio(in, NULL); + } else { + SSLerrorx(SSL_R_BAD_SSL_FILETYPE); + goto end; + } + if (pkey == NULL) { + SSLerrorx(j); + goto end; + } + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + end: + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_PrivateKey_file); + +int +SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const unsigned char *d, + long len) +{ + int ret; + EVP_PKEY *pkey; + + if ((pkey = d2i_PrivateKey(type, NULL, &d, (long)len)) == NULL) { + SSLerrorx(ERR_R_ASN1_LIB); + return (0); + } + + ret = SSL_CTX_use_PrivateKey(ctx, pkey); + EVP_PKEY_free(pkey); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_PrivateKey_ASN1); + + +/* + * Read a bio that contains our certificate in "PEM" format, + * possibly followed by a sequence of CA certificates that should be + * sent to the peer in the Certificate message. + */ +static int +ssl_use_certificate_chain_bio(SSL_CTX *ctx, SSL *ssl, BIO *in) +{ + pem_password_cb *passwd_cb; + void *passwd_arg; + X509 *ca, *x = NULL; + unsigned long err; + int ret = 0; + + if (!ssl_get_password_cb_and_arg(ctx, ssl, &passwd_cb, &passwd_arg)) + goto err; + + if ((x = PEM_read_bio_X509_AUX(in, NULL, passwd_cb, passwd_arg)) == + NULL) { + SSLerrorx(ERR_R_PEM_LIB); + goto err; + } + + if (!ssl_set_cert(ctx, ssl, x)) + goto err; + + if (!ssl_cert_set0_chain(ctx, ssl, NULL)) + goto err; + + /* Process any additional CA certificates. */ + while ((ca = PEM_read_bio_X509(in, NULL, passwd_cb, passwd_arg)) != + NULL) { + if (!ssl_cert_add0_chain_cert(ctx, ssl, ca)) { + X509_free(ca); + goto err; + } + } + + /* When the while loop ends, it's usually just EOF. */ + err = ERR_peek_last_error(); + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + ERR_clear_error(); + ret = 1; + } + + err: + X509_free(x); + + return (ret); +} + +int +ssl_use_certificate_chain_file(SSL_CTX *ctx, SSL *ssl, const char *file) +{ + BIO *in; + int ret = 0; + + in = BIO_new(BIO_s_file()); + if (in == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + goto end; + } + + if (BIO_read_filename(in, file) <= 0) { + SSLerrorx(ERR_R_SYS_LIB); + goto end; + } + + ret = ssl_use_certificate_chain_bio(ctx, ssl, in); + + end: + BIO_free(in); + return (ret); +} + +int +SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file) +{ + return ssl_use_certificate_chain_file(ctx, NULL, file); +} +LSSL_ALIAS(SSL_CTX_use_certificate_chain_file); + +int +SSL_use_certificate_chain_file(SSL *ssl, const char *file) +{ + return ssl_use_certificate_chain_file(NULL, ssl, file); +} +LSSL_ALIAS(SSL_use_certificate_chain_file); + +int +SSL_CTX_use_certificate_chain_mem(SSL_CTX *ctx, void *buf, int len) +{ + BIO *in; + int ret = 0; + + in = BIO_new_mem_buf(buf, len); + if (in == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + goto end; + } + + ret = ssl_use_certificate_chain_bio(ctx, NULL, in); + + end: + BIO_free(in); + return (ret); +} +LSSL_ALIAS(SSL_CTX_use_certificate_chain_mem); diff --git a/ssl/ssl_seclevel.c b/ssl/ssl_seclevel.c new file mode 100644 index 0000000..1869c81 --- /dev/null +++ b/ssl/ssl_seclevel.c @@ -0,0 +1,473 @@ +/* $OpenBSD: ssl_seclevel.c,v 1.27 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2020-2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" + +static int +ssl_security_normalize_level(const SSL_CTX *ctx, const SSL *ssl, int *out_level) +{ + int security_level; + + if (ctx != NULL) + security_level = SSL_CTX_get_security_level(ctx); + else + security_level = SSL_get_security_level(ssl); + + if (security_level < 0) + security_level = 0; + if (security_level > 5) + security_level = 5; + + *out_level = security_level; + + return 1; +} + +static int +ssl_security_level_to_minimum_bits(int security_level, int *out_minimum_bits) +{ + if (security_level < 0) + return 0; + + if (security_level == 0) + *out_minimum_bits = 0; + else if (security_level == 1) + *out_minimum_bits = 80; + else if (security_level == 2) + *out_minimum_bits = 112; + else if (security_level == 3) + *out_minimum_bits = 128; + else if (security_level == 4) + *out_minimum_bits = 192; + else if (security_level >= 5) + *out_minimum_bits = 256; + + return 1; +} + +static int +ssl_security_level_and_minimum_bits(const SSL_CTX *ctx, const SSL *ssl, + int *out_level, int *out_minimum_bits) +{ + int security_level = 0, minimum_bits = 0; + + if (!ssl_security_normalize_level(ctx, ssl, &security_level)) + return 0; + if (!ssl_security_level_to_minimum_bits(security_level, &minimum_bits)) + return 0; + + if (out_level != NULL) + *out_level = security_level; + if (out_minimum_bits != NULL) + *out_minimum_bits = minimum_bits; + + return 1; +} + +static int +ssl_security_secop_cipher(const SSL_CTX *ctx, const SSL *ssl, int bits, + void *arg) +{ + const SSL_CIPHER *cipher = arg; + int security_level, minimum_bits; + + if (!ssl_security_level_and_minimum_bits(ctx, ssl, &security_level, + &minimum_bits)) + return 0; + + if (security_level <= 0) + return 1; + + if (bits < minimum_bits) + return 0; + + /* No unauthenticated ciphersuites. */ + if (cipher->algorithm_auth & SSL_aNULL) + return 0; + + if (cipher->algorithm_mac & SSL_MD5) + return 0; + + if (security_level <= 1) + return 1; + + if (cipher->algorithm_enc & SSL_RC4) + return 0; + + if (security_level <= 2) + return 1; + + /* Security level >= 3 requires a cipher with forward secrecy. */ + if ((cipher->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) == 0 && + cipher->algorithm_ssl != SSL_TLSV1_3) + return 0; + + if (security_level <= 3) + return 1; + + if (cipher->algorithm_mac & SSL_SHA1) + return 0; + + return 1; +} + +static int +ssl_security_secop_version(const SSL_CTX *ctx, const SSL *ssl, int version) +{ + int min_version = TLS1_2_VERSION; + int security_level; + + if (!ssl_security_level_and_minimum_bits(ctx, ssl, &security_level, NULL)) + return 0; + + if (security_level < 4) + min_version = TLS1_1_VERSION; + if (security_level < 3) + min_version = TLS1_VERSION; + + return ssl_tls_version(version) >= min_version; +} + +static int +ssl_security_secop_compression(const SSL_CTX *ctx, const SSL *ssl) +{ + return 0; +} + +static int +ssl_security_secop_tickets(const SSL_CTX *ctx, const SSL *ssl) +{ + int security_level; + + if (!ssl_security_level_and_minimum_bits(ctx, ssl, &security_level, NULL)) + return 0; + + return security_level < 3; +} + +static int +ssl_security_secop_tmp_dh(const SSL_CTX *ctx, const SSL *ssl, int bits) +{ + int security_level, minimum_bits; + + if (!ssl_security_level_and_minimum_bits(ctx, ssl, &security_level, + &minimum_bits)) + return 0; + + /* Disallow DHE keys weaker than 1024 bits even at security level 0. */ + if (security_level <= 0 && bits < 80) + return 0; + + return bits >= minimum_bits; +} + +static int +ssl_security_secop_default(const SSL_CTX *ctx, const SSL *ssl, int bits) +{ + int minimum_bits; + + if (!ssl_security_level_and_minimum_bits(ctx, ssl, NULL, &minimum_bits)) + return 0; + + return bits >= minimum_bits; +} + +int +ssl_security_default_cb(const SSL *ssl, const SSL_CTX *ctx, int secop, int bits, + int version, void *cipher, void *ex_data) +{ + switch (secop) { + case SSL_SECOP_CIPHER_SUPPORTED: + case SSL_SECOP_CIPHER_SHARED: + case SSL_SECOP_CIPHER_CHECK: + return ssl_security_secop_cipher(ctx, ssl, bits, cipher); + case SSL_SECOP_VERSION: + return ssl_security_secop_version(ctx, ssl, version); + case SSL_SECOP_COMPRESSION: + return ssl_security_secop_compression(ctx, ssl); + case SSL_SECOP_TICKET: + return ssl_security_secop_tickets(ctx, ssl); + case SSL_SECOP_TMP_DH: + return ssl_security_secop_tmp_dh(ctx, ssl, bits); + default: + return ssl_security_secop_default(ctx, ssl, bits); + } +} + +static int +ssl_ctx_security(const SSL_CTX *ctx, int secop, int bits, int nid, void *other) +{ + return ctx->cert->security_cb(NULL, ctx, secop, bits, nid, + other, ctx->cert->security_ex_data); +} + +static int +ssl_security(const SSL *ssl, int secop, int bits, int nid, void *other) +{ + return ssl->cert->security_cb(ssl, NULL, secop, bits, nid, other, + ssl->cert->security_ex_data); +} + +int +ssl_security_sigalg_check(const SSL *ssl, const EVP_PKEY *pkey) +{ + int bits; + + bits = EVP_PKEY_security_bits(pkey); + + return ssl_security(ssl, SSL_SECOP_SIGALG_CHECK, bits, 0, NULL); +} + +int +ssl_security_tickets(const SSL *ssl) +{ + return ssl_security(ssl, SSL_SECOP_TICKET, 0, 0, NULL); +} + +int +ssl_security_version(const SSL *ssl, int version) +{ + return ssl_security(ssl, SSL_SECOP_VERSION, 0, version, NULL); +} + +static int +ssl_security_cipher(const SSL *ssl, SSL_CIPHER *cipher, int secop) +{ + return ssl_security(ssl, secop, cipher->strength_bits, 0, cipher); +} + +int +ssl_security_cipher_check(const SSL *ssl, SSL_CIPHER *cipher) +{ + return ssl_security_cipher(ssl, cipher, SSL_SECOP_CIPHER_CHECK); +} + +int +ssl_security_shared_cipher(const SSL *ssl, SSL_CIPHER *cipher) +{ + return ssl_security_cipher(ssl, cipher, SSL_SECOP_CIPHER_SHARED); +} + +int +ssl_security_supported_cipher(const SSL *ssl, SSL_CIPHER *cipher) +{ + return ssl_security_cipher(ssl, cipher, SSL_SECOP_CIPHER_SUPPORTED); +} + +int +ssl_ctx_security_dh(const SSL_CTX *ctx, DH *dh) +{ + int bits; + + bits = DH_security_bits(dh); + + return ssl_ctx_security(ctx, SSL_SECOP_TMP_DH, bits, 0, dh); +} + +int +ssl_security_dh(const SSL *ssl, DH *dh) +{ + int bits; + + bits = DH_security_bits(dh); + + return ssl_security(ssl, SSL_SECOP_TMP_DH, bits, 0, dh); +} + +static int +ssl_cert_pubkey_security_bits(const X509 *x509) +{ + EVP_PKEY *pkey; + + if ((pkey = X509_get0_pubkey(x509)) == NULL) + return -1; + + /* + * XXX: DSA_security_bits() returns -1 on keys without parameters and + * makes the default security callback fail. + */ + + return EVP_PKEY_security_bits(pkey); +} + +static int +ssl_security_cert_key(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) +{ + int security_bits; + + security_bits = ssl_cert_pubkey_security_bits(x509); + + if (ssl != NULL) + return ssl_security(ssl, secop, security_bits, 0, x509); + + return ssl_ctx_security(ctx, secop, security_bits, 0, x509); +} + +static int +ssl_cert_signature_md_nid(X509 *x509) +{ + int md_nid, signature_nid; + + if ((signature_nid = X509_get_signature_nid(x509)) == NID_undef) + return NID_undef; + + if (!OBJ_find_sigid_algs(signature_nid, &md_nid, NULL)) + return NID_undef; + + return md_nid; +} + +static int +ssl_cert_md_nid_security_bits(int md_nid) +{ + const EVP_MD *md; + + if (md_nid == NID_undef) + return -1; + + if ((md = EVP_get_digestbynid(md_nid)) == NULL) + return -1; + + /* Assume 4 bits of collision resistance for each hash octet. */ + return EVP_MD_size(md) * 4; +} + +static int +ssl_security_cert_sig(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, int secop) +{ + int md_nid, security_bits; + + /* Don't check signature if self signed. */ + if ((X509_get_extension_flags(x509) & EXFLAG_SS) != 0) + return 1; + + md_nid = ssl_cert_signature_md_nid(x509); + security_bits = ssl_cert_md_nid_security_bits(md_nid); + + if (ssl != NULL) + return ssl_security(ssl, secop, security_bits, md_nid, x509); + + return ssl_ctx_security(ctx, secop, security_bits, md_nid, x509); +} + +int +ssl_security_cert(const SSL_CTX *ctx, const SSL *ssl, X509 *x509, + int is_ee, int *out_error) +{ + int key_error, operation; + + *out_error = 0; + + if (is_ee) { + operation = SSL_SECOP_EE_KEY; + key_error = SSL_R_EE_KEY_TOO_SMALL; + } else { + operation = SSL_SECOP_CA_KEY; + key_error = SSL_R_CA_KEY_TOO_SMALL; + } + + if (!ssl_security_cert_key(ctx, ssl, x509, operation)) { + *out_error = key_error; + return 0; + } + + if (!ssl_security_cert_sig(ctx, ssl, x509, SSL_SECOP_CA_MD)) { + *out_error = SSL_R_CA_MD_TOO_WEAK; + return 0; + } + + return 1; +} + +/* + * Check security of a chain. If |sk| includes the end entity certificate + * then |x509| must be NULL. + */ +int +ssl_security_cert_chain(const SSL *ssl, STACK_OF(X509) *sk, X509 *x509, + int *out_error) +{ + int start_idx = 0; + int is_ee; + int i; + + if (x509 == NULL) { + x509 = sk_X509_value(sk, 0); + start_idx = 1; + } + + is_ee = 1; + if (!ssl_security_cert(NULL, ssl, x509, is_ee, out_error)) + return 0; + + is_ee = 0; + for (i = start_idx; i < sk_X509_num(sk); i++) { + x509 = sk_X509_value(sk, i); + + if (!ssl_security_cert(NULL, ssl, x509, is_ee, out_error)) + return 0; + } + + return 1; +} + +static int +ssl_security_group(const SSL *ssl, uint16_t group_id, int secop) +{ + CBB cbb; + int bits, nid; + uint8_t group[2]; + + if (!tls1_ec_group_id2bits(group_id, &bits)) + return 0; + if (!tls1_ec_group_id2nid(group_id, &nid)) + return 0; + + if (!CBB_init_fixed(&cbb, group, sizeof(group))) + return 0; + if (!CBB_add_u16(&cbb, group_id)) + return 0; + if (!CBB_finish(&cbb, NULL, NULL)) + return 0; + + return ssl_security(ssl, secop, bits, nid, group); +} + +int +ssl_security_shared_group(const SSL *ssl, uint16_t group_id) +{ + return ssl_security_group(ssl, group_id, SSL_SECOP_CURVE_SHARED); +} + +int +ssl_security_supported_group(const SSL *ssl, uint16_t group_id) +{ + return ssl_security_group(ssl, group_id, SSL_SECOP_CURVE_SUPPORTED); +} diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c new file mode 100644 index 0000000..aa6b08e --- /dev/null +++ b/ssl/ssl_sess.c @@ -0,0 +1,1388 @@ +/* $OpenBSD: ssl_sess.c,v 1.122 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include + +#ifndef OPENSSL_NO_ENGINE +#include +#endif + +#include "ssl_local.h" + +static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s); +static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s); +static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck); + +/* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */ +SSL_SESSION * +SSL_get_session(const SSL *ssl) +{ + return (ssl->session); +} +LSSL_ALIAS(SSL_get_session); + +/* variant of SSL_get_session: caller really gets something */ +SSL_SESSION * +SSL_get1_session(SSL *ssl) +{ + SSL_SESSION *sess; + + /* + * Need to lock this all up rather than just use CRYPTO_add so that + * somebody doesn't free ssl->session between when we check it's + * non-null and when we up the reference count. + */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_SESSION); + sess = ssl->session; + if (sess) + sess->references++; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_SESSION); + + return (sess); +} +LSSL_ALIAS(SSL_get1_session); + +int +SSL_SESSION_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, + CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) +{ + return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, + argl, argp, new_func, dup_func, free_func); +} +LSSL_ALIAS(SSL_SESSION_get_ex_new_index); + +int +SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg) +{ + return (CRYPTO_set_ex_data(&s->ex_data, idx, arg)); +} +LSSL_ALIAS(SSL_SESSION_set_ex_data); + +void * +SSL_SESSION_get_ex_data(const SSL_SESSION *s, int idx) +{ + return (CRYPTO_get_ex_data(&s->ex_data, idx)); +} +LSSL_ALIAS(SSL_SESSION_get_ex_data); + +uint32_t +SSL_SESSION_get_max_early_data(const SSL_SESSION *s) +{ + return 0; +} +LSSL_ALIAS(SSL_SESSION_get_max_early_data); + +int +SSL_SESSION_set_max_early_data(SSL_SESSION *s, uint32_t max_early_data) +{ + return 1; +} +LSSL_ALIAS(SSL_SESSION_set_max_early_data); + +SSL_SESSION * +SSL_SESSION_new(void) +{ + SSL_SESSION *ss; + + if (!OPENSSL_init_ssl(0, NULL)) { + SSLerrorx(SSL_R_LIBRARY_BUG); + return(NULL); + } + + if ((ss = calloc(1, sizeof(*ss))) == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + return (NULL); + } + + ss->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */ + ss->references = 1; + ss->timeout = 60 * 5 + 4; /* 5 minutes 4 seconds timeout by default */ + ss->time = time(NULL); + ss->prev = NULL; + ss->next = NULL; + ss->tlsext_hostname = NULL; + + ss->peer_cert_type = -1; + + ss->tlsext_ecpointformatlist_length = 0; + ss->tlsext_ecpointformatlist = NULL; + ss->tlsext_supportedgroups_length = 0; + ss->tlsext_supportedgroups = NULL; + + CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + + return (ss); +} +LSSL_ALIAS(SSL_SESSION_new); + +SSL_SESSION * +ssl_session_dup(SSL_SESSION *sess, int include_ticket) +{ + SSL_SESSION *copy; + CBS cbs; + + if ((copy = calloc(1, sizeof(*copy))) == NULL) { + SSLerrorx(ERR_R_MALLOC_FAILURE); + goto err; + } + + copy->ssl_version = sess->ssl_version; + + CBS_init(&cbs, sess->master_key, sess->master_key_length); + if (!CBS_write_bytes(&cbs, copy->master_key, sizeof(copy->master_key), + ©->master_key_length)) + goto err; + + CBS_init(&cbs, sess->session_id, sess->session_id_length); + if (!CBS_write_bytes(&cbs, copy->session_id, sizeof(copy->session_id), + ©->session_id_length)) + goto err; + + CBS_init(&cbs, sess->sid_ctx, sess->sid_ctx_length); + if (!CBS_write_bytes(&cbs, copy->sid_ctx, sizeof(copy->sid_ctx), + ©->sid_ctx_length)) + goto err; + + if (sess->peer_cert != NULL) { + if (!X509_up_ref(sess->peer_cert)) + goto err; + copy->peer_cert = sess->peer_cert; + } + copy->peer_cert_type = sess->peer_cert_type; + + copy->verify_result = sess->verify_result; + + copy->timeout = sess->timeout; + copy->time = sess->time; + copy->references = 1; + + copy->cipher = sess->cipher; + copy->cipher_id = sess->cipher_id; + + if (sess->ciphers != NULL) { + if ((copy->ciphers = sk_SSL_CIPHER_dup(sess->ciphers)) == NULL) + goto err; + } + + if (sess->tlsext_hostname != NULL) { + copy->tlsext_hostname = strdup(sess->tlsext_hostname); + if (copy->tlsext_hostname == NULL) + goto err; + } + + if (include_ticket) { + CBS_init(&cbs, sess->tlsext_tick, sess->tlsext_ticklen); + if (!CBS_stow(&cbs, ©->tlsext_tick, ©->tlsext_ticklen)) + goto err; + copy->tlsext_tick_lifetime_hint = + sess->tlsext_tick_lifetime_hint; + + /* + * XXX - copy sess->resumption_master_secret and all other + * TLSv1.3 info here. + */ + } + + if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, copy, + ©->ex_data)) + goto err; + + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ©->ex_data, + &sess->ex_data)) + goto err; + + /* Omit prev/next: the new session gets its own slot in the cache. */ + + copy->not_resumable = sess->not_resumable; + + CBS_init(&cbs, sess->tlsext_ecpointformatlist, + sess->tlsext_ecpointformatlist_length); + if (!CBS_stow(&cbs, ©->tlsext_ecpointformatlist, + ©->tlsext_ecpointformatlist_length)) + goto err; + + if (sess->tlsext_supportedgroups != NULL) { + if ((copy->tlsext_supportedgroups = calloc(sizeof(uint16_t), + sess->tlsext_supportedgroups_length)) == NULL) + goto err; + memcpy(copy->tlsext_supportedgroups, + sess->tlsext_supportedgroups, + sizeof(uint16_t) * sess->tlsext_supportedgroups_length); + copy->tlsext_supportedgroups_length = + sess->tlsext_supportedgroups_length; + } + + return copy; + + err: + SSL_SESSION_free(copy); + + return NULL; +} + +const unsigned char * +SSL_SESSION_get_id(const SSL_SESSION *ss, unsigned int *len) +{ + if (len != NULL) + *len = (unsigned int)ss->session_id_length; + return ss->session_id; +} +LSSL_ALIAS(SSL_SESSION_get_id); + +const unsigned char * +SSL_SESSION_get0_id_context(const SSL_SESSION *ss, unsigned int *len) +{ + if (len != NULL) + *len = (unsigned int)ss->sid_ctx_length; + return ss->sid_ctx; +} +LSSL_ALIAS(SSL_SESSION_get0_id_context); + +unsigned int +SSL_SESSION_get_compress_id(const SSL_SESSION *ss) +{ + return 0; +} +LSSL_ALIAS(SSL_SESSION_get_compress_id); + +unsigned long +SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) +{ + return s->tlsext_tick_lifetime_hint; +} +LSSL_ALIAS(SSL_SESSION_get_ticket_lifetime_hint); + +int +SSL_SESSION_has_ticket(const SSL_SESSION *s) +{ + return (s->tlsext_ticklen > 0) ? 1 : 0; +} +LSSL_ALIAS(SSL_SESSION_has_ticket); + +/* + * SSLv3/TLSv1 has 32 bytes (256 bits) of session ID space. As such, filling + * the ID with random gunk repeatedly until we have no conflict is going to + * complete in one iteration pretty much "most" of the time (btw: + * understatement). So, if it takes us 10 iterations and we still can't avoid + * a conflict - well that's a reasonable point to call it quits. Either the + * arc4random code is broken or someone is trying to open roughly very close to + * 2^128 (or 2^256) SSL sessions to our server. How you might store that many + * sessions is perhaps a more interesting question... + */ + +#define MAX_SESS_ID_ATTEMPTS 10 + +static int +def_generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len) +{ + unsigned int retry = 0; + + do { + arc4random_buf(id, *id_len); + } while (SSL_has_matching_session_id(ssl, id, *id_len) && + (++retry < MAX_SESS_ID_ATTEMPTS)); + + if (retry < MAX_SESS_ID_ATTEMPTS) + return 1; + + /* else - woops a session_id match */ + /* XXX We should also check the external cache -- + * but the probability of a collision is negligible, and + * we could not prevent the concurrent creation of sessions + * with identical IDs since we currently don't have means + * to atomically check whether a session ID already exists + * and make a reservation for it if it does not + * (this problem applies to the internal cache as well). + */ + return 0; +} + +int +ssl_get_new_session(SSL *s, int session) +{ + unsigned int tmp; + SSL_SESSION *ss = NULL; + GEN_SESSION_CB cb = def_generate_session_id; + + /* This gets used by clients and servers. */ + + if ((ss = SSL_SESSION_new()) == NULL) + return (0); + + /* If the context has a default timeout, use it */ + if (s->session_ctx->session_timeout == 0) + ss->timeout = SSL_get_default_timeout(s); + else + ss->timeout = s->session_ctx->session_timeout; + + if (s->session != NULL) { + SSL_SESSION_free(s->session); + s->session = NULL; + } + + if (session) { + switch (s->version) { + case TLS1_VERSION: + case TLS1_1_VERSION: + case TLS1_2_VERSION: + case DTLS1_VERSION: + case DTLS1_2_VERSION: + ss->ssl_version = s->version; + ss->session_id_length = SSL3_SSL_SESSION_ID_LENGTH; + break; + default: + SSLerror(s, SSL_R_UNSUPPORTED_SSL_VERSION); + SSL_SESSION_free(ss); + return (0); + } + + /* If RFC4507 ticket use empty session ID. */ + if (s->tlsext_ticket_expected) { + ss->session_id_length = 0; + goto sess_id_done; + } + + /* Choose which callback will set the session ID. */ + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + if (s->generate_session_id) + cb = s->generate_session_id; + else if (s->session_ctx->generate_session_id) + cb = s->session_ctx->generate_session_id; + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + /* Choose a session ID. */ + tmp = ss->session_id_length; + if (!cb(s, ss->session_id, &tmp)) { + /* The callback failed */ + SSLerror(s, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED); + SSL_SESSION_free(ss); + return (0); + } + + /* + * Don't allow the callback to set the session length to zero. + * nor set it higher than it was. + */ + if (tmp == 0 || tmp > ss->session_id_length) { + /* The callback set an illegal length */ + SSLerror(s, SSL_R_SSL_SESSION_ID_HAS_BAD_LENGTH); + SSL_SESSION_free(ss); + return (0); + } + ss->session_id_length = tmp; + + /* Finally, check for a conflict. */ + if (SSL_has_matching_session_id(s, ss->session_id, + ss->session_id_length)) { + SSLerror(s, SSL_R_SSL_SESSION_ID_CONFLICT); + SSL_SESSION_free(ss); + return (0); + } + + sess_id_done: + if (s->tlsext_hostname) { + ss->tlsext_hostname = strdup(s->tlsext_hostname); + if (ss->tlsext_hostname == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + } + } else { + ss->session_id_length = 0; + } + + if (s->sid_ctx_length > sizeof ss->sid_ctx) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + SSL_SESSION_free(ss); + return 0; + } + + memcpy(ss->sid_ctx, s->sid_ctx, s->sid_ctx_length); + ss->sid_ctx_length = s->sid_ctx_length; + s->session = ss; + ss->ssl_version = s->version; + ss->verify_result = X509_V_OK; + + return (1); +} + +static SSL_SESSION * +ssl_session_from_cache(SSL *s, CBS *session_id) +{ + SSL_SESSION *sess; + SSL_SESSION data; + + if ((s->session_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) + return NULL; + + memset(&data, 0, sizeof(data)); + + data.ssl_version = s->version; + + if (!CBS_write_bytes(session_id, data.session_id, + sizeof(data.session_id), &data.session_id_length)) + return NULL; + + CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); + sess = lh_SSL_SESSION_retrieve(s->session_ctx->sessions, &data); + if (sess != NULL) + CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + + if (sess == NULL) + s->session_ctx->stats.sess_miss++; + + return sess; +} + +static SSL_SESSION * +ssl_session_from_callback(SSL *s, CBS *session_id) +{ + SSL_SESSION *sess; + int copy; + + if (s->session_ctx->get_session_cb == NULL) + return NULL; + + copy = 1; + if ((sess = s->session_ctx->get_session_cb(s, + CBS_data(session_id), CBS_len(session_id), ©)) == NULL) + return NULL; + /* + * The copy handler may have set copy == 0 to indicate that the session + * structures are shared between threads and that it handles the + * reference count itself. If it didn't set copy to zero, we must + * increment the reference count. + */ + if (copy) + CRYPTO_add(&sess->references, 1, CRYPTO_LOCK_SSL_SESSION); + + s->session_ctx->stats.sess_cb_hit++; + + /* Add the externally cached session to the internal cache as well. */ + if (!(s->session_ctx->session_cache_mode & + SSL_SESS_CACHE_NO_INTERNAL_STORE)) { + /* + * The following should not return 1, + * otherwise, things are very strange. + */ + SSL_CTX_add_session(s->session_ctx, sess); + } + + return sess; +} + +static SSL_SESSION * +ssl_session_by_id(SSL *s, CBS *session_id) +{ + SSL_SESSION *sess; + + if (CBS_len(session_id) == 0) + return NULL; + + if ((sess = ssl_session_from_cache(s, session_id)) == NULL) + sess = ssl_session_from_callback(s, session_id); + + return sess; +} + +/* + * ssl_get_prev_session attempts to find an SSL_SESSION to be used to resume + * this connection. It is only called by servers. + * + * session_id: points at the session ID in the ClientHello. This code will + * read past the end of this in order to parse out the session ticket + * extension, if any. + * ext_block: a CBS for the ClientHello extensions block. + * alert: alert that the caller should send in case of failure. + * + * Returns: + * -1: error + * 0: a session may have been found. + * + * Side effects: + * - If a session is found then s->session is pointed at it (after freeing + * an existing session if need be) and s->verify_result is set from the + * session. + * - For both new and resumed sessions, s->tlsext_ticket_expected + * indicates whether the server should issue a new session ticket or not. + */ +int +ssl_get_prev_session(SSL *s, CBS *session_id, CBS *ext_block, int *alert) +{ + SSL_SESSION *sess = NULL; + int alert_desc = SSL_AD_INTERNAL_ERROR, fatal = 0; + int ticket_decrypted = 0; + + /* This is used only by servers. */ + + if (CBS_len(session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) + goto err; + + /* Sets s->tlsext_ticket_expected. */ + switch (tls1_process_ticket(s, ext_block, &alert_desc, &sess)) { + case TLS1_TICKET_FATAL_ERROR: + fatal = 1; + goto err; + case TLS1_TICKET_NONE: + case TLS1_TICKET_EMPTY: + if ((sess = ssl_session_by_id(s, session_id)) == NULL) + goto err; + break; + case TLS1_TICKET_NOT_DECRYPTED: + goto err; + case TLS1_TICKET_DECRYPTED: + ticket_decrypted = 1; + + /* + * The session ID is used by some clients to detect that the + * ticket has been accepted so we copy it into sess. + */ + if (!CBS_write_bytes(session_id, sess->session_id, + sizeof(sess->session_id), &sess->session_id_length)) { + fatal = 1; + goto err; + } + break; + default: + SSLerror(s, ERR_R_INTERNAL_ERROR); + fatal = 1; + goto err; + } + + /* Now sess is non-NULL and we own one of its reference counts. */ + + if (sess->sid_ctx_length != s->sid_ctx_length || + timingsafe_memcmp(sess->sid_ctx, s->sid_ctx, + sess->sid_ctx_length) != 0) { + /* + * We have the session requested by the client, but we don't + * want to use it in this context. Treat it like a cache miss. + */ + goto err; + } + + if ((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0) { + /* + * We can't be sure if this session is being used out of + * context, which is especially important for SSL_VERIFY_PEER. + * The application should have used + * SSL[_CTX]_set_session_id_context. + * + * For this error case, we generate an error instead of treating + * the event like a cache miss (otherwise it would be easy for + * applications to effectively disable the session cache by + * accident without anyone noticing). + */ + SSLerror(s, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED); + fatal = 1; + goto err; + } + + if (sess->cipher == NULL) { + sess->cipher = ssl3_get_cipher_by_id(sess->cipher_id); + if (sess->cipher == NULL) + goto err; + } + + if (sess->timeout < (time(NULL) - sess->time)) { + s->session_ctx->stats.sess_timeout++; + if (!ticket_decrypted) { + /* The session was from the cache, so remove it. */ + SSL_CTX_remove_session(s->session_ctx, sess); + } + goto err; + } + + s->session_ctx->stats.sess_hit++; + + SSL_SESSION_free(s->session); + s->session = sess; + s->verify_result = s->session->verify_result; + + return 1; + + err: + SSL_SESSION_free(sess); + if (ticket_decrypted) { + /* + * The session was from a ticket. Issue a ticket for the new + * session. + */ + s->tlsext_ticket_expected = 1; + } + if (fatal) { + *alert = alert_desc; + return -1; + } + return 0; +} + +int +SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) +{ + int ret = 0; + SSL_SESSION *s; + + /* + * Add just 1 reference count for the SSL_CTX's session cache + * even though it has two ways of access: each session is in a + * doubly linked list and an lhash. + */ + CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION); + + /* + * If session c is in already in cache, we take back the increment + * later. + */ + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + s = lh_SSL_SESSION_insert(ctx->sessions, c); + + /* + * s != NULL iff we already had a session with the given PID. + * In this case, s == c should hold (then we did not really modify + * ctx->sessions), or we're in trouble. + */ + if (s != NULL && s != c) { + /* We *are* in trouble ... */ + SSL_SESSION_list_remove(ctx, s); + SSL_SESSION_free(s); + /* + * ... so pretend the other session did not exist in cache + * (we cannot handle two SSL_SESSION structures with identical + * session ID in the same cache, which could happen e.g. when + * two threads concurrently obtain the same session from an + * external cache). + */ + s = NULL; + } + + /* Put at the head of the queue unless it is already in the cache */ + if (s == NULL) + SSL_SESSION_list_add(ctx, c); + + if (s != NULL) { + /* + * existing cache entry -- decrement previously incremented + * reference count because it already takes into account the + * cache. + */ + SSL_SESSION_free(s); /* s == c */ + ret = 0; + } else { + /* + * New cache entry -- remove old ones if cache has become + * too large. + */ + + ret = 1; + + if (SSL_CTX_sess_get_cache_size(ctx) > 0) { + while (SSL_CTX_sess_number(ctx) > + SSL_CTX_sess_get_cache_size(ctx)) { + if (!remove_session_lock(ctx, + ctx->session_cache_tail, 0)) + break; + else + ctx->stats.sess_cache_full++; + } + } + } + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + return (ret); +} +LSSL_ALIAS(SSL_CTX_add_session); + +int +SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c) +{ + return remove_session_lock(ctx, c, 1); +} +LSSL_ALIAS(SSL_CTX_remove_session); + +static int +remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck) +{ + SSL_SESSION *r; + int ret = 0; + + if (c == NULL || c->session_id_length == 0) + return 0; + + if (lck) + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + if ((r = lh_SSL_SESSION_retrieve(ctx->sessions, c)) == c) { + ret = 1; + r = lh_SSL_SESSION_delete(ctx->sessions, c); + SSL_SESSION_list_remove(ctx, c); + } + if (lck) + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); + + if (ret) { + r->not_resumable = 1; + if (ctx->remove_session_cb != NULL) + ctx->remove_session_cb(ctx, r); + SSL_SESSION_free(r); + } + + return ret; +} + +void +SSL_SESSION_free(SSL_SESSION *ss) +{ + int i; + + if (ss == NULL) + return; + + i = CRYPTO_add(&ss->references, -1, CRYPTO_LOCK_SSL_SESSION); + if (i > 0) + return; + + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data); + + explicit_bzero(ss->master_key, sizeof ss->master_key); + explicit_bzero(ss->session_id, sizeof ss->session_id); + + X509_free(ss->peer_cert); + + sk_SSL_CIPHER_free(ss->ciphers); + + free(ss->tlsext_hostname); + free(ss->tlsext_tick); + free(ss->tlsext_ecpointformatlist); + free(ss->tlsext_supportedgroups); + + tls13_secret_cleanup(&ss->resumption_master_secret); + + freezero(ss, sizeof(*ss)); +} +LSSL_ALIAS(SSL_SESSION_free); + +int +SSL_SESSION_up_ref(SSL_SESSION *ss) +{ + int refs = CRYPTO_add(&ss->references, 1, CRYPTO_LOCK_SSL_SESSION); + return (refs > 1) ? 1 : 0; +} +LSSL_ALIAS(SSL_SESSION_up_ref); + +int +SSL_set_session(SSL *s, SSL_SESSION *session) +{ + const SSL_METHOD *method; + + if (session == NULL) { + SSL_SESSION_free(s->session); + s->session = NULL; + + return SSL_set_ssl_method(s, s->ctx->method); + } + + if ((method = ssl_get_method(session->ssl_version)) == NULL) { + SSLerror(s, SSL_R_UNABLE_TO_FIND_SSL_METHOD); + return (0); + } + + if (!SSL_set_ssl_method(s, method)) + return (0); + + CRYPTO_add(&session->references, 1, CRYPTO_LOCK_SSL_SESSION); + SSL_SESSION_free(s->session); + s->session = session; + s->verify_result = s->session->verify_result; + + return (1); +} +LSSL_ALIAS(SSL_set_session); + +size_t +SSL_SESSION_get_master_key(const SSL_SESSION *ss, unsigned char *out, + size_t max_out) +{ + size_t len = ss->master_key_length; + + if (out == NULL) + return len; + + if (len > max_out) + len = max_out; + + memcpy(out, ss->master_key, len); + + return len; +} +LSSL_ALIAS(SSL_SESSION_get_master_key); + +long +SSL_SESSION_set_timeout(SSL_SESSION *s, long t) +{ + if (s == NULL) + return (0); + s->timeout = t; + return (1); +} +LSSL_ALIAS(SSL_SESSION_set_timeout); + +long +SSL_SESSION_get_timeout(const SSL_SESSION *s) +{ + if (s == NULL) + return (0); + return (s->timeout); +} +LSSL_ALIAS(SSL_SESSION_get_timeout); + +/* XXX 2038 */ +long +SSL_SESSION_get_time(const SSL_SESSION *s) +{ + if (s == NULL) + return (0); + return (s->time); +} +LSSL_ALIAS(SSL_SESSION_get_time); + +/* XXX 2038 */ +long +SSL_SESSION_set_time(SSL_SESSION *s, long t) +{ + if (s == NULL) + return (0); + s->time = t; + return (t); +} +LSSL_ALIAS(SSL_SESSION_set_time); + +int +SSL_SESSION_get_protocol_version(const SSL_SESSION *s) +{ + return s->ssl_version; +} +LSSL_ALIAS(SSL_SESSION_get_protocol_version); + +const SSL_CIPHER * +SSL_SESSION_get0_cipher(const SSL_SESSION *s) +{ + return s->cipher; +} +LSSL_ALIAS(SSL_SESSION_get0_cipher); + +X509 * +SSL_SESSION_get0_peer(SSL_SESSION *s) +{ + return s->peer_cert; +} +LSSL_ALIAS(SSL_SESSION_get0_peer); + +int +SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid, + unsigned int sid_len) +{ + if (sid_len > SSL_MAX_SSL_SESSION_ID_LENGTH) { + SSLerrorx(SSL_R_SSL_SESSION_ID_TOO_LONG); + return 0; + } + s->session_id_length = sid_len; + memmove(s->session_id, sid, sid_len); + return 1; +} +LSSL_ALIAS(SSL_SESSION_set1_id); + +int +SSL_SESSION_set1_id_context(SSL_SESSION *s, const unsigned char *sid_ctx, + unsigned int sid_ctx_len) +{ + if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) { + SSLerrorx(SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG); + return 0; + } + s->sid_ctx_length = sid_ctx_len; + memcpy(s->sid_ctx, sid_ctx, sid_ctx_len); + + return 1; +} +LSSL_ALIAS(SSL_SESSION_set1_id_context); + +int +SSL_SESSION_is_resumable(const SSL_SESSION *s) +{ + return 0; +} +LSSL_ALIAS(SSL_SESSION_is_resumable); + +long +SSL_CTX_set_timeout(SSL_CTX *s, long t) +{ + long l; + + if (s == NULL) + return (0); + l = s->session_timeout; + s->session_timeout = t; + + return (l); +} +LSSL_ALIAS(SSL_CTX_set_timeout); + +long +SSL_CTX_get_timeout(const SSL_CTX *s) +{ + if (s == NULL) + return (0); + return (s->session_timeout); +} +LSSL_ALIAS(SSL_CTX_get_timeout); + +int +SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, + void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, + SSL_CIPHER **cipher, void *arg), void *arg) +{ + if (s == NULL) + return (0); + s->tls_session_secret_cb = tls_session_secret_cb; + s->tls_session_secret_cb_arg = arg; + return (1); +} +LSSL_ALIAS(SSL_set_session_secret_cb); + +int +SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, + void *arg) +{ + if (s == NULL) + return (0); + s->tls_session_ticket_ext_cb = cb; + s->tls_session_ticket_ext_cb_arg = arg; + return (1); +} +LSSL_ALIAS(SSL_set_session_ticket_ext_cb); + +int +SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) +{ + if (s->version >= TLS1_VERSION) { + free(s->tlsext_session_ticket); + s->tlsext_session_ticket = + malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); + if (!s->tlsext_session_ticket) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (ext_data) { + s->tlsext_session_ticket->length = ext_len; + s->tlsext_session_ticket->data = + s->tlsext_session_ticket + 1; + memcpy(s->tlsext_session_ticket->data, + ext_data, ext_len); + } else { + s->tlsext_session_ticket->length = 0; + s->tlsext_session_ticket->data = NULL; + } + + return 1; + } + + return 0; +} +LSSL_ALIAS(SSL_set_session_ticket_ext); + +typedef struct timeout_param_st { + SSL_CTX *ctx; + long time; + struct lhash_st_SSL_SESSION *cache; +} TIMEOUT_PARAM; + +static void +timeout_doall_arg(SSL_SESSION *s, TIMEOUT_PARAM *p) +{ + if ((p->time == 0) || (p->time > (s->time + s->timeout))) { + /* timeout */ + /* The reason we don't call SSL_CTX_remove_session() is to + * save on locking overhead */ + (void)lh_SSL_SESSION_delete(p->cache, s); + SSL_SESSION_list_remove(p->ctx, s); + s->not_resumable = 1; + if (p->ctx->remove_session_cb != NULL) + p->ctx->remove_session_cb(p->ctx, s); + SSL_SESSION_free(s); + } +} + +static void +timeout_LHASH_DOALL_ARG(void *arg1, void *arg2) +{ + SSL_SESSION *a = arg1; + TIMEOUT_PARAM *b = arg2; + + timeout_doall_arg(a, b); +} + +/* XXX 2038 */ +void +SSL_CTX_flush_sessions(SSL_CTX *s, long t) +{ + unsigned long i; + TIMEOUT_PARAM tp; + + tp.ctx = s; + tp.cache = s->sessions; + if (tp.cache == NULL) + return; + tp.time = t; + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + i = CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load; + CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = 0; + lh_SSL_SESSION_doall_arg(tp.cache, timeout_LHASH_DOALL_ARG, + TIMEOUT_PARAM, &tp); + CHECKED_LHASH_OF(SSL_SESSION, tp.cache)->down_load = i; + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +} +LSSL_ALIAS(SSL_CTX_flush_sessions); + +int +ssl_clear_bad_session(SSL *s) +{ + if ((s->session != NULL) && !(s->shutdown & SSL_SENT_SHUTDOWN) && + !(SSL_in_init(s) || SSL_in_before(s))) { + SSL_CTX_remove_session(s->ctx, s->session); + return (1); + } else + return (0); +} + +/* locked by SSL_CTX in the calling function */ +static void +SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s) +{ + if (s->next == NULL || s->prev == NULL) + return; + + if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail)) { + /* last element in list */ + if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { + /* only one element in list */ + ctx->session_cache_head = NULL; + ctx->session_cache_tail = NULL; + } else { + ctx->session_cache_tail = s->prev; + s->prev->next = + (SSL_SESSION *)&(ctx->session_cache_tail); + } + } else { + if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head)) { + /* first element in list */ + ctx->session_cache_head = s->next; + s->next->prev = + (SSL_SESSION *)&(ctx->session_cache_head); + } else { + /* middle of list */ + s->next->prev = s->prev; + s->prev->next = s->next; + } + } + s->prev = s->next = NULL; +} + +static void +SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s) +{ + if (s->next != NULL && s->prev != NULL) + SSL_SESSION_list_remove(ctx, s); + + if (ctx->session_cache_head == NULL) { + ctx->session_cache_head = s; + ctx->session_cache_tail = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + s->next = (SSL_SESSION *)&(ctx->session_cache_tail); + } else { + s->next = ctx->session_cache_head; + s->next->prev = s; + s->prev = (SSL_SESSION *)&(ctx->session_cache_head); + ctx->session_cache_head = s; + } +} + +void +SSL_CTX_sess_set_new_cb(SSL_CTX *ctx, + int (*cb)(struct ssl_st *ssl, SSL_SESSION *sess)) { + ctx->new_session_cb = cb; +} +LSSL_ALIAS(SSL_CTX_sess_set_new_cb); + +int +(*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess) +{ + return ctx->new_session_cb; +} +LSSL_ALIAS(SSL_CTX_sess_get_new_cb); + +void +SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx, + void (*cb)(SSL_CTX *ctx, SSL_SESSION *sess)) +{ + ctx->remove_session_cb = cb; +} +LSSL_ALIAS(SSL_CTX_sess_set_remove_cb); + +void +(*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx, SSL_SESSION *sess) +{ + return ctx->remove_session_cb; +} +LSSL_ALIAS(SSL_CTX_sess_get_remove_cb); + +void +SSL_CTX_sess_set_get_cb(SSL_CTX *ctx, SSL_SESSION *(*cb)(struct ssl_st *ssl, + const unsigned char *data, int len, int *copy)) +{ + ctx->get_session_cb = cb; +} +LSSL_ALIAS(SSL_CTX_sess_set_get_cb); + +SSL_SESSION * +(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl, const unsigned char *data, + int len, int *copy) +{ + return ctx->get_session_cb; +} +LSSL_ALIAS(SSL_CTX_sess_get_get_cb); + +void +SSL_CTX_set_info_callback(SSL_CTX *ctx, + void (*cb)(const SSL *ssl, int type, int val)) +{ + ctx->info_callback = cb; +} +LSSL_ALIAS(SSL_CTX_set_info_callback); + +void +(*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl, int type, int val) +{ + return ctx->info_callback; +} +LSSL_ALIAS(SSL_CTX_get_info_callback); + +void +SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey)) +{ + ctx->client_cert_cb = cb; +} +LSSL_ALIAS(SSL_CTX_set_client_cert_cb); + +int +(*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509, + EVP_PKEY **pkey) +{ + return ctx->client_cert_cb; +} +LSSL_ALIAS(SSL_CTX_get_client_cert_cb); + +#ifndef OPENSSL_NO_ENGINE +int +SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e) +{ + if (!ENGINE_init(e)) { + SSLerrorx(ERR_R_ENGINE_LIB); + return 0; + } + if (!ENGINE_get_ssl_client_cert_function(e)) { + SSLerrorx(SSL_R_NO_CLIENT_CERT_METHOD); + ENGINE_finish(e); + return 0; + } + ctx->client_cert_engine = e; + return 1; +} +LSSL_ALIAS(SSL_CTX_set_client_cert_engine); +#endif + +void +SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)) +{ + ctx->app_gen_cookie_cb = cb; +} +LSSL_ALIAS(SSL_CTX_set_cookie_generate_cb); + +void +SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx, + int (*cb)(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len)) +{ + ctx->app_verify_cookie_cb = cb; +} +LSSL_ALIAS(SSL_CTX_set_cookie_verify_cb); + +int +PEM_write_SSL_SESSION(FILE *fp, SSL_SESSION *x) +{ + return PEM_ASN1_write((i2d_of_void *)i2d_SSL_SESSION, + PEM_STRING_SSL_SESSION, fp, x, NULL, NULL, 0, NULL, NULL); +} +LSSL_ALIAS(PEM_write_SSL_SESSION); + +SSL_SESSION * +PEM_read_SSL_SESSION(FILE *fp, SSL_SESSION **x, pem_password_cb *cb, void *u) +{ + return PEM_ASN1_read((d2i_of_void *)d2i_SSL_SESSION, + PEM_STRING_SSL_SESSION, fp, (void **)x, cb, u); +} +LSSL_ALIAS(PEM_read_SSL_SESSION); + +SSL_SESSION * +PEM_read_bio_SSL_SESSION(BIO *bp, SSL_SESSION **x, pem_password_cb *cb, void *u) +{ + return PEM_ASN1_read_bio((d2i_of_void *)d2i_SSL_SESSION, + PEM_STRING_SSL_SESSION, bp, (void **)x, cb, u); +} +LSSL_ALIAS(PEM_read_bio_SSL_SESSION); + +int +PEM_write_bio_SSL_SESSION(BIO *bp, SSL_SESSION *x) +{ + return PEM_ASN1_write_bio((i2d_of_void *)i2d_SSL_SESSION, + PEM_STRING_SSL_SESSION, bp, x, NULL, NULL, 0, NULL, NULL); +} +LSSL_ALIAS(PEM_write_bio_SSL_SESSION); diff --git a/ssl/ssl_sigalgs.c b/ssl/ssl_sigalgs.c new file mode 100644 index 0000000..f59beb4 --- /dev/null +++ b/ssl/ssl_sigalgs.c @@ -0,0 +1,388 @@ +/* $OpenBSD: ssl_sigalgs.c,v 1.48 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018-2020 Bob Beck + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "tls13_internal.h" + +const struct ssl_sigalg sigalgs[] = { + { + .value = SIGALG_RSA_PKCS1_SHA512, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha512, + .security_level = 5, + }, + { + .value = SIGALG_ECDSA_SECP521R1_SHA512, + .key_type = EVP_PKEY_EC, + .md = EVP_sha512, + .security_level = 5, + .group_nid = NID_secp521r1, + }, +#ifndef OPENSSL_NO_GOST + { + .value = SIGALG_GOSTR12_512_STREEBOG_512, + .key_type = EVP_PKEY_GOSTR12_512, + .md = EVP_streebog512, + .security_level = 0, + }, +#endif + { + .value = SIGALG_RSA_PKCS1_SHA384, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha384, + .security_level = 4, + }, + { + .value = SIGALG_ECDSA_SECP384R1_SHA384, + .key_type = EVP_PKEY_EC, + .md = EVP_sha384, + .security_level = 4, + .group_nid = NID_secp384r1, + }, + { + .value = SIGALG_RSA_PKCS1_SHA256, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha256, + .security_level = 3, + }, + { + .value = SIGALG_ECDSA_SECP256R1_SHA256, + .key_type = EVP_PKEY_EC, + .md = EVP_sha256, + .security_level = 3, + .group_nid = NID_X9_62_prime256v1, + }, +#ifndef OPENSSL_NO_GOST + { + .value = SIGALG_GOSTR12_256_STREEBOG_256, + .key_type = EVP_PKEY_GOSTR12_256, + .md = EVP_streebog256, + .security_level = 0, + }, + { + .value = SIGALG_GOSTR01_GOST94, + .key_type = EVP_PKEY_GOSTR01, + .md = EVP_gostr341194, + .security_level = 0, /* XXX */ + }, +#endif + { + .value = SIGALG_RSA_PSS_RSAE_SHA256, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha256, + .security_level = 3, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PSS_RSAE_SHA384, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha384, + .security_level = 4, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PSS_RSAE_SHA512, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha512, + .security_level = 5, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PSS_PSS_SHA256, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha256, + .security_level = 3, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PSS_PSS_SHA384, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha384, + .security_level = 4, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PSS_PSS_SHA512, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha512, + .security_level = 5, + .flags = SIGALG_FLAG_RSA_PSS, + }, + { + .value = SIGALG_RSA_PKCS1_SHA224, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha224, + .security_level = 2, + }, + { + .value = SIGALG_ECDSA_SECP224R1_SHA224, + .key_type = EVP_PKEY_EC, + .md = EVP_sha224, + .security_level = 2, + }, + { + .value = SIGALG_RSA_PKCS1_SHA1, + .key_type = EVP_PKEY_RSA, + .md = EVP_sha1, + .security_level = 1, + }, + { + .value = SIGALG_ECDSA_SHA1, + .key_type = EVP_PKEY_EC, + .md = EVP_sha1, + .security_level = 1, + }, + { + .value = SIGALG_RSA_PKCS1_MD5_SHA1, + .key_type = EVP_PKEY_RSA, + .md = EVP_md5_sha1, + .security_level = 1, + }, + { + .value = SIGALG_NONE, + }, +}; + +/* Sigalgs for TLSv1.3, in preference order. */ +const uint16_t tls13_sigalgs[] = { + SIGALG_RSA_PSS_RSAE_SHA512, + SIGALG_RSA_PKCS1_SHA512, + SIGALG_ECDSA_SECP521R1_SHA512, + SIGALG_RSA_PSS_RSAE_SHA384, + SIGALG_RSA_PKCS1_SHA384, + SIGALG_ECDSA_SECP384R1_SHA384, + SIGALG_RSA_PSS_RSAE_SHA256, + SIGALG_RSA_PKCS1_SHA256, + SIGALG_ECDSA_SECP256R1_SHA256, +}; +const size_t tls13_sigalgs_len = (sizeof(tls13_sigalgs) / sizeof(tls13_sigalgs[0])); + +/* Sigalgs for TLSv1.2, in preference order. */ +const uint16_t tls12_sigalgs[] = { + SIGALG_RSA_PSS_RSAE_SHA512, + SIGALG_RSA_PKCS1_SHA512, + SIGALG_ECDSA_SECP521R1_SHA512, + SIGALG_RSA_PSS_RSAE_SHA384, + SIGALG_RSA_PKCS1_SHA384, + SIGALG_ECDSA_SECP384R1_SHA384, + SIGALG_RSA_PSS_RSAE_SHA256, + SIGALG_RSA_PKCS1_SHA256, + SIGALG_ECDSA_SECP256R1_SHA256, + SIGALG_RSA_PKCS1_SHA1, /* XXX */ + SIGALG_ECDSA_SHA1, /* XXX */ +}; +const size_t tls12_sigalgs_len = (sizeof(tls12_sigalgs) / sizeof(tls12_sigalgs[0])); + +static void +ssl_sigalgs_for_version(uint16_t tls_version, const uint16_t **out_values, + size_t *out_len) +{ + if (tls_version >= TLS1_3_VERSION) { + *out_values = tls13_sigalgs; + *out_len = tls13_sigalgs_len; + } else { + *out_values = tls12_sigalgs; + *out_len = tls12_sigalgs_len; + } +} + +static const struct ssl_sigalg * +ssl_sigalg_lookup(uint16_t value) +{ + int i; + + for (i = 0; sigalgs[i].value != SIGALG_NONE; i++) { + if (sigalgs[i].value == value) + return &sigalgs[i]; + } + + return NULL; +} + +static const struct ssl_sigalg * +ssl_sigalg_from_value(SSL *s, uint16_t value) +{ + const uint16_t *values; + size_t len; + int i; + + ssl_sigalgs_for_version(s->s3->hs.negotiated_tls_version, + &values, &len); + + for (i = 0; i < len; i++) { + if (values[i] == value) + return ssl_sigalg_lookup(value); + } + + return NULL; +} + +int +ssl_sigalgs_build(uint16_t tls_version, CBB *cbb, int security_level) +{ + const struct ssl_sigalg *sigalg; + const uint16_t *values; + size_t len; + size_t i; + int ret = 0; + + ssl_sigalgs_for_version(tls_version, &values, &len); + + /* Add values in order as long as they are supported. */ + for (i = 0; i < len; i++) { + /* Do not allow the legacy value for < 1.2 to be used. */ + if (values[i] == SIGALG_RSA_PKCS1_MD5_SHA1) + return 0; + if ((sigalg = ssl_sigalg_lookup(values[i])) == NULL) + return 0; + if (sigalg->security_level < security_level) + continue; + + if (!CBB_add_u16(cbb, values[i])) + return 0; + + ret = 1; + } + return ret; +} + +static const struct ssl_sigalg * +ssl_sigalg_for_legacy(SSL *s, EVP_PKEY *pkey) +{ + if (SSL_get_security_level(s) > 1) + return NULL; + + /* Default signature algorithms used for TLSv1.2 and earlier. */ + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_RSA: + if (s->s3->hs.negotiated_tls_version < TLS1_2_VERSION) + return ssl_sigalg_lookup(SIGALG_RSA_PKCS1_MD5_SHA1); + return ssl_sigalg_lookup(SIGALG_RSA_PKCS1_SHA1); + case EVP_PKEY_EC: + return ssl_sigalg_lookup(SIGALG_ECDSA_SHA1); +#ifndef OPENSSL_NO_GOST + case EVP_PKEY_GOSTR01: + return ssl_sigalg_lookup(SIGALG_GOSTR01_GOST94); +#endif + } + SSLerror(s, SSL_R_UNKNOWN_PKEY_TYPE); + return NULL; +} + +static int +ssl_sigalg_pkey_ok(SSL *s, const struct ssl_sigalg *sigalg, EVP_PKEY *pkey) +{ + if (sigalg == NULL || pkey == NULL) + return 0; + if (sigalg->key_type != EVP_PKEY_id(pkey)) + return 0; + + /* RSA PSS must have a sufficiently large RSA key. */ + if ((sigalg->flags & SIGALG_FLAG_RSA_PSS)) { + if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA || + EVP_PKEY_size(pkey) < (2 * EVP_MD_size(sigalg->md()) + 2)) + return 0; + } + + if (!ssl_security_sigalg_check(s, pkey)) + return 0; + + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION) + return 1; + + /* RSA cannot be used without PSS in TLSv1.3. */ + if (sigalg->key_type == EVP_PKEY_RSA && + (sigalg->flags & SIGALG_FLAG_RSA_PSS) == 0) + return 0; + + /* Ensure that group matches for EC keys. */ + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { + if (sigalg->group_nid == 0) + return 0; + if (EC_GROUP_get_curve_name(EC_KEY_get0_group( + EVP_PKEY_get0_EC_KEY(pkey))) != sigalg->group_nid) + return 0; + } + + return 1; +} + +const struct ssl_sigalg * +ssl_sigalg_select(SSL *s, EVP_PKEY *pkey) +{ + CBS cbs; + + if (!SSL_USE_SIGALGS(s)) + return ssl_sigalg_for_legacy(s, pkey); + + /* + * RFC 5246 allows a TLS 1.2 client to send no sigalgs extension, + * in which case the server must use the default. + */ + if (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION && + s->s3->hs.sigalgs == NULL) + return ssl_sigalg_for_legacy(s, pkey); + + /* + * If we get here, we have client or server sent sigalgs, use one. + */ + CBS_init(&cbs, s->s3->hs.sigalgs, s->s3->hs.sigalgs_len); + while (CBS_len(&cbs) > 0) { + const struct ssl_sigalg *sigalg; + uint16_t sigalg_value; + + if (!CBS_get_u16(&cbs, &sigalg_value)) + return NULL; + + if ((sigalg = ssl_sigalg_from_value(s, sigalg_value)) == NULL) + continue; + if (ssl_sigalg_pkey_ok(s, sigalg, pkey)) + return sigalg; + } + + SSLerror(s, SSL_R_UNKNOWN_PKEY_TYPE); + return NULL; +} + +const struct ssl_sigalg * +ssl_sigalg_for_peer(SSL *s, EVP_PKEY *pkey, uint16_t sigalg_value) +{ + const struct ssl_sigalg *sigalg; + + if (!SSL_USE_SIGALGS(s)) + return ssl_sigalg_for_legacy(s, pkey); + + if ((sigalg = ssl_sigalg_from_value(s, sigalg_value)) == NULL) { + SSLerror(s, SSL_R_UNKNOWN_DIGEST); + return NULL; + } + if (!ssl_sigalg_pkey_ok(s, sigalg, pkey)) { + SSLerror(s, SSL_R_WRONG_SIGNATURE_TYPE); + return NULL; + } + + return sigalg; +} diff --git a/ssl/ssl_sigalgs.h b/ssl/ssl_sigalgs.h new file mode 100644 index 0000000..21a54d6 --- /dev/null +++ b/ssl/ssl_sigalgs.h @@ -0,0 +1,79 @@ +/* $OpenBSD: ssl_sigalgs.h,v 1.26 2022/07/02 16:00:12 tb Exp $ */ +/* + * Copyright (c) 2018-2019 Bob Beck + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_SSL_SIGALGS_H +#define HEADER_SSL_SIGALGS_H + +__BEGIN_HIDDEN_DECLS + +#define SIGALG_NONE 0x0000 + +/* + * RFC 8446 Section 4.2.3 + * RFC 5246 Section 7.4.1.4.1 + */ +#define SIGALG_RSA_PKCS1_SHA224 0x0301 +#define SIGALG_RSA_PKCS1_SHA256 0x0401 +#define SIGALG_RSA_PKCS1_SHA384 0x0501 +#define SIGALG_RSA_PKCS1_SHA512 0x0601 +#define SIGALG_ECDSA_SECP224R1_SHA224 0x0303 +#define SIGALG_ECDSA_SECP256R1_SHA256 0x0403 +#define SIGALG_ECDSA_SECP384R1_SHA384 0x0503 +#define SIGALG_ECDSA_SECP521R1_SHA512 0x0603 +#define SIGALG_RSA_PSS_RSAE_SHA256 0x0804 +#define SIGALG_RSA_PSS_RSAE_SHA384 0x0805 +#define SIGALG_RSA_PSS_RSAE_SHA512 0x0806 +#define SIGALG_ED25519 0x0807 +#define SIGALG_ED448 0x0808 +#define SIGALG_RSA_PSS_PSS_SHA256 0x0809 +#define SIGALG_RSA_PSS_PSS_SHA384 0x080a +#define SIGALG_RSA_PSS_PSS_SHA512 0x080b +#define SIGALG_RSA_PKCS1_SHA1 0x0201 +#define SIGALG_ECDSA_SHA1 0x0203 +#define SIGALG_PRIVATE_START 0xFE00 +#define SIGALG_PRIVATE_END 0xFFFF + +/* + * If Russia can elect the US President, surely + * IANA could fix this problem. + */ +#define SIGALG_GOSTR12_512_STREEBOG_512 0xEFEF +#define SIGALG_GOSTR12_256_STREEBOG_256 0xEEEE +#define SIGALG_GOSTR01_GOST94 0xEDED + +/* Legacy sigalg for < TLSv1.2 same value as BoringSSL uses. */ +#define SIGALG_RSA_PKCS1_MD5_SHA1 0xFF01 + +#define SIGALG_FLAG_RSA_PSS 0x00000001 + +struct ssl_sigalg { + uint16_t value; + int key_type; + const EVP_MD *(*md)(void); + int security_level; + int group_nid; + int flags; +}; + +int ssl_sigalgs_build(uint16_t tls_version, CBB *cbb, int security_level); +const struct ssl_sigalg *ssl_sigalg_select(SSL *s, EVP_PKEY *pkey); +const struct ssl_sigalg *ssl_sigalg_for_peer(SSL *s, EVP_PKEY *pkey, + uint16_t sigalg_value); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/ssl_srvr.c b/ssl/ssl_srvr.c new file mode 100644 index 0000000..a518e1a --- /dev/null +++ b/ssl/ssl_srvr.c @@ -0,0 +1,2629 @@ +/* $OpenBSD: ssl_srvr.c,v 1.156 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * ECC cipher suite support in OpenSSL originally written by + * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_GOST +#include +#endif + +#include "bytestring.h" +#include "dtls_local.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" + +static int ssl3_get_client_hello(SSL *s); +static int ssl3_send_dtls_hello_verify_request(SSL *s); +static int ssl3_send_server_hello(SSL *s); +static int ssl3_send_hello_request(SSL *s); +static int ssl3_send_server_certificate(SSL *s); +static int ssl3_send_server_key_exchange(SSL *s); +static int ssl3_send_certificate_request(SSL *s); +static int ssl3_send_server_done(SSL *s); +static int ssl3_get_client_certificate(SSL *s); +static int ssl3_get_client_key_exchange(SSL *s); +static int ssl3_get_cert_verify(SSL *s); +static int ssl3_send_newsession_ticket(SSL *s); +static int ssl3_send_cert_status(SSL *s); +static int ssl3_send_server_change_cipher_spec(SSL *s); +static int ssl3_send_server_finished(SSL *s); +static int ssl3_get_client_finished(SSL *s); + +int +ssl3_accept(SSL *s) +{ + unsigned long alg_k; + int new_state, state, skip = 0; + int listen = 0; + int ret = -1; + + ERR_clear_error(); + errno = 0; + + if (SSL_is_dtls(s)) + listen = s->d1->listen; + + /* init things to blank */ + s->in_handshake++; + if (!SSL_in_init(s) || SSL_in_before(s)) + SSL_clear(s); + + if (SSL_is_dtls(s)) + s->d1->listen = listen; + + for (;;) { + state = s->s3->hs.state; + + switch (s->s3->hs.state) { + case SSL_ST_RENEGOTIATE: + s->renegotiate = 1; + /* s->s3->hs.state=SSL_ST_ACCEPT; */ + + case SSL_ST_BEFORE: + case SSL_ST_ACCEPT: + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + case SSL_ST_OK|SSL_ST_ACCEPT: + s->server = 1; + + ssl_info_callback(s, SSL_CB_HANDSHAKE_START, 1); + + if (!ssl_legacy_stack_version(s, s->version)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!ssl_supported_tls_version_range(s, + &s->s3->hs.our_min_tls_version, + &s->s3->hs.our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + ret = -1; + goto end; + } + + if (!ssl_security_version(s, + s->s3->hs.our_min_tls_version)) { + SSLerror(s, SSL_R_VERSION_TOO_LOW); + ret = -1; + goto end; + } + + if (!ssl3_setup_init_buffer(s)) { + ret = -1; + goto end; + } + if (!ssl3_setup_buffers(s)) { + ret = -1; + goto end; + } + + s->init_num = 0; + + if (s->s3->hs.state != SSL_ST_RENEGOTIATE) { + /* + * Ok, we now need to push on a buffering BIO + * so that the output is sent in a way that + * TCP likes :-) + */ + if (!ssl_init_wbio_buffer(s, 1)) { + ret = -1; + goto end; + } + + if (!tls1_transcript_init(s)) { + ret = -1; + goto end; + } + + s->s3->hs.state = SSL3_ST_SR_CLNT_HELLO_A; + s->ctx->stats.sess_accept++; + } else if (!SSL_is_dtls(s) && !s->s3->send_connection_binding) { + /* + * Server attempting to renegotiate with + * client that doesn't support secure + * renegotiation. + */ + SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + ret = -1; + goto end; + } else { + /* + * s->s3->hs.state == SSL_ST_RENEGOTIATE, + * we will just send a HelloRequest. + */ + s->ctx->stats.sess_accept_renegotiate++; + s->s3->hs.state = SSL3_ST_SW_HELLO_REQ_A; + } + break; + + case SSL3_ST_SW_HELLO_REQ_A: + case SSL3_ST_SW_HELLO_REQ_B: + s->shutdown = 0; + if (SSL_is_dtls(s)) { + dtls1_clear_record_buffer(s); + dtls1_start_timer(s); + } + ret = ssl3_send_hello_request(s); + if (ret <= 0) + goto end; + if (SSL_is_dtls(s)) + s->s3->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; + else + s->s3->hs.tls12.next_state = SSL3_ST_SW_HELLO_REQ_C; + s->s3->hs.state = SSL3_ST_SW_FLUSH; + s->init_num = 0; + + if (SSL_is_dtls(s)) { + if (!tls1_transcript_init(s)) { + ret = -1; + goto end; + } + } + break; + + case SSL3_ST_SW_HELLO_REQ_C: + s->s3->hs.state = SSL_ST_OK; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + case SSL3_ST_SR_CLNT_HELLO_B: + case SSL3_ST_SR_CLNT_HELLO_C: + s->shutdown = 0; + if (SSL_is_dtls(s)) { + ret = ssl3_get_client_hello(s); + if (ret <= 0) + goto end; + dtls1_stop_timer(s); + + if (ret == 1 && + (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) + s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A; + else + s->s3->hs.state = SSL3_ST_SW_SRVR_HELLO_A; + + s->init_num = 0; + + /* + * Reflect ClientHello sequence to remain + * stateless while listening. + */ + if (listen) { + tls12_record_layer_reflect_seq_num( + s->rl); + } + + /* If we're just listening, stop here */ + if (listen && s->s3->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { + ret = 2; + s->d1->listen = 0; + /* + * Set expected sequence numbers to + * continue the handshake. + */ + s->d1->handshake_read_seq = 2; + s->d1->handshake_write_seq = 1; + s->d1->next_handshake_write_seq = 1; + goto end; + } + } else { + if (s->rwstate != SSL_X509_LOOKUP) { + ret = ssl3_get_client_hello(s); + if (ret <= 0) + goto end; + } + + s->renegotiate = 2; + s->s3->hs.state = SSL3_ST_SW_SRVR_HELLO_A; + s->init_num = 0; + } + break; + + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + ret = ssl3_send_dtls_hello_verify_request(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_FLUSH; + s->s3->hs.tls12.next_state = SSL3_ST_SR_CLNT_HELLO_A; + + /* HelloVerifyRequest resets Finished MAC. */ + tls1_transcript_reset(s); + break; + + case SSL3_ST_SW_SRVR_HELLO_A: + case SSL3_ST_SW_SRVR_HELLO_B: + if (SSL_is_dtls(s)) { + s->renegotiate = 2; + dtls1_start_timer(s); + } + ret = ssl3_send_server_hello(s); + if (ret <= 0) + goto end; + if (s->hit) { + if (s->tlsext_ticket_expected) + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_A; + else + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; + } else { + s->s3->hs.state = SSL3_ST_SW_CERT_A; + } + s->init_num = 0; + break; + + case SSL3_ST_SW_CERT_A: + case SSL3_ST_SW_CERT_B: + /* Check if it is anon DH or anon ECDH. */ + if (!(s->s3->hs.cipher->algorithm_auth & + SSL_aNULL)) { + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_server_certificate(s); + if (ret <= 0) + goto end; + if (s->tlsext_status_expected) + s->s3->hs.state = SSL3_ST_SW_CERT_STATUS_A; + else + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; + } else { + skip = 1; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; + } + s->init_num = 0; + break; + + case SSL3_ST_SW_KEY_EXCH_A: + case SSL3_ST_SW_KEY_EXCH_B: + alg_k = s->s3->hs.cipher->algorithm_mkey; + + /* + * Only send if using a DH key exchange. + * + * For ECC ciphersuites, we send a ServerKeyExchange + * message only if the cipher suite is ECDHE. In other + * cases, the server certificate contains the server's + * public key for key exchange. + */ + if (alg_k & (SSL_kDHE|SSL_kECDHE)) { + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_server_key_exchange(s); + if (ret <= 0) + goto end; + } else + skip = 1; + + s->s3->hs.state = SSL3_ST_SW_CERT_REQ_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_CERT_REQ_A: + case SSL3_ST_SW_CERT_REQ_B: + /* + * Determine whether or not we need to request a + * certificate. + * + * Do not request a certificate if: + * + * - We did not ask for it (SSL_VERIFY_PEER is unset). + * + * - SSL_VERIFY_CLIENT_ONCE is set and we are + * renegotiating. + * + * - We are using an anonymous ciphersuites + * (see section "Certificate request" in SSL 3 drafts + * and in RFC 2246) ... except when the application + * insists on verification (against the specs, but + * s3_clnt.c accepts this for SSL 3). + */ + if (!(s->verify_mode & SSL_VERIFY_PEER) || + ((s->session->peer_cert != NULL) && + (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) || + ((s->s3->hs.cipher->algorithm_auth & + SSL_aNULL) && !(s->verify_mode & + SSL_VERIFY_FAIL_IF_NO_PEER_CERT))) { + /* No cert request. */ + skip = 1; + s->s3->hs.tls12.cert_request = 0; + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_A; + + if (!SSL_is_dtls(s)) + tls1_transcript_free(s); + } else { + s->s3->hs.tls12.cert_request = 1; + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_certificate_request(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_A; + s->init_num = 0; + } + break; + + case SSL3_ST_SW_SRVR_DONE_A: + case SSL3_ST_SW_SRVR_DONE_B: + if (SSL_is_dtls(s)) + dtls1_start_timer(s); + ret = ssl3_send_server_done(s); + if (ret <= 0) + goto end; + s->s3->hs.tls12.next_state = SSL3_ST_SR_CERT_A; + s->s3->hs.state = SSL3_ST_SW_FLUSH; + s->init_num = 0; + break; + + case SSL3_ST_SW_FLUSH: + /* + * This code originally checked to see if + * any data was pending using BIO_CTRL_INFO + * and then flushed. This caused problems + * as documented in PR#1939. The proposed + * fix doesn't completely resolve this issue + * as buggy implementations of BIO_CTRL_PENDING + * still exist. So instead we just flush + * unconditionally. + */ + s->rwstate = SSL_WRITING; + if (BIO_flush(s->wbio) <= 0) { + if (SSL_is_dtls(s)) { + /* If the write error was fatal, stop trying. */ + if (!BIO_should_retry(s->wbio)) { + s->rwstate = SSL_NOTHING; + s->s3->hs.state = s->s3->hs.tls12.next_state; + } + } + ret = -1; + goto end; + } + s->rwstate = SSL_NOTHING; + s->s3->hs.state = s->s3->hs.tls12.next_state; + break; + + case SSL3_ST_SR_CERT_A: + case SSL3_ST_SR_CERT_B: + if (s->s3->hs.tls12.cert_request != 0) { + ret = ssl3_get_client_certificate(s); + if (ret <= 0) + goto end; + } + s->init_num = 0; + s->s3->hs.state = SSL3_ST_SR_KEY_EXCH_A; + break; + + case SSL3_ST_SR_KEY_EXCH_A: + case SSL3_ST_SR_KEY_EXCH_B: + ret = ssl3_get_client_key_exchange(s); + if (ret <= 0) + goto end; + + if (SSL_is_dtls(s)) { + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + } + + alg_k = s->s3->hs.cipher->algorithm_mkey; + if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) { + /* + * A GOST client may use the key from its + * certificate for key exchange, in which case + * the CertificateVerify message is not sent. + */ + s->s3->hs.state = SSL3_ST_SR_FINISHED_A; + s->init_num = 0; + } else if (SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) { + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + if (!s->session->peer_cert) + break; + /* + * Freeze the transcript for use during client + * certificate verification. + */ + tls1_transcript_freeze(s); + } else { + s->s3->hs.state = SSL3_ST_SR_CERT_VRFY_A; + s->init_num = 0; + + tls1_transcript_free(s); + + /* + * We need to get hashes here so if there is + * a client cert, it can be verified. + */ + if (!tls1_transcript_hash_value(s, + s->s3->hs.tls12.cert_verify, + sizeof(s->s3->hs.tls12.cert_verify), + NULL)) { + ret = -1; + goto end; + } + } + break; + + case SSL3_ST_SR_CERT_VRFY_A: + case SSL3_ST_SR_CERT_VRFY_B: + if (SSL_is_dtls(s)) + s->d1->change_cipher_spec_ok = 1; + else + s->s3->flags |= SSL3_FLAGS_CCS_OK; + + /* we should decide if we expected this one */ + ret = ssl3_get_cert_verify(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SR_FINISHED_A; + s->init_num = 0; + break; + + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_SR_FINISHED_B: + if (SSL_is_dtls(s)) + s->d1->change_cipher_spec_ok = 1; + else + s->s3->flags |= SSL3_FLAGS_CCS_OK; + ret = ssl3_get_client_finished(s); + if (ret <= 0) + goto end; + if (SSL_is_dtls(s)) + dtls1_stop_timer(s); + if (s->hit) + s->s3->hs.state = SSL_ST_OK; + else if (s->tlsext_ticket_expected) + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_A; + else + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_SESSION_TICKET_A: + case SSL3_ST_SW_SESSION_TICKET_B: + ret = ssl3_send_newsession_ticket(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_CHANGE_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_CERT_STATUS_A: + case SSL3_ST_SW_CERT_STATUS_B: + ret = ssl3_send_cert_status(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_A; + s->init_num = 0; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_SW_CHANGE_B: + ret = ssl3_send_server_change_cipher_spec(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_FINISHED_A; + s->init_num = 0; + s->session->cipher = s->s3->hs.cipher; + + if (!tls1_setup_key_block(s)) { + ret = -1; + goto end; + } + if (!tls1_change_write_cipher_state(s)) { + ret = -1; + goto end; + } + break; + + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_SW_FINISHED_B: + ret = ssl3_send_server_finished(s); + if (ret <= 0) + goto end; + s->s3->hs.state = SSL3_ST_SW_FLUSH; + if (s->hit) { + s->s3->hs.tls12.next_state = SSL3_ST_SR_FINISHED_A; + tls1_transcript_free(s); + } else + s->s3->hs.tls12.next_state = SSL_ST_OK; + s->init_num = 0; + break; + + case SSL_ST_OK: + /* clean a few things up */ + tls1_cleanup_key_block(s); + + if (s->s3->handshake_transcript != NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ret = -1; + goto end; + } + + if (!SSL_is_dtls(s)) + ssl3_release_init_buffer(s); + + /* remove buffering on output */ + ssl_free_wbio_buffer(s); + + s->init_num = 0; + + /* Skipped if we just sent a HelloRequest. */ + if (s->renegotiate == 2) { + s->renegotiate = 0; + s->new_session = 0; + + ssl_update_cache(s, SSL_SESS_CACHE_SERVER); + + s->ctx->stats.sess_accept_good++; + /* s->server=1; */ + s->handshake_func = ssl3_accept; + + ssl_info_callback(s, SSL_CB_HANDSHAKE_DONE, 1); + } + + ret = 1; + + if (SSL_is_dtls(s)) { + /* Done handshaking, next message is client hello. */ + s->d1->handshake_read_seq = 0; + /* Next message is server hello. */ + s->d1->handshake_write_seq = 0; + s->d1->next_handshake_write_seq = 0; + } + goto end; + /* break; */ + + default: + SSLerror(s, SSL_R_UNKNOWN_STATE); + ret = -1; + goto end; + /* break; */ + } + + if (!s->s3->hs.tls12.reuse_message && !skip) { + if (s->debug) { + if ((ret = BIO_flush(s->wbio)) <= 0) + goto end; + } + + + if (s->s3->hs.state != state) { + new_state = s->s3->hs.state; + s->s3->hs.state = state; + ssl_info_callback(s, SSL_CB_ACCEPT_LOOP, 1); + s->s3->hs.state = new_state; + } + } + skip = 0; + } + end: + /* BIO_flush(s->wbio); */ + s->in_handshake--; + ssl_info_callback(s, SSL_CB_ACCEPT_EXIT, ret); + + return (ret); +} + +static int +ssl3_send_hello_request(SSL *s) +{ + CBB cbb, hello; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_HELLO_REQ_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &hello, + SSL3_MT_HELLO_REQUEST)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_HELLO_REQ_B; + } + + /* SSL3_ST_SW_HELLO_REQ_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_get_client_hello(SSL *s) +{ + CBS cbs, client_random, session_id, cookie, cipher_suites; + CBS compression_methods; + uint16_t client_version; + uint8_t comp_method; + int comp_null; + int i, j, al, ret, cookie_valid = 0; + unsigned long id; + SSL_CIPHER *c; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + unsigned long alg_k; + const SSL_METHOD *method; + uint16_t shared_version; + + /* + * We do this so that we will respond with our native type. + * If we are TLSv1 and we get SSLv3, we will respond with TLSv1, + * This down switching should be handled by a different method. + * If we are SSLv3, we will respond with SSLv3, even if prompted with + * TLSv1. + */ + if (s->s3->hs.state == SSL3_ST_SR_CLNT_HELLO_A) + s->s3->hs.state = SSL3_ST_SR_CLNT_HELLO_B; + + s->first_packet = 1; + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CLNT_HELLO_B, + SSL3_ST_SR_CLNT_HELLO_C, SSL3_MT_CLIENT_HELLO, + SSL3_RT_MAX_PLAIN_LENGTH)) <= 0) + return ret; + s->first_packet = 0; + + ret = -1; + + if (s->init_num < 0) + goto err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + /* Parse client hello up until the extensions (if any). */ + if (!CBS_get_u16(&cbs, &client_version)) + goto decode_err; + if (!CBS_get_bytes(&cbs, &client_random, SSL3_RANDOM_SIZE)) + goto decode_err; + if (!CBS_get_u8_length_prefixed(&cbs, &session_id)) + goto decode_err; + if (CBS_len(&session_id) > SSL3_SESSION_ID_SIZE) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_SSL3_SESSION_ID_TOO_LONG); + goto fatal_err; + } + if (SSL_is_dtls(s)) { + if (!CBS_get_u8_length_prefixed(&cbs, &cookie)) + goto decode_err; + } + if (!CBS_get_u16_length_prefixed(&cbs, &cipher_suites)) + goto decode_err; + if (!CBS_get_u8_length_prefixed(&cbs, &compression_methods)) + goto decode_err; + + /* + * Use version from inside client hello, not from record header. + * (may differ: see RFC 2246, Appendix E, second paragraph) + */ + if (!ssl_max_shared_version(s, client_version, &shared_version)) { + if ((client_version >> 8) == SSL3_VERSION_MAJOR && + !tls12_record_layer_write_protected(s->rl)) { + /* + * Similar to ssl3_get_record, send alert using remote + * version number. + */ + s->version = client_version; + } + SSLerror(s, SSL_R_WRONG_VERSION_NUMBER); + al = SSL_AD_PROTOCOL_VERSION; + goto fatal_err; + } + s->s3->hs.peer_legacy_version = client_version; + s->version = shared_version; + + s->s3->hs.negotiated_tls_version = ssl_tls_version(shared_version); + if (s->s3->hs.negotiated_tls_version == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if ((method = ssl_get_method(shared_version)) == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + s->method = method; + + /* + * If we require cookies (DTLS) and this ClientHello does not contain + * one, just return since we do not want to allocate any memory yet. + * So check cookie length... + */ + if (SSL_is_dtls(s)) { + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + if (CBS_len(&cookie) == 0) + return (1); + } + } + + if (!CBS_write_bytes(&client_random, s->s3->client_random, + sizeof(s->s3->client_random), NULL)) + goto err; + + s->hit = 0; + + /* + * Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag + * rather than a change to default behavior so that applications + * relying on this for security won't even compile against older + * library versions). + * + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() + * to request renegotiation but not a new session (s->new_session + * remains unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be + * ignored. + */ + if ((s->new_session && (s->options & + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { + if (!ssl_get_new_session(s, 1)) + goto err; + } else { + CBS ext_block; + + CBS_dup(&cbs, &ext_block); + + i = ssl_get_prev_session(s, &session_id, &ext_block, &al); + if (i == 1) { /* previous session */ + s->hit = 1; + } else if (i == -1) + goto fatal_err; + else { + /* i == 0 */ + if (!ssl_get_new_session(s, 1)) + goto err; + } + } + + if (SSL_is_dtls(s)) { + /* + * The ClientHello may contain a cookie even if the HelloVerify + * message has not been sent - make sure that it does not cause + * an overflow. + */ + if (CBS_len(&cookie) > sizeof(s->d1->rcvd_cookie)) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_COOKIE_MISMATCH); + goto fatal_err; + } + + /* Verify the cookie if appropriate option is set. */ + if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && + CBS_len(&cookie) > 0) { + size_t cookie_len; + + /* XXX - rcvd_cookie seems to only be used here... */ + if (!CBS_write_bytes(&cookie, s->d1->rcvd_cookie, + sizeof(s->d1->rcvd_cookie), &cookie_len)) + goto err; + + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, + s->d1->rcvd_cookie, cookie_len) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_COOKIE_MISMATCH); + goto fatal_err; + } + /* else cookie verification succeeded */ + /* XXX - can d1->cookie_len > sizeof(rcvd_cookie) ? */ + } else if (timingsafe_memcmp(s->d1->rcvd_cookie, + s->d1->cookie, s->d1->cookie_len) != 0) { + /* default verification */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_COOKIE_MISMATCH); + goto fatal_err; + } + cookie_valid = 1; + } + } + + /* XXX - This logic seems wrong... */ + if (CBS_len(&cipher_suites) == 0 && CBS_len(&session_id) != 0) { + /* we need a cipher if we are not resuming a session */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_NO_CIPHERS_SPECIFIED); + goto fatal_err; + } + + if (CBS_len(&cipher_suites) > 0) { + if ((ciphers = ssl_bytes_to_cipher_list(s, + &cipher_suites)) == NULL) + goto err; + } + + /* If it is a hit, check that the cipher is in the list */ + /* XXX - CBS_len(&cipher_suites) will always be zero here... */ + if (s->hit && CBS_len(&cipher_suites) > 0) { + j = 0; + id = s->session->cipher->id; + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + c = sk_SSL_CIPHER_value(ciphers, i); + if (c->id == id) { + j = 1; + break; + } + } + if (j == 0) { + /* + * We need to have the cipher in the cipher + * list if we are asked to reuse it + */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_REQUIRED_CIPHER_MISSING); + goto fatal_err; + } + } + + comp_null = 0; + while (CBS_len(&compression_methods) > 0) { + if (!CBS_get_u8(&compression_methods, &comp_method)) + goto decode_err; + if (comp_method == 0) + comp_null = 1; + } + if (comp_null == 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_NO_COMPRESSION_SPECIFIED); + goto fatal_err; + } + + if (!tlsext_server_parse(s, SSL_TLSEXT_MSG_CH, &cbs, &al)) { + SSLerror(s, SSL_R_PARSE_TLSEXT); + goto fatal_err; + } + + if (CBS_len(&cbs) != 0) + goto decode_err; + + if (!s->s3->renegotiate_seen && s->renegotiate) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); + goto fatal_err; + } + + if (ssl_check_clienthello_tlsext_early(s) <= 0) { + SSLerror(s, SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } + + /* + * Check if we want to use external pre-shared secret for this + * handshake for not reused session only. We need to generate + * server_random before calling tls_session_secret_cb in order to allow + * SessionTicket processing to use it in key derivation. + */ + arc4random_buf(s->s3->server_random, SSL3_RANDOM_SIZE); + + if (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION && + s->s3->hs.negotiated_tls_version < s->s3->hs.our_max_tls_version) { + /* + * RFC 8446 section 4.1.3. If we are downgrading from TLS 1.3 + * we must set the last 8 bytes of the server random to magical + * values to indicate we meant to downgrade. For TLS 1.2 it is + * recommended that we do the same. + */ + size_t index = SSL3_RANDOM_SIZE - sizeof(tls13_downgrade_12); + uint8_t *magic = &s->s3->server_random[index]; + if (s->s3->hs.negotiated_tls_version == TLS1_2_VERSION) { + /* Indicate we chose to downgrade to 1.2. */ + memcpy(magic, tls13_downgrade_12, + sizeof(tls13_downgrade_12)); + } else { + /* Indicate we chose to downgrade to 1.1 or lower */ + memcpy(magic, tls13_downgrade_11, + sizeof(tls13_downgrade_11)); + } + } + + if (!s->hit && s->tls_session_secret_cb != NULL) { + SSL_CIPHER *pref_cipher = NULL; + int master_key_length = sizeof(s->session->master_key); + + if (!s->tls_session_secret_cb(s, + s->session->master_key, &master_key_length, ciphers, + &pref_cipher, s->tls_session_secret_cb_arg)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (master_key_length <= 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + s->session->master_key_length = master_key_length; + + s->hit = 1; + s->session->verify_result = X509_V_OK; + + sk_SSL_CIPHER_free(s->session->ciphers); + s->session->ciphers = ciphers; + ciphers = NULL; + + /* Check if some cipher was preferred by the callback. */ + if (pref_cipher == NULL) + pref_cipher = ssl3_choose_cipher(s, s->session->ciphers, + SSL_get_ciphers(s)); + if (pref_cipher == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_NO_SHARED_CIPHER); + goto fatal_err; + } + s->session->cipher = pref_cipher; + + sk_SSL_CIPHER_free(s->cipher_list); + s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); + } + + /* + * Given s->session->ciphers and SSL_get_ciphers, we must + * pick a cipher + */ + + if (!s->hit) { + if (ciphers == NULL) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerror(s, SSL_R_NO_CIPHERS_PASSED); + goto fatal_err; + } + sk_SSL_CIPHER_free(s->session->ciphers); + s->session->ciphers = ciphers; + ciphers = NULL; + + if ((c = ssl3_choose_cipher(s, s->session->ciphers, + SSL_get_ciphers(s))) == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_NO_SHARED_CIPHER); + goto fatal_err; + } + s->s3->hs.cipher = c; + } else { + s->s3->hs.cipher = s->session->cipher; + } + + if (!tls1_transcript_hash_init(s)) + goto err; + + alg_k = s->s3->hs.cipher->algorithm_mkey; + if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) || + !(s->verify_mode & SSL_VERIFY_PEER)) + tls1_transcript_free(s); + + /* + * We now have the following setup. + * client_random + * cipher_list - our preferred list of ciphers + * ciphers - the clients preferred list of ciphers + * compression - basically ignored right now + * ssl version is set - sslv3 + * s->session - The ssl session has been setup. + * s->hit - session reuse flag + * s->hs.cipher - the new cipher to use. + */ + + /* Handles TLS extensions that we couldn't check earlier */ + if (ssl_check_clienthello_tlsext_late(s) <= 0) { + SSLerror(s, SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } + + ret = cookie_valid ? 2 : 1; + + if (0) { + decode_err: + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: + sk_SSL_CIPHER_free(ciphers); + + return (ret); +} + +static int +ssl3_send_dtls_hello_verify_request(SSL *s) +{ + CBB cbb, verify, cookie; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A) { + if (s->ctx->app_gen_cookie_cb == NULL || + s->ctx->app_gen_cookie_cb(s, s->d1->cookie, + &(s->d1->cookie_len)) == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * Per RFC 6347 section 4.2.1, the HelloVerifyRequest should + * always contain DTLSv1.0 regardless of the version that is + * going to be negotiated. + */ + if (!ssl3_handshake_msg_start(s, &cbb, &verify, + DTLS1_MT_HELLO_VERIFY_REQUEST)) + goto err; + if (!CBB_add_u16(&verify, DTLS1_VERSION)) + goto err; + if (!CBB_add_u8_length_prefixed(&verify, &cookie)) + goto err; + if (!CBB_add_bytes(&cookie, s->d1->cookie, s->d1->cookie_len)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B; + } + + /* s->s3->hs.state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_server_hello(SSL *s) +{ + CBB cbb, server_hello, session_id; + size_t sl; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_SRVR_HELLO_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &server_hello, + SSL3_MT_SERVER_HELLO)) + goto err; + + if (!CBB_add_u16(&server_hello, s->version)) + goto err; + if (!CBB_add_bytes(&server_hello, s->s3->server_random, + sizeof(s->s3->server_random))) + goto err; + + /* + * There are several cases for the session ID to send + * back in the server hello: + * + * - For session reuse from the session cache, + * we send back the old session ID. + * - If stateless session reuse (using a session ticket) + * is successful, we send back the client's "session ID" + * (which doesn't actually identify the session). + * - If it is a new session, we send back the new + * session ID. + * - However, if we want the new session to be single-use, + * we send back a 0-length session ID. + * + * s->hit is non-zero in either case of session reuse, + * so the following won't overwrite an ID that we're supposed + * to send back. + */ + if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit) + s->session->session_id_length = 0; + + sl = s->session->session_id_length; + if (sl > sizeof(s->session->session_id)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!CBB_add_u8_length_prefixed(&server_hello, &session_id)) + goto err; + if (!CBB_add_bytes(&session_id, s->session->session_id, sl)) + goto err; + + /* Cipher suite. */ + if (!CBB_add_u16(&server_hello, + ssl3_cipher_get_value(s->s3->hs.cipher))) + goto err; + + /* Compression method (null). */ + if (!CBB_add_u8(&server_hello, 0)) + goto err; + + /* TLS extensions */ + if (!tlsext_server_build(s, SSL_TLSEXT_MSG_SH, &server_hello)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + } + + /* SSL3_ST_SW_SRVR_HELLO_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_server_done(SSL *s) +{ + CBB cbb, done; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_SRVR_DONE_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &done, + SSL3_MT_SERVER_DONE)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_SRVR_DONE_B; + } + + /* SSL3_ST_SW_SRVR_DONE_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_server_kex_dhe(SSL *s, CBB *cbb) +{ + int nid = NID_dhKeyAgreement; + + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; + + if (s->cert->dhe_params_auto != 0) { + size_t key_bits; + + if ((key_bits = ssl_dhe_params_auto_key_bits(s)) == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_INTERNAL_ERROR); + goto err; + } + tls_key_share_set_key_bits(s->s3->hs.key_share, + key_bits); + } else { + DH *dh_params = s->cert->dhe_params; + + if (dh_params == NULL && s->cert->dhe_params_cb != NULL) + dh_params = s->cert->dhe_params_cb(s, 0, + SSL_C_PKEYLENGTH(s->s3->hs.cipher)); + + if (dh_params == NULL) { + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + ssl3_send_alert(s, SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + + if (!tls_key_share_set_dh_params(s->s3->hs.key_share, dh_params)) + goto err; + } + + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + + if (!tls_key_share_params(s->s3->hs.key_share, cbb)) + goto err; + if (!tls_key_share_public(s->s3->hs.key_share, cbb)) + goto err; + + if (!tls_key_share_peer_security(s, s->s3->hs.key_share)) { + SSLerror(s, SSL_R_DH_KEY_TOO_SMALL); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + return 0; + } + + return 1; + + err: + return 0; +} + +static int +ssl3_send_server_kex_ecdhe(SSL *s, CBB *cbb) +{ + CBB public; + int nid; + + if (!tls1_get_supported_group(s, &nid)) { + SSLerror(s, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + + tls_key_share_free(s->s3->hs.key_share); + if ((s->s3->hs.key_share = tls_key_share_new_nid(nid)) == NULL) + goto err; + + if (!tls_key_share_generate(s->s3->hs.key_share)) + goto err; + + /* + * ECC key exchange - see RFC 8422, section 5.4. + */ + if (!CBB_add_u8(cbb, NAMED_CURVE_TYPE)) + goto err; + if (!CBB_add_u16(cbb, tls_key_share_group(s->s3->hs.key_share))) + goto err; + if (!CBB_add_u8_length_prefixed(cbb, &public)) + goto err; + if (!tls_key_share_public(s->s3->hs.key_share, &public)) + goto err; + if (!CBB_flush(cbb)) + goto err; + + return 1; + + err: + return 0; +} + +static int +ssl3_send_server_key_exchange(SSL *s) +{ + CBB cbb, cbb_signature, cbb_signed_params, server_kex; + CBS params; + const struct ssl_sigalg *sigalg = NULL; + unsigned char *signed_params = NULL; + size_t signed_params_len; + unsigned char *signature = NULL; + size_t signature_len = 0; + const EVP_MD *md = NULL; + unsigned long type; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + int al; + + memset(&cbb, 0, sizeof(cbb)); + memset(&cbb_signed_params, 0, sizeof(cbb_signed_params)); + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + + if (s->s3->hs.state == SSL3_ST_SW_KEY_EXCH_A) { + + if (!ssl3_handshake_msg_start(s, &cbb, &server_kex, + SSL3_MT_SERVER_KEY_EXCHANGE)) + goto err; + + if (!CBB_init(&cbb_signed_params, 0)) + goto err; + + if (!CBB_add_bytes(&cbb_signed_params, s->s3->client_random, + SSL3_RANDOM_SIZE)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if (!CBB_add_bytes(&cbb_signed_params, s->s3->server_random, + SSL3_RANDOM_SIZE)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + + type = s->s3->hs.cipher->algorithm_mkey; + if (type & SSL_kDHE) { + if (!ssl3_send_server_kex_dhe(s, &cbb_signed_params)) + goto err; + } else if (type & SSL_kECDHE) { + if (!ssl3_send_server_kex_ecdhe(s, &cbb_signed_params)) + goto err; + } else { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + goto fatal_err; + } + + if (!CBB_finish(&cbb_signed_params, &signed_params, + &signed_params_len)) + goto err; + + CBS_init(¶ms, signed_params, signed_params_len); + if (!CBS_skip(¶ms, 2 * SSL3_RANDOM_SIZE)) + goto err; + + if (!CBB_add_bytes(&server_kex, CBS_data(¶ms), + CBS_len(¶ms))) + goto err; + + /* Add signature unless anonymous. */ + if (!(s->s3->hs.cipher->algorithm_auth & SSL_aNULL)) { + if ((pkey = ssl_get_sign_pkey(s, s->s3->hs.cipher, + &md, &sigalg)) == NULL) { + al = SSL_AD_DECODE_ERROR; + goto fatal_err; + } + s->s3->hs.our_sigalg = sigalg; + + /* Send signature algorithm. */ + if (SSL_USE_SIGALGS(s)) { + if (!CBB_add_u16(&server_kex, sigalg->value)) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto fatal_err; + } + } + + if (!EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if ((sigalg->flags & SIGALG_FLAG_RSA_PSS) && + (!EVP_PKEY_CTX_set_rsa_padding(pctx, + RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (!EVP_DigestSign(md_ctx, NULL, &signature_len, + signed_params, signed_params_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if ((signature = calloc(1, signature_len)) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestSign(md_ctx, signature, &signature_len, + signed_params, signed_params_len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + if (!CBB_add_u16_length_prefixed(&server_kex, + &cbb_signature)) + goto err; + if (!CBB_add_bytes(&cbb_signature, signature, + signature_len)) + goto err; + } + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_KEY_EXCH_B; + } + + EVP_MD_CTX_free(md_ctx); + free(signature); + free(signed_params); + + return (ssl3_handshake_write(s)); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + CBB_cleanup(&cbb_signed_params); + CBB_cleanup(&cbb); + EVP_MD_CTX_free(md_ctx); + free(signature); + free(signed_params); + + return (-1); +} + +static int +ssl3_send_certificate_request(SSL *s) +{ + CBB cbb, cert_request, cert_types, sigalgs, cert_auth, dn; + STACK_OF(X509_NAME) *sk = NULL; + X509_NAME *name; + int i; + + /* + * Certificate Request - RFC 5246 section 7.4.4. + */ + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_CERT_REQ_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &cert_request, + SSL3_MT_CERTIFICATE_REQUEST)) + goto err; + + if (!CBB_add_u8_length_prefixed(&cert_request, &cert_types)) + goto err; + if (!ssl3_get_req_cert_types(s, &cert_types)) + goto err; + + if (SSL_USE_SIGALGS(s)) { + if (!CBB_add_u16_length_prefixed(&cert_request, + &sigalgs)) + goto err; + if (!ssl_sigalgs_build(s->s3->hs.negotiated_tls_version, + &sigalgs, SSL_get_security_level(s))) + goto err; + } + + if (!CBB_add_u16_length_prefixed(&cert_request, &cert_auth)) + goto err; + + sk = SSL_get_client_CA_list(s); + for (i = 0; i < sk_X509_NAME_num(sk); i++) { + unsigned char *name_data; + size_t name_len; + + name = sk_X509_NAME_value(sk, i); + name_len = i2d_X509_NAME(name, NULL); + + if (!CBB_add_u16_length_prefixed(&cert_auth, &dn)) + goto err; + if (!CBB_add_space(&dn, &name_data, name_len)) + goto err; + if (i2d_X509_NAME(name, &name_data) != name_len) + goto err; + } + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_CERT_REQ_B; + } + + /* SSL3_ST_SW_CERT_REQ_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) +{ + unsigned char fakekey[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char *pms = NULL; + unsigned char *p; + size_t pms_len = 0; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; + CBS enc_pms; + int decrypt_len; + int al = -1; + + arc4random_buf(fakekey, sizeof(fakekey)); + + fakekey[0] = s->s3->hs.peer_legacy_version >> 8; + fakekey[1] = s->s3->hs.peer_legacy_version & 0xff; + + pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey; + if (pkey == NULL || (rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_MISSING_RSA_CERTIFICATE); + goto fatal_err; + } + + pms_len = RSA_size(rsa); + if (pms_len < SSL_MAX_MASTER_KEY_LENGTH) + goto err; + if ((pms = malloc(pms_len)) == NULL) + goto err; + p = pms; + + if (!CBS_get_u16_length_prefixed(cbs, &enc_pms)) + goto decode_err; + if (CBS_len(cbs) != 0 || CBS_len(&enc_pms) != RSA_size(rsa)) { + SSLerror(s, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); + goto err; + } + + decrypt_len = RSA_private_decrypt(CBS_len(&enc_pms), CBS_data(&enc_pms), + pms, rsa, RSA_PKCS1_PADDING); + + ERR_clear_error(); + + if (decrypt_len != SSL_MAX_MASTER_KEY_LENGTH) { + al = SSL_AD_DECODE_ERROR; + /* SSLerror(s, SSL_R_BAD_RSA_DECRYPT); */ + } + + if ((al == -1) && !((pms[0] == (s->s3->hs.peer_legacy_version >> 8)) && + (pms[1] == (s->s3->hs.peer_legacy_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). + * + * 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" -- an alert would + * reveal that the plaintext corresponding to some ciphertext + * made up by the adversary is properly formatted except that + * the version number is wrong. To avoid such attacks, we should + * treat this just like any other decryption error. + */ + al = SSL_AD_DECODE_ERROR; + /* SSLerror(s, SSL_R_BAD_PROTOCOL_VERSION_NUMBER); */ + } + + if (al != -1) { + /* + * Some decryption failure -- use random value instead + * as countermeasure against Bleichenbacher's attack + * on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). + */ + p = fakekey; + } + + if (!tls12_derive_master_secret(s, p, SSL_MAX_MASTER_KEY_LENGTH)) + goto err; + + freezero(pms, pms_len); + + return 1; + + decode_err: + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + freezero(pms, pms_len); + + return 0; +} + +static int +ssl3_get_client_kex_dhe(SSL *s, CBS *cbs) +{ + uint8_t *key = NULL; + size_t key_len = 0; + int decode_error, invalid_key; + int ret = 0; + + if (s->s3->hs.key_share == NULL) { + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + goto err; + } + + if (!tls_key_share_peer_public(s->s3->hs.key_share, cbs, + &decode_error, &invalid_key)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + if (invalid_key) { + SSLerror(s, SSL_R_BAD_DH_PUB_KEY_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); + goto err; + } + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + +static int +ssl3_get_client_kex_ecdhe(SSL *s, CBS *cbs) +{ + uint8_t *key = NULL; + size_t key_len = 0; + int decode_error; + CBS public; + int ret = 0; + + if (s->s3->hs.key_share == NULL) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + SSLerror(s, SSL_R_MISSING_TMP_DH_KEY); + goto err; + } + + if (!CBS_get_u8_length_prefixed(cbs, &public)) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + goto err; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, &public, + &decode_error, NULL)) { + if (decode_error) { + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + } + goto err; + } + + if (!tls_key_share_derive(s->s3->hs.key_share, &key, &key_len)) + goto err; + + if (!tls12_derive_master_secret(s, key, key_len)) + goto err; + + ret = 1; + + err: + freezero(key, key_len); + + return ret; +} + +static int +ssl3_get_client_kex_gost(SSL *s, CBS *cbs) +{ + unsigned char premaster_secret[32]; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *client_pubkey; + EVP_PKEY *pkey = NULL; + size_t outlen; + CBS gostblob; + + /* Get our certificate private key*/ +#ifndef OPENSSL_NO_GOST + if ((s->s3->hs.cipher->algorithm_auth & SSL_aGOST01) != 0) + pkey = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; +#endif + + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) + goto err; + if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) + goto err; + + /* + * If client certificate is present and is of the same type, + * maybe use it for key exchange. + * Don't mind errors from EVP_PKEY_derive_set_peer, because + * it is completely valid to use a client certificate for + * authorization only. + */ + if ((client_pubkey = X509_get0_pubkey(s->session->peer_cert)) != NULL) { + if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pubkey) <= 0) + ERR_clear_error(); + } + + /* Decrypt session key */ + if (!CBS_get_asn1(cbs, &gostblob, CBS_ASN1_SEQUENCE)) + goto decode_err; + if (CBS_len(cbs) != 0) + goto decode_err; + outlen = sizeof(premaster_secret); + if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, + CBS_data(&gostblob), CBS_len(&gostblob)) <= 0) { + SSLerror(s, SSL_R_DECRYPTION_FAILED); + goto err; + } + + if (!tls12_derive_master_secret(s, premaster_secret, + sizeof(premaster_secret))) + goto err; + + /* Check if pubkey from client certificate was used */ + if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, + 2, NULL) > 0) + s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY; + + explicit_bzero(premaster_secret, sizeof(premaster_secret)); + EVP_PKEY_CTX_free(pkey_ctx); + + return 1; + + decode_err: + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + err: + explicit_bzero(premaster_secret, sizeof(premaster_secret)); + EVP_PKEY_CTX_free(pkey_ctx); + + return 0; +} + +static int +ssl3_get_client_key_exchange(SSL *s) +{ + unsigned long alg_k; + int al, ret; + CBS cbs; + + /* 2048 maxlen is a guess. How long a key does that permit? */ + if ((ret = ssl3_get_message(s, SSL3_ST_SR_KEY_EXCH_A, + SSL3_ST_SR_KEY_EXCH_B, SSL3_MT_CLIENT_KEY_EXCHANGE, 2048)) <= 0) + return ret; + + if (s->init_num < 0) + goto err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + alg_k = s->s3->hs.cipher->algorithm_mkey; + + if (alg_k & SSL_kRSA) { + if (!ssl3_get_client_kex_rsa(s, &cbs)) + goto err; + } else if (alg_k & SSL_kDHE) { + if (!ssl3_get_client_kex_dhe(s, &cbs)) + goto err; + } else if (alg_k & SSL_kECDHE) { + if (!ssl3_get_client_kex_ecdhe(s, &cbs)) + goto err; + } else if (alg_k & SSL_kGOST) { + if (!ssl3_get_client_kex_gost(s, &cbs)) + goto err; + } else { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerror(s, SSL_R_UNKNOWN_CIPHER_TYPE); + goto fatal_err; + } + + if (CBS_len(&cbs) != 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + goto fatal_err; + } + + return (1); + + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (-1); +} + +static int +ssl3_get_cert_verify(SSL *s) +{ + CBS cbs, signature; + const struct ssl_sigalg *sigalg = NULL; + uint16_t sigalg_value = SIGALG_NONE; + EVP_PKEY *pkey; + X509 *peer_cert = NULL; + EVP_MD_CTX *mctx = NULL; + int al, verify; + const unsigned char *hdata; + size_t hdatalen; + int type = 0; + int ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_VRFY_A, + SSL3_ST_SR_CERT_VRFY_B, -1, SSL3_RT_MAX_PLAIN_LENGTH)) <= 0) + return ret; + + ret = 0; + + if (s->init_num < 0) + goto err; + + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + peer_cert = s->session->peer_cert; + pkey = X509_get0_pubkey(peer_cert); + type = X509_certificate_type(peer_cert, pkey); + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE_VERIFY) { + s->s3->hs.tls12.reuse_message = 1; + if (peer_cert != NULL) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_MISSING_VERIFY_MESSAGE); + goto fatal_err; + } + ret = 1; + goto end; + } + + if (peer_cert == NULL) { + SSLerror(s, SSL_R_NO_CLIENT_CERT_RECEIVED); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto fatal_err; + } + + if (!(type & EVP_PKT_SIGN)) { + SSLerror(s, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE); + al = SSL_AD_ILLEGAL_PARAMETER; + goto fatal_err; + } + + if (s->s3->change_cipher_spec) { + SSLerror(s, SSL_R_CCS_RECEIVED_EARLY); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto fatal_err; + } + + if (SSL_USE_SIGALGS(s)) { + if (!CBS_get_u16(&cbs, &sigalg_value)) + goto decode_err; + } + if (!CBS_get_u16_length_prefixed(&cbs, &signature)) + goto err; + if (CBS_len(&cbs) != 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_EXTRA_DATA_IN_MESSAGE); + goto fatal_err; + } + + if (CBS_len(&signature) > EVP_PKEY_size(pkey)) { + SSLerror(s, SSL_R_WRONG_SIGNATURE_SIZE); + al = SSL_AD_DECODE_ERROR; + goto fatal_err; + } + + if ((sigalg = ssl_sigalg_for_peer(s, pkey, + sigalg_value)) == NULL) { + al = SSL_AD_DECODE_ERROR; + goto fatal_err; + } + s->s3->hs.peer_sigalg = sigalg; + + if (SSL_USE_SIGALGS(s)) { + EVP_PKEY_CTX *pctx; + + if (!tls1_transcript_data(s, &hdata, &hdatalen)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + if (!EVP_DigestVerifyInit(mctx, &pctx, sigalg->md(), + NULL, pkey)) { + SSLerror(s, ERR_R_EVP_LIB); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + if ((sigalg->flags & SIGALG_FLAG_RSA_PSS) && + (!EVP_PKEY_CTX_set_rsa_padding(pctx, + RSA_PKCS1_PSS_PADDING) || + !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1))) { + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } +#ifndef OPENSSL_NO_GOST + if (sigalg->key_type == EVP_PKEY_GOSTR01 && + EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_VERIFY, + EVP_PKEY_CTRL_GOST_SIG_FORMAT, GOST_SIG_FORMAT_RS_LE, + NULL) <= 0) { + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } +#endif + if (EVP_DigestVerify(mctx, CBS_data(&signature), + CBS_len(&signature), hdata, hdatalen) <= 0) { + SSLerror(s, ERR_R_EVP_LIB); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + RSA *rsa; + + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_EVP_LIB); + goto fatal_err; + } + verify = RSA_verify(NID_md5_sha1, s->s3->hs.tls12.cert_verify, + MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, CBS_data(&signature), + CBS_len(&signature), rsa); + if (verify < 0) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_BAD_RSA_DECRYPT); + goto fatal_err; + } + if (verify == 0) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_BAD_RSA_SIGNATURE); + goto fatal_err; + } + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { + EC_KEY *eckey; + + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerror(s, ERR_R_EVP_LIB); + goto fatal_err; + } + verify = ECDSA_verify(0, + &(s->s3->hs.tls12.cert_verify[MD5_DIGEST_LENGTH]), + SHA_DIGEST_LENGTH, CBS_data(&signature), + CBS_len(&signature), eckey); + if (verify <= 0) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_BAD_ECDSA_SIGNATURE); + goto fatal_err; + } +#ifndef OPENSSL_NO_GOST + } else if (EVP_PKEY_id(pkey) == NID_id_GostR3410_94 || + EVP_PKEY_id(pkey) == NID_id_GostR3410_2001) { + unsigned char sigbuf[128]; + unsigned int siglen = sizeof(sigbuf); + EVP_PKEY_CTX *pctx; + const EVP_MD *md; + int nid; + + if (!tls1_transcript_data(s, &hdata, &hdatalen)) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + if (!EVP_PKEY_get_default_digest_nid(pkey, &nid) || + !(md = EVP_get_digestbynid(nid))) { + SSLerror(s, ERR_R_EVP_LIB); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + SSLerror(s, ERR_R_EVP_LIB); + al = SSL_AD_INTERNAL_ERROR; + goto fatal_err; + } + if (!EVP_DigestInit_ex(mctx, md, NULL) || + !EVP_DigestUpdate(mctx, hdata, hdatalen) || + !EVP_DigestFinal(mctx, sigbuf, &siglen) || + (EVP_PKEY_verify_init(pctx) <= 0) || + (EVP_PKEY_CTX_set_signature_md(pctx, md) <= 0) || + (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_VERIFY, + EVP_PKEY_CTRL_GOST_SIG_FORMAT, + GOST_SIG_FORMAT_RS_LE, NULL) <= 0)) { + SSLerror(s, ERR_R_EVP_LIB); + al = SSL_AD_INTERNAL_ERROR; + EVP_PKEY_CTX_free(pctx); + goto fatal_err; + } + if (EVP_PKEY_verify(pctx, CBS_data(&signature), + CBS_len(&signature), sigbuf, siglen) <= 0) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_BAD_SIGNATURE); + EVP_PKEY_CTX_free(pctx); + goto fatal_err; + } + + EVP_PKEY_CTX_free(pctx); +#endif + } else { + SSLerror(s, ERR_R_INTERNAL_ERROR); + al = SSL_AD_UNSUPPORTED_CERTIFICATE; + goto fatal_err; + } + + ret = 1; + if (0) { + decode_err: + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + end: + tls1_transcript_free(s); + err: + EVP_MD_CTX_free(mctx); + + return (ret); +} + +static int +ssl3_get_client_certificate(SSL *s) +{ + CBS cbs, cert_list, cert_data; + STACK_OF(X509) *certs = NULL; + X509 *cert = NULL; + const uint8_t *p; + int al, ret; + + if ((ret = ssl3_get_message(s, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B, + -1, s->max_cert_list)) <= 0) + return ret; + + ret = -1; + + if (s->s3->hs.tls12.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) { + if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto fatal_err; + } + + /* + * If we asked for a client certificate and the client has none, + * it must respond with a certificate list of length zero. + */ + if (s->s3->hs.tls12.cert_request != 0) { + SSLerror(s, SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST); + al = SSL_AD_UNEXPECTED_MESSAGE; + goto fatal_err; + } + s->s3->hs.tls12.reuse_message = 1; + return (1); + } + + if (s->s3->hs.tls12.message_type != SSL3_MT_CERTIFICATE) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_WRONG_MESSAGE_TYPE); + goto fatal_err; + } + + if (s->init_num < 0) + goto decode_err; + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (!CBS_get_u24_length_prefixed(&cbs, &cert_list)) + goto decode_err; + if (CBS_len(&cbs) != 0) + goto decode_err; + + /* + * A TLS client must send an empty certificate list, if no suitable + * certificate is available (rather than omitting the Certificate + * handshake message) - see RFC 5246 section 7.4.6. + */ + if (CBS_len(&cert_list) == 0) { + if ((s->verify_mode & SSL_VERIFY_PEER) && + (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) { + SSLerror(s, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + al = SSL_AD_HANDSHAKE_FAILURE; + goto fatal_err; + } + /* No client certificate so free transcript. */ + tls1_transcript_free(s); + goto done; + } + + if ((certs = sk_X509_new_null()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + + while (CBS_len(&cert_list) > 0) { + if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) + goto decode_err; + p = CBS_data(&cert_data); + if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) { + SSLerror(s, ERR_R_ASN1_LIB); + goto err; + } + if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) + goto decode_err; + if (!sk_X509_push(certs, cert)) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + cert = NULL; + } + + if (ssl_verify_cert_chain(s, certs) <= 0) { + al = ssl_verify_alarm_type(s->verify_result); + SSLerror(s, SSL_R_NO_CERTIFICATE_RETURNED); + goto fatal_err; + } + s->session->verify_result = s->verify_result; + ERR_clear_error(); + + if (!tls_process_peer_certs(s, certs)) + goto err; + + done: + ret = 1; + if (0) { + decode_err: + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_PACKET_LENGTH); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + } + err: + sk_X509_pop_free(certs, X509_free); + X509_free(cert); + + return (ret); +} + +static int +ssl3_send_server_certificate(SSL *s) +{ + CBB cbb, server_cert; + SSL_CERT_PKEY *cpk; + + /* + * Server Certificate - RFC 5246, section 7.4.2. + */ + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_CERT_A) { + if ((cpk = ssl_get_server_send_pkey(s)) == NULL) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return (0); + } + + if (!ssl3_handshake_msg_start(s, &cbb, &server_cert, + SSL3_MT_CERTIFICATE)) + goto err; + if (!ssl3_output_cert_chain(s, &server_cert, cpk)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_CERT_B; + } + + /* SSL3_ST_SW_CERT_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (0); +} + +/* send a new session ticket (not necessarily for a new session) */ +static int +ssl3_send_newsession_ticket(SSL *s) +{ + CBB cbb, session_ticket, ticket; + SSL_CTX *tctx = s->initial_ctx; + size_t enc_session_len, enc_session_max_len, hmac_len; + size_t session_len = 0; + unsigned char *enc_session = NULL, *session = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char key_name[16]; + unsigned char *hmac; + unsigned int hlen; + EVP_CIPHER_CTX *ctx = NULL; + HMAC_CTX *hctx = NULL; + int len; + + /* + * New Session Ticket - RFC 5077, section 3.3. + */ + + memset(&cbb, 0, sizeof(cbb)); + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if ((hctx = HMAC_CTX_new()) == NULL) + goto err; + + if (s->s3->hs.state == SSL3_ST_SW_SESSION_TICKET_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &session_ticket, + SSL3_MT_NEWSESSION_TICKET)) + goto err; + + if (!SSL_SESSION_ticket(s->session, &session, &session_len)) + goto err; + if (session_len > 0xffff) + goto err; + + /* + * Initialize HMAC and cipher contexts. If callback is present + * it does all the work, otherwise use generated values from + * parent context. + */ + if (tctx->tlsext_ticket_key_cb != NULL) { + if (tctx->tlsext_ticket_key_cb(s, + key_name, iv, ctx, hctx, 1) < 0) + goto err; + } else { + arc4random_buf(iv, 16); + EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, iv); + HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, + 16, EVP_sha256(), NULL); + memcpy(key_name, tctx->tlsext_tick_key_name, 16); + } + + /* Encrypt the session state. */ + enc_session_max_len = session_len + EVP_MAX_BLOCK_LENGTH; + if ((enc_session = calloc(1, enc_session_max_len)) == NULL) + goto err; + enc_session_len = 0; + if (!EVP_EncryptUpdate(ctx, enc_session, &len, session, + session_len)) + goto err; + enc_session_len += len; + if (!EVP_EncryptFinal_ex(ctx, enc_session + enc_session_len, + &len)) + goto err; + enc_session_len += len; + + if (enc_session_len > enc_session_max_len) + goto err; + + /* Generate the HMAC. */ + if (!HMAC_Update(hctx, key_name, sizeof(key_name))) + goto err; + if (!HMAC_Update(hctx, iv, EVP_CIPHER_CTX_iv_length(ctx))) + goto err; + if (!HMAC_Update(hctx, enc_session, enc_session_len)) + goto err; + + if ((hmac_len = HMAC_size(hctx)) <= 0) + goto err; + + /* + * Ticket lifetime hint (advisory only): + * We leave this unspecified for resumed session + * (for simplicity), and guess that tickets for new + * sessions will live as long as their sessions. + */ + if (!CBB_add_u32(&session_ticket, + s->hit ? 0 : s->session->timeout)) + goto err; + + if (!CBB_add_u16_length_prefixed(&session_ticket, &ticket)) + goto err; + if (!CBB_add_bytes(&ticket, key_name, sizeof(key_name))) + goto err; + if (!CBB_add_bytes(&ticket, iv, EVP_CIPHER_CTX_iv_length(ctx))) + goto err; + if (!CBB_add_bytes(&ticket, enc_session, enc_session_len)) + goto err; + if (!CBB_add_space(&ticket, &hmac, hmac_len)) + goto err; + + if (!HMAC_Final(hctx, hmac, &hlen)) + goto err; + if (hlen != hmac_len) + goto err; + + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_SESSION_TICKET_B; + } + + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + freezero(session, session_len); + free(enc_session); + + /* SSL3_ST_SW_SESSION_TICKET_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + EVP_CIPHER_CTX_free(ctx); + HMAC_CTX_free(hctx); + freezero(session, session_len); + free(enc_session); + + return (-1); +} + +static int +ssl3_send_cert_status(SSL *s) +{ + CBB cbb, certstatus, ocspresp; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_CERT_STATUS_A) { + if (!ssl3_handshake_msg_start(s, &cbb, &certstatus, + SSL3_MT_CERTIFICATE_STATUS)) + goto err; + if (!CBB_add_u8(&certstatus, s->tlsext_status_type)) + goto err; + if (!CBB_add_u24_length_prefixed(&certstatus, &ocspresp)) + goto err; + if (!CBB_add_bytes(&ocspresp, s->tlsext_ocsp_resp, + s->tlsext_ocsp_resp_len)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_CERT_STATUS_B; + } + + /* SSL3_ST_SW_CERT_STATUS_B */ + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} + +static int +ssl3_send_server_change_cipher_spec(SSL *s) +{ + size_t outlen; + CBB cbb; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_CHANGE_A) { + if (!CBB_init_fixed(&cbb, s->init_buf->data, + s->init_buf->length)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_MT_CCS)) + goto err; + if (!CBB_finish(&cbb, NULL, &outlen)) + goto err; + + if (outlen > INT_MAX) + goto err; + + s->init_num = (int)outlen; + s->init_off = 0; + + if (SSL_is_dtls(s)) { + s->d1->handshake_write_seq = + s->d1->next_handshake_write_seq; + dtls1_set_message_header_int(s, SSL3_MT_CCS, 0, + s->d1->handshake_write_seq, 0, 0); + dtls1_buffer_message(s, 1); + } + + s->s3->hs.state = SSL3_ST_SW_CHANGE_B; + } + + /* SSL3_ST_SW_CHANGE_B */ + return ssl3_record_write(s, SSL3_RT_CHANGE_CIPHER_SPEC); + + err: + CBB_cleanup(&cbb); + + return -1; +} + +static int +ssl3_get_client_finished(SSL *s) +{ + int al, md_len, ret; + CBS cbs; + + /* should actually be 36+4 :-) */ + if ((ret = ssl3_get_message(s, SSL3_ST_SR_FINISHED_A, + SSL3_ST_SR_FINISHED_B, SSL3_MT_FINISHED, 64)) <= 0) + return ret; + + /* If this occurs, we have missed a message */ + if (!s->s3->change_cipher_spec) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerror(s, SSL_R_GOT_A_FIN_BEFORE_A_CCS); + goto fatal_err; + } + s->s3->change_cipher_spec = 0; + + md_len = TLS1_FINISH_MAC_LENGTH; + + if (s->init_num < 0) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + CBS_init(&cbs, s->init_msg, s->init_num); + + if (s->s3->hs.peer_finished_len != md_len || + CBS_len(&cbs) != md_len) { + al = SSL_AD_DECODE_ERROR; + SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); + goto fatal_err; + } + + if (!CBS_mem_equal(&cbs, s->s3->hs.peer_finished, CBS_len(&cbs))) { + al = SSL_AD_DECRYPT_ERROR; + SSLerror(s, SSL_R_DIGEST_CHECK_FAILED); + goto fatal_err; + } + + /* Copy finished so we can use it for renegotiation checks. */ + OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); + memcpy(s->s3->previous_client_finished, + s->s3->hs.peer_finished, md_len); + s->s3->previous_client_finished_len = md_len; + + return (1); + fatal_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return (0); +} + +static int +ssl3_send_server_finished(SSL *s) +{ + CBB cbb, finished; + + memset(&cbb, 0, sizeof(cbb)); + + if (s->s3->hs.state == SSL3_ST_SW_FINISHED_A) { + if (!tls12_derive_finished(s)) + goto err; + + /* Copy finished so we can use it for renegotiation checks. */ + memcpy(s->s3->previous_server_finished, + s->s3->hs.finished, s->s3->hs.finished_len); + s->s3->previous_server_finished_len = s->s3->hs.finished_len; + + if (!ssl3_handshake_msg_start(s, &cbb, &finished, + SSL3_MT_FINISHED)) + goto err; + if (!CBB_add_bytes(&finished, s->s3->hs.finished, + s->s3->hs.finished_len)) + goto err; + if (!ssl3_handshake_msg_finish(s, &cbb)) + goto err; + + s->s3->hs.state = SSL3_ST_SW_FINISHED_B; + } + + return (ssl3_handshake_write(s)); + + err: + CBB_cleanup(&cbb); + + return (-1); +} diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c new file mode 100644 index 0000000..803b83b --- /dev/null +++ b/ssl/ssl_stat.c @@ -0,0 +1,797 @@ +/* $OpenBSD: ssl_stat.c,v 1.21 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include + +#include "ssl_local.h" + +const char * +SSL_state_string_long(const SSL *s) +{ + const char *str; + + switch (s->s3->hs.state) { + case SSL_ST_BEFORE: + str = "before SSL initialization"; + break; + case SSL_ST_ACCEPT: + str = "before accept initialization"; + break; + case SSL_ST_CONNECT: + str = "before connect initialization"; + break; + case SSL_ST_OK: + str = "SSL negotiation finished successfully"; + break; + case SSL_ST_RENEGOTIATE: + str = "SSL renegotiate ciphers"; + break; + case SSL_ST_BEFORE|SSL_ST_CONNECT: + str = "before/connect initialization"; + break; + case SSL_ST_OK|SSL_ST_CONNECT: + str = "ok/connect SSL initialization"; + break; + case SSL_ST_BEFORE|SSL_ST_ACCEPT: + str = "before/accept initialization"; + break; + case SSL_ST_OK|SSL_ST_ACCEPT: + str = "ok/accept SSL initialization"; + break; + + /* SSLv3 additions */ + case SSL3_ST_CW_CLNT_HELLO_A: + str = "SSLv3 write client hello A"; + break; + case SSL3_ST_CW_CLNT_HELLO_B: + str = "SSLv3 write client hello B"; + break; + case SSL3_ST_CR_SRVR_HELLO_A: + str = "SSLv3 read server hello A"; + break; + case SSL3_ST_CR_SRVR_HELLO_B: + str = "SSLv3 read server hello B"; + break; + case SSL3_ST_CR_CERT_A: + str = "SSLv3 read server certificate A"; + break; + case SSL3_ST_CR_CERT_B: + str = "SSLv3 read server certificate B"; + break; + case SSL3_ST_CR_KEY_EXCH_A: + str = "SSLv3 read server key exchange A"; + break; + case SSL3_ST_CR_KEY_EXCH_B: + str = "SSLv3 read server key exchange B"; + break; + case SSL3_ST_CR_CERT_REQ_A: + str = "SSLv3 read server certificate request A"; + break; + case SSL3_ST_CR_CERT_REQ_B: + str = "SSLv3 read server certificate request B"; + break; + case SSL3_ST_CR_SESSION_TICKET_A: + str = "SSLv3 read server session ticket A"; + break; + case SSL3_ST_CR_SESSION_TICKET_B: + str = "SSLv3 read server session ticket B"; + break; + case SSL3_ST_CR_SRVR_DONE_A: + str = "SSLv3 read server done A"; + break; + case SSL3_ST_CR_SRVR_DONE_B: + str = "SSLv3 read server done B"; + break; + case SSL3_ST_CW_CERT_A: + str = "SSLv3 write client certificate A"; + break; + case SSL3_ST_CW_CERT_B: + str = "SSLv3 write client certificate B"; + break; + case SSL3_ST_CW_CERT_C: + str = "SSLv3 write client certificate C"; + break; + case SSL3_ST_CW_CERT_D: + str = "SSLv3 write client certificate D"; + break; + case SSL3_ST_CW_KEY_EXCH_A: + str = "SSLv3 write client key exchange A"; + break; + case SSL3_ST_CW_KEY_EXCH_B: + str = "SSLv3 write client key exchange B"; + break; + case SSL3_ST_CW_CERT_VRFY_A: + str = "SSLv3 write certificate verify A"; + break; + case SSL3_ST_CW_CERT_VRFY_B: + str = "SSLv3 write certificate verify B"; + break; + + case SSL3_ST_CW_CHANGE_A: + case SSL3_ST_SW_CHANGE_A: + str = "SSLv3 write change cipher spec A"; + break; + case SSL3_ST_CW_CHANGE_B: + case SSL3_ST_SW_CHANGE_B: + str = "SSLv3 write change cipher spec B"; + break; + case SSL3_ST_CW_FINISHED_A: + case SSL3_ST_SW_FINISHED_A: + str = "SSLv3 write finished A"; + break; + case SSL3_ST_CW_FINISHED_B: + case SSL3_ST_SW_FINISHED_B: + str = "SSLv3 write finished B"; + break; + case SSL3_ST_CR_CHANGE_A: + case SSL3_ST_SR_CHANGE_A: + str = "SSLv3 read change cipher spec A"; + break; + case SSL3_ST_CR_CHANGE_B: + case SSL3_ST_SR_CHANGE_B: + str = "SSLv3 read change cipher spec B"; + break; + case SSL3_ST_CR_FINISHED_A: + case SSL3_ST_SR_FINISHED_A: + str = "SSLv3 read finished A"; + break; + case SSL3_ST_CR_FINISHED_B: + case SSL3_ST_SR_FINISHED_B: + str = "SSLv3 read finished B"; + break; + + case SSL3_ST_CW_FLUSH: + case SSL3_ST_SW_FLUSH: + str = "SSLv3 flush data"; + break; + + case SSL3_ST_SR_CLNT_HELLO_A: + str = "SSLv3 read client hello A"; + break; + case SSL3_ST_SR_CLNT_HELLO_B: + str = "SSLv3 read client hello B"; + break; + case SSL3_ST_SR_CLNT_HELLO_C: + str = "SSLv3 read client hello C"; + break; + case SSL3_ST_SW_HELLO_REQ_A: + str = "SSLv3 write hello request A"; + break; + case SSL3_ST_SW_HELLO_REQ_B: + str = "SSLv3 write hello request B"; + break; + case SSL3_ST_SW_HELLO_REQ_C: + str = "SSLv3 write hello request C"; + break; + case SSL3_ST_SW_SRVR_HELLO_A: + str = "SSLv3 write server hello A"; + break; + case SSL3_ST_SW_SRVR_HELLO_B: + str = "SSLv3 write server hello B"; + break; + case SSL3_ST_SW_CERT_A: + str = "SSLv3 write certificate A"; + break; + case SSL3_ST_SW_CERT_B: + str = "SSLv3 write certificate B"; + break; + case SSL3_ST_SW_KEY_EXCH_A: + str = "SSLv3 write key exchange A"; + break; + case SSL3_ST_SW_KEY_EXCH_B: + str = "SSLv3 write key exchange B"; + break; + case SSL3_ST_SW_CERT_REQ_A: + str = "SSLv3 write certificate request A"; + break; + case SSL3_ST_SW_CERT_REQ_B: + str = "SSLv3 write certificate request B"; + break; + case SSL3_ST_SW_SESSION_TICKET_A: + str = "SSLv3 write session ticket A"; + break; + case SSL3_ST_SW_SESSION_TICKET_B: + str = "SSLv3 write session ticket B"; + break; + case SSL3_ST_SW_SRVR_DONE_A: + str = "SSLv3 write server done A"; + break; + case SSL3_ST_SW_SRVR_DONE_B: + str = "SSLv3 write server done B"; + break; + case SSL3_ST_SR_CERT_A: + str = "SSLv3 read client certificate A"; + break; + case SSL3_ST_SR_CERT_B: + str = "SSLv3 read client certificate B"; + break; + case SSL3_ST_SR_KEY_EXCH_A: + str = "SSLv3 read client key exchange A"; + break; + case SSL3_ST_SR_KEY_EXCH_B: + str = "SSLv3 read client key exchange B"; + break; + case SSL3_ST_SR_CERT_VRFY_A: + str = "SSLv3 read certificate verify A"; + break; + case SSL3_ST_SR_CERT_VRFY_B: + str = "SSLv3 read certificate verify B"; + break; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + str = "DTLS1 read hello verify request A"; + break; + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + str = "DTLS1 read hello verify request B"; + break; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + str = "DTLS1 write hello verify request A"; + break; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + str = "DTLS1 write hello verify request B"; + break; + + default: + str = "unknown state"; + break; + } + return (str); +} +LSSL_ALIAS(SSL_state_string_long); + +const char * +SSL_rstate_string_long(const SSL *s) +{ + const char *str; + + switch (s->rstate) { + case SSL_ST_READ_HEADER: + str = "read header"; + break; + case SSL_ST_READ_BODY: + str = "read body"; + break; + case SSL_ST_READ_DONE: + str = "read done"; + break; + default: + str = "unknown"; + break; + } + return (str); +} +LSSL_ALIAS(SSL_rstate_string_long); + +const char * +SSL_state_string(const SSL *s) +{ + const char *str; + + switch (s->s3->hs.state) { + case SSL_ST_BEFORE: + str = "PINIT "; + break; + case SSL_ST_ACCEPT: + str = "AINIT "; + break; + case SSL_ST_CONNECT: + str = "CINIT "; + break; + case SSL_ST_OK: + str = "SSLOK "; + break; + + /* SSLv3 additions */ + case SSL3_ST_SW_FLUSH: + case SSL3_ST_CW_FLUSH: + str = "3FLUSH"; + break; + case SSL3_ST_CW_CLNT_HELLO_A: + str = "3WCH_A"; + break; + case SSL3_ST_CW_CLNT_HELLO_B: + str = "3WCH_B"; + break; + case SSL3_ST_CR_SRVR_HELLO_A: + str = "3RSH_A"; + break; + case SSL3_ST_CR_SRVR_HELLO_B: + str = "3RSH_B"; + break; + case SSL3_ST_CR_CERT_A: + str = "3RSC_A"; + break; + case SSL3_ST_CR_CERT_B: + str = "3RSC_B"; + break; + case SSL3_ST_CR_KEY_EXCH_A: + str = "3RSKEA"; + break; + case SSL3_ST_CR_KEY_EXCH_B: + str = "3RSKEB"; + break; + case SSL3_ST_CR_CERT_REQ_A: + str = "3RCR_A"; + break; + case SSL3_ST_CR_CERT_REQ_B: + str = "3RCR_B"; + break; + case SSL3_ST_CR_SRVR_DONE_A: + str = "3RSD_A"; + break; + case SSL3_ST_CR_SRVR_DONE_B: + str = "3RSD_B"; + break; + case SSL3_ST_CW_CERT_A: + str = "3WCC_A"; + break; + case SSL3_ST_CW_CERT_B: + str = "3WCC_B"; + break; + case SSL3_ST_CW_CERT_C: + str = "3WCC_C"; + break; + case SSL3_ST_CW_CERT_D: + str = "3WCC_D"; + break; + case SSL3_ST_CW_KEY_EXCH_A: + str = "3WCKEA"; + break; + case SSL3_ST_CW_KEY_EXCH_B: + str = "3WCKEB"; + break; + case SSL3_ST_CW_CERT_VRFY_A: + str = "3WCV_A"; + break; + case SSL3_ST_CW_CERT_VRFY_B: + str = "3WCV_B"; + break; + + case SSL3_ST_SW_CHANGE_A: + case SSL3_ST_CW_CHANGE_A: + str = "3WCCSA"; + break; + case SSL3_ST_SW_CHANGE_B: + case SSL3_ST_CW_CHANGE_B: + str = "3WCCSB"; + break; + case SSL3_ST_SW_FINISHED_A: + case SSL3_ST_CW_FINISHED_A: + str = "3WFINA"; + break; + case SSL3_ST_SW_FINISHED_B: + case SSL3_ST_CW_FINISHED_B: + str = "3WFINB"; + break; + case SSL3_ST_SR_CHANGE_A: + case SSL3_ST_CR_CHANGE_A: + str = "3RCCSA"; + break; + case SSL3_ST_SR_CHANGE_B: + case SSL3_ST_CR_CHANGE_B: + str = "3RCCSB"; + break; + case SSL3_ST_SR_FINISHED_A: + case SSL3_ST_CR_FINISHED_A: + str = "3RFINA"; + break; + case SSL3_ST_SR_FINISHED_B: + case SSL3_ST_CR_FINISHED_B: + str = "3RFINB"; + break; + + case SSL3_ST_SW_HELLO_REQ_A: + str = "3WHR_A"; + break; + case SSL3_ST_SW_HELLO_REQ_B: + str = "3WHR_B"; + break; + case SSL3_ST_SW_HELLO_REQ_C: + str = "3WHR_C"; + break; + case SSL3_ST_SR_CLNT_HELLO_A: + str = "3RCH_A"; + break; + case SSL3_ST_SR_CLNT_HELLO_B: + str = "3RCH_B"; + break; + case SSL3_ST_SR_CLNT_HELLO_C: + str = "3RCH_C"; + break; + case SSL3_ST_SW_SRVR_HELLO_A: + str = "3WSH_A"; + break; + case SSL3_ST_SW_SRVR_HELLO_B: + str = "3WSH_B"; + break; + case SSL3_ST_SW_CERT_A: + str = "3WSC_A"; + break; + case SSL3_ST_SW_CERT_B: + str = "3WSC_B"; + break; + case SSL3_ST_SW_KEY_EXCH_A: + str = "3WSKEA"; + break; + case SSL3_ST_SW_KEY_EXCH_B: + str = "3WSKEB"; + break; + case SSL3_ST_SW_CERT_REQ_A: + str = "3WCR_A"; + break; + case SSL3_ST_SW_CERT_REQ_B: + str = "3WCR_B"; + break; + case SSL3_ST_SW_SRVR_DONE_A: + str = "3WSD_A"; + break; + case SSL3_ST_SW_SRVR_DONE_B: + str = "3WSD_B"; + break; + case SSL3_ST_SR_CERT_A: + str = "3RCC_A"; + break; + case SSL3_ST_SR_CERT_B: + str = "3RCC_B"; + break; + case SSL3_ST_SR_KEY_EXCH_A: + str = "3RCKEA"; + break; + case SSL3_ST_SR_KEY_EXCH_B: + str = "3RCKEB"; + break; + case SSL3_ST_SR_CERT_VRFY_A: + str = "3RCV_A"; + break; + case SSL3_ST_SR_CERT_VRFY_B: + str = "3RCV_B"; + break; + + /* DTLS */ + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A: + str = "DRCHVA"; + break; + case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B: + str = "DRCHVB"; + break; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A: + str = "DWCHVA"; + break; + case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B: + str = "DWCHVB"; + break; + + default: + str = "UNKWN "; + break; + } + return (str); +} +LSSL_ALIAS(SSL_state_string); + +const char * +SSL_alert_type_string_long(int value) +{ + value >>= 8; + if (value == SSL3_AL_WARNING) + return ("warning"); + else if (value == SSL3_AL_FATAL) + return ("fatal"); + else + return ("unknown"); +} +LSSL_ALIAS(SSL_alert_type_string_long); + +const char * +SSL_alert_type_string(int value) +{ + value >>= 8; + if (value == SSL3_AL_WARNING) + return ("W"); + else if (value == SSL3_AL_FATAL) + return ("F"); + else + return ("U"); +} +LSSL_ALIAS(SSL_alert_type_string); + +const char * +SSL_alert_desc_string(int value) +{ + const char *str; + + switch (value & 0xff) { + case SSL_AD_CLOSE_NOTIFY: + str = "CN"; + break; + case SSL_AD_UNEXPECTED_MESSAGE: + str = "UM"; + break; + case SSL_AD_BAD_RECORD_MAC: + str = "BM"; + break; + case SSL_AD_DECOMPRESSION_FAILURE: + str = "DF"; + break; + case SSL_AD_HANDSHAKE_FAILURE: + str = "HF"; + break; + case SSL_AD_BAD_CERTIFICATE: + str = "BC"; + break; + case SSL_AD_UNSUPPORTED_CERTIFICATE: + str = "UC"; + break; + case SSL_AD_CERTIFICATE_REVOKED: + str = "CR"; + break; + case SSL_AD_CERTIFICATE_EXPIRED: + str = "CE"; + break; + case SSL_AD_CERTIFICATE_UNKNOWN: + str = "CU"; + break; + case SSL_AD_ILLEGAL_PARAMETER: + str = "IP"; + break; + case SSL_AD_RECORD_OVERFLOW: + str = "RO"; + break; + case SSL_AD_UNKNOWN_CA: + str = "CA"; + break; + case SSL_AD_ACCESS_DENIED: + str = "AD"; + break; + case SSL_AD_DECODE_ERROR: + str = "DE"; + break; + case SSL_AD_DECRYPT_ERROR: + str = "CY"; + break; + case SSL_AD_PROTOCOL_VERSION: + str = "PV"; + break; + case SSL_AD_INSUFFICIENT_SECURITY: + str = "IS"; + break; + case SSL_AD_INTERNAL_ERROR: + str = "IE"; + break; + case SSL_AD_USER_CANCELLED: + str = "US"; + break; + case SSL_AD_NO_RENEGOTIATION: + str = "NR"; + break; + case SSL_AD_MISSING_EXTENSION: + str = "ME"; + break; + case SSL_AD_UNSUPPORTED_EXTENSION: + str = "UE"; + break; + case SSL_AD_CERTIFICATE_UNOBTAINABLE: + str = "CO"; + break; + case SSL_AD_UNRECOGNIZED_NAME: + str = "UN"; + break; + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + str = "BR"; + break; + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: + str = "BH"; + break; + case SSL_AD_UNKNOWN_PSK_IDENTITY: + str = "UP"; + break; + default: + str = "UK"; + break; + } + return (str); +} +LSSL_ALIAS(SSL_alert_desc_string); + +const char * +SSL_alert_desc_string_long(int value) +{ + const char *str; + + switch (value & 0xff) { + case SSL_AD_CLOSE_NOTIFY: + str = "close notify"; + break; + case SSL_AD_UNEXPECTED_MESSAGE: + str = "unexpected_message"; + break; + case SSL_AD_BAD_RECORD_MAC: + str = "bad record mac"; + break; + case SSL_AD_DECOMPRESSION_FAILURE: + str = "decompression failure"; + break; + case SSL_AD_HANDSHAKE_FAILURE: + str = "handshake failure"; + break; + case SSL_AD_BAD_CERTIFICATE: + str = "bad certificate"; + break; + case SSL_AD_UNSUPPORTED_CERTIFICATE: + str = "unsupported certificate"; + break; + case SSL_AD_CERTIFICATE_REVOKED: + str = "certificate revoked"; + break; + case SSL_AD_CERTIFICATE_EXPIRED: + str = "certificate expired"; + break; + case SSL_AD_CERTIFICATE_UNKNOWN: + str = "certificate unknown"; + break; + case SSL_AD_ILLEGAL_PARAMETER: + str = "illegal parameter"; + break; + case SSL_AD_RECORD_OVERFLOW: + str = "record overflow"; + break; + case SSL_AD_UNKNOWN_CA: + str = "unknown CA"; + break; + case SSL_AD_ACCESS_DENIED: + str = "access denied"; + break; + case SSL_AD_DECODE_ERROR: + str = "decode error"; + break; + case SSL_AD_DECRYPT_ERROR: + str = "decrypt error"; + break; + case SSL_AD_PROTOCOL_VERSION: + str = "protocol version"; + break; + case SSL_AD_INSUFFICIENT_SECURITY: + str = "insufficient security"; + break; + case SSL_AD_INTERNAL_ERROR: + str = "internal error"; + break; + case SSL_AD_USER_CANCELLED: + str = "user canceled"; + break; + case SSL_AD_NO_RENEGOTIATION: + str = "no renegotiation"; + break; + case SSL_AD_MISSING_EXTENSION: + str = "missing extension"; + break; + case SSL_AD_UNSUPPORTED_EXTENSION: + str = "unsupported extension"; + break; + case SSL_AD_CERTIFICATE_UNOBTAINABLE: + str = "certificate unobtainable"; + break; + case SSL_AD_UNRECOGNIZED_NAME: + str = "unrecognized name"; + break; + case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE: + str = "bad certificate status response"; + break; + case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: + str = "bad certificate hash value"; + break; + case SSL_AD_UNKNOWN_PSK_IDENTITY: + str = "unknown PSK identity"; + break; + default: + str = "unknown"; + break; + } + return (str); +} +LSSL_ALIAS(SSL_alert_desc_string_long); + +const char * +SSL_rstate_string(const SSL *s) +{ + const char *str; + + switch (s->rstate) { + case SSL_ST_READ_HEADER: + str = "RH"; + break; + case SSL_ST_READ_BODY: + str = "RB"; + break; + case SSL_ST_READ_DONE: + str = "RD"; + break; + default: + str = "unknown"; + break; + } + return (str); +} +LSSL_ALIAS(SSL_rstate_string); diff --git a/ssl/ssl_tlsext.c b/ssl/ssl_tlsext.c new file mode 100644 index 0000000..5dd4b69 --- /dev/null +++ b/ssl/ssl_tlsext.c @@ -0,0 +1,2519 @@ +/* $OpenBSD: ssl_tlsext.c,v 1.137 2023/04/28 18:14:59 tb Exp $ */ +/* + * Copyright (c) 2016, 2017, 2019 Joel Sing + * Copyright (c) 2017 Doug Hogan + * Copyright (c) 2018-2019 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include + +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" + +#define TLSEXT_TYPE_alpn TLSEXT_TYPE_application_layer_protocol_negotiation + +/* + * Supported Application-Layer Protocol Negotiation - RFC 7301 + */ + +static int +tlsext_alpn_client_needs(SSL *s, uint16_t msg_type) +{ + /* ALPN protos have been specified and this is the initial handshake */ + return s->alpn_client_proto_list != NULL && + s->s3->hs.finished_len == 0; +} + +static int +tlsext_alpn_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB protolist; + + if (!CBB_add_u16_length_prefixed(cbb, &protolist)) + return 0; + + if (!CBB_add_bytes(&protolist, s->alpn_client_proto_list, + s->alpn_client_proto_list_len)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +tlsext_alpn_check_format(CBS *cbs) +{ + CBS proto_name_list; + + if (CBS_len(cbs) == 0) + return 0; + + CBS_dup(cbs, &proto_name_list); + while (CBS_len(&proto_name_list) > 0) { + CBS proto_name; + + if (!CBS_get_u8_length_prefixed(&proto_name_list, &proto_name)) + return 0; + if (CBS_len(&proto_name) == 0) + return 0; + } + + return 1; +} + +static int +tlsext_alpn_server_parse(SSL *s, uint16_t msg_types, CBS *cbs, int *alert) +{ + CBS alpn, selected_cbs; + const unsigned char *selected; + unsigned char selected_len; + int r; + + if (!CBS_get_u16_length_prefixed(cbs, &alpn)) + return 0; + + if (!tlsext_alpn_check_format(&alpn)) + return 0; + + if (s->ctx->alpn_select_cb == NULL) + return 1; + + /* + * XXX - A few things should be considered here: + * 1. Ensure that the same protocol is selected on session resumption. + * 2. Should the callback be called even if no ALPN extension was sent? + * 3. TLSv1.2 and earlier: ensure that SNI has already been processed. + */ + r = s->ctx->alpn_select_cb(s, &selected, &selected_len, + CBS_data(&alpn), CBS_len(&alpn), + s->ctx->alpn_select_cb_arg); + + if (r == SSL_TLSEXT_ERR_OK) { + CBS_init(&selected_cbs, selected, selected_len); + + if (!CBS_stow(&selected_cbs, &s->s3->alpn_selected, + &s->s3->alpn_selected_len)) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; + } + + /* On SSL_TLSEXT_ERR_NOACK behave as if no callback was present. */ + if (r == SSL_TLSEXT_ERR_NOACK) + return 1; + + *alert = SSL_AD_NO_APPLICATION_PROTOCOL; + SSLerror(s, SSL_R_NO_APPLICATION_PROTOCOL); + + return 0; +} + +static int +tlsext_alpn_server_needs(SSL *s, uint16_t msg_type) +{ + return s->s3->alpn_selected != NULL; +} + +static int +tlsext_alpn_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB list, selected; + + if (!CBB_add_u16_length_prefixed(cbb, &list)) + return 0; + + if (!CBB_add_u8_length_prefixed(&list, &selected)) + return 0; + + if (!CBB_add_bytes(&selected, s->s3->alpn_selected, + s->s3->alpn_selected_len)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_alpn_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS list, proto; + + if (s->alpn_client_proto_list == NULL) { + *alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } + + if (!CBS_get_u16_length_prefixed(cbs, &list)) + return 0; + + if (!CBS_get_u8_length_prefixed(&list, &proto)) + return 0; + + if (CBS_len(&list) != 0) + return 0; + if (CBS_len(&proto) == 0) + return 0; + + if (!CBS_stow(&proto, &s->s3->alpn_selected, &s->s3->alpn_selected_len)) + return 0; + + return 1; +} + +/* + * Supported Groups - RFC 7919 section 2 + */ +static int +tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type) +{ + return ssl_has_ecc_ciphers(s) || + (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_supportedgroups_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + const uint16_t *groups; + size_t groups_len; + CBB grouplist; + int i; + + tls1_get_group_list(s, 0, &groups, &groups_len); + if (groups_len == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!CBB_add_u16_length_prefixed(cbb, &grouplist)) + return 0; + + for (i = 0; i < groups_len; i++) { + if (!ssl_security_supported_group(s, groups[i])) + continue; + if (!CBB_add_u16(&grouplist, groups[i])) + return 0; + } + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_supportedgroups_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + CBS grouplist; + uint16_t *groups; + size_t groups_len; + int i; + + if (!CBS_get_u16_length_prefixed(cbs, &grouplist)) + return 0; + + groups_len = CBS_len(&grouplist); + if (groups_len == 0 || groups_len % 2 != 0) + return 0; + groups_len /= 2; + + if (s->hit) + return 1; + + if (s->s3->hs.tls13.hrr) { + if (s->session->tlsext_supportedgroups == NULL) { + *alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + /* + * The ClientHello extension hashing ensures that the client + * did not change its list of supported groups. + */ + + return 1; + } + + if (s->session->tlsext_supportedgroups != NULL) + return 0; /* XXX internal error? */ + + if ((groups = reallocarray(NULL, groups_len, sizeof(uint16_t))) == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + for (i = 0; i < groups_len; i++) { + if (!CBS_get_u16(&grouplist, &groups[i])) { + free(groups); + return 0; + } + } + + if (CBS_len(&grouplist) != 0) { + free(groups); + return 0; + } + + s->session->tlsext_supportedgroups = groups; + s->session->tlsext_supportedgroups_length = groups_len; + + return 1; +} + +/* This extension is never used by the server. */ +static int +tlsext_supportedgroups_server_needs(SSL *s, uint16_t msg_type) +{ + return 0; +} + +static int +tlsext_supportedgroups_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return 0; +} + +static int +tlsext_supportedgroups_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + /* + * Servers should not send this extension per the RFC. + * + * However, certain F5 BIG-IP systems incorrectly send it. This bug is + * from at least 2014 but as of 2017, there are still large sites with + * this unpatched in production. As a result, we need to currently skip + * over the extension and ignore its content: + * + * https://support.f5.com/csp/article/K37345003 + */ + if (!CBS_skip(cbs, CBS_len(cbs))) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +/* + * Supported Point Formats Extension - RFC 4492 section 5.1.2 + */ +static int +tlsext_ecpf_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB ecpf; + size_t formats_len; + const uint8_t *formats; + + tls1_get_formatlist(s, 0, &formats, &formats_len); + + if (formats_len == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + return 0; + } + + if (!CBB_add_u8_length_prefixed(cbb, &ecpf)) + return 0; + if (!CBB_add_bytes(&ecpf, formats, formats_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_ecpf_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS ecpf; + + if (!CBS_get_u8_length_prefixed(cbs, &ecpf)) + return 0; + if (CBS_len(&ecpf) == 0) + return 0; + + /* Must contain uncompressed (0) - RFC 8422, section 5.1.2. */ + if (!CBS_contains_zero_byte(&ecpf)) { + SSLerror(s, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST); + *alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + if (!s->hit) { + if (!CBS_stow(&ecpf, &(s->session->tlsext_ecpointformatlist), + &(s->session->tlsext_ecpointformatlist_length))) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + return 1; +} + +static int +tlsext_ecpf_client_needs(SSL *s, uint16_t msg_type) +{ + return ssl_has_ecc_ciphers(s); +} + +static int +tlsext_ecpf_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return tlsext_ecpf_build(s, msg_type, cbb); +} + +static int +tlsext_ecpf_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + return tlsext_ecpf_parse(s, msg_type, cbs, alert); +} + +static int +tlsext_ecpf_server_needs(SSL *s, uint16_t msg_type) +{ + return ssl_using_ecc_cipher(s); +} + +static int +tlsext_ecpf_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return tlsext_ecpf_build(s, msg_type, cbb); +} + +static int +tlsext_ecpf_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + return tlsext_ecpf_parse(s, msg_type, cbs, alert); +} + +/* + * Renegotiation Indication - RFC 5746. + */ +static int +tlsext_ri_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->renegotiate); +} + +static int +tlsext_ri_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB reneg; + + if (!CBB_add_u8_length_prefixed(cbb, &reneg)) + return 0; + if (!CBB_add_bytes(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_ri_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS reneg; + + if (!CBS_get_u8_length_prefixed(cbs, &reneg)) { + SSLerror(s, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + if (!CBS_mem_equal(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); + *alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + s->s3->renegotiate_seen = 1; + s->s3->send_connection_binding = 1; + + return 1; +} + +static int +tlsext_ri_server_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.negotiated_tls_version < TLS1_3_VERSION && + s->s3->send_connection_binding); +} + +static int +tlsext_ri_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB reneg; + + if (!CBB_add_u8_length_prefixed(cbb, &reneg)) + return 0; + if (!CBB_add_bytes(&reneg, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) + return 0; + if (!CBB_add_bytes(&reneg, s->s3->previous_server_finished, + s->s3->previous_server_finished_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_ri_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS reneg, prev_client, prev_server; + + /* + * Ensure that the previous client and server values are both not + * present, or that they are both present. + */ + if ((s->s3->previous_client_finished_len == 0 && + s->s3->previous_server_finished_len != 0) || + (s->s3->previous_client_finished_len != 0 && + s->s3->previous_server_finished_len == 0)) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + if (!CBS_get_u8_length_prefixed(cbs, &reneg)) { + SSLerror(s, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + if (!CBS_get_bytes(&reneg, &prev_client, + s->s3->previous_client_finished_len)) { + SSLerror(s, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + if (!CBS_get_bytes(&reneg, &prev_server, + s->s3->previous_server_finished_len)) { + SSLerror(s, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + if (CBS_len(&reneg) != 0) { + SSLerror(s, SSL_R_RENEGOTIATION_ENCODING_ERR); + return 0; + } + + if (!CBS_mem_equal(&prev_client, s->s3->previous_client_finished, + s->s3->previous_client_finished_len)) { + SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); + *alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + if (!CBS_mem_equal(&prev_server, s->s3->previous_server_finished, + s->s3->previous_server_finished_len)) { + SSLerror(s, SSL_R_RENEGOTIATION_MISMATCH); + *alert = SSL_AD_HANDSHAKE_FAILURE; + return 0; + } + + s->s3->renegotiate_seen = 1; + s->s3->send_connection_binding = 1; + + return 1; +} + +/* + * Signature Algorithms - RFC 5246 section 7.4.1.4.1. + */ +static int +tlsext_sigalgs_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.our_max_tls_version >= TLS1_2_VERSION); +} + +static int +tlsext_sigalgs_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + uint16_t tls_version = s->s3->hs.negotiated_tls_version; + CBB sigalgs; + + if (msg_type == SSL_TLSEXT_MSG_CH) + tls_version = s->s3->hs.our_min_tls_version; + + if (!CBB_add_u16_length_prefixed(cbb, &sigalgs)) + return 0; + if (!ssl_sigalgs_build(tls_version, &sigalgs, SSL_get_security_level(s))) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_sigalgs_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS sigalgs; + + if (!CBS_get_u16_length_prefixed(cbs, &sigalgs)) + return 0; + if (CBS_len(&sigalgs) % 2 != 0 || CBS_len(&sigalgs) > 64) + return 0; + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, &s->s3->hs.sigalgs_len)) + return 0; + + return 1; +} + +static int +tlsext_sigalgs_server_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_sigalgs_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB sigalgs; + + if (!CBB_add_u16_length_prefixed(cbb, &sigalgs)) + return 0; + if (!ssl_sigalgs_build(s->s3->hs.negotiated_tls_version, &sigalgs, + SSL_get_security_level(s))) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_sigalgs_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS sigalgs; + + if (ssl_effective_tls_version(s) < TLS1_3_VERSION) + return 0; + + if (!CBS_get_u16_length_prefixed(cbs, &sigalgs)) + return 0; + if (CBS_len(&sigalgs) % 2 != 0 || CBS_len(&sigalgs) > 64) + return 0; + if (!CBS_stow(&sigalgs, &s->s3->hs.sigalgs, &s->s3->hs.sigalgs_len)) + return 0; + + return 1; +} + +/* + * Server Name Indication - RFC 6066, section 3. + */ +static int +tlsext_sni_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->tlsext_hostname != NULL); +} + +static int +tlsext_sni_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB server_name_list, host_name; + + if (!CBB_add_u16_length_prefixed(cbb, &server_name_list)) + return 0; + if (!CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name)) + return 0; + if (!CBB_add_u16_length_prefixed(&server_name_list, &host_name)) + return 0; + if (!CBB_add_bytes(&host_name, (const uint8_t *)s->tlsext_hostname, + strlen(s->tlsext_hostname))) + return 0; + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_sni_is_ip_literal(CBS *cbs, int *is_ip) +{ + union { + struct in_addr ip4; + struct in6_addr ip6; + } addrbuf; + char *hostname = NULL; + + *is_ip = 0; + + if (!CBS_strdup(cbs, &hostname)) + return 0; + + if (inet_pton(AF_INET, hostname, &addrbuf) == 1 || + inet_pton(AF_INET6, hostname, &addrbuf) == 1) + *is_ip = 1; + + free(hostname); + + return 1; +} + +/* + * Validate that the CBS contains only a hostname consisting of RFC 5890 + * compliant A-labels (see RFC 6066 section 3). Not a complete check + * since we don't parse punycode to verify its validity but limits to + * correct structure and character set. + */ +int +tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip) +{ + uint8_t prev, c = 0; + int component = 0; + CBS hostname; + + *is_ip = 0; + + CBS_dup(cbs, &hostname); + + if (CBS_len(&hostname) > TLSEXT_MAXLEN_host_name) + return 0; + + /* An IP literal is invalid as a host name (RFC 6066 section 3). */ + if (!tlsext_sni_is_ip_literal(&hostname, is_ip)) + return 0; + if (*is_ip) + return 0; + + while (CBS_len(&hostname) > 0) { + prev = c; + if (!CBS_get_u8(&hostname, &c)) + return 0; + /* Everything has to be ASCII, with no NUL byte. */ + if (!isascii(c) || c == '\0') + return 0; + /* It must be alphanumeric, a '-', or a '.' */ + if (!isalnum(c) && c != '-' && c != '.') + return 0; + /* '-' and '.' must not start a component or be at the end. */ + if (component == 0 || CBS_len(&hostname) == 0) { + if (c == '-' || c == '.') + return 0; + } + if (c == '.') { + /* Components can not end with a dash. */ + if (prev == '-') + return 0; + /* Start new component */ + component = 0; + continue; + } + /* Components must be 63 chars or less. */ + if (++component > 63) + return 0; + } + + return 1; +} + +static int +tlsext_sni_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS server_name_list, host_name; + uint8_t name_type; + int is_ip; + + if (!CBS_get_u16_length_prefixed(cbs, &server_name_list)) + goto err; + + if (!CBS_get_u8(&server_name_list, &name_type)) + goto err; + + /* + * RFC 6066 section 3, only one type (host_name) is specified. + * We do not tolerate unknown types, neither does BoringSSL. + * other implementations appear more tolerant. + */ + if (name_type != TLSEXT_NAMETYPE_host_name) { + *alert = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + + /* + * RFC 6066 section 3 specifies a host name must be at least 1 byte + * so 0 length is a decode error. + */ + if (!CBS_get_u16_length_prefixed(&server_name_list, &host_name)) + goto err; + if (CBS_len(&host_name) < 1) + goto err; + + if (!tlsext_sni_is_valid_hostname(&host_name, &is_ip)) { + /* + * Various pieces of software have been known to set the SNI + * host name to an IP address, even though that violates the + * RFC. If this is the case, pretend the SNI extension does + * not exist. + */ + if (is_ip) + goto done; + + *alert = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + + if (s->hit || s->s3->hs.tls13.hrr) { + if (s->session->tlsext_hostname == NULL) { + *alert = SSL_AD_UNRECOGNIZED_NAME; + goto err; + } + if (!CBS_mem_equal(&host_name, s->session->tlsext_hostname, + strlen(s->session->tlsext_hostname))) { + *alert = SSL_AD_UNRECOGNIZED_NAME; + goto err; + } + } else { + if (s->session->tlsext_hostname != NULL) + goto err; + if (!CBS_strdup(&host_name, &s->session->tlsext_hostname)) { + *alert = SSL_AD_INTERNAL_ERROR; + goto err; + } + } + + done: + /* + * RFC 6066 section 3 forbids multiple host names with the same type, + * therefore we allow only one entry. + */ + if (CBS_len(&server_name_list) != 0) { + *alert = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + + return 1; + + err: + return 0; +} + +static int +tlsext_sni_server_needs(SSL *s, uint16_t msg_type) +{ + if (s->hit) + return 0; + + return (s->session->tlsext_hostname != NULL); +} + +static int +tlsext_sni_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return 1; +} + +static int +tlsext_sni_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + if (s->tlsext_hostname == NULL || CBS_len(cbs) != 0) { + *alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } + + if (s->hit) { + if (s->session->tlsext_hostname == NULL) { + *alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } + if (strcmp(s->tlsext_hostname, + s->session->tlsext_hostname) != 0) { + *alert = SSL_AD_UNRECOGNIZED_NAME; + return 0; + } + } else { + if (s->session->tlsext_hostname != NULL) + return 0; + if ((s->session->tlsext_hostname = + strdup(s->tlsext_hostname)) == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + return 1; +} + +/* + * Certificate Status Request - RFC 6066 section 8. + */ + +static int +tlsext_ocsp_client_needs(SSL *s, uint16_t msg_type) +{ + if (msg_type != SSL_TLSEXT_MSG_CH) + return 0; + + return (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp); +} + +static int +tlsext_ocsp_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB respid_list, respid, exts; + unsigned char *ext_data; + size_t ext_len; + int i; + + if (!CBB_add_u8(cbb, TLSEXT_STATUSTYPE_ocsp)) + return 0; + if (!CBB_add_u16_length_prefixed(cbb, &respid_list)) + return 0; + for (i = 0; i < sk_OCSP_RESPID_num(s->tlsext_ocsp_ids); i++) { + unsigned char *respid_data; + OCSP_RESPID *id; + size_t id_len; + + if ((id = sk_OCSP_RESPID_value(s->tlsext_ocsp_ids, + i)) == NULL) + return 0; + if ((id_len = i2d_OCSP_RESPID(id, NULL)) == -1) + return 0; + if (!CBB_add_u16_length_prefixed(&respid_list, &respid)) + return 0; + if (!CBB_add_space(&respid, &respid_data, id_len)) + return 0; + if ((i2d_OCSP_RESPID(id, &respid_data)) != id_len) + return 0; + } + if (!CBB_add_u16_length_prefixed(cbb, &exts)) + return 0; + if ((ext_len = i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, + NULL)) == -1) + return 0; + if (!CBB_add_space(&exts, &ext_data, ext_len)) + return 0; + if ((i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ext_data) != + ext_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + return 1; +} + +static int +tlsext_ocsp_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + int alert_desc = SSL_AD_DECODE_ERROR; + CBS respid_list, respid, exts; + const unsigned char *p; + uint8_t status_type; + int ret = 0; + + if (msg_type != SSL_TLSEXT_MSG_CH) + goto err; + + if (!CBS_get_u8(cbs, &status_type)) + goto err; + if (status_type != TLSEXT_STATUSTYPE_ocsp) { + /* ignore unknown status types */ + s->tlsext_status_type = -1; + + if (!CBS_skip(cbs, CBS_len(cbs))) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + return 1; + } + s->tlsext_status_type = status_type; + if (!CBS_get_u16_length_prefixed(cbs, &respid_list)) + goto err; + + /* XXX */ + sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free); + s->tlsext_ocsp_ids = NULL; + if (CBS_len(&respid_list) > 0) { + s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null(); + if (s->tlsext_ocsp_ids == NULL) { + alert_desc = SSL_AD_INTERNAL_ERROR; + goto err; + } + } + + while (CBS_len(&respid_list) > 0) { + OCSP_RESPID *id; + + if (!CBS_get_u16_length_prefixed(&respid_list, &respid)) + goto err; + p = CBS_data(&respid); + if ((id = d2i_OCSP_RESPID(NULL, &p, CBS_len(&respid))) == NULL) + goto err; + if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) { + alert_desc = SSL_AD_INTERNAL_ERROR; + OCSP_RESPID_free(id); + goto err; + } + } + + /* Read in request_extensions */ + if (!CBS_get_u16_length_prefixed(cbs, &exts)) + goto err; + if (CBS_len(&exts) > 0) { + sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts, + X509_EXTENSION_free); + p = CBS_data(&exts); + if ((s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL, + &p, CBS_len(&exts))) == NULL) + goto err; + } + + ret = 1; + err: + if (ret == 0) + *alert = alert_desc; + return ret; +} + +static int +tlsext_ocsp_server_needs(SSL *s, uint16_t msg_type) +{ + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION && + s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && + s->ctx->tlsext_status_cb != NULL) { + s->tlsext_status_expected = 0; + if (s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg) == SSL_TLSEXT_ERR_OK && + s->tlsext_ocsp_resp_len > 0) + s->tlsext_status_expected = 1; + } + return s->tlsext_status_expected; +} + +static int +tlsext_ocsp_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB ocsp_response; + + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) { + if (!CBB_add_u8(cbb, TLSEXT_STATUSTYPE_ocsp)) + return 0; + if (!CBB_add_u24_length_prefixed(cbb, &ocsp_response)) + return 0; + if (!CBB_add_bytes(&ocsp_response, + s->tlsext_ocsp_resp, + s->tlsext_ocsp_resp_len)) + return 0; + if (!CBB_flush(cbb)) + return 0; + } + return 1; +} + +static int +tlsext_ocsp_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + uint8_t status_type; + CBS response; + + if (ssl_effective_tls_version(s) >= TLS1_3_VERSION) { + if (msg_type == SSL_TLSEXT_MSG_CR) { + /* + * RFC 8446, 4.4.2.1 - the server may request an OCSP + * response with an empty status_request. + */ + if (CBS_len(cbs) == 0) + return 1; + + SSLerror(s, SSL_R_LENGTH_MISMATCH); + return 0; + } + if (!CBS_get_u8(cbs, &status_type)) { + SSLerror(s, SSL_R_LENGTH_MISMATCH); + return 0; + } + if (status_type != TLSEXT_STATUSTYPE_ocsp) { + SSLerror(s, SSL_R_UNSUPPORTED_STATUS_TYPE); + return 0; + } + if (!CBS_get_u24_length_prefixed(cbs, &response)) { + SSLerror(s, SSL_R_LENGTH_MISMATCH); + return 0; + } + if (CBS_len(&response) > 65536) { + SSLerror(s, SSL_R_DATA_LENGTH_TOO_LONG); + return 0; + } + if (!CBS_stow(&response, &s->tlsext_ocsp_resp, + &s->tlsext_ocsp_resp_len)) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else { + if (s->tlsext_status_type == -1) { + *alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } + /* Set flag to expect CertificateStatus message */ + s->tlsext_status_expected = 1; + } + return 1; +} + +/* + * SessionTicket extension - RFC 5077 section 3.2 + */ +static int +tlsext_sessionticket_client_needs(SSL *s, uint16_t msg_type) +{ + /* + * Send session ticket extension when enabled and not overridden. + * + * When renegotiating, send an empty session ticket to indicate support. + */ + if ((SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) + return 0; + + if (!ssl_security_tickets(s)) + return 0; + + if (s->new_session) + return 1; + + if (s->tlsext_session_ticket != NULL && + s->tlsext_session_ticket->data == NULL) + return 0; + + return 1; +} + +static int +tlsext_sessionticket_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + /* + * Signal that we support session tickets by sending an empty + * extension when renegotiating or no session found. + */ + if (s->new_session || s->session == NULL) + return 1; + + if (s->session->tlsext_tick != NULL) { + /* Attempt to resume with an existing session ticket */ + if (!CBB_add_bytes(cbb, s->session->tlsext_tick, + s->session->tlsext_ticklen)) + return 0; + + } else if (s->tlsext_session_ticket != NULL) { + /* + * Attempt to resume with a custom provided session ticket set + * by SSL_set_session_ticket_ext(). + */ + if (s->tlsext_session_ticket->length > 0) { + size_t ticklen = s->tlsext_session_ticket->length; + + if ((s->session->tlsext_tick = malloc(ticklen)) == NULL) + return 0; + memcpy(s->session->tlsext_tick, + s->tlsext_session_ticket->data, + ticklen); + s->session->tlsext_ticklen = ticklen; + + if (!CBB_add_bytes(cbb, s->session->tlsext_tick, + s->session->tlsext_ticklen)) + return 0; + } + } + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_sessionticket_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + if (s->tls_session_ticket_ext_cb) { + if (!s->tls_session_ticket_ext_cb(s, CBS_data(cbs), + (int)CBS_len(cbs), + s->tls_session_ticket_ext_cb_arg)) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + /* We need to signal that this was processed fully */ + if (!CBS_skip(cbs, CBS_len(cbs))) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +static int +tlsext_sessionticket_server_needs(SSL *s, uint16_t msg_type) +{ + return (s->tlsext_ticket_expected && + !(SSL_get_options(s) & SSL_OP_NO_TICKET) && + ssl_security_tickets(s)); +} + +static int +tlsext_sessionticket_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + /* Empty ticket */ + return 1; +} + +static int +tlsext_sessionticket_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + if (s->tls_session_ticket_ext_cb) { + if (!s->tls_session_ticket_ext_cb(s, CBS_data(cbs), + (int)CBS_len(cbs), + s->tls_session_ticket_ext_cb_arg)) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + if ((SSL_get_options(s) & SSL_OP_NO_TICKET) != 0 || CBS_len(cbs) > 0) { + *alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } + + s->tlsext_ticket_expected = 1; + + return 1; +} + +/* + * DTLS extension for SRTP key establishment - RFC 5764 + */ + +#ifndef OPENSSL_NO_SRTP + +static int +tlsext_srtp_client_needs(SSL *s, uint16_t msg_type) +{ + return SSL_is_dtls(s) && SSL_get_srtp_profiles(s) != NULL; +} + +static int +tlsext_srtp_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB profiles, mki; + int ct, i; + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = NULL; + const SRTP_PROTECTION_PROFILE *prof; + + if ((clnt = SSL_get_srtp_profiles(s)) == NULL) { + SSLerror(s, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if ((ct = sk_SRTP_PROTECTION_PROFILE_num(clnt)) < 1) { + SSLerror(s, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (!CBB_add_u16_length_prefixed(cbb, &profiles)) + return 0; + + for (i = 0; i < ct; i++) { + if ((prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i)) == NULL) + return 0; + if (!CBB_add_u16(&profiles, prof->id)) + return 0; + } + + if (!CBB_add_u8_length_prefixed(cbb, &mki)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_srtp_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + const SRTP_PROTECTION_PROFILE *cprof, *sprof; + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = NULL, *srvr; + int i, j; + int ret; + uint16_t id; + CBS profiles, mki; + + ret = 0; + + if (!CBS_get_u16_length_prefixed(cbs, &profiles)) + goto err; + if (CBS_len(&profiles) == 0 || CBS_len(&profiles) % 2 != 0) + goto err; + + if ((clnt = sk_SRTP_PROTECTION_PROFILE_new_null()) == NULL) + goto err; + + while (CBS_len(&profiles) > 0) { + if (!CBS_get_u16(&profiles, &id)) + goto err; + + if (!srtp_find_profile_by_num(id, &cprof)) { + if (!sk_SRTP_PROTECTION_PROFILE_push(clnt, cprof)) + goto err; + } + } + + if (!CBS_get_u8_length_prefixed(cbs, &mki) || CBS_len(&mki) != 0) { + SSLerror(s, SSL_R_BAD_SRTP_MKI_VALUE); + goto done; + } + + /* + * Per RFC 5764 section 4.1.1 + * + * Find the server preferred profile using the client's list. + * + * The server MUST send a profile if it sends the use_srtp + * extension. If one is not found, it should fall back to the + * negotiated DTLS cipher suite or return a DTLS alert. + */ + if ((srvr = SSL_get_srtp_profiles(s)) == NULL) + goto err; + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(srvr); i++) { + if ((sprof = sk_SRTP_PROTECTION_PROFILE_value(srvr, i)) == NULL) + goto err; + + for (j = 0; j < sk_SRTP_PROTECTION_PROFILE_num(clnt); j++) { + if ((cprof = sk_SRTP_PROTECTION_PROFILE_value(clnt, j)) + == NULL) + goto err; + + if (cprof->id == sprof->id) { + s->srtp_profile = sprof; + ret = 1; + goto done; + } + } + } + + /* If we didn't find anything, fall back to the negotiated */ + ret = 1; + goto done; + + err: + SSLerror(s, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + + done: + sk_SRTP_PROTECTION_PROFILE_free(clnt); + return ret; +} + +static int +tlsext_srtp_server_needs(SSL *s, uint16_t msg_type) +{ + return SSL_is_dtls(s) && SSL_get_selected_srtp_profile(s) != NULL; +} + +static int +tlsext_srtp_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + SRTP_PROTECTION_PROFILE *profile; + CBB srtp, mki; + + if (!CBB_add_u16_length_prefixed(cbb, &srtp)) + return 0; + + if ((profile = SSL_get_selected_srtp_profile(s)) == NULL) + return 0; + + if (!CBB_add_u16(&srtp, profile->id)) + return 0; + + if (!CBB_add_u8_length_prefixed(cbb, &mki)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_srtp_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + STACK_OF(SRTP_PROTECTION_PROFILE) *clnt; + const SRTP_PROTECTION_PROFILE *prof; + int i; + uint16_t id; + CBS profile_ids, mki; + + if (!CBS_get_u16_length_prefixed(cbs, &profile_ids)) { + SSLerror(s, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (!CBS_get_u16(&profile_ids, &id) || CBS_len(&profile_ids) != 0) { + SSLerror(s, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + return 0; + } + + if (!CBS_get_u8_length_prefixed(cbs, &mki) || CBS_len(&mki) != 0) { + SSLerror(s, SSL_R_BAD_SRTP_MKI_VALUE); + *alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + if ((clnt = SSL_get_srtp_profiles(s)) == NULL) { + SSLerror(s, SSL_R_NO_SRTP_PROFILES); + return 0; + } + + for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) { + if ((prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i)) + == NULL) { + SSLerror(s, SSL_R_NO_SRTP_PROFILES); + return 0; + } + + if (prof->id == id) { + s->srtp_profile = prof; + return 1; + } + } + + SSLerror(s, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); + + return 0; +} + +#endif /* OPENSSL_NO_SRTP */ + +/* + * TLSv1.3 Key Share - RFC 8446 section 4.2.8. + */ +static int +tlsext_keyshare_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_keyshare_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB client_shares, key_exchange; + + if (!CBB_add_u16_length_prefixed(cbb, &client_shares)) + return 0; + + if (!CBB_add_u16(&client_shares, + tls_key_share_group(s->s3->hs.key_share))) + return 0; + if (!CBB_add_u16_length_prefixed(&client_shares, &key_exchange)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &key_exchange)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS client_shares, key_exchange; + int decode_error; + uint16_t group; + + if (!CBS_get_u16_length_prefixed(cbs, &client_shares)) + return 0; + + while (CBS_len(&client_shares) > 0) { + + /* Unpack client share. */ + if (!CBS_get_u16(&client_shares, &group)) + return 0; + if (!CBS_get_u16_length_prefixed(&client_shares, &key_exchange)) + return 0; + + /* + * XXX - check key exchange against supported groups from client. + * XXX - check that groups only appear once. + */ + + /* + * Ignore this client share if we're using earlier than TLSv1.3 + * or we've already selected a key share. + */ + if (s->s3->hs.our_max_tls_version < TLS1_3_VERSION) + continue; + if (s->s3->hs.key_share != NULL) + continue; + + /* XXX - consider implementing server preference. */ + if (!tls1_check_group(s, group)) + continue; + + /* Decode and store the selected key share. */ + if ((s->s3->hs.key_share = tls_key_share_new(group)) == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, + &key_exchange, &decode_error, NULL)) { + if (!decode_error) + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + } + + return 1; +} + +static int +tlsext_keyshare_server_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION && + tlsext_extension_seen(s, TLSEXT_TYPE_key_share)); +} + +static int +tlsext_keyshare_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB key_exchange; + + /* In the case of a HRR, we only send the server selected group. */ + if (s->s3->hs.tls13.hrr) { + if (s->s3->hs.tls13.server_group == 0) + return 0; + return CBB_add_u16(cbb, s->s3->hs.tls13.server_group); + } + + if (s->s3->hs.key_share == NULL) + return 0; + + if (!CBB_add_u16(cbb, tls_key_share_group(s->s3->hs.key_share))) + return 0; + if (!CBB_add_u16_length_prefixed(cbb, &key_exchange)) + return 0; + if (!tls_key_share_public(s->s3->hs.key_share, &key_exchange)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_keyshare_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS key_exchange; + int decode_error; + uint16_t group; + + /* Unpack server share. */ + if (!CBS_get_u16(cbs, &group)) + return 0; + + if (CBS_len(cbs) == 0) { + /* HRR does not include an actual key share, only the group. */ + if (msg_type != SSL_TLSEXT_MSG_HRR) + return 0; + + s->s3->hs.tls13.server_group = group; + return 1; + } + + if (!CBS_get_u16_length_prefixed(cbs, &key_exchange)) + return 0; + + if (s->s3->hs.key_share == NULL) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + if (tls_key_share_group(s->s3->hs.key_share) != group) { + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + if (!tls_key_share_peer_public(s->s3->hs.key_share, + &key_exchange, &decode_error, NULL)) { + if (!decode_error) + *alert = SSL_AD_INTERNAL_ERROR; + return 0; + } + + return 1; +} + +/* + * Supported Versions - RFC 8446 section 4.2.1. + */ +static int +tlsext_versions_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_versions_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + uint16_t max, min; + uint16_t version; + CBB versions; + + max = s->s3->hs.our_max_tls_version; + min = s->s3->hs.our_min_tls_version; + + if (!CBB_add_u8_length_prefixed(cbb, &versions)) + return 0; + + /* XXX - fix, but contiguous for now... */ + for (version = max; version >= min; version--) { + if (!CBB_add_u16(&versions, version)) + return 0; + } + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS versions; + uint16_t version; + uint16_t max, min; + uint16_t matched_version = 0; + + max = s->s3->hs.our_max_tls_version; + min = s->s3->hs.our_min_tls_version; + + if (!CBS_get_u8_length_prefixed(cbs, &versions)) + return 0; + + while (CBS_len(&versions) > 0) { + if (!CBS_get_u16(&versions, &version)) + return 0; + /* + * XXX What is below implements client preference, and + * ignores any server preference entirely. + */ + if (matched_version == 0 && version >= min && version <= max) + matched_version = version; + } + + if (matched_version > 0) { + /* XXX - this should be stored for later processing. */ + s->version = matched_version; + return 1; + } + + *alert = SSL_AD_PROTOCOL_VERSION; + return 0; +} + +static int +tlsext_versions_server_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_versions_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return CBB_add_u16(cbb, TLS1_3_VERSION); +} + +static int +tlsext_versions_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + uint16_t selected_version; + + if (!CBS_get_u16(cbs, &selected_version)) + return 0; + + /* XXX - need to fix for DTLS 1.3 */ + if (selected_version < TLS1_3_VERSION) { + *alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + /* XXX test between min and max once initialization code goes in */ + s->s3->hs.tls13.server_version = selected_version; + + return 1; +} + + +/* + * Cookie - RFC 8446 section 4.2.2. + */ + +static int +tlsext_cookie_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION && + s->s3->hs.tls13.cookie_len > 0 && s->s3->hs.tls13.cookie != NULL); +} + +static int +tlsext_cookie_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB cookie; + + if (!CBB_add_u16_length_prefixed(cbb, &cookie)) + return 0; + + if (!CBB_add_bytes(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_cookie_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS cookie; + + if (!CBS_get_u16_length_prefixed(cbs, &cookie)) + return 0; + + if (CBS_len(&cookie) != s->s3->hs.tls13.cookie_len) + return 0; + + /* + * Check provided cookie value against what server previously + * sent - client *MUST* send the same cookie with new CR after + * a cookie is sent by the server with an HRR. + */ + if (!CBS_mem_equal(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) { + /* XXX special cookie mismatch alert? */ + *alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + return 1; +} + +static int +tlsext_cookie_server_needs(SSL *s, uint16_t msg_type) +{ + /* + * Server needs to set cookie value in tls13 handshake + * in order to send one, should only be sent with HRR. + */ + return (s->s3->hs.our_max_tls_version >= TLS1_3_VERSION && + s->s3->hs.tls13.cookie_len > 0 && s->s3->hs.tls13.cookie != NULL); +} + +static int +tlsext_cookie_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB cookie; + + /* XXX deduplicate with client code */ + + if (!CBB_add_u16_length_prefixed(cbb, &cookie)) + return 0; + + if (!CBB_add_bytes(&cookie, s->s3->hs.tls13.cookie, + s->s3->hs.tls13.cookie_len)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_cookie_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + CBS cookie; + + /* + * XXX This currently assumes we will not get a second + * HRR from a server with a cookie to process after accepting + * one from the server in the same handshake + */ + if (s->s3->hs.tls13.cookie != NULL || + s->s3->hs.tls13.cookie_len != 0) { + *alert = SSL_AD_ILLEGAL_PARAMETER; + return 0; + } + + if (!CBS_get_u16_length_prefixed(cbs, &cookie)) + return 0; + + if (!CBS_stow(&cookie, &s->s3->hs.tls13.cookie, + &s->s3->hs.tls13.cookie_len)) + return 0; + + return 1; +} + +/* + * Pre-Shared Key Exchange Modes - RFC 8446, 4.2.9. + */ + +static int +tlsext_psk_kex_modes_client_needs(SSL *s, uint16_t msg_type) +{ + return (s->s3->hs.tls13.use_psk_dhe_ke && + s->s3->hs.our_max_tls_version >= TLS1_3_VERSION); +} + +static int +tlsext_psk_kex_modes_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + CBB ke_modes; + + if (!CBB_add_u8_length_prefixed(cbb, &ke_modes)) + return 0; + + /* Only indicate support for PSK with DHE key establishment. */ + if (!CBB_add_u8(&ke_modes, TLS13_PSK_DHE_KE)) + return 0; + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +static int +tlsext_psk_kex_modes_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + CBS ke_modes; + uint8_t ke_mode; + + if (!CBS_get_u8_length_prefixed(cbs, &ke_modes)) + return 0; + + while (CBS_len(&ke_modes) > 0) { + if (!CBS_get_u8(&ke_modes, &ke_mode)) + return 0; + + if (ke_mode == TLS13_PSK_DHE_KE) + s->s3->hs.tls13.use_psk_dhe_ke = 1; + } + + return 1; +} + +static int +tlsext_psk_kex_modes_server_needs(SSL *s, uint16_t msg_type) +{ + /* Servers MUST NOT send this extension. */ + return 0; +} + +static int +tlsext_psk_kex_modes_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return 0; +} + +static int +tlsext_psk_kex_modes_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, + int *alert) +{ + return 0; +} + +/* + * Pre-Shared Key Extension - RFC 8446, 4.2.11 + */ + +static int +tlsext_psk_client_needs(SSL *s, uint16_t msg_type) +{ + return 0; +} + +static int +tlsext_psk_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return 0; +} + +static int +tlsext_psk_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + return CBS_skip(cbs, CBS_len(cbs)); +} + +static int +tlsext_psk_server_needs(SSL *s, uint16_t msg_type) +{ + return 0; +} + +static int +tlsext_psk_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return 0; +} + +static int +tlsext_psk_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + return CBS_skip(cbs, CBS_len(cbs)); +} + +/* + * QUIC transport parameters extension - RFC 9001 section 8.2. + */ + +static int +tlsext_quic_transport_parameters_client_needs(SSL *s, uint16_t msg_type) +{ + return SSL_is_quic(s) && s->quic_transport_params_len > 0; +} + +static int +tlsext_quic_transport_parameters_client_build(SSL *s, uint16_t msg_type, + CBB *cbb) +{ + if (!CBB_add_bytes(cbb, s->quic_transport_params, + s->quic_transport_params_len)) + return 0; + + return 1; +} + +static int +tlsext_quic_transport_parameters_client_parse(SSL *s, uint16_t msg_type, + CBS *cbs, int *alert) +{ + if (!SSL_is_quic(s)) { + *alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } + + if (!CBS_stow(cbs, &s->s3->peer_quic_transport_params, + &s->s3->peer_quic_transport_params_len)) + return 0; + if (!CBS_skip(cbs, s->s3->peer_quic_transport_params_len)) + return 0; + + return 1; +} + +static int +tlsext_quic_transport_parameters_server_needs(SSL *s, uint16_t msg_type) +{ + return SSL_is_quic(s) && s->quic_transport_params_len > 0; +} + +static int +tlsext_quic_transport_parameters_server_build(SSL *s, uint16_t msg_type, + CBB *cbb) +{ + if (!CBB_add_bytes(cbb, s->quic_transport_params, + s->quic_transport_params_len)) + return 0; + + return 1; +} + +static int +tlsext_quic_transport_parameters_server_parse(SSL *s, uint16_t msg_type, + CBS *cbs, int *alert) +{ + if (!SSL_is_quic(s)) { + *alert = SSL_AD_UNSUPPORTED_EXTENSION; + return 0; + } + + if (!CBS_stow(cbs, &s->s3->peer_quic_transport_params, + &s->s3->peer_quic_transport_params_len)) + return 0; + if (!CBS_skip(cbs, s->s3->peer_quic_transport_params_len)) + return 0; + + return 1; +} + +struct tls_extension_funcs { + int (*needs)(SSL *s, uint16_t msg_type); + int (*build)(SSL *s, uint16_t msg_type, CBB *cbb); + int (*parse)(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); +}; + +struct tls_extension { + uint16_t type; + uint16_t messages; + struct tls_extension_funcs client; + struct tls_extension_funcs server; +}; + +static const struct tls_extension tls_extensions[] = { + { + .type = TLSEXT_TYPE_supported_versions, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH | + SSL_TLSEXT_MSG_HRR, + .client = { + .needs = tlsext_versions_client_needs, + .build = tlsext_versions_client_build, + .parse = tlsext_versions_client_parse, + }, + .server = { + .needs = tlsext_versions_server_needs, + .build = tlsext_versions_server_build, + .parse = tlsext_versions_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_key_share, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH | + SSL_TLSEXT_MSG_HRR, + .client = { + .needs = tlsext_keyshare_client_needs, + .build = tlsext_keyshare_client_build, + .parse = tlsext_keyshare_client_parse, + }, + .server = { + .needs = tlsext_keyshare_server_needs, + .build = tlsext_keyshare_server_build, + .parse = tlsext_keyshare_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_server_name, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_EE, + .client = { + .needs = tlsext_sni_client_needs, + .build = tlsext_sni_client_build, + .parse = tlsext_sni_client_parse, + }, + .server = { + .needs = tlsext_sni_server_needs, + .build = tlsext_sni_server_build, + .parse = tlsext_sni_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_renegotiate, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH, + .client = { + .needs = tlsext_ri_client_needs, + .build = tlsext_ri_client_build, + .parse = tlsext_ri_client_parse, + }, + .server = { + .needs = tlsext_ri_server_needs, + .build = tlsext_ri_server_build, + .parse = tlsext_ri_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_status_request, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_CR | + SSL_TLSEXT_MSG_CT, + .client = { + .needs = tlsext_ocsp_client_needs, + .build = tlsext_ocsp_client_build, + .parse = tlsext_ocsp_client_parse, + }, + .server = { + .needs = tlsext_ocsp_server_needs, + .build = tlsext_ocsp_server_build, + .parse = tlsext_ocsp_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_ec_point_formats, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH, + .client = { + .needs = tlsext_ecpf_client_needs, + .build = tlsext_ecpf_client_build, + .parse = tlsext_ecpf_client_parse, + }, + .server = { + .needs = tlsext_ecpf_server_needs, + .build = tlsext_ecpf_server_build, + .parse = tlsext_ecpf_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_supported_groups, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_EE, + .client = { + .needs = tlsext_supportedgroups_client_needs, + .build = tlsext_supportedgroups_client_build, + .parse = tlsext_supportedgroups_client_parse, + }, + .server = { + .needs = tlsext_supportedgroups_server_needs, + .build = tlsext_supportedgroups_server_build, + .parse = tlsext_supportedgroups_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_session_ticket, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH, + .client = { + .needs = tlsext_sessionticket_client_needs, + .build = tlsext_sessionticket_client_build, + .parse = tlsext_sessionticket_client_parse, + }, + .server = { + .needs = tlsext_sessionticket_server_needs, + .build = tlsext_sessionticket_server_build, + .parse = tlsext_sessionticket_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_signature_algorithms, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_CR, + .client = { + .needs = tlsext_sigalgs_client_needs, + .build = tlsext_sigalgs_client_build, + .parse = tlsext_sigalgs_client_parse, + }, + .server = { + .needs = tlsext_sigalgs_server_needs, + .build = tlsext_sigalgs_server_build, + .parse = tlsext_sigalgs_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_alpn, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_EE, + .client = { + .needs = tlsext_alpn_client_needs, + .build = tlsext_alpn_client_build, + .parse = tlsext_alpn_client_parse, + }, + .server = { + .needs = tlsext_alpn_server_needs, + .build = tlsext_alpn_server_build, + .parse = tlsext_alpn_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_cookie, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_HRR, + .client = { + .needs = tlsext_cookie_client_needs, + .build = tlsext_cookie_client_build, + .parse = tlsext_cookie_client_parse, + }, + .server = { + .needs = tlsext_cookie_server_needs, + .build = tlsext_cookie_server_build, + .parse = tlsext_cookie_server_parse, + }, + }, +#ifndef OPENSSL_NO_SRTP + { + .type = TLSEXT_TYPE_use_srtp, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH /* XXX */ | + SSL_TLSEXT_MSG_EE, + .client = { + .needs = tlsext_srtp_client_needs, + .build = tlsext_srtp_client_build, + .parse = tlsext_srtp_client_parse, + }, + .server = { + .needs = tlsext_srtp_server_needs, + .build = tlsext_srtp_server_build, + .parse = tlsext_srtp_server_parse, + }, + }, +#endif /* OPENSSL_NO_SRTP */ + { + .type = TLSEXT_TYPE_quic_transport_parameters, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_EE, + .client = { + .needs = tlsext_quic_transport_parameters_client_needs, + .build = tlsext_quic_transport_parameters_client_build, + .parse = tlsext_quic_transport_parameters_client_parse, + }, + .server = { + .needs = tlsext_quic_transport_parameters_server_needs, + .build = tlsext_quic_transport_parameters_server_build, + .parse = tlsext_quic_transport_parameters_server_parse, + }, + }, + { + .type = TLSEXT_TYPE_psk_key_exchange_modes, + .messages = SSL_TLSEXT_MSG_CH, + .client = { + .needs = tlsext_psk_kex_modes_client_needs, + .build = tlsext_psk_kex_modes_client_build, + .parse = tlsext_psk_kex_modes_client_parse, + }, + .server = { + .needs = tlsext_psk_kex_modes_server_needs, + .build = tlsext_psk_kex_modes_server_build, + .parse = tlsext_psk_kex_modes_server_parse, + }, + }, + { + /* MUST be last extension in CH per RFC 8446 section 4.2. */ + + .type = TLSEXT_TYPE_pre_shared_key, + .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH, + .client = { + .needs = tlsext_psk_client_needs, + .build = tlsext_psk_client_build, + .parse = tlsext_psk_client_parse, + }, + .server = { + .needs = tlsext_psk_server_needs, + .build = tlsext_psk_server_build, + .parse = tlsext_psk_server_parse, + }, + }, +}; + +#define N_TLS_EXTENSIONS (sizeof(tls_extensions) / sizeof(*tls_extensions)) + +/* Ensure that extensions fit in a uint32_t bitmask. */ +CTASSERT(N_TLS_EXTENSIONS <= (sizeof(uint32_t) * 8)); + +uint16_t +tls_extension_type(const struct tls_extension *extension) +{ + return extension->type; +} + +const struct tls_extension * +tls_extension_find(uint16_t type, size_t *tls_extensions_idx) +{ + size_t i; + + for (i = 0; i < N_TLS_EXTENSIONS; i++) { + if (tls_extensions[i].type == type) { + *tls_extensions_idx = i; + return &tls_extensions[i]; + } + } + + return NULL; +} + +int +tlsext_extension_seen(SSL *s, uint16_t type) +{ + size_t idx; + + if (tls_extension_find(type, &idx) == NULL) + return 0; + return ((s->s3->hs.extensions_seen & (1 << idx)) != 0); +} + +const struct tls_extension_funcs * +tlsext_funcs(const struct tls_extension *tlsext, int is_server) +{ + if (is_server) + return &tlsext->server; + + return &tlsext->client; +} + +int +tlsext_randomize_build_order(SSL *s) +{ + size_t idx, new_idx, psk_idx; + size_t alpn_idx = 0, sni_idx = 0; + + free(s->tlsext_build_order); + s->tlsext_build_order_len = 0; + + if ((s->tlsext_build_order = calloc(sizeof(*s->tlsext_build_order), + N_TLS_EXTENSIONS)) == NULL) + return 0; + s->tlsext_build_order_len = N_TLS_EXTENSIONS; + + /* RFC 8446, section 4.2: PSK must be the last extension in the CH. */ + psk_idx = N_TLS_EXTENSIONS - 1; + s->tlsext_build_order[psk_idx] = &tls_extensions[psk_idx]; + + /* Fisher-Yates shuffle with PSK fixed. */ + for (idx = 0; idx < psk_idx; idx++) { + new_idx = arc4random_uniform(idx + 1); + s->tlsext_build_order[idx] = s->tlsext_build_order[new_idx]; + s->tlsext_build_order[new_idx] = &tls_extensions[idx]; + } + + /* + * XXX - Apache2 special until year 2025: ensure that SNI precedes ALPN + * for clients so that virtual host setups work correctly. + */ + + if (s->server) + return 1; + + for (idx = 0; idx < N_TLS_EXTENSIONS; idx++) { + if (s->tlsext_build_order[idx]->type == TLSEXT_TYPE_alpn) + alpn_idx = idx; + if (s->tlsext_build_order[idx]->type == TLSEXT_TYPE_server_name) + sni_idx = idx; + } + if (alpn_idx < sni_idx) { + const struct tls_extension *tmp; + + tmp = s->tlsext_build_order[alpn_idx]; + s->tlsext_build_order[alpn_idx] = s->tlsext_build_order[sni_idx]; + s->tlsext_build_order[sni_idx] = tmp; + } + + return 1; +} + +int +tlsext_linearize_build_order(SSL *s) +{ + size_t idx; + + free(s->tlsext_build_order); + s->tlsext_build_order_len = 0; + + if ((s->tlsext_build_order = calloc(sizeof(*s->tlsext_build_order), + N_TLS_EXTENSIONS)) == NULL) + return 0; + s->tlsext_build_order_len = N_TLS_EXTENSIONS; + + for (idx = 0; idx < N_TLS_EXTENSIONS; idx++) + s->tlsext_build_order[idx] = &tls_extensions[idx]; + + return 1; +} + +static int +tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb) +{ + const struct tls_extension_funcs *ext; + const struct tls_extension *tlsext; + CBB extensions, extension_data; + int extensions_present = 0; + uint16_t tls_version; + size_t i; + + tls_version = ssl_effective_tls_version(s); + + if (!CBB_add_u16_length_prefixed(cbb, &extensions)) + return 0; + + for (i = 0; i < N_TLS_EXTENSIONS; i++) { + tlsext = s->tlsext_build_order[i]; + ext = tlsext_funcs(tlsext, is_server); + + /* RFC 8446 Section 4.2 */ + if (tls_version >= TLS1_3_VERSION && + !(tlsext->messages & msg_type)) + continue; + + if (!ext->needs(s, msg_type)) + continue; + + if (!CBB_add_u16(&extensions, tlsext->type)) + return 0; + if (!CBB_add_u16_length_prefixed(&extensions, &extension_data)) + return 0; + + if (!ext->build(s, msg_type, &extension_data)) + return 0; + + extensions_present = 1; + } + + if (!extensions_present && + (msg_type & (SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH)) != 0) + CBB_discard_child(cbb); + + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +tlsext_clienthello_hash_extension(SSL *s, uint16_t type, CBS *cbs) +{ + /* + * RFC 8446 4.1.2. For subsequent CH, early data will be removed, + * cookie may be added, padding may be removed. + */ + struct tls13_ctx *ctx = s->tls13; + + if (type == TLSEXT_TYPE_early_data || type == TLSEXT_TYPE_cookie || + type == TLSEXT_TYPE_padding) + return 1; + if (!tls13_clienthello_hash_update_bytes(ctx, (void *)&type, + sizeof(type))) + return 0; + /* + * key_share data may be changed, and pre_shared_key data may + * be changed + */ + if (type == TLSEXT_TYPE_pre_shared_key || type == TLSEXT_TYPE_key_share) + return 1; + if (!tls13_clienthello_hash_update(ctx, cbs)) + return 0; + + return 1; +} + +static int +tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) +{ + const struct tls_extension_funcs *ext; + const struct tls_extension *tlsext; + CBS extensions, extension_data; + uint16_t type; + size_t idx; + uint16_t tls_version; + int alert_desc; + + tls_version = ssl_effective_tls_version(s); + + s->s3->hs.extensions_seen = 0; + + /* An empty extensions block is valid. */ + if (CBS_len(cbs) == 0) + return 1; + + alert_desc = SSL_AD_DECODE_ERROR; + + if (!CBS_get_u16_length_prefixed(cbs, &extensions)) + goto err; + + while (CBS_len(&extensions) > 0) { + if (!CBS_get_u16(&extensions, &type)) + goto err; + if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) + goto err; + + if (s->tlsext_debug_cb != NULL) + s->tlsext_debug_cb(s, !is_server, type, + (unsigned char *)CBS_data(&extension_data), + CBS_len(&extension_data), + s->tlsext_debug_arg); + + /* Unknown extensions are ignored. */ + if ((tlsext = tls_extension_find(type, &idx)) == NULL) + continue; + + if (tls_version >= TLS1_3_VERSION && is_server && + msg_type == SSL_TLSEXT_MSG_CH) { + if (!tlsext_clienthello_hash_extension(s, type, + &extension_data)) + goto err; + } + + /* RFC 8446 Section 4.2 */ + if (tls_version >= TLS1_3_VERSION && + !(tlsext->messages & msg_type)) { + alert_desc = SSL_AD_ILLEGAL_PARAMETER; + goto err; + } + + /* Check for duplicate known extensions. */ + if ((s->s3->hs.extensions_seen & (1 << idx)) != 0) + goto err; + s->s3->hs.extensions_seen |= (1 << idx); + + ext = tlsext_funcs(tlsext, is_server); + if (!ext->parse(s, msg_type, &extension_data, &alert_desc)) + goto err; + + if (CBS_len(&extension_data) != 0) + goto err; + } + + return 1; + + err: + *alert = alert_desc; + + return 0; +} + +static void +tlsext_server_reset_state(SSL *s) +{ + s->tlsext_status_type = -1; + s->s3->renegotiate_seen = 0; + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; + s->srtp_profile = NULL; +} + +int +tlsext_server_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return tlsext_build(s, 1, msg_type, cbb); +} + +int +tlsext_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + /* XXX - this should be done by the caller... */ + if (msg_type == SSL_TLSEXT_MSG_CH) + tlsext_server_reset_state(s); + + return tlsext_parse(s, 1, msg_type, cbs, alert); +} + +static void +tlsext_client_reset_state(SSL *s) +{ + s->s3->renegotiate_seen = 0; + free(s->s3->alpn_selected); + s->s3->alpn_selected = NULL; + s->s3->alpn_selected_len = 0; +} + +int +tlsext_client_build(SSL *s, uint16_t msg_type, CBB *cbb) +{ + return tlsext_build(s, 0, msg_type, cbb); +} + +int +tlsext_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) +{ + /* XXX - this should be done by the caller... */ + if (msg_type == SSL_TLSEXT_MSG_SH) + tlsext_client_reset_state(s); + + return tlsext_parse(s, 0, msg_type, cbs, alert); +} diff --git a/ssl/ssl_tlsext.h b/ssl/ssl_tlsext.h new file mode 100644 index 0000000..da14f7f --- /dev/null +++ b/ssl/ssl_tlsext.h @@ -0,0 +1,48 @@ +/* $OpenBSD: ssl_tlsext.h,v 1.33 2023/04/23 18:51:53 tb Exp $ */ +/* + * Copyright (c) 2016, 2017 Joel Sing + * Copyright (c) 2017 Doug Hogan + * Copyright (c) 2019 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_SSL_TLSEXT_H +#define HEADER_SSL_TLSEXT_H + +/* TLSv1.3 - RFC 8446 Section 4.2. */ +#define SSL_TLSEXT_MSG_CH 0x0001 /* ClientHello */ +#define SSL_TLSEXT_MSG_SH 0x0002 /* ServerHello */ +#define SSL_TLSEXT_MSG_EE 0x0004 /* EncryptedExtension */ +#define SSL_TLSEXT_MSG_CT 0x0008 /* Certificate */ +#define SSL_TLSEXT_MSG_CR 0x0010 /* CertificateRequest */ +#define SSL_TLSEXT_MSG_NST 0x0020 /* NewSessionTicket */ +#define SSL_TLSEXT_MSG_HRR 0x0040 /* HelloRetryRequest */ + +__BEGIN_HIDDEN_DECLS + +int tlsext_alpn_check_format(CBS *cbs); +int tlsext_sni_is_valid_hostname(CBS *cbs, int *is_ip); + +int tlsext_client_build(SSL *s, uint16_t msg_type, CBB *cbb); +int tlsext_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); + +int tlsext_server_build(SSL *s, uint16_t msg_type, CBB *cbb); +int tlsext_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); + +int tlsext_extension_seen(SSL *s, uint16_t); +int tlsext_randomize_build_order(SSL *s); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/ssl_transcript.c b/ssl/ssl_transcript.c new file mode 100644 index 0000000..22cd6c3 --- /dev/null +++ b/ssl/ssl_transcript.c @@ -0,0 +1,197 @@ +/* $OpenBSD: ssl_transcript.c,v 1.9 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" +#include "tls_internal.h" + +int +tls1_transcript_hash_init(SSL *s) +{ + const unsigned char *data; + const EVP_MD *md; + size_t len; + + tls1_transcript_hash_free(s); + + if (!ssl_get_handshake_evp_md(s, &md)) { + SSLerrorx(ERR_R_INTERNAL_ERROR); + goto err; + } + + if ((s->s3->handshake_hash = EVP_MD_CTX_new()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_DigestInit_ex(s->s3->handshake_hash, md, NULL)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + if (!tls1_transcript_data(s, &data, &len)) { + SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH); + goto err; + } + if (!tls1_transcript_hash_update(s, data, len)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + + return 1; + + err: + tls1_transcript_hash_free(s); + + return 0; +} + +int +tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len) +{ + if (s->s3->handshake_hash == NULL) + return 1; + + return EVP_DigestUpdate(s->s3->handshake_hash, buf, len); +} + +int +tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len, + size_t *outlen) +{ + EVP_MD_CTX *mdctx = NULL; + unsigned int mdlen; + int ret = 0; + + if (s->s3->handshake_hash == NULL) + goto err; + + if (EVP_MD_CTX_size(s->s3->handshake_hash) > len) + goto err; + + if ((mdctx = EVP_MD_CTX_new()) == NULL) { + SSLerror(s, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!EVP_MD_CTX_copy_ex(mdctx, s->s3->handshake_hash)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (!EVP_DigestFinal_ex(mdctx, out, &mdlen)) { + SSLerror(s, ERR_R_EVP_LIB); + goto err; + } + if (outlen != NULL) + *outlen = mdlen; + + ret = 1; + + err: + EVP_MD_CTX_free(mdctx); + + return (ret); +} + +void +tls1_transcript_hash_free(SSL *s) +{ + EVP_MD_CTX_free(s->s3->handshake_hash); + s->s3->handshake_hash = NULL; +} + +int +tls1_transcript_init(SSL *s) +{ + if (s->s3->handshake_transcript != NULL) + return 0; + + if ((s->s3->handshake_transcript = tls_buffer_new(0)) == NULL) + return 0; + + tls1_transcript_reset(s); + + return 1; +} + +void +tls1_transcript_free(SSL *s) +{ + tls_buffer_free(s->s3->handshake_transcript); + s->s3->handshake_transcript = NULL; +} + +void +tls1_transcript_reset(SSL *s) +{ + tls_buffer_clear(s->s3->handshake_transcript); + + tls1_transcript_unfreeze(s); +} + +int +tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len) +{ + if (s->s3->handshake_transcript == NULL) + return 1; + + if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT) + return 1; + + return tls_buffer_append(s->s3->handshake_transcript, buf, len); +} + +int +tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len) +{ + CBS cbs; + + if (s->s3->handshake_transcript == NULL) + return 0; + + if (!tls_buffer_data(s->s3->handshake_transcript, &cbs)) + return 0; + + /* XXX - change to caller providing a CBS argument. */ + *data = CBS_data(&cbs); + *len = CBS_len(&cbs); + + return 1; +} + +void +tls1_transcript_freeze(SSL *s) +{ + s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT; +} + +void +tls1_transcript_unfreeze(SSL *s) +{ + s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT; +} + +int +tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len) +{ + if (!tls1_transcript_hash_update(s, buf, len)) + return 0; + + if (!tls1_transcript_append(s, buf, len)) + return 0; + + return 1; +} diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c new file mode 100644 index 0000000..ee3d218 --- /dev/null +++ b/ssl/ssl_txt.c @@ -0,0 +1,201 @@ +/* $OpenBSD: ssl_txt.c,v 1.37 2023/07/08 16:40:13 beck Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include + +#include + +#include "ssl_local.h" + +int +SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *x) +{ + BIO *b; + int ret; + + if ((b = BIO_new(BIO_s_file())) == NULL) { + SSLerrorx(ERR_R_BUF_LIB); + return 0; + } + BIO_set_fp(b, fp, BIO_NOCLOSE); + ret = SSL_SESSION_print(b, x); + BIO_free(b); + return ret; +} +LSSL_ALIAS(SSL_SESSION_print_fp); + +int +SSL_SESSION_print(BIO *bp, const SSL_SESSION *x) +{ + size_t i; + int ret = 0; + + if (x == NULL) + goto err; + + if (BIO_puts(bp, "SSL-Session:\n") <= 0) + goto err; + + if (BIO_printf(bp, " Protocol : %s\n", + ssl_version_string(x->ssl_version)) <= 0) + goto err; + + if (x->cipher == NULL) { + if (BIO_printf(bp, " Cipher : %04lX\n", + x->cipher_id & SSL3_CK_VALUE_MASK) <= 0) + goto err; + } else { + const char *cipher_name = "unknown"; + + if (x->cipher->name != NULL) + cipher_name = x->cipher->name; + + if (BIO_printf(bp, " Cipher : %s\n", cipher_name) <= 0) + goto err; + } + + if (BIO_puts(bp, " Session-ID: ") <= 0) + goto err; + + for (i = 0; i < x->session_id_length; i++) { + if (BIO_printf(bp, "%02X", x->session_id[i]) <= 0) + goto err; + } + + if (BIO_puts(bp, "\n Session-ID-ctx: ") <= 0) + goto err; + + for (i = 0; i < x->sid_ctx_length; i++) { + if (BIO_printf(bp, "%02X", x->sid_ctx[i]) <= 0) + goto err; + } + + if (BIO_puts(bp, "\n Master-Key: ") <= 0) + goto err; + + for (i = 0; i < x->master_key_length; i++) { + if (BIO_printf(bp, "%02X", x->master_key[i]) <= 0) + goto err; + } + + if (x->tlsext_tick_lifetime_hint > 0) { + if (BIO_printf(bp, + "\n TLS session ticket lifetime hint: %u (seconds)", + x->tlsext_tick_lifetime_hint) <= 0) + goto err; + } + + if (x->tlsext_tick != NULL) { + if (BIO_puts(bp, "\n TLS session ticket:\n") <= 0) + goto err; + if (BIO_dump_indent(bp, x->tlsext_tick, x->tlsext_ticklen, + 4) <= 0) + goto err; + } + + if (x->time != 0) { + if (BIO_printf(bp, "\n Start Time: %lld", + (long long)x->time) <= 0) + goto err; + } + + if (x->timeout != 0) { + if (BIO_printf(bp, "\n Timeout : %ld (sec)", + x->timeout) <= 0) + goto err; + } + + if (BIO_puts(bp, "\n") <= 0) + goto err; + + if (BIO_printf(bp, " Verify return code: %ld (%s)\n", + x->verify_result, + X509_verify_cert_error_string(x->verify_result)) <= 0) + goto err; + + ret = 1; + err: + return ret; +} +LSSL_ALIAS(SSL_SESSION_print); diff --git a/ssl/ssl_versions.c b/ssl/ssl_versions.c new file mode 100644 index 0000000..8273546 --- /dev/null +++ b/ssl/ssl_versions.c @@ -0,0 +1,373 @@ +/* $OpenBSD: ssl_versions.c,v 1.27 2023/07/02 17:21:32 beck Exp $ */ +/* + * Copyright (c) 2016, 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ssl_local.h" + +static uint16_t +ssl_dtls_to_tls_version(uint16_t dtls_ver) +{ + if (dtls_ver == DTLS1_VERSION) + return TLS1_1_VERSION; + if (dtls_ver == DTLS1_2_VERSION) + return TLS1_2_VERSION; + return 0; +} + +static uint16_t +ssl_tls_to_dtls_version(uint16_t tls_ver) +{ + if (tls_ver == TLS1_1_VERSION) + return DTLS1_VERSION; + if (tls_ver == TLS1_2_VERSION) + return DTLS1_2_VERSION; + return 0; +} + +static int +ssl_clamp_tls_version_range(uint16_t *min_ver, uint16_t *max_ver, + uint16_t clamp_min, uint16_t clamp_max) +{ + if (clamp_min > clamp_max || *min_ver > *max_ver) + return 0; + if (clamp_max < *min_ver || clamp_min > *max_ver) + return 0; + + if (*min_ver < clamp_min) + *min_ver = clamp_min; + if (*max_ver > clamp_max) + *max_ver = clamp_max; + + return 1; +} + +int +ssl_version_set_min(const SSL_METHOD *meth, uint16_t proto_ver, + uint16_t max_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver) +{ + uint16_t min_proto, min_version, max_version; + + if (proto_ver == 0) { + *out_tls_ver = meth->min_tls_version; + *out_proto_ver = 0; + return 1; + } + + min_version = proto_ver; + max_version = max_tls_ver; + + if (meth->dtls) { + if ((min_version = ssl_dtls_to_tls_version(proto_ver)) == 0) + return 0; + } + + if (!ssl_clamp_tls_version_range(&min_version, &max_version, + meth->min_tls_version, meth->max_tls_version)) + return 0; + + min_proto = min_version; + if (meth->dtls) { + if ((min_proto = ssl_tls_to_dtls_version(min_version)) == 0) + return 0; + } + *out_tls_ver = min_version; + *out_proto_ver = min_proto; + + return 1; +} + +int +ssl_version_set_max(const SSL_METHOD *meth, uint16_t proto_ver, + uint16_t min_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver) +{ + uint16_t max_proto, min_version, max_version; + + if (proto_ver == 0) { + *out_tls_ver = meth->max_tls_version; + *out_proto_ver = 0; + return 1; + } + + min_version = min_tls_ver; + max_version = proto_ver; + + if (meth->dtls) { + if ((max_version = ssl_dtls_to_tls_version(proto_ver)) == 0) + return 0; + } + + if (!ssl_clamp_tls_version_range(&min_version, &max_version, + meth->min_tls_version, meth->max_tls_version)) + return 0; + + max_proto = max_version; + if (meth->dtls) { + if ((max_proto = ssl_tls_to_dtls_version(max_version)) == 0) + return 0; + } + *out_tls_ver = max_version; + *out_proto_ver = max_proto; + + return 1; +} + +int +ssl_enabled_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver) +{ + uint16_t min_version, max_version; + unsigned long options; + + /* + * The enabled versions have to be a contiguous range, which means we + * cannot enable and disable single versions at our whim, even though + * this is what the OpenSSL flags allow. The historical way this has + * been handled is by making a flag mean that all higher versions + * are disabled, if any version lower than the flag is enabled. + */ + + min_version = 0; + max_version = TLS1_3_VERSION; + options = s->options; + + if (SSL_is_dtls(s)) { + options = 0; + if (s->options & SSL_OP_NO_DTLSv1) + options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; + if (s->options & SSL_OP_NO_DTLSv1_2) + options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2; + } + + if ((options & SSL_OP_NO_TLSv1_2) == 0) + min_version = TLS1_2_VERSION; + else if ((options & SSL_OP_NO_TLSv1_3) == 0) + min_version = TLS1_3_VERSION; + + if ((options & SSL_OP_NO_TLSv1_3) && min_version < TLS1_3_VERSION) + max_version = TLS1_2_VERSION; + if ((options & SSL_OP_NO_TLSv1_2) && min_version < TLS1_2_VERSION) + max_version = 0; + + /* Everything has been disabled... */ + if (min_version == 0 || max_version == 0) + return 0; + + /* Limit to configured version range. */ + if (!ssl_clamp_tls_version_range(&min_version, &max_version, + s->min_tls_version, s->max_tls_version)) + return 0; + + /* QUIC requires a minimum of TLSv1.3. */ + if (SSL_is_quic(s)) { + if (max_version < TLS1_3_VERSION) + return 0; + if (min_version < TLS1_3_VERSION) + min_version = TLS1_3_VERSION; + } + + if (min_ver != NULL) + *min_ver = min_version; + if (max_ver != NULL) + *max_ver = max_version; + + return 1; +} + +int +ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver) +{ + uint16_t min_version, max_version; + + if (!ssl_enabled_tls_version_range(s, &min_version, &max_version)) + return 0; + + /* Limit to the versions supported by this method. */ + if (!ssl_clamp_tls_version_range(&min_version, &max_version, + s->method->min_tls_version, s->method->max_tls_version)) + return 0; + + if (min_ver != NULL) + *min_ver = min_version; + if (max_ver != NULL) + *max_ver = max_version; + + return 1; +} + +uint16_t +ssl_tls_version(uint16_t version) +{ + if (version == TLS1_VERSION || version == TLS1_1_VERSION || + version == TLS1_2_VERSION || version == TLS1_3_VERSION) + return version; + + if (version == DTLS1_VERSION) + return TLS1_1_VERSION; + if (version == DTLS1_2_VERSION) + return TLS1_2_VERSION; + + return 0; +} + +uint16_t +ssl_effective_tls_version(SSL *s) +{ + if (s->s3->hs.negotiated_tls_version > 0) + return s->s3->hs.negotiated_tls_version; + + return s->s3->hs.our_max_tls_version; +} + +int +ssl_max_supported_version(SSL *s, uint16_t *max_ver) +{ + uint16_t max_version; + + *max_ver = 0; + + if (!ssl_supported_tls_version_range(s, NULL, &max_version)) + return 0; + + if (SSL_is_dtls(s)) { + if ((max_version = ssl_tls_to_dtls_version(max_version)) == 0) + return 0; + } + + *max_ver = max_version; + + return 1; +} + +int +ssl_max_legacy_version(SSL *s, uint16_t *max_ver) +{ + uint16_t max_version; + + if ((max_version = s->s3->hs.our_max_tls_version) > TLS1_2_VERSION) + max_version = TLS1_2_VERSION; + + if (SSL_is_dtls(s)) { + if ((max_version = ssl_tls_to_dtls_version(max_version)) == 0) + return 0; + } + + *max_ver = max_version; + + return 1; +} + +int +ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver) +{ + uint16_t min_version, max_version, peer_tls_version, shared_version; + + *max_ver = 0; + peer_tls_version = peer_ver; + + if (SSL_is_dtls(s)) { + if ((peer_ver >> 8) != DTLS1_VERSION_MAJOR) + return 0; + + /* + * Convert the peer version to a TLS version - DTLS versions are + * the 1's complement of TLS version numbers (but not the actual + * protocol version numbers, that would be too sensible). Not to + * mention that DTLSv1.0 is really equivalent to DTLSv1.1. + */ + peer_tls_version = ssl_dtls_to_tls_version(peer_ver); + + /* + * This may be a version that we do not know about, if it is + * newer than DTLS1_2_VERSION (yes, less than is correct due + * to the "clever" versioning scheme), use TLS1_2_VERSION. + */ + if (peer_tls_version == 0) { + if (peer_ver < DTLS1_2_VERSION) + peer_tls_version = TLS1_2_VERSION; + } + } + + if (peer_tls_version >= TLS1_3_VERSION) + shared_version = TLS1_3_VERSION; + else if (peer_tls_version >= TLS1_2_VERSION) + shared_version = TLS1_2_VERSION; + else if (peer_tls_version >= TLS1_1_VERSION) + shared_version = TLS1_1_VERSION; + else if (peer_tls_version >= TLS1_VERSION) + shared_version = TLS1_VERSION; + else + return 0; + + if (!ssl_supported_tls_version_range(s, &min_version, &max_version)) + return 0; + + if (shared_version < min_version) + return 0; + + if (shared_version > max_version) + shared_version = max_version; + + if (SSL_is_dtls(s)) { + /* + * The resulting shared version will by definition be something + * that we know about. Switch back from TLS to DTLS. + */ + shared_version = ssl_tls_to_dtls_version(shared_version); + if (shared_version == 0) + return 0; + } + + if (!ssl_security_version(s, shared_version)) + return 0; + + *max_ver = shared_version; + + return 1; +} + +int +ssl_check_version_from_server(SSL *s, uint16_t server_version) +{ + uint16_t min_tls_version, max_tls_version, server_tls_version; + + /* Ensure that the version selected by the server is valid. */ + + server_tls_version = server_version; + if (SSL_is_dtls(s)) { + server_tls_version = ssl_dtls_to_tls_version(server_version); + if (server_tls_version == 0) + return 0; + } + + if (!ssl_supported_tls_version_range(s, &min_tls_version, + &max_tls_version)) + return 0; + + if (server_tls_version < min_tls_version || + server_tls_version > max_tls_version) + return 0; + + return ssl_security_version(s, server_tls_version); +} + +int +ssl_legacy_stack_version(SSL *s, uint16_t version) +{ + if (SSL_is_dtls(s)) + return version == DTLS1_VERSION || version == DTLS1_2_VERSION; + + return version == TLS1_VERSION || version == TLS1_1_VERSION || + version == TLS1_2_VERSION; +} diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c new file mode 100644 index 0000000..c6140e9 --- /dev/null +++ b/ssl/t1_enc.c @@ -0,0 +1,415 @@ +/* $OpenBSD: t1_enc.c,v 1.157 2022/11/26 16:08:56 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +#include +#include + +#include +#include +#include +#include + +#include "dtls_local.h" +#include "ssl_local.h" + +void +tls1_cleanup_key_block(SSL *s) +{ + tls12_key_block_free(s->s3->hs.tls12.key_block); + s->s3->hs.tls12.key_block = NULL; +} + +/* + * TLS P_hash() data expansion function - see RFC 5246, section 5. + */ +static int +tls1_P_hash(const EVP_MD *md, const unsigned char *secret, size_t secret_len, + const void *seed1, size_t seed1_len, const void *seed2, size_t seed2_len, + const void *seed3, size_t seed3_len, const void *seed4, size_t seed4_len, + const void *seed5, size_t seed5_len, unsigned char *out, size_t out_len) +{ + unsigned char A1[EVP_MAX_MD_SIZE], hmac[EVP_MAX_MD_SIZE]; + size_t A1_len, hmac_len; + EVP_MD_CTX *ctx = NULL; + EVP_PKEY *mac_key = NULL; + int ret = 0; + int chunk; + size_t i; + + chunk = EVP_MD_size(md); + OPENSSL_assert(chunk >= 0); + + if ((ctx = EVP_MD_CTX_new()) == NULL) + goto err; + + mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, secret, secret_len); + if (mac_key == NULL) + goto err; + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) + goto err; + if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len)) + goto err; + if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len)) + goto err; + if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len)) + goto err; + if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len)) + goto err; + if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len)) + goto err; + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) + goto err; + + for (;;) { + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) + goto err; + if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) + goto err; + if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len)) + goto err; + if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len)) + goto err; + if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len)) + goto err; + if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len)) + goto err; + if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len)) + goto err; + if (!EVP_DigestSignFinal(ctx, hmac, &hmac_len)) + goto err; + + if (hmac_len > out_len) + hmac_len = out_len; + + for (i = 0; i < hmac_len; i++) + out[i] ^= hmac[i]; + + out += hmac_len; + out_len -= hmac_len; + + if (out_len == 0) + break; + + if (!EVP_DigestSignInit(ctx, NULL, md, NULL, mac_key)) + goto err; + if (!EVP_DigestSignUpdate(ctx, A1, A1_len)) + goto err; + if (!EVP_DigestSignFinal(ctx, A1, &A1_len)) + goto err; + } + ret = 1; + + err: + EVP_PKEY_free(mac_key); + EVP_MD_CTX_free(ctx); + + explicit_bzero(A1, sizeof(A1)); + explicit_bzero(hmac, sizeof(hmac)); + + return ret; +} + +int +tls1_PRF(SSL *s, const unsigned char *secret, size_t secret_len, + const void *seed1, size_t seed1_len, const void *seed2, size_t seed2_len, + const void *seed3, size_t seed3_len, const void *seed4, size_t seed4_len, + const void *seed5, size_t seed5_len, unsigned char *out, size_t out_len) +{ + const EVP_MD *md; + size_t half_len; + + memset(out, 0, out_len); + + if (!ssl_get_handshake_evp_md(s, &md)) + return (0); + + if (EVP_MD_type(md) == NID_md5_sha1) { + /* + * Partition secret between MD5 and SHA1, then XOR result. + * If the secret length is odd, a one byte overlap is used. + */ + half_len = secret_len - (secret_len / 2); + if (!tls1_P_hash(EVP_md5(), secret, half_len, seed1, seed1_len, + seed2, seed2_len, seed3, seed3_len, seed4, seed4_len, + seed5, seed5_len, out, out_len)) + return (0); + + secret += secret_len - half_len; + if (!tls1_P_hash(EVP_sha1(), secret, half_len, seed1, seed1_len, + seed2, seed2_len, seed3, seed3_len, seed4, seed4_len, + seed5, seed5_len, out, out_len)) + return (0); + + return (1); + } + + if (!tls1_P_hash(md, secret, secret_len, seed1, seed1_len, + seed2, seed2_len, seed3, seed3_len, seed4, seed4_len, + seed5, seed5_len, out, out_len)) + return (0); + + return (1); +} + +int +tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len) +{ + return tls1_PRF(s, + s->session->master_key, s->session->master_key_length, + TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE, + s->s3->server_random, SSL3_RANDOM_SIZE, + s->s3->client_random, SSL3_RANDOM_SIZE, + NULL, 0, NULL, 0, key_block, key_block_len); +} + +static int +tls1_change_cipher_state(SSL *s, int is_write) +{ + CBS mac_key, key, iv; + + /* Use client write keys on client write and server read. */ + if ((!s->server && is_write) || (s->server && !is_write)) { + tls12_key_block_client_write(s->s3->hs.tls12.key_block, + &mac_key, &key, &iv); + } else { + tls12_key_block_server_write(s->s3->hs.tls12.key_block, + &mac_key, &key, &iv); + } + + if (!is_write) { + if (!tls12_record_layer_change_read_cipher_state(s->rl, + &mac_key, &key, &iv)) + goto err; + if (SSL_is_dtls(s)) + dtls1_reset_read_seq_numbers(s); + } else { + if (!tls12_record_layer_change_write_cipher_state(s->rl, + &mac_key, &key, &iv)) + goto err; + } + return (1); + + err: + return (0); +} + +int +tls1_change_read_cipher_state(SSL *s) +{ + return tls1_change_cipher_state(s, 0); +} + +int +tls1_change_write_cipher_state(SSL *s) +{ + return tls1_change_cipher_state(s, 1); +} + +int +tls1_setup_key_block(SSL *s) +{ + struct tls12_key_block *key_block; + int mac_type = NID_undef, mac_secret_size = 0; + const EVP_CIPHER *cipher = NULL; + const EVP_AEAD *aead = NULL; + const EVP_MD *handshake_hash = NULL; + const EVP_MD *mac_hash = NULL; + int ret = 0; + + /* + * XXX - callers should be changed so that they only call this + * function once. + */ + if (s->s3->hs.tls12.key_block != NULL) + return (1); + + if (s->session->cipher && + (s->session->cipher->algorithm_mac & SSL_AEAD)) { + if (!ssl_cipher_get_evp_aead(s->session, &aead)) { + SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return (0); + } + } else { + /* XXX - mac_type and mac_secret_size are now unused. */ + if (!ssl_cipher_get_evp(s->session, &cipher, &mac_hash, + &mac_type, &mac_secret_size)) { + SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); + return (0); + } + } + + if (!ssl_get_handshake_evp_md(s, &handshake_hash)) + return (0); + + tls12_record_layer_set_aead(s->rl, aead); + tls12_record_layer_set_cipher_hash(s->rl, cipher, + handshake_hash, mac_hash); + + if ((key_block = tls12_key_block_new()) == NULL) + goto err; + if (!tls12_key_block_generate(key_block, s, aead, cipher, mac_hash)) + goto err; + + s->s3->hs.tls12.key_block = key_block; + key_block = NULL; + + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) && + s->method->version <= TLS1_VERSION) { + /* + * Enable vulnerability countermeasure for CBC ciphers with + * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) + */ + s->s3->need_empty_fragments = 1; + + if (s->session->cipher != NULL) { + if (s->session->cipher->algorithm_enc == SSL_eNULL) + s->s3->need_empty_fragments = 0; + +#ifndef OPENSSL_NO_RC4 + if (s->session->cipher->algorithm_enc == SSL_RC4) + s->s3->need_empty_fragments = 0; +#endif + } + } + + ret = 1; + + err: + tls12_key_block_free(key_block); + + return (ret); +} diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c new file mode 100644 index 0000000..85d5eaa --- /dev/null +++ b/ssl/t1_lib.c @@ -0,0 +1,1132 @@ +/* $OpenBSD: t1_lib.c,v 1.197 2022/11/26 16:08:56 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" + +static int tls_decrypt_ticket(SSL *s, CBS *ticket, int *alert, + SSL_SESSION **psess); + +int +tls1_new(SSL *s) +{ + if (!ssl3_new(s)) + return (0); + s->method->ssl_clear(s); + return (1); +} + +void +tls1_free(SSL *s) +{ + if (s == NULL) + return; + + free(s->tlsext_session_ticket); + ssl3_free(s); +} + +void +tls1_clear(SSL *s) +{ + ssl3_clear(s); + s->version = s->method->version; +} + +struct supported_group { + int nid; + int bits; +}; + +/* + * Supported groups (formerly known as named curves) + * https://www.iana.org/assignments/tls-parameters/#tls-parameters-8 + */ +static const struct supported_group nid_list[] = { + [1] = { + .nid = NID_sect163k1, + .bits = 80, + }, + [2] = { + .nid = NID_sect163r1, + .bits = 80, + }, + [3] = { + .nid = NID_sect163r2, + .bits = 80, + }, + [4] = { + .nid = NID_sect193r1, + .bits = 80, + }, + [5] = { + .nid = NID_sect193r2, + .bits = 80, + }, + [6] = { + .nid = NID_sect233k1, + .bits = 112, + }, + [7] = { + .nid = NID_sect233r1, + .bits = 112, + }, + [8] = { + .nid = NID_sect239k1, + .bits = 112, + }, + [9] = { + .nid = NID_sect283k1, + .bits = 128, + }, + [10] = { + .nid = NID_sect283r1, + .bits = 128, + }, + [11] = { + .nid = NID_sect409k1, + .bits = 192, + }, + [12] = { + .nid = NID_sect409r1, + .bits = 192, + }, + [13] = { + .nid = NID_sect571k1, + .bits = 256, + }, + [14] = { + .nid = NID_sect571r1, + .bits = 256, + }, + [15] = { + .nid = NID_secp160k1, + .bits = 80, + }, + [16] = { + .nid = NID_secp160r1, + .bits = 80, + }, + [17] = { + .nid = NID_secp160r2, + .bits = 80, + }, + [18] = { + .nid = NID_secp192k1, + .bits = 80, + }, + [19] = { + .nid = NID_X9_62_prime192v1, /* aka secp192r1 */ + .bits = 80, + }, + [20] = { + .nid = NID_secp224k1, + .bits = 112, + }, + [21] = { + .nid = NID_secp224r1, + .bits = 112, + }, + [22] = { + .nid = NID_secp256k1, + .bits = 128, + }, + [23] = { + .nid = NID_X9_62_prime256v1, /* aka secp256r1 */ + .bits = 128, + }, + [24] = { + .nid = NID_secp384r1, + .bits = 192, + }, + [25] = { + .nid = NID_secp521r1, + .bits = 256, + }, + [26] = { + .nid = NID_brainpoolP256r1, + .bits = 128, + }, + [27] = { + .nid = NID_brainpoolP384r1, + .bits = 192, + }, + [28] = { + .nid = NID_brainpoolP512r1, + .bits = 256, + }, + [29] = { + .nid = NID_X25519, + .bits = 128, + }, +}; + +#define NID_LIST_LEN (sizeof(nid_list) / sizeof(nid_list[0])) + +#if 0 +static const uint8_t ecformats_list[] = { + TLSEXT_ECPOINTFORMAT_uncompressed, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 +}; +#endif + +static const uint8_t ecformats_default[] = { + TLSEXT_ECPOINTFORMAT_uncompressed, +}; + +#if 0 +static const uint16_t ecgroups_list[] = { + 29, /* X25519 (29) */ + 14, /* sect571r1 (14) */ + 13, /* sect571k1 (13) */ + 25, /* secp521r1 (25) */ + 28, /* brainpoolP512r1 (28) */ + 11, /* sect409k1 (11) */ + 12, /* sect409r1 (12) */ + 27, /* brainpoolP384r1 (27) */ + 24, /* secp384r1 (24) */ + 9, /* sect283k1 (9) */ + 10, /* sect283r1 (10) */ + 26, /* brainpoolP256r1 (26) */ + 22, /* secp256k1 (22) */ + 23, /* secp256r1 (23) */ + 8, /* sect239k1 (8) */ + 6, /* sect233k1 (6) */ + 7, /* sect233r1 (7) */ + 20, /* secp224k1 (20) */ + 21, /* secp224r1 (21) */ + 4, /* sect193r1 (4) */ + 5, /* sect193r2 (5) */ + 18, /* secp192k1 (18) */ + 19, /* secp192r1 (19) */ + 1, /* sect163k1 (1) */ + 2, /* sect163r1 (2) */ + 3, /* sect163r2 (3) */ + 15, /* secp160k1 (15) */ + 16, /* secp160r1 (16) */ + 17, /* secp160r2 (17) */ +}; +#endif + +static const uint16_t ecgroups_client_default[] = { + 29, /* X25519 (29) */ + 23, /* secp256r1 (23) */ + 24, /* secp384r1 (24) */ + 25, /* secp521r1 (25) */ +}; + +static const uint16_t ecgroups_server_default[] = { + 29, /* X25519 (29) */ + 23, /* secp256r1 (23) */ + 24, /* secp384r1 (24) */ +}; + +int +tls1_ec_group_id2nid(uint16_t group_id, int *out_nid) +{ + int nid; + + if (group_id >= NID_LIST_LEN) + return 0; + + if ((nid = nid_list[group_id].nid) == 0) + return 0; + + *out_nid = nid; + + return 1; +} + +int +tls1_ec_group_id2bits(uint16_t group_id, int *out_bits) +{ + int bits; + + if (group_id >= NID_LIST_LEN) + return 0; + + if ((bits = nid_list[group_id].bits) == 0) + return 0; + + *out_bits = bits; + + return 1; +} + +int +tls1_ec_nid2group_id(int nid, uint16_t *out_group_id) +{ + uint16_t group_id; + + if (nid == 0) + return 0; + + for (group_id = 0; group_id < NID_LIST_LEN; group_id++) { + if (nid_list[group_id].nid == nid) { + *out_group_id = group_id; + return 1; + } + } + + return 0; +} + +/* + * Return the appropriate format list. If client_formats is non-zero, return + * the client/session formats. Otherwise return the custom format list if one + * exists, or the default formats if a custom list has not been specified. + */ +void +tls1_get_formatlist(const SSL *s, int client_formats, const uint8_t **pformats, + size_t *pformatslen) +{ + if (client_formats != 0) { + *pformats = s->session->tlsext_ecpointformatlist; + *pformatslen = s->session->tlsext_ecpointformatlist_length; + return; + } + + *pformats = s->tlsext_ecpointformatlist; + *pformatslen = s->tlsext_ecpointformatlist_length; + if (*pformats == NULL) { + *pformats = ecformats_default; + *pformatslen = sizeof(ecformats_default); + } +} + +/* + * Return the appropriate group list. If client_groups is non-zero, return + * the client/session groups. Otherwise return the custom group list if one + * exists, or the default groups if a custom list has not been specified. + */ +void +tls1_get_group_list(const SSL *s, int client_groups, const uint16_t **pgroups, + size_t *pgroupslen) +{ + if (client_groups != 0) { + *pgroups = s->session->tlsext_supportedgroups; + *pgroupslen = s->session->tlsext_supportedgroups_length; + return; + } + + *pgroups = s->tlsext_supportedgroups; + *pgroupslen = s->tlsext_supportedgroups_length; + if (*pgroups != NULL) + return; + + if (!s->server) { + *pgroups = ecgroups_client_default; + *pgroupslen = sizeof(ecgroups_client_default) / 2; + } else { + *pgroups = ecgroups_server_default; + *pgroupslen = sizeof(ecgroups_server_default) / 2; + } +} + +static int +tls1_get_group_lists(const SSL *ssl, const uint16_t **pref, size_t *preflen, + const uint16_t **supp, size_t *supplen) +{ + unsigned long server_pref; + + /* Cannot do anything on the client side. */ + if (!ssl->server) + return 0; + + server_pref = (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE); + tls1_get_group_list(ssl, (server_pref == 0), pref, preflen); + tls1_get_group_list(ssl, (server_pref != 0), supp, supplen); + + return 1; +} + +static int +tls1_group_id_present(uint16_t group_id, const uint16_t *list, size_t list_len) +{ + size_t i; + + for (i = 0; i < list_len; i++) { + if (group_id == list[i]) + return 1; + } + + return 0; +} + +int +tls1_count_shared_groups(const SSL *ssl, size_t *out_count) +{ + size_t count, preflen, supplen, i; + const uint16_t *pref, *supp; + + if (!tls1_get_group_lists(ssl, &pref, &preflen, &supp, &supplen)) + return 0; + + count = 0; + for (i = 0; i < preflen; i++) { + if (!tls1_group_id_present(pref[i], supp, supplen)) + continue; + + if (!ssl_security_shared_group(ssl, pref[i])) + continue; + + count++; + } + + *out_count = count; + + return 1; +} + +static int +tls1_group_by_index(const SSL *ssl, size_t n, int *out_nid, + int (*ssl_security_fn)(const SSL *, uint16_t)) +{ + size_t count, preflen, supplen, i; + const uint16_t *pref, *supp; + + if (!tls1_get_group_lists(ssl, &pref, &preflen, &supp, &supplen)) + return 0; + + count = 0; + for (i = 0; i < preflen; i++) { + if (!tls1_group_id_present(pref[i], supp, supplen)) + continue; + + if (!ssl_security_fn(ssl, pref[i])) + continue; + + if (count++ == n) + return tls1_ec_group_id2nid(pref[i], out_nid); + } + + return 0; +} + +int +tls1_get_shared_group_by_index(const SSL *ssl, size_t index, int *out_nid) +{ + return tls1_group_by_index(ssl, index, out_nid, + ssl_security_shared_group); +} + +int +tls1_get_supported_group(const SSL *ssl, int *out_nid) +{ + return tls1_group_by_index(ssl, 0, out_nid, + ssl_security_supported_group); +} + +int +tls1_set_groups(uint16_t **out_group_ids, size_t *out_group_ids_len, + const int *groups, size_t ngroups) +{ + uint16_t *group_ids; + size_t i; + + if ((group_ids = calloc(ngroups, sizeof(uint16_t))) == NULL) + return 0; + + for (i = 0; i < ngroups; i++) { + if (!tls1_ec_nid2group_id(groups[i], &group_ids[i])) { + free(group_ids); + return 0; + } + } + + free(*out_group_ids); + *out_group_ids = group_ids; + *out_group_ids_len = ngroups; + + return 1; +} + +int +tls1_set_group_list(uint16_t **out_group_ids, size_t *out_group_ids_len, + const char *groups) +{ + uint16_t *new_group_ids, *group_ids = NULL; + size_t ngroups = 0; + char *gs, *p, *q; + int nid; + + if ((gs = strdup(groups)) == NULL) + return 0; + + q = gs; + while ((p = strsep(&q, ":")) != NULL) { + nid = OBJ_sn2nid(p); + if (nid == NID_undef) + nid = OBJ_ln2nid(p); + if (nid == NID_undef) + nid = EC_curve_nist2nid(p); + if (nid == NID_undef) + goto err; + + if ((new_group_ids = reallocarray(group_ids, ngroups + 1, + sizeof(uint16_t))) == NULL) + goto err; + group_ids = new_group_ids; + + if (!tls1_ec_nid2group_id(nid, &group_ids[ngroups])) + goto err; + + ngroups++; + } + + free(gs); + free(*out_group_ids); + *out_group_ids = group_ids; + *out_group_ids_len = ngroups; + + return 1; + + err: + free(gs); + free(group_ids); + + return 0; +} + +/* Check that a group is one of our preferences. */ +int +tls1_check_group(SSL *s, uint16_t group_id) +{ + const uint16_t *groups; + size_t groupslen, i; + + tls1_get_group_list(s, 0, &groups, &groupslen); + + for (i = 0; i < groupslen; i++) { + if (!ssl_security_supported_group(s, groups[i])) + continue; + if (groups[i] == group_id) + return 1; + } + return 0; +} + +/* For an EC key set TLS ID and required compression based on parameters. */ +static int +tls1_set_ec_id(uint16_t *group_id, uint8_t *comp_id, EC_KEY *ec) +{ + const EC_GROUP *grp; + const EC_METHOD *meth; + int prime_field; + int nid; + + if (ec == NULL) + return (0); + + /* Determine whether the group is defined over a prime field. */ + if ((grp = EC_KEY_get0_group(ec)) == NULL) + return (0); + if ((meth = EC_GROUP_method_of(grp)) == NULL) + return (0); + prime_field = (EC_METHOD_get_field_type(meth) == NID_X9_62_prime_field); + + /* Determine group ID. */ + nid = EC_GROUP_get_curve_name(grp); + /* If we have an ID set it, otherwise set arbitrary explicit group. */ + if (!tls1_ec_nid2group_id(nid, group_id)) + *group_id = prime_field ? 0xff01 : 0xff02; + + if (comp_id == NULL) + return (1); + + /* Specify the compression identifier. */ + if (EC_KEY_get0_public_key(ec) == NULL) + return (0); + *comp_id = TLSEXT_ECPOINTFORMAT_uncompressed; + if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) { + *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + if (prime_field) + *comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + } + + return (1); +} + +/* Check that an EC key is compatible with extensions. */ +static int +tls1_check_ec_key(SSL *s, const uint16_t *group_id, const uint8_t *comp_id) +{ + size_t groupslen, formatslen, i; + const uint16_t *groups; + const uint8_t *formats; + + /* + * Check point formats extension if present, otherwise everything + * is supported (see RFC4492). + */ + tls1_get_formatlist(s, 1, &formats, &formatslen); + if (comp_id != NULL && formats != NULL) { + for (i = 0; i < formatslen; i++) { + if (formats[i] == *comp_id) + break; + } + if (i == formatslen) + return (0); + } + + /* + * Check group list if present, otherwise everything is supported. + */ + tls1_get_group_list(s, 1, &groups, &groupslen); + if (group_id != NULL && groups != NULL) { + for (i = 0; i < groupslen; i++) { + if (groups[i] == *group_id) + break; + } + if (i == groupslen) + return (0); + } + + return (1); +} + +/* Check EC server key is compatible with client extensions. */ +int +tls1_check_ec_server_key(SSL *s) +{ + SSL_CERT_PKEY *cpk = s->cert->pkeys + SSL_PKEY_ECC; + uint16_t group_id; + uint8_t comp_id; + EC_KEY *eckey; + EVP_PKEY *pkey; + + if (cpk->x509 == NULL || cpk->privatekey == NULL) + return (0); + if ((pkey = X509_get0_pubkey(cpk->x509)) == NULL) + return (0); + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) + return (0); + if (!tls1_set_ec_id(&group_id, &comp_id, eckey)) + return (0); + + return tls1_check_ec_key(s, &group_id, &comp_id); +} + +int +ssl_check_clienthello_tlsext_early(SSL *s) +{ + int ret = SSL_TLSEXT_ERR_NOACK; + int al = SSL_AD_UNRECOGNIZED_NAME; + + /* The handling of the ECPointFormats extension is done elsewhere, namely in + * ssl3_choose_cipher in s3_lib.c. + */ + /* The handling of the EllipticCurves extension is done elsewhere, namely in + * ssl3_choose_cipher in s3_lib.c. + */ + + if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) + ret = s->ctx->tlsext_servername_callback(s, &al, + s->ctx->tlsext_servername_arg); + else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) + ret = s->initial_ctx->tlsext_servername_callback(s, &al, + s->initial_ctx->tlsext_servername_arg); + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; + case SSL_TLSEXT_ERR_NOACK: + default: + return 1; + } +} + +int +ssl_check_clienthello_tlsext_late(SSL *s) +{ + int ret = SSL_TLSEXT_ERR_OK; + int al = 0; /* XXX gcc3 */ + + /* If status request then ask callback what to do. + * Note: this must be called after servername callbacks in case + * the certificate has changed, and must be called after the cipher + * has been chosen because this may influence which certificate is sent + */ + if ((s->tlsext_status_type != -1) && + s->ctx && s->ctx->tlsext_status_cb) { + int r; + SSL_CERT_PKEY *certpkey; + certpkey = ssl_get_server_send_pkey(s); + /* If no certificate can't return certificate status */ + if (certpkey == NULL) { + s->tlsext_status_expected = 0; + return 1; + } + /* Set current certificate to one we will use so + * SSL_get_certificate et al can pick it up. + */ + s->cert->key = certpkey; + r = s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg); + switch (r) { + /* We don't want to send a status request response */ + case SSL_TLSEXT_ERR_NOACK: + s->tlsext_status_expected = 0; + break; + /* status request response should be sent */ + case SSL_TLSEXT_ERR_OK: + if (s->tlsext_ocsp_resp) + s->tlsext_status_expected = 1; + else + s->tlsext_status_expected = 0; + break; + /* something bad happened */ + case SSL_TLSEXT_ERR_ALERT_FATAL: + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + al = SSL_AD_INTERNAL_ERROR; + goto err; + } + } else + s->tlsext_status_expected = 0; + + err: + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; + default: + return 1; + } +} + +int +ssl_check_serverhello_tlsext(SSL *s) +{ + int ret = SSL_TLSEXT_ERR_NOACK; + int al = SSL_AD_UNRECOGNIZED_NAME; + + ret = SSL_TLSEXT_ERR_OK; + + if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0) + ret = s->ctx->tlsext_servername_callback(s, &al, + s->ctx->tlsext_servername_arg); + else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0) + ret = s->initial_ctx->tlsext_servername_callback(s, &al, + s->initial_ctx->tlsext_servername_arg); + + /* If we've requested certificate status and we wont get one + * tell the callback + */ + if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected) && + s->ctx && s->ctx->tlsext_status_cb) { + int r; + + free(s->tlsext_ocsp_resp); + s->tlsext_ocsp_resp = NULL; + s->tlsext_ocsp_resp_len = 0; + + r = s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg); + if (r == 0) { + al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE; + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + } + if (r < 0) { + al = SSL_AD_INTERNAL_ERROR; + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + } + } + + switch (ret) { + case SSL_TLSEXT_ERR_ALERT_FATAL: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + return -1; + case SSL_TLSEXT_ERR_ALERT_WARNING: + ssl3_send_alert(s, SSL3_AL_WARNING, al); + return 1; + case SSL_TLSEXT_ERR_NOACK: + default: + return 1; + } +} + +/* Since the server cache lookup is done early on in the processing of the + * ClientHello, and other operations depend on the result, we need to handle + * any TLS session ticket extension at the same time. + * + * ext_block: a CBS for the ClientHello extensions block. + * ret: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + * + * If s->tls_session_secret_cb is set then we are expecting a pre-shared key + * ciphersuite, in which case we have no use for session tickets and one will + * never be decrypted, nor will s->tlsext_ticket_expected be set to 1. + * + * Returns: + * TLS1_TICKET_FATAL_ERROR: error from parsing or decrypting the ticket. + * TLS1_TICKET_NONE: no ticket was found (or was ignored, based on settings). + * TLS1_TICKET_EMPTY: a zero length extension was found, indicating that the + * client supports session tickets but doesn't currently have one to offer. + * TLS1_TICKET_NOT_DECRYPTED: either s->tls_session_secret_cb was + * set, or a ticket was offered but couldn't be decrypted because of a + * non-fatal error. + * TLS1_TICKET_DECRYPTED: a ticket was successfully decrypted and *ret was set. + * + * Side effects: + * Sets s->tlsext_ticket_expected to 1 if the server will have to issue + * a new session ticket to the client because the client indicated support + * (and s->tls_session_secret_cb is NULL) but the client either doesn't have + * a session ticket or we couldn't use the one it gave us, or if + * s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket. + * Otherwise, s->tlsext_ticket_expected is set to 0. + */ +int +tls1_process_ticket(SSL *s, CBS *ext_block, int *alert, SSL_SESSION **ret) +{ + CBS extensions, ext_data; + uint16_t ext_type = 0; + + s->tlsext_ticket_expected = 0; + *ret = NULL; + + /* + * If tickets disabled behave as if no ticket present to permit stateful + * resumption. + */ + if (SSL_get_options(s) & SSL_OP_NO_TICKET) + return TLS1_TICKET_NONE; + + /* + * An empty extensions block is valid, but obviously does not contain + * a session ticket. + */ + if (CBS_len(ext_block) == 0) + return TLS1_TICKET_NONE; + + if (!CBS_get_u16_length_prefixed(ext_block, &extensions)) { + *alert = SSL_AD_DECODE_ERROR; + return TLS1_TICKET_FATAL_ERROR; + } + + while (CBS_len(&extensions) > 0) { + if (!CBS_get_u16(&extensions, &ext_type) || + !CBS_get_u16_length_prefixed(&extensions, &ext_data)) { + *alert = SSL_AD_DECODE_ERROR; + return TLS1_TICKET_FATAL_ERROR; + } + + if (ext_type == TLSEXT_TYPE_session_ticket) + break; + } + + if (ext_type != TLSEXT_TYPE_session_ticket) + return TLS1_TICKET_NONE; + + if (CBS_len(&ext_data) == 0) { + /* + * The client will accept a ticket but does not currently + * have one. + */ + s->tlsext_ticket_expected = 1; + return TLS1_TICKET_EMPTY; + } + + if (s->tls_session_secret_cb != NULL) { + /* + * Indicate that the ticket could not be decrypted rather than + * generating the session from ticket now, trigger abbreviated + * handshake based on external mechanism to calculate the master + * secret later. + */ + return TLS1_TICKET_NOT_DECRYPTED; + } + + return tls_decrypt_ticket(s, &ext_data, alert, ret); +} + +/* tls_decrypt_ticket attempts to decrypt a session ticket. + * + * ticket: a CBS containing the body of the session ticket extension. + * psess: (output) on return, if a ticket was decrypted, then this is set to + * point to the resulting session. + * + * Returns: + * TLS1_TICKET_FATAL_ERROR: error from parsing or decrypting the ticket. + * TLS1_TICKET_NOT_DECRYPTED: the ticket couldn't be decrypted. + * TLS1_TICKET_DECRYPTED: a ticket was decrypted and *psess was set. + */ +static int +tls_decrypt_ticket(SSL *s, CBS *ticket, int *alert, SSL_SESSION **psess) +{ + CBS ticket_name, ticket_iv, ticket_encdata, ticket_hmac; + SSL_SESSION *sess = NULL; + unsigned char *sdec = NULL; + size_t sdec_len = 0; + const unsigned char *p; + unsigned char hmac[EVP_MAX_MD_SIZE]; + HMAC_CTX *hctx = NULL; + EVP_CIPHER_CTX *cctx = NULL; + SSL_CTX *tctx = s->initial_ctx; + int slen, hlen; + int alert_desc = SSL_AD_INTERNAL_ERROR; + int ret = TLS1_TICKET_FATAL_ERROR; + + *psess = NULL; + + if (!CBS_get_bytes(ticket, &ticket_name, 16)) + goto derr; + + /* + * Initialize session ticket encryption and HMAC contexts. + */ + if ((cctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if ((hctx = HMAC_CTX_new()) == NULL) + goto err; + + if (tctx->tlsext_ticket_key_cb != NULL) { + int rv; + + /* + * The API guarantees EVP_MAX_IV_LENGTH bytes of space for + * the iv to tlsext_ticket_key_cb(). Since the total space + * required for a session cookie is never less than this, + * this check isn't too strict. The exact check comes later. + */ + if (CBS_len(ticket) < EVP_MAX_IV_LENGTH) + goto derr; + + if ((rv = tctx->tlsext_ticket_key_cb(s, + (unsigned char *)CBS_data(&ticket_name), + (unsigned char *)CBS_data(ticket), cctx, hctx, 0)) < 0) + goto err; + if (rv == 0) + goto derr; + if (rv == 2) { + /* Renew ticket. */ + s->tlsext_ticket_expected = 1; + } + + /* + * Now that the cipher context is initialised, we can extract + * the IV since its length is known. + */ + if (!CBS_get_bytes(ticket, &ticket_iv, + EVP_CIPHER_CTX_iv_length(cctx))) + goto derr; + } else { + /* Check that the key name matches. */ + if (!CBS_mem_equal(&ticket_name, + tctx->tlsext_tick_key_name, + sizeof(tctx->tlsext_tick_key_name))) + goto derr; + if (!CBS_get_bytes(ticket, &ticket_iv, + EVP_CIPHER_iv_length(EVP_aes_128_cbc()))) + goto derr; + if (!EVP_DecryptInit_ex(cctx, EVP_aes_128_cbc(), NULL, + tctx->tlsext_tick_aes_key, CBS_data(&ticket_iv))) + goto err; + if (!HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key, + sizeof(tctx->tlsext_tick_hmac_key), EVP_sha256(), + NULL)) + goto err; + } + + /* + * Attempt to process session ticket. + */ + + if ((hlen = HMAC_size(hctx)) < 0) + goto err; + + if (hlen > CBS_len(ticket)) + goto derr; + if (!CBS_get_bytes(ticket, &ticket_encdata, CBS_len(ticket) - hlen)) + goto derr; + if (!CBS_get_bytes(ticket, &ticket_hmac, hlen)) + goto derr; + if (CBS_len(ticket) != 0) { + alert_desc = SSL_AD_DECODE_ERROR; + goto err; + } + + /* Check HMAC of encrypted ticket. */ + if (HMAC_Update(hctx, CBS_data(&ticket_name), + CBS_len(&ticket_name)) <= 0) + goto err; + if (HMAC_Update(hctx, CBS_data(&ticket_iv), + CBS_len(&ticket_iv)) <= 0) + goto err; + if (HMAC_Update(hctx, CBS_data(&ticket_encdata), + CBS_len(&ticket_encdata)) <= 0) + goto err; + if (HMAC_Final(hctx, hmac, &hlen) <= 0) + goto err; + + if (!CBS_mem_equal(&ticket_hmac, hmac, hlen)) + goto derr; + + /* Attempt to decrypt session data. */ + sdec_len = CBS_len(&ticket_encdata); + if ((sdec = calloc(1, sdec_len)) == NULL) + goto err; + if (EVP_DecryptUpdate(cctx, sdec, &slen, CBS_data(&ticket_encdata), + CBS_len(&ticket_encdata)) <= 0) + goto derr; + if (EVP_DecryptFinal_ex(cctx, sdec + slen, &hlen) <= 0) + goto derr; + + slen += hlen; + + /* + * For session parse failures, indicate that we need to send a new + * ticket. + */ + p = sdec; + if ((sess = d2i_SSL_SESSION(NULL, &p, slen)) == NULL) + goto derr; + *psess = sess; + sess = NULL; + + ret = TLS1_TICKET_DECRYPTED; + goto done; + + derr: + ERR_clear_error(); + s->tlsext_ticket_expected = 1; + ret = TLS1_TICKET_NOT_DECRYPTED; + goto done; + + err: + *alert = alert_desc; + ret = TLS1_TICKET_FATAL_ERROR; + goto done; + + done: + freezero(sdec, sdec_len); + EVP_CIPHER_CTX_free(cctx); + HMAC_CTX_free(hctx); + SSL_SESSION_free(sess); + + return ret; +} diff --git a/ssl/tls12_internal.h b/ssl/tls12_internal.h new file mode 100644 index 0000000..d416b2e --- /dev/null +++ b/ssl/tls12_internal.h @@ -0,0 +1,29 @@ +/* $OpenBSD: tls12_internal.h,v 1.1 2022/11/07 11:58:45 jsing Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS12_INTERNAL_H +#define HEADER_TLS12_INTERNAL_H + +__BEGIN_HIDDEN_DECLS + +int tls12_exporter(SSL *s, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, int use_context, + uint8_t *out, size_t out_len); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls12_key_schedule.c b/ssl/tls12_key_schedule.c new file mode 100644 index 0000000..6d714c1 --- /dev/null +++ b/ssl/tls12_key_schedule.c @@ -0,0 +1,295 @@ +/* $OpenBSD: tls12_key_schedule.c,v 1.3 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "tls12_internal.h" + +struct tls12_key_block { + CBS client_write_mac_key; + CBS server_write_mac_key; + CBS client_write_key; + CBS server_write_key; + CBS client_write_iv; + CBS server_write_iv; + + uint8_t *key_block; + size_t key_block_len; +}; + +struct tls12_key_block * +tls12_key_block_new(void) +{ + return calloc(1, sizeof(struct tls12_key_block)); +} + +static void +tls12_key_block_clear(struct tls12_key_block *kb) +{ + CBS_init(&kb->client_write_mac_key, NULL, 0); + CBS_init(&kb->server_write_mac_key, NULL, 0); + CBS_init(&kb->client_write_key, NULL, 0); + CBS_init(&kb->server_write_key, NULL, 0); + CBS_init(&kb->client_write_iv, NULL, 0); + CBS_init(&kb->server_write_iv, NULL, 0); + + freezero(kb->key_block, kb->key_block_len); + kb->key_block = NULL; + kb->key_block_len = 0; +} + +void +tls12_key_block_free(struct tls12_key_block *kb) +{ + if (kb == NULL) + return; + + tls12_key_block_clear(kb); + + freezero(kb, sizeof(struct tls12_key_block)); +} + +void +tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key, + CBS *key, CBS *iv) +{ + CBS_dup(&kb->client_write_mac_key, mac_key); + CBS_dup(&kb->client_write_key, key); + CBS_dup(&kb->client_write_iv, iv); +} + +void +tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key, + CBS *key, CBS *iv) +{ + CBS_dup(&kb->server_write_mac_key, mac_key); + CBS_dup(&kb->server_write_key, key); + CBS_dup(&kb->server_write_iv, iv); +} + +int +tls12_key_block_generate(struct tls12_key_block *kb, SSL *s, + const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash) +{ + size_t mac_key_len = 0, key_len = 0, iv_len = 0; + uint8_t *key_block = NULL; + size_t key_block_len = 0; + CBS cbs; + + /* + * Generate a TLSv1.2 key block and partition into individual secrets, + * as per RFC 5246 section 6.3. + */ + + tls12_key_block_clear(kb); + + /* Must have AEAD or cipher/MAC pair. */ + if (aead == NULL && (cipher == NULL || mac_hash == NULL)) + goto err; + + if (aead != NULL) { + key_len = EVP_AEAD_key_length(aead); + + /* AEAD fixed nonce length. */ + if (aead == EVP_aead_aes_128_gcm() || + aead == EVP_aead_aes_256_gcm()) + iv_len = 4; + else if (aead == EVP_aead_chacha20_poly1305()) + iv_len = 12; + else + goto err; + } else if (cipher != NULL && mac_hash != NULL) { + /* + * A negative integer return value will be detected via the + * EVP_MAX_* checks against the size_t variables below. + */ + mac_key_len = EVP_MD_size(mac_hash); + key_len = EVP_CIPHER_key_length(cipher); + iv_len = EVP_CIPHER_iv_length(cipher); + + /* Special handling for GOST... */ + if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC) + mac_key_len = 32; + } + + if (mac_key_len > EVP_MAX_MD_SIZE) + goto err; + if (key_len > EVP_MAX_KEY_LENGTH) + goto err; + if (iv_len > EVP_MAX_IV_LENGTH) + goto err; + + key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len; + if ((key_block = calloc(1, key_block_len)) == NULL) + goto err; + + if (!tls1_generate_key_block(s, key_block, key_block_len)) + goto err; + + kb->key_block = key_block; + kb->key_block_len = key_block_len; + key_block = NULL; + key_block_len = 0; + + /* Partition key block into individual secrets. */ + CBS_init(&cbs, kb->key_block, kb->key_block_len); + if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len)) + goto err; + if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len)) + goto err; + if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len)) + goto err; + if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len)) + goto err; + if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len)) + goto err; + if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len)) + goto err; + if (CBS_len(&cbs) != 0) + goto err; + + return 1; + + err: + tls12_key_block_clear(kb); + freezero(key_block, key_block_len); + + return 0; +} + +struct tls12_reserved_label { + const char *label; + size_t label_len; +}; + +/* + * RFC 5705 section 6. + */ +static const struct tls12_reserved_label tls12_reserved_labels[] = { + { + .label = TLS_MD_CLIENT_FINISH_CONST, + .label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE, + }, + { + .label = TLS_MD_SERVER_FINISH_CONST, + .label_len = TLS_MD_SERVER_FINISH_CONST_SIZE, + }, + { + .label = TLS_MD_MASTER_SECRET_CONST, + .label_len = TLS_MD_MASTER_SECRET_CONST_SIZE, + }, + { + .label = TLS_MD_KEY_EXPANSION_CONST, + .label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE, + }, + { + .label = NULL, + .label_len = 0, + }, +}; + +int +tls12_exporter(SSL *s, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, int use_context, + uint8_t *out, size_t out_len) +{ + uint8_t *data = NULL; + size_t data_len = 0; + CBB cbb, context; + CBS seed; + size_t i; + int ret = 0; + + /* + * RFC 5705 - Key Material Exporters for TLS. + */ + + memset(&cbb, 0, sizeof(cbb)); + + if (!SSL_is_init_finished(s)) { + SSLerror(s, SSL_R_BAD_STATE); + goto err; + } + + if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) + goto err; + + /* + * Due to exceptional design choices, we need to build a concatenation + * of the label and the seed value, before checking for reserved + * labels. This prevents a reserved label from being split across the + * label and the seed (that includes the client random), which are + * concatenated by the PRF. + */ + if (!CBB_init(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, label, label_len)) + goto err; + if (!CBB_add_bytes(&cbb, s->s3->client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBB_add_bytes(&cbb, s->s3->server_random, SSL3_RANDOM_SIZE)) + goto err; + if (use_context) { + if (!CBB_add_u16_length_prefixed(&cbb, &context)) + goto err; + if (context_value_len > 0) { + if (!CBB_add_bytes(&context, context_value, + context_value_len)) + goto err; + } + } + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + /* + * Ensure that the block (label + seed) does not start with a reserved + * label - in an ideal world we would ensure that the label has an + * explicitly permitted prefix instead, but of course this also got + * messed up by the standards. + */ + for (i = 0; tls12_reserved_labels[i].label != NULL; i++) { + /* XXX - consider adding/using CBS_has_prefix(). */ + if (tls12_reserved_labels[i].label_len > data_len) + goto err; + if (memcmp(data, tls12_reserved_labels[i].label, + tls12_reserved_labels[i].label_len) == 0) { + SSLerror(s, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); + goto err; + } + } + + CBS_init(&seed, data, data_len); + if (!CBS_skip(&seed, label_len)) + goto err; + + if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length, + label, label_len, CBS_data(&seed), CBS_len(&seed), NULL, 0, NULL, 0, + NULL, 0, out, out_len)) + goto err; + + ret = 1; + + err: + freezero(data, data_len); + CBB_cleanup(&cbb); + + return ret; +} diff --git a/ssl/tls12_lib.c b/ssl/tls12_lib.c new file mode 100644 index 0000000..96b3abc --- /dev/null +++ b/ssl/tls12_lib.c @@ -0,0 +1,118 @@ +/* $OpenBSD: tls12_lib.c,v 1.6 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ssl_local.h" + +static int +tls12_finished_verify_data(SSL *s, const char *finished_label, + size_t finished_label_len, uint8_t *verify_data, size_t verify_data_len, + size_t *out_len) +{ + uint8_t transcript_hash[EVP_MAX_MD_SIZE]; + size_t transcript_hash_len; + + *out_len = 0; + + if (s->session->master_key_length == 0) + return 0; + + if (verify_data_len < TLS1_FINISH_MAC_LENGTH) + return 0; + + if (!tls1_transcript_hash_value(s, transcript_hash, + sizeof(transcript_hash), &transcript_hash_len)) + return 0; + + if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length, + finished_label, finished_label_len, transcript_hash, + transcript_hash_len, NULL, 0, NULL, 0, NULL, 0, verify_data, + TLS1_FINISH_MAC_LENGTH)) + return 0; + + *out_len = TLS1_FINISH_MAC_LENGTH; + + return 1; +} + +static int +tls12_client_finished_verify_data(SSL *s, uint8_t *verify_data, + size_t verify_data_len, size_t *out_len) +{ + return tls12_finished_verify_data(s, TLS_MD_CLIENT_FINISH_CONST, + TLS_MD_CLIENT_FINISH_CONST_SIZE, verify_data, verify_data_len, + out_len); +} + +static int +tls12_server_finished_verify_data(SSL *s, uint8_t *verify_data, + size_t verify_data_len, size_t *out_len) +{ + return tls12_finished_verify_data(s, TLS_MD_SERVER_FINISH_CONST, + TLS_MD_SERVER_FINISH_CONST_SIZE, verify_data, verify_data_len, + out_len); +} + +int +tls12_derive_finished(SSL *s) +{ + if (!s->server) { + return tls12_client_finished_verify_data(s, + s->s3->hs.finished, sizeof(s->s3->hs.finished), + &s->s3->hs.finished_len); + } else { + return tls12_server_finished_verify_data(s, + s->s3->hs.finished, sizeof(s->s3->hs.finished), + &s->s3->hs.finished_len); + } +} + +int +tls12_derive_peer_finished(SSL *s) +{ + if (s->server) { + return tls12_client_finished_verify_data(s, + s->s3->hs.peer_finished, sizeof(s->s3->hs.peer_finished), + &s->s3->hs.peer_finished_len); + } else { + return tls12_server_finished_verify_data(s, + s->s3->hs.peer_finished, sizeof(s->s3->hs.peer_finished), + &s->s3->hs.peer_finished_len); + } +} + +int +tls12_derive_master_secret(SSL *s, uint8_t *premaster_secret, + size_t premaster_secret_len) +{ + s->session->master_key_length = 0; + + if (premaster_secret_len == 0) + return 0; + + CTASSERT(sizeof(s->session->master_key) == SSL_MAX_MASTER_KEY_LENGTH); + + if (!tls1_PRF(s, premaster_secret, premaster_secret_len, + TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, + s->s3->client_random, SSL3_RANDOM_SIZE, NULL, 0, + s->s3->server_random, SSL3_RANDOM_SIZE, NULL, 0, + s->session->master_key, sizeof(s->session->master_key))) + return 0; + + s->session->master_key_length = SSL_MAX_MASTER_KEY_LENGTH; + + return 1; +} diff --git a/ssl/tls12_record_layer.c b/ssl/tls12_record_layer.c new file mode 100644 index 0000000..997026b --- /dev/null +++ b/ssl/tls12_record_layer.c @@ -0,0 +1,1342 @@ +/* $OpenBSD: tls12_record_layer.c,v 1.40 2023/07/08 20:38:23 beck Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "ssl_local.h" + +#define TLS12_RECORD_SEQ_NUM_LEN 8 +#define TLS12_AEAD_FIXED_NONCE_MAX_LEN 12 + +struct tls12_record_protection { + uint16_t epoch; + uint8_t seq_num[TLS12_RECORD_SEQ_NUM_LEN]; + + EVP_AEAD_CTX *aead_ctx; + + uint8_t *aead_nonce; + size_t aead_nonce_len; + + uint8_t *aead_fixed_nonce; + size_t aead_fixed_nonce_len; + + size_t aead_variable_nonce_len; + size_t aead_tag_len; + + int aead_xor_nonces; + int aead_variable_nonce_in_record; + + EVP_CIPHER_CTX *cipher_ctx; + EVP_MD_CTX *hash_ctx; + + int stream_mac; + + uint8_t *mac_key; + size_t mac_key_len; +}; + +static struct tls12_record_protection * +tls12_record_protection_new(void) +{ + return calloc(1, sizeof(struct tls12_record_protection)); +} + +static void +tls12_record_protection_clear(struct tls12_record_protection *rp) +{ + EVP_AEAD_CTX_free(rp->aead_ctx); + + freezero(rp->aead_nonce, rp->aead_nonce_len); + freezero(rp->aead_fixed_nonce, rp->aead_fixed_nonce_len); + + EVP_CIPHER_CTX_free(rp->cipher_ctx); + EVP_MD_CTX_free(rp->hash_ctx); + + freezero(rp->mac_key, rp->mac_key_len); + + memset(rp, 0, sizeof(*rp)); +} + +static void +tls12_record_protection_free(struct tls12_record_protection *rp) +{ + if (rp == NULL) + return; + + tls12_record_protection_clear(rp); + + freezero(rp, sizeof(struct tls12_record_protection)); +} + +static int +tls12_record_protection_engaged(struct tls12_record_protection *rp) +{ + return rp->aead_ctx != NULL || rp->cipher_ctx != NULL; +} + +static int +tls12_record_protection_unused(struct tls12_record_protection *rp) +{ + return rp->aead_ctx == NULL && rp->cipher_ctx == NULL && + rp->hash_ctx == NULL && rp->mac_key == NULL; +} + +static int +tls12_record_protection_eiv_len(struct tls12_record_protection *rp, + size_t *out_eiv_len) +{ + int eiv_len; + + *out_eiv_len = 0; + + if (rp->cipher_ctx == NULL) + return 0; + + eiv_len = 0; + if (EVP_CIPHER_CTX_mode(rp->cipher_ctx) == EVP_CIPH_CBC_MODE) + eiv_len = EVP_CIPHER_CTX_iv_length(rp->cipher_ctx); + if (eiv_len < 0 || eiv_len > EVP_MAX_IV_LENGTH) + return 0; + + *out_eiv_len = eiv_len; + + return 1; +} + +static int +tls12_record_protection_block_size(struct tls12_record_protection *rp, + size_t *out_block_size) +{ + int block_size; + + *out_block_size = 0; + + if (rp->cipher_ctx == NULL) + return 0; + + block_size = EVP_CIPHER_CTX_block_size(rp->cipher_ctx); + if (block_size < 0 || block_size > EVP_MAX_BLOCK_LENGTH) + return 0; + + *out_block_size = block_size; + + return 1; +} + +static int +tls12_record_protection_mac_len(struct tls12_record_protection *rp, + size_t *out_mac_len) +{ + int mac_len; + + *out_mac_len = 0; + + if (rp->hash_ctx == NULL) + return 0; + + mac_len = EVP_MD_CTX_size(rp->hash_ctx); + if (mac_len <= 0 || mac_len > EVP_MAX_MD_SIZE) + return 0; + + *out_mac_len = mac_len; + + return 1; +} + +struct tls12_record_layer { + uint16_t version; + uint16_t initial_epoch; + int dtls; + + uint8_t alert_desc; + + const EVP_AEAD *aead; + const EVP_CIPHER *cipher; + const EVP_MD *handshake_hash; + const EVP_MD *mac_hash; + + /* Pointers to active record protection (memory is not owned). */ + struct tls12_record_protection *read; + struct tls12_record_protection *write; + + struct tls12_record_protection *read_current; + struct tls12_record_protection *write_current; + struct tls12_record_protection *write_previous; +}; + +struct tls12_record_layer * +tls12_record_layer_new(void) +{ + struct tls12_record_layer *rl; + + if ((rl = calloc(1, sizeof(struct tls12_record_layer))) == NULL) + goto err; + if ((rl->read_current = tls12_record_protection_new()) == NULL) + goto err; + if ((rl->write_current = tls12_record_protection_new()) == NULL) + goto err; + + rl->read = rl->read_current; + rl->write = rl->write_current; + + return rl; + + err: + tls12_record_layer_free(rl); + + return NULL; +} + +void +tls12_record_layer_free(struct tls12_record_layer *rl) +{ + if (rl == NULL) + return; + + tls12_record_protection_free(rl->read_current); + tls12_record_protection_free(rl->write_current); + tls12_record_protection_free(rl->write_previous); + + freezero(rl, sizeof(struct tls12_record_layer)); +} + +void +tls12_record_layer_alert(struct tls12_record_layer *rl, uint8_t *alert_desc) +{ + *alert_desc = rl->alert_desc; +} + +int +tls12_record_layer_write_overhead(struct tls12_record_layer *rl, + size_t *overhead) +{ + size_t block_size, eiv_len, mac_len; + + *overhead = 0; + + if (rl->write->aead_ctx != NULL) { + *overhead = rl->write->aead_tag_len; + } else if (rl->write->cipher_ctx != NULL) { + eiv_len = 0; + if (rl->version != TLS1_VERSION) { + if (!tls12_record_protection_eiv_len(rl->write, &eiv_len)) + return 0; + } + if (!tls12_record_protection_block_size(rl->write, &block_size)) + return 0; + if (!tls12_record_protection_mac_len(rl->write, &mac_len)) + return 0; + + *overhead = eiv_len + block_size + mac_len; + } + + return 1; +} + +int +tls12_record_layer_read_protected(struct tls12_record_layer *rl) +{ + return tls12_record_protection_engaged(rl->read); +} + +int +tls12_record_layer_write_protected(struct tls12_record_layer *rl) +{ + return tls12_record_protection_engaged(rl->write); +} + +void +tls12_record_layer_set_aead(struct tls12_record_layer *rl, const EVP_AEAD *aead) +{ + rl->aead = aead; +} + +void +tls12_record_layer_set_cipher_hash(struct tls12_record_layer *rl, + const EVP_CIPHER *cipher, const EVP_MD *handshake_hash, + const EVP_MD *mac_hash) +{ + rl->cipher = cipher; + rl->handshake_hash = handshake_hash; + rl->mac_hash = mac_hash; +} + +void +tls12_record_layer_set_version(struct tls12_record_layer *rl, uint16_t version) +{ + rl->version = version; + rl->dtls = ((version >> 8) == DTLS1_VERSION_MAJOR); +} + +void +tls12_record_layer_set_initial_epoch(struct tls12_record_layer *rl, + uint16_t epoch) +{ + rl->initial_epoch = epoch; +} + +uint16_t +tls12_record_layer_read_epoch(struct tls12_record_layer *rl) +{ + return rl->read->epoch; +} + +uint16_t +tls12_record_layer_write_epoch(struct tls12_record_layer *rl) +{ + return rl->write->epoch; +} + +int +tls12_record_layer_use_write_epoch(struct tls12_record_layer *rl, uint16_t epoch) +{ + if (rl->write->epoch == epoch) + return 1; + + if (rl->write_current->epoch == epoch) { + rl->write = rl->write_current; + return 1; + } + + if (rl->write_previous != NULL && rl->write_previous->epoch == epoch) { + rl->write = rl->write_previous; + return 1; + } + + return 0; +} + +void +tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, uint16_t epoch) +{ + if (rl->write_previous == NULL || rl->write_previous->epoch != epoch) + return; + + rl->write = rl->write_current; + + tls12_record_protection_free(rl->write_previous); + rl->write_previous = NULL; +} + +void +tls12_record_layer_clear_read_state(struct tls12_record_layer *rl) +{ + tls12_record_protection_clear(rl->read); + rl->read->epoch = rl->initial_epoch; +} + +void +tls12_record_layer_clear_write_state(struct tls12_record_layer *rl) +{ + tls12_record_protection_clear(rl->write); + rl->write->epoch = rl->initial_epoch; + + tls12_record_protection_free(rl->write_previous); + rl->write_previous = NULL; +} + +void +tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl) +{ + memcpy(rl->write->seq_num, rl->read->seq_num, + sizeof(rl->write->seq_num)); +} + +static const uint8_t tls12_max_seq_num[TLS12_RECORD_SEQ_NUM_LEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +int +tls12_record_layer_inc_seq_num(struct tls12_record_layer *rl, uint8_t *seq_num) +{ + CBS max_seq_num; + int i; + + /* + * RFC 5246 section 6.1 and RFC 6347 section 4.1 - both TLS and DTLS + * sequence numbers must not wrap. Note that for DTLS the first two + * bytes are used as an "epoch" and not part of the sequence number. + */ + CBS_init(&max_seq_num, seq_num, TLS12_RECORD_SEQ_NUM_LEN); + if (rl->dtls) { + if (!CBS_skip(&max_seq_num, 2)) + return 0; + } + if (CBS_mem_equal(&max_seq_num, tls12_max_seq_num, + CBS_len(&max_seq_num))) + return 0; + + for (i = TLS12_RECORD_SEQ_NUM_LEN - 1; i >= 0; i--) { + if (++seq_num[i] != 0) + break; + } + + return 1; +} + +static int +tls12_record_layer_set_mac_key(struct tls12_record_protection *rp, + const uint8_t *mac_key, size_t mac_key_len) +{ + freezero(rp->mac_key, rp->mac_key_len); + rp->mac_key = NULL; + rp->mac_key_len = 0; + + if (mac_key == NULL || mac_key_len == 0) + return 1; + + if ((rp->mac_key = calloc(1, mac_key_len)) == NULL) + return 0; + + memcpy(rp->mac_key, mac_key, mac_key_len); + rp->mac_key_len = mac_key_len; + + return 1; +} + +static int +tls12_record_layer_ccs_aead(struct tls12_record_layer *rl, + struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key, + CBS *iv) +{ + if (!tls12_record_protection_unused(rp)) + return 0; + + if ((rp->aead_ctx = EVP_AEAD_CTX_new()) == NULL) + return 0; + + /* AES GCM cipher suites use variable nonce in record. */ + if (rl->aead == EVP_aead_aes_128_gcm() || + rl->aead == EVP_aead_aes_256_gcm()) + rp->aead_variable_nonce_in_record = 1; + + /* ChaCha20 Poly1305 XORs the fixed and variable nonces. */ + if (rl->aead == EVP_aead_chacha20_poly1305()) + rp->aead_xor_nonces = 1; + + if (!CBS_stow(iv, &rp->aead_fixed_nonce, &rp->aead_fixed_nonce_len)) + return 0; + + rp->aead_nonce = calloc(1, EVP_AEAD_nonce_length(rl->aead)); + if (rp->aead_nonce == NULL) + return 0; + + rp->aead_nonce_len = EVP_AEAD_nonce_length(rl->aead); + rp->aead_tag_len = EVP_AEAD_max_overhead(rl->aead); + rp->aead_variable_nonce_len = TLS12_RECORD_SEQ_NUM_LEN; + + if (rp->aead_xor_nonces) { + /* Fixed nonce length must match, variable must not exceed. */ + if (rp->aead_fixed_nonce_len != rp->aead_nonce_len) + return 0; + if (rp->aead_variable_nonce_len > rp->aead_nonce_len) + return 0; + } else { + /* Concatenated nonce length must equal AEAD nonce length. */ + if (rp->aead_fixed_nonce_len + + rp->aead_variable_nonce_len != rp->aead_nonce_len) + return 0; + } + + if (!EVP_AEAD_CTX_init(rp->aead_ctx, rl->aead, CBS_data(key), + CBS_len(key), EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) + return 0; + + return 1; +} + +static int +tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl, + struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key, + CBS *iv) +{ + EVP_PKEY *mac_pkey = NULL; + int gost_param_nid; + int mac_type; + int ret = 0; + + if (!tls12_record_protection_unused(rp)) + goto err; + + mac_type = EVP_PKEY_HMAC; + rp->stream_mac = 0; + + if (CBS_len(iv) > INT_MAX || CBS_len(key) > INT_MAX) + goto err; + if (EVP_CIPHER_iv_length(rl->cipher) != CBS_len(iv)) + goto err; + if (EVP_CIPHER_key_length(rl->cipher) != CBS_len(key)) + goto err; + +#ifndef OPENSSL_NO_GOST + /* XXX die die die */ + /* Special handling for GOST... */ + if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) { + if (CBS_len(mac_key) != 32) + goto err; + mac_type = EVP_PKEY_GOSTIMIT; + rp->stream_mac = 1; + } else { +#endif + if (CBS_len(mac_key) > INT_MAX) + goto err; + if (EVP_MD_size(rl->mac_hash) != CBS_len(mac_key)) + goto err; +#ifndef OPENSSL_NO_GOST + } +#endif + + if ((rp->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + if ((rp->hash_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + + if (!tls12_record_layer_set_mac_key(rp, CBS_data(mac_key), + CBS_len(mac_key))) + goto err; + + if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, CBS_data(mac_key), + CBS_len(mac_key))) == NULL) + goto err; + + if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, CBS_data(key), + CBS_data(iv), is_write)) + goto err; + + if (EVP_DigestSignInit(rp->hash_ctx, NULL, rl->mac_hash, NULL, + mac_pkey) <= 0) + goto err; + + /* More special handling for GOST... */ + if (EVP_CIPHER_type(rl->cipher) == NID_gost89_cnt) { + gost_param_nid = NID_id_tc26_gost_28147_param_Z; + if (EVP_MD_type(rl->handshake_hash) == NID_id_GostR3411_94) + gost_param_nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet; + + if (EVP_CIPHER_CTX_ctrl(rp->cipher_ctx, EVP_CTRL_GOST_SET_SBOX, + gost_param_nid, 0) <= 0) + goto err; + + if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) { + if (EVP_MD_CTX_ctrl(rp->hash_ctx, EVP_MD_CTRL_GOST_SET_SBOX, + gost_param_nid, 0) <= 0) + goto err; + } + } + + ret = 1; + + err: + EVP_PKEY_free(mac_pkey); + + return ret; +} + +static int +tls12_record_layer_change_cipher_state(struct tls12_record_layer *rl, + struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key, + CBS *iv) +{ + if (rl->aead != NULL) + return tls12_record_layer_ccs_aead(rl, rp, is_write, mac_key, + key, iv); + + return tls12_record_layer_ccs_cipher(rl, rp, is_write, mac_key, + key, iv); +} + +int +tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl, + CBS *mac_key, CBS *key, CBS *iv) +{ + struct tls12_record_protection *read_new = NULL; + int ret = 0; + + if ((read_new = tls12_record_protection_new()) == NULL) + goto err; + + /* Read sequence number gets reset to zero. */ + + /* DTLS epoch is incremented and is permitted to wrap. */ + if (rl->dtls) + read_new->epoch = rl->read_current->epoch + 1; + + if (!tls12_record_layer_change_cipher_state(rl, read_new, 0, + mac_key, key, iv)) + goto err; + + tls12_record_protection_free(rl->read_current); + rl->read = rl->read_current = read_new; + read_new = NULL; + + ret = 1; + + err: + tls12_record_protection_free(read_new); + + return ret; +} + +int +tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl, + CBS *mac_key, CBS *key, CBS *iv) +{ + struct tls12_record_protection *write_new; + int ret = 0; + + if ((write_new = tls12_record_protection_new()) == NULL) + goto err; + + /* Write sequence number gets reset to zero. */ + + /* DTLS epoch is incremented and is permitted to wrap. */ + if (rl->dtls) + write_new->epoch = rl->write_current->epoch + 1; + + if (!tls12_record_layer_change_cipher_state(rl, write_new, 1, + mac_key, key, iv)) + goto err; + + if (rl->dtls) { + tls12_record_protection_free(rl->write_previous); + rl->write_previous = rl->write_current; + rl->write_current = NULL; + } + tls12_record_protection_free(rl->write_current); + rl->write = rl->write_current = write_new; + write_new = NULL; + + ret = 1; + + err: + tls12_record_protection_free(write_new); + + return ret; +} + +static int +tls12_record_layer_build_seq_num(struct tls12_record_layer *rl, CBB *cbb, + uint16_t epoch, uint8_t *seq_num, size_t seq_num_len) +{ + CBS seq; + + CBS_init(&seq, seq_num, seq_num_len); + + if (rl->dtls) { + if (!CBB_add_u16(cbb, epoch)) + return 0; + if (!CBS_skip(&seq, 2)) + return 0; + } + + return CBB_add_bytes(cbb, CBS_data(&seq), CBS_len(&seq)); +} + +static int +tls12_record_layer_pseudo_header(struct tls12_record_layer *rl, + uint8_t content_type, uint16_t record_len, CBS *seq_num, uint8_t **out, + size_t *out_len) +{ + CBB cbb; + + *out = NULL; + *out_len = 0; + + /* Build the pseudo-header used for MAC/AEAD. */ + if (!CBB_init(&cbb, 13)) + goto err; + + if (!CBB_add_bytes(&cbb, CBS_data(seq_num), CBS_len(seq_num))) + goto err; + if (!CBB_add_u8(&cbb, content_type)) + goto err; + if (!CBB_add_u16(&cbb, rl->version)) + goto err; + if (!CBB_add_u16(&cbb, record_len)) + goto err; + + if (!CBB_finish(&cbb, out, out_len)) + goto err; + + return 1; + + err: + CBB_cleanup(&cbb); + + return 0; +} + +static int +tls12_record_layer_mac(struct tls12_record_layer *rl, CBB *cbb, + EVP_MD_CTX *hash_ctx, int stream_mac, CBS *seq_num, uint8_t content_type, + const uint8_t *content, size_t content_len, size_t *out_len) +{ + EVP_MD_CTX *mac_ctx = NULL; + uint8_t *header = NULL; + size_t header_len = 0; + size_t mac_len; + uint8_t *mac; + int ret = 0; + + if ((mac_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_MD_CTX_copy(mac_ctx, hash_ctx)) + goto err; + + if (!tls12_record_layer_pseudo_header(rl, content_type, content_len, + seq_num, &header, &header_len)) + goto err; + + if (EVP_DigestSignUpdate(mac_ctx, header, header_len) <= 0) + goto err; + if (EVP_DigestSignUpdate(mac_ctx, content, content_len) <= 0) + goto err; + if (EVP_DigestSignFinal(mac_ctx, NULL, &mac_len) <= 0) + goto err; + if (!CBB_add_space(cbb, &mac, mac_len)) + goto err; + if (EVP_DigestSignFinal(mac_ctx, mac, &mac_len) <= 0) + goto err; + if (mac_len == 0) + goto err; + + if (stream_mac) { + if (!EVP_MD_CTX_copy(hash_ctx, mac_ctx)) + goto err; + } + + *out_len = mac_len; + ret = 1; + + err: + EVP_MD_CTX_free(mac_ctx); + freezero(header, header_len); + + return ret; +} + +static int +tls12_record_layer_read_mac_cbc(struct tls12_record_layer *rl, CBB *cbb, + uint8_t content_type, CBS *seq_num, const uint8_t *content, + size_t content_len, size_t mac_len, size_t padding_len) +{ + uint8_t *header = NULL; + size_t header_len = 0; + uint8_t *mac = NULL; + size_t out_mac_len = 0; + int ret = 0; + + /* + * Must be constant time to avoid leaking details about CBC padding. + */ + + if (!ssl3_cbc_record_digest_supported(rl->read->hash_ctx)) + goto err; + + if (!tls12_record_layer_pseudo_header(rl, content_type, content_len, + seq_num, &header, &header_len)) + goto err; + + if (!CBB_add_space(cbb, &mac, mac_len)) + goto err; + if (!ssl3_cbc_digest_record(rl->read->hash_ctx, mac, &out_mac_len, header, + content, content_len + mac_len, content_len + mac_len + padding_len, + rl->read->mac_key, rl->read->mac_key_len)) + goto err; + if (mac_len != out_mac_len) + goto err; + + ret = 1; + + err: + freezero(header, header_len); + + return ret; +} + +static int +tls12_record_layer_read_mac(struct tls12_record_layer *rl, CBB *cbb, + uint8_t content_type, CBS *seq_num, const uint8_t *content, + size_t content_len) +{ + EVP_CIPHER_CTX *enc = rl->read->cipher_ctx; + size_t out_len; + + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) + return 0; + + return tls12_record_layer_mac(rl, cbb, rl->read->hash_ctx, + rl->read->stream_mac, seq_num, content_type, content, content_len, + &out_len); +} + +static int +tls12_record_layer_write_mac(struct tls12_record_layer *rl, CBB *cbb, + uint8_t content_type, CBS *seq_num, const uint8_t *content, + size_t content_len, size_t *out_len) +{ + return tls12_record_layer_mac(rl, cbb, rl->write->hash_ctx, + rl->write->stream_mac, seq_num, content_type, content, content_len, + out_len); +} + +static int +tls12_record_layer_aead_concat_nonce(struct tls12_record_layer *rl, + struct tls12_record_protection *rp, CBS *seq_num) +{ + CBB cbb; + + if (rp->aead_variable_nonce_len > CBS_len(seq_num)) + return 0; + + /* Fixed nonce and variable nonce (sequence number) are concatenated. */ + if (!CBB_init_fixed(&cbb, rp->aead_nonce, rp->aead_nonce_len)) + goto err; + if (!CBB_add_bytes(&cbb, rp->aead_fixed_nonce, + rp->aead_fixed_nonce_len)) + goto err; + if (!CBB_add_bytes(&cbb, CBS_data(seq_num), + rp->aead_variable_nonce_len)) + goto err; + if (!CBB_finish(&cbb, NULL, NULL)) + goto err; + + return 1; + + err: + CBB_cleanup(&cbb); + + return 0; +} + +static int +tls12_record_layer_aead_xored_nonce(struct tls12_record_layer *rl, + struct tls12_record_protection *rp, CBS *seq_num) +{ + uint8_t *pad; + CBB cbb; + int i; + + if (rp->aead_variable_nonce_len > CBS_len(seq_num)) + return 0; + if (rp->aead_fixed_nonce_len < rp->aead_variable_nonce_len) + return 0; + if (rp->aead_fixed_nonce_len != rp->aead_nonce_len) + return 0; + + /* + * Variable nonce (sequence number) is right padded, before the fixed + * nonce is XOR'd in. + */ + if (!CBB_init_fixed(&cbb, rp->aead_nonce, rp->aead_nonce_len)) + goto err; + if (!CBB_add_space(&cbb, &pad, + rp->aead_fixed_nonce_len - rp->aead_variable_nonce_len)) + goto err; + if (!CBB_add_bytes(&cbb, CBS_data(seq_num), + rp->aead_variable_nonce_len)) + goto err; + if (!CBB_finish(&cbb, NULL, NULL)) + goto err; + + for (i = 0; i < rp->aead_fixed_nonce_len; i++) + rp->aead_nonce[i] ^= rp->aead_fixed_nonce[i]; + + return 1; + + err: + CBB_cleanup(&cbb); + + return 0; +} + +static int +tls12_record_layer_open_record_plaintext(struct tls12_record_layer *rl, + uint8_t content_type, CBS *fragment, struct tls_content *out) +{ + if (tls12_record_protection_engaged(rl->read)) + return 0; + + return tls_content_dup_data(out, content_type, CBS_data(fragment), + CBS_len(fragment)); +} + +static int +tls12_record_layer_open_record_protected_aead(struct tls12_record_layer *rl, + uint8_t content_type, CBS *seq_num, CBS *fragment, struct tls_content *out) +{ + struct tls12_record_protection *rp = rl->read; + uint8_t *header = NULL; + size_t header_len = 0; + uint8_t *content = NULL; + size_t content_len = 0; + size_t out_len = 0; + CBS var_nonce; + int ret = 0; + + if (rp->aead_xor_nonces) { + if (!tls12_record_layer_aead_xored_nonce(rl, rp, seq_num)) + goto err; + } else if (rp->aead_variable_nonce_in_record) { + if (!CBS_get_bytes(fragment, &var_nonce, + rp->aead_variable_nonce_len)) + goto err; + if (!tls12_record_layer_aead_concat_nonce(rl, rp, &var_nonce)) + goto err; + } else { + if (!tls12_record_layer_aead_concat_nonce(rl, rp, seq_num)) + goto err; + } + + /* XXX EVP_AEAD_max_tag_len vs EVP_AEAD_CTX_tag_len. */ + if (CBS_len(fragment) < rp->aead_tag_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (CBS_len(fragment) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + content_len = CBS_len(fragment) - rp->aead_tag_len; + if ((content = calloc(1, CBS_len(fragment))) == NULL) { + content_len = 0; + goto err; + } + + if (!tls12_record_layer_pseudo_header(rl, content_type, content_len, + seq_num, &header, &header_len)) + goto err; + + if (!EVP_AEAD_CTX_open(rp->aead_ctx, content, &out_len, content_len, + rp->aead_nonce, rp->aead_nonce_len, CBS_data(fragment), + CBS_len(fragment), header, header_len)) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + if (out_len > SSL3_RT_MAX_PLAIN_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + if (out_len != content_len) + goto err; + + tls_content_set_data(out, content_type, content, content_len); + content = NULL; + content_len = 0; + + ret = 1; + + err: + freezero(header, header_len); + freezero(content, content_len); + + return ret; +} + +static int +tls12_record_layer_open_record_protected_cipher(struct tls12_record_layer *rl, + uint8_t content_type, CBS *seq_num, CBS *fragment, struct tls_content *out) +{ + EVP_CIPHER_CTX *enc = rl->read->cipher_ctx; + SSL3_RECORD_INTERNAL rrec; + size_t block_size, eiv_len; + uint8_t *mac = NULL; + size_t mac_len = 0; + uint8_t *out_mac = NULL; + size_t out_mac_len = 0; + uint8_t *content = NULL; + size_t content_len = 0; + size_t min_len; + CBB cbb_mac; + int ret = 0; + + memset(&cbb_mac, 0, sizeof(cbb_mac)); + memset(&rrec, 0, sizeof(rrec)); + + if (!tls12_record_protection_block_size(rl->read, &block_size)) + goto err; + + /* Determine explicit IV length. */ + eiv_len = 0; + if (rl->version != TLS1_VERSION) { + if (!tls12_record_protection_eiv_len(rl->read, &eiv_len)) + goto err; + } + + mac_len = 0; + if (rl->read->hash_ctx != NULL) { + if (!tls12_record_protection_mac_len(rl->read, &mac_len)) + goto err; + } + + /* CBC has at least one padding byte. */ + min_len = eiv_len + mac_len; + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) + min_len += 1; + + if (CBS_len(fragment) < min_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (CBS_len(fragment) > SSL3_RT_MAX_ENCRYPTED_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + if (CBS_len(fragment) % block_size != 0) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + if ((content = calloc(1, CBS_len(fragment))) == NULL) + goto err; + content_len = CBS_len(fragment); + + if (!EVP_Cipher(enc, content, CBS_data(fragment), CBS_len(fragment))) + goto err; + + rrec.data = content; + rrec.input = content; + rrec.length = content_len; + + /* + * We now have to remove padding, extract MAC, calculate MAC + * and compare MAC in constant time. + */ + if (block_size > 1) + ssl3_cbc_remove_padding(&rrec, eiv_len, mac_len); + + if ((mac = calloc(1, mac_len)) == NULL) + goto err; + + if (!CBB_init(&cbb_mac, EVP_MAX_MD_SIZE)) + goto err; + if (EVP_CIPHER_CTX_mode(enc) == EVP_CIPH_CBC_MODE) { + ssl3_cbc_copy_mac(mac, &rrec, mac_len, rrec.length + + rrec.padding_length); + rrec.length -= mac_len; + if (!tls12_record_layer_read_mac_cbc(rl, &cbb_mac, content_type, + seq_num, rrec.input, rrec.length, mac_len, + rrec.padding_length)) + goto err; + } else { + rrec.length -= mac_len; + memcpy(mac, rrec.data + rrec.length, mac_len); + if (!tls12_record_layer_read_mac(rl, &cbb_mac, content_type, + seq_num, rrec.input, rrec.length)) + goto err; + } + if (!CBB_finish(&cbb_mac, &out_mac, &out_mac_len)) + goto err; + if (mac_len != out_mac_len) + goto err; + + if (timingsafe_memcmp(mac, out_mac, mac_len) != 0) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + + if (rrec.length > SSL3_RT_MAX_COMPRESSED_LENGTH + mac_len) { + rl->alert_desc = SSL_AD_BAD_RECORD_MAC; + goto err; + } + if (rrec.length > SSL3_RT_MAX_PLAIN_LENGTH) { + rl->alert_desc = SSL_AD_RECORD_OVERFLOW; + goto err; + } + + tls_content_set_data(out, content_type, content, content_len); + content = NULL; + content_len = 0; + + /* Actual content is after EIV, minus padding and MAC. */ + if (!tls_content_set_bounds(out, eiv_len, rrec.length)) + goto err; + + ret = 1; + + err: + CBB_cleanup(&cbb_mac); + freezero(mac, mac_len); + freezero(out_mac, out_mac_len); + freezero(content, content_len); + + return ret; +} + +int +tls12_record_layer_open_record(struct tls12_record_layer *rl, uint8_t *buf, + size_t buf_len, struct tls_content *out) +{ + CBS cbs, fragment, seq_num; + uint16_t version; + uint8_t content_type; + + CBS_init(&cbs, buf, buf_len); + CBS_init(&seq_num, rl->read->seq_num, sizeof(rl->read->seq_num)); + + if (!CBS_get_u8(&cbs, &content_type)) + return 0; + if (!CBS_get_u16(&cbs, &version)) + return 0; + if (rl->dtls) { + /* + * The DTLS sequence number is split into a 16 bit epoch and + * 48 bit sequence number, however for the purposes of record + * processing it is treated the same as a TLS 64 bit sequence + * number. DTLS also uses explicit read sequence numbers, which + * we need to extract from the DTLS record header. + */ + if (!CBS_get_bytes(&cbs, &seq_num, SSL3_SEQUENCE_SIZE)) + return 0; + if (!CBS_write_bytes(&seq_num, rl->read->seq_num, + sizeof(rl->read->seq_num), NULL)) + return 0; + } + if (!CBS_get_u16_length_prefixed(&cbs, &fragment)) + return 0; + + if (rl->read->aead_ctx != NULL) { + if (!tls12_record_layer_open_record_protected_aead(rl, + content_type, &seq_num, &fragment, out)) + return 0; + } else if (rl->read->cipher_ctx != NULL) { + if (!tls12_record_layer_open_record_protected_cipher(rl, + content_type, &seq_num, &fragment, out)) + return 0; + } else { + if (!tls12_record_layer_open_record_plaintext(rl, + content_type, &fragment, out)) + return 0; + } + + if (!rl->dtls) { + if (!tls12_record_layer_inc_seq_num(rl, rl->read->seq_num)) + return 0; + } + + return 1; +} + +static int +tls12_record_layer_seal_record_plaintext(struct tls12_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len, CBB *out) +{ + if (tls12_record_protection_engaged(rl->write)) + return 0; + + return CBB_add_bytes(out, content, content_len); +} + +static int +tls12_record_layer_seal_record_protected_aead(struct tls12_record_layer *rl, + uint8_t content_type, CBS *seq_num, const uint8_t *content, + size_t content_len, CBB *out) +{ + struct tls12_record_protection *rp = rl->write; + uint8_t *header = NULL; + size_t header_len = 0; + size_t enc_record_len, out_len; + uint8_t *enc_data; + int ret = 0; + + if (rp->aead_xor_nonces) { + if (!tls12_record_layer_aead_xored_nonce(rl, rp, seq_num)) + goto err; + } else { + if (!tls12_record_layer_aead_concat_nonce(rl, rp, seq_num)) + goto err; + } + + if (rp->aead_variable_nonce_in_record) { + if (rp->aead_variable_nonce_len > CBS_len(seq_num)) + goto err; + if (!CBB_add_bytes(out, CBS_data(seq_num), + rp->aead_variable_nonce_len)) + goto err; + } + + if (!tls12_record_layer_pseudo_header(rl, content_type, content_len, + seq_num, &header, &header_len)) + goto err; + + /* XXX EVP_AEAD_max_tag_len vs EVP_AEAD_CTX_tag_len. */ + enc_record_len = content_len + rp->aead_tag_len; + if (enc_record_len > SSL3_RT_MAX_ENCRYPTED_LENGTH) + goto err; + if (!CBB_add_space(out, &enc_data, enc_record_len)) + goto err; + + if (!EVP_AEAD_CTX_seal(rp->aead_ctx, enc_data, &out_len, enc_record_len, + rp->aead_nonce, rp->aead_nonce_len, content, content_len, header, + header_len)) + goto err; + + if (out_len != enc_record_len) + goto err; + + ret = 1; + + err: + freezero(header, header_len); + + return ret; +} + +static int +tls12_record_layer_seal_record_protected_cipher(struct tls12_record_layer *rl, + uint8_t content_type, CBS *seq_num, const uint8_t *content, + size_t content_len, CBB *out) +{ + EVP_CIPHER_CTX *enc = rl->write->cipher_ctx; + size_t block_size, eiv_len, mac_len, pad_len; + uint8_t *enc_data, *eiv, *pad, pad_val; + uint8_t *plain = NULL; + size_t plain_len = 0; + int ret = 0; + CBB cbb; + + if (!CBB_init(&cbb, SSL3_RT_MAX_PLAIN_LENGTH)) + goto err; + + /* Add explicit IV if necessary. */ + eiv_len = 0; + if (rl->version != TLS1_VERSION) { + if (!tls12_record_protection_eiv_len(rl->write, &eiv_len)) + goto err; + } + if (eiv_len > 0) { + if (!CBB_add_space(&cbb, &eiv, eiv_len)) + goto err; + arc4random_buf(eiv, eiv_len); + } + + if (!CBB_add_bytes(&cbb, content, content_len)) + goto err; + + mac_len = 0; + if (rl->write->hash_ctx != NULL) { + if (!tls12_record_layer_write_mac(rl, &cbb, content_type, + seq_num, content, content_len, &mac_len)) + goto err; + } + + plain_len = eiv_len + content_len + mac_len; + + /* Add padding to block size, if necessary. */ + if (!tls12_record_protection_block_size(rl->write, &block_size)) + goto err; + if (block_size > 1) { + pad_len = block_size - (plain_len % block_size); + pad_val = pad_len - 1; + + if (pad_len > 255) + goto err; + if (!CBB_add_space(&cbb, &pad, pad_len)) + goto err; + memset(pad, pad_val, pad_len); + } + + if (!CBB_finish(&cbb, &plain, &plain_len)) + goto err; + + if (plain_len % block_size != 0) + goto err; + if (plain_len > SSL3_RT_MAX_ENCRYPTED_LENGTH) + goto err; + + if (!CBB_add_space(out, &enc_data, plain_len)) + goto err; + if (!EVP_Cipher(enc, enc_data, plain, plain_len)) + goto err; + + ret = 1; + + err: + CBB_cleanup(&cbb); + freezero(plain, plain_len); + + return ret; +} + +int +tls12_record_layer_seal_record(struct tls12_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len, CBB *cbb) +{ + uint8_t *seq_num_data = NULL; + size_t seq_num_len = 0; + CBB fragment, seq_num_cbb; + CBS seq_num; + int ret = 0; + + /* + * Construct the effective sequence number - this is used in both + * the DTLS header and for MAC calculations. + */ + if (!CBB_init(&seq_num_cbb, SSL3_SEQUENCE_SIZE)) + goto err; + if (!tls12_record_layer_build_seq_num(rl, &seq_num_cbb, rl->write->epoch, + rl->write->seq_num, sizeof(rl->write->seq_num))) + goto err; + if (!CBB_finish(&seq_num_cbb, &seq_num_data, &seq_num_len)) + goto err; + CBS_init(&seq_num, seq_num_data, seq_num_len); + + if (!CBB_add_u8(cbb, content_type)) + goto err; + if (!CBB_add_u16(cbb, rl->version)) + goto err; + if (rl->dtls) { + if (!CBB_add_bytes(cbb, CBS_data(&seq_num), CBS_len(&seq_num))) + goto err; + } + if (!CBB_add_u16_length_prefixed(cbb, &fragment)) + goto err; + + if (rl->write->aead_ctx != NULL) { + if (!tls12_record_layer_seal_record_protected_aead(rl, + content_type, &seq_num, content, content_len, &fragment)) + goto err; + } else if (rl->write->cipher_ctx != NULL) { + if (!tls12_record_layer_seal_record_protected_cipher(rl, + content_type, &seq_num, content, content_len, &fragment)) + goto err; + } else { + if (!tls12_record_layer_seal_record_plaintext(rl, + content_type, content, content_len, &fragment)) + goto err; + } + + if (!CBB_flush(cbb)) + goto err; + + if (!tls12_record_layer_inc_seq_num(rl, rl->write->seq_num)) + goto err; + + ret = 1; + + err: + CBB_cleanup(&seq_num_cbb); + free(seq_num_data); + + return ret; +} diff --git a/ssl/tls13_client.c b/ssl/tls13_client.c new file mode 100644 index 0000000..053cf16 --- /dev/null +++ b/ssl/tls13_client.c @@ -0,0 +1,1060 @@ +/* $OpenBSD: tls13_client.c,v 1.102 2023/06/10 15:34:36 tb Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" +#include "tls13_handshake.h" +#include "tls13_internal.h" + +int +tls13_client_init(struct tls13_ctx *ctx) +{ + const uint16_t *groups; + size_t groups_len; + SSL *s = ctx->ssl; + + if (!ssl_supported_tls_version_range(s, &ctx->hs->our_min_tls_version, + &ctx->hs->our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + s->version = ctx->hs->our_max_tls_version; + + tls13_record_layer_set_retry_after_phh(ctx->rl, + (s->mode & SSL_MODE_AUTO_RETRY) != 0); + + if (!ssl_get_new_session(s, 0)) /* XXX */ + return 0; + + if (!tls1_transcript_init(s)) + return 0; + + /* Generate a key share using our preferred group. */ + tls1_get_group_list(s, 0, &groups, &groups_len); + if (groups_len < 1) + return 0; + if ((ctx->hs->key_share = tls_key_share_new(groups[0])) == NULL) + return 0; + if (!tls_key_share_generate(ctx->hs->key_share)) + return 0; + + arc4random_buf(s->s3->client_random, SSL3_RANDOM_SIZE); + + /* + * The legacy session identifier should either be set to an + * unpredictable 32-byte value or zero length... a non-zero length + * legacy session identifier triggers compatibility mode (see RFC 8446 + * Appendix D.4). In the pre-TLSv1.3 case a zero length value is used. + */ + if (ctx->middlebox_compat && + ctx->hs->our_max_tls_version >= TLS1_3_VERSION) { + arc4random_buf(ctx->hs->tls13.legacy_session_id, + sizeof(ctx->hs->tls13.legacy_session_id)); + ctx->hs->tls13.legacy_session_id_len = + sizeof(ctx->hs->tls13.legacy_session_id); + } + + return 1; +} + +int +tls13_client_connect(struct tls13_ctx *ctx) +{ + if (ctx->mode != TLS13_HS_CLIENT) + return TLS13_IO_FAILURE; + + return tls13_handshake_perform(ctx); +} + +static int +tls13_client_hello_build(struct tls13_ctx *ctx, CBB *cbb) +{ + CBB cipher_suites, compression_methods, session_id; + uint16_t client_version; + SSL *s = ctx->ssl; + + /* Legacy client version is capped at TLS 1.2. */ + if (!ssl_max_legacy_version(s, &client_version)) + goto err; + + if (!CBB_add_u16(cbb, client_version)) + goto err; + if (!CBB_add_bytes(cbb, s->s3->client_random, SSL3_RANDOM_SIZE)) + goto err; + + if (!CBB_add_u8_length_prefixed(cbb, &session_id)) + goto err; + if (!CBB_add_bytes(&session_id, ctx->hs->tls13.legacy_session_id, + ctx->hs->tls13.legacy_session_id_len)) + goto err; + + if (!CBB_add_u16_length_prefixed(cbb, &cipher_suites)) + goto err; + if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &cipher_suites)) { + SSLerror(s, SSL_R_NO_CIPHERS_AVAILABLE); + goto err; + } + + if (!CBB_add_u8_length_prefixed(cbb, &compression_methods)) + goto err; + if (!CBB_add_u8(&compression_methods, 0)) + goto err; + + if (!tlsext_client_build(s, SSL_TLSEXT_MSG_CH, cbb)) + goto err; + + if (!CBB_flush(cbb)) + goto err; + + return 1; + + err: + return 0; +} + +int +tls13_client_hello_send(struct tls13_ctx *ctx, CBB *cbb) +{ + if (ctx->hs->our_min_tls_version < TLS1_2_VERSION) + tls13_record_layer_set_legacy_version(ctx->rl, TLS1_VERSION); + + /* We may receive a pre-TLSv1.3 alert in response to the client hello. */ + tls13_record_layer_allow_legacy_alerts(ctx->rl, 1); + + if (!tls13_client_hello_build(ctx, cbb)) + return 0; + + return 1; +} + +int +tls13_client_hello_sent(struct tls13_ctx *ctx) +{ + tls1_transcript_freeze(ctx->ssl); + + if (ctx->middlebox_compat) { + tls13_record_layer_allow_ccs(ctx->rl, 1); + ctx->send_dummy_ccs = 1; + } + + return 1; +} + +static int +tls13_server_hello_is_legacy(CBS *cbs) +{ + CBS extensions_block, extensions, extension_data; + uint16_t selected_version = 0; + uint16_t type; + + CBS_dup(cbs, &extensions_block); + + if (!CBS_get_u16_length_prefixed(&extensions_block, &extensions)) + return 1; + + while (CBS_len(&extensions) > 0) { + if (!CBS_get_u16(&extensions, &type)) + return 1; + if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) + return 1; + + if (type != TLSEXT_TYPE_supported_versions) + continue; + if (!CBS_get_u16(&extension_data, &selected_version)) + return 1; + if (CBS_len(&extension_data) != 0) + return 1; + } + + return (selected_version < TLS1_3_VERSION); +} + +static int +tls13_server_hello_is_retry(CBS *cbs) +{ + CBS server_hello, server_random; + uint16_t legacy_version; + + CBS_dup(cbs, &server_hello); + + if (!CBS_get_u16(&server_hello, &legacy_version)) + return 0; + if (!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE)) + return 0; + + /* See if this is a HelloRetryRequest. */ + return CBS_mem_equal(&server_random, tls13_hello_retry_request_hash, + sizeof(tls13_hello_retry_request_hash)); +} + +static int +tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) +{ + CBS server_random, session_id; + uint16_t tlsext_msg_type = SSL_TLSEXT_MSG_SH; + uint16_t cipher_suite, legacy_version; + uint8_t compression_method; + const SSL_CIPHER *cipher; + int alert_desc; + SSL *s = ctx->ssl; + + if (!CBS_get_u16(cbs, &legacy_version)) + goto err; + if (!CBS_get_bytes(cbs, &server_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBS_get_u8_length_prefixed(cbs, &session_id)) + goto err; + if (!CBS_get_u16(cbs, &cipher_suite)) + goto err; + if (!CBS_get_u8(cbs, &compression_method)) + goto err; + + if (tls13_server_hello_is_legacy(cbs)) { + if (ctx->hs->our_max_tls_version >= TLS1_3_VERSION) { + /* + * RFC 8446 section 4.1.3: we must not downgrade if + * the server random value contains the TLS 1.2 or 1.1 + * magical value. + */ + if (!CBS_skip(&server_random, CBS_len(&server_random) - + sizeof(tls13_downgrade_12))) + goto err; + if (CBS_mem_equal(&server_random, tls13_downgrade_12, + sizeof(tls13_downgrade_12)) || + CBS_mem_equal(&server_random, tls13_downgrade_11, + sizeof(tls13_downgrade_11))) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + } + + if (!CBS_skip(cbs, CBS_len(cbs))) + goto err; + + ctx->hs->tls13.use_legacy = 1; + return 1; + } + + /* From here on in we know we are doing TLSv1.3. */ + tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION); + tls13_record_layer_allow_legacy_alerts(ctx->rl, 0); + + /* See if this is a HelloRetryRequest. */ + /* XXX - see if we can avoid doing this twice. */ + if (CBS_mem_equal(&server_random, tls13_hello_retry_request_hash, + sizeof(tls13_hello_retry_request_hash))) { + tlsext_msg_type = SSL_TLSEXT_MSG_HRR; + ctx->hs->tls13.hrr = 1; + } + + if (!tlsext_client_parse(s, tlsext_msg_type, cbs, &alert_desc)) { + ctx->alert = alert_desc; + goto err; + } + + /* + * The supported versions extension indicated 0x0304 or greater. + * Ensure that it was 0x0304 and that legacy version is set to 0x0303 + * (RFC 8446 section 4.2.1). + */ + if (ctx->hs->tls13.server_version != TLS1_3_VERSION || + legacy_version != TLS1_2_VERSION) { + ctx->alert = TLS13_ALERT_PROTOCOL_VERSION; + goto err; + } + ctx->hs->negotiated_tls_version = ctx->hs->tls13.server_version; + ctx->hs->peer_legacy_version = legacy_version; + + /* The session_id must match. */ + if (!CBS_mem_equal(&session_id, ctx->hs->tls13.legacy_session_id, + ctx->hs->tls13.legacy_session_id_len)) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + /* + * Ensure that the cipher suite is one that we offered in the client + * hello and that it is a TLSv1.3 cipher suite. + */ + cipher = ssl3_get_cipher_by_value(cipher_suite); + if (cipher == NULL || !ssl_cipher_in_list(SSL_get_ciphers(s), cipher)) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + if (cipher->algorithm_ssl != SSL_TLSV1_3) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + if (!(ctx->handshake_stage.hs_type & WITHOUT_HRR) && !ctx->hs->tls13.hrr) { + /* + * A ServerHello following a HelloRetryRequest MUST use the same + * cipher suite (RFC 8446 section 4.1.4). + */ + if (ctx->hs->cipher != cipher) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + } + ctx->hs->cipher = cipher; + + if (compression_method != 0) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + return 1; + + err: + if (ctx->alert == 0) + ctx->alert = TLS13_ALERT_DECODE_ERROR; + + return 0; +} + +static int +tls13_client_engage_record_protection(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets; + struct tls13_secret context; + unsigned char buf[EVP_MAX_MD_SIZE]; + uint8_t *shared_key = NULL; + size_t shared_key_len = 0; + size_t hash_len; + SSL *s = ctx->ssl; + int ret = 0; + + /* Derive the shared key and engage record protection. */ + + if (!tls_key_share_derive(ctx->hs->key_share, &shared_key, + &shared_key_len)) + goto err; + + s->session->cipher = ctx->hs->cipher; + s->session->ssl_version = ctx->hs->tls13.server_version; + + if ((ctx->aead = tls13_cipher_aead(ctx->hs->cipher)) == NULL) + goto err; + if ((ctx->hash = tls13_cipher_hash(ctx->hs->cipher)) == NULL) + goto err; + + if ((secrets = tls13_secrets_create(ctx->hash, 0)) == NULL) + goto err; + ctx->hs->tls13.secrets = secrets; + + /* XXX - pass in hash. */ + if (!tls1_transcript_hash_init(s)) + goto err; + tls1_transcript_free(s); + if (!tls1_transcript_hash_value(s, buf, sizeof(buf), &hash_len)) + goto err; + context.data = buf; + context.len = hash_len; + + /* Early secrets. */ + if (!tls13_derive_early_secrets(secrets, secrets->zeros.data, + secrets->zeros.len, &context)) + goto err; + + /* Handshake secrets. */ + if (!tls13_derive_handshake_secrets(ctx->hs->tls13.secrets, shared_key, + shared_key_len, &context)) + goto err; + + tls13_record_layer_set_aead(ctx->rl, ctx->aead); + tls13_record_layer_set_hash(ctx->rl, ctx->hash); + + if (!tls13_record_layer_set_read_traffic_key(ctx->rl, + &secrets->server_handshake_traffic, ssl_encryption_handshake)) + goto err; + if (!tls13_record_layer_set_write_traffic_key(ctx->rl, + &secrets->client_handshake_traffic, ssl_encryption_handshake)) + goto err; + + ret = 1; + + err: + freezero(shared_key, shared_key_len); + + return ret; +} + +int +tls13_server_hello_retry_request_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + /* + * The state machine has no way of knowing if we're going to receive a + * HelloRetryRequest or a ServerHello. As such, we have to handle + * this case here and hand off to the appropriate function. + */ + if (!tls13_server_hello_is_retry(cbs)) { + ctx->handshake_stage.hs_type |= WITHOUT_HRR; + return tls13_server_hello_recv(ctx, cbs); + } + + if (!tls13_server_hello_process(ctx, cbs)) + return 0; + + /* + * This may have been a TLSv1.2 or earlier ServerHello that just + * happened to have matching server random... + */ + if (ctx->hs->tls13.use_legacy) + return tls13_use_legacy_client(ctx); + + if (!ctx->hs->tls13.hrr) + return 0; + + if (!tls13_synthetic_handshake_message(ctx)) + return 0; + if (!tls13_handshake_msg_record(ctx)) + return 0; + + ctx->hs->tls13.hrr = 0; + + return 1; +} + +int +tls13_client_hello_retry_send(struct tls13_ctx *ctx, CBB *cbb) +{ + /* + * Ensure that the server supported group is one that we listed in our + * supported groups and is not the same as the key share we previously + * offered. + */ + if (!tls1_check_group(ctx->ssl, ctx->hs->tls13.server_group)) + return 0; /* XXX alert */ + if (ctx->hs->tls13.server_group == tls_key_share_group(ctx->hs->key_share)) + return 0; /* XXX alert */ + + /* Switch to new key share. */ + tls_key_share_free(ctx->hs->key_share); + if ((ctx->hs->key_share = + tls_key_share_new(ctx->hs->tls13.server_group)) == NULL) + return 0; + if (!tls_key_share_generate(ctx->hs->key_share)) + return 0; + + if (!tls13_client_hello_build(ctx, cbb)) + return 0; + + return 1; +} + +int +tls13_server_hello_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + SSL *s = ctx->ssl; + + /* + * We may have received a legacy (pre-TLSv1.3) ServerHello or a TLSv1.3 + * ServerHello. HelloRetryRequests have already been handled. + */ + if (!tls13_server_hello_process(ctx, cbs)) + return 0; + + if (ctx->handshake_stage.hs_type & WITHOUT_HRR) { + tls1_transcript_unfreeze(s); + if (!tls13_handshake_msg_record(ctx)) + return 0; + } + + if (ctx->hs->tls13.use_legacy) { + if (!(ctx->handshake_stage.hs_type & WITHOUT_HRR)) + return 0; + return tls13_use_legacy_client(ctx); + } + + if (ctx->hs->tls13.hrr) { + /* The server has sent two HelloRetryRequests. */ + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + return 0; + } + + if (!tls13_client_engage_record_protection(ctx)) + return 0; + + ctx->handshake_stage.hs_type |= NEGOTIATED; + + return 1; +} + +int +tls13_server_encrypted_extensions_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + int alert_desc; + + if (!tlsext_client_parse(ctx->ssl, SSL_TLSEXT_MSG_EE, cbs, &alert_desc)) { + ctx->alert = alert_desc; + return 0; + } + + return 1; +} + +int +tls13_server_certificate_request_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + CBS cert_request_context; + int alert_desc; + + /* + * Thanks to poor state design in the RFC, this function can be called + * when we actually have a certificate message instead of a certificate + * request... in that case we call the certificate handler after + * switching state, to avoid advancing state. + */ + if (tls13_handshake_msg_type(ctx->hs_msg) == TLS13_MT_CERTIFICATE) { + ctx->handshake_stage.hs_type |= WITHOUT_CR; + return tls13_server_certificate_recv(ctx, cbs); + } + + if (!CBS_get_u8_length_prefixed(cbs, &cert_request_context)) + goto err; + if (CBS_len(&cert_request_context) != 0) + goto err; + + if (!tlsext_client_parse(ctx->ssl, SSL_TLSEXT_MSG_CR, cbs, &alert_desc)) { + ctx->alert = alert_desc; + goto err; + } + + return 1; + + err: + if (ctx->alert == 0) + ctx->alert = TLS13_ALERT_DECODE_ERROR; + + return 0; +} + +int +tls13_server_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + CBS cert_request_context, cert_list, cert_data; + struct stack_st_X509 *certs = NULL; + SSL *s = ctx->ssl; + X509 *cert = NULL; + const uint8_t *p; + int alert_desc; + int ret = 0; + + if ((certs = sk_X509_new_null()) == NULL) + goto err; + + if (!CBS_get_u8_length_prefixed(cbs, &cert_request_context)) + goto err; + if (CBS_len(&cert_request_context) != 0) + goto err; + if (!CBS_get_u24_length_prefixed(cbs, &cert_list)) + goto err; + + while (CBS_len(&cert_list) > 0) { + if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) + goto err; + + if (!tlsext_client_parse(ctx->ssl, SSL_TLSEXT_MSG_CT, + &cert_list, &alert_desc)) { + ctx->alert = alert_desc; + goto err; + } + + p = CBS_data(&cert_data); + if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) + goto err; + if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) + goto err; + + if (!sk_X509_push(certs, cert)) + goto err; + + cert = NULL; + } + + /* A server must always provide a non-empty certificate list. */ + if (sk_X509_num(certs) < 1) { + ctx->alert = TLS13_ALERT_DECODE_ERROR; + tls13_set_errorx(ctx, TLS13_ERR_NO_PEER_CERTIFICATE, 0, + "peer failed to provide a certificate", NULL); + goto err; + } + + /* + * At this stage we still have no proof of possession. As such, it would + * be preferable to keep the chain and verify once we have successfully + * processed the CertificateVerify message. + */ + if (ssl_verify_cert_chain(s, certs) <= 0 && + s->verify_mode != SSL_VERIFY_NONE) { + ctx->alert = ssl_verify_alarm_type(s->verify_result); + tls13_set_errorx(ctx, TLS13_ERR_VERIFY_FAILED, 0, + "failed to verify peer certificate", NULL); + goto err; + } + s->session->verify_result = s->verify_result; + ERR_clear_error(); + + if (!tls_process_peer_certs(s, certs)) + goto err; + + if (ctx->ocsp_status_recv_cb != NULL && + !ctx->ocsp_status_recv_cb(ctx)) + goto err; + + ret = 1; + + err: + sk_X509_pop_free(certs, X509_free); + X509_free(cert); + + return ret; +} + +int +tls13_server_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + const struct ssl_sigalg *sigalg; + uint16_t signature_scheme; + uint8_t *sig_content = NULL; + size_t sig_content_len; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + X509 *cert; + CBS signature; + CBB cbb; + int ret = 0; + + memset(&cbb, 0, sizeof(cbb)); + + if (!CBS_get_u16(cbs, &signature_scheme)) + goto err; + if (!CBS_get_u16_length_prefixed(cbs, &signature)) + goto err; + + if (!CBB_init(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, tls13_cert_verify_pad, + sizeof(tls13_cert_verify_pad))) + goto err; + if (!CBB_add_bytes(&cbb, tls13_cert_server_verify_context, + strlen(tls13_cert_server_verify_context))) + goto err; + if (!CBB_add_u8(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) + goto err; + + if ((cert = ctx->ssl->session->peer_cert) == NULL) + goto err; + if ((pkey = X509_get0_pubkey(cert)) == NULL) + goto err; + if ((sigalg = ssl_sigalg_for_peer(ctx->ssl, pkey, + signature_scheme)) == NULL) + goto err; + ctx->hs->peer_sigalg = sigalg; + + if (CBS_len(&signature) > EVP_PKEY_size(pkey)) + goto err; + + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestVerifyInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) + goto err; + if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { + if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) + goto err; + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) + goto err; + } + if (EVP_DigestVerify(mdctx, CBS_data(&signature), CBS_len(&signature), + sig_content, sig_content_len) <= 0) { + ctx->alert = TLS13_ALERT_DECRYPT_ERROR; + goto err; + } + + ret = 1; + + err: + if (!ret && ctx->alert == 0) + ctx->alert = TLS13_ALERT_DECODE_ERROR; + CBB_cleanup(&cbb); + EVP_MD_CTX_free(mdctx); + free(sig_content); + + return ret; +} + +int +tls13_server_finished_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret context = { .data = "", .len = 0 }; + struct tls13_secret finished_key; + uint8_t transcript_hash[EVP_MAX_MD_SIZE]; + size_t transcript_hash_len; + uint8_t *verify_data = NULL; + size_t verify_data_len; + uint8_t key[EVP_MAX_MD_SIZE]; + HMAC_CTX *hmac_ctx = NULL; + unsigned int hlen; + int ret = 0; + + /* + * Verify server finished. + */ + finished_key.data = key; + finished_key.len = EVP_MD_size(ctx->hash); + + if (!tls13_hkdf_expand_label(&finished_key, ctx->hash, + &secrets->server_handshake_traffic, "finished", + &context)) + goto err; + + if ((hmac_ctx = HMAC_CTX_new()) == NULL) + goto err; + if (!HMAC_Init_ex(hmac_ctx, finished_key.data, finished_key.len, + ctx->hash, NULL)) + goto err; + if (!HMAC_Update(hmac_ctx, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + verify_data_len = HMAC_size(hmac_ctx); + if ((verify_data = calloc(1, verify_data_len)) == NULL) + goto err; + if (!HMAC_Final(hmac_ctx, verify_data, &hlen)) + goto err; + if (hlen != verify_data_len) + goto err; + + if (!CBS_mem_equal(cbs, verify_data, verify_data_len)) { + ctx->alert = TLS13_ALERT_DECRYPT_ERROR; + goto err; + } + + if (!CBS_write_bytes(cbs, ctx->hs->peer_finished, + sizeof(ctx->hs->peer_finished), + &ctx->hs->peer_finished_len)) + goto err; + + if (!CBS_skip(cbs, verify_data_len)) + goto err; + + /* + * Derive application traffic keys. + */ + if (!tls1_transcript_hash_value(ctx->ssl, transcript_hash, + sizeof(transcript_hash), &transcript_hash_len)) + goto err; + + context.data = transcript_hash; + context.len = transcript_hash_len; + + if (!tls13_derive_application_secrets(secrets, &context)) + goto err; + + /* + * Any records following the server finished message must be encrypted + * using the server application traffic keys. + */ + if (!tls13_record_layer_set_read_traffic_key(ctx->rl, + &secrets->server_application_traffic, ssl_encryption_application)) + goto err; + + tls13_record_layer_allow_ccs(ctx->rl, 0); + + ret = 1; + + err: + HMAC_CTX_free(hmac_ctx); + free(verify_data); + + return ret; +} + +static int +tls13_client_check_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY *cpk, + int *ok, const struct ssl_sigalg **out_sigalg) +{ + const struct ssl_sigalg *sigalg; + SSL *s = ctx->ssl; + + *ok = 0; + *out_sigalg = NULL; + + if (cpk->x509 == NULL || cpk->privatekey == NULL) + goto done; + + if ((sigalg = ssl_sigalg_select(s, cpk->privatekey)) == NULL) + goto done; + + *ok = 1; + *out_sigalg = sigalg; + + done: + return 1; +} + +static int +tls13_client_select_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY **out_cpk, + const struct ssl_sigalg **out_sigalg) +{ + SSL *s = ctx->ssl; + const struct ssl_sigalg *sigalg; + SSL_CERT_PKEY *cpk; + int cert_ok; + + *out_cpk = NULL; + *out_sigalg = NULL; + + /* + * XXX - RFC 8446, 4.4.2.3: the server can communicate preferences + * with the certificate_authorities (4.2.4) and oid_filters (4.2.5) + * extensions. We should honor the former and must apply the latter. + */ + + cpk = &s->cert->pkeys[SSL_PKEY_ECC]; + if (!tls13_client_check_certificate(ctx, cpk, &cert_ok, &sigalg)) + return 0; + if (cert_ok) + goto done; + + cpk = &s->cert->pkeys[SSL_PKEY_RSA]; + if (!tls13_client_check_certificate(ctx, cpk, &cert_ok, &sigalg)) + return 0; + if (cert_ok) + goto done; + + cpk = NULL; + sigalg = NULL; + + done: + *out_cpk = cpk; + *out_sigalg = sigalg; + + return 1; +} + +int +tls13_client_certificate_send(struct tls13_ctx *ctx, CBB *cbb) +{ + SSL *s = ctx->ssl; + CBB cert_request_context, cert_list; + const struct ssl_sigalg *sigalg; + STACK_OF(X509) *chain; + SSL_CERT_PKEY *cpk; + X509 *cert; + int i, ret = 0; + + if (!tls13_client_select_certificate(ctx, &cpk, &sigalg)) + goto err; + + ctx->hs->tls13.cpk = cpk; + ctx->hs->our_sigalg = sigalg; + + if (!CBB_add_u8_length_prefixed(cbb, &cert_request_context)) + goto err; + if (!CBB_add_u24_length_prefixed(cbb, &cert_list)) + goto err; + + /* No certificate selected. */ + if (cpk == NULL) + goto done; + + if ((chain = cpk->chain) == NULL) + chain = s->ctx->extra_certs; + + if (!tls13_cert_add(ctx, &cert_list, cpk->x509, tlsext_client_build)) + goto err; + + for (i = 0; i < sk_X509_num(chain); i++) { + cert = sk_X509_value(chain, i); + if (!tls13_cert_add(ctx, &cert_list, cert, tlsext_client_build)) + goto err; + } + + ctx->handshake_stage.hs_type |= WITH_CCV; + done: + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + return ret; +} + +int +tls13_client_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) +{ + const struct ssl_sigalg *sigalg; + uint8_t *sig = NULL, *sig_content = NULL; + size_t sig_len, sig_content_len; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + const SSL_CERT_PKEY *cpk; + CBB sig_cbb; + int ret = 0; + + memset(&sig_cbb, 0, sizeof(sig_cbb)); + + if ((cpk = ctx->hs->tls13.cpk) == NULL) + goto err; + if ((sigalg = ctx->hs->our_sigalg) == NULL) + goto err; + pkey = cpk->privatekey; + + if (!CBB_init(&sig_cbb, 0)) + goto err; + if (!CBB_add_bytes(&sig_cbb, tls13_cert_verify_pad, + sizeof(tls13_cert_verify_pad))) + goto err; + if (!CBB_add_bytes(&sig_cbb, tls13_cert_client_verify_context, + strlen(tls13_cert_client_verify_context))) + goto err; + if (!CBB_add_u8(&sig_cbb, 0)) + goto err; + if (!CBB_add_bytes(&sig_cbb, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + if (!CBB_finish(&sig_cbb, &sig_content, &sig_content_len)) + goto err; + + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestSignInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) + goto err; + if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { + if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) + goto err; + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) + goto err; + } + if (!EVP_DigestSign(mdctx, NULL, &sig_len, sig_content, sig_content_len)) + goto err; + if ((sig = calloc(1, sig_len)) == NULL) + goto err; + if (!EVP_DigestSign(mdctx, sig, &sig_len, sig_content, sig_content_len)) + goto err; + + if (!CBB_add_u16(cbb, sigalg->value)) + goto err; + if (!CBB_add_u16_length_prefixed(cbb, &sig_cbb)) + goto err; + if (!CBB_add_bytes(&sig_cbb, sig, sig_len)) + goto err; + + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + if (!ret && ctx->alert == 0) + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + + CBB_cleanup(&sig_cbb); + EVP_MD_CTX_free(mdctx); + free(sig_content); + free(sig); + + return ret; +} + +int +tls13_client_end_of_early_data_send(struct tls13_ctx *ctx, CBB *cbb) +{ + return 0; +} + +int +tls13_client_finished_send(struct tls13_ctx *ctx, CBB *cbb) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret context = { .data = "", .len = 0 }; + struct tls13_secret finished_key = { .data = NULL, .len = 0 }; + uint8_t transcript_hash[EVP_MAX_MD_SIZE]; + size_t transcript_hash_len; + uint8_t *verify_data; + size_t verify_data_len; + unsigned int hlen; + HMAC_CTX *hmac_ctx = NULL; + CBS cbs; + int ret = 0; + + if (!tls13_secret_init(&finished_key, EVP_MD_size(ctx->hash))) + goto err; + + if (!tls13_hkdf_expand_label(&finished_key, ctx->hash, + &secrets->client_handshake_traffic, "finished", + &context)) + goto err; + + if (!tls1_transcript_hash_value(ctx->ssl, transcript_hash, + sizeof(transcript_hash), &transcript_hash_len)) + goto err; + + if ((hmac_ctx = HMAC_CTX_new()) == NULL) + goto err; + if (!HMAC_Init_ex(hmac_ctx, finished_key.data, finished_key.len, + ctx->hash, NULL)) + goto err; + if (!HMAC_Update(hmac_ctx, transcript_hash, transcript_hash_len)) + goto err; + + verify_data_len = HMAC_size(hmac_ctx); + if (!CBB_add_space(cbb, &verify_data, verify_data_len)) + goto err; + if (!HMAC_Final(hmac_ctx, verify_data, &hlen)) + goto err; + if (hlen != verify_data_len) + goto err; + + CBS_init(&cbs, verify_data, verify_data_len); + if (!CBS_write_bytes(&cbs, ctx->hs->finished, + sizeof(ctx->hs->finished), &ctx->hs->finished_len)) + goto err; + + ret = 1; + + err: + tls13_secret_cleanup(&finished_key); + HMAC_CTX_free(hmac_ctx); + + return ret; +} + +int +tls13_client_finished_sent(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + + /* + * Any records following the client finished message must be encrypted + * using the client application traffic keys. + */ + return tls13_record_layer_set_write_traffic_key(ctx->rl, + &secrets->client_application_traffic, ssl_encryption_application); +} diff --git a/ssl/tls13_error.c b/ssl/tls13_error.c new file mode 100644 index 0000000..295b6c4 --- /dev/null +++ b/ssl/tls13_error.c @@ -0,0 +1,99 @@ +/* $OpenBSD: tls13_error.c,v 1.1 2020/01/20 13:10:37 jsing Exp $ */ +/* + * Copyright (c) 2014,2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "tls13_internal.h" + +void +tls13_error_clear(struct tls13_error *error) +{ + error->code = 0; + error->subcode = 0; + error->errnum = 0; + error->file = NULL; + error->line = 0; + free(error->msg); + error->msg = NULL; +} + +static int +tls13_error_vset(struct tls13_error *error, int code, int subcode, int errnum, + const char *file, int line, const char *fmt, va_list ap) +{ + char *errmsg = NULL; + int rv = -1; + + tls13_error_clear(error); + + error->code = code; + error->subcode = subcode; + error->errnum = errnum; + error->file = file; + error->line = line; + + if (vasprintf(&errmsg, fmt, ap) == -1) { + errmsg = NULL; + goto err; + } + + if (errnum == -1) { + error->msg = errmsg; + return 0; + } + + if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errnum)) == -1) { + error->msg = NULL; + goto err; + } + rv = 0; + + err: + free(errmsg); + + return rv; +} + +int +tls13_error_set(struct tls13_error *error, int code, int subcode, + const char *file, int line, const char *fmt, ...) +{ + va_list ap; + int errnum, rv; + + errnum = errno; + + va_start(ap, fmt); + rv = tls13_error_vset(error, code, subcode, errnum, file, line, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls13_error_setx(struct tls13_error *error, int code, int subcode, + const char *file, int line, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = tls13_error_vset(error, code, subcode, -1, file, line, fmt, ap); + va_end(ap); + + return (rv); +} diff --git a/ssl/tls13_handshake.c b/ssl/tls13_handshake.c new file mode 100644 index 0000000..9723edf --- /dev/null +++ b/ssl/tls13_handshake.c @@ -0,0 +1,721 @@ +/* $OpenBSD: tls13_handshake.c,v 1.72 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018-2021 Theo Buehler + * Copyright (c) 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" +#include "tls13_handshake.h" +#include "tls13_internal.h" + +/* Based on RFC 8446 and inspired by s2n's TLS 1.2 state machine. */ + +struct tls13_handshake_action { + uint8_t handshake_type; + uint8_t sender; + uint8_t handshake_complete; + uint8_t send_preserve_transcript_hash; + uint8_t recv_preserve_transcript_hash; + + int (*send)(struct tls13_ctx *ctx, CBB *cbb); + int (*sent)(struct tls13_ctx *ctx); + int (*recv)(struct tls13_ctx *ctx, CBS *cbs); +}; + +static enum tls13_message_type + tls13_handshake_active_state(struct tls13_ctx *ctx); + +static const struct tls13_handshake_action * + tls13_handshake_active_action(struct tls13_ctx *ctx); +static int tls13_handshake_advance_state_machine(struct tls13_ctx *ctx); + +static int tls13_handshake_send_action(struct tls13_ctx *ctx, + const struct tls13_handshake_action *action); +static int tls13_handshake_recv_action(struct tls13_ctx *ctx, + const struct tls13_handshake_action *action); + +static int tls13_handshake_set_legacy_state(struct tls13_ctx *ctx); +static int tls13_handshake_legacy_info_callback(struct tls13_ctx *ctx); + +static const struct tls13_handshake_action state_machine[] = { + [CLIENT_HELLO] = { + .handshake_type = TLS13_MT_CLIENT_HELLO, + .sender = TLS13_HS_CLIENT, + .send = tls13_client_hello_send, + .sent = tls13_client_hello_sent, + .recv = tls13_client_hello_recv, + }, + [CLIENT_HELLO_RETRY] = { + .handshake_type = TLS13_MT_CLIENT_HELLO, + .sender = TLS13_HS_CLIENT, + .send = tls13_client_hello_retry_send, + .recv = tls13_client_hello_retry_recv, + }, + [CLIENT_END_OF_EARLY_DATA] = { + .handshake_type = TLS13_MT_END_OF_EARLY_DATA, + .sender = TLS13_HS_CLIENT, + .send = tls13_client_end_of_early_data_send, + .recv = tls13_client_end_of_early_data_recv, + }, + [CLIENT_CERTIFICATE] = { + .handshake_type = TLS13_MT_CERTIFICATE, + .sender = TLS13_HS_CLIENT, + .send_preserve_transcript_hash = 1, + .send = tls13_client_certificate_send, + .recv = tls13_client_certificate_recv, + }, + [CLIENT_CERTIFICATE_VERIFY] = { + .handshake_type = TLS13_MT_CERTIFICATE_VERIFY, + .sender = TLS13_HS_CLIENT, + .recv_preserve_transcript_hash = 1, + .send = tls13_client_certificate_verify_send, + .recv = tls13_client_certificate_verify_recv, + }, + [CLIENT_FINISHED] = { + .handshake_type = TLS13_MT_FINISHED, + .sender = TLS13_HS_CLIENT, + .recv_preserve_transcript_hash = 1, + .send = tls13_client_finished_send, + .sent = tls13_client_finished_sent, + .recv = tls13_client_finished_recv, + }, + [SERVER_HELLO] = { + .handshake_type = TLS13_MT_SERVER_HELLO, + .sender = TLS13_HS_SERVER, + .send = tls13_server_hello_send, + .sent = tls13_server_hello_sent, + .recv = tls13_server_hello_recv, + }, + [SERVER_HELLO_RETRY_REQUEST] = { + .handshake_type = TLS13_MT_SERVER_HELLO, + .sender = TLS13_HS_SERVER, + .send = tls13_server_hello_retry_request_send, + .recv = tls13_server_hello_retry_request_recv, + .sent = tls13_server_hello_retry_request_sent, + }, + [SERVER_ENCRYPTED_EXTENSIONS] = { + .handshake_type = TLS13_MT_ENCRYPTED_EXTENSIONS, + .sender = TLS13_HS_SERVER, + .send = tls13_server_encrypted_extensions_send, + .recv = tls13_server_encrypted_extensions_recv, + }, + [SERVER_CERTIFICATE] = { + .handshake_type = TLS13_MT_CERTIFICATE, + .sender = TLS13_HS_SERVER, + .send_preserve_transcript_hash = 1, + .send = tls13_server_certificate_send, + .recv = tls13_server_certificate_recv, + }, + [SERVER_CERTIFICATE_REQUEST] = { + .handshake_type = TLS13_MT_CERTIFICATE_REQUEST, + .sender = TLS13_HS_SERVER, + .send = tls13_server_certificate_request_send, + .recv = tls13_server_certificate_request_recv, + }, + [SERVER_CERTIFICATE_VERIFY] = { + .handshake_type = TLS13_MT_CERTIFICATE_VERIFY, + .sender = TLS13_HS_SERVER, + .recv_preserve_transcript_hash = 1, + .send = tls13_server_certificate_verify_send, + .recv = tls13_server_certificate_verify_recv, + }, + [SERVER_FINISHED] = { + .handshake_type = TLS13_MT_FINISHED, + .sender = TLS13_HS_SERVER, + .recv_preserve_transcript_hash = 1, + .send_preserve_transcript_hash = 1, + .send = tls13_server_finished_send, + .sent = tls13_server_finished_sent, + .recv = tls13_server_finished_recv, + }, + [APPLICATION_DATA] = { + .handshake_complete = 1, + }, +}; + +const enum tls13_message_type handshakes[][TLS13_NUM_MESSAGE_TYPES] = { + [INITIAL] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + }, + [NEGOTIATED] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE_REQUEST, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_CERTIFICATE, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITHOUT_HRR] = { + CLIENT_HELLO, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE_REQUEST, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_CERTIFICATE, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITHOUT_CR] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITHOUT_HRR | WITHOUT_CR] = { + CLIENT_HELLO, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITH_PSK] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITHOUT_HRR | WITH_PSK] = { + CLIENT_HELLO, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_FINISHED, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITH_CCV] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE_REQUEST, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_CERTIFICATE, + CLIENT_CERTIFICATE_VERIFY, + CLIENT_FINISHED, + APPLICATION_DATA, + }, + [NEGOTIATED | WITHOUT_HRR | WITH_CCV] = { + CLIENT_HELLO, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE_REQUEST, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_CERTIFICATE, + CLIENT_CERTIFICATE_VERIFY, + CLIENT_FINISHED, + APPLICATION_DATA, + }, +}; + +const size_t handshake_count = sizeof(handshakes) / sizeof(handshakes[0]); + +#ifndef TLS13_DEBUG +#define DEBUGF(...) +#else +#define DEBUGF(...) fprintf(stderr, __VA_ARGS__) + +static const char * +tls13_handshake_mode_name(uint8_t mode) +{ + switch (mode) { + case TLS13_HS_CLIENT: + return "Client"; + case TLS13_HS_SERVER: + return "Server"; + } + return "Unknown"; +} + +static const char * +tls13_handshake_message_name(uint8_t msg_type) +{ + switch (msg_type) { + case TLS13_MT_CLIENT_HELLO: + return "ClientHello"; + case TLS13_MT_SERVER_HELLO: + return "ServerHello"; + case TLS13_MT_NEW_SESSION_TICKET: + return "NewSessionTicket"; + case TLS13_MT_END_OF_EARLY_DATA: + return "EndOfEarlyData"; + case TLS13_MT_ENCRYPTED_EXTENSIONS: + return "EncryptedExtensions"; + case TLS13_MT_CERTIFICATE: + return "Certificate"; + case TLS13_MT_CERTIFICATE_REQUEST: + return "CertificateRequest"; + case TLS13_MT_CERTIFICATE_VERIFY: + return "CertificateVerify"; + case TLS13_MT_FINISHED: + return "Finished"; + } + return "Unknown"; +} +#endif + +static enum tls13_message_type +tls13_handshake_active_state(struct tls13_ctx *ctx) +{ + struct tls13_handshake_stage hs = ctx->handshake_stage; + + if (hs.hs_type >= handshake_count) + return INVALID; + if (hs.message_number >= TLS13_NUM_MESSAGE_TYPES) + return INVALID; + + return handshakes[hs.hs_type][hs.message_number]; +} + +static const struct tls13_handshake_action * +tls13_handshake_active_action(struct tls13_ctx *ctx) +{ + enum tls13_message_type mt = tls13_handshake_active_state(ctx); + + if (mt == INVALID) + return NULL; + + return &state_machine[mt]; +} + +static int +tls13_handshake_advance_state_machine(struct tls13_ctx *ctx) +{ + if (++ctx->handshake_stage.message_number >= TLS13_NUM_MESSAGE_TYPES) + return 0; + + return 1; +} + +static int +tls13_handshake_end_of_flight(struct tls13_ctx *ctx, + const struct tls13_handshake_action *previous) +{ + const struct tls13_handshake_action *current; + + if ((current = tls13_handshake_active_action(ctx)) == NULL) + return 1; + + return current->sender != previous->sender; +} + +int +tls13_handshake_msg_record(struct tls13_ctx *ctx) +{ + CBS cbs; + + tls13_handshake_msg_data(ctx->hs_msg, &cbs); + return tls1_transcript_record(ctx->ssl, CBS_data(&cbs), CBS_len(&cbs)); +} + +int +tls13_handshake_perform(struct tls13_ctx *ctx) +{ + const struct tls13_handshake_action *action; + int sending; + int ret; + + if (!ctx->handshake_started) { + /* + * Set legacy state to connect/accept and call info callback + * to signal that the handshake started. + */ + if (!tls13_handshake_set_legacy_state(ctx)) + return TLS13_IO_FAILURE; + if (!tls13_handshake_legacy_info_callback(ctx)) + return TLS13_IO_FAILURE; + + ctx->handshake_started = 1; + + /* Set legacy state for initial ClientHello read or write. */ + if (!tls13_handshake_set_legacy_state(ctx)) + return TLS13_IO_FAILURE; + } + + for (;;) { + if ((action = tls13_handshake_active_action(ctx)) == NULL) + return TLS13_IO_FAILURE; + + if (ctx->need_flush) { + if ((ret = tls13_record_layer_flush(ctx->rl)) != + TLS13_IO_SUCCESS) + return ret; + ctx->need_flush = 0; + } + + if (action->handshake_complete) { + ctx->handshake_completed = 1; + tls13_record_layer_handshake_completed(ctx->rl); + + if (!tls13_handshake_set_legacy_state(ctx)) + return TLS13_IO_FAILURE; + if (!tls13_handshake_legacy_info_callback(ctx)) + return TLS13_IO_FAILURE; + + return TLS13_IO_SUCCESS; + } + + sending = action->sender == ctx->mode; + + DEBUGF("%s %s %s\n", tls13_handshake_mode_name(ctx->mode), + sending ? "sending" : "receiving", + tls13_handshake_message_name(action->handshake_type)); + + if (ctx->alert != 0) + return tls13_send_alert(ctx->rl, ctx->alert); + + if (sending) + ret = tls13_handshake_send_action(ctx, action); + else + ret = tls13_handshake_recv_action(ctx, action); + + if (ctx->alert != 0) + return tls13_send_alert(ctx->rl, ctx->alert); + + if (ret <= 0) { + DEBUGF("%s %s returned %d\n", + tls13_handshake_mode_name(ctx->mode), + (action->sender == ctx->mode) ? "send" : "recv", + ret); + return ret; + } + + if (!tls13_handshake_legacy_info_callback(ctx)) + return TLS13_IO_FAILURE; + + if (!tls13_handshake_advance_state_machine(ctx)) + return TLS13_IO_FAILURE; + + if (sending) + ctx->need_flush = tls13_handshake_end_of_flight(ctx, + action); + + if (!tls13_handshake_set_legacy_state(ctx)) + return TLS13_IO_FAILURE; + } +} + +static int +tls13_handshake_send_action(struct tls13_ctx *ctx, + const struct tls13_handshake_action *action) +{ + ssize_t ret; + CBB cbb; + + if (ctx->send_dummy_ccs) { + if ((ret = tls13_send_dummy_ccs(ctx->rl)) != TLS13_IO_SUCCESS) + return ret; + ctx->send_dummy_ccs = 0; + if (ctx->send_dummy_ccs_after) { + ctx->send_dummy_ccs_after = 0; + return TLS13_IO_SUCCESS; + } + } + + /* If we have no handshake message, we need to build one. */ + if (ctx->hs_msg == NULL) { + if ((ctx->hs_msg = tls13_handshake_msg_new()) == NULL) + return TLS13_IO_FAILURE; + if (!tls13_handshake_msg_start(ctx->hs_msg, &cbb, + action->handshake_type)) + return TLS13_IO_FAILURE; + if (!action->send(ctx, &cbb)) + return TLS13_IO_FAILURE; + if (!tls13_handshake_msg_finish(ctx->hs_msg)) + return TLS13_IO_FAILURE; + } + + if ((ret = tls13_handshake_msg_send(ctx->hs_msg, ctx->rl)) <= 0) + return ret; + + if (!tls13_handshake_msg_record(ctx)) + return TLS13_IO_FAILURE; + + if (action->send_preserve_transcript_hash) { + if (!tls1_transcript_hash_value(ctx->ssl, + ctx->hs->tls13.transcript_hash, + sizeof(ctx->hs->tls13.transcript_hash), + &ctx->hs->tls13.transcript_hash_len)) + return TLS13_IO_FAILURE; + } + + if (ctx->handshake_message_sent_cb != NULL) + ctx->handshake_message_sent_cb(ctx); + + tls13_handshake_msg_free(ctx->hs_msg); + ctx->hs_msg = NULL; + + if (action->sent != NULL && !action->sent(ctx)) + return TLS13_IO_FAILURE; + + if (ctx->send_dummy_ccs_after) { + ctx->send_dummy_ccs = 1; + if ((ret = tls13_send_dummy_ccs(ctx->rl)) != TLS13_IO_SUCCESS) + return ret; + ctx->send_dummy_ccs = 0; + ctx->send_dummy_ccs_after = 0; + } + + return TLS13_IO_SUCCESS; +} + +static int +tls13_handshake_recv_action(struct tls13_ctx *ctx, + const struct tls13_handshake_action *action) +{ + uint8_t msg_type; + ssize_t ret; + CBS cbs; + + if (ctx->hs_msg == NULL) { + if ((ctx->hs_msg = tls13_handshake_msg_new()) == NULL) + return TLS13_IO_FAILURE; + } + + if ((ret = tls13_handshake_msg_recv(ctx->hs_msg, ctx->rl)) <= 0) + return ret; + + if (action->recv_preserve_transcript_hash) { + if (!tls1_transcript_hash_value(ctx->ssl, + ctx->hs->tls13.transcript_hash, + sizeof(ctx->hs->tls13.transcript_hash), + &ctx->hs->tls13.transcript_hash_len)) + return TLS13_IO_FAILURE; + } + + if (!tls13_handshake_msg_record(ctx)) + return TLS13_IO_FAILURE; + + if (ctx->handshake_message_recv_cb != NULL) + ctx->handshake_message_recv_cb(ctx); + + /* + * In TLSv1.3 there is no way to know if you're going to receive a + * certificate request message or not, hence we have to special case it + * here. The receive handler also knows how to deal with this situation. + */ + msg_type = tls13_handshake_msg_type(ctx->hs_msg); + if (msg_type != action->handshake_type && + (msg_type != TLS13_MT_CERTIFICATE || + action->handshake_type != TLS13_MT_CERTIFICATE_REQUEST)) + return tls13_send_alert(ctx->rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + + if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs)) + return TLS13_IO_FAILURE; + + ret = TLS13_IO_FAILURE; + if (action->recv(ctx, &cbs)) { + if (CBS_len(&cbs) != 0) { + tls13_set_errorx(ctx, TLS13_ERR_TRAILING_DATA, 0, + "trailing data in handshake message", NULL); + ctx->alert = TLS13_ALERT_DECODE_ERROR; + } else { + ret = TLS13_IO_SUCCESS; + } + } + + tls13_handshake_msg_free(ctx->hs_msg); + ctx->hs_msg = NULL; + + if (ctx->ssl->method->version < TLS1_3_VERSION) + return TLS13_IO_USE_LEGACY; + + return ret; +} + +struct tls13_handshake_legacy_state { + int recv; + int send; +}; + +static const struct tls13_handshake_legacy_state legacy_states[] = { + [CLIENT_HELLO] = { + .recv = SSL3_ST_SR_CLNT_HELLO_A, + .send = SSL3_ST_CW_CLNT_HELLO_A, + }, + [SERVER_HELLO_RETRY_REQUEST] = { + .recv = SSL3_ST_CR_SRVR_HELLO_A, + .send = SSL3_ST_SW_SRVR_HELLO_A, + }, + [CLIENT_HELLO_RETRY] = { + .recv = SSL3_ST_SR_CLNT_HELLO_A, + .send = SSL3_ST_CW_CLNT_HELLO_A, + }, + [SERVER_HELLO] = { + .recv = SSL3_ST_CR_SRVR_HELLO_A, + .send = SSL3_ST_SW_SRVR_HELLO_A, + }, + [SERVER_ENCRYPTED_EXTENSIONS] = { + .send = 0, + .recv = 0, + }, + [SERVER_CERTIFICATE_REQUEST] = { + .recv = SSL3_ST_CR_CERT_REQ_A, + .send = SSL3_ST_SW_CERT_REQ_A, + }, + [SERVER_CERTIFICATE] = { + .recv = SSL3_ST_CR_CERT_A, + .send = SSL3_ST_SW_CERT_A, + }, + [SERVER_CERTIFICATE_VERIFY] = { + .send = 0, + .recv = 0, + }, + [SERVER_FINISHED] = { + .recv = SSL3_ST_CR_FINISHED_A, + .send = SSL3_ST_SW_FINISHED_A, + }, + [CLIENT_END_OF_EARLY_DATA] = { + .send = 0, + .recv = 0, + }, + [CLIENT_CERTIFICATE] = { + .recv = SSL3_ST_SR_CERT_VRFY_A, + .send = SSL3_ST_CW_CERT_VRFY_B, + }, + [CLIENT_CERTIFICATE_VERIFY] = { + .send = 0, + .recv = 0, + }, + [CLIENT_FINISHED] = { + .recv = SSL3_ST_SR_FINISHED_A, + .send = SSL3_ST_CW_FINISHED_A, + }, + [APPLICATION_DATA] = { + .recv = 0, + .send = 0, + }, +}; + +CTASSERT(sizeof(state_machine) / sizeof(state_machine[0]) == + sizeof(legacy_states) / sizeof(legacy_states[0])); + +static int +tls13_handshake_legacy_state(struct tls13_ctx *ctx, int *out_state) +{ + const struct tls13_handshake_action *action; + enum tls13_message_type mt; + + *out_state = 0; + + if (!ctx->handshake_started) { + if (ctx->mode == TLS13_HS_CLIENT) + *out_state = SSL_ST_CONNECT; + else + *out_state = SSL_ST_ACCEPT; + + return 1; + } + + if (ctx->handshake_completed) { + *out_state = SSL_ST_OK; + return 1; + } + + if ((mt = tls13_handshake_active_state(ctx)) == INVALID) + return 0; + + if ((action = tls13_handshake_active_action(ctx)) == NULL) + return 0; + + if (action->sender == ctx->mode) + *out_state = legacy_states[mt].send; + else + *out_state = legacy_states[mt].recv; + + return 1; +} + +static int +tls13_handshake_info_position(struct tls13_ctx *ctx) +{ + if (!ctx->handshake_started) + return TLS13_INFO_HANDSHAKE_STARTED; + + if (ctx->handshake_completed) + return TLS13_INFO_HANDSHAKE_COMPLETED; + + if (ctx->mode == TLS13_HS_CLIENT) + return TLS13_INFO_CONNECT_LOOP; + else + return TLS13_INFO_ACCEPT_LOOP; +} + +static int +tls13_handshake_legacy_info_callback(struct tls13_ctx *ctx) +{ + int state, where; + + if (!tls13_handshake_legacy_state(ctx, &state)) + return 0; + + /* Do nothing if there's no corresponding legacy state. */ + if (state == 0) + return 1; + + if (ctx->info_cb != NULL) { + where = tls13_handshake_info_position(ctx); + ctx->info_cb(ctx, where, 1); + } + + return 1; +} + +static int +tls13_handshake_set_legacy_state(struct tls13_ctx *ctx) +{ + int state; + + if (!tls13_handshake_legacy_state(ctx, &state)) + return 0; + + /* Do nothing if there's no corresponding legacy state. */ + if (state == 0) + return 1; + + ctx->hs->state = state; + + return 1; +} diff --git a/ssl/tls13_handshake.h b/ssl/tls13_handshake.h new file mode 100644 index 0000000..8a08b9f --- /dev/null +++ b/ssl/tls13_handshake.h @@ -0,0 +1,54 @@ +/* $OpenBSD: tls13_handshake.h,v 1.5 2020/04/22 17:05:07 jsing Exp $ */ +/* + * Copyright (c) 2019 Theo Buehler + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS13_HANDSHAKE_H +#define HEADER_TLS13_HANDSHAKE_H + +#include /* for NULL */ + +__BEGIN_HIDDEN_DECLS + +#define INITIAL 0x00 +#define NEGOTIATED 0x01 +#define WITHOUT_HRR 0x02 +#define WITHOUT_CR 0x04 +#define WITH_PSK 0x08 +#define WITH_CCV 0x10 +#define WITH_0RTT 0x20 + +enum tls13_message_type { + INVALID, + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + SERVER_ENCRYPTED_EXTENSIONS, + SERVER_CERTIFICATE_REQUEST, + SERVER_CERTIFICATE, + SERVER_CERTIFICATE_VERIFY, + SERVER_FINISHED, + CLIENT_END_OF_EARLY_DATA, + CLIENT_CERTIFICATE, + CLIENT_CERTIFICATE_VERIFY, + CLIENT_FINISHED, + APPLICATION_DATA, + TLS13_NUM_MESSAGE_TYPES, +}; + +__END_HIDDEN_DECLS + +#endif /* !HEADER_TLS13_HANDSHAKE_H */ diff --git a/ssl/tls13_handshake_msg.c b/ssl/tls13_handshake_msg.c new file mode 100644 index 0000000..134cfb2 --- /dev/null +++ b/ssl/tls13_handshake_msg.c @@ -0,0 +1,188 @@ +/* $OpenBSD: tls13_handshake_msg.c,v 1.6 2022/07/22 19:33:53 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bytestring.h" +#include "tls13_internal.h" + +#define TLS13_HANDSHAKE_MSG_HEADER_LEN 4 +#define TLS13_HANDSHAKE_MSG_INITIAL_LEN 256 +#define TLS13_HANDSHAKE_MSG_MAX_LEN (256 * 1024) + +struct tls13_handshake_msg { + uint8_t msg_type; + uint32_t msg_len; + uint8_t *data; + size_t data_len; + + struct tls_buffer *buf; + CBS cbs; + CBB cbb; +}; + +struct tls13_handshake_msg * +tls13_handshake_msg_new() +{ + struct tls13_handshake_msg *msg = NULL; + + if ((msg = calloc(1, sizeof(struct tls13_handshake_msg))) == NULL) + goto err; + if ((msg->buf = tls_buffer_new(0)) == NULL) + goto err; + + return msg; + + err: + tls13_handshake_msg_free(msg); + + return NULL; +} + +void +tls13_handshake_msg_free(struct tls13_handshake_msg *msg) +{ + if (msg == NULL) + return; + + tls_buffer_free(msg->buf); + + CBB_cleanup(&msg->cbb); + + freezero(msg->data, msg->data_len); + freezero(msg, sizeof(struct tls13_handshake_msg)); +} + +void +tls13_handshake_msg_data(struct tls13_handshake_msg *msg, CBS *cbs) +{ + CBS_init(cbs, msg->data, msg->data_len); +} + +uint8_t +tls13_handshake_msg_type(struct tls13_handshake_msg *msg) +{ + return msg->msg_type; +} + +int +tls13_handshake_msg_content(struct tls13_handshake_msg *msg, CBS *cbs) +{ + tls13_handshake_msg_data(msg, cbs); + + return CBS_skip(cbs, TLS13_HANDSHAKE_MSG_HEADER_LEN); +} + +int +tls13_handshake_msg_start(struct tls13_handshake_msg *msg, CBB *body, + uint8_t msg_type) +{ + if (!CBB_init(&msg->cbb, TLS13_HANDSHAKE_MSG_INITIAL_LEN)) + return 0; + if (!CBB_add_u8(&msg->cbb, msg_type)) + return 0; + if (!CBB_add_u24_length_prefixed(&msg->cbb, body)) + return 0; + + return 1; +} + +int +tls13_handshake_msg_finish(struct tls13_handshake_msg *msg) +{ + if (!CBB_finish(&msg->cbb, &msg->data, &msg->data_len)) + return 0; + + CBS_init(&msg->cbs, msg->data, msg->data_len); + + return 1; +} + +static ssize_t +tls13_handshake_msg_read_cb(void *buf, size_t n, void *cb_arg) +{ + struct tls13_record_layer *rl = cb_arg; + + return tls13_read_handshake_data(rl, buf, n); +} + +int +tls13_handshake_msg_recv(struct tls13_handshake_msg *msg, + struct tls13_record_layer *rl) +{ + uint8_t msg_type; + uint32_t msg_len; + CBS cbs; + int ret; + + if (msg->data != NULL) + return TLS13_IO_FAILURE; + + if (msg->msg_type == 0) { + if ((ret = tls_buffer_extend(msg->buf, + TLS13_HANDSHAKE_MSG_HEADER_LEN, + tls13_handshake_msg_read_cb, rl)) <= 0) + return ret; + + if (!tls_buffer_data(msg->buf, &cbs)) + return TLS13_IO_FAILURE; + + if (!CBS_get_u8(&cbs, &msg_type)) + return TLS13_IO_FAILURE; + if (!CBS_get_u24(&cbs, &msg_len)) + return TLS13_IO_FAILURE; + + /* XXX - do we want to make this variable on message type? */ + if (msg_len > TLS13_HANDSHAKE_MSG_MAX_LEN) + return TLS13_IO_FAILURE; + + msg->msg_type = msg_type; + msg->msg_len = msg_len; + } + + if ((ret = tls_buffer_extend(msg->buf, + TLS13_HANDSHAKE_MSG_HEADER_LEN + msg->msg_len, + tls13_handshake_msg_read_cb, rl)) <= 0) + return ret; + + if (!tls_buffer_finish(msg->buf, &msg->data, &msg->data_len)) + return TLS13_IO_FAILURE; + + return TLS13_IO_SUCCESS; +} + +int +tls13_handshake_msg_send(struct tls13_handshake_msg *msg, + struct tls13_record_layer *rl) +{ + ssize_t ret; + + if (msg->data == NULL) + return TLS13_IO_FAILURE; + + if (CBS_len(&msg->cbs) == 0) + return TLS13_IO_FAILURE; + + while (CBS_len(&msg->cbs) > 0) { + if ((ret = tls13_write_handshake_data(rl, CBS_data(&msg->cbs), + CBS_len(&msg->cbs))) <= 0) + return ret; + + if (!CBS_skip(&msg->cbs, ret)) + return TLS13_IO_FAILURE; + } + + return TLS13_IO_SUCCESS; +} diff --git a/ssl/tls13_internal.h b/ssl/tls13_internal.h new file mode 100644 index 0000000..f4b17bd --- /dev/null +++ b/ssl/tls13_internal.h @@ -0,0 +1,443 @@ +/* $OpenBSD: tls13_internal.h,v 1.101 2022/07/24 14:28:16 jsing Exp $ */ +/* + * Copyright (c) 2018 Bob Beck + * Copyright (c) 2018 Theo Buehler + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS13_INTERNAL_H +#define HEADER_TLS13_INTERNAL_H + +#include +#include + +#include "bytestring.h" +#include "tls_internal.h" + +__BEGIN_HIDDEN_DECLS + +#define TLS13_HS_CLIENT 1 +#define TLS13_HS_SERVER 2 + +#define TLS13_IO_SUCCESS 1 +#define TLS13_IO_EOF 0 +#define TLS13_IO_FAILURE -1 +#define TLS13_IO_ALERT -2 +#define TLS13_IO_WANT_POLLIN -3 +#define TLS13_IO_WANT_POLLOUT -4 +#define TLS13_IO_WANT_RETRY -5 /* Retry the previous call immediately. */ +#define TLS13_IO_USE_LEGACY -6 +#define TLS13_IO_RECORD_VERSION -7 +#define TLS13_IO_RECORD_OVERFLOW -8 + +#define TLS13_ERR_VERIFY_FAILED 16 +#define TLS13_ERR_HRR_FAILED 17 +#define TLS13_ERR_TRAILING_DATA 18 +#define TLS13_ERR_NO_SHARED_CIPHER 19 +#define TLS13_ERR_NO_CERTIFICATE 20 +#define TLS13_ERR_NO_PEER_CERTIFICATE 21 + +#define TLS13_ALERT_LEVEL_WARNING 1 +#define TLS13_ALERT_LEVEL_FATAL 2 + +#define TLS13_ALERT_CLOSE_NOTIFY 0 +#define TLS13_ALERT_UNEXPECTED_MESSAGE 10 +#define TLS13_ALERT_BAD_RECORD_MAC 20 +#define TLS13_ALERT_RECORD_OVERFLOW 22 +#define TLS13_ALERT_HANDSHAKE_FAILURE 40 +#define TLS13_ALERT_BAD_CERTIFICATE 42 +#define TLS13_ALERT_UNSUPPORTED_CERTIFICATE 43 +#define TLS13_ALERT_CERTIFICATE_REVOKED 44 +#define TLS13_ALERT_CERTIFICATE_EXPIRED 45 +#define TLS13_ALERT_CERTIFICATE_UNKNOWN 46 +#define TLS13_ALERT_ILLEGAL_PARAMETER 47 +#define TLS13_ALERT_UNKNOWN_CA 48 +#define TLS13_ALERT_ACCESS_DENIED 49 +#define TLS13_ALERT_DECODE_ERROR 50 +#define TLS13_ALERT_DECRYPT_ERROR 51 +#define TLS13_ALERT_PROTOCOL_VERSION 70 +#define TLS13_ALERT_INSUFFICIENT_SECURITY 71 +#define TLS13_ALERT_INTERNAL_ERROR 80 +#define TLS13_ALERT_INAPPROPRIATE_FALLBACK 86 +#define TLS13_ALERT_USER_CANCELED 90 +#define TLS13_ALERT_MISSING_EXTENSION 109 +#define TLS13_ALERT_UNSUPPORTED_EXTENSION 110 +#define TLS13_ALERT_UNRECOGNIZED_NAME 112 +#define TLS13_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 +#define TLS13_ALERT_UNKNOWN_PSK_IDENTITY 115 +#define TLS13_ALERT_CERTIFICATE_REQUIRED 116 +#define TLS13_ALERT_NO_APPLICATION_PROTOCOL 120 + +#define TLS13_INFO_HANDSHAKE_STARTED SSL_CB_HANDSHAKE_START +#define TLS13_INFO_HANDSHAKE_COMPLETED SSL_CB_HANDSHAKE_DONE +#define TLS13_INFO_ACCEPT_LOOP SSL_CB_ACCEPT_LOOP +#define TLS13_INFO_CONNECT_LOOP SSL_CB_CONNECT_LOOP +#define TLS13_INFO_ACCEPT_EXIT SSL_CB_ACCEPT_EXIT +#define TLS13_INFO_CONNECT_EXIT SSL_CB_CONNECT_EXIT + +typedef void (*tls13_alert_cb)(uint8_t _alert_desc, void *_cb_arg); +typedef ssize_t (*tls13_phh_recv_cb)(void *_cb_arg); +typedef void (*tls13_phh_sent_cb)(void *_cb_arg); +typedef void (*tls13_handshake_message_cb)(void *_cb_arg); +typedef void (*tls13_info_cb)(void *_cb_arg, int _state, int _ret); +typedef int (*tls13_ocsp_status_cb)(void *_cb_arg); + +/* + * PSK support. + */ + +/* + * Known PskKeyExchangeMode values. + * https://www.iana.org/assignments/tls-parameters/#tls-pskkeyexchangemode + */ +#define TLS13_PSK_KE 0 +#define TLS13_PSK_DHE_KE 1 + +/* + * Secrets. + */ +struct tls13_secret { + uint8_t *data; + size_t len; +}; + +/* RFC 8446 Section 7.1 Page 92 */ +struct tls13_secrets { + const EVP_MD *digest; + int resumption; + int init_done; + int early_done; + int handshake_done; + int schedule_done; + int insecure; /* Set by tests */ + struct tls13_secret zeros; + struct tls13_secret empty_hash; + struct tls13_secret extracted_early; + struct tls13_secret binder_key; + struct tls13_secret client_early_traffic; + struct tls13_secret early_exporter_master; + struct tls13_secret derived_early; + struct tls13_secret extracted_handshake; + struct tls13_secret client_handshake_traffic; + struct tls13_secret server_handshake_traffic; + struct tls13_secret derived_handshake; + struct tls13_secret extracted_master; + struct tls13_secret client_application_traffic; + struct tls13_secret server_application_traffic; + struct tls13_secret exporter_master; + struct tls13_secret resumption_master; +}; + +int tls13_secret_init(struct tls13_secret *secret, size_t len); +void tls13_secret_cleanup(struct tls13_secret *secret); +struct tls13_secrets *tls13_secrets_create(const EVP_MD *digest, + int resumption); +void tls13_secrets_destroy(struct tls13_secrets *secrets); + +int tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, + const struct tls13_secret *secret, const char *label, + const struct tls13_secret *context); +int tls13_hkdf_expand_label_with_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context); + +int tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, + const struct tls13_secret *secret, const char *label, + const struct tls13_secret *context); +int tls13_derive_secret_with_label_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context); + +int tls13_derive_early_secrets(struct tls13_secrets *secrets, uint8_t *psk, + size_t psk_len, const struct tls13_secret *context); +int tls13_derive_handshake_secrets(struct tls13_secrets *secrets, + const uint8_t *ecdhe, size_t ecdhe_len, const struct tls13_secret *context); +int tls13_derive_application_secrets(struct tls13_secrets *secrets, + const struct tls13_secret *context); +int tls13_update_client_traffic_secret(struct tls13_secrets *secrets); +int tls13_update_server_traffic_secret(struct tls13_secrets *secrets); + +/* + * Record Layer. + */ +struct tls13_record_layer; + +struct tls13_record_layer_callbacks { + /* Wire callbacks. */ + tls_read_cb wire_read; + tls_write_cb wire_write; + tls_flush_cb wire_flush; + + /* Interceptors. */ + tls_handshake_read_cb handshake_read; + tls_handshake_write_cb handshake_write; + tls_traffic_key_cb set_read_traffic_key; + tls_traffic_key_cb set_write_traffic_key; + tls_alert_send_cb alert_send; + + /* Notification callbacks. */ + tls13_alert_cb alert_recv; + tls13_alert_cb alert_sent; + tls13_phh_recv_cb phh_recv; + tls13_phh_sent_cb phh_sent; +}; + +struct tls13_record_layer *tls13_record_layer_new( + const struct tls13_record_layer_callbacks *callbacks, void *cb_arg); +void tls13_record_layer_free(struct tls13_record_layer *rl); +void tls13_record_layer_set_callbacks(struct tls13_record_layer *rl, + const struct tls13_record_layer_callbacks *callbacks, void *cb_arg); +void tls13_record_layer_allow_ccs(struct tls13_record_layer *rl, int allow); +void tls13_record_layer_allow_legacy_alerts(struct tls13_record_layer *rl, int allow); +void tls13_record_layer_rcontent(struct tls13_record_layer *rl, CBS *cbs); +void tls13_record_layer_set_aead(struct tls13_record_layer *rl, + const EVP_AEAD *aead); +void tls13_record_layer_set_hash(struct tls13_record_layer *rl, + const EVP_MD *hash); +void tls13_record_layer_set_legacy_version(struct tls13_record_layer *rl, + uint16_t version); +void tls13_record_layer_set_retry_after_phh(struct tls13_record_layer *rl, int retry); +void tls13_record_layer_handshake_completed(struct tls13_record_layer *rl); +int tls13_record_layer_set_read_traffic_key(struct tls13_record_layer *rl, + struct tls13_secret *read_key, enum ssl_encryption_level_t read_level); +int tls13_record_layer_set_write_traffic_key(struct tls13_record_layer *rl, + struct tls13_secret *write_key, enum ssl_encryption_level_t write_level); +ssize_t tls13_record_layer_send_pending(struct tls13_record_layer *rl); +ssize_t tls13_record_layer_phh(struct tls13_record_layer *rl, CBS *cbs); +ssize_t tls13_record_layer_flush(struct tls13_record_layer *rl); + +ssize_t tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); +ssize_t tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf, + size_t n); +ssize_t tls13_pending_application_data(struct tls13_record_layer *rl); +ssize_t tls13_peek_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); +ssize_t tls13_read_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n); +ssize_t tls13_write_application_data(struct tls13_record_layer *rl, const uint8_t *buf, + size_t n); + +ssize_t tls13_send_alert(struct tls13_record_layer *rl, uint8_t alert_desc); +ssize_t tls13_send_dummy_ccs(struct tls13_record_layer *rl); + +/* + * Handshake Messages. + */ +struct tls13_handshake_msg; + +struct tls13_handshake_msg *tls13_handshake_msg_new(void); +void tls13_handshake_msg_free(struct tls13_handshake_msg *msg); +void tls13_handshake_msg_data(struct tls13_handshake_msg *msg, CBS *cbs); +uint8_t tls13_handshake_msg_type(struct tls13_handshake_msg *msg); +int tls13_handshake_msg_content(struct tls13_handshake_msg *msg, CBS *cbs); +int tls13_handshake_msg_start(struct tls13_handshake_msg *msg, CBB *body, + uint8_t msg_type); +int tls13_handshake_msg_finish(struct tls13_handshake_msg *msg); +int tls13_handshake_msg_recv(struct tls13_handshake_msg *msg, + struct tls13_record_layer *rl); +int tls13_handshake_msg_send(struct tls13_handshake_msg *msg, + struct tls13_record_layer *rl); + +struct tls13_handshake_stage { + uint8_t hs_type; + uint8_t message_number; +}; + +struct ssl_handshake_tls13_st; + +struct tls13_error { + int code; + int subcode; + int errnum; + const char *file; + int line; + char *msg; +}; + +struct tls13_ctx { + struct tls13_error error; + + SSL *ssl; + struct ssl_handshake_st *hs; + uint8_t mode; + struct tls13_handshake_stage handshake_stage; + int handshake_started; + int handshake_completed; + int need_flush; + int middlebox_compat; + int send_dummy_ccs; + int send_dummy_ccs_after; + + int close_notify_sent; + int close_notify_recv; + + const EVP_AEAD *aead; + const EVP_MD *hash; + + struct tls13_record_layer *rl; + struct tls13_handshake_msg *hs_msg; + uint8_t key_update_request; + uint8_t alert; + int phh_count; + time_t phh_last_seen; + + tls13_handshake_message_cb handshake_message_sent_cb; + tls13_handshake_message_cb handshake_message_recv_cb; + tls13_info_cb info_cb; + tls13_ocsp_status_cb ocsp_status_recv_cb; +}; +#ifndef TLS13_PHH_LIMIT_TIME +#define TLS13_PHH_LIMIT_TIME 3600 +#endif +#ifndef TLS13_PHH_LIMIT +#define TLS13_PHH_LIMIT 100 +#endif + +struct tls13_ctx *tls13_ctx_new(int mode, SSL *ssl); +void tls13_ctx_free(struct tls13_ctx *ctx); + +const EVP_AEAD *tls13_cipher_aead(const SSL_CIPHER *cipher); +const EVP_MD *tls13_cipher_hash(const SSL_CIPHER *cipher); + +void tls13_alert_received_cb(uint8_t alert_desc, void *arg); +void tls13_alert_sent_cb(uint8_t alert_desc, void *arg); +ssize_t tls13_phh_received_cb(void *cb_arg); +void tls13_phh_done_cb(void *cb_arg); + +int tls13_quic_init(struct tls13_ctx *ctx); + +/* + * Legacy interfaces. + */ +int tls13_use_legacy_client(struct tls13_ctx *ctx); +int tls13_use_legacy_server(struct tls13_ctx *ctx); +int tls13_legacy_accept(SSL *ssl); +int tls13_legacy_connect(SSL *ssl); +int tls13_legacy_return_code(SSL *ssl, ssize_t ret); +ssize_t tls13_legacy_wire_read_cb(void *buf, size_t n, void *arg); +ssize_t tls13_legacy_wire_write_cb(const void *buf, size_t n, void *arg); +ssize_t tls13_legacy_wire_flush_cb(void *arg); +int tls13_legacy_pending(const SSL *ssl); +int tls13_legacy_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, + int peek); +int tls13_legacy_write_bytes(SSL *ssl, int type, const void *buf, int len); +int tls13_legacy_shutdown(SSL *ssl); +int tls13_legacy_servername_process(struct tls13_ctx *ctx, uint8_t *alert); + +/* + * Message Types - RFC 8446, Section B.3. + * + * Values listed as "_RESERVED" were used in previous versions of TLS and are + * listed here for completeness. TLS 1.3 implementations MUST NOT send them but + * might receive them from older TLS implementations. + */ +#define TLS13_MT_HELLO_REQUEST_RESERVED 0 +#define TLS13_MT_CLIENT_HELLO 1 +#define TLS13_MT_SERVER_HELLO 2 +#define TLS13_MT_HELLO_VERIFY_REQUEST_RESERVED 3 +#define TLS13_MT_NEW_SESSION_TICKET 4 +#define TLS13_MT_END_OF_EARLY_DATA 5 +#define TLS13_MT_HELLO_RETRY_REQUEST_RESERVED 6 +#define TLS13_MT_ENCRYPTED_EXTENSIONS 8 +#define TLS13_MT_CERTIFICATE 11 +#define TLS13_MT_SERVER_KEY_EXCHANGE_RESERVED 12 +#define TLS13_MT_CERTIFICATE_REQUEST 13 +#define TLS13_MT_SERVER_HELLO_DONE_RESERVED 14 +#define TLS13_MT_CERTIFICATE_VERIFY 15 +#define TLS13_MT_CLIENT_KEY_EXCHANGE_RESERVED 16 +#define TLS13_MT_FINISHED 20 +#define TLS13_MT_CERTIFICATE_URL_RESERVED 21 +#define TLS13_MT_CERTIFICATE_STATUS_RESERVED 22 +#define TLS13_MT_SUPPLEMENTAL_DATA_RESERVED 23 +#define TLS13_MT_KEY_UPDATE 24 +#define TLS13_MT_MESSAGE_HASH 254 + +int tls13_handshake_msg_record(struct tls13_ctx *ctx); +int tls13_handshake_perform(struct tls13_ctx *ctx); + +int tls13_client_init(struct tls13_ctx *ctx); +int tls13_server_init(struct tls13_ctx *ctx); +int tls13_client_connect(struct tls13_ctx *ctx); +int tls13_server_accept(struct tls13_ctx *ctx); + +int tls13_client_hello_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_hello_sent(struct tls13_ctx *ctx); +int tls13_client_hello_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_hello_retry_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_hello_retry_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_end_of_early_data_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_end_of_early_data_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_certificate_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_finished_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_client_finished_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_client_finished_sent(struct tls13_ctx *ctx); +int tls13_server_hello_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_hello_sent(struct tls13_ctx *ctx); +int tls13_server_hello_retry_request_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_hello_retry_request_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_hello_retry_request_sent(struct tls13_ctx *ctx); +int tls13_server_encrypted_extensions_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_encrypted_extensions_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_certificate_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_certificate_request_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_certificate_request_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_finished_recv(struct tls13_ctx *ctx, CBS *cbs); +int tls13_server_finished_send(struct tls13_ctx *ctx, CBB *cbb); +int tls13_server_finished_sent(struct tls13_ctx *ctx); + +void tls13_error_clear(struct tls13_error *error); +int tls13_cert_add(struct tls13_ctx *ctx, CBB *cbb, X509 *cert, + int(*build_extensions)(SSL *s, uint16_t msg_type, CBB *cbb)); + +int tls13_synthetic_handshake_message(struct tls13_ctx *ctx); +int tls13_clienthello_hash_init(struct tls13_ctx *ctx); +void tls13_clienthello_hash_clear(struct ssl_handshake_tls13_st *hs); +int tls13_clienthello_hash_update_bytes(struct tls13_ctx *ctx, void *data, + size_t len); +int tls13_clienthello_hash_update(struct tls13_ctx *ctx, CBS *cbs); +int tls13_clienthello_hash_finalize(struct tls13_ctx *ctx); +int tls13_clienthello_hash_validate(struct tls13_ctx *ctx); + +int tls13_error_set(struct tls13_error *error, int code, int subcode, + const char *file, int line, const char *fmt, ...); +int tls13_error_setx(struct tls13_error *error, int code, int subcode, + const char *file, int line, const char *fmt, ...); + +#define tls13_set_error(ctx, code, subcode, fmt, ...) \ + tls13_error_set(&(ctx)->error, (code), (subcode), __FILE__, __LINE__, \ + (fmt), __VA_ARGS__) +#define tls13_set_errorx(ctx, code, subcode, fmt, ...) \ + tls13_error_setx(&(ctx)->error, (code), (subcode), __FILE__, __LINE__, \ + (fmt), __VA_ARGS__) + +int tls13_exporter(struct tls13_ctx *ctx, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, uint8_t *out, + size_t out_len); + +extern const uint8_t tls13_downgrade_12[8]; +extern const uint8_t tls13_downgrade_11[8]; +extern const uint8_t tls13_hello_retry_request_hash[32]; +extern const uint8_t tls13_cert_verify_pad[64]; +extern const uint8_t tls13_cert_client_verify_context[]; +extern const uint8_t tls13_cert_server_verify_context[]; + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls13_key_schedule.c b/ssl/tls13_key_schedule.c new file mode 100644 index 0000000..05bcf0f --- /dev/null +++ b/ssl/tls13_key_schedule.c @@ -0,0 +1,458 @@ +/* $OpenBSD: tls13_key_schedule.c,v 1.18 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018, Bob Beck + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "tls13_internal.h" + +int +tls13_secret_init(struct tls13_secret *secret, size_t len) +{ + if (secret->data != NULL) + return 0; + + if ((secret->data = calloc(1, len)) == NULL) + return 0; + secret->len = len; + + return 1; +} + +void +tls13_secret_cleanup(struct tls13_secret *secret) +{ + freezero(secret->data, secret->len); + secret->data = NULL; + secret->len = 0; +} + +/* + * Allocate a set of secrets for a key schedule using + * a size of hash_length from RFC 8446 section 7.1. + */ +struct tls13_secrets * +tls13_secrets_create(const EVP_MD *digest, int resumption) +{ + struct tls13_secrets *secrets = NULL; + EVP_MD_CTX *mdctx = NULL; + unsigned int mdlen; + size_t hash_length; + + hash_length = EVP_MD_size(digest); + + if ((secrets = calloc(1, sizeof(struct tls13_secrets))) == NULL) + goto err; + + if (!tls13_secret_init(&secrets->zeros, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->empty_hash, hash_length)) + goto err; + + if (!tls13_secret_init(&secrets->extracted_early, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->binder_key, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->client_early_traffic, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->early_exporter_master, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->derived_early, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->extracted_handshake, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->client_handshake_traffic, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->server_handshake_traffic, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->derived_handshake, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->extracted_master, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->client_application_traffic, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->server_application_traffic, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->exporter_master, hash_length)) + goto err; + if (!tls13_secret_init(&secrets->resumption_master, hash_length)) + goto err; + + /* + * Calculate the hash of a zero-length string - this is needed during + * the "derived" step for key extraction. + */ + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestInit_ex(mdctx, digest, NULL)) + goto err; + if (!EVP_DigestUpdate(mdctx, secrets->zeros.data, 0)) + goto err; + if (!EVP_DigestFinal_ex(mdctx, secrets->empty_hash.data, &mdlen)) + goto err; + EVP_MD_CTX_free(mdctx); + mdctx = NULL; + + if (secrets->empty_hash.len != mdlen) + goto err; + + secrets->digest = digest; + secrets->resumption = resumption; + secrets->init_done = 1; + + return secrets; + + err: + tls13_secrets_destroy(secrets); + EVP_MD_CTX_free(mdctx); + + return NULL; +} + +void +tls13_secrets_destroy(struct tls13_secrets *secrets) +{ + if (secrets == NULL) + return; + + /* you can never be too sure :) */ + tls13_secret_cleanup(&secrets->zeros); + tls13_secret_cleanup(&secrets->empty_hash); + + tls13_secret_cleanup(&secrets->extracted_early); + tls13_secret_cleanup(&secrets->binder_key); + tls13_secret_cleanup(&secrets->client_early_traffic); + tls13_secret_cleanup(&secrets->early_exporter_master); + tls13_secret_cleanup(&secrets->derived_early); + tls13_secret_cleanup(&secrets->extracted_handshake); + tls13_secret_cleanup(&secrets->client_handshake_traffic); + tls13_secret_cleanup(&secrets->server_handshake_traffic); + tls13_secret_cleanup(&secrets->derived_handshake); + tls13_secret_cleanup(&secrets->extracted_master); + tls13_secret_cleanup(&secrets->client_application_traffic); + tls13_secret_cleanup(&secrets->server_application_traffic); + tls13_secret_cleanup(&secrets->exporter_master); + tls13_secret_cleanup(&secrets->resumption_master); + + freezero(secrets, sizeof(struct tls13_secrets)); +} + +int +tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, + const struct tls13_secret *secret, const char *label, + const struct tls13_secret *context) +{ + return tls13_hkdf_expand_label_with_length(out, digest, secret, label, + strlen(label), context); +} + +int +tls13_hkdf_expand_label_with_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context) +{ + const char tls13_plabel[] = "tls13 "; + uint8_t *hkdf_label = NULL; + size_t hkdf_label_len; + CBB cbb, child; + int ret; + + if (!CBB_init(&cbb, 256)) + goto err; + + if (out->data == NULL || out->len == 0) + goto err; + + if (!CBB_add_u16(&cbb, out->len)) + goto err; + if (!CBB_add_u8_length_prefixed(&cbb, &child)) + goto err; + if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel))) + goto err; + if (!CBB_add_bytes(&child, label, label_len)) + goto err; + if (!CBB_add_u8_length_prefixed(&cbb, &child)) + goto err; + if (!CBB_add_bytes(&child, context->data, context->len)) + goto err; + if (!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) + goto err; + + ret = HKDF_expand(out->data, out->len, digest, secret->data, + secret->len, hkdf_label, hkdf_label_len); + + free(hkdf_label); + return(ret); + err: + CBB_cleanup(&cbb); + return(0); +} + +int +tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, + const struct tls13_secret *secret, const char *label, + const struct tls13_secret *context) +{ + return tls13_hkdf_expand_label(out, digest, secret, label, context); +} + +int +tls13_derive_secret_with_label_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, const uint8_t *label, + size_t label_len, const struct tls13_secret *context) +{ + return tls13_hkdf_expand_label_with_length(out, digest, secret, label, + label_len, context); +} + +int +tls13_derive_early_secrets(struct tls13_secrets *secrets, + uint8_t *psk, size_t psk_len, const struct tls13_secret *context) +{ + if (!secrets->init_done || secrets->early_done) + return 0; + + if (!HKDF_extract(secrets->extracted_early.data, + &secrets->extracted_early.len, secrets->digest, psk, psk_len, + secrets->zeros.data, secrets->zeros.len)) + return 0; + + if (secrets->extracted_early.len != secrets->zeros.len) + return 0; + + if (!tls13_derive_secret(&secrets->binder_key, secrets->digest, + &secrets->extracted_early, + secrets->resumption ? "res binder" : "ext binder", + &secrets->empty_hash)) + return 0; + if (!tls13_derive_secret(&secrets->client_early_traffic, + secrets->digest, &secrets->extracted_early, "c e traffic", + context)) + return 0; + if (!tls13_derive_secret(&secrets->early_exporter_master, + secrets->digest, &secrets->extracted_early, "e exp master", + context)) + return 0; + if (!tls13_derive_secret(&secrets->derived_early, + secrets->digest, &secrets->extracted_early, "derived", + &secrets->empty_hash)) + return 0; + + /* RFC 8446 recommends */ + if (!secrets->insecure) + explicit_bzero(secrets->extracted_early.data, + secrets->extracted_early.len); + secrets->early_done = 1; + return 1; +} + +int +tls13_derive_handshake_secrets(struct tls13_secrets *secrets, + const uint8_t *ecdhe, size_t ecdhe_len, + const struct tls13_secret *context) +{ + if (!secrets->init_done || !secrets->early_done || + secrets->handshake_done) + return 0; + + if (!HKDF_extract(secrets->extracted_handshake.data, + &secrets->extracted_handshake.len, secrets->digest, + ecdhe, ecdhe_len, secrets->derived_early.data, + secrets->derived_early.len)) + return 0; + + if (secrets->extracted_handshake.len != secrets->zeros.len) + return 0; + + /* XXX */ + if (!secrets->insecure) + explicit_bzero(secrets->derived_early.data, + secrets->derived_early.len); + + if (!tls13_derive_secret(&secrets->client_handshake_traffic, + secrets->digest, &secrets->extracted_handshake, "c hs traffic", + context)) + return 0; + if (!tls13_derive_secret(&secrets->server_handshake_traffic, + secrets->digest, &secrets->extracted_handshake, "s hs traffic", + context)) + return 0; + if (!tls13_derive_secret(&secrets->derived_handshake, + secrets->digest, &secrets->extracted_handshake, "derived", + &secrets->empty_hash)) + return 0; + + /* RFC 8446 recommends */ + if (!secrets->insecure) + explicit_bzero(secrets->extracted_handshake.data, + secrets->extracted_handshake.len); + + secrets->handshake_done = 1; + + return 1; +} + +int +tls13_derive_application_secrets(struct tls13_secrets *secrets, + const struct tls13_secret *context) +{ + if (!secrets->init_done || !secrets->early_done || + !secrets->handshake_done || secrets->schedule_done) + return 0; + + if (!HKDF_extract(secrets->extracted_master.data, + &secrets->extracted_master.len, secrets->digest, + secrets->zeros.data, secrets->zeros.len, + secrets->derived_handshake.data, secrets->derived_handshake.len)) + return 0; + + if (secrets->extracted_master.len != secrets->zeros.len) + return 0; + + /* XXX */ + if (!secrets->insecure) + explicit_bzero(secrets->derived_handshake.data, + secrets->derived_handshake.len); + + if (!tls13_derive_secret(&secrets->client_application_traffic, + secrets->digest, &secrets->extracted_master, "c ap traffic", + context)) + return 0; + if (!tls13_derive_secret(&secrets->server_application_traffic, + secrets->digest, &secrets->extracted_master, "s ap traffic", + context)) + return 0; + if (!tls13_derive_secret(&secrets->exporter_master, + secrets->digest, &secrets->extracted_master, "exp master", + context)) + return 0; + if (!tls13_derive_secret(&secrets->resumption_master, + secrets->digest, &secrets->extracted_master, "res master", + context)) + return 0; + + /* RFC 8446 recommends */ + if (!secrets->insecure) + explicit_bzero(secrets->extracted_master.data, + secrets->extracted_master.len); + + secrets->schedule_done = 1; + + return 1; +} + +int +tls13_update_client_traffic_secret(struct tls13_secrets *secrets) +{ + struct tls13_secret context = { .data = "", .len = 0 }; + + if (!secrets->init_done || !secrets->early_done || + !secrets->handshake_done || !secrets->schedule_done) + return 0; + + return tls13_hkdf_expand_label(&secrets->client_application_traffic, + secrets->digest, &secrets->client_application_traffic, + "traffic upd", &context); +} + +int +tls13_update_server_traffic_secret(struct tls13_secrets *secrets) +{ + struct tls13_secret context = { .data = "", .len = 0 }; + + if (!secrets->init_done || !secrets->early_done || + !secrets->handshake_done || !secrets->schedule_done) + return 0; + + return tls13_hkdf_expand_label(&secrets->server_application_traffic, + secrets->digest, &secrets->server_application_traffic, + "traffic upd", &context); +} + +int +tls13_exporter(struct tls13_ctx *ctx, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, uint8_t *out, + size_t out_len) +{ + struct tls13_secret context, export_out, export_secret; + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + EVP_MD_CTX *md_ctx = NULL; + unsigned int md_out_len; + int md_len; + int ret = 0; + + /* + * RFC 8446 Section 7.5. + */ + + memset(&context, 0, sizeof(context)); + memset(&export_secret, 0, sizeof(export_secret)); + + export_out.data = out; + export_out.len = out_len; + + if (!ctx->handshake_completed) + return 0; + + md_len = EVP_MD_size(secrets->digest); + if (md_len <= 0 || md_len > EVP_MAX_MD_SIZE) + goto err; + + if (!tls13_secret_init(&export_secret, md_len)) + goto err; + if (!tls13_secret_init(&context, md_len)) + goto err; + + /* In TLSv1.3 no context is equivalent to an empty context. */ + if (context_value == NULL) { + context_value = ""; + context_value_len = 0; + } + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestInit_ex(md_ctx, secrets->digest, NULL)) + goto err; + if (!EVP_DigestUpdate(md_ctx, context_value, context_value_len)) + goto err; + if (!EVP_DigestFinal_ex(md_ctx, context.data, &md_out_len)) + goto err; + if (md_len != md_out_len) + goto err; + + if (!tls13_derive_secret_with_label_length(&export_secret, + secrets->digest, &secrets->exporter_master, label, label_len, + &secrets->empty_hash)) + goto err; + + if (!tls13_hkdf_expand_label(&export_out, secrets->digest, + &export_secret, "exporter", &context)) + goto err; + + ret = 1; + + err: + EVP_MD_CTX_free(md_ctx); + tls13_secret_cleanup(&context); + tls13_secret_cleanup(&export_secret); + + return ret; +} diff --git a/ssl/tls13_legacy.c b/ssl/tls13_legacy.c new file mode 100644 index 0000000..1d6a5a1 --- /dev/null +++ b/ssl/tls13_legacy.c @@ -0,0 +1,556 @@ +/* $OpenBSD: tls13_legacy.c,v 1.40 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" +#include "tls13_internal.h" + +static ssize_t +tls13_legacy_wire_read(SSL *ssl, uint8_t *buf, size_t len) +{ + int n; + + if (ssl->rbio == NULL) { + SSLerror(ssl, SSL_R_BIO_NOT_SET); + return TLS13_IO_FAILURE; + } + + ssl->rwstate = SSL_READING; + errno = 0; + + if ((n = BIO_read(ssl->rbio, buf, len)) <= 0) { + if (BIO_should_read(ssl->rbio)) + return TLS13_IO_WANT_POLLIN; + if (n == 0) + return TLS13_IO_EOF; + + if (ERR_peek_error() == 0 && errno != 0) + SYSerror(errno); + + return TLS13_IO_FAILURE; + } + + if (n == len) + ssl->rwstate = SSL_NOTHING; + + return n; +} + +ssize_t +tls13_legacy_wire_read_cb(void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + + return tls13_legacy_wire_read(ctx->ssl, buf, n); +} + +static ssize_t +tls13_legacy_wire_write(SSL *ssl, const uint8_t *buf, size_t len) +{ + int n; + + if (ssl->wbio == NULL) { + SSLerror(ssl, SSL_R_BIO_NOT_SET); + return TLS13_IO_FAILURE; + } + + ssl->rwstate = SSL_WRITING; + errno = 0; + + if ((n = BIO_write(ssl->wbio, buf, len)) <= 0) { + if (BIO_should_write(ssl->wbio)) + return TLS13_IO_WANT_POLLOUT; + + if (ERR_peek_error() == 0 && errno != 0) + SYSerror(errno); + + return TLS13_IO_FAILURE; + } + + if (n == len) + ssl->rwstate = SSL_NOTHING; + + return n; +} + +ssize_t +tls13_legacy_wire_write_cb(const void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + + return tls13_legacy_wire_write(ctx->ssl, buf, n); +} + +static ssize_t +tls13_legacy_wire_flush(SSL *ssl) +{ + if (BIO_flush(ssl->wbio) <= 0) { + if (BIO_should_write(ssl->wbio)) + return TLS13_IO_WANT_POLLOUT; + + if (ERR_peek_error() == 0 && errno != 0) + SYSerror(errno); + + return TLS13_IO_FAILURE; + } + + return TLS13_IO_SUCCESS; +} + +ssize_t +tls13_legacy_wire_flush_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + + return tls13_legacy_wire_flush(ctx->ssl); +} + +static void +tls13_legacy_error(SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->tls13; + int reason = SSL_R_UNKNOWN; + + /* If we received a fatal alert we already put an error on the stack. */ + if (ssl->s3->fatal_alert != 0) + return; + + switch (ctx->error.code) { + case TLS13_ERR_VERIFY_FAILED: + reason = SSL_R_CERTIFICATE_VERIFY_FAILED; + break; + case TLS13_ERR_HRR_FAILED: + reason = SSL_R_NO_CIPHERS_AVAILABLE; + break; + case TLS13_ERR_TRAILING_DATA: + reason = SSL_R_EXTRA_DATA_IN_MESSAGE; + break; + case TLS13_ERR_NO_SHARED_CIPHER: + reason = SSL_R_NO_SHARED_CIPHER; + break; + case TLS13_ERR_NO_CERTIFICATE: + reason = SSL_R_MISSING_RSA_CERTIFICATE; /* XXX */ + break; + case TLS13_ERR_NO_PEER_CERTIFICATE: + reason = SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE; + break; + } + + /* Something (probably libcrypto) already pushed an error on the stack. */ + if (reason == SSL_R_UNKNOWN && ERR_peek_error() != 0) + return; + + ERR_put_error(ERR_LIB_SSL, (0xfff), reason, ctx->error.file, + ctx->error.line); +} + +int +tls13_legacy_return_code(SSL *ssl, ssize_t ret) +{ + if (ret > INT_MAX) { + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return -1; + } + + /* A successful read, write or other operation. */ + if (ret > 0) + return ret; + + ssl->rwstate = SSL_NOTHING; + + switch (ret) { + case TLS13_IO_EOF: + return 0; + + case TLS13_IO_FAILURE: + tls13_legacy_error(ssl); + return -1; + + case TLS13_IO_ALERT: + tls13_legacy_error(ssl); + return -1; + + case TLS13_IO_WANT_POLLIN: + BIO_set_retry_read(ssl->rbio); + ssl->rwstate = SSL_READING; + return -1; + + case TLS13_IO_WANT_POLLOUT: + BIO_set_retry_write(ssl->wbio); + ssl->rwstate = SSL_WRITING; + return -1; + + case TLS13_IO_WANT_RETRY: + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return -1; + } + + SSLerror(ssl, ERR_R_INTERNAL_ERROR); + return -1; +} + +int +tls13_legacy_pending(const SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->tls13; + ssize_t ret; + + if (ctx == NULL) + return 0; + + ret = tls13_pending_application_data(ctx->rl); + if (ret < 0 || ret > INT_MAX) + return 0; + + return ret; +} + +int +tls13_legacy_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, int peek) +{ + struct tls13_ctx *ctx = ssl->tls13; + ssize_t ret; + + if (ctx == NULL || !ctx->handshake_completed) { + if ((ret = ssl->handshake_func(ssl)) <= 0) + return ret; + if (len == 0) + return 0; + return tls13_legacy_return_code(ssl, TLS13_IO_WANT_POLLIN); + } + + tls13_record_layer_set_retry_after_phh(ctx->rl, + (ctx->ssl->mode & SSL_MODE_AUTO_RETRY) != 0); + + if (type != SSL3_RT_APPLICATION_DATA) { + SSLerror(ssl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } + if (len < 0) { + SSLerror(ssl, SSL_R_BAD_LENGTH); + return -1; + } + + if (peek) + ret = tls13_peek_application_data(ctx->rl, buf, len); + else + ret = tls13_read_application_data(ctx->rl, buf, len); + + return tls13_legacy_return_code(ssl, ret); +} + +int +tls13_legacy_write_bytes(SSL *ssl, int type, const void *vbuf, int len) +{ + struct tls13_ctx *ctx = ssl->tls13; + const uint8_t *buf = vbuf; + size_t n, sent; + ssize_t ret; + + if (ctx == NULL || !ctx->handshake_completed) { + if ((ret = ssl->handshake_func(ssl)) <= 0) + return ret; + if (len == 0) + return 0; + return tls13_legacy_return_code(ssl, TLS13_IO_WANT_POLLOUT); + } + + if (type != SSL3_RT_APPLICATION_DATA) { + SSLerror(ssl, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } + if (len < 0) { + SSLerror(ssl, SSL_R_BAD_LENGTH); + return -1; + } + + /* + * The TLSv1.3 record layer write behaviour is the same as + * SSL_MODE_ENABLE_PARTIAL_WRITE. + */ + if (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE) { + ret = tls13_write_application_data(ctx->rl, buf, len); + return tls13_legacy_return_code(ssl, ret); + } + + /* + * In the non-SSL_MODE_ENABLE_PARTIAL_WRITE case we have to loop until + * we have written out all of the requested data. + */ + sent = ssl->s3->wnum; + if (len < sent) { + SSLerror(ssl, SSL_R_BAD_LENGTH); + return -1; + } + n = len - sent; + for (;;) { + if (n == 0) { + ssl->s3->wnum = 0; + return sent; + } + if ((ret = tls13_write_application_data(ctx->rl, + &buf[sent], n)) <= 0) { + ssl->s3->wnum = sent; + return tls13_legacy_return_code(ssl, ret); + } + sent += ret; + n -= ret; + } +} + +static int +tls13_use_legacy_stack(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + CBB cbb, fragment; + CBS cbs; + + memset(&cbb, 0, sizeof(cbb)); + + s->method = tls_legacy_method(); + + if (!ssl3_setup_init_buffer(s)) + goto err; + if (!ssl3_setup_buffers(s)) + goto err; + if (!ssl_init_wbio_buffer(s, 1)) + goto err; + + /* Stash any unprocessed data from the last record. */ + tls13_record_layer_rcontent(ctx->rl, &cbs); + if (CBS_len(&cbs) > 0) { + if (!CBB_init_fixed(&cbb, s->s3->rbuf.buf, + s->s3->rbuf.len)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_RT_HANDSHAKE)) + goto err; + if (!CBB_add_u16(&cbb, TLS1_2_VERSION)) + goto err; + if (!CBB_add_u16_length_prefixed(&cbb, &fragment)) + goto err; + if (!CBB_add_bytes(&fragment, CBS_data(&cbs), CBS_len(&cbs))) + goto err; + if (!CBB_finish(&cbb, NULL, NULL)) + goto err; + + s->s3->rbuf.offset = SSL3_RT_HEADER_LENGTH; + s->s3->rbuf.left = CBS_len(&cbs); + s->s3->rrec.type = SSL3_RT_HANDSHAKE; + s->s3->rrec.length = CBS_len(&cbs); + s->rstate = SSL_ST_READ_BODY; + s->packet = s->s3->rbuf.buf; + s->packet_length = SSL3_RT_HEADER_LENGTH; + s->mac_packet = 1; + } + + /* Stash the current handshake message. */ + tls13_handshake_msg_data(ctx->hs_msg, &cbs); + if (!BUF_MEM_grow_clean(s->init_buf, CBS_len(&cbs))) + goto err; + if (!CBS_write_bytes(&cbs, s->init_buf->data, + s->init_buf->length, NULL)) + goto err; + + s->s3->hs.tls12.reuse_message = 1; + s->s3->hs.tls12.message_type = tls13_handshake_msg_type(ctx->hs_msg); + s->s3->hs.tls12.message_size = CBS_len(&cbs) - SSL3_HM_HEADER_LENGTH; + + return 1; + + err: + CBB_cleanup(&cbb); + + return 0; +} + +int +tls13_use_legacy_client(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + + if (!tls13_use_legacy_stack(ctx)) + return 0; + + s->handshake_func = s->method->ssl_connect; + s->version = s->method->max_tls_version; + + return 1; +} + +int +tls13_use_legacy_server(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + + if (!tls13_use_legacy_stack(ctx)) + return 0; + + s->handshake_func = s->method->ssl_accept; + s->version = s->method->max_tls_version; + s->server = 1; + + return 1; +} + +int +tls13_legacy_accept(SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->tls13; + int ret; + + if (ctx == NULL) { + if ((ctx = tls13_ctx_new(TLS13_HS_SERVER, ssl)) == NULL) { + SSLerror(ssl, ERR_R_INTERNAL_ERROR); /* XXX */ + return -1; + } + if (!tls13_server_init(ctx)) { + if (ERR_peek_error() == 0) + SSLerror(ssl, ERR_R_INTERNAL_ERROR); /* XXX */ + return -1; + } + } + + ERR_clear_error(); + + ret = tls13_server_accept(ctx); + if (ret == TLS13_IO_USE_LEGACY) + return ssl->method->ssl_accept(ssl); + + ret = tls13_legacy_return_code(ssl, ret); + + if (ctx->info_cb != NULL) + ctx->info_cb(ctx, TLS13_INFO_ACCEPT_EXIT, ret); + + return ret; +} + +int +tls13_legacy_connect(SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->tls13; + int ret; + + if (ctx == NULL) { + if ((ctx = tls13_ctx_new(TLS13_HS_CLIENT, ssl)) == NULL) { + SSLerror(ssl, ERR_R_INTERNAL_ERROR); /* XXX */ + return -1; + } + if (!tls13_client_init(ctx)) { + if (ERR_peek_error() == 0) + SSLerror(ssl, ERR_R_INTERNAL_ERROR); /* XXX */ + return -1; + } + } + + ERR_clear_error(); + + ret = tls13_client_connect(ctx); + if (ret == TLS13_IO_USE_LEGACY) + return ssl->method->ssl_connect(ssl); + + ret = tls13_legacy_return_code(ssl, ret); + + if (ctx->info_cb != NULL) + ctx->info_cb(ctx, TLS13_INFO_CONNECT_EXIT, ret); + + return ret; +} + +int +tls13_legacy_shutdown(SSL *ssl) +{ + struct tls13_ctx *ctx = ssl->tls13; + uint8_t buf[512]; /* XXX */ + ssize_t ret; + + /* + * We need to return 0 at the point that we have completed sending a + * close-notify. We return 1 when we have sent and received close-notify + * alerts. All other cases, including EOF, return -1 and set internal + * state appropriately. + */ + if (ctx == NULL || ssl->quiet_shutdown) { + ssl->shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN; + return 1; + } + + if (!ctx->close_notify_sent) { + /* Enqueue and send close notify. */ + if (!(ssl->shutdown & SSL_SENT_SHUTDOWN)) { + ssl->shutdown |= SSL_SENT_SHUTDOWN; + if ((ret = tls13_send_alert(ctx->rl, + TLS13_ALERT_CLOSE_NOTIFY)) < 0) + return tls13_legacy_return_code(ssl, ret); + } + ret = tls13_record_layer_send_pending(ctx->rl); + if (ret == TLS13_IO_EOF) + return -1; + if (ret != TLS13_IO_SUCCESS) + return tls13_legacy_return_code(ssl, ret); + } else if (!ctx->close_notify_recv) { + /* + * If there is no application data pending, attempt to read more + * data in order to receive a close-notify. This should trigger + * a record to be read from the wire, which may be application + * handshake or alert data. Only one attempt is made to match + * previous semantics. + */ + if (tls13_pending_application_data(ctx->rl) == 0) { + if ((ret = tls13_read_application_data(ctx->rl, buf, + sizeof(buf))) < 0) + return tls13_legacy_return_code(ssl, ret); + if (!ctx->close_notify_recv) + return -1; + } + } + + if (ctx->close_notify_recv) + return 1; + + return 0; +} + +int +tls13_legacy_servername_process(struct tls13_ctx *ctx, uint8_t *alert) +{ + int legacy_alert = SSL_AD_UNRECOGNIZED_NAME; + int ret = SSL_TLSEXT_ERR_NOACK; + SSL_CTX *ssl_ctx = ctx->ssl->ctx; + SSL *s = ctx->ssl; + + if (ssl_ctx->tlsext_servername_callback == NULL) + ssl_ctx = s->initial_ctx; + if (ssl_ctx->tlsext_servername_callback == NULL) + return 1; + + ret = ssl_ctx->tlsext_servername_callback(s, &legacy_alert, + ssl_ctx->tlsext_servername_arg); + + /* + * Ignore SSL_TLSEXT_ERR_ALERT_WARNING returns to match OpenSSL's + * behavior: the only warning alerts in TLSv1.3 are close_notify and + * user_canceled, neither of which should be returned by the callback. + */ + if (ret == SSL_TLSEXT_ERR_ALERT_FATAL) { + if (legacy_alert >= 0 && legacy_alert <= 255) + *alert = legacy_alert; + return 0; + } + + return 1; +} diff --git a/ssl/tls13_lib.c b/ssl/tls13_lib.c new file mode 100644 index 0000000..05f125a --- /dev/null +++ b/ssl/tls13_lib.c @@ -0,0 +1,701 @@ +/* $OpenBSD: tls13_lib.c,v 1.76 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * Copyright (c) 2019 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "ssl_local.h" +#include "ssl_tlsext.h" +#include "tls13_internal.h" + +/* + * RFC 8446, section 4.6.1. Servers must not indicate a lifetime longer than + * 7 days and clients must not cache tickets for longer than 7 days. + */ + +#define TLS13_MAX_TICKET_LIFETIME (7 * 24 * 3600) + +/* + * Downgrade sentinels - RFC 8446 section 4.1.3, magic values which must be set + * by the server in server random if it is willing to downgrade but supports + * TLSv1.3 + */ +const uint8_t tls13_downgrade_12[8] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01, +}; +const uint8_t tls13_downgrade_11[8] = { + 0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00, +}; + +/* + * HelloRetryRequest hash - RFC 8446 section 4.1.3. + */ +const uint8_t tls13_hello_retry_request_hash[32] = { + 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, + 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91, + 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e, + 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, +}; + +/* + * Certificate Verify padding - RFC 8446 section 4.4.3. + */ +const uint8_t tls13_cert_verify_pad[64] = { + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, +}; + +const uint8_t tls13_cert_client_verify_context[] = + "TLS 1.3, client CertificateVerify"; +const uint8_t tls13_cert_server_verify_context[] = + "TLS 1.3, server CertificateVerify"; + +const EVP_AEAD * +tls13_cipher_aead(const SSL_CIPHER *cipher) +{ + if (cipher == NULL) + return NULL; + if (cipher->algorithm_ssl != SSL_TLSV1_3) + return NULL; + + switch (cipher->algorithm_enc) { + case SSL_AES128GCM: + return EVP_aead_aes_128_gcm(); + case SSL_AES256GCM: + return EVP_aead_aes_256_gcm(); + case SSL_CHACHA20POLY1305: + return EVP_aead_chacha20_poly1305(); + } + + return NULL; +} + +const EVP_MD * +tls13_cipher_hash(const SSL_CIPHER *cipher) +{ + if (cipher == NULL) + return NULL; + if (cipher->algorithm_ssl != SSL_TLSV1_3) + return NULL; + + switch (cipher->algorithm2) { + case SSL_HANDSHAKE_MAC_SHA256: + return EVP_sha256(); + case SSL_HANDSHAKE_MAC_SHA384: + return EVP_sha384(); + } + + return NULL; +} + +void +tls13_alert_received_cb(uint8_t alert_desc, void *arg) +{ + struct tls13_ctx *ctx = arg; + + if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY) { + ctx->close_notify_recv = 1; + ctx->ssl->shutdown |= SSL_RECEIVED_SHUTDOWN; + ctx->ssl->s3->warn_alert = alert_desc; + return; + } + + if (alert_desc == TLS13_ALERT_USER_CANCELED) { + /* + * We treat this as advisory, since a close_notify alert + * SHOULD follow this alert (RFC 8446 section 6.1). + */ + return; + } + + /* All other alerts are treated as fatal in TLSv1.3. */ + ctx->ssl->s3->fatal_alert = alert_desc; + + SSLerror(ctx->ssl, SSL_AD_REASON_OFFSET + alert_desc); + ERR_asprintf_error_data("SSL alert number %d", alert_desc); + + SSL_CTX_remove_session(ctx->ssl->ctx, ctx->ssl->session); +} + +void +tls13_alert_sent_cb(uint8_t alert_desc, void *arg) +{ + struct tls13_ctx *ctx = arg; + + if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY) { + ctx->close_notify_sent = 1; + return; + } + + if (alert_desc == TLS13_ALERT_USER_CANCELED) { + return; + } + + /* All other alerts are treated as fatal in TLSv1.3. */ + if (ctx->error.code == 0) + SSLerror(ctx->ssl, SSL_AD_REASON_OFFSET + alert_desc); +} + +static void +tls13_legacy_handshake_message_recv_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *s = ctx->ssl; + CBS cbs; + + if (s->msg_callback == NULL) + return; + + tls13_handshake_msg_data(ctx->hs_msg, &cbs); + ssl_msg_callback_cbs(s, 0, SSL3_RT_HANDSHAKE, &cbs); +} + +static void +tls13_legacy_handshake_message_sent_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *s = ctx->ssl; + CBS cbs; + + if (s->msg_callback == NULL) + return; + + tls13_handshake_msg_data(ctx->hs_msg, &cbs); + ssl_msg_callback_cbs(s, 1, SSL3_RT_HANDSHAKE, &cbs); +} + +static void +tls13_legacy_info_cb(void *arg, int state, int ret) +{ + struct tls13_ctx *ctx = arg; + SSL *s = ctx->ssl; + + ssl_info_callback(s, state, ret); +} + +static int +tls13_legacy_ocsp_status_recv_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *s = ctx->ssl; + int ret; + + if (s->ctx->tlsext_status_cb == NULL) + return 1; + + ret = s->ctx->tlsext_status_cb(s, + s->ctx->tlsext_status_arg); + if (ret < 0) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + SSLerror(s, ERR_R_MALLOC_FAILURE); + return 0; + } + if (ret == 0) { + ctx->alert = TLS13_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE; + SSLerror(s, SSL_R_INVALID_STATUS_RESPONSE); + return 0; + } + + return 1; +} + +static int +tls13_phh_update_read_traffic_secret(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret *secret; + + if (ctx->mode == TLS13_HS_CLIENT) { + secret = &secrets->server_application_traffic; + if (!tls13_update_server_traffic_secret(secrets)) + return 0; + } else { + secret = &secrets->client_application_traffic; + if (!tls13_update_client_traffic_secret(secrets)) + return 0; + } + + return tls13_record_layer_set_read_traffic_key(ctx->rl, + secret, ssl_encryption_application); +} + +static int +tls13_phh_update_write_traffic_secret(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret *secret; + + if (ctx->mode == TLS13_HS_CLIENT) { + secret = &secrets->client_application_traffic; + if (!tls13_update_client_traffic_secret(secrets)) + return 0; + } else { + secret = &secrets->server_application_traffic; + if (!tls13_update_server_traffic_secret(secrets)) + return 0; + } + + return tls13_record_layer_set_write_traffic_key(ctx->rl, + secret, ssl_encryption_application); +} + +/* + * XXX arbitrarily chosen limit of 100 post handshake handshake + * messages in an hour - to avoid a hostile peer from constantly + * requesting certificates or key renegotiaitons, etc. + */ +static int +tls13_phh_limit_check(struct tls13_ctx *ctx) +{ + time_t now = time(NULL); + + if (ctx->phh_last_seen > now - TLS13_PHH_LIMIT_TIME) { + if (ctx->phh_count > TLS13_PHH_LIMIT) + return 0; + } else + ctx->phh_count = 0; + ctx->phh_count++; + ctx->phh_last_seen = now; + return 1; +} + +static ssize_t +tls13_key_update_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + struct tls13_handshake_msg *hs_msg = NULL; + CBB cbb_hs; + CBS cbs_hs; + uint8_t alert = TLS13_ALERT_INTERNAL_ERROR; + uint8_t key_update_request; + ssize_t ret; + + if (!CBS_get_u8(cbs, &key_update_request)) { + alert = TLS13_ALERT_DECODE_ERROR; + goto err; + } + if (CBS_len(cbs) != 0) { + alert = TLS13_ALERT_DECODE_ERROR; + goto err; + } + if (key_update_request > 1) { + alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + if (!tls13_phh_update_read_traffic_secret(ctx)) + goto err; + + if (key_update_request == 0) + return TLS13_IO_SUCCESS; + + /* Our peer requested that we update our write traffic keys. */ + if ((hs_msg = tls13_handshake_msg_new()) == NULL) + goto err; + if (!tls13_handshake_msg_start(hs_msg, &cbb_hs, TLS13_MT_KEY_UPDATE)) + goto err; + if (!CBB_add_u8(&cbb_hs, 0)) + goto err; + if (!tls13_handshake_msg_finish(hs_msg)) + goto err; + + ctx->key_update_request = 1; + tls13_handshake_msg_data(hs_msg, &cbs_hs); + ret = tls13_record_layer_phh(ctx->rl, &cbs_hs); + + tls13_handshake_msg_free(hs_msg); + hs_msg = NULL; + + return ret; + + err: + tls13_handshake_msg_free(hs_msg); + + return tls13_send_alert(ctx->rl, alert); +} + +/* RFC 8446 section 4.6.1 */ +static ssize_t +tls13_new_session_ticket_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret nonce; + uint32_t ticket_lifetime, ticket_age_add; + CBS ticket_nonce, ticket; + SSL_SESSION *sess = NULL; + int alert, session_id_length; + ssize_t ret = 0; + + memset(&nonce, 0, sizeof(nonce)); + + if (ctx->mode != TLS13_HS_CLIENT) { + alert = TLS13_ALERT_UNEXPECTED_MESSAGE; + goto err; + } + + alert = TLS13_ALERT_DECODE_ERROR; + + if (!CBS_get_u32(cbs, &ticket_lifetime)) + goto err; + if (!CBS_get_u32(cbs, &ticket_age_add)) + goto err; + if (!CBS_get_u8_length_prefixed(cbs, &ticket_nonce)) + goto err; + if (!CBS_get_u16_length_prefixed(cbs, &ticket)) + goto err; + /* Extensions can only contain early_data, which we currently ignore. */ + if (!tlsext_client_parse(ctx->ssl, SSL_TLSEXT_MSG_NST, cbs, &alert)) + goto err; + + if (CBS_len(cbs) != 0) + goto err; + + /* Zero indicates that the ticket should be discarded immediately. */ + if (ticket_lifetime == 0) { + ret = TLS13_IO_SUCCESS; + goto done; + } + + /* Servers MUST NOT use any value larger than 7 days. */ + if (ticket_lifetime > TLS13_MAX_TICKET_LIFETIME) { + alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + alert = TLS13_ALERT_INTERNAL_ERROR; + + /* + * Create new session instead of modifying the current session. + * The current session could already be in the session cache. + */ + if ((sess = ssl_session_dup(ctx->ssl->session, 0)) == NULL) + goto err; + + sess->time = time(NULL); + + sess->tlsext_tick_lifetime_hint = ticket_lifetime; + sess->tlsext_tick_age_add = ticket_age_add; + + if (!CBS_stow(&ticket, &sess->tlsext_tick, &sess->tlsext_ticklen)) + goto err; + + /* XXX - ensure this doesn't overflow session_id if hash is changed. */ + if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), + sess->session_id, &session_id_length, EVP_sha256(), NULL)) + goto err; + sess->session_id_length = session_id_length; + + if (!CBS_stow(&ticket_nonce, &nonce.data, &nonce.len)) + goto err; + + if (!tls13_secret_init(&sess->resumption_master_secret, 256)) + goto err; + + if (!tls13_derive_secret(&sess->resumption_master_secret, + secrets->digest, &secrets->resumption_master, "resumption", + &nonce)) + goto err; + + SSL_SESSION_free(ctx->ssl->session); + ctx->ssl->session = sess; + sess = NULL; + + ssl_update_cache(ctx->ssl, SSL_SESS_CACHE_CLIENT); + + ret = TLS13_IO_SUCCESS; + goto done; + + err: + ret = tls13_send_alert(ctx->rl, alert); + + done: + tls13_secret_cleanup(&nonce); + SSL_SESSION_free(sess); + + return ret; +} + +ssize_t +tls13_phh_received_cb(void *cb_arg) +{ + ssize_t ret = TLS13_IO_FAILURE; + struct tls13_ctx *ctx = cb_arg; + CBS cbs; + + if (!tls13_phh_limit_check(ctx)) + return tls13_send_alert(ctx->rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + + if ((ctx->hs_msg == NULL) && + ((ctx->hs_msg = tls13_handshake_msg_new()) == NULL)) + return TLS13_IO_FAILURE; + + if ((ret = tls13_handshake_msg_recv(ctx->hs_msg, ctx->rl)) != + TLS13_IO_SUCCESS) + return ret; + + if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs)) + return TLS13_IO_FAILURE; + + switch(tls13_handshake_msg_type(ctx->hs_msg)) { + case TLS13_MT_KEY_UPDATE: + ret = tls13_key_update_recv(ctx, &cbs); + break; + case TLS13_MT_NEW_SESSION_TICKET: + ret = tls13_new_session_ticket_recv(ctx, &cbs); + break; + case TLS13_MT_CERTIFICATE_REQUEST: + /* XXX add support if we choose to advertise this */ + /* FALLTHROUGH */ + default: + ret = TLS13_IO_FAILURE; /* XXX send alert */ + break; + } + + tls13_handshake_msg_free(ctx->hs_msg); + ctx->hs_msg = NULL; + return ret; +} + +void +tls13_phh_done_cb(void *cb_arg) +{ + struct tls13_ctx *ctx = cb_arg; + + if (ctx->key_update_request) { + tls13_phh_update_write_traffic_secret(ctx); + ctx->key_update_request = 0; + } +} + +static const struct tls13_record_layer_callbacks tls13_rl_callbacks = { + .wire_read = tls13_legacy_wire_read_cb, + .wire_write = tls13_legacy_wire_write_cb, + .wire_flush = tls13_legacy_wire_flush_cb, + + .alert_recv = tls13_alert_received_cb, + .alert_sent = tls13_alert_sent_cb, + .phh_recv = tls13_phh_received_cb, + .phh_sent = tls13_phh_done_cb, +}; + +struct tls13_ctx * +tls13_ctx_new(int mode, SSL *ssl) +{ + struct tls13_ctx *ctx = NULL; + + if ((ctx = calloc(sizeof(struct tls13_ctx), 1)) == NULL) + goto err; + + ctx->hs = &ssl->s3->hs; + ctx->mode = mode; + ctx->ssl = ssl; + + if ((ctx->rl = tls13_record_layer_new(&tls13_rl_callbacks, ctx)) == NULL) + goto err; + + ctx->handshake_message_sent_cb = tls13_legacy_handshake_message_sent_cb; + ctx->handshake_message_recv_cb = tls13_legacy_handshake_message_recv_cb; + ctx->info_cb = tls13_legacy_info_cb; + ctx->ocsp_status_recv_cb = tls13_legacy_ocsp_status_recv_cb; + + ctx->middlebox_compat = 1; + + ssl->tls13 = ctx; + + if (SSL_is_quic(ssl)) { + if (!tls13_quic_init(ctx)) + goto err; + } + + return ctx; + + err: + tls13_ctx_free(ctx); + + return NULL; +} + +void +tls13_ctx_free(struct tls13_ctx *ctx) +{ + if (ctx == NULL) + return; + + tls13_error_clear(&ctx->error); + tls13_record_layer_free(ctx->rl); + tls13_handshake_msg_free(ctx->hs_msg); + + freezero(ctx, sizeof(struct tls13_ctx)); +} + +int +tls13_cert_add(struct tls13_ctx *ctx, CBB *cbb, X509 *cert, + int (*build_extensions)(SSL *s, uint16_t msg_type, CBB *cbb)) +{ + CBB cert_data, cert_exts; + uint8_t *data; + int cert_len; + + if ((cert_len = i2d_X509(cert, NULL)) < 0) + return 0; + + if (!CBB_add_u24_length_prefixed(cbb, &cert_data)) + return 0; + if (!CBB_add_space(&cert_data, &data, cert_len)) + return 0; + if (i2d_X509(cert, &data) != cert_len) + return 0; + if (build_extensions != NULL) { + if (!build_extensions(ctx->ssl, SSL_TLSEXT_MSG_CT, cbb)) + return 0; + } else { + if (!CBB_add_u16_length_prefixed(cbb, &cert_exts)) + return 0; + } + if (!CBB_flush(cbb)) + return 0; + + return 1; +} + +int +tls13_synthetic_handshake_message(struct tls13_ctx *ctx) +{ + struct tls13_handshake_msg *hm = NULL; + unsigned char buf[EVP_MAX_MD_SIZE]; + size_t hash_len; + CBB cbb; + CBS cbs; + SSL *s = ctx->ssl; + int ret = 0; + + /* + * Replace ClientHello with synthetic handshake message - see + * RFC 8446 section 4.4.1. + */ + if (!tls1_transcript_hash_init(s)) + goto err; + if (!tls1_transcript_hash_value(s, buf, sizeof(buf), &hash_len)) + goto err; + + if ((hm = tls13_handshake_msg_new()) == NULL) + goto err; + if (!tls13_handshake_msg_start(hm, &cbb, TLS13_MT_MESSAGE_HASH)) + goto err; + if (!CBB_add_bytes(&cbb, buf, hash_len)) + goto err; + if (!tls13_handshake_msg_finish(hm)) + goto err; + + tls13_handshake_msg_data(hm, &cbs); + + tls1_transcript_reset(ctx->ssl); + if (!tls1_transcript_record(ctx->ssl, CBS_data(&cbs), CBS_len(&cbs))) + goto err; + + ret = 1; + + err: + tls13_handshake_msg_free(hm); + + return ret; +} + +int +tls13_clienthello_hash_init(struct tls13_ctx *ctx) +{ + if (ctx->hs->tls13.clienthello_md_ctx != NULL) + return 0; + if ((ctx->hs->tls13.clienthello_md_ctx = EVP_MD_CTX_new()) == NULL) + return 0; + if (!EVP_DigestInit_ex(ctx->hs->tls13.clienthello_md_ctx, + EVP_sha256(), NULL)) + return 0; + + if ((ctx->hs->tls13.clienthello_hash == NULL) && + (ctx->hs->tls13.clienthello_hash = calloc(1, EVP_MAX_MD_SIZE)) == + NULL) + return 0; + + return 1; +} + +void +tls13_clienthello_hash_clear(struct ssl_handshake_tls13_st *hs) /* XXX */ +{ + EVP_MD_CTX_free(hs->clienthello_md_ctx); + hs->clienthello_md_ctx = NULL; + freezero(hs->clienthello_hash, EVP_MAX_MD_SIZE); + hs->clienthello_hash = NULL; +} + +int +tls13_clienthello_hash_update_bytes(struct tls13_ctx *ctx, void *data, + size_t len) +{ + return EVP_DigestUpdate(ctx->hs->tls13.clienthello_md_ctx, data, len); +} + +int +tls13_clienthello_hash_update(struct tls13_ctx *ctx, CBS *cbs) +{ + return tls13_clienthello_hash_update_bytes(ctx, (void *)CBS_data(cbs), + CBS_len(cbs)); +} + +int +tls13_clienthello_hash_finalize(struct tls13_ctx *ctx) +{ + if (!EVP_DigestFinal_ex(ctx->hs->tls13.clienthello_md_ctx, + ctx->hs->tls13.clienthello_hash, + &ctx->hs->tls13.clienthello_hash_len)) + return 0; + EVP_MD_CTX_free(ctx->hs->tls13.clienthello_md_ctx); + ctx->hs->tls13.clienthello_md_ctx = NULL; + return 1; +} + +int +tls13_clienthello_hash_validate(struct tls13_ctx *ctx) +{ + unsigned char new_ch_hash[EVP_MAX_MD_SIZE]; + unsigned int new_ch_hash_len; + + if (ctx->hs->tls13.clienthello_hash == NULL) + return 0; + + if (!EVP_DigestFinal_ex(ctx->hs->tls13.clienthello_md_ctx, + new_ch_hash, &new_ch_hash_len)) + return 0; + EVP_MD_CTX_free(ctx->hs->tls13.clienthello_md_ctx); + ctx->hs->tls13.clienthello_md_ctx = NULL; + + if (ctx->hs->tls13.clienthello_hash_len != new_ch_hash_len) + return 0; + if (memcmp(ctx->hs->tls13.clienthello_hash, new_ch_hash, + new_ch_hash_len) != 0) + return 0; + + return 1; +} diff --git a/ssl/tls13_quic.c b/ssl/tls13_quic.c new file mode 100644 index 0000000..e5c386e --- /dev/null +++ b/ssl/tls13_quic.c @@ -0,0 +1,181 @@ +/* $OpenBSD: tls13_quic.c,v 1.7 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ssl_local.h" +#include "tls13_internal.h" + +static ssize_t +tls13_quic_wire_read_cb(void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + SSLerror(ssl, SSL_R_QUIC_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_wire_write_cb(const void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + SSLerror(ssl, SSL_R_QUIC_INTERNAL_ERROR); + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_quic_wire_flush_cb(void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + if (!ssl->quic_method->flush_flight(ssl)) { + SSLerror(ssl, SSL_R_QUIC_INTERNAL_ERROR); + return TLS13_IO_FAILURE; + } + + return TLS13_IO_SUCCESS; +} + +static ssize_t +tls13_quic_handshake_read_cb(void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + + if (ctx->hs->tls13.quic_read_buffer == NULL) + return TLS13_IO_WANT_POLLIN; + + return tls_buffer_read(ctx->hs->tls13.quic_read_buffer, buf, n); +} + +static ssize_t +tls13_quic_handshake_write_cb(const void *buf, size_t n, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + if (!ssl->quic_method->add_handshake_data(ssl, + ctx->hs->tls13.quic_write_level, buf, n)) { + SSLerror(ssl, SSL_R_QUIC_INTERNAL_ERROR); + return TLS13_IO_FAILURE; + } + + return n; +} + +static int +tls13_quic_set_read_traffic_key(struct tls13_secret *read_key, + enum ssl_encryption_level_t read_level, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + ctx->hs->tls13.quic_read_level = read_level; + + /* Handle both the new (BoringSSL) and old (quictls) APIs. */ + + if (ssl->quic_method->set_read_secret != NULL) + return ssl->quic_method->set_read_secret(ssl, + ctx->hs->tls13.quic_read_level, ctx->hs->cipher, + read_key->data, read_key->len); + + if (ssl->quic_method->set_encryption_secrets != NULL) + return ssl->quic_method->set_encryption_secrets(ssl, + ctx->hs->tls13.quic_read_level, read_key->data, NULL, + read_key->len); + + return 0; +} + +static int +tls13_quic_set_write_traffic_key(struct tls13_secret *write_key, + enum ssl_encryption_level_t write_level, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + ctx->hs->tls13.quic_write_level = write_level; + + /* Handle both the new (BoringSSL) and old (quictls) APIs. */ + + if (ssl->quic_method->set_write_secret != NULL) + return ssl->quic_method->set_write_secret(ssl, + ctx->hs->tls13.quic_write_level, ctx->hs->cipher, + write_key->data, write_key->len); + + if (ssl->quic_method->set_encryption_secrets != NULL) + return ssl->quic_method->set_encryption_secrets(ssl, + ctx->hs->tls13.quic_write_level, NULL, write_key->data, + write_key->len); + + return 0; +} + +static int +tls13_quic_alert_send_cb(int alert_desc, void *arg) +{ + struct tls13_ctx *ctx = arg; + SSL *ssl = ctx->ssl; + + if (!ssl->quic_method->send_alert(ssl, ctx->hs->tls13.quic_write_level, + alert_desc)) { + SSLerror(ssl, SSL_R_QUIC_INTERNAL_ERROR); + return TLS13_IO_FAILURE; + } + + return TLS13_IO_SUCCESS; +} + +static const struct tls13_record_layer_callbacks quic_rl_callbacks = { + .wire_read = tls13_quic_wire_read_cb, + .wire_write = tls13_quic_wire_write_cb, + .wire_flush = tls13_quic_wire_flush_cb, + + .handshake_read = tls13_quic_handshake_read_cb, + .handshake_write = tls13_quic_handshake_write_cb, + .set_read_traffic_key = tls13_quic_set_read_traffic_key, + .set_write_traffic_key = tls13_quic_set_write_traffic_key, + .alert_send = tls13_quic_alert_send_cb, + + .alert_recv = tls13_alert_received_cb, + .alert_sent = tls13_alert_sent_cb, + .phh_recv = tls13_phh_received_cb, + .phh_sent = tls13_phh_done_cb, +}; + +int +tls13_quic_init(struct tls13_ctx *ctx) +{ + BIO *bio; + + tls13_record_layer_set_callbacks(ctx->rl, &quic_rl_callbacks, ctx); + + ctx->middlebox_compat = 0; + + /* + * QUIC does not use BIOs, however we currently expect a BIO to exist + * for status handling. + */ + if ((bio = BIO_new(BIO_s_null())) == NULL) + return 0; + + SSL_set_bio(ctx->ssl, bio, bio); + bio = NULL; + + return 1; +} diff --git a/ssl/tls13_record.c b/ssl/tls13_record.c new file mode 100644 index 0000000..dbc835c --- /dev/null +++ b/ssl/tls13_record.c @@ -0,0 +1,186 @@ +/* $OpenBSD: tls13_record.c,v 1.10 2022/07/22 19:33:53 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "tls13_internal.h" +#include "tls13_record.h" + +struct tls13_record { + uint16_t version; + uint8_t content_type; + size_t rec_len; + uint8_t *data; + size_t data_len; + CBS cbs; + + struct tls_buffer *buf; +}; + +struct tls13_record * +tls13_record_new(void) +{ + struct tls13_record *rec = NULL; + + if ((rec = calloc(1, sizeof(struct tls13_record))) == NULL) + goto err; + if ((rec->buf = tls_buffer_new(TLS13_RECORD_MAX_LEN)) == NULL) + goto err; + + return rec; + + err: + tls13_record_free(rec); + + return NULL; +} + +void +tls13_record_free(struct tls13_record *rec) +{ + if (rec == NULL) + return; + + tls_buffer_free(rec->buf); + + freezero(rec->data, rec->data_len); + freezero(rec, sizeof(struct tls13_record)); +} + +uint16_t +tls13_record_version(struct tls13_record *rec) +{ + return rec->version; +} + +uint8_t +tls13_record_content_type(struct tls13_record *rec) +{ + return rec->content_type; +} + +int +tls13_record_header(struct tls13_record *rec, CBS *cbs) +{ + if (rec->data_len < TLS13_RECORD_HEADER_LEN) + return 0; + + CBS_init(cbs, rec->data, TLS13_RECORD_HEADER_LEN); + + return 1; +} + +int +tls13_record_content(struct tls13_record *rec, CBS *cbs) +{ + CBS content; + + tls13_record_data(rec, &content); + + if (!CBS_skip(&content, TLS13_RECORD_HEADER_LEN)) + return 0; + + CBS_dup(&content, cbs); + + return 1; +} + +void +tls13_record_data(struct tls13_record *rec, CBS *cbs) +{ + CBS_init(cbs, rec->data, rec->data_len); +} + +int +tls13_record_set_data(struct tls13_record *rec, uint8_t *data, size_t data_len) +{ + if (data_len > TLS13_RECORD_MAX_LEN) + return 0; + + freezero(rec->data, rec->data_len); + rec->data = data; + rec->data_len = data_len; + CBS_init(&rec->cbs, rec->data, rec->data_len); + + return 1; +} + +ssize_t +tls13_record_recv(struct tls13_record *rec, tls_read_cb wire_read, + void *wire_arg) +{ + uint16_t rec_len, rec_version; + uint8_t content_type; + ssize_t ret; + CBS cbs; + + if (rec->data != NULL) + return TLS13_IO_FAILURE; + + if (rec->content_type == 0) { + if ((ret = tls_buffer_extend(rec->buf, + TLS13_RECORD_HEADER_LEN, wire_read, wire_arg)) <= 0) + return ret; + + if (!tls_buffer_data(rec->buf, &cbs)) + return TLS13_IO_FAILURE; + + if (!CBS_get_u8(&cbs, &content_type)) + return TLS13_IO_FAILURE; + if (!CBS_get_u16(&cbs, &rec_version)) + return TLS13_IO_FAILURE; + if (!CBS_get_u16(&cbs, &rec_len)) + return TLS13_IO_FAILURE; + + if ((rec_version >> 8) != SSL3_VERSION_MAJOR) + return TLS13_IO_RECORD_VERSION; + if (rec_len > TLS13_RECORD_MAX_CIPHERTEXT_LEN) + return TLS13_IO_RECORD_OVERFLOW; + + rec->content_type = content_type; + rec->version = rec_version; + rec->rec_len = rec_len; + } + + if ((ret = tls_buffer_extend(rec->buf, + TLS13_RECORD_HEADER_LEN + rec->rec_len, wire_read, wire_arg)) <= 0) + return ret; + + if (!tls_buffer_finish(rec->buf, &rec->data, &rec->data_len)) + return TLS13_IO_FAILURE; + + return rec->data_len; +} + +ssize_t +tls13_record_send(struct tls13_record *rec, tls_write_cb wire_write, + void *wire_arg) +{ + ssize_t ret; + + if (rec->data == NULL) + return TLS13_IO_FAILURE; + + while (CBS_len(&rec->cbs) > 0) { + if ((ret = wire_write(CBS_data(&rec->cbs), + CBS_len(&rec->cbs), wire_arg)) <= 0) + return ret; + + if (!CBS_skip(&rec->cbs, ret)) + return TLS13_IO_FAILURE; + } + + return rec->data_len; +} diff --git a/ssl/tls13_record.h b/ssl/tls13_record.h new file mode 100644 index 0000000..18e4fa1 --- /dev/null +++ b/ssl/tls13_record.h @@ -0,0 +1,66 @@ +/* $OpenBSD: tls13_record.h,v 1.5 2021/10/23 13:12:14 jsing Exp $ */ +/* + * Copyright (c) 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS13_RECORD_H +#define HEADER_TLS13_RECORD_H + +#include "bytestring.h" + +__BEGIN_HIDDEN_DECLS + +/* + * TLSv1.3 Record Protocol - RFC 8446 section 5. + * + * The maximum plaintext is 2^14, however for inner plaintext an additional + * byte is allowed for the content type. A maximum AEAD overhead of 255-bytes + * is permitted, along with a 5-byte header, giving a maximum size of + * 5 + 2^14 + 1 + 255 = 16,645-bytes. + */ +#define TLS13_RECORD_HEADER_LEN 5 +#define TLS13_RECORD_MAX_AEAD_OVERHEAD 255 +#define TLS13_RECORD_MAX_PLAINTEXT_LEN 16384 +#define TLS13_RECORD_MAX_INNER_PLAINTEXT_LEN \ + (TLS13_RECORD_MAX_PLAINTEXT_LEN + 1) +#define TLS13_RECORD_MAX_CIPHERTEXT_LEN \ + (TLS13_RECORD_MAX_INNER_PLAINTEXT_LEN + TLS13_RECORD_MAX_AEAD_OVERHEAD) +#define TLS13_RECORD_MAX_LEN \ + (TLS13_RECORD_HEADER_LEN + TLS13_RECORD_MAX_CIPHERTEXT_LEN) + +/* + * TLSv1.3 Per-Record Nonces and Sequence Numbers - RFC 8446 section 5.3. + */ +#define TLS13_RECORD_SEQ_NUM_LEN 8 + +struct tls13_record; + +struct tls13_record *tls13_record_new(void); +void tls13_record_free(struct tls13_record *_rec); +uint16_t tls13_record_version(struct tls13_record *_rec); +uint8_t tls13_record_content_type(struct tls13_record *_rec); +int tls13_record_header(struct tls13_record *_rec, CBS *_cbs); +int tls13_record_content(struct tls13_record *_rec, CBS *_cbs); +void tls13_record_data(struct tls13_record *_rec, CBS *_cbs); +int tls13_record_set_data(struct tls13_record *_rec, uint8_t *_data, + size_t _data_len); +ssize_t tls13_record_recv(struct tls13_record *_rec, tls_read_cb _wire_read, + void *_wire_arg); +ssize_t tls13_record_send(struct tls13_record *_rec, tls_write_cb _wire_write, + void *_wire_arg); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls13_record_layer.c b/ssl/tls13_record_layer.c new file mode 100644 index 0000000..4ae4e29 --- /dev/null +++ b/ssl/tls13_record_layer.c @@ -0,0 +1,1222 @@ +/* $OpenBSD: tls13_record_layer.c,v 1.72 2022/11/11 17:15:27 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "tls13_internal.h" +#include "tls13_record.h" +#include "tls_content.h" + +static ssize_t tls13_record_layer_write_chunk(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *buf, size_t n); +static ssize_t tls13_record_layer_write_record(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len); + +struct tls13_record_protection { + EVP_AEAD_CTX *aead_ctx; + struct tls13_secret iv; + struct tls13_secret nonce; + uint8_t seq_num[TLS13_RECORD_SEQ_NUM_LEN]; +}; + +struct tls13_record_protection * +tls13_record_protection_new(void) +{ + return calloc(1, sizeof(struct tls13_record_protection)); +} + +void +tls13_record_protection_clear(struct tls13_record_protection *rp) +{ + EVP_AEAD_CTX_free(rp->aead_ctx); + + tls13_secret_cleanup(&rp->iv); + tls13_secret_cleanup(&rp->nonce); + + memset(rp, 0, sizeof(*rp)); +} + +void +tls13_record_protection_free(struct tls13_record_protection *rp) +{ + if (rp == NULL) + return; + + tls13_record_protection_clear(rp); + + freezero(rp, sizeof(struct tls13_record_protection)); +} + +struct tls13_record_layer { + uint16_t legacy_version; + + int ccs_allowed; + int ccs_seen; + int ccs_sent; + int handshake_completed; + int legacy_alerts_allowed; + int phh; + int phh_retry; + + /* + * Read and/or write channels are closed due to an alert being + * sent or received. In the case of an error alert both channels + * are closed, whereas in the case of a close notify only one + * channel is closed. + */ + int read_closed; + int write_closed; + + struct tls13_record *rrec; + + struct tls13_record *wrec; + uint8_t wrec_content_type; + size_t wrec_appdata_len; + size_t wrec_content_len; + + /* Alert to be sent on return from current read handler. */ + uint8_t alert; + + /* Pending alert messages. */ + uint8_t *alert_data; + size_t alert_len; + uint8_t alert_level; + uint8_t alert_desc; + + /* Pending post-handshake handshake messages (RFC 8446, section 4.6). */ + CBS phh_cbs; + uint8_t *phh_data; + size_t phh_len; + + /* Content from opened records. */ + struct tls_content *rcontent; + + /* Record protection. */ + const EVP_MD *hash; + const EVP_AEAD *aead; + struct tls13_record_protection *read; + struct tls13_record_protection *write; + + /* Callbacks. */ + struct tls13_record_layer_callbacks cb; + void *cb_arg; +}; + +static void +tls13_record_layer_rrec_free(struct tls13_record_layer *rl) +{ + tls13_record_free(rl->rrec); + rl->rrec = NULL; +} + +static void +tls13_record_layer_wrec_free(struct tls13_record_layer *rl) +{ + tls13_record_free(rl->wrec); + rl->wrec = NULL; +} + +struct tls13_record_layer * +tls13_record_layer_new(const struct tls13_record_layer_callbacks *callbacks, + void *cb_arg) +{ + struct tls13_record_layer *rl; + + if ((rl = calloc(1, sizeof(struct tls13_record_layer))) == NULL) + goto err; + + if ((rl->rcontent = tls_content_new()) == NULL) + goto err; + + if ((rl->read = tls13_record_protection_new()) == NULL) + goto err; + if ((rl->write = tls13_record_protection_new()) == NULL) + goto err; + + rl->legacy_version = TLS1_2_VERSION; + + tls13_record_layer_set_callbacks(rl, callbacks, cb_arg); + + return rl; + + err: + tls13_record_layer_free(rl); + + return NULL; +} + +void +tls13_record_layer_free(struct tls13_record_layer *rl) +{ + if (rl == NULL) + return; + + tls13_record_layer_rrec_free(rl); + tls13_record_layer_wrec_free(rl); + + freezero(rl->alert_data, rl->alert_len); + freezero(rl->phh_data, rl->phh_len); + + tls_content_free(rl->rcontent); + + tls13_record_protection_free(rl->read); + tls13_record_protection_free(rl->write); + + freezero(rl, sizeof(struct tls13_record_layer)); +} + +void +tls13_record_layer_set_callbacks(struct tls13_record_layer *rl, + const struct tls13_record_layer_callbacks *callbacks, void *cb_arg) +{ + rl->cb = *callbacks; + rl->cb_arg = cb_arg; +} + +void +tls13_record_layer_rcontent(struct tls13_record_layer *rl, CBS *cbs) +{ + CBS_dup(tls_content_cbs(rl->rcontent), cbs); +} + +static const uint8_t tls13_max_seq_num[TLS13_RECORD_SEQ_NUM_LEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +int +tls13_record_layer_inc_seq_num(uint8_t *seq_num) +{ + int i; + + /* RFC 8446 section 5.3 - sequence numbers must not wrap. */ + if (memcmp(seq_num, tls13_max_seq_num, TLS13_RECORD_SEQ_NUM_LEN) == 0) + return 0; + + for (i = TLS13_RECORD_SEQ_NUM_LEN - 1; i >= 0; i--) { + if (++seq_num[i] != 0) + break; + } + + return 1; +} + +static int +tls13_record_layer_update_nonce(struct tls13_secret *nonce, + struct tls13_secret *iv, uint8_t *seq_num) +{ + ssize_t i, j; + + if (nonce->len != iv->len) + return 0; + + /* + * RFC 8446 section 5.3 - sequence number is zero padded and XOR'd + * with the IV to produce a per-record nonce. The IV will also be + * at least 8-bytes in length. + */ + for (i = nonce->len - 1, j = TLS13_RECORD_SEQ_NUM_LEN - 1; i >= 0; i--, j--) + nonce->data[i] = iv->data[i] ^ (j >= 0 ? seq_num[j] : 0); + + return 1; +} + +void +tls13_record_layer_allow_ccs(struct tls13_record_layer *rl, int allow) +{ + rl->ccs_allowed = allow; +} + +void +tls13_record_layer_allow_legacy_alerts(struct tls13_record_layer *rl, int allow) +{ + rl->legacy_alerts_allowed = allow; +} + +void +tls13_record_layer_set_aead(struct tls13_record_layer *rl, + const EVP_AEAD *aead) +{ + rl->aead = aead; +} + +void +tls13_record_layer_set_hash(struct tls13_record_layer *rl, + const EVP_MD *hash) +{ + rl->hash = hash; +} + +void +tls13_record_layer_set_legacy_version(struct tls13_record_layer *rl, + uint16_t version) +{ + rl->legacy_version = version; +} + +void +tls13_record_layer_handshake_completed(struct tls13_record_layer *rl) +{ + rl->handshake_completed = 1; +} + +void +tls13_record_layer_set_retry_after_phh(struct tls13_record_layer *rl, int retry) +{ + rl->phh_retry = retry; +} + +static ssize_t +tls13_record_layer_process_alert(struct tls13_record_layer *rl) +{ + uint8_t alert_level, alert_desc; + ssize_t ret = TLS13_IO_FAILURE; + + /* + * RFC 8446 - sections 5.1 and 6. + * + * A TLSv1.3 alert record can only contain a single alert - this means + * that processing the alert must consume all of the record. The alert + * will result in one of three things - continuation (user_cancelled), + * read channel closure (close_notify) or termination (all others). + */ + if (tls_content_type(rl->rcontent) != SSL3_RT_ALERT) + return TLS13_IO_FAILURE; + + if (!CBS_get_u8(tls_content_cbs(rl->rcontent), &alert_level)) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + if (!CBS_get_u8(tls_content_cbs(rl->rcontent), &alert_desc)) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + + if (tls_content_remaining(rl->rcontent) != 0) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + + tls_content_clear(rl->rcontent); + + /* + * Alert level is ignored for closure alerts (RFC 8446 section 6.1), + * however for error alerts (RFC 8446 section 6.2), the alert level + * must be specified as fatal. + */ + if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY) { + rl->read_closed = 1; + ret = TLS13_IO_EOF; + } else if (alert_desc == TLS13_ALERT_USER_CANCELED) { + /* Ignored at the record layer. */ + ret = TLS13_IO_WANT_RETRY; + } else if (alert_level == TLS13_ALERT_LEVEL_FATAL) { + rl->read_closed = 1; + rl->write_closed = 1; + ret = TLS13_IO_ALERT; + } else if (rl->legacy_alerts_allowed && + alert_level == TLS13_ALERT_LEVEL_WARNING) { + /* Ignored and not passed to the callback. */ + return TLS13_IO_WANT_RETRY; + } else { + return tls13_send_alert(rl, TLS13_ALERT_ILLEGAL_PARAMETER); + } + + rl->cb.alert_recv(alert_desc, rl->cb_arg); + + return ret; +} + +static ssize_t +tls13_record_layer_send_alert(struct tls13_record_layer *rl) +{ + ssize_t ret; + + /* This has to fit into a single record, per RFC 8446 section 5.1. */ + if ((ret = tls13_record_layer_write_record(rl, SSL3_RT_ALERT, + rl->alert_data, rl->alert_len)) != rl->alert_len) { + if (ret == TLS13_IO_EOF) + ret = TLS13_IO_ALERT; + return ret; + } + + freezero(rl->alert_data, rl->alert_len); + rl->alert_data = NULL; + rl->alert_len = 0; + + if (rl->alert_desc == TLS13_ALERT_CLOSE_NOTIFY) { + rl->write_closed = 1; + ret = TLS13_IO_SUCCESS; + } else if (rl->alert_desc == TLS13_ALERT_USER_CANCELED) { + /* Ignored at the record layer. */ + ret = TLS13_IO_SUCCESS; + } else { + rl->read_closed = 1; + rl->write_closed = 1; + ret = TLS13_IO_ALERT; + } + + rl->cb.alert_sent(rl->alert_desc, rl->cb_arg); + + return ret; +} + +static ssize_t +tls13_record_layer_send_phh(struct tls13_record_layer *rl) +{ + ssize_t ret; + + /* Push out pending post-handshake handshake messages. */ + if ((ret = tls13_record_layer_write_chunk(rl, SSL3_RT_HANDSHAKE, + CBS_data(&rl->phh_cbs), CBS_len(&rl->phh_cbs))) <= 0) + return ret; + if (!CBS_skip(&rl->phh_cbs, ret)) + return TLS13_IO_FAILURE; + if (CBS_len(&rl->phh_cbs) != 0) + return TLS13_IO_WANT_RETRY; + + freezero(rl->phh_data, rl->phh_len); + rl->phh_data = NULL; + rl->phh_len = 0; + + CBS_init(&rl->phh_cbs, rl->phh_data, rl->phh_len); + + rl->cb.phh_sent(rl->cb_arg); + + return TLS13_IO_SUCCESS; +} + +ssize_t +tls13_record_layer_send_pending(struct tls13_record_layer *rl) +{ + /* + * If an alert is pending, then it needs to be sent. However, + * if we're already part of the way through sending post-handshake + * handshake messages, then we need to finish that first... + */ + + if (rl->phh_data != NULL && CBS_len(&rl->phh_cbs) != rl->phh_len) + return tls13_record_layer_send_phh(rl); + + if (rl->alert_data != NULL) + return tls13_record_layer_send_alert(rl); + + if (rl->phh_data != NULL) + return tls13_record_layer_send_phh(rl); + + return TLS13_IO_SUCCESS; +} + +static ssize_t +tls13_record_layer_enqueue_alert(struct tls13_record_layer *rl, + uint8_t alert_level, uint8_t alert_desc) +{ + CBB cbb; + + if (rl->alert_data != NULL) + return TLS13_IO_FAILURE; + + if (!CBB_init(&cbb, 0)) + goto err; + + if (!CBB_add_u8(&cbb, alert_level)) + goto err; + if (!CBB_add_u8(&cbb, alert_desc)) + goto err; + if (!CBB_finish(&cbb, &rl->alert_data, &rl->alert_len)) + goto err; + + rl->alert_level = alert_level; + rl->alert_desc = alert_desc; + + return tls13_record_layer_send_pending(rl); + + err: + CBB_cleanup(&cbb); + + return TLS13_IO_FAILURE; +} + +ssize_t +tls13_record_layer_phh(struct tls13_record_layer *rl, CBS *cbs) +{ + if (rl->phh_data != NULL) + return TLS13_IO_FAILURE; + + if (!CBS_stow(cbs, &rl->phh_data, &rl->phh_len)) + return TLS13_IO_FAILURE; + + CBS_init(&rl->phh_cbs, rl->phh_data, rl->phh_len); + + return tls13_record_layer_send_pending(rl); +} + +static int +tls13_record_layer_set_traffic_key(const EVP_AEAD *aead, const EVP_MD *hash, + struct tls13_record_protection *rp, struct tls13_secret *traffic_key) +{ + struct tls13_secret context = { .data = "", .len = 0 }; + struct tls13_secret key = { .data = NULL, .len = 0 }; + int ret = 0; + + tls13_record_protection_clear(rp); + + if ((rp->aead_ctx = EVP_AEAD_CTX_new()) == NULL) + return 0; + + if (!tls13_secret_init(&rp->iv, EVP_AEAD_nonce_length(aead))) + goto err; + if (!tls13_secret_init(&rp->nonce, EVP_AEAD_nonce_length(aead))) + goto err; + if (!tls13_secret_init(&key, EVP_AEAD_key_length(aead))) + goto err; + + if (!tls13_hkdf_expand_label(&rp->iv, hash, traffic_key, "iv", &context)) + goto err; + if (!tls13_hkdf_expand_label(&key, hash, traffic_key, "key", &context)) + goto err; + + if (!EVP_AEAD_CTX_init(rp->aead_ctx, aead, key.data, key.len, + EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) + goto err; + + ret = 1; + + err: + tls13_secret_cleanup(&key); + + return ret; +} + +int +tls13_record_layer_set_read_traffic_key(struct tls13_record_layer *rl, + struct tls13_secret *read_key, enum ssl_encryption_level_t read_level) +{ + if (rl->cb.set_read_traffic_key != NULL) + return rl->cb.set_read_traffic_key(read_key, read_level, + rl->cb_arg); + + return tls13_record_layer_set_traffic_key(rl->aead, rl->hash, + rl->read, read_key); +} + +int +tls13_record_layer_set_write_traffic_key(struct tls13_record_layer *rl, + struct tls13_secret *write_key, enum ssl_encryption_level_t write_level) +{ + if (rl->cb.set_write_traffic_key != NULL) + return rl->cb.set_write_traffic_key(write_key, write_level, + rl->cb_arg); + + return tls13_record_layer_set_traffic_key(rl->aead, rl->hash, + rl->write, write_key); +} + +static int +tls13_record_layer_open_record_plaintext(struct tls13_record_layer *rl) +{ + CBS cbs; + + if (rl->aead != NULL) + return 0; + + /* + * We're still operating in plaintext mode, so just copy the + * content from the record to the plaintext buffer. + */ + if (!tls13_record_content(rl->rrec, &cbs)) + return 0; + + if (CBS_len(&cbs) > TLS13_RECORD_MAX_PLAINTEXT_LEN) { + rl->alert = TLS13_ALERT_RECORD_OVERFLOW; + return 0; + } + + if (!tls_content_dup_data(rl->rcontent, + tls13_record_content_type(rl->rrec), CBS_data(&cbs), CBS_len(&cbs))) + return 0; + + return 1; +} + +static int +tls13_record_layer_open_record_protected(struct tls13_record_layer *rl) +{ + CBS header, enc_record, inner; + uint8_t *content = NULL; + size_t content_len = 0; + uint8_t content_type; + size_t out_len; + + if (rl->aead == NULL) + goto err; + + if (!tls13_record_header(rl->rrec, &header)) + goto err; + if (!tls13_record_content(rl->rrec, &enc_record)) + goto err; + + /* XXX - minus tag len? */ + if ((content = calloc(1, CBS_len(&enc_record))) == NULL) + goto err; + content_len = CBS_len(&enc_record); + + if (!tls13_record_layer_update_nonce(&rl->read->nonce, &rl->read->iv, + rl->read->seq_num)) + goto err; + + if (!EVP_AEAD_CTX_open(rl->read->aead_ctx, + content, &out_len, content_len, + rl->read->nonce.data, rl->read->nonce.len, + CBS_data(&enc_record), CBS_len(&enc_record), + CBS_data(&header), CBS_len(&header))) + goto err; + + if (out_len > TLS13_RECORD_MAX_INNER_PLAINTEXT_LEN) { + rl->alert = TLS13_ALERT_RECORD_OVERFLOW; + goto err; + } + + if (!tls13_record_layer_inc_seq_num(rl->read->seq_num)) + goto err; + + /* + * The real content type is hidden at the end of the record content and + * it may be followed by padding that consists of one or more zeroes. + * Time to hunt for that elusive content type! + */ + CBS_init(&inner, content, out_len); + content_type = 0; + while (CBS_get_last_u8(&inner, &content_type)) { + if (content_type != 0) + break; + } + if (content_type == 0) { + /* Unexpected message per RFC 8446 section 5.4. */ + rl->alert = TLS13_ALERT_UNEXPECTED_MESSAGE; + goto err; + } + if (CBS_len(&inner) > TLS13_RECORD_MAX_PLAINTEXT_LEN) { + rl->alert = TLS13_ALERT_RECORD_OVERFLOW; + goto err; + } + + tls_content_set_data(rl->rcontent, content_type, CBS_data(&inner), + CBS_len(&inner)); + + return 1; + + err: + freezero(content, content_len); + + return 0; +} + +static int +tls13_record_layer_open_record(struct tls13_record_layer *rl) +{ + if (rl->handshake_completed && rl->aead == NULL) + return 0; + + if (rl->aead == NULL) + return tls13_record_layer_open_record_plaintext(rl); + + return tls13_record_layer_open_record_protected(rl); +} + +static int +tls13_record_layer_seal_record_plaintext(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len) +{ + uint8_t *data = NULL; + size_t data_len = 0; + CBB cbb, body; + + /* + * Allow dummy CCS messages to be sent in plaintext even when + * record protection has been engaged, as long as the handshake + * has not yet completed. + */ + if (rl->handshake_completed) + return 0; + if (rl->aead != NULL && content_type != SSL3_RT_CHANGE_CIPHER_SPEC) + return 0; + + /* + * We're still operating in plaintext mode, so just copy the + * content into the record. + */ + if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN + content_len)) + goto err; + + if (!CBB_add_u8(&cbb, content_type)) + goto err; + if (!CBB_add_u16(&cbb, rl->legacy_version)) + goto err; + if (!CBB_add_u16_length_prefixed(&cbb, &body)) + goto err; + if (!CBB_add_bytes(&body, content, content_len)) + goto err; + + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (!tls13_record_set_data(rl->wrec, data, data_len)) + goto err; + + rl->wrec_content_len = content_len; + rl->wrec_content_type = content_type; + + return 1; + + err: + CBB_cleanup(&cbb); + freezero(data, data_len); + + return 0; +} + +static int +tls13_record_layer_seal_record_protected(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len) +{ + uint8_t *data = NULL, *header = NULL, *inner = NULL; + size_t data_len = 0, header_len = 0, inner_len = 0; + uint8_t *enc_record; + size_t enc_record_len; + ssize_t ret = 0; + size_t out_len; + CBB cbb; + + if (rl->aead == NULL) + return 0; + + memset(&cbb, 0, sizeof(cbb)); + + /* Build inner plaintext. */ + if (!CBB_init(&cbb, content_len + 1)) + goto err; + if (!CBB_add_bytes(&cbb, content, content_len)) + goto err; + if (!CBB_add_u8(&cbb, content_type)) + goto err; + /* XXX - padding? */ + if (!CBB_finish(&cbb, &inner, &inner_len)) + goto err; + + if (inner_len > TLS13_RECORD_MAX_INNER_PLAINTEXT_LEN) + goto err; + + /* XXX EVP_AEAD_max_tag_len vs EVP_AEAD_CTX_tag_len. */ + enc_record_len = inner_len + EVP_AEAD_max_tag_len(rl->aead); + if (enc_record_len > TLS13_RECORD_MAX_CIPHERTEXT_LEN) + goto err; + + /* Build the record header. */ + if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN)) + goto err; + if (!CBB_add_u8(&cbb, SSL3_RT_APPLICATION_DATA)) + goto err; + if (!CBB_add_u16(&cbb, TLS1_2_VERSION)) + goto err; + if (!CBB_add_u16(&cbb, enc_record_len)) + goto err; + if (!CBB_finish(&cbb, &header, &header_len)) + goto err; + + /* Build the actual record. */ + if (!CBB_init(&cbb, TLS13_RECORD_HEADER_LEN + enc_record_len)) + goto err; + if (!CBB_add_bytes(&cbb, header, header_len)) + goto err; + if (!CBB_add_space(&cbb, &enc_record, enc_record_len)) + goto err; + if (!CBB_finish(&cbb, &data, &data_len)) + goto err; + + if (!tls13_record_layer_update_nonce(&rl->write->nonce, + &rl->write->iv, rl->write->seq_num)) + goto err; + + /* + * XXX - consider a EVP_AEAD_CTX_seal_iov() that takes an iovec... + * this would avoid a copy since the inner would be passed as two + * separate pieces. + */ + if (!EVP_AEAD_CTX_seal(rl->write->aead_ctx, + enc_record, &out_len, enc_record_len, + rl->write->nonce.data, rl->write->nonce.len, + inner, inner_len, header, header_len)) + goto err; + + if (out_len != enc_record_len) + goto err; + + if (!tls13_record_layer_inc_seq_num(rl->write->seq_num)) + goto err; + + if (!tls13_record_set_data(rl->wrec, data, data_len)) + goto err; + + rl->wrec_content_len = content_len; + rl->wrec_content_type = content_type; + + data = NULL; + data_len = 0; + + ret = 1; + + err: + CBB_cleanup(&cbb); + + freezero(data, data_len); + freezero(header, header_len); + freezero(inner, inner_len); + + return ret; +} + +static int +tls13_record_layer_seal_record(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len) +{ + if (rl->handshake_completed && rl->aead == NULL) + return 0; + + tls13_record_layer_wrec_free(rl); + + if ((rl->wrec = tls13_record_new()) == NULL) + return 0; + + if (rl->aead == NULL || content_type == SSL3_RT_CHANGE_CIPHER_SPEC) + return tls13_record_layer_seal_record_plaintext(rl, + content_type, content, content_len); + + return tls13_record_layer_seal_record_protected(rl, content_type, + content, content_len); +} + +static ssize_t +tls13_record_layer_read_record(struct tls13_record_layer *rl) +{ + uint8_t content_type, ccs; + ssize_t ret; + CBS cbs; + + if (rl->rrec == NULL) { + if ((rl->rrec = tls13_record_new()) == NULL) + goto err; + } + + if ((ret = tls13_record_recv(rl->rrec, rl->cb.wire_read, rl->cb_arg)) <= 0) { + switch (ret) { + case TLS13_IO_RECORD_VERSION: + return tls13_send_alert(rl, TLS13_ALERT_PROTOCOL_VERSION); + case TLS13_IO_RECORD_OVERFLOW: + return tls13_send_alert(rl, TLS13_ALERT_RECORD_OVERFLOW); + } + return ret; + } + + content_type = tls13_record_content_type(rl->rrec); + + /* + * In response to a client hello we may receive an alert in a + * record with a legacy version. Otherwise enforce that the + * legacy record version is 0x0303 per RFC 8446, section 5.1. + */ + if (rl->legacy_version == TLS1_2_VERSION && + tls13_record_version(rl->rrec) != TLS1_2_VERSION && + (content_type != SSL3_RT_ALERT || !rl->legacy_alerts_allowed)) + return tls13_send_alert(rl, TLS13_ALERT_PROTOCOL_VERSION); + + /* + * Bag of hacks ahead... after the first ClientHello message has been + * sent or received and before the peer's Finished message has been + * received, we may receive an unencrypted ChangeCipherSpec record + * (see RFC 8446 section 5 and appendix D.4). This record must be + * ignored. + */ + if (content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { + if (!rl->ccs_allowed || rl->ccs_seen >= 2) + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + if (!tls13_record_content(rl->rrec, &cbs)) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + if (!CBS_get_u8(&cbs, &ccs)) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + if (ccs != 1) + return tls13_send_alert(rl, TLS13_ALERT_ILLEGAL_PARAMETER); + if (CBS_len(&cbs) != 0) + return tls13_send_alert(rl, TLS13_ALERT_DECODE_ERROR); + rl->ccs_seen++; + tls13_record_layer_rrec_free(rl); + return TLS13_IO_WANT_RETRY; + } + + /* + * Once record protection is engaged, we should only receive + * protected application data messages (aside from the + * dummy ChangeCipherSpec messages, handled above). + */ + if (rl->aead != NULL && content_type != SSL3_RT_APPLICATION_DATA) + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + + if (!tls13_record_layer_open_record(rl)) + goto err; + + tls13_record_layer_rrec_free(rl); + + /* + * On receiving a handshake or alert record with empty inner plaintext, + * we must terminate the connection with an unexpected_message alert. + * See RFC 8446 section 5.4. + */ + if (tls_content_remaining(rl->rcontent) == 0 && + (tls_content_type(rl->rcontent) == SSL3_RT_ALERT || + tls_content_type(rl->rcontent) == SSL3_RT_HANDSHAKE)) + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + + switch (tls_content_type(rl->rcontent)) { + case SSL3_RT_ALERT: + return tls13_record_layer_process_alert(rl); + + case SSL3_RT_HANDSHAKE: + break; + + case SSL3_RT_APPLICATION_DATA: + if (!rl->handshake_completed) + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + break; + + default: + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + } + + return TLS13_IO_SUCCESS; + + err: + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_record_layer_pending(struct tls13_record_layer *rl, uint8_t content_type) +{ + if (tls_content_type(rl->rcontent) != content_type) + return 0; + + return tls_content_remaining(rl->rcontent); +} + +static ssize_t +tls13_record_layer_recv_phh(struct tls13_record_layer *rl) +{ + ssize_t ret = TLS13_IO_FAILURE; + + rl->phh = 1; + + /* + * The post handshake handshake receive callback is allowed to return: + * + * TLS13_IO_WANT_POLLIN need more handshake data. + * TLS13_IO_WANT_POLLOUT got whole handshake message, response enqueued. + * TLS13_IO_SUCCESS got the whole handshake, nothing more to do. + * TLS13_IO_FAILURE something broke. + */ + if (rl->cb.phh_recv != NULL) + ret = rl->cb.phh_recv(rl->cb_arg); + + tls_content_clear(rl->rcontent); + + /* Leave post handshake handshake mode unless we need more data. */ + if (ret != TLS13_IO_WANT_POLLIN) + rl->phh = 0; + + if (ret == TLS13_IO_SUCCESS) { + if (rl->phh_retry) + return TLS13_IO_WANT_RETRY; + + return TLS13_IO_WANT_POLLIN; + } + + return ret; +} + +static ssize_t +tls13_record_layer_read_internal(struct tls13_record_layer *rl, + uint8_t content_type, uint8_t *buf, size_t n, int peek) +{ + ssize_t ret; + + if ((ret = tls13_record_layer_send_pending(rl)) != TLS13_IO_SUCCESS) + return ret; + + if (rl->read_closed) + return TLS13_IO_EOF; + + /* If necessary, pull up the next record. */ + if (tls_content_remaining(rl->rcontent) == 0) { + if ((ret = tls13_record_layer_read_record(rl)) <= 0) + return ret; + + /* + * We may have read a valid 0-byte application data record, + * in which case we need to read the next record. + */ + if (tls_content_remaining(rl->rcontent) == 0) + return TLS13_IO_WANT_POLLIN; + } + + /* + * If we are in post handshake handshake mode, we must not see + * any record type that isn't a handshake until we are done. + */ + if (rl->phh && tls_content_type(rl->rcontent) != SSL3_RT_HANDSHAKE) + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + + /* + * Handshake content can appear as post-handshake messages (yup, + * the RFC reused the same content type...), which means we can + * be trying to read application data and need to handle a + * post-handshake handshake message instead... + */ + if (tls_content_type(rl->rcontent) != content_type) { + if (tls_content_type(rl->rcontent) == SSL3_RT_HANDSHAKE) { + if (rl->handshake_completed) + return tls13_record_layer_recv_phh(rl); + } + return tls13_send_alert(rl, TLS13_ALERT_UNEXPECTED_MESSAGE); + } + + if (peek) + return tls_content_peek(rl->rcontent, buf, n); + + return tls_content_read(rl->rcontent, buf, n); +} + +static ssize_t +tls13_record_layer_peek(struct tls13_record_layer *rl, uint8_t content_type, + uint8_t *buf, size_t n) +{ + ssize_t ret; + + do { + ret = tls13_record_layer_read_internal(rl, content_type, buf, n, 1); + } while (ret == TLS13_IO_WANT_RETRY); + + if (rl->alert != 0) + return tls13_send_alert(rl, rl->alert); + + return ret; +} + +static ssize_t +tls13_record_layer_read(struct tls13_record_layer *rl, uint8_t content_type, + uint8_t *buf, size_t n) +{ + ssize_t ret; + + do { + ret = tls13_record_layer_read_internal(rl, content_type, buf, n, 0); + } while (ret == TLS13_IO_WANT_RETRY); + + if (rl->alert != 0) + return tls13_send_alert(rl, rl->alert); + + return ret; +} + +static ssize_t +tls13_record_layer_write_record(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *content, size_t content_len) +{ + ssize_t ret; + + if (rl->write_closed) + return TLS13_IO_EOF; + + /* + * If we pushed out application data while handling other messages, + * we need to return content length on the next call. + */ + if (content_type == SSL3_RT_APPLICATION_DATA && + rl->wrec_appdata_len != 0) { + ret = rl->wrec_appdata_len; + rl->wrec_appdata_len = 0; + return ret; + } + + /* See if there is an existing record and attempt to push it out... */ + if (rl->wrec != NULL) { + if ((ret = tls13_record_send(rl->wrec, rl->cb.wire_write, + rl->cb_arg)) <= 0) + return ret; + tls13_record_layer_wrec_free(rl); + + if (rl->wrec_content_type == content_type) { + ret = rl->wrec_content_len; + rl->wrec_content_len = 0; + rl->wrec_content_type = 0; + return ret; + } + + /* + * The only partial record type should be application data. + * All other cases are handled to completion. + */ + if (rl->wrec_content_type != SSL3_RT_APPLICATION_DATA) + return TLS13_IO_FAILURE; + rl->wrec_appdata_len = rl->wrec_content_len; + } + + if (content_len > TLS13_RECORD_MAX_PLAINTEXT_LEN) + goto err; + + if (!tls13_record_layer_seal_record(rl, content_type, content, content_len)) + goto err; + + if ((ret = tls13_record_send(rl->wrec, rl->cb.wire_write, rl->cb_arg)) <= 0) + return ret; + + tls13_record_layer_wrec_free(rl); + + return content_len; + + err: + return TLS13_IO_FAILURE; +} + +static ssize_t +tls13_record_layer_write_chunk(struct tls13_record_layer *rl, + uint8_t content_type, const uint8_t *buf, size_t n) +{ + if (n > TLS13_RECORD_MAX_PLAINTEXT_LEN) + n = TLS13_RECORD_MAX_PLAINTEXT_LEN; + + return tls13_record_layer_write_record(rl, content_type, buf, n); +} + +static ssize_t +tls13_record_layer_write(struct tls13_record_layer *rl, uint8_t content_type, + const uint8_t *buf, size_t n) +{ + ssize_t ret; + + do { + ret = tls13_record_layer_send_pending(rl); + } while (ret == TLS13_IO_WANT_RETRY); + if (ret != TLS13_IO_SUCCESS) + return ret; + + do { + ret = tls13_record_layer_write_chunk(rl, content_type, buf, n); + } while (ret == TLS13_IO_WANT_RETRY); + + return ret; +} + +ssize_t +tls13_record_layer_flush(struct tls13_record_layer *rl) +{ + return rl->cb.wire_flush(rl->cb_arg); +} + +static const uint8_t tls13_dummy_ccs[] = { 0x01 }; + +ssize_t +tls13_send_dummy_ccs(struct tls13_record_layer *rl) +{ + ssize_t ret; + + if (rl->ccs_sent) + return TLS13_IO_FAILURE; + + if ((ret = tls13_record_layer_write(rl, SSL3_RT_CHANGE_CIPHER_SPEC, + tls13_dummy_ccs, sizeof(tls13_dummy_ccs))) <= 0) + return ret; + + rl->ccs_sent = 1; + + return TLS13_IO_SUCCESS; +} + +ssize_t +tls13_read_handshake_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) +{ + if (rl->cb.handshake_read != NULL) + return rl->cb.handshake_read(buf, n, rl->cb_arg); + + return tls13_record_layer_read(rl, SSL3_RT_HANDSHAKE, buf, n); +} + +ssize_t +tls13_write_handshake_data(struct tls13_record_layer *rl, const uint8_t *buf, + size_t n) +{ + if (rl->cb.handshake_write != NULL) + return rl->cb.handshake_write(buf, n, rl->cb_arg); + + return tls13_record_layer_write(rl, SSL3_RT_HANDSHAKE, buf, n); +} + +ssize_t +tls13_pending_application_data(struct tls13_record_layer *rl) +{ + if (!rl->handshake_completed) + return 0; + + return tls13_record_layer_pending(rl, SSL3_RT_APPLICATION_DATA); +} + +ssize_t +tls13_peek_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) +{ + if (!rl->handshake_completed) + return TLS13_IO_FAILURE; + + return tls13_record_layer_peek(rl, SSL3_RT_APPLICATION_DATA, buf, n); +} + +ssize_t +tls13_read_application_data(struct tls13_record_layer *rl, uint8_t *buf, size_t n) +{ + if (!rl->handshake_completed) + return TLS13_IO_FAILURE; + + return tls13_record_layer_read(rl, SSL3_RT_APPLICATION_DATA, buf, n); +} + +ssize_t +tls13_write_application_data(struct tls13_record_layer *rl, const uint8_t *buf, + size_t n) +{ + if (!rl->handshake_completed) + return TLS13_IO_FAILURE; + + return tls13_record_layer_write(rl, SSL3_RT_APPLICATION_DATA, buf, n); +} + +ssize_t +tls13_send_alert(struct tls13_record_layer *rl, uint8_t alert_desc) +{ + uint8_t alert_level = TLS13_ALERT_LEVEL_FATAL; + ssize_t ret; + + if (rl->cb.alert_send != NULL) + return rl->cb.alert_send(alert_desc, rl->cb_arg); + + if (alert_desc == TLS13_ALERT_CLOSE_NOTIFY || + alert_desc == TLS13_ALERT_USER_CANCELED) + alert_level = TLS13_ALERT_LEVEL_WARNING; + + do { + ret = tls13_record_layer_enqueue_alert(rl, alert_level, + alert_desc); + } while (ret == TLS13_IO_WANT_RETRY); + + return ret; +} diff --git a/ssl/tls13_server.c b/ssl/tls13_server.c new file mode 100644 index 0000000..dfeb1e0 --- /dev/null +++ b/ssl/tls13_server.c @@ -0,0 +1,1095 @@ +/* $OpenBSD: tls13_server.c,v 1.106 2023/06/10 15:34:36 tb Exp $ */ +/* + * Copyright (c) 2019, 2020 Joel Sing + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" +#include "ssl_sigalgs.h" +#include "ssl_tlsext.h" +#include "tls13_handshake.h" +#include "tls13_internal.h" + +int +tls13_server_init(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + + if (!ssl_supported_tls_version_range(s, &ctx->hs->our_min_tls_version, + &ctx->hs->our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + return 0; + } + s->version = ctx->hs->our_max_tls_version; + + tls13_record_layer_set_retry_after_phh(ctx->rl, + (s->mode & SSL_MODE_AUTO_RETRY) != 0); + + if (!ssl_get_new_session(s, 0)) /* XXX */ + return 0; + + tls13_record_layer_set_legacy_version(ctx->rl, TLS1_VERSION); + + if (!tls1_transcript_init(s)) + return 0; + + arc4random_buf(s->s3->server_random, SSL3_RANDOM_SIZE); + + return 1; +} + +int +tls13_server_accept(struct tls13_ctx *ctx) +{ + if (ctx->mode != TLS13_HS_SERVER) + return TLS13_IO_FAILURE; + + return tls13_handshake_perform(ctx); +} + +static int +tls13_client_hello_is_legacy(CBS *cbs) +{ + CBS extensions_block, extensions, extension_data, versions; + uint16_t version, max_version = 0; + uint16_t type; + + CBS_dup(cbs, &extensions_block); + + if (!CBS_get_u16_length_prefixed(&extensions_block, &extensions)) + return 1; + + while (CBS_len(&extensions) > 0) { + if (!CBS_get_u16(&extensions, &type)) + return 1; + if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) + return 1; + + if (type != TLSEXT_TYPE_supported_versions) + continue; + if (!CBS_get_u8_length_prefixed(&extension_data, &versions)) + return 1; + while (CBS_len(&versions) > 0) { + if (!CBS_get_u16(&versions, &version)) + return 1; + if (version >= max_version) + max_version = version; + } + if (CBS_len(&extension_data) != 0) + return 1; + } + + return (max_version < TLS1_3_VERSION); +} + +int +tls13_client_hello_required_extensions(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + + /* + * RFC 8446, section 9.2. If the ClientHello has supported_versions + * containing TLSv1.3, presence or absence of some extensions requires + * presence or absence of others. + */ + + /* + * RFC 8446 section 4.2.9 - if we received a pre_shared_key, then we + * also need psk_key_exchange_modes. Otherwise, section 9.2 specifies + * that we need both signature_algorithms and supported_groups. + */ + if (tlsext_extension_seen(s, TLSEXT_TYPE_pre_shared_key)) { + if (!tlsext_extension_seen(s, + TLSEXT_TYPE_psk_key_exchange_modes)) + return 0; + } else { + if (!tlsext_extension_seen(s, TLSEXT_TYPE_signature_algorithms)) + return 0; + if (!tlsext_extension_seen(s, TLSEXT_TYPE_supported_groups)) + return 0; + } + + /* + * supported_groups and key_share must either both be present or + * both be absent. + */ + if (tlsext_extension_seen(s, TLSEXT_TYPE_supported_groups) != + tlsext_extension_seen(s, TLSEXT_TYPE_key_share)) + return 0; + + /* + * XXX - Require server_name from client? If so, we SHOULD enforce + * this here - RFC 8446, 9.2. + */ + + return 1; +} + +static const uint8_t tls13_compression_null_only[] = { 0 }; + +static int +tls13_client_hello_process(struct tls13_ctx *ctx, CBS *cbs) +{ + CBS cipher_suites, client_random, compression_methods, session_id; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + const SSL_CIPHER *cipher; + uint16_t legacy_version; + int alert_desc; + SSL *s = ctx->ssl; + int ret = 0; + + if (!CBS_get_u16(cbs, &legacy_version)) + goto err; + if (!CBS_get_bytes(cbs, &client_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBS_get_u8_length_prefixed(cbs, &session_id)) + goto err; + if (!CBS_get_u16_length_prefixed(cbs, &cipher_suites)) + goto err; + if (!CBS_get_u8_length_prefixed(cbs, &compression_methods)) + goto err; + + if (tls13_client_hello_is_legacy(cbs) || s->version < TLS1_3_VERSION) { + if (!CBS_skip(cbs, CBS_len(cbs))) + goto err; + return tls13_use_legacy_server(ctx); + } + ctx->hs->negotiated_tls_version = TLS1_3_VERSION; + ctx->hs->peer_legacy_version = legacy_version; + + /* Ensure we send subsequent alerts with the correct record version. */ + tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION); + + /* + * Ensure that the client has not requested middlebox compatibility mode + * if it is prohibited from doing so. + */ + if (!ctx->middlebox_compat && CBS_len(&session_id) != 0) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + /* Add decoded values to the current ClientHello hash */ + if (!tls13_clienthello_hash_init(ctx)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + if (!tls13_clienthello_hash_update_bytes(ctx, (void *)&legacy_version, + sizeof(legacy_version))) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + if (!tls13_clienthello_hash_update(ctx, &client_random)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + if (!tls13_clienthello_hash_update(ctx, &session_id)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + if (!tls13_clienthello_hash_update(ctx, &cipher_suites)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + if (!tls13_clienthello_hash_update(ctx, &compression_methods)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + + if (!tlsext_server_parse(s, SSL_TLSEXT_MSG_CH, cbs, &alert_desc)) { + ctx->alert = alert_desc; + goto err; + } + + /* Finalize first ClientHello hash, or validate against it */ + if (!ctx->hs->tls13.hrr) { + if (!tls13_clienthello_hash_finalize(ctx)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + } else { + if (!tls13_clienthello_hash_validate(ctx)) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + tls13_clienthello_hash_clear(&ctx->hs->tls13); + } + + if (!tls13_client_hello_required_extensions(ctx)) { + ctx->alert = TLS13_ALERT_MISSING_EXTENSION; + goto err; + } + + /* + * If we got this far we have a supported versions extension that offers + * TLS 1.3 or later. This requires the legacy version be set to 0x0303. + */ + if (legacy_version != TLS1_2_VERSION) { + ctx->alert = TLS13_ALERT_PROTOCOL_VERSION; + goto err; + } + + /* + * The legacy session identifier must either be zero length or a 32 byte + * value (in which case the client is requesting middlebox compatibility + * mode), as per RFC 8446 section 4.1.2. If it is valid, store the value + * so that we can echo it back to the client. + */ + if (CBS_len(&session_id) != 0 && + CBS_len(&session_id) != sizeof(ctx->hs->tls13.legacy_session_id)) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + if (!CBS_write_bytes(&session_id, ctx->hs->tls13.legacy_session_id, + sizeof(ctx->hs->tls13.legacy_session_id), + &ctx->hs->tls13.legacy_session_id_len)) { + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + goto err; + } + + /* Parse cipher suites list and select preferred cipher. */ + if ((ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites)) == NULL) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + cipher = ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s)); + if (cipher == NULL) { + tls13_set_errorx(ctx, TLS13_ERR_NO_SHARED_CIPHER, 0, + "no shared cipher found", NULL); + ctx->alert = TLS13_ALERT_HANDSHAKE_FAILURE; + goto err; + } + ctx->hs->cipher = cipher; + + sk_SSL_CIPHER_free(s->session->ciphers); + s->session->ciphers = ciphers; + ciphers = NULL; + + /* Ensure only the NULL compression method is advertised. */ + if (!CBS_mem_equal(&compression_methods, tls13_compression_null_only, + sizeof(tls13_compression_null_only))) { + ctx->alert = TLS13_ALERT_ILLEGAL_PARAMETER; + goto err; + } + + ret = 1; + + err: + sk_SSL_CIPHER_free(ciphers); + + return ret; +} + +int +tls13_client_hello_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + SSL *s = ctx->ssl; + + if (!tls13_client_hello_process(ctx, cbs)) + goto err; + + /* See if we switched back to the legacy client method. */ + if (s->method->version < TLS1_3_VERSION) + return 1; + + /* + * If a matching key share was provided, we do not need to send a + * HelloRetryRequest. + */ + /* + * XXX - ideally NEGOTIATED would only be added after record protection + * has been enabled. This would probably mean using either an + * INITIAL | WITHOUT_HRR state, or another intermediate state. + */ + if (ctx->hs->key_share != NULL) + ctx->handshake_stage.hs_type |= NEGOTIATED | WITHOUT_HRR; + + tls13_record_layer_allow_ccs(ctx->rl, 1); + + return 1; + + err: + return 0; +} + +static int +tls13_server_hello_build(struct tls13_ctx *ctx, CBB *cbb, int hrr) +{ + uint16_t tlsext_msg_type = SSL_TLSEXT_MSG_SH; + const uint8_t *server_random; + CBB session_id; + SSL *s = ctx->ssl; + uint16_t cipher; + + cipher = SSL_CIPHER_get_value(ctx->hs->cipher); + server_random = s->s3->server_random; + + if (hrr) { + server_random = tls13_hello_retry_request_hash; + tlsext_msg_type = SSL_TLSEXT_MSG_HRR; + } + + if (!CBB_add_u16(cbb, TLS1_2_VERSION)) + goto err; + if (!CBB_add_bytes(cbb, server_random, SSL3_RANDOM_SIZE)) + goto err; + if (!CBB_add_u8_length_prefixed(cbb, &session_id)) + goto err; + if (!CBB_add_bytes(&session_id, ctx->hs->tls13.legacy_session_id, + ctx->hs->tls13.legacy_session_id_len)) + goto err; + if (!CBB_add_u16(cbb, cipher)) + goto err; + if (!CBB_add_u8(cbb, 0)) + goto err; + if (!tlsext_server_build(s, tlsext_msg_type, cbb)) + goto err; + + if (!CBB_flush(cbb)) + goto err; + + return 1; + err: + return 0; +} + +static int +tls13_server_engage_record_protection(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets; + struct tls13_secret context; + unsigned char buf[EVP_MAX_MD_SIZE]; + uint8_t *shared_key = NULL; + size_t shared_key_len = 0; + size_t hash_len; + SSL *s = ctx->ssl; + int ret = 0; + + if (!tls_key_share_derive(ctx->hs->key_share, &shared_key, + &shared_key_len)) + goto err; + + s->session->cipher = ctx->hs->cipher; + + if ((ctx->aead = tls13_cipher_aead(ctx->hs->cipher)) == NULL) + goto err; + if ((ctx->hash = tls13_cipher_hash(ctx->hs->cipher)) == NULL) + goto err; + + if ((secrets = tls13_secrets_create(ctx->hash, 0)) == NULL) + goto err; + ctx->hs->tls13.secrets = secrets; + + /* XXX - pass in hash. */ + if (!tls1_transcript_hash_init(s)) + goto err; + tls1_transcript_free(s); + if (!tls1_transcript_hash_value(s, buf, sizeof(buf), &hash_len)) + goto err; + context.data = buf; + context.len = hash_len; + + /* Early secrets. */ + if (!tls13_derive_early_secrets(secrets, secrets->zeros.data, + secrets->zeros.len, &context)) + goto err; + + /* Handshake secrets. */ + if (!tls13_derive_handshake_secrets(ctx->hs->tls13.secrets, shared_key, + shared_key_len, &context)) + goto err; + + tls13_record_layer_set_aead(ctx->rl, ctx->aead); + tls13_record_layer_set_hash(ctx->rl, ctx->hash); + + if (!tls13_record_layer_set_read_traffic_key(ctx->rl, + &secrets->client_handshake_traffic, ssl_encryption_handshake)) + goto err; + if (!tls13_record_layer_set_write_traffic_key(ctx->rl, + &secrets->server_handshake_traffic, ssl_encryption_handshake)) + goto err; + + ctx->handshake_stage.hs_type |= NEGOTIATED; + if (!(SSL_get_verify_mode(s) & SSL_VERIFY_PEER)) + ctx->handshake_stage.hs_type |= WITHOUT_CR; + + ret = 1; + + err: + freezero(shared_key, shared_key_len); + return ret; +} + +int +tls13_server_hello_retry_request_send(struct tls13_ctx *ctx, CBB *cbb) +{ + int nid; + + ctx->hs->tls13.hrr = 1; + + if (!tls13_synthetic_handshake_message(ctx)) + return 0; + + if (ctx->hs->key_share != NULL) + return 0; + if (!tls1_get_supported_group(ctx->ssl, &nid)) + return 0; + if (!tls1_ec_nid2group_id(nid, &ctx->hs->tls13.server_group)) + return 0; + + if (!tls13_server_hello_build(ctx, cbb, 1)) + return 0; + + return 1; +} + +int +tls13_server_hello_retry_request_sent(struct tls13_ctx *ctx) +{ + /* + * If the client has requested middlebox compatibility mode, + * we MUST send a dummy CCS following our first handshake message. + * See RFC 8446 Appendix D.4. + */ + if (ctx->hs->tls13.legacy_session_id_len > 0) + ctx->send_dummy_ccs_after = 1; + + return 1; +} + +int +tls13_client_hello_retry_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + SSL *s = ctx->ssl; + + if (!tls13_client_hello_process(ctx, cbs)) + return 0; + + /* XXX - need further checks. */ + if (s->method->version < TLS1_3_VERSION) + return 0; + + ctx->hs->tls13.hrr = 0; + + return 1; +} + +static int +tls13_servername_process(struct tls13_ctx *ctx) +{ + uint8_t alert = TLS13_ALERT_INTERNAL_ERROR; + + if (!tls13_legacy_servername_process(ctx, &alert)) { + ctx->alert = alert; + return 0; + } + + return 1; +} + +int +tls13_server_hello_send(struct tls13_ctx *ctx, CBB *cbb) +{ + if (ctx->hs->key_share == NULL) + return 0; + if (!tls_key_share_generate(ctx->hs->key_share)) + return 0; + if (!tls13_servername_process(ctx)) + return 0; + + ctx->hs->tls13.server_group = 0; + + if (!tls13_server_hello_build(ctx, cbb, 0)) + return 0; + + return 1; +} + +int +tls13_server_hello_sent(struct tls13_ctx *ctx) +{ + /* + * If the client has requested middlebox compatibility mode, + * we MUST send a dummy CCS following our first handshake message. + * See RFC 8446 Appendix D.4. + */ + if ((ctx->handshake_stage.hs_type & WITHOUT_HRR) && + ctx->hs->tls13.legacy_session_id_len > 0) + ctx->send_dummy_ccs_after = 1; + + return tls13_server_engage_record_protection(ctx); +} + +int +tls13_server_encrypted_extensions_send(struct tls13_ctx *ctx, CBB *cbb) +{ + if (!tlsext_server_build(ctx->ssl, SSL_TLSEXT_MSG_EE, cbb)) + goto err; + + return 1; + err: + return 0; +} + +int +tls13_server_certificate_request_send(struct tls13_ctx *ctx, CBB *cbb) +{ + CBB certificate_request_context; + + if (!CBB_add_u8_length_prefixed(cbb, &certificate_request_context)) + goto err; + if (!tlsext_server_build(ctx->ssl, SSL_TLSEXT_MSG_CR, cbb)) + goto err; + + if (!CBB_flush(cbb)) + goto err; + + return 1; + err: + return 0; +} + +static int +tls13_server_check_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY *cpk, + int *ok, const struct ssl_sigalg **out_sigalg) +{ + const struct ssl_sigalg *sigalg; + SSL *s = ctx->ssl; + + *ok = 0; + *out_sigalg = NULL; + + if (cpk->x509 == NULL || cpk->privatekey == NULL) + goto done; + + /* + * The digitalSignature bit MUST be set if the Key Usage extension is + * present as per RFC 8446 section 4.4.2.2. + */ + if (!(X509_get_key_usage(cpk->x509) & X509v3_KU_DIGITAL_SIGNATURE)) + goto done; + + if ((sigalg = ssl_sigalg_select(s, cpk->privatekey)) == NULL) + goto done; + + *ok = 1; + *out_sigalg = sigalg; + + done: + return 1; +} + +static int +tls13_server_select_certificate(struct tls13_ctx *ctx, SSL_CERT_PKEY **out_cpk, + const struct ssl_sigalg **out_sigalg) +{ + SSL *s = ctx->ssl; + const struct ssl_sigalg *sigalg; + SSL_CERT_PKEY *cpk; + int cert_ok; + + *out_cpk = NULL; + *out_sigalg = NULL; + + cpk = &s->cert->pkeys[SSL_PKEY_ECC]; + if (!tls13_server_check_certificate(ctx, cpk, &cert_ok, &sigalg)) + return 0; + if (cert_ok) + goto done; + + cpk = &s->cert->pkeys[SSL_PKEY_RSA]; + if (!tls13_server_check_certificate(ctx, cpk, &cert_ok, &sigalg)) + return 0; + if (cert_ok) + goto done; + + cpk = NULL; + sigalg = NULL; + + done: + *out_cpk = cpk; + *out_sigalg = sigalg; + + return 1; +} + +int +tls13_server_certificate_send(struct tls13_ctx *ctx, CBB *cbb) +{ + SSL *s = ctx->ssl; + CBB cert_request_context, cert_list; + const struct ssl_sigalg *sigalg; + X509_STORE_CTX *xsc = NULL; + STACK_OF(X509) *chain; + SSL_CERT_PKEY *cpk; + X509 *cert; + int i, ret = 0; + + if (!tls13_server_select_certificate(ctx, &cpk, &sigalg)) + goto err; + + if (cpk == NULL) { + /* A server must always provide a certificate. */ + ctx->alert = TLS13_ALERT_HANDSHAKE_FAILURE; + tls13_set_errorx(ctx, TLS13_ERR_NO_CERTIFICATE, 0, + "no server certificate", NULL); + goto err; + } + + ctx->hs->tls13.cpk = cpk; + ctx->hs->our_sigalg = sigalg; + + if ((chain = cpk->chain) == NULL) + chain = s->ctx->extra_certs; + + if (chain == NULL && !(s->mode & SSL_MODE_NO_AUTO_CHAIN)) { + if ((xsc = X509_STORE_CTX_new()) == NULL) + goto err; + if (!X509_STORE_CTX_init(xsc, s->ctx->cert_store, cpk->x509, NULL)) + goto err; + X509_VERIFY_PARAM_set_flags(X509_STORE_CTX_get0_param(xsc), + X509_V_FLAG_LEGACY_VERIFY); + X509_verify_cert(xsc); + ERR_clear_error(); + chain = X509_STORE_CTX_get0_chain(xsc); + } + + if (!CBB_add_u8_length_prefixed(cbb, &cert_request_context)) + goto err; + if (!CBB_add_u24_length_prefixed(cbb, &cert_list)) + goto err; + + if (!tls13_cert_add(ctx, &cert_list, cpk->x509, tlsext_server_build)) + goto err; + + for (i = 0; i < sk_X509_num(chain); i++) { + cert = sk_X509_value(chain, i); + + /* + * In the case of auto chain, the leaf certificate will be at + * the top of the chain - skip over it as we've already added + * it earlier. + */ + if (i == 0 && cert == cpk->x509) + continue; + + /* + * XXX we don't send extensions with chain certs to avoid sending + * a leaf ocsp staple with the chain certs. This needs to get + * fixed. + */ + if (!tls13_cert_add(ctx, &cert_list, cert, NULL)) + goto err; + } + + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + X509_STORE_CTX_free(xsc); + + return ret; +} + +int +tls13_server_certificate_verify_send(struct tls13_ctx *ctx, CBB *cbb) +{ + const struct ssl_sigalg *sigalg; + uint8_t *sig = NULL, *sig_content = NULL; + size_t sig_len, sig_content_len; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + const SSL_CERT_PKEY *cpk; + CBB sig_cbb; + int ret = 0; + + memset(&sig_cbb, 0, sizeof(sig_cbb)); + + if ((cpk = ctx->hs->tls13.cpk) == NULL) + goto err; + if ((sigalg = ctx->hs->our_sigalg) == NULL) + goto err; + pkey = cpk->privatekey; + + if (!CBB_init(&sig_cbb, 0)) + goto err; + if (!CBB_add_bytes(&sig_cbb, tls13_cert_verify_pad, + sizeof(tls13_cert_verify_pad))) + goto err; + if (!CBB_add_bytes(&sig_cbb, tls13_cert_server_verify_context, + strlen(tls13_cert_server_verify_context))) + goto err; + if (!CBB_add_u8(&sig_cbb, 0)) + goto err; + if (!CBB_add_bytes(&sig_cbb, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + if (!CBB_finish(&sig_cbb, &sig_content, &sig_content_len)) + goto err; + + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestSignInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) + goto err; + if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { + if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) + goto err; + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) + goto err; + } + if (!EVP_DigestSign(mdctx, NULL, &sig_len, sig_content, sig_content_len)) + goto err; + if ((sig = calloc(1, sig_len)) == NULL) + goto err; + if (!EVP_DigestSign(mdctx, sig, &sig_len, sig_content, sig_content_len)) + goto err; + + if (!CBB_add_u16(cbb, sigalg->value)) + goto err; + if (!CBB_add_u16_length_prefixed(cbb, &sig_cbb)) + goto err; + if (!CBB_add_bytes(&sig_cbb, sig, sig_len)) + goto err; + + if (!CBB_flush(cbb)) + goto err; + + ret = 1; + + err: + if (!ret && ctx->alert == 0) + ctx->alert = TLS13_ALERT_INTERNAL_ERROR; + + CBB_cleanup(&sig_cbb); + EVP_MD_CTX_free(mdctx); + free(sig_content); + free(sig); + + return ret; +} + +int +tls13_server_finished_send(struct tls13_ctx *ctx, CBB *cbb) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret context = { .data = "", .len = 0 }; + struct tls13_secret finished_key = { .data = NULL, .len = 0 } ; + uint8_t transcript_hash[EVP_MAX_MD_SIZE]; + size_t transcript_hash_len; + uint8_t *verify_data; + size_t verify_data_len; + unsigned int hlen; + HMAC_CTX *hmac_ctx = NULL; + CBS cbs; + int ret = 0; + + if (!tls13_secret_init(&finished_key, EVP_MD_size(ctx->hash))) + goto err; + + if (!tls13_hkdf_expand_label(&finished_key, ctx->hash, + &secrets->server_handshake_traffic, "finished", + &context)) + goto err; + + if (!tls1_transcript_hash_value(ctx->ssl, transcript_hash, + sizeof(transcript_hash), &transcript_hash_len)) + goto err; + + if ((hmac_ctx = HMAC_CTX_new()) == NULL) + goto err; + if (!HMAC_Init_ex(hmac_ctx, finished_key.data, finished_key.len, + ctx->hash, NULL)) + goto err; + if (!HMAC_Update(hmac_ctx, transcript_hash, transcript_hash_len)) + goto err; + + verify_data_len = HMAC_size(hmac_ctx); + if (!CBB_add_space(cbb, &verify_data, verify_data_len)) + goto err; + if (!HMAC_Final(hmac_ctx, verify_data, &hlen)) + goto err; + if (hlen != verify_data_len) + goto err; + + CBS_init(&cbs, verify_data, verify_data_len); + if (!CBS_write_bytes(&cbs, ctx->hs->finished, + sizeof(ctx->hs->finished), &ctx->hs->finished_len)) + goto err; + + ret = 1; + + err: + tls13_secret_cleanup(&finished_key); + HMAC_CTX_free(hmac_ctx); + + return ret; +} + +int +tls13_server_finished_sent(struct tls13_ctx *ctx) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret context = { .data = "", .len = 0 }; + + /* + * Derive application traffic keys. + */ + context.data = ctx->hs->tls13.transcript_hash; + context.len = ctx->hs->tls13.transcript_hash_len; + + if (!tls13_derive_application_secrets(secrets, &context)) + return 0; + + /* + * Any records following the server finished message must be encrypted + * using the server application traffic keys. + */ + return tls13_record_layer_set_write_traffic_key(ctx->rl, + &secrets->server_application_traffic, ssl_encryption_application); +} + +int +tls13_client_certificate_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + CBS cert_request_context, cert_list, cert_data, cert_exts; + struct stack_st_X509 *certs = NULL; + SSL *s = ctx->ssl; + X509 *cert = NULL; + const uint8_t *p; + int ret = 0; + + if (!CBS_get_u8_length_prefixed(cbs, &cert_request_context)) + goto err; + if (CBS_len(&cert_request_context) != 0) + goto err; + if (!CBS_get_u24_length_prefixed(cbs, &cert_list)) + goto err; + if (CBS_len(&cert_list) == 0) { + if (!(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) + return 1; + ctx->alert = TLS13_ALERT_CERTIFICATE_REQUIRED; + tls13_set_errorx(ctx, TLS13_ERR_NO_PEER_CERTIFICATE, 0, + "peer did not provide a certificate", NULL); + goto err; + } + + if ((certs = sk_X509_new_null()) == NULL) + goto err; + while (CBS_len(&cert_list) > 0) { + if (!CBS_get_u24_length_prefixed(&cert_list, &cert_data)) + goto err; + if (!CBS_get_u16_length_prefixed(&cert_list, &cert_exts)) + goto err; + + p = CBS_data(&cert_data); + if ((cert = d2i_X509(NULL, &p, CBS_len(&cert_data))) == NULL) + goto err; + if (p != CBS_data(&cert_data) + CBS_len(&cert_data)) + goto err; + + if (!sk_X509_push(certs, cert)) + goto err; + + cert = NULL; + } + + /* + * At this stage we still have no proof of possession. As such, it would + * be preferable to keep the chain and verify once we have successfully + * processed the CertificateVerify message. + */ + if (ssl_verify_cert_chain(s, certs) <= 0) { + ctx->alert = ssl_verify_alarm_type(s->verify_result); + tls13_set_errorx(ctx, TLS13_ERR_VERIFY_FAILED, 0, + "failed to verify peer certificate", NULL); + goto err; + } + s->session->verify_result = s->verify_result; + ERR_clear_error(); + + if (!tls_process_peer_certs(s, certs)) + goto err; + + ctx->handshake_stage.hs_type |= WITH_CCV; + ret = 1; + + err: + sk_X509_pop_free(certs, X509_free); + X509_free(cert); + + return ret; +} + +int +tls13_client_certificate_verify_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + const struct ssl_sigalg *sigalg; + uint16_t signature_scheme; + uint8_t *sig_content = NULL; + size_t sig_content_len; + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *pctx; + EVP_PKEY *pkey; + X509 *cert; + CBS signature; + CBB cbb; + int ret = 0; + + memset(&cbb, 0, sizeof(cbb)); + + if (!CBS_get_u16(cbs, &signature_scheme)) + goto err; + if (!CBS_get_u16_length_prefixed(cbs, &signature)) + goto err; + + if (!CBB_init(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, tls13_cert_verify_pad, + sizeof(tls13_cert_verify_pad))) + goto err; + if (!CBB_add_bytes(&cbb, tls13_cert_client_verify_context, + strlen(tls13_cert_client_verify_context))) + goto err; + if (!CBB_add_u8(&cbb, 0)) + goto err; + if (!CBB_add_bytes(&cbb, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + if (!CBB_finish(&cbb, &sig_content, &sig_content_len)) + goto err; + + if ((cert = ctx->ssl->session->peer_cert) == NULL) + goto err; + if ((pkey = X509_get0_pubkey(cert)) == NULL) + goto err; + if ((sigalg = ssl_sigalg_for_peer(ctx->ssl, pkey, + signature_scheme)) == NULL) + goto err; + ctx->hs->peer_sigalg = sigalg; + + if (CBS_len(&signature) > EVP_PKEY_size(pkey)) + goto err; + + if ((mdctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestVerifyInit(mdctx, &pctx, sigalg->md(), NULL, pkey)) + goto err; + if (sigalg->flags & SIGALG_FLAG_RSA_PSS) { + if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING)) + goto err; + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) + goto err; + } + if (EVP_DigestVerify(mdctx, CBS_data(&signature), CBS_len(&signature), + sig_content, sig_content_len) <= 0) { + ctx->alert = TLS13_ALERT_DECRYPT_ERROR; + goto err; + } + + ret = 1; + + err: + if (!ret && ctx->alert == 0) + ctx->alert = TLS13_ALERT_DECODE_ERROR; + + CBB_cleanup(&cbb); + EVP_MD_CTX_free(mdctx); + free(sig_content); + + return ret; +} + +int +tls13_client_end_of_early_data_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + return 0; +} + +int +tls13_client_finished_recv(struct tls13_ctx *ctx, CBS *cbs) +{ + struct tls13_secrets *secrets = ctx->hs->tls13.secrets; + struct tls13_secret context = { .data = "", .len = 0 }; + struct tls13_secret finished_key; + uint8_t *verify_data = NULL; + size_t verify_data_len; + uint8_t key[EVP_MAX_MD_SIZE]; + HMAC_CTX *hmac_ctx = NULL; + unsigned int hlen; + int ret = 0; + + /* + * Verify client finished. + */ + finished_key.data = key; + finished_key.len = EVP_MD_size(ctx->hash); + + if (!tls13_hkdf_expand_label(&finished_key, ctx->hash, + &secrets->client_handshake_traffic, "finished", + &context)) + goto err; + + if ((hmac_ctx = HMAC_CTX_new()) == NULL) + goto err; + if (!HMAC_Init_ex(hmac_ctx, finished_key.data, finished_key.len, + ctx->hash, NULL)) + goto err; + if (!HMAC_Update(hmac_ctx, ctx->hs->tls13.transcript_hash, + ctx->hs->tls13.transcript_hash_len)) + goto err; + verify_data_len = HMAC_size(hmac_ctx); + if ((verify_data = calloc(1, verify_data_len)) == NULL) + goto err; + if (!HMAC_Final(hmac_ctx, verify_data, &hlen)) + goto err; + if (hlen != verify_data_len) + goto err; + + if (!CBS_mem_equal(cbs, verify_data, verify_data_len)) { + ctx->alert = TLS13_ALERT_DECRYPT_ERROR; + goto err; + } + + if (!CBS_write_bytes(cbs, ctx->hs->peer_finished, + sizeof(ctx->hs->peer_finished), + &ctx->hs->peer_finished_len)) + goto err; + + if (!CBS_skip(cbs, verify_data_len)) + goto err; + + /* + * Any records following the client finished message must be encrypted + * using the client application traffic keys. + */ + if (!tls13_record_layer_set_read_traffic_key(ctx->rl, + &secrets->client_application_traffic, ssl_encryption_application)) + goto err; + + tls13_record_layer_allow_ccs(ctx->rl, 0); + + ret = 1; + + err: + HMAC_CTX_free(hmac_ctx); + free(verify_data); + + return ret; +} diff --git a/ssl/tls_buffer.c b/ssl/tls_buffer.c new file mode 100644 index 0000000..517d66d --- /dev/null +++ b/ssl/tls_buffer.c @@ -0,0 +1,257 @@ +/* $OpenBSD: tls_buffer.c,v 1.4 2022/11/10 18:06:37 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "bytestring.h" +#include "tls_internal.h" + +#define TLS_BUFFER_CAPACITY_LIMIT (1024 * 1024) + +struct tls_buffer { + size_t capacity; + size_t capacity_limit; + uint8_t *data; + size_t len; + size_t offset; +}; + +static int tls_buffer_resize(struct tls_buffer *buf, size_t capacity); + +struct tls_buffer * +tls_buffer_new(size_t init_size) +{ + struct tls_buffer *buf = NULL; + + if ((buf = calloc(1, sizeof(struct tls_buffer))) == NULL) + goto err; + + buf->capacity_limit = TLS_BUFFER_CAPACITY_LIMIT; + + if (!tls_buffer_resize(buf, init_size)) + goto err; + + return buf; + + err: + tls_buffer_free(buf); + + return NULL; +} + +void +tls_buffer_clear(struct tls_buffer *buf) +{ + freezero(buf->data, buf->capacity); + + buf->data = NULL; + buf->capacity = 0; + buf->len = 0; + buf->offset = 0; +} + +void +tls_buffer_free(struct tls_buffer *buf) +{ + if (buf == NULL) + return; + + tls_buffer_clear(buf); + + freezero(buf, sizeof(struct tls_buffer)); +} + +static int +tls_buffer_grow(struct tls_buffer *buf, size_t capacity) +{ + if (buf->capacity >= capacity) + return 1; + + return tls_buffer_resize(buf, capacity); +} + +static int +tls_buffer_resize(struct tls_buffer *buf, size_t capacity) +{ + uint8_t *data; + + /* + * XXX - Consider maintaining a minimum size and growing more + * intelligently (rather than exactly). + */ + if (buf->capacity == capacity) + return 1; + + if (capacity > buf->capacity_limit) + return 0; + + if ((data = recallocarray(buf->data, buf->capacity, capacity, 1)) == NULL) + return 0; + + buf->data = data; + buf->capacity = capacity; + + /* Ensure that len and offset are valid if capacity decreased. */ + if (buf->len > buf->capacity) + buf->len = buf->capacity; + if (buf->offset > buf->len) + buf->offset = buf->len; + + return 1; +} + +void +tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit) +{ + /* + * XXX - do we want to force a resize if this limit is less than current + * capacity... and what do we do with existing data? Force a clear? + */ + buf->capacity_limit = limit; +} + +ssize_t +tls_buffer_extend(struct tls_buffer *buf, size_t len, + tls_read_cb read_cb, void *cb_arg) +{ + ssize_t ret; + + if (len == buf->len) + return buf->len; + + if (len < buf->len) + return TLS_IO_FAILURE; + + if (!tls_buffer_resize(buf, len)) + return TLS_IO_FAILURE; + + for (;;) { + if ((ret = read_cb(&buf->data[buf->len], + buf->capacity - buf->len, cb_arg)) <= 0) + return ret; + + if (ret > buf->capacity - buf->len) + return TLS_IO_FAILURE; + + buf->len += ret; + + if (buf->len == buf->capacity) + return buf->len; + } +} + +size_t +tls_buffer_remaining(struct tls_buffer *buf) +{ + if (buf->offset > buf->len) + return 0; + + return buf->len - buf->offset; +} + +ssize_t +tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n) +{ + if (buf->offset > buf->len) + return TLS_IO_FAILURE; + + if (buf->offset == buf->len) + return TLS_IO_WANT_POLLIN; + + if (n > buf->len - buf->offset) + n = buf->len - buf->offset; + + memcpy(rbuf, &buf->data[buf->offset], n); + + buf->offset += n; + + return n; +} + +ssize_t +tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n) +{ + if (buf->offset > buf->len) + return TLS_IO_FAILURE; + + /* + * To avoid continually growing the buffer, pull data up to the + * start of the buffer. If all data has been read then we can simply + * reset, otherwise wait until we're going to save at least 4KB of + * memory to reduce overhead. + */ + if (buf->offset == buf->len) { + buf->len = 0; + buf->offset = 0; + } + if (buf->offset >= 4096) { + memmove(buf->data, &buf->data[buf->offset], + buf->len - buf->offset); + buf->len -= buf->offset; + buf->offset = 0; + } + + if (buf->len > SIZE_MAX - n) + return TLS_IO_FAILURE; + if (!tls_buffer_grow(buf, buf->len + n)) + return TLS_IO_FAILURE; + + memcpy(&buf->data[buf->len], wbuf, n); + + buf->len += n; + + return n; +} + +int +tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n) +{ + return tls_buffer_write(buf, wbuf, n) == n; +} + +int +tls_buffer_data(struct tls_buffer *buf, CBS *out_cbs) +{ + CBS cbs; + + CBS_init(&cbs, buf->data, buf->len); + + if (!CBS_skip(&cbs, buf->offset)) + return 0; + + CBS_dup(&cbs, out_cbs); + + return 1; +} + +int +tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len) +{ + if (out == NULL || out_len == NULL) + return 0; + + *out = buf->data; + *out_len = buf->len; + + buf->data = NULL; + buf->capacity = 0; + buf->len = 0; + buf->offset = 0; + + return 1; +} diff --git a/ssl/tls_content.c b/ssl/tls_content.c new file mode 100644 index 0000000..726de0f --- /dev/null +++ b/ssl/tls_content.c @@ -0,0 +1,164 @@ +/* $OpenBSD: tls_content.c,v 1.2 2022/11/11 17:15:27 jsing Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "tls_content.h" + +/* Content from a TLS record. */ +struct tls_content { + uint8_t type; + uint16_t epoch; + + const uint8_t *data; + size_t data_len; + CBS cbs; +}; + +struct tls_content * +tls_content_new(void) +{ + return calloc(1, sizeof(struct tls_content)); +} + +void +tls_content_clear(struct tls_content *content) +{ + freezero((void *)content->data, content->data_len); + memset(content, 0, sizeof(*content)); +} + +void +tls_content_free(struct tls_content *content) +{ + if (content == NULL) + return; + + tls_content_clear(content); + + freezero(content, sizeof(struct tls_content)); +} + +CBS * +tls_content_cbs(struct tls_content *content) +{ + return &content->cbs; +} + +int +tls_content_equal(struct tls_content *content, const uint8_t *buf, size_t n) +{ + return CBS_mem_equal(&content->cbs, buf, n); +} + +size_t +tls_content_remaining(struct tls_content *content) +{ + return CBS_len(&content->cbs); +} + +uint8_t +tls_content_type(struct tls_content *content) +{ + return content->type; +} + +int +tls_content_dup_data(struct tls_content *content, uint8_t type, + const uint8_t *data, size_t data_len) +{ + uint8_t *dup; + + if ((dup = calloc(1, data_len)) == NULL) + return 0; + memcpy(dup, data, data_len); + + tls_content_set_data(content, type, dup, data_len); + + return 1; +} + +uint16_t +tls_content_epoch(struct tls_content *content) +{ + return content->epoch; +} + +void +tls_content_set_epoch(struct tls_content *content, uint16_t epoch) +{ + content->epoch = epoch; +} + +void +tls_content_set_data(struct tls_content *content, uint8_t type, + const uint8_t *data, size_t data_len) +{ + tls_content_clear(content); + + content->type = type; + content->data = data; + content->data_len = data_len; + + CBS_init(&content->cbs, content->data, content->data_len); +} + +int +tls_content_set_bounds(struct tls_content *content, size_t offset, size_t len) +{ + size_t content_len; + + content_len = offset + len; + if (content_len < len) + return 0; + if (content_len > content->data_len) + return 0; + + CBS_init(&content->cbs, content->data, content_len); + return CBS_skip(&content->cbs, offset); +} + +static ssize_t +tls_content_read_internal(struct tls_content *content, uint8_t *buf, size_t n, + int peek) +{ + if (n > CBS_len(&content->cbs)) + n = CBS_len(&content->cbs); + + /* XXX - CBS_memcpy? CBS_copy_bytes? */ + memcpy(buf, CBS_data(&content->cbs), n); + + if (!peek) { + if (!CBS_skip(&content->cbs, n)) + return -1; + } + + return n; +} + +ssize_t +tls_content_peek(struct tls_content *content, uint8_t *buf, size_t n) +{ + return tls_content_read_internal(content, buf, n, 1); +} + +ssize_t +tls_content_read(struct tls_content *content, uint8_t *buf, size_t n) +{ + return tls_content_read_internal(content, buf, n, 0); +} diff --git a/ssl/tls_content.h b/ssl/tls_content.h new file mode 100644 index 0000000..b807248 --- /dev/null +++ b/ssl/tls_content.h @@ -0,0 +1,50 @@ +/* $OpenBSD: tls_content.h,v 1.2 2022/11/11 17:15:27 jsing Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS_CONTENT_H +#define HEADER_TLS_CONTENT_H + +#include "bytestring.h" + +__BEGIN_HIDDEN_DECLS + +struct tls_content; + +struct tls_content *tls_content_new(void); +void tls_content_clear(struct tls_content *content); +void tls_content_free(struct tls_content *content); + +CBS *tls_content_cbs(struct tls_content *content); +int tls_content_equal(struct tls_content *content, const uint8_t *buf, size_t n); +size_t tls_content_remaining(struct tls_content *content); +uint8_t tls_content_type(struct tls_content *content); +uint16_t tls_content_epoch(struct tls_content *content); + +int tls_content_dup_data(struct tls_content *content, uint8_t type, + const uint8_t *data, size_t data_len); +void tls_content_set_data(struct tls_content *content, uint8_t type, + const uint8_t *data, size_t data_len); +int tls_content_set_bounds(struct tls_content *content, size_t offset, + size_t len); +void tls_content_set_epoch(struct tls_content *content, uint16_t epoch); + +ssize_t tls_content_peek(struct tls_content *content, uint8_t *buf, size_t n); +ssize_t tls_content_read(struct tls_content *content, uint8_t *buf, size_t n); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls_internal.h b/ssl/tls_internal.h new file mode 100644 index 0000000..84edde8 --- /dev/null +++ b/ssl/tls_internal.h @@ -0,0 +1,101 @@ +/* $OpenBSD: tls_internal.h,v 1.10 2022/11/10 18:06:37 jsing Exp $ */ +/* + * Copyright (c) 2018, 2019, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS_INTERNAL_H +#define HEADER_TLS_INTERNAL_H + +#include +#include + +#include "bytestring.h" + +__BEGIN_HIDDEN_DECLS + +#define TLS_IO_SUCCESS 1 +#define TLS_IO_EOF 0 +#define TLS_IO_FAILURE -1 +#define TLS_IO_ALERT -2 +#define TLS_IO_WANT_POLLIN -3 +#define TLS_IO_WANT_POLLOUT -4 +#define TLS_IO_WANT_RETRY -5 /* Retry the previous call immediately. */ + +enum ssl_encryption_level_t; + +struct tls13_secret; + +/* + * Callbacks. + */ +typedef ssize_t (*tls_read_cb)(void *_buf, size_t _buflen, void *_cb_arg); +typedef ssize_t (*tls_write_cb)(const void *_buf, size_t _buflen, + void *_cb_arg); +typedef ssize_t (*tls_flush_cb)(void *_cb_arg); + +typedef ssize_t (*tls_handshake_read_cb)(void *_buf, size_t _buflen, + void *_cb_arg); +typedef ssize_t (*tls_handshake_write_cb)(const void *_buf, size_t _buflen, + void *_cb_arg); +typedef int (*tls_traffic_key_cb)(struct tls13_secret *key, + enum ssl_encryption_level_t level, void *_cb_arg); +typedef int (*tls_alert_send_cb)(int _alert_desc, void *_cb_arg); + +/* + * Buffers. + */ +struct tls_buffer; + +struct tls_buffer *tls_buffer_new(size_t init_size); +void tls_buffer_clear(struct tls_buffer *buf); +void tls_buffer_free(struct tls_buffer *buf); +void tls_buffer_set_capacity_limit(struct tls_buffer *buf, size_t limit); +ssize_t tls_buffer_extend(struct tls_buffer *buf, size_t len, + tls_read_cb read_cb, void *cb_arg); +size_t tls_buffer_remaining(struct tls_buffer *buf); +ssize_t tls_buffer_read(struct tls_buffer *buf, uint8_t *rbuf, size_t n); +ssize_t tls_buffer_write(struct tls_buffer *buf, const uint8_t *wbuf, size_t n); +int tls_buffer_append(struct tls_buffer *buf, const uint8_t *wbuf, size_t n); +int tls_buffer_data(struct tls_buffer *buf, CBS *cbs); +int tls_buffer_finish(struct tls_buffer *buf, uint8_t **out, size_t *out_len); + +/* + * Key shares. + */ +struct tls_key_share; + +struct tls_key_share *tls_key_share_new(uint16_t group_id); +struct tls_key_share *tls_key_share_new_nid(int nid); +void tls_key_share_free(struct tls_key_share *ks); + +uint16_t tls_key_share_group(struct tls_key_share *ks); +int tls_key_share_nid(struct tls_key_share *ks); +void tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits); +int tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params); +int tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey); +int tls_key_share_generate(struct tls_key_share *ks); +int tls_key_share_params(struct tls_key_share *ks, CBB *cbb); +int tls_key_share_public(struct tls_key_share *ks, CBB *cbb); +int tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params); +int tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_key); +int tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, + size_t *shared_key_len); +int tls_key_share_peer_security(const SSL *ssl, struct tls_key_share *ks); + +__END_HIDDEN_DECLS + +#endif diff --git a/ssl/tls_key_share.c b/ssl/tls_key_share.c new file mode 100644 index 0000000..cf7b1da --- /dev/null +++ b/ssl/tls_key_share.c @@ -0,0 +1,484 @@ +/* $OpenBSD: tls_key_share.c,v 1.8 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2020, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include + +#include "bytestring.h" +#include "ssl_local.h" +#include "tls_internal.h" + +struct tls_key_share { + int nid; + uint16_t group_id; + size_t key_bits; + + DH *dhe; + DH *dhe_peer; + + EC_KEY *ecdhe; + EC_KEY *ecdhe_peer; + + uint8_t *x25519_public; + uint8_t *x25519_private; + uint8_t *x25519_peer_public; +}; + +static struct tls_key_share * +tls_key_share_new_internal(int nid, uint16_t group_id) +{ + struct tls_key_share *ks; + + if ((ks = calloc(1, sizeof(struct tls_key_share))) == NULL) + return NULL; + + ks->group_id = group_id; + ks->nid = nid; + + return ks; +} + +struct tls_key_share * +tls_key_share_new(uint16_t group_id) +{ + int nid; + + if (!tls1_ec_group_id2nid(group_id, &nid)) + return NULL; + + return tls_key_share_new_internal(nid, group_id); +} + +struct tls_key_share * +tls_key_share_new_nid(int nid) +{ + uint16_t group_id = 0; + + if (nid != NID_dhKeyAgreement) { + if (!tls1_ec_nid2group_id(nid, &group_id)) + return NULL; + } + + return tls_key_share_new_internal(nid, group_id); +} + +void +tls_key_share_free(struct tls_key_share *ks) +{ + if (ks == NULL) + return; + + DH_free(ks->dhe); + DH_free(ks->dhe_peer); + + EC_KEY_free(ks->ecdhe); + EC_KEY_free(ks->ecdhe_peer); + + freezero(ks->x25519_public, X25519_KEY_LENGTH); + freezero(ks->x25519_private, X25519_KEY_LENGTH); + freezero(ks->x25519_peer_public, X25519_KEY_LENGTH); + + freezero(ks, sizeof(*ks)); +} + +uint16_t +tls_key_share_group(struct tls_key_share *ks) +{ + return ks->group_id; +} + +int +tls_key_share_nid(struct tls_key_share *ks) +{ + return ks->nid; +} + +void +tls_key_share_set_key_bits(struct tls_key_share *ks, size_t key_bits) +{ + ks->key_bits = key_bits; +} + +int +tls_key_share_set_dh_params(struct tls_key_share *ks, DH *dh_params) +{ + if (ks->nid != NID_dhKeyAgreement) + return 0; + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe = DHparams_dup(dh_params)) == NULL) + return 0; + if ((ks->dhe_peer = DHparams_dup(dh_params)) == NULL) + return 0; + + return 1; +} + +int +tls_key_share_peer_pkey(struct tls_key_share *ks, EVP_PKEY *pkey) +{ + if (ks->nid == NID_dhKeyAgreement && ks->dhe_peer != NULL) + return EVP_PKEY_set1_DH(pkey, ks->dhe_peer); + + if (ks->nid == NID_X25519 && ks->x25519_peer_public != NULL) + return ssl_kex_dummy_ecdhe_x25519(pkey); + + if (ks->ecdhe_peer != NULL) + return EVP_PKEY_set1_EC_KEY(pkey, ks->ecdhe_peer); + + return 0; +} + +static int +tls_key_share_generate_dhe(struct tls_key_share *ks) +{ + /* + * If auto params are not being used then we must already have DH + * parameters set. + */ + if (ks->key_bits == 0) { + if (ks->dhe == NULL) + return 0; + + return ssl_kex_generate_dhe(ks->dhe, ks->dhe); + } + + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe = DH_new()) == NULL) + return 0; + if (!ssl_kex_generate_dhe_params_auto(ks->dhe, ks->key_bits)) + return 0; + if ((ks->dhe_peer = DHparams_dup(ks->dhe)) == NULL) + return 0; + + return 1; +} + +static int +tls_key_share_generate_ecdhe_ecp(struct tls_key_share *ks) +{ + EC_KEY *ecdhe = NULL; + int ret = 0; + + if (ks->ecdhe != NULL) + goto err; + + if ((ecdhe = EC_KEY_new()) == NULL) + goto err; + if (!ssl_kex_generate_ecdhe_ecp(ecdhe, ks->nid)) + goto err; + + ks->ecdhe = ecdhe; + ecdhe = NULL; + + ret = 1; + + err: + EC_KEY_free(ecdhe); + + return ret; +} + +static int +tls_key_share_generate_x25519(struct tls_key_share *ks) +{ + uint8_t *public = NULL, *private = NULL; + int ret = 0; + + if (ks->x25519_public != NULL || ks->x25519_private != NULL) + goto err; + + if ((public = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + if ((private = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + + X25519_keypair(public, private); + + ks->x25519_public = public; + ks->x25519_private = private; + public = NULL; + private = NULL; + + ret = 1; + + err: + freezero(public, X25519_KEY_LENGTH); + freezero(private, X25519_KEY_LENGTH); + + return ret; +} + +int +tls_key_share_generate(struct tls_key_share *ks) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_generate_dhe(ks); + + if (ks->nid == NID_X25519) + return tls_key_share_generate_x25519(ks); + + return tls_key_share_generate_ecdhe_ecp(ks); +} + +static int +tls_key_share_params_dhe(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->dhe == NULL) + return 0; + + return ssl_kex_params_dhe(ks->dhe, cbb); +} + +int +tls_key_share_params(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_params_dhe(ks, cbb); + + return 0; +} + +static int +tls_key_share_public_dhe(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->dhe == NULL) + return 0; + + return ssl_kex_public_dhe(ks->dhe, cbb); +} + +static int +tls_key_share_public_ecdhe_ecp(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->ecdhe == NULL) + return 0; + + return ssl_kex_public_ecdhe_ecp(ks->ecdhe, cbb); +} + +static int +tls_key_share_public_x25519(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->x25519_public == NULL) + return 0; + + return CBB_add_bytes(cbb, ks->x25519_public, X25519_KEY_LENGTH); +} + +int +tls_key_share_public(struct tls_key_share *ks, CBB *cbb) +{ + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_public_dhe(ks, cbb); + + if (ks->nid == NID_X25519) + return tls_key_share_public_x25519(ks, cbb); + + return tls_key_share_public_ecdhe_ecp(ks, cbb); +} + +static int +tls_key_share_peer_params_dhe(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params) +{ + if (ks->dhe != NULL || ks->dhe_peer != NULL) + return 0; + + if ((ks->dhe_peer = DH_new()) == NULL) + return 0; + if (!ssl_kex_peer_params_dhe(ks->dhe_peer, cbs, decode_error, + invalid_params)) + return 0; + if ((ks->dhe = DHparams_dup(ks->dhe_peer)) == NULL) + return 0; + + return 1; +} + +int +tls_key_share_peer_params(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_params) +{ + if (ks->nid != NID_dhKeyAgreement) + return 0; + + return tls_key_share_peer_params_dhe(ks, cbs, decode_error, + invalid_params); +} + +static int +tls_key_share_peer_public_dhe(struct tls_key_share *ks, CBS *cbs, + int *decode_error, int *invalid_key) +{ + if (ks->dhe_peer == NULL) + return 0; + + return ssl_kex_peer_public_dhe(ks->dhe_peer, cbs, decode_error, + invalid_key); +} + +static int +tls_key_share_peer_public_ecdhe_ecp(struct tls_key_share *ks, CBS *cbs) +{ + EC_KEY *ecdhe = NULL; + int ret = 0; + + if (ks->ecdhe_peer != NULL) + goto err; + + if ((ecdhe = EC_KEY_new()) == NULL) + goto err; + if (!ssl_kex_peer_public_ecdhe_ecp(ecdhe, ks->nid, cbs)) + goto err; + + ks->ecdhe_peer = ecdhe; + ecdhe = NULL; + + ret = 1; + + err: + EC_KEY_free(ecdhe); + + return ret; +} + +static int +tls_key_share_peer_public_x25519(struct tls_key_share *ks, CBS *cbs, + int *decode_error) +{ + size_t out_len; + + *decode_error = 0; + + if (ks->x25519_peer_public != NULL) + return 0; + + if (CBS_len(cbs) != X25519_KEY_LENGTH) { + *decode_error = 1; + return 0; + } + + return CBS_stow(cbs, &ks->x25519_peer_public, &out_len); +} + +int +tls_key_share_peer_public(struct tls_key_share *ks, CBS *cbs, int *decode_error, + int *invalid_key) +{ + *decode_error = 0; + + if (invalid_key != NULL) + *invalid_key = 0; + + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_peer_public_dhe(ks, cbs, decode_error, + invalid_key); + + if (ks->nid == NID_X25519) + return tls_key_share_peer_public_x25519(ks, cbs, decode_error); + + return tls_key_share_peer_public_ecdhe_ecp(ks, cbs); +} + +static int +tls_key_share_derive_dhe(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + if (ks->dhe == NULL || ks->dhe_peer == NULL) + return 0; + + return ssl_kex_derive_dhe(ks->dhe, ks->dhe_peer, shared_key, + shared_key_len); +} + +static int +tls_key_share_derive_ecdhe_ecp(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + if (ks->ecdhe == NULL || ks->ecdhe_peer == NULL) + return 0; + + return ssl_kex_derive_ecdhe_ecp(ks->ecdhe, ks->ecdhe_peer, + shared_key, shared_key_len); +} + +static int +tls_key_share_derive_x25519(struct tls_key_share *ks, + uint8_t **shared_key, size_t *shared_key_len) +{ + uint8_t *sk = NULL; + int ret = 0; + + if (ks->x25519_private == NULL || ks->x25519_peer_public == NULL) + goto err; + + if ((sk = calloc(1, X25519_KEY_LENGTH)) == NULL) + goto err; + if (!X25519(sk, ks->x25519_private, ks->x25519_peer_public)) + goto err; + + *shared_key = sk; + *shared_key_len = X25519_KEY_LENGTH; + sk = NULL; + + ret = 1; + + err: + freezero(sk, X25519_KEY_LENGTH); + + return ret; +} + +int +tls_key_share_derive(struct tls_key_share *ks, uint8_t **shared_key, + size_t *shared_key_len) +{ + if (*shared_key != NULL) + return 0; + + *shared_key_len = 0; + + if (ks->nid == NID_dhKeyAgreement) + return tls_key_share_derive_dhe(ks, shared_key, + shared_key_len); + + if (ks->nid == NID_X25519) + return tls_key_share_derive_x25519(ks, shared_key, + shared_key_len); + + return tls_key_share_derive_ecdhe_ecp(ks, shared_key, + shared_key_len); +} + +int +tls_key_share_peer_security(const SSL *ssl, struct tls_key_share *ks) +{ + switch (ks->nid) { + case NID_dhKeyAgreement: + return ssl_security_dh(ssl, ks->dhe_peer); + default: + return 0; + } +} diff --git a/ssl/tls_lib.c b/ssl/tls_lib.c new file mode 100644 index 0000000..db734c3 --- /dev/null +++ b/ssl/tls_lib.c @@ -0,0 +1,68 @@ +/* $OpenBSD: tls_lib.c,v 1.3 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2019, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ssl_local.h" + +int +tls_process_peer_certs(SSL *s, STACK_OF(X509) *peer_certs) +{ + STACK_OF(X509) *peer_certs_no_leaf; + X509 *peer_cert = NULL; + EVP_PKEY *pkey; + int cert_type; + int ret = 0; + + if (sk_X509_num(peer_certs) < 1) + goto err; + peer_cert = sk_X509_value(peer_certs, 0); + X509_up_ref(peer_cert); + + if ((pkey = X509_get0_pubkey(peer_cert)) == NULL) { + SSLerror(s, SSL_R_NO_PUBLICKEY); + goto err; + } + if (EVP_PKEY_missing_parameters(pkey)) { + SSLerror(s, SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + goto err; + } + if ((cert_type = ssl_cert_type(pkey)) < 0) { + SSLerror(s, SSL_R_UNKNOWN_CERTIFICATE_TYPE); + goto err; + } + + s->session->peer_cert_type = cert_type; + + X509_free(s->session->peer_cert); + s->session->peer_cert = peer_cert; + peer_cert = NULL; + + sk_X509_pop_free(s->s3->hs.peer_certs, X509_free); + if ((s->s3->hs.peer_certs = X509_chain_up_ref(peer_certs)) == NULL) + goto err; + + if ((peer_certs_no_leaf = X509_chain_up_ref(peer_certs)) == NULL) + goto err; + X509_free(sk_X509_shift(peer_certs_no_leaf)); + sk_X509_pop_free(s->s3->hs.peer_certs_no_leaf, X509_free); + s->s3->hs.peer_certs_no_leaf = peer_certs_no_leaf; + + ret = 1; + err: + X509_free(peer_cert); + + return ret; +} diff --git a/tests/aeadtest.c b/tests/aeadtest.c new file mode 100644 index 0000000..82fe728 --- /dev/null +++ b/tests/aeadtest.c @@ -0,0 +1,591 @@ +/* $OpenBSD: aeadtest.c,v 1.26 2023/09/28 14:55:48 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * This program tests an AEAD against a series of test vectors from a file. The + * test vector file consists of key-value lines where the key and value are + * separated by a colon and optional whitespace. The keys are listed in + * NAMES, below. The values are hex-encoded data. + * + * After a number of key-value lines, a blank line indicates the end of the + * test case. + * + * For example, here's a valid test case: + * + * AEAD: chacha20-poly1305 + * KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5 + * NONCE: 1e8b4c510f5ca083 + * IN: 8c8419bc27 + * AD: 34ab88c265 + * CT: 1a7c2f33f5 + * TAG: 2875c659d0f2808de3a40027feff91a4 + */ + +#define BUF_MAX 1024 + +/* MS defines in global headers, remove it */ +#ifdef _MSC_VER +#ifdef IN +#undef IN +#endif +#endif + +/* These are the different types of line that are found in the input file. */ +enum { + AEAD = 0, /* name of the AEAD algorithm. */ + KEY, /* hex encoded key. */ + NONCE, /* hex encoded nonce. */ + IN, /* hex encoded plaintext. */ + AD, /* hex encoded additional data. */ + CT, /* hex encoded ciphertext (not including the + * authenticator, which is next. */ + TAG, /* hex encoded authenticator. */ + NUM_TYPES +}; + +static const char NAMES[NUM_TYPES][6] = { + "AEAD", + "KEY", + "NONCE", + "IN", + "AD", + "CT", + "TAG", +}; + +static unsigned char +hex_digit(char h) +{ + if (h >= '0' && h <= '9') + return h - '0'; + else if (h >= 'a' && h <= 'f') + return h - 'a' + 10; + else if (h >= 'A' && h <= 'F') + return h - 'A' + 10; + else + return 16; +} + +static int +aead_from_name(const EVP_AEAD **aead, const EVP_CIPHER **cipher, + const char *name) +{ + *aead = NULL; + *cipher = NULL; + + if (strcmp(name, "aes-128-gcm") == 0) { + *aead = EVP_aead_aes_128_gcm(); + *cipher = EVP_aes_128_gcm(); + } else if (strcmp(name, "aes-192-gcm") == 0) { + *cipher = EVP_aes_192_gcm(); + } else if (strcmp(name, "aes-256-gcm") == 0) { + *aead = EVP_aead_aes_256_gcm(); + *cipher = EVP_aes_256_gcm(); + } else if (strcmp(name, "chacha20-poly1305") == 0) { + *aead = EVP_aead_chacha20_poly1305(); + *cipher = EVP_chacha20_poly1305(); + } else if (strcmp(name, "xchacha20-poly1305") == 0) { + *aead = EVP_aead_xchacha20_poly1305(); + } else { + fprintf(stderr, "Unknown AEAD: %s\n", name); + return 0; + } + + return 1; +} + +static int +run_aead_test(const EVP_AEAD *aead, unsigned char bufs[NUM_TYPES][BUF_MAX], + const unsigned int lengths[NUM_TYPES], unsigned int line_no) +{ + EVP_AEAD_CTX *ctx; + unsigned char out[BUF_MAX + EVP_AEAD_MAX_TAG_LENGTH], out2[BUF_MAX]; + size_t out_len, out_len2; + int ret = 0; + + if ((ctx = EVP_AEAD_CTX_new()) == NULL) { + fprintf(stderr, "Failed to allocate AEAD context on line %u\n", + line_no); + goto err; + } + + if (!EVP_AEAD_CTX_init(ctx, aead, bufs[KEY], lengths[KEY], + lengths[TAG], NULL)) { + fprintf(stderr, "Failed to init AEAD on line %u\n", line_no); + goto err; + } + + if (!EVP_AEAD_CTX_seal(ctx, out, &out_len, sizeof(out), bufs[NONCE], + lengths[NONCE], bufs[IN], lengths[IN], bufs[AD], lengths[AD])) { + fprintf(stderr, "Failed to run AEAD on line %u\n", line_no); + goto err; + } + + if (out_len != lengths[CT] + lengths[TAG]) { + fprintf(stderr, "Bad output length on line %u: %zu vs %u\n", + line_no, out_len, (unsigned)(lengths[CT] + lengths[TAG])); + goto err; + } + + if (memcmp(out, bufs[CT], lengths[CT]) != 0) { + fprintf(stderr, "Bad output on line %u\n", line_no); + goto err; + } + + if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) { + fprintf(stderr, "Bad tag on line %u\n", line_no); + goto err; + } + + if (!EVP_AEAD_CTX_open(ctx, out2, &out_len2, lengths[IN], bufs[NONCE], + lengths[NONCE], out, out_len, bufs[AD], lengths[AD])) { + fprintf(stderr, "Failed to decrypt on line %u\n", line_no); + goto err; + } + + if (out_len2 != lengths[IN]) { + fprintf(stderr, "Bad decrypt on line %u: %zu\n", + line_no, out_len2); + goto err; + } + + if (memcmp(out2, bufs[IN], out_len2) != 0) { + fprintf(stderr, "Plaintext mismatch on line %u\n", line_no); + goto err; + } + + out[0] ^= 0x80; + if (EVP_AEAD_CTX_open(ctx, out2, &out_len2, lengths[IN], bufs[NONCE], + lengths[NONCE], out, out_len, bufs[AD], lengths[AD])) { + fprintf(stderr, "Decrypted bad data on line %u\n", line_no); + goto err; + } + + ret = 1; + + err: + EVP_AEAD_CTX_free(ctx); + + return ret; +} + +static int +run_cipher_aead_encrypt_test(const EVP_CIPHER *cipher, + unsigned char bufs[NUM_TYPES][BUF_MAX], + const unsigned int lengths[NUM_TYPES], unsigned int line_no) +{ + unsigned char out[BUF_MAX + EVP_AEAD_MAX_TAG_LENGTH]; + EVP_CIPHER_CTX *ctx; + size_t out_len; + int len; + int ivlen; + int ret = 0; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_CIPHER_CTX_new\n"); + goto err; + } + + if (!EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL)) { + fprintf(stderr, "FAIL: EVP_EncryptInit_ex with cipher\n"); + goto err; + } + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, lengths[NONCE], NULL)) { + fprintf(stderr, "FAIL: EVP_CTRL_AEAD_SET_IVLEN\n"); + goto err; + } + + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + if (ivlen != (int)lengths[NONCE]) { + fprintf(stderr, "FAIL: ivlen %d != nonce length %d\n", ivlen, + (int)lengths[NONCE]); + goto err; + } + + if (!EVP_EncryptInit_ex(ctx, NULL, NULL, bufs[KEY], NULL)) { + fprintf(stderr, "FAIL: EVP_EncryptInit_ex with key\n"); + goto err; + } + if (!EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, bufs[NONCE])) { + fprintf(stderr, "FAIL: EVP_EncryptInit_ex with nonce\n"); + goto err; + } + + if (!EVP_EncryptUpdate(ctx, NULL, &len, bufs[AD], lengths[AD])) { + fprintf(stderr, "FAIL: EVP_EncryptUpdate with AD\n"); + goto err; + } + if ((unsigned int)len != lengths[AD]) { + fprintf(stderr, "FAIL: EVP_EncryptUpdate with AD length = %u, " + "want %u\n", len, lengths[AD]); + goto err; + } + if (!EVP_EncryptUpdate(ctx, out, &len, bufs[IN], lengths[IN])) { + fprintf(stderr, "FAIL: EVP_EncryptUpdate with plaintext\n"); + goto err; + } + out_len = len; + if (!EVP_EncryptFinal_ex(ctx, out + out_len, &len)) { + fprintf(stderr, "FAIL: EVP_EncryptFinal_ex\n"); + goto err; + } + out_len += len; + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, lengths[TAG], + out + out_len)) { + fprintf(stderr, "FAIL: EVP_EncryptInit_ex with cipher\n"); + goto err; + } + out_len += lengths[TAG]; + + if (out_len != lengths[CT] + lengths[TAG]) { + fprintf(stderr, "Bad output length on line %u: %zu vs %u\n", + line_no, out_len, (unsigned)(lengths[CT] + lengths[TAG])); + goto err; + } + + if (memcmp(out, bufs[CT], lengths[CT]) != 0) { + fprintf(stderr, "Bad output on line %u\n", line_no); + goto err; + } + + if (memcmp(out + lengths[CT], bufs[TAG], lengths[TAG]) != 0) { + fprintf(stderr, "Bad tag on line %u\n", line_no); + goto err; + } + + ret = 1; + + err: + EVP_CIPHER_CTX_free(ctx); + + return ret; +} + +static int +run_cipher_aead_decrypt_test(const EVP_CIPHER *cipher, int invalid, + unsigned char bufs[NUM_TYPES][BUF_MAX], + const unsigned int lengths[NUM_TYPES], unsigned int line_no) +{ + unsigned char in[BUF_MAX], out[BUF_MAX + EVP_AEAD_MAX_TAG_LENGTH]; + EVP_CIPHER_CTX *ctx; + size_t out_len; + int len; + int ret = 0; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_CIPHER_CTX_new\n"); + goto err; + } + + if (!EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL)) { + fprintf(stderr, "FAIL: EVP_DecryptInit_ex with cipher\n"); + goto err; + } + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, lengths[NONCE], + NULL)) { + fprintf(stderr, "FAIL: EVP_CTRL_AEAD_SET_IVLEN\n"); + goto err; + } + + memcpy(in, bufs[TAG], lengths[TAG]); + if (invalid && lengths[CT] == 0) + in[0] ^= 0x80; + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, lengths[TAG], in)) { + fprintf(stderr, "FAIL: EVP_CTRL_AEAD_SET_TAG\n"); + goto err; + } + + if (!EVP_DecryptInit_ex(ctx, NULL, NULL, bufs[KEY], NULL)) { + fprintf(stderr, "FAIL: EVP_DecryptInit_ex with key\n"); + goto err; + } + if (!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, bufs[NONCE])) { + fprintf(stderr, "FAIL: EVP_DecryptInit_ex with nonce\n"); + goto err; + } + + if (!EVP_DecryptUpdate(ctx, NULL, &len, bufs[AD], lengths[AD])) { + fprintf(stderr, "FAIL: EVP_DecryptUpdate with AD\n"); + goto err; + } + if ((unsigned int)len != lengths[AD]) { + fprintf(stderr, "FAIL: EVP_EncryptUpdate with AD length = %u, " + "want %u\n", len, lengths[AD]); + goto err; + } + + memcpy(in, bufs[CT], lengths[CT]); + if (invalid && lengths[CT] > 0) + in[0] ^= 0x80; + + if (!EVP_DecryptUpdate(ctx, out, &len, in, lengths[CT])) { + fprintf(stderr, "FAIL: EVP_DecryptUpdate with ciphertext\n"); + goto err; + } + out_len = len; + + if (invalid) { + if (EVP_DecryptFinal_ex(ctx, out + out_len, &len)) { + fprintf(stderr, "FAIL: EVP_DecryptFinal_ex succeeded " + "with invalid ciphertext on line %u\n", line_no); + goto err; + } + goto done; + } + + if (!EVP_DecryptFinal_ex(ctx, out + out_len, &len)) { + fprintf(stderr, "FAIL: EVP_DecryptFinal_ex\n"); + goto err; + } + out_len += len; + + if (out_len != lengths[IN]) { + fprintf(stderr, "Bad decrypt on line %u: %zu\n", + line_no, out_len); + goto err; + } + + if (memcmp(out, bufs[IN], out_len) != 0) { + fprintf(stderr, "Plaintext mismatch on line %u\n", line_no); + goto err; + } + + done: + ret = 1; + + err: + EVP_CIPHER_CTX_free(ctx); + + return ret; +} + +static int +run_cipher_aead_test(const EVP_CIPHER *cipher, + unsigned char bufs[NUM_TYPES][BUF_MAX], + const unsigned int lengths[NUM_TYPES], unsigned int line_no) +{ + if (!run_cipher_aead_encrypt_test(cipher, bufs, lengths, line_no)) + return 0; + if (!run_cipher_aead_decrypt_test(cipher, 0, bufs, lengths, line_no)) + return 0; + if (!run_cipher_aead_decrypt_test(cipher, 1, bufs, lengths, line_no)) + return 0; + + return 1; +} + +int +main(int argc, char **argv) +{ + FILE *f; + const EVP_AEAD *aead = NULL; + const EVP_CIPHER *cipher = NULL; + unsigned int line_no = 0, num_tests = 0, j; + unsigned char bufs[NUM_TYPES][BUF_MAX]; + unsigned int lengths[NUM_TYPES]; + const char *aeadname; + + if (argc != 3) { + fprintf(stderr, "%s \n", argv[0]); + return 1; + } + + if ((f = fopen(argv[2], "r")) == NULL) { + perror("failed to open input"); + return 1; + } + + for (j = 0; j < NUM_TYPES; j++) + lengths[j] = 0; + + for (;;) { + char line[4096]; + unsigned int i, type_len = 0; + + unsigned char *buf = NULL; + unsigned int *buf_len = NULL; + + if (!fgets(line, sizeof(line), f)) + break; + + line_no++; + if (line[0] == '#') + continue; + + if (line[0] == '\n' || line[0] == 0) { + /* Run a test, if possible. */ + char any_values_set = 0; + for (j = 0; j < NUM_TYPES; j++) { + if (lengths[j] != 0) { + any_values_set = 1; + break; + } + } + + if (!any_values_set) + continue; + + aeadname = argv[1]; + if (lengths[AEAD] != 0) + aeadname = bufs[AEAD]; + + if (!aead_from_name(&aead, &cipher, aeadname)) { + fprintf(stderr, "Aborting...\n"); + return 4; + } + + if (aead != NULL) { + if (!run_aead_test(aead, bufs, lengths, + line_no)) + return 4; + } + if (cipher != NULL) { + if (!run_cipher_aead_test(cipher, bufs, lengths, + line_no)) + return 4; + } + + for (j = 0; j < NUM_TYPES; j++) + lengths[j] = 0; + + num_tests++; + continue; + } + + /* + * Each line looks like: + * TYPE: 0123abc + * Where "TYPE" is the type of the data on the line, + * e.g. "KEY". + */ + for (i = 0; line[i] != 0 && line[i] != '\n'; i++) { + if (line[i] == ':') { + type_len = i; + break; + } + } + i++; + + if (type_len == 0) { + fprintf(stderr, "Parse error on line %u\n", line_no); + return 3; + } + + /* After the colon, there's optional whitespace. */ + for (; line[i] != 0 && line[i] != '\n'; i++) { + if (line[i] != ' ' && line[i] != '\t') + break; + } + + line[type_len] = 0; + for (j = 0; j < NUM_TYPES; j++) { + if (strcmp(line, NAMES[j]) != 0) + continue; + if (lengths[j] != 0) { + fprintf(stderr, "Duplicate value on line %u\n", + line_no); + return 3; + } + buf = bufs[j]; + buf_len = &lengths[j]; + break; + } + + if (buf == NULL) { + fprintf(stderr, "Unknown line type on line %u\n", + line_no); + return 3; + } + + if (j == AEAD) { + *buf_len = strlcpy(buf, line + i, BUF_MAX); + for (j = 0; j < BUF_MAX; j++) { + if (buf[j] == '\n') + buf[j] = '\0'; + } + continue; + } + + if (line[i] == '"') { + i++; + for (j = 0; line[i] != 0 && line[i] != '\n'; i++) { + if (line[i] == '"') + break; + if (j == BUF_MAX) { + fprintf(stderr, "Too much data on " + "line %u (max is %u bytes)\n", + line_no, (unsigned) BUF_MAX); + return 3; + } + buf[j++] = line[i]; + *buf_len = *buf_len + 1; + } + if (line[i + 1] != 0 && line[i + 1] != '\n') { + fprintf(stderr, "Trailing data on line %u\n", + line_no); + return 3; + } + } else { + for (j = 0; line[i] != 0 && line[i] != '\n'; i++) { + unsigned char v, v2; + v = hex_digit(line[i++]); + if (line[i] == 0 || line[i] == '\n') { + fprintf(stderr, "Odd-length hex data " + "on line %u\n", line_no); + return 3; + } + v2 = hex_digit(line[i]); + if (v > 15 || v2 > 15) { + fprintf(stderr, "Invalid hex char on " + "line %u\n", line_no); + return 3; + } + v <<= 4; + v |= v2; + + if (j == BUF_MAX) { + fprintf(stderr, "Too much hex data on " + "line %u (max is %u bytes)\n", + line_no, (unsigned) BUF_MAX); + return 3; + } + buf[j++] = v; + *buf_len = *buf_len + 1; + } + } + } + + printf("Completed %u test cases\n", num_tests); + printf("PASS\n"); + fclose(f); + + return 0; +} diff --git a/tests/aeadtests.txt b/tests/aeadtests.txt new file mode 100644 index 0000000..4ca4730 --- /dev/null +++ b/tests/aeadtests.txt @@ -0,0 +1,86 @@ +# $OpenBSD: aeadtests.txt,v 1.8 2019/01/22 00:59:21 dlg Exp $ +# +# MACsec GCM-AES Test Vectors (bn-randall-test-vectors-0511-v1.pdf) +# + +# 2.5.1 65-byte Packet Authentication Using GCM-AES-128 +AEAD: aes-128-gcm +KEY: 013FE00B5F11BE7F866D0CBBC55A7A90 +NONCE: 7CFDE9F9E33724C68932D612 +IN: +AD: 84C5D513D2AAF6E5BBD2727788E523008932D6127CFDE9F9E33724C608000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F0005 +CT: +TAG: 217867E50C2DAD74C28C3B50ABDF695A + +# 2.5.2 65-byte Packet Authentication Using GCM-AES-256 +AEAD: aes-256-gcm +KEY: 83C093B58DE7FFE1C0DA926AC43FB3609AC1C80FEE1B624497EF942E2F79A823 +NONCE: 7CFDE9F9E33724C68932D612 +IN: +AD: 84C5D513D2AAF6E5BBD2727788E523008932D6127CFDE9F9E33724C608000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F0005 +CT: +TAG: 6EE160E8FAECA4B36C86B234920CA975 + +# 2.8.1 75-byte Packet Encryption Using GCM-AES-128 +AEAD: aes-128-gcm +KEY: 88EE087FD95DA9FBF6725AA9D757B0CD +NONCE: 7AE8E2CA4EC500012E58495C +IN: 08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748490008 +AD: 68F2E77696CE7AE8E2CA4EC588E54D002E58495C +CT: C31F53D99E5687F7365119B832D2AAE70741D593F1F9E2AB3455779B078EB8FEACDFEC1F8E3E5277F8180B43361F6512ADB16D2E38548A2C719DBA7228D840 +TAG: 88F8757ADB8AA788D8F65AD668BE70E7 + +# 2.8.2 75-byte Packet Encryption Using GCM-AES-256 +AEAD: aes-256-gcm +KEY: 4C973DBC7364621674F8B5B89E5C15511FCED9216490FB1C1A2CAA0FFE0407E5 +NONCE: 7AE8E2CA4EC500012E58495C +IN: 08000F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748490008 +AD: 68F2E77696CE7AE8E2CA4EC588E54D002E58495C +CT: BA8AE31BC506486D6873E4FCE460E7DC57591FF00611F31C3834FE1C04AD80B66803AFCF5B27E6333FA67C99DA47C2F0CED68D531BD741A943CFF7A6713BD0 +TAG: 2611CD7DAA01D61C5C886DC1A8170107 + +# Test vector from RFC7539 2.8.2 +AEAD: chacha20-poly1305 +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e +AD: 50515253c0c1c2c3c4c5c6c7 +CT: d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116 +TAG: 1ae10b594f09e26a7e902ecbd0600691 + +# Test vector from RFC7539 Appendix A.5 +AEAD: chacha20-poly1305 +KEY: 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0 +NONCE: 000000000102030405060708 +IN: 496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d +AD: f33388860000000000004e91 +CT: 64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b +TAG: eead9d67890cbb22392336fea1851f38 + +# Test vector from RFC7634 Appendix A +AEAD: chacha20-poly1305 +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: a0a1a2a31011121314151617 +IN: 45000054a6f200004001e778c6336405c000020508005b7a3a080000553bec100007362708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363701020204 +AD: 0102030400000005 +CT: 24039428b97f417e3c13753a4f05087b67c352e6a7fab1b982d466ef407ae5c614ee8099d52844eb61aa95dfab4c02f72aa71e7c4c4f64c9befe2facc638e8f3cbec163fac469b502773f6fb94e664da9165b82829f641e0 +TAG: 76aaa8266b7fb0f7b11b369907e1ad43 + +# Test vector from RFC7634 Appendix B +AEAD: chacha20-poly1305 +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: a0a1a2a31011121314151617 +IN: 0000000c000040010000000a00 +AD: c0c1c2c3c4c5c6c7d0d1d2d3d4d5d6d72e202500000000090000004529000029 +CT: 610394701f8d017f7c12924889 +TAG: 6b71bfe25236efd7cdc67066906315b2 + +# Test vector from draft-arciszewski-xchacha-02 +AEAD: xchacha20-poly1305 +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 404142434445464748494a4b4c4d4e4f5051525354555657 +IN: 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e +AD: 50515253c0c1c2c3c4c5c6c7 +CT: bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52e +TAG: c0875924c1c7987947deafd8780acf49 + diff --git a/tests/aes_128_gcm_tests.txt b/tests/aes_128_gcm_tests.txt new file mode 100644 index 0000000..3ca8cbf --- /dev/null +++ b/tests/aes_128_gcm_tests.txt @@ -0,0 +1,532 @@ +# The AES-128-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: d480429666d48b400633921c5407d1d1 +NONCE: 3388c676dc754acfa66e172a +IN: +AD: +CT: +TAG: 7d7daf44850921a34e636b01adeb104f + +KEY: 3881e7be1bb3bbcaff20bdb78e5d1b67 +NONCE: dcf5b7ae2d7552e2297fcfa9 +IN: 0a2714aa7d +AD: c60c64bbf7 +CT: 5626f96ecb +TAG: ff4c4f1d92b0abb1d0820833d9eb83c7 + +KEY: ea4f6f3c2fed2b9dd9708c2e721ae00f +NONCE: f975809ddb5172382745634f +IN: 8d6c08446cb10d9a2075 +AD: 5c65d4f261d2c54ffe6a +CT: 0f51f7a83c5b5aa796b9 +TAG: 70259cddfe8f9a15a5c5eb485af578fb + +KEY: cdbc90e60aab7905bdffdfd8d13c0138 +NONCE: 9d987184c4b4e873d4774931 +IN: cb75a0f9134c579bebbd27fe4a3011 +AD: 7dc79f38e1df9383e5d3a1378b56ef +CT: c6a899758b6c11208241627c8a0096 +TAG: 7525125e650d397d0e176fa21315f09a + +KEY: 819bc8d2f41996baca697441f982ad37 +NONCE: 08b7a15f388fafb16711ce19 +IN: 9b1ddd177d2842a701b794450e3c81f151f195a1 +AD: 277c372784559784b0e047c6f8b7e9efb6f7491e +CT: de9b9c8fe09f705f558c62dc6d40b75e3aa625b6 +TAG: 52e2d2f153a4235eb6fac87ff6b96926 + +KEY: 682769d52fa0bfeaebe0d0c898d3cda7 +NONCE: 6af0738b249d09547837883c +IN: 3461523cd98a6e8bdddd01150812e6c58d5cfa25d385cdbbc4 +AD: abe8302d7d5595698d9f31011c24d4d180a637597098361354 +CT: aa3ecb46b9330554b36d0cf6f6ac4cf5e27bfd5f602da1b3c9 +TAG: 0ba547961eba5c58726c418f51d31311 + +KEY: e2b30b9b040bce7902c54ca7eec00d09 +NONCE: 28ccf218e8de56ea91422a25 +IN: 483080d7e2fb42580dfb862d2d266fad9fdce7cdcdb1158d415f84b6e269 +AD: 9f06fbe67eb2ace15c8011032feeaf72fdf6d316e1e08ef4cc0a176588af +CT: 67e1980ced4cd232ce893938e40b0798b17a1692476342e520b480a18570 +TAG: 9994185d4329cfa5f4bbeb170ef3a54b + +KEY: eaafa992ef6dbcc29cc58b6b8684f7c7 +NONCE: 1ded022dbc56e9ad733e880f +IN: 900951f487221c7125aa140104b776ba77e7b656194933fa4b94a6d7f9722aad51b2fe +AD: 863ceb297cb90c445dbcf2fcffe85b71db88d8c935158f697023e2cea103ec39766679 +CT: e0b3aaa890e45f1c39ad4f13ba7592f5251d6a02ca40fe3633651b35fba74a579f48c5 +TAG: 5c95fd941b272bafbd757553f394991b + +KEY: a43859049b2702e8807ac55b0ad27b0e +NONCE: bbe8c571342cac7fcc5d66cd +IN: 8673d6ee2903265c92446ce110d5bb30aa2dd1b1ac5558029f23974acb8a2fbf4c74858fc73d6104 +AD: f77c998ad3ace0839a8657e350bed15ffbd58f152a0dc04ffc227d6beb5738ad061d0f83c2a26999 +CT: 40e201a513979b093637445275b2db5ed4cb1fa050af0e20e43b21af6bc56dec654541e55b295b72 +TAG: 41bbef45727d19ee544fba5b360312f0 + +KEY: 68fd608c8697243d30bd3f1f028c5b74 +NONCE: 319a210b33c523d8bc39fbea +IN: 2c088f38f7a58e68bdd92632da84770303cd1ff115d6364479fb0aa706571f68d51be745f5c1d1b44fa1501cd5 +AD: 1417a65249b85a918622472a49df50bdb2766aae7bc74a6230b056549851b3c2f0cef727dc805ba2160727fbb2 +CT: 9d376b147620c2ac6a5eaa8ee44f82f179f61c9bc8acdd21680a7ff03acec953437a3cc9660c7ecb1204563944 +TAG: 05a4fb5be11e3edd89e34d0b7132d0fa + +KEY: 6edd3bd2aa318f78b4a51103cb08d489 +NONCE: ef0027b144691bc9716fbeca +IN: e98f2f99680dc748fe0b57390df38a99950faaf555a888d463d005ef4e4b1c22663d3d3daa812b20ae35ac934c2e187cbba7 +AD: 97337902507391de0f15c88462aa5ffc5e4760543850719ccd8a0cfef89484d8095c23ff8c1d06eae4ff6d758c95e65cc3b5 +CT: 3c54842c2099b73daa9c3f1cb64bb913c0527955d923510f3f3046df471c1365db97333bc5a86dc7c5f23047e938fac976c0 +TAG: 375b2a25421434e5e3a021d434fb2d04 + +KEY: f70482d53d3ef70cdc3cd3c4a37aeb2b +NONCE: e69d3de363e225749cb1666f +IN: 4cb68874e69125e1a6f6e68669b48317e1b361d0f7f95ec4cf613b7da2c835832010e8f95eaef4e6800b79bd86cd7cda869d2df258c267 +AD: d72975f15721bd0957f5cb1edecaad2d1ef047afb0e779035f777f94cd7ed1bdf8ca9d4f357d2a1e195f195e7483dea1476133235f7e6b +CT: caa1e48decbda18e314057c5ec32f8733a5cf03ed0d05c3654531bf56faa70751a6c7f70fbd7d39f7e9775a772aba8fe7731cd0230beab +TAG: 47d909cbdd1c7f8b485fc3232bb7185f + +KEY: 98a12fe16a02ec2a4b3a45c82138ae82 +NONCE: 4b3404684825dfcf81966e96 +IN: 899710fc8333c0d2d87f4496436349259cf57c592e98ec1e3c54c037bc7ef24d039a8c573ec7868e8ce9610b0404ea1b553ae10cc8cec26468cc975c +AD: ea1a99cee666bf56c8c3667ef4c73c2e1e6534800d6e39a97de3bd5d39068bb3e2f74f96c03463afa18f1ee88c21209bae87f37e5d0269b68db370fe +CT: 0431b7fc4889ae401eab5edba07a60f9682fe58419d4140cbf4f20c62d79d8a3cc1f23fabead0e96e1c8c90929756ea1efab508336e1d0ed552eafd0 +TAG: 01053ceeb4f9c797eef9426930573d23 + +KEY: 6538e8c8753928960ffc9356d43306b6 +NONCE: eee386a2b1e310665e335746 +IN: a92eb9a93a90fdbb2c74dea91d273a48efe9582f8af7a4e3a377b114770a69ca45421959fcf36107815e53dc61b7bf018fc42965fb71d1eafce0961d7698fabbd4 +AD: c5e572e464718398374c8b45ff8749cd9f517bbd97767f77a96cd021176c49c0acec8b055ef761f49aa6d910375a45b2f572cd5420b99153971a682b377ac88f09 +CT: f36353de609d0b5246f64a519d89a4dfcd9d53325a2d2cf910e7692e68391b0357b056b944e0b53e41568f304bea8822f9ff7a0375a5a8087509799226862f707f +TAG: f7f9b891089d02cac1181337d95b6725 + +KEY: cabdcf541aebf917bac019f13925d267 +NONCE: 2c34c00c42dae382279d7974 +IN: 88cc1e07dfde8e08082e6766e0a88103384742af378d7b6b8a87fce036af7441c13961c25afea7f6e56193f54bee0011cb78642c3ab9e6d5b2e35833ec16cd355515af1a190f +AD: dd10e371b22e15671c31afee552bf1dea07cbbf685e2caa0e0363716a276e120c6c0eb4acb1a4d1ba73fde6615f708aaa46bc76c7ff345a4f76bda117fe56f0dc9b939040ddd +CT: 049453baf1578787d68ed5478726c0b8a636337a0b8a82b86836f91cde25e6e44c345940e819a0c505751e603cb8f8c4fe98719185562794a185e5dec415c81f2f162cdcd650 +TAG: dce7198728bfc1b5f949b9b5374199c6 + +KEY: fd1dd6a237a12d7f64f68eb96890c872 +NONCE: 459ced97ebc385ab3a8da8d5 +IN: 04a9709fdc0a4edb423fe8cf61c33a40043f1a585d5458c7512ec8e4e066a0f95e2e6609abf3c95a5d3ae2c738269533855daedd92eca20bdedbbd5677cd4eee84b7a1efae0904364f1e54 +AD: d253b829a2fbc5877b0fbe92e7b79f38886a49ca889ae72b91f2c3aebe257a3ffe0d390b5d320bea22d6a5536cd9213612f5ed6e3b0ea33ac91cfee284cb25eaaf6b85b15f7ca894317182 +CT: 4a565d3ba4f2ec461c9bd8dd0f96bc00d2a561bfb56443c8cf47681bdf1c61f55854bea060c4219696cac79c09aa9400a7e5c59c6b6ca556f38c619a662905fc5f0e8437b906af6138e3fb +TAG: be5f93201d7980af4c5bceb24ac1d238 + +KEY: b09a4d99112e1637d7f89a058988b417 +NONCE: 74348f7126c0cac836e9de5d +IN: 6b3c4cfd1eb139b62d91ed5d1d8b0f3b52278d5c48787ce46f12b9f026e3eed1bfbc8c6684c6662f06614c69440b3d7cff7c46b2e4aebaa4b5b89236a3cc75535bc600104f240d01de91e0fb3bcad02c +AD: 7883ad259fa5d856ce283419f6da371b444b9b64ea0ddb371b17ec0a9ada27b0eb61b53bd3605f21a848b1e7ed91162f3d51f25481f32d61ec902a7f2cbd6938a7ce466a37e4467e4ec2b2c82b4e66ca +CT: 5e1b783b20fd740310333eddde99a06b5740428cb1a910812219fabd394b72a22a6e3ca31df0afae0a965f0bc0ae631feeaa5ce4c9a38cd5233140b8557bde9f878e65e8932b9e3c3f6e57a73cda36cc +TAG: 784b73ee7824adf7279c0a18e46d9a2b + +KEY: 284bd8c4b5d7b16aebce1b12988fa1d3 +NONCE: 7ff05007c5d018b17562f803 +IN: 903416331583dcbd31420906c64dc76e14d0c5044d728cd9b605b531ddc350fdaadeabe67d08f0b4c7179f82a1044696716cd96459506453141e9ec3130e893d8c2ff9b8b4c241b73866ca4fc1f712d17d7a88bf4a +AD: d0a1f92f80094c1fad630ca584edd953bf44cdde404f22c8e476df8708a97a0712e7fbd8054caa7d65144d0be3b30442d0dfa5469ba720afe1d00aa6bb53c79c1c178ed42fce596eeb6c638c8a8dedf76a431976c5 +CT: 9bc3708f70a68fc16bcc33099325c821a0ae9a2fd0a6a98382fa21b42ddb3a9ac6c34a13c4805d3beb92586cdf0f4dce3885793d49abce33190685e7009a79242dd93594722a1ceaa44886371c30bcc8312fa2bf67 +TAG: 3fd8a4d760d5b878852b1ca2d34dde6e + +KEY: 6d76dd7dea607a5cf5c21cd44c21a315 +NONCE: c1d13e56b080a500f1cb80bd +IN: cb959b92e777f835afc4ae4149b190638851238b7b13c9bf65343adb3130e8ad2356101037f30997d4a5fcc0a1d6415210179fdec881236a799f6e90dd43ea3817819b432611eaafd072368b9c7036c7a88c8b7774a8ed986134 +AD: 92a2bc3b6b6ca9de0cef10d8bdeaadf6f54782cdb2b09e66cce8cb5b56895636e982f7a3c7bd9d221ade62c9ecf68bde70becf683804386606ab1c48ac764c4e11620064545c5beaa5911c118856dfc5cdb8df50052b01762c6c +CT: 522ba9bfb47efc624cd8933fc9e17784919d2b3ccfaeec46af414c1b316355f65b9f9fd7f0be6ac3064b4016e43b8fb2028459f0fa0d81fb6656be0ab8fd841d05d24682b4a57c7c59d89af384db22c2f77ce10abc4d1c352a1a +TAG: 5ea4a77381679876e0e272b53519d533 + +KEY: 1dbcbe45a47e527e3b6f9c5c9c89e675 +NONCE: 98f2da8ed8aa23e137148913 +IN: bb23b884c897103b7850b83f65b2fea85264784737d40f93ecf867bfdba1052f41f10d2c5607127da2c10c23b1fbd3a05ce378a9583b1a29c0efbf78a84b382698346e27469330a898b341ec1554d7bf408cf979d81807c0cc78260afdb214 +AD: 46f1bde51f6c97a9dae712e653fcac4da639d93a10b39350956681e121fb9ea969d9dc8ef6ddfb2203fad7ab7e3ef7b71eb90b5089844d60d666e8b55388d8afb261f92b6252f4d56240fe8c6c48bfde63e54bd994ff17e0bf9380ebfb653b +CT: 0d90e869d2f4c85b511fdf85b947ba3ab75c6b1845d8191634770413d7574a6fbd9d86897cb3d3b5d3d8e6f74fac3bd2a9b783cb16cfbec55dd7d2f7fc5c39fe85d39bf186a3fdd3564bc27d86f4019ae0cb73f5f516b602331433689c1b08 +TAG: 8777f2002d5a5214a7bd8ef5a3ccfbbb + +KEY: fe33f47136506e5cc14114eb62d26d64 +NONCE: 9534a10af0c96d8981eaf6b3 +IN: 3ca38385513eaf1fcd03ac837e4db95c0ed1a2528b7ab3ac8e09ecc95698d52b7d90bf974bf96d8f791aa595965e2527aa466fb76da53b5743eda30bb3ebd9f6a8a7721fbfe71fe637d99a7b4b622e6da89e0824ac8aea299ea15e43250d2eccb0d4d553 +AD: 50b7bd342df76bea99b2e9118a525c0f7041c7acdf4a3b17912b5cbb9650900246ed945cfc7db2b34a988af822c763451ac2e769ec67361eded9bcab37ac41f04cdb1d2471c9520a02db9673daaf07001570f9d9f4ac38f09da03ff1c56fdefe16a855ac +CT: 927fe3c924d914a7aae6695ddad54961142b7dd5ff4c0ba5ca3e0cf3d73bdb576afd59bd2b54d820d2a5da03286c124507a48008c571c28a0ce76f0ed68dbac3a61848e7e2162be8e0bee8147b9bf60da625cdab8601bfb37dfcd165f533e94a32c26952 +TAG: 9bd47a4a2acaf865a8a260179aabf8ad + +KEY: dec1b34b7b81fb19586c6ec948ecf462 +NONCE: d9faf07e72e3c39a0165fecd +IN: f7b0bbe9f0ff4dcf162792e9ee14d1ed286114f411c834ad06b143cadbbe10a6fbc86f6664e0e07ff7c6876d4543e5b01ff5ddb629f896c30c8cefd56c15d9f24dfd2ed590304a6aae24caac5870ddafc0e672ac3aacae1867891942998c712d45efbfa4d99a8a6f03 +AD: d3c4fc4838cb3cda3937455229ddaf1cb9102e815cb9f519a5434677c68b11a0bae1280faee82f1a5bee593e669e6f81d5ece3675b8af63f1491bb298531aacc940f53678ba56ae96fc66be92b904bc35f2d5b68b3ed98569a4d04e8f8a9689ad9fa4b51db0938a9f3 +CT: 2f44ecf549077b98ba551819538097bb80304a55c48ef853e20ed8c3f808dc8cb5eb41c2463d19fed2606b59cee4b458958ea75715f7654146df4519dc63524a0569a00d7bbc4b32a372f82d955be5f190d09d35c267da1017e8b16096ae84f8a671b45aaf0d1ca59c +TAG: bc3af80cf9388d35deadecff5455d515 + +KEY: 021add6030bd9f3fed8b0d1f16f83783 +NONCE: 4e460f51fe6b5eb9558c4571 +IN: d9aa1d0db5de536cfbacb59bb75c592ae3f34a5f9c5ff4f22d14e8e4bd0754af19570221893797f60c89a251cd6a19c2953662dca51264afc21099ed5c80077b0e10a5295b3c4c6fe47d3c1c84fee69ebf7d8a7d9b1b338dae162e657e6cf5277ca70d47b9290aa7efe67b0ce574 +AD: 38d99cfd7578d40ffa1749d5fe83500362ceee76c5af38935806837b2f2d1b3422a5057bf617b07868dd95d8e5f4a24e74f96177d53a0275450b429a2b1f364805030765e376151ae35001d6a4872200142fdce82017f3e976ab0edac1a08d2649d297648320e7dd9143b554fa3d +CT: 8863ad51578fd1c9dc40702e34236adee885955f0478ad9a094a6941f95f900e466882dcd5b86e1563ba89aa105f56f3ba5ed860ec3338ee1b750a2f9332acb3f0f61718de7e40fb80442d046b35f147f178bd05362f0559a20a53ebbf78e920fe14c9d80d1c9fb21bee152f8ab2 +TAG: 614539247fdcf1a2aa851102d25bb3bc + +KEY: 311c2045d5486bfadd698e5e14faa58a +NONCE: f1cd8b373cec6451ae405618 +IN: bd154e428369aac5c13128d29bd3031364939abd071c34bacac6ea7292b657b794b2e717d9bcb5d7d01496d805283fffd8f7de6a3493ddd8d1dd7f58835a44d43ea22d95468d1239ca5567d6c80bdf432fce2afc544a731a2852ef733667b9f8f4f8923eaa9de3aa32addddf99b607efce966f +AD: f70cb7e67b2842207df55fc7582013bbddff8c7f3bd9ebbaf43827aa40f8490e65397934ee6a412de6272cd568566ea172789a006a92e5920140ca5f93f292b47dc262cefc66b75543f94365c08795b7c5e9c6c29b7dc67b2532fbf8a6487d40a3eff504e75c3f2bb2cc3969621028e2112e67 +CT: f88f4ef0431d0f23911aaa38a4022e700d3a33c31e0c7bdebe00f62ca3b55d358385de25ceb0538242871eb9c24530e557d7981fa0182436e1e49272d52689541f09517fd147a8da0f0d2bb32d54911a36eded0b87bcba54d6842edf461b45839df1cab5176e2c82c871b3be4ec1bced67ec5d +TAG: ae8d847f106e914ffadbdfe7cb57beba + +KEY: ceab57de6220b2c80e67f0c088e97b36 +NONCE: 8cf438aeb0cb29dd67506b9c +IN: ce2a7a5663449cf6e0068085e3c373c5ca6f027544e327bbc09ac00f1571268bee186d51a00bbc16da7429e4d3d5235d8d54ac96b6ecb2fb7d77a6e5b9e70d431dd4dce78ceb972e9e4b63059e350efaff841c2c42bc29c139b7fd070097556b6281b58e074d5271d9f66c6744ec6dd3b9db2f4a21aeeb7d +AD: 03e464d111ac9228d39d22a00120c6ee671fe5bbf462b1ee3fdf348b34999518998ac4e175ed48189c29b49b5527c27c43094eecbeaeacd3cdb48cd15aa82573e884a7b97bbcdad610a6955f7d8b04f6f98a13a907bc2bec4c940b77582b248f5fced1771f810977b2d0a4fa48bd4d78e4bc383bb92743fd +CT: 1fa9c379c78b92fa3c1e478443ae38d7b4b50235448ce2a88467514bc9db95844ec1baf4dbdbd1b0720e377d05d82c3b58b52af8c9c50417b39ad225e373c7ff18ac5a6ea5d182b255f1c8a2766e31e3e4e3d55dc08dfc64b818ead40a0e824b06ab24f0dc9f4f0c383db7cd4d40016b31701bb401b126dd +TAG: a9a885578467430504731d1a8f537e3c + +KEY: 585bbac0ab4508afb8b72d84167551aa +NONCE: 774c82af194277a5506e45ba +IN: d788112213d2b8b5b66b056e8b3e344a7876f6193b59a480c51fc04d3ec2e5166344c833187b14117276fd671a20937a4553181c29d3d85afe385dd86093708226f082a2ea4ec3288f372c772ca7ceae86b746ff428e8add17b0f34f8553e3db63f55224c39edf41f138a2c28be49d56aa8b4c93502b9794a16310f78b +AD: a29665261a8eb58c88803bcf623dd1a14e76af49ec5db72a267f2ebcbc479385fb6b32bafcb1239515d74a8282b228e83daf282d1ab228099b315bbed0f0e6b3427e029cc28c025460a8bf0914bd584c13e7de7830ab77fb4a9258dfdc9fdaa96ca941546477f04cea19a365a27de34e23e154e7419aefb0be0e871bbe +CT: 24f2856e4e40c0b2b8b47e43d94c1faba498884f59d2ae1cdf58c73770279c96feeee3025ec698cd8f0ae25bf0c9fbf2b350674c317e52bad50aa6ed9845e194f294eb71ff192604af50ac7192f308583a3edaf6c7aeb588990be81b801dc916ffd621dd4016e2b76e9078c89fac9da39f3a88f6548006a48b0199a732 +TAG: a5c8f9daa30b045bd3e1c1b01f438518 + +KEY: c5d727d159dd328b4160ff45a183226b +NONCE: 881c0802db519ce1595573ff +IN: 88b4be77bb8a2f37bc5e84ef9da92a4b8c3777dbcccfed13b97e93c19674c8c3f13119363ace377a14e5f36501ba9a3898fc09340886d91bf0a17ef0d028f2a92ec150071623a4a5db8e56e99e764629679943ea879ec7634fad1480e8617fe834c26210276d7db208b13f9b4c2060f2867aacb1b47c8e110830beff721dd8d120de +AD: 5f6513ad3d490f784dd68ca1df41e8c8e1ab9a240ea8e9bc22d0b1d7353da94d5d37c94f0dcd1a2dedd6d8e1c79a383e7e214cbb6ee2ccb7c6d894ffce5d01b6cf13876ae2648d36adccd88710d7d2ab6d43826d37ee0ee3b434972a2cb8f4db1c3304cee0a352bbef76f05de0e6f55a410eea5e697afb197f2483f0200d0abee224 +CT: 66bbee209eb11c675ecd3303c38cf1087b010c532e1357732c4911ca9db78c67805c95c829194cd413b635a900a08454c6eb9cfa3597ab531fc9ddfdc5b02b290be2a618df7d03b1ab465d6d03e8b87a430bf4e80d8cb9916145cf2d2342a91fc79defa151b1f3c695608e76ca2abc4c0383897f1cbb9d4bd9969b2f33813e2b5502 +TAG: 43daa08e6eac70e3238ce655adb65005 + +KEY: 16af56326046c92afca49fe173d643ad +NONCE: d32a935b4e56472d92d9f2ce +IN: c49c8e5769670384d23d9af9834026395d3f3bd32d88e61ed06b2e00e52a5ae4fe3867993c2af95203cd4006470a89677864431fb9edbed17412913bad4bb3eaff0fccaa150c9b13f83b9bf06698af844841a640d6f94d845296638ac27fb5ed87c310dbbd36415161310b284b8f84b4e025267906e0a4c822b76a682d44a70f9afde9bcf48ac2 +AD: f713886f4086026779a7e479fa646cb33574e6c977d70b8da49c8fdbb395dc7c149a59e219db8e4fff053cb00e2a1df9850fce94e52fd34661fd3d4cd8ad3ffe0b4bc7ccfbbf42eeef3e30ce13cdfd77dbd067ae9f5aebfa068f6b7ae2c17ad956dc03511dfcc38eac9fa3c0c0e9a340f5c58e39d868b77dede54fea1173216c0bb8f0a6c2990f +CT: d5d7d1ed0ae3e3481e2ccee201857ce1f427734fbb4fbe82a2b90601104008b8ad4daf74514b8ab3e42b6f6b509159ca04489b1175ce1e3fe33d36ea521e0aedff8c69fd00aa588d7a2eb9d2d551e2b8fea321f573e2a1df147535a873d540a3169d3ebc099ea6c33cefc04a2d55dc2d47237b95ad269fcdcd3c3750af426beb4edfe7837b413f +TAG: cbe0fb9509c224bb0e8e33f7ef9b49e6 + +KEY: b3df227e6dc2c846095e2a3b825d7645 +NONCE: 578bc24ca3845e23204df661 +IN: bf69be81cf0b340b006badc9f644d10376f4f9a7a78c997edb8729e3786447f21e97e4c1e0c0c74e01ef655d0a84ffc04ff7c6712ad65adc9a0da2e3078d4c9e796c9bcd71e7a9da26b987990d366b5e00a23a93652e10942e07a6aa01375af27080c9cbab5f554497abc48260937a6fe895361e79cd3d5e78c1a65c6723d4a4fbe9b3dcae3c05699cf6d3fb +AD: 00898eedad307fc017917a3296bcedabaad8a505edd34e93d92f3b61797ddccf3fc31144ef70f255be3b0c165c97eb8706f14c495f4aa9b3f15d2dafd65bf6741d67fe240967efbf0e75e610db9a8f722035e039b5e9246d258084a04c12ee8ad1668032f8caec737481fd894dba2ef702d3e6089acbb0fe0bdd6daa2a5cd47fc62603499fe3ea37365072e5 +CT: cfeb249551a695ddfec5f789e7f0a9f916abc8ee01d6233c32744c10a09b5b19ff9ed15e9f10de8f93c8ca1ae3c34e26fdbbb7f3b0f5f8b064501830d3cc982da99b294ce51bd33085c98b0ac0bfe44a8f4a5a26511afa3461aa88b770f076fe119ec90f33d8c9e7777f30b8cc95864f06e04dd8e328ad7a2c7dab83b03abfdde065bcd0c7d6dd47389108c4 +TAG: 3dedd1054f1a29286a51817264317b83 + +KEY: 58a57f04d1d5cbdd1bfbe01dd5f7e915 +NONCE: 47affabd7dbb4cce76661081 +IN: 5f82d481a6a3856c6f0be2aca54d666f16de88294a4d763134dd51ef03661bab45da94b9871d94e5b574a52214b22c92cf9690ecbffca9b108fe796abed9e608778c0b99d7bea1daec08dae89d5f7229c04fd52cc906b5f5b9fc0f0fc1e0b2272dcf4865286ee22bd9edcce1afadb579ec72cdf6038cfc75c2dbab5a1fd64b6f8e200d1ad0afcf25863293fdb7276648de +AD: 4b662822b48005fbd85bb99e6a946eaa74403909f646d914a236eecc5f4558b60b2efb1584b1f32d936b90428dda6568515801d21d24d6fb622e6463897c70be01f81fef741d6dd5c6556d163c3f048abe49f21817b41850ce79d7ec1fdfeba32935b58d898e964fa4b36f79c0f1f560b0afec3887ab325e1a025fa7662f9baf8e08a9ee714b8369621a2f1e6d2e96896a +CT: 31ab08ce0aaa883628f4b33369e5f6e5a54ee4a6596f25ecd54eeea30e81b41d357cb6c671adb6acd3d4e6654feb2ab1f3259692502efb33c5121e0852cbcb2dc5d9a4c65752debe9c4bf5e995fc909a2881621d46cc220806703795e61c0fe74c99e3c1230521b1f97bcbf4e95326e2d581f0cc879a2fc06ef88226a4413f9e9985edc913c418cc198c4df13cd46afc24 +TAG: 1e54066c6cc37f35c62b47426b609457 + +KEY: 64011470970333b7b677d4ad8ebf3ea2 +NONCE: 17031c5133a426d96de93123 +IN: 882cac1ece2d22a1db7f8339332379eb68516c8b7dcb3c089a5bfecceb49f48a169215313686eb5708135f379d89962af478cae865841e0c97ab47a57a456f634282c4e03c99abf7f7cc4e8360deb48160288f06e96cb09114877f9d91dae98828285626a1528aac87f39cfb8ad3db344fe4318aeef6f6ba14bd1edf9caab548c09f8eea091229a90dbc4b0fa34fda2bf13d300a1f9c +AD: 0394bb920cf58806b909d90c046402c745f6876af85d8a281081e22a1908f8475126594b39a0e191a070bda7c78d30dc4867e69ea522cfc962fa5f9915daea9133e998eab22f32a18957a3cf7d91c6f3d54cea94875d60be694ee841fef01e69bf5997ba4f25e846558431eb592605265f235211c2bb2d4807278f4b9c314039d0768df24e9c098c6a01c689d6a143073fb1a29f4400 +CT: dd347d6a3d4a71b2bcae0a0c690ca311f012c6ceda4f7fc054b8f9b59bad54237b64b93331b99f1305801640a68e7d50cef581a57ff2564c90995a8dbf57fa8cff046d0b946af5f68e0aa3d73262965622fe6d35c78f949a6cf9e4f62ba71accbf403b690e31f610305faa6737a19efba1e1ee97084cff2d125bd69a5a4ff99aa399df650452daa835b3e54114b295f00d94fc60e2f8 +TAG: e5e72cda6755bfb3a44377945adb5ca1 + +KEY: 4852e546fdea545d7dd12493a687e895 +NONCE: 7a3e136cd961191570c1b0b7 +IN: 30c10d7a63b614bcae1b79b07c252dc55f322554ac34ca664910fe4a0c9a33e30698e124d91cbb55cf34e931807cbe591a87667f2284c1c18dacd108163aa7a82e274ae659c4ea144191e3fc0f82d4cac929969a50b98ed9fbee52cdf465a1f0535d7d7df15a9a6eff3f4a14e254571cc47f82716d7a835dfa839213677c4da8c8623517244891993ad5956f65d318d9bba16f1eb54d2974a741ac +AD: c5ded7f545d2eaccbc2cf5cbd1b38b0ec3b6bbc054ba25a16efdd448e5a47b0085974e469c1b0df22441340170d6677f5158e4ccd71446d7ac73dcf5fcfe4ad7248c4ddcfab4c8ccab0968d74d66d9c9561650eb98c088d87766440fc9967e8463febcd12ed07f7e44fef47cabf05274002d0014c4e31f230a41171868db68bf5a83c902724397ed181dd8c6768a898e0c78f6aeb886df95442e99 +CT: f798de4998683da7fa9ca030a23dbc493f36c48bb52cd1113c3ea97ef2b67433c00195000777fa3b75a3f689a66b148159524a1fe9576587948760b279cda56164a23748564ec66ea51368ba2a900c97169eb33cf1e557f46100193575737dba670175035f0d921675d45415c6591cae079698e6b1f74e82d4b9216c20e907b148a1d514b2cf653d2e4994f7f668dcfe88dc49c29c544de96d8dd0 +TAG: 3663fb2672223154981b4c580ed3d2d9 + +KEY: a65b520a2ab67a24fb8fc669c41f2753 +NONCE: 3bd6c7e8d29242abecc4c108 +IN: 9d1559d283f7a38847088116f2156b19a8feab0731f04d0d499c6b0d21b8563a89a9c284230c1298b28a622cbdd38dbceb098ab896a7259caaabfcc7b0d9ea797178c18aaaa351c7f516342dcb9d3e91405882c8faa9a28f7c67f3db8913b31c0dcd56472d8ebbfb20cda2896a66bff2706b12ae0d9bc8c6c123c02f1f0bbaa418c1806482423eac72d718cad0dbccd208eb81663a9d9043d6ae7a52cf32b1fa +AD: 2538529cc6eec03f70df2ab085027ce015279484981422f31e58aeee31e79703d72752af2b8822dce9b385f1530f19e692e00e20ef973d333f4bd585ecf122bd4ed9b0626cef46baff0302c71411d27e372361f36c7245096faff21f0236f3dd675646760d5687b3cf1544dbcaa863f1267bce04bca976616b890c7c6ff3448d16072c3938f9b62377609950ff7818cbdd21fba2560bf1954a93517962181b18 +CT: c3194fbb5c319a94c0f61c432a730ce7611a005cfc78266ac4e5d7c95351e71d613f06f52d9d008b9d886f4d9a57bcc232d47e0c75ab755dfccc057a9c7558d7fb696a8c29843a8b9199e2406d23cd6507d35a872fa54cb95e2cb9af45405ebc6b6ee353e8a80debc393329bb9499c61c6344a6380c118f30fcd76376a9765517652e1b21ecafa63c0d19c1875658f1eda89c15ac2daf1a6f526ca72ee792a4f +TAG: fc16cd532c926ba01e2e6b15327bfb3a + +KEY: 84215d2c8f86e5b7bf93cb0620da6bb7 +NONCE: b35e99ce89dffd1ec616ed92 +IN: dfe500919f97713f6d9c4f53913175b162b8b7587d85d5b63f0cd5f51def23119e2e02c224142ecfba7f0a519aaea3c28be20b9c2a9c98eb145afd4db523b7f0b822e67dad630846b2a192bb146dcbeae00198c81b80c290d881125c24a6b01ec901b8912bad5b081ec7d97d6997b33052ec287f692489df928ce36cba1e3d6a41cf10c697a9e1f4aaf75dc5be054b98965ec3ce173be7e127c4c5387048ae6ab5a8d247f3 +AD: 6bf6222e64a46c90f83f47305554d090bc8d3838b7a856f0e5e1d92c4e7231eda6af1d9eb7ff6ce914f2256a3b0c853453b9bc75e46109cf8d7e8a9dca224e022d3d1a139d00476775622799541edf9d53eb645a40f6d98ea559e181d96e4df0141e51fe067542300581c0424f534d2c2e3b1b27153c0cd496a1c03301226beeed2b5cce0710d1f485e68b44a918b63fd8db610c7ff894514e272b6ed7ae33a38907e0698b +CT: 6c6faa54df62ba5659d45f64a5f014684138c93bf152da8a495e9d067b13a30b9fb84847f56231b2da4d87e6cd509a3e38a9ff47589c627e5b5a1196e27fc7afaa14a8432c2d10d8fbfd5d6d394e4b947c456420708a76c2aa638df7de119c160636fc8dfba32227c5de12e5ef429da933ab04e77b489f2eb761d0c753738647ad6793cad64b8942f621ac67b13bd0cab106ffeff21f24c79de69424e50ae550f2241d4029 +TAG: 202b232472d050b9bbc68b59a0c02040 + +KEY: 7c02b6bc3db61e23736c5f36faddd942 +NONCE: b958decc680d5f79ea7b8632 +IN: 7e5992ed0474f4224b8da1d038eeb78413fc2f9614fab7120043e75986a4bf1114a80703780a149fcc8dfd115b768f45917065c85176a3f00be40b427fe3765d3919a5b741708624e29bcae876d251fd46dd8d36a8ef66f671c25f984761cf7f75f4329de7093937cdabe32f130b77531ab1aa0a1bc38fbe2758c2664eded828b2589fc5c34d9a0d57a5a4463163736f419b65f0543f50207fff4cf1065a551bc00ffe9466538b673b2a +AD: 76e430fce1a7d8340104e6001f1c2048d457ac335c5453e48727244b75c3c4f04f55afbb5ce55ba6f8632dbc168ed715b83968a32e5b8e91cb24abc9efee6dcb7a8bed9394a546f0b9efc5823ecaa192df061eb41c671bd863498c2130f322074a711ee43791a1cc02b5cacccf25119ecdd99233abf3b131c83ddb8c62c93a0d653e91499e7481303adc8dbac615ec464eb8640ea138f6236b0ee31cea060f97ea9145a22d15e28eaf6b +CT: 14cfd190ae0521f94ee6b36bfcc403139782bfac3d33fe95c81f53e83c7d0c9a8fdebbddd79746b550a383ece1b5c93316b2fdf5aa36b4e97f739f78ccd2de9963ee7fb4d77b581cf676bb679b2dc4a48d977b45564f21181dc60ecee84d736f2324196c20327495d18973660ccb5dae69b79853d12e48ee0706c8ed821b7f722e46f35c8dee2b7b55ebee01dd3ea1e8ef80493cab6b27c264a67596cee06c15062e3a96b140d0d9ba38 +TAG: b6c47410e6f4a2f2b172c6a4490732f8 + +KEY: 1f58ccb33649d0dc91c50f2aedc95cbc +NONCE: b3a392b1fff0157e95f82a44 +IN: 738e04dc5a8188d775262c2cdaa04468844755dc912a4edf9db308efb3c229b8e46b2b34aee2c6330219bcd29d3493e3cead142cef5f192b043502b8a4cf0419f9b3f5e001a640541c84141e36d585b05a2f702356bd39bda518c42b461564326969983d22c3ac5a2aa214807ede803d57a61c9547505dd7e08402cc43e6ed1574a48366cf5b5573afcc7aa3c4d4721b362d20a58cbf251315f2b5f9e2c97c5ef6bff44beaa5004e5b7c7f28295df2 +AD: 93f7f5054605edc769efc30b35018ee6c929a83bc6454352c69ba9c72e4b4ea6f51c9ed06f314b5682be6a701c719087765d0a7022e5c9d495f28a9053bd435b8b834045c3670856149b08dae742b372a15a0184375d50eb09877bf94f63859e64228606791c516e76c5695a4e529b9dc5f76eff1d4641a22597e4460aea4eff107348077d4ed2d6262744b0a2d6610f25264d905133309ace10bb52f7138674c25e5d43ededbd87c13dc8fd9d3b1b +CT: a002b47b18d1febaf64842fe9011484d618a2e855c4efcccc7d08f02dc9b53d0bd4fc8013e01e21fbf2d9bc7fdda69e68be0c06d32003d045dca6bd251c0bb8c2cbe3693b252265c8694295772b767f83661ecefd57353f6f1c442f9d21ed98c55cbe1db8171ef7b54fe3e3a1a253b4dd48416b5fbc7c18d73692e9fc90dc75d4b88de1fa47c9ad33ddfa4e582d3fc61ca2a8b1eab898b9992c8e56d170730454ca50cd4f28d2759388cb8e302be10 +TAG: ac502a9a52fb3a68a7e90dc639c7ad42 + +KEY: c67510714f556ea1744af9207917eb60 +NONCE: 71b347a21653cec3d113087a +IN: 7040fde3513cf7f1886d7be9c0f371a3b75415e94c3bdfbef485081199bec4494beeee76dcea05b6601ebd4c8fe231fa16d3b0f046eb3e9c9ed8baef25bb0ff6bc85469b2eb41b929fe904735f819b241b01230c68c0b61577899426bf0dd30e085cccb4ac290244d8c1cd7514412a3ebc51aecb6bb4be1a5a4a8d2ff3fc99191f7d7d0b44fe2cc4ec34deccf901f54e3dbe19d2dfe663855fa9d93a01ab14faed7f00c14834f63e1d153441c6fabb3cf22506e8 +AD: 6d28b410c788dba025c387f5b94c0bc392c69ef646b9cdce53dc169326359de26a721703d9a7c5017631a469da13b2d9ad9115de7d06922ed6f093792ac25ae2e27993ad6be5217dc4f6c51e18f230d4eabb01a474704b71b1407d9cff921bd98e28bb60c4fc019b4d609667c747e83eef779ee62000b6800ba2666f415dccb12d43af4f585d3185d66ba2ecf0b0fcddf762445dd1b6154591dd069f03977243b45b113b6f9b110f9fdd96f0b74e2c9843a45c6a +CT: f2a2cdb4f890241f44e00b3373769542cc3dd24c3d07502ed162dfa10be9906871051b991f36b2d5c4240df483c2ad704be14b9efe79ca704e8eeb9dc250e75a92ebf5800c59fb9a6a32228fa1121d21e0b423b77e20010d36b9e6c68dbc000f69bddbd521a1f7bbc9d7e431e4e46e5094be96a928c6729293d2d805c468a3993fb7439f192b1142272a78585e3b7fcedd2f7cced52ab2bc42e2521603b89ba7633fa3b4d07d9a314d1159d7bd5b2dc5198b0c34 +TAG: 0b386c3a58ad23e9a45f00ae107d319c + +KEY: 171d25e195bae2eaf666993f3b42d690 +NONCE: fc16bde0c69d5c894642f1f3 +IN: 8775d6aa2e46ffea6ad4439000a968bcd4fce86535b7265684071a498e0bfb37646f56fad79e0fdc4d6016fd1e935dac5ad74b11c69f5261c3321efdb9cf03f9b7ec681a7f708ba8e3f66648b24c41485a5147df31385809c800155d0d4bbf41d248453302c3754eed4909b267893309ba5249588cb4a4a14b4a29496f1e799559ac9f4baba7a9b4cb5bace1c11dc0e7ef7a2ddd2596c29cdaa378b97c7d3c50db49bcadb8e1840c6b9fa12ad88c0b8152fd753efb04ead427 +AD: ebb169a863dd05cffb9deb866bdd130a1c6852046881f3f8e9013158c83bfcbaa98743957ed4b0619eb88d7ff69b3a5d06da74076c3cc2dff83dc0375236d363c0e2b1fb60c9cf10ecc0fec94757b1b719abc7066af15ff9b66788b38083f766d67005369319967995407ea20339ba27e7bf1dc263fdd54ddd8088232a500f605ba825fedfed69cccca75c207b06594d1d0070ed12a259d4f574f352d2e2ea6fa45199213b6a42d53a7c717250715e0404f2fe7b64e3ec7e89 +CT: 8694eac2bb3968303f795bf0118e43c132c9dd22ec320ecffefbe878ebe6b1e0833d19515c07ebc83f12cd9bb50d2658e6d7fe44a9fbcc2225e93ed58e1bebd78edecbe6c8b3491eedfdcc957cc8ddc95d8116d50cc50b1999ac420802605cc652134ce51a41533e00fe232344e805df146a952b40ce27a2f5c6bbba2154489ca40cbb617476ce6ceac1a6b9c0175ee33615f252377f52583e970f77795b573610baf5cbf5edc6d2837244f88bc155f71588c9c4c1c802be9c +TAG: f6725998336b3ef020b99818e0d932ac + +KEY: f7db0fd345ca6ca82ec8624950f8e672 +NONCE: 3e7ee1a209b1a191f0a00370 +IN: fa86869e14df0fd8e77eba7fe5a933fd1bc58654deab310a03aa7202a089713e323a323f4932b4b8f6b40982d6738aef48951f621aeb82a747d290d93d1eb5bdec6a62fe66774209a4aea7261acff80af9512af090e0eb0f5905ce8baf2a0ec50ed89906d8d67f370639e6f16eafbdfa982897cd5a3f88929d7f1032a8b3355223bf666be94ba9945fb5cafe655d59af69829ef92365f54ff3eebc45e01ffc439b16e23ce892ba6db7e661fc3676a175a8ede746000ca147db57a14303a1 +AD: f7b826afe62356f985e8e10ff356dc9b5b9d9df24486523c3bab7db355c84ec7e4bbdf66482b74fc6b4c6aaeccd7717fba44eb4820a40f03639076776719ea7aabd3a815c201146428bf4c6bf1e8b056b5a22ebcb214fbba64de54089a20ababda5c860ec301f36e1801fc55fe8fa189f35722a2cbf83ae921a9537be2b4f060d918af9b12f9111909d59db7cad24418896ce49762223d8a20a3a83fdf24b64703c19c78f528daecaa8689f307da7fe0befa1d6b1bef24ac8d9f5f12b6c1 +CT: acdacc648833698eff4d42a5dc0b123cdf6f2985ef05e6f2d42c9cd04663635d240648da18dce158b21cc0a3f7a2c35441799a4f1f5622e11051c874b2bcc64314bf0b94c2589d2a24d996af57d22085a64f10135322cb68428fbb951d8b14683bf6fc96b1395829a0b05ec83eeb20e54daf7a413e070ae1e0b73bde56faac630363fe215f1883cd9eef9c3b7d076bbb56f6f5ffcce0d31570f79be8864482b6b3666424dadb674f873a1b52ae6e3d8ec8984edf54186e38c71602098308 +TAG: 4dba5b1385565427a987c9d0b030f4b2 + +KEY: ca80ac4cf4057182d06d65dcdc09763a +NONCE: 63cdd8090e041baa9dca5bec +IN: 701c739ba0c146983b9e1fe0a9723850caeb818514860c3d4adef10dc5e020a8dd7f2fa282896170f9039d5b3fa629dbee3bcb81db44d0d68f9522477619269a59ec1a9ed399d4902f25271dff5c42f3747ab0f4b61c26a2c1bfe1c0fed02282fc2ef88b47825cdfb11df3ced0fe0227e8264132dd62af2d31f23d0c0e253f01c80400127c37806762eb28bc71f31807229172c78ae994b4ad800d6247ea12d3f4f902bb50b72c132902dd4faee05e67836facc7001c8f58475366668ed20d4899aec4 +AD: 0e91b38fdc70951b97e43aa9ea2c6f78d445d90ddf4faabd3e6e0ef74f528fbd5c3d4da18cc3d8bd3167b756da495cba49ea35e2db849bc37f6db8370b492d7f82f2efafa5444ac62835cb5602796cdbe85caa50084e51eec2651996d2da0dc18fe10bd6f374168d4c9ea0a36ba665148192252ce9d05cb78429c55256fbb65f1bbffb8799d63bf41701d1d706a44e3f27eb245cf720f2a329ea24fbea803c575513830fff579a1bde3daa975eecdb8d3956ddd374fe252637aac86ed3c702c4ec63e6 +CT: ca46eac0addd544bb45a97a4989d45d21599ec70f843d9db38157d186716dc39a5d1a5c0624e6c825b5b7f1fd41aa542ac846ec0edfe6bc28f727823667a33cf6cb5ba1ba6654cd023857c53ff00a63b34d2c17ebae5d46dbd073edb7b2f9e02842dbf663bbe36238f3eaeb7a23e328b0d3d50f49674253898f360c0243722af266c934f021e4f2fb8747fae728d06717b2d68cadbff762956826c910cc8ad2d4aea4518d5ac4deec978a13072fd1675a272539ebea31d736c759227f31abc911e0e76 +TAG: 9f0202c228ec48f4be6b2f876fd05a83 + +KEY: 9c2daabcfae974ae165a2ea58ecb212a +NONCE: 4b9317e4be2256a467e2831c +IN: 09169c1f5d873f03821393bef013bbcafcd82314cc986675922e2d43031417c8e65e625ce737af4621aabea6fe75030b84acf96967e791f8427b8f052051d6247a897006c6ddedd49cb7148afa5109a561e78abff7c55b97091f356e31b5667270d5653a497e2503d75e5856ac1efdcf3fb6e80b8deba8802acc064905e2b09d45e446d7d810971e5996540ee9c01fac1b4331f99ad329565a8db38eb93f2e2a8ca37d64d73cc8a7f4fe3234cc155226393f1f2ad17d0f01d5e60537ea44835dea853e027dd597f7 +AD: 1feb0ca13b3022456a4801d8f5382cad95f7a50e466a102d2208e7482dc8ba5c710d1721de7103000fe8811bb13fdf698844257dd164f1e21b0707251f228ca8bd437994526ed5684c4165c9754d1cefe7eb18f9e116a455c28db1f7c04feab74ab06af029819f51ed96f453fb6a634f73ba8c80e19dc62384e82feac70a12d42e3125c360ec2a97f4ce0a07039687ffc37c5dc1df1ed24f05a37591fcd5c34a3fc5f825c79213adbbdef65078f5e41a4062517334a67560ab215fedde53cd8129a51f27baa80f53 +CT: 8a4d4ae0842f8032d83b2e4eecfaea439f745f1d0d07808bee4b68e3b58fcb65a4c8fd9b93cba2d5b4781d28a9cc01508e9e85796551064867551f9083cce342ba1aac4d2b8f5b0b0e4e3d7c82082c441467e47aa2b0f47e167b28fd29cb8d5ee52c2298c1f87cf811061d922f056214346c1ec3d2534045c5c485ccddac7d9998d3d08a80a62eceb2ee18e1a27f97616969df52ec486015974f160745667d6be25ffc20b143d89bcc8b6eab9dff82ce3c8f95a034316a8f2f2a52674105f1246b2daa28edfd829d +TAG: 0361e65b1fdb9d967492ded32e1fe811 + +KEY: c98ed84949749efd2ee41eaeec51edba +NONCE: 7b056c9c7b393b0b04382946 +IN: 41b87fe62c82bd34cbdc70033ca8d2ec5f13eb2c14947f97fbb5d97da7323f8eb5c2eba210be11b1ab9554feaa516aa493822af4a264c8849e9c6ff41f690f44966bb49c9c1df5995de8070a2fcfa42d0b0b5115a36738102134f571988ba4fb210edc3202d3c74b5f8801a7d1e217b90caa27acb49ece590ebe6637fb6e2f5f0b849f29804efdeb8c102b3e3d2abfc4f6f2c5f71f0a6e4d5daa5cf16561914f14601edc40547d55f7d11eb4768d5c64fc621d04e8c64aa3aa1245c7192852d2ccaaabd448e06f806eae66da1b +AD: 2fdac5a70356c2c8d70def497321c6bee8ebb08a5abc8dd508d83f03bf1a09942d7f7a387d4f875a1ff16c7b5abb53d32bcc372012eab7a3b848a93f7af634eff8c5deb3269d418be698a3026f6f08f55a6e31543105cf1ccf56193cd1af802f32e10512a6bcd3101b7b54a8f3efdba03018d5f2475b51bd65e5e183a62ab11c9462450883e3e87a9640eac909f72b83da8bbd34431ed87d14c6f7e79957067c1cf2a12b5fa083496f903269a3c6c8ccd5e3f9cc287904223ee62bffc4f157f0db409e82101e3ca5e05d962378 +CT: 384ddc8e7ed6868aa722f6785fab15eb69caadf43246521b97c8d016afd976360365bbfc9f48c08b0eaf5437af8a9c23061dcbdd0d22e1d58c92951b43e013689afa6b1587f79fe9ad3104ee1f80b3c95388e35b0b9a5a3b733b32a3e62fc143e6255d0e5b1b55bc9439d3c1cbed610d36c3667378bbc1ac20d93a5a7e5563409a5b94ec799a5281213d724e46f4987588e6bc7e9e6468bbcf340d5f1a1eb1b45dc9fe9c832befff54c8a85db9c07196d7d45cc389fc9d62f4bf1f4bb82801cfa9c408498331eef4ae1ee2809e +TAG: e8cbdc1d6d51ac64f16cf08725f81370 + +KEY: 42ece9aeffc9d2e8ea02e73d1a4de834 +NONCE: b59e0770c689d60823c06c69 +IN: eccbb9a2c1241c88d17204cb0f0c069e20512bb1d31f966349add203d84cbb79d88f7add957a0a8370b9a0e04c9f17215531cd48d08c4612bbeeecf3dce68d41724166e06a331e7897e8c7c6a6affb7bf07dae1874bf3bec044d38227bef5c228f4cface9ea37255e15d6b27e154b349b16048b0e7984f17cffa03da07924b190f9b91d6222db1124c1e4e77c2b989fe2a7c338c7316a49c7df0be173d0420e8790bad669f6da96745cf34cd2eb429d18eeb61a8e80a5e03294dcf3a5886bd1865e2a55a72574db8db04a9560f969711aa7a +AD: 2aeb8ee162a7aafe5a72a8d8873ce3bc43a65fd7bbdef1f6ba71b61e5a9c3bd033e7e8eaa55e08ae381362ad0991d65bf22c99a425019c4cd7768622f108f5917a4be22b4ab65ede66c58191e402f8cdad69decf6552dd52b62e8d62268b84122b64145c97115373a26d2d5e59e69b7dca5f96c48106e9fb3f7fc7e0ab11c78a1fafc697fc73603d3f08fdfc0ee885f84572fb04fda718a21744c7e5dbace91b0e141fa82fbd4d1a7dc35edafaba7c5894778c5952ec787bb547a37e509b035c684a8f51ceac5e12ae71b165dfe957c6de15 +CT: c5874137f5e75ef02521b37f0759b5724798aaab8a1e62df81b73175690ca1d32cab6e7a9d7803a8aea420ab273fb46eab9e5f0773b7f5457d7a8c0058ed9675a6e1a7f15805c7fb695d277ba06adc3963606ead0cedb342614cb410f4197f4fad0b5df2187f8d2ebfe85ad3d5f59bbf652364c7e8c3542c5d7f15bc6e6c24eeb1d3232bcddf6588ab1c1953085bd0a1516046b76714d2b97718ce57ad23cd213507f6cda95ee9c5c23036cc7d4133c84a1d36393979f9d1bbc613350252a6de78d905607adf51368175a20106f81aa9ff9d +TAG: eab1c7790a5941270f2ae49895b3113d + +KEY: 6ace8b5fa16054558c9d0e272573a7a1 +NONCE: 358c73828e032f0e0db608fa +IN: 915466e994705239afebb8025aa965626973e41a750bd75f9e8ccc7c1078ec555fa618120b4f4b5e273fb9b262df73d39950fe5cc1c265c06a08e2318efa83c63dfc689de80966f45cab0d2dba603bf116b9ef7242bf4d9cc691a775f78148d2c75059d6049c861da5dc40d5f94848c7247a724db956d050975d613433066ab89bf91936e0fc85c61af5c2c61cd1eb414b9df0dc125a31a3805903a886b427fb78551bc696610833a9e55c7776ec1622abf839d733594864de06999be8d483f8dbc4da99f541c6f7e21d946cce229a104a57e4b823bfea +AD: e54b90d037c375238f4989910d423bc58d32ccc06ddee558dc6a0c2f9a0f13b2332883e2c4ef9cce41d72cd636516b3506f28f914dcc88311fd7c79bff0ad32770e4847362affd98ad468117cf0daa0f5747c86359615ad6087ee18e6c58453be60f3bf30f8c61c1466d107116f88499fb1b5df9a01eb762317676d5413b839c66e5c1b74121f6f2f7408825745fafa2b10ba7450f4ce207a9cc682d1e1442f972a86d5d4039c4856ccbc00c43b5b3412f5b3f87c16508ffa527c8080a556944d359f388f787f9cbc033fb3333e72127e94c455b433222 +CT: 37be446820f5635c1b5ca1d8ccc2c5ab5b393243ef5229999a2c084fbb54a330bb338963740ba470973adc86e640fcc167a88bb940e5ad1723a01089b5e804b932138efed6fa0ed99c1ac4e9c607f466c829af04407a4a2e5cba486685f693a7b973921746902ad8a0242e02075cab66204084e6b281d58430f2d62bf55ad56ad279bdab0fc8c3d570fc3371dc3280ef3aea70d686c855d40ff205c04d457adb518d904f5715fc6a9a5f30bf1cc74703b175d70a1470cc810a366cb8927fb937aecc200928db6b73873935c429e2f8d595b418c5b1bf9c +TAG: 01b05fbaa9f2257b3c23ed3cf91bcbd0 + +KEY: c5bf40aa1127073b03c114b10f3f78f2 +NONCE: b4ac4fe9920fbb4e032f6aa6 +IN: 164906110c34354a0d4cb6370e1ccc17a739350cbb11d6570f398d50efe3d9db1a97f00d031a579f56d23da2441295af18a640a4e33c29dfdc848d722786d9b73550bfb76da1676af24a7bdf5fd3301090bf342369a24ba830c7f8883db6ed77a2ced83bb85205ca31f75a16a58fbbbd163a3af5e5021bee2d2cece33c08442e89d3f4d6d2359b94a7ec6cac388208a689b584d5dd1103fcf6af10ea2c7cda4f690ea0e4c7376fe2c3e69365d982da28c5bc18d58fe384c9ad2689f4047f9575e54970961a02419d9f2bac8061ce943f132edae1b9622738593cde52 +AD: 9f05d0391cb128690cd8bd120120f21725a79e5d2d0ef9e8322c04bf775f7215a82ce1ffdcf0f6562c188e84cb520f30842b8dcbdec36436725633325020cfdda7ed1af3323d86b2bc72d1b4a326f02be2231fcf133762c4fa76c8a7d5d3ac31cd19f63411a220eba4fcbdec40b8eb01e4ef33c6620978d09a8d428ce0e74d02c140881f46f6f81c2850edd82dc46f3460b5d5fe0b54f09a3f31548dc520f1dd46ed657995e63297b6834df57525408b944badf56234eb2b9a43b1422a5c6a59bc58be683e47753803f7341cbb0075b5795228b586cc571c1bca70d5 +CT: 5c75ee10a917651c49eab6a1187ed631c7069134e492bdb5e5698f8ccd5503cea5b1902d779c2f6e6c03b0108cee3fba03f2b47803e390930060ee4ac984b1ceb9488b4cce80e329d3427851aa7da2213eca2dc5f79366caf601c49a6b7a8ab068f1a9bb899b81a23c99a9de20466fe01398bc071c724b2942640cb1a00489e0ca7052f7a06398ad42500780f194078e3e77142df5710ae88540761b902084f57d87c2b0ec57bcb7eacee6743d419d8877d61666f93a127d22ccb49b5db0b93e4f4ac0dd9393d6351780dafa412380205a90fc8daad3dfcb1b7ffaff +TAG: 8048088e7e9dadc4ef98777c0f6cb661 + +KEY: b628ee6726a4d7925734ab1db3ec4645 +NONCE: c830b0d1b4113f4c9aae46b2 +IN: cdccda3718f2b0963414d965a3c36bce0a165f8e88aa70ca9eb3de6510d02b0b49c29cda4a7f6d439c18cc8fd80b932d0a4190236a13edc9994b1c4a71dbdb694ea5dea53ef781ed398e453ce372a99c204a138739edf5b606160e38cc8444c8fb6e9cfc3aeecc1760e90d13d01692ca894572a0bcb02e13f61d8604a75bb98e96f5f36d10e70a48bbb4f73771ef97031c7da23550b3a12554c2c436115fe56713dd303d1c3d87bcebf25f61710eecc9f01c555494facac496c68ef44344aae40bbe1199de793096d4630018a725b130a27d38ab2e8c629e61d2d8d37b5974f9b7 +AD: f4d345e55ebd1ef9faf967d76736f7ef38e5eb9d659bf8a89fd3c6c3c674161bb54758f1c14856281a7dff7c9cec16cc138384f644544881d50c7692bf22513223b63274e3cb7509c8a410a389277f86cefc801d026b0049c13d85b26da1dbcc7cb387084a3d4a469788ef85b6da02ed2ba0412ba999c8cd83c9c6716cd66b65760c42d4ef3e324b470c2a5e031846fde97cadc448e87bec15164da006c10d3a846adab2b09c29ecc27ec8a9134d5fcfd2c54f17fb23f1a05dc8da46e737f317db42e927818ed00d36af8dabfef09c8641159fabfcfaed344b03a1dd6f9b883f7e +CT: 4f39b8fbd8ecbc8aaea871db2e67583a5b06cb83ed8035ff639dbc9af92c4e3f9fe57b970f4e998a0262dbf77dc024d5e208d3678ae0d90e6fa5d45e2c7f0cf90676368c8784c851d3818e221abaa87c5e54298229a2f4d3f82505ef7bf45686aaf12e8322210a727cfd57c74a5f23bb5d8222115b28503eae7a5c600ebc4765011161736a346b535e1bfcded85c198c6ce6fccfcff0fdb0c2fc480bc6e71fd5de77355932d82f8eae245091bcf5abfa0d62123302e5805ab1f5006a976bc1468e3bed0452c5844029d7d4ea6cbd4a907e905dfc796c01bbeb69c54807354a5bd8 +TAG: 2b55edb998ac9971e53ebc8973c4e8fc + +KEY: 095b26bf096971842fae34af6833c77c +NONCE: d59d30bd5384b86b19b33c13 +IN: 3be9eeac265ec4eb947dd32583ac2e595505b363d660f8b8c2ef631390bb152f016ba7c75bf7c2e5e23c980d6967772ca4535bcbf4871ac1bf70b53826a34174e5a2e6118d7ff86d4836736c9a1f9de44c80b236c5530bb5f80e5fbce9814f3b0843a088afd029f4cd2e6190dd51fa804f8216448e7acc785ddc5478287b101bab80256977494fae87d0c13054fa4470c3827b2e8172224944c8c4f78b0a33dd78ee2bff16fabff15e5909f62c49beb455dd655ee1188b8eff35bfba72f2ec5e4ebad63d7db8b6338660f9b818c6832954241860925ea9b7eb07479dd6de27489d64b1a9191b +AD: 2ff9a8d12980e63a378d6d635d319c26e8f747435aa5d797c6e21aa69fe21f653f56da7db7d67cbf54451f336f683aa9cf373ab40c16738c44efd3e664ecc6eec40d6af82df2b3e58d7abcf26b1d9ebbe6263176ce4ef8087d14b0d5ae1c16917141d2ebdc76a0834e8d83c4ef76add82e957ae376b210ce2d94d2684a045a109454799f3cb453279d89c60ba9d038a1dcb99540fac078d7216ee94f96f5cce939eca9b5f9715b1cf3c9f1e6be982897c2f25225919db3e31595713a4e281e9919bc2c5a88c46835ce05411d0757eb738ac9e45ab3f1a42ffcd6dbd09f17f656f40f1cc2c050 +CT: 4723fb7339048f811434eaaf1db24759fc232466f5f53926b84e740b67f457c8c76f902f4d70ebfd97696380de95e8e40e62434ab1089e3a5308cb066fd4cc7e862a391c2f727a63a01bfd9fdb8ceae55067fd9d6f55312f73bc2c38e4b12b3aa96edd156dd758e9175e67a64a17aedd27c9c70945a065216773d756f533b035f2ab53335a159d9ed3f97b2b7a57aef676fad95c46e3b82eb800197c03812ca4e580916c5f7cdbd4aa1308ab16096a8af5290a0a2330902966a58dcf2e72eea7ce799a8f05c986c6457b05e3eec2adfdd4ed38926a3dc07ef208c91a619848917b96a082ac27 +TAG: 3ff349a628f7fa8d3f970aff8a6302f0 + +KEY: e27171ed1baad563d3d299abc0968b75 +NONCE: 5931a4414d5a90e93d2ac47b +IN: 1d209b32a772e87c5bc593fe943d3d7a1497f390ecdccfefac50ce14595b98b682111f82957278241f291e655b3af108a9cc1523721652b6d446f34cdba2e61464a3217b29344e18ce8f47f10da88c2845a009b7491bbd1e1f36ec49997a0fb09764ee25355de29e56eae7af42a8c96aa137c02268078b7f145fb1249bdd74f2d4e4685de75be4dd7fcf29482eb26b5dfa5028accbd23c3c654bc202c1c0ae7a597ef15f4d14f7b8a14fd45698470ac6355e04fe4a14e3b2907bcade18e4152c68631f313cbef48341008482f434c017bf8e1dbd048f0d6d207446e697fea68202be7283188d1227f21ae4 +AD: af2f6abc40ca82d92901de02113cb8f7638f0a510f6a03bf056a75b02beb10157c97632320fe14fdf0610235e3a06172b6b6e80d2fe18263b11e9a5e3a07758c55131ffca0a6c9b121c37a0c85658125d5bc2edc8e4e247a636d7793a1cde364ac22bf754844607daec0a6b939d05fff5a8c44ad030181aad2361ff61f20a224f2bbf2083b2fc2a5b92f5a66bf2f9b4c49b39dcc23cd3ba66b5e7c19c5b7b74a766c3da0c2b02ac80ac22c006e8eaddf48ce6f6887f69fff1fd0aaba0a0f70ef84b54280830a62d8b0dba55ddaa5b0385c586dee60d1a05a28863a081cb9b41edbf3ee9ebff98cff983917 +CT: 673ae48b6080a3dbd08034312c36201d18508f4e1ee178ae2632a9a5ce0938687ac7e6cb238cff852ecfc736bb8b3c04b42752fe65cbf6ff897e207582e85533f7c238b0be14bb1deb4cdaff524b013661e4f2c96807bcd928e15e4e159390e1eeed036ce776b579d9f3fadcad81adfcbb99986babc9a8465def3de8de0cae19bdbf6488c12534a9b6b7d6fdaeb1d4c3be36b4adf7444a0b9fc69c69a46f7bdeced1214743f3357803d2eae24dc50933a733defc653dec56f0e0bfb8928de76699d4f7029fce9175b3b7cfb6c7ab1018f6f3eeb2b9401115c8cd382b06e4b9b43a097f42bebcc1493a49d4 +TAG: 285c1a0028fed3ab2a4d68946399d700 + +KEY: cfea8c059d7b866051aa54b8977befe3 +NONCE: e54e684ef16a2fa8e25786d9 +IN: 5a20333c4dd9b7378bfb773b7d64ab80379d16c0a56eb1f48f53c19d0fc4519d0b5f478e37f16d6e5085af31dc63488f9f2cbde3e49ba954b674b0a4e20df811098f7b8e716efaee6a4109f16afe128ddb0e54034d66bd00d13a6c69c9ef2e5a065825701f5e85634e118c69ff0fd71bfccc25030fe94e778e7f474136cd3722eb5bfd88bc99fb45dbc3060a24ac2bdadc5c82d883c5c63ccc0f7aaf5384f4c7fb07310b66a7c767d025c1a02dc9aa3d7aa921a72084906ae6039f837454493aac3e3549ad3722a735dfce4211819a2d7ec279221d43360edd9a4cb930815c8565c22b94b4849a979d5e2a57b2da8ecb +AD: 376d8e02071a93c892293902e369b8c7c44a4c9541b5050347b016243935408d0c9557b0f66c6cd493c1b8da68c8635f4c868e685674aed42f196ee9b6e56ee44510eb9b9e89108d878be917454dca0c62d207fa462a563a267270d6b1602d6795717475bc6fb5c87b747589328e39b1d4db3cb19f0fbe9791aa4232e33abd9e14b5fa3abe4705ee988c657677fa063aa349f1a05de045f3ee66da03af18b6b8b83e29b203e12bb02a4cbaf79eab3cfeb83a5a997daaf8f36fa9e12faee86c9cb351ff361351d98ee3a10af999799955a02fc46ddf56c23070319b3fe0cb42d07d811ae976f242670e618eed113b4342 +CT: 06ccc7336773919c2b1bd832e7c48ae4a569db96545363ae0b28061fede28a25ab6cc0382aae3e6b31efaa4c225073640d0148878524a7f381f53b4d21a43e39afd4c12cfdcda442d5023a8d2a8ad49f4a002ecc8354c86520524017e561fe891b6962682d168a860210e0def1cb4be1bfc6590121c1b1988254757fc5a37ef916827a5fc258ae772773a6902b084817f3641c21d3d1d1e8818b9851dd05aa49ea74e16778593f6f486957345462732ab92b1e4b06c32b5ad3270c5ef3d80b4e4bd08451e92c26acebcac1a4592e08ea434a1fbc6dfedc677151ae9471661913db19723184d9ef4bb49342606f784d98 +TAG: e7be877dad60c889d397726bf1b6ea89 + +KEY: 40d35704108a944f1e7582503018cc85 +NONCE: 26048431289e7e100481e2bb +IN: 515f9bd4935dc10e77dadd81f5a4e0b53eb858ded393979ed75330b80adb36f6b81288dcbc581e8d93b0e4705c07be3e200422397ca3648c9676952e60ea26d12198add3e33cdc589ee5a800a750d77978976344dd5dc710e56dbad462fab7fbd08c057a9f8765c4caa9418e6380038d288e09a90befeffb1e8d60e79925dcb3772cbb3258b15544f9c9554181df3483784b89b73bb6f9ca55f6d644c02fbd7e31bfbff45cc40132d2bbd08db6a27f5a302e1dce2f0afe4ef5bd4ca844c7900ba18faa1896a36896a1c80307cb37162174205665613b39cabd0a5b2dd1d5f8b6fee948006f0b2e31488c0c613c1d178b7800dddcfc +AD: 9c86692c874fa785e0d9384061bfce8d8332871ecc195621ed478706c46057bb4fff80515ed65b5fbbca3d463a62e227c228a340143bf012233b1c05a50fdb4ed04b840d983f47e00e001844a0d2ce14f6dcea58069c9b0bd8824537d2420147be7caf4a88dc9912853a7fde6d2a5cc21f85eeabca7902b94eb79d5fa143d02585acd57b93e4eb6bcdbe289a51c6631f7aea7bd9dc0f6cc2ee8426b37220216f834033fde15e3543422612fb3d972b8eacaece9614a4b759d93dcdeed026cc90ea058d7dc985c10859d4ef14ac5cb14849d4ae404badbcd98c28663eaf7274aade4bb7527c4f960875ca703ee6732c9a3720b629f2 +CT: 89a21a1d502ba947ac1921efd3c998bfdb437c2da0802e5eefff66de3af00bde934fb9109e961f179771c52de783680683f4bb752f877897882103146d030bea5bc3c03f923b477443e640450244cdf66d7d346954f6e862a3a577820d49151a82f4205340ccf2e11e4575b53f7ffeef09ec640df65a0b8c04b37f6dad7f940cf2d7446a6fc5bc2dc31854c27567b2badf6f8e94294ed5d899a458a080f38d6e72df59f13f5c8f736264fa2b302d5375d6e3f8c3abe4811f4f85cb6e302e2c12a892a1e7a78a5a33e4b555c02917330ea7a45f20cb59fa991f183d1e2a5bb1761005b73fb728124fa2082f41cdbc88bb06389eb165 +TAG: 5476c08e9561442745fd2f222d08b535 + +KEY: 2c6796d0773d12455829a3242ac7d480 +NONCE: b43c0e7842006f6a7953d598 +IN: e0f7ac13e8cdf4da6c17f1221df18b98267277e79c362ec2793dbb842bb9662b5e2fa34e43cea12f71b4eb53d9c862f176efc5d91f06b5c532d9c30206eb4355ad442127d325ae2c30ec436889e3d7a56b683ee09c7d79768d6876ebeb67b5a2cc13df02ab93646386106e0473149ed77ad0ec91dd282712d0aa26f30bfc44f93cad39504356e3472c5bfcbbf9557cd85b53e33e1a88d2f08686955a3d876e4eacfe783e5f6089b3106295899d4a73fbbdc1bd22e1408a2b93a9d89c9489cfe7a9a7cda7c92b06560a189f5ed04d1f02489685c602f8741baeef3fddf610b1a25ed26d88daf9a05aa0a476c8000dbbf798de92b0ab8779add7b7 +AD: 1048769719a44958dbafe1a59a159ddf2427c5dd8746a8454180dbf59f48ff6467d760f8e06aae8d2d2a79efefaef2dd2abf33ba1929073685d0320a583a56e8748288b50c7eac551aa859b274629f3d3cdca5fd7b2a08f0bc830e929584bcba85f80e2eb12bf83de607e4749eaf7631c3545f06ac236d55769c8a08427abce0174c52718c2c08b02afc7e418bd7aa7715de95a930eaf92f54c7dfa2f3ff3691187a21c6bb9b238d2fe2dac7266de30c94c7ee96fa60caf5ec0f5aae5cef28264933cbbc295cade787321f4c12f63ddd85185997a63fec48fc5ddb83be3b47a94e15dda3f315e7495098bc7a0b7d26802e12fdfc6a94bc6c5a76 +CT: 794ba0a7df144e66e6e7fc83ee290431818d149673d1821e1df496565aa7996f9e581fcfe9499c01d8716fd3f6d67acd6641285b70f8457108063933126c95b665e551925722af60aed5343e429e645574a65cb6fd767b204ca8fa91979c6fe49377fe4b43fb9994e619e1dd962fa49a8ae5ae0b8eb630f112c43a4e9c28ad91fee9b5bec0b27c5472e30c2699e984dcd9f984a3eb7a7b7209a165b2f4a74bca555dceb81e3495a3d39115d32609f372d8dfce820aded274ac567112d295de5b261b10c01f4939ac532d4a0591f87742d9502d7a2201178b4cb4c069b1873c44b73a901e299d4a41e57dabdefa39907dc559b44e99f2b950e09c +TAG: ae5afc2bc4096e308cffe8063277ef88 + +KEY: 092e4a78c47bcd0b169aa35343c885f6 +NONCE: adb73023c873661f02bf4ea6 +IN: 0751fac5f54602181fac252cd2fc408ea3763fe229b80149bfb4b0044f541801843c8a20ffa1ec931830bdbde31efa998e0875c09eadaba6906c870549dcc650b865665c56b5cf29b75da63de088fe4d79cce59499518a04a17dce18879e3e33ed11ad808d470b2811da4617039758109f56fe75eeee696ff51c18d5ac04fe895518fe59435ed1f073b56079dec1701999ce0e5ab45829cbb85cb1f94dc67c9ad28815728f6de85fb7ae12203eff28420393c1ae5cf644bfb5633156e9189beb02294d7199e54ca0d2012bee2dcd6322eb90f41b3c6086cf0ac6b3888b21131f3e57643f2ab60141aeb17d9d07daa213658b52503482fabc4a0ba17bbe3a1a +AD: 60fbcd82efaa99e17f3cb16a4d2a1e04659d13d84a83135a5e332366ba5e6716bb3674d27e6b2df4269180a0df25841e2235eed7d8eaba571b34178ac1a1041623138641f500a7d4ceb28efdc0ab45274cf26c0dd16174c77dcdbb79a7980e04d48b35efd3656e501e352b605bdd1b57cb7f9ceca5ca14a3953b2dc77d18fe1c4e1b859d2b02feffd3da7e259fbbf27721d330049f0d1c2729ed2f8048abfdc0e7b3609d2e6b4f5b42ece472f0fc330247880fd04768b678fbe20ba9581f3db18bf3668fa0c80751d78286e1927aa6e27ecce63fe883ee88e7a05f8ca2a387b86246f7d1a4791881b14f619a340163da62f4130b2a2c0bf39f463ef0af4120 +CT: eb0fffeb17e3309d1104c9a9c211bfbd585f9516f775793c365d36352e93af1b4db15430b454d1e7aa913f2af994191c365d76a4d49eda531fa7ce9c49b98bad4d591c868fb066a2e00a6bf4b1bf529002d403313c5df306ae34b8c62e939569bb5401eb7ba87080ba505e5c40a3856d2e177d247a5d8c727b32a13014a00a57e9f01cdeacb4d1abd16f1548256d661c45da12c2fe3ab561375875c7b6e273bbff5659749631fe26cef86e02742d0cc3f63a76ae5ece59b6556ab27da9de1a20c627da8bef3c596ebd7b246505006d1a381c2a24dda70e52b126b919471acfce274b89e07d125bc69bd94f2c65bddb82441897973566014fef625bca7e342f +TAG: 8f2dbbcc01538ccc45436e7176c2df47 + +KEY: ab1405116f454a3b1f106fd491cdfc8e +NONCE: a9e9a06e4bb83c215fc59a00 +IN: f64f0ed5ca25e118f2a2dbf069a9dc0169ab0079d91c6552d4a7e8d0314c910ce0614e1f6157b0f758ed6d3fb3fc3e2eaaa9718ef30e8d0c136c8bd6dcff97c0f5ff8a5d3808d8c23f2a9ccc35fb9427afd10dc1c298e95b335044b8d33e414ecc17d7b34901608284bc175418910116410a40b29dbb379eacf4ead521db3ab2a3d9956081af6d7438714c0631147b7d1e9ee4789751d4260b57630bb573739a3fd0b19a7ee8c301d7f1b09f86e60e31d5f2a86c7a65b244d5e4d591df3df3caab80887ea5f1dbb569516672eee351db5d5ee4d662a3d3c0e48cca108966ac6dfa6e4f9b88e5e577752826d2da05f2677dac7c31774eb64b1b0fc938580a78e4a296889c +AD: 3726f25fea1d10c2712d157e1a1bfa75d6f9e5bda448944ea2b7b85c7d4ff4ac00f68988f2a290cff3d5dfd6af33770a021b03fadd5741bffb7532924f3f2841a7f7658c49c6b915b1dc41ee4bb9ee89386c9911974979f43e71297bcb34ad6ed085177ea91300c9b42524503bbbbfcdcaea03e3f2c939d6b1dfc9c6b6e53e221568d2557bc3055752f4fd487b903a2a0bb7697a19a763fb7c615c7edd099f72e87849f57722cb0987651bfc476a0acfe13d02d6b01f761784d247301bf514a14a990cd4b59664f826649e0f389787641c1e5b87388cff42fec144d6ff3f382b85062bc21368c93019bacb56b643808a848c60bb3d804aa64e2b8fa1c128d6914663d9d3 +CT: bc1c14f1df6ca46e6b4daafb016daa235718fcccfc1ac698a061885c33479c0a7fd44e46e805869383232168940b1a9379bc652c565059ba81b4ec2ab435eb9b91de5bc03cb0a7dc11805690ed9abbadafeab2add15f9fd69b5ff4bf4ab5cdb4a6fd3164ceb7820530641d8460b83929b13860bd2e64b984407dbfd2de51e865d88c63554ea1f04305ab72bfc991fa5573bd6b41c4f8c848fff4b0c5d2398a57b4de4678ca4dfcb16a7612773a24088893444a8ea3d0916e4b460b33657f41d2b04d0c28653ed068a3653975402c31088cd74722d3bc09c50679d0ec94c1e84844886b1a56c4fc3b14614634f08c5b0868d276e9f8f992f94b2c55be5f2e408a498d27c7 +TAG: ee43dba528a9ce84a53ed8fc1fbcd871 + +KEY: 7990cd12d13fbb929fa541bdb8e3107e +NONCE: ff7b2818b62e856952aa2cac +IN: 5ba2afc1da8c18d8be3936a2e515bf9eabb93e44905a86773a38de7f959c49ca56d7f1fb43213cf7fe394b49733b031334729ce6c7ef17d843790fde814672ca982807b76475350210871ddf8309f59fb280a7d41726ba7f00ed2fd96b4a17aeb7d157130cb7e49c8a454cd08622824d20f86b4ba062bb3b3f9d4a9c1402a9d80f3324e4127ee57ad94f87d6ccfda76145363fa70df95341d483dfcc304757da7541a0f148036b2e2dc7f93697d8d275456107a016b425542a89ee33ec02289f5260257176369d990c8c89df73892d7e67227086c0c2c258e5fbfff8bf9129a230c229356fb0935738d2d6fb82992c3465ca5a9472ec06c7b5a29240b611837225c61a0e14ca2dd30f +AD: 865a9b2706eea62f3fd3164805cd8fe4740d1ba7be809cad9fb39cac26f7c57d4c449f4eac03d87f87dcf219c562b9ee07ab3ce22abd46237eef8221049fe499c9189f789948af92bc434b24aa44fff600c2d698593bdfcaea878f8780adbe8dad2cf453d253e8668631a6eb831be01db9c7f1b7b8bfedfae83bcdfef3501cf2b2ea48bcb19f40a70733f3e4c3dd90e17912d5797fa46ec852edcd49b0780bf6287679aaad13a926f750ad7d3ca1ccab577b74fc0ce4cb22e5c619d2d668292c9db4a98c5acc4c49561a77275c06f5c3fd514ed8555db3e2f50dde5c23e84a38129e7a91cec8d168bc828d09239a5c6bbb180bf69950540d8876f9fac5d1a258543a771610991b92ec +CT: 1901c8f9b5a99c46c9cbdf8ace9db03f36ac17183295544d8170fdc3a16c7194a2fda400f8f0b251a3eccf639f539cc356ed3fd09383954a8119b536290865c30a629d44e467acff5fc323d2be97f29fb9b4ef7cf2c18a63dabfefd7f75e696c574372f4a35249897a3387a2b10c1a50ae23ea74560b498c9d06bede78f4c8c9d879667c8c8e137a0a254f3f881ce8d183588546e066314bf1989d1acadbae61f7836fa633de9fd0fcc5b3f72aa03ac432be8f7a14c8e86b45bee416acfdace44b783137e3135a801342061781007ab939a52c68d686f5e3b401240bb10e764211a059fb0aa00e2f635ef214322918fffd0326ae38ee939b4045c6039df7e7def36fdad7f5b65c20dd +TAG: 3e003897b4d9411cbd449cd8dca5b58b + +KEY: 64f0a8065987a4713e35dede10afb708 +NONCE: d6ee984b82f1097331400f38 +IN: 29327f95b41119679b80c3b51fb5240490689880ebb5ff7b59a62ae5e08f7cf0993c09b13fd845ffb32a99ce18c22bb8825c137c3aa622cf3a8390042c6a1a159aa1dcb6b6b21f4e07fada584dd21620b2fe0aef64dc609aac925d8b8d26915fc101031b68a4bc89898bb92146a0a580103da265cad1946791c5735b95d85d3f0f1f39a88f47b9c52e61307627c084d68d14bd14e3572825e190bc7146080bca423099f643d53ee3989386b87fe3dd9c383f6a58fc0437fdb2087b5211df2069bfd981d8ca785384cab31545ecfc35345f38837883dbde917155e631a46ed1444ea0ea8a5441bebd54e5f6ff914fcdd66d62efd223f34e16a880370a529b2ce6ade88e907102021dc87aba9900b6 +AD: c8116196a12363785d4d6fc593b23226a5fe83b00a77ba24c69644d2e52291dc59d2af3c6ae102707439f22c33251a01c41867f54ecc552396a5aa98ffc687e3a88d8d0dcf826645bc78ff9c1a3052481933c3e8ba8e30bc249e6d095699ebdc51684696a15dcc9e28d09cac757e51336f79a0cd5ce8d070579e12956a740666d28ead49c47bae10db20fff8dfe6fb0260a87cc6f5a879cd0b2f949dbff046d90cf42c7ab51337e8908302935e50755a4503107c84fc94f7db3d3f0e8eac9c0def7435676701c9acd7f4c2349c3b7324622dfc4d6ddd8265a810c000158260aa6a7e3af973f8b178959de409792652e9c4ed1d50fce2e5e6bcf205c6889ed717db7f4b14500aa8641b8514150cab +CT: 3e04445e0ba21e8788f6f192b710b466d5d3433463f0308a3c0fbf7f1666fe01853b9d340f496bb0c2212ae3e3d34b0fa1adaf33f039201d1962f2b51031c2a4dd9aedc08f7c895682d1352e9a21225d81c98ac7fd4b4de6efe3dbe437d255e4464a1258d4497e2a1d4ef6c319869b78fdbcf4632743825112fc21acc0a1431d8cf8eb8865e695c0f3668ff5acd8e850373331ed7ae3bbe515b42c1d0ca0b9caa4df0048425fcd08850f23a86b4adc859291b5c49ed54e41778c7ee2a11da9598396aa889dda9513afb9fa0b66c0affa555bf76849d754702163004fe3e77ae5a7c46f3696bbd52cb8680583aa5cac22608c6d45b96770dbbfca14312fba61b3fd0d7041ded80d8dfbdc3f901b10 +TAG: f42a0e4e6e6a1e0654aca2ab7877350d + +KEY: 2c351f0b77cf0920873fb57c910cea15 +NONCE: 4f844d27dd26df3015608119 +IN: 227ae9330bfd5a662af4137ca7fa164f383a63e5bc33eba94726a0e7a27f666887fe484680899ad8aaf6fc5426600760f5e6ba53b0484615d0089d9b1e75f5952ce0665d16a045b272c3c50194ab7b3831b313dbd800168a24e576cab5dca4319660fc6add76bb400376fa29cbcaa25adf3cac81f3e66a6baeb0d94ed92aa37271d2cbd8219c0647f0af6a4ba8a8e169c10cf6354122054a547ba046e67cf1fb424271d3d3eee5b51e94019d450de6c1f770395316421b61c5ee9ff00c910103e58d423946c68369730a974a392c21be3fc8223cd816e7432200390fd7cc3f5160795422c9daffed23df42a7f8259e295d43fe57f75f674886c6405bc6954d17c2a36348761ba09694964646cb86c0d8c64c00 +AD: 9d7d5e5f63267154bab863a7b53e0ba159a6d8a57a8c49e084b513b463a1e812e94611116dce9c1ceab2b7e18b4d69f7dfd225d2bdf5b7750d0d9dc131f22987bc812da5b0a8ecbe9d0ca2210cf6ed8a791d95c3f72898497226f69c8971c2da342500b75367842d14983384b5985041eda7f1cd73e2b5c71bbbec6537390313583bbd53d2d563848fc93d81579d8db321d1bec973f7c4e8f34b6cab8bd7b5789a7b40f599f2f8c43f6d7f8fdf940577ca8b5159e699d449ffb00acee0940937d491a71a81ee9da0949f8fa1d780f3957908819221941f0c5d011bfb2560acf2d7386f973358d68487954e26ea9ad3068c65b797307831e03aef7d1f1bba9ddbba2f251329e85172ed8efb1a689f8026b5068c +CT: 4ef2a097a8e507143b6354ecd94d072c0068c68698fd04f2211a771bec45d616d8eb7eaf90140850c135cf468dab9e9f3dbf059b56efcf616b32992df407bdb735a8b5ac2c361973abf47029bcde46dd5b13728add772264f2faf60f3de10494b0606618c383c8929377f2390c4a104141a11711ba7e3a3c83396761d7d62a997e8782822f51ffd0eaa0e6c9e02ae4effc0686af29f2805039c1cabc8b826d1ceb75c4274e95f854a9f5be709ddf1002481272586aa021acc2fcfe3e6cb0b2a47d124bd8b83585b43bc38599a497d0de3979c30c81536ab06a1649a3cf5dc2c2a6e52bcbb05a76e35139c668dc8a3c038ffd1fde8c1b4a31de48341b5fd586c674e35bef3b104e4b84063889907c268226dc73 +TAG: 12aa2a46a9014800b3243d1020290d1b + +KEY: d94582550b2e0d42255f13a8753f8e82 +NONCE: 82f7abb31dfc28491697b347 +IN: 53ba297d691fc3abd93ea8b6f3d629584370ac045934b1b738a73c09a8236bf5f99f357b1cbb120414c68ee64d304b7751c88c563d5d16fa094602c0ad3c803a8f116f3a5071c049a4b88f19ba2d500a171565c719fa64e691bd4a9c4588077b0c2b91733a30a214e474d868ac6b301898dc85346523bdd4f6c9807ef69941a5369b4b7ff7fdfd252729d3829a7bde65427639de0b2b154b4830f57ac13894bbe705f02362f8b75367ec7962c53bd6aebbf15d72b25c08570392592b6a83d4f44d2037da8cbfea2456696cc39a3272e46a5b4fb837bc6e4bcd9606afa58d3b260e9f6f58bb5d0f07438f378b6a36c1931e9eaf923c2a3679a789e7ef5865c7e799ff4633f1b2acfb79a5a0fe9cdda9cf347b9664568def93 +AD: 2bfb6a6726c6564b31cca749bec29a8c9fd7bfa22f26af0a80db5e6b13a3b10367be6ad87325abc59252453422535466347059b7d57fd2b1eda1d6d37dcfa9da7df34746e1bbc98baeb4bae17281a537fff85c0785f9f27617e77333f11be28f9aa3704651e4ddd72502c79cb2a810c4686147cedf056b5f035566eb34d117c83ae7815e7e1e83163907020cf0736ff1862371e87269e5c8c1926e0bafbc10610a6ba6cfc273c9d9bec0922726dea04acf72b3f88a5fffc57e0af6dddd0396b4937d2e7d52feaf60d29dddc5b4cc139eb855acbb794b99d74b8a93e3731f9092b92b9bd50c846eecb6eaed2e51290cd1f98dccf3fe746c5293e0b970dde72835c44b3a445dc1f2bd67fff6b1a7e378611eaa42889fb92de1 +CT: 1afa2fec98728ce39fba26bcc769e9766993c8276f88613db574773c84c91fce6ee7dc6ba4281b8d2dfe13820723526f0d6f20cc21f305b792e9a2bb1622c742fbc05ca1f0121cb9f6e1ad6c3ba80891e2043adaac4f1bdf29260a44a182cb165f58f480be5f16b51fddfd0d264bc4a18bec589d24817f586fc8bad15df7cb4d48d788fe7fbe69f821b5558b0a664ee12ba8ddc6bbd325f9b83a024245b4e68b310f2282f4cc6005209f7b7aa6ccc025d435441e3bb990e81bcd4c8218b8360163ab266be4a1f5603059db2bb67e541e1edbe8e7762ac522a81f495f5ff8bf99948050e61c86e83134f4e1212f879c86f7fccff472fd9753e27a0601f914655a5f803061cc986431445021c907b3ae0f060fac13f3723867 +TAG: 5ef1ed1e2bf562893b094d58516c11a9 + +KEY: 31d93fd51c2d6450cf35d9edd71413f4 +NONCE: 28f6f0c288c9f92e80252e1e +IN: e78eba6c58f93cc2374932fc21e54f695f2daeda3bd1e0121a77d178e3bf5c0e824a99042e8f2522df829d014e4d35a756780e8c07f53ca8fb78db6fb76754ad461665051c4572b2514804d0a9cbae1a1a013b796565eee13a7832ab8834b8406b1185332552d38754dde2344ff4f6e4823390964ba2dc43de136f2235b1d919e0f4ad60813d30f0ac1dad35abe3bee9479337c7b430841d2c722f12aeaf931cedd8a82053f697fff8d07f0af6013da7da58a5dfcf45561943e7ccdfd8d11fbe96a68a5a27982e47346500c0284caf8e6b63c6621e80503a7365d6693dc9a249093dc45221cfd88562e25910034c2c123e44e3b09d8a8a15547285d2596b98c7a0ee9d10b2cdb032d08a6caee1212420b6854181a583c15e046aa202dd +AD: a4fdd42aad5475ffc1b122170024486406033c8640233cd9b23c286fdd40c5b69eee39cfbf965f7a10c73663f9804e6821c4f62980f8362a580bab446325b009a004b60b1dbd12566b55b42e58d8037d86c1050cd6ecaaac2fb0ef616a15bc5bcd8252fd459165795c500bbb2fb1476e5cfef9549db733be65bde391c810d099e3745a2cc7a94debe1f4ff6653b338123ef7d2f9a602bc9a4bbe757a63f932a802014f2f06c6688faf14332a355b1025f33687124399f55b6a5adb4864727ec6c5334c41d78d1463400925f6c29c0f611f35c9640045a740dad5b4f0dcb632e7f9a3478b526aa9f97cd9f8d3ad094b7922890e7b6d9c67fcc4f747d04ddcd115fba0a8f0433c6fb1bf6011a9cd153f866c76b26d427a25aebc60d10540 +CT: 8d668fb50efda82552aeb5d075ff3977c37929d73f6639289e7c6da8c89c664df80b2387e788d12398d62d3c0ed2f9f918010d41021c464d54f016c4e10e85e29ba3a45793df2ebd6cdf30045363434387bb0d20439f4986e6eb7ae9fd85fe776f7b8035025624c2413ca8491cc6e79fe901b9c40ff3a0e37a7c7e88b56de4fee65861865162821e046846d253982e4ecd17bd26214b0923a4297d4ed9423395d856940829ca5ee74488c3b4d8aa3c5ceade17d8a3f2e45d3ba91360ac1c76d6a29f8243bf49c1d75aa41ba239fa6f3b123e198ba799e3b70c674607c5371894800954eda0264b3b82606433f71371dabc5f1fb3d703232533662920a241f613c38d16b0bad24f4aa3b336af89cdcd2f371e1bed7aaa47c56d17100a01 +TAG: 594ee5c93636cfb5fde940e3d561440a + +KEY: b06d694a83b14768ae26a8f00fb78ecf +NONCE: af11369ee342454cddb8db62 +IN: c01130afd7d3f4276dcfc1ffaf4bb636a85d18e0778df6c6791b6edb92a617894b84cffef6556c834a4800b336dc295e80b699b28cf478a01c54052ab0d0d4208e1865edd6906e3a263862c05f033668d7eb5b42baf36c702d102a6a5c723974e63bec848c89d16584f0d1ec429c87686b1ccffd7626e0a83f9c471cb615541ccb02cb58d10e63ffef171f1affca492ace4d39fbf33bb5126c575963e6b6ef9fd2ee4d6efcae5afe422bbfd9c3dc22b6b47cab8dc04127ff93b016e0f92f5d8518d5bd3bc6edd45e0397440f1a4a0c7c9c2773c0a0cd3b890effb010dbcc00237dbed1177b86bf60913309bfda9376b4192da59a360afc5bcfaf8be16ea8313de97b417aaddceadc63a1c3a355693616413ed4101ad68f6e6aaa99c839dd2a9ff536 +AD: 18e3195358bae4ccf43ff8daa34902fe48f99fc1371d34060aaa442a43016a1d756f795fa5c9c4a828525554571e18c27134f46094790dd1e68471ee40c17bfa02f175b2c2f7f2aef20f00e4d71926560b58f015de19c871d808acdd341675d8fc19d1e6d4028e1e8926df500c4685c14729c6a056898cf919bf3ae429fa3ca8746495716d78c9a8f2ecde596f985b1c25ad0e73aa305a86259319176b4c4f3bb231fdaa478a856f46416ddb10a14ed23c96dcb86f5bea3114568a44d8fc6ff4bb47fd0e2538b70d964842910a682e7bc7c7263249832c21b7083a1e8b143828de0f3dea8b404cbd82efb19a11e4d60aeef13abd86621ccbc3d8f220715730eabbe04a6bf0e11a4f78cd2c4369ce2447a76f4fa48ef8d322a8a28a67039c24c4bfbf +CT: 6beeb306c71318cedabe3877ec916ce2074b2c3f1df887cc3a3e8019c10d353854b6b65c947359138d5decc62a42d50921dc8f6cf63a16062af47aa8cd50d0b2dcbc3300ba0d7d069a5e4b4fe03bbf7062c6001e276be116fdd00d15a6399d1b0db71c58f396f8bc7e51c2b1f47430d4ebd6c5d05328b29aa79bcb26927ea5a40c82715aa0e36cc83ca6d250812c1305c02ed4291a25762cd709cb3d808031b5f918ce253f622c1afcb83c43707edc493d18ec6f0dba4353a1cde7184db65654088fa13baf45f7643f0dfedf4058e6095156b791ed30827c556a7721658314356e7a3f3c62cd62fe938b008cda56ceca71442fa0ffeb78b13c5847a3ee9668bcd2a01c753bd797c240378505d1e8f2b8905428b23bf589de9af390f94f21630d1826 +TAG: df5a21a399354b2b3346a9eb6820b81f + +KEY: 06a4c6a8aa189134f5784a525d46ff10 +NONCE: 0f765d3893af99f5c3e6d9e1 +IN: 706b754094869313523493089e591d34868b708cbde9bd8b42cba8175d1fdb6a8769bb9ec156d44bcb8f9cbf2685a0dc18b5a802dcf7a12570bb9042a0aa53dfb19af8c0f13763f388d9626a480d6d435dd90fbdbb4292d9015a5633252aa0583498d6f7ec54460d8589c1d6a6d16a349d10ec6070e1cc52e5fb996f810d333675a7130e4f3db9f4db0e3fd3541d32e0b2efbd40ba70cd59295bc8d08481f0f137832b01bac1778ffd7450376e174067b3ec23d0495cbf936bdc176cabc3f42e2991947a4fa87dd8343c32fa3d7ac0e2d22660a0c128a00e1b51a8742fdb2aff44540e39e588c5920ea16293aaa522513c944d3b77f3a0e90bd9105319c170886202e336893d100b0a25aa609a49a8255f78233561f7b88256386d1c3c002c3ee68f2775585c65 +AD: 18e2ed6d500b176e49f7e1b5074c0b7dbfdefdf00a63d9fa2fea8c5e78a1c4ae00f17b23442933543ac864097629e112a099f3dce6d5beb1e3f3c8e19522c6b8f615cbe23444bc91a802edf8a08995a55125da805ebb073fd89863996ef708f7293069a744ad95db8c17cbcfedc331119e85020df8852d74b8092fd38ad424f3da41b4775beac19536ed801ac1069925b12303d8ad2c52c36ca5b4ec95e96f02ebc5725ee6cdc099e666d9055b789e39ded77a8fdca0fe2d94b8039be55b6a75209cbee4fc7864957402b50427db71bc75a0b1e3d2ed6ea20f12a980c5ee916067d0dde7d686570d075da4df7088fe5dccf0d440064a96998da6f318b603d513104c723f27484780bdad586ee358d821b480f9569e4dbdd1a45ab9056f8d8e5a879789a0d65338 +CT: 5f3627bd53f8da0bbe6f3c9246d6f96fe9abb91cdecf66ddd42f833d98f4d4634c2e1e1ad4088c84c22191bdb9d99ef227320e455dd112c4a9e9cca95724fcc9ae024ed12bf60a802d0b87b99d9bf22590786567c2962171d2b05bec9754c627608e9eba7bccc70540aa4da72e1e04b26d8f968b10230f707501c0091a8ac118f86e87aae1ac00257aee29c3345bd3839154977acd378fc1b2197f5c1fd8e12262f9c2974fb92dc481eeb51aadd44a8851f61b93a84ba57f2870df0423d289bfdcfe634f9ecb7d7c6110a95b49418a2dd6663377690275c205b3efa79a0a77c92567fb429d8ee437312a39df7516dc238f7b9414938223d7ec24d256d3fb3a5954a7c75dbd79486d49ba6bb38a7ccce0f58700260b71319adf98ab8684e34913abe2d9d97193e2 +TAG: e690e89af39ff367f5d40a1b7c7ccd4f + +KEY: 31323334353637383930313233343536 +NONCE: 31323334353637383930313233343536 +IN: 48656c6c6f2c20576f726c64 +AD: +CT: cec189d0e8419b90fb16d555 +TAG: 32893832a8d609224d77c2e56a922282 + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 58e2fccefa7e3061367f1d57a4e7455a + +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78 +AD: "" +TAG: ab6e47d42cec13bdf53a67b21257bddf + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985 +AD: "" +TAG: 4d5c2af327cd64a62cf35abd2ba6fab4 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 5bc94fbc3221a5db94fae95ae7121a47 + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3612d2e79e3b0785561be14aaca2fccb + +KEY: feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 619cc5aefffe0bfa462af43c1699d050 + +# local add-ons, primarily streaming ghash tests + +# 128 bytes AD +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +TAG: 5fea793a2d6f974d37e68e0cb8ff9492 + +# 48 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0 +AD: "" +TAG: 9dd0a376b08e40eb00c35f29f9ea61a4 + +# 80 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291 +AD: "" +TAG: 98885a3a22bd4742fe7b72172193b163 + +# 128 bytes plaintext +KEY: 00000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40 +AD: "" +TAG: cac45f60e31efd3b5a43b98a22ce1aa1 + +# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606 +AD: "" +TAG: 566f8ef683078bfdeeffa869d751a017 + +# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF +KEY: 00000000000000000000000000000000 +NONCE: ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +IN: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +CT: 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c +AD: "" +TAG: 8b307f6b33286d0ab026a9ed3fe1e85f + +# 80 bytes plaintext, submitted by Intel +KEY: 843ffcf5d2b72694d19ed01d01249412 +NONCE: dbcca32ebf9b804617c3aa9e +IN: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f +AD: 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f +CT: 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5 +TAG: 3b629ccfbc1119b7319e1dce2cd6fd6d + diff --git a/tests/aes_192_gcm_tests.txt b/tests/aes_192_gcm_tests.txt new file mode 100644 index 0000000..cacfaae --- /dev/null +++ b/tests/aes_192_gcm_tests.txt @@ -0,0 +1,44 @@ +# Test vectors from NIST: http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +AD: +TAG: cd33b28ac773f74ba00ed1f312572435 +IN: +CT: + +KEY: 000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +AD: +TAG: 2ff58d80033927ab8ef4d4587514f0fb +IN: 00000000000000000000000000000000 +CT: 98e7247c07f0fe411c267e4384b0f600 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c +NONCE: cafebabefacedbaddecaf888 +AD: +TAG: 9924a7c8587336bfb118024db8674a14 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c +NONCE: cafebabefacedbaddecaf888 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 2519498e80f1478f37ba55bd6d27618c +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c +NONCE: cafebabefacedbad +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 65dcc57fcf623a24094fcca40d3533f8 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: dcf566ff291c25bbb8568fc3d376a6d9 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b + diff --git a/tests/aes_256_gcm_tests.txt b/tests/aes_256_gcm_tests.txt new file mode 100644 index 0000000..9a30a23 --- /dev/null +++ b/tests/aes_256_gcm_tests.txt @@ -0,0 +1,467 @@ +# The AES-256-GCM test cases from cipher_tests.txt have been merged into this +# file. + +KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01 +NONCE: 5bf11a0951f0bfc7ea5c9e58 +IN: +AD: +CT: +TAG: d7cba289d6d19a5af45dc13857016bac + +KEY: 73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a +NONCE: a330a184fc245812f4820caa +IN: f0535fe211 +AD: e91428be04 +CT: e9b8a896da +TAG: 9115ed79f26a030c14947b3e454db9e7 + +KEY: 80e2e561886eb2a953cf923aaac1653ed2db0111ee62e09cb20d9e2652bd3476 +NONCE: 5daf201589654da8884c3c68 +IN: 96669d2d3542a4d49c7c +AD: e51e5bce7cbceb660399 +CT: 4521953e7d39497e4563 +TAG: 2083e3c0d84d663066bbe2961b08dcf7 + +KEY: 881cca012ef9d6f1241b88e4364084d8c95470c6022e59b62732a1afcc02e657 +NONCE: 172ec639be736062bba5c32f +IN: 8ed8ef4c09360ef70bb22c716554ef +AD: 98c115f2c3bbe22e3a0c562e8e67ff +CT: 06a761987a7eb0e57a31979043747d +TAG: cf07239b9d40a759e0f4f8ef088f016a + +KEY: a6efd2e2b0056d0f955e008ca88ca59fb21a8f5fc0e9aa6d730fbfc5a28b5f90 +NONCE: f6775dca7cd8674c16fdb4ee +IN: 5dc495d949f4b2c8a709092b120ac8078cdfd104 +AD: 86a597f5e2c398fff963fcfe126eae1bc13f097f +CT: 04416e23586ee364b1cf3fb75405f8ef28fddbde +TAG: e7b9d5ecb2cf30162a28c8f645f62f87 + +KEY: 8d6ed9a6d410989e3bd37874edb5a89f9ab355fa395967dcbbfa216ec9ce3f45 +NONCE: 55debbb289b9439eb47834ab +IN: 52939c7416220822a77435a46687f134cebc70a2f1a4c33d37 +AD: 7790af913d84a04c1b72d4484ea2e09fdaa802d8b1733b8470 +CT: d7bddae8929ed6bbc9ac077e2415d9fbafae4a0432f8f7eb6b +TAG: e6383b16ed9c32521dcaeef3a7b9b67f + +KEY: 525429d45a66b9d860c83860111cc65324ab91ff77938bbc30a654220bb3e526 +NONCE: 31535d82b9b46f5ad75a1629 +IN: 677eca74660499acf2e2fd6c7800fd6da2d0273a31906a691205b5765b85 +AD: 513bc218acee89848e73ab108401bfc4f9c2aa70310a4e543644c37dd2f3 +CT: f1e6032ee3ce224b2e8f17f91055c81a480398e07fd9366ad69d84dca712 +TAG: e39da5658f1d2994a529646d692c55d8 + +KEY: 630b506aa4b15c555cf279dc4a7ee9add213219d2c68163ceaeda903fb892c30 +NONCE: 79eca200a5cdf92b28be5a7a +IN: b12e6f1f8160cd65278c48f68ad53c8c82fd17c2c39bbb109f077c17fdcb8a0b3a5dbf +AD: 46cb18593b3b26ba75e4cb20a252caef31d00be31093d2369e93572a393d650c68313f +CT: 9a9ad1f78b4d411afe450d2e46347a7df98f39daa4fd478b9ab6e6b417878bcd52743a +TAG: 55453a003b021c8a247379cdc4fa6da6 + +KEY: d10bb6641e9ba0a3f1b016317831ad4232f81c2137adac0940ecd7fa36de0563 +NONCE: 99c922d37c95ebeda8e81ae8 +IN: 8b9089df5bb048cebbe709cb61e178ec768515a0031288d95b7cc4dfffeb51b836e126a237ec50cc +AD: f1cbf6c83493b2087d9f88e02121a114f45ed51817e46ffc0b66a783350eae89c6700db3f3be5f4a +CT: 8a838c51a8ef8134481e9951033295ae686624aa4df72f869d140980347a5e69a6d7cb3d7119b303 +TAG: 9152bef766579a3e9a1e36abd7ebb64c + +KEY: ca665229adcc7554f1b1c8f50e7444c6d4059c525f9c0da1406ffb35d50cae97 +NONCE: 8e2df19123ce0ad41df416d4 +IN: 12365eaac86b270e9c61b3ae7702a6f3583ef4accb80a98454c56e34e2ab97d8afa23ddee34e7e3a522497f985 +AD: bf539d8e9e3a02f3e5834970e7efd40cc7cb340a075041428d6a69ed9fa5105e4bc63720be9a7040ce5b4af6e1 +CT: 96027efdcd4433df8e7f6181c05be365cdce550b09d45cfc96fe258eab6d55976a9306a0070c9589ef08cf7a42 +TAG: ec9fb5e79cdf8ad4c8a79c900975159d + +KEY: 5033338bf7526cca0425f4a620424662ebc58364c8d985d130e525fd1f598f3f +NONCE: b40842b30758aa3eef7cda62 +IN: 69a62b8c5f9b81cebee3a9345f4e49ea089b0d9c1cc57b4ef707956d0287de83fcca6d8f5270a9393e00693075028189bda7 +AD: 3efe0ed6fbafa61070388abc59c0d06589309736b02418df5534c8c594d61a2afefbee17af8283d01634b6ca3e8e2aeadff8 +CT: d6184677a21978b6443d99d7de1fd01c6b6334cf01b7e7d58456267453f4de96708b62301172c8c87e970f91c5301e0ff61e +TAG: f8ac7aef208712845d137b8b176c89f1 + +KEY: f33c39140999a2cb69e43129cb5df18fffeb3513ec3560792e9909784daee43b +NONCE: 70608463f1dfabb1fc4451e9 +IN: e2802c4d290468177fdb031a717345753cd7c3028ed07dea428db84e7c50c3eb7b24f7381a167b4ee31bf88dcaf5251fdb90ecbb74ac2f +AD: 10a6f463dc59d4791b3c2b4c93cbe2dec579a154962cb2c4cc77664e8c2b106c574fe115fd43dad94b8b1bf2f74820e28435b4444b2b82 +CT: a27419a46037323c033d7cf2a716777fedc02a5ddd8bfbdbca82ffbdea3037bc1cc80df7c5e502b32276ae88ad6fd0f0cfe72604648812 +TAG: b1ae330d47fd399aaaa687e141e23fc7 + +KEY: 2121056225a7b2316a93c4bfeb970486fa9c586c14ba8b40be5844a31e9449c0 +NONCE: b4b7d1e8fa7d0e2334c92315 +IN: 2038e2c6cdf5282f081292448f8febbb60a1520fa3771cbfef387f48c5915a1438ab709628e8d4c81623ddbc2f6f159c3c9a8922905c4994269898b8 +AD: b07f66508a39c4932b04c16172d6462d78273cd9463e52284bb73e3b8b8e7047bdf10c5ace1f903e5a5eacbf67c9351f82c74bda140df2fe0480c80a +CT: 7b54618ae09b37ee72e51873c82cdd20b6dca37c334af89548f52f34df3a757e632cc0d453fc97270898eb50ce2f2a98c4cbd4cbb22a5b7c7564406b +TAG: de3a9e2aab2439675c4f7f0b61216d5a + +KEY: efb15235bc91771aa32d51472877b0eb364de2f88766908eebc6e6b57a702099 +NONCE: 1a510b42dc20d1d0fb34fb52 +IN: 4eff604dd4bba67f143dab0728b8597e269d4e0ecb4ce80c9850afc645d96da239d9db360605bb4268d74e1fe3431a44242ae862fa2340c076db13315f615b85f0 +AD: e8dad34f727e77444a96cf06425640f1fc80fe3b01dafd1d91476140afe8204286d01b0ebdadc0270a3d218516ff5f08a69a7ba251ac325983caccbe0d9e1de359 +CT: 989fef0145e2fe93b9f99fd90123632d83d9df8f37d8e1f80dac329dbe0c214c2191009e31232538fec63a29665f0fc1c77dc86b2f5f2050b86b3ae48e85d63116 +TAG: 6816304faeb45da4e4772f5c35730f8a + +KEY: 998c22912d5687fc3faac262a902783fcb0c738520b5c4135a8dd2cdbd7b0dfb +NONCE: eeb535c5bd6edfd696655b60 +IN: 1f6ae10d425923c882b7d2f556571acfc10333ec665b07bfad9f8948a3b8c5e5f163a4e99d4726da1a35359c657c848f327b7fd9b5f61987440ab12b9399db24715715a2d1c8 +AD: 9a3c76dbaeb69a6481a89318caeb6358267ef51a1a364a48387bf77526837c9c70afb6f105cd47d2b976dbda7d2b6bfea7b76b135810c53437472f7b80ffc8ce4dc95c7e5045 +CT: 87f4e2c80a4f15f92a8e94f468e70fe7f0e0f83c0a7799a1d465043d25210ac6f0f39a5e9765b4daca637864d1bcc090d2ef33ddfccded2d2dad61dab443b3cfcc683147c490 +TAG: 0744d928a5b5ec95f3087cc2623f0031 + +KEY: e12effa8da2c90a5d35d257c07d1b467991bd5f75fecd7129aea4e26b9e27ff1 +NONCE: 4edd0b4cc349d37eb77f5576 +IN: 21dc87984edca46a629ed95ffb04471397da8806c525a781d9a71818422e344e4af577f38e7cdbc556d4766770a9a3c95bea59ad497fe0127816ec4dcecb6b999486719b0b86cdb2c9d09e +AD: bc158e6570fb0a08d73367dba65b80a8c8e57ba6c7b99493ebdaef0424e18d8ab1f7c88670cf51c4d91b77eb9ce0f89a46ed1316141e4299ec6c3d6e712ec9e92d3db44640402aa4ac00ba +CT: 07ab8c623d683ff83030392e2864edd4b8e3d296d60579a226a8d2aff6bc5af3c4598a18cc1e8d7db4ac8eb56a082af864ac52a324851dd29af51a0945cee4bf303ea111b9b627aabf5ff8 +TAG: 53e69b7be969c39560c016c6bc1aa4e1 + +KEY: 3d9723c9235939df8647529b7e4a57b8536476d5b71b424e2c27ba4d0b82b0e8 +NONCE: 60163d2eb7822af7fad64c04 +IN: b44face0f45e4a8da19aa0c5cbe3aa960ed6b74fe3d3d9201f52523dfe7651756b2ce482e759c87bde4ec670a0e808fb4883e437c7cbcf2f6470352174327824200cb0897edc4def1736f51e229addaa +AD: a4b2b7bf36a70a5246feee52c474058100bc618fb0e3d32e8c1f76153edec47fab3045dcc7eed9ca1886bb2593703c9ffb8883c45386d2f4e3fbb0b7c722d19f2eca94767174d9127450549e8993ae33 +CT: 66fa63ded066ac67bf218af7bc21169a875f4bd695f44fbdff906f0a9b8a067be721fd260571c53a8b51661c8d49fe178dcb28c31deb3fa71b096b387f9fc8f3657d280404c05d2b6443eba7e60b562e +TAG: 59d5450872510c4bfb590d9497524331 + +KEY: 75b0a20935c4a5e2126ac7420d632bfda8d41bc947c2402bed4759b6e617ff92 +NONCE: 0c3edf0dcd1125d7e263b897 +IN: 8edc98e70030e40bea1548f6f56b4561272be0c333f3b7ae53ff3e27c35a91b1aa42d39e6305ec4811e75931e5cae2261d88a6f7d6c5b05bfb48802264e9cac782411f1de579e29d464ba56840b126a3fad07f01c4 +AD: 7e35081ef652424da6304852243ce43ff711da17f7881d5e0433b1ad7535e755a8531b93d67ce99ffe66e59fbb24f6b42655524b39f2c84daa5cdacb5e7916266c05711a118b2128930b95de83ff1a67e53337474a +CT: 858dc74dbec6fdbe4ef15a3596ff7201c8f4fcca765bf5452f678b1493a66ed9852a6fa174a73099acf951a35699f33289ec50625538c01eaa456dc658013a29e4d133b856eb969c1f221f99e11fadc98b0ee08243 +TAG: 3d8f17838c4fc69f04d7e2b76eebbc0b + +KEY: 7a3823191abcebadb7970d1b65c2a8dab8a908151737bd5400b3b6c0d59e3b08 +NONCE: e32eb00e5106097e2ef0e8ba +IN: 220db5400dce604adee4cb698cdc02d2ca61622bbdeebe347b0bfef55cc45319b940f93773a9878725c5f55485d7a26363251b9ce0d3da1f8f6e34ad5329dc9f752ec7dc12b2d259ac89a8059085996a431a56cc2dc2400a26b4 +AD: a83b6dc78931cb7500eddcf77792e810c1edbd5f4e33f85018807a8539a3cace094fb794fa9ea058e82c830d42d5a6b3e22b7785698774aec5c73edd92731c51106a23c569c0c0fef18d13da1562a9a42aa435b243c4fbc9fe42 +CT: 5ce6ec0e1d67ced5a6aa46c909b9b8907b372be03331dd0940ceb6d87e928c14a1a1e8ef9096c9b63ab4cd93242ec7be7e38b80643f9c52e7e90ffa06b8f2d238fa63dcd97af74ae37802d124623b8a272e68ca18b3432b7c017 +TAG: e21c61d604253bc5b5d58283756b9eb3 + +KEY: 53ff6dc0af3e89fc2de7370caa433f539d068609fcfed6400a5b9fda4c83e3aa +NONCE: 91a824c5e023283959858062 +IN: fc23e07b4018460279f8392e86423ecfe465b25b60382f58995ef5fa1f9ca235e4bf87112554aa0e72836831d7b5f39125df11518b8aeb1809d804419beb05ae013482213012e4ce980ddd1c58e11608b775d12b450ecace83e678c69d2c5d +AD: b3a1db2d467780480f166859e0e7aab212738b85e88237c2782496c9c503347de02f3dad6bfc671fda71a04ff1e4661767c11303daa0c36d944346d39e3e29ec63d695cdcd83b2b57181582c5ac692b13e4299ab5e86c59d09c2dc6194ebe9 +CT: 88af588ec33bdac2cc748a01ee3eec97e5bbfdf69de1d66176f42b66383bbffa8b185cdedc25b11a62237d334d68120fccfd68c2f9447b3b8e1f623f33f7f97ad8815d29bf11bc0c65641ba8fca4a087783f4694fb1d574450191825f84402 +TAG: 2c4973323e635a885f78ee106eddf19e + +KEY: ca2b4d335598f26d3d3607e62b9ef853d3543e741350f92f3050894721d3d450 +NONCE: 2431b5cee8c3ecec4caad278 +IN: 75e29e46350d1fa99403b1e5baa414e41a8e714910f313f8e850cf3076508ff650011af766b51283fbd5626166d775fd4b4cb7124d26d77b41eb17bf642bf67a34c1caf0fa9b43eec12103f864e56c5ccdc81b89c1a35e394362688d05dd94eda3d05dd2 +AD: 31c3ce532bc1bae65b5ced69449129b112019cc6078268b853dd17c41832ecae07f9c6b068ef6cba2b55f352904afd6096ff8432081aed408d9340c319fd8e2029c389b6e3a4bdc38853444c3f7be9385ff1ca27e59c43b542e99799bb4ce56b8e26d6c1 +CT: 90c13ec26d01b7b96bdd6816d3ee57df57efeabdb15ba602229ff71d71793fe8081eb1b462e8b2967bc4af96fd6dc72cee3d2b6495c7f04c9068b2ad0b073e11cd5999df541ad705c6315eefa8da49c5dbc258f7ba922908489c1ce672971c3bfb6e8482 +TAG: 3a7741a094be92b838850c32e4b06c6d + +KEY: 49fbbdb5ae21cd955be7f7603cb8563ea0b02b77a9ea14016baa5cffc55d20c9 +NONCE: c0a4463350506d2af9e35d8f +IN: f31003aaf5d8fd6261c01c5bb1e7bf6af248e0be3cf8aac67ccaeb0b7468a40d98be526a8e4f692dd23763563e601915ebcb59ecbf03bf9c665c4c5313c318939a911888fd427d5297b9b2fd91dd33eb7ed38e2f0f6ab74ec263989cdd9915811a022d4a46ed35eef0 +AD: 17e01af2386531ce67d5bc3325d8f83b53a87b38f1c305f99c0798380a7e59d3ecddf33a5ad23a82e33f0fa34eb2438b17e958451439774ab642fafd3794f80a0ee1b9bc165f32df705a6175310670ba54af3a204e446db35170ab02670086c47a475c22d1f14cbe44 +CT: bd661836d1b74244baca62d7d1cb6717e17e2fb0bcbc8d36b3265a983d557c562b0be60708499d0e7e9626825bc049db79a0ef4d2393fef6024d849089455e55693fd4da3d910eac11496492a645e4376855732765e1b3580461a2a2533cebb482736ac928cba175bb +TAG: 4596e3802109c899f27f6cfcbdceac5d + +KEY: 30d0e4f6425e38c92ac34dcaa06a815166f301289ca9cb0ed08156617d87bdf4 +NONCE: 525618ac9e317405c7d44367 +IN: 06f2204ca864dd3f7c9d0290f6fe3d0337eb9442cd5d2b586d1d5c30e58951fc2f4e99831ac7bca4356db4609a0428c482f2580b9e8cf5fd00d86d474fd88ac3b2413f44c1ff66e59e7538c090b2444396f02004ff636aca05ec40439f4e3f470a24916fa4033cb60127223addc1 +AD: 23c1a3e1083904f7226be7242027abb7af9d62f1115340cd4a57611be88303955cbcbeba44eab5488c80aed3e063c70cb7bbdd9ac289c8c8977868c3702be63d0358836838a97b31f6aee148f2b8615ad7c5dc0de7c48db7752e5f1ae8637f8c70335bbecf1313ae1b972ffb9442 +CT: afe3e71953bad46ad28113b7c8f2092fdebaeb81626bf94bd7e9dd59e000e8ba31c1ce7f728fe19dbbb42322e54aab278e3c29beb59b2d085e65cb8e54ea45d6a9fb1f561bac0bb74afe18cc8de51abf962c2fbc974c7ed54ccf2c063ff148b3e6cccdaa65cc89ab19fcd9cd0436 +TAG: e9f5edea1fdfc31cd5da693b50b72094 + +KEY: 661309741227606892db13ab553070b456c5e421cca59087144873ae6d59e590 +NONCE: 9f07692c017e1391a981e70e +IN: 40b5f8081b5dd173203e02e90a6c171fc41f804b2903ea18109edcf77c03dba687b47ca389c55389bd7b0ac59bfaefaf43b5f97065df6a5375c1fbb95d95cad589c2a45cd9e1e7960b1d13622440f7180aa565863b4f9dfe26ed336ff4318653e1a520bdb830e01db78a7e598f251834d0c9bb +AD: e8540d084f24b80414af554f470048b29a5af8adb2f9d55c9759e5ff1595ca74884af67027324587131d90c77ca72b2d15b66564549ce93df7f667d0218a6e874848563a33886c6a0c5a9d00fa435dfabaa9053243b4c8c25779a4dbf79eb4b8530a7c7bf4263ea824713a90cee92dec78c449 +CT: d543f49e6cbe26f1d8a6e058769d5b16e6f8255a28b4d73ba2cbdf664bbc5ded73f9dea12a11b86b6a6acd578f685afabc232dbe9ff8431a5318ec7f0202959a310595b147353a7ca89c9d1fc2d2b92ea610cf6d9ad2716df2dfed70f5b74d498edab114058c22c96873a2a64abc254c82af46 +TAG: 31a8441886d0e4c6bfcd6d74f6a5ee5e + +KEY: a248b0d683973d205ef2d3f86468cf5a343d6ad7c5aaac0b9b6b2a412eed3552 +NONCE: 8f62ffac4027f4dfeacf3df2 +IN: c2d7d29256832def577392acb9fe4f249eb4859025ea55cc0c4a67806caba3e1cb81bc7f5717d94e1c91ff06607b23c238daafcb0fa96905616f02205b702508970fe3bfca87270ed1102a9ab96df57ebdcfd86ef6e9c4c4242b4febd82b0220b0d6f76d8c2d0fba33ca49279907f6bcf7e8401d1419ed58 +AD: c738cdbde6dc277ab81dae20fbbb4a50d71bcf0ac1ee0ec6a39747ccd87be40b1f0f2c37f2c6b32ea99722979fcfddd0ddc2e4ff34a2e6113b591cbfda317c6f4b021ad30325276f8d8dd78f757618b53297fec091f029f9b00850b35f3863a3801c882422b318b4a1bdd89002f928371ea05c6fabcb1792 +CT: 7a837df292ad2e58f21b89da43a74de411e1746556fe47db55a136757513bd249384bf67887a5c1f605e7f7e3057596e17039701ea351e5ccaf0fd4882559e87197144632977cf07cf9e86784a959fa7399476a4fd196d7c507fe3876d759e2b37bd37edb3c12b89716f29ddc8b64974263a1ec1b6364b0e +TAG: 291098a2376a0faa5da6fb2606b4f2a4 + +KEY: 80634a8baea1c4fe5dedb664c9b5d714422dd1726d642e60d15e02364195206e +NONCE: 725ee5023ae08fece15d621a +IN: 4d1d8855b4d155e77bd1bf34b3d049ef09b2b94f4e604306406b015a2d520e8772b084ed668b868e32c7563085f2a82e7d99219da549e507aff9515e45a045c7cd5292c0e09a3a38c769acfd0a11826b27d8bf05184971670200e79c49754debbfc57d9ebc661b25f22f241c4d143bd922f7b0981a48c6a63462cb5cfd +AD: 12b3fa94a64454dc5b47433df1ce0a7dd5e8066d05b2433c6cbcb83087bb7d22d153a19c05aeb76141431c5f9801cb13531691655939c0c812611c6a30083ed3ec27e63e6868f186be559c48367a00b18085ffb8c7727638e833a7b907ff8465e3a01d654b52432767b18b855c05a9cfb5d4aabae19164f0dc2ca6346c +CT: 6b01e934916823f391cd0d2829c224a12eeddc79f18351d2484ef6cb5d492ec9ec4d8c4bd3354f01d538bbd81327f6360a7d157feee64b539489bfdd1be4d7f724d2a6dfa1af91e4108dbfffd529afa71388b07e5079236644da289ae236100b2fbeda0c17bf2a01e76cd1f88081682c2d074223fb8a41d59e70a37870 +TAG: 55762e95d897a33c4c75106449112986 + +KEY: 4f2edc967b11983f05ef5ee2a4364039ac02dbcccef3f3719913ae2719c8217c +NONCE: 255f8209b0c67a6277bdb42e +IN: f8217163bcaf77c1383089e396b271e22c517e8ccda244256cc39315fab7d0c291078d90e9b6e336992f015282caa1ec0ea858a179c9735b7a2f0d50f6f1eecaf3b9308772279ebb95f8aa53826e9dd60fb354de0c50c10001c98812b59d7c0f36daa1aecda6782ca36130fbb559363fe07704b0b91ea85be319ada027e47840c764 +AD: 1dc7065f1585384b88be47598ca484782716c78f49b3b6bf5d24a5b0d24fbd7831f18d77d80951d2c4fafb6f939d46362a69b558afadb3bb4d8aa27f7fcf3dd9624e1e075fce9bb239926d51ea9dff03619d64d5828103a414e360adcda8fd864fca55c21df86c76972c3765ab1d68ce89f708e7e5a3e06cd4de08573cf750c6f5f9 +CT: 6719849b7cea3f7f2a8e4de13d7a864d581b7c638f49fb06378a768d2034548179963c33f0ad099254c2edda9ef771daf5d299f58850033e2e449d7bc21ca3f7d3b7408429b596da615c8582886a6d8c1a9ba81fec4a41a38b7cbf1a80ee0ec8bd71451e727051fbf2a1d1e3c6ca98ee113e47650ba4fe80451e79b04abc8bb99a2a +TAG: 2ac7f962553a8007de3369c7795bc876 + +KEY: 51c5cf1f0c76ec96f4a5f9aa50a36185521f3ba259145ac6cb4da3cd12467696 +NONCE: c751e5e7e3d75874acfd2bfa +IN: fcda42cd098b7936f4bebaa37d5850cb0fdd6526966b1b5734f23d5050ee44466627576e1144957929123198e40b64eaef74476870afecd7b70f7583208603a1b5247074c6c77e10b9bbd41a3d468ff41db89895b0e9ca95be77526ddb30d4c5eb0796ba97d7d5c56d0eece344dde3ebd7de586226c00da224b04e74d9abe832686797df067c52 +AD: 343ae5e73fd1da48dce92ba7b86d21de0a203ba8587536fbaf4646bc45051a7feb343e38916f6c4c75b65f940045e830857c7b62b34a44622a36b34268b8a397892ed3e4de5df3fa7384d4ca50202b5b0833f921349c877931f4b735cec45db6b95410c8042ba49c1a39870276e0165f09c73b14bdf7f36d19084f958695c7ad2cc56f0487eae9 +CT: 04192659d6a2f1b7be472372c8f969a7de388c97d37b4a89653593e48b630947d2160b569379698e94de49b21572ef0b4dd330487a8be814a84e959a1a8e3cf33dcc9f7464fd44814d0cd7ab85e4c01c9d015f42ce3723c8ef8c311222b0c78eb83d81696c217992be725faf27701b4922c6e6099442787ddde2b7572500a5320a4d0c787b786e +TAG: 23c7a866574976dca8f401c4b5b58292 + +KEY: 1cec3efc0311d623f34b6853b3dc97e470fa728cdfd65993d9d48fdc192b28e9 +NONCE: 320fe742ef171b7b8cb615cc +IN: 722e503a97166a07974dcbf136fbaec6c03668fa52495b040383433ca59f6311103f2fc6a95ba4c925f8637167537321eff6949aa3051269fc094393a7b17d1ac8d29af052760835665b0ee89adda5dae7738656af9e8513c96e8a532a46ef34cd7430832d2be51c586a14e9aaec2458c1911bbc0f90b496737e838a12ff37d3db058bda9360d7d33e11629a +AD: fd5ccf6b6948c3eb96543aa40f107fafe94e5206c326dd8900ea510c6b61d1bcf746151a75404e31406c8e991fbf6e660db7c18e243fd2608aa22dd7ca9de88f277037661ce6dea4ff0a86809dbfe1708cd47d3061a34657cad143e6577549c9944e081f79c276300bb406378b26f349a91fa87de02a1405d712c516ae11b4bcf30ac9d56e677d03eb33e3be +CT: 363c1d6b806a6d97e2fddf53b242378e1d2b818828863fbb3f856f7737d63998a84e02d6c91e1df5f5eb6cf89f7ef53e16d10ad52f82362292d3acafaa02c23be7da7616a8b8daf8ee3ae74ee1078742c4ddc3e5a110e510417b9f43fbcbb00e17af3301b2fbcb784fb0a05b66469e771fbd78114fce3c4352c42928bf5a0ecc49228a3c930b0790bde7ad7b +TAG: 669482999be99149f9b723b60fec62d3 + +KEY: d3465cdecaecbf25943b7bbf8084ccabc15474a4228c46cbe652a99be24a861b +NONCE: 04fc836de3a1420b8e7136ca +IN: 81e0e984ce0a4074a44524f93e375eabc650a847a42393f5c524c65523368d38a7e2b677fe08502dd3bc42311775016b5689c660cc0ca8cb33a09b89f3ed3d02fa0fb75ca5bf0dc3c27c546b369ab5e7731f93bc074d37ee50d6f8366f6c8a45f73ac92b05c4aa552ecc5266041dc122a0df69a36ad625a26edb57bfff43a84e527ea0d9d3cf076f8de9eda28eb09de3ff +AD: e4adc14ac4bbf3ae7ec7d97f5c0e6090bf8127a75e8b70e9b86496a62a759dba5a4eef64a8c679c362785501260d29b58e1af647782564947950428dbf14edab8e6841c7afaf9e7949b560419c44bae30315c597f6f6e02204da7ec605a4d9a8753de1268bb0b1c84c972b4e7296da5c969781feeb35a44d2aef799ed228aa399ea04e21cf9f7d5600a2c07b047aa78388 +CT: d7995e7b610eede708526c05c584039d48b9b4356fc71b0c37ec2559309a688a7c69ac9655f94e178cd2311db58587863b0fbb990554dc9a6aa849571f945c61e5611ae7e1a96903be725a1aa75adc381b86e43fbc68a36f44e0e0cb8fe5c494caa91f758597b6ef3b80a879154cd8a7e5f570893b4f768105b24b58efb67c5f07c6db60e0f48eba9563f17d38aaf0847e +TAG: cc3fe61642c2d7fcbd579048fdfb19ec + +KEY: 1a0dfe2a6bc6a69659c68942ad0858e1df905890f47dab728ab9c73f742f469f +NONCE: f8f76b014116ba61392597de +IN: d93eead436e835a061ca061e3a53c3f9c66c6f011b21682b8a6fed098bde2018a2462aa5ab542c69bfa2805612cf6146c9150888b9720db1dcd0f359c1fa3416df4cd225dd0b0d949e917adfb3e83bf5ba2b967d48908e6b6d8aabc545335014d951a67390d7b5c7cd7dcbcf66e4e3f02aa4e5e9cccaf73e75622bad006c63433d36cb1c6aa4aa253dd1b2eacac75c548aa6648ecf9d +AD: 56ca2d5340629ca75de4e98921da352941559bd79f47ef0ab42d1d5857059352f96ee877f5458f090ca237e4eef5b08a53311c8dfd4c4582f18a93aaa8cf75080734cb2ea3389c9c74d2b04ead614eb54512ea93f0e3434e9a9366454b303a8129d6ce6cf96b1d6dd4f751311c736b517dcb50a6f6e0962c46637b4f5aaf0f34bff518cbd551a7aad3fa615708b17cf6d8fbc864f580 +CT: 8dc4d8483dc665b174ba32d6b6244da5f2a8fcc4b1865d662ec23057838b332a07ff073ecc893d413696f3fffc6dca5d107a5673f14abe8e0457a02e61138380d25e269686cbbd23cb7da3060f482f62bf80a40dcc2e711ecf5f7836ca14e456c4b73a48bef90749024393f5f8af01b73302e81bc37c4110dc26174702231d831cd14231905d2dd3f375cf2bef0425084d5b19f1039f +TAG: 825e7b7e195f65c454ce9fdd637138c1 + +KEY: 03cec87d0a947822493b5b67b918b5c6a6bbdebe45d016ec5cb6779c3ddfb35d +NONCE: eb7d261a6b56a179c88e88ad +IN: 2326102c58524326759ad399222c5b5a563cd01a29809d6aed4d49772a4723cfdf30c9f85f031063e838f543c201412d6f085a8f5435b0b2fe94659aaf70cf7bde99309239ed5b815b48342d4f81011f5aefe10ba105ac15601c64a91076c29c3cdafaa12bdd5706dd7305b48e923873cf06944b5027b210c59d79856f602bd6481980ea909152216756d77362c59d57673cedb91ee6f56a40061e +AD: 4d0fbeb69c1869d2d23198ec49b3dc23149005a84aace7025293c3afb8cb2e38c167a822e25c2fdf667d3677f4e94ed6574529c987de506d26b7ffccf3b7a36d9adac48bca76084710338eeb5bfca9df1bf6b403e33e90761a0b3152afac333071a5ef4f54010b945d03b51f123865673e8877f41ca23359e60518f076cc64232b306bd858634417e92e546ede4ac6231635c9cfcf43aab1f8fc1e +CT: 06746f993843901ce72f2fcd4af7d15e64b3102d2f9bec0fe72cdd0b97e43177a1a2238c9c1dfc3311f701196653249e767a73dbe819b660cee07a5f3bb8f25823875fb4b4d34a5a3a212d2e166311bbe11fb1d36f4e725c3b74054ed7fffb7082203ccb5e9d65873cb8a1ce28d5c6e2b6555c1a864a725e6c7d5555d37dcaf1d0884264be72d38cc4b65bc2f0d039d542c5055da56c57e084b804 +TAG: d36a4b6d2f592d4f0d347d906fc319cc + +KEY: 7f4b4bfa26719d9610c80ba3f474c43127f4aa3414fb070fc2f389e5219886e1 +NONCE: b144d4df961d4f1c25342d12 +IN: 638982b95d66ddb689b7b92e3adb683ac0ac19480148bac9db550be034cd18dbd10f2459c915e99c385cd8dc4dc6ec48b75f97e818030fc2d8fcdf66d66b80df64f0ca4af91bba83a74f3946b17af405bbbc6e216435641f5633ad3ee24c1a2ed1b39f649acce59ee56c282a3aebaee6e97f96b34cfc63d5b0482fec20d755f399dd5f61688fe55878713cc55d562c2d72236eb674a340d1a64932cdd8534a06 +AD: f2fe3d27bfc278cdcf16fffc541846d428b31534ec5cf51c30c8b6d988dc36cd6c0d41a4485a3f4469e92ea0fc7e694065bd8130c2854c95549630bd9cbaab2205f27a6efdc2c918c3be53f2d12f8f7cc8e6a81dc8be7cccd217be1fa2e6887cea7d637d2e2a390f50d2c5be10a32a9b380a400cddbdd40eac67f1fe9ba6033d4bfa88c563eaf57272c8a7052916cf4460f31ad026a0ac2588a45d082fbb5c0e +CT: 0d4de3489e09c7239972b675063579e409acbb663bea76bee8fb3f7e8785158ebe1c26db9219a9b97ea29e74762999518613249c3a87fbcd0128f651e2db8e2167f10ab532eced3464b56bcaa09780e5ece18182a6e092477ad933bd8de015c80e67c6802257a97a647fe2b1e9ab6a76c1cbf7d905deeb824aba2a34095f84b276d55ff940d6ab788c16cd63d9b16e0908d718c851a3230b0a37257751df5a38 +TAG: 9f0a882d4456847f44c7287c8ff3ba04 + +KEY: 9799ae8045d58250e4d9c3b0ccc8897a04b5b9fb164e54019dc58d7d77b65459 +NONCE: 0f20d002dbcd06528a23d5e0 +IN: 8f323018b1b636617c935791e1c8023f887da67974080af07378b533a7573424f1de9193c5d38f55e9af870f6c60ab49c80d7d1ad1f18f1a34893fd2892d49c315ee668c431f5f35e3f60ecfd534b4b09b64cc77cd16b0e1b8882872cd109a5ca377518e5b660d75052e9a4228e3935705b6bf6b4f4249346b7bf4afb891641a76621cd315cd75de391c898959be945ccca7a96073f2569f217617b08502f7d569bd2f80e0 +AD: 3f1e297bd91a276a4a4b613add617b0488414a57ede2ac75d10934e03be58ec518a418e98a4dbb39d2365889db7c5f389b2a16d8c702cf21b888a4cbf77b356df48a30298c825fb86128de45d7fa0e5f4b0b7bf82a2c4cad2470f33c231802263901fbda54a6edbf2df638716492157ec1407e7fc2eb6c663d9a215afbec3612778b8115e78a5fd68cf6ce66c12c0ca26e5c1f7ab079bc09c3bc7b673d21835671a13dd2a0 +CT: 9a5758dad7997a766db05d698b43fd491bdcec21352032cc023bcf10e136523219745a56f0360efee75a37de55da23cc7d8184a50ccebb110bcb960dcf6b25fe731e21f26290281d9c1c7715c4e6ff3dc0026cce52929163ba222f123d4f50e1d3cf67725fb4737f4010ee2b5b163ca6251c50efe05c5ab0b1ff57b97ffa24c98653f5c82690d40c791047a3d5e553a0142fa2f4346cfcd1c849a9647885c0daaac9efe222 +TAG: 5b85501a476217f100be680b2f5882cb + +KEY: a26c0e3864a7dd3b589d17a74a7c9c1f7e8f9adb4aafa0e75c083d10956b6bf6 +NONCE: b54a2a43ca3f84aef3824375 +IN: 6fd4ec60613646490791d82de30ded1a12e61fd270f1642d2221272dbb150ef63ef2604213e203b740dfc9c4bcdf722b3c85aa20abb1197949de710d7e8311956c8649524afc72a9bf5eddf0b284c7fc6d48a741b82c215a0dcd73bb8afd08d5532a6f7f99b5c6beb2ad793d6da53a81e6523b2240729924ddac996a723421f57125f928990daa7a55a5b6b53d7361d9728f66590d969659aacd9aa5c0ec627d991b55e9fd0bf9c3210f +AD: d6d8b570eca29a48a4d408d5b27ec6aec291d70cfefcd02bbfe8d8ba8aeb6db770bfd723d2c3a4859f1992767d24e7b33e3e241874292af640e2bd22a5b77e0e9e1e0d5e485041cac41d4694ac929ae1fbc08e7591e1cef689028f5db26f95fc9e0868887fb9c635579fc6335757697f63b4f2b46664ae338eafdd827988c8f2ebad80ea9787871ed8d6b302d5dbf7e8019f2e139c59036cb5964a3701ec049b839e19e33e68b83539c8 +CT: 2420e09adb24098038b2750c946551a5f6a5bdf23b126947348ddb5e938b3fcb874b33fbac6407095e05ce62df999e7234cd2b4e413009c71d855b23993cd58c1e26ba0deed891dc88f099fdf852cec0aab45f488a90edd8feb6f4c837036945bd304edbf7a2737921a2f8c1b00a1daaf9e25b908a65a8f69963fc767bc975b5b7bcc215ce37009009dc90b5c7edb1a1174a10ad28f4c1d1a2241e7ffc215edef4f847ceedf7b64f2d15 +TAG: 20521b35310385ae66557740b435d204 + +KEY: 53ef3dc7a10e435650dd20550cf3ec2b997afc8d9e79cca8f7062622afac3496 +NONCE: 257a205ed0f84016183f4613 +IN: 081e2769935f945419aa06fb5fa7d8412efd1f9b52a45863808022850836c1974d53d2b2c5c0cd420711a71e6d1a09e984366b8b677e6c61bbce8f3adf9f5a9fb5860887617a08c923171d681c4fbc6d569690f6a183d42b52a80ef0693862efd22bf83b7b4014a7008424c356b5022df1842309b3a4a2caee0fd3f4d3fc52a17d53959daccf8e0ca889578ee2905dd8c17d52e76712dc104344148e8184c82af8165ea8386f91de585b54fc8535c3 +AD: 5b73ae02bf4a70e57f5d48fbf45f85b8496ae8514c8aeb779c184f9cf823d8c1883c9e5a42b2c099d959c2298ace2d86c4479059256d6a4325e109fa4b6c4ce90f84a8228316e80aa86de9b5e111d88b2be447a29297b35ca90a8eb280d4c0fe92a1d593cb966cb0010bc06831efb0c72c1e222b031e900ef06ab8da542a5abe2870a0efbe92351d5915ab545b14900e41a27c5ca9d75d6277afafe7ae861131c2767eb314c0c3da5c264f8f2b4ac7 +CT: 20ecb6cda861b660656d692c626436227bd4ac17a9bc71f6c84a1917ef3b5a0f6ba370f00fa2e7f1bd5aa8d6c15032572090482c23e4ab7376ef1f4dfb77f79d5dc065792fe3476c9c37614e32f493e461981b519dd7d10234c2c69264ffe5be06a8e14c81022b652c8cfa24adcc7c7536a55a2fc41e9ffcd09e1c483541cba814eafd5e09e9e44477018a41b073e387c9257c07d97e40f0761fe295d015e1f2df5be65b13f34b6ef0fe1b109ad109 +TAG: c129ba4c10bc9e9c2b7d67f5f249d971 + +KEY: 15ddf0d794b1bf2e67db1af47b45b8abb0c62ff5fe09b29659f63ff943815c39 +NONCE: a6e6b4fd129bee3ab8144da1 +IN: 9c82ac83e3dd227d0cb9692703dbf41292fbaf4961e28b7407ef069e33850371ce2838b1808ec1f837511dae9899a867959183ef3d988ac20758d7a1a6859cedf687d8a42f3dd53fa4b5843e5be61422fb8774c9eb0fd22cbda5950155caa0ceaa00417f1e89a863fcc08cbf911776fbea8d7c14a6d819c070c9abe76a7f0d04598188d07fcbb822758081172e654c025703bb24c523cee2dfdc31c8d2c84534a60e7efa9f52f7e74e19c859889f9bd024f28763 +AD: 892bc04375e9ad5ad2b5c117d1aacc202a74ee4cd4125019f38ed4d716ce361b8b50463ec3255a00670f5f95d361e79349e90bfccbf084586cb5fa145b9eece8a10187c13055ba0d17c0fa526ba7985f00f3eb4a2cd53b6da488827fa8481cf47f6be58771d1e40125652732a7dd5adc49cf99ed6b085fa9fe8721c86f7241b6efb6002e65ae5f72e16ce6a09ce81365485b20f1fc2e092216024b1acd0bb4c2b4ffe28d62a9a813fcc389774688eedd76c0b041 +CT: e30465518e7dab44b9ca4ab6c86fd7b701e334b050a7889fefd08aa12c9e381acc7875ad5f8574fa44f8550bfc820b6d9a5600cfb82d1f98721a875610a91c8f47960ea64445c0e22fd3ebe94b3564e98b9b00a68e9bd941eef5382a67782c5e24ac44b928fc986c62a02fc702b145843b1c6882188dcbbb6f6b51ce1aa7784da03cbdc3efb1a01c1cfd7e90dc3332fc6e912a6a967ef1f239cfdc9752e235dfe75dab8088f8cc207a4a28994f122859aeb52d01 +TAG: 62e7455cd6b95319efa3ae0d14b88452 + +KEY: dc0cff51030582f29676482ec8dbf0490a135a4cf3e444edfb7d1ec733cdf7b9 +NONCE: 58c892d618ceb6027afbabb9 +IN: d6c4d49a9431d51bfda5bd4b07997690748fdc3df196d27d219a62480dfcb6300c5a234d675aec1239280446cc134bd4e0e0b5ebf6f10bb11b788caf949c0c3553497b62e729f08700b66c6720c35f1f434f16b15a4e404d627fd054ae1394a77d5ba728f3422aad5d99a608c2aa52b058946a76a408c5dfb210d280629ac999e86ab1f9da8f2b7b79ec07cb666105582564974180ace98c63bdb962e4580692abe58929d29f066d2f7e25c23a3824483d9e49cb6f5fc4a1b0 +AD: ee3bc8d875a4d43c278cfeefed8ced8a3da946adaef93dc356001da151010548990fe08b62edda46634db320601c7f4b50956e29868bda9ae5df186f15c3ab4a19d7cec274209cecc71602e45c37c273b7e4b2a168de5c29278042a3dd1fbea0998d7d9707d412f476ac8de7936e2e5c268a2f22646f682e664e526f88004e7c461bd42337dd21b1cb39ff678974adb67c2ea1b7055ca98697ec16c4b3bfa95b4dcbd7fb015480135634c34acb20f58549f7e7e11e20a991a1 +CT: 54eedf8ca21f31d21067af5a05dc3cb99c3dc046540d2cd1664abb32fc7714ac057d039cebdeb124e1ca9511bc71f92ddfd4c6bd3edc8a1934f2fa2511503944f2a0818e30b9bdd26bd3c51b9673f55ad3f2ee5e41de114ccc55abcdce06a5bcf63a5bd61fe71dbbfc97e1c7f3417fcb9c1462e244ad91725081c9176a0b91d3485400d273a16eecd870ec1e9e016a7f4af2fab39a0bc93576ffd1eeef9cc15b7e47feaef85b21de422666ec722cbaef26edd1941e7dc03f72 +TAG: 1cc8c395b2ccae3a685183667ee7bd34 + +KEY: 90da49f8f64e8a585697a43644a48bcbef33a8ed23c1a93c65e59a217c04a1e0 +NONCE: 0812f87792508dee6868d454 +IN: 26dac57d9f30bae5831f98ed074cbc9af9731a52b2322cdd23f1f0abbf78092c48d6d24a43c7d49edb3fa66086030f37dd9dc67847714437b11577d2bec645b3210baa8f7a540cbfc20deec5973b7489b7607eafe72e249df5d0fed95e29f03cf7f0c7a22fb2f06a0bc75214446b06d25a45ab8087270eec56af3960f53b80412a4ea7b45e54a2c374e8a3789e8eb57e656e22107503920313ee3e4025836b9e1a98541446c23bd5674cb83483642f2f3e8270bd1f77c85bcfb205a9133c +AD: f2168cef97c27a902d93cbca07b03f35c5c3ed934192d29a743c3a6c480c5a62172c088fc89cb2d8651b8979e5bd1864272ff179be8003c6dee18789c17583dc1de4e8b4fec80e5c7575838e621cac4b5b51ce5952f22e06b1c196101d2ac8d05e797323e5baacc49d1e74db97142e1bed723d46ab858d59fd36d5d08eaa63f696b610eebdc9662e504992fd3481de1264bcac8ac426b09fbc641ebc93f72c5d460088fe0b08420d88fae219b6a5a67420a5f9d1201bf8d64b2ab3e9050a +CT: 82196d89624689bb172e4ff71619046a91149c8ea99ebbaa3f2c32c77938b5ac466481575dd82a008c7f5867bc46ee44faf95fa40b6237c8c3b62474af2efcf07c771e23a63e65b48b0bd8ed26fc64dffe03e71fac6d3857b1248df63d888567d7d3618c68d6b8f1c88029bd7af8677d3b51f70ccccb4eec9e100768515637ad8a4b2e2e317902e456974ce9fe23095cc68566e85cd913e8b64119444f124640d16ef3e98136f32d618eef78f7ffbafb64227b3185bda8f541c0e7ee8405 +TAG: 71fffdbd6358f755dd22f1dbe42c4aca + +KEY: 0b1b256665284390a9193b7b7aa4e3ad15a3d2a58e79d75da8ec284c02fa3a2f +NONCE: 346ae65660de8920605fe8d1 +IN: acfa83f56f137ac39d6447d98c5f7d5e812d1d8e7c7fa7f7beea9a87c59961449683fcf5332c9ef1587135030309a1c2d95257114b790b18cc32f65f4c7d1652c0106e3331f826e9b8b0dffc50aa6723d0827076b71c668370ddc8156db3831559a72e48266b3886a6d88318e6ca646ff561ed4f71e665abb7a60089f0a115c7b7fad9cbba6c4cb0c242b9e1f17705825d98f4bc10bacd8ab2e11cf579f29b2a0b085d8c96a372434785856b483c3fc9ae909029b0c931098d7e59f233cb6450fe0b0d +AD: 64347fc132379d39cf142ca81d7e49c010f54f354ca3365d5195a7e43175c9a47603062c5ca61aaf2b381f5cd538bbf48f50d620ff2b5980c086049a378aca69570ab7c406b510a6aa6b7e8682ade6a091b1f822a97ce671fcf7c911c43c4795b78ce1c86e990e32bc5c9fa34a8a4b22a20d6f7c46722d1bafd49443b4da9634db4615f7cabc3d5bd9a8921e67de45dac261f54bcd0af2b2f845e255a16f2d2f1ffe26e88238f5dbdbe111393aab3409e08dee8b9bc85c51b385c191ee9290454236ab +CT: 9d7421330f0c2a525495bc360cd5c2273531d050d461336a254c9af8611d07c3559931cd6804fbdc6e6c9c997283cf40bc23596efd1bf116fffcc6620e45d1c738569af012a7ed0d575ace3c12662f88f3ee480af30ee015ae70db112bf4a185e220660a912f9ad840346e7cc0715e853dcd9b415ca9e865d5e4de2321e6a1b7cd8a35c760abd3f099d395576a91503147bdd51cb4bd1452c4043b42dd526de6f61bcbe819cfa3c122c6f62e0d4c38b443f5a138325a5f0ff8a9a2071c2773ce62edda +TAG: 2af508d74bcf8157ae9c55b28b5d2db9 + +KEY: c055bfc7828d9fe8fa8d9851d33f3e4888e0f7e286e1eed455e14832369f26fa +NONCE: 2804e5ec079eada8bb3946e4 +IN: a26a9b189ada0ccafab92a79711360c7c396374c6170de395bd8ed80dc5db96ef1534adc4dcd419fdf1801add1444a195367213e374eb1ab093f1f54cd82eaba5c1cde6b867e0d8fff99cdab4d96e69aee0c58a64120ce0cfd923f15cdf65076a12e06e53ab37463096d9ccb11ec654e401c24309fda7afa45ee26e5e4b8adc8febbddaff1e7cecacad1d825a6b16a115287b4b3c9f8a29b30fa6236ca6e883abda412177af38b93e0e64b012d33d7bf52ed18c4219bdf07f36151b7ea4c53091ddfe58b6c9beeca +AD: a184e4811d5565849a08d0b312f009143ac954d426ca8d563ad47550688c82dbddc1edbdea672f3a94a3c145676de66085ded7bcf356c5b7e798f5ab3bb3a11bd63c485fbcded50c3b31f914d020840cbc936c24e0b3245fead8c2f0f3e10b165d5f9c3f6be8f8d9e99b97efda5c6722051d5b81a343a7d107e30d9319c94dbc7c31c23b06a4ae948f276d0eabd050394c05781712b879317ac03eb7752462f048bcd0dccb5440f6740ad0a3a4c742c3da32a49dfda82ed1b66380a8cfd09dda73178ffa49236d20 +CT: 58dca29b5008f74bf132947df768dc85e2492a381429f151a3bad3132e63a4a977aa09f10879d206f43f27a26909495d0a2c8cb252fbcb3abd953f6e0ef0f6d5e89d89a1d9ecdb0e44686fbf5567a6fe7557a084a8a5ef5316890917bc432164266a331118c828fad4f5d1776645d163dc5444c2e12def608efb47adeb8f9928a5ffd3c46f963a749c310688e78525e34a510f529472a14bc7a5b65594338f6f5ea1d95bb5bddc6e8e1d1a449d126442accd162e4e03c10824fd48b32df763de5d7700dafc54206b +TAG: 141c80e1d044e1e9cf1c217bd881589c + +KEY: a54a347a7a388c2e0661d4ae1b5743d1c2f9116c0a7aa2d6c778a21e2bf691a9 +NONCE: bd3456b0dd0e971451627522 +IN: 3d17e3d9b5020d51295f7bd72e524027e763b94e045755af4b3cc4f86bce632a1286f71734e051dbcac95780b9817b5f1b272c419e6bc00d90c27496ac5ab8a65d63c2ea16eeeebe4b06457e66beeed20fc8d23a9b844ba2cc3eb3d87e16e1230fdb6a9134bad3e42eadccd49baed5e03e055f389a488d939c276982e4bc77f0a1c738fcdee222e2641b06fe12ed63ede2ab2fee3c54d7901d0911c32980b7c663a67d35ece23136c77f8e4536464225ab427d937e7a4260460d55bb5fdd7ea2f105604c4b0cf129dec49b81b1 +AD: c12d1ffb08acf27d51e63f5c0e311180b687438e825204074d4456d70b7c5ba9903ad0b0778a5fe36c3e12e82718c00f5d1ce585e5c73b23d6c5e41ac4a180c97c9418b07ccccbfc58c678e97882ea36395c0a05572b4cd25ddb3c32fa580c89c48a0e3066b8032e3823893a5721a4fd1e59c7d012a01b9e9afc12f3bea93e9d1a2cf5cab26e064576b36bb65606de62fe2887ace0cf399dec08da618954ce55362c8a2bcf31457a1804bbfff68a76d752f9aea81be8868bbca8f1af3375f7137941a1924b8a2b178f06a9e33f +CT: 938f8f596e17eae6920410f602c805ad9715833087e1d543eb20b1b313771266dc6a8f86f2ba033609fadec92ac38c1f1f0f728e568fe8bcecbae2ade7b9c4128fb3133c8b4107ad5c29cacbd5937f66905e18cc52d9239c14e4c8edbb2db89b26f5f4a9ff0f2045192fd212af6c65e448834580deb8787b612d6345466483dbec00b03fee4751f543a6155f2dbb745c1094e9721aea3e544a894e4a19a14645725cb8fdc21d259e086b1e411fb1bdb11293d0224ada25da2896dfe0d35095230af6894404d27d901540b0ec35 +TAG: c55c870a5eac5c0c774dd10dbadd3fec + +KEY: b262f6a609c4ad6da3710d58530b634fd7bed875956d426bf4b2412209902233 +NONCE: 0b455031d28e4e17a45b7a60 +IN: 9cff6ec8832bd0e62d9063e43821db6a1e0f3ae7947ab4d029643b0e7db8224f8bd00a2c011b246a4d5eccf9801fb314aeadc0532fa71cffe188e801d7c045e81b9dfc5cf6ae1e310b363adec4e7ca52fa754ece2540545a5161eaf9ed5748070b6e232125fa8e0fb7548fd3eed57a6be72ce0a9112f166776816a0a4ccf8151b6b93780875d03ea3d59ac57e7904c83b90b7666de85f055b25f9e342af4cb04b0c3f123ea0906c04f252f2b16b28d612e37b2a7b788d66beb8b361385efb73a825ccfb1a5ca55d60afde0349e5dad8096c7 +AD: fb99bc661b51464c0df92ba4f64c4c56d601622287bb1bf8e0a082ed3793e74db6a2f5a546391ef55dc45fd2f24878834bdc2903054d9d02ac05bd5ff122b65555d7ab1664cc36b630039e4432315445f303837e57149fdf6bf8d6856ba97abc5a18b6cd2f8f28cd3ac079355b314561c50126812861c39180fd94f9aa24edbec37bead760093d32b96ce30e389f63b2b271fc051b42952b3f5cf3950def581f7cbb2b4aa5b151a16ed3773166761232c106d3ff57851895640ea12befd69daadecc4122b4a481e85088edb093e02d5d3d8a +CT: 5341e8c7e67303d5374e3f5693c28dd9f9a5c9368efaaf82d900b4a4ab44337f7d53364544bbd822020d79443e2ab0fd2381bc73750203caa3d28858a8f9a6dba57a7c5248361ebb152a81a89c00b1bf49de9e2d08c0243b38eefe316ef89164b4907515f340468291e0b51009c9d80cf5a998d9cd8fce41d0c7405fc2d1854aae873f0e24cfad253ee07d9f4cd27080ee8ec85d787459080a06d290e6e721d23738470835f173ed815f1a15f293ffe95ad973210486372e19a9cc737c73928572cbc03f64201d1b6fd23ebb7b49d12f2eef +TAG: 5e0ac1993ceccc89d44cfa37bb319d1c + +KEY: 9b4387e01c03d2e039a44ca2991aa8557dea6179d19259d819d70ab2d5179eb0 +NONCE: 852124b4e04d7d1d63743d74 +IN: 92c6f01cd2cd959495bd8aca704f948060bee01ca61c46005b4db43e2e7655af4c0d96656cd75d904325ecc325f5fc9a5fff3eeafde6f81323b0e3b64269028cb64c9fbe866b400e76487f1759d6ab8fc66589e23df0c008974e1613bb4ec556bd1a6a0751f6dbbbaeff219874c57dffca59a955e0aae62e8fd6a904a50fa7eaacccc6dfd4a2b8c6c040505d3448ed2217b7024224bbc4335c63b2ae8172d7d3088b819edbaa17991a4729bcd5a456cad20ba20dbee99ae56f8ef669dff93c99a995c8f5dcb5d113db4178a49516206a1cba7d872682b1 +AD: 92a1d2574182f850e37aa62338b19f403fe99dbc7ddbe1e6524ac67c4092cfe296b5ee9b94eddb5c228c902c18ec1ec26e1ef0263d05c5caf1c71ed9e5ff987e9964b46f27be05a83e20867f1f2107db26b6bc7066af2b0efdcad2b65f2ebe8b31fbe2f3c30171f2e4969f1650c9642ae47c8db5bda47e57e8a9af210a6fd4894dcc2934b4ecf823cc841cdb3c93ecc779b455b8cc796d7d60437da201c3f848dcd5f45e88973e06364e7cd01afd2d49fd3032550f1c1a60c4ba48137398f4d58e5fd0093c06042b103ce0064f2cd1cfdd39b7440121d7 +CT: 28b87d324854d5c9c6ebb303fb802b12d946ed681ed5b3384dce2cd782bfbd022f213f193bcac579176440bbf2af378b019d21dde5d70e42d257722d15417a9fecc8e56430551ea3bee798a01faf74d0fb09be6dd0c14cd03feaae29c7d17581e1fda0b4bce632ef790202e98c8c4f8f842fb3e33b3fa5e8700c8644ed6d64280652bc2a5d40b3ee0e47dd5a9f3535e15b1fabb30264515afd4f9b1caa5c224574636935baebf6d1992bf1a7a3d698d457db4248a2b38a803837ac4fab7998722d52de61bfab4f98e1933a77046bfb3941bb7988acebce +TAG: 1b07d58be48b81f7007e5683b399dc28 + +KEY: 9d36155d429b90b5ff22ded128c9f0cfe77ed514d410998091bfca4dce7e3c88 +NONCE: a7b73ba1b2b0e846c3f635aa +IN: 2510210b420b12300d51ee4a7ad233c9c97d71672c0f9a7b9041d32172fdf3a6ce274aca77a0db6961d7921d1681ede2c1088a7618382481296778e7f56d2c0074c7c545ccda313495ae2a6dfd042474b07d2b59c79a0cd8c3dc16132beff1687111a48ee3d291ac556987e73c5a3807923c2deb3b9a59a135a8fa0d85d5b39016edfe0649dc13be672a639db58839d3362eaeca046767fa1182ef8a63abc104e7cdc8610b1e956aac89af76b40844a358fe6f7343d217e1838aad19587ab4b1c765d2cd7bf7018e338c0207d4c9dabdb1625af0c75749e9a20a0d8d +AD: 39e96c8d824bee306189a3bc8a8d4862df55e8016726222a528d76de169746a363e82e82e359b774d061a6e98e3c35aca8ba802a5956a2c512501fed44ae341cfa65ec9d95485763d99cbd9aea078ce551f7f82272bf54dfb6420ae7653f275ef145b2c87720c9ccfa56bd286c61cb822d0473dc2cc3fa22d50fd16bc0358e7c615aa1791b990f30b1d737f798219f4446d173e80fa62380dfdfebdb36b1284a62c2b6638f28fc370034812d09b57d27e5b7d589075bbab42fcd6a91fa2714538be6286e4c7b2657b80f045df7f8954738efa7d49a38e5a55a2af934 +CT: 8cb991b10218bfefa522e2f808dc973620ea391623947cb260b852efd28939ccca4c8b1f02d66fd6d0d7058854fac028fa0f23e8de801ed9a4361bf7e5a23e6a7086624a64a29815bedd5e5ebe4d9f9386d47e1408286971654b38ff8e5dd1fef7686d7614ef01900ad33bf97896b4ad02e7445782b1794b45af967ca3ba72a2e5cd5252a9ff0ff550ee56fdd8aa555bbb0bf8a5dd534fd65b13235fa6650761dfe2a28b2757077a2680ef88c84eaada743d1f0d25de38fdd1974ffc07dbb9c7fa67cacca309a10753c6e2561c4784470f5c7e116e12070fb3d87131 +TAG: 665fe87506f8df07d173fedcc401d18b + +KEY: bd187500219308edd6ac7340d72813ee20054d6d4b1bc2ebcde466046e96a255 +NONCE: aab93d3181e7a04cedf17031 +IN: 55b824816e045702526f8b5def71a0d023a2e42257fc1e06f9a8531ef9f7717474ba4f469e442b471d5da6e71aa635a307205c0a935a54b8a59be8856144dec435e29aa1a3568073aa6bd3439bc0f219fa1179ba0a316f7d966ea379da16be4db2f1fdac2fa6d00bef9351b78bb2773bc30ddc9d019e6e7d78dfaf38010080027afac33e751c0429ef6c70a1f2d01f103482818e9353e39a3a4b785a7dd2c7e1ba7a4c36a5f3836d5465c002bcd1ac576d90ad276952ac155dabba6873e6d92b5278280a540071b205ba99b77b7568862e70e6ddbd804906c33fa130f8b0862001 +AD: 11b35743bbcd0113d2c188f75d382df44e874a2d4b3c3148ecf8e0406479305f29197a3a71dc7bcd71b6136ab11a7cf46de80140e15046acfa18774cbcc755e9f3beb37202fc308c03b1c20470b3128f5b91d925bd6703dfb3277d65159688f656d5ccd83d2beadfd778854472b1cb8fe440bdb7efe806f4cb95249cddf69fa0013dc5a626eb8ab69a48b3ddb1a317b35f7772f711221cee1cee9469e2639c44448c5942c95324dc2fcfdc952e05aa336ddbaf57cec2d1b33981ecb8f70ccd34a279b211c50a7784906f2981a2d2ad8fb130100c4f6bdb09c95dfcf4b0eb7ac6d5 +CT: 1e99d06f82333ec8e4fa1e81014458c81325e5d69db561449b153727da35c0b540c570b60488aca6aae58f75f84792388d0160dc45e4e5bef552c49228d806fcc22259f0f94da2f786cc94a3ecf3cc15ac67719379d86abaa54ce41e868110ed2b56dbeeaad4a444eab51a96aed404a4f4b9677d22345fdb67ed0df091d23d8acd70bf6cd29f19c99910888b3281b65637590af984e493ac70011486ca88e72fd14ef1cba06a50070f138dfaed35ab12690a14b1c8ac319f597bb690cae28019d64c868acf9a58fde1d8aa18dc1ec9c3c4a0ee9c4cfff8912b1bf23c805af6df48 +TAG: 1a43147e6e097a46b61f8b05c7dbbe1b + +KEY: ce53e967bb4675a51652a9e6e87da6be36d16245c1e37ee00bae09cc30ed8528 +NONCE: 0f53ed18bfdd28918c3993d9 +IN: 3f2416477ff2ce7da3e5766f043e7a06ea2b87fdf06320d296c71cbaec4b115da356f8c7f34220f91e90c97a5cbbb7fcf0048fb89414eddeb2ec1062d08cc75a39a1f9f214fc3efd6fc8e70d78418007d7d28944b3f37fa5667ff79098d7af36a9324419b53efa76e98a311e1436ecedd977397cd02cc8d377ea8558edca35ff4c71ec31943119b76af4c78a435033eafe73c7079224bf2328b49ed58acef9b043ae3c7ff17a66b521e190d6ca2b2835ed8edc2c173f04616af237391a4440fc5306366c834f6a504e902dca6d3e9e1554088eaf5b15db7fc1fa19f0867ece90ded639ee8072 +AD: 64a596ffca0889833fcb537f58d94791f9ba9b6b7ce0c7f144f2f1a95d62ce334f7bf7f0d2ef0c6e7afa2324b069dc6a7a522f19a001c335cc0252ac4a26079c3f267cdca1e3f933069f52fe72e1a00c83d8fcbd2e76149a912c7b37663c2e7967a3a80656c87094d349af6b9d64b3873f467ed376eaa1e0abae06180c847e981c6a12d32b580acd34f779c343f8b79df1b5004d333a5c37a8be7a94c6f6400f819ffbe6d54d3c1a92824fb15c279fc8121c735b6c42248ee22e665245966d40eadc51f12904cd64110d69354cc9d9fc415b3469317d5e4643942dd4b649de0ee2fc5d200701 +CT: be462da8cc9d8cdf343f7025df0b8b41c24f7b6060cea2d3c63338b6c3e83f0797e966b8c5dd889bf1b5058fb4d694be2178fb33d9be1a351812046a6d3bd36c84ee3665d39fb98159e4d30f8a25a60064caf980f744fc519e2dc451f5fbcc0834b72920d32f0492abedc1022b0db4f2f44b91ec48c588334775fac91f174a4714b3825e96fa53cad3de94807f3b888950c8776189cc18fdf379cdc9d6054952c6ed2b3fb7f6b49beebacee7ddcb19a3eaee2b2e2b7a5d6476e5fc1f216ca443b859a9a661dcf2f7709f87361186368a62f255d78150f09ad4ab1a20e7329f3d96fa2a33cbf6 +TAG: 1cf74908f6fbfa5b2b309ebeff2f3ad1 + +KEY: 093d932ed969cfae63f07e0c04c7f9eaf1b36f656095f8d5f112517dfc430cdc +NONCE: ce36a837ae93a280d2fffc63 +IN: d9da99635f8d728843dd587cbb24e68e1df2f81b5f7abfe233a224cdbd48cd8b82da3711d2ab6c1ca722610b87f426a2cdee4456b50781e3b25da037ca636f2a5eea01f4eeea52d0feb7f1f6c2594d63d8c05c2adf339839449cb1d2aca94852d1b64b5641a572c2da02ebe299c7d1ff4da8706f44b14602f44c0ced711fc78005f87b1686106250d3d3860b67f5b38788db1891150f88d4c5276751afa0b2e37a59587cd8b718767455e65eef25bddaf787d52b88556710f740f117b02f244edd47cf0e45646d40e789671ae61ab06336e24fad8b64cd8f60b427ea1f58af443c6f55d54028edd5f40d78 +AD: 5e9c95c3449cee3f9f726be031089b2358ee92fe7b408b355739c8da6369304f3b287ca60dde4685bdc59879e1530ffd8f6589449196abf0f0dc6dcd82ba7fba481f13376cf29b32af2ecca24a161e6e57b6db70a7e02ee2154cc0bb5280b08f8dca35b1a342fa18b8025c7a805cebaed99e30b43c139de7c37adc25b0b6b5d873ed86530622ef2d0ed3ab19e9c27df98a4a15324f902c35a23adcad4598c6e990c64893355be15fa7320c1935b4ad3c069c068d6b3c8f43d6fe0588b59170bf567ac3a53a50db68e4be17964f55acfe695638cb5fdea5c40805334a385c2d35aa836637ccdf71390487d9 +CT: 40380718f069f44c88932af22a10f80513821caa71fd7a9e5c4f37e1c756c43fe491ac13f244bd1299844cc78d7812110f570b693e63614e639ec7395cf65c206eb6fc9bba86f89d03dd19e45d5ec64c7d3a308ced4ac1f59cf4e13be64e49acd9ebee209afc508c97ac817f1367629af9d59b0cd48f138d23abb61f92dac530351f46a4e7f70ac87388e44f6e9548d3e6a26884bb7611f632da7db2a12fd9174773e685df316ea9401d8b352135b6b32a374eef8661b77eeedc34fa4178d0a5731ac9bfc14bce1dfe96af095b0088371ab1a04b2062625f0c4fdf01fc0a6bbf1661cca11932e93690501a +TAG: ef7f960b146747ba4f25c705d942f8c7 + +KEY: 86875efa72ec1827f133a8935193292463ecef801bf3b461c96b0312cfcf32e1 +NONCE: 738136465c8935d77c8d4ea4 +IN: d692d3ef47a5c9d0d9a3b6a0d498e90a3ea06278134ce90cc1d69da2159d9a1f5d0a9ef4b4ce5f873e26e8f9d53ced79991491325ba5511be4d9e6563b70459b10e60d8c5da45d3b0b34dad86772b0560314f0215bef7b55c6ae53999cb2d6a14a35b50fe5a1598adb7ebeee097968ee7624bde42862824900c8cb45b12785d9c4d50ef38133d31a66a612d8638008d03edd19c4d7edb5f9b9f195c60883a7d6aa85bc3ca3b59c395b85dbe9bb30ef6896c4ebae8d72cbecfadfa451bf36631aefddd3feb36978aa8d9a45c9fa09bfa0b2c040d9a422840e68f4dcc3eb902f6be1d91b11e1749183d89715761b6cf22c +AD: 17208cfe5a96adf0ec903c7618d994492d3eb77275fe5bfce5ab1f67d27431c7746314e52934b8c44481e5760cc8f6b0e17d1fcac7fd5b476196e3152c3dc90adeb58c2c9c62cd684b4b18d4a94f8e5b4336ed3f1758b58a254f48b3aecd9cfa63cf758f2df54c52eb246d046198b6eabc90b2a0dd6c5323e915a117235174fc9089cc9bcb1a3bb49080cbcc24367e7f4e17e27a2054bdda0ad8996df1cfc6bcf43f70cd854f4d97aaa4badb5826dd86765d36a2ecc83d3daaf31594eff02999a423185356d693f26025a576037336c156543353423dd3b5da75f45e297c60dd8e091b961f60eb6786fc988f6324f9e8 +CT: 55f48dc2b6836b8603e19264382ddfc568b1bf06e678de255d355fd865ef03339f644312c4372494386589431d4ae7af2eaee5dd3c16340ecae3e87dda9220a5f9b9fe6cc3eaa226d9608385b7e8a6216e7da71997088eaf7c67b5402be01c0b182383ed3c0e72e91fc51fc99c59cc8271660dd7a59ee0e7d9626ccd4439bb9a1499c71492807f8126891ce09451d07d9c5525c5f185559ec44aa31498be3fc574389cf948640dcc37d0b122249060bb7d5d7e5194d4b7a7bb64d98d82a1155e30970a854f7c0d294fbb1a9e058f3b9f4762972c21086e0bf228768d0d879a9cdb110f9e3a172feca7417d48b3fa0b0b +TAG: e588a9849c6b7556b2f9068d5f9ead57 + +KEY: e9467b3a75dde39b0dd44e7cbf2b70ba1757ba6a2f70cc233d5258e321d5b3ad +NONCE: a9756c7b8e2e2f4e0459f1bb +IN: d6d7f6112947be12e7ec8d27ce02924503f548456d0ba407bf23e848b9ecc310e4a0c7b00c0de141777a94cb4b84a5cc34b2b05c8a37cda08b6c2dba80e80853f2a18bcc41341a719f84262b601610a93721f638a8ca651a2f6c03c3cf1070f32b92c4ab7a4982a8f5e8ae70800f7513405f3ae28ba97a9ce8241608eeb5351e6cef5560c4209790ee528b3876896846e013a0bd3a1aa89edaefe08fb4b73b3fa64c0c8b0f7ab70653ee138456319230174f0f1f7f3477f0cfc80eab8a96e29e85e20658cebb830ba216b1d8281ce499f729278dcfeb59cde3a043ef3fe2c42705f311a422e9f80fc3b58ca849dd4b99e5e66a958c +AD: ccab7afe4d320e94f77963d779ade1343e66ae80446eaa5f9ec4d3e3bb3166255e4aac5707ab407b284dfcdbb18ff515cf08790f0470cf335946040438c7de2d2a342096d7607e1920d86b519e96cec1715f4b0dfe375c5959644bd664d23d879b825dffbbdc458ea9da5ede5682ce1ad1cff33dd8820761b1c067cec638873a3cae79c7682ee8d4f97cb96a413dbbded1c242ca669d50ebb6de3c27eca3041fa8aee8974c3d17b0cf79c32c7bbfe20dcfd57303cc40334fbdc43e925df1d63fde57bf60553d7790fc56bd95e675db934dabb1125eb97cded95f397b32bfb3a2d40703e3f11c6c226633b3cb7f9da1e3367de2ba4d +CT: 47bb258ddc0945079a0b99ed5cdc0186f453f8e0393cfea258412e423dde4a00c014ac298c4dfe7c03b0d9bbd4ad189624cb6fbaf13e60ec2b4d83c5bc3294dfec30bd6c8f7125e11d7be145a966dfd78fd77af68099b855989fe077cd9f427d4381b4930abc1daae55722540e4bcbe1b560fde208ef1c2dfcaa2c51b76072e67da311c2556eaa2c25413bfc43d00dd84aa8859b296e05945683e028699d60a29227de1363c4138b9ec2db8f3b502fe09d368c5f2ffd81abe50cc1ec1ef216f27f401456d061429d1910623af00bcf500cbc6509c5aebf7de9c956e40a3f0b0d562775b03c282c204e33c0b380ce1475eb5c0441f6 +TAG: 9ea19333f5050354a7937fed68e38dd4 + +KEY: 4e323dedb68bb5cc4cf2edfe3a54a19b410f849492ed6f66fc053d8903c3d766 +NONCE: f77b876eff796db621eabe88 +IN: a7514c4111d7d8bce2d56faee25d9f5fbb527162576b444fadebf42d48d2631cfed344b0437ce8a7609bf30bf0a44aef172f8b12ea7567cfa5dccbd08bb3115efec59437ff02e7128df9d9e5193794373e30dff7b3d8ec0fcd6cd3872d755c0314f1cd9cb996e4c6ca8ee2e35f9b64a1f0bd1669369f9b333a356ba58e553ff9bf9cb6c5522599dccca2f7f57a91006e7dca4095d11955e5aabff69febb98a408aee92293c0abc12ff23482ebe9d541bf8fc7493eef2c68044dd185eb243b54a2bad9844d831d9b0766a0ef013ad3ac03627b1feeb287e5e61875bb1d0a01315761bae6323a9d678cdcd3c4a85be71b70213d081b348c63fc603 +AD: 9bd10dc97ab5e9b35e1c8c36ef37f90a11bae7dd18af436fa8b283eafe04a5bbb16bede6ce1260187299ae6474628e706cc08b3627f5243f1a9ab469455666e6d5f2ab597b6799bd60a365a9248341decc36d473fa52ac5ac469b965cb2023d43b437dded84ad49de95a6dfc6ae4bbefaf86f9b06e3a33ec90d32ea3af541fd2c43387c75dbd94d44b9582e8ea41afba5e49f1d158d48e979d04888fbd42876e12bfd6695cb99640c537f2f9223d37cf6b627207b9318bd1f4c64556b5db1101c486c53dd8dccd7405e148d6d9b38b7ac875a44bd6df75edfa4da8594a9c43b223e7a6f5b81a5cb8dd6e06e9a976ef156e45520af332e4d56035 +CT: 9885d7a11004ec546955fb7a8c77ae57588fa2e7fedcc8e9000123495b9016d1a101fec1e6724302e93eb8e01bd05efbe8502eb97b1064bafa9bba5658b1677819cec4998dbf02df1f1eef51bb3e75c19f570efdda98b0b8dc5dd9250eae8396090ca9ebecdb90f32c5e2085e86b64e57464d251af62d9f8c01d7bd6cec5f9dfa5eb7c4cd412077571bd071a4eff5098883940d63b917c08bf373916cccd7a446abff0aa5c687518703c25cd8d3c5d724f348e20be54f77fd18dbf6344d1d25c788ccb5a5747d575435829b1825e31f9e94abc33c0d2750fb62ae167a7a74fc9e39db620d43e0b8514d5f70a647e53dd5764254b7785b1519474 +TAG: 936072d637b12b0b6a4141050f4024ce + +KEY: e57e74595d230e8eae078df1dbc071c66a979a912e2252257e28447e97fc82a7 +NONCE: b613d6d5fff507e917674f2f +IN: f1ecbb2a45f04ca844616528b10ffa4d2c5d522ed4ae3366888fb371b6ee7eb4be53c8204783e43265931f58f308623f7b2733384c173540aa0bdf879fad0283c2be6c42a7b4feb2b29265fffdb518ea77d33507dbbff7d9921bd97fd27f1100402e02135f7df4b5df85f7472fa75618facca3e24d487453e831efa91242e62ee9d32880bc20f7ec016eb12edb589dc8a669f7c78375f915d7c2b03457b00ac2aceaf37c0369a85c3f6fe7c0447c022d66bb5acaee62163837a36e882cfb8579ba9182d3153a25623f339758ede5a62f67b199fc8abe235fe4b607a6804fd4d15378c76e0c26c1edf1cd637b7ea59edc66cd5ef9b8cf79b95ff89c235ab195 +AD: bf4c0737e461c1d6fc45b87175fd7833625c98a03e089c4e3d47c6b21f4bf38cb4b7666322217eb8fa022afae473df56ba3502c88cf702276bf39c6fcccf01e629925a83816a5096e612458af6380dcb7f63cfc0eae99d63475616b18b44111a1927b05503c4ce46ca48321b0f8f247a54919fc844fbabd3a2481e83bed8a5ee8086d7559db00fd1d64f4892ee9363d59829ce1e10af66696c28e86297b43190800251f346bec1b577446120529d486266a271c71011528b24ff4caf2c30f9748a2b03c788dd583541368a643075a52127c48b3b6f0c6ef413e61479c9afdbeb4bda44340ff0d81c7bc0321d3de4080cf7e108dda3fd4e480e685b202c6bfc +CT: afb2aae2dce03cb0bd3467447ef6895a132cec06b9f7764ee24d90078660dc820b8384c01375e03c20a6c688a780d7d7fbe5837d477e8f3d7ab3ab865dacb0eedb5694d3276ea914a421b03b9d4e4f586227a3af7e8d5d579bd832450f038eaa7bac57aab996df55367ddf59b338e5d370e310124e8ef43c9fe54e5d23d60023aee266054ea66c9f32170ce97998b527073fd178ed4e1752cb9c515c0b32766b363c39c513c2e9ff6d1c24807afb43af3c5a317f1536087d8576fa3be3b007d3a77ab0422303cd0b142c4ad194e1bb86471b91861235dc336dfe9666f4f2c6a32a92b8fc52b99873f9792cb359476a2aea21996d21c17ab814de4a52eeeb33 +TAG: 05906cbf531931559cf2d86c383c145e + +KEY: 847eb274561fdf0c1af8b565a92da74641f17261a0ea4cf63ba5f36ba7028192 +NONCE: a379511688390ade6f0318bb +IN: 1e588cd0636f34b656b140b591a9adafb8dc68d0abb75531942e3c6ec1d29e4f67853e3d718dbe61b733490525c7f9ce6746f8639e4d271267a95f0940b3406c67ded0aaed36374b9a4bb8c753579051c6dc3244d6126a8a97d4a912569ba139d55dd00c380e7ec450d44f6c7b9482c2594b21f61ef8d165666c830867139262be5ad3a31f44a286d7e86d4e5c9bd6118147efc8e606c522ad0e9a218aea4daa39d1653157e4c3730240fff67a42e4f34186de1c13ddcb1e44020b7a31d21ba6ba96b3f42360dd1d754a7bae75b6fdb6eb3c76412cc1fd8e900d7aacf4d897f4224f19a1d44a77e06c95eda5fe76b11c6f5088e8ca75c87e07edc64c09a6a31371552449 +AD: 331d48e814f660516f3a796b08afb1312625b3b17218819cfdbbbca4c333378b57fd93482d971992b5b15b62f0724d6e7b9beb5ddffd3c70b6f8bdd3cd826663eeb91d37734a686c987efeb4d4906b80c5378fcd07806d2dbf3eb528472a110743df8cd96b6eb67e98b13ac506c9bda167f045a412c93d78e860c9b4bbd7a2d71adbd3530f30253847b4112d4b898b520c7a14fd075e62605b05084f26fd138179c2791fd6e8d3bfbb2735002ae12d986f92d7d300fd6f1dc12c993449f8522f6f32f506a677c8a981aef9815e83019713b2f9943acc8d5b3f6f65b9e2b9a14ad2e300d636166da2d35a6a0a756a76d08709a043d65341695490124971a7574cf0b5845a +CT: fc1f0d7309e6420b42d59740c9b9d4b97075b874015251ad55483068b00f87502b18182b140db07c70a80fd884fd79b7b5fef1d307ca4db0ff046494443e1cae83478d275c31402035f1fc24e26214b78d9a4dac78d074150012f9fee810a121d87a16d8e1eec5700e9facba350029788480a259d9f30df1c2b8df7691629314391719853c0b68614134f6028865700b1fc4e7f34ff28f449c6abc3027f38d7a7f6d84b8f27f7cc5afa09478c809eec346bb58244ab42a3bef61a14ae7640d76591343983de9fe5f1b985ce56c9fcfb2e3f6220779ca6f92a6b8aa726573b38ed7663ebe4c85066ae3f488ea3309593fa41dba8efd2b8f44b9fa8f7a427823c1228093a3 +TAG: f1832022e06228c36181856325d4eb68 + +KEY: 3828b138f72f8fe793d46c55ad413bab31a51e7a9093cdd10fddb4739e28e678 +NONCE: a60413c0ab529ccf3de58468 +IN: fec017c1c51da5ce9dcd8e84cdc03a43145b31edfd039c7c85d8811a2f58efe7a2d7590149a98cf0b5af82d3e0a325223bc9d5585ceb1afc4cdd96024be6c8064c2abac14f68e65de49e25e3e967500ce5b4504d00a9cbad1e86bbdcf65c01a7a92de27583b7b92122b6a4923b7192994a1edf00b75d14a982f92559dbc2d5e427a75ad29715375d90193ddbb39b9a52c1a23d75629c539e0a6ce822c7c08fc77dcd3adc357893215df4694673a16d34513de21217ce86897c8f0575d213ce0c66eb1d1985fe73dd86da3ab5e89df4243e1be9dd95af94f878995d02929ee42a062100d6d4d3884730f54593d5ff7b7ae53e03d4f0e10f6f4c3077206499ab7d4de1e825d532d0918f +AD: e2b16ff2b6c73c9374704ffb4cdfe7bad9eeee32157f2eedf427f99c2cce80c5aa4d9145e85af0cb08e6ed477cbe79ee168ded5c0895f9f4f939c21916b3dd5c9d268b3aabdefb85d953bce9b70732fc9acf6c7b727f78d8c9aaca9e022d7cf0f95583e81744227d87fa34ae19de44d202ba01e3d03993f38c9b2fb00b54dfb677d67e6f5a15f46c29eb5597ae3d5384b37bbeca3f3d825e2b7cceaaeb36a8c1273062259608956dd0c79877cc460d0268de27355e34b9d8d1188c062ac5e10a73f2d70fd0636304b3de06cffeedd246e2db19b8b66785f9f9c62b8f0198f29d37a4ab5280f4aa0320559810f89a1618844d0ad5f3a4f5a0e834ab31e56798b7158217f834d372c36f +CT: 88ea11ef6b6ee6fb0be77bcbf227e77508922550ef0d7534bf05668ae5fcab2f4defe643747716e7e000950e36c6cb24b79987389a150382c091d39ddf841b0a5e31d763d9c59753a3ef36a23b81f38e6e715357395ce715d30c14d6ab5b7454804ecf633daa39b6107f562fae6a646efb25c1119dd17955bb9e640105a21566345408f72f2acc8f2726a0be465551f9ae566da559fc0b92c36764c5ca20a18a316c02e606030a53450e7ae1146050a48a64c600d33cb84389b0bdac7ff45d3d1f2f669a6e365ef722d76d2fe9bef2df93c58bbdd6965e18111b5de0f4a62dbb874161bf8adfa61e9cdecd97b4fff668b3efeb3e32eeb929cf58d94ad8077c0a2ca79e80877c5d9329 +TAG: 9b47afc5816b7229213cd3c9135545ed + +KEY: 91ea63dc27d9d6bbc279ec6cecdce6c45ff0b247cfb8e26b6ab15f9b63b031a4 +NONCE: 80a134fac73eca30459d5964 +IN: a848e41c77ac8c733370435b5b6a9960af36031e96260d5703ce15b003606875a7901cd11e4571bf88dda29a627c0b98065a8b4e6d382852dfa4f47d86fa08e48ad8f5a98e55c305900b83200d44029f304abd21e0264115192a3fd7b0eb69b9f8ca7865b3be93f4ba5a28468fd7bbb584c32ae867f5146efbeb1412d3ac36c30cb308c327a6f207e30f561d6efe0a535446c693e14176e9e714ffb5a5b1075812909a362a6c4bbe18322e15690c2c9cf5a18e0120c11551cb7055b5aee97e7a56d7c24fdf1214641c8eacb196d74f3d96a7fbecdd4fe52dc7b6ead9041cafd5a3fdf91fd3614e63189b488d4d7c1ea3c6351d112a2223b29d390ac3ab7f09a60bbd3df6e0d606d902aa44244334 +AD: 47940a0694183b2fcb5e760c9ef6dbe4cbff6ccf33208337a981138f9d35c03f8adbd810e94636acaebef6791b531a65e99b03fc78e7eb48036615874e97cf762fa6ca5d880bb2c2f644f1aed70c667880f98834d501caa277cb8ef1095ff882e79c3a92ea8982abebf63ea9ed7e9a24d32cb81d5d98e891974e3d636a59e165984e00f05a040d33f07b39eccb924fb24780a422a6b2b7bddb5b316beddcf6fad20e4cee7d0141c2f7c4e4f759db8691dc7b8525ccbc3ee6071a2ead63e750d6d92dde7eb1303d5b1194702b6c3e0c2e6f9649e60eeddec9c1f71cf309af0672cd2ffcf94ba7e6c3d7cee020a224a9a956274d1d36ba16030e215d90a165756666eff066a8e51bf7d4babe8b7d8d +CT: b90449af99327afb1124bb24f1c8b5cb878423b0370d5f7cd297b28cc4135ee77d6f1913a221cfeee119bafa873072bfa79e303fe377bbed05add41ce3a42ca4632b98f40a36227de1a9ba84d6176c01eca9d33d954d0ebdf4e40f136e0f6a56156fbb33b344a8a433941fd6e08774bd00075aedb0e396c2bc37d1250541248dbeb899e1b5170cdfeaf7b89995b049428bb277c501354f8cd48fb58f6f04f956dfd099c48778dbdbb4c95b7c9d6797cf6d3bcd1d00e88cea885ee4a10d94356509e148990a0e10dd89103a9d5c8434a7bdbed6c0ac1271e0709eba144abf3cf075c020e9f7835d5a98fb2439b399e377ae6e19fc5f32df9ddfb9e936190d3e9c62de99835249d1f32ca3f92ecd44 +TAG: 6ccaf7c142d86b83e4d0b4289b49c4d4 + +KEY: 1344db082889367fd48c5f06bc39f9cb9e3ad4b92fa484ccf49418dd4caa2e19 +NONCE: c04a98e7e29326b5330818d4 +IN: b0e12e3122c1ebfdcadded5a45163a6208548e9bdf95cfd18ea504e5d2e97372e58dbfe460a57b724d38f3bc0ce02a54015779bcf127343474d7d4c1402d598bee56897203b903da5b819e2218bd0d1a2af11c542544f02c46969cd2bfac683b76a8de61698ccba63361a1a0b570adf69d24e9a7e466873c8c12e25e0bcead7828386179a4d65d5bbdb800eb52fc01b67498d7b5f9864270162158a8572eccf541b07833f001848672098c57708eb479855799567c318b1aa097efa70db0d8a8d36fe0ac22ebcc2870baacac690a79e07ab286acad9f7a877939cf2989cd6200eb86dfa7a41e969a3683ceacc7c97d1cd5487f13c439a9777a67770687657d38267a347a0b6d3aa3cf64e7f31017246e4369da +AD: c96db14dbc2aa0ce3ac63794f75c7e78037dac6763282edb307821a7938de4baa3d2e35a8cfe0c8724c2a8d870d0a462ea157e15aacc69a3c881d9c819225ea8be479872d55e655c897936c95b9ab340820264567495fc5e4e3354f42b84e191b470ca9f4d8fc25d011bf9c9e73e1590e1bb919dd2f288b26935fbfb8c93e54331dc8edad5e1cc4aec103c2f3320d59870c1770319f105ee790b704ed655be423e63ab040f1153f41e7070ae3a0f34d217c4649c180c84814463902d99a9396f8c7c85a3a4c8ae2f01737649fae478a40fc72303a108822775e9c421f945cc0eea992730790a9aa0c0d014518dab371b52d30b5a560f34946a9344cfb8a19b09ee9b123bcb8f642780697508f04983b790dd2d +CT: ffda075dbde7b874995230e1324f17894689baaa7f1354e26100befb546ea23dc74807818e43a3cee00ec1bbb95c82180489ae5f3a1c482dec28f96ecaf5ca4655ff7f33c814197cb1973cf02a0b720a5c44068d8ddff0789fc1e7f20ef408c1a438133fce4f7a3e8c85d95a381b94e949ce47a85895c4be7cbfad468e52a160dee34b8ddeef2ab280eaaed4990ecec790ac16de3c74aac6fe2d5e28ea2b66a921c894a3971cee4a2158054c3567e0d941f867ded5ed1d21d8ab090848fb3eddfb1559bf11815db52b8eed871cfc117980f297da79da31da32de3f162a03d95090d3329da3662df29e6ec9b236e0f7c1d7d957cfd54d5efc99c694b9dece989912388254798513d881e5943ce830729a8e2ddf +TAG: 81c55fe9aa2de0d63efe3f74a3d8096f + +KEY: 31dbefe589b661af00a6fbad426e013f30f448c763f957bbcbaf9c09764f4a95 +NONCE: 147fe99bba0f606c57242314 +IN: 908bd801b70d85085dd480e1207a4a4b7ef179dac495a9befb16afe5adf7cb6f6d734882e6e96f587d38bfc080341dc8d5428a5fe3498b9d5faa497f60646bcb1155d2342f6b26381795daeb261d4ab1415f35c6c8ac9c8e90ea34823122df25c6ddae365cc66d92fc2fe2941f60895e00233b2e5968b01e2811c8c6f7a0a229f1c301a72715bd5c35234c1be81ef7d5cc2779e146314d3783a7aa72d87a8f107654b93cb66e3648c26fc9e4a2f0378fa178c586d096092f6a80e2e03708da72d6e4d7316c2384a522459a4ad369c82d192f6f695b0d90fcc47c6f86b8bbc6f2f4ea303aa64f5ce8b8710da62482147bcc29c8238116549256a7a011fd9c78bbb8c40e278740dc156c2cc99c3591fec2918cdeb5240fb428 +AD: 5a32d7044f003b2ffefffe5896933f4d8d64909fa03e321a1bdf063099b9f89752d72e877291d8da12340c5dd570d7d42984ffab5177824fc5483b4faf488504e6822e371dca9af541c6a97312b9cbf341b4198b0902cd2985ac10a8b5b5fe9691bb29a88344f863c980e4e871a72a8b74f92eef68c176e9d2ef037898ff567298e186af52ec62eb7429a8004ac46b945678b82859396d36d388ec3d67653aec35cf1da2684bbc6c78a5f9e3ce1b355af3b207f64e0fa73501c5d48a14638d0906c87eaa876debcf1a532c1475d80ed3d4b96458d2236eb9f67988863bc6d5c16b96b93d898683d248d7bc601b5035fc365481b89465e37a8f7dd64635e19a0282639cecde72c6b1638e0aa6e56f9c00d031cdadc59ce37e +CT: aeab9db30a579ca54195e54a9e6c787f40100c6d12ceee35643f36ae45f618cc9bb66aa4c0fae0ec2686cb4101a5b23a46877460c7e020b38b0d8d1f533ecfa99df03d346bc854a578276d7d5685ad1fb03655683a64aae4159c9efa6781f053057e0811226c7c533967a94587f4025353b28cc3a2ce5763783b4c31e7818b8ad9195bc03be8f294f9f6ceac578f9d30b22b1f5a68d647d46cf6db4a9c3a8a5c06fa97c9efb4578f501ea96db1f40942e3f24c44a7e4070a6b931c39947d9692930b67767357015de51a39e46fff94b6019e4bc1ad9d216a571ba0dc88859c49d2c487ca657384e49b4d382d86a60c8d5195320909c4e82fc077a3b22bd4eccf0f067e66ec78eed642b2d16f0f304f60f1d9ba69e205c982 +TAG: 17ca09e3084504fc22e914ee28312c8e + +KEY: 0ecc44c9036961fba57c841ace4ca3c547c51d9f126567bf41626765cfcbd53b +NONCE: aa98b6ddff7e4b2041f29d70 +IN: e49a2a5713f507bfa00c140dfbefc0c43e37bcb932e0741db03f0055da61cd837b6e2d8f99115d70750fb23685a17121b52e98a37c87204e0207729fd9219d11a48e57970d790338793cf329f7b239512a44dd4409fe9d157f92123dfc5cba24af106442644dedda87e1d9e95fd395f2f0ad8f7d27f313e6ce1a07d9845dec5ad732e6e4749b3a161527c8ce42331f5de1d700650072fb68e9c7645a0e0e529d0563d2727e3fb38ed341f74ef1ad95a0216a440e1384d0e7ef71cde38cecdc9e2b2d563f19014c40c1f92ea0af3b4f6da9146d433ae85f647153db326a28ef6ea2e0ebac0cc1aff157067c7dba7cc4317d56920ee9deab5764368e7e5b3ce8bebd0fa129f869b15897c09659c53188bf8efb7b6ac7d265c9b85fe96166 +AD: df41db4ef5350d4afcaa88b4a577b3370b96699bbd73e59aeebca6ea856cf22694a9399ae7f97a3bec226d82f5598f8949dfb92530dcfe77770f066f2af988fba5543b8ba7655bc43f8dca032981a34a1beff695c6908169d475c55b2119fe5578623f68a9dd85b653656881b0db4006d3336fdfc784d1805e48ff478fdc196601f044c9d33fca3ddde2db0102f90fff0b370f520e00e3786c2a9b0b4a9a7ea6f9d866f77d870c8ef0f3a8bedef17949a32598512af665679dfbe71e1c3efc3dee8f5d4499e20dc63281191751f67e51f201973a6675896484527d66bed94d6aaceff65fbc4192cec19452b8873f22d72bf2f4981fe656285cb24be5c58e77dafd3e096166b230f18d3f4197fe16f6ec84c060ce0793ae6848311a18b7 +CT: b15b2bc4b9e8ecc5d9c4a6359a805b7590bdb4bfaa9b3fc4d7676d721edc4b3b1ef71b18a3d78f1b31a477cf25e55b278eb3ed774805ae8e5a2a0204f7291d9587663c4d8b1b744154f3b7cef796e0b91590161f3bde82f1d8139cb8d017606ae6d0552ba144788fd8caf435ab09a43a1f4057776af49bad98fc35cefefb159cfebfed76f2e4d18b7be143677ff8b3d6e2b440fe68475b5a1193bcd19ab157d0d2257f33de8e50091ea3388648c3410aa68c830566a0413d92454e4eff433c3edc74e8f7516ec17b2c01cf57a2d7c48db97b706b8d7da0b68051f2d6a87c417f46cf217a48611980890f669d39b478c35d834ed2c79299df2381a1215d6db303cb63e2795fe517649874226e0a6dbfe2c86370b9fbdd8c5de349bfa25f +TAG: 7082c7ef72c82d23e0ba524132acd208 + +KEY: c05dc14b5def43f2e8f86c3008ef44e4dc6513768812e9218b2b216818c4cec6 +NONCE: 5cfe0dca6e599ed9aa89ba97 +IN: 8a06e2997b8e5f8040b22e07978c83c48d0f90bd2b2f8b426b43feea0b614d3b0681745ea4224cabcaa25ca45c3053a6300c47ffa4f72e838db135ae35c27939aad4cf7f75fb61daa3148d869057598e4e8b44c6fb19b0d9281e18676d8bc137489bb77a51a3a8f807a896d558f00040e8729ea9bbdc7db6102c8b99c8a1eacb0735577bc6533cd1d8147013935b6344116090a1bdef1f2e38a877a50c8fc0f394bafede31375c57476ba06d95ae734e6dae771a32e5091dff71d845c5f7385b9b9069ced12fcfea34a510880b088bb0016e94a5932c89baee038cbafbf06b3d09426afd2d5dd5e392636362e9ffa9186b5c753eb84f82f68fb1286ed06c58a5a936cad018ebc4269037b49f2ea0349373adea99f06062e5dbb0bf94f2883f5c0556 +AD: f2a3f7af8ea984bbd85953f14202c6e478f98d0bcaacd414329ec480d0c29fb4c1a052d3228c883928448f0bef12cee5b69829b4a3eb4680084131867cfc3d3af84fcc0d80c2292d3fe02405634f6cfb20b0fb90345da3a557fb30582175c32e432be66ad096f9425ff4060df54d6741fd6567a1e2fc5f6f3ed95cefc806ff64ae91ae82920b5c829ea026f83fd90d760e240da3c9ddaafe4d08507f4af1049056dc6d09657779a3dbd889d851e97d4ac60dc66df2d24979ba8947a7890a304bb301d0d42b67824e0c68fc882e90cb6deee50c2e3d9f0da59ab23c997b05635a0d56c71fc39aa0e6b19c43a7fe12d4e4145453cd7fbd8a3f33bf5451addf05052df7ef044a33513bc5f1a4cfc8b68015664bb5c8e4bf54a85efff109ee96af75d4a5 +CT: 2cf630548d6f2b449057c7861920308958199f77b123a142c6b7c89c4982f4ed0efa2fe899914ddbf4543e70865a5e683b0721d6c8443df2e697acf31e11c8809aba94196409020a7c64d396fe136826455aec973af23a6c7733cb567f5ea550e50e0b796623a97807d042855568e3c568990cfc818c31a1bf415337f43e9baed57fada2fb2ad3c3543f2b7f2777e03f84040c1c854c310ab1cc5dc7f2a5fb213af79ac068b46c7d9475bea126adf079e2100bb57904a931faf248e0f7d5832ca83ea8a283e0136979737132afb1f4ab38d307ac0774814f4d5ecdc4aad79185c05f8a706f579b78f2c1c7004cb38e6cd22c2080735b34c3f6134955ed3bc36b1ad5c8e33209c9f3c658fb07b59b6002b2526cd8d853a5c624b7108573d7df60c827 +TAG: 3dcdabcd1c82002a551cea41921570e5 + +KEY: b33f449deccc2ef0d7616f22b4a00fcd84c51a8383782f66f1696bc6405005ee +NONCE: 6afa8baf923f986b5779ac6a +IN: b0af85a6deae5fcaa94778bce015ce2da7400ab768f3e114cc1b645fb2716789e2aeb96894fda6da5bc24fcf2466124720d6ba99e5475d77e5bcf2c2f8c8e5becf5eb73ad650861bbdeb51ba5ee789c227478934200fc18f36e4fe392c99d4c3fe0b38b40d2e84f831b8ef9bce9ac1362c755943521ecf5b5cf8fbcdf08f2d47ff7cd62838597dd342695a1b037bcede69500bf70bf1edbb40a17b44695bd8ff8bc8664b3211a6bbfdcbd1bffbfb1a2ea0141cfbc6ac841c803b137be5eeb2666c46c09cc1c4fa82be43bfd56e7a2b8ceeecb6efc1933a90213a0e1bc7aca2af35f2d1dad5f0d9002561064a699f1ce76c39d9c2224ae596e88a1517e19c2115370768d50107f3f2a55051838ae5897acf2ac0814ccd864eee2f6b5d7a6728c6ac6e6a57327102 +AD: 2134f74e882a44e457c38b6580cd58ce20e81267baeb4a9d50c41ababc2a91ddf300c39963643d3c0797b628c75a5fc39c058d319e7d6deb836334dbe8e1fe3cc5704b90c712e1fb60a3c8b58d474a73d65fae886394f8b2c029e420b923f2af4d54c9de3c7fa2bccaa1e96664ccf681cacbbf9845069a4bfd6c135c4392d7d6be338eca414e3a45f50510718e2a5a3e5815eafa0c50172cf5f147510645d2269929843bbbab682deb5823d4cdf42bd250bdbd20c43e2919d7a6e48973f43a4cab73454b97cdca96721ebd83b6dbaaec7e12cf0dae678a57c431b81421657037dd47dccbee73a41f56495fd7c25c75744fe8f55cbd1eac4a174d8f7dd6f6ba57b3e53449a9ce7806517e3e07cf6546a0fa62c7b1fa244d42eee64a3182461792edb628e567b23a +CT: 0fe35823610ea698aeb5b571f3ebbaf0ac3586ecb3b24fcc7c56943d4426f7fdf4e4a53fb430751456d41551f8e5502faa0e1ac5f452b27b13c1dc63e9231c6b192f8dd2978300293298acb6293459d3204429e374881085d49ed6ad76f1d85e3f6dd5455a7a5a9d7127386a30f80658395dc8eb158e5ca052a7137feef28aa247e176cceb9c031f73fb8d48139e3bdb30e2e19627f7fc3501a6d6287e2fb89ad184cefa1774585aa663586f289c778462eee3cd88071140274770e4ed98b9b83cd4fa659fcdd2d1fde7e58333c6cf7f83fe285b97ad8f276a375fafa15f88e6167f5f2bfb95af1aefee80b0620a9bc09402ab79036e716f0c8d518ae2fa15094f6ea4c5e8b283f97cc27f2f1d0b6367b4b508c7bad16f1539325751bd785e9e08cd508bdb3b84 +TAG: 1976d7e121704ce463a8d4fe1b93d90f + +# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: "" +CT: "" +AD: "" +TAG: 530f8afbc74536b9a963b4f1c4cb738b + +KEY: 0000000000000000000000000000000000000000000000000000000000000000 +NONCE: 000000000000000000000000 +IN: 00000000000000000000000000000000 +CT: cea7403d4d606b6e074ec5d3baf39d18 +AD: "" +TAG: d0d1c8a799996bf0265b98b5d48ab919 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad +AD: "" +TAG: b094dac5d93471bdec1a502270e3cc6c + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbaddecaf888 +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 76fc6ece0f4e1768cddf8853bb2d551b + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: cafebabefacedbad +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: 3a337dbf46a792c45e454913fe2ea8f2 + +KEY: feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +NONCE: 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b +IN: d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +CT: 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f +AD: feedfacedeadbeeffeedfacedeadbeefabaddad2 +TAG: a44a8266ee1c8eb0c8b5d4cf5ae9f19a + diff --git a/tests/aes_test.c b/tests/aes_test.c new file mode 100644 index 0000000..37bee05 --- /dev/null +++ b/tests/aes_test.c @@ -0,0 +1,979 @@ +/* $OpenBSD: aes_test.c,v 1.3 2023/09/28 08:21:43 tb Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct aes_test { + const int mode; + const uint8_t key[64]; + const uint8_t iv[64]; + const int iv_len; + const uint8_t in[64]; + const int in_len; + const uint8_t out[64]; + const int out_len; + const int padding; +}; + +static const struct aes_test aes_tests[] = { + /* ECB - Test vectors from FIPS-197, Appendix C. */ + { + .mode = NID_aes_128_ecb, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .in_len = 16, + .out = { + 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a, + }, + .out_len = 16, + }, + { + .mode = NID_aes_192_ecb, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + }, + .in = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .in_len = 16, + .out = { + 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91, + }, + .out_len = 16, + }, + { + .mode = NID_aes_256_ecb, + .key = { + 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, + }, + .in = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }, + .in_len = 16, + .out = { + 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89, + }, + .out_len = 16, + }, + + /* CBC - Test vectors from RFC 3602 */ + { + .mode = NID_aes_128_cbc, + .key = { + 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, + 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06, + }, + .iv = { + 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, + 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41, + }, + .iv_len = 16, + .in = { + 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, + 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67, + }, + .in_len = 16, + .out = { + 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, + 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a, + }, + .out_len = 16, + }, + { + .mode = NID_aes_128_cbc, + .key = { + 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, + 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a, + }, + .iv = { + 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, + 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58, + }, + .iv_len = 16, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, + 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, + 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, + 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1, + }, + .out_len = 32, + }, + { + .mode = NID_aes_128_cbc, + .key = { + 0x6c, 0x3e, 0xa0, 0x47, 0x76, 0x30, 0xce, 0x21, + 0xa2, 0xce, 0x33, 0x4a, 0xa7, 0x46, 0xc2, 0xcd, + }, + .iv = { + 0xc7, 0x82, 0xdc, 0x4c, 0x09, 0x8c, 0x66, 0xcb, + 0xd9, 0xcd, 0x27, 0xd8, 0x25, 0x68, 0x2c, 0x81, + }, + .iv_len = 16, + .in = { + 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x20, 0x34, 0x38, 0x2d, 0x62, 0x79, 0x74, + 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x20, 0x28, 0x65, 0x78, 0x61, 0x63, 0x74, + 0x6c, 0x79, 0x20, 0x33, 0x20, 0x41, 0x45, 0x53, + 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x29, + }, + .in_len = 48, + .out = { + 0xd0, 0xa0, 0x2b, 0x38, 0x36, 0x45, 0x17, 0x53, + 0xd4, 0x93, 0x66, 0x5d, 0x33, 0xf0, 0xe8, 0x86, + 0x2d, 0xea, 0x54, 0xcd, 0xb2, 0x93, 0xab, 0xc7, + 0x50, 0x69, 0x39, 0x27, 0x67, 0x72, 0xf8, 0xd5, + 0x02, 0x1c, 0x19, 0x21, 0x6b, 0xad, 0x52, 0x5c, + 0x85, 0x79, 0x69, 0x5d, 0x83, 0xba, 0x26, 0x84, + }, + .out_len = 48, + }, + { + .mode = NID_aes_128_cbc, + .key = { + 0x56, 0xe4, 0x7a, 0x38, 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, 0xba, 0x29, 0x03, 0x49, + }, + .iv = { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + }, + .iv_len = 16, + .in = { + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + }, + .in_len = 64, + .out = { + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }, + .out_len = 64, + }, + + /* CBC - Test vectors from NIST SP 800-38A */ + { + .mode = NID_aes_128_cbc, + .key = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, + 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, + 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, + 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, + 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7, + }, + .out_len = 64, + }, + { + .mode = NID_aes_192_cbc, + .key = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, + 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, + 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, + 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a, + 0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0, + 0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0, + 0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81, + 0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd, + }, + .out_len = 64, + }, + { + .mode = NID_aes_256_cbc, + .key = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, + 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, + 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, + 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d, + 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, + 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61, + 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, + 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b, + }, + .out_len = 64, + }, + + /* CFB128 - Test vectors from NIST SP 800-38A */ + { + .mode = NID_aes_128_cfb128, + .key = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, + 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, + 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b, + 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, + 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf, + 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, + 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6, + }, + .out_len = 64, + }, + { + .mode = NID_aes_192_cfb128, + .key = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, + 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, + 0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a, + 0x2e, 0x1e, 0x8a, 0x1d, 0xd5, 0x9b, 0x88, 0xb1, + 0xc8, 0xe6, 0x0f, 0xed, 0x1e, 0xfa, 0xc4, 0xc9, + 0xc0, 0x5f, 0x9f, 0x9c, 0xa9, 0x83, 0x4f, 0xa0, + 0x42, 0xae, 0x8f, 0xba, 0x58, 0x4b, 0x09, 0xff, + }, + .out_len = 64, + }, + { + .mode = NID_aes_256_cfb128, + .key = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, + 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, + 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, + 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b, + 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, + 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9, + 0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, + 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71, + }, + .out_len = 64, + }, + + /* OFB128 - Test vectors from NIST SP 800-38A */ + { + .mode = NID_aes_128_ofb128, + .key = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, + 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e, + }, + .out_len = 64, + }, + { + .mode = NID_aes_192_ofb128, + .key = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, + 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a, + }, + .out_len = 64, + }, + { + .mode = NID_aes_256_ofb128, + .key = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4, + }, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .iv_len = 16, + .in = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, + }, + .in_len = 64, + .out = { + 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, + 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84, + }, + .out_len = 64, + }, +}; + +#define N_AES_TESTS (sizeof(aes_tests) / sizeof(aes_tests[0])) + +static int +aes_ecb_test(size_t test_number, const char *label, int key_bits, + const struct aes_test *at) +{ + AES_KEY key; + uint8_t out[64]; + + if (at->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + AES_set_encrypt_key(at->key, key_bits, &key); + AES_ecb_encrypt(at->in, out, &key, 1); + + if (memcmp(at->out, out, at->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + label, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + AES_set_decrypt_key(at->key, key_bits, &key); + AES_ecb_encrypt(at->out, out, &key, 0); + + if (memcmp(at->in, out, at->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + label, test_number); + return 0; + } + + return 1; +} + + +static int +aes_cbc_test(size_t test_number, const char *label, int key_bits, + const struct aes_test *at) +{ + AES_KEY key; + uint8_t out[64]; + uint8_t iv[16]; + + if (at->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, at->iv, at->iv_len); + AES_set_encrypt_key(at->key, key_bits, &key); + AES_cbc_encrypt(at->in, out, at->in_len, &key, iv, 1); + + if (memcmp(at->out, out, at->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + label, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, at->iv, at->iv_len); + AES_set_decrypt_key(at->key, key_bits, &key); + AES_cbc_encrypt(at->out, out, at->out_len, &key, iv, 0); + + if (memcmp(at->in, out, at->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + label, test_number); + return 0; + } + + return 1; +} + +static int +aes_evp_test(size_t test_number, const struct aes_test *at, const char *label, + int key_bits, const EVP_CIPHER *cipher) +{ + EVP_CIPHER_CTX *ctx; + uint8_t out[64]; + int in_len, out_len, total_len; + int i; + int success = 0; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_new failed\n", + label, test_number); + goto failed; + } + + /* EVP encryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_EncryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, at->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_EncryptInit(ctx, NULL, at->key, at->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < at->in_len;) { + in_len = arc4random_uniform(at->in_len / 2); + if (in_len > at->in_len - i) + in_len = at->in_len - i; + + if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len, + at->in + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_EncryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_EncryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != at->out_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP encryption length mismatch " + "(%d != %d)\n", label, test_number, total_len, at->out_len); + goto failed; + } + + if (memcmp(at->out, out, at->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP encryption mismatch\n", + label, test_number); + goto failed; + } + + /* EVP decryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_DecryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, at->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_DecryptInit(ctx, NULL, at->key, at->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < at->out_len;) { + in_len = arc4random_uniform(at->out_len / 2); + if (in_len > at->out_len - i) + in_len = at->out_len - i; + + if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len, + at->out + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DecryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != at->in_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP decryption length mismatch\n", + label, test_number); + goto failed; + } + + if (memcmp(at->in, out, at->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP decryption mismatch\n", + label, test_number); + goto failed; + } + + success = 1; + + failed: + EVP_CIPHER_CTX_free(ctx); + return success; +} + + +static int +aes_key_bits_from_nid(int nid) +{ + switch (nid) { + case NID_aes_128_ecb: + case NID_aes_128_cbc: + case NID_aes_128_cfb128: + case NID_aes_128_ofb128: + case NID_aes_128_gcm: + case NID_aes_128_ccm: + return 128; + case NID_aes_192_ecb: + case NID_aes_192_cbc: + case NID_aes_192_cfb128: + case NID_aes_192_ofb128: + case NID_aes_192_gcm: + case NID_aes_192_ccm: + return 192; + case NID_aes_256_ecb: + case NID_aes_256_cbc: + case NID_aes_256_cfb128: + case NID_aes_256_ofb128: + case NID_aes_256_gcm: + case NID_aes_256_ccm: + return 256; + default: + return -1; + } +} + +static int +aes_cipher_from_nid(int nid, const char **out_label, + const EVP_CIPHER **out_cipher) +{ + switch (nid) { + /* ECB */ + case NID_aes_128_ecb: + *out_label = SN_aes_128_ecb; + *out_cipher = EVP_aes_128_ecb(); + break; + case NID_aes_192_ecb: + *out_label = SN_aes_192_ecb; + *out_cipher = EVP_aes_192_ecb(); + break; + case NID_aes_256_ecb: + *out_label = SN_aes_256_ecb; + *out_cipher = EVP_aes_256_ecb(); + break; + + /* CBC */ + case NID_aes_128_cbc: + *out_label = SN_aes_128_cbc; + *out_cipher = EVP_aes_128_cbc(); + break; + case NID_aes_192_cbc: + *out_label = SN_aes_192_cbc; + *out_cipher = EVP_aes_192_cbc(); + break; + case NID_aes_256_cbc: + *out_label = SN_aes_256_cbc; + *out_cipher = EVP_aes_256_cbc(); + break; + + /* CFB128 */ + case NID_aes_128_cfb128: + *out_label = SN_aes_128_cfb128; + *out_cipher = EVP_aes_128_cfb128(); + break; + case NID_aes_192_cfb128: + *out_label = SN_aes_192_cfb128; + *out_cipher = EVP_aes_192_cfb128(); + break; + case NID_aes_256_cfb128: + *out_label = SN_aes_256_cfb128; + *out_cipher = EVP_aes_256_cfb128(); + break; + + /* OFB128 */ + case NID_aes_128_ofb128: + *out_label = SN_aes_128_ofb128; + *out_cipher = EVP_aes_128_ofb(); + break; + case NID_aes_192_ofb128: + *out_label = SN_aes_192_ofb128; + *out_cipher = EVP_aes_192_ofb(); + break; + case NID_aes_256_ofb128: + *out_label = SN_aes_256_ofb128; + *out_cipher = EVP_aes_256_ofb(); + break; + + /* GCM */ + case NID_aes_128_gcm: + *out_label = SN_aes_128_gcm; + *out_cipher = EVP_aes_128_gcm(); + break; + case NID_aes_192_gcm: + *out_label = SN_aes_192_gcm; + *out_cipher = EVP_aes_192_gcm(); + break; + case NID_aes_256_gcm: + *out_label = SN_aes_256_gcm; + *out_cipher = EVP_aes_256_gcm(); + break; + + /* CCM */ + case NID_aes_128_ccm: + *out_label = SN_aes_128_ccm; + *out_cipher = EVP_aes_128_ccm(); + break; + case NID_aes_192_ccm: + *out_label = SN_aes_192_ccm; + *out_cipher = EVP_aes_192_ccm(); + break; + case NID_aes_256_ccm: + *out_label = SN_aes_256_ccm; + *out_cipher = EVP_aes_256_ccm(); + break; + + /* Unknown */ + default: + return 0; + } + + return 1; +} + +static int +aes_test(void) +{ + const struct aes_test *at; + const char *label; + const EVP_CIPHER *cipher; + int key_bits; + size_t i; + int failed = 1; + + for (i = 0; i < N_AES_TESTS; i++) { + at = &aes_tests[i]; + key_bits = aes_key_bits_from_nid(at->mode); + if (!aes_cipher_from_nid(at->mode, &label, &cipher)) + goto failed; + + switch (at->mode) { + /* ECB */ + case NID_aes_128_ecb: + case NID_aes_192_ecb: + case NID_aes_256_ecb: + if (!aes_ecb_test(i, label, key_bits, at)) + goto failed; + break; + + /* CBC */ + case NID_aes_128_cbc: + case NID_aes_192_cbc: + case NID_aes_256_cbc: + if (!aes_cbc_test(i, label, key_bits, at)) + goto failed; + break; + + /* CFB128 */ + case NID_aes_128_cfb128: + case NID_aes_192_cfb128: + case NID_aes_256_cfb128: + /* XXX - CFB128 non-EVP tests */ + break; + + /* OFB128 */ + case NID_aes_128_ofb128: + case NID_aes_192_ofb128: + case NID_aes_256_ofb128: + /* XXX - OFB128 non-EVP tests */ + break; + + /* GCM */ + case NID_aes_128_gcm: + case NID_aes_192_gcm: + case NID_aes_256_gcm: + /* GCM is EVP-only */ + break; + + /* CCM */ + case NID_aes_128_ccm: + case NID_aes_192_ccm: + case NID_aes_256_ccm: + /* XXX - CCM non-EVP tests */ + break; + + /* Unknown */ + default: + fprintf(stderr, "FAIL: unknown mode (%d)\n", + at->mode); + goto failed; + } + + if (!aes_evp_test(i, at, label, key_bits, cipher)) + goto failed; + } + + failed = 0; + + failed: + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= aes_test(); + + return failed; +} + diff --git a/tests/aes_wrap.c b/tests/aes_wrap.c new file mode 100644 index 0000000..2b61ae3 --- /dev/null +++ b/tests/aes_wrap.c @@ -0,0 +1,187 @@ +/* $OpenBSD: aes_wrap.c,v 1.5 2021/04/04 20:40:48 tb Exp $ */ +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. + */ +/* ==================================================================== + * Copyright (c) 2008 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include +#include + +#include + +int AES_wrap_unwrap_test(const unsigned char *, int, const unsigned char *, + const unsigned char *, const unsigned char *, int); + +int +AES_wrap_unwrap_test(const unsigned char *kek, int keybits, + const unsigned char *iv, const unsigned char *eout, + const unsigned char *key, int keylen) +{ + unsigned char *otmp = NULL, *ptmp = NULL; + int r, ret = 0; + AES_KEY wctx; + + otmp = malloc(keylen + 8); + ptmp = malloc(keylen); + if (otmp == NULL || ptmp == NULL) + goto err; + if (AES_set_encrypt_key(kek, keybits, &wctx)) + goto err; + r = AES_wrap_key(&wctx, iv, otmp, key, keylen); + if (r <= 0) + goto err; + + if (eout && memcmp(eout, otmp, keylen)) + goto err; + + if (AES_set_decrypt_key(kek, keybits, &wctx)) + goto err; + r = AES_unwrap_key(&wctx, iv, ptmp, otmp, r); + if (r <= 0) + goto err; + + if (memcmp(key, ptmp, keylen)) + goto err; + + ret = 1; + +err: + free(otmp); + free(ptmp); + + return ret; +} + +int +main(int argc, char **argv) +{ + static const unsigned char kek[] = { + 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 + }; + + static const unsigned char key[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + + static const unsigned char e1[] = { + 0x1f, 0xa6, 0x8b, 0x0a, 0x81, 0x12, 0xb4, 0x47, + 0xae, 0xf3, 0x4b, 0xd8, 0xfb, 0x5a, 0x7b, 0x82, + 0x9d, 0x3e, 0x86, 0x23, 0x71, 0xd2, 0xcf, 0xe5 + }; + + static const unsigned char e2[] = { + 0x96, 0x77, 0x8b, 0x25, 0xae, 0x6c, 0xa4, 0x35, + 0xf9, 0x2b, 0x5b, 0x97, 0xc0, 0x50, 0xae, 0xd2, + 0x46, 0x8a, 0xb8, 0xa1, 0x7a, 0xd8, 0x4e, 0x5d + }; + + static const unsigned char e3[] = { + 0x64, 0xe8, 0xc3, 0xf9, 0xce, 0x0f, 0x5b, 0xa2, + 0x63, 0xe9, 0x77, 0x79, 0x05, 0x81, 0x8a, 0x2a, + 0x93, 0xc8, 0x19, 0x1e, 0x7d, 0x6e, 0x8a, 0xe7 + }; + + static const unsigned char e4[] = { + 0x03, 0x1d, 0x33, 0x26, 0x4e, 0x15, 0xd3, 0x32, + 0x68, 0xf2, 0x4e, 0xc2, 0x60, 0x74, 0x3e, 0xdc, + 0xe1, 0xc6, 0xc7, 0xdd, 0xee, 0x72, 0x5a, 0x93, + 0x6b, 0xa8, 0x14, 0x91, 0x5c, 0x67, 0x62, 0xd2 + }; + + static const unsigned char e5[] = { + 0xa8, 0xf9, 0xbc, 0x16, 0x12, 0xc6, 0x8b, 0x3f, + 0xf6, 0xe6, 0xf4, 0xfb, 0xe3, 0x0e, 0x71, 0xe4, + 0x76, 0x9c, 0x8b, 0x80, 0xa3, 0x2c, 0xb8, 0x95, + 0x8c, 0xd5, 0xd1, 0x7d, 0x6b, 0x25, 0x4d, 0xa1 + }; + + static const unsigned char e6[] = { + 0x28, 0xc9, 0xf4, 0x04, 0xc4, 0xb8, 0x10, 0xf4, + 0xcb, 0xcc, 0xb3, 0x5c, 0xfb, 0x87, 0xf8, 0x26, + 0x3f, 0x57, 0x86, 0xe2, 0xd8, 0x0e, 0xd3, 0x26, + 0xcb, 0xc7, 0xf0, 0xe7, 0x1a, 0x99, 0xf4, 0x3b, + 0xfb, 0x98, 0x8b, 0x9b, 0x7a, 0x02, 0xdd, 0x21 + }; + + int ret, nfailures = 0; + ret = AES_wrap_unwrap_test(kek, 128, NULL, e1, key, 16); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 192, NULL, e2, key, 16); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e3, key, 16); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 192, NULL, e4, key, 24); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e5, key, 24); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + ret = AES_wrap_unwrap_test(kek, 256, NULL, e6, key, 32); + if (ret == 0) + nfailures++; + fprintf(stderr, "Key test result %d\n", ret); + + return nfailures; +} diff --git a/tests/apitest.c b/tests/apitest.c new file mode 100644 index 0000000..9a58de9 --- /dev/null +++ b/tests/apitest.c @@ -0,0 +1,374 @@ +/* $OpenBSD: apitest.c,v 1.2 2023/04/14 12:38:30 tb Exp $ */ +/* + * Copyright (c) 2020, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#ifndef CERTSDIR +#define CERTSDIR "." +#endif + +const char *certs_path = CERTSDIR; + +int debug = 0; + +static int +ssl_ctx_use_ca_file(SSL_CTX *ssl_ctx, const char *ca_file) +{ + char *ca_path = NULL; + int ret = 0; + + if (asprintf(&ca_path, "%s/%s", certs_path, ca_file) == -1) + goto err; + if (!SSL_CTX_load_verify_locations(ssl_ctx, ca_path, NULL)) { + fprintf(stderr, "load_verify_locations(%s) failed\n", ca_path); + goto err; + } + + ret = 1; + + err: + free(ca_path); + + return ret; +} + +static int +ssl_ctx_use_keypair(SSL_CTX *ssl_ctx, const char *chain_file, + const char *key_file) +{ + char *chain_path = NULL, *key_path = NULL; + int ret = 0; + + if (asprintf(&chain_path, "%s/%s", certs_path, chain_file) == -1) + goto err; + if (SSL_CTX_use_certificate_chain_file(ssl_ctx, chain_path) != 1) { + fprintf(stderr, "FAIL: Failed to load certificates\n"); + goto err; + } + if (asprintf(&key_path, "%s/%s", certs_path, key_file) == -1) + goto err; + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_path, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "FAIL: Failed to load private key\n"); + goto err; + } + + ret = 1; + + err: + free(chain_path); + free(key_path); + + return ret; +} + +static SSL * +tls_client(BIO *rbio, BIO *wbio) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "client context"); + + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + + if (!ssl_ctx_use_ca_file(ssl_ctx, "ca-root-rsa.pem")) + goto failure; + if (!ssl_ctx_use_keypair(ssl_ctx, "client1-rsa-chain.pem", + "client1-rsa.pem")) + goto failure; + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "client ssl"); + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + + SSL_set_bio(ssl, rbio, wbio); + + failure: + SSL_CTX_free(ssl_ctx); + + return ssl; +} + +static SSL * +tls_server(BIO *rbio, BIO *wbio) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "server context"); + + SSL_CTX_set_dh_auto(ssl_ctx, 2); + + SSL_CTX_set_verify(ssl_ctx, + SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); + + if (!ssl_ctx_use_ca_file(ssl_ctx, "ca-root-rsa.pem")) + goto failure; + if (!ssl_ctx_use_keypair(ssl_ctx, "server1-rsa-chain.pem", + "server1-rsa.pem")) + goto failure; + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "server ssl"); + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + + SSL_set_bio(ssl, rbio, wbio); + + failure: + SSL_CTX_free(ssl_ctx); + + return ssl; +} + +static int +ssl_error(SSL *ssl, const char *name, const char *desc, int ssl_ret) +{ + int ssl_err; + + ssl_err = SSL_get_error(ssl, ssl_ret); + + if (ssl_err == SSL_ERROR_WANT_READ) { + return 1; + } else if (ssl_err == SSL_ERROR_WANT_WRITE) { + return 1; + } else if (ssl_err == SSL_ERROR_SYSCALL && errno == 0) { + /* Yup, this is apparently a thing... */ + } else { + fprintf(stderr, "FAIL: %s %s failed - ssl err = %d, errno = %d\n", + name, desc, ssl_err, errno); + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} + +static int +do_connect(SSL *ssl, const char *name, int *done) +{ + int ssl_ret; + + if ((ssl_ret = SSL_connect(ssl)) == 1) { + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + return 1; + } + + return ssl_error(ssl, name, "connect", ssl_ret); +} + +static int +do_accept(SSL *ssl, const char *name, int *done) +{ + int ssl_ret; + + if ((ssl_ret = SSL_accept(ssl)) == 1) { + fprintf(stderr, "INFO: %s accept done\n", name); + *done = 1; + return 1; + } + + return ssl_error(ssl, name, "accept", ssl_ret); +} + +typedef int (*ssl_func)(SSL *ssl, const char *name, int *done); + +static int +do_client_server_loop(SSL *client, ssl_func client_func, SSL *server, + ssl_func server_func) +{ + int client_done = 0, server_done = 0; + int i = 0; + + do { + if (!client_done) { + if (debug) + fprintf(stderr, "DEBUG: client loop\n"); + if (!client_func(client, "client", &client_done)) + return 0; + } + if (!server_done) { + if (debug) + fprintf(stderr, "DEBUG: server loop\n"); + if (!server_func(server, "server", &server_done)) + return 0; + } + } while (i++ < 100 && (!client_done || !server_done)); + + if (!client_done || !server_done) + fprintf(stderr, "FAIL: gave up\n"); + + return client_done && server_done; +} + +static int +ssl_get_peer_cert_chain_test(uint16_t tls_version) +{ + STACK_OF(X509) *peer_chain; + X509 *peer_cert; + BIO *client_wbio = NULL, *server_wbio = NULL; + SSL *client = NULL, *server = NULL; + int failed = 1; + + if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) + goto failure; + + if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) + goto failure; + + if ((client = tls_client(server_wbio, client_wbio)) == NULL) + goto failure; + if (tls_version != 0) { + if (!SSL_set_min_proto_version(client, tls_version)) + goto failure; + if (!SSL_set_max_proto_version(client, tls_version)) + goto failure; + } + + if ((server = tls_server(client_wbio, server_wbio)) == NULL) + goto failure; + if (tls_version != 0) { + if (!SSL_set_min_proto_version(server, tls_version)) + goto failure; + if (!SSL_set_max_proto_version(server, tls_version)) + goto failure; + } + + if (!do_client_server_loop(client, do_connect, server, do_accept)) { + fprintf(stderr, "FAIL: client and server handshake failed\n"); + goto failure; + } + + if (tls_version != 0) { + if (SSL_version(client) != tls_version) { + fprintf(stderr, "FAIL: client got TLS version %x, " + "want %x\n", SSL_version(client), tls_version); + goto failure; + } + if (SSL_version(server) != tls_version) { + fprintf(stderr, "FAIL: server got TLS version %x, " + "want %x\n", SSL_version(server), tls_version); + goto failure; + } + } + + /* + * Due to the wonders of API inconsistency, SSL_get_peer_cert_chain() + * includes the peer's leaf certificate when called by the client, + * however it does not when called by the server. Futhermore, the + * certificate returned by SSL_get_peer_certificate() has already + * had its reference count incremented and must be freed, where as + * the certificates returned from SSL_get_peer_cert_chain() must + * not be freed... *sigh* + */ + peer_cert = SSL_get_peer_certificate(client); + peer_chain = SSL_get_peer_cert_chain(client); + X509_free(peer_cert); + + if (peer_cert == NULL) { + fprintf(stderr, "FAIL: client got no peer cert\n"); + goto failure; + } + if (sk_X509_num(peer_chain) != 2) { + fprintf(stderr, "FAIL: client got peer cert chain with %d " + "certificates, want 2\n", sk_X509_num(peer_chain)); + goto failure; + } + if (X509_cmp(peer_cert, sk_X509_value(peer_chain, 0)) != 0) { + fprintf(stderr, "FAIL: client got peer cert chain without peer " + "certificate\n"); + goto failure; + } + + peer_cert = SSL_get_peer_certificate(server); + peer_chain = SSL_get_peer_cert_chain(server); + X509_free(peer_cert); + + if (peer_cert == NULL) { + fprintf(stderr, "FAIL: server got no peer cert\n"); + goto failure; + } + if (sk_X509_num(peer_chain) != 1) { + fprintf(stderr, "FAIL: server got peer cert chain with %d " + "certificates, want 1\n", sk_X509_num(peer_chain)); + goto failure; + } + if (X509_cmp(peer_cert, sk_X509_value(peer_chain, 0)) == 0) { + fprintf(stderr, "FAIL: server got peer cert chain with peer " + "certificate\n"); + goto failure; + } + + fprintf(stderr, "INFO: Done!\n"); + + failed = 0; + + failure: + BIO_free(client_wbio); + BIO_free(server_wbio); + + SSL_free(client); + SSL_free(server); + + return failed; +} + +static int +ssl_get_peer_cert_chain_tests(void) +{ + int failed = 0; + + fprintf(stderr, "\n== Testing SSL_get_peer_cert_chain()... ==\n"); + + failed |= ssl_get_peer_cert_chain_test(0); + failed |= ssl_get_peer_cert_chain_test(TLS1_3_VERSION); + failed |= ssl_get_peer_cert_chain_test(TLS1_2_VERSION); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + if (argc > 2) { + fprintf(stderr, "usage: %s [certspath]\n", argv[0]); + exit(1); + } + if (argc == 2) + certs_path = argv[1]; + + failed |= ssl_get_peer_cert_chain_tests(); + + return failed; +} diff --git a/tests/arc4randomforktest.c b/tests/arc4randomforktest.c new file mode 100644 index 0000000..4bc9c63 --- /dev/null +++ b/tests/arc4randomforktest.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHECK(x) assert(x) +#define CHECK_EQ(a, b) assert((a) == (b)) +#define CHECK_NE(a, b) assert((a) != (b)) +#define CHECK_GE(a, b) assert((a) >= (b)) +#define CHECK_LE(a, b) assert((a) <= (b)) + +/* Test arc4random_buf(3) instead of arc4random(3). */ +static int flagbuf; + +/* Initialize arc4random(3) before forking. */ +static int flagprefork; + +enum { + N = 4096 +}; + +typedef struct { + uint32_t x[N]; +} Buf; + +static int +isfullbuf(const Buf *buf) +{ + size_t i; + for (i = 0; i < N; i++) + if (buf->x[i]) + return (1); + return (0); +} + +static void +fillbuf(Buf *buf) +{ + if (flagbuf) { + arc4random_buf(buf->x, sizeof(buf->x)); + } else { + size_t i; + for (i = 0; i < N; i++) + buf->x[i] = arc4random(); + } +} + +static void +usage() +{ + errx(1, "usage: arc4random-fork [-bp]"); +} + +static pid_t +safewaitpid(pid_t pid, int *status, int options) +{ + pid_t ret; + do { + ret = waitpid(pid, status, options); + } while (ret == -1 && errno == EINTR); + return (ret); +} + +int +main(int argc, char *argv[]) +{ + int opt, status; + Buf *bufparent, *bufchildone, *bufchildtwo; + pid_t pidone, pidtwo; + size_t i, countone = 0, counttwo = 0, countkids = 0; + + /* Ensure SIGCHLD isn't set to SIG_IGN. */ + const struct sigaction sa = { + .sa_handler = SIG_DFL, + }; + CHECK_EQ(0, sigaction(SIGCHLD, &sa, NULL)); + + while ((opt = getopt(argc, argv, "bp")) != -1) { + switch (opt) { + case 'b': + flagbuf = 1; + break; + case 'p': + flagprefork = 1; + break; + default: + usage(); + } + } + + if (flagprefork) + arc4random(); + + bufparent = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, -1, 0); + CHECK_NE(MAP_FAILED, bufparent); + + bufchildone = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_SHARED, -1, 0); + CHECK_NE(MAP_FAILED, bufchildone); + + bufchildtwo = mmap(NULL, sizeof(Buf), PROT_READ|PROT_WRITE, + MAP_ANON|MAP_SHARED, -1, 0); + CHECK_NE(MAP_FAILED, bufchildtwo); + + pidone = fork(); + CHECK_GE(pidone, 0); + if (pidone == 0) { + fillbuf(bufchildone); + _exit(0); + } + + pidtwo = fork(); + CHECK_GE(pidtwo, 0); + if (pidtwo == 0) { + fillbuf(bufchildtwo); + _exit(0); + } + + fillbuf(bufparent); + + CHECK_EQ(pidone, safewaitpid(pidone, &status, 0)); + CHECK(WIFEXITED(status)); + CHECK_EQ(0, WEXITSTATUS(status)); + + CHECK_EQ(pidtwo, safewaitpid(pidtwo, &status, 0)); + CHECK(WIFEXITED(status)); + CHECK_EQ(0, WEXITSTATUS(status)); + + CHECK(isfullbuf(bufchildone)); + CHECK(isfullbuf(bufchildtwo)); + + for (i = 0; i < N; i++) { + countone += bufparent->x[i] == bufchildone->x[i]; + counttwo += bufparent->x[i] == bufchildtwo->x[i]; + countkids += bufchildone->x[i] == bufchildtwo->x[i]; + } + + /* + * These checks are inherently probabilistic and theoretically risk + * flaking, but there's less than a 1 in 2^40 chance of more than + * one pairwise match between two vectors of 4096 32-bit integers. + */ + CHECK_LE(countone, 1); + CHECK_LE(counttwo, 1); + CHECK_LE(countkids, 1); + + return (0); +} diff --git a/tests/asn1_string_to_utf8.c b/tests/asn1_string_to_utf8.c new file mode 100644 index 0000000..a87969d --- /dev/null +++ b/tests/asn1_string_to_utf8.c @@ -0,0 +1,134 @@ +/* $OpenBSD: asn1_string_to_utf8.c,v 1.2 2022/11/23 08:51:05 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +struct asn1_string_to_utf8_test_case { + const char *description; + const ASN1_ITEM *item; + const uint8_t der[32]; + size_t der_len; + const uint8_t want[32]; + int want_len; +}; + +static const struct asn1_string_to_utf8_test_case tests[] = { + { + .description = "hello", + .item = &ASN1_PRINTABLESTRING_it, + .der = { + 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, + }, + .der_len = 7, + .want = { + 0x68, 0x65, 0x6c, 0x6c, 0x6f, + }, + .want_len = 5, + }, + { + .description = "face with tears of joy", + .item = &ASN1_UTF8STRING_it, + .der = { + 0x0c, 0x04, 0xF0, 0x9F, 0x98, 0x82, + }, + .der_len = 6, + .want = { + 0xF0, 0x9F, 0x98, 0x82, + }, + .want_len = 4, + }, + { + .description = "hi", + .item = &ASN1_IA5STRING_it, + .der = { + 0x16, 0x02, 0x68, 0x69, + }, + .der_len = 4, + .want = { + 0x68, 0x69, + }, + .want_len = 2, + }, +}; + +const size_t N_TESTS = sizeof(tests) / sizeof(tests[0]); + +static int +asn1_string_to_utf8_test(const struct asn1_string_to_utf8_test_case *test) +{ + ASN1_STRING *str = NULL; + const unsigned char *der; + unsigned char *out = NULL; + int ret; + int failed = 1; + + der = test->der; + if ((str = (ASN1_STRING *)ASN1_item_d2i(NULL, &der, test->der_len, + test->item)) == NULL) { + warnx("ASN1_item_d2i failed"); + goto err; + } + + if ((ret = ASN1_STRING_to_UTF8(&out, str)) < 0) { + warnx("ASN1_STRING_to_UTF8 failed: got %d, want %d", ret, + test->want_len); + goto err; + } + + if (ret != test->want_len) { + warnx("ASN1_STRING_to_UTF8: got %d, want %d", ret, + test->want_len); + goto err; + } + + if (memcmp(out, test->want, test->want_len) != 0) { + warnx("memcmp failed"); + goto err; + } + + failed = 0; + err: + ASN1_STRING_free(str); + free(out); + + return failed; +} + +static int +asn1_string_to_utf8_tests(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_TESTS; i++) + failed |= asn1_string_to_utf8_test(&tests[i]); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= asn1_string_to_utf8_tests(); + + return failed; +} diff --git a/tests/asn1api.c b/tests/asn1api.c new file mode 100644 index 0000000..8d016bd --- /dev/null +++ b/tests/asn1api.c @@ -0,0 +1,415 @@ +/* $OpenBSD: asn1api.c,v 1.3 2022/07/09 14:47:42 tb Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +const long asn1_tag2bits[] = { + [0] = 0, + [1] = 0, + [2] = 0, + [3] = B_ASN1_BIT_STRING, + [4] = B_ASN1_OCTET_STRING, + [5] = 0, + [6] = 0, + [7] = B_ASN1_UNKNOWN, + [8] = B_ASN1_UNKNOWN, + [9] = B_ASN1_UNKNOWN, + [10] = B_ASN1_UNKNOWN, + [11] = B_ASN1_UNKNOWN, + [12] = B_ASN1_UTF8STRING, + [13] = B_ASN1_UNKNOWN, + [14] = B_ASN1_UNKNOWN, + [15] = B_ASN1_UNKNOWN, + [16] = B_ASN1_SEQUENCE, + [17] = 0, + [18] = B_ASN1_NUMERICSTRING, + [19] = B_ASN1_PRINTABLESTRING, + [20] = B_ASN1_T61STRING, + [21] = B_ASN1_VIDEOTEXSTRING, + [22] = B_ASN1_IA5STRING, + [23] = B_ASN1_UTCTIME, + [24] = B_ASN1_GENERALIZEDTIME, + [25] = B_ASN1_GRAPHICSTRING, + [26] = B_ASN1_ISO64STRING, + [27] = B_ASN1_GENERALSTRING, + [28] = B_ASN1_UNIVERSALSTRING, + [29] = B_ASN1_UNKNOWN, + [30] = B_ASN1_BMPSTRING, +}; + +static int +asn1_tag2bit(void) +{ + int failed = 1; + long bit; + int i; + + for (i = -3; i <= V_ASN1_NEG + 30; i++) { + bit = ASN1_tag2bit(i); + if (i >= 0 && i <= 30) { + if (bit != asn1_tag2bits[i]) { + fprintf(stderr, "FAIL: ASN1_tag2bit(%d) = 0x%lx," + " want 0x%lx\n", i, bit, asn1_tag2bits[i]); + goto failed; + } + } else { + if (bit != 0) { + fprintf(stderr, "FAIL: ASN1_tag2bit(%d) = 0x%lx," + " want 0x0\n", i, bit); + goto failed; + } + } + } + + failed = 0; + + failed: + return failed; +} + +static int +asn1_tag2str(void) +{ + int failed = 1; + const char *s; + int i; + + for (i = -3; i <= V_ASN1_NEG + 30; i++) { + if ((s = ASN1_tag2str(i)) == NULL) { + fprintf(stderr, "FAIL: ASN1_tag2str(%d) returned " + "NULL\n", i); + goto failed; + } + if ((i >= 0 && i <= 30) || i == V_ASN1_NEG_INTEGER || + i == V_ASN1_NEG_ENUMERATED) { + if (strcmp(s, "(unknown)") == 0) { + fprintf(stderr, "FAIL: ASN1_tag2str(%d) = '%s'," + " want tag name\n", i, s); + goto failed; + } + } else { + if (strcmp(s, "(unknown)") != 0) { + fprintf(stderr, "FAIL: ASN1_tag2str(%d) = '%s'," + " want '(unknown')\n", i, s); + goto failed; + } + } + } + + failed = 0; + + failed: + return failed; +} + +struct asn1_get_object_test { + const uint8_t asn1[64]; + size_t asn1_len; + size_t asn1_hdr_len; + int want_ret; + long want_length; + int want_tag; + int want_class; + int want_error; +}; + +const struct asn1_get_object_test asn1_get_object_tests[] = { + { + /* Zero tag and zero length (EOC). */ + .asn1 = {0x00, 0x00}, + .asn1_len = 2, + .asn1_hdr_len = 2, + .want_ret = 0x00, + .want_length = 0, + .want_tag = 0, + .want_class = 0, + }, + { + /* Boolean with short form length. */ + .asn1 = {0x01, 0x01}, + .asn1_len = 3, + .asn1_hdr_len = 2, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 1, + .want_class = 0, + }, + { + /* Long form tag. */ + .asn1 = {0x1f, 0x7f, 0x01}, + .asn1_len = 3 + 128, + .asn1_hdr_len = 3, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 127, + .want_class = 0, + }, + { + /* Long form tag with class application. */ + .asn1 = {0x5f, 0x7f, 0x01}, + .asn1_len = 3 + 128, + .asn1_hdr_len = 3, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 127, + .want_class = 1 << 6, + }, + { + /* Long form tag with class context-specific. */ + .asn1 = {0x9f, 0x7f, 0x01}, + .asn1_len = 3 + 128, + .asn1_hdr_len = 3, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 127, + .want_class = 2 << 6, + }, + { + /* Long form tag with class private. */ + .asn1 = {0xdf, 0x7f, 0x01}, + .asn1_len = 3 + 128, + .asn1_hdr_len = 3, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 127, + .want_class = 3 << 6, + }, + { + /* Long form tag (maximum). */ + .asn1 = {0x1f, 0x87, 0xff, 0xff, 0xff, 0x7f, 0x01}, + .asn1_len = 8, + .asn1_hdr_len = 7, + .want_ret = 0x00, + .want_length = 1, + .want_tag = 0x7fffffff, + .want_class = 0, + }, + { + /* Long form tag (maximum + 1). */ + .asn1 = {0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x01}, + .asn1_len = 8, + .asn1_hdr_len = 7, + .want_ret = 0x80, + .want_error = ASN1_R_HEADER_TOO_LONG, + }, + { + /* OctetString with long form length. */ + .asn1 = {0x04, 0x81, 0x80}, + .asn1_len = 3 + 128, + .asn1_hdr_len = 3, + .want_ret = 0x00, + .want_length = 128, + .want_tag = 4, + .want_class = 0, + }, + { + /* OctetString with long form length. */ + .asn1 = {0x04, 0x84, 0x7f, 0xff, 0xff, 0xf9}, + .asn1_len = 0x7fffffff, + .asn1_hdr_len = 6, + .want_ret = 0x00, + .want_length = 0x7ffffff9, + .want_tag = 4, + .want_class = 0, + }, + { + /* Long form tag and long form length. */ + .asn1 = {0x1f, 0x87, 0xff, 0xff, 0xff, 0x7f, 0x84, 0x7f, 0xff, 0xff, 0xf4}, + .asn1_len = 0x7fffffff, + .asn1_hdr_len = 11, + .want_ret = 0x00, + .want_length = 0x7ffffff4, + .want_tag = 0x7fffffff, + .want_class = 0, + }, + { + /* Constructed OctetString with definite length. */ + .asn1 = {0x24, 0x03}, + .asn1_len = 5, + .asn1_hdr_len = 2, + .want_ret = 0x20, + .want_length = 3, + .want_tag = 4, + .want_class = 0, + }, + { + /* Constructed OctetString with indefinite length. */ + .asn1 = {0x24, 0x80}, + .asn1_len = 5, + .asn1_hdr_len = 2, + .want_ret = 0x21, + .want_length = 0, + .want_tag = 4, + .want_class = 0, + }, + { + /* Boolean with indefinite length (invalid). */ + .asn1 = {0x01, 0x80}, + .asn1_len = 3, + .want_ret = 0x80, + .want_error = ASN1_R_HEADER_TOO_LONG, + }, + { + /* OctetString with insufficient data (only tag). */ + .asn1 = {0x04, 0x04}, + .asn1_len = 1, + .want_ret = 0x80, + .want_error = ASN1_R_HEADER_TOO_LONG, + }, + { + /* OctetString with insufficient data (missing content). */ + .asn1 = {0x04, 0x04}, + .asn1_len = 2, + .asn1_hdr_len = 2, + .want_ret = 0x80, + .want_length = 4, + .want_tag = 4, + .want_class = 0, + .want_error = ASN1_R_TOO_LONG, + }, + { + /* OctetString with insufficient data (partial content). */ + .asn1 = {0x04, 0x04}, + .asn1_len = 5, + .asn1_hdr_len = 2, + .want_ret = 0x80, + .want_length = 4, + .want_tag = 4, + .want_class = 0, + .want_error = ASN1_R_TOO_LONG, + }, + { + /* Constructed OctetString with insufficient data (only tag/len). */ + .asn1 = {0x24, 0x04}, + .asn1_len = 2, + .asn1_hdr_len = 2, + .want_ret = 0xa0, + .want_length = 4, + .want_tag = 4, + .want_class = 0, + .want_error = ASN1_R_TOO_LONG, + }, +}; + +#define N_ASN1_GET_OBJECT_TESTS \ + (sizeof(asn1_get_object_tests) / sizeof(*asn1_get_object_tests)) + +static int +asn1_get_object(void) +{ + const struct asn1_get_object_test *agot; + const uint8_t *p; + int ret, tag, tag_class; + long err, length; + size_t i; + int failed = 1; + + for (i = 0; i < N_ASN1_GET_OBJECT_TESTS; i++) { + agot = &asn1_get_object_tests[i]; + + ERR_clear_error(); + + p = agot->asn1; + ret = ASN1_get_object(&p, &length, &tag, &tag_class, agot->asn1_len); + + if (ret != agot->want_ret) { + fprintf(stderr, "FAIL: %zu - got return value %x, want %x\n", + i, ret, agot->want_ret); + goto failed; + } + if (ret & 0x80) { + err = ERR_peek_error(); + if (ERR_GET_REASON(err) != agot->want_error) { + fprintf(stderr, "FAIL: %zu - got error reason %d, " + "want %d\n", i, ERR_GET_REASON(err), + agot->want_error); + goto failed; + } + if (ERR_GET_REASON(err) == ASN1_R_HEADER_TOO_LONG) { + if (p != agot->asn1) { + fprintf(stderr, "FAIL: %zu - got ber_in %p, " + "want %p\n", i, p, agot->asn1); + goto failed; + } + continue; + } + } + if (length != agot->want_length) { + fprintf(stderr, "FAIL: %zu - got length %ld, want %ld\n", + i, length, agot->want_length); + goto failed; + } + if (tag != agot->want_tag) { + fprintf(stderr, "FAIL: %zu - got tag %d, want %d\n", + i, tag, agot->want_tag); + goto failed; + } + if (tag_class != agot->want_class) { + fprintf(stderr, "FAIL: %zu - got class %d, want %d\n", + i, tag_class, agot->want_class); + goto failed; + } + if (p != agot->asn1 + agot->asn1_hdr_len) { + fprintf(stderr, "FAIL: %zu - got ber_in %p, want %p\n", + i, p, agot->asn1 + agot->asn1_len); + goto failed; + } + } + + failed = 0; + + failed: + return failed; +} + +static int +asn1_integer_get_null_test(void) +{ + int failed = 0; + long ret; + + if ((ret = ASN1_INTEGER_get(NULL)) != 0) { + fprintf(stderr, "FAIL: ASN1_INTEGER_get(NULL) %ld != 0\n", ret); + failed |= 1; + } + + if ((ret = ASN1_ENUMERATED_get(NULL)) != 0) { + fprintf(stderr, "FAIL: ASN1_ENUMERATED_get(NULL) %ld != 0\n", + ret); + failed |= 1; + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= asn1_tag2bit(); + failed |= asn1_tag2str(); + failed |= asn1_get_object(); + failed |= asn1_integer_get_null_test(); + + return (failed); +} diff --git a/tests/asn1basic.c b/tests/asn1basic.c new file mode 100644 index 0000000..5bcb900 --- /dev/null +++ b/tests/asn1basic.c @@ -0,0 +1,1137 @@ +/* $OpenBSD: asn1basic.c,v 1.15 2023/08/15 21:05:44 tb Exp $ */ +/* + * Copyright (c) 2017, 2021 Joel Sing + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include "asn1_local.h" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, + const unsigned char *d2, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: %s - byte lengths differ " + "(%d != %d)\n", label, len1, len2); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: %s - bytes differ\n", label); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + return 1; +} + +const uint8_t asn1_bit_string_primitive[] = { + 0x03, 0x07, + 0x04, 0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0, +}; + +static int +asn1_bit_string_test(void) +{ + uint8_t bs[] = {0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0}; + ASN1_BIT_STRING *abs; + uint8_t *p = NULL, *pp; + const uint8_t *q; + int bit, i, len; + int failed = 1; + + if ((abs = ASN1_BIT_STRING_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_BIT_STRING_new() == NULL\n"); + goto failed; + } + if (!ASN1_BIT_STRING_set(abs, bs, sizeof(bs))) { + fprintf(stderr, "FAIL: failed to set bit string\n"); + goto failed; + } + + if ((len = i2d_ASN1_BIT_STRING(abs, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING with NULL\n"); + goto failed; + } + if ((p = malloc(len)) == NULL) + errx(1, "malloc"); + memset(p, 0xbd, len); + pp = p; + if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { + fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); + goto failed; + } + if (!asn1_compare_bytes("BIT_STRING", p, len, asn1_bit_string_primitive, + sizeof(asn1_bit_string_primitive))) + goto failed; + if (pp != p + len) { + fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING pp = %p, want %p\n", + pp, p + len); + goto failed; + } + + /* Test primitive decoding. */ + q = p; + if (d2i_ASN1_BIT_STRING(&abs, &q, len) == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_BIT_STRING primitive\n"); + goto failed; + } + if (!asn1_compare_bytes("BIT_STRING primitive data", abs->data, abs->length, + bs, sizeof(bs))) + goto failed; + if (q != p + len) { + fprintf(stderr, "FAIL: d2i_ASN1_BIT_STRING q = %p, want %p\n", + q, p + len); + goto failed; + } + + /* Test ASN1_BIT_STRING_get_bit(). */ + for (i = 0; i < ((int)sizeof(bs) * 8); i++) { + bit = (bs[i / 8] >> (7 - i % 8)) & 1; + + if (ASN1_BIT_STRING_get_bit(abs, i) != bit) { + fprintf(stderr, "FAIL: ASN1_BIT_STRING_get_bit(_, %d) " + "= %d, want %d\n", i, + ASN1_BIT_STRING_get_bit(abs, i), bit); + goto failed; + } + } + + /* Test ASN1_BIT_STRING_set_bit(). */ + for (i = 0; i < ((int)sizeof(bs) * 8); i++) { + if (!ASN1_BIT_STRING_set_bit(abs, i, 1)) { + fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit 1\n"); + goto failed; + } + } + for (i = ((int)sizeof(bs) * 8) - 1; i >= 0; i--) { + bit = (bs[i / 8] >> (7 - i % 8)) & 1; + if (bit == 1) + continue; + if (!ASN1_BIT_STRING_set_bit(abs, i, 0)) { + fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit\n"); + goto failed; + } + } + + if ((i2d_ASN1_BIT_STRING(abs, NULL)) != len) { + fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); + goto failed; + } + + memset(p, 0xbd, len); + pp = p; + if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { + fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); + goto failed; + } + + if (!asn1_compare_bytes("BIT_STRING set", p, len, asn1_bit_string_primitive, + sizeof(asn1_bit_string_primitive))) + goto failed; + + failed = 0; + + failed: + ASN1_BIT_STRING_free(abs); + free(p); + + return failed; +} + +const uint8_t asn1_boolean_false[] = { + 0x01, 0x01, 0x00, +}; +const uint8_t asn1_boolean_true[] = { + 0x01, 0x01, 0x01, +}; + +static int +asn1_boolean_test(void) +{ + uint8_t *p = NULL, *pp; + const uint8_t *q; + int len; + int failed = 1; + + if ((len = i2d_ASN1_BOOLEAN(0, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false with NULL\n"); + goto failed; + } + if ((p = malloc(len)) == NULL) + errx(1, "calloc"); + memset(p, 0xbd, len); + pp = p; + if ((i2d_ASN1_BOOLEAN(0, &pp)) != len) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false\n"); + goto failed; + } + if (pp != p + len) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN pp = %p, want %p\n", + pp, p + len); + goto failed; + } + + if (!asn1_compare_bytes("BOOLEAN false", p, len, asn1_boolean_false, + sizeof(asn1_boolean_false))) + goto failed; + + q = p; + if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 0) { + fprintf(stderr, "FAIL: BOOLEAN false did not decode to 0\n"); + goto failed; + } + if (q != p + len) { + fprintf(stderr, "FAIL: d2i_ASN1_BOOLEAN q = %p, want %p\n", + q, p + len); + goto failed; + } + + free(p); + p = NULL; + + if ((len = i2d_ASN1_BOOLEAN(1, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true with NULL\n"); + goto failed; + } + if ((p = calloc(1, len)) == NULL) + errx(1, "calloc"); + pp = p; + if ((i2d_ASN1_BOOLEAN(1, &pp)) != len) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true\n"); + goto failed; + } + if (pp != p + len) { + fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN pp = %p, want %p\n", + pp, p + len); + goto failed; + } + + if (!asn1_compare_bytes("BOOLEAN true", p, len, asn1_boolean_true, + sizeof(asn1_boolean_true))) + goto failed; + + q = p; + if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 1) { + fprintf(stderr, "FAIL: BOOLEAN true did not decode to 1\n"); + goto failed; + } + if (q != p + len) { + fprintf(stderr, "FAIL: d2i_ASN1_BOOLEAN q = %p, want %p\n", + q, p + len); + goto failed; + } + + failed = 0; + + failed: + free(p); + + return failed; +} + +struct asn1_integer_test { + long value; + uint8_t content[64]; + size_t content_len; + int content_neg; + uint8_t der[64]; + size_t der_len; + int want_error; +}; + +struct asn1_integer_test asn1_integer_tests[] = { + { + .value = 0, + .content = {0x00}, + .content_len = 1, + .der = {0x02, 0x01, 0x00}, + .der_len = 3, + }, + { + .value = 1, + .content = {0x01}, + .content_len = 1, + .der = {0x02, 0x01, 0x01}, + .der_len = 3, + }, + { + .value = -1, + .content = {0x01}, + .content_len = 1, + .content_neg = 1, + .der = {0x02, 0x01, 0xff}, + .der_len = 3, + }, + { + .value = 127, + .content = {0x7f}, + .content_len = 1, + .der = {0x02, 0x01, 0x7f}, + .der_len = 3, + }, + { + .value = -127, + .content = {0x7f}, + .content_len = 1, + .content_neg = 1, + .der = {0x02, 0x01, 0x81}, + .der_len = 3, + }, + { + .value = 128, + .content = {0x80}, + .content_len = 1, + .der = {0x02, 0x02, 0x00, 0x80}, + .der_len = 4, + }, + { + .value = -128, + .content = {0x80}, + .content_len = 1, + .content_neg = 1, + .der = {0x02, 0x01, 0x80}, + .der_len = 3, + }, + { + /* 2^64 */ + .content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .content_len = 9, + .der = {0x02, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .der_len = 11, + }, + { + /* -2^64 */ + .content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .content_len = 9, + .content_neg = 1, + .der = {0x02, 0x09, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .der_len = 11, + }, + { + /* Invalid length. */ + .der = {0x02, 0x00}, + .der_len = 2, + .want_error = 1, + }, + { + /* Invalid padding. */ + .der = {0x02, 0x09, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .der_len = 11, + .want_error = 1, + }, + { + /* Invalid padding. */ + .der = {0x02, 0x09, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .der_len = 11, + .want_error = 1, + }, + { + /* Invalid encoding (constructed with definite length). */ + .der = {0x22, 0x03, 0x02, 0x01, 0x01}, + .der_len = 5, + .want_error = 1, + }, + { + /* Invalid encoding (constructed with indefinite length). */ + .der = {0x22, 0x80, 0x02, 0x01, 0x01, 0x00, 0x00}, + .der_len = 7, + .want_error = 1, + }, +}; + +#define N_ASN1_INTEGER_TESTS \ + (sizeof(asn1_integer_tests) / sizeof(*asn1_integer_tests)) + +static int +asn1_integer_set_test(struct asn1_integer_test *ait) +{ + ASN1_INTEGER *aint = NULL; + uint8_t *p = NULL, *pp; + int len; + int failed = 1; + + if ((aint = ASN1_INTEGER_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); + goto failed; + } + if (!ASN1_INTEGER_set(aint, ait->value)) { + fprintf(stderr, "FAIL: ASN1_INTEGER_(%ld) failed\n", + ait->value); + goto failed; + } + if (ait->value != 0 && + !asn1_compare_bytes("INTEGER set", aint->data, aint->length, + ait->content, ait->content_len)) + goto failed; + if (ait->content_neg && aint->type != V_ASN1_NEG_INTEGER) { + fprintf(stderr, "FAIL: Not V_ASN1_NEG_INTEGER\n"); + goto failed; + } + if (ASN1_INTEGER_get(aint) != ait->value) { + fprintf(stderr, "FAIL: ASN1_INTEGER_get() = %ld, want %ld\n", + ASN1_INTEGER_get(aint), ait->value); + goto failed; + } + if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if ((p = malloc(len)) == NULL) + errx(1, "malloc"); + memset(p, 0xbd, len); + pp = p; + if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if (!asn1_compare_bytes("INTEGER set", p, len, ait->der, + ait->der_len)) + goto failed; + + failed = 0; + + failed: + ASN1_INTEGER_free(aint); + free(p); + + return failed; +} + +static int +asn1_integer_content_test(struct asn1_integer_test *ait) +{ + ASN1_INTEGER *aint = NULL; + uint8_t *p = NULL, *pp; + int len; + int failed = 1; + + if ((aint = ASN1_INTEGER_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); + goto failed; + } + if ((aint->data = malloc(ait->content_len)) == NULL) + errx(1, "malloc"); + memcpy(aint->data, ait->content, ait->content_len); + aint->length = ait->content_len; + if (ait->content_neg) + aint->type = V_ASN1_NEG_INTEGER; + + if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if ((p = malloc(len)) == NULL) + errx(1, "malloc"); + memset(p, 0xbd, len); + pp = p; + if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if (!asn1_compare_bytes("INTEGER content", p, len, ait->der, + ait->der_len)) + goto failed; + if (pp != p + len) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER pp = %p, want %p\n", + pp, p + len); + goto failed; + } + + failed = 0; + + failed: + ASN1_INTEGER_free(aint); + free(p); + + return failed; +} + +static int +asn1_integer_decode_test(struct asn1_integer_test *ait) +{ + ASN1_INTEGER *aint = NULL; + const uint8_t *q; + int failed = 1; + + q = ait->der; + if (d2i_ASN1_INTEGER(&aint, &q, ait->der_len) != NULL) { + if (ait->want_error != 0) { + fprintf(stderr, "FAIL: INTEGER decoded when it should " + "have failed\n"); + goto failed; + } + if (!asn1_compare_bytes("INTEGER content", aint->data, + aint->length, ait->content, ait->content_len)) + goto failed; + if (q != ait->der + ait->der_len) { + fprintf(stderr, "FAIL: d2i_ASN1_INTEGER q = %p, want %p\n", + q, ait->der + ait->der_len); + goto failed; + } + } else if (ait->want_error == 0) { + fprintf(stderr, "FAIL: INTEGER failed to decode\n"); + ERR_print_errors_fp(stderr); + goto failed; + } + + failed = 0; + + failed: + ASN1_INTEGER_free(aint); + + return failed; +} + +static int +asn1_integer_set_val_test(void) +{ + ASN1_INTEGER *aint = NULL; + uint64_t uval; + int64_t val; + int failed = 1; + + if ((aint = ASN1_INTEGER_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); + goto failed; + } + + if (!ASN1_INTEGER_set_uint64(aint, 0)) { + fprintf(stderr, "FAIL: ASN_INTEGER_set_uint64() failed with " + "0\n"); + goto failed; + } + if (!ASN1_INTEGER_get_uint64(&uval, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_uint64() failed with " + "0\n"); + goto failed; + } + if (uval != 0) { + fprintf(stderr, "FAIL: uval != 0\n"); + goto failed; + } + + if (!ASN1_INTEGER_set_uint64(aint, UINT64_MAX)) { + fprintf(stderr, "FAIL: ASN_INTEGER_set_uint64() failed with " + "UINT64_MAX\n"); + goto failed; + } + if (!ASN1_INTEGER_get_uint64(&uval, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_uint64() failed with " + "UINT64_MAX\n"); + goto failed; + } + if (uval != UINT64_MAX) { + fprintf(stderr, "FAIL: uval != UINT64_MAX\n"); + goto failed; + } + if (ASN1_INTEGER_get_int64(&val, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_int64() succeeded " + "with UINT64_MAX\n"); + goto failed; + } + + if (!ASN1_INTEGER_set_int64(aint, INT64_MIN)) { + fprintf(stderr, "FAIL: ASN_INTEGER_set_int64() failed with " + "INT64_MIN\n"); + goto failed; + } + if (!ASN1_INTEGER_get_int64(&val, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_int64() failed with " + "INT64_MIN\n"); + goto failed; + } + if (val != INT64_MIN) { + fprintf(stderr, "FAIL: val != INT64_MIN\n"); + goto failed; + } + if (ASN1_INTEGER_get_uint64(&uval, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_uint64() succeeded " + "with INT64_MIN\n"); + goto failed; + } + + if (!ASN1_INTEGER_set_int64(aint, INT64_MAX)) { + fprintf(stderr, "FAIL: ASN_INTEGER_set_int64() failed with " + "INT64_MAX\n"); + goto failed; + } + if (!ASN1_INTEGER_get_int64(&val, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_int64() failed with " + "INT64_MAX\n"); + goto failed; + } + if (val != INT64_MAX) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_int64() failed with " + "INT64_MAX\n"); + goto failed; + } + if (!ASN1_INTEGER_get_uint64(&uval, aint)) { + fprintf(stderr, "FAIL: ASN_INTEGER_get_uint64() failed with " + "INT64_MAX\n"); + goto failed; + } + if (uval != INT64_MAX) { + fprintf(stderr, "FAIL: uval != INT64_MAX\n"); + goto failed; + } + + failed = 0; + + failed: + ASN1_INTEGER_free(aint); + + return failed; +} + +static int +asn1_integer_cmp_test(void) +{ + ASN1_INTEGER *a = NULL, *b = NULL; + int failed = 1; + + if ((a = ASN1_INTEGER_new()) == NULL) + goto failed; + if ((b = ASN1_INTEGER_new()) == NULL) + goto failed; + + if (ASN1_INTEGER_cmp(a, b) != 0) { + fprintf(stderr, "FAIL: INTEGER 0 == 0"); + goto failed; + } + + if (!ASN1_INTEGER_set(b, 1)) { + fprintf(stderr, "FAIL: failed to set INTEGER"); + goto failed; + } + if (ASN1_INTEGER_cmp(a, b) >= 0) { + fprintf(stderr, "FAIL: INTEGER 0 < 1"); + goto failed; + } + if (ASN1_INTEGER_cmp(b, a) <= 0) { + fprintf(stderr, "FAIL: INTEGER 1 > 0"); + goto failed; + } + + if (!ASN1_INTEGER_set(b, -1)) { + fprintf(stderr, "FAIL: failed to set INTEGER"); + goto failed; + } + if (ASN1_INTEGER_cmp(a, b) <= 0) { + fprintf(stderr, "FAIL: INTEGER 0 > -1"); + goto failed; + } + if (ASN1_INTEGER_cmp(b, a) >= 0) { + fprintf(stderr, "FAIL: INTEGER -1 < 0"); + goto failed; + } + + if (!ASN1_INTEGER_set(a, 1)) { + fprintf(stderr, "FAIL: failed to set INTEGER"); + goto failed; + } + if (ASN1_INTEGER_cmp(a, b) <= 0) { + fprintf(stderr, "FAIL: INTEGER 1 > -1"); + goto failed; + } + if (ASN1_INTEGER_cmp(b, a) >= 0) { + fprintf(stderr, "FAIL: INTEGER -1 < 1"); + goto failed; + } + + if (!ASN1_INTEGER_set(b, 1)) { + fprintf(stderr, "FAIL: failed to set INTEGER"); + goto failed; + } + if (ASN1_INTEGER_cmp(a, b) != 0) { + fprintf(stderr, "FAIL: INTEGER 1 == 1"); + goto failed; + } + + failed = 0; + + failed: + ASN1_INTEGER_free(a); + ASN1_INTEGER_free(b); + + return failed; +} + +static int +asn1_integer_null_data_test(void) +{ + const uint8_t der[] = {0x02, 0x01, 0x00}; + ASN1_INTEGER *aint = NULL; + uint8_t *p = NULL, *pp; + int len; + int failed = 0; + + if ((aint = ASN1_INTEGER_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); + goto failed; + } + if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if ((p = calloc(1, len)) == NULL) + errx(1, "calloc"); + pp = p; + if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) { + fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); + goto failed; + } + if (!asn1_compare_bytes("INTEGER NULL data", p, len, der, sizeof(der))) + goto failed; + + failed = 0; + + failed: + ASN1_INTEGER_free(aint); + free(p); + + return failed; +} + +static int +asn1_integer_test(void) +{ + struct asn1_integer_test *ait; + int failed = 0; + size_t i; + + for (i = 0; i < N_ASN1_INTEGER_TESTS; i++) { + ait = &asn1_integer_tests[i]; + if (ait->content_len > 0 && ait->content_len <= 4) + failed |= asn1_integer_set_test(ait); + if (ait->content_len > 0) + failed |= asn1_integer_content_test(ait); + failed |= asn1_integer_decode_test(ait); + } + + failed |= asn1_integer_cmp_test(); + failed |= asn1_integer_null_data_test(); + failed |= asn1_integer_set_val_test(); + + return failed; +} + +static const struct asn1_string_new_test { + const char *name; + ASN1_STRING *(*new)(void); + void (*free)(ASN1_STRING *); + int type; + long flags; +} asn1_string_new_tests[] = { + { + .name = "ASN1_STRING", + .new = ASN1_STRING_new, + .free = ASN1_STRING_free, + .type = V_ASN1_OCTET_STRING, + }, + { + .name = "ASN1_OCTET_STRING", + .new = ASN1_OCTET_STRING_new, + .free = ASN1_OCTET_STRING_free, + .type = V_ASN1_OCTET_STRING, + }, + { + .name = "ASN1_BIT_STRING", + .new = ASN1_BIT_STRING_new, + .free = ASN1_BIT_STRING_free, + .type = V_ASN1_BIT_STRING, + }, + { + .name = "ASN1_INTEGER", + .new = ASN1_INTEGER_new, + .free = ASN1_INTEGER_free, + .type = V_ASN1_INTEGER, + }, + { + .name = "ASN1_ENUMERATED", + .new = ASN1_ENUMERATED_new, + .free = ASN1_ENUMERATED_free, + .type = V_ASN1_ENUMERATED, + }, + { + .name = "ASN1_UTF8STRING", + .new = ASN1_UTF8STRING_new, + .free = ASN1_UTF8STRING_free, + .type = V_ASN1_UTF8STRING, + }, + { + .name = "ASN1_IA5STRING", + .new = ASN1_IA5STRING_new, + .free = ASN1_IA5STRING_free, + .type = V_ASN1_IA5STRING, + }, + { + .name = "ASN1_UNIVERSALSTRING", + .new = ASN1_UNIVERSALSTRING_new, + .free = ASN1_UNIVERSALSTRING_free, + .type = V_ASN1_UNIVERSALSTRING, + }, + { + .name = "ASN1_BMPSTRING", + .new = ASN1_BMPSTRING_new, + .free = ASN1_BMPSTRING_free, + .type = V_ASN1_BMPSTRING, + }, + { + .name = "ASN1_GENERALSTRING", + .new = ASN1_GENERALSTRING_new, + .free = ASN1_GENERALSTRING_free, + .type = V_ASN1_GENERALSTRING, + }, + { + .name = "ASN1_T61STRING", + .new = ASN1_T61STRING_new, + .free = ASN1_T61STRING_free, + .type = V_ASN1_T61STRING, + }, + { + .name = "ASN1_VISIBLESTRING", + .new = ASN1_VISIBLESTRING_new, + .free = ASN1_VISIBLESTRING_free, + .type = V_ASN1_VISIBLESTRING, + }, + { + .name = "ASN1_PRINTABLESTRING", + .new = ASN1_PRINTABLESTRING_new, + .free = ASN1_PRINTABLESTRING_free, + .type = V_ASN1_PRINTABLESTRING, + }, + { + .name = "ASN1_PRINTABLE", + .new = ASN1_PRINTABLE_new, + .free = ASN1_PRINTABLE_free, + .type = V_ASN1_UNDEF, + .flags = ASN1_STRING_FLAG_MSTRING, + }, + { + .name = "DIRECTORYSTRING", + .new = DIRECTORYSTRING_new, + .free = DIRECTORYSTRING_free, + .type = V_ASN1_UNDEF, + .flags = ASN1_STRING_FLAG_MSTRING, + }, + { + .name = "DISPLAYTEXT", + .new = DISPLAYTEXT_new, + .free = DISPLAYTEXT_free, + .type = V_ASN1_UNDEF, + .flags = ASN1_STRING_FLAG_MSTRING, + }, + { + .name = "ASN1_GENERALIZEDTIME", + .new = ASN1_GENERALIZEDTIME_new, + .free = ASN1_GENERALIZEDTIME_free, + .type = V_ASN1_GENERALIZEDTIME, + }, + { + .name = "ASN1_UTCTIME", + .new = ASN1_UTCTIME_new, + .free = ASN1_UTCTIME_free, + .type = V_ASN1_UTCTIME, + }, + { + .name = "ASN1_TIME", + .new = ASN1_TIME_new, + .free = ASN1_TIME_free, + .type = V_ASN1_UNDEF, + .flags = ASN1_STRING_FLAG_MSTRING, + }, +}; + +#define N_ASN1_STRING_NEW_TESTS \ + (sizeof(asn1_string_new_tests) / sizeof(asn1_string_new_tests[0])) + +static int +asn1_string_new_test(void) +{ + size_t i; + ASN1_STRING *astr = NULL; + int failed = 1; + + for (i = 0; i < N_ASN1_STRING_NEW_TESTS; i++) { + const struct asn1_string_new_test *asnt = &asn1_string_new_tests[i]; + + if ((astr = asnt->new()) == NULL) { + fprintf(stderr, "%s_new() failed\n", asnt->name); + goto err; + } + if (ASN1_STRING_type(astr) != asnt->type) { + fprintf(stderr, "%s type: want %d, got %d\n", + asnt->name, asnt->type, ASN1_STRING_type(astr)); + goto err; + } + if (ASN1_STRING_data(astr) != NULL) { + fprintf(stderr, "%s data != NULL\n", asnt->name); + goto err; + } + if (ASN1_STRING_get0_data(astr) != NULL) { + fprintf(stderr, "%s data != NULL\n", asnt->name); + goto err; + } + if (ASN1_STRING_length(astr) != 0) { + fprintf(stderr, "%s length %d != 0\n", asnt->name, + ASN1_STRING_length(astr)); + goto err; + } + ASN1_STRING_length_set(astr, 20); + if (ASN1_STRING_length(astr) != 20) { + fprintf(stderr, "%s length %d != 20\n", asnt->name, + ASN1_STRING_length(astr)); + goto err; + } + astr->flags |= ASN1_STRING_FLAG_NDEF; + if (astr->flags != (asnt->flags | ASN1_STRING_FLAG_NDEF)) { + fprintf(stderr, "%s flags: %lx\n", asnt->name, + astr->flags); + goto err; + } + /* ASN1_STRING_set0() clears ASN1_STRING_FLAG_NDEF. */ + ASN1_STRING_set0(astr, NULL, 0); + if (astr->flags != asnt->flags) { + fprintf(stderr, "%s flags: %lx != %lx\n", asnt->name, + astr->flags, asnt->flags); + goto err; + } + asnt->free(astr); + astr = NULL; + + if ((astr = ASN1_STRING_type_new(asnt->type)) == NULL) { + fprintf(stderr, "ASN1_STRING_type_new(%s) failed\n", + asnt->name); + goto err; + } + if (ASN1_STRING_type(astr) != asnt->type) { + fprintf(stderr, "%s type: want %d, got %d\n", + asnt->name, asnt->type, ASN1_STRING_type(astr)); + goto err; + } + if (ASN1_STRING_data(astr) != NULL) { + fprintf(stderr, "%s data != NULL\n", asnt->name); + goto err; + } + /* ASN1_STRING_type_new() does not set flags. */ + if (astr->flags != 0) { + fprintf(stderr, "%s flags %lx\n", asnt->name, + astr->flags); + goto err; + } + asnt->free(astr); + astr = NULL; + + } + + failed = 0; + + err: + ASN1_STRING_free(astr); + + return failed; +} + +static char *comparison_str = "mystring"; + +static int +asn1_string_cmp_test(void) +{ + ASN1_STRING *a = NULL, *b = NULL; + int got, want; + int failed = 1; + + if ((got = ASN1_STRING_cmp(NULL, NULL)) != -1) { + fprintf(stderr, "ASN1_STRING_cmp(NULL, NULL): %d != -1\n", got); + goto err; + } + + if ((a = ASN1_STRING_new()) == NULL) { + fprintf(stderr, "a = ASN1_STRING_new() failed\n"); + goto err; + } + if ((b = ASN1_STRING_type_new(V_ASN1_UTF8STRING)) == NULL) { + fprintf(stderr, "b = ASN1_STRING_type_new() failed\n"); + goto err; + } + + if ((got = ASN1_STRING_cmp(a, NULL)) != -1) { + fprintf(stderr, "ASN1_STRING_cmp(a, NULL): %d != -1\n", got); + goto err; + } + if ((got = ASN1_STRING_cmp(NULL, a)) != -1) { + fprintf(stderr, "ASN1_STRING_cmp(NULL, a): %d != -1\n", got); + goto err; + } + + if (ASN1_STRING_cmp(a, b) >= 0) { + fprintf(stderr, "V_ASN1_OCTET_STRING >= V_ASN1_UTF8STRING\n"); + goto err; + } + want = V_ASN1_UTF8STRING - V_ASN1_OCTET_STRING; + if ((got = ASN1_STRING_cmp(b, a)) != want) { + fprintf(stderr, "comparison of octet with utf8 string:" + "want %d, got %d\n", want, got); + goto err; + } + + ASN1_STRING_set0(a, comparison_str, strlen(comparison_str)); + ASN1_STRING_set0(b, comparison_str, strlen(comparison_str)); + + /* Ensure any data set on a or b isn't freed/zeroed. */ + a->flags |= ASN1_STRING_FLAG_NDEF; + b->flags |= ASN1_STRING_FLAG_NDEF; + + if ((got = ASN1_STRING_cmp(b, a)) != want) { + fprintf(stderr, "comparison of octet with utf8 string:" + "want %d, got %d\n", want, got); + goto err; + } + + b->type = V_ASN1_OCTET_STRING; + + if ((got = ASN1_STRING_cmp(a, b)) != 0) { + fprintf(stderr, "same string on both. want 0, got %d\n", got); + goto err; + } + + if (!ASN1_STRING_set(b, "myString", -1)) { + fprintf(stderr, "ASN1_STRING_set(b) failed\n"); + goto err; + } + + if ((got = ASN1_STRING_cmp(a, b)) <= 0) { + fprintf(stderr, "capitalized letter compares larger: got %d\n", + got); + goto err; + } + if ((got = ASN1_STRING_cmp(b, a)) >= 0) { + fprintf(stderr, "capitalized letter is larger 2: %d\n", got); + goto err; + } + + ASN1_STRING_length_set(b, 2); + + want = strlen(comparison_str) - 2; + + if ((got = ASN1_STRING_cmp(a, b)) != want) { + fprintf(stderr, "comparison of a with truncated b: " + "want %d, got %d\n", want, got); + goto err; + } + + want = -want; + + if ((got = ASN1_STRING_cmp(b, a)) != want) { + fprintf(stderr, "comparison of truncated b with a: " + "want %d, got %d\n", want, got); + goto err; + } + + ASN1_STRING_length_set(a, 2); + + if ((got = ASN1_STRING_cmp(a, b)) != 0) { + fprintf(stderr, "both truncated compared to %d\n", got); + goto err; + } + + ASN1_STRING_length_set(a, strlen(comparison_str)); + + ASN1_STRING_set0(b, NULL, 0); + + want = strlen(comparison_str); + if ((got = ASN1_STRING_cmp(a, b)) != want) { + fprintf(stderr, "comparison of a with zeroed b: " + "want %d, got %d\n", want, got); + goto err; + } + + ASN1_STRING_set0(b, "", 0); + b->flags |= ASN1_STRING_FLAG_NDEF; + + if ((got = ASN1_STRING_cmp(a, b)) != want) { + fprintf(stderr, "comparison of a with zero-length b: " + "want %d, got %d\n", want, got); + goto err; + } + + ASN1_STRING_set0(a, NULL, 0); + if ((got = ASN1_STRING_cmp(a, b)) != 0) { + fprintf(stderr, "comparison of zeroed a with zero-length b: " + "want 0, got %d\n", got); + goto err; + } + if ((got = ASN1_STRING_cmp(b, a)) != 0) { + fprintf(stderr, "comparison of zero-length b with zeroed a: " + "want 0, got %d\n", got); + goto err; + } + + failed = 0; + + err: + ASN1_STRING_free(a); + ASN1_STRING_free(b); + + return failed; +} + +static int +asn1_string_test(void) +{ + int failed = 0; + + failed |= asn1_string_new_test(); + failed |= asn1_string_cmp_test(); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= asn1_bit_string_test(); + failed |= asn1_boolean_test(); + failed |= asn1_integer_test(); + failed |= asn1_string_test(); + + return (failed); +} diff --git a/tests/asn1complex.c b/tests/asn1complex.c new file mode 100644 index 0000000..6f34154 --- /dev/null +++ b/tests/asn1complex.c @@ -0,0 +1,324 @@ +/* $OpenBSD: asn1complex.c,v 1.4 2022/09/05 21:06:31 tb Exp $ */ +/* + * Copyright (c) 2017, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, + const unsigned char *d2, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: %s - byte lengths differ " + "(%d != %d)\n", label, len1, len2); + return 0; + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: %s - bytes differ\n", label); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + return 1; +} + +/* Constructed octet string with length 12. */ +const uint8_t asn1_constructed_basic_ber[] = { + 0x24, 0x0c, + 0x04, 0x01, 0x01, + 0x04, 0x02, 0x01, 0x02, + 0x04, 0x03, 0x01, 0x02, 0x03 +}; +const uint8_t asn1_constructed_basic_content[] = { + 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, +}; + +/* Nested constructed octet string. */ +const uint8_t asn1_constructed_nested_ber[] = { + 0x24, 0x1a, + 0x04, 0x01, 0x01, + 0x24, 0x15, + 0x04, 0x02, 0x02, 0x03, + 0x24, 0x0f, + 0x24, 0x0d, + 0x04, 0x03, 0x04, 0x05, 0x06, + 0x24, 0x06, + 0x24, 0x04, + 0x04, 0x02, 0x07, 0x08, +}; +const uint8_t asn1_constructed_nested_content[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, +}; + +/* Deeply nested constructed octet string. */ +const uint8_t asn1_constructed_deep_nested_ber[] = { + 0x24, 0x1b, + 0x04, 0x01, 0x01, + 0x24, 0x16, + 0x04, 0x02, 0x02, 0x03, + 0x24, 0x10, + 0x24, 0x0e, + 0x04, 0x03, 0x04, 0x05, 0x06, + 0x24, 0x07, + 0x24, 0x05, + 0x24, 0x03, + 0x04, 0x01, 0x07, +}; + +/* Constructed octet string with indefinite length. */ +const uint8_t asn1_constructed_indefinite_ber[] = { + 0x24, 0x80, + 0x04, 0x01, 0x01, + 0x04, 0x02, 0x01, 0x02, + 0x04, 0x03, 0x01, 0x02, 0x03, + 0x00, 0x00, +}; +const uint8_t asn1_constructed_indefinite_content[] = { + 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, +}; + +struct asn1_constructed_test { + const char *name; + const uint8_t *asn1; + size_t asn1_len; + const uint8_t *want; + size_t want_len; + int want_error; + int valid; +}; + +const struct asn1_constructed_test asn1_constructed_tests[] = { + { + .name = "basic constructed", + .asn1 = asn1_constructed_basic_ber, + .asn1_len = sizeof(asn1_constructed_basic_ber), + .want = asn1_constructed_basic_content, + .want_len = sizeof(asn1_constructed_basic_content), + .valid = 1, + }, + { + .name = "nested constructed", + .asn1 = asn1_constructed_nested_ber, + .asn1_len = sizeof(asn1_constructed_nested_ber), + .want = asn1_constructed_nested_content, + .want_len = sizeof(asn1_constructed_nested_content), + .valid = 1, + }, + { + .name = "deep nested constructed", + .asn1 = asn1_constructed_deep_nested_ber, + .asn1_len = sizeof(asn1_constructed_deep_nested_ber), + .want_error = ASN1_R_NESTED_ASN1_STRING, + .valid = 0, + }, + { + .name = "indefinite length constructed", + .asn1 = asn1_constructed_indefinite_ber, + .asn1_len = sizeof(asn1_constructed_indefinite_ber), + .want = asn1_constructed_indefinite_content, + .want_len = sizeof(asn1_constructed_indefinite_content), + .valid = 1, + }, +}; + +#define N_CONSTRUCTED_TESTS \ + (sizeof(asn1_constructed_tests) / sizeof(*asn1_constructed_tests)) + +static int +do_asn1_constructed_test(const struct asn1_constructed_test *act) +{ + ASN1_OCTET_STRING *aos = NULL; + const uint8_t *p; + long err; + int failed = 1; + + ERR_clear_error(); + + p = act->asn1; + aos = d2i_ASN1_OCTET_STRING(NULL, &p, act->asn1_len); + if (!act->valid) { + if (aos != NULL) { + fprintf(stderr, "FAIL: invalid ASN.1 decoded\n"); + goto failed; + } + if (act->want_error != 0) { + err = ERR_peek_error(); + if (ERR_GET_REASON(err) != act->want_error) { + fprintf(stderr, "FAIL: got error reason %d," + "want %d", ERR_GET_REASON(err), + act->want_error); + goto failed; + } + } + goto done; + } + if (aos == NULL) { + fprintf(stderr, "FAIL: failed to decode ASN.1 constructed " + "octet string\n"); + ERR_print_errors_fp(stderr); + goto failed; + } + if (!asn1_compare_bytes(act->name, ASN1_STRING_data(aos), + ASN1_STRING_length(aos), act->want, act->want_len)) + goto failed; + + done: + failed = 0; + + failed: + ASN1_OCTET_STRING_free(aos); + + return failed; +} + +static int +do_asn1_constructed_tests(void) +{ + const struct asn1_constructed_test *act; + int failed = 0; + size_t i; + + for (i = 0; i < N_CONSTRUCTED_TESTS; i++) { + act = &asn1_constructed_tests[i]; + failed |= do_asn1_constructed_test(act); + } + + return failed; +} + +/* Sequence with length. */ +const uint8_t asn1_sequence_ber[] = { + 0x30, 0x16, + 0x04, 0x01, 0x01, + 0x04, 0x02, 0x01, 0x02, + 0x04, 0x03, 0x01, 0x02, 0x03, + 0x30, 0x80, 0x04, 0x01, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x01, + + 0x04, 0x01, 0x01, /* Trailing data. */ +}; + +const uint8_t asn1_sequence_content[] = { + 0x30, 0x16, 0x04, 0x01, 0x01, 0x04, 0x02, 0x01, + 0x02, 0x04, 0x03, 0x01, 0x02, 0x03, 0x30, 0x80, + 0x04, 0x01, 0x01, 0x00, 0x00, 0x04, 0x01, 0x01, +}; + +/* Sequence with indefinite length. */ +const uint8_t asn1_sequence_indefinite_ber[] = { + 0x30, 0x80, + 0x04, 0x01, 0x01, + 0x04, 0x02, 0x01, 0x02, + 0x04, 0x03, 0x01, 0x02, 0x03, + 0x30, 0x80, 0x04, 0x01, 0x01, 0x00, 0x00, + 0x04, 0x01, 0x01, + 0x00, 0x00, + + 0x04, 0x01, 0x01, /* Trailing data. */ +}; + +const uint8_t asn1_sequence_indefinite_content[] = { + 0x30, 0x80, 0x04, 0x01, 0x01, 0x04, 0x02, 0x01, + 0x02, 0x04, 0x03, 0x01, 0x02, 0x03, 0x30, 0x80, + 0x04, 0x01, 0x01, 0x00, 0x00, 0x04, 0x01, 0x01, + 0x00, 0x00, +}; + +static int +do_asn1_sequence_string_tests(void) +{ + ASN1_STRING *astr = NULL; + const uint8_t *p; + long len; + int failed = 1; + + ERR_clear_error(); + + /* + * Test decoding of sequence with length and indefinite length into + * a string - in this case the ASN.1 is not decoded and is stored + * directly as the content for the string. + */ + if ((astr = ASN1_STRING_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_STRING_new() returned NULL\n"); + goto failed; + } + + p = asn1_sequence_ber; + len = sizeof(asn1_sequence_ber); + if (ASN1_item_d2i((ASN1_VALUE **)&astr, &p, len, + &ASN1_SEQUENCE_it) == NULL) { + fprintf(stderr, "FAIL: failed to decode ASN1_SEQUENCE\n"); + ERR_print_errors_fp(stderr); + goto failed; + } + + if (!asn1_compare_bytes("sequence", ASN1_STRING_data(astr), + ASN1_STRING_length(astr), asn1_sequence_content, + sizeof(asn1_sequence_content))) + goto failed; + + p = asn1_sequence_indefinite_ber; + len = sizeof(asn1_sequence_indefinite_ber); + if (ASN1_item_d2i((ASN1_VALUE **)&astr, &p, len, + &ASN1_SEQUENCE_it) == NULL) { + fprintf(stderr, "FAIL: failed to decode ASN1_SEQUENCE\n"); + ERR_print_errors_fp(stderr); + goto failed; + } + + if (!asn1_compare_bytes("sequence indefinite", ASN1_STRING_data(astr), + ASN1_STRING_length(astr), asn1_sequence_indefinite_content, + sizeof(asn1_sequence_indefinite_content))) + goto failed; + + failed = 0; + + failed: + ASN1_STRING_free(astr); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= do_asn1_constructed_tests(); + failed |= do_asn1_sequence_string_tests(); + + return (failed); +} diff --git a/tests/asn1evp.c b/tests/asn1evp.c new file mode 100644 index 0000000..0bf0a5f --- /dev/null +++ b/tests/asn1evp.c @@ -0,0 +1,150 @@ +/* $OpenBSD: asn1evp.c,v 1.5 2022/09/05 21:06:31 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#define TEST_NUM 0x7fffffffL + +unsigned char asn1_atios[] = { + 0x30, 0x10, 0x02, 0x04, 0x7f, 0xff, 0xff, 0xff, + 0x04, 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, +}; + +unsigned char test_octetstring[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +}; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +compare_data(const char *label, const unsigned char *d1, size_t d1_len, + const unsigned char *d2, size_t d2_len) +{ + if (d1_len != d2_len) { + fprintf(stderr, "FAIL: got %s with length %zu, want %zu\n", + label, d1_len, d2_len); + return -1; + } + if (memcmp(d1, d2, d1_len) != 0) { + fprintf(stderr, "FAIL: %s differs\n", label); + fprintf(stderr, "got:\n"); + hexdump(d1, d1_len); + fprintf(stderr, "want:\n"); + hexdump(d2, d2_len); + return -1; + } + return 0; +} + +int +main(int argc, char **argv) +{ + unsigned char data[16]; + long num = TEST_NUM; + ASN1_TYPE *at = NULL; + int failed = 1; + int len; + + if ((at = ASN1_TYPE_new()) == NULL) { + fprintf(stderr, "FAIL: ASN1_TYPE_new returned NULL\n"); + goto done; + } + + if (!ASN1_TYPE_set_int_octetstring(at, num, test_octetstring, + sizeof(test_octetstring))) { + fprintf(stderr, "FAIL: ASN1_TYPE_set_int_octetstring failed\n"); + goto done; + } + if (at->type != V_ASN1_SEQUENCE) { + fprintf(stderr, "FAIL: not a V_ASN1_SEQUENCE (%d != %d)\n", + at->type, V_ASN1_SEQUENCE); + goto done; + } + if (at->value.sequence->type != V_ASN1_OCTET_STRING) { + fprintf(stderr, "FAIL: not a V_ASN1_OCTET_STRING (%d != %d)\n", + at->type, V_ASN1_OCTET_STRING); + goto done; + } + if (compare_data("sequence", at->value.sequence->data, + at->value.sequence->length, asn1_atios, sizeof(asn1_atios)) == -1) + goto done; + + memset(&data, 0, sizeof(data)); + num = 0; + + if ((len = ASN1_TYPE_get_int_octetstring(at, &num, data, + sizeof(data))) < 0) { + fprintf(stderr, "FAIL: ASN1_TYPE_get_int_octetstring failed\n"); + goto done; + } + if (num != TEST_NUM) { + fprintf(stderr, "FAIL: got num %ld, want %ld\n", num, TEST_NUM); + goto done; + } + if (compare_data("octet string", data, len, + test_octetstring, sizeof(test_octetstring)) == -1) + goto done; + if (data[len] != 0) { + fprintf(stderr, "FAIL: octet string overflowed buffer\n"); + goto done; + } + + memset(&data, 0, sizeof(data)); + num = 0; + + /* With a limit buffer, the output should be truncated... */ + if ((len = ASN1_TYPE_get_int_octetstring(at, &num, data, 4)) < 0) { + fprintf(stderr, "FAIL: ASN1_TYPE_get_int_octetstring failed\n"); + goto done; + } + if (num != TEST_NUM) { + fprintf(stderr, "FAIL: got num %ld, want %ld\n", num, TEST_NUM); + goto done; + } + if (len != sizeof(test_octetstring)) { + fprintf(stderr, "FAIL: got length mismatch (%d != %zu)\n", + len, sizeof(test_octetstring)); + goto done; + } + if (compare_data("octet string", data, 4, test_octetstring, 4) == -1) + goto done; + if (data[4] != 0) { + fprintf(stderr, "FAIL: octet string overflowed buffer\n"); + goto done; + } + + failed = 0; + + done: + ASN1_TYPE_free(at); + + return failed; +} diff --git a/tests/asn1object.c b/tests/asn1object.c new file mode 100644 index 0000000..539c6aa --- /dev/null +++ b/tests/asn1object.c @@ -0,0 +1,495 @@ +/* $OpenBSD: asn1object.c,v 1.10 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2017, 2021, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include "asn1_local.h" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, + const unsigned char *d2, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: %s - byte lengths differ " + "(%d != %d)\n", label, len1, len2); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: %s - bytes differ\n", label); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + return 1; +} + +struct asn1_object_test { + const char *oid; + const char *txt; + const uint8_t content[255]; + size_t content_len; + const uint8_t der[255]; + size_t der_len; + int want_error; +}; + +struct asn1_object_test asn1_object_tests[] = { + { + .oid = "2.5", + .txt = "directory services (X.500)", + .content = { + 0x55, + }, + .content_len = 1, + .der = { + 0x06, 0x01, 0x55, + }, + .der_len = 3, + }, + { + .oid = "2.5.4", + .txt = "X509", + .content = { + 0x55, 0x04, + }, + .content_len = 2, + .der = { + 0x06, 0x02, 0x55, 0x04, + }, + .der_len = 4, + }, + { + .oid = "2.5.4.10", + .txt = "organizationName", + .content = { + 0x55, 0x04, 0x0a, + }, + .content_len = 3, + .der = { + 0x06, 0x03, 0x55, 0x04, 0x0a, + }, + .der_len = 5, + }, + { + .oid = "2 5 4 10", + .txt = "organizationName", + .content = { + 0x55, 0x04, 0x0a, + }, + .content_len = 3, + .der = { + 0x06, 0x03, 0x55, 0x04, 0x0a, + }, + .der_len = 5, + }, + { + .oid = "2.5.0.0", + .txt = "2.5.0.0", + .content = { + 0x55, 0x00, 0x00, + }, + .content_len = 3, + .der = { + 0x06, 0x03, 0x55, 0x00, 0x00, + }, + .der_len = 5, + }, + { + .oid = "0.0.0.0", + .txt = "0.0.0.0", + .content = { + 0x00, 0x00, 0x00, + }, + .content_len = 3, + .der = { + 0x06, 0x03, 0x00, 0x00, 0x00, + }, + .der_len = 5, + }, + { + .oid = "1.3.6.1.4.1.11129.2.4.5", + .txt = "CT Certificate SCTs", + .content = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, + 0x04, 0x05, + }, + .content_len = 10, + .der = { + 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, + 0x79, 0x02, 0x04, 0x05, + }, + .der_len = 12, + }, + { + .oid = "2.00005.0000000000004.10", + .want_error = ASN1_R_INVALID_NUMBER, + }, + { + .oid = "2..5.4.10", + .want_error = ASN1_R_INVALID_NUMBER, + }, + { + .oid = "2.5..4.10", + .want_error = ASN1_R_INVALID_NUMBER, + }, + { + .oid = "2.5.4..10", + .want_error = ASN1_R_INVALID_NUMBER, + }, + { + .oid = "2.5.4.10.", + .want_error = ASN1_R_INVALID_NUMBER, + }, + { + .oid = "3.5.4.10", + .want_error = ASN1_R_FIRST_NUM_TOO_LARGE, + }, + { + .oid = "0.40.4.10", + .want_error = ASN1_R_SECOND_NUMBER_TOO_LARGE, + }, + { + .oid = "1.40.4.10", + .want_error = ASN1_R_SECOND_NUMBER_TOO_LARGE, + }, + { + .oid = "2", + .want_error = ASN1_R_MISSING_SECOND_NUMBER, + }, + { + .oid = "2.5 4.10", + .want_error = ASN1_R_INVALID_SEPARATOR, + }, + { + .oid = "2,5,4,10", + .want_error = ASN1_R_INVALID_SEPARATOR, + }, + { + .oid = "2.5,4.10", + .want_error = ASN1_R_INVALID_DIGIT, + }, + { + .oid = "2a.5.4.10", + .want_error = ASN1_R_INVALID_SEPARATOR, + }, + { + .oid = "2.5a.4.10", + .want_error = ASN1_R_INVALID_DIGIT, + }, +}; + +#define N_ASN1_OBJECT_TESTS \ + (sizeof(asn1_object_tests) / sizeof(*asn1_object_tests)) + +static int +do_asn1_object_test(struct asn1_object_test *aot) +{ + ASN1_OBJECT *aobj = NULL; + uint8_t buf[1024]; + const uint8_t *p; + uint8_t *q; + int err, ret; + int failed = 1; + + ERR_clear_error(); + + ret = a2d_ASN1_OBJECT(NULL, 0, aot->oid, -1); + if (ret < 0 || (size_t)ret != aot->content_len) { + fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') = %d, want %zu\n", + aot->oid, ret, aot->content_len); + goto failed; + } + ret = a2d_ASN1_OBJECT(buf, sizeof(buf), aot->oid, -1); + if (ret < 0 || (size_t)ret != aot->content_len) { + fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') = %d, want %zu\n", + aot->oid, ret, aot->content_len); + goto failed; + } + if (aot->content_len == 0) { + err = ERR_peek_error(); + if (ERR_GET_REASON(err) != aot->want_error) { + fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') - got " + "error reason %d, want %d\n", aot->oid, + ERR_GET_REASON(err), aot->want_error); + goto failed; + } + goto done; + } + + if (!asn1_compare_bytes("ASN1_OBJECT content", buf, ret, aot->content, + aot->content_len)) + goto failed; + + p = aot->content; + if ((aobj = c2i_ASN1_OBJECT(NULL, &p, aot->content_len)) == NULL) { + fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() failed\n"); + goto failed; + } + + q = buf; + ret = i2d_ASN1_OBJECT(aobj, &q); + if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, aot->der, + aot->der_len)) + goto failed; + + ASN1_OBJECT_free(aobj); + aobj = NULL; + + p = aot->der; + if ((aobj = d2i_ASN1_OBJECT(NULL, &p, aot->der_len)) == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n"); + goto failed; + } + if (p != aot->der + aot->der_len) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() p = %p, want %p\n", + p, aot->der + aot->der_len); + goto failed; + } + + if (aot->txt != NULL) { + ret = i2t_ASN1_OBJECT(buf, sizeof(buf), aobj); + if (ret <= 0 || (size_t)ret >= sizeof(buf)) { + fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() failed\n"); + goto failed; + } + if (strcmp(aot->txt, buf) != 0) { + fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() = '%s', " + "want '%s'\n", buf, aot->txt); + goto failed; + } + } + + done: + failed = 0; + + failed: + ASN1_OBJECT_free(aobj); + + return failed; +} + +static int +asn1_object_test(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_ASN1_OBJECT_TESTS; i++) + failed |= do_asn1_object_test(&asn1_object_tests[i]); + + return failed; +} + +const uint8_t asn1_object_bad_content1[] = { + 0x55, 0x80, 0x04, 0x0a, +}; +const uint8_t asn1_object_bad_content2[] = { + 0x55, 0x04, 0x8a, +}; + +static int +asn1_object_bad_content_test(void) +{ + ASN1_OBJECT *aobj = NULL; + const uint8_t *p; + size_t len; + int failed = 1; + + p = asn1_object_bad_content1; + len = sizeof(asn1_object_bad_content1); + if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) { + fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad " + "content 1\n"); + goto failed; + } + + p = asn1_object_bad_content2; + len = sizeof(asn1_object_bad_content2); + if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) { + fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad " + "content 2\n"); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(aobj); + + return failed; +} + +static int +asn1_object_txt_test(void) +{ + const char *obj_txt = "organizationName"; + ASN1_OBJECT *aobj = NULL; + uint8_t small_buf[2]; + const uint8_t *p; + int err, len, ret; + BIO *bio = NULL; + char *data; + long data_len; + int failed = 1; + + ERR_clear_error(); + + ret = a2d_ASN1_OBJECT(small_buf, sizeof(small_buf), "1.2.3.4", -1); + if (ret != 0) { + fprintf(stderr, "FAIL: a2d_ASN1_OBJECT() with small buffer " + "returned %d, want %d\n", ret, 0); + goto failed; + } + err = ERR_peek_error(); + if (ERR_GET_REASON(err) != ASN1_R_BUFFER_TOO_SMALL) { + fprintf(stderr, "FAIL: Got error reason %d, want %d\n", + ERR_GET_REASON(err), ASN1_R_BUFFER_TOO_SMALL); + goto failed; + } + + p = &asn1_object_tests[2].der[0]; + len = asn1_object_tests[2].der_len; + aobj = d2i_ASN1_OBJECT(NULL, &p, len); + if (aobj == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n"); + goto failed; + } + ret = i2t_ASN1_OBJECT(small_buf, sizeof(small_buf), aobj); + if (ret < 0 || (unsigned long)ret != strlen(obj_txt)) { + fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() with small buffer " + "returned %d, want %zu\n", ret, strlen(obj_txt)); + goto failed; + } + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "FAIL: BIO_new() returned NULL\n"); + goto failed; + } + ret = i2a_ASN1_OBJECT(bio, NULL); + if (ret != 4) { + fprintf(stderr, "FAIL: i2a_ASN1_OBJECT(_, NULL) returned %d, " + "want 4\n", ret); + goto failed; + } + data_len = BIO_get_mem_data(bio, &data); + if (ret != data_len || memcmp("NULL", data, data_len) != 0) { + fprintf(stderr, "FAIL: i2a_ASN1_OBJECT(_, NULL) did not return " + "'NULL'\n"); + goto failed; + } + + if ((ret = BIO_reset(bio)) <= 0) { + fprintf(stderr, "FAIL: BIO_reset failed: ret = %d\n", ret); + goto failed; + } + ret = i2a_ASN1_OBJECT(bio, aobj); + if (ret < 0 || (unsigned long)ret != strlen(obj_txt)) { + fprintf(stderr, "FAIL: i2a_ASN1_OBJECT() returned %d, " + "want %zu\n", ret, strlen(obj_txt)); + goto failed; + } + data_len = BIO_get_mem_data(bio, &data); + if (ret != data_len || memcmp(obj_txt, data, data_len) != 0) { + fprintf(stderr, "FAIL: i2a_ASN1_OBJECT() did not return " + "'%s'\n", obj_txt); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(aobj); + BIO_free(bio); + + return failed; +} + +const uint8_t asn1_large_oid_der[] = { + 0x06, 0x26, + 0x2b, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, +}; + +static int +asn1_object_large_oid_test(void) +{ + ASN1_OBJECT *aobj = NULL; + uint8_t buf[1024]; + const uint8_t *p; + uint8_t *q; + int ret; + int failed = 1; + + failed = 0; + + p = asn1_large_oid_der; + aobj = d2i_ASN1_OBJECT(NULL, &p, sizeof(asn1_large_oid_der)); + if (aobj == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed with " + "large oid\n"); + goto failed; + } + + q = buf; + ret = i2d_ASN1_OBJECT(aobj, &q); + if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, asn1_large_oid_der, + sizeof(asn1_large_oid_der))) + goto failed; + + failed: + ASN1_OBJECT_free(aobj); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= asn1_object_test(); + failed |= asn1_object_bad_content_test(); + failed |= asn1_object_txt_test(); + failed |= asn1_object_large_oid_test(); + + return (failed); +} diff --git a/tests/asn1oct.c b/tests/asn1oct.c new file mode 100644 index 0000000..d989d1e --- /dev/null +++ b/tests/asn1oct.c @@ -0,0 +1,280 @@ +/* $OpenBSD: asn1oct.c,v 1.4 2023/05/13 07:17:32 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#define TESTBUFFER_SIZE 20 + +static const struct i2s_asn1_octet_string_test { + const char *desc; + const uint8_t buf[TESTBUFFER_SIZE]; + long len; + const char *want; +} i2s_test[] = { + { + .desc = "Empty buffer gives empty string", + .buf = { 0x00, }, + .len = 0, + .want = "", + }, + { + .desc = "all hex digits", + .buf = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, }, + .len = 8, + .want = "01:23:45:67:89:AB:CD:EF", + }, + { + .desc = "all hex digits, scrambled", + .buf = { 0x98, 0x24, 0xbf, 0x3a, 0xc7, 0xd6, 0x01, 0x5e, }, + .len = 8, + .want = "98:24:BF:3A:C7:D6:01:5E", + }, + { + .desc = "Embedded 0 byte", + .buf = { 0x7a, 0x00, 0xbb, }, + .len = 3, + .want = "7A:00:BB", + }, + { + .desc = "All zeroes", + .buf = { 0x00, 0x00, 0x00, 0x00, 0x00, }, + .len = 4, + .want = "00:00:00:00", + }, + { + .desc = "All bits set", + .buf = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, + .len = 8, + .want = "FF:FF:FF:FF:FF:FF:FF:FF", + }, + { + .desc = "negative length", + .buf = { 0x00, }, + .len = -1, + }, +}; + +#define N_I2S_TESTS (sizeof(i2s_test) / sizeof(i2s_test[0])) + +static int +test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test *test) +{ + ASN1_OCTET_STRING *aos = NULL; + int should_fail = test->want == NULL; + char *got = NULL; + int failed = 0; + + if ((aos = ASN1_OCTET_STRING_new()) == NULL) + errx(1, "ASN1_OCTET_STRING_new"); + + if (!ASN1_STRING_set(aos, (void *)test->buf, test->len)) + errx(1, "ASN1_STRING_set"); + + if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) { + if (!should_fail) + errx(1, "i2s_ASN1_OCTET_STRING"); + } + + if (!should_fail && strcmp(test->want, got) != 0) { + fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n", + __func__, test->desc, test->want, got); + failed |= 1; + } + + ASN1_OCTET_STRING_free(aos); + free(got); + + return failed; +} + +static int +test_new_ASN1_OCTET_STRING(void) +{ + ASN1_OCTET_STRING *aos = NULL; + char *got; + int failed = 0; + + if ((aos = ASN1_OCTET_STRING_new()) == NULL) + errx(1, "%s: ASN1_OCTET_STRING_new", __func__); + if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) + errx(1, "%s: i2s_ASN1_OCTET_STRING", __func__); + + if (strcmp("", got) != 0) { + fprintf(stderr, "%s failed: want \"\", got \"%s\"\n", + __func__, got); + failed |= 1; + } + + ASN1_OCTET_STRING_free(aos); + free(got); + + return failed; +} + +static int +run_i2s_ASN1_OCTET_STRING_tests(void) +{ + size_t i; + int failed = 0; + + failed |= test_new_ASN1_OCTET_STRING(); + + for (i = 0; i < N_I2S_TESTS; i++) + failed |= test_i2s_ASN1_OCTET_STRING(&i2s_test[i]); + + return failed; +} + +static const struct s2i_asn1_octet_string_test { + const char *desc; + const char *in; + const char *want; +} s2i_test[] = { + /* Tests that should succeed. */ + { + .desc = "empty string", + .in = "", + .want = "", + }, + { + .desc = "only colons", + .in = ":::::::", + .want = "", + }, + { + .desc = "a 0 octet", + .in = "00", + .want = "00", + }, + { + .desc = "a 0 octet with stupid colons", + .in = ":::00:::::", + .want = "00", + }, + { + .desc = "more stupid colons", + .in = ":::C0fF::Ee:::::", + .want = "C0:FF:EE", + }, + { + .desc = "all hex digits", + .in = "0123456789abcdef", + .want = "01:23:45:67:89:AB:CD:EF", + }, + + /* Tests that should fail. */ + { + .desc = "colons between hex digits", + .in = "A:F", + }, + { + .desc = "more colons between hex digits", + .in = "5:7", + }, + { + .desc = "one hex digit", + .in = "1", + }, + { + .desc = "three hex digits", + .in = "bad", + }, + { + .desc = "three hex digits, colon after first digit", + .in = "b:ad", + }, + { + .desc = "three hex digits, colon after second digit", + .in = "ba:d", + }, + { + .desc = "non-hex digit", + .in = "g00d", + }, + { + .desc = "non-hex digits", + .in = "d0gged", + }, + { + .desc = "trailing non-hex digit", + .in = "d00der", + }, +}; + +#define N_S2I_TESTS (sizeof(s2i_test) / sizeof(s2i_test[0])) + +static int +test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test *test) +{ + ASN1_OCTET_STRING *aos = NULL; + char *got = NULL; + int should_fail = test->want == NULL; + int failed = 0; + + if ((aos = s2i_ASN1_OCTET_STRING(NULL, NULL, test->in)) == NULL) { + if (!should_fail) + errx(1, "%s: s2i_ASN1_OCTET_STRING", test->desc); + goto done; + } + + if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) + errx(1, "%s: i2s_ASN1_OCTET_STRING", test->desc); + + assert(test->want != NULL); + if (strcmp(test->want, got) != 0) { + fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n", + __func__, test->desc, test->want, got); + failed |= 1; + } + + done: + ASN1_OCTET_STRING_free(aos); + free(got); + + return failed; +} + +static int +run_s2i_ASN1_OCTET_STRING_tests(void) +{ + size_t i; + int failed = 0; + + failed |= test_new_ASN1_OCTET_STRING(); + + for (i = 0; i < N_S2I_TESTS; i++) + failed |= test_s2i_ASN1_OCTET_STRING(&s2i_test[i]); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= run_i2s_ASN1_OCTET_STRING_tests(); + failed |= run_s2i_ASN1_OCTET_STRING_tests(); + + return failed; +} diff --git a/tests/asn1string_copy.c b/tests/asn1string_copy.c new file mode 100644 index 0000000..9c71dd0 --- /dev/null +++ b/tests/asn1string_copy.c @@ -0,0 +1,119 @@ +/* $OpenBSD: asn1string_copy.c,v 1.1 2021/11/13 20:50:14 schwarze Exp $ */ +/* + * Copyright (c) 2021 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +int +main(void) +{ + const unsigned char *data = "hello world"; + const unsigned char *str; + ASN1_STRING *src, *dst; + int irc; + + /* Set up the source string. */ + + if ((src = ASN1_IA5STRING_new()) == NULL) + err(1, "FAIL: ASN1_IA5STRING_new() returned NULL"); + if (ASN1_STRING_set(src, data, -1) == 0) + err(1, "FAIL: ASN1_STRING_set(src) failed"); + if ((str = ASN1_STRING_get0_data(src)) == NULL) + errx(1, "FAIL: 1st ASN1_STRING_get0_data(src) returned NULL"); + if (strcmp(str, data)) + errx(1, "FAIL: 1st ASN1_STRING_get0_data(src) " + "returned wrong data: \"%s\" (expected \"%s\")", + str, data); + if ((irc = ASN1_STRING_length(src)) != (int)strlen(data)) + errx(1, "FAIL: 1st ASN1_STRING_length(src) " + "returned a wrong length: %d (expected %zu)", + irc, strlen(data)); + if ((irc = ASN1_STRING_type(src)) != V_ASN1_IA5STRING) + errx(1, "FAIL: 1st ASN1_STRING_type(src) " + "returned a wrong type: %d (expected %d)", + irc, V_ASN1_IA5STRING); + + /* Set up the destination string. */ + + if ((dst = ASN1_STRING_new()) == NULL) + err(1, "FAIL: ASN1_STRING_new() returned NULL"); + if ((str = ASN1_STRING_get0_data(dst)) != NULL) + errx(1, "FAIL: 1st ASN1_STRING_get0_data(dst) " + "returned \"%s\" (expected NULL)", str); + if ((irc = ASN1_STRING_length(dst)) != 0) + errx(1, "FAIL: 1st ASN1_STRING_length(dst) " + "returned a wrong length: %d (expected 0)", irc); + if ((irc = ASN1_STRING_type(dst)) != V_ASN1_OCTET_STRING) + errx(1, "FAIL: 1st ASN1_STRING_type(dst) " + "returned a wrong type: %d (expected %d)", + irc, V_ASN1_OCTET_STRING); + ASN1_STRING_length_set(dst, -1); + if ((str = ASN1_STRING_get0_data(dst)) != NULL) + errx(1, "FAIL: 2nd ASN1_STRING_get0_data(dst) " + "returned \"%s\" (expected NULL)", str); + if ((irc = ASN1_STRING_length(dst)) != -1) + errx(1, "FAIL: 2nd ASN1_STRING_length(dst) " + "returned a wrong length: %d (expected -1)", irc); + if ((irc = ASN1_STRING_type(dst)) != V_ASN1_OCTET_STRING) + errx(1, "FAIL: 2nd ASN1_STRING_type(dst) " + "returned a wrong type: %d (expected %d)", + irc, V_ASN1_OCTET_STRING); + + /* Attempt to copy in the wrong direction. */ + + if (ASN1_STRING_copy(src, dst) != 0) + errx(1, "FAIL: ASN1_STRING_copy unexpectedly succeeded"); + if ((str = ASN1_STRING_get0_data(src)) == NULL) + errx(1, "FAIL: 2nd ASN1_STRING_get0_data(src) returned NULL"); + if (strcmp(str, data)) + errx(1, "FAIL: 2nd ASN1_STRING_get0_data(src) " + "returned wrong data: \"%s\" (expected \"%s\")", + str, data); + if ((irc = ASN1_STRING_length(src)) != (int)strlen(data)) + errx(1, "FAIL: 2nd ASN1_STRING_length(src) " + "returned a wrong length: %d (expected %zu)", + irc, strlen(data)); + if ((irc = ASN1_STRING_type(src)) != V_ASN1_IA5STRING) + errx(1, "FAIL: 2nd ASN1_STRING_type(src) " + "returned a wrong type: %d (expected %d)", + irc, V_ASN1_IA5STRING); + + /* Copy in the right direction. */ + + if (ASN1_STRING_copy(dst, src) != 1) + err(1, "FAIL: ASN1_STRING_copy unexpectedly failed"); + if ((str = ASN1_STRING_get0_data(dst)) == NULL) + errx(1, "FAIL: 3rd ASN1_STRING_get0_data(dst) returned NULL"); + if (strcmp(str, data)) + errx(1, "FAIL: 3rd ASN1_STRING_get0_data(dst) " + "returned wrong data: \"%s\" (expected \"%s\")", + str, data); + if ((irc = ASN1_STRING_length(dst)) != (int)strlen(data)) + errx(1, "FAIL: 3rd ASN1_STRING_length(dst) " + "returned a wrong length: %d (expected %zu)", + irc, strlen(data)); + if ((irc = ASN1_STRING_type(dst)) != V_ASN1_IA5STRING) + errx(1, "FAIL: 3rd ASN1_STRING_type(dst) " + "returned a wrong type: %d (expected %d)", + irc, V_ASN1_IA5STRING); + + ASN1_STRING_free(src); + ASN1_STRING_free(dst); + return 0; +} diff --git a/tests/asn1test.c b/tests/asn1test.c new file mode 100644 index 0000000..6e9362b --- /dev/null +++ b/tests/asn1test.c @@ -0,0 +1,478 @@ +/* $OpenBSD: asn1test.c,v 1.12 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2014, 2016 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#include "ssl_local.h" + +int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); +SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, + long length); + +X509 *peer_cert; + +unsigned char *peer_cert_pem = + "-----BEGIN CERTIFICATE-----\n" + "MIIBcTCCARugAwIBAgIJAPYhaZJAvUuUMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV\n" + "BAoMCVRlc3QgUGVlcjAeFw0xNjEyMjYxNDQ3NDdaFw0yNjEyMjQxNDQ3NDdaMBQx\n" + "EjAQBgNVBAoMCVRlc3QgUGVlcjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCyhAdJ\n" + "wojHv/uKONh8MbmR2U2+VF1HQusnLfSfHPqkJfvDzLWJ41TG7QcXkx2rIJVtAFrO\n" + "U9yNdFYJLA/hsrbjAgMBAAGjUDBOMB0GA1UdDgQWBBS3bZOw7fvaortdsdE2TPMq\n" + "IRXFRzAfBgNVHSMEGDAWgBS3bZOw7fvaortdsdE2TPMqIRXFRzAMBgNVHRMEBTAD\n" + "AQH/MA0GCSqGSIb3DQEBBQUAA0EAHsxNS+rNUZbopeDMhVIviOfUmelDjJrT56Rc\n" + "VJoFN3Gc1cV8nQAHm9aJs71uksC+MN04Pzh0WqmYX9XXrnYPcg==\n" + "-----END CERTIFICATE-----\n"; + +struct ssl_asn1_test { + SSL_SESSION session; + int peer_cert; + const unsigned char asn1[1024]; + int asn1_len; +}; + +unsigned char tlsext_tick[] = { + 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x31, 0x36, 0x30, 0x3a, 0x20, 0x37, + 0x74, 0x68, 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, + 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, + 0x45, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x35, + 0x32, 0x39, 0x38, 0x3a, 0x20, 0x38, 0x74, 0x68, + 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, + 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, + 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x39, + 0x38, 0x3a, 0x20, 0x32, 0x31, 0x73, 0x74, 0x20, + 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, + 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x33, 0x34, 0x37, 0x30, + 0x3a, 0x20, 0x33, 0x30, 0x74, 0x68, 0x20, 0x4d, + 0x61, 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, + 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x31, 0x39, 0x35, 0x3a, 0x20, 0x35, + 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, + 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, + 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x32, + 0x32, 0x31, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20, + 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31, + 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x34, 0x3a, + 0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, + 0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, +}; + +struct ssl_asn1_test ssl_asn1_tests[] = { + { + .session = { + .cipher_id = 0x03000000L | 1, + .ssl_version = TLS1_2_VERSION, + }, + .asn1 = { + 0x30, 0x13, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, + 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x00, 0x04, + 0x00, 0xa4, 0x02, 0x04, 0x00, + }, + .asn1_len = 21, + }, + { + .session = { + .cipher_id = 0x03000000L | 1, + .ssl_version = TLS1_2_VERSION, + .master_key_length = 26, + .session_id = "0123456789", + .session_id_length = 10, + .sid_ctx = "abcdefghijklmnopqrstuvwxyz", + .sid_ctx_length = 26, + }, + .asn1 = { + 0x30, 0x51, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, + 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x0a, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x04, 0x1a, 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, 0xa4, 0x1c, 0x04, + 0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, + }, + .asn1_len = 83, + }, + { + .session = { + .cipher_id = 0x03000000L | 1, + .ssl_version = TLS1_2_VERSION, + .master_key_length = 26, + .session_id = "0123456789", + .session_id_length = 10, + .sid_ctx = "abcdefghijklmnopqrstuvwxyz", + .sid_ctx_length = 26, + .time = 1405266069, + .timeout = 5, + .verify_result = 42, + .tlsext_hostname = "libressl.openbsd.org", + .tlsext_tick_lifetime_hint = 0x7abbccdd, + .tlsext_tick = tlsext_tick, + .tlsext_ticklen = sizeof(tlsext_tick), + }, + .peer_cert = 1, + .asn1 = { + 0x30, 0x82, 0x02, 0xd1, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x03, 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, + 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, + 0x37, 0x38, 0x39, 0x04, 0x1a, 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, 0xa1, + 0x06, 0x02, 0x04, 0x53, 0xc2, 0xa8, 0x95, 0xa2, + 0x03, 0x02, 0x01, 0x05, 0xa3, 0x82, 0x01, 0x75, + 0x30, 0x82, 0x01, 0x71, 0x30, 0x82, 0x01, 0x1b, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xf6, 0x21, 0x69, 0x92, 0x40, 0xbd, 0x4b, 0x94, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x0c, 0x09, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x50, 0x65, 0x65, 0x72, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x36, 0x31, 0x32, 0x32, 0x36, 0x31, + 0x34, 0x34, 0x37, 0x34, 0x37, 0x5a, 0x17, 0x0d, + 0x32, 0x36, 0x31, 0x32, 0x32, 0x34, 0x31, 0x34, + 0x34, 0x37, 0x34, 0x37, 0x5a, 0x30, 0x14, 0x31, + 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x09, 0x54, 0x65, 0x73, 0x74, 0x20, 0x50, + 0x65, 0x65, 0x72, 0x30, 0x5c, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, + 0x48, 0x02, 0x41, 0x00, 0xb2, 0x84, 0x07, 0x49, + 0xc2, 0x88, 0xc7, 0xbf, 0xfb, 0x8a, 0x38, 0xd8, + 0x7c, 0x31, 0xb9, 0x91, 0xd9, 0x4d, 0xbe, 0x54, + 0x5d, 0x47, 0x42, 0xeb, 0x27, 0x2d, 0xf4, 0x9f, + 0x1c, 0xfa, 0xa4, 0x25, 0xfb, 0xc3, 0xcc, 0xb5, + 0x89, 0xe3, 0x54, 0xc6, 0xed, 0x07, 0x17, 0x93, + 0x1d, 0xab, 0x20, 0x95, 0x6d, 0x00, 0x5a, 0xce, + 0x53, 0xdc, 0x8d, 0x74, 0x56, 0x09, 0x2c, 0x0f, + 0xe1, 0xb2, 0xb6, 0xe3, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0xb7, 0x6d, 0x93, 0xb0, 0xed, 0xfb, 0xda, 0xa2, + 0xbb, 0x5d, 0xb1, 0xd1, 0x36, 0x4c, 0xf3, 0x2a, + 0x21, 0x15, 0xc5, 0x47, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xb7, 0x6d, 0x93, 0xb0, 0xed, 0xfb, 0xda, + 0xa2, 0xbb, 0x5d, 0xb1, 0xd1, 0x36, 0x4c, 0xf3, + 0x2a, 0x21, 0x15, 0xc5, 0x47, 0x30, 0x0c, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, + 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x41, 0x00, 0x1e, 0xcc, 0x4d, + 0x4b, 0xea, 0xcd, 0x51, 0x96, 0xe8, 0xa5, 0xe0, + 0xcc, 0x85, 0x52, 0x2f, 0x88, 0xe7, 0xd4, 0x99, + 0xe9, 0x43, 0x8c, 0x9a, 0xd3, 0xe7, 0xa4, 0x5c, + 0x54, 0x9a, 0x05, 0x37, 0x71, 0x9c, 0xd5, 0xc5, + 0x7c, 0x9d, 0x00, 0x07, 0x9b, 0xd6, 0x89, 0xb3, + 0xbd, 0x6e, 0x92, 0xc0, 0xbe, 0x30, 0xdd, 0x38, + 0x3f, 0x38, 0x74, 0x5a, 0xa9, 0x98, 0x5f, 0xd5, + 0xd7, 0xae, 0x76, 0x0f, 0x72, 0xa4, 0x1c, 0x04, + 0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0xa5, 0x03, 0x02, 0x01, 0x2a, + 0xa6, 0x16, 0x04, 0x14, 0x6c, 0x69, 0x62, 0x72, + 0x65, 0x73, 0x73, 0x6c, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, + 0xa9, 0x06, 0x02, 0x04, 0x7a, 0xbb, 0xcc, 0xdd, + 0xaa, 0x81, 0xd2, 0x04, 0x81, 0xcf, 0x43, 0x56, + 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x36, 0x30, 0x3a, 0x20, 0x37, 0x74, 0x68, + 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, + 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, + 0x32, 0x30, 0x31, 0x30, 0x2d, 0x35, 0x32, 0x39, + 0x38, 0x3a, 0x20, 0x38, 0x74, 0x68, 0x20, 0x41, + 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, + 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, + 0x31, 0x34, 0x2d, 0x30, 0x31, 0x39, 0x38, 0x3a, + 0x20, 0x32, 0x31, 0x73, 0x74, 0x20, 0x41, 0x70, + 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, + 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, + 0x34, 0x2d, 0x33, 0x34, 0x37, 0x30, 0x3a, 0x20, + 0x33, 0x30, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x79, + 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, + 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, + 0x31, 0x39, 0x35, 0x3a, 0x20, 0x35, 0x74, 0x68, + 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, + 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, + 0x30, 0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x31, + 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, + 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, + 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, + 0x2d, 0x30, 0x32, 0x32, 0x34, 0x3a, 0x20, 0x35, + 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, + 0x32, 0x30, 0x31, 0x34, 0x0a, + }, + .asn1_len = 725, + }, + { + .session = { + .cipher_id = 0x03000000L | 1, + .ssl_version = TLS1_2_VERSION, + .timeout = -1, + }, + .asn1 = { + 0x0, + }, + .asn1_len = -1, + }, + { + .session = { + .cipher_id = 0x03000000L | 1, + .ssl_version = TLS1_2_VERSION, + .time = -1, + }, + .asn1 = { + 0x0, + }, + .asn1_len = -1, + }, +}; + +#define N_SSL_ASN1_TESTS \ + (sizeof(ssl_asn1_tests) / sizeof(*ssl_asn1_tests)) + +static int +session_strcmp(const unsigned char *o1, const unsigned char *o2, size_t len) +{ + if (o1 == NULL && o2 == NULL) + return (0); + if (o1 == NULL || o2 == NULL) + return (1); + return memcmp(o1, o2, len); +} + +static int +session_cmp(SSL_SESSION *s1, SSL_SESSION *s2) +{ + /* Compare the ASN.1 encoded values from two sessions. */ + if (s1->ssl_version != s2->ssl_version) { + fprintf(stderr, "ssl_version differs: %d != %d\n", + s1->ssl_version, s2->ssl_version); + return (1); + } + if (s1->cipher_id != s2->cipher_id) { + fprintf(stderr, "cipher_id differs: %ld != %ld\n", + s1->cipher_id, s2->cipher_id); + return (1); + } + + if (s1->master_key_length != s2->master_key_length) { + fprintf(stderr, "master_key_length differs: %zu != %zu\n", + s1->master_key_length, s2->master_key_length); + return (1); + } + if (session_strcmp(s1->master_key, s2->master_key, + s1->master_key_length) != 0) { + fprintf(stderr, "master_key differs\n"); + return (1); + } + + if (s1->session_id_length != s2->session_id_length) { + fprintf(stderr, "session_id_length differs: %zu != %zu\n", + s1->session_id_length, s2->session_id_length); + return (1); + } + if (session_strcmp(s1->session_id, s2->session_id, + s1->session_id_length) != 0) { + fprintf(stderr, "session_id differs\n"); + return (1); + } + + if (s1->sid_ctx_length != s2->sid_ctx_length) { + fprintf(stderr, "sid_ctx_length differs: %zu != %zu\n", + s1->sid_ctx_length, s2->sid_ctx_length); + return (1); + } + if (session_strcmp(s1->sid_ctx, s2->sid_ctx, + s1->sid_ctx_length) != 0) { + fprintf(stderr, "sid_ctx differs\n"); + return (1); + } + + /* d2i_SSL_SESSION uses the current time if decoding a zero value. */ + if ((s1->time != s2->time) && s1->time != 0 && s2->time != 0) { + fprintf(stderr, "time differs: %lld != %lld\n", + (long long)s1->time, (long long)s2->time); + return (1); + } + /* d2i_SSL_SESSION uses a timeout of 3 if decoding a zero value. */ + if ((s1->timeout != s2->timeout) && + s1->timeout != 3 && s2->timeout != 3) { + fprintf(stderr, "timeout differs: %ld != %ld\n", + s1->timeout, s2->timeout); + return (1); + } + + /* Ensure that a certificate is or is not present in both. */ + if ((s1->peer_cert != NULL || s2->peer_cert != NULL) && + (s1->peer_cert == NULL || s2->peer_cert == NULL || + X509_cmp(s1->peer_cert, s2->peer_cert) != 0)) { + fprintf(stderr, "peer_cert differs\n"); + return (1); + } + + if (s1->verify_result != s2->verify_result) { + fprintf(stderr, "verify_result differs: %ld != %ld\n", + s1->verify_result, s2->verify_result); + return (1); + } + + if (session_strcmp(s1->tlsext_hostname, s2->tlsext_hostname, + (s1->tlsext_hostname ? strlen(s1->tlsext_hostname) : 0)) != 0) { + fprintf(stderr, "sid_ctx differs\n"); + return (1); + } + if (s1->tlsext_tick_lifetime_hint != s2->tlsext_tick_lifetime_hint) { + fprintf(stderr, "tlsext_tick_lifetime_hint differs: " + "%u != %u\n", s1->tlsext_tick_lifetime_hint, + s2->tlsext_tick_lifetime_hint); + return (1); + } + if (s1->tlsext_ticklen != s2->tlsext_ticklen) { + fprintf(stderr, "tlsext_ticklen differs: %zu != %zu\n", + s1->tlsext_ticklen, s2->tlsext_ticklen); + return (1); + } + if (session_strcmp(s1->tlsext_tick, s2->tlsext_tick, + s1->tlsext_ticklen) != 0) { + fprintf(stderr, "tlsext_tick differs\n"); + return (1); + } + + return (0); +} + +static int +do_ssl_asn1_test(int test_no, struct ssl_asn1_test *sat) +{ + SSL_SESSION *sp = NULL; + unsigned char *ap, *asn1 = NULL; + const unsigned char *pp; + int i, len, rv = 1; + + if (sat->peer_cert) + sat->session.peer_cert = peer_cert; + + len = i2d_SSL_SESSION(&sat->session, NULL); + if (len != sat->asn1_len) { + fprintf(stderr, "FAIL: test %d returned ASN1 length %d, " + "want %d\n", test_no, len, sat->asn1_len); + goto failed; + } + + /* See if the test is expected to fail... */ + if (sat->asn1_len == -1) + return (0); + + if ((asn1 = malloc(len)) == NULL) + errx(1, "failed to allocate memory"); + + ap = asn1; + len = i2d_SSL_SESSION(&sat->session, &ap); + + /* Check the length again since the code path is different. */ + if (len != sat->asn1_len) { + fprintf(stderr, "FAIL: test %d returned ASN1 length %d, " + "want %d\n", test_no, len, sat->asn1_len); + goto failed; + } + /* ap should now point at the end of the buffer. */ + if (ap - asn1 != len) { + fprintf(stderr, "FAIL: test %d pointer increment does not " + "match length (%d != %d)\n", test_no, (int)(ap - asn1), len); + goto failed; + } + + if (memcmp(asn1, &sat->asn1, len) != 0) { + fprintf(stderr, "FAIL: test %d - encoding differs:\n", test_no); + fprintf(stderr, "encoding:\n"); + for (i = 1; i <= len; i++) { + fprintf(stderr, " 0x%02hhx,", asn1[i - 1]); + if (i % 8 == 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + fprintf(stderr, "test data:\n"); + for (i = 1; i <= sat->asn1_len; i++) { + fprintf(stderr, " 0x%02hhx,", sat->asn1[i - 1]); + if (i % 8 == 0) + fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + goto failed; + } + + pp = sat->asn1; + + if ((sp = d2i_SSL_SESSION(NULL, &pp, sat->asn1_len)) == NULL) { + fprintf(stderr, "FAIL: test %d - decoding failed\n", test_no); + goto failed; + } + + if (session_cmp(sp, &sat->session) != 0) { + fprintf(stderr, "FAIL: test %d - decoding differs\n", test_no); + goto failed; + } + + rv = 0; + + failed: + ERR_print_errors_fp(stderr); + SSL_SESSION_free(sp); + free(asn1); + + return (rv); +} + +int +main(int argc, char **argv) +{ + BIO *bio = NULL; + int failed = 0; + size_t i; + + SSL_library_init(); + SSL_load_error_strings(); + + bio = BIO_new_mem_buf(peer_cert_pem, -1); + if (bio == NULL) + errx(1, "failed to create bio"); + + peer_cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (peer_cert == NULL) + errx(1, "failed to read peer cert"); + + for (i = 0; i < N_SSL_ASN1_TESTS; i++) + failed += do_ssl_asn1_test(i, &ssl_asn1_tests[i]); + + X509_free(peer_cert); + BIO_free(bio); + + return (failed); +} diff --git a/tests/asn1time.c b/tests/asn1time.c new file mode 100644 index 0000000..bb58f61 --- /dev/null +++ b/tests/asn1time.c @@ -0,0 +1,611 @@ +/* $OpenBSD: asn1time.c,v 1.20 2023/10/02 11:14:15 tb Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +struct asn1_time_test { + const char *str; + const char *data; + const unsigned char der[32]; + time_t time; +}; + +static const struct asn1_time_test asn1_invtime_tests[] = { + { + .str = "", + }, + { + .str = "2015", + }, + { + .str = "201509", + }, + { + .str = "20150923", + }, + { + .str = "20150923032700", + }, + { + .str = "20150923032700.Z", + }, + { + .str = "20150923032700.123", + }, + { + .str = "20150923032700+1.09", + }, + { + .str = "20150923032700+1100Z", + }, + { + .str = "20150923032700-11001", + }, + { + /* UTC time cannot have fractional seconds. */ + .str = "150923032700.123Z", + }, + { + .str = "aaaaaaaaaaaaaaZ", + }, + /* utc time with omitted seconds, should fail */ + { + .str = "1609082343Z", + }, +}; + +static const struct asn1_time_test asn1_invgentime_tests[] = { + /* Generalized time with omitted seconds, should fail */ + { + .str = "201612081934Z", + }, + /* Valid UTC time, should fail as a generalized time */ + { + .str = "160908234300Z", + }, +}; + +static const struct asn1_time_test asn1_gentime_tests[] = { + { + .str = "20161208193400Z", + .data = "20161208193400Z", + .time = 1481225640, + .der = { + 0x18, 0x0f, 0x32, 0x30, 0x31, 0x36, 0x31, 0x32, + 0x30, 0x38, 0x31, 0x39, 0x33, 0x34, 0x30, 0x30, + 0x5a, + }, + }, + { + .str = "19700101000000Z", + .data = "19700101000000Z", + .time = 0, + .der = { + 0x18, 0x0f, 0x31, 0x39, 0x37, 0x30, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5a, + }, + }, + { + .str = "20150923032700Z", + .data = "20150923032700Z", + .time = 1442978820, + .der = { + 0x18, 0x0f, 0x32, 0x30, 0x31, 0x35, 0x30, 0x39, + 0x32, 0x33, 0x30, 0x33, 0x32, 0x37, 0x30, 0x30, + 0x5a, + }, + }, +}; + +static const struct asn1_time_test asn1_utctime_tests[] = { + { + .str = "700101000000Z", + .data = "700101000000Z", + .time = 0, + .der = { + 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + }, + }, + { + .str = "150923032700Z", + .data = "150923032700Z", + .time = 1442978820, + .der = { + 0x17, 0x0d, 0x31, 0x35, 0x30, 0x39, 0x32, 0x33, + 0x30, 0x33, 0x32, 0x37, 0x30, 0x30, 0x5a, + }, + }, + { + .str = "140524144512Z", + .data = "140524144512Z", + .time = 1400942712, + .der = { + 0x17, 0x0d, 0x31, 0x34, 0x30, 0x35, 0x32, 0x34, + 0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a, + }, + }, + { + .str = "240401144512Z", + .data = "240401144512Z", + .time = 1711982712, + .der = { + 0x17, 0x0d, 0x32, 0x34, 0x30, 0x34, 0x30, 0x31, + 0x31, 0x34, 0x34, 0x35, 0x31, 0x32, 0x5a + }, + }, +}; + +#define N_INVTIME_TESTS \ + (sizeof(asn1_invtime_tests) / sizeof(*asn1_invtime_tests)) +#define N_INVGENTIME_TESTS \ + (sizeof(asn1_invgentime_tests) / sizeof(*asn1_invgentime_tests)) +#define N_GENTIME_TESTS \ + (sizeof(asn1_gentime_tests) / sizeof(*asn1_gentime_tests)) +#define N_UTCTIME_TESTS \ + (sizeof(asn1_utctime_tests) / sizeof(*asn1_utctime_tests)) + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +asn1_compare_bytes(int test_no, const unsigned char *d1, + const unsigned char *d2, int len1, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: test %d - byte lengths differ " + "(%d != %d)\n", test_no, len1, len2); + return (1); + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: test %d - bytes differ\n", test_no); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return (1); + } + return (0); +} + +static int +asn1_compare_str(int test_no, const struct asn1_string_st *asn1str, + const char *str) +{ + int length = strlen(str); + + if (asn1str->length != length) { + fprintf(stderr, "FAIL: test %d - string lengths differ " + "(%d != %d)\n", test_no, asn1str->length, length); + return (1); + } + if (strncmp(asn1str->data, str, length) != 0) { + fprintf(stderr, "FAIL: test %d - strings differ " + "('%s' != '%s')\n", test_no, asn1str->data, str); + return (1); + } + + return (0); +} + +static int +asn1_invtime_test(int test_no, const struct asn1_time_test *att, int gen) +{ + ASN1_GENERALIZEDTIME *gt = NULL; + ASN1_UTCTIME *ut = NULL; + ASN1_TIME *t = NULL; + int failure = 1; + + if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL) + goto done; + if ((ut = ASN1_UTCTIME_new()) == NULL) + goto done; + if ((t = ASN1_TIME_new()) == NULL) + goto done; + + if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) { + fprintf(stderr, "FAIL: test %d - successfully set " + "GENERALIZEDTIME string '%s'\n", test_no, att->str); + goto done; + } + + if (gen) { + failure = 0; + goto done; + } + + if (ASN1_UTCTIME_set_string(ut, att->str) != 0) { + fprintf(stderr, "FAIL: test %d - successfully set UTCTIME " + "string '%s'\n", test_no, att->str); + goto done; + } + if (ASN1_TIME_set_string(t, att->str) != 0) { + fprintf(stderr, "FAIL: test %d - successfully set TIME " + "string '%s'\n", test_no, att->str); + goto done; + } + if (ASN1_TIME_set_string_X509(t, att->str) != 0) { + fprintf(stderr, "FAIL: test %d - successfully set x509 TIME " + "string '%s'\n", test_no, att->str); + goto done; + } + + failure = 0; + + done: + ASN1_GENERALIZEDTIME_free(gt); + ASN1_UTCTIME_free(ut); + ASN1_TIME_free(t); + + return (failure); +} + +static int +asn1_gentime_test(int test_no, const struct asn1_time_test *att) +{ + const unsigned char *der; + unsigned char *p = NULL; + ASN1_GENERALIZEDTIME *gt = NULL; + int failure = 1; + int len; + struct tm tm; + + if (ASN1_GENERALIZEDTIME_set_string(NULL, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + + if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL) + goto done; + + if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + if (asn1_compare_str(test_no, gt, att->str) != 0) + goto done; + + if (ASN1_TIME_to_tm(gt, &tm) == 0) { + fprintf(stderr, "FAIL: test %d - ASN1_time_to_tm failed '%s'\n", + test_no, att->str); + goto done; + } + + if (timegm(&tm) != att->time) { + /* things with crappy time_t should die in fire */ + int64_t a = timegm(&tm); + int64_t b = att->time; + fprintf(stderr, "FAIL: test %d - times don't match, expected %lld got %lld\n", + test_no, (long long)b, (long long)a); + goto done; + } + + if ((len = i2d_ASN1_GENERALIZEDTIME(gt, &p)) <= 0) { + fprintf(stderr, "FAIL: test %d - i2d_ASN1_GENERALIZEDTIME " + "failed\n", test_no); + goto done; + } + der = att->der; + if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0) + goto done; + + len = strlen(att->der); + if (d2i_ASN1_GENERALIZEDTIME(>, &der, len) == NULL) { + fprintf(stderr, "FAIL: test %d - d2i_ASN1_GENERALIZEDTIME " + "failed\n", test_no); + goto done; + } + if (asn1_compare_str(test_no, gt, att->str) != 0) + goto done; + + ASN1_GENERALIZEDTIME_free(gt); + + if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) { + fprintf(stderr, "FAIL: test %d - failed to set time %lld\n", + test_no, (long long)att->time); + goto done; + } + if (asn1_compare_str(test_no, gt, att->data) != 0) + goto done; + + failure = 0; + + done: + ASN1_GENERALIZEDTIME_free(gt); + free(p); + + return (failure); +} + +static int +asn1_utctime_test(int test_no, const struct asn1_time_test *att) +{ + const unsigned char *der; + unsigned char *p = NULL; + ASN1_UTCTIME *ut = NULL; + int failure = 1; + int len; + + if (ASN1_UTCTIME_set_string(NULL, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + + if ((ut = ASN1_UTCTIME_new()) == NULL) + goto done; + + if (ASN1_UTCTIME_set_string(ut, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + if (asn1_compare_str(test_no, ut, att->str) != 0) + goto done; + + if ((len = i2d_ASN1_UTCTIME(ut, &p)) <= 0) { + fprintf(stderr, "FAIL: test %d - i2d_ASN1_UTCTIME failed\n", + test_no); + goto done; + } + der = att->der; + if (asn1_compare_bytes(test_no, p, der, len, strlen(der)) != 0) + goto done; + + len = strlen(att->der); + if (d2i_ASN1_UTCTIME(&ut, &der, len) == NULL) { + fprintf(stderr, "FAIL: test %d - d2i_ASN1_UTCTIME failed\n", + test_no); + goto done; + } + if (asn1_compare_str(test_no, ut, att->str) != 0) + goto done; + + ASN1_UTCTIME_free(ut); + + if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) { + fprintf(stderr, "FAIL: test %d - failed to set time %lld\n", + test_no, (long long)att->time); + goto done; + } + if (asn1_compare_str(test_no, ut, att->data) != 0) + goto done; + + failure = 0; + + done: + ASN1_UTCTIME_free(ut); + free(p); + + return (failure); +} + +static int +asn1_time_test(int test_no, const struct asn1_time_test *att, int type) +{ + ASN1_TIME *t = NULL, *tx509 = NULL; + int failure = 1; + + if (ASN1_TIME_set_string(NULL, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + + if ((t = ASN1_TIME_new()) == NULL) + goto done; + + if ((tx509 = ASN1_TIME_new()) == NULL) + goto done; + + if (ASN1_TIME_set_string(t, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + + if (t->type != type) { + fprintf(stderr, "FAIL: test %d - got type %d, want %d\n", + test_no, t->type, type); + goto done; + } + + if (ASN1_TIME_normalize(t) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set normalize '%s'\n", + test_no, att->str); + goto done; + } + + if (ASN1_TIME_set_string_X509(tx509, t->data) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string X509 '%s'\n", + test_no, t->data); + goto done; + } + + if (t->type != tx509->type) { + fprintf(stderr, "FAIL: test %d - type %d, different from %d\n", + test_no, t->type, tx509->type); + goto done; + } + + if (ASN1_TIME_compare(t, tx509) != 0) { + fprintf(stderr, "FAIL: ASN1_TIME values differ!\n"); + goto done; + } + + + failure = 0; + + done: + + ASN1_TIME_free(t); + ASN1_TIME_free(tx509); + + return (failure); +} + +static int +time_t_cmp(time_t t1, time_t t2) +{ + if (t1 < t2) + return -1; + if (t2 < t1) + return 1; + return 0; +} + +static int +asn1_time_compare_families(const struct asn1_time_test *fam1, size_t fam1_size, + const struct asn1_time_test *fam2, size_t fam2_size) +{ + const struct asn1_time_test *att1, *att2; + ASN1_TIME *t1 = NULL, *t2 = NULL; + size_t i, j; + int asn1_cmp, time_cmp; + int comparison_failure = 0; + int failure = 1; + + if ((t1 = ASN1_TIME_new()) == NULL) + goto done; + if ((t2 = ASN1_TIME_new()) == NULL) + goto done; + + for (i = 0; i < fam1_size; i++) { + att1 = &fam1[i]; + + if (!ASN1_TIME_set_string(t1, att1->str)) + goto done; + for (j = 0; j < fam2_size; j++) { + att2 = &fam2[j]; + + if (!ASN1_TIME_set_string(t2, att2->str)) + goto done; + + time_cmp = time_t_cmp(att1->time, att2->time); + asn1_cmp = ASN1_TIME_compare(t1, t2); + + if (time_cmp != asn1_cmp) { + fprintf(stderr, "%s vs. %s: want %d, got %d\n", + att1->str, att2->str, time_cmp, asn1_cmp); + comparison_failure |= 1; + } + + time_cmp = ASN1_TIME_cmp_time_t(t1, att2->time); + if (time_cmp != asn1_cmp) { + fprintf(stderr, "%s vs. %lld: want %d, got %d\n", + att1->str, (long long)att2->time, + asn1_cmp, time_cmp); + comparison_failure |= 1; + } + + /* + * XXX - add ASN1_UTCTIME_cmp_time_t later. Don't want + * to mess with LIBRESSL_INTERNAL right before lock. + */ + } + } + + failure = comparison_failure; + + done: + ASN1_TIME_free(t1); + ASN1_TIME_free(t2); + + return failure; +} + +static int +asn1_time_compare_test(void) +{ + const struct asn1_time_test *gen = asn1_gentime_tests; + size_t gen_size = N_GENTIME_TESTS; + const struct asn1_time_test *utc = asn1_utctime_tests; + size_t utc_size = N_UTCTIME_TESTS; + int failed = 0; + + failed |= asn1_time_compare_families(gen, gen_size, gen, gen_size); + failed |= asn1_time_compare_families(gen, gen_size, utc, utc_size); + failed |= asn1_time_compare_families(utc, utc_size, gen, gen_size); + failed |= asn1_time_compare_families(utc, utc_size, utc, utc_size); + + return failed; +} + +int +main(int argc, char **argv) +{ + const struct asn1_time_test *att; + int failed = 0; + size_t i; + + fprintf(stderr, "Invalid time tests...\n"); + for (i = 0; i < N_INVTIME_TESTS; i++) { + att = &asn1_invtime_tests[i]; + failed |= asn1_invtime_test(i, att, 0); + } + + fprintf(stderr, "Invalid generalized time tests...\n"); + for (i = 0; i < N_INVGENTIME_TESTS; i++) { + att = &asn1_invgentime_tests[i]; + failed |= asn1_invtime_test(i, att, 1); + } + + fprintf(stderr, "GENERALIZEDTIME tests...\n"); + for (i = 0; i < N_GENTIME_TESTS; i++) { + att = &asn1_gentime_tests[i]; + failed |= asn1_gentime_test(i, att); + } + + fprintf(stderr, "UTCTIME tests...\n"); + for (i = 0; i < N_UTCTIME_TESTS; i++) { + att = &asn1_utctime_tests[i]; + failed |= asn1_utctime_test(i, att); + } + + fprintf(stderr, "TIME tests...\n"); + for (i = 0; i < N_UTCTIME_TESTS; i++) { + att = &asn1_utctime_tests[i]; + failed |= asn1_time_test(i, att, V_ASN1_UTCTIME); + } + for (i = 0; i < N_GENTIME_TESTS; i++) { + att = &asn1_gentime_tests[i]; + failed |= asn1_time_test(i, att, V_ASN1_GENERALIZEDTIME); + } + + fprintf(stderr, "ASN1_TIME_compare tests...\n"); + failed |= asn1_time_compare_test(); + + /* Check for a leak in ASN1_TIME_normalize(). */ + failed |= ASN1_TIME_normalize(NULL) != 0; + + return (failed); +} diff --git a/tests/asn1x509.c b/tests/asn1x509.c new file mode 100644 index 0000000..972b829 --- /dev/null +++ b/tests/asn1x509.c @@ -0,0 +1,842 @@ +/* $OpenBSD: asn1x509.c,v 1.5 2023/08/11 22:50:44 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char *dsa_test_key = + "-----BEGIN DSA PRIVATE KEY-----\n" + "MIH5AgEAAkEAt+CNNryEe8t2SkjuP0azjOKjSMXsw3GzjLS5c+vFLQKs0zIuPp8F\n" + "I/z5t8vcNt/D8EyzQZWxgCfoasHqDOJvRwIVAKrJMyIMt9iJtaS31cyIJmIDVlZX\n" + "AkEAs1/Uy+x0+1C1n7V3eJxuBdO/LUalbrZM5PfcwDshf9kcQNLsRu5zTZkU0OX/\n" + "8xANz+ue2o6LON2sTAtuEfSM1QJBAIDRt0rQGGrFCRJ4O39Iqlf27yIO6Gq1ppbE\n" + "Wvsvz4YSIZsG02vlBlzVIhULftNnkpN59MFtIjx8RsbEQ4YTnSICFDXPf/UIRvdH\n" + "20NV++tnUZYUAXM+\n" + "-----END DSA PRIVATE KEY-----\n"; + +unsigned char dsa_test_asn1_pubkey[] = { + 0x30, 0x81, 0xf2, 0x30, 0x81, 0xa9, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01, 0x30, + 0x81, 0x9d, 0x02, 0x41, 0x00, 0xb7, 0xe0, 0x8d, + 0x36, 0xbc, 0x84, 0x7b, 0xcb, 0x76, 0x4a, 0x48, + 0xee, 0x3f, 0x46, 0xb3, 0x8c, 0xe2, 0xa3, 0x48, + 0xc5, 0xec, 0xc3, 0x71, 0xb3, 0x8c, 0xb4, 0xb9, + 0x73, 0xeb, 0xc5, 0x2d, 0x02, 0xac, 0xd3, 0x32, + 0x2e, 0x3e, 0x9f, 0x05, 0x23, 0xfc, 0xf9, 0xb7, + 0xcb, 0xdc, 0x36, 0xdf, 0xc3, 0xf0, 0x4c, 0xb3, + 0x41, 0x95, 0xb1, 0x80, 0x27, 0xe8, 0x6a, 0xc1, + 0xea, 0x0c, 0xe2, 0x6f, 0x47, 0x02, 0x15, 0x00, + 0xaa, 0xc9, 0x33, 0x22, 0x0c, 0xb7, 0xd8, 0x89, + 0xb5, 0xa4, 0xb7, 0xd5, 0xcc, 0x88, 0x26, 0x62, + 0x03, 0x56, 0x56, 0x57, 0x02, 0x41, 0x00, 0xb3, + 0x5f, 0xd4, 0xcb, 0xec, 0x74, 0xfb, 0x50, 0xb5, + 0x9f, 0xb5, 0x77, 0x78, 0x9c, 0x6e, 0x05, 0xd3, + 0xbf, 0x2d, 0x46, 0xa5, 0x6e, 0xb6, 0x4c, 0xe4, + 0xf7, 0xdc, 0xc0, 0x3b, 0x21, 0x7f, 0xd9, 0x1c, + 0x40, 0xd2, 0xec, 0x46, 0xee, 0x73, 0x4d, 0x99, + 0x14, 0xd0, 0xe5, 0xff, 0xf3, 0x10, 0x0d, 0xcf, + 0xeb, 0x9e, 0xda, 0x8e, 0x8b, 0x38, 0xdd, 0xac, + 0x4c, 0x0b, 0x6e, 0x11, 0xf4, 0x8c, 0xd5, 0x03, + 0x44, 0x00, 0x02, 0x41, 0x00, 0x80, 0xd1, 0xb7, + 0x4a, 0xd0, 0x18, 0x6a, 0xc5, 0x09, 0x12, 0x78, + 0x3b, 0x7f, 0x48, 0xaa, 0x57, 0xf6, 0xef, 0x22, + 0x0e, 0xe8, 0x6a, 0xb5, 0xa6, 0x96, 0xc4, 0x5a, + 0xfb, 0x2f, 0xcf, 0x86, 0x12, 0x21, 0x9b, 0x06, + 0xd3, 0x6b, 0xe5, 0x06, 0x5c, 0xd5, 0x22, 0x15, + 0x0b, 0x7e, 0xd3, 0x67, 0x92, 0x93, 0x79, 0xf4, + 0xc1, 0x6d, 0x22, 0x3c, 0x7c, 0x46, 0xc6, 0xc4, + 0x43, 0x86, 0x13, 0x9d, 0x22, +}; + +const unsigned char dsa_test_asn1_pubkey_noparams[] = { + 0x30, 0x51, 0x30, 0x09, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x38, 0x04, 0x01, 0x03, 0x44, 0x00, + 0x02, 0x41, 0x00, 0x80, 0xd1, 0xb7, 0x4a, 0xd0, + 0x18, 0x6a, 0xc5, 0x09, 0x12, 0x78, 0x3b, 0x7f, + 0x48, 0xaa, 0x57, 0xf6, 0xef, 0x22, 0x0e, 0xe8, + 0x6a, 0xb5, 0xa6, 0x96, 0xc4, 0x5a, 0xfb, 0x2f, + 0xcf, 0x86, 0x12, 0x21, 0x9b, 0x06, 0xd3, 0x6b, + 0xe5, 0x06, 0x5c, 0xd5, 0x22, 0x15, 0x0b, 0x7e, + 0xd3, 0x67, 0x92, 0x93, 0x79, 0xf4, 0xc1, 0x6d, + 0x22, 0x3c, 0x7c, 0x46, 0xc6, 0xc4, 0x43, 0x86, + 0x13, 0x9d, 0x22, +}; + +const char *ec_test_key = + "-----BEGIN EC PRIVATE KEY-----\n" + "MHcCAQEEIEDkF84aPdBNu4vbPE+QV3EP9ULp4Enr1N0lz4vzuc2boAoGCCqGSM49\n" + "AwEHoUQDQgAEUQGHBjYwbfHvI3QqdDy8ftNU5UvQqh6TH6upIrtz4CVccxnWO2+s\n" + "qSMOu1z5KnGIOVf2kLQ2S2iMahyFMezr8g==\n" + "-----END EC PRIVATE KEY-----\n"; + +unsigned char ec_test_asn1_pubkey[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x51, 0x01, 0x87, 0x06, 0x36, + 0x30, 0x6d, 0xf1, 0xef, 0x23, 0x74, 0x2a, 0x74, + 0x3c, 0xbc, 0x7e, 0xd3, 0x54, 0xe5, 0x4b, 0xd0, + 0xaa, 0x1e, 0x93, 0x1f, 0xab, 0xa9, 0x22, 0xbb, + 0x73, 0xe0, 0x25, 0x5c, 0x73, 0x19, 0xd6, 0x3b, + 0x6f, 0xac, 0xa9, 0x23, 0x0e, 0xbb, 0x5c, 0xf9, + 0x2a, 0x71, 0x88, 0x39, 0x57, 0xf6, 0x90, 0xb4, + 0x36, 0x4b, 0x68, 0x8c, 0x6a, 0x1c, 0x85, 0x31, + 0xec, 0xeb, 0xf2, +}; + +const char *rsa_test_key = + "-----BEGIN PRIVATE KEY-----\n" + "MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEA4Fs6ljFFQw/ElDf5\n" + "LTghVw972PVpQuKPQvwb1cWbV3+7W5sXOcoM/RvwzO7WeppkeltVCBoKaQd+9e2Z\n" + "BHtYhwIDAQABAkEAhWv7dWIrrGvuHa8D0i51NU8R+b5IMOyHAfDnpMN1VByWcBdb\n" + "G7ZJsEYlO1Tbx1zFQOVyrDUY2hn0YttPjWys0QIhAP9+FRhHCYye/EY14zSa+lxb\n" + "ljOPjWgddMdJBcPOVNUNAiEA4M1QUtIcTnTnfvcxvEBIhbmSR8fRvZYAeT5EoTKM\n" + "puMCIQD9898X8JRHWEg9qZabVWiBoO+ddJUD5jOLWsQGKvMbiQIgBOQyxTqRJxvg\n" + "FaEnUeNMMKyzBCDS7X8gD4NNVvyUluUCIQC/lnO9xYi6S4BFMwHFEUY0jLr5vgsR\n" + "+esRU9dLkMqt+w==\n" + "-----END PRIVATE KEY-----\n"; + +unsigned char rsa_test_asn1_pubkey[] = { + 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, + 0x00, 0xe0, 0x5b, 0x3a, 0x96, 0x31, 0x45, 0x43, + 0x0f, 0xc4, 0x94, 0x37, 0xf9, 0x2d, 0x38, 0x21, + 0x57, 0x0f, 0x7b, 0xd8, 0xf5, 0x69, 0x42, 0xe2, + 0x8f, 0x42, 0xfc, 0x1b, 0xd5, 0xc5, 0x9b, 0x57, + 0x7f, 0xbb, 0x5b, 0x9b, 0x17, 0x39, 0xca, 0x0c, + 0xfd, 0x1b, 0xf0, 0xcc, 0xee, 0xd6, 0x7a, 0x9a, + 0x64, 0x7a, 0x5b, 0x55, 0x08, 0x1a, 0x0a, 0x69, + 0x07, 0x7e, 0xf5, 0xed, 0x99, 0x04, 0x7b, 0x58, + 0x87, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +const char dh_test_key[] = + "-----BEGIN PRIVATE KEY-----\n" + "MIICJgIBADCCARcGCSqGSIb3DQEDATCCAQgCggEBAIXmHiRswMxVCnVzq4GuaErl\n" + "2fBPDquOzFaxd/YSN7tVxnz3wcMNfBsHZWqtAXxTBWeyt8ydHcrIWx4EB3XTSwSi\n" + "Jqh3CEcFhDfqKdo/u7vffxG+43lEsvZZIzZHYMcYsHIpcERRoAu0xnqjHUQTkvoi\n" + "w7ukbuWr28bJrncPaxFGC8zZvLhSnUst5yzdyAsIddQvHgYBdCn2UEbz6qBx8gvJ\n" + "lb3Jv1BiVJJ0odL94vpNXRGNZ57PPm5Xlj/n8l8LHpzzxbtjc52MVYbMPpVuWzmv\n" + "2nWV0eL14708S/XG6e2AWGKb8AX8hCitdtVQ28SbEsf8Yd1dyWNo++oedFvU49sC\n" + "AQIEggEEAoIBAGywTP/vBwEeuWIgTPnBf1/jWQgfFA5no3HdRIQsHVgo2EEZHErS\n" + "X82hALavaUTEu+pHu+/yv3BLPr/8Lau6O7LOiqeXMjYX4HtSNmLZIEjugd1aCyCp\n" + "n+jZjIHQCG0fvnwWFqkKTADe4n4DUz5qxuHYmlFY4NsdMj5yARAh9mn7hqwYX+Mf\n" + "WhHLhHIHngXKNs7vKdHH/guo638uL6dv6OuTS0wbBsjLMFvQvccVlVUWlUFkH6I8\n" + "GFt8kAFLdrzz8+oMq3hHsoWIrDSp0GYq6keSu3pBj4q2mTP7ugUU8ag/dZnga5sB\n" + "Mdt2hicktiw/mQZP578plm6z2Lg0gl5yLxk=\n" + "-----END PRIVATE KEY-----\n"; + +const unsigned char dh_test_asn1_pubkey[] = { + 0x30, 0x82, 0x02, 0x24, 0x30, 0x82, 0x01, 0x17, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x03, 0x01, 0x30, 0x82, 0x01, 0x08, 0x02, + 0x82, 0x01, 0x01, 0x00, 0x85, 0xe6, 0x1e, 0x24, + 0x6c, 0xc0, 0xcc, 0x55, 0x0a, 0x75, 0x73, 0xab, + 0x81, 0xae, 0x68, 0x4a, 0xe5, 0xd9, 0xf0, 0x4f, + 0x0e, 0xab, 0x8e, 0xcc, 0x56, 0xb1, 0x77, 0xf6, + 0x12, 0x37, 0xbb, 0x55, 0xc6, 0x7c, 0xf7, 0xc1, + 0xc3, 0x0d, 0x7c, 0x1b, 0x07, 0x65, 0x6a, 0xad, + 0x01, 0x7c, 0x53, 0x05, 0x67, 0xb2, 0xb7, 0xcc, + 0x9d, 0x1d, 0xca, 0xc8, 0x5b, 0x1e, 0x04, 0x07, + 0x75, 0xd3, 0x4b, 0x04, 0xa2, 0x26, 0xa8, 0x77, + 0x08, 0x47, 0x05, 0x84, 0x37, 0xea, 0x29, 0xda, + 0x3f, 0xbb, 0xbb, 0xdf, 0x7f, 0x11, 0xbe, 0xe3, + 0x79, 0x44, 0xb2, 0xf6, 0x59, 0x23, 0x36, 0x47, + 0x60, 0xc7, 0x18, 0xb0, 0x72, 0x29, 0x70, 0x44, + 0x51, 0xa0, 0x0b, 0xb4, 0xc6, 0x7a, 0xa3, 0x1d, + 0x44, 0x13, 0x92, 0xfa, 0x22, 0xc3, 0xbb, 0xa4, + 0x6e, 0xe5, 0xab, 0xdb, 0xc6, 0xc9, 0xae, 0x77, + 0x0f, 0x6b, 0x11, 0x46, 0x0b, 0xcc, 0xd9, 0xbc, + 0xb8, 0x52, 0x9d, 0x4b, 0x2d, 0xe7, 0x2c, 0xdd, + 0xc8, 0x0b, 0x08, 0x75, 0xd4, 0x2f, 0x1e, 0x06, + 0x01, 0x74, 0x29, 0xf6, 0x50, 0x46, 0xf3, 0xea, + 0xa0, 0x71, 0xf2, 0x0b, 0xc9, 0x95, 0xbd, 0xc9, + 0xbf, 0x50, 0x62, 0x54, 0x92, 0x74, 0xa1, 0xd2, + 0xfd, 0xe2, 0xfa, 0x4d, 0x5d, 0x11, 0x8d, 0x67, + 0x9e, 0xcf, 0x3e, 0x6e, 0x57, 0x96, 0x3f, 0xe7, + 0xf2, 0x5f, 0x0b, 0x1e, 0x9c, 0xf3, 0xc5, 0xbb, + 0x63, 0x73, 0x9d, 0x8c, 0x55, 0x86, 0xcc, 0x3e, + 0x95, 0x6e, 0x5b, 0x39, 0xaf, 0xda, 0x75, 0x95, + 0xd1, 0xe2, 0xf5, 0xe3, 0xbd, 0x3c, 0x4b, 0xf5, + 0xc6, 0xe9, 0xed, 0x80, 0x58, 0x62, 0x9b, 0xf0, + 0x05, 0xfc, 0x84, 0x28, 0xad, 0x76, 0xd5, 0x50, + 0xdb, 0xc4, 0x9b, 0x12, 0xc7, 0xfc, 0x61, 0xdd, + 0x5d, 0xc9, 0x63, 0x68, 0xfb, 0xea, 0x1e, 0x74, + 0x5b, 0xd4, 0xe3, 0xdb, 0x02, 0x01, 0x02, 0x03, + 0x82, 0x01, 0x05, 0x00, 0x02, 0x82, 0x01, 0x00, + 0x44, 0x30, 0x25, 0xe2, 0xeb, 0x8f, 0xd0, 0x81, + 0x96, 0x3e, 0x7d, 0x1d, 0x9b, 0x82, 0x8a, 0x2d, + 0x0f, 0xb3, 0x2d, 0x9c, 0x2b, 0xb2, 0x88, 0xda, + 0xc6, 0xef, 0x6c, 0x9d, 0x1c, 0x80, 0xf1, 0xee, + 0x9d, 0x6b, 0x31, 0xb7, 0xb1, 0x9f, 0x30, 0x0d, + 0xb7, 0x92, 0xcf, 0x56, 0xeb, 0xfc, 0x91, 0x16, + 0x35, 0x96, 0x0c, 0x7b, 0x95, 0xbc, 0x65, 0x66, + 0x10, 0x81, 0x4b, 0x46, 0x04, 0xee, 0x95, 0xca, + 0xc9, 0x0c, 0xea, 0xc1, 0xd7, 0x3b, 0x83, 0xfb, + 0xce, 0x76, 0x17, 0xb4, 0x15, 0xad, 0x03, 0xd0, + 0x00, 0xef, 0xb2, 0xee, 0x12, 0x3f, 0x75, 0xd1, + 0xb8, 0x6c, 0xfd, 0x87, 0xb5, 0x07, 0xfa, 0x1e, + 0x60, 0x9b, 0x49, 0x6f, 0x89, 0xc2, 0x75, 0x4d, + 0x7d, 0x21, 0xdb, 0xb6, 0x85, 0x78, 0xa5, 0x77, + 0xbe, 0xeb, 0x4d, 0x9e, 0x1c, 0x05, 0xbc, 0x51, + 0x97, 0x0f, 0xe9, 0x68, 0x78, 0x5a, 0xc8, 0x4e, + 0xef, 0x72, 0x8f, 0x53, 0x41, 0x0d, 0x57, 0xf2, + 0xc5, 0x29, 0x33, 0x67, 0xdd, 0x35, 0x43, 0xfc, + 0x13, 0x49, 0x92, 0x1d, 0x14, 0x92, 0x40, 0x14, + 0x38, 0x32, 0xdb, 0x14, 0x95, 0x44, 0x2a, 0x03, + 0xb7, 0x87, 0xa3, 0x5a, 0x5a, 0xe2, 0x3b, 0xc5, + 0x44, 0xa4, 0x06, 0xf6, 0x14, 0xe6, 0x08, 0x9c, + 0x51, 0x09, 0x2a, 0xc4, 0x2e, 0x72, 0xb3, 0x20, + 0x46, 0x77, 0xe2, 0xda, 0x07, 0xd8, 0x10, 0x89, + 0xcf, 0x2b, 0xef, 0x67, 0xa2, 0x48, 0xfd, 0xa3, + 0x71, 0x59, 0xf0, 0x89, 0x3a, 0x35, 0x31, 0x87, + 0xad, 0x45, 0x9e, 0x35, 0xbd, 0x64, 0xec, 0xd1, + 0xd7, 0xea, 0x92, 0xed, 0x72, 0x9c, 0x81, 0x8e, + 0x11, 0x4e, 0xa5, 0xe7, 0x12, 0xe3, 0x7c, 0x53, + 0x2b, 0x31, 0xd4, 0x3d, 0xd5, 0xd9, 0xbd, 0x44, + 0x27, 0xa3, 0x4a, 0x3f, 0x20, 0x87, 0xce, 0x73, + 0x0e, 0xa8, 0x90, 0xcd, 0xfe, 0x32, 0x69, 0x9a, +}; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +compare_data(const char *label, const unsigned char *d1, size_t d1_len, + const unsigned char *d2, size_t d2_len) +{ + if (d1_len != d2_len) { + fprintf(stderr, "FAIL: got %s with length %zu, want %zu\n", + label, d1_len, d2_len); + return -1; + } + if (memcmp(d1, d2, d1_len) != 0) { + fprintf(stderr, "FAIL: %s differs\n", label); + fprintf(stderr, "got:\n"); + hexdump(d1, d1_len); + fprintf(stderr, "want:\n"); + hexdump(d2, d2_len); + return -1; + } + return 0; +} + +static int +dh_pubkey_test(void) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY *pkey_a = NULL, *pkey_b = NULL; + unsigned char *out = NULL, *data = NULL; + DH *dh_a = NULL, *dh_b = NULL; + const unsigned char *p; + BIO *bio_mem = NULL; + int failure = 1; + int len; + + ERR_clear_error(); + + if ((bio_mem = BIO_new_mem_buf(dh_test_key, -1)) == NULL) + errx(1, "failed to create BIO"); + + if ((pkey = PEM_read_bio_PrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to decode DH key from PEM"); + } + + /* + * Test PEM_write_bio_PrivateKey(). + */ + BIO_free_all(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + if (!PEM_write_bio_PrivateKey(bio_mem, pkey, NULL, NULL, 0, 0, NULL)) { + fprintf(stderr, "FAIL: PEM_write_bio_PrivateKey failed\n"); + goto done; + } + + len = BIO_get_mem_data(bio_mem, &data); + if (compare_data("DH PrivateKey", data, len, + dh_test_key, sizeof(dh_test_key) - 1) == -1) + goto done; + + /* + * Test i2d_PUBKEY/d2i_PUBKEY. + */ + + if ((dh_a = EVP_PKEY_get1_DH(pkey)) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to get1 DH key from PEM"); + } + + if ((pkey_a = EVP_PKEY_new()) == NULL) + errx(1, "failed to create EVP_PKEY"); + if (!EVP_PKEY_set1_DH(pkey_a, dh_a)) + errx(1, "failed to set DH on EVP_PKEY"); + + if ((len = i2d_PUBKEY(pkey_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_PUBKEY failed\n"); + goto done; + } + if (compare_data("DH PUBKEY", out, len, dh_test_asn1_pubkey, + sizeof(dh_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((pkey_b = d2i_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(DH_get0_pub_key(EVP_PKEY_get0_DH(pkey_a)), + DH_get0_pub_key(EVP_PKEY_get0_DH(pkey_b))) != 0) { + fprintf(stderr, "FAIL: DH public keys mismatch\n"); + goto done; + } + + failure = 0; + + done: + BIO_free_all(bio_mem); + EVP_PKEY_free(pkey); + DH_free(dh_a); + DH_free(dh_b); + EVP_PKEY_free(pkey_a); + EVP_PKEY_free(pkey_b); + free(out); + + return failure; +} + +static int +dsa_pubkey_test(void) +{ + EVP_PKEY *pkey_a = NULL, *pkey_b = NULL; + unsigned char *out = NULL, *data = NULL; + DSA *dsa_a = NULL, *dsa_b = NULL; + const unsigned char *p; + BIO *bio_mem = NULL; + int failure = 1; + int len, ret; + + ERR_clear_error(); + + if ((bio_mem = BIO_new_mem_buf((void *)dsa_test_key, -1)) == NULL) + errx(1, "failed to create BIO"); + + if ((dsa_a = PEM_read_bio_DSAPrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to decode DSA key from PEM"); + } + + /* + * Test i2d_PUBKEY/d2i_PUBKEY. + */ + if ((pkey_a = EVP_PKEY_new()) == NULL) + errx(1, "failed to create EVP_PKEY"); + if (!EVP_PKEY_set1_DSA(pkey_a, dsa_a)) + errx(1, "failed to set DSA on EVP_PKEY"); + + if ((len = i2d_PUBKEY(pkey_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_PUBKEY failed\n"); + goto done; + } + if (compare_data("DSA PUBKEY", out, len, dsa_test_asn1_pubkey, + sizeof(dsa_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((pkey_b = d2i_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey_a)), + DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey_b))) != 0) { + fprintf(stderr, "FAIL: DSA public keys mismatch\n"); + goto done; + } + + if (EVP_PKEY_missing_parameters(pkey_b)) { + fprintf(stderr, "FAIL: DSA pkey_b has missing parameters\n"); + goto done; + } + + if (!EVP_PKEY_cmp_parameters(pkey_a, pkey_b)) { + fprintf(stderr, "FAIL: DSA parameters mismatch\n"); + goto done; + } + + /* + * Check save_parameters defaults - EVP_PKEY_save_parameters() returns + * the current save_parameters; mode -1 inspects without setting. + */ + if ((ret = EVP_PKEY_save_parameters(pkey_b, 0)) != 1) { + fprintf(stderr, "FAIL: DSA save_parameters want 1, got %d\n", ret); + goto done; + } + if ((ret = EVP_PKEY_save_parameters(pkey_b, -1)) != 0) { + fprintf(stderr, "FAIL: DSA save_parameters want 0, got %d\n", ret); + goto done; + } + + free(out); + out = NULL; + + if ((len = i2d_PUBKEY(pkey_b, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_PUBKEY (no params) failed\n"); + goto done; + } + + if (compare_data("PUBKEY (no params)", dsa_test_asn1_pubkey_noparams, + sizeof(dsa_test_asn1_pubkey_noparams), out, len) == -1) + goto done; + + EVP_PKEY_free(pkey_b); + + p = out; + if ((pkey_b = d2i_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_PUBKEY (no params) failed\n"); + goto done; + } + + if (!EVP_PKEY_missing_parameters(pkey_b)) { + fprintf(stderr, "FAIL: DSA pkey_b has no missing parameters\n"); + goto done; + } + + if (BN_cmp(DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey_a)), + DSA_get0_pub_key(EVP_PKEY_get0_DSA(pkey_b))) != 0) { + fprintf(stderr, "FAIL: DSA public keys mismatch\n"); + goto done; + } + + if (EVP_PKEY_cmp_parameters(pkey_a, pkey_b)) { + fprintf(stderr, "FAIL: DSA parameters match\n"); + goto done; + } + + if (EVP_PKEY_cmp(pkey_a, pkey_b)) { + fprintf(stderr, "FAIL: DSA keys should not match\n"); + goto done; + } + + if (!EVP_PKEY_copy_parameters(pkey_b, pkey_a)) { + fprintf(stderr, "FAIL: failed to copy DSA parameters\n"); + goto done; + } + + if (!EVP_PKEY_cmp(pkey_a, pkey_b)) { + fprintf(stderr, "FAIL: DSA keys should match\n"); + goto done; + } + + free(out); + out = NULL; + + /* + * Test i2d_DSA_PUBKEY/d2i_DSA_PUBKEY. + */ + + if ((len = i2d_DSA_PUBKEY(dsa_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_DSA_PUBKEY failed\n"); + goto done; + } + if (compare_data("DSA_PUBKEY", out, len, dsa_test_asn1_pubkey, + sizeof(dsa_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((dsa_b = d2i_DSA_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_DSA_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(DSA_get0_pub_key(dsa_a), DSA_get0_pub_key(dsa_b)) != 0) { + fprintf(stderr, "FAIL: DSA public keys mismatch\n"); + goto done; + } + + p = out; + if ((dsa_a = d2i_DSA_PUBKEY(&dsa_a, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_DSA_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(DSA_get0_pub_key(dsa_a), DSA_get0_pub_key(dsa_b)) != 0) { + fprintf(stderr, "FAIL: DSA public keys mismatch\n"); + goto done; + } + + /* + * Test i2d_DSA_PUBKEY_bio/d2i_DSA_PUBKEY_bio. + */ + BIO_free_all(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + if ((len = i2d_DSA_PUBKEY_bio(bio_mem, dsa_a)) < 0) { + fprintf(stderr, "FAIL: i2d_DSA_PUBKEY_bio failed\n"); + goto done; + } + + len = BIO_get_mem_data(bio_mem, &data); + if (compare_data("DSA_PUBKEY", data, len, dsa_test_asn1_pubkey, + sizeof(dsa_test_asn1_pubkey)) == -1) + goto done; + + DSA_free(dsa_b); + if ((dsa_b = d2i_DSA_PUBKEY_bio(bio_mem, NULL)) == NULL) { + fprintf(stderr, "FAIL: d2i_DSA_PUBKEY_bio failed\n"); + goto done; + } + + if (BN_cmp(DSA_get0_pub_key(dsa_a), DSA_get0_pub_key(dsa_b)) != 0) { + fprintf(stderr, "FAIL: DSA public keys mismatch\n"); + goto done; + } + + failure = 0; + + done: + BIO_free_all(bio_mem); + DSA_free(dsa_a); + DSA_free(dsa_b); + EVP_PKEY_free(pkey_a); + EVP_PKEY_free(pkey_b); + free(out); + + return (failure); +} + +static int +ec_pubkey_test(void) +{ + EVP_PKEY *pkey_a = NULL, *pkey_b = NULL; + unsigned char *out = NULL, *data = NULL; + EC_KEY *ec_a = NULL, *ec_b = NULL; + const unsigned char *p; + BIO *bio_mem = NULL; + int failure = 1; + int len; + + ERR_clear_error(); + + if ((bio_mem = BIO_new_mem_buf((void *)ec_test_key, -1)) == NULL) + errx(1, "failed to create BIO"); + + if ((ec_a = PEM_read_bio_ECPrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to decode EC key from PEM"); + } + + /* + * Test i2d_PUBKEY/d2i_PUBKEY. + */ + if ((pkey_a = EVP_PKEY_new()) == NULL) + errx(1, "failed to create EVP_PKEY"); + if (!EVP_PKEY_set1_EC_KEY(pkey_a, ec_a)) + errx(1, "failed to set EC_KEY on EVP_PKEY"); + + if ((len = i2d_PUBKEY(pkey_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_PUBKEY failed\n"); + goto done; + } + if (compare_data("EC_KEY PUBKEY", out, len, ec_test_asn1_pubkey, + sizeof(ec_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((pkey_b = d2i_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_PUBKEY failed\n"); + goto done; + } + + if (EC_GROUP_cmp(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey_a)), + EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey_b)), NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY groups keys mismatch\n"); + goto done; + } + if (EC_POINT_cmp(EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey_a)), + EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(pkey_a)), + EC_KEY_get0_public_key(EVP_PKEY_get0_EC_KEY(pkey_b)), NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY public keys mismatch\n"); + goto done; + } + + free(out); + out = NULL; + + /* + * Test i2d_EC_PUBKEY/d2i_EC_PUBKEY. + */ + + if ((len = i2d_EC_PUBKEY(ec_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_EC_PUBKEY failed\n"); + goto done; + } + if (compare_data("EC_PUBKEY", out, len, ec_test_asn1_pubkey, + sizeof(ec_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((ec_b = d2i_EC_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_EC_PUBKEY failed\n"); + goto done; + } + + if (EC_GROUP_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_group(ec_b), + NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY groups keys mismatch\n"); + goto done; + } + if (EC_POINT_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_public_key(ec_a), + EC_KEY_get0_public_key(ec_b), NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY public keys mismatch\n"); + goto done; + } + + p = out; + if ((ec_a = d2i_EC_PUBKEY(&ec_a, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_EC_PUBKEY failed\n"); + goto done; + } + + if (EC_GROUP_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_group(ec_b), + NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY groups keys mismatch\n"); + goto done; + } + if (EC_POINT_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_public_key(ec_a), + EC_KEY_get0_public_key(ec_b), NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY public keys mismatch\n"); + goto done; + } + + /* + * Test i2d_EC_PUBKEY_bio/d2i_EC_PUBKEY_bio. + */ + BIO_free_all(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + if ((len = i2d_EC_PUBKEY_bio(bio_mem, ec_a)) < 0) { + fprintf(stderr, "FAIL: i2d_EC_PUBKEY_bio failed\n"); + goto done; + } + + len = BIO_get_mem_data(bio_mem, &data); + if (compare_data("EC_PUBKEY", data, len, ec_test_asn1_pubkey, + sizeof(ec_test_asn1_pubkey)) == -1) + goto done; + + EC_KEY_free(ec_b); + if ((ec_b = d2i_EC_PUBKEY_bio(bio_mem, NULL)) == NULL) { + fprintf(stderr, "FAIL: d2i_EC_PUBKEY_bio failed\n"); + goto done; + } + + if (EC_GROUP_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_group(ec_b), + NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY groups keys mismatch\n"); + goto done; + } + if (EC_POINT_cmp(EC_KEY_get0_group(ec_a), EC_KEY_get0_public_key(ec_a), + EC_KEY_get0_public_key(ec_b), NULL) != 0) { + fprintf(stderr, "FAIL: EC_KEY public keys mismatch\n"); + goto done; + } + + failure = 0; + + done: + BIO_free_all(bio_mem); + EC_KEY_free(ec_a); + EC_KEY_free(ec_b); + EVP_PKEY_free(pkey_a); + EVP_PKEY_free(pkey_b); + free(out); + + return (failure); +} + +static int +rsa_pubkey_test(void) +{ + EVP_PKEY *pkey_a = NULL, *pkey_b = NULL; + RSA *rsa_a = NULL, *rsa_b = NULL; + unsigned char *out = NULL, *data = NULL; + const unsigned char *p; + BIO *bio_mem = NULL; + int failure = 1; + int len; + + ERR_clear_error(); + + if ((bio_mem = BIO_new_mem_buf((void *)rsa_test_key, -1)) == NULL) + errx(1, "failed to create BIO"); + + if ((rsa_a = PEM_read_bio_RSAPrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to decode RSA key from PEM"); + } + + /* + * Test i2d_PUBKEY/d2i_PUBKEY. + */ + if ((pkey_a = EVP_PKEY_new()) == NULL) + errx(1, "failed to create EVP_PKEY"); + if (!EVP_PKEY_set1_RSA(pkey_a, rsa_a)) + errx(1, "failed to set RSA on EVP_PKEY"); + + if ((len = i2d_PUBKEY(pkey_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_PUBKEY failed\n"); + goto done; + } + if (compare_data("RSA PUBKEY", out, len, rsa_test_asn1_pubkey, + sizeof(rsa_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((pkey_b = d2i_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(RSA_get0_n(EVP_PKEY_get0_RSA(pkey_a)), + RSA_get0_n(EVP_PKEY_get0_RSA(pkey_b))) != 0 || + BN_cmp(RSA_get0_e(EVP_PKEY_get0_RSA(pkey_a)), + RSA_get0_e(EVP_PKEY_get0_RSA(pkey_b))) != 0) { + fprintf(stderr, "FAIL: RSA public keys mismatch\n"); + goto done; + } + + free(out); + out = NULL; + + /* + * Test i2d_RSA_PUBKEY/d2i_RSA_PUBKEY. + */ + + if ((len = i2d_RSA_PUBKEY(rsa_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_RSA_PUBKEY failed\n"); + goto done; + } + if (compare_data("RSA_PUBKEY", out, len, rsa_test_asn1_pubkey, + sizeof(rsa_test_asn1_pubkey)) == -1) + goto done; + + p = out; + if ((rsa_b = d2i_RSA_PUBKEY(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_RSA_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(RSA_get0_n(rsa_a), RSA_get0_n(rsa_b)) != 0 || + BN_cmp(RSA_get0_e(rsa_a), RSA_get0_e(rsa_b)) != 0) { + fprintf(stderr, "FAIL: RSA public keys mismatch\n"); + goto done; + } + + p = out; + if ((rsa_a = d2i_RSA_PUBKEY(&rsa_a, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_RSA_PUBKEY failed\n"); + goto done; + } + + if (BN_cmp(RSA_get0_n(rsa_a), RSA_get0_n(rsa_b)) != 0 || + BN_cmp(RSA_get0_e(rsa_a), RSA_get0_e(rsa_b)) != 0) { + fprintf(stderr, "FAIL: RSA public keys mismatch\n"); + goto done; + } + + /* + * Test i2d_RSA_PUBKEY_bio/d2i_RSA_PUBKEY_bio. + */ + BIO_free_all(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + if ((len = i2d_RSA_PUBKEY_bio(bio_mem, rsa_a)) < 0) { + fprintf(stderr, "FAIL: i2d_RSA_PUBKEY_bio failed\n"); + goto done; + } + + len = BIO_get_mem_data(bio_mem, &data); + if (compare_data("RSA_PUBKEY", data, len, rsa_test_asn1_pubkey, + sizeof(rsa_test_asn1_pubkey)) == -1) + goto done; + + RSA_free(rsa_b); + if ((rsa_b = d2i_RSA_PUBKEY_bio(bio_mem, NULL)) == NULL) { + fprintf(stderr, "FAIL: d2i_RSA_PUBKEY_bio failed\n"); + goto done; + } + + if (BN_cmp(RSA_get0_n(rsa_a), RSA_get0_n(rsa_b)) != 0 || + BN_cmp(RSA_get0_e(rsa_a), RSA_get0_e(rsa_b)) != 0) { + fprintf(stderr, "FAIL: RSA public keys mismatch\n"); + goto done; + } + + failure = 0; + + done: + BIO_free_all(bio_mem); + RSA_free(rsa_a); + RSA_free(rsa_b); + EVP_PKEY_free(pkey_a); + EVP_PKEY_free(pkey_b); + free(out); + + return (failure); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + ERR_load_crypto_strings(); + + failed |= dh_pubkey_test(); + failed |= dsa_pubkey_test(); + failed |= ec_pubkey_test(); + failed |= rsa_pubkey_test(); + + return (failed); +} diff --git a/tests/base64test.c b/tests/base64test.c new file mode 100644 index 0000000..9ab2a40 --- /dev/null +++ b/tests/base64test.c @@ -0,0 +1,486 @@ +/* $OpenBSD: base64test.c,v 1.10 2022/09/05 21:06:31 tb Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#define BUF_SIZE 128 + +struct base64_test { + const unsigned char in[BUF_SIZE]; + const ssize_t in_len; + const unsigned char out[BUF_SIZE]; + const ssize_t out_len; + const ssize_t valid_len; +}; + +/* + * Many of these tests are based on those found in Go's encoding/base64 tests. + */ +struct base64_test base64_tests[] = { + + /* RFC3548 examples. */ + { "\x14\xfb\x9c\x03\xd9\x7e", 6, "FPucA9l+", 8, 6, }, + { "\x14\xfb\x9c\x03\xd9", 5, "FPucA9k=", 8, 5, }, + { "\x14\xfb\x9c\x03", 4, "FPucAw==", 8, 4, }, + + /* RFC4648 examples. */ + { "", 0, "", 0, 0, }, + { "f", 1, "Zg==", 4, 1, }, + { "fo", 2, "Zm8=", 4, 2, }, + { "foo", 3, "Zm9v", 4, 3, }, + { "foob", 4, "Zm9vYg==", 8, 4, }, + { "fooba", 5, "Zm9vYmE=", 8, 5, }, + { "foobar", 6, "Zm9vYmFy", 8, 6, }, + + /* Wikipedia examples. */ + { "sure.", 5, "c3VyZS4=", 8, 5, }, + { "sure", 4, "c3VyZQ==", 8, 4, }, + { "sur", 3, "c3Vy", 4, 3, }, + { "su", 2, "c3U=", 4, 2, }, + { "leasure.", 8, "bGVhc3VyZS4=", 12, 8, }, + { "easure.", 7, "ZWFzdXJlLg==", 12, 7, }, + { "asure.", 6, "YXN1cmUu", 8, 6, }, + + { "abcd", 4, "YWJjZA==", 8, 4, }, + + { + "Twas brillig, and the slithy toves", + 34, + "VHdhcyBicmlsbGlnLCBhbmQgdGhlIHNsaXRoeSB0b3Zlcw==", + 48, + 34, + }, +}; + +#define N_TESTS (sizeof(base64_tests) / sizeof(*base64_tests)) + +struct base64_test base64_nl_tests[] = { + + /* Corrupt/invalid encodings. */ + { "", -1, "", 0, 0, }, + { "", -1, "!!!!", 4, 0, }, + { "", -1, "====", 4, 0, }, + { "", -1, "x===", 4, 0, }, + { "", -1, "=AAA", 4, 0, }, + { "", -1, "A=AA", 4, 0, }, + { "", -1, "AA=A", 4, 0, }, + { "", -1, "AA==A", 5, 0, }, + { "", -1, "AAA=AAAA", 8, 0, }, + { "", -1, "AAAAA", 5, 0, }, + { "", -1, "AAAAAA", 6, 0, }, + { "", -1, "A=", 2, 0, }, + { "", -1, "A==", 3, 0, }, + { "", -1, "AA=", 3, 0, }, + { "", -1, "AA==", 4, 1, }, /* XXX - output ix 0x0. */ + { "", -1, "AAA=", 4, 2, }, /* XXX - output ix 2x 0x0. */ + { "", -1, "AAAA", 4, 3, }, /* XXX - output ix 3x 0x0. */ + { "", -1, "AAAAAA=", 7, 0, }, + { "", -1, "YWJjZA=====", 11, 0, }, + + + /* Encodings with embedded CR/LF. */ + { "sure", 4, "c3VyZQ==", 8, 4, }, + { "sure", 4, "c3VyZQ==\r", 9, 4, }, + { "sure", 4, "c3VyZQ==\n", 9, 4, }, + { "sure", 4, "c3VyZQ==\r\n", 10, 4, }, + { "sure", 4, "c3VyZ\r\nQ==", 10, 4, }, + { "sure", 4, "c3V\ryZ\nQ==", 10, 4, }, + { "sure", 4, "c3V\nyZ\rQ==", 10, 4, }, + { "sure", 4, "c3VyZ\nQ==", 9, 4, }, + { "sure", 4, "c3VyZQ\n==", 9, 4, }, + { "sure", 4, "c3VyZQ=\n=", 9, 4, }, + { "sure", 4, "c3VyZQ=\r\n\r\n=", 12, 4, }, + + { + "", + -1, + "YWJjZA======================================================" + "============", + 74, + 0, + }, + + /* OpenSSL-1.1.1d test */ + /* canonical */ + { "", 0, "", 0, 0, }, + /* canonical */ + { "h", 1, "aA==\n", 5, 1, }, + /* canonical */ + { "hello", 5, "aGVsbG8=\n", 9, 5, }, + /* canonical */ + { "hello world!", 12, "aGVsbG8gd29ybGQh\n", 17, 12, }, + /* canonical */ + { "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xa0\xb0\xc0\xd0\xe0\xf0\x00", 17, "AAECAwQFBgcICaCwwNDg8AA=\n", 25, 17, }, + /* invalid # Missing padding */ + { "", -1, "aGVsbG8", 7, 0, }, + /* invalid */ + { "", -1, "aGVsbG8\n", 8, 0, }, + /* valid # Tolerate missing newline */ + { "hello", -1, "aGVsbG8=", 8, 5, }, + /* invalid # Don't tolerate extra trailing '=' */ + { "", -1, "aGVsbG8==\n", 10, 0, }, + /* invalid */ + { "", -1, "aGVsbG8===\n", 11, 0, }, + /* invalid # Don't tolerate data after '=' */ + { "", -1, "aGV=sbG8=\n", 10, 0, }, + /* valid # Newlines are ignored */ + { "hello", -1, "aGV\nsbG8=\n", 10, 5, }, + /* canonical */ + { "hello", 5, "\x61\x47\x56\x73\x62\x47\x38\x3d\x0a", 9, 5, }, + /* invalid # Invalid characters */ + { "", -1, "\x61\x47\x56\x73\x62\x47\x38\x3d\x0a\x00", 10, 0, }, + /* invalid */ + { "", -1, "\x61\x47\x56\x00\x73\x62\x47\x38\x3d\x0a", 10, 0, }, + /* invalid */ + { "", -1, "\x61\x47\x56\x01\x73\x62\x47\x38\x3d\x0a", 10, 0, }, + /* invalid */ + { "", -1, "\x61\x47\x56\x80\x73\x62\x47\x38\x3d\x0a", 10, 0, }, + /* invalid */ + { "", -1, "\xe1\x47\x56\x73\x62\x47\x38\x3d\x0a", 9, 0, }, + /* canonical */ + { "OpenSSLOpenSSL\n", 15, "T3BlblNTTE9wZW5TU0wK\n", 21, 15, }, + /* valid */ + { "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK", 20, 15, }, + /* invalid # Truncate 1-3 chars */ + { "", -1, "T3BlblNTTE9wZW5TU0w", 19, 0, }, + /* invalid */ + { "", -1, "T3BlblNTTE9wZW5TU0", 18, 0, }, + /* invalid */ + { "", -1, "T3BlblNTTE9wZW5TU", 17, 0, }, + /* invalid */ + { "", -1, "T3BlblNTTE9wZW5TU0wK====", 24, 0, }, + /* invalid */ + { "", -1, "T3BlblNTTE9wZW5TU0wK============================================\n", 65, 0, }, + /* invalid */ + { "", -1, "YQ==YQ==YQ==\n", 13, 0, }, + /* invalid */ + { "", -1, "A", 1, 0, }, + /* invalid */ + { "", -1, "A\n", 2, 0, }, + /* invalid */ + { "", -1, "A=", 2, 0, }, + /* invalid */ + { "", -1, "A==\n", 4, 0, }, + /* invalid */ + { "", -1, "A===\n", 5, 0, }, + /* invalid */ + { "", -1, "A====\n", 6, 0, }, + /* valid */ + { "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK\n\n", 22, 15, }, + /* valid */ + { "OpenSSLOpenSSL\n", -1, "T3BlblNTTE\n9wZW5TU0wK", 21, 15, }, + /* invalid # CVE 2015-0292 */ + { "", -1, "ZW5jb2RlIG1lCg==================================================================\n", 81, 0, }, + /* canonical */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 46, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n", 65, 46, }, + /* valid */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n", 66, 46, }, + /* valid */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n", 66, 46, }, + /* invalid */ + { "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA====\n", 67, 0, }, + /* canonical # Multiline output without padding */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 60, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh4eHh4eHh4\n", 82, 60, }, + /* canonical # Multiline output with padding */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 64, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh4eHh4eHh4eHh4eA==\n", 90, 64, }, + /* valid # Multiline output with line break in the middle of a b64 block is accepted */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh4eHh4eHh4eHh4eA==\n", 90, 64, }, + /* valid # Long lines are accepted */ + { "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n", 89, 64, }, + /* invalid # Multiline input with data after '='. */ + { "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\neHh4eHh4eHh4eHh4eHh4eHh4\n", 90, 0, }, + /* invalid */ + { "", -1, "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neA==eHh4eHh4eHh4eHh4eHh4\n", 90, 0, }, + /* valid # B64_EOF ('-') terminates input and trailing bytes are ignored */ + { "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK\n-abcd", 26, 15, }, + /* valid */ + { "OpenSSLOpenSSL\n", -1, "T3BlblNTTE9wZW5TU0wK-abcd", 25, 15, }, +}; + +#define N_NL_TESTS (sizeof(base64_nl_tests) / sizeof(*base64_nl_tests)) + +struct base64_test base64_no_nl_tests[] = { + + /* + * In non-newline mode, the output resulting from corrupt/invalid + * encodings is completely crazy. A number of zero bytes is returned + * rather than nothing. + */ + + /* Corrupt/invalid encodings. */ + { "", -1, "", 0, 0, }, + { "", -1, "!!!!", 4, 0, }, + { "", -1, "====", 4, 1, }, + { "", -1, "x===", 4, 1, }, + { "", -1, "=AAA", 4, 3, }, + { "", -1, "A=AA", 4, 3, }, + { "", -1, "AA=A", 4, 3, }, + { "", -1, "AA==A", 5, 1, }, + { "", -1, "AAA=AAAA", 8, 6, }, + { "", -1, "AAAAA", 5, 3, }, + { "", -1, "AAAAAA", 6, 3, }, + { "", -1, "A=", 2, 0, }, + { "", -1, "A==", 3, 0, }, + { "", -1, "AA=", 3, 0, }, + { "", -1, "AA==", 4, 1, }, + { "", -1, "AAA=", 4, 2, }, + { "", -1, "AAAA", 4, 3, }, + { "", -1, "AAAAAA=", 7, 3, }, + { "", -1, "YWJjZA=====", 11, 4, }, + + /* Encodings with embedded CR/LF. */ + { "sure", 4, "c3VyZQ==", 8, 4, }, + { "sure", 4, "c3VyZQ==\r", 9, 4, }, + { "sure", 4, "c3VyZQ==\n", 9, 4, }, + { "sure", 4, "c3VyZQ==\r\n", 10, 4, }, + { "sure", -1, "c3VyZ\r\nQ==", 10, 0, }, + { "sure", -1, "c3V\ryZ\nQ==", 10, 0, }, + { "sure", -1, "c3V\nyZ\rQ==", 10, 0, }, + { "sure", -1, "c3VyZ\nQ==", 9, 0, }, + { "sure", -1, "c3VyZQ\n==", 9, 0, }, + { "sure", -1, "c3VyZQ=\n=", 9, 0, }, + { "sure", -1, "c3VyZQ=\r\n\r\n=", 12, 0, }, + + /* + * This is invalid, yet results in 'abcd' followed by a stream of + * zero value bytes. + */ + { + "", + -1, + "YWJjZA======================================================" + "============", + 74, + 52, + }, +}; + +#define N_NO_NL_TESTS (sizeof(base64_no_nl_tests) / sizeof(*base64_no_nl_tests)) + +static int +base64_encoding_test(int test_no, struct base64_test *bt, int test_nl) +{ + BIO *bio_b64, *bio_mem; + unsigned char *buf, *out; + ssize_t i, len, b64len; + int failure = 0; + + buf = malloc(BUF_SIZE); + if (buf == NULL) + errx(1, "malloc"); + + bio_b64 = BIO_new(BIO_f_base64()); + if (bio_b64 == NULL) + errx(1, "BIO_new failed for BIO_f_base64"); + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + bio_mem = BIO_push(bio_b64, bio_mem); + + if (!test_nl) + BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); + + len = BIO_write(bio_mem, bt->in, bt->in_len); + if (len != bt->in_len) { + fprintf(stderr, "FAIL: test %d - only wrote %zd out of %zd " + "characters\n", test_no, len, bt->in_len); + failure = 1; + goto done; + } + if (BIO_flush(bio_mem) < 0) { + fprintf(stderr, "FAIL: test %d - flush failed\n", test_no); + failure = 1; + goto done; + } + + b64len = 0; + for (i = 0; i < bt->out_len; i++) { + if ((!test_nl || + (test_nl && (i % 64 != 0 || i == bt->out_len - 1))) && + (bt->out[i] == '\r' || bt->out[i] == '\n')) + continue; + buf[b64len++] = bt->out[i]; + } + if (test_nl) + buf[b64len++] = '\n'; + + len = BIO_get_mem_data(bio_mem, &out); + + /* An empty string with NL results in no output, rather than '\n'. */ + if (test_nl && b64len == 1 && len == 0) + goto done; + + if (len != b64len) { + fprintf(stderr, "FAIL: test %d - encoding resulted in %zd " + "characters instead of %zd\n", test_no, len, b64len); + failure = 1; + goto done; + } + + if (memcmp(buf, out, b64len) != 0) { + fprintf(stderr, "FAIL: test %d - encoding differs:\n", test_no); + fprintf(stderr, " encoding: "); + for (i = 0; i < len; i++) + fprintf(stderr, "%c", out[i]); + fprintf(stderr, "\n"); + fprintf(stderr, " test data: "); + for (i = 0; i < bt->out_len; i++) + fprintf(stderr, "%c", buf[i]); + fprintf(stderr, "\n"); + failure = 1; + } + +done: + BIO_free_all(bio_mem); + free(buf); + + return failure; +} + +static int +base64_decoding_test(int test_no, struct base64_test *bt, int test_nl) +{ + BIO *bio_b64, *bio_mem; + char *buf, *input; + ssize_t i, inlen, len; + int failure = 0; + + buf = malloc(BUF_SIZE); + if (buf == NULL) + errx(1, "malloc"); + + if ((input = malloc(BUF_SIZE)) == NULL) + errx(1, "malloc"); + + memcpy(input, bt->out, bt->out_len); + inlen = bt->out_len; + if (test_nl) { + memcpy(&input[bt->out_len], "\r\n", 2); + inlen += 2; + } + + bio_mem = BIO_new_mem_buf(input, inlen); + if (bio_mem == NULL) + errx(1, "BIO_new_mem_buf failed"); + + bio_b64 = BIO_new(BIO_f_base64()); + if (bio_b64 == NULL) + errx(1, "BIO_new failed for BIO_f_base64"); + + if (!test_nl) + BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL); + + bio_mem = BIO_push(bio_b64, bio_mem); + + /* + * If we wrote zero characters then a BIO_read will result in a return + * value of -1, hence we need to handle this case. + */ + len = BIO_read(bio_mem, buf, BUF_SIZE); + if (len != bt->valid_len && (bt->in_len != 0 || len != -1)) { + fprintf(stderr, "FAIL: test %d - decoding resulted in %zd " + "characters instead of %zd\n", test_no, len, bt->valid_len); + fprintf(stderr, " input: "); + for (i = 0; i < inlen; i++) + fprintf(stderr, "%c", input[i]); + fprintf(stderr, "\n"); + fprintf(stderr, " decoding: "); + for (i = 0; i < len; i++) + fprintf(stderr, "0x%x ", buf[i]); + fprintf(stderr, "\n"); + failure = 1; + goto done; + } + + /* See if we expect this to fail decoding. */ + if (bt->in_len == -1) + goto done; + + if (memcmp(bt->in, buf, bt->in_len) != 0) { + fprintf(stderr, "FAIL: test %d - decoding differs:\n", test_no); + fprintf(stderr, " decoding: "); + for (i = 0; i < len; i++) + fprintf(stderr, "0x%x ", buf[i]); + fprintf(stderr, "\n"); + fprintf(stderr, " test data: "); + for (i = 0; i < bt->in_len; i++) + fprintf(stderr, "0x%x ", bt->in[i]); + fprintf(stderr, "\n"); + failure = 1; + } + +done: + BIO_free_all(bio_mem); + free(buf); + free(input); + + return failure; +} + +int +main(int argc, char **argv) +{ + struct base64_test *bt; + int failed = 0; + size_t i; + + fprintf(stderr, "Starting combined tests...\n"); + + for (i = 0; i < N_TESTS; i++) { + bt = &base64_tests[i]; + if (bt->in_len != -1) + failed += base64_encoding_test(i, bt, 0); + if (bt->out_len != -1) + failed += base64_decoding_test(i, bt, 0); + if (bt->in_len != -1) + failed += base64_encoding_test(i, bt, 1); + if (bt->out_len != -1) + failed += base64_decoding_test(i, bt, 1); + } + + fprintf(stderr, "Starting NL tests...\n"); + + for (i = 0; i < N_NL_TESTS; i++) { + bt = &base64_nl_tests[i]; + + if (bt->in_len != -1) + failed += base64_encoding_test(i, bt, 1); + if (bt->out_len != -1) + failed += base64_decoding_test(i, bt, 1); + } + + fprintf(stderr, "Starting NO NL tests...\n"); + + for (i = 0; i < N_NO_NL_TESTS; i++) { + bt = &base64_no_nl_tests[i]; + + if (bt->in_len != -1) + failed += base64_encoding_test(i, bt, 0); + if (bt->out_len != -1) + failed += base64_decoding_test(i, bt, 0); + } + + return failed; +} diff --git a/tests/bf_test.c b/tests/bf_test.c new file mode 100644 index 0000000..153444e --- /dev/null +++ b/tests/bf_test.c @@ -0,0 +1,1368 @@ +/* $OpenBSD: bf_test.c,v 1.2 2022/11/07 23:04:25 joshua Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct bf_test { + const int mode; + const uint8_t key[64]; + const int key_len; + const uint8_t iv[64]; + const int iv_len; + const uint8_t in[64]; + const int in_len; + const uint8_t out[64]; + const int out_len; + const int padding; +}; + +static const struct bf_test bf_tests[] = { + /* + * ECB - Test vectors from + * https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt + */ + { + .mode = NID_bf_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }, + .key_len = 8, + .in = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }, + .in_len = 8, + .out = { + 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .in = { + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + .in_len = 8, + .out = { + 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + }, + .key_len = 8, + .in = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + }, + .in_len = 8, + .out = { + 0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .key_len = 8, + .in = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + }, + .in_len = 8, + .out = { + 0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + }, + .key_len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .in_len = 8, + .out = { + 0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 + }, + .key_len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .in_len = 8, + .out = { + 0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57, + }, + .key_len = 8, + .in = { + 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42, + }, + .in_len = 8, + .out = { + 0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E, + }, + .key_len = 8, + .in = { + 0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA, + }, + .in_len = 8, + .out = { + 0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86, + }, + .key_len = 8, + .in = { + 0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72, + }, + .in_len = 8, + .out = { + 0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E, + }, + .key_len = 8, + .in = { + 0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A, + }, + .in_len = 8, + .out = { + 0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6, + }, + .key_len = 8, + .in = { + 0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2, + }, + .in_len = 8, + .out = { + 0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE, + }, + .key_len = 8, + .in = { + 0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A, + }, + .in_len = 8, + .out = { + 0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6, + }, + .key_len = 8, + .in = { + 0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2, + }, + .in_len = 8, + .out = { + 0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE, + }, + .key_len = 8, + .in = { + 0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A, + }, + .in_len = 8, + .out = { + 0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16, + }, + .key_len = 8, + .in = { + 0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02, + }, + .in_len = 8, + .out = { + 0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F, + }, + .key_len = 8, + .in = { + 0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A, + }, + .in_len = 8, + .out = { + 0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46, + }, + .key_len = 8, + .in = { + 0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32, + }, + .in_len = 8, + .out = { + 0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E, + }, + .key_len = 8, + .in = { + 0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA, + }, + .in_len = 8, + .out = { + 0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76, + }, + .key_len = 8, + .in = { + 0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62, + }, + .in_len = 8, + .out = { + 0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07, + }, + .key_len = 8, + .in = { + 0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2, + }, + .in_len = 8, + .out = { + 0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F, + }, + .key_len = 8, + .in = { + 0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA, + }, + .in_len = 8, + .out = { + 0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7, + }, + .key_len = 8, + .in = { + 0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92, + }, + .in_len = 8, + .out = { + 0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF, + }, + .key_len = 8, + .in = { + 0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A, + }, + .in_len = 8, + .out = { + 0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6, + }, + .key_len = 8, + .in = { + 0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2, + }, + .in_len = 8, + .out = { + 0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF, + }, + .key_len = 8, + .in = { + 0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A, + }, + .in_len = 8, + .out = { + 0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + }, + .key_len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .in_len = 8, + .out = { + 0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E, + }, + .key_len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .in_len = 8, + .out = { + 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE, + }, + .key_len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .in_len = 8, + .out = { + 0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .in = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }, + .in_len = 8, + .out = { + 0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }, + .key_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + }, + .key_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A, + }, + .out_len = 8, + }, + { + .mode = NID_bf_ecb, + .key = { + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }, + .key_len = 8, + .in = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }, + .in_len = 8, + .out = { + 0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A, + }, + .out_len = 8, + }, + + /* + * CBC - Test vector from + * https://www.schneier.com/wp-content/uploads/2015/12/vectors-2.txt + */ + { + .mode = NID_bf_cbc, + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87, + }, + .key_len = 16, + .iv = { + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + }, + .iv_len = 8, + .in = { + 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20, + 0x66, 0x6F, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 32, + .out = { + 0x6B, 0x77, 0xB4, 0xD6, 0x30, 0x06, 0xDE, 0xE6, + 0x05, 0xB1, 0x56, 0xE2, 0x74, 0x03, 0x97, 0x93, + 0x58, 0xDE, 0xB9, 0xE7, 0x15, 0x46, 0x16, 0xD9, + 0x59, 0xF1, 0x65, 0x2B, 0xD5, 0xFF, 0x92, 0xCC, + }, + .out_len = 32, + .padding = 0, + }, + + /* CBC (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xb9, 0x95, 0xf2, 0x4d, 0xdf, 0xe8, 0x7b, 0xf0, + 0x05, 0x3c, 0x33, 0x39, 0x43, 0x35, 0x83, 0x62, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0x86, 0x6f, 0x5e, 0x72, 0xe5, 0x9a, 0x19, 0x51, + 0x56, 0xf3, 0x2f, 0x5e, 0x95, 0xfb, 0xd6, 0x52, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0xb9, 0x95, 0xf2, 0x4d, 0xdf, 0xe8, 0x7b, 0xf0, + 0x00, 0xf6, 0x2e, 0xf6, 0x6a, 0x03, 0x2d, 0x40, + 0x9c, 0xc9, 0x06, 0x31, 0x67, 0x7f, 0x6e, 0x24, + 0xeb, 0x2d, 0x3b, 0x02, 0xa3, 0x53, 0x52, 0xe9, + }, + .out_len = 32, + }, + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + 0x8b, 0xa5, 0x5d, 0x18, 0x27, 0x44, 0x9c, 0xd3, + }, + .out_len = 24, + .padding = 1, + }, + { + .mode = NID_bf_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 12, + .out = { + 0xc0, 0x1f, 0xae, 0x76, 0x86, 0x86, 0xe7, 0xb7, + 0x3b, 0x0d, 0xd9, 0x72, 0x33, 0x2b, 0x38, 0x5d, + }, + .out_len = 16, + .padding = 1, + }, + + /* CFB64 (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xb9, 0x95, 0xf2, 0x4d, 0xdf, 0xe8, 0x7b, 0xf0, + 0x05, 0x3c, 0x33, 0x39, 0x43, 0x35, 0x83, 0x62, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0xb9, 0x94, 0xf0, 0x4e, 0xdb, 0xed, 0x7d, 0xf7, + 0x0a, 0xf8, 0x96, 0xbf, 0x4d, 0x3c, 0x95, 0xdf, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0x86, 0x6e, 0x5c, 0x71, 0xe1, 0x9f, 0x1f, 0x56, + 0x1f, 0x02, 0xaa, 0x8c, 0x09, 0xe0, 0x61, 0x43, + 0x91, 0x8d, 0xd2, 0x43, 0x70, 0x5d, 0xa3, 0xf1, + 0xc7, 0x96, 0x56, 0x77, 0xfc, 0x33, 0x74, 0x9e, + }, + .out_len = 32, + }, + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + }, + .out_len = 16, + }, + { + .mode = NID_bf_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 12, + .out = { + 0xc0, 0x1f, 0xae, 0x76, 0x86, 0x86, 0xe7, 0xb7, + 0x05, 0xbb, 0xd4, 0x5e, + }, + .out_len = 12, + }, + + /* OFB64 (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + }, + .out_len = 16, + }, + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xb9, 0x95, 0xf2, 0x4d, 0xdf, 0xe8, 0x7b, 0xf0, + 0x05, 0x3c, 0x33, 0x39, 0x43, 0x35, 0x83, 0x62, + }, + .out_len = 16, + }, + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0xb9, 0x94, 0xf0, 0x4e, 0xdb, 0xed, 0x7d, 0xf7, + 0x0d, 0x35, 0x39, 0x32, 0x4f, 0x38, 0x8d, 0x6d, + }, + .out_len = 16, + }, + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0x86, 0x6e, 0x5c, 0x71, 0xe1, 0x9f, 0x1f, 0x56, + 0xbb, 0xcb, 0xd9, 0x35, 0x81, 0x57, 0xea, 0xb9, + 0xd7, 0x85, 0x28, 0x4a, 0xdc, 0xeb, 0x94, 0x99, + 0xf0, 0x87, 0x7c, 0x5a, 0x56, 0x60, 0xc7, 0x60, + }, + .out_len = 32, + }, + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x4e, 0xf9, 0x97, 0x45, 0x61, 0x98, 0xdd, 0x78, + 0xe1, 0xc0, 0x30, 0xe7, 0x4c, 0x14, 0xd2, 0x61, + }, + .out_len = 16, + }, + { + .mode = NID_bf_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .key_len = 8, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 12, + .out = { + 0xc0, 0x1f, 0xae, 0x76, 0x86, 0x86, 0xe7, 0xb7, + 0x05, 0xbb, 0xd4, 0x5e, + }, + .out_len = 12, + }, +}; + +#define N_BF_TESTS (sizeof(bf_tests) / sizeof(bf_tests[0])) + +static int +bf_ecb_test(size_t test_number, const struct bf_test *bt) +{ + BF_KEY key; + uint8_t out[8]; + + if (bt->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + BF_set_key(&key, bt->key_len, bt->key); + BF_ecb_encrypt(bt->in, out, &key, 1); + + if (memcmp(bt->out, out, bt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_bf_ecb, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + BF_set_key(&key, bt->key_len, bt->key); + BF_ecb_encrypt(bt->out, out, &key, 0); + + if (memcmp(bt->in, out, bt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_bf_ecb, test_number); + return 0; + } + + return 1; +} + +static int +bf_cbc_test(size_t test_number, const struct bf_test *bt) +{ + BF_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + + if (bt->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_cbc_encrypt(bt->in, out, bt->in_len, &key, iv, 1); + + if (memcmp(bt->out, out, bt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_bf_cbc, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_cbc_encrypt(bt->out, out, bt->out_len, &key, iv, 0); + + if (memcmp(bt->in, out, bt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_bf_cbc, test_number); + return 0; + } + + return 1; +} + +static int +bf_cfb64_test(size_t test_number, const struct bf_test *bt) +{ + BF_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + int remainder = 0; + + if (bt->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_cfb64_encrypt(bt->in, out, bt->in_len * 8, &key, iv, &remainder, 1); + + if (memcmp(bt->out, out, bt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_bf_cfb64, test_number); + return 0; + } + + /* Decryption */ + remainder = 0; + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_cfb64_encrypt(bt->out, out, bt->out_len, &key, iv, &remainder, 0); + + if (memcmp(bt->in, out, bt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_bf_cfb64, test_number); + return 0; + } + + return 1; +} + +static int +bf_ofb64_test(size_t test_number, const struct bf_test *bt) +{ + BF_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + int remainder = 0; + + if (bt->padding) { + /* XXX - Handle padding */ + return 1; + } + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_ofb64_encrypt(bt->in, out, bt->in_len, &key, iv, &remainder); + + if (memcmp(bt->out, out, bt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_bf_ofb64, test_number); + return 0; + } + + /* Decryption */ + remainder = 0; + memset(out, 0, sizeof(out)); + memcpy(iv, bt->iv, bt->iv_len); + BF_set_key(&key, bt->key_len, bt->key); + BF_ofb64_encrypt(bt->out, out, bt->out_len, &key, iv, &remainder); + + if (memcmp(bt->in, out, bt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_bf_ofb64, test_number); + return 0; + } + + return 1; +} + +static int +bf_evp_test(size_t test_number, const struct bf_test *bt, const char *label, + const EVP_CIPHER *cipher) +{ + EVP_CIPHER_CTX *ctx; + uint8_t out[512]; + int in_len, out_len, total_len; + int i; + int success = 0; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_new failed\n", + label, test_number); + goto failed; + } + + /* EVP encryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_EncryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_key_length(ctx, bt->key_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, bt->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_EncryptInit(ctx, NULL, bt->key, bt->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < bt->in_len;) { + in_len = arc4random_uniform(bt->in_len / 2); + if (in_len > bt->in_len - i) + in_len = bt->in_len - i; + + if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len, + bt->in + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_EncryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_EncryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != bt->out_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP encryption length mismatch " + "(%d != %d)\n", label, test_number, total_len, bt->out_len); + goto failed; + } + + if (memcmp(bt->out, out, bt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP encryption mismatch\n", + label, test_number); + goto failed; + } + + /* EVP decryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_DecryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_key_length(ctx, bt->key_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, bt->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_DecryptInit(ctx, NULL, bt->key, bt->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < bt->out_len;) { + in_len = arc4random_uniform(bt->out_len / 2); + if (in_len > bt->out_len - i) + in_len = bt->out_len - i; + + if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len, + bt->out + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DecryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != bt->in_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP decryption length mismatch\n", + label, test_number); + goto failed; + } + + if (memcmp(bt->in, out, bt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP decryption mismatch\n", + label, test_number); + goto failed; + } + + success = 1; + + failed: + EVP_CIPHER_CTX_free(ctx); + return success; +} + +static int +bf_test(void) +{ + const struct bf_test *bt; + const char *label; + const EVP_CIPHER *cipher; + size_t i; + int failed = 1; + + for (i = 0; i < N_BF_TESTS; i++) { + bt = &bf_tests[i]; + switch (bt->mode) { + case NID_bf_ecb: + label = SN_bf_ecb; + cipher = EVP_bf_ecb(); + if (!bf_ecb_test(i, bt)) + goto failed; + break; + case NID_bf_cbc: + label = SN_bf_cbc; + cipher = EVP_bf_cbc(); + if (!bf_cbc_test(i, bt)) + goto failed; + break; + case NID_bf_cfb64: + label = SN_bf_cfb64; + cipher = EVP_bf_cfb64(); + if (!bf_cfb64_test(i, bt)) + goto failed; + break; + case NID_bf_ofb64: + label = SN_bf_ofb64; + cipher = EVP_bf_ofb(); + if (!bf_ofb64_test(i, bt)) + goto failed; + break; + default: + fprintf(stderr, "FAIL: unknown mode (%d)\n", + bt->mode); + goto failed; + } + + if (!bf_evp_test(i, bt, label, cipher)) + goto failed; + } + + failed = 0; + + failed: + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= bf_test(); + + return failed; +} + diff --git a/tests/bio_asn1.c b/tests/bio_asn1.c new file mode 100644 index 0000000..3eba184 --- /dev/null +++ b/tests/bio_asn1.c @@ -0,0 +1,232 @@ +/* $OpenBSD: bio_asn1.c,v 1.5 2023/07/21 20:22:47 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "asn1_local.h" + +/* + * Minimal reproducer for the BIO_new_NDEF() write after free fixed in + * bio_ndef.c r1.13. + */ + +static int +waf_cb(int op, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) +{ + return 0; +} + +static const ASN1_AUX WAF_aux = { + .asn1_cb = waf_cb, +}; + +static const ASN1_ITEM WAF_it = { + .funcs = &WAF_aux, +}; + +static int +test_bio_new_ndef_waf(void) +{ + BIO *out = NULL; + int failed = 1; + + if ((out = BIO_new(BIO_s_mem())) == NULL) + goto err; + + /* + * BIO_new_NDEF() pushes out onto asn_bio. The waf_cb() call fails. + * Prior to bio_ndef.c r1.13, asn_bio was freed and out->prev_bio + * still pointed to it. + */ + + if (BIO_new_NDEF(out, NULL, &WAF_it) != NULL) { + fprintf(stderr, "%s: BIO_new_NDEF succeeded\n", __func__); + goto err; + } + + /* + * If out->prev_bio != NULL, this writes to out->prev_bio->next_bio. + * After bio_ndef.c r1.13, out is an isolated BIO, so this is a noop. + */ + + BIO_pop(out); + + failed = 0; + + err: + BIO_free(out); + + return failed; +} + +/* + * test_prefix_leak() leaks before asn/bio_asn1.c r1.19. + */ + +static long +read_leak_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret) +{ + int read_return = BIO_CB_READ | BIO_CB_RETURN; + char *set_me; + + if ((cmd & read_return) != read_return) + return ret; + + set_me = BIO_get_callback_arg(bio); + *set_me = 1; + + return 0; +} + +static int +test_prefix_leak(void) +{ + BIO *bio_in = NULL, *bio_out = NULL; + PKCS7 *pkcs7 = NULL; + char set_me = 0; + int failed = 1; + + if ((bio_in = BIO_new_mem_buf("some data\n", -1)) == NULL) + goto err; + + BIO_set_callback(bio_in, read_leak_cb); + BIO_set_callback_arg(bio_in, &set_me); + + if ((pkcs7 = PKCS7_new()) == NULL) + goto err; + if (!PKCS7_set_type(pkcs7, NID_pkcs7_data)) + goto err; + + if ((bio_out = BIO_new(BIO_s_mem())) == NULL) + goto err; + + if (!i2d_PKCS7_bio_stream(bio_out, pkcs7, bio_in, + SMIME_STREAM | SMIME_BINARY)) + goto err; + + if (set_me != 1) { + fprintf(stderr, "%s: read_leak_cb didn't set set_me", __func__); + goto err; + } + + failed = 0; + + err: + BIO_free(bio_in); + BIO_free(bio_out); + PKCS7_free(pkcs7); + + return failed; +} + +/* + * test_infinite_loop() would hang before asn/bio_asn1.c r1.18. + */ + +#define SENTINEL (-57) + +static long +inf_loop_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret) +{ + int write_return = BIO_CB_WRITE | BIO_CB_RETURN; + char *set_me; + + if ((cmd & write_return) != write_return) + return ret; + + set_me = BIO_get_callback_arg(bio); + + /* First time around: ASN1_STATE_HEADER_COPY - succeed. */ + if (*set_me == 0) { + *set_me = 1; + return ret; + } + + /* Second time around: ASN1_STATE_DATA_COPY - return sentinel value. */ + if (*set_me == 1) { + *set_me = 2; + return SENTINEL; + } + + /* Everything else is unexpected: return EOF. */ + *set_me = 3; + + return 0; + +} + +static int +test_infinite_loop(void) +{ + BIO *asn_bio = NULL, *bio = NULL; + char set_me = 0; + int failed = 1; + int write_ret; + + if ((asn_bio = BIO_new(BIO_f_asn1())) == NULL) + goto err; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto err; + + BIO_set_callback(bio, inf_loop_cb); + BIO_set_callback_arg(bio, &set_me); + + if (BIO_push(asn_bio, bio) == NULL) { + BIO_free(bio); + goto err; + } + + if ((write_ret = BIO_write(asn_bio, "foo", 3)) != SENTINEL) { + fprintf(stderr, "%s: BIO_write: want %d, got %d", __func__, + SENTINEL, write_ret); + goto err; + } + + if (set_me != 2) { + fprintf(stderr, "%s: set_me: %d != 2", __func__, set_me); + goto err; + } + + failed = 0; + err: + BIO_free_all(asn_bio); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_bio_new_ndef_waf(); + failed |= test_prefix_leak(); + failed |= test_infinite_loop(); + + return failed; +} diff --git a/tests/bio_chain.c b/tests/bio_chain.c new file mode 100644 index 0000000..abf475b --- /dev/null +++ b/tests/bio_chain.c @@ -0,0 +1,515 @@ +/* $OpenBSD: bio_chain.c,v 1.16 2023/08/07 11:00:54 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#include "bio_local.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +#define CHAIN_POP_LEN 5 +#define LINK_CHAIN_A_LEN 8 +#define LINK_CHAIN_B_LEN 5 + +static BIO * +BIO_prev(BIO *bio) +{ + if (bio == NULL) + return NULL; + + return bio->prev_bio; +} + +static void bio_chain_destroy(BIO **, size_t); + +static int +bio_chain_create(const BIO_METHOD *meth, BIO *chain[], size_t len) +{ + BIO *prev; + size_t i; + + memset(chain, 0, len * sizeof(BIO *)); + + prev = NULL; + for (i = 0; i < len; i++) { + if ((chain[i] = BIO_new(meth)) == NULL) { + fprintf(stderr, "BIO_new failed\n"); + goto err; + } + if ((prev = BIO_push(prev, chain[i])) == NULL) { + fprintf(stderr, "BIO_push failed\n"); + goto err; + } + } + + return 1; + + err: + bio_chain_destroy(chain, len); + + return 0; +} + +static void +bio_chain_destroy(BIO *chain[], size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + BIO_free(chain[i]); + + memset(chain, 0, len * sizeof(BIO *)); +} + +static int +bio_chain_pop_test(void) +{ + BIO *bio[CHAIN_POP_LEN]; + BIO *prev, *next; + size_t i, j; + int failed = 1; + + for (i = 0; i < nitems(bio); i++) { + memset(bio, 0, sizeof(bio)); + prev = NULL; + + if (!bio_chain_create(BIO_s_null(), bio, nitems(bio))) + goto err; + + /* Check that the doubly-linked list was set up as expected. */ + if (BIO_prev(bio[0]) != NULL) { + fprintf(stderr, + "i = %zu: first BIO has predecessor\n", i); + goto err; + } + if (BIO_next(bio[nitems(bio) - 1]) != NULL) { + fprintf(stderr, "i = %zu: last BIO has successor\n", i); + goto err; + } + for (j = 0; j < nitems(bio); j++) { + if (j > 0) { + if (BIO_prev(bio[j]) != bio[j - 1]) { + fprintf(stderr, "i = %zu: " + "BIO_prev(bio[%zu]) != bio[%zu]\n", + i, j, j - 1); + goto err; + } + } + if (j < nitems(bio) - 1) { + if (BIO_next(bio[j]) != bio[j + 1]) { + fprintf(stderr, "i = %zu: " + "BIO_next(bio[%zu]) != bio[%zu]\n", + i, j, j + 1); + goto err; + } + } + } + + /* Drop the ith bio from the chain. */ + next = BIO_pop(bio[i]); + + if (BIO_prev(bio[i]) != NULL || BIO_next(bio[i]) != NULL) { + fprintf(stderr, + "BIO_pop() didn't isolate bio[%zu]\n", i); + goto err; + } + + if (i < nitems(bio) - 1) { + if (next != bio[i + 1]) { + fprintf(stderr, "BIO_pop(bio[%zu]) did not " + "return bio[%zu]\n", i, i + 1); + goto err; + } + } else { + if (next != NULL) { + fprintf(stderr, "i = %zu: " + "BIO_pop(last) != NULL\n", i); + goto err; + } + } + + /* + * Walk the remainder of the chain and see if the doubly linked + * list checks out. + */ + if (i == 0) { + prev = bio[1]; + j = 2; + } else { + prev = bio[0]; + j = 1; + } + + for (; j < nitems(bio); j++) { + if (j == i) + continue; + if (BIO_next(prev) != bio[j]) { + fprintf(stderr, "i = %zu, j = %zu: " + "BIO_next(prev) != bio[%zu]\n", i, j, j); + goto err; + } + if (BIO_prev(bio[j]) != prev) { + fprintf(stderr, "i = %zu, j = %zu: " + "BIO_prev(bio[%zu]) != prev\n", i, j, j); + goto err; + } + prev = bio[j]; + } + + if (BIO_next(prev) != NULL) { + fprintf(stderr, "i = %zu: BIO_next(prev) != NULL\n", i); + goto err; + } + + bio_chain_destroy(bio, nitems(bio)); + } + + failed = 0; + + err: + bio_chain_destroy(bio, nitems(bio)); + + return failed; +} + +static void +walk(BIO *(*step)(BIO *), BIO *start, BIO **end, size_t *len) +{ + BIO *current = NULL; + BIO *next = start; + + *len = 0; + while (next != NULL) { + current = next; + next = step(current); + (*len)++; + } + *end = current; +} + +static int +walk_report(BIO *last, BIO *expected_last, size_t len, size_t expected_len, + size_t i, size_t j, const char *fn, const char *description, + const char *direction, const char *last_name) +{ + if (last != expected_last) { + fprintf(stderr, "%s case (%zu, %zu) %s %s has unexpected %s\n", + fn, i, j, description, direction, last_name); + return 0; + } + + if (len != expected_len) { + fprintf(stderr, "%s case (%zu, %zu) %s %s want %zu, got %zu\n", + fn, i, j, description, direction, expected_len, len); + return 0; + } + + return 1; +} + +static int +walk_forward(BIO *start, BIO *expected_end, size_t expected_len, + size_t i, size_t j, const char *fn, const char *description) +{ + BIO *end; + size_t len; + + walk(BIO_next, start, &end, &len); + + return walk_report(end, expected_end, len, expected_len, + i, j, fn, description, "forward", "end"); +} + +static int +walk_backward(BIO *expected_start, BIO *end, size_t expected_len, + size_t i, size_t j, const char *fn, const char *description) +{ + BIO *start; + size_t len; + + walk(BIO_prev, end, &start, &len); + + return walk_report(start, expected_start, len, expected_len, + i, j, fn, description, "backward", "start"); +} + +static int +check_chain(BIO *start, BIO *end, size_t expected_len, size_t i, size_t j, + const char *fn, const char *description) +{ + if (!walk_forward(start, end, expected_len, i, j, fn, description)) + return 0; + + if (!walk_backward(start, end, expected_len, i, j, fn, description)) + return 0; + + return 1; +} + +/* + * Link two linear chains of BIOs A[] and B[] together using either + * BIO_push(A[i], B[j]) or BIO_set_next(A[i], B[j]). + * + * BIO_push() first walks the chain A[] to its end and then appends the tail + * of chain B[] starting at B[j]. If j > 0, we get two chains + * + * A[0] -- ... -- A[nitems(A) - 1] -- B[j] -- ... -- B[nitems(B) - 1] + * `- link created by BIO_push() + * B[0] -- ... -- B[j-1] + * |<-- oldhead -->| + * + * of lengths nitems(A) + nitems(B) - j and j, respectively. + * If j == 0, the second chain (oldhead) is empty. One quirk of BIO_push() is + * that the outcome of BIO_push(A[i], B[j]) apart from the return value is + * independent of i. + * + * Prior to bio_lib.c r1.41, BIO_push(A[i], B[j]) would fail to dissociate the + * two chains and leave B[j] with two parents for 0 < j < nitems(B). + * B[j]->prev_bio would point at A[nitems(A) - 1], while both B[j - 1] and + * A[nitems(A) - 1] would point at B[j]. In particular, BIO_free_all(A[0]) + * followed by BIO_free_all(B[0]) results in a double free of B[j]. + * + * The result for BIO_set_next() is different: three chains are created. + * + * |--- oldtail --> + * ... -- A[i-1] -- A[i] -- A[i+1] -- ... + * \ + * \ link created by BIO_set_next() + * --- oldhead -->| \ + * ... -- B[j-1] -- B[j] -- B[j+1] -- ... + * + * After creating a new link, the new chain has length i + 1 + nitems(B) - j, + * oldtail has length nitems(A) - i - 1 and oldhead has length j. + * + * Prior to bio_lib.c r1.40, BIO_set_next(A[i], B[j]) would result in both A[i] + * and B[j - 1] pointing at B[j] while B[j] would point back at A[i]. Calling + * BIO_free_all(A[0]) and BIO_free_all(B[0]) results in a double free of B[j]. + * + * XXX: Should check that the callback is called on BIO_push() as expected. + */ + +static int +link_chains_at(size_t i, size_t j, int use_bio_push) +{ + const char *fn = use_bio_push ? "BIO_push" : "BIO_set_next"; + BIO *A[LINK_CHAIN_A_LEN], *B[LINK_CHAIN_B_LEN]; + BIO *new_start, *new_end; + BIO *oldhead_start, *oldhead_end, *oldtail_start, *oldtail_end; + size_t new_len, oldhead_len, oldtail_len; + int failed = 1; + + memset(A, 0, sizeof(A)); + memset(B, 0, sizeof(B)); + + if (i >= nitems(A) || j >= nitems(B)) + goto err; + + /* Create two linear chains of BIOs. */ + if (!bio_chain_create(BIO_s_null(), A, nitems(A))) + goto err; + if (!bio_chain_create(BIO_s_null(), B, nitems(B))) + goto err; + + /* + * Set our expectations. ... it's complicated. + */ + + new_start = A[0]; + new_end = B[nitems(B) - 1]; + /* new_len depends on use_bio_push. It is set a few lines down. */ + + oldhead_start = B[0]; + oldhead_end = BIO_prev(B[j]); + oldhead_len = j; + + /* If we push B[0] or set next to B[0], the oldhead chain is empty. */ + if (j == 0) { + oldhead_start = NULL; + oldhead_end = NULL; + oldhead_len = 0; + } + + if (use_bio_push) { + new_len = nitems(A) + nitems(B) - j; + + /* oldtail doesn't exist in the BIO_push() case. */ + oldtail_start = NULL; + oldtail_end = NULL; + oldtail_len = 0; + } else { + new_len = i + 1 + nitems(B) - j; + + oldtail_start = BIO_next(A[i]); + oldtail_end = A[nitems(A) - 1]; + oldtail_len = nitems(A) - i - 1; + + /* If we set next on end of A[], the oldtail chain is empty. */ + if (i == nitems(A) - 1) { + oldtail_start = NULL; + oldtail_end = NULL; + oldtail_len = 0; + } + } + + /* The two chains A[] and B[] are split into three disjoint pieces. */ + if (nitems(A) + nitems(B) != new_len + oldtail_len + oldhead_len) { + fprintf(stderr, "%s case (%zu, %zu) inconsistent lengths: " + "%zu + %zu != %zu + %zu + %zu\n", fn, i, j, + nitems(A), nitems(B), new_len, oldtail_len, oldhead_len); + goto err; + } + + /* + * Now actually push or set next. + */ + + if (use_bio_push) { + if (BIO_push(A[i], B[j]) != A[i]) { + fprintf(stderr, "BIO_push(A[%zu], B[%zu]) != A[%zu]\n", + i, j, i); + goto err; + } + } else { + BIO_set_next(A[i], B[j]); + } + + /* + * Check that all the chains match our expectations. + */ + + if (!check_chain(new_start, new_end, new_len, i, j, fn, "new chain")) + goto err; + + if (!check_chain(oldhead_start, oldhead_end, oldhead_len, i, j, fn, + "oldhead")) + goto err; + + if (!check_chain(oldtail_start, oldtail_end, oldtail_len, i, j, fn, + "oldtail")) + goto err; + + /* + * All sanity checks passed. We can now free the chains + * with the BIO API without risk of leaks or double frees. + */ + + BIO_free_all(new_start); + BIO_free_all(oldhead_start); + BIO_free_all(oldtail_start); + + memset(A, 0, sizeof(A)); + memset(B, 0, sizeof(B)); + + failed = 0; + + err: + bio_chain_destroy(A, nitems(A)); + bio_chain_destroy(B, nitems(B)); + + return failed; +} + +static int +link_chains(int use_bio_push) +{ + size_t i, j; + int failure = 0; + + for (i = 0; i < LINK_CHAIN_A_LEN; i++) { + for (j = 0; j < LINK_CHAIN_B_LEN; j++) { + failure |= link_chains_at(i, j, use_bio_push); + } + } + + return failure; +} + +static int +bio_push_link_test(void) +{ + int use_bio_push = 1; + + return link_chains(use_bio_push); +} + +static int +bio_set_next_link_test(void) +{ + int use_bio_push = 0; + + return link_chains(use_bio_push); +} + +static long +dup_leak_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret) +{ + if (argi == BIO_CTRL_DUP) + return 0; + + return ret; +} + +static int +bio_dup_chain_leak(void) +{ + BIO *bio[CHAIN_POP_LEN]; + BIO *dup; + int failed = 1; + + if (!bio_chain_create(BIO_s_null(), bio, nitems(bio))) + goto err; + + if ((dup = BIO_dup_chain(bio[0])) == NULL) { + fprintf(stderr, "BIO_set_callback() failed\n"); + goto err; + } + + BIO_set_callback(bio[CHAIN_POP_LEN - 1], dup_leak_cb); + + BIO_free_all(dup); + if ((dup = BIO_dup_chain(bio[0])) != NULL) { + fprintf(stderr, "BIO_dup_chain() succeeded unexpectedly\n"); + BIO_free_all(dup); + goto err; + } + + failed = 0; + + err: + bio_chain_destroy(bio, nitems(bio)); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= bio_chain_pop_test(); + failed |= bio_push_link_test(); + failed |= bio_set_next_link_test(); + failed |= bio_dup_chain_leak(); + + return failed; +} diff --git a/tests/bio_host.c b/tests/bio_host.c new file mode 100644 index 0000000..b3a4645 --- /dev/null +++ b/tests/bio_host.c @@ -0,0 +1,154 @@ +/* $OpenBSD: bio_host.c,v 1.1 2022/12/08 17:49:02 tb Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include + +#include + +struct bio_get_host_ip_test { + char *input; + uint32_t ip; + int ret; +}; + +struct bio_get_host_ip_test bio_get_host_ip_tests[] = { + {"", 0, 0}, + {".", 0, 0}, + {"1", 0, 0}, + {"1.2", 0, 0}, + {"1.2.3", 0, 0}, + {"1.2.3.", 0, 0}, + {"1.2.3.4", 0x01020304, 1}, + {"1.2.3.256", 0, 0}, + {"1:2:3::4", 0, 0}, + {"0.0.0.0", INADDR_ANY, 1}, + {"127.0.0.1", INADDR_LOOPBACK, 1}, + {"localhost", INADDR_LOOPBACK, 1}, + {"255.255.255.255", INADDR_BROADCAST, 1}, + {"0xff.0xff.0xff.0xff", 0, 0}, +}; + +#define N_BIO_GET_IP_TESTS \ + (sizeof(bio_get_host_ip_tests) / sizeof(*bio_get_host_ip_tests)) + +struct bio_get_port_test { + char *input; + unsigned short port; + int ret; +}; + +struct bio_get_port_test bio_get_port_tests[] = { + {NULL, 0, 0}, + {"", 0, 0}, + {"-1", 0, 0}, + {"0", 0, 1}, + {"1", 1, 1}, + {"12345", 12345, 1}, + {"65535", 65535, 1}, + {"65536", 0, 0}, + {"999999999999", 0, 0}, + {"xyzzy", 0, 0}, + {"https", 443, 1}, + {"imaps", 993, 1}, + {"telnet", 23, 1}, +}; + +#define N_BIO_GET_PORT_TESTS \ + (sizeof(bio_get_port_tests) / sizeof(*bio_get_port_tests)) + +static int +do_bio_get_host_ip_tests(void) +{ + struct bio_get_host_ip_test *bgit; + union { + unsigned char c[4]; + uint32_t i; + } ip; + int failed = 0; + size_t i; + int ret; + + for (i = 0; i < N_BIO_GET_IP_TESTS; i++) { + bgit = &bio_get_host_ip_tests[i]; + memset(&ip, 0, sizeof(ip)); + + ret = BIO_get_host_ip(bgit->input, ip.c); + if (ret != bgit->ret) { + fprintf(stderr, "FAIL: test %zd (\"%s\") %s, want %s\n", + i, bgit->input, ret ? "success" : "failure", + bgit->ret ? "success" : "failure"); + failed = 1; + continue; + } + if (ret && ntohl(ip.i) != bgit->ip) { + fprintf(stderr, "FAIL: test %zd (\"%s\") returned ip " + "%x != %x\n", i, bgit->input, + ntohl(ip.i), bgit->ip); + failed = 1; + } + } + + return failed; +} + +static int +do_bio_get_port_tests(void) +{ + struct bio_get_port_test *bgpt; + unsigned short port; + int failed = 0; + size_t i; + int ret; + + for (i = 0; i < N_BIO_GET_PORT_TESTS; i++) { + bgpt = &bio_get_port_tests[i]; + port = 0; + + ret = BIO_get_port(bgpt->input, &port); + if (ret != bgpt->ret) { + fprintf(stderr, "FAIL: test %zd (\"%s\") %s, want %s\n", + i, bgpt->input, ret ? "success" : "failure", + bgpt->ret ? "success" : "failure"); + failed = 1; + continue; + } + if (ret && port != bgpt->port) { + fprintf(stderr, "FAIL: test %zd (\"%s\") returned port " + "%u != %u\n", i, bgpt->input, port, bgpt->port); + failed = 1; + } + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= do_bio_get_host_ip_tests(); + failed |= do_bio_get_port_tests(); + + return failed; +} diff --git a/tests/bio_mem.c b/tests/bio_mem.c new file mode 100644 index 0000000..0da7ee9 --- /dev/null +++ b/tests/bio_mem.c @@ -0,0 +1,345 @@ +/* $OpenBSD: bio_mem.c,v 1.1 2022/12/08 17:49:02 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include +#include + +static int +bio_mem_test(void) +{ + uint8_t *data = NULL; + size_t data_len; + uint8_t *rodata; + long rodata_len; + BUF_MEM *pbuf; + BUF_MEM *buf = NULL; + BIO *bio = NULL; + int ret; + int failed = 1; + + data_len = 4096; + if ((data = malloc(data_len)) == NULL) + err(1, "malloc"); + + memset(data, 0xdb, data_len); + data[0] = 0x01; + data[data_len - 1] = 0xff; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "FAIL: BIO_new() returned NULL\n"); + goto failure; + } + if ((ret = BIO_write(bio, data, data_len)) != (int)data_len) { + fprintf(stderr, "FAIL: BIO_write() = %d, want %zu\n", ret, + data_len); + goto failure; + } + if ((rodata_len = BIO_get_mem_data(bio, &rodata)) != (long)data_len) { + fprintf(stderr, "FAIL: BIO_get_mem_data() = %ld, want %zu\n", + rodata_len, data_len); + goto failure; + } + if (rodata[0] != 0x01) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", rodata[0], 0x01); + goto failure; + } + if (rodata[rodata_len - 1] != 0xff) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", + rodata[rodata_len - 1], 0xff); + goto failure; + } + + if (!BIO_get_mem_ptr(bio, &pbuf)) { + fprintf(stderr, "FAIL: BIO_get_mem_ptr() failed\n"); + goto failure; + } + if (pbuf->length != data_len) { + fprintf(stderr, "FAIL: Got buffer with length %zu, want %zu\n", + pbuf->length, data_len); + goto failure; + } + if (memcmp(pbuf->data, data, data_len) != 0) { + fprintf(stderr, "FAIL: Got buffer with differing data\n"); + goto failure; + } + pbuf = NULL; + + if ((buf = BUF_MEM_new()) == NULL) { + fprintf(stderr, "FAIL: BUF_MEM_new() returned NULL\n"); + goto failure; + } + if (!BIO_set_mem_buf(bio, buf, BIO_NOCLOSE)) { + fprintf(stderr, "FAIL: BUF_set_mem_buf() failed\n"); + goto failure; + } + if ((ret = BIO_puts(bio, "Hello\n")) != 6) { + fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6); + goto failure; + } + if ((ret = BIO_puts(bio, "World\n")) != 6) { + fprintf(stderr, "FAIL: BUF_puts() = %d, want %d\n", ret, 6); + goto failure; + } + if (buf->length != 12) { + fprintf(stderr, "FAIL: buffer has length %zu, want %d\n", + buf->length, 12); + goto failure; + } + buf->length = 11; + if ((ret = BIO_gets(bio, data, data_len)) != 6) { + fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 6); + goto failure; + } + if (strcmp(data, "Hello\n") != 0) { + fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n", + data, "Hello\\n"); + goto failure; + } + if ((ret = BIO_gets(bio, data, data_len)) != 5) { + fprintf(stderr, "FAIL: BUF_gets() = %d, want %d\n", ret, 5); + goto failure; + } + if (strcmp(data, "World") != 0) { + fprintf(stderr, "FAIL: BUF_gets() returned '%s', want '%s'\n", + data, "World"); + goto failure; + } + + if (!BIO_eof(bio)) { + fprintf(stderr, "FAIL: BIO is not EOF\n"); + goto failure; + } + if ((ret = BIO_read(bio, data, data_len)) != -1) { + fprintf(stderr, "FAIL: BIO_read() = %d, want -1\n", ret); + goto failure; + } + if (!BIO_set_mem_eof_return(bio, -2)) { + fprintf(stderr, "FAIL: BIO_set_mem_eof_return() failed\n"); + goto failure; + } + if ((ret = BIO_read(bio, data, data_len)) != -2) { + fprintf(stderr, "FAIL: BIO_read() = %d, want -2\n", ret); + goto failure; + } + + failed = 0; + + failure: + free(data); + BUF_MEM_free(buf); + BIO_free(bio); + + return failed; +} + +static int +bio_mem_small_io_test(void) +{ + uint8_t buf[2]; + int i, j, ret; + BIO *bio; + int failed = 1; + + memset(buf, 0xdb, sizeof(buf)); + + if ((bio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "FAIL: BIO_new() returned NULL\n"); + goto failure; + } + + for (i = 0; i < 100; i++) { + if (!BIO_reset(bio)) { + fprintf(stderr, "FAIL: BIO_reset() failed\n"); + goto failure; + } + for (j = 0; j < 25000; j++) { + ret = BIO_write(bio, buf, sizeof(buf)); + if (ret != sizeof(buf)) { + fprintf(stderr, "FAIL: BIO_write() = %d, " + "want %zu\n", ret, sizeof(buf)); + goto failure; + } + } + for (j = 0; j < 25000; j++) { + ret = BIO_read(bio, buf, sizeof(buf)); + if (ret != sizeof(buf)) { + fprintf(stderr, "FAIL: BIO_read() = %d, " + "want %zu\n", ret, sizeof(buf)); + goto failure; + } + ret = BIO_write(bio, buf, sizeof(buf)); + if (ret != sizeof(buf)) { + fprintf(stderr, "FAIL: BIO_write() = %d, " + "want %zu\n", ret, sizeof(buf)); + goto failure; + } + } + for (j = 0; j < 25000; j++) { + ret = BIO_read(bio, buf, sizeof(buf)); + if (ret != sizeof(buf)) { + fprintf(stderr, "FAIL: BIO_read() = %d, " + "want %zu\n", ret, sizeof(buf)); + goto failure; + } + } + if (!BIO_eof(bio)) { + fprintf(stderr, "FAIL: BIO not EOF\n"); + goto failure; + } + } + + if (buf[0] != 0xdb || buf[1] != 0xdb) { + fprintf(stderr, "FAIL: buf = {0x%x, 0x%x}, want {0xdb, 0xdb}\n", + buf[0], buf[1]); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + + return failed; +} + +static int +bio_mem_readonly_test(void) +{ + uint8_t *data = NULL; + size_t data_len; + uint8_t buf[2048]; + BIO *bio = NULL; + int ret; + int failed = 1; + + data_len = 4096; + if ((data = malloc(data_len)) == NULL) + err(1, "malloc"); + + memset(data, 0xdb, data_len); + data[0] = 0x01; + data[data_len - 1] = 0xff; + + if ((bio = BIO_new_mem_buf(data, data_len)) == NULL) { + fprintf(stderr, "FAIL: BIO_new_mem_buf failed\n"); + goto failure; + } + if ((ret = BIO_read(bio, buf, 1)) != 1) { + fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret, + sizeof(buf)); + goto failure; + } + if (buf[0] != 0x01) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01); + goto failure; + } + if ((ret = BIO_read(bio, buf, sizeof(buf))) != sizeof(buf)) { + fprintf(stderr, "FAIL: BIO_read() = %d, want %zu\n", ret, + sizeof(buf)); + goto failure; + } + if (buf[0] != 0xdb) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0xdb); + goto failure; + } + if ((ret = BIO_write(bio, buf, 1)) != -1) { + fprintf(stderr, "FAIL: BIO_write() = %d, want -1\n", ret); + goto failure; + } + if (BIO_eof(bio)) { + fprintf(stderr, "FAIL: BIO is EOF\n"); + goto failure; + } + if (BIO_ctrl_pending(bio) != 2047) { + fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 2047\n", + BIO_ctrl_pending(bio)); + goto failure; + } + if ((ret = BIO_read(bio, buf, sizeof(buf))) != 2047) { + fprintf(stderr, "FAIL: BIO_read() = %d, want 2047\n", ret); + goto failure; + } + if (buf[2045] != 0xdb) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2045], 0xdb); + goto failure; + } + if (buf[2046] != 0xff) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[2046], 0xff); + goto failure; + } + if (!BIO_eof(bio)) { + fprintf(stderr, "FAIL: BIO is not EOF\n"); + goto failure; + } + if (BIO_ctrl_pending(bio) != 0) { + fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 0\n", + BIO_ctrl_pending(bio)); + goto failure; + } + + if (!BIO_reset(bio)) { + fprintf(stderr, "FAIL: failed to reset bio\n"); + goto failure; + } + if (BIO_eof(bio)) { + fprintf(stderr, "FAIL: BIO is EOF\n"); + goto failure; + } + if (BIO_ctrl_pending(bio) != 4096) { + fprintf(stderr, "FAIL: BIO_ctrl_pending() = %zu, want 4096\n", + BIO_ctrl_pending(bio)); + goto failure; + } + if ((ret = BIO_read(bio, buf, 2)) != 2) { + fprintf(stderr, "FAIL: BIO_read() = %d, want 2\n", ret); + goto failure; + } + if (buf[0] != 0x01) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[0], 0x01); + goto failure; + } + if (buf[1] != 0xdb) { + fprintf(stderr, "FAIL: got 0x%x, want 0x%x\n", buf[1], 0xdb); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + free(data); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= bio_mem_test(); + failed |= bio_mem_small_io_test(); + failed |= bio_mem_readonly_test(); + + return failed; +} diff --git a/tests/bn_add_sub.c b/tests/bn_add_sub.c new file mode 100644 index 0000000..2901dcb --- /dev/null +++ b/tests/bn_add_sub.c @@ -0,0 +1,249 @@ +/* $OpenBSD: bn_add_sub.c,v 1.3 2023/01/31 05:12:16 jsing Exp $ */ +/* + * Copyright (c) 2018 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Test basic functionality of BN_add(), BN_sub(), BN_uadd() and BN_usub() */ + +#include +#include + +#include +#include + +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) + +struct hexinput_st { + const char *a_hex; + const char *b_hex; + const char *e_hex; /* expected result */ + const char ret; /* check return value */ + int compare; /* use BN_cmp() to verify results */ +}; + +int bn_op_test(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *), + struct hexinput_st[], unsigned int, const char *); +void print_failure_case(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, int, + const char *); + +struct hexinput_st test_bn_add[] = { + { + "F", + "F", + "1E", + 1, + 1, + }, + { + "FFFFFFFFFFFFFFFFFFF", + "1", + "10000000000000000000", + 1, + 1, + }, + { + "7878787878787878", + "1010101010101010", + "8888888888888888", + 1, + 1, + }, + { + "FFFFFFFFFFFFFFFF0000000000000000", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "1FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + 1, + 1, + }, + { + "F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0", + "10101010101010101010101010101010", + "101010101010101010101010101010100", + 1, + 1, + }, +}; + +struct hexinput_st test_bn_sub[] = { + { + "10", + "1", + "F", + 1, + 1, + }, + { + "10", + "1", + "E", + 1, + 0, + }, + { + "100000000001000000000", + "11100000001", + "FFFFFFFFFEFEFFFFFFFF", + 1, + 1, + }, + { + "-FFFFFFFFFFFFFFFFFFFF", + "1", + "-100000000000000000000", + 1, + 1, + }, +}; + +struct hexinput_st test_bn_usub[] = { + { + "10", + "1", + "F", + 1, + 1, + }, + { + "10", + "1", + "E", + 1, + 0, + }, + { + "100000000001000000000", + "11100000001", + "FFFFFFFFFEFEFFFFFFFF", + 1, + 1, + }, + { + "11100000001", + "100000000001000000000", + "0", + 0, + 0, + }, + { + "100000000000000000000", + "1", + "FFFFFFFFFFFFFFFFFFFF", + 1, + 1, + }, + { + "1", + "0", + "1", + 1, + 1, + }, + { + "1", + "2", + "FFFFFFFFFFFFFFFF", + 0, + 0, + }, + { + "0", + "1", + "0", + 0, + 0, + }, +}; + +void +print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i, + const char *testname) +{ + fprintf(stderr, "%s #%d failed:", testname, i); + fprintf(stderr, "\na = "); + BN_print_fp(stderr, a); + fprintf(stderr, "\nb = "); + BN_print_fp(stderr, b); + fprintf(stderr, "\nexpected: e = "); + BN_print_fp(stderr, e); + fprintf(stderr, "\nobtained: r = "); + BN_print_fp(stderr, r); + fprintf(stderr, "\n"); +} + +int +bn_op_test(int (*bn_op)(BIGNUM *, const BIGNUM *, const BIGNUM *), + struct hexinput_st tests[], unsigned int ntests, const char *testname) +{ + BIGNUM *a = NULL, *b = NULL, *e = NULL, *r = NULL; + unsigned int i; + int failed = 0; + + if (((a = BN_new()) == NULL) || + ((b = BN_new()) == NULL) || + ((e = BN_new()) == NULL) || + ((r = BN_new()) == NULL)) { + failed = 1; + ERR_print_errors_fp(stderr); + goto err; + } + + for (i = 0; i < ntests; i++) { + int print = 0; + + if (!BN_hex2bn(&a, tests[i].a_hex) || + !BN_hex2bn(&b, tests[i].b_hex) || + !BN_hex2bn(&e, tests[i].e_hex)) { + print = 1; + ERR_print_errors_fp(stderr); + } + + if (tests[i].ret != bn_op(r, a, b)) + print = 1; + if (tests[i].compare == 1 && BN_cmp(e, r) != 0) + print = 1; + if (print) { + failed = 1; + print_failure_case(a, b, e, r, i, testname); + } + } + + err: + BN_free(a); + BN_free(b); + BN_free(e); + BN_free(r); + return failed; +} + +int +main(int argc, char *argv[]) +{ + int failed = 0; + + if (bn_op_test(BN_add, test_bn_add, nitems(test_bn_add), + "BN_add with test_bn_add[]")) + failed = 1; + if (bn_op_test(BN_uadd, test_bn_add, nitems(test_bn_add), + "BN_uadd with test_bn_add[]")) + failed = 1; + if (bn_op_test(BN_sub, test_bn_sub, nitems(test_bn_sub), + "BN_sub with test_bn_sub[]")) + failed = 1; + if (bn_op_test(BN_usub, test_bn_usub, nitems(test_bn_usub), + "BN_usub with test_bn_usub[]")) + failed = 1; + + return failed; +} diff --git a/tests/bn_cmp.c b/tests/bn_cmp.c new file mode 100644 index 0000000..047fac3 --- /dev/null +++ b/tests/bn_cmp.c @@ -0,0 +1,360 @@ +/* $OpenBSD: bn_cmp.c,v 1.2 2023/06/21 07:16:08 jsing Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +struct bn_cmp_test { + const char *a; + const char *b; + int cmp; + int ucmp; +}; + +struct bn_cmp_test bn_cmp_tests[] = { + { + .a = "0", + .b = "0", + .cmp = 0, + .ucmp = 0, + }, + { + .a = "-1", + .b = "0", + .cmp = -1, + .ucmp = 1, + }, + { + .a = "1ffffffffffffffff", + .b = "1ffffffffffffffff", + .cmp = 0, + .ucmp = 0, + }, + { + .a = "1fffffffffffffffe", + .b = "1ffffffffffffffff", + .cmp = -1, + .ucmp = -1, + }, + { + .a = "1ffffffffffffffff", + .b = "1fffffffffffffffe", + .cmp = 1, + .ucmp = 1, + }, + { + .a = "0", + .b = "1ffffffffffffffff", + .cmp = -1, + .ucmp = -1, + }, + { + .a = "1ffffffffffffffff", + .b = "0", + .cmp = 1, + .ucmp = 1, + }, + { + .a = "-1ffffffffffffffff", + .b = "0", + .cmp = -1, + .ucmp = 1, + }, + { + .a = "1ffffffffffffffff", + .b = "00000000000000001ffffffffffffffff", + .cmp = 0, + .ucmp = 0, + }, + { + .a = "-1ffffffffffffffff", + .b = "-00000000000000001ffffffffffffffff", + .cmp = 0, + .ucmp = 0, + }, + { + .a = "1ffffffffffffffff", + .b = "-00000000000000001ffffffffffffffff", + .cmp = 1, + .ucmp = 0, + }, + { + .a = "-1ffffffffffffffff", + .b = "00000000000000001ffffffffffffffff", + .cmp = -1, + .ucmp = 0, + }, +}; + +#define N_BN_CMP_TESTS \ + (sizeof(bn_cmp_tests) / sizeof(*bn_cmp_tests)) + +static int +test_bn_cmp(void) +{ + struct bn_cmp_test *bct; + BIGNUM *a = NULL, *b = NULL; + size_t i; + int ret; + int failed = 1; + + if ((a = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + if ((b = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + + for (i = 0; i < N_BN_CMP_TESTS; i++) { + bct = &bn_cmp_tests[i]; + + if (!BN_hex2bn(&a, bct->a)) { + fprintf(stderr, "FAIL: failed to set a from hex\n"); + goto failure; + } + if (!BN_hex2bn(&b, bct->b)) { + fprintf(stderr, "FAIL: failed to set b from hex\n"); + goto failure; + } + + if ((ret = BN_cmp(a, b)) != bct->cmp) { + fprintf(stderr, "FAIL: BN_cmp(%s, %s) = %d, want %d\n", + bct->a, bct->b, ret, bct->cmp); + goto failure; + } + if ((ret = BN_ucmp(a, b)) != bct->ucmp) { + fprintf(stderr, "FAIL: BN_ucmp(%s, %s) = %d, want %d\n", + bct->a, bct->b, ret, bct->ucmp); + goto failure; + } + } + + failed = 0; + + failure: + BN_free(a); + BN_free(b); + + return failed; +} + +static int +test_bn_cmp_null(void) +{ + BIGNUM *a = NULL; + int ret; + int failed = 1; + + if ((a = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + + /* + * Comparison to NULL. + */ + if ((ret = BN_cmp(NULL, NULL)) != 0) { + fprintf(stderr, "FAIL: BN_cmp(NULL, NULL) == %d, want 0\n", ret); + goto failure; + } + + if ((ret = BN_cmp(a, NULL)) != -1) { + fprintf(stderr, "FAIL: BN_cmp(0, NULL) == %d, want -1\n", ret); + goto failure; + } + if ((ret = BN_cmp(NULL, a)) != 1) { + fprintf(stderr, "FAIL: BN_cmp(NULL, 0) == %d, want 1\n", ret); + goto failure; + } + + if (!BN_set_word(a, 1)) { + fprintf(stderr, "FAIL: failed to set BN to 1\n"); + goto failure; + } + if ((ret = BN_cmp(a, NULL)) != -1) { + fprintf(stderr, "FAIL: BN_cmp(1, NULL) == %d, want -1\n", ret); + goto failure; + } + if ((ret = BN_cmp(NULL, a)) != 1) { + fprintf(stderr, "FAIL: BN_cmp(NULL, 1) == %d, want 1\n", ret); + goto failure; + } + + BN_set_negative(a, 1); + if ((ret = BN_cmp(a, NULL)) != -1) { + fprintf(stderr, "FAIL: BN_cmp(-1, NULL) == %d, want -1\n", ret); + goto failure; + } + if ((ret = BN_cmp(NULL, a)) != 1) { + fprintf(stderr, "FAIL: BN_cmp(NULL, -1) == %d, want 1\n", ret); + goto failure; + } + + failed = 0; + + failure: + BN_free(a); + + return failed; +} + +struct bn_cmp_word_test { + int a; + int b; + int cmp; + int ucmp; +}; + +struct bn_cmp_word_test bn_cmp_word_tests[] = { + { + .a = -1, + .b = -1, + .cmp = 0, + .ucmp = 0, + }, + { + .a = 0, + .b = 0, + .cmp = 0, + .ucmp = 0, + }, + { + .a = 1, + .b = 1, + .cmp = 0, + .ucmp = 0, + }, + { + .a = 0, + .b = 1, + .cmp = -1, + .ucmp = -1, + }, + { + .a = 1, + .b = 0, + .cmp = 1, + .ucmp = 1, + }, + { + .a = -1, + .b = 0, + .cmp = -1, + .ucmp = 1, + }, + { + .a = 0, + .b = -1, + .cmp = 1, + .ucmp = -1, + }, + { + .a = -1, + .b = 1, + .cmp = -1, + .ucmp = 0, + }, + { + .a = 1, + .b = -1, + .cmp = 1, + .ucmp = 0, + }, +}; + +#define N_BN_CMP_WORD_TESTS \ + (sizeof(bn_cmp_word_tests) / sizeof(*bn_cmp_word_tests)) + +static int +test_bn_cmp_word(void) +{ + struct bn_cmp_word_test *bcwt; + BIGNUM *a = NULL, *b = NULL; + BN_ULONG v; + size_t i; + int ret; + int failed = 1; + + if ((a = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + if ((b = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + + for (i = 0; i < N_BN_CMP_WORD_TESTS; i++) { + bcwt = &bn_cmp_word_tests[i]; + + if (bcwt->a >= 0) { + v = bcwt->a; + } else { + v = 0 - bcwt->a; + } + if (!BN_set_word(a, v)) { + fprintf(stderr, "FAIL: failed to set a\n"); + goto failure; + } + BN_set_negative(a, (bcwt->a < 0)); + + if (bcwt->b >= 0) { + v = bcwt->b; + } else { + v = 0 - bcwt->b; + } + if (!BN_set_word(b, v)) { + fprintf(stderr, "FAIL: failed to set b\n"); + goto failure; + } + BN_set_negative(b, (bcwt->b < 0)); + + if ((ret = BN_cmp(a, b)) != bcwt->cmp) { + fprintf(stderr, "FAIL: BN_cmp(%d, %d) = %d, want %d\n", + bcwt->a, bcwt->b, ret, bcwt->cmp); + goto failure; + } + if ((ret = BN_ucmp(a, b)) != bcwt->ucmp) { + fprintf(stderr, "FAIL: BN_ucmp(%d, %d) = %d, want %d\n", + bcwt->a, bcwt->b, ret, bcwt->ucmp); + goto failure; + } + } + + failed = 0; + + failure: + BN_free(a); + BN_free(b); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_bn_cmp(); + failed |= test_bn_cmp_null(); + failed |= test_bn_cmp_word(); + + return failed; +} diff --git a/tests/bn_convert.c b/tests/bn_convert.c new file mode 100644 index 0000000..69f7da4 --- /dev/null +++ b/tests/bn_convert.c @@ -0,0 +1,628 @@ +/* $OpenBSD: bn_convert.c,v 1.3 2023/06/23 10:50:47 tb Exp $ */ +/* + * Copyright (c) 2023 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +/* + * Additional test coverage is needed for: + * + * - BN_bn2binpad() + * - BN_bn2lebinpad() + * - BN_lebin2bn() + * - BN_bn2mpi()/BN_mpi2bn() + * - BN_print()/BN_print_fp() + * + * - Invalid inputs to {asc,dec,hex,mpi}2bn + * - Zero padded inputs + */ + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +check_bin_output(size_t test_no, const char *label, const uint8_t *bin, + size_t bin_len, const BIGNUM *bn) +{ + uint8_t *out = NULL; + int out_len; + int ret; + int failed = 1; + + out_len = BN_num_bytes(bn); + if (out_len != (int)bin_len) { + fprintf(stderr, "FAIL: Test %zu %s - BN_num_bytes() = %d, " + "want %zu\n", test_no, label, out_len, bin_len); + goto failure; + } + if ((out = malloc(out_len)) == NULL) + err(1, "malloc"); + if ((ret = BN_bn2bin(bn, out)) != out_len) { + fprintf(stderr, "FAIL: Test %zu %s - BN_bn2bin() returned %d, " + "want %d\n", test_no, label, ret, out_len); + goto failure; + } + if (memcmp(out, bin, bin_len) != 0) { + fprintf(stderr, "FAIL: Test %zu %s - output from " + "BN_bn2bin() differs\n", test_no, label); + fprintf(stderr, "Got:\n"); + hexdump(out, out_len); + fprintf(stderr, "Want:\n"); + hexdump(bin, bin_len); + goto failure; + } + + failed = 0; + + failure: + free(out); + + return failed; +} + +struct bn_asc2bn_test { + const char *in; + const uint8_t bin[64]; + size_t bin_len; + int neg; + int want_error; +}; + +static const struct bn_asc2bn_test bn_asc2bn_tests[] = { + { + .in = "", + .want_error = 1, + }, + { + .in = "-", + .want_error = 1, + }, + { + .in = "0", + .bin = { 0x00, }, + .bin_len = 0, + .neg = 0, + }, + { + .in = "0x0", + .bin = { 0x00, }, + .bin_len = 0, + .neg = 0, + }, + { + .in = "-0", + .bin = { 0x00, }, + .bin_len = 0, + .neg = 0, + }, + { + .in = "-0x0", + .bin = { 0x00, }, + .bin_len = 0, + .neg = 0, + }, + { + .in = "123456789", + .bin = { 0x07, 0x5b, 0xcd, 0x15, }, + .bin_len = 4, + .neg = 0, + }, + { + .in = "0123456789", + .bin = { 0x07, 0x5b, 0xcd, 0x15, }, + .bin_len = 4, + .neg = 0, + }, + { + .in = "-123456789", + .bin = { 0x07, 0x5b, 0xcd, 0x15, }, + .bin_len = 4, + .neg = 1, + }, + { + .in = "0X123456789", + .bin = { 0x01, 0x23, 0x45, 0x67, 0x89, }, + .bin_len = 5, + .neg = 0, + }, + { + .in = "0x123456789", + .bin = { 0x01, 0x23, 0x45, 0x67, 0x89, }, + .bin_len = 5, + .neg = 0, + }, + { + .in = "-0x123456789", + .bin = { 0x01, 0x23, 0x45, 0x67, 0x89, }, + .bin_len = 5, + .neg = 1, + }, + { + .in = "abcdef123456789", + .want_error = 1, + }, + { + .in = "0x000123456789abCdEf", + .bin = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + .bin_len = 8, + .neg = 0, + }, +}; + +#define N_BN_ASC2BN_TESTS \ + (sizeof(bn_asc2bn_tests) / sizeof(*bn_asc2bn_tests)) + +static int +test_bn_asc2bn(void) +{ + const struct bn_asc2bn_test *bat; + BIGNUM *bn = NULL; + size_t i; + int failed = 1; + + for (i = 0; i < N_BN_ASC2BN_TESTS; i++) { + bat = &bn_asc2bn_tests[i]; + + BN_free(bn); + bn = NULL; + + if (!BN_asc2bn(&bn, bat->in)) { + if (bat->want_error) + continue; + fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() failed\n", i); + goto failure; + } + if (bat->want_error) { + fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() succeeded " + "when it should have failed\n", i); + goto failure; + } + + if (check_bin_output(i, "BN_asc2bn()", bat->bin, bat->bin_len, + bn) != 0) + goto failure; + + if (BN_is_negative(bn) != bat->neg) { + fprintf(stderr, "FAIL: Test %zu - BN_asc2bn() resulted " + "in negative %d, want %d", i, BN_is_negative(bn), + bat->neg); + goto failure; + } + } + + /* + * While it makes little sense to call BN_asc2bn() with a NULL bn, + * check for consistent behavior. + */ + if (!BN_asc2bn(NULL, "1") || !BN_asc2bn(NULL, "-1") || + !BN_asc2bn(NULL, "0x1") || !BN_asc2bn(NULL, "-0x1")) { + fprintf(stderr, "FAIL: BN_asc2bn() with NULL BIGNUM failed\n"); + goto failure; + } + + failed = 0; + + failure: + BN_free(bn); + + return failed; +} + +struct bn_convert_test { + const uint8_t bin[64]; + size_t bin_len; + int neg; + const char *dec; + const char *hex; +}; + +static const struct bn_convert_test bn_convert_tests[] = { + { + .bin = { 0x0, }, + .bin_len = 0, + .neg = 0, + .dec = "0", + .hex = "0", + }, + { + .bin = { 0x1, }, + .bin_len = 1, + .neg = 0, + .dec = "1", + .hex = "01", + }, + { + .bin = { 0x7f, 0xff, 0xff, }, + .bin_len = 3, + .neg = 0, + .dec = "8388607", + .hex = "7FFFFF", + }, + { + .bin = { 0x7f, 0xff, 0xff, }, + .bin_len = 3, + .neg = 1, + .dec = "-8388607", + .hex = "-7FFFFF", + }, + { + .bin = { 0xff, 0xff, 0xff, 0xff, }, + .bin_len = 4, + .neg = 0, + .dec = "4294967295", + .hex = "FFFFFFFF", + }, + { + .bin = { 0xff, 0xff, 0xff, 0xff, }, + .bin_len = 4, + .neg = 1, + .dec = "-4294967295", + .hex = "-FFFFFFFF", + }, + { + .bin = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }, + .bin_len = 8, + .neg = 0, + .dec = "18446744069414584320", + .hex = "FFFFFFFF00000000", + }, + { + .bin = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }, + .bin_len = 8, + .neg = 1, + .dec = "-18446744069414584320", + .hex = "-FFFFFFFF00000000", + }, + { + .bin = { 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, }, + .bin_len = 8, + .neg = 0, + .dec = "9223794255762391041", + .hex = "8001800180018001", + }, + { + .bin = { 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, }, + .bin_len = 8, + .neg = 1, + .dec = "-9223794255762391041", + .hex = "-8001800180018001", + }, + { + .bin = { 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, }, + .bin_len = 9, + .neg = 0, + .dec = "27670538329471942657", + .hex = "018001800180018001", + }, + { + .bin = { 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, }, + .bin_len = 9, + .neg = 1, + .dec = "-27670538329471942657", + .hex = "-018001800180018001", + }, + { + .bin = { + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + }, + .bin_len = 32, + .neg = 0, + .dec = "57895161181645529494837117048595051142566530671229791132691030063130991362047", + .hex = "7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF", + }, + { + .bin = { + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, + }, + .bin_len = 32, + .neg = 1, + .dec = "-57895161181645529494837117048595051142566530671229791132691030063130991362047", + .hex = "-7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF7FFF", + }, +}; + +#define N_BN_CONVERT_TESTS \ + (sizeof(bn_convert_tests) / sizeof(*bn_convert_tests)) + +static int +test_bn_convert(void) +{ + const struct bn_convert_test *bct; + char *out_str = NULL; + BIGNUM *bn = NULL; + size_t i; + int failed = 1; + + for (i = 0; i < N_BN_CONVERT_TESTS; i++) { + bct = &bn_convert_tests[i]; + + BN_free(bn); + if ((bn = BN_bin2bn(bct->bin, bct->bin_len, NULL)) == NULL) { + fprintf(stderr, "FAIL: BN_bin2bn() failed\n"); + goto failure; + } + BN_set_negative(bn, bct->neg); + + if (check_bin_output(i, "BN_bin2bn()", bct->bin, bct->bin_len, + bn) != 0) + goto failure; + + free(out_str); + if ((out_str = BN_bn2dec(bn)) == NULL) { + fprintf(stderr, "FAIL: BN_bn2dec() failed\n"); + goto failure; + } + if (strcmp(out_str, bct->dec) != 0) { + fprintf(stderr, "FAIL: Test %zu - BN_bn2dec() returned " + "'%s', want '%s'", i, out_str, bct->dec); + goto failure; + } + + free(out_str); + if ((out_str = BN_bn2hex(bn)) == NULL) { + fprintf(stderr, "FAIL: BN_bn2hex() failed\n"); + goto failure; + } + if (strcmp(out_str, bct->hex) != 0) { + fprintf(stderr, "FAIL: Test %zu - BN_bn2hex() returned " + "'%s', want '%s'", i, out_str, bct->hex); + goto failure; + } + + if (BN_dec2bn(&bn, bct->dec) != (int)strlen(bct->dec)) { + fprintf(stderr, "FAIL: BN_dec2bn() failed\n"); + goto failure; + } + if (BN_is_negative(bn) != bct->neg) { + fprintf(stderr, "FAIL: Test %zu - BN_dec2bn() resulted " + "in negative %d, want %d", i, BN_is_negative(bn), + bct->neg); + goto failure; + } + + if (check_bin_output(i, "BN_dec2bn()", bct->bin, bct->bin_len, + bn) != 0) + goto failure; + + if (BN_hex2bn(&bn, bct->hex) != (int)strlen(bct->hex)) { + fprintf(stderr, "FAIL: BN_hex2bn() failed\n"); + goto failure; + } + if (BN_is_negative(bn) != bct->neg) { + fprintf(stderr, "FAIL: Test %zu - BN_hex2bn() resulted " + "in negative %d, want %d", i, BN_is_negative(bn), + bct->neg); + goto failure; + } + + if (check_bin_output(i, "BN_hex2bn()", bct->bin, bct->bin_len, + bn) != 0) + goto failure; + } + + failed = 0; + + failure: + free(out_str); + BN_free(bn); + + return failed; +} + +static int +test_bn_dec2bn(void) +{ + BIGNUM *bn = NULL; + BN_ULONG w; + int ret; + int failed = 1; + + /* An empty string fails to parse, as does NULL. */ + if (BN_dec2bn(&bn, "") != 0) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"\") succeeded\n"); + goto failure; + } + if (bn != NULL) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"\") succeeded\n"); + goto failure; + } + if (BN_dec2bn(&bn, NULL) != 0) { + fprintf(stderr, "FAIL: BN_dec2bn(_, NULL) succeeded\n"); + goto failure; + } + if (bn != NULL) { + fprintf(stderr, "FAIL: BN_dec2bn(_, NULL) succeeded\n"); + goto failure; + } + + /* A minus sign parses as 0. */ + if (BN_dec2bn(&bn, "-") != 1) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") failed\n"); + goto failure; + } + if (bn == NULL) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") failed\n"); + goto failure; + } + if (!BN_is_zero(bn)) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") is non-zero\n"); + goto failure; + } + if (BN_is_negative(bn)) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-\") resulted in " + "negative zero\n"); + goto failure; + } + + /* Ensure that -0 results in 0. */ + if (BN_dec2bn(&bn, "-0") != 2) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") failed\n"); + goto failure; + } + if (!BN_is_zero(bn)) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") is non-zero\n"); + goto failure; + } + if (BN_is_negative(bn)) { + fprintf(stderr, "FAIL: BN_dec2bn(_, \"-0\") resulted in " + "negative zero\n"); + goto failure; + } + + /* BN_dec2bn() is the new atoi()... */ + if ((ret = BN_dec2bn(&bn, "0123456789abcdef")) != 10) { + fprintf(stderr, "FAIL: BN_dec2bn() returned %d, want 10\n", ret); + goto failure; + } + if ((w = BN_get_word(bn)) != 0x75bcd15) { + fprintf(stderr, "FAIL: BN_dec2bn() resulted in %llx, want %llx\n", + (unsigned long long)w, 0x75bcd15ULL); + goto failure; + } + + /* And we can call BN_dec2bn() without actually converting to a BIGNUM. */ + if ((ret = BN_dec2bn(NULL, "0123456789abcdef")) != 10) { + fprintf(stderr, "FAIL: BN_dec2bn() returned %d, want 10\n", ret); + goto failure; + } + + failed = 0; + + failure: + BN_free(bn); + + return failed; +} + +static int +test_bn_hex2bn(void) +{ + BIGNUM *bn = NULL; + BN_ULONG w; + int ret; + int failed = 1; + + /* An empty string fails to parse, as does NULL. */ + if (BN_hex2bn(&bn, "") != 0) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"\") succeeded\n"); + goto failure; + } + if (bn != NULL) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"\") succeeded\n"); + goto failure; + } + if (BN_hex2bn(&bn, NULL) != 0) { + fprintf(stderr, "FAIL: BN_hex2bn(_, NULL) succeeded\n"); + goto failure; + } + if (bn != NULL) { + fprintf(stderr, "FAIL: BN_hex2bn(_, NULL) succeeded\n"); + goto failure; + } + + /* A minus sign parses as 0. */ + if (BN_hex2bn(&bn, "-") != 1) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") failed\n"); + goto failure; + } + if (bn == NULL) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") failed\n"); + goto failure; + } + if (!BN_is_zero(bn)) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") returned non-zero\n"); + goto failure; + } + if (BN_is_negative(bn)) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-\") returned negative zero\n"); + goto failure; + } + + /* Ensure that -0 results in 0. */ + if (BN_hex2bn(&bn, "-0") != 2) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") failed\n"); + goto failure; + } + if (!BN_is_zero(bn)) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") is non-zero\n"); + goto failure; + } + if (BN_is_negative(bn)) { + fprintf(stderr, "FAIL: BN_hex2bn(_, \"-0\") resulted in " + "negative zero\n"); + goto failure; + } + + /* BN_hex2bn() is the new atoi()... */ + if ((ret = BN_hex2bn(&bn, "9abcdefz")) != 7) { + fprintf(stderr, "FAIL: BN_hex2bn() returned %d, want 7\n", ret); + goto failure; + } + if ((w = BN_get_word(bn)) != 0x9abcdef) { + fprintf(stderr, "FAIL: BN_hex2bn() resulted in %llx, want %llx\n", + (unsigned long long)w, 0x9abcdefULL); + goto failure; + } + + /* A 0x prefix fails to parse without BN_asc2bn() (instead we get 0!). */ + if (BN_hex2bn(&bn, "0x1") != 1) { + fprintf(stderr, "FAIL: BN_hex2bn() parsed a 0x prefix\n"); + goto failure; + } + + /* And we can call BN_hex2bn() without actually converting to a BIGNUM. */ + if ((ret = BN_hex2bn(NULL, "9abcdefz")) != 7) { + fprintf(stderr, "FAIL: BN_hex2bn() returned %d, want 7\n", ret); + goto failure; + } + + failed = 0; + + failure: + BN_free(bn); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_bn_asc2bn(); + failed |= test_bn_convert(); + failed |= test_bn_dec2bn(); + failed |= test_bn_hex2bn(); + + return failed; +} diff --git a/tests/bn_gcd.c b/tests/bn_gcd.c new file mode 100644 index 0000000..b247b9b --- /dev/null +++ b/tests/bn_gcd.c @@ -0,0 +1,3670 @@ +/* $OpenBSD: bn_gcd.c,v 1.3 2023/04/07 17:09:54 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_gcd_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + +static const struct gcd_test_fn { + const char *name; + int (*fn)(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + int fails_on_zero; +} gcd_fn[] = { + { + .name = "BN_gcd", + .fn = BN_gcd, + }, + { + .name = "BN_gcd_ct", + .fn = BN_gcd_ct, + .fails_on_zero = 1, + }, +}; + +#define N_GCD_FN (sizeof(gcd_fn) / sizeof(gcd_fn[0])) + +static const struct gcd_test { + const char *a; + const char *b; + const char *r; +} bn_gcd_tests[] = { + { + .a = "0", + .b = "0", + .r = "0", + }, + { + .a = "1", + .b = "1", + .r = "1", + }, + { + .a = "1", + .b = "0", + .r = "1", + }, + { + .a = "0", + .b = "1", + .r = "1", + }, + { + .a = "57", + .b = "0", + .r = "57", + }, + { + .a = "0", + .b = "57", + .r = "57", + }, + + /* + * The following test cases were randomly generated. + */ + + { + .a = "255", + .b = "278d3", + .r = "3", + }, + { + .a = "6a54d", + .b = "619", + .r = "7", + }, + { + .a = "e9", + .b = "e695", + .r = "1", + }, + { + .a = "3f3a9", + .b = "41f", + .r = "5", + }, + { + .a = "643", + .b = "5bff1", + .r = "7", + }, + { + .a = "2bb", + .b = "29be3", + .r = "3", + }, + { + .a = "49e", + .b = "5770e", + .r = "6", + }, + { + .a = "f1d5", + .b = "fb", + .r = "1", + }, + { + .a = "250eb50", + .b = "206b0", + .r = "2b0", + }, + { + .a = "57ad2", + .b = "64927d6", + .r = "6a6", + }, + { + .a = "430bc", + .b = "48757a4", + .r = "564", + }, + { + .a = "7593a8c", + .b = "7161c", + .r = "7ec", + }, + { + .a = "5771161", + .b = "53d9b", + .r = "5e9", + }, + { + .a = "4132d82", + .b = "37b1e", + .r = "49e", + }, + { + .a = "72492b0", + .b = "65f90", + .r = "730", + }, + { + .a = "14bab", + .b = "163605b", + .r = "1af", + }, + { + .a = "602d952bd", + .b = "5a08833", + .r = "62ebb", + }, + { + .a = "698bf2b", + .b = "65849195f", + .r = "701db", + }, + { + .a = "37d4a5f", + .b = "402dcce6f", + .r = "488d3", + }, + { + .a = "614e922", + .b = "6644a8e72", + .r = "6cc7a", + }, + { + .a = "1eea0a75c", + .b = "1ea5c64", + .r = "21ac4", + }, + { + .a = "6136d54", + .b = "6acfd5d8c", + .r = "7e544", + }, + { + .a = "2bba7aaf2", + .b = "33894f6", + .r = "34902", + }, + { + .a = "467c1e94", + .b = "3c036c", + .r = "4d34", + }, + { + .a = "19c3fcfc5", + .b = "15f969b26a7", + .r = "1b9928b", + }, + { + .a = "145666d9a", + .b = "13bbb7f3bb6", + .r = "159a73a", + }, + { + .a = "1b0c38f9e", + .b = "18765759b3e", + .r = "1f0ce22", + }, + { + .a = "784064e87", + .b = "667b4b1bc85", + .r = "7fbc6f7", + }, + { + .a = "498054afdd3", + .b = "44d269073", + .r = "596efd7", + }, + { + .a = "198ba337af6", + .b = "1f5755eca", + .r = "214ab6a", + }, + { + .a = "5effbed2b", + .b = "6a7cdb539bd", + .r = "7b7352f", + }, + { + .a = "14388cf1265", + .b = "153338971", + .r = "174af49", + }, + { + .a = "2d4aff46122f30851a52b", + .b = "2edb8fdd14ab1b645", + .r = "332805d24fd69", + }, + { + .a = "43733ea897495e14339f9", + .b = "3e843370070058d8d", + .r = "49977f36263b5", + }, + { + .a = "58aafd7662b8de019", + .b = "5538bdda74849754e4949", + .r = "5daa7b4439b0f", + }, + { + .a = "474100872e962de8b0596", + .b = "45223dbbeaaba9e92", + .r = "580218df81b62", + }, + { + .a = "307c55bb52be32b4d", + .b = "2cc525ce8e2d2bc67aa6d", + .r = "30c17810923d9", + }, + { + .a = "4a2a6504adf43e733", + .b = "497c44b84fb6f8774f787", + .r = "5ea902856aae1", + }, + { + .a = "5b8e523f7c7b60972", + .b = "4aebe8c99000a8bd30652", + .r = "63b8fd8af9062", + }, + { + .a = "53a047f3c3f81986811d7", + .b = "53b004a9fa740fcbb", + .r = "64d12a952833b", + }, + { + .a = "6f177c61fa6afe2d209", + .b = "670a0a35553c35d52fb18f5", + .r = "74c624a8a32333b", + }, + { + .a = "5343fd2374414df3034", + .b = "507c3e327a45f92c78eeb84", + .r = "5974af2eca1fe94", + }, + { + .a = "4a07f6267329d80c7d4bdfa", + .b = "56a012dd8379b7a0e16", + .r = "59052131189608e", + }, + { + .a = "63bba164fd337e80d0c", + .b = "615a76fb66b1094efbcba2c", + .r = "735585f95d70274", + }, + { + .a = "2453ea8b7fca0284b883078", + .b = "234099d522bcad7e248", + .r = "2d69bd4f4b8d088", + }, + { + .a = "61b5dc7806b84d2b08c", + .b = "58b8dde9e5f8ecfde43cd74", + .r = "75ff164a01eaa7c", + }, + { + .a = "3816984948c1e79f882", + .b = "3b5b01106809f6bb2e2e016", + .r = "48170e737316bca", + }, + { + .a = "41b4deb320e45f566b", + .b = "4874dbcc44f53775a6a1d7", + .r = "4977a5459131df", + }, + { + .a = "364580a30652080c07c9dc48", + .b = "2e1c73c5131cbbf50628", + .r = "36825feeccb49b58", + }, + { + .a = "695d74ad760a5795570a3", + .b = "62bc190742c20aa29644c84eb", + .r = "6abcf0da95d5be6f7", + }, + { + .a = "74db3db1ab6c202baff804bcd", + .b = "6380a7b03658ba56b34a3", + .r = "756f230199f1529ab", + }, + { + .a = "4b26c75874a09700b9d512ed8", + .b = "4ca3361909906b0cf7618", + .r = "53055ca37fd154698", + }, + { + .a = "1f81faea97f44cd5c6adb457d", + .b = "22c452983db5a6ce9736f", + .r = "241a04dc3e4719c37", + }, + { + .a = "95e5584090df556539aa9fd9", + .b = "b02f19eec1f1f2d44c59", + .r = "c5c889564b7e8bab", + }, + { + .a = "4a908939e089498a7feab", + .b = "60045b573dccb74a9e2e379d5", + .r = "6116326ef394c59e7", + }, + { + .a = "39443c6a7d6bd95529a12", + .b = "409e977e693f5bd1b17b0433a", + .r = "49802f618e94d218a", + }, + { + .a = "3e6fc6cf9eaba3e94f24f03", + .b = "345aa9ded17c65a6c85dd7e6d61", + .r = "3ea3e52d4d5d024c389", + }, + { + .a = "64f62375ce39484ec7e85f4e3d", + .b = "69459ea484d6480a376e91", + .r = "748b7824736c5c39e5", + }, + { + .a = "4186cead307cad31530dd205a39", + .b = "4f5ee69f4afbb46507ccc8b", + .r = "533aef3d540410a6b2b", + }, + { + .a = "536b816e2daa705e44bae82", + .b = "4e8a14632ccec82f41941b1fd7e", + .r = "5bf87a677ef2ec1bd76", + }, + { + .a = "6518022e9b5920c69de925", + .b = "6d90bcb3174b93f44a2854f601", + .r = "7cc47ec91e90d61599", + }, + { + .a = "2f443ac559d746b4b8f87c802af", + .b = "2ef35b22f59380207cd3a09", + .r = "33f82dc6aa168711c2f", + }, + { + .a = "17418a08c177e039b1e5000", + .b = "183bf7b0342fe483457340ab000", + .r = "1da412c88f3a0c3f000", + }, + { + .a = "77685efaa0d4e6a25268eaa07", + .b = "65b89e487f7a272f6187b", + .r = "80861458bce7097f7", + }, + { + .a = "1488a0aab5415ee1ce826ecb38f7b33", + .b = "131c43cca73843a27b9feac46cd03d5de7a2f", + .r = "17b3a3001f3660377791cd8cf", + }, + { + .a = "5349d29af82e6b8fae6c25859fadec6207032", + .b = "64d277bfb253b9a22f3c0187445253a", + .r = "6573b739e39b0650a9c2c2f02", + }, + { + .a = "21df6046ab805b9f71a304d34236fe8", + .b = "1fe085864e8e75ea073efebfe6fbab133e4e8", + .r = "23e3d1525042d237154d245f8", + }, + { + .a = "56454c66089738f7074ce55236dce53b22a11", + .b = "5d5308342f5a0c2277762ba37273f07", + .r = "71fb0beacaae6adab73b8cfbb", + }, + { + .a = "25e20fcd81385c099f1db654feba9b1", + .b = "2134ea8527e2ad47f460d70b918ba69fd4c6b", + .r = "268d03475633df8adccd7eda9", + }, + { + .a = "6713eb612dab2940e2741150dfa203f632d5f", + .b = "611184b794056ec03b0aeb7c1646be9", + .r = "752472cea4fe17a0cc5881d23", + }, + { + .a = "39a3fe02e4f8cb7cfc972275862512c6e863c", + .b = "356731db8ae0f405b01423d24a00df4", + .r = "4230cc0ff4cb762463e8f45a4", + }, + { + .a = "48c66d2a5a9f354fbe6a24379b3c868", + .b = "3d52dfc550d9288335bc4ca727d0008e225d8", + .r = "4e38e92332937fe6d87b9e888", + }, + { + .a = "30de4f96ec186d1f64298c5ae4510f448", + .b = "30cbcdb08d24818e2845286f4b70760116f96e8", + .r = "32f5f8996bc47879755ea626348", + }, + { + .a = "4e3cbdc0d866680fd0cf79732b914033c", + .b = "4c0fc242dbe2f4ba5592ffc621eca68499e807c", + .r = "556fcff7e03458aba9b3229def4", + }, + { + .a = "4f902e3c221d879daae7536c66d0d1e0a", + .b = "4e2451f07d9559f3c36746cef62cb2ce95525de", + .r = "5be6e06842ff90445f2d002fdce", + }, + { + .a = "1ec50fe3ba8edcdd47cecf6b1e67d2263bee334", + .b = "20eb4fa3aabacd28aa5126fa29425be14", + .r = "244d6242059f13924023015b8bc", + }, + { + .a = "f85a29486c90172f2fcb0e8f2b9cc357235f8", + .b = "d988a3b4b5b168ed7ebe15381da5818", + .r = "fdfee673f1bde9585970c65b8", + }, + { + .a = "60ff4616bccb386ab1c8c4fd663afd554f8d8cc", + .b = "5e4e6ea5e8217e17f69c63ea07d8e93bc", + .r = "780275e6eaa0fe4bf87a78c9974", + }, + { + .a = "1ba4b71fa06394748ad36489d8a1232de12d6f0", + .b = "1da078788fa13e18814edbf15907ef930", + .r = "235f9d5de3c2a7b93122d930ad0", + }, + { + .a = "3b09f70af16cc8c40573bfffb63750b2c", + .b = "3d4c9928047325884f90888dee2d64f64dca29c", + .r = "3fc1e8665f4df4243c2062b6d0c", + }, + { + .a = "4d3079fb7639d1e7fdab98015c21c782c4c2b7878", + .b = "3dfed750b07e2be9e32d2627c31a0a1e3c8", + .r = "500cd222944614585265eb9f9e958", + }, + { + .a = "536e6614ee85be4cba997bceeacd5d87db", + .b = "48a13d2d2df5788977b9e8ecd434cba45fe3ee1b", + .r = "549a3e0100b99d244e7f85384439", + }, + { + .a = "1d83beadd7fe8d557ee9985f3d4c47b9144", + .b = "22be84a3090cce29b0b666a7cb049f9ba808cb494", + .r = "25d4b9fb71a6f79ff05eeabfbd454", + }, + { + .a = "5b5bc6dc131ab9f1f765c976c96852f5cb024d121", + .b = "4c8375dd9a13a1c7d31f2c3fc87dd070075", + .r = "5ec3c5e03869f4dd4372d274fb553", + }, + { + .a = "220220e66a4abb06681151d2a9cdf0d30a0", + .b = "26002cab182d2500064e1c19184707b9e8ba673e0", + .r = "2633ad7265ae0db8b891f4459eee0", + }, + { + .a = "1e2ff1ff6bd8bee4b18ff6fc09e2b4a82e6", + .b = "207e14815ccc0a2f5cf3903d7e2bf754356c65676", + .r = "239e193c1bc65766c6b580dcddcc2", + }, + { + .a = "26b7793830e334ac155cc8d480f2f3a6de4", + .b = "27a0ce62b6c85cd1566cdc532b5b1e322e52996cc", + .r = "297defac305c3a2f2154541ef1dc4", + }, + { + .a = "50fda952177aa819c4042847414f2d2d14e", + .b = "45255a9ae2fd394ed8b760ce3133fb71f94362a86", + .r = "56aae2037820936b47d6a9cf771fa", + }, + { + .a = "5acedf307d7016ffd7380015df422691ebbf7d97e91", + .b = "53c6266c3e6520cc40abc70370ad94e8a629d", + .r = "686ec3910fdac81085a738d1d4799d3", + }, + { + .a = "584f15ec6c7e7bfa4ba24e1780fde1511fe12", + .b = "575a78c8e8bb4f02e57efb0010d86b4a408f150fe7e", + .r = "6317a26e7ae3218b60d8ef6cfa64186", + }, + { + .a = "f617d44caf7dc67791e20feac2c1c27e655f", + .b = "11542c315141d0c46bae8863c1a945963b91b644603", + .r = "12f20af110dee02b9bbde9c9431ef47", + }, + { + .a = "54538d3df7d85581e923e44291cae3aa3a3fcd20cc5", + .b = "67eef9400e79570ce246df916892707014bbb", + .r = "6a00b7b006c767a710fdd8b7652cacd", + }, + { + .a = "1d567e0e5af1b4994bd82baf9c601d188107d", + .b = "1dae559a89e7e21212345a8148689c33da8d28f3fc9", + .r = "1f41fa99ba8e144971e741732e76cc1", + }, + { + .a = "2c3172df78361b326b2c1f83749d1b9e42672", + .b = "2ff4be223d91f31e03e07fee0c18e082f970191a41a", + .r = "3693dd9f37613c4a7de1d831f44dd26", + }, + { + .a = "32e11a127828647a88f8f7b6d48f475e8e71eda585b", + .b = "2ddf9f7e0f870347401ce5d93ff70a5a3a9cb", + .r = "3a4156da31ca81617974669400e3629", + }, + { + .a = "47f54df57b2d124be53c0c6603700e8f69829238b49", + .b = "489167e7ed18db6d541c8a94cf6a58f10836d", + .r = "5ca417bb8cb42fefd91fd832a89bdb7", + }, + { + .a = "8963a8cf862bfeda36412dea185c6984c3acf3b22204", + .b = "8035daf441d2a728b3dbded074c57e103e58ad65efaf5fe3" + "b23c", + .r = "a7cbf319f110484e28a631c8425609ed72ec", + }, + { + .a = "40f583721493abb5ead342942d9e142ce51f7251ecb6a333" + "c0888", + .b = "4cce4f3aff6019192f7e32c372c9e32385b2352d32518", + .r = "52d94814b2149c815d82619dc02750648e558", + }, + { + .a = "34a08b5c152b6bda536ab231199c5de7d8e96ad8814f3", + .b = "328d23516a0bacc130bcbb9b95965ffdd99827c49f306a6c" + "06983", + .r = "431ef899d79eb5aff9b6aa3759bca625f1317", + }, + { + .a = "4765f462b4167b25df009c3d0d710d707dc4e8a990e81", + .b = "5495c974f06f6f2cf98d285af77a76be3ef32eab77ca815b" + "a2031", + .r = "58ab78d483cc486014fb6ea972c22f7ab7b5d", + }, + { + .a = "44ad54c2afc1aeac7ec3511d847cbbee8902ec2ede784", + .b = "3cf4ddd41867fea4681efd043e079ba7788bcf66dd2694ba" + "dce1c", + .r = "495c740575ba1a56128a3a6721dc6b26fa664", + }, + { + .a = "1fa1582b89ffb94b0b97acdb1de271dbfdbc305af4513fdf" + "5b307", + .b = "27f5a44e5e13c9b5261f50a2f19f00e6a5023c0c755e5", + .r = "27f8d558c92c865c814efc3aa6a1f4d70bf73", + }, + { + .a = "591a92aedb904d763b651b2db15c965368d909b219ee607a" + "5c68c", + .b = "5b4be0a485cd99ee2d1126e62f657581da85e941e725c", + .r = "68117134ecfe0984ea313bfe818d2072186dc", + }, + { + .a = "23d0f4377e7c81b3531b876a2c277c5c60ec5db222e02", + .b = "28b7dd0cdd3dbf3d6f92099865fdda7b659264979e55a77a" + "7d9a2", + .r = "2e942c88caa87225c5a8498d87fa59dc870fa", + }, + { + .a = "44c61f3dbac478676dcbec9e9b85a1fce1822640a45c7830" + "7cca326", + .b = "4f6d3f6085a1937280761490ea12e7bfa776274e9b22dda", + .r = "58ca1394a549af73f5c95c86891f65fe0f02ce6", + }, + { + .a = "4db4b7f75bc45038ca28ac52e2f39fd546890e7b6566753f" + "65750f8", + .b = "5340542372ef34ac534d473cb2e0a5ffde3dae86c609c68", + .r = "65ac57454f6de8aa076e8754b9766f088c01598", + }, + { + .a = "5d975374b2babbc978bd336e1c3f219f1e288f2e1db9945", + .b = "4fc6275ab900f3b867af5ac9107a6605e4b7092613ae76ca" + "0caff79", + .r = "607a26e662f6a1c9bd222c7f34dab5814576bcf", + }, + { + .a = "7809cd380713c9d12f3f5700bbc69abc9a4508c400d3b6a", + .b = "7a6d99dcad253fafd6b85854588a608eb8983a6ef7f1f2cd" + "8f181a2", + .r = "7f5c9339cbbeffe9bae9e1fbcaac2b9ca73c89e", + }, + { + .a = "3d9e9943572b9a1f79ad2957b7c244a596d0ac6f1de51efc" + "9137e16", + .b = "426bbbff4bdbff38522f35096168f0edd6eb8827bdfcd92", + .r = "4aded736b377b0e75db171dbbfefdfae8d76c4a", + }, + { + .a = "37f44546e8b6837ded1179af6539491608d495d2b95d940", + .b = "39acb184673736b04fdc295ec18d4873c9e87be5291a7de0" + "66146c0", + .r = "48cd7455d2c1cfa8df085c3bbcda3db9aae91c0", + }, + { + .a = "44e3fb32ef2f76b49a2f237268b130a67a4d33fcf6b5526", + .b = "45346b4482d0967d50c829d9cd3c004ae308b257ba3e424f" + "281c142", + .r = "47ab194984b1e24a53f37d7458b0ab935bf72a6", + }, + { + .a = "583ccfde7a58547a5d4865a587f53d5bb14357ae1884ace", + .b = "672af3971a2220742816400394cf5e51d30c7e84f12c5f99" + "fc5ff6a", + .r = "73691aa5d3db4eaf50cb025db292dbf56c4655e", + }, + { + .a = "5313de0a5a6130944f256c41f1f0eb656fd0db717a910d71" + "667328c93", + .b = "523fa7f470e6662d511de7c89b98332246311c00411602c9" + "d", + .r = "63c5b2d400135796ba239bc1897c105a035cf4af1", + }, + { + .a = "6261142ad8b400e852a18dcc22ad59e799b49a441877590a" + "2b3a9c848", + .b = "540da3c401662ab7a46a45112216372f40b265bf5f29a41b" + "8", + .r = "6d6843c2bfad5aa2576615cae1dae5d89fa8dd748", + }, + { + .a = "608ca9bd26508d03ca0bd1b7298277f8f663f211a8d8f9ef" + "3", + .b = "66a32e807cd5ba8aaa27a26a6557b612410405c533e30db0" + "cd181388b", + .r = "7c082059c2fe5ec79de0cd0fdc6589bf628c34dbf", + }, + { + .a = "3c3f129b151cebc5ad541b2f055935f4b6b6d999916278d5" + "4f39de38e", + .b = "399a8dbd7959ceb3c21d040c70edc1b0b6a78979649cc87e" + "6", + .r = "3df890c79455b17a785efc18df7c4036b8d2036ce", + }, + { + .a = "a4c9bbe3961f010618e049eee287111d6ac85ed9eec95d91", + .b = "9b400dddd76cd1e856dc42e0250fa7abd9e1ca6d40406de9" + "ef6a4fdb", + .r = "ba72df9f2f039bf06d4db604f939971305056d95", + }, + { + .a = "4c877496518b9c0d55af99d7d06a06257c5a28e10f113b39" + "6bc15c3e4", + .b = "3e6fe477af388c8ac70124319f42bd92ce5544bca3ae90b2" + "c", + .r = "4edc3785759dca43fffb4143a7da85079d538bf5c", + }, + { + .a = "1a9606caa24d27f4e8886379ace27a42809d16e826628e5b" + "50b5e3672", + .b = "186dfdc633d6b265fa84e201e361465007ddc0b5ce2cdf6d" + "a", + .r = "1b58867321f49d16b1354c1788a813cc155f90c1e", + }, + { + .a = "3280c3a090a37682a1f0726730833cc826c31dc489026926" + "5", + .b = "35ae94985e20a405161cdc4901436dd36397c38fdd4a7e33" + "bae99cdef", + .r = "4192391ee1a855ec8961147e8939fe45cac80d73b", + }, + { + .a = "55cd7d3fcb430b18fafd57849074593658619b78c342a80f" + "35f", + .b = "6c002b00fbc036c3fc8e61ed14bf9dc00557be4fcd953c30" + "6220f314535", + .r = "6d6cdb2824bf090412b402523161702b44aca463751", + }, + { + .a = "5b7c45727d9663df29ccd97638ea1e5365e69737e1d2999c" + "ffe0a67e34a", + .b = "5b77539fe191d0829ebd7db19748881f4ed579662f8b3788" + "02a", + .r = "6c1d167c73f79f0a90667983c795100c81a582d7aba", + }, + { + .a = "6147dc08368c5a0de97a1935be04149805f74804c0717685" + "335", + .b = "7536275bc0c3267b7fdc41743e6419955861fc5fa9bfd466" + "0634a4fbf57", + .r = "7737a65bb5496810a9f619da5a791c8393baf33c5db", + }, + { + .a = "27828740d648ee93a505acedb32f024ac4480381a4f5b908" + "14ed67a54fe", + .b = "24e2003c3aa30c231bea1c97822dd073c29c4c530aeb2d5e" + "c66", + .r = "2a4fd1d87bc6758693cb48907b0daaab4ae3730ef9a", + }, + { + .a = "3238e873f75c5e83aab4011008be5feca52b86af433a6e72" + "68d", + .b = "2c155346f370ea6bedf6914edfd6f661c6e715fda6407b56" + "7548e0e4cb7", + .r = "3657adc3dc062f48f73ed00287b9d829a0c38eaed3b", + }, + { + .a = "639383fe0a40f99614d8e5546e51c541e303f4db310d9c88" + "657", + .b = "530a8a0bf423b328dbffa4d4576e7450ed609c096421f2a9" + "32699a2f73b", + .r = "6c8164cbaebfbfa60301953d5aa2643ba693be30469", + }, + { + .a = "6104c4f4458890e2328e437f28d4098b2a095bc350756587" + "b2a", + .b = "624a78cea710d55ed9002ee5ea2b04bf0c20e07cf07af576" + "05b0515784a", + .r = "7496a2ec992703084ce1c0612530bb24fa4fce869ca", + }, + { + .a = "21bcfd56d055ce91bf9dfeb28dbd856b8948dc6bcdf4ddad" + "c85", + .b = "21613395d1b095dbc2692e515625af73e204ca223ac29153" + "885bd953ee5", + .r = "24089f6dfee4127877db2b33b3db071fc92031cb779", + }, + { + .a = "2da7975f2ad52bd7d58b2d498890293ea0cc7e6e7194733c" + "f52ed491620782a1df1ca", + .b = "378ab3607cfa0980ee987cabdc98b365a2cafedd48860d16" + "12357d10b42", + .r = "37e537c681b6044fd268d6e53cefce7c5de4f6cf7975ab81" + "6", + }, + { + .a = "2021c9e46190f90e3c10576444aa894f248347eaaeac5b96" + "d9796824473db64d9a8f5", + .b = "1d17ba28d355234b36eb29bd3eb53caddd4e12f6144ca07e" + "54524e2a22b", + .r = "265dd940ee35b5eb0d4ab86f6cd19a4ddef731cdb8fae8b1" + "f", + }, + { + .a = "260f058e995913d6e981e740f57555e3ee86158ad4d8339f" + "06afedcad195ebda92732", + .b = "2249d97ddb467f6f63a6f76ae328cd8d34c2f3115ec4dd7c" + "01accbbe856", + .r = "2c5aca0890e94d789e13c3137a5c614284461a0081dcbe2c" + "e", + }, + { + .a = "582298f46a8c2bf26123bcb6754e71100d5c32ab6186078e" + "fd5c2490ca829be4bcd53", + .b = "6b0f201145e607d237aecf363c5758cd75261ddb034c3167" + "e3a31b38583", + .r = "6f31d80d7dcaae28f5160f13bfd6070db69a67bcbf7cf0e3" + "f", + }, + { + .a = "68d6e63cd61d4ed41693bc9e9bf5c1dfaf8a3dfeb44c8112" + "c5005c69ea94e4d5b3f0f", + .b = "69d2bc47efe097dad533f6b6700e078de4bb56bee98f3535" + "c4ba41b3f7d", + .r = "6e96f508e056eedf13eefe495a5074d9cfd51c970ac0f324" + "b", + }, + { + .a = "38f65d469da22947dfccb3fcff57132c50903f7d5f421851" + "4b4a906fa27", + .b = "35f6780af8e1935b2f26094ab97c4231cb103a7f0c1d91b5" + "2d458ac5e3ff932cf8ead", + .r = "3dc4f73d3af023d0f5cf52a1db4e0bb77fbf7d197b33c82a" + "9", + }, + { + .a = "d37bb7a5630dd5ac27a8bbe67a9e572d9adc849cba18d49a" + "46229844da5ae4915e68", + .b = "e1af2e7b007853438ec70464709355c401b6a153d3588c88" + "ad34b945b8", + .r = "10e3d1db198dc19ba1e4fe56f88772f0dd033831e6054c0a" + "8", + }, + { + .a = "cd763ea0a64c145f02c704855a79c9c3560db84138e5e3a4" + "1518be36e2acaff923e", + .b = "b866a8b952e2560bab904405b5460e7746d86f656994db40" + "072946252", + .r = "d865003bbcff5c843cb5fdeb4f5d0b20393c372fa5f4a4a", + }, + { + .a = "192d53a727cd60ffd45f517998642027212ceb1c22cf5e04" + "c86a374578e0a7ca0b025c8", + .b = "160b4e86db9e83d0b52a5419fa1507a5691ea7f53b752778" + "b98132567afd8", + .r = "1d0af6c5acad8c58a45571ee6ecdf76cf93146f4b833fa1d" + "958", + }, + { + .a = "6e72fcf18123c5fd106660b972858a9f60153e0da651e506" + "4d2dedbeb1acb", + .b = "5afe95c191b714b28933c2c4209d87c8322114863bc7633c" + "c54bb3eba70c449ab38d535", + .r = "779639703fc67cfb5b44cc447cf421864ed9297c67d3253c" + "321", + }, + { + .a = "2244b5c5cfcb3ed924dd5400e93f3ba9f3b91af3c9951350" + "947b78e2e63329e79cea9d4", + .b = "29351beb4d4d1427e1864b0c0f50a83b7ce96a99e1354fb7" + "1b1bd5a5f56fc", + .r = "293f736bb759cf96ffe993d1318f386e9825a16fef8a0ceb" + "3ec", + }, + { + .a = "5cbd24cde8f4ecc8e05edaacbfe038f7587ed23304980129" + "693ee7ba9ccb2e4c37cfe3c", + .b = "511f8aa67af7b2fbc64ba4411ce6d5cb9b5d6fc079139d29" + "2aa4b3235dff4", + .r = "5ddb2337c954a1d3f7bf64f47d6c31f31bc4aae902b91165" + "9dc", + }, + { + .a = "568e21d4ea4742f62550e06340933309c92235f91233624a" + "323ad33837e8f4df0cedeb9", + .b = "478f9166ae59494b600cb56998a6085b28c851229aeb88c3" + "43e64b4b5b78b", + .r = "5c0f58b79e8f8e5cd804cfbabb6e69d19195283d224de10d" + "aad", + }, + { + .a = "4c3188411f8916bf3bc0ae56202f7fa377f68094ff57e216" + "bf90fb61a4cd0", + .b = "3c1c9e1ab85fe9e59760317a49dd166d5bdabf5b7a17789c" + "e81ca4fea487de64c85e630", + .r = "4e3d0022f0e8936a6c364df09cfdf6114355cc757c5a1cbf" + "a50", + }, + { + .a = "11666f96a79abce41bdd2cfe3d5645340039176f66bf8f17" + "c32f76d4f57a8", + .b = "1391e654616857ab4bbf5e9bc59e6e95e1bb0466b128cfe4" + "fc56f302e9de322382266a8", + .r = "14e192315ba47c1ec563966fb4203cdce3c2198777757cfe" + "858", + }, + { + .a = "5dd52c6c3f0a8e3c69a4741c4e9e1ebe42b3491ef4748155" + "bf29001790c70aa59d114e7", + .b = "63e0213b6a9ec52cc3b17dd7bed6e0c5c65d6e309871d223" + "c692ca6adbc77", + .r = "786a2b6037ac9e417750820a5408fd854a1dd7822dfa8281" + "5c3", + }, + { + .a = "f339707d7232d30823ec944eb57f0c40994db22a6151bfdc" + "100838e0e2f15d", + .b = "e8a967992d66b599802b25c4173b71c092b9b297e4fe6f5e" + "b2be799de65ca4eda7b71b97", + .r = "f76e8c28e7c097b1151a3340e9a6f81da2736868f20106df" + "429f", + }, + { + .a = "9e768f5cbb3b3d6f7690ee66fc18b71e6e42de3e7ba7ae7d" + "1230c7ab75ae1f7035998746", + .b = "8a64e46ac9bff23d58e79f10772853bb7aadb2258642282b" + "a3faeeca2856b2", + .r = "a10ae3ba4bd787e552a47efb031d917dfe78b8a362d9b3c0" + "4236", + }, + { + .a = "6676693864c9be0b2d54f2fddb64734d49ea8608eb6c77a4" + "c95ce3d87e98a30a793bf731b", + .b = "70a9d0d8930a216d33cdd447a8f386e76b67133b657389e4" + "b94f95dfbf89d17", + .r = "742a457f57c070b0d76dc3817106351863acb689d3d8ca49" + "9e4d5", + }, + { + .a = "3d3f2333e7053685777a0a35774020f35f37c5dc10dc2f74" + "770fcf181ee58977917bfba79", + .b = "3c659ed6efa9270b17532a4da41e80e33629597b82666b9c" + "5d5f669d551378b", + .r = "433d6d9daaa8273a36fb2ec6d4c7403e2609b0ade522e44f" + "06d5b", + }, + { + .a = "26df635cda763dcb206cea154dea57bdbb0c61c207772042" + "9a0621f12a037ab1f3fc65104", + .b = "2301db7a7731c7ac7fe37451ff70e3ae589d7fd1b8e4e6ff" + "fe2300f6e8a1574", + .r = "299457348e1ae419c4d856b7208d9d3002c2179d4d36d1e9" + "52f3c", + }, + { + .a = "32e720d3ff483e0970b16a2386ae0f6853984e8c800148cf" + "e9e00454619c6b75230c1ca31", + .b = "3abaf52e682307727bcd803f699f5a74df082b8ed85cdf27" + "1498b6c144d54c3", + .r = "3d5c919f138c486f1d41adea3eecedf5e7c638a97dda3a57" + "d71d7", + }, + { + .a = "581da07e6c7da7915b98e34f3ce2df3d5038df161cbfa9a2" + "71d3c58f86dc091", + .b = "4c9ec9a853b470c8c0dd6ea8eef17135530e5e3b8802efb0" + "f8c34488f04253775bf79a29b", + .r = "588b9cebe85c4a617f1db1e85de3f7bad59ad52b99e9abca" + "25227", + }, + { + .a = "62970e919336999817be9521a615285a8db12e33160d2132" + "9eccb37bc43409d68f93799bb", + .b = "698bb6088d35165e3606663ad8bbfbc96095874aac7f1a45" + "8746b6fcd138091", + .r = "7e43151d6f44023d51e5fcb458d21118dfdb5493b4add441" + "8794f", + }, + { + .a = "4a7ecde2877df55b4a71db70a1b48d4b6b9f00148b450bd9" + "9bdcd1425dc9ac19e", + .b = "4e88b372e168f3b35abec63e3c34c6ac51c22878c6747aea" + "1605538e96415156e799576fce2", + .r = "5b47cb37e95f7ae2ee32c61c0368e5bb5902becd43fa1069" + "4b98976", + }, + { + .a = "1886913566ee6de450c1bb2df7118ae2a7a116327b6e4ead" + "bd6f9f7bb244eb0d2", + .b = "19e0bbc5cb73a10da7ec1249f1d1cecbfc0a003e55c09334" + "29293a2c93751c3ea69d8679b56", + .r = "1cc44e36e74585dcda4a6f53e39cc8b01b47928968e0d2f3" + "cf8b342", + }, + { + .a = "5f3a2c0b3c745311105cc6f6b2b460c5cc223b6111e0df12" + "9fd84b2387218b30b", + .b = "6ba00655a3417cccc7d0b64daad96efc0a5b5ea1910d280a" + "603e6af3337295a0e2315509b09", + .r = "7a836b272ddac421d45b0a25722dcee984d7cb192ddffa50" + "8b85ffd", + }, + { + .a = "63aa301030ef2eb49a2566470bccb90e1b0b7e4a7e45b149" + "4556eb47044fd13f0", + .b = "7076c5b843c90cceae07e2e5e8f08167c0f27c6226d88ede" + "0ef4a74aac509ffb109c97b76d0", + .r = "7f1726ce9ca18dde940d0da2bba31fca807fcf187d12d354" + "4780970", + }, + { + .a = "5151e338d3760bb7716028c045b7022d254d329cf2375b9e" + "c2233c6c8e6faf526", + .b = "56d9d823ecb6a7612e0a8cee927d88080b29dc95435ed411" + "0bbffa49f957e63a3586abad5aa", + .r = "67855cbdd911b1b2c5aa7aaca9a667fdf2fc2a53e71e1fc3" + "a50fa46", + }, + { + .a = "56f5e7190ab7ae84beba7746a9b27782ca7832904b330ecc" + "3954342d1be8acaf1", + .b = "5d4d9d53bbfd5a82c49c7e7c33dc0bad53dde899642bfe83" + "9056fce5260c16b1bfdeb73ba1b", + .r = "5dce8a6cc7f1100c375137bcd796e2d34f385c7aaa15267a" + "f5239c7", + }, + { + .a = "4d16c85b71f478b9cab1432b07b80db869d279923ac19638" + "b866d137fb5381fa18b6407155f", + .b = "4ef20f6226388decfc59dcaa0662c74554f170027b344c10" + "45af07d25320cca7b", + .r = "58bec748aea77048b9dfc219223c73ccaa1f32d903ac9acd" + "15e984f", + }, + { + .a = "60328dc320fdf6262a28a2cb49b8faa6fd025f60e9af3709" + "7f6d33e8d63740c9c", + .b = "5ad7495b98a54265ceb0e36c7bd1b1fbafed5d0d32790166" + "1e2b0351f88d563d1380daa3134", + .r = "6a07a2a77696240c1a4bc6626677a90fbf1210ac15b8523c" + "e058f8c", + }, + { + .a = "2ada6242bb6cc488ae781765e7946f6c7afa742fa22a10fe" + "5096a5e25d4662ca5c80f834f", + .b = "334c4a3485923bd40e7f476260a668bd2743c79c819f2328" + "18edf7e4f50da5769ecbda346329a28223341", + .r = "33f17f3a6bbcf17c181d8f7c13e74d514c98e3e628f87006" + "58cd1696e6207", + }, + { + .a = "116bcd8479b8977f3718bde35bd6fdf81812871aa2c888c7" + "9c058f423ab7d6385cd96598a", + .b = "ff4b7acaffca1ecdb159befd40177452837d1596ca45f2ad" + "fd94a4d7d24a7d8c10d52331c786fa7010e6", + .r = "150e9b0d68cf9546371739fcdfbdcfb662cd0910b65e8be9" + "743333126c866", + }, + { + .a = "31b1fff563621964f922465bbc2e6a273c65eef5aaa70692" + "fe9402ea9e34c3de978cde805", + .b = "3ce8f8d96e0dc345e2ed0268bbd0b9149eaf79be4bcdc2de" + "0ee9d4e0fbf58fb928342a69bf772fba17159", + .r = "3d74328b3406e9339af633fdb1f840d3f73ac53a333bbf4e" + "bcad4f564c1f1", + }, + { + .a = "35a452dd614fe7fee6f6cc1101b69980faac01b347a0f98e" + "d92579b0df8d9547e0dcf7a27", + .b = "3a36d5da926d5c775e4588939d740d7ffd01a37fa1157fae" + "bb43cb2e1dcda302cb0d97022865c5c43c903", + .r = "45c72930805ce0bc2f501404c897b828dd3311542d444cc9" + "aa8e4bf3f2b1f", + }, + { + .a = "54709f5da657b3cd9c53fdc481eab8a4ff55960b81032208" + "816c8ac63e83a001d84316bd0", + .b = "5547ee69224b4569a774ddff29c386e050d79f68105ce717" + "ae5554f8ae5813ef92fe4e412f746b067c830", + .r = "56ce87708173c3f347240d9188e39df8c1cbe6bad771cc84" + "abe538d73d670", + }, + { + .a = "582436c89ce1b69993d372fbb3efe56fd98ed01797075071" + "11b367bca3ed422c47731c3c754422822458d", + .b = "505f3e85baf27ffc59822432dc6be370282d2a50345d7e93" + "8295e75b01c0b8f865c74b04f", + .r = "65645b3a51e014830040c63c1bbbe4421536e910b48a3001" + "bd5f2dfb657c1", + }, + { + .a = "c21f93ac416ac68e131736c009187b9fe1066fb41c55dd0e" + "15235211ceb6124fa831099e", + .b = "c5502a7884c7dc04608aa4b3a990050517fea2c56775a128" + "be5baab5a58d05f313bbb09278918566495a", + .r = "c7c1e75e42448a1b7bfa46f18696e834e5d973e62efbd790" + "fe6d1db99dae", + }, + { + .a = "51e1ec852753ea16507229075a7e291728975425e1dad21c" + "a3ff80221fe48726d8ece58f6", + .b = "51257f27b935687b014f8140c4b59542e8fefc1bf201d11b" + "53581594c8a06f1dadd2dbf195adf798678de", + .r = "68875cab619af70abd75a89a40eecde3a1502b5430cd7938" + "aadb39c1380aa", + }, + { + .a = "5536f79100df9ae80b3fe4afdaf70b025af96430452af4da" + "547b8a620b7e1f6ddab222526d4", + .b = "6a47460921edc3de377569b670ea0a919c375314a366c652" + "bcd9abb642ae53ef3123b0db0f7b77aad66a41c", + .r = "6fcc63ea83f37c6435ecf4a205502dd4b0cf979ad62b3e9f" + "16ebaf389521f24", + }, + { + .a = "6f7df67694667235a7db91a84463615e4825e6a750704598" + "1bf8475db70d237f548326867cf", + .b = "66889dcc9881c53db1c02f741e462203dc40edb1931ca92e" + "18c29f91a36c4e50f050ba5fe4a68591feacbcd", + .r = "76fadabc9ebdaaa534887b73763f788de0bc5c2d74009bf7" + "8a59e12dc65f767", + }, + { + .a = "522c9f3d8affecc1d1a6b1f0d8dd59837d786b424811464b" + "f705accb9e371e80ff80b53efb132abcd5f7fc7", + .b = "4f2a601d7f0f802ead4383cb18fc55ddad88347cc569e73c" + "d84a7d302128e9665e903175797", + .r = "5ec7929a08be3a9c3307950b3da7a0fc91f60c574958364d" + "82718e1cbf3eb39", + }, + { + .a = "6a92d27f6ade6e00696bce4a84600e851ce06bbc5bfc51b2" + "c97b78d91d4ff7457bd4f5a002930e168ba5721", + .b = "764c31550c2fbbc8df2ff51a11116286af8613aa215fff71" + "8e30bc2f0de5daae67f61b43e19", + .r = "7810f9e35452f529dc0414cf230b4cfd9c5ef86e176cc901" + "c0f270ea79b3e4d", + }, + { + .a = "776572ff9922ee187d4e012eb4e51df04ca377b4e2362601" + "d050787b069f03053bf7fd9acc228fa1d9b1a8", + .b = "722162ef71899f03ea9c3a79f42f113c042ef1a98dd832e9" + "a09a98e7bb8a2816ca80ec2498", + .r = "7d18769900c4ee401f7e3302eb6adec095b086fbf7c14022" + "842824c8a35228", + }, + { + .a = "704a3e08400a2547bf55534a388a030ac9d578abd16d6e91" + "4afd0c206169865a938b9113fea", + .b = "705df82ca14906c33ca0274f8e1b1f298aa423c611baa0e3" + "70f3b1362803d3dc4c09546cf67b0748bf2b72a", + .r = "72f7735b6a15ba7f5be4d23a12e7408d068c5fcf2c5ce787" + "760fd3138682dee", + }, + { + .a = "3fc7a378c8cf05031a6d046377b972a1750bed9ba593570f" + "cfb8bf7f5c9d50ecf31b5eb28e4", + .b = "4db0ffa81b690182e0f3e06ef9e69026b5ce6406a896dc83" + "1889f00b84906aade207119d7652af684fa20fc", + .r = "502a09e0f389139ddf160ed6a19ac4bb710b02519a62cfa1" + "cfa55e0efb1d1f4", + }, + { + .a = "16cbb51798798f0c16a94a1fcb5e2586dd9c21af834bcbdb" + "b023b57d07834a775e20d8469f77d5f94d82bff", + .b = "1bfd911d099dab2ada4a8802cb0458c6b0595a165007f8f1" + "8e6e846358eee4b91d4ac1fbc43", + .r = "1e216f67c3a6d2621e21b8e0ca0534dbec20a1a31e2cb732" + "efca7397f9d2c6f", + }, + { + .a = "44cdb070b28fce182cb43b25333e1ccae887f4d147fa77f6" + "79c162b4b77071965b4bdccd1d74f0d33e2cbaa50", + .b = "4d9f3309128c553d5f57ec02bbba290e57c26267cdd1a5cc" + "f13fd5f03664f077ebec3bb57f810", + .r = "5b77b2a8f63255f7315f5966de10651d1715b74bb9654892" + "e5083bf49dcc611d0", + }, + { + .a = "2647edd2e11a223bca5724d6091946e25216db7931c96f06" + "177558bf7985288633e95f900b54f3fbf5ae9123f", + .b = "1fc2b218e131cad304876c1d09bf163f9612bf5afdd2bab9" + "c71be88a05be2b38f32671b5e0db7", + .r = "2759c93c8dfc827d7c2644e71ff0139650f80510807fd6ec" + "a2b1bd19e5f36ea31", + }, + { + .a = "36581909e6c39c3bf952ae81696c1419da97c9f38a3f40be" + "a497fc72a991cdc7c10343d658fe78db64340369b", + .b = "39366d8a79b046202bd9ae5472ed7e49dbfc090063844b5b" + "574d6a9b6212fd4c693dc9a59287b", + .r = "47baf308398f5c586faa74220ba8bceb406a6b29f8827fdc" + "227336b36f22e2d49", + }, + { + .a = "3417000970f156f7981b412cdac3efced457f2d0614042d0" + "c97be7cf6aad37ec2d8ce2292a467699c17b1062c", + .b = "3ff5db132200d8c379e548a6e3c934bae79fd509fc36efc9" + "3c984f71b4f2af6afe9fd94454ba4", + .r = "41f97cf95567cf25245694d8508618aca1476da358bbe1c0" + "6c543137cd864dd0c", + }, + { + .a = "6cd488c8a691a37180363f607df41cad6ff38cddbbe45cc7" + "c2f29d0267e8f05e054d01e8cb0b350679f7335d", + .b = "749e450b884827115eb77c622300f5b002c48f2257baffd5" + "c5a1060db36b7a0bf369cec39715", + .r = "89fbd91b2ced71c432be0ec4c04c9b8fe61ef9b5870e5d78" + "3a84a39d3235d481", + }, + { + .a = "2c3d1e27c27d09773ac154c62cfe94878e3218bc42d12ba3" + "572e39b33fa456442680c9ad4b1e99d189b90af20", + .b = "25d3d1bd9b2d0149e5d1811b4de4814577f0dcbdbfbffbff" + "cbd3111ac9c49995d72388f7a29e0", + .r = "2c60932e5574bef4c948b60c8b81def818ddc3efa45e4d29" + "cafc3b709aaaffae0", + }, + { + .a = "5a568e8f4c8e2ebbdf73537193b4580da661794afb37efd7" + "b25f2405956e5ce00736fbd7650f7", + .b = "4557e77035caf8429267990f443b9a7302c44e4c942721c1" + "63c90c672a42b8c1af7c0029d03f8e83a4862e843", + .r = "5a9dcffb4fcb3eb6bdb247af9f311b118eb1474aa66e4c78" + "640484b52d9a9a1fb", + }, + { + .a = "5f90593a7a231b83793a3490d425e1a1de1db8cd1fbb3a73" + "348a332138b52c2d5613efdea9dac", + .b = "5ab5021b9909a11b4e9febefbb3edfe69d4a2e0fbb4fea85" + "b57f92b2e5706d76e6b4dc1180090f6f1ce4c873c", + .r = "76b6af6e823b4ba077d790f1d01e6730d04803f4e4c62618" + "24687081619f2136c", + }, + { + .a = "f5cbf9c6e50adae62ef916b5241dff18f2dfe4704aa60d79" + "b035d2f2611d87c3e192ea93926fcf", + .b = "12cf1ce2298ba5f7c4e11873a42485a6db8a876ea27b5c3e" + "d92d8f423e67dc52158926928a5e28b7e13fc526d25", + .r = "13be9d4ad29c676ff96078bd4093ac49d512f532844d6493" + "126ad6dbba8e690b649", + }, + { + .a = "1fa5d509f556a4c587c709fb49adf1b24817fc3301652167" + "89510894bb26993f99fe800882c20dc", + .b = "1c97ce542d64bb2b0c0666783b50ad7b0ec83dd585326a2e" + "edb287ed08900414ad5a35303da5548ef7874e1b784", + .r = "219df42a796f67ba3fb54c4a95aeee52cf50e912cc90fcd5" + "7727d9bb278771ceee4", + }, + { + .a = "3f79506e9a18ecfc96ecf82ae0e88b3c61b6afc8919df51c" + "e958d3e8956f3be1d9f44cbcf53f92c", + .b = "3ffa55470d667fa61719bb07cab29e9e78748401bb248825" + "50d32d71a37def452f2ee24a5878decbbba036f5b74", + .r = "433ee870e398a7045a26803592d99e9f3f7d0bc931ee7a5f" + "7e5bd81d671899d74ec", + }, + { + .a = "1e88e5e1b5ac07c2e1868026dc8b58fd14c17338e19f0b7c" + "b42ec3af35eb01ed9a69d588beead9ee8bfad6fd702", + .b = "222adfc3c1ba3ab465a187e4861a963813657e04bdc8fcb1" + "d72419645621975d43ea7d508b0416e", + .r = "26718380c83c5b4c29dacacaea851056054770896fc8373d" + "c088e14c64224d6876a", + }, + { + .a = "6f53e0a1787a708e47bc9fe83d695a32b97d60927970a6d3" + "e0c7c7940ea7104fdad2c2b2a345fc2", + .b = "6998951fc97fa4ce0d4e038f51031bb412560291e5391204" + "3eb3cb05971620915f8e896b4b82a7209506248e60a", + .r = "759797a7335f9f0be50246d2906c3fd300c921b3ae21d133" + "c81caabdd16b41a0c56", + }, + { + .a = "404df924bab9c9eb6c43df3712bf251d44ab49dd0da0d809" + "7225ca0afde0e63ae8e3c5c9c38d168", + .b = "42d9ad894a69a138d23ad400e70876d3189f993c06c3b722" + "f0fc175cfaf2a53d11da39162822f3d0bd2deb096e8", + .r = "489d13795e291c9dd3aad13c3cbb2137c6d1cdc696128f62" + "58e41563b61c4b636a8", + }, + { + .a = "11fdc2eaf5a0227b9a6bae285f8d057036b972c5b46dc13c" + "9982982d35c608e37e6d4e6b23572beb1e0c6ca86f8", + .b = "112f78a73b732aa0e65be6a8075f531fc176986eaf4f4aaa" + "f51a1532490cdbbde1f6ff7ca1c68d8", + .r = "15f0d4c054ad88f5ee39c62f53de3efd922bf821cd0fd469" + "08d421218b6d4760758", + }, + { + .a = "48f25eb7d347227114488ff751f9fd907b80fb8370ff95a2" + "f4e20ed1f8587f0bfc6e433d1368e17", + .b = "45268786ce924277c48ccf87bcbcccaf6a9abbac4055e612" + "827d30499ba9acfd5f41f3c3e9b1831d0bf65074e83", + .r = "4d224af8f3dd16f8c916c1c871e6063cb619f0accc7aa03c" + "d6f4874857794f87ec7", + }, + { + .a = "230dde83b7195646b37ec13da3f9be4befc86492d2d65a1d" + "134245c2740f4dba0d9b22d79b0300ba00a8953", + .b = "1e00b351da3fc2d7a92a3863d606d963873e0b42e9323f53" + "76768b00d1f73c5c432e60f08a1188fe2063bb5094bc8ef3" + "4a731", + .r = "25d3f691c07a8bf2fe4ca889e6398e569210af5908aa6e09" + "3c67163703ad224522114e56d", + }, + { + .a = "589f46b0dbff1eba912f1936684b26de8014c18685e9d74f" + "30bd31eedce3538bf414ee7bce19d883e84d5a1", + .b = "5e3bf15c8c82e6e92d77c169868e8b89ecf812291c25ce7c" + "8615f1c035a1a0a6787f8c777147b6561df511da82a8e8fd" + "441a3", + .r = "68c76daa2e2a401874ebf9b82566b969132ca2fcba086df4" + "87a555e3e26d05d9cd1841a03", + }, + { + .a = "3649851b4ba0c637119aa5c53309bf937829973e54da5dad" + "11258fd1ef9deedfac65911552e50e6aa0edce2f1389f491" + "d9e29", + .b = "34723bb44b3b993ceab03d15e6c1c1fe2be151ac95d66459" + "5758768ffd10186b984604fe8f182b4bebce953", + .r = "38593265e78e78b00ab40b01c619c3a0701202e697de1097" + "c0ef93170e07e53aba19ca851", + }, + { + .a = "2940099c4bc4ff3479aa4b3545359c165edf212e215c2310" + "9b7f031ce69760df577d931600ed8737c143ba1", + .b = "307560f1adcf4265d9b3e924ac729fbe695e27162e965d8e" + "0902655a051941f9809c2087437e5ad813a828fe103d5d60" + "ba77d", + .r = "33ccad14f748edceb7c1cbdec84dbe3ae3353edcd0d61c7b" + "bd535e599d9600bfc530843f3", + }, + { + .a = "3cde94be664c6c5ca7d8739597cc53ee554247e8f5e73b3a" + "27b3b4b33ba65983e725e59924e32ed4f5f1bb4", + .b = "3d1e0b1f767fbcbd39110747bfe209deed805708b2225dd1" + "edec2db9376bea0943fe924a3ff70399c7cbac034f35befd" + "5f404", + .r = "3ef6117751b78060f043af98185626b9aebbc0f8b1d035ed" + "acffc6020ad6a172ad8f85dcc", + }, + { + .a = "2eb2d4011022e0d082870fda04ab4fd39007f0dd808a8d48" + "46a9ee2903922cfd8c35b8fcf764d4491fa40e4", + .b = "27418e94127081dbebcbb9e8a374b1421f0b9440a8977344" + "7ef4544b15d5466157800e66a9564f91a27a60c3e10163dd" + "dae3c", + .r = "30e1241abff04618884278256ae3f007bce514a250c9f2ec" + "a8276f8519afeca70d2d8e8dc", + }, + { + .a = "42c5f83c6dfcd0292baefe5061f9c4350c00bafa02959afe" + "b830f1528202b87f38a308ef95c9d2ec1a7126d", + .b = "45993bc7165341ad65abf6600542ed3a592798b31e0631ba" + "cf8fd3ee0bda613f218bb8a917fea9608b703a01b766724f" + "f697f", + .r = "58608cfcecaec3e088210fdf6c1e6f1bf7b746dcdbe47002" + "8e3fb73f7baeb2b031865ff39", + }, + { + .a = "3d900881a88aae0e937ec4ab473b40878b12ea9b3075e864" + "87ff592e4188fab6e34878c98f38c08a0891647", + .b = "3b6d97698c50aa9a1293065aaa2ede7a25cdf961a79117ce" + "177cac2aca1aaff004283dde652cd5fd84eff17dfa965e35" + "30f7b", + .r = "4ed4240327bdfef5fc636fa2bdb399e82e1d1023c501b37d" + "f5ca6e2eaaaa81232b01cf399", + }, + { + .a = "2de3dd6f988b7ad5331d43660f258a899beedb5637501149" + "6bfca53ea72a73b4751ce4dc1cca0dd7e27da7c8e3575842" + "8b08c98", + .b = "309535207f6f72e75fef6cc5701d9279aa2f23a9d9146dbe" + "871164f3dbeeffaec516366685259cf2843938ba8", + .r = "340aa5245babbe936447907ed363da1760c2ed50ec15e860" + "afd003f2207461ca4d345445948", + }, + { + .a = "378d58d4e50373da3dc5cfa9406655ddce1f30c04c8fbce2" + "4a22e827268bc301b5aff83f47bad460ee99595ef", + .b = "3b84d43deacfdf9a69a139b549a72dd330ab25b640637d89" + "02e8d41c8912c0c1a2cf8f443374daab97f2798beec8a54b" + "756b569", + .r = "436a5604f9425acffa4c56c50ac01124560a03e4431015ac" + "985ec89391c5a766a3bdbf7396b", + }, + { + .a = "2e2be92a674b64271ba77a8ceef636947c06c8e043dbbba6" + "419aa89d72b5b0c3c8fcf0e297cb1d89b48a28afbe81249a" + "ee5e45c", + .b = "324369fc279d52cf53b932597f686ce898d05e486757d6cd" + "c56db2400656450c3710a909cb6c9a244b5ccde3c", + .r = "3818db349fa3908706c1d601b7b8af9d0bcc0cb2e59bc2ae" + "160bb678c151d0d0169db45d6ec", + }, + { + .a = "3cf8d75fa4dff25e8d3ae92b8fe1268ae29d7dc6796e8edf" + "4168d084e172eb066c0672678de975dc8f266efbee1fe284" + "2eda24", + .b = "363be447b5dcd69f18a23cddb887413c538e2ca983b47dad" + "40968ac80fca6befc4659464d14a34321da9078c", + .r = "46e81c9549394650f06cb651ea66d9e343711fa23e51142d" + "e1c84b376c75a6d08bddffa234", + }, + { + .a = "5dcb41c0c32ce8b01ee1c09a48ec6c03139a109f1de3a99d" + "d5cd9c72cedef58f9d83c2a1efe2853fc991282637dece62" + "970cf26", + .b = "74f3a69b820d910ed7c0e47d0fdfb74b27990df6502e27eb" + "f7dd95368748b11012e92aca10c5b927df0e489f2", + .r = "7bdcd8ca6c2ebfb0312b400d328e77b99a5423a7447c420e" + "5b359640ed3d3a31251ea7f4b0a", + }, + { + .a = "19cd8b4aa083fbdd52c5e36278cf791308d40acacf5ad1bb" + "e362f125129d6471ce98fab1a73b8c155f76067c0", + .b = "1600d7a5562574c7b3992703e469b4d2c57f3b49dbddea56" + "c4087949baf82f3016423ff4deacdda9ddabd0b7ae65071c" + "990a540", + .r = "1d4cab55e0d93ef827953dacfbe3135ac9500f5b41d559ed" + "0cd10af09d955255e9a0ee6cdc0", + }, + { + .a = "1521d207a6110cf889bd3bf2288204e532edd789c0087e28" + "d11f1f0c2cf4281a1604c2e5c48cf0b3878047f7b", + .b = "11e2602fff3cd4b12e1df2edd9c13aacec71fa1c1258b58b" + "8f21ee736ce29d639ba63c7efe76c0043f8f8759ee9b9d40" + "c6d8293", + .r = "1696a702010efbcbe0f8428337ab4d8392cee906db9ef465" + "f860ffa079afd87a009118cf98f", + }, + { + .a = "1ba61782c3046b89565645b83fa16aafa8dfadffc1c39f99" + "bafe55ebd529b6e46cfe0bb1120b46b58e89f015a", + .b = "1bea4aa3c29b7c7266d543da0337040df47b0e97555cd08b" + "d79ec07c346b71814cfa3af0c8ab6e5d2877353657961e78" + "20c2a5e", + .r = "1e83c86d8156cd04087fcc693ea652114a035261f4298204" + "d7c6764ae538ae99edd7586fe56", + }, + { + .a = "3ecf496e4292b75f9a9670880538645345bf502e1a5bc2c8" + "9328b16944216d0a0e66c65b5192f4432c630af3bfe", + .b = "46951e3e9c58c1a91b9b75d56c33bb511da5e4872c995ef9" + "949455cca8e7af6e3f58d5319218249718aaf871de538f67" + "bbe50dcd2", + .r = "4d04a92c6bb39ee24669385a7264209b2f471f2b6b81bc4e" + "1cbf1b4cfd7f633c8e51846a4ef26", + }, + { + .a = "b37e192b94f62fbbd90ea281a2fd8fc59402b6a15b22395c" + "cf26b94089e19257750d6f0aad5ce89311dc88c6676989ef" + "c51e6b5d", + .b = "aca73bf07977f19b5ab808cdab73702ade57811031783532" + "1b4e3a5e114374004aa903360b9b8811ed1c384be5", + .r = "c561207d0c56ad8c6a62a5718d66fbeb819fd3f53b69bad7" + "6d2ce4f793a04ef167c5bf7fd743", + }, + { + .a = "5209152a97476e27655f662b192bced6a6378a399de7838f" + "8e2619ae5b5e32b627042058245ecc2968cd55a26916d9b3" + "801481ab9", + .b = "5d72f984a9382edf6aec318ce694dfb517cf9fb3594fedc9" + "8b0f817c607285a5dae2a102d2dcc1eee0bedc586fb", + .r = "62b0bad8348883fda93d1d871656e88a150078fdb6855e78" + "08cec104a068d5d478e62af058e77", + }, + { + .a = "54d02589d4c0f2d1f19e5dbe19426ce8f10c3718f20d084b" + "b2b218d30dffc03cf774d5dcb1ba3cec4c7969dc5c6", + .b = "61a0bf4ac88d4cb5f1171a705d4d7998d128e203c9c6debe" + "9e0195f0a76b095378bbef1aaa61227df204299f9218a20a" + "4478f45ea", + .r = "6ca36fa2cad2b8b0fe8f96af99809b33ccec45e9d52a1374" + "6ce61eeac0cee3b92420862f9054e", + }, + { + .a = "59fbb5e77ac4c6939f506a3d2b88561c7d857072cf0254ae" + "03f3f3b7580d79f44563f1107d32fdb316b649ae19c", + .b = "5308f555030dfe2a2d3acc43b8a0f76fcc3adf883f41e73c" + "b0d22384bf1da72d0b610f2f26ad369d3528047a6118210c" + "7564bd2fc", + .r = "5a9be472cc242465acd0fd46542ff8a8ca1a0d57215d97b9" + "d347095bb0d6b307e98c59195bcac", + }, + { + .a = "13c6df0db0cad2e785a62a999c9207722733730694a6c277" + "04f97a23dda58d54afda7e039254c1ad64c3d4e8d18b2326" + "83441fc85", + .b = "1154aaa622140d190c33b5d6c543a78e532665581bb3a3d2" + "c4629bdf86acb532ada4c5f70979dba6471dd6d4ab3", + .r = "16712b107ba923b96e99ec357f4a4b21bb9ac59b10e7af22" + "81fb523eb258972737b8a3ddda541", + }, + { + .a = "ad2ec769ec95442a5822b2ea7fb629f33e3599d319428362" + "2016ac11cacc2757b9c4f4c598fb5c460bddcef5f0f6cb0c" + "a891dbf4", + .b = "a7c23207484b51c7fd1f29115dbac4e645d5fa19dbf57d70" + "65d42e073cb2027cb63c3ffaa68c4c6e7c648a0144", + .r = "d3da58210ecd163b976b24fde2c9f082797d0d48942d35c6" + "ed6a1e964cd01e923833830678c4", + }, + { + .a = "3389e7430497fbfd7cac8430d84669cb672f888da04a0f68" + "81d74b5e15a29533670b077f2853edabe588b7fa63cb8d14" + "1416691c5", + .b = "3ba8383dfa55b8f94a8a1672dfedb3d353b4f4d589b1134e" + "bd9ae57b8eb780c5bfbcf911a04949dc498cb2082a1", + .r = "3bd105eac1dc90b428c864fc6ee986e7cd881a9461f11bd2" + "d1e89b831f9029c97d185c660e565", + }, + { + .a = "68937566f61f83d4be7315ff349e2c3db46247c7534b82ef" + "edb3ff280f01be3240a21bd043bacadc83a6e9fb34ca3941" + "bb2b643bb81", + .b = "657f9bc80e5d7a8749637a9ffae10b1378b7531779fb245c" + "92dad2253102a61408d3bb952c87774157e155b6fd9b3", + .r = "698a96710f17107988c87ba2ebb9f968dad998ff44545043" + "0e1ae0db1f35f1652ca51b174f9afad", + }, + { + .a = "806e21a6018f6902c32b5ac321abd7a9cf3871165926037b" + "b70bb13ecdb601fec01431e17341ab539f2b074468f10e4d" + "f19688267c", + .b = "973640b2656ab402878f1d7d910d1c65a4bbf0243deb0a22" + "c5e3b5c49ceebda794c2e2efbbd43f73bb264301e44c", + .r = "a191a837fb16e2706612fc2329b522d1d708e95e3e2ba43c" + "8b17a6c83987029e496582e5dc024c", + }, + { + .a = "4bfe6d14d02adbdece3c22192db04c62a7e6928590d4f4c0" + "a214c35b5c51c094fcea85ad161c0cf6ce9b641645fd4", + .b = "4f4e3b6003407e08520742559cafb7589e94fa8f2e5d22ad" + "def829a1a4313fda088baa948df6adcbbd1d9458e5fbe4ee" + "8c7f4d974f4", + .r = "5b668aa84bc05a492e9fe10afd275844a5197f828dcb50fe" + "9eadf68ec180b2ee10319fc58d4447c", + }, + { + .a = "16282008f340c333d130e2f7784183fb78546a5c0371c704" + "25387c03849b26f351843868865be89ee6820fa936285", + .b = "1606d544d1376ac311019aa10888a8c67bb518f0008e4fea" + "56fa823fcdd9489475cf1c013adb41fa5bb3e913b24cd780" + "b8f22c0b2e1", + .r = "177f836eb1cbf73e066e460bad118c201af32b042be78aa3" + "98ecbb87e0710976726bf2767a1d5c3", + }, + { + .a = "715a6da986222027f63d756ccef34905d458b4ca7ab5fc15" + "049a1aeb234874f104529c6f9a06969a27cd2f7210fff67e" + "a1ccd75f7ee", + .b = "7282278d0877ee30b1f0a0bb2654f57cd0e699fdd9cb3ff5" + "9dd5f1e5e006989c179d55b5f05d6b36729eae3b1e18e", + .r = "7c392f13a9f95cf9e2f70153c9dadf3d48394670ba5ae281" + "73bbf89c16de3234e99d33d08ffc70e", + }, + { + .a = "f1bc46ce609cdf7a7c97bd840b9b224869cec121e65a74ed" + "818a8954da8b40c694bae85a1c16111c47e7d82b0106", + .b = "fb75c11e8dee621c2ae2452251bf8d517c05d54d36e87f1f" + "5230a1c4d22a87836c1f048d5f4a334e7ddd03e4df206bf7" + "64649bdc96", + .r = "128da5ef0333c0d1efee31eb0a0c6816df7ef64565fa795e" + "c1a355d6cc4ba707787b5faa67674ce", + }, + { + .a = "5be40b81712d5af8f166e965433656616dc88505dae1c99c" + "f6251c40ffaa726cab994f3f2a6f8c9d885a48a48b45241e" + "4ec158130f6", + .b = "5017c43fe300730ec66d150aae46ac1ed96136a79fdc493b" + "9333c73a0292cac1454966ed522dd4ad175b7af495fea", + .r = "65ec987fb27319bc814c28c2f38e8d84ea0d8caa7e7bddee" + "887664442c04a6c68cd72777d68761a", + }, + { + .a = "24e090e514260628e7006fe8ef6982dcde7b6641ed26650d" + "67fe928111bb02f7e7d7894dafd79d23dcc761e1cdaf1e55" + "04c6bff620b", + .b = "222d8a56ba7bf5a83b835705d81ed5583f7066a36155b3d7" + "0cbe9e71aff38b31ed74a3cea2ea3e26129f5c7ec4d39", + .r = "27c9ee26d3cb8aa69095d665e1d14beadffd7902ffa7870e" + "025c24fe8e1a5a8d5cc68d27a3f2a8d", + }, + { + .a = "61405295402dd8b00e25700dfacf55b743e601814262c84d" + "e0798206b1802e8d491d5a02537aeb1def33efd9106918d1" + "eced5", + .b = "6626c83bcea1940abf7aece1d543b9172da120438bd315b3" + "5fce702d4cf40ceaad6c5a37b6d5831f0041f03cba63b1e9" + "aec522acec80dab7ab735", + .r = "6c40ce2b24791b71a8514e9ff5d974186a4050b08456d03a" + "58d71c1976920487b813752b193641dcac0c7", + }, + { + .a = "5e46d5de23e7c2a600290201d033e698d1d55eea4e67e465" + "f6ef83091c696554b9871fbaaf93a166c96224be5d0e79ce" + "75601d43cbe6e19f6684d", + .b = "663d6b9033445b119e8a40f2589ae93c5642726461cab0a7" + "72fea02072bdb4139a73a2b48bb1a72bb390248e6aad95ce" + "a8ad3", + .r = "78b05f955b7d0909b24486705188e732a6b3261bd0d90b45" + "968e3fa1e3316dbbed97e86e2cceb34d8742f", + }, + { + .a = "7c27f13e17b58dbdd5eaf0def441960a365cc6a92b3c2169" + "c59c15f3028f232587112c89c0464b31fc0bf61a497450f1" + "fd977", + .b = "69d9a1bbfb7804f4ecc322b26e77e14466e3d474c09022b8" + "a28c934319344858ebd6ad300737ba51feaa0f100bdb7f24" + "a06023471aaa3f095daf1", + .r = "7cc662a8353de4828ea513b11e28b093ae2dead59e1cef76" + "c99fc112980d723bac561364940efd64d4105", + }, + { + .a = "3c43ed3c6f93afdf6ebaf31befb5399d686eb0964e77494d" + "2039c68582f3cc1f8fb401217f18b60fc5119594fb0f82a7" + "c1cb38c2c35bd092737d0", + .b = "3787da5390f2c638eb5b4ac61d2885d79d087d377fb6b249" + "28d8b4f1e1b4e46f0665627422091dc0fc8205e6a445ee9a" + "c7cf0", + .r = "4611f3c04c5a9a21bcf07704efd6e217cb1d030109a7caab" + "7e51cd12927b59b0f0c00b603b0f5e30e42d0", + }, + { + .a = "26c430b726deba75855f8756fbdc3f66253d7c434a90d788" + "b73101aee9adced0fa265d906eb776337d9357eded1e31c5" + "afb61c8dbaf1235d917dd", + .b = "227295b37eaca84adb6fe12af22af018c5a70887707fa808" + "54344cd39cb0ae8d8f1b70ef8c29e6e38f2cfa637233109a" + "bfc65", + .r = "28f99f06a87e410dda5fb6f4c63d02a0009df2c8e0086fcf" + "5f0b63d24e1722964fa7ed778b93e3599c44f", + }, + { + .a = "28b7a4eeb8f949472ccbd81afbf5967c68b4404d78744a66" + "41eeb49656f0c5658fed789f3e911c5bfe40a398a8776ed6" + "a788cfdcd50e12deb8113", + .b = "2879837a5b56ba4e56812fd7b586cb43b28f279fefc3a0dd" + "d6968d9272500e44ca3abff4d2a73a843c786264b510c2e5" + "ce6d7", + .r = "2a37b7efe69d1fa03018413a39fc11da6212d5a2b312f88c" + "702a6c0fb913944ad63e2aec38fb97cab11fd", + }, + { + .a = "6ab9c198e86120643261db28c3b4bafec69938f7b4be4be1" + "dd7a4558b7b891ce8b6cdbb8efbe2574516ba730c510548d" + "8c99628efeb8a2031abeb", + .b = "6cf468976da9cf19b0ed4b90fc5648f676c62b1c29ac2095" + "0575ed8c6ebaeb2cdb3c66acf1b50a4c62097eb861defbbb" + "60cad", + .r = "75a486b9ff6c5e6d027ae67a70c3f25c01fc7e0a826aeeb8" + "d77013ac33b43e9991a0a07db6df09396eac7", + }, + { + .a = "66773cc79a73512979d0c797d5450eca79039239c0048e29" + "97f127c1a9140401eb790fa93c2459dab8c8741efe0f0b05" + "3116dbc4f19b3ea394513", + .b = "667303ba154d16bd6d221e5f2af88584c8ec971cc5d3cfe4" + "a815ebeea56d00efd0c793c21b2cf9a9b7f37ed2fa1e3926" + "7593d", + .r = "68b8c5e600e1d87cf63cc326855ed9b4263b2be793d00b31" + "2b1a0b224a04b4d354d0e27ad7a6322f267c5", + }, + { + .a = "b69c2f59854f1b7d9f48a5de97bcdd5ffb2d567345afcfc9" + "64c81abfdfccaa46d0332643487aa5bca28f4afa703886af" + "0cc3c4", + .b = "e82f0af1d64112f342bbf28a9fa9a7a8746e98d01d777b88" + "90857d23f3d68c6762478b77105ffe142be97d8a6d7975b9" + "3e95b2960916b27eebc63c", + .r = "ee9ed664275dfb3490e1c5b4212865380c1529098e615a18" + "592970a533ca75b58a5f7e99450d568cf6d56c", + }, + { + .a = "2f031d9878d58ef04fa42f3db553f38c6d13ad4f2acb5666" + "52e938cde96707fe12dab205fe2f0e7fd90eb8dc0db7ca34" + "8e1ecac", + .b = "2562b63f3618a28f06036e276a3a0b51f740c6c4ccc62358" + "0b332529e3c886a56d74dc88213afc34f2631e5a13b2fddd" + "38318ab4f5033df22d7a9dc", + .r = "3165477e4299482810038cda9e697de73399dcd3b266c5d0" + "4781c4b56bf7d6b21ca6b3c4549b47716945fbc", + }, + { + .a = "4099c54116dc69711a515cea21910dc0ade5f71bc3cbbcb8" + "722596882216ca77b1305babc60c0506e39ecabc92b4da82" + "b1c7739", + .b = "46b308f71f4e280ea802ee3235cefab5abdd7c4539943290" + "4868f866958ddefe7e7935d3a67480e7c112da217a23f827" + "c9b46d923f47e52c51d2071", + .r = "4930122b2e74cfeeaf98f311b02cb6b7d74d2c2cbb957cf7" + "194be2c3f5dd616464afd4278b18210fa862117", + }, + { + .a = "2eba58133e1905b0c3e3d1f38a050722bed713fee446e1f7" + "8a5d5b34ed3eb1dfd5890a8e9cfbe6f3431ba3ef82d593b9" + "da631d52c1f58c41f2a02f", + .b = "30d19a2230add9ef8636858843cac35ad81346e14c737468" + "de5c9235eacc9c73ae7cb19cac6c3c5e0f873b3776451623" + "dcc83b", + .r = "3a4b375620193c4b9f9ffedf3936a038b68bee38723a9591" + "671e6dc252921ab32ef4eabcbe1d5e98952609", + }, + { + .a = "62d3eeed739586b307d520aa66fdf31627b2b06dd2707a62" + "7400bd1f2db8b6e780c3ea9f26007fc632e0b2eb084f0b87" + "e5c1c0077a854d7f409ad7e", + .b = "669360d5bdd658d566543fe18895b0d7f454c8a02c394b03" + "a1d9b2b003f6ac2d2d4528297ac68608ff2f4a63cb349281" + "946e9f6", + .r = "6fd213d3646cf9a5129db36182a84778ffacfab2d66c71b3" + "f4b005ea09340d7598046deb3706b4d8d528966", + }, + { + .a = "347888d60a33f8b61f9bb2007532aa1eb744e2c2a84ecf97" + "c295c4137ea532e6e672e14287055c936325a1e7542b81f0" + "57c700f", + .b = "38cb5516f2b444d95a339f89acb2cf464868279b43e8bbee" + "bf91ae3c3c87b745756f2ad7fd8b77c20225fe52b67bd952" + "f7e6c3902d3b95673114dbb", + .r = "4510be2431127d541a3eff0dae5dcde6f1e63013ba108f9c" + "5a0692c24e34edf4dcd9620fe7a65c4a26e2ef7", + }, + { + .a = "45e85d18e8d7c1aa45704b4c2058bb1614dc1d3fb8340f69" + "806522d93702813241e6da3294f7ae7409983383382a7bea" + "65fabe0", + .b = "538d2e8074c2edf23f519974b2864cafb3eee403d6836f2c" + "b867cb5aaafd0c1347ad0eee407b681dd442d554e018d4df" + "1202bf831be7b887f1961a0", + .r = "56bcbfa2a82c68699f85d0b9045e6309274412af1bf9e93f" + "f3b911dc96038c7628bf877b6a77dee23c0a1a0", + }, + { + .a = "1288316274aacc19f984426f79563260201a93817228c304" + "7b1af465bd63bd2d28e0b0cfabbd593d18263e57c1a1d5a8" + "7fb9c7d97a8f42d7c3648", + .b = "10941ef14a7e6a5a46ed981831c20dee4d585eacf824aaab" + "98992437669dc86627a78dd1d820cc473d510525844948f1" + "c9098", + .r = "14f78f752730b6f05aee516ee5a9e8c8066752b68f1e2359" + "e188bb1f5fa30b818654385cfde2b6cdeb678", + }, + { + .a = "280357b80157b056a9f93236ea4a96b0a30180678dab7e29" + "042855b83c6900334df17b9d756c37b0862661fc311c9386" + "731c9be4be8c7c83582ff6bba", + .b = "240ea2a02538bb8d07c1c7dda2b441666ff44de744a61795" + "59c66aa4795ffbd4160d90c8bd5856f112ba55ce1b619e08" + "ee26b5f26", + .r = "2fba59e8f3c862b295846bbd2ee0faf2d8d18f0223b7cd06" + "71ffbeab03b49418e4ea97b55e4164e51ec5f8ada", + }, + { + .a = "93e0f8a84c728310c6b64841da981c57dac26291708cd338" + "bdf55a8188474b6fd791b5f26088c9ad56286523f4ba86cb" + "81bdbc2", + .b = "834da9c3dcd0642656ae7661b7c56de481e5b7ba1e78c276" + "907e2681a7c35fc4d381b429903c7315e850573f1aa03529" + "7492b0d7da203b3dd5b6076", + .r = "ac42f47f1b241a5a237960708e9ca24df3c74c7d792031c2" + "d7f0c557ad3bb8228319397c7f90457bac284da", + }, + { + .a = "9dcb088cffb10531ddf0211f9127b767bed3d7cd56db782d" + "9d99f775b0aa5a12bcdb34f9de21acd8dfdeab663ce3b113" + "834508f3529c0e4c33d94c19", + .b = "b044e928a4fbf8635c92585f0b97d2dc37b2958d1802a94e" + "1018785a5c10df530e039792f82b8c05c96552914fb0e74e" + "58f9f525", + .r = "b7c22f0b01fcf7e8b6e6231b3d9470dbbabc2d531f6ded3a" + "4d20deb5821a54a7fabdb5b16a0f793037aad2e3", + }, + { + .a = "2c73e3861c90dce2a7d933f2060f84850429d00c01c514c5" + "63505886a2b11a4c4ac2b63825f29d814ca1e6f4afa41e4c" + "cae9aa407", + .b = "288531d5b6595048d0e7b770ea6cf9c26786a3aeb7a1b5f0" + "307030acf9317edd73120816386c46a9f9b91f7c6aec1d68" + "5f72c962570187b34c40f8a53", + .r = "2ccbbbad78953dafe4777123a005bb92757bf250e00abd52" + "3724fdbd51fe3b5d14c596e281b8a0745648f2857", + }, + { + .a = "4999e088dcea64cbf4cba439295ed028c001ee0b3be03232" + "61d01e1d59570a9ec5c5611f5778a8f47c9930bfc6bd2ec1" + "5a05746d0", + .b = "487ff683437e448efae77e8a5bc621807e0a832b854bd7a6" + "68517b8d217bfa8b0996d6769a94578c09d3e27263512f27" + "5ce5ec27cce7653407e95d230", + .r = "4ab76065639776a1253bdba9ec37341444641ed9a1336a71" + "b4292d257b8436e6ae3f44967966b3bb41a4b8a50", + }, + { + .a = "53177f79018ed47528ec38153be5e8c6e90039b7cde42f7f" + "0126ce89feb93e11fe09861687dd73b537639034ca5561fa" + "454faf0cb8e80c8eca7c4ded7", + .b = "58be4ef81a47d47f6642037ee4e405f01d7c9ae87a05c493" + "64797d99c1ebfca8454e219ec7b388c9b969d14db722bf94" + "7e125132f", + .r = "5b294290e7c727163911d40aeae5d9f1fb482e4b8df31b55" + "19d77d6db35f1b79458f219c5fc87d7267d192077", + }, + { + .a = "1add9825d173a9f85180570eb176be0cc1854e34ac4396fb" + "8342b4f6da67830e9a636ba89534dbb50150bab457492bd5" + "40ba103e", + .b = "18d51b9dccc09ed1a938915e0662b23c78ba1f9dbe4f2585" + "8c7d395cd4147c0a4d229a05655b7d81f325371f10aa1b93" + "f48adbe09dbe0598fa7da896", + .r = "203fd7241aa0e48302d55a51df04c84d84330e3652e6b39e" + "9ffa7bdab9cd999e7ad1e0e454d191c8595848f6", + }, + { + .a = "547d4291bcbeb5f4a506357ffc3a962d5d0326eb39ca3e7c" + "6e3bd08384a83b53cda4ceb000f4d8001713e6111265a38a" + "3164575cb", + .b = "46b880b9775b5eac3b4af101d290d229a9495ef51f08d47d" + "643e5258bebd9400d02ae7686395066a9130e1d2b98b4a1f" + "383e8e863a108bd90f6083a07", + .r = "55ac2d896546247e799293383cbe526c07ec1132c5007de6" + "8ef8def59325b7d6aaed8b05c806bffc128ae9fa5", + }, + { + .a = "478d00c0c26851533fa5fb00e1d663f4db0d9a96c20957d6" + "1d412edff90f713f37347b4692f280c01c2b8862505d0660" + "1abc1600ef4", + .b = "4545034b956ee4aae5f482a37749aca3c85f81c4069f8e16" + "f268de62136bda95f1a3aefc7fa6919a237eba53fd86a084" + "d4b2eaf747a9c3d619a0071b25c", + .r = "50397d24f801f90f08afbc36b8a736928acb83a89fdac71b" + "5f12c6318792c2e5c9578033e1c7134f2cf2c166d24", + }, + { + .a = "31e346bb41fbc4a426d1df66e980dc34bcdece632cd64f8d" + "fe8b5e834cc7c2b786426c8a420610f2c22739601ae91dd4" + "5f138a7cee8", + .b = "3004245c6132c6a83102b859144076b36d99dc67fd58175e" + "1af03088a47c2fb72f87a4f0d70085bac3c1e6635915ddd8" + "30fa74a57448739813212522538", + .r = "32d0eb3acf9f2656ec77db54badd51ea28ca120078e69f85" + "ae2896b410a2fc0fad95077ee3cdf1efbf891c894e8", + }, + { + .a = "1ccdd16940b590eb23ff82c5f9f6d57a621f34eb3236f803" + "c095124b7da573c6e289dbbb662e93649a5dfc8d6dc98fae" + "c46e02856ebdef3b31eadca55a0", + .b = "1ae5fd16b2b322ca4b7f7b1f9a4796fb8970aad3d0fa91e0" + "8ad507ce487e3c0b8f627bff1ee11678fb3d96f9337a632d" + "7b55b2d7420", + .r = "1f287b4a3c158c597491a8cda09bf5b7b598508d14fe62ca" + "39c4bd4dcbfe60d8ab9ab1256b7dfac21a10a48a7a0", + }, + { + .a = "5fa7b4163add817d4e75cf4f577e120b240beb9a009b3930" + "e079bae2413f6676918426159eaa93318ebe2b5793abefaf" + "b5e38c02f2aed3ae66b6fdda9b8", + .b = "4a264e3d87007b75657b6280a5255bb3a516faa770d62884" + "87c26e23122f8e148544c2706cee6c87dd63146b3d760eb1" + "b09db607f48", + .r = "6164889cc4d58877517991567e772f06ee3557047736bf2b" + "3dd56a320968c9cbfcee92db6f94d4af72741363a28", + }, + { + .a = "4b280b247c4464acd4c5834dd98fa9457899ca12873fecd9" + "b87c180d0173d69ca2d152854b040b1899e2cadf29b3333e" + "87574957177", + .b = "4aa64863f4890c3f9a5c1f7e2c7064e80ffdef93f1f11b04" + "dbd64b7e0ead8f4121a915ea44101954e8e58e2bd6af14b8" + "98ed0b0c64ccda0ce2d8a5784d7", + .r = "5978246f6a19c365ea7dd01721a2378a9fee53707d4df7b0" + "d8e83f44b5fdaac20d39b79f8f39829bf93fad96765", + }, + { + .a = "2ba16f75674eb3a0dd7d19eaa93d49e7f21d32a8be164ddc" + "6e08681e4aebbc08adf959daea7928d7ddf79d1c793e219d" + "535e84fb234", + .b = "23b197ea7236d30bbdab39f6f90758cd4b69663e9e0b5444" + "7126db3ad6ef8149e4038213b761a19552dec45892d5f9a4" + "cb2d9a7ce7d900571046dd40cf4", + .r = "2e87d4fd2fd116d078cbcb0616a04cf5aa91ace4e89621b0" + "4158afa45e44b71ccf66c3046fb3738ec30663b0c2c", + }, + { + .a = "3b61d77906519c5de1be3277abae9007bf94091e4a62daee" + "7a901070b2088a96995511dfe37c42c5c2de572408b9abbe" + "29de5522aaa2ccc0739cdde8fbf", + .b = "3c25ab9e8afbf26dd1fa537b1a647c571c3f0d261b4539c9" + "cc919ac09e02e1df3b26dc3419dd70337c1480dcbd2acc19" + "d613a6cd9fb", + .r = "3cfe3abb8fd56c28ca4e2e5ba63e005f47086b208db7c28c" + "5be741c0dc4d8e47fb78051e6a33a4ec7fef86aa2ab", + }, + { + .a = "2969653d2fd900fc2e1a9522e08d762cdc7da4f86d014efc" + "dca49284133d92979943445f066fba74a829f8d81f1baab2" + "6a5732cf89a88845eb310f7ba22", + .b = "259a8f8c0e0785b581046d1b87c4ef8c4869f16aa5598c9e" + "7c8e5354c80b752e4271825b83f99666d815b229ac6e86ea" + "0bf165cb0ca", + .r = "31d8a7405d8e6721f4d4cea11bcb866886a157d3d2f7b019" + "e7b394bfef7f7cd9f708bef0d4297f4cd9585be1876", + }, + { + .a = "506f8d1906b029c816b5cd4ab1d9b59d9fc89b74336141e4" + "5eb79f17388a29246eb55331331de78dd60515a3adbf9b1c" + "323976491668d9c8556", + .b = "494be98359239745ee26f3d7aaa521e2cb276a37d47c166e" + "0369c44fbb77d7c3be7b0ca2ce85d69706e652557ff30906" + "15ca9f4e970ee9c4b4075b6ff4ebefca8a7f2", + .r = "5909113404994148bf757ae73c913969c4cdd10aefce2a7c" + "cc0deadecbaeb2eb0d9f42fa135b3aa1f57e91619b6e9c69" + "e", + }, + { + .a = "21343f9bae0a088229513be0b7b3980c8c4254084f1af6b8" + "dad25196f2c46bd19ab09a5e070cf6383147b27e2de3f59d" + "ab9e98705ed82ea5976e5594e7e54e17f9988", + .b = "21488f27cf5d5c2f8e68984c29367add5d261a07ea636743" + "6f3710787c7a684f2cd6f31aa67c4cfc7031cad9d1480085" + "305d3a55e7d2e2eb408", + .r = "23315f7125c5e9557a20a2ee85c4d2ebe6bd52e73e6a8831" + "43f032dcb8997966ec5b4e09777e4577108496e284da4de3" + "8", + }, + { + .a = "58a5d5787fc9ed20149a99828579cf06aa7fb92956fa8783" + "0c63f9d88a98d1ac89ceb3da69a1c723a97413aa4022d857" + "3c89ca9488ba1cf1c79", + .b = "5b07e7dafbfdd8ad725a7c4095fdc4a52df69702253f374f" + "e32ffa965a5ce4549f266a98590ce8de7c6e01f7a62bf429" + "9c4a4defbd38bc845104ddcf8912c1cbfacdd", + .r = "64f6bfe98925bc757c53aa7f9feeb67757f12c01992bb2e3" + "bccdd4c940303dbbcba127d73cf193d78d3c0efa78bbf442" + "1", + }, + { + .a = "d91b8fe0860e8843877df1899e65373722d4faec5b6d3acd" + "217f33733f46659a7afb4857fb368ed583fd1ceb33ae2faf" + "7ebcb71e48df0ca9ba", + .b = "10620c79f1b5119d772b87c9585dd059a198281b8563dabb" + "e62965f1798a6021024604bdad93f5908141f99ce060aa1f" + "2f691d15ff1ab0460f2d22620bb410797204a", + .r = "11d9f3439f0ee0fd907ed8a473e377bdebb29200acc7fe09" + "4637215325c5e63ebd9fdcc111c7579ac3c3c60f9688f5e5" + "6", + }, + { + .a = "8df384d9fc8aef45ef7bc545004b42473b5167c0af668748" + "e73747ff944665b1cd8af417cdb4f2cccbdb5fa260eb3e54" + "e94988fabf95776b42", + .b = "9134ead1a618378f80138ccdccc39d364151c221a8d3c6b2" + "893ed89a2199b3104dc5993ea2171e03dd3333e6f51e8628" + "9b698fa4ba0a12bafaf6d33bfdf1aa790872", + .r = "a8644df3da83254713532df1104ff7c63d56471252a1c0b2" + "ef32fa3e071c3dd61c35a0b722d7f81c70cb0881492446c2", + }, + { + .a = "4503fb24d650b931b8b9488e30c934775bb84af01d25048a" + "b4da3a829ea01fa9f2f72c251130c8f138bde24974ffa17a" + "abeea363c98282cd2ea", + .b = "437bf0cb65aabfab5125a12841d24b03191b3f5d2954af40" + "14394340b98b7e21278c0afa76e458144bafce54b3edebb7" + "9ebab9670fdcaa965181841680c093d775df2", + .r = "4b9b8468e03c458b40fc9e211b392d842f31becc6ac91e19" + "4e9937d2e1e0ca319e761529b4f17e9f241ca19267754ad4" + "2", + }, + { + .a = "51e178c447a0d68b7f63b31f380b6f11031eb470dc79eb1d" + "63286dc855d138aa61fb13c14e049f899546934f58e83df6" + "c6d1040f05f217934eaaca5066b5108e700de", + .b = "4e966d28e5a384975950696b18aa0718b53f1a0a641fa8a2" + "e9fcb89a8bac638e9bbba048d7a4e4c9d9e00255bcd27e15" + "1ed5a22faaee4ed40b2", + .r = "53828448c58e59b5686c5476e392ff03d9dae93db7b59815" + "1f96ef490d88000fd6d10c13a825b8703818397738963c8d" + "a", + }, + { + .a = "73bf0bd98904a9426b98276ef8c4db6c0d88f798af42c6cb" + "7331923b42cbe1e8b837ddc5fd64b8dac401ef638f912193" + "5650d75095d4caa642a47f90bcd149baa1495", + .b = "641c99db7076110f5f409a5e8a5cd5d95343fa00fec709b3" + "49cddd9099ce3df4d3b5f3b5c07492509704dbfdc6160bdc" + "5b4c095f434a3b4bf13", + .r = "75940862ea8c907c0a285e99a363887db2396c2af94f7bc0" + "5ce010d4f05d7e06c915dad223de4bb487c40823b425bbcf" + "d", + }, + { + .a = "64051802505f6a22a4dbe92b6941a998f2769451f226b229" + "0f9f49527ddf48e7033748fbf6a5b8aacd8e04c60bd91cd4" + "3dc3ad4b071d3de011b96829c228e8092c1561d", + .b = "5f966b3742e94b0026201eba0ad5c5df694ddc5ecca6c3ae" + "9ba7a607cb6d7cf251422130b756550124e026247fbae63b" + "4defeef4c767c3f5ecc83", + .r = "7dcb81527d60b9836352d5ec3fb149d3e84ec3ee942f6c08" + "39916f157865b53b0baa40e767a6dc8003f184966d6aeb1d" + "a6f", + }, + { + .a = "1d61c7a7e3573a91d180cac4739adf48b5b74c72f7063038" + "e9c4d1765d7e4763124ab4031b640e689e25ccc6afddb4a4" + "fecbd6fef8527ed069a84ca9d2c9667274d2da7", + .b = "212cf854e16a4cb27c31647c40475f2eb107a6088a3421c1" + "7dc6505e0174aa96a8c6b0927600088a2a528db26569563b" + "7076cb90679d4e744ad17", + .r = "22263a57f0b9e118ee0dcbfce244d886f9703057ded0c813" + "639b667a40bbcc6c025fd10f4825d775591bb1db67c9ebb4" + "373", + }, + { + .a = "446a314d814702308b15e746cc333e10b1b7993052aa8b7f" + "d2ad435b4a8ea39cfa9d15e3b6b1cb6a16f0f809a4dd0b75" + "b9009b854f2d4bf42bc23", + .b = "3fe2ef96281cc785d5f4b5e9682c08a7abc223fe9cf74dbf" + "97e7fea943970e45bee301db05528c0b82137f9b411041ca" + "90f39805b607cfa52f7b41f5e8602fc47c6bafb", + .r = "45c015f28190be09b97094a8c59bc04f34239eda90ae2ce9" + "085dd1bfd5205b26d22f1b362290ae010f19cae6a6a02462" + "723", + }, + { + .a = "ed71c4d73211323dd48ee38cad0864c8179c3b7198701fd9" + "cdcd05ae0298a47985802c387324ad277c915d050d463173" + "d702e5a873ed31527a142fdcd086cc759dcde9", + .b = "f99de4bea4fa9b029bb50dd02b77fb53d2d61403b1bf80f4" + "ed44cda0f665679f8601c385729f7d90c3216fc025c3a9df" + "9af035f5ab423c668fe5", + .r = "134afb2bc229180a005cca6cd96115a480c26218b7512cb2" + "99ae6629e77e74344ba74968a67e25cce60bd0bb7f3d1aac" + "017", + }, + { + .a = "158f69f9bf4d1cae17a2b6a85e72a62272837ac452fe147d" + "d69b096bc68a8f8e51cefe6e7f7c8d38290c918ed82073a2" + "909cfbb48669d7f21a982", + .b = "14d3d9149b52047e1ab18766533415bb6a4bc5f2f5e80285" + "c45dd1f73542089039a15d35162e37e7e258374cf9fed223" + "c1ce9c4fdc1d49985892edf4b6197bc96613ab6", + .r = "170caa7f4eb0bb1c72138de7ab78d8ec7ca40bc8c5ad2962" + "af6edf075a6af208f5a05631ed2f9531a56e2141c3e5883d" + "cca", + }, + { + .a = "1d5716fc95b5ba0fa4a0998f836ae1dab1c194480d2064d6" + "aed4349bc6d65f591d9dd4a42411bb249965a64ab979e9fc" + "f227b29095c8a2ead7f6d", + .b = "1c44c0622846ffdedea025144cc4e84aaaea8ce1dc5d1205" + "58164aa8b63aae1975fa5bbc42895bfa8f2e13dd8d1cfc5d" + "8ae30db81f9bf2d1d3ca75c9ebc6b9368dc085f", + .r = "21e1d58ab5abf752819ed5cd86894f812415170bc16fd03f" + "5360e713602f25215e2e01000a690f52ddd48e802b790625" + "ee9", + }, + { + .a = "5f95d61d5ac8dfb6237f983a975254959e16a64099f629b1" + "73d59728ba69a78b82e1d0d6ac33bcd2ce1925da02d7c34f" + "dd9ca4fb2fbf2f91a1ffc", + .b = "5250417c833f88eeb2891b033f077fd58a3d3d56afe8749f" + "688006fd5e3db3924ead2f9fcc610b86f41d570f66d0f9be" + "131d49c41f851a60a3a7cb0ab6117b469f46944", + .r = "6b8d9606cd8926ebc739c6162125b4ce0dab87354c13b6a7" + "7075cd343d8732a5af16fc330fb1c600b6b36d47f66b6607" + "43c", + }, + { + .a = "59039282401a65c164713172f1ccf9c4d97afaada58d9566" + "7e7a7533e064bd6390f59a6b7a34bc2c8f19f36fcc5fb272" + "ca6b46fa91f64c9f20af505ecf0004def24cea6", + .b = "58352c71242e461377106b457b8d778004c825641a53ccf7" + "d4697f821a074e21ec65cec7d9f8112177d76746d955e48f" + "008f4f513cf75ba3c0dba", + .r = "65da4653de3b0fdcd2e5ba6ecbfa05efbff01288526b7fcc" + "15e5332828b3e4f19945d535e4599129c4ba06c4818d673a" + "5ea", + }, + { + .a = "3684d6032ff15dd42be955e32b0fdbb85f2a1c6c8bb00384" + "1dae0e00bf12df6984067c54bc5838bd4e8fac98ff0cd678" + "0ef1cae4037d800c62ba4d1", + .b = "3411cd025265dd2da51495775758bff7813259693b9ae734" + "67b5b87febb41c27e9fd871150eb93e09fc8283c335432c6" + "3c9ad3a46cc81fed9be9e1c49d4ced031d200fe69", + .r = "42513f708f738678c4fa764fa601af6e93c152b165ffc39d" + "f97146b14f57d39fec1033b7ba6040e142716f66659ca2fa" + "d972f", + }, + { + .a = "35f5d92e10e5b20213267b3e394a9a9c389095800cee76a0" + "0ee0dcb7fbfded16bff6b4d011ab39a680421248423f6825" + "76f202c5358d69e73c253d2a507e53fda2453f075", + .b = "2d337d460643e294732a70f1970c4bab4ea720422a238027" + "1ee50e5bd897b18ce52a8820757e139dd515e187c4a24a9e" + "82aa1fc2e5a72f0f7a6eddf", + .r = "37805ddf1106510d462969dd0901ed9ac685ceb2039519a2" + "2d3e18de0d5009876dcd66d24f1303facfba475c8e14af6b" + "19fb9", + }, + { + .a = "176df0a85bd4230ba16ce860963ad6cb1b05e1feea2ea3c1" + "a3ab916f039e3e1a27db3565ac5648b82717eef5c357cc51" + "694ca181b64ea28ded069df", + .b = "15f221fbd53d4eb74ddc06ad6d768ee04e40dcf58bc1c084" + "235786fcbbdadd235181084d85938955813459912103d37e" + "964d685b4627e682d4491eb2c03bdb39e32039353", + .r = "1a62b3f8b2d3cc0657433fa37f6521c051eb5eae3ecaec7c" + "763d5095a346a60cf3470357626a1e074ec0358e382c2899" + "21dc7", + }, + { + .a = "4e6a76eba33ff0050eae889e896f01022b3e97d8d3d79bf3" + "ef4aa0a7e3c47e1d260082fdf5cc48e7a4fba332f2a1bf6b" + "2f865d5b1d22d4252ad556e", + .b = "4251261d1cfcbd60e29b0159cdbde3ef593f14855e260e1d" + "810dfa3b7965644c8294f03b39c69587808b0d5d67bf359d" + "059caf99067305486e0d9399eff72f285b5da1a02", + .r = "55daf1aecc86dbd8dc1bc1e39cfd601e24895032894b1b4e" + "aad0154972a597cb8b0d836d57c634962767c053c27576c0" + "a04ae", + }, + { + .a = "a7e3063f253529bf049b25d65650adb1585fa551103b71ad" + "bc022b3a897b7549d658795d8e6561b2222d76da2243fc2b" + "42d10dad8bab28e5265804", + .b = "ac5f34ac9bf20f064fa36b457d77769035a4bfe6702e6b42" + "edabe0a2bef03516d463a04bad0e57d6f2ae8f43050292b7" + "4d54e24c40a6fcb02c20bf699cbb4c213f4e60d4", + .r = "bab2f490dac73cb3fc7839d65ab4eeb93f5a333dae6f326b" + "c13de7cf18fb94acaccb915da4d45c0c51f7b902360eab63" + "4b94", + }, + { + .a = "4046e1893473d68e42c580d2533b7e34db79b16f9d859ac2" + "3dbab1998300ce578e0b0f0ce4e907d53d7f682e23d37dc2" + "147c451ae0b00cd68fbded75ab158fec892149847", + .b = "319d4ac19ff7a710f7e30b17f732dd5908ea93167aaf1734" + "edd540c438fbf91d41f1c65d1a46c6dc5b13eeb7dbc968d4" + "12c249f762691a511f07b15", + .r = "412458da91a0a1521fd0d1c22b7c053b814fab4df3e87ba6" + "ae21dc22d25b3bee7e475a3f48ecba135dc83868c6ddd25e" + "d58e9", + }, + { + .a = "1acc10bd504085b8432777bb6c271c9055c233cc21b8ce2d" + "6b470cdb6d1d0c74af0e1695442da2081d9492d35770cccc" + "2d1731e002cdcb45ee45921", + .b = "1b4f37bd77e0a7b314f592443f59ea10de1dbf0445bc6bed" + "128dae391f8516186ee45b516ca3475fb3ea11116a34f2ee" + "850a74e0ba20fdef9ee45588c3ca0ef127d0489af", + .r = "1d9141432a729a9b3aaa82d0503baa91568654af70cd4363" + "0355718ca82f62ee6f14770f10c6437bc42d1854c6eeccb5" + "e36ed", + }, + { + .a = "60b82f6346f5e1ff60a0176b471ce808fbf43358a16d736b" + "db3219f3f5f9a46a996122b2f2784c50121dd93596279b2d" + "6a2a07713e677ea4c9419005a6d986bcf3a9ce0bf", + .b = "74939f572534c6a8436abfddbf00ae0c33a465675989946a" + "474da3c695fba4c6490478f37b3d6e5c76e590662d87dcf0" + "14ac17b13cbe07199cd3ba5", + .r = "7e8091f648a47ce00f184882ab10932efe8967447807c941" + "0b82727bb25620adb9fb91c58bd701cb50a444af3deda2ac" + "cc4f1", + }, + { + .a = "5041a12256efd3559135a980a600dd8c71d33bc55b01475c" + "2d8516d2d606962efd8b8b4536a96f9b9a0e092f275b8652" + "c5ac60f2c8956d6fdc821e9fe480061b3b9d5e2dce4", + .b = "3f8ba54304ec5f724fe2f8161a4a15eeb203ef9b96c9c3dc" + "ad5769b15ff60240643b6b3e6dffb1f57e210e794a46d510" + "aaa4243762085a3e6d2e8ddf4", + .r = "53f22b42f1cfb21f48afc31b3ef5e63f16117906d9d5619f" + "3b9e4425d35fc00588d23493defc3b3c741b57f0e3925105" + "55a1934", + }, + { + .a = "482592525884dcfa5a3c7d1ef4ee019ee36b74efa8760e03" + "b8c9c25f73d11c2b0eefb6a4c1eb054d6cab50608dc46180" + "cffe442c5028a444591cbbe4fbd7a3a8a7e9af7aec6", + .b = "48068b5e29280df0aa9946c85ac651eb99129e56460fcb80" + "3404cf2aba590a80f27862bac4f5dfc3b53f705efc47d5b4" + "301b11b24aff938ef1b2a6dce", + .r = "54d661714aa606419e3c4a493fac4758d55a4de6d0ae8669" + "d539a1867447073a821c4f8ead9730cf1eca56bd3913143a" + "b8cacce", + }, + { + .a = "5baf6c4efe7c773afef12ce9e45f367cf462bc8677b90154" + "9df1f106ad7a59e79d3407532fd4e40792ca94ea8614a51a" + "da0f04042588aaa21f71a15ac747a583753ecee0193", + .b = "4fec301df38963b0df53ae7456fc3241d338fb0ebc719c4c" + "b6590ed2930885854f03c0bbe83ccc313ce7a40819957c71" + "1dca992576432c20528369c33", + .r = "5d49d2348ebd7e89402f54b05af16b6b25834d1d39c96f89" + "cb908d3dbd18f80edd0b2d1b11f45e3eec077694101e855d" + "49cbd11", + }, + { + .a = "2a2b63ed2a72e6759bc1cd7f47e1431dd871bfb226ed3aa8" + "8f7b1b17abcb08dbb3098d12b5e3e58d06963a6a9519bbce" + "c6528ef1a45476623662a2e11", + .b = "2c46b323b913734721878e9a9898953631956bb6c9a2b4ef" + "cedf8362065409753428aaea818f13649321f92611843a31" + "8a8a38a4840460119a08d217641560a1976b1d679c3", + .r = "2c9003a62b4e3a5e43abc538038004d390a656d238b411e5" + "db21f7bcd7f7d79f52749cfeec14ece4baaa35aa51746e41" + "2024acf", + }, + { + .a = "1cbd299d709faa872571432fbc27fe7bd54d73f083d4f64c" + "c0bb273983fc6ca835d6d520d2e469609c785aa1d5052fb5" + "1dbe4d591c5493638b2e19eb6", + .b = "1d41ded2310a8082543d3a458ab9d3a3b7673562b365d209" + "9a00f32b66a9ed87d95dcb3c9ba5a87a969d6f5b74a030c6" + "fa6faa5d03e7676a5855b91c46dee64e00f8658e75a", + .r = "24425b1ed3cd100af596e80c6fd95404e71c5b4fe9aa7add" + "518c3577da1e13a1074e60eb08c7d8e13f02475430a2e63a" + "be88cb2", + }, + { + .a = "1ca04f2c09b9596c42931ba8ee02db210ff47fb418a30b57" + "9f7efd43eef13532cbd81ab417785c1683a69980735dad72" + "c50c14231b7a97b7b8bf95e67", + .b = "1c808fde57e0c48e8ce127b7f2f1fbf45c48f1e750d05780" + "94af9ab929452340a01ff8bef56aaf980518b11b3657574c" + "9094992f00e9f865d7d20e2458bf72c7d301f84c3db", + .r = "22a0e51cd1b018a42796cbef433a38feabbb38205518b6e3" + "1e354f8d88b3b5b6c639b774804a44a0fefdd1b95a8a0e55" + "39ec419", + }, + { + .a = "52c2829183621220af8de2c0ed3dc76a8a6dec5267236f0b" + "2a22a805d4bcb70a18c8ec62e535954c6aaab0d88425c7a9" + "0a8071419efef709b1fb521d0", + .b = "44f44bcf15967aa6840213cae893971a501acda24258d714" + "8725ee3e032a422e5be1d69121a9f9ec7678b2de016ed626" + "f697ea4620534572e975ef10d3e91ce1bc9c8cb8890", + .r = "5a8dc5f968e491cf69c4addbb173d8b7ab541ea69290fbf7" + "9d4c58c8dae65a97350ae0cf2888c8bf8d2ea686f99dcf74" + "c85e790", + }, + { + .a = "3d5c521fa9d5e9b5ce987fbd317fbe82fa1a22ba4195c3b7" + "d240fb96f7f64afa63609f0938cb071c148c762b02b78eca" + "0f102b0a00d8f340bfed713df", + .b = "4486f157d285fc7fc4b3baf3d13557a20652a98199c15282" + "65c7b45f4368f968402871bf12e674f29521f75deda405f9" + "cb8f5ba0548a7fb9815c90b398fb11abf1979cab9fd", + .r = "4ded51500c9fbfa781c67ad1f645744af2c37a43d3dbd701" + "c2226db2484f0d386e5c7a4bb721eb6e1d978862914bfff5" + "cd625bb", + }, + { + .a = "9b8e2ba3744f0e2ccc6c64489f5e636e128fe0f78e5c4eb0" + "ef7edfa0e873f642478f131b5d6cc48cd6bb6c8ef878f5df" + "edeaa3fccfed4206ea3cb46f49ae74a9", + .b = "9cfb2f846b2252a87acdb0cb8f1edbc4c7f411d20dde77f0" + "a4e88be62b53b2fa3426f6a42eb8a937ab7280b1035ee3bd" + "7945fd0c7a17f8e5ae45947971d22425af6081491de906d5" + "003f", + .r = "bfa5e6375e267d9bb687e7ac7213831fb8cfc3229e4d9d56" + "99ff6827e2d0aed224e70dfcbac063d07abb5666e0c0af9b" + "41bd0111f5a7", + }, + { + .a = "2ebadfb0f01dcb25f167580ed3b4b9d59419cf269d32072d" + "1147e8fcdfe4b8cd10039a6c8465c4bd9ac22009fc6b8454" + "9adb4b1ab384a9dacfcb558dd3363b32b", + .b = "25e6acf6f10c62342188f297d83778472942056aa75d7e9f" + "6f807df6a48128a021d8da02ab76be79cb49cc238428e2a0" + "e588d8949ce6a9c02165ede046b0ca2888a4b370e656f936" + "e93ff", + .r = "309ff1985b7e18d34be1be59b8c973ee2bd8a9fad57e956b" + "88a202f470119f705cd4fd39066a4398a482a9865141a336" + "7a267a3f8b069", + }, + { + .a = "6cceed6943720a5a324197e2cdaedad687e7adda7c0d243c" + "fcab73a56f2f12dadb559e79ef3aff46c19c0d56c6c61d1d" + "22fd91fe2e624a3d41aec8a461a3f6ed6", + .b = "79a4c305491a52aa8f683102d1453741ccddcfad823e04ad" + "0420452aca76e439c065e7f4ed424e49d479148a6b3dd2b1" + "afd5d16bdedc4926156574651bfa621cd194054c92d2cee6" + "6929a", + .r = "7fc3b98762a487c12434b4913191da9e4990f0451817ac25" + "3297905f6217caeaf7861560edbb94aabf59f26cda12c830" + "7a236dced98da", + }, + { + .a = "63294e7f411ed0934592fd1ce56aa40af1f598c5eb3313c5" + "a7d72d0ca7fbd9fe0a58d0c47af5afa04a239cf98d6a0bfa" + "6ef0d145f8b3724a8e454e6cc620e431d82aaf229ba34760" + "8980a", + .b = "6fd3d8cdbb3230478da0959b4b373d71087dbe5424f610df" + "cd24f85d66a3d22f37da887118c1679676b9259ed5a8cd79" + "99bdc6342d98ffeedba5d89e6db6530d6", + .r = "720e83b9e76c2f544657365583ec7cb2f9dabb4bc64d088a" + "212405a4589a86264a22d4b81e77cceb3ae25a24a29e45dc" + "b6b0015062c22", + }, + { + .a = "dbd562f8706bd4ff1e3a3e3634de519231e6088576e60e55" + "1f10ec0abe40f95eac51dabbc571f9878e35b17d89cbca5a" + "327d0cca3600389249a460e444a72233", + .b = "ea1adae8f7712d0808c291c3d001201135640d4b182caf77" + "b9b7090ba51a4e990b1a7be13bf6a145f94082f0b80a77e9" + "85af920fddcad73de46572e5b50633bedd0f15dbfcd5977b" + "6ab9", + .r = "f728f23f3351350ede514d09827e93cef6e262d00f191535" + "0847175ba8e3e5ba34037e8ff5229194ec74a96101efff4b" + "059c0f1c08c1", + }, + { + .a = "4e62aa8b1c23927db9db64c95eebfef251ae385904f5798c" + "ce13acb401fe2e49ba9ee86342c080b63639a5deaedd9ccd" + "dd327677a0bba4da0cdba26fc68a6e95636cd47b691f4771" + "d656d", + .b = "4612daa4e7a3d3775dda8c03495ef240de334b3854747e51" + "982e4b4cc98559ad40e1b29b63586d71228a4e2f2df1f5bc" + "0ddc87c48f504f1d1fbb175017e817637", + .r = "5067e4b9a1c71f5d2ac2b6efa944791b160e131bf05a479d" + "d33823e918b27df3a775377d670d882016dfc62ccfcfa8ef" + "a186fb8cbabfd", + }, + { + .a = "5782ea018a2d729011580674ecd0fd6f2fc08775d370e387" + "fbb229df3b46c3159b02abf84f71c2acd4dccd7672700800" + "63c0d9508588d8ea2ad006c9d17fa8005b12c08f05be86f6" + "ca475", + .b = "6f1193e160ac77e6201a927a6ab19f46ebe565a1d972eeeb" + "d69352900a9ce5eeed923a15fe44ae410de225d3265bda50" + "f26956167cf7a5af19988bd90a2c905f1", + .r = "7435426ff00b17e724ef65e2a274a0a3cd920fba3719c06b" + "cad61d485da7236efad8b31592dfdaf04bc5f75765134d03" + "c793017085499", + }, + { + .a = "6359ee8249c069ec298cbeb0fd9840e579ad9c8d35064207" + "90b5b93a9c9b08a54e6dbe18168fed3cd8a17718f9a2ad38" + "cd45d617d86f21479b6164faafa80d2e4e0fbf77f3e07977" + "7468", + .b = "596ab00e4d9697fa70ec94c7e21ba6afde01e261e891ef58" + "081385ceb26ba02020cb58159670bd8f0cee21be73a53e6b" + "0a77b4e3ff40a92d7653653098009798", + .r = "64126ee141f2ea8ac8a19530379ca283fa4b0f6133e78086" + "6374a49b319d99755321c42dba02a1483bfb0b0b82eb83fa" + "33cf2fbcf518", + }, + { + .a = "af2ebc45afff617620644e4f1b5234fdb933ab59534411cd" + "f4f80081e5048874684a94cf4197ea6ab18137cff1b88954" + "365da4b4ba63a9509800040528fc93ff3e", + .b = "b4698b65c0b51cb00948d5d894fb2113333888a964d930f6" + "e477fb65c9f5880003ad205d69eea463e14a201cc31de4d9" + "c22e96730dfe9ef3bfeae662507787237ba7e0fca09e5a20" + "f7382e", + .r = "c52c16502901190a09a84fadf933fa99be94b142196fcc3e" + "f685f9b81a7596acb73f1a6ad014dd5afc1156181f6cda66" + "64db4cf33994ca", + }, + { + .a = "32bd7040cc6866c2a5de1a578d8585a0fbcd75545158acb7" + "cc07c092537c777f6470d2c81f2b653a856ac731a0bc8e64" + "3eec2c37dcc2ef374724d50ac0f6e19d273b1430d2f7abaf" + "ae89c5c", + .b = "36c361594992c8b0ad0b8ed3cbecf7aa5dba9f55b2064398" + "31081eecf83dd8e39e50020a919323994c2cf367e497787c" + "6d40ee718105088aa308955002745cc2dec", + .r = "379d7395a1f2680686876adc77c0f44ca50d271b80740af9" + "6d697e5c7686a07490ae10bb0af3baab942873862e7cb801" + "4b57100bdf3d3cc", + }, + { + .a = "6ab2c1f8e181aadae9772ea977fcbd6c0e769e9b03cfa1ae" + "f1836a1a96114172a589429f6fb2c73c7b395be503caf3ca" + "9f808ada6a10ef799a654de7c18a42c5b37", + .b = "5ed086dce77d1e41ab41f8c7236e1146a102aa2b9cf543d7" + "ce344b94fdf62a09796dffb761dec0a19c94881a26bd7c88" + "d7e9f2a41926aadd938cf8046646eb83889830bcfc588d41" + "f60a031", + .r = "6fad8f4134b6057fa6c577eb469d2a1f0493a4123156fbbf" + "18b4b87e9611a511cf285e68f5c8da5f1167f9ad927756a3" + "74fb81caa603bff", + }, + { + .a = "4222b1f9292feabe85a201d7546c7fde474b882c72c68aa0" + "831767fb7502f6710d4dda3682c594f76c3a9e95798f3e29" + "c4f208b84a43bffd66a9bfe6bef7cbf3f0f", + .b = "421306ddb3844b33b1316dc79bb75fd6e1fa0413fa3e97ae" + "e2416ee2be0677509caf92904e3f55ac4b59ecf2987a4963" + "ccdcce2aaf0934a574ee1214771a756b01109d1eb730506b" + "cb9f0a7", + .r = "4274b685f1621bdc8e6b09a293c06555ba1af6aa8aa28ba7" + "2d830fbb7325fcfec6d4554ab1be06a06fd85ecc7462c70e" + "e80ad341b770047", + }, + { + .a = "16b17d8beb25b38e18784fcf2126b1cf548ac5adb1716a52" + "58374dff36496e1bf518d6cfb071430669646f0a0c5b59cb" + "8156dffa4f6df5248a7451113f6dad2ed8dafdce8e2f6c3b" + "b5ad9df", + .b = "1b2b4e114eee4170d7ced5e894d921ac2550c00e62bda9eb" + "eedc48b5a5215f122a5aa75f04e5d4d83def46ac52476c48" + "a26963b7347aa71819f76516bb296340d51", + .r = "1dd468531f7021964214cecf79e9e73e868b887291607e4e" + "9af36c03ef8c472054f4250ba8951fb8b4d53c88bc5edf81" + "ff47ae2170cbf57", + }, + { + .a = "323c6f3e02cb806d581580e1388a4e20013e0501fe70c982" + "c3afc8d5ff04856103bdd8a57e47e3293e6ad69e19bfa94d" + "4ba469e65a2424960e2341ec60090e2d1e542f8d19fc3301" + "a0bade", + .b = "2f8677752eac018756090ab75170b4e5246c28cd6efcea6e" + "51ecf22a00530f5ce2015758419b23b0188785cffb278165" + "e92028c492e77f1d2a712f2df446bc99da", + .r = "386d1d78f1223150f0b22e01de5dc7a14a606d00cf504478" + "694b0fd9df55e8d944dd9ff94f23670788f1944bf5376066" + "4f324cdf52ddb6", + }, + { + .a = "24e663278b6b76e6e472090021b0c3fcf10851a94e225d97" + "0e93344f952e0d0142fd106d1f12056e821993bc7a66f773" + "f04584139442affd723b798f52b63d4a21c", + .b = "284b2b26790a09071efac26cfa788d9f3549ecf642064a6a" + "b1a1ed2c705c1d43c7c7690bb50a1538e0869915007676f9" + "43d4b39b24270275aa134de2b6be1012a2f7df067a794472" + "de278cc", + .r = "3013a01d87cae7273ae913ce8317e62f6183fd9d1b0733d7" + "fa3eb629bb945ef0eb31187ddcfbee739467271edefd898d" + "4fdbc26ef1bfb0c", + }, + { + .a = "545d432d036aff1691fefe5327b30f2178a8960b86aee56a" + "522dcd14e7fc04a277b9502373e8df7457b8edc63b1dbfa6" + "050abfeef758e84b8e7d21bd38e9693a459e30c8b80af40c" + "50f1743", + .b = "4c50a7e6879619d3cdc8283524d9677ae8b15654ed9b5d9e" + "adce653180782fca9d28f56717d9e27837b5309f8aec61cf" + "3ab8dd2ba67ef7143538a18b9b169a36e51", + .r = "57692da8c61de8e02aa9230ced68c3566014563552b9995c" + "8db15082638a254b2dd6056b71faa4547cac5768006975c4" + "ea77311f7cc96b3", + }, + { + .a = "1896655e0b2717301b8e7fc93b174d5092a46ae2b8e574d4" + "6a48ffed75df363b1f3079969aa13087eafe8d910212f48f" + "77e294ab538eff2d40708984966be46937847", + .b = "15f198b7de0ef20eb58877b470ce8b1595b082be9a8554cc" + "9936abae6774cec058b24270d77c6279342ce2d0584680de" + "c38e2b54fa2bb3b3c4fb840bd193dd3fafadc9447f1834d3" + "4d782c32d", + .r = "1b60531fa4b7912ffc8396d21dafb03a6ce484d925d5c281" + "62d3e5ed871175e9e83299164e9682a34ad55d940bc83d32" + "a49b40068e0c93fdd", + }, + { + .a = "43d8780b46c862cdb9baf5bde283ddaddde8ccb24aafd634" + "855de1fbdc6f0a2f1b4d8a83f711120e703c3aa46cf8147c" + "d6f37da644737bdc28e8fb3d31968b7a7c3af", + .b = "3f7167c05f5a6a976060da8bc4d8ea655cceae378978cf50" + "4cfaf93dacdd1efa1d17c1354a268f982d7eb8c52997b258" + "da5d91abd74b3d027830f99861707902df4e3dd60f7bd98f" + "5bd9526bb", + .r = "4a07551954c425e696fafffa8f2aefcce1e29ead1ec506c6" + "198d085d1dd31c2af5cef4b29ad65d8c5fd22fb5062182f8" + "96b3bd77f8497a6d5", + }, + { + .a = "67ddb1941fdd37163a493e3da23050851964f45d8d753e5c" + "60c84ffb32e8d6dac19418385f90b43dbf1af8b71421329c" + "ed35e1476952d18ed2094c1ba974c976bbfa5", + .b = "52c3fd899ea97862a0427c3b0030faeba715f30babd0c1e1" + "b0461ecfd4e4bb35622c51b507addd4c59e76467add7fabf" + "afb87c0f2f52128ec6a239195d67883cfd350e24fb4b7c13" + "7e1503815", + .r = "6b2b63676ff005d7250de5ff66d64c29c5a7a7e72736602d" + "c4a9b8a097c986899e1177df736e0aa7cc75845a460886ce" + "a568d0c4d0d101d5b", + }, + { + .a = "57e1552f1cae68e8412770607b7c6d67d5f6ef1f17c4000a" + "045667d35bf1d040c99b590f2b669af84f2d642679a95ba2" + "7a46bcd290ab6e1044fedc02b04eeedd3b75", + .b = "5cf62e9235bc95309dcbe49ba173500e7187bfc9be14044c" + "532e1aeacccfef483ac66e7e26564f8e2ce45bd7bdd391e7" + "52f17d3f5830b70edaea49ca72b98f2c37d2d508b644149f" + "a8fbebab", + .r = "5cfdcbe753eb651090213d2a783f08190d48c662bde9940e" + "239fec164c9a8a81c9dd1051c9b1f75c9aafd1b698ce0729" + "e7e37e76a06c2e5d", + }, + { + .a = "20ea9c5dcb3087f695b27c4f815f189fe882ea70a8ebcef1" + "ae3b97577f24ae2656f0c01bf9fd33aa22d4c112aff8092d" + "6794d3b0fdda4108aadc1a9fe9bb61fcf28d9404446ca5a0" + "09d88df49", + .b = "266088bdb989801f5b345876164751f85a8a564061dc2827" + "d9514c0b53776553b041ecd57151d9c55da2a89d3c7ebd36" + "b43d56723336d9beee5af50fd2230428e1213", + .r = "2b1cf5b2dd1d1cd04cabdf12f70f16028b22a281d653955b" + "4ea0436f92b4c913317bcb862d7380b774e385191f881383" + "a7d956a8afa4239e3", + }, + { + .a = "541e1f20337202fd80059713e6cc475dd33792c9d92ad34c" + "1773f1585df2da12dafd3f8d24816e2ad0093aa31cfcc8da" + "fb249a5e5930ab4b9f6cb9c5547a86bc953bf165f1abe376" + "14006361", + .b = "622f62ec0a012dec5507e76c7707206f4fb26f5020a0a2b6" + "371fe7aa171a09a4e60fb3174c8072910e826da3525dc6bf" + "af73356544b7623090d911d4b8991e29fe83", + .r = "62c57e0dc260c7ee0602c25df9828b47e89be38550145da4" + "5432dd9c9a7b96278d71a606c9f3645fbb3517626b8f32ab" + "d0afe435f4ecb433", + }, + { + .a = "2cd4051f179794ef9ef8862d26ef9dab6d182c0cb8f7ebf5" + "639c9d3496fefeb0aba58a39c9cd23ac10be381a767249d1" + "237d2ec1ee8c8ee11f8eb1bdc98369eb72997", + .b = "353fc536676f933bcc683cd1749f43c301f70c78c14061e1" + "96937152e2525308c58c0aeb1870c673d29dc587c10d85e5" + "a43f58ca37cd96c237bf47334f480d92d1548b001a773aef" + "7ce7bae6d", + .r = "36d086207bdb311c6c7f40ff336994320618686e0a8ce908" + "d26977e9366d3fbe9d0c7531b6fce290b1054c3ac6b94ef8" + "a20c196ef6fe052a3", + }, + { + .a = "44255a3fed2be652f9a34a4f4abe0eb311c2e57a0f85343d" + "2d097d970782ef3dd61260410f5607b495103b0989ba4109" + "6da388c5cbb64a497e249adf4d23c71489c7b", + .b = "4344b250abb87d531d7c6ec2665fefeb44623de4394fb82f" + "20b4af81c9b0f1f95a5e8024cbb26ec876dfeb740137d8e1" + "e22975a708e57a0bf009b09bb0855d871f9dc94dc4f2f05d" + "0a38cce7d", + .r = "593263ec0796447aac52c4687c2c795e17288b03a9e90eba" + "0d7264d0759409064c33461d6126c433f2928ebab6635f0b" + "b7622d036e16ec2b1", + }, + { + .a = "441a895ec6bb6311365e27a6bbeefe3cccd5319e2477ab4a" + "114f31b7075dbbbd2fcbfc52bf596b95566179f8e3ba1b3d" + "d5d9fe612a117174b171e6d7d8a9dfcbecae0e0cfb2c1290" + "a45b38e1dd1", + .b = "3508180db77ae987b951ad99f94eee1371709f6a9e5e1f54" + "e15af30d3305d1c03a859252fdbcc6616a362f44d2f9a107" + "54f38da41a8e01a65703de5bcb8ad1d99b34863", + .r = "45665350710b2ce8936b54b6de415eeed16612f11bf2613c" + "a7e8c8a4ee4e6103206e45bef2d696cdfaca8c25dc15f7ed" + "3baaed29ae81af3be71", + }, + { + .a = "54da6ed1f70897bc3cd66600ddda1608fb2455d09321da8b" + "c87ccaaf82291a66101c2e6e0169057bbad4531983194bb9" + "fe1a67eaaf08583ff718bb86a8aa3e5db3d23d540bc9a2a4" + "3fa939e0dcf", + .b = "595bbda1f517ee904529a9300cf6bb6baf27445355b55349" + "7c3e337b693b2ae8df63188698f84f1bb8e99b231f1541fe" + "7f1e55f471342543896860c3b4a6425cbedca2b", + .r = "5e3d812cc1c469dc551de91f369368b93c94b947c69afc31" + "67db9e82486c42774559e218e3ded0b730a52a42b0fd768c" + "86b1791b5aebd5f5d31", + }, + { + .a = "440f0ad9199fbb9071aafb23f0bffd90cfa77cf928940edb" + "cb952194ce19bc173eb4de9dff4b962399851fbde873aa8a" + "6e4286ca648c2a42c264b74d58c931c319af9e2", + .b = "5032c0da861e24e1004fff70b44b084acb03854d88f4e70e" + "f66639dd7d3a5cefdb421e4d660f903b2dd99f5ab4bb25ff" + "b7ecd3973c46d32557773f4c82095c7ca94edcfab23c3af2" + "afb486eba12", + .r = "50ccbbd6ba5993da82e631824c52f869753f03590b296be3" + "c5f0ddf8a2390e7646e7066418551aef8e5185cbf70dd335" + "75a05f94cd88f56b282", + }, + { + .a = "3c875709bfe10d50babf283029ebd6254860eb2ea5fa96a0" + "68fc3466e32d7a242fccf602fd6dff901041973b7b57d046" + "52cf6a8ffcf6d46316609a82fa58b1fbeabd4bc", + .b = "3d179ade5d386f2d58590c71984454bd7669fc25b059fdaa" + "42bf7e64075fc7f0204b7e90c0f9f70b727264a56a7bf1c3" + "27cbd33afbbba9ed1bd124d2fff205eb31a61b0487d28c9b" + "cab2df5390c", + .r = "40bbe8a212039b7f67dd515ffbb394c114d743aae1137f74" + "28f14e2056daa74ed90088b1fd0a4349faf168d3c01a3cbb" + "c793d521ecd159d183c", + }, + { + .a = "15e3afb34c242493b52d1dc6dbb65f7678297c34bf9f17ba" + "e3d4496f08a44ea971aeb7584ac66255d153584fd7a07e4f" + "3b5b0597d2ae476b02012299f71c46825911f10f2daf7319" + "d74e2df221b", + .b = "1468791ae811bf12455592f932b46f69a98e89ca3b333fcb" + "f287c8eb173c4971554753915de9f73719527343530eb6e5" + "f14409d8717b7088274efbbbf8891295a399beb", + .r = "1ad99426793db7942559aa005fea7d65827a4ee96d8754b4" + "bb94b0220b7bb008c7b2bb5511b5022cc5e23e99be347164" + "5205cfcc19360830a47", + }, + { + .a = "41cf8df652d0fedc98d1a4a6ad6a8549028ca5359eac99a0" + "aaa8465e92c4006b23c3bfbe55da176cdd1e1c23e8b442cd" + "e4e0b04a796836ddb3fe7105f7863c8de9888efdf198c764" + "f100f554db1", + .b = "4b441c2350d6c803ed1585f765774356132b84acc4d6e063" + "3767dd9f272080bee38af40fc0ccf1491caebd0d397056c0" + "1fa0a94cfa2c3ff15c8f26a8e2f88c2f5ce3547", + .r = "52f009be59e82fbab92297bbd7abe8a43b252958092adda9" + "c4ef32c24e08c752bee3e6ba574d2607dc1359382f29ae40" + "96f0171290295eb388b", + }, + { + .a = "6956040bbdab4b9bc0655df3a2cae92548495d3a31d53580" + "f7d24be5f7abe168f127e4d3833e814b381a6dfbdca18f8d" + "941afa3bfcdd6e61495f05cbfe67140edf361e97527d7630" + "c8ac3f07d56", + .b = "71c2d447d125d367b7c91f4cf019b6a0d7f9ae9637d4d75b" + "1eee393667904609a9e43bf618c25a1c6dd82fde20afec33" + "2507b73233987aa27bb7756ee0b6fc84d277d02", + .r = "7338a44552a4ecad8029aeef2a4c222b111dd5f256c623fd" + "11c39599d070eb64fdd1ef4db2078002ccbdffc8ab2a555c" + "8fa570796b45effd6f2", + }, + { + .a = "66007f6a13f6e7086df1d1eb53423db4310683351648aea0" + "bca894901744467996594837aeb9d1b0652948e5ec7fb5f5" + "6bef90232ab1450f41c3929c311d8ce595b5df86df8584ff" + "9dbf988846d", + .b = "602242d9a346d1ad7b3474efea6151eb28d899c695b05acf" + "626d984cc2646a8292b62037393907223c005b6035d5e80d" + "74a4a5ebbc1690e6c77c9b568281aa1b30a714d", + .r = "685bb934a3edaafe9df57649a9678283591c89e169aa2f96" + "86bc78711d252015f17bf6865f697b09be0dda12bda0fd3a" + "2c505c94aced0b7a277", + }, + { + .a = "a1c8515f72e0513de3e7a560a4f25406bd7df2e39666ddf9" + "0cd339d9ad4620e1fcb1063cc965e3b5f74ca5cb47905e0f" + "1d02c1f339e8a11b41d9f7ee44202a6974b9675b731810", + .b = "aa6a210674f66079f971d693322fb89c87df9c3746cc5b52" + "760a3d7d5f6591c96a29e22142cbcd4a3d4d2f56a44a3397" + "10436032b9b286d2506b217bbaf00bfb026c6bba10b0b847" + "f3903d68b7e082f949d0", + .r = "ae558be6e081e845c1b7332505e65eefd673020d06271289" + "98a2a3cf0d3d6457e58d0d504dba4b956d18059a9073530a" + "84f9aefc01b78ee7c5f2b930", + }, + { + .a = "63a2fc46309a37f6dee99d2027c20815e0ae0c73845585b2" + "32cb4ecdf4670fb5f00df6165eb48aa2c589a8439e4531c0" + "43521257245446c94e826722a04d60a711fd262271f9213", + .b = "5998b0bb3a3c937764cba78a0df0e9edb2b15f4233e2f594" + "ad195f1d76fe799d1ba7b98c4e983b78c1df913632096723" + "b18b796e296c1edbdc87fea7f543a1285e2cefbc4411c420" + "e512835e32f232de8767d", + .r = "75fb0f8b649d3b211427a2b659490fe7c9e45aab6a032310" + "2f36ddb69bf6431160297ef61824517550deaf40751a65bc" + "db3edf29d723bb44e83090247", + }, + { + .a = "5f37cd5f95c9d3a33b10ea4fa514894e4ffc15dfe73766e8" + "f3f7789fdbe9c998ff8020eb56bf47027a7dfdd28ba2d289" + "c8d3879d782342a9a6321d4a182657831dac8569986585a", + .b = "609a77e881ed16209a21be8c97ee2fb56a169827b53cbc86" + "c4902e4f97c7bcf903a1934aea4c8979120d1e9480f36890" + "a439f4686aa390654e074f821155b96623585c939030f1b7" + "185632ab71febf33a50fa", + .r = "69e8c95b10f176e970088059cefa975139f63098fd1572b7" + "ee198569f40de0c0f165e60b5f2041e6cc3f6561fc26325f" + "0c73759241cfcae05f5dfc986", + }, + { + .a = "286933c1c00f2b660e3fe32ef6e83860802f604833db3b71" + "d3dfb4159832ddb6b8c523b4dd97a638153601a00ef0277d" + "afcd4672ee18270248d330370e2b3680fa6d45e2589f9737" + "a1598116771404cc0f6fa", + .b = "236d98a863512a94fa2596fcd9f8208b3443fb57c21bdfe2" + "97057ce9d71060cc6d3d5cc8803ed478f08b96e1975e4cc7" + "8dcb4e51a0f815b758ac30f505da9d3bcec9bd95e58cc7e", + .r = "28da8edc8852c39e8ecd24e02e049bf949018e6cbf56da50" + "106cd851f68aa25eb010e5e07f3bc0890d5437bfae851246" + "69d2272c6c86d470c54b558f2", + }, + { + .a = "a1f7a323d50b847d125780718fba3e18dc0d27dedd4bd564" + "1a1e77d4f135ba301d9e35e0a64636e02beccd74dcfe7dbb" + "aa887e81d70cfb20cb29b7f01388cf03574bee3b662c06e1" + "729b24b3661baf9897c5", + .b = "b69a7319b587f4ddfbae74df4f9150d294378dcf72daad7a" + "1457f22a0d3d06f440b336e5235d01ad0d5701fb89bcd32d" + "91dc6619453ff97efec1fad9327b75d611d2f5d6e92b21", + .r = "bfbc64ece94c37370bfe82d8e6a0251d01aa25ca8a24eb7a" + "c2a46436bfb1bed25bb7461e33dbca024b5630b642566abb" + "9e9885e376ac5e2918370fbf", + }, + { + .a = "580c74733e7398fc4f93a09607019a42520d56a192197917" + "461fb30901f0d1cc51e8ad0fc811087193d99df741275886" + "5f46e78373f104531a3847bf474b28f56a5676c958768394" + "54634afe2973cc9ffbc3b", + .b = "4f616036bea3ee473e1d48729f0d8d0a1f6eff21ad44737a" + "9050b6e974fe2d83593025c34f69e95285631e3e18b50962" + "f85f2966a77975cfc0850bc2859fa595f563def7e253495", + .r = "5c5adfa84bfefd45bd3de3e20e061559bae05d2abd5fe44f" + "cc33068bf024f905f4898bef8fe95cb454d42a0bae6d7113" + "ef5cee3dcdc6918271af159ef", + }, + { + .a = "698290f68e55de40eebbeffdb5e85ee1c90b9b26bfde16b7" + "e57f6d49372d28b452b740cc0151ad03f4a4cdc620d4ecc6" + "ca4801532302aa6ad15e95f03ee47b364c51025560b3e4e", + .b = "7c154bd23d9802aaacb972cec50ee01e0cd238d99d52acdf" + "6e423fb2d25a8d43d48c190a98722bd1dc9ed362572552be" + "849525a75808ed1858301fde5ede16966aaee47b96840725" + "f0959af32aa06e9456b82", + .r = "7f9b685607df0eb284c13f737512dc08fc285924763cca08" + "010271ac23a1e3beaa6bbe99d4b0123172315084fcf38bb8" + "05d095248901f3b0aac02d4c2", + }, + { + .a = "2d0508ff787ed77aae3eec5f3b653c16a61e5c2131484a6a" + "76c8f5c55a3fb8892cc944746d88d6df8a173934a3b08e33" + "ab661013ea4cac984e7702c480121cc0a61e9a84b8cb790", + .b = "2d0d2615faa6a3270be7838e2113f003257db1301c1733b1" + "c0e7b6ecbfecd7df5025aca3ff20424029a0be85400b17a0" + "10e3d3bb2d68b869b8e3ca35e2ca578707f41ef94d1cd5f5" + "6576cc6585ed9e98f3d30", + .r = "31f493348ec0de8a0b395765ec9e0a2c53fcfeb860b7f491" + "5b97d5501a7abf7a231d8b51b0a14d403a0c33614c2bf64e" + "871540ffbed0a5c71228c9af0", + }, + { + .a = "63358d19c542aeb26102faa596947f11a4b855390eca13a0" + "5de52db574a62508f6f6ceccc465d354129670206e28ed00" + "233fbcdfcc39d33d381dd2aa085d1213b543264757e01f43" + "5", + .b = "5240f1b49d6adb2bd9e56f356ff3be942989b83a35fa88cb" + "4b1807725401d82353e90e44dcefb7d485e7c0e0e8761ddc" + "7fd082754b0c8ecb157f26efb878bf39db5afeee008bac7d" + "c04512e3d5cb1aa85edaa87", + .r = "6d728eb98af7b75867fe8171099636251252e3aebdde0ab3" + "8e61da18162d7d3f9424cd4cf5952b6fca88ea01b52118ed" + "415123848a78f861a9c5ee89675", + }, + { + .a = "4b1a96b626c403e74398c96f775cdf543313d7e5c30f3200" + "da045ddef99606fb3e06a0cf102c315bbe544684bc97e0af" + "25c63e95e96cf79d488ff0c09d3bf476871bd2e16193193b" + "cea695c9f7b5506ca32c59b", + .b = "53b13941fcaa37b2c6488181b60a22f77ff393613bd75ebf" + "9fd887e7f3a45c40b081d164f9cd694c96ef585623a75b94" + "4f9852d74b707d074d16ad35913035ecd50dbdce84def4c1" + "9", + .r = "5ac217cda9a3e134d89a18453518a3e305b32161ff87275a" + "c038066f3bdfc755cd27b5096fd0b467ad050f2fc0b621cc" + "e0a5ba13cc43066bdfcebcafee3", + }, + { + .a = "2e9c3add5fbc37e68c6ecb0d69893a6230c96097d703c6f6" + "44ac81f78853e7fe1c153e31c332515363e1fc3d116103b2" + "1edabf3f9267a2a8b859256acbdb5001bc81bec6e75817d6" + "a", + .b = "28ab95367724b0d6b25899eddf97bff39af736f56ec36b58" + "8b2c79d15d0f7b83e6c002c8ab93319a004752b9ae65edbb" + "14ec62070a24b1d7c982da5e8f278e4ab4f5ee794777a0ba" + "d3251551c42e9dec1613d96", + .r = "35bae327800c8ab846e8a3ff9e2065d49843562e1053b305" + "419c722fdfc60facd8b96b361497ea6208c1e113733f94e3" + "dfade4850b027c4e29361acf1fe", + }, + { + .a = "28d49ba94cec96bcd7c4c4b648fa02fc964253c91b3f8055" + "9bd301eb085239e0bb81d27a0930f67d31da8e0800fe00c3" + "110206ae5510c198c7ca8455e81cbbfe2da668a94275b84a" + "9a7622cae01b9218fd38665", + .b = "25fa6fb38d020d435dab152bc5f17d9ce691fe72d6c02047" + "464d2812a51728a5b021a1dccb8699c18b2a96ae7ba7905f" + "c03926debba4c1832cec97b05ecd3d1810c7249d15a82dbc" + "d", + .r = "2b4f6fe0b050b6b25d1c45cc405c1b826fae754bdf2ebdfa" + "67796176e627df6ba640e8a1b423af7bb4b398b0a90a6dbc" + "7188f88814fcab190921a455087", + }, + { + .a = "211a642e3def54b03888b99bbd5ba647232038dc9a570283" + "1018dfe3754088d6698ef224d63545c0605abf884e979f6d" + "45135895794fccae82d2cd3701059f621d9f7dad15e1f226" + "d6730f64b83b88214ae4b79", + .b = "2224220d00b674d4c20d71b7c3f3eb4c0477cb760add9e1d" + "9a142f7fbbfa6f15103365902c5b9f71cddef2f7e73a7ba3" + "6c4cf6febca1e8164c4244af2def72c61c73b7ee84d2668e" + "3", + .r = "280c8c13bfe857fa3522cbb70d5c04f0d998a1e8847dda48" + "f7de2a9387a2a2c25b731e5f4750e8337841b897c73618ac" + "e8869a75d1394fdfea8e773f2f9", + }, + { + .a = "4994b58f2a35736e189646223fe59b96081e41138a136f81" + "802d7260c251e9ef469f328dd791df126f4181a848ad08f5" + "9b0b6f6714b77387039be2e24b0a45f8b870db8a32e572e5" + "6", + .b = "53dbd859b1980b52a856a182bcad446ba31e9e38c8f38239" + "9787ade90ce668230fc79d8c9ee37ac58b4ec70d09b2d96a" + "7dd434fe13950da2d5d89260fcde8437da73896f4e3edc91" + "9e7eaf24e68fb83cb3f13a6", + .r = "5caf1894f182dbc7729b357e28a8485603bc4d4d73ca64e6" + "9dcdbb5ea37ab9534c5caed7896669fe36624011b29bc26c" + "e7fa14520e4fe6b9bf49c581b8e", + }, + { + .a = "4e9d6310d7f9107cd13932e8fd8d123529e7f1c1be039c77" + "7cebbc80fa688158c55fff8cdb7bdaaa605c234aff554b0a" + "76a93eb7aa6133a24e462260d6f407280f4e6b42978bc2b7" + "f99ee90a835fc4abaabe12a", + .b = "566140ad10242b4c8661e010188b30f6bb119f13d91ba8d7" + "80b3d7027551d50d4dad1bd8a2a941f016f9949e67f63675" + "33ccf7badf855598b792c69c18f6e78dee8d310d42716dcb" + "a", + .r = "635ebf35796abc2d75157ca5244cef21dd30f3de6d6a0b09" + "f540e25d28a4c24e8cbe0e8041015f818da03ab383ab48a3" + "f8bdd4cc724bbf01c05a076300a", + }, + { + .a = "3d5bbcf58d4674d72427fd547b4c3a04363549248d086c00" + "a6d7bbd4bcbde6d709db692514346c347096000f3819937c" + "29a251dd0f4709ea1823566ae73218ee7134bfb2dc4f4d71" + "6", + .b = "384b1ee7d2f374c44125d327983f5616a1d3a980b0451f1b" + "53bc5297b5a9110b104b7785b3ae44efc4bc1f188dec1081" + "3ae93366f10e204e9aefa65923fc08baea8c8d8c9ec6dd16" + "c25ffe541b0666ad1983832", + .r = "49b1f9b8a8be2063c6937252ad20c082a2baeffcf4495d51" + "875f49203a3c4e87df4e8f386d6ffea8f247a261be9d453d" + "be646ec243f44f3a86074a80b92", + }, + { + .a = "2f4f1d590e2344a8304c0da12ed20d320027447352a6c91f" + "be0910aa7b22176a52de2a743ee00c970af26d4d6b17ee65" + "b5733a6762c4a910a90e34b223852f1570217677e5391f3e" + "450", + .b = "3a9055f97eb776d220bda9012bb25b2fb333d692b4a64df8" + "465e2b4c4e92937e0c2da20df98aef923f2ddf775e89392d" + "626759563dba5c9b9c0bd4e72c43840873322884687d4f82" + "c17e78e8f23047c7e486436b0", + .r = "3eb0196e0434c7973e4184ed035a3dfb7b22537dffb54e7f" + "318d399e34318c098240e2b12490cc36587630abe98683d0" + "b525f6000cd29faf2311d047d7ff0", + }, + { + .a = "362e74a668ad43cc6a7b5205fcd03142a012aef0145b20a0" + "13e57019ecfc0d8dd82320991fb55114ea5a355c69220410" + "3a5ea3c17763bd095098e16c16a778b37e312bcd0542dad9" + "f944c97cabea1e4c4b8253a67", + .b = "3349ab6445ba4fbf835b4acb058afcef4c4cec07fea01935" + "dd99708e29f6929c63c7403cdd665b055f066e7a32d27cb9" + "45af3db650525bbe6cce328e48c7df688fc671f9dec68e8b" + "633", + .r = "4142e2681e3d2a70ba3651a484d2526af26d8e9945ed1ae2" + "2a6a6edb8ef6efd3623b3fb972e992ff29c8b0ed34c69259" + "c8a3973f06b667306ed2fadd6825f", + }, + { + .a = "6259d0352e249d1288eb6321e88fa4c2ff6372e6bdcd744e" + "75175953185e3d04b315c6cdea3e443bc0d07236b2b545d6" + "c02740fb1055d6cb8dcedd7fd603ef0a58204de4f717c737" + "8d71ffd215ae50c226585ef9d", + .b = "6451bf96dfda1c3624bc3face722a88fe80cdd859c9fa6bf" + "5d7aaf8017ddf75c53e1542c4c18b436abd6585bcdc20c91" + "34a227cd3d758c2d715be9762d2b310d8e302ba7802ac6bb" + "2d9", + .r = "6edc27a1e26484474f1b8989e30fb334c40fef25b5b0388b" + "8984d36d7376f0ca903572b6bbaa658c4fcb06bdef18b8bf" + "231344e15d656b79cb9af46a2637d", + }, + { + .a = "29c1dd0b414e89c92df099bcc0368148bd9da74cba13ab75" + "69926f43c155bb73c224eff597c168da1a3482c1eb5fdacb" + "3525efe8cd760e75ae4f82a9927744711ad4aedd9678207a" + "5c3", + .b = "2725f9ce0e76a58de38b514540a785b5f81b6b477cadc764" + "e451d4cfc672ffe8b45708674d8677355519b4fac1b2e205" + "2da08bb71e0302fb9b0539e5a089ec820934a7fab8a67f1a" + "cdfd284cb4d1a47a0fb6d323d", + .r = "2a112329b5a954fabcd561681a5c706baff6c5bc63409d5e" + "75f92905b8556dd9a413c066d06de375e0673881e03d2de5" + "ba0ef77162eb00b6ff38b3a3d93b3", + }, + { + .a = "6cbbcc9a66966508df9163db9047397c268dca3bb912c7d0" + "0d6f648c1d7d1e17bb401428f1f35e228ddf31a1eeafa6a9" + "ad423d8a568cf53b8295f18445d5659bdca6546b3bf486d0" + "742", + .b = "6d1caee6688280ba580c2be1f6a05e46e8adbcde74f0eb20" + "415b7e7a1d78392adb45a9568bd2d75154fed048aa63223c" + "f07dbe02b17e80ef1d849e2deb22355f564e950640dc123b" + "eca95514b77db9569a1fb8742", + .r = "7b73d174ad87c7f6929c0ff8cfdd46216ca8b52d9af14965" + "372989b353d9ece7225447637beebf9a3b4dc5c55fedb01c" + "462c9869cffda467450d5bfaa6e02", + }, + { + .a = "2ffb47c34f03a353a71fcd0407c23a0907fd8f9699e6a79d" + "4c498c7b7c21635da7dd9c6bb1b6c2ca7a1a9a9f8cccad9f" + "df7e9692298db418bdce2d0a0b2eef85b0a8bf2e669443e1" + "977", + .b = "3167566cc4a6b4394bbfa428b59bfbd481c89f0297510a00" + "06f8525bb254618d0f9fb5a7d7b6896118f084ee67e904eb" + "7e058353ccc8284802dc4e4be387aa9e51fc4f037b800de9" + "a134c5d3718d8b357cecee8f7", + .r = "34a0e93f4d59795393a404dfc5be097ef284c02b3f431e03" + "2850144f7b9f182a1968f0419b62897dfd68bc556da82d7d" + "4bee27efa7441a57f10ad3a969b7d", + }, + { + .a = "2b5b70d4b8acaa1efd052d536b2011fd6f9e4537cf137ead" + "5ea8e5a9290e1eeb798184d6a03ded2c300b1a2888fa0953" + "31c19b46ab58c131831664120d5ecdb508617499b43d2e84" + "48b239e907af8310e551fc9ca", + .b = "2e28a7ae1bb29b3c58a9958f4861eaff3ed846ac0fa1a97e" + "c413e437c8da9968de78b2c3d7e8ebedf359de341562f243" + "c4c4b2307af6f8b8783d1ea71ae86aab49b2da6c95e58aee" + "80e", + .r = "2f731e7066df73cdfafff2f0c05435593fd49aa6c57ad125" + "1927ceabf03a4a19f97102ac81607b8448d74ea340017b4f" + "e1b2b8a3428066cc7a9163fc774e2", + }, + { + .a = "1f502837bbe73b0fea089bba9cc9951db97ce193168acb55" + "c9d10465524feb504e1a07b0b084e1b43e8a638cf3072b70" + "4d134b6f3922918979651ce87aadb83d84de661569ffb63d" + "44ce00e1b0b0d2e95a917fde4", + .b = "2023c2547a2c3c4344046ef7fca206ddaf19f348747d41ff" + "7631592d81059726324e90a8bff168f5ee920f6a39dbcfe0" + "52efe5507a45ab92134124da25f3e13c7addd6ff6c18c6d7" + "a54", + .r = "286972b401a798a475640cdf1f12a08ef72faa75eb2b9560" + "db47d7c9c6ef3a7a509bf1abde076f599cee0fefc031c043" + "115427e8c030205f469879ec18ffc", + }, + { + .a = "2601371a98307e3e57ff5dce30264ff73dc3597a1c10d06e" + "7024e3a553455c77470eef23ea143a5baf1980439603d854" + "c854e0c6ab98dc517da6e52cbbde9821ab4f2669ca5cdda9" + "7c64", + .b = "293f63a8d23b4a57972134d1fd5808e7cae2e69756ad8fcc" + "c5582950e50d39f860f1c68805c07bd56be1bb3bf42c3323" + "c78547a51f5e69bd52676c0d92d7e595d1ef6fd9bf0895ac" + "588f18ef54b6befc24a7ab4014", + .r = "29986146c05bb389e166d704f15fe12df8dc9797512c5863" + "6c2a88c32dc781a1d8b2e494bf69a8fbfce90f29a7159cc6" + "fc5bddc6e867d456c8d9fdfcf3ad54", + }, + { + .a = "60d0b1fee7def86c82f63bd34fef4daf7342dc1b7a957874" + "bb74a7c2b468418a85a05bb320b87d1608ba5462d1655cde" + "b21131889a22f6f5a8bc80780af967f366c94fbb19fa2db1" + "020ee", + .b = "6d006a52efe8d29184eae98fb77a073be1410cbd17149372" + "a8a58298cf94c39062914d7d9696b20b52d256639f0c1d5c" + "bfdcd3fb61c21c2dcdac746b927ddc8cf8ff4f4c40bfeeb3" + "b797e5440aa1040781859b9cf22", + .r = "7cab7c05cbbd2434ada90d92153bcb0c2307d9cf9e97b183" + "925d0993cf15cd10c4a559f22e7a37569fdf2cbaf06a664e" + "295cb75ddceeb76aba71f5c6186c36e", + }, + { + .a = "6b65db8f217601560b67966fff62a85326a355b04362373c" + "b75b61bf72df96ccf564e776a9e260df527619eea83e2134" + "2a4aa260e21267633a335d5f1e423d57382715ed19757c55" + "6b8a6", + .b = "6de2dc6f6d0ee1e9e51bc8f32191af47b123bc6b91fdaa82" + "4b541bfbadf38d5f0f24498378aa1e1a8c8c2f58acda2ae7" + "29d85b2760326806b9075293908cee6e7a6584fb9a48cf61" + "30645512e1ee3782fdcd5b44402", + .r = "7686fcf9c12c8d09c554b47747cb85068829caa4cadf13f2" + "a6e51b1beebded15f29c3b5811c7a520d2789c8e38557d96" + "a942f083aed301fed8d55380993f01a", + }, + { + .a = "47eceb53ea1c6f9bd9710e5b441d7b8aae96074ee598100b" + "5fe1a6d1da97a34175009b0b70403a1bad9ced6a669c8989" + "43ecb37b7f1fa9b2f6961f8ba948e26b9b6348f135aad8df" + "49e24613b1d2564d0955c6d9b57", + .b = "36a85b25a3519226e79420fa52ce09ab7bc251334b47a1b2" + "b5ba8e6c57e95440f4c29ea43944b0f7021c2997a8d9c0bd" + "ee01976d43e3b17c255adb3b2ce39cbe070190e995dda8ae" + "33d17", + .r = "482139d04fb1265200bb6dac1053e701e2f380deadf3d879" + "fdb290ca71dc1be05acadc1cd92c859f5f102b2497e32821" + "4a8ade526ad3bd6f75b01dbb5221cbf", + }, + { + .a = "4e776b04968be7d5b36f76f639c69655c3ae7e6dc631dee2" + "2953a6b0ba71641ea0737f0d20d231d897efb5d6c6611607" + "d8ac4c2603c414ce2c050d7c5af793645114c239ae3e82b1" + "703314f365abfd17ebe304e3e02", + .b = "40dcfedd9e92687615ca5ebae237e2c6518e81c2bcfe5a16" + "1dc4040e8ca08da86e8b13a2c7e81830ba4194bf1da4ade2" + "6574c799c59334978b1ea0b4fcd24835b78436b20a288f7e" + "3a662", + .r = "539efa234b6ec2b3522f56fc3458eddc1f824c7ed5e69b61" + "ffef8dd721b9047b8e84dbba68c61496026b7b3225b52a37" + "7649853bf31996fe08cc1d5cc60df3e", + }, + { + .a = "6248530af91ff8a2512105605308371dd35ad4cbab53268d" + "f60a98f71b069570cea5f0d1627814906d78bcb2f0311d83" + "2da3747d865670c808d6e5561f9c57629a2a2fd0f97f9fe3" + "ef7b8", + .b = "68d82bcea9af58edf598014eb89d362ab60796fb6cebcdb7" + "c1f362791026b855d2d53ff21e200c5a6f09f8f5988b81f5" + "e5ac6eeaff8d40645c2610357cb17d7aa92b841bc0f8a62a" + "88796f971a90df96c9fd8ed9568", + .r = "71df33a8cd2b40bcc1cd88ab619f9be7ba598ee307e882d7" + "e3c3fe21006207d4027413375acde14895e4d6f531864398" + "df0700e19199e152c44a32312e1ada8", + }, + { + .a = "48a027241005fad8ad81dd613ec10404f19355fa0d70f838" + "df119556204fe6e37d2ca5691d0f6d1a46d2f60448960619" + "c542269e1cb159a8154976b01b7156ddb34644f94abfedd1" + "ecc90ce5baee6208587a79ef864", + .b = "5e06838a5e561438cecc8b5050e7b76f2c0a709ad75bbef4" + "db8a6766e7d08f4147acd0eb24f838274731070dcbdb3fae" + "f6806e06a765d32cb0ad4b9bcf938dd420e99a0c1850959e" + "068ec", + .r = "5ef23537d261c6701373d1b59b311b8d74aaab868c28c12f" + "c40c742d32f510516383527ba995526ca4ae14b1f0af8ec2" + "2f03db896320319fb5fd6f9aaad223c", + }, + { + .a = "24f02c53b3ceba7449b66b5b3fec9b0301c1ec94241f1a49" + "d6054987e8b15323f3e191b7a3bc2f58d3e5918fbfa2d6b0" + "a91a8b91f71070e42594fc4e9cb1ccbccadd0d39dd66ff6d" + "b67d7a5a0a4df91b5472bc00c2c", + .b = "2203162a0ac7281aa4801c56bd345ee940a3c56e75786cc6" + "94495214fb92e6ed32ebecb645c832f2f9414425e14f875e" + "d25d9b90512d391bda492fba97acd268fc81eb68f6b3288f" + "b3cec", + .r = "269cefdbbc38de2dfe75b1556db7819facd5afff70fe141b" + "0320907a0542e85582bcf724cd74a31dcca1f1e45158c048" + "7d15ff63cfaa19735b3fe2b794cb314", + }, + { + .a = "311daa474d338d72eba858a27a869ac50e27c00a98336ed0" + "79dc55a141ba10d4d2df9cce57c37fb623ab1acc3a908a3d" + "63bea88f2c88e9ea6291a03a983638d061ac4083990a489a" + "e8358314f98aa", + .b = "2f2dc2784c526989ce90674a073b56e1c698b72f34e86014" + "f6a5bf3ff45373192ba3ecd94b643072bbc581795d5ebfd7" + "73f685dc72cf17b744c3f4b1c183a4c9b15ad83cc835e27c" + "0253e12637e50519f4d936ae525eb84aaee1e", + .r = "359c38503bbc71801a6d09d4659fa3aee3eb9ba08aeae383" + "f283a91a563b27c075cd0b75a9eefe69ac1858f744cb0bdd" + "1275222460356f837598f3fc6db51b1b6bd56", + }, + { + .a = "4fc542ebb5dd54c2f75c4767b4693b59e46a7cddd3b1c034" + "92bd7c1ce9b99903189112669a122888ddfeba2abc2c5d84" + "0f6e6b3e652a3863265b618034cff081c55f0848082873fe" + "0860d6c458f32a5d090a56ceefc26d2f68c51", + .b = "4927608f0f371e47def5bc8602aeee09b98d8ffcc22332cc" + "755714695efff915eef1edc8f852cf1db7ad046e235d32d3" + "d5e0905e7a56d1cca7fe5996b10b65e77dcdd9c10a9a9f92" + "9ef6a40e1f899", + .r = "5c65d455c60362ee4771fa967eb6756a2c332262a0fb6edf" + "d5853b4d0422139aebbf60a87abcb1800b711dd6d3552a15" + "f657ef0f3d052a29a86c91feb98fc84c63e9f", + }, + { + .a = "420f9b7bc5385ff84114032b2fb8b6312a216fd86ea9426b" + "6b5ba622405b6bca3d38d41cc9892744d687e61bc7aa96ed" + "44cdd5f62e8f2ce900bb7bff4f3e3a3c40d19e47d7430c4f" + "b259d41806a8c", + .b = "45e49fd63db64eff1699c8c4cb518a4ddb640a4687589635" + "f9f03bae7af06e1ab608a230be3e536e7ecc236af9faa31a" + "b1bd91103b4c382144bd0c8956b32a57bc7d9cdbe996d305" + "646dae29d1c1358eff8b509f8b9d80108e2fc", + .r = "50ce5c547d5bead574e0e816d5165d55d07b9a30f9ff64e4" + "2e42333e3afc89deaef1b2f493b63877fdb17a37a6f5fec6" + "ae797d43d5ea9090b09f5bfd1ec2fe4fea8ec", + }, + { + .a = "44b8197d0642e796cd53c6bede2289a4b812c4a1b10b645e" + "819e8d079c41f6c14404f7565e2cf057a097395ecd789317" + "fdce049d6e19a4e4897df8c9af394bfadd61e2fd56b8cb34" + "04e1cbe933a63", + .b = "40e078cf89ac3fb2c4810cae1b443b669f7c5166f7537fb2" + "223ff70700df746f8d618cb9a455d5875a56e73b600ecb97" + "212611f42b255753048c6a6ef47ba91702b7709d5e72cfb8" + "b045ed808916937f1b8dc634cecc95b94812b", + .r = "4eed24653e77a9eca3fe2c1b63c3df278c0f4c0280985957" + "d6b004f66dcf6e39a9d74947d2af6ccffba2d7e3899b0076" + "ac2452b8e0270cbdfcf0649cf43a7d40b1975", + }, + { + .a = "76080bd59c509c12905beaadf568f83e5406fabaf03de198" + "0da2dbc4f7313d7d1fce50bab61e959611213fa50a348842" + "e98866853219b1aec55fecb4437418d218a9e159faa081da" + "d55340f6f4007", + .b = "653a2d3e6cd9fe2a6682652fe58df01102ea6afd799ef20b" + "5e59eb9b258fc48397f33f796a2e8d5708cd1f2f1bb78e80" + "91343bdcd8df1cd53b04b451d131933031b8670f57ef7e6c" + "79cd965edd09286e9114030f23cecb2802b03", + .r = "7625e3b21f93cac17b64759bbd6374c5b8f1794d42eb2140" + "169bcbff6f30c26727704a63f36c0af124f7c072337bd3eb" + "c1efe0deff13f498f7d52bdfd49e7d429c479", + }, + { + .a = "2165efdf206b9f3d284b1649b883fc4ebe19dd2eded07226" + "1ff33f63c76f0462fdf33151defc54c504fcc045ba6f7d8e" + "9c78e2ca866588e3260d831cb0a76f9574bb9c38b68f9f5a" + "7a8635ab69816cd357b8e9fe2a5e44aa0af72", + .b = "26990c66e29b1fc2fa5a27bf7027255c2a9269dc8564dc31" + "0e0b1897ec76be18a36c8ff535107a71d401048286d881b1" + "457e952f083ba5b6eaf21ba928523d39e7b5add8b92460cf" + "588fba4b641b2", + .r = "26f01c12ab3c84a7fd95926bbba5947df3f3a793c7bcb4d3" + "561546eb89e5204de6cf1cffd37a791bd0bc257beb0d4aad" + "2dc95704d0bbb53db71767911605798c464fa", + }, + { + .a = "4cd1da71ab1b7d0f0d2878d3d9afd4a65503f44ef1a5bb96" + "c672eee44baf3ba6dafb576338cdc58ce53dcef44adb96a6" + "916db259bbd6898e570b0cde7c104eb75bafec51d3afffb3" + "028b761e2ea3bbffc27446702564d43cac3e", + .b = "59ee8b7e46d672cba41db23f9a553be294b9576ae9eed5f7" + "ef2219814e85d92374def56b34a26840f79e475227e68e52" + "e0cb9c1d4028a5c4aba40560bc60cedc9f74f0bd9733077a" + "c51c2d9b5c26", + .r = "6051ff998a975b8d4afd44d3ff5991ea396ec2404262d25d" + "0bcbf143d4abf8e2e43a758dca2f8bf63e689429cedab262" + "1c82d299eb665aae5cffcf49887cb8ccc47a", + }, + { + .a = "3278327513e6660bf43bdd9c2f0503d1db14d1d011b20d15" + "035249dc68f402f2439f86e9f088299d6b4d72127f6710a3" + "5867445a93421a509087dbaea6cd8cdefb800116be932f54" + "838bddf1aef01", + .b = "3261ecbf9169630196e0b0edcc37c13503bbd96689be7a8c" + "fad898fdb62ba588291aeaf08c010c81ed36873d0b489037" + "1005bf531376dbdf91b8fa0a00519326103a2d231c33fe26" + "561bbbdb2d5e8cc8319fd772cea67d866fc3b", + .r = "421d0cd7cf2e36f148cab008dbe8dd131425d2e57c0c8dab" + "49446b570494e8f73508dcba47e2fd04ca795a1be21c756e" + "2eb72fcaef768ff7677b017e3bcce7af48a5f", + }, + { + .a = "3112ae572ed5c2bf9efb02d11203769de237edd54a7daeef" + "99a79f002eaf11c5f83ae6915b9b3903e7a1207d481900b1" + "cf7ef3e8bb0455a99d9ff56e2d44fe34a1b740f128aeaec5" + "7cda32fe1949c2459b0d0d8ab17886332129dfd", + .b = "2a07dae423f1f9dd41d69fc5aff306e5bd3553f08d2d088d" + "4bac224caa1c0f00525b4b7661d611cbb2a121139177a2f2" + "97ea52e7bcb4bd1670ec031da4e641b2d73dc25b80e79f4d" + "7ddd94ba401dbb5", + .r = "31da054252aff10a4cc955cacafd6a64a8a03e575c850b92" + "e7fb4eb591a887c424d59d77cfb9e7669ad27407f0d5ae53" + "5c097e281aa88744bcb5495f7614dee4f008169", + }, + { + .a = "5a99840534ed75cf3c48250eb21477027251fee776c4513f" + "162ab48f0fba91297c86e9181c55410dda0d2b9a9a88eb05" + "b1de88d5c0cebd9de8c30534c45e7a52c31b784d697b26b4" + "3d9ce287597559b", + .b = "5d00668b79b842c749fc97f756bfd23c4d93e32b1e45f33c" + "03a75ba6856e557ea44b07e6d5614833d7432304bd8a2e5a" + "d0669a9653550ce3d8fe1720c41aa5c8ef1ba841c3dec653" + "d7e627eb6f73e00d753540d8a3a716e437896ab", + .r = "76408d57c8d9ed78d6719c18ac1e5ceadbf9e440482b03a2" + "84ddcdbc2409f8c358fd1a68710632141ad8a53b6a56df02" + "ec6f344d7a329acb7183d42aa5f4908a15b03b9", + }, + { + .a = "1fff5661c3409cc5bb806df271119041576bf30437f579d3" + "febe68040124b4a8a80470c99831b91936544c540f59d1b0" + "f185d1ceb609219c05a922f30be429c30719c0bd8c332020" + "3bdb54f0da90f5cab3c2a90a341097369cd3fe3", + .b = "209b21fda82c9e7b5a9fce721e69e740a6aaed5ab49b6404" + "0ef4ef69e3b8604cc01d73c5274d5400890666a90e30a969" + "0600793f66e12ce64a63b5f330289469ba1787ddf90601ca" + "5783beb15663d4f", + .r = "20adb144f68ca15bf1b2c53e08928d98fafc2bc50a78ebd2" + "527b5311e76fc872b36b9e2b67fb3432e98b8dd02a1fab5a" + "36cf09a6c20e343ceadd377b1bc466c63439671", + }, + { + .a = "342ba5b58ce8c7bbd2e8e886bd9ded881c8974fa8ff330d5" + "370cedb0a15643f92441c822fd4ec520de49506b4a8fe3ee" + "a95e405acbf5e09421fe79e0b6808d98ea42433cc7835dbb" + "15d4a4b5813e851696d895cc37321edc016f1c4", + .b = "3db942a5261eb2554d8c07f49c9b4f63d7836374c70e1728" + "3e698093c3b35f7b8551a1d8398937e121d9072049dcf8e7" + "0ba8b689350bbff993da177cce0d98eb7561da786618aa01" + "f92d5399af1af3c", + .r = "439f3e885a5a4174c79b5f267480d8975e689bdce44724b4" + "fc035b5988e881119529a00aef3a25a46a7a8d3089b91651" + "7aded47b31ceec49fc12421e03b713436055f64", + }, + { + .a = "371e2bf2000f60628f208640c701ea4171d01828172d0c30" + "cde6c73e7751285ce32d3c7f4e3ec6898412ebb726dcc80f" + "687ca47b2e9d7a1767a6bd51c924e5a1ea5ad29b2cddec59" + "c832ab32ddae4b70a7811dd1c7800d8878ebc3d", + .b = "428146e53ba9e513544ec840520e6a3bcea1a34f598b5890" + "32302576e99cd54a8467b43a5cadde2562021b8717a730f5" + "cc7c450d64d1bb070020a65b2b9bcc9ef4dc3358cd6c6397" + "3b3662b9ad977cd", + .r = "45e7a46b06c582473292b42270e5d11cf5a4816cda22381e" + "d5adf05d8f071109f3d0aafd89da4fb012df63fb0bddf518" + "0e33d0d2d4b0f1a3ac2750c2219088e80e6fb95", + }, + { + .a = "174624f63c7f56165bd918816c6f9928e4a559e8ba011a9c" + "a3c2b3e54939622e8b54b92db303745a6e89f014f216ad7e" + "dcc6eab8c1178d1532831fb5c004a37064916b91cfa39b9e" + "5bc232b62bf369", + .b = "1902db596f7070d5dc3df09f805f3008fb680fd8eb572775" + "d2f562b4a37f6cf500e67d5d680bff68cf0aa456269c99e5" + "92a10b713eb3a2d160f2fc3ad1b66a99e60c441671ef7afc" + "fd05380181525eb53b9a86043d4698b2a65f6d", + .r = "1983b5ae26a2caf8c8e5f67ad020fbb72a97bc8c9a66c070" + "b76c857b84fa7679ac539b8478a937d0564d408f643659ca" + "5b6e3041eca6c166cd4dfe59acabd1304f2fc9", + }, + { + .a = "166ac1610f2feb02a26390da221b50c826931c98e94aa393" + "99415c85237f730e65c9c8d0b50043e96e62249e1fb39885" + "f4ab8cf2a9b77c1c8cfb95f501052da8e80450f0988967fb" + "4df550b692127ea82e10d168d3cb3715595a014", + .b = "19488565e24ac7c11eeaf77144b3d95508203e931eb9b7e8" + "0639b92f0ff337fff07ed97b4722b7f8814d071c5fa09260" + "7453069aa9708c431cc4bc2209ae30db76db8f248c5a4592" + "76f2438d9a2de0c", + .r = "1ac1ea1783caf51bf4ab0f40db6810354a0fa44e69770677" + "bf04602b02b519f64fbb150019cde0254bacfa365553afa2" + "1e1012fe4b5b4596fff33c84ff84cb9d4c047cc", + }, + { + .a = "5b75b6143a1c6cbcac489957ac2e43ceb1eaf389d6f40285" + "b167f0d6f01ef6dc680c42aa7f4b15c2b970b519cc2a748c" + "7d495d7dca200144f7b35490710d90f589c95bae6e2450b9" + "96d13d9cc1d1dac", + .b = "5e9a81924c38ae2f348d6b8d72fe1efdd831a0244801108b" + "1f9c37218a167bbcd699ad7709a3a4a6fadd10a2977161f0" + "2f4097c4614c904ab0a9cbf6b212505995cd2c369b4494b0" + "4e5ba0367b9881ccfa59645b6abeca953699734", + .r = "69d18f3862bc74145c45a988b81cf48e2cc03bfe96c34f9b" + "981012b15fd615c51d585a913340688db34ed8d52f4c52ca" + "945d58910fb63e927ca8058d88725ef986e0ec4", + }, + { + .a = "674701bcb8b7d1afcdee9861b2523a119593959acd7d16aa" + "ef2ad3509ec7e9cc60b91b833ade557d0276185244155ffc" + "9065a9341b281f6435b7d26d6caa6b39d475f919b5d8167d" + "048d1a5bb433da5bd0d4c5901b71d585c32047047", + .b = "6215d41d790981f440660c4097750c75c0b6ef765b2fc08f" + "d7caed2fc6305e84d751d806a3b469ec3ea6825e8bfc18f9" + "acb12ad29d099ad6009a0baa13a2bbb1776a567ab705788c" + "555ff3c59cd6848f7", + .r = "76a0f17a23014c2b2b4d06cd952086837c69c3da36bc8cee" + "d0d88a74e50dfefe4a8d294cc6ab52a5cee2859ee8ffb141" + "0dd1e4fe363035825401679aeab07ab247b67d431", + }, + { + .a = "2ad3d974fa2b64854fba3e82434a1df17390ffe49f984a77" + "ce7384a02e7fe7b4c77097187ba049699cfedd4d1372cd1a" + "a64f837235ca2f9bec822c822e9981ee9afc4ec4f666b37f" + "dba827c818306a34a5ec916857dfaf2b8b128d81a", + .b = "3353e8614d8b3c5c86c76006ab8fb3f1f0973a57ebe08d81" + "93a6712a7d180c6ddb91ba324239e399bb910105bf011f48" + "f13a9c6c08a11f963cde4adf41ce4bb88ce2f395b11fe2ec" + "b19ceaf98d08b19fa", + .r = "3848694f56c96a0867df3953f63d8b90a140c15b0922dc17" + "173002079a986e669a0f032ccae911a8aef52bea6abc0427" + "76d99aeb5cfa27d105bca7e2487d051f113e69782", + }, + { + .a = "5f6264c220d6716aaf0c345b02791a38ede3a0ad8a44bc08" + "6e2fcf001bfabae0028b2ffea988bf1c2328ff9b01524db1" + "659dcf2934c26be9c32205933f5334ff2220de1d7a8333b0" + "307ad05cd08b8bde423036e898e400c5e0cc887a0", + .b = "551ff6ad295ae1bce11f72540ef81f4233d1fb688708c3f8" + "2c92695e9f57be321dfb98cb7ece06cee2a191470209cb39" + "737f9465747378a2b6a2c01ae0e92b9e5e6d954576f25abe" + "957f4ad86a8d73ea0", + .r = "6b4c3708b48166f86d1701bfd9152d7455ac0b56024fe4d6" + "e947813c8c87d343a54a14459804fc951190a17134cee19a" + "1d6bcca81480ab030ff2c58f677976bbf96d2e4e0", + }, + { + .a = "29dc9a1cc77dad36cb857326121100f546dc63a624fd950a" + "5edda4361acc17af684faaf932a8a467233321a6966c3e61" + "29f490b98e2d463b9abcd4c34263042b7966953411e6ab95" + "4f3dabd1d94baf3", + .b = "32e7ae042092a898c8de2d016f3c9d9d88d534a11fb0ff37" + "dac04057e7093ee68fc6a1a9f2639fe69959d82f0109bd6d" + "f470869db5feece762683943c506ee79c7544a56a0da307b" + "9a02ffec03ae0b4b2797a5699fda4f17853a12f", + .r = "3376875790192ffc6c7981d34ce9a79e445ab96df93be276" + "a290745feef1f204cf826ab0029074ef42b7a7b207f78d40" + "fcf5c639a1fe2492cf0bdbcf69b6d0ce3bb05b3", + }, + { + .a = "1e0b1c983532babc965cdedc4aea20127d2110d1c6bf636e" + "b5384cb9a67059e3bab8ef56a28dc34630ca37fc126ed7b6" + "25fc1164f8dd06e79ac03cd6668dee32834e32abbe29e4b9" + "415c34f6b12407369", + .b = "208f4ba8619b531371a3359236423c217565ad6261992978" + "42e96a79b0ad9bc89312da9aba13acc17c7cbd12ee3fc769" + "e2473be10228f38e666afaefe868a9a960cff9e20fdc047c" + "e44b85d26e523a5acef4507da9c145f335ab3521b", + .r = "270744a30ad54fcc784ebb3ea9f8bfc50372c09ec5578eb5" + "8ff70118681efada3d75394a5ed973df0333a14573418ae2" + "42c5585b923bcfc6d10f1ee3fd1ca497553c7de6f", + }, + { + .a = "4a83938144f1565d1407f16a811c8fd217b594b210dbc259" + "459ec5fdf9769ee85878ebe617c386284285e7354898f5ed" + "2236d1f832c606e2e7598680c4d3a103730e32a700895f86" + "fa2ab0cf34af11b48", + .b = "424ee13ea5c95ff7e99889e3912b217b97975227c303f1d1" + "57c7f8147e239cbcad6a3dd28ffe8315a60b566b326b2827" + "cb21f0da1acb02a8a094415fec55f6a76ca47d7443608703" + "21e4db7cd1449892b57ecc2c26d8efd6a6bfab978", + .r = "4aaf2a59ebfbb0d69ab6e0b867762c3fe76c54757caecc33" + "3f2c4fc9d39edda28e1beb4bd7fdf35d27f8189bc8c76a7d" + "c1613c932b1b921fea1b1eaf11a8390cacc472b28", + }, + { + .a = "6c95db45eae9c3890c716013ac0e8c8093000c0030d6b7eb" + "d556e749fd6f253d31622c5b8db0ba41d1a0709e0ed5d2d3" + "1406d0cec72e7b78bb4a21c5480bdca95a648e8331a26ca8" + "5f67c442d9471860", + .b = "7de0f00b2f156e38ab5549ff5ba31e16a6cb843823a97044" + "7abd7542db53e78e812b4eb58d16df6a614a07bb590d673a" + "7208ebb98a0fc80b070c55ecfb0a6590f530daddc5ded569" + "b80aae255b9cda0b6058c2971474106319df77e0", + .r = "7e7ff05971d259d4c99403f85afb3236188d72bf350e2e2d" + "4c44be9b3a6c569ebf47e8d0dd55c6157a8846d49a1556fa" + "d3bb1e00b077bc2a01eab5a0790e0ffadffe39e0", + }, + { + .a = "4394fd57db60ab172f4c909cdb8f3ea434e2bc6adc1ba173" + "a087dda50d52ed530384197589a0a66dc3fa5c7e47fbbc77" + "bd1bf2064d70f6ae0ab33b8fab6beeb56c985baba93b6ee5" + "fe086c99c919e3986", + .b = "4940242edd9807e4ec93d363187f29ec73623961e851a5f1" + "176e62cf1de9d47e95d43fefa3e6e05a7de8ef3eef1fbe0a" + "e9ac7bf200f8d5c9dd7eb3acca2f1e5245790065e319f456" + "419bb208665aa060009300b9197ffd6000d810876", + .r = "5360c87629e74983d59adea5ec47b9a198b3c5613afc3926" + "b9ccdad58725f4e232b7b5f8963838fb1772338620ba9240" + "967ebfdb2e29aef289cfd0d50f7a7036081e42e92", + }, + { + .a = "61be17703b62e5adf51e2c388ee77758a80632adab7c3a0d" + "d56b86ce827242baeb8a2324490c3c1e1615dcf8518aa7c2" + "65983441c7542c896e71dd213fdd04be682f654308c05cec" + "3c14c8defff396874763f57687e54e32f4ce9d1434c", + .b = "522d15c2681543b7bb50d64526e6032bebf8cd452cb06f5f" + "0105616cc681eee2d522a86f683cd675082de34844ad7836" + "4555c7d2b1e960ae02826cdb4d80937bbfcdfa59d0cdbf2b" + "4c9a96dc35b5ecbfbac", + .r = "6534089f006b049c13da2253ee4057e2aac083ce0610de29" + "00b01eddd57f4ed13adda2146fbd37bbb443420a0e7a081a" + "015e82b9dc85dd6c2389ce55a139e96f6448a424e6c", + }, + { + .a = "b287e8ac4abad5500ebe7739682f6bcf324d1afb32d68b0f" + "fd0b689aecdcf61473947ab8cc84a0a8873fce752d7027d3" + "403ccc28e522aab65b993883cd781b68b7a7d20bbabbdf3e" + "93c02aab4ccc335e4fbff8135d7d55fb5fee349bc8", + .b = "abf36a5b8c6d09a3db1ed4cc037cb32072fb0812652bebb4" + "e7f0e194494017958cce507f64f1270083cf4855c9ea85ed" + "cd2f99bcb43dcfdff5e65ff2f6b18878999a646e67b10871" + "d767a014cb39c06268", + .r = "bcfa04e04d226734bb8794716a3a3424893b94724dd5e802" + "54adad60ee8cea7cf7e8d798aa1287462a43b9d337b89d2b" + "8e2dbda0efe829e8fd784d61f0e09df7cee9d9a108", + }, + { + .a = "5805113ca06a22d67bf70a022cb538560f1e48331209ec43" + "682117ee841f4b7c425f23ce05b9febfe1ceb76784f6ff8c" + "4022df8cf61625b95f02f5f8cbf9a24f885776ee0b10acfb" + "e9b6535ceaf6c592243", + .b = "5e164dba2f2ef870b086ee79a8b37b80aaf4d26c1ab53c1f" + "3de828ddc22e1820f5a7857de133684e95d9c0487270ac90" + "66bea466dc67a70a6f6f22687f35c159314eef3d5c4ee0e2" + "f18f1b8a98f270a71bd45d44de71025b1dc966618d3", + .r = "679f032203be069cd9d44729aecad54a5fd518f9582cf4be" + "a3ef0bd7e62dec0aa124369db4f68ff416700a6f052e83a1" + "aaf3dee6d31c8f34192a60eba7eb57c759686b53d3f", + }, + { + .a = "6133ca653e55b423bb47988e353d8500c668540f10efeafa" + "a08aa8b04894517b1a4ce8b0431c2a219dd6c738b878f3a3" + "ec8f55f975b24e3d56b42ac4b087200411afc3c6716402ac" + "9d05a3b5c099be9d073cea6b51264fab6b602c76efe", + .b = "52bca44f91ee3f41b18fd6286b91463c00a50f7ac5131d76" + "ac1dcc7fd60340a3f55357a364be360744b8699a83a4ac31" + "a5b7a6f9d9bd35da094e2d20a3cfb9d21aa3b573013d8301" + "cb8cbad78c811e60f5e", + .r = "61b7a3d5d104cc66dca872b821dfc45afc88f7e46010b538" + "83aff819e90d1406991b3e104c4842db52fe1bc97c8daf37" + "a0ae1aaf3faa02ab92645764cf9173160c80cde79ea", + }, + { + .a = "5ba6fdd7fbeccfe482b2f57cdac17d53d09a60bb76422fb4" + "22b4c7785ce7186c88bf33cba40afa8f74a2d66b195c7d3a" + "f49ffc436fffb2e32c4cdfb67253c1afa4898bcb5dcbe39e" + "e6288129c59cf16dc177d63d0bf02fe216c1fbeba9b", + .b = "5a1e35a1fa9ca5d66244af81b6a239d1d7b94841e38413ad" + "35b47fafb2d7509a30011e6d7a64360d4ccdb9f86d00a939" + "4721575f8fe9e23306ffe3059ef99447d09fd00f5c795d38" + "36c1dc663834da34991", + .r = "70d68f80fbeac749d6f0f718ba5a6bca7ca23dee2b7ee687" + "ba0e3be0f45941d0ee637b3e8406ea2aed4f1638bdb47f17" + "7beec21cab2e49d832d9bda5a9d3b62003d6429bcbf", + }, + { + .a = "58f54f7ea83715900bc82bd5fc183f926f0fef989159bab7" + "c3aa18fd186efd7fc79d2a58c0bbd8556c1fabb784975801" + "396089ffa82f59eff04a2557b532f99bd39e08f597e00d0c" + "c96eccf3618cc02ec57b592d4d019152b686bd84bac", + .b = "4866326c48b8226bec5aae93bc3b3b3fdac0a60319730efa" + "7d9aa373da03f59159d3ccbeb478dbb5393fd91c6daaad8c" + "28dc0187a59448847ad960648b8fdfc14f785f09e423c8cb" + "1c6cc5862b4ec95a25c", + .r = "5f4a880841ce22ffd67705b03d965c39517a79f8e8ab6669" + "482eef3966895a050c67cce16965f98cd53477aeac38a521" + "02a6274dba0f5d2f02f1d5f1dff5653db7ca109a9cc", + }, + { + .a = "6a0e2e61d2859ce130d11aff8a8a9cc0672d3cea86da2f31" + "4a6a656e13f4830826cd8a6044d1233f7a6d70cae35060ea" + "fb66ae062c7f4af5eff978da2c5c29421322ed65293dbe9e" + "1855cb2977bec2fbf20", + .b = "594a63062ee8b0b61f0143ed9237906010c17e6d03cfb2fe" + "675f13edc7f8c54770f25dbb275f3236a8fa3bddc10c4fa8" + "fe0b704e6c4c0ee29929d2d49500a4254903350cdc72b02e" + "dddf83964b5c382b4f12571fc4741fd5b3ac9c24a20", + .r = "6c4c28b2358329ee65678c92b6e9b31187d4ddd793f9af45" + "e780b723f63b82c287e2ab0fb06ccd173a9bec960667a47f" + "0ebd5a2ce8d1d0059500be32d67c8ab308e3e08fda0", + }, + { + .a = "b37bbec16572713e3cadbcbd2703c48673edde83d6ab5cc0" + "02c32dd693950f4c3965506c04cddcbd754f23245ce63f92" + "f5dcb926f40bbf08583de1a11047e0c2508b47d0896cc0cb" + "fbe031a5e9a148923e", + .b = "e8cceb9061392e35fd652346312aff143d88fb156695e0a7" + "f7b84419ca35214374733457d32517d0cb7c16c31a10f002" + "d4f2bd2fd4ee4ded122f1e221dfc989d0c8dd66deb1ac49a" + "9199290905db12c064d3376805451b969ee424a59a", + .r = "e9eb6a282f306af29a28df6d720469568183f136e58813e3" + "d61929b91f8538cf0f777fd5fb1672f0bdc4e59ccb9a4f79" + "16aabeba3101842a700fa4c08e758ec7169726d682", + }, +}; + +#define N_GCD_TESTS (sizeof(bn_gcd_tests) / sizeof(bn_gcd_tests[0])) + +static int +bn_gcd_test(const struct gcd_test *testcase) +{ + BN_CTX *ctx; + BIGNUM *a, *b, *want, *got; + size_t i; + int signs; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get(ctx)"); + if ((b = BN_CTX_get(ctx)) == NULL) + errx(1, "b = BN_CTX_get(ctx)"); + if ((want = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get(ctx)"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "got = BN_CTX_get(ctx)"); + + if (!BN_hex2bn(&a, testcase->a)) + errx(1, "a = hex2bn(%s)", testcase->a); + if (!BN_hex2bn(&b, testcase->b)) + errx(1, "b = hex2bn(%s)", testcase->b); + if (!BN_hex2bn(&want, testcase->r)) + errx(1, "want = hex2bn(%s)", testcase->r); + + for (i = 0; i < N_GCD_FN; i++) { + for (signs = 0; signs < 4; signs++) { + const struct gcd_test_fn *test = &gcd_fn[i]; + + /* XXX - BN_gcd_ct(a, 0) divides by zero */ + if (test->fails_on_zero && BN_is_zero(b)) + continue; + + BN_set_negative(a, (signs >> 0) & 1); + BN_set_negative(b, (signs >> 1) & 1); + + if (!test->fn(got, a, b, ctx)) { + fprintf(stderr, "%s(%s, %s) failed\n", + test->name, testcase->a, testcase->b); + goto err; + } + + if (BN_cmp(got, want) != 0) { + fprintf(stderr, "a: %s\n", testcase->a); + fprintf(stderr, "b: %s\n", testcase->b); + fprintf(stderr, "%s, i: %zu, signs %d, want %s, got ", + test->name, i, signs, testcase->r); + BN_print_fp(stderr, got); + fprintf(stderr, "\n"); + + failed |= 1; + } + } + } + + err: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return failed; +} + +static int +run_bn_gcd_tests(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_GCD_TESTS; i++) + failed |= bn_gcd_test(&bn_gcd_tests[i]); + + return failed; +} + +/* + * This test uses the coprime factorization 2^(2k) - 1 = (2^k - 1) * (2^k + 1). + */ + +static int +bn_binomial_gcd_test(const struct gcd_test_fn *test, int k, BIGNUM *a, + BIGNUM *b, BN_CTX *ctx) +{ + BIGNUM *gcd; + int shift, signs; + int failed = 0; + + BN_CTX_start(ctx); + + if ((gcd = BN_CTX_get(ctx)) == NULL) + errx(1, "%s: gcd = BN_CTX_get(ctx)", test->name); + + for (shift = 0; shift < 16; shift++) { + for (signs = 0; signs < 4; signs++) { + /* XXX - BN_gcd_ct(a, 0) divides by zero */ + if (test->fails_on_zero && BN_is_zero(b)) + continue; + + BN_set_negative(a, (signs >> 0) & 1); + BN_set_negative(b, (signs >> 1) & 1); + + if (!test->fn(gcd, a, b, ctx)) { + errx(1, "%s(), k: %d, shift: %d, signs %d\n", + test->name, k, shift, signs); + } + + if (BN_is_negative(gcd)) { + fprintf(stderr, "%s: negative gcd, " + "k: %d, shift: %d, signs %d\n", + test->name, k, shift, signs); + failed |= 1; + } + + if (BN_ucmp(gcd, b) != 0) { + fprintf(stderr, "%s: BN_ucmp(gcd, b) failed, " + "k: %d, shift: %d, signs %d\n", + test->name, k, shift, signs); + BN_print_fp(stderr, gcd); + fprintf(stderr, "\n"); + BN_print_fp(stderr, b); + fprintf(stderr, "\n"); + failed |= 1; + } + } + + if (!BN_lshift1(a, a)) + errx(1, "%s: BN_lshift1(a, a)", test->name); + if (!BN_lshift1(b, b)) + errx(1, "%s: BN_lshift1(b, b)", test->name); + } + + BN_CTX_end(ctx); + + return failed; +} + +static int +run_bn_binomial_gcd_tests(void) +{ + BN_CTX *ctx; + BIGNUM *a, *b; + size_t i; + int k; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "%s: BN_CTX_new()", __func__); + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "%s: a = BN_CTX_get(ctx)", __func__); + if ((b = BN_CTX_get(ctx)) == NULL) + errx(1, "%s: b = BN_CTX_get(ctx)", __func__); + + for (i = 0; i < N_GCD_FN; i++) { + const struct gcd_test_fn *test = &gcd_fn[i]; + + for (k = 0; k < 400; k++) { + BN_zero(a); + BN_zero(b); + + /* a = 2^(2k) - 1 */ + if (!BN_set_bit(a, 2 * k)) + errx(1, "%s: BN_set_bit(a, 2 * k)", test->name); + if (!BN_sub_word(a, 1)) + errx(1, "%s: BN_sub_word(a, 1)", test->name); + + /* b = 2^k - 1 */ + if (!BN_set_bit(b, k)) + errx(1, "%s: BN_set_bit(a, k)", test->name); + if (!BN_sub_word(b, 1)) + errx(1, "%s: BN_sub_word(a, 1)", test->name); + + failed |= bn_binomial_gcd_test(test, k, a, b, ctx); + + BN_zero(a); + BN_zero(b); + + /* a = 2^(2k) - 1 */ + if (!BN_set_bit(a, 2 * k)) + errx(1, "%s: BN_set_bit(a, 2 * k)", test->name); + if (!BN_sub_word(a, 1)) + errx(1, "%s: BN_sub_word(a, 1)", test->name); + + /* b = 2^k + 1 */ + if (!BN_set_bit(b, k)) + errx(1, "%s: BN_set_bit(a, k)", test->name); + if (!BN_add_word(b, 1)) + errx(1, "%s: BN_add_word(a, 1)", test->name); + + failed |= bn_binomial_gcd_test(test, k, a, b, ctx); + } + } + + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= run_bn_gcd_tests(); + failed |= run_bn_binomial_gcd_tests(); + + return failed; +} diff --git a/tests/bn_general.c b/tests/bn_general.c new file mode 100644 index 0000000..622cbaf --- /dev/null +++ b/tests/bn_general.c @@ -0,0 +1,182 @@ +/* $OpenBSD: bn_general.c,v 1.2 2023/04/11 05:53:53 jsing Exp $ */ +/* + * Copyright (c) 2022, 2023 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static void +benchmark_bn_copy_setup(BIGNUM *dst, BIGNUM *src, int n) +{ + if (!BN_set_bit(dst, n - 1)) + errx(1, "BN_set_bit"); + if (!BN_set_bit(src, n - 1)) + errx(1, "BN_set_bit"); +} + +static void +benchmark_bn_copy_run_once(BIGNUM *dst, BIGNUM *src) +{ + if (BN_copy(dst, src) == NULL) + errx(1, "BN_copy"); +} + +struct benchmark { + const char *desc; + void (*setup)(BIGNUM *, BIGNUM *, int); + void (*run_once)(BIGNUM *, BIGNUM *); + int bits; +}; + +struct benchmark benchmarks[] = { + { + .desc = "BN_copy() 32 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 32, + }, + { + .desc = "BN_copy() 256 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 256, + }, + { + .desc = "BN_copy() 320 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 320, + }, + { + .desc = "BN_copy() 512 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 512, + }, + { + .desc = "BN_copy() 1024 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 1024, + }, + { + .desc = "BN_copy() 2048 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 2048, + }, + { + .desc = "BN_copy() 4096 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 4096, + }, + { + .desc = "BN_copy() 16384 bits", + .setup = benchmark_bn_copy_setup, + .run_once = benchmark_bn_copy_run_once, + .bits = 16384, + }, +}; + +#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) + +static int benchmark_stop; + +static void +benchmark_sig_alarm(int sig) +{ + benchmark_stop = 1; +} + +static void +benchmark_run(const struct benchmark *bm, int seconds) +{ + struct timespec start, end, duration; + struct rusage rusage; + BIGNUM *dst, *src; + int i; + + signal(SIGALRM, benchmark_sig_alarm); + + if ((src = BN_new()) == NULL) + errx(1, "BN_new"); + if ((dst = BN_new()) == NULL) + errx(1, "BN_new"); + + bm->setup(dst, src, bm->bits); + + benchmark_stop = 0; + i = 0; + alarm(seconds); + + if (getrusage(RUSAGE_SELF, &rusage) == -1) + err(1, "getrusage failed"); + TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start); + + fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); + while (!benchmark_stop) { + bm->run_once(dst, src); + i++; + } + if (getrusage(RUSAGE_SELF, &rusage) == -1) + err(1, "getrusage failed"); + TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end); + + timespecsub(&end, &start, &duration); + fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i, + duration.tv_sec + duration.tv_nsec / 1000000000.0, + (uint64_t)i * 1000000000 / + (duration.tv_sec * 1000000000 + duration.tv_nsec)); + + BN_free(src); + BN_free(dst); +} + +static void +benchmark_bn_general(void) +{ + const struct benchmark *bm; + size_t i; + + for (i = 0; i < N_BENCHMARKS; i++) { + bm = &benchmarks[i]; + benchmark_run(bm, 5); + } +} + +int +main(int argc, char **argv) +{ + int benchmark = 0, failed = 0; + + if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) + benchmark = 1; + + if (benchmark && !failed) + benchmark_bn_general(); + + return failed; +} diff --git a/tests/bn_isqrt.c b/tests/bn_isqrt.c new file mode 100644 index 0000000..d8a2d27 --- /dev/null +++ b/tests/bn_isqrt.c @@ -0,0 +1,330 @@ +/* $OpenBSD: bn_isqrt.c,v 1.4 2023/08/03 18:53:56 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "bn_local.h" + +#define N_TESTS 100 + +/* Sample squares between 2^128 and 2^4096. */ +#define LOWER_BITS 128 +#define UPPER_BITS 4096 + +extern const uint8_t is_square_mod_11[]; +extern const uint8_t is_square_mod_63[]; +extern const uint8_t is_square_mod_64[]; +extern const uint8_t is_square_mod_65[]; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static const uint8_t * +get_table(int modulus) +{ + switch (modulus) { + case 11: + return is_square_mod_11; + case 63: + return is_square_mod_63; + case 64: + return is_square_mod_64; + case 65: + return is_square_mod_65; + default: + return NULL; + } +} + +static int +check_tables(int print) +{ + int fill[] = {11, 63, 64, 65}; + const uint8_t *table; + uint8_t q[65]; + size_t i; + int j; + int failed = 0; + + for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) { + memset(q, 0, sizeof(q)); + + for (j = 0; j < fill[i]; j++) + q[(j * j) % fill[i]] = 1; + + if ((table = get_table(fill[i])) == NULL) { + fprintf(stderr, "failed to get table %d\n", fill[i]); + failed |= 1; + continue; + } + + if (memcmp(table, q, fill[i]) != 0) { + fprintf(stderr, "table %d does not match:\n", fill[i]); + fprintf(stderr, "want:\n"); + hexdump(table, fill[i]); + fprintf(stderr, "got:\n"); + hexdump(q, fill[i]); + failed |= 1; + continue; + } + + if (!print) + continue; + + printf("const uint8_t is_square_mod_%d[] = {\n\t", fill[i]); + for (j = 0; j < fill[i]; j++) { + const char *end = " "; + + if (j % 16 == 15) + end = "\n\t"; + if (j + 1 == fill[i]) + end = ""; + + printf("%d,%s", q[j], end); + } + printf("\n};\nCTASSERT(sizeof(is_square_mod_%d) == %d);\n\n", + fill[i], fill[i]); + } + + return failed; +} + +static int +validate_tables(void) +{ + int fill[] = {11, 63, 64, 65}; + const uint8_t *table; + size_t i; + int j, k; + int failed = 0; + + for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) { + if ((table = get_table(fill[i])) == NULL) { + fprintf(stderr, "failed to get table %d\n", fill[i]); + failed |= 1; + continue; + } + + for (j = 0; j < fill[i]; j++) { + for (k = 0; k < fill[i]; k++) { + if (j == (k * k) % fill[i]) + break; + } + + if (table[j] == 0 && k < fill[i]) { + fprintf(stderr, "%d == %d^2 (mod %d)", j, k, + fill[i]); + failed |= 1; + } + if (table[j] == 1 && k == fill[i]) { + fprintf(stderr, "%d not a square (mod %d)", j, + fill[i]); + failed |= 1; + } + } + } + + return failed; +} + +/* + * Choose a random number n of bit length between LOWER_BITS and UPPER_BITS and + * check that n == isqrt(n^2). Random numbers n^2 <= testcase < (n + 1)^2 are + * checked to have isqrt(testcase) == n. + */ +static int +isqrt_test(void) +{ + BN_CTX *ctx; + BIGNUM *n, *n_sqr, *lower, *upper, *testcase, *isqrt; + int cmp, i, is_perfect_square; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(ctx); + + if ((lower = BN_CTX_get(ctx)) == NULL) + errx(1, "lower = BN_CTX_get(ctx)"); + if ((upper = BN_CTX_get(ctx)) == NULL) + errx(1, "upper = BN_CTX_get(ctx)"); + if ((n = BN_CTX_get(ctx)) == NULL) + errx(1, "n = BN_CTX_get(ctx)"); + if ((n_sqr = BN_CTX_get(ctx)) == NULL) + errx(1, "n = BN_CTX_get(ctx)"); + if ((isqrt = BN_CTX_get(ctx)) == NULL) + errx(1, "result = BN_CTX_get(ctx)"); + if ((testcase = BN_CTX_get(ctx)) == NULL) + errx(1, "testcase = BN_CTX_get(ctx)"); + + /* lower = 2^LOWER_BITS, upper = 2^UPPER_BITS. */ + if (!BN_set_bit(lower, LOWER_BITS)) + errx(1, "BN_set_bit(lower, %d)", LOWER_BITS); + if (!BN_set_bit(upper, UPPER_BITS)) + errx(1, "BN_set_bit(upper, %d)", UPPER_BITS); + + if (!bn_rand_in_range(n, lower, upper)) + errx(1, "bn_rand_in_range n"); + + /* n_sqr = n^2 */ + if (!BN_sqr(n_sqr, n, ctx)) + errx(1, "BN_sqr"); + + if (!bn_isqrt(isqrt, &is_perfect_square, n_sqr, ctx)) + errx(1, "bn_isqrt n_sqr"); + + if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) { + fprintf(stderr, "n = "); + BN_print_fp(stderr, n); + fprintf(stderr, "\nn^2 is_perfect_square: %d, cmp: %d\n", + is_perfect_square, cmp); + failed = 1; + } + + /* upper = 2 * n + 1 */ + if (!BN_lshift1(upper, n)) + errx(1, "BN_lshift1(upper, n)"); + if (!BN_add_word(upper, 1)) + errx(1, "BN_sub_word(upper, 1)"); + + /* upper = (n + 1)^2 = n^2 + upper */ + if (!BN_add(upper, n_sqr, upper)) + errx(1, "BN_add"); + + /* + * Check that isqrt((n + 1)^2) - 1 == n. + */ + + if (!bn_isqrt(isqrt, &is_perfect_square, upper, ctx)) + errx(1, "bn_isqrt(upper)"); + + if (!BN_sub_word(isqrt, 1)) + errx(1, "BN_add_word(isqrt, 1)"); + + if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) { + fprintf(stderr, "n = "); + BN_print_fp(stderr, n); + fprintf(stderr, "\n(n + 1)^2 is_perfect_square: %d, cmp: %d\n", + is_perfect_square, cmp); + failed = 1; + } + + /* + * Test N_TESTS random numbers n^2 <= testcase < (n + 1)^2 and check + * that their isqrt is n. + */ + + for (i = 0; i < N_TESTS; i++) { + if (!bn_rand_in_range(testcase, n_sqr, upper)) + errx(1, "bn_rand_in_range testcase"); + + if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx)) + errx(1, "bn_isqrt testcase"); + + if ((cmp = BN_cmp(n, isqrt)) != 0 || + (is_perfect_square && BN_cmp(n_sqr, testcase) != 0)) { + fprintf(stderr, "n = "); + BN_print_fp(stderr, n); + fprintf(stderr, "\ntestcase = "); + BN_print_fp(stderr, testcase); + fprintf(stderr, + "\ntestcase is_perfect_square: %d, cmp: %d\n", + is_perfect_square, cmp); + failed = 1; + } + } + + /* + * Finally check that isqrt(n^2 - 1) + 1 == n. + */ + + if (!BN_sub(testcase, n_sqr, BN_value_one())) + errx(1, "BN_sub(testcase, n_sqr, 1)"); + + if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx)) + errx(1, "bn_isqrt(n_sqr - 1)"); + + if (!BN_add_word(isqrt, 1)) + errx(1, "BN_add_word(isqrt, 1)"); + + if ((cmp = BN_cmp(n, isqrt)) != 0 || is_perfect_square) { + fprintf(stderr, "n = "); + BN_print_fp(stderr, n); + fprintf(stderr, "\nn_sqr - 1 is_perfect_square: %d, cmp: %d\n", + is_perfect_square, cmp); + failed = 1; + } + + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return failed; +} + +static void +usage(void) +{ + fprintf(stderr, "usage: bn_isqrt [-C]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + size_t i; + int ch; + int failed = 0, print = 0; + + while ((ch = getopt(argc, argv, "C")) != -1) { + switch (ch) { + case 'C': + print = 1; + break; + default: + usage(); + break; + } + } + + if (print) + return check_tables(1); + + for (i = 0; i < N_TESTS; i++) + failed |= isqrt_test(); + + failed |= check_tables(0); + failed |= validate_tables(); + + return failed; +} diff --git a/tests/bn_mod_exp.c b/tests/bn_mod_exp.c new file mode 100644 index 0000000..14e1883 --- /dev/null +++ b/tests/bn_mod_exp.c @@ -0,0 +1,575 @@ +/* $OpenBSD: bn_mod_exp.c,v 1.38 2023/05/09 05:39:24 tb Exp $ */ + +/* + * Copyright (c) 2022,2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include "bn_local.h" + +#define N_MOD_EXP_TESTS 100 +#define N_MOD_EXP2_TESTS 50 + +#define INIT_MOD_EXP_FN(f) { .name = #f, .mod_exp_fn = (f), } +#define INIT_MOD_EXP_MONT_FN(f) { .name = #f, .mod_exp_mont_fn = (f), } + +static int +bn_mod_exp2_mont_first(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx) +{ + const BIGNUM *one = BN_value_one(); + + return BN_mod_exp2_mont(r, a, p, one, one, m, ctx, mctx); +} + +static int +bn_mod_exp2_mont_second(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx) +{ + const BIGNUM *one = BN_value_one(); + + return BN_mod_exp2_mont(r, one, one, a, p, m, ctx, mctx); +} + +static const struct mod_exp_test { + const char *name; + int (*mod_exp_fn)(BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*mod_exp_mont_fn)(BIGNUM *, const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +} mod_exp_fn[] = { + INIT_MOD_EXP_FN(BN_mod_exp), + INIT_MOD_EXP_FN(BN_mod_exp_ct), + INIT_MOD_EXP_FN(BN_mod_exp_nonct), + INIT_MOD_EXP_FN(BN_mod_exp_recp), + INIT_MOD_EXP_FN(BN_mod_exp_simple), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_ct), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_consttime), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_nonct), + INIT_MOD_EXP_MONT_FN(bn_mod_exp2_mont_first), + INIT_MOD_EXP_MONT_FN(bn_mod_exp2_mont_second), +}; + +#define N_MOD_EXP_FN (sizeof(mod_exp_fn) / sizeof(mod_exp_fn[0])) + +static void +bn_print(const char *name, const BIGNUM *bn) +{ + size_t len; + int pad = 0; + + if ((len = strlen(name)) < 7) + pad = 6 - len; + + fprintf(stderr, "%s: %*s", name, pad, ""); + BN_print_fp(stderr, bn); + fprintf(stderr, "\n"); +} + +static void +print_zero_test_failure(const BIGNUM *got, const BIGNUM *a, const BIGNUM *m, + const char *name) +{ + fprintf(stderr, "%s() zero test failed:\n", name); + + bn_print("a", a); + bn_print("m", m); + bn_print("got", got); +} + +static int +bn_mod_exp_zero_test(const struct mod_exp_test *test, BN_CTX *ctx, + int neg_modulus, int random_base) +{ + BIGNUM *a, *m, *p, *got; + int mod_exp_ret; + int failed = 1; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((m = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + + if (!BN_one(m)) + errx(1, "BN_one"); + if (neg_modulus) + BN_set_negative(m, 1); + BN_zero(a); + BN_zero(p); + + if (random_base) { + if (!BN_rand(a, 1024, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + errx(1, "BN_rand"); + } + + if (test->mod_exp_fn != NULL) { + mod_exp_ret = test->mod_exp_fn(got, a, p, m, ctx); + } else { + mod_exp_ret = test->mod_exp_mont_fn(got, a, p, m, ctx, NULL); + } + + if (!mod_exp_ret) { + fprintf(stderr, "%s failed\n", test->name); + ERR_print_errors_fp(stderr); + goto err; + } + + if (!BN_is_zero(got)) { + print_zero_test_failure(got, a, m, test->name); + goto err; + } + + failed = 0; + + err: + BN_CTX_end(ctx); + + return failed; +} + +static int +bn_mod_exp_zero_word_test(BN_CTX *ctx, int neg_modulus) +{ + const char *name = "BN_mod_exp_mont_word"; + BIGNUM *m, *p, *got; + int failed = 1; + + BN_CTX_start(ctx); + + if ((m = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + + if (!BN_one(m)) + errx(1, "BN_one"); + if (neg_modulus) + BN_set_negative(m, neg_modulus); + BN_zero(p); + + if (!BN_mod_exp_mont_word(got, 1, p, m, ctx, NULL)) { + fprintf(stderr, "%s failed\n", name); + ERR_print_errors_fp(stderr); + goto err; + } + + if (!BN_is_zero(got)) { + print_zero_test_failure(got, p, m, name); + goto err; + } + + failed = 0; + + err: + BN_CTX_end(ctx); + + return failed; +} + +static int +test_bn_mod_exp_zero(void) +{ + BN_CTX *ctx; + size_t i, j; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + for (i = 0; i < N_MOD_EXP_FN; i++) { + for (j = 0; j < 4; j++) { + int neg_modulus = (j >> 0) & 1; + int random_base = (j >> 1) & 1; + + failed |= bn_mod_exp_zero_test(&mod_exp_fn[i], ctx, + neg_modulus, random_base); + } + } + + failed |= bn_mod_exp_zero_word_test(ctx, 0); + failed |= bn_mod_exp_zero_word_test(ctx, 1); + + BN_CTX_free(ctx); + + return failed; +} + +static int +generate_bn(BIGNUM *bn, int avg_bits, int deviate, int force_odd) +{ + int bits; + + if (bn == NULL) + return 1; + + if (avg_bits <= 0 || deviate <= 0 || deviate >= avg_bits) + return 0; + + bits = avg_bits + arc4random_uniform(deviate) - deviate; + + return BN_rand(bn, bits, 0, force_odd); +} + +static int +generate_test_quintuple(int reduce, BIGNUM *a, BIGNUM *p, BIGNUM *b, BIGNUM *q, + BIGNUM *m, BN_CTX *ctx) +{ + BIGNUM *mmodified; + BN_ULONG multiple; + int avg = 2 * BN_BITS, deviate = BN_BITS / 2; + int ret = 0; + + if (!generate_bn(a, avg, deviate, 0)) + return 0; + + if (!generate_bn(p, avg, deviate, 0)) + return 0; + + if (!generate_bn(b, avg, deviate, 0)) + return 0; + + if (!generate_bn(q, avg, deviate, 0)) + return 0; + + if (!generate_bn(m, avg, deviate, 1)) + return 0; + + if (reduce) { + if (!BN_mod(a, a, m, ctx)) + return 0; + + if (b == NULL) + return 1; + + return BN_mod(b, b, m, ctx); + } + + /* + * Add a random multiple of m to a to test unreduced exponentiation. + */ + + BN_CTX_start(ctx); + + if ((mmodified = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!bn_copy(mmodified, m)) + goto err; + + multiple = arc4random_uniform(16) + 2; + + if (!BN_mul_word(mmodified, multiple)) + goto err; + + if (!BN_add(a, a, mmodified)) + goto err; + + if (b == NULL) + goto done; + + if (!BN_add(b, b, mmodified)) + goto err; + + done: + ret = 1; + + err: + BN_CTX_end(ctx); + + return ret; +} + +static int +generate_test_triple(int reduce, BIGNUM *a, BIGNUM *p, BIGNUM *m, BN_CTX *ctx) +{ + return generate_test_quintuple(reduce, a, p, NULL, NULL, m, ctx); +} + +static void +dump_results(const BIGNUM *a, const BIGNUM *p, const BIGNUM *b, const BIGNUM *q, + const BIGNUM *m, const BIGNUM *want, const BIGNUM *got, const char *name) +{ + fprintf(stderr, "BN_mod_exp_simple() and %s() disagree:\n", name); + + bn_print("want", want); + bn_print("got", got); + + bn_print("a", a); + bn_print("p", p); + + if (b != NULL) { + bn_print("b", b); + bn_print("q", q); + } + + bn_print("m", m); + + fprintf(stderr, "\n"); +} + +static int +test_mod_exp(const BIGNUM *want, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, const struct mod_exp_test *test) +{ + BIGNUM *got; + int mod_exp_ret; + int ret = 0; + + BN_CTX_start(ctx); + + if ((got = BN_CTX_get(ctx)) == NULL) + goto err; + + if (test->mod_exp_fn != NULL) + mod_exp_ret = test->mod_exp_fn(got, a, p, m, ctx); + else + mod_exp_ret = test->mod_exp_mont_fn(got, a, p, m, ctx, NULL); + + if (!mod_exp_ret) + errx(1, "%s() failed", test->name); + + if (BN_cmp(want, got) != 0) { + dump_results(a, p, NULL, NULL, m, want, got, test->name); + goto err; + } + + ret = 1; + + err: + BN_CTX_end(ctx); + + return ret; +} + +static int +bn_mod_exp_test(int reduce, BIGNUM *want, BIGNUM *a, BIGNUM *p, BIGNUM *m, + BN_CTX *ctx) +{ + size_t i, j; + int failed = 0; + + if (!generate_test_triple(reduce, a, p, m, ctx)) + errx(1, "generate_test_triple"); + + for (i = 0; i < 8 && !failed; i++) { + BN_set_negative(a, (i >> 0) & 1); + BN_set_negative(p, (i >> 1) & 1); + BN_set_negative(m, (i >> 2) & 1); + + if ((BN_mod_exp_simple(want, a, p, m, ctx)) <= 0) + errx(1, "BN_mod_exp_simple"); + + for (j = 0; j < N_MOD_EXP_FN; j++) { + const struct mod_exp_test *test = &mod_exp_fn[j]; + + if (!test_mod_exp(want, a, p, m, ctx, test)) + failed |= 1; + } + } + + return failed; +} + +static int +test_bn_mod_exp(void) +{ + BIGNUM *a, *p, *m, *want; + BN_CTX *ctx; + int i; + int reduce; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get()"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "p = BN_CTX_get()"); + if ((m = BN_CTX_get(ctx)) == NULL) + errx(1, "m = BN_CTX_get()"); + if ((want = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get()"); + + reduce = 0; + for (i = 0; i < N_MOD_EXP_TESTS && !failed; i++) + failed |= bn_mod_exp_test(reduce, want, a, p, m, ctx); + + reduce = 1; + for (i = 0; i < N_MOD_EXP_TESTS && !failed; i++) + failed |= bn_mod_exp_test(reduce, want, a, p, m, ctx); + + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return failed; +} + +static int +bn_mod_exp2_simple(BIGNUM *out, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *b, const BIGNUM *q, const BIGNUM *m, BN_CTX *ctx) +{ + BIGNUM *fact1, *fact2; + int ret = 0; + + BN_CTX_start(ctx); + + if ((fact1 = BN_CTX_get(ctx)) == NULL) + goto err; + if ((fact2 = BN_CTX_get(ctx)) == NULL) + goto err; + + if (!BN_mod_exp_simple(fact1, a, p, m, ctx)) + goto err; + if (!BN_mod_exp_simple(fact2, b, q, m, ctx)) + goto err; + if (!BN_mod_mul(out, fact1, fact2, m, ctx)) + goto err; + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +static int +bn_mod_exp2_test(int reduce, BIGNUM *want, BIGNUM *got, BIGNUM *a, BIGNUM *p, + BIGNUM *b, BIGNUM *q, BIGNUM *m, BN_CTX *ctx) +{ + size_t i; + int failed = 0; + + if (!generate_test_quintuple(reduce, a, p, b, q, m, ctx)) + errx(1, "generate_test_quintuple"); + + for (i = 0; i < 32 && !failed; i++) { + BN_set_negative(a, (i >> 0) & 1); + BN_set_negative(p, (i >> 1) & 1); + BN_set_negative(b, (i >> 2) & 1); + BN_set_negative(q, (i >> 3) & 1); + BN_set_negative(m, (i >> 4) & 1); + + if (!bn_mod_exp2_simple(want, a, p, b, q, m, ctx)) + errx(1, "BN_mod_exp_simple"); + + if (!BN_mod_exp2_mont(got, a, p, b, q, m, ctx, NULL)) + errx(1, "BN_mod_exp2_mont"); + + if (BN_cmp(want, got) != 0) { + dump_results(a, p, b, q, m, want, got, "BN_mod_exp2_mont"); + failed |= 1; + } + } + + return failed; +} + +static int +test_bn_mod_exp2(void) +{ + BIGNUM *a, *p, *b, *q, *m, *want, *got; + BN_CTX *ctx; + int i; + int reduce; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get()"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "p = BN_CTX_get()"); + if ((b = BN_CTX_get(ctx)) == NULL) + errx(1, "b = BN_CTX_get()"); + if ((q = BN_CTX_get(ctx)) == NULL) + errx(1, "q = BN_CTX_get()"); + if ((m = BN_CTX_get(ctx)) == NULL) + errx(1, "m = BN_CTX_get()"); + if ((want = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get()"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "got = BN_CTX_get()"); + + reduce = 0; + for (i = 0; i < N_MOD_EXP_TESTS && !failed; i++) + failed |= bn_mod_exp2_test(reduce, want, got, a, p, b, q, m, ctx); + + reduce = 1; + for (i = 0; i < N_MOD_EXP_TESTS && !failed; i++) + failed |= bn_mod_exp2_test(reduce, want, got, a, p, b, q, m, ctx); + + BN_CTX_end(ctx); + BN_CTX_free(ctx); + + return failed; +} + +/* + * Small test for a crash reported by Guido Vranken, fixed in bn_exp2.c r1.13. + * https://github.com/openssl/openssl/issues/17648 + */ + +static int +test_bn_mod_exp2_mont_crash(void) +{ + BIGNUM *m; + int failed = 0; + + if ((m = BN_new()) == NULL) + errx(1, "BN_new"); + + if (BN_mod_exp2_mont(NULL, NULL, NULL, NULL, NULL, m, NULL, NULL)) { + fprintf(stderr, "BN_mod_exp2_mont succeeded\n"); + failed |= 1; + } + + BN_free(m); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_bn_mod_exp_zero(); + failed |= test_bn_mod_exp(); + failed |= test_bn_mod_exp2(); + failed |= test_bn_mod_exp2_mont_crash(); + + return failed; +} diff --git a/tests/bn_mod_inverse.c b/tests/bn_mod_inverse.c new file mode 100644 index 0000000..f05e78c --- /dev/null +++ b/tests/bn_mod_inverse.c @@ -0,0 +1,387 @@ +/* $OpenBSD: bn_mod_inverse.c,v 1.2 2023/06/04 07:14:47 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +BIGNUM *BN_mod_inverse(BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); + +static const struct mod_inv_test { + const char *i; + const char *a; + const char *m; +} mod_inv_tests[] = { + { + .i = "0", + .a = "0", + .m = "1", + }, + { + .i = "0", + .a = "1", + .m = "1", + }, + { + .i = "0", + .a = "2", + .m = "1", + }, + { + .i = "0", + .a = "3", + .m = "1", + }, + { + .i = "64", + .a = "54", + .m = "e3", + }, + { + .i = "13", + .a = "2b", + .m = "30", + }, + { + .i = "2f", + .a = "30", + .m = "37", + }, + { + .i = "4", + .a = "13", + .m = "4b", + }, + { + .i = "1c47", + .a = "cd4", + .m = "6a21", + }, + { + .i = "2b97", + .a = "8e7", + .m = "49c0", + }, + { + .i = "29b9", + .a = "fcb", + .m = "3092", + }, + { + .i = "a83", + .a = "14bf", + .m = "41ae", + }, + { + .i = "18f15fe1", + .a = "11b5d53e", + .m = "322e92a1", + }, + { + .i = "32f9453b", + .a = "8af6df6", + .m = "33d45eb7", + }, + { + .i = "d696369", + .a = "c5f89dd5", + .m = "fc09c17c", + }, + { + .i = "622839d8", + .a = "60c2526", + .m = "74200493", + }, + { + .i = "fb5a8aee7bbc4ef", + .a = "24ebd835a70be4e2", + .m = "9c7256574e0c5e93", + }, + { + .i = "846bc225402419c", + .a = "23026003ab1fbdb", + .m = "1683cbe32779c59b", + }, + { + .i = "5ff84f63a78982f9", + .a = "4a2420dc733e1a0f", + .m = "a73c6bfabefa09e6", + }, + { + .i = "133e74d28ef42b43", + .a = "2e9511ae29cdd41", + .m = "15234df99f19fcda", + }, + { + .i = "46ae1fabe9521e4b99b198fc84396090" + "23aa69be2247c0d1e27c2a0ea332f9c5", + .a = "6331fec5f01014046788c919ed50dc86" + "ac7a80c085f1b6f645dd179c0f0dc9cd", + .m = "8ef409de82318259a8655a39293b1e76" + "2fa2cc7e0aeb4c59713a1e1fff6af640", + }, + { + .i = "444ccea3a7b21677dd294d34de53cc8a" + "5b51e69b37782310a00fc6bcc975709b", + .a = "679280bd880994c08322143a4ea8a082" + "5d0466fda1bb6b3eb86fc8e90747512b", + .m = "e4fecab84b365c63a0dab4244ce3f921" + "a9c87ec64d69a2031939f55782e99a2e", + }, + { + .i = "1ac7d7a03ceec5f690f567c9d61bf346" + "9c078285bcc5cf00ac944596e887ca17", + .a = "1593ef32d9c784f5091bdff952f5c5f5" + "92a3aed6ba8ea865efa6d7df87be1805", + .m = "1e276882f90c95e0c1976eb079f97af0" + "75445b1361c02018d6bd7191162e67b2", + }, + { + .i = "639108b90dfe946f498be21303058413" + "bbb0e59d0bd6a6115788705abd0666d6", + .a = "9258d6238e4923d120b2d1033573ffca" + "c691526ad0842a3b174dccdbb79887bd", + .m = "ce62909c39371d463aaba3d4b72ea6da" + "49cb9b529e39e1972ef3ccd9a66fe08f", + }, + { + .i = "aebde7654cb17833a106231c4b9e2f51" + "9140e85faee1bfb4192830f03f385e77" + "3c0f4767e93e874ffdc3b7a6b7e6a710" + "e5619901c739ee8760a26128e8c91ef8" + "cf761d0e505d8b28ae078d17e6071c37" + "2893bb7b72538e518ebc57efa70b7615" + "e406756c49729b7c6e74f84aed7a316b" + "6fa748ff4b9f143129d29dad1bff98bb", + .a = "a29dacaf5487d354280fdd2745b9ace4" + "cd50f2bde41d0ee529bf26a1913244f7" + "08085452ff32feab19a7418897990da4" + "6a0633f7c8375d583367319091bbbe06" + "9b0052c5e48a7daac9fb650db5af768c" + "d2508ec3e2cda7456d4b9ce1c3945962" + "7a8b77e038b826cd7e326d0685b0cd0c" + "b50f026f18300dae9f5fd42aa150ee8b", + .m = "d686f9b86697313251685e995c09b9f1" + "e337ddfaa050bd2df15bf4ca1dc46c55" + "65021314765299c434ea1a6ec42bf92a" + "29a7d1ffff599f4e50b79a82243fb248" + "13060580c770d4c1140aeb2ab2685007" + "e948b6f1f62e8001a0545619477d4981" + "32c907774479f6d95899e6251e7136f7" + "9ab6d3b7c82e4aca421e7d22fe7db19c", + }, + { + .i = "1ec872f4f20439e203597ca4de9d1296" + "743f95781b2fe85d5def808558bbadef" + "02a46b8955f47c83e1625f8bb40228ea" + "b09cad2a35c9ad62ab77a30e39328729" + "59c5898674162da244a0ec1f68c0ed89" + "f4b0f3572bfdc658ad15bf1b1c6e1176" + "b0784c9935bd3ff1f49bb43753eacee1" + "d8ca1c0b652d39ec727da83984fe3a0f", + .a = "2e527b0a1dc32460b2dd94ec446c6929" + "89f7b3c7451a5cbeebf69fc0ea9c4871" + "fbe78682d5dc5b66689f7ed889b52161" + "cd9830b589a93d21ab26dbede6c33959" + "f5a0f0d107169e2daaac78bac8cf2d41" + "a1eb1369cb6dc9e865e73bb2e51b886f" + "4e896082db199175e3dde0c4ed826468" + "f238a77bd894245d0918efc9ca84f945", + .m = "b13133a9ebe0645f987d170c077eea2a" + "a44e85c9ab10386d02867419a590cb18" + "2d9826a882306c212dbe75225adde23f" + "80f5b37ca75ed09df20fc277cc7fbbfa" + "c8d9ef37a50f6b68ea158f5447283618" + "e64e1426406d26ea85232afb22bf546c" + "75018c1c55cb84c374d58d9d44c0a13b" + "a88ac2e387765cb4c3269e3a983250fa", + }, + { + .i = "30ffa1876313a69de1e4e6ee132ea1d3" + "a3da32f3b56f5cfb11402b0ad517dce6" + "05cf8e91d69fa375dd887fa8507bd8a2" + "8b2d5ce745799126e86f416047709f93" + "f07fbd88918a047f13100ea71b1d48f6" + "fc6d12e5c917646df3041b302187af64" + "1eaedf4908abc36f12c204e1526a7d80" + "e96e302fb0779c28d7da607243732f26", + .a = "31157208bde6b85ebecaa63735947b3b" + "36fa351b5c47e9e1c40c947339b78bf9" + "6066e5dbe21bb42629e6fcdb81f5f88d" + "b590bfdd5f4c0a6a0c3fc6377e5c1fd8" + "235e46e291c688b6d6ecfb36604891c2" + "a7c9cbcc58c26e44b43beecb9c5044b5" + "8bb58e35de3cf1128f3c116534fe4e42" + "1a33f83603c3df1ae36ec88092f67f2a", + .m = "53408b23d6cb733e6c9bc3d1e2ea2286" + "a5c83cc4e3e7470f8af3a1d9f28727f5" + "b1f8ae348c1678f5d1105dc3edf2de64" + "e65b9c99545c47e64b770b17c8b4ef5c" + "f194b43a0538053e87a6b95ade1439ce" + "bf3d34c6aa72a11c1497f58f76011e16" + "c5be087936d88aba7a740113120e939e" + "27bd3ddcb6580c2841aa406566e33c35", + }, + { + .i = "87355002f305c81ba0dc97ca2234a2bc" + "02528cefde38b94ac5bd95efc7bf4c14" + "0899107fff47f0df9e3c6aa70017ebc9" + "0610a750f112cd4f475b9c76b204a953" + "444b4e7196ccf17e93fdaed160b7345c" + "a9b397eddf9446e8ea8ee3676102ce70" + "eaafbe9038a34639789e6f2f1e3f3526" + "38f2e8a8f5fc56aaea7ec705ee068dd5", + .a = "42a25d0bc96f71750f5ac8a51a1605a4" + "1b506cca51c9a7ecf80cad713e56f70f" + "1b4b6fa51cbb101f55fd74f318adefb3" + "af04e0c8a7e281055d5a40dd40913c0e" + "1211767c5be915972c73886106dc4932" + "5df6c2df49e9eea4536f0343a8e7d332" + "c6159e4f5bdb20d89f90e67597c4a2a6" + "32c31b2ef2534080a9ac61f52303990d", + .m = "d3d3f95d50570351528a76ab1e806bae" + "1968bd420899bdb3d87c823fac439a43" + "54c31f6c888c939784f18fe10a95e6d2" + "03b1901caa18937ba6f8be033af10c35" + "fc869cf3d16bef479f280f53b3499e64" + "5d0387554623207ca4989e5de00bfeaa" + "5e9ab56474fc60dd4967b100e0832eaa" + "f2fcb2ef82a181567057b880b3afef62", + }, + { + .i = "9b8c28a4", + .a = "135935f57", + .m = "c24242ff", + }, +}; + +#define N_MOD_INV_TESTS (sizeof(mod_inv_tests) / sizeof(mod_inv_tests[0])) + +static int +bn_mod_inverse_test(const struct mod_inv_test *test, BN_CTX *ctx, int flags) +{ + BIGNUM *i, *a, *m, *inv, *elt, *mod; + int failed_step; + int failed = 0; + + BN_CTX_start(ctx); + + if ((i = BN_CTX_get(ctx)) == NULL) + errx(1, "i = BN_CTX_get()"); + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get()"); + if ((m = BN_CTX_get(ctx)) == NULL) + errx(1, "m = BN_CTX_get()"); + if ((inv = BN_CTX_get(ctx)) == NULL) + errx(1, "inv = BN_CTX_get()"); + if ((elt = BN_CTX_get(ctx)) == NULL) + errx(1, "elt = BN_CTX_get()"); + if ((mod = BN_CTX_get(ctx)) == NULL) + errx(1, "mod = BN_CTX_get()"); + + BN_set_flags(i, flags); + BN_set_flags(a, flags); + BN_set_flags(m, flags); + BN_set_flags(inv, flags); + BN_set_flags(elt, flags); + BN_set_flags(mod, flags); + + if (BN_hex2bn(&i, test->i) == 0) + errx(1, "BN_hex2bn(%s)", test->i); + if (BN_hex2bn(&a, test->a) == 0) + errx(1, "BN_hex2bn(%s)", test->a); + if (BN_hex2bn(&m, test->m) == 0) + errx(1, "BN_hex2bn(%s)", test->m); + + if (BN_copy(elt, a) == NULL) + errx(1, "BN_copy(elt, a)"); + if (BN_copy(mod, m) == NULL) + errx(1, "BN_copy(mod, m)"); + + if (BN_mod_inverse(inv, elt, mod, ctx) == NULL) + errx(1, "BN_mod_inverse(inv, elt, mod)"); + + failed_step = BN_cmp(i, inv) != 0; + if (failed_step) + fprintf(stderr, "FAIL (simple), %x:\ni: %s\na: %s\nm: %s\n", + flags, test->i, test->a, test->m); + failed |= failed_step; + + if (BN_copy(elt, a) == NULL) + errx(1, "BN_copy(elt, a)"); + if (BN_copy(inv, m) == NULL) + errx(1, "BN_copy(inv, m)"); + + if (BN_mod_inverse(inv, elt, inv, ctx) == NULL) + errx(1, "BN_mod_inverse(inv, elt, inv)"); + failed_step = BN_cmp(i, inv) != 0; + if (failed_step) + fprintf(stderr, "FAIL (inv == mod), %x:\ni: %s\na: %s\nm: %s\n", + flags, test->i, test->a, test->m); + failed |= failed_step; + + if (BN_copy(inv, a) == NULL) + errx(1, "BN_copy(elt, a)"); + if (BN_copy(mod, m) == NULL) + errx(1, "BN_copy(inv, m)"); + + if (BN_mod_inverse(inv, inv, mod, ctx) == NULL) + errx(1, "BN_mod_inverse(inv, inv, mod)"); + failed_step = BN_cmp(i, inv) != 0; + if (failed_step) + fprintf(stderr, "FAIL (inv == elt), %x:\ni: %s\na: %s\nm: %s\n", + flags, test->i, test->a, test->m); + failed |= failed_step; + + BN_CTX_end(ctx); + + return failed; +} + +static int +test_bn_mod_inverse(void) +{ + BN_CTX *ctx; + size_t i; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + for (i = 0; i < N_MOD_INV_TESTS; i++) + failed |= bn_mod_inverse_test(&mod_inv_tests[i], ctx, 0); + + for (i = 0; i < N_MOD_INV_TESTS; i++) + failed |= bn_mod_inverse_test(&mod_inv_tests[i], ctx, + BN_FLG_CONSTTIME); + + BN_CTX_free(ctx); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_bn_mod_inverse(); + + return failed; +} diff --git a/tests/bn_mod_sqrt.c b/tests/bn_mod_sqrt.c new file mode 100644 index 0000000..7ab7905 --- /dev/null +++ b/tests/bn_mod_sqrt.c @@ -0,0 +1,4533 @@ +/* $OpenBSD: bn_mod_sqrt.c,v 1.10 2023/04/11 10:10:52 tb Exp $ */ + +/* + * Copyright (c) 2022,2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +/* + * Test that .sqrt * .sqrt = .a (mod .p) where .p is a prime. If .sqrt is + * omitted, .a does not have a square root and BN_mod_sqrt() fails. + */ + +struct mod_sqrt_test { + const char *a; + const char *p; + const char *sqrt; +} mod_sqrt_test_data[] = { + { + .a = "0", + .p = "2", + .sqrt = "0", + }, + { + .a = "1", + .p = "2", + .sqrt = "1", + }, + { + .a = "23", + .p = "2", + .sqrt = "1", + }, + { + .a = "24", + .p = "2", + .sqrt = "0", + }, + { + .a = "1", + .p = "1", + }, + { + .a = "0", + .p = "17", + .sqrt = "0", + }, + { + .a = "1", + .p = "17", + .sqrt = "1", + }, + { + .a = "3", + .p = "17", + .sqrt = "7", + }, + + /* + * Test cases resulting in an infinite loop before bn_sqrt.c r1.10. + */ + + { + .a = "20a7ee", + .p = "460201", /* 460201 == 4D5 * E7D */ + }, + { + .a = "65bebdb00a96fc814ec44b81f98b59fba3c30203928fa521" + "4c51e0a97091645280c947b005847f239758482b9bfc45b0" + "66fde340d1fe32fc9c1bf02e1b2d0ed", + .p = "9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e2" + "46b41c32f71e951f", + }, + + /* + * p = 3 (mod 4) + */ + + { + .a = "c3978f75d6c2908ae3e9a714ad3d09b13031868dfc5873d7" + "bd9a9691f3b45", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "37f112813516c2563028c63a687d38b", + }, + { + .a = "1730fbcd9e78e1e786284f708aaa599ffa0d744ff223e3f7" + "ac1faac3d7d2a45e", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "4d0d44591c8c80bf1314762cf73c251f", + }, + { + .a = "1fd006456db047a16b32a48235749b8b627be66a5f9e05d7" + "d1857114baa9ff1", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "168fa1c701b579827436c8abc65bae54", + }, + { + .a = "216c1526fc9afa21788f84ff1bba10e8bccd39fc60978cdd" + "f89087d66dffdd35", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "5c7fc4b52edf59c44b0916cb134e852a", + }, + { + .a = "1cd486f29a9632ef276d10bb9754aae1b2723163a1a42552" + "4e514dd9b40e9b6e", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "55e8f564c1dd1455fea889203ae81c48", + }, + { + .a = "7272d05925151c067fcd3fb44d4d4908c9104691e3fa82a5" + "d2ed4a58479020f", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "2acad049c45fe1bf4307bd7b962dbd7d", + }, + { + .a = "6d12f19be6960d04f651867737a0e9a0b16e614cc5eb6ffe" + "cc6c911d3c9b260", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "29c68091856db1e3f6d63eaa341cbecd", + }, + { + .a = "23681522f2ab9e0e7cf34243e092dd8bada26d18dc1211fc" + "d9d49f65569cd179", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "5f349a0ac98fd5c7b575bc9ff05482cf", + }, + { + .a = "3218f7cc3f00df33b1279c2f5386f1f1837db81cf3a69052" + "d23f6220f1b43b4b", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "713f53f8fc8038dc2b8ad3adf2bb6a3a", + }, + { + .a = "1d1cd78fc48830494c54113173d636119286e7bd0bd7d627" + "21063f88256868fc", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + .sqrt = "565470af11ec50128e82606f07bd3baf", + }, + { + .a = "3a9de6e9da1e02f6e7e9b4f1556a0bcd1072d065", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + }, + { + .a = "8bdbc0195d2af794784a8b6f7b63d9fce9fe7a29", + .p = "e9f638f327f3ca2a2928f5451bb3b6ff", + }, + { + .a = "262b386d4027cc114b4bb73ea745650e6e4a22ef314e9e03" + "486f3fa7d721b15e", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "62d977c29cfede2669e617851d1db12b", + }, + { + .a = "172020616142af15b1d55675aae05601206663c1749e3753" + "f1b80696d62ece4", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "133c4f98c82d077789f01c232eca5692", + }, + { + .a = "199daf5ed7d4c07f9c22af215c32fc024cc609df92135d9e" + "360076ae2baf943b", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "50fac2c950af164b0bd7d9b5cf9600ae", + }, + { + .a = "15b01b8d11211643af99034b3e902305228c903653baea22" + "4c4896949b037800", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "4a8330fc5c8164f858e5cf5028ba69da", + }, + { + .a = "a326d1821af01d2c4251d84807980a9942b3ecab8dfe0fe9" + "9b4fd27c47de741", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "3317a2ea8c32838e0c8ac6b0838b2518", + }, + { + .a = "1213f38d2c4444e54ec1966acd28c568ad273a1d8337154e" + "3e2a137c372624fd", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "44076fb0b477e1a29315aabc95dafe43", + }, + { + .a = "399cc2207e49304d48c5ae4e32d3db8676fd16bd79ad98e6" + "dc001fb405ef6f0", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "1e5c722148e8939872584ca89e01237d", + }, + { + .a = "2faee914d3da21f1a5e82303f945593cbbb8bfc94315cb32" + "5faca3f8877b23a", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "1b9f0867a249063caf36bc28b68b5d54", + }, + { + .a = "17f6c4ba6517237a5ceaaa186400a0e5a9657db2fd863628" + "d6ac524027287880", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "4e5323a7cda4e3037d258f1436e3b964", + }, + { + .a = "1973a0acd4be1a2115b396969421d78bcd32f2cc9b31b1a7" + "3e876b0926f34142", + .p = "e36058b270896dd9380d4d693a2593eb", + .sqrt = "50b82d13351cca9addb25052c4d9bead", + }, + { + .a = "2768ea8c5bc132c003b0451a9e356ef1b9821646", + .p = "e36058b270896dd9380d4d693a2593eb", + }, + { + .a = "ae5450500ae2fdd7d07df1c46337e3de89730ec2", + .p = "e36058b270896dd9380d4d693a2593eb", + }, + { + .a = "15a78159fcd81c039d997cb2266513d677a36856756ccebd" + "7942fe063a99a42b", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "4a746881ec00b6cb8e637daf97c7f7d1", + }, + { + .a = "17ec38e2fbb20de601b699aab3a420d174a2c541938ea004" + "a65f97bc3713a273", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "4e41e59e7b80b061ae255fc98748d2d7", + }, + { + .a = "f8327d6ecd54a96d4cb2d1b5ac4be958a1073fd3c9216f18" + "4a2e1b65c80c28a", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "3f04610bae1450420bc38988dfd57fa4", + }, + { + .a = "1c8ad905faae5434f6070960507696b2879d5e7891d3073f" + "66a96bdf74c1a56c", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "557ae7ee14896190564703f963bb6516", + }, + { + .a = "21bbfe1ed600301ead629d7b87e11c5403bd16dd9c28aaca" + "03fffbf6597c1f47", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "5cee17372e523911e1a0f914db42230d", + }, + { + .a = "250de7ab5e802b1b399e8c3333b20d18dbe433ea28c333a2" + "0a9db317c5c96f2f", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "616546bc036efa2a5a30d35c1cb32ec9", + }, + { + .a = "20ae8c29c0aa7030c63efd48fb9f371f5a15fb1918859d74" + "d91a160d4533c73", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "16de015e7590bb75c7f9a0d719368285", + }, + { + .a = "a9e4dd7fea7f671c392560cc6abd8241ed88655d4adc4907" + "1b7f2151d7931f", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "d08ca78515bb8670926a12f02ae69fa", + }, + { + .a = "1a0126ea28387c8caf8a1b0b8440969407279c759673171b" + "80ba9a42281cadbc", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "5197642a69ddeb7c366b25a634a6c33b", + }, + { + .a = "52006bab38c980f87129d9d1b0d7a9559b0a8f304ddefee1" + "81b9d2874d12cbb", + .p = "c3b321a39659c8c574148821cc2f4c23", + .sqrt = "2438cea95ea42a348190d5d004ca0f6f", + }, + { + .a = "43e921a1d7d2706dc74144886815c02719a6e3c9", + .p = "c3b321a39659c8c574148821cc2f4c23", + }, + { + .a = "fe62c1aaa54f6abba02bf1add8118c2cc57ae9c", + .p = "c3b321a39659c8c574148821cc2f4c23", + }, + { + .a = "1c70683aeb6b0025b8509da40e743f4f98f74f8b81dcbd2f" + "b83c72059f45d986", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "555346fcb482ad8a501120ab9176fece", + }, + { + .a = "c30e49d25c864756e6432366defb5a7cd8cb3f18eda3cde2" + "6c88aec3a0ae004", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "37dd6d96b275bff258b4fde3321a9217", + }, + { + .a = "331e18f1f1ed03ac53c78f2d98bf9d2757127d3c25ec0cdb" + "f02882cb70595f", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "7264fcc091e4523541e8f0ee130571e", + }, + { + .a = "3c9c518aec7a7b502e49dca16acb91f9f1d57c7ca69dd199" + "d55212b710a1f", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "1f242105b1371a672211389a0b02ae5", + }, + { + .a = "a3c104e9871de2bf7e2f3e1f2e072f1d869a72935928e293" + "627f04c0fe9567", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "ccbf0901efa15d8d0d8758a57e2ab4f", + }, + { + .a = "c60bb5e0a48db72bc0cebe9455e9f94a08febd08d634591a" + "cdd1a7433eeffd9", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "384a9f1f39e3a04e3ec7e3b99cdf123b", + }, + { + .a = "22d9c628e23c14d45eaac1bb5c563cb4718556d31798e754" + "bb7f81a3c6b911d", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "179d2110991a0f85ad40927cb08a9c15", + }, + { + .a = "20354be2a9992a4f192687ab68025fe85b9724faea87f37d" + "39a43d26b71c4ee", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "16b36e6bffa91122c3615aa277cc249c", + }, + { + .a = "3ad95db7205d9413ed31b2145c4b368db365e949e54c4dbf" + "0acaef2bfb54304", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "1eaf6d6949ddfe0d9b915b2c9f472f78", + }, + { + .a = "1aa4354b3a677970dfccafe223df531fd9c753f91d802ba4" + "35362bf5ac66c11e", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + .sqrt = "5295a52e193ac5011d91f2bbeef1691e", + }, + { + .a = "f48312e68f2a47df61bff728ac986ec049c283", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + }, + { + .a = "897e77b7f767ac6a99d4be1ac2a4e52153884672", + .p = "c3c9132a60dcb07a29ea04ce12f10af7", + }, + { + .a = "105505111e51c9a73001339ccff3554c2bdd879baa46210e" + "1df8f73b70527a97", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "40a92a8fcac919aa46ee0ea2a6ccdc66", + }, + { + .a = "330b1cce03412398a36967102c7cf6e47534b630c60ceb26" + "04bf2e3842bb994", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "1c93ef2631f86d57ebc0c843e2082fe7", + }, + { + .a = "1cfe5a70784209591d7ced341bba4484e1603226449e52b0" + "a16d9afa9aa1fc0e", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "56273048848c7784c2589e3d91dbceaf", + }, + { + .a = "7baa8b5f02cdd3451df420b504bd8e16c738a07e7f9cb987" + "9944b99e1496e7d", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "2c7b6c3c5e43c0f2acd1ebfee4e234ca", + }, + { + .a = "608d55d43908ea7ea3aaf4ca05d5a8321d55cbe09b565e4c" + "163412e45c62386", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "274deb2741766cffb60a517e8f3fadbc", + }, + { + .a = "526ebff9146c9f50021f56304120d8f9b09ce515d0066346" + "8f20115421f024", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "91449230a1a386e9c1093ee0cdbba09", + }, + { + .a = "2a20b65b2a28f1b3c9e1d876d86a5f5d87d94421ddf7ef69" + "1a71f07955a09a8b", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "67d976d658fd3cbd77c1474a0906404c", + }, + { + .a = "1e083613b3a5b9f547972034d37a1f6f42733731dabbe889" + "99b5c0f50a7dca82", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "57aeb4be88de6be03a7a453a7ba5b50f", + }, + { + .a = "11d00fbce28d46f526bb51246a1cdd3c3b2d8bb83725a83a" + "564f6a67d23a0ff", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "10e1ce79ade89e839f3f0f29d72eea8a", + }, + { + .a = "3285f0c5eb6ff451af071089be87c1a7fe564e1e8de5911f" + "fe390fda34c8799e", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + .sqrt = "71ba3c5d0d93cb2da4a8242269f8f349", + }, + { + .a = "d0d1f950ec1b85862398f403e8768936ea03cf1d", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + }, + { + .a = "e5a7a57d99efdd8965c84e10b83df9d0871cc1e", + .p = "e84fd723abb1fc0208ad23dfe5986c97", + }, + { + .a = "102ce98ef5044dc2f1afa2e6600008198b5329aa0757d239" + "3f6860f7e252f5db", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "4059946cd6922b83dd0425fc4acb6651", + }, + { + .a = "132922d347e42176551bcf327fcb764380a996142bcec3a7" + "e5c55f822c53e99b", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "4609639f50503b898f97fcbce84bd069", + }, + { + .a = "1b1be4c1234332b5ac8494697d1de921f851d9c2b4557931" + "125b94f68229dbc1", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "534e5790710771e405fa386a75fddcee", + }, + { + .a = "272ac5b81ce6e27b4b5aac25ca34abfe8725d28f7f67c8d1" + "9d16d2fdbdadf2d5", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "64223ee58ff69643ec0b4cabda6fa41b", + }, + { + .a = "77a6fa94c13869d5cc265d70edc83bfed1d0e1b0ac8b89ae" + "e56580f73696b4", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "af045f74c28b50570b7d2ed8a53705c", + }, + { + .a = "207b2287539f1489a52c29d82415be4d2dbcc256c8f58f51" + "697dacc3ea2c091c", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "5b2ff6ea861f522cbe4aeda70ec954b3", + }, + { + .a = "a6322e0055de7fd226828206a28c61091a8221449c39bbd1" + "969e9cdb1cbd7b3", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "33911aaca827e264d82da9b63fe25c98", + }, + { + .a = "5c0625d646c4183b59ccea7fb137399802389d925c999c8f" + "34700cb1edd482f", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "265f251061587b79dc4bb3e2dbbddedc", + }, + { + .a = "ab2267257b8fb94428bfa7782d114a8189ad9188af7c35aa" + "2f58851104a3c3", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "d14f31646a99511d5df395ee0c6f23b", + }, + { + .a = "2ccb942f89fcd0f396e6f60dbf26faba338a9f42a08ae83a" + "8349881f4d2c9707", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + .sqrt = "6b1637561bc8e2b7c6797ff14898b78a", + }, + { + .a = "49e501a514b25ec54e97e0643fef58c2331a9e0", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + }, + { + .a = "bda6072e85a4703a58766eb147beca3a9e407324", + .p = "dfcf17789278b6e9cafdb4beaf2cfcfb", + }, + { + .a = "e505c659e3649ac1974baa7ecf478c9c46d988149506c124" + "f528a8a1da13bff", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "3c88b1ef1aa5441216ef7c2457edfb52", + }, + { + .a = "88db3bfef58b46e08c36ddcc96ff4588a8c10311ddac5620" + "682e92351245c4", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "bb2d50c0a9fc425d2f093f5e9882845", + }, + { + .a = "eccf316a16ed9aa505b82e99a9c089513f3f5465178c0595" + "5e1c8e7138da57b", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "3d8df00919e543a5f782cec0e2833eba", + }, + { + .a = "23a72d78c1d23f89f21c9aff268ada5431568d136b8980cf" + "cc72b27c7ab4e93b", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "5f89488ed8134af87ee97152df43de42", + }, + { + .a = "1863d4f3fbbcc5ad3cf555c22d5a34045e91039acfe30365" + "4fce949c31d5aba", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "13c1259e5a87acded9d3999bdd6e7cae", + }, + { + .a = "be8a91ec3aed7e990a3a01e12572b1bcf131a6dd93d46e4f" + "c6719ec22197d0", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "dcdbd473cf66c3ffb560ff8fb1411d5", + }, + { + .a = "b268924f724222d8df0d48f502c6bd33b406742efe65b153" + "3f9c34d30819ff5", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "356d87ec862cd46e67997119202dd092", + }, + { + .a = "c860b34209538b9b8efbb4bb51a70a22c1003dec12e5474d" + "2f061f29b1c1c0d", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "389f374589c29d78ffd4fddfcbc9fdad", + }, + { + .a = "857bb672df76352d6ed3259cdf20a65d941b7c3f2ea07a19" + "c513605e4b502bb", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "2e36c7760d3a9ab2d437ba376940b71c", + }, + { + .a = "248ebd6e07fabf93019b22ea1d1ab4d0fc9eba3d780d7307" + "429a57739066844b", + .p = "dfe11f28376b5562def9fbecfa68ca47", + .sqrt = "60bd96b2e42a4ba4e1c5529dbc4b31f9", + }, + { + .a = "7f0b66aca27105e059b111992986f46a71b25c9a", + .p = "dfe11f28376b5562def9fbecfa68ca47", + }, + { + .a = "a964ffcec8532b0209457c1eda9988e40fe37482", + .p = "dfe11f28376b5562def9fbecfa68ca47", + }, + { + .a = "12dc5769139571557c0af544a1eca5bec5f9b3cf70cc87d2" + "d48107c5b4d20d98", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "457c7c100eaa11609392f6af4fbdc07f", + }, + { + .a = "10d05ec3bd88a33465a1c5d9d467b587c2ea46f93a369223" + "29d1893adf131b9d", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "419b922a2d4e0fdb18d0e31a130a3b57", + }, + { + .a = "34d65ba3637b3b9d46a7d1a3558d7e3e946761ae0b8e4db5" + "1c4b9b6bdfde0492", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "744d88ffa822b5d259c4fd138e489067", + }, + { + .a = "292612ef1616fff0453f2e66580cffc763dad52f12ec5c37" + "6246c4d8f69c0062", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "66a2b919787e57087ca4fd47b6ad37cd", + }, + { + .a = "3a7ec6f19e0d9a4cca6f9bd8e2d126519c9370a88fe61879" + "a0ccef7a6d5ccb23", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "7a5f18c79265b00cbaedc8bbef8cc26d", + }, + { + .a = "b2f41bfdd2c86f5115724830a7dff681ad4f06198f7c989a" + "b8ed9912f690fe7", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "3582689e0e3d046dae757b3e395f2a09", + }, + { + .a = "12b9a1b6c4f1bd7888f206445c91c722219e1ced30bb2ee8" + "5eb1a511347c430b", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "453c6e4824654ae983a123749adf41e1", + }, + { + .a = "4a7c46417c3fefe77ee50565fe79aaee7886e1b708eebba8" + "84fd59d616e1c8", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "8a16821ca0a63ff8b03b4b1a6afc5b5", + }, + { + .a = "70b12a7a215f436eac38a7b2e9bdeae47f4e313c9622bbf0" + "ddc4ae3cdd48ef6", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "2a766d514a8eeb2518e55d56d435b5b3", + }, + { + .a = "1127295ddd79b3dc0d36759e8475e793c903136b3d779ba4" + "a4b40eaaa2510cec", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + .sqrt = "42440e1bdce37bc4099b36183270b686", + }, + { + .a = "780039d1fb613f1654993c81ebce1000256ec462", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + }, + { + .a = "55f30fcaf020db602e2db2bed4ed2cdd061683d9", + .p = "fddaa93d6ef55fe16d65f36467751ff3", + }, + { + .a = "297aa82c160b09d1551443f560c355085c075871687b98af" + "3b2028156e24fa4b", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "670bff83e4425dbc782a92735135b8c7", + }, + { + .a = "aa4b8a060fcf9f4adb09ccd99c58a0d71023319539618b60" + "8be198e4e19898", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "d0cba27ce684c00b2b22b661305ab22", + }, + { + .a = "4307405764f9c05f6b8a433fd442e97b20b6dd725a0c5488" + "fc0947daf6daecc", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "20bf92a53eeb49fc15a28fa47156c7e1", + }, + { + .a = "25e25f800892a56195c46c027eeab26ec820354e889a8057" + "a46da80343dfb960", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "627af6200712b962235b167671d6859f", + }, + { + .a = "1ee2add6b546b09bfa3acaa640feff18f0a844638a3e526e" + "a9c22ff1657802e0", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "58eb64eee715b3535a68d8d4f4c389c9", + }, + { + .a = "22c0b5472fee1bb7876e8612b63676678f0815a5a5984718" + "d44000eab1632e6", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "1794a1976ec2bb6f199e9e833c9bc7c9", + }, + { + .a = "c31233d4d15b615d95bf209890c2bc3446800af361aa69af" + "3d65390eb64b01b", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "37ddfd137bf27b3ce0f21c86c844cdf4", + }, + { + .a = "12977980fc461d4cf8f61b364e59783c589b5ff4dbb0f67d" + "5ef13413dcf58afd", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "44fd2b8b167f4c5a14cabe9344b2e337", + }, + { + .a = "3ae43a729fe988282a2a3f2e821aa58409784a661741bf05" + "237563c1025edef", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "1eb2423fde03aed73f280a8500172693", + }, + { + .a = "25988dd5cd06919bd5cb184431955d865033c58c65466597" + "fcb737ac19f27492", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + .sqrt = "621ad4ed8769873118ac6279833549c3", + }, + { + .a = "b1216cf6c24d756b71dc6cf2c88becfb95bdaf4e", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + }, + { + .a = "15ad69f58f2c2f4e820e73120f229c70e4facc3", + .p = "db9874b4d0f7b1cfcb69168102ef111f", + }, + { + .a = "aa9714b318b654674644c3daac851bbd4f39d01dfd89e3af" + "8e099d3b8903329", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "343e7b2f7e303f97e6dc9db20894ac1d", + }, + { + .a = "40597523833f21d1fee6c963939dd73397e2a2352db1b049" + "1b0f8fd50b1bdd5", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "2016557da8396370d7a7c3d9a947e666", + }, + { + .a = "10ddb7215a1e681614b6d7324b92b24fc715ed863d5038be" + "05d740824a0b3114", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "41b5964db90af860d17fbbcdd4afcc55", + }, + { + .a = "1c36ce697e95d06ec63af3b82a6c2d8e9622c2c33f3f87ea" + "ac3e75f2abef8ce", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "153f2c9007b549d8e802a903ffd2171a", + }, + { + .a = "35a13697c77f9629ef70d36fae88659d39b4048dc67828bc" + "4425d1cb41edbbc", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "1d4afd8ce507d6950e0b714c27e5e4c2", + }, + { + .a = "1886d861ea3d46d0edb942a01397780a84f5ce199e6352d7" + "42ed995a94302701", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "4f3d39e8213df646cee264182fef1f47", + }, + { + .a = "143c8b6264d12017961d3829d3aa0088ce4e8c6261a39e68" + "0ea5b276d427e465", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "47f9db1679dd06966c91bb7ee81f22c3", + }, + { + .a = "121134f6cb228fafbd45a934db668a78d27aa12fb87ab25b" + "e714ec93d05137a5", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "4402458a9a80428c77dda8334ff41f74", + }, + { + .a = "1ba2eabc24b78ce8ed873c0aba09443e5f02b98858c0a09a" + "bfdb6d4da798abc3", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "541cce775b911592fb759167755743f3", + }, + { + .a = "e58fe89a18f8200b4aa289446b6de2ae4e4b0ad911e59cf0" + "1e0a0b32b609141", + .p = "cd1f525d3eb5172c591bb299f52ba447", + .sqrt = "3c9af08f9f626f41c7ebe2f32875497a", + }, + { + .a = "b15263e714de941bb702cf71e0db12613a383de7", + .p = "cd1f525d3eb5172c591bb299f52ba447", + }, + { + .a = "5deae3520dc28e0e3bdee22fd91a66dad70b41c2", + .p = "cd1f525d3eb5172c591bb299f52ba447", + }, + + /* + * p = 5 (mod 8) + */ + + { + .a = "495114892a3986a8b4a6e05bacc0e293421716b0c4557330" + "0cf4243f784e33d", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "224004cbf31a7c967d53819764506317", + }, + { + .a = "3f7683a65a7b5ab1134a944cb831bb8a0f9d9835a45d230b" + "d3c6b8bb3902c1", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "7f7639804be2c91aed7cdb70e1af18e", + }, + { + .a = "9b044b4d448169fbb7da81261016b997ff24b3921b03dfb1" + "d6dc5b1b28de2f1", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "31cd63124ff7c306503ea3a2437bdbb0", + }, + { + .a = "128b830f7eed54c5b7cfeced129aa45ad857d6e3d9f2a70e" + "8cbf6097607ba1b0", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "44e6f601015c26b885d7cd32663bc970", + }, + { + .a = "1883fe98086c0821ff2858347227720a967a2c468a8ad9ab" + "018257dd49ec8a18", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "4f389ee648fb323847e453c77db0a364", + }, + { + .a = "23ab14a89775f60cc6d8c397711429e9aae1fa59b637d356" + "f7a8fbfe6b5379ef", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "5f8e83217d7de9d61afc3edb95912f2f", + }, + { + .a = "7c1252084891eb7e2b7d1c5ff6102949bf2b598a6ee05a0d" + "03ec0471f963fbd", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "2c8e124682ee306b16eebb31464c868f", + }, + { + .a = "824e2173788853d264c075c287c558407ab196193af02427" + "b7f7be09945bfcc", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "2da917e56d3146f4d6e496bcfb50509d", + }, + { + .a = "506661349ca4c1c1d32c030ebaec699f584e537fd561c5a5" + "40bb2339775ad6", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "8f7731dd48b0165519d0dfaf629cd81", + }, + { + .a = "d21846fcb456b5cc76e2e9e95c72cd8d10537f2f91b7817c" + "06bb2d946f9e1fd", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + .sqrt = "39fa851e5ff14e140a6f98124bcbf2bf", + }, + { + .a = "3727e2a9498ef20c8a6f0d2f8de533d664bd8f2a", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + }, + { + .a = "2eef7eeaf13b6173f9c68f71cb3a83621672810b", + .p = "c9b4dee4aa04ce668cedd3d2bb8395fd", + }, + { + .a = "7695ae6d4aa3f51985234f35cded2e378912e848d1e08bb9" + "921dce2b937aa8", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "ae3c0c05a16cb2ad83b0dde2f46d15d", + }, + { + .a = "6932c69d54861b47fe83f8531f19d3af58d3b85737e1b540" + "e2f434b05eb4ffa", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "2906c888cd5fe48ccca5c925944559bb", + }, + { + .a = "22894e6a44618c1a14c10695cf41b5083f7f6d8a34c58309" + "9334b3ec5a53a6de", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "5e07397aa72c55103caf053fd20540c1", + }, + { + .a = "d5189535263311b02c0b50f869524ae54ff3b493ccc15952" + "330792e5676feac", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "3a642808df53bce255b9d4ec52316a36", + }, + { + .a = "462df11d760ac7ba6320dce59dd012a5a13e81e93a4a23a3" + "2c2bb60314bc564", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "21825fb45eaf1c3cf86b8b6ec3f3e4a6", + }, + { + .a = "1e2fbc91cf281ba1a838e600f8a7348b03daa0d6dc5ceb82" + "788539919839184d", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "57e854eb15ea535a9210c70e2b1d0397", + }, + { + .a = "1ac89e6b45c1f3d3888411a374f291e52af2abfbd7dcf23d" + "e8024623ace61a1c", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "52ce01029221f38a79750615d89c83e2", + }, + { + .a = "408ada83c389027bb76db1c90279ead9b9855b604403ef4b" + "b2821f807a2f5dc", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "2022a3e12dff46cfd45e4b670e14f5c0", + }, + { + .a = "17157376051a1da95618c37fa6a1febd48cbc52dcc3150eb" + "c590f93be06991e8", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "4cdf79e5c4a5e9413612c09652b60588", + }, + { + .a = "c43c6a117ba38669cadfebc127dcc99a3292fe772077b322" + "d47c1f62bc8ed29", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + .sqrt = "3808a0c60e94e3bf5453c16c14b6e936", + }, + { + .a = "7899729705aaa981ccd5b22ca3b9384c957e6d8", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + }, + { + .a = "aa82a2131cf182e08daa64945131572020110835", + .p = "c7ff289dd9db4bc68a80d6d0837f5195", + }, + { + .a = "3b2c1fa25b77539a5adbc8daaaf3afb1660be07651f3f0e1" + "77331853bcd49b21", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "7b13e508e84efddeb4eeae18144046db", + }, + { + .a = "3b98fb79556ae299a2d9349f8e9544fe7c3fc9b0a7265ec4" + "00dfd31c139c1869", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "7b84e784f47a5586e6c3cb970bc98a03", + }, + { + .a = "149c120dc19610055d7f0ba9d007f458c558c68a40acd0a6" + "00bb40d2650ee1f4", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "48a2f5e66dc7919bd19d00549d177c3c", + }, + { + .a = "13c3763c5d74356dafe968f30e1d9a4f8e6c63c6101a02ea" + "ec1cec8db01798bc", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "472140c031a001ef403cb71274a91830", + }, + { + .a = "8353728f214d74a60f740e3098dc80c8bf3b3878499b71e7" + "06ded8c999a5c68", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "2dd6c9cf6caa11c9051d6823a4775155", + }, + { + .a = "5e387c6058eeb03b33b59fce405c6278d7e373083fe3ea9c" + "f1d64e8be3f58e7", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "26d3b19397db8053cf072f385f71f81e", + }, + { + .a = "22eca556be0a5ee93e1bae520342f32331727c75dfca6082" + "3aac96741594cd18", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "5e8e13ba599582dc056f0896c4cbae8a", + }, + { + .a = "308e76f45903562ae8c4a56fd9e181cf2b802586383cc133" + "7a186fe1d79c8726", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "6f7df34d1556913182384ed31aae29eb", + }, + { + .a = "9b572efdd07a8a9cc36f20d040d92f3a90fd87a4e0aa651a" + "f71361589d360bf", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "31dab1ec08d2030a50cae92533215502", + }, + { + .a = "2f720cb02294a4b8b69f41cf5f7071f7010f10038f1e603b" + "1394fdb65d388d5", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + .sqrt = "1b8d622e0887aadbf3113f7e9c923373", + }, + { + .a = "dd9e74c33015c49e90c1b54e29a123bb759e77f0", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + }, + { + .a = "da290f4e04f8dfc3c07e43dbb7121b91ee2ee29d", + .p = "fc5054f3123deeb6ca2d35c77263c08d", + }, + { + .a = "111aa51f58dcaae1d55a7f50cdb2e15da632407008ca0cc3" + "7ce53d6f53ea2a", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "422bdc54895f3fbab7fdc8e8bfe7edb", + }, + { + .a = "19381515e93479f7e5d4ce92ce1ee883ed9f50e5802d120d" + "b390d62df8736b6", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "1416624ee1b331632ede4da5a72c679f", + }, + { + .a = "605525d619104f91c7df399e6d68b960ff69d810ae481754" + "5bfa65a00d67dea", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "274279c61f21177b40e140015ac3b690", + }, + { + .a = "e59076d17860b58cf92dc7edbba52d72c3cfa5baf141c600" + "8bf897afc3a0d0e", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "3c9b0355733638764f3529906f702f46", + }, + { + .a = "1b99dda206922285a173c2e05547e366061c908b7a23af82" + "fe78a3f21c6917", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "540f073d38ac532e5382f9afc215523", + }, + { + .a = "543e02b3d7c30e8ff3a141aaf6a150f01b9874b033344ce8" + "348ddbff79aca9", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "92da8c6295ced9d22457eff8df968bb", + }, + { + .a = "2e6d5bf0b9d6ba16af020be648c01aa77b2717ce9262f23e" + "ebf2e2dfb11fd125", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "6d051e57847d8f83e8e003e833c514ca", + }, + { + .a = "179d7fc2e81864cbd54dfa14306c06fcecfc65ed159f1f4b" + "dbd4ba616ceb064e", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "4dc0b7fd597e46fdffe17ed9b8928355", + }, + { + .a = "3275ac40f4e32e5343d33881d4b3994820572bb121ece88e" + "c7995e668017ef56", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "71a7ebbb86f85e267d71b796b233b773", + }, + { + .a = "34d9fd618cd45afdbe87718ad19d8377d17619376bdaecc0" + "ddb8695e035846a", + .p = "e7616abd0448ce8b22a99105ef99f00d", + .sqrt = "1d14620b9c69abad878797bfb2fa3bd4", + }, + { + .a = "e34380a3d760ab9415cd794c58569e3687568038", + .p = "e7616abd0448ce8b22a99105ef99f00d", + }, + { + .a = "4e3af908dac0c11da23d73e9b1f2d6d3d5e94906", + .p = "e7616abd0448ce8b22a99105ef99f00d", + }, + { + .a = "6ea9d07bd5e2ce59ce999d82dde6e42cfc90ba60f0b70c17" + "e6e4cef1c8d5fa8", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "2a1422e259229156026fe1ecaecb2026", + }, + { + .a = "171dc2573d5011c8c9254adeef55f0ef572af94fa89bd329" + "d0f02d2f6fa916db", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "4ced4e16d63f14de9e77c320d7e61dba", + }, + { + .a = "5da9be4927acc2a00f8eb2bd9007b7ea51c77e6440a1e020" + "75fbc67618e9de8", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "26b63d2d91137017b1e5e0d3d15210e1", + }, + { + .a = "d32669bc65290f5b1fac5c04bcc3de52f582fb9dc22007f4" + "776a2fc05472435", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "3a1fbf4661e72f835fc36be9075f43c9", + }, + { + .a = "89cb34dafdb05e01f54169143a88b7a9a4201dd66f12b957" + "6703e52cc176861", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "2ef448e5f6e4c92d59db78cde0a066f1", + }, + { + .a = "5b8674a77fced1b08dd2376af9a96d4c4824786104ebf9f0" + "7fcc2ddd3ab0201", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "26447c86fefaa791bf1d1c15d4607fc8", + }, + { + .a = "c54d49d0b63981375c4a9129ed4647a7e8a251045a244324" + "fd58d42baa8355a", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "382f88a82f4719b32f2021eb845f7045", + }, + { + .a = "2256345a067ee92e441731a5007b08461aa7d2adef64664d" + "a92c40b7d79a9dc9", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "5dc18f24fe2dd7bcf37ae865c9b48122", + }, + { + .a = "36da4779faa88d91d59824acd9b9bd00181aa5c7cfdf8243" + "7eb2544592c91c8", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "1da00204dad7da917cb1719a9c826cd0", + }, + { + .a = "98f15c0e715dffc5a54dccee9c598314fdee262cee747268" + "2f585b7ff248ff8", + .p = "c039e7b229cc3b7792b37ed541001005", + .sqrt = "3177d023e1f4310118c00c362b422bf1", + }, + { + .a = "5bf6cf4b386b5de218728434e62fd0d802008bdf", + .p = "c039e7b229cc3b7792b37ed541001005", + }, + { + .a = "13c22cf6c3c54b75f2c07830cf50777a5add43bf", + .p = "c039e7b229cc3b7792b37ed541001005", + }, + { + .a = "8ea35eb078a0033844e5869778d9f581007c9c221338d1f6" + "4e09c528ac24747", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "2fc5c1c76763b2843384eaa1609285ce", + }, + { + .a = "274714f1060ba85737c3803bb6192cef8f1478448e0f3662" + "ad57fa2a6cbd13ff", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "6446686b34424dbb056c499ee47d6af8", + }, + { + .a = "1be91ab1e867e7c0ff4b9e039fe3a33515ade6590baba482" + "6d6ca8347f89082c", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "54875a1b0c7063fb4597f579a852bbce", + }, + { + .a = "b436cb73a7318ec101548cd18d97e350873563b145312a88" + "6c7e539ebcaa135", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "35b2914a881429245dfb9adaff55f249", + }, + { + .a = "485f18975843b575318dc7086eb45bdfdc54a8aed83b4189" + "934d2546fe231d7", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "2207504b2e026ad2c0754aadad5d322c", + }, + { + .a = "607d62025340dee0adc2de94c8dab17eb912c5cc8cc1589b" + "d227218c5ea6759", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "274aabccb65a4996273ebc7d1941981f", + }, + { + .a = "48a5421193d567325bc1d25965ac555d9384efa37843d840" + "b66b0c104f7618c", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "2217cafc385b2089617782b01c3cc88e", + }, + { + .a = "1e496e33fb89a64d8fcc3591304b05f7fddf4cfdb5a0986a" + "188e0e4e49f85e14", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "580db67fe95fbe4f965c678c3e80879d", + }, + { + .a = "ec4337ba1339cd0bf3374832526038121727b4bb78b6fd4a" + "11300ba5506612", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "f5eef0b27ded737243fe13eace325aa", + }, + { + .a = "e826c96625f199c8db32619c61d175f2255aeeefa9183a42" + "63553a1f3f0f29d", + .p = "d9c22e349011878f87754687ee523365", + .sqrt = "3cf232080315a091c876b8cfea4160d6", + }, + { + .a = "c7831203f6b08d222b1b622a7cbbee77237fc689", + .p = "d9c22e349011878f87754687ee523365", + }, + { + .a = "bb13fd167d0ceec6baf65d67537d685c82c65c8b", + .p = "d9c22e349011878f87754687ee523365", + }, + { + .a = "bd8c5e76b6e2746d4de3467b5c65169c3f62317dc4595bc6" + "dd1c6a1693e07f8", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "37121413fdc699e9e61ca1893700c75a", + }, + { + .a = "e24e97d56b8a5982465b48fd71f816623028b66ac9b2070f" + "ce474f541473e13", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "3c2c8c3d819b3b178474394684d256d6", + }, + { + .a = "eb5e5424a250f5921315b3b80e611a8bb31fe0ca502b3673" + "50dfb435d244a00", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "3d5decb13bdf112d2a7b8f7eb0499b9f", + }, + { + .a = "6974a858d34d14491e668420065eb1fb7c46a76464e66799" + "af8b6f21b43b7f8", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "29139f465027081bf12280ef60322f91", + }, + { + .a = "3534a02b5daf8f7448ba228e933b98fc0a237e3b6fa34a60" + "78e1a8788f7669", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "74b51a89bdf7e7f1bb04c8cc07d506b", + }, + { + .a = "279ffd9d740d5de93484de00ca0b02f876c2f8a49548fa4e" + "a16bb9b5a764f63f", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "64b7a63b5b33224381ee8dc1e0bed0da", + }, + { + .a = "19ff5b6b054acc5ca156cb335fbb57a949d3b495609625f0" + "b1b1ea0e19c1e669", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "5194934308057d3c8ecdcccb8a1f8801", + }, + { + .a = "286c1adb06c8e0d91743543c715d66581e0f1404952f2cf1" + "9a92168097e4bce", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "196e70cf9b236e13078af721e59d4642", + }, + { + .a = "2fb921c1706f29159470f5080f009b7af73a2b4b59319e89" + "44313f674843c790", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "6e87f87aae63457cd4a4a6ea532641c6", + }, + { + .a = "1e9be1645bc61e1814adf8ca7809fe2f024723b319556971" + "114b2a184e9121f6", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + .sqrt = "5885400cb80c63bae4914308b2cdf9ea", + }, + { + .a = "9ca8cf6730dbca96d208b79b0fd52535e792b304", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + }, + { + .a = "73f219324f36e0aae1f6e8d95b89d0468ab1922b", + .p = "e3fe457cf7ae0d453157fac07cbaa725", + }, + { + .a = "124b02b0fd0ff677573e733d6bc3bea9a6be60d6e84ef86a" + "6e67b740c7112749", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "446eb9f9ac09ff7ac2b358dd78ebb4c1", + }, + { + .a = "d0d034bfbdcca69049d17eead78572c66b5f5a9e230fa1b7" + "d41e7b623a83153", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "39cd2ece90ca23d6c2693178c5fcf193", + }, + { + .a = "25f55f4ea11fd8adef2d8f9781363006366f6caa0b0337a5" + "e0184795f3fad", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "18a4e931a05b8416bf5b991bc02cf1a", + }, + { + .a = "25337b83d2f3e5853dd52b7052496b7a5e6380e941685db6" + "b4693edeaa62e106", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "61969ce7afde7fada420c587b0241dbf", + }, + { + .a = "50eaeefcd5f5a1b5b0926caed2ec08c92c561f00275694d4" + "68c7bba52ae7b", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "23fb513f8e77985606921ec8e1f49b5", + }, + { + .a = "609baed1c2d4d52f1c91a9ed2f3c68ffe87641b5f00464d2" + "128086a4c1e981e", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "2750d6a4effd2c9ba5f71f80c2f58cce", + }, + { + .a = "2d9514eff20d87bf3afcbd25bc681c134780dec20d01b97d" + "3b29cc911a1d90c", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "1b01816bc1b20bfaee478233e5f22911", + }, + { + .a = "28d32b18c9082ae7ea28f0be3cd7aa8efad600561d4347a8" + "53b467758443b1a8", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "663b1fed3e5cfed7167cce2dbae810b1", + }, + { + .a = "fd38ba6f44adf4ce8d06344d0c3e5e4a44a34aaf93497b25" + "3f1e9b1009c6b0", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "fe9b64d7af41c5ce81ff18a391165af", + }, + { + .a = "590d9ed0431461071609075d93270c323533800822a360e1" + "60210e2d5c438be", + .p = "d258b10a93a427f65fcdf8cbc655b845", + .sqrt = "25bf48a476372ef10dc669ed3f7d4896", + }, + { + .a = "5b0f78a90cee80f72695c3b14d340e7a38567f11", + .p = "d258b10a93a427f65fcdf8cbc655b845", + }, + { + .a = "afad58d4e0c0c06fb40a77131871575bc72369a7", + .p = "d258b10a93a427f65fcdf8cbc655b845", + }, + { + .a = "1e19fd22e601573225586b66084a4df65158ef45ad0fe8f0" + "a68faa4ad447cf65", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "57c8a49ae8a34fc47bf236674b817723", + }, + { + .a = "5c15b5ef617d5cf85e4c9276478d9278e04a30527a2bcb66" + "a6adeb05ccb671e", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "2662638f71038b2b0b9e4a06e46bb361", + }, + { + .a = "f1243406b9dbcaa1f252e7dd8c22daa9345c9151f6fa6e54" + "df6ac088c81ceb2", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "3e1d6b16acc35ee99a3cf9b58f385d65", + }, + { + .a = "a951e30e28201b632da15521f791e8101ae9fdf7a107e6c5" + "6c35e4f7ce52d46", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "340c978f9204064fc549747774070f41", + }, + { + .a = "2d0cda470ec77db7e748640e1c82131141b262df8cc2cea7" + "43915d3ce85533e1", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "6b64207016d908d10e20b8d8098fe79b", + }, + { + .a = "47ee4bb1de2238c9ffb9ab96eef909b14b165c8cd9bc2049" + "0837e26d76134cf", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "21ecc111c02eac8f8693cd21c980dea7", + }, + { + .a = "d6d0e077785db6f2246475088ce5104e6bda7921c1fb12ac" + "1149bb3c9b7eea", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "ea816f0e6b06c0d446fa0a00e79103c", + }, + { + .a = "3f0fa323e5d12f4aa296f2024f86b51cad3a0339d978bb2f" + "c4a5ce4fc83a29a4", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "7f0ebfc9efebd5de70d24955fa75393a", + }, + { + .a = "247680753d5599c95aab84d1b1fa516d41e092622574f295" + "ebf9b51e3825bb74", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "609d7f6a4769d94e1a3ffc6916c02b50", + }, + { + .a = "5f1e3012e6d330b09e72cfbae64d71ecc314161a43045cc1" + "39c06f35a9842a5", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + .sqrt = "2702e8eea69442b4e6172a2a604727b3", + }, + { + .a = "37f3b0d8b439d1154897e5570a0c3848df6bbd0", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + }, + { + .a = "7eaf05eecb0d43ecf2512817192528adf0889694", + .p = "ffd67dcb5d329a4a2bb7dd5714883bc5", + }, + { + .a = "105c1fa13632480e2b74fb6cf6bc328cc3942f9d8e53b98f" + "1cdbe90f20cbd421", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "40b738fd5e8a939cff33399ccf94500f", + }, + { + .a = "13a3407966b0d6d73397a45fa9be2b11acaecc6e80df03fa" + "ed2e048b044bdbd5", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "46e7329b7c7e48e6fa2a369589706b6b", + }, + { + .a = "22147b448cd5a73ec3034e900e5e35e2c7449ddea0217f7b" + "65fc368cb7fc571", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "1759ea6c3c8c4564b5978c40efdc030a", + }, + { + .a = "e10c85d3fcfda9437b148bd660ad5a7ebca4d80c8c68c524" + "6ceb0939273b4dc", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "3c01ab6ba6cbdb7e8516e22542b2b18d", + }, + { + .a = "28f0530dbfaae27d8c0d6681d32a5d550cd335c110b789ef" + "2988c39b6c4d3294", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "665f9acaaa3c55e7088bb93dc88fb6a3", + }, + { + .a = "4962eae6c1079bb2a5ee60600f9b9c9db0715a9779c20a5a" + "8415b20c4b3d85", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "8910bc8cbf206a16968ee9607017bb3", + }, + { + .a = "15d05b2c3428db47461d4b90e8146dd4b4ad5f86465abb8a" + "7bb252ca423ff7de", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "4aba823c04a7ec0d08070999f7ab5965", + }, + { + .a = "37c0957199baff074190dae6fde2420a56748d522ba89182" + "13bdda91a171085", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "1dddf264310f08e6d212b7809744b075", + }, + { + .a = "1170b6f4f5c7d90fc1127a987baf05d47c1f91b62ba0dd01" + "e2ffc3e61e26544", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "10b462a39a4ea25517c916ca1267d4ee", + }, + { + .a = "dc67e90034f4b1c96158d66c61ef94f6322bf30540767194" + "289d50a0e64a34", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + .sqrt = "ed8984640b9032ff7d5dc6164ea1f40", + }, + { + .a = "6412bbff1fbbca4e25a7f59fc99722dd655b1941", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + }, + { + .a = "a98c16965781b8b6fb49a1fdfbefbd00ade3dc92", + .p = "ce66d97f3c1ed87b6103b64014e37bb5", + }, + + /* + * p = 1 (mod 8), short initial segment of quadratic residues + */ + + { + .a = "b0b43e2686e8bf81e07908ee0315393cde48656e98e2c432" + "3bd5133a07a1c76", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "352c0a67702fab872833b758680a99fb", + }, + { + .a = "c95dc97c4405b42ccc6bec830850684245262d383756c231" + "8dd79378a9f8669", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "38c2ee16f6e355ea53e346fd9078f655", + }, + { + .a = "35379a66ef1ef5a281091c35966a31d312095cb7ac0959a0" + "0f99997ecb69f251", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "74b85e7a7766ca98047ce8a702c9ebd5", + }, + { + .a = "4ccc534c7ac3ac9526407a4aae616151c8e5a38984f59a9d" + "b5e75f03c296", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "8c371cbd5d69a8d82889263b56773d", + }, + { + .a = "e30807499ebe6f6c89322fd3c4b428f11ba4952f6fbae497" + "c90edc5297bdf3b", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "3c452e6bd40178ab4cf09f121a9a89ef", + }, + { + .a = "24dc33460e63ad6ae3d5e659bcfcf7208f083c804501a5e9" + "1b12f0478c6f5f2f", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "6123de04bebd162ffb002e0500ab8359", + }, + { + .a = "26c2a761b5d95bc3847ff7a58825f249738d9c1eb8a003ba" + "53be67dd6a4b92d", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "18e73380a4810e17bb114f3e1f38bb14", + }, + { + .a = "362b43adb6aa4f3f7041ee86d42ee37897495fbcd2a52a47" + "9e1a80493f1fbc7e", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "75c264b8c82dfb64c9cfee3e0c64c699", + }, + { + .a = "7364cfd413f046b4bb886cda3d7dcda21f619ebb715a5bd0" + "6cc3833be5d4107", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "2af7f6495da83f2f27d947cb982cec03", + }, + { + .a = "3e7559de589e876d2fe6efd091a0a91511b7334576eef8f0" + "ecacb298b61838a", + .p = "eec87e1e532b9f1a091122c4cff81d01", + .sqrt = "1f9cbc8282c070ed616cc1a97fac79a9", + }, + { + .a = "25ba186abff6724df832e524fd872f6306adefbd", + .p = "eec87e1e532b9f1a091122c4cff81d01", + }, + { + .a = "59193d6469d246596bc69cc0030b2e0a0ff2296a", + .p = "eec87e1e532b9f1a091122c4cff81d01", + }, + { + .a = "1f14cb634a8e3f4f262998e8e661b91b424ec91b48e245b2" + "0c7b79d21bfc9307", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "59336bf333f7dab3f26b6e5b3d580ae4", + }, + { + .a = "6b1b8ea97893defaaaa262bbedec178071cd0de9fb5b1bf6" + "35148c2880bbcac", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "2965aa4725e333b86683bf030fd5828d", + }, + { + .a = "12996d48b6f9cc889c9173399f5f4db773f29a964a192980" + "2183f3939b94ab8d", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "4500cab9ab7aec1150b1223ee9cd7049", + }, + { + .a = "3dae5dd26b2373500194c86816b27350a53aae4b5dd31531" + "01d5f6e5a9d3df4", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "1f6a38ef49cc8bd1eef8883f1491227f", + }, + { + .a = "9e2de20f229e667f8e79d43f9f31b890f8b9b58aba382037" + "ae889c6fc807bf2", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "324ec7636c3dff4fa3253fbc81af6dab", + }, + { + .a = "80d25f2f19978918bca80dab98de01d82ae3b169ba0f6e89" + "03d21cb4fc27329", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "2d665de92ba36cd16eafa053f5dc4ef5", + }, + { + .a = "70410faf098a2039617c43dd4768c4366f3583a543d74d00" + "7781d5fae6308ec", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "2a61492be8dbba6a845ebf0d132e2698", + }, + { + .a = "5a35e960ebdb0461f1867c55fd8e4f1e626a7facab744924" + "2c92e8fe724c17b", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "25fde03b1a02c096f8383c840443c2d3", + }, + { + .a = "a1d2ed930145ab18b174126582c20cc189d64844227bcbd4" + "6437cd12564cee5", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "32e24ed1bc281819156635ca43ef4a4c", + }, + { + .a = "7054c96a5e8841dcc19561c1324d5ad01c31e853eb73f983" + "f4d3b86a199cbb6", + .p = "c6f187c92de82671e10480e2f38454f1", + .sqrt = "2a65023c989bb86d8ea28dce73589cd5", + }, + { + .a = "be49695b8e19d4480f861204bc929de31e6cc630", + .p = "c6f187c92de82671e10480e2f38454f1", + }, + { + .a = "3a0c60b78ae72dfe52da83947fa263ceb2db906b", + .p = "c6f187c92de82671e10480e2f38454f1", + }, + { + .a = "165cf974fe4ed624e4f37336c62619b3e7e810c12efaa571" + "5edddc9fecd73a43", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "4ba9df1fcfeeb2d1c8ee0ac376216ef2", + }, + { + .a = "4678e362dc4e15b9398f7ccc8fa691b6a05ba26089a0ee9b" + "b6b538a62e96043", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "21943f77370cefaa2abbd82ec27bbe25", + }, + { + .a = "7eff91bde1563cc1919ae3a81fa35182a6a44454164c9ba4" + "9e3f3cf689d23a1", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "2d13d1477e40f4bcf7df8323b1f2c103", + }, + { + .a = "1de4798791513fe1babddcef80e6a15c996d15f5b70f584b" + "9ece3ca9ab76d2cf", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "577a7a0479f552028216368fb7a36ecb", + }, + { + .a = "82732b80ab0df57861ffec20a3c75c270bc5e134eebb264f" + "99d8f3ebbd53ab4", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "2daf94bf89a6d4b92d99f6ec2be281b1", + }, + { + .a = "27eb19d9f5b57e8b8eb038da5358a95908dcbeaf7910a9d2" + "7b063d6f00850fc4", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "6516ee003d56d1d4eac285a97de1af3a", + }, + { + .a = "12f3ebcf10e154bd69406ed2df0fe0ffd2f613ac45e69c4b" + "bec2c33247a28df", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "1169f787334a104e5da71364960bb4b3", + }, + { + .a = "81de8f01e74ce3a1b254c9f2a18817c806e50a3c95903392" + "943ea1b8ec0d2ac", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "2d9587643969929cfb837f76ca325d5d", + }, + { + .a = "148c6cdf92945f7111d9ad5ad4a206a349cc46be1a89781c" + "1b09780f40cebafd", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "48875ebd5c183cc3ae177c2506c27249", + }, + { + .a = "fe6ef7838aa594f982ac528e59641752e0a4873ef72d900d" + "703462f5f18c20b", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + .sqrt = "3fcdcb3f24ebb63257de3e9acd379046", + }, + { + .a = "704e6918f3a0a47b167296642e1f6c064b5fed6", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + }, + { + .a = "e10a7f7f045c58adf44a12fcc6cec87bd63b75b", + .p = "debc88c58dfc9ad8e61d69f61fc52d49", + }, + { + .a = "b9656d002c98fa8c120ac1db4a05775df1c3319de5bfb690" + "1c0d264f372014", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "d9db3f403b9e424045df0a09e6cd899", + }, + { + .a = "1974d77a065c76035af3290bb7dd8e1cddfc19c59facb248" + "1639bd8eee190b", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "50ba19e7001bcb74ee9d6df6933e18b", + }, + { + .a = "94751c7af51c0786c679e31948c0489d12fabf16c8814bad" + "906b3b41e6b229b", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "30bcbc5bf9b4bde195aba7aeefa44bfc", + }, + { + .a = "3dc05f7bd4aabe0a68e366abcc0487f1a10c4c179cb665b7" + "ccf4f39ce6063bb0", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "7dbb39e9a61cdbcf7e83b21483d922f6", + }, + { + .a = "208977daf6a72daa5c5d4e14fbe2e28fa533753867d08329" + "5af878df4c7e377e", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "5b4413582ab1a3ff47f447cc08c0d0ed", + }, + { + .a = "3de30458947b12443eb955b8895c7b45db79e53805a82933" + "3b93dee77f4528e", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "1f779e770a66ab59075023137a0f55fd", + }, + { + .a = "18f5f5e27aec608f1fd5520a17983aba52d6a1d0ac3d88ec" + "0243fb82a649ec4c", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "4fefee3399d14feca488bbafcbd9b10e", + }, + { + .a = "155a7cab9f3549ddc09cd71691144e147b6471e3e9ecfef2" + "6db13e9fa385108d", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "49ef89b4f7a44d54bba946b799fee7b0", + }, + { + .a = "567ec8920ee7fc5d5a66fd5fb6714a449dd86220a424d4ad" + "86f0a6b31b7a3c4", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "25337d299557bb92261fd1fd30cc7236", + }, + { + .a = "1d3a6ca959af4a5d1cb68a950f244400259e87f51c6f29bd" + "ac8905767b7e6342", + .p = "fbde582b5fbe2da75cae71930eb93f21", + .sqrt = "568042169dc73549d6345470ee1eabb2", + }, + { + .a = "ecc06a093a4b1438a644026f9daba3dbfee04846", + .p = "fbde582b5fbe2da75cae71930eb93f21", + }, + { + .a = "4b770b922a4704dd5dcfb1b44bccc4bc79d75dd6", + .p = "fbde582b5fbe2da75cae71930eb93f21", + }, + { + .a = "142f20f570f05d4fe64988f56be3ab87aa855d4f8b145dda" + "7176d7b51c93e765", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "47e1fb727135a208cc2c7ea7b0c379fe", + }, + { + .a = "979a2fbdbf6fe322c4b7a96d1b8dcf98aa337ee09989d42b" + "2846137dd294a18", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "314031569a866f17741995c94339eff3", + }, + { + .a = "1125db5aba454aced382b162c403d256b4b74f15a8da2bd9" + "8c7df618069b5a00", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "424188e0d7180cc52c9cade1410166be", + }, + { + .a = "5c15ec51bdca83353cda8dae1258b75eda7320fb2b5f61fd" + "9c2dd4ef047184", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "9989bb94715481c52520a8f18b5d16a", + }, + { + .a = "a14e2920e9a3d3c9dcb2b2625570c2799d1ec9bf13eef681" + "6a2493e0bb67abf", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "32cd6adb81261c417dd10a2583a2d1de", + }, + { + .a = "4f7e44dd885cfcc183c4c6a81bbc54029b5ec16a57c18d2a" + "dcb85ddb1f674a", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "8ea784baad105cace13c408e30333c4", + }, + { + .a = "1ca8323e809c9adda0190816e6083aecf2d7249f111b80af" + "e243f3ec95b07909", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "55a6cf22f6779438a874c1790ee79b01", + }, + { + .a = "241ffcdf08f03805c6ba3bd1fe664a031aed20225e841269" + "8df05607921bb7ae", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "602a9d0981fbdf7429190008e771bf43", + }, + { + .a = "2005bcee577a5a69d7d38a7c33c0f32a5d4d092cb961369b" + "8ce8718596581c5", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "16a2a5a7aed60909e10cdde80133b3d1", + }, + { + .a = "24e5fd362ef16d84a64f25481f99daea591b537726220bcf" + "59ecc270559a1e21", + .p = "c579568a7fda58a3116a02bde4c395b1", + .sqrt = "6130c332ad0069454b0e327e635ad978", + }, + { + .a = "aa65d05d557cf6a73d04668ac5c474cf738d20a0", + .p = "c579568a7fda58a3116a02bde4c395b1", + }, + { + .a = "b0e60e655eef70c827476d6706b8ebc040392f78", + .p = "c579568a7fda58a3116a02bde4c395b1", + }, + { + .a = "2e2f92d2457763400965223456e5fb40f67df2022e1b397a" + "f37ca2135582db4", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "1b2f1ed46b49eb6a0529b395c74f44bf", + }, + { + .a = "c4fab9bdefce241989dc61671de4c86d7d7644c02c0be973" + "54a9f6d865b8128", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "3823c5f72e6d52d7022b4cb12a312f00", + }, + { + .a = "13d0f37f258adc9fbfbde054fb0a9560eacdc5cd8ccd7cdc" + "928730d1b7e1ff4a", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "473982d7a7015f122afc0a97e94bf72b", + }, + { + .a = "e7593a8c8cca00d2996f301e0b2246f12609bcdff086020c" + "8e78ad216665e", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "3cd73095a2a43b2dc019896d5f51fab", + }, + { + .a = "1fb9fe423f25e1546d266fee359a6b65cbbf4fa49822f597" + "76a67f989057af2", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "1687d08343e40b4750c9592bac920dbc", + }, + { + .a = "dbb601ad3da8e497e34eb2f541fcd576dafefa41751a18bd" + "435ceefbef0c44a", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "3b4a64d9bf6ebdd2bd243432c0d532a6", + }, + { + .a = "6d71e7136f775c460d920b0796c8df487e7dc97d22ea5d92" + "e8bce3470504a13", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "29d8abe2fb649295530753aaf1327711", + }, + { + .a = "5609c11c6911640ff282bd04ce8400a1221c097df2ef63ed" + "4ac8b4e999d51a5", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "251a49ed949d8ddcc69aa3d6dda2dbdb", + }, + { + .a = "2df199e2eba7bd3163719afb875e1f64bb5327a51c2e9fe6" + "c56ef8592a9598a", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "1b1cdbcd9320d9443ac170ff59d6c27c", + }, + { + .a = "2c91906b42c1a3c210516de02bc028f1f2916992158e13b6" + "03565a950e1b863", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + .sqrt = "1ab432280a0b62a6784abdb8ff2d863c", + }, + { + .a = "ac93b16f0e514f2d4ea5270fede89adea8bf3205", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + }, + { + .a = "74a3c88c833d3c186c8ddfc0ae0cd9134503c933", + .p = "d1bd970108af0ab47a7ccff9c1f7b6d1", + }, + { + .a = "164e6a030c238052514d8152aed4f20009275ea0555e7f14" + "f2789eff29e27be0", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "4b913964a95efc1abff3727531e6d1be", + }, + { + .a = "121a1159c2305a9bc5b85cd1ae1cda94cee7dbfa471e99f3" + "5d5471c7bffe918d", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "4412f0d87aa6931d475a536af11974aa", + }, + { + .a = "205b1ab436bfcb8c64aca2a495d47c16703746de53edfcbe" + "71762c73f73cd7f4", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "5b02f5b0766eb62563120a97d3da7016", + }, + { + .a = "1a84a5e3bf3784e752c2734c536659b1daf6acd4423c7ad9" + "c89c56fc2959b6df", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "5264ac2cedc3afd4ed552aeead50c87e", + }, + { + .a = "a008aa6563a2233120e31e75f2bf91c4c32ddfbe4ce80e22" + "c10f16efe9ed7f5", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "329a0f3350dba44da9c0fa3fb3001460", + }, + { + .a = "3454b1dba0a1eb696492911db8d36c58fd1f283802533765" + "984e3f5c3ce0dee", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "1cef9f32af8abe01ee1fb856df4a9619", + }, + { + .a = "24cc035dd244bca942b1144f4533548fa36faef24f838deb" + "371870df172474a3", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "610e8750278f896c548f5b8f6c08d896", + }, + { + .a = "24308e5a0df6a24c4c01726759757ee155ef2f107b4d69d7" + "90e1c66b47beb33", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "18102a01dea52cf26ec7bcd9ce7bcf1e", + }, + { + .a = "2656e62c6b0cc284f0cb348094467a51d89eec529b8ffcfe" + "f34805a2211fdfa1", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "6311f6d63ed3fdd25ea3b0b44444fcb8", + }, + { + .a = "227ea04bc695cf6afc9ae8414776f4a4a09b7baa3755eb93" + "569e1c6e979a09f", + .p = "cc0bd352a591f8665ea869e19947a909", + .sqrt = "177e2b9aa023b58ab846307b1e948d16", + }, + { + .a = "2b40088613eb00bcaa1fa590a18924b12876e414", + .p = "cc0bd352a591f8665ea869e19947a909", + }, + { + .a = "2ef7c6d7541f87a19fa4f788bc213b2e4807eedc", + .p = "cc0bd352a591f8665ea869e19947a909", + }, + { + .a = "22edc2d92411cc04ef7ad3119a87a5e12073d9e09c74539b" + "be76677cbe145ab2", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "5e8f9636712aecc1a01b915baeda4f76", + }, + { + .a = "29fea5f62359b09c8dbb54de10637f04295258dbe34e91a8" + "3dbb0f81447c0f", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "67af71fc655003a5abf936a9ac002b8", + }, + { + .a = "8f66c7428f3d42ff8c1d5ee690d8378457d6f2398d7031ef" + "74663b895758689", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "2fe66fbc713a5304afed6b054570859b", + }, + { + .a = "fd9a8bfabaf8bae3776af4c4863dd94751de970d9d27a8ee" + "12ff19fa805f721", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "3fb32357d34705010c2c57f5f01d142d", + }, + { + .a = "2fc61df839a0b92ddeb05d69df8f5830b13faa5325cbe198" + "e9731e1892c347c", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "1ba5c042e81e591307e09615209ed8a4", + }, + { + .a = "5721f5f2c40a81655246041e141a8399cabc43e19c866568" + "568d5383337dfba", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "255683ec2efe5057dea7391c5912ae9c", + }, + { + .a = "2c7a60d81f0a2ee7e1ff17f0271be4af740fe7001e6f9602" + "07766cffd9dd583e", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "6ab4fc3f4f0c7674d9443ffbddf70d99", + }, + { + .a = "3a167990a328fae6c924e193fd37eb420eb5761dffbf6269" + "b7f1696b6598ee", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "79f1ce74a61de8d2da7f4fff2421e30", + }, + { + .a = "13ca314b6be0b28ade1f8d3581eb137f8196a74f8f3f801b" + "7410bc0d12d49cd", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "11cb571a0d7832a5131c3bd9e2b2175b", + }, + { + .a = "2ac0f52b513f3d5dc1aad96129f2d68f3512b1a83a9ed1a9" + "8ae07407527c1", + .p = "e2fd3d48b3845be5df89591787fd68e1", + .sqrt = "1a278fccb0eafab3c74cdb5a1e0660a", + }, + { + .a = "b3b7c12e0c3c394e7b41748f46bb5a71422f44fe", + .p = "e2fd3d48b3845be5df89591787fd68e1", + }, + { + .a = "c339daf5e328d836ca0274464ead34c8d4e8b3df", + .p = "e2fd3d48b3845be5df89591787fd68e1", + }, + { + .a = "1cad67a0472e3d78ce2f4db0079bf3d3efef4c16bb8b1295" + "df85c8790aae9586", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "55ae976c8da057f164602c832173e3bd", + }, + { + .a = "1f2aa0fa2d7aaf972d75e84280b1c193bbd4de6de474a1b1" + "daa929b44805eaa4", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "5952bb50076a5002d4fd98ee1b234bee", + }, + { + .a = "18b96cb4952e56620973262602bb7c65b81b7155e0561c0f" + "c27e611cdaca4ebe", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "4f8ec4312a94b37af9d2677320b55d88", + }, + { + .a = "19c0b132a768d471e98aec9b3d06620894d3909bae11fc3c" + "3ecb9f33c7cdac28", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "5132056926467b9ebc503517eae731b4", + }, + { + .a = "2e91ee9e3f29a743a7ed896237b1cdc4ff7045391128a3fe" + "1fe43b7eb33b88c8", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "6d3006960c9822d8e3e20277297f2b4d", + }, + { + .a = "a89e2e2f33c155e357ace3a22721d0acd7b7c754698e6f46" + "b75c5b8507315d9", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "33f0f13b9bfbccfc3af5ebcf2932234f", + }, + { + .a = "bafc09132b129b127efb13fca3e56fd94d70f5e60664d93d" + "6e56bcfd43f138", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "dac9a361004882677076847427fc17a", + }, + { + .a = "2ca6dca28ad4a0c1b16ddbb1d9439cdfce6f8220ddd77af8" + "192d157f0cc18a", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "6aea4b1e58873c72cf789c7e1b38c67", + }, + { + .a = "aacc0a85bd836d8b31aafaa15b5b30198cfe32943796490a" + "2f66829fea31ead", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "344696a190e09e2fcc7c162be811ea3a", + }, + { + .a = "145df6843833e76a7d4f7b9ee3df29ed2a604663887296de" + "844739e5f2c59086", + .p = "dd371a07847d0e0ba15fe277859db621", + .sqrt = "483530d37ec99f64af73f91ff39c2071", + }, + { + .a = "b73e95675c9ae0eeb18640fb9e9363ec44c83275", + .p = "dd371a07847d0e0ba15fe277859db621", + }, + { + .a = "86545503f6b37446d95dfab5af4536927ef7c949", + .p = "dd371a07847d0e0ba15fe277859db621", + }, + { + .a = "1a0ca94f23fb2ff2f05ee6edf6c5288ee6632c9bb78b1f27" + "a1418ea74cefec90", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "51a970741b5119c5d0f3ef99ee70c620", + }, + { + .a = "40941999acd5ecaf4819064d829274799f81c557c872b94f" + "9c55f90669bbbce", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "2024f113a8ff4531638916f5ce8ce437", + }, + { + .a = "1d2b395e6e74c7a9c89df6b709b809747ad27b2f39e2c84c" + "c6bfe6c88c591a48", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "5669c103c43a3e71eff5067f1c64689e", + }, + { + .a = "256567c23e2f5efcae74a5ee4390c2a53371f70cc6a391e4" + "6cb41df3ac32d795", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "61d801f9493c8dd4df81bdec46b11044", + }, + { + .a = "1cf702151efb378046c6e1ff7c4fdea64dab11de545b18cc" + "4635faff50bb2023", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "561c45e4d90fbc3d67e257d464522362", + }, + { + .a = "2a76050e09a73aeec0b232bd0c58141f1240c51fd0e1c802" + "d2c6cf88090cbeb9", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "6842672d2370bdef87261e322caefacc", + }, + { + .a = "3a947f3f87fdac9374669cbd3f426629b2b4b0813a72679c" + "91bf1536b4bdf95", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "1e9d73ae67b54e8c1b37638ff2c5e17f", + }, + { + .a = "a2e97855accfaca7225f22b1956b639f40dff10ee0767b7e" + "34e8daf8af129d3", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "330e06e86764464282b30f49d39e279b", + }, + { + .a = "233a0d4f8e8b10457cee27d567331ada6c3bb189737efd83" + "6461a7c3b00e0e40", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "5ef6a2fd26778224d90f8d922c064306", + }, + { + .a = "22e5d6d527c72836c1120fb64094f939bf0bf7739cd999f0" + "7e04c68e3223c074", + .p = "d8708392da9cc40e2cc47ad468621c99", + .sqrt = "5e84dc6e6d114b48d36564b1d9881eac", + }, + { + .a = "766cf945129c9768cabe5c8bc206ee011a133fb3", + .p = "d8708392da9cc40e2cc47ad468621c99", + }, + { + .a = "8b8061d0214fb275eb3edf0ac4efc12983c5188a", + .p = "d8708392da9cc40e2cc47ad468621c99", + }, + + /* + * p = 1 (mod 8), long initial segment of quadratic residues + */ + + { + .a = "121a50ac860d84f7632ea520155e45108edbf726ef400312" + "af265d6d6b542aa", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "1104d9fa5277ffd941b2ca504033f3c1", + }, + { + .a = "12bba14492ac49da4e944ac02ac9ded3a2d449cadbba048f" + "9d30d2a96f6b9e1", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "115007fab662b063f1c1a85a986d9574", + }, + { + .a = "13d8ac7d33c3ea1bcb184abc660fe5ff6ac0b3eace1f6ac0" + "76425b4a70b6bf0a", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "474762679be31397e717f008a6d94c44", + }, + { + .a = "331f552bbda4b1d992dd79a7dac65fc714d6123502efd1ca" + "131eca10e1f832cd", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "72665e9479b1cae103882e27b3896e4e", + }, + { + .a = "d39f0377067e6d7814a3b54b74d5fc877e6a150a842dee80" + "2a5b35f434e94ef", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "3a3056445c077b79b88dd4feac16ee6f", + }, + { + .a = "59ffa4f211e11e9e28bf06313768d9e6f30539ce99a64803" + "3b147f97992630b", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "25f271261880530813283b393df6d638", + }, + { + .a = "196e733b9783263e5097a258d393314e518d78908dbbd0d9" + "8e835ea8811ded62", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "50aff6d9df607c2aab6c09da72abe272", + }, + { + .a = "1ad74de96a84df153ed96f4f3305965c688ce85c8e8285b1" + "16551b86fbf46c41", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "52e4b15907eafab6fab028f7ff777318", + }, + { + .a = "d559fae722d3d02118faf185537d3b9872888085c08f0e33" + "2f79667588a85", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "3a6d1d1324934f1c6ab27f4340030b2", + }, + { + .a = "1fda911e045e686c13d0ed29ef87858456bfe08a6dcc64c5" + "044dfa62c2c48755", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + .sqrt = "5a4d79d775b65857a6a3eae7e6c65fd7", + }, + { + .a = "c2072a78c83712d1f17d1f4d5146a0b14068e152", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + }, + { + .a = "4a46c4c627d798c4a3d26f415e869f18e2b8cd60", + .p = "ee690b3287cc4bef7173d1ae8c38af11", + }, + { + .a = "33a4da7f8fab68215f235b974676bb5f530284c9c4346bd2" + "9c0904947b9893a", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "1cbed89a3a6add32a2caedd7aa666d4a", + }, + { + .a = "12454eb2f4fb16b606b45cdd2f1964bcae0c638cd67eebbd" + "6e3c12cb58303d0", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "11190392b941d3c89014057d43c2b933", + }, + { + .a = "1be7aad902860399a59a3a4ab60355a96233a1095785d78f" + "7ef1fad6cbfd499f", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "54852d0df6fc249853261a64a8bfc356", + }, + { + .a = "171d95cc535784789996b38108bf0570f7bf822c848bdad4" + "017dbd03006159e5", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "4ced03f935a5b8e00177ac488ceda8ed", + }, + { + .a = "13bc64edf2aa045dff33a834f301b9ae53f21b0507a52a6b" + "9bb9f70ec9fa95e0", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "471487b8b79cd2cc1562319251cfd065", + }, + { + .a = "575eaa57283b6ca36106e03ac951f1eb514aef0871563f17" + "85b83ae61972cc", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "958e0d5480ae5eb29c7a2031e5e4747", + }, + { + .a = "1497fcf0a83b6d52e15c77e5ee46c84843e2d405f8551c16" + "961fb7ff05f0df47", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "489bc3d8bc5b72090a498a3e932cbccf", + }, + { + .a = "8156269059697cbe658d596ee7316dc56e2da0f3c9c6bc94" + "2e318b4f92b3a", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "2d7d908fba94f97f14510009d92f58f", + }, + { + .a = "52d9cdd76ed355c0b91964303075ed7ed5b6bf574c78166e" + "bb57797cc5988d", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "91a2c7ccc1fa93a8353d40cd3567b0a", + }, + { + .a = "241675d474e36edda5c3b52592f3ca2778b80e3cc9d7ccfc" + "ff9acea456fad162", + .p = "c94395af7aa282d79adc16e955ceba59", + .sqrt = "601dedc64c2739d55eade2b81bf9f8c3", + }, + { + .a = "1c1209a5d14e9c5fd860b4095128e11d30727138", + .p = "c94395af7aa282d79adc16e955ceba59", + }, + { + .a = "56962f61002646287cb6213cf007e2b812757b3d", + .p = "c94395af7aa282d79adc16e955ceba59", + }, + { + .a = "53277a6735ee7f2b1e6a1ecbaf7697da5d13467f57c2696a" + "7ae29f809cc2bc", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "91e6fc750eae4d47389d23991722161", + }, + { + .a = "fb3df21f43f9d6b0454ae88e536fbe2562b90e242e9d4813" + "859f853e37086e", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "fd9c1dcee2d6f1e72864100bf2250f5", + }, + { + .a = "1fe8895b0f43e7c7cf435a9708d90fa6af7e102cd797f1c1" + "06d28f270ff6ef0", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "16985135456ec55e3725b2649e85f1ce", + }, + { + .a = "8c18527907be48bfe6bba3f269b16accf36cd895650d6b9d" + "e1f131f3fd6b2d", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "bd60f7b30295f53e4b330e67945b6b7", + }, + { + .a = "27ceb721ee3cd6332803e248b636270c224fbad700346d2e" + "a5568d415f99ded7", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "64f2f6748b0c7dd09ad91e9987e57627", + }, + { + .a = "22c6e133d12d207d07d9a0884092c502e77d38c260f6b23f" + "7d95611ffc98be4", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "1796b981cb621d743e84f701e0026dd9", + }, + { + .a = "25893abcc46a5a2aa1a62ebd893decf99a5d9f5d6d6a094b" + "876f3ff330720c4", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "1881b51449505ca0bdb7eb4f6c7ca0bb", + }, + { + .a = "bc4082a238d1575921b5eaab6627422cb203184fb28f0e08" + "6060e840dc1899c", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "36e1c98a1360f6c88e4d7e949a6796c9", + }, + { + .a = "11cd69e093fb539abe544337e8a572a6d90f9d5c64535b9c" + "c6ea45b5fb873b17", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "438234d3d5d8a32f5c0fdf0b08364d15", + }, + { + .a = "23c0c8b1387989e141f57cf845d006452579c911f9f524e8" + "6ca76ce6e15cffae", + .p = "e01ad2e26513df5d8863c0407b51c089", + .sqrt = "5fab91205cecc253a5ef159f1279f7ce", + }, + { + .a = "16506dcf1e424dff4ff0163ff326011f2db4baf3", + .p = "e01ad2e26513df5d8863c0407b51c089", + }, + { + .a = "7c735c98cb5e13142fb42696c52dea4f86c35f27", + .p = "e01ad2e26513df5d8863c0407b51c089", + }, + { + .a = "1546a26d92c7a1b90e846b8def8a95dcc5fd8d098681485c" + "f9f40454c2e56a44", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "49cd2327060e71f193255ab50227b50c", + }, + { + .a = "40d7e51170443f269b12256b03b7f78916639a565bb91683" + "7afae2c07bccc81", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "2035cc0bddddef9ab1a6044f713e0e2f", + }, + { + .a = "12b4099bd0acc2e80398c544809f6ea261d6cfc6753ff181" + "7e19ee7cd5cfebb9", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "453215e8591db1b9a53f077b3e388bd2", + }, + { + .a = "7e978b624e693fda3c0f159fade85c07690c840dec951b49" + "571b7563f4f55", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "2d01575650de55dc3553c480bd5d61e", + }, + { + .a = "1851ce97073e83d6e3c76ece920c5d91460ab827eeec431b" + "94adef9c506c80d0", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "4ee75e54c41de8a702b6ce0cb35c7911", + }, + { + .a = "1eeeb89f9c697a2a08bff8da8dc6d7fd6e71f43b6922a7cf" + "8e89087734e24eb2", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "58fcb8ed1d1adcd40427574beb6b6b98", + }, + { + .a = "82ea9d2e6ce9f8a7e70d20bb3a00eb0951f0aa9602c98202" + "a33cf05cbc3f473", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "2dc47a644bfbcd83d67f001ec9f37ec3", + }, + { + .a = "7ee5b35c2a7284cce7fc26e681f824c7ef88b92ad6a956e3" + "04d32ea49935656", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "2d0f39c1415aa6ecdb216eba95e8d130", + }, + { + .a = "16691aa76616aa66ba8cb19138b2de30f3e19b4a5f1cc57a" + "cc7812c0344a0ca6", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "4bbe61678ace7fad9e1f61aac5fc4248", + }, + { + .a = "22a64631a16464b2b41f91a716213bc7f5289bd1b8ef5dfe" + "5de03fa85e43bf49", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + .sqrt = "5e2ea04651665b0764861ce7cd63a2c1", + }, + { + .a = "7904a8e905770d9c71da1bf00c1246d5365070b2", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + }, + { + .a = "7941e180046e485ad69df661a9353c369bffa269", + .p = "d9adedeb8bc5d4d1a4bbd07dc62a48d1", + }, + { + .a = "22c8e6edc37789d7738ec6dcefebbd607d1fdaaa7c584cad" + "61d1526800c92018", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "5e5da4530248bd7ab1a3fbd08f69f1c5", + }, + { + .a = "1ca92a917bec25c99039774b1246aa9f2fb5a2c9ba9f4f27" + "fa2b893cb3f559b9", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "55a84239f80708583d3f9a76ff73958e", + }, + { + .a = "1159fd297bb177aa585fdaa7bd4bd97ba5fec4770aaf40c9" + "277496ea0743f4fd", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "42a5f38ec5af19489aeb45e7bfcce9de", + }, + { + .a = "26f55dd518994145017f5fd0dc182be72ab0dcef72ead33b" + "2a69a803f6b19161", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "63dde2ed42f80e076e0481dbaf0cbf02", + }, + { + .a = "2d1189aaeea16c966889adada17bcb26232c86006015164a" + "30742831511eff6", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "1ada6d768160903b16fe877dd9aa113f", + }, + { + .a = "28acf490426026147635bdc6b062d6d04b635c9b99a198cd" + "86b47dc47b96e5f", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "1982cf14b64995642cd5dbd245c27afb", + }, + { + .a = "2fc7aefd1b206bcfb2644576a4c8cca7fe9a72a7b2e4dcc8" + "ed127ffb685fd14", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "1ba6344ba57e08173d21a98328b71684", + }, + { + .a = "f035046ddb03b1e343cc2e5dc24a91fe807dbd7906b2f16f" + "02480db9c8627e5", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "3dfe9533519e67d651b4c524b737dd99", + }, + { + .a = "3609bf3e9b32879a3add17aa6d1542c2f549030d23bf4cb0" + "4d65a353f11230f", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "1d677c1e06055bd8d77565b6e97b18f4", + }, + { + .a = "103a6d3816aa8b314402c12ffb54a111bfc100f599aa5f78" + "ff9574c3523e0121", + .p = "e26c6cd64976b9391f43981671002d69", + .sqrt = "40747083db7013669a8050e31542a781", + }, + { + .a = "4ce4c0d22add35bbe43784924de6dbc0906e533d", + .p = "e26c6cd64976b9391f43981671002d69", + }, + { + .a = "c5c1e597f6dd8751825916133738c2f42c04114", + .p = "e26c6cd64976b9391f43981671002d69", + }, + { + .a = "beeeb4fc61586d0d2d7149410c8bfaa7129f65cd12accd00" + "ae821bac17ba37", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "dd15d5ca7cdce13ab7e98c88fc88f19", + }, + { + .a = "2a0b5b4376ec8b0bbb8f0a283a0a317fd09589bdc8e693f0" + "031c2bc1a1ae087b", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "67bf2103f485c73c075cbb5f8243bad9", + }, + { + .a = "26c4d966b33befb307a16c8a87acab27a12f94b7921af11e" + "430adeacac82a62d", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "639fa027439489f0eef60d704e8cef98", + }, + { + .a = "29eadb8e533f3a9e325bf9bbbc9db41291f5c93281e02a70" + "3e7153c744a817e6", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "6797009adb6ae5b392734d13664e56b2", + }, + { + .a = "e4aa928dd30d75d78f5074e8931d697b45c4a65b6ba31109" + "86e9bd08fa3cb8e", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "3c7ca3274282f6fbf175d681fe84526d", + }, + { + .a = "32f1d70f5fadfb94c555b61651de9eea025b7150feefddda" + "6d5319eb6bdfbe37", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "72336c9bfae5183830819108df6061da", + }, + { + .a = "1c941c73a20169cb3bf4f4c3c37690d041402787e7d12156" + "6269ccbbc4990a46", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "5588c5d715f5f9e0c90823d91b6c7cc7", + }, + { + .a = "1579253f887c3a8185c70f385203a19b867d8bf51657e531" + "78ac6d665c7ba070", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "4a248a6f3b66c3dbcf633d86248b6bbf", + }, + { + .a = "1a12783318c06b7477ea1f2c7323bf1bade4969a5c2b2d1c" + "d5de12ca124bc7b5", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "51b28a8e6affa359cb3d437785560a6d", + }, + { + .a = "b42d6aedb666a8102825bcb9af19b001b37c1902cc3a5751" + "9775caa627d0c69", + .p = "e74a67bb1628c7b1d923808f320470a9", + .sqrt = "35b12ba2fc934dbfb1f447ea5063f20e", + }, + { + .a = "bf7b664d321a2d4a31c0d798f674c0e25a885ec1", + .p = "e74a67bb1628c7b1d923808f320470a9", + }, + { + .a = "2a324cfa40e3117fc1da8357e67be94c39365a56", + .p = "e74a67bb1628c7b1d923808f320470a9", + }, + { + .a = "82e929f47c509779ae81f2eb12dcac84c1288827cd7909ae" + "43dbb8bdef71eef", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "2dc43980830b15b0c83573d07afe6999", + }, + { + .a = "4589649eb9b85e1be15abcc1f48f2eb4c58b197ebac83abc" + "8d809024e40803e", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "215affc621edf6c85922903ab48ea658", + }, + { + .a = "1c868a42c164513eaf724725ca5994f241c16b2e68f303e1" + "b5d57b57c1183304", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "55747461ff8137d4e05eeaf2c29aa0a8", + }, + { + .a = "518e36afe548286568e99c20afef30074ecac2b1c25ac73d" + "9556855fda6e2c", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "907e3233f20c0db9a659d896a9c2512", + }, + { + .a = "4c41116acdaf952fadd8643ad7db01266cbbd3f3dc86242c" + "7b255fa17f7bedf", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "22edf0b170fabd22b9cd2919e45ebc77", + }, + { + .a = "1deb14e6e04d5c3da1bde36ed62b5c98b30d9637ce70d467" + "1553062f135fb743", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "578424546feb87643c07224b5ac59802", + }, + { + .a = "19b9585337d4bf6c126db6f56929140ceff37c6072503ff1" + "cdf661c36471bf", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "51266f7e4ea87ca3749d508ed010664", + }, + { + .a = "e79ca7697fb17fca33dc2be93bc1408b890da7861b685f4f" + "432d87a3f0f152f", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "3ce00d970ebd09af262bca93d838fa1f", + }, + { + .a = "2ad3e70e0575ddcb8a6b150eb98caba70854861249aefd23" + "d517198827f406f6", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "68b56a7414fae89868d5bf8352d273fa", + }, + { + .a = "13120bbe4f9aa9295e79f6e1d14c6e4ad6857a9cb781542c" + "d803927706a35b26", + .p = "d64bb8768a638d7f5d3825337ace2de9", + .sqrt = "45df23b41b892c677376741d846897ec", + }, + { + .a = "39c6f0ca17b31cdd576136a42afacc1951195d46", + .p = "d64bb8768a638d7f5d3825337ace2de9", + }, + { + .a = "364f883be424ee5552e3e2964066cf720981ef15", + .p = "d64bb8768a638d7f5d3825337ace2de9", + }, + { + .a = "2a482b02a0fa79c96ef9d00287b3b5eb306bd82d29cbcee0" + "d4698e0d6cad30fa", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "680a0d10bec5fd5a019917ee00f61184", + }, + { + .a = "dace96b6e89e3d170e76b81a9f023d9f364a80e9ff40cdd3" + "338e2b538177cce", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "3b2b230a1222cd9af8aa60978608e5b1", + }, + { + .a = "1350c9c08466500847eb0573aa711123b77d86a12d52184e" + "584496ebb278e1f8", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "4651b6413d019c9b27af8be350b9efbd", + }, + { + .a = "309971a3c9a159c454fe42fcbabe744b8ad1b8aa8ba475b5" + "8466da45a84de", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "1be2a35bf675130b7362bd13d1bd119", + }, + { + .a = "e88515de6431e1ac3259fc16bc996b369e621113c8505c34" + "ba18d7a77239e80", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "3cfe918a2d7deaec83f14014593287dd", + }, + { + .a = "dd42d98bed06e1eee7825a3df6ee9a9406b501801e35fd43" + "54538ed582c38b1", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "3b7fd868d0022fc7f467d06f3a673aef", + }, + { + .a = "e47b2f19b59423aeddf737a59b95433d6c335de8380113c4" + "cdb781e9851d2fd", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "3c765e522c77141a85a7f5be88e6dce9", + }, + { + .a = "1317abf2c6630cecee00a0b2c3619269c6abc56b19d52521" + "afdeed13e8181498", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "45e9714caf9599488f7b5f50663a6f47", + }, + { + .a = "fb4a9ec53f4b5b8337db3b52729f92660c540a57ba26f6a3" + "1132c3df8e7fbcc", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "3f68a0d5d9b6773b6462d520fc15a592", + }, + { + .a = "17bde3718d8c79dea7bf8177b429b9fbbe2ec377ee056318" + "8b1723601dfe97f4", + .p = "d3b5db60b30e3077d3bc605643d0a579", + .sqrt = "4df5f7e0af55aa287adf15f97d58a39f", + }, + { + .a = "9d6a2d424236cef8719d331a7352de39ecf44983", + .p = "d3b5db60b30e3077d3bc605643d0a579", + }, + { + .a = "c09b3647eca9c87b3a542b0c1e734bf52ce314df", + .p = "d3b5db60b30e3077d3bc605643d0a579", + }, + { + .a = "1d8903ab585dc5b9992ba2f4295e058111c46c3620554d27" + "5e46107e55d7a2c", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "15bd0fdd249f3c6a8c2f548736905f23", + }, + { + .a = "f85fac41fc1b4425c176f56f6e9d62e1e76e1b2211ef4fb4" + "59c33ae66b796c", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "fc2874c1abda2571ab8a869d1808175", + }, + { + .a = "e42771a0f23fd6acdfb6aa40aca83b16c58759815f4dc6a3" + "8fd3eef95cee3ea", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "3c6b48d5885c257eca850ffce85e46be", + }, + { + .a = "195fc0fe25e90c6173a995e481fee9e7e256409fe143fea6" + "1826da3486c3e297", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "5098a32cc135bdea68430ed532ea0005", + }, + { + .a = "b9ba371e8df3cd27092a0acc00e0fb452607e13a8cd3a003" + "515de9e1d7bda62", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "368342b57f60ae446e6effdf172b074b", + }, + { + .a = "110fccbd58d822da1cf00b2ebf75e8479fba35602ae212f8" + "7abe5470aa0a8dc", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "1085b79c4bb04aeb47ee70702a56c09e", + }, + { + .a = "770192a443c51e1652e7057f01317a4daa394f698c7e8552" + "a2708ce9a171da8", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "2ba2cf3f71977f2ab422dc333af01aed", + }, + { + .a = "d64e10830c62eca1dac4bc5f1fa566f9504bb15ca82c63a3" + "efa32cef3b1c5b0", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "3a8e7f5e1cb03581dc78638cf4860450", + }, + { + .a = "1e44103d73e7744ed150aea64c9781bb286d0c8896086aad" + "a0d01ec4018edd9e", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "5805e8e0c4c53dfa1e3ea9e4ef6659db", + }, + { + .a = "2602d83a0b822bf52b8a02e7a5df83d06bf6f75f52658484" + "03a60c25c70d2fb", + .p = "d221951118210ae00de11d059add5179", + .sqrt = "18a9486523c9cbdcc1d9d812345978a3", + }, + { + .a = "7575749b1df9decda4eeb931f3e077a35ab17cb4", + .p = "d221951118210ae00de11d059add5179", + }, + { + .a = "1ab8eec9aa32cd78e7fccc74bea5bc666224eae5", + .p = "d221951118210ae00de11d059add5179", + }, + { + .a = "1fcb7176f1300935e5f662830115c7330fe0a336e27f1ded" + "642f51a97f71f6c", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "168e01d97eb477d70cd284571dfff3ec", + }, + { + .a = "a856d9e3eb0073dc8acf9736094df283bfaa8ecf94d633d3" + "0c21fd34154c3df", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "33e5f39cdd6b39931e1295525323eced", + }, + { + .a = "23ca9267d09a2a9697887b8d71794f91e7ad6ee2282a6247" + "5d37273ea49cfb24", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "5fb8a8b3082f117d9c32ba395772f1f9", + }, + { + .a = "2e5adfa8b2e4baf9a120ad13afc13d420ea82b7b6552ef49" + "b93d827edd782420", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "6cef6806482bb27a8f431c2be11da15d", + }, + { + .a = "1856d952cfe49f088152e15c8a35a6e02e9e6471ef8ba7c2" + "a8085d01f197911c", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "4eef8bc5cbe83339d5363dd75fcb906c", + }, + { + .a = "809153ea20aab3373a44470d4a92e5415293c42084757301" + "4ecef756ebe3b6e", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "2d5ae64f52b011c2b47b196d3257815a", + }, + { + .a = "d8f2c65347eba4148fed9f5420a50727915e41417b090095" + "d011f2dd85d13a1", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "3aeaaa8f5a07973ffdc5c96e28c6b6a0", + }, + { + .a = "2fc2023299021c3bbd160fdc96f3f235105bec74eedd0bc5" + "ba2c6ba3aea5845", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "1ba48fe5d1a5c1b26b142965ce0dd426", + }, + { + .a = "7c57bc6f695242e8c31ea7ea07ccb856fd80291ab481aab2" + "66980264ffa3b64", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "2c9a8745a0f72ec9dbb8d2ad4e86e6cf", + }, + { + .a = "194e31d9e40a273b975b87cf5b4956b892b0b810e9c56d63" + "9731eb011f3b5bba", + .p = "e9103af488d3bc5209fe348dcf043dc1", + .sqrt = "507cbb530412e9a988aeecda15a9c9e1", + }, + { + .a = "d26fa79e1156dd232b5886efaf8b5b7a08dc5740", + .p = "e9103af488d3bc5209fe348dcf043dc1", + }, + { + .a = "cceefd8c7bc0a4b82b8eacbbcb786f9b21f6ff31", + .p = "e9103af488d3bc5209fe348dcf043dc1", + }, +}; + +const size_t N_TESTS = sizeof(mod_sqrt_test_data) / sizeof(*mod_sqrt_test_data); + +static int +mod_sqrt_test(struct mod_sqrt_test *test, BN_CTX *ctx) +{ + BIGNUM *a, *p, *want, *got, *diff; + int failed = 1; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get()"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "p = BN_CTX_get()"); + if ((want = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get()"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "got = BN_CTX_get()"); + if ((diff = BN_CTX_get(ctx)) == NULL) + errx(1, "diff = BN_CTX_get()"); + + if (!BN_hex2bn(&a, test->a)) + errx(1, "BN_hex2bn(%s)", test->a); + if (!BN_hex2bn(&p, test->p)) + errx(1, "BN_hex2bn(%s)", test->p); + + if (BN_mod_sqrt(got, a, p, ctx) == NULL) { + failed = test->sqrt != NULL; + if (failed) + fprintf(stderr, "BN_mod_sqrt(%s, %s) failed\n", + test->a, test->p); + goto out; + } + + if (!BN_hex2bn(&want, test->sqrt)) + errx(1, "BN_hex2bn(%s)", test->sqrt); + if (!BN_mod_sub(diff, want, got, p, ctx)) + errx(1, "BN_mod_sub() failed\n"); + + if (!BN_is_zero(diff)) { + fprintf(stderr, "a: %s\n", test->a); + fprintf(stderr, "p: %s\n", test->p); + fprintf(stderr, "want: %s\n", test->sqrt); + fprintf(stderr, "got: "); + BN_print_fp(stderr, got); + fprintf(stderr, "\n\n"); + + goto out; + } + + failed = 0; + + out: + BN_CTX_end(ctx); + + return failed; +} + +static int +bn_mod_sqrt_test(void) +{ + BN_CTX *ctx; + size_t i; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new()"); + + for (i = 0; i < N_TESTS; i++) + failed |= mod_sqrt_test(&mod_sqrt_test_data[i], ctx); + + BN_CTX_free(ctx); + + return failed; +} + +/* + * A list of primes p = 1 (mod 8) with long initial segments of quadratic + * residues. These exercise the non-deterministic path of Tonelli-Shanks. + */ + +#define N_SMALL_SQUARE_TESTS 100 + +static const struct p_is_1_mod_8_tests { + const char *p; + int first_non_square; + const char *sqrt[N_SMALL_SQUARE_TESTS]; +} p_is_1_mod_8_tests[] = { + { + .p = "d7a6133d89b7a840ec0d80d2ee197849", + .first_non_square = 101, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "127b07d9558aa7382fda337e674b0020", + [3] = "2b0756607c913be85534cec59846e6f8", + [4] = "2", + [5] = "1ac3bfe91dd86f91be44b30936b6bcff", + [6] = "3a03fcd8bc70d0a08444356250a316c9", + [7] = "22c3c29b3cf04300495e694db5a1fb11", + [8] = "24f60fb2ab154e705fb466fcce960040", + [9] = "3", + [10] = "46dce6880d735d143a40b99097f87f9e", + [11] = "3eab85485728056c43cd2681a96976ba", + [12] = "560eacc0f92277d0aa699d8b308dcdf0", + [13] = "19bf2319a32e92a6c2d80d364a19229d", + [14] = "51554e1d7adc5173841a9525b4a2ff7d", + [15] = "3d9a295185f27dc096b33184e4edd834", + [16] = "4", + [17] = "407d75edc1fba51c637aeddcb35abc1e", + [18] = "3771178c009ff5a88f8e9a7b35e10060", + [19] = "9e48ccec873561b315a0980c409c291", + [20] = "35877fd23bb0df237c8966126d6d79fe", + [21] = "2f4a3220291ac0440f3a2cb35d8e8f4c", + [22] = "218f85684d6378bf6a90d02b0f94dc11", + [23] = "432f4d621cc773b7945a024a076048d4", + [24] = "639e198c10d606ffe385160e4cd34ab7", + [25] = "5", + [26] = "8478976383e49d4fbda384883343e1", + [27] = "5690101c1403f487ec6f14822544c361", + [28] = "4587853679e0860092bcd29b6b43f622", + [29] = "47804840abaf4bc53e37c87291f55527", + [30] = "48925009cc14fbef1dee0b4a2f920890", + [31] = "228ef1765a5448f6a4600026dfb14830", + [32] = "49ec1f65562a9ce0bf68cdf99d2c0080", + [33] = "a41fb079bc22c9d1e5658a86db0e6bb", + [34] = "675b3a95cddf5b210dde6d3e7dd4cfa3", + [35] = "5b727e9bccd4da204cac92594babe837", + [36] = "6", + [37] = "64ba7d11b9d672e6d31a9b5971e60d2f", + [38] = "24afa6855c01017537555a58a70da6f9", + [39] = "3bb009b3541796452327d8e6fd8323ba", + [40] = "49ec462d6ed0ee18778c0db1be28790d", + [41] = "545f0385bd365fa7862502739a781f69", + [42] = "2b0b17173a32035911223d142ab00a4e", + [43] = "67109cc9a742fc0305d031cc20e7fd1f", + [44] = "5a4f08acdb679d68647333cf9b468ad5", + [45] = "504b3fbb59894eb53ace191ba42436fd", + [46] = "38e6358e14aa1cd9778b09cbf05deb48", + [47] = "319d132fc72dff9b631b3c2ca0c2f49f", + [48] = "2b88b9bb9772b89f973a45bc8cfddc69", + [49] = "7", + [50] = "5c67273eabb54418ef430178047700a0", + [51] = "3558bf08253c3d5afd58bd1c3c0498e3", + [52] = "337e4633465d254d85b01a6c9432453a", + [53] = "1845657cc9012fafd8a266bf41b2ce66", + [54] = "299a1cb35465365f5f40e0abfc3033ee", + [55] = "582fca95baf4c0b18befc9aa5b09aff4", + [56] = "34fb770293ff0559e3d8568784d3794f", + [57] = "62e847fb9f593dbe7d2f1a5c74594670", + [58] = "1c85e173426916ea88c889b950bd5d96", + [59] = "13e4d1ad2ef6d69c758826e554d3fce7", + [60] = "5c71c09a7dd2acbfbea71dc9243dc7e1", + [61] = "5bd4d7bf50d72c7642321ac648a41207", + [62] = "4d543e0b7cb7a087f6c6820871402203", + [63] = "684b47d1b6d0c900dc1b3be920e5f133", + [64] = "8", + [65] = "4720271c07130a09c11989006d5b65b7", + [66] = "27c5c5d3ef4be7d25b799ea455ff933", + [67] = "563c042e90bd60de622c83b96aad46f3", + [68] = "56ab276205c05e082517a5198764000d", + [69] = "40aabad2f12469f355cbd0e524021817", + [70] = "69f41210ae2c64ebbbfb9cc4436b121b", + [71] = "2495fdd3e3ee43c51d78a037f2af961", + [72] = "68c3e4258877bcefccf04bdc82577789", + [73] = "a54afbfe8d22b43dba10c45c3e1945a", + [74] = "387797174f3bf5d6281fe71ea18676e1", + [75] = "81635b1ae17cb7420576f6f4b6f571", + [76] = "13c9199d90e6ac3662b4130188138522", + [77] = "2095521a5b009be0acd08b5ee47fa519", + [78] = "2bdce5c6e97146d22fd25f4abb3bfa49", + [79] = "15d3c2c27cdc4411498596c20ef7d174", + [80] = "6b0effa47761be46f912cc24dadaf3fc", + [81] = "9", + [82] = "12af1ddc568bab9c8609a1069ad98974", + [83] = "4ba992f528674a24e7d11121eb88af39", + [84] = "5e946440523580881e745966bb1d1e98", + [85] = "1a0d8dbdac9222fddfacbae62f73dc50", + [86] = "4040b1fc21cc440034ac36b0e9eb9c90", + [87] = "1203e4b669c80a95eb2a5134436217aa", + [88] = "431f0ad09ac6f17ed521a0561f29b822", + [89] = "62aa36cb4434c129d65d92ff25a9c3c4", + [90] = "30f5fa5615d91043d4b5421262ff96f", + [91] = "2b64e196026445e615b7c019aafc52c4", + [92] = "514778795028c0d1c3597c3edf58e6a1", + [93] = "25eb81b5dcc44f0a8bcf7fb909690c50", + [94] = "48e96bc3845c7d38eb06fdf2d9274207", + [95] = "18ae0da0ae22f6cdee901b535977cfe", + [96] = "1069e025680b9a41250354b65472e2db", + [97] = "6bc184c777e6c859c4ce144eb68d6bef", + [98] = "5648dc4c32ed15b79d16185e1b0c7769", + [99] = "1ba38364843f97fc20a60d4df1dd141b", + }, + }, + { + .p = "ed2ca93a2b8b7053b5cbfbfc164284d9", + .first_non_square = 83, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "3a3c6e5ea115faa8be69eac1c177f698", + [3] = "2748dedd33f6c6a09f84973f2f862922", + [4] = "2", + [5] = "d7607decaa9bfe5ec031537ce343ed0", + [6] = "401d83de7c83456c0bee28fd25829dd5", + [7] = "21f72780e6f6789259086212c3e9538c", + [8] = "7478dcbd422bf5517cd3d58382efed30", + [9] = "3", + [10] = "28f8f6227299e5883b1a59e07b4cdec", + [11] = "4b557ee20b98bd00344c14563ca8f839", + [12] = "4e91bdba67ed8d413f092e7e5f0c5244", + [13] = "10242586b3f9e2ca74409066950b0dc", + [14] = "a4bfde50f20b288cf44d40af83abd84", + [15] = "43fffde1b3477313dd57b9cd7261cdc3", + [16] = "4", + [17] = "524907a08de4e5c0c153c544c87bf9ce", + [18] = "3e775e1e484980597a8e3bb6d1daa111", + [19] = "427441618f7df01a97f7435904162b4d", + [20] = "1aec0fbd95537fcbd8062a6f9c687da0", + [21] = "6cb69f443aa14ed65113febd0cfbdf66", + [22] = "7311499cc97a3d0f4a9c0597b2c761ec", + [23] = "2e4c8606309b68cd815085fb51529a9c", + [24] = "6cf1a17d3284e57b9defaa01cb3d492f", + [25] = "5", + [26] = "3565c3eaf0daac1e3a2c028657569676", + [27] = "75da9c979be453e1de8dc5bd8e927b66", + [28] = "43ee4f01cdecf124b210c42587d2a718", + [29] = "35864fac94ecba016620c63c0ccc5f56", + [30] = "3c85a120dba23570cc87f22b973f1654", + [31] = "6838d8565fcbbc5dbf597fb37a1f5406", + [32] = "43aefbfa73385b0bc2450f51062aa79", + [33] = "45bc0d05b45e92a9ec86fdb68d4d8b6d", + [34] = "617de3651efcd26b6524a971fc68398c", + [35] = "4101878d7ace3b9fb358dad9ace0a5c8", + [36] = "6", + [37] = "673a3026784b7a41328bac018550b86f", + [38] = "2b23c1a47cab7f8fcd0105546e230715", + [39] = "4e915dc6234ac56a095df35c40ea4907", + [40] = "51f1ec44e533cb107634b3c0f699bd8", + [41] = "3360c9282c4fdef670b93037989ff143", + [42] = "35e69c414ce1d44b024bcd9a7225a5c1", + [43] = "2e48de0b4bd10c05fbfb2f9719b20e69", + [44] = "5681ab761459f6534d33d34f9cf09467", + [45] = "2862179c5ffd3fb1c4093fa76a9cbc70", + [46] = "643d5c5c9b5af336e504f41726dfc0d3", + [47] = "3e98383357bcacf462c70cc9351a91a0", + [48] = "50092dc55bb055d137b99eff5829e051", + [49] = "7", + [50] = "36017e9ef9e274f8024599ccb1154c1f", + [51] = "5bf023ca007e263e4b5a030838af810c", + [52] = "20484b0d67f3c594e88120cd2a161b8", + [53] = "2b9e8a3b3ed1ed9329bede411f92778c", + [54] = "2cd41d9eb601a00f92018104a5baab5a", + [55] = "5bec2e51e71bb1f1a852e3e56d43a184", + [56] = "1497fbca1e4165119e89a815f0757b08", + [57] = "63423607948c915df58134dba2f29d07", + [58] = "18d9afef351887618e7bb9e3cfb0211", + [59] = "3ea4eee3e48e677c53aa0f392d896490", + [60] = "652cad76c4fc8a2bfb1c8861317ee953", + [61] = "66fbaa07b40873c3ac00b38cb100f017", + [62] = "6a018a4798e4a471a9ff4fb9dac762f", + [63] = "65e57682b4e369b70b1926384bbbfaa4", + [64] = "8", + [65] = "6188263fe8ff27e6249f9fb45efc8a9", + [66] = "3cff332519838822fd763253838bf932", + [67] = "4c83bbd2d19d60743a698d36db22c917", + [68] = "489a99f90fc1a4d233247172854a913d", + [69] = "38607b0f81008cc1a1dd707a16fc4d28", + [70] = "4eecbfcfce6b4da4c456d606983c3ef4", + [71] = "303995f9d14e1722b14e98314f7064ca", + [72] = "703decfd9af86fa0c0af848e728d42b7", + [73] = "17b2676a1150040ad999fbcd06f41d3a", + [74] = "1a7989bf779d64cf9a301debf4fec091", + [75] = "28c04ee827b98f30983507c028a3b72f", + [76] = "684426770c8f901e85dd754a0e162e3f", + [77] = "2b5c61ea91f69b1c7c7ebaeefb3240c5", + [78] = "568763066059e114d011688b51121883", + [79] = "a43ac4b02b98857c9d659c953154885", + [80] = "35d81f7b2aa6ff97b00c54df38d0fb40", + [81] = "9", + [82] = "d688cbf38d1530c3d11285f8a829bc3", + [84] = "13bf6ab1b648d2a713a3fe81fc4ac60d", + [85] = "4760657d9d6c47c60833c08573e79b80", + [86] = "3532206ae6f0f9a9721be80adf3b3df4", + [87] = "755e6970bfe25e6ac8bf805cf22b7343", + [88] = "70a16009896f6352093f0ccb0b3c101", + [90] = "7aeae26757cdb098b14f0da171e69c4", + [91] = "2bbeb474b349124e3ef6c222b62ad7b3", + [92] = "5c990c0c6136d19b02a10bf6a2a53538", + [93] = "46e5aa500f60629978168938a0c01682", + [94] = "228459bf06f9dfb15baf8ac31efe34c1", + [95] = "69e2c2104da63c9b919341b9013db3b7", + [96] = "1349663fc681a55c79eca7f87fc7f27b", + [97] = "39c6a22fb3f9d6c91f40fc217241c45e", + [98] = "42b24dddef7d060a36b28cabe23d4b8a", + [99] = "b2c2c9408c1395318e7bef960479c2e", + }, + }, + { + .p = "f9df802d991ea5ebaed8d3b9a42cf101", + .first_non_square = 59, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "9b87b93bb96389be7801b89dc1652d8", + [3] = "59e13489928842f26ae2886d9310b8f3", + [4] = "2", + [5] = "4c5c3af3b9fab5886e65b82402dad66f", + [6] = "69e583a41fd4c41fad8dfafe1d64ce80", + [7] = "2226e4abbf4dabfbc798cafda99b0c40", + [8] = "1370f727772c7137cf003713b82ca5b0", + [9] = "3", + [10] = "56069730d91a5cc07e2a98a6a68b7202", + [11] = "3f7c0d6dd412594787118d6095384c3a", + [12] = "461d171a740e2006d913c2de7e0b7f1b", + [13] = "40b3ccbea21d3d72c74263ab6879d65f", + [14] = "119ec14e3683163583a5553d2a0e9311", + [15] = "2aa84242c307fd827f2ab90abc5e7d0e", + [16] = "4", + [17] = "79b4a0e036f6d7ac8945c382d3135b5d", + [18] = "1d2972bb32c2a9d3b680529d9442f888", + [19] = "4fc091a564105b66fd19904959dd1c2b", + [20] = "61270a4625293adad20d63719e774423", + [21] = "5a0e8b4c8c5c042b55235a9cb7adaf60", + [22] = "35a1aa98a855b5d2c77f916145f41758", + [23] = "72a841aa741cb731c7986c8eee1af3b", + [24] = "261478e559751dac53bcddbd69635401", + [25] = "5", + [26] = "47e09b3873557e6bc1ceadd3969fbe88", + [27] = "13c41d6f1e7a22eb91cec58f150539d8", + [28] = "444dc9577e9b57f78f3195fb53361880", + [29] = "57798532e4e9404df4b67adf52c37099", + [30] = "3590327cc41d87a9e09fd8d9619c06c6", + [31] = "e15fec88e2da65f950f0a29275df452", + [32] = "26e1ee4eee58e26f9e006e2770594b60", + [33] = "614bdf992ff880c1f9092b13cdc354f2", + [34] = "16f4ebd0bea0a507679dfed7c67cfa36", + [35] = "84b3b3b80ffec8c1d8269511ac835ac", + [36] = "6", + [37] = "7533be777b68bc56c672a6970f2021d4", + [38] = "66d2c23bdb3236d9d65c761f5cd0b606", + [39] = "68bdd47cfdfa7a81e2550461aae74818", + [40] = "4dd251cbe6e9ec6ab283a26c57160cfd", + [41] = "38d5408abd422d8fcf19e8cf070d342d", + [42] = "358408a1b5fa21b4ad7eaeab5970dd7d", + [43] = "395a8a9786765fcc10641a5932985fac", + [44] = "7ae76551f0f9f35ca0b5b8f879bc588d", + [45] = "14cacf526b2e855263a7ab4d9b9c6db4", + [46] = "fefca61affd696e5b8c9179dc6ea1b5", + [47] = "70c9d4ca66eb1683ef376ed8e27f78de", + [48] = "6da551f8b10265ddfcb14dfca815f2cb", + [49] = "7", + [50] = "309a69e2a9ef1b0b858089b14c6f9e38", + [51] = "2f7c7a1a80c51f68ca01ad786d31730a", + [52] = "7877e6b054e42b0620540c62d3394443", + [53] = "10cd478dce3a9dc19548ee40ca0c2b0", + [54] = "43d10abec65fa67359d11d40b4017a7f", + [55] = "528ec8c6e928f443382d5537ef5e4844", + [56] = "233d829c6d062c6b074aaa7a541d2622", + [57] = "72bd2260fffce41b2fceb568f468cd5f", + [58] = "7159169c936f53e5d9e62a97f2c7fcaa", + [60] = "55508485860ffb04fe55721578bcfa1c", + [62] = "549a3f9a716d2b96a14ac143160611cc", + [63] = "6674ae033de903f356ca60f8fcd124c0", + [64] = "8", + [65] = "645b10018a4ad21e827fe92a1e59f098", + [66] = "bdb26c2d680b416a65bbcdbccc495f0", + [68] = "6763e6d2b30f6929c4d4cb3fe063a47", + [69] = "5b40ed33d02f5dc35137a11e753e982b", + [70] = "30c34c8e71a415dbbb1f090970f44828", + [71] = "13e6bbfca6921f5a4856c934c5d6e3c5", + [72] = "3a52e576658553a76d00a53b2885f110", + [74] = "3c65617b9a3fcb1c3f7296ea850efa7", + [75] = "3258f9ab5593fd1b4744fd4f69064543", + [76] = "5a5e5ce2d0fdef1db4a5b326f072b8ab", + [77] = "3552f699dfaa4c271b0eeda26ed29d78", + [78] = "58976ff498c84c33a271944f973ae216", + [80] = "37916ba14ecc30360abe0cd6673e68bb", + [81] = "9", + [82] = "5a9d0c87e518c6cb13a811c0ebbca59c", + [83] = "5ef2cb8d6cb52a4627e5c105c143c922", + [84] = "45c2699480669d9504921e8034d19241", + [85] = "4bba44a6872d99a6cd89235b86fd6796", + [86] = "5632d46186d2d1e32be4c3055231edaf", + [87] = "531f902b8fb73220ef988a46ca801f16", + [88] = "6b43553150ab6ba58eff22c28be82eb0", + [90] = "8344564f2307055cba6f63a4f756505", + [91] = "76240705743b992bad77b0ecb5569616", + [92] = "e5508354e8396e638f30d91ddc35e76", + [93] = "154d0dac17c4a150f8fc0c8c1ae2021e", + [94] = "6713d7b3635f41a9a0bee026abfdddb0", + [95] = "64321552a81000b462142ecd1287bc36", + [96] = "4c28f1cab2ea3b58a779bb7ad2c6a802", + [98] = "440b610a211b8c435480c0c5049c43e8", + [99] = "3b6b57e41ce79a1519a42b97e4840c53", + }, + }, + { + .p = "e74738af4ed4cdd4b646d73096a2ccc1", + .first_non_square = 73, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "6ac4647c98cf7af7efe36371c9840eaf", + [3] = "21f4d6a5034093c1707e59226887fd48", + [4] = "2", + [5] = "548a6d10aee79ac83c925efab62b6a1b", + [6] = "67066dfb891738c460a2e75221d367c5", + [7] = "1953c6191d849b93d1aab79fa4cda95", + [8] = "11be6fb61d35d7e4d680104d039aaf63", + [9] = "3", + [10] = "180026ae5dbe974e7eb06b324927eaf0", + [11] = "1f9a4dff72cd9019164b73b04505333c", + [12] = "43e9ad4a06812782e0fcb244d10ffa90", + [13] = "643262a816c65c4721ec5f69b3669844", + [14] = "233636554b325c46cbad926a62d900d6", + [15] = "2b886afec0a6d18648114e84a91330c4", + [16] = "4", + [17] = "25046e4d32a4c22cb9f8afba3f3ceffb", + [18] = "5905f4c67b99a31319635324c5e95f4c", + [19] = "369e8c7fda6cf7c0d54f91eff4932e14", + [20] = "3e325e8df10598443d22193b2a4bf88b", + [21] = "70a98d624f107a23b9291ed17c65e708", + [22] = "48e20c07cccf03cc10d026cd8f1ef8d8", + [23] = "39ac71be3dfc7f2469a7df772ca4a372", + [24] = "193a5cb83ca65c4bf501088c52fbfd37", + [25] = "5", + [26] = "8c353e6ed18c48d8d54754f51d9522", + [27] = "65de83ef09c1bb44517b0b673997f7d8", + [28] = "32a78c323b093727a3556f3f499b52a", + [29] = "4ec6fa6a98995394f71e0b2207f371a9", + [30] = "13107997fc19873b1902a2a615da9376", + [31] = "51dc60db382d37d1cd141b86b4154757", + [32] = "237cdf6c3a6bafc9ad00209a07355ec6", + [33] = "25640e49e12fb784a6ac33b6d27d6e77", + [34] = "25f4ab6cd383cb4026bffd362b15d7f", + [35] = "411f7f296f7fac0ef30960fd99f42d43", + [36] = "6", + [37] = "2feabe9655a9641a8fa1f87f22531049", + [38] = "720bb70b21823e069d150e3e64d26b7b", + [39] = "177beb203ec9b72d675ca269eab76fd5", + [40] = "30004d5cbb7d2e9cfd60d664924fd5e0", + [41] = "382967f0e5f5feb1984360723a0c4f82", + [42] = "22468c3c9efc7faffb5d3e8dd251fc40", + [43] = "2de84badd9bff0944b460f3b8d0458e", + [44] = "3f349bfee59b20322c96e7608a0a6678", + [45] = "16580e82bde20283ff7045bf8bdf7190", + [46] = "456c8f05a1da32e653cc5b839fa9b9e3", + [47] = "1092ae6dfcff9bf2b3292f357aca1c05", + [48] = "5f73de1b41d27ecef44d72a6f482d7a1", + [49] = "7", + [50] = "474785105e63cb2e42e342d7c24eafe9", + [51] = "4b16b51a17a20de39e3f2a36fc8c9abd", + [52] = "1ee2735f21481546726e185d2fd59c39", + [53] = "2be013c5a5285182d8f04af39b1d6fef", + [54] = "4dcc11434c70dc786ba1dec5ced76a8e", + [55] = "542fb8ff09b332e95786de3e3ec8a568", + [56] = "466c6caa9664b88d975b24d4c5b201ac", + [57] = "5a3d33318760312855953f24bffd9ced", + [58] = "469159fcdc46912a4e3fcab24a5ef2ac", + [59] = "25635a436530a1238a7f4b2f0025e32b", + [60] = "5710d5fd814da30c90229d0952266188", + [61] = "3deb808b5ad9f2cb409d268e094918af", + [62] = "2dbc7a4f609cc9466560d9177a45bfbb", + [63] = "4bfb524b588dd2bb750026deee68fbf", + [64] = "8", + [65] = "235c214fd9dc61623c9955f87db2b12", + [66] = "463c486bc87316cf7424a483bf537d38", + [67] = "41be254c0da85d290b883c6b08421178", + [68] = "4a08dc9a6549845973f15f747e79dff6", + [69] = "1632bc546d2fa40a63b66c9c0b10399", + [70] = "1de0640a5afe477f5b35616ff7a4cf41", + [71] = "52b9f4585f7d01646e479ec08cff289e", + [72] = "353b4f2257a187ae838030e70ad00e29", + [74] = "233e33da1bb170db78a61f5463dea41c", + [75] = "3d7f07763e91eb0d83cf19848bfada59", + [76] = "6d3d18ffb4d9ef81aa9f23dfe9265c28", + [77] = "a8291ed9a50df270c807f51fd931ec", + [78] = "10d7025482f44ccf3b15f625e68fa814", + [80] = "6ae27b936cc99d4c3c02a4ba420adbab", + [81] = "9", + [82] = "10a7130308b2012359b349defd48bb7c", + [84] = "5f41deab0b3d98d43f4998d9dd6feb1", + [85] = "593575a6c6f3d3defc4139e083a23789", + [86] = "14bb748ced6ace4ce9ba942b124e9978", + [87] = "54085d04c4746201ca5df23ce9c207b8", + [88] = "5583209fb536c63c94a689957864db11", + [90] = "4800740b193bc5eb7c114196db77c0d0", + [91] = "3ccce2be9baf4d2f5575efc5d8bcaf5d", + [92] = "7358e37c7bf8fe48d34fbeee594946e4", + [93] = "5f7b21557f767e363b43f867baf4921c", + [94] = "25f9463099ba6747ef039591b8a24142", + [95] = "618ad1c02988e0f3f4ecc2dff670aac2", + [96] = "3274b970794cb897ea021118a5f7fa6e", + [98] = "3589155a412df3496c63328abeb40086", + [99] = "5ecee9fe5868b04b42e25b10cf0f99b4", + }, + }, + { + .p = "d3a1b64e241479381932df4745621009", + .first_non_square = 53, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "3256df5d0e4054ee1c708a8c2a94ce21", + [3] = "1aceb5e620540ea3c8e28ff09e65a03e", + [4] = "2", + [5] = "4a920722c3d286a0acf498eb88a17407", + [6] = "59c0e022516ddfc6f750aed84fc5ae70", + [7] = "123de903d6dc595ff3db324dee5f1a27", + [8] = "64adbeba1c80a9dc38e1151855299c42", + [9] = "3", + [10] = "10fb193db4a2e4fb1183cb7aa4488898", + [11] = "f4ee6591467dcf7223ee39a1828d8a6", + [12] = "359d6bcc40a81d4791c51fe13ccb407c", + [13] = "3259920bf856147b6d524ea42d74cd0d", + [14] = "5a72ba66b8b0b50d7dfc78997218456f", + [15] = "41028b2be43eda537b3de57589b190bf", + [16] = "4", + [17] = "62de61e0af734f1d89f10bc4ac9ae273", + [18] = "3c9d1836f9537a6dc3e13fa2c5a3a5a6", + [19] = "4eacea5adabc97af905b65f1f32a67d6", + [20] = "3e7da8089c6f6bf6bf49ad70341f27fb", + [21] = "665de344f793cfcf0d8851eeaa979209", + [22] = "4ab0fe70c9af2e359407cfb7a9284d2e", + [23] = "55a3bad41617c6c316d63b172d065de3", + [24] = "201ff6098138b9aa2a918196a5d6b329", + [25] = "5", + [26] = "13519dc6a212b6970dbdfa5c48317dde", + [27] = "506c21b260fc2beb5aa7afd1db30e0ba", + [28] = "247bd207adb8b2bfe7b6649bdcbe344e", + [29] = "a108bd629d894d7d4ae6b94fc533244", + [30] = "25de096124247dca639e5b4bdb451969", + [31] = "3d7f485499372a399679f8a3ad2cb393", + [32] = "a4638d9eb13257fa770b5169b0ed785", + [33] = "63142ce93321793c61bc51c04ef70535", + [34] = "ddef86ef8e2539ebeca14b526f44b5", + [35] = "4ce13194f399e69fa318bb4bb8f7ea7b", + [36] = "6", + [37] = "9228193d6c0e38073c07cdf448de5ee", + [38] = "11c081d52a1f27b9dafd424384c59554", + [39] = "5006ac3ae7fc06103b81937bc75a2b33", + [40] = "21f6327b6945c9f6230796f548911130", + [41] = "3f455b8cd2f901c587b0598a682b583f", + [42] = "1df60d29d9e20a850f71ff40123437c1", + [43] = "2382b8ce194e6c36c92a0b3faadaaa52", + [44] = "1e9dccb228cfb9ee447dc7343051b14c", + [45] = "c145f1a27631aa9edaaeb7b54824c0c", + [46] = "671467f745d92daf13ebb67ecf24fca3", + [47] = "264506f56045c3502ef62170be528551", + [48] = "6866deb5a2c43ea8f5a89f84cbcb8f11", + [49] = "7", + [50] = "2810a683232d2f6e74ffd5758f85f69c", + [51] = "1ebedbfc86ece8fe5b90062a149969f8", + [52] = "64b32417f0ac28f6daa49d485ae99a1a", + [54] = "39a0ea18d035261cccbf2d41a9eefb47", + [55] = "694639a2f3d08884ecb2affda5ee61e3", + [56] = "1ebc4180b2b30f1d1d39ee146131852b", + [57] = "5d2cec4ee0c2ce79bf81a15df81ceb4f", + [58] = "2ce9fcc748ecf7848e9dcf2211e67206", + [60] = "519c9ff65b96c49122b7145c31feee8b", + [62] = "12685eaa555f8cb49a90178a0a6015fc", + [63] = "36b9bb0b84950c1fdb9196e9cb1d4e75", + [64] = "8", + [65] = "4de278e7a145b79c2419db6e07e791f", + [66] = "379ddde1c4ac6a9e5ca97ef7aba7a6c", + [67] = "37c6a10abcd0fe2aa60f330f989550ca", + [68] = "de4f28cc52ddafd0550c7bdec2c4b23", + [69] = "2769cef201b1aac7821d582d2d2e8780", + [70] = "639e469a7c754f5cd697dab32f90d07", + [71] = "2c68191bf87dfe5cef79f5f62b726623", + [72] = "5a6785e0316d845c91706001ba1ac4bd", + [73] = "3a6fe5f9d81eb2fe4353d17adde7346f", + [74] = "1576149deacfc14d26864a3cc3e17600", + [75] = "4d9828cf827030052cc60f942d65eed3", + [76] = "3647e1986e9b49d8f87c13635f0d405d", + [77] = "630c6e7117790a971af1517d57363f28", + [78] = "6856e68603816f2c27fdc4c7d5016934", + [80] = "56a6663ceb35a14a9a9f8466dd23c013", + [81] = "9", + [82] = "59830bfb04b7677115c088282226682f", + [84] = "6e5efc434ecd999fe223b69f032ebf7", + [85] = "59925907902ef6ef57cd520278a260c5", + [86] = "632a92f87db0fc76ab82a2d352768c19", + [87] = "16d7959610ea9badc85fb36603a94879", + [88] = "3e3fb96c90b61cccf1233fd7f31175ad", + [89] = "13088ca71d4342c41581472612636828", + [90] = "32f14bb91de8aef1348b626fecd999c8", + [91] = "5c0a55b7b9d58943b809015a4aa020ff", + [92] = "285a40a5f7e4ebb1eb866918eb555443", + [93] = "1592a85e0341d9c9825096e1976e192b", + [94] = "2fb36c59090a20bbaa092c8aa8992ac2", + [95] = "2e74a563b5f9c6a6b01d52288f9c0d6b", + [96] = "403fec13027173545523032d4bad6652", + [98] = "46e35110e4669fed6b51f4b960b27d2b", + [99] = "2decb30b3d3796e566bcaace487a89f2", + }, + }, + { + .p = "d7da4ea4510511593950179f8f711349", + .first_non_square = 59, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "959d1dbbc442f0c03fab00d7b74bc39", + [3] = "54011c029cc999cc59490b7ee97eeab5", + [4] = "2", + [5] = "27a5f203b507150a1470c9475067a7a9", + [6] = "5b106a2f61672bff1fc84537031bb8bf", + [7] = "c1c26a4d8728d54300851fec2a6c397", + [8] = "12b3a3b778885e1807f5601af6e97872", + [9] = "3", + [10] = "5454e217bab81e821a0b173196678210", + [11] = "1682f9cf7225b6fd06af37171fe3fde1", + [12] = "2fd8169f1771ddc086be00a1bc733ddf", + [13] = "217f7c4618539196631e3abcf5fe454d", + [14] = "46176a55e55c6e8920b06a348e37c612", + [15] = "43fc3e63a8bbe3e9e702986f4f1ed133", + [16] = "4", + [17] = "19453763a8648666e6d09e4de90b0333", + [18] = "1c0d759334cc8d240bf01028725e34ab", + [19] = "119bcbb7bff3e1badada7f4d83e36e67", + [20] = "4f4be4076a0e2a1428e1928ea0cf4f52", + [21] = "1d5498842ef5c553b8ef2d356bcc6eab", + [22] = "15b78a01b3f6097e3cf9b453f141e9ed", + [23] = "980e6f8411b4639e84cd6c712a9cba1", + [24] = "21b97a458e36b95af9bf8d318939a1cb", + [25] = "5", + [26] = "20dcca93e1306a7f700b99170fbce6c7", + [27] = "242905638557bc0bd28b0add2d0bacd6", + [28] = "18384d49b0e51aa86010a3fd854d872e", + [29] = "5a6e09373884c6bfa72122a486a177b3", + [30] = "12e5df3ef102359d598724a0811ba203", + [31] = "5c85b8dbe7a3ff15fcc9eb57067b82bc", + [32] = "2567476ef110bc300feac035edd2f0e4", + [33] = "6b8e76260fca9eefcef94f3f2d12200f", + [34] = "3b36f3d67d8463ece78ac1e3396d148e", + [35] = "394b72ee77c8734547637275946556da", + [36] = "6", + [37] = "4b64318604f4ae445368e8876704e136", + [38] = "c3a81ce44aaa2db666a3d16b0201d09", + [39] = "1e45b92f0be82f1042ad3fe274ff0c88", + [40] = "2f308a74db94d4550539e93c62a20f29", + [41] = "3e9c285ed90c12fe79cf4ba4128f6185", + [42] = "2025ee1dd9e72c7313b99e9f1c90d856", + [43] = "3a3dbbf0e96a1a3ce316b144b7826682", + [44] = "2d05f39ee44b6dfa0d5e6e2e3fc7fbc2", + [45] = "60e8789931efd23afbfdbbc99e3a1c4e", + [46] = "fee50de01be07f792ac6f5b9b5de4b7", + [47] = "8b0f0ef7048f8d3e4c9ba6d4ef80f6f", + [48] = "5fb02d3e2ee3bb810d7c014378e67bbe", + [49] = "7", + [50] = "2ec1194aad54eb3c13e570436947ad1d", + [51] = "17e29b58202c9cefddc75b5fafc7e372", + [52] = "42fef88c30a7232cc63c7579ebfc8a9a", + [53] = "3a0c58a5ec20f119c262f12ae5183157", + [54] = "3956efe9d33072a42608b80579e216f4", + [55] = "2be21c25e83850a25db71abbc4a48100", + [56] = "4bab79f8864c3446f7ef433673018725", + [57] = "5386749f14c9429c39b8d9d424f075b5", + [58] = "360395662a2d98180968961c84e61588", + [60] = "4fe1d1dcff8d49856b4ae6c0f13370e3", + [61] = "4238404aca0d8514e461aa1b212a5af6", + [62] = "629800208ccbf1d82b7b1b43ec19118c", + [63] = "245473ee8957a7fc9018f5fc47f44ac5", + [64] = "8", + [65] = "6b2bef42c7770064af9022b31d103d5c", + [66] = "20454e81a6a03a241dbc136180e8c664", + [68] = "328a6ec750c90ccdcda13c9bd2160666", + [69] = "160e654845d6518f69ca871d43a32123", + [70] = "1bb310d630d1bc146d36acc51d7abf11", + [72] = "381aeb2669991a4817e02050e4bc6956", + [73] = "472e264b5e0edc8ec4a88d77a050dc04", + [74] = "49a4a35f203f4e4d29034e654752f75", + [75] = "baf113b921a21b4b432f5c48f679109", + [76] = "2337976f7fe7c375b5b4fe9b07c6dcce", + [77] = "28caa6a79c150442aa8ad26a6a293d6b", + [78] = "1ea04d76bcb64865c84cbabc0eef714b", + [80] = "394286957ce8bd30e78cf2824dd274a5", + [81] = "9", + [82] = "f4596207cde9bd65f928c1c6ad96fe", + [83] = "56f024a084a7418b7fbb56a3398cdf40", + [84] = "3aa931085deb8aa771de5a6ad798dd56", + [85] = "5f4260a2d155f008378db93f90204793", + [86] = "140253b4201d75301a986809baed51d8", + [87] = "f5d00583106340970471bc36ca2d0d7", + [88] = "2b6f140367ec12fc79f368a7e283d3da", + [89] = "6adb209ecb5bcd002bef5b6bee7f253a", + [90] = "252457a2df234a2d14d12df533c572e7", + [91] = "1c21f090707344b4d211c183e4e5bd60", + [92] = "1301cdf082368c73d099ad8e25539742", + [93] = "4c8047a783cda4682655dc2f757b35bb", + [94] = "6eaa3447c9e7a4f0b0afe99836c88ee", + [95] = "69c7233d4237d40d65ac836ac27e305a", + [96] = "4372f48b1c6d72b5f37f1a6312734396", + [98] = "4174bd0225dd49541bdad05e6031258f", + [99] = "4388ed6e567124f7140da5455fabf9a3", + }, + }, + { + .p = "e4ad8bf1a7b946d591595a7347b15f71", + .first_non_square = 53, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "4c49d878822cfbe76fb4b402caaed4fd", + [3] = "3c37757e7487b01dfbc37216d844db99", + [4] = "2", + [5] = "5aeece5c7ed9ca8c1ed52da45babc777", + [6] = "40713762535e9a0c57f602473ff52998", + [7] = "3ecda635990f5dea2acb9b1a9fdefbf5", + [8] = "4c19db00a35f4f06b1eff26db253b577", + [9] = "3", + [10] = "91ce7bde461ea19843dc9847de90e4", + [11] = "125b241be577156bc1797be7208ee62b", + [12] = "6c3ea0f4bea9e69999d276459727a83f", + [13] = "425700a36490fb859641b2b08a7eae0a", + [14] = "10f1f9d70043a045d55a6d116c2a6f31", + [15] = "469981b6614fca719735f3d6d9dcb656", + [16] = "4", + [17] = "72796d6db8598786ae34c9df885233b", + [18] = "2ffd77decdace0bdc4c195185b1f86", + [19] = "1dcf29a92bb5b16be3ff967d956e78c1", + [20] = "2ecfef38aa05b1bd53aeff2a9059d083", + [21] = "417e0eec0ee9eab8893e2c6432f1410f", + [22] = "65551d126459325ddff4e27e0e154850", + [23] = "3394ef48c3876261e519f07c5cc22838", + [24] = "63cb1d2d00fc12bce16d55e4c7c70c41", + [25] = "5", + [26] = "10772742d4d9fbe450d15ef5ffc3fe71", + [27] = "30072b764a22367b9e0f042ebee2cca6", + [28] = "67123f86759a8b013bc2243e07f36787", + [29] = "5cc3d6327e652a41154770644a38b969", + [30] = "4ad60c254ddec972fae777b256a7c5d5", + [31] = "2e00a145ed5a04009a8355499ce70919", + [32] = "4c79d5f060faa8c82d797597e309f483", + [33] = "5cf3346d66af0589ba6cc2ca64333c79", + [34] = "4a3aaa0b4b8c6ede15bc17190bdada64", + [35] = "71363966ddc55278fda04d8b9c1ae94b", + [36] = "6", + [37] = "1b3a4a911ed3a3c94924fa36bb0b2ee9", + [38] = "28e73aa747bd0f9c9a9bc913df016115", + [39] = "6f8a1ed7db16005ca5df3eddb25eacbb", + [40] = "1239cf7bc8c3d433087b9308fbd21c8", + [41] = "6a7533c0bc1acd73a3b48be478dd13a2", + [42] = "9e55812741e9524ca166ce7bff9be9e", + [43] = "6244c591bd3277fca7ec50e93b69221c", + [44] = "24b64837caee2ad782f2f7ce411dcc56", + [45] = "2c1edf23d4d418cecb262e79cb51f6f4", + [46] = "e3c5e20bd259295570a71eec9ecd768", + [47] = "4cf99eaa49470e4938c90a22bc4ccb88", + [48] = "c304a082a6579a25db46de819620ef3", + [49] = "7", + [50] = "4be9dd88c491a225f42b30d899f895f1", + [51] = "3467e2afaf03823c26a922d43928cc08", + [52] = "5fff8aaade974fca64d5f51232b4035d", + [54] = "2359e5caad9d78b08977539d87d1e2a9", + [55] = "bd103977e456b841e966a74aad0e057", + [56] = "21e3f3ae0087408baab4da22d854de62", + [57] = "2c4fbdbb74128aab91bd39e1913a3f27", + [58] = "3371407d6491e3ec1977f1b775823de2", + [60] = "577a8884e519b1f262ed72c593f7f2c5", + [61] = "3ee45bf8835e5badafeb6df43185f5bc", + [62] = "56cb5291a6e682ffcaf3ff8b4150c72e", + [63] = "28449950dc8b2d1710f6892368146b92", + [64] = "8", + [65] = "143912b856d247f8c39d24c1c062491", + [66] = "3c15ad8b379ebaff4763bab01a9bcda9", + [68] = "e4f2dadb70b30f0d5c6993bf10a4676", + [69] = "635cd56cb6cb00cf27fa36b7aedfbc53", + [70] = "43c04f20e4e9ac170210fc23ab9c2dc2", + [72] = "5ffaefbd9b59c17b89832a30b63f0c", + [74] = "bfdaba577a3472dd49bfd77fd19918f", + [75] = "4867bf869eed29c05977dffef1a6ea8c", + [76] = "3b9e5352576b62d7c7ff2cfb2adcf182", + [77] = "2006ed422b0a69dc4d57d750f38d34ab", + [78] = "4b050d62afd87d0f33db026adbb1c115", + [80] = "5d9fde71540b637aa75dfe5520b3a106", + [81] = "9", + [82] = "b0dc8230270044d0edf3ab1ad97b16d", + [84] = "61b16e1989e571647edd01aae1cedd53", + [85] = "46e0143233ee83c76c0b13168f19a07a", + [86] = "52a1b3caadecf3720ef1d80d467e74bc", + [87] = "14589812286e6d6f123be7173952a95c", + [88] = "1a0351ccdf06e219d16f95772b86ced1", + [89] = "539cf0fd123cf0a349f1fa6ffdfc4a68", + [90] = "1b56b739ad25be4c8cb95c8d79bb2ac", + [91] = "5662acc7560be428cb14e9cc5a4e2128", + [92] = "6729de91870ec4c3ca33e0f8b9845070", + [93] = "5cb5d378c21458c2912dd06deb1a7735", + [94] = "552aec748d185891ca356d1379aed772", + [95] = "4fc9e390534febdb6c6ec3fea343b79c", + [96] = "1d175197a5c1215bce7eaea9b82346ef", + [98] = "4ca9d3683fc855a8eb3e372cfb651409", + [99] = "37116c53b0654043446c73b561acb281", + }, + }, + { + .p = "cbcabb1f226a0c65460ae623608b1ad9", + .first_non_square = 59, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "20aa56375597d8cdab6a03b709d4a278", + [3] = "49d44e3b109e23292d3d13445b9b8eea", + [4] = "2", + [5] = "1e0e210eb335cae047c35d767f674637", + [6] = "625c5c0f38eca85e2ecb80174fa4a95e", + [7] = "3745673b54e841a6a4fb1a8a3759b8bf", + [8] = "4154ac6eab2fb19b56d4076e13a944f0", + [9] = "3", + [10] = "4f0396e7b9df52bac992b43575c33c35", + [11] = "4d679981c0acbe4a8e305ca2cc963ef9", + [12] = "38221ea9012dc612eb90bf9aa953fd05", + [13] = "6596f0c8f4a91c4a17e751f02c81a82f", + [14] = "20d6292a2fdef5fadd66420ecd85cbd3", + [15] = "266647395842faa57f249c38db0f1eb1", + [16] = "4", + [17] = "3cba2f5354d5ba2192012e780019d728", + [18] = "61ff02a600c78a69023e0b251d7de768", + [19] = "577f304041afec01a5c075ab05175217", + [20] = "3c1c421d666b95c08f86baecfece8c6e", + [21] = "28429bbbd4c6513ad4f08b5ea351f8a", + [22] = "29cf35616a805dd926e7cdcbe6d63680", + [23] = "55d452f7467ccbaa62afc2985787cf17", + [24] = "7120300b090bba8e873e5f4c141c81d", + [25] = "5", + [26] = "29e4c4e321eced80ec26e6133bf20af6", + [27] = "11b22f920f705d1641ac53a9b24791e5", + [28] = "5d3feca878998917fc14b10ef1d7a95b", + [29] = "5b4b3eed097bd01db9cd0c7a288b56c3", + [30] = "3575cde15467aaaae6e0187e24d6d2ee", + [31] = "5840337f0dc69197ea45a3a340700304", + [32] = "49216241cc0aa92e9862d747393890f9", + [33] = "54002bd7d536884838b4eeda47283774", + [34] = "4951e9a1bd020bb682f868df70b4bfbc", + [35] = "376b66fcc1a223932d2b34a06781ff17", + [36] = "6", + [37] = "3f93f4d11e213ad8cdab598763039e7b", + [38] = "324d3ab2b47ec5393ef6070e5374bb34", + [39] = "261e82ec98f3c07d5dc28a1484db4146", + [40] = "2dc38d4faeab66efb2e57db87504a26f", + [41] = "1976a2ea6012d0647da3523808d36740", + [42] = "42de54dbb74f15f8e3186afc44a48501", + [43] = "4f751abc9fe3a2f84f1ccb3fd63bd3f6", + [44] = "30fb881ba1108fd029aa2cddc75e9ce7", + [45] = "5a2a632c19a160a0d74a18637e35d2a5", + [46] = "494db3f0b07d25c8a30faeec07f9b5e8", + [47] = "182d2c235507872a1e99c776b83ccfbe", + [48] = "5b867dcd200e803f6ee966ee0de320cf", + [49] = "7", + [50] = "28770c0a7672d060ecf8d3902f63ee81", + [51] = "d05c776625315a66187a12849c70f79", + [52] = "9cd98d3917d3d1163c42430787ca7b", + [53] = "286f9d986059b7f9938b43ead8c8d654", + [54] = "5b4a590e885becb546579a228e62e141", + [55] = "51aa04d6a5d11b6edc1a6fe2233eee6b", + [56] = "41ac52545fbdebf5bacc841d9b0b97a6", + [57] = "5aa5e71f1dfc8b3cc0e026612f7e1fb6", + [58] = "35533f553747e464072c4440bac52a0e", + [60] = "4ccc8e72b085f54afe493871b61e3d62", + [61] = "24551bf46096d057148ef425467a9ba9", + [62] = "3e52033154f120b235978178d647c143", + [63] = "25fa856d23b1477157199684ba7df09c", + [64] = "8", + [65] = "563a6e8eb33b076dbe065396eb315574", + [66] = "5e864cca82f747ea276994780ac8a19d", + [68] = "52565c7878be98222208893360576c89", + [69] = "5ce922cd0c1b446c1e4ca6c4e0f24df8", + [70] = "11f934d12f2ffcc38b0a891a84025b50", + [72] = "7ccb5d320daf793418ecfd9258f4c09", + [73] = "52a7a870244bba2a55519bf744ebed05", + [74] = "ad23956ae428025f0a0257bf2dda72f", + [75] = "266fef16f1bd68fca9e46bf0f70c6b20", + [76] = "1ccc5a9e9f0a3461fa89facd565c76ab", + [77] = "14072fe6875f3477f254a09d386e4654", + [78] = "38f4c4a6b86698a0480425b350bdbebe", + [80] = "539236e45592e0e426fd704962ee01fd", + [81] = "9", + [82] = "3f7b778244278ec4835d885d4839b2b4", + [84] = "50853777a98ca275a9e116bd46a3f14", + [85] = "22d770096f8b019cc1dbe271c8d798b8", + [86] = "50718b1afe946781b22c7ce102fd4243", + [87] = "50259cceac8c1f8b42544d960fee46fb", + [88] = "539e6ac2d500bbb24dcf9b97cdac6d00", + [90] = "214009980b33ebcb16ad367d00be99c6", + [91] = "2df48de5831087e5fa6d5f4b545beb59", + [92] = "202215309570751080ab60f2b17b7cab", + [93] = "384da52f8b0dd624357002ef2753ab23", + [94] = "2d9c483316aab53053292ffc1364a199", + [95] = "17d3a3a478758dcb2d715b6a6c291770", + [96] = "e24060161217751d0e7cbe98283903a", + [98] = "18dda06434bce13a69db33dde445566f", + [99] = "1c6c11661f9c2e7a64862fc50537a212", + }, + }, + { + .p = "fe4140ab1703f4636f45c48bfb0068a1", + .first_non_square = 53, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "7ba6780b0fed766515a7f52780bc9293", + [3] = "6149de094ae83131a239de5a6df50f3d", + [4] = "2", + [5] = "8e08f47c68cea90d366ed88b052dc0d", + [6] = "712eb140f38d2eda5c637e54d10bef43", + [7] = "647ecb433b6c7bac3b1d2f9d6054d0ba", + [8] = "6f45094f729079943f5da3cf987437b", + [9] = "3", + [10] = "329e80ca3b64fa4f1155f9c270b8f4ce", + [11] = "24c5b58cbd45b14e27fb39d98513e861", + [12] = "3bad8498813392002ad207d71f164a27", + [13] = "30b405638cc9503430b6aa41495bb61", + [14] = "2f1bc9fc42ecee2906bb9cb2c4b48844", + [15] = "1060959a729316d3567679f61abc49af", + [16] = "4", + [17] = "2743cff56b8c8f8ee97f7446ae99739e", + [18] = "74b2277618c46ecbd1b21aea87354f18", + [19] = "3fbbfcdfd2487c9b851129505f179076", + [20] = "11c11e8f8d19d521a6cddb1160a5b81a", + [21] = "6fc009527f629afe432b1f4f1e4b1fea", + [22] = "3f01ff2d6c6d833d28056e6072b25e60", + [23] = "506f5b0f98fa595bed0cbc10ab7c5ee5", + [24] = "1be3de292fe996aeb67ec7e258e88a1b", + [25] = "5", + [26] = "10be4164d8254ac55662322c7ddcf6fe", + [27] = "259c5970c9b49f317767d6834edec516", + [28] = "3543aa24a02afd0af90b65513a56c72d", + [29] = "5e4f3f1a728ca81e0562ea16d3b3cffd", + [30] = "5f7adf9503c5bf6b2ed871ee578d7f7f", + [31] = "5a732eeb6c03d753dce4cbca35427431", + [32] = "de8a129ee520f3287ebb479f30e86f6", + [33] = "515718e3cde407eb2f1f134140cb21fe", + [34] = "58f96aeb670e2022511ae47d9ecba760", + [35] = "7b8229e2856880ab02cd93d5da144228", + [36] = "6", + [37] = "6b81b8e27b6cf32c0457ca6fdadea755", + [38] = "b8e8b04539168fe235d3def1490dad8", + [39] = "15bf17346ca8088e3cce95dfb9c418f7", + [40] = "653d019476c9f49e22abf384e171e99c", + [41] = "70c50f028034d998186c4fa9b24ec776", + [42] = "4025367c12a3595db005c840e28fca2f", + [43] = "10bd851db1dbc8acea1e2f5c9a539027", + [44] = "498b6b197a8b629c4ff673b30a27d0c2", + [45] = "1aa1add753a6bfb27a34c89a10f89427", + [46] = "2f0c4d81e381d9b019bf8094b3eecee6", + [47] = "15534147c6ebf56b2ecc5c10e0770e14", + [48] = "775b09310267240055a40fae3e2c944e", + [49] = "7", + [50] = "6dbdd6e1219b67328dbc40ad8dae0b9d", + [51] = "70e70926d41fd03e102a5a44ce1229f9", + [52] = "61680ac71992a068616d548292b76c2", + [54] = "554ad317c3a3982ba5e4b67278236528", + [55] = "1459f9f6ec22944520f4871412088d85", + [56] = "5e3793f885d9dc520d77396589691088", + [57] = "341ef10187760d3c36d527145b4ad817", + [58] = "529922ce1cc858cb8a2b30f4684aa9fd", + [59] = "37be2dfe9028978862327c01c89586e2", + [60] = "20c12b34e5262da6acecf3ec3578935e", + [62] = "6ecd16e975917832f0959b6c9542da42", + [63] = "2f3b211e9b417ea14211ca4c25fe098d", + [64] = "8", + [65] = "7345a2c482c5a9588f299989ac40ecad", + [66] = "18770759a8b2f26d1a24dba6c2d52a07", + [68] = "4e879fead7191f1dd2fee88d5d32e73c", + [69] = "3a0988799c07916f61906d56b5afe5ec", + [70] = "1d94b3814a59d9cd691f356c42e05881", + [72] = "14dcf1bee57b16cbcbe18eb6ec95ca71", + [74] = "1d13c613cdf866cb5b13e4a51dc7ebe3", + [75] = "16112b27b77ef2ceb36a3153d0378511", + [76] = "7ec946eb7272fb2c652371eb3cd147b5", + [77] = "3ea093d7619691c048b296bdc0d37662", + [78] = "3af49044c061c8aad58fc0604c081c2c", + [80] = "23823d1f1a33aa434d9bb622c14b7034", + [81] = "9", + [82] = "21662760541dd24c3115bfa4f0b2f76d", + [84] = "1ec12e06183ebe66e8ef85edbe6a28cd", + [85] = "34b4035b5edce75b16326453cc7b7c59", + [86] = "67f099b3ac6c1e2285f800c1169f3e74", + [87] = "28d2792fa43528197df02a2ab64f10b4", + [88] = "7e03fe5ad8db067a500adcc0e564bcc0", + [89] = "131cea5295f0f890d408cd55292baa9a", + [90] = "6665be4c64d505763b43d744a8d58a37", + [91] = "6166d2bbeaabb0fc8f2a7f54155dba4c", + [92] = "5d628a8be50f41ab952c4c6aa407aad7", + [93] = "5d9415660fcce03cc4807ceb85b729c0", + [94] = "63b43ba1ab89508e123048325aa02be5", + [95] = "453ec81c6776384522e1ecda1b6ddee5", + [96] = "37c7bc525fd32d5d6cfd8fc4b1d11436", + [98] = "66c9864c2a725f9949c666709426c822", + [99] = "6e5120a637d113ea77f1ad8c8f3bb923", + }, + }, + { + .p = "c952099317697fbee819206f51261769", + .first_non_square = 61, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "1030ca5f555429e4df1a0364d52ed574", + [3] = "1c008a94d898f5934cc6768dc4aa9e7", + [4] = "2", + [5] = "6453a0cada2df423a5cadbfdb1f7a43a", + [6] = "4ead969961f9970cc0957f4c1997a2eb", + [7] = "9516aa771b15128eb5879ba5cbbcb6c", + [8] = "206194beaaa853c9be3406c9aa5daae8", + [9] = "3", + [10] = "218b5770aff5df5ee5dea41f84d956f8", + [11] = "2e5ad00f8babb3bf597470ccdefa6904", + [12] = "38011529b131eb26998ced1b89553ce", + [13] = "5b7093eeeaabe2273d89ed1269e95a8d", + [14] = "150e9ff34aebd4279f3f194d0b008b9a", + [15] = "52f554395146f4e92284fd0195f3da81", + [16] = "4", + [17] = "e87f72fca45eea33de5b19bdc8598a6", + [18] = "30925f1dfffc7dae9d4e0a2e7f8c805c", + [19] = "dbbf4eb69d3d3d80113b9c179dbdf14", + [20] = "aac7fd630d97779c836873ed36cef5", + [21] = "343a4efea6c533ef26fbc9c0455bba4b", + [22] = "561d91e30353cd92dad551df29b34330", + [23] = "1c46770900025779e503a37fbf3652f", + [24] = "2bf6dc60537651a566ee21d71df6d193", + [25] = "5", + [26] = "d8061aede379d718c4477b0c72eeb0b", + [27] = "54019fbe89cae0b9e65363a94dffdb5", + [28] = "12a2d54ee362a251d6b0f374b97796d8", + [29] = "1a00dd8133c4574015541507f34fa2a2", + [30] = "354823c12c93d938a6150ca543c49001", + [31] = "2c50d713847df4e0e6c8092bbb7ff748", + [32] = "40c3297d5550a7937c680d9354bb55d0", + [33] = "1dadd4e7aed55d1dee86fa9fbec2b5f9", + [34] = "495c10a814ec41ca882fd0a3db20dae0", + [35] = "e02ae2c2ae827bcbcb8d5cee71ce245", + [36] = "6", + [37] = "48666c8d4ae91cdb3baa3faaf209f863", + [38] = "1348689ee8394ec3c373f58427071294", + [39] = "22ebc3a88ac979c4cb232cb96ef56c3d", + [40] = "4316aee15febbebdcbbd483f09b2adf0", + [41] = "5d6e17005c737be1d08b4c361e7c38aa", + [42] = "63bdca4c2bc7704338cb6b9040f977bc", + [43] = "bbcd28418772487d60fa0e99ee30f4e", + [44] = "5cb5a01f1757677eb2e8e199bdf4d208", + [45] = "63a8d8cd77205cac09477389c4c0d545", + [46] = "27626a82bfa70599fc17246961bdadd0", + [47] = "e64fa81b1411430a01be20a26516d3", + [48] = "70022a536263d64d3319da3712aa79c", + [49] = "7", + [50] = "50f3f3dcaaa4d1785b8210f829ea2b44", + [51] = "4573f3634cf8d8277095b591bba6eb32", + [52] = "1270e1b54211bb706d05464a7d53624f", + [53] = "4b910f3075773d693fc6320490320417", + [54] = "22b6ba390e83456759a75d74fba0d158", + [55] = "43d64c3a87c506ed9f669fb02a34490f", + [56] = "2a1d3fe695d7a84f3e7e329a16011734", + [57] = "f9eab4f7d57e3626e924cb0a2ed38d1", + [58] = "2c268106581c388b69a240d04f41ddb3", + [59] = "5468c6518f3cc44a8b95e3bebafe1160", + [60] = "2367612074db95eca30f266c253e6267", + [62] = "45bc5f2b116bb2147e21226906d83f5e", + [63] = "1bf43ff65513f37ac2096d2f16336244", + [64] = "8", + [65] = "3a05b5275ba2635e914620a14673f977", + [66] = "1a17a7a83581669f72accc1078c3b313", + [68] = "1d0fee5f948bdd467bcb6337b90b314c", + [69] = "212575df2c4a30476197bbdee2f94cc7", + [70] = "a3f6dea37e9f80dc82f120598fd4bf", + [71] = "f488a226be605e99163987425d9d390", + [72] = "6124be3bfff8fb5d3a9c145cff1900b8", + [74] = "13d134042559929d1edc56f26b66f3b", + [75] = "8c02b4e83afccbe07fe050c4d755183", + [76] = "1b77e9d6d3a7a7b002277382f3b7be28", + [77] = "173a062e52c9d7f72af37a962c86bc64", + [78] = "564a72f1159c013f5c9bad4a81a1e2e2", + [79] = "4398a271233b37edbd0ff6c5bc3dba1", + [80] = "1558ffac61b2eef3906d0e7da6d9dea", + [81] = "9", + [82] = "360ac3f246c2a2011620260c69e306ee", + [84] = "60dd6b95c9df17e09a218ceec66ea2d3", + [85] = "1042e7ab08c6e4551896de0fc918b9a7", + [86] = "bf0a7212c4ed469c981a78d7c6c7e86", + [87] = "4e6d3d71bd2dca40b63270d75cb33802", + [88] = "1d16e5cd10c1e499326e7cb0fdbf9109", + [90] = "64a206520fe19e1cb19bec5e8e8c04e8", + [91] = "53cbd73f05e4d2cdd9ea452367ba48a3", + [92] = "388cee120004aef3ca0746ff7e6ca5e", + [93] = "5068af97e0ba758c38264b3fb6aaba9c", + [94] = "3d7f4045e3fa05122e1616448e2b059f", + [95] = "2b0448ad5e65cf7b24cc311cd17c2e1e", + [96] = "57edb8c0a6eca34acddc43ae3beda326", + [97] = "49893d9e5a5a5c7bb1c62e154d45677a", + [98] = "57fc80f7c21c5a7cce6308ad7cde413d", + [99] = "3e41996474666480dbbbce08b436dc5d", + }, + }, + { + .p = "c4ed76cc85621982d0467c08b185a479", + .first_non_square = 53, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "3f8cc442a5387175ec9f6de0eb3fcfe6", + [3] = "5904ffdcb4ae08d74f449e78de9eab94", + [4] = "2", + [5] = "259e201e5d0138c02f3566bfd710b661", + [6] = "32b732707de2692db32c7ea095415db8", + [7] = "65daac5f051d65191914b053e23ef41", + [8] = "45d3ee473af13696f707a046db0604ad", + [9] = "3", + [10] = "40b664afaf338d62876013bbf2850e05", + [11] = "4939a174028adff8511dd38caf5f62fa", + [12] = "12e377131c0607d431bd3f16f4484d51", + [13] = "4ed277339c1cddb3c56b926ece26e9b3", + [14] = "52db8f0f6f42d7552ccd23ca9d43c858", + [15] = "5da61b91394552f37eea84e6e9b9e447", + [16] = "4", + [17] = "3263fc1c526565e2ffed7234ab9ede85", + [18] = "6472a0495b8c5210a683265efc634c7", + [19] = "20ffb9b29d785211f5fb2761e31d1051", + [20] = "4b3c403cba0271805e6acd7fae216cc2", + [21] = "4e785976b5b051b1b2e78ffcc9067f4e", + [22] = "2e284efd9784af8211500f8c36f5a70e", + [23] = "594077cd6306cf9a454adc544da4d3d6", + [24] = "5f7f11eb899d472769ed7ec78702e909", + [25] = "5", + [26] = "2e2ba3ff7ddf95e9b6def6042acaea23", + [27] = "462188c998a801031d875f61ea565e43", + [28] = "cbb558be0a3aca32322960a7c47de82", + [29] = "3fdb558ea0ae7f05f9623ff54ff6c31", + [30] = "399eecae8ad427718879430013cbaead", + [31] = "1cc235d349911eb835346be57f23afd4", + [32] = "39459a3e0f7fac54e2373b7afb799b1f", + [33] = "3ee92e429c7167e910ad8d9e907ce9e6", + [34] = "9a58bf423affc176de6871c6946427f", + [35] = "217de1bb8bb1ab729df5ceb28cc237", + [36] = "6", + [37] = "4a7d3127acb1d9d63fbb12d1998acbcd", + [38] = "37a1b1cc5ce5955e6927b8a0be607672", + [39] = "67dc5debbe41df6e4f625aa1282f90d", + [40] = "4380ad6d26fafebdc1865490cc7b886f", + [41] = "59027e0c78b977e07824ad3f13d8fb83", + [42] = "37abc1ab524a3fa6426e7699e79ed055", + [43] = "1f5889733073ba0dbc15699a91e9ce77", + [44] = "327a33e4804c59922e0ad4ef52c6de85", + [45] = "541316716e5e6f4242a647c92c538156", + [46] = "1045c1a86d83c28384cc59075121c424", + [47] = "4e57a3fbf4a57fb46047b4ab5a9d9e13", + [48] = "25c6ee26380c0fa8637a7e2de8909aa2", + [49] = "7", + [50] = "4c1b184bd0a9fbb8016fd2accacc3974", + [51] = "5f3dc1f5436670ae7db2a3697e96fc1", + [52] = "274888654d285e1b456f572b1537d113", + [54] = "2cc7df7b0bbaddf9b6c10026f1c18b51", + [55] = "5f18346aeb83dd5f3d12ba08d2626129", + [56] = "1f3658ada6dc6ad876ac347376fe13c9", + [57] = "1322a9c3b403434ff5f0844599617ca7", + [58] = "35387bde818eb63ada2200a8961719d1", + [59] = "f15241a33b0cfb446f6b396297ffbf3", + [60] = "9a13faa12d7739bd271723ade11dbeb", + [62] = "45c11c41de0139f08cc806b248eeea7d", + [63] = "13190051d0f582f4b4b3e10fba6bcdc3", + [64] = "8", + [65] = "2f44ee31ef11f1e041c5dc4734a05708", + [66] = "4acbc94b0fd58ca158900d5ce645bec", + [68] = "60257e93e0974dbcd06b979f5a47e76f", + [69] = "4cdf1a7305f09d090eaeda3aeae4a635", + [70] = "4ae10ea94a44e9be9451a847e77a3936", + [72] = "c8e54092b718a4214d064cbdf8c698e", + [74] = "3444a9a3dc80764eb53f9202edb24a12", + [75] = "333e11b67ca1f92eebca204af60e10f2", + [76] = "41ff73653af0a423ebf64ec3c63a20a2", + [77] = "33f489c7462d8f1ae74f1c038423686", + [78] = "1770c4abd4023f184ba032ba66c8ade3", + [79] = "3c4c81760ef85c7b571b4f891649e64f", + [80] = "2e74f653115d36821370e1095542caf5", + [81] = "9", + [82] = "55eb50263e7b6e913814c68ba433a0b3", + [84] = "27fcc3df1a01761f6a775c0f1f78a5dd", + [85] = "444699a6ec75af134e8304bf932e79db", + [86] = "2a80de463669824da6b3253c088d97e5", + [87] = "51bb41a01003857029b5fb4020e9c1d7", + [88] = "5c509dfb2f095f0422a01f186deb4e1c", + [89] = "1923d478504b67b59ec8ae1a154654ff", + [90] = "2ca48bd77c7715b3a2640d4d9f67a6a", + [91] = "ca61e8231f3b59f1a97cedd8768fbc6", + [92] = "126c8731bf547a4e45b0c360163bfccd", + [93] = "479c97732d6fac4a0c4ad8964b95adf7", + [94] = "356870d65524375c5802aac1ff4c506a", + [95] = "63840baecb9ce0a51a270159bc79796", + [96] = "5ef52f572278b33fc6b7e79a37fd267", + [97] = "3610283097aedf2a259556d93489ea97", + [98] = "32fe703979c6e733d7cf09150bb36658", + [99] = "16bf6d8f823e86662312fe9d5c988475", + }, + }, + { + .p = "edf5623aef85b0b731e8f3e4c9e8d089", + .first_non_square = 53, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "16fcdbe33357a001d4fc47a63b82b779", + [3] = "1ecf4968a0192536a7749d06021eb42d", + [4] = "2", + [5] = "20a67fac9adbaf3e3780a6234ab6822e", + [6] = "2af9620e1f106e9a9051afc7aad33623", + [7] = "6ca9e7acb8e5b669c9b88ca94e76fdb", + [8] = "2df9b7c666af4003a9f88f4c77056ef2", + [9] = "3", + [10] = "4b00db7c853c5b4f00c6644aad3be157", + [11] = "2d736e49f3108641e7452d9978126b30", + [12] = "3d9e92d140324a6d4ee93a0c043d685a", + [13] = "43cac0cde7a35ba38264df5cbcbb4cd5", + [14] = "41a304d2883c6a82d4fb6b2c3079e110", + [15] = "67b91838119086d8078fd5be1bc8080c", + [16] = "4", + [17] = "5bd9ce3ab9d83d23da97a992ad7057d5", + [18] = "44f693a99a06e0057ef4d6f2b288266b", + [19] = "6bf0939c5e1638d3f76312968f659bd3", + [20] = "414cff5935b75e7c6f014c46956d045c", + [21] = "597b55effbb87b39e16b6d017bf7b30e", + [22] = "2c06cac16e38fca86d4478f9c87c625d", + [23] = "3c68a5b1ddb3dde1e92ccd7ec30a0b59", + [24] = "55f2c41c3e20dd3520a35f8f55a66c46", + [25] = "5", + [26] = "15af5f9e777e5614e2b9c15efe617ffa", + [27] = "5c6ddc39e04b6fa3f65dd712065c1c87", + [28] = "d953cf5971cb6cd3937119529cedfb6", + [29] = "2715ddb62536c46c4eea2bc625137fcd", + [30] = "212c5620fd99f5f09808644e22c79c32", + [31] = "6b577ba061d38d163ed349282302a120", + [32] = "5bf36f8ccd5e800753f11e98ee0adde4", + [33] = "13aa3aa2e45a174e92d9731e834dd329", + [34] = "5f856c5a327c79f10ea1e2a8d7703c3c", + [35] = "2dc1e3e916a6334eb3477947df87b8ae", + [36] = "6", + [37] = "2ce03f825cbb1e23600f9aa78fd89284", + [38] = "f0756eb9a9c43ad60272f73d2f20934", + [39] = "312aa19e77e6fef0afd8ad15ba1059ba", + [40] = "57f3ab41e50cfa19305c2b4f6f710ddb", + [41] = "56fb9e4458d3ec5aa118b9631c581c61", + [42] = "6a4cd4bfebe6ce666facf556c29ab9e", + [43] = "36c0e5bef8ace24e6a9b6a35dc24b702", + [44] = "5ae6dc93e6210c83ce8a5b32f024d660", + [45] = "61f37f05d0930dbaa681f269e023868a", + [46] = "35dab1813560b2e575205b9c85ba76ce", + [47] = "5037067f108024661ae1aa2c5c3228cd", + [48] = "72b83c986f211bdc94167fccc16dffd5", + [49] = "7", + [50] = "72f04b7000b6200928ed663f298d955d", + [51] = "f5a4507c2325355cdb0dadb2b2bce2c", + [52] = "665fe09f203ef9702d1f352b507236df", + [54] = "6d093c10925464e780f3e48dc96f2e20", + [55] = "3eca2d8e6904692c541d73928b4b8451", + [56] = "6aaf5895df0cdbb187f21d8c68f50e69", + [57] = "27423a9ff36f3d4ef62ac239f3ac9262", + [58] = "4d1eab01cec65f80ea32b0606b44490", + [60] = "1e8331cacc64a30722c948689258c071", + [61] = "274990b8bb86788b18d8567d7cf13f7f", + [62] = "2012553a6ccaec6d59c20d078ad45a53", + [63] = "145fdb7062ab1233d5d29a5fbeb64f91", + [64] = "8", + [65] = "2323facf1d23fd1dca99c58dcf9f51d1", + [66] = "abb680a9971a272a8ea46b2364fc14a", + [68] = "3641c5c57bd5366f7cb9a0bf6f0820df", + [69] = "6fe190bed95ca359eb6734e670f50c4a", + [70] = "15c4010e04617c35f94feed5c2417719", + [72] = "64083ae7bb77f0ac33ff45ff64d883b3", + [73] = "6bee761e1205d462392ce8e9c95c7da8", + [74] = "596eca3cd2371ce3ec9ffca3b68bc077", + [75] = "53e8f32fcf07f6a5eca1e2c6bf4f4ba8", + [76] = "16143b0233593f0f4322ceb7ab1d98e3", + [77] = "71702a65ae7de31ccb0de3444caf69af", + [78] = "114dfd1ba42d0cdda59bb8d4845e6f6d", + [80] = "6b5b63888416f3be53e65b579f0ec7d1", + [81] = "9", + [82] = "2ca2b887752daa4e112076a9f94ee2a4", + [84] = "3afeb65af814ba436f1219e1d1f96a6d", + [85] = "584290bf297fad6e90ca21b3a654a2ea", + [86] = "579d6f1c2105e88017132be6c7046179", + [87] = "272af66060f7c2226c9cf2d1b97a9396", + [88] = "580d9582dc71f950da88f1f390f8c4ba", + [90] = "cf2cfc55fd09eca2f95c704c2352c84", + [91] = "305a0b4b9244b27f0fac4d3f66cb1493", + [92] = "752416d7341df4f35f8f58e743d4b9d7", + [93] = "14764518d2fa770b40d7b124c1028271", + [94] = "12413e5231c1fbf54bf1ae472e0be00e", + [95] = "73033d976e08cf57e754d4502cee064f", + [96] = "420fda027343f64cf0a234c61e9bf7fd", + [98] = "4d0b5f04882050aa5f02fe592955cc3a", + [99] = "659b175d16541df17c196b1861b18ef9", + }, + }, + { + .p = "f216567317bd6168b283b35efdeb6e01", + .first_non_square = 61, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "480d3cc58db85c317fd3ca162a7ef31", + [3] = "751e72f645812eae49b9e8f43808b53c", + [4] = "2", + [5] = "66a75882537b0fd3e89cfaf5a83e5caf", + [6] = "47664935d814e997186d42dfa98dd547", + [7] = "4da889482696f681bdbef67c7ac1796e", + [8] = "901a798b1b70b862ffa7942c54fde62", + [9] = "3", + [10] = "57d17116e7de4d7c7380b35d174c50fe", + [11] = "692649e1555a93b8fa42eafb084cf8a1", + [12] = "7d970868cbb040c1f0fe1768dda0389", + [13] = "3209b67f7292b1ffb4371dc03ba01083", + [14] = "148d5a6790f3e04b3568bf944c02fe61", + [15] = "5520d9f992eb5c8c8881685999651f93", + [16] = "4", + [17] = "57d481f0380db09125d31dc6dfd1d9c9", + [18] = "d827b650a92914947f7b5e427f7cd93", + [19] = "69962be7fbbdd6eb3f9293403a845b10", + [20] = "24c7a56e70c741c0e149bd73ad6eb4a3", + [21] = "4ce832377d3bc8b2e4d6a23d6f5dd99f", + [22] = "331c2415f14f2d68991cf9c2e2fc696a", + [23] = "52c3351f96e116c602e2ca5e4298e8a7", + [24] = "6349c40767938e3a81a92d9faacfc373", + [25] = "5", + [26] = "14d036065850428ccb1ba5e425fa304f", + [27] = "6d45026fb8c62aa22aaa077daa2eb1b3", + [28] = "56c543e2ca8f74653705c66608687b25", + [29] = "29f9490f6684ea66db901d68cce1cdb1", + [30] = "576da7973e26fea493d4f7b7d53fb53", + [31] = "192cd4b66179a4082118574bfc148b27", + [32] = "12034f31636e170c5ff4f2858a9fbcc4", + [33] = "23224092a600150201ba52b3424456d7", + [34] = "5f9b7eb636b189b226aac177355abc25", + [35] = "733b83f9abd4bc87d247385c96040338", + [36] = "6", + [37] = "3d5cdd23a2a5a3f9d4d323b3f874ca9b", + [38] = "657de6d78704b86d6df714f94c9596b7", + [39] = "25a875a44f870578858989b880e1d053", + [40] = "427374454800c66fcb824ca4cf52cc05", + [41] = "5bed9dc9cb362674bda905c0aac4335", + [42] = "f12748e2759fd3766c92ead058963ce", + [43] = "9ccd7e40b4b4dbe60c0e14bbe7f12cc", + [44] = "1fc9c2b06d0839f6bdfddd68ed517cbf", + [45] = "41dfb313e2b3ce1307533d81facfa80c", + [46] = "4cc8c3b03683a8d1853c9e55ec8d52e8", + [47] = "3f765db35fcf6e1a387d4ecc26efd1e5", + [48] = "fb2e10d197608183e1fc2ed1bb40712", + [49] = "7", + [50] = "168422fdbc499ccf77f22f26ed47abf5", + [51] = "2e3b00d48ee6701ed7f985e0698e7e1e", + [52] = "64136cfee52563ff686e3b8077402106", + [53] = "6f4feac060b10c8f42797ff7f442ea12", + [54] = "1be37ad18f7ea4a3693beac00141ee2c", + [55] = "769f25532938ca79dd2823b747b11e1e", + [56] = "291ab4cf21e7c0966ad17f289805fcc2", + [57] = "3a8c4047c4ddf27d1e5e917d9185a6b", + [58] = "69a0f3549b38d0265f39e4d632238958", + [59] = "16b4266e9fcb5601a88ba6a1eee156b1", + [60] = "47d4a27ff1e6a84fa180e2abcb212edb", + [62] = "158d6e26917f81791039a0a8358c9866", + [63] = "91cba9aa3f87de37946cfe98da701b7", + [64] = "8", + [65] = "cbe13f6bfadaee035d56a39bf98bfad", + [66] = "6604d1e998f3793831782f4d99b1bd84", + [68] = "426d5292a7a2004666dd77d13e47ba6f", + [69] = "1b280a5d865f3099592b6d469a6f3ac", + [70] = "167dd1d604c01acd4591c8a2c13e301f", + [71] = "271e22c50a6918cd603a20c2872a8b59", + [72] = "1b04f6ca152522928fef6bc84fef9b26", + [73] = "11a5924dfa463201c0cc2c515c1f0bf1", + [74] = "60091028fb4a74808bad9094366d9379", + [75] = "656b91e92c0b26960b9a26071c54ae2a", + [76] = "1ee9fea32041b392335e8cde88e2b7e1", + [77] = "2bdf95db0fa53563fe363c057dd8bd33", + [78] = "3df809dc85028674ec0781daa86cdc8c", + [79] = "2b5c1a1ba7726ca49bdb8ffb265cebc7", + [80] = "498f4adce18e8381c2937ae75add6946", + [81] = "9", + [82] = "4fbde7f74ad09eca78d83d64e54c9a30", + [83] = "26e0943fdb9849c21d9f0cccdee7b474", + [84] = "5845f2041d45d002e8d66ee41f2fbac3", + [85] = "1742e5ddddcdc922680c7ccb36f25999", + [86] = "3db8bbcd65fc815230dc101898dd51f9", + [87] = "77f93b086452981199e093f1112ac36", + [88] = "6638482be29e5ad13239f385c5f8d2d4", + [90] = "155dfcd19fdd870ca7fe66b847f984f9", + [91] = "8bf6d293b0a33d416f2d8765850281a", + [92] = "4c8fec33e9fb33dcacbe1ea278b99cb3", + [93] = "16b76f5c478034b02d3a2455278766b0", + [94] = "54aada5a9d62cf663caa710a4fa9265", + [95] = "564288cd696118b6fb7a77938d8329f6", + [96] = "2b82ce64489644f3af31581fa84be71b", + [98] = "1f85ca966e00a855a7eca869b2978a57", + [99] = "495c8730e85259c23c450d921afb7be2", + }, + }, + { + .p = "d5b3e02a00ec37238b8739f3ab1bed99", + .first_non_square = 67, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "45029faf1a073c8cb536f5eda7fd1560", + [3] = "f768c37c2f57a1a9c226ff461c562b", + [4] = "2", + [5] = "65b4689cf2d75db16dcd3105953ce3c6", + [6] = "5684c6ba43a113848a8969d2fb6ca23a", + [7] = "1ff8e09fcaf051326e5c632e0cd4f823", + [8] = "4baea0cbccddbe0a21194e185b21c2d9", + [9] = "3", + [10] = "4285c184615d84354cf9a87345e9d1bb", + [11] = "e970057e6c9a32e07738b0ab78d90ba", + [12] = "1eed186f85eaf4353844dfe8c38ac56", + [13] = "67cc0965e6dd98513e4d39d0b090df81", + [14] = "1ab1e5e513662050b68d92f8f531b05d", + [15] = "281851578e9af5ae568a5b6f1c9147fd", + [16] = "4", + [17] = "1889951f21b30e2095ab76c87fcf9ba5", + [18] = "6ac011cb2d6817d6be2582ab324ad79", + [19] = "5eb623f1739f6fdc336ee0e74b3511ca", + [20] = "a4b0ef01b3d7bc0afecd7e880a2260d", + [21] = "5df17f78bd0ed66c6837513486b31cc5", + [22] = "606ae7b931bdba98f04c5fe37af4ff6b", + [23] = "148d44e0e884ce444c99b6cd437c575e", + [24] = "28aa52b579aa101a7674664db442a925", + [25] = "5", + [26] = "325e9911c86ae631a6bc1f5b699c7e31", + [27] = "2e63a4a748e06e4fd4674fdd2550281", + [28] = "3ff1c13f95e0a264dcb8c65c19a9f046", + [29] = "38fcfd8cec4b90a0de1c4c38cedc15b9", + [30] = "2f6ec8019c1949b8d7f7ce76ff9fa69b", + [31] = "e6ca869dfb345ffd59ace43b3792685", + [32] = "3e569e926730bb0f49549dc2f4d867e7", + [33] = "579bee988ae90b7ccc3e68e0c54d9e2f", + [34] = "569b25c035de96b42221456fa925c7f5", + [35] = "1f830a9c274bf0424f04e1dc96fba083", + [36] = "6", + [37] = "56a04e969e561d11e819e3f0999b2ec3", + [38] = "1399392aaee18717002eebf72a4f2714", + [39] = "184fa0b19872dbc03cc003fb7ef0a647", + [40] = "50a85d213e312eb8f193e90d1f484a23", + [41] = "32edb4d05e11465009b98a6710278c1", + [42] = "1a8d7edc19c5bfc9ffd61781bccc9691", + [43] = "22c80c569d45bb4a9f05877846f790f3", + [44] = "1d2e00afcd93465c0ee716156f1b2174", + [45] = "5b6959acd799e1f0bde0591d149abdb9", + [46] = "21456a4847a1103ea0c239e574779197", + [47] = "47bfe557af21dc9c64152430cf6cf25c", + [48] = "3dda30df0bd5e86a7089bfd187158ac", + [49] = "7", + [50] = "525aa1e87fb43f878cfba6430e467052", + [51] = "68bd2ad79d20ea7312ed693d62c8d008", + [52] = "61bcd5e333106810eecc65249fa2e97", + [53] = "81bd0dba2601145e75e1d77f1d04844", + [54] = "2dda7404c9f7036a141503854729f915", + [55] = "68e4b71490938a9f48933bde86807125", + [56] = "3563cbca26cc40a16d1b25f1ea6360ba", + [57] = "4f2d5569b091a5a79ab7e16a6ba25362", + [58] = "55c448979b854e6bb106146571f68426", + [59] = "302a3d80209e0026e0fecb63e2ce75dd", + [60] = "5030a2af1d35eb5cad14b6de39228ffa", + [61] = "2b92f6a2d393e7a4259eb1cb017f2b00", + [62] = "5a261ada71bcb91ccb1a04c49d16c6e9", + [63] = "5feaa1df60d0f3974b15298a267ee869", + [64] = "8", + [65] = "6181cb54bab42602fb979953302dbe36", + [66] = "610168cbd024ca65f82099abc21d6efd", + [68] = "31132a3e43661c412b56ed90ff9f374a", + [69] = "4835741318cf28d4227c2137b4c5613c", + [70] = "209bda2b3602ef01ac5d0be10bfad042", + [71] = "40ba51b46a55058308aec51c587fc6fe", + [72] = "d58023965ad02fad7c4b05566495af2", + [74] = "d230d76484819d75b87a4216ee67233", + [75] = "4d50bd16cecb62850cac2fc5e8daed7", + [76] = "1847984719ad576b24a9782514b1ca05", + [77] = "3c0c6536905353924fb4f8abc19e281b", + [78] = "3d0dff19927ac726586098881fb096ea", + [80] = "14961de0367af7815fd9afd101444c1a", + [81] = "9", + [82] = "1bccdc1adcd9e6f574bab3fd655d69df", + [83] = "18d4bce73268207ac84da046587f3c06", + [84] = "19d0e13886ce8a4abb18978a9db5b40f", + [85] = "4b9978cf3d8230ed3cadc49a74d5368", + [86] = "128b08847198de2b1645ac717643a123", + [87] = "63caad9c66c7cf88bcaf13f4ec88588a", + [88] = "14de10b79d70c1f1aaee7a2cb531eec3", + [90] = "e229b9cdcd3aa83a49a4099d95e7868", + [91] = "636ffea27582b5e892f407d04f9dfc9", + [92] = "291a89c1d1099c8899336d9a86f8aebc", + [93] = "26be0f04da5bbe43fd72738163315128", + [94] = "2978cccfee4c80269a3463e3bebb5dc8", + [95] = "36c57b7d41260e361126830cb6b5c75f", + [96] = "5154a56af3542034ece8cc9b6885524a", + [98] = "37aa9d75b45a3991dd72459841b3ba6e", + [99] = "2bc50107b45ce98a165aa12026a8b22e", + }, + }, + { + .p = "ebad0be3a536493da57f0fe644b4e021", + .first_non_square = 61, + .sqrt = { + [0] = "0", + [1] = "1", + [2] = "123db297cea699fb0344c1a1a1f186f3", + [3] = "bf6436b702b833d17678ccfe261262f", + [4] = "2", + [5] = "70f8ee4ff65e26fb5773b23de20012cf", + [6] = "5dee45725830feb3edd2b0e1513d9316", + [7] = "66a976a6da314fb8c0e2017aa49b4aaa", + [8] = "247b652f9d4d33f60689834343e30de6", + [9] = "3", + [10] = "3b0561b1c9001e576bf37ae3e029d215", + [11] = "2a4ac9391e3061d7182f14f088c62564", + [12] = "17ec86d6e057067a2ecf199fc4c24c5e", + [13] = "3648df5a9ba7ba504370d498d59fd9a1", + [14] = "6481962d0448c2db2aa4e42a481786f3", + [15] = "1af1cbdc9ef10ecc8382347a181e34cc", + [16] = "4", + [17] = "3f172b01dabd178cca0bc966f1fdf6f3", + [18] = "36b917c76bf3cdf109ce44e4e5d494d9", + [19] = "65ef4e2e99d2781eb82b88fe04e6f1f5", + [20] = "9bb2f43b879fb46f697ab6a80b4ba83", + [21] = "18e1abe04941114658e9e6f21f47dd08", + [22] = "5f978475f36f4e4ce77c522191208b3", + [23] = "357fa88c030974a0bc36f851f0795e64", + [24] = "2fd080fef4d44bd5c9d9ae23a239b9f5", + [25] = "5", + [26] = "408935d3281810e0ce90b4f2985fcf5e", + [27] = "23e2ca42508289b74636a66fa723728d", + [28] = "1e5a1e95f0d3a9cc23bb0cf0fb7e4acd", + [29] = "5f2c0d7368f0b6b1d2a16643a705a279", + [30] = "17549d7da5e5b8bd89b2849403020df0", + [31] = "7210f7c02ab70af02f0c665461b42f9c", + [32] = "48f6ca5f3a9a67ec0d13068687c61bcc", + [33] = "4951d8bebbe35c3f19483f7c871c8ee2", + [34] = "5a7a0a5f2d5f90c936cee2e1f1448983", + [35] = "2d5cc3d220d762d0bafed021e3b701f7", + [36] = "6", + [37] = "4eb91be8674d073b7cad4f89d9b90fd9", + [38] = "223270fd99acd27c3e6ca67c60efee95", + [39] = "2c8220ca14a994690d2737863449596e", + [40] = "75a2488013360c8ecd981a1e84613bf7", + [41] = "67b2177c12aabd92026438a46ab4cb61", + [42] = "5d34f549c9252d13b2e417b1dda2793d", + [43] = "4710ac452532ca6122daeacc47ada339", + [44] = "549592723c60c3ae305e29e1118c4ac8", + [45] = "673dbf0c3de42bb460dc06d3614b584c", + [46] = "600d79740b8a279419d8716358bdcff8", + [47] = "6bb1a8ff33f37594bad6958999635634", + [48] = "2fd90dadc0ae0cf45d9e333f898498bc", + [49] = "7", + [50] = "5b347cf7094101e71057c82829b7a2bf", + [51] = "fb13b5a54b5f9a85079f05cd8dbc210", + [52] = "6c91beb5374f74a086e1a931ab3fb342", + [53] = "5c04393e2792c7f52e5ea35e49daf887", + [54] = "2e1dc473635cb2de23f902bdaf03d921", + [55] = "59c9e5d019f3c45d7bd67877148f7b0b", + [56] = "22a9df899ca4c38750354791b485d23b", + [57] = "1cbf6261b5e6f70d8b62240aca1404c0", + [58] = "6df943332998c675130fe1ea5965661", + [59] = "3931526869d8069ffab62e14f7463ebc", + [60] = "35e397b93de21d99070468f4303c6998", + [62] = "71287677776721bbb63d7a47e3d3271f", + [63] = "484f5810e95da5ec9d26f489a91cffdd", + [64] = "8", + [65] = "24f66f45952f7b1a8a788adf0b988dd8", + [66] = "55358e335092c9ad35db80f42dbda41a", + [67] = "541c13cfadd2c6e4a3e57237c33e2b6e", + [68] = "6d7eb5dfefbc1a2411677d1860b8f23b", + [69] = "5bd017f4178d6d06fb91e3dd0daee5de", + [70] = "bce4858fe7d92a437b916d8525a45b0", + [71] = "2f318248a0091aa2094717d79179c32f", + [72] = "6d722f8ed7e79be2139c89c9cba929b2", + [74] = "5979aa2335b2e6800722423a6dce7cc8", + [75] = "3bcf511930d990317505c00f6be5beeb", + [76] = "1fce6f86719159003527fdea3ae6fc37", + [77] = "3548cedb5a44367e61e396e1b9fbccd7", + [78] = "3820cfa14dd428ff95f92b750c0af8fa", + [79] = "1b610761a0faff110434c44da3056ad", + [80] = "13765e8770f3f68ded2f56d501697506", + [81] = "9", + [82] = "4f0934854d6129caf0f3268c2b6b9ba1", + [84] = "31c357c09282228cb1d3cde43e8fba10", + [85] = "6528c8fcf5a00c45c1a742a924dc6105", + [86] = "40948b6c8dacf9307d00643172b10021", + [87] = "58f0cbf88142db86d306e56d7ca053ab", + [88] = "bf2f08ebe6de9c99cef8a4432241166", + [90] = "3a9ce6ce4a35ee3761a49f3aa43769e2", + [91] = "61e94c9be16d9115fcf3d10de819b796", + [92] = "6aff51180612e941786df0a3e0f2bcc8", + [93] = "70e2effd74ee8238a346798baf98f88", + [94] = "27630a3037b0748d160c9f0d0b6446ae", + [95] = "3ab1e5b6243a976461a7c25ebc9b6933", + [96] = "5fa101fde9a897ab93b35c47447373ea", + [98] = "6bfd29bcfea813608e9dc47ad71a2f7c", + [99] = "6cccb0384aa523b85cf1d114aa626ff5", + }, + }, +}; + +#define N_P_IS_1_MOD_8_TESTS \ + (sizeof(p_is_1_mod_8_tests) / sizeof(p_is_1_mod_8_tests[0])) + +static int +bn_mod_sqrt_p_is_1_mod_8_test(const struct p_is_1_mod_8_tests *test, + BN_CTX *ctx) +{ + BIGNUM *a, *p, *want, *got, *diff; + const char *const *sqrts = test->sqrt; + int i; + int failed = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "a = BN_CTX_get()"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "p = BN_CTX_get()"); + if ((want = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get()"); + if ((got = BN_CTX_get(ctx)) == NULL) + errx(1, "got = BN_CTX_get()"); + if ((diff = BN_CTX_get(ctx)) == NULL) + errx(1, "diff = BN_CTX_get()"); + + if (!BN_hex2bn(&p, test->p)) + errx(1, "BN_hex2bn"); + + for (i = 0; i < N_SMALL_SQUARE_TESTS; i++) { + if (!BN_set_word(a, i)) + errx(1, "BN_set_word"); + + if (BN_mod_sqrt(got, a, p, ctx) == NULL) { + if (i < test->first_non_square || sqrts[i] != NULL) { + fprintf(stderr, "no sqrt(%d) (mod %s)?\n", + i, test->p); + failed |= 1; + } + continue; + } + + if (sqrts[i] == NULL) { + fprintf(stderr, "sqrt(%d) (mod %s): ", i, test->p); + BN_print_fp(stderr, got); + fprintf(stderr, "?\n"); + failed |= 1; + continue; + } + + if (!BN_hex2bn(&want, sqrts[i])) + errx(1, "BN_hex2bn"); + + if (!BN_mod_sub(diff, want, got, p, ctx)) + errx(1, "BN_mod_sub() failed\n"); + + if (!BN_is_zero(diff)) { + fprintf(stderr, "a: %d\n", i); + fprintf(stderr, "p: %s\n", test->p); + fprintf(stderr, "want: %s\n", sqrts[i]); + fprintf(stderr, "got: "); + BN_print_fp(stderr, got); + fprintf(stderr, "\n\n"); + + failed |= 1; + continue; + } + } + + BN_CTX_end(ctx); + + return failed; +} + +static int +bn_mod_sqrt_p_is_1_mod_8(void) +{ + BN_CTX *ctx; + size_t i; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + for (i = 0; i < N_P_IS_1_MOD_8_TESTS; i++) { + const struct p_is_1_mod_8_tests *test = &p_is_1_mod_8_tests[i]; + + failed |= bn_mod_sqrt_p_is_1_mod_8_test(test, ctx); + } + + BN_CTX_free(ctx); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= bn_mod_sqrt_test(); + failed |= bn_mod_sqrt_p_is_1_mod_8(); + + return failed; +} diff --git a/tests/bn_mont.c b/tests/bn_mont.c new file mode 100644 index 0000000..4bcc79d --- /dev/null +++ b/tests/bn_mont.c @@ -0,0 +1,83 @@ +/* $OpenBSD: bn_mont.c,v 1.2 2022/12/06 18:23:29 tb Exp $ */ + +/* + * Copyright (c) 2014 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* + * Test for proper bn_mul_mont behaviour when operands are of vastly different + * sizes. + */ + +int +main(int argc, char *argv[]) +{ + DH *dh = NULL; + BIGNUM *priv_key = NULL; + unsigned char *key = NULL; + unsigned char r[32 + 16 * 8]; + size_t privsz; + + arc4random_buf(r, sizeof(r)); + + for (privsz = 32; privsz <= sizeof(r); privsz += 8) { + dh = DH_new(); + if (dh == NULL) + goto err; + if (DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2, + NULL) == 0) + goto err; + + /* force private key to be much larger than public one */ + priv_key = BN_bin2bn(r, privsz, NULL); + if (priv_key == NULL) + goto err; + + if (!DH_set0_key(dh, NULL, priv_key)) + goto err; + priv_key = NULL; + + if (DH_generate_key(dh) == 0) + goto err; + key = malloc(DH_size(dh)); + if (key == NULL) + err(1, "malloc"); + if (DH_compute_key(key, DH_get0_pub_key(dh), dh) == -1) + goto err; + + free(key); + key = NULL; + DH_free(dh); + dh = NULL; + } + + return 0; + + err: + ERR_print_errors_fp(stderr); + free(key); + BN_free(priv_key); + DH_free(dh); + return 1; +} diff --git a/tests/bn_mul_div.c b/tests/bn_mul_div.c new file mode 100644 index 0000000..625d5e3 --- /dev/null +++ b/tests/bn_mul_div.c @@ -0,0 +1,500 @@ +/* $OpenBSD: bn_mul_div.c,v 1.7 2023/06/21 07:18:10 jsing Exp $ */ +/* + * Copyright (c) 2023 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static int +benchmark_bn_div_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits, + BIGNUM *r, BIGNUM *q) +{ + if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_rand(b, b_bits - 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_set_bit(r, a_bits)) + return 0; + if (!BN_set_bit(q, b_bits)) + return 0; + + return 1; +} + +static void +benchmark_bn_div_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx) +{ + if (!BN_div(r, q, a, b, bn_ctx)) + errx(1, "BN_div"); +} + +static int +benchmark_bn_mul_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits, + BIGNUM *r, BIGNUM *q) +{ + if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_rand(b, b_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_set_bit(r, (a_bits + b_bits) - 1)) + return 0; + + return 1; +} + +static void +benchmark_bn_mul_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx) +{ + if (!BN_mul(r, a, b, bn_ctx)) + errx(1, "BN_mul"); +} + +static int +benchmark_bn_sqr_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits, + BIGNUM *r, BIGNUM *q) +{ + if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_set_bit(r, (a_bits + a_bits) - 1)) + return 0; + + return 1; +} + +static void +benchmark_bn_sqr_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx) +{ + if (!BN_sqr(r, a, bn_ctx)) + errx(1, "BN_sqr"); +} + +struct benchmark { + const char *desc; + int (*setup)(BIGNUM *, size_t, BIGNUM *, size_t, BIGNUM *, BIGNUM *); + void (*run_once)(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BN_CTX *); + size_t a_bits; + size_t b_bits; +}; + +struct benchmark benchmarks[] = { + { + .desc = "BN_div (64 bit / 64 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 64, + .b_bits = 64, + }, + { + .desc = "BN_div (128 bit / 128 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 128, + .b_bits = 128, + }, + { + .desc = "BN_div (196 bit / 196 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 196, + .b_bits = 196, + }, + { + .desc = "BN_div (256 bit / 256 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 256, + .b_bits = 256, + }, + { + .desc = "BN_div (320 bit / 320 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 320, + .b_bits = 320, + }, + { + .desc = "BN_div (384 bit / 384 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 384, + .b_bits = 384, + }, + { + .desc = "BN_div (384 bit / 128 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 384, + .b_bits = 128, + }, + { + .desc = "BN_div (448 bit / 256 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 448, + .b_bits = 256, + }, + { + .desc = "BN_div (512 bit / 512 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 512, + .b_bits = 512, + }, + { + .desc = "BN_div (768 bit / 256 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 768, + .b_bits = 256, + }, + { + .desc = "BN_div (1024 bit / 128 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 1024, + .b_bits = 128, + }, + { + .desc = "BN_div (2048 bit / 512 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 2048, + .b_bits = 128, + }, + { + .desc = "BN_div (3072 bit / 1024 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 2048, + .b_bits = 1024, + }, + { + .desc = "BN_div (4288 bit / 2176 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 2048, + .b_bits = 1024, + }, + { + .desc = "BN_div (6144 bit / 2048 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 2048, + .b_bits = 1024, + }, + { + .desc = "BN_div (16384 bit / 8192 bit)", + .setup = benchmark_bn_div_setup, + .run_once = benchmark_bn_div_run_once, + .a_bits = 16384, + .b_bits = 8192, + }, + { + .desc = "BN_mul (128 bit x 128 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 128, + .b_bits = 128, + }, + { + .desc = "BN_mul (128 bit x 256 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 128, + .b_bits = 256, + }, + { + .desc = "BN_mul (256 bit x 256 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 256, + .b_bits = 256, + }, + { + .desc = "BN_mul (512 bit x 512 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 512, + .b_bits = 512, + }, + { + .desc = "BN_mul (1024 bit x 1024 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 1024, + .b_bits = 1024, + }, + { + .desc = "BN_mul (1024 bit x 2048 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 1024, + .b_bits = 2048, + }, + { + .desc = "BN_mul (2048 bit x 2048 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 2048, + .b_bits = 2048, + }, + { + .desc = "BN_mul (4096 bit x 4096 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 4096, + .b_bits = 4096, + }, + { + .desc = "BN_mul (4096 bit x 8192 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 4096, + .b_bits = 8192, + }, + { + .desc = "BN_mul (8192 bit x 8192 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 8192, + .b_bits = 8192, + }, + { + .desc = "BN_sqr (128 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 128, + }, + { + .desc = "BN_sqr (256 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 256, + }, + { + .desc = "BN_sqr (512 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 512, + }, + { + .desc = "BN_sqr (1024 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 1024, + }, + { + .desc = "BN_sqr (2048 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 2048, + }, + { + .desc = "BN_sqr (4096 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 4096, + }, + { + .desc = "BN_sqr (8192 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 8192, + }, +}; + +#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) + +static volatile sig_atomic_t benchmark_stop; + +static void +benchmark_sig_alarm(int sig) +{ + benchmark_stop = 1; +} + +static void +benchmark_run(const struct benchmark *bm, int seconds) +{ + struct timespec start, end, duration; + struct rusage rusage; + BIGNUM *a, *b, *r, *q; + BN_CTX *bn_ctx; + int i; + + signal(SIGALRM, benchmark_sig_alarm); + + if ((bn_ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(bn_ctx); + + if ((a = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((b = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((r = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((q = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + + BN_set_flags(a, BN_FLG_CONSTTIME); + BN_set_flags(b, BN_FLG_CONSTTIME); + + if (!bm->setup(a, bm->a_bits, b, bm->b_bits, r, q)) + errx(1, "benchmark setup failed"); + + benchmark_stop = 0; + i = 0; + alarm(seconds); + + if (getrusage(RUSAGE_SELF, &rusage) == -1) + err(1, "getrusage failed"); + TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start); + + fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); + while (!benchmark_stop) { + bm->run_once(r, q, a, b, bn_ctx); + i++; + } + if (getrusage(RUSAGE_SELF, &rusage) == -1) + err(1, "getrusage failed"); + TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end); + + timespecsub(&end, &start, &duration); + fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i, + duration.tv_sec + duration.tv_nsec / 1000000000.0, + (uint64_t)i * 1000000000 / + (duration.tv_sec * 1000000000 + duration.tv_nsec)); + + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); +} + +static void +benchmark_bn_mul_sqr(void) +{ + const struct benchmark *bm; + size_t i; + + for (i = 0; i < N_BENCHMARKS; i++) { + bm = &benchmarks[i]; + benchmark_run(bm, 5); + } +} + +static int +test_bn_sqr(void) +{ + BN_CTX *bn_ctx = NULL; + BIGNUM *a, *r; + int failed = 1; + + if ((bn_ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(bn_ctx); + + if ((a = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_new"); + if ((r = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_new"); + + /* Square of a new BN. */ + if (!BN_sqr(r, a, bn_ctx)) { + fprintf(stderr, "FAIL: BN_sqr() on new BN failed\n"); + goto failure; + } + if (!BN_is_zero(r)) { + fprintf(stderr, "FAIL: BN_sqr() on new BN is not zero\n"); + goto failure; + } + + /* Square of BN that is explicitly set to zero. */ + if (!BN_set_word(a, 0)) { + fprintf(stderr, "FAIL: BN_set_word(0) failed\n"); + goto failure; + } + if (!BN_sqr(r, a, bn_ctx)) { + fprintf(stderr, "FAIL: BN_sqr(0) failed\n"); + goto failure; + } + if (!BN_is_zero(r)) { + fprintf(stderr, "FAIL: BN_sqr(0) != 0\n"); + goto failure; + } + + /* Square of BN with value one. */ + if (!BN_set_word(a, 1)) { + fprintf(stderr, "FAIL: BN_set_word(1) failed\n"); + goto failure; + } + if (!BN_sqr(r, a, bn_ctx)) { + fprintf(stderr, "FAIL: BN_sqr(1) failed\n"); + goto failure; + } + if (BN_get_word(r) != 1) { + fprintf(stderr, "FAIL: BN_sqr(1) != 1\n"); + goto failure; + } + + /* Square of BN with value two. */ + if (!BN_set_word(a, 2)) { + fprintf(stderr, "FAIL: BN_set_word(2) failed\n"); + goto failure; + } + if (!BN_sqr(r, a, bn_ctx)) { + fprintf(stderr, "FAIL: BN_sqr(2) failed\n"); + goto failure; + } + if (BN_get_word(r) != 4) { + fprintf(stderr, "FAIL: BN_sqr(2) != 4\n"); + goto failure; + } + + failed = 0; + + failure: + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); + + return failed; +} + +int +main(int argc, char **argv) +{ + int benchmark = 0, failed = 0; + + if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) + benchmark = 1; + + failed |= test_bn_sqr(); + + if (benchmark && !failed) + benchmark_bn_mul_sqr(); + + return failed; +} diff --git a/tests/bn_primes.c b/tests/bn_primes.c new file mode 100644 index 0000000..8180b0d --- /dev/null +++ b/tests/bn_primes.c @@ -0,0 +1,148 @@ +/* $OpenBSD: bn_primes.c,v 1.3 2023/04/25 15:30:03 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#include "bn_prime.h" + +static int +test_bn_is_prime_fasttest(int do_trial_division) +{ + BIGNUM *n = NULL; + char *descr = NULL; + uint16_t i, j, max; + int is_prime, ret; + int failed = 1; + + if (asprintf(&descr, "with%s trial divisions", + do_trial_division ? "" : "out") == -1) { + descr = NULL; + fprintf(stderr, "asprintf failed\n"); + goto err; + } + + if ((n = BN_new()) == NULL) { + fprintf(stderr, "BN_new failed\n"); + goto err; + } + + max = primes[NUMPRIMES - 1] + 1; + + failed = 0; + for (i = 1, j = 0; i < max && j < NUMPRIMES; i++) { + if (!BN_set_word(n, i)) { + fprintf(stderr, "BN_set_word(%d) failed", i); + failed = 1; + goto err; + } + + is_prime = i == primes[j]; + if (is_prime) + j++; + + ret = BN_is_prime_fasttest_ex(n, BN_prime_checks, NULL, + do_trial_division, NULL); + if (ret != is_prime) { + fprintf(stderr, + "BN_is_prime_fasttest_ex(%d) %s: want %d, got %d\n", + i, descr, is_prime, ret); + failed = 1; + } + } + + if (i < max || j < NUMPRIMES) { + fprintf(stderr, "%s: %d < %d or %d < %d\n", descr, i, max, j, + NUMPRIMES); + failed = 1; + } + + err: + BN_free(n); + free(descr); + return failed; +} + +#define BN_PRIME_FN_INIT(a) { .fn = a, .name = #a } + +static const struct test_dynamic_api { + BIGNUM *(*fn)(BIGNUM *); + const char *name; +} dynamic_api_data[] = { + BN_PRIME_FN_INIT(BN_get_rfc2409_prime_1024), + BN_PRIME_FN_INIT(BN_get_rfc2409_prime_768), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_1536), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_2048), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_3072), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_4096), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_6144), + BN_PRIME_FN_INIT(BN_get_rfc3526_prime_8192), +}; + +#define N_DYNAMIC_TESTS (sizeof(dynamic_api_data) / sizeof(dynamic_api_data[0])) + +static int +test_prime_dynamic_api(const struct test_dynamic_api *tc) +{ + BIGNUM *prime; + int ret; + int failed = 1; + + if ((prime = tc->fn(NULL)) == NULL) { + fprintf(stderr, "%s failed\n", tc->name); + goto err; + } + + if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) { + fprintf(stderr, "%s: %s want 1, got %d\n", tc->name, + "BN_is_prime_fasttest_ex", ret); + goto err; + } + + failed = 0; + + err: + BN_free(prime); + return failed; +} + +static int +test_prime_constants(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_DYNAMIC_TESTS; i++) + failed |= test_prime_dynamic_api(&dynamic_api_data[i]); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_bn_is_prime_fasttest(0); + failed |= test_bn_is_prime_fasttest(1); + failed |= test_prime_constants(); + + return failed; +} diff --git a/tests/bn_print.c b/tests/bn_print.c new file mode 100644 index 0000000..a311886 --- /dev/null +++ b/tests/bn_print.c @@ -0,0 +1,305 @@ +/* $OpenBSD: bn_print.c,v 1.5 2023/07/27 06:41:39 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +#include "bn_local.h" + +#define BATIHDIDIDI "mana mana" +#define BUF_MEM_LEN 1024 + +static const char *pk = "040d305e1b159d03d0a17935b73a3c927aca151ccd62f39c" + "265c073de554faa3d6cc12eaf4145fe88e19ab2f2e48e6ac" + "184378acd037c3bdb2cd2ce647e21ae663b83d2e2f78c44f" + "dbf40fa4684c55726b951d4e18429578cc373c91e29b652b" + "29"; + +const struct print_test { + const char *desc; + const char *want; +} bn_print_tests[] = { + { + .desc = "zero", + .want = " mana mana 0\n", + }, + { + .desc = "minus one", + .want = " mana mana 1 (0x1)\n", + }, + { + .desc = "minus one", + .want = " mana mana -1 (-0x1)\n", + }, +#ifdef _LP64 + { + .desc = "largest word", + .want = " mana mana 18446744073709551615 " + "(0xffffffffffffffff)\n", + }, + { + .desc = "smallest word", + .want = " mana mana -18446744073709551615 " + "(-0xffffffffffffffff)\n", + }, + { + .desc = "largest negative non-word", + .want = " mana mana (Negative)\n" + " 01:00:00:00:00:00:00:00:00\n", + }, + { + .desc = "smallest positive non-word", + .want = " mana mana\n" + " 01:00:00:00:00:00:00:00:00\n", + }, +#else + { + .desc = "largest word", + .want = " mana mana 4294967295 (0xffffffff)\n", + }, + { + .desc = "smallest word", + .want = " mana mana -4294967295 (-0xffffffff)\n", + }, + { + .desc = "largest negative non-word", + .want = " mana mana (Negative)\n" + " 01:00:00:00:00\n", + }, + { + .desc = "smallest positive non-word", + .want = " mana mana\n" + " 01:00:00:00:00\n", + }, +#endif + { + .desc = "some pubkey", + .want = " mana mana\n" + " 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n" + " 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n" + " fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n" + " 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n" + " 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n" + " a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37:\n" + " 3c:91:e2:9b:65:2b:29\n", + }, + { + .desc = "negated pubkey", + .want = " mana mana (Negative)\n" + " 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n" + " 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n" + " fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n" + " 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n" + " 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n" + " a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37:\n" + " 3c:91:e2:9b:65:2b:29\n", + }, + { + .desc = "shifted negated pubkey", + .want = " mana mana (Negative)\n" + " 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n" + " 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n" + " fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n" + " 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n" + " 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n" + " a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37\n", + }, + { + .desc = "shifted pubkey", + .want = " mana mana\n" + " 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:\n" + " 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:\n" + " fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:\n" + " 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:\n" + " 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:\n" + " a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37\n", + }, + { + .desc = "high bit of first nibble is set", + .want = " mana mana\n" + " 00:80:00:00:00:00:00:00:00:00\n", + }, + { + /* XXX - this is incorrect and should be fixed. */ + .desc = "high bit of first nibble is set for negative number", + .want = " mana mana (Negative)\n" + " 00:80:00:00:00:00:00:00:00:00\n", + }, +}; + +#define N_TESTCASES (sizeof(bn_print_tests) / sizeof(bn_print_tests[0])) + +static int +bn_print_testcase(const BIGNUM *bn, const struct print_test *test) +{ + BIO *bio; + char *got; + size_t want_len; + long got_len; + int failed = 1; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new"); + + if (!bn_printf(bio, bn, 4, "%s", BATIHDIDIDI)) + errx(1, "bn_printf"); + + if ((got_len = BIO_get_mem_data(bio, &got)) < 0) + errx(1, "BIO_get_mem_data"); + + if ((want_len = strlen(test->want)) != (size_t)got_len) { + fprintf(stderr, "%s: want: %zu, got %ld\n", + test->desc, want_len, got_len); + goto err; + } + + if (strncmp(got, test->want, want_len) != 0) { + fprintf(stderr, "%s: strings differ\n", test->desc); + fprintf(stderr, "want: \"%s\"\ngot : \"%*s\"\n", + test->want, (int)got_len, got); + goto err; + } + + failed = 0; + err: + BIO_free(bio); + + return failed; +} + +int +main(void) +{ + const struct print_test *test; + size_t testcase = 0; + BIGNUM *bn; + int failed = 0; + + /* zero */ + if ((bn = BN_new()) == NULL) + errx(1, "BN_new"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* one */ + if (!BN_set_word(bn, 1)) + errx(1, "BIO_set_word"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* minus one */ + BN_set_negative(bn, 1); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* largest word */ + if (!BN_set_word(bn, ~0)) + errx(1, "BN_set_word"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* smallest word */ + BN_set_negative(bn, 1); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* largest negative non-word */ + if (!BN_sub_word(bn, 1)) + errx(1, "ASN1_bn_print"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* smallest positive non-word */ + BN_set_negative(bn, 0); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* some pubkey */ + if (BN_hex2bn(&bn, pk) == 0) + errx(1, "BN_hex2bn"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* negated pubkey */ + BN_set_negative(bn, 1); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* shifted negated pubkey */ + if (!BN_rshift(bn, bn, 7 * 8)) + errx(1, "BN_rshift"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* shifted pubkey */ + BN_set_negative(bn, 0); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* high bit of first nibble is set. */ + BN_zero(bn); + if (!BN_set_bit(bn, 71)) + errx(1, "BN_set_bit"); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + /* high bit of first nibble is set for negative number. */ + BN_set_negative(bn, 1); + if (testcase >= N_TESTCASES) + errx(1, "Too many tests"); + test = &bn_print_tests[testcase++]; + failed |= bn_print_testcase(bn, test); + + if (testcase != N_TESTCASES) { + warnx("Not all tests run"); + failed |= 1; + } + + BN_free(bn); + + return failed; +} diff --git a/tests/bn_shift.c b/tests/bn_shift.c new file mode 100644 index 0000000..95a6197 --- /dev/null +++ b/tests/bn_shift.c @@ -0,0 +1,659 @@ +/* $OpenBSD: bn_shift.c,v 1.9 2023/03/11 14:02:26 jsing Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +static const char *bn_shift_want_hex = \ + "02AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \ + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8"; + +static int +check_shift_result(BIGNUM *bn1) +{ + BIGNUM *bn2 = NULL; + char *s = NULL; + int ret = 0; + + if (!BN_hex2bn(&bn2, bn_shift_want_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn() failed\n"); + goto failure; + } + if (BN_cmp(bn1, bn2) != 0) { + fprintf(stderr, "FAIL: shifted result differs\n"); + if ((s = BN_bn2hex(bn1)) == NULL) { + fprintf(stderr, "FAIL: BN_bn2hex()\n"); + goto failure; + } + fprintf(stderr, "Got: %s\n", s); + free(s); + if ((s = BN_bn2hex(bn2)) == NULL) { + fprintf(stderr, "FAIL: BN_bn2hex()\n"); + goto failure; + } + fprintf(stderr, "Want: %s\n", s); + } + + ret = 1; + + failure: + BN_free(bn2); + free(s); + + return ret; +} + +static int +test_bn_shift1(void) +{ + BIGNUM *bn1 = NULL, *bn2 = NULL; + int i; + int failed = 1; + + if ((bn1 = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + if ((bn2 = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN\n"); + goto failure; + } + + for (i = 1; i <= 256; i++) { + if (!BN_set_bit(bn1, 1)) { + fprintf(stderr, "FAIL: failed to set bit\n"); + goto failure; + } + if (!BN_lshift1(bn1, bn1)) { + fprintf(stderr, "FAIL: failed to BN_lshift1()\n"); + goto failure; + } + if (!BN_lshift1(bn1, bn1)) { + fprintf(stderr, "FAIL: failed to BN_lshift1()\n"); + goto failure; + } + if (!BN_rshift1(bn1, bn1)) { + fprintf(stderr, "FAIL: failed to BN_rshift1()\n"); + goto failure; + } + if (!BN_lshift1(bn1, bn1)) { + fprintf(stderr, "FAIL: failed to BN_lshift1()\n"); + goto failure; + } + } + + if (!check_shift_result(bn1)) + goto failure; + + /* + * Shift result into a different BN. + */ + if (!BN_lshift1(bn1, bn1)) { + fprintf(stderr, "FAIL: failed to BN_lshift1()\n"); + goto failure; + } + if (!BN_rshift1(bn2, bn1)) { + fprintf(stderr, "FAIL: failed to BN_rshift1()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + if (!BN_rshift1(bn2, bn2)) { + fprintf(stderr, "FAIL: failed to BN_rshift1()\n"); + goto failure; + } + if (!BN_lshift1(bn1, bn2)) { + fprintf(stderr, "FAIL: failed to BN_lshift1()\n"); + goto failure; + } + + if (!check_shift_result(bn1)) + goto failure; + + failed = 0; + + failure: + BN_free(bn1); + BN_free(bn2); + + return failed; +} + +static int +test_bn_shift(void) +{ + BIGNUM *bn1 = NULL, *bn2 = NULL; + int i; + int failed = 1; + + if ((bn1 = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN 1\n"); + goto failure; + } + if ((bn2 = BN_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create BN 2\n"); + goto failure; + } + + for (i = 1; i <= 256; i++) { + if (!BN_set_bit(bn1, 1)) { + fprintf(stderr, "FAIL: failed to set bit\n"); + goto failure; + } + if (!BN_lshift(bn1, bn1, i + 1)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + if (!BN_rshift(bn1, bn1, i - 1)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + } + + if (!check_shift_result(bn1)) + goto failure; + + for (i = 0; i <= 256; i++) { + if (!BN_lshift(bn1, bn1, i)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + if (i > 1) { + if (!BN_set_bit(bn1, 1)) { + fprintf(stderr, "FAIL: failed to set bit\n"); + goto failure; + } + } + } + + if (BN_num_bytes(bn1) != 4177) { + fprintf(stderr, "FAIL: BN has %d bytes, want 4177\n", + BN_num_bytes(bn1)); + goto failure; + } + + for (i = 0; i <= 256; i++) { + if (!BN_rshift(bn1, bn1, i)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + } + + if (!check_shift_result(bn1)) + goto failure; + + /* + * Shift result into a different BN. + */ + if (!BN_lshift(bn1, bn1, BN_BITS2 + 1)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + if (!BN_rshift(bn2, bn1, BN_BITS2 + 1)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + if (!BN_rshift(bn2, bn2, 3)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + if (!BN_lshift(bn1, bn2, 3)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + + if (!check_shift_result(bn1)) + goto failure; + + /* + * Shift of zero (equivalent to a copy). + */ + BN_zero(bn2); + if (!BN_lshift(bn2, bn1, 0)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + if (!BN_lshift(bn2, bn2, 0)) { + fprintf(stderr, "FAIL: failed to BN_lshift()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + BN_zero(bn2); + if (!BN_rshift(bn2, bn1, 0)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + if (!BN_rshift(bn2, bn2, 0)) { + fprintf(stderr, "FAIL: failed to BN_rshift()\n"); + goto failure; + } + + if (!check_shift_result(bn2)) + goto failure; + + failed = 0; + + failure: + BN_free(bn1); + BN_free(bn2); + + return failed; +} + +static int +test_bn_rshift_to_zero(void) +{ + BIGNUM *bn1 = NULL, *bn2 = NULL; + int failed = 1; + + if (!BN_hex2bn(&bn1, "ffff")) { + fprintf(stderr, "FAIL: BN_hex2bn() failed\n"); + goto failure; + } + if (!BN_lshift(bn1, bn1, BN_BITS2)) { + fprintf(stderr, "FAIL: BN_lshift() failed\n"); + goto failure; + } + + if ((bn2 = BN_new()) == NULL) { + fprintf(stderr, "FAIL: BN_new() failed\n"); + goto failure; + } + + /* Shift all words. */ + if (!BN_rshift(bn2, bn1, BN_BITS2 * 2)) { + fprintf(stderr, "FAIL: BN_rshift() failed\n"); + goto failure; + } + if (BN_is_zero(bn1)) { + fprintf(stderr, "FAIL: BN is zero\n"); + goto failure; + } + if (!BN_is_zero(bn2)) { + fprintf(stderr, "FAIL: BN is not zero\n"); + goto failure; + } + + /* Shift to zero, with partial shift for top most word. */ + if (!BN_rshift(bn2, bn1, BN_BITS2 + 16)) { + fprintf(stderr, "FAIL: BN_rshift() failed\n"); + goto failure; + } + if (BN_is_zero(bn1)) { + fprintf(stderr, "FAIL: BN is zero\n"); + goto failure; + } + if (!BN_is_zero(bn2)) { + fprintf(stderr, "FAIL: BN is not zero\n"); + goto failure; + } + + /* Shift to zero of negative value. */ + if (!BN_one(bn1)) { + fprintf(stderr, "FAIL: BN_one() failed\n"); + goto failure; + } + BN_set_negative(bn1, 1); + if (!BN_rshift(bn1, bn1, 1)) { + fprintf(stderr, "FAIL: BN_rshift() failed\n"); + goto failure; + } + if (!BN_is_zero(bn1)) { + fprintf(stderr, "FAIL: BN is not zero\n"); + goto failure; + } + if (BN_is_negative(bn1)) { + fprintf(stderr, "FAIL: BN is negative zero\n"); + goto failure; + } + + failed = 0; + + failure: + BN_free(bn1); + BN_free(bn2); + + return failed; +} + +#if 0 + +static void +benchmark_bn_lshift1(BIGNUM *bn) +{ + int i; + + if (!BN_set_bit(bn, 8192)) + errx(1, "BN_set_bit"); + + if (!BN_one(bn)) + errx(1, "BN_one"); + + for (i = 0; i < 8192; i++) { + if (!BN_lshift1(bn, bn)) + errx(1, "BN_lshift1"); + } +} + +static void +benchmark_bn_lshift(BIGNUM *bn, int n) +{ + int i; + + if (!BN_set_bit(bn, 8192 * n)) + errx(1, "BN_set_bit"); + + if (!BN_one(bn)) + errx(1, "BN_one"); + + for (i = 0; i < 8192; i++) { + if (!BN_lshift(bn, bn, n)) + errx(1, "BN_lshift"); + } +} + +static void +benchmark_bn_lshift_1(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 1); +} + +static void +benchmark_bn_lshift_16(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 16); +} + +static void +benchmark_bn_lshift_32(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 32); +} + +static void +benchmark_bn_lshift_64(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 64); +} + +static void +benchmark_bn_lshift_65(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 65); +} + +static void +benchmark_bn_lshift_80(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 80); +} + +static void +benchmark_bn_lshift_127(BIGNUM *bn) +{ + benchmark_bn_lshift(bn, 127); +} + +static void +benchmark_bn_rshift1(BIGNUM *bn) +{ + int i; + + if (!BN_one(bn)) + errx(1, "BN_one"); + + if (!BN_set_bit(bn, 8192)) + errx(1, "BN_set_bit"); + + for (i = 0; i < 8192; i++) { + if (!BN_rshift1(bn, bn)) + errx(1, "BN_rshift1"); + } +} + +static void +benchmark_bn_rshift(BIGNUM *bn, int n) +{ + int i; + + if (!BN_one(bn)) + errx(1, "BN_one"); + + if (!BN_set_bit(bn, 8192 * n)) + errx(1, "BN_set_bit"); + + for (i = 0; i < 8192; i++) { + if (!BN_rshift(bn, bn, n)) + errx(1, "BN_rshift"); + } +} + +static void +benchmark_bn_rshift_1(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 1); +} + +static void +benchmark_bn_rshift_16(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 16); +} + +static void +benchmark_bn_rshift_32(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 32); +} + +static void +benchmark_bn_rshift_64(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 64); +} + +static void +benchmark_bn_rshift_65(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 65); +} + +static void +benchmark_bn_rshift_80(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 80); +} + +static void +benchmark_bn_rshift_127(BIGNUM *bn) +{ + benchmark_bn_rshift(bn, 127); +} + +struct benchmark { + const char *desc; + void (*func)(BIGNUM *); +}; + +static const struct benchmark benchmarks[] = { + { + .desc = "BN_lshift1()", + .func = benchmark_bn_lshift1, + }, + { + .desc = "BN_lshift(_, _, 1)", + .func = benchmark_bn_lshift_1, + }, + { + .desc = "BN_lshift(_, _, 16)", + .func = benchmark_bn_lshift_16, + }, + { + .desc = "BN_lshift(_, _, 32)", + .func = benchmark_bn_lshift_32, + }, + { + .desc = "BN_lshift(_, _, 64)", + .func = benchmark_bn_lshift_64, + }, + { + .desc = "BN_lshift(_, _, 65)", + .func = benchmark_bn_lshift_65, + }, + { + .desc = "BN_lshift(_, _, 80)", + .func = benchmark_bn_lshift_80, + }, + { + .desc = "BN_lshift(_, _, 127)", + .func = benchmark_bn_lshift_127, + }, + { + .desc = "BN_rshift1()", + .func = benchmark_bn_rshift1, + }, + { + .desc = "BN_rshift(_, _, 1)", + .func = benchmark_bn_rshift_1, + }, + { + .desc = "BN_rshift(_, _, 16)", + .func = benchmark_bn_rshift_16, + }, + { + .desc = "BN_rshift(_, _, 32)", + .func = benchmark_bn_rshift_32, + }, + { + .desc = "BN_rshift(_, _, 64)", + .func = benchmark_bn_rshift_64, + }, + { + .desc = "BN_rshift(_, _, 65)", + .func = benchmark_bn_rshift_65, + }, + { + .desc = "BN_rshift(_, _, 80)", + .func = benchmark_bn_rshift_80, + }, + { + .desc = "BN_rshift(_, _, 127)", + .func = benchmark_bn_rshift_127, + }, +}; + +#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) + +static volatile sig_atomic_t benchmark_stop; + +static void +benchmark_sig_alarm(int sig) +{ + benchmark_stop = 1; +} + +static void +benchmark_run(const struct benchmark *bm, int seconds) +{ + struct timespec start, end, duration; + BIGNUM *bn; + int i; + + signal(SIGALRM, benchmark_sig_alarm); + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new"); + + benchmark_stop = 0; + i = 0; + alarm(seconds); + + clock_gettime(CLOCK_MONOTONIC, &start); + + fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); + while (!benchmark_stop) { + bm->func(bn); + i++; + } + clock_gettime(CLOCK_MONOTONIC, &end); + timespecsub(&end, &start, &duration); + fprintf(stderr, "%d iterations in %f seconds\n", i, + duration.tv_sec + duration.tv_nsec / 1000000000.0); + + BN_free(bn); +} + +#endif + +static void +benchmark_bn_shift(void) +{ +#if 0 + const struct benchmark *bm; + size_t i; + + for (i = 0; i < N_BENCHMARKS; i++) { + bm = &benchmarks[i]; + benchmark_run(bm, 5); + } +#else + return; +#endif +} + +int +main(int argc, char **argv) +{ + int benchmark = 0, failed = 0; + + if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) + benchmark = 1; + + failed |= test_bn_shift1(); + failed |= test_bn_shift(); + failed |= test_bn_rshift_to_zero(); + + if (benchmark && !failed) + benchmark_bn_shift(); + + return failed; +} diff --git a/tests/bn_test.c b/tests/bn_test.c new file mode 100644 index 0000000..f73799b --- /dev/null +++ b/tests/bn_test.c @@ -0,0 +1,1916 @@ +/* $OpenBSD: bn_test.c,v 1.19 2023/04/25 17:17:21 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the Eric Young open source + * license provided above. + * + * The binary polynomial arithmetic software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "bn_local.h" + +const int num0 = 100; /* number of tests */ +const int num1 = 50; /* additional tests for some functions */ +const int num2 = 5; /* number of tests for slow functions */ + +int test_add(BIO *bp, BN_CTX *ctx); +int test_sub(BIO *bp, BN_CTX *ctx); +int test_lshift1(BIO *bp, BN_CTX *ctx); +int test_lshift(BIO *bp, BN_CTX *ctx, int use_lst); +int test_rshift1(BIO *bp, BN_CTX *ctx); +int test_rshift(BIO *bp, BN_CTX *ctx); +int test_div(BIO *bp, BN_CTX *ctx); +int test_div_word(BIO *bp, BN_CTX *ctx); +int test_div_recp(BIO *bp, BN_CTX *ctx); +int test_mul(BIO *bp, BN_CTX *ctx); +int test_sqr(BIO *bp, BN_CTX *ctx); +int test_mont(BIO *bp, BN_CTX *ctx); +int test_mod(BIO *bp, BN_CTX *ctx); +int test_mod_mul(BIO *bp, BN_CTX *ctx); +int test_mod_exp(BIO *bp, BN_CTX *ctx); +int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx); +int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx); +int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx); +int test_exp(BIO *bp, BN_CTX *ctx); +int test_kron(BIO *bp, BN_CTX *ctx); +int test_sqrt(BIO *bp, BN_CTX *ctx); +int rand_neg(void); +static int results = 0; + +#define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \ + __LINE__) + +#define CHECK_GOTO(a) do { \ + if (!(a)) { \ + PRINT_ERROR; \ + goto err; \ + } \ +} while (0) + +static void +message(BIO *out, char *m) +{ + ERR_print_errors_fp(stderr); + ERR_clear_error(); + + fprintf(stderr, "test %s\n", m); + BIO_puts(out, "print \"test "); + BIO_puts(out, m); + BIO_puts(out, "\\n\"\n"); +} + +int +main(int argc, char *argv[]) +{ + BN_CTX *ctx; + BIO *out; + char *outfile = NULL; + + results = 0; + + argc--; + argv++; + while (argc >= 1) { + if (strcmp(*argv, "-results") == 0) + results = 1; + else if (strcmp(*argv, "-out") == 0) { + if (--argc < 1) + break; + outfile= *(++argv); + } + argc--; + argv++; + } + + if ((ctx = BN_CTX_new()) == NULL) + exit(1); + + if ((out = BIO_new(BIO_s_file())) == NULL) + exit(1); + if (outfile == NULL) { + BIO_set_fp(out, stdout, BIO_NOCLOSE); + } else { + if (!BIO_write_filename(out, outfile)) { + perror(outfile); + exit(1); + } + } + + if (!results) + BIO_puts(out, "obase=16\nibase=16\n"); + + message(out, "BN_add"); + if (!test_add(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_sub"); + if (!test_sub(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_lshift1"); + if (!test_lshift1(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_lshift (fixed)"); + if (!test_lshift(out, ctx, 0)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_lshift"); + if (!test_lshift(out, ctx, 1)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_rshift1"); + if (!test_rshift1(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_rshift"); + if (!test_rshift(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_sqr"); + if (!test_sqr(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mul"); + if (!test_mul(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_div"); + if (!test_div(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_div_word"); + if (!test_div_word(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_div_recp"); + if (!test_div_recp(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod"); + if (!test_mod(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod_mul"); + if (!test_mod_mul(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mont"); + if (!test_mont(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod_exp"); + if (!test_mod_exp(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod_exp_mont_consttime"); + if (!test_mod_exp_mont_consttime(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod_exp_mont5"); + if (!test_mod_exp_mont5(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_exp"); + if (!test_exp(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_kronecker"); + if (!test_kron(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "BN_mod_sqrt"); + if (!test_sqrt(out, ctx)) + goto err; + (void)BIO_flush(out); + + message(out, "Modexp with different sizes"); + if (!test_mod_exp_sizes(out, ctx)) + goto err; + (void)BIO_flush(out); + + BN_CTX_free(ctx); + BIO_free(out); + + exit(0); + err: + BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices + * the failure, see test_bn in test/Makefile.ssl*/ + + (void)BIO_flush(out); + ERR_load_crypto_strings(); + ERR_print_errors_fp(stderr); + exit(1); +} + +int +test_add(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0)); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_bntest_rand(b, 450 + i, 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + CHECK_GOTO(BN_add(c, a, b)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " + "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + BN_set_negative(a, !BN_is_negative(a)); + BN_set_negative(b, !BN_is_negative(b)); + CHECK_GOTO(BN_add(c, c, b)); + CHECK_GOTO(BN_add(c, c, a)); + if (!BN_is_zero(c)) { + fprintf(stderr, "Add test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_sub(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + + for (i = 0; i < num0 + num1; i++) { + if (i < num1) { + CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0)); + CHECK_GOTO(bn_copy(b, a)); + if (BN_set_bit(a, i) == 0) + goto err; + CHECK_GOTO(BN_add_word(b, i)); + } else { + CHECK_GOTO(BN_bntest_rand(b, 400 + i - num1, 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + } + CHECK_GOTO(BN_sub(c, a, b)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " - "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_add(c, c, b)); + CHECK_GOTO(BN_sub(c, c, a)); + if (!BN_is_zero(c)) { + fprintf(stderr, "Subtract test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_div(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_one(a)); + BN_zero(b); + + if (BN_div(d, c, a, b, ctx)) { + fprintf(stderr, "Division by zero succeeded!\n"); + goto err; + } + ERR_clear_error(); + + for (i = 0; i < num0 + num1; i++) { + if (i < num1) { + CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0)); + CHECK_GOTO(bn_copy(b, a)); + CHECK_GOTO(BN_lshift(a, a, i)); + CHECK_GOTO(BN_add_word(a, i)); + } else + CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + CHECK_GOTO(BN_div(d, c, a, b, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " / "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(e, d, b, ctx)); + CHECK_GOTO(BN_add(d, e, c)); + CHECK_GOTO(BN_sub(d, d, a)); + if (!BN_is_zero(d)) { + fprintf(stderr, "Division test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +static void +print_word(BIO *bp, BN_ULONG w) +{ +#ifdef SIXTY_FOUR_BIT + if (sizeof(w) > sizeof(unsigned long)) { + unsigned long h = (unsigned long)(w >> 32), l = (unsigned long)(w); + + if (h) + BIO_printf(bp, "%lX%08lX", h, l); + else + BIO_printf(bp, "%lX", l); + return; + } +#endif + BIO_printf(bp, BN_HEX_FMT1, w); +} + +int +test_div_word(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b; + BN_ULONG r, rmod, s = 0; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + + for (i = 0; i < num0; i++) { + do { + if (!BN_bntest_rand(a, 512, -1, 0) || + !BN_bntest_rand(b, BN_BITS2, -1, 0)) + goto err; + s = BN_get_word(b); + } while (!s); + + if (!bn_copy(b, a)) + goto err; + + rmod = BN_mod_word(b, s); + r = BN_div_word(b, s); + + if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) + goto err; + + if (rmod != r) { + fprintf(stderr, "Mod (word) test failed!\n"); + goto err; + } + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " / "); + print_word(bp, s); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, "\n"); + + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " % "); + print_word(bp, s); + BIO_puts(bp, " - "); + } + print_word(bp, r); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul_word(b, s)); + CHECK_GOTO(BN_add_word(b, r)); + CHECK_GOTO(BN_sub(b, a, b)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Division (word) test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_div_recp(BIO *bp, BN_CTX *ctx) +{ + BN_RECP_CTX *recp = NULL; + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + if ((recp = BN_RECP_CTX_new()) == NULL) + goto err; + + for (i = 0; i < num0 + num1; i++) { + if (i < num1) { + CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0)); + CHECK_GOTO(bn_copy(b, a)); + CHECK_GOTO(BN_lshift(a, a, i)); + CHECK_GOTO(BN_add_word(a, i)); + } else + CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + CHECK_GOTO(BN_RECP_CTX_set(recp, b, ctx)); + CHECK_GOTO(BN_div_recp(d, c, a, recp, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " / "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(e, d, b, ctx)); + CHECK_GOTO(BN_add(d, e, c)); + CHECK_GOTO(BN_sub(d, d, a)); + if (!BN_is_zero(d)) { + fprintf(stderr, "Reciprocal division test failed!\n"); + fprintf(stderr, "a="); + CHECK_GOTO(BN_print_fp(stderr, a)); + fprintf(stderr, "\nb="); + CHECK_GOTO(BN_print_fp(stderr, b)); + fprintf(stderr, "\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + BN_RECP_CTX_free(recp); + + return ret; +} + +int +test_mul(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + for (i = 0; i < num0 + num1; i++) { + if (i <= num1) { + CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0)); + } else + CHECK_GOTO(BN_bntest_rand(b, i - num1, 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + CHECK_GOTO(BN_mul(c, a, b, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_div(d, e, c, a, ctx)); + CHECK_GOTO(BN_sub(d, d, b)); + if (!BN_is_zero(d) || !BN_is_zero(e)) { + fprintf(stderr, "Multiplication test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_sqr(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_bntest_rand(a, 40 + i * 10, 0, 0)); + BN_set_negative(a, rand_neg()); + CHECK_GOTO(BN_sqr(c, a, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_div(d, e, c, a, ctx)); + CHECK_GOTO(BN_sub(d, d, a)); + if (!BN_is_zero(d) || !BN_is_zero(e)) { + fprintf(stderr, "Square test failed!\n"); + goto err; + } + } + + /* Regression test for a BN_sqr overflow bug. */ + if (!BN_hex2bn(&a, "80000000000000008000000000000001" + "FFFFFFFFFFFFFFFE0000000000000000")) { + fprintf(stderr, "BN_hex2bn failed\n"); + goto err; + } + CHECK_GOTO(BN_sqr(c, a, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(d, a, a, ctx)); + if (BN_cmp(c, d)) { + fprintf(stderr, + "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + goto err; + } + + /* Regression test for a BN_sqr overflow bug. */ + if (!BN_hex2bn(&a, "80000000000000000000000080000001" + "FFFFFFFE000000000000000000000000")) { + fprintf(stderr, "BN_hex2bn failed\n"); + goto err; + } + CHECK_GOTO(BN_sqr(c, a, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(d, a, a, ctx)); + if (BN_cmp(c, d)) { + fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce " + "different results!\n"); + goto err; + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_mont(BIO *bp, BN_CTX *ctx) +{ + BN_MONT_CTX *mont = NULL; + BIGNUM *a, *b, *c, *d, *A, *B, *n; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((A = BN_CTX_get(ctx)) == NULL) + goto err; + if ((B = BN_CTX_get(ctx)) == NULL) + goto err; + if ((n = BN_CTX_get(ctx)) == NULL) + goto err; + + if ((mont = BN_MONT_CTX_new()) == NULL) + goto err; + + BN_zero(n); + if (BN_MONT_CTX_set(mont, n, ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n"); + goto err; + } + ERR_clear_error(); + + CHECK_GOTO(BN_set_word(n, 16)); + if (BN_MONT_CTX_set(mont, n, ctx)) { + fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n"); + goto err; + } + ERR_clear_error(); + + CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0)); + for (i = 0; i < num2; i++) { + int bits = (200 * (i + 1)) / num2; + + if (bits == 0) + continue; + CHECK_GOTO(BN_bntest_rand(n, bits, 0, 1)); + CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); + + CHECK_GOTO(BN_nnmod(a, a, n, ctx)); + CHECK_GOTO(BN_nnmod(b, b, n, ctx)); + + CHECK_GOTO(BN_to_montgomery(A, a, mont, ctx)); + CHECK_GOTO(BN_to_montgomery(B, b, mont, ctx)); + + CHECK_GOTO(BN_mod_mul_montgomery(c, A, B, mont, ctx)); + CHECK_GOTO(BN_from_montgomery(A, c, mont, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + /* n == &mont->N */ + CHECK_GOTO(BN_print(bp, n)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, A)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mod_mul(d, a, b, n, ctx)); + CHECK_GOTO(BN_sub(d, d, A)); + if (!BN_is_zero(d)) { + fprintf(stderr, "Montgomery multiplication test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + BN_MONT_CTX_free(mont); + + return ret; +} + +int +test_mod(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0)); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_bntest_rand(b, 450 + i * 10, 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + CHECK_GOTO(BN_mod(c, a, b, ctx)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_div(d, e, a, b, ctx)); + CHECK_GOTO(BN_sub(e, e, c)); + if (!BN_is_zero(e)) { + fprintf(stderr, "Modulo test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_mod_mul(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i, j; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_one(a)); + CHECK_GOTO(BN_one(b)); + BN_zero(c); + if (BN_mod_mul(e, a, b, c, ctx)) { + fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n"); + goto err; + } + ERR_clear_error(); + + for (j = 0; j < 3; j++) { + CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0)); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_bntest_rand(a, 475 + i * 10, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 425 + i * 11, 0, 0)); + BN_set_negative(a, rand_neg()); + BN_set_negative(b, rand_neg()); + if (!BN_mod_mul(e, a, b, c, ctx)) { + unsigned long l; + + while ((l = ERR_get_error())) + fprintf(stderr, "ERROR:%s\n", + ERR_error_string(l, NULL)); + exit(1); + } + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, c)); + if ((BN_is_negative(a) ^ BN_is_negative(b)) && + !BN_is_zero(e)) { + /* If (a*b) % c is negative, c must be added + * in order to obtain the normalized remainder + * (new with OpenSSL 0.9.7, previous versions of + * BN_mod_mul could generate negative results) + */ + BIO_puts(bp, " + "); + CHECK_GOTO(BN_print(bp, c)); + } + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, e)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(d, a, b, ctx)); + CHECK_GOTO(BN_sub(d, d, e)); + CHECK_GOTO(BN_div(a, b, d, c, ctx)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Modulo multiply test failed!\n"); + ERR_print_errors_fp(stderr); + goto err; + } + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_mod_exp(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_one(a)); + CHECK_GOTO(BN_one(b)); + BN_zero(c); + if (BN_mod_exp(d, a, b, c, ctx)) { + fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n"); + goto err; + } + ERR_clear_error(); + if (BN_mod_exp_ct(d, a, b, c, ctx)) { + fprintf(stderr, "BN_mod_exp_ct with zero modulus succeeded!\n"); + goto err; + } + ERR_clear_error(); + if (BN_mod_exp_nonct(d, a, b, c, ctx)) { + fprintf(stderr, "BN_mod_exp_nonct with zero modulus succeeded!\n"); + goto err; + } + ERR_clear_error(); + + CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ + for (i = 0; i < num2; i++) { + CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); + + if (!BN_mod_exp(d, a, b, c, ctx)) + goto err; + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " ^ "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_exp(e, a, b, ctx)); + CHECK_GOTO(BN_sub(e, e, d)); + CHECK_GOTO(BN_div(a, b, e, c, ctx)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + goto err; + } + } + + CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ + for (i = 0; i < num2; i++) { + CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); + + if (!BN_mod_exp_ct(d, a, b, c, ctx)) + goto err; + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " ^ "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_exp(e, a, b, ctx)); + CHECK_GOTO(BN_sub(e, e, d)); + CHECK_GOTO(BN_div(a, b, e, c, ctx)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + goto err; + } + } + + CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ + for (i = 0; i < num2; i++) { + CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); + + if (!BN_mod_exp_nonct(d, a, b, c, ctx)) + goto err; + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " ^ "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_exp(e, a, b, ctx)); + CHECK_GOTO(BN_sub(e, e, d)); + CHECK_GOTO(BN_div(a, b, e, c, ctx)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_one(a)); + CHECK_GOTO(BN_one(b)); + BN_zero(c); + if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus " + "succeeded\n"); + goto err; + } + ERR_clear_error(); + + CHECK_GOTO(BN_set_word(c, 16)); + if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) { + fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus " + "succeeded\n"); + goto err; + } + ERR_clear_error(); + + CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */ + for (i = 0; i < num2; i++) { + CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); + + if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) + goto err; + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " ^ "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " % "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_exp(e, a, b, ctx)); + CHECK_GOTO(BN_sub(e, e, d)); + CHECK_GOTO(BN_div(a, b, e, c, ctx)); + if (!BN_is_zero(b)) { + fprintf(stderr, "Modulo exponentiation test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +/* + * Test constant-time modular exponentiation with 1024-bit inputs, which on + * x86_64 cause a different code branch to be taken. + */ +int +test_mod_exp_mont5(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *p, *m, *d, *e; + BIGNUM *b, *n, *c; + BN_MONT_CTX *mont = NULL; + int len; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((p = BN_CTX_get(ctx)) == NULL) + goto err; + if ((m = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((n = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(mont = BN_MONT_CTX_new()); + + CHECK_GOTO(BN_bntest_rand(m, 1024, 0, 1)); /* must be odd for montgomery */ + /* Zero exponent */ + CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0)); + BN_zero(p); + if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) + goto err; + if (!BN_is_one(d)) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + goto err; + } + /* Regression test for carry bug in mulx4x_mont */ + len = BN_hex2bn(&a, + "7878787878787878787878787878787878787878787878787878787878787878" + "7878787878787878787878787878787878787878787878787878787878787878" + "7878787878787878787878787878787878787878787878787878787878787878" + "7878787878787878787878787878787878787878787878787878787878787878"); + CHECK_GOTO(len); + len = BN_hex2bn(&b, + "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744" + "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593" + "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03" + "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81"); + CHECK_GOTO(len); + len = BN_hex2bn(&n, + "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B" + "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5" + "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4" + "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF"); + CHECK_GOTO(len); + CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); + CHECK_GOTO(BN_mod_mul_montgomery(c, a, b, mont, ctx)); + CHECK_GOTO(BN_mod_mul_montgomery(d, b, a, mont, ctx)); + if (BN_cmp(c, d)) { + fprintf(stderr, "Montgomery multiplication test failed:" + " a*b != b*a.\n"); + goto err; + } + /* Regression test for carry bug in sqr[x]8x_mont */ + len = BN_hex2bn(&n, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF00" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF"); + CHECK_GOTO(len); + len = BN_hex2bn(&a, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF0000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000FFFFFFFFFFFFFF00000000"); + CHECK_GOTO(len); + CHECK_GOTO(bn_copy(b, a)); + CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx)); + CHECK_GOTO(BN_mod_mul_montgomery(c, a, a, mont, ctx)); + CHECK_GOTO(BN_mod_mul_montgomery(d, a, b, mont, ctx)); + if (BN_cmp(c, d)) { + fprintf(stderr, "Montgomery multiplication test failed:" + " a**2 != a*a.\n"); + goto err; + } + /* Zero input */ + CHECK_GOTO(BN_bntest_rand(p, 1024, 0, 0)); + BN_zero(a); + if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) + goto err; + if (!BN_is_zero(d)) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + goto err; + } + /* + * Craft an input whose Montgomery representation is 1, i.e., shorter + * than the modulus m, in order to test the const time precomputation + * scattering/gathering. + */ + CHECK_GOTO(BN_one(a)); + CHECK_GOTO(BN_MONT_CTX_set(mont, m, ctx)); + if (!BN_from_montgomery(e, a, mont, ctx)) + goto err; + if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) + goto err; + if (!BN_mod_exp_simple(a, e, p, m, ctx)) + goto err; + if (BN_cmp(a, d) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + goto err; + } + /* Finally, some regular test vectors. */ + CHECK_GOTO(BN_bntest_rand(e, 1024, 0, 0)); + if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) + goto err; + if (!BN_mod_exp_simple(a, e, p, m, ctx)) + goto err; + if (BN_cmp(a, d) != 0) { + fprintf(stderr, "Modular exponentiation test failed!\n"); + goto err; + } + + ret = 1; + err: + BN_CTX_end(ctx); + BN_MONT_CTX_free(mont); + + return ret; +} + +int +test_exp(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + + for (i = 0; i < num2; i++) { + CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0)); + CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0)); + + if (BN_exp(d, a, b, ctx) <= 0) + goto err; + + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " ^ "); + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, d)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_one(e)); + for (; !BN_is_zero(b); BN_sub_word(b, 1)) + CHECK_GOTO(BN_mul(e, e, a, ctx)); + CHECK_GOTO(BN_sub(e, e, d)); + if (!BN_is_zero(e)) { + fprintf(stderr, "Exponentiation test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +static int +genprime_cb(int p, int n, BN_GENCB *arg) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + putc(c, stderr); + return 1; +} + +int +test_kron(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *r, *t; + BN_GENCB *cb = NULL; + int i; + int legendre, kronecker; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((r = BN_CTX_get(ctx)) == NULL) + goto err; + if ((t = BN_CTX_get(ctx)) == NULL) + goto err; + + if ((cb = BN_GENCB_new()) == NULL) + goto err; + + BN_GENCB_set(cb, genprime_cb, NULL); + + /* + * We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). In + * this case we know that if b is prime, then BN_kronecker(a, b, ctx) is + * congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). So we + * generate a random prime b and compare these values for a number of + * random a's. (That is, we run the Solovay-Strassen primality test to + * confirm that b is prime, except that we don't want to test whether b + * is prime but whether BN_kronecker works.) + */ + + if (!BN_generate_prime_ex(b, 512, 0, NULL, NULL, cb)) + goto err; + BN_set_negative(b, rand_neg()); + putc('\n', stderr); + + for (i = 0; i < num0; i++) { + if (!BN_bntest_rand(a, 512, 0, 0)) + goto err; + BN_set_negative(a, rand_neg()); + + /* t := (|b|-1)/2 (note that b is odd) */ + if (!bn_copy(t, b)) + goto err; + BN_set_negative(t, 0); + if (!BN_sub_word(t, 1)) + goto err; + if (!BN_rshift1(t, t)) + goto err; + /* r := a^t mod b */ + BN_set_negative(b, 0); + + if (!BN_mod_exp_recp(r, a, t, b, ctx)) + goto err; + BN_set_negative(b, 1); + + if (BN_is_word(r, 1)) + legendre = 1; + else if (BN_is_zero(r)) + legendre = 0; + else { + if (!BN_add_word(r, 1)) + goto err; + if (0 != BN_ucmp(r, b)) { + fprintf(stderr, "Legendre symbol computation failed\n"); + goto err; + } + legendre = -1; + } + + kronecker = BN_kronecker(a, b, ctx); + if (kronecker < -1) + goto err; + /* we actually need BN_kronecker(a, |b|) */ + if (BN_is_negative(a) && BN_is_negative(b)) + kronecker = -kronecker; + + if (legendre != kronecker) { + fprintf(stderr, "legendre != kronecker; a = "); + CHECK_GOTO(BN_print_fp(stderr, a)); + fprintf(stderr, ", b = "); + CHECK_GOTO(BN_print_fp(stderr, b)); + fprintf(stderr, "\n"); + goto err; + } + + putc('.', stderr); + } + + putc('\n', stderr); + + ret = 1; + err: + BN_GENCB_free(cb); + BN_CTX_end(ctx); + + return ret; +} + +int +test_sqrt(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *p, *r; + BN_GENCB *cb = NULL; + int i, j; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((p = BN_CTX_get(ctx)) == NULL) + goto err; + if ((r = BN_CTX_get(ctx)) == NULL) + goto err; + + if ((cb = BN_GENCB_new()) == NULL) + goto err; + + BN_GENCB_set(cb, genprime_cb, NULL); + + for (i = 0; i < 16; i++) { + if (i < 8) { + unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 }; + + if (!BN_set_word(p, primes[i])) + goto err; + } else { + if (!BN_set_word(a, 32)) + goto err; + if (!BN_set_word(r, 2 * i + 1)) + goto err; + + if (!BN_generate_prime_ex(p, 256, 0, a, r, cb)) + goto err; + putc('\n', stderr); + } + BN_set_negative(p, rand_neg()); + + for (j = 0; j < num2; j++) { + /* + * construct 'a' such that it is a square modulo p, but in + * general not a proper square and not reduced modulo p + */ + if (!BN_bntest_rand(r, 256, 0, 3)) + goto err; + if (!BN_nnmod(r, r, p, ctx)) + goto err; + if (!BN_mod_sqr(r, r, p, ctx)) + goto err; + if (!BN_bntest_rand(a, 256, 0, 3)) + goto err; + if (!BN_nnmod(a, a, p, ctx)) + goto err; + if (!BN_mod_sqr(a, a, p, ctx)) + goto err; + if (!BN_mul(a, a, r, ctx)) + goto err; + if (rand_neg()) + if (!BN_sub(a, a, p)) + goto err; + + if (!BN_mod_sqrt(r, a, p, ctx)) + goto err; + if (!BN_mod_sqr(r, r, p, ctx)) + goto err; + + if (!BN_nnmod(a, a, p, ctx)) + goto err; + + if (BN_cmp(a, r) != 0) { + fprintf(stderr, "BN_mod_sqrt failed: a = "); + CHECK_GOTO(BN_print_fp(stderr, a)); + fprintf(stderr, ", r = "); + CHECK_GOTO(BN_print_fp(stderr, r)); + fprintf(stderr, ", p = "); + CHECK_GOTO(BN_print_fp(stderr, p)); + fprintf(stderr, "\n"); + goto err; + } + + putc('.', stderr); + } + + putc('\n', stderr); + } + + ret = 1; + err: + BN_GENCB_free(cb); + BN_CTX_end(ctx); + + return ret; +} + +int +test_lshift(BIO *bp, BN_CTX *ctx, int use_lst) +{ + BIGNUM *a, *b, *c, *d; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + CHECK_GOTO(BN_one(c)); + + if (use_lst) { + if (!BN_hex2bn(&a, "C64F43042AEACA6E5836805BE8C99B04" + "5D4836C2FD16C964F0")) + goto err; + } else { + CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); + BN_set_negative(a, rand_neg()); + } + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_lshift(b, a, i + 1)); + CHECK_GOTO(BN_add(c, c, c)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_mul(d, a, c, ctx)); + CHECK_GOTO(BN_sub(d, d, b)); + if (!BN_is_zero(d)) { + fprintf(stderr, "Left shift test failed!\n"); + fprintf(stderr, "a="); + CHECK_GOTO(BN_print_fp(stderr, a)); + fprintf(stderr, "\nb="); + CHECK_GOTO(BN_print_fp(stderr, b)); + fprintf(stderr, "\nc="); + CHECK_GOTO(BN_print_fp(stderr, c)); + fprintf(stderr, "\nd="); + CHECK_GOTO(BN_print_fp(stderr, d)); + fprintf(stderr, "\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_lshift1(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); + BN_set_negative(a, rand_neg()); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_lshift1(b, a)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " * 2"); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_add(c, a, a)); + CHECK_GOTO(BN_sub(a, b, c)); + if (!BN_is_zero(a)) { + fprintf(stderr, "Left shift one test failed!\n"); + goto err; + } + + CHECK_GOTO(bn_copy(a, b)); + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_rshift(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c, *d, *e; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + if ((d = BN_CTX_get(ctx)) == NULL) + goto err; + if ((e = BN_CTX_get(ctx)) == NULL) + goto err; + CHECK_GOTO(BN_one(c)); + + CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); + BN_set_negative(a, rand_neg()); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_rshift(b, a, i + 1)); + CHECK_GOTO(BN_add(c, c, c)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " / "); + CHECK_GOTO(BN_print(bp, c)); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_div(d, e, a, c, ctx)); + CHECK_GOTO(BN_sub(d, d, b)); + if (!BN_is_zero(d)) { + fprintf(stderr, "Right shift test failed!\n"); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +test_rshift1(BIO *bp, BN_CTX *ctx) +{ + BIGNUM *a, *b, *c; + int i; + int ret = 0; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + goto err; + if ((b = BN_CTX_get(ctx)) == NULL) + goto err; + if ((c = BN_CTX_get(ctx)) == NULL) + goto err; + + CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0)); + BN_set_negative(a, rand_neg()); + for (i = 0; i < num0; i++) { + CHECK_GOTO(BN_rshift1(b, a)); + if (bp != NULL) { + if (!results) { + CHECK_GOTO(BN_print(bp, a)); + BIO_puts(bp, " / 2"); + BIO_puts(bp, " - "); + } + CHECK_GOTO(BN_print(bp, b)); + BIO_puts(bp, "\n"); + } + CHECK_GOTO(BN_sub(c, a, b)); + CHECK_GOTO(BN_sub(c, c, b)); + if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) { + fprintf(stderr, "Right shift one test failed!\n"); + goto err; + } + CHECK_GOTO(bn_copy(a, b)); + } + + ret = 1; + err: + BN_CTX_end(ctx); + + return ret; +} + +int +rand_neg(void) +{ + static unsigned int neg = 0; + static int sign[8] = { 0, 0, 0, 1, 1, 0, 1, 1 }; + + return sign[neg++ % 8]; +} + +int +test_mod_exp_sizes(BIO *bp, BN_CTX *ctx) +{ + BN_MONT_CTX *mont_ctx = NULL; + BIGNUM *p, *x, *y, *r, *r2; + int size; + int ret = 0; + + BN_CTX_start(ctx); + CHECK_GOTO(p = BN_CTX_get(ctx)); + CHECK_GOTO(x = BN_CTX_get(ctx)); + CHECK_GOTO(y = BN_CTX_get(ctx)); + CHECK_GOTO(r = BN_CTX_get(ctx)); + CHECK_GOTO(r2 = BN_CTX_get(ctx)); + mont_ctx = BN_MONT_CTX_new(); + + if (r2 == NULL || mont_ctx == NULL) + goto err; + + if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) || + !BN_MONT_CTX_set(mont_ctx, p, ctx)) + goto err; + + for (size = 32; size < 1024; size += 8) { + if (!BN_rand(x, size, -1, 0) || + !BN_rand(y, size, -1, 0) || + !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) || + !BN_mod_exp(r2, x, y, p, ctx)) + goto err; + + if (BN_cmp(r, r2) != 0) { + char *r_str = NULL; + char *r2_str = NULL; + CHECK_GOTO(r_str = BN_bn2hex(r)); + CHECK_GOTO(r2_str = BN_bn2hex(r2)); + + printf("Incorrect answer at size %d: %s vs %s\n", + size, r_str, r2_str); + free(r_str); + free(r2_str); + goto err; + } + } + + ret = 1; + err: + BN_CTX_end(ctx); + BN_MONT_CTX_free(mont_ctx); + + return ret; +} diff --git a/tests/bn_to_string.c b/tests/bn_to_string.c new file mode 100644 index 0000000..93945b8 --- /dev/null +++ b/tests/bn_to_string.c @@ -0,0 +1,252 @@ +/* $OpenBSD: bn_to_string.c,v 1.5 2023/04/10 21:00:16 tb Exp $ */ +/* + * Copyright (c) 2019 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +struct bn_to_string_tests { + const char *input; + const char *want; +} testcases[] = { + { + .input = "0x0", + .want = "0", + }, + { + .input = "-0x0", + .want = "0", + }, + { + .input = "0x7", + .want = "7", + }, + { + .input = "-0x7", + .want = "-7", + }, + { + .input = "0x8", + .want = "8", + }, + { + .input = "-0x8", + .want = "-8", + }, + { + .input = "0xF", + .want = "15", + }, + { + .input = "-0xF", + .want = "-15", + }, + { + .input = "0x10", + .want = "16", + }, + { + .input = "-0x10", + .want = "-16", + }, + { + .input = "0x7F", + .want = "127", + }, + { + .input = "-0x7F", + .want = "-127", + }, + { + .input = "0x80", + .want = "128", + }, + { + .input = "-0x80", + .want = "-128", + }, + { + .input = "0xFF", + .want = "255", + }, + { + .input = "-0xFF", + .want = "-255", + }, + { + .input = "0x100", + .want = "256", + }, + { + .input = "0x7FFF", + .want = "32767", + }, + { + .input = "-0x7FFF", + .want = "-32767", + }, + { + .input = "0x8000", + .want = "32768", + }, + { + .input = "-0x8000", + .want = "-32768", + }, + { + .input = "0xFFFF", + .want = "65535", + }, + { + .input = "-0xFFFF", + .want = "-65535", + }, + { + .input = "0x10000", + .want = "65536", + }, + { + .input = "-0x10000", + .want = "-65536", + }, + { + .input = "0x7FFFFFFF", + .want = "2147483647", + }, + { + .input = "-0x7FFFFFFF", + .want = "-2147483647", + }, + { + .input = "0x80000000", + .want = "2147483648", + }, + { + .input = "-0x80000000", + .want = "-2147483648", + }, + { + .input = "0xFFFFFFFF", + .want = "4294967295", + }, + { + .input = "-0xFFFFFFFF", + .want = "-4294967295", + }, + { + .input = "0x100000000", + .want = "4294967296", + }, + { + .input = "-0x100000000", + .want = "-4294967296", + }, + { + .input = "0x7FFFFFFFFFFFFFFF", + .want = "9223372036854775807", + }, + { + .input = "-0x7FFFFFFFFFFFFFFF", + .want = "-9223372036854775807", + }, + { + .input = "0x8000000000000000", + .want = "9223372036854775808", + }, + { + .input = "-0x8000000000000000", + .want = "-9223372036854775808", + }, + { + .input = "0xFFFFFFFFFFFFFFFF", + .want = "18446744073709551615", + }, + { + .input = "-0xFFFFFFFFFFFFFFFF", + .want = "-18446744073709551615", + }, + { + .input = "0x10000000000000000", + .want = "18446744073709551616", + }, + { + .input = "-0x10000000000000000", + .want = "-18446744073709551616", + }, + { + .input = "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + .want = "170141183460469231731687303715884105727", + }, + { + .input = "-0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + .want = "-170141183460469231731687303715884105727", + }, + { + .input = "0x80000000000000000000000000000000", + .want = "0x80000000000000000000000000000000", + }, + { + .input = "-0x80000000000000000000000000000000", + .want = "-0x80000000000000000000000000000000", + }, + { + .input = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + .want = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + }, + { + .input = "-0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + .want = "-0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + }, + { + .input = "0x100000000000000000000000000000000", + .want = "0x0100000000000000000000000000000000", + }, + { + .input = "-0x100000000000000000000000000000000", + .want = "-0x0100000000000000000000000000000000", + }, + { + .input = NULL, + }, +}; + +int +main(void) +{ + struct bn_to_string_tests *test; + ASN1_INTEGER *aint; + char *got; + int failed = 0; + + for (test = testcases; test->input != NULL; test++) { + if ((aint = s2i_ASN1_INTEGER(NULL, test->input)) == NULL) + errx(1, "s2i_ASN1_INTEGER(%s)", test->input); + if ((got = i2s_ASN1_INTEGER(NULL, aint)) == NULL) + errx(1, "i2s_ASN1_INTEGER(%s)", test->input); + if (strcmp(got, test->want) != 0) { + warnx("want: %s, got: %s", test->want, got); + failed |= 1; + } + ASN1_INTEGER_free(aint); + free(got); + } + + return failed; +} diff --git a/tests/bn_unit.c b/tests/bn_unit.c new file mode 100644 index 0000000..3a88bfc --- /dev/null +++ b/tests/bn_unit.c @@ -0,0 +1,307 @@ +/* $OpenBSD: bn_unit.c,v 1.7 2023/06/21 07:15:38 jsing Exp $ */ + +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include + +static int +test_bn_print_wrapper(char *a, size_t size, const char *descr, + int (*to_bn)(BIGNUM **, const char *)) +{ + int ret; + + ret = to_bn(NULL, a); + if (ret != 0 && (ret < 0 || (size_t)ret != size - 1)) { + fprintf(stderr, "unexpected %s() return" + "want 0 or %zu, got %d\n", descr, size - 1, ret); + return 1; + } + + return 0; +} + +static int +test_bn_print_null_derefs(void) +{ + size_t size = INT_MAX / 4 + 4; + size_t datalimit = (size + 500 * 1024) / 1024; + char *a; + char digit; + int failed = 0; + + if ((a = malloc(size)) == NULL) { + warn("malloc(%zu) failed (make sure data limit is >= %zu KiB)", + size, datalimit); + return 0; + } + + /* Fill with a random digit since coverity doesn't like us using '0'. */ + digit = '0' + arc4random_uniform(10); + + memset(a, digit, size - 1); + a[size - 1] = '\0'; + + failed |= test_bn_print_wrapper(a, size, "BN_dec2bn", BN_dec2bn); + failed |= test_bn_print_wrapper(a, size, "BN_hex2bn", BN_hex2bn); + + free(a); + + return failed; +} + +static int +test_bn_num_bits(void) +{ + BIGNUM *bn; + int i, num_bits; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new"); + + if ((num_bits = BN_num_bits(bn)) != 0) { + warnx("BN_num_bits(0): got %d, want 0", num_bits); + failed |= 1; + } + + if (!BN_set_word(bn, 1)) + errx(1, "BN_set_word"); + + for (i = 0; i <= 5 * BN_BITS2; i++) { + if ((num_bits = BN_num_bits(bn)) != i + 1) { + warnx("BN_num_bits(1 << %d): got %d, want %d", + i, num_bits, i + 1); + failed |= 1; + } + if (!BN_lshift1(bn, bn)) + errx(1, "BN_lshift1"); + } + + if (BN_hex2bn(&bn, "0000000000000000010000000000000000") != 34) + errx(1, "BN_hex2bn"); + + if ((num_bits = BN_num_bits(bn)) != 65) { + warnx("BN_num_bits(1 << 64) padded: got %d, want %d", + num_bits, 65); + failed |= 1; + } + + BN_free(bn); + + return failed; +} + +static int +test_bn_num_bits_word(void) +{ + BN_ULONG w = 1; + int i, num_bits; + int failed = 0; + + if ((num_bits = BN_num_bits_word(0)) != 0) { + warnx("BN_num_bits_word(0): want 0, got %d", num_bits); + failed |= 1; + } + + for (i = 0; i < BN_BITS2; i++) { + if ((num_bits = BN_num_bits_word(w << i)) != i + 1) { + warnx("BN_num_bits_word(0x%llx): want %d, got %d", + (unsigned long long)(w << i), i + 1, num_bits); + failed |= 1; + } + } + + return failed; +} + +#define BN_FLG_ALL_KNOWN \ + (BN_FLG_STATIC_DATA | BN_FLG_CONSTTIME | BN_FLG_MALLOCED) + +static int +bn_check_expected_flags(const BIGNUM *bn, int expected, const char *fn, + const char *descr) +{ + int flags, got; + int ret = 1; + + flags = BN_get_flags(bn, BN_FLG_ALL_KNOWN); + + if ((got = flags & expected) != expected) { + fprintf(stderr, "%s: %s: expected flags: want %x, got %x\n", + fn, descr, expected, got); + ret = 0; + } + + if ((got = flags & ~expected) != 0) { + fprintf(stderr, "%s: %s: unexpected flags: want %x, got %x\n", + fn, descr, 0, got); + ret = 0; + } + + return ret; +} + +static int +test_bn_copy_copies_flags(void) +{ + BIGNUM *dst, *src; + int failed = 0; + + if ((dst = BN_new()) == NULL) + errx(1, "%s: src = BN_new()", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED, + __func__, "dst after BN_new")) + failed |= 1; + + if (BN_copy(dst, BN_value_one()) == NULL) + errx(1, "%s: bn_copy()", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED, + __func__, "dst after bn_copy")) + failed |= 1; + + if ((src = BN_new()) == NULL) + errx(1, "%s: src = BN_new()", __func__); + + BN_set_flags(src, BN_FLG_CONSTTIME); + + if (!bn_check_expected_flags(src, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "src after BN_set_flags")) + failed |= 1; + + if (!BN_set_word(src, 57)) + errx(1, "%s: BN_set_word(src, 57)", __func__); + + if (BN_copy(dst, src) == NULL) + errx(1, "%s: BN_copy(dst, src)", __func__); + + if (BN_cmp(src, dst) != 0) { + fprintf(stderr, "copy not equal to original\n"); + failed |= 1; + } + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "dst after BN_copy(dst, src)")) + failed |= 1; + + BN_free(dst); + BN_free(src); + + return failed; +} + +static int +test_bn_copy_consttime_is_sticky(void) +{ + BIGNUM *src, *dst; + int failed = 0; + + if ((src = BN_new()) == NULL) + errx(1, "%s: src = BN_new()", __func__); + + if (!bn_check_expected_flags(src, BN_FLG_MALLOCED, + __func__, "src after BN_new")) + failed |= 1; + + if ((dst = BN_new()) == NULL) + errx(1, "%s: dst = BN_new()", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED, + __func__, "dst after BN_new")) + failed |= 1; + + BN_set_flags(dst, BN_FLG_CONSTTIME); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "src after BN_new")) + failed |= 1; + + if (BN_copy(dst, BN_value_one()) == NULL) + errx(1, "%s: bn_copy()", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "dst after bn_copy")) + failed |= 1; + + BN_free(dst); + BN_free(src); + + return failed; +} + +static int +test_bn_dup_consttime_is_sticky(void) +{ + BIGNUM *src, *dst; + int failed = 0; + + if (!bn_check_expected_flags(BN_value_one(), BN_FLG_STATIC_DATA, + __func__, "flags on BN_value_one()")) + failed |= 1; + + if ((dst = BN_dup(BN_value_one())) == NULL) + errx(1, "%s: dst = BN_dup(BN_value_one())", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED, + __func__, "dst after BN_dup(BN_value_one())")) + failed |= 1; + + BN_free(dst); + + if ((src = BN_new()) == NULL) + errx(1, "%s: src = BN_new()", __func__); + + BN_set_flags(src, BN_FLG_CONSTTIME); + + if (!bn_check_expected_flags(src, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "src after BN_new")) + failed |= 1; + + if ((dst = BN_dup(src)) == NULL) + errx(1, "%s: dst = BN_dup(src)", __func__); + + if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME, + __func__, "dst after bn_copy")) + failed |= 1; + + BN_free(dst); + BN_free(src); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_bn_print_null_derefs(); + failed |= test_bn_num_bits(); + failed |= test_bn_num_bits_word(); + failed |= test_bn_copy_copies_flags(); + failed |= test_bn_copy_consttime_is_sticky(); + failed |= test_bn_dup_consttime_is_sticky(); + + return failed; +} diff --git a/tests/bn_word.c b/tests/bn_word.c new file mode 100644 index 0000000..0a543ad --- /dev/null +++ b/tests/bn_word.c @@ -0,0 +1,617 @@ +/* $OpenBSD: bn_word.c,v 1.1 2023/03/11 14:04:21 jsing Exp $ */ +/* + * Copyright (c) 2023 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +struct bn_word_test { + const char *in_hex; + BN_ULONG in_word; + BN_ULONG mod_word; + BN_ULONG out_word; + const char *out_hex; + int out_is_negative; +}; + +static int +check_bn_word_test(const char *op_name, const BIGNUM *bn, + const struct bn_word_test *bwt) +{ + char *out_hex = NULL; + BN_ULONG out_word; + int failed = 1; + + if ((out_word = BN_get_word(bn)) != bwt->out_word) { + fprintf(stderr, "FAIL %s: Got word %lx, want %lx\n", + op_name, (unsigned long)out_word, + (unsigned long)bwt->out_word); + goto failure; + } + + if (BN_is_negative(bn) != bwt->out_is_negative) { + fprintf(stderr, "FAIL %s: Got is negative %d, want %d\n", + op_name, BN_is_negative(bn), bwt->out_is_negative); + goto failure; + } + + if ((out_hex = BN_bn2hex(bn)) == NULL) + errx(1, "BN_bn2hex() failed\n"); + + if (strcmp(out_hex, bwt->out_hex) != 0) { + fprintf(stderr, "FAIL %s: Got hex %s, want %s\n", + op_name, out_hex, bwt->out_hex); + goto failure; + } + + if (BN_is_zero(bn) && BN_is_negative(bn) != 0) { + fprintf(stderr, "FAIL %s: Got negative zero\n", op_name); + goto failure; + } + + failed = 0; + + failure: + free(out_hex); + + return failed; +} + +static int +test_bn_word(int (*bn_word_op)(BIGNUM *, BN_ULONG), const char *op_name, + const struct bn_word_test *bwts, size_t num_tests) +{ + const struct bn_word_test *bwt; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < num_tests; i++) { + bwt = &bwts[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if (!bn_word_op(bn, bwt->in_word)) { + fprintf(stderr, "FAIL: %s(%lx) failed\n", op_name, + (unsigned long)bwt->in_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +static const struct bn_word_test bn_add_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "-1", + .in_word = 2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xfffffffeUL, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .out_word = BN_MASK2, + .out_hex = "010000000000000000", + }, +}; + +#define N_BN_ADD_WORD_TESTS \ + (sizeof(bn_add_word_tests) / sizeof(bn_add_word_tests[0])) + +static int +test_bn_add_word(void) +{ + return test_bn_word(BN_add_word, "BN_add_word", bn_add_word_tests, + N_BN_ADD_WORD_TESTS); +} + +static const struct bn_word_test bn_sub_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "2", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 2, + .out_word = 3, + .out_hex = "-03", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "3", + .in_word = 2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 5, + .out_hex = "-05", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 0xfffffffeUL, + .out_word = 0xffffffffUL, + .out_hex = "-FFFFFFFF", + .out_is_negative = 1, + }, + { + .in_hex = "010000000000000000", + .in_word = 1, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, +}; + +#define N_BN_SUB_WORD_TESTS \ + (sizeof(bn_sub_word_tests) / sizeof(bn_sub_word_tests[0])) + +static int +test_bn_sub_word(void) +{ + return test_bn_word(BN_sub_word, "BN_sub_word", bn_sub_word_tests, + N_BN_SUB_WORD_TESTS); +} + +static const struct bn_word_test bn_mul_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-1", + .in_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 6, + .out_hex = "-06", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xfffffffeUL, + .out_word = 0xfffffffeUL, + .out_hex = "FFFFFFFE", + }, + { + .in_hex = "010000000000000000", + .in_word = 2, + .out_word = BN_MASK2, + .out_hex = "020000000000000000", + }, +}; + +#define N_BN_MUL_WORD_TESTS \ + (sizeof(bn_mul_word_tests) / sizeof(bn_mul_word_tests[0])) + +static int +test_bn_mul_word(void) +{ + return test_bn_word(BN_mul_word, "BN_mul_word", bn_mul_word_tests, + N_BN_MUL_WORD_TESTS); +} + +static const struct bn_word_test bn_div_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .mod_word = BN_MASK2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .mod_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "4", + .in_word = 2, + .mod_word = 0, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "7", + .in_word = 3, + .mod_word = 1, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "1", + .in_word = 1, + .mod_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-2", + .in_word = 1, + .mod_word = 0, + .out_word = 2, + .out_hex = "-02", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 2, + .mod_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-3", + .in_word = 2, + .mod_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xffffffffUL, + .mod_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFE", + .in_word = 0xffffffffUL, + .mod_word = 0xfffffffeUL, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0xff, + .mod_word = 0, + .out_word = 0x1010101UL, + .out_hex = "01010101", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0x10, + .mod_word = 0xf, + .out_word = 0xfffffffUL, + .out_hex = "0FFFFFFF", + }, +}; + +#define N_BN_DIV_WORD_TESTS \ + (sizeof(bn_div_word_tests) / sizeof(bn_div_word_tests[0])) + +static int +test_bn_div_word(void) +{ + const char *op_name = "BN_div_word"; + const struct bn_word_test *bwt; + BN_ULONG mod_word; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < N_BN_DIV_WORD_TESTS; i++) { + bwt = &bn_div_word_tests[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if ((mod_word = BN_div_word(bn, bwt->in_word)) != bwt->mod_word) { + fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n", + op_name, (unsigned long)mod_word, + (unsigned long)bwt->mod_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +static const struct bn_word_test bn_mod_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .mod_word = BN_MASK2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .mod_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "4", + .in_word = 2, + .mod_word = 0, + .out_word = 4, + .out_hex = "04", + }, + { + .in_hex = "7", + .in_word = 3, + .mod_word = 1, + .out_word = 7, + .out_hex = "07", + }, + { + .in_hex = "1", + .in_word = 1, + .mod_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-2", + .in_word = 1, + .mod_word = 0, + .out_word = 2, + .out_hex = "-02", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 2, + .mod_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "-3", + .in_word = 2, + .mod_word = 1, + .out_word = 3, + .out_hex = "-03", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xffffffffUL, + .mod_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFE", + .in_word = 0xffffffffUL, + .mod_word = 0xfffffffeUL, + .out_word = 0xfffffffeUL, + .out_hex = "FFFFFFFE", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0xff, + .mod_word = 0, + .out_word = 0xffffffff, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0x10, + .mod_word = 0xf, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, +}; + +#define N_BN_MOD_WORD_TESTS \ + (sizeof(bn_mod_word_tests) / sizeof(bn_mod_word_tests[0])) + +static int +test_bn_mod_word(void) +{ + const char *op_name = "BN_mod_word"; + const struct bn_word_test *bwt; + BN_ULONG mod_word; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < N_BN_MOD_WORD_TESTS; i++) { + bwt = &bn_mod_word_tests[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if ((mod_word = BN_mod_word(bn, bwt->in_word)) != bwt->mod_word) { + fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n", + op_name, (unsigned long)mod_word, + (unsigned long)bwt->mod_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_bn_add_word(); + failed |= test_bn_sub_word(); + failed |= test_bn_mul_word(); + failed |= test_bn_div_word(); + failed |= test_bn_mod_word(); + + return failed; +} diff --git a/tests/buffertest.c b/tests/buffertest.c new file mode 100644 index 0000000..3dfad7c --- /dev/null +++ b/tests/buffertest.c @@ -0,0 +1,364 @@ +/* $OpenBSD: buffertest.c,v 1.6 2022/07/22 19:34:55 jsing Exp $ */ +/* + * Copyright (c) 2019, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include "tls_internal.h" + +uint8_t testdata[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, +}; + +struct read_state { + uint8_t *buf; + size_t len; + size_t offset; +}; + +static ssize_t +read_cb(void *buf, size_t buflen, void *cb_arg) +{ + struct read_state *rs = cb_arg; + ssize_t n; + + if (rs->offset > rs->len) + return TLS_IO_EOF; + + if ((size_t)(n = buflen) > (rs->len - rs->offset)) + n = rs->len - rs->offset; + + if (n == 0) + return TLS_IO_WANT_POLLIN; + + memcpy(buf, &rs->buf[rs->offset], n); + rs->offset += n; + + return n; +} + +struct extend_test { + size_t extend_len; + size_t read_len; + ssize_t want_ret; +}; + +const struct extend_test extend_tests[] = { + { + .extend_len = 4, + .read_len = 0, + .want_ret = TLS_IO_WANT_POLLIN, + }, + { + .extend_len = 4, + .read_len = 8, + .want_ret = 4, + }, + { + .extend_len = 12, + .read_len = 8, + .want_ret = TLS_IO_WANT_POLLIN, + }, + { + .extend_len = 12, + .read_len = 10, + .want_ret = TLS_IO_WANT_POLLIN, + }, + { + .extend_len = 12, + .read_len = 12, + .want_ret = 12, + }, + { + .extend_len = 16, + .read_len = 16, + .want_ret = 16, + }, + { + .extend_len = 20, + .read_len = 1, + .want_ret = TLS_IO_EOF, + }, +}; + +#define N_EXTEND_TESTS (sizeof(extend_tests) / sizeof(extend_tests[0])) + +static int +tls_buffer_extend_test(void) +{ + const struct extend_test *et; + struct tls_buffer *buf; + struct read_state rs; + uint8_t *data = NULL; + size_t i, data_len; + ssize_t ret; + CBS cbs; + int failed = 1; + + rs.buf = testdata; + rs.offset = 0; + + if ((buf = tls_buffer_new(0)) == NULL) + errx(1, "tls_buffer_new"); + + for (i = 0; i < N_EXTEND_TESTS; i++) { + et = &extend_tests[i]; + rs.len = et->read_len; + + ret = tls_buffer_extend(buf, et->extend_len, read_cb, &rs); + if (ret != extend_tests[i].want_ret) { + fprintf(stderr, "FAIL: Test %zd - extend returned %zd, " + "want %zd\n", i, ret, et->want_ret); + goto failed; + } + + if (!tls_buffer_data(buf, &cbs)) { + fprintf(stderr, "FAIL: Test %zd - failed to get data\n", + i); + goto failed; + } + + if (!CBS_mem_equal(&cbs, testdata, CBS_len(&cbs))) { + fprintf(stderr, "FAIL: Test %zd - extend buffer " + "mismatch", i); + goto failed; + } + } + + if (!tls_buffer_finish(buf, &data, &data_len)) { + fprintf(stderr, "FAIL: failed to finish\n"); + goto failed; + } + + tls_buffer_free(buf); + buf = NULL; + + if (data_len != sizeof(testdata)) { + fprintf(stderr, "FAIL: got data length %zu, want %zu\n", + data_len, sizeof(testdata)); + goto failed; + } + if (memcmp(data, testdata, data_len) != 0) { + fprintf(stderr, "FAIL: data mismatch\n"); + goto failed; + } + + failed = 0; + + failed: + tls_buffer_free(buf); + free(data); + + return failed; +} + +struct read_write_test { + uint8_t pattern; + size_t read; + size_t write; + size_t append; + ssize_t want; +}; + +const struct read_write_test read_write_tests[] = { + { + .read = 2048, + .want = TLS_IO_WANT_POLLIN, + }, + { + .pattern = 0xdb, + .write = 2048, + .want = 2048, + }, + { + .pattern = 0xbd, + .append = 2048, + .want = 1, + }, + { + .pattern = 0xdb, + .read = 2048, + .want = 2048, + }, + { + .pattern = 0xfe, + .append = 1024, + .want = 1, + }, + { + .pattern = 0xbd, + .read = 1000, + .want = 1000, + }, + { + .pattern = 0xbd, + .read = 1048, + .want = 1048, + }, + { + .pattern = 0xdb, + .write = 2048, + .want = 2048, + }, + { + .pattern = 0xbd, + .append = 1024, + .want = 1, + }, + { + .pattern = 0xee, + .append = 4096, + .want = 1, + }, + { + .pattern = 0xfe, + .append = 1, + .want = 0, + }, + { + .pattern = 0xfe, + .write = 1, + .want = TLS_IO_FAILURE, + }, + { + .pattern = 0xfe, + .read = 1024, + .want = 1024, + }, + { + .pattern = 0xdb, + .read = 2048, + .want = 2048, + }, + { + .pattern = 0xbd, + .read = 1024, + .want = 1024, + }, + { + .pattern = 0xee, + .read = 1024, + .want = 1024, + }, + { + .pattern = 0xee, + .read = 4096, + .want = 3072, + }, + { + .read = 2048, + .want = TLS_IO_WANT_POLLIN, + }, +}; + +#define N_READ_WRITE_TESTS (sizeof(read_write_tests) / sizeof(read_write_tests[0])) + +static int +tls_buffer_read_write_test(void) +{ + const struct read_write_test *rwt; + struct tls_buffer *buf = NULL; + uint8_t *rbuf = NULL, *wbuf = NULL; + ssize_t n; + size_t i; + int ret; + int failed = 1; + + if ((buf = tls_buffer_new(0)) == NULL) + errx(1, "tls_buffer_new"); + + tls_buffer_set_capacity_limit(buf, 8192); + + for (i = 0; i < N_READ_WRITE_TESTS; i++) { + rwt = &read_write_tests[i]; + + if (rwt->append > 0) { + free(wbuf); + if ((wbuf = malloc(rwt->append)) == NULL) + errx(1, "malloc"); + memset(wbuf, rwt->pattern, rwt->append); + if ((ret = tls_buffer_append(buf, wbuf, rwt->append)) != + rwt->want) { + fprintf(stderr, "FAIL: test %zu - " + "tls_buffer_append() = %d, want %zu\n", + i, ret, rwt->want); + goto failed; + } + } + + if (rwt->write > 0) { + free(wbuf); + if ((wbuf = malloc(rwt->write)) == NULL) + errx(1, "malloc"); + memset(wbuf, rwt->pattern, rwt->write); + if ((n = tls_buffer_write(buf, wbuf, rwt->write)) != + rwt->want) { + fprintf(stderr, "FAIL: test %zu - " + "tls_buffer_write() = %zi, want %zu\n", + i, n, rwt->want); + goto failed; + } + } + + if (rwt->read > 0) { + free(rbuf); + if ((rbuf = calloc(1, rwt->read)) == NULL) + errx(1, "malloc"); + if ((n = tls_buffer_read(buf, rbuf, rwt->read)) != + rwt->want) { + fprintf(stderr, "FAIL: test %zu - " + "tls_buffer_read() = %zi, want %zu\n", + i, n, rwt->want); + goto failed; + } + if (rwt->want > 0) { + free(wbuf); + if ((wbuf = malloc(rwt->want)) == NULL) + errx(1, "malloc"); + memset(wbuf, rwt->pattern, rwt->want); + if (memcmp(rbuf, wbuf, rwt->want) != 0) { + fprintf(stderr, "FAIL: test %zu - " + "read byte mismatch\n", i); + goto failed; + } + } + } + } + + failed = 0; + + failed: + tls_buffer_free(buf); + free(rbuf); + free(wbuf); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= tls_buffer_extend_test(); + failed |= tls_buffer_read_write_test(); + + return failed; +} diff --git a/tests/bytestringtest.c b/tests/bytestringtest.c new file mode 100644 index 0000000..36f45c4 --- /dev/null +++ b/tests/bytestringtest.c @@ -0,0 +1,968 @@ +/* $OpenBSD: bytestringtest.c,v 1.17 2023/01/01 17:43:04 miod Exp $ */ +/* + * Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include +#include + +#include + +#include "bytestring.h" + +/* This is from in boringssl */ +#define OPENSSL_U64(x) x##ULL + +#define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \ + __LINE__) + +#define CHECK(a) do { \ + if (!(a)) { \ + PRINT_ERROR; \ + return 0; \ + } \ +} while (0) + +#define CHECK_GOTO(a) do { \ + if (!(a)) { \ + PRINT_ERROR; \ + goto err; \ + } \ +} while (0) + +static int +test_skip(void) +{ + static const uint8_t kData[] = {1, 2, 3}; + CBS data; + + CBS_init(&data, kData, sizeof(kData)); + + CHECK(CBS_len(&data) == 3); + CHECK(CBS_skip(&data, 1)); + CHECK(CBS_len(&data) == 2); + CHECK(CBS_skip(&data, 2)); + CHECK(CBS_len(&data) == 0); + CHECK(!CBS_skip(&data, 1)); + + return 1; +} + +static int +test_get_u(void) +{ + static const uint8_t kData[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + }; + uint8_t u8; + uint16_t u16; + uint32_t u32; + uint64_t u64; + CBS data; + + CBS_init(&data, kData, sizeof(kData)); + + CHECK(CBS_get_u8(&data, &u8)); + CHECK(u8 == 1); + CHECK(CBS_get_u16(&data, &u16)); + CHECK(u16 == 0x203); + CHECK(CBS_get_u24(&data, &u32)); + CHECK(u32 == 0x40506); + CHECK(CBS_get_u32(&data, &u32)); + CHECK(u32 == 0x708090a); + CHECK(CBS_get_u64(&data, &u64)); + CHECK(u64 == 0x0b0c0d0e0f101112ULL); + CHECK(CBS_get_last_u8(&data, &u8)); + CHECK(u8 == 20); + CHECK(CBS_get_last_u8(&data, &u8)); + CHECK(u8 == 19); + CHECK(!CBS_get_u8(&data, &u8)); + CHECK(!CBS_get_last_u8(&data, &u8)); + + return 1; +} + +static int +test_get_prefixed(void) +{ + static const uint8_t kData[] = {1, 2, 0, 2, 3, 4, 0, 0, 3, 3, 2, 1}; + uint8_t u8; + uint16_t u16; + uint32_t u32; + CBS data, prefixed; + + CBS_init(&data, kData, sizeof(kData)); + + CHECK(CBS_get_u8_length_prefixed(&data, &prefixed)); + CHECK(CBS_len(&prefixed) == 1); + CHECK(CBS_get_u8(&prefixed, &u8)); + CHECK(u8 == 2); + CHECK(CBS_get_u16_length_prefixed(&data, &prefixed)); + CHECK(CBS_len(&prefixed) == 2); + CHECK(CBS_get_u16(&prefixed, &u16)); + CHECK(u16 == 0x304); + CHECK(CBS_get_u24_length_prefixed(&data, &prefixed)); + CHECK(CBS_len(&prefixed) == 3); + CHECK(CBS_get_u24(&prefixed, &u32)); + CHECK(u32 == 0x30201); + + return 1; +} + +static int +test_get_prefixed_bad(void) +{ + static const uint8_t kData1[] = {2, 1}; + static const uint8_t kData2[] = {0, 2, 1}; + static const uint8_t kData3[] = {0, 0, 2, 1}; + CBS data, prefixed; + + CBS_init(&data, kData1, sizeof(kData1)); + CHECK(!CBS_get_u8_length_prefixed(&data, &prefixed)); + + CBS_init(&data, kData2, sizeof(kData2)); + CHECK(!CBS_get_u16_length_prefixed(&data, &prefixed)); + + CBS_init(&data, kData3, sizeof(kData3)); + CHECK(!CBS_get_u24_length_prefixed(&data, &prefixed)); + + return 1; +} + +static int +test_peek_u(void) +{ + static const uint8_t kData[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, + }; + uint8_t u8; + uint16_t u16; + uint32_t u32; + CBS data; + + CBS_init(&data, kData, sizeof(kData)); + + CHECK(CBS_peek_u8(&data, &u8)); + CHECK(u8 == 1); + CHECK(CBS_peek_u16(&data, &u16)); + CHECK(u16 == 0x102); + CHECK(CBS_peek_u24(&data, &u32)); + CHECK(u32 == 0x10203); + CHECK(CBS_peek_u32(&data, &u32)); + CHECK(u32 == 0x1020304); + CHECK(CBS_get_u32(&data, &u32)); + CHECK(u32 == 0x1020304); + CHECK(CBS_peek_last_u8(&data, &u8)); + CHECK(u8 == 9); + CHECK(CBS_peek_u32(&data, &u32)); + CHECK(u32 == 0x5060708); + CHECK(CBS_get_u32(&data, &u32)); + CHECK(u32 == 0x5060708); + CHECK(CBS_get_u8(&data, &u8)); + CHECK(u8 == 9); + CHECK(!CBS_get_u8(&data, &u8)); + + return 1; +} + +static int +test_get_asn1(void) +{ + static const uint8_t kData1[] = {0x30, 2, 1, 2}; + static const uint8_t kData2[] = {0x30, 3, 1, 2}; + static const uint8_t kData3[] = {0x30, 0x80}; + static const uint8_t kData4[] = {0x30, 0x81, 1, 1}; + static const uint8_t kData5[4 + 0x80] = {0x30, 0x82, 0, 0x80}; + static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1}; + static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1}; + static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1}; + static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff}; + + CBS data, contents; + int present; + uint64_t value; + + CBS_init(&data, kData1, sizeof(kData1)); + + CHECK(!CBS_peek_asn1_tag(&data, 0x1)); + CHECK(CBS_peek_asn1_tag(&data, 0x30)); + + CHECK(CBS_get_asn1(&data, &contents, 0x30)); + CHECK(CBS_len(&contents) == 2); + CHECK(memcmp(CBS_data(&contents), "\x01\x02", 2) == 0); + + CBS_init(&data, kData2, sizeof(kData2)); + /* data is truncated */ + CHECK(!CBS_get_asn1(&data, &contents, 0x30)); + + CBS_init(&data, kData3, sizeof(kData3)); + /* zero byte length of length */ + CHECK(!CBS_get_asn1(&data, &contents, 0x30)); + + CBS_init(&data, kData4, sizeof(kData4)); + /* long form mistakenly used. */ + CHECK(!CBS_get_asn1(&data, &contents, 0x30)); + + CBS_init(&data, kData5, sizeof(kData5)); + /* length takes too many bytes. */ + CHECK(!CBS_get_asn1(&data, &contents, 0x30)); + + CBS_init(&data, kData1, sizeof(kData1)); + /* wrong tag. */ + CHECK(!CBS_get_asn1(&data, &contents, 0x31)); + + CBS_init(&data, NULL, 0); + /* peek at empty data. */ + CHECK(!CBS_peek_asn1_tag(&data, 0x30)); + + CBS_init(&data, NULL, 0); + /* optional elements at empty data. */ + CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa0)); + CHECK(!present); + CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present, + 0xa0)); + CHECK(!present); + CHECK(CBS_len(&contents) == 0); + CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0)); + CHECK(CBS_len(&contents) == 0); + CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42)); + CHECK(value == 42); + + CBS_init(&data, kData6, sizeof(kData6)); + /* optional element. */ + CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa0)); + CHECK(!present); + CHECK(CBS_get_optional_asn1(&data, &contents, &present, 0xa1)); + CHECK(present); + CHECK(CBS_len(&contents) == 3); + CHECK(memcmp(CBS_data(&contents), "\x04\x01\x01", 3) == 0); + + CBS_init(&data, kData6, sizeof(kData6)); + /* optional octet string. */ + CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present, + 0xa0)); + CHECK(!present); + CHECK(CBS_len(&contents) == 0); + CHECK(CBS_get_optional_asn1_octet_string(&data, &contents, &present, + 0xa1)); + CHECK(present); + CHECK(CBS_len(&contents) == 1); + CHECK(CBS_data(&contents)[0] == 1); + + CBS_init(&data, kData7, sizeof(kData7)); + /* invalid optional octet string. */ + CHECK(!CBS_get_optional_asn1_octet_string(&data, &contents, &present, + 0xa1)); + + CBS_init(&data, kData8, sizeof(kData8)); + /* optional octet string. */ + CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42)); + CHECK(value == 42); + CHECK(CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)); + CHECK(value == 1); + + CBS_init(&data, kData9, sizeof(kData9)); + /* invalid optional integer. */ + CHECK(!CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)); + + return 1; +} + +static int +test_get_optional_asn1_bool(void) +{ + CBS data; + int val; + + static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff}; + static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00}; + static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01}; + + CBS_init(&data, NULL, 0); + val = 2; + CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0)); + CHECK(val == 0); + + CBS_init(&data, kTrue, sizeof(kTrue)); + val = 2; + CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0)); + CHECK(val == 1); + + CBS_init(&data, kFalse, sizeof(kFalse)); + val = 2; + CHECK(CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)); + CHECK(val == 0); + + CBS_init(&data, kInvalid, sizeof(kInvalid)); + CHECK(!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)); + + return 1; +} + +static int +test_cbb_basic(void) +{ + static const uint8_t kExpected[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, + }; + uint8_t *buf = NULL; + size_t buf_len; + int ret = 0; + CBB cbb; + + CHECK(CBB_init(&cbb, 100)); + + CBB_cleanup(&cbb); + + CHECK(CBB_init(&cbb, 0)); + CHECK_GOTO(CBB_add_u8(&cbb, 1)); + CHECK_GOTO(CBB_add_u16(&cbb, 0x203)); + CHECK_GOTO(CBB_add_u24(&cbb, 0x40506)); + CHECK_GOTO(CBB_add_u32(&cbb, 0x708090a)); + CHECK_GOTO(CBB_add_bytes(&cbb, (const uint8_t*) "\x0b\x0c", 2)); + CHECK_GOTO(CBB_add_u64(&cbb, 0xd0e0f1011121314LL)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + + ret = (buf_len == sizeof(kExpected) + && memcmp(buf, kExpected, buf_len) == 0); + + if (0) { +err: + CBB_cleanup(&cbb); + } + free(buf); + return ret; +} + +static int +test_cbb_add_space(void) +{ + static const uint8_t kExpected[] = {1, 2, 0, 0, 0, 0, 7, 8}; + uint8_t *buf = NULL; + size_t buf_len; + uint8_t *data; + int ret = 0; + CBB cbb; + + CHECK(CBB_init(&cbb, 100)); + + CHECK_GOTO(CBB_add_u16(&cbb, 0x102)); + CHECK_GOTO(CBB_add_space(&cbb, &data, 4)); + CHECK_GOTO(CBB_add_u16(&cbb, 0x708)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + + ret |= (buf_len == sizeof(kExpected) + && memcmp(buf, kExpected, buf_len) == 0); + + memset(buf, 0xa5, buf_len); + CHECK(CBB_init_fixed(&cbb, buf, buf_len)); + + CHECK_GOTO(CBB_add_u16(&cbb, 0x102)); + CHECK_GOTO(CBB_add_space(&cbb, &data, 4)); + CHECK_GOTO(CBB_add_u16(&cbb, 0x708)); + CHECK_GOTO(CBB_finish(&cbb, NULL, NULL)); + + ret |= (buf_len == sizeof(kExpected) + && memcmp(buf, kExpected, buf_len) == 0); + + if (0) { +err: + CBB_cleanup(&cbb); + } + free(buf); + return ret; +} + +static int +test_cbb_fixed(void) +{ + CBB cbb; + uint8_t buf[1]; + uint8_t *out_buf = NULL; + size_t out_size; + int ret = 0; + + CHECK(CBB_init_fixed(&cbb, NULL, 0)); + CHECK_GOTO(!CBB_add_u8(&cbb, 1)); + CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size)); + CHECK(out_buf == NULL && out_size == 0); + + CHECK(CBB_init_fixed(&cbb, buf, 1)); + CHECK_GOTO(CBB_add_u8(&cbb, 1)); + CHECK_GOTO(!CBB_add_u8(&cbb, 2)); + CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size)); + + ret = (out_buf == buf && out_size == 1 && buf[0] == 1); + + if (0) { +err: + CBB_cleanup(&cbb); + } + + return ret; +} + +static int +test_cbb_finish_child(void) +{ + CBB cbb, child; + uint8_t *out_buf = NULL; + size_t out_size; + int ret = 0; + + CHECK(CBB_init(&cbb, 16)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child)); + CHECK_GOTO(!CBB_finish(&child, &out_buf, &out_size)); + CHECK_GOTO(CBB_finish(&cbb, &out_buf, &out_size)); + + ret = (out_size == 1 && out_buf[0] == 0); + +err: + free(out_buf); + return ret; +} + +static int +test_cbb_prefixed(void) +{ + static const uint8_t kExpected[] = {0, 1, 1, 0, 2, 2, 3, 0, 0, 3, + 4, 5, 6, 5, 4, 1, 0, 1, 2}; + CBB cbb, contents, inner_contents, inner_inner_contents; + uint8_t *buf = NULL; + size_t buf_len; + int ret = 0; + + CHECK(CBB_init(&cbb, 0)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8(&contents, 1)); + CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u16(&contents, 0x203)); + CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u24(&contents, 0x40506)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents)); + CHECK_GOTO(CBB_add_u8(&inner_contents, 1)); + CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents, + &inner_inner_contents)); + CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 2)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + + ret = (buf_len == sizeof(kExpected) + && memcmp(buf, kExpected, buf_len) == 0); + + if (0) { +err: + CBB_cleanup(&cbb); + } + free(buf); + return ret; +} + +static int +test_cbb_discard_child(void) +{ + static const uint8_t kExpected[] = { + 0xaa, + 0, + 1, 0xbb, + 0, 2, 0xcc, 0xcc, + 0, 0, 3, 0xdd, 0xdd, 0xdd, + 1, 0xff, + }; + CBB cbb, contents, inner_contents, inner_inner_contents; + uint8_t *buf = NULL; + size_t buf_len; + int ret = 0; + + CHECK(CBB_init(&cbb, 0)); + CHECK_GOTO(CBB_add_u8(&cbb, 0xaa)); + + // Discarding |cbb|'s children preserves the byte written. + CBB_discard_child(&cbb); + + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8(&contents, 0xbb)); + CHECK_GOTO(CBB_add_u16_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u16(&contents, 0xcccc)); + CHECK_GOTO(CBB_add_u24_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u24(&contents, 0xdddddd)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &contents)); + CHECK_GOTO(CBB_add_u8(&contents, 0xff)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&contents, &inner_contents)); + CHECK_GOTO(CBB_add_u8(&inner_contents, 0x42)); + CHECK_GOTO(CBB_add_u16_length_prefixed(&inner_contents, + &inner_inner_contents)); + CHECK_GOTO(CBB_add_u8(&inner_inner_contents, 0x99)); + + // Discard everything from |inner_contents| down. + CBB_discard_child(&contents); + + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + + ret = (buf_len == sizeof(kExpected) + && memcmp(buf, kExpected, buf_len) == 0); + + if (0) { +err: + CBB_cleanup(&cbb); + } + free(buf); + return ret; +} + +static int +test_cbb_misuse(void) +{ + CBB cbb, child, contents; + uint8_t *buf = NULL; + size_t buf_len; + int ret = 0; + + CHECK(CBB_init(&cbb, 0)); + CHECK_GOTO(CBB_add_u8_length_prefixed(&cbb, &child)); + CHECK_GOTO(CBB_add_u8(&child, 1)); + CHECK_GOTO(CBB_add_u8(&cbb, 2)); + + /* + * Since we wrote to |cbb|, |child| is now invalid and attempts to write + * to it should fail. + */ + CHECK_GOTO(!CBB_add_u8(&child, 1)); + CHECK_GOTO(!CBB_add_u16(&child, 1)); + CHECK_GOTO(!CBB_add_u24(&child, 1)); + CHECK_GOTO(!CBB_add_u8_length_prefixed(&child, &contents)); + CHECK_GOTO(!CBB_add_u16_length_prefixed(&child, &contents)); + CHECK_GOTO(!CBB_add_asn1(&child, &contents, 1)); + CHECK_GOTO(!CBB_add_bytes(&child, (const uint8_t*) "a", 1)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + + ret = (buf_len == 3 && memcmp(buf, "\x01\x01\x02", 3) == 0); + + if (0) { +err: + CBB_cleanup(&cbb); + } + free(buf); + return ret; +} + +static int +test_cbb_asn1(void) +{ + static const uint8_t kExpected[] = {0x30, 3, 1, 2, 3}; + uint8_t *buf = NULL, *test_data = NULL; + size_t buf_len; + CBB cbb, contents, inner_contents; + int ret = 0; + int alloc = 0; + + CHECK_GOTO(CBB_init(&cbb, 0)); + alloc = 1; + CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30)); + CHECK_GOTO(CBB_add_bytes(&contents, (const uint8_t*) "\x01\x02\x03", + 3)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + alloc = 0; + + CHECK_GOTO(buf_len == sizeof(kExpected)); + CHECK_GOTO(memcmp(buf, kExpected, buf_len) == 0); + + free(buf); + buf = NULL; + + CHECK_GOTO(((test_data = malloc(100000)) != NULL)); + memset(test_data, 0x42, 100000); + + CHECK_GOTO(CBB_init(&cbb, 0)); + alloc = 1; + CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30)); + CHECK_GOTO(CBB_add_bytes(&contents, test_data, 130)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + alloc = 0; + + CHECK_GOTO(buf_len == 3 + 130); + CHECK_GOTO(memcmp(buf, "\x30\x81\x82", 3) == 0); + CHECK_GOTO(memcmp(buf + 3, test_data, 130) == 0); + + free(buf); + buf = NULL; + + CHECK_GOTO(CBB_init(&cbb, 0)); + alloc = 1; + CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30)); + CHECK_GOTO(CBB_add_bytes(&contents, test_data, 1000)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + alloc = 0; + + CHECK_GOTO(buf_len == 4 + 1000); + CHECK_GOTO(memcmp(buf, "\x30\x82\x03\xe8", 4) == 0); + CHECK_GOTO(!memcmp(buf + 4, test_data, 1000)); + + free(buf); + buf = NULL; + + CHECK_GOTO(CBB_init(&cbb, 0)); + alloc = 1; + CHECK_GOTO(CBB_add_asn1(&cbb, &contents, 0x30)); + CHECK_GOTO(CBB_add_asn1(&contents, &inner_contents, 0x30)); + CHECK_GOTO(CBB_add_bytes(&inner_contents, test_data, 100000)); + CHECK_GOTO(CBB_finish(&cbb, &buf, &buf_len)); + alloc = 0; + + CHECK_GOTO(buf_len == 5 + 5 + 100000); + CHECK_GOTO(memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) + == 0); + CHECK_GOTO(!memcmp(buf + 10, test_data, 100000)); + + ret = 1; + + if (0) { +err: + if (alloc) + CBB_cleanup(&cbb); + } + free(buf); + free(test_data); + return ret; +} + +static int +do_indefinite_convert(const char *name, const uint8_t *definite_expected, + size_t definite_len, const uint8_t *indefinite, size_t indefinite_len) +{ + CBS in; + uint8_t *out = NULL; + size_t out_len; + int ret = 0; + + CBS_init(&in, indefinite, indefinite_len); + + CHECK_GOTO(CBS_asn1_indefinite_to_definite(&in, &out, &out_len)); + + if (out == NULL) { + + if (indefinite_len != definite_len || + memcmp(definite_expected, indefinite, indefinite_len) != 0) { + PRINT_ERROR; + goto err; + } + + return 1; + } + + if (out_len != definite_len || + memcmp(out, definite_expected, definite_len) != 0) { + PRINT_ERROR; + goto err; + } + + ret = 1; +err: + free(out); + return ret; +} + +static int +test_indefinite_convert(void) +{ + static const uint8_t kSimpleBER[] = {0x01, 0x01, 0x00}; + + /* kIndefBER contains a SEQUENCE with an indefinite length. */ + static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, + 0x00}; + static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02}; + + /* + * kOctetStringBER contains an indefinite length OCTETSTRING with two + * parts. These parts need to be concatenated in DER form. + */ + static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0, + 1, 0x04, 0x02, 2, 3, 0x00, 0x00}; + static const uint8_t kOctetStringDER[] = {0x04, 0x04, 0, 1, 2, 3}; + + /* + * kNSSBER is part of a PKCS#12 message generated by NSS that uses + * indefinite length elements extensively. + */ + static const uint8_t kNSSBER[] = { + 0x30, 0x80, 0x02, 0x01, 0x03, 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x80, 0x24, 0x80, + 0x04, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, 0x98, 0xfc, 0x66, + 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, 0x8f, 0xfe, 0x1d, + 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, 0x62, 0xc6, 0x44, + 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, 0x6e, 0x10, 0x9b, + 0xb8, 0x02, 0x02, 0x07, 0xd0, 0x00, 0x00, + }; + + static const uint8_t kNSSDER[] = { + 0x30, 0x53, 0x02, 0x01, 0x03, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x06, 0x04, 0x04, + 0x01, 0x02, 0x03, 0x04, 0x30, 0x39, 0x30, 0x21, 0x30, 0x09, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x84, + 0x98, 0xfc, 0x66, 0x33, 0xee, 0xba, 0xe7, 0x90, 0xc1, 0xb6, 0xe8, + 0x8f, 0xfe, 0x1d, 0xc5, 0xa5, 0x97, 0x93, 0x3e, 0x04, 0x10, 0x38, + 0x62, 0xc6, 0x44, 0x12, 0xd5, 0x30, 0x00, 0xf8, 0xf2, 0x1b, 0xf0, + 0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0, + }; + + CHECK(do_indefinite_convert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER), + kSimpleBER, sizeof(kSimpleBER))); + CHECK(do_indefinite_convert("kIndefBER", kIndefDER, sizeof(kIndefDER), + kIndefBER, sizeof(kIndefBER))); + CHECK(do_indefinite_convert("kOctetStringBER", kOctetStringDER, + sizeof(kOctetStringDER), kOctetStringBER, + sizeof(kOctetStringBER))); + CHECK(do_indefinite_convert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER, + sizeof(kNSSBER))); + + return 1; +} + +typedef struct { + uint64_t value; + const char *encoding; + size_t encoding_len; +} ASN1_UINT64_TEST; + +static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = { + {0, "\x02\x01\x00", 3}, + {1, "\x02\x01\x01", 3}, + {127, "\x02\x01\x7f", 3}, + {128, "\x02\x02\x00\x80", 4}, + {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7}, + {OPENSSL_U64(0x0102030405060708), + "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10}, + {OPENSSL_U64(0xffffffffffffffff), + "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11}, +}; + +typedef struct { + const char *encoding; + size_t encoding_len; +} ASN1_INVALID_UINT64_TEST; + +static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = { + /* Bad tag. */ + {"\x03\x01\x00", 3}, + /* Empty contents. */ + {"\x02\x00", 2}, + /* Negative number. */ + {"\x02\x01\x80", 3}, + /* Overflow. */ + {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11}, + /* Leading zeros. */ + {"\x02\x02\x00\x01", 4}, +}; + +static int +test_asn1_uint64(void) +{ + CBB cbb; + uint8_t *out = NULL; + size_t i; + int ret = 0; + int alloc = 0; + + for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); + i++) { + const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i]; + CBS cbs; + uint64_t value; + size_t len; + + CBS_init(&cbs, (const uint8_t *)test->encoding, + test->encoding_len); + + CHECK(CBS_get_asn1_uint64(&cbs, &value)); + CHECK(CBS_len(&cbs) == 0); + CHECK(value == test->value); + + CHECK(CBB_init(&cbb, 0)); + alloc = 1; + CHECK_GOTO(CBB_add_asn1_uint64(&cbb, test->value)); + CHECK_GOTO(CBB_finish(&cbb, &out, &len)); + alloc = 0; + + CHECK_GOTO(len == test->encoding_len); + CHECK_GOTO(memcmp(out, test->encoding, len) == 0); + free(out); + out = NULL; + } + + for (i = 0; i < sizeof(kAsn1InvalidUint64Tests) + / sizeof(kAsn1InvalidUint64Tests[0]); i++) { + const ASN1_INVALID_UINT64_TEST *test = + &kAsn1InvalidUint64Tests[i]; + CBS cbs; + uint64_t value; + + CBS_init(&cbs, (const uint8_t *)test->encoding, + test->encoding_len); + CHECK(!CBS_get_asn1_uint64(&cbs, &value)); + } + + ret = 1; + + if (0) { +err: + if (alloc) + CBB_cleanup(&cbb); + } + free(out); + + return ret; +} + +static int +test_offset(void) +{ + uint8_t v; + static const uint8_t input[] = {1, 2, 3, 4, 5}; + CBS data; + + CBS_init(&data, input, sizeof(input)); + CHECK(sizeof(input) == 5); + CHECK(CBS_len(&data) == 5); + CHECK(CBS_offset(&data) == 0); + CHECK(CBS_get_u8(&data, &v)); + CHECK(v == 1); + CHECK(CBS_len(&data) == 4); + CHECK(CBS_offset(&data) == 1); + CHECK(CBS_skip(&data, 2)); + CHECK(CBS_len(&data) == 2); + CHECK(CBS_offset(&data) == 3); + CHECK(CBS_get_u8(&data, &v)); + CHECK(v == 4); + CHECK(CBS_get_u8(&data, &v)); + CHECK(v == 5); + CHECK(CBS_len(&data) == 0); + CHECK(CBS_offset(&data) == 5); + CHECK(!CBS_skip(&data, 1)); + + CBS_init(&data, input, sizeof(input)); + CHECK(CBS_skip(&data, 2)); + CHECK(CBS_len(&data) == 3); + CHECK(CBS_offset(&data) == 2); + CHECK(CBS_skip(&data, 3)); + CHECK(CBS_len(&data) == 0); + CHECK(CBS_offset(&data) == 5); + CHECK(!CBS_get_u8(&data, &v)); + + return 1; +} + +static int +test_write_bytes(void) +{ + int ret = 0; + uint8_t v; + size_t len; + static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'}; + CBS data; + uint8_t *tmp = NULL; + + CHECK_GOTO((tmp = malloc(sizeof(input))) != NULL); + memset(tmp, 100, sizeof(input)); + + CBS_init(&data, input, sizeof(input)); + CHECK_GOTO(CBS_len(&data) == 6); + CHECK_GOTO(CBS_offset(&data) == 0); + CHECK_GOTO(CBS_get_u8(&data, &v)); + CHECK_GOTO(v == 102 /* f */); + CHECK_GOTO(CBS_skip(&data, 1)); + CHECK_GOTO(!CBS_skip(&data, 15)); + CHECK_GOTO(CBS_write_bytes(&data, tmp, sizeof(input), &len)); + CHECK_GOTO(len == 4); + CHECK_GOTO(memcmp(input + 2, tmp, len) == 0); + CHECK_GOTO(tmp[4] == 100 && tmp[5] == 100); + + ret = 1; + +err: + free(tmp); + return ret; +} + +static int +test_cbs_dup(void) +{ + CBS data, check; + static const uint8_t input[] = {'f', 'o', 'o', 'b', 'a', 'r'}; + + CBS_init(&data, input, sizeof(input)); + CHECK(CBS_len(&data) == 6); + CBS_dup(&data, &check); + CHECK(CBS_len(&check) == 6); + CHECK(CBS_data(&data) == CBS_data(&check)); + CHECK(CBS_skip(&data, 1)); + CHECK(CBS_len(&data) == 5); + CHECK(CBS_len(&check) == 6); + CHECK(CBS_data(&data) == CBS_data(&check) + 1); + CHECK(CBS_skip(&check, 1)); + CHECK(CBS_len(&data) == 5); + CHECK(CBS_len(&check) == 5); + CHECK(CBS_data(&data) == CBS_data(&check)); + CHECK(CBS_offset(&data) == 1); + CHECK(CBS_offset(&check) == 1); + + CBS_init(&data, input, sizeof(input)); + CHECK(CBS_skip(&data, 5)); + CBS_dup(&data, &check); + CHECK(CBS_len(&data) == 1); + CHECK(CBS_len(&check) == 1); + CHECK(CBS_data(&data) == input + 5); + CHECK(CBS_data(&data) == CBS_data(&check)); + CHECK(CBS_offset(&data) == 5); + CHECK(CBS_offset(&check) == 5); + + return 1; +} + +int +main(void) +{ + int failed = 0; + + failed |= !test_skip(); + failed |= !test_get_u(); + failed |= !test_get_prefixed(); + failed |= !test_get_prefixed_bad(); + failed |= !test_peek_u(); + failed |= !test_get_asn1(); + failed |= !test_cbb_basic(); + failed |= !test_cbb_add_space(); + failed |= !test_cbb_fixed(); + failed |= !test_cbb_finish_child(); + failed |= !test_cbb_discard_child(); + failed |= !test_cbb_misuse(); + failed |= !test_cbb_prefixed(); + failed |= !test_cbb_asn1(); + failed |= !test_indefinite_convert(); + failed |= !test_asn1_uint64(); + failed |= !test_get_optional_asn1_bool(); + failed |= !test_offset(); + failed |= !test_write_bytes(); + failed |= !test_cbs_dup(); + + if (!failed) + printf("PASS\n"); + return failed; +} diff --git a/tests/ca-int-ecdsa.crl b/tests/ca-int-ecdsa.crl new file mode 100644 index 0000000..b904de3 --- /dev/null +++ b/tests/ca-int-ecdsa.crl @@ -0,0 +1,8 @@ +-----BEGIN X509 CRL----- +MIHuMIGUMAoGCCqGSM49BAMCMC4xLDAqBgNVBAMMI0xpYnJlU1NMIFRlc3QgSW50 +ZXJtZWRpYXRlIENBIEVDRFNBFw0yMTEyMjcxNDQwNDBaFw0yMjAxMjYxNDQwNDBa +MDgwGgIJAOVssaaTYoH5Fw0yMTEyMjcxNDQwNDBaMBoCCQDlbLGmk2KB+xcNMjEx +MjI3MTQ0MDQwWjAKBggqhkjOPQQDAgNJADBGAiEA9FWkenCgh+6Rz0/nuS7DaiUR +J5imCs0Wx6TiG3YUL3oCIQDfTT+54eKAEFXeYN2oToZtHbTHh5YUici5GA/PDmOG +Ig== +-----END X509 CRL----- diff --git a/tests/ca-int-ecdsa.pem b/tests/ca-int-ecdsa.pem new file mode 100644 index 0000000..fa1db86 --- /dev/null +++ b/tests/ca-int-ecdsa.pem @@ -0,0 +1,13 @@ +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/ca-int-rsa.crl b/tests/ca-int-rsa.crl new file mode 100644 index 0000000..481886a --- /dev/null +++ b/tests/ca-int-rsa.crl @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBrDCBlTANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0 +IEludGVybWVkaWF0ZSBDQSBSU0EXDTIxMTIyNzE0NDAzOFoXDTIyMDEyNjE0NDAz +OFowODAaAgkA5WyxppNigfQXDTIxMTIyNzE0NDAzN1owGgIJAOVssaaTYoH2Fw0y +MTEyMjcxNDQwMzhaMA0GCSqGSIb3DQEBCwUAA4IBAQCGMtlhTlaOK7fK2OHXgoAf +lDr1FQfqfNo5ZNE2+VqOvjYfgwdOgfxIsIuUoNp9/NhzO3e4KNe6P/33axwIsy7o +RofbGYFSlHIYPEf1LyvH8z5mT2L2LAQAi+p+QMFizH6KNc74Oftygyi1bcJlN3CJ +dP9LyvACdJSna7dEh7Snu2hy8tEDAO/RxUrryOZca0+5I4aaD8QCdFwdicDQ8U1s +gTJ5w1gxkEWKv/J/AjCjRAVoAjE2/sUC1PPOJnZy7b0sS2Fv7zV7UAWSzO0KEYv+ +vav3UekGIgw0A5PDdWmUqCxE7aK71iy4EmlzMyVNULVcF1qX6qBQT5OpXr0Eo6WR +-----END X509 CRL----- diff --git a/tests/ca-int-rsa.pem b/tests/ca-int-rsa.pem new file mode 100644 index 0000000..b457ad6 --- /dev/null +++ b/tests/ca-int-rsa.pem @@ -0,0 +1,22 @@ +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/ca-root-ecdsa.pem b/tests/ca-root-ecdsa.pem new file mode 100644 index 0000000..c7862da --- /dev/null +++ b/tests/ca-root-ecdsa.pem @@ -0,0 +1,13 @@ +subject= CN = LibreSSL Test Root CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBpjCCAUygAwIBAgIJALqTupYRbYuwMAoGCCqGSM49BAMCMCYxJDAiBgNVBAMM +G0xpYnJlU1NMIFRlc3QgUm9vdCBDQSBFQ0RTQTAeFw0yMTEyMjcxNDQwNDBaFw0z +MTEyMjUxNDQwNDBaMCYxJDAiBgNVBAMMG0xpYnJlU1NMIFRlc3QgUm9vdCBDQSBF +Q0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIxQjA3Gp+4irgwEumPY1/EG +lVy6/olnAc+4elWkj0SqqdjfWanQqO8wHFY0qICKq8lHKhcyw2v9oyOsNVXZj8Kj +YzBhMB0GA1UdDgQWBBS2+Rq3hR1xQSKm3ov88GAQVgfoDDAfBgNVHSMEGDAWgBS2 ++Rq3hR1xQSKm3ov88GAQVgfoDDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAKBggqhkjOPQQDAgNIADBFAiAqAN8RFQOAIXeJcxCHUCN1n3sUBuYF/XkS +VnTsAEU/kwIhANNk/xjGq9O2YeLEFT1InoltVlwM5P8oa7krPnPbFnwY +-----END CERTIFICATE----- diff --git a/tests/ca-root-rsa.pem b/tests/ca-root-rsa.pem new file mode 100644 index 0000000..daf3407 --- /dev/null +++ b/tests/ca-root-rsa.pem @@ -0,0 +1,22 @@ +subject= CN = LibreSSL Test Root CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgIJAIuM+uV8F+LtMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAkMSIwIAYDVQQDDBlMaWJyZVNTTCBUZXN0IFJvb3QgQ0Eg +UlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnvrj8h5JmJ+7V33R +wloqhM0nLvmidkmk1sqJaOi0GNXoMLnaut90+2TnRiFDbsblzAjTijQC6PEfaJTB +AEFBgNSQKdhVruYTL5HHhw/XHTjxqftizvJj1FsZh2n6gkTG/QOgbaDMCx+yFF88 +wro7Br32TZF+BuDuyzVcSPJUajYT+C9bWSq9jX8Fhvl5M3IOG7olg3gAMmU+E8SY +TaKhoJ7KGLHDEQP9NJknJusV8T72lY/TzacVDDOxEUxpuYtJ1Kayytflhs1065Ua +PkiIReoFnhK/tRAgyxz3bc6HDDmTz4FpyGPcAsSRtEbn1n1417hzH4Neq5eioVmx +hX1HTwIDAQABo2MwYTAdBgNVHQ4EFgQUPkv8e/SsNCqlESgB8ojoXY//FdEwHwYD +VR0jBBgwFoAUPkv8e/SsNCqlESgB8ojoXY//FdEwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAEYi6O+l7SS14myiZydm +eP0hS8+ABWz/xqzu81W5Uxo7XD3sNfz5hkhA3S2FrBg5xpDScAzsM9Og6VRuQA7/ +StWLc2gLvLI6cZNdOCOH/O4K6IYRGR0kXG7WA4MpBiDrPXZKXI3WcUNyTHM36Un4 +ZATRkO+xMLKFpnxHCkY5U9kp8xX5boNxtQsGkWfuG+fm7GVBaQapnvN+WRY4QXKQ +jF10CFUcIUNGG81XTEhQwpcP0b0ruZK6JBah4VG7lUHbJ6/WoYiGYXCToK09ohIX +PuWiVTiT9LH90U58No3NfinQPbE55mJju+YNNqLU4Wk3ub5rYpp0WFmo6T9kXL/z +fO8= +-----END CERTIFICATE----- diff --git a/tests/ca.pem b/tests/ca.pem new file mode 100644 index 0000000..07f9b3f --- /dev/null +++ b/tests/ca.pem @@ -0,0 +1,45 @@ +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIJAJz/hGfwYXLrMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQDDBRPcGVuU1NMIFRlc3QgUm9vdCBD +QTAeFw0xNDA1MjQxNDQ1MTFaFw0yNDA1MjExNDQ1MTFaMGgxCzAJBgNVBAYTAlVL +MRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVTVElORyBQ +VVJQT1NFUyBPTkxZMR0wGwYDVQQDDBRPcGVuU1NMIFRlc3QgUm9vdCBDQTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANMaarigKGOra5Mc/LrhOkcmHzDs +vkYL7dfaaht8fLBKRTYwzSBvO9x54koTWjq7HkbaxkYAg3HnDTkNCyzkGKNdM89H +q/PtGIFFlceQIOat3Kjd05Iw3PtLEWTDjT6FMA9Mkjk/XbpmycqRIwNKtgICoFsG +juIpc4P31kxK7i3ri+JnlyvVmRZjJxrheJB0qHGXilrOVDPOliDn//jXbcyzXemu +R8KgAeQM4IIs9jYHJOgHrTItIpwa9wNTEp9KCGkO6xr20NkKyDp6XRyd+hmnUB7r +77WTptvKPFFTjTDFqEtcif9U2kVkCfn2mSRO8noCbVH++fuR8LMWlD99gt8CAwEA +AaNjMGEwHQYDVR0OBBYEFIwZD9dCMXcFBuHTsZ/rOft4cTpFMB8GA1UdIwQYMBaA +FIwZD9dCMXcFBuHTsZ/rOft4cTpFMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCPfqm4KbYtXEB8aP1RdUH2BkPSjyau +WQLMGfKNF/zkUQue0REgdJ4wVR06NTTlOCsfHC6b68vgz2QFC1mM8ZANgDiyr4M1 +6gjvP0eZQVxokJ3EMzjDMFRHIiFrZZAFr7aGq8dxoruuehovqyehuJRakAe0oNUb +4ZTKrGuTKh9Mwti9721XNFByjeTFL2dlH6ulz7qyfI+lrTi+pNsUchuVYE8a1TP3 +OEiG6whsyPU1YoTlemC1mvW0ixtj8Tcem0KyotCUyOmJlwyWj0bA43sCI6z/OVqJ +tVvwgfqrOeVNk9nN2JslCsttnwstwqUfDoEXFoScej2CT0QezFGPTN21 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvjCCAqagAwIBAgIJAPrXr2k7uM/OMA0GCSqGSIb3DQEBBQUAMGgxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQDDBRPcGVuU1NMIFRlc3QgUm9vdCBD +QTAeFw0xNDA1MjQxNDQ1MTFaFw0yNDA1MDExNDQ1MTFaMHAxCzAJBgNVBAYTAlVL +MRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVTVElORyBQ +VVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJtZWRpYXRl +IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsErw75CmLYD6pkrG +W/YhAl/K8L5wJYxDjqu2FghxjD8K308W3EHq4uBxEwR1OHXaM1+6ZZw7/r2I37VL +IdurBEAIEUdbzx0so74FPawgz5EW2CTqoJnK8F71/vo5Kj1VPwW46CxwxUR3cfvJ +GNXND2ip0TcyTSPLROXOyQakcVfIGJmdSa1wHKi+c2gMA4emADudZUOYLrg80gr2 +ldePm07ynbVsKKzCcStw8MdmoW9Qt3fLnPJn2TFUUBNWj+4kvL+88edWCVQXKNds +ysD/CDrH4W/hjyPDStVsM6XpiNU0+L2ZY6fcj3OP8d0goOx45xotMn9m8hNkCGsr +VXx9IwIDAQABo2MwYTAdBgNVHQ4EFgQUNsNsiOeV/rC97M4+PYarIYGH2towHwYD +VR0jBBgwFoAUjBkP10IxdwUG4dOxn+s5+3hxOkUwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAAIwwR8jyFN6qYGIRAKi +ahyeHd26hNPC4RiCvjz6dytuvDUqfMTUZcjBy6Ez1Wsfs1/PC8u3IDpOTwZSz72K +ACQzPpmXREWkO5nx8I+W+94yJsbklhsTxDlZj3X2oJCQ7qO4hdIpYESWfMchYra9 +5e55SMBXeGDp+uRILt+6UfOXCGaXaoYqyrzQROJAiGy1x96A/5sU6ZU3KdKN1JLM +XTZ268ihubCMRVScHnpYUjRDoGrhnQM7007ybVfRUGNXDs+ENqjGfyxc5ScR+Un4 +UQtOd4zD2g9wrdXvlDiqxci6W7IOEPVP6qHG2GIh+T2zpO3GOAuZCe5cjLiCDATs +hNw= +-----END CERTIFICATE----- diff --git a/tests/callback.c b/tests/callback.c new file mode 100644 index 0000000..a01ffd5 --- /dev/null +++ b/tests/callback.c @@ -0,0 +1,428 @@ +/* $OpenBSD: callback.c,v 1.4 2023/01/28 19:12:20 tb Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * Copyright (c) 2020-2021 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_verify.h" + +#define MODE_MODERN_VFY 0 +#define MODE_MODERN_VFY_DIR 1 +#define MODE_LEGACY_VFY 2 +#define MODE_VERIFY 3 + +static int verbose = 1; +FILE *output; + +static int +passwd_cb(char *buf, int size, int rwflag, void *u) +{ + memset(buf, 0, size); + return (0); +} + +static int +certs_from_file(const char *filename, STACK_OF(X509) **certs) +{ + STACK_OF(X509_INFO) *xis = NULL; + STACK_OF(X509) *xs = NULL; + BIO *bio = NULL; + X509 *x; + int i; + + if ((xs = sk_X509_new_null()) == NULL) + errx(1, "failed to create X509 stack"); + if ((bio = BIO_new_file(filename, "r")) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to create bio"); + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, passwd_cb, NULL)) == NULL) + errx(1, "failed to read PEM"); + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + if ((x = sk_X509_INFO_value(xis, i)->x509) == NULL) + continue; + if (!sk_X509_push(xs, x)) + errx(1, "failed to push X509"); + X509_up_ref(x); + } + + *certs = xs; + xs = NULL; + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + sk_X509_pop_free(xs, X509_free); + BIO_free(bio); + + return 1; +} + +static int +verify_cert_cb(int ok, X509_STORE_CTX *xsc) +{ + X509 *current_cert, *issuer_cert; + int verify_err, verify_depth; + + current_cert = X509_STORE_CTX_get_current_cert(xsc); + issuer_cert = X509_STORE_CTX_get0_current_issuer(xsc); + verify_depth = X509_STORE_CTX_get_error_depth(xsc); + verify_err = X509_STORE_CTX_get_error(xsc); + fprintf(output, "depth %d error %d", verify_depth, verify_err); + fprintf(output, " cert: "); + if (current_cert != NULL) { + X509_NAME_print_ex_fp(output, + X509_get_subject_name(current_cert), 0, + XN_FLAG_ONELINE); + } else + fprintf(output, "NULL"); + fprintf(output, " issuer: "); + if (issuer_cert != NULL) { + X509_NAME_print_ex_fp(output, + X509_get_subject_name(issuer_cert), 0, + XN_FLAG_ONELINE); + } else + fprintf(output, "NULL"); + fprintf(output, "\n"); + + return ok; +} + +static void +verify_cert(const char *roots_dir, const char *roots_file, + const char *bundle_file, int *chains, int mode) +{ + STACK_OF(X509) *roots = NULL, *bundle = NULL; + X509_STORE_CTX *xsc = NULL; + X509_STORE *store = NULL; + int verify_err, use_dir; + X509 *leaf = NULL; + + *chains = 0; + use_dir = (mode == MODE_MODERN_VFY_DIR); + + if (!use_dir && !certs_from_file(roots_file, &roots)) + errx(1, "failed to load roots from '%s'", roots_file); + if (!certs_from_file(bundle_file, &bundle)) + errx(1, "failed to load bundle from '%s'", bundle_file); + if (sk_X509_num(bundle) < 1) + errx(1, "not enough certs in bundle"); + leaf = sk_X509_shift(bundle); + + if ((xsc = X509_STORE_CTX_new()) == NULL) + errx(1, "X509_STORE_CTX"); + if (use_dir && (store = X509_STORE_new()) == NULL) + errx(1, "X509_STORE"); + if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) { + ERR_print_errors_fp(stderr); + errx(1, "failed to init store context"); + } + if (use_dir) { + if (!X509_STORE_load_locations(store, NULL, roots_dir)) + errx(1, "failed to set by_dir directory of %s", roots_dir); + } + if (mode == MODE_LEGACY_VFY) + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_LEGACY_VERIFY); + else + X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(xsc), + X509_V_FLAG_LEGACY_VERIFY); + + if (verbose) + X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); + if (!use_dir) + X509_STORE_CTX_set0_trusted_stack(xsc, roots); + if (X509_verify_cert(xsc) == 1) { + *chains = 1; /* XXX */ + goto done; + } + + verify_err = X509_STORE_CTX_get_error(xsc); + if (verify_err == 0) + errx(1, "Error unset on failure!\n"); + + fprintf(stderr, "failed to verify at %d: %s\n", + X509_STORE_CTX_get_error_depth(xsc), + X509_verify_cert_error_string(verify_err)); + + done: + sk_X509_pop_free(roots, X509_free); + sk_X509_pop_free(bundle, X509_free); + X509_STORE_free(store); + X509_STORE_CTX_free(xsc); + X509_free(leaf); +} + +struct verify_cert_test { + const char *id; + int want_chains; + int failing; +}; + +struct verify_cert_test verify_cert_tests[] = { + { + .id = "1a", + .want_chains = 1, + }, + { + .id = "2a", + .want_chains = 1, + }, + { + .id = "2b", + .want_chains = 0, + }, + { + .id = "2c", + .want_chains = 1, + }, + { + .id = "3a", + .want_chains = 1, + }, + { + .id = "3b", + .want_chains = 0, + }, + { + .id = "3c", + .want_chains = 0, + }, + { + .id = "3d", + .want_chains = 0, + }, + { + .id = "3e", + .want_chains = 1, + }, + { + .id = "4a", + .want_chains = 2, + }, + { + .id = "4b", + .want_chains = 1, + }, + { + .id = "4c", + .want_chains = 1, + .failing = 1, + }, + { + .id = "4d", + .want_chains = 1, + }, + { + .id = "4e", + .want_chains = 1, + }, + { + .id = "4f", + .want_chains = 2, + }, + { + .id = "4g", + .want_chains = 1, + .failing = 1, + }, + { + .id = "4h", + .want_chains = 1, + }, + { + .id = "5a", + .want_chains = 2, + }, + { + .id = "5b", + .want_chains = 1, + .failing = 1, + }, + { + .id = "5c", + .want_chains = 1, + }, + { + .id = "5d", + .want_chains = 1, + }, + { + .id = "5e", + .want_chains = 1, + .failing = 1, + }, + { + .id = "5f", + .want_chains = 1, + }, + { + .id = "5g", + .want_chains = 2, + }, + { + .id = "5h", + .want_chains = 1, + }, + { + .id = "5i", + .want_chains = 1, + .failing = 1, + }, + { + .id = "6a", + .want_chains = 1, + }, + { + .id = "6b", + .want_chains = 1, + .failing = 1, + }, + { + .id = "7a", + .want_chains = 1, + .failing = 1, + }, + { + .id = "7b", + .want_chains = 1, + }, + { + .id = "8a", + .want_chains = 0, + }, + { + .id = "9a", + .want_chains = 0, + }, + { + .id = "10a", + .want_chains = 1, + }, + { + .id = "10b", + .want_chains = 1, + }, + { + .id = "11a", + .want_chains = 1, + .failing = 1, + }, + { + .id = "11b", + .want_chains = 1, + }, + { + .id = "12a", + .want_chains = 1, + }, + { + .id = "13a", + .want_chains = 1, + .failing = 1, + }, +}; + +#define N_VERIFY_CERT_TESTS \ + (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests)) + +static int +verify_cert_test(const char *certs_path, int mode) +{ + char *roots_file, *bundle_file, *roots_dir; + struct verify_cert_test *vct; + int failed = 0; + int chains; + size_t i; + + for (i = 0; i < N_VERIFY_CERT_TESTS; i++) { + vct = &verify_cert_tests[i]; + + if (asprintf(&roots_file, "%s/%s/roots.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&roots_dir, "./%s/roots", vct->id) == -1) + errx(1, "asprintf"); + + fprintf(output, "== Test %zu (%s)\n", i, vct->id); + fprintf(output, "== Legacy:\n"); + mode = MODE_LEGACY_VFY; + verify_cert(roots_dir, roots_file, bundle_file, &chains, mode); + if ((mode == MODE_VERIFY && chains == vct->want_chains) || + (chains == 0 && vct->want_chains == 0) || + (chains == 1 && vct->want_chains > 0)) { + fprintf(output, "INFO: Succeeded with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (mode == MODE_LEGACY_VFY && vct->failing) + failed |= 1; + } else { + fprintf(output, "FAIL: Failed with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (!vct->failing) + failed |= 1; + } + fprintf(output, "\n"); + fprintf(output, "== Modern:\n"); + mode = MODE_MODERN_VFY; + verify_cert(roots_dir, roots_file, bundle_file, &chains, mode); + if ((mode == MODE_VERIFY && chains == vct->want_chains) || + (chains == 0 && vct->want_chains == 0) || + (chains == 1 && vct->want_chains > 0)) { + fprintf(output, "INFO: Succeeded with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (mode == MODE_LEGACY_VFY && vct->failing) + failed |= 1; + } else { + fprintf(output, "FAIL: Failed with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (!vct->failing) + failed |= 1; + } + fprintf(output, "\n"); + + free(roots_file); + free(bundle_file); + free(roots_dir); + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + + output = fopen("callback.out", "w+"); + + fprintf(stderr, "\n\nTesting legacy and modern X509_vfy\n"); + failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY); + return (failed); +} diff --git a/tests/callbackfailures.c b/tests/callbackfailures.c new file mode 100644 index 0000000..53570e1 --- /dev/null +++ b/tests/callbackfailures.c @@ -0,0 +1,298 @@ +/* $OpenBSD: callbackfailures.c,v 1.2 2023/01/28 19:12:20 tb Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * Copyright (c) 2020-2021 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_verify.h" + +#define MODE_MODERN_VFY 0 +#define MODE_MODERN_VFY_DIR 1 +#define MODE_LEGACY_VFY 2 +#define MODE_VERIFY 3 + +static int verbose = 1; + +static int expected_depth; +static int expected_error; +static int seen_depth; +static int seen_error; + +static int +passwd_cb(char *buf, int size, int rwflag, void *u) +{ + memset(buf, 0, size); + return (0); +} + +static int +certs_from_file(const char *filename, STACK_OF(X509) **certs, int clear) +{ + STACK_OF(X509_INFO) *xis = NULL; + STACK_OF(X509) *xs = NULL; + BIO *bio = NULL; + X509 *x; + int i; + + if (clear) { + if ((xs = sk_X509_new_null()) == NULL) + errx(1, "failed to create X509 stack"); + } else + xs = *certs; + if ((bio = BIO_new_file(filename, "r")) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to create bio"); + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, passwd_cb, NULL)) == NULL) + errx(1, "failed to read PEM"); + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + if ((x = sk_X509_INFO_value(xis, i)->x509) == NULL) + continue; + if (!sk_X509_push(xs, x)) + errx(1, "failed to push X509"); + X509_up_ref(x); + } + + *certs = xs; + xs = NULL; + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + sk_X509_pop_free(xs, X509_free); + BIO_free(bio); + + return 1; +} + +static int +verify_cert_cb(int ok, X509_STORE_CTX *xsc) +{ + X509 *current_cert; + int verify_err; + + current_cert = X509_STORE_CTX_get_current_cert(xsc); + if (current_cert != NULL) { + X509_NAME_print_ex_fp(stderr, + X509_get_subject_name(current_cert), 0, + XN_FLAG_ONELINE); + fprintf(stderr, "\n"); + } + + verify_err = X509_STORE_CTX_get_error(xsc); + if (verify_err != X509_V_OK) { + seen_depth = X509_STORE_CTX_get_error_depth(xsc); + seen_error = verify_err; + fprintf(stderr, "verify error at depth %d: %s\n", + X509_STORE_CTX_get_error_depth(xsc), + X509_verify_cert_error_string(verify_err)); + } + + fprintf(stderr, "chain of length %d\n", sk_X509_num (X509_STORE_CTX_get0_chain (xsc))); + + return ok; +} + +static void +verify_cert(const char *roots_dir, const char *roots_file, + const char *bundle_file, const char*bundle_file2, int *chains, int mode) +{ + STACK_OF(X509) *roots = NULL, *bundle = NULL; + X509_STORE_CTX *xsc = NULL; + X509_STORE *store = NULL; + int verify_err, use_dir; + X509 *leaf = NULL; + + *chains = 0; + use_dir = (mode == MODE_MODERN_VFY_DIR); + + if (!use_dir && !certs_from_file(roots_file, &roots, 1)) + errx(1, "failed to load roots from '%s'", roots_file); + if (!certs_from_file(bundle_file, &bundle, 1)) + errx(1, "failed to load bundle from '%s'", bundle_file); + if (!certs_from_file(bundle_file, &bundle, 0)) + errx(1, "failed to load bundle from '%s'", bundle_file2); + if (sk_X509_num(bundle) < 1) + errx(1, "not enough certs in bundle"); + leaf = sk_X509_shift(bundle); + + if ((xsc = X509_STORE_CTX_new()) == NULL) + errx(1, "X509_STORE_CTX"); + if (use_dir && (store = X509_STORE_new()) == NULL) + errx(1, "X509_STORE"); + if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) { + ERR_print_errors_fp(stderr); + errx(1, "failed to init store context"); + } + + if (use_dir) { + if (!X509_STORE_load_locations(store, NULL, roots_dir)) + errx(1, "failed to set by_dir directory of %s", roots_dir); + } + if (mode == MODE_LEGACY_VFY) + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_LEGACY_VERIFY); + else + X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(xsc), + X509_V_FLAG_LEGACY_VERIFY); + + if (verbose) + X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); + if (!use_dir) + X509_STORE_CTX_set0_trusted_stack(xsc, roots); + + if (X509_verify_cert(xsc) == 1) { + *chains = 1; /* XXX */ + goto done; + } + + verify_err = X509_STORE_CTX_get_error(xsc); + if (verify_err == 0) + errx(1, "Error unset on failure!\n"); + + fprintf(stderr, "failed to verify at %d: %s\n", + X509_STORE_CTX_get_error_depth(xsc), + X509_verify_cert_error_string(verify_err)); + + done: + sk_X509_pop_free(roots, X509_free); + sk_X509_pop_free(bundle, X509_free); + X509_STORE_free(store); + X509_STORE_CTX_free(xsc); + X509_free(leaf); +} + +struct verify_cert_test { + const char *id; + int want_chains; + int failing; + int depth; + int error; +}; + +struct verify_cert_test verify_cert_tests[] = { + { + .id = "1a", + .want_chains = 0, + .depth = 0, + .error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + }, + { + .id = "2a", + .want_chains = 0, + .depth = 1, + .error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + }, + { + .id = "2c", + .want_chains = 0, + .depth = 2, + .error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, + }, +}; + +#define N_VERIFY_CERT_TESTS \ + (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests)) + +static int +verify_cert_test(const char *certs_path, int mode) +{ + char *roots_file, *bundle_file, *bundle_file2, *roots_dir; + struct verify_cert_test *vct; + int failed = 0; + int chains; + size_t i; + + for (i = 0; i < N_VERIFY_CERT_TESTS; i++) { + vct = &verify_cert_tests[i]; + + if (asprintf(&roots_file, "/etc/ssl/cert.pem") == -1) + errx(1, "asprintf"); + if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&bundle_file2, "%s/%s/roots.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&roots_dir, "./%s/roots", vct->id) == -1) + errx(1, "asprintf"); + + fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); + fprintf(stderr, "== depth %d\n", vct->depth); + fprintf(stderr, "== error %d\n", vct->error); + expected_depth = vct->depth; + expected_error = vct->error; + verify_cert(roots_dir, roots_file, bundle_file, bundle_file2, &chains, mode); + if (chains == 0 && vct->want_chains == 0) { + if (seen_error != expected_error) { + fprintf(stderr, "FAIL: expected error %d, got %d\n", + seen_error, expected_error); + failed |= 1; + } + if (seen_depth != expected_depth) { + fprintf(stderr, "FAIL: expected depth %d, got %d\n", + seen_depth, expected_depth); + failed |= 1; + } + } + + if ((mode == MODE_VERIFY && chains == vct->want_chains) || + (chains == 0 && vct->want_chains == 0) || + (chains == 1 && vct->want_chains > 0)) { + fprintf(stderr, "INFO: Succeeded with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (mode == MODE_LEGACY_VFY && vct->failing) + failed |= 1; + } else { + fprintf(stderr, "FAIL: Failed with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (!vct->failing) + failed |= 1; + } + fprintf(stderr, "\n"); + + free(roots_file); + free(bundle_file); + free(bundle_file2); + free(roots_dir); + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + + fprintf(stderr, "\n\nTesting legacy x509_vfy\n"); + failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY); + fprintf(stderr, "\n\nTesting modern x509_vfy\n"); + failed |= verify_cert_test(argv[1], MODE_MODERN_VFY); + + return (failed); +} diff --git a/tests/casttest.c b/tests/casttest.c new file mode 100644 index 0000000..df72caf --- /dev/null +++ b/tests/casttest.c @@ -0,0 +1,197 @@ +/* $OpenBSD: casttest.c,v 1.7 2023/08/20 22:35:52 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include + +static const unsigned char k[16] = { + 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A, +}; + +static const unsigned char in[8] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, +}; + +static int k_len[3] = {16, 10, 5}; +static const unsigned char c[3][8] = { + {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2}, + {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B}, + {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}, +}; +static unsigned char out[80]; + +static const unsigned char in_a[16] = { + 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A, +}; +static const unsigned char in_b[16] = { + 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A, +}; + +static const unsigned char c_a[16] = { + 0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6, + 0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92, +}; +static const unsigned char c_b[16] = { + 0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71, + 0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E, +}; + +int +main(int argc, char *argv[]) +{ + long l; + CAST_KEY key_b; + int i, z, err = 0; + CAST_KEY key; + + for (z = 0; z < 3; z++) { + CAST_set_key(&key, k_len[z], k); + + CAST_ecb_encrypt(in, out, &key, CAST_ENCRYPT); + if (memcmp(out, &(c[z][0]), 8) != 0) { + printf("ecb cast error encrypting for keysize %d\n", + k_len[z]*8); + printf("got :"); + for (i = 0; i < 8; i++) + printf("%02X ", out[i]); + printf("\n"); + printf("expected:"); + for (i = 0; i < 8; i++) + printf("%02X ", c[z][i]); + err = 20; + printf("\n"); + } + + CAST_ecb_encrypt(out, out, &key, CAST_DECRYPT); + if (memcmp(out, in, 8) != 0) { + printf("ecb cast error decrypting for keysize %d\n", + k_len[z]*8); + printf("got :"); + for (i = 0; i < 8; i++) + printf("%02X ", out[i]); + printf("\n"); + printf("expected:"); + for (i = 0; i < 8; i++) + printf("%02X ", in[i]); + printf("\n"); + err = 3; + } + } + if (err == 0) + printf("ecb cast5 ok\n"); + + { + unsigned char out_a[16], out_b[16]; + static char *hex = "0123456789ABCDEF"; + + printf("This test will take some time...."); + fflush(stdout); + memcpy(out_a, in_a, sizeof(in_a)); + memcpy(out_b, in_b, sizeof(in_b)); + i = 1; + + for (l = 0; l < 1000000L; l++) { + CAST_set_key(&key_b, 16, out_b); + CAST_ecb_encrypt(&(out_a[0]), &(out_a[0]), &key_b, + CAST_ENCRYPT); + CAST_ecb_encrypt(&(out_a[8]), &(out_a[8]), &key_b, + CAST_ENCRYPT); + CAST_set_key(&key, 16, out_a); + CAST_ecb_encrypt(&(out_b[0]), &(out_b[0]), &key, + CAST_ENCRYPT); + CAST_ecb_encrypt(&(out_b[8]), &(out_b[8]), &key, + CAST_ENCRYPT); + if ((l & 0xffff) == 0xffff) { + printf("%c", hex[i & 0x0f]); + fflush(stdout); + i++; + } + } + + if ((memcmp(out_a, c_a, sizeof(c_a)) != 0) || + (memcmp(out_b, c_b, sizeof(c_b)) != 0)) { + printf("\n"); + printf("Error\n"); + + printf("A out ="); + for (i = 0; i < 16; i++) + printf("%02X ", out_a[i]); + printf("\nactual="); + for (i = 0; i < 16; i++) + printf("%02X ", c_a[i]); + printf("\n"); + + printf("B out ="); + for (i = 0; i < 16; i++) + printf("%02X ", out_b[i]); + printf("\nactual="); + for (i = 0; i < 16; i++) + printf("%02X ", c_b[i]); + printf("\n"); + } else + printf(" ok\n"); + } + + exit(err); +} diff --git a/tests/chacha20_poly1305_tests.txt b/tests/chacha20_poly1305_tests.txt new file mode 100644 index 0000000..7656247 --- /dev/null +++ b/tests/chacha20_poly1305_tests.txt @@ -0,0 +1,576 @@ +# Test vector from RFC 8439 Section 2.8.1. + +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." +AD: 50515253c0c1c2c3c4c5c6c7 +CT: d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116 +TAG: 1ae10b594f09e26a7e902ecbd0600691 + +# Test padding AD with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "1" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: dac9c841c168379dcf8f2bb8e22d6da2 + +# Test padding IN with 15 zeros in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "1" +AD: "123456789abcdef0" +CT: ae +TAG: 3ed2f824f901a8994052f852127c196a + +# Test padding AD with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef0" +AD: "123456789abcdef" +CT: ae49da6934cb77822c83ed9852e46c9e +TAG: 2e9c9b1689adb5ec444002eb920efb66 + +# Test padding IN with 1 zero in the tag calculation. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: 070000004041424344454647 +IN: "123456789abcdef" +AD: "123456789abcdef0" +CT: ae49da6934cb77822c83ed9852e46c +TAG: 05b2937f8bbc64fed21f0fb74cd7147c + +# Test maximal nonce value. +KEY: 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f +NONCE: ffffffffffffffffffffffff +IN: "123456789abcdef0" +AD: "123456789abcdef0" +CT: e275aeb341e1fc9a70c4fd4496fc7cdb +TAG: 41acd0560ea6843d3e5d4e5babf6e946 + +KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6 +NONCE: 000000003de9c0da2bd7f91e +IN: "" +AD: "" +CT: "" +TAG: 5a6e21f4ba6dbee57380e79e79c30def + +KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5 +NONCE: 000000001e8b4c510f5ca083 +IN: 8c8419bc27 +AD: 34ab88c265 +CT: 1a7c2f33f5 +TAG: 2a63876a887f4f080c9df418813fc1fd + +KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007 +NONCE: 00000000cd7cf67be39c794a +IN: 86d09974840bded2a5ca +AD: 87e229d4500845a079c0 +CT: e3e446f7ede9a19b62a4 +TAG: 356d9eda66d08016b853d87c08b5c1b3 + +KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3 +NONCE: 000000001d12d6d91848f2ea +IN: 537a645387f22d6f6dbbea568d3feb +AD: bef267c99aec8af56bc238612bfea6 +CT: 281a366705c5a24b94e56146681e44 +TAG: 59143dab187449060a3ec2a1681613cc + +KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685 +NONCE: 000000002bca0e59e39508d3 +IN: b76733895c871edd728a45ed1a21f15a9597d49d +AD: cc1243ea54272db602fb0853c8e7027c56338b6c +CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858 +TAG: 219b4252deb16a43b292165aabc5d5ce + +KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c +NONCE: 0000000013ce7382734c4a71 +IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb +AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9 +CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f +TAG: 7ae32f186cf9ec59b41b764b34307d4f + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5919a + +KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14 +NONCE: 00000000c7f2f7a233104a2d +IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338 +AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb +CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe +TAG: 63c2b4e0973096299488b0a66ffa54c1 + +KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc +NONCE: 0000000088049f44ba61b88f +IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89 +AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc +CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638 +TAG: 4461139c4055333106cf7f7556fd4171 + +KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48 +NONCE: 00000000066215be6567377a +IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d +AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb +CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346 +TAG: b2ad07b86aca1b3ab34033c12d6a08cc + +KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde +NONCE: 000000003f2d44e7b352360f +IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344 +AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb +CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943 +TAG: 6de01091d749f189c4e25aa315b31495 + +KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a +NONCE: 000000001b9cd73d2fc3cb8e +IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f +AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c +CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd +TAG: 0887ec7d5e1a4e532746ec247a30825a + +KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97 +NONCE: 00000000d69e54badec11560 +IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276 +AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9 +CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320 +TAG: a27f18846f5a4f7fcc724656c91cf4f3 + +KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639 +NONCE: 0000000088b54b28d6da8c81 +IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284 +AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575 +CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d +TAG: 854cbb42bade86a09597482c8604681a + +KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13 +NONCE: 00000000c5c8009459b9e31a +IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab +AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce +CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0 +TAG: 2865d2a26f413cc92416340f9491e1be + +KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020 +NONCE: 00000000ce5cf6fef84d0010 +IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2 +AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142 +CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba +TAG: 1414f1b91966340417c38226ccca9d3d + +KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4 +NONCE: 000000008b6ba494c540fba4 +IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5 +AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f +CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945 +TAG: c5ca34599c6a8b357c6723ee12b24da8 + +KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d +NONCE: 00000000d3875d1b6c808353 +IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c +AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280 +CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e +TAG: e84211b6cfd43543f8b1b4db07a494d1 + +KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c +NONCE: 0000000040b32e3fdc646453 +IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14 +AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd +CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51 +TAG: 55e025a1eb87bc84d4be00c775c92ad2 + +KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866 +NONCE: 000000009559bd08718b75af +IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9 +AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2 +CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37 +TAG: ab1d8a5a1f3eda9b5609c0028737477f + +KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf +NONCE: 00000000d9dae2ea8d2ffc31 +IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23 +AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06 +CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef +TAG: 1c6bdff7d8b9554dc7bf40e50b37d352 + +KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507 +NONCE: 000000008a81c92b37221f2f +IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97 +AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075 +CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661 +TAG: 689a141bc11159d306dad7a4ecf6ad9d + +KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a +NONCE: 000000003c4c6f0281841aff +IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83 +AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92 +CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40 +TAG: 780cc54bb6f1c9b78545c1562cd9d550 + +KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466 +NONCE: 000000006255bf5c71bb27d1 +IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44 +AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3 +CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe +TAG: 2ecccea4607d14dbb2d2475792aeb468 + +KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638 +NONCE: 00000000a28a6dedf3f2b01a +IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212 +AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2 +CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf +TAG: 17ec6cf2b172f01e3c456ad047196805 + +KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9 +NONCE: 0000000056fb4923a97e9320 +IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd +AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf +CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787 +TAG: d29a8968067aeb457ffc114c3a9efb95 + +KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54 +NONCE: 000000002f4a5ca096a4faf8 +IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd +AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7 +CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86 +TAG: 28a5284696ed82714eaa94c9ebe6e815 + +KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0 +NONCE: 00000000b5e35fe3398efa34 +IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc +AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5 +CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf +TAG: 4ef49e8a0c2ef85826d7f03e81c577f2 + +KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401 +NONCE: 00000000f0c4a213a6168aab +IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98 +AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd +CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43 +TAG: fad7d5a5193dfb121c68529ba8c0c35d + +KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b +NONCE: 000000007968379a8ce88117 +IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa +AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3 +CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c +TAG: 96ae06cd7c72456e5568a42317046158 + +KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714 +NONCE: 00000000fdd913a321c40eb0 +IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814 +AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca +CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e +TAG: bcf523a9bcf772e157941753c6d7401e + +KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29 +NONCE: 00000000a6c191f6d1818f8e +IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303 +AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815 +CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092 +TAG: bd05336ed6426de412aac37661953052 + +KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99 +NONCE: 000000007b3ae31f8f938251 +IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d +AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485 +CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74 +TAG: d48657033095db3f873c33445fec8d35 + +KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7 +NONCE: 000000002358ae0ce3fb8e9f +IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac +AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f +CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23 +TAG: 298f84c8312029a7b1f38c5ea6021f57 + +KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83 +NONCE: 00000000263a2fc06a2872e7 +IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3 +AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113 +CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4 +TAG: 6234e81e089b779d0d509d14e566b5d7 + +KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe +NONCE: 00000000b6aef34c75818e7c +IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc +AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c +CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af +TAG: e3b4192f6e50528c4f4f70267f094c56 + +KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817 +NONCE: 00000000cd7ed9e70f608613 +IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83 +AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93 +CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400 +TAG: 874875c9a0ba3060a0680291c3dc85a2 + +KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f +NONCE: 00000000c965d578ba91d227 +IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280 +AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43 +CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6 +TAG: f6dcad5412b95994f5e4d6829c2eba98 + +KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663 +NONCE: 000000005c6da1259451119a +IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a +AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c +CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae +TAG: 90fcc2544880250f1c3abe8a3761ba08 + +KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a +NONCE: 00000000760de0f7b7cb67e2 +IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625 +AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f +CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b +TAG: 7fa630c9bcb455e89f13d7a99d5e8dbe + +KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1 +NONCE: 0000000065a748004b352ba6 +IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950 +AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df +CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5 +TAG: 82c6194de4d27aac4c54b023b9831634 + +KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2 +NONCE: 00000000c7091f6afbbeb360 +IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f +AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d +CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9 +TAG: aeb0a4eb29886f0a7a12ec0516bd4af5 + +KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559 +NONCE: 000000007858dfc084fe4b0f +IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1 +AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b +CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6 +TAG: 61c6d4d6918b04fc1b72a7a0e9a3b799 + +KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0 +NONCE: 0000000006699d245916686d +IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de +AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536 +CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f +TAG: b9fec6da464c7b85b2a4726694562fe9 + +KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52 +NONCE: 000000009c27065c3ef2d522 +IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a +AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df +CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125 +TAG: 94118ccc68de1921d480aab43d1ef0d1 + +KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414 +NONCE: 000000009fb909169bc9f4e9 +IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3 +AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a +CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b +TAG: 8980e8e4fe796428b733f4f8e1954a45 + +KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c +NONCE: 000000007ac93e754e290323 +IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36 +AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9 +CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775 +TAG: 16c972829819b8fb030b2c5f40dab717 + +KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7 +NONCE: 0000000023b2f9068b2c4c85 +IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1 +AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5 +CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828 +TAG: c549aa944d6d97e52e0793ed572682c0 + +KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4 +NONCE: 000000000b3f16f898a5a7d5 +IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082 +AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc +CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2 +TAG: baf9a51180f172e5c0cc2c946ce55055 + +KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596 +NONCE: 00000000874144dbf648b325 +IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720 +AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e +CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1 +TAG: eb9b2ee43e9a3ae1e33561800169d868 + +KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc +NONCE: 000000007f5e560a1de434ba +IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce +AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83 +CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b +TAG: e0bf9b6837428843f5a233ee5ddb8a1e + +KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba +NONCE: 00000000d08d486620ed2e84 +IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe +AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe +CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06 +TAG: 2e8eb9ff4467c0f61c2abf6ca10893ef + +KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc +NONCE: 0000000047738ac8f10f2c3a +IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f +AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4 +CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f +TAG: ce507bdb0c71f8e89f5078495f7995b8 + +KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098 +NONCE: 000000000808da8292dc14e0 +IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046 +AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051 +CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb +TAG: 73b00b1705602479aab944dcc1b282a2 + +KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d +NONCE: 0000000077d185aaf715aa48 +IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578 +AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462 +CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14 +TAG: 69302888812eea030d621b640e7bcf7c + +KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb +NONCE: 000000007d0ced2fdb1c9173 +IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b +AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6 +CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4 +TAG: 19bbacfac768bb0ce71e39c5d4d3e9a0 + +KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb +NONCE: 000000002ccbf0d6c40cb302 +IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70 +AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860 +CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50 +TAG: 0fa4cb2bab84336409aa4349ab99a8bd + +KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0 +NONCE: 00000000a0f73297b87f5deb +IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d +AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3 +CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc +TAG: 9bd8b7743c056bb2334833afd6143e18 + +KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b +NONCE: 00000000e7a87e6bf6b5a354 +IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895 +AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8 +CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6 +TAG: ee1ec36804e1d5cdbddb52608c711fd8 + +KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4 +NONCE: 00000000db37c0a405b4626d +IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422 +AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6 +CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f +TAG: 296a397d280d026fc3627f4718971be9 + +# Tag truncation tests. + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c2 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f3 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f37465 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a8413 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a841386 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a5 + +KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865 +NONCE: 000000005d9856060c54ab06 +IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e +AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51 +CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36 +TAG: d3f7b9c295f374651a84138648a591 + diff --git a/tests/chachatest.c b/tests/chachatest.c new file mode 100644 index 0000000..4e15974 --- /dev/null +++ b/tests/chachatest.c @@ -0,0 +1,509 @@ +/* $OpenBSD: chachatest.c,v 1.6 2019/01/22 00:59:21 dlg Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +struct chacha_tv { + const char *desc; + const unsigned char key[32]; + const unsigned char iv[8]; + const size_t len; + const unsigned char out[512]; +}; + +/* + * Test vectors from: + * http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-01 + */ +struct chacha_tv chacha_test_vectors[] = { + { + "TC1: All zero key and IV", + { + 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, + }, + 64, + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86, + }, + }, + { + "TC2: Single bit in key set, all zero IV", + { + 0x01, 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, + }, + 64, + { + 0xc5, 0xd3, 0x0a, 0x7c, 0xe1, 0xec, 0x11, 0x93, + 0x78, 0xc8, 0x4f, 0x48, 0x7d, 0x77, 0x5a, 0x85, + 0x42, 0xf1, 0x3e, 0xce, 0x23, 0x8a, 0x94, 0x55, + 0xe8, 0x22, 0x9e, 0x88, 0x8d, 0xe8, 0x5b, 0xbd, + 0x29, 0xeb, 0x63, 0xd0, 0xa1, 0x7a, 0x5b, 0x99, + 0x9b, 0x52, 0xda, 0x22, 0xbe, 0x40, 0x23, 0xeb, + 0x07, 0x62, 0x0a, 0x54, 0xf6, 0xfa, 0x6a, 0xd8, + 0x73, 0x7b, 0x71, 0xeb, 0x04, 0x64, 0xda, 0xc0, + }, + }, + { + "TC3: Single bit in IV set, all zero key", + { + 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, + }, + { + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + 64, + { + 0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb, + 0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80, + 0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac, + 0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32, + 0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c, + 0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54, + 0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d, + 0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b + }, + }, + { + "TC4: All bits in key and IV are set", + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + 64, + { + 0xd9, 0xbf, 0x3f, 0x6b, 0xce, 0x6e, 0xd0, 0xb5, + 0x42, 0x54, 0x55, 0x77, 0x67, 0xfb, 0x57, 0x44, + 0x3d, 0xd4, 0x77, 0x89, 0x11, 0xb6, 0x06, 0x05, + 0x5c, 0x39, 0xcc, 0x25, 0xe6, 0x74, 0xb8, 0x36, + 0x3f, 0xea, 0xbc, 0x57, 0xfd, 0xe5, 0x4f, 0x79, + 0x0c, 0x52, 0xc8, 0xae, 0x43, 0x24, 0x0b, 0x79, + 0xd4, 0x90, 0x42, 0xb7, 0x77, 0xbf, 0xd6, 0xcb, + 0x80, 0xe9, 0x31, 0x27, 0x0b, 0x7f, 0x50, 0xeb, + }, + }, + { + "TC5: Every even bit set in key and IV", + { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + }, + { + 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, + }, + 64, + { + 0xbe, 0xa9, 0x41, 0x1a, 0xa4, 0x53, 0xc5, 0x43, + 0x4a, 0x5a, 0xe8, 0xc9, 0x28, 0x62, 0xf5, 0x64, + 0x39, 0x68, 0x55, 0xa9, 0xea, 0x6e, 0x22, 0xd6, + 0xd3, 0xb5, 0x0a, 0xe1, 0xb3, 0x66, 0x33, 0x11, + 0xa4, 0xa3, 0x60, 0x6c, 0x67, 0x1d, 0x60, 0x5c, + 0xe1, 0x6c, 0x3a, 0xec, 0xe8, 0xe6, 0x1e, 0xa1, + 0x45, 0xc5, 0x97, 0x75, 0x01, 0x7b, 0xee, 0x2f, + 0xa6, 0xf8, 0x8a, 0xfc, 0x75, 0x80, 0x69, 0xf7, + }, + }, + { + "TC6: Every odd bit set in key and IV", + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + 64, + { + 0x9a, 0xa2, 0xa9, 0xf6, 0x56, 0xef, 0xde, 0x5a, + 0xa7, 0x59, 0x1c, 0x5f, 0xed, 0x4b, 0x35, 0xae, + 0xa2, 0x89, 0x5d, 0xec, 0x7c, 0xb4, 0x54, 0x3b, + 0x9e, 0x9f, 0x21, 0xf5, 0xe7, 0xbc, 0xbc, 0xf3, + 0xc4, 0x3c, 0x74, 0x8a, 0x97, 0x08, 0x88, 0xf8, + 0x24, 0x83, 0x93, 0xa0, 0x9d, 0x43, 0xe0, 0xb7, + 0xe1, 0x64, 0xbc, 0x4d, 0x0b, 0x0f, 0xb2, 0x40, + 0xa2, 0xd7, 0x21, 0x15, 0xc4, 0x80, 0x89, 0x06, + }, + }, + { + "TC7: Sequence patterns in key and IV", + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, + }, + { + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, + }, + 64, + { + 0x9f, 0xad, 0xf4, 0x09, 0xc0, 0x08, 0x11, 0xd0, + 0x04, 0x31, 0xd6, 0x7e, 0xfb, 0xd8, 0x8f, 0xba, + 0x59, 0x21, 0x8d, 0x5d, 0x67, 0x08, 0xb1, 0xd6, + 0x85, 0x86, 0x3f, 0xab, 0xbb, 0x0e, 0x96, 0x1e, + 0xea, 0x48, 0x0f, 0xd6, 0xfb, 0x53, 0x2b, 0xfd, + 0x49, 0x4b, 0x21, 0x51, 0x01, 0x50, 0x57, 0x42, + 0x3a, 0xb6, 0x0a, 0x63, 0xfe, 0x4f, 0x55, 0xf7, + 0xa2, 0x12, 0xe2, 0x16, 0x7c, 0xca, 0xb9, 0x31, + }, + }, + { + "TC8: key: 'All your base are belong to us!, IV: 'IETF2013'", + { + 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78, + 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35, + 0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb, + 0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d, + }, + { + 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21, + }, + 64, + { + 0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9, + 0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06, + 0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00, + 0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf, + 0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd, + 0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f, + 0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f, + 0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92, + }, + }, +}; + +#define N_VECTORS (sizeof(chacha_test_vectors) / sizeof(*chacha_test_vectors)) + +/* Single-shot ChaCha20 using CRYPTO_chacha_20 interface. */ +static void +crypto_chacha_20_test(struct chacha_tv *tv, unsigned char *out, + unsigned char *in) +{ + CRYPTO_chacha_20(out, in, tv->len, tv->key, tv->iv, 0); +} + +/* Single-shot ChaCha20 using the ChaCha interface. */ +static void +chacha_ctx_full_test(struct chacha_tv *tv, unsigned char *out, + unsigned char *in) +{ + ChaCha_ctx ctx; + + ChaCha_set_key(&ctx, tv->key, 256); + ChaCha_set_iv(&ctx, tv->iv, NULL); + ChaCha(&ctx, out, in, tv->len); +} + +/* ChaCha20 with partial writes using the Chacha interface. */ +static void +chacha_ctx_partial_test(struct chacha_tv *tv, unsigned char *out, + unsigned char *in) +{ + ChaCha_ctx ctx; + int len, size = 0; + + ChaCha_set_key(&ctx, tv->key, 256); + ChaCha_set_iv(&ctx, tv->iv, NULL); + len = tv->len - 1; + while (len > 1) { + size = len / 2; + ChaCha(&ctx, out, in, size); + in += size; + out += size; + len -= size; + } + ChaCha(&ctx, out, in, len + 1); +} + +/* ChaCha20 with single byte writes using the Chacha interface. */ +static void +chacha_ctx_single_test(struct chacha_tv *tv, unsigned char *out, + unsigned char *in) +{ + ChaCha_ctx ctx; + size_t i; + + ChaCha_set_key(&ctx, tv->key, 256); + ChaCha_set_iv(&ctx, tv->iv, NULL); + for (i = 0; i < tv->len; i++) + ChaCha(&ctx, out + i, in + i, 1); +} + +struct chacha_test_function { + char *name; + void (*func)(struct chacha_tv *, unsigned char *, unsigned char *); +}; + +struct chacha_test_function chacha_test_functions[] = { + {"crypto_chacha_20_test", crypto_chacha_20_test}, + {"chacha_ctx_full_test", chacha_ctx_full_test}, + {"chacha_ctx_partial_test", chacha_ctx_partial_test}, + {"chacha_ctx_single_test", chacha_ctx_single_test}, +}; + +#define N_FUNCS (sizeof(chacha_test_functions) / sizeof(*chacha_test_functions)) + +/* draft-arciszewski-xchacha-02 test vectors */ +static int +crypto_hchacha_20_test(void) +{ + static const unsigned char 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 + }; + static const unsigned char nonce[16] = { + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x41, 0x59, 0x27, + }; + static const unsigned char result[32] = { + 0x82, 0x41, 0x3b, 0x42, 0x27, 0xb2, 0x7b, 0xfe, + 0xd3, 0x0e, 0x42, 0x50, 0x8a, 0x87, 0x7d, 0x73, + 0xa0, 0xf9, 0xe4, 0xd5, 0x8a, 0x74, 0xa8, 0x53, + 0xc1, 0x2e, 0xc4, 0x13, 0x26, 0xd3, 0xec, 0xdc, + }; + unsigned char out[32]; + int failed = 0; + size_t k; + + CRYPTO_hchacha_20(out, key, nonce); + + if (memcmp(out, result, sizeof(out)) != 0) { + printf("HChaCha20 failed!\n"); + + printf("Got:\t"); + for (k = 0; k < sizeof(out); k++) + printf("%2.2x", out[k]); + printf("\n"); + + printf("Want:\t"); + for (k = 0; k < sizeof(result); k++) + printf("%2.2x", result[k]); + printf("\n"); + + failed = 1; + } + + return (failed); +} + +static int +crypto_xchacha_20_test(void) +{ + static const unsigned char key[32] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + }; + static const unsigned char iv[24] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x58 + }; + static const unsigned char plain[] = { + 0x54, 0x68, 0x65, 0x20, 0x64, 0x68, 0x6f, 0x6c, + 0x65, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x6e, 0x6f, + 0x75, 0x6e, 0x63, 0x65, 0x64, 0x20, 0x22, 0x64, + 0x6f, 0x6c, 0x65, 0x22, 0x29, 0x20, 0x69, 0x73, + 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6b, 0x6e, + 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x41, 0x73, 0x69, 0x61, 0x74, + 0x69, 0x63, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x20, + 0x64, 0x6f, 0x67, 0x2c, 0x20, 0x72, 0x65, 0x64, + 0x20, 0x64, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x77, 0x68, 0x69, 0x73, 0x74, 0x6c, + 0x69, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x67, 0x2e, + 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x20, 0x47, 0x65, 0x72, 0x6d, 0x61, + 0x6e, 0x20, 0x73, 0x68, 0x65, 0x70, 0x68, 0x65, + 0x72, 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6c, + 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6d, 0x6f, 0x72, + 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x61, + 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x6c, 0x65, + 0x67, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x78, + 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x68, + 0x69, 0x67, 0x68, 0x6c, 0x79, 0x20, 0x65, 0x6c, + 0x75, 0x73, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x73, 0x6b, 0x69, 0x6c, 0x6c, 0x65, + 0x64, 0x20, 0x6a, 0x75, 0x6d, 0x70, 0x65, 0x72, + 0x20, 0x69, 0x73, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77, + 0x69, 0x74, 0x68, 0x20, 0x77, 0x6f, 0x6c, 0x76, + 0x65, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x79, 0x6f, + 0x74, 0x65, 0x73, 0x2c, 0x20, 0x6a, 0x61, 0x63, + 0x6b, 0x61, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x66, 0x6f, 0x78, 0x65, 0x73, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, + 0x61, 0x78, 0x6f, 0x6e, 0x6f, 0x6d, 0x69, 0x63, + 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, + 0x43, 0x61, 0x6e, 0x69, 0x64, 0x61, 0x65, 0x2e, + }; + static const unsigned char cipher[] = { + 0x45, 0x59, 0xab, 0xba, 0x4e, 0x48, 0xc1, 0x61, + 0x02, 0xe8, 0xbb, 0x2c, 0x05, 0xe6, 0x94, 0x7f, + 0x50, 0xa7, 0x86, 0xde, 0x16, 0x2f, 0x9b, 0x0b, + 0x7e, 0x59, 0x2a, 0x9b, 0x53, 0xd0, 0xd4, 0xe9, + 0x8d, 0x8d, 0x64, 0x10, 0xd5, 0x40, 0xa1, 0xa6, + 0x37, 0x5b, 0x26, 0xd8, 0x0d, 0xac, 0xe4, 0xfa, + 0xb5, 0x23, 0x84, 0xc7, 0x31, 0xac, 0xbf, 0x16, + 0xa5, 0x92, 0x3c, 0x0c, 0x48, 0xd3, 0x57, 0x5d, + 0x4d, 0x0d, 0x2c, 0x67, 0x3b, 0x66, 0x6f, 0xaa, + 0x73, 0x10, 0x61, 0x27, 0x77, 0x01, 0x09, 0x3a, + 0x6b, 0xf7, 0xa1, 0x58, 0xa8, 0x86, 0x42, 0x92, + 0xa4, 0x1c, 0x48, 0xe3, 0xa9, 0xb4, 0xc0, 0xda, + 0xec, 0xe0, 0xf8, 0xd9, 0x8d, 0x0d, 0x7e, 0x05, + 0xb3, 0x7a, 0x30, 0x7b, 0xbb, 0x66, 0x33, 0x31, + 0x64, 0xec, 0x9e, 0x1b, 0x24, 0xea, 0x0d, 0x6c, + 0x3f, 0xfd, 0xdc, 0xec, 0x4f, 0x68, 0xe7, 0x44, + 0x30, 0x56, 0x19, 0x3a, 0x03, 0xc8, 0x10, 0xe1, + 0x13, 0x44, 0xca, 0x06, 0xd8, 0xed, 0x8a, 0x2b, + 0xfb, 0x1e, 0x8d, 0x48, 0xcf, 0xa6, 0xbc, 0x0e, + 0xb4, 0xe2, 0x46, 0x4b, 0x74, 0x81, 0x42, 0x40, + 0x7c, 0x9f, 0x43, 0x1a, 0xee, 0x76, 0x99, 0x60, + 0xe1, 0x5b, 0xa8, 0xb9, 0x68, 0x90, 0x46, 0x6e, + 0xf2, 0x45, 0x75, 0x99, 0x85, 0x23, 0x85, 0xc6, + 0x61, 0xf7, 0x52, 0xce, 0x20, 0xf9, 0xda, 0x0c, + 0x09, 0xab, 0x6b, 0x19, 0xdf, 0x74, 0xe7, 0x6a, + 0x95, 0x96, 0x74, 0x46, 0xf8, 0xd0, 0xfd, 0x41, + 0x5e, 0x7b, 0xee, 0x2a, 0x12, 0xa1, 0x14, 0xc2, + 0x0e, 0xb5, 0x29, 0x2a, 0xe7, 0xa3, 0x49, 0xae, + 0x57, 0x78, 0x20, 0xd5, 0x52, 0x0a, 0x1f, 0x3f, + 0xb6, 0x2a, 0x17, 0xce, 0x6a, 0x7e, 0x68, 0xfa, + 0x7c, 0x79, 0x11, 0x1d, 0x88, 0x60, 0x92, 0x0b, + 0xc0, 0x48, 0xef, 0x43, 0xfe, 0x84, 0x48, 0x6c, + 0xcb, 0x87, 0xc2, 0x5f, 0x0a, 0xe0, 0x45, 0xf0, + 0xcc, 0xe1, 0xe7, 0x98, 0x9a, 0x9a, 0xa2, 0x20, + 0xa2, 0x8b, 0xdd, 0x48, 0x27, 0xe7, 0x51, 0xa2, + 0x4a, 0x6d, 0x5c, 0x62, 0xd7, 0x90, 0xa6, 0x63, + 0x93, 0xb9, 0x31, 0x11, 0xc1, 0xa5, 0x5d, 0xd7, + 0x42, 0x1a, 0x10, 0x18, 0x49, 0x74, 0xc7, 0xc5, + }; + unsigned char out[sizeof(cipher)]; + int failed = 0; + size_t k; + + CRYPTO_xchacha_20(out, plain, sizeof(out), key, iv); + + if (memcmp(out, cipher, sizeof(out)) != 0) { + printf("XChaCha20 failed!\n"); + + printf("Got:\t"); + for (k = 0; k < sizeof(out); k++) + printf("%2.2x", out[k]); + printf("\n"); + + printf("Want:\t"); + for (k = 0; k < sizeof(cipher); k++) + printf("%2.2x", cipher[k]); + printf("\n"); + + failed = 1; + } + + return (failed); +} + +int +main(int argc, char **argv) +{ + struct chacha_tv *tv; + unsigned char *in, *out; + size_t i, j, k; + int failed = 0; + + for (i = 0; i < N_VECTORS; i++) { + tv = &chacha_test_vectors[i]; + + for (j = 0; j < N_FUNCS; j++) { + in = calloc(1, tv->len); + if (in == NULL) + errx(1, "calloc in"); + out = calloc(1, tv->len); + if (out == NULL) + errx(1, "calloc out"); + + chacha_test_functions[j].func(tv, out, in); + + if (memcmp(out, tv->out, tv->len) != 0) { + printf("ChaCha %s failed for \"%s\"!\n", + chacha_test_functions[j].name, tv->desc); + + printf("Got:\t"); + for (k = 0; k < tv->len; k++) + printf("%2.2x", out[k]); + printf("\n"); + + printf("Want:\t"); + for (k = 0; k < tv->len; k++) + printf("%2.2x", tv->out[k]); + printf("\n"); + + failed = 1; + } + + free(in); + free(out); + } + } + + if (crypto_hchacha_20_test() != 0) + failed = 1; + + if (crypto_xchacha_20_test() != 0) + failed = 1; + + return failed; +} diff --git a/tests/cipher_list.c b/tests/cipher_list.c new file mode 100644 index 0000000..c715f60 --- /dev/null +++ b/tests/cipher_list.c @@ -0,0 +1,231 @@ +/* $OpenBSD: cipher_list.c,v 1.14 2022/12/17 16:05:28 jsing Exp $ */ +/* + * Copyright (c) 2015 Doug Hogan + * Copyright (c) 2015 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Test TLS ssl bytes (aka cipher suites) to cipher list and back. + * + * TLSv1.0 - RFC 2246 section 7.4.1.2 (ClientHello struct) + * TLSv1.1 - RFC 4346 section 7.4.1.2 (ClientHello struct) + * TLSv1.2 - RFC 5246 section 7.4.1.2 (ClientHello struct) + * + * In all of these standards, the relevant structures are: + * + * uint8 CipherSuite[2]; + * + * struct { + * ... + * CipherSuite cipher_suites<2..2^16-2> + * ... + * } ClientHello; + */ + +#include + +#include +#include + +#include "ssl_local.h" + +#include "tests.h" + +static uint8_t cipher_bytes[] = { + 0xcc, 0xa8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ + 0xcc, 0xa9, /* ECDHE-RSA-CHACHA20-POLY1305 */ + 0xcc, 0xaa, /* DHE-RSA-CHACHA20-POLY1305 */ + 0x00, 0x9c, /* AES128-GCM-SHA256 */ + 0x00, 0x3d, /* AES256-SHA256 */ +}; + +static uint8_t cipher_bytes_seclevel3[] = { + 0xcc, 0xa8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ + 0xcc, 0xa9, /* ECDHE-RSA-CHACHA20-POLY1305 */ + 0xcc, 0xaa, /* DHE-RSA-CHACHA20-POLY1305 */ +}; + +static uint16_t cipher_values[] = { + 0xcca8, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ + 0xcca9, /* ECDHE-RSA-CHACHA20-POLY1305 */ + 0xccaa, /* DHE-RSA-CHACHA20-POLY1305 */ + 0x009c, /* AES128-GCM-SHA256 */ + 0x003d, /* AES256-SHA256 */ +}; + +#define N_CIPHERS (sizeof(cipher_bytes) / 2) + +static int +ssl_bytes_to_list_alloc(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) +{ + SSL_CIPHER *cipher; + uint16_t value; + CBS cbs; + int i; + + CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes)); + + *ciphers = ssl_bytes_to_cipher_list(s, &cbs); + CHECK(*ciphers != NULL); + CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); + for (i = 0; i < sk_SSL_CIPHER_num(*ciphers); i++) { + cipher = sk_SSL_CIPHER_value(*ciphers, i); + CHECK(cipher != NULL); + value = SSL_CIPHER_get_value(cipher); + CHECK(value == cipher_values[i]); + } + + return 1; +} + +static int +ssl_list_to_bytes_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers, + const uint8_t *cb, size_t cb_len) +{ + CBB cbb; + unsigned char *buf = NULL; + size_t buflen, outlen; + int ret = 0; + + /* Space for cipher bytes, plus reneg SCSV and two spare bytes. */ + CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); + buflen = cb_len + 2 + 2; + CHECK((buf = calloc(1, buflen)) != NULL); + + /* Clear renegotiate so it adds SCSV */ + s->renegotiate = 0; + + CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen)); + CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb)); + CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen)); + + CHECK_GOTO(outlen > 0 && outlen == cb_len + 2); + CHECK_GOTO(memcmp(buf, cb, cb_len) == 0); + CHECK_GOTO(buf[buflen - 4] == 0x00 && buf[buflen - 3] == 0xff); + CHECK_GOTO(buf[buflen - 2] == 0x00 && buf[buflen - 1] == 0x00); + + ret = 1; + + err: + free(buf); + return ret; +} + +static int +ssl_list_to_bytes_no_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers, + const uint8_t *cb, size_t cb_len) +{ + CBB cbb; + unsigned char *buf = NULL; + size_t buflen, outlen; + int ret = 0; + + /* Space for cipher bytes and two spare bytes */ + CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); + buflen = cb_len + 2; + CHECK((buf = calloc(1, buflen)) != NULL); + buf[buflen - 2] = 0xfe; + buf[buflen - 1] = 0xab; + + /* Set renegotiate so it doesn't add SCSV */ + s->renegotiate = 1; + + CHECK_GOTO(CBB_init_fixed(&cbb, buf, buflen)); + CHECK_GOTO(ssl_cipher_list_to_bytes(s, *ciphers, &cbb)); + CHECK_GOTO(CBB_finish(&cbb, NULL, &outlen)); + + CHECK_GOTO(outlen > 0 && outlen == cb_len); + CHECK_GOTO(memcmp(buf, cb, cb_len) == 0); + CHECK_GOTO(buf[buflen - 2] == 0xfe && buf[buflen - 1] == 0xab); + + ret = 1; + + err: + free(buf); + return ret; +} + +static int +ssl_bytes_to_list_invalid(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) +{ + uint8_t empty_cipher_bytes[] = {0}; + CBS cbs; + + sk_SSL_CIPHER_free(*ciphers); + + /* Invalid length: CipherSuite is 2 bytes so it must be even */ + CBS_init(&cbs, cipher_bytes, sizeof(cipher_bytes) - 1); + *ciphers = ssl_bytes_to_cipher_list(s, &cbs); + CHECK(*ciphers == NULL); + + /* Invalid length: cipher_suites must be at least 2 */ + CBS_init(&cbs, empty_cipher_bytes, sizeof(empty_cipher_bytes)); + *ciphers = ssl_bytes_to_cipher_list(s, &cbs); + CHECK(*ciphers == NULL); + + return 1; +} + +int +main(void) +{ + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CTX *ctx = NULL; + SSL *s = NULL; + int rv = 1; + + SSL_library_init(); + + /* Use TLSv1.2 client to get all ciphers. */ + CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL); + CHECK_GOTO((s = SSL_new(ctx)) != NULL); + SSL_set_security_level(s, 2); + + if (!ssl_bytes_to_list_alloc(s, &ciphers)) + goto err; + if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes, + sizeof(cipher_bytes))) + goto err; + if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes, + sizeof(cipher_bytes))) + goto err; + if (!ssl_bytes_to_list_invalid(s, &ciphers)) + goto err; + + sk_SSL_CIPHER_free(ciphers); + ciphers = NULL; + + SSL_set_security_level(s, 3); + if (!ssl_bytes_to_list_alloc(s, &ciphers)) + goto err; + if (!ssl_list_to_bytes_scsv(s, &ciphers, cipher_bytes_seclevel3, + sizeof(cipher_bytes_seclevel3))) + goto err; + if (!ssl_list_to_bytes_no_scsv(s, &ciphers, cipher_bytes_seclevel3, + sizeof(cipher_bytes_seclevel3))) + goto err; + + rv = 0; + + err: + sk_SSL_CIPHER_free(ciphers); + SSL_CTX_free(ctx); + SSL_free(s); + + if (!rv) + printf("PASS %s\n", __FILE__); + + return rv; +} diff --git a/tests/cipherstest.c b/tests/cipherstest.c new file mode 100644 index 0000000..c43939d --- /dev/null +++ b/tests/cipherstest.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 2015, 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +int ssl3_num_ciphers(void); +const SSL_CIPHER *ssl3_get_cipher(unsigned int u); + +int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str); + +static inline int +ssl_aes_is_accelerated(void) +{ +#if defined(__i386__) || defined(__x86_64__) + return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); +#else + return (0); +#endif +} + +static int +check_cipher_order(void) +{ + unsigned long id, prev_id = 0; + const SSL_CIPHER *cipher; + int num_ciphers; + int i; + + num_ciphers = ssl3_num_ciphers(); + + for (i = 1; i <= num_ciphers; i++) { + /* + * For some reason, ssl3_get_cipher() returns ciphers in + * reverse order. + */ + if ((cipher = ssl3_get_cipher(num_ciphers - i)) == NULL) { + fprintf(stderr, "FAIL: ssl3_get_cipher(%d) returned " + "NULL\n", i); + return 1; + } + if ((id = SSL_CIPHER_get_id(cipher)) <= prev_id) { + fprintf(stderr, "FAIL: ssl3_ciphers is not sorted by " + "id - cipher %d (%lx) <= cipher %d (%lx)\n", + i, id, i - 1, prev_id); + return 1; + } + prev_id = id; + } + + return 0; +} + +static int +cipher_find_test(void) +{ + STACK_OF(SSL_CIPHER) *ciphers; + const SSL_CIPHER *cipher; + unsigned char buf[2]; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int ret = 1; + int i; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + if (!SSL_set_cipher_list(ssl, "ALL")) { + fprintf(stderr, "SSL_set_cipher_list failed\n"); + goto failure; + } + + if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { + fprintf(stderr, "no ciphers\n"); + goto failure; + } + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + uint16_t cipher_value; + + cipher = sk_SSL_CIPHER_value(ciphers, i); + cipher_value = SSL_CIPHER_get_value(cipher); + + buf[0] = cipher_value >> 8; + buf[1] = cipher_value & 0xff; + + if ((cipher = SSL_CIPHER_find(ssl, buf)) == NULL) { + fprintf(stderr, + "SSL_CIPHER_find() returned NULL for %s\n", + SSL_CIPHER_get_name(cipher)); + goto failure; + } + + if (SSL_CIPHER_get_value(cipher) != cipher_value) { + fprintf(stderr, + "got cipher with value 0x%x, want 0x%x\n", + SSL_CIPHER_get_value(cipher), cipher_value); + goto failure; + } + } + + ret = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (ret); +} + +static int +cipher_get_by_value_tests(void) +{ + STACK_OF(SSL_CIPHER) *ciphers; + const SSL_CIPHER *cipher; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + unsigned long id; + uint16_t value; + int ret = 1; + int i; + + if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + + if ((ciphers = SSL_get_ciphers(ssl)) == NULL) { + fprintf(stderr, "no ciphers\n"); + goto failure; + } + + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + cipher = sk_SSL_CIPHER_value(ciphers, i); + + id = SSL_CIPHER_get_id(cipher); + if (SSL_CIPHER_get_by_id(id) == NULL) { + fprintf(stderr, "SSL_CIPHER_get_by_id() failed " + "for %s (0x%lx)\n", SSL_CIPHER_get_name(cipher), + id); + goto failure; + } + + value = SSL_CIPHER_get_value(cipher); + if (SSL_CIPHER_get_by_value(value) == NULL) { + fprintf(stderr, "SSL_CIPHER_get_by_value() failed " + "for %s (0x%04hx)\n", SSL_CIPHER_get_name(cipher), + value); + goto failure; + } + } + + ret = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (ret); +} + +struct parse_ciphersuites_test { + const char *str; + const int want; + const unsigned long cids[32]; +}; + +struct parse_ciphersuites_test parse_ciphersuites_tests[] = { + { + /* LibreSSL names. */ + .str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + }, + }, + { + /* OpenSSL names. */ + .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + }, + }, + { + /* Different priority order. */ + .str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + }, + }, + { + /* Known but unsupported names. */ + .str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256", + .want = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + }, + }, + { + /* Empty string means no TLSv1.3 ciphersuites. */ + .str = "", + .want = 1, + .cids = { 0 }, + }, + { + .str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE", + .want = 0, + }, + { + .str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256", + .want = 0, + }, +}; + +#define N_PARSE_CIPHERSUITES_TESTS \ + (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests)) + +static int +parse_ciphersuites_test(void) +{ + struct parse_ciphersuites_test *pct; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CIPHER *cipher; + int failed = 1; + int j, ret; + size_t i; + + for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) { + pct = &parse_ciphersuites_tests[i]; + + ret = ssl_parse_ciphersuites(&ciphers, pct->str); + if (ret != pct->want) { + fprintf(stderr, "FAIL: test %zu - " + "ssl_parse_ciphersuites returned %d, want %d\n", + i, ret, pct->want); + goto failed; + } + if (ret == 0) + continue; + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + cipher = sk_SSL_CIPHER_value(ciphers, j); + if (SSL_CIPHER_get_id(cipher) == pct->cids[j]) + continue; + fprintf(stderr, "FAIL: test %zu - got cipher %d with " + "id %lx, want %lx\n", i, j, + SSL_CIPHER_get_id(cipher), pct->cids[j]); + goto failed; + } + if (pct->cids[j] != 0) { + fprintf(stderr, "FAIL: test %zu - got %d ciphers, " + "expected more", i, sk_SSL_CIPHER_num(ciphers)); + goto failed; + } + } + + failed = 0; + + failed: + sk_SSL_CIPHER_free(ciphers); + + return failed; +} + +struct cipher_set_test { + int ctx_ciphersuites_first; + const char *ctx_ciphersuites; + const char *ctx_rulestr; + int ssl_ciphersuites_first; + const char *ssl_ciphersuites; + const char *ssl_rulestr; + int cids_aes_accel_fixup; + unsigned long cids[32]; +}; + +struct cipher_set_test cipher_set_tests[] = { + { + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids_aes_accel_fixup = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids_aes_accel_fixup = 1, + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_3_CK_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites_first = 1, + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 1, + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites_first = 0, + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 0, + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 1, + .ssl_ciphersuites = "", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ssl_ciphersuites_first = 0, + .ssl_ciphersuites = "", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, + { + .ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES", + .ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256", + .cids = { + TLS1_3_CK_AES_256_GCM_SHA384, + TLS1_3_CK_CHACHA20_POLY1305_SHA256, + TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + }, + }, +}; + +#define N_CIPHER_SET_TESTS \ + (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests)) + +static int +cipher_set_test(void) +{ + struct cipher_set_test *cst; + STACK_OF(SSL_CIPHER) *ciphers = NULL; + SSL_CIPHER *cipher; + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + int failed = 0; + size_t i; + int j; + + for (i = 0; i < N_CIPHER_SET_TESTS; i++) { + cst = &cipher_set_tests[i]; + + if (!ssl_aes_is_accelerated() && cst->cids_aes_accel_fixup) { + cst->cids[0] = TLS1_3_CK_CHACHA20_POLY1305_SHA256; + cst->cids[1] = TLS1_3_CK_AES_256_GCM_SHA384; + } + + if ((ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "SSL_CTX_new"); + + if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { + if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) + errx(1, "SSL_CTX_set_ciphersuites"); + } + if (cst->ctx_rulestr != NULL) { + if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr)) + errx(1, "SSL_CTX_set_cipher_list"); + } + if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) { + if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites)) + errx(1, "SSL_CTX_set_ciphersuites"); + } + + /* XXX - check SSL_CTX_get_ciphers(ctx) */ + + if ((ssl = SSL_new(ctx)) == NULL) + errx(1, "SSL_new"); + + if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { + if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) + errx(1, "SSL_set_ciphersuites"); + } + if (cst->ssl_rulestr != NULL) { + if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr)) + errx(1, "SSL_set_cipher_list"); + } + if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) { + if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites)) + errx(1, "SSL_set_ciphersuites"); + } + + ciphers = SSL_get_ciphers(ssl); + + for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) { + cipher = sk_SSL_CIPHER_value(ciphers, j); + if (SSL_CIPHER_get_id(cipher) == cst->cids[j]) + continue; + fprintf(stderr, "FAIL: test %zu - got cipher %d with " + "id %lx, want %lx\n", i, j, + SSL_CIPHER_get_id(cipher), cst->cids[j]); + failed |= 1; + } + if (cst->cids[j] != 0) { + fprintf(stderr, "FAIL: test %zu - got %d ciphers, " + "expected more", i, sk_SSL_CIPHER_num(ciphers)); + failed |= 1; + } + + SSL_CTX_free(ctx); + SSL_free(ssl); + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= check_cipher_order(); + + failed |= cipher_find_test(); + failed |= cipher_get_by_value_tests(); + + failed |= parse_ciphersuites_test(); + failed |= cipher_set_test(); + + return (failed); +} diff --git a/tests/client.c b/tests/client.c new file mode 100644 index 0000000..31a9603 --- /dev/null +++ b/tests/client.c @@ -0,0 +1,285 @@ +/* $OpenBSD: client.c,v 1.11 2022/07/07 13:12:57 tb Exp $ */ +/* + * Copyright (c) 2018-2019 Alexander Bluhm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "util.h" + +void __dead usage(void); + +void __dead +usage(void) +{ + fprintf(stderr, "usage: client [-Lsv] [-C CA] [-c crt -k key] " + "[-l ciphers] [-V version] host port\n"); + exit(2); +} + +int +main(int argc, char *argv[]) +{ + const SSL_METHOD *method; + SSL_CTX *ctx; + SSL *ssl; + BIO *bio; + SSL_SESSION *session = NULL; + int ch, error, listciphers = 0, sessionreuse = 0, verify = 0; + int version = 0; + char buf[256]; + char *ca = NULL, *crt = NULL, *key = NULL, *ciphers = NULL; + char *host_port, *host = "127.0.0.1", *port = "0"; + + while ((ch = getopt(argc, argv, "C:c:k:Ll:p:sV:v")) != -1) { + switch (ch) { + case 'C': + ca = optarg; + break; + case 'c': + crt = optarg; + break; + case 'k': + key = optarg; + break; + case 'L': + listciphers = 1; + break; + case 'l': + ciphers = optarg; + break; + case 's': + /* multiple reueses are possible */ + sessionreuse++; + break; + case 'V': + if (strcmp(optarg, "TLS1") == 0) { + version = TLS1_VERSION; + } else if (strcmp(optarg, "TLS1_1") == 0) { + version = TLS1_1_VERSION; + } else if (strcmp(optarg, "TLS1_2") == 0) { + version = TLS1_2_VERSION; +#ifdef TLS1_3_VERSION + } else if (strcmp(optarg, "TLS1_3") == 0) { + version = TLS1_3_VERSION; +#endif + } else { + errx(1, "unknown protocol version: %s", optarg); + } + break; + case 'v': + verify = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc == 2) { + host = argv[0]; + port = argv[1]; + } else if (!listciphers) { + usage(); + } + if (asprintf(&host_port, strchr(host, ':') ? "[%s]:%s" : "%s:%s", + host, port) == -1) + err(1, "asprintf host port"); + if ((crt == NULL && key != NULL) || (crt != NULL && key == NULL)) + errx(1, "certificate and private key must be used together"); + + SSL_library_init(); + SSL_load_error_strings(); + print_version(); + + /* setup method and context */ +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + method = TLS_client_method(); + if (method == NULL) + err_ssl(1, "TLS_client_method"); +#else + switch (version) { + case TLS1_VERSION: + method = TLSv1_client_method(); + break; + case TLS1_1_VERSION: + method = TLSv1_1_client_method(); + break; + case TLS1_2_VERSION: + method = TLSv1_2_client_method(); + break; +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + err(1, "TLS1_3 not supported"); +#endif + default: + method = SSLv23_client_method(); + break; + } + if (method == NULL) + err_ssl(1, "SSLv23_client_method"); +#endif + ctx = SSL_CTX_new(method); + if (ctx == NULL) + err_ssl(1, "SSL_CTX_new"); + +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + if (version) { + if (SSL_CTX_set_min_proto_version(ctx, version) != 1) + err_ssl(1, "SSL_CTX_set_min_proto_version"); + if (SSL_CTX_set_max_proto_version(ctx, version) != 1) + err_ssl(1, "SSL_CTX_set_max_proto_version"); + } +#endif + + /* load client certificate */ + if (crt != NULL) { + if (SSL_CTX_use_certificate_file(ctx, crt, + SSL_FILETYPE_PEM) <= 0) + err_ssl(1, "SSL_CTX_use_certificate_file"); + if (SSL_CTX_use_PrivateKey_file(ctx, key, + SSL_FILETYPE_PEM) <= 0) + err_ssl(1, "SSL_CTX_use_PrivateKey_file"); + if (SSL_CTX_check_private_key(ctx) <= 0) + err_ssl(1, "SSL_CTX_check_private_key"); + } + + /* verify server certificate */ + if (ca != NULL) { + if (SSL_CTX_load_verify_locations(ctx, ca, NULL) <= 0) + err_ssl(1, "SSL_CTX_load_verify_locations"); + } + SSL_CTX_set_verify(ctx, verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, + verify_callback); + + if (sessionreuse) { + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT); + } + + if (ciphers) { + if (SSL_CTX_set_cipher_list(ctx, ciphers) <= 0) + err_ssl(1, "SSL_CTX_set_cipher_list"); + } + + if (listciphers) { + STACK_OF(SSL_CIPHER) *supported_ciphers; + +#if OPENSSL_VERSION_NUMBER < 0x1010000f +#define SSL_get1_supported_ciphers SSL_get_ciphers +#endif + ssl = SSL_new(ctx); + if (ssl == NULL) + err_ssl(1, "SSL_new"); + supported_ciphers = SSL_get1_supported_ciphers(ssl); + if (supported_ciphers == NULL) + err_ssl(1, "SSL_get1_supported_ciphers"); + print_ciphers(supported_ciphers); + +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + sk_SSL_CIPHER_free(supported_ciphers); +#endif + return 0; + } + + do { + /* setup bio for socket operations */ + bio = BIO_new_connect(host_port); + if (bio == NULL) + err_ssl(1, "BIO_new_connect"); + + /* connect */ + if (BIO_do_connect(bio) <= 0) + err_ssl(1, "BIO_do_connect"); + printf("connect "); + print_sockname(bio); + printf("connect "); + print_peername(bio); + + /* do ssl client handshake */ + ssl = SSL_new(ctx); + if (ssl == NULL) + err_ssl(1, "SSL_new"); + SSL_set_bio(ssl, bio, bio); + /* resuse session if possible */ + if (session != NULL) { + if (SSL_set_session(ssl, session) <= 0) + err_ssl(1, "SSL_set_session"); + } + if ((error = SSL_connect(ssl)) <= 0) + err_ssl(1, "SSL_connect %d", error); + printf("session %d: %s\n", sessionreuse, + SSL_session_reused(ssl) ? "reuse" : "new"); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + + /* print session statistics */ + if (sessionreuse) { + session = SSL_get1_session(ssl); + if (session == NULL) + err_ssl(1, "SSL1_get_session"); + } else { + session = SSL_get_session(ssl); + if (session == NULL) + err_ssl(1, "SSL_get_session"); + } + if (SSL_SESSION_print_fp(stdout, session) <= 0) + err_ssl(1, "SSL_SESSION_print_fp"); + + /* read server greeting and write client hello over TLS */ + if ((error = SSL_read(ssl, buf, 9)) <= 0) + err_ssl(1, "SSL_read %d", error); + if (error != 9) + errx(1, "read not 9 bytes greeting: %d", error); + buf[9] = '\0'; + printf("<<< %s", buf); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + strlcpy(buf, "hello\n", sizeof(buf)); + printf(">>> %s", buf); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + if ((error = SSL_write(ssl, buf, 6)) <= 0) + err_ssl(1, "SSL_write %d", error); + if (error != 6) + errx(1, "write not 6 bytes hello: %d", error); + + /* shutdown connection */ + if ((error = SSL_shutdown(ssl)) < 0) + err_ssl(1, "SSL_shutdown unidirectional %d", error); + if (error <= 0) { + if ((error = SSL_shutdown(ssl)) <= 0) + err_ssl(1, "SSL_shutdown bidirectional %d", + error); + } + + SSL_free(ssl); + } while (sessionreuse--); + + SSL_CTX_free(ctx); + + printf("success\n"); + + return 0; +} diff --git a/tests/client.pem b/tests/client.pem new file mode 100644 index 0000000..ce4bf49 --- /dev/null +++ b/tests/client.pem @@ -0,0 +1,51 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Client Cert +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt +ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMVoXDTI0MDQwMTE0NDUxMVowZDELMAkG +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY ++yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs +lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D +nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 +x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 +bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 +AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG ++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B +AQUFAAOCAQEAJzA4KTjkjXGSC4He63yX9Br0DneGBzjAwc1H6f72uqnCs8m7jgkE +PQJFdTzQUKh97QPUuayZ2gl8XHagg+iWGy60Kw37gQ0+lumCN2sllvifhHU9R03H +bWtS4kue+yQjMbrzf3zWygMDgwvFOUAIgBpH9qGc+CdNu97INTYd0Mvz51vLlxRn +sC5aBYCWaZFnw3lWYxf9eVFRy9U+DkYFqX0LpmbDtcKP7AZGE6ZwSzaim+Cnoz1u +Cgn+QmpFXgJKMFIZ82iSZISn+JkCCGxctZX1lMvai4Wi8Y0HxW9FTFZ6KBNwwE4B +zjbN/ehBkgLlW/DWfi44DvwUHmuU6QP3cw== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAtK2p2x0S3C1ajftAc3GaWPsji6scw1k9Sw/XltbLQuDc11/f +wwrUiFcje2CB3Ri6yD6+uCA3V12jEc4GdqzirJZhwgIhaTv42vfYBgiUcR9McEGr +agFC3yVR3lIbOzhBjmXNp1on46irxnzU4pT+w58IuvYqUBavaEtfRZocFR5NsIOy +mRhyNag8htOFK3wmTEYrb0vflFYT6SD47ogYtsd/xWSKS+YFyb7xSusR2Ot6Ktmr +MswQE57QYJz+KiRVlnL0cduMBdT52Wm8blaC9mz50PyrzjQ68NyHapCoWDU7pe4x +HLtzpXGSDMPuw4miiSwMym/2wReYJv6cFugLPQIDAQABAoIBAAZOyc9MhIwLSU4L +p4RgQvM4UVVe8/Id+3XTZ8NsXExJbWxXfIhiqGjaIfL8u4vsgRjcl+v1s/jo2/iT +KMab4o4D8gXD7UavQVDjtjb/ta79WL3SjRl2Uc9YjjMkyq6WmDNQeo2NKDdafCTB +1uzSJtLNipB8Z53ELPuHJhxX9QMHrMnuha49riQgXZ7buP9iQrHJFhImBjSzbxJx +L+TI6rkyLSf9Wi0Pd3L27Ob3QWNfNRYNSeTE+08eSRChkur5W0RuXAcuAICdQlCl +LBvWO/LmmvbzCqiDcgy/TliSb6CGGwgiNG7LJZmlkYNj8laGwalNlYZs3UrVv6NO +Br2loAECgYEA2kvCvPGj0Dg/6g7WhXDvAkEbcaL1tSeCxBbNH+6HS2UWMWvyTtCn +/bbD519QIdkvayy1QjEf32GV/UjUVmlULMLBcDy0DGjtL3+XpIhLKWDNxN1v1/ai +1oz23ZJCOgnk6K4qtFtlRS1XtynjA+rBetvYvLP9SKeFrnpzCgaA2r0CgYEA0+KX +1ACXDTNH5ySX3kMjSS9xdINf+OOw4CvPHFwbtc9aqk2HePlEsBTz5I/W3rKwXva3 +NqZ/bRqVVeZB/hHKFywgdUQk2Uc5z/S7Lw70/w1HubNTXGU06Ngb6zOFAo/o/TwZ +zTP1BMIKSOB6PAZPS3l+aLO4FRIRotfFhgRHOoECgYEAmiZbqt8cJaJDB/5YYDzC +mp3tSk6gIb936Q6M5VqkMYp9pIKsxhk0N8aDCnTU+kIK6SzWBpr3/d9Ecmqmfyq7 +5SvWO3KyVf0WWK9KH0abhOm2BKm2HBQvI0DB5u8sUx2/hsvOnjPYDISbZ11t0MtK +u35Zy89yMYcSsIYJjG/ROCUCgYEAgI2P9G5PNxEP5OtMwOsW84Y3Xat/hPAQFlI+ +HES+AzbFGWJkeT8zL2nm95tVkFP1sggZ7Kxjz3w7cpx7GX0NkbWSE9O+T51pNASV +tN1sQ3p5M+/a+cnlqgfEGJVvc7iAcXQPa3LEi5h2yPR49QYXAgG6cifn3dDSpmwn +SUI7PQECgYEApGCIIpSRPLAEHTGmP87RBL1smurhwmy2s/pghkvUkWehtxg0sGHh +kuaqDWcskogv+QC0sVdytiLSz8G0DwcEcsHK1Fkyb8A+ayiw6jWJDo2m9+IF4Fww +1Te6jFPYDESnbhq7+TLGgHGhtwcu5cnb4vSuYXGXKupZGzoLOBbv1Zw= +-----END RSA PRIVATE KEY----- diff --git a/tests/client1-ecdsa-chain.pem b/tests/client1-ecdsa-chain.pem new file mode 100644 index 0000000..7a6883d --- /dev/null +++ b/tests/client1-ecdsa-chain.pem @@ -0,0 +1,27 @@ +subject= CN = LibreSSL Test Client 1 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrTCCAVKgAwIBAgIJAOVssaaTYoH6MAoGCCqGSM49BAMCMC4xLDAqBgNVBAMM +I0xpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTIxMTIyNzE0 +NDA0MFoXDTMxMTIyNTE0NDA0MFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBD +bGllbnQgMSBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMnRxZ9SVIjF +eygaoub4qyo/tQlHXpQ2U66mhwKhchXD02w3viqOW0qklPSRhwV4nFKsdkVTogCg +Y8AJokxKDU6jYDBeMB0GA1UdDgQWBBTikUU9S7ASdWw7fhaYVdDqUAyH+DAfBgNV +HSMEGDAWgBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIHgDAKBggqhkjOPQQDAgNJADBGAiEA+Aal+cjgT+pknsmAPbivSHY+ +9clFV0Ree1c+nPbBz8cCIQCZDS2G/X8QthK7hZwV2mYhwvd6M/8kwet4u39qJYx8 +eA== +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/client1-ecdsa.pem b/tests/client1-ecdsa.pem new file mode 100644 index 0000000..7d1b2cf --- /dev/null +++ b/tests/client1-ecdsa.pem @@ -0,0 +1,19 @@ +subject= CN = LibreSSL Test Client 1 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrTCCAVKgAwIBAgIJAOVssaaTYoH6MAoGCCqGSM49BAMCMC4xLDAqBgNVBAMM +I0xpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTIxMTIyNzE0 +NDA0MFoXDTMxMTIyNTE0NDA0MFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBD +bGllbnQgMSBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMnRxZ9SVIjF +eygaoub4qyo/tQlHXpQ2U66mhwKhchXD02w3viqOW0qklPSRhwV4nFKsdkVTogCg +Y8AJokxKDU6jYDBeMB0GA1UdDgQWBBTikUU9S7ASdWw7fhaYVdDqUAyH+DAfBgNV +HSMEGDAWgBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIHgDAKBggqhkjOPQQDAgNJADBGAiEA+Aal+cjgT+pknsmAPbivSHY+ +9clFV0Ree1c+nPbBz8cCIQCZDS2G/X8QthK7hZwV2mYhwvd6M/8kwet4u39qJYx8 +eA== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghOgzNmZV/rLf5+I5 +pnOXJ3N6W8QE5biANh/RVNNmNImhRANCAATJ0cWfUlSIxXsoGqLm+KsqP7UJR16U +NlOupocCoXIVw9NsN74qjltKpJT0kYcFeJxSrHZFU6IAoGPACaJMSg1O +-----END PRIVATE KEY----- diff --git a/tests/client1-rsa-chain.pem b/tests/client1-rsa-chain.pem new file mode 100644 index 0000000..e5267eb --- /dev/null +++ b/tests/client1-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Client 1 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH1MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzhaFw0zMTEyMjUxNDQwMzhaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +Q2xpZW50IDEgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyct5 +l3L4GIzbFPszUioY0/+W9IGnQqOlBtFJQSzJtM96/UcJ/9MEkz08UUaf07CTYWy/ +Qbwl3DizPV9yymiae64oe9RBc2Hh/Z88473Q6UZvPrdoexoVb159tTdvF8IDfIER +HEB2VAtssFvszERa04ndpDqS8tHfBcLGUCu2kZQ0FSCKbNSDLLwoQmyNgnWo8PDY +XshJGdABaTmnhpkrhJq2zeYiUResoWo8z08iVn7vLgjRNTi9mtXr5eC4L0DfEuZB +exaC8frQXH2rXKvojFrFwJ67QLwCOiUKbGlUQBeKS6iahgDL/dRprHqbNZFI7in4 +QiokqixjfzYSmALFqwIDAQABo2AwXjAdBgNVHQ4EFgQUNRNEZs+zkqBu6va5XyGv +UfzSKZQwHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBACmIu0ppKw1T +hzGAoyjxK0y1ffbIDvObcwAMtXSHprMNhkdk7jyQBiXpx4ngEg1LhalUUDkp9Yt1 +qUVjyM4cphJL7ni3N/SyoUtuYWY4s8mqIhloT5adaUJ24kHJ2eFzNBLDuno5wen4 +dXKevTZPNqkkNohbVHrrFewsqS8CYw+rfiNerOJYZzSMbueWK5Pck0od05STZlAE +/B2zesXgd3ZmRKM8jrlZS6gan1FaJOzwErccP7jWnrOeW9uLysRg0ww26/H8Q9xS +dm0L8IXjzmE/yodk/nrt9G72mJnUITt4uHW/1ibMi4+iUR0Ff4oeqrBHQAbRawMK +XKRzXhtI9sI= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/client1-rsa.pem b/tests/client1-rsa.pem new file mode 100644 index 0000000..7e0c47c --- /dev/null +++ b/tests/client1-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Client 1 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH1MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzhaFw0zMTEyMjUxNDQwMzhaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +Q2xpZW50IDEgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyct5 +l3L4GIzbFPszUioY0/+W9IGnQqOlBtFJQSzJtM96/UcJ/9MEkz08UUaf07CTYWy/ +Qbwl3DizPV9yymiae64oe9RBc2Hh/Z88473Q6UZvPrdoexoVb159tTdvF8IDfIER +HEB2VAtssFvszERa04ndpDqS8tHfBcLGUCu2kZQ0FSCKbNSDLLwoQmyNgnWo8PDY +XshJGdABaTmnhpkrhJq2zeYiUResoWo8z08iVn7vLgjRNTi9mtXr5eC4L0DfEuZB +exaC8frQXH2rXKvojFrFwJ67QLwCOiUKbGlUQBeKS6iahgDL/dRprHqbNZFI7in4 +QiokqixjfzYSmALFqwIDAQABo2AwXjAdBgNVHQ4EFgQUNRNEZs+zkqBu6va5XyGv +UfzSKZQwHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBACmIu0ppKw1T +hzGAoyjxK0y1ffbIDvObcwAMtXSHprMNhkdk7jyQBiXpx4ngEg1LhalUUDkp9Yt1 +qUVjyM4cphJL7ni3N/SyoUtuYWY4s8mqIhloT5adaUJ24kHJ2eFzNBLDuno5wen4 +dXKevTZPNqkkNohbVHrrFewsqS8CYw+rfiNerOJYZzSMbueWK5Pck0od05STZlAE +/B2zesXgd3ZmRKM8jrlZS6gan1FaJOzwErccP7jWnrOeW9uLysRg0ww26/H8Q9xS +dm0L8IXjzmE/yodk/nrt9G72mJnUITt4uHW/1ibMi4+iUR0Ff4oeqrBHQAbRawMK +XKRzXhtI9sI= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDJy3mXcvgYjNsU ++zNSKhjT/5b0gadCo6UG0UlBLMm0z3r9Rwn/0wSTPTxRRp/TsJNhbL9BvCXcOLM9 +X3LKaJp7rih71EFzYeH9nzzjvdDpRm8+t2h7GhVvXn21N28XwgN8gREcQHZUC2yw +W+zMRFrTid2kOpLy0d8FwsZQK7aRlDQVIIps1IMsvChCbI2Cdajw8NheyEkZ0AFp +OaeGmSuEmrbN5iJRF6yhajzPTyJWfu8uCNE1OL2a1evl4LgvQN8S5kF7FoLx+tBc +fatcq+iMWsXAnrtAvAI6JQpsaVRAF4pLqJqGAMv91Gmseps1kUjuKfhCKiSqLGN/ +NhKYAsWrAgMBAAECggEAahMtnXDv/We9mi/Z8Gz0lCwcm/azh5IiI41MJph2hzcx +fYYkOXghRYzA8jBfv5VoQ6Q4fUN722Fqxu4vlzqZSj5oRX9z0EU52GomRcj30kgW +Hi+nGl7BucM/7Uxwd1qjHoVyCxnPmapPvfz0YwPjgqNMARJRQJcV1x9lw6rW03rW +qvoQKwnQ5vZRYldFnvYXRM0VUu8GdruaidWJ2Ra6FUFbEH+I77oIIoyWgXniq9jq +h0VJNRVCLwV4rFzmMkOAz1yxvJ+4UG9/wHYsZVhJDkyos1FVf0klKipKTS7Z87Em +aFlZ01JrM//kS/qdgohllCU8Xt1uVtvsYmJY9T6IEQKBgQD1IJzdopCI+BL7PfWf +qSpyUOgp+8J50CnIJ42ZdBWDhPZSbBqWmqbgBlnXEyPwkKVOhHde6td9DtxRVOiE +Zfy0gpUp4xWUxFdMKyW0+JmsmXiUJKIck6LxqfYDZUTzD2wp1/AhLGJ2M/J5e4IP +umr6IQ4BbDfKGp2NiHEQElCmdwKBgQDSvtOy71EhewJQ9slazR+10skSBbc5Ks9W +cy1fZKcnNB/dPenak5i8Gr04nPhhNvgAwmtDGb9hH1mwjHCUz/TaoPsbTKvtTN2N +MxFzQEsE9F803ULOvFOppe5YEy/M2OaDLHVil1bMwbrg3pGKD4TUfy5cE2NfCDi3 +JwlKk6uDbQKBgQCLAQ9zb7hes66v4pbjD18OrGq7RBUoVq8a3bMijf2VM1UrsDnz +pYd0CqXvnN8IkD3tpJi8rpe8Ry0QwgGI8vy2sEY+FpQqZJzMiLs9QKyEgBMsjwmP +Avmn6SWlD0xmORyxLc7yQOUk+phJ44wBt0jqxsvWarPIXAd0NydGYdxySQKBgAWo +B4iS8cuDQLGpngfo34QCz1DDhIJtSrlYSAx6aB4eQQiwI7mxInVSBmghlm0Ni6SB +k11usHtL2x1o95CW8Ex566N08FxjJsMmbr54KEtOv8tscOGZnmk8QeRtR2gpHi7B +H7lwtGy0em6UqrVY60jEzRq9jno7f0IzMwWkZwMVAoGAL9mQ8xVIaDNyhK477NvD +ZF2AWrHHLXDeTfwdI+HTCUdeDC208kgTx4Z/AX1cN7KQtWZfKIW0bWtCDnKsIwbK +zheDR2AjuDEbT9HWLtYgQvx5/fEc/yxJqtQk+n4CTrDY+rNeow51kziBKWFnu8Je +m38SJSK7uNLz5ZWNgj3XIUE= +-----END PRIVATE KEY----- diff --git a/tests/client2-ecdsa-chain.pem b/tests/client2-ecdsa-chain.pem new file mode 100644 index 0000000..0cba867 --- /dev/null +++ b/tests/client2-ecdsa-chain.pem @@ -0,0 +1,26 @@ +subject= CN = LibreSSL Test Client 2 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBpjCCAUygAwIBAgIDEAACMAoGCCqGSM49BAMCMC4xLDAqBgNVBAMMI0xpYnJl +U1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTEwMDEwMTAwMDAwMFoX +DTIwMDEwMTAwMDAwMFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBDbGllbnQg +MiBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL7oVxdDfyspO7ozwbv+ +2QKCXR8Z1+JWKj6lLmAkN6GY/gXPYcCAtXOWRoVt5yg4YrH0eOJalah7yGjAeHLq +EHijYDBeMB0GA1UdDgQWBBRO8eCtJ/+3xfn+3qY31gP3Ch5JvDAfBgNVHSMEGDAW +gBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE +AwIHgDAKBggqhkjOPQQDAgNIADBFAiEA10kcAL7I/Y0KVNryJGrfVa1er0uiUXxS +2GmnKWFCQKECID9PY+LK4+DNvxyn4ld47AGJZjdolx6mwLFHK8RvtLo9 +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/client2-ecdsa.pem b/tests/client2-ecdsa.pem new file mode 100644 index 0000000..f0576e6 --- /dev/null +++ b/tests/client2-ecdsa.pem @@ -0,0 +1,18 @@ +subject= CN = LibreSSL Test Client 2 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBpjCCAUygAwIBAgIDEAACMAoGCCqGSM49BAMCMC4xLDAqBgNVBAMMI0xpYnJl +U1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTEwMDEwMTAwMDAwMFoX +DTIwMDEwMTAwMDAwMFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBDbGllbnQg +MiBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL7oVxdDfyspO7ozwbv+ +2QKCXR8Z1+JWKj6lLmAkN6GY/gXPYcCAtXOWRoVt5yg4YrH0eOJalah7yGjAeHLq +EHijYDBeMB0GA1UdDgQWBBRO8eCtJ/+3xfn+3qY31gP3Ch5JvDAfBgNVHSMEGDAW +gBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE +AwIHgDAKBggqhkjOPQQDAgNIADBFAiEA10kcAL7I/Y0KVNryJGrfVa1er0uiUXxS +2GmnKWFCQKECID9PY+LK4+DNvxyn4ld47AGJZjdolx6mwLFHK8RvtLo9 +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGJcFF0AYtzYr190f +tXnGfakMTr5zk0UO1nAfVSLMW2OhRANCAAS+6FcXQ38rKTu6M8G7/tkCgl0fGdfi +Vio+pS5gJDehmP4Fz2HAgLVzlkaFbecoOGKx9HjiWpWoe8howHhy6hB4 +-----END PRIVATE KEY----- diff --git a/tests/client2-rsa-chain.pem b/tests/client2-rsa-chain.pem new file mode 100644 index 0000000..bc09c2e --- /dev/null +++ b/tests/client2-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Client 2 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgIDEAACMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNVBAMMIUxp +YnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0xMDAxMDEwMDAwMDBa +Fw0yMDAxMDEwMDAwMDBaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3QgQ2xpZW50 +IDIgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6TPjTtVn4l/2 +3g+XVWUMpxZWu1G3GJ1TY14loqG2lLcyFwHfbxPgjdeUYUXgKw2v3LKdK1xlwohi +7adKmf8ZsqgWYd+SWtvzyoEEEvWQVj5bbs2+EI9CTP4L96lqsiBYZoHxCI+TG3pY +6JOZQT2wmJEL0zeK9cmUXoaV6fQOcEtSmp6m8XWLEEyUZvVHG3OX+7FtcV0snDfz +XrnvpRpu4zolbCC6jysufU46VoJNrrKdPlDu4PbF8PKrJl7jOSULaYHqugIeniMV +V9enkg9t0Bb8bW5sW8/c4vwS52dlRNLHXkwGE7u9+XEVOGDJ+a01eRjVOxQwqptn +qrWTF++D0QIDAQABo2AwXjAdBgNVHQ4EFgQUmUxF57QtRFh9JBPTMx5rUvRjj+4w +HwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/BAIwADAO +BgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAMAvLchG7tWtNXPK3+Ie +u+htMMPhgJCsHhEC0ssZezD3BfYHaJh7ayQwI1KWKrQOwu9z+oOGWQjoVmhBzoi2 +hmvH9vT4GFVnM5agf68USNLxQvlQiShfnqPZiy3EduwY0q+uNvvNYlHeLTp/Au7F +SesJqWoaMr3130n8QqiO8myNjUj3GVrmBBpFogU5qxQAHkcy2AbpkATjRtfG4Jn2 +DWXR9Yd56KuvmkpdVkw+DScOXbIgXmHyutJ7qDbm6lwXLD3U5ulvbSxXW/MhJpb9 +72UjtpQbhMzcyQwCvNrKnST+QqKMisAdkOOhCdEYTj8flpCbMA5bqwBRX+t+AMeD +4lY= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/client2-rsa.pem b/tests/client2-rsa.pem new file mode 100644 index 0000000..b4431ce --- /dev/null +++ b/tests/client2-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Client 2 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgIDEAACMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNVBAMMIUxp +YnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0xMDAxMDEwMDAwMDBa +Fw0yMDAxMDEwMDAwMDBaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3QgQ2xpZW50 +IDIgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6TPjTtVn4l/2 +3g+XVWUMpxZWu1G3GJ1TY14loqG2lLcyFwHfbxPgjdeUYUXgKw2v3LKdK1xlwohi +7adKmf8ZsqgWYd+SWtvzyoEEEvWQVj5bbs2+EI9CTP4L96lqsiBYZoHxCI+TG3pY +6JOZQT2wmJEL0zeK9cmUXoaV6fQOcEtSmp6m8XWLEEyUZvVHG3OX+7FtcV0snDfz +XrnvpRpu4zolbCC6jysufU46VoJNrrKdPlDu4PbF8PKrJl7jOSULaYHqugIeniMV +V9enkg9t0Bb8bW5sW8/c4vwS52dlRNLHXkwGE7u9+XEVOGDJ+a01eRjVOxQwqptn +qrWTF++D0QIDAQABo2AwXjAdBgNVHQ4EFgQUmUxF57QtRFh9JBPTMx5rUvRjj+4w +HwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/BAIwADAO +BgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAMAvLchG7tWtNXPK3+Ie +u+htMMPhgJCsHhEC0ssZezD3BfYHaJh7ayQwI1KWKrQOwu9z+oOGWQjoVmhBzoi2 +hmvH9vT4GFVnM5agf68USNLxQvlQiShfnqPZiy3EduwY0q+uNvvNYlHeLTp/Au7F +SesJqWoaMr3130n8QqiO8myNjUj3GVrmBBpFogU5qxQAHkcy2AbpkATjRtfG4Jn2 +DWXR9Yd56KuvmkpdVkw+DScOXbIgXmHyutJ7qDbm6lwXLD3U5ulvbSxXW/MhJpb9 +72UjtpQbhMzcyQwCvNrKnST+QqKMisAdkOOhCdEYTj8flpCbMA5bqwBRX+t+AMeD +4lY= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDpM+NO1WfiX/be +D5dVZQynFla7UbcYnVNjXiWiobaUtzIXAd9vE+CN15RhReArDa/csp0rXGXCiGLt +p0qZ/xmyqBZh35Ja2/PKgQQS9ZBWPltuzb4Qj0JM/gv3qWqyIFhmgfEIj5Mbeljo +k5lBPbCYkQvTN4r1yZRehpXp9A5wS1KanqbxdYsQTJRm9Ucbc5f7sW1xXSycN/Ne +ue+lGm7jOiVsILqPKy59TjpWgk2usp0+UO7g9sXw8qsmXuM5JQtpgeq6Ah6eIxVX +16eSD23QFvxtbmxbz9zi/BLnZ2VE0sdeTAYTu735cRU4YMn5rTV5GNU7FDCqm2eq +tZMX74PRAgMBAAECggEAGghk06QXGLpFwLxU1H+XTf+8ZuTUX7cQXANiiCktTKS2 +vsLCwo+hfbQXKFS4lZXNkAGQcgq6gWDgSk9mkJJduAfzl7FxkRsEuBJ29fbbygTk +CBaHpSmY6SdjBp6u/nuF4suWsLH2ZhbeXfg8H4BXenCWtVl59b4vBe5YRemswvQv +DJzV9gVKDf7HnvcjUMBXNKNWk0cLlodKX6bRhpPbq/WNPAubA3z4Z0JZqnW9uuWa +wTd7QPeKxVbQmz5Y5hifKMI4ML5i1+Fo6Xvcdt1TwfeHYy+iPNtB8fEu1VdH25DN +iN5iiMOr7go8MOc4LxCZGsXqIDd6WYOg/DmCEsSiEQKBgQD78UT9ezhI7TLVmUdC +eQd8+oi1qXykHXpMvobCJUrEulF6/iZSICcVVdH/DcvGRPv7A+90QZWGcY2Bzhtz +8C2XFLqLvSyHegSA4P57PbHjBOqowFAWntLTn/gSOb+nYKSM5XzOQq7RQctYX3EO +jZb4GKhPOUwzy2Ugd9zNhqD8gwKBgQDs9VtAYvM2i3ylRLH/UdAu/E+oA05ydxT1 +dt4tK6R54KSZk+E/LM/k8D3p70tyiRbfky6DtGrGZSpyecCPdkNF0FJTRER1eDsb +Au2uH6zP0nn2FUnQnL5fcIkVlclukf8pMox5fbFcoZjIWti9TURIdMTkaQVX9LKf +Gme84UX2GwKBgQCqsJZuKbpDZjinkDZAKeFR4icW9KIWSkZekkKYbE2QpS6o5mEu +CMyR3tfsNfuV84zITq0/lWNpd6tIg0wEK3enwQp1vA/cJWXBry2ab30CcoVNGSXp +fWcWq22VY3yeOJKjRqNc1r671RigYeEl2/WpVoNJUWd4O9fivHJi6FBPYwKBgQDI +3B5y0K27gbex3C5J8A7ZlTTshYj8zGZuwEkK3yC30y2TpV/dDl5XgTHqV9aLixth +f0CBkfCkpeK6UOxib2wNBM6UGJ0zOixX9D6HSABT1eVeLKN6ezOAcUMykdrCqG0z +fc7HuT0b+TsqMp/gr1t/U8QGneNSsHCtH1PqLscAGwKBgFdecOiUhKezd6mReDYc +cBKBN/2EBPNCSKlzuskSGoU/mC0H+2Mj1XX4fx5Wjvjp3hqKEVgs/L8Eth1KYfgF +CaQzGAkavihH03L73to1Wj/K4XineBAKZLtXkdzWdB+kM8zkYJqmagh6h6BlXFun +TJvYJYIK9U3kvhZtsD6w1slZ +-----END PRIVATE KEY----- diff --git a/tests/client3-ecdsa-chain.pem b/tests/client3-ecdsa-chain.pem new file mode 100644 index 0000000..a389943 --- /dev/null +++ b/tests/client3-ecdsa-chain.pem @@ -0,0 +1,26 @@ +subject= CN = LibreSSL Test Client 3 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIJAOVssaaTYoH7MAkGByqGSM49BAEwLjEsMCoGA1UEAwwj +TGlicmVTU0wgVGVzdCBJbnRlcm1lZGlhdGUgQ0EgRUNEU0EwHhcNMjExMjI3MTQ0 +MDQwWhcNMzExMjI1MTQ0MDQwWjAnMSUwIwYDVQQDDBxMaWJyZVNTTCBUZXN0IENs +aWVudCAzIEVDRFNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqlNqEjPuPpw3 +HaWxXbWql6f9g2HPei7RGZRfEAeNrnWT+Y4okVoqcxjeLNBA6dNl3uALWbSmDu6a +kmBSU1aY9KNgMF4wHQYDVR0OBBYEFKxGR7LhwxXUGYyxjqBrxi5RKHamMB8GA1Ud +IwQYMBaAFBdWPW/8SlcSOULKAnKBq1AN5MIIMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgeAMAkGByqGSM49BAEDSAAwRQIhAMFzwaCpvWiXD+zEZ/mUBdbMQq2W +JLELD9Mv11NiBhi6AiAN/QNQjluNEUTkxCH6p9bQiOYCQ3DOnPTxrSly/RQOSQ== +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/client3-ecdsa.pem b/tests/client3-ecdsa.pem new file mode 100644 index 0000000..f42528b --- /dev/null +++ b/tests/client3-ecdsa.pem @@ -0,0 +1,18 @@ +subject= CN = LibreSSL Test Client 3 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIJAOVssaaTYoH7MAkGByqGSM49BAEwLjEsMCoGA1UEAwwj +TGlicmVTU0wgVGVzdCBJbnRlcm1lZGlhdGUgQ0EgRUNEU0EwHhcNMjExMjI3MTQ0 +MDQwWhcNMzExMjI1MTQ0MDQwWjAnMSUwIwYDVQQDDBxMaWJyZVNTTCBUZXN0IENs +aWVudCAzIEVDRFNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqlNqEjPuPpw3 +HaWxXbWql6f9g2HPei7RGZRfEAeNrnWT+Y4okVoqcxjeLNBA6dNl3uALWbSmDu6a +kmBSU1aY9KNgMF4wHQYDVR0OBBYEFKxGR7LhwxXUGYyxjqBrxi5RKHamMB8GA1Ud +IwQYMBaAFBdWPW/8SlcSOULKAnKBq1AN5MIIMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgeAMAkGByqGSM49BAEDSAAwRQIhAMFzwaCpvWiXD+zEZ/mUBdbMQq2W +JLELD9Mv11NiBhi6AiAN/QNQjluNEUTkxCH6p9bQiOYCQ3DOnPTxrSly/RQOSQ== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfaMOzQZ+d1yL3ToI +VPcHtdkIVhqatu/rDcJLuJcNnQehRANCAASqU2oSM+4+nDcdpbFdtaqXp/2DYc96 +LtEZlF8QB42udZP5jiiRWipzGN4s0EDp02Xe4AtZtKYO7pqSYFJTVpj0 +-----END PRIVATE KEY----- diff --git a/tests/client3-rsa-chain.pem b/tests/client3-rsa-chain.pem new file mode 100644 index 0000000..251344f --- /dev/null +++ b/tests/client3-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Client 3 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH2MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzhaFw0zMTEyMjUxNDQwMzhaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +Q2xpZW50IDMgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1vW +q3L63zPi8RJaJ07LsR05gCBYJ7FrnprqKbo7swLra3HE5WQFTxxOPkzBBnCUEaa2 +tqPtov34mrOmnYTQDBxpljx5u6AzjgMfwJZfh7CtGf893nbbP7T2f3pXAFBR0A32 +xmEvso5afyLNRvmxCsrdr2u73bETmBqFQFgGrhtBpTeGqsixgOegZzKHVF67ZjJi +e+faM24GAtkOiPB7PfVgZFyTfe8HQsqqcMRVtjd7JxuN33k8cFIWqv5i8oqVLBME +mLFM2WFIYNTsMtQ38eA7xieuuK6OPTp+cJKQY6jA3wUJOTRt9UE7pEjxOTumckfM +u/ZE1+AODHkH97FptwIDAQABo2AwXjAdBgNVHQ4EFgQUz44RRa+P1oRBVI6lla3o +VsVQq7swHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAFgL5955qwHN +vFGnAKoHhoszX3qf2h8zc5HvFfnbvZbBbsuRFW1/QGfQPGWDq8YUlb6wu8NjLjSM +qTSYd1CvWXO1s91kr3LM5k7+9x+whOgbzWjGiprloS9pXcZ+ljTunW4o7jE7pPjZ +opk7W2WmD7/dEDg10x0yDZnKbzea5PMpp6kLqNjtENW4SETtcnwBdi/MZ09ApuUC +E+XWK/uKmxbIJ7Rt/Vi5H3BE74w7souq7fMwGGk7NL8Fmha78VQApKvZV/Rsfrio +D0vVU8djTlEJyXCeqFYU2eKWhc0bfiONIFJ6Wtg/1cR6Jn12+6X36J+wW1G3ibMu +ey+V9oVpM2U= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/client3-rsa.pem b/tests/client3-rsa.pem new file mode 100644 index 0000000..b825391 --- /dev/null +++ b/tests/client3-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Client 3 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH2MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzhaFw0zMTEyMjUxNDQwMzhaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +Q2xpZW50IDMgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp1vW +q3L63zPi8RJaJ07LsR05gCBYJ7FrnprqKbo7swLra3HE5WQFTxxOPkzBBnCUEaa2 +tqPtov34mrOmnYTQDBxpljx5u6AzjgMfwJZfh7CtGf893nbbP7T2f3pXAFBR0A32 +xmEvso5afyLNRvmxCsrdr2u73bETmBqFQFgGrhtBpTeGqsixgOegZzKHVF67ZjJi +e+faM24GAtkOiPB7PfVgZFyTfe8HQsqqcMRVtjd7JxuN33k8cFIWqv5i8oqVLBME +mLFM2WFIYNTsMtQ38eA7xieuuK6OPTp+cJKQY6jA3wUJOTRt9UE7pEjxOTumckfM +u/ZE1+AODHkH97FptwIDAQABo2AwXjAdBgNVHQ4EFgQUz44RRa+P1oRBVI6lla3o +VsVQq7swHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAFgL5955qwHN +vFGnAKoHhoszX3qf2h8zc5HvFfnbvZbBbsuRFW1/QGfQPGWDq8YUlb6wu8NjLjSM +qTSYd1CvWXO1s91kr3LM5k7+9x+whOgbzWjGiprloS9pXcZ+ljTunW4o7jE7pPjZ +opk7W2WmD7/dEDg10x0yDZnKbzea5PMpp6kLqNjtENW4SETtcnwBdi/MZ09ApuUC +E+XWK/uKmxbIJ7Rt/Vi5H3BE74w7souq7fMwGGk7NL8Fmha78VQApKvZV/Rsfrio +D0vVU8djTlEJyXCeqFYU2eKWhc0bfiONIFJ6Wtg/1cR6Jn12+6X36J+wW1G3ibMu +ey+V9oVpM2U= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnW9arcvrfM+Lx +ElonTsuxHTmAIFgnsWuemuopujuzAutrccTlZAVPHE4+TMEGcJQRpra2o+2i/fia +s6adhNAMHGmWPHm7oDOOAx/All+HsK0Z/z3edts/tPZ/elcAUFHQDfbGYS+yjlp/ +Is1G+bEKyt2va7vdsROYGoVAWAauG0GlN4aqyLGA56BnModUXrtmMmJ759ozbgYC +2Q6I8Hs99WBkXJN97wdCyqpwxFW2N3snG43feTxwUhaq/mLyipUsEwSYsUzZYUhg +1Owy1Dfx4DvGJ664ro49On5wkpBjqMDfBQk5NG31QTukSPE5O6ZyR8y79kTX4A4M +eQf3sWm3AgMBAAECggEBAJV3HddtDsR8sHegbkegxaXeddYKDPEWMQkrTWoK2vpa +5ynEJ5a+p0cp/m8BWXqI3JSPEas36CmjLH3taCZR0QSf82SrigSZZLG19IupQJQM +o+wN2pFuEQ1qbqMW/dBX61kmv3gYn+KV5BibWj3DDeyXlTjvvI6XcOps9QisFPs0 +BqPC7U4B3DaILeK+cLS9ONjXv4WgGi1LB8dpSR3HgT+qKs/bceCWGCcjfi3PQVJw +8Ahv8wce71rwIWxhnh6hcHq8iiGUj2CAtOA9E4qtxgQ5VkhR049pPQ0CkcrFBRT8 +wTDF5ffzSAbU9QRp/cL7k/eeEAiNQg0aL2GUHhmO/KECgYEA1PxATAFTzX6K4nM/ +yRU769vegTiblYjzUB5JL7baMUgSGgXrZ4UomtQQiYZSDhho8bDSEKM7cNzddMTo +BFyKTvV4Won6LtF2R/JiFbUfDxhGS1+uoLXGciAFdB+NABLrmTQ0jp0N3y53UBmr +jwMDz9BqXq+6QoM3lLUsL4V2j08CgYEAySiax4D3pkr3T6iTuEaLqW9vTV58vWUY +sDstNA2YONYTPHUtFMpVfPgMmrraWHl3yNC2LB9W3SjJ+05oRYObUBI1oAg68u9z +T2+jcxM3fN8HFwyFMm5gd3tygawdwGsvCjLPMJaHdtwlbg8lYfHyEl1hJRA+cnKg +Y5hrfWtpJRkCgYEApWeBR4WAX4Z2tYZrcu5aqsEF+7TKn0bMLtxWWgfXS459AFi4 +iJyQ/CzU6vi1oNy0I37+pI0gDHZ6RcTlqv1zK/7WiPm+ob1p7lX+dn1CsaZYcRDN +vWFtzBOyKIyYJAaNkV1Js7eknj6nyj0lTts4ipuBACfYru7Yq1RIDF/Jw2ECgYA9 +qTWwu+at0cL3ZwxI6076VA9BHxqLj8a+lpUnpJcprO1eleiIu/DyirKKZ4ZwomNG +aju9UKn2xv8LCqDJ1iqwo7ROZtdzClVFX0oyBwz2OQNaXFsj91OYrH2QJCtGhVR5 +AtQh57KEi7zpfLkPyfNTD86sZstNl7d0cA9a9abYWQKBgQCPESj1LojjkEvGKtiD +9w+ZMaDf+mYK+RYQnjEthUMpAPI+mhm9cAl8mMJu3FaNgviOX9oB1/1XGl1Pj5od +KWej9CF1ltoW/PcjsSTeeRFye5jvXn9BLr3w6iUl9pwyo4sVyLHgMzZpiQvGoRNy +u80tjy6bVP3dGa5VHm36pENC4Q== +-----END PRIVATE KEY----- diff --git a/tests/clienttest.c b/tests/clienttest.c new file mode 100644 index 0000000..8fb5a1d --- /dev/null +++ b/tests/clienttest.c @@ -0,0 +1,754 @@ +/* $OpenBSD: clienttest.c,v 1.42 2023/07/11 17:03:44 tb Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include +#include +#include + +#define DTLS_HM_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH) +#define DTLS_RANDOM_OFFSET (DTLS_HM_OFFSET + 2) +#define DTLS_CIPHER_OFFSET (DTLS_HM_OFFSET + 38) + +#define SSL3_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH) +#define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2) +#define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37) + +#define TLS13_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH) +#define TLS13_RANDOM_OFFSET (TLS13_HM_OFFSET + 2) +#define TLS13_SESSION_OFFSET (TLS13_HM_OFFSET + 34) +#define TLS13_CIPHER_OFFSET (TLS13_HM_OFFSET + 69) +#define TLS13_KEY_SHARE_OFFSET (TLS13_HM_OFFSET + 188) +#define TLS13_ONLY_KEY_SHARE_OFFSET (TLS13_HM_OFFSET + 98) + +#define TLS1_3_VERSION_ONLY (TLS1_3_VERSION | 0x10000) + +int tlsext_linearize_build_order(SSL *); + +static const uint8_t cipher_list_dtls1[] = { + 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, + 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, + 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, + 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t client_hello_dtls1[] = { + 0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x74, 0x01, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xfe, 0xff, 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, 0x26, 0xc0, + 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, + 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, + 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, + 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, + 0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, + 0x18, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, + 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x23, 0x00, + 0x00, +}; + +static const uint8_t cipher_list_dtls12_aes[] = { + 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, + 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, + 0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, + 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, + 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, + 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, + 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, + 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, + 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, + 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, + 0x00, 0x0a, 0x00, 0xff +}; + +static const uint8_t cipher_list_dtls12_chacha[] = { + 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, + 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, + 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, + 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, + 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, + 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, + 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, + 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, + 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, + 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t client_hello_dtls12[] = { + 0x16, 0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, + 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb2, 0xfe, 0xfd, 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, 0x54, 0xc0, + 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, + 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, + 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, + 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, + 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, + 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, + 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, + 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, + 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, + 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, + 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x34, 0x00, + 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, + 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, 0x00, + 0x0d, 0x00, 0x18, 0x00, 0x16, 0x08, 0x06, 0x06, + 0x01, 0x06, 0x03, 0x08, 0x05, 0x05, 0x01, 0x05, + 0x03, 0x08, 0x04, 0x04, 0x01, 0x04, 0x03, 0x02, + 0x01, 0x02, 0x03, +}; + +static const uint8_t cipher_list_tls10[] = { + 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, + 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, + 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, + 0x00, 0x05, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, + 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t client_hello_tls10[] = { + 0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00, + 0x6d, 0x03, 0x01, 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, 0x2c, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, + 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, + 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, + 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff, 0x01, 0x00, 0x00, 0x18, 0x00, 0x0b, + 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, + 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, + 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, +}; + +static const uint8_t cipher_list_tls11[] = { + 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, + 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, + 0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, + 0x00, 0x05, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, + 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t client_hello_tls11[] = { + 0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00, + 0x6d, 0x03, 0x02, 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, 0x2c, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, + 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13, + 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f, + 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff, 0x01, 0x00, 0x00, 0x18, 0x00, 0x0b, + 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, + 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, + 0x00, 0x19, 0x00, 0x23, 0x00, 0x00, +}; + +static const uint8_t cipher_list_tls12_aes[] = { + 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, + 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, + 0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, + 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, + 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, + 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, + 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, + 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, + 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, + 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff, +}; + +static const uint8_t cipher_list_tls12_chacha[] = { + 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, + 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, + 0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, + 0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, + 0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, + 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, + 0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, + 0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, + 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff, +}; + +static const uint8_t client_hello_tls12[] = { + 0x16, 0x03, 0x03, 0x00, 0xbb, 0x01, 0x00, 0x00, + 0xb7, 0x03, 0x03, 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, 0x5a, 0xc0, 0x30, + 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, + 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85, + 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, + 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, + 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, + 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, + 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, + 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0xc0, 0x12, + 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, + 0x01, 0x00, 0x00, 0x34, 0x00, 0x0b, 0x00, 0x02, + 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, + 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, + 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, + 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, + 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, + 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, +}; + +static const uint8_t cipher_list_tls13_aes[] = { + 0x13, 0x02, 0x13, 0x03, 0x13, 0x01, 0xc0, 0x30, + 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, + 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85, + 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, + 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, + 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, + 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, + 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, + 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0xc0, 0x12, + 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t cipher_list_tls13_chacha[] = { + 0x13, 0x03, 0x13, 0x02, 0x13, 0x01, 0xcc, 0xa9, + 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, + 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, + 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, + 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, + 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, + 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, + 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, + 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, + 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0xc0, 0x12, + 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, +}; + +static const uint8_t client_hello_tls13[] = { + 0x16, 0x03, 0x03, 0x01, 0x14, 0x01, 0x00, 0x01, + 0x10, 0x03, 0x03, 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, 0x20, 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, 0x60, 0x13, 0x03, + 0x13, 0x02, 0x13, 0x01, 0xcc, 0xa9, 0xcc, 0xa8, + 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, + 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, + 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, 0x00, 0xc4, + 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 0x00, 0x3d, + 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 0xc0, 0x2f, + 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, + 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x33, + 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 0x00, 0x3c, + 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, 0xc0, 0x11, + 0xc0, 0x07, 0x00, 0x05, 0xc0, 0x12, 0xc0, 0x08, + 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, + 0x00, 0x67, 0x00, 0x2b, 0x00, 0x05, 0x04, 0x03, + 0x04, 0x03, 0x03, 0x00, 0x33, 0x00, 0x26, 0x00, + 0x24, 0x00, 0x1d, 0x00, 0x20, 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, 0x0b, 0x00, + 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, + 0x19, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, + 0x18, 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, + 0x03, 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, + 0x04, 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, + 0x03, +}; + +static const uint8_t cipher_list_tls13_only_aes[] = { + 0x13, 0x02, 0x13, 0x03, 0x13, 0x01, +}; + +static const uint8_t cipher_list_tls13_only_chacha[] = { + 0x13, 0x03, 0x13, 0x02, 0x13, 0x01, +}; + +static const uint8_t client_hello_tls13_only[] = { + 0x16, 0x03, 0x03, 0x00, 0xb6, 0x01, 0x00, 0x00, + 0xb2, 0x03, 0x03, 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, 0x20, 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, 0x08, 0x13, 0x03, + 0x13, 0x02, 0x13, 0x01, 0x00, 0xff, 0x01, 0x00, + 0x00, 0x61, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, + 0x04, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, + 0x1d, 0x00, 0x20, 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, 0x0b, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, + 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, + 0x12, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 0x08, + 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, + 0x01, 0x04, 0x03, +}; + +struct client_hello_test { + const char *desc; + const int protocol; + const size_t random_start; + const size_t session_start; + const size_t key_share_start; + const SSL_METHOD *(*ssl_method)(void); + const long ssl_options; + int connect_fails; +}; + +static const struct client_hello_test client_hello_tests[] = { + { + .desc = "DTLSv1 client method", + .protocol = DTLS1_VERSION, + .random_start = DTLS_RANDOM_OFFSET, + .ssl_method = DTLSv1_client_method, + .connect_fails = 1, + }, + { + .desc = "DTLSv1.2 client method", + .protocol = DTLS1_2_VERSION, + .random_start = DTLS_RANDOM_OFFSET, + .ssl_method = DTLSv1_2_client_method, + }, + { + .desc = "DTLS client method", + .protocol = DTLS1_2_VERSION, + .random_start = DTLS_RANDOM_OFFSET, + .ssl_method = DTLS_client_method, + }, + { + .desc = "DTLS client method (no DTLSv1.2)", + .protocol = DTLS1_VERSION, + .random_start = DTLS_RANDOM_OFFSET, + .ssl_method = DTLS_client_method, + .ssl_options = SSL_OP_NO_DTLSv1_2, + .connect_fails = 1, + }, + { + .desc = "DTLS client method (no DTLSv1.0)", + .protocol = DTLS1_2_VERSION, + .random_start = DTLS_RANDOM_OFFSET, + .ssl_method = DTLS_client_method, + .ssl_options = SSL_OP_NO_DTLSv1, + }, + { + .desc = "TLSv1 client method", + .protocol = TLS1_VERSION, + .random_start = SSL3_RANDOM_OFFSET, + .ssl_method = TLSv1_client_method, + .connect_fails = 1, + }, + { + .desc = "TLSv1_1 client method", + .protocol = TLS1_1_VERSION, + .random_start = SSL3_RANDOM_OFFSET, + .ssl_method = TLSv1_1_client_method, + .connect_fails = 1, + }, + { + .desc = "TLSv1_2 client method", + .protocol = TLS1_2_VERSION, + .random_start = SSL3_RANDOM_OFFSET, + .ssl_method = TLSv1_2_client_method, + }, + { + .desc = "SSLv23 default", + .protocol = TLS1_3_VERSION, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, + .ssl_method = SSLv23_client_method, + .ssl_options = 0, + }, + { + .desc = "SSLv23 default (no TLSv1.3)", + .protocol = TLS1_2_VERSION, + .random_start = SSL3_RANDOM_OFFSET, + .ssl_method = SSLv23_client_method, + .ssl_options = SSL_OP_NO_TLSv1_3, + }, + { + .desc = "SSLv23 (no TLSv1.2)", + .protocol = TLS1_3_VERSION_ONLY, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_ONLY_KEY_SHARE_OFFSET, + .ssl_method = SSLv23_client_method, + .ssl_options = SSL_OP_NO_TLSv1_2, + }, + { + .desc = "SSLv23 (no TLSv1.1)", + .protocol = TLS1_3_VERSION, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, + .ssl_method = SSLv23_client_method, + .ssl_options = SSL_OP_NO_TLSv1_1, + }, + { + .desc = "TLS default", + .protocol = TLS1_3_VERSION, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = 0, + }, + { + .desc = "TLS (no TLSv1.3)", + .protocol = TLS1_2_VERSION, + .random_start = SSL3_RANDOM_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = SSL_OP_NO_TLSv1_3, + }, + { + .desc = "TLS (no TLSv1.2)", + .protocol = TLS1_3_VERSION_ONLY, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_ONLY_KEY_SHARE_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = SSL_OP_NO_TLSv1_2, + }, + { + .desc = "TLS (no TLSv1.1)", + .protocol = TLS1_3_VERSION, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = SSL_OP_NO_TLSv1_1, + }, +#if 0 + /* XXX - build client hello with explicit versions extension. */ + { + .desc = "TLS (no TLSv1.0, no TLSv1.1)", + .protocol = TLS1_3_VERSION, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, + }, +#endif + { + .desc = "TLS (no TLSv1.0, no TLSv1.1, no TLSv1.2)", + .protocol = TLS1_3_VERSION_ONLY, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_ONLY_KEY_SHARE_OFFSET, + .ssl_method = TLS_client_method, + .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, + }, +}; + +#define N_CLIENT_HELLO_TESTS \ + (sizeof(client_hello_tests) / sizeof(*client_hello_tests)) + +static void +hexdump(const uint8_t *buf, size_t len, const uint8_t *compare) +{ + const char *mark = ""; + size_t i; + + for (i = 1; i <= len; i++) { + if (compare != NULL) + mark = (buf[i - 1] != compare[i - 1]) ? "*" : " "; + fprintf(stderr, " %s0x%02hhx,%s", mark, buf[i - 1], + i % 8 && i != len ? "" : "\n"); + } + fprintf(stderr, "\n"); +} + +static inline int +ssl_aes_is_accelerated(void) +{ +#if defined(__i386__) || defined(__x86_64__) + return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); +#else + return (0); +#endif +} + +static int +make_client_hello(int protocol, char **out, size_t *outlen) +{ + size_t client_hello_len, cipher_list_len, cipher_list_offset; + const uint8_t *client_hello, *cipher_list; + char *p; + + *out = NULL; + *outlen = 0; + + switch (protocol) { + case DTLS1_VERSION: + client_hello = client_hello_dtls1; + client_hello_len = sizeof(client_hello_dtls1); + cipher_list = cipher_list_dtls1; + cipher_list_len = sizeof(cipher_list_dtls1); + cipher_list_offset = DTLS_CIPHER_OFFSET; + break; + + case DTLS1_2_VERSION: + client_hello = client_hello_dtls12; + client_hello_len = sizeof(client_hello_dtls12); + cipher_list = cipher_list_dtls12_chacha; + cipher_list_len = sizeof(cipher_list_dtls12_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_dtls12_aes; + cipher_list_len = sizeof(cipher_list_dtls12_aes); + } + cipher_list_offset = DTLS_CIPHER_OFFSET; + break; + + case TLS1_VERSION: + client_hello = client_hello_tls10; + client_hello_len = sizeof(client_hello_tls10); + cipher_list = cipher_list_tls10; + cipher_list_len = sizeof(cipher_list_tls10); + cipher_list_offset = SSL3_CIPHER_OFFSET; + break; + + case TLS1_1_VERSION: + client_hello = client_hello_tls11; + client_hello_len = sizeof(client_hello_tls11); + cipher_list = cipher_list_tls11; + cipher_list_len = sizeof(cipher_list_tls11); + cipher_list_offset = SSL3_CIPHER_OFFSET; + break; + + case TLS1_2_VERSION: + client_hello = client_hello_tls12; + client_hello_len = sizeof(client_hello_tls12); + cipher_list = cipher_list_tls12_chacha; + cipher_list_len = sizeof(cipher_list_tls12_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_tls12_aes; + cipher_list_len = sizeof(cipher_list_tls12_aes); + } + cipher_list_offset = SSL3_CIPHER_OFFSET; + break; + + case TLS1_3_VERSION: + client_hello = client_hello_tls13; + client_hello_len = sizeof(client_hello_tls13); + cipher_list = cipher_list_tls13_chacha; + cipher_list_len = sizeof(cipher_list_tls13_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_tls13_aes; + cipher_list_len = sizeof(cipher_list_tls13_aes); + } + cipher_list_offset = TLS13_CIPHER_OFFSET; + break; + + case TLS1_3_VERSION_ONLY: + client_hello = client_hello_tls13_only; + client_hello_len = sizeof(client_hello_tls13_only); + cipher_list = cipher_list_tls13_only_chacha; + cipher_list_len = sizeof(cipher_list_tls13_only_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_tls13_only_aes; + cipher_list_len = sizeof(cipher_list_tls13_only_aes); + } + cipher_list_offset = TLS13_CIPHER_OFFSET; + break; + + default: + return (-1); + } + + if ((p = malloc(client_hello_len)) == NULL) + return (-1); + + memcpy(p, client_hello, client_hello_len); + memcpy(p + cipher_list_offset, cipher_list, cipher_list_len); + + *out = p; + *outlen = client_hello_len; + + return (0); +} + +static int +client_hello_test(int testno, const struct client_hello_test *cht) +{ + BIO *rbio = NULL, *wbio = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + char *client_hello = NULL; + size_t client_hello_len; + size_t session_len; + char *wbuf, rbuf[1]; + int ret = 1; + long len; + + fprintf(stderr, "Test %d - %s\n", testno, cht->desc); + + /* Providing a small buf causes *_get_server_hello() to return. */ + if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) { + fprintf(stderr, "Failed to setup rbio\n"); + goto failure; + } + if ((wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "Failed to setup wbio\n"); + goto failure; + } + + if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + + SSL_CTX_set_options(ssl_ctx, cht->ssl_options); + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + + if (!tlsext_linearize_build_order(ssl)) { + fprintf(stderr, "failed to linearize build order"); + goto failure; + } + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + SSL_set_bio(ssl, rbio, wbio); + + if (SSL_connect(ssl) != 0) { + if (cht->connect_fails) + goto done; + fprintf(stderr, "SSL_connect() returned non-zero\n"); + goto failure; + } + + len = BIO_get_mem_data(wbio, &wbuf); + + if (make_client_hello(cht->protocol, &client_hello, + &client_hello_len) != 0) + errx(1, "failed to make client hello"); + + if ((size_t)len != client_hello_len) { + fprintf(stderr, "FAIL: test returned ClientHello length %ld, " + "want %zu\n", len, client_hello_len); + fprintf(stderr, "received:\n"); + hexdump(wbuf, len, NULL); + fprintf(stderr, "test data:\n"); + hexdump(client_hello, client_hello_len, NULL); + fprintf(stderr, "\n"); + goto failure; + } + + /* We expect the client random to differ. */ + if (memcmp(&client_hello[cht->random_start], &wbuf[cht->random_start], + SSL3_RANDOM_SIZE) == 0) { + fprintf(stderr, "FAIL: ClientHello has zeroed random\n"); + goto failure; + } + + memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); + + if (cht->session_start > 0) { + session_len = wbuf[cht->session_start]; + if (session_len > 0) + memset(&wbuf[cht->session_start + 1], 0, session_len); + } + if (cht->key_share_start > 0) + memset(&wbuf[cht->key_share_start], 0, 32); + + if (memcmp(client_hello, wbuf, client_hello_len) != 0) { + fprintf(stderr, "FAIL: ClientHello differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(wbuf, len, client_hello); + fprintf(stderr, "test data:\n"); + hexdump(client_hello, client_hello_len, wbuf); + fprintf(stderr, "\n"); + goto failure; + } + + done: + ret = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + BIO_free(rbio); + BIO_free(wbio); + + free(client_hello); + + return (ret); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + SSL_library_init(); + + for (i = 0; i < N_CLIENT_HELLO_TESTS; i++) + failed |= client_hello_test(i, &client_hello_tests[i]); + + return (failed); +} diff --git a/tests/cmstest.c b/tests/cmstest.c new file mode 100644 index 0000000..c207b9e --- /dev/null +++ b/tests/cmstest.c @@ -0,0 +1,326 @@ +/* $OpenBSD: cmstest.c,v 1.7 2023/03/02 21:08:14 tb Exp $ */ +/* + * Copyright (c) 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#include + +static int verbose = 0; + +static const char cms_msg[] = "Hello CMS!\r\n"; + +static const char cms_ca_1[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICqDCCAZACCQD8ebR8e4kdvjANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtU\n" + "ZXN0IENNUyBDQTAeFw0xOTA1MTExNTUzNTNaFw0yOTA1MDgxNTUzNTNaMBYxFDAS\n" + "BgNVBAMMC1Rlc3QgQ01TIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\n" + "AQEAoIiW3POGYfhY0BEgG8mIwouOI917M72jsuUE57ccjEXLWseItLb7r9vkiwW/\n" + "FYbz0UYkJW1JgpZmWaTGOgZGxj+WTzxh1aq7OHyJb6Pxwp9wGrGJu+BEqOZN/bi/\n" + "aQ1l8x7DxVJkFeI1+4QKDfmGYfWoVzQLgamO3u0vxz3Vi/XzX01ZomcZUYYx0lIq\n" + "hxAO665HoPUmecqYdLPquJNxdfiy37ieLJOmIsKZJtMcCZAxqhcCwE7I0196Ng3P\n" + "fK9Sl7BCyTBszb2YC2qOleuI2Wjg/7o1+hugopUkjxz0RGFu5s3K9PhCLwpqylXg\n" + "IXe9Vwi38gKawD3yjtDBRDNmIwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAvsvtc\n" + "cO0Eo0F6MvB0bjBIMHBkKyWcmD2c5gVFhbHyRD+XBVXNdn5CcBba2amm0VgShBpM\n" + "4e1rOtIH/Hf6nB3c/EjZvd16ryoTCTvzayac7sD2Y8IxF1JIAKvjFbu+LmzM/F5f\n" + "x3/WdY1qs5W7lO46i8xmSUAP88gohWP4cyVUAITNrh/RSOFaWUd5i1/vZ+iEexLI\n" + "rQWsweJleOxvA8SrXm2gAkqRWEncsxOrsX/MsPl7iJoebLhWbS3cOHhutWrfhdlC\n" + "2uT6K7SA9rn6qqmvI6mLkHJQpqq++Py2UTDo1u8VKa3ieYNUN070kgxpYiVBGs3L\n" + "aaACIcEs48gnTRWc\n" + "-----END CERTIFICATE-----\n"; + +static const char cms_cert_1[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICpDCCAYwCAQMwDQYJKoZIhvcNAQEFBQAwFjEUMBIGA1UEAwwLVGVzdCBDTVMg\n" + "Q0EwHhcNMTkwNTExMTU1MzU0WhcNMjkwNTA4MTU1MzU0WjAaMRgwFgYDVQQDDA9U\n" + "ZXN0IENNUyBDZXJ0IDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDD\n" + "MLSuy+tc0AwfrlszgHJ3z7UEpJSn5mcKxquFnEC5DtchgQJ+cj5VFvB9A9G98ykQ\n" + "0IrHXNUTbS2yvf8ac1PlocuA8ggeDK4gPHCe097j0nUphhT0VzhwwFfP6Uo6VaR8\n" + "B7Qb3zFTz64bN66V89etZ5NQJKMdrh4oOh5nfxLKvCcTK+9U4ZrgeGVdVXmL6HJp\n" + "3m9CPobCBsC8DgI+zF/tg4GjDoVCJd6Tv5MRAmKiBrzTGglVeknkgiyIZ9C7gXU/\n" + "7NMUihmLlt+80zr+nL0P+MA924WV4fZJi1wtf6Eioalq6n/9i93nBRCeu8bEOBrT\n" + "pAre2oBEoULIJu7Ubx79AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBADnLc6ZzApHq\n" + "Z8l4zrFKAG/O/oULPMRTA8/zXNQ60BMV10hVtTCxVNq59d48wEljuUOGLfM91rhj\n" + "gId8AOlsQbfRZE94DxlcaaAXaEjbkVSke56yfdLd4NqkIWrXGrFlbepj4b4ORAHh\n" + "85kPwDEDnpMgQ63LqNX3gru3xf2AGIa1Fck2ISkVafqW5TH0Y6dCeGGFTtnH/QUT\n" + "ofTm8uQ2vG9ERn+C1ooqJ2dyAckXFdmCcpor26vO/ZssMEKSee38ZNWR/01LEkOG\n" + "G0+AL7E1mJdlVOtp3DDFN0hoNY7PbVuuzT+mrAwGLhCp2jnf68iNdrIuDdIE6yvi\n" + "6WWvmmz+rC0=\n" + "-----END CERTIFICATE-----\n"; + +static const char cms_key_1[] = + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDDMLSuy+tc0Awf\n" + "rlszgHJ3z7UEpJSn5mcKxquFnEC5DtchgQJ+cj5VFvB9A9G98ykQ0IrHXNUTbS2y\n" + "vf8ac1PlocuA8ggeDK4gPHCe097j0nUphhT0VzhwwFfP6Uo6VaR8B7Qb3zFTz64b\n" + "N66V89etZ5NQJKMdrh4oOh5nfxLKvCcTK+9U4ZrgeGVdVXmL6HJp3m9CPobCBsC8\n" + "DgI+zF/tg4GjDoVCJd6Tv5MRAmKiBrzTGglVeknkgiyIZ9C7gXU/7NMUihmLlt+8\n" + "0zr+nL0P+MA924WV4fZJi1wtf6Eioalq6n/9i93nBRCeu8bEOBrTpAre2oBEoULI\n" + "Ju7Ubx79AgMBAAECggEAD4XkGLKm+S6iiDJ5llL0x4qBPulH2UJ9l2HNakbO7ui7\n" + "OzLjW+MCCgpU/dw75ftcnLW5E7nSSEU6iSiLDTN2zKBdatfUxW8EuhOUcU0wQLYQ\n" + "E0lSiUwWdQEW+rX27US6XBLQxBav+ZZeplN7UvmdgXDnSkxfnJCoXVKh8GEuwWip\n" + "sM/Lwg8MSZK0o5qFVXtPp7kreB8CWlVyPYW5rDYy3k02R1t9k6WSdO2foPXe9rdZ\n" + "iiThkALcHdBcFF0NHrIkAgMdtcAxkDIwO2kOnGJQKDXu+txbzPYodMU0Z6eVnlIu\n" + "jh9ZjnZKBJgX6YVLVPRBwQXHXeGAnvMNm2WXH7SCAQKBgQDmMxvspc3K6HOqMoik\n" + "59Rq1gXIuaGH0uSMSiUMTkr4laJbh9WgZ6JTAfIPuhj1xKGfDK7LF9VjPQ104SgL\n" + "dCA1pV6nsuGS3j3vBnaMfmO7yr3yON+p/WDpKOgqC51Z3/pT8reJtMnyowQuDeYe\n" + "UVRVyeXA11nve0SSc97US4AtXQKBgQDZERtgs6ejiUJQXuflu9HDczEZ/pHfPI1y\n" + "+RU0tvI4860OTjerVJA2YBeOBLa9Y3hblvNpOU0SoVeMAGQLblEznJAl1nbaWqVY\n" + "kPgvtQcTOL/awEB90JklvSRqR82WJchMOHMG5SeqrpUx3Dg+cPH6nId0e8UCt3/U\n" + "W/u/5hP+IQKBgQDfReEmxaZ10MIm6P6p24Wm3dEcYBfxEjbEb0HBzspek1u3JWep\n" + "PfsuQavTXy/IaKBOENIUgBhjOZssqxnZChgXkD7frtulRNOTW5RuLkRzp3BWWJ1v\n" + "VifB3gBYj41d16UH+VnVQbnCEiUCuk5hR4bh8oJaaUV8xvW6ipItHNHErQKBgGoe\n" + "2uuj6UkiSbFRNL4z3JFZN6AlvNsOl3imHZ/v8Ou29dwQkVbJuNdckydzVoOwpZ7h\n" + "ZY8D3JJHHq3rYv3TqQ86c56MAv8tYbiy5yMrtZHIJMOlSeI4oSa6GZt8Dx5gylO5\n" + "JUMxtPrU70u5BiZAwYxsCi0AdYimfXAsqB9hNFUBAoGBAJPT7Xsr7NIkrbv+aYXj\n" + "rVVJ1qokUEKT6H1GmFXO3Fkw3kjPKS8VZloKOB7OiBC+AwMEQIflArCZ+PJdnVNO\n" + "48ntHnaeaZk8rKXsYdJsqMKgIxZYZuCIazZz9WHeYxn5vkH76Q3DrfqrneJ3HSU/\n" + "pFtLoXoGoVXRjAtpNvX7fh/G\n" + "-----END PRIVATE KEY-----\n"; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\n"); + if (len % 8 != 0) + fprintf(stderr, "\n"); +} + +static int +test_cms_encrypt_decrypt(void) +{ + STACK_OF(X509) *certs = NULL; + CMS_ContentInfo *ci = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio_mem = NULL; + BIO *bio_out = NULL; + X509 *cert = NULL; + size_t len; + long mem_len; + char *p; + int failed = 1; + + if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) + errx(1, "failed to create BIO"); + + if ((certs = sk_X509_new_null()) == NULL) + errx(1, "failed to create certs"); + if ((bio_mem = BIO_new_mem_buf(cms_cert_1, -1)) == NULL) + errx(1, "failed to create BIO for cert"); + if ((cert = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read cert"); + if (!sk_X509_push(certs, cert)) + errx(1, "failed to push cert"); + + BIO_free(bio_mem); + if ((bio_mem = BIO_new_mem_buf(cms_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read key"); + + BIO_free(bio_mem); + if ((bio_mem = BIO_new_mem_buf(cms_msg, -1)) == NULL) + errx(1, "failed to create BIO for message"); + + if ((ci = CMS_encrypt(certs, bio_mem, EVP_aes_256_cbc(), 0)) == NULL) { + fprintf(stderr, "FAIL: CMS_encrypt returned NULL\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (verbose) { + if (!CMS_ContentInfo_print_ctx(bio_out, ci, 0, NULL)) + errx(1, "failed to print CMS ContentInfo"); + if (!PEM_write_bio_CMS(bio_out, ci)) + errx(1, "failed to print CMS PEM"); + } + + BIO_free(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "failed to create BIO for message"); + + if (!CMS_decrypt(ci, pkey, cert, NULL, bio_mem, 0)) { + fprintf(stderr, "FAIL: CMS_decrypt failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if ((mem_len = BIO_get_mem_data(bio_mem, &p)) <= 0) { + fprintf(stderr, "FAIL: BIO_get_mem_data returned %ld\n", + mem_len); + goto failure; + } + if ((len = strlen(cms_msg)) != (size_t)mem_len) { + fprintf(stderr, "FAIL: CMS decrypt returned %ld bytes, " + "want %zu bytes\n", mem_len, len); + fprintf(stderr, "Got CMS data:\n"); + hexdump(p, mem_len); + fprintf(stderr, "Want CMS data:\n"); + hexdump(cms_msg, len); + goto failure; + } + if (memcmp(p, cms_msg, len) != 0) { + fprintf(stderr, "FAIL: CMS decrypt message differs"); + fprintf(stderr, "Got CMS data:\n"); + hexdump(p, mem_len); + fprintf(stderr, "Want CMS data:\n"); + hexdump(cms_msg, len); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio_mem); + BIO_free(bio_out); + CMS_ContentInfo_free(ci); + EVP_PKEY_free(pkey); + sk_X509_free(certs); + X509_free(cert); + + return failed; +} + +static int +test_cms_sign_verify(void) +{ + STACK_OF(X509) *certs = NULL; + CMS_ContentInfo *ci = NULL; + X509_STORE *store = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio_mem = NULL; + BIO *bio_out = NULL; + X509 *cert = NULL; + X509 *ca = NULL; + size_t len; + long mem_len; + char *p; + int failed = 1; + + if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) + errx(1, "failed to create BIO"); + + if ((certs = sk_X509_new_null()) == NULL) + errx(1, "failed to create certs"); + if ((bio_mem = BIO_new_mem_buf(cms_cert_1, -1)) == NULL) + errx(1, "failed to create BIO for cert"); + if ((cert = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read cert"); + if (!sk_X509_push(certs, cert)) + errx(1, "failed to push cert"); + + BIO_free(bio_mem); + if ((bio_mem = BIO_new_mem_buf(cms_ca_1, -1)) == NULL) + errx(1, "failed to create BIO for cert"); + if ((ca = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read cert"); + if ((store = X509_STORE_new()) == NULL) + errx(1, "failed to create X509 store"); + if (!X509_STORE_add_cert(store, ca)) + errx(1, "failed to add cert to store"); + + BIO_free(bio_mem); + if ((bio_mem = BIO_new_mem_buf(cms_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio_mem, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read key"); + + BIO_free(bio_mem); + if ((bio_mem = BIO_new_mem_buf(cms_msg, -1)) == NULL) + errx(1, "failed to create BIO for message"); + + if ((ci = CMS_sign(cert, pkey, NULL, bio_mem, 0)) == NULL) { + fprintf(stderr, "FAIL: CMS sign failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (verbose) { + if (!CMS_ContentInfo_print_ctx(bio_out, ci, 0, NULL)) + errx(1, "failed to print CMS ContentInfo"); + if (!PEM_write_bio_CMS(bio_out, ci)) + errx(1, "failed to print CMS PEM"); + } + + BIO_free(bio_mem); + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "failed to create BIO for message"); + + if (!CMS_verify(ci, certs, store, NULL, bio_mem, 0)) { + fprintf(stderr, "FAIL: CMS_verify failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if ((mem_len = BIO_get_mem_data(bio_mem, &p)) <= 0) { + fprintf(stderr, "FAIL: BIO_get_mem_data returned %ld\n", + mem_len); + goto failure; + } + if ((len = strlen(cms_msg)) != (size_t)mem_len) { + fprintf(stderr, "FAIL: CMS verify returned %ld bytes, " + "want %zu bytes\n", mem_len, len); + fprintf(stderr, "Got CMS data:\n"); + hexdump(p, mem_len); + fprintf(stderr, "Want CMS data:\n"); + hexdump(cms_msg, len); + goto failure; + } + if (memcmp(p, cms_msg, len) != 0) { + fprintf(stderr, "FAIL: CMS verify message differs"); + fprintf(stderr, "Got CMS data:\n"); + hexdump(p, mem_len); + fprintf(stderr, "Want CMS data:\n"); + hexdump(cms_msg, len); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio_mem); + BIO_free(bio_out); + CMS_ContentInfo_free(ci); + EVP_PKEY_free(pkey); + sk_X509_free(certs); + X509_free(cert); + X509_STORE_free(store); + X509_free(ca); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + ERR_load_crypto_strings(); + + failed |= test_cms_encrypt_decrypt(); + failed |= test_cms_sign_verify(); + + return failed; +} diff --git a/tests/compat/memmem.c b/tests/compat/memmem.c new file mode 100644 index 0000000..9b11960 --- /dev/null +++ b/tests/compat/memmem.c @@ -0,0 +1,183 @@ +/* $OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */ + +/* + * Copyright (c) 2005-2020 Rich Felker, et al. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +static char * +twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; + for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-2; + return hw == nw ? (char *)h-2 : 0; +} + +static char * +threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; + for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) + if (hw == nw) return (char *)h-3; + return hw == nw ? (char *)h-3 : 0; +} + +static char * +fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; + for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-4; + return hw == nw ? (char *)h-4 : 0; +} + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BITOP(a,b,op) \ + ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) + +/* + * Maxime Crochemore and Dominique Perrin, Two-way string-matching, + * Journal of the ACM, 38(3):651-675, July 1991. + */ +static char * +twoway_memmem(const unsigned char *h, const unsigned char *z, + const unsigned char *n, size_t l) +{ + size_t i, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (i=0; i n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (memcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Search loop */ + for (;;) { + /* If remainder of haystack is shorter than needle, done */ + if (z-h < l) return 0; + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l-1], &)) { + k = l-shift[h[l-1]]; + if (k) { + if (k < mem) k = mem; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); + if (k <= mem) return (char *)h; + h += p; + mem = mem0; + } +} + +void * +memmem(const void *h0, size_t k, const void *n0, size_t l) +{ + const unsigned char *h = h0, *n = n0; + + /* Return immediately on empty needle */ + if (!l) return (void *)h; + + /* Return immediately when needle is longer than haystack */ + if (k + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +struct parse_protocols_test { + const char *protostr; + int want_return; + uint32_t want_protocols; +}; + +struct parse_protocols_test parse_protocols_tests[] = { + { + .protostr = NULL, + .want_return = 0, + .want_protocols = TLS_PROTOCOLS_DEFAULT, + }, + { + .protostr = "default", + .want_return = 0, + .want_protocols = TLS_PROTOCOLS_DEFAULT, + }, + { + .protostr = "secure", + .want_return = 0, + .want_protocols = TLS_PROTOCOLS_DEFAULT, + }, + { + .protostr = "all", + .want_return = 0, + .want_protocols = TLS_PROTOCOLS_ALL, + }, + { + .protostr = "tlsv1", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1, + }, + { + .protostr = "tlsv1.2", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2, + }, + { + .protostr = "tlsv1.3", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_3, + }, + { + .protostr = "", + .want_return = -1, + .want_protocols = 0, + }, + { + .protostr = "tlsv1.0:tlsv1.1:tlsv1.2:tlsv1.3", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3, + }, + { + .protostr = "tlsv1.0,tlsv1.1,tlsv1.2,tlsv1.3", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2 | TLS_PROTOCOL_TLSv1_3, + }, + { + .protostr = "tlsv1.1,tlsv1.2,tlsv1.0", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2, + }, + { + .protostr = "tlsv1.1,tlsv1.2,tlsv1.1", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2, + }, + { + .protostr = "tlsv1.1,tlsv1.2,!tlsv1.1", + .want_return = 0, + .want_protocols = 0, + }, + { + .protostr = "unknown", + .want_return = -1, + .want_protocols = 0, + }, + { + .protostr = "all,!unknown", + .want_return = -1, + .want_protocols = 0, + }, + { + .protostr = "sslv3,tlsv1.0,tlsv1.1,tlsv1.2", + .want_return = -1, + .want_protocols = 0, + }, + { + .protostr = "all,!tlsv1.0", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_3, + }, + { + .protostr = "!tlsv1.0", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_3, + }, + { + .protostr = "!tlsv1.0,!tlsv1.1,!tlsv1.3", + .want_return = 0, + .want_protocols = 0, + }, + { + .protostr = "!tlsv1.0,!tlsv1.1,tlsv1.2,!tlsv1.3", + .want_return = 0, + .want_protocols = TLS_PROTOCOL_TLSv1_2, + }, +}; + +#define N_PARSE_PROTOCOLS_TESTS \ + (sizeof(parse_protocols_tests) / sizeof(*parse_protocols_tests)) + +static int +do_parse_protocols_test(int test_no, struct parse_protocols_test *ppt) +{ + uint32_t protocols = 0; + int failed = 1; + int rv; + + rv = tls_config_parse_protocols(&protocols, ppt->protostr); + if (rv != ppt->want_return) { + fprintf(stderr, "FAIL: test %i - tls_config_parse_protocols() " + "returned %i, want %i\n", test_no, rv, ppt->want_return); + goto done; + } + if (protocols != ppt->want_protocols) { + fprintf(stderr, "FAIL: test %i - got protocols 0x%x, " + "want 0x%x\n", test_no, protocols, ppt->want_protocols); + goto done; + } + + failed = 0; + + done: + return (failed); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + tls_init(); + + for (i = 0; i < N_PARSE_PROTOCOLS_TESTS; i++) + failed += do_parse_protocols_test(i, &parse_protocols_tests[i]); + + return (failed); +} diff --git a/tests/constraints.c b/tests/constraints.c new file mode 100644 index 0000000..6677b58 --- /dev/null +++ b/tests/constraints.c @@ -0,0 +1,584 @@ +/* $OpenBSD: constraints.c,v 1.17 2023/10/01 04:48:39 tb Exp $ */ +/* + * Copyright (c) 2020 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include "x509_internal.h" + +#define FAIL(msg, ...) \ +do { \ + fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \ + fprintf(stderr, msg, ##__VA_ARGS__); \ +} while(0) + +unsigned char *valid_hostnames[] = { + "openbsd.org", + "op3nbsd.org", + "org", + "3openbsd.com", + "3-0penb-d.c-m", + "a", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "open_bsd.org", /* because this is liberal */ + NULL, +}; + +unsigned char *valid_sandns_names[] = { + "*.ca", + "*.op3nbsd.org", + "c*.openbsd.org", + "foo.*.d*.c*.openbsd.org", + NULL, +}; + +unsigned char *valid_domain_constraints[] = { + "", + ".ca", + ".op3nbsd.org", + ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "www.openbsd.org", + NULL, +}; + +unsigned char *valid_mbox_names[] = { + "\"!#$%&\\\"*+-/=?\002^_`{|}~.\"@openbsd.org", + "beck@openbsd.org", + "beck@openbsd.org", + "beck@op3nbsd.org", + "beck@org", + "beck@3openbsd.com", + "beck@3-0penb-d.c-m", + "bec@a", + "beck@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + "beck@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "beck@open_bsd.org", /* because this is liberal */ + NULL, +}; + +unsigned char *invalid_hostnames[] = { + "openbsd.org.", + "openbsd..org", + "openbsd.org-", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a", + "-p3nbsd.org", + "openbs-.org", + "openbsd\n.org", + "open\178bsd.org", + "open\255bsd.org", + "*.openbsd.org", + NULL, +}; + +unsigned char *invalid_sandns_names[] = { + "", + ".", + "*.a", + "*.", + "*.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a", + "*.-p3nbsd.org", + "*.*..openbsd.org", + "*..openbsd.org", + ".openbsd.org", + "c*c.openbsd.org", + NULL, +}; + +unsigned char *invalid_mbox_names[] = { + "beck@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + "beck@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a", + "beck@.-openbsd.org", + "beck@.openbsd.org.", + "beck@.a", + "beck@.", + "beck@", + "beck@.ca", + "@openbsd.org", + NULL, +}; + +unsigned char *invalid_domain_constraints[] = { + ".", + ".a", + "..", + ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + ".aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a", + ".-p3nbsd.org", + "..openbsd.org", + NULL, +}; + +unsigned char *invaliduri[] = { + "https://-www.openbsd.org", + "https://.www.openbsd.org/", + "https://www.ope|nbsd.org%", + "https://www.openbsd.org.#", + "https://192.168.1.1./", + "https://192.168.1.1|/", + "https://.192.168.1.1/", + "https://192.168..1.1/", + "https://.2001:0DB8:AC10:FE01::/", + "https://.2001:0DB8:AC10:FE01::|/", + "///", + "//", + "/", + "", + NULL, +}; + +unsigned char *validuri[] = { + "https://www.openbsd.org/meep/meep/meep/", + "https://192.168.1.1/", + "https://2001:0DB8:AC10:FE01::/", + "https://192.168.1/", /* Not an IP, but valid component */ + "https://999.999.999.999/", /* Not an IP, but valid component */ + NULL, +}; + +static int +test_valid_hostnames(void) +{ + int i, failure = 0; + + for (i = 0; valid_hostnames[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, valid_hostnames[i], strlen(valid_hostnames[i])); + if (!x509_constraints_valid_host(&cbs, 0)) { + FAIL("Valid hostname '%s' rejected\n", + valid_hostnames[i]); + failure = 1; + goto done; + } + CBS_init(&cbs, valid_hostnames[i], strlen(valid_hostnames[i])); + if (!x509_constraints_valid_sandns(&cbs)) { + FAIL("Valid sandns '%s' rejected\n", + valid_hostnames[i]); + failure = 1; + goto done; + } + } + + done: + return failure; +} + +static int +test_valid_sandns_names(void) +{ + int i, failure = 0; + for (i = 0; valid_sandns_names[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, valid_sandns_names[i], + strlen(valid_sandns_names[i])); + if (!x509_constraints_valid_sandns(&cbs)) { + FAIL("Valid dnsname '%s' rejected\n", + valid_sandns_names[i]); + failure = 1; + goto done; + } + } + + done: + return failure; +} + +static int +test_valid_domain_constraints(void) +{ + int i, failure = 0; + for (i = 0; valid_domain_constraints[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, valid_domain_constraints[i], + strlen(valid_domain_constraints[i])); + if (!x509_constraints_valid_domain_constraint(&cbs)) { + FAIL("Valid dnsname '%s' rejected\n", + valid_domain_constraints[i]); + failure = 1; + goto done; + } + } + + done: + return failure; +} + +static int +test_valid_mbox_names(void) +{ + struct x509_constraints_name name = {0}; + int i, failure = 0; + for (i = 0; valid_mbox_names[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, valid_mbox_names[i], + strlen(valid_mbox_names[i])); + if (!x509_constraints_parse_mailbox(&cbs, &name)) { + FAIL("Valid mailbox name '%s' rejected\n", + valid_mbox_names[i]); + failure = 1; + goto done; + } + free(name.name); + name.name = NULL; + free(name.local); + name.local = NULL; + } + + done: + return failure; +} + +static int +test_invalid_hostnames(void) +{ + int i, failure = 0; + char *nulhost = "www.openbsd.org\0"; + CBS cbs; + + for (i = 0; invalid_hostnames[i] != NULL; i++) { + CBS_init(&cbs, invalid_hostnames[i], + strlen(invalid_hostnames[i])); + if (x509_constraints_valid_host(&cbs, 0)) { + FAIL("Invalid hostname '%s' accepted\n", + invalid_hostnames[i]); + failure = 1; + goto done; + } + } + CBS_init(&cbs, nulhost, strlen(nulhost) + 1); + if (x509_constraints_valid_host(&cbs, 0)) { + FAIL("hostname with NUL byte accepted\n"); + failure = 1; + goto done; + } + CBS_init(&cbs, nulhost, strlen(nulhost) + 1); + if (x509_constraints_valid_sandns(&cbs)) { + FAIL("sandns with NUL byte accepted\n"); + failure = 1; + goto done; + } + + done: + return failure; +} + +static int +test_invalid_sandns_names(void) +{ + int i, failure = 0; + for (i = 0; invalid_sandns_names[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, invalid_sandns_names[i], + strlen(invalid_sandns_names[i])); + if (x509_constraints_valid_sandns(&cbs)) { + FAIL("Valid dnsname '%s' rejected\n", + invalid_sandns_names[i]); + failure = 1; + goto done; + } + } + + done: + return failure; +} + +static int +test_invalid_mbox_names(void) +{ + int i, failure = 0; + struct x509_constraints_name name = {0}; + for (i = 0; invalid_mbox_names[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, invalid_mbox_names[i], + strlen(invalid_mbox_names[i])); + if (x509_constraints_parse_mailbox(&cbs, &name)) { + FAIL("invalid mailbox name '%s' accepted\n", + invalid_mbox_names[i]); + failure = 1; + goto done; + } + free(name.name); + name.name = NULL; + free(name.local); + name.local = NULL; + } + + done: + return failure; +} + +static int +test_invalid_domain_constraints(void) +{ + int i, failure = 0; + for (i = 0; invalid_domain_constraints[i] != NULL; i++) { + CBS cbs; + CBS_init(&cbs, invalid_domain_constraints[i], + strlen(invalid_domain_constraints[i])); + if (x509_constraints_valid_domain_constraint(&cbs)) { + FAIL("invalid dnsname '%s' accepted\n", + invalid_domain_constraints[i]); + failure = 1; + goto done; + } + } + + done: + return failure; +} + +static int +test_invalid_uri(void) +{ + int j, failure = 0; + char *hostpart = NULL; + + for (j = 0; invaliduri[j] != NULL; j++) { + if (x509_constraints_uri_host(invaliduri[j], + strlen(invaliduri[j]), &hostpart) != 0) { + FAIL("invalid URI '%s' accepted\n", + invaliduri[j]); + failure = 1; + goto done; + } + free(hostpart); + hostpart = NULL; + } + + done: + return failure; +} + +static int +test_valid_uri(void) +{ + int j, failure = 0; + char *hostpart = NULL; + + for (j = 0; validuri[j] != NULL; j++) { + if (x509_constraints_uri_host(validuri[j], + strlen(invaliduri[j]), &hostpart) == 0) { + FAIL("Valid URI '%s' NOT accepted\n", + validuri[j]); + failure = 1; + goto done; + } + free(hostpart); + hostpart = NULL; + } + + done: + return failure; +} + +static int +test_constraints1(void) +{ + char *c; + size_t cl; + char *d; + size_t dl; + int failure = 0; + int error = 0; + int i, j; + unsigned char *constraints[] = { + ".org", + ".openbsd.org", + "www.openbsd.org", + NULL, + }; + unsigned char *failing[] = { + ".ca", + "openbsd.ca", + "org", + NULL, + }; + unsigned char *matching[] = { + "www.openbsd.org", + NULL, + }; + unsigned char *matchinguri[] = { + "https://www.openbsd.org", + "https://www.openbsd.org/", + "https://www.openbsd.org?", + "https://www.openbsd.org#", + "herp://beck@www.openbsd.org:", + "spiffe://beck@www.openbsd.org/this/is/so/spiffe/", + NULL, + }; + unsigned char *failinguri[] = { + "https://www.openbsd.ca", + "https://www.freebsd.com/", + "https://www.openbsd.net?", + "https://org#", + "herp://beck@org:", + "///", + "//", + "/", + "", + NULL, + }; + unsigned char *noauthority[] = { + "urn:open62541.server.application", + NULL, + }; + for (i = 0; constraints[i] != NULL; i++) { + char *constraint = constraints[i]; + size_t clen = strlen(constraints[i]); + for (j = 0; matching[j] != NULL; j++) { + if (!x509_constraints_domain(matching[j], + strlen(matching[j]), constraint, clen)) { + FAIL("constraint '%s' should have matched" + " '%s'\n", + constraint, matching[j]); + failure = 1; + goto done; + } + } + for (j = 0; matchinguri[j] != NULL; j++) { + error = 0; + if (!x509_constraints_uri(matchinguri[j], + strlen(matchinguri[j]), constraint, clen, &error)) { + FAIL("constraint '%s' should have matched URI" + " '%s' (error %d)\n", + constraint, matchinguri[j], error); + failure = 1; + goto done; + } + } + for (j = 0; failing[j] != NULL; j++) { + if (x509_constraints_domain(failing[j], + strlen(failing[j]), constraint, clen)) { + FAIL("constraint '%s' should not have matched" + " '%s'\n", + constraint, failing[j]); + failure = 1; + goto done; + } + } + for (j = 0; failinguri[j] != NULL; j++) { + error = 0; + if (x509_constraints_uri(failinguri[j], + strlen(failinguri[j]), constraint, clen, &error)) { + FAIL("constraint '%s' should not have matched URI" + " '%s' (error %d)\n", + constraint, failinguri[j], error); + failure = 1; + goto done; + } + } + for (j = 0; noauthority[j] != NULL; j++) { + char *hostpart = NULL; + error = 0; + if (!x509_constraints_uri_host(noauthority[j], + strlen(noauthority[j]), NULL) || + !x509_constraints_uri_host(noauthority[j], + strlen(noauthority[j]), &hostpart)) { + FAIL("name '%s' should parse as a URI", + noauthority[j]); + failure = 1; + free(hostpart); + goto done; + } + free(hostpart); + + if (x509_constraints_uri(noauthority[j], + strlen(noauthority[j]), constraint, clen, &error)) { + FAIL("constraint '%s' should not have matched URI" + " '%s' (error %d)\n", + constraint, failinguri[j], error); + failure = 1; + goto done; + } + } + } + c = ".openbsd.org"; + cl = strlen(".openbsd.org"); + d = "*.openbsd.org"; + dl = strlen("*.openbsd.org"); + if (!x509_constraints_domain(d, dl, c, cl)) { + FAIL("constraint '%s' should have matched '%s'\n", + c, d); + failure = 1; + goto done; + } + c = "www.openbsd.org"; + cl = strlen("www.openbsd.org"); + if (x509_constraints_domain(d, dl, c, cl)) { + FAIL("constraint '%s' should not have matched '%s'\n", + c, d); + failure = 1; + goto done; + } + c = ""; + cl = 0; + if (!x509_constraints_domain(d, dl, c, cl)) { + FAIL("constraint '%s' should have matched '%s'\n", + c, d); + failure = 1; + goto done; + } + + done: + return failure; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_valid_hostnames(); + failed |= test_invalid_hostnames(); + failed |= test_valid_sandns_names(); + failed |= test_invalid_sandns_names(); + failed |= test_valid_mbox_names(); + failed |= test_invalid_mbox_names(); + failed |= test_valid_domain_constraints(); + failed |= test_invalid_domain_constraints(); + failed |= test_invalid_uri(); + failed |= test_valid_uri(); + failed |= test_constraints1(); + + return (failed); +} diff --git a/tests/ctlog.conf b/tests/ctlog.conf new file mode 100644 index 0000000..83a01f6 --- /dev/null +++ b/tests/ctlog.conf @@ -0,0 +1,5 @@ +enabled_logs = argon2022 + +[argon2022] +description = Google Argon 2022 +key = MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeIPc6fGmuBg6AJkv/z7NFckmHvf/OqmjchZJ6wm2qN200keRDg352dWpi7CHnSV51BpQYAj1CQY5JuRAwrrDwg== diff --git a/tests/cttest.c b/tests/cttest.c new file mode 100644 index 0000000..9e0a99b --- /dev/null +++ b/tests/cttest.c @@ -0,0 +1,491 @@ +/* $OpenBSD: cttest.c,v 1.8 2023/04/14 14:36:13 tb Exp $ */ +/* + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#ifndef CTPATH +#define CTPATH "." +#endif + +char *test_ctlog_conf_file; +char *test_cert_file; +char *test_issuer_file; + +const int debug = 0; + +const uint8_t scts_asn1[] = { + 0x04, 0x81, 0xf2, 0x00, 0xf0, 0x00, 0x77, 0x00, + 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21, + 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5, + 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9, + 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84, + 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x1f, 0x6f, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x48, 0x30, 0x46, + 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a, 0x65, 0x98, + 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26, 0xf7, 0x52, + 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0, 0x64, 0xcb, + 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41, 0xe0, 0xbd, + 0x28, 0x56, 0xad, 0x02, 0x21, 0x00, 0xc2, 0x4f, + 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55, 0x67, 0x80, + 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1, 0x96, 0xa7, + 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c, 0x4e, 0x02, + 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8, 0x00, 0x75, + 0x00, 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31, + 0x19, 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff, + 0x77, 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00, + 0x29, 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9, + 0x13, 0x00, 0x00, 0x01, 0x7d, 0x39, 0x51, 0x20, + 0x3b, 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30, + 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28, 0x70, + 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12, 0x1a, + 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83, 0x36, + 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40, 0xe1, + 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae, 0x2b, + 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb, 0x63, + 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a, 0x32, + 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83, 0xa5, + 0x49, 0x00, 0xc4, 0x57, 0xb8, +}; + +const char *sct_log_id1_base64 = "KXm+8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4Q="; + +const uint8_t sct_signature1[] = { + 0x30, 0x46, 0x02, 0x21, 0x00, 0x93, 0xed, 0x3a, + 0x65, 0x98, 0x9a, 0x85, 0xf0, 0x3b, 0x3c, 0x26, + 0xf7, 0x52, 0x94, 0xd7, 0x92, 0x48, 0xc2, 0xc0, + 0x64, 0xcb, 0x01, 0xf5, 0xec, 0xf7, 0x6d, 0x41, + 0xe0, 0xbd, 0x28, 0x56, 0xad, 0x02, 0x21, 0x00, + 0xc2, 0x4f, 0x92, 0xfb, 0xa0, 0xbb, 0xef, 0x55, + 0x67, 0x80, 0x06, 0x10, 0x07, 0xe7, 0xb9, 0xb1, + 0x96, 0xa7, 0xa9, 0x8b, 0xb2, 0xcb, 0xd3, 0x9c, + 0x4e, 0x02, 0xe8, 0xdb, 0x24, 0x65, 0x1e, 0xc8 +}; + +const char *sct_signature1_base64 = + "BAMASDBGAiEAk+06ZZiahfA7PCb3UpTXkkjCwGTLAfXs921B4L0oVq0CIQDCT5L7oLvvVWeABh" + "AH57mxlqepi7LL05xOAujbJGUeyA=="; + +const char *sct_log_id2_base64 = "b1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RM="; + +const uint8_t sct_signature2[] = { + 0x30, 0x44, 0x02, 0x20, 0x26, 0xc9, 0x12, 0x28, + 0x70, 0x2d, 0x15, 0x05, 0xa7, 0xa2, 0xea, 0x12, + 0x1a, 0xff, 0x39, 0x36, 0x5f, 0x93, 0xdf, 0x83, + 0x36, 0x5f, 0xed, 0x07, 0x38, 0xb8, 0x0a, 0x40, + 0xe1, 0x8d, 0xb9, 0xfa, 0x02, 0x20, 0x61, 0xae, + 0x2b, 0x86, 0xbd, 0x8e, 0x86, 0x65, 0x2b, 0xfb, + 0x63, 0xe1, 0xda, 0x77, 0xb3, 0xf3, 0xc5, 0x2a, + 0x32, 0xb8, 0x23, 0x1e, 0x7e, 0xfa, 0x7d, 0x83, + 0xa5, 0x49, 0x00, 0xc4, 0x57, 0xb8 +}; + +const char *sct_signature2_base64 = + "BAMARjBEAiAmyRIocC0VBaei6hIa/zk2X5PfgzZf7Qc4uApA4Y25+gIgYa4rhr2OhmUr+2Ph2n" + "ez88UqMrgjHn76fYOlSQDEV7g="; + +struct sct_data { + uint8_t version; + uint8_t log_id[32]; + uint64_t timestamp; + size_t extensions_len; + int signature_nid; + const uint8_t *signature; + size_t signature_len; +}; + +const struct sct_data sct_test_data[] = { + { + .version = 0, + .log_id = { + 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21, + 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5, + 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9, + 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84, + }, + .timestamp = 1637344157551LL, + .extensions_len = 0, + .signature_nid = NID_ecdsa_with_SHA256, + .signature = sct_signature1, + .signature_len = sizeof(sct_signature1), + }, + { + .version = 0, + .log_id = { + 0x6f, 0x53, 0x76, 0xac, 0x31, 0xf0, 0x31, 0x19, + 0xd8, 0x99, 0x00, 0xa4, 0x51, 0x15, 0xff, 0x77, + 0x15, 0x1c, 0x11, 0xd9, 0x02, 0xc1, 0x00, 0x29, + 0x06, 0x8d, 0xb2, 0x08, 0x9a, 0x37, 0xd9, 0x13 + }, + .timestamp = 1637344157755LL, + .extensions_len = 0, + .signature_nid = NID_ecdsa_with_SHA256, + .signature = sct_signature2, + .signature_len = sizeof(sct_signature2), + }, +}; + +#define N_SCT_TEST_DATA (sizeof(sct_test_data) / sizeof(*sct_test_data)) + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static void +cert_from_file(const char *filename, X509 **cert) +{ + BIO *bio = NULL; + X509 *x; + + if ((bio = BIO_new_file(filename, "r")) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to create bio"); + } + if ((x = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) + errx(1, "failed to read PEM"); + + *cert = x; + + BIO_free(bio); +} + +static int +ct_compare_test_scts(STACK_OF(SCT) *scts) +{ + const struct sct_data *sdt; + BIO *bio_err = NULL; + SCT *sct; + uint8_t *data; + size_t len; + int i; + int ret = 0; + + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + + if (sk_SCT_num(scts) != N_SCT_TEST_DATA) { + fprintf(stderr, "FAIL: got %d SCTS, want %zu\n", + sk_SCT_num(scts), N_SCT_TEST_DATA); + goto failure; + } + + for (i = 0; i < sk_SCT_num(scts); i++) { + sct = sk_SCT_value(scts, i); + sdt = &sct_test_data[i]; + + if (debug > 0) { + SCT_print(sct, bio_err, 0, NULL); + BIO_printf(bio_err, "\n"); + } + + if (SCT_get_version(sct) != sdt->version) { + fprintf(stderr, "FAIL: SCT %d - got version %u, " + "want %u\n", i, SCT_get_version(sct), sdt->version); + goto failure; + } + len = SCT_get0_log_id(sct, &data); + if (len != sizeof(sdt->log_id)) { + fprintf(stderr, "FAIL: SCT %d - got version %u, " + "want %u\n", i, SCT_get_version(sct), sdt->version); + goto failure; + } + if (memcmp(data, sdt->log_id, len) != 0) { + fprintf(stderr, "FAIL: SCT %d - log ID differs\n", i); + fprintf(stderr, "Got:\n"); + hexdump(data, len); + fprintf(stderr, "Want:\n"); + hexdump(sdt->log_id, sizeof(sdt->log_id)); + goto failure; + } + if (SCT_get_timestamp(sct) != sdt->timestamp) { + fprintf(stderr, "FAIL: SCT %d - got timestamp %llu, " + "want %llu\n", i, + (unsigned long long)SCT_get_timestamp(sct), + (unsigned long long)sdt->timestamp); + goto failure; + } + if (SCT_get_signature_nid(sct) != sdt->signature_nid) { + fprintf(stderr, "FAIL: SCT %d - got signature_nid %d, " + "want %d\n", i, SCT_get_signature_nid(sct), + sdt->signature_nid); + goto failure; + } + len = SCT_get0_extensions(sct, &data); + if (len != sdt->extensions_len) { + fprintf(stderr, "FAIL: SCT %d - got extensions with " + "length %zu, want %zu\n", i, len, + sdt->extensions_len); + goto failure; + } + len = SCT_get0_signature(sct, &data); + if (len != sdt->signature_len) { + fprintf(stderr, "FAIL: SCT %d - got signature with " + "length %zu, want %zu\n", i, len, + sdt->signature_len); + goto failure; + } + if (memcmp(data, sdt->signature, len) != 0) { + fprintf(stderr, "FAIL: SCT %d - signature differs\n", + i); + fprintf(stderr, "Got:\n"); + hexdump(data, len); + fprintf(stderr, "Want:\n"); + hexdump(sdt->signature, sdt->signature_len); + goto failure; + } + } + + ret = 1; + + failure: + BIO_free(bio_err); + + return ret; +} + +static int +ct_cert_test(void) +{ + X509 *cert = NULL; + X509_EXTENSION *ext; + STACK_OF(SCT) *scts = NULL; + int idx; + int failed = 1; + + cert_from_file(test_cert_file, &cert); + + if ((idx = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1)) == -1) { + fprintf(stderr, "FAIL: failed to find SCTs\n"); + goto failure; + } + if ((ext = X509_get_ext(cert, idx)) == NULL) { + fprintf(stderr, "FAIL: failed to get SCT extension\n"); + goto failure; + } + if ((scts = X509V3_EXT_d2i(ext)) == NULL) { + fprintf(stderr, "FAIL: failed to decode SCTs\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (!ct_compare_test_scts(scts)) + goto failure; + + failed = 0; + + failure: + SCT_LIST_free(scts); + X509_free(cert); + + return failed; +} + +static int +ct_sct_test(void) +{ + STACK_OF(SCT) *scts = NULL; + const uint8_t *p; + uint8_t *data = NULL; + int len; + int failed = 1; + + p = scts_asn1; + if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) { + fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (!ct_compare_test_scts(scts)) + goto failure; + + data = NULL; + if ((len = i2d_SCT_LIST(scts, &data)) <= 0) { + fprintf(stderr, "FAIL: failed to encode SCTS to ASN.1\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + if (len != sizeof(scts_asn1)) { + fprintf(stderr, "FAIL: ASN.1 length differs - got %d, want " + "%zu\n", len, sizeof(scts_asn1)); + goto failure; + } + if (memcmp(data, scts_asn1, len) != 0) { + fprintf(stderr, "FAIL: ASN.1 for SCTS differs\n"); + fprintf(stderr, "Got:\n"); + hexdump(data, len); + fprintf(stderr, "Want:\n"); + hexdump(scts_asn1, sizeof(scts_asn1)); + goto failure; + } + + failed = 0; + + failure: + SCT_LIST_free(scts); + free(data); + + return failed; +} + +static int +ct_sct_base64_test(void) +{ + SCT *sct1 = NULL, *sct2 = NULL; + STACK_OF(SCT) *scts = NULL; + int failed = 1; + + if ((sct1 = SCT_new_from_base64(SCT_VERSION_V1, sct_log_id1_base64, + CT_LOG_ENTRY_TYPE_X509, 1637344157551LL, "", + sct_signature1_base64)) == NULL) { + fprintf(stderr, "FAIL: SCT_new_from_base64() failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + if ((sct2 = SCT_new_from_base64(SCT_VERSION_V1, sct_log_id2_base64, + CT_LOG_ENTRY_TYPE_X509, 1637344157755LL, "", + sct_signature2_base64)) == NULL) { + fprintf(stderr, "FAIL: SCT_new_from_base64() failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + if ((scts = sk_SCT_new_null()) == NULL) + goto failure; + if (!sk_SCT_push(scts, sct1)) + goto failure; + sct1 = NULL; + if (!sk_SCT_push(scts, sct2)) + goto failure; + sct2 = NULL; + + if (!ct_compare_test_scts(scts)) + goto failure; + + failed = 0; + + failure: + SCT_LIST_free(scts); + SCT_free(sct1); + SCT_free(sct2); + + return failed; +} + +static int +ct_sct_verify_test(void) +{ + STACK_OF(SCT) *scts = NULL; + CT_POLICY_EVAL_CTX *ct_policy = NULL; + CTLOG_STORE *ctlog_store = NULL; + X509 *cert = NULL, *issuer = NULL; + const uint8_t *p; + SCT *sct; + int failed = 1; + + cert_from_file(test_cert_file, &cert); + cert_from_file(test_issuer_file, &issuer); + + if ((ctlog_store = CTLOG_STORE_new()) == NULL) + goto failure; + if (!CTLOG_STORE_load_file(ctlog_store, test_ctlog_conf_file)) + goto failure; + + if ((ct_policy = CT_POLICY_EVAL_CTX_new()) == NULL) + goto failure; + + CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ct_policy, ctlog_store); + CT_POLICY_EVAL_CTX_set_time(ct_policy, 1641393117000LL); + + if (!CT_POLICY_EVAL_CTX_set1_cert(ct_policy, cert)) + goto failure; + if (!CT_POLICY_EVAL_CTX_set1_issuer(ct_policy, issuer)) + goto failure; + + p = scts_asn1; + if ((scts = d2i_SCT_LIST(NULL, &p, sizeof(scts_asn1))) == NULL) { + fprintf(stderr, "FAIL: failed to decode SCTS from ASN.1\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + sct = sk_SCT_value(scts, 0); + + if (!SCT_set_log_entry_type(sct, CT_LOG_ENTRY_TYPE_PRECERT)) + goto failure; + if (!SCT_validate(sct, ct_policy)) { + fprintf(stderr, "FAIL: SCT_validate failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + failed = 0; + + failure: + CT_POLICY_EVAL_CTX_free(ct_policy); + CTLOG_STORE_free(ctlog_store); + X509_free(cert); + X509_free(issuer); + SCT_LIST_free(scts); + + return failed; +} + +int +main(int argc, char **argv) +{ + const char *ctpath = CTPATH; + int failed = 0; + + if (argc > 2) { + fprintf(stderr, "usage %s [ctpath]\n", argv[0]); + exit(1); + } + if (argc == 2) + ctpath = argv[1]; + + if (asprintf(&test_cert_file, "%s/%s", ctpath, + "libressl.org.crt") == -1) + errx(1, "asprintf test_cert_file"); + if (asprintf(&test_issuer_file, "%s/%s", ctpath, + "letsencrypt-r3.crt") == -1) + errx(1, "asprintf test_issuer_file"); + if (asprintf(&test_ctlog_conf_file, "%s/%s", ctpath, + "ctlog.conf") == -1) + errx(1, "asprintf test_ctlog_conf_file"); + + failed |= ct_cert_test(); + failed |= ct_sct_test(); + failed |= ct_sct_base64_test(); + failed |= ct_sct_verify_test(); + + free(test_cert_file); + free(test_issuer_file); + free(test_ctlog_conf_file); + + return (failed); +} diff --git a/tests/destest.c b/tests/destest.c new file mode 100644 index 0000000..ebc67f3 --- /dev/null +++ b/tests/destest.c @@ -0,0 +1,884 @@ +/* $OpenBSD: destest.c,v 1.4 2018/07/17 17:06:49 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#include +#include + +#include + +#define crypt(c,s) (DES_crypt((c),(s))) + +/* tisk tisk - the test keys don't all have odd parity :-( */ +/* test data */ +#define NUM_TESTS 34 +static unsigned char key_data[NUM_TESTS][8]={ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + {0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}, + {0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57}, + {0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E}, + {0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86}, + {0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E}, + {0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6}, + {0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE}, + {0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6}, + {0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE}, + {0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16}, + {0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F}, + {0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46}, + {0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E}, + {0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76}, + {0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07}, + {0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F}, + {0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7}, + {0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF}, + {0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6}, + {0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF}, + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E}, + {0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10}}; + +static unsigned char plain_data[NUM_TESTS][8]={ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + {0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01}, + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42}, + {0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA}, + {0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72}, + {0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A}, + {0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2}, + {0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A}, + {0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2}, + {0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A}, + {0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02}, + {0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A}, + {0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32}, + {0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA}, + {0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62}, + {0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2}, + {0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA}, + {0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92}, + {0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A}, + {0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2}, + {0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF}, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}; + +static unsigned char cipher_data[NUM_TESTS][8]={ + {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, + {0x73,0x59,0xB2,0x16,0x3E,0x4E,0xDC,0x58}, + {0x95,0x8E,0x6E,0x62,0x7A,0x05,0x55,0x7B}, + {0xF4,0x03,0x79,0xAB,0x9E,0x0E,0xC5,0x33}, + {0x17,0x66,0x8D,0xFC,0x72,0x92,0x53,0x2D}, + {0x8A,0x5A,0xE1,0xF8,0x1A,0xB8,0xF2,0xDD}, + {0x8C,0xA6,0x4D,0xE9,0xC1,0xB1,0x23,0xA7}, + {0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4}, + {0x69,0x0F,0x5B,0x0D,0x9A,0x26,0x93,0x9B}, + {0x7A,0x38,0x9D,0x10,0x35,0x4B,0xD2,0x71}, + {0x86,0x8E,0xBB,0x51,0xCA,0xB4,0x59,0x9A}, + {0x71,0x78,0x87,0x6E,0x01,0xF1,0x9B,0x2A}, + {0xAF,0x37,0xFB,0x42,0x1F,0x8C,0x40,0x95}, + {0x86,0xA5,0x60,0xF1,0x0E,0xC6,0xD8,0x5B}, + {0x0C,0xD3,0xDA,0x02,0x00,0x21,0xDC,0x09}, + {0xEA,0x67,0x6B,0x2C,0xB7,0xDB,0x2B,0x7A}, + {0xDF,0xD6,0x4A,0x81,0x5C,0xAF,0x1A,0x0F}, + {0x5C,0x51,0x3C,0x9C,0x48,0x86,0xC0,0x88}, + {0x0A,0x2A,0xEE,0xAE,0x3F,0xF4,0xAB,0x77}, + {0xEF,0x1B,0xF0,0x3E,0x5D,0xFA,0x57,0x5A}, + {0x88,0xBF,0x0D,0xB6,0xD7,0x0D,0xEE,0x56}, + {0xA1,0xF9,0x91,0x55,0x41,0x02,0x0B,0x56}, + {0x6F,0xBF,0x1C,0xAF,0xCF,0xFD,0x05,0x56}, + {0x2F,0x22,0xE4,0x9B,0xAB,0x7C,0xA1,0xAC}, + {0x5A,0x6B,0x61,0x2C,0xC2,0x6C,0xCE,0x4A}, + {0x5F,0x4C,0x03,0x8E,0xD1,0x2B,0x2E,0x41}, + {0x63,0xFA,0xC0,0xD0,0x34,0xD9,0xF7,0x93}, + {0x61,0x7B,0x3A,0x0C,0xE8,0xF0,0x71,0x00}, + {0xDB,0x95,0x86,0x05,0xF8,0xC8,0xC6,0x06}, + {0xED,0xBF,0xD1,0xC6,0x6C,0x29,0xCC,0xC7}, + {0x35,0x55,0x50,0xB2,0x15,0x0E,0x24,0x51}, + {0xCA,0xAA,0xAF,0x4D,0xEA,0xF1,0xDB,0xAE}, + {0xD5,0xD4,0x4F,0xF7,0x20,0x68,0x3D,0x0D}, + {0x2A,0x2B,0xB0,0x08,0xDF,0x97,0xC2,0xF2}}; + +static unsigned char cipher_ecb2[NUM_TESTS-1][8]={ + {0x92,0x95,0xB5,0x9B,0xB3,0x84,0x73,0x6E}, + {0x19,0x9E,0x9D,0x6D,0xF3,0x9A,0xA8,0x16}, + {0x2A,0x4B,0x4D,0x24,0x52,0x43,0x84,0x27}, + {0x35,0x84,0x3C,0x01,0x9D,0x18,0xC5,0xB6}, + {0x4A,0x5B,0x2F,0x42,0xAA,0x77,0x19,0x25}, + {0xA0,0x6B,0xA9,0xB8,0xCA,0x5B,0x17,0x8A}, + {0xAB,0x9D,0xB7,0xFB,0xED,0x95,0xF2,0x74}, + {0x3D,0x25,0x6C,0x23,0xA7,0x25,0x2F,0xD6}, + {0xB7,0x6F,0xAB,0x4F,0xBD,0xBD,0xB7,0x67}, + {0x8F,0x68,0x27,0xD6,0x9C,0xF4,0x1A,0x10}, + {0x82,0x57,0xA1,0xD6,0x50,0x5E,0x81,0x85}, + {0xA2,0x0F,0x0A,0xCD,0x80,0x89,0x7D,0xFA}, + {0xCD,0x2A,0x53,0x3A,0xDB,0x0D,0x7E,0xF3}, + {0xD2,0xC2,0xBE,0x27,0xE8,0x1B,0x68,0xE3}, + {0xE9,0x24,0xCF,0x4F,0x89,0x3C,0x5B,0x0A}, + {0xA7,0x18,0xC3,0x9F,0xFA,0x9F,0xD7,0x69}, + {0x77,0x2C,0x79,0xB1,0xD2,0x31,0x7E,0xB1}, + {0x49,0xAB,0x92,0x7F,0xD0,0x22,0x00,0xB7}, + {0xCE,0x1C,0x6C,0x7D,0x85,0xE3,0x4A,0x6F}, + {0xBE,0x91,0xD6,0xE1,0x27,0xB2,0xE9,0x87}, + {0x70,0x28,0xAE,0x8F,0xD1,0xF5,0x74,0x1A}, + {0xAA,0x37,0x80,0xBB,0xF3,0x22,0x1D,0xDE}, + {0xA6,0xC4,0xD2,0x5E,0x28,0x93,0xAC,0xB3}, + {0x22,0x07,0x81,0x5A,0xE4,0xB7,0x1A,0xAD}, + {0xDC,0xCE,0x05,0xE7,0x07,0xBD,0xF5,0x84}, + {0x26,0x1D,0x39,0x2C,0xB3,0xBA,0xA5,0x85}, + {0xB4,0xF7,0x0F,0x72,0xFB,0x04,0xF0,0xDC}, + {0x95,0xBA,0xA9,0x4E,0x87,0x36,0xF2,0x89}, + {0xD4,0x07,0x3A,0xF1,0x5A,0x17,0x82,0x0E}, + {0xEF,0x6F,0xAF,0xA7,0x66,0x1A,0x7E,0x89}, + {0xC1,0x97,0xF5,0x58,0x74,0x8A,0x20,0xE7}, + {0x43,0x34,0xCF,0xDA,0x22,0xC4,0x86,0xC8}, + {0x08,0xD7,0xB4,0xFB,0x62,0x9D,0x08,0x85}}; + +static unsigned char cbc_key [8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; +static unsigned char cbc2_key[8]={0xf1,0xe0,0xd3,0xc2,0xb5,0xa4,0x97,0x86}; +static unsigned char cbc3_key[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; +static unsigned char cbc_iv [8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; +/* Changed the following text constant to binary so it will work on ebcdic + * machines :-) */ +/* static char cbc_data[40]="7654321 Now is the time for \0001"; */ +static unsigned char cbc_data[40]={ + 0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x20, + 0x4E,0x6F,0x77,0x20,0x69,0x73,0x20,0x74, + 0x68,0x65,0x20,0x74,0x69,0x6D,0x65,0x20, + 0x66,0x6F,0x72,0x20,0x00,0x31,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + }; + +static unsigned char cbc_ok[32]={ + 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, + 0xac,0xd8,0xae,0xfd,0xdf,0xd8,0xa1,0xeb, + 0x46,0x8e,0x91,0x15,0x78,0x88,0xba,0x68, + 0x1d,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; + +#ifdef SCREW_THE_PARITY +#error "SCREW_THE_PARITY is not ment to be defined." +#error "Original vectors are preserved for reference only." +static unsigned char cbc2_key[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; +static unsigned char xcbc_ok[32]={ + 0x86,0x74,0x81,0x0D,0x61,0xA4,0xA5,0x48, + 0xB9,0x93,0x03,0xE1,0xB8,0xBB,0xBD,0xBD, + 0x64,0x30,0x0B,0xB9,0x06,0x65,0x81,0x76, + 0x04,0x1D,0x77,0x62,0x17,0xCA,0x2B,0xD2, + }; +#else +static unsigned char xcbc_ok[32]={ + 0x84,0x6B,0x29,0x14,0x85,0x1E,0x9A,0x29, + 0x54,0x73,0x2F,0x8A,0xA0,0xA6,0x11,0xC1, + 0x15,0xCD,0xC2,0xD7,0x95,0x1B,0x10,0x53, + 0xA6,0x3C,0x5E,0x03,0xB2,0x1A,0xA3,0xC4, + }; +#endif + +static unsigned char cbc3_ok[32]={ + 0x3F,0xE3,0x01,0xC9,0x62,0xAC,0x01,0xD0, + 0x22,0x13,0x76,0x3C,0x1C,0xBD,0x4C,0xDC, + 0x79,0x96,0x57,0xC0,0x64,0xEC,0xF5,0xD4, + 0x1C,0x67,0x38,0x12,0xCF,0xDE,0x96,0x75}; + +static unsigned char pcbc_ok[32]={ + 0xcc,0xd1,0x73,0xff,0xab,0x20,0x39,0xf4, + 0x6d,0xec,0xb4,0x70,0xa0,0xe5,0x6b,0x15, + 0xae,0xa6,0xbf,0x61,0xed,0x7d,0x9c,0x9f, + 0xf7,0x17,0x46,0x3b,0x8a,0xb3,0xcc,0x88}; + +static unsigned char cfb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; +static unsigned char cfb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; +static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; +static unsigned char plain[24]= + { + 0x4e,0x6f,0x77,0x20,0x69,0x73, + 0x20,0x74,0x68,0x65,0x20,0x74, + 0x69,0x6d,0x65,0x20,0x66,0x6f, + 0x72,0x20,0x61,0x6c,0x6c,0x20 + }; +static unsigned char cfb_cipher8[24]= { + 0xf3,0x1f,0xda,0x07,0x01,0x14, 0x62,0xee,0x18,0x7f,0x43,0xd8, + 0x0a,0x7c,0xd9,0xb5,0xb0,0xd2, 0x90,0xda,0x6e,0x5b,0x9a,0x87 }; +static unsigned char cfb_cipher16[24]={ + 0xF3,0x09,0x87,0x87,0x7F,0x57, 0xF7,0x3C,0x36,0xB6,0xDB,0x70, + 0xD8,0xD5,0x34,0x19,0xD3,0x86, 0xB2,0x23,0xB7,0xB2,0xAD,0x1B }; +static unsigned char cfb_cipher32[24]={ + 0xF3,0x09,0x62,0x49,0xA4,0xDF, 0xA4,0x9F,0x33,0xDC,0x7B,0xAD, + 0x4C,0xC8,0x9F,0x64,0xE4,0x53, 0xE5,0xEC,0x67,0x20,0xDA,0xB6 }; +static unsigned char cfb_cipher48[24]={ + 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x30,0xB5,0x15,0xEC,0xBB,0x85, + 0x97,0x5A,0x13,0x8C,0x68,0x60, 0xE2,0x38,0x34,0x3C,0xDC,0x1F }; +static unsigned char cfb_cipher64[24]={ + 0xF3,0x09,0x62,0x49,0xC7,0xF4, 0x6E,0x51,0xA6,0x9E,0x83,0x9B, + 0x1A,0x92,0xF7,0x84,0x03,0x46, 0x71,0x33,0x89,0x8E,0xA6,0x22 }; + +static unsigned char ofb_key[8]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; +static unsigned char ofb_iv[8]={0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef}; +static unsigned char ofb_buf1[24],ofb_buf2[24],ofb_tmp[8]; +static unsigned char ofb_cipher[24]= + { + 0xf3,0x09,0x62,0x49,0xc7,0xf4,0x6e,0x51, + 0x35,0xf2,0x4a,0x24,0x2e,0xeb,0x3d,0x3f, + 0x3d,0x6d,0x5b,0xe3,0x25,0x5a,0xf8,0xc3 + }; + +#if 0 +static DES_LONG cbc_cksum_ret=0xB462FEF7L; +#else +static DES_LONG cbc_cksum_ret=0xF7FE62B4L; +#endif +static unsigned char cbc_cksum_data[8]={0x1D,0x26,0x93,0x97,0xf7,0xfe,0x62,0xb4}; + +static char *pt(unsigned char *p); +static int cfb_test(int bits, unsigned char *cfb_cipher); +static int cfb64_test(unsigned char *cfb_cipher); +static int ede_cfb64_test(unsigned char *cfb_cipher); +int main(int argc, char *argv[]) + { + int j,err=0; + unsigned int i; + DES_cblock in,out,outin,iv3,iv2; + DES_key_schedule ks,ks2,ks3; + unsigned char cbc_in[40]; + unsigned char cbc_out[40]; + DES_LONG cs; + unsigned char cret[8]; + DES_LONG lqret[4]; + int num; + char *str; + +#ifndef OPENSSL_NO_DESCBCM + printf("Doing cbcm\n"); + if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0) + { + printf("Key error %d\n",j); + err=1; + } + if ((j=DES_set_key_checked(&cbc2_key,&ks2)) != 0) + { + printf("Key error %d\n",j); + err=1; + } + if ((j=DES_set_key_checked(&cbc3_key,&ks3)) != 0) + { + printf("Key error %d\n",j); + err=1; + } + memset(cbc_out,0,40); + memset(cbc_in,0,40); + i=strlen((char *)cbc_data)+1; + /* i=((i+7)/8)*8; */ + memcpy(iv3,cbc_iv,sizeof(cbc_iv)); + memset(iv2,'\0',sizeof iv2); + + DES_ede3_cbcm_encrypt(cbc_data,cbc_out,16L,&ks,&ks2,&ks3,&iv3,&iv2, + DES_ENCRYPT); + DES_ede3_cbcm_encrypt(&cbc_data[16],&cbc_out[16],i-16,&ks,&ks2,&ks3, + &iv3,&iv2,DES_ENCRYPT); + /* if (memcmp(cbc_out,cbc3_ok, + (unsigned int)(strlen((char *)cbc_data)+1+7)/8*8) != 0) + { + printf("des_ede3_cbc_encrypt encrypt error\n"); + err=1; + } + */ + memcpy(iv3,cbc_iv,sizeof(cbc_iv)); + memset(iv2,'\0',sizeof iv2); + DES_ede3_cbcm_encrypt(cbc_out,cbc_in,i,&ks,&ks2,&ks3,&iv3,&iv2,DES_DECRYPT); + if (memcmp(cbc_in,cbc_data,strlen((char *)cbc_data)+1) != 0) + { + unsigned int n; + + printf("des_ede3_cbcm_encrypt decrypt error\n"); + for(n=0 ; n < i ; ++n) + printf(" %02x",cbc_data[n]); + printf("\n"); + for(n=0 ; n < i ; ++n) + printf(" %02x",cbc_in[n]); + printf("\n"); + err=1; + } +#endif + + printf("Doing ecb\n"); + for (i=0; i>4)&0xf]; + ret[i*2+1]=f[p[i]&0xf]; + } + ret[16]='\0'; + return(ret); + } + +static int cfb_test(int bits, unsigned char *cfb_cipher) + { + DES_key_schedule ks; + int i,err=0; + + DES_set_key_checked(&cfb_key,&ks); + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + DES_cfb_encrypt(plain,cfb_buf1,bits,sizeof(plain),&ks,&cfb_tmp, + DES_ENCRYPT); + if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) + { + err=1; + printf("cfb_encrypt encrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf1[i]))); + } + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + DES_cfb_encrypt(cfb_buf1,cfb_buf2,bits,sizeof(plain),&ks,&cfb_tmp, + DES_DECRYPT); + if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) + { + err=1; + printf("cfb_encrypt decrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf1[i]))); + } + return(err); + } + +static int cfb64_test(unsigned char *cfb_cipher) + { + DES_key_schedule ks; + int err=0,i,n; + + DES_set_key_checked(&cfb_key,&ks); + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + n=0; + DES_cfb64_encrypt(plain,cfb_buf1,12,&ks,&cfb_tmp,&n,DES_ENCRYPT); + DES_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]),sizeof(plain)-12,&ks, + &cfb_tmp,&n,DES_ENCRYPT); + if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) + { + err=1; + printf("cfb_encrypt encrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf1[i]))); + } + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + n=0; + DES_cfb64_encrypt(cfb_buf1,cfb_buf2,17,&ks,&cfb_tmp,&n,DES_DECRYPT); + DES_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), + sizeof(plain)-17,&ks,&cfb_tmp,&n,DES_DECRYPT); + if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) + { + err=1; + printf("cfb_encrypt decrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf2[i]))); + } + return(err); + } + +static int ede_cfb64_test(unsigned char *cfb_cipher) + { + DES_key_schedule ks; + int err=0,i,n; + + DES_set_key_checked(&cfb_key,&ks); + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + n=0; + DES_ede3_cfb64_encrypt(plain,cfb_buf1,12,&ks,&ks,&ks,&cfb_tmp,&n, + DES_ENCRYPT); + DES_ede3_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), + sizeof(plain)-12,&ks,&ks,&ks, + &cfb_tmp,&n,DES_ENCRYPT); + if (memcmp(cfb_cipher,cfb_buf1,sizeof(plain)) != 0) + { + err=1; + printf("ede_cfb_encrypt encrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf1[i]))); + } + memcpy(cfb_tmp,cfb_iv,sizeof(cfb_iv)); + n=0; + DES_ede3_cfb64_encrypt(cfb_buf1,cfb_buf2,(long)17,&ks,&ks,&ks, + &cfb_tmp,&n,DES_DECRYPT); + DES_ede3_cfb64_encrypt(&(cfb_buf1[17]),&(cfb_buf2[17]), + sizeof(plain)-17,&ks,&ks,&ks, + &cfb_tmp,&n,DES_DECRYPT); + if (memcmp(plain,cfb_buf2,sizeof(plain)) != 0) + { + err=1; + printf("ede_cfb_encrypt decrypt error\n"); + for (i=0; i<24; i+=8) + printf("%s\n",pt(&(cfb_buf2[i]))); + } + return(err); + } diff --git a/tests/dhtest.c b/tests/dhtest.c new file mode 100644 index 0000000..0df5427 --- /dev/null +++ b/tests/dhtest.c @@ -0,0 +1,170 @@ +/* $OpenBSD: dhtest.c,v 1.14 2023/08/20 22:21:00 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static int +cb(int p, int n, BN_GENCB *arg) +{ + char c = '*'; + + if (p == 0) + c = '.'; + if (p == 1) + c = '+'; + if (p == 2) + c = '*'; + if (p == 3) + c = '\n'; + printf("%c", c); + fflush(stdout); + return 1; +} + +int +main(int argc, char *argv[]) +{ + BN_GENCB *_cb; + DH *dh = NULL; + unsigned char *buf = NULL; + int flags, buf_len, secret_len; + int i; + int ret = 1; + + if ((_cb = BN_GENCB_new()) == NULL) + err(1, "BN_GENCB_new"); + + BN_GENCB_set(_cb, &cb, NULL); + if ((dh = DH_new()) == NULL) + goto err; + +#ifdef OPENSSL_NO_ENGINE + if (DH_get0_engine(dh) != NULL) { + fprintf(stderr, "ENGINE was not NULL\n"); + goto err; + } +#endif + + if (!DH_generate_parameters_ex(dh, 64, DH_GENERATOR_5, _cb)) + goto err; + + if (!DH_check(dh, &flags)) + goto err; + if (flags & DH_CHECK_P_NOT_PRIME) + printf("p value is not prime\n"); + if (flags & DH_CHECK_P_NOT_SAFE_PRIME) + printf("p value is not a safe prime\n"); + if (flags & DH_UNABLE_TO_CHECK_GENERATOR) + printf("unable to check the generator value\n"); + if (flags & DH_NOT_SUITABLE_GENERATOR) + printf("the g value is not a generator\n"); + + printf("\np = "); + if (!BN_print_fp(stdout, DH_get0_p(dh))) + goto err; + printf("\ng = "); + if (!BN_print_fp(stdout, DH_get0_g(dh))) + goto err; + printf("\n"); + + if (!DH_generate_key(dh)) + goto err; + printf("pri1 = "); + if (!BN_print_fp(stdout, DH_get0_priv_key(dh))) + goto err; + printf("\npub1 = "); + if (!BN_print_fp(stdout, DH_get0_pub_key(dh))) + goto err; + printf("\n"); + + buf_len = DH_size(dh); + if ((buf = malloc(buf_len)) == NULL) + err(1, "malloc"); + secret_len = DH_compute_key(buf, DH_get0_pub_key(dh), dh); + + printf("key1 = "); + for (i = 0; i < secret_len; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + + if (secret_len < 4) { + fprintf(stderr, "Error in DH routines\n"); + goto err; + } + + ret = 0; +err: + ERR_print_errors_fp(stderr); + + free(buf); + DH_free(dh); + BN_GENCB_free(_cb); + + return (ret); +} diff --git a/tests/dsatest.c b/tests/dsatest.c new file mode 100644 index 0000000..6234345 --- /dev/null +++ b/tests/dsatest.c @@ -0,0 +1,235 @@ +/* $OpenBSD: dsatest.c,v 1.9 2023/08/20 22:22:55 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static int dsa_cb(int p, int n, BN_GENCB *arg); + +/* seed, out_p, out_q, out_g are taken from the updated Appendix 5 to + * FIPS PUB 186 and also appear in Appendix 5 to FIPS PIB 186-1 */ +static unsigned char seed[20] = { + 0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b, 0x40, + 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3, +}; + +static unsigned char out_p[] = { + 0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, + 0x3d, 0x25, 0x75, 0x9b, 0xb0, 0x68, 0x69, 0xcb, + 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d, 0x0c, 0xf7, + 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, + 0xd0, 0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, + 0xc2, 0xe9, 0xad, 0xac, 0x32, 0xab, 0x7a, 0xac, + 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24, 0xc2, + 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91, +}; + +static unsigned char out_q[] = { + 0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, + 0x99, 0x3b, 0x4f, 0x2d, 0xed, 0x30, 0xf4, 0x8e, + 0xda, 0xce, 0x91, 0x5f, +}; + +static unsigned char out_g[] = { + 0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, + 0x41, 0x31, 0x63, 0xa5, 0x5b, 0x4c, 0xb5, 0x00, + 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c, 0xef, 0xcb, + 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, + 0x71, 0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, + 0x58, 0xe5, 0xb7, 0x95, 0x21, 0x92, 0x5c, 0x9c, + 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08, 0x8c, + 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02, +}; + +static const unsigned char str1[] = "12345678901234567890"; + +static BIO *bio_err = NULL; + +int +main(int argc, char **argv) +{ + BN_GENCB *cb; + DSA *dsa = NULL; + int counter, i, j; + unsigned char buf[256]; + unsigned long h; + unsigned char sig[256]; + unsigned int siglen; + int ret = 0; + + if (bio_err == NULL) + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + + ERR_load_crypto_strings(); + + BIO_printf(bio_err, "test generation of DSA parameters\n"); + + if ((cb = BN_GENCB_new()) == NULL) + goto end; + + BN_GENCB_set(cb, dsa_cb, bio_err); + if ((dsa = DSA_new()) == NULL) + goto end; + +#ifdef OPENSSL_NO_ENGINE + if (DSA_get0_engine(dsa) != NULL) { + BIO_printf(bio_err, "ENGINE was not NULL\n"); + goto end; + } +#endif + + if (!DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, cb)) + goto end; + + BIO_printf(bio_err, "seed\n"); + for (i = 0; i < 20; i += 4) { + BIO_printf(bio_err, "%02X%02X%02X%02X ", + seed[i], seed[i + 1], seed[i + 2], seed[i + 3]); + } + BIO_printf(bio_err, "\ncounter=%d h=%ld\n", counter, h); + + DSA_print(bio_err, dsa, 0); + if (counter != 105) { + BIO_printf(bio_err, "counter should be 105\n"); + goto end; + } + if (h != 2) { + BIO_printf(bio_err, "h should be 2\n"); + goto end; + } + + i = BN_bn2bin(DSA_get0_q(dsa), buf); + j = sizeof(out_q); + if ((i != j) || (memcmp(buf, out_q, i) != 0)) { + BIO_printf(bio_err, "q value is wrong\n"); + goto end; + } + + i = BN_bn2bin(DSA_get0_p(dsa), buf); + j = sizeof(out_p); + if ((i != j) || (memcmp(buf, out_p, i) != 0)) { + BIO_printf(bio_err, "p value is wrong\n"); + goto end; + } + + i = BN_bn2bin(DSA_get0_g(dsa), buf); + j = sizeof(out_g); + if ((i != j) || (memcmp(buf, out_g, i) != 0)) { + BIO_printf(bio_err, "g value is wrong\n"); + goto end; + } + + DSA_generate_key(dsa); + DSA_sign(0, str1, 20, sig, &siglen, dsa); + if (DSA_verify(0, str1, 20, sig, siglen, dsa) == 1) + ret = 1; + +end: + BN_GENCB_free(cb); + if (!ret) + ERR_print_errors(bio_err); + DSA_free(dsa); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_thread_state(NULL); + ERR_free_strings(); + CRYPTO_mem_leaks(bio_err); + BIO_free(bio_err); + bio_err = NULL; + + return !ret; +} + +static int +dsa_cb(int p, int n, BN_GENCB *arg) +{ + char c = '*'; + static int ok = 0, num = 0; + + if (p == 0) { + c = '.'; + num++; + } + if (p == 1) + c = '+'; + if (p == 2) { + c = '*'; + ok++; + } + + if (p == 3) + c = '\n'; + BIO_write(BN_GENCB_get_arg(arg), &c, 1); + (void)BIO_flush(BN_GENCB_get_arg(arg)); + + if (!ok && (p == 0) && (num > 1)) { + BIO_printf((BIO *)arg, "error in dsatest\n"); + return 0; + } + return 1; +} diff --git a/tests/dtlstest.c b/tests/dtlstest.c new file mode 100644 index 0000000..a749bcf --- /dev/null +++ b/tests/dtlstest.c @@ -0,0 +1,1077 @@ +/* $OpenBSD: dtlstest.c,v 1.18 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2020, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "bio_local.h" +#include "ssl_local.h" + +const char *server_ca_file; +const char *server_cert_file; +const char *server_key_file; + +char dtls_cookie[32]; + +int debug = 0; + +void tls12_record_layer_set_initial_epoch(struct tls12_record_layer *rl, + uint16_t epoch); + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +#define BIO_C_DELAY_COUNT 1000 +#define BIO_C_DELAY_FLUSH 1001 +#define BIO_C_DELAY_PACKET 1002 +#define BIO_C_DROP_PACKET 1003 +#define BIO_C_DROP_RANDOM 1004 + +struct bio_packet_monkey_ctx { + unsigned int delay_count; + unsigned int delay_mask; + unsigned int drop_rand; + unsigned int drop_mask; + uint8_t *delayed_msg; + size_t delayed_msg_len; +}; + +static int +bio_packet_monkey_new(BIO *bio) +{ + struct bio_packet_monkey_ctx *ctx; + + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + return 0; + + bio->flags = 0; + bio->init = 1; + bio->num = 0; + bio->ptr = ctx; + + return 1; +} + +static int +bio_packet_monkey_free(BIO *bio) +{ + struct bio_packet_monkey_ctx *ctx; + + if (bio == NULL) + return 1; + + ctx = bio->ptr; + free(ctx->delayed_msg); + free(ctx); + + return 1; +} + +static int +bio_packet_monkey_delay_flush(BIO *bio) +{ + struct bio_packet_monkey_ctx *ctx = bio->ptr; + + if (ctx->delayed_msg == NULL) + return 1; + + if (debug) + fprintf(stderr, "DEBUG: flushing delayed packet...\n"); + if (debug > 1) + hexdump(ctx->delayed_msg, ctx->delayed_msg_len); + + BIO_write(bio->next_bio, ctx->delayed_msg, ctx->delayed_msg_len); + + free(ctx->delayed_msg); + ctx->delayed_msg = NULL; + + return BIO_ctrl(bio->next_bio, BIO_CTRL_FLUSH, 0, NULL); +} + +static long +bio_packet_monkey_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + struct bio_packet_monkey_ctx *ctx; + + ctx = bio->ptr; + + switch (cmd) { + case BIO_C_DELAY_COUNT: + if (num < 1 || num > 31) + return 0; + ctx->delay_count = num; + return 1; + + case BIO_C_DELAY_FLUSH: + return bio_packet_monkey_delay_flush(bio); + + case BIO_C_DELAY_PACKET: + if (num < 1 || num > 31) + return 0; + ctx->delay_mask |= 1 << ((unsigned int)num - 1); + return 1; + + case BIO_C_DROP_PACKET: + if (num < 1 || num > 31) + return 0; + ctx->drop_mask |= 1 << ((unsigned int)num - 1); + return 1; + + case BIO_C_DROP_RANDOM: + if (num < 0 || (size_t)num > UINT_MAX) + return 0; + ctx->drop_rand = (unsigned int)num; + return 1; + } + + if (bio->next_bio == NULL) + return 0; + + return BIO_ctrl(bio->next_bio, cmd, num, ptr); +} + +static int +bio_packet_monkey_read(BIO *bio, char *out, int out_len) +{ + struct bio_packet_monkey_ctx *ctx = bio->ptr; + int ret; + + if (ctx == NULL || bio->next_bio == NULL) + return 0; + + ret = BIO_read(bio->next_bio, out, out_len); + + if (ret > 0) { + if (debug) + fprintf(stderr, "DEBUG: read packet...\n"); + if (debug > 1) + hexdump(out, ret); + } + + BIO_clear_retry_flags(bio); + if (ret <= 0 && BIO_should_retry(bio->next_bio)) + BIO_set_retry_read(bio); + + return ret; +} + +static int +bio_packet_monkey_write(BIO *bio, const char *in, int in_len) +{ + struct bio_packet_monkey_ctx *ctx = bio->ptr; + const char *label = "writing"; + int delay = 0, drop = 0; + int ret; + + if (ctx == NULL || bio->next_bio == NULL) + return 0; + + if (ctx->delayed_msg != NULL && ctx->delay_count > 0) + ctx->delay_count--; + + if (ctx->delayed_msg != NULL && ctx->delay_count == 0) { + if (debug) + fprintf(stderr, "DEBUG: writing delayed packet...\n"); + if (debug > 1) + hexdump(ctx->delayed_msg, ctx->delayed_msg_len); + + ret = BIO_write(bio->next_bio, ctx->delayed_msg, + ctx->delayed_msg_len); + + BIO_clear_retry_flags(bio); + if (ret <= 0 && BIO_should_retry(bio->next_bio)) { + BIO_set_retry_write(bio); + return (ret); + } + + free(ctx->delayed_msg); + ctx->delayed_msg = NULL; + } + + if (ctx->delay_mask > 0) { + delay = ctx->delay_mask & 1; + ctx->delay_mask >>= 1; + } + if (ctx->drop_rand > 0) { + drop = arc4random_uniform(ctx->drop_rand) == 0; + } else if (ctx->drop_mask > 0) { + drop = ctx->drop_mask & 1; + ctx->drop_mask >>= 1; + } + + if (delay) + label = "delaying"; + if (drop) + label = "dropping"; + if (debug) + fprintf(stderr, "DEBUG: %s packet...\n", label); + if (debug > 1) + hexdump(in, in_len); + + if (drop) + return in_len; + + if (delay) { + if (ctx->delayed_msg != NULL) + return 0; + if ((ctx->delayed_msg = calloc(1, in_len)) == NULL) + return 0; + memcpy(ctx->delayed_msg, in, in_len); + ctx->delayed_msg_len = in_len; + return in_len; + } + + ret = BIO_write(bio->next_bio, in, in_len); + + BIO_clear_retry_flags(bio); + if (ret <= 0 && BIO_should_retry(bio->next_bio)) + BIO_set_retry_write(bio); + + return ret; +} + +static int +bio_packet_monkey_puts(BIO *bio, const char *str) +{ + return bio_packet_monkey_write(bio, str, strlen(str)); +} + +static const BIO_METHOD bio_packet_monkey = { + .type = BIO_TYPE_BUFFER, + .name = "packet monkey", + .bread = bio_packet_monkey_read, + .bwrite = bio_packet_monkey_write, + .bputs = bio_packet_monkey_puts, + .ctrl = bio_packet_monkey_ctrl, + .create = bio_packet_monkey_new, + .destroy = bio_packet_monkey_free +}; + +static const BIO_METHOD * +BIO_f_packet_monkey(void) +{ + return &bio_packet_monkey; +} + +static BIO * +BIO_new_packet_monkey(void) +{ + return BIO_new(BIO_f_packet_monkey()); +} + +static int +BIO_packet_monkey_delay(BIO *bio, int num, int count) +{ + if (!BIO_ctrl(bio, BIO_C_DELAY_COUNT, count, NULL)) + return 0; + + return BIO_ctrl(bio, BIO_C_DELAY_PACKET, num, NULL); +} + +static int +BIO_packet_monkey_delay_flush(BIO *bio) +{ + return BIO_ctrl(bio, BIO_C_DELAY_FLUSH, 0, NULL); +} + +static int +BIO_packet_monkey_drop(BIO *bio, int num) +{ + return BIO_ctrl(bio, BIO_C_DROP_PACKET, num, NULL); +} + +#if 0 +static int +BIO_packet_monkey_drop_random(BIO *bio, int num) +{ + return BIO_ctrl(bio, BIO_C_DROP_RANDOM, num, NULL); +} +#endif + +static int +datagram_pair(int *client_sock, int *server_sock, + struct sockaddr_in *server_sin) +{ + struct sockaddr_in sin; + socklen_t sock_len; + int cs = -1, ss = -1; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if ((ss = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + err(1, "server socket"); + if (bind(ss, (struct sockaddr *)&sin, sizeof(sin)) == -1) + err(1, "server bind"); + sock_len = sizeof(sin); + if (getsockname(ss, (struct sockaddr *)&sin, &sock_len) == -1) + err(1, "server getsockname"); + + if ((cs = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + err(1, "client socket"); + if (connect(cs, (struct sockaddr *)&sin, sizeof(sin)) == -1) + err(1, "client connect"); + + *client_sock = cs; + *server_sock = ss; + memcpy(server_sin, &sin, sizeof(sin)); + + return 1; +} + +static int +poll_timeout(SSL *client, SSL *server) +{ + int client_timeout = 0, server_timeout = 0; + struct timeval timeout; + + if (DTLSv1_get_timeout(client, &timeout)) + client_timeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000; + + if (DTLSv1_get_timeout(server, &timeout)) + server_timeout = timeout.tv_sec * 1000 + timeout.tv_usec / 1000; + + if (client_timeout < 10) + client_timeout = 10; + if (server_timeout < 10) + server_timeout = 10; + + /* XXX */ + if (client_timeout <= 0) + return server_timeout; + if (client_timeout > 0 && server_timeout <= 0) + return client_timeout; + if (client_timeout < server_timeout) + return client_timeout; + + return server_timeout; +} + +static int +dtls_cookie_generate(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + arc4random_buf(dtls_cookie, sizeof(dtls_cookie)); + memcpy(cookie, dtls_cookie, sizeof(dtls_cookie)); + *cookie_len = sizeof(dtls_cookie); + + return 1; +} + +static int +dtls_cookie_verify(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + return cookie_len == sizeof(dtls_cookie) && + memcmp(cookie, dtls_cookie, sizeof(dtls_cookie)) == 0; +} + +static void +dtls_info_callback(const SSL *ssl, int type, int val) +{ + /* + * Squeals ahead... remove the bbio from the info callback, so we can + * drop specific messages. Ideally this would be an option for the SSL. + */ + if (ssl->wbio == ssl->bbio) + ((SSL *)ssl)->wbio = BIO_pop(ssl->wbio); +} + +static SSL * +dtls_client(int sock, struct sockaddr_in *server_sin, long mtu) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + BIO *bio = NULL; + + if ((bio = BIO_new_dgram(sock, BIO_NOCLOSE)) == NULL) + errx(1, "client bio"); + if (!BIO_socket_nbio(sock, 1)) + errx(1, "client nbio"); + if (!BIO_ctrl_set_connected(bio, 1, server_sin)) + errx(1, "client set connected"); + + if ((ssl_ctx = SSL_CTX_new(DTLS_method())) == NULL) + errx(1, "client context"); + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "client ssl"); + + SSL_set_bio(ssl, bio, bio); + bio = NULL; + + if (mtu > 0) { + SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(ssl, mtu); + } + + SSL_CTX_free(ssl_ctx); + BIO_free(bio); + + return ssl; +} + +static SSL * +dtls_server(int sock, long options, long mtu) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + BIO *bio = NULL; + + if ((bio = BIO_new_dgram(sock, BIO_NOCLOSE)) == NULL) + errx(1, "server bio"); + if (!BIO_socket_nbio(sock, 1)) + errx(1, "server nbio"); + + if ((ssl_ctx = SSL_CTX_new(DTLS_method())) == NULL) + errx(1, "server context"); + + SSL_CTX_set_cookie_generate_cb(ssl_ctx, dtls_cookie_generate); + SSL_CTX_set_cookie_verify_cb(ssl_ctx, dtls_cookie_verify); + SSL_CTX_set_dh_auto(ssl_ctx, 2); + SSL_CTX_set_options(ssl_ctx, options); + + if (SSL_CTX_use_certificate_chain_file(ssl_ctx, server_cert_file) != 1) { + fprintf(stderr, "FAIL: Failed to load server certificate"); + goto failure; + } + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key_file, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "FAIL: Failed to load server private key"); + goto failure; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "server ssl"); + + if (SSL_use_certificate_chain_file(ssl, server_cert_file) != 1) { + fprintf(stderr, "FAIL: Failed to load server certificate"); + goto failure; + } + SSL_set_bio(ssl, bio, bio); + bio = NULL; + + if (mtu > 0) { + SSL_set_options(ssl, SSL_OP_NO_QUERY_MTU); + SSL_set_mtu(ssl, mtu); + } + + failure: + SSL_CTX_free(ssl_ctx); + BIO_free(bio); + + return ssl; +} + +static int +ssl_error(SSL *ssl, const char *name, const char *desc, int ssl_ret, + short *events) +{ + int ssl_err; + + ssl_err = SSL_get_error(ssl, ssl_ret); + + if (ssl_err == SSL_ERROR_WANT_READ) { + *events = POLLIN; + } else if (ssl_err == SSL_ERROR_WANT_WRITE) { + *events = POLLOUT; + } else if (ssl_err == SSL_ERROR_SYSCALL && errno == 0) { + /* Yup, this is apparently a thing... */ + } else { + fprintf(stderr, "FAIL: %s %s failed - ssl err = %d, errno = %d\n", + name, desc, ssl_err, errno); + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} + +static int +do_connect(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + return 1; +} + +static int +do_connect_read(SSL *ssl, const char *name, int *done, short *events) +{ + uint8_t buf[2048]; + int ssl_ret; + int i; + + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + for (i = 0; i < 3; i++) { + fprintf(stderr, "INFO: %s reading after connect\n", name); + if ((ssl_ret = SSL_read(ssl, buf, sizeof(buf))) != 3) { + fprintf(stderr, "ERROR: %s read failed\n", name); + return 0; + } + } + + return 1; +} + +static int +do_connect_shutdown(SSL *ssl, const char *name, int *done, short *events) +{ + uint8_t buf[2048]; + int ssl_ret; + + if ((ssl_ret = SSL_connect(ssl)) != 1) + return ssl_error(ssl, name, "connect", ssl_ret, events); + + fprintf(stderr, "INFO: %s connect done\n", name); + *done = 1; + + ssl_ret = SSL_read(ssl, buf, sizeof(buf)); + if (SSL_get_error(ssl, ssl_ret) != SSL_ERROR_ZERO_RETURN) { + fprintf(stderr, "FAIL: %s did not receive close-notify\n", name); + return 0; + } + + fprintf(stderr, "INFO: %s received close-notify\n", name); + + return 1; +} + +static int +do_accept(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + *done = 1; + + return 1; +} + +static int +do_accept_write(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + BIO *bio; + int i; + + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + + for (i = 0; i < 3; i++) { + fprintf(stderr, "INFO: %s writing after accept\n", name); + if ((ssl_ret = SSL_write(ssl, "abc", 3)) != 3) { + fprintf(stderr, "ERROR: %s write failed\n", name); + return 0; + } + } + + if ((bio = SSL_get_wbio(ssl)) == NULL) + errx(1, "SSL has NULL bio"); + + /* Flush any delayed packets. */ + BIO_packet_monkey_delay_flush(bio); + + *done = 1; + return 1; +} + +static int +do_accept_shutdown(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + BIO *bio; + + if ((ssl_ret = SSL_accept(ssl)) != 1) + return ssl_error(ssl, name, "accept", ssl_ret, events); + + fprintf(stderr, "INFO: %s accept done\n", name); + + SSL_shutdown(ssl); + + if ((bio = SSL_get_wbio(ssl)) == NULL) + errx(1, "SSL has NULL bio"); + + /* Flush any delayed packets. */ + BIO_packet_monkey_delay_flush(bio); + + *done = 1; + return 1; +} + +static int +do_read(SSL *ssl, const char *name, int *done, short *events) +{ + uint8_t buf[512]; + int ssl_ret; + + if ((ssl_ret = SSL_read(ssl, buf, sizeof(buf))) > 0) { + fprintf(stderr, "INFO: %s read done\n", name); + if (debug > 1) + hexdump(buf, ssl_ret); + *done = 1; + return 1; + } + + return ssl_error(ssl, name, "read", ssl_ret, events); +} + +static int +do_write(SSL *ssl, const char *name, int *done, short *events) +{ + const uint8_t buf[] = "Hello, World!\n"; + int ssl_ret; + + if ((ssl_ret = SSL_write(ssl, buf, sizeof(buf))) > 0) { + fprintf(stderr, "INFO: %s write done\n", name); + *done = 1; + return 1; + } + + return ssl_error(ssl, name, "write", ssl_ret, events); +} + +static int +do_shutdown(SSL *ssl, const char *name, int *done, short *events) +{ + int ssl_ret; + + ssl_ret = SSL_shutdown(ssl); + if (ssl_ret == 1) { + fprintf(stderr, "INFO: %s shutdown done\n", name); + *done = 1; + return 1; + } + return ssl_error(ssl, name, "shutdown", ssl_ret, events); +} + +typedef int (ssl_func)(SSL *ssl, const char *name, int *done, short *events); + +static int +do_client_server_loop(SSL *client, ssl_func *client_func, SSL *server, + ssl_func *server_func, struct pollfd pfd[2]) +{ + int client_done = 0, server_done = 0; + int i = 0; + + pfd[0].revents = POLLIN; + pfd[1].revents = POLLIN; + + do { + if (!client_done) { + if (debug) + fprintf(stderr, "DEBUG: client loop\n"); + if (DTLSv1_handle_timeout(client) > 0) + fprintf(stderr, "INFO: client timeout\n"); + if (!client_func(client, "client", &client_done, + &pfd[0].events)) + return 0; + if (client_done) + pfd[0].events = 0; + } + if (!server_done) { + if (debug) + fprintf(stderr, "DEBUG: server loop\n"); + if (DTLSv1_handle_timeout(server) > 0) + fprintf(stderr, "INFO: server timeout\n"); + if (!server_func(server, "server", &server_done, + &pfd[1].events)) + return 0; + if (server_done) + pfd[1].events = 0; + } + if (poll(pfd, 2, poll_timeout(client, server)) == -1) + err(1, "poll"); + + } while (i++ < 100 && (!client_done || !server_done)); + + if (!client_done || !server_done) + fprintf(stderr, "FAIL: gave up\n"); + + return client_done && server_done; +} + +#define MAX_PACKET_DELAYS 32 +#define MAX_PACKET_DROPS 32 + +struct dtls_delay { + uint8_t packet; + uint8_t count; +}; + +struct dtls_test { + const unsigned char *desc; + long mtu; + long ssl_options; + int client_bbio_off; + int server_bbio_off; + uint16_t initial_epoch; + int write_after_accept; + int shutdown_after_accept; + struct dtls_delay client_delays[MAX_PACKET_DELAYS]; + struct dtls_delay server_delays[MAX_PACKET_DELAYS]; + uint8_t client_drops[MAX_PACKET_DROPS]; + uint8_t server_drops[MAX_PACKET_DROPS]; +}; + +static const struct dtls_test dtls_tests[] = { + { + .desc = "DTLS without cookies", + .ssl_options = 0, + }, + { + .desc = "DTLS without cookies (initial epoch 0xfffe)", + .ssl_options = 0, + .initial_epoch = 0xfffe, + }, + { + .desc = "DTLS without cookies (initial epoch 0xffff)", + .ssl_options = 0, + .initial_epoch = 0xffff, + }, + { + .desc = "DTLS with cookies", + .ssl_options = SSL_OP_COOKIE_EXCHANGE, + }, + { + .desc = "DTLS with low MTU", + .mtu = 256, + .ssl_options = 0, + }, + { + .desc = "DTLS with low MTU and cookies", + .mtu = 256, + .ssl_options = SSL_OP_COOKIE_EXCHANGE, + }, + { + .desc = "DTLS with dropped server response", + .ssl_options = 0, + .server_drops = { 1 }, + }, + { + .desc = "DTLS with two dropped server responses", + .ssl_options = 0, + .server_drops = { 1, 2 }, + }, + { + .desc = "DTLS with dropped ServerHello", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_drops = { 1 }, + }, + { + .desc = "DTLS with dropped server Certificate", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_drops = { 2 }, + }, + { + .desc = "DTLS with dropped ServerKeyExchange", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_drops = { 3 }, + }, + { + .desc = "DTLS with dropped ServerHelloDone", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_drops = { 4 }, + }, +#if 0 + /* + * These two result in the server accept completing and the + * client looping on a timeout. Presumably the server should not + * complete until the client Finished is received... this due to + * a flaw in the DTLSv1.0 specification, which is addressed in + * DTLSv1.2 (see references to "last flight" in RFC 6347 section + * 4.2.4). Our DTLS server code still needs to support this. + */ + { + .desc = "DTLS with dropped server CCS", + .ssl_options = 0, + .server_bbio_off = 1, + .server_drops = { 5 }, + }, + { + .desc = "DTLS with dropped server Finished", + .ssl_options = 0, + .server_bbio_off = 1, + .server_drops = { 6 }, + }, +#endif + { + .desc = "DTLS with dropped ClientKeyExchange", + .ssl_options = 0, + .client_bbio_off = 1, + .client_drops = { 2 }, + }, + { + .desc = "DTLS with dropped client CCS", + .ssl_options = 0, + .client_bbio_off = 1, + .client_drops = { 3 }, + }, + { + .desc = "DTLS with dropped client Finished", + .ssl_options = 0, + .client_bbio_off = 1, + .client_drops = { 4 }, + }, + { + /* Send CCS after client Finished. */ + .desc = "DTLS with delayed client CCS", + .ssl_options = 0, + .client_bbio_off = 1, + .client_delays = { { 3, 2 } }, + }, + { + /* + * Send CCS after server Finished - note app data will be + * dropped if we send the CCS after app data. + */ + .desc = "DTLS with delayed server CCS", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 5, 2 } }, + .write_after_accept = 1, + }, + { + .desc = "DTLS with delayed server CCS (initial epoch 0xfffe)", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .initial_epoch = 0xfffe, + .server_delays = { { 5, 2 } }, + .write_after_accept = 1, + }, + { + .desc = "DTLS with delayed server CCS (initial epoch 0xffff)", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .initial_epoch = 0xffff, + .server_delays = { { 5, 2 } }, + .write_after_accept = 1, + }, + { + /* Send Finished after app data - this is currently buffered. */ + .desc = "DTLS with delayed server Finished", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 6, 3 } }, + .write_after_accept = 1, + }, + { + /* Send CCS after server finished and close-notify. */ + .desc = "DTLS with delayed server CCS (close-notify)", + .ssl_options = SSL_OP_NO_TICKET, + .server_bbio_off = 1, + .server_delays = { { 5, 3 } }, + .shutdown_after_accept = 1, + }, +}; + +#define N_DTLS_TESTS (sizeof(dtls_tests) / sizeof(*dtls_tests)) + +static void +dtlstest_packet_monkey(SSL *ssl, const struct dtls_delay delays[], + const uint8_t drops[]) +{ + BIO *bio_monkey; + BIO *bio; + int i; + + if ((bio_monkey = BIO_new_packet_monkey()) == NULL) + errx(1, "packet monkey"); + + for (i = 0; i < MAX_PACKET_DELAYS; i++) { + if (delays[i].packet == 0) + break; + if (!BIO_packet_monkey_delay(bio_monkey, delays[i].packet, + delays[i].count)) + errx(1, "delay failure"); + } + + for (i = 0; i < MAX_PACKET_DROPS; i++) { + if (drops[i] == 0) + break; + if (!BIO_packet_monkey_drop(bio_monkey, drops[i])) + errx(1, "drop failure"); + } + + if ((bio = SSL_get_wbio(ssl)) == NULL) + errx(1, "SSL has NULL bio"); + + BIO_up_ref(bio); + bio = BIO_push(bio_monkey, bio); + + SSL_set_bio(ssl, bio, bio); +} + +static int +dtlstest(const struct dtls_test *dt) +{ + SSL *client = NULL, *server = NULL; + ssl_func *connect_func, *accept_func; + struct sockaddr_in server_sin; + struct pollfd pfd[2]; + int client_sock = -1; + int server_sock = -1; + int failed = 1; + + fprintf(stderr, "\n== Testing %s... ==\n", dt->desc); + + if (!datagram_pair(&client_sock, &server_sock, &server_sin)) + goto failure; + + if ((client = dtls_client(client_sock, &server_sin, dt->mtu)) == NULL) + goto failure; + + if ((server = dtls_server(server_sock, dt->ssl_options, dt->mtu)) == NULL) + goto failure; + + tls12_record_layer_set_initial_epoch(client->rl, dt->initial_epoch); + tls12_record_layer_set_initial_epoch(server->rl, dt->initial_epoch); + + if (dt->client_bbio_off) + SSL_set_info_callback(client, dtls_info_callback); + if (dt->server_bbio_off) + SSL_set_info_callback(server, dtls_info_callback); + + dtlstest_packet_monkey(client, dt->client_delays, dt->client_drops); + dtlstest_packet_monkey(server, dt->server_delays, dt->server_drops); + + pfd[0].fd = client_sock; + pfd[0].events = POLLOUT; + pfd[1].fd = server_sock; + pfd[1].events = POLLIN; + + accept_func = do_accept; + connect_func = do_connect; + + if (dt->write_after_accept) { + accept_func = do_accept_write; + connect_func = do_connect_read; + } else if (dt->shutdown_after_accept) { + accept_func = do_accept_shutdown; + connect_func = do_connect_shutdown; + } + + if (!do_client_server_loop(client, connect_func, server, accept_func, pfd)) { + fprintf(stderr, "FAIL: client and server handshake failed\n"); + goto failure; + } + + if (dt->write_after_accept || dt->shutdown_after_accept) + goto done; + + pfd[0].events = POLLIN; + pfd[1].events = POLLOUT; + + if (!do_client_server_loop(client, do_read, server, do_write, pfd)) { + fprintf(stderr, "FAIL: client read and server write I/O failed\n"); + goto failure; + } + + pfd[0].events = POLLOUT; + pfd[1].events = POLLIN; + + if (!do_client_server_loop(client, do_write, server, do_read, pfd)) { + fprintf(stderr, "FAIL: client write and server read I/O failed\n"); + goto failure; + } + + pfd[0].events = POLLOUT; + pfd[1].events = POLLOUT; + + if (!do_client_server_loop(client, do_shutdown, server, do_shutdown, pfd)) { + fprintf(stderr, "FAIL: client and server shutdown failed\n"); + goto failure; + } + + done: + fprintf(stderr, "INFO: Done!\n"); + + failed = 0; + + failure: + if (client_sock != -1) + close(client_sock); + if (server_sock != -1) + close(server_sock); + + SSL_free(client); + SSL_free(server); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + if (argc != 4) { + fprintf(stderr, "usage: %s keyfile certfile cafile\n", + argv[0]); + exit(1); + } + + server_key_file = argv[1]; + server_cert_file = argv[2]; + server_ca_file = argv[3]; + + for (i = 0; i < N_DTLS_TESTS; i++) + failed |= dtlstest(&dtls_tests[i]); + + return failed; +} diff --git a/tests/ec_asn1_test.c b/tests/ec_asn1_test.c new file mode 100644 index 0000000..512f5c5 --- /dev/null +++ b/tests/ec_asn1_test.c @@ -0,0 +1,206 @@ +/* $OpenBSD: ec_asn1_test.c,v 1.2 2021/12/04 17:03:43 tb Exp $ */ +/* + * Copyright (c) 2017, 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +const uint8_t ec_secp256r1_pkparameters_named_curve[] = { + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, +}; + +const uint8_t ec_secp256r1_pkparameters_parameters[] = { + 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30, 0x2c, + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, + 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04, 0x20, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, + 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, + 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, + 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, + 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d, 0x36, + 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, + 0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, + 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1, 0xf2, + 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, + 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, + 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, + 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, + 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, + 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, + 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, + 0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, + 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, + 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51, 0x02, + 0x01, 0x01, +}; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +compare_data(const char *label, const unsigned char *d1, size_t d1_len, + const unsigned char *d2, size_t d2_len) +{ + if (d1_len != d2_len) { + fprintf(stderr, "FAIL: got %s with length %zu, want %zu\n", + label, d1_len, d2_len); + return -1; + } + if (memcmp(d1, d2, d1_len) != 0) { + fprintf(stderr, "FAIL: %sdiffer\n", label); + fprintf(stderr, "got:\n"); + hexdump(d1, d1_len); + fprintf(stderr, "want:\n"); + hexdump(d2, d2_len); + return -1; + } + return 0; +} + +static int +ec_group_pkparameters_test(const char *label, int asn1_flag, + const uint8_t *test_data, size_t test_data_len) +{ + EC_GROUP *group_a = NULL, *group_b = NULL; + unsigned char *out = NULL, *data = NULL; + const unsigned char *p; + BIO *bio_mem = NULL; + int failure = 1; + int len; + + /* + * Test i2d_ECPKParameters/d2i_ECPKParameters. + */ + if ((group_a = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) + errx(1, "failed to create EC_GROUP"); + + EC_GROUP_set_asn1_flag(group_a, asn1_flag); + + if ((len = i2d_ECPKParameters(group_a, &out)) < 0) { + fprintf(stderr, "FAIL: i2d_ECPKParameters failed\n"); + goto done; + } + if (compare_data(label, out, len, test_data, test_data_len) == -1) + goto done; + + p = out; + if ((group_b = d2i_ECPKParameters(NULL, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_ECPKParameters failed\n"); + goto done; + } + + if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) { + fprintf(stderr, "FAIL: EC_GROUPs do not match!\n"); + goto done; + } + + p = out; + if ((group_a = d2i_ECPKParameters(&group_a, &p, len)) == NULL) { + fprintf(stderr, "FAIL: d2i_ECPKParameters failed\n"); + goto done; + } + + if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) { + fprintf(stderr, "FAIL: EC_GROUPs do not match!\n"); + goto done; + } + + /* + * Test i2d_ECPKParameters_bio/d2i_ECPKParameters_bio. + */ + if ((bio_mem = BIO_new(BIO_s_mem())) == NULL) + errx(1, "BIO_new failed for BIO_s_mem"); + + if ((len = i2d_ECPKParameters_bio(bio_mem, group_a)) < 0) { + fprintf(stderr, "FAIL: i2d_ECPKParameters_bio failed\n"); + goto done; + } + + len = BIO_get_mem_data(bio_mem, &data); + if (compare_data(label, out, len, test_data, test_data_len) == -1) + goto done; + + EC_GROUP_free(group_b); + if ((group_b = d2i_ECPKParameters_bio(bio_mem, NULL)) == NULL) { + fprintf(stderr, "FAIL: d2i_ECPKParameters_bio failed\n"); + goto done; + } + + if (EC_GROUP_cmp(group_a, group_b, NULL) != 0) { + fprintf(stderr, "FAIL: EC_GROUPs do not match!\n"); + goto done; + } + + failure = 0; + + done: + BIO_free_all(bio_mem); + EC_GROUP_free(group_a); + EC_GROUP_free(group_b); + free(out); + + return (failure); +} + +static int +ec_group_pkparameters_named_curve_test(void) +{ + return ec_group_pkparameters_test("ECPKPARAMETERS named curve", + OPENSSL_EC_NAMED_CURVE, ec_secp256r1_pkparameters_named_curve, + sizeof(ec_secp256r1_pkparameters_named_curve)); +} + +static int +ec_group_pkparameters_parameters_test(void) +{ + return ec_group_pkparameters_test("ECPKPARAMETERS parameters", + OPENSSL_EC_EXPLICIT_CURVE, ec_secp256r1_pkparameters_parameters, + sizeof(ec_secp256r1_pkparameters_parameters)); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= ec_group_pkparameters_named_curve_test(); + failed |= ec_group_pkparameters_parameters_test(); + + return (failed); +} diff --git a/tests/ec_point_conversion.c b/tests/ec_point_conversion.c new file mode 100644 index 0000000..001e8a0 --- /dev/null +++ b/tests/ec_point_conversion.c @@ -0,0 +1,545 @@ +/* $OpenBSD: ec_point_conversion.c,v 1.14 2023/08/01 17:19:49 tb Exp $ */ +/* + * Copyright (c) 2021 Theo Buehler + * Copyright (c) 2021 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +int forms[] = { + POINT_CONVERSION_COMPRESSED, + POINT_CONVERSION_UNCOMPRESSED, + POINT_CONVERSION_HYBRID, +}; + +static const size_t N_FORMS = sizeof(forms) / sizeof(forms[0]); +#define N_RANDOM_POINTS 10 + +static const char * +form2str(int form) +{ + switch (form) { + case POINT_CONVERSION_COMPRESSED: + return "compressed form"; + case POINT_CONVERSION_UNCOMPRESSED: + return "uncompressed form"; + case POINT_CONVERSION_HYBRID: + return "hybrid form"; + default: + return "unknown form"; + } +} + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static int +roundtrip(EC_GROUP *group, EC_POINT *point, int form, BIGNUM *x, BIGNUM *y) +{ + BIGNUM *x_out = NULL, *y_out = NULL; + size_t len; + uint8_t *buf = NULL; + int failed = 1; + + if ((len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL)) == 0) + errx(1, "point2oct"); + if ((buf = malloc(len)) == NULL) + errx(1, "malloc"); + if (EC_POINT_point2oct(group, point, form, buf, len, NULL) != len) + errx(1, "point2oct"); + + if (!EC_POINT_oct2point(group, point, buf, len, NULL)) + errx(1, "%s oct2point", form2str(form)); + + if ((x_out = BN_new()) == NULL) + errx(1, "new x_out"); + if ((y_out = BN_new()) == NULL) + errx(1, "new y_out"); + + if (!EC_POINT_get_affine_coordinates(group, point, x_out, y_out, NULL)) + errx(1, "get affine"); + + if (BN_cmp(x, x_out) != 0) { + warnx("%s: x", form2str(form)); + goto err; + } + if (BN_cmp(y, y_out) != 0) { + warnx("%s: y", form2str(form)); + goto err; + } + + failed = 0; + + err: + if (failed) + hexdump(buf, len); + + free(buf); + BN_free(x_out); + BN_free(y_out); + + return failed; +} + +/* XXX This only tests multiples of the generator for now... */ +static int +test_random_points_on_curve(EC_builtin_curve *curve) +{ + EC_GROUP *group; + BIGNUM *order = NULL; + BIGNUM *random; + BIGNUM *x, *y; + size_t i, j; + int failed = 0; + + if ((group = EC_GROUP_new_by_curve_name(curve->nid)) == NULL) + errx(1, "EC_GROUP_new_by_curve_name(%s)", + OBJ_nid2sn(curve->nid)); + + if ((order = BN_new()) == NULL) + errx(1, "BN_new order"); + if ((random = BN_new()) == NULL) + errx(1, "BN_new random"); + if ((x = BN_new()) == NULL) + errx(1, "BN_new x"); + if ((y = BN_new()) == NULL) + errx(1, "BN_new y"); + + if (!EC_GROUP_get_order(group, order, NULL)) + errx(1, "EC_group_get_order"); + + for (i = 0; i < N_RANDOM_POINTS; i++) { + EC_POINT *random_point; + + do { + if (!BN_rand_range(random, order)) + errx(1, "BN_rand_range"); + } while (BN_is_zero(random)); + + if ((random_point = EC_POINT_new(group)) == NULL) + errx(1, "EC_POINT_new"); + + if (!EC_POINT_mul(group, random_point, random, NULL, NULL, NULL)) + errx(1, "EC_POINT_mul"); + + if (EC_POINT_is_at_infinity(group, random_point)) { + EC_POINT_free(random_point); + + warnx("info: got infinity"); + fprintf(stderr, "random = "); + BN_print_fp(stderr, random); + fprintf(stderr, "\n"); + + continue; + } + + if (!EC_POINT_get_affine_coordinates(group, random_point, + x, y, NULL)) + errx(1, "EC_POINT_get_affine_coordinates"); + + for (j = 0; j < N_FORMS; j++) + failed |= roundtrip(group, random_point, forms[j], x, y); + + EC_POINT_free(random_point); + } + + BN_free(order); + BN_free(random); + BN_free(x); + BN_free(y); + EC_GROUP_free(group); + + return failed; +} + +static int +test_random_points(void) +{ + EC_builtin_curve *all_curves = NULL; + size_t ncurves = 0; + size_t curve_id; + int failed = 0; + + ncurves = EC_get_builtin_curves(NULL, 0); + if ((all_curves = calloc(ncurves, sizeof(EC_builtin_curve))) == NULL) + err(1, "calloc builtin curves"); + EC_get_builtin_curves(all_curves, ncurves); + + for (curve_id = 0; curve_id < ncurves; curve_id++) + failed |= test_random_points_on_curve(&all_curves[curve_id]); + + fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : ""); + + free(all_curves); + return failed; +} + +static const struct point_conversion { + const char *description; + int nid; + uint8_t octets[256]; + uint8_t octets_len; + int valid; +} point_conversions[] = { + /* XXX - now that sect571 is no longer tested, add another test? */ + { + .description = "point at infinity on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { 0x00 }, + .octets_len = 1, + .valid = 1, + }, + { + .description = "point at infinity on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { 0x01 }, + .octets_len = 1, + .valid = 0, + }, + { + .description = "zero x compressed point on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x02, 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, + }, + .octets_len = 33, + .valid = 1, + }, + { + .description = + "zero x compressed point on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x03, 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, + }, + .octets_len = 33, + .valid = 1, + }, + { + .description = "generic compressed point on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x03, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b, + 0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11, + 0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0, + 0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee, + 0xdd, + }, + .octets_len = 33, + .valid = 1, + }, + { + .description = + "generic compressed point on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x02, 0xa3, 0x96, 0xa0, 0x42, 0x73, 0x1a, 0x8b, + 0x90, 0xd8, 0xcb, 0xae, 0xda, 0x1b, 0x23, 0x11, + 0x77, 0x5f, 0x6a, 0x4c, 0xb4, 0x57, 0xbf, 0xe0, + 0x65, 0xd4, 0x09, 0x11, 0x5f, 0x54, 0xe4, 0xee, + 0xdd, + }, + .octets_len = 33, + .valid = 1, + }, + { + .description = "zero x uncompressed point #1 on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x04, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, + 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, + 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, + 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, + 0xf4, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "zero x uncompressed point #1 on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, + 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, + 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, + 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, + 0xf4, + }, + .octets_len = 65, + .valid = 0, + }, + { + .description = "zero x uncompressed point #2 on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x04, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, + 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, + 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, + 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, + 0x0b, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "zero x uncompressed point #2 on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, + 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, + 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, + 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, + 0x0b, + }, + .octets_len = 65, + .valid = 0, + }, + { + .description = "generic uncompressed point on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x04, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34, + 0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4, + 0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c, + 0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73, + 0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2, + 0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a, + 0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc, + 0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2, + 0x03, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "generic uncompressed point on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x05, 0x23, 0xe5, 0x85, 0xa5, 0x4b, 0xda, 0x34, + 0x7e, 0xe5, 0x65, 0x53, 0x7f, 0x3b, 0xce, 0xe4, + 0x54, 0xd8, 0xa4, 0x5a, 0x53, 0x4b, 0xb0, 0x4c, + 0xb9, 0x31, 0x09, 0x29, 0xa2, 0x03, 0x4c, 0x73, + 0x20, 0xd2, 0xc6, 0x17, 0xca, 0xe3, 0xcf, 0xc2, + 0xd8, 0x31, 0xfe, 0xf1, 0x7c, 0x6f, 0x9d, 0x7a, + 0x01, 0x7c, 0x34, 0x65, 0x42, 0x05, 0xaf, 0xcc, + 0x04, 0xa3, 0x2f, 0x44, 0x14, 0xbe, 0xd8, 0xc2, + 0x03, + }, + .octets_len = 65, + .valid = 0, + }, + { + .description = "zero x hybrid point #1 on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x06, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, + 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, + 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, + 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, + 0xf4, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "zero x hybrid point #1 on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x07, 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, 0x66, 0x48, 0x5c, 0x78, 0x0e, 0x2f, 0x83, + 0xd7, 0x24, 0x33, 0xbd, 0x5d, 0x84, 0xa0, 0x6b, + 0xb6, 0x54, 0x1c, 0x2a, 0xf3, 0x1d, 0xae, 0x87, + 0x17, 0x28, 0xbf, 0x85, 0x6a, 0x17, 0x4f, 0x93, + 0xf4, + }, + .octets_len = 65, + .valid = 0, + }, + { + .description = "zero x hybrid point #2 on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x07, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, + 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, + 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, + 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, + 0x0b, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "zero x hybrid point #2 on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x06, 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, 0x99, 0xb7, 0xa3, 0x86, 0xf1, 0xd0, 0x7c, + 0x29, 0xdb, 0xcc, 0x42, 0xa2, 0x7b, 0x5f, 0x94, + 0x49, 0xab, 0xe3, 0xd5, 0x0d, 0xe2, 0x51, 0x78, + 0xe8, 0xd7, 0x40, 0x7a, 0x95, 0xe8, 0xb0, 0x6c, + 0x0b, + }, + .octets_len = 65, + .valid = 0, + }, + { + .description = "generic hybrid point on secp256r1", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x07, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec, + 0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63, + 0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f, + 0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92, + 0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59, + 0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6, + 0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd, + 0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7, + 0xc5, + }, + .octets_len = 65, + .valid = 1, + }, + { + .description = + "generic hybrid point on secp256r1 (flipped y_bit)", + .nid = NID_X9_62_prime256v1, + .octets = { + 0x06, 0x38, 0xb2, 0x98, 0x38, 0x21, 0x6b, 0xec, + 0x87, 0xcf, 0x50, 0xbb, 0x65, 0x11, 0x96, 0x63, + 0xf3, 0x90, 0x64, 0xc3, 0x5c, 0x59, 0xa5, 0x6f, + 0xaf, 0x56, 0x2a, 0x0c, 0xc0, 0x3a, 0x9b, 0x92, + 0x85, 0x95, 0x54, 0xf3, 0x08, 0x0f, 0x78, 0x59, + 0xa2, 0x44, 0x2f, 0x19, 0x5d, 0xd5, 0xcd, 0xf6, + 0xa5, 0xbe, 0x2f, 0x83, 0x70, 0x94, 0xf5, 0xcd, + 0x8c, 0x40, 0x7f, 0xd8, 0x97, 0x92, 0x14, 0xf7, + 0xc5, + }, + .octets_len = 65, + .valid = 0, + }, +}; + +static const size_t N_POINT_CONVERSIONS = + sizeof(point_conversions) / sizeof(point_conversions[0]); + +static int +point_conversion_form_y_bit(const struct point_conversion *test) +{ + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + int ret; + int failed = 0; + + if ((group = EC_GROUP_new_by_curve_name(test->nid)) == NULL) + errx(1, "group"); + if ((point = EC_POINT_new(group)) == NULL) + errx(1, "point"); + + ret = EC_POINT_oct2point(group, point, test->octets, test->octets_len, + NULL); + if (ret != test->valid) { + fprintf(stderr, "%s want %d got %d\n", test->description, + test->valid, ret); + failed |= 1; + } + + EC_GROUP_free(group); + EC_POINT_free(point); + + return failed; +} + +static int +test_point_conversions(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_POINT_CONVERSIONS; i++) + failed |= point_conversion_form_y_bit(&point_conversions[i]); + + fprintf(stderr, "%s %s\n", __func__, failed ? ": FAILED" : ""); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_random_points(); + failed |= test_point_conversions(); + + return failed; +} diff --git a/tests/ecc_cdh.c b/tests/ecc_cdh.c new file mode 100644 index 0000000..0333cf1 --- /dev/null +++ b/tests/ecc_cdh.c @@ -0,0 +1,2506 @@ +/* $OpenBSD: ecc_cdh.c,v 1.2 2023/07/16 08:25:41 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * ECC-CDH test vectors extracted from version 14.1 of Component-Testing#ECCCDH + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/ + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +static const struct ecc_cdh_test { + int nid; + const char *peer_x; + const char *peer_y; + const char *priv; + const char *pub_x; + const char *pub_y; + const char *want; +} ecc_cdh_tests[] = { + { + .nid = NID_X9_62_prime192v1, + .peer_x = "42ea6dd9969dd2a61fea1aac7f8e98edcc896c6e55857cc0", + .peer_y = "dfbe5d7c61fac88b11811bde328e8a0d12bf01a9d204b523", + .priv = "f17d3fea367b74d340851ca4270dcb24c271f445bed9d527", + .pub_x = "b15053401f57285637ec324c1cd2139e3a67de3739234b37", + .pub_y = "f269c158637482aad644cd692dd1d3ef2c8a7c49e389f7f6", + .want = "803d8ab2e5b6e6fca715737c3a82f7ce3c783124f6d51cd0", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "deb5712fa027ac8d2f22c455ccb73a91e17b6512b5e030e7", + .peer_y = "7e2690a02cc9b28708431a29fb54b87b1f0c14e011ac2125", + .priv = "56e853349d96fe4c442448dacb7cf92bb7a95dcf574a9bd5", + .pub_x = "c00d435716ffea53fd8c162792414c37665187e582716539", + .pub_y = "ab711c62aa71a5a18e8a3c48f89dc6fa52fac0108e52a8a0", + .want = "c208847568b98835d7312cef1f97f7aa298283152313c29d", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "4edaa8efc5a0f40f843663ec5815e7762dddc008e663c20f", + .peer_y = "0a9f8dc67a3e60ef6d64b522185d03df1fc0adfd42478279", + .priv = "c6ef61fe12e80bf56f2d3f7d0bb757394519906d55500949", + .pub_x = "e184bc182482f3403c8787b83842477467fcd011db0f6c64", + .pub_y = "f9d1c14142f40de8639db97d51a63d2cce1007ccf773cdcb", + .want = "87229107047a3b611920d6e3b2c0c89bea4f49412260b8dd", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "8887c276edeed3e9e866b46d58d895c73fbd80b63e382e88", + .peer_y = "04c5097ba6645e16206cfb70f7052655947dd44a17f1f9d5", + .priv = "e6747b9c23ba7044f38ff7e62c35e4038920f5a0163d3cda", + .pub_x = "2b838dbe73735f37a39a78d3195783d26991e86ff4d92d1a", + .pub_y = "60d344942274489f98903b2e7f93f8d197fc9ae60a0ed53a", + .want = "eec0bed8fc55e1feddc82158fd6dc0d48a4d796aaf47d46c", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "0d045f30254adc1fcefa8a5b1f31bf4e739dd327cd18d594", + .peer_y = "542c314e41427c08278a08ce8d7305f3b5b849c72d8aff73", + .priv = "beabedd0154a1afcfc85d52181c10f5eb47adc51f655047d", + .pub_x = "1f65cf6e8978e1c1bc10bb61a7db311de310088c8cf9768b", + .pub_y = "f7d438168e7f42ab14b16af53a7a2f646ff40b53d74cbcc7", + .want = "716e743b1b37a2cd8479f0a3d5a74c10ba2599be18d7e2f4", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "fb35ca20d2e96665c51b98e8f6eb3d79113508d8bccd4516", + .peer_y = "368eec0d5bfb847721df6aaff0e5d48c444f74bf9cd8a5a7", + .priv = "cf70354226667321d6e2baf40999e2fd74c7a0f793fa8699", + .pub_x = "5f4844ffcce61005d24f737db98675e92f7b6543aeb6106c", + .pub_y = "5424f598139215d389b6b12b86d58014857f2ddadb540f51", + .want = "f67053b934459985a315cb017bf0302891798d45d0e19508", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "824752960c1307e5f13a83da21c7998ca8b5b00b9549f6d0", + .peer_y = "bc52d91e234363bc32ee0b6778f25cd8c1847510f4348b94", + .priv = "fe942515237fffdd7b4eb5c64909eee4856a076cdf12bae2", + .pub_x = "e6369df79b207b8b8679f7c869cfc264859d1ab55aa401e8", + .pub_y = "1f99c71f801a30b52f74da6e5e6dbb62ee4c5da1090cc020", + .want = "75822971193edd472bf30151a782619c55ad0b279c9303dd", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "10bb57020291141981f833b4749e5611034b308e84011d21", + .peer_y = "e1cacd6b7bd17ed8ddb50b6aee0654c35f2d0eddc1cffcf6", + .priv = "33fed10492afa5bea0333c0af12cac940c4d222455bcd0fe", + .pub_x = "ef0b28afc41637d737f42e4c8aaceadc84ba2e0b849ca18c", + .pub_y = "57797942e552173bba17f73278e029f42335068bd770ddf2", + .want = "67cba2cbb69ee78bf1abafb0e6fbe33fa2094c128d59652d", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "5192fce4185a7758ea1bc56e0e4f4e8b2dce32348d0dced1", + .peer_y = "20989981beaaf0006d88a96e7971a2fa3a33ba46047fc7ba", + .priv = "f3557c5d70b4c7954960c33568776adbe8e43619abe26b13", + .pub_x = "d70112c5f0f0844386494ac1ad99dce2214134176ebfb9af", + .pub_y = "d3c187a038510ab31d459e2b7af1a380dd7576af06267548", + .want = "cf99a2770a386ca0137d1eca0a226e484297ac3c513f3631", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "26d019dbe279ead01eed143a91601ada26e2f42225b1c62b", + .peer_y = "6ca653f08272e0386fc9421fbd580093d7ae6301bca94476", + .priv = "586cfba1c6e81766ed52828f177b1be14ebbc5b83348c311", + .pub_x = "58b3c63e56bec9d696bf9a88df2873738391f76368aa2b49", + .pub_y = "5776773b261faf7ba2fdc4fe43b92c0b1c7a2fd054a43650", + .want = "576331e2b4fb38a112810e1529834de8307fb0a0d2756877", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "539bc40fe20a0fb267888b647b03eaaf6ec20c02a1e1f8c8", + .peer_y = "69095e5bb7b4d44c3278a7ee6beca397c45246da9a34c8be", + .priv = "cad8100603a4f65be08d8fc8a1b7e884c5ff65deb3c96d99", + .pub_x = "b7fcc0f52c7a411edbed39e10bf02b6ae0f26614c6b325a2", + .pub_y = "47483b26eb67776de2b93ab7119d5447573739e3d55e72fb", + .want = "902f4501916a0dd945554c3a37b3d780d375a6da713197c4", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "5d343ddb96318fb4794d10f6c573f99fee5d0d57b996250f", + .peer_y = "99fbdf9d97dd88ad410235dac36e5b92ce2824b8e587a82c", + .priv = "1edd879cc5c79619cae6c73a691bd5a0395c0ef3b356fcd2", + .pub_x = "6ce6adb2c30808f590048c33dffad4524ebf7a5fd39b747b", + .pub_y = "4966bd2f3d00569b4d4c0409fbd7a2db752f6d09bca8c25f", + .want = "46e4de335054d429863218ae33636fc9b89c628b64b506c7", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "8d3db9bdce137ffbfb891388c37df6c0cbc90aa5e5376220", + .peer_y = "135d30b5cb660eef8764ffc744f15c1b5d6dc06ba4416d37", + .priv = "460e452273fe1827602187ad3bebee65cb84423bb4f47537", + .pub_x = "d1bd3a3efabf4767fe6380bdf0dbf49d52d4cf0cbb89404c", + .pub_y = "c150c2b4c8b3aa35f765f847e4f7f8fd8704d241a181ee99", + .want = "1bfe9e5a20ac7a38d8f605b425bb9030be31ef97c101c76c", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "9e0a6949519c7f5be68c0433c5fdf13064aa13fb29483dc3", + .peer_y = "e1c8ba63e1f471db23185f50d9c871edea21255b3a63b4b7", + .priv = "b970365008456f8758ecc5a3b33cf3ae6a8d568107a52167", + .pub_x = "c1b8610c8c63f8d4abda093b9a11a566044bf65c6faa8999", + .pub_y = "a5bc4b3ca095382e9738aee95fe9479b17879b3ad5295559", + .want = "0e8c493a4adc445dc9288a3b9b272599224054592d7265b3", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "be088238902e9939b3d054eeeb8492daf4bdcf09a2ab77f1", + .peer_y = "58d6749a3a923dc80440f2661fd35b651617e65294b46375", + .priv = "59c15b8a2464e41dfe4371c7f7dadf470ae425544f8113bd", + .pub_x = "1fe776f73567b6ac0b0d6764164de6c5be751ba8d1ff455e", + .pub_y = "4c160bf38afb2b71f684261664115ce874553e8b059432d2", + .want = "0f1991086b455ded6a1c4146f7bf59fe9b495de566ebc6bf", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "bf5ae05025e1be617e666d87a4168363873d5761b376b503", + .peer_y = "e1e6e38b372b6bee0ff5b3502d83735e3b2c26825e4f0fcc", + .priv = "a6e9b885c66b959d1fc2708d591b6d3228e49eb98f726d61", + .pub_x = "632bb7651dbf49dde9dd125d13fb234e06617723beed3d1b", + .pub_y = "f4ad5209638488397c5f44f994dd7479807e79f4887d2e71", + .want = "b30f2127c34df35aaa91dbf0bbe15798e799a03ed11698c1", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "6cc4feed84c7ab0d09005d660ed34de6955a9461c4138d11", + .peer_y = "31225f33864ed48da06fa45a913b46cf42557742e35085e6", + .priv = "bdb754096ffbfbd8b0f3cb046ccb7ca149c4e7192067a3ee", + .pub_x = "d9c098d421d741f6faab116f3e4731d28c5558e19fe112a1", + .pub_y = "38d4dc48ccdb1d3ed8d31fd06784a4f87a68aec1cbd5b08f", + .want = "64a5c246599d3e8177a2402a1110eb81e6c456ab4edb5127", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "36157315bee7afedded58c4e8ba14d3421c401e51135bcc9", + .peer_y = "37c297ca703f77c52bb062d8ce971db84097ba0c753a418f", + .priv = "d5bcf2534dafc3d99964c7bd63ab7bd15999fe56dd969c42", + .pub_x = "fda1d5d28d6fe0e7909d6a8bafa7824db5572ab92ffe7de6", + .pub_y = "134a297c1d9c8bbab249abacd951ed11e5a99f92e7991572", + .want = "017b8ca53c82fab163da2ab783966a39e061b32c8cfa334d", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "98464d47f0256f8292e027e8c92582ea77cf9051f5ce8e5d", + .peer_y = "449552ef7578be96236fe5ed9d0643c0bb6c5a9134b0108d", + .priv = "43d4b9df1053be5b4268104c02244d3bf9594b010b46a8b2", + .pub_x = "c3020b7091463d788f1f1d76f7cfeec82ecdb3b7d99c345c", + .pub_y = "9a7710d5179591d8f3df0aa122301768ae7db7eee2d7f583", + .want = "340ef3db3dbebdd91c62c3d4e1a3da2c7c52a3338b865259", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "563eb66c334cf6f123bf04c7803b48a3110214237e983bf5", + .peer_y = "0f351104819199ef07c9a6051d20758f3af79027ea66a53f", + .priv = "94cac2c2ca714746401670d94edbf3f677867b5a03bee7ad", + .pub_x = "b18554a2e743ef0aa2f040987c4c451004e096df3d80ddae", + .pub_y = "6e3e2c618f896e36ba620077684b70a05ffb79bf5e6c7640", + .want = "2162144921df5103d0e6a650fb13fd246f4738d0896ce92f", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "86828c4ac92b5507618aec7873a1d4fc6543c5be33cf3078", + .peer_y = "b22ca72437545e10d6d4f052422eb898b737a4b8543ee550", + .priv = "2a3a9e33c8cc3107a9f9265c3bdea1206570e86f92ac7014", + .pub_x = "a7ba38be1bc669dd23ccfcee0645b1f0db8cf942deafaeb6", + .pub_y = "b82db79d80cd0e37f28d4163adc389dee8fc7797b5c9831b", + .want = "4c69e7feed4b11159adfc16a6047a92572ea44e0740b23af", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "6700a102437781a9581da2bc25ced5abf419da91d3c803df", + .peer_y = "71396c9cf08bcd91854e3e6e42d8c657ce0f27ab77a9dc4b", + .priv = "4a6b78a98ac98fa8e99a8ece08ec0251125f85c6fd0e289b", + .pub_x = "e769dbbcd5ce2d83514b768d3d2d5aa0bcd8f66af15f5500", + .pub_y = "2fc6d0b039e0f28f74fbeffe9e883d4dd72296e4e95cae71", + .want = "46072acefd67bff50de355ca7a31fa6be59f26e467587259", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "a82f354cf97bee5d22dc6c079f2902ead44d96a8f614f178", + .peer_y = "a654a9aa8a1a0802f2ce0ee8a0f4ebe96dee1b37464b1ff2", + .priv = "c5a6491d78844d6617ef33be6b8bd54da221450885d5950f", + .pub_x = "db1b24f7466bc154e9d7d2c3ca52dcfe0bfc9563c5fdb6f3", + .pub_y = "1c74fbbf5bd99921f1a9a744f8e1cf770bd6a76a772b3003", + .want = "ec5580eabca9f3389d2b427ddf6e49e26d629afd03fa766e", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "3cec21b28668a12a2cf78e1a8e55d0efe065152fffc34718", + .peer_y = "1029557beba4ff1992bd21c23cb4825f6dae70e3318fd1ca", + .priv = "2ba2703c5e23f6463c5b88dc37292fabd3399b5e1fb67c05", + .pub_x = "7543148906cef9b37a71a7c08363cdd3bba50142d65241aa", + .pub_y = "8b3a6973de8dc271e27c1ead1e962fdaae3710c724daac38", + .want = "7f3929dd3cbf7673bc30d859d90b880307475f800660ea32", + }, + { + .nid = NID_X9_62_prime192v1, + .peer_x = "7082644715b8b731f8228b5118e7270d34d181f361a221fc", + .peer_y = "464649d6c88ca89614488a1cc7b8442bb42f9fb3020a3d76", + .priv = "836118c6248f882e9147976f764826c1a28755a6102977d5", + .pub_x = "fcd345a976c720caaa97de6697226825615e1287a9eff67e", + .pub_y = "58ea42edbeeafca9ff44cfd7f29abd2cbde7626d79e422c9", + .want = "72e88f3ea67d46d46dbf83926e7e2a6b85b54536741e6d2c", + }, + + { + .nid = NID_secp224r1, + .peer_x = + "af33cd0629bc7e996320a3f40368f74de8704fa37b8fab69abaae280", + .peer_y = + "882092ccbba7930f419a8a4f9bb16978bbc3838729992559a6f2e2d7", + .priv = + "8346a60fc6f293ca5a0d2af68ba71d1dd389e5e40837942df3e43cbd", + .pub_x = + "8de2e26adf72c582d6568ef638c4fd59b18da171bdf501f1d929e048", + .pub_y = + "4a68a1c2b0fb22930d120555c1ece50ea98dea8407f71be36efac0de", + .want = + "7d96f9a3bd3c05cf5cc37feb8b9d5209d5c2597464dec3e9983743e8", + }, + { + .nid = NID_secp224r1, + .peer_x = + "13bfcd4f8e9442393cab8fb46b9f0566c226b22b37076976f0617a46", + .peer_y = + "eeb2427529b288c63c2f8963c1e473df2fca6caa90d52e2f8db56dd4", + .priv = + "043cb216f4b72cdf7629d63720a54aee0c99eb32d74477dac0c2f73d", + .pub_x = + "2f90f5c8eac9c7decdbb97b6c2f715ab725e4fe40fe6d746efbf4e1b", + .pub_y = + "66897351454f927a309b269c5a6d31338be4c19a5acfc32cf656f45c", + .want = + "ee93ce06b89ff72009e858c68eb708e7bc79ee0300f73bed69bbca09", + }, + { + .nid = NID_secp224r1, + .peer_x = + "756dd806b9d9c34d899691ecb45b771af468ec004486a0fdd283411e", + .peer_y = + "4d02c2ca617bb2c5d9613f25dd72413d229fd2901513aa29504eeefb", + .priv = + "5ad0dd6dbabb4f3c2ea5fe32e561b2ca55081486df2c7c15c9622b08", + .pub_x = + "005bca45d793e7fe99a843704ed838315ab14a5f6277507e9bc37531", + .pub_y = + "43e9d421e1486ae5893bfd23c210e5c140d7c6b1ada59d842c9a98de", + .want = + "3fcc01e34d4449da2a974b23fc36f9566754259d39149790cfa1ebd3", + }, + { + .nid = NID_secp224r1, + .peer_x = + "0f537bf1c1122c55656d25e8aa8417e0b44b1526ae0523144f9921c4", + .peer_y = + "f79b26d30e491a773696cc2c79b4f0596bc5b9eebaf394d162fb8684", + .priv = + "0aa6ff55a5d820efcb4e7d10b845ea3c9f9bc5dff86106db85318e22", + .pub_x = + "2f96754131e0968198aa78fbe8c201dc5f3581c792de487340d32448", + .pub_y = + "61e8a5cd79615203b6d89e9496f9e236fe3b6be8731e743d615519c6", + .want = + "49129628b23afcef48139a3f6f59ff5e9811aa746aa4ff33c24bb940", + }, + { + .nid = NID_secp224r1, + .peer_x = + "2b3631d2b06179b3174a100f7f57131eeea8947be0786c3dc64b2239", + .peer_y = + "83de29ae3dad31adc0236c6de7f14561ca2ea083c5270c78a2e6cbc0", + .priv = + "efe6e6e25affaf54c98d002abbc6328da159405a1b752e32dc23950a", + .pub_x = + "355e962920bde043695f6bffb4b355c63da6f5de665ed46f2ec817e2", + .pub_y = + "748e095368f62e1d364edd461719793b404adbdaacbcadd88922ff37", + .want = + "fcdc69a40501d308a6839653a8f04309ec00233949522902ffa5eac6", + }, + { + .nid = NID_secp224r1, + .peer_x = + "4511403de29059f69a475c5a6a5f6cabed5d9f014436a8cb70a02338", + .peer_y = + "7d2d1b62aa046df9340f9c37a087a06b32cf7f08a223f992812a828b", + .priv = + "61cb2932524001e5e9eeed6df7d9c8935ee3322029edd7aa8acbfd51", + .pub_x = + "d50e4adabfd989d7dbc7cf4052546cc7c447a97630436997ad4b9536", + .pub_y = + "5bea503473c5eaef9552d42c40b1f2f7ca292733b255b9bbe1b12337", + .want = + "827e9025cb62e0e837c596063f3b9b5a0f7afd8d8783200086d61ec1", + }, + { + .nid = NID_secp224r1, + .peer_x = + "314a0b26dd31c248845d7cc17b61cad4608259bed85a58d1f1ffd378", + .peer_y = + "66e4b350352e119eecada382907f3619fd748ea73ae4899dfd496302", + .priv = + "8c7ace347171f92def98d845475fc82e1d1496da81ee58f505b985fa", + .pub_x = + "b1a8dcac89aca2799320b451df1c7ff4d97567abb68141c0d95fc2aa", + .pub_y = + "3524950902b1510bdc987d860afc27ad871ceaea66935abd3c0a99a8", + .want = + "335ba51228d94acbed851ca7821c801d5cb1c7975d7aa90a7159f8fa", + }, + { + .nid = NID_secp224r1, + .peer_x = + "abe6843beec2fd9e5fb64730d0be4d165438ce922ed75dd80b4603e5", + .peer_y = + "6afe8673a96c4ba9900ad85995e631e436c6cc88a2c2b47b7c4886b8", + .priv = + "382feb9b9ba10f189d99e71a89cdfe44cb554cec13a212840977fb68", + .pub_x = + "abb6f1e3773ff8fc73aea2a0b107809ce70adcefed6e41fc5cb43045", + .pub_y = + "a963897ae906c10a055eeadb97ffdd6f748d3e5621e5fff304e48ba7", + .want = + "8c2e627594206b34f7356d3426eb3d79f518ef843fbe94014cceace3", + }, + { + .nid = NID_secp224r1, + .peer_x = + "13cf9d6d2c9aae8274c27d446afd0c888ffdd52ae299a35984d4f527", + .peer_y = + "dcbee75b515751f8ee2ae355e8afd5de21c62a939a6507b538cbc4af", + .priv = + "e0d62035101ef487c485c60fb4500eebe6a32ec64dbe97dbe0232c46", + .pub_x = + "88537735e9b23e3e0e076f135a82d33f9bffb465f3abce8322a62a62", + .pub_y = + "b4c8c123673197875c0bd14ed097606d330fba2b9200ef65a44764d3", + .want = + "632abb662728dbc994508873d5c527ca5ef923c0d31fa6c47ef4c825", + }, + { + .nid = NID_secp224r1, + .peer_x = + "965b637c0dfbc0cf954035686d70f7ec30929e664e521dbaa2280659", + .peer_y = + "82a58ff61bc90019bbcbb5875d3863db0bc2a1fa34b0ad4de1a83f99", + .priv = + "b96ade5b73ba72aa8b6e4d74d7bf9c58e962ff78eb542287c7b44ba2", + .pub_x = + "37682926a54f70a4c1748f54d50d5b00138a055f924f2c65e5b0bbe4", + .pub_y = + "596afefcdd640d29635015b89bdddd1f8c2723686d332e7a06ca8799", + .want = + "34641141aab05ef58bd376d609345901fb8f63477c6be9097f037f1f", + }, + { + .nid = NID_secp224r1, + .peer_x = + "73cc645372ca2e71637cda943d8148f3382ab6dd0f2e1a49da94e134", + .peer_y = + "df5c355c23e6e232ebc3bee2ab1873ee0d83e3382f8e6fe613f6343c", + .priv = + "a40d7e12049c71e6522c7ff2384224061c3a457058b310557655b854", + .pub_x = + "399801243bfe0c2da9b0a53c8ca57f2eee87aaa94a8e4d5e029f42ca", + .pub_y = + "aa49e6d4b47cee7a5c4ab71d5a67da84e0b9b425ce3e70da68c889e7", + .want = + "4f74ac8507501a32bfc5a78d8271c200e835966e187e8d00011a8c75", + }, + { + .nid = NID_secp224r1, + .peer_x = + "546578216250354e449e21546dd11cd1c5174236739acad9ce0f4512", + .peer_y = + "d2a22fcd66d1abedc767668327c5cb9c599043276239cf3c8516af24", + .priv = + "ad2519bc724d484e02a69f05149bb047714bf0f5986fac2e222cd946", + .pub_x = + "df9c1e0ef15e53b9f626e2be1cbe893639c06f3e0439ee95d7d4b1e3", + .pub_y = + "7a52a7386adda243efdf8941085c84e31239cab92b8017336748965e", + .want = + "ad09c9ae4d2324ea81bb555b200d3c003e22a6870ee03b52df49e4de", + }, + { + .nid = NID_secp224r1, + .peer_x = + "1d46b1dc3a28123cb51346e67baec56404868678faf7d0e8b2afa22a", + .peer_y = + "0ec9e65ec97e218373e7fc115c2274d5b829a60d93f71e01d58136c3", + .priv = + "3d312a9b9d8ed09140900bbac1e095527ebc9e3c6493bcf3666e3a29", + .pub_x = + "b4a0198dc8810e884425b750928b0c960c31f7a99663400b01a179df", + .pub_y = + "812b601bfc0738242c6f86f830f27acd632ca618a0b5280c9d5769f7", + .want = + "ef029c28c68064b8abd2965a38c404fb5e944ace57e8638daba9d3cd", + }, + { + .nid = NID_secp224r1, + .peer_x = + "266d038cc7a4fe21f6c976318e827b82bb5b8f7443a55298136506e0", + .peer_y = + "df123d98a7a20bbdf3943df2e3563422f8c0cf74d53aaabdd7c973ba", + .priv = + "8ce0822dc24c153995755ac350737ef506641c7d752b4f9300c612ed", + .pub_x = + "00dfc7ec137690cd6d12fdb2fd0b8c5314582108769c2b722ffb3958", + .pub_y = + "5eef3da4ba458127346bb64023868bddb7558a2ecfc813645f4ce9fe", + .want = + "f83c16661dfcbad021cc3b5a5af51d9a18db4653866b3ff90787ce3e", + }, + { + .nid = NID_secp224r1, + .peer_x = + "eb0a09f7a1c236a61f595809ec5670efd92e4598d5e613e092cdfdca", + .peer_y = + "50787ae2f2f15b88bc10f7b5f0aee1418373f16153aebd1fba54288d", + .priv = + "0ff9b485325ab77f29e7bc379fed74bfac859482da0dee7528c19db2", + .pub_x = + "7e603e6976db83c36011508fa695d1b515249e2e54b48fcbcfb90247", + .pub_y = + "0179a600ce86adfca9b1b931fa5173d618da09e841803d19b0264286", + .want = + "f51258c63f232e55a66aa25ebd597b2018d1052c02eeb63866758005", + }, + { + .nid = NID_secp224r1, + .peer_x = + "6b2f6b18a587f562ffc61bd9b0047322286986a78f1fd139b84f7c24", + .peer_y = + "7096908e4615266be59a53cd655515056ff92370a6271a5d3823d704", + .priv = + "19cf5ff6306467f28b9fe0675a43c0582552c8c12e59ce7c38f292b1", + .pub_x = + "fc20e906e609c112cfc2e0fea6303882c5db94e87e022373ab2c082a", + .pub_y = + "aecdf1daa71782bc5a26bbbd8d7e8a76490e26abc17dffc774bd7341", + .want = + "7fdc969a186ff18429f2a276dac43beea21182d82ce2e5a0876552b1", + }, + { + .nid = NID_secp224r1, + .peer_x = + "328101ba826acd75ff9f34d5574ce0dbc92f709bad8d7a33c47940c1", + .peer_y = + "df39f1ea88488c55d5538160878b9ced18a887ea261dd712d14024ff", + .priv = + "90a15368e3532c0b1e51e55d139447c2c89bc160719d697291ea7c14", + .pub_x = + "c6837d506e976da7db3ad1267c359dff2ea6fb0b7f7f8e77024c59e9", + .pub_y = + "67eb491d2fc8a530c46525d2a8b2d7c1df5fba1ae740a4649c683ee6", + .want = + "3d60ab6db2b3ffe2d29ccff46d056e54230cf34982e241556ed2920c", + }, + { + .nid = NID_secp224r1, + .peer_x = + "0081e34270871e2ebbd94183f617b4ae15f0416dd634fe6e934cf3c0", + .peer_y = + "3a1e9f38a7b90b7317d26b9f6311063ab58b268cf489b2e50386d5d6", + .priv = + "8e0838e05e1721491067e1cabc2e8051b290e2616eec427b7121897d", + .pub_x = + "e9150f770075626019e18f95473b71e6828041791d3f08d3faeeaa2b", + .pub_y = + "475f70735eaae52308a3b763dc88efe18ab590ebafa035f6e08b001c", + .want = + "9116d72786f4db5df7a8b43078c6ab9160d423513d35ea5e2559306d", + }, + { + .nid = NID_secp224r1, + .peer_x = + "2623632fdf0bd856805a69aa186d4133ef5904e1f655a972d66cce07", + .peer_y = + "2cef9728dd06fb8b50150f529b695076d4507983912585c89bd0682e", + .priv = + "38106e93f16a381adb1d72cee3da66ae462ad4bbfea9ecdf35d0814e", + .pub_x = + "7be6c4c917829ab657dd79e8637d7aefd2f81f0de7654d957e97658d", + .pub_y = + "430d22d9e8438310f61e0d43f25fa3e34585f432baad27db3021bf0d", + .want = + "207c53dcefac789aaa0276d9200b3a940ce5f2296f4cb2e81a185d3d", + }, + { + .nid = NID_secp224r1, + .peer_x = + "8ee4d1dcc31dee4bf6fe21ca8a587721d910acfb122c16c2a77a8152", + .peer_y = + "4ebf323fff04eb477069a0ac68b345f6b1ae134efc31940e513cb99f", + .priv = + "e5d1718431cf50f6cbd1bc8019fa16762dfa12c989e5999977fb4ea2", + .pub_x = + "2ea4966e7f92ed7f5cc61fde792045f63b731d6e7d0de2577f2d8ece", + .pub_y = + "1c4a7b1ede6f839162292df424be78e8176fb6f942a3c02391700f31", + .want = + "10e467da34f48ad7072005bccd6da1b2ba3f71eafa1c393842f91d74", + }, + { + .nid = NID_secp224r1, + .peer_x = + "97dcbe6d28335882a6d193cc54a1063dd0775dc328565300bb99e691", + .peer_y = + "dad11dd5ece8cfd9f97c9a526e4a1506e6355969ee87826fc38bcd24", + .priv = + "3d635691b62a9a927c633951c9369c8862bd2119d30970c2644727d6", + .pub_x = + "438bbb980517afb20be1d674e3ac2b31cef07a9b23fb8f6e38e0d6c0", + .pub_y = + "0be5f1c47d58d21b6ed28423b32f5a94750da47edcef33ea79942afd", + .want = + "82fd2f9c60c4f999ac00bbe64bfc11da8ff8cda2e499fced65230bb1", + }, + { + .nid = NID_secp224r1, + .peer_x = + "ce9126dd53972dea1de1d11efef900de34b661859c4648c5c0e534f7", + .peer_y = + "e113b6f2c1659d07f2716e64a83c18bbce344dd2121fe85168eae085", + .priv = + "acf3c85bbdc379f02f5ea36e7f0f53095a9e7046a28685a8659bf798", + .pub_x = + "ff7511215c71d796bd646e8474be4416b91684ce0d269ef6f422013b", + .pub_y = + "b7bf5e79b5a9393bb9ea42c0bdb2d3c2dc806e1a7306aa58e4fdbea5", + .want = + "530f7e7fc932613b29c981f261cb036cba3f1df3864e0e1cba2685a2", + }, + { + .nid = NID_secp224r1, + .peer_x = + "84419967d6cfad41e75a02b6da605a97949a183a97c306c4b46e66a5", + .peer_y = + "5cc9b259718b1bc8b144fde633a894616ffd59a3a6d5d8e942c7cbb7", + .priv = + "cffd62cb00a0e3163fbf2c397fadc9618210f86b4f54a675287305f0", + .pub_x = + "04bf4d948f4430d18b4ed6c96dbaf981fa11a403ed16887f06754981", + .pub_y = + "7c1326a9cef51f79d4e78303d6064b459f612584ac2fdf593d7d5d84", + .want = + "49f6fd0139248ef4df2db05d1319bd5b1489e249827a45a8a5f12427", + }, + { + .nid = NID_secp224r1, + .peer_x = + "7c9cac35768063c2827f60a7f51388f2a8f4b7f8cd736bd6bc337477", + .peer_y = + "29ee6b849c6025d577dbcc55fbd17018f4edbc2ef105b004d6257bcd", + .priv = + "85f903e43943d13c68932e710e80de52cbc0b8f1a1418ea4da079299", + .pub_x = + "970a4a7e01d4188497ceb46955eb1b842d9085819a9b925c84529d3d", + .pub_y = + "dfa2526480f833ea0edbd204e4e365fef3472888fe7d9691c3ebc09f", + .want = + "8f7e34e597ae8093b98270a74a8dfcdbed457f42f43df487c5487161", + }, + { + .nid = NID_secp224r1, + .peer_x = + "085a7642ad8e59b1a3e8726a7547afbecffdac1dab7e57230c6a9df4", + .peer_y = + "f91c36d881fe9b8047a3530713554a1af4c25c5a8e654dcdcf689f2e", + .priv = + "cce64891a3d0129fee0d4a96cfbe7ac470b85e967529057cfa31a1d9", + .pub_x = + "a6b29632db94da2125dc1cf80e03702687b2acc1122022fa2174765a", + .pub_y = + "61723edd73e10daed73775278f1958ba56f1fc9d085ebc2b64c84fe5", + .want = + "71954e2261e8510be1a060733671d2e9d0a2d012eb4e09556d697d2a", + }, + + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "700c48f77f56584c5cc632ca65640db9" + "1b6bacce3a4df6b42ce7cc838833d287", + .peer_y = + "db71e509e3fd9b060ddb20ba5c51dcc5" + "948d46fbf640dfe0441782cab85fa4ac", + .priv = + "7d7dc5f71eb29ddaf80d6214632eeae0" + "3d9058af1fb6d22ed80badb62bc1a534", + .pub_x = + "ead218590119e8876b29146ff89ca617" + "70c4edbbf97d38ce385ed281d8a6b230", + .pub_y = + "28af61281fd35e2fa7002523acc85a42" + "9cb06ee6648325389f59edfce1405141", + .want = + "46fc62106420ff012e54a434fbdd2d25" + "ccc5852060561e68040dd7778997bd7b", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "809f04289c64348c01515eb03d5ce7ac" + "1a8cb9498f5caa50197e58d43a86a7ae", + .peer_y = + "b29d84e811197f25eba8f5194092cb6f" + "f440e26d4421011372461f579271cda3", + .priv = + "38f65d6dce47676044d58ce5139582d5" + "68f64bb16098d179dbab07741dd5caf5", + .pub_x = + "119f2f047902782ab0c9e27a54aff5eb" + "9b964829ca99c06b02ddba95b0a3f6d0", + .pub_y = + "8f52b726664cac366fc98ac7a012b268" + "2cbd962e5acb544671d41b9445704d1d", + .want = + "057d636096cb80b67a8c038c890e887d" + "1adfa4195e9b3ce241c8a778c59cda67", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "a2339c12d4a03c33546de533268b4ad6" + "67debf458b464d77443636440ee7fec3", + .peer_y = + "ef48a3ab26e20220bcda2c1851076839" + "dae88eae962869a497bf73cb66faf536", + .priv = + "1accfaf1b97712b85a6f54b148985a1b" + "dc4c9bec0bd258cad4b3d603f49f32c8", + .pub_x = + "d9f2b79c172845bfdb560bbb01447ca5" + "ecc0470a09513b6126902c6b4f8d1051", + .pub_y = + "f815ef5ec32128d3487834764678702e" + "64e164ff7315185e23aff5facd96d7bc", + .want = + "2d457b78b4614132477618a5b077965e" + "c90730a8c81a1c75d6d4ec68005d67ec", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "df3989b9fa55495719b3cf46dccd28b5" + "153f7808191dd518eff0c3cff2b705ed", + .peer_y = + "422294ff46003429d739a33206c87525" + "52c8ba54a270defc06e221e0feaf6ac4", + .priv = + "207c43a79bfee03db6f4b944f53d2fb7" + "6cc49ef1c9c4d34d51b6c65c4db6932d", + .pub_x = + "24277c33f450462dcb3d4801d57b9ced" + "05188f16c28eda873258048cd1607e0d", + .pub_y = + "c4789753e2b1f63b32ff014ec42cd6a6" + "9fac81dfe6d0d6fd4af372ae27c46f88", + .want = + "96441259534b80f6aee3d287a6bb17b5" + "094dd4277d9e294f8fe73e48bf2a0024", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "41192d2813e79561e6a1d6f53c8bc1a4" + "33a199c835e141b05a74a97b0faeb922", + .peer_y = + "1af98cc45e98a7e041b01cf35f462b75" + "62281351c8ebf3ffa02e33a0722a1328", + .priv = + "59137e38152350b195c9718d39673d51" + "9838055ad908dd4757152fd8255c09bf", + .pub_x = + "a8c5fdce8b62c5ada598f141adb3b26c" + "f254c280b2857a63d2ad783a73115f6b", + .pub_y = + "806e1aafec4af80a0d786b3de45375b5" + "17a7e5b51ffb2c356537c9e6ef227d4a", + .want = + "19d44c8d63e8e8dd12c22a87b8cd4ece" + "27acdde04dbf47f7f27537a6999a8e62", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "33e82092a0f1fb38f5649d5867fba28b" + "503172b7035574bf8e5b7100a3052792", + .peer_y = + "f2cf6b601e0a05945e335550bf648d78" + "2f46186c772c0f20d3cd0d6b8ca14b2f", + .priv = + "f5f8e0174610a661277979b58ce5c90f" + "ee6c9b3bb346a90a7196255e40b132ef", + .pub_x = + "7b861dcd2844a5a8363f6b8ef8d49364" + "0f55879217189d80326aad9480dfc149", + .pub_y = + "c4675b45eeb306405f6c33c38bc69eb2" + "bdec9b75ad5af4706aab84543b9cc63a", + .want = + "664e45d5bba4ac931cd65d52017e4be9" + "b19a515f669bea4703542a2c525cd3d3", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "6a9e0c3f916e4e315c91147be571686d" + "90464e8bf981d34a90b6353bca6eeba7", + .peer_y = + "40f9bead39c2f2bcc2602f75b8a73ec7" + "bdffcbcead159d0174c6c4d3c5357f05", + .priv = + "3b589af7db03459c23068b64f63f28d3" + "c3c6bc25b5bf76ac05f35482888b5190", + .pub_x = + "9fb38e2d58ea1baf7622e96720101cae" + "3cde4ba6c1e9fa26d9b1de0899102863", + .pub_y = + "d5561b900406edf50802dd7d73e89395" + "f8aed72fba0e1d1b61fe1d22302260f0", + .want = + "ca342daa50dc09d61be7c196c85e60a8" + "0c5cb04931746820be548cdde055679d", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "a9c0acade55c2a73ead1a86fb0a97132" + "23c82475791cd0e210b046412ce224bb", + .peer_y = + "f6de0afa20e93e078467c053d241903e" + "dad734c6b403ba758c2b5ff04c9d4229", + .priv = + "d8bf929a20ea7436b2461b541a11c80e" + "61d826c0a4c9d322b31dd54e7f58b9c8", + .pub_x = + "20f07631e4a6512a89ad487c4e9d6303" + "9e579cb0d7a556cb9e661cd59c1e7fa4", + .pub_y = + "6de91846b3eee8a5ec09c2ab1f41e21b" + "d83620ccdd1bdce3ab7ea6e02dd274f5", + .want = + "35aa9b52536a461bfde4e85fc756be92" + "8c7de97923f0416c7a3ac8f88b3d4489", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "94e94f16a98255fff2b9ac0c9598aac3" + "5487b3232d3231bd93b7db7df36f9eb9", + .peer_y = + "d8049a43579cfa90b8093a94416cbefb" + "f93386f15b3f6e190b6e3455fedfe69a", + .priv = + "0f9883ba0ef32ee75ded0d8bda39a514" + "6a29f1f2507b3bd458dbea0b2bb05b4d", + .pub_x = + "abb61b423be5d6c26e21c605832c9142" + "dc1dfe5a5fff28726737936e6fbf516d", + .pub_y = + "733d2513ef58beab202090586fac91bf" + "0fee31e80ab33473ab23a2d89e58fad6", + .want = + "605c16178a9bc875dcbff54d63fe00df" + "699c03e8a888e9e94dfbab90b25f39b4", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "e099bf2a4d557460b5544430bbf6da11" + "004d127cb5d67f64ab07c94fcdf5274f", + .peer_y = + "d9c50dbe70d714edb5e221f4e020610e" + "eb6270517e688ca64fb0e98c7ef8c1c5", + .priv = + "2beedb04b05c6988f6a67500bb813faf" + "2cae0d580c9253b6339e4a3337bb6c08", + .pub_x = + "3d63e429cb5fa895a9247129bf4e48e8" + "9f35d7b11de8158efeb3e106a2a87395", + .pub_y = + "0cae9e477ef41e7c8c1064379bb7b554" + "ddcbcae79f9814281f1e50f0403c61f3", + .want = + "f96e40a1b72840854bb62bc13c40cc27" + "95e373d4e715980b261476835a092e0b", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "f75a5fe56bda34f3c1396296626ef012" + "dc07e4825838778a645c8248cff01658", + .peer_y = + "33bbdf1b1772d8059df568b061f3f112" + "2f28a8d819167c97be448e3dc3fb0c3c", + .priv = + "77c15dcf44610e41696bab758943eff1" + "409333e4d5a11bbe72c8f6c395e9f848", + .pub_x = + "ad5d13c3db508ddcd38457e5991434a2" + "51bed49cf5ddcb59cdee73865f138c9f", + .pub_y = + "62cec1e70588aa4fdfc7b9a09daa6780" + "81c04e1208b9d662b8a2214bf8e81a21", + .want = + "8388fa79c4babdca02a8e8a34f9e4355" + "4976e420a4ad273c81b26e4228e9d3a3", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "2db4540d50230756158abf61d9835712" + "b6486c74312183ccefcaef2797b7674d", + .peer_y = + "62f57f314e3f3495dc4e099012f5e0ba" + "71770f9660a1eada54104cdfde77243e", + .priv = + "42a83b985011d12303db1a800f2610f7" + "4aa71cdf19c67d54ce6c9ed951e9093e", + .pub_x = + "ab48caa61ea35f13f8ed07ffa6a13e8d" + "b224dfecfae1a7df8b1bb6ebaf0cb97d", + .pub_y = + "1274530ca2c385a3218bddfbcbf0b402" + "4c9badd5243bff834ebff24a8618dccb", + .want = + "72877cea33ccc4715038d4bcbdfe0e43" + "f42a9e2c0c3b017fc2370f4b9acbda4a", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "cd94fc9497e8990750309e9a8534fd11" + "4b0a6e54da89c4796101897041d14ecb", + .peer_y = + "c3def4b5fe04faee0a11932229fff563" + "637bfdee0e79c6deeaf449f85401c5c4", + .priv = + "ceed35507b5c93ead5989119b9ba342c" + "fe38e6e638ba6eea343a55475de2800b", + .pub_x = + "9a8cd9bd72e71752df91440f77c54750" + "9a84df98114e7de4f26cdb39234a625d", + .pub_y = + "d07cfc84c8e144fab2839f5189bb1d7c" + "88631d579bbc58012ed9a2327da52f62", + .want = + "e4e7408d85ff0e0e9c838003f28cdbd5" + "247cdce31f32f62494b70e5f1bc36307", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "15b9e467af4d290c417402e040426fe4" + "cf236bae72baa392ed89780dfccdb471", + .peer_y = + "cdf4e9170fb904302b8fd93a820ba8cc" + "7ed4efd3a6f2d6b05b80b2ff2aee4e77", + .priv = + "43e0e9d95af4dc36483cdd1968d2b7ee" + "b8611fcce77f3a4e7d059ae43e509604", + .pub_x = + "f989cf8ee956a82e7ebd9881cdbfb2fd" + "946189b08db53559bc8cfdd48071eb14", + .pub_y = + "5eff28f1a18a616b04b7d337868679f6" + "dd84f9a7b3d7b6f8af276c19611a541d", + .want = + "ed56bcf695b734142c24ecb1fc1bb64d" + "08f175eb243a31f37b3d9bb4407f3b96", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "49c503ba6c4fa605182e186b5e81113f" + "075bc11dcfd51c932fb21e951eee2fa1", + .peer_y = + "8af706ff0922d87b3f0c5e4e31d8b259" + "aeb260a9269643ed520a13bb25da5924", + .priv = + "b2f3600df3368ef8a0bb85ab22f41fc0" + "e5f4fdd54be8167a5c3cd4b08db04903", + .pub_x = + "69c627625b36a429c398b45c38677cb3" + "5d8beb1cf78a571e40e99fe4eac1cd4e", + .pub_y = + "81690112b0a88f20f7136b28d7d47e5f" + "bc2ada3c8edd87589bc19ec9590637bd", + .want = + "bc5c7055089fc9d6c89f83c1ea1ada87" + "9d9934b2ea28fcf4e4a7e984b28ad2cf", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "19b38de39fdd2f70f7091631a4f75d19" + "93740ba9429162c2a45312401636b29c", + .peer_y = + "09aed7232b28e060941741b6828bcdfa" + "2bc49cc844f3773611504f82a390a5ae", + .priv = + "4002534307f8b62a9bf67ff641ddc60f" + "ef593b17c3341239e95bdb3e579bfdc8", + .pub_x = + "5fe964671315a18aa68a2a6e3dd1fde7" + "e23b8ce7181471cfac43c99e1ae80262", + .pub_y = + "d5827be282e62c84de531b963884ba83" + "2db5d6b2c3a256f0e604fe7e6b8a7f72", + .want = + "9a4e8e657f6b0e097f47954a63c75d74" + "fcba71a30d83651e3e5a91aa7ccd8343", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "2c91c61f33adfe9311c942fdbff6ba47" + "020feff416b7bb63cec13faf9b099954", + .peer_y = + "6cab31b06419e5221fca014fb84ec870" + "622a1b12bab5ae43682aa7ea73ea08d0", + .priv = + "4dfa12defc60319021b681b3ff84a10a" + "511958c850939ed45635934ba4979147", + .pub_x = + "c9b2b8496f1440bd4a2d1e52752fd372" + "835b364885e154a7dac49295f281ec7c", + .pub_y = + "fbe6b926a8a4de26ccc83b802b121240" + "0754be25d9f3eeaf008b09870ae76321", + .want = + "3ca1fc7ad858fb1a6aba232542f3e2a7" + "49ffc7203a2374a3f3d3267f1fc97b78", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "a28a2edf58025668f724aaf83a50956b" + "7ac1cfbbff79b08c3bf87dfd2828d767", + .peer_y = + "dfa7bfffd4c766b86abeaf5c99b6e50c" + "b9ccc9d9d00b7ffc7804b0491b67bc03", + .priv = + "1331f6d874a4ed3bc4a2c6e9c74331d3" + "039796314beee3b7152fcdba5556304e", + .pub_x = + "59e1e101521046ad9cf1d082e9d2ec7d" + "d22530cce064991f1e55c5bcf5fcb591", + .pub_y = + "482f4f673176c8fdaa0bb6e59b15a3e4" + "7454e3a04297d3863c9338d98add1f37", + .want = + "1aaabe7ee6e4a6fa732291202433a237" + "df1b49bc53866bfbe00db96a0f58224f", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "a2ef857a081f9d6eb206a81c4cf78a80" + "2bdf598ae380c8886ecd85fdc1ed7644", + .peer_y = + "563c4c20419f07bc17d0539fade1855e" + "34839515b892c0f5d26561f97fa04d1a", + .priv = + "dd5e9f70ae740073ca0204df60763fb6" + "036c45709bf4a7bb4e671412fad65da3", + .pub_x = + "30b9db2e2e977bcdc98cb87dd736cbd8" + "e78552121925cf16e1933657c2fb2314", + .pub_y = + "6a45028800b81291bce5c2e1fed7ded6" + "50620ebbe6050c6f3a7f0dfb4673ab5c", + .want = + "430e6a4fba4449d700d2733e557f66a3" + "bf3d50517c1271b1ddae1161b7ac798c", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "ccd8a2d86bc92f2e01bce4d6922cf7fe" + "1626aed044685e95e2eebd464505f01f", + .peer_y = + "e9ddd583a9635a667777d5b8a8f31b0f" + "79eba12c75023410b54b8567dddc0f38", + .priv = + "5ae026cfc060d55600717e55b8a12e11" + "6d1d0df34af831979057607c2d9c2f76", + .pub_x = + "46c9ebd1a4a3c8c0b6d572b5dcfba124" + "67603208a9cb5d2acfbb733c40cf6391", + .pub_y = + "46c913a27d044185d38b467ace011e04" + "d4d9bbbb8cb9ae25fa92aaf15a595e86", + .want = + "1ce9e6740529499f98d1f1d71329147a" + "33df1d05e4765b539b11cf615d6974d3", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "c188ffc8947f7301fb7b53e36746097c" + "2134bf9cc981ba74b4e9c4361f595e4e", + .peer_y = + "bf7d2f2056e72421ef393f0c0f2b0e00" + "130e3cac4abbcc00286168e85ec55051", + .priv = + "b601ac425d5dbf9e1735c5e2d5bdb79c" + "a98b3d5be4a2cfd6f2273f150e064d9d", + .pub_x = + "7c9e950841d26c8dde8994398b8f5d47" + "5a022bc63de7773fcf8d552e01f1ba0a", + .pub_y = + "cc42b9885c9b3bee0f8d8c57d3a8f635" + "5016c019c4062fa22cff2f209b5cc2e1", + .want = + "4690e3743c07d643f1bc183636ab2a9c" + "b936a60a802113c49bb1b3f2d0661660", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "317e1020ff53fccef18bf47bb7f2dd77" + "07fb7b7a7578e04f35b3beed222a0eb6", + .peer_y = + "09420ce5a19d77c6fe1ee587e6a49fba" + "f8f280e8df033d75403302e5a27db2ae", + .priv = + "fefb1dda1845312b5fce6b81b2be205a" + "f2f3a274f5a212f66c0d9fc33d7ae535", + .pub_x = + "38b54db85500cb20c61056edd3d88b6a" + "9dc26780a047f213a6e1b900f76596eb", + .pub_y = + "6387e4e5781571e4eb8ae62991a33b5d" + "c33301c5bc7e125d53794a39160d8fd0", + .want = + "30c2261bd0004e61feda2c16aa5e21ff" + "a8d7e7f7dbf6ec379a43b48e4b36aeb0", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "45fb02b2ceb9d7c79d9c2fa93e9c7967" + "c2fa4df5789f9640b24264b1e524fcb1", + .peer_y = + "5c6e8ecf1f7d3023893b7b1ca1e4d178" + "972ee2a230757ddc564ffe37f5c5a321", + .priv = + "334ae0c4693d23935a7e8e043ebbde21" + "e168a7cba3fa507c9be41d7681e049ce", + .pub_x = + "3f2bf1589abf3047bf3e54ac9a95379b" + "ff95f8f55405f64eca36a7eebe8ffca7", + .pub_y = + "5212a94e66c5ae9a8991872f66a72723" + "d80ec5b2e925745c456f5371943b3a06", + .want = + "2adae4a138a239dcd93c243a3803c3e4" + "cf96e37fe14e6a9b717be9599959b11c", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "a19ef7bff98ada781842fbfc51a47aff" + "39b5935a1c7d9625c8d323d511c92de6", + .peer_y = + "e9c184df75c955e02e02e400ffe45f78" + "f339e1afe6d056fb3245f4700ce606ef", + .priv = + "2c4bde40214fcc3bfc47d4cf434b629a" + "cbe9157f8fd0282540331de7942cf09d", + .pub_x = + "29c0807f10cbc42fb45c9989da50681e" + "ead716daa7b9e91fd32e062f5eb92ca0", + .pub_y = + "ff1d6d1955d7376b2da24fe1163a2716" + "59136341bc2eb1195fc706dc62e7f34d", + .want = + "2e277ec30f5ea07d6ce513149b9479b9" + "6e07f4b6913b1b5c11305c1444a1bc0b", + }, + { + .nid = NID_X9_62_prime256v1, + .peer_x = + "356c5a444c049a52fee0adeb7e5d82ae" + "5aa83030bfff31bbf8ce2096cf161c4b", + .peer_y = + "57d128de8b2a57a094d1a001e572173f" + "96e8866ae352bf29cddaf92fc85b2f92", + .priv = + "85a268f9d7772f990c36b42b0a331adc" + "92b5941de0b862d5d89a347cbf8faab0", + .pub_x = + "9cf4b98581ca1779453cc816ff28b410" + "0af56cf1bf2e5bc312d83b6b1b21d333", + .pub_y = + "7a5504fcac5231a0d12d658218284868" + "229c844a04a3450d6c7381abe080bf3b", + .want = + "1e51373bd2c6044c129c436e742a55be" + "2a668a85ae08441b6756445df5493857", + }, + + { + .nid = NID_secp384r1, + .peer_x = + "a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e76459" + "2efda27fe7513272734466b400091adbf2d68c58e0c50066", + .peer_y = + "ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b66" + "1efedf243451915ed0905a32b060992b468c64766fc8437a", + .priv = + "3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b1" + "5618b6818a661774ad463b205da88cf699ab4d43c9cf98a1", + .pub_x = + "9803807f2f6d2fd966cdd0290bd410c0190352fbec7ff624" + "7de1302df86f25d34fe4a97bef60cff548355c015dbb3e5f", + .pub_y = + "ba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2" + "af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99", + .want = + "5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f4" + "0ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1", + }, + { + .nid = NID_secp384r1, + .peer_x = + "30f43fcf2b6b00de53f624f1543090681839717d53c7c955" + "d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0", + .peer_y = + "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c" + "860857a68153ab62e525ec0530d81b5aa15897981e858757", + .priv = + "92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8" + "b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783", + .pub_x = + "ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66" + "fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b66", + .pub_y = + "68835a91484f05ef028284df6436fb88ffebabcdd69ab013" + "3e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6", + .want = + "a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd50" + "1a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff", + }, + { + .nid = NID_secp384r1, + .peer_x = + "1aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7c" + "c906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180", + .peer_y = + "419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b63" + "97b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3", + .priv = + "12cf6a223a72352543830f3f18530d5cb37f26880a0b2944" + "82c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853", + .pub_x = + "fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901" + "b0b59d6ac81baad316a242ba32bde85cb248119b852fab66", + .pub_y = + "972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3" + "ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b", + .want = + "3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d" + "15b111b6773223da3c3489121db173d414b5bd5ad7153435", + }, + { + .nid = NID_secp384r1, + .peer_x = + "8bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c" + "83d4de3a5607037ec397683f8cef07eab2fe357eae36c449", + .peer_y = + "d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693" + "526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7", + .priv = + "8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1" + "600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1", + .pub_x = + "e38c9846248123c3421861ea4d32669a7b5c3c08376ad281" + "04399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3c", + .pub_y = + "9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cb" + "f75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce", + .want = + "6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d0" + "2a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854", + }, + { + .nid = NID_secp384r1, + .peer_x = + "eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3" + "b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b0", + .peer_y = + "f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058" + "a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1", + .priv = + "84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c180" + "85fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f", + .pub_x = + "3222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0" + "d164b84bce71c431705cb9aea9a45f5d73806655a058bee3", + .pub_y = + "e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9" + "cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6", + .want = + "ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e" + "069214818613447df8c611de66da200db7c375cf913e4405", + }, + { + .nid = NID_secp384r1, + .peer_x = + "441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022a" + "ff058b3695d0b8c814cc88da6285dc6df1ac55c553885003", + .peer_y = + "e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd" + "9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345", + .priv = + "68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd177095" + "1451c3484cdb77cb136d00e731260597cc2859601c01a25b", + .pub_x = + "868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf" + "523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb3b", + .pub_y = + "9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e" + "0773b1bc71d3a219f05b8116074658ee86b52e36f3897116", + .want = + "ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01c" + "a381f45370e486fe87f9f419b150c61e329a286d1aa265ec", + }, + { + .nid = NID_secp384r1, + .peer_x = + "3d4e6bf08a73404accc1629873468e4269e82d90d832e58a" + "d72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2f", + .peer_y = + "9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc" + "0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71", + .priv = + "b1764c54897e7aae6de9e7751f2f37de849291f88f0f9109" + "3155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd", + .pub_x = + "c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f9" + "1ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae", + .pub_y = + "047d6b4d765123563f81116bc665b7b8cc6207830d805fd8" + "4da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662", + .want = + "1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61" + "964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b", + }, + { + .nid = NID_secp384r1, + .peer_x = + "f5f6bef1d110da03be0017eac760cc34b24d092f736f237b" + "c7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d", + .peer_y = + "06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb919" + "20d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5", + .priv = + "f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50" + "e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82", + .pub_x = + "99c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d" + "94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69eab", + .pub_y = + "5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f90" + "0fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0", + .want = + "d06a568bf2336b90cbac325161be7695eacb2295f599500d" + "787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0", + }, + { + .nid = NID_secp384r1, + .peer_x = + "7cdec77e0737ea37c67b89b7137fe38818010f4464438ee4" + "d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a67", + .peer_y = + "28c42ee8d6027c56cf979ba4c229fdb01d234944f8ac4336" + "50112c3cf0f02844e888a3569dfef7828a8a884589aa055e", + .priv = + "9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000" + "941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2", + .pub_x = + "4c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bc" + "cedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd92", + .pub_y = + "d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f77" + "93ff5d271925d13a41f8e52409f4eba1990f33acb0bac669", + .want = + "bb3b1eda9c6560d82ff5bee403339f1e80342338a9913448" + "53b56b24f109a4d94b92f654f0425edd4c205903d7586104", + }, + { + .nid = NID_secp384r1, + .peer_x = + "8eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc5" + "87a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1ba", + .peer_y = + "73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee8" + "57f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e", + .priv = + "d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90" + "893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018", + .pub_x = + "171546923b87b2cbbad664f01ce932bf09d6a61181686784" + "46bfa9f0938608cb4667a98f4ec8ac1462285c2508f74862", + .pub_y = + "fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2" + "a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf", + .want = + "1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d" + "8672a8206bfdcf0a106b8768f983258c74167422e44e4d14", + }, + { + .nid = NID_secp384r1, + .peer_x = + "a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6" + "cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f", + .peer_y = + "14ba6e26355109ad35129366d5e3a640ae798505a7fa55a9" + "6a36b5dad33de00474f6670f522214dd7952140ab0a7eb68", + .priv = + "83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e" + "834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b", + .pub_x = + "57cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae" + "1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c63", + .pub_y = + "7ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c4742" + "27c5bda88637a4f26c64817929af999592da6f787490332f", + .want = + "1023478840e54775bfc69293a3cf97f5bc914726455c6653" + "8eb5623e218feef7df4befa23e09d77145ad577db32b41f9", + }, + { + .nid = NID_secp384r1, + .peer_x = + "d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba" + "1738286b45827561e7da37b880276c656cfc38b32ade847e", + .peer_y = + "34b314bdc134575654573cffaf40445da2e6aaf987f7e913" + "cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c", + .priv = + "8f558e05818b88ed383d5fca962e53413db1a0e4637eda19" + "4f761944cbea114ab9d5da175a7d57882550b0e432f395a9", + .pub_x = + "9a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd" + "7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60ba", + .pub_y = + "d9b94ee82da9cc601f346044998ba387aee56404dc6ecc8a" + "b2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9", + .want = + "6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbf" + "f8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954", + }, + { + .nid = NID_secp384r1, + .peer_x = + "815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e" + "9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f", + .peer_y = + "e79269948b2611484560fd490feec887cb55ef99a4b52488" + "0fa7499d6a07283aae2afa33feab97deca40bc606c4d8764", + .priv = + "0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d" + "3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb", + .pub_x = + "23346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8b" + "c75f3b23681ebe614d0597dd614fae58677c835a9f0b273b", + .pub_y = + "82ba36290d2f94db41479eb45ab4eaf67928a2315138d59e" + "ecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf", + .want = + "cc9e063566d46b357b3fcae21827377331e5e290a36e60cd" + "7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437", + }, + { + .nid = NID_secp384r1, + .peer_x = + "1c0eeda7a2be000c5bdcda0478aed4db733d2a9e34122437" + "9123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3b", + .peer_y = + "ec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f1" + "4b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456", + .priv = + "037b633b5b8ba857c0fc85656868232e2febf59578718391" + "b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4", + .pub_x = + "8878ac8a947f7d5cb2b47aad24fbb8210d86126585399a28" + "71f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc74", + .pub_y = + "632f5cd2f900c2711c32f8930728eb647d31edd8d650f965" + "4e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37", + .want = + "deff7f03bd09865baf945e73edff6d5122c03fb561db87de" + "c8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9", + }, + { + .nid = NID_secp384r1, + .peer_x = + "c95c185e256bf997f30b311548ae7f768a38dee43eeeef43" + "083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1a", + .peer_y = + "3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a524" + "4550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5", + .priv = + "e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb" + "2e37b4ac47f429a637d06a67d2fba33838764ef203464991", + .pub_x = + "e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9" + "d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb18", + .pub_y = + "1773ee591822f7abaa856a1a60bc0a5203548dbd1cb50254" + "66eff8481bd07614eaa04a16c3db76905913e972a5b6b59d", + .want = + "c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4" + "e461948329d3923b969e5db663675623611a457fcda35a71", + }, + { + .nid = NID_secp384r1, + .peer_x = + "3497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631e" + "b3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a", + .peer_y = + "a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d40" + "4d7765183195aed3f913641b90c81a306ebf0d8913861316", + .priv = + "f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218" + "f2da62333f99905117b141c760e8974efc4af10570635791", + .pub_x = + "a4ad77aa7d86e5361118a6b921710c820721210712f4c347" + "985fdee58aa4effa1e28be80a17b120b139f96300f89b49b", + .pub_y = + "1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130" + "c1b57ebb95982496524f31d3797793396fa823f22bdb4328", + .want = + "d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d" + "49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e", + }, + { + .nid = NID_secp384r1, + .peer_x = + "90a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944" + "ffa6573c6df4f41dec0d11b697abd934d390871d4b453240", + .peer_y = + "9b590719bb3307c149a7817be355d684893a307764b512ee" + "ffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e", + .priv = + "59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a" + "6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664", + .pub_x = + "9c43bf971edf09402876ee742095381f78b1bd3aa39b5132" + "af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b0", + .pub_y = + "a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46e" + "b4e53e250597942351a99665a122ffea9bde0636c375daf2", + .want = + "32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e368" + "75f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1", + }, + { + .nid = NID_secp384r1, + .peer_x = + "dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07" + "aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1d", + .peer_y = + "15bbb2597913035faadf413476f4c70f7279769a40c986f4" + "70c427b4ee4962abdf8173bbad81874772925fd32f0b159f", + .priv = + "3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998" + "da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded", + .pub_x = + "5a949594228b1a3d6f599eb3db0d06070fbc551c657b5823" + "4ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3d", + .pub_y = + "2baad447c8c290cfed25edd9031c41d0b76921457327f42d" + "b31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8", + .want = + "1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41" + "dca71e475646fd489615979ca92fb4389aeadefde79a24f1", + }, + { + .nid = NID_secp384r1, + .peer_x = + "788be2336c52f4454d63ee944b1e49bfb619a08371048e6d" + "a92e584eae70bde1f171c4df378bd1f3c0ab03048a237802", + .peer_y = + "4673ebd8db604eaf41711748bab2968a23ca4476ce144e72" + "8247f08af752929157b5830f1e26067466bdfa8b65145a33", + .priv = + "50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd4" + "40a6deea04e37a07c6e72791c190ad4e4e86e01efba84269", + .pub_x = + "756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c" + "38d223f22a3a9095a8d564653af528e04c7e1824be4a6512", + .pub_y = + "17c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f" + "70b4e461419b2972ce68ad46127fdda6c39195774ea86df3", + .want = + "793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd" + "2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb", + }, + { + .nid = NID_secp384r1, + .peer_x = + "d09bb822eb99e38060954747c82bb3278cf96bbf36fece34" + "00f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf26", + .peer_y = + "d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608" + "df512037584f213a648d47f16ac326e19aae972f63fd76c9", + .priv = + "06f132b71f74d87bf99857e1e4350a594e5fe35533b88855" + "2ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064", + .pub_x = + "2a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f" + "4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459e", + .pub_y = + "bf9985960176da6d23c7452a2954ffcbbcb24249b43019a2" + "a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3", + .want = + "012d191cf7404a523678c6fc075de8285b243720a9030477" + "08bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8", + }, + { + .nid = NID_secp384r1, + .peer_x = + "13741262ede5861dad71063dfd204b91ea1d3b7c631df68e" + "b949969527d79a1dc59295ef7d2bca6743e8cd77b04d1b58", + .peer_y = + "0baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bf" + "df201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586", + .priv = + "12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846" + "fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241", + .pub_x = + "bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180" + "511cbfdd49cce377c39e34c031b5240dc9980503ed2f262c", + .pub_y = + "8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552" + "ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6", + .want = + "ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e9670" + "85eea45f0cd959f20f18f522763e28bcc925e496a52dda98", + }, + { + .nid = NID_secp384r1, + .peer_x = + "9e22cbc18657f516a864b37b783348b66f1aa9626cd631f4" + "fa1bd32ad88cf11db52057c660860d39d11fbf024fabd444", + .peer_y = + "6b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198" + "cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f", + .priv = + "34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850" + "c8104029f7d48449714b9884328cae189978754ab460b486", + .pub_x = + "867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d" + "1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462fc", + .pub_y = + "9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e" + "9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863", + .want = + "dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394" + "b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95", + }, + { + .nid = NID_secp384r1, + .peer_x = + "2db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52d" + "f15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5dc0", + .peer_y = + "22e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbb" + "ac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989", + .priv = + "dc60fa8736d702135ff16aab992bb88eac397f5972456c72" + "ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c", + .pub_x = + "b69beede85d0f829fec1b893ccb9c3e052ff692e13b97453" + "7bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf908914", + .pub_y = + "66f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fe" + "e647b59897b619f20eed95a632e6a4206bf7da429c04c560", + .want = + "d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519" + "e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347", + }, + { + .nid = NID_secp384r1, + .peer_x = + "329647baa354224eb4414829c5368c82d7893b39804e08cb" + "b2180f459befc4b347a389a70c91a23bd9d30c83be5295d3", + .peer_y = + "cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b756" + "60ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12", + .priv = + "6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89" + "772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce", + .pub_x = + "53de1fc1328e8de14aecab29ad8a40d6b13768f86f7d2984" + "33d20fec791f86f8bc73f358098b256a298bb488de257bf4", + .pub_y = + "ac28944fd27f17b82946c04c66c41f0053d3692f275da55c" + "d8739a95bd8cd3af2f96e4de959ea8344d8945375905858b", + .want = + "d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335" + "aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2", + }, + { + .nid = NID_secp384r1, + .peer_x = + "29d8a36d22200a75b7aea1bb47cdfcb1b7fd66de96704143" + "4728ab5d533a060df732130600fe6f75852a871fb2938e39", + .peer_y = + "e19b53db528395de897a45108967715eb8cb55c3fcbf2337" + "9372c0873a058d57544b102ecce722b2ccabb1a603774fd5", + .priv = + "74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110c" + "a302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8", + .pub_x = + "27a3e83cfb9d5122e73129d801615857da7cc089cccc9c54" + "ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd691063", + .pub_y = + "8d60e44aa5e0fd30c918456796af37f0e41957901645e5c5" + "96c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e", + .want = + "81e1e71575bb4505498de097350186430a6242fa6c57b85a" + "5f984a23371123d2d1424eefbf804258392bc723e4ef1e35", + }, + + { + .nid = NID_secp521r1, + .peer_x = + "000000685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5d" + "a4f4370f3a9490340854334b1e1b87fa395464c60626124a" + "4e70d0f785601d37c09870ebf176666877a2046d", + .peer_y = + "000001ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05" + "400697942e80b739884a83bde99e0f6716939e632bc8986f" + "a18dccd443a348b6c3e522497955a4f3c302f676", + .priv = + "0000017eecc07ab4b329068fba65e56a1f8890aa935e5713" + "4ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefe" + "e5743ae2241bfeb95d5ce31ddcb6f9edb4d6fc47", + .pub_x = + "000000602f9d0cf9e526b29e22381c203c48a886c2b06730" + "33366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed3" + "4275eb01c8467d05ca80315bf1a7bbd945f550a5", + .pub_y = + "000001b7c85f26f5d4b2d7355cf6b02117659943762b6d1d" + "b5ab4f1dbc44ce7b2946eb6c7de342962893fd387d1b73d7" + "a8672d1f236961170b7eb3579953ee5cdc88cd2d", + .want = + "005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc" + "5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0" + "ad9759436a4d3c5bf6e74b9578fac148c831", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001df277c152108349bc34d539ee0cf06b24f5d350067" + "7b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51" + "b3ab7f316aa5e74a951c5e53f74cd95fc29aee7a", + .peer_y = + "0000013d52f33a9f3c14384d1587fa8abe7aed74bc33749a" + "d9c570b471776422c7d4505d9b0a96b3bfac041e4c6a6990" + "ae7f700e5b4a6640229112deafa0cd8bb0d089b0", + .priv = + "000000816f19c1fb10ef94d4a1d81c156ec3d1de08b66761" + "f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14" + "d74cc872f95d05d07ad50f621ceb620cd905cfb8", + .pub_x = + "000000d45615ed5d37fde699610a62cd43ba76bedd8f85ed" + "31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9" + "f4671105309ec9b6879d0551d930dac8ba45d255", + .pub_y = + "000001425332844e592b440c0027972ad1526431c06732df" + "19cd46a242172d4dd67c2c8c99dfc22e49949a56cf90c647" + "3635ce82f25b33682fb19bc33bd910ed8ce3a7fa", + .want = + "000b3920ac830ade812c8f96805da2236e002acbbf13596a" + "9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032" + "c26d42189273ca4efa4c3db6bd12a6853759", + }, + { + .nid = NID_secp521r1, + .peer_x = + "00000092db3142564d27a5f0006f819908fba1b85038a5bc" + "2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019" + "204b471cd88024f82115d8149cc0cf4f7ce1a4d5", + .peer_y = + "0000016bad0623f517b158d9881841d2571efbad63f85cbe" + "2e581960c5d670601a6760272675a548996217e4ab2b8ebc" + "e31d71fca63fcc3c08e91c1d8edd91cf6fe845f8", + .priv = + "0000012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feea" + "f8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443" + "bc1b141caf8afb3a71f97f57c225c03e1e4d42b0", + .pub_x = + "000000717fcb3d4a40d103871ede044dc803db508aaa4ae7" + "4b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4" + "f9343636c531a4fac68a35a93665546b9a878679", + .pub_y = + "000000f3d96a8637036993ab5d244500fff9d2772112826f" + "6436603d3eb234a44d5c4e5c577234679c4f9df725ee5b91" + "18f23d8a58d0cc01096daf70e8dfec0128bdc2e8", + .want = + "006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f" + "2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf" + "746a10a3ad694daae00d980d944aabc6a08f", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000000fdd40d9e9d974027cb3bae682162eac1328ad61bc4" + "353c45bf5afe76bf607d2894c8cce23695d920f2464fda47" + "73d4693be4b3773584691bdb0329b7f4c86cc299", + .peer_y = + "00000034ceac6a3fef1c3e1c494bfe8d872b183832219a7e" + "14da414d4e3474573671ec19b033be831b915435905925b4" + "4947c592959945b4eb7c951c3b9c8cf52530ba23", + .priv = + "000000e548a79d8b05f923b9825d11b656f222e8cb98b0f8" + "9de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a9" + "81e1a3e78bdebb97d7c204b9261b4ef92e0918e0", + .pub_x = + "0000000ce800217ed243dd10a79ad73df578aa8a3f9194af" + "528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab" + "3aa806d9020cbaa2ed72b7fecdc5a09a6dad6f32", + .pub_y = + "000001543c9ab45b12469232918e21d5a351f9a4b9cbf9ef" + "b2afcc402fa9b31650bec2d641a05c440d35331c0893d11f" + "b13151335988b303341301a73dc5f61d574e67d9", + .want = + "00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd" + "8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336" + "823b19e98bf1cec05e4beffb0591f97713c6", + }, + { + .nid = NID_secp521r1, + .peer_x = + "00000098d99dee0816550e84dbfced7e88137fddcf581a72" + "5a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973" + "cdceaca205da39e0bd98c8062536c47f258f44b5", + .peer_y = + "000000cd225c8797371be0c4297d2b457740100c774141d8" + "f214c23b61aa2b6cd4806b9b70722aa4965fb622f42b7391" + "e27e5ec21c5679c5b06b59127372997d421adc1e", + .priv = + "000001c8aae94bb10b8ca4f7be577b4fb32bb2381032c494" + "2c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef" + "9f23545f72c5602140046839e963313c3decc864", + .pub_x = + "00000106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b" + "75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3" + "378df4dc760cd14d62be700779dd1a4377943656", + .pub_y = + "0000002366ce3941e0b284b1aa81215d0d3b9778fce23c8c" + "d1e4ed6fa0abf62156c91d4b3eb55999c3471bed275e9e60" + "e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74", + .want = + "0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa5" + "1971eff442808a23b4e23c187e639ff928c3725fbd1c0c2a" + "d0d4aeb207bc1a6fb6cb6d467888dc044b3c", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000007ae115adaaf041691ab6b7fb8c921f99d8ed32d283" + "d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b" + "6f93406119f40e32b5773ed25a28a9a85c4a7588", + .peer_y = + "000001a28e004e37eeaefe1f4dbb71f1878696141af3a10a" + "9691c4ed93487214643b761fa4b0fbeeb247cf6d3fba7a60" + "697536ad03f49b80a9d1cb079673654977c5fa94", + .priv = + "0000009b0af137c9696c75b7e6df7b73156bb2d45f482e5a" + "4217324f478b10ceb76af09724cf86afa316e7f89918d31d" + "54824a5c33107a483c15c15b96edc661340b1c0e", + .pub_x = + "000000748cdbb875d35f4bccb62abe20e82d32e4c14dc2fe" + "b5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92f" + "cf53cdbbae2a404c0babd564ad7adeac6273efa3", + .pub_y = + "000001984acab8d8f173323de0bb60274b228871609373bb" + "22a17287e9dec7495873abc09a8915b54c8455c8e02f654f" + "602e23a2bbd7a9ebb74f3009bd65ecc650814cc0", + .want = + "005c5721e96c273319fd60ecc46b5962f698e974b429f28f" + "e6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8" + "d861016b6ad0c79805784c67f73ada96f351", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000012588115e6f7f7bdcfdf57f03b169b479758baafdaf" + "569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe" + "90620f38b5535c6d2260c173e61eb888ca920203", + .peer_y = + "000001542c169cf97c2596fe2ddd848a222e367c5f7e6267" + "ebc1bcd9ab5dcf49158f1a48e4af29a897b7e6a82091c2db" + "874d8e7abf0f58064691344154f396dbaed188b6", + .priv = + "000001e48faacee6dec83ffcde944cf6bdf4ce4bae727478" + "88ebafee455b1e91584971efb49127976a52f4142952f7c2" + "07ec0265f2b718cf3ead96ea4f62c752e4f7acd3", + .pub_x = + "0000010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea6" + "1c00391dc766c76ed9fa608449377d1e4fadd12360254173" + "30b4b91086704ace3e4e6484c606e2a943478c86", + .pub_y = + "00000149413864069825ee1d0828da9f4a97713005e9bd1a" + "dbc3b38c5b946900721a960fe96ad2c1b3a44fe3de915613" + "6d44cb17cbc2415729bb782e16bfe2deb3069e43", + .want = + "01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c0" + "6ff3f66a3be15ceec6e65e308347593f00d7f33591da4043" + "c30763d72749f72cdceebe825e4b34ecd570", + }, + { + .nid = NID_secp521r1, + .peer_x = + "00000169491d55bd09049fdf4c2a53a660480fee4c03a053" + "8675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39c" + "e0e6b890a163c50f9645b3d21d1cbb3b60a6fff4", + .peer_y = + "00000083494b2eba76910fed33c761804515011fab50e3b3" + "77abd8a8a045d886d2238d2c268ac1b6ec88bd71b7ba78e2" + "c33c152e4bf7da5d565e4acbecf5e92c7ad662bb", + .priv = + "000000c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98" + "c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef3" + "1b758859556eb3e0e042d8dd6aaac57a05ca61e3", + .pub_x = + "0000001511c848ef60d5419a98d10204db0fe58224124370" + "061bcfa4e9249d50618c56bf3722471b259f38263bb7b280" + "d23caf2a1ee8737f9371cdb2732cdc958369930c", + .pub_y = + "000001d461681ae6d8c49b4c5f4d6016143fb1bd7491573e" + "3ed0e6c48b82e821644f87f82f0e5f08fd16f1f98fa17586" + "200ab02ed8c627b35c3f27617ec5fd92f456203f", + .want = + "018f2ae9476c771726a77780208dedfefa205488996b18fe" + "cc50bfd4c132753f5766b2cd744afa9918606de2e016effc" + "63622e9029e76dc6e3f0c69f7aeced565c2c", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6b" + "a101860ae45d3c60e1e0e3f7247a4626a60fdd404965c356" + "6c79f6449e856ce0bf94619f97da8da24bd2cfb6", + .peer_y = + "000000fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b" + "03c24d42dc50f74a8c465a0afc4683f10fab84652dfe9e92" + "8c2626b5456453e1573ff60be1507467d431fbb2", + .priv = + "00000028692be2bf5c4b48939846fb3d5bce74654bb2646e" + "15f8389e23708a1afadf561511ea0d9957d0b53453819d60" + "fba8f65a18f7b29df021b1bb01cd163293acc3cc", + .pub_x = + "000001cfdc10c799f5c79cb6930a65fba351748e07567993" + "e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190a" + "c812b9245f48a7973b658daf408822fe5b85f668", + .pub_y = + "00000180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b" + "2cce30388301b51cecbe3276307ef439b5c9e6a72dc2d94d" + "879bc395052dbb4a5787d06efb280210fb8be037", + .want = + "0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd1" + "9dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d" + "92536d6aa544dc7537a00c858f8b66319e25", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001c721eea805a5cba29f34ba5758775be0cf6160e6c0" + "8723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2b" + "f6845debd5a869f124ebfa7aa72fe565050b7f18", + .peer_y = + "000000b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1" + "a9bfd3fe8f22841b26763265f074c4ccf2d634ae97b70195" + "6f67a11006c52d97197d92f585f5748bc2672eeb", + .priv = + "000001194d1ee613f5366cbc44b504d21a0cf6715e209cd3" + "58f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a8" + "6bacffc819f1edf1b8c727ccfb3047240a57c435", + .pub_x = + "0000016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11" + "d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeed" + "df75a93c130191c84108042ea2fca17fd3f80d14", + .pub_y = + "000001560502d04b74fce1743aab477a9d1eac93e5226981" + "fdb97a7478ce4ce566ff7243931284fad850b0c2bcae0ddd" + "2d97790160c1a2e77c3ed6c95ecc44b89e2637fc", + .want = + "004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d" + "6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d" + "6af7a7f8c7befb611afe487ff032921f750f", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001c35823e440a9363ab98d9fc7a7bc0c0532dc7977a7" + "9165599bf1a9cc64c00fb387b42cca365286e8430360bfad" + "3643bc31354eda50dc936c329ecdb60905c40fcb", + .peer_y = + "000000d9e7f433531e44df4f6d514201cbaabb06badd6783" + "e01111726d815531d233c5cdb722893ffbb2027259d594de" + "77438809738120c6f783934f926c3fb69b40c409", + .priv = + "000001fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5b" + "d54b5b14aee2ed6723dde5181f5085b68169b09fbec72137" + "2ccf6b284713f9a6356b8d560a8ff78ca3737c88", + .pub_x = + "000001ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4" + "d384c31b8d6288d8071517acade9b39796c7af5163bcf71a" + "eda777533f382c6cf0a4d9bbb938c85f44b78037", + .pub_y = + "0000016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9" + "b2951333535e5748baa34a99f61ff4d5f812079e0f01e877" + "89f34efdad8098015ee74a4f846dd190d16dc6e1", + .want = + "0100c8935969077bae0ba89ef0df8161d975ec5870ac811a" + "e7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000" + "b0594baa82ef8f244e6984ae87ae1ed124b7", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000000093057fb862f2ad2e82e581baeb3324e7b32946f2b" + "a845a9beeed87d6995f54918ec6619b9931955d5a89d4d74" + "adf1046bb362192f2ef6bd3e3d2d04dd1f87054a", + .peer_y = + "000000aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa8" + "02d7262f19983c44674fe15327acaac1fa40424c395a6556" + "cb8167312527fae5865ecffc14bbdc17da78cdcf", + .priv = + "0000009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3" + "753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9" + "a0703aecf6c42799c245011064f530c09db98369", + .pub_x = + "000000234e32be0a907131d2d128a6477e0caceb86f02479" + "745e0fe245cb332de631c078871160482eeef584e274df7f" + "a412cea3e1e91f71ecba8781d9205d48386341ad", + .pub_y = + "000001cf86455b09b1c005cffba8d76289a3759628c874be" + "ea462f51f30bd581e3803134307dedbb771b3334ee15be2e" + "242cd79c3407d2f58935456c6941dd9b6d155a46", + .want = + "017f36af19303841d13a389d95ec0b801c7f9a679a823146" + "c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c" + "2946c4b8abd1d56d620fab1b5ff1a3adc71f", + }, + { + .nid = NID_secp521r1, + .peer_x = + "00000083192ed0b1cb31f75817794937f66ad91cf74552cd" + "510cedb9fd641310422af5d09f221cad249ee814d16dd7ac" + "84ded9eacdc28340fcfc9c0c06abe30a2fc28cd8", + .peer_y = + "0000002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f" + "2852d0928c48930e875cc7b428d0e7f3f4d503e5d60c68cb" + "49b13c2480cd486bed9200caddaddfe4ff8e3562", + .priv = + "000001b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fd" + "fd64b539ba48c25926926bd5e332b45649c0b184f77255e9" + "d58fe8afa1a6d968e2cb1d4637777120c765c128", + .pub_x = + "000001de3dc9263bc8c4969dc684be0eec54befd9a9f3dba" + "194d8658a789341bf0d78d84da6735227cafaf0935195169" + "1197573c8c360a11e5285712b8bbdf5ac91b977c", + .pub_y = + "000000812de58cd095ec2e5a9b247eb3ed41d8bef6aeace1" + "94a7a05b65aa5d289fbc9b1770ec84bb6be0c2c64cc37c1d" + "54a7f5d71377a9adbe20f26f6f2b544a821ea831", + .want = + "00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa54" + "6b00ebe87a7260bf724be20d34b9d02076655c933d056b21" + "e304c24ddb1dedf1dd76de611fc4a2340336", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001a89b636a93e5d2ba6c2292bf23033a84f06a3ac122" + "0ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30" + "212bf7aae7fdf6d376c212f0554e656463ffab7e", + .peer_y = + "00000182efcaf70fc412d336602e014da47256a0b606f2ad" + "dcce8053bf817ac8656bb4e42f14c8cbf2a68f488ab35dcd" + "f64056271dee1f606a440ba4bd4e5a11b8b8e54f", + .priv = + "0000011a6347d4e801c91923488354cc533e7e35fddf81ff" + "0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6" + "e055895c8da24b8b0639a742314390cc04190ed6", + .pub_x = + "000000fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d37" + "6644620ca4fadee5626a3cede25ad254624def727a7048f7" + "145f76162aa98042f9b123b2076f8e8cf59b3fdf", + .pub_y = + "0000001145dc6631953b6e2945e94301d6cbb098fe4b04f7" + "ee9b09411df104dc82d7d79ec46a01ed0f2d3e7db6eb6806" + "94bdeb107c1078aec6cabd9ebee3d342fe7e54df", + .want = + "0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18" + "a04b9197034b250b48294f1867fb9641518f92766066a07a" + "8b917b0e76879e1011e51ccbd9f540c54d4f", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba" + "00fbc25f9dc72a07ce59372904899f364c44cb264c097b64" + "7d4412bee3e519892d534d9129f8a28f7500fee7", + .peer_y = + "000000baba8d672a4f4a3b63de48b96f56e18df5d68f7d70" + "d5109833f43770d6732e06b39ad60d93e5b43db8789f1ec0" + "aba47286a39ea584235acea757dbf13d53b58364", + .priv = + "00000022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d2" + "39538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f35" + "92bf5f1f2d4b56013aacc3d8d1bc02f00d3146cc", + .pub_x = + "000000ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57f" + "fd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d93" + "49cd2ed77bb1049ceb692a2ec5b17ad61502a64c", + .pub_y = + "0000001ec91d3058573fa6c0564a02a1a010160c313bc7c7" + "3510dc983e5461682b5be00dbce7e2c682ad73f29ca822cd" + "c111f68fabe33a7b384a648342c3cdb9f050bcdb", + .want = + "0101e462e9d9159968f6440e956f11dcf2227ae4aea81667" + "122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db" + "01a75af1ba519b2d31da33eda87a9d565748", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000004efd5dbd2f979e3831ce98f82355d6ca14a5757842" + "875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1" + "f3602f9ca653dc346fac858658d75626f4d4fb08", + .peer_y = + "00000061cf15dbdaa7f31589c98400373da284506d70c89f" + "074ed262a9e28140796b7236c2eef99016085e71552ff488" + "c72b7339fefb7915c38459cb20ab85aec4e45052", + .priv = + "0000005bacfff268acf6553c3c583b464ea36a1d35e2b257" + "a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff758" + "6490ccd3ddc1a98b39ce63749c6288ce0dbdac7d", + .pub_x = + "00000036e488da7581472a9d8e628c58d6ad727311b7e6a3" + "f6ae33a8544f34b09280249020be7196916fafd90e2ec54b" + "66b5468d2361b99b56fa00d7ac37abb8c6f16653", + .pub_y = + "0000011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c" + "9b66334e3af927c8befb4307104f299acec4e30f812d9345" + "c9720d19869dbfffd4ca3e7d2713eb5fc3f42615", + .want = + "0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc" + "35202cc7699b9b04d49616f82255debf7bbec045ae58f982" + "a66905fcfae69d689785e38c868eb4a27e7b", + }, + { + .nid = NID_secp521r1, + .peer_x = + "00000129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca4" + "5bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87" + "eacb78330d8bd52515f9f9a0b58e85f446bb4e10", + .peer_y = + "0000009edd679696d3d1d0ef327f200383253f6413683d9e" + "4fcc87bb35f112c2f110098d15e5701d7ceee416291ff5fe" + "d85e687f727388b9afe26a4f6feed560b218e6bb", + .priv = + "0000008e2c93c5423876223a637cad367c8589da69a2d0fc" + "68612f31923ae50219df2452e7cc92615b67f17b57ffd2f5" + "2b19154bb40d7715336420fde2e89fee244f59dc", + .pub_x = + "000000fa3b35118d6c422570f724a26f90b2833b19239174" + "cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c" + "4c39616479c1bb0c146799a118032dcf98f899c0", + .pub_y = + "00000069f040229006151fa32b51f679c8816f7c17506b40" + "3809dc77cd58a2aec430d94d13b6c916de99f355aa45fcfb" + "c6853d686c71be496a067d24bfaea4818fc51f75", + .want = + "00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a0" + "67a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351" + "903b14bf9a6a70c439257199a640890b61d1", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001a3c20240e59f5b7a3e17c275d2314ba1741210ad58" + "b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426" + "c23ffcc447054670d2908ff8fe67dc2306034c5c", + .peer_y = + "000001d2825bfd3af8b1e13205780c137fe938f84fde4018" + "8e61ea02cead81badfdb425c29f7d7fb0324debadc10bbb9" + "3de68f62c35069268283f5265865db57a79f7bf7", + .priv = + "00000004d49d39d40d8111bf16d28c5936554326b197353e" + "ebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b98" + "9754074daddb3045f4e4ce745669fdb3ec0d5fa8", + .pub_x = + "0000012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c" + "98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84f" + "a33b1803690dae04da7218d30026157fc995cf52", + .pub_y = + "0000004837dfbf3426f57b5c793269130abb9a38f6185322" + "11931154db4eeb9aede88e57290f842ea0f2ea9a5f74c620" + "3a3920fe4e305f6118f676b154e1d75b9cb5eb88", + .want = + "006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccf" + "d224757c7276f7a1010091b17ed072074f8d10a5ec971eb3" + "5a5cb7076603b7bc38d432cbc059f80f9488", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000007e2d138f2832e345ae8ff65957e40e5ec7163f016b" + "df6d24a2243daa631d878a4a16783990c722382130f9e51f" + "0c1bd6ff5ac96780e48b68f5dec95f42e6144bb5", + .peer_y = + "000000b0de5c896791f52886b0f09913e26e78dd0b69798f" + "c4df6d95e3ca708ecbcbcce1c1895f5561bbabaae372e9e6" + "7e6e1a3be60e19b470cdf673ec1fc393d3426e20", + .priv = + "0000011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e2" + "7b739864334a07c03367efda7a4619fa6eef3a9746492283" + "b3c445610a023a9cc49bf4591140384fca5c8bb5", + .pub_x = + "000000eb07c7332eedb7d3036059d35f7d2288d4377d5f42" + "337ad3964079fb120ccd4c8bd384b585621055217023acd9" + "a94fcb3b965bfb394675e788ade41a1de73e620c", + .pub_y = + "000000491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e" + "94ee8d751014dc720784fd3b54500c86ebaef18429f09e8e" + "876d5d1538968a030d7715dde99f0d8f06e29d59", + .want = + "01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b7" + "8871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279a" + "f6f146f0bbfb0683140403bfa4ccdb524a29", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000000118c36022209b1af8ebad1a12b566fc48744576e11" + "99fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b" + "691d0c22ee29d6bdf73ec7bbfd746f2cd97a357d", + .peer_y = + "000000da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf" + "63e6fe622f22c13e614e0a847c11a1ab3f1d12cc850c32e0" + "95614ca8f7e2721477b486e9ff40372977c3f65c", + .priv = + "0000010c908caf1be74c616b625fc8c1f514446a6aec83b5" + "937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd" + "8bf836c56d3c0ebdcc980e43a186f938f3a78ae7", + .pub_x = + "00000031890f4c7abec3f723362285d77d2636f876817db3" + "bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb" + "8cbea69b82ddf36acadd406871798ecb2ac3aa7f", + .pub_y = + "000000d8b429ae3250266b9643c0c765a60dc10155bc2531" + "cf8627296f4978b6640a9e600e19d0037d58503fa8079954" + "6a814d7478a550aa90e5ebeb052527faaeae5d08", + .want = + "0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2" + "b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea" + "8954a8d0c8b851e81a56fda95212a6578f0e", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001780edff1ca1c03cfbe593edc6c049bcb2860294a92" + "c355489d9afb2e702075ade1c953895a456230a0cde905de" + "4a3f38573dbfcccd67ad6e7e93f0b5581e926a5d", + .peer_y = + "000000a5481962c9162962e7f0ebdec936935d0eaa813e82" + "26d40d7f6119bfd940602380c86721e61db1830f51e139f2" + "10000bcec0d8edd39e54d73a9a129f95cd5fa979", + .priv = + "000001b37d6b7288de671360425d3e5ac1ccb21815079d8d" + "73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593" + "eba9d98bf25c75ef0b4d3a2098bbc641f59a2b77", + .pub_x = + "000000189a5ee34de7e35aefeaeef9220c18071b4c29a4c3" + "bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f52" + "7cf4581501e28ef5671873e65267733d003520af", + .pub_y = + "000001eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b34228" + "72e544bdf75c7bf60f5166ddc11eb08fa7c30822dabaee37" + "3ab468eb2d922e484e2a527fff2ebb804b7d9a37", + .want = + "015d613e267a36342e0d125cdad643d80d97ed0600afb9e6" + "b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218" + "a80abafc106ef065c8f1c4e1119ef58d298b", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000016dacffa183e5303083a334f765de724ec5ec940202" + "6d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc7" + "3b6a35c1c7b01d373e31abc192d48a4241a35803", + .peer_y = + "0000011e5327cac22d305e7156e559176e19bee7e4f2f59e" + "86f1a9d0b6603b6a7df1069bde6387feb71587b8ffce5b26" + "6e1bae86de29378a34e5c74b6724c4d40a719923", + .priv = + "000000f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72" + "618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a16" + "81ee44d96ab2135a6e5f3415ebbcd55165b1afb0", + .pub_x = + "000000a8e25a6902d687b4787cdc94c364ac7cecc5c49548" + "3ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d" + "7e54c6822f52f47162a25109aaaba690cab696ec", + .pub_y = + "00000168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520" + "b6270557504e72ca4394a2c6918625e15ac0c51b8f95cd56" + "0123653fb8e8ee6db961e2c4c62cc54e92e2a2a9", + .want = + "014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb1" + "4a4c991e3c82a9731288bdb91e0e85bda313912d06384fc4" + "4f2153fb13506fa9cf43c9aab5750988c943", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000000a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d0" + "01967b801d1cec27e605c580b2387c1cb464f55ce7ac8033" + "4102ab03cfb86d88af76c9f4129c01bedd3bbfc4", + .peer_y = + "0000008c9c577a8e6fc446815e9d40baa66025f15dae285f" + "19eb668ee60ae9c98e7ecdbf2b2a68e22928059f67db1880" + "07161d3ecf397e0883f0c4eb7eaf7827a62205cc", + .priv = + "000000f430ca1261f09681a9282e9e970a9234227b1d5e58" + "d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc795861" + "16b0efc15f79340fb7eaf5ce6c44341dcf8dde27", + .pub_x = + "0000006c1d9b5eca87de1fb871a0a32f807c725adccde9b3" + "967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6" + "e8d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b", + .pub_y = + "000001141b2109e7f4981c952aa818a2b9f6f5c41feccdb7" + "a7a45b9b4b672937771b008cae5f934dfe3fed10d383ab1f" + "38769c92ce88d9be5414817ecb073a31ab368ccb", + .want = + "0020c00747cb8d492fd497e0fec54644bf027d418ab68638" + "1f109712a99cabe328b9743d2225836f9ad66e5d7fed1de2" + "47e0da92f60d5b31f9e47672e57f710598f4", + }, + { + .nid = NID_secp521r1, + .peer_x = + "0000004f38816681771289ce0cb83a5e29a1ab06fc91f786" + "994b23708ff08a08a0f675b809ae99e9f9967eb1a49f1960" + "57d69e50d6dedb4dd2d9a81c02bdcc8f7f518460", + .peer_y = + "0000009efb244c8b91087de1eed766500f0e81530752d469" + "256ef79f6b965d8a2232a0c2dbc4e8e1d09214bab38485be" + "6e357c4200d073b52f04e4a16fc6f5247187aecb", + .priv = + "0000005dc33aeda03c2eb233014ee468dff753b72f73b009" + "91043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff" + "2e6e473a5a4ff98e90f90d6dadd25100e8d85666", + .pub_x = + "000000c825ba307373cec8dd2498eef82e21fd9862168dbf" + "eb83593980ca9f82875333899fe94f137daf1c4189eb5029" + "37c3a367ea7951ed8b0f3377fcdf2922021d46a5", + .pub_y = + "0000016b8a2540d5e65493888bc337249e67c0a68774f3e8" + "d81e3b4574a0125165f0bd58b8af9de74b35832539f95c3c" + "d9f1b759408560aa6851ae3ac7555347b0d3b13b", + .want = + "00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c" + "574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca66" + "0d216c553622362794f7a2acc71022bdb16f", + }, + { + .nid = NID_secp521r1, + .peer_x = + "000001a32099b02c0bd85371f60b0dd20890e6c7af048c81" + "79890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0b" + "3cb96ae1eb7684132795c478ad6f962e4a6f446d", + .peer_y = + "0000017627357b39e9d7632a1370b3e93c1afb5c851b910e" + "b4ead0c9d387df67cde85003e0e427552f1cd09059aad026" + "2e235cce5fba8cedc4fdc1463da76dcd4b6d1a46", + .priv = + "000000df14b1f1432a7b0fb053965fd8643afee26b2451ec" + "b6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb236274" + "71dffc5c2523bd2ae89957cba3a57a23933e5a78", + .pub_x = + "0000004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f" + "3c560229664329baa5138c3bb1c36428abd4e23d17fcb7a2" + "cfcc224b2e734c8941f6f121722d7b6b94154576", + .pub_y = + "000001cf0874f204b0363f020864672fadbf87c8811eb147" + "758b254b74b14fae742159f0f671a018212bbf25b8519e12" + "6d4cad778cfff50d288fd39ceb0cac635b175ec0", + .want = + "01aaf24e5d47e4080c18c55ea35581cd8da30f1a07956504" + "5d2008d51b12d0abb4411cda7a0785b15d149ed301a36970" + "62f42da237aa7f07e0af3fd00eb1800d9c41", + }, +}; + +#define N_ECC_CDH_TESTS (sizeof(ecc_cdh_tests) / sizeof(ecc_cdh_tests[0])) + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static int +run_ecc_cdh_test(const struct ecc_cdh_test *test) +{ + static int last_nid; + static size_t count; + EC_KEY *key = NULL; + const EC_GROUP *group; + EC_POINT *peer_pub = NULL; + BN_CTX *ctx = NULL; + BIGNUM *peer_x, *peer_y, *priv, *pub_x, *pub_y, *shared; + uint8_t *out, *want; + int out_len; + int failed = 1; + + if (test->nid != last_nid) { + last_nid = test->nid; + count = 0; + } + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(ctx); + + if ((peer_x = BN_CTX_get(ctx)) == NULL) + errx(1, "peer_x = BN_CTX_get()"); + if ((peer_y = BN_CTX_get(ctx)) == NULL) + errx(1, "peer_y = BN_CTX_get()"); + if ((priv = BN_CTX_get(ctx)) == NULL) + errx(1, "priv = BN_CTX_get()"); + if ((pub_x = BN_CTX_get(ctx)) == NULL) + errx(1, "pub_x = BN_CTX_get()"); + if ((pub_y = BN_CTX_get(ctx)) == NULL) + errx(1, "pub_y = BN_CTX_get()"); + if ((shared = BN_CTX_get(ctx)) == NULL) + errx(1, "want = BN_CTX_get()"); + + if ((key = EC_KEY_new_by_curve_name(test->nid)) == NULL) + errx(1, "EC_KEY_new_by_curve_name(%d)", test->nid); + + if (!BN_hex2bn(&peer_x, test->peer_x)) + errx(1, "peer_x = BN_hex2bn()"); + if (!BN_hex2bn(&peer_y, test->peer_y)) + errx(1, "peer_y = BN_hex2bn()"); + + if ((group = EC_KEY_get0_group(key)) == NULL) + errx(1, "EC_KEY_get0_group"); + + if ((peer_pub = EC_POINT_new(group)) == NULL) + errx(1, "EC_POINT_new"); + + if (!EC_POINT_set_affine_coordinates(group, peer_pub, peer_x, peer_y, ctx)) + errx(1, "EC_POINT_set_affine_coordinates"); + + if (!BN_hex2bn(&priv, test->priv)) + errx(1, "priv = BN_hex2bn()"); + if (!BN_hex2bn(&pub_x, test->pub_x)) + errx(1, "pub_x = BN_hex2bn()"); + if (!BN_hex2bn(&pub_y, test->pub_y)) + errx(1, "pub_y = BN_hex2bn()"); + + if (!EC_KEY_set_private_key(key, priv)) + errx(1, "EC_KEY_set_private_key"); + if (!EC_KEY_set_public_key_affine_coordinates(key, pub_x, pub_y)) + errx(1, "EC_KEY_set_public_key_affine_coordinates"); + + EC_KEY_set_flags(key, EC_FLAG_COFACTOR_ECDH); + + out_len = ECDH_size(key); + if ((out = calloc(1, out_len)) == NULL) + errx(1, NULL); + + if (ECDH_compute_key(out, out_len, peer_pub, key, NULL) != out_len) + errx(1, "ECDH_compute_key"); + + if (!BN_hex2bn(&shared, test->want)) + errx(1, "shared = BN_hex2bn()"); + + if ((want = calloc(1, out_len)) == NULL) + errx(1, NULL); + + if (BN_bn2binpad(shared, want, out_len) != out_len) + errx(1, "BN_bn2binpad"); + + if (memcmp(out, want, out_len) != 0) { + fprintf(stderr, "%s test %zu failed:\nwant:\n", + OBJ_nid2sn(test->nid), count); + hexdump(want, out_len); + fprintf(stderr, "got:\n"); + hexdump(out, out_len); + goto failed; + } + + failed = 0; + + failed: + count++; + + EC_KEY_free(key); + EC_POINT_free(peer_pub); + BN_CTX_end(ctx); + BN_CTX_free(ctx); + freezero(out, out_len); + freezero(want, out_len); + + return failed; +} + +int +main(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_ECC_CDH_TESTS; i++) + failed |= run_ecc_cdh_test(&ecc_cdh_tests[i]); + + return failed; +} diff --git a/tests/ecdhtest.c b/tests/ecdhtest.c new file mode 100644 index 0000000..7d7bbf5 --- /dev/null +++ b/tests/ecdhtest.c @@ -0,0 +1,418 @@ +/* $OpenBSD: ecdhtest.c,v 1.20 2023/07/16 07:34:07 tb Exp $ */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * The Elliptic Curve Public-Key Crypto Library (ECC Code) included + * herein is developed by SUN MICROSYSTEMS, INC., and is contributed + * to the OpenSSL project. + * + * The ECC Code is licensed pursuant to the OpenSSL open source + * license provided below. + * + * The ECDH software is originally written by Douglas Stebila of + * Sun Microsystems Laboratories. + * + */ +/* ==================================================================== + * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stdout, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stdout, "\n"); +} + +static void * +KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen) +{ +#ifdef OPENSSL_NO_SHA + return NULL; +#else + if (*outlen < SHA_DIGEST_LENGTH) + return NULL; + *outlen = SHA_DIGEST_LENGTH; + return SHA1(in, inlen, out); +#endif +} + +static int +ecdh_keygen_test(int nid) +{ + EC_KEY *keya = NULL, *keyb = NULL; + const EC_POINT *puba, *pubb; + unsigned char *abuf = NULL, *bbuf = NULL; + int len = SHA_DIGEST_LENGTH; + int failed = 1; + + if ((keya = EC_KEY_new_by_curve_name(nid)) == NULL) + goto err; + if (!EC_KEY_generate_key(keya)) + goto err; + if ((puba = EC_KEY_get0_public_key(keya)) == NULL) + goto err; + + if ((keyb = EC_KEY_new_by_curve_name(nid)) == NULL) + goto err; + if (!EC_KEY_generate_key(keyb)) + goto err; + if ((pubb = EC_KEY_get0_public_key(keyb)) == NULL) + goto err; + + if ((abuf = calloc(1, len)) == NULL) + goto err; + if ((bbuf = calloc(1, len)) == NULL) + goto err; + + if (ECDH_compute_key(abuf, len, pubb, keya, KDF1_SHA1) != len) + goto err; + if (ECDH_compute_key(bbuf, len, puba, keyb, KDF1_SHA1) != len) + goto err; + + if (memcmp(abuf, bbuf, len) != 0) { + printf("key generation with %s failed\n", OBJ_nid2sn(nid)); + + EC_KEY_print_fp(stdout, keya, 1); + printf(" shared secret:\n"); + hexdump(abuf, len); + + EC_KEY_print_fp(stdout, keyb, 1); + printf(" shared secret:\n"); + hexdump(bbuf, len); + + fprintf(stderr, "Error in ECDH routines\n"); + + goto err; + } + + failed = 0; + + err: + ERR_print_errors_fp(stderr); + + EC_KEY_free(keya); + EC_KEY_free(keyb); + freezero(abuf, len); + freezero(bbuf, len); + + return failed; +} + +static const struct ecdh_kat_test { + const int nid; + const char *keya; + const char *keyb; + const char *want; +} ecdh_kat_tests[] = { + /* Keys and shared secrets from RFC 5114 */ + { + .nid = NID_X9_62_prime192v1, + .keya = "323fa3169d8e9c6593f59476bc142000ab5be0e249c43426", + .keyb = "631f95bb4a67632c9c476eee9ab695ab240a0499307fcf62", + .want = "ad420182633f8526bfe954acda376f05e5ff4f837f54febe", + }, + { + .nid = NID_secp224r1, + .keya = "b558eb6c288da707bbb4f8fbae2ab9e9cb62e3bc5c7573e2" + "2e26d37f", + .keyb = "ac3b1add3d9770e6f6a708ee9f3b8e0ab3b480e9f27f85c8" + "8b5e6d18", + .want = "52272f50f46f4edc9151569092f46df2d96ecc3b6dc1714a" + "4ea949fa", + }, + { + .nid = NID_X9_62_prime256v1, + .keya = "814264145f2f56f2e96a8e337a1284993faf432a5abce59e" + "867b7291d507a3af", + .keyb = "2ce1788ec197e096db95a200cc0ab26a19ce6bccad562b8e" + "ee1b593761cf7f41", + .want = "dd0f5396219d1ea393310412d19a08f1f5811e9dc8ec8eea" + "7f80d21c820c2788", + }, + { + .nid = NID_secp384r1, + .keya = "d27335ea71664af244dd14e9fd1260715dfd8a7965571c48" + "d709ee7a7962a156d706a90cbcb5df2986f05feadb9376f1", + .keyb = "52d1791fdb4b70f89c0f00d456c2f7023b6125262c36a7df" + "1f80231121cce3d39be52e00c194a4132c4a6c768bcd94d2", + .want = "5ea1fc4af7256d2055981b110575e0a8cae53160137d904c" + "59d926eb1b8456e427aa8a4540884c37de159a58028abc0e", + }, + { + .nid = NID_secp521r1, + .keya = "0113f82da825735e3d97276683b2b74277bad27335ea7166" + "4af2430cc4f33459b9669ee78b3ffb9b8683015d344dcbfe" + "f6fb9af4c6c470be254516cd3c1a1fb47362", + .keyb = "00cee3480d8645a17d249f2776d28bae616952d1791fdb4b" + "70f7c3378732aa1b22928448bcd1dc2496d435b01048066e" + "be4f72903c361b1a9dc1193dc2c9d0891b96", + .want = "00cdea89621cfa46b132f9e4cfe2261cde2d4368eb565663" + "4c7cc98c7a00cde54ed1866a0dd3e6126c9d2f845daff82c" + "eb1da08f5d87521bb0ebeca77911169c20cc", + }, + /* Keys and shared secrets from RFC 5903 */ + { + .nid = NID_X9_62_prime256v1, + .keya = "c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049" + "c62a9c57862d1433", + .keyb = "c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0" + "b283ab46476bee53", + .want = "d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03" + "812464d04b9442de", + }, + { + .nid = NID_secp384r1, + .keya = "099f3c7034d4a2c699884d73a375a67f7624ef7c6b3c0f16" + "0647b67414dce655e35b538041e649ee3faef896783ab194", + .keyb = "41cb0779b4bdb85d47846725fbec3c9430fab46cc8dc5060" + "855cc9bda0aa2942e0308312916b8ed2960e4bd55a7448fc", + .want = "11187331c279962d93d604243fd592cb9d0a926f422e4718" + "7521287e7156c5c4d603135569b9e9d09cf5d4a270f59746", + }, + { + .nid = NID_secp521r1, + .keya = "0037ade9319a89f4dabdb3ef411aaccca5123c61acab57b5" + "393dce47608172a095aa85a30fe1c2952c6771d937ba9777" + "f5957b2639bab072462f68c27a57382d" + "4a52", + .keyb = "0145ba99a847af43793fdd0e872e7cdfa16be30fdc780f97" + "bccc3f078380201e9c677d600b343757a3bdbf2a3163e4c2" + "f869cca7458aa4a4effc311f5cb151685eb9", + .want = "01144c7d79ae6956bc8edb8e7c787c4521cb086fa64407f9" + "7894e5e6b2d79b04d1427e73ca4baa240a34786859810c06" + "b3c715a3a8cc3151f2bee417996d19f3ddea", + }, + /* Keys and shared secrets from RFC 7027 */ + { + .nid = NID_brainpoolP256r1, + .keya = "81db1ee100150ff2ea338d708271be38300cb54241d79950" + "f77b063039804f1d", + .keyb = "55e40bc41e37e3e2ad25c3c6654511ffa8474a91a0032087" + "593852d3e7d76bd3", + .want = "89afc39d41d3b327814b80940b042590f96556ec91e6ae79" + "39bce31f3a18bf2b", + }, + { + .nid = NID_brainpoolP384r1, + .keya = "1e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d" + "57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042", + .keyb = "032640bc6003c59260f7250c3db58ce647f98e1260acce4a" + "cda3dd869f74e01f8ba5e0324309db6a9831497abac96670", + .want = "0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc" + "51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42", + }, + { + .nid = NID_brainpoolP512r1, + .keya = "16302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a" + "56850a38bd87bd59b09e80279609ff333eb9d4c061231fb2" + "6f92eeb04982a5f1d1764cad57665422", + .keyb = "230e18e1bcc88a362fa54e4ea3902009292f7f8033624fd4" + "71b5d8ace49d12cfabbc19963dab8e2f1eba00bffb29e4d7" + "2d13f2224562f405cb80503666b25429", + .want = "a7927098655f1f9976fa50a9d566865dc530331846381c87" + "256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d" + "24f11a9b5c0bef679fe1454b21c4cd1f", + }, +}; + +#define N_KATS (sizeof(ecdh_kat_tests) / sizeof(ecdh_kat_tests[0])) + +/* Given private value and NID, create EC_KEY structure */ + +static EC_KEY * +mk_eckey(int nid, const char *priv_str) +{ + EC_KEY *key = NULL; + BIGNUM *priv = NULL; + EC_POINT *pub = NULL; + const EC_GROUP *group; + EC_KEY *ret = NULL; + + if ((key = EC_KEY_new_by_curve_name(nid)) == NULL) + goto err; + if (!BN_hex2bn(&priv, priv_str)) + goto err; + if (!EC_KEY_set_private_key(key, priv)) + goto err; + if ((group = EC_KEY_get0_group(key)) == NULL) + goto err; + if ((pub = EC_POINT_new(group)) == NULL) + goto err; + if (!EC_POINT_mul(group, pub, priv, NULL, NULL, NULL)) + goto err; + if (!EC_KEY_set_public_key(key, pub)) + goto err; + + ret = key; + key = NULL; + + err: + EC_KEY_free(key); + BN_free(priv); + EC_POINT_free(pub); + + return ret; +} + +/* + * Known answer test: compute shared secret and check it matches expected value. + */ +static int +ecdh_kat(const struct ecdh_kat_test *kat) +{ + EC_KEY *keya = NULL, *keyb = NULL; + const EC_POINT *puba, *pubb; + BIGNUM *z = NULL; + unsigned char *want = NULL, *got = NULL; + int len = 0; + int failed = 1; + + if ((keya = mk_eckey(kat->nid, kat->keya)) == NULL) + goto err; + if ((puba = EC_KEY_get0_public_key(keya)) == NULL) + goto err; + if ((keyb = mk_eckey(kat->nid, kat->keyb)) == NULL) + goto err; + if ((pubb = EC_KEY_get0_public_key(keyb)) == NULL) + goto err; + + if ((len = ECDH_size(keya)) != ECDH_size(keyb)) + goto err; + + if ((want = calloc(1, len)) == NULL) + goto err; + if ((got = calloc(1, len)) == NULL) + goto err; + + if (!BN_hex2bn(&z, kat->want)) + goto err; + if (BN_num_bytes(z) > len) + goto err; + if (BN_bn2binpad(z, want, len) != len) + goto err; + + if (ECDH_compute_key(got, len, pubb, keya, NULL) != len) + goto err; + if (memcmp(got, want, len) != 0) + goto err; + + memset(got, 0, len); + + if (ECDH_compute_key(got, len, puba, keyb, NULL) != len) + goto err; + if (memcmp(got, want, len) != 0) + goto err; + + failed = 0; + + err: + if (failed) { + printf("shared secret with %s failed", OBJ_nid2sn(kat->nid)); + + fprintf(stderr, "Error in ECDH routines\n"); + ERR_print_errors_fp(stderr); + } + + EC_KEY_free(keya); + EC_KEY_free(keyb); + BN_free(z); + freezero(want, len); + freezero(got, len); + + return failed; +} + +int +main(void) +{ + EC_builtin_curve *curves = NULL; + size_t i, n_curves; + int failed = 0; + + if ((n_curves = EC_get_builtin_curves(NULL, 0)) == 0) + errx(1, "EC_get_builtin_curves failed"); + if ((curves = calloc(n_curves, sizeof(*curves))) == NULL) + errx(1, NULL); + if (EC_get_builtin_curves(curves, n_curves) != n_curves) + errx(1, "EC_get_builtin_curves failed"); + + for (i = 0; i < n_curves; i++) + failed |= ecdh_keygen_test(curves[i].nid); + + for (i = 0; i < N_KATS; i++) + failed |= ecdh_kat(&ecdh_kat_tests[i]); + + free(curves); + ERR_print_errors_fp(stderr); + + return failed; +} diff --git a/tests/ecdsatest.c b/tests/ecdsatest.c new file mode 100644 index 0000000..b0b9bd0 --- /dev/null +++ b/tests/ecdsatest.c @@ -0,0 +1,348 @@ +/* $OpenBSD: ecdsatest.c,v 1.17 2023/05/04 13:50:14 tb Exp $ */ +/* + * Written by Nils Larsch for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 2000-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include + +int test_builtin(void); + +int +test_builtin(void) +{ + unsigned char digest[20], wrong_digest[20]; + EC_builtin_curve *curves = NULL; + size_t num_curves = 0, n = 0; + EC_KEY *eckey = NULL, *wrong_eckey = NULL; + EC_GROUP *group; + ECDSA_SIG *ecdsa_sig = NULL; + BIGNUM *r = NULL, *s = NULL; + unsigned char *signature = NULL; + const unsigned char *sig_ptr; + unsigned char *sig_ptr2; + unsigned char *raw_buf = NULL; + unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; + int nid; + int failed = 1; + + /* fill digest values with some random data */ + arc4random_buf(digest, 20); + arc4random_buf(wrong_digest, 20); + + /* create and verify a ecdsa signature with every available curve */ + printf("\ntesting ECDSA_sign() and ECDSA_verify() " + "with some internal curves:\n"); + + /* get a list of all internal curves */ + num_curves = EC_get_builtin_curves(NULL, 0); + + curves = reallocarray(NULL, sizeof(EC_builtin_curve), num_curves); + if (curves == NULL) { + printf("reallocarray error\n"); + goto err; + } + + if (!EC_get_builtin_curves(curves, num_curves)) { + printf("unable to get internal curves\n"); + goto err; + } + + /* now create and verify a signature for every curve */ + for (n = 0; n < num_curves; n++) { + unsigned char dirt, offset; + + nid = curves[n].nid; + if (nid == NID_ipsec4) + continue; + + if ((eckey = EC_KEY_new()) == NULL) + goto err; + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) + goto err; + if (EC_KEY_set_group(eckey, group) == 0) + goto err; + degree = EC_GROUP_get_degree(group); + EC_GROUP_free(group); + if (degree < 160) { + /* drop the curve */ + EC_KEY_free(eckey); + eckey = NULL; + continue; + } + printf("%s: ", OBJ_nid2sn(nid)); + + if (!EC_KEY_generate_key(eckey)) { + goto err; + } + + /* Exercise ECParameters_dup() and let ASAN test for leaks. */ + if ((wrong_eckey = ECParameters_dup(eckey)) == NULL) + goto err; + group = EC_GROUP_new_by_curve_name(nid); + if (group == NULL) + goto err; + if (EC_KEY_set_group(wrong_eckey, group) == 0) + goto err; + EC_GROUP_free(group); + if (!EC_KEY_generate_key(wrong_eckey)) + goto err; + + printf("."); + fflush(stdout); + + if (!EC_KEY_check_key(eckey)) + goto err; + + printf("."); + fflush(stdout); + + if ((sig_len = ECDSA_size(eckey)) == 0) + goto err; + if ((signature = malloc(sig_len)) == NULL) + goto err; + if (!ECDSA_sign(0, digest, 20, signature, &sig_len, eckey)) + goto err; + + printf("."); + fflush(stdout); + + if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) + goto err; + + printf("."); + fflush(stdout); + + /* verify signature with the wrong key */ + if (ECDSA_verify(0, digest, 20, signature, sig_len, + wrong_eckey) == 1) + goto err; + + printf("."); + fflush(stdout); + + if (ECDSA_verify(0, wrong_digest, 20, signature, sig_len, + eckey) == 1) + goto err; + + printf("."); + fflush(stdout); + + if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, + eckey) == 1) + goto err; + + printf("."); + fflush(stdout); + + /* + * Modify a single byte of the signature: to ensure we don't + * garble the ASN1 structure, we read the raw signature and + * modify a byte in one of the bignums directly. + */ + sig_ptr = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, + sig_len)) == NULL) + goto err; + + /* Store the two BIGNUMs in raw_buf. */ + r_len = BN_num_bytes(ECDSA_SIG_get0_r(ecdsa_sig)); + s_len = BN_num_bytes(ECDSA_SIG_get0_s(ecdsa_sig)); + bn_len = (degree + 7) / 8; + if ((r_len > bn_len) || (s_len > bn_len)) + goto err; + + buf_len = 2 * bn_len; + if ((raw_buf = calloc(1, buf_len)) == NULL) + goto err; + BN_bn2bin(ECDSA_SIG_get0_r(ecdsa_sig), + raw_buf + bn_len - r_len); + BN_bn2bin(ECDSA_SIG_get0_s(ecdsa_sig), + raw_buf + buf_len - s_len); + + /* Modify a single byte in the buffer. */ + offset = raw_buf[10] % buf_len; + dirt = raw_buf[11] ? raw_buf[11] : 1; + raw_buf[offset] ^= dirt; + /* Now read the BIGNUMs back in from raw_buf. */ + if ((r = BN_bin2bn(raw_buf, bn_len, NULL)) == NULL || + (s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) == NULL) + goto err; + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) + goto err; + r = NULL; + s = NULL; + + if ((sig_len = i2d_ECDSA_SIG(ecdsa_sig, NULL)) <= 0) + goto err; + free(signature); + if ((signature = calloc(1, sig_len)) == NULL) + goto err; + + sig_ptr2 = signature; + if ((sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2)) <= 0) + goto err; + if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) + goto err; + + /* Sanity check: undo the modification and verify signature. */ + raw_buf[offset] ^= dirt; + if ((r = BN_bin2bn(raw_buf, bn_len, NULL)) == NULL || + (s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) == NULL) + goto err; + if (!ECDSA_SIG_set0(ecdsa_sig, r, s)) + goto err; + r = NULL; + s = NULL; + + if ((sig_len = i2d_ECDSA_SIG(ecdsa_sig, NULL)) <= 0) + goto err; + free(signature); + if ((signature = calloc(1, sig_len)) == NULL) + goto err; + + sig_ptr2 = signature; + if ((sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr2)) <= 0) + goto err; + if (ECDSA_verify(0, digest, 20, signature, sig_len, + eckey) != 1) + goto err; + + printf("."); + fflush(stdout); + + printf(" ok\n"); + + ERR_clear_error(); + free(signature); + signature = NULL; + EC_KEY_free(eckey); + eckey = NULL; + EC_KEY_free(wrong_eckey); + wrong_eckey = NULL; + ECDSA_SIG_free(ecdsa_sig); + ecdsa_sig = NULL; + free(raw_buf); + raw_buf = NULL; + } + + failed = 0; + + err: + if (failed) + printf(" failed\n"); + + BN_free(r); + BN_free(s); + EC_KEY_free(eckey); + EC_KEY_free(wrong_eckey); + ECDSA_SIG_free(ecdsa_sig); + free(signature); + free(raw_buf); + free(curves); + + return failed; +} + +int +main(void) +{ + int failed = 1; + + /* the tests */ + if (test_builtin()) + goto err; + + printf("\nECDSA test passed\n"); + failed = 0; + + err: + if (failed) { + printf("\nECDSA test failed\n"); + ERR_print_errors_fp(stdout); + } + + CRYPTO_cleanup_all_ex_data(); + ERR_remove_thread_state(NULL); + ERR_free_strings(); + + return failed; +} diff --git a/tests/ectest.c b/tests/ectest.c new file mode 100644 index 0000000..f0b1028 --- /dev/null +++ b/tests/ectest.c @@ -0,0 +1,781 @@ +/* $OpenBSD: ectest.c,v 1.21 2023/07/26 22:46:06 tb Exp $ */ +/* + * Originally written by Bodo Moeller for the OpenSSL project. + */ +/* ==================================================================== + * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * + * Portions of the attached software ("Contribution") are developed by + * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. + * + * The Contribution is licensed pursuant to the OpenSSL open source + * license provided above. + * + * The elliptic curve binary polynomial software is originally written by + * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. + * + */ + +#include +#include +#include +#include + +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include +#include +#include +#include + +#define ABORT do { \ + fflush(stdout); \ + fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \ + ERR_print_errors_fp(stderr); \ + exit(1); \ +} while (0) + +#define TIMING_BASE_PT 0 +#define TIMING_RAND_PT 1 +#define TIMING_SIMUL 2 + +int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, + const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx); + +/* test multiplication with group order, long and negative scalars */ +static void +group_order_tests(EC_GROUP *group) +{ + BIGNUM *n1, *n2, *order; + EC_POINT *P = EC_POINT_new(group); + EC_POINT *Q = EC_POINT_new(group); + BN_CTX *ctx; + + if ((ctx = BN_CTX_new()) == NULL) + ABORT; + + if ((n1 = BN_new()) == NULL) + ABORT; + if ((n2 = BN_new()) == NULL) + ABORT; + if ((order = BN_new()) == NULL) + ABORT; + fprintf(stdout, "verify group order ..."); + fflush(stdout); + if (!EC_GROUP_get_order(group, order, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, Q)) + ABORT; + fprintf(stdout, "."); + fflush(stdout); + if (!EC_GROUP_precompute_mult(group, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, order, NULL, NULL, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, Q)) + ABORT; + fprintf(stdout, " ok\n"); + fprintf(stdout, "long/negative scalar tests ... "); + /* XXX - switch back to BN_one() after next bump. */ + if (!BN_set_word(n1, 1)) + ABORT; + /* n1 = 1 - order */ + if (!BN_sub(n1, n1, order)) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n1, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + /* n2 = 1 + order */ + if (!BN_add(n2, order, BN_value_one())) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + /* n2 = (1 - order) * (1 + order) */ + if (!BN_mul(n2, n1, n2, ctx)) + ABORT; + if (!EC_POINT_mul(group, Q, NULL, P, n2, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, Q, P, ctx)) + ABORT; + fprintf(stdout, "ok\n"); + EC_POINT_free(P); + EC_POINT_free(Q); + BN_free(n1); + BN_free(n2); + BN_free(order); + BN_CTX_free(ctx); +} + +static void +prime_field_tests(void) +{ + BN_CTX *ctx = NULL; + BIGNUM *p, *a, *b; + EC_GROUP *group; + EC_GROUP *P_160 = NULL, *P_192 = NULL, *P_224 = NULL, *P_256 = NULL, *P_384 = NULL, *P_521 = NULL; + EC_POINT *P, *Q, *R; + BIGNUM *x, *y, *z; + unsigned char buf[100]; + size_t i, len; + int k; + + ctx = BN_CTX_new(); + if (!ctx) + ABORT; + + p = BN_new(); + a = BN_new(); + b = BN_new(); + if (!p || !a || !b) + ABORT; + + if (!BN_hex2bn(&p, "17")) + ABORT; + if (!BN_hex2bn(&a, "1")) + ABORT; + if (!BN_hex2bn(&b, "1")) + ABORT; + + group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp + * so that the library gets to choose the EC_METHOD */ + if (!group) + ABORT; + + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + { + EC_GROUP *tmp; + tmp = EC_GROUP_new(EC_GROUP_method_of(group)); + if (!tmp) + ABORT; + if (!EC_GROUP_copy(tmp, group)) + ABORT; + EC_GROUP_free(group); + group = tmp; + } + + if (!EC_GROUP_get_curve(group, p, a, b, ctx)) + ABORT; + + fprintf(stdout, "Curve defined by Weierstrass equation\n y^2 = x^3 + a*x + b (mod 0x"); + BN_print_fp(stdout, p); + fprintf(stdout, ")\n a = 0x"); + BN_print_fp(stdout, a); + fprintf(stdout, "\n b = 0x"); + BN_print_fp(stdout, b); + fprintf(stdout, "\n"); + + P = EC_POINT_new(group); + Q = EC_POINT_new(group); + R = EC_POINT_new(group); + if (!P || !Q || !R) + ABORT; + + if (!EC_POINT_set_to_infinity(group, P)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + buf[0] = 0; + if (!EC_POINT_oct2point(group, Q, buf, 1, ctx)) + ABORT; + + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + x = BN_new(); + y = BN_new(); + z = BN_new(); + if (!x || !y || !z) + ABORT; + + if (!BN_hex2bn(&x, "D")) + ABORT; + if (!EC_POINT_set_compressed_coordinates(group, Q, x, 1, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, Q, ctx) <= 0) { + if (!EC_POINT_get_affine_coordinates(group, Q, x, y, ctx)) + ABORT; + fprintf(stderr, "Point is not on curve: x = 0x"); + BN_print_fp(stderr, x); + fprintf(stderr, ", y = 0x"); + BN_print_fp(stderr, y); + fprintf(stderr, "\n"); + ABORT; + } + + fprintf(stdout, "A cyclic subgroup:\n"); + k = 100; + do { + if (k-- == 0) + ABORT; + + if (EC_POINT_is_at_infinity(group, P)) + fprintf(stdout, " point at infinity\n"); + else { + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + + fprintf(stdout, " x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, ", y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + } + + if (!EC_POINT_copy(R, P)) + ABORT; + if (!EC_POINT_add(group, P, P, Q, ctx)) + ABORT; + } while (!EC_POINT_is_at_infinity(group, P)); + + if (!EC_POINT_add(group, P, Q, R, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, P)) + ABORT; + + len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_COMPRESSED, buf, sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "Generator as octet string, compressed form:\n "); + for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); + + len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, uncompressed form:\n "); + for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); + + len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); + if (len == 0) + ABORT; + if (!EC_POINT_oct2point(group, P, buf, len, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, Q, ctx)) + ABORT; + fprintf(stdout, "\nGenerator as octet string, hybrid form:\n "); + for (i = 0; i < len; i++) fprintf(stdout, "%02X", buf[i]); + + if (!EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx)) + ABORT; + fprintf(stdout, "\nA representation of the inverse of that generator in\nJacobian projective coordinates:\n X = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, ", Y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, ", Z = 0x"); + BN_print_fp(stdout, z); + fprintf(stdout, "\n"); + + if (!EC_POINT_invert(group, P, ctx)) + ABORT; + if (0 != EC_POINT_cmp(group, P, R, ctx)) + ABORT; + + + /* Curve secp160r1 (Certicom Research SEC 2 Version 1.0, section 2.4.2, 2000) + * -- not a NIST curve, but commonly used */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45")) + ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) + ABORT; + if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) + ABORT; + if (!EC_POINT_set_affine_coordinates(group, P, x, y, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "23a628553168947d59dcc912042351377ac5fb32")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 160) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_160 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_160, group)) + ABORT; + + + /* Curve P-192 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")) + ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) + ABORT; + if (!EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-192 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 192) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_192 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_192, group)) + ABORT; + + + /* Curve P-224 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")) + ABORT; + if (!BN_hex2bn(&b, "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")) + ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) + ABORT; + if (!EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) + ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-224 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 224) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_224 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_224, group)) + ABORT; + + + /* Curve P-256 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF")) + ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")) + ABORT; + if (!BN_hex2bn(&b, "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")) + ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) + ABORT; + if (!EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" + "84F3B9CAC2FC632551")) ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-256 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5")) + ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 256) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_256 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_256, group)) + ABORT; + + + /* Curve P-384 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF")) ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")) ABORT; + if (!BN_hex2bn(&b, "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141" + "120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")) ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" + "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; + if (!EC_POINT_set_compressed_coordinates(group, P, x, 1, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-384 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A14" + "7CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F")) ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 384) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_384 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_384, group)) + ABORT; + + + /* Curve P-521 (FIPS PUB 186-2, App. 6) */ + + if (!BN_hex2bn(&p, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF")) ABORT; + if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) + ABORT; + if (!BN_hex2bn(&a, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFFFFFFFFC")) ABORT; + if (!BN_hex2bn(&b, "051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B" + "315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573" + "DF883D2C34F1EF451FD46B503F00")) ABORT; + if (!EC_GROUP_set_curve(group, p, a, b, ctx)) + ABORT; + + if (!BN_hex2bn(&x, "C6858E06B70404E9CD9E3ECB662395B4429C648139053F" + "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" + "3C1856A429BF97E7E31C2E5BD66")) ABORT; + if (!EC_POINT_set_compressed_coordinates(group, P, x, 0, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" + "C9B8899C47AEBB6FB71E91386409")) ABORT; + if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) + ABORT; + + if (!EC_POINT_get_affine_coordinates(group, P, x, y, ctx)) + ABORT; + fprintf(stdout, "\nNIST curve P-521 -- Generator:\n x = 0x"); + BN_print_fp(stdout, x); + fprintf(stdout, "\n y = 0x"); + BN_print_fp(stdout, y); + fprintf(stdout, "\n"); + /* G_y value taken from the standard: */ + if (!BN_hex2bn(&z, "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579" + "B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C" + "7086A272C24088BE94769FD16650")) ABORT; + if (0 != BN_cmp(y, z)) + ABORT; + + fprintf(stdout, "verify degree ..."); + if (EC_GROUP_get_degree(group) != 521) + ABORT; + fprintf(stdout, " ok\n"); + + group_order_tests(group); + + if (!(P_521 = EC_GROUP_new(EC_GROUP_method_of(group)))) + ABORT; + if (!EC_GROUP_copy(P_521, group)) + ABORT; + + + /* more tests using the last curve */ + fprintf(stdout, "infinity tests ..."); + fflush(stdout); + if (!EC_POINT_copy(Q, P)) + ABORT; + if (EC_POINT_is_at_infinity(group, Q)) + ABORT; + /* P := 2P */ + if (!EC_POINT_dbl(group, P, P, ctx)) + ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) + ABORT; + /* Q := -P */ + if (!EC_POINT_invert(group, Q, ctx)) + ABORT; + /* R := 2P - P = P */ + if (!EC_POINT_add(group, R, P, Q, ctx)) + ABORT; + /* R := R + Q = P - P = infty */ + if (!EC_POINT_add(group, R, R, Q, ctx)) + ABORT; + if (!EC_POINT_is_at_infinity(group, R)) + ABORT; + fprintf(stdout, " ok\n\n"); + + if (ctx) + BN_CTX_free(ctx); + BN_free(p); + BN_free(a); + BN_free(b); + EC_GROUP_free(group); + EC_POINT_free(P); + EC_POINT_free(Q); + EC_POINT_free(R); + BN_free(x); + BN_free(y); + BN_free(z); + + if (P_160) + EC_GROUP_free(P_160); + if (P_192) + EC_GROUP_free(P_192); + if (P_224) + EC_GROUP_free(P_224); + if (P_256) + EC_GROUP_free(P_256); + if (P_384) + EC_GROUP_free(P_384); + if (P_521) + EC_GROUP_free(P_521); + +} + +static void +internal_curve_test(void) +{ + EC_builtin_curve *curves = NULL; + size_t crv_len = 0, n = 0; + int ok = 1; + + crv_len = EC_get_builtin_curves(NULL, 0); + + curves = reallocarray(NULL, sizeof(EC_builtin_curve), crv_len); + + if (curves == NULL) + return; + + if (!EC_get_builtin_curves(curves, crv_len)) { + free(curves); + return; + } + + fprintf(stdout, "testing internal curves: "); + + for (n = 0; n < crv_len; n++) { + EC_GROUP *group = NULL; + int nid = curves[n].nid; + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) { + ok = 0; + fprintf(stdout, "\nEC_GROUP_new_curve_name() failed with" + " curve %s\n", OBJ_nid2sn(nid)); + /* try next curve */ + continue; + } + if (!EC_GROUP_check(group, NULL)) { + ok = 0; + fprintf(stdout, "\nEC_GROUP_check() failed with" + " curve %s\n", OBJ_nid2sn(nid)); + EC_GROUP_free(group); + /* try the next curve */ + continue; + } + fprintf(stdout, "."); + fflush(stdout); + EC_GROUP_free(group); + } + if (ok) + fprintf(stdout, " ok\n\n"); + else { + fprintf(stdout, " failed\n\n"); + ABORT; + } + free(curves); + return; +} + +int +main(int argc, char *argv[]) +{ + ERR_load_crypto_strings(); + + prime_field_tests(); + puts(""); + /* test the internal curves */ + internal_curve_test(); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + ERR_remove_thread_state(NULL); + CRYPTO_mem_leaks_fp(stderr); + + return 0; +} diff --git a/tests/ed25519test.c b/tests/ed25519test.c new file mode 100644 index 0000000..78ed85c --- /dev/null +++ b/tests/ed25519test.c @@ -0,0 +1,474 @@ +/* $OpenBSD: ed25519test.c,v 1.10 2022/12/01 13:55:22 tb Exp $ */ +/* + * Copyright (c) 2019, 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +struct testvector { + const uint8_t sec_key[ED25519_PRIVATE_KEY_LENGTH]; + const uint8_t pub_key[ED25519_PUBLIC_KEY_LENGTH]; + const uint8_t signature[ED25519_SIGNATURE_LENGTH]; + const uint8_t message[1024]; + size_t message_len; +}; + +/* + * Test vectors from https://tools.ietf.org/html/rfc8032#section-7.1. + */ +static const struct testvector testvectors[] = { + { + .sec_key = { + 0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, + 0xba, 0x84, 0x4a, 0xf4, 0x92, 0xec, 0x2c, 0xc4, + 0x44, 0x49, 0xc5, 0x69, 0x7b, 0x32, 0x69, 0x19, + 0x70, 0x3b, 0xac, 0x03, 0x1c, 0xae, 0x7f, 0x60, + }, + .pub_key = { + 0xd7, 0x5a, 0x98, 0x01, 0x82, 0xb1, 0x0a, 0xb7, + 0xd5, 0x4b, 0xfe, 0xd3, 0xc9, 0x64, 0x07, 0x3a, + 0x0e, 0xe1, 0x72, 0xf3, 0xda, 0xa6, 0x23, 0x25, + 0xaf, 0x02, 0x1a, 0x68, 0xf7, 0x07, 0x51, 0x1a, + }, + .message = { + 0x0, /* Windows has stupid compilers... */ + }, + .message_len = 0, + .signature = { + 0xe5, 0x56, 0x43, 0x00, 0xc3, 0x60, 0xac, 0x72, + 0x90, 0x86, 0xe2, 0xcc, 0x80, 0x6e, 0x82, 0x8a, + 0x84, 0x87, 0x7f, 0x1e, 0xb8, 0xe5, 0xd9, 0x74, + 0xd8, 0x73, 0xe0, 0x65, 0x22, 0x49, 0x01, 0x55, + 0x5f, 0xb8, 0x82, 0x15, 0x90, 0xa3, 0x3b, 0xac, + 0xc6, 0x1e, 0x39, 0x70, 0x1c, 0xf9, 0xb4, 0x6b, + 0xd2, 0x5b, 0xf5, 0xf0, 0x59, 0x5b, 0xbe, 0x24, + 0x65, 0x51, 0x41, 0x43, 0x8e, 0x7a, 0x10, 0x0b, + }, + }, + { + .sec_key = { + 0x4c, 0xcd, 0x08, 0x9b, 0x28, 0xff, 0x96, 0xda, + 0x9d, 0xb6, 0xc3, 0x46, 0xec, 0x11, 0x4e, 0x0f, + 0x5b, 0x8a, 0x31, 0x9f, 0x35, 0xab, 0xa6, 0x24, + 0xda, 0x8c, 0xf6, 0xed, 0x4f, 0xb8, 0xa6, 0xfb, + }, + .pub_key = { + 0x3d, 0x40, 0x17, 0xc3, 0xe8, 0x43, 0x89, 0x5a, + 0x92, 0xb7, 0x0a, 0xa7, 0x4d, 0x1b, 0x7e, 0xbc, + 0x9c, 0x98, 0x2c, 0xcf, 0x2e, 0xc4, 0x96, 0x8c, + 0xc0, 0xcd, 0x55, 0xf1, 0x2a, 0xf4, 0x66, 0x0c, + }, + .message = { + 0x72, + }, + .message_len = 1, + .signature = { + 0x92, 0xa0, 0x09, 0xa9, 0xf0, 0xd4, 0xca, 0xb8, + 0x72, 0x0e, 0x82, 0x0b, 0x5f, 0x64, 0x25, 0x40, + 0xa2, 0xb2, 0x7b, 0x54, 0x16, 0x50, 0x3f, 0x8f, + 0xb3, 0x76, 0x22, 0x23, 0xeb, 0xdb, 0x69, 0xda, + 0x08, 0x5a, 0xc1, 0xe4, 0x3e, 0x15, 0x99, 0x6e, + 0x45, 0x8f, 0x36, 0x13, 0xd0, 0xf1, 0x1d, 0x8c, + 0x38, 0x7b, 0x2e, 0xae, 0xb4, 0x30, 0x2a, 0xee, + 0xb0, 0x0d, 0x29, 0x16, 0x12, 0xbb, 0x0c, 0x00, + }, + }, + { + .sec_key = { + 0xc5, 0xaa, 0x8d, 0xf4, 0x3f, 0x9f, 0x83, 0x7b, + 0xed, 0xb7, 0x44, 0x2f, 0x31, 0xdc, 0xb7, 0xb1, + 0x66, 0xd3, 0x85, 0x35, 0x07, 0x6f, 0x09, 0x4b, + 0x85, 0xce, 0x3a, 0x2e, 0x0b, 0x44, 0x58, 0xf7, + }, + .pub_key = { + 0xfc, 0x51, 0xcd, 0x8e, 0x62, 0x18, 0xa1, 0xa3, + 0x8d, 0xa4, 0x7e, 0xd0, 0x02, 0x30, 0xf0, 0x58, + 0x08, 0x16, 0xed, 0x13, 0xba, 0x33, 0x03, 0xac, + 0x5d, 0xeb, 0x91, 0x15, 0x48, 0x90, 0x80, 0x25, + }, + .message = { + 0xaf, 0x82, + }, + .message_len = 2, + .signature = { + 0x62, 0x91, 0xd6, 0x57, 0xde, 0xec, 0x24, 0x02, + 0x48, 0x27, 0xe6, 0x9c, 0x3a, 0xbe, 0x01, 0xa3, + 0x0c, 0xe5, 0x48, 0xa2, 0x84, 0x74, 0x3a, 0x44, + 0x5e, 0x36, 0x80, 0xd7, 0xdb, 0x5a, 0xc3, 0xac, + 0x18, 0xff, 0x9b, 0x53, 0x8d, 0x16, 0xf2, 0x90, + 0xae, 0x67, 0xf7, 0x60, 0x98, 0x4d, 0xc6, 0x59, + 0x4a, 0x7c, 0x15, 0xe9, 0x71, 0x6e, 0xd2, 0x8d, + 0xc0, 0x27, 0xbe, 0xce, 0xea, 0x1e, 0xc4, 0x0a, + }, + }, + { + .sec_key = { + 0xf5, 0xe5, 0x76, 0x7c, 0xf1, 0x53, 0x31, 0x95, + 0x17, 0x63, 0x0f, 0x22, 0x68, 0x76, 0xb8, 0x6c, + 0x81, 0x60, 0xcc, 0x58, 0x3b, 0xc0, 0x13, 0x74, + 0x4c, 0x6b, 0xf2, 0x55, 0xf5, 0xcc, 0x0e, 0xe5, + }, + .pub_key = { + 0x27, 0x81, 0x17, 0xfc, 0x14, 0x4c, 0x72, 0x34, + 0x0f, 0x67, 0xd0, 0xf2, 0x31, 0x6e, 0x83, 0x86, + 0xce, 0xff, 0xbf, 0x2b, 0x24, 0x28, 0xc9, 0xc5, + 0x1f, 0xef, 0x7c, 0x59, 0x7f, 0x1d, 0x42, 0x6e, + }, + .message = { + 0x08, 0xb8, 0xb2, 0xb7, 0x33, 0x42, 0x42, 0x43, + 0x76, 0x0f, 0xe4, 0x26, 0xa4, 0xb5, 0x49, 0x08, + 0x63, 0x21, 0x10, 0xa6, 0x6c, 0x2f, 0x65, 0x91, + 0xea, 0xbd, 0x33, 0x45, 0xe3, 0xe4, 0xeb, 0x98, + 0xfa, 0x6e, 0x26, 0x4b, 0xf0, 0x9e, 0xfe, 0x12, + 0xee, 0x50, 0xf8, 0xf5, 0x4e, 0x9f, 0x77, 0xb1, + 0xe3, 0x55, 0xf6, 0xc5, 0x05, 0x44, 0xe2, 0x3f, + 0xb1, 0x43, 0x3d, 0xdf, 0x73, 0xbe, 0x84, 0xd8, + 0x79, 0xde, 0x7c, 0x00, 0x46, 0xdc, 0x49, 0x96, + 0xd9, 0xe7, 0x73, 0xf4, 0xbc, 0x9e, 0xfe, 0x57, + 0x38, 0x82, 0x9a, 0xdb, 0x26, 0xc8, 0x1b, 0x37, + 0xc9, 0x3a, 0x1b, 0x27, 0x0b, 0x20, 0x32, 0x9d, + 0x65, 0x86, 0x75, 0xfc, 0x6e, 0xa5, 0x34, 0xe0, + 0x81, 0x0a, 0x44, 0x32, 0x82, 0x6b, 0xf5, 0x8c, + 0x94, 0x1e, 0xfb, 0x65, 0xd5, 0x7a, 0x33, 0x8b, + 0xbd, 0x2e, 0x26, 0x64, 0x0f, 0x89, 0xff, 0xbc, + 0x1a, 0x85, 0x8e, 0xfc, 0xb8, 0x55, 0x0e, 0xe3, + 0xa5, 0xe1, 0x99, 0x8b, 0xd1, 0x77, 0xe9, 0x3a, + 0x73, 0x63, 0xc3, 0x44, 0xfe, 0x6b, 0x19, 0x9e, + 0xe5, 0xd0, 0x2e, 0x82, 0xd5, 0x22, 0xc4, 0xfe, + 0xba, 0x15, 0x45, 0x2f, 0x80, 0x28, 0x8a, 0x82, + 0x1a, 0x57, 0x91, 0x16, 0xec, 0x6d, 0xad, 0x2b, + 0x3b, 0x31, 0x0d, 0xa9, 0x03, 0x40, 0x1a, 0xa6, + 0x21, 0x00, 0xab, 0x5d, 0x1a, 0x36, 0x55, 0x3e, + 0x06, 0x20, 0x3b, 0x33, 0x89, 0x0c, 0xc9, 0xb8, + 0x32, 0xf7, 0x9e, 0xf8, 0x05, 0x60, 0xcc, 0xb9, + 0xa3, 0x9c, 0xe7, 0x67, 0x96, 0x7e, 0xd6, 0x28, + 0xc6, 0xad, 0x57, 0x3c, 0xb1, 0x16, 0xdb, 0xef, + 0xef, 0xd7, 0x54, 0x99, 0xda, 0x96, 0xbd, 0x68, + 0xa8, 0xa9, 0x7b, 0x92, 0x8a, 0x8b, 0xbc, 0x10, + 0x3b, 0x66, 0x21, 0xfc, 0xde, 0x2b, 0xec, 0xa1, + 0x23, 0x1d, 0x20, 0x6b, 0xe6, 0xcd, 0x9e, 0xc7, + 0xaf, 0xf6, 0xf6, 0xc9, 0x4f, 0xcd, 0x72, 0x04, + 0xed, 0x34, 0x55, 0xc6, 0x8c, 0x83, 0xf4, 0xa4, + 0x1d, 0xa4, 0xaf, 0x2b, 0x74, 0xef, 0x5c, 0x53, + 0xf1, 0xd8, 0xac, 0x70, 0xbd, 0xcb, 0x7e, 0xd1, + 0x85, 0xce, 0x81, 0xbd, 0x84, 0x35, 0x9d, 0x44, + 0x25, 0x4d, 0x95, 0x62, 0x9e, 0x98, 0x55, 0xa9, + 0x4a, 0x7c, 0x19, 0x58, 0xd1, 0xf8, 0xad, 0xa5, + 0xd0, 0x53, 0x2e, 0xd8, 0xa5, 0xaa, 0x3f, 0xb2, + 0xd1, 0x7b, 0xa7, 0x0e, 0xb6, 0x24, 0x8e, 0x59, + 0x4e, 0x1a, 0x22, 0x97, 0xac, 0xbb, 0xb3, 0x9d, + 0x50, 0x2f, 0x1a, 0x8c, 0x6e, 0xb6, 0xf1, 0xce, + 0x22, 0xb3, 0xde, 0x1a, 0x1f, 0x40, 0xcc, 0x24, + 0x55, 0x41, 0x19, 0xa8, 0x31, 0xa9, 0xaa, 0xd6, + 0x07, 0x9c, 0xad, 0x88, 0x42, 0x5d, 0xe6, 0xbd, + 0xe1, 0xa9, 0x18, 0x7e, 0xbb, 0x60, 0x92, 0xcf, + 0x67, 0xbf, 0x2b, 0x13, 0xfd, 0x65, 0xf2, 0x70, + 0x88, 0xd7, 0x8b, 0x7e, 0x88, 0x3c, 0x87, 0x59, + 0xd2, 0xc4, 0xf5, 0xc6, 0x5a, 0xdb, 0x75, 0x53, + 0x87, 0x8a, 0xd5, 0x75, 0xf9, 0xfa, 0xd8, 0x78, + 0xe8, 0x0a, 0x0c, 0x9b, 0xa6, 0x3b, 0xcb, 0xcc, + 0x27, 0x32, 0xe6, 0x94, 0x85, 0xbb, 0xc9, 0xc9, + 0x0b, 0xfb, 0xd6, 0x24, 0x81, 0xd9, 0x08, 0x9b, + 0xec, 0xcf, 0x80, 0xcf, 0xe2, 0xdf, 0x16, 0xa2, + 0xcf, 0x65, 0xbd, 0x92, 0xdd, 0x59, 0x7b, 0x07, + 0x07, 0xe0, 0x91, 0x7a, 0xf4, 0x8b, 0xbb, 0x75, + 0xfe, 0xd4, 0x13, 0xd2, 0x38, 0xf5, 0x55, 0x5a, + 0x7a, 0x56, 0x9d, 0x80, 0xc3, 0x41, 0x4a, 0x8d, + 0x08, 0x59, 0xdc, 0x65, 0xa4, 0x61, 0x28, 0xba, + 0xb2, 0x7a, 0xf8, 0x7a, 0x71, 0x31, 0x4f, 0x31, + 0x8c, 0x78, 0x2b, 0x23, 0xeb, 0xfe, 0x80, 0x8b, + 0x82, 0xb0, 0xce, 0x26, 0x40, 0x1d, 0x2e, 0x22, + 0xf0, 0x4d, 0x83, 0xd1, 0x25, 0x5d, 0xc5, 0x1a, + 0xdd, 0xd3, 0xb7, 0x5a, 0x2b, 0x1a, 0xe0, 0x78, + 0x45, 0x04, 0xdf, 0x54, 0x3a, 0xf8, 0x96, 0x9b, + 0xe3, 0xea, 0x70, 0x82, 0xff, 0x7f, 0xc9, 0x88, + 0x8c, 0x14, 0x4d, 0xa2, 0xaf, 0x58, 0x42, 0x9e, + 0xc9, 0x60, 0x31, 0xdb, 0xca, 0xd3, 0xda, 0xd9, + 0xaf, 0x0d, 0xcb, 0xaa, 0xaf, 0x26, 0x8c, 0xb8, + 0xfc, 0xff, 0xea, 0xd9, 0x4f, 0x3c, 0x7c, 0xa4, + 0x95, 0xe0, 0x56, 0xa9, 0xb4, 0x7a, 0xcd, 0xb7, + 0x51, 0xfb, 0x73, 0xe6, 0x66, 0xc6, 0xc6, 0x55, + 0xad, 0xe8, 0x29, 0x72, 0x97, 0xd0, 0x7a, 0xd1, + 0xba, 0x5e, 0x43, 0xf1, 0xbc, 0xa3, 0x23, 0x01, + 0x65, 0x13, 0x39, 0xe2, 0x29, 0x04, 0xcc, 0x8c, + 0x42, 0xf5, 0x8c, 0x30, 0xc0, 0x4a, 0xaf, 0xdb, + 0x03, 0x8d, 0xda, 0x08, 0x47, 0xdd, 0x98, 0x8d, + 0xcd, 0xa6, 0xf3, 0xbf, 0xd1, 0x5c, 0x4b, 0x4c, + 0x45, 0x25, 0x00, 0x4a, 0xa0, 0x6e, 0xef, 0xf8, + 0xca, 0x61, 0x78, 0x3a, 0xac, 0xec, 0x57, 0xfb, + 0x3d, 0x1f, 0x92, 0xb0, 0xfe, 0x2f, 0xd1, 0xa8, + 0x5f, 0x67, 0x24, 0x51, 0x7b, 0x65, 0xe6, 0x14, + 0xad, 0x68, 0x08, 0xd6, 0xf6, 0xee, 0x34, 0xdf, + 0xf7, 0x31, 0x0f, 0xdc, 0x82, 0xae, 0xbf, 0xd9, + 0x04, 0xb0, 0x1e, 0x1d, 0xc5, 0x4b, 0x29, 0x27, + 0x09, 0x4b, 0x2d, 0xb6, 0x8d, 0x6f, 0x90, 0x3b, + 0x68, 0x40, 0x1a, 0xde, 0xbf, 0x5a, 0x7e, 0x08, + 0xd7, 0x8f, 0xf4, 0xef, 0x5d, 0x63, 0x65, 0x3a, + 0x65, 0x04, 0x0c, 0xf9, 0xbf, 0xd4, 0xac, 0xa7, + 0x98, 0x4a, 0x74, 0xd3, 0x71, 0x45, 0x98, 0x67, + 0x80, 0xfc, 0x0b, 0x16, 0xac, 0x45, 0x16, 0x49, + 0xde, 0x61, 0x88, 0xa7, 0xdb, 0xdf, 0x19, 0x1f, + 0x64, 0xb5, 0xfc, 0x5e, 0x2a, 0xb4, 0x7b, 0x57, + 0xf7, 0xf7, 0x27, 0x6c, 0xd4, 0x19, 0xc1, 0x7a, + 0x3c, 0xa8, 0xe1, 0xb9, 0x39, 0xae, 0x49, 0xe4, + 0x88, 0xac, 0xba, 0x6b, 0x96, 0x56, 0x10, 0xb5, + 0x48, 0x01, 0x09, 0xc8, 0xb1, 0x7b, 0x80, 0xe1, + 0xb7, 0xb7, 0x50, 0xdf, 0xc7, 0x59, 0x8d, 0x5d, + 0x50, 0x11, 0xfd, 0x2d, 0xcc, 0x56, 0x00, 0xa3, + 0x2e, 0xf5, 0xb5, 0x2a, 0x1e, 0xcc, 0x82, 0x0e, + 0x30, 0x8a, 0xa3, 0x42, 0x72, 0x1a, 0xac, 0x09, + 0x43, 0xbf, 0x66, 0x86, 0xb6, 0x4b, 0x25, 0x79, + 0x37, 0x65, 0x04, 0xcc, 0xc4, 0x93, 0xd9, 0x7e, + 0x6a, 0xed, 0x3f, 0xb0, 0xf9, 0xcd, 0x71, 0xa4, + 0x3d, 0xd4, 0x97, 0xf0, 0x1f, 0x17, 0xc0, 0xe2, + 0xcb, 0x37, 0x97, 0xaa, 0x2a, 0x2f, 0x25, 0x66, + 0x56, 0x16, 0x8e, 0x6c, 0x49, 0x6a, 0xfc, 0x5f, + 0xb9, 0x32, 0x46, 0xf6, 0xb1, 0x11, 0x63, 0x98, + 0xa3, 0x46, 0xf1, 0xa6, 0x41, 0xf3, 0xb0, 0x41, + 0xe9, 0x89, 0xf7, 0x91, 0x4f, 0x90, 0xcc, 0x2c, + 0x7f, 0xff, 0x35, 0x78, 0x76, 0xe5, 0x06, 0xb5, + 0x0d, 0x33, 0x4b, 0xa7, 0x7c, 0x22, 0x5b, 0xc3, + 0x07, 0xba, 0x53, 0x71, 0x52, 0xf3, 0xf1, 0x61, + 0x0e, 0x4e, 0xaf, 0xe5, 0x95, 0xf6, 0xd9, 0xd9, + 0x0d, 0x11, 0xfa, 0xa9, 0x33, 0xa1, 0x5e, 0xf1, + 0x36, 0x95, 0x46, 0x86, 0x8a, 0x7f, 0x3a, 0x45, + 0xa9, 0x67, 0x68, 0xd4, 0x0f, 0xd9, 0xd0, 0x34, + 0x12, 0xc0, 0x91, 0xc6, 0x31, 0x5c, 0xf4, 0xfd, + 0xe7, 0xcb, 0x68, 0x60, 0x69, 0x37, 0x38, 0x0d, + 0xb2, 0xea, 0xaa, 0x70, 0x7b, 0x4c, 0x41, 0x85, + 0xc3, 0x2e, 0xdd, 0xcd, 0xd3, 0x06, 0x70, 0x5e, + 0x4d, 0xc1, 0xff, 0xc8, 0x72, 0xee, 0xee, 0x47, + 0x5a, 0x64, 0xdf, 0xac, 0x86, 0xab, 0xa4, 0x1c, + 0x06, 0x18, 0x98, 0x3f, 0x87, 0x41, 0xc5, 0xef, + 0x68, 0xd3, 0xa1, 0x01, 0xe8, 0xa3, 0xb8, 0xca, + 0xc6, 0x0c, 0x90, 0x5c, 0x15, 0xfc, 0x91, 0x08, + 0x40, 0xb9, 0x4c, 0x00, 0xa0, 0xb9, 0xd0, + }, + .message_len = 1023, + .signature = { + 0x0a, 0xab, 0x4c, 0x90, 0x05, 0x01, 0xb3, 0xe2, + 0x4d, 0x7c, 0xdf, 0x46, 0x63, 0x32, 0x6a, 0x3a, + 0x87, 0xdf, 0x5e, 0x48, 0x43, 0xb2, 0xcb, 0xdb, + 0x67, 0xcb, 0xf6, 0xe4, 0x60, 0xfe, 0xc3, 0x50, + 0xaa, 0x53, 0x71, 0xb1, 0x50, 0x8f, 0x9f, 0x45, + 0x28, 0xec, 0xea, 0x23, 0xc4, 0x36, 0xd9, 0x4b, + 0x5e, 0x8f, 0xcd, 0x4f, 0x68, 0x1e, 0x30, 0xa6, + 0xac, 0x00, 0xa9, 0x70, 0x4a, 0x18, 0x8a, 0x03, + }, + }, + { + .sec_key = { + 0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, + 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e, + 0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, + 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42, + }, + .pub_key = { + 0xec, 0x17, 0x2b, 0x93, 0xad, 0x5e, 0x56, 0x3b, + 0xf4, 0x93, 0x2c, 0x70, 0xe1, 0x24, 0x50, 0x34, + 0xc3, 0x54, 0x67, 0xef, 0x2e, 0xfd, 0x4d, 0x64, + 0xeb, 0xf8, 0x19, 0x68, 0x34, 0x67, 0xe2, 0xbf, + }, + .message = { + 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f, + }, + .message_len = 64, + .signature = { + 0xdc, 0x2a, 0x44, 0x59, 0xe7, 0x36, 0x96, 0x33, + 0xa5, 0x2b, 0x1b, 0xf2, 0x77, 0x83, 0x9a, 0x00, + 0x20, 0x10, 0x09, 0xa3, 0xef, 0xbf, 0x3e, 0xcb, + 0x69, 0xbe, 0xa2, 0x18, 0x6c, 0x26, 0xb5, 0x89, + 0x09, 0x35, 0x1f, 0xc9, 0xac, 0x90, 0xb3, 0xec, + 0xfd, 0xfb, 0xc7, 0xc6, 0x64, 0x31, 0xe0, 0x30, + 0x3d, 0xca, 0x17, 0x9c, 0x13, 0x8a, 0xc1, 0x7a, + 0xd9, 0xbe, 0xf1, 0x17, 0x73, 0x31, 0xa7, 0x04, + }, + }, +}; + +const size_t num_testvectors = sizeof(testvectors) / sizeof(testvectors[0]); + +static int +test_ED25519_verify(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < num_testvectors; i++) { + const struct testvector *tc = &testvectors[i]; + + if (!ED25519_verify(tc->message, tc->message_len, tc->signature, + tc->pub_key)) { + warnx("failed verification in test case %zu", i); + failed = 1; + } + } + + return failed; +} + +static int +test_ED25519_sign(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < num_testvectors; i++) { + const struct testvector *tc = &testvectors[i]; + uint8_t signature[64]; + + if (!ED25519_sign(signature, tc->message, tc->message_len, + tc->pub_key, tc->sec_key)) { + warnx("failed signature in test case %zu", i); + failed = 1; + } + + if (memcmp(tc->signature, signature, sizeof signature) != 0) { + warnx("signature mismatch in test case %zu", i); + failed = 1; + } + } + + return failed; +} + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static void +dump_info(const uint8_t *message, size_t message_len, const uint8_t *public_key, + const uint8_t *private_key, const uint8_t *signature) +{ + + fprintf(stderr, "message:\n"); + hexdump(message, message_len); + + fprintf(stderr, "public key:\n"); + hexdump(public_key, ED25519_PUBLIC_KEY_LENGTH); + fprintf(stderr, "private key:\n"); + hexdump(private_key, ED25519_PRIVATE_KEY_LENGTH); + + if (signature != NULL) { + fprintf(stderr, "signature:\n"); + hexdump(signature, ED25519_SIGNATURE_LENGTH); + } +} + +/* + * Little-endian representation of the order of edwards25519, + * see https://www.rfc-editor.org/rfc/rfc7748#section-4.1 + */ +static const uint8_t order[] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, +}; + +/* + * Modify signature by adding the group order to the upper half of the + * signature. This is caught by the check added in curve25519.c r1.14. + */ +static void +modify_signature(uint8_t *signature) +{ + uint16_t sum; + uint8_t *upper_half = &signature[32]; + uint16_t carry = 0; + size_t i; + + for (i = 0; i < sizeof(order); i++) { + sum = carry + order[i] + upper_half[i]; + carry = (sum > 0xff); + upper_half[i] = sum & 0xff; + } + + /* carry == 0 since 0 <= upper_half < order and 2 * order < 2^256. */ +} + +static int +test_ED25519_signature_malleability(void) +{ + uint8_t public_key[ED25519_PUBLIC_KEY_LENGTH]; + uint8_t private_key[ED25519_PRIVATE_KEY_LENGTH]; + uint8_t message[32]; + uint8_t signature[ED25519_SIGNATURE_LENGTH]; + int failed = 1; + + ED25519_keypair(public_key, private_key); + arc4random_buf(message, sizeof(message)); + + if (!ED25519_sign(signature, message, sizeof(message), + public_key, private_key)) { + fprintf(stderr, "Failed to sign random message\n"); + dump_info(message, sizeof(message), public_key, private_key, + NULL); + goto err; + } + + if (!ED25519_verify(message, sizeof(message), signature, public_key)) { + fprintf(stderr, "Failed to verify random message\n"); + dump_info(message, sizeof(message), public_key, private_key, + signature); + goto err; + } + + modify_signature(signature); + + if (ED25519_verify(message, sizeof(message), signature, public_key)) { + fprintf(stderr, "Verified with modified signature\n"); + dump_info(message, sizeof(message), public_key, private_key, + signature); + goto err; + } + + failed = 0; + + err: + return failed; +} + +int +main(int argc, char *argv[]) +{ + int failed = 0; + + failed |= test_ED25519_verify(); + failed |= test_ED25519_sign(); + failed |= test_ED25519_signature_malleability(); + + return failed; +} diff --git a/tests/empty.c b/tests/empty.c new file mode 100644 index 0000000..e69de29 diff --git a/tests/enginetest.c b/tests/enginetest.c new file mode 100644 index 0000000..9afae39 --- /dev/null +++ b/tests/enginetest.c @@ -0,0 +1,253 @@ +/* $OpenBSD: enginetest.c,v 1.10 2023/06/19 18:52:29 tb Exp $ */ +/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL + * project 2000. + */ +/* ==================================================================== + * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include + +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#include + +static void display_engine_list(void) +{ + ENGINE *h; + int loop; + + h = ENGINE_get_first(); + loop = 0; + printf("listing available engine types\n"); + while (h) { + printf("engine %d, id = \"%s\", name = \"%s\"\n", + loop++, ENGINE_get_id(h), ENGINE_get_name(h)); + h = ENGINE_get_next(h); + } + + printf("end of list\n"); + /* + * ENGINE_get_first() increases the struct_ref counter, so we must call + * ENGINE_free() to decrease it again + */ + ENGINE_free(h); +} + +int main(int argc, char *argv[]) +{ + ENGINE *block[512]; + char *id, *name; + ENGINE *ptr; + int loop; + int to_return = 1; + ENGINE *new_h1 = NULL; + ENGINE *new_h2 = NULL; + ENGINE *new_h3 = NULL; + ENGINE *new_h4 = NULL; + + ERR_load_crypto_strings(); + + memset(block, 0, 512 * sizeof(ENGINE *)); + if (((new_h1 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h1, "test_id0") || + !ENGINE_set_name(new_h1, "First test item") || + ((new_h2 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h2, "test_id1") || + !ENGINE_set_name(new_h2, "Second test item") || + ((new_h3 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h3, "test_id2") || + !ENGINE_set_name(new_h3, "Third test item") || + ((new_h4 = ENGINE_new()) == NULL) || + !ENGINE_set_id(new_h4, "test_id3") || + !ENGINE_set_name(new_h4, "Fourth test item")) { + printf("Couldn't set up test ENGINE structures\n"); + goto end; + } + + printf("\nenginetest beginning\n\n"); + display_engine_list(); + if (!ENGINE_add(new_h1)) { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + ptr = ENGINE_get_first(); + if (!ENGINE_remove(ptr)) { + printf("Remove failed!\n"); + goto end; + } + ENGINE_free(ptr); + display_engine_list(); + if (!ENGINE_add(new_h3) || !ENGINE_add(new_h2)) { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + if (!ENGINE_remove(new_h2)) { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if (!ENGINE_add(new_h4)) { + printf("Add failed!\n"); + goto end; + } + display_engine_list(); + if (ENGINE_add(new_h3)) { + printf("Add *should* have failed but didn't!\n"); + goto end; + } else + printf("Add that should fail did.\n"); + ERR_clear_error(); + if (ENGINE_remove(new_h2)) { + printf("Remove *should* have failed but didn't!\n"); + goto end; + } else + printf("Remove that should fail did.\n"); + ERR_clear_error(); + if (!ENGINE_remove(new_h3)) { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + if (!ENGINE_remove(new_h4)) { + printf("Remove failed!\n"); + goto end; + } + display_engine_list(); + /* + * Depending on whether there's any hardware support compiled + * in, this remove may be destined to fail. + */ + ptr = ENGINE_get_first(); + if (ptr) + if (!ENGINE_remove(ptr)) + printf("Remove failed!i - probably no hardware " + "support present.\n"); + ENGINE_free(ptr); + display_engine_list(); + + if (!ENGINE_add(new_h1) || !ENGINE_remove(new_h1)) { + printf("Couldn't add and remove to an empty list!\n"); + goto end; + } else + printf("Successfully added and removed to an empty list!\n"); + + printf("About to beef up the engine-type list\n"); + for (loop = 0; loop < 512; loop++) { + if (asprintf(&id, "id%d", loop) == -1) + goto end; + if (asprintf(&name, "Fake engine type %d", loop) == -1) + goto end; + + if (((block[loop] = ENGINE_new()) == NULL) || + !id || !ENGINE_set_id(block[loop], id) || + !name || !ENGINE_set_name(block[loop], name)) { + printf("Couldn't create block of ENGINE structures.\n"); + goto end; + } + } + + for (loop = 0; loop < 512; loop++) { + if (!ENGINE_add(block[loop])) { + printf("\nAdding stopped at %d, (%s,%s)\n", + loop, ENGINE_get_id(block[loop]), + ENGINE_get_name(block[loop])); + break; + } + printf("."); + fflush(stdout); + } + printf("\nAbout to empty the engine-type list\n"); + while ((ptr = ENGINE_get_first()) != NULL) { + if (!ENGINE_remove(ptr)) { + printf("\nRemove failed!\n"); + goto end; + } + ENGINE_free(ptr); + printf("."); fflush(stdout); + } + for (loop = 0; loop < 512; loop++) { + free((void *)ENGINE_get_id(block[loop])); + free((void *)ENGINE_get_name(block[loop])); + } + printf("\nTests completed happily\n"); + to_return = 0; +end: + if (to_return) + ERR_print_errors_fp(stderr); + ENGINE_free(new_h1); + ENGINE_free(new_h2); + ENGINE_free(new_h3); + ENGINE_free(new_h4); + for (loop = 0; loop < 512; loop++) + ENGINE_free(block[loop]); + ENGINE_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + ERR_remove_thread_state(NULL); + CRYPTO_mem_leaks_fp(stderr); + return to_return; +} +#else +int +main(void) +{ + printf("ENGINE support is disabled\n"); + return 0; +} +#endif diff --git a/tests/evp_ecx_test.c b/tests/evp_ecx_test.c new file mode 100644 index 0000000..b28378b --- /dev/null +++ b/tests/evp_ecx_test.c @@ -0,0 +1,831 @@ +/* $OpenBSD: evp_ecx_test.c,v 1.5 2023/03/02 20:04:42 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include "curve25519_internal.h" + +static const uint8_t ed25519_priv_key_1[] = + "-----BEGIN PRIVATE KEY-----\n" + "MC4CAQAwBQYDK2VwBCIEIIkDg89yB70IpUXsAZieCcCDE2ig9nin9JJWpDQoCup8\n" + "-----END PRIVATE KEY-----\n"; + +const uint8_t ed25519_raw_priv_key_1[] = { + 0x89, 0x03, 0x83, 0xcf, 0x72, 0x07, 0xbd, 0x08, + 0xa5, 0x45, 0xec, 0x01, 0x98, 0x9e, 0x09, 0xc0, + 0x83, 0x13, 0x68, 0xa0, 0xf6, 0x78, 0xa7, 0xf4, + 0x92, 0x56, 0xa4, 0x34, 0x28, 0x0a, 0xea, 0x7c, +}; + +static const uint8_t ed25519_pub_key_1[] = + "-----BEGIN PUBLIC KEY-----\n" + "MCowBQYDK2VwAyEA1vxPpbnoC7G8vFmRjYVXUU2aln3hUZEgfW1atlTHF/o=\n" + "-----END PUBLIC KEY-----\n"; + +const uint8_t ed25519_raw_pub_key_1[] = { + 0xd6, 0xfc, 0x4f, 0xa5, 0xb9, 0xe8, 0x0b, 0xb1, + 0xbc, 0xbc, 0x59, 0x91, 0x8d, 0x85, 0x57, 0x51, + 0x4d, 0x9a, 0x96, 0x7d, 0xe1, 0x51, 0x91, 0x20, + 0x7d, 0x6d, 0x5a, 0xb6, 0x54, 0xc7, 0x17, 0xfa, +}; + +static const uint8_t message_1[] = { + 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, +}; + +static const uint8_t signature_1[] = { + 0x1c, 0xba, 0x71, 0x5a, 0xbc, 0x7f, 0x3b, 0x6b, + 0xc1, 0x61, 0x04, 0x02, 0xb6, 0x37, 0x9e, 0xe1, + 0xa6, 0x7c, 0xfe, 0xcd, 0xdd, 0x68, 0x59, 0xb5, + 0xc8, 0x09, 0xa5, 0x36, 0x66, 0xfb, 0xad, 0xc5, + 0x68, 0x31, 0xd1, 0x7a, 0x48, 0x44, 0xaa, 0xa9, + 0x9c, 0xf1, 0x1a, 0xbb, 0xd5, 0x49, 0xd5, 0xe8, + 0x63, 0xe2, 0x94, 0x77, 0x16, 0x1a, 0x52, 0xfa, + 0x33, 0x6b, 0xf3, 0x57, 0x93, 0xd4, 0xc1, 0x07, +}; + +static const uint8_t x25519_priv_key_1[] = + "-----BEGIN PRIVATE KEY-----\n" + "MC4CAQAwBQYDK2VuBCIEICi6rzFFJb02mi6sopELeshEi2vr68ul4bzEHPOz+K1o\n" + "-----END PRIVATE KEY-----\n"; + +const uint8_t x25519_raw_priv_key_1[] = { + 0x28, 0xba, 0xaf, 0x31, 0x45, 0x25, 0xbd, 0x36, + 0x9a, 0x2e, 0xac, 0xa2, 0x91, 0x0b, 0x7a, 0xc8, + 0x44, 0x8b, 0x6b, 0xeb, 0xeb, 0xcb, 0xa5, 0xe1, + 0xbc, 0xc4, 0x1c, 0xf3, 0xb3, 0xf8, 0xad, 0x68, +}; + +static const uint8_t x25519_pub_key_1[] = + "-----BEGIN PUBLIC KEY-----\n" + "MCowBQYDK2VuAyEAu4WHXnAQL2YfonJhuoEO9PM2WwXjveApPmCXSiDnf1M=\n" + "-----END PUBLIC KEY-----\n"; + +static const uint8_t x25519_raw_pub_key_1[] = { + 0xbb, 0x85, 0x87, 0x5e, 0x70, 0x10, 0x2f, 0x66, + 0x1f, 0xa2, 0x72, 0x61, 0xba, 0x81, 0x0e, 0xf4, + 0xf3, 0x36, 0x5b, 0x05, 0xe3, 0xbd, 0xe0, 0x29, + 0x3e, 0x60, 0x97, 0x4a, 0x20, 0xe7, 0x7f, 0x53, +}; + +static const uint8_t x25519_priv_key_2[] = + "-----BEGIN PRIVATE KEY-----\n" + "MC4CAQAwBQYDK2VuBCIEIAg9Jbp/Ma0TO4r179WGGiv+VnGxGNRh4VNrHUij7Ql/\n" + "-----END PRIVATE KEY-----\n"; + +static const uint8_t x25519_raw_priv_key_2[] = { + 0x08, 0x3d, 0x25, 0xba, 0x7f, 0x31, 0xad, 0x13, + 0x3b, 0x8a, 0xf5, 0xef, 0xd5, 0x86, 0x1a, 0x2b, + 0xfe, 0x56, 0x71, 0xb1, 0x18, 0xd4, 0x61, 0xe1, + 0x53, 0x6b, 0x1d, 0x48, 0xa3, 0xed, 0x09, 0x7f, +}; + +static const uint8_t x25519_pub_key_2[] = + "-----BEGIN PUBLIC KEY-----\n" + "MCowBQYDK2VuAyEABvksGQRgsUXEK5CaniVZ59pPvDoABgBSdAM+EF0Q9Cw=\n" + "-----END PUBLIC KEY-----\n"; + +static const uint8_t x25519_raw_pub_key_2[] = { + 0x06, 0xf9, 0x2c, 0x19, 0x04, 0x60, 0xb1, 0x45, + 0xc4, 0x2b, 0x90, 0x9a, 0x9e, 0x25, 0x59, 0xe7, + 0xda, 0x4f, 0xbc, 0x3a, 0x00, 0x06, 0x00, 0x52, + 0x74, 0x03, 0x3e, 0x10, 0x5d, 0x10, 0xf4, 0x2c, +}; + +static const uint8_t shared_key_1[] = { + 0xa2, 0x61, 0xf5, 0x91, 0x2e, 0x82, 0xbc, 0x98, + 0x6c, 0x85, 0xb6, 0x51, 0x1f, 0x69, 0xdb, 0xfa, + 0x88, 0x6c, 0x4b, 0x9e, 0x3b, 0xb0, 0x71, 0xd1, + 0xf3, 0xea, 0x2a, 0xd0, 0xef, 0xf6, 0xa5, 0x5a, +}; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +ecx_ed25519_keygen_test(void) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio = NULL; + int failed = 1; + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to create ED25519 context\n"); + goto failure; + } + + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + fprintf(stderr, "FAIL: failed to init keygen for ED25519\n"); + goto failure; + } + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) { + fprintf(stderr, "FAIL: failed to generate ED25519 key\n"); + goto failure; + } + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { + fprintf(stderr, "FAIL: failed to write ED25519 to PEM\n"); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); + + return failed; +} + +static int +ecx_ed25519_raw_key_test(void) +{ + EVP_PKEY *pkey = NULL; + uint8_t *priv_key = NULL; + size_t priv_key_len = 0; + uint8_t *pub_key = NULL; + size_t pub_key_len = 0; + const uint8_t *pp; + BIO *bio = NULL; + int failed = 1; + + /* + * Decode private key from PEM and check raw private and raw public. + */ + + if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read private key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw private key len\n"); + goto failure; + } + if (priv_key_len != sizeof(ed25519_raw_priv_key_1)) { + fprintf(stderr, "FAIL: raw private key length differs " + "(%zu != %zu)\n", priv_key_len, + sizeof(ed25519_raw_priv_key_1)); + goto failure; + } + if ((priv_key = malloc(priv_key_len)) == NULL) + errx(1, "failed to malloc priv key"); + if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw private key len\n"); + goto failure; + } + if (memcmp(priv_key, ed25519_raw_priv_key_1, priv_key_len) != 0) { + fprintf(stderr, "FAIL: get raw private key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(priv_key, priv_key_len); + fprintf(stderr, "Want:\n"); + hexdump(ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1)); + goto failure; + } + + if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) { + fprintf(stderr, "FAIL: raw public key length differs " + "(%zu != %zu)\n", pub_key_len, + sizeof(ed25519_raw_pub_key_1)); + goto failure; + } + if ((pub_key = malloc(pub_key_len)) == NULL) + errx(1, "failed to malloc private key"); + if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) { + fprintf(stderr, "FAIL: get raw public key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(pub_key, pub_key_len); + fprintf(stderr, "Want:\n"); + hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1)); + goto failure; + } + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; + + freezero(priv_key, priv_key_len); + priv_key = NULL; + priv_key_len = 0; + + freezero(pub_key, pub_key_len); + pub_key = NULL; + pub_key_len = 0; + + /* + * Decode public key from PEM and check raw private and raw public. + */ + + if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read public key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + /* + * Yet another astounding API design - we cannot tell if the private key + * is not present, or if some other failure occurred. + */ + if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw priv key len\n"); + goto failure; + } + if ((priv_key = malloc(priv_key_len)) == NULL) + errx(1, "failed to malloc priv key"); + if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) { + fprintf(stderr, "FAIL: got raw private key, should fail\n"); + goto failure; + } + + if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (pub_key_len != sizeof(ed25519_raw_pub_key_1)) { + fprintf(stderr, "FAIL: raw public key length differs " + "(%zu != %zu)\n", pub_key_len, + sizeof(ed25519_raw_pub_key_1)); + goto failure; + } + if ((pub_key = malloc(pub_key_len)) == NULL) + errx(1, "failed to malloc private key"); + if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (memcmp(pub_key, ed25519_raw_pub_key_1, pub_key_len) != 0) { + fprintf(stderr, "FAIL: get raw public key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(pub_key, pub_key_len); + fprintf(stderr, "Want:\n"); + hexdump(ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1)); + goto failure; + } + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; + + /* + * Create PKEY from raw private, check PEM encoded private and public. + */ + if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, + ed25519_raw_priv_key_1, sizeof(ed25519_raw_priv_key_1))) == NULL) { + fprintf(stderr, "FAIL: PKEY from raw private key failed"); + goto failure; + } + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { + fprintf(stderr, "FAIL: failed to write ED25519 private to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(ed25519_priv_key_1, pp) != 0) { + fprintf(stderr, "FAIL: resulting private key PEM differs\n"); + goto failure; + } + + (void)BIO_reset(bio); + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(ed25519_pub_key_1, pp) != 0) { + fprintf(stderr, "FAIL: resulting public key PEM differs\n"); + fprintf(stderr, "%s\n", ed25519_pub_key_1); + fprintf(stderr, "%s\n", pp); + //goto failure; + } + + EVP_PKEY_free(pkey); + pkey = NULL; + + /* + * Create PKEY from raw public, check public key PEM. + */ + if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, + ed25519_raw_pub_key_1, sizeof(ed25519_raw_pub_key_1))) == NULL) { + fprintf(stderr, "FAIL: PKEY from raw public key failed"); + goto failure; + } + (void)BIO_reset(bio); + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + fprintf(stderr, "FAIL: failed to write ED25519 public to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(ed25519_pub_key_1, pp) != 0) { + fprintf(stderr, "FAIL: resulting public key PEM differs\n"); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_PKEY_free(pkey); + freezero(priv_key, priv_key_len); + freezero(pub_key, pub_key_len); + + return failed; +} + +static int +ecx_ed25519_sign_test(void) +{ + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *pkey = NULL; + uint8_t *signature = NULL; + size_t signature_len = 0; + BIO *bio = NULL; + int failed = 1; + + if ((bio = BIO_new_mem_buf(ed25519_priv_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read private key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + errx(1, "failed to create MD_CTX"); + + if (!EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, pkey)) { + fprintf(stderr, "FAIL: failed to init digest sign\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + if (!EVP_DigestSign(md_ctx, NULL, &signature_len, NULL, 0)) { + fprintf(stderr, "FAIL: failed to digest sign update\n"); + goto failure; + } + if ((signature = calloc(1, signature_len)) == NULL) + errx(1, "failed to allocate signature"); + if (!EVP_DigestSign(md_ctx, signature, &signature_len, message_1, + sizeof(message_1))) { + fprintf(stderr, "FAIL: failed to digest sign update\n"); + goto failure; + } + + if (signature_len != sizeof(signature_1)) { + fprintf(stderr, "FAIL: signature length differs (%zu != %zu)\n", + signature_len, sizeof(signature_1)); + goto failure; + } + + if (memcmp(signature, signature_1, signature_len) != 0) { + fprintf(stderr, "FAIL: Ed25519 sign failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(signature, signature_len); + fprintf(stderr, "Want:\n"); + hexdump(signature_1, sizeof(signature_1)); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_free(pkey); + free(signature); + + return failed; +} + +static int +ecx_ed25519_verify_test(void) +{ + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio = NULL; + int failed = 1; + + if ((bio = BIO_new_mem_buf(ed25519_pub_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read public key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + errx(1, "failed to create MD_CTX"); + + if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey)) { + fprintf(stderr, "FAIL: failed to init digest verify\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + if (!EVP_DigestVerify(md_ctx, signature_1, sizeof(signature_1), + message_1, sizeof(message_1))) { + fprintf(stderr, "FAIL: failed to digest verify update\n"); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_MD_CTX_free(md_ctx); + EVP_PKEY_free(pkey); + + return failed; +} + +static int +ecx_x25519_keygen_test(void) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + BIO *bio = NULL; + int failed = 1; + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to create X25519 context\n"); + goto failure; + } + + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + fprintf(stderr, "FAIL: failed to init keygen for X25519\n"); + goto failure; + } + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) { + fprintf(stderr, "FAIL: failed to generate X25519 key\n"); + goto failure; + } + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { + fprintf(stderr, "FAIL: failed to write X25519 to PEM\n"); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); + + return failed; +} + +static int +ecx_x25519_derive_test(void) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL, *pkey_peer = NULL; + uint8_t *shared_key = NULL; + size_t shared_key_len = 0; + BIO *bio = NULL; + int failed = 1; + + if ((bio = BIO_new_mem_buf(x25519_priv_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read private key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + BIO_free(bio); + if ((bio = BIO_new_mem_buf(x25519_pub_key_2, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey_peer = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read peer public key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to create X25519 context\n"); + goto failure; + } + if (EVP_PKEY_derive_init(pkey_ctx) <= 0) { + fprintf(stderr, "FAIL: failed to init derive for X25519\n"); + goto failure; + } + if (EVP_PKEY_derive_set_peer(pkey_ctx, pkey_peer) <= 0) { + fprintf(stderr, "FAIL: failed to set peer key for X25519\n"); + goto failure; + } + if (EVP_PKEY_derive(pkey_ctx, NULL, &shared_key_len) <= 0) { + fprintf(stderr, "FAIL: failed to derive X25519 key length\n"); + goto failure; + } + if ((shared_key = malloc(shared_key_len)) == NULL) + errx(1, "failed to malloc shared key"); + if (EVP_PKEY_derive(pkey_ctx, shared_key, &shared_key_len) <= 0) { + fprintf(stderr, "FAIL: failed to derive X25519 key\n"); + goto failure; + } + + if (shared_key_len != sizeof(shared_key_1)) { + fprintf(stderr, "FAIL: shared key length differs (%zu != %zu)\n", + shared_key_len, sizeof(shared_key_1)); + goto failure; + } + + if (memcmp(shared_key, shared_key_1, shared_key_len) != 0) { + fprintf(stderr, "FAIL: X25519 derive failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(shared_key, shared_key_len); + fprintf(stderr, "Want:\n"); + hexdump(shared_key_1, sizeof(shared_key_1)); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey_peer); + EVP_PKEY_free(pkey); + freezero(shared_key, shared_key_len); + + return failed; +} + +static int +ecx_x25519_raw_key_test(void) +{ + EVP_PKEY *pkey = NULL; + uint8_t *priv_key = NULL; + size_t priv_key_len = 0; + uint8_t *pub_key = NULL; + size_t pub_key_len = 0; + const uint8_t *pp; + BIO *bio = NULL; + int failed = 1; + + /* + * Decode private key from PEM and check raw private and raw public. + */ + + if ((bio = BIO_new_mem_buf(x25519_priv_key_2, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read private key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw private key len\n"); + goto failure; + } + if (priv_key_len != sizeof(x25519_raw_priv_key_2)) { + fprintf(stderr, "FAIL: raw private key length differs " + "(%zu != %zu)\n", priv_key_len, + sizeof(x25519_raw_priv_key_2)); + goto failure; + } + if ((priv_key = malloc(priv_key_len)) == NULL) + errx(1, "failed to malloc priv key"); + if (!EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw private key len\n"); + goto failure; + } + if (memcmp(priv_key, x25519_raw_priv_key_2, priv_key_len) != 0) { + fprintf(stderr, "FAIL: get raw private key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(priv_key, priv_key_len); + fprintf(stderr, "Want:\n"); + hexdump(x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2)); + goto failure; + } + + if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (pub_key_len != sizeof(x25519_raw_pub_key_2)) { + fprintf(stderr, "FAIL: raw public key length differs " + "(%zu != %zu)\n", pub_key_len, + sizeof(x25519_raw_pub_key_2)); + goto failure; + } + if ((pub_key = malloc(pub_key_len)) == NULL) + errx(1, "failed to malloc private key"); + if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (memcmp(pub_key, x25519_raw_pub_key_2, pub_key_len) != 0) { + fprintf(stderr, "FAIL: get raw public key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(pub_key, pub_key_len); + fprintf(stderr, "Want:\n"); + hexdump(x25519_raw_pub_key_2, sizeof(x25519_raw_pub_key_2)); + goto failure; + } + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; + + freezero(priv_key, priv_key_len); + priv_key = NULL; + priv_key_len = 0; + + freezero(pub_key, pub_key_len); + pub_key = NULL; + pub_key_len = 0; + + /* + * Decode public key from PEM and check raw private and raw public. + */ + + if ((bio = BIO_new_mem_buf(x25519_pub_key_1, -1)) == NULL) + errx(1, "failed to create BIO for key"); + if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to read public key\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + /* + * Yet another astounding API design - we cannot tell if the private key + * is not present, or if some other failure occurred. + */ + if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &priv_key_len)) { + fprintf(stderr, "FAIL: failed to get raw priv key len\n"); + goto failure; + } + if ((priv_key = malloc(priv_key_len)) == NULL) + errx(1, "failed to malloc priv key"); + if (EVP_PKEY_get_raw_private_key(pkey, priv_key, &priv_key_len)) { + fprintf(stderr, "FAIL: got raw private key, should fail\n"); + goto failure; + } + + if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (pub_key_len != sizeof(x25519_raw_pub_key_1)) { + fprintf(stderr, "FAIL: raw public key length differs " + "(%zu != %zu)\n", pub_key_len, + sizeof(x25519_raw_pub_key_1)); + goto failure; + } + if ((pub_key = malloc(pub_key_len)) == NULL) + errx(1, "failed to malloc private key"); + if (!EVP_PKEY_get_raw_public_key(pkey, pub_key, &pub_key_len)) { + fprintf(stderr, "FAIL: failed to get raw pub key len\n"); + goto failure; + } + if (memcmp(pub_key, x25519_raw_pub_key_1, pub_key_len) != 0) { + fprintf(stderr, "FAIL: get raw public key failed\n"); + fprintf(stderr, "Got:\n"); + hexdump(pub_key, pub_key_len); + fprintf(stderr, "Want:\n"); + hexdump(x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1)); + goto failure; + } + + BIO_free(bio); + bio = NULL; + + EVP_PKEY_free(pkey); + pkey = NULL; + + /* + * Create PKEY from raw private, check PEM encoded private and public. + */ + if ((pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, + x25519_raw_priv_key_2, sizeof(x25519_raw_priv_key_2))) == NULL) { + fprintf(stderr, "FAIL: PKEY from raw private key failed"); + goto failure; + } + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL)) { + fprintf(stderr, "FAIL: failed to write X25519 private to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(x25519_priv_key_2, pp) != 0) { + fprintf(stderr, "FAIL: resulting private key PEM differs\n"); + goto failure; + } + + (void)BIO_reset(bio); + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(x25519_pub_key_2, pp) != 0) { + fprintf(stderr, "FAIL: resulting public key PEM differs\n"); + goto failure; + } + + EVP_PKEY_free(pkey); + pkey = NULL; + + /* + * Create PKEY from raw public, check public key PEM. + */ + if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL, + x25519_raw_pub_key_1, sizeof(x25519_raw_pub_key_1))) == NULL) { + fprintf(stderr, "FAIL: PKEY from raw public key failed"); + goto failure; + } + (void)BIO_reset(bio); + if (!PEM_write_bio_PUBKEY(bio, pkey)) { + fprintf(stderr, "FAIL: failed to write X25519 public to PEM\n"); + goto failure; + } + BIO_get_mem_data(bio, &pp); + if (strcmp(x25519_pub_key_1, pp) != 0) { + fprintf(stderr, "FAIL: resulting public key PEM differs\n"); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EVP_PKEY_free(pkey); + freezero(priv_key, priv_key_len); + freezero(pub_key, pub_key_len); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= ecx_ed25519_raw_key_test(); + failed |= ecx_ed25519_keygen_test(); + failed |= ecx_ed25519_sign_test(); + failed |= ecx_ed25519_verify_test(); + + failed |= ecx_x25519_keygen_test(); + failed |= ecx_x25519_derive_test(); + failed |= ecx_x25519_raw_key_test(); + + return failed; +} diff --git a/tests/evp_pkey_check.c b/tests/evp_pkey_check.c new file mode 100644 index 0000000..7b73316 --- /dev/null +++ b/tests/evp_pkey_check.c @@ -0,0 +1,397 @@ +/* $OpenBSD: evp_pkey_check.c,v 1.4 2023/03/02 20:18:40 tb Exp $ */ +/* + * Copyright (c) 2021-2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#define EVP_TEST_RSA_BITS 2048 + +static int +evp_pkey_check_rsa(void) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + RSA *rsa = NULL; + BIGNUM *rsa_d; + int ret; + int fail_soft = 0; + int failed = 1; + + /* + * Generate a run-off-the-mill RSA key. + */ + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_CTX_new_id()\n", __func__); + goto err; + } + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_keygen_init\n", __func__); + goto err; + } + if (!EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, EVP_TEST_RSA_BITS)) { + fprintf(stderr, "%s: EVP_PKEY_CTX_set_rsa_keygen_bits\n", + __func__); + goto err; + } + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_keygen\n", __func__); + goto err; + } + + /* At this point, no pkey is set on pkey_ctx, we should fail with 0. */ + if (EVP_PKEY_check(pkey_ctx) != 0) { + fprintf(stderr, "%s: EVP_PKEY_check() succeeded without pkey\n", + __func__); + ERR_print_errors_fp(stderr); + fail_soft = 1; + } + + ERR_clear_error(); + + /* + * Create a new EVP_PKEY_CTX with pkey set. + */ + + EVP_PKEY_CTX_free(pkey_ctx); + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_CTX_new\n", __func__); + goto err; + } + + /* The freshly generated pkey is set on pkey_ctx. We should succeed. */ + if ((ret = EVP_PKEY_check(pkey_ctx)) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_check(), generated pkey: %d\n", + __func__, ret); + ERR_print_errors_fp(stderr); + ERR_clear_error(); + fail_soft = 1; + } + + /* Public key checking for RSA is not supported. */ + if (EVP_PKEY_public_check(pkey_ctx) != -2) { + fprintf(stderr, + "%s: EVP_PKEY_public_check() supported for RSA?\n", + __func__); + goto err; + } + ERR_clear_error(); + + /* Parameter checking for RSA is not supported. */ + if (EVP_PKEY_param_check(pkey_ctx) != -2) { + fprintf(stderr, + "%s: EVP_PKEY_param_check() supported for RSA?\n", + __func__); + goto err; + } + ERR_clear_error(); + + /* + * Now modify the RSA key a bit. The check should then fail. + */ + + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_get0_RSA\n", __func__); + goto err; + } + /* We're lazy and modify rsa->d directly, hence the ugly cast. */ + if ((rsa_d = (BIGNUM *)RSA_get0_d(rsa)) == NULL) { + fprintf(stderr, "%s: RSA_get0_d()\n", __func__); + goto err; + } + if (!BN_add_word(rsa_d, 2)) { + fprintf(stderr, "%s: BN_add_word\n", __func__); + goto err; + } + + /* Since (d+2) * e != 1 mod (p-1)*(q-1), we should fail */ + if (EVP_PKEY_check(pkey_ctx) == 1) { + fprintf(stderr, "%s: EVP_PKEY_check success with modified d\n", + __func__); + fail_soft = 1; + } + + if (ERR_peek_error() == 0) { + fprintf(stderr, "%s: expected some RSA errors\n", __func__); + fail_soft = 1; + } + ERR_clear_error(); + + failed = 0; + + err: + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); + + return failed | fail_soft; +} + +static int +evp_pkey_check_ec(void) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + EC_KEY *eckey = NULL; + BIGNUM *private_key = NULL; + EC_GROUP *group; + const EC_POINT *generator; + BIGNUM *cofactor = NULL, *order = NULL; + int ret; + int fail_soft = 0; + int failed = 1; + + /* + * Generate an elliptic curve key on secp384r1 + */ + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_CTX_new_id\n", __func__); + goto err; + } + if (EVP_PKEY_keygen_init(pkey_ctx) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_keygen_init\n", __func__); + goto err; + } + if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx, + NID_secp384r1) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_CTX_set_ec_paramgen_curve_nid\n", + __func__); + goto err; + } + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_keygen\n", __func__); + goto err; + } + + /* At this point, no pkey is set on pkey_ctx, we should fail with 0. */ + if (EVP_PKEY_check(pkey_ctx) != 0) { + fprintf(stderr, "%s: EVP_PKEY_check() succeeded without pkey\n", + __func__); + ERR_print_errors_fp(stderr); + fail_soft = 1; + } + + ERR_clear_error(); + + /* + * Create a new EVP_PKEY_CTX with pkey set. + */ + + EVP_PKEY_CTX_free(pkey_ctx); + if ((pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_CTX_new\n", __func__); + goto err; + } + + /* The freshly generated pkey is set on pkey_ctx. We should succeed. */ + if ((ret = EVP_PKEY_check(pkey_ctx)) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_check(), generated pkey: %d\n", + __func__, ret); + ERR_print_errors_fp(stderr); + ERR_clear_error(); + fail_soft = 1; + } + + /* We should also succeed the public check. */ + if ((ret = EVP_PKEY_public_check(pkey_ctx)) <= 0) { + fprintf(stderr, + "%s: EVP_PKEY_public_check(), generated pkey: %d\n", + __func__, ret); + ERR_print_errors_fp(stderr); + ERR_clear_error(); + fail_soft = 1; + } + + /* We should also succeed the parameter check. */ + if ((ret = EVP_PKEY_param_check(pkey_ctx)) <= 0) { + fprintf(stderr, + "%s: EVP_PKEY_param_check(), generated pkey: %d\n", + __func__, ret); + ERR_print_errors_fp(stderr); + ERR_clear_error(); + fail_soft = 1; + } + + /* + * Modify the private key slightly. + */ + + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) { + fprintf(stderr, "%s: EVP_PKEY_get0_EC_KEY\n", __func__); + goto err; + } + + /* We're lazy and modify the private key directly. */ + if ((private_key = (BIGNUM *)EC_KEY_get0_private_key(eckey)) == NULL) { + fprintf(stderr, "%s: EC_KEY_get0_private_key\n", __func__); + goto err; + } + + /* + * The private key is a random number in [1, order). Preserve this + * property by adding 1 if it is equal to 1 and subtracting 1 otherwise. + */ + if (BN_cmp(private_key, BN_value_one()) == 0) { + if (!BN_add_word(private_key, 1)) { + fprintf(stderr, "%s: BN_add_word\n", __func__); + goto err; + } + } else { + if (!BN_sub_word(private_key, 1)) { + fprintf(stderr, "%s: BN_sub_word\n", __func__); + goto err; + } + } + + /* Generator times private key will no longer be equal to public key. */ + if (EVP_PKEY_check(pkey_ctx) == 1) { + fprintf(stderr, "%s: EVP_PKEY_check succeeded unexpectedly\n", + __func__); + fail_soft = 1; + } + + if (ERR_peek_error() == 0) { + fprintf(stderr, "%s: expected a private key error\n", __func__); + fail_soft = 1; + } + ERR_clear_error(); + + /* EVP_PKEY_public_check checks the private key (sigh), so we fail. */ + if (EVP_PKEY_public_check(pkey_ctx) == 1) { + fprintf(stderr, + "%s: EVP_PKEY_public_check succeeded unexpectedly\n", + __func__); + fail_soft = 1; + } + + /* We should still succeed the parameter check. */ + if ((ret = EVP_PKEY_param_check(pkey_ctx)) <= 0) { + fprintf(stderr, + "%s: EVP_PKEY_param_check(), modified privkey pkey: %d\n", + __func__, ret); + ERR_print_errors_fp(stderr); + ERR_clear_error(); + fail_soft = 1; + } + + /* Now set the private key to NULL. The API will think malloc failed. */ + if (EC_KEY_set_private_key(eckey, NULL) != 0) { + fprintf(stderr, "%s: EC_KEY_set_private_key succeeded?!", + __func__); + goto err; + } + + /* + * EVP_PKEY_public_check now only checks that the public key is on the + * curve. We should succeed again. + */ + + if ((ret = EVP_PKEY_public_check(pkey_ctx)) <= 0) { + fprintf(stderr, "%s: EVP_PKEY_check(), generated pkey: %d\n", + __func__, ret); + fail_soft = 1; + } + + ERR_clear_error(); + + /* + * Now let's modify the group to trip the parameter check. + */ + + if ((group = (EC_GROUP *)EC_KEY_get0_group(eckey)) == NULL) { + fprintf(stderr, "%s: EC_KEY_get0_group() failed\n", __func__); + goto err; + } + + if ((generator = EC_GROUP_get0_generator(group)) == NULL) { + fprintf(stderr, "%s: EC_GROUP_get0_generator() failed\n", + __func__); + goto err; + } + + if ((order = BN_new()) == NULL) { + fprintf(stderr, "%s: order = BN_new() failed\n", __func__); + goto err; + } + if ((cofactor = BN_new()) == NULL) { + fprintf(stderr, "%s: cofactor = BN_new() failed\n", __func__); + goto err; + } + + if (!EC_GROUP_get_order(group, order, NULL)) { + fprintf(stderr, "%s: EC_GROUP_get_order() failed\n", __func__); + goto err; + } + if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) { + fprintf(stderr, "%s: EC_GROUP_get_cofactor() failed\n", + __func__); + goto err; + } + + /* Decrement order so order * generator != (point at infinity). */ + if (!BN_sub_word(order, 1)) { + fprintf(stderr, "%s: BN_sub_word() failed\n", __func__); + goto err; + } + + /* Now set this nonsense on the group. */ + if (!EC_GROUP_set_generator(group, generator, order, cofactor)) { + fprintf(stderr, "%s: EC_GROUP_set_generator() failed\n", + __func__); + goto err; + } + + /* We should now fail the parameter check. */ + if (EVP_PKEY_param_check(pkey_ctx) == 1) { + fprintf(stderr, + "%s: EVP_PKEY_param_check(), succeeded unexpectedly\n", + __func__); + fail_soft = 1; + } + + if (ERR_peek_error() == 0) { + fprintf(stderr, "%s: expected a group order error\n", __func__); + fail_soft = 1; + } + ERR_clear_error(); + + failed = 0; + + err: + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); + BN_free(order); + BN_free(cofactor); + + return failed | fail_soft; +} + +int +main(void) +{ + int failed = 0; + + failed |= evp_pkey_check_rsa(); + failed |= evp_pkey_check_ec(); + + return failed; +} diff --git a/tests/evp_pkey_cleanup.c b/tests/evp_pkey_cleanup.c new file mode 100644 index 0000000..fd922ef --- /dev/null +++ b/tests/evp_pkey_cleanup.c @@ -0,0 +1,83 @@ +/* $OpenBSD: evp_pkey_cleanup.c,v 1.3 2022/12/01 13:49:12 tb Exp $ */ + +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "evp_local.h" + +struct pkey_cleanup_test { + const char *name; + int nid; + void (*free)(void); +}; + +int pkey_ids[] = { + EVP_PKEY_CMAC, + EVP_PKEY_DH, + EVP_PKEY_DSA, + EVP_PKEY_EC, + EVP_PKEY_GOSTIMIT, + EVP_PKEY_GOSTR01, + EVP_PKEY_HMAC, + EVP_PKEY_RSA, + EVP_PKEY_RSA_PSS, +}; + +static const size_t N_PKEY_IDS = sizeof(pkey_ids) / sizeof(pkey_ids[0]); + +static int +test_evp_pkey_ctx_cleanup(int nid) +{ + EVP_PKEY_CTX *pkey_ctx = NULL; + void *data; + int failed = 1; + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(nid, NULL)) == NULL) { + fprintf(stderr, "EVP_PKEY_CTX_new_id(%d, NULL) failed\n", nid); + goto err; + } + + data = EVP_PKEY_CTX_get_data(pkey_ctx); + + EVP_PKEY_CTX_set_data(pkey_ctx, NULL); + if (pkey_ctx->pmeth->cleanup != NULL) + pkey_ctx->pmeth->cleanup(pkey_ctx); + + EVP_PKEY_CTX_set_data(pkey_ctx, data); + + failed = 0; + + err: + EVP_PKEY_CTX_free(pkey_ctx); + + return failed; +} + +int +main(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_PKEY_IDS; i++) + failed |= test_evp_pkey_ctx_cleanup(pkey_ids[i]); + + return failed; +} diff --git a/tests/evp_test.c b/tests/evp_test.c new file mode 100644 index 0000000..eff071f --- /dev/null +++ b/tests/evp_test.c @@ -0,0 +1,419 @@ +/* $OpenBSD: evp_test.c,v 1.7 2023/09/29 06:53:05 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +#include "evp_local.h" + +static int +evp_asn1_method_test(void) +{ + const EVP_PKEY_ASN1_METHOD *method; + int count, pkey_id, i; + int failed = 1; + + if ((count = EVP_PKEY_asn1_get_count()) < 1) { + fprintf(stderr, "FAIL: failed to get pkey asn1 method count\n"); + goto failure; + } + for (i = 0; i < count; i++) { + if ((method = EVP_PKEY_asn1_get0(i)) == NULL) { + fprintf(stderr, "FAIL: failed to get pkey %d\n", i); + goto failure; + } + } + + if ((method = EVP_PKEY_asn1_find(NULL, EVP_PKEY_RSA)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA method\n"); + goto failure; + } + if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, method)) { + fprintf(stderr, "FAIL: failed to get RSA method info\n"); + goto failure; + } + if (pkey_id != EVP_PKEY_RSA) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA); + goto failure; + } + + if ((method = EVP_PKEY_asn1_find(NULL, EVP_PKEY_RSA_PSS)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA-PSS method\n"); + goto failure; + } + if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, method)) { + fprintf(stderr, "FAIL: failed to get RSA-PSS method info\n"); + goto failure; + } + if (pkey_id != EVP_PKEY_RSA_PSS) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA_PSS); + goto failure; + } + + if ((method = EVP_PKEY_asn1_find_str(NULL, "RSA", -1)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA method by str\n"); + goto failure; + } + if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, method)) { + fprintf(stderr, "FAIL: failed to get RSA method info\n"); + goto failure; + } + if (pkey_id != EVP_PKEY_RSA) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA); + goto failure; + } + + if ((method = EVP_PKEY_asn1_find_str(NULL, "RSA-PSS", -1)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA-PSS method\n"); + goto failure; + } + if (!EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, method)) { + fprintf(stderr, "FAIL: failed to get RSA-PSS method info\n"); + goto failure; + } + if (pkey_id != EVP_PKEY_RSA_PSS) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA_PSS); + goto failure; + } + + failed = 0; + + failure: + + return failed; +} + +static int +evp_pkey_method_test(void) +{ + const EVP_PKEY_METHOD *method; + int pkey_id; + int failed = 1; + + if ((method = EVP_PKEY_meth_find(EVP_PKEY_RSA)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA method\n"); + goto failure; + } + EVP_PKEY_meth_get0_info(&pkey_id, NULL, method); + if (pkey_id != EVP_PKEY_RSA) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA); + goto failure; + } + + if ((method = EVP_PKEY_meth_find(EVP_PKEY_RSA_PSS)) == NULL) { + fprintf(stderr, "FAIL: failed to find RSA-PSS method\n"); + goto failure; + } + EVP_PKEY_meth_get0_info(&pkey_id, NULL, method); + if (pkey_id != EVP_PKEY_RSA_PSS) { + fprintf(stderr, "FAIL: method ID mismatch (%d != %d)\n", + pkey_id, EVP_PKEY_RSA_PSS); + goto failure; + } + + failed = 0; + + failure: + + return failed; +} + +static const struct evp_iv_len_test { + const EVP_CIPHER *(*cipher)(void); + int iv_len; + int setlen; + int expect; +} evp_iv_len_tests[] = { + { + .cipher = EVP_aes_128_ccm, + .iv_len = 7, + .setlen = 11, + .expect = 1, + }, + { + .cipher = EVP_aes_128_ccm, + .iv_len = 7, + .setlen = 6, + .expect = 0, + }, + { + .cipher = EVP_aes_128_ccm, + .iv_len = 7, + .setlen = 13, + .expect = 1, + }, + { + .cipher = EVP_aes_128_ccm, + .iv_len = 7, + .setlen = 14, + .expect = 0, + }, + + { + .cipher = EVP_aes_192_ccm, + .iv_len = 7, + .setlen = 11, + .expect = 1, + }, + { + .cipher = EVP_aes_192_ccm, + .iv_len = 7, + .setlen = 6, + .expect = 0, + }, + { + .cipher = EVP_aes_192_ccm, + .iv_len = 7, + .setlen = 13, + .expect = 1, + }, + { + .cipher = EVP_aes_192_ccm, + .iv_len = 7, + .setlen = 14, + .expect = 0, + }, + + { + .cipher = EVP_aes_256_ccm, + .iv_len = 7, + .setlen = 11, + .expect = 1, + }, + { + .cipher = EVP_aes_256_ccm, + .iv_len = 7, + .setlen = 6, + .expect = 0, + }, + { + .cipher = EVP_aes_256_ccm, + .iv_len = 7, + .setlen = 13, + .expect = 1, + }, + { + .cipher = EVP_aes_256_ccm, + .iv_len = 7, + .setlen = 14, + .expect = 0, + }, + + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 16, + .expect = 1, + }, + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 0, + .expect = 0, + }, + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 1, + .expect = 1, + }, + /* XXX - GCM IV length isn't capped... */ + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 1024 * 1024, + .expect = 1, + }, + + { + .cipher = EVP_aes_192_gcm, + .iv_len = 12, + .setlen = 16, + .expect = 1, + }, + { + .cipher = EVP_aes_192_gcm, + .iv_len = 12, + .setlen = 0, + .expect = 0, + }, + { + .cipher = EVP_aes_192_gcm, + .iv_len = 12, + .setlen = 1, + .expect = 1, + }, + /* XXX - GCM IV length isn't capped... */ + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 1024 * 1024, + .expect = 1, + }, + + { + .cipher = EVP_aes_256_gcm, + .iv_len = 12, + .setlen = 16, + .expect = 1, + }, + { + .cipher = EVP_aes_256_gcm, + .iv_len = 12, + .setlen = 0, + .expect = 0, + }, + { + .cipher = EVP_aes_256_gcm, + .iv_len = 12, + .setlen = 1, + .expect = 1, + }, + /* XXX - GCM IV length isn't capped... */ + { + .cipher = EVP_aes_128_gcm, + .iv_len = 12, + .setlen = 1024 * 1024, + .expect = 1, + }, + + { + .cipher = EVP_aes_128_ecb, + .iv_len = 0, + .setlen = 11, + .expect = 0, + }, + + { + .cipher = EVP_chacha20_poly1305, + .iv_len = 12, + .setlen = 11, + .expect = 1, + }, + { + .cipher = EVP_chacha20_poly1305, + .iv_len = 12, + .setlen = 12, + .expect = 1, + }, + { + .cipher = EVP_chacha20_poly1305, + .iv_len = 12, + .setlen = 13, + .expect = 0, + }, + { + .cipher = EVP_chacha20_poly1305, + .iv_len = 12, + .setlen = 1, + .expect = 1, + }, + { + .cipher = EVP_chacha20_poly1305, + .iv_len = 12, + .setlen = 0, + .expect = 0, + }, +}; + +#define N_EVP_IV_LEN_TESTS \ + (sizeof(evp_iv_len_tests) / sizeof(evp_iv_len_tests[0])) + +static int +evp_pkey_iv_len_testcase(const struct evp_iv_len_test *test) +{ + const EVP_CIPHER *cipher = test->cipher(); + const char *name; + EVP_CIPHER_CTX *ctx; + int ret; + int failure = 1; + + assert(cipher != NULL); + name = OBJ_nid2ln(EVP_CIPHER_nid(cipher)); + assert(name != NULL); + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: %s: EVP_CIPHER_CTX_new()\n", name); + goto failure; + } + + if ((ret = EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL)) <= 0) { + fprintf(stderr, "FAIL: %s: EVP_EncryptInit_ex:" + " want %d, got %d\n", name, 1, ret); + goto failure; + } + if ((ret = EVP_CIPHER_CTX_iv_length(ctx)) != test->iv_len) { + fprintf(stderr, "FAIL: %s EVP_CIPHER_CTX_iv_length (before set)" + " want %d, got %d\n", name, test->iv_len, ret); + goto failure; + } + if ((ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, + test->setlen, NULL)) != test->expect) { + fprintf(stderr, "FAIL: %s EVP_CIPHER_CTX_ctrl" + " want %d, got %d\n", name, test->expect, ret); + goto failure; + } + if (test->expect == 0) + goto done; + if ((ret = EVP_CIPHER_CTX_iv_length(ctx)) != test->setlen) { + fprintf(stderr, "FAIL: %s EVP_CIPHER_CTX_iv_length (after set)" + " want %d, got %d\n", name, test->setlen, ret); + goto failure; + } + + done: + failure = 0; + + failure: + EVP_CIPHER_CTX_free(ctx); + + return failure; +} + +static int +evp_pkey_iv_len_test(void) +{ + size_t i; + int failure = 0; + + for (i = 0; i < N_EVP_IV_LEN_TESTS; i++) + failure |= evp_pkey_iv_len_testcase(&evp_iv_len_tests[i]); + + return failure; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= evp_asn1_method_test(); + failed |= evp_pkey_method_test(); + failed |= evp_pkey_iv_len_test(); + + OPENSSL_cleanup(); + + return failed; +} diff --git a/tests/evptest.c b/tests/evptest.c new file mode 100644 index 0000000..6f677dd --- /dev/null +++ b/tests/evptest.c @@ -0,0 +1,470 @@ +/* $OpenBSD: evptest.c,v 1.12 2023/03/02 20:24:51 tb Exp $ */ +/* Written by Ben Laurie, 2001 */ +/* + * Copyright (c) 2001 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include + +int verbose; + +static void +hexdump(FILE *f, const char *title, const unsigned char *s, int l) +{ + int n = 0; + + fprintf(f, "%s",title); + for (; n < l; ++n) { + if ((n % 16) == 0) + fprintf(f, "\n%04x",n); + fprintf(f, " %02x",s[n]); + } + fprintf(f, "\n"); +} + +static int +convert(unsigned char *s) +{ + unsigned char *d; + + for (d = s; *s; s += 2,++d) { + unsigned int n; + + if (!s[1]) { + fprintf(stderr, "Odd number of hex digits!\n"); + exit(4); + } + if (sscanf((char *)s, "%2x", &n) != 1) { + fprintf(stderr, "Invalid hex value at %s\n", s); + exit(4); + } + + *d = (unsigned char)n; + } + return s - d; +} + +static char * +sstrsep(char **string, const char *delim) +{ + char isdelim[256]; + char *token = *string; + + if (**string == 0) + return NULL; + + memset(isdelim, 0, 256); + isdelim[0] = 1; + + while (*delim) { + isdelim[(unsigned char)(*delim)] = 1; + delim++; + } + + while (!isdelim[(unsigned char)(**string)]) { + (*string)++; + } + + if (**string) { + **string = 0; + (*string)++; + } + + return token; +} + +static unsigned char * +ustrsep(char **p, const char *sep) +{ + return (unsigned char *)sstrsep(p, sep); +} + +static int +test1_exit(int ec) +{ + exit(ec); + return(0); /* To keep some compilers quiet */ +} + +static void +test1(const EVP_CIPHER *c, const unsigned char *key, int kn, + const unsigned char *iv, int in, const unsigned char *plaintext, int pn, + const unsigned char *ciphertext, int cn, int encdec) +{ + EVP_CIPHER_CTX *ctx; + unsigned char out[4096]; + const unsigned char *eiv; + int outl, outl2; + + if (verbose) { + printf("Testing cipher %s%s\n", EVP_CIPHER_name(c), + (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)"))); + hexdump(stdout, "Key",key,kn); + if (in) + hexdump(stdout, "IV",iv,in); + hexdump(stdout, "Plaintext",plaintext,pn); + hexdump(stdout, "Ciphertext",ciphertext,cn); + } + + if (kn != EVP_CIPHER_key_length(c)) { + fprintf(stderr, "Key length doesn't match, got %d expected %lu\n",kn, + (unsigned long)EVP_CIPHER_key_length(c)); + test1_exit(5); + } + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(12); + } + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + if (encdec != 0) { + eiv = iv; + if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) + eiv = NULL; + if (!EVP_EncryptInit_ex(ctx, c, NULL, key, eiv)) { + fprintf(stderr, "EncryptInit failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(10); + } + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (!EVP_EncryptUpdate(ctx, out, &outl, plaintext, pn)) { + fprintf(stderr, "Encrypt failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(6); + } + if (!EVP_EncryptFinal_ex(ctx, out + outl, &outl2)) { + fprintf(stderr, "EncryptFinal failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(7); + } + + if (outl + outl2 != cn) { + fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n", + outl + outl2, cn); + test1_exit(8); + } + + if (memcmp(out, ciphertext, cn)) { + fprintf(stderr, "Ciphertext mismatch\n"); + hexdump(stderr, "Got",out,cn); + hexdump(stderr, "Expected",ciphertext,cn); + test1_exit(9); + } + } + + if (encdec <= 0) { + eiv = iv; + if (EVP_CIPHER_mode(c) == EVP_CIPH_WRAP_MODE && in == 0) + eiv = NULL; + if (!EVP_DecryptInit_ex(ctx, c,NULL, key, eiv)) { + fprintf(stderr, "DecryptInit failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(11); + } + EVP_CIPHER_CTX_set_padding(ctx, 0); + + if (!EVP_DecryptUpdate(ctx, out, &outl, ciphertext, cn)) { + fprintf(stderr, "Decrypt failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(6); + } + if (!EVP_DecryptFinal_ex(ctx, out + outl, &outl2)) { + fprintf(stderr, "DecryptFinal failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(7); + } + + if (outl + outl2 != pn) { + fprintf(stderr, "Plaintext length mismatch got %d expected %d\n", + outl + outl2, pn); + test1_exit(8); + } + + if (memcmp(out, plaintext, pn)) { + fprintf(stderr, "Plaintext mismatch\n"); + hexdump(stderr, "Got",out,pn); + hexdump(stderr, "Expected",plaintext,pn); + test1_exit(9); + } + } + + EVP_CIPHER_CTX_free(ctx); + + if (verbose) + printf("\n"); +} + +static int +test_cipher(const char *cipher, const unsigned char *key, int kn, + const unsigned char *iv, int in, const unsigned char *plaintext, int pn, + const unsigned char *ciphertext, int cn, int encdec) +{ + const EVP_CIPHER *c; + + c = EVP_get_cipherbyname(cipher); + if (!c) + return 0; + + test1(c, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec); + + return 1; +} + +static int +test_digest(const char *digest, const unsigned char *plaintext, int pn, + const unsigned char *ciphertext, unsigned int cn) +{ + const EVP_MD *d; + EVP_MD_CTX *ctx; + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int mdn; + + d = EVP_get_digestbyname(digest); + if (!d) + return 0; + + if (verbose) { + printf("Testing digest %s\n",EVP_MD_name(d)); + hexdump(stdout, "Plaintext",plaintext,pn); + hexdump(stdout, "Digest",ciphertext,cn); + } + + if ((ctx = EVP_MD_CTX_new()) == NULL) { + fprintf(stderr, "EVP_CIPHER_CTX_new failed\n"); + ERR_print_errors_fp(stderr); + test1_exit(104); + } + if (!EVP_DigestInit_ex(ctx, d, NULL)) { + fprintf(stderr, "DigestInit failed\n"); + ERR_print_errors_fp(stderr); + exit(100); + } + if (!EVP_DigestUpdate(ctx, plaintext, pn)) { + fprintf(stderr, "DigestUpdate failed\n"); + ERR_print_errors_fp(stderr); + exit(101); + } + if (!EVP_DigestFinal_ex(ctx, md, &mdn)) { + fprintf(stderr, "DigestFinal failed\n"); + ERR_print_errors_fp(stderr); + exit(101); + } + EVP_MD_CTX_free(ctx); + ctx = NULL; + + if (mdn != cn) { + fprintf(stderr, "Digest length mismatch, got %d expected %d\n",mdn,cn); + exit(102); + } + + if (memcmp(md, ciphertext, cn)) { + fprintf(stderr, "Digest mismatch\n"); + hexdump(stderr, "Got",md,cn); + hexdump(stderr, "Expected",ciphertext,cn); + exit(103); + } + if (verbose) + printf("\n"); + + return 1; +} + +int +main(int argc, char **argv) +{ + const char *szTestFile; + FILE *f; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "%s \n",argv[0]); + exit(1); + } + if (argc == 3 && strcmp(argv[1], "-v") == 0) { + verbose = 1; + argv++; + argc--; + } + + szTestFile = argv[1]; + + f=fopen(szTestFile, "r"); + if (!f) { + perror(szTestFile); + exit(2); + } + + /* Load up the software EVP_CIPHER and EVP_MD definitions */ + OpenSSL_add_all_ciphers(); + OpenSSL_add_all_digests(); +#ifndef OPENSSL_NO_ENGINE + /* Load all compiled-in ENGINEs */ + ENGINE_load_builtin_engines(); +#endif +#if 0 + OPENSSL_config(); +#endif +#ifndef OPENSSL_NO_ENGINE + /* Register all available ENGINE implementations of ciphers and digests. + * This could perhaps be changed to "ENGINE_register_all_complete()"? */ + ENGINE_register_all_ciphers(); + ENGINE_register_all_digests(); + /* If we add command-line options, this statement should be switchable. + * It'll prevent ENGINEs being ENGINE_init()ialised for cipher/digest use if + * they weren't already initialised. */ + /* ENGINE_set_cipher_flags(ENGINE_CIPHER_FLAG_NOINIT); */ +#endif + + for (;;) { + char line[8 * 1024]; + char *p; + char *cipher; + unsigned char *iv, *key, *plaintext, *ciphertext; + int encdec; + int kn, in, pn, cn; + + if (!fgets((char *)line, sizeof line, f)) + break; + if (line[0] == '#' || line[0] == '\n') + continue; + p = line; + cipher=sstrsep(&p, ":"); + key=ustrsep(&p, ":"); + iv=ustrsep(&p, ":"); + plaintext=ustrsep(&p, ":"); + ciphertext=ustrsep(&p, ":"); + if (p[-1] == '\n') { + p[-1] = '\0'; + encdec = -1; + } else { + encdec = atoi(sstrsep(&p, "\n")); + } + + + kn = convert(key); + in = convert(iv); + pn = convert(plaintext); + cn = convert(ciphertext); + + if (!test_cipher(cipher, key, kn, iv, in, plaintext, pn, ciphertext, cn, encdec) && + !test_digest(cipher, plaintext, pn, ciphertext, cn)) { +#ifdef OPENSSL_NO_AES + if (strstr(cipher, "AES") == cipher && verbose) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_DES + if (strstr(cipher, "DES") == cipher && verbose) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_RC4 + if (strstr(cipher, "RC4") == cipher && verbose) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_CAMELLIA + if (strstr(cipher, "CAMELLIA") == cipher && verbose) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_SEED + if (strstr(cipher, "SEED") == cipher) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_CHACHA + if (strstr(cipher, "ChaCha") == cipher) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif +#ifdef OPENSSL_NO_GOST + if (strstr(cipher, "md_gost") == cipher || + strstr(cipher, "streebog") == cipher) { + if (verbose) + fprintf(stdout, "Cipher disabled, skipping %s\n", cipher); + continue; + } +#endif + fprintf(stderr, "Can't find %s\n",cipher); + exit(3); + } + } + fclose(f); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_thread_state(NULL); + ERR_free_strings(); + CRYPTO_mem_leaks_fp(stderr); + + return 0; +} diff --git a/tests/evptests.txt b/tests/evptests.txt new file mode 100644 index 0000000..2a58065 --- /dev/null +++ b/tests/evptests.txt @@ -0,0 +1,384 @@ +# $OpenBSD: evptests.txt,v 1.9 2020/01/26 03:31:40 tb Exp $ +#cipher:key:iv:plaintext:ciphertext:0/1(decrypt/encrypt) +#digest:::input:output + +# SHA(1) tests (from shatest.c) +SHA1:::616263:a9993e364706816aba3e25717850c26c9cd0d89d + +# MD5 tests (from md5test.c) +MD5::::d41d8cd98f00b204e9800998ecf8427e +MD5:::61:0cc175b9c0f1b6a831c399e269772661 +MD5:::616263:900150983cd24fb0d6963f7d28e17f72 +MD5:::6d65737361676520646967657374:f96b697d7cb7938d525a2f31aaf161d0 +MD5:::6162636465666768696a6b6c6d6e6f707172737475767778797a:c3fcd3d76192e4007dfb496cca67e13b +MD5:::4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839:d174ab98d277d9f5a5611c2c9f419d9f +MD5:::3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930:57edf4a22be3c955ac49da2e2107b67a + +# MD5+SHA1 tests +MD5-SHA1:::616263:900150983cd24fb0d6963f7d28e17f72a9993e364706816aba3e25717850c26c9cd0d89d + +# GOST R 34.11 tests +md_gost94::::981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0 +streebog512::::8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a +streebog256::::3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb +streebog512:::303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132:1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48 +streebog256:::303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132:9d151eefd8590b89daa6ba6cb74af9275dd051026bb149a452fd84e5e57b5500 +streebog512:::d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb:1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28 +streebog256:::d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb:9dd2fe4e90409e5da87f53976d7405b0c0cac628fc669a741d50063c557e8f50 +streebog512:::000000000000000000000000000000000000000000000000000000000000000021ffffffffffffff7fffffffffff7bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000b1cd42dd2900f900:efd5fec76e1e7929baebb85007ec80c9d565ac8fa5cb4f100749091afb943499ab5d408d11091f6eb278fa7d06e18cae63370a5570f041ecd14bb36eb262c82a + +# AES 128 ECB tests (from FIPS-197 test vectors, encrypt) + +AES-128-ECB:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:69C4E0D86A7B0430D8CDB78070B4C55A:1 + +# AES 192 ECB tests (from FIPS-197 test vectors, encrypt) + +AES-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:DDA97CA4864CDFE06EAF70A0EC0D7191:1 + +# AES 256 ECB tests (from FIPS-197 test vectors, encrypt) + +AES-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:8EA2B7CA516745BFEAFC49904B496089:1 + +# AES 128 ECB tests (from NIST test vectors, encrypt) + +#AES-128-ECB:00000000000000000000000000000000::00000000000000000000000000000000:C34C052CC0DA8D73451AFE5F03BE297F:1 + +# AES 128 ECB tests (from NIST test vectors, decrypt) + +#AES-128-ECB:00000000000000000000000000000000::44416AC2D1F53C583303917E6BE9EBE0:00000000000000000000000000000000:0 + +# AES 192 ECB tests (from NIST test vectors, decrypt) + +#AES-192-ECB:000000000000000000000000000000000000000000000000::48E31E9E256718F29229319C19F15BA4:00000000000000000000000000000000:0 + +# AES 256 ECB tests (from NIST test vectors, decrypt) + +#AES-256-ECB:0000000000000000000000000000000000000000000000000000000000000000::058CCFFDBBCB382D1F6F56585D8A4ADE:00000000000000000000000000000000:0 + +# AES 128 CBC tests (from NIST test vectors, encrypt) + +#AES-128-CBC:00000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:8A05FC5E095AF4848A08D328D3688E3D:1 + +# AES 192 CBC tests (from NIST test vectors, encrypt) + +#AES-192-CBC:000000000000000000000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:7BD966D53AD8C1BB85D2ADFAE87BB104:1 + +# AES 256 CBC tests (from NIST test vectors, encrypt) + +#AES-256-CBC:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000:FE3C53653E2F45B56FCD88B2CC898FF0:1 + +# AES 128 CBC tests (from NIST test vectors, decrypt) + +#AES-128-CBC:00000000000000000000000000000000:00000000000000000000000000000000:FACA37E0B0C85373DF706E73F7C9AF86:00000000000000000000000000000000:0 + +# AES tests from NIST document SP800-38A +# For all ECB encrypts and decrypts, the transformed sequence is +# AES-bits-ECB:key::plaintext:ciphertext:encdec +# ECB-AES128.Encrypt and ECB-AES128.Decrypt +AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::6BC1BEE22E409F96E93D7E117393172A:3AD77BB40D7A3660A89ECAF32466EF97 +AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:F5D3D58503B9699DE785895A96FDBAAF +AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:43B1CD7F598ECE23881B00E3ED030688 +AES-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:7B0C785E27E8AD3F8223207104725DD4 +# ECB-AES192.Encrypt and ECB-AES192.Decrypt +AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:BD334F1D6E45F25FF712A214571FA5CC +AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:974104846D0AD3AD7734ECB3ECEE4EEF +AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:EF7AFD2270E2E60ADCE0BA2FACE6444E +AES-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:9A4B41BA738D6C72FB16691603C18E0E +# ECB-AES256.Encrypt and ECB-AES256.Decrypt +AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:F3EED1BDB5D2A03C064B5A7E3DB181F8 +AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:591CCB10D410ED26DC5BA74A31362870 +AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:B6ED21B99CA6F4F9F153E7B1BEAFED1D +AES-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::F69F2445DF4F9B17AD2B417BE66C3710:23304B7A39F9F3FF067D8D8F9E24ECC7 +# For all CBC encrypts and decrypts, the transformed sequence is +# AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec +# CBC-AES128.Encrypt and CBC-AES128.Decrypt +AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:7649ABAC8119B246CEE98E9B12E9197D +AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:7649ABAC8119B246CEE98E9B12E9197D:AE2D8A571E03AC9C9EB76FAC45AF8E51:5086CB9B507219EE95DB113A917678B2 +AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:5086CB9B507219EE95DB113A917678B2:30C81C46A35CE411E5FBC1191A0A52EF:73BED6B8E3C1743B7116E69E22229516 +AES-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:73BED6B8E3C1743B7116E69E22229516:F69F2445DF4F9B17AD2B417BE66C3710:3FF1CAA1681FAC09120ECA307586E1A7 +# CBC-AES192.Encrypt and CBC-AES192.Decrypt +AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:4F021DB243BC633D7178183A9FA071E8 +AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:4F021DB243BC633D7178183A9FA071E8:AE2D8A571E03AC9C9EB76FAC45AF8E51:B4D9ADA9AD7DEDF4E5E738763F69145A +AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:B4D9ADA9AD7DEDF4E5E738763F69145A:30C81C46A35CE411E5FBC1191A0A52EF:571B242012FB7AE07FA9BAAC3DF102E0 +AES-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:571B242012FB7AE07FA9BAAC3DF102E0:F69F2445DF4F9B17AD2B417BE66C3710:08B0E27988598881D920A9E64F5615CD +# CBC-AES256.Encrypt and CBC-AES256.Decrypt +AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:F58C4C04D6E5F1BA779EABFB5F7BFBD6 +AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:F58C4C04D6E5F1BA779EABFB5F7BFBD6:AE2D8A571E03AC9C9EB76FAC45AF8E51:9CFC4E967EDB808D679F777BC6702C7D +AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:9CFC4E967EDB808D679F777BC6702C7D:30C81C46A35CE411E5FBC1191A0A52EF:39F23369A9D9BACFA530E26304231461 +AES-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39F23369A9D9BACFA530E26304231461:F69F2445DF4F9B17AD2B417BE66C3710:B2EB05E2C39BE9FCDA6C19078C6A9D1B +# We don't support CFB{1,8}-AESxxx.{En,De}crypt +# For all CFB128 encrypts and decrypts, the transformed sequence is +# AES-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec +# CFB128-AES128.Encrypt +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:1 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:1 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:26751F67A3CBB140B1808CF187A4F4DF:F69F2445DF4F9B17AD2B417BE66C3710:C04B05357C5D1C0EEAC4C66F9FF7F2E6:1 +# CFB128-AES128.Decrypt +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:3B3FD92EB72DAD20333449F8E83CFB4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:C8A64537A0B3A93FCDE3CDAD9F1CE58B:0 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:C8A64537A0B3A93FCDE3CDAD9F1CE58B:30C81C46A35CE411E5FBC1191A0A52EF:26751F67A3CBB140B1808CF187A4F4DF:0 +AES-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:26751F67A3CBB140B1808CF187A4F4DF:F69F2445DF4F9B17AD2B417BE66C3710:C04B05357C5D1C0EEAC4C66F9FF7F2E6:0 +# CFB128-AES192.Encrypt +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:CDC80D6FDDF18CAB34C25909C99A4174:AE2D8A571E03AC9C9EB76FAC45AF8E51:67CE7F7F81173621961A2B70171D3D7A:1 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:67CE7F7F81173621961A2B70171D3D7A:30C81C46A35CE411E5FBC1191A0A52EF:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:1 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:F69F2445DF4F9B17AD2B417BE66C3710:C05F9F9CA9834FA042AE8FBA584B09FF:1 +# CFB128-AES192.Decrypt +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:CDC80D6FDDF18CAB34C25909C99A4174:AE2D8A571E03AC9C9EB76FAC45AF8E51:67CE7F7F81173621961A2B70171D3D7A:0 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:67CE7F7F81173621961A2B70171D3D7A:30C81C46A35CE411E5FBC1191A0A52EF:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:0 +AES-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2E1E8A1DD59B88B1C8E60FED1EFAC4C9:F69F2445DF4F9B17AD2B417BE66C3710:C05F9F9CA9834FA042AE8FBA584B09FF:0 +# CFB128-AES256.Encrypt +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:1 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:1 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:1 +# CFB128-AES256.Decrypt +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DC7E84BFDA79164B7ECD8486985D3860:AE2D8A571E03AC9C9EB76FAC45AF8E51:39FFED143B28B1C832113C6331E5407B:0 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:39FFED143B28B1C832113C6331E5407B:30C81C46A35CE411E5FBC1191A0A52EF:DF10132415E54B92A13ED0A8267AE2F9:0 +AES-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:DF10132415E54B92A13ED0A8267AE2F9:F69F2445DF4F9B17AD2B417BE66C3710:75A385741AB9CEF82031623D55B1E471:0 +# For all OFB encrypts and decrypts, the transformed sequence is +# AES-bits-CFB:key:IV/output':plaintext:ciphertext:encdec +# OFB-AES128.Encrypt +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:1 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:1 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:1 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:1 +# OFB-AES128.Decrypt +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:3B3FD92EB72DAD20333449F8E83CFB4A:0 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:7789508D16918F03F53C52DAC54ED825:0 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:9740051E9C5FECF64344F7A82260EDCC:0 +AES-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:304C6528F659C77866A510D9C1D6AE5E:0 +# OFB-AES192.Encrypt +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:1 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:1 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:1 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:1 +# OFB-AES192.Decrypt +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CDC80D6FDDF18CAB34C25909C99A4174:0 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:FCC28B8D4C63837C09E81700C1100401:0 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:8D9A9AEAC0F6596F559C6D4DAF59A5F2:0 +AES-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:6D9F200857CA6C3E9CAC524BD9ACC92A:0 +# OFB-AES256.Encrypt +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:1 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:1 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:1 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:1 +# OFB-AES256.Decrypt +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:DC7E84BFDA79164B7ECD8486985D3860:0 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:4FEBDC6740D20B3AC88F6AD82A4FB08D:0 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:71AB47A086E86EEDF39D1C5BBA97C408:0 +AES-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0126141D67F37BE8538F5A8BE740E484:0 + +# AES Counter test vectors from RFC3686 +aes-128-ctr:AE6852F8121067CC4BF7A5765577F39E:00000030000000000000000000000001:53696E676C6520626C6F636B206D7367:E4095D4FB7A7B3792D6175A3261311B8:1 +aes-128-ctr:7E24067817FAE0D743D6CE1F32539163:006CB6DBC0543B59DA48D90B00000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28:1 +aes-128-ctr:7691BE035E5020A8AC6E618529F9A0DC:00E0017B27777F3F4A1786F000000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F:1 + +aes-192-ctr:16AF5B145FC9F579C175F93E3BFB0EED863D06CCFDB78515:0000004836733C147D6D93CB00000001:53696E676C6520626C6F636B206D7367:4B55384FE259C9C84E7935A003CBE928:1 +aes-192-ctr:7C5CB2401B3DC33C19E7340819E0F69C678C3DB8E6F6A91A:0096B03B020C6EADC2CB500D00000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:453243FC609B23327EDFAAFA7131CD9F8490701C5AD4A79CFC1FE0FF42F4FB00:1 +aes-192-ctr:02BF391EE8ECB159B959617B0965279BF59B60A786D3E0FE:0007BDFD5CBD60278DCC091200000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:96893FC55E5C722F540B7DD1DDF7E758D288BC95C69165884536C811662F2188ABEE0935:1 + +aes-256-ctr:776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104:00000060DB5672C97AA8F0B200000001:53696E676C6520626C6F636B206D7367:145AD01DBF824EC7560863DC71E3E0C0:1 +aes-256-ctr:F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884:00FAAC24C1585EF15A43D87500000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F:F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C:1 +aes-256-ctr:FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D:001CC5B751A51D70A1C1114800000001:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223:EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8:1 + +# AES wrap tests from RFC3394 +id-aes128-wrap:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5 +id-aes192-wrap:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D +id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7 +id-aes192-wrap:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF0001020304050607:031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2 +id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF0001020304050607:A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1 +id-aes256-wrap:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F:28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21 +# DES ECB tests (from destest) + +DES-ECB:0000000000000000::0000000000000000:8CA64DE9C1B123A7 +DES-ECB:FFFFFFFFFFFFFFFF::FFFFFFFFFFFFFFFF:7359B2163E4EDC58 +DES-ECB:3000000000000000::1000000000000001:958E6E627A05557B +DES-ECB:1111111111111111::1111111111111111:F40379AB9E0EC533 +DES-ECB:0123456789ABCDEF::1111111111111111:17668DFC7292532D +DES-ECB:1111111111111111::0123456789ABCDEF:8A5AE1F81AB8F2DD +DES-ECB:FEDCBA9876543210::0123456789ABCDEF:ED39D950FA74BCC4 + +# DESX-CBC tests (from destest) +DESX-CBC:0123456789abcdeff1e0d3c2b5a49786fedcba9876543210:fedcba9876543210:37363534333231204E6F77206973207468652074696D6520666F722000000000:846B2914851E9A2954732F8AA0A611C115CDC2D7951B1053A63C5E03B21AA3C4 + +# DES EDE3 CBC tests (from destest) +DES-EDE3-CBC:0123456789abcdeff1e0d3c2b5a49786fedcba9876543210:fedcba9876543210:37363534333231204E6F77206973207468652074696D6520666F722000000000:3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675 + +# RC4 tests (from rc4test) +RC4:0123456789abcdef0123456789abcdef::0123456789abcdef:75b7878099e0c596 +RC4:0123456789abcdef0123456789abcdef::0000000000000000:7494c2e7104b0879 +RC4:00000000000000000000000000000000::0000000000000000:de188941a3375d3a +RC4:ef012345ef012345ef012345ef012345::0000000000000000000000000000000000000000:d6a141a7ec3c38dfbd615a1162e1c7ba36b67858 +RC4:0123456789abcdef0123456789abcdef::123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678:66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf +RC4:ef012345ef012345ef012345ef012345::00000000000000000000:d6a141a7ec3c38dfbd61 + + +# Camellia tests from RFC3713 +# For all ECB encrypts and decrypts, the transformed sequence is +# CAMELLIA-bits-ECB:key::plaintext:ciphertext:encdec +CAMELLIA-128-ECB:0123456789abcdeffedcba9876543210::0123456789abcdeffedcba9876543210:67673138549669730857065648eabe43 +CAMELLIA-192-ECB:0123456789abcdeffedcba98765432100011223344556677::0123456789abcdeffedcba9876543210:b4993401b3e996f84ee5cee7d79b09b9 +CAMELLIA-256-ECB:0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff::0123456789abcdeffedcba9876543210:9acc237dff16d76c20ef7c919e3a7509 + +# ECB-CAMELLIA128.Encrypt +CAMELLIA-128-ECB:000102030405060708090A0B0C0D0E0F::00112233445566778899AABBCCDDEEFF:77CF412067AF8270613529149919546F:1 +CAMELLIA-192-ECB:000102030405060708090A0B0C0D0E0F1011121314151617::00112233445566778899AABBCCDDEEFF:B22F3C36B72D31329EEE8ADDC2906C68:1 +CAMELLIA-256-ECB:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F::00112233445566778899AABBCCDDEEFF:2EDF1F3418D53B88841FC8985FB1ECF2:1 + +# ECB-CAMELLIA128.Encrypt and ECB-CAMELLIA128.Decrypt +CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::6BC1BEE22E409F96E93D7E117393172A:432FC5DCD628115B7C388D770B270C96 +CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::AE2D8A571E03AC9C9EB76FAC45AF8E51:0BE1F14023782A22E8384C5ABB7FAB2B +CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::30C81C46A35CE411E5FBC1191A0A52EF:A0A1ABCD1893AB6FE0FE5B65DF5F8636 +CAMELLIA-128-ECB:2B7E151628AED2A6ABF7158809CF4F3C::F69F2445DF4F9B17AD2B417BE66C3710:E61925E0D5DFAA9BB29F815B3076E51A + +# ECB-CAMELLIA192.Encrypt and ECB-CAMELLIA192.Decrypt +CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::6BC1BEE22E409F96E93D7E117393172A:CCCC6C4E138B45848514D48D0D3439D3 +CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::AE2D8A571E03AC9C9EB76FAC45AF8E51:5713C62C14B2EC0F8393B6AFD6F5785A +CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::30C81C46A35CE411E5FBC1191A0A52EF:B40ED2B60EB54D09D030CF511FEEF366 +CAMELLIA-192-ECB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B::F69F2445DF4F9B17AD2B417BE66C3710:909DBD95799096748CB27357E73E1D26 + +# ECB-CAMELLIA256.Encrypt and ECB-CAMELLIA256.Decrypt +CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::6BC1BEE22E409F96E93D7E117393172A:BEFD219B112FA00098919CD101C9CCFA +CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::AE2D8A571E03AC9C9EB76FAC45AF8E51:C91D3A8F1AEA08A9386CF4B66C0169EA +CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::30C81C46A35CE411E5FBC1191A0A52EF:A623D711DC5F25A51BB8A80D56397D28 +CAMELLIA-256-ECB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4::F69F2445DF4F9B17AD2B417BE66C3710:7960109FB6DC42947FCFE59EA3C5EB6B + +# For all CBC encrypts and decrypts, the transformed sequence is +# CAMELLIA-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec +# CBC-CAMELLIA128.Encrypt and CBC-CAMELLIA128.Decrypt +CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:1607CF494B36BBF00DAEB0B503C831AB +CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:1607CF494B36BBF00DAEB0B503C831AB:AE2D8A571E03AC9C9EB76FAC45AF8E51:A2F2CF671629EF7840C5A5DFB5074887 +CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:A2F2CF671629EF7840C5A5DFB5074887:30C81C46A35CE411E5FBC1191A0A52EF:0F06165008CF8B8B5A63586362543E54 +CAMELLIA-128-CBC:2B7E151628AED2A6ABF7158809CF4F3C:36A84CDAFD5F9A85ADA0F0A993D6D577:F69F2445DF4F9B17AD2B417BE66C3710:74C64268CDB8B8FAF5B34E8AF3732980 + +# CBC-CAMELLIA192.Encrypt and CBC-CAMELLIA192.Decrypt +CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:2A4830AB5AC4A1A2405955FD2195CF93 +CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:2A4830AB5AC4A1A2405955FD2195CF93:AE2D8A571E03AC9C9EB76FAC45AF8E51:5D5A869BD14CE54264F892A6DD2EC3D5 +CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:5D5A869BD14CE54264F892A6DD2EC3D5:30C81C46A35CE411E5FBC1191A0A52EF:37D359C3349836D884E310ADDF68C449 +CAMELLIA-192-CBC:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:37D359C3349836D884E310ADDF68C449:F69F2445DF4F9B17AD2B417BE66C3710:01FAAA930B4AB9916E9668E1428C6B08 + +# CBC-CAMELLIA256.Encrypt and CBC-CAMELLIA256.Decrypt +CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:E6CFA35FC02B134A4D2C0B6737AC3EDA +CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E6CFA35FC02B134A4D2C0B6737AC3EDA:AE2D8A571E03AC9C9EB76FAC45AF8E51:36CBEB73BD504B4070B1B7DE2B21EB50 +CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:36CBEB73BD504B4070B1B7DE2B21EB50:30C81C46A35CE411E5FBC1191A0A52EF:E31A6055297D96CA3330CDF1B1860A83 +CAMELLIA-256-CBC:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E31A6055297D96CA3330CDF1B1860A83:F69F2445DF4F9B17AD2B417BE66C3710:5D563F6D1CCCF236051C0C5C1C58F28F + +# We don't support CFB{1,8}-CAMELLIAxxx.{En,De}crypt +# For all CFB128 encrypts and decrypts, the transformed sequence is +# CAMELLIA-bits-CFB:key:IV/ciphertext':plaintext:ciphertext:encdec +# CFB128-CAMELLIA128.Encrypt +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:1 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:1 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:9C2157A664626D1DEF9EA420FDE69B96:F69F2445DF4F9B17AD2B417BE66C3710:742A25F0542340C7BAEF24CA8482BB09:1 + +# CFB128-CAMELLIA128.Decrypt +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:14F7646187817EB586599146B82BD719:AE2D8A571E03AC9C9EB76FAC45AF8E51:A53D28BB82DF741103EA4F921A44880B:0 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:A53D28BB82DF741103EA4F921A44880B:30C81C46A35CE411E5FBC1191A0A52EF:9C2157A664626D1DEF9EA420FDE69B96:0 +CAMELLIA-128-CFB:2B7E151628AED2A6ABF7158809CF4F3C:9C2157A664626D1DEF9EA420FDE69B96:F69F2445DF4F9B17AD2B417BE66C3710:742A25F0542340C7BAEF24CA8482BB09:0 + +# CFB128-CAMELLIA192.Encrypt +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:1 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:C832BB9780677DAA82D9B6860DCD565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:86F8491627906D780C7A6D46EA331F98:1 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:86F8491627906D780C7A6D46EA331F98:30C81C46A35CE411E5FBC1191A0A52EF:69511CCE594CF710CB98BB63D7221F01:1 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:69511CCE594CF710CB98BB63D7221F01:F69F2445DF4F9B17AD2B417BE66C3710:D5B5378A3ABED55803F25565D8907B84:1 + +# CFB128-CAMELLIA192.Decrypt +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:0 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:C832BB9780677DAA82D9B6860DCD565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:86F8491627906D780C7A6D46EA331F98:0 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:86F8491627906D780C7A6D46EA331F98:30C81C46A35CE411E5FBC1191A0A52EF:69511CCE594CF710CB98BB63D7221F01:0 +CAMELLIA-192-CFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:69511CCE594CF710CB98BB63D7221F01:F69F2445DF4F9B17AD2B417BE66C3710:D5B5378A3ABED55803F25565D8907B84:0 + +# CFB128-CAMELLIA256.Encrypt +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:1 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:1 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:555FC3F34BDD2D54C62D9E3BF338C1C4:F69F2445DF4F9B17AD2B417BE66C3710:5953ADCE14DB8C7F39F1BD39F359BFFA:1 + +# CFB128-CAMELLIA256.Decrypt +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:CF6107BB0CEA7D7FB1BD31F5E7B06C93:AE2D8A571E03AC9C9EB76FAC45AF8E51:89BEDB4CCDD864EA11BA4CBE849B5E2B:0 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:89BEDB4CCDD864EA11BA4CBE849B5E2B:30C81C46A35CE411E5FBC1191A0A52EF:555FC3F34BDD2D54C62D9E3BF338C1C4:0 +CAMELLIA-256-CFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:555FC3F34BDD2D54C62D9E3BF338C1C4:F69F2445DF4F9B17AD2B417BE66C3710:5953ADCE14DB8C7F39F1BD39F359BFFA:0 + +# For all OFB encrypts and decrypts, the transformed sequence is +# CAMELLIA-bits-OFB:key:IV/output':plaintext:ciphertext:encdec +# OFB-CAMELLIA128.Encrypt +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:1 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:1 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:1 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:1 + +# OFB-CAMELLIA128.Decrypt +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:14F7646187817EB586599146B82BD719:0 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:50FE67CC996D32B6DA0937E99BAFEC60:AE2D8A571E03AC9C9EB76FAC45AF8E51:25623DB569CA51E01482649977E28D84:0 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:D9A4DADA0892239F6B8B3D7680E15674:30C81C46A35CE411E5FBC1191A0A52EF:C776634A60729DC657D12B9FCA801E98:0 +CAMELLIA-128-OFB:2B7E151628AED2A6ABF7158809CF4F3C:A78819583F0308E7A6BF36B1386ABF23:F69F2445DF4F9B17AD2B417BE66C3710:D776379BE0E50825E681DA1A4C980E8E:0 + +# OFB-CAMELLIA192.Encrypt +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:1 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:1 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:1 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:1 + +# OFB-CAMELLIA192.Decrypt +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:C832BB9780677DAA82D9B6860DCD565E:0 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:A609B38DF3B1133DDDFF2718BA09565E:AE2D8A571E03AC9C9EB76FAC45AF8E51:8ECEB7D0350D72C7F78562AEBDF99339:0 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:52EF01DA52602FE0975F78AC84BF8A50:30C81C46A35CE411E5FBC1191A0A52EF:BDD62DBBB9700846C53B507F544696F0:0 +CAMELLIA-192-OFB:8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B:BD5286AC63AABD7EB067AC54B553F71D:F69F2445DF4F9B17AD2B417BE66C3710:E28014E046B802F385C4C2E13EAD4A72:0 + +# OFB-CAMELLIA256.Encrypt +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:1 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:1 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:1 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:1 + +# OFB-CAMELLIA256.Decrypt +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:000102030405060708090A0B0C0D0E0F:6BC1BEE22E409F96E93D7E117393172A:CF6107BB0CEA7D7FB1BD31F5E7B06C93:0 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:B7BF3A5DF43989DD97F0FA97EBCE2F4A:AE2D8A571E03AC9C9EB76FAC45AF8E51:127AD97E8E3994E4820027D7BA109368:0 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:E1C656305ED1A7A6563805746FE03EDC:30C81C46A35CE411E5FBC1191A0A52EF:6BFF6265A6A6B7A535BC65A80B17214E:0 +CAMELLIA-256-OFB:603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4:41635BE625B48AFC1666DD42A09D96E7:F69F2445DF4F9B17AD2B417BE66C3710:0A4A0404E26AA78A27CB271E8BF3CF20:0 + +# SEED test vectors from RFC4269 +SEED-ECB:00000000000000000000000000000000::000102030405060708090A0B0C0D0E0F:5EBAC6E0054E166819AFF1CC6D346CDB:0 +SEED-ECB:000102030405060708090A0B0C0D0E0F::00000000000000000000000000000000:C11F22F20140505084483597E4370F43:0 +SEED-ECB:4706480851E61BE85D74BFB3FD956185::83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:0 +SEED-ECB:28DBC3BC49FFD87DCFA509B11D422BE7::B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:0 +SEED-ECB:00000000000000000000000000000000::000102030405060708090A0B0C0D0E0F:5EBAC6E0054E166819AFF1CC6D346CDB:1 +SEED-ECB:000102030405060708090A0B0C0D0E0F::00000000000000000000000000000000:C11F22F20140505084483597E4370F43:1 +SEED-ECB:4706480851E61BE85D74BFB3FD956185::83A2F8A288641FB9A4E9A5CC2F131C7D:EE54D13EBCAE706D226BC3142CD40D4A:1 +SEED-ECB:28DBC3BC49FFD87DCFA509B11D422BE7::B41E6BE2EBA84A148E2EED84593C5EC7:9B9B7BFCD1813CB95D0B3618F40F5122:1 + +# ChaCha test vectors +ChaCha:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586:1 +ChaCha:0000000000000000000000000000000000000000000000000000000000000000:01000000000000000000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f:1 +ChaCha:0000000000000000000000000000000000000000000000000000000000000001:01000000000000000000000000000002:416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f:a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221:1 +ChaCha:1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0:2a000000000000000000000000000002:2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e:62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1:1 +ChaCha:0000000000000000000000000000000000000000000000000000000000000001:00000000000000000000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:4540f05a9f1fb296d7736e7b208e3c96eb4fe1834688d2604f450952ed432d41bbe2a0b6ea7566d2a5d1e7e20d42af2c53d792b1c43fea817e9ad275ae546963:1 +ChaCha:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000000000000000001:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:de9cba7bf3d69ef5e786dc63973f653a0b49e015adbff7134fcb7df137821031e85a050278a7084527214f73efc7fa5b5277062eb7a0433e445f41e31afab757:1 +ChaCha:0000000000000000000000000000000000000000000000000000000000000000:00000000000000000100000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:ef3fdfd6c61578fbf5cf35bd3dd33b8009631634d21e42ac33960bd138e50d32111e4caf237ee53ca8ad6426194a88545ddc497a0b466e7d6bbdb0041b2f586b:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c9:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c730:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444a:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF1798:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF17980D6E7E67E861E28201C1EE30B441040FD06878D65042C95582A4318207BFC700BE0CE32889AEC2FFE5085E8967910D879FA0E8C0FF85FDC510B9FF2FBF87CFCB:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF17980D6E7E67E861E28201C1EE30B441040FD06878D65042C95582A4318207BFC700BE0CE32889AEC2FFE5085E8967910D879FA0E8C0FF85FDC510B9FF2FBF87CFCB29577D68099E04FFA05F752A73D377C70D3A8BC2DA80E6E780EC057182C33AD1DE387252258A1E18E6FAD910327CE7F42FD1E1E0515F9586E2F2EFCB9F472B1D:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF17980D6E7E67E861E28201C1EE30B441040FD06878D65042C95582A4318207BFC700BE0CE32889AEC2FFE5085E8967910D879FA0E8C0FF85FDC510B9FF2FBF87CFCB29577D68099E04FFA05F752A73D377C70D3A8BC2DA80E6E780EC057182C33AD1DE387252258A1E18E6FAD910327CE7F42FD1E1E0515F9586E2F2EFCB9F472B1DBDBAC354A4162151E9D92C79FB08BB4DDC56F19448C0175A46E2E6C491FEC71419AA43A349BEA768A92C75DE68FD9591E68067F3197094D3FB87ED81785EA075:1 +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF17980D6E7E67E861E28201C1EE30B441040FD06878D65042C95582A4318207BFC700BE0CE32889AEC2FFE5085E8967910D879FA0E8C0FF85FDC510B9FF2FBF87CFCB29577D68099E04FFA05F752A73D377C70D3A8BC2DA80E6E780EC057182C33AD1DE387252258A1E18E6FAD910327CE7F42FD1E1E0515F9586E2F2EFCB9F472B1DBDBAC354A4162151E9D92C79FB08BB4DDC56F19448C0175A46E2E6C491FEC71419AA43A349BEA768A92C75DE68FD9591E68067F3197094D3FB87ED81785EA075E4B65E3E4C78F81DA9B751C5EFE024152301C48E63245B556C4C67AFF857E5EA15A908D83A1D9704F8E55E7352B20B694BF9970298E6B5AAD33EA2155D105D4E:1 + +ChaCha:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f:00000000000000000001020304050607:0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f798a189f195e66982105ffb640bb7757f579da31602fc93ec01ac56f85ac3c134a4547b733b46413042c9440049176905d3be59ea1c53f15916155c2be8241a38008b9a26bc35941e2444177c8ade6689de95264986d95889fb60e84629c9bd9a5acb1cc118be563eb9b3a4a472f82e09a7e778492b562ef7130e88dfe031c79db9d4f7c7a899151b9a475032b63fc385245fe054e3dd5a97a5f576fe064025d3ce042c566ab2c507b138db853e3d6959660996546cc9c4a6eafdc777c040d70eaf46f76dad3979e5c5360c3317166a1c894c94a371876a94df7628fe4eaaf2ccb27d5aaae0ad7ad0f9d4b6ad3b54098746d4524d38407a6deb3ab78fab78c94213668bbbd394c5de93b853178addd6b97f9fa1ec3e56c00c9ddff0a44a204241175a4cab0f961ba53ede9bdf960b94f9829b1f3414726429b362c5b538e391520f489b7ed8d20ae3fd49e9e259e44397514d618c96c4846be3c680bdc11c71dcbbe29ccf80d62a0938fa549391e6ea57ecbe2606790ec15d2224ae307c144226b7c4e8c2f97d2a1d67852d29beba110edd445197012062a393a9c92803ad3b4f31d7bc6033ccf7932cfed3f019044d25905916777286f82f9a4cc1ffe430ffd1dcfc27deed327b9f9630d2fa969fb6f0603cd19dd9a9519e673bcfcd9014125291a44669ef7285e74ed3729b677f801c3cdf058c50963168b496043716c7307cd9e0cdd137fccb0f05b47cdbb95c5f54831622c3652a32b2531fe326bcd6e2bbf56a194fa196fbd1a54952110f51c73433865f7664b836685e3664b3d8444aF89A242805E18C975F1146324996FDE17007CF3E6E8F4E764022533EDBFE07D4733E48BB372D75B0EF48EC983EB78532161CC529E5ABB89837DFCCA6261DBB37C7C5E6A87478BF41EE85A518C0F4EFA9BDE828C5A71B8E46597B634AFD204D3C501334239C3414285ED72D3A9169EABBD4DC25D52BB7516D3BA712D75AD8C0AE5D493C19E38A77939E7A058D713E9CCCCA58045F436B434B1C80D365472406E392951987DB6905C80D431DA18451135BE7E82BCAB358CB3971E61405B2FF17980D6E7E67E861E28201C1EE30B441040FD06878D65042C95582A4318207BFC700BE0CE32889AEC2FFE5085E8967910D879FA0E8C0FF85FDC510B9FF2FBF87CFCB29577D68099E04FFA05F752A73D377C70D3A8BC2DA80E6E780EC057182C33AD1DE387252258A1E18E6FAD910327CE7F42FD1E1E0515F9586E2F2EFCB9F472B1DBDBAC354A4162151E9D92C79FB08BB4DDC56F19448C0175A46E2E6C491FEC71419AA43A349BEA768A92C75DE68FD9591E68067F3197094D3FB87ED81785EA075E4B65E3E4C78F81DA9B751C5EFE024152301C48E63245B556C4C67AFF857E5EA15A908D83A1D9704F8E55E7352B20B694BF9970298E6B5AAD33EA2155D105D4E637D1E87C40A8E5F4E8C5A16A4B8F3DC27B31721D77A65FD1ED6F86BE25FB95DB29B1988493770A7C60E451FF97DD241A236851FC425691979FE30226559AD95:1 +ChaCha:0100000000000000000000000000000000000000000000000000000000000000:000000000000000000000000000000000000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:c5d30a7ce1ec119378c84f487d775a8542f13ece238a9455e8229e888de85bbd29eb63d0a17a5b999b52da22be4023eb07620a54f6fa6ad8737b71eb0464dac0:1 +ChaCha:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff:0000000000000000ffffffffffffffff0000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:d9bf3f6bce6ed0b54254557767fb57443dd4778911b606055c39cc25e674b8363feabc57fde54f790c52c8ae43240b79d49042b777bfd6cb80e931270b7f50eb:1 +ChaCha:5555555555555555555555555555555555555555555555555555555555555555:0000000000000000aaaaaaaaaaaaaaaa0000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:aff7418293f3a553894b1e7484bd1e8ede196eced5a1d6814de37091e07e076e34bbba8107a686c982850f0a7353940d40db1ab0b5765b78b4cf473d9485a3dd:1 +ChaCha:5555555555555555555555555555555555555555555555555555555555555555:000000000000000055555555555555550000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:bea9411aa453c5434a5ae8c92862f564396855a9ea6e22d6d3b50ae1b3663311a4a3606c671d605ce16c3aece8e61ea145c59775017bee2fa6f88afc758069f7:1 +ChaCha:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:0000000000000000aaaaaaaaaaaaaaaa0000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9aa2a9f656efde5aa7591c5fed4b35aea2895dec7cb4543b9e9f21f5e7bcbcf3c43c748a970888f8248393a09d43e0b7e164bc4d0b0fb240a2d72115c4808906:1 +ChaCha:00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100:00000000000000000f1e2d3c4b5a69780000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931:1 +ChaCha:c46ec1b18ce8a878725a37e780dfb7351f68ed2e194c79fbc6aebee1a667975d:00000000000000001ada31d5cf6882210000000000000000:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:f63a89b75c2271f9368816542ba52f06ed49241792302b00b5e8f80ae9a473afc25b218f519af0fdd406362e8d69de7f54c604a6e00f353f110f771bdca8ab92:1 diff --git a/tests/expirecallback.c b/tests/expirecallback.c new file mode 100644 index 0000000..88cef6f --- /dev/null +++ b/tests/expirecallback.c @@ -0,0 +1,321 @@ +/* $OpenBSD: expirecallback.c,v 1.3 2023/01/28 19:12:20 tb Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * Copyright (c) 2020-2021 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "x509_verify.h" + +#define MODE_MODERN_VFY 0 +#define MODE_MODERN_VFY_DIR 1 +#define MODE_LEGACY_VFY 2 +#define MODE_VERIFY 3 + +static int verbose = 1; + +static int +passwd_cb(char *buf, int size, int rwflag, void *u) +{ + memset(buf, 0, size); + return (0); +} + +static int +certs_from_file(const char *filename, STACK_OF(X509) **certs) +{ + STACK_OF(X509_INFO) *xis = NULL; + STACK_OF(X509) *xs = NULL; + BIO *bio = NULL; + X509 *x; + int i; + + if ((xs = sk_X509_new_null()) == NULL) + errx(1, "failed to create X509 stack"); + if ((bio = BIO_new_file(filename, "r")) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to create bio"); + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, passwd_cb, NULL)) == NULL) + errx(1, "failed to read PEM"); + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + if ((x = sk_X509_INFO_value(xis, i)->x509) == NULL) + continue; + if (!sk_X509_push(xs, x)) + errx(1, "failed to push X509"); + X509_up_ref(x); + } + + *certs = xs; + xs = NULL; + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + sk_X509_pop_free(xs, X509_free); + BIO_free(bio); + + return 1; +} + +static int +verify_cert_cb(int ok, X509_STORE_CTX *xsc) +{ + X509 *current_cert; + int verify_err; + + current_cert = X509_STORE_CTX_get_current_cert(xsc); + if (current_cert != NULL) { + X509_NAME_print_ex_fp(stderr, + X509_get_subject_name(current_cert), 0, + XN_FLAG_ONELINE); + fprintf(stderr, "\n"); + } + + verify_err = X509_STORE_CTX_get_error(xsc); + if (verify_err != X509_V_OK) { + if (verify_err == X509_V_ERR_CERT_HAS_EXPIRED) + fprintf(stderr, "IGNORING "); + fprintf(stderr, "verify error at depth %d: %s\n", + X509_STORE_CTX_get_error_depth(xsc), + X509_verify_cert_error_string(verify_err)); + } + + /* + * Ignore expired certs, in the way people are told to do it + * by OpenSSL + */ + + if (verify_err == X509_V_ERR_CERT_HAS_EXPIRED) + return 1; + + return ok; +} + +static void +verify_cert(const char *roots_dir, const char *roots_file, + const char *bundle_file, int *chains, int *error, int *error_depth, + int mode) +{ + STACK_OF(X509) *roots = NULL, *bundle = NULL; + X509_STORE_CTX *xsc = NULL; + X509_STORE *store = NULL; + X509 *leaf = NULL; + int use_dir; + int ret; + + *chains = 0; + *error = 0; + *error_depth = 0; + + use_dir = (mode == MODE_MODERN_VFY_DIR); + + if (!use_dir && !certs_from_file(roots_file, &roots)) + errx(1, "failed to load roots from '%s'", roots_file); + if (!certs_from_file(bundle_file, &bundle)) + errx(1, "failed to load bundle from '%s'", bundle_file); + if (sk_X509_num(bundle) < 1) + errx(1, "not enough certs in bundle"); + leaf = sk_X509_shift(bundle); + + if ((xsc = X509_STORE_CTX_new()) == NULL) + errx(1, "X509_STORE_CTX"); + if (use_dir && (store = X509_STORE_new()) == NULL) + errx(1, "X509_STORE"); + if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) { + ERR_print_errors_fp(stderr); + errx(1, "failed to init store context"); + } + + if (use_dir) { + if (!X509_STORE_load_locations(store, NULL, roots_dir)) + errx(1, "failed to set by_dir directory of %s", roots_dir); + } + if (mode == MODE_LEGACY_VFY) + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_LEGACY_VERIFY); + else + X509_VERIFY_PARAM_clear_flags(X509_STORE_CTX_get0_param(xsc), + X509_V_FLAG_LEGACY_VERIFY); + + if (verbose) + X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); + if (!use_dir) + X509_STORE_CTX_set0_trusted_stack(xsc, roots); + + ret = X509_verify_cert(xsc); + + *error = X509_STORE_CTX_get_error(xsc); + *error_depth = X509_STORE_CTX_get_error_depth(xsc); + + if (ret == 1) { + *chains = 1; /* XXX */ + goto done; + } + + if (*error == 0) + errx(1, "Error unset on failure!\n"); + + fprintf(stderr, "failed to verify at %d: %s\n", + *error_depth, X509_verify_cert_error_string(*error)); + + done: + sk_X509_pop_free(roots, X509_free); + sk_X509_pop_free(bundle, X509_free); + X509_STORE_free(store); + X509_STORE_CTX_free(xsc); + X509_free(leaf); +} + +struct verify_cert_test { + const char *id; + int want_chains; + int want_error; + int want_error_depth; + int want_legacy_error; + int want_legacy_error_depth; + int failing; +}; + +struct verify_cert_test verify_cert_tests[] = { + { + .id = "2a", + .want_chains = 1, + .want_error = 0, + .want_error_depth = 0, + .want_legacy_error = 0, + .want_legacy_error_depth = 0, + }, + { + .id = "8a", + .want_chains = 1, + .want_error = X509_V_ERR_CERT_HAS_EXPIRED, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_CERT_HAS_EXPIRED, + .want_legacy_error_depth = 0, + }, + { + .id = "9a", + .want_chains = 1, + .want_error = X509_V_ERR_CERT_HAS_EXPIRED, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + .want_legacy_error_depth = 0, + .failing = 1, + }, +}; + +#define N_VERIFY_CERT_TESTS \ + (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests)) + +static int +verify_cert_test(const char *certs_path, int mode) +{ + char *roots_file, *bundle_file, *roots_dir; + struct verify_cert_test *vct; + int chains, error, error_depth; + int failed = 0; + size_t i; + + for (i = 0; i < N_VERIFY_CERT_TESTS; i++) { + vct = &verify_cert_tests[i]; + + if (asprintf(&roots_file, "%s/%s/roots.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&bundle_file, "%s/%s/bundle.pem", certs_path, + vct->id) == -1) + errx(1, "asprintf"); + if (asprintf(&roots_dir, "./%s/roots", vct->id) == -1) + errx(1, "asprintf"); + + fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); + verify_cert(roots_dir, roots_file, bundle_file, &chains, &error, + &error_depth, mode); + + if ((mode == MODE_VERIFY && chains == vct->want_chains) || + (chains == 0 && vct->want_chains == 0) || + (chains == 1 && vct->want_chains > 0)) { + fprintf(stderr, "INFO: Succeeded with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (mode == MODE_LEGACY_VFY && vct->failing) + failed |= 1; + } else { + fprintf(stderr, "FAIL: Failed with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (!vct->failing) + failed |= 1; + } + + if (mode == MODE_LEGACY_VFY) { + if (error != vct->want_legacy_error) { + fprintf(stderr, "FAIL: Got legacy error %d, " + "want %d\n", error, vct->want_legacy_error); + failed |= 1; + } + if (error_depth != vct->want_legacy_error_depth) { + fprintf(stderr, "FAIL: Got legacy error depth " + "%d, want %d\n", error_depth, + vct->want_legacy_error_depth); + failed |= 1; + } + } else if (mode == MODE_MODERN_VFY || mode == MODE_MODERN_VFY_DIR) { + if (error != vct->want_error) { + fprintf(stderr, "FAIL: Got error %d, want %d\n", + error, vct->want_error); + failed |= 1; + } + if (error_depth != vct->want_error_depth) { + fprintf(stderr, "FAIL: Got error depth %d, want" + " %d\n", error_depth, vct->want_error_depth); + failed |= 1; + } + } + + fprintf(stderr, "\n"); + + free(roots_file); + free(bundle_file); + free(roots_dir); + } + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + + fprintf(stderr, "\n\nTesting legacy x509_vfy\n"); + failed |= verify_cert_test(argv[1], MODE_LEGACY_VFY); + fprintf(stderr, "\n\nTesting modern x509_vfy\n"); + failed |= verify_cert_test(argv[1], MODE_MODERN_VFY); + fprintf(stderr, "\n\nTesting modern x509_vfy by_dir\n"); + failed |= verify_cert_test(argv[1], MODE_MODERN_VFY_DIR); + + return (failed); +} diff --git a/tests/explicit_bzero.c b/tests/explicit_bzero.c new file mode 100644 index 0000000..496bafb --- /dev/null +++ b/tests/explicit_bzero.c @@ -0,0 +1,225 @@ +/* $OpenBSD: explicit_bzero.c,v 1.9 2022/02/10 08:39:32 tb Exp $ */ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#define ASSERT_EQ(a, b) assert((a) == (b)) +#define ASSERT_NE(a, b) assert((a) != (b)) +#define ASSERT_GE(a, b) assert((a) >= (b)) + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define __SANITIZE_ADDRESS__ +#endif +#endif +#ifdef __SANITIZE_ADDRESS__ +#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#else +#define ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +/* 128 bits of random data. */ +static const char secret[16] = { + 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c, + 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96, +}; + +enum { + SECRETCOUNT = 64, + SECRETBYTES = SECRETCOUNT * sizeof(secret) +}; + +/* + * As of glibc 2.34, when _GNU_SOURCE is defined, SIGSTKSZ is no longer + * constant on Linux. SIGSTKSZ is redefined to sysconf (_SC_SIGSTKSZ). + */ +static char *altstack; +#define ALTSTACK_SIZE (SIGSTKSZ + SECRETBYTES) + +static void +setup_stack(void) +{ + altstack = calloc(1, ALTSTACK_SIZE); + ASSERT_NE(NULL, altstack); + + const stack_t sigstk = { + .ss_sp = altstack, + .ss_size = ALTSTACK_SIZE + }; + + ASSERT_EQ(0, sigaltstack(&sigstk, NULL)); +} + +static void +cleanup_stack(void) +{ + free(altstack); +} + +static void +assert_on_stack(void) +{ + stack_t cursigstk; + ASSERT_EQ(0, sigaltstack(NULL, &cursigstk)); + ASSERT_EQ(SS_ONSTACK, cursigstk.ss_flags & (SS_DISABLE|SS_ONSTACK)); +} + +static void +call_on_stack(void (*fn)(int)) +{ + /* + * This is a bit more complicated than strictly necessary, but + * it ensures we don't have any flaky test failures due to + * inherited signal masks/actions/etc. + * + * On systems where SA_ONSTACK is not supported, this could + * alternatively be implemented using makecontext() or + * pthread_attr_setstack(). + */ + + const struct sigaction sigact = { + .sa_handler = fn, + .sa_flags = SA_ONSTACK, + }; + struct sigaction oldsigact; + sigset_t sigset, oldsigset; + + /* First, block all signals. */ + ASSERT_EQ(0, sigemptyset(&sigset)); + ASSERT_EQ(0, sigfillset(&sigset)); + ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset, &oldsigset)); + + /* Next setup the signal handler for SIGUSR1. */ + ASSERT_EQ(0, sigaction(SIGUSR1, &sigact, &oldsigact)); + + /* Raise SIGUSR1 and momentarily unblock it to run the handler. */ + ASSERT_EQ(0, raise(SIGUSR1)); + ASSERT_EQ(0, sigdelset(&sigset, SIGUSR1)); + ASSERT_EQ(-1, sigsuspend(&sigset)); + ASSERT_EQ(EINTR, errno); + + /* Restore the original signal action, stack, and mask. */ + ASSERT_EQ(0, sigaction(SIGUSR1, &oldsigact, NULL)); + ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL)); +} + +static void +populate_secret(char *buf, size_t len) +{ + int i, fds[2]; + ASSERT_EQ(0, pipe(fds)); + + for (i = 0; i < SECRETCOUNT; i++) + ASSERT_EQ(sizeof(secret), write(fds[1], secret, sizeof(secret))); + ASSERT_EQ(0, close(fds[1])); + + ASSERT_EQ(len, read(fds[0], buf, len)); + ASSERT_EQ(0, close(fds[0])); +} + +static int +count_secrets(const char *buf) +{ + int res = 0; + size_t i; + for (i = 0; i < SECRETCOUNT; i++) { + if (memcmp(buf + i * sizeof(secret), secret, + sizeof(secret)) == 0) + res += 1; + } + return (res); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static char * +test_without_bzero(void) +{ + char buf[SECRETBYTES]; + assert_on_stack(); + populate_secret(buf, sizeof(buf)); + char *res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf)); + ASSERT_NE(NULL, res); + return (res); +} + +ATTRIBUTE_NO_SANITIZE_ADDRESS static char * +test_with_bzero(void) +{ + char buf[SECRETBYTES]; + assert_on_stack(); + populate_secret(buf, sizeof(buf)); + char *res = memmem(altstack, ALTSTACK_SIZE, buf, sizeof(buf)); + ASSERT_NE(NULL, res); + explicit_bzero(buf, sizeof(buf)); + return (res); +} + +static void +do_test_without_bzero(int signo) +{ + char *buf = test_without_bzero(); + ASSERT_GE(count_secrets(buf), 1); +} + +static void +do_test_with_bzero(int signo) +{ + char *buf = test_with_bzero(); + ASSERT_EQ(count_secrets(buf), 0); +} + +int +main(void) +{ + setup_stack(); + + /* + * Solaris and OS X clobber the signal stack after returning to the + * normal stack, so we need to inspect altstack while we're still + * running on it. Unfortunately, this means we risk clobbering the + * buffer ourselves. + * + * To minimize this risk, test_with{,out}_bzero() are responsible for + * locating the offset of their buf variable within altstack, and + * and returning that address. Then we can simply memcmp() repeatedly + * to count how many instances of secret we found. + */ + + /* + * First, test that if we *don't* call explicit_bzero, that we + * *are* able to find at least one instance of the secret data still + * on the stack. This sanity checks that call_on_stack() and + * populate_secret() work as intended. + */ + memset(altstack, 0, ALTSTACK_SIZE); + call_on_stack(do_test_without_bzero); + + /* + * Now test with a call to explicit_bzero() and check that we + * *don't* find any instances of the secret data. + */ + memset(altstack, 0, ALTSTACK_SIZE); + call_on_stack(do_test_with_bzero); + + cleanup_stack(); + + return (0); +} diff --git a/tests/exportertest.c b/tests/exportertest.c new file mode 100644 index 0000000..252fcb0 --- /dev/null +++ b/tests/exportertest.c @@ -0,0 +1,664 @@ +/* $OpenBSD: exportertest.c,v 1.3 2023/04/14 14:23:05 tb Exp $ */ +/* + * Copyright (c) 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include "ssl_local.h" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +struct exporter_test { + uint16_t tls_version; + unsigned int cipher_id; + const uint8_t *label; + size_t label_len; + const uint8_t context_value[64]; + size_t context_value_len; + int use_context; + const uint8_t client_random[SSL3_RANDOM_SIZE]; + const uint8_t server_random[SSL3_RANDOM_SIZE]; + const uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH]; + const uint8_t shared_key[64]; + size_t shared_key_len; + const uint8_t export[64]; + size_t export_len; + int want_error; +}; + +static const struct exporter_test exporter_tests[] = { + { + /* Valid export, no context - 32 bytes. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0x14, 0x08, 0x00, 0x9e, 0x6a, 0x67, 0x75, 0x4c, + 0xc4, 0xf3, 0x51, 0x57, 0x2f, 0x75, 0x0b, 0xf8, + 0x16, 0xfa, 0x61, 0x74, 0xd2, 0x12, 0x8f, 0x78, + 0x77, 0xf9, 0x8a, 0x3e, 0x58, 0x70, 0xf3, 0xd8, + }, + .export_len = 32, + }, + { + /* Valid export, no context - 32 bytes. */ + .tls_version = TLS1_3_VERSION, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .use_context = 0, + .shared_key = { + 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, + }, + .shared_key_len = 32, + .export = { + 0x69, 0xf4, 0xac, 0xec, 0x80, 0x67, 0xac, 0x5c, + 0xa6, 0x24, 0x47, 0xb1, 0x0f, 0xc8, 0xa1, 0x13, + 0x3b, 0x91, 0x33, 0x82, 0x97, 0x0a, 0xc0, 0xbf, + 0xac, 0x6d, 0x6b, 0x34, 0x20, 0xd3, 0x3a, 0x02, + }, + .export_len = 32, + }, + { + /* Valid export, no context - 64 bytes. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0x14, 0x08, 0x00, 0x9e, 0x6a, 0x67, 0x75, 0x4c, + 0xc4, 0xf3, 0x51, 0x57, 0x2f, 0x75, 0x0b, 0xf8, + 0x16, 0xfa, 0x61, 0x74, 0xd2, 0x12, 0x8f, 0x78, + 0x77, 0xf9, 0x8a, 0x3e, 0x58, 0x70, 0xf3, 0xd8, + 0xe8, 0xd2, 0xb7, 0xcd, 0xbc, 0x37, 0xdf, 0x16, + 0x12, 0xf1, 0xe8, 0xb2, 0x62, 0x79, 0x91, 0x45, + 0x77, 0xe0, 0x68, 0x6d, 0xd5, 0x31, 0x54, 0x55, + 0x22, 0x63, 0xc0, 0x36, 0x31, 0x07, 0xda, 0x33, + }, + .export_len = 64, + }, + { + /* Valid export, no context - 64 bytes. */ + .tls_version = TLS1_3_VERSION, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .use_context = 0, + .shared_key = { + 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, + }, + .shared_key_len = 32, + .export = { + 0x77, 0x15, 0xe2, 0x07, 0x65, 0x64, 0x3b, 0x14, + 0x38, 0xcb, 0x73, 0x93, 0xda, 0x70, 0xfa, 0x86, + 0x2c, 0x34, 0xcc, 0x94, 0x52, 0xc2, 0xd3, 0xb4, + 0x59, 0x2c, 0xc8, 0x05, 0x70, 0xfe, 0x48, 0x61, + 0xd3, 0xea, 0x57, 0x66, 0xa9, 0x66, 0x2f, 0x4a, + 0x35, 0xc9, 0x88, 0x86, 0x28, 0x52, 0xe3, 0x64, + 0x5e, 0xf9, 0x28, 0x53, 0x8a, 0x3a, 0x92, 0x92, + 0x40, 0x8c, 0x89, 0x17, 0x59, 0xd0, 0xd0, 0x82, + }, + .export_len = 64, + }, + { + /* Valid export, zero length context - 32 bytes. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .context_value_len = 0, + .use_context = 1, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0xdb, 0xc9, 0xdf, 0x7c, 0x04, 0x39, 0xdd, 0x23, + 0xc3, 0x68, 0xdc, 0xf3, 0x04, 0xcf, 0x4c, 0x4d, + 0x86, 0x5b, 0xe6, 0x48, 0xc5, 0x6d, 0xe5, 0x1e, + 0xea, 0xc5, 0xe4, 0x00, 0x27, 0x72, 0xda, 0xb6, + }, + .export_len = 32, + }, + { + /* Valid export, zero length context - 32 bytes. */ + .tls_version = TLS1_3_VERSION, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .context_value_len = 0, + .use_context = 1, + .shared_key = { + 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, + }, + .shared_key_len = 32, + .export = { + 0x69, 0xf4, 0xac, 0xec, 0x80, 0x67, 0xac, 0x5c, + 0xa6, 0x24, 0x47, 0xb1, 0x0f, 0xc8, 0xa1, 0x13, + 0x3b, 0x91, 0x33, 0x82, 0x97, 0x0a, 0xc0, 0xbf, + 0xac, 0x6d, 0x6b, 0x34, 0x20, 0xd3, 0x3a, 0x02, + }, + .export_len = 32, + }, + { + /* Valid export, with context value - 32 bytes. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .context_value = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + }, + .context_value_len = 16, + .use_context = 1, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0x0e, 0xb4, 0xd1, 0x3a, 0x0e, 0x24, 0xab, 0x0d, + 0x4c, 0x48, 0x35, 0x25, 0xf6, 0x4d, 0xa2, 0x9b, + 0xaa, 0x1d, 0xbc, 0x54, 0x7e, 0xb0, 0x3c, 0x4b, + 0x07, 0x04, 0x9c, 0x7c, 0x06, 0xa7, 0xea, 0x70, + }, + .export_len = 32, + }, + { + /* Valid export, with context value - 32 bytes. */ + .tls_version = TLS1_3_VERSION, + .label = "EXPERIMENTAL testing", + .label_len = 20, + .context_value = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + }, + .context_value_len = 16, + .use_context = 1, + .shared_key = { + 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, + }, + .shared_key_len = 32, + .export = { + 0x34, 0xb8, 0x00, 0x6a, 0xb2, 0x62, 0xab, 0xea, + 0xc7, 0x2b, 0x15, 0xa0, 0x85, 0xda, 0xaa, 0xa5, + 0x12, 0x85, 0xbf, 0x4a, 0xa4, 0x71, 0x42, 0xc8, + 0xd4, 0xa6, 0x66, 0x18, 0xc6, 0xc9, 0x26, 0x6f, + }, + .export_len = 32, + }, + { + /* Valid export, with different label - 32 bytes. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "EXPERIMENTAL more testing", + .label_len = 20, + .context_value = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + }, + .context_value_len = 16, + .use_context = 1, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0xb0, 0xb6, 0x45, 0xdd, 0x30, 0x76, 0xf0, 0x57, + 0x22, 0x31, 0xbb, 0x8d, 0xe1, 0xf9, 0xe3, 0xed, + 0xae, 0x74, 0x6f, 0x40, 0x94, 0xf6, 0xc2, 0xfc, + 0x21, 0xff, 0xf7, 0x00, 0x86, 0x54, 0xb6, 0x06, + }, + .export_len = 32, + }, + { + /* Valid export, with different label - 32 bytes. */ + .tls_version = TLS1_3_VERSION, + .label = "EXPERIMENTAL more testing", + .label_len = 20, + .context_value = { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + }, + .context_value_len = 16, + .use_context = 1, + .shared_key = { + 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, + }, + .shared_key_len = 32, + .export = { + 0x18, 0x4e, 0x65, 0x3c, 0x91, 0x5d, 0x6a, 0xc3, + 0x25, 0x38, 0xbe, 0x6e, 0xca, 0x12, 0x54, 0x76, + 0x5a, 0x84, 0xf7, 0x19, 0x44, 0x78, 0xec, 0xc0, + 0x83, 0xf6, 0x22, 0xb8, 0x86, 0x31, 0xe9, 0x2e, + }, + .export_len = 32, + }, + { + /* Invalid - illegal label. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = TLS_MD_CLIENT_FINISH_CONST, + .label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export_len = 32, + .want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL, + }, + { + /* Invalid - illegal label. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = TLS_MD_SERVER_FINISH_CONST, + .label_len = TLS_MD_SERVER_FINISH_CONST_SIZE, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export_len = 32, + .want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL, + }, + { + /* Invalid - illegal label. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = TLS_MD_KEY_EXPANSION_CONST, + .label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export_len = 32, + .want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL, + }, + { + /* Invalid - illegal label. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = TLS_MD_MASTER_SECRET_CONST, + .label_len = TLS_MD_MASTER_SECRET_CONST_SIZE, + .use_context = 0, + .client_random = { + 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export_len = 32, + .want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL, + }, + { + /* Invalid - illegal label, split over label and seed. */ + .tls_version = TLS1_2_VERSION, + .cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + .label = "master ", + .label_len = 7, + .use_context = 0, + .client_random = { + 's', 'e', 'c', 'r', 'e', 't', 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, + }, + .server_random = { + 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, + }, + .master_key = { + 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, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + }, + .export = { + 0x40, 0x70, 0xba, 0xfa, 0xba, 0x44, 0x74, 0x93, + 0xa2, 0x43, 0x18, 0x07, 0xa4, 0x4f, 0x3f, 0xda, + 0x88, 0x7b, 0x0e, 0x79, 0x70, 0xcf, 0xdb, 0x91, + 0xfc, 0x3f, 0x96, 0x78, 0x6b, 0x50, 0xe3, 0xa6, + }, + .export_len = 32, + .want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL, + }, +}; + +#define N_EXPORTER_TESTS (sizeof(exporter_tests) / sizeof(exporter_tests[0])) + +static int +exporter_test(size_t test_no, const struct exporter_test *et) +{ + struct tls13_secret tls13_context = { .data = "", .len = 0 }; + struct tls13_ctx *tls13_ctx; + struct tls13_secrets *tls13_secrets; + SSL_SESSION *ssl_session = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + uint8_t export[256]; + int err, ret; + int failed = 1; + + memset(export, 0, sizeof(export)); + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) { + fprintf(stderr, "FAIL: SSL_CTX_new\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "FAIL: SSL_new\n"); + goto failure; + } + if ((ssl_session = SSL_SESSION_new()) == NULL) { + fprintf(stderr, "FAIL: SSL_SESSION_new\n"); + goto failure; + } + + ssl_session->ssl_version = et->tls_version; + + if (!SSL_set_session(ssl, ssl_session)) { + fprintf(stderr, "FAIL: SSL_set_session\n"); + goto failure; + } + + memcpy(ssl_session->master_key, et->master_key, + sizeof(ssl_session->master_key)); + memcpy(ssl->s3->client_random, et->client_random, + sizeof(ssl->s3->client_random)); + memcpy(ssl->s3->server_random, et->server_random, + sizeof(ssl->s3->server_random)); + + if (et->tls_version >= TLS1_3_VERSION) { + if ((tls13_ctx = tls13_ctx_new(TLS13_HS_CLIENT, ssl)) == NULL) { + fprintf(stderr, "FAIL: tls13_ctx_new\n"); + goto failure; + } + ssl->tls13 = tls13_ctx; + + if ((tls13_secrets = tls13_secrets_create(EVP_sha384(), + 0)) == NULL) { + fprintf(stderr, "FAIL: tls13_secrets_create\n"); + goto failure; + } + ssl->s3->hs.tls13.secrets = tls13_secrets; + + if (!tls13_derive_early_secrets(tls13_secrets, + tls13_secrets->zeros.data, tls13_secrets->zeros.len, + &tls13_context)) { + fprintf(stderr, "FAIL: tls13_derive_early_secrets\n"); + goto failure; + } + if (!tls13_derive_handshake_secrets(tls13_secrets, et->shared_key, + et->shared_key_len, &tls13_context)) { + fprintf(stderr, "FAIL: tls13_derive_handshake_secrets\n"); + goto failure; + } + if (!tls13_derive_application_secrets(tls13_secrets, + &tls13_context)) { + fprintf(stderr, "FAIL: tls13_derive_early_secrets\n"); + goto failure; + } + + tls13_ctx->handshake_completed = 1; + } + + ssl->s3->hs.state = SSL_ST_OK; + ssl->s3->hs.negotiated_tls_version = et->tls_version; + ssl->s3->hs.cipher = SSL_CIPHER_get_by_id(et->cipher_id); + + ret = SSL_export_keying_material(ssl, export, et->export_len, et->label, + et->label_len, et->context_value, et->context_value_len, + et->use_context); + + if (et->want_error != 0) { + if (ret) { + fprintf(stderr, "FAIL: test %zu - " + "SSL_export_keying_material() succeeded, want " + "error\n", test_no); + goto failure; + } + + err = ERR_peek_error(); + if (ERR_GET_REASON(err) != et->want_error) { + fprintf(stderr, "FAIL: %zu - got error reason %d, " + "want %d\n", test_no, ERR_GET_REASON(err), + et->want_error); + goto failure; + } + } else { + if (!ret) { + fprintf(stderr, "FAIL: test %zu - " + "SSL_export_keying_material() failed\n", test_no); + ERR_print_errors_fp(stderr); + goto failure; + } + + if (memcmp(et->export, export, et->export_len) != 0) { + fprintf(stderr, "FAIL: test %zu\n", test_no); + fprintf(stderr, "Got export:\n"); + hexdump(export, et->export_len); + fprintf(stderr, "Want export:\n"); + hexdump(et->export, et->export_len); + goto failure; + } + } + + failed = 0; + + failure: + SSL_SESSION_free(ssl_session); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_EXPORTER_TESTS; i++) + failed |= exporter_test(i, &exporter_tests[i]); + + return (failed); +} diff --git a/tests/freenull.c b/tests/freenull.c new file mode 100644 index 0000000..75c7553 --- /dev/null +++ b/tests/freenull.c @@ -0,0 +1,239 @@ +/* $OpenBSD: freenull.c.head,v 1.6 2023/07/28 17:13:56 tb Exp $ */ + +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int +main(int argc, char **argv) +{ + ACCESS_DESCRIPTION_free(NULL); + ASIdOrRange_free(NULL); + ASIdentifierChoice_free(NULL); + ASIdentifiers_free(NULL); + ASN1_BIT_STRING_free(NULL); + ASN1_BMPSTRING_free(NULL); + ASN1_ENUMERATED_free(NULL); + ASN1_GENERALIZEDTIME_free(NULL); + ASN1_GENERALSTRING_free(NULL); + ASN1_IA5STRING_free(NULL); + ASN1_INTEGER_free(NULL); + ASN1_NULL_free(NULL); + ASN1_OBJECT_free(NULL); + ASN1_OCTET_STRING_free(NULL); + ASN1_PCTX_free(NULL); + ASN1_PRINTABLESTRING_free(NULL); + ASN1_PRINTABLE_free(NULL); + ASN1_STRING_free(NULL); + ASN1_T61STRING_free(NULL); + ASN1_TIME_free(NULL); + ASN1_TYPE_free(NULL); + ASN1_UNIVERSALSTRING_free(NULL); + ASN1_UTCTIME_free(NULL); + ASN1_UTF8STRING_free(NULL); + ASN1_VISIBLESTRING_free(NULL); + ASRange_free(NULL); + AUTHORITY_INFO_ACCESS_free(NULL); + AUTHORITY_KEYID_free(NULL); + BASIC_CONSTRAINTS_free(NULL); + BIO_free(NULL); + BIO_meth_free(NULL); + BN_CTX_free(NULL); + BN_GENCB_free(NULL); + BN_MONT_CTX_free(NULL); + BN_clear_free(NULL); + BN_free(NULL); + BUF_MEM_free(NULL); + CERTIFICATEPOLICIES_free(NULL); + CMAC_CTX_free(NULL); + CMS_ContentInfo_free(NULL); + CMS_ReceiptRequest_free(NULL); + CONF_free(NULL); + CRL_DIST_POINTS_free(NULL); + CTLOG_STORE_free(NULL); + CTLOG_free(NULL); + CT_POLICY_EVAL_CTX_free(NULL); + DH_free(NULL); + DIRECTORYSTRING_free(NULL); + DISPLAYTEXT_free(NULL); + DIST_POINT_NAME_free(NULL); + DIST_POINT_free(NULL); + DSA_SIG_free(NULL); + DSA_free(NULL); + DSA_meth_free(NULL); + ECDSA_SIG_free(NULL); + EC_GROUP_clear_free(NULL); + EC_GROUP_free(NULL); + EC_KEY_METHOD_free(NULL); + EC_KEY_free(NULL); + EC_POINT_clear_free(NULL); + EC_POINT_free(NULL); + EDIPARTYNAME_free(NULL); +#ifndef OPENSSL_NO_ENGINE + ENGINE_free(NULL); +#endif + ESS_CERT_ID_free(NULL); + ESS_ISSUER_SERIAL_free(NULL); + ESS_SIGNING_CERT_free(NULL); + EVP_AEAD_CTX_free(NULL); + EVP_CIPHER_CTX_free(NULL); + EVP_CIPHER_meth_free(NULL); + EVP_ENCODE_CTX_free(NULL); + EVP_MD_CTX_free(NULL); + EVP_MD_meth_free(NULL); + EVP_PKEY_CTX_free(NULL); + EVP_PKEY_asn1_free(NULL); + EVP_PKEY_free(NULL); + EVP_PKEY_meth_free(NULL); + EXTENDED_KEY_USAGE_free(NULL); + GENERAL_NAMES_free(NULL); + GENERAL_NAME_free(NULL); + GENERAL_SUBTREE_free(NULL); + GOST_CIPHER_PARAMS_free(NULL); + GOST_KEY_free(NULL); + HMAC_CTX_free(NULL); + IPAddressChoice_free(NULL); + IPAddressFamily_free(NULL); + IPAddressOrRange_free(NULL); + IPAddressRange_free(NULL); + ISSUING_DIST_POINT_free(NULL); + NAME_CONSTRAINTS_free(NULL); + NCONF_free(NULL); + NETSCAPE_SPKAC_free(NULL); + NETSCAPE_SPKI_free(NULL); + NOTICEREF_free(NULL); + OCSP_BASICRESP_free(NULL); + OCSP_CERTID_free(NULL); + OCSP_CERTSTATUS_free(NULL); + OCSP_CRLID_free(NULL); + OCSP_ONEREQ_free(NULL); + OCSP_REQINFO_free(NULL); + OCSP_REQUEST_free(NULL); + OCSP_REQ_CTX_free(NULL); + OCSP_RESPBYTES_free(NULL); + OCSP_RESPDATA_free(NULL); + OCSP_RESPID_free(NULL); + OCSP_RESPONSE_free(NULL); + OCSP_REVOKEDINFO_free(NULL); + OCSP_SERVICELOC_free(NULL); + OCSP_SIGNATURE_free(NULL); + OCSP_SINGLERESP_free(NULL); + OTHERNAME_free(NULL); + PBE2PARAM_free(NULL); + PBEPARAM_free(NULL); + PBKDF2PARAM_free(NULL); + PKCS12_BAGS_free(NULL); + PKCS12_MAC_DATA_free(NULL); + PKCS12_SAFEBAG_free(NULL); + PKCS12_free(NULL); + PKCS7_DIGEST_free(NULL); + PKCS7_ENCRYPT_free(NULL); + PKCS7_ENC_CONTENT_free(NULL); + PKCS7_ENVELOPE_free(NULL); + PKCS7_ISSUER_AND_SERIAL_free(NULL); + PKCS7_RECIP_INFO_free(NULL); + PKCS7_SIGNED_free(NULL); + PKCS7_SIGNER_INFO_free(NULL); + PKCS7_SIGN_ENVELOPE_free(NULL); + PKCS7_free(NULL); + PKCS8_PRIV_KEY_INFO_free(NULL); + PKEY_USAGE_PERIOD_free(NULL); + POLICYINFO_free(NULL); + POLICYQUALINFO_free(NULL); + POLICY_CONSTRAINTS_free(NULL); + POLICY_MAPPING_free(NULL); + RSA_OAEP_PARAMS_free(NULL); + RSA_PSS_PARAMS_free(NULL); + RSA_free(NULL); + RSA_meth_free(NULL); + SCT_LIST_free(NULL); + SCT_free(NULL); + TS_ACCURACY_free(NULL); + TS_MSG_IMPRINT_free(NULL); + TS_REQ_ext_free(NULL); + TS_REQ_free(NULL); + TS_RESP_CTX_free(NULL); + TS_RESP_free(NULL); + TS_STATUS_INFO_free(NULL); + TS_TST_INFO_ext_free(NULL); + TS_TST_INFO_free(NULL); + TS_VERIFY_CTX_free(NULL); + TXT_DB_free(NULL); + UI_free(NULL); + USERNOTICE_free(NULL); + X509V3_conf_free(NULL); + X509_ALGOR_free(NULL); + X509_ATTRIBUTE_free(NULL); + X509_CERT_AUX_free(NULL); + X509_CINF_free(NULL); + X509_CRL_INFO_free(NULL); + X509_CRL_METHOD_free(NULL); + X509_CRL_free(NULL); + X509_EXTENSION_free(NULL); + X509_INFO_free(NULL); + X509_LOOKUP_free(NULL); + X509_NAME_ENTRY_free(NULL); + X509_NAME_free(NULL); + X509_OBJECT_free(NULL); + X509_PKEY_free(NULL); + X509_PUBKEY_free(NULL); + X509_REQ_INFO_free(NULL); + X509_REQ_free(NULL); + X509_REVOKED_free(NULL); + X509_SIG_free(NULL); + X509_STORE_CTX_free(NULL); + X509_STORE_free(NULL); + X509_VAL_free(NULL); + X509_VERIFY_PARAM_free(NULL); + X509_email_free(NULL); + X509_free(NULL); + lh_free(NULL); + sk_free(NULL); +/* $OpenBSD: freenull.c.tail,v 1.2 2018/07/10 20:55:57 tb Exp $ */ + + BIO_free_all(NULL); + NCONF_free_data(NULL); + _CONF_free_data(NULL); + + lh_FUNCTION_free(NULL); + + sk_ASN1_OBJECT_pop_free(NULL, NULL); + sk_CONF_VALUE_pop_free(NULL, NULL); + sk_GENERAL_NAME_pop_free(NULL, NULL); + sk_OCSP_CERTID_free(NULL); + sk_OPENSSL_STRING_free(NULL); + sk_PKCS12_SAFEBAG_pop_free(NULL, NULL); + sk_PKCS7_pop_free(NULL, NULL); + sk_X509_ATTRIBUTE_free(NULL); + sk_X509_CRL_pop_free(NULL, NULL); + sk_X509_EXTENSION_pop_free(NULL, NULL); + sk_X509_INFO_free(NULL); + sk_X509_INFO_pop_free(NULL, NULL); + sk_X509_NAME_ENTRY_pop_free(NULL, NULL); + sk_X509_free(NULL); + sk_X509_pop_free(NULL, NULL); + + printf("PASS\n"); + + return 0; +} diff --git a/tests/freenull.c.body b/tests/freenull.c.body new file mode 100644 index 0000000..cffd63d --- /dev/null +++ b/tests/freenull.c.body @@ -0,0 +1,182 @@ + ACCESS_DESCRIPTION_free(NULL); + ASIdOrRange_free(NULL); + ASIdentifierChoice_free(NULL); + ASIdentifiers_free(NULL); + ASN1_BIT_STRING_free(NULL); + ASN1_BMPSTRING_free(NULL); + ASN1_ENUMERATED_free(NULL); + ASN1_GENERALIZEDTIME_free(NULL); + ASN1_GENERALSTRING_free(NULL); + ASN1_IA5STRING_free(NULL); + ASN1_INTEGER_free(NULL); + ASN1_NULL_free(NULL); + ASN1_OBJECT_free(NULL); + ASN1_OCTET_STRING_free(NULL); + ASN1_PCTX_free(NULL); + ASN1_PRINTABLESTRING_free(NULL); + ASN1_PRINTABLE_free(NULL); + ASN1_STRING_free(NULL); + ASN1_T61STRING_free(NULL); + ASN1_TIME_free(NULL); + ASN1_TYPE_free(NULL); + ASN1_UNIVERSALSTRING_free(NULL); + ASN1_UTCTIME_free(NULL); + ASN1_UTF8STRING_free(NULL); + ASN1_VISIBLESTRING_free(NULL); + ASRange_free(NULL); + AUTHORITY_INFO_ACCESS_free(NULL); + AUTHORITY_KEYID_free(NULL); + BASIC_CONSTRAINTS_free(NULL); + BIO_free(NULL); + BIO_meth_free(NULL); + BN_CTX_free(NULL); + BN_GENCB_free(NULL); + BN_MONT_CTX_free(NULL); + BN_clear_free(NULL); + BN_free(NULL); + BUF_MEM_free(NULL); + CERTIFICATEPOLICIES_free(NULL); + CMAC_CTX_free(NULL); + CMS_ContentInfo_free(NULL); + CMS_ReceiptRequest_free(NULL); + CONF_free(NULL); + CRL_DIST_POINTS_free(NULL); + CTLOG_STORE_free(NULL); + CTLOG_free(NULL); + CT_POLICY_EVAL_CTX_free(NULL); + DH_free(NULL); + DIRECTORYSTRING_free(NULL); + DISPLAYTEXT_free(NULL); + DIST_POINT_NAME_free(NULL); + DIST_POINT_free(NULL); + DSA_SIG_free(NULL); + DSA_free(NULL); + DSA_meth_free(NULL); + ECDSA_SIG_free(NULL); + EC_GROUP_clear_free(NULL); + EC_GROUP_free(NULL); + EC_KEY_METHOD_free(NULL); + EC_KEY_free(NULL); + EC_POINT_clear_free(NULL); + EC_POINT_free(NULL); + EDIPARTYNAME_free(NULL); +#ifndef OPENSSL_NO_ENGINE + ENGINE_free(NULL); +#endif + ESS_CERT_ID_free(NULL); + ESS_ISSUER_SERIAL_free(NULL); + ESS_SIGNING_CERT_free(NULL); + EVP_AEAD_CTX_free(NULL); + EVP_CIPHER_CTX_free(NULL); + EVP_CIPHER_meth_free(NULL); + EVP_ENCODE_CTX_free(NULL); + EVP_MD_CTX_free(NULL); + EVP_MD_meth_free(NULL); + EVP_PKEY_CTX_free(NULL); + EVP_PKEY_asn1_free(NULL); + EVP_PKEY_free(NULL); + EVP_PKEY_meth_free(NULL); + EXTENDED_KEY_USAGE_free(NULL); + GENERAL_NAMES_free(NULL); + GENERAL_NAME_free(NULL); + GENERAL_SUBTREE_free(NULL); + GOST_CIPHER_PARAMS_free(NULL); + GOST_KEY_free(NULL); + HMAC_CTX_free(NULL); + IPAddressChoice_free(NULL); + IPAddressFamily_free(NULL); + IPAddressOrRange_free(NULL); + IPAddressRange_free(NULL); + ISSUING_DIST_POINT_free(NULL); + NAME_CONSTRAINTS_free(NULL); + NCONF_free(NULL); + NETSCAPE_SPKAC_free(NULL); + NETSCAPE_SPKI_free(NULL); + NOTICEREF_free(NULL); + OCSP_BASICRESP_free(NULL); + OCSP_CERTID_free(NULL); + OCSP_CERTSTATUS_free(NULL); + OCSP_CRLID_free(NULL); + OCSP_ONEREQ_free(NULL); + OCSP_REQINFO_free(NULL); + OCSP_REQUEST_free(NULL); + OCSP_REQ_CTX_free(NULL); + OCSP_RESPBYTES_free(NULL); + OCSP_RESPDATA_free(NULL); + OCSP_RESPID_free(NULL); + OCSP_RESPONSE_free(NULL); + OCSP_REVOKEDINFO_free(NULL); + OCSP_SERVICELOC_free(NULL); + OCSP_SIGNATURE_free(NULL); + OCSP_SINGLERESP_free(NULL); + OTHERNAME_free(NULL); + PBE2PARAM_free(NULL); + PBEPARAM_free(NULL); + PBKDF2PARAM_free(NULL); + PKCS12_BAGS_free(NULL); + PKCS12_MAC_DATA_free(NULL); + PKCS12_SAFEBAG_free(NULL); + PKCS12_free(NULL); + PKCS7_DIGEST_free(NULL); + PKCS7_ENCRYPT_free(NULL); + PKCS7_ENC_CONTENT_free(NULL); + PKCS7_ENVELOPE_free(NULL); + PKCS7_ISSUER_AND_SERIAL_free(NULL); + PKCS7_RECIP_INFO_free(NULL); + PKCS7_SIGNED_free(NULL); + PKCS7_SIGNER_INFO_free(NULL); + PKCS7_SIGN_ENVELOPE_free(NULL); + PKCS7_free(NULL); + PKCS8_PRIV_KEY_INFO_free(NULL); + PKEY_USAGE_PERIOD_free(NULL); + POLICYINFO_free(NULL); + POLICYQUALINFO_free(NULL); + POLICY_CONSTRAINTS_free(NULL); + POLICY_MAPPING_free(NULL); + RSA_OAEP_PARAMS_free(NULL); + RSA_PSS_PARAMS_free(NULL); + RSA_free(NULL); + RSA_meth_free(NULL); + SCT_LIST_free(NULL); + SCT_free(NULL); + TS_ACCURACY_free(NULL); + TS_MSG_IMPRINT_free(NULL); + TS_REQ_ext_free(NULL); + TS_REQ_free(NULL); + TS_RESP_CTX_free(NULL); + TS_RESP_free(NULL); + TS_STATUS_INFO_free(NULL); + TS_TST_INFO_ext_free(NULL); + TS_TST_INFO_free(NULL); + TS_VERIFY_CTX_free(NULL); + TXT_DB_free(NULL); + UI_free(NULL); + USERNOTICE_free(NULL); + X509V3_conf_free(NULL); + X509_ALGOR_free(NULL); + X509_ATTRIBUTE_free(NULL); + X509_CERT_AUX_free(NULL); + X509_CINF_free(NULL); + X509_CRL_INFO_free(NULL); + X509_CRL_METHOD_free(NULL); + X509_CRL_free(NULL); + X509_EXTENSION_free(NULL); + X509_INFO_free(NULL); + X509_LOOKUP_free(NULL); + X509_NAME_ENTRY_free(NULL); + X509_NAME_free(NULL); + X509_OBJECT_free(NULL); + X509_PKEY_free(NULL); + X509_PUBKEY_free(NULL); + X509_REQ_INFO_free(NULL); + X509_REQ_free(NULL); + X509_REVOKED_free(NULL); + X509_SIG_free(NULL); + X509_STORE_CTX_free(NULL); + X509_STORE_free(NULL); + X509_VAL_free(NULL); + X509_VERIFY_PARAM_free(NULL); + X509_email_free(NULL); + X509_free(NULL); + lh_free(NULL); + sk_free(NULL); diff --git a/tests/gcm128test.c b/tests/gcm128test.c new file mode 100644 index 0000000..def7653 --- /dev/null +++ b/tests/gcm128test.c @@ -0,0 +1,926 @@ +/* $OpenBSD: gcm128test.c,v 1.7 2022/09/05 21:06:31 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 2010 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include +#include +#include +#include + +#include +#include + +/* XXX - something like this should be in the public headers. */ +struct gcm128_context { + uint64_t opaque[64]; +}; + +struct gcm128_test { + const uint8_t K[128]; + size_t K_len; + const uint8_t IV[128]; + size_t IV_len; + const uint8_t P[512]; + size_t P_len; + const uint8_t A[128]; + size_t A_len; + const uint8_t C[512]; + size_t C_len; + const uint8_t T[16]; +}; + +struct gcm128_test gcm128_tests[] = { + { + /* Test Case 1. */ + .K = {0}, + .K_len = 16, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 0, + .A = {0}, + .A_len = 0, + .C = {0}, + .C_len = 0, + .T = { + 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a, + }, + }, + { + /* Test Case 2. */ + .K = {0}, + .K_len = 16, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 16, + .A = {0}, + .A_len = 0, + .C = { + 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78, + }, + .C_len = 16, + .T = { + 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf, + }, + }, + { + /* Test Case 3. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 16, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, + }, + .P_len = 64, + .A = {0}, + .A_len = 0, + .C = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, + }, + .C_len = 64, + .T = { + 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, + } + }, + { + /* Test Case 4. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 16, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, + }, + .C_len = 60, + .T = { + 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, + }, + }, + { + /* Test Case 5. */ + /* K, P, A are the same as TC4. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 16, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + }, + .IV_len = 8, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98, + }, + .C_len = 60, + .T = { + 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, + }, + }, + { + /* Test Case 6. */ + /* K, P, A are the same as TC4. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 16, + .IV = { + 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b, + }, + .IV_len = 60, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5, + }, + .C_len = 60, + .T = { + 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, + }, + }, + { + /* Test Case 7. */ + .K = {0}, + .K_len = 24, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 0, + .A = {0}, + .A_len = 0, + .C = {0}, + .C_len = 0, + .T = { + 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35, + }, + }, + { + /* Test Case 8. */ + .K = {0}, + .K_len = 24, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 16, + .A = {0}, + .A_len = 0, + .C = { + 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00, + }, + .C_len = 16, + .T = { + 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb, + }, + }, + { + /* Test Case 9. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + }, + .K_len = 24, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, + }, + .P_len = 64, + .A = {0}, + .A_len = 0, + .C = { + 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56, + }, + .C_len = 64, + .T = { + 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14, + }, + }, + { + /* Test Case 10. */ + /* K and IV are the same as TC9. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + }, + .K_len = 24, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, + }, + .C_len = 60, + .T = { + 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c, + }, + }, + { + /* Test Case 11. */ + /* K is the same as TC9, P and A are the same as TC10. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + }, + .K_len = 24, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + }, + .IV_len = 8, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 + }, + .C_len = 60, + .T = { + 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8, + }, + }, + { + /* Test Case 12. */ + /* K is the same as TC9, P and A are the same as TC10. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + }, + .K_len = 24, + .IV = { + 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b, + }, + .IV_len = 60, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b, + }, + .C_len = 60, + .T = { + 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9, + }, + }, + { + /* Test Case 13. */ + .K = {0}, + .K_len = 32, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 0, + .A = {0}, + .A_len = 0, + .C = {0}, + .C_len = 0, + .T = { + 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b, + }, + }, + { + /* Test Case 14. */ + .K = {0}, + .K_len = 32, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 16, + .A = {0}, + .A_len = 0, + .C = { + 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18, + }, + .C_len = 16, + .T = { + 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19, + }, + }, + { + /* Test Case 15. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 32, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, + }, + .P_len = 64, + .A = {0}, + .A_len = 0, + .C = { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad, + }, + .C_len = 64, + .T = { + 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c, + }, + }, + { + /* Test Case 16. */ + /* K and IV are the same as TC15. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 32, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, + }, + .IV_len = 12, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, + }, + .C_len = 60, + .T = { + 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b, + }, + }, + { + /* Test Case 17. */ + /* K is the same as TC15, P and A are the same as TC 16. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 32, + .IV = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + }, + .IV_len = 8, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f, + }, + .C_len = 60, + .T = { + 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2, + }, + }, + { + /* Test Case 18. */ + /* K is the same as TC15, P and A are the same as TC 16. */ + .K = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + }, + .K_len = 32, + .IV = { + 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b, + }, + .IV_len = 60, + .P = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, + }, + .P_len = 60, + .A = { + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, + }, + .A_len = 20, + .C = { + 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f, + }, + .C_len = 60, + .T = { + 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a, + }, + }, + { + /* Test Case 19. */ + .K = {0}, + .K_len = 16, + .IV = {0}, + .IV_len = 12, + .P = {0}, + .P_len = 0, + .A = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad, + }, + .A_len = 128, + .C = {0}, + .C_len = 0, + .T = { + 0x5f, 0xea, 0x79, 0x3a, 0x2d, 0x6f, 0x97, 0x4d, + 0x37, 0xe6, 0x8e, 0x0c, 0xb8, 0xff, 0x94, 0x92, + }, + }, + { + /* Test Case 20. */ + .K = {0}, + .K_len = 16, + .IV = { + /* This results in 0xff in counter LSB. */ + 0xff, 0xff, 0xff, 0xff, 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, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .IV_len = 64, + .P = {0}, + .P_len = 288, + .A = {0}, + .A_len = 0, + .C = { + 0x56, 0xb3, 0x37, 0x3c, 0xa9, 0xef, 0x6e, 0x4a, + 0x2b, 0x64, 0xfe, 0x1e, 0x9a, 0x17, 0xb6, 0x14, + 0x25, 0xf1, 0x0d, 0x47, 0xa7, 0x5a, 0x5f, 0xce, + 0x13, 0xef, 0xc6, 0xbc, 0x78, 0x4a, 0xf2, 0x4f, + 0x41, 0x41, 0xbd, 0xd4, 0x8c, 0xf7, 0xc7, 0x70, + 0x88, 0x7a, 0xfd, 0x57, 0x3c, 0xca, 0x54, 0x18, + 0xa9, 0xae, 0xff, 0xcd, 0x7c, 0x5c, 0xed, 0xdf, + 0xc6, 0xa7, 0x83, 0x97, 0xb9, 0xa8, 0x5b, 0x49, + 0x9d, 0xa5, 0x58, 0x25, 0x72, 0x67, 0xca, 0xab, + 0x2a, 0xd0, 0xb2, 0x3c, 0xa4, 0x76, 0xa5, 0x3c, + 0xb1, 0x7f, 0xb4, 0x1c, 0x4b, 0x8b, 0x47, 0x5c, + 0xb4, 0xf3, 0xf7, 0x16, 0x50, 0x94, 0xc2, 0x29, + 0xc9, 0xe8, 0xc4, 0xdc, 0x0a, 0x2a, 0x5f, 0xf1, + 0x90, 0x3e, 0x50, 0x15, 0x11, 0x22, 0x13, 0x76, + 0xa1, 0xcd, 0xb8, 0x36, 0x4c, 0x50, 0x61, 0xa2, + 0x0c, 0xae, 0x74, 0xbc, 0x4a, 0xcd, 0x76, 0xce, + 0xb0, 0xab, 0xc9, 0xfd, 0x32, 0x17, 0xef, 0x9f, + 0x8c, 0x90, 0xbe, 0x40, 0x2d, 0xdf, 0x6d, 0x86, + 0x97, 0xf4, 0xf8, 0x80, 0xdf, 0xf1, 0x5b, 0xfb, + 0x7a, 0x6b, 0x28, 0x24, 0x1e, 0xc8, 0xfe, 0x18, + 0x3c, 0x2d, 0x59, 0xe3, 0xf9, 0xdf, 0xff, 0x65, + 0x3c, 0x71, 0x26, 0xf0, 0xac, 0xb9, 0xe6, 0x42, + 0x11, 0xf4, 0x2b, 0xae, 0x12, 0xaf, 0x46, 0x2b, + 0x10, 0x70, 0xbe, 0xf1, 0xab, 0x5e, 0x36, 0x06, + 0x87, 0x2c, 0xa1, 0x0d, 0xee, 0x15, 0xb3, 0x24, + 0x9b, 0x1a, 0x1b, 0x95, 0x8f, 0x23, 0x13, 0x4c, + 0x4b, 0xcc, 0xb7, 0xd0, 0x32, 0x00, 0xbc, 0xe4, + 0x20, 0xa2, 0xf8, 0xeb, 0x66, 0xdc, 0xf3, 0x64, + 0x4d, 0x14, 0x23, 0xc1, 0xb5, 0x69, 0x90, 0x03, + 0xc1, 0x3e, 0xce, 0xf4, 0xbf, 0x38, 0xa3, 0xb6, + 0x0e, 0xed, 0xc3, 0x40, 0x33, 0xba, 0xc1, 0x90, + 0x27, 0x83, 0xdc, 0x6d, 0x89, 0xe2, 0xe7, 0x74, + 0x18, 0x8a, 0x43, 0x9c, 0x7e, 0xbc, 0xc0, 0x67, + 0x2d, 0xbd, 0xa4, 0xdd, 0xcf, 0xb2, 0x79, 0x46, + 0x13, 0xb0, 0xbe, 0x41, 0x31, 0x5e, 0xf7, 0x78, + 0x70, 0x8a, 0x70, 0xee, 0x7d, 0x75, 0x16, 0x5c, + }, + .C_len = 288, + .T = { + 0x8b, 0x30, 0x7f, 0x6b, 0x33, 0x28, 0x6d, 0x0a, + 0xb0, 0x26, 0xa9, 0xed, 0x3f, 0xe1, 0xe8, 0x5f, + }, + }, +}; + +#define N_TESTS (sizeof(gcm128_tests) / sizeof(*gcm128_tests)) + +static int +do_gcm128_test(int test_no, struct gcm128_test *tv) +{ + GCM128_CONTEXT ctx; + AES_KEY key; + uint8_t *out = NULL; + size_t out_len; + int ret = 1; + + out_len = tv->P_len; + if (out_len != 0) { + out = malloc(out_len); + if (out == NULL) + err(1, "malloc"); + } + + AES_set_encrypt_key(tv->K, tv->K_len * 8, &key); + + if (out_len != 0) + memset(out, 0, out_len); + CRYPTO_gcm128_init(&ctx, &key, (block128_f)AES_encrypt); + CRYPTO_gcm128_setiv(&ctx, tv->IV, tv->IV_len); + if (tv->A_len > 0) + CRYPTO_gcm128_aad(&ctx, tv->A, tv->A_len); + if (tv->P_len > 0) + CRYPTO_gcm128_encrypt(&ctx, tv->P, out, out_len); + if (CRYPTO_gcm128_finish(&ctx, tv->T, 16)) { + fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n", + test_no); + goto fail; + } + if (tv->C_len > 0 && memcmp(out, tv->C, out_len)) { + fprintf(stderr, "TEST %d: encrypt failed\n", test_no); + goto fail; + } + + if (out_len != 0) + memset(out, 0, out_len); + CRYPTO_gcm128_setiv(&ctx, tv->IV, tv->IV_len); + if (tv->A_len > 0) + CRYPTO_gcm128_aad(&ctx, tv->A, tv->A_len); + if (tv->C_len > 0) + CRYPTO_gcm128_decrypt(&ctx, tv->C, out, out_len); + if (CRYPTO_gcm128_finish(&ctx, tv->T, 16)) { + fprintf(stderr, "TEST %d: CRYPTO_gcm128_finish failed\n", + test_no); + goto fail; + } + if (tv->P_len > 0 && memcmp(out, tv->P, out_len)) { + fprintf(stderr, "TEST %d: decrypt failed\n", test_no); + goto fail; + } + + ret = 0; + +fail: + free(out); + return (ret); +} + +int +main(int argc, char **argv) +{ + int ret = 0; + size_t i; + + for (i = 0; i < N_TESTS; i++) + ret |= do_gcm128_test(i + 1, &gcm128_tests[i]); + + return ret; +} diff --git a/tests/gost2814789t.c b/tests/gost2814789t.c new file mode 100644 index 0000000..5e439a7 --- /dev/null +++ b/tests/gost2814789t.c @@ -0,0 +1,1491 @@ +/* $OpenBSD: gost2814789t.c,v 1.9 2023/06/19 18:51:47 tb Exp $ */ +/* vim: set fileencoding=ascii : Charset: ASCII */ +/* test/gostr2814789t.c */ +/* ==================================================================== + * Copyright (c) 2012 Crypto-Pro, Ltd., Serguei E. Leontiev, + * lse@cryptopro.ru + * + * This file is distributed under the same license as OpenSSL + * ==================================================================== + */ +#include + +#if defined(OPENSSL_NO_GOST) +int main(int argc, char *argv[]) +{ + printf("No GOST 28147-89 support\n"); + return 0; +} +#else + +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include +#include +#include + +#define G89_MAX_TC_LEN (2048) +#define G89_BLOCK_LEN (8) + +#undef U64 +#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) +#define U64(C) C##UI64 +#elif defined(_LP64) || defined(__arch64__) +#define U64(C) C##UL +#else +#define U64(C) C##ULL +#endif + +typedef enum g89_mode_ { + G89_ECB, + G89_CFB, + G89_CNT, + G89_IMIT +} g89_mode; + +typedef struct g89_tc_ { + uint64_t ullLen; /* ullLen > G89_MAX_TC_LEN */ + /* Clear text ullLen */ + /* of zero unsigned chars */ + const unsigned char bIn[G89_MAX_TC_LEN]; /* Clear text, when */ + /* ullLen <= G89_MAX_TC_LEN */ + const char *szParamSet; /* S-Box ID */ + const char *szDerive; /* String for derive bRawKey */ + const unsigned char bRawKey[EVP_MAX_KEY_LENGTH]; + g89_mode gMode; /* Mode of encryption or MAC */ + const unsigned char bIV[EVP_MAX_IV_LENGTH]; /* IV for CFB or CNT mode */ + const unsigned char bOut[G89_MAX_TC_LEN]; /* Cipher text for ECB/CFB/CNT */ + /* mode, when ullLen <= G89_MAX_TC_LEN; + * Last 16 unsigned char of cipher text for + * ECB/CFB/CNT, when ullLen > + * G89_MAX_TC_LEN; + * 4 unsigned char MAC for imitovstavka */ +} g89_tc; + +const g89_tc tcs[] = { + /* + * GOST R 34.11-94 Test cases + */ + { /* see p. A.3.1 [GOSTR341194], p. 7.3.1 [ENG-GOSTR341194] */ + /* */ + /* Iteration 1, K[1], see Errata for RFC 5831 */ + 8, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + "id-GostR3411-94-TestParamSet", + NULL, + { + 0x54, 0x6d, 0x20, 0x33, 0x68, 0x65, 0x6c, 0x32, + 0x69, 0x73, 0x65, 0x20, 0x73, 0x73, 0x6e, 0x62, + 0x20, 0x61, 0x67, 0x79, 0x69, 0x67, 0x74, 0x74, + 0x73, 0x65, 0x68, 0x65, 0x20, 0x2c, 0x3d, 0x73 + }, + G89_ECB, + { 0 }, + { + 0x1b, 0x0b, 0xbc, 0x32, 0xce, 0xbc, 0xab, 0x42 + } + }, + { /* see p. A.3.1 [GOSTR341194], p. 7.3.1 [ENG-GOSTR341194] */ + /* */ + /* Iteration 1, K[4] */ + 8, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + "id-GostR3411-94-TestParamSet", + NULL, + { + 0xec, 0x0a, 0x8b, 0xa1, 0x5e, 0xc0, 0x04, 0xa8, + 0xba, 0xc5, 0x0c, 0xac, 0x0c, 0x62, 0x1d, 0xee, + 0xe1, 0xc7, 0xb8, 0xe7, 0x00, 0x7a, 0xe2, 0xec, + 0xf2, 0x73, 0x1b, 0xff, 0x4e, 0x80, 0xe2, 0xa0 + }, + G89_ECB, + { 0 }, + { + 0x2d, 0x56, 0x2a, 0x0d, 0x19, 0x04, 0x86, 0xe7 + } + }, + { /* see p. A.3.1 [GOSTR341194], p. 7.3.1 [ENG-GOSTR341194] */ + /* */ + /* Iteration 2, K[1] */ + 8, + { + 0x34, 0xc0, 0x15, 0x33, 0xe3, 0x7d, 0x1c, 0x56 + }, + "id-GostR3411-94-TestParamSet", + NULL, + { + 0x34, 0x87, 0x24, 0xa4, 0xc1, 0xa6, 0x76, 0x67, + 0x15, 0x3d, 0xde, 0x59, 0x33, 0x88, 0x42, 0x50, + 0xe3, 0x24, 0x8c, 0x65, 0x7d, 0x41, 0x3b, 0x8c, + 0x1c, 0x9c, 0xa0, 0x9a, 0x56, 0xd9, 0x68, 0xcf + }, + G89_ECB, + { 0 }, + { + 0x86, 0x3e, 0x78, 0xdd, 0x2d, 0x60, 0xd1, 0x3c + } + }, + /* + * id-Gost28147-89-CryptoPro-A-ParamSet (1.2.643.2.2.31.1) + * Test cases + */ + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 16, + { + 0x74, 0x3d, 0x76, 0xf9, 0x1b, 0xee, 0x35, 0x3c, + 0xa2, 0x5c, 0x3b, 0x10, 0xeb, 0x64, 0xcf, 0xf5 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testecb1", + { + 0xbb, 0xf1, 0xed, 0xd3, 0x20, 0xaf, 0x8a, 0x62, + 0x8e, 0x11, 0xc8, 0xa9, 0x51, 0xcc, 0xbe, 0x81, + 0x47, 0x7b, 0x41, 0xa1, 0x6a, 0xf6, 0x7f, 0x05, + 0xe8, 0x51, 0x2f, 0x9e, 0x01, 0xf8, 0xcf, 0x49 + }, + G89_ECB, + { 0 }, + { + 0xc3, 0x73, 0x90, 0x95, 0x35, 0x58, 0x08, 0x63, + 0xcb, 0x68, 0x85, 0x96, 0x77, 0xe8, 0xfb, 0xa9 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 16, + { + 0xd2, 0xfd, 0xf8, 0x3a, 0xc1, 0xb4, 0x39, 0x23, + 0x2e, 0xaa, 0xcc, 0x98, 0x0a, 0x02, 0xda, 0x33 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testcfb1", + { + 0x8d, 0x5a, 0x2c, 0x83, 0xa7, 0xc7, 0x0a, 0x61, + 0xd6, 0x1b, 0x34, 0xb5, 0x1f, 0xdf, 0x42, 0x68, + 0x66, 0x71, 0xa3, 0x5d, 0x87, 0x4c, 0xfd, 0x84, + 0x99, 0x36, 0x63, 0xb6, 0x1e, 0xd6, 0x0d, 0xad + }, + G89_CFB, + { + 0x46, 0x60, 0x6f, 0x0d, 0x88, 0x34, 0x23, 0x5a + }, + { + 0x88, 0xb7, 0x75, 0x16, 0x74, 0xa5, 0xee, 0x2d, + 0x14, 0xfe, 0x91, 0x67, 0xd0, 0x5c, 0xcc, 0x40 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 16, + { + 0x90, 0xa2, 0x39, 0x66, 0xae, 0x01, 0xb9, 0xa3, + 0x52, 0x4e, 0xc8, 0xed, 0x6c, 0xdd, 0x88, 0x30 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testcnt1", + { + 0x59, 0x9f, 0x84, 0xba, 0xc3, 0xf3, 0xd2, 0xf1, + 0x60, 0xe1, 0xe3, 0xf2, 0x6a, 0x96, 0x1a, 0xf9, + 0x9c, 0x48, 0xb2, 0x4e, 0xbc, 0xbb, 0xbf, 0x7c, + 0xd8, 0xf3, 0xac, 0xcd, 0x96, 0x8d, 0x28, 0x6a + }, + G89_CNT, + { + 0x8d, 0xaf, 0xa8, 0xd1, 0x58, 0xed, 0x05, 0x8d + }, + { + 0x6e, 0x72, 0x62, 0xcc, 0xe3, 0x59, 0x36, 0x90, + 0x83, 0x3a, 0xfe, 0xa9, 0x1b, 0xc9, 0xbe, 0xce + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 16, + { + 0xb5, 0xa1, 0xf0, 0xe3, 0xce, 0x2f, 0x02, 0x1d, + 0x67, 0x61, 0x94, 0x34, 0x5c, 0x41, 0xe3, 0x6e + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit1", + { + 0x9d, 0x05, 0xb7, 0x9e, 0x90, 0xca, 0xd0, 0x0a, + 0x2c, 0xda, 0xd2, 0x2e, 0xf4, 0xe8, 0x6f, 0x5c, + 0xf5, 0xdc, 0x37, 0x68, 0x19, 0x85, 0xb3, 0xbf, + 0xaa, 0x18, 0xc1, 0xc3, 0x05, 0x0a, 0x91, 0xa2 + }, + G89_IMIT, + { 0 }, + { + 0xf8, 0x1f, 0x08, 0xa3 + } + }, + /* + * Other paramsets and key meshing test cases. + */ + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 1039, + { + 0x8c, 0x9c, 0x44, 0x35, 0xfb, 0xe9, 0xa5, 0xa3, + 0xa0, 0xae, 0x28, 0x56, 0x91, 0x10, 0x8e, 0x1e , + 0xd2, 0xbb, 0x18, 0x53, 0x81, 0x27, 0x0d, 0xa6, + 0x68, 0x59, 0x36, 0xc5, 0x81, 0x62, 0x9a, 0x8e, + 0x7d, 0x50, 0xf1, 0x6f, 0x97, 0x62, 0x29, 0xec, + 0x80, 0x51, 0xe3, 0x7d, 0x6c, 0xc4, 0x07, 0x95, + 0x28, 0x63, 0xdc, 0xb4, 0xb9, 0x2d, 0xb8, 0x13, + 0xb1, 0x05, 0xb5, 0xf9, 0xeb, 0x75, 0x37, 0x4e, + 0xf7, 0xbf, 0x51, 0xf1, 0x98, 0x86, 0x43, 0xc4, + 0xe4, 0x3d, 0x3e, 0xa7, 0x62, 0xec, 0x41, 0x59, + 0xe0, 0xbd, 0xfb, 0xb6, 0xfd, 0xec, 0xe0, 0x77, + 0x13, 0xd2, 0x59, 0x90, 0xa1, 0xb8, 0x97, 0x6b, + 0x3d, 0x8b, 0x7d, 0xfc, 0x9d, 0xca, 0x82, 0x73, + 0x32, 0x70, 0x0a, 0x74, 0x03, 0xc6, 0x0c, 0x26, + 0x7f, 0x56, 0xf0, 0x9d, 0xb2, 0xeb, 0x71, 0x40, + 0xd7, 0xc3, 0xb1, 0xa7, 0xc5, 0x1e, 0x20, 0x17, + 0xb3, 0x50, 0x1d, 0x8a, 0x6e, 0x19, 0xcb, 0xbe, + 0x20, 0x86, 0x2b, 0xd6, 0x1c, 0xfd, 0xb4, 0xb7, + 0x5d, 0x9a, 0xb3, 0xe3, 0x7d, 0x15, 0x7a, 0x35, + 0x01, 0x9f, 0x5d, 0x65, 0x89, 0x4b, 0x34, 0xc6, + 0xf4, 0x81, 0x3f, 0x78, 0x30, 0xcf, 0xe9, 0x15, + 0x90, 0x9a, 0xf9, 0xde, 0xba, 0x63, 0xd0, 0x19, + 0x14, 0x66, 0x3c, 0xb9, 0xa4, 0xb2, 0x84, 0x94, + 0x02, 0xcf, 0xce, 0x20, 0xcf, 0x76, 0xe7, 0xc5, + 0x48, 0xf7, 0x69, 0x3a, 0x5d, 0xec, 0xaf, 0x41, + 0xa7, 0x12, 0x64, 0x83, 0xf5, 0x99, 0x1e, 0x9e, + 0xb2, 0xab, 0x86, 0x16, 0x00, 0x23, 0x8e, 0xe6, + 0xd9, 0x80, 0x0b, 0x6d, 0xc5, 0x93, 0xe2, 0x5c, + 0x8c, 0xd8, 0x5e, 0x5a, 0xae, 0x4a, 0x85, 0xfd, + 0x76, 0x01, 0xea, 0x30, 0xf3, 0x78, 0x34, 0x10, + 0x72, 0x51, 0xbc, 0x9f, 0x76, 0xce, 0x1f, 0xd4, + 0x8f, 0x33, 0x50, 0x34, 0xc7, 0x4d, 0x7b, 0xcf, + 0x91, 0x63, 0x7d, 0x82, 0x9e, 0xa1, 0x23, 0x45, + 0xf5, 0x45, 0xac, 0x98, 0x7a, 0x48, 0xff, 0x64, + 0xd5, 0x59, 0x47, 0xde, 0x2b, 0x3f, 0xfa, 0xec, + 0x50, 0xe0, 0x81, 0x60, 0x8b, 0xc3, 0xfc, 0x80, + 0x98, 0x17, 0xc7, 0xa3, 0xc2, 0x57, 0x3d, 0xab, + 0x91, 0x67, 0xf5, 0xc4, 0xab, 0x92, 0xc8, 0xd6, + 0x3b, 0x6b, 0x3f, 0xff, 0x15, 0x6b, 0xcf, 0x53, + 0x65, 0x02, 0xf1, 0x74, 0xca, 0xa9, 0xbe, 0x24, + 0xd2, 0xf0, 0xb7, 0x26, 0xa8, 0xd7, 0x6d, 0xed, + 0x90, 0x36, 0x7b, 0x3e, 0x41, 0xa9, 0x7f, 0xa3, + 0x1b, 0xf4, 0x43, 0xc5, 0x51, 0xbe, 0x28, 0x59, + 0xe9, 0x45, 0x26, 0x49, 0x38, 0x32, 0xf8, 0xf3, + 0x92, 0x6e, 0x30, 0xcc, 0xb0, 0xa0, 0xf9, 0x01, + 0x14, 0xc8, 0xba, 0xd9, 0xf0, 0x2a, 0x29, 0xe2, + 0x52, 0x9a, 0x76, 0x95, 0x3a, 0x16, 0x32, 0xec, + 0xf4, 0x10, 0xec, 0xee, 0x47, 0x00, 0x70, 0x19, + 0xe4, 0x72, 0x35, 0x66, 0x44, 0x53, 0x2d, 0xa2, + 0xf3, 0xaa, 0x7e, 0x8a, 0x33, 0x13, 0xcd, 0xc8, + 0xbf, 0x0e, 0x40, 0x90, 0x00, 0xe4, 0x42, 0xc3, + 0x09, 0x84, 0xe1, 0x66, 0x17, 0xa2, 0xaf, 0x03, + 0xab, 0x6b, 0xa1, 0xec, 0xfb, 0x17, 0x72, 0x81, + 0xfe, 0x9a, 0x9f, 0xf4, 0xb2, 0x33, 0x1f, 0xae, + 0x0c, 0xd1, 0x6a, 0xae, 0x19, 0xb8, 0xaf, 0xec, + 0xe3, 0xea, 0x00, 0xf8, 0xac, 0x87, 0x07, 0x5f, + 0x6d, 0xb0, 0xac, 0x6b, 0x22, 0x48, 0x36, 0xbf, + 0x22, 0x18, 0xb0, 0x03, 0x9f, 0x6c, 0x70, 0x45, + 0x36, 0xf0, 0x6b, 0xc6, 0xc2, 0xa5, 0x72, 0x2c, + 0xd8, 0xe0, 0x27, 0x3d, 0xec, 0x56, 0x07, 0x05, + 0x7d, 0x83, 0xa1, 0x65, 0x7d, 0x41, 0x5b, 0xcd, + 0x77, 0x24, 0xe5, 0xaa, 0x76, 0x47, 0xd0, 0x50, + 0xf6, 0xe7, 0xb5, 0x59, 0x75, 0x31, 0x27, 0xef, + 0xd8, 0xa6, 0x4e, 0x7f, 0xb8, 0x40, 0xb1, 0xdf, + 0x53, 0x14, 0xed, 0xf1, 0x68, 0x5f, 0xfc, 0x3f, + 0x02, 0xdb, 0x05, 0xeb, 0x31, 0xe4, 0x2c, 0x7f, + 0x32, 0xb5, 0x70, 0x8e, 0x75, 0x85, 0xa4, 0x5c, + 0x16, 0x23, 0x37, 0xf2, 0x10, 0x79, 0xcb, 0xdc, + 0xf8, 0x1c, 0x25, 0xc2, 0xa1, 0x3d, 0x9c, 0x33, + 0x6c, 0xed, 0xc3, 0xe7, 0xf3, 0x02, 0x87, 0x82, + 0x4e, 0xfb, 0xac, 0xb3, 0x2d, 0xfc, 0xf8, 0x0d, + 0x1d, 0x4a, 0x39, 0xd4, 0xb3, 0x09, 0xbb, 0xe9, + 0x25, 0xc7, 0xec, 0x6a, 0x87, 0x72, 0x84, 0xed, + 0x12, 0x60, 0x19, 0x64, 0xeb, 0x16, 0x2a, 0x5b, + 0x10, 0x76, 0x27, 0xff, 0x7b, 0xe4, 0xae, 0xe5, + 0xa4, 0x04, 0x02, 0x7f, 0xbb, 0x0a, 0xb5, 0xf4, + 0x05, 0xa5, 0x56, 0x1c, 0x53, 0x31, 0x7a, 0x93, + 0xba, 0x16, 0x15, 0xab, 0x62, 0x60, 0xfc, 0xde, + 0x72, 0x36, 0x6e, 0x28, 0xaf, 0x98, 0x0d, 0xe6, + 0xf4, 0xde, 0x60, 0xa7, 0x7e, 0x06, 0x07, 0x86, + 0xf3, 0x94, 0xb6, 0x6d, 0x0d, 0x93, 0xa6, 0xbc, + 0x60, 0x70, 0x33, 0xac, 0x3f, 0xa1, 0xa8, 0x4a, + 0x20, 0x61, 0xb6, 0xb5, 0x43, 0xa3, 0x15, 0x5a, + 0x00, 0xbe, 0x76, 0x98, 0x57, 0x72, 0xab, 0x7a, + 0x0e, 0x18, 0x93, 0x82, 0x3a, 0x18, 0x78, 0x6e, + 0x71, 0x7b, 0x78, 0x4f, 0x7e, 0x8c, 0xde, 0x7a, + 0x62, 0xb5, 0x0a, 0x7c, 0x45, 0x1d, 0x16, 0xd5, + 0xc3, 0x8c, 0x9b, 0x25, 0xb4, 0x50, 0x90, 0xcd, + 0x96, 0x93, 0xad, 0x0f, 0xd4, 0x43, 0xcb, 0x49, + 0x0f, 0xfc, 0x5a, 0x31, 0xf4, 0x19, 0xb7, 0xd4, + 0xeb, 0x4d, 0x40, 0x58, 0xd0, 0x3b, 0xc8, 0xe0, + 0x4a, 0x54, 0x2f, 0xdb, 0x22, 0xc3, 0x29, 0x7b, + 0x40, 0x90, 0x61, 0x43, 0xd3, 0x7e, 0xe2, 0x30, + 0x2b, 0x48, 0x3c, 0xce, 0x90, 0x93, 0xb1, 0x8b, + 0x31, 0x96, 0x65, 0x6d, 0x57, 0x8b, 0x9d, 0x4d, + 0x53, 0xf0, 0x83, 0x1c, 0xe5, 0xa1, 0x9d, 0x55, + 0xe3, 0xbf, 0x7e, 0xca, 0x1a, 0x74, 0x66, 0x14, + 0xcc, 0x47, 0x43, 0xd9, 0xbb, 0xef, 0x97, 0x7d, + 0xb7, 0x6e, 0xff, 0xf1, 0x22, 0xf8, 0x10, 0x2d, + 0x3f, 0xcd, 0x49, 0x96, 0xd9, 0x09, 0x11, 0xb8, + 0x33, 0xd0, 0x23, 0x9a, 0xfa, 0x16, 0xcb, 0x50, + 0x26, 0x57, 0x24, 0x5c, 0x0e, 0xba, 0xf0, 0x3f, + 0x37, 0x2f, 0xa3, 0xf7, 0x18, 0x57, 0x48, 0x48, + 0x95, 0xcf, 0xef, 0x87, 0x67, 0x2a, 0xe9, 0xb6, + 0x8a, 0x21, 0x36, 0x7f, 0xff, 0x48, 0x6c, 0x46, + 0x35, 0x57, 0xf2, 0xbc, 0x48, 0x67, 0x8f, 0x63, + 0x23, 0x78, 0x11, 0x2b, 0xc2, 0x08, 0xde, 0x51, + 0xe8, 0x8b, 0x92, 0x29, 0xf9, 0x9a, 0x9e, 0xad, + 0xed, 0x0f, 0xeb, 0xa2, 0xd2, 0x40, 0x92, 0xd4, + 0xde, 0x62, 0x95, 0x76, 0xfd, 0x6e, 0x3c, 0xbf, + 0xc0, 0xd7, 0x0d, 0xe5, 0x1b, 0xa4, 0xc7, 0x18, + 0xe1, 0x58, 0xa4, 0x56, 0xef, 0x2e, 0x17, 0x1b, + 0x75, 0xcb, 0xbc, 0xf9, 0x2a, 0x95, 0x71, 0xa7, + 0x1d, 0x7f, 0xe7, 0x73, 0x63, 0x05, 0x6b, 0x19, + 0x4c, 0xf4, 0x22, 0x14, 0xc4, 0x59, 0x88, 0x66, + 0x92, 0x86, 0x61, 0x5c, 0x6a, 0xae, 0xec, 0x58, + 0xff, 0xc9, 0xf2, 0x44, 0xd4, 0xa2, 0xf5, 0x98, + 0xeb, 0x5f, 0x09, 0xbc, 0x8a, 0xbf, 0x3c, 0xb4, + 0x3e, 0xb1, 0x20, 0x05, 0x44, 0x96, 0x79, 0x0a, + 0x40, 0x92, 0x7f, 0x9d, 0xd1, 0xaf, 0xbc, 0x90, + 0x95, 0x0a, 0x81, 0xd4, 0xa7, 0xc6, 0xb8, 0xe0, + 0xe4, 0x39, 0x30, 0x1d, 0x79, 0xc0, 0xe5, 0xfa, + 0xb4, 0xe9, 0x63, 0xb4, 0x09, 0x72, 0x3b, 0x3e, + 0xd9, 0xf6, 0xd9, 0x10, 0x21, 0x18, 0x7e, 0xe5, + 0xad, 0x81, 0xd7, 0xd5, 0x82, 0xd0, 0x8c, 0x3b, + 0x38, 0x95, 0xf8, 0x92, 0x01, 0xa9, 0x92, 0x00, + 0x70, 0xd1, 0xa7, 0x88, 0x77, 0x1f, 0x3a, 0xeb, + 0xb5, 0xe4, 0xf5, 0x9d, 0xc7, 0x37, 0x86, 0xb2, + 0x12, 0x46, 0x34, 0x19, 0x72, 0x8c, 0xf5, 0x8c, + 0xf6, 0x78, 0x98, 0xe0, 0x7c, 0xd3, 0xf4 + }, + "id-Gost28147-89-CryptoPro-B-ParamSet", + "testcfb2", + { + 0x48, 0x0c, 0x74, 0x1b, 0x02, 0x6b, 0x55, 0xd5, + 0xb6, 0x6d, 0xd7, 0x1d, 0x40, 0x48, 0x05, 0x6b, + 0x6d, 0xeb, 0x3c, 0x29, 0x0f, 0x84, 0x80, 0x23, + 0xee, 0x0d, 0x47, 0x77, 0xe3, 0xfe, 0x61, 0xc9 + }, + G89_CFB, + { + 0x1f, 0x3f, 0x82, 0x1e, 0x0d, 0xd8, 0x1e, 0x22 + }, + { + 0x23, 0xc6, 0x7f, 0x20, 0xa1, 0x23, 0x58, 0xbc, + 0x7b, 0x05, 0xdb, 0x21, 0x15, 0xcf, 0x96, 0x41, + 0xc7, 0x88, 0xef, 0x76, 0x5c, 0x49, 0xdb, 0x42, + 0xbf, 0xf3, 0xc0, 0xf5, 0xbd, 0x5d, 0xd9, 0x8e, + 0xaf, 0x3d, 0xf4, 0xe4, 0xda, 0x88, 0xbd, 0xbc, + 0x47, 0x5d, 0x76, 0x07, 0xc9, 0x5f, 0x54, 0x1d, + 0x1d, 0x6a, 0xa1, 0x2e, 0x18, 0xd6, 0x60, 0x84, + 0x02, 0x18, 0x37, 0x92, 0x92, 0x15, 0xab, 0x21, + 0xee, 0x21, 0xcc, 0x71, 0x6e, 0x51, 0xd9, 0x2b, + 0xcc, 0x81, 0x97, 0x3f, 0xeb, 0x45, 0x99, 0xb8, + 0x1b, 0xda, 0xff, 0x90, 0xd3, 0x41, 0x06, 0x9c, + 0x3f, 0xfb, 0xe4, 0xb2, 0xdc, 0xc9, 0x03, 0x0d, + 0xa7, 0xae, 0xd7, 0x7d, 0x02, 0xb8, 0x32, 0xab, + 0xf3, 0x65, 0xa3, 0x65, 0x6c, 0x4e, 0xe4, 0xa2, + 0x5e, 0x9e, 0xee, 0xcd, 0xde, 0x79, 0x36, 0x6b, + 0x1b, 0xe1, 0x3c, 0xdf, 0x10, 0xad, 0x4f, 0x02, + 0xe1, 0x14, 0xaa, 0x09, 0xb4, 0x0b, 0x76, 0xeb, + 0x69, 0x38, 0x20, 0x02, 0xcb, 0x8e, 0xc0, 0xdf, + 0xca, 0x48, 0x74, 0xc3, 0x31, 0xad, 0x42, 0x2c, + 0x51, 0x9b, 0xd0, 0x6a, 0xc1, 0x36, 0xd7, 0x21, + 0xdf, 0xb0, 0x45, 0xba, 0xca, 0x7f, 0x35, 0x20, + 0x28, 0xbb, 0xc1, 0x76, 0xfd, 0x43, 0x5d, 0x23, + 0x7d, 0x31, 0x84, 0x1a, 0x97, 0x4d, 0x83, 0xaa, + 0x7e, 0xf1, 0xc4, 0xe6, 0x83, 0xac, 0x0d, 0xef, + 0xef, 0x3c, 0xa4, 0x7c, 0x48, 0xe4, 0xc8, 0xca, + 0x0d, 0x7d, 0xea, 0x7c, 0x45, 0xd7, 0x73, 0x50, + 0x25, 0x1d, 0x01, 0xc4, 0x02, 0x1a, 0xcd, 0xe0, + 0x38, 0x5b, 0xa8, 0x5a, 0x16, 0x9a, 0x10, 0x59, + 0x74, 0xd7, 0x19, 0xc6, 0xf3, 0xb5, 0x17, 0xf6, + 0x59, 0x8d, 0x62, 0xaf, 0x44, 0xe8, 0xdc, 0xe9, + 0xc1, 0x76, 0xf1, 0xd0, 0xbd, 0x29, 0xd7, 0xec, + 0x1d, 0xac, 0x57, 0xdb, 0x1a, 0x3f, 0xd8, 0xf6, + 0x6e, 0xb6, 0xe6, 0xdf, 0x36, 0xe7, 0x89, 0xce, + 0x56, 0x35, 0x43, 0x1c, 0x7d, 0x57, 0x79, 0x0e, + 0xd8, 0xf4, 0xd7, 0xa7, 0x0d, 0xc6, 0x8f, 0x91, + 0x66, 0x67, 0x82, 0x0f, 0x49, 0xc9, 0xc5, 0x65, + 0x81, 0xa1, 0x39, 0x5a, 0x53, 0x9f, 0x02, 0xa5, + 0xd5, 0x36, 0x22, 0xa8, 0xa8, 0x1c, 0x37, 0x0e, + 0x76, 0x46, 0xdf, 0xbd, 0x6a, 0xdb, 0xfc, 0x1b, + 0xbd, 0x10, 0xb8, 0xb1, 0xbc, 0x72, 0x4c, 0x58, + 0x4a, 0xda, 0x6d, 0x66, 0x00, 0xda, 0x7a, 0x66, + 0xa0, 0xe7, 0x3b, 0x39, 0xa3, 0xf7, 0x05, 0x07, + 0xfa, 0x21, 0x4b, 0xc7, 0x94, 0xc0, 0xd3, 0x7b, + 0x19, 0x02, 0x5d, 0x4a, 0x10, 0xf1, 0xc2, 0x0f, + 0x19, 0x68, 0x27, 0xc7, 0x7d, 0xbf, 0x55, 0x03, + 0x57, 0x7d, 0xaf, 0x77, 0xae, 0x80, 0x2f, 0x7a, + 0xe6, 0x1f, 0x4b, 0xdc, 0x15, 0x18, 0xc0, 0x62, + 0xa1, 0xe8, 0xd9, 0x1c, 0x9e, 0x8c, 0x96, 0x39, + 0xc1, 0xc4, 0x88, 0xf7, 0x0c, 0xe1, 0x04, 0x84, + 0x68, 0x51, 0xce, 0xf1, 0x90, 0xda, 0x7f, 0x76, + 0xc8, 0xc0, 0x88, 0xef, 0x8e, 0x15, 0x25, 0x3e, + 0x7b, 0xe4, 0x79, 0xb5, 0x66, 0x2d, 0x9c, 0xd1, + 0x13, 0xda, 0xd0, 0xd5, 0x46, 0xd5, 0x8d, 0x46, + 0x18, 0x07, 0xee, 0xd8, 0xc9, 0x64, 0xe3, 0xbe, + 0x0e, 0x68, 0x27, 0x09, 0x96, 0x26, 0xf6, 0xe2, + 0x19, 0x61, 0x3f, 0xf4, 0x58, 0x27, 0x0a, 0xeb, + 0xce, 0x7c, 0xb6, 0x68, 0x92, 0xe7, 0x12, 0x3b, + 0x31, 0xd4, 0x48, 0xdf, 0x35, 0x8d, 0xf4, 0x86, + 0x42, 0x2a, 0x15, 0x4b, 0xe8, 0x19, 0x1f, 0x26, + 0x65, 0x9b, 0xa8, 0xda, 0x4b, 0x79, 0x1f, 0x8e, + 0xe6, 0x13, 0x7e, 0x49, 0x8f, 0xc1, 0xce, 0xdc, + 0x5e, 0x64, 0x74, 0xce, 0x02, 0x78, 0xe0, 0xcf, + 0xa0, 0xed, 0x5e, 0x31, 0x74, 0xd1, 0xd0, 0xb4, + 0xee, 0x70, 0x19, 0x14, 0x3c, 0x8f, 0x16, 0xa6, + 0xcf, 0x12, 0x93, 0x15, 0x88, 0xeb, 0x91, 0x65, + 0x76, 0x98, 0xfd, 0xa1, 0x94, 0x30, 0xba, 0x43, + 0x62, 0x65, 0x40, 0x04, 0x77, 0x9e, 0xd6, 0xab, + 0x8b, 0x0d, 0x93, 0x80, 0x50, 0x5f, 0xa2, 0x76, + 0x20, 0xa7, 0xd6, 0x9c, 0x27, 0x15, 0x27, 0xbc, + 0xa5, 0x5a, 0xbf, 0xe9, 0x92, 0x82, 0x05, 0xa8, + 0x41, 0xe9, 0xb5, 0x60, 0xd5, 0xc0, 0xd7, 0x4b, + 0xad, 0x38, 0xb2, 0xe9, 0xd1, 0xe5, 0x51, 0x5f, + 0x24, 0x78, 0x24, 0x9a, 0x23, 0xd2, 0xc2, 0x48, + 0xbd, 0x0e, 0xf1, 0x37, 0x72, 0x91, 0x87, 0xb0, + 0x4e, 0xbd, 0x99, 0x6b, 0x2c, 0x01, 0xb6, 0x79, + 0x69, 0xec, 0x0c, 0xed, 0xe5, 0x3f, 0x50, 0x64, + 0x7c, 0xb9, 0xdd, 0xe1, 0x92, 0x81, 0xb5, 0xd0, + 0xcb, 0x17, 0x83, 0x86, 0x8b, 0xea, 0x4f, 0x93, + 0x08, 0xbc, 0x22, 0x0c, 0xef, 0xe8, 0x0d, 0xf5, + 0x9e, 0x23, 0xe1, 0xf9, 0xb7, 0x6b, 0x45, 0x0b, + 0xcb, 0xa9, 0xb6, 0x4d, 0x28, 0x25, 0xba, 0x3e, + 0x86, 0xf2, 0x75, 0x47, 0x5d, 0x9d, 0x6b, 0xf6, + 0x8a, 0x05, 0x58, 0x73, 0x3d, 0x00, 0xde, 0xfd, + 0x69, 0xb1, 0x61, 0x16, 0xf5, 0x2e, 0xb0, 0x9f, + 0x31, 0x6a, 0x00, 0xb9, 0xef, 0x71, 0x63, 0x47, + 0xa3, 0xca, 0xe0, 0x40, 0xa8, 0x7e, 0x02, 0x04, + 0xfe, 0xe5, 0xce, 0x48, 0x73, 0xe3, 0x94, 0xcf, + 0xe2, 0xff, 0x29, 0x7e, 0xf6, 0x32, 0xbb, 0xb7, + 0x55, 0x12, 0x21, 0x7a, 0x9c, 0x75, 0x04, 0x0c, + 0xb4, 0x7c, 0xb0, 0x3d, 0x40, 0xb3, 0x11, 0x9a, + 0x7a, 0x9a, 0x13, 0xfb, 0x77, 0xa7, 0x51, 0x68, + 0xf7, 0x05, 0x47, 0x3b, 0x0f, 0x52, 0x5c, 0xe6, + 0xc2, 0x99, 0x3a, 0x37, 0x54, 0x5c, 0x4f, 0x2b, + 0xa7, 0x01, 0x08, 0x74, 0xbc, 0x91, 0xe3, 0xe2, + 0xfe, 0x65, 0x94, 0xfd, 0x3d, 0x18, 0xe0, 0xf0, + 0x62, 0xed, 0xc2, 0x10, 0x82, 0x9c, 0x58, 0x7f, + 0xb2, 0xa3, 0x87, 0x8a, 0x74, 0xd9, 0xc1, 0xfb, + 0x84, 0x28, 0x17, 0xc7, 0x2b, 0xcb, 0x53, 0x1f, + 0x4e, 0x8a, 0x82, 0xfc, 0xb4, 0x3f, 0xc1, 0x47, + 0x25, 0xf3, 0x21, 0xdc, 0x4c, 0x2d, 0x08, 0xfa, + 0xe7, 0x0f, 0x03, 0xa9, 0x68, 0xde, 0x6b, 0x41, + 0xa0, 0xf9, 0x41, 0x6c, 0x57, 0x4d, 0x3a, 0x0e, + 0xea, 0x51, 0xca, 0x9f, 0x97, 0x11, 0x7d, 0xf6, + 0x8e, 0x88, 0x63, 0x67, 0xc9, 0x65, 0x13, 0xca, + 0x38, 0xed, 0x35, 0xbe, 0xf4, 0x27, 0xa9, 0xfc, + 0xa9, 0xe6, 0xc3, 0x40, 0x86, 0x08, 0x39, 0x72, + 0x37, 0xee, 0xb2, 0x87, 0x09, 0x96, 0xb7, 0x40, + 0x87, 0x36, 0x92, 0xc1, 0x5d, 0x6a, 0x2c, 0x43, + 0xca, 0x25, 0xc8, 0x35, 0x37, 0x2d, 0xb5, 0xa9, + 0x27, 0x44, 0x50, 0xf2, 0x6d, 0x22, 0x75, 0x41, + 0x77, 0x2a, 0xdb, 0xb1, 0x8c, 0x6d, 0x05, 0xe8, + 0xc9, 0x99, 0xc7, 0x08, 0xf9, 0x14, 0x8f, 0x78, + 0xa9, 0x8f, 0xc2, 0x5a, 0x7a, 0x65, 0xc5, 0xd8, + 0x86, 0xbb, 0x72, 0x69, 0x6b, 0x6b, 0x45, 0x83, + 0x5b, 0xb1, 0xf7, 0xcd, 0x16, 0x73, 0xee, 0xe9, + 0x80, 0x85, 0xfe, 0x8e, 0xe1, 0xae, 0x53, 0x8f, + 0xde, 0xbe, 0x48, 0x8b, 0x59, 0xef, 0xf6, 0x7e, + 0xd8, 0xb5, 0xa8, 0x47, 0xc0, 0x4e, 0x15, 0x58, + 0xca, 0xd3, 0x2f, 0xf8, 0x6c, 0xa6, 0x3d, 0x78, + 0x4d, 0x7a, 0x54, 0xd6, 0x10, 0xe5, 0xcc, 0x05, + 0xe2, 0x29, 0xb5, 0x86, 0x07, 0x39, 0x7d, 0x78, + 0x8e, 0x5a, 0x8f, 0x83, 0x4c, 0xe7, 0x3d, 0x68, + 0x3e, 0xe5, 0x02, 0xe6, 0x64, 0x4f, 0x5e, 0xb4, + 0x49, 0x77, 0xf0, 0xc0, 0xfa, 0x6f, 0xc8, 0xfb, + 0x9f, 0x84, 0x6f, 0x55, 0xfb, 0x30, 0x5e, 0x89, + 0x93, 0xa9, 0xf3, 0xa6, 0xa3, 0xd7, 0x26, 0xbb, + 0xd8, 0xa8, 0xd9, 0x95, 0x1d, 0xfe, 0xfc, 0xd7, + 0xa8, 0x93, 0x66, 0x2f, 0x04, 0x53, 0x06, 0x64, + 0x7f, 0x31, 0x29, 0xae, 0xb7, 0x9f, 0xba, 0xc4, + 0x6d, 0x68, 0xd1, 0x24, 0x32, 0xf4, 0x11 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 4, + { + 0x07, 0x9c, 0x91, 0xbe + }, + "id-Gost28147-89-CryptoPro-C-ParamSet", + "testcfb3", + { + 0x77, 0xc3, 0x45, 0x8e, 0xf6, 0x42, 0xe7, 0x04, + 0x8e, 0xfc, 0x08, 0xe4, 0x70, 0x96, 0xd6, 0x05, + 0x93, 0x59, 0x02, 0x6d, 0x6f, 0x97, 0xca, 0xe9, + 0xcf, 0x89, 0x44, 0x4b, 0xde, 0x6c, 0x22, 0x1d + }, + G89_CFB, + { + 0x43, 0x7c, 0x3e, 0x8e, 0x2f, 0x2a, 0x00, 0x98 + }, + { + 0x19, 0x35, 0x81, 0x34 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 9, + { + 0x2f, 0x31, 0xd8, 0x83, 0xb4, 0x20, 0xe8, 0x6e, + 0xda + }, + "id-Gost28147-89-CryptoPro-D-ParamSet", + "testcfb4", + { + 0x38, 0x9f, 0xe8, 0x37, 0xff, 0x9c, 0x5d, 0x29, + 0xfc, 0x48, 0x55, 0xa0, 0x87, 0xea, 0xe8, 0x40, + 0x20, 0x87, 0x5b, 0xb2, 0x01, 0x15, 0x55, 0xa7, + 0xe3, 0x2d, 0xcb, 0x3d, 0xd6, 0x59, 0x04, 0x73 + }, + G89_CFB, + { + 0xc5, 0xa2, 0xd2, 0x1f, 0x2f, 0xdf, 0xb8, 0xeb + }, + { + 0x6d, 0xa4, 0xed, 0x40, 0x08, 0x88, 0x71, 0xad, + 0x16 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 5242880+8, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test5Mcfb", + { + 0x61, 0x58, 0x44, 0x5a, 0x41, 0xf6, 0xc7, 0x0f, + 0x6b, 0xdb, 0x51, 0x91, 0x6a, 0xf6, 0x81, 0x30, + 0x8c, 0xa7, 0x98, 0xdd, 0x38, 0x35, 0x8a, 0x60, + 0x85, 0xb4, 0xf0, 0xf9, 0x43, 0xa2, 0x7d, 0x9a + }, + G89_CFB, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x1c, 0x16, 0xa0, 0xe9, 0x63, 0x94, 0xfe, 0x38, + 0x37, 0xa7, 0x9b, 0x70, 0x25, 0x2e, 0xd6, 0x00 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + U64(4294967296)+16, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test4Gcfb", + { + 0xae, 0x57, 0xa2, 0xdd, 0xa4, 0xef, 0x4f, 0x96, + 0xb8, 0x94, 0xa5, 0xd1, 0x1b, 0xc8, 0x9b, 0x42, + 0xa5, 0x24, 0xcc, 0x89, 0x5c, 0xb8, 0x92, 0x52, + 0xc1, 0x12, 0x6a, 0xb0, 0x9a, 0x26, 0xe8, 0x06 + }, + G89_CFB, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x2e, 0x62, 0xb0, 0x2e, 0xc7, 0x87, 0x4b, 0x29, + 0x33, 0x16, 0x6b, 0xb4, 0xd6, 0x61, 0x66, 0xd9 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 1037, + { + 0x3d, 0x0b, 0x69, 0xf7, 0xa8, 0xe4, 0xfc, 0x99, + 0x22, 0x2e, 0xee, 0xd1, 0x63, 0x12, 0xfe, 0xa8, + 0x9d, 0xcb, 0x6c, 0x4d, 0x48, 0x8c, 0xe8, 0xbd, + 0x8b, 0x60, 0xf1, 0xbf, 0x7b, 0xe3, 0x79, 0xd5, + 0x2b, 0x25, 0x97, 0x13, 0xef, 0x35, 0xda, 0xf4, + 0xbc, 0x77, 0xce, 0xea, 0xe9, 0x3f, 0xa4, 0xb6, + 0x01, 0xd5, 0x73, 0x29, 0x58, 0xda, 0xd7, 0x67, + 0x17, 0xac, 0xe4, 0x75, 0x2f, 0x57, 0x23, 0xac, + 0x96, 0x21, 0xc7, 0x62, 0x2d, 0xf7, 0x32, 0xb5, + 0x44, 0x5f, 0x72, 0xb1, 0x5f, 0xba, 0x1b, 0x1e, + 0xdb, 0x4a, 0x09, 0x8c, 0x92, 0x61, 0xa2, 0xb0, + 0x49, 0x68, 0xe5, 0xb3, 0xa2, 0x8f, 0x13, 0x4b, + 0xf5, 0x4d, 0x84, 0xda, 0xab, 0xa0, 0xb6, 0xd1, + 0x5a, 0x63, 0x19, 0xe8, 0xa2, 0x09, 0xf6, 0x76, + 0x6f, 0x9b, 0x48, 0x0a, 0x15, 0x5d, 0xb7, 0x20, + 0x21, 0x9a, 0x2e, 0xb9, 0x6d, 0xfa, 0x1e, 0xc2, + 0x0e, 0xef, 0x15, 0xab, 0x59, 0x01, 0xfe, 0x43, + 0x90, 0xf2, 0x62, 0xca, 0x4a, 0x9a, 0x48, 0x38, + 0xab, 0x6f, 0x9d, 0x21, 0xb3, 0xad, 0xa7, 0x60, + 0x46, 0xe3, 0xef, 0xd0, 0xe3, 0x1d, 0xc5, 0xe1, + 0xb8, 0xa1, 0xe2, 0x99, 0x20, 0xc5, 0x76, 0xcc, + 0xaa, 0x8a, 0xa9, 0x45, 0x55, 0xa0, 0x78, 0x00, + 0x64, 0xde, 0xcf, 0x5b, 0xdf, 0x26, 0x48, 0xcd, + 0xba, 0x8a, 0xb5, 0xfb, 0xfd, 0x4a, 0xd5, 0xc4, + 0xe0, 0x43, 0xa6, 0x71, 0x90, 0xa4, 0x8b, 0xca, + 0x2e, 0x88, 0x7b, 0xac, 0xb2, 0xdc, 0xf2, 0x01, + 0xcb, 0xda, 0x6e, 0x91, 0x27, 0x28, 0x44, 0x88, + 0x9a, 0xd2, 0x12, 0xf1, 0xa6, 0xf5, 0xb7, 0x61, + 0xce, 0x79, 0x62, 0x52, 0x3c, 0xe6, 0x14, 0x73, + 0xd1, 0x41, 0x92, 0x50, 0xbd, 0xdc, 0x3b, 0xd0, + 0xa7, 0x11, 0x8c, 0x3a, 0xe4, 0x2d, 0xf2, 0x52, + 0xd3, 0x2f, 0x7c, 0x8e, 0x54, 0x90, 0x4e, 0x23, + 0xae, 0xb3, 0xa0, 0xf3, 0x25, 0x7e, 0x66, 0xaa, + 0x0f, 0x6f, 0x81, 0x72, 0x77, 0xbb, 0xd3, 0x47, + 0xe8, 0x05, 0xff, 0xe1, 0x5b, 0xc9, 0x37, 0x50, + 0x33, 0x49, 0x17, 0xaf, 0xab, 0x1d, 0xe1, 0x15, + 0xf2, 0xe5, 0x98, 0x5e, 0x2d, 0x05, 0x1f, 0x0d, + 0x55, 0x97, 0xed, 0xff, 0x5e, 0xe0, 0x0f, 0xc3, + 0x9c, 0xbd, 0x82, 0xc2, 0x06, 0xbe, 0x45, 0x66, + 0xae, 0x33, 0xbe, 0x28, 0x48, 0xe9, 0x2d, 0x1a, + 0xe6, 0x65, 0x8e, 0xdf, 0x76, 0x03, 0x73, 0x4b, + 0xc0, 0x80, 0x71, 0xf9, 0xac, 0xba, 0xa0, 0xb0, + 0x19, 0x1a, 0x0a, 0xd4, 0x35, 0x12, 0x88, 0x76, + 0x05, 0x75, 0x8f, 0x7c, 0xb5, 0xf0, 0x19, 0x75, + 0x6d, 0x05, 0xcb, 0x0d, 0xbc, 0x8d, 0xe9, 0xf0, + 0xd4, 0xdb, 0x3c, 0x3c, 0x29, 0x8e, 0x2c, 0x32, + 0x1d, 0xf7, 0xb6, 0x49, 0xcf, 0xdb, 0x63, 0xee, + 0x3c, 0xfa, 0x33, 0x73, 0x6f, 0xe4, 0x97, 0x4e, + 0x2f, 0xc9, 0x4c, 0x5c, 0x65, 0xfe, 0xea, 0xfb, + 0xc6, 0xdd, 0xc1, 0x1c, 0x47, 0x3f, 0xf4, 0x50, + 0x2f, 0xde, 0x1b, 0x5b, 0x0b, 0x16, 0xca, 0xb6, + 0x46, 0x44, 0xf2, 0xc1, 0x0d, 0xa1, 0x1d, 0xa6, + 0xdb, 0xf0, 0x3d, 0xb1, 0x6c, 0x05, 0x31, 0x85, + 0x8e, 0x74, 0xae, 0xf2, 0x39, 0x26, 0xf7, 0xc1, + 0xe7, 0x4c, 0xdd, 0x9d, 0x40, 0xb8, 0xf3, 0xc5, + 0xc2, 0x16, 0x64, 0x6b, 0xaa, 0xdb, 0x4b, 0x82, + 0x5c, 0xd3, 0x02, 0xd3, 0x8f, 0x26, 0x79, 0x8d, + 0xb0, 0x78, 0x70, 0x19, 0x58, 0x0c, 0xb4, 0x31, + 0x88, 0x44, 0x1c, 0x91, 0x6f, 0xf4, 0x52, 0x39, + 0xa8, 0xf5, 0xc0, 0x1b, 0xfe, 0xf2, 0x0e, 0x4b, + 0xac, 0x0a, 0xc2, 0x7e, 0x9c, 0x9b, 0xeb, 0x5d, + 0x4e, 0x4f, 0x42, 0xd8, 0x71, 0x0a, 0x97, 0x27, + 0x03, 0x14, 0x96, 0xa6, 0x3d, 0x04, 0xea, 0x9f, + 0x14, 0x14, 0x27, 0x4c, 0xd9, 0xa2, 0x89, 0x5f, + 0x65, 0x4a, 0xe1, 0x9d, 0x2c, 0xb8, 0xf8, 0xd4, + 0x8f, 0x2a, 0x57, 0x36, 0xcc, 0x06, 0x9c, 0x2c, + 0xc5, 0x13, 0x16, 0xdf, 0xfc, 0xae, 0x22, 0x16, + 0xa8, 0x2b, 0x71, 0x6f, 0x1d, 0xb3, 0x47, 0x54, + 0x3f, 0x2d, 0x0a, 0x68, 0x9f, 0x2e, 0xf6, 0x90, + 0xd8, 0xa1, 0x21, 0x09, 0xd4, 0x97, 0xb9, 0x7b, + 0x7f, 0x9b, 0x6a, 0xed, 0xd1, 0xf0, 0xe3, 0xb6, + 0x28, 0xc7, 0x62, 0x82, 0x00, 0xc9, 0x38, 0xa1, + 0x82, 0x78, 0xce, 0x87, 0xc8, 0x53, 0xac, 0x4f, + 0x2e, 0x31, 0xb9, 0x50, 0x7f, 0x36, 0x00, 0x4a, + 0x32, 0xe6, 0xd8, 0xbb, 0x59, 0x45, 0x0e, 0x91, + 0x1b, 0x38, 0xa9, 0xbc, 0xb9, 0x5e, 0x6c, 0x6a, + 0x9c, 0x03, 0x01, 0x1c, 0xde, 0xe8, 0x1f, 0x1e, + 0xe3, 0xde, 0x25, 0xa2, 0x56, 0x79, 0xe1, 0xbd, + 0x58, 0xc4, 0x93, 0xe6, 0xd0, 0x8a, 0x4d, 0x08, + 0xab, 0xf7, 0xaa, 0xc3, 0x7d, 0xc1, 0xee, 0x68, + 0x37, 0xbc, 0x78, 0x0b, 0x19, 0x68, 0x2b, 0x2b, + 0x2e, 0x6d, 0xc4, 0x6f, 0xaa, 0x3b, 0xc6, 0x19, + 0xcb, 0xf1, 0x58, 0xb9, 0x60, 0x85, 0x45, 0xae, + 0x52, 0x97, 0xba, 0x24, 0x32, 0x13, 0x72, 0x16, + 0x6e, 0x7b, 0xc1, 0x98, 0xac, 0xb1, 0xed, 0xb4, + 0xcc, 0x6c, 0xcf, 0x45, 0xfc, 0x50, 0x89, 0x80, + 0x8e, 0x7a, 0xa4, 0xd3, 0x64, 0x50, 0x63, 0x37, + 0xc9, 0x6c, 0xf1, 0xc4, 0x3d, 0xfb, 0xde, 0x5a, + 0x5c, 0xa8, 0x21, 0x35, 0xe6, 0x2e, 0x8c, 0x2a, + 0x3c, 0x12, 0x17, 0x79, 0x9a, 0x0d, 0x2e, 0x79, + 0xeb, 0x67, 0x1f, 0x2b, 0xf8, 0x6e, 0xca, 0xc1, + 0xfa, 0x45, 0x18, 0x9e, 0xdf, 0x6a, 0xe6, 0xcb, + 0xe9, 0x5c, 0xc3, 0x09, 0xaf, 0x93, 0x58, 0x13, + 0xbf, 0x90, 0x84, 0x87, 0x75, 0xd6, 0x82, 0x28, + 0x8d, 0xe7, 0x2f, 0xa3, 0xfb, 0x97, 0x74, 0x2a, + 0x73, 0x04, 0x82, 0x06, 0x76, 0x69, 0xb1, 0x0b, + 0x19, 0xfc, 0xae, 0xb3, 0xdd, 0x2a, 0xe5, 0xc1, + 0x05, 0xd8, 0x80, 0x95, 0x22, 0x90, 0x71, 0xfc, + 0xc2, 0x92, 0x42, 0xfd, 0xf1, 0x70, 0xb4, 0x68, + 0x88, 0xa4, 0x9e, 0x0a, 0x24, 0x40, 0x13, 0xc8, + 0xa2, 0x56, 0x4f, 0x39, 0xe6, 0x06, 0xf1, 0xdc, + 0xf5, 0x13, 0x0e, 0xad, 0x9c, 0x8b, 0xaf, 0xe9, + 0xe3, 0x88, 0x72, 0xff, 0xa0, 0x6d, 0xda, 0x08, + 0x70, 0xb9, 0x2e, 0x83, 0xc5, 0xbb, 0x32, 0xa5, + 0x74, 0xc7, 0xfb, 0x7b, 0x76, 0xaf, 0x02, 0xbb, + 0x2b, 0xb8, 0x5e, 0x65, 0x02, 0xfe, 0x0e, 0xa0, + 0x99, 0xce, 0x01, 0x3b, 0x35, 0xe1, 0xb0, 0x22, + 0xe5, 0x94, 0xbd, 0xdd, 0x8e, 0xbb, 0xf6, 0x75, + 0xbf, 0xbf, 0xee, 0x7a, 0xb1, 0x58, 0xb4, 0x81, + 0xb8, 0x39, 0x3e, 0xb6, 0x1e, 0xde, 0xda, 0x1b, + 0xd5, 0xf7, 0xdd, 0x7d, 0x65, 0x9c, 0xaa, 0x56, + 0x93, 0xb8, 0xaf, 0x48, 0x53, 0xc7, 0x22, 0xe4, + 0x1c, 0xdf, 0xe9, 0x79, 0xb4, 0x20, 0x89, 0xcc, + 0x2a, 0x79, 0x2c, 0x09, 0xbe, 0x78, 0xcf, 0xcc, + 0xf2, 0x90, 0xd6, 0x65, 0xc5, 0x29, 0xfc, 0xda, + 0x69, 0xfc, 0xc0, 0xd6, 0x70, 0x99, 0x61, 0x3f, + 0x60, 0x02, 0xd8, 0x12, 0x22, 0xc8, 0x34, 0xc6, + 0x3b, 0xb3, 0xc2, 0x33, 0xa1, 0x5c, 0x8f, 0x4c, + 0xd1, 0x52, 0x72, 0xf2, 0x42, 0x05, 0x8e, 0x18, + 0x1f, 0x16, 0xda, 0xb8, 0x53, 0xa1, 0x5f, 0x01, + 0x32, 0x1b, 0x90, 0xb3, 0x53, 0x9b, 0xd0, 0x85, + 0x61, 0x2d, 0x17, 0xed, 0x0a, 0xa4, 0xa5, 0x27, + 0x09, 0x75, 0x7c, 0xbc, 0x30, 0xf7, 0x5e, 0x59, + 0x9a, 0x07, 0x96, 0x84, 0x28, 0x86, 0x4b, 0xa7, + 0x22, 0x35, 0x28, 0xc7, 0xed, 0x0d, 0xc3, 0xce, + 0x98, 0xcc, 0x2d, 0xec, 0xd4, 0x98, 0x09, 0x8e, + 0x52, 0x5f, 0x2b, 0x9a, 0x13, 0xbe, 0x99, 0x16, + 0x73, 0xd1, 0x1f, 0x81, 0xe5, 0xa2, 0x08, 0x78, + 0xcb, 0x0c, 0x20, 0xd4, 0xa5, 0xea, 0x4b, 0x5b, + 0x95, 0x5a, 0x92, 0x9a, 0x52 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testcnt2", + { + 0x1b, 0x5d, 0xdb, 0x77, 0xcf, 0xf9, 0xec, 0x95, + 0x5e, 0xcc, 0x67, 0x9f, 0x5d, 0x28, 0xad, 0x4a, + 0x27, 0xf4, 0x32, 0xc6, 0xb2, 0xcb, 0xb1, 0x45, + 0x6a, 0x88, 0x14, 0x0c, 0x9b, 0x9b, 0x5f, 0x48 + }, + G89_CNT, + { + 0x71, 0x58, 0x8c, 0xe1, 0x55, 0xf4, 0xf6, 0xb3 + }, + { + 0x8e, 0xcd, 0x8f, 0xc8, 0xac, 0xe1, 0x15, 0x48, + 0x2d, 0xae, 0x24, 0x8a, 0xc7, 0xfb, 0xba, 0x0f, + 0x1d, 0x8a, 0x95, 0xa2, 0x43, 0xef, 0xcb, 0xdc, + 0x59, 0x57, 0xa7, 0xc7, 0x0e, 0xe3, 0xe2, 0xb9, + 0x0d, 0x86, 0x29, 0x62, 0xcb, 0x83, 0x4d, 0x07, + 0x0c, 0x40, 0xd4, 0x7b, 0x2e, 0xca, 0xba, 0xbf, + 0x4a, 0x60, 0x3b, 0x31, 0x98, 0xc8, 0x88, 0x47, + 0xd9, 0x82, 0xab, 0xfc, 0x8f, 0x48, 0xe2, 0x46, + 0xab, 0xd3, 0xa1, 0xab, 0x8a, 0x05, 0x22, 0x8c, + 0xf4, 0xec, 0x9a, 0x1e, 0x76, 0xab, 0x1a, 0x60, + 0xd9, 0x25, 0x6b, 0xb8, 0x56, 0xe5, 0xb2, 0xea, + 0x10, 0xf3, 0x62, 0x04, 0x32, 0x5e, 0xaa, 0x3b, + 0x7b, 0x57, 0xbc, 0x3b, 0x8b, 0x43, 0x47, 0xf2, + 0xd5, 0x03, 0x7e, 0x51, 0x01, 0xff, 0x77, 0x28, + 0xca, 0x90, 0xa3, 0xfe, 0x7e, 0x2e, 0x70, 0x16, + 0x75, 0x18, 0x44, 0xf0, 0x1b, 0x85, 0x05, 0xea, + 0xe3, 0x21, 0xf7, 0x26, 0x86, 0x76, 0x3c, 0x67, + 0x9d, 0xfc, 0xbc, 0x10, 0x7f, 0x77, 0xe4, 0xed, + 0xd3, 0x12, 0xf8, 0x83, 0x00, 0x1f, 0x4b, 0x92, + 0x95, 0x92, 0x5c, 0xf3, 0x5a, 0xf3, 0xb7, 0xd0, + 0xa9, 0x5f, 0xf2, 0x18, 0xc4, 0x66, 0x62, 0xc1, + 0x84, 0x0e, 0x66, 0xe8, 0x80, 0x7d, 0x1f, 0xf0, + 0xba, 0x01, 0x9b, 0x71, 0xae, 0x93, 0xcc, 0x27, + 0x54, 0x34, 0x9a, 0xbd, 0xca, 0xee, 0x52, 0x09, + 0x92, 0x9d, 0xb0, 0xd5, 0xd9, 0xba, 0x2f, 0xb9, + 0x96, 0xdc, 0xfa, 0xbd, 0xce, 0xea, 0x1a, 0x7b, + 0x9a, 0x1d, 0x13, 0xa7, 0x11, 0xe2, 0x9a, 0x64, + 0xf6, 0xd3, 0xee, 0xc6, 0x33, 0xb7, 0x6e, 0xef, + 0x25, 0x9e, 0x1e, 0x7c, 0xe3, 0x1f, 0x2c, 0x6e, + 0xa9, 0xc0, 0xf8, 0xc1, 0xbf, 0x3b, 0xf8, 0x34, + 0x03, 0x9b, 0xa1, 0x40, 0x5b, 0x0c, 0x3c, 0x09, + 0x66, 0x9d, 0x63, 0xe2, 0xe2, 0x04, 0x8f, 0x06, + 0x84, 0x74, 0x68, 0xb2, 0x5c, 0x3b, 0x4c, 0xad, + 0x0b, 0x3f, 0x03, 0xb3, 0x07, 0x8a, 0x64, 0xa7, + 0x36, 0x56, 0x26, 0x39, 0x66, 0xda, 0xe9, 0x6d, + 0x1b, 0xd5, 0x88, 0xe8, 0x5c, 0xaf, 0x5a, 0x4c, + 0x49, 0xf7, 0xf5, 0xb7, 0x78, 0xf0, 0xde, 0xec, + 0xcd, 0x16, 0x23, 0x9e, 0x8c, 0x13, 0xbe, 0x6b, + 0x6f, 0x9b, 0x07, 0xe5, 0xbb, 0xcc, 0x3a, 0x1b, + 0x6f, 0x43, 0xdf, 0xff, 0x46, 0x2a, 0xae, 0x47, + 0x19, 0x18, 0x9a, 0x25, 0x09, 0xc9, 0x24, 0x40, + 0x0c, 0x4b, 0xa7, 0xda, 0x5e, 0x0d, 0xee, 0xfa, + 0x62, 0x45, 0x8e, 0xcc, 0x2f, 0x23, 0x08, 0x1d, + 0x92, 0xf0, 0xfe, 0x82, 0x0f, 0xd7, 0x11, 0x60, + 0x7e, 0x0b, 0x0b, 0x75, 0xf4, 0xf5, 0x3b, 0xc0, + 0xa4, 0xe8, 0x72, 0xa5, 0xb6, 0xfa, 0x5a, 0xad, + 0x5a, 0x4f, 0x39, 0xb5, 0xa2, 0x12, 0x96, 0x0a, + 0x32, 0x84, 0xb2, 0xa1, 0x06, 0x68, 0x56, 0x57, + 0x97, 0xa3, 0x7b, 0x22, 0x61, 0x76, 0x5d, 0x30, + 0x1a, 0x31, 0xab, 0x99, 0x06, 0xc5, 0x1a, 0x96, + 0xcf, 0xcf, 0x14, 0xff, 0xb2, 0xc4, 0xcc, 0x2b, + 0xbf, 0x0c, 0x9d, 0x91, 0x8f, 0x79, 0x5b, 0xbc, + 0xa9, 0x6b, 0x91, 0x6a, 0xb4, 0x93, 0x5c, 0x7b, + 0x5d, 0xc2, 0x8a, 0x75, 0xc0, 0xc1, 0x08, 0xfa, + 0x99, 0xf9, 0x4d, 0x5e, 0x0c, 0x06, 0x64, 0x60, + 0xa9, 0x01, 0x4a, 0x34, 0x0f, 0x33, 0x84, 0x95, + 0x69, 0x30, 0xc1, 0x1c, 0x36, 0xf8, 0xfc, 0x30, + 0x23, 0xb2, 0x71, 0xe5, 0x52, 0x4d, 0x12, 0x1a, + 0xc9, 0xbe, 0xee, 0xc9, 0xcb, 0x01, 0x85, 0xf3, + 0xdb, 0x30, 0xf9, 0x41, 0xa9, 0x40, 0xb0, 0x06, + 0x29, 0x77, 0xcd, 0xc5, 0xec, 0x58, 0x02, 0x48, + 0x83, 0x53, 0x44, 0x6a, 0xd2, 0xca, 0x05, 0xd8, + 0x5a, 0x08, 0xeb, 0xa9, 0xf4, 0xe6, 0xc7, 0x9d, + 0xd5, 0x7b, 0x74, 0x0b, 0x31, 0xb7, 0xa5, 0x57, + 0x7c, 0x7a, 0xfd, 0x1a, 0x0e, 0xd7, 0x97, 0x41, + 0xbf, 0xdd, 0xc6, 0x19, 0x6c, 0x77, 0x8c, 0x18, + 0x52, 0x57, 0x83, 0xba, 0x71, 0x25, 0xee, 0x39, + 0xbb, 0xe2, 0x43, 0xa0, 0x14, 0xdc, 0x0e, 0x84, + 0xb4, 0x2b, 0xde, 0x3e, 0xe5, 0x36, 0xb7, 0xa2, + 0x92, 0x98, 0x05, 0xb8, 0x96, 0xe5, 0xd0, 0x8c, + 0x08, 0x93, 0x35, 0xc2, 0x81, 0xe0, 0xfc, 0x59, + 0x71, 0xe2, 0x44, 0x49, 0x5d, 0xda, 0xfb, 0x9c, + 0xaa, 0x70, 0x9f, 0x43, 0xa8, 0xa5, 0xd9, 0x67, + 0xd9, 0x8f, 0xa3, 0x1e, 0xbe, 0x0e, 0xec, 0xdf, + 0x12, 0x2b, 0x6a, 0xe7, 0x1c, 0x12, 0x17, 0xe7, + 0xc4, 0x6d, 0x50, 0xc9, 0x52, 0x7a, 0xd5, 0xe8, + 0x7f, 0xbc, 0x07, 0x15, 0xac, 0xdb, 0x93, 0x66, + 0xb1, 0xf0, 0xa7, 0x7b, 0x2f, 0xe9, 0xec, 0xd0, + 0x47, 0x69, 0x59, 0x87, 0xf1, 0x4c, 0x3e, 0x4b, + 0x9b, 0x11, 0x79, 0x13, 0xe4, 0x96, 0xf6, 0x56, + 0x04, 0x6e, 0x0b, 0x33, 0xfc, 0x40, 0xf6, 0xc7, + 0xc1, 0x43, 0xb1, 0xbf, 0x0e, 0xb3, 0x87, 0xfd, + 0x0b, 0x1c, 0x63, 0x46, 0x3a, 0xd3, 0xa0, 0x17, + 0x59, 0x25, 0x94, 0x6c, 0x9c, 0x3d, 0x0c, 0x81, + 0xce, 0x82, 0x72, 0x42, 0x28, 0xf9, 0x37, 0x6a, + 0x6d, 0xe4, 0x12, 0xf4, 0x21, 0xaa, 0xf7, 0xfe, + 0x27, 0x55, 0x40, 0x1a, 0x14, 0xc3, 0x39, 0x5b, + 0xbf, 0x63, 0xc2, 0x5f, 0x10, 0x1f, 0x14, 0x25, + 0xd0, 0xce, 0xf3, 0x14, 0x48, 0x13, 0xa5, 0x0b, + 0x4d, 0x38, 0xcf, 0x0d, 0x34, 0xc0, 0x0a, 0x11, + 0xb4, 0xb5, 0x72, 0xc8, 0x4b, 0xc2, 0x6f, 0xe7, + 0x9d, 0x93, 0xf7, 0xdf, 0xb8, 0x43, 0x72, 0x7e, + 0xda, 0x3e, 0x20, 0x1f, 0xbc, 0x21, 0x2a, 0xce, + 0x00, 0xfa, 0x96, 0x9f, 0x3d, 0xe5, 0x88, 0x96, + 0xef, 0x29, 0x84, 0xdf, 0x6c, 0x1c, 0x96, 0xd8, + 0x58, 0x47, 0xaa, 0x92, 0xf3, 0x07, 0xe5, 0xfb, + 0xaf, 0xea, 0x95, 0x7e, 0x0b, 0x71, 0xcd, 0x81, + 0x0f, 0xb7, 0x0a, 0x59, 0x8f, 0x31, 0x4d, 0xd1, + 0xc3, 0xf3, 0x2f, 0x70, 0x5c, 0x59, 0x18, 0x97, + 0xaf, 0x77, 0x95, 0x5e, 0xaf, 0x40, 0x06, 0x12, + 0x81, 0x61, 0x86, 0x08, 0x4e, 0xbc, 0x89, 0x46, + 0x07, 0x2e, 0x5b, 0x10, 0xaa, 0x12, 0xf0, 0xa7, + 0x84, 0xe2, 0x9a, 0x08, 0xf1, 0xde, 0x59, 0xe3, + 0x0e, 0x47, 0x4b, 0xff, 0xc3, 0xc9, 0x18, 0xaf, + 0x95, 0x9c, 0x67, 0x2a, 0xde, 0x8a, 0x7a, 0x99, + 0x04, 0xc4, 0xb8, 0x97, 0x4c, 0x04, 0x29, 0x71, + 0x05, 0xda, 0xb3, 0xd6, 0xdb, 0x6c, 0x71, 0xe6, + 0xe8, 0x03, 0xbf, 0x94, 0x7d, 0xde, 0x3d, 0xc8, + 0x44, 0xfa, 0x7d, 0x62, 0xb4, 0x36, 0x03, 0xee, + 0x36, 0x52, 0x64, 0xb4, 0x85, 0x6d, 0xd5, 0x78, + 0xf0, 0x6f, 0x67, 0x2d, 0x0e, 0xe0, 0x2c, 0x88, + 0x9b, 0x55, 0x19, 0x29, 0x40, 0xf6, 0x8c, 0x12, + 0xbb, 0x2c, 0x83, 0x96, 0x40, 0xc0, 0x36, 0xf5, + 0x77, 0xff, 0x70, 0x8c, 0x75, 0x92, 0x0b, 0xad, + 0x05, 0x9b, 0x7e, 0xa2, 0xfc, 0xa9, 0xd1, 0x64, + 0x76, 0x82, 0x13, 0xba, 0x22, 0x5e, 0x33, 0x0e, + 0x26, 0x70, 0xa9, 0xbe, 0x74, 0x28, 0xf5, 0xe2, + 0xc4, 0x96, 0xee, 0x3a, 0xbc, 0x97, 0xa6, 0x2c, + 0x2a, 0xe0, 0x64, 0x8d, 0x35, 0xc6, 0x1a, 0xca, + 0xf4, 0x92, 0xfa, 0xc3, 0xf1, 0x1f, 0x98, 0xe4, + 0x43, 0x88, 0x69, 0x3a, 0x09, 0xbf, 0x63, 0xe5, + 0x96, 0x29, 0x0b, 0x9b, 0x62, 0x23, 0x14, 0x8a, + 0x95, 0xe4, 0x1c, 0x5c, 0x0a, 0xa9, 0xc5, 0xb9, + 0x6f, 0x4f, 0x2b, 0x25, 0x6f, 0x74, 0x1e, 0x18, + 0xd5, 0xfe, 0x27, 0x7d, 0x3f, 0x6e, 0x55, 0x2c, + 0x67, 0xe6, 0xde, 0xb5, 0xcc, 0xc0, 0x2d, 0xff, + 0xc4, 0xe4, 0x06, 0x21, 0xa5, 0xc8, 0xd3, 0xd6, + 0x6c, 0xa1, 0xc3, 0xfb, 0x88, 0x92, 0xb1, 0x1d, + 0x90, 0xe1, 0x35, 0x05, 0x9b, 0x29, 0x6d, 0xba, + 0xf1, 0xf4, 0x1e, 0x23, 0x2e + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 5242880+8, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test5Mcnt", + { + 0x07, 0x52, 0x65, 0xe7, 0xca, 0xa3, 0xca, 0x45, + 0xcf, 0x3a, 0x05, 0x1d, 0x38, 0x03, 0x53, 0x0c, + 0x22, 0x31, 0xba, 0x99, 0x4f, 0x9b, 0x6a, 0x1b, + 0x7e, 0x09, 0x9d, 0x4e, 0xb5, 0xc9, 0x84, 0x2e + }, + G89_CNT, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x3d, 0x05, 0x07, 0x57, 0xc0, 0x75, 0x89, 0x97, + 0xd6, 0x94, 0x49, 0x11, 0x1d, 0xd0, 0x91, 0xee + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + U64(4294967296)+16, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test4Gcnt", + { + 0x75, 0xa3, 0x3c, 0xae, 0x03, 0x6b, 0x10, 0xdb, + 0xc1, 0x56, 0x50, 0x89, 0x03, 0xd2, 0x9f, 0x91, + 0xee, 0xe8, 0x64, 0x1d, 0x43, 0xf2, 0x4e, 0xf8, + 0xf2, 0x6c, 0xed, 0xda, 0x8f, 0xe4, 0x88, 0xe9 + }, + G89_CNT, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0xfa, 0x6c, 0x96, 0x78, 0xe2, 0xf8, 0xdd, 0xaa, + 0x67, 0x5a, 0xc9, 0x5d, 0x57, 0xf1, 0xbd, 0x99 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 1035, + { + 0xd6, 0xcf, 0x31, 0x96, 0x9c, 0xa1, 0xfb, 0xd6, + 0x8d, 0xa3, 0xdd, 0x01, 0xd9, 0x88, 0xc0, 0x2f, + 0xbc, 0x46, 0xc7, 0x3a, 0xe4, 0x21, 0x86, 0x96, + 0x8d, 0xe2, 0xca, 0xb6, 0x37, 0xa2, 0xe1, 0xa8, + 0x7e, 0xa7, 0x79, 0x2e, 0xa4, 0x56, 0x75, 0x7f, + 0x3e, 0x55, 0x8b, 0x43, 0xae, 0x65, 0xdf, 0xaa, + 0x42, 0xb6, 0x00, 0xa6, 0x61, 0x03, 0x0d, 0xd3, + 0x41, 0x02, 0x27, 0x23, 0x95, 0x79, 0x9b, 0x34, + 0x81, 0xa9, 0x86, 0xb5, 0xa7, 0x90, 0xe2, 0xae, + 0xc4, 0x2f, 0xc3, 0x8e, 0x32, 0x56, 0x13, 0xfa, + 0x4d, 0x4e, 0x9f, 0x15, 0x75, 0x7e, 0x74, 0xdc, + 0x32, 0x2d, 0xee, 0x4d, 0x67, 0x70, 0x9f, 0x62, + 0xb9, 0xc4, 0xdb, 0x24, 0x84, 0xcc, 0x16, 0x7b, + 0xda, 0x22, 0xf7, 0xc5, 0xf3, 0x93, 0x35, 0x73, + 0xc6, 0x03, 0x1c, 0x77, 0xa5, 0xf2, 0x76, 0x56, + 0xb4, 0x95, 0xd4, 0x7e, 0x0d, 0x20, 0xc6, 0x6e, + 0xee, 0x8f, 0x25, 0x48, 0xff, 0x7e, 0x01, 0x3a, + 0xb4, 0x1f, 0xaa, 0x35, 0xc0, 0x33, 0x58, 0x9c, + 0xb5, 0xba, 0x65, 0x4b, 0xd3, 0x51, 0x14, 0xec, + 0x61, 0xce, 0xe4, 0xba, 0x49, 0xba, 0x39, 0x32, + 0xab, 0xce, 0x81, 0x72, 0xce, 0xab, 0xed, 0xd4, + 0xd2, 0x19, 0x87, 0x85, 0x92, 0xfa, 0x64, 0x34, + 0xd8, 0x86, 0xf4, 0x8a, 0x08, 0x3c, 0xde, 0xee, + 0x97, 0x92, 0x92, 0x69, 0xba, 0x9b, 0x5f, 0x7a, + 0x03, 0xc1, 0x5d, 0x43, 0x02, 0x8c, 0xbe, 0xd2, + 0x46, 0x72, 0x81, 0x40, 0x7d, 0x68, 0x98, 0x45, + 0x0b, 0x54, 0x27, 0x1c, 0xaf, 0x80, 0x42, 0xe4, + 0xd5, 0xd4, 0xe4, 0xa2, 0x98, 0x07, 0x8f, 0x03, + 0xf5, 0x2c, 0x8c, 0x88, 0xca, 0x5a, 0xde, 0xe4, + 0x9f, 0xb1, 0x5f, 0x82, 0xff, 0x20, 0x67, 0x52, + 0x85, 0x84, 0x4f, 0xc8, 0xfe, 0xa7, 0x9e, 0xae, + 0x1c, 0xfa, 0xb8, 0x75, 0xd3, 0xf7, 0x9f, 0x0d, + 0xda, 0x2d, 0xe6, 0xcc, 0x86, 0x6b, 0xa4, 0x14, + 0x65, 0xc3, 0xf9, 0x15, 0xbc, 0x87, 0xf5, 0xae, + 0x8c, 0x10, 0xd4, 0xce, 0x5b, 0x9c, 0xe2, 0xdd, + 0x42, 0x03, 0x09, 0x87, 0x47, 0xed, 0x5d, 0xd0, + 0x7a, 0x69, 0x4c, 0xfa, 0x43, 0x7d, 0xbf, 0x07, + 0x85, 0x6a, 0xee, 0x68, 0xe6, 0x7a, 0x57, 0xb2, + 0x20, 0x8d, 0x80, 0xf2, 0x91, 0x6f, 0x5c, 0x07, + 0x8c, 0xe4, 0x6a, 0x49, 0x90, 0x85, 0x8b, 0x77, + 0x29, 0x56, 0x1c, 0x5e, 0xa9, 0x3f, 0xab, 0x8b, + 0x79, 0xa3, 0x6f, 0x6b, 0x34, 0xcb, 0x61, 0xf6, + 0xe6, 0x92, 0xd1, 0x48, 0x9e, 0x11, 0xa2, 0x82, + 0xc0, 0x4e, 0x23, 0xd2, 0x15, 0x0d, 0x8d, 0xff, + 0xfa, 0x17, 0x9d, 0x81, 0xb8, 0xbc, 0xd7, 0x5b, + 0x08, 0x81, 0x20, 0x40, 0xc0, 0x3c, 0x06, 0x8b, + 0x1a, 0x88, 0x0b, 0x4b, 0x7b, 0x31, 0xf5, 0xd4, + 0x4e, 0x09, 0xd1, 0x4d, 0x0d, 0x7f, 0x45, 0xd1, + 0x09, 0x35, 0xba, 0xce, 0x65, 0xdd, 0xf2, 0xb8, + 0xfb, 0x7a, 0xbc, 0xc4, 0x4b, 0xc8, 0x75, 0xda, + 0x6b, 0xce, 0x3d, 0xe8, 0x94, 0xcc, 0x23, 0x6f, + 0xb0, 0x3b, 0x4f, 0x7d, 0x07, 0xb9, 0x0f, 0x62, + 0x92, 0x7e, 0xda, 0x70, 0x50, 0xce, 0xd3, 0x28, + 0x12, 0x11, 0x00, 0xeb, 0x8d, 0x63, 0x70, 0x78, + 0xa8, 0x7b, 0x76, 0xab, 0xc6, 0x40, 0xc0, 0x4e, + 0x80, 0xdd, 0xf0, 0xfe, 0x83, 0x72, 0x56, 0x4c, + 0x09, 0x4c, 0xf1, 0x72, 0x72, 0x86, 0x26, 0x31, + 0xc3, 0xc2, 0xdc, 0x8e, 0xc7, 0xf4, 0x35, 0xec, + 0x17, 0x06, 0x63, 0x47, 0x49, 0x88, 0x47, 0xaf, + 0xb3, 0x38, 0x4f, 0x7e, 0x44, 0x95, 0xb5, 0xbb, + 0x1d, 0xbd, 0x5a, 0x91, 0x5b, 0xd0, 0x1a, 0xdf, + 0x0d, 0x0b, 0x50, 0xd8, 0xe2, 0x0e, 0xc5, 0x00, + 0x2d, 0x5b, 0x29, 0x19, 0xaa, 0x2b, 0x64, 0xc5, + 0x40, 0x31, 0x48, 0x11, 0xbc, 0x04, 0xd1, 0xcf, + 0x6d, 0xf9, 0xa5, 0x2f, 0x4a, 0xc9, 0x82, 0xfa, + 0x59, 0xe1, 0xfc, 0xab, 0x1c, 0x33, 0x26, 0x0a, + 0x5f, 0xef, 0xf2, 0x06, 0xd8, 0xd3, 0x7e, 0x16, + 0x58, 0x16, 0x78, 0x73, 0xae, 0xba, 0xeb, 0xe5, + 0x3d, 0xb2, 0x0a, 0xb3, 0x32, 0x2d, 0x14, 0xa4, + 0xfa, 0x3f, 0x1f, 0x43, 0xf9, 0x7b, 0xa9, 0x43, + 0x98, 0x18, 0x94, 0x07, 0x07, 0xe5, 0x19, 0x34, + 0xa8, 0x16, 0x5f, 0x71, 0x67, 0xaa, 0x29, 0xe5, + 0xfa, 0xf0, 0x83, 0x06, 0x1d, 0x9d, 0xfc, 0xfe, + 0xfe, 0x8c, 0xb5, 0xb2, 0xa9, 0xe7, 0xa0, 0x40, + 0x60, 0xb6, 0x71, 0x9e, 0xab, 0x5b, 0x83, 0xb9, + 0x0c, 0x2b, 0x58, 0x23, 0x80, 0x09, 0x9e, 0x5d, + 0x94, 0x7d, 0x40, 0x76, 0xa9, 0x16, 0x96, 0x9e, + 0x83, 0xe0, 0x0d, 0xec, 0xa0, 0xec, 0x76, 0x2a, + 0xb7, 0xa0, 0xff, 0xb8, 0x50, 0x4c, 0x5b, 0xc6, + 0x8b, 0x0a, 0x65, 0x2e, 0xfe, 0xb4, 0x40, 0x9a, + 0x01, 0xd8, 0xc6, 0xa3, 0xab, 0x99, 0xa2, 0xc5, + 0x0c, 0x08, 0xc4, 0xb7, 0xee, 0x4d, 0x1d, 0xc4, + 0x08, 0x15, 0xd0, 0xdb, 0xaa, 0x63, 0x4f, 0x31, + 0xeb, 0x14, 0x97, 0x43, 0xbd, 0xc1, 0x94, 0x08, + 0xe6, 0xde, 0x43, 0x9f, 0x95, 0x0b, 0x96, 0x7e, + 0x7f, 0x3c, 0x68, 0xba, 0x6f, 0xc4, 0xc9, 0x35, + 0x2b, 0xc4, 0x0e, 0xda, 0x1f, 0x91, 0x68, 0x64, + 0x63, 0x34, 0x73, 0xbe, 0x57, 0x75, 0xb9, 0xed, + 0xf7, 0x2d, 0x3b, 0x05, 0x21, 0x93, 0x28, 0x48, + 0x96, 0x95, 0x97, 0xa0, 0xd2, 0x7d, 0x78, 0xbb, + 0x6a, 0x49, 0x8f, 0x76, 0x55, 0x74, 0x63, 0xb9, + 0xc5, 0x36, 0x12, 0x25, 0xbf, 0x03, 0x82, 0x8f, + 0xf0, 0xf6, 0x80, 0xbb, 0x33, 0xb4, 0xf4, 0x17, + 0x27, 0x1c, 0xf3, 0x4c, 0x10, 0xa3, 0xe4, 0xd1, + 0x55, 0xd9, 0x68, 0x21, 0x4e, 0x5a, 0x83, 0x67, + 0xbf, 0xf8, 0x3c, 0x7d, 0x4e, 0x62, 0xd3, 0x28, + 0xa7, 0x26, 0x6f, 0xe9, 0xee, 0xc2, 0x0b, 0x2d, + 0x03, 0x84, 0xb1, 0xff, 0xd6, 0x68, 0x1f, 0xb6, + 0xf2, 0xe4, 0x0f, 0xda, 0x2d, 0xee, 0x5f, 0x6e, + 0x21, 0xc8, 0xe1, 0xfc, 0xad, 0x6b, 0x0e, 0x04, + 0x7d, 0xaf, 0xc2, 0x3b, 0xa5, 0x68, 0x9b, 0x0c, + 0xf3, 0x56, 0xf3, 0xda, 0x8d, 0xc8, 0x7d, 0x39, + 0xdc, 0xd5, 0x99, 0xc6, 0x01, 0x10, 0xce, 0x42, + 0x1b, 0xac, 0x48, 0xdc, 0x97, 0x78, 0x0a, 0xec, + 0xb3, 0x8f, 0x47, 0x35, 0xa3, 0x6a, 0x64, 0xb2, + 0x8e, 0x63, 0x69, 0x22, 0x66, 0xae, 0x2e, 0xe0, + 0x88, 0xf9, 0x40, 0x3c, 0xc9, 0xa2, 0x57, 0x61, + 0xf6, 0xad, 0xf0, 0xdc, 0x90, 0x56, 0x3f, 0x06, + 0x9b, 0x7d, 0xbd, 0xc2, 0x81, 0x02, 0xab, 0xb8, + 0x15, 0x09, 0x88, 0x4a, 0xff, 0x2f, 0x31, 0xbf, + 0x5e, 0xfa, 0x6a, 0x7e, 0xf6, 0xc5, 0xa7, 0xf7, + 0xd5, 0xab, 0x55, 0xac, 0xae, 0x0d, 0x8c, 0x8d, + 0x7f, 0x4b, 0x25, 0xbb, 0x32, 0xff, 0x11, 0x33, + 0x2e, 0x37, 0x37, 0x69, 0x96, 0x15, 0x17, 0xb1, + 0x17, 0x49, 0xe0, 0x9a, 0x9c, 0xd9, 0x5b, 0x8d, + 0x58, 0xa3, 0x1d, 0x92, 0x87, 0xf8, 0x80, 0xb9, + 0xbd, 0x5a, 0xec, 0x40, 0xe1, 0x00, 0x33, 0x60, + 0xe4, 0x86, 0x16, 0x6d, 0x61, 0x81, 0xf2, 0x28, + 0x6a, 0xa7, 0xce, 0x3f, 0x95, 0xae, 0x43, 0xca, + 0xe1, 0x3f, 0x81, 0x74, 0x7e, 0x1c, 0x47, 0x17, + 0x95, 0xc6, 0x60, 0xda, 0x74, 0x77, 0xd9, 0x9f, + 0xfa, 0x92, 0xb4, 0xbe, 0xe1, 0x23, 0x98, 0x18, + 0x95, 0x63, 0x03, 0x13, 0x4c, 0x1a, 0x2d, 0x41, + 0xcd, 0xe4, 0x84, 0xf7, 0xe6, 0x38, 0xef, 0xff, + 0x95, 0xb2, 0xe8, 0x7c, 0x8f, 0x58, 0xb5, 0xb5, + 0xed, 0x27, 0x7f, 0x3c, 0x18, 0xab, 0xbe, 0x7f, + 0x4f, 0xe2, 0x35, 0x15, 0x71, 0xb7, 0x6f, 0x85, + 0x38, 0x9b, 0x88, 0xf6, 0x9c, 0x8d, 0x43, 0xb5, + 0x58, 0x9e, 0xf2, 0xd1, 0x96, 0xbe, 0xb7, 0xad, + 0x1a, 0xa0, 0x98 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit2", + { + 0x80, 0xd9, 0xa0, 0xdc, 0x21, 0xf9, 0x30, 0x40, + 0x75, 0xfe, 0x49, 0x1b, 0x9e, 0x71, 0x90, 0x91, + 0x78, 0x88, 0x21, 0x60, 0x39, 0xe7, 0xc9, 0x2b, + 0xfb, 0x55, 0x1d, 0xf4, 0xdd, 0x2b, 0x0a, 0x01 + }, + G89_IMIT, + { 0 }, + { + 0x90, 0xf2, 0x11, 0x9a + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 10, + { + 0x1d, 0xeb, 0xe6, 0x79, 0x0a, 0x59, 0x00, 0xe6, + 0x8e, 0x5c + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit3", + { + 0xa9, 0xb6, 0x37, 0xcc, 0x6d, 0x9b, 0x2f, 0x25, + 0xb0, 0xdf, 0x47, 0x04, 0x50, 0x68, 0xb0, 0x27, + 0x41, 0x27, 0x58, 0x6a, 0xbd, 0x0a, 0x6e, 0x50, + 0x2f, 0xc6, 0xfc, 0xc0, 0x3e, 0x29, 0x42, 0xa5 + }, + G89_IMIT, + { 0 }, + { + 0x31, 0x7c, 0x16, 0xe4 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 6, + { + 0xef, 0x06, 0x8f, 0x14, 0xc9, 0x04 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit4", + { + 0xb0, 0x6c, 0x48, 0x23, 0x0a, 0x6e, 0xf4, 0xec, + 0x27, 0x98, 0x01, 0x23, 0xa7, 0xd8, 0xbf, 0x60, + 0x89, 0xef, 0xad, 0xe8, 0x8f, 0x79, 0x14, 0x8c, + 0x18, 0x5c, 0x9a, 0xda, 0xef, 0x0b, 0xdd, 0xa0 + }, + G89_IMIT, + { 0 }, + { + 0xe9, 0x72, 0xae, 0xbf + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 16, + { + 0x02, 0xf8, 0xec, 0x2b, 0x4d, 0x1f, 0xbc, 0x7c, + 0x6e, 0x47, 0xe3, 0x87, 0x22, 0x75, 0x41, 0xa7 + }, + "id-Gost28147-89-CryptoPro-B-ParamSet", + "testimit5", + { + 0x33, 0xd3, 0xef, 0x01, 0x19, 0x95, 0x0e, 0x15, + 0xa1, 0x69, 0x75, 0xae, 0x56, 0x27, 0x17, 0x79, + 0x63, 0x47, 0xab, 0x62, 0x9d, 0x4a, 0xf0, 0x34, + 0xd3, 0x1e, 0x69, 0x74, 0xec, 0x31, 0x48, 0xfc + }, + G89_IMIT, + { 0 }, + { + 0xf5, 0x55, 0x1f, 0x28 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 8, + { + 0xf3, 0xb2, 0x29, 0xd2, 0x7a, 0x37, 0x03, 0x12 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit6", + { + 0x42, 0x35, 0x81, 0x91, 0x0b, 0xa9, 0x99, 0xff, + 0xd9, 0x43, 0xf8, 0xc6, 0x19, 0x55, 0x1f, 0x2f, + 0x2d, 0x45, 0x40, 0x20, 0x1e, 0x1d, 0x32, 0x7a, + 0xb1, 0x07, 0x6b, 0x4f, 0x45, 0x90, 0xd9, 0x80 + }, + G89_IMIT, + { 0 }, + { + 0x6e, 0x15, 0xfa, 0xe8 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 0, + { + 0 + }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "testimit7", + { + 0x26, 0xcb, 0xb9, 0xf0, 0x0c, 0x62, 0x9f, 0xaa, + 0x4a, 0x1d, 0xb6, 0x30, 0x09, 0x01, 0x56, 0x89, + 0x66, 0xd4, 0xe4, 0x0e, 0xfe, 0xf6, 0x10, 0x6b, + 0x6c, 0xe8, 0x04, 0x3a, 0xe3, 0x61, 0x4b, 0x19 + }, + G89_IMIT, + { 0 }, + { + 0x00, 0x00, 0x00, 0x00 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 5242880, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test5Mimit", + { + 0xaa, 0x85, 0x84, 0xcd, 0x65, 0x28, 0xe1, 0xdb, + 0xb8, 0x20, 0x19, 0x43, 0xe0, 0x36, 0x35, 0x10, + 0x19, 0xc3, 0x70, 0x5b, 0x27, 0xc1, 0x9d, 0x84, + 0x75, 0xa3, 0xc6, 0x49, 0x46, 0x8f, 0x7c, 0x4e + }, + G89_IMIT, + { 0 }, + { + 0x2a, 0xe6, 0x23, 0xc6 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + 3221225472U + 16, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test3Gimit1", + { + 0xd5, 0xda, 0xfe, 0x06, 0x60, 0xdc, 0xf0, 0xb3, + 0x49, 0x5a, 0x02, 0x59, 0xc8, 0x2e, 0x4a, 0x2b, + 0xcc, 0x9b, 0x98, 0x04, 0xb7, 0xf2, 0x78, 0xb7, + 0xce, 0xa3, 0xf2, 0xdb, 0x9e, 0xa8, 0x49, 0x1d + }, + G89_IMIT, + { 0 }, + { + 0xcc, 0x46, 0x67, 0xe4 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + U64(4)*1024*1024*1024, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test4Gimit3", + { + 0x0d, 0xf1, 0xa8, 0x7f, 0x57, 0x03, 0x44, 0xcc, + 0xdb, 0x20, 0xde, 0xed, 0x85, 0x50, 0x38, 0xda, + 0xc9, 0x44, 0xec, 0x2c, 0x0d, 0x66, 0xb7, 0xdc, + 0x17, 0x14, 0x55, 0x95, 0x33, 0x6e, 0x43, 0x3e + }, + G89_IMIT, + { 0 }, + { + 0xb7, 0x21, 0x2e, 0x48 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + U64(4)*1024*1024*1024+4, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test4Gimit1", + { + 0x0c, 0xf3, 0xe9, 0xb0, 0x28, 0x3b, 0x9f, 0x8b, + 0xe3, 0x82, 0xb9, 0xa2, 0xa6, 0xbd, 0x80, 0xd2, + 0xcd, 0xfa, 0x3f, 0xf7, 0x90, 0xa7, 0x55, 0x06, + 0x9b, 0x7a, 0x58, 0xee, 0xe7, 0xf1, 0x9d, 0xbe + }, + G89_IMIT, + { 0 }, + { + 0xda, 0x15, 0x10, 0x73 + } + }, + { /* Calculated by libcapi10, CryptoPro CSP 3.6R2, Mac OSX */ + U64(4)*1024*1024*1024+10, + { 0 }, + "id-Gost28147-89-CryptoPro-A-ParamSet", + "test4Gimit2", + { + 0x97, 0x1a, 0x42, 0x22, 0xfa, 0x07, 0xb2, 0xca, + 0xf9, 0xd2, 0x34, 0x5a, 0x92, 0xb1, 0x1f, 0x6b, + 0x53, 0xf8, 0xaf, 0xed, 0x9a, 0x73, 0xc4, 0x38, + 0xd7, 0x7d, 0x25, 0x81, 0x00, 0x0d, 0xd4, 0x29 + }, + G89_IMIT, + { 0 }, + { + 0x52, 0xaa, 0x22, 0xb4 + } + } +}; + +/* const */ unsigned char bZB[40*1024*1024]; +unsigned char bTS[40*1024*1024]; + +int main(int argc, char *argv[]) +{ + unsigned int t; + uint64_t ullMaxLen = 6*1000*1000; + int ignore = 0; + EVP_MD_CTX *mctx = NULL; + EVP_CIPHER_CTX *ectx = NULL; + EVP_PKEY *mac_key; + unsigned char bDerive[EVP_MAX_KEY_LENGTH]; + unsigned char bTest[G89_MAX_TC_LEN]; + unsigned char bTest1[G89_MAX_TC_LEN]; + uint64_t ullLeft; + unsigned int mdl = 0; + int enlu = 0; + int enlf = 0; + size_t siglen; + size_t l = 0; + BIO *bio_err; + const EVP_MD *md_gost94 = NULL; + const EVP_CIPHER *cp_g89ecb = NULL; + const EVP_CIPHER *cp_g89cfb = NULL; + const EVP_CIPHER *cp_g89cnt = NULL; + const EVP_CIPHER *ctype = NULL; + const EVP_MD *md_g89imit = NULL; + int ret = 0; + + printf("Testing GOST 28147-89 "); + + if(1 < argc) { + if(1 != sscanf(argv[1], "%" SCNu64, &ullMaxLen) || + ( 2 < argc ? + 1 != sscanf(argv[2], "%d", &ignore) : 0)) { + fflush(NULL); + fprintf(stderr, "Usage: %s [maxlen [ignore-error]]\n", + argv[0]); + ret = 1; + goto out; + } + } + + ERR_load_crypto_strings(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); +#endif + OPENSSL_load_builtin_modules(); + OpenSSL_add_all_algorithms(); + + memset(bZB, 0, sizeof bZB); + memset(bTS, 0, sizeof bTS); + + /* Test load engine */ + if(NULL == (md_gost94 = EVP_get_digestbyname(SN_id_GostR3411_94))) { + fflush(NULL); + fprintf(stderr, "\"" SN_id_GostR3411_94 "\" - not found\n"); + if(!ignore) { + ret = 7; + goto out; + } + } + if(NULL == (cp_g89cfb = EVP_get_cipherbyname(SN_id_Gost28147_89))) { + fflush(NULL); + fprintf(stderr, "\"" SN_id_Gost28147_89 "\" - not found\n"); + if(!ignore) { + ret = 8; + goto out; + } + } + if(NULL == (cp_g89cnt = EVP_get_cipherbyname(SN_gost89_cnt))) { + fflush(NULL); + fprintf(stderr, "\"" SN_gost89_cnt "\" - not found\n"); + if(!ignore) { + ret = 9; + goto out; + } + } + if(NULL == (cp_g89ecb = EVP_get_cipherbyname(SN_gost89_ecb))) { + fflush(NULL); + fprintf(stderr, "\"" SN_gost89_ecb "\" - not found\n"); + if(!ignore) { + ret = 8; + goto out; + } + } + if(NULL == (md_g89imit = EVP_get_digestbyname(SN_id_Gost28147_89_MAC))) { + fflush(NULL); + fprintf(stderr, "\"" SN_id_Gost28147_89_MAC "\" - not found\n"); + if(!ignore) { + ret = 10; + goto out; + } + } + + /* Test cases */ + for(t = 0; t < sizeof(tcs)/sizeof(tcs[0]); t++) { + if(NULL != tcs[t].szDerive) { + memset(bDerive, 0x3c, sizeof(bDerive)); + mdl = sizeof(bDerive); + if (!EVP_Digest(tcs[t].szDerive, strlen(tcs[t].szDerive), bDerive, + &mdl, md_gost94, NULL)) + goto out; + if(0 != memcmp(tcs[t].bRawKey, bDerive, mdl)) { + fflush(NULL); + fprintf(stderr, "Engine test t=%d " + "derive key error.\n", t); + if(!ignore) { + ret = 12; + goto out; + } + } + } + if(ullMaxLen < tcs[t].ullLen) { + printf("@"); + continue; + } + memset(bTest, 0xa5, sizeof(bTest)); + memset(bTest1, 0x5a, sizeof(bTest1)); + + switch(tcs[t].gMode) { + case G89_ECB: + ctype = cp_g89ecb; + goto engine_cipher_check; + case G89_CFB: + ctype = cp_g89cfb; + goto engine_cipher_check; + case G89_CNT: + ctype = cp_g89cnt; +engine_cipher_check: + if ((ectx = EVP_CIPHER_CTX_new()) == NULL) + goto imit_fail; + if (!EVP_EncryptInit_ex(ectx, ctype, NULL, tcs[t].bRawKey, + tcs[t].bIV)) + goto imit_fail; + if (!EVP_CIPHER_CTX_ctrl(ectx, EVP_CTRL_GOST_SET_SBOX, + OBJ_txt2nid(tcs[t].szParamSet), 0)) + goto imit_fail; + if(G89_MAX_TC_LEN >= tcs[t].ullLen) { + enlu = sizeof(bTest); + if (!EVP_EncryptUpdate(ectx, bTest, &enlu, tcs[t].bIn, + (int)tcs[t].ullLen)) + goto imit_fail; + l = (size_t)tcs[t].ullLen; + } else { + for(ullLeft = tcs[t].ullLen; + ullLeft >= sizeof(bZB); + ullLeft -= sizeof(bZB)) { + printf("B"); + fflush(NULL); + enlu = sizeof(bTS); + if (!EVP_EncryptUpdate(ectx, bTS, &enlu, bZB, + sizeof(bZB))) + goto imit_fail; + } + printf("b%" PRIu64 "/%" PRIu64, ullLeft, tcs[t].ullLen); + fflush(NULL); + if (!EVP_EncryptUpdate(ectx, bTS, &enlu, bZB, (int)ullLeft)) + goto imit_fail; + memcpy(bTest, &bTS[enlu-16], 16); + enlu = (int)tcs[t].ullLen; + l = 16; + } + enlf = sizeof(bTest1); + if (tcs[t].gMode == G89_ECB) + enlf = 0; + else { + if (!EVP_EncryptFinal_ex(ectx, bTest1, &enlf)) + goto imit_fail; + } + EVP_CIPHER_CTX_free(ectx); + ectx = NULL; + break; + case G89_IMIT: + if ((mctx = EVP_MD_CTX_new()) == NULL) + goto imit_fail; + mac_key = EVP_PKEY_new_mac_key( + NID_id_Gost28147_89_MAC, NULL, + bDerive, mdl); + if (mac_key == NULL) + goto imit_fail; + if (!EVP_DigestSignInit(mctx, NULL, md_g89imit, NULL, mac_key)) + goto imit_fail; + if (!EVP_MD_CTX_ctrl(mctx, EVP_MD_CTRL_GOST_SET_SBOX, + OBJ_txt2nid(tcs[t].szParamSet), 0)) + goto imit_fail; + if(G89_MAX_TC_LEN >= tcs[t].ullLen) { + if (!EVP_DigestSignUpdate(mctx, tcs[t].bIn, + (unsigned int)tcs[t].ullLen)) + goto imit_fail; + } else { + for(ullLeft = tcs[t].ullLen; + ullLeft >= sizeof(bZB); + ullLeft -= sizeof(bZB)) { + printf("B"); + fflush(NULL); + if (!EVP_DigestSignUpdate(mctx, bZB, sizeof(bZB))) + goto imit_fail; + } + printf("b%" PRIu64 "/%" PRIu64, ullLeft, tcs[t].ullLen); + fflush(NULL); + if (!EVP_DigestSignUpdate(mctx, bZB, (unsigned int)ullLeft)) + goto imit_fail; + } + siglen = 4; + OPENSSL_assert(EVP_DigestSignFinal(mctx, bTest, &siglen)); + EVP_MD_CTX_free(mctx); + mctx = NULL; + EVP_PKEY_free(mac_key); + enlu = (int)tcs[t].ullLen; + enlf = 0; + l = siglen; + break; + } + if((int)tcs[t].ullLen != enlu || 0 != enlf || + 0 != memcmp(tcs[t].bOut, bTest, l)) { +imit_fail: + fflush(NULL); + fprintf(stderr, "\nEngine test t=%d len=%" PRIu64 + " mode=%d failed.\n", t, tcs[t].ullLen, tcs[t].gMode); + if(!ignore) { + ret = 13; + goto out; + } + } else { + printf("."); + fflush(NULL); + } + } + + printf(" passed\n"); + fflush(NULL); + + out: + + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + ERR_print_errors(bio_err); + (void)BIO_flush(bio_err); + BIO_free(bio_err); + EVP_CIPHER_CTX_free(ectx); + EVP_MD_CTX_free(mctx); + return ret; +} +#endif diff --git a/tests/handshake_table.c b/tests/handshake_table.c new file mode 100644 index 0000000..8ebed9a --- /dev/null +++ b/tests/handshake_table.c @@ -0,0 +1,550 @@ +/* $OpenBSD: handshake_table.c,v 1.18 2022/12/01 13:49:12 tb Exp $ */ +/* + * Copyright (c) 2019 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "tls13_handshake.h" + +#define MAX_FLAGS (UINT8_MAX + 1) + +/* + * From RFC 8446: + * + * Appendix A. State Machine + * + * This appendix provides a summary of the legal state transitions for + * the client and server handshakes. State names (in all capitals, + * e.g., START) have no formal meaning but are provided for ease of + * comprehension. Actions which are taken only in certain circumstances + * are indicated in []. The notation "K_{send,recv} = foo" means "set + * the send/recv key to the given key". + * + * A.1. Client + * + * START <----+ + * Send ClientHello | | Recv HelloRetryRequest + * [K_send = early data] | | + * v | + * / WAIT_SH ----+ + * | | Recv ServerHello + * | | K_recv = handshake + * Can | V + * send | WAIT_EE + * early | | Recv EncryptedExtensions + * data | +--------+--------+ + * | Using | | Using certificate + * | PSK | v + * | | WAIT_CERT_CR + * | | Recv | | Recv CertificateRequest + * | | Certificate | v + * | | | WAIT_CERT + * | | | | Recv Certificate + * | | v v + * | | WAIT_CV + * | | | Recv CertificateVerify + * | +> WAIT_FINISHED <+ + * | | Recv Finished + * \ | [Send EndOfEarlyData] + * | K_send = handshake + * | [Send Certificate [+ CertificateVerify]] + * Can send | Send Finished + * app data --> | K_send = K_recv = application + * after here v + * CONNECTED + * + * Note that with the transitions as shown above, clients may send + * alerts that derive from post-ServerHello messages in the clear or + * with the early data keys. If clients need to send such alerts, they + * SHOULD first rekey to the handshake keys if possible. + * + */ + +struct child { + enum tls13_message_type mt; + uint8_t flag; + uint8_t forced; + uint8_t illegal; +}; + +static struct child stateinfo[][TLS13_NUM_MESSAGE_TYPES] = { + [CLIENT_HELLO] = { + { + .mt = SERVER_HELLO_RETRY_REQUEST, + }, + { + .mt = SERVER_HELLO, + .flag = WITHOUT_HRR, + }, + }, + [SERVER_HELLO_RETRY_REQUEST] = { + { + .mt = CLIENT_HELLO_RETRY, + }, + }, + [CLIENT_HELLO_RETRY] = { + { + .mt = SERVER_HELLO, + }, + }, + [SERVER_HELLO] = { + { + .mt = SERVER_ENCRYPTED_EXTENSIONS, + }, + }, + [SERVER_ENCRYPTED_EXTENSIONS] = { + { + .mt = SERVER_CERTIFICATE_REQUEST, + }, + { .mt = SERVER_CERTIFICATE, + .flag = WITHOUT_CR, + }, + { + .mt = SERVER_FINISHED, + .flag = WITH_PSK, + }, + }, + [SERVER_CERTIFICATE_REQUEST] = { + { + .mt = SERVER_CERTIFICATE, + }, + }, + [SERVER_CERTIFICATE] = { + { + .mt = SERVER_CERTIFICATE_VERIFY, + }, + }, + [SERVER_CERTIFICATE_VERIFY] = { + { + .mt = SERVER_FINISHED, + }, + }, + [SERVER_FINISHED] = { + { + .mt = CLIENT_FINISHED, + .forced = WITHOUT_CR | WITH_PSK, + }, + { + .mt = CLIENT_CERTIFICATE, + .illegal = WITHOUT_CR | WITH_PSK, + }, + }, + [CLIENT_CERTIFICATE] = { + { + .mt = CLIENT_FINISHED, + }, + { + .mt = CLIENT_CERTIFICATE_VERIFY, + .flag = WITH_CCV, + }, + }, + [CLIENT_CERTIFICATE_VERIFY] = { + { + .mt = CLIENT_FINISHED, + }, + }, + [CLIENT_FINISHED] = { + { + .mt = APPLICATION_DATA, + }, + }, + [APPLICATION_DATA] = { + { + .mt = 0, + }, + }, +}; + +const size_t stateinfo_count = sizeof(stateinfo) / sizeof(stateinfo[0]); + +void build_table(enum tls13_message_type + table[MAX_FLAGS][TLS13_NUM_MESSAGE_TYPES], + struct child current, struct child end, + struct child path[], uint8_t flags, unsigned int depth); +size_t count_handshakes(void); +void edge(enum tls13_message_type start, + enum tls13_message_type end, uint8_t flag); +const char *flag2str(uint8_t flag); +void flag_label(uint8_t flag); +void forced_edges(enum tls13_message_type start, + enum tls13_message_type end, uint8_t forced); +int generate_graphics(void); +void fprint_entry(FILE *stream, + enum tls13_message_type path[TLS13_NUM_MESSAGE_TYPES], + uint8_t flags); +void fprint_flags(FILE *stream, uint8_t flags); +const char *mt2str(enum tls13_message_type mt); +void usage(void); +int verify_table(enum tls13_message_type + table[MAX_FLAGS][TLS13_NUM_MESSAGE_TYPES], int print); + +const char * +flag2str(uint8_t flag) +{ + const char *ret; + + if (flag & (flag - 1)) + errx(1, "more than one bit is set"); + + switch (flag) { + case INITIAL: + ret = "INITIAL"; + break; + case NEGOTIATED: + ret = "NEGOTIATED"; + break; + case WITHOUT_CR: + ret = "WITHOUT_CR"; + break; + case WITHOUT_HRR: + ret = "WITHOUT_HRR"; + break; + case WITH_PSK: + ret = "WITH_PSK"; + break; + case WITH_CCV: + ret = "WITH_CCV"; + break; + case WITH_0RTT: + ret = "WITH_0RTT"; + break; + default: + ret = "UNKNOWN"; + } + + return ret; +} + +const char * +mt2str(enum tls13_message_type mt) +{ + const char *ret; + + switch (mt) { + case INVALID: + ret = "INVALID"; + break; + case CLIENT_HELLO: + ret = "CLIENT_HELLO"; + break; + case CLIENT_HELLO_RETRY: + ret = "CLIENT_HELLO_RETRY"; + break; + case CLIENT_END_OF_EARLY_DATA: + ret = "CLIENT_END_OF_EARLY_DATA"; + break; + case CLIENT_CERTIFICATE: + ret = "CLIENT_CERTIFICATE"; + break; + case CLIENT_CERTIFICATE_VERIFY: + ret = "CLIENT_CERTIFICATE_VERIFY"; + break; + case CLIENT_FINISHED: + ret = "CLIENT_FINISHED"; + break; + case SERVER_HELLO: + ret = "SERVER_HELLO"; + break; + case SERVER_HELLO_RETRY_REQUEST: + ret = "SERVER_HELLO_RETRY_REQUEST"; + break; + case SERVER_ENCRYPTED_EXTENSIONS: + ret = "SERVER_ENCRYPTED_EXTENSIONS"; + break; + case SERVER_CERTIFICATE: + ret = "SERVER_CERTIFICATE"; + break; + case SERVER_CERTIFICATE_VERIFY: + ret = "SERVER_CERTIFICATE_VERIFY"; + break; + case SERVER_CERTIFICATE_REQUEST: + ret = "SERVER_CERTIFICATE_REQUEST"; + break; + case SERVER_FINISHED: + ret = "SERVER_FINISHED"; + break; + case APPLICATION_DATA: + ret = "APPLICATION_DATA"; + break; + case TLS13_NUM_MESSAGE_TYPES: + ret = "TLS13_NUM_MESSAGE_TYPES"; + break; + default: + ret = "UNKNOWN"; + break; + } + + return ret; +} + +void +fprint_flags(FILE *stream, uint8_t flags) +{ + int first = 1, i; + + if (flags == 0) { + fprintf(stream, "%s", flag2str(flags)); + return; + } + + for (i = 0; i < 8; i++) { + uint8_t set = flags & (1U << i); + + if (set) { + fprintf(stream, "%s%s", first ? "" : " | ", + flag2str(set)); + first = 0; + } + } +} + +void +fprint_entry(FILE *stream, + enum tls13_message_type path[TLS13_NUM_MESSAGE_TYPES], uint8_t flags) +{ + int i; + + fprintf(stream, "\t["); + fprint_flags(stream, flags); + fprintf(stream, "] = {\n"); + + for (i = 0; i < TLS13_NUM_MESSAGE_TYPES; i++) { + if (path[i] == 0) + break; + fprintf(stream, "\t\t%s,\n", mt2str(path[i])); + } + fprintf(stream, "\t},\n"); +} + +void +edge(enum tls13_message_type start, enum tls13_message_type end, + uint8_t flag) +{ + printf("\t%s -> %s", mt2str(start), mt2str(end)); + flag_label(flag); + printf(";\n"); +} + +void +flag_label(uint8_t flag) +{ + if (flag) + printf(" [label=\"%s\"]", flag2str(flag)); +} + +void +forced_edges(enum tls13_message_type start, enum tls13_message_type end, + uint8_t forced) +{ + uint8_t forced_flag, i; + + if (forced == 0) + return; + + for (i = 0; i < 8; i++) { + forced_flag = forced & (1U << i); + if (forced_flag) + edge(start, end, forced_flag); + } +} + +int +generate_graphics(void) +{ + enum tls13_message_type start, end; + unsigned int child; + uint8_t flag; + uint8_t forced; + + printf("digraph G {\n"); + printf("\t%s [shape=box];\n", mt2str(CLIENT_HELLO)); + printf("\t%s [shape=box];\n", mt2str(APPLICATION_DATA)); + + for (start = CLIENT_HELLO; start < APPLICATION_DATA; start++) { + for (child = 0; stateinfo[start][child].mt != 0; child++) { + end = stateinfo[start][child].mt; + flag = stateinfo[start][child].flag; + forced = stateinfo[start][child].forced; + + if (forced == 0) + edge(start, end, flag); + else + forced_edges(start, end, forced); + } + } + + printf("}\n"); + return 0; +} + +extern enum tls13_message_type handshakes[][TLS13_NUM_MESSAGE_TYPES]; +extern size_t handshake_count; + +size_t +count_handshakes(void) +{ + size_t ret = 0, i; + + for (i = 0; i < handshake_count; i++) { + if (handshakes[i][0] != INVALID) + ret++; + } + + return ret; +} + +void +build_table(enum tls13_message_type table[MAX_FLAGS][TLS13_NUM_MESSAGE_TYPES], + struct child current, struct child end, struct child path[], uint8_t flags, + unsigned int depth) +{ + unsigned int i; + + if (depth >= TLS13_NUM_MESSAGE_TYPES - 1) + errx(1, "recursed too deeply"); + + /* Record current node. */ + path[depth++] = current; + flags |= current.flag; + + /* If we haven't reached the end, recurse over the children. */ + if (current.mt != end.mt) { + for (i = 0; stateinfo[current.mt][i].mt != 0; i++) { + struct child child = stateinfo[current.mt][i]; + int forced = stateinfo[current.mt][i].forced; + int illegal = stateinfo[current.mt][i].illegal; + + if ((forced == 0 || (forced & flags)) && + (illegal == 0 || !(illegal & flags))) + build_table(table, child, end, path, flags, + depth); + } + return; + } + + if (flags == 0) + errx(1, "path does not set flags"); + + if (table[flags][0] != 0) + errx(1, "path traversed twice"); + + for (i = 0; i < depth; i++) + table[flags][i] = path[i].mt; +} + +int +verify_table(enum tls13_message_type table[MAX_FLAGS][TLS13_NUM_MESSAGE_TYPES], + int print) +{ + int success = 1, i; + size_t num_valid, num_found = 0; + uint8_t flags = 0; + + do { + if (table[flags][0] == 0) + continue; + + num_found++; + + for (i = 0; i < TLS13_NUM_MESSAGE_TYPES; i++) { + if (table[flags][i] != handshakes[flags][i]) { + fprintf(stderr, + "incorrect entry %d of handshake ", i); + fprint_flags(stderr, flags); + fprintf(stderr, "\n"); + success = 0; + } + } + + if (print) + fprint_entry(stdout, table[flags], flags); + } while(++flags != 0); + + num_valid = count_handshakes(); + if (num_valid != num_found) { + fprintf(stderr, + "incorrect number of handshakes: want %zu, got %zu.\n", + num_valid, num_found); + success = 0; + } + + return success; +} + +void +usage(void) +{ + fprintf(stderr, "usage: handshake_table [-C | -g]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + static enum tls13_message_type + hs_table[MAX_FLAGS][TLS13_NUM_MESSAGE_TYPES] = { + [INITIAL] = { + CLIENT_HELLO, + SERVER_HELLO_RETRY_REQUEST, + CLIENT_HELLO_RETRY, + SERVER_HELLO, + }, + }; + struct child start = { + .mt = CLIENT_HELLO, + }; + struct child end = { + .mt = APPLICATION_DATA, + }; + struct child path[TLS13_NUM_MESSAGE_TYPES] = {{0}}; + uint8_t flags = NEGOTIATED; + unsigned int depth = 0; + int ch, graphviz = 0, print = 0; + + while ((ch = getopt(argc, argv, "Cg")) != -1) { + switch (ch) { + case 'C': + print = 1; + break; + case 'g': + graphviz = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc != 0) + usage(); + + if (graphviz && print) + usage(); + + if (graphviz) + return generate_graphics(); + + build_table(hs_table, start, end, path, flags, depth); + if (!verify_table(hs_table, print)) + return 1; + + return 0; +} diff --git a/tests/hkdf_test.c b/tests/hkdf_test.c new file mode 100644 index 0000000..5e89f33 --- /dev/null +++ b/tests/hkdf_test.c @@ -0,0 +1,300 @@ +/* $OpenBSD: hkdf_test.c,v 1.2 2018/07/17 17:06:49 tb Exp $ */ +/* Copyright (c) 2014, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include +#include + +#include +#include +#include +#include + +#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) + +typedef struct HKDFTestVector_st { + const EVP_MD *(*md_func)(void); + const uint8_t ikm[80]; + const size_t ikm_len; + const uint8_t salt[80]; + const size_t salt_len; + const uint8_t info[80]; + const size_t info_len; + const uint8_t prk[EVP_MAX_MD_SIZE]; + const size_t prk_len; + const size_t out_len; + const uint8_t out[82]; +} HKDFTestVector; + +/* These test vectors are from RFC 5869. */ +static const HKDFTestVector kTests[] = { + { + EVP_sha256, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, + }, 13, + { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + }, 10, + { + 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, + 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5, + }, 32, + 42, { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, + 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, + 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65 + } + }, + { + EVP_sha256, + { + 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, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, + 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44, + }, 32, + 82, { + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, + 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, + 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, + 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 + } + }, + { + EVP_sha256, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, + 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04 + }, 32, + 42, { + 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, + 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, + 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 11, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, + }, 13, + { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, + }, 10, + { + 0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, + 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43 + }, 20, + 42, { + 0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, + 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, + 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96 + } + }, + { + EVP_sha1, + { + 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, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }, 80, + { + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, + 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, + 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }, 80, + { + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, + 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }, 80, + { + 0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, + 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6, + }, 20, + 82, { + 0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, + 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, + 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, + 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4 + } + }, + { + EVP_sha1, + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, + 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01, + }, 20, + 42, { + 0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, + 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, + 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18 + } + }, + { + EVP_sha1, + { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + }, 22, + { + 0, + }, 0, + { + 0, + }, 0, + { + 0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, + 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd, + }, 20, + 42, { + 0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, + 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, + 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48 + } + }, +}; + +int main(void) { + size_t i; + OPENSSL_add_all_algorithms_noconf(); + + for (i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) { + const HKDFTestVector *test = &kTests[i]; + uint8_t prk[EVP_MAX_MD_SIZE]; + uint8_t buf[82]; + size_t prk_len; + if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, + test->ikm_len, test->salt, test->salt_len)) { + fprintf(stderr, "Call to HKDF_extract failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (prk_len != test->prk_len || + memcmp(prk, test->prk, test->prk_len) != 0) { + fprintf(stderr, "%zu: Resulting PRK does not match" + "test vector\n", i); + return 1; + } + if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len, + test->info, test->info_len)) { + fprintf(stderr, "Call to HKDF_expand failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test" + "vector\n", i); + return 1; + } + + if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, + test->ikm_len, test->salt, test->salt_len, test->info, + test->info_len)) { + fprintf(stderr, "Call to HKDF failed\n"); + ERR_print_errors_fp(stderr); + return 1; + } + if (memcmp(buf, test->out, test->out_len) != 0) { + fprintf(stderr, + "%zu: Resulting key material does not match test" + "vector\n", i); + return 1; + } + } + + printf("PASS\n"); + return 0; +} diff --git a/tests/hmactest.c b/tests/hmactest.c new file mode 100644 index 0000000..f61a177 --- /dev/null +++ b/tests/hmactest.c @@ -0,0 +1,335 @@ +/* $OpenBSD: hmactest.c,v 1.7 2021/11/18 20:11:55 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include +#ifndef OPENSSL_NO_MD5 +#include +#endif + +#ifndef OPENSSL_NO_MD5 +static struct test_st { + unsigned char key[16]; + int key_len; + unsigned char data[64]; + int data_len; + unsigned char *digest; +} test[8] = { + { "", + 0, + "More text test vectors to stuff up EBCDIC machines :-)", + 54, + (unsigned char *)"e9139d1e6ee064ef8cf514fc7dc83e86", + }, + { {0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,}, + 16, + "Hi There", + 8, + (unsigned char *)"9294727a3638bb1c13f48ef8158bfc9d", + }, + { "Jefe", + 4, + "what do ya want for nothing?", + 28, + (unsigned char *)"750c783e6ab0b503eaa86e310a5db738", + }, + { {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,}, + 16, + {0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd, + 0xdd,0xdd}, + 50, + (unsigned char *)"56be34521d144c88dbb8c733f0e8b3f6", + }, + { "", + 0, + "My test data", + 12, + (unsigned char *)"61afdecb95429ef494d61fdee15990cabf0826fc" + }, + { "", + 0, + "My test data", + 12, + (unsigned char *)"2274b195d90ce8e03406f4b526a47e0787a88a65479938f1a5baa3ce0f079776" + }, + { "123456", + 6, + "My test data", + 12, + (unsigned char *)"bab53058ae861a7f191abe2d0145cbb123776a6369ee3f9d79ce455667e411dd" + }, + { "12345", + 5, + "My test data again", + 12, + (unsigned char *)"7dbe8c764c068e3bcd6e6b0fbcd5e6fc197b15bb" + } +}; +#endif + +static char *pt(unsigned char *md, unsigned int len); + +int +main(int argc, char *argv[]) +{ +#ifndef OPENSSL_NO_MD5 + int i; + char *p; +#endif + int err = 0; + HMAC_CTX *ctx = NULL, *ctx2 = NULL; + unsigned char buf[EVP_MAX_MD_SIZE]; + unsigned int len; + +#ifdef OPENSSL_NO_MD5 + printf("test skipped: MD5 disabled\n"); +#else + + for (i = 0; i < 4; i++) { + p = pt(HMAC(EVP_md5(), + test[i].key, test[i].key_len, + test[i].data, test[i].data_len, NULL, NULL), + MD5_DIGEST_LENGTH); + + if (strcmp(p, (char *)test[i].digest) != 0) { + printf("error calculating HMAC on %d entry'\n", i); + printf("got %s instead of %s\n", p, test[i].digest); + err++; + } else + printf("test %d ok\n", i); + } +#endif /* OPENSSL_NO_MD5 */ + +/* test4 */ + if ((ctx = HMAC_CTX_new()) == NULL) { + printf("HMAC_CTX_init failed (test 4)\n"); + exit(1); + } + if (HMAC_Init_ex(ctx, NULL, 0, NULL, NULL)) { + printf("Should fail to initialise HMAC with empty MD and key (test 4)\n"); + err++; + goto test5; + } + if (HMAC_Update(ctx, test[4].data, test[4].data_len)) { + printf("Should fail HMAC_Update with ctx not set up (test 4)\n"); + err++; + goto test5; + } + if (HMAC_Init_ex(ctx, NULL, 0, EVP_sha1(), NULL)) { + printf("Should fail to initialise HMAC with empty key (test 4)\n"); + err++; + goto test5; + } + if (HMAC_Update(ctx, test[4].data, test[4].data_len)) { + printf("Should fail HMAC_Update with ctx not set up (test 4)\n"); + err++; + goto test5; + } + printf("test 4 ok\n"); + test5: + HMAC_CTX_reset(ctx); + if (HMAC_Init_ex(ctx, test[4].key, test[4].key_len, NULL, NULL)) { + printf("Should fail to initialise HMAC with empty MD (test 5)\n"); + err++; + goto test6; + } + if (HMAC_Update(ctx, test[4].data, test[4].data_len)) { + printf("Should fail HMAC_Update with ctx not set up (test 5)\n"); + err++; + goto test6; + } + if (HMAC_Init_ex(ctx, test[4].key, -1, EVP_sha1(), NULL)) { + printf("Should fail to initialise HMAC with invalid key len(test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha1(), NULL)) { + printf("Failed to initialise HMAC (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Update(ctx, test[4].data, test[4].data_len)) { + printf("Error updating HMAC with data (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Final(ctx, buf, &len)) { + printf("Error finalising data (test 5)\n"); + err++; + goto test6; + } + p = pt(buf, len); + if (strcmp(p, (char *)test[4].digest) != 0) { + printf("Error calculating interim HMAC on test 5\n"); + printf("got %s instead of %s\n", p, test[4].digest); + err++; + goto test6; + } + if (HMAC_Init_ex(ctx, NULL, 0, EVP_sha256(), NULL)) { + printf("Should disallow changing MD without a new key (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Init_ex(ctx, test[4].key, test[4].key_len, EVP_sha256(), NULL)) { + printf("Failed to reinitialise HMAC (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Update(ctx, test[5].data, test[5].data_len)) { + printf("Error updating HMAC with data (sha256) (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Final(ctx, buf, &len)) { + printf("Error finalising data (sha256) (test 5)\n"); + err++; + goto test6; + } + p = pt(buf, len); + if (strcmp(p, (char *)test[5].digest) != 0) { + printf("Error calculating 2nd interim HMAC on test 5\n"); + printf("got %s instead of %s\n", p, test[5].digest); + err++; + goto test6; + } + if (!HMAC_Init_ex(ctx, test[6].key, test[6].key_len, NULL, NULL)) { + printf("Failed to reinitialise HMAC with key (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Update(ctx, test[6].data, test[6].data_len)) { + printf("Error updating HMAC with data (new key) (test 5)\n"); + err++; + goto test6; + } + if (!HMAC_Final(ctx, buf, &len)) { + printf("Error finalising data (new key) (test 5)\n"); + err++; + goto test6; + } + p = pt(buf, len); + if (strcmp(p, (char *)test[6].digest) != 0) { + printf("error calculating HMAC on test 5\n"); + printf("got %s instead of %s\n", p, test[6].digest); + err++; + } else { + printf("test 5 ok\n"); + } + test6: + HMAC_CTX_reset(ctx); + if (!HMAC_Init_ex(ctx, test[7].key, test[7].key_len, EVP_sha1(), NULL)) { + printf("Failed to initialise HMAC (test 6)\n"); + err++; + goto end; + } + if (!HMAC_Update(ctx, test[7].data, test[7].data_len)) { + printf("Error updating HMAC with data (test 6)\n"); + err++; + goto end; + } + if ((ctx2 = HMAC_CTX_new()) == NULL) { + printf("HMAC_CTX_new failed (test 6)\n"); + exit(1); + } + if (!HMAC_CTX_copy(ctx2, ctx)) { + printf("Failed to copy HMAC_CTX (test 6)\n"); + err++; + goto end; + } + if (!HMAC_Final(ctx2, buf, &len)) { + printf("Error finalising data (test 6)\n"); + err++; + goto end; + } + p = pt(buf, len); + if (strcmp(p, (char *)test[7].digest) != 0) { + printf("Error calculating HMAC on test 6\n"); + printf("got %s instead of %s\n", p, test[7].digest); + err++; + } else { + printf("test 6 ok\n"); + } +end: + HMAC_CTX_free(ctx); + HMAC_CTX_free(ctx2); + exit(err); + return(0); +} + +#ifndef OPENSSL_NO_MD5 +static char * +pt(unsigned char *md, unsigned int len) +{ + unsigned int i; + static char buf[80]; + + for (i = 0; i < len; i++) + snprintf(buf + i * 2, sizeof(buf) - i * 2, "%02x", md[i]); + return(buf); +} +#endif diff --git a/tests/ideatest.c b/tests/ideatest.c new file mode 100644 index 0000000..b33b824 --- /dev/null +++ b/tests/ideatest.c @@ -0,0 +1,221 @@ +/* $OpenBSD: ideatest.c,v 1.2 2018/07/17 17:06:49 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include +#include + +#include + +unsigned char k[16]={ + 0x00,0x01,0x00,0x02,0x00,0x03,0x00,0x04, + 0x00,0x05,0x00,0x06,0x00,0x07,0x00,0x08}; + +unsigned char in[8]={0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x03}; +unsigned char c[8]={0x11,0xFB,0xED,0x2B,0x01,0x98,0x6D,0xE5}; +unsigned char out[80]; + +char *text="Hello to all people out there"; + +static unsigned char cfb_key[16]={ + 0xe1,0xf0,0xc3,0xd2,0xa5,0xb4,0x87,0x96, + 0x69,0x78,0x4b,0x5a,0x2d,0x3c,0x0f,0x1e, + }; +static unsigned char cfb_iv[80]={0x34,0x12,0x78,0x56,0xab,0x90,0xef,0xcd}; +static unsigned char cfb_buf1[40],cfb_buf2[40],cfb_tmp[8]; +#define CFB_TEST_SIZE 24 +static unsigned char plain[CFB_TEST_SIZE]= + { + 0x4e,0x6f,0x77,0x20,0x69,0x73, + 0x20,0x74,0x68,0x65,0x20,0x74, + 0x69,0x6d,0x65,0x20,0x66,0x6f, + 0x72,0x20,0x61,0x6c,0x6c,0x20 + }; +static unsigned char cfb_cipher64[CFB_TEST_SIZE]={ + 0x59,0xD8,0xE2,0x65,0x00,0x58,0x6C,0x3F, + 0x2C,0x17,0x25,0xD0,0x1A,0x38,0xB7,0x2A, + 0x39,0x61,0x37,0xDC,0x79,0xFB,0x9F,0x45 + +/* 0xF9,0x78,0x32,0xB5,0x42,0x1A,0x6B,0x38, + 0x9A,0x44,0xD6,0x04,0x19,0x43,0xC4,0xD9, + 0x3D,0x1E,0xAE,0x47,0xFC,0xCF,0x29,0x0B,*/ + }; + +static int cfb64_test(unsigned char *cfb_cipher); +static char *pt(unsigned char *p); +int main(int argc, char *argv[]) + { + int i,err=0; + IDEA_KEY_SCHEDULE key,dkey; + unsigned char iv[8]; + + idea_set_encrypt_key(k,&key); + idea_ecb_encrypt(in,out,&key); + if (memcmp(out,c,8) != 0) + { + printf("ecb idea error encrypting\n"); + printf("got :"); + for (i=0; i<8; i++) + printf("%02X ",out[i]); + printf("\n"); + printf("expected:"); + for (i=0; i<8; i++) + printf("%02X ",c[i]); + err=20; + printf("\n"); + } + + idea_set_decrypt_key(&key,&dkey); + idea_ecb_encrypt(c,out,&dkey); + if (memcmp(out,in,8) != 0) + { + printf("ecb idea error decrypting\n"); + printf("got :"); + for (i=0; i<8; i++) + printf("%02X ",out[i]); + printf("\n"); + printf("expected:"); + for (i=0; i<8; i++) + printf("%02X ",in[i]); + printf("\n"); + err=3; + } + + if (err == 0) printf("ecb idea ok\n"); + + memcpy(iv,k,8); + idea_cbc_encrypt((unsigned char *)text,out,strlen(text)+1,&key,iv,1); + memcpy(iv,k,8); + idea_cbc_encrypt(out,out,8,&dkey,iv,0); + idea_cbc_encrypt(&(out[8]),&(out[8]),strlen(text)+1-8,&dkey,iv,0); + if (memcmp(text,out,strlen(text)+1) != 0) + { + printf("cbc idea bad\n"); + err=4; + } + else + printf("cbc idea ok\n"); + + printf("cfb64 idea "); + if (cfb64_test(cfb_cipher64)) + { + printf("bad\n"); + err=5; + } + else + printf("ok\n"); + + exit(err); + } + +static int cfb64_test(unsigned char *cfb_cipher) + { + IDEA_KEY_SCHEDULE eks,dks; + int err=0,i,n; + + idea_set_encrypt_key(cfb_key,&eks); + idea_set_decrypt_key(&eks,&dks); + memcpy(cfb_tmp,cfb_iv,8); + n=0; + idea_cfb64_encrypt(plain,cfb_buf1,(long)12,&eks, + cfb_tmp,&n,IDEA_ENCRYPT); + idea_cfb64_encrypt(&(plain[12]),&(cfb_buf1[12]), + (long)CFB_TEST_SIZE-12,&eks, + cfb_tmp,&n,IDEA_ENCRYPT); + if (memcmp(cfb_cipher,cfb_buf1,CFB_TEST_SIZE) != 0) + { + err=1; + printf("idea_cfb64_encrypt encrypt error\n"); + for (i=0; i>4)&0xf]; + ret[i*2+1]=f[p[i]&0xf]; + } + ret[16]='\0'; + return(ret); + } diff --git a/tests/igetest.c b/tests/igetest.c new file mode 100644 index 0000000..2191af8 --- /dev/null +++ b/tests/igetest.c @@ -0,0 +1,370 @@ +/* $OpenBSD: igetest.c,v 1.4 2018/07/17 17:06:49 tb Exp $ */ +/* ==================================================================== + * Copyright (c) 2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#include +#include +#include +#include + +#include + +#define TEST_SIZE 128 +#define BIG_TEST_SIZE 10240 + +static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) + { + int n=0; + + fprintf(f,"%s",title); + for( ; n < l ; ++n) + { + if((n%16) == 0) + fprintf(f,"\n%04x",n); + fprintf(f," %02x",s[n]); + } + fprintf(f,"\n"); + } + +#define MAX_VECTOR_SIZE 64 + +struct ige_test + { + const unsigned char key[16]; + const unsigned char iv[32]; + const unsigned char in[MAX_VECTOR_SIZE]; + const unsigned char out[MAX_VECTOR_SIZE]; + const size_t length; + const int encrypt; + }; + +static struct ige_test const ige_test_vectors[] = { +{ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key */ + { 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 }, /* iv */ + { 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 }, /* in */ + { 0x1a, 0x85, 0x19, 0xa6, 0x55, 0x7b, 0xe6, 0x52, + 0xe9, 0xda, 0x8e, 0x43, 0xda, 0x4e, 0xf4, 0x45, + 0x3c, 0xf4, 0x56, 0xb4, 0xca, 0x48, 0x8a, 0xa3, + 0x83, 0xc7, 0x9c, 0x98, 0xb3, 0x47, 0x97, 0xcb }, /* out */ + 32, AES_ENCRYPT }, /* test vector 0 */ + +{ { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65 }, /* key */ + { 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x47, 0x45, + 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f, + 0x72, 0x20, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53 }, /* iv */ + { 0x4c, 0x2e, 0x20, 0x4c, 0x65, 0x74, 0x27, 0x73, + 0x20, 0x68, 0x6f, 0x70, 0x65, 0x20, 0x42, 0x65, + 0x6e, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x69, 0x74, + 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x21, 0x0a }, /* in */ + { 0x99, 0x70, 0x64, 0x87, 0xa1, 0xcd, 0xe6, 0x13, + 0xbc, 0x6d, 0xe0, 0xb6, 0xf2, 0x4b, 0x1c, 0x7a, + 0xa4, 0x48, 0xc8, 0xb9, 0xc3, 0x40, 0x3e, 0x34, + 0x67, 0xa8, 0xca, 0xd8, 0x93, 0x40, 0xf5, 0x3b }, /* out */ + 32, AES_DECRYPT }, /* test vector 1 */ +}; + +static int run_test_vectors(void) + { + unsigned int n; + int errs = 0; + + for(n=0 ; n < sizeof(ige_test_vectors)/sizeof(ige_test_vectors[0]) ; ++n) + { + const struct ige_test * const v = &ige_test_vectors[n]; + AES_KEY key; + unsigned char buf[MAX_VECTOR_SIZE]; + unsigned char iv[AES_BLOCK_SIZE*2]; + + assert(v->length <= MAX_VECTOR_SIZE); + + if(v->encrypt == AES_ENCRYPT) + AES_set_encrypt_key(v->key, 8*sizeof v->key, &key); + else + AES_set_decrypt_key(v->key, 8*sizeof v->key, &key); + memcpy(iv, v->iv, sizeof iv); + AES_ige_encrypt(v->in, buf, v->length, &key, iv, v->encrypt); + + if(memcmp(v->out, buf, v->length)) + { + printf("IGE test vector %d failed\n", n); + hexdump(stdout, "key", v->key, sizeof v->key); + hexdump(stdout, "iv", v->iv, sizeof v->iv); + hexdump(stdout, "in", v->in, v->length); + hexdump(stdout, "expected", v->out, v->length); + hexdump(stdout, "got", buf, v->length); + + ++errs; + } + + /* try with in == out */ + memcpy(iv, v->iv, sizeof iv); + memcpy(buf, v->in, v->length); + AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt); + + if(memcmp(v->out, buf, v->length)) + { + printf("IGE test vector %d failed (with in == out)\n", n); + hexdump(stdout, "key", v->key, sizeof v->key); + hexdump(stdout, "iv", v->iv, sizeof v->iv); + hexdump(stdout, "in", v->in, v->length); + hexdump(stdout, "expected", v->out, v->length); + hexdump(stdout, "got", buf, v->length); + + ++errs; + } + } + + return errs; + } + +int main(int argc, char **argv) + { + unsigned char rkey[16]; + unsigned char rkey2[16]; + AES_KEY key; + AES_KEY key2; + unsigned char plaintext[BIG_TEST_SIZE]; + unsigned char ciphertext[BIG_TEST_SIZE]; + unsigned char checktext[BIG_TEST_SIZE]; + unsigned char iv[AES_BLOCK_SIZE*4]; + unsigned char saved_iv[AES_BLOCK_SIZE*4]; + int err = 0; + unsigned int n; + unsigned matches; + + assert(BIG_TEST_SIZE >= TEST_SIZE); + + arc4random_buf(rkey, sizeof(rkey)); + arc4random_buf(plaintext, sizeof(plaintext)); + arc4random_buf(iv, sizeof(iv)); + memcpy(saved_iv, iv, sizeof(saved_iv)); + + /* Forward IGE only... */ + + /* Straight encrypt/decrypt */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, iv, + AES_ENCRYPT); + + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, + AES_DECRYPT); + + if(memcmp(checktext, plaintext, TEST_SIZE)) + { + printf("Encrypt+decrypt doesn't match\n"); + hexdump(stdout, "Plaintext", plaintext, TEST_SIZE); + hexdump(stdout, "Checktext", checktext, TEST_SIZE); + ++err; + } + + /* Now check encrypt chaining works */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv, + AES_ENCRYPT); + AES_ige_encrypt(plaintext+TEST_SIZE/2, + ciphertext+TEST_SIZE/2, TEST_SIZE/2, + &key, iv, AES_ENCRYPT); + + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, + AES_DECRYPT); + + if(memcmp(checktext, plaintext, TEST_SIZE)) + { + printf("Chained encrypt+decrypt doesn't match\n"); + hexdump(stdout, "Plaintext", plaintext, TEST_SIZE); + hexdump(stdout, "Checktext", checktext, TEST_SIZE); + ++err; + } + + /* And check decrypt chaining */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv, + AES_ENCRYPT); + AES_ige_encrypt(plaintext+TEST_SIZE/2, + ciphertext+TEST_SIZE/2, TEST_SIZE/2, + &key, iv, AES_ENCRYPT); + + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(ciphertext, checktext, TEST_SIZE/2, &key, iv, + AES_DECRYPT); + AES_ige_encrypt(ciphertext+TEST_SIZE/2, + checktext+TEST_SIZE/2, TEST_SIZE/2, &key, iv, + AES_DECRYPT); + + if(memcmp(checktext, plaintext, TEST_SIZE)) + { + printf("Chained encrypt+chained decrypt doesn't match\n"); + hexdump(stdout, "Plaintext", plaintext, TEST_SIZE); + hexdump(stdout, "Checktext", checktext, TEST_SIZE); + ++err; + } + + /* make sure garble extends forwards only */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv, + AES_ENCRYPT); + + /* corrupt halfway through */ + ++ciphertext[sizeof ciphertext/2]; + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + memcpy(iv, saved_iv, sizeof iv); + AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv, + AES_DECRYPT); + + matches=0; + for(n=0 ; n < sizeof checktext ; ++n) + if(checktext[n] == plaintext[n]) + ++matches; + + if(matches > sizeof checktext/2+sizeof checktext/100) + { + printf("More than 51%% matches after garbling\n"); + ++err; + } + + if(matches < sizeof checktext/2) + { + printf("Garble extends backwards!\n"); + ++err; + } + + /* make sure garble extends both ways */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv, + AES_ENCRYPT); + + /* corrupt halfway through */ + ++ciphertext[sizeof ciphertext/2]; + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv, + AES_DECRYPT); + + matches=0; + for(n=0 ; n < sizeof checktext ; ++n) + if(checktext[n] == plaintext[n]) + ++matches; + + if(matches > sizeof checktext/100) + { + printf("More than 1%% matches after bidirectional garbling\n"); + ++err; + } + + /* make sure garble extends both ways (2) */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv, + AES_ENCRYPT); + + /* corrupt right at the end */ + ++ciphertext[sizeof ciphertext-1]; + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv, + AES_DECRYPT); + + matches=0; + for(n=0 ; n < sizeof checktext ; ++n) + if(checktext[n] == plaintext[n]) + ++matches; + + if(matches > sizeof checktext/100) + { + printf("More than 1%% matches after bidirectional garbling (2)\n"); + ++err; + } + + /* make sure garble extends both ways (3) */ + AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv, + AES_ENCRYPT); + + /* corrupt right at the start */ + ++ciphertext[0]; + AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); + AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2); + AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv, + AES_DECRYPT); + + matches=0; + for(n=0 ; n < sizeof checktext ; ++n) + if(checktext[n] == plaintext[n]) + ++matches; + + if(matches > sizeof checktext/100) + { + printf("More than 1%% matches after bidirectional garbling (3)\n"); + ++err; + } + + err += run_test_vectors(); + + return err; + } diff --git a/tests/init_pledge.c b/tests/init_pledge.c new file mode 100644 index 0000000..76f5668 --- /dev/null +++ b/tests/init_pledge.c @@ -0,0 +1,34 @@ +/* $OpenBSD: init_pledge.c,v 1.1 2018/03/19 14:34:33 beck Exp $ */ + +/* + * Copyright (c) 2018 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + + +int +main (int argc, char *argv[]) +{ + pledge("stdio", NULL); + + ERR_load_ERR_strings(); + printf("[SUCCESS] - crypto autoinit is pledge(\"stdio\") safe\n"); + + exit(0); +} diff --git a/tests/key_schedule.c b/tests/key_schedule.c new file mode 100644 index 0000000..f937d04 --- /dev/null +++ b/tests/key_schedule.c @@ -0,0 +1,317 @@ +/* $OpenBSD: key_schedule.c,v 1.10 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2018-2019 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" + +#include "bytestring.h" +#include "ssl_tlsext.h" +#include "tls13_internal.h" + +static int failures = 0; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static void +compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect, + size_t expect_len) +{ + fprintf(stderr, "received:\n"); + hexdump(recv, recv_len); + + fprintf(stderr, "test data:\n"); + hexdump(expect, expect_len); +} + +#define FAIL(msg, ...) \ +do { \ + fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \ + fprintf(stderr, msg, ##__VA_ARGS__); \ + failures++; \ +} while(0) + +/* Hashes and secrets from test vector */ + +uint8_t chello[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 +}; +const struct tls13_secret chello_hash = { + .data = chello, + .len = 32, +}; + +uint8_t cshello [] = { + 0x86, 0x0c, 0x06, 0xed, 0xc0, 0x78, 0x58, 0xee, + 0x8e, 0x78, 0xf0, 0xe7, 0x42, 0x8c, 0x58, 0xed, + 0xd6, 0xb4, 0x3f, 0x2c, 0xa3, 0xe6, 0xe9, 0x5f, + 0x02, 0xed, 0x06, 0x3c, 0xf0, 0xe1, 0xca, 0xd8 +}; + +const struct tls13_secret cshello_hash = { + .data = cshello, + .len = 32, +}; + +const uint8_t ecdhe [] = { + 0x8b, 0xd4, 0x05, 0x4f, 0xb5, 0x5b, 0x9d, 0x63, + 0xfd, 0xfb, 0xac, 0xf9, 0xf0, 0x4b, 0x9f, 0x0d, + 0x35, 0xe6, 0xd6, 0x3f, 0x53, 0x75, 0x63, 0xef, + 0xd4, 0x62, 0x72, 0x90, 0x0f, 0x89, 0x49, 0x2d +}; + +uint8_t csfhello [] = { + 0x96, 0x08, 0x10, 0x2a, 0x0f, 0x1c, 0xcc, 0x6d, + 0xb6, 0x25, 0x0b, 0x7b, 0x7e, 0x41, 0x7b, 0x1a, + 0x00, 0x0e, 0xaa, 0xda, 0x3d, 0xaa, 0xe4, 0x77, + 0x7a, 0x76, 0x86, 0xc9, 0xff, 0x83, 0xdf, 0x13 +}; + +const struct tls13_secret csfhello_hash = { + .data = csfhello, + .len = 32, +}; + + +/* Expected Values */ + +uint8_t expected_extracted_early[] = { + 0x33, 0xad, 0x0a, 0x1c, 0x60, 0x7e, 0xc0, 0x3b, + 0x09, 0xe6, 0xcd, 0x98, 0x93, 0x68, 0x0c, 0xe2, + 0x10, 0xad, 0xf3, 0x00, 0xaa, 0x1f, 0x26, 0x60, + 0xe1, 0xb2, 0x2e, 0x10, 0xf1, 0x70, 0xf9, 0x2a +}; +uint8_t expected_derived_early[] = { + 0x6f, 0x26, 0x15, 0xa1, 0x08, 0xc7, 0x02, 0xc5, + 0x67, 0x8f, 0x54, 0xfc, 0x9d, 0xba, 0xb6, 0x97, + 0x16, 0xc0, 0x76, 0x18, 0x9c, 0x48, 0x25, 0x0c, + 0xeb, 0xea, 0xc3, 0x57, 0x6c, 0x36, 0x11, 0xba +}; +uint8_t expected_extracted_handshake[] = { + 0x1d, 0xc8, 0x26, 0xe9, 0x36, 0x06, 0xaa, 0x6f, + 0xdc, 0x0a, 0xad, 0xc1, 0x2f, 0x74, 0x1b, 0x01, + 0x04, 0x6a, 0xa6, 0xb9, 0x9f, 0x69, 0x1e, 0xd2, + 0x21, 0xa9, 0xf0, 0xca, 0x04, 0x3f, 0xbe, 0xac +}; +uint8_t expected_client_handshake_traffic[] = { + 0xb3, 0xed, 0xdb, 0x12, 0x6e, 0x06, 0x7f, 0x35, + 0xa7, 0x80, 0xb3, 0xab, 0xf4, 0x5e, 0x2d, 0x8f, + 0x3b, 0x1a, 0x95, 0x07, 0x38, 0xf5, 0x2e, 0x96, + 0x00, 0x74, 0x6a, 0x0e, 0x27, 0xa5, 0x5a, 0x21 +}; + +uint8_t expected_server_handshake_traffic[] = { + 0xb6, 0x7b, 0x7d, 0x69, 0x0c, 0xc1, 0x6c, 0x4e, + 0x75, 0xe5, 0x42, 0x13, 0xcb, 0x2d, 0x37, 0xb4, + 0xe9, 0xc9, 0x12, 0xbc, 0xde, 0xd9, 0x10, 0x5d, + 0x42, 0xbe, 0xfd, 0x59, 0xd3, 0x91, 0xad, 0x38 +}; + +uint8_t expected_derived_handshake[] = { + 0x43, 0xde, 0x77, 0xe0, 0xc7, 0x77, 0x13, 0x85, + 0x9a, 0x94, 0x4d, 0xb9, 0xdb, 0x25, 0x90, 0xb5, + 0x31, 0x90, 0xa6, 0x5b, 0x3e, 0xe2, 0xe4, 0xf1, + 0x2d, 0xd7, 0xa0, 0xbb, 0x7c, 0xe2, 0x54, 0xb4 +}; + +uint8_t expected_extracted_master[] = { + 0x18, 0xdf, 0x06, 0x84, 0x3d, 0x13, 0xa0, 0x8b, + 0xf2, 0xa4, 0x49, 0x84, 0x4c, 0x5f, 0x8a, 0x47, + 0x80, 0x01, 0xbc, 0x4d, 0x4c, 0x62, 0x79, 0x84, + 0xd5, 0xa4, 0x1d, 0xa8, 0xd0, 0x40, 0x29, 0x19 +}; + +uint8_t expected_server_application_traffic[] = { + 0xa1, 0x1a, 0xf9, 0xf0, 0x55, 0x31, 0xf8, 0x56, + 0xad, 0x47, 0x11, 0x6b, 0x45, 0xa9, 0x50, 0x32, + 0x82, 0x04, 0xb4, 0xf4, 0x4b, 0xfb, 0x6b, 0x3a, + 0x4b, 0x4f, 0x1f, 0x3f, 0xcb, 0x63, 0x16, 0x43 +}; + +uint8_t expected_server_application_traffic_updated[] = { + 0x51, 0x92, 0x1b, 0x8a, 0xa3, 0x00, 0x19, 0x76, + 0xeb, 0x40, 0x1d, 0x0a, 0x43, 0x19, 0xa8, 0x51, + 0x64, 0x16, 0xa6, 0xc5, 0x60, 0x01, 0xa3, 0x57, + 0xe5, 0xd1, 0x62, 0x03, 0x1e, 0x84, 0xf9, 0x16, +}; + +uint8_t expected_client_application_traffic[] = { + 0x9e, 0x40, 0x64, 0x6c, 0xe7, 0x9a, 0x7f, 0x9d, + 0xc0, 0x5a, 0xf8, 0x88, 0x9b, 0xce, 0x65, 0x52, + 0x87, 0x5a, 0xfa, 0x0b, 0x06, 0xdf, 0x00, 0x87, + 0xf7, 0x92, 0xeb, 0xb7, 0xc1, 0x75, 0x04, 0xa5, +}; + +uint8_t expected_client_application_traffic_updated[] = { + 0xfc, 0xdf, 0xcc, 0x72, 0x72, 0x5a, 0xae, 0xe4, + 0x8b, 0xf6, 0x4e, 0x4f, 0xd8, 0xb7, 0x49, 0xcd, + 0xbd, 0xba, 0xb3, 0x9d, 0x90, 0xda, 0x0b, 0x26, + 0xe2, 0x24, 0x5c, 0xa6, 0xea, 0x16, 0x72, 0x07, +}; + +uint8_t expected_exporter_master[] = { + 0xfe, 0x22, 0xf8, 0x81, 0x17, 0x6e, 0xda, 0x18, + 0xeb, 0x8f, 0x44, 0x52, 0x9e, 0x67, 0x92, 0xc5, + 0x0c, 0x9a, 0x3f, 0x89, 0x45, 0x2f, 0x68, 0xd8, + 0xae, 0x31, 0x1b, 0x43, 0x09, 0xd3, 0xcf, 0x50 +}; + +int +main (int argc, char **argv) +{ + struct tls13_secrets *secrets; + + if ((secrets = tls13_secrets_create(EVP_sha256(), 0)) == NULL) + errx(1,"failed to create secrets\n"); + + secrets->insecure = 1; /* don't explicit_bzero when done */ + + if (tls13_derive_handshake_secrets(secrets, ecdhe, 32, &cshello_hash)) + FAIL("derive_handshake_secrets worked when it shouldn't\n"); + if (tls13_derive_application_secrets(secrets, + &chello_hash)) + FAIL("derive_application_secrets worked when it shouldn't\n"); + + if (!tls13_derive_early_secrets(secrets, + secrets->zeros.data, secrets->zeros.len, &chello_hash)) + FAIL("derive_early_secrets failed\n"); + if (tls13_derive_early_secrets(secrets, + secrets->zeros.data, secrets->zeros.len, &chello_hash)) + FAIL("derive_early_secrets worked when it shouldn't(2)\n"); + + if (!tls13_derive_handshake_secrets(secrets, ecdhe, 32, &cshello_hash)) + FAIL("derive_handshake_secrets failed\n"); + if (tls13_derive_handshake_secrets(secrets, ecdhe, 32, &cshello_hash)) + FAIL("derive_handshake_secrets worked when it shouldn't(2)\n"); + + /* XXX fix hash here once test vector sorted */ + if (!tls13_derive_application_secrets(secrets, &csfhello_hash)) + FAIL("derive_application_secrets failed\n"); + if (tls13_derive_application_secrets(secrets, &csfhello_hash)) + FAIL("derive_application_secrets worked when it " + "shouldn't(2)\n"); + + fprintf(stderr, "extracted_early:\n"); + compare_data(secrets->extracted_early.data, 32, + expected_extracted_early, 32); + if (memcmp(secrets->extracted_early.data, + expected_extracted_early, 32) != 0) + FAIL("extracted_early does not match\n"); + + fprintf(stderr, "derived_early:\n"); + compare_data(secrets->derived_early.data, 32, + expected_derived_early, 32); + if (memcmp(secrets->derived_early.data, + expected_derived_early, 32) != 0) + FAIL("derived_early does not match\n"); + + fprintf(stderr, "extracted_handshake:\n"); + compare_data(secrets->extracted_handshake.data, 32, + expected_extracted_handshake, 32); + if (memcmp(secrets->extracted_handshake.data, + expected_extracted_handshake, 32) != 0) + FAIL("extracted_handshake does not match\n"); + + fprintf(stderr, "client_handshake_traffic:\n"); + compare_data(secrets->client_handshake_traffic.data, 32, + expected_client_handshake_traffic, 32); + if (memcmp(secrets->client_handshake_traffic.data, + expected_client_handshake_traffic, 32) != 0) + FAIL("client_handshake_traffic does not match\n"); + + fprintf(stderr, "server_handshake_traffic:\n"); + compare_data(secrets->server_handshake_traffic.data, 32, + expected_server_handshake_traffic, 32); + if (memcmp(secrets->server_handshake_traffic.data, + expected_server_handshake_traffic, 32) != 0) + FAIL("server_handshake_traffic does not match\n"); + + fprintf(stderr, "derived_early:\n"); + compare_data(secrets->derived_early.data, 32, + expected_derived_early, 32); + if (memcmp(secrets->derived_early.data, + expected_derived_early, 32) != 0) + FAIL("derived_early does not match\n"); + + fprintf(stderr, "derived_handshake:\n"); + compare_data(secrets->derived_handshake.data, 32, + expected_derived_handshake, 32); + if (memcmp(secrets->derived_handshake.data, + expected_derived_handshake, 32) != 0) + FAIL("derived_handshake does not match\n"); + + fprintf(stderr, "extracted_master:\n"); + compare_data(secrets->extracted_master.data, 32, + expected_extracted_master, 32); + if (memcmp(secrets->extracted_master.data, + expected_extracted_master, 32) != 0) + FAIL("extracted_master does not match\n"); + + fprintf(stderr, "server_application_traffic:\n"); + compare_data(secrets->server_application_traffic.data, 32, + expected_server_application_traffic, 32); + if (memcmp(secrets->server_application_traffic.data, + expected_server_application_traffic, 32) != 0) + FAIL("server_application_traffic does not match\n"); + + fprintf(stderr, "client_application_traffic:\n"); + compare_data(secrets->client_application_traffic.data, 32, + expected_client_application_traffic, 32); + if (memcmp(secrets->client_application_traffic.data, + expected_client_application_traffic, 32) != 0) + FAIL("server_application_traffic does not match\n"); + + fprintf(stderr, "exporter_master:\n"); + compare_data(secrets->exporter_master.data, 32, + expected_exporter_master, 32); + if (memcmp(secrets->exporter_master.data, + expected_exporter_master, 32) != 0) + FAIL("exporter_master does not match\n"); + + tls13_update_server_traffic_secret(secrets); + fprintf(stderr, "server_application_traffic after update:\n"); + compare_data(secrets->server_application_traffic.data, 32, + expected_server_application_traffic_updated, 32); + if (memcmp(secrets->server_application_traffic.data, + expected_server_application_traffic_updated, 32) != 0) + FAIL("server_application_traffic does not match after update\n"); + + + tls13_update_client_traffic_secret(secrets); + fprintf(stderr, "client_application_traffic after update:\n"); + compare_data(secrets->client_application_traffic.data, 32, + expected_client_application_traffic_updated, 32); + if (memcmp(secrets->client_application_traffic.data, + expected_client_application_traffic_updated, 32) != 0) + FAIL("client_application_traffic does not match after update\n"); + + tls13_secrets_destroy(secrets); + + return failures; +} diff --git a/tests/keypairtest.c b/tests/keypairtest.c new file mode 100644 index 0000000..31bf7d6 --- /dev/null +++ b/tests/keypairtest.c @@ -0,0 +1,211 @@ +/* $OpenBSD: keypairtest.c,v 1.6 2022/02/08 18:05:57 tb Exp $ */ +/* + * Copyright (c) 2018 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define PUBKEY_HASH \ + "SHA256:858d0f94beb0a08eb4f13871ba57bf0a2e081287d0efbaeb3bbac59dd8f1a8e5" + +char *cert_file, *key_file, *ocsp_staple_file; + +static void +load_file(const char *filename, const uint8_t **data, size_t *data_len) +{ + struct stat sb; + uint8_t *buf; + size_t len; + ssize_t n; + int fd; + + if ((fd = open(filename, O_RDONLY)) == -1) + err(1, "failed to open '%s'", filename); + if ((fstat(fd, &sb)) == -1) + err(1, "failed to stat '%s'", filename); + if (sb.st_size < 0) + err(1, "file size invalid for '%s'", filename); + len = (size_t)sb.st_size; + if ((buf = malloc(len)) == NULL) + err(1, "out of memory"); + n = read(fd, buf, len); + if (n < 0 || (size_t)n != len) + err(1, "failed to read '%s'", filename); + close(fd); + + *data = buf; + *data_len = len; +} + +static int +compare_mem(char *label, const uint8_t *data1, size_t data1_len, + const uint8_t *data2, size_t data2_len) +{ + if (data1_len != data2_len) { + fprintf(stderr, "FAIL: %s length mismatch (%zu != %zu)\n", + label, data1_len, data2_len); + return -1; + } + if (data1 == data2) { + fprintf(stderr, "FAIL: %s comparing same memory (%p == %p)\n", + label, data1, data2); + return -1; + } + if (memcmp(data1, data2, data1_len) != 0) { + fprintf(stderr, "FAIL: %s data mismatch\n", label); + return -1; + } + return 0; +} + +static int +do_keypair_tests(void) +{ + size_t cert_len, key_len, ocsp_staple_len; + const uint8_t *cert, *key, *ocsp_staple; + X509 *x509_cert = NULL; + struct tls_keypair *kp; + struct tls_error err; + int failed = 1; + + load_file(cert_file, &cert, &cert_len); + load_file(key_file, &key, &key_len); + load_file(ocsp_staple_file, &ocsp_staple, &ocsp_staple_len); + + if ((kp = tls_keypair_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create keypair\n"); + goto done; + } + + if (tls_keypair_set_cert_file(kp, &err, cert_file) == -1) { + fprintf(stderr, "FAIL: failed to load cert file: %s\n", + err.msg); + goto done; + } + if (tls_keypair_set_key_file(kp, &err, key_file) == -1) { + fprintf(stderr, "FAIL: failed to load key file: %s\n", err.msg); + goto done; + } + if (tls_keypair_set_ocsp_staple_file(kp, &err, ocsp_staple_file) == -1) { + fprintf(stderr, "FAIL: failed to load ocsp staple file: %s\n", + err.msg); + goto done; + } + + if (compare_mem("certificate", cert, cert_len, kp->cert_mem, + kp->cert_len) == -1) + goto done; + if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1) + goto done; + if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len, + kp->ocsp_staple, kp->ocsp_staple_len) == -1) + goto done; + if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) { + fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'", + kp->pubkey_hash, PUBKEY_HASH); + goto done; + } + + tls_keypair_clear_key(kp); + + if (kp->key_mem != NULL || kp->key_len != 0) { + fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)", + kp->key_mem, kp->key_len); + goto done; + } + + if (tls_keypair_set_cert_mem(kp, &err, cert, cert_len) == -1) { + fprintf(stderr, "FAIL: failed to load cert: %s\n", err.msg); + goto done; + } + if (tls_keypair_set_key_mem(kp, &err, key, key_len) == -1) { + fprintf(stderr, "FAIL: failed to load key: %s\n", err.msg); + goto done; + } + if (tls_keypair_set_ocsp_staple_mem(kp, &err, ocsp_staple, + ocsp_staple_len) == -1) { + fprintf(stderr, "FAIL: failed to load ocsp staple: %s\n", err.msg); + goto done; + } + if (compare_mem("certificate", cert, cert_len, kp->cert_mem, + kp->cert_len) == -1) + goto done; + if (compare_mem("key", key, key_len, kp->key_mem, kp->cert_len) == -1) + goto done; + if (compare_mem("ocsp staple", ocsp_staple, ocsp_staple_len, + kp->ocsp_staple, kp->ocsp_staple_len) == -1) + goto done; + if (strcmp(kp->pubkey_hash, PUBKEY_HASH) != 0) { + fprintf(stderr, "FAIL: got pubkey hash '%s', want '%s'", + kp->pubkey_hash, PUBKEY_HASH); + goto done; + } + + if (tls_keypair_load_cert(kp, &err, &x509_cert) == -1) { + fprintf(stderr, "FAIL: failed to load X509 certificate: %s\n", + err.msg); + goto done; + } + + tls_keypair_clear_key(kp); + + if (kp->key_mem != NULL || kp->key_len != 0) { + fprintf(stderr, "FAIL: key not cleared (mem %p, len %zu)", + kp->key_mem, kp->key_len); + goto done; + } + + failed = 0; + + done: + tls_keypair_free(kp); + X509_free(x509_cert); + free((uint8_t *)cert); + free((uint8_t *)key); + free((uint8_t *)ocsp_staple); + + return (failed); +} + +int +main(int argc, char **argv) +{ + int failure = 0; + + if (argc != 4) { + fprintf(stderr, "usage: %s ocspstaplefile certfile keyfile\n", + argv[0]); + return (1); + } + + ocsp_staple_file = argv[1]; + cert_file = argv[2]; + key_file = argv[3]; + + failure |= do_keypair_tests(); + + return (failure); +} diff --git a/tests/letsencrypt-r3.crt b/tests/letsencrypt-r3.crt new file mode 100644 index 0000000..43b222a --- /dev/null +++ b/tests/letsencrypt-r3.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw +WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg +RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP +R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx +sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm +NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg +Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG +/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB +Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA +FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw +AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw +Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB +gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W +PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl +ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz +CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm +lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4 +avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2 +yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O +yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids +hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+ +HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv +MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX +nLRbwHOoq7hHwg== +-----END CERTIFICATE----- diff --git a/tests/libressl.org.crt b/tests/libressl.org.crt new file mode 100644 index 0000000..4259548 --- /dev/null +++ b/tests/libressl.org.crt @@ -0,0 +1,39 @@ +-----BEGIN CERTIFICATE----- +MIIG3DCCBcSgAwIBAgISA7cdK3Ainj5sW/nVzBz0QTKzMA0GCSqGSIb3DQEBCwUA +MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD +EwJSMzAeFw0yMTExMTkxNjQ5MTdaFw0yMjAyMTcxNjQ5MTZaMBoxGDAWBgNVBAMT +D3d3dy5vcGVuYnNkLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +AONf/xu/gf0QoQT8nqjEpfUQaaygDkhPBw5mswqAU0fOMg9ZaZT7Nx8g9qAH0mgi +6GNd/y7I2fMM7vvkFk/NQn8pu51EMLJ7aNKv6o4ThJYzyvPikdZW+RcdIdt185wJ +ws7MNq2kaZ0gJRXsIE8haE0iDB9nPRtJ8HAbhxOeCRczrALjvJBI6blg/9TBI+sd +zvA8yEOelGRox6AikFSP6JDmSmzoBgVSTXq9riKKQeK1j+Wa6vBYmsN2LFmbWPYN +1TbJk1C37E7Q3CTCkHt+CZNcAqBFIovClb9jmR+0QU3NQnTSqeXnyKyOe2RtYHOx +3oRs9A8bsRPybvh6zYf33Od2QbFwCGOS1H9sRux1LJEeZlCFDuccRpU3X9f7IO1X +n5cYr9eIUFIniTAfiksGvL7do2nYNmX/ujdraX7ttPmJZMVVDBjct9g4KGC7aMvB +CSc695JcLA7RJuJ8qKXcKxINavIpSHsFPobLDPwl43xxihCMQpMfb8Eg3fi5CQcu +FjdljawMkFeAiVv4iI1rbpWhpZeOGQTKxxjagWd9UNJW9PQxqh+x63I2zO47+W6r +jSbk2SicUrYTK7F1W+4HRPbA4e5U+hFk881nngnG0mB0D3sinqzxWIyM5DWTDuVp +ePBJQq3odt2/ityGRY0FcO35mlYkuB26/7Dfq/KmI4olAgMBAAGjggMCMIIC/jAO +BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG +A1UdEwEB/wQCMAAwHQYDVR0OBBYEFIQBXV9xwD2xyW1oHNhKs8qxdQFtMB8GA1Ud +IwQYMBaAFBQusxe3WFbLrlAJQOYfr52LFMLGMFUGCCsGAQUFBwEBBEkwRzAhBggr +BgEFBQcwAYYVaHR0cDovL3IzLm8ubGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRw +Oi8vcjMuaS5sZW5jci5vcmcvMIHRBgNVHREEgckwgcaCD2Z0cC5vcGVuYnNkLm9y +Z4IMbGlicmVzc2wub3JnggtvcGVuYnNkLm9yZ4IMb3BlbmlrZWQub3JnggtvcGVu +c3NoLmNvbYIPcnBraS1jbGllbnQub3JnghB3d3cubGlicmVzc2wub3Jngg93d3cu +b3BlbmJzZC5vcmeCEHd3dy5vcGVuaWtlZC5vcmeCEXd3dy5vcGVucnN5bmMub3Jn +gg93d3cub3BlbnNzaC5jb22CE3d3dy5ycGtpLWNsaWVudC5vcmcwTAYDVR0gBEUw +QzAIBgZngQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDov +L2Nwcy5sZXRzZW5jcnlwdC5vcmcwggEEBgorBgEEAdZ5AgQCBIH1BIHyAPAAdwAp +eb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZcJV3HhAAAAX05UR9vAAAEAwBIMEYC +IQCT7TplmJqF8Ds8JvdSlNeSSMLAZMsB9ez3bUHgvShWrQIhAMJPkvugu+9VZ4AG +EAfnubGWp6mLssvTnE4C6NskZR7IAHUAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQAp +Bo2yCJo32RMAAAF9OVEgOwAABAMARjBEAiAmyRIocC0VBaei6hIa/zk2X5PfgzZf +7Qc4uApA4Y25+gIgYa4rhr2OhmUr+2Ph2nez88UqMrgjHn76fYOlSQDEV7gwDQYJ +KoZIhvcNAQELBQADggEBADMSIRTpbJOdHjy/ju4TPXmc9H7mhyXwXH382FKnkC+T +VaqPsJL7Mve7Lgr96tzRGVU8hLF3oRXpZVv6qSNmV3ULyCDVG8JoYDZbJV/v7ziU +RITnWsraI8BYtxgDx6YU8ISbWU0Kh8REdi+mQ49FWmmPaJO9XyvkvG2BD2e+t1Zh +8O78YFFhtQLuwTtOYa4WKOzWVXD8t2vZBGecJ+APnhcPGS6NQ9qqpKdDwmm0qYG7 +gafHxcWd2k2phmqbp7R3qqY/VP21VyUXCXoGAp+IaqJRunyEmTBAUyB6LkFBfQpc +y0LH4LFzj5ouo5HtlZQRR5z3MN9WmwAej1gNpC/j688= +-----END CERTIFICATE----- diff --git a/tests/md_test.c b/tests/md_test.c new file mode 100644 index 0000000..f2b4eca --- /dev/null +++ b/tests/md_test.c @@ -0,0 +1,301 @@ +/* $OpenBSD: md_test.c,v 1.1.1.1 2022/09/02 13:34:48 tb Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +struct md_test { + const int algorithm; + const uint8_t in[128]; + const size_t in_len; + const uint8_t out[EVP_MAX_MD_SIZE]; +}; + +static const struct md_test md_tests[] = { + /* MD4 (RFC 1320 test vectors) */ + { + .algorithm = NID_md4, + .in = "", + .in_len = 0, + .out = { + 0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0, + } + }, + { + .algorithm = NID_md4, + .in = "a", + .in_len = 1, + .out = { + 0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24, + } + }, + { + .algorithm = NID_md4, + .in = "abc", + .in_len = 3, + .out = { + 0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d, + } + }, + { + .algorithm = NID_md4, + .in = "message digest", + .in_len = 14, + .out = { + 0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b, + } + }, + { + .algorithm = NID_md4, + .in = "abcdefghijklmnopqrstuvwxyz", + .in_len = 26, + .out = { + 0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9, + } + }, + { + .algorithm = NID_md4, + .in = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" + "wxyz0123456789", + .in_len = 62, + .out = { + 0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4, + } + }, + { + .algorithm = NID_md4, + .in = + "123456789012345678901234567890123456789012345678" + "90123456789012345678901234567890", + .in_len = 80, + .out = { + 0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36, + } + }, + + /* MD5 (RFC 1321 test vectors) */ + { + .algorithm = NID_md5, + .in = "", + .in_len = 0, + .out = { + 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e, + } + }, + { + .algorithm = NID_md5, + .in = "a", + .in_len = 1, + .out = { + 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61, + } + }, + { + .algorithm = NID_md5, + .in = "abc", + .in_len = 3, + .out = { + 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72, + } + }, + { + .algorithm = NID_md5, + .in = "message digest", + .in_len = 14, + .out = { + 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0, + } + }, + { + .algorithm = NID_md5, + .in = "abcdefghijklmnopqrstuvwxyz", + .in_len = 26, + .out = { + 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b, + } + }, + { + .algorithm = NID_md5, + .in = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" + "wxyz0123456789", + .in_len = 62, + .out = { + 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f, + } + }, + { + .algorithm = NID_md5, + .in = + "123456789012345678901234567890123456789012345678" + "90123456789012345678901234567890", + .in_len = 80, + .out = { + 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a, + } + }, +}; + +#define N_MD_TESTS (sizeof(md_tests) / sizeof(md_tests[0])) + +typedef unsigned char *(*md_hash_func)(const unsigned char *, size_t, + unsigned char *); + +static int +md_hash_from_algorithm(int algorithm, const char **out_label, + md_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) +{ + switch (algorithm) { + case NID_md4: + *out_label = SN_md4; + *out_func = MD4; + *out_md = EVP_md4(); + *out_len = MD4_DIGEST_LENGTH; + break; + case NID_md5: + *out_label = SN_md5; + *out_func = MD5; + *out_md = EVP_md5(); + *out_len = MD5_DIGEST_LENGTH; + break; + default: + fprintf(stderr, "FAIL: unknown algorithm (%d)\n", + algorithm); + return 0; + } + + return 1; +} + +static int +md_test(void) +{ + unsigned char *(*md_func)(const unsigned char *, size_t, unsigned char *); + const struct md_test *st; + EVP_MD_CTX *hash = NULL; + const EVP_MD *md; + uint8_t out[EVP_MAX_MD_SIZE]; + size_t in_len, out_len; + size_t i; + const char *label; + int failed = 1; + + if ((hash = EVP_MD_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); + goto failed; + } + + for (i = 0; i < N_MD_TESTS; i++) { + st = &md_tests[i]; + if (!md_hash_from_algorithm(st->algorithm, &label, &md_func, + &md, &out_len)) + goto failed; + + /* Digest */ + memset(out, 0, sizeof(out)); + md_func(st->in, st->in_len, out); + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s): mismatch\n", label); + goto failed; + } + + /* EVP single-shot digest */ + memset(out, 0, sizeof(out)); + if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { + fprintf(stderr, "FAIL (%s): EVP_Digest failed\n", + label); + goto failed; + } + + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s): EVP single-shot mismatch\n", + label); + goto failed; + } + + /* EVP digest */ + memset(out, 0, sizeof(out)); + if (!EVP_DigestInit_ex(hash, md, NULL)) { + fprintf(stderr, "FAIL (%s): EVP_DigestInit_ex failed\n", + label); + goto failed; + } + + in_len = st->in_len / 2; + if (!EVP_DigestUpdate(hash, st->in, in_len)) { + fprintf(stderr, + "FAIL (%s): EVP_DigestUpdate first half failed\n", + label); + goto failed; + } + + if (!EVP_DigestUpdate(hash, st->in + in_len, + st->in_len - in_len)) { + fprintf(stderr, + "FAIL (%s): EVP_DigestUpdate second half failed\n", + label); + goto failed; + } + + if (!EVP_DigestFinal_ex(hash, out, NULL)) { + fprintf(stderr, + "FAIL (%s): EVP_DigestFinal_ex failed\n", + label); + goto failed; + } + + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s): EVP mismatch\n", label); + goto failed; + } + } + + failed = 0; + + failed: + EVP_MD_CTX_free(hash); + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= md_test(); + + return failed; +} diff --git a/tests/objectstest.c b/tests/objectstest.c new file mode 100644 index 0000000..5be26d4 --- /dev/null +++ b/tests/objectstest.c @@ -0,0 +1,588 @@ +/* $OpenBSD: objectstest.c,v 1.8 2023/05/23 11:06:52 tb Exp $ */ +/* + * Copyright (c) 2017, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +obj_compare_bytes(const char *label, const unsigned char *d1, int len1, + const unsigned char *d2, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: %s - byte lengths differ " + "(%d != %d)\n", label, len1, len2); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: %s - bytes differ\n", label); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + return 1; +} + +struct obj_test { + const char *oid; + const char *sn; + const char *ln; + int nid; + uint8_t data[255]; + size_t data_len; +}; + +struct obj_test obj_tests[] = { + { + .oid = NULL, + .sn = "UNDEF", + .ln = "undefined", + .nid = NID_undef, + }, + { + .oid = "2.5.4.10", + .sn = "O", + .ln = "organizationName", + .nid = NID_organizationName, + .data = { + 0x55, 0x04, 0x0a, + }, + .data_len = 3, + }, + { + .oid = "2.5.4.8", + .sn = "ST", + .ln = "stateOrProvinceName", + .nid = NID_stateOrProvinceName, + .data = { + 0x55, 0x04, 0x08, + }, + .data_len = 3, + }, + { + .oid = "2.23.43.1", + .sn = "wap-wsg", + .nid = NID_wap_wsg, + .data = { + 0x67, 0x2b, 0x01, + }, + .data_len = 3, + }, + { + .oid = "1.3.6.1.4.1.11129.2.4.5", + .sn = "ct_cert_scts", + .ln = "CT Certificate SCTs", + .nid = NID_ct_cert_scts, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, + 0x04, 0x05, + }, + .data_len = 10, + }, + { + .oid = "1.3.6.1.4.1", + .sn = "enterprises", + .ln = "Enterprises", + .nid = NID_Enterprises, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, + }, + .data_len = 5, + }, + { + .oid = "1.3.6.1.4.1.5454.1.70.6.11.2", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xaa, 0x4e, 0x01, + 0x46, 0x06, 0x0b, 0x02, + }, + .data_len = 12, + }, + { + .oid = "1.3.6.1.4.1.890.1.5.8.60.102.2", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x86, 0x7a, 0x01, + 0x05, 0x08, 0x3c, 0x66, 0x02, + }, + .data_len = 13, + }, + { + .oid = "1.3.6.1.4.1.173.7.3.4.1.1.26", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x2d, 0x07, + 0x03, 0x04, 0x01, 0x01, 0x1a, + }, + .data_len = 13, + }, +}; + +#define N_OBJ_TESTS (sizeof(obj_tests) / sizeof(*obj_tests)) + +static int +obj_name_test(struct obj_test *ot) +{ + const char *ln, *sn; + int nid; + int failed = 1; + + if (ot->ln != NULL) { + if ((nid = OBJ_ln2nid(ot->ln)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_ln2nid() for '%s' = %d, " + "want %d\n", ot->ln, nid, ot->nid); + goto failed; + } + if ((ln = OBJ_nid2ln(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2ln() for '%s' returned " + "NULL\n", ot->oid); + goto failed; + } + if (strcmp(ln, ot->ln) != 0) { + fprintf(stderr, "FAIL: OBJ_nid2ln() for '%s' = '%s', " + "want '%s'\n", ot->oid, ln, ot->ln); + goto failed; + } + } + if (ot->sn != NULL) { + if ((nid = OBJ_sn2nid(ot->sn)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_sn2nid() for '%s' = %d, " + "want %d\n", ot->sn, nid, ot->nid); + goto failed; + } + if ((sn = OBJ_nid2sn(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2sn() for '%s' returned " + "NULL\n", ot->oid); + goto failed; + } + if (strcmp(sn, ot->sn) != 0) { + fprintf(stderr, "FAIL: OBJ_nid2sn() for '%s' = '%s', " + "want '%s'\n", ot->oid, sn, ot->sn); + goto failed; + } + } + + failed = 0; + + failed: + return failed; +} + +static int +obj_name_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_name_test(&obj_tests[i]); + + return failed; +} + +static int +obj_nid_test(struct obj_test *ot) +{ + ASN1_OBJECT *obj = NULL; + int nid; + int failed = 1; + + if (ot->nid == NID_undef && ot->oid != NULL) + return 0; + + if ((obj = OBJ_nid2obj(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2obj() failed for '%s' (NID %d)\n", + ot->oid, ot->nid); + goto failed; + } + if ((nid = OBJ_obj2nid(obj)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_obj2nid() failed for '%s' - got %d, " + "want %d\n", ot->oid ? ot->oid : "undef", nid, ot->nid); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_nid_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_nid_test(&obj_tests[i]); + + return failed; +} + +static int +obj_oid_test(struct obj_test *ot) +{ + ASN1_OBJECT *obj = NULL; + char buf[1024]; + int len, nid; + int failed = 1; + + if (ot->oid == NULL) + return 0; + + if ((obj = OBJ_txt2obj(ot->oid, 0)) == NULL) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s'\n", ot->oid); + goto failed; + } + if ((nid = OBJ_txt2nid(ot->oid)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_txt2nid() failed for '%s', got %d " + "want %d\n", ot->oid, nid, ot->nid); + goto failed; + } + + if (!obj_compare_bytes("object data", OBJ_get0_data(obj), OBJ_length(obj), + ot->data, ot->data_len)) + goto failed; + + len = OBJ_obj2txt(buf, sizeof(buf), obj, 1); + if (len <= 0 || (size_t)len >= sizeof(buf)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for '%s'\n", ot->oid); + goto failed; + } + if (strcmp(buf, ot->oid) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt() returned '%s', want '%s'\n", + buf, ot->oid); + goto failed; + } + + if ((OBJ_obj2txt(NULL, 0, obj, 1) != len)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() with NULL buffer != %d\n", + len); + goto failed; + } + if ((OBJ_obj2txt(buf, 3, obj, 1) != len)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() with short buffer != %d\n", + len); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_oid_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_oid_test(&obj_tests[i]); + + return failed; +} + +static int +obj_txt_test(struct obj_test *ot) +{ + ASN1_OBJECT *obj = NULL; + const char *want; + char buf[1024]; + int len, nid; + int failed = 1; + + if (ot->oid == NULL) + return 0; + + if (ot->sn != NULL) { + if ((obj = OBJ_txt2obj(ot->sn, 0)) == NULL) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s'\n", + ot->sn); + goto failed; + } + if ((nid = OBJ_obj2nid(obj)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s', " + "got nid %d want %d\n", ot->sn, nid, ot->nid); + goto failed; + } + ASN1_OBJECT_free(obj); + obj = NULL; + } + if (ot->ln != NULL) { + if ((obj = OBJ_txt2obj(ot->ln, 0)) == NULL) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s'\n", + ot->ln); + goto failed; + } + if ((nid = OBJ_obj2nid(obj)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s', " + "got nid %d want %d\n", ot->ln, nid, ot->nid); + goto failed; + } + ASN1_OBJECT_free(obj); + obj = NULL; + } + + if ((obj = OBJ_txt2obj(ot->oid, 0)) == NULL) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s'\n", ot->oid); + goto failed; + } + if ((nid = OBJ_obj2nid(obj)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s', " + "got nid %d want %d\n", ot->oid, nid, ot->nid); + goto failed; + } + + len = OBJ_obj2txt(buf, sizeof(buf), obj, 0); + if (len <= 0 || (size_t)len >= sizeof(buf)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for '%s'\n", ot->oid); + goto failed; + } + want = ot->ln; + if (want == NULL) + want = ot->sn; + if (want == NULL) + want = ot->oid; + if (strcmp(buf, want) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt() returned '%s', want '%s'\n", + buf, want); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_txt_early_nul_test(void) +{ + ASN1_OBJECT *obj = NULL; + char buf[2]; + int failed = 1; + + buf[0] = 'x'; + buf[1] = '\0'; + + if (OBJ_obj2txt(buf, sizeof(buf), NULL, 1) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt(NULL) succeded\n"); + goto failed; + } + if (buf[0] != '\0') { + fprintf(stderr, "FAIL: OBJ_obj2txt(NULL) did not NUL terminate\n"); + goto failed; + } + + if ((obj = ASN1_OBJECT_new()) == NULL) + errx(1, "ASN1_OBJECT_new"); + + buf[0] = 'x'; + buf[1] = '\0'; + + if (OBJ_obj2txt(buf, sizeof(buf), obj, 1) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt(obj) succeeded\n"); + goto failed; + } + if (buf[0] != '\0') { + fprintf(stderr, "FAIL: OBJ_obj2txt(obj) did not NUL terminate\n"); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_txt_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_txt_test(&obj_tests[i]); + + failed |= obj_txt_early_nul_test(); + + return failed; +} + +/* OID 1.3.18446744073709551615 (64 bits). */ +const uint8_t asn1_large_oid1[] = { + 0x06, 0x0b, + 0x2b, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, +}; + +/* OID 1.3.18446744073709551616 (65 bits). */ +const uint8_t asn1_large_oid2[] = { + 0x06, 0x0b, + 0x2b, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x00, +}; + +/* OID 1.3.340282366920938463463374607431768211455 (128 bits). */ +const uint8_t asn1_large_oid3[] = { + 0x06, 0x14, + 0x2b, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, +}; + +/* OID 1.3.115792089237316195423570985008687907853269984665640564039457584007913129639935 (256 bits). */ +const uint8_t asn1_large_oid4[] = { + 0x06, 0x26, + 0x2b, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, +}; + +struct oid_large_test { + const char *oid; + const uint8_t *asn1_der; + size_t asn1_der_len; + int obj2txt; +}; + +struct oid_large_test oid_large_tests[] = { + { + .oid = "1.3.18446744073709551615", + .asn1_der = asn1_large_oid1, + .asn1_der_len = sizeof(asn1_large_oid1), + .obj2txt = 1, + }, + { + .oid = "1.3.18446744073709551616", + .asn1_der = asn1_large_oid2, + .asn1_der_len = sizeof(asn1_large_oid2), + .obj2txt = 0, + }, + { + .oid = "1.3.340282366920938463463374607431768211455", + .asn1_der = asn1_large_oid3, + .asn1_der_len = sizeof(asn1_large_oid3), + .obj2txt = 0, + }, + { + .oid = "1.3.115792089237316195423570985008687907853269984665640" + "564039457584007913129639935", + .asn1_der = asn1_large_oid4, + .asn1_der_len = sizeof(asn1_large_oid4), + .obj2txt = 0, + }, +}; + +#define N_OID_LARGE_TESTS (sizeof(oid_large_tests) / sizeof(*oid_large_tests)) + +static int +obj_oid_large_test(size_t test_no, struct oid_large_test *olt) +{ + ASN1_OBJECT *obj = NULL; + const uint8_t *p; + char buf[1024]; + int len; + int failed = 1; + + p = olt->asn1_der; + if ((obj = d2i_ASN1_OBJECT(NULL, &p, olt->asn1_der_len)) == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed for large " + "oid %zu\n", test_no); + goto failed; + } + len = OBJ_obj2txt(buf, sizeof(buf), obj, 1); + if (len < 0 || (size_t)len >= sizeof(buf)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for large " + "oid %zu\n", test_no); + goto failed; + } + if ((len != 0) != olt->obj2txt) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for large " + "oid %zu\n", test_no); + goto failed; + } + if (len != 0 && strcmp(buf, olt->oid) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt() returned '%s', want '%s'\n", + buf, olt->oid); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_oid_large_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OID_LARGE_TESTS; i++) + failed |= obj_oid_large_test(i, &oid_large_tests[i]); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= obj_name_tests(); + failed |= obj_nid_tests(); + failed |= obj_oid_tests(); + failed |= obj_txt_tests(); + failed |= obj_oid_large_tests(); + + return (failed); +} diff --git a/tests/ocsp_test.c b/tests/ocsp_test.c new file mode 100644 index 0000000..a38d281 --- /dev/null +++ b/tests/ocsp_test.c @@ -0,0 +1,159 @@ +/* $OpenBSD: ocsp_test.c,v 1.7 2023/07/07 19:54:36 bcook Exp $ */ +/* + * Copyright (c) 2016 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +static int +tcp_connect(char *host, char *port) +{ + int error, sd = -1; + struct addrinfo hints, *res, *r; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + if (BIO_sock_init() != 1) { + perror("BIO_sock_init()"); + exit(-1); + } + + error = getaddrinfo(host, port, &hints, &res); + if (error != 0) { + perror("getaddrinfo()"); + exit(-1); + } + + for (r = res; r != NULL; r = r->ai_next) { + sd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if (sd == -1) + continue; + + if (connect(sd, r->ai_addr, r->ai_addrlen) == 0) + break; + + close(sd); + } + + freeaddrinfo(res); + + return sd; +} + +int +main(int argc, char *argv[]) +{ + int sd, ocsp_status; + const unsigned char *p; + long len; + OCSP_RESPONSE *rsp = NULL; + OCSP_BASICRESP *br = NULL; + X509_STORE *st = NULL; + STACK_OF(X509) *ch = NULL; + char *host, *port; +#ifdef _PATH_SSL_CA_FILE + char *cafile = _PATH_SSL_CA_FILE; +#else + char *cafile = "/etc/ssl/cert.pem"; +#endif + + SSL *ssl; + SSL_CTX *ctx; + + SSL_library_init(); + SSL_load_error_strings(); + + ctx = SSL_CTX_new(SSLv23_client_method()); + + if (!SSL_CTX_load_verify_locations(ctx, cafile, NULL)) { + printf("failed to load %s\n", cafile); + exit(-1); + } + + if (argc != 3) + errx(-1, "need a host and port to connect to"); + else { + host = argv[1]; + port = argv[2]; + } + + sd = tcp_connect(host, port); + + ssl = SSL_new(ctx); + + SSL_set_fd(ssl, (int) sd); + SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp); + + if (SSL_connect(ssl) <= 0) { + printf("SSL connect error\n"); + exit(-1); + } + + if (SSL_get_verify_result(ssl) != X509_V_OK) { + printf("Certificate doesn't verify from host %s port %s\n", host, port); + exit(-1); + } + + /* ==== VERIFY OCSP RESPONSE ==== */ + + + len = SSL_get_tlsext_status_ocsp_resp(ssl, &p); + + if (!p) { + printf("No OCSP response received for %s port %s\n", host, port); + exit(-1); + } + + rsp = d2i_OCSP_RESPONSE(NULL, &p, len); + if (!rsp) { + puts("Invalid OCSP response"); + exit(-1); + } + + ocsp_status = OCSP_response_status(rsp); + if (ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + printf("Invalid OCSP response status: %s (%d)", + OCSP_response_status_str(ocsp_status), ocsp_status); + exit(-1); + } + + br = OCSP_response_get1_basic(rsp); + if (!br) { + puts("Invalid OCSP response"); + exit(-1); + } + + ch = SSL_get_peer_cert_chain(ssl); + st = SSL_CTX_get_cert_store(ctx); + + if (OCSP_basic_verify(br, ch, st, 0) <= 0) { + puts("OCSP response verification failed"); + exit(-1); + } + + printf("OCSP validated from %s %s\n", host, port); + + return 0; +} diff --git a/tests/pbkdf2.c b/tests/pbkdf2.c new file mode 100644 index 0000000..9cbc031 --- /dev/null +++ b/tests/pbkdf2.c @@ -0,0 +1,214 @@ +/* $OpenBSD: pbkdf2.c,v 1.2 2018/07/17 17:06:49 tb Exp $ */ +/* Written by Christian Heimes, 2013 */ +/* + * Copyright (c) 2013 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include + +typedef struct { + const char *pass; + int passlen; + const char *salt; + int saltlen; + int iter; +} testdata; + +static const testdata test_cases[] = { + {"password", 8, "salt", 4, 1}, + {"password", 8, "salt", 4, 2}, + {"password", 8, "salt", 4, 4096}, + {"passwordPASSWORDpassword", 24, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096}, + {"pass\0word", 9, "sa\0lt", 5, 4096}, + {NULL}, +}; + +static const char *sha1_results[] = { + "0c60c80f961f0e71f3a9b524af6012062fe037a6", + "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957", + "4b007901b765489abead49d926f721d065a429c1", + "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038", + "56fa6aa75548099dcc37d7f03425e0c3", +}; + +static const char *sha256_results[] = { + "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b", + "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43", + "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a", + "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c63551" + "8c7dac47e9", + "89b69d0516f829893c696226650a8687", +}; + +static const char *sha512_results[] = { + "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d47" + "0a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce", + "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab" + "2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e", + "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30" + "602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5", + "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59" + "f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8", + "9d9e9c4cd21fe4be24d5b8244c759665", +}; + +static void +hexdump(FILE *f, const char *title, const unsigned char *s, size_t len) +{ + fprintf(f, "%s", title); + for (; len != 0; len--) + fprintf(f, " 0x%02x", *(s++)); + fprintf(f, "\n"); +} + +static int +convert(unsigned char *dst, const unsigned char *src, size_t len) +{ + unsigned int n; + + for (; len != 0; src += 2, len--) { + if (sscanf((char *)src, "%2x", &n) != 1) + return EINVAL; + *dst++ = (unsigned char)n; + } + return 0; +} + +static void +test_p5_pbkdf2(unsigned int n, const char *digestname, const testdata *test, + const char *hex) +{ + const EVP_MD *digest; + unsigned char *out; + unsigned char *expected; + size_t keylen; + int r; + + digest = EVP_get_digestbyname(digestname); + if (digest == NULL) { + fprintf(stderr, "unknown digest %s\n", digestname); + exit(5); + } + + keylen = strlen(hex); + if ((keylen % 2) != 0) { + fprintf(stderr, "odd hex string %s, digest %u\n", digestname, n); + exit(5); + } + keylen /= 2; + expected = malloc(keylen); + out = malloc(keylen); + if (expected == NULL || out == NULL) { + fprintf(stderr, "malloc() failed\n"); + exit(5); + } + if (convert(expected, (const unsigned char *)hex, keylen) != 0) { + fprintf(stderr, "invalid hex string %s, digest %u\n", hex, n); + exit(5); + } + + r = PKCS5_PBKDF2_HMAC(test->pass, test->passlen, + (const unsigned char *)test->salt, test->saltlen, + test->iter, digest, keylen, out); + + if (r == 0) { + fprintf(stderr, "PKCS5_PBKDF2_HMAC(%s) failure test %u\n", + digestname, n); + exit(3); + } + if (memcmp(expected, out, keylen) != 0) { + fprintf(stderr, + "Wrong result for PKCS5_PBKDF2_HMAC(%s) test %u\n", + digestname, n); + hexdump(stderr, "expected: ", expected, keylen); + hexdump(stderr, "result: ", out, keylen); + exit(2); + } + free(expected); + free(out); +} + +int +main(int argc,char **argv) +{ + unsigned int n; + const testdata *test = test_cases; + + OpenSSL_add_all_digests(); +#ifndef OPENSSL_NO_ENGINE + ENGINE_load_builtin_engines(); + ENGINE_register_all_digests(); +#endif + + for (n = 0; test->pass != NULL; n++, test++) { + test_p5_pbkdf2(n, "sha1", test, sha1_results[n]); + test_p5_pbkdf2(n, "sha256", test, sha256_results[n]); + test_p5_pbkdf2(n, "sha512", test, sha512_results[n]); + } + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_thread_state(NULL); + ERR_free_strings(); + return 0; +} diff --git a/tests/pkcs7test.c b/tests/pkcs7test.c new file mode 100644 index 0000000..28e0f67 --- /dev/null +++ b/tests/pkcs7test.c @@ -0,0 +1,301 @@ +/* $OpenBSD: pkcs7test.c,v 1.5 2021/04/07 17:21:40 tb Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +const char certificate[] = "\ +-----BEGIN CERTIFICATE----- \n\ +MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV \n\ +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT \n\ +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt \n\ +ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMVoXDTI0MDQwMTE0NDUxMVowZDELMAkG \n\ +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU \n\ +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw \n\ +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY \n\ ++yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs \n\ +lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D \n\ +nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 \n\ +x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 \n\ +bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 \n\ +AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG \n\ ++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B \n\ +AQUFAAOCAQEAJzA4KTjkjXGSC4He63yX9Br0DneGBzjAwc1H6f72uqnCs8m7jgkE \n\ +PQJFdTzQUKh97QPUuayZ2gl8XHagg+iWGy60Kw37gQ0+lumCN2sllvifhHU9R03H \n\ +bWtS4kue+yQjMbrzf3zWygMDgwvFOUAIgBpH9qGc+CdNu97INTYd0Mvz51vLlxRn \n\ +sC5aBYCWaZFnw3lWYxf9eVFRy9U+DkYFqX0LpmbDtcKP7AZGE6ZwSzaim+Cnoz1u \n\ +Cgn+QmpFXgJKMFIZ82iSZISn+JkCCGxctZX1lMvai4Wi8Y0HxW9FTFZ6KBNwwE4B \n\ +zjbN/ehBkgLlW/DWfi44DvwUHmuU6QP3cw== \n\ +-----END CERTIFICATE----- \n\ +"; + +const char private_key[] = "\ +-----BEGIN RSA PRIVATE KEY----- \n\ +MIIEpQIBAAKCAQEAtK2p2x0S3C1ajftAc3GaWPsji6scw1k9Sw/XltbLQuDc11/f \n\ +wwrUiFcje2CB3Ri6yD6+uCA3V12jEc4GdqzirJZhwgIhaTv42vfYBgiUcR9McEGr \n\ +agFC3yVR3lIbOzhBjmXNp1on46irxnzU4pT+w58IuvYqUBavaEtfRZocFR5NsIOy \n\ +mRhyNag8htOFK3wmTEYrb0vflFYT6SD47ogYtsd/xWSKS+YFyb7xSusR2Ot6Ktmr \n\ +MswQE57QYJz+KiRVlnL0cduMBdT52Wm8blaC9mz50PyrzjQ68NyHapCoWDU7pe4x \n\ +HLtzpXGSDMPuw4miiSwMym/2wReYJv6cFugLPQIDAQABAoIBAAZOyc9MhIwLSU4L \n\ +p4RgQvM4UVVe8/Id+3XTZ8NsXExJbWxXfIhiqGjaIfL8u4vsgRjcl+v1s/jo2/iT \n\ +KMab4o4D8gXD7UavQVDjtjb/ta79WL3SjRl2Uc9YjjMkyq6WmDNQeo2NKDdafCTB \n\ +1uzSJtLNipB8Z53ELPuHJhxX9QMHrMnuha49riQgXZ7buP9iQrHJFhImBjSzbxJx \n\ +L+TI6rkyLSf9Wi0Pd3L27Ob3QWNfNRYNSeTE+08eSRChkur5W0RuXAcuAICdQlCl \n\ +LBvWO/LmmvbzCqiDcgy/TliSb6CGGwgiNG7LJZmlkYNj8laGwalNlYZs3UrVv6NO \n\ +Br2loAECgYEA2kvCvPGj0Dg/6g7WhXDvAkEbcaL1tSeCxBbNH+6HS2UWMWvyTtCn \n\ +/bbD519QIdkvayy1QjEf32GV/UjUVmlULMLBcDy0DGjtL3+XpIhLKWDNxN1v1/ai \n\ +1oz23ZJCOgnk6K4qtFtlRS1XtynjA+rBetvYvLP9SKeFrnpzCgaA2r0CgYEA0+KX \n\ +1ACXDTNH5ySX3kMjSS9xdINf+OOw4CvPHFwbtc9aqk2HePlEsBTz5I/W3rKwXva3 \n\ +NqZ/bRqVVeZB/hHKFywgdUQk2Uc5z/S7Lw70/w1HubNTXGU06Ngb6zOFAo/o/TwZ \n\ +zTP1BMIKSOB6PAZPS3l+aLO4FRIRotfFhgRHOoECgYEAmiZbqt8cJaJDB/5YYDzC \n\ +mp3tSk6gIb936Q6M5VqkMYp9pIKsxhk0N8aDCnTU+kIK6SzWBpr3/d9Ecmqmfyq7 \n\ +5SvWO3KyVf0WWK9KH0abhOm2BKm2HBQvI0DB5u8sUx2/hsvOnjPYDISbZ11t0MtK \n\ +u35Zy89yMYcSsIYJjG/ROCUCgYEAgI2P9G5PNxEP5OtMwOsW84Y3Xat/hPAQFlI+ \n\ +HES+AzbFGWJkeT8zL2nm95tVkFP1sggZ7Kxjz3w7cpx7GX0NkbWSE9O+T51pNASV \n\ +tN1sQ3p5M+/a+cnlqgfEGJVvc7iAcXQPa3LEi5h2yPR49QYXAgG6cifn3dDSpmwn \n\ +SUI7PQECgYEApGCIIpSRPLAEHTGmP87RBL1smurhwmy2s/pghkvUkWehtxg0sGHh \n\ +kuaqDWcskogv+QC0sVdytiLSz8G0DwcEcsHK1Fkyb8A+ayiw6jWJDo2m9+IF4Fww \n\ +1Te6jFPYDESnbhq7+TLGgHGhtwcu5cnb4vSuYXGXKupZGzoLOBbv1Zw= \n\ +-----END RSA PRIVATE KEY----- \n\ +"; + +const char message[] = "\ +Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do \r\n\ +eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut \r\n\ +enim ad minim veniam, quis nostrud exercitation ullamco laboris \r\n\ +nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor \r\n\ +in reprehenderit in voluptate velit esse cillum dolore eu fugiat \r\n\ +nulla pariatur. Excepteur sint occaecat cupidatat non proident, \r\n\ +sunt in culpa qui officia deserunt mollit anim id est laborum. \r\n\ +"; + +static int +x509_store_callback(int ok, X509_STORE_CTX *ctx) +{ + /* Pretend the certificate issuer is valid... */ + return 1; +} + +static void +fatal(const char *msg) +{ + warnx("%s", msg); + ERR_print_errors_fp(stderr); + exit(1); +} + +static void +message_compare(const char *out, size_t len) +{ + if (len != sizeof(message)) { + fprintf(stderr, "FAILURE: length mismatch (%zu != %zu)\n", + len, sizeof(message)); + exit(1); + } + if (memcmp(out, message, len) != 0) { + fprintf(stderr, "FAILURE: message mismatch\n"); + fprintf(stderr, "Got:\n%s\n", out); + fprintf(stderr, "Want:\n%s\n", message); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + BIO *bio_in, *bio_content, *bio_out, *bio_cert, *bio_pkey; + STACK_OF(X509) *certs; + const EVP_CIPHER *cipher; + EVP_PKEY *pkey; + X509_STORE *store; + X509 *cert; + PKCS7 *p7; + size_t len; + char *out; + int flags; + + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + + /* + * A bunch of setup... + */ + cipher = EVP_aes_256_cbc(); + if (cipher == NULL) + fatal("cipher"); + + certs = sk_X509_new_null(); + if (certs == NULL) + fatal("sk_X509_new_null"); + + bio_cert = BIO_new_mem_buf((char *)certificate, sizeof(certificate)); + if (bio_cert == NULL) + fatal("BIO_new_mem_buf certificate"); + + cert = PEM_read_bio_X509_AUX(bio_cert, NULL, NULL, NULL); + if (cert == NULL) + fatal("PEM_read_bio_X509_AUX"); + sk_X509_push(certs, cert); + + store = X509_STORE_new(); + if (store == NULL) + fatal("X509_STORE_new"); + X509_STORE_set_verify_cb(store, x509_store_callback); + + bio_pkey = BIO_new_mem_buf((char *)private_key, sizeof(private_key)); + if (bio_pkey == NULL) + fatal("BIO_new_mem_buf private_key"); + + pkey = PEM_read_bio_PrivateKey(bio_pkey, NULL, NULL, NULL); + if (pkey == NULL) + fatal("PEM_read_bio_PrivateKey"); + + bio_content = BIO_new_mem_buf((char *)message, sizeof(message)); + if (bio_content == NULL) + fatal("BIO_new_mem_buf message"); + + /* + * Encrypt and then decrypt. + */ + if (BIO_reset(bio_content) != 1) + fatal("BIO_reset"); + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + p7 = PKCS7_encrypt(certs, bio_content, cipher, 0); + if (p7 == NULL) + fatal("PKCS7_encrypt"); + if (PEM_write_bio_PKCS7(bio_out, p7) != 1) + fatal("PEM_write_bio_PKCS7"); + PKCS7_free(p7); + + bio_in = bio_out; + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); + if (p7 == NULL) + fatal("PEM_read_bio_PKCS7"); + if (PKCS7_decrypt(p7, pkey, cert, bio_out, 0) != 1) + fatal("PKCS7_decrypt"); + PKCS7_free(p7); + + len = BIO_get_mem_data(bio_out, &out); + message_compare(out, len); + + BIO_free(bio_in); + BIO_free(bio_out); + + /* + * Sign and then verify. + */ + if (BIO_reset(bio_content) != 1) + fatal("BIO_reset"); + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + p7 = PKCS7_sign(cert, pkey, certs, bio_content, 0); + if (p7 == NULL) + fatal("PKCS7_sign"); + if (PEM_write_bio_PKCS7(bio_out, p7) != 1) + fatal("PEM_write_bio_PKCS7"); + PKCS7_free(p7); + + bio_in = bio_out; + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); + if (p7 == NULL) + fatal("PEM_read_bio_PKCS7"); + if (PKCS7_verify(p7, certs, store, NULL, bio_out, 0) != 1) + fatal("PKCS7_verify"); + PKCS7_free(p7); + + len = BIO_get_mem_data(bio_out, &out); + message_compare(out, len); + + BIO_free(bio_in); + BIO_free(bio_out); + + /* + * Sign and then verify with a detached signature. + */ + if (BIO_reset(bio_content) != 1) + fatal("BIO_reset"); + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + flags = PKCS7_DETACHED|PKCS7_PARTIAL; + p7 = PKCS7_sign(NULL, NULL, NULL, bio_content, flags); + if (p7 == NULL) + fatal("PKCS7_sign"); + if (PKCS7_sign_add_signer(p7, cert, pkey, NULL, flags) == NULL) + fatal("PKCS7_sign_add_signer"); + if (PKCS7_final(p7, bio_content, flags) != 1) + fatal("PKCS7_final"); + if (PEM_write_bio_PKCS7(bio_out, p7) != 1) + fatal("PEM_write_bio_PKCS7"); + PKCS7_free(p7); + + /* bio_out contains only the detached signature. */ + bio_in = bio_out; + if (BIO_reset(bio_content) != 1) + fatal("BIO_reset"); + + bio_out = BIO_new(BIO_s_mem()); + if (bio_out == NULL) + fatal("BIO_new"); + + p7 = PEM_read_bio_PKCS7(bio_in, NULL, NULL, NULL); + if (p7 == NULL) + fatal("PEM_read_bio_PKCS7"); + if (PKCS7_verify(p7, certs, store, bio_content, bio_out, flags) != 1) + fatal("PKCS7_verify"); + PKCS7_free(p7); + + len = BIO_get_mem_data(bio_out, &out); + message_compare(out, len); + + BIO_free(bio_in); + BIO_free(bio_out); + BIO_free(bio_content); + BIO_free(bio_cert); + BIO_free(bio_pkey); + + EVP_PKEY_free(pkey); + + X509_free(cert); + X509_STORE_free(store); + sk_X509_free(certs); + + return 0; +} diff --git a/tests/policy.c b/tests/policy.c new file mode 100644 index 0000000..f5c9700 --- /dev/null +++ b/tests/policy.c @@ -0,0 +1,667 @@ +/* $OpenBSD: policy.c,v 1.12 2023/06/02 08:35:10 tb Exp $ */ +/* + * Copyright (c) 2020 Joel Sing + * Copyright (c) 2020-2023 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "x509_verify.h" + +#define MODE_MODERN_VFY 0 +#define MODE_MODERN_VFY_DIR 1 +#define MODE_LEGACY_VFY 2 + +static int verbose = 1; + +#define OID1 "1.2.840.113554.4.1.72585.2.1" +#define OID2 "1.2.840.113554.4.1.72585.2.2" +#define OID3 "1.2.840.113554.4.1.72585.2.3" +#define OID4 "1.2.840.113554.4.1.72585.2.4" +#define OID5 "1.2.840.113554.4.1.72585.2.5" + +#ifndef CERTSDIR +#define CERTSDIR "." +#endif + +static int +passwd_cb(char *buf, int size, int rwflag, void *u) +{ + memset(buf, 0, size); + return (0); +} + +static int +certs_from_file(const char *filename, STACK_OF(X509) **certs) +{ + STACK_OF(X509_INFO) *xis = NULL; + STACK_OF(X509) *xs = NULL; + BIO *bio = NULL; + X509 *x; + int i; + + if (*certs == NULL) { + if ((xs = sk_X509_new_null()) == NULL) + errx(1, "failed to create X509 stack"); + } else { + xs = *certs; + } + if ((bio = BIO_new_file(filename, "r")) == NULL) { + ERR_print_errors_fp(stderr); + errx(1, "failed to create bio"); + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, passwd_cb, NULL)) == NULL) + errx(1, "failed to read PEM"); + + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + if ((x = sk_X509_INFO_value(xis, i)->x509) == NULL) + continue; + if (!sk_X509_push(xs, x)) + errx(1, "failed to push X509"); + X509_up_ref(x); + } + + *certs = xs; + xs = NULL; + + sk_X509_INFO_pop_free(xis, X509_INFO_free); + sk_X509_pop_free(xs, X509_free); + BIO_free(bio); + + return 1; +} + +static int +verify_cert_cb(int ok, X509_STORE_CTX *xsc) +{ + X509 *current_cert; + int verify_err; + + current_cert = X509_STORE_CTX_get_current_cert(xsc); + if (current_cert != NULL) { + X509_NAME_print_ex_fp(stderr, + X509_get_subject_name(current_cert), 0, + XN_FLAG_ONELINE); + fprintf(stderr, "\n"); + } + + verify_err = X509_STORE_CTX_get_error(xsc); + if (verify_err != X509_V_OK) { + fprintf(stderr, "verify error at depth %d: %s\n", + X509_STORE_CTX_get_error_depth(xsc), + X509_verify_cert_error_string(verify_err)); + } + + return ok; +} + +static void +verify_cert(const char *roots_file, const char *intermediate_file, + const char *leaf_file, int *chains, int *error, int *error_depth, + int mode, ASN1_OBJECT *policy_oid, ASN1_OBJECT *policy_oid2, + int verify_flags) +{ + STACK_OF(X509) *roots = NULL, *bundle = NULL; + X509_STORE_CTX *xsc = NULL; + X509_STORE *store = NULL; + X509 *leaf = NULL; + int flags, ret; + + *chains = 0; + *error = 0; + *error_depth = 0; + + if (!certs_from_file(roots_file, &roots)) + errx(1, "failed to load roots from '%s'", roots_file); + if (!certs_from_file(leaf_file, &bundle)) + errx(1, "failed to load leaf from '%s'", leaf_file); + if (intermediate_file != NULL && !certs_from_file(intermediate_file, + &bundle)) + errx(1, "failed to load intermediate from '%s'", + intermediate_file); + if (sk_X509_num(bundle) < 1) + errx(1, "not enough certs in bundle"); + leaf = sk_X509_shift(bundle); + + if ((xsc = X509_STORE_CTX_new()) == NULL) + errx(1, "X509_STORE_CTX"); + if (!X509_STORE_CTX_init(xsc, store, leaf, bundle)) { + ERR_print_errors_fp(stderr); + errx(1, "failed to init store context"); + } + + flags = X509_V_FLAG_POLICY_CHECK; + flags |= verify_flags; + if (mode == MODE_LEGACY_VFY) + flags |= X509_V_FLAG_LEGACY_VERIFY; + X509_STORE_CTX_set_flags(xsc, flags); + + if (verbose) + X509_STORE_CTX_set_verify_cb(xsc, verify_cert_cb); + X509_STORE_CTX_set0_trusted_stack(xsc, roots); + + if (policy_oid != NULL) { + X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(xsc); + ASN1_OBJECT *copy = OBJ_dup(policy_oid); + X509_VERIFY_PARAM_add0_policy(param, copy); + } + if (policy_oid2 != NULL) { + X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(xsc); + ASN1_OBJECT *copy = OBJ_dup(policy_oid2); + X509_VERIFY_PARAM_add0_policy(param, copy); + } + + ret = X509_verify_cert(xsc); + + *error = X509_STORE_CTX_get_error(xsc); + *error_depth = X509_STORE_CTX_get_error_depth(xsc); + + if (ret == 1) { + *chains = 1; /* XXX */ + goto done; + } + + if (*error == 0) + errx(1, "Error unset on failure!\n"); + + fprintf(stderr, "failed to verify at %d: %s\n", + *error_depth, X509_verify_cert_error_string(*error)); + + done: + sk_X509_pop_free(roots, X509_free); + sk_X509_pop_free(bundle, X509_free); + X509_STORE_free(store); + X509_STORE_CTX_free(xsc); + X509_free(leaf); +} + +struct verify_cert_test { + const char *id; + const char *root_file; + const char *intermediate_file; + const char *leaf_file; + const char *policy_oid_to_check; + const char *policy_oid_to_check2; + int want_chains; + int want_error; + int want_error_depth; + int want_legacy_error; + int want_legacy_error_depth; + int failing; + int verify_flags; +}; + +struct verify_cert_test verify_cert_tests[] = { + /* + * Comments here are from boringssl/crypto/x509/x509_test.cc + * certs were generated by + * boringssl/crypto/x509/test/make_policy_certs.go + */ + + /* The chain is good for |oid1| and |oid2|, but not |oid3|. */ + { + .id = "nothing in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .want_chains = 1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + }, + { + .id = "1, in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .want_chains = 1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + }, + { + .id = "2, in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID2, + .want_chains = 1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + }, + { + .id = "3, in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + { + .id = "1 and 2, in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .policy_oid_to_check2 = OID2, + .want_chains = 1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + }, + { + .id = "1 and 3, in 1 and 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .policy_oid_to_check2 = OID3, + .want_chains = 1, + }, + /* The policy extension cannot be parsed. */ + { + .id = "1 in invalid intermediate policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_invalid.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + { + .id = "invalid intermediate", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_invalid.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + { + .id = "1 in invalid policy in leaf", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_invalid.pem", + .policy_oid_to_check = OID1, + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + { + .id = "invalid leaf", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_invalid.pem", + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + { + .id = "invalid leaf without explicit policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_invalid.pem", + .want_chains = 0, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + /* There is a duplicate policy in the leaf policy extension. */ + { + .id = "1 in duplicate policy extension in leaf", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_duplicate.pem", + .policy_oid_to_check = OID1, + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + /* There is a duplicate policy in the intermediate policy extension. */ + { + .id = "1 in duplicate policy extension in intermediate", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_duplicate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .want_chains = 0, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + /* + * Without |X509_V_FLAG_EXPLICIT_POLICY|, the policy tree is built and + * intersected with user-specified policies, but it is not required to result + * in any valid policies. + */ + { + .id = "nothing with explicit_policy unset", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .want_chains = 1, + }, + { + .id = "oid3 with explicit_policy unset", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 1, + }, + /* However, a CA with policy constraints can require an explicit policy. */ + { + .id = "oid1 with explicit_policy unset, intermediate requiring policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID1, + .want_chains = 1, + }, + { + .id = "oid3 with explicit_policy unset, intermediate requiring policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* + * requireExplicitPolicy applies even if the application does not configure a + * user-initial-policy-set. If the validation results in no policies, the + * chain is invalid. + */ + { + .id = "nothing explict_policy unset, with intermediate requiring policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_none.pem", + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* A leaf can also set requireExplicitPolicy but should work with none */ + { + .id = "nothing explicit_policy unset, with leaf requiring policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_require.pem", + .want_chains = 1, + }, + /* A leaf can also set requireExplicitPolicy but should fail with policy */ + { + .id = "oid3, explicit policy unset, with leaf requiring policy", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_require.pem", + .policy_oid_to_check = OID3, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* + * requireExplicitPolicy is a count of certificates to skip. If the value is + * not zero by the end of the chain, it doesn't count. + */ + { + .id = "oid3, with intermediate requiring explicit depth 1", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require1.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + { + .id = "oid3, with intermediate requiring explicit depth 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require2.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 1, + }, + { + .id = "oid3, with leaf requiring explicit depth 1", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_require1.pem", + .policy_oid_to_check = OID3, + .want_chains = 1, + }, + /* + * If multiple certificates specify the constraint, the more constrained value + * wins. + */ + { + .id = "oid3, with leaf and intermediate requiring explicit depth 1", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require1.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_require1.pem", + .policy_oid_to_check = OID3, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + { + .id = "oid3, with leaf requiring explicit depth 1 and intermediate depth 2", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require2.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_require.pem", + .policy_oid_to_check = OID3, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* + * An intermediate that requires an explicit policy, but then specifies no + * policies should fail verification as a result. + */ + { + .id = "oid1 with explicit_policy unset, intermediate requiring policy but specifying none", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require_no_policies.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* + * A constrained intermediate's policy extension has a duplicate policy, which + * is invalid. Historically this, and the above case, leaked memory. + */ + { + .id = "oid1 with explicit_policy unset, intermediate requiring policy but has duplicate", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_require_duplicate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf.pem", + .policy_oid_to_check = OID3, + .want_chains = 0, + .want_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_INVALID_POLICY_EXTENSION, + .want_legacy_error_depth = 0, + }, + /* + * The leaf asserts anyPolicy, but the intermediate does not. The resulting + * valid policies are the intersection.(and vice versa) + */ + { + .id = "oid1, with explicit_policy set, with leaf asserting any", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_any.pem", + .policy_oid_to_check = OID1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 1, + }, + { + .id = "oid3, with explicit_policy set, with leaf asserting any", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_any.pem", + .policy_oid_to_check = OID3, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 0, + .want_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_error_depth = 0, + .want_legacy_error = X509_V_ERR_NO_EXPLICIT_POLICY, + .want_legacy_error_depth = 0, + }, + /* Both assert anyPolicy. All policies are valid. */ + { + .id = "oid1, with explicit_policy set, with leaf and intermediate asserting any", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_any.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_any.pem", + .policy_oid_to_check = OID1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 1, + }, + { + .id = "oid3, with explicit_policy set, with leaf and intermediate asserting any", + .root_file = CERTSDIR "/" "policy_root.pem", + .intermediate_file = CERTSDIR "/" "policy_intermediate_any.pem", + .leaf_file = CERTSDIR "/" "policy_leaf_any.pem", + .policy_oid_to_check = OID1, + .verify_flags = X509_V_FLAG_EXPLICIT_POLICY, + .want_chains = 1, + }, + /* + * BoringSSL tests just a trust anchor but behaves differently in this corner case. + * than libressl for reasons that have nothing to do with policy (because parital + * chains and legacy verifier horror) + */ +}; + +#define N_VERIFY_CERT_TESTS \ + (sizeof(verify_cert_tests) / sizeof(*verify_cert_tests)) + +static int +verify_cert_test(int mode) +{ + ASN1_OBJECT *policy_oid, *policy_oid2; + struct verify_cert_test *vct; + int chains, error, error_depth; + int failed = 0; + size_t i; + + for (i = 0; i < N_VERIFY_CERT_TESTS; i++) { + vct = &verify_cert_tests[i]; + policy_oid = vct->policy_oid_to_check ? + OBJ_txt2obj(vct->policy_oid_to_check, 1) : NULL; + policy_oid2 = vct->policy_oid_to_check2 ? + OBJ_txt2obj(vct->policy_oid_to_check2, 1) : NULL; + + error = 0; + error_depth = 0; + + fprintf(stderr, "== Test %zu (%s)\n", i, vct->id); + verify_cert(vct->root_file, vct->intermediate_file, + vct->leaf_file, &chains, &error, &error_depth, + mode, policy_oid, policy_oid2, vct->verify_flags); + + if ((chains == 0 && vct->want_chains == 0) || + (chains == 1 && vct->want_chains > 0)) { + fprintf(stderr, "INFO: Succeeded with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (mode == MODE_LEGACY_VFY && vct->failing) + failed |= 1; + } else { + fprintf(stderr, "FAIL: Failed with %d chains%s\n", + chains, vct->failing ? " (legacy failure)" : ""); + if (!vct->failing) + failed |= 1; + } + + if (mode == MODE_LEGACY_VFY) { + if (error != vct->want_legacy_error) { + fprintf(stderr, "FAIL: Got legacy error %d, " + "want %d\n", error, vct->want_legacy_error); + failed |= 1; + } + if (error_depth != vct->want_legacy_error_depth) { + fprintf(stderr, "FAIL: Got legacy error depth " + "%d, want %d\n", error_depth, + vct->want_legacy_error_depth); + failed |= 1; + } + } + fprintf(stderr, "\n"); + ASN1_OBJECT_free(policy_oid); + ASN1_OBJECT_free(policy_oid2); + } + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + fprintf(stderr, "\n\nTesting legacy x509_vfy\n"); + failed |= verify_cert_test(MODE_LEGACY_VFY); + fprintf(stderr, "\n\nTesting modern x509_vfy\n"); + failed |= verify_cert_test(MODE_MODERN_VFY); + /* New verifier does not do policy goop at the moment */ + + return (failed); +} diff --git a/tests/policy_intermediate.pem b/tests/policy_intermediate.pem new file mode 100644 index 0000000..759deb4 --- /dev/null +++ b/tests/policy_intermediate.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgYUwgYIwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAoGCCqGSM49BAMCA0cAMEQCIFN2ZtknXQ9vz23qD1ecprC9iIo7 +j/SI42Ub64qZQaraAiA+CRCWJz/l+NQ1+TPWYDDWY6Wh2L9Wbddh1Nj5KJEkhQ== +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_any.pem b/tests/policy_intermediate_any.pem new file mode 100644 index 0000000..0931964 --- /dev/null +++ b/tests/policy_intermediate_any.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBkDCCATWgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjajBoMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjARBgNVHSAECjAIMAYGBFUdIAAwCgYIKoZIzj0EAwIDSQAwRgIh +AJbyXshUwjsFCiqrJkg91GzJdhZZ+3WXOekCJgi8uEESAiEAhv4sEE0wRRqgHDjl +vIt26IELfFE2Z/FBF3ihGmi6NoI= +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_duplicate.pem b/tests/policy_intermediate_duplicate.pem new file mode 100644 index 0000000..0eafe8d --- /dev/null +++ b/tests/policy_intermediate_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBvDCCAWKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZYwgZMwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMDwGA1UdIAQ1MDMwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMA8GDSqGSIb3EgQBhLcJAgIwCgYIKoZIzj0EAwIDSAAwRQIgUpG6 +FUeWrC62BtTPHiSlWBdnLWUYH0llS6uYUkpJFJECIQCWfhoZYXvHdMhgBDSI/vzY +Sw4uNdcMxrC2kP6lIioUSw== +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_invalid.pem b/tests/policy_intermediate_invalid.pem new file mode 100644 index 0000000..11c95af --- /dev/null +++ b/tests/policy_intermediate_invalid.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjDCCATKgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjZzBlMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjAOBgNVHSAEB0lOVkFMSUQwCgYIKoZIzj0EAwIDSAAwRQIgS2uK +cYlZ1bxeqgMy3X0Sfi0arAnqpePsAqAeEf+HJHQCIQDwfCnXrWyHET9lM/gJSkfN +j/JRJvJELDrAMVewCxZWKA== +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_mapped.pem b/tests/policy_intermediate_mapped.pem new file mode 100644 index 0000000..fa45e60 --- /dev/null +++ b/tests/policy_intermediate_mapped.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICrjCCAlSgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggGHMIIBgzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wXgYDVR0gBFcwVTAPBg0qhkiG9xIEAYS3CQIBMA8GDSqG +SIb3EgQBhLcJAgIwDwYNKoZIhvcSBAGEtwkCAzAPBg0qhkiG9xIEAYS3CQIEMA8G +DSqGSIb3EgQBhLcJAgUwgcsGA1UdIQSBwzCBwDAeBg0qhkiG9xIEAYS3CQIDBg0q +hkiG9xIEAYS3CQIBMB4GDSqGSIb3EgQBhLcJAgMGDSqGSIb3EgQBhLcJAgIwHgYN +KoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBDAeBg0qhkiG9xIEAYS3CQIEBg0q +hkiG9xIEAYS3CQIFMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3EgQBhLcJAgQwHgYN +KoZIhvcSBAGEtwkCBQYNKoZIhvcSBAGEtwkCBTAKBggqhkjOPQQDAgNIADBFAiAe +Ah2vJMZsW/RV35mM7b7/NjsjScjPEIxfDJu49inNXQIhANmGBqyWUogh/gXyVB0/ +IfDro27pANW3R02A+zH34q5k +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_mapped_any.pem b/tests/policy_intermediate_mapped_any.pem new file mode 100644 index 0000000..ae47bf4 --- /dev/null +++ b/tests/policy_intermediate_mapped_any.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICYjCCAgegAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggE6MIIBNjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wEQYDVR0gBAowCDAGBgRVHSAAMIHLBgNVHSEEgcMwgcAw +HgYNKoZIhvcSBAGEtwkCAwYNKoZIhvcSBAGEtwkCATAeBg0qhkiG9xIEAYS3CQID +Bg0qhkiG9xIEAYS3CQICMB4GDSqGSIb3EgQBhLcJAgQGDSqGSIb3EgQBhLcJAgQw +HgYNKoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBTAeBg0qhkiG9xIEAYS3CQIF +Bg0qhkiG9xIEAYS3CQIEMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3EgQBhLcJAgUw +CgYIKoZIzj0EAwIDSQAwRgIhAIOx3GL5xlldQGdTLIvTTAvczm8wiYHzZDAif2yj +wAjEAiEAg4K02kTYX9x7PC/u1PYdwvo+LVbnGbO6AN6U3K2d7gs= +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_mapped_oid3.pem b/tests/policy_intermediate_mapped_oid3.pem new file mode 100644 index 0000000..c04a38a --- /dev/null +++ b/tests/policy_intermediate_mapped_oid3.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICajCCAhCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjggFDMIIBPzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUkNL3/g7u +qGsIhGHCxes9UFqAba4wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIDMIHLBgNV +HSEEgcMwgcAwHgYNKoZIhvcSBAGEtwkCAwYNKoZIhvcSBAGEtwkCATAeBg0qhkiG +9xIEAYS3CQIDBg0qhkiG9xIEAYS3CQICMB4GDSqGSIb3EgQBhLcJAgQGDSqGSIb3 +EgQBhLcJAgQwHgYNKoZIhvcSBAGEtwkCBAYNKoZIhvcSBAGEtwkCBTAeBg0qhkiG +9xIEAYS3CQIFBg0qhkiG9xIEAYS3CQIEMB4GDSqGSIb3EgQBhLcJAgUGDSqGSIb3 +EgQBhLcJAgUwCgYIKoZIzj0EAwIDSAAwRQIhAK0bRaGgd5qQlX+zTw3IUynFHxfk +zRbZagnTzjYtkNNmAiBJ2kOnvRdW930eHAwZPGpc1Hn5hMSOQdUhNZ3XZDASkQ== +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_require.pem b/tests/policy_intermediate_require.pem new file mode 100644 index 0000000..5cf5d5b --- /dev/null +++ b/tests/policy_intermediate_require.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQAwCgYIKoZIzj0EAwIDRwAwRAIgbPUZ9ezH +SgTqom7VLPOvrQQXwy3b/ijSobs7+SOouKMCIDaqcb9143BG005etqeTvlgUyOGF +GQDWhiW8bizH+KEl +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_require1.pem b/tests/policy_intermediate_require1.pem new file mode 100644 index 0000000..7087404 --- /dev/null +++ b/tests/policy_intermediate_require1.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBujCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQEwCgYIKoZIzj0EAwIDSQAwRgIhAIAwvhHB +GQDN5YXlidd+n3OT/SqoeXfp7RiEonBnCkW4AiEA+iFc47EOBchHb+Gy0gg8F9Po +RnlpoulWDfbDwx9r4lc= +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_require2.pem b/tests/policy_intermediate_require2.pem new file mode 100644 index 0000000..350f419 --- /dev/null +++ b/tests/policy_intermediate_require2.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuTCCAV+gAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgZMwgZAwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMCsGA1UdIAQkMCIwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMAwGA1UdJAQFMAOAAQIwCgYIKoZIzj0EAwIDSAAwRQIgOpliSKKA ++wy/auQnKKl+wwtn/hGw6eZXgIOtFgDmyMYCIQC84zoJL87AE64gsrdX4XSHq6lb +WhZQp9ZnDaNu88SQLQ== +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_require_duplicate.pem b/tests/policy_intermediate_require_duplicate.pem new file mode 100644 index 0000000..733087a --- /dev/null +++ b/tests/policy_intermediate_require_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIByjCCAXCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjgaQwgaEwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJDS9/4O7qhr +CIRhwsXrPVBagG2uMDwGA1UdIAQ1MDMwDwYNKoZIhvcSBAGEtwkCATAPBg0qhkiG +9xIEAYS3CQICMA8GDSqGSIb3EgQBhLcJAgIwDAYDVR0kBAUwA4ABADAKBggqhkjO +PQQDAgNIADBFAiA2GxzMRYYo7NNq8u/ZvffXkCj/phqXQ8I64tEDd0X8pgIhAOJJ +e+dzzf4vbWfMlYkOQ4kf6ei5Zf+J2PL6VrqVrHQa +-----END CERTIFICATE----- diff --git a/tests/policy_intermediate_require_no_policies.pem b/tests/policy_intermediate_require_no_policies.pem new file mode 100644 index 0000000..1e81e0c --- /dev/null +++ b/tests/policy_intermediate_require_no_policies.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBizCCATCgAwIBAgIBAjAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowHjEcMBoGA1UE +AxMTUG9saWN5IEludGVybWVkaWF0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA +BOI6fKiM3jFLkLyAn88cvlw4SwxuygRjopP3FFBKHyUQvh3VVvfqSpSCSmp50Qia +jQ6Dg7CTpVZVVH+bguT7JTCjZTBjMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK +BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSQ0vf+Du6oawiE +YcLF6z1QWoBtrjAMBgNVHSQEBTADgAEAMAoGCCqGSM49BAMCA0kAMEYCIQDJYPgf +50fFDVho5TFeqkNVONx0ArVNgULPB27yPDHLrwIhAN+eua6oM4Q/O0jUESQ4VAKt +ts7ZCquTZbvgRgyqtjuT +-----END CERTIFICATE----- diff --git a/tests/policy_leaf.pem b/tests/policy_leaf.pem new file mode 100644 index 0000000..fb70306 --- /dev/null +++ b/tests/policy_leaf.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBpzCCAU2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo34wfDAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wKwYDVR0gBCQwIjAPBg0qhkiG9xIEAYS3CQIBMA8GDSqGSIb3EgQB +hLcJAgIwCgYIKoZIzj0EAwIDSAAwRQIgBEOriD1N3/cqoAofxEtf73M7Wi4UfjFK +jiU9nQhwnnoCIQD1v/XDp2BkWNHxNq7TaPnil3xXTvMX97yUbkUg8IRo0w== +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_any.pem b/tests/policy_leaf_any.pem new file mode 100644 index 0000000..d2c1b9e --- /dev/null +++ b/tests/policy_leaf_any.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjTCCATOgAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo2QwYjAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wEQYDVR0gBAowCDAGBgRVHSAAMAoGCCqGSM49BAMCA0gAMEUCIQC4 +UwAf1R4HefSzyO8lyQ3fmMjkptVEhFBee0a7N12IvwIgJMYZgQ52VTbqXyXqraJ8 +V+y+o7eHds7NewqnyuLbc78= +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_duplicate.pem b/tests/policy_leaf_duplicate.pem new file mode 100644 index 0000000..bdeb13c --- /dev/null +++ b/tests/policy_leaf_duplicate.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBsTCCAVigAwIBAgIBAzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowGjEYMBYGA1UE +AxMPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkSrY +vFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1SERGnEaiNLpoc0dle +TS8wQT/cjw/wPgoeV6OBkDCBjTAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYI +KwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhhbXBsZS5j +b20wPAYDVR0gBDUwMzAPBg0qhkiG9xIEAYS3CQIBMA8GDSqGSIb3EgQBhLcJAgIw +DwYNKoZIhvcSBAGEtwkCAjAKBggqhkjOPQQDAgNHADBEAiBjYDwsWcs35hU/wPqa +5gf0QUMvV/8z5LPX14fB2y4RGQIgMw0ekrt9K5UcgkvFupV/XXIjLRFQvc8URA3C +/+w+2/4= +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_invalid.pem b/tests/policy_leaf_invalid.pem new file mode 100644 index 0000000..de7a5e9 --- /dev/null +++ b/tests/policy_leaf_invalid.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBgjCCASigAwIBAgIBAzAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowGjEYMBYGA1UE +AxMPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkSrY +vFVtkZJmvirfY0JDDYrZQrNJecPLt0ksJux2URL5nAQiQY1SERGnEaiNLpoc0dle +TS8wQT/cjw/wPgoeV6NhMF8wDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQMMAoGCCsG +AQUFBwMBMAwGA1UdEwEB/wQCMAAwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29t +MA4GA1UdIAQHSU5WQUxJRDAKBggqhkjOPQQDAgNIADBFAiAgfcDIeqmV+u5YtUe4 +aBnj13tZAJAQh6ttum1xZ+xHEgIhAJqvGX5c0/d1qYelBlm/jE3UuivijdEjVsLX +GVH+X1VA +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_none.pem b/tests/policy_leaf_none.pem new file mode 100644 index 0000000..13ad7ce --- /dev/null +++ b/tests/policy_leaf_none.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBezCCASCgAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo1EwTzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wCgYIKoZIzj0EAwIDSQAwRgIhAIDFeeYJ8nmYo09OnJFpNS3A6fYO +ZliHkAqOsg193DTnAiEA3OSHLCczcvRjMG+qd/FI61u2sKU1hhHh7uHtD/YO/dA= +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_oid1.pem b/tests/policy_leaf_oid1.pem new file mode 100644 index 0000000..94cd1a7 --- /dev/null +++ b/tests/policy_leaf_oid1.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlTCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIBMAoGCCqGSM49BAMC +A0cAMEQCIHh4Bo8l/HVJhLMWcYusPOE0arqoDrJ5E0M6nEi3nRhgAiAArK8bBohG +fZ3DmVMq/2BJtQZwRRj+50VKWuf9mBSflQ== +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_oid2.pem b/tests/policy_leaf_oid2.pem new file mode 100644 index 0000000..10adf86 --- /dev/null +++ b/tests/policy_leaf_oid2.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQICMAoGCCqGSM49BAMC +A0kAMEYCIQDvW7rdL6MSW/0BPNET4hEeECO6LWmZZHKCHIu6o33dsAIhAPwgm6lD +KV2hMOxkE6rBDQzlCr+zAkQrxSzQZqJp5p+W +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_oid3.pem b/tests/policy_leaf_oid3.pem new file mode 100644 index 0000000..e5c1031 --- /dev/null +++ b/tests/policy_leaf_oid3.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIDMAoGCCqGSM49BAMC +A0kAMEYCIQDBPnPpRsOH20ncg8TKUdlONfbO62WafQj9SKgyi/nGBQIhAMhT8J7f +fTEou6jlAilaIQwlAgZzVKRqgghIHezFY86T +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_oid4.pem b/tests/policy_leaf_oid4.pem new file mode 100644 index 0000000..7dd7a54 --- /dev/null +++ b/tests/policy_leaf_oid4.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIEMAoGCCqGSM49BAMC +A0kAMEYCIQD2gnpCTMxUalCtEV52eXzqeJgsKMYvEpJTuU/VqH5KwQIhAPEavAkt +cSJsgMgJcJnbBzAdSrbOgHXF2etDHmFbg0hz +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_oid5.pem b/tests/policy_leaf_oid5.pem new file mode 100644 index 0000000..2a9aee7 --- /dev/null +++ b/tests/policy_leaf_oid5.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBlzCCATygAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo20wazAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l +BAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAaBgNVHREEEzARgg93d3cuZXhh +bXBsZS5jb20wGgYDVR0gBBMwETAPBg0qhkiG9xIEAYS3CQIFMAoGCCqGSM49BAMC +A0kAMEYCIQDDFVjhlQ1Wu0KITcRX8kELpVDeYSKSlvEbZc3rn1QjkQIhAMPthqBi +I0acz8DPQcdFmHXV0xR2xyC1yuen0gES5WLR +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_require.pem b/tests/policy_leaf_require.pem new file mode 100644 index 0000000..169b844 --- /dev/null +++ b/tests/policy_leaf_require.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo4GNMIGKMA4GA1UdDwEB/wQEAwICBDATBgNV +HSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCD3d3dy5l +eGFtcGxlLmNvbTArBgNVHSAEJDAiMA8GDSqGSIb3EgQBhLcJAgEwDwYNKoZIhvcS +BAGEtwkCAjAMBgNVHSQEBTADgAEAMAoGCCqGSM49BAMCA0kAMEYCIQDrNQPi/mdK +l7Nd/YmMXWYTHJBWWin1zA64Ohkd7z4jGgIhAJpw/umk5MxS1MwSi+YTkkcSQKpl +YROQH6+T53DauoW6 +-----END CERTIFICATE----- diff --git a/tests/policy_leaf_require1.pem b/tests/policy_leaf_require1.pem new file mode 100644 index 0000000..261ef95 --- /dev/null +++ b/tests/policy_leaf_require1.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV2gAwIBAgIBAzAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNQb2xpY3kg +SW50ZXJtZWRpYXRlMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAa +MRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAASRKti8VW2Rkma+Kt9jQkMNitlCs0l5w8u3SSwm7HZREvmcBCJBjVIREacR +qI0umhzR2V5NLzBBP9yPD/A+Ch5Xo4GNMIGKMA4GA1UdDwEB/wQEAwICBDATBgNV +HSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBoGA1UdEQQTMBGCD3d3dy5l +eGFtcGxlLmNvbTArBgNVHSAEJDAiMA8GDSqGSIb3EgQBhLcJAgEwDwYNKoZIhvcS +BAGEtwkCAjAMBgNVHSQEBTADgAEBMAoGCCqGSM49BAMCA0kAMEYCIQCtXENGJrKv +IOeLHO/3Nu/SMRXc69Vb3q+4b/uHBFbuqwIhAK22Wfh/ZIHKu3FwbjL+sN0Z39pf +Dsak6fp1y4tqNuvK +-----END CERTIFICATE----- diff --git a/tests/policy_root.pem b/tests/policy_root.pem new file mode 100644 index 0000000..595f8a1 --- /dev/null +++ b/tests/policy_root.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBdTCCARqgAwIBAgIBATAKBggqhkjOPQQDAjAWMRQwEgYDVQQDEwtQb2xpY3kg +Um9vdDAgFw0wMDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowFjEUMBIGA1UE +AxMLUG9saWN5IFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQmdqXYl1Gv +Y7y3jcTTK6MVXIQr44TqChRYI6IeV9tIB6jIsOY+Qol1bk8x/7A5FGOnUWFVLEAP +EPSJwPndjolto1cwVTAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0lBAwwCgYIKwYBBQUH +AwEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU0GnnoB+yeN63WMthnh6Uh1HH +dRIwCgYIKoZIzj0EAwIDSQAwRgIhAKVxVAaJnmvt+q4SqegGS23QSzKPM9Yakw9e +bOUU9+52AiEAjXPRBdd90YDey4VFu4f/78yVe0cxMK30lll7lLl7TTA= +-----END CERTIFICATE----- diff --git a/tests/policy_root2.pem b/tests/policy_root2.pem new file mode 100644 index 0000000..1350035 --- /dev/null +++ b/tests/policy_root2.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBeDCCAR6gAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1Qb2xpY3kg +Um9vdCAyMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAYMRYwFAYD +VQQDEw1Qb2xpY3kgUm9vdCAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJnal +2JdRr2O8t43E0yujFVyEK+OE6goUWCOiHlfbSAeoyLDmPkKJdW5PMf+wORRjp1Fh +VSxADxD0icD53Y6JbaNXMFUwDgYDVR0PAQH/BAQDAgIEMBMGA1UdJQQMMAoGCCsG +AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNBp56Afsnjet1jLYZ4e +lIdRx3USMAoGCCqGSM49BAMCA0gAMEUCIQDm9rw9ODVtJUPBn2lWoK8s7ElbyY4/ +Gc2thHR50UUzbgIgKRenEDhKiBR6cGC77RaIiaaafW8b7HMd7obuZdDU/58= +-----END CERTIFICATE----- diff --git a/tests/policy_root_cross_inhibit_mapping.pem b/tests/policy_root_cross_inhibit_mapping.pem new file mode 100644 index 0000000..9273a53 --- /dev/null +++ b/tests/policy_root_cross_inhibit_mapping.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBljCCAT2gAwIBAgIBATAKBggqhkjOPQQDAjAYMRYwFAYDVQQDEw1Qb2xpY3kg +Um9vdCAyMCAXDTAwMDEwMTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjAWMRQwEgYD +VQQDEwtQb2xpY3kgUm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCZ2pdiX +Ua9jvLeNxNMroxVchCvjhOoKFFgjoh5X20gHqMiw5j5CiXVuTzH/sDkUY6dRYVUs +QA8Q9InA+d2OiW2jeDB2MA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAKBggrBgEF +BQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTQaeegH7J43rdYy2GeHpSH +Ucd1EjARBgNVHSAECjAIMAYGBFUdIAAwDAYDVR0kBAUwA4EBADAKBggqhkjOPQQD +AgNHADBEAiBzR3JGEf9PITYuiXTx+vx9gXji5idGsVog9wRUbY98wwIgVVeYNQQb +x+RN2wYp3kmm8iswUOrqiI6J4PSzT8CYP8Q= +-----END CERTIFICATE----- diff --git a/tests/poly1305test.c b/tests/poly1305test.c new file mode 100644 index 0000000..3f9af0d --- /dev/null +++ b/tests/poly1305test.c @@ -0,0 +1,169 @@ +/* $OpenBSD: poly1305test.c,v 1.3 2018/07/17 17:06:49 tb Exp $ */ +/* + * Public Domain poly1305 from Andrew Moon + * Based on poly1305-donna.c from: + * https://github.com/floodyberry/poly1305-donna + */ + +#include + +#include + +void poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, + const unsigned char key[32]); + +int poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]); +int poly1305_power_on_self_test(void); + +void +poly1305_auth(unsigned char mac[16], const unsigned char *m, size_t bytes, +const unsigned char key[32]) { + poly1305_context ctx; + CRYPTO_poly1305_init(&ctx, key); + CRYPTO_poly1305_update(&ctx, m, bytes); + CRYPTO_poly1305_finish(&ctx, mac); +} + +int +poly1305_verify(const unsigned char mac1[16], const unsigned char mac2[16]) +{ + size_t i; + unsigned int dif = 0; + for (i = 0; i < 16; i++) + dif |= (mac1[i] ^ mac2[i]); + dif = (dif - 1) >> ((sizeof(unsigned int) * 8) - 1); + return (dif & 1); +} + +/* test a few basic operations */ +int +poly1305_power_on_self_test(void) +{ + /* example from nacl */ + static const unsigned char nacl_key[32] = { + 0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, + 0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25, + 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, + 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80, + }; + + static const unsigned char nacl_msg[131] = { + 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, + 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, + 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, + 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, + 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, + 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, + 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, + 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, + 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, + 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, + 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, + 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, + 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, + 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, + 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, + 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, + 0xe3, 0x55, 0xa5 + }; + + static const unsigned char nacl_mac[16] = { + 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, + 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9 + }; + + /* generates a final value of (2^130 - 2) == 3 */ + static const unsigned char wrap_key[32] = { + 0x02, 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, + }; + + static const unsigned char wrap_msg[16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + static const unsigned char wrap_mac[16] = { + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + /* + mac of the macs of messages of length 0 to 256, where the key and messages + have all their values set to the length + */ + static const unsigned char total_key[32] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + static const unsigned char total_mac[16] = { + 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd, + 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39 + }; + + poly1305_context ctx; + poly1305_context total_ctx; + unsigned char all_key[32]; + unsigned char all_msg[256]; + unsigned char mac[16]; + size_t i, j; + int result = 1; + + for (i = 0; i < sizeof(mac); i++) + mac[i] = 0; + poly1305_auth(mac, nacl_msg, sizeof(nacl_msg), nacl_key); + result &= poly1305_verify(nacl_mac, mac); + + for (i = 0; i < sizeof(mac); i++) + mac[i] = 0; + CRYPTO_poly1305_init(&ctx, nacl_key); + CRYPTO_poly1305_update(&ctx, nacl_msg + 0, 32); + CRYPTO_poly1305_update(&ctx, nacl_msg + 32, 64); + CRYPTO_poly1305_update(&ctx, nacl_msg + 96, 16); + CRYPTO_poly1305_update(&ctx, nacl_msg + 112, 8); + CRYPTO_poly1305_update(&ctx, nacl_msg + 120, 4); + CRYPTO_poly1305_update(&ctx, nacl_msg + 124, 2); + CRYPTO_poly1305_update(&ctx, nacl_msg + 126, 1); + CRYPTO_poly1305_update(&ctx, nacl_msg + 127, 1); + CRYPTO_poly1305_update(&ctx, nacl_msg + 128, 1); + CRYPTO_poly1305_update(&ctx, nacl_msg + 129, 1); + CRYPTO_poly1305_update(&ctx, nacl_msg + 130, 1); + CRYPTO_poly1305_finish(&ctx, mac); + result &= poly1305_verify(nacl_mac, mac); + + for (i = 0; i < sizeof(mac); i++) + mac[i] = 0; + poly1305_auth(mac, wrap_msg, sizeof(wrap_msg), wrap_key); + result &= poly1305_verify(wrap_mac, mac); + + CRYPTO_poly1305_init(&total_ctx, total_key); + for (i = 0; i < 256; i++) { + /* set key and message to 'i,i,i..' */ + for (j = 0; j < sizeof(all_key); j++) + all_key[j] = i; + for (j = 0; j < i; j++) + all_msg[j] = i; + poly1305_auth(mac, all_msg, i, all_key); + CRYPTO_poly1305_update(&total_ctx, mac, 16); + } + CRYPTO_poly1305_finish(&total_ctx, mac); + result &= poly1305_verify(total_mac, mac); + + return result; +} + +int +main(int argc, char **argv) +{ + if (!poly1305_power_on_self_test()) { + fprintf(stderr, "One or more self tests failed!\n"); + return 1; + } + + return 0; +} diff --git a/tests/pq_expected.txt b/tests/pq_expected.txt new file mode 100644 index 0000000..c59d6cd --- /dev/null +++ b/tests/pq_expected.txt @@ -0,0 +1,3 @@ +item 6966726167696c69 +item 7374696365787069 +item 737570657263616c diff --git a/tests/pq_test.c b/tests/pq_test.c new file mode 100644 index 0000000..a078ba5 --- /dev/null +++ b/tests/pq_test.c @@ -0,0 +1,118 @@ +/* crypto/pqueue/pq_test.c */ +/* + * DTLS implementation written by Nagendra Modadugu + * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. + */ +/* ==================================================================== + * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#include +#include +#include +#include "pqueue.h" + +/* remember to change expected.txt if you change these values */ +unsigned char prio1[8] = "supercal"; +unsigned char prio2[8] = "ifragili"; +unsigned char prio3[8] = "sticexpi"; + +static void +pqueue_print(pqueue pq) +{ + pitem *iter, *item; + + iter = pqueue_iterator(pq); + for (item = pqueue_next(&iter); item != NULL; + item = pqueue_next(&iter)) { + printf("item\t%02x%02x%02x%02x%02x%02x%02x%02x\n", + item->priority[0], item->priority[1], + item->priority[2], item->priority[3], + item->priority[4], item->priority[5], + item->priority[6], item->priority[7]); + } +} + +int +main(void) +{ + pitem *item; + pqueue pq; + + pq = pqueue_new(); + + item = pitem_new(prio3, NULL); + pqueue_insert(pq, item); + + item = pitem_new(prio1, NULL); + pqueue_insert(pq, item); + + item = pitem_new(prio2, NULL); + pqueue_insert(pq, item); + + item = pqueue_find(pq, prio1); + fprintf(stderr, "found %p\n", item->priority); + + item = pqueue_find(pq, prio2); + fprintf(stderr, "found %p\n", item->priority); + + item = pqueue_find(pq, prio3); + fprintf(stderr, "found %p\n", item ? item->priority: 0); + + pqueue_print(pq); + + for (item = pqueue_pop(pq); item != NULL; item = pqueue_pop(pq)) + pitem_free(item); + + pqueue_free(pq); + return 0; +} diff --git a/tests/quictest.c b/tests/quictest.c new file mode 100644 index 0000000..cdd4b23 --- /dev/null +++ b/tests/quictest.c @@ -0,0 +1,339 @@ +/* $OpenBSD: quictest.c,v 1.1 2022/08/27 09:16:29 jsing Exp $ */ +/* + * Copyright (c) 2020, 2021, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +const char *server_ca_file; +const char *server_cert_file; +const char *server_key_file; + +int debug = 0; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +struct quic_data { + enum ssl_encryption_level_t rlevel; + enum ssl_encryption_level_t wlevel; + BIO *rbio; + BIO *wbio; +}; + +static int +quic_set_read_secret(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) +{ + struct quic_data *qd = SSL_get_app_data(ssl); + + qd->rlevel = level; + + return 1; +} + +static int +quic_set_write_secret(SSL *ssl, enum ssl_encryption_level_t level, + const SSL_CIPHER *cipher, const uint8_t *secret, size_t secret_len) +{ + struct quic_data *qd = SSL_get_app_data(ssl); + + qd->wlevel = level; + + return 1; +} + +static int +quic_read_handshake_data(SSL *ssl) +{ + struct quic_data *qd = SSL_get_app_data(ssl); + uint8_t buf[2048]; + int ret; + + if ((ret = BIO_read(qd->rbio, buf, sizeof(buf))) > 0) { + if (debug > 1) { + fprintf(stderr, "== quic_read_handshake_data ==\n"); + hexdump(buf, ret); + } + if (!SSL_provide_quic_data(ssl, qd->rlevel, buf, ret)) + return -1; + } + + return 1; +} + +static int +quic_add_handshake_data(SSL *ssl, enum ssl_encryption_level_t level, + const uint8_t *data, size_t len) +{ + struct quic_data *qd = SSL_get_app_data(ssl); + int ret; + + if (debug > 1) { + fprintf(stderr, "== quic_add_handshake_data\n"); + hexdump(data, len); + } + + if ((ret = BIO_write(qd->wbio, data, len)) <= 0) + return 0; + + return (size_t)ret == len; +} + +static int +quic_flush_flight(SSL *ssl) +{ + return 1; +} + +static int +quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level, uint8_t alert) +{ + return 1; +} + +const SSL_QUIC_METHOD quic_method = { + .set_read_secret = quic_set_read_secret, + .set_write_secret = quic_set_write_secret, + .add_handshake_data = quic_add_handshake_data, + .flush_flight = quic_flush_flight, + .send_alert = quic_send_alert, +}; + +static SSL * +quic_client(struct quic_data *data) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "client context"); + + if (!SSL_CTX_set_quic_method(ssl_ctx, &quic_method)) { + fprintf(stderr, "FAIL: Failed to set QUIC method\n"); + goto failure; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "client ssl"); + + SSL_set_connect_state(ssl); + SSL_set_app_data(ssl, data); + + failure: + SSL_CTX_free(ssl_ctx); + + return ssl; +} + +static SSL * +quic_server(struct quic_data *data) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "server context"); + + SSL_CTX_set_dh_auto(ssl_ctx, 2); + + if (SSL_CTX_use_certificate_file(ssl_ctx, server_cert_file, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "FAIL: Failed to load server certificate\n"); + goto failure; + } + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key_file, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "FAIL: Failed to load server private key\n"); + goto failure; + } + + if (!SSL_CTX_set_quic_method(ssl_ctx, &quic_method)) { + fprintf(stderr, "FAIL: Failed to set QUIC method\n"); + goto failure; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "server ssl"); + + SSL_set_accept_state(ssl); + SSL_set_app_data(ssl, data); + + failure: + SSL_CTX_free(ssl_ctx); + + return ssl; +} + +static int +ssl_error(SSL *ssl, const char *name, const char *desc, int ssl_ret) +{ + int ssl_err; + + ssl_err = SSL_get_error(ssl, ssl_ret); + + if (ssl_err == SSL_ERROR_WANT_READ) { + if (quic_read_handshake_data(ssl) < 0) + return 0; + return 1; + } else if (ssl_err == SSL_ERROR_WANT_WRITE) { + return 1; + } else if (ssl_err == SSL_ERROR_SYSCALL && errno == 0) { + /* Yup, this is apparently a thing... */ + } else { + fprintf(stderr, "FAIL: %s %s failed - ssl err = %d, errno = %d\n", + name, desc, ssl_err, errno); + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} + +static int +do_handshake(SSL *ssl, const char *name, int *done) +{ + int ssl_ret; + + if ((ssl_ret = SSL_do_handshake(ssl)) == 1) { + fprintf(stderr, "INFO: %s handshake done\n", name); + *done = 1; + return 1; + } + + return ssl_error(ssl, name, "handshake", ssl_ret); +} + +typedef int (*ssl_func)(SSL *ssl, const char *name, int *done); + +static int +do_client_server_loop(SSL *client, ssl_func client_func, SSL *server, + ssl_func server_func) +{ + int client_done = 0, server_done = 0; + int i = 0; + + do { + if (!client_done) { + if (debug) + fprintf(stderr, "DEBUG: client loop\n"); + if (!client_func(client, "client", &client_done)) + return 0; + } + if (!server_done) { + if (debug) + fprintf(stderr, "DEBUG: server loop\n"); + if (!server_func(server, "server", &server_done)) + return 0; + } + } while (i++ < 100 && (!client_done || !server_done)); + + if (!client_done || !server_done) + fprintf(stderr, "FAIL: gave up\n"); + + return client_done && server_done; +} + +static int +quictest(void) +{ + struct quic_data *client_data = NULL, *server_data = NULL; + BIO *client_wbio = NULL, *server_wbio = NULL; + SSL *client = NULL, *server = NULL; + int failed = 1; + + if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) + goto failure; + + if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) + goto failure; + if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) + goto failure; + + if ((client_data = calloc(1, sizeof(*client_data))) == NULL) + goto failure; + + client_data->rbio = server_wbio; + client_data->wbio = client_wbio; + + if ((client = quic_client(client_data)) == NULL) + goto failure; + + if ((server_data = calloc(1, sizeof(*server_data))) == NULL) + goto failure; + + server_data->rbio = client_wbio; + server_data->wbio = server_wbio; + + if ((server = quic_server(server_data)) == NULL) + goto failure; + + if (!do_client_server_loop(client, do_handshake, server, do_handshake)) { + fprintf(stderr, "FAIL: client and server handshake failed\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + fprintf(stderr, "INFO: Done!\n"); + + failed = 0; + + failure: + BIO_free(client_wbio); + BIO_free(server_wbio); + + free(client_data); + free(server_data); + + SSL_free(client); + SSL_free(server); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + if (argc != 4) { + fprintf(stderr, "usage: %s keyfile certfile cafile\n", + argv[0]); + exit(1); + } + + server_key_file = argv[1]; + server_cert_file = argv[2]; + server_ca_file = argv[3]; + + failed |= quictest(); + + return failed; +} diff --git a/tests/randtest.c b/tests/randtest.c new file mode 100644 index 0000000..d0f02ad --- /dev/null +++ b/tests/randtest.c @@ -0,0 +1,204 @@ +/* $OpenBSD: randtest.c,v 1.3 2018/07/17 17:06:49 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#include +#include + +#undef LIBRESSL_INTERNAL /* Needed to get RAND_pseudo_bytes(). */ +#include + +/* some FIPS 140-1 random number test */ +/* some simple tests */ + +int main(int argc,char **argv) + { + unsigned char buf[2500]; + int i,j,k,s,sign,nsign,err=0; + unsigned long n1; + unsigned long n2[16]; + unsigned long runs[2][34]; + /*double d; */ + long d; + + i = RAND_pseudo_bytes(buf,2500); + if (i < 0) + { + printf ("init failed, the rand method is not properly installed\n"); + err++; + goto err; + } + + n1=0; + for (i=0; i<16; i++) n2[i]=0; + for (i=0; i<34; i++) runs[0][i]=runs[1][i]=0; + + /* test 1 and 2 */ + sign=0; + nsign=0; + for (i=0; i<2500; i++) + { + j=buf[i]; + + n2[j&0x0f]++; + n2[(j>>4)&0x0f]++; + + for (k=0; k<8; k++) + { + s=(j&0x01); + if (s == sign) + nsign++; + else + { + if (nsign > 34) nsign=34; + if (nsign != 0) + { + runs[sign][nsign-1]++; + if (nsign > 6) + runs[sign][5]++; + } + sign=s; + nsign=1; + } + + if (s) n1++; + j>>=1; + } + } + if (nsign > 34) nsign=34; + if (nsign != 0) runs[sign][nsign-1]++; + + /* test 1 */ + if (!((9654 < n1) && (n1 < 10346))) + { + printf("test 1 failed, X=%lu\n",n1); + err++; + } + printf("test 1 done\n"); + + /* test 2 */ + d=0; + for (i=0; i<16; i++) + d+=n2[i]*n2[i]; + d=(d*8)/25-500000; + if (!((103 < d) && (d < 5740))) + { + printf("test 2 failed, X=%ld.%02ld\n",d/100L,d%100L); + err++; + } + printf("test 2 done\n"); + + /* test 3 */ + for (i=0; i<2; i++) + { + if (!((2267 < runs[i][0]) && (runs[i][0] < 2733))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,1,runs[i][0]); + err++; + } + if (!((1079 < runs[i][1]) && (runs[i][1] < 1421))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,2,runs[i][1]); + err++; + } + if (!(( 502 < runs[i][2]) && (runs[i][2] < 748))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,3,runs[i][2]); + err++; + } + if (!(( 223 < runs[i][3]) && (runs[i][3] < 402))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,4,runs[i][3]); + err++; + } + if (!(( 90 < runs[i][4]) && (runs[i][4] < 223))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,5,runs[i][4]); + err++; + } + if (!(( 90 < runs[i][5]) && (runs[i][5] < 223))) + { + printf("test 3 failed, bit=%d run=%d num=%lu\n", + i,6,runs[i][5]); + err++; + } + } + printf("test 3 done\n"); + + /* test 4 */ + if (runs[0][33] != 0) + { + printf("test 4 failed, bit=%d run=%d num=%lu\n", + 0,34,runs[0][33]); + err++; + } + if (runs[1][33] != 0) + { + printf("test 4 failed, bit=%d run=%d num=%lu\n", + 1,34,runs[1][33]); + err++; + } + printf("test 4 done\n"); + err: + err=((err)?1:0); + exit(err); + } diff --git a/tests/rc2_test.c b/tests/rc2_test.c new file mode 100644 index 0000000..2e503c5 --- /dev/null +++ b/tests/rc2_test.c @@ -0,0 +1,917 @@ +/* $OpenBSD: rc2_test.c,v 1.6 2022/11/09 12:13:08 joshua Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct rc2_test { + const int mode; + const uint8_t key[64]; + const int key_len; + const int key_bits; + const uint8_t iv[64]; + const int iv_len; + const uint8_t in[64]; + const int in_len; + const uint8_t out[64]; + const int out_len; + const int padding; +}; + +static const struct rc2_test rc2_tests[] = { + /* ECB (Test vectors from RFC 2268) */ + { + .mode = NID_rc2_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .key_bits = 63, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + .key_len = 8, + .key_bits = 64, + .in = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + .in_len = 8, + .out = { + 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .key_bits = 64, + .in = { + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + .in_len = 8, + .out = { + 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x88, + }, + .key_len = 1, + .key_bits = 64, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, + }, + .key_len = 7, + .key_bits = 64, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2, + }, + .key_len = 16, + .key_bits = 64, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2, + }, + .key_len = 16, + .key_bits = 128, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2, + 0x16, 0xf8, 0x0a, 0x6f, 0x85, 0x92, 0x05, 0x84, + 0xc4, 0x2f, 0xce, 0xb0, 0xbe, 0x25, 0x5d, 0xaf, + 0x1e, + }, + .key_len = 33, + .key_bits = 129, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x5b, 0x78, 0xd3, 0xa4, 0x3d, 0xff, 0xf1, 0xf1, + }, + .out_len = 8, + }, + + /* ECB (Test vectors from http://websites.umich.edu/~x509/ssleay/rrc2.html) */ + { + .mode = NID_rc2_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 16, + .key_bits = 1024, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x1c, 0x19, 0x8a, 0x83, 0x8d, 0xf0, 0x28, 0xb7, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + .key_len = 16, + .key_bits = 1024, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x21, 0x82, 0x9C, 0x78, 0xA9, 0xF9, 0xC0, 0x74, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 16, + .key_bits = 1024, + .in = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + .in_len = 8, + .out = { + 0x13, 0xdb, 0x35, 0x17, 0xd3, 0x21, 0x86, 0x9e, + }, + .out_len = 8, + }, + { + .mode = NID_rc2_ecb, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 1024, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 8, + .out = { + 0x50, 0xdc, 0x01, 0x62, 0xbd, 0x75, 0x7f, 0x31, + }, + .out_len = 8, + }, + + /* CBC (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_rc2_cbc, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .key_bits = 64, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff, + 0xf0, 0x51, 0x77, 0x8b, 0x65, 0xdb, 0x13, 0x57, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x9c, 0x4b, 0xfe, 0x6d, 0xfe, 0x73, 0x9c, 0x2b, + 0x52, 0x8f, 0xc8, 0x47, 0x2b, 0x66, 0xf9, 0x70, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0x8b, 0x11, 0x08, 0x1c, 0xf0, 0xa0, 0x86, 0xe9, + 0x60, 0x57, 0x69, 0x5d, 0xdd, 0x42, 0x38, 0xe3, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cbc, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0x9c, 0x4b, 0xfe, 0x6d, 0xfe, 0x73, 0x9c, 0x2b, + 0x29, 0xf1, 0x7a, 0xd2, 0x16, 0xa0, 0xb2, 0xc6, + 0xd1, 0xa2, 0x31, 0xbe, 0xa3, 0x94, 0xc6, 0xb0, + 0x81, 0x22, 0x27, 0x17, 0x5b, 0xd4, 0x6d, 0x29, + }, + .out_len = 32, + }, + + /* CFB64 (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_rc2_cfb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .key_bits = 64, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff, + 0xf0, 0x51, 0x77, 0x8b, 0x65, 0xdb, 0x13, 0x57, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x9c, 0x4b, 0xfe, 0x6d, 0xfe, 0x73, 0x9c, 0x2b, + 0x52, 0x8f, 0xc8, 0x47, 0x2b, 0x66, 0xf9, 0x70, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0x9c, 0x4a, 0xfc, 0x6e, 0xfa, 0x76, 0x9a, 0x2c, + 0xeb, 0xdf, 0x25, 0xb0, 0x15, 0x8b, 0x6a, 0x2a, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_cfb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0x8b, 0x10, 0x0a, 0x1f, 0xf4, 0xa5, 0x80, 0xee, + 0x94, 0x4d, 0xc3, 0xcd, 0x26, 0x79, 0x81, 0xc0, + 0xe9, 0x3e, 0x20, 0x85, 0x11, 0x71, 0x61, 0x2a, + 0x1d, 0x4c, 0x8a, 0xe2, 0xb7, 0x0a, 0xa8, 0xcf, + }, + .out_len = 32, + }, + + /* OFB64 (generated using https://github.com/joshuasing/libressl-test-gen) */ + { + .mode = NID_rc2_ofb64, + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .key_bits = 64, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff, + 0xf0, 0x51, 0x77, 0x8b, 0x65, 0xdb, 0x13, 0x57, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .in_len = 16, + .out = { + 0x9c, 0x4b, 0xfe, 0x6d, 0xfe, 0x73, 0x9c, 0x2b, + 0x52, 0x8f, 0xc8, 0x47, 0x2b, 0x66, 0xf9, 0x70, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .iv_len = 8, + .in = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .in_len = 16, + .out = { + 0x9c, 0x4a, 0xfc, 0x6e, 0xfa, 0x76, 0x9a, 0x2c, + 0x5a, 0x86, 0xc2, 0x4c, 0x27, 0x6b, 0xf7, 0x7f, + }, + .out_len = 16, + }, + { + .mode = NID_rc2_ofb64, + .key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + }, + .key_len = 16, + .key_bits = 128, + .iv = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + }, + .iv_len = 8, + .in = { + 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, + }, + .in_len = 32, + .out = { + 0x8b, 0x10, 0x0a, 0x1f, 0xf4, 0xa5, 0x80, 0xee, + 0xfa, 0x1d, 0x1a, 0x7c, 0xb2, 0x93, 0x00, 0x9d, + 0x36, 0xa1, 0xff, 0x3a, 0x77, 0x1d, 0x00, 0x9b, + 0x20, 0xde, 0x5f, 0x93, 0xcc, 0x3e, 0x51, 0xaa, + }, + .out_len = 32, + }, +}; + +#define N_RC2_TESTS (sizeof(rc2_tests) / sizeof(rc2_tests[0])) + +static int +rc2_ecb_test(size_t test_number, const struct rc2_test *rt) +{ + RC2_KEY key; + uint8_t out[8]; + + /* Encryption */ + memset(out, 0, sizeof(out)); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_ecb_encrypt(rt->in, out, &key, 1); + + if (memcmp(rt->out, out, rt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_rc2_ecb, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_ecb_encrypt(rt->out, out, &key, 0); + + if (memcmp(rt->in, out, rt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_rc2_ecb, test_number); + return 0; + } + + return 1; +} + +static int +rc2_cbc_test(size_t test_number, const struct rc2_test *rt) +{ + RC2_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_cbc_encrypt(rt->in, out, rt->in_len, &key, iv, 1); + + if (memcmp(rt->out, out, rt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_cbc_encrypt(rt->out, out, rt->out_len, &key, iv, 0); + + if (memcmp(rt->in, out, rt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + return 1; +} + +static int +rc2_cfb64_test(size_t test_number, const struct rc2_test *rt) +{ + RC2_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + int remainder = 0; + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_cfb64_encrypt(rt->in, out, rt->in_len * 8, &key, iv, &remainder, 1); + + if (memcmp(rt->out, out, rt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_cfb64_encrypt(rt->out, out, rt->out_len, &key, iv, &remainder, 0); + + if (memcmp(rt->in, out, rt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + return 1; +} + +static int +rc2_ofb64_test(size_t test_number, const struct rc2_test *rt) +{ + RC2_KEY key; + uint8_t out[512]; + uint8_t iv[64]; + int remainder = 0; + + /* Encryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_ofb64_encrypt(rt->in, out, rt->in_len, &key, iv, &remainder); + + if (memcmp(rt->out, out, rt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): encryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + memcpy(iv, rt->iv, rt->iv_len); + RC2_set_key(&key, rt->key_len, rt->key, rt->key_bits); + RC2_ofb64_encrypt(rt->out, out, rt->out_len, &key, iv, &remainder); + + if (memcmp(rt->in, out, rt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): decryption mismatch\n", + SN_rc2_cbc, test_number); + return 0; + } + + return 1; +} + +static int +rc2_evp_test(size_t test_number, const struct rc2_test *rt, const char *label, + const EVP_CIPHER *cipher) +{ + EVP_CIPHER_CTX *ctx; + uint8_t out[512]; + int in_len, out_len, total_len; + int i; + int success = 0; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_new failed\n", + label, test_number); + goto failed; + } + + /* EVP encryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_EncryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, + rt->key_bits, NULL) <= 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, rt->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_EncryptInit(ctx, NULL, rt->key, rt->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < rt->in_len;) { + in_len = arc4random_uniform(rt->in_len / 2); + if (in_len > rt->in_len - i) + in_len = rt->in_len - i; + + if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len, + rt->in + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_EncryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_EncryptFinal_ex(ctx, out + out_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_EncryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != rt->out_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP encryption length mismatch\n", + label, test_number); + goto failed; + } + + if (memcmp(rt->out, out, rt->out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP encryption mismatch\n", + label, test_number); + goto failed; + } + + /* EVP decryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_DecryptInit(ctx, cipher, NULL, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, + rt->key_bits, NULL) <= 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP_CIPHER_CTX_ctrl failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_key_length(ctx, rt->key_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_key_length failed\n", + label, test_number); + goto failed; + } + + if (!EVP_CIPHER_CTX_set_padding(ctx, rt->padding)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_set_padding failed\n", + label, test_number); + goto failed; + } + + if (!EVP_DecryptInit(ctx, NULL, rt->key, rt->iv)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptInit failed\n", + label, test_number); + goto failed; + } + + for (i = 0; i < rt->out_len;) { + in_len = arc4random_uniform(rt->out_len / 2); + if (in_len > rt->out_len - i) + in_len = rt->out_len - i; + + if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len, + rt->out + i, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DecryptUpdate failed\n", + label, test_number); + goto failed; + } + + i += in_len; + total_len += out_len; + } + + if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_DecryptFinal_ex failed\n", + label, test_number); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_CIPHER_CTX_reset failed\n", + label, test_number); + goto failed; + } + + if (total_len != rt->in_len) { + fprintf(stderr, + "FAIL (%s:%zu): EVP decryption length mismatch\n", + label, test_number); + goto failed; + } + + if (memcmp(rt->in, out, rt->in_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP decryption mismatch\n", + label, test_number); + goto failed; + } + + success = 1; + + failed: + EVP_CIPHER_CTX_free(ctx); + return success; +} + +static int +rc2_test(void) +{ + const struct rc2_test *rt; + const char *label; + const EVP_CIPHER *cipher; + size_t i; + int failed = 1; + + for (i = 0; i < N_RC2_TESTS; i++) { + rt = &rc2_tests[i]; + switch (rt->mode) { + case NID_rc2_ecb: + label = SN_rc2_ecb; + cipher = EVP_rc2_ecb(); + if (!rc2_ecb_test(i, rt)) + goto failed; + break; + case NID_rc2_cbc: + label = SN_rc2_cbc; + cipher = EVP_rc2_cbc(); + if (!rc2_cbc_test(i, rt)) + goto failed; + break; + case NID_rc2_cfb64: + label = SN_rc2_cfb64; + cipher = EVP_rc2_cfb64(); + if (!rc2_cfb64_test(i, rt)) + goto failed; + break; + case NID_rc2_ofb64: + label = SN_rc2_ofb64; + cipher = EVP_rc2_ofb(); + if (!rc2_ofb64_test(i, rt)) + goto failed; + break; + default: + fprintf(stderr, "FAIL: unknown mode (%d)\n", + rt->mode); + goto failed; + } + + if (!rc2_evp_test(i, rt, label, cipher)) + goto failed; + } + + failed = 0; + + failed: + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= rc2_test(); + + return failed; +} diff --git a/tests/rc4_test.c b/tests/rc4_test.c new file mode 100644 index 0000000..fc4c65f --- /dev/null +++ b/tests/rc4_test.c @@ -0,0 +1,479 @@ +/* $OpenBSD: rc4_test.c,v 1.6 2022/11/09 12:10:17 joshua Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct rc4_test { + const uint8_t key[32]; + const int key_len; + const int len; + const uint8_t in[512]; + const uint8_t out[512]; +}; + +static const struct rc4_test rc4_tests[] = { + /* + * Test vectors from RFC 6229, with 40 and 128-bit keys. + * Note that this only uses the first 32 bytes of each test vector due + * to stream offsets. + */ + { + .key = { + 0x01, 0x02, 0x03, 0x04, 0x05, + }, + .key_len = 5, + .len = 32, + .in = { + 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, + }, + .out = { + 0xb2, 0x39, 0x63, 0x05, 0xf0, 0x3d, 0xc0, 0x27, + 0xcc, 0xc3, 0x52, 0x4a, 0x0a, 0x11, 0x18, 0xa8, + 0x69, 0x82, 0x94, 0x4f, 0x18, 0xfc, 0x82, 0xd5, + 0x89, 0xc4, 0x03, 0xa4, 0x7a, 0x0d, 0x09, 0x19, + }, + }, + { + .key = { + 0x83, 0x32, 0x22, 0x77, 0x2a, + }, + .key_len = 5, + .len = 32, + .in = { + 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, + }, + .out = { + 0x80, 0xad, 0x97, 0xbd, 0xc9, 0x73, 0xdf, 0x8a, + 0x2e, 0x87, 0x9e, 0x92, 0xa4, 0x97, 0xef, 0xda, + 0x20, 0xf0, 0x60, 0xc2, 0xf2, 0xe5, 0x12, 0x65, + 0x01, 0xd3, 0xd4, 0xfe, 0xa1, 0x0d, 0x5f, 0xc0, + }, + }, + { + .key = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + }, + .key_len = 16, + .len = 32, + .in = { + 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, + }, + .out = { + 0x9a, 0xc7, 0xcc, 0x9a, 0x60, 0x9d, 0x1e, 0xf7, + 0xb2, 0x93, 0x28, 0x99, 0xcd, 0xe4, 0x1b, 0x97, + 0x52, 0x48, 0xc4, 0x95, 0x90, 0x14, 0x12, 0x6a, + 0x6e, 0x8a, 0x84, 0xf1, 0x1d, 0x1a, 0x9e, 0x1c, + }, + }, + { + .key = { + 0xeb, 0xb4, 0x62, 0x27, 0xc6, 0xcc, 0x8b, 0x37, + 0x64, 0x19, 0x10, 0x83, 0x32, 0x22, 0x77, 0x2a, + }, + .key_len = 16, + .len = 32, + .in = { + 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, + }, + .out = { + 0x72, 0x0c, 0x94, 0xb6, 0x3e, 0xdf, 0x44, 0xe1, + 0x31, 0xd9, 0x50, 0xca, 0x21, 0x1a, 0x5a, 0x30, + 0xc3, 0x66, 0xfd, 0xea, 0xcf, 0x9c, 0xa8, 0x04, + 0x36, 0xbe, 0x7c, 0x35, 0x84, 0x24, 0xd2, 0x0b, + }, + }, + + /* + * Test vectors from the original cypherpunk posting of ARC4: + * https://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0?pli=1 + */ + { + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + }, + .key_len = 8, + .len = 8, + .in = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + }, + .out = { + 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96, + }, + }, + { + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + }, + .key_len = 8, + .len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .out = { + 0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79, + }, + }, + { + .key = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .key_len = 8, + .len = 8, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .out = { + 0xde, 0x18, 0x89, 0x41, 0xa3, 0x37, 0x5d, 0x3a, + }, + }, + { + .key = { + 0xef, 0x01, 0x23, 0x45, + }, + .key_len = 4, + .len = 10, + .in = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + }, + .out = { + 0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, + 0xbd, 0x61, + }, + }, + { + .key = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + }, + .key_len = 8, + .len = 512, + .in = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + }, + .out = { + 0x75, 0x95, 0xc3, 0xe6, 0x11, 0x4a, 0x09, 0x78, + 0x0c, 0x4a, 0xd4, 0x52, 0x33, 0x8e, 0x1f, 0xfd, + 0x9a, 0x1b, 0xe9, 0x49, 0x8f, 0x81, 0x3d, 0x76, + 0x53, 0x34, 0x49, 0xb6, 0x77, 0x8d, 0xca, 0xd8, + 0xc7, 0x8a, 0x8d, 0x2b, 0xa9, 0xac, 0x66, 0x08, + 0x5d, 0x0e, 0x53, 0xd5, 0x9c, 0x26, 0xc2, 0xd1, + 0xc4, 0x90, 0xc1, 0xeb, 0xbe, 0x0c, 0xe6, 0x6d, + 0x1b, 0x6b, 0x1b, 0x13, 0xb6, 0xb9, 0x19, 0xb8, + 0x47, 0xc2, 0x5a, 0x91, 0x44, 0x7a, 0x95, 0xe7, + 0x5e, 0x4e, 0xf1, 0x67, 0x79, 0xcd, 0xe8, 0xbf, + 0x0a, 0x95, 0x85, 0x0e, 0x32, 0xaf, 0x96, 0x89, + 0x44, 0x4f, 0xd3, 0x77, 0x10, 0x8f, 0x98, 0xfd, + 0xcb, 0xd4, 0xe7, 0x26, 0x56, 0x75, 0x00, 0x99, + 0x0b, 0xcc, 0x7e, 0x0c, 0xa3, 0xc4, 0xaa, 0xa3, + 0x04, 0xa3, 0x87, 0xd2, 0x0f, 0x3b, 0x8f, 0xbb, + 0xcd, 0x42, 0xa1, 0xbd, 0x31, 0x1d, 0x7a, 0x43, + 0x03, 0xdd, 0xa5, 0xab, 0x07, 0x88, 0x96, 0xae, + 0x80, 0xc1, 0x8b, 0x0a, 0xf6, 0x6d, 0xff, 0x31, + 0x96, 0x16, 0xeb, 0x78, 0x4e, 0x49, 0x5a, 0xd2, + 0xce, 0x90, 0xd7, 0xf7, 0x72, 0xa8, 0x17, 0x47, + 0xb6, 0x5f, 0x62, 0x09, 0x3b, 0x1e, 0x0d, 0xb9, + 0xe5, 0xba, 0x53, 0x2f, 0xaf, 0xec, 0x47, 0x50, + 0x83, 0x23, 0xe6, 0x71, 0x32, 0x7d, 0xf9, 0x44, + 0x44, 0x32, 0xcb, 0x73, 0x67, 0xce, 0xc8, 0x2f, + 0x5d, 0x44, 0xc0, 0xd0, 0x0b, 0x67, 0xd6, 0x50, + 0xa0, 0x75, 0xcd, 0x4b, 0x70, 0xde, 0xdd, 0x77, + 0xeb, 0x9b, 0x10, 0x23, 0x1b, 0x6b, 0x5b, 0x74, + 0x13, 0x47, 0x39, 0x6d, 0x62, 0x89, 0x74, 0x21, + 0xd4, 0x3d, 0xf9, 0xb4, 0x2e, 0x44, 0x6e, 0x35, + 0x8e, 0x9c, 0x11, 0xa9, 0xb2, 0x18, 0x4e, 0xcb, + 0xef, 0x0c, 0xd8, 0xe7, 0xa8, 0x77, 0xef, 0x96, + 0x8f, 0x13, 0x90, 0xec, 0x9b, 0x3d, 0x35, 0xa5, + 0x58, 0x5c, 0xb0, 0x09, 0x29, 0x0e, 0x2f, 0xcd, + 0xe7, 0xb5, 0xec, 0x66, 0xd9, 0x08, 0x4b, 0xe4, + 0x40, 0x55, 0xa6, 0x19, 0xd9, 0xdd, 0x7f, 0xc3, + 0x16, 0x6f, 0x94, 0x87, 0xf7, 0xcb, 0x27, 0x29, + 0x12, 0x42, 0x64, 0x45, 0x99, 0x85, 0x14, 0xc1, + 0x5d, 0x53, 0xa1, 0x8c, 0x86, 0x4c, 0xe3, 0xa2, + 0xb7, 0x55, 0x57, 0x93, 0x98, 0x81, 0x26, 0x52, + 0x0e, 0xac, 0xf2, 0xe3, 0x06, 0x6e, 0x23, 0x0c, + 0x91, 0xbe, 0xe4, 0xdd, 0x53, 0x04, 0xf5, 0xfd, + 0x04, 0x05, 0xb3, 0x5b, 0xd9, 0x9c, 0x73, 0x13, + 0x5d, 0x3d, 0x9b, 0xc3, 0x35, 0xee, 0x04, 0x9e, + 0xf6, 0x9b, 0x38, 0x67, 0xbf, 0x2d, 0x7b, 0xd1, + 0xea, 0xa5, 0x95, 0xd8, 0xbf, 0xc0, 0x06, 0x6f, + 0xf8, 0xd3, 0x15, 0x09, 0xeb, 0x0c, 0x6c, 0xaa, + 0x00, 0x6c, 0x80, 0x7a, 0x62, 0x3e, 0xf8, 0x4c, + 0x3d, 0x33, 0xc1, 0x95, 0xd2, 0x3e, 0xe3, 0x20, + 0xc4, 0x0d, 0xe0, 0x55, 0x81, 0x57, 0xc8, 0x22, + 0xd4, 0xb8, 0xc5, 0x69, 0xd8, 0x49, 0xae, 0xd5, + 0x9d, 0x4e, 0x0f, 0xd7, 0xf3, 0x79, 0x58, 0x6b, + 0x4b, 0x7f, 0xf6, 0x84, 0xed, 0x6a, 0x18, 0x9f, + 0x74, 0x86, 0xd4, 0x9b, 0x9c, 0x4b, 0xad, 0x9b, + 0xa2, 0x4b, 0x96, 0xab, 0xf9, 0x24, 0x37, 0x2c, + 0x8a, 0x8f, 0xff, 0xb1, 0x0d, 0x55, 0x35, 0x49, + 0x00, 0xa7, 0x7a, 0x3d, 0xb5, 0xf2, 0x05, 0xe1, + 0xb9, 0x9f, 0xcd, 0x86, 0x60, 0x86, 0x3a, 0x15, + 0x9a, 0xd4, 0xab, 0xe4, 0x0f, 0xa4, 0x89, 0x34, + 0x16, 0x3d, 0xdd, 0xe5, 0x42, 0xa6, 0x58, 0x55, + 0x40, 0xfd, 0x68, 0x3c, 0xbf, 0xd8, 0xc0, 0x0f, + 0x12, 0x12, 0x9a, 0x28, 0x4d, 0xea, 0xcc, 0x4c, + 0xde, 0xfe, 0x58, 0xbe, 0x71, 0x37, 0x54, 0x1c, + 0x04, 0x71, 0x26, 0xc8, 0xd4, 0x9e, 0x27, 0x55, + 0xab, 0x18, 0x1a, 0xb7, 0xe9, 0x40, 0xb0, 0xc0, + }, + }, +}; + +#define N_RC4_TESTS (sizeof(rc4_tests) / sizeof(rc4_tests[0])) + +static int +rc4_test(void) +{ + const struct rc4_test *rt; + RC4_KEY key; + EVP_CIPHER_CTX *ctx = NULL; + const EVP_CIPHER *cipher; + uint8_t out[512]; + int in_len, out_len, total_len; + size_t i; + int j; + int failed = 1; + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_CIPHER_CTX_new() failed\n"); + goto failed; + } + + for (i = 0; i < N_RC4_TESTS; i++) { + rt = &rc4_tests[i]; + + /* Encryption */ + memset(out, 0, sizeof(out)); + RC4_set_key(&key, rt->key_len, rt->key); + RC4(&key, rt->len, rt->in, out); + + if (memcmp(rt->out, out, rt->len) != 0) { + fprintf(stderr, "FAIL: encryption mismatch\n"); + goto failed; + } + + /* Decryption */ + memset(out, 0, sizeof(out)); + RC4_set_key(&key, rt->key_len, rt->key); + RC4(&key, rt->len, rt->out, out); + + if (memcmp(rt->in, out, rt->len) != 0) { + fprintf(stderr, "FAIL: decryption mismatch\n"); + goto failed; + } + + /* + * EVP tests + */ + if (rt->key_len == 5) { + cipher = EVP_rc4_40(); + } else if (rt->key_len == 16) { + cipher = EVP_rc4(); + } else { + /* EVP does not support this key length */ + continue; + } + + /* EVP encryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_EncryptInit(ctx, cipher, rt->key, NULL)) { + fprintf(stderr, "FAIL: EVP_EncryptInit failed\n"); + goto failed; + } + + for (j = 0; j < rt->len;) { + in_len = arc4random_uniform(rt->len / 2); + if (in_len > rt->len - j) + in_len = rt->len - j; + + if (!EVP_EncryptUpdate(ctx, out + total_len, &out_len, + rt->in + j, in_len)) { + fprintf(stderr, + "FAIL: EVP_EncryptUpdate failed\n"); + goto failed; + } + + j += in_len; + total_len += out_len; + } + + if (!EVP_EncryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL: EVP_EncryptFinal_ex failed\n"); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, "FAIL: EVP_CIPHER_CTX_reset failed\n"); + goto failed; + } + + if (total_len != rt->len) { + fprintf(stderr, + "FAIL: EVP encryption length mismatch\n"); + goto failed; + } + + if (memcmp(rt->out, out, rt->len) != 0) { + fprintf(stderr, "FAIL: EVP encryption mismatch\n"); + goto failed; + } + + /* EVP decryption */ + total_len = 0; + memset(out, 0, sizeof(out)); + if (!EVP_DecryptInit(ctx, cipher, rt->key, NULL)) { + fprintf(stderr, "FAIL: EVP_DecryptInit failed\n"); + goto failed; + } + + for (j = 0; j < rt->len;) { + in_len = arc4random_uniform(rt->len / 2); + if (in_len > rt->len - j) + in_len = rt->len - j; + + if (!EVP_DecryptUpdate(ctx, out + total_len, &out_len, + rt->in + j, in_len)) { + fprintf(stderr, + "FAIL: EVP_DecryptUpdate failed\n"); + goto failed; + } + + j += in_len; + total_len += out_len; + } + + if (!EVP_DecryptFinal_ex(ctx, out + total_len, &out_len)) { + fprintf(stderr, "FAIL: EVP_DecryptFinal_ex failed\n"); + goto failed; + } + total_len += out_len; + + if (!EVP_CIPHER_CTX_reset(ctx)) { + fprintf(stderr, "FAIL: EVP_CIPHER_CTX_reset failed\n"); + goto failed; + } + + if (total_len != rt->len) { + fprintf(stderr, + "FAIL: EVP decryption length mismatch\n"); + goto failed; + } + + if (memcmp(rt->out, out, rt->len) != 0) { + fprintf(stderr, "FAIL: EVP decryption mismatch\n"); + goto failed; + } + } + + failed = 0; + + failed: + EVP_CIPHER_CTX_free(ctx); + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= rc4_test(); + + return failed; +} diff --git a/tests/record_layer_test.c b/tests/record_layer_test.c new file mode 100644 index 0000000..2db0c10 --- /dev/null +++ b/tests/record_layer_test.c @@ -0,0 +1,306 @@ +/* $OpenBSD: record_layer_test.c,v 1.6 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2019, 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "ssl_local.h" +#include "tls13_internal.h" +#include "tls13_record.h" + +int tls12_record_layer_inc_seq_num(struct tls12_record_layer *rl, + uint8_t *seq_num); +int tls13_record_layer_inc_seq_num(uint8_t *seq_num); + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\n"); + if (len % 8 != 0) + fprintf(stderr, "\n"); +} + +struct seq_num_test { + uint8_t seq_num[TLS13_RECORD_SEQ_NUM_LEN]; + uint8_t want_num[TLS13_RECORD_SEQ_NUM_LEN]; + int want; +}; + +struct seq_num_test seq_num_dtls_tests[] = { + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, + .want = 1, + }, + { + .seq_num = {0xab, 0xcd, 0xef, 0x00, 0xfe, 0xff, 0xff, 0xff}, + .want_num = {0xab, 0xcd, 0xef, 0x00, 0xff, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 0, + }, + { + .seq_num = {0x01, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, + .want_num = {0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 1, + }, + { + .seq_num = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want_num = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want = 1, + }, + { + .seq_num = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 0, + }, + { + .seq_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, + .want_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 1, + }, + { + .seq_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 0, + }, +}; + +#define N_SEQ_NUM_DTLS_TESTS \ + (sizeof(seq_num_dtls_tests) / sizeof(seq_num_dtls_tests[0])) + +struct seq_num_test seq_num_tls_tests[] = { + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff}, + .want_num = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, + .want = 1, + }, + { + .seq_num = {0xab, 0xcd, 0xef, 0x00, 0xfe, 0xff, 0xff, 0xff}, + .want_num = {0xab, 0xcd, 0xef, 0x00, 0xff, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want_num = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + .want = 1, + }, + { + .seq_num = {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + .want = 1, + }, + { + .seq_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}, + .want_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 1, + }, + { + .seq_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want_num = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .want = 0, + }, +}; + +#define N_SEQ_NUM_TLS_TESTS \ + (sizeof(seq_num_tls_tests) / sizeof(seq_num_tls_tests[0])) + +#ifndef TLS12_RECORD_SEQ_NUM_LEN +#define TLS12_RECORD_SEQ_NUM_LEN 8 +#endif + +static int +do_seq_num_test_tls12(size_t test_no, int dtls, struct seq_num_test *snt) +{ + uint8_t seq_num[TLS12_RECORD_SEQ_NUM_LEN]; + struct tls12_record_layer *rl; + int failed = 1; + int ret; + + if ((rl = tls12_record_layer_new()) == NULL) + errx(1, "tls12_record_layer_new"); + + if (dtls) + tls12_record_layer_set_version(rl, DTLS1_2_VERSION); + + memcpy(seq_num, snt->seq_num, sizeof(seq_num)); + + if ((ret = tls12_record_layer_inc_seq_num(rl, seq_num)) != snt->want) { + fprintf(stderr, "FAIL: Test %zu - got return %d, want %d\n", + test_no, ret, snt->want); + goto failure; + } + + if (memcmp(seq_num, snt->want_num, sizeof(seq_num)) != 0) { + fprintf(stderr, "FAIL: Test %zu - got sequence number:\n", + test_no); + hexdump(seq_num, sizeof(seq_num)); + fprintf(stderr, "want:\n"); + hexdump(snt->want_num, sizeof(snt->want_num)); + goto failure; + } + + failed = 0; + + failure: + tls12_record_layer_free(rl); + + return failed; +} + +static int +test_seq_num_tls12(void) +{ + int failed = 0; + size_t i; + + fprintf(stderr, "Running TLSv1.2 sequence number tests...\n"); + for (i = 0; i < N_SEQ_NUM_TLS_TESTS; i++) + failed |= do_seq_num_test_tls12(i, 0, &seq_num_tls_tests[i]); + + fprintf(stderr, "Running DTLSv1.2 sequence number tests...\n"); + for (i = 0; i < N_SEQ_NUM_DTLS_TESTS; i++) + failed |= do_seq_num_test_tls12(i, 1, &seq_num_dtls_tests[i]); + + return failed; +} + +static int +do_seq_num_test_tls13(size_t test_no, struct seq_num_test *snt) +{ + uint8_t seq_num[TLS13_RECORD_SEQ_NUM_LEN]; + int failed = 1; + int ret; + + memcpy(seq_num, snt->seq_num, sizeof(seq_num)); + + if ((ret = tls13_record_layer_inc_seq_num(seq_num)) != snt->want) { + fprintf(stderr, "FAIL: Test %zu - got return %d, want %d\n", + test_no, ret, snt->want); + goto failure; + } + + if (memcmp(seq_num, snt->want_num, sizeof(seq_num)) != 0) { + fprintf(stderr, "FAIL: Test %zu - got sequence number:\n", + test_no); + hexdump(seq_num, sizeof(seq_num)); + fprintf(stderr, "want:\n"); + hexdump(snt->want_num, sizeof(snt->want_num)); + goto failure; + } + + failed = 0; + + failure: + return failed; +} + +static int +test_seq_num_tls13(void) +{ + int failed = 0; + size_t i; + + fprintf(stderr, "Running TLSv1.3 sequence number tests...\n"); + + for (i = 0; i < N_SEQ_NUM_TLS_TESTS; i++) + failed |= do_seq_num_test_tls13(i, &seq_num_tls_tests[i]); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_seq_num_tls12(); + failed |= test_seq_num_tls13(); + + return failed; +} diff --git a/tests/recordtest.c b/tests/recordtest.c new file mode 100644 index 0000000..de9bfd6 --- /dev/null +++ b/tests/recordtest.c @@ -0,0 +1,555 @@ +/* $OpenBSD: recordtest.c,v 1.5 2022/06/10 22:00:15 tb Exp $ */ +/* + * Copyright (c) 2019 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "tls13_internal.h" +#include "tls13_record.h" + +/* Valid record. */ +static uint8_t test_record_1[] = { + 0x16, 0x03, 0x03, 0x00, 0x7a, 0x02, 0x00, 0x00, + 0x76, 0x03, 0x03, 0x14, 0xae, 0x2b, 0x6d, 0x58, + 0xe9, 0x79, 0x9d, 0xd4, 0x90, 0x52, 0x90, 0x13, + 0x1c, 0x08, 0xaa, 0x3f, 0x5b, 0xfb, 0x64, 0xfe, + 0x9a, 0xca, 0x73, 0x6d, 0x87, 0x8d, 0x8b, 0x3b, + 0x70, 0x14, 0xa3, 0x20, 0xd7, 0x50, 0xa4, 0xe5, + 0x17, 0x42, 0x5d, 0xce, 0xe6, 0xfe, 0x1b, 0x59, + 0x27, 0x6b, 0xff, 0xc8, 0x40, 0xc7, 0xac, 0x16, + 0x32, 0xe6, 0x5b, 0xd2, 0xd9, 0xd4, 0xb5, 0x3f, + 0x8f, 0x74, 0x6e, 0x7d, 0x13, 0x02, 0x00, 0x00, + 0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00, + 0x20, 0x72, 0xb0, 0xaf, 0x7f, 0xf5, 0x89, 0x0f, + 0xcd, 0x6e, 0x45, 0xb1, 0x51, 0xa0, 0xbd, 0x1e, + 0xee, 0x7e, 0xf1, 0xa5, 0xc5, 0xc6, 0x7e, 0x5f, + 0x6a, 0xca, 0xc9, 0xe4, 0xae, 0xb9, 0x50, 0x76, + 0x0a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, +}; + +/* Truncated record. */ +static uint8_t test_record_2[] = { + 0x17, 0x03, 0x03, 0x41, 0x00, 0x02, 0x00, 0x00, +}; + +/* Oversized and truncated record. */ +static uint8_t test_record_3[] = { + 0x17, 0x03, 0x03, 0x41, 0x01, 0x02, 0x00, 0x00, +}; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\n"); + if (len % 8 != 0) + fprintf(stderr, "\n"); +} + +struct rw_state { + uint8_t *buf; + size_t len; + size_t offset; + uint8_t eof; +}; + +static ssize_t +read_cb(void *buf, size_t buflen, void *cb_arg) +{ + struct rw_state *rs = cb_arg; + ssize_t n; + + if (rs->eof) + return TLS13_IO_EOF; + + if ((size_t)(n = buflen) > (rs->len - rs->offset)) + n = rs->len - rs->offset; + + if (n == 0) + return TLS13_IO_WANT_POLLIN; + + memcpy(buf, &rs->buf[rs->offset], n); + rs->offset += n; + + return n; +} + +static ssize_t +write_cb(const void *buf, size_t buflen, void *cb_arg) +{ + struct rw_state *ws = cb_arg; + ssize_t n; + + if (ws->eof) + return TLS13_IO_EOF; + + if ((size_t)(n = buflen) > (ws->len - ws->offset)) + n = ws->len - ws->offset; + + if (n == 0) + return TLS13_IO_WANT_POLLOUT; + + memcpy(&ws->buf[ws->offset], buf, n); + ws->offset += n; + + return n; +} + +struct record_test { + size_t rw_len; + int eof; + ssize_t want_ret; +}; + +struct record_recv_test { + uint8_t *read_buf; + struct record_test rt[10]; + uint8_t want_content_type; + uint8_t *want_data; + size_t want_len; +}; + +struct record_recv_test record_recv_tests[] = { + { + .read_buf = test_record_1, + .rt = { + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_content_type = SSL3_RT_HANDSHAKE, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .read_buf = test_record_1, + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_content_type = SSL3_RT_HANDSHAKE, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .read_buf = test_record_1, + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = 5, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_content_type = SSL3_RT_HANDSHAKE, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .read_buf = test_record_1, + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = 2, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = 6, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_content_type = SSL3_RT_HANDSHAKE, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .read_buf = test_record_1, + .rt = { + { + .rw_len = 4, + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .eof = 1, + .want_ret = TLS13_IO_EOF, + }, + }, + }, + { + .read_buf = test_record_1, + .rt = { + { + .eof = 1, + .want_ret = TLS13_IO_EOF, + }, + }, + }, + { + .read_buf = test_record_2, + .rt = { + { + .rw_len = sizeof(test_record_2), + .want_ret = TLS13_IO_WANT_POLLIN, + }, + { + .eof = 1, + .want_ret = TLS13_IO_EOF, + }, + }, + .want_content_type = SSL3_RT_APPLICATION_DATA, + }, + { + .read_buf = test_record_3, + .rt = { + { + .rw_len = sizeof(test_record_3), + .want_ret = TLS13_IO_RECORD_OVERFLOW, + }, + }, + }, +}; + +#define N_RECORD_RECV_TESTS (sizeof(record_recv_tests) / sizeof(record_recv_tests[0])) + +struct record_send_test { + uint8_t *data; + size_t data_len; + struct record_test rt[10]; + uint8_t *want_data; + size_t want_len; +}; + +struct record_send_test record_send_tests[] = { + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = 5, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = 2, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = 6, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .rw_len = sizeof(test_record_1), + .want_ret = sizeof(test_record_1), + }, + }, + .want_data = test_record_1, + .want_len = sizeof(test_record_1), + }, + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = 4, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .eof = 1, + .want_ret = TLS13_IO_EOF, + }, + }, + .want_data = test_record_1, + .want_len = 4, + }, + { + .data = test_record_1, + .data_len = sizeof(test_record_1), + .rt = { + { + .rw_len = 0, + .want_ret = TLS13_IO_WANT_POLLOUT, + }, + { + .eof = 1, + .want_ret = TLS13_IO_EOF, + }, + }, + .want_data = NULL, + .want_len = 0, + }, +}; + +#define N_RECORD_SEND_TESTS (sizeof(record_send_tests) / sizeof(record_send_tests[0])) + +static int +test_record_recv(size_t test_no, struct record_recv_test *rrt) +{ + struct tls13_record *rec; + struct rw_state rs; + int failed = 1; + ssize_t ret; + size_t i; + CBS cbs; + + rs.buf = rrt->read_buf; + rs.offset = 0; + + if ((rec = tls13_record_new()) == NULL) + errx(1, "tls13_record_new"); + + for (i = 0; rrt->rt[i].rw_len != 0 || rrt->rt[i].want_ret != 0; i++) { + rs.eof = rrt->rt[i].eof; + rs.len = rrt->rt[i].rw_len; + + ret = tls13_record_recv(rec, read_cb, &rs); + if (ret != rrt->rt[i].want_ret) { + fprintf(stderr, "FAIL: Test %zu/%zu - tls_record_recv " + "returned %zd, want %zd\n", test_no, i, ret, + rrt->rt[i].want_ret); + goto failure; + } + } + + if (tls13_record_content_type(rec) != rrt->want_content_type) { + fprintf(stderr, "FAIL: Test %zu - got content type %u, " + "want %u\n", test_no, tls13_record_content_type(rec), + rrt->want_content_type); + goto failure; + } + + tls13_record_data(rec, &cbs); + if (rrt->want_data == NULL) { + if (CBS_data(&cbs) != NULL || CBS_len(&cbs) != 0) { + fprintf(stderr, "FAIL: Test %zu - got CBS with data, " + "want NULL\n", test_no); + goto failure; + } + goto done; + } + if (!CBS_mem_equal(&cbs, rrt->want_data, rrt->want_len)) { + fprintf(stderr, "FAIL: Test %zu - data mismatch\n", test_no); + fprintf(stderr, "Got record data:\n"); + hexdump(CBS_data(&cbs), CBS_len(&cbs)); + fprintf(stderr, "Want record data:\n"); + hexdump(rrt->want_data, rrt->want_len); + goto failure; + } + + if (!tls13_record_header(rec, &cbs)) { + fprintf(stderr, "FAIL: Test %zu - fail to get record " + "header", test_no); + goto failure; + } + if (!CBS_mem_equal(&cbs, rrt->want_data, TLS13_RECORD_HEADER_LEN)) { + fprintf(stderr, "FAIL: Test %zu - header mismatch\n", test_no); + fprintf(stderr, "Got record header:\n"); + hexdump(CBS_data(&cbs), CBS_len(&cbs)); + fprintf(stderr, "Want record header:\n"); + hexdump(rrt->want_data, rrt->want_len); + goto failure; + } + + if (!tls13_record_content(rec, &cbs)) { + fprintf(stderr, "FAIL: Test %zu - fail to get record " + "content", test_no); + goto failure; + } + if (!CBS_mem_equal(&cbs, rrt->want_data + TLS13_RECORD_HEADER_LEN, + rrt->want_len - TLS13_RECORD_HEADER_LEN)) { + fprintf(stderr, "FAIL: Test %zu - content mismatch\n", test_no); + fprintf(stderr, "Got record content:\n"); + hexdump(CBS_data(&cbs), CBS_len(&cbs)); + fprintf(stderr, "Want record content:\n"); + hexdump(rrt->want_data, rrt->want_len); + goto failure; + } + + done: + failed = 0; + + failure: + tls13_record_free(rec); + + return failed; +} + +static int +test_record_send(size_t test_no, struct record_send_test *rst) +{ + uint8_t *data = NULL; + struct tls13_record *rec; + struct rw_state ws; + int failed = 1; + ssize_t ret; + size_t i; + + if ((ws.buf = malloc(TLS13_RECORD_MAX_LEN)) == NULL) + errx(1, "malloc"); + + ws.offset = 0; + + if ((rec = tls13_record_new()) == NULL) + errx(1, "tls13_record_new"); + + if ((data = malloc(rst->data_len)) == NULL) + errx(1, "malloc"); + memcpy(data, rst->data, rst->data_len); + + if (!tls13_record_set_data(rec, data, rst->data_len)) { + fprintf(stderr, "FAIL: Test %zu - failed to set record data\n", + test_no); + goto failure; + } + data = NULL; + + for (i = 0; rst->rt[i].rw_len != 0 || rst->rt[i].want_ret != 0; i++) { + ws.eof = rst->rt[i].eof; + ws.len = rst->rt[i].rw_len; + + ret = tls13_record_send(rec, write_cb, &ws); + if (ret != rst->rt[i].want_ret) { + fprintf(stderr, "FAIL: Test %zu/%zu - tls_record_send " + "returned %zd, want %zd\n", test_no, i, ret, + rst->rt[i].want_ret); + goto failure; + } + } + + if (rst->want_data != NULL && + memcmp(ws.buf, rst->want_data, rst->want_len) != 0) { + fprintf(stderr, "FAIL: Test %zu - content mismatch\n", test_no); + fprintf(stderr, "Got record data:\n"); + hexdump(rst->data, rst->data_len); + fprintf(stderr, "Want record data:\n"); + hexdump(rst->want_data, rst->want_len); + goto failure; + } + + failed = 0; + + failure: + tls13_record_free(rec); + free(ws.buf); + + return failed; +} + +static int +test_recv_records(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_RECORD_RECV_TESTS; i++) + failed |= test_record_recv(i, &record_recv_tests[i]); + + return failed; +} + +static int +test_send_records(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_RECORD_SEND_TESTS; i++) + failed |= test_record_send(i, &record_send_tests[i]); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_recv_records(); + failed |= test_send_records(); + + return failed; +} diff --git a/tests/rfc3779.c b/tests/rfc3779.c new file mode 100644 index 0000000..33808d4 --- /dev/null +++ b/tests/rfc3779.c @@ -0,0 +1,1965 @@ +/* $OpenBSD: rfc3779.c,v 1.9 2023/04/20 07:39:17 tb Exp $ */ +/* + * Copyright (c) 2021 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#define RAW_ADDRESS_SIZE 16 + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + if (len % 8) + fprintf(stderr, "\n"); +} + +static void +report_hexdump(const char *func, const char *description, const char *msg, + const unsigned char *want, size_t want_len, + const unsigned char *got, size_t got_len) +{ + fprintf(stderr, "%s: \"%s\" %s\nwant:\n", func, description, msg); + hexdump(want, want_len); + fprintf(stderr, "got:\n"); + hexdump(got, got_len); +} + +static int +afi_size(int afi) +{ + switch (afi) { + case IANA_AFI_IPV4: + return 4; + case IANA_AFI_IPV6: + return 16; + } + return 0; +} + +struct IPAddressOrRange_test { + const char *description; + const uint8_t der[32]; + size_t der_len; + unsigned afi; + const uint8_t min[RAW_ADDRESS_SIZE]; + const uint8_t max[RAW_ADDRESS_SIZE]; +}; + +const struct IPAddressOrRange_test IPAddressOrRange_test_data[] = { + /* Examples from RFC 3779, section 2.1.1 */ + { + .description = "address 10.5.0.4", + .der = { + 0x03, 0x05, 0x00, 0x0a, 0x05, 0x00, 0x04, + }, + .der_len = 7, + .afi = IANA_AFI_IPV4, + .min = { + 0x0a, 0x05, 0x00, 0x04, + }, + .max = { + 0x0a, 0x05, 0x00, 0x04, + } + }, + { + .description = "prefix 10.5.0/23", + .der = { + 0x03, 0x04, 0x01, 0x0a, 0x05, 0x00, + }, + .der_len = 6, + .afi = IANA_AFI_IPV4, + .min = { + 0x0a, 0x05, 0x00, 0x00, + }, + .max = { + 0x0a, 0x05, 0x01, 0xff, + } + }, + { + .description = "address 2001:0:200:3::1", + .der = { + 0x03, 0x11, 0x00, 0x20, 0x01, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, + }, + .der_len = 19, + .afi = IANA_AFI_IPV6, + .min = { + 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + .max = { + 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + }, + }, + { + .description = "prefix 2001:0:200/39", + .der = { + 0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02, + }, + .der_len = 8, + .afi = IANA_AFI_IPV6, + .min = { + 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .max = { + 0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + }, + }, + + /* Examples from RFC 3779, Section 2.1.2 */ + { + .description = "prefix 10.5.0/23 as a range", + .der = { + /* Sequence */ + 0x30, 0x0b, + /* 10.5.0.0 */ + 0x03, 0x03, 0x00, 0x0a, 0x05, + /* 10.5.1.255 */ + 0x03, 0x04, 0x01, 0x0a, 0x05, 0x00, + }, + .der_len = 13, + .afi = IANA_AFI_IPV4, + .min = { + 0x0a, 0x05, 0x00, 0x00, + }, + .max = { + 0x0a, 0x05, 0x01, 0xff, + } + }, + { + .description = "prefix 2001:0:200/39 as a range", + .der = { + /* Sequence */ + 0x30, 0x10, + /* 2001:0:200:: */ + 0x03, 0x06, 0x01, 0x20, 0x01, 0x00, 0x00, 0x02, + /* 2001:0:3ff:ffff:ffff:ffff:ffff:ffff */ + 0x03, 0x06, 0x02, 0x20, 0x01, 0x00, 0x00, 0x00, + }, + .der_len = 18, + .afi = IANA_AFI_IPV6, + .min = { + 0x20, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + .max = { + 0x20, 0x01, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + } + }, + { + .description = "prefix 0/0", + .der = { + 0x03, 0x01, 0x00, + }, + .der_len = 3, + .afi = IANA_AFI_IPV4, + .min = { + 0x00, 0x00, 0x00, 0x00, + }, + .max = { + 0xff, 0xff, 0xff, 0xff, + } + }, + { + .description = "prefix 10.64/12", + .der = { + 0x03, 0x03, 0x04, 0x0a, 0x40, + }, + .der_len = 5, + .afi = IANA_AFI_IPV4, + .min = { + 0x0a, 0x40, 0x00, 0x00, + }, + .max = { + 0x0a, 0x4f, 0xff, 0xff, + }, + }, + { + .description = "prefix 10.64/20", + .der = { + 0x03, 0x04, 0x04, 0x0a, 0x40, 0x00, + }, + .der_len = 6, + .afi = IANA_AFI_IPV4, + .min = { + 0x0a, 0x40, 0x00, 0x00, + }, + .max = { + 0x0a, 0x40, 0x0f, 0xff, + }, + }, +}; + +const size_t N_IPADDRESSORRANGE_TESTS = + sizeof(IPAddressOrRange_test_data) / sizeof(IPAddressOrRange_test_data[0]); + +static int +test_IPAddressOrRange(const struct IPAddressOrRange_test *test) +{ + IPAddressOrRange *aor; + const unsigned char *p; + unsigned char min[RAW_ADDRESS_SIZE] = {0}, max[RAW_ADDRESS_SIZE] = {0}; + unsigned char *out = NULL; + int out_len; + int afi_len; + int memcmp_failed = 0; + int failed = 1; + + /* + * First, decode DER from the test case. + */ + + p = &test->der[0]; + if ((aor = d2i_IPAddressOrRange(NULL, &p, test->der_len)) == NULL) { + fprintf(stderr, "%s: \"%s\" d2i_IPAddressOrRange failed\n", + __func__, test->description); + goto err; + } + + /* + * Now extract minimum and maximum from the parsed range. + */ + + afi_len = afi_size(test->afi); + + if (X509v3_addr_get_range(aor, test->afi, min, max, sizeof min) != + afi_len) { + fprintf(stderr, "%s: \"%s\" X509v3_addr_get_range failed\n", + __func__, test->description); + goto err; + } + + /* + * Check that min and max match expectations. + */ + + if (memcmp(min, test->min, afi_len) != 0) { + memcmp_failed |= 1; + report_hexdump(__func__, test->description, "memcmp min failed", + test->min, afi_len, min, afi_len); + } + if (memcmp(max, test->max, afi_len) != 0) { + memcmp_failed |= 1; + report_hexdump(__func__, test->description, "memcmp max failed", + test->max, afi_len, max, afi_len); + } + if (memcmp_failed) + goto err; + + /* + * Now turn the parsed IPAddressOrRange back into DER and check that + * it matches the DER in the test case. + */ + + out = NULL; + if ((out_len = i2d_IPAddressOrRange(aor, &out)) <= 0) { + fprintf(stderr, "%s: \"%s\" i2d_IPAddressOrRange failed\n", + __func__, test->description); + goto err; + } + + memcmp_failed = (size_t)out_len != test->der_len; + if (!memcmp_failed) + memcmp_failed = memcmp(test->der, out, out_len); + + if (memcmp_failed) { + report_hexdump(__func__, test->description, "memcmp DER failed", + test->der, test->der_len, out, out_len); + goto err; + } + + failed = 0; + err: + IPAddressOrRange_free(aor); + free(out); + + return failed; +} + +static int +run_IPAddressOrRange_tests(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_IPADDRESSORRANGE_TESTS; i++) + failed |= + test_IPAddressOrRange(&IPAddressOrRange_test_data[i]); + + return failed; +} + +/* + * XXX: These should really be part of the public API... + */ +static IPAddrBlocks *IPAddrBlocks_new(void); +static void IPAddrBlocks_free(IPAddrBlocks *addr); +static IPAddrBlocks *d2i_IPAddrBlocks(IPAddrBlocks **addrs, + const unsigned char **in, long len); +static int i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out); + +static IPAddrBlocks * +IPAddrBlocks_new(void) +{ + IPAddrBlocks *addrs; + + /* + * XXX The comparison function IPAddressFamily_cmp() isn't public. + * Start with the default and exploit a side effect of the lovely API + * which helpfully sets the correct function in a few places. Let's + * use the cheapest and easiest to reach one. + */ + if ((addrs = sk_IPAddressFamily_new_null()) == NULL) + return NULL; + if (!X509v3_addr_canonize(addrs)) { + IPAddrBlocks_free(addrs); + return NULL; + } + + return addrs; +} + +static void +IPAddrBlocks_free(IPAddrBlocks *addr) +{ + sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); +} + +/* + * We want {d2i,i2d}_IPAddrBlocks() to play with the DER of the extension. + * These don't exist, so we have to implement them ourselves. IPAddrBlocks_it + * isn't public, so we need to fetch it from the library. We cache it in a + * static variable to avoid the cost of a binary search through all supported + * extensions on each call. + */ + +static const ASN1_ITEM_EXP * +get_IPAddrBlocks_it(void) +{ + static const ASN1_ITEM_EXP *my_IPAddrBlocks_it; + const X509V3_EXT_METHOD *v3_addr; + + if (my_IPAddrBlocks_it != NULL) + return my_IPAddrBlocks_it; + + if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL) { + fprintf(stderr, "could not get v3_addr\n"); + return NULL; + } + + my_IPAddrBlocks_it = v3_addr->it; + + return my_IPAddrBlocks_it; +} + +static IPAddrBlocks * +d2i_IPAddrBlocks(IPAddrBlocks **addrs, const unsigned char **in, long len) +{ + const ASN1_ITEM_EXP *my_IPAddrBlocks_it; + + if ((my_IPAddrBlocks_it = get_IPAddrBlocks_it()) == NULL) + return NULL; + + return (IPAddrBlocks *)ASN1_item_d2i((ASN1_VALUE **)addrs, in, len, + my_IPAddrBlocks_it); +} + +static int +i2d_IPAddrBlocks(IPAddrBlocks *addrs, unsigned char **out) +{ + const ASN1_ITEM_EXP *my_IPAddrBlocks_it; + + if ((my_IPAddrBlocks_it = get_IPAddrBlocks_it()) == NULL) + return -1; + + return ASN1_item_i2d((ASN1_VALUE *)addrs, out, my_IPAddrBlocks_it); +} + +struct ipv4_prefix { + unsigned char addr[4]; + size_t addr_len; + size_t prefix_len; +}; + +struct ipv4_range { + unsigned char min[4]; + unsigned char max[4]; +}; + +union ipv4_choice { + struct ipv4_prefix prefix; + struct ipv4_range range; +}; + +struct ipv6_prefix { + unsigned char addr[16]; + size_t addr_len; + size_t prefix_len; +}; + +struct ipv6_range { + unsigned char min[16]; + unsigned char max[16]; +}; + +union ipv6_choice { + struct ipv6_prefix prefix; + struct ipv6_range range; +}; + +enum choice_type { + choice_prefix, + choice_range, + choice_inherit, + choice_last, +}; + +union ip { + union ipv4_choice ipv4; + union ipv6_choice ipv6; +}; + +enum safi { + safi_none, + safi_unicast, + safi_multicast, +}; + +struct ip_addr_block { + unsigned int afi; + enum safi safi; + enum choice_type type; + union ip addr; +}; + +struct build_addr_block_test_data { + char *description; + struct ip_addr_block addrs[16]; + char der[128]; + size_t der_len; + int is_canonical; + int inherits; + unsigned int afis[4]; + int afi_len; +}; + +const struct build_addr_block_test_data build_addr_block_tests[] = { + { + .description = "RFC 3779, Appendix B, example 1", + .addrs = { + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 0, 32, + }, + .addr_len = 3, + .prefix_len = 20, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 0, 64, + }, + .addr_len = 3, + .prefix_len = 24, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 1, + }, + .addr_len = 2, + .prefix_len = 16, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 2, 48, + }, + .addr_len = 3, + .prefix_len = 20, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 2, 64, + }, + .addr_len = 3, + .prefix_len = 24, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 3, + }, + .addr_len = 2, + .prefix_len = 16, + }, + }, + { + .afi = IANA_AFI_IPV6, + .safi = safi_none, + .type = choice_inherit, + }, + { + .type = choice_last, + }, + }, + .der = { + 0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01, + 0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00, + 0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03, + 0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04, + 0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a, + 0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30, + 0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00, + }, + .der_len = 55, + .is_canonical = 0, + .inherits = 1, + .afis = { + IANA_AFI_IPV4, IANA_AFI_IPV6, + }, + .afi_len = 2, + }, + { + .description = "RFC 3779, Appendix B, example 1 canonical", + .addrs = { + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 0, 32, + }, + .addr_len = 3, + .prefix_len = 20, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 0, 64, + }, + .addr_len = 3, + .prefix_len = 24, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 1, + }, + .addr_len = 2, + .prefix_len = 16, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_range, + .addr.ipv4.range = { + .min = { + 10, 2, 48, 00, + }, + .max = { + 10, 2, 64, 255, + }, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, 3, + }, + .addr_len = 2, + .prefix_len = 16, + }, + }, + { + .afi = IANA_AFI_IPV6, + .safi = safi_none, + .type = choice_inherit, + }, + { + .type = choice_last, + }, + }, + .der = { + 0x30, 0x35, 0x30, 0x2b, 0x04, 0x03, 0x00, 0x01, + 0x01, 0x30, 0x24, 0x03, 0x04, 0x04, 0x0a, 0x00, + 0x20, 0x03, 0x04, 0x00, 0x0a, 0x00, 0x40, 0x03, + 0x03, 0x00, 0x0a, 0x01, 0x30, 0x0c, 0x03, 0x04, + 0x04, 0x0a, 0x02, 0x30, 0x03, 0x04, 0x00, 0x0a, + 0x02, 0x40, 0x03, 0x03, 0x00, 0x0a, 0x03, 0x30, + 0x06, 0x04, 0x02, 0x00, 0x02, 0x05, 0x00, + }, + .der_len = 55, + .is_canonical = 1, + .inherits = 1, + .afis = { + IANA_AFI_IPV4, IANA_AFI_IPV6, + }, + .afi_len = 2, + }, + { + .description = "RFC 3779, Appendix B, example 2", + .addrs = { + { + .afi = IANA_AFI_IPV6, + .safi = safi_none, + .type = choice_prefix, + .addr.ipv6.prefix = { + .addr = { + 0x20, 0x01, 0x00, 0x00, + 0x00, 0x02, + }, + .addr_len = 6, + .prefix_len = 48, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 10, + }, + .addr_len = 1, + .prefix_len = 8, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_unicast, + .type = choice_prefix, + .addr.ipv4.prefix = { + .addr = { + 172, 16, + }, + .addr_len = 2, + .prefix_len = 12, + }, + }, + { + .afi = IANA_AFI_IPV4, + .safi = safi_multicast, + .type = choice_inherit, + }, + { + .type = choice_last, + }, + }, + .der = { + 0x30, 0x2c, 0x30, 0x10, 0x04, 0x03, 0x00, 0x01, + 0x01, 0x30, 0x09, 0x03, 0x02, 0x00, 0x0a, 0x03, + 0x03, 0x04, 0xac, 0x10, 0x30, 0x07, 0x04, 0x03, + 0x00, 0x01, 0x02, 0x05, 0x00, 0x30, 0x0f, 0x04, + 0x02, 0x00, 0x02, 0x30, 0x09, 0x03, 0x07, 0x00, + 0x20, 0x01, 0x00, 0x00, 0x00, 0x02, + }, + .der_len = 46, + .is_canonical = 0, + .inherits = 1, + .afis = { + IANA_AFI_IPV4, IANA_AFI_IPV4, + }, + .afi_len = 2, + }, + { + .description = "Range should be prefix 127/8", + .addrs = { + { + .afi = IANA_AFI_IPV4, + .safi = safi_none, + .type = choice_range, + .addr.ipv4.range = { + .min = { + 127, 0, 0, 0, + }, + .max = { + 127, 255, 255, 255, + }, + }, + }, + { + .type = choice_last, + }, + }, + .der = { + 0x30, 0x0c, 0x30, 0x0a, 0x04, 0x02, 0x00, 0x01, + 0x30, 0x04, 0x03, 0x02, 0x00, 0x7f, + }, + .der_len = 14, + .is_canonical = 1, + .inherits = 0, + .afis = { + IANA_AFI_IPV4, + }, + .afi_len = 1, + }, +}; + +const size_t N_BUILD_ADDR_BLOCK_TESTS = + sizeof(build_addr_block_tests) / sizeof(build_addr_block_tests[0]); + +static unsigned int * +addr_block_get_safi(const struct ip_addr_block *addr) +{ + static unsigned int safi; + + switch (addr->safi) { + case safi_none: + return NULL; + case safi_unicast: + safi = 1; + break; + case safi_multicast: + safi = 2; + break; + } + + return &safi; +} + +static int +addr_block_add_ipv4_addr(IPAddrBlocks *block, enum choice_type type, + const union ipv4_choice *ipv4, unsigned int *safi) +{ + unsigned char addr[RAW_ADDRESS_SIZE] = {0}; + unsigned char min[RAW_ADDRESS_SIZE]; + unsigned char max[RAW_ADDRESS_SIZE]; + + switch (type) { + case choice_prefix: + memcpy(addr, ipv4->prefix.addr, ipv4->prefix.addr_len); + return X509v3_addr_add_prefix(block, IANA_AFI_IPV4, safi, + addr, ipv4->prefix.prefix_len); + case choice_range: + memcpy(min, ipv4->range.min, sizeof(ipv4->range.min)); + memcpy(max, ipv4->range.max, sizeof(ipv4->range.max)); + return X509v3_addr_add_range(block, IANA_AFI_IPV4, safi, + min, max); + case choice_inherit: + return X509v3_addr_add_inherit(block, IANA_AFI_IPV4, safi); + case choice_last: + default: + return 0; + } +} + +static int +addr_block_add_ipv6_addr(IPAddrBlocks *block, enum choice_type type, + const union ipv6_choice *ipv6, unsigned int *safi) +{ + unsigned char addr[RAW_ADDRESS_SIZE] = {0}; + unsigned char min[RAW_ADDRESS_SIZE]; + unsigned char max[RAW_ADDRESS_SIZE]; + + switch (type) { + case choice_prefix: + memcpy(addr, ipv6->prefix.addr, ipv6->prefix.addr_len); + return X509v3_addr_add_prefix(block, IANA_AFI_IPV6, safi, + addr, ipv6->prefix.prefix_len); + case choice_range: + memcpy(min, ipv6->range.min, sizeof(ipv6->range.min)); + memcpy(max, ipv6->range.max, sizeof(ipv6->range.max)); + return X509v3_addr_add_range(block, IANA_AFI_IPV6, safi, + min, max); + case choice_inherit: + return X509v3_addr_add_inherit(block, IANA_AFI_IPV6, safi); + case choice_last: + default: + return 0; + } +} + +static int +addr_block_add_addrs(IPAddrBlocks *block, const struct ip_addr_block addrs[]) +{ + const struct ip_addr_block *addr; + unsigned int *safi; + + for (addr = &addrs[0]; addr->type != choice_last; addr++) { + safi = addr_block_get_safi(addr); + switch (addr->afi) { + case IANA_AFI_IPV4: + if (!addr_block_add_ipv4_addr(block, addr->type, + &addr->addr.ipv4, safi)) + return 0; + break; + case IANA_AFI_IPV6: + if (!addr_block_add_ipv6_addr(block, addr->type, + &addr->addr.ipv6, safi)) + return 0; + break; + default: + fprintf(stderr, "%s: corrupt test data", __func__); + exit(1); + } + } + + return 1; +} + +static int +build_addr_block_test(const struct build_addr_block_test_data *test) +{ + IPAddrBlocks *addrs = NULL, *parsed = NULL; + const unsigned char *p; + unsigned char *out = NULL; + int out_len; + int i; + int memcmp_failed = 1; + int failed = 1; + + if ((addrs = IPAddrBlocks_new()) == NULL) + goto err; + + if (!addr_block_add_addrs(addrs, test->addrs)) + goto err; + + if (X509v3_addr_is_canonical(addrs) != test->is_canonical) { + fprintf(stderr, "%s: \"%s\" X509v3_addr_is_canonical not %d\n", + __func__, test->description, test->is_canonical); + goto err; + } + + if (!X509v3_addr_canonize(addrs)) { + fprintf(stderr, "%s: \"%s\" failed to canonize\n", + __func__, test->description); + goto err; + } + + if (!X509v3_addr_is_canonical(addrs)) { + fprintf(stderr, "%s: \"%s\" canonization wasn't canonical\n", + __func__, test->description); + goto err; + } + + if ((out_len = i2d_IPAddrBlocks(addrs, &out)) <= 0) { + fprintf(stderr, "%s: \"%s\" i2d_IPAddrBlocks failed\n", + __func__, test->description); + goto err; + } + + memcmp_failed = (size_t)out_len != test->der_len; + if (!memcmp_failed) + memcmp_failed = memcmp(out, test->der, test->der_len); + if (memcmp_failed) { + report_hexdump(__func__, test->description, "memcmp DER failed", + test->der, test->der_len, out, out_len); + goto err; + } + + if (X509v3_addr_inherits(addrs) != test->inherits) { + fprintf(stderr, "%s: \"%s\" X509v3_addr_inherits not %d\n", + __func__, test->description, test->inherits); + goto err; + } + + for (i = 0; i < sk_IPAddressFamily_num(addrs) && i < test->afi_len; i++) { + IPAddressFamily *family; + unsigned int afi; + + family = sk_IPAddressFamily_value(addrs, i); + + if ((afi = X509v3_addr_get_afi(family)) == 0) { + fprintf(stderr, "%s: \"%s\" X509v3_addr_get_afi" + " failed\n", __func__, test->description); + goto err; + } + if (test->afis[i] != afi){ + fprintf(stderr, "%s: \"%s\" afi[%d] mismatch. " + "want: %u, got: %u\n", __func__, + test->description, i, test->afis[i], afi); + goto err; + } + } + if (i != test->afi_len) { + fprintf(stderr, "%s: \"%s\" checked %d afis, expected %d\n", + __func__, test->description, i, test->afi_len); + goto err; + } + + p = test->der; + if ((parsed = d2i_IPAddrBlocks(NULL, &p, test->der_len)) == NULL) { + fprintf(stderr, "%s: \"%s\" d2i_IPAddrBlocks failed\n", + __func__, test->description); + goto err; + } + if (!X509v3_addr_is_canonical(parsed)) { + fprintf(stderr, "%s: \"%s\" parsed AddrBlocks isn't canonical\n", + __func__, test->description); + goto err; + } + /* Can't compare IPAddrBlocks with inheritance. */ + if (!X509v3_addr_inherits(addrs) && !X509v3_addr_inherits(parsed)) { + if (!X509v3_addr_subset(addrs, parsed)) { + fprintf(stderr, "%s: \"%s\" addrs not subset of parsed\n", + __func__, test->description); + } + if (!X509v3_addr_subset(parsed, addrs)) { + fprintf(stderr, "%s: \"%s\" parsed not subset of addrs\n", + __func__, test->description); + } + } + + failed = 0; + + err: + IPAddrBlocks_free(addrs); + IPAddrBlocks_free(parsed); + free(out); + + return failed; +} + +static int +run_IPAddrBlock_tests(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_BUILD_ADDR_BLOCK_TESTS; i++) + failed |= build_addr_block_test(&build_addr_block_tests[i]); + + return failed; +} + +struct asid_or_range { + int type; + int inherit; + const unsigned char *min; + const unsigned char *max; +}; + +struct ASIdentifiers_build_test { + const char *description; + int should_build; + int inherits; + int canonical; + int should_canonize; + struct asid_or_range delegations[8]; + const unsigned char der[128]; + size_t der_len; +}; + +/* Sentinel value used for marking the end of the delegations table. */ +#define V3_ASID_END -1 + +const struct ASIdentifiers_build_test ASIdentifiers_build_data[] = { + { + .description = "RFC 3779, Appendix C", + .should_build = 1, + .inherits = 1, + .canonical = 1, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "135", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3000", + .max = "3999", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "5001", + .max = NULL, + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + .min = NULL, + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x1a, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02, + 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, + 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89, + 0xa1, 0x02, 0x05, 0x00, + }, + .der_len = 28, + }, + { + .description = "RFC 3779, Appendix C without rdi", + .should_build = 1, + .inherits = 0, + .canonical = 1, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "135", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3000", + .max = "3999", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "5001", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x16, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02, + 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, + 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89, + }, + .der_len = 24, + }, + { + .description = "RFC 3779, Appendix C variant", + .should_build = 1, + .inherits = 0, + .canonical = 1, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "135", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3000", + .max = "3999", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "5001", + .max = NULL, + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "135", + .max = NULL, + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "3000", + .max = "3999", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "5001", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x2c, 0xa0, 0x14, 0x30, 0x12, 0x02, 0x02, + 0x00, 0x87, 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, + 0x02, 0x02, 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89, + 0xa1, 0x14, 0x30, 0x12, 0x02, 0x02, 0x00, 0x87, + 0x30, 0x08, 0x02, 0x02, 0x0b, 0xb8, 0x02, 0x02, + 0x0f, 0x9f, 0x02, 0x02, 0x13, 0x89, + }, + .der_len = 46, + }, + { + .description = "inherit only", + .should_build = 1, + .inherits = 1, + .canonical = 1, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 1, + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x08, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x02, + 0x05, 0x00, + }, + .der_len = 10, + }, + { + .description = "adjacent unsorted ranges are merged", + .should_build = 1, + .inherits = 0, + .canonical = 0, + .should_canonize = 1, + .delegations = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "27", + .max = NULL, + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "28", + .max = "57", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "66", + .max = "68", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "58", + .max = "63", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "64", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x14, 0xa1, 0x12, 0x30, 0x10, 0x30, 0x06, + 0x02, 0x01, 0x1b, 0x02, 0x01, 0x40, 0x30, 0x06, + 0x02, 0x01, 0x42, 0x02, 0x01, 0x44, + }, + .der_len = 22, + }, + { + .description = "range of length 0", + .should_build = 1, + .inherits = 1, + .canonical = 1, + .should_canonize = 1, + .delegations = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "27", + .max = "27", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .der = { + 0x30, 0x10, 0xa0, 0x02, 0x05, 0x00, 0xa1, 0x0a, + 0x30, 0x08, 0x30, 0x06, 0x02, 0x01, 0x1b, 0x02, + 0x01, 0x1b, + }, + .der_len = 18, + }, + { + .description = "reversed range doesn't canonize", + .should_build = 1, + .inherits = 0, + .canonical = 0, + .should_canonize = 0, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "57", + .max = "42", + }, + { + .type = V3_ASID_END, + }, + }, + }, + { + .description = "overlapping ranges don't canonize", + .should_build = 1, + .inherits = 0, + .canonical = 0, + .should_canonize = 0, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "42", + .max = "57", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "57", + .max = "60", + }, + { + .type = V3_ASID_END, + }, + }, + }, + { + .description = "reversed interior range doesn't canonize", + .should_build = 1, + .inherits = 0, + .canonical = 0, + .should_canonize = 0, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "2", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "57", + .max = "42", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "65523", + .max = "65535", + }, + { + .type = V3_ASID_END, + }, + }, + }, + { + .description = "can't inherit and add AS ids", + .should_build = 0, + .inherits = 0, + .canonical = 0, + .should_canonize = 0, + .delegations = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "2", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + }, + { + .description = "can't inherit and add rdis", + .should_build = 0, + .inherits = 0, + .canonical = 0, + .should_canonize = 0, + .delegations = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "2", + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + }, +}; + +const size_t N_ASIDENTIFIERS_BUILD_TESTS = + sizeof(ASIdentifiers_build_data) / sizeof(ASIdentifiers_build_data[0]); + +static int +add_as_delegation(ASIdentifiers *asid, const struct asid_or_range *delegation) +{ + ASN1_INTEGER *min = NULL, *max = NULL; + int ret = 0; + + if (delegation->inherit) + return X509v3_asid_add_inherit(asid, delegation->type); + + if ((min = s2i_ASN1_INTEGER(NULL, delegation->min)) == NULL) + goto err; + + if (delegation->max != NULL) { + if ((max = s2i_ASN1_INTEGER(NULL, delegation->max)) == NULL) + goto err; + } + + if (!X509v3_asid_add_id_or_range(asid, delegation->type, min, max)) + goto err; + min = NULL; + max = NULL; + + ret = 1; + + err: + ASN1_INTEGER_free(min); + ASN1_INTEGER_free(max); + + return ret; +} + +static ASIdentifiers * +build_asid(const struct asid_or_range delegations[]) +{ + ASIdentifiers *asid = NULL; + const struct asid_or_range *delegation; + + if ((asid = ASIdentifiers_new()) == NULL) + goto err; + + for (delegation = &delegations[0]; delegation->type != V3_ASID_END; + delegation++) { + if (!add_as_delegation(asid, delegation)) + goto err; + } + + return asid; + + err: + ASIdentifiers_free(asid); + return NULL; +} + +static int +build_asid_test(const struct ASIdentifiers_build_test *test) +{ + ASIdentifiers *asid = NULL; + unsigned char *out = NULL; + int out_len; + int memcmp_failed = 1; + int failed = 1; + + if ((asid = build_asid(test->delegations)) == NULL) { + if (!test->should_build) { + failed = 0; + return failed; + } + fprintf(stderr, "%s: \"%s\" failed to build\n", __func__, + test->description); + return failed; + } + + if (!test->canonical) { + if (X509v3_asid_is_canonical(asid)) { + fprintf(stderr, "%s: \"%s\" shouldn't be canonical\n", + __func__, test->description); + goto err; + } + if (X509v3_asid_canonize(asid) != test->should_canonize) { + fprintf(stderr, "%s: \"%s\" failed to canonize\n", + __func__, test->description); + goto err; + } + if (!test->should_canonize) { + failed = 0; + goto err; + } + } + + /* + * Verify that asid is in canonical form before converting it to DER. + */ + if (!X509v3_asid_is_canonical(asid)) { + fprintf(stderr, "%s: asid is not canonical\n", __func__); + goto err; + } + + /* + * Convert asid to DER and check that it matches expectations + */ + out = NULL; + if ((out_len = i2d_ASIdentifiers(asid, &out)) <= 0) { + fprintf(stderr, "%s: \"%s\" i2d_ASIdentifiers failed\n", + __func__, test->description); + goto err; + } + + + memcmp_failed = (size_t)out_len != test->der_len; + if (!memcmp_failed) + memcmp_failed = memcmp(out, test->der, test->der_len); + if (memcmp_failed) { + report_hexdump(__func__, test->description, "memcmp DER failed", + test->der, test->der_len, out, out_len); + goto err; + } + + /* + * Verify that asid inherits as expected + */ + if (X509v3_asid_inherits(asid) != test->inherits) { + fprintf(stderr, "%s: \"%s\" unexpected asid inherit %d\n", + __func__, test->description, test->inherits); + goto err; + } + + failed = 0; + + err: + free(out); + ASIdentifiers_free(asid); + + return failed; +} + +static int +run_ASIdentifiers_build_test(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_ASIDENTIFIERS_BUILD_TESTS; i++) + failed |= build_asid_test(&ASIdentifiers_build_data[i]); + + return failed; +} + +struct ASIdentifiers_subset_test { + const char *description; + struct asid_or_range delegationsA[8]; + struct asid_or_range delegationsB[8]; + int is_subset; + int is_subset_if_canonized; +}; + +const struct ASIdentifiers_subset_test ASIdentifiers_subset_data[] = { + { + .description = "simple subset relation", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = "4", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 1, + .is_subset_if_canonized = 1, + }, + { + .description = "only asnums", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = "4", + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 1, + .is_subset_if_canonized = 1, + }, + { + .description = "only rdis", + .delegationsA = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 1, + .is_subset_if_canonized = 1, + }, + { + .description = "child only has asnums, parent only has rdis", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = "4", + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 0, + }, + { + .description = "child only has rdis, parent only has asnums", + .delegationsA = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "2", + .max = "4", + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 0, + }, + { + .description = "child only has rdis, parent has both", + .delegationsA = { + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "2", + .max = "4", + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 1, + .is_subset_if_canonized = 1, + }, + { + .description = "subset relation only after canonization", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3", + .max = "4", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "3", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "4", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 1, + }, + { + .description = "no subset if A inherits", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3", + .max = "4", + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "3", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "4", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "1", + .max = "5", + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 0, + }, + { + .description = "no subset if B inherits", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3", + .max = "4", + }, + { + .type = V3_ASID_RDI, + .inherit = 0, + .min = "5", + .max = NULL, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "3", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "4", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 0, + }, + { + .description = "no subset if both inherit", + .delegationsA = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "2", + .max = NULL, + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "3", + .max = "4", + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .delegationsB = { + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "1", + .max = "3", + }, + { + .type = V3_ASID_ASNUM, + .inherit = 0, + .min = "4", + .max = "5", + }, + { + .type = V3_ASID_RDI, + .inherit = 1, + }, + { + .type = V3_ASID_END, + }, + }, + .is_subset = 0, + .is_subset_if_canonized = 0, + }, +}; + +const size_t N_ASIDENTIFIERS_SUBSET_TESTS = + sizeof(ASIdentifiers_subset_data) / sizeof(ASIdentifiers_subset_data[0]); + +static int +asid_subset_test(const struct ASIdentifiers_subset_test *test) +{ + ASIdentifiers *asidA = NULL, *asidB = NULL; + int failed = 0; + + if ((asidA = build_asid(test->delegationsA)) == NULL) + goto err; + if ((asidB = build_asid(test->delegationsB)) == NULL) + goto err; + + if (X509v3_asid_subset(asidA, asidB) != test->is_subset) { + fprintf(stderr, "%s: \"%s\" X509v3_asid_subset failed\n", + __func__, test->description); + failed = 1; + } + + if (!test->is_subset) { + if (!X509v3_asid_canonize(asidA)) + goto err; + if (!X509v3_asid_canonize(asidB)) + goto err; + if (X509v3_asid_subset(asidA, asidB) != + test->is_subset_if_canonized) { + fprintf(stderr, "%s: \"%s\" canonized subset failed\n", + __func__, test->description); + failed = 1; + } + } + + err: + ASIdentifiers_free(asidA); + ASIdentifiers_free(asidB); + + return failed; +} + +static int +run_ASIdentifiers_subset_test(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_ASIDENTIFIERS_SUBSET_TESTS; i++) + failed |= asid_subset_test(&ASIdentifiers_subset_data[i]); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= run_IPAddressOrRange_tests(); + failed |= run_IPAddrBlock_tests(); + failed |= run_ASIdentifiers_build_test(); + failed |= run_ASIdentifiers_subset_test(); + + return failed; +} diff --git a/tests/rfc5280time.c b/tests/rfc5280time.c new file mode 100644 index 0000000..dfffb35 --- /dev/null +++ b/tests/rfc5280time.c @@ -0,0 +1,390 @@ +/* $OpenBSD: rfc5280time.c,v 1.7 2022/09/05 21:12:08 tb Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * Copyright (c) 2015 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +struct rfc5280_time_test { + const char *str; + const char *data; + time_t time; +}; + +struct rfc5280_time_test rfc5280_invtime_tests[] = { + { + .str = "", + }, + { + .str = "2015", + }, + { + .str = "201509", + }, + { + .str = "20150923", + }, + { + .str = "20150923032700", + }, + { + /* UTC time must have seconds */ + .str = "7001010000Z", + }, + { + .str = "201509230327Z", + }, + { + .str = "20150923032700.Z", + }, + { + .str = "20150923032700.123", + }, + { + .str = "20150923032700+1100Z", + }, + { + .str = "20150923032700-11001", + }, + { + /* UTC time cannot have fractional seconds. */ + .str = "150923032700.123Z", + }, + { + /* Gen time cannot have +- TZ. */ + .str = "20150923032712+1115", + }, + { + /* Gen time cannot have fractional seconds */ + .str = "20150923032712.123Z", + }, + { + .str = "aaaaaaaaaaaaaaZ", + }, + { + /* Must be a UTC time per RFC 5280 */ + .str = "19700101000000Z", + .data = "19700101000000Z", + .time = 0, + }, + { + /* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */ + .str = "20150923032700Z", + .data = "20150923032700Z", + .time = 1442978820, + }, +#if SIZEOF_TIME_T == 8 + { + /* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */ + .str = "00000101000000Z", + .data = "00000101000000Z", + .time = -62167219200LL, + }, + { + /* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */ + .str = "20491231235959Z", + .data = "20491231235959Z", + .time = 2524607999LL, + }, +#endif + { + /* (times before 2050 must be UTCTIME) Per RFC 5280 4.1.2.5 */ + .str = "19500101000000Z", + .data = "19500101000000Z", + .time = -631152000LL, + }, +}; + +struct rfc5280_time_test rfc5280_gentime_tests[] = { +#if SIZEOF_TIME_T == 8 + { + /* Biggest RFC 5280 time */ + .str = "99991231235959Z", + .data = "99991231235959Z", + .time = 253402300799LL, + }, + { + .str = "21600218104000Z", + .data = "21600218104000Z", + .time = 6000000000LL, + }, + { + /* Smallest RFC 5280 gen time */ + .str = "20500101000000Z", + .data = "20500101000000Z", + .time = 2524608000LL, + }, +#endif +}; +struct rfc5280_time_test rfc5280_utctime_tests[] = { + { + .str = "500101000000Z", + .data = "500101000000Z", + .time = -631152000, + }, + { + .str = "540226230640Z", + .data = "540226230640Z", + .time = -500000000, + }, +#if SIZEOF_TIME_T == 8 + { + .str = "491231235959Z", + .data = "491231235959Z", + .time = 2524607999LL, + }, +#endif + { + .str = "700101000000Z", + .data = "700101000000Z", + .time = 0, + }, + { + .str = "150923032700Z", + .data = "150923032700Z", + .time = 1442978820, + }, + { + .str = "150923102700Z", + .data = "150923102700Z", + .time = 1443004020, + }, + { + .str = "150922162712Z", + .data = "150922162712Z", + .time = 1442939232, + }, + { + .str = "140524144512Z", + .data = "140524144512Z", + .time = 1400942712, + }, + { + .str = "240401144512Z", + .data = "240401144512Z", + .time = 1711982712, + }, +}; + +#define N_INVTIME_TESTS \ + (sizeof(rfc5280_invtime_tests) / sizeof(*rfc5280_invtime_tests)) +#define N_GENTIME_TESTS \ + (sizeof(rfc5280_gentime_tests) / sizeof(*rfc5280_gentime_tests)) +#define N_UTCTIME_TESTS \ + (sizeof(rfc5280_utctime_tests) / sizeof(*rfc5280_utctime_tests)) + +static int +asn1_compare_str(int test_no, struct asn1_string_st *asn1str, const char *str) +{ + int length = strlen(str); + + if (asn1str->length != length) { + fprintf(stderr, "FAIL: test %d - string lengths differ " + "(%d != %d)\n", test_no, asn1str->length, length); + return (1); + } + if (strncmp(asn1str->data, str, length) != 0) { + fprintf(stderr, "FAIL: test %d - strings differ " + "('%s' != '%s')\n", test_no, asn1str->data, str); + return (1); + } + + return (0); +} + +static int +rfc5280_invtime_test(int test_no, struct rfc5280_time_test *att) +{ + ASN1_GENERALIZEDTIME *gt = NULL; + ASN1_UTCTIME *ut = NULL; + ASN1_TIME *t = NULL; + int failure = 1; + time_t now = time(NULL); + + if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL) + goto done; + if ((ut = ASN1_UTCTIME_new()) == NULL) + goto done; + if ((t = ASN1_TIME_new()) == NULL) + goto done; + + if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 0) { + if (X509_cmp_time(gt, &now) != 0) { + fprintf(stderr, "FAIL: test %d - successfully parsed as GENTIME " + "string '%s'\n", test_no, att->str); + goto done; + } + } + if (ASN1_UTCTIME_set_string(ut, att->str) != 0) { + if (X509_cmp_time(ut, &now) != 0) { + fprintf(stderr, "FAIL: test %d - successfully parsed as UTCTIME " + "string '%s'\n", test_no, att->str); + goto done; + } + } + if (ASN1_TIME_set_string(t, att->str) != 0) { + if (X509_cmp_time(t, &now) != 0) { + fprintf(stderr, "FAIL: test %d - successfully parsed as UTCTIME " + "string '%s'\n", test_no, att->str); + goto done; + } + } + + failure = 0; + + done: + ASN1_GENERALIZEDTIME_free(gt); + ASN1_UTCTIME_free(ut); + ASN1_TIME_free(t); + + return (failure); +} + +static int +rfc5280_gentime_test(int test_no, struct rfc5280_time_test *att) +{ + unsigned char *p = NULL; + ASN1_GENERALIZEDTIME *gt; + int failure = 1; + int i; + + if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL) + goto done; + + if (ASN1_GENERALIZEDTIME_set_string(gt, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + if (asn1_compare_str(test_no, gt, att->str) != 0) + goto done; + + if ((i = X509_cmp_time(gt, &att->time)) != -1) { + fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n", + test_no, i, (long long)att->time); + goto done; + } + + att->time--; + if ((i = X509_cmp_time(gt, &att->time)) != 1) { + fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n", + test_no, i, (long long)att->time); + goto done; + } + att->time++; + + ASN1_GENERALIZEDTIME_free(gt); + + if ((gt = ASN1_GENERALIZEDTIME_set(NULL, att->time)) == NULL) { + fprintf(stderr, "FAIL: test %d - failed to set time %lld\n", + test_no, (long long)att->time); + goto done; + } + if (asn1_compare_str(test_no, gt, att->data) != 0) + goto done; + + failure = 0; + + done: + ASN1_GENERALIZEDTIME_free(gt); + free(p); + + return (failure); +} + +static int +rfc5280_utctime_test(int test_no, struct rfc5280_time_test *att) +{ + unsigned char *p = NULL; + ASN1_UTCTIME *ut; + int failure = 1; + int i; + + if ((ut = ASN1_UTCTIME_new()) == NULL) + goto done; + + if (ASN1_UTCTIME_set_string(ut, att->str) != 1) { + fprintf(stderr, "FAIL: test %d - failed to set string '%s'\n", + test_no, att->str); + goto done; + } + if (asn1_compare_str(test_no, ut, att->str) != 0) + goto done; + + if ((i = X509_cmp_time(ut, &att->time)) != -1) { + fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n", + test_no, i, (long long)att->time); + goto done; + } + + att->time--; + if ((i = X509_cmp_time(ut, &att->time)) != 1) { + fprintf(stderr, "FAIL: test %d - X509_cmp_time failed - returned %d compared to %lld\n", + test_no, i, (long long)att->time); + goto done; + } + att->time++; + + ASN1_UTCTIME_free(ut); + + if ((ut = ASN1_UTCTIME_set(NULL, att->time)) == NULL) { + fprintf(stderr, "FAIL: test %d - failed to set time %lld\n", + test_no, (long long)att->time); + goto done; + } + if (asn1_compare_str(test_no, ut, att->data) != 0) + goto done; + + failure = 0; + + done: + ASN1_UTCTIME_free(ut); + free(p); + + return (failure); +} + +int +main(int argc, char **argv) +{ + struct rfc5280_time_test *att; + int failed = 0; + size_t i; + + fprintf(stderr, "RFC5280 Invalid time tests...\n"); + for (i = 0; i < N_INVTIME_TESTS; i++) { + att = &rfc5280_invtime_tests[i]; + failed |= rfc5280_invtime_test(i, att); + } + + fprintf(stderr, "RFC5280 GENERALIZEDTIME tests...\n"); + for (i = 0; i < N_GENTIME_TESTS; i++) { + att = &rfc5280_gentime_tests[i]; + failed |= rfc5280_gentime_test(i, att); + } + + fprintf(stderr, "RFC5280 UTCTIME tests...\n"); + for (i = 0; i < N_UTCTIME_TESTS; i++) { + att = &rfc5280_utctime_tests[i]; + failed |= rfc5280_utctime_test(i, att); + } + return (failed); +} diff --git a/tests/rmd_test.c b/tests/rmd_test.c new file mode 100644 index 0000000..0a88a9b --- /dev/null +++ b/tests/rmd_test.c @@ -0,0 +1,201 @@ +/* $OpenBSD: rmd_test.c,v 1.1 2022/09/02 15:45:52 tb Exp $ */ +/* + * Copyright (c) 2022 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct rmd_test { + const uint8_t in[128]; + const size_t in_len; + const uint8_t out[EVP_MAX_MD_SIZE]; +}; + +static const struct rmd_test rmd_tests[] = { + /* + * RIPEMD-160 - Test vectors from + * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html + */ + { + .in = "", + .in_len = 0, + .out = { + 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, + 0x61, 0x28, 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, + 0xb2, 0x25, 0x8d, 0x31, + }, + }, + { + .in = "a", + .in_len = 1, + .out = { + 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, + 0xda, 0xae, 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, + 0x5a, 0x46, 0x7f, 0xfe, + }, + }, + { + .in = "abc", + .in_len = 3, + .out = { + 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, + 0x9b, 0x04, 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, + 0xf1, 0x5a, 0x0b, 0xfc, + }, + }, + { + .in = "message digest", + .in_len = 14, + .out = { + 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, + 0x72, 0xb8, 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, + 0x21, 0x59, 0x5f, 0x36, + }, + }, + { + .in = "abcdefghijklmnopqrstuvwxyz", + .in_len = 26, + .out = { + 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, + 0x56, 0xbb, 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, + 0xb3, 0x70, 0x8d, 0xbc, + }, + }, + { + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + .in_len = 56, + .out = { + 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, + 0xe4, 0x05, 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, + 0xda, 0x62, 0xeb, 0x2b, + }, + }, + { + .in = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" + "wxyz0123456789", + .in_len = 62, + .out = { + 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, + 0x86, 0xed, 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, + 0xb2, 0x1f, 0x51, 0x89, + }, + }, + { + .in = + "123456789012345678901234567890123456789012345678" + "90123456789012345678901234567890", + .in_len = 80, + .out = { + 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, + 0xf4, 0xdb, 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, + 0x63, 0x32, 0x6b, 0xfb, + }, + }, +}; + +#define N_RMD_TESTS (sizeof(rmd_tests) / sizeof(rmd_tests[0])) + +static int +rmd_test(void) +{ + const struct rmd_test *rt; + EVP_MD_CTX *hash = NULL; + uint8_t out[EVP_MAX_MD_SIZE]; + size_t in_len; + size_t i; + int failed = 1; + + if ((hash = EVP_MD_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); + goto failed; + } + + for (i = 0; i < N_RMD_TESTS; i++) { + rt = &rmd_tests[i]; + + /* Digest */ + memset(out, 0, sizeof(out)); + RIPEMD160(rt->in, rt->in_len, out); + if (memcmp(rt->out, out, RIPEMD160_DIGEST_LENGTH) != 0) { + fprintf(stderr, "FAIL: mismatch\n"); + goto failed; + } + + /* EVP single-shot digest */ + memset(out, 0, sizeof(out)); + if (!EVP_Digest(rt->in, rt->in_len, out, NULL, EVP_ripemd160(), NULL)) { + fprintf(stderr, "FAIL: EVP_Digest failed\n"); + goto failed; + } + + if (memcmp(rt->out, out, RIPEMD160_DIGEST_LENGTH) != 0) { + fprintf(stderr, "FAIL: EVP single-shot mismatch\n"); + goto failed; + } + + /* EVP digest */ + memset(out, 0, sizeof(out)); + if (!EVP_DigestInit_ex(hash, EVP_ripemd160(), NULL)) { + fprintf(stderr, "FAIL: EVP_DigestInit_ex failed\n"); + goto failed; + } + + in_len = rt->in_len / 2; + if (!EVP_DigestUpdate(hash, rt->in, in_len)) { + fprintf(stderr, + "FAIL: EVP_DigestUpdate first half failed\n"); + goto failed; + } + + if (!EVP_DigestUpdate(hash, rt->in + in_len, + rt->in_len - in_len)) { + fprintf(stderr, + "FAIL: EVP_DigestUpdate second half failed\n"); + goto failed; + } + + if (!EVP_DigestFinal_ex(hash, out, NULL)) { + fprintf(stderr, "FAIL: EVP_DigestFinal_ex failed\n"); + goto failed; + } + + if (memcmp(rt->out, out, RIPEMD160_DIGEST_LENGTH) != 0) { + fprintf(stderr, "FAIL: EVP mismatch\n"); + goto failed; + } + } + + failed = 0; + + failed: + EVP_MD_CTX_free(hash); + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= rmd_test(); + + return failed; +} diff --git a/tests/rsa_test.c b/tests/rsa_test.c new file mode 100644 index 0000000..6fd0ddc --- /dev/null +++ b/tests/rsa_test.c @@ -0,0 +1,472 @@ +/* $OpenBSD: rsa_test.c,v 1.4 2021/11/25 16:51:31 tb Exp $ */ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* test vectors from p1ovect1.txt */ + +#include +#include + +#include +#include +#include +#include + +#ifdef OPENSSL_NO_RSA +int main(int argc, char *argv[]) +{ + printf("No RSA support\n"); + return (0); +} +#else +# include + +static int +key1(RSA *key, unsigned char *c) +{ + static unsigned char n[] = + "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F" + "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5" + "\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93" + "\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1" + "\xF5"; + + static unsigned char e[] = "\x11"; + + static unsigned char d[] = + "\x0A\x03\x37\x48\x62\x64\x87\x69\x5F\x5F\x30\xBC\x38\xB9\x8B\x44" + "\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64" + "\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9" + "\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51"; + + static unsigned char p[] = + "\x00\xD8\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5" + "\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x12" + "\x0D"; + + static unsigned char q[] = + "\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9" + "\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D" + "\x89"; + + static unsigned char dmp1[] = + "\x59\x0B\x95\x72\xA2\xC2\xA9\xC4\x06\x05\x9D\xC2\xAB\x2F\x1D\xAF" + "\xEB\x7E\x8B\x4F\x10\xA7\x54\x9E\x8E\xED\xF5\xB4\xFC\xE0\x9E\x05"; + + static unsigned char dmq1[] = + "\x00\x8E\x3C\x05\x21\xFE\x15\xE0\xEA\x06\xA3\x6F\xF0\xF1\x0C\x99" + "\x52\xC3\x5B\x7A\x75\x14\xFD\x32\x38\xB8\x0A\xAD\x52\x98\x62\x8D" + "\x51"; + + static unsigned char iqmp[] = + "\x36\x3F\xF7\x18\x9D\xA8\xE9\x0B\x1D\x34\x1F\x71\xD0\x9B\x76\xA8" + "\xA9\x43\xE1\x1D\x10\xB2\x4D\x24\x9F\x2D\xEA\xFE\xF8\x0C\x18\x26"; + + static unsigned char ctext_ex[] = + "\x1b\x8f\x05\xf9\xca\x1a\x79\x52\x6e\x53\xf3\xcc\x51\x4f\xdb\x89" + "\x2b\xfb\x91\x93\x23\x1e\x78\xb9\x92\xe6\x8d\x50\xa4\x80\xcb\x52" + "\x33\x89\x5c\x74\x95\x8d\x5d\x02\xab\x8c\x0f\xd0\x40\xeb\x58\x44" + "\xb0\x05\xc3\x9e\xd8\x27\x4a\x9d\xbf\xa8\x06\x71\x40\x94\x39\xd2"; + + BIGNUM *bn_n = NULL, *bn_e = NULL, *bn_d = NULL; + BIGNUM *bn_p = NULL, *bn_q = NULL; + BIGNUM *bn_dmp1 = NULL, *bn_dmq1 = NULL, *bn_iqmp = NULL; + + bn_n = BN_bin2bn(n, sizeof(n) - 1, NULL); + bn_e = BN_bin2bn(e, sizeof(e) - 1, NULL); + bn_d = BN_bin2bn(d, sizeof(d) - 1, NULL); + if (bn_n == NULL || bn_e == NULL || bn_d == NULL) + goto err; + if (!RSA_set0_key(key, bn_n, bn_e, bn_d)) + goto err; + bn_n = NULL; + bn_e = NULL; + bn_d = NULL; + + bn_p = BN_bin2bn(p, sizeof(p) - 1, NULL); + bn_q = BN_bin2bn(q, sizeof(q) - 1, NULL); + if (bn_p == NULL || bn_q == NULL) + goto err; + if (!RSA_set0_factors(key, bn_p, bn_q)) + goto err; + bn_p = NULL; + bn_q = NULL; + + bn_dmp1 = BN_bin2bn(dmp1, sizeof(dmp1) - 1, NULL); + bn_dmq1 = BN_bin2bn(dmq1, sizeof(dmq1) - 1, NULL); + bn_iqmp = BN_bin2bn(iqmp, sizeof(iqmp) - 1, NULL); + if (bn_dmp1 == NULL || bn_dmq1 == NULL || bn_iqmp == NULL) + goto err; + if (!RSA_set0_crt_params(key, bn_dmp1, bn_dmq1, bn_iqmp)) + goto err; + bn_dmp1 = NULL; + bn_dmq1 = NULL; + bn_iqmp = NULL; + + memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); + return sizeof(ctext_ex) - 1; + + err: + BN_free(bn_n); + BN_free(bn_e); + BN_free(bn_d); + BN_free(bn_p); + BN_free(bn_q); + BN_free(bn_dmp1); + BN_free(bn_dmq1); + BN_free(bn_iqmp); + + return -1; +} + +static int +key2(RSA *key, unsigned char *c) +{ + static unsigned char n[] = + "\x00\xA3\x07\x9A\x90\xDF\x0D\xFD\x72\xAC\x09\x0C\xCC\x2A\x78\xB8" + "\x74\x13\x13\x3E\x40\x75\x9C\x98\xFA\xF8\x20\x4F\x35\x8A\x0B\x26" + "\x3C\x67\x70\xE7\x83\xA9\x3B\x69\x71\xB7\x37\x79\xD2\x71\x7B\xE8" + "\x34\x77\xCF"; + + static unsigned char e[] = "\x3"; + + static unsigned char d[] = + "\x6C\xAF\xBC\x60\x94\xB3\xFE\x4C\x72\xB0\xB3\x32\xC6\xFB\x25\xA2" + "\xB7\x62\x29\x80\x4E\x68\x65\xFC\xA4\x5A\x74\xDF\x0F\x8F\xB8\x41" + "\x3B\x52\xC0\xD0\xE5\x3D\x9B\x59\x0F\xF1\x9B\xE7\x9F\x49\xDD\x21" + "\xE5\xEB"; + + static unsigned char p[] = + "\x00\xCF\x20\x35\x02\x8B\x9D\x86\x98\x40\xB4\x16\x66\xB4\x2E\x92" + "\xEA\x0D\xA3\xB4\x32\x04\xB5\xCF\xCE\x91"; + + static unsigned char q[] = + "\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9" + "\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5F"; + + static unsigned char dmp1[] = + "\x00\x8A\x15\x78\xAC\x5D\x13\xAF\x10\x2B\x22\xB9\x99\xCD\x74\x61" + "\xF1\x5E\x6D\x22\xCC\x03\x23\xDF\xDF\x0B"; + + static unsigned char dmq1[] = + "\x00\x86\x55\x21\x4A\xC5\x4D\x8D\x4E\xCD\x61\x77\xF1\xC7\x36\x90" + "\xCE\x2A\x48\x2C\x8B\x05\x99\xCB\xE0\x3F"; + + static unsigned char iqmp[] = + "\x00\x83\xEF\xEF\xB8\xA9\xA4\x0D\x1D\xB6\xED\x98\xAD\x84\xED\x13" + "\x35\xDC\xC1\x08\xF3\x22\xD0\x57\xCF\x8D"; + + static unsigned char ctext_ex[] = + "\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a" + "\x8b\x40\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4" + "\x17\x53\x03\x29\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52" + "\x62\x51"; + + BIGNUM *bn_n = NULL, *bn_e = NULL, *bn_d = NULL; + BIGNUM *bn_p = NULL, *bn_q = NULL; + BIGNUM *bn_dmp1 = NULL, *bn_dmq1 = NULL, *bn_iqmp = NULL; + + bn_n = BN_bin2bn(n, sizeof(n) - 1, NULL); + bn_e = BN_bin2bn(e, sizeof(e) - 1, NULL); + bn_d = BN_bin2bn(d, sizeof(d) - 1, NULL); + if (bn_n == NULL || bn_e == NULL || bn_d == NULL) + goto err; + if (!RSA_set0_key(key, bn_n, bn_e, bn_d)) + goto err; + bn_n = NULL; + bn_e = NULL; + bn_d = NULL; + + bn_p = BN_bin2bn(p, sizeof(p) - 1, NULL); + bn_q = BN_bin2bn(q, sizeof(q) - 1, NULL); + if (bn_p == NULL || bn_q == NULL) + goto err; + if (!RSA_set0_factors(key, bn_p, bn_q)) + goto err; + bn_p = NULL; + bn_q = NULL; + + bn_dmp1 = BN_bin2bn(dmp1, sizeof(dmp1) - 1, NULL); + bn_dmq1 = BN_bin2bn(dmq1, sizeof(dmq1) - 1, NULL); + bn_iqmp = BN_bin2bn(iqmp, sizeof(iqmp) - 1, NULL); + if (bn_dmp1 == NULL || bn_dmq1 == NULL || bn_iqmp == NULL) + goto err; + if (!RSA_set0_crt_params(key, bn_dmp1, bn_dmq1, bn_iqmp)) + goto err; + bn_dmp1 = NULL; + bn_dmq1 = NULL; + bn_iqmp = NULL; + + memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); + return sizeof(ctext_ex) - 1; + + err: + BN_free(bn_n); + BN_free(bn_e); + BN_free(bn_d); + BN_free(bn_p); + BN_free(bn_q); + BN_free(bn_dmp1); + BN_free(bn_dmq1); + BN_free(bn_iqmp); + + return -1; +} + +static int +key3(RSA *key, unsigned char *c) +{ + static unsigned char n[] = + "\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71" + "\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5" + "\x1F\xB8\xDF\xBA\xAF\x03\x5C\x02\xAB\x61\xEA\x48\xCE\xEB\x6F\xCD" + "\x48\x76\xED\x52\x0D\x60\xE1\xEC\x46\x19\x71\x9D\x8A\x5B\x8B\x80" + "\x7F\xAF\xB8\xE0\xA3\xDF\xC7\x37\x72\x3E\xE6\xB4\xB7\xD9\x3A\x25" + "\x84\xEE\x6A\x64\x9D\x06\x09\x53\x74\x88\x34\xB2\x45\x45\x98\x39" + "\x4E\xE0\xAA\xB1\x2D\x7B\x61\xA5\x1F\x52\x7A\x9A\x41\xF6\xC1\x68" + "\x7F\xE2\x53\x72\x98\xCA\x2A\x8F\x59\x46\xF8\xE5\xFD\x09\x1D\xBD" + "\xCB"; + + static unsigned char e[] = "\x11"; + + static unsigned char d[] = + "\x00\xA5\xDA\xFC\x53\x41\xFA\xF2\x89\xC4\xB9\x88\xDB\x30\xC1\xCD" + "\xF8\x3F\x31\x25\x1E\x06\x68\xB4\x27\x84\x81\x38\x01\x57\x96\x41" + "\xB2\x94\x10\xB3\xC7\x99\x8D\x6B\xC4\x65\x74\x5E\x5C\x39\x26\x69" + "\xD6\x87\x0D\xA2\xC0\x82\xA9\x39\xE3\x7F\xDC\xB8\x2E\xC9\x3E\xDA" + "\xC9\x7F\xF3\xAD\x59\x50\xAC\xCF\xBC\x11\x1C\x76\xF1\xA9\x52\x94" + "\x44\xE5\x6A\xAF\x68\xC5\x6C\x09\x2C\xD3\x8D\xC3\xBE\xF5\xD2\x0A" + "\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94" + "\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3" + "\xC1"; + + static unsigned char p[] = + "\x00\xEE\xCF\xAE\x81\xB1\xB9\xB3\xC9\x08\x81\x0B\x10\xA1\xB5\x60" + "\x01\x99\xEB\x9F\x44\xAE\xF4\xFD\xA4\x93\xB8\x1A\x9E\x3D\x84\xF6" + "\x32\x12\x4E\xF0\x23\x6E\x5D\x1E\x3B\x7E\x28\xFA\xE7\xAA\x04\x0A" + "\x2D\x5B\x25\x21\x76\x45\x9D\x1F\x39\x75\x41\xBA\x2A\x58\xFB\x65" + "\x99"; + + static unsigned char q[] = + "\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9" + "\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D" + "\x86\x98\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5" + "\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x15" + "\x03"; + + static unsigned char dmp1[] = + "\x54\x49\x4C\xA6\x3E\xBA\x03\x37\xE4\xE2\x40\x23\xFC\xD6\x9A\x5A" + "\xEB\x07\xDD\xDC\x01\x83\xA4\xD0\xAC\x9B\x54\xB0\x51\xF2\xB1\x3E" + "\xD9\x49\x09\x75\xEA\xB7\x74\x14\xFF\x59\xC1\xF7\x69\x2E\x9A\x2E" + "\x20\x2B\x38\xFC\x91\x0A\x47\x41\x74\xAD\xC9\x3C\x1F\x67\xC9\x81"; + + static unsigned char dmq1[] = + "\x47\x1E\x02\x90\xFF\x0A\xF0\x75\x03\x51\xB7\xF8\x78\x86\x4C\xA9" + "\x61\xAD\xBD\x3A\x8A\x7E\x99\x1C\x5C\x05\x56\xA9\x4C\x31\x46\xA7" + "\xF9\x80\x3F\x8F\x6F\x8A\xE3\x42\xE9\x31\xFD\x8A\xE4\x7A\x22\x0D" + "\x1B\x99\xA4\x95\x84\x98\x07\xFE\x39\xF9\x24\x5A\x98\x36\xDA\x3D"; + + static unsigned char iqmp[] = + "\x00\xB0\x6C\x4F\xDA\xBB\x63\x01\x19\x8D\x26\x5B\xDB\xAE\x94\x23" + "\xB3\x80\xF2\x71\xF7\x34\x53\x88\x50\x93\x07\x7F\xCD\x39\xE2\x11" + "\x9F\xC9\x86\x32\x15\x4F\x58\x83\xB1\x67\xA9\x67\xBF\x40\x2B\x4E" + "\x9E\x2E\x0F\x96\x56\xE6\x98\xEA\x36\x66\xED\xFB\x25\x79\x80\x39" + "\xF7"; + + static unsigned char ctext_ex[] = + "\xb8\x24\x6b\x56\xa6\xed\x58\x81\xae\xb5\x85\xd9\xa2\x5b\x2a\xd7" + "\x90\xc4\x17\xe0\x80\x68\x1b\xf1\xac\x2b\xc3\xde\xb6\x9d\x8b\xce" + "\xf0\xc4\x36\x6f\xec\x40\x0a\xf0\x52\xa7\x2e\x9b\x0e\xff\xb5\xb3" + "\xf2\xf1\x92\xdb\xea\xca\x03\xc1\x27\x40\x05\x71\x13\xbf\x1f\x06" + "\x69\xac\x22\xe9\xf3\xa7\x85\x2e\x3c\x15\xd9\x13\xca\xb0\xb8\x86" + "\x3a\x95\xc9\x92\x94\xce\x86\x74\x21\x49\x54\x61\x03\x46\xf4\xd4" + "\x74\xb2\x6f\x7c\x48\xb4\x2e\xe6\x8e\x1f\x57\x2a\x1f\xc4\x02\x6a" + "\xc4\x56\xb4\xf5\x9f\x7b\x62\x1e\xa1\xb9\xd8\x8f\x64\x20\x2f\xb1"; + + BIGNUM *bn_n = NULL, *bn_e = NULL, *bn_d = NULL; + BIGNUM *bn_p = NULL, *bn_q = NULL; + BIGNUM *bn_dmp1 = NULL, *bn_dmq1 = NULL, *bn_iqmp = NULL; + + bn_n = BN_bin2bn(n, sizeof(n) - 1, NULL); + bn_e = BN_bin2bn(e, sizeof(e) - 1, NULL); + bn_d = BN_bin2bn(d, sizeof(d) - 1, NULL); + if (bn_n == NULL || bn_e == NULL || bn_d == NULL) + goto err; + if (!RSA_set0_key(key, bn_n, bn_e, bn_d)) + goto err; + bn_n = NULL; + bn_e = NULL; + bn_d = NULL; + + bn_p = BN_bin2bn(p, sizeof(p) - 1, NULL); + bn_q = BN_bin2bn(q, sizeof(q) - 1, NULL); + if (bn_p == NULL || bn_q == NULL) + goto err; + if (!RSA_set0_factors(key, bn_p, bn_q)) + goto err; + bn_p = NULL; + bn_q = NULL; + + bn_dmp1 = BN_bin2bn(dmp1, sizeof(dmp1) - 1, NULL); + bn_dmq1 = BN_bin2bn(dmq1, sizeof(dmq1) - 1, NULL); + bn_iqmp = BN_bin2bn(iqmp, sizeof(iqmp) - 1, NULL); + if (bn_dmp1 == NULL || bn_dmq1 == NULL || bn_iqmp == NULL) + goto err; + if (!RSA_set0_crt_params(key, bn_dmp1, bn_dmq1, bn_iqmp)) + goto err; + bn_dmp1 = NULL; + bn_dmq1 = NULL; + bn_iqmp = NULL; + + memcpy(c, ctext_ex, sizeof(ctext_ex) - 1); + + return sizeof(ctext_ex) - 1; + + err: + BN_free(bn_n); + BN_free(bn_e); + BN_free(bn_d); + BN_free(bn_p); + BN_free(bn_q); + BN_free(bn_dmp1); + BN_free(bn_dmq1); + BN_free(bn_iqmp); + + return -1; +} + +static int +pad_unknown(void) +{ + unsigned long l; + while ((l = ERR_get_error()) != 0) + if (ERR_GET_REASON(l) == RSA_R_UNKNOWN_PADDING_TYPE) + return (1); + return (0); +} + +int +main(int argc, char *argv[]) +{ + int err = 0; + int v; + RSA *key; + unsigned char ptext[256]; + unsigned char ctext[256]; + static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a"; + unsigned char ctext_ex[256]; + int plen; + int clen = 0; + int num; + int n; + + plen = sizeof(ptext_ex) - 1; + + for (v = 0; v < 3; v++) { + key = RSA_new(); + switch (v) { + case 0: + clen = key1(key, ctext_ex); + break; + case 1: + clen = key2(key, ctext_ex); + break; + case 2: + clen = key3(key, ctext_ex); + break; + } + + if (clen <= 0) { + printf("failed to generate key%d\n", v); + err = 1; + goto next; + } + + num = RSA_public_encrypt(plen, ptext_ex, ctext, key, + RSA_PKCS1_PADDING); + if (num != clen) { + printf("PKCS#1 v1.5 encryption failed!\n"); + err = 1; + goto oaep; + } + + num = RSA_private_decrypt(num, ctext, ptext, key, + RSA_PKCS1_PADDING); + if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { + printf("PKCS#1 v1.5 decryption failed!\n"); + err = 1; + } else + printf("PKCS #1 v1.5 encryption/decryption ok\n"); + + oaep: + ERR_clear_error(); + num = RSA_public_encrypt(plen, ptext_ex, ctext, key, + RSA_PKCS1_OAEP_PADDING); + if (num == -1 && pad_unknown()) { + printf("No OAEP support\n"); + goto next; + } + if (num != clen) { + printf("OAEP encryption failed!\n"); + err = 1; + goto next; + } + + num = RSA_private_decrypt(num, ctext, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { + printf("OAEP decryption (encrypted data) failed!\n"); + err = 1; + } else if (memcmp(ctext, ctext_ex, num) == 0) + printf("OAEP test vector %d passed!\n", v); + + /* + * Different ciphertexts (rsa_oaep.c without -DPKCS_TESTVECT). + * Try decrypting ctext_ex + */ + + num = RSA_private_decrypt(clen, ctext_ex, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (num != plen || memcmp(ptext, ptext_ex, num) != 0) { + printf("OAEP decryption (test vector data) failed!\n"); + err = 1; + } else + printf("OAEP encryption/decryption ok\n"); + + /* Try decrypting corrupted ciphertexts. */ + for (n = 0; n < clen; ++n) { + ctext[n] ^= 1; + num = RSA_private_decrypt(clen, ctext, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (num > 0) { + printf("Corrupt data decrypted!\n"); + err = 1; + break; + } + ctext[n] ^= 1; + } + + /* Test truncated ciphertexts, as well as negative length. */ + for (n = -1; n < clen; ++n) { + num = RSA_private_decrypt(n, ctext, ptext, key, + RSA_PKCS1_OAEP_PADDING); + if (num > 0) { + printf("Truncated data decrypted!\n"); + err = 1; + break; + } + } + + next: + RSA_free(key); + } + + return err; +} +#endif diff --git a/tests/server.c b/tests/server.c new file mode 100644 index 0000000..a634adb --- /dev/null +++ b/tests/server.c @@ -0,0 +1,321 @@ +/* $OpenBSD: server.c,v 1.12 2023/02/01 14:39:09 tb Exp $ */ +/* + * Copyright (c) 2018-2019 Alexander Bluhm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "util.h" + +void __dead usage(void); + +void __dead +usage(void) +{ + fprintf(stderr, "usage: server [-Lsvv] [-C CA] [-c crt -k key] " + "[-l ciphers] [-p dhparam] [-V version] [host port]\n"); + exit(2); +} + +int +main(int argc, char *argv[]) +{ + const SSL_METHOD *method; + SSL_CTX *ctx; + SSL *ssl; + BIO *abio, *cbio; + SSL_SESSION *session; + int ch, error, listciphers = 0, sessionreuse = 0, verify = 0; + int version = 0; + char buf[256], *dhparam = NULL; + char *ca = NULL, *crt = NULL, *key = NULL, *ciphers = NULL; + char *host_port, *host = "127.0.0.1", *port = "0"; + + while ((ch = getopt(argc, argv, "C:c:k:Ll:p:sV:v")) != -1) { + switch (ch) { + case 'C': + ca = optarg; + break; + case 'c': + crt = optarg; + break; + case 'k': + key = optarg; + break; + case 'L': + listciphers = 1; + break; + case 'l': + ciphers = optarg; + break; + case 'p': + dhparam = optarg; + break; + case 's': + /* multiple reueses are possible */ + sessionreuse++; + break; + case 'V': + if (strcmp(optarg, "TLS1") == 0) { + version = TLS1_VERSION; + } else if (strcmp(optarg, "TLS1_1") == 0) { + version = TLS1_1_VERSION; + } else if (strcmp(optarg, "TLS1_2") == 0) { + version = TLS1_2_VERSION; + } else if (strcmp(optarg, "TLS1_3") == 0) { + version = TLS1_3_VERSION; + } else { + errx(1, "unknown protocol version: %s", optarg); + } + break; + case 'v': + /* use twice to force client cert */ + verify++; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc == 2) { + host = argv[0]; + port = argv[1]; + } else if (argc != 0 && !listciphers) { + usage(); + } + if (asprintf(&host_port, strchr(host, ':') ? "[%s]:%s" : "%s:%s", + host, port) == -1) + err(1, "asprintf host port"); + if ((crt == NULL && key != NULL) || (crt != NULL && key == NULL)) + errx(1, "certificate and private key must be used together"); + if (crt == NULL && asprintf(&crt, "%s.crt", host) == -1) + err(1, "asprintf crt"); + if (key == NULL && asprintf(&key, "%s.key", host) == -1) + err(1, "asprintf key"); + + SSL_library_init(); + SSL_load_error_strings(); + print_version(); + + /* setup method and context */ +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + method = TLS_server_method(); + if (method == NULL) + err_ssl(1, "TLS_server_method"); +#else + switch (version) { + case TLS1_VERSION: + method = TLSv1_server_method(); + break; + case TLS1_1_VERSION: + method = TLSv1_1_server_method(); + break; + case TLS1_2_VERSION: + method = TLSv1_2_server_method(); + break; +#ifdef TLS1_3_VERSION + case TLS1_3_VERSION: + err(1, "TLS1_3 not supported"); +#endif + default: + method = SSLv23_server_method(); + break; + } + if (method == NULL) + err_ssl(1, "SSLv23_server_method"); +#endif + ctx = SSL_CTX_new(method); + if (ctx == NULL) + err_ssl(1, "SSL_CTX_new"); + +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + if (version) { + if (SSL_CTX_set_min_proto_version(ctx, version) != 1) + err_ssl(1, "SSL_CTX_set_min_proto_version"); + if (SSL_CTX_set_max_proto_version(ctx, version) != 1) + err_ssl(1, "SSL_CTX_set_max_proto_version"); + } +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + /* needed to use DHE cipher with libressl */ + if (SSL_CTX_set_dh_auto(ctx, 1) <= 0) + err_ssl(1, "SSL_CTX_set_dh_auto"); +#endif + /* needed to use ADH, EDH, DHE cipher with openssl */ + if (dhparam != NULL) { + DH *dh; + FILE *file; + + file = fopen(dhparam, "r"); + if (file == NULL) + err(1, "fopen %s", dhparam); + dh = PEM_read_DHparams(file, NULL, NULL, NULL); + if (dh == NULL) + err_ssl(1, "PEM_read_DHparams"); + if (SSL_CTX_set_tmp_dh(ctx, dh) <= 0) + err_ssl(1, "SSL_CTX_set_tmp_dh"); + fclose(file); + } + + /* load server certificate */ + if (SSL_CTX_use_certificate_file(ctx, crt, SSL_FILETYPE_PEM) <= 0) + err_ssl(1, "SSL_CTX_use_certificate_file"); + if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) + err_ssl(1, "SSL_CTX_use_PrivateKey_file"); + if (SSL_CTX_check_private_key(ctx) <= 0) + err_ssl(1, "SSL_CTX_check_private_key"); + + /* request client certificate and verify it */ + if (ca != NULL) { + STACK_OF(X509_NAME) *x509stack; + + x509stack = SSL_load_client_CA_file(ca); + if (x509stack == NULL) + err_ssl(1, "SSL_load_client_CA_file"); + SSL_CTX_set_client_CA_list(ctx, x509stack); + if (SSL_CTX_load_verify_locations(ctx, ca, NULL) <= 0) + err_ssl(1, "SSL_CTX_load_verify_locations"); + } + SSL_CTX_set_verify(ctx, + verify == 0 ? SSL_VERIFY_NONE : + verify == 1 ? SSL_VERIFY_PEER : + SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + verify_callback); + + if (sessionreuse) { + uint32_t context; + + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); + context = arc4random(); + if (SSL_CTX_set_session_id_context(ctx, + (unsigned char *)&context, sizeof(context)) <= 0) + err_ssl(1, "SSL_CTX_set_session_id_context"); + } + + if (ciphers) { + if (SSL_CTX_set_cipher_list(ctx, ciphers) <= 0) + err_ssl(1, "SSL_CTX_set_cipher_list"); + } + + if (listciphers) { + STACK_OF(SSL_CIPHER) *supported_ciphers; + + ssl = SSL_new(ctx); + if (ssl == NULL) + err_ssl(1, "SSL_new"); + supported_ciphers = SSL_get1_supported_ciphers(ssl); + if (supported_ciphers == NULL) + err_ssl(1, "SSL_get1_supported_ciphers"); + print_ciphers(supported_ciphers); + + sk_SSL_CIPHER_free(supported_ciphers); + return 0; + } + + /* setup bio for socket operations */ + abio = BIO_new_accept(host_port); + if (abio == NULL) + err_ssl(1, "BIO_new_accept"); + + /* bind, listen */ + if (BIO_do_accept(abio) <= 0) + err_ssl(1, "BIO_do_accept setup"); + printf("listen "); + print_sockname(abio); + + /* fork to background and set timeout */ + if (daemon(1, 1) == -1) + err(1, "daemon"); + alarm(10); + + do { + /* accept connection */ + if (BIO_do_accept(abio) <= 0) + err_ssl(1, "BIO_do_accept wait"); + cbio = BIO_pop(abio); + printf("accept "); + print_sockname(cbio); + printf("accept "); + print_peername(cbio); + + /* do ssl server handshake */ + ssl = SSL_new(ctx); + if (ssl == NULL) + err_ssl(1, "SSL_new"); + SSL_set_bio(ssl, cbio, cbio); + if ((error = SSL_accept(ssl)) <= 0) + err_ssl(1, "SSL_accept %d", error); + printf("session %d: %s\n", sessionreuse, + SSL_session_reused(ssl) ? "reuse" : "new"); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + + + /* print session statistics */ + session = SSL_get_session(ssl); + if (session == NULL) + err_ssl(1, "SSL_get_session"); + if (SSL_SESSION_print_fp(stdout, session) <= 0) + err_ssl(1, "SSL_SESSION_print_fp"); + + /* write server greeting and read client hello over TLS */ + strlcpy(buf, "greeting\n", sizeof(buf)); + printf(">>> %s", buf); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + if ((error = SSL_write(ssl, buf, 9)) <= 0) + err_ssl(1, "SSL_write %d", error); + if (error != 9) + errx(1, "write not 9 bytes greeting: %d", error); + if ((error = SSL_read(ssl, buf, 6)) <= 0) + err_ssl(1, "SSL_read %d", error); + if (error != 6) + errx(1, "read not 6 bytes hello: %d", error); + buf[6] = '\0'; + printf("<<< %s", buf); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + + /* shutdown connection */ + if ((error = SSL_shutdown(ssl)) < 0) + err_ssl(1, "SSL_shutdown unidirectional %d", error); + if (error <= 0) { + if ((error = SSL_shutdown(ssl)) <= 0) + err_ssl(1, "SSL_shutdown bidirectional %d", + error); + } + + SSL_free(ssl); + } while (sessionreuse--); + + SSL_CTX_free(ctx); + + printf("success\n"); + + return 0; +} diff --git a/tests/server.pem b/tests/server.pem new file mode 100644 index 0000000..7412490 --- /dev/null +++ b/tests/server.pem @@ -0,0 +1,51 @@ +subject= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = Test Server Cert +issuer= C = UK, O = OpenSSL Group, OU = FOR TESTING PURPOSES ONLY, CN = OpenSSL Test Intermediate CA +-----BEGIN CERTIFICATE----- +MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eUMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt +ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMloXDTI0MDQwMTE0NDUxMlowZDELMAkG +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgU2VydmVyIENlcnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDzhPOSNtyyRspmeuUpxfNJ +KCLTuf7g3uQ4zu4iHOmRO5TQci+HhVlLZrHF9XqFXcIP0y4pWDbMSGuiorUmzmfi +R7bfSdI/+qIQt8KXRH6HNG1t8ou0VSvWId5TS5Dq/er5ODUr9OaaDva7EquHIcMv +vPQGuI+OEAcnleVCy9HVEIySrO4P3CNIicnGkwwiAud05yUAq/gPXBC1hTtmlPD7 +TVcGVSEiJdvzqqlgv02qedGrkki6GY4S7GjZxrrf7Foc2EP+51LJzwLQx3/JfrCU +41NEWAsu/Sl0tQabXESN+zJ1pDqoZ3uHMgpQjeGiE0olr+YcsSW/tJmiU9OiAr8R +AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG ++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B +AQUFAAOCAQEADfy8VrY5er5ebYLyiC1il5kVOuJHSf8aN5SciJz/VcifA1+Hl2Bu +CfuizhP/kUdB9PTSj8ep9sL+5PBFl7CZJDO6Sxs5+qJe15XvLBP8UEdvc779plL6 +StUMJT0aU/MaqUZZCldC3G4CcbwzOzKSD5YzvxxIGspxBWRduZKKMOju/4aqK76p +dwA/VGCve9mjft3LIrb0gSaPi5KmdGtpAjzW3H1+63DSqxCYb1oiPtUZBs4STwjh +WPRmAEVR4RPCETM3Sth4C+bE0QMCGY12ctcbzhj7Xgo7LcSpqviq6JD8SPuU7ISL +hy4NcnBBHJr9OV9WTLpmS9V9Vg6QmOpxQw== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA84TzkjbcskbKZnrlKcXzSSgi07n+4N7kOM7uIhzpkTuU0HIv +h4VZS2axxfV6hV3CD9MuKVg2zEhroqK1Js5n4ke230nSP/qiELfCl0R+hzRtbfKL +tFUr1iHeU0uQ6v3q+Tg1K/Tmmg72uxKrhyHDL7z0BriPjhAHJ5XlQsvR1RCMkqzu +D9wjSInJxpMMIgLndOclAKv4D1wQtYU7ZpTw+01XBlUhIiXb86qpYL9NqnnRq5JI +uhmOEuxo2ca63+xaHNhD/udSyc8C0Md/yX6wlONTRFgLLv0pdLUGm1xEjfsydaQ6 +qGd7hzIKUI3hohNKJa/mHLElv7SZolPTogK/EQIDAQABAoIBAADq9FwNtuE5IRQn +zGtO4q7Y5uCzZ8GDNYr9RKp+P2cbuWDbvVAecYq2NV9QoIiWJOAYZKklOvekIju3 +r0UZLA0PRiIrTg6NrESx3JrjWDK8QNlUO7CPTZ39/K+FrmMkV9lem9yxjJjyC34D +AQB+YRTx+l14HppjdxNwHjAVQpIx/uO2F5xAMuk32+3K+pq9CZUtrofe1q4Agj9R +5s8mSy9pbRo9kW9wl5xdEotz1LivFOEiqPUJTUq5J5PeMKao3vdK726XI4Z455Nm +W2/MA0YV0ug2FYinHcZdvKM6dimH8GLfa3X8xKRfzjGjTiMSwsdjgMa4awY3tEHH +674jhAECgYEA/zqMrc0zsbNk83sjgaYIug5kzEpN4ic020rSZsmQxSCerJTgNhmg +utKSCt0Re09Jt3LqG48msahX8ycqDsHNvlEGPQSbMu9IYeO3Wr3fAm75GEtFWePY +BhM73I7gkRt4s8bUiUepMG/wY45c5tRF23xi8foReHFFe9MDzh8fJFECgYEA9EFX +4qAik1pOJGNei9BMwmx0I0gfVEIgu0tzeVqT45vcxbxr7RkTEaDoAG6PlbWP6D9a +WQNLp4gsgRM90ZXOJ4up5DsAWDluvaF4/omabMA+MJJ5kGZ0gCj5rbZbKqUws7x8 +bp+6iBfUPJUbcqNqFmi/08Yt7vrDnMnyMw2A/sECgYEAiiuRMxnuzVm34hQcsbhH +6ymVqf7j0PW2qK0F4H1ocT9qhzWFd+RB3kHWrCjnqODQoI6GbGr/4JepHUpre1ex +4UEN5oSS3G0ru0rC3U4C59dZ5KwDHFm7ffZ1pr52ljfQDUsrjjIMRtuiwNK2OoRa +WSsqiaL+SDzSB+nBmpnAizECgYBdt/y6rerWUx4MhDwwtTnel7JwHyo2MDFS6/5g +n8qC2Lj6/fMDRE22w+CA2esp7EJNQJGv+b27iFpbJEDh+/Lf5YzIT4MwVskQ5bYB +JFcmRxUVmf4e09D7o705U/DjCgMH09iCsbLmqQ38ONIRSHZaJtMDtNTHD1yi+jF+ +OT43gQKBgQC/2OHZoko6iRlNOAQ/tMVFNq7fL81GivoQ9F1U0Qr+DH3ZfaH8eIkX +xT0ToMPJUzWAn8pZv0snA0um6SIgvkCuxO84OkANCVbttzXImIsL7pFzfcwV/ERK +UM6j0ZuSMFOCr/lGPAoOQU0fskidGEHi1/kW+suSr28TqsyYZpwBDQ== +-----END RSA PRIVATE KEY----- diff --git a/tests/server1-ecdsa-chain.pem b/tests/server1-ecdsa-chain.pem new file mode 100644 index 0000000..46add4d --- /dev/null +++ b/tests/server1-ecdsa-chain.pem @@ -0,0 +1,26 @@ +subject= CN = LibreSSL Test Server 1 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqzCCAVKgAwIBAgIJAOVssaaTYoH4MAoGCCqGSM49BAMCMC4xLDAqBgNVBAMM +I0xpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTIxMTIyNzE0 +NDA0MFoXDTMxMTIyNTE0NDA0MFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBT +ZXJ2ZXIgMSBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLCfzrwjvJ6V +m2Jog48gtuDNYupHd8TKOCVb6J7f1/U3Owwy2//ZVTvM+9uoIC8xxUJAmN0PC+9a ++5TkRWiD1KWjYDBeMB0GA1UdDgQWBBTo776/p89eGJwMmJRNk4k+xGVRPTAfBgNV +HSMEGDAWgBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAhHPaADQMcGea7iBRbKZWSHUAf +fZSNIWF/nYASNBvKLgIgQXLiuWxt6/a7vxaZwgYXkhP1YfDSC5Kpktxr/3jHcAU= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/server1-ecdsa.pem b/tests/server1-ecdsa.pem new file mode 100644 index 0000000..541fed6 --- /dev/null +++ b/tests/server1-ecdsa.pem @@ -0,0 +1,18 @@ +subject= CN = LibreSSL Test Server 1 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqzCCAVKgAwIBAgIJAOVssaaTYoH4MAoGCCqGSM49BAMCMC4xLDAqBgNVBAMM +I0xpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTIxMTIyNzE0 +NDA0MFoXDTMxMTIyNTE0NDA0MFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBT +ZXJ2ZXIgMSBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLCfzrwjvJ6V +m2Jog48gtuDNYupHd8TKOCVb6J7f1/U3Owwy2//ZVTvM+9uoIC8xxUJAmN0PC+9a ++5TkRWiD1KWjYDBeMB0GA1UdDgQWBBTo776/p89eGJwMmJRNk4k+xGVRPTAfBgNV +HSMEGDAWgBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIHgDAKBggqhkjOPQQDAgNHADBEAiAhHPaADQMcGea7iBRbKZWSHUAf +fZSNIWF/nYASNBvKLgIgQXLiuWxt6/a7vxaZwgYXkhP1YfDSC5Kpktxr/3jHcAU= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgvh2q0Zzqn18tPux2 +csqpbWDtHGialpwtx/r/0ENHeKOhRANCAASwn868I7yelZtiaIOPILbgzWLqR3fE +yjglW+ie39f1NzsMMtv/2VU7zPvbqCAvMcVCQJjdDwvvWvuU5EVog9Sl +-----END PRIVATE KEY----- diff --git a/tests/server1-rsa-chain.pem b/tests/server1-rsa-chain.pem new file mode 100644 index 0000000..57dec7b --- /dev/null +++ b/tests/server1-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Server 1 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoHzMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzdaFw0zMTEyMjUxNDQwMzdaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +U2VydmVyIDEgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnvyt +i0uA2qaFltVb8+PElYk84AnjY0WZDcGtKSMCAYTD857fO2V4S/wpJ9ZMt8kBKQ29 +D2Glkkhc/HPpb7wJcAUT++aZ/PbOtuzOHzdxheOolfZ6aw+qCSiVlcflKfMp7VPL +swimqKpm6atl2aSqldKfmGzjhAAPiTXbzUjh9pbTfO8ykdn/6AqP7ju3+4sseMPL +seNq1wstWRdiHm0P/BoJn4lwDe7QTSp1AxMqDTz5BiO+UjCW2oTsOFfo/hhslQf5 +qv7uPLrz/VWiEojQP5RzfcnVwplUgTvtaOkXxZeOH7VkKS1v8W506/h3RIKj0X8Y +JDLuIPqSAPNLWGyH4wIDAQABo2AwXjAdBgNVHQ4EFgQUFJPGTfe+ULC/anJ4fCVz +DXA0JI4wHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAGP5hYyAYzlj +YCV24ApNPb+mNEMHu1SL1MgDXJOTWZMFOvuYcibtmcVIfwpM4+UpC7cRqPRjBEqm +NdLbJi4jGzQDNOcI7OZCCx6oKvAhjMofpb42Iq4bDuBqlhHRXvYnO30y0yRbSGXt +GvKvkNKOSXUnY1UtcBAN5szcyFk30xQK+f/2VqJguvjsTquFV+piqFyq91ICyIeQ +1gjTn1N2/SkmYpwZdyf0HqSjyqJ0FG4xiW6T0HmX1QI651Kux49vLel7ySxzGY+6 +axnPilTYx/7pkciGk5ckLdujpXsDPhC+E2hdoee494c5NvX/uibYhigLU/gHK/ZP +YisY8ihnPl8= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/server1-rsa.pem b/tests/server1-rsa.pem new file mode 100644 index 0000000..12e9ac9 --- /dev/null +++ b/tests/server1-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Server 1 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoHzMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzdaFw0zMTEyMjUxNDQwMzdaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +U2VydmVyIDEgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnvyt +i0uA2qaFltVb8+PElYk84AnjY0WZDcGtKSMCAYTD857fO2V4S/wpJ9ZMt8kBKQ29 +D2Glkkhc/HPpb7wJcAUT++aZ/PbOtuzOHzdxheOolfZ6aw+qCSiVlcflKfMp7VPL +swimqKpm6atl2aSqldKfmGzjhAAPiTXbzUjh9pbTfO8ykdn/6AqP7ju3+4sseMPL +seNq1wstWRdiHm0P/BoJn4lwDe7QTSp1AxMqDTz5BiO+UjCW2oTsOFfo/hhslQf5 +qv7uPLrz/VWiEojQP5RzfcnVwplUgTvtaOkXxZeOH7VkKS1v8W506/h3RIKj0X8Y +JDLuIPqSAPNLWGyH4wIDAQABo2AwXjAdBgNVHQ4EFgQUFJPGTfe+ULC/anJ4fCVz +DXA0JI4wHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAGP5hYyAYzlj +YCV24ApNPb+mNEMHu1SL1MgDXJOTWZMFOvuYcibtmcVIfwpM4+UpC7cRqPRjBEqm +NdLbJi4jGzQDNOcI7OZCCx6oKvAhjMofpb42Iq4bDuBqlhHRXvYnO30y0yRbSGXt +GvKvkNKOSXUnY1UtcBAN5szcyFk30xQK+f/2VqJguvjsTquFV+piqFyq91ICyIeQ +1gjTn1N2/SkmYpwZdyf0HqSjyqJ0FG4xiW6T0HmX1QI651Kux49vLel7ySxzGY+6 +axnPilTYx/7pkciGk5ckLdujpXsDPhC+E2hdoee494c5NvX/uibYhigLU/gHK/ZP +YisY8ihnPl8= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCe/K2LS4DapoWW +1Vvz48SViTzgCeNjRZkNwa0pIwIBhMPznt87ZXhL/Ckn1ky3yQEpDb0PYaWSSFz8 +c+lvvAlwBRP75pn89s627M4fN3GF46iV9nprD6oJKJWVx+Up8yntU8uzCKaoqmbp +q2XZpKqV0p+YbOOEAA+JNdvNSOH2ltN87zKR2f/oCo/uO7f7iyx4w8ux42rXCy1Z +F2IebQ/8GgmfiXAN7tBNKnUDEyoNPPkGI75SMJbahOw4V+j+GGyVB/mq/u48uvP9 +VaISiNA/lHN9ydXCmVSBO+1o6RfFl44ftWQpLW/xbnTr+HdEgqPRfxgkMu4g+pIA +80tYbIfjAgMBAAECggEBAJDm9PkW6KrfyLPPZA5mUl6EBWKgQInS/gsmsT7j9EkU +C1A4RXcqJTkD6zKuw59h6NfU+LJTKgeoQm+o6WJ3/BYH2s3kwAZpn7/jFn4nFyWT +d6yuR6baUPwl7CfmV3wjbtwqWmajhNoG7OMd3yc9SGhi3iibXcWKFJ7W4q04NxJ5 +txswRddLYMFUeJxPBdImlyibyUIWaYFid4O2kozTQWpyJld5SP4+YQObb6sBJuvN +wR53eaRGb0OaUGppglGlWTahIADBjbhf0zd9YiUjvums/cjx2goHzQqt4rIj1Pid +I3duu/kw7AsuRlvmhk02Cu4Ixr8hljbeo2L7UAP+4BkCgYEAzVq8Fqi/5IVdjl0H +FwvS9NX3HFFzdixtI2p/jCQ721Kxpf73zvRpMG/YZL3vBt4sXT7WpJZZsKrYogL7 +8s/dG7p/GpzSnvJKQfT6Ko+jnv24MEIoqMx+Smd+nJJJ0KzZRvrqzcF+wsicmKnN +y/4t8T1DqSm4WxDyuy/uDozqCP0CgYEAxjJ9GJha40sHlY4sOTaJqapN6va/t70/ +iRj+Mt9Bm1O41PBgu+SMADGukrjL5DYp53QRGhyqb2PWmZsGYvftPZNq5b3pzKPo +8jiP9AxYDt/GLO3x/GppiywOxHD8CV19BDVqWcBkV1ATu2kkmokDbq+g94xnMBzN +nURtfL5Hml8CgYAMeJIrnhvpOOAxoRypHaK2E7hqE9g7OP93wyPz0s9/xknbltxd +ySIKOwCdPZuigyOWlhZa8HaJ8BYv4JaEbHM1F+JYL2XrGTPBRatbolWBdk8VPy9Q +8PpKcnaR86Bf999KHDreO/4CvkQkUUuaM9l+aQYO4+W6QhE7pPGEGLKt0QKBgCL2 +exzgm3/nF3JpfyGknkpA0bf2SUG3b8LWltkQizlEXqGpudbLbWsHWJ1nXghnCaNb +1Tx+/A3kVdIJB+pjhAVNwRjAFMNV0t0P300U9F/DV+lLHFoDx5SWdBBxQfTA+jHI +3nbwuoKwjJqN5LgiHWnkL4gby4QwQJFSpeHQiz8PAoGBAJaur4aFaSlgGAiKJX4/ +Om4AedImBgFsVKf44xx5pDwEcqLeEwRBxa0r5Sftqsrz+Ck60hR/MWCwJEBll5PV +MJtOHBb2bINFhLOqV1WoSkSoKEhtMvFnLbWGBi5gYHC4+lYuyQqD/vu3sxe5IT9C +PKgUgKV32Z7KBpDuFGtGmiDb +-----END PRIVATE KEY----- diff --git a/tests/server2-ecdsa-chain.pem b/tests/server2-ecdsa-chain.pem new file mode 100644 index 0000000..494d2ea --- /dev/null +++ b/tests/server2-ecdsa-chain.pem @@ -0,0 +1,26 @@ +subject= CN = LibreSSL Test Server 2 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBpjCCAUygAwIBAgIDEAABMAoGCCqGSM49BAMCMC4xLDAqBgNVBAMMI0xpYnJl +U1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTEwMDEwMTAwMDAwMFoX +DTIwMDEwMTAwMDAwMFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBTZXJ2ZXIg +MiBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJOTftmDhBMSS23a+sRO +3Zr43RUwtdJvNfKhpHKRbBLIttBkbI1wWCgufMLCJXhL6pSpCeT/C9ioFks2JMg7 +CPCjYDBeMB0GA1UdDgQWBBSCtBk04EXYNjiFaaTcJumL0BFylTAfBgNVHSMEGDAW +gBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE +AwIHgDAKBggqhkjOPQQDAgNIADBFAiEAqnQ+TRgMZRys3z3olZysrnP0d6XIdfgv +XvlXRaM0s/QCIHdrTx/IPfJSvo0rDN08CJfbO0NBOc9PFsnDRUKsxJd4 +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/server2-ecdsa.pem b/tests/server2-ecdsa.pem new file mode 100644 index 0000000..2f49df9 --- /dev/null +++ b/tests/server2-ecdsa.pem @@ -0,0 +1,18 @@ +subject= CN = LibreSSL Test Server 2 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBpjCCAUygAwIBAgIDEAABMAoGCCqGSM49BAMCMC4xLDAqBgNVBAMMI0xpYnJl +U1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIEVDRFNBMB4XDTEwMDEwMTAwMDAwMFoX +DTIwMDEwMTAwMDAwMFowJzElMCMGA1UEAwwcTGlicmVTU0wgVGVzdCBTZXJ2ZXIg +MiBFQ0RTQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJOTftmDhBMSS23a+sRO +3Zr43RUwtdJvNfKhpHKRbBLIttBkbI1wWCgufMLCJXhL6pSpCeT/C9ioFks2JMg7 +CPCjYDBeMB0GA1UdDgQWBBSCtBk04EXYNjiFaaTcJumL0BFylTAfBgNVHSMEGDAW +gBQXVj1v/EpXEjlCygJygatQDeTCCDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE +AwIHgDAKBggqhkjOPQQDAgNIADBFAiEAqnQ+TRgMZRys3z3olZysrnP0d6XIdfgv +XvlXRaM0s/QCIHdrTx/IPfJSvo0rDN08CJfbO0NBOc9PFsnDRUKsxJd4 +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgxkOt2jb6kQC1ZaUa +MLSz0lyS0YQtqChoyAvJ7yQf3FahRANCAASTk37Zg4QTEktt2vrETt2a+N0VMLXS +bzXyoaRykWwSyLbQZGyNcFgoLnzCwiV4S+qUqQnk/wvYqBZLNiTIOwjw +-----END PRIVATE KEY----- diff --git a/tests/server2-rsa-chain.pem b/tests/server2-rsa-chain.pem new file mode 100644 index 0000000..5bb660f --- /dev/null +++ b/tests/server2-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Server 2 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgIDEAABMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNVBAMMIUxp +YnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0xMDAxMDEwMDAwMDBa +Fw0yMDAxMDEwMDAwMDBaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3QgU2VydmVy +IDIgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu08owc3HqHu2 ++92bKDs/VCVjkGMZSVOrdAXYEKf9WQ6cGxiowjJy391szSd5bW/Yf7hbNhctr29G +8oIj0wsMfz3lxuHDYISt8uAjbjqFiZTNfBeg7PVE9aDWXqaophcq4DT2ygv9O190 +09RxTJD6PdclUtQNYZHr3c7kP2AdeBWWVPAmKISDSEkjXqc0x9LEtm7UA/0WAtKM +NUXUb/ZNBu90j7gRpjN6VyfaqJMdoDR31s7QXivL5hr4x0M0Y1ihN1/cHA5Qjb0s +6t8w6H2b0xtvJgO5N3ZUAVclAO3MsVRqr04aAyxcJ47qOkWPbh9OqaFyZFdl7L2r +UTLloQNkcwIDAQABo2AwXjAdBgNVHQ4EFgQUrDgWmmX6bVZt4Z7SvCSXEfJMoZQw +HwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/BAIwADAO +BgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBANbQG/fAGsV+J+cmEIlg +9i5c44hpr3BAXn5QYMbV9OQ8M9Rq8cZx/EkwNlCfPnQph2PqN2tZNstBnlL90rNq +pOj1Ee+ppemeJrHKFuEncytGHbgqjRLgi9n0vR5RF1I7dJvRlPugpf/FxeMC/7f2 +qDDfdMsvmu/+qWBMb+U5yPLXlibGr7nf7B3t9ZBtku5flP3OOmipIjFpLOmvu06Z +9fac0JHDRvBQCemvIbSIa8Sz6UVJ1hKTjaN+lqc7e5tgbovNqjgFiLx0lQrfBmg9 +tnNhoaEuwwyPNIVLUK3J1Q4lv/m9fX7BVmL5C56AexwtD/jupdXe2utjFx6YXrKG +nxU= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/server2-rsa.pem b/tests/server2-rsa.pem new file mode 100644 index 0000000..ed7389a --- /dev/null +++ b/tests/server2-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Server 2 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgIDEAABMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNVBAMMIUxp +YnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0xMDAxMDEwMDAwMDBa +Fw0yMDAxMDEwMDAwMDBaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3QgU2VydmVy +IDIgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu08owc3HqHu2 ++92bKDs/VCVjkGMZSVOrdAXYEKf9WQ6cGxiowjJy391szSd5bW/Yf7hbNhctr29G +8oIj0wsMfz3lxuHDYISt8uAjbjqFiZTNfBeg7PVE9aDWXqaophcq4DT2ygv9O190 +09RxTJD6PdclUtQNYZHr3c7kP2AdeBWWVPAmKISDSEkjXqc0x9LEtm7UA/0WAtKM +NUXUb/ZNBu90j7gRpjN6VyfaqJMdoDR31s7QXivL5hr4x0M0Y1ihN1/cHA5Qjb0s +6t8w6H2b0xtvJgO5N3ZUAVclAO3MsVRqr04aAyxcJ47qOkWPbh9OqaFyZFdl7L2r +UTLloQNkcwIDAQABo2AwXjAdBgNVHQ4EFgQUrDgWmmX6bVZt4Z7SvCSXEfJMoZQw +HwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/BAIwADAO +BgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBANbQG/fAGsV+J+cmEIlg +9i5c44hpr3BAXn5QYMbV9OQ8M9Rq8cZx/EkwNlCfPnQph2PqN2tZNstBnlL90rNq +pOj1Ee+ppemeJrHKFuEncytGHbgqjRLgi9n0vR5RF1I7dJvRlPugpf/FxeMC/7f2 +qDDfdMsvmu/+qWBMb+U5yPLXlibGr7nf7B3t9ZBtku5flP3OOmipIjFpLOmvu06Z +9fac0JHDRvBQCemvIbSIa8Sz6UVJ1hKTjaN+lqc7e5tgbovNqjgFiLx0lQrfBmg9 +tnNhoaEuwwyPNIVLUK3J1Q4lv/m9fX7BVmL5C56AexwtD/jupdXe2utjFx6YXrKG +nxU= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7TyjBzceoe7b7 +3ZsoOz9UJWOQYxlJU6t0BdgQp/1ZDpwbGKjCMnLf3WzNJ3ltb9h/uFs2Fy2vb0by +giPTCwx/PeXG4cNghK3y4CNuOoWJlM18F6Ds9UT1oNZepqimFyrgNPbKC/07X3TT +1HFMkPo91yVS1A1hkevdzuQ/YB14FZZU8CYohINISSNepzTH0sS2btQD/RYC0ow1 +RdRv9k0G73SPuBGmM3pXJ9qokx2gNHfWztBeK8vmGvjHQzRjWKE3X9wcDlCNvSzq +3zDofZvTG28mA7k3dlQBVyUA7cyxVGqvThoDLFwnjuo6RY9uH06poXJkV2XsvatR +MuWhA2RzAgMBAAECggEAc5ApQzkkv+xkPwzAl5fGQLI4tXKOvVDj7VdVsSEUDAgZ +hBY4uGfLvBau8/wwzLY+yr4BeGPgieaLzT9BvwmIElEsHQJZOolhkQF8mpt8nB+0 +j6U8YjYI78rlt8v3LVIJ3/6NbKbs+96vA6qEpIql+dVtb6bpApO3BEiLRhaU1+ra +pi5YbF56S3XlUFL6H46hpNTUxOqbb6toZ/2rr1nscu4jkQhL8u/KS5Uz1Y7RW3zd +A3U4rbxXnM8SVZrRuWsN1DRL5CpAOdGGiVhew46vAxZU8iX6rODrRaRCp+Gbnoll +x/ubMMrBrE4WpCY5orb41FPb4U6raY9ZZzTGPuC9YQKBgQDs0LrDy8kh3V7wsIwn +6vMT9MD2Olpl6zwSyQJ0C04u+hGNur3L6intg78TSRqZ7ZKK7CspPy9JCGTYztTG +vFbXy2vahCFlI2G3lfZj2nS2D+UNSmo2pdpBtuk/iKj67pFAlaa8C3OQ8MXjldQn +3QPANsCo276t0E9SmFcbJYJVCwKBgQDKe7sfdg0tQr9xsBeDuSxRJQOrtWeTmXm6 +zcPKRX8avWr5Ag6w4/BX/RxGZkD4brV5LaK6Qsbwl8v8aNe8Hv4yBQFdW0IMP8mB +v4kVaNEGxoJE4fnKk1wS22TQvX5fxWPGZhOWQ1sgIqp3Dzvky0nalK7Ru0gRA4gS +Jl0a4Sp/OQKBgQCHwuW/B53n5yPdcij3XW87Go5g2nUmhqPq1QeuBSkuLzhO+yaB +t12QB35MDRXN9u+S6u+XdtyhzskZrgE3aZOTpM/Q9vy6IX2MpNEaz4snMJeMdgPM +DmrAT58KSEsviAMHdoOevCXlitK3tRZqP/89e2YZp9h5hrlizWjqbCd6nwKBgQCS +XFWqLB7iNHlFqE+W+2a5UNQSbhHscue2y71WnF1/6qNEUuRjoJ++OksR6B/Wc8/h +Q8d4c4RxrIfab75hUNXVOiD+ZlSbng/+JYDlZNqS1zKar+1rLJFFYCjDafXLLFcu +teI6n31jASvO28gjXX6I7ShgmctB4ReeZvSt1UxuoQKBgHQ/0fA3owx9kDRA41Hu +a+npibal0F2JOxn0xiwgW3JcH/EkcSIvUELm8Kjl3GBxf0y9Osu0uf3cSqW9K9+z +CRpwZmFq+q3HFN6FYHYI6oVvPKIljDhmkvw9HyexXFLRKNs1z2b7Noz2H7ysE0cb +1sAZitEjace2/eAx/wWr2dq0 +-----END PRIVATE KEY----- diff --git a/tests/server3-ecdsa-chain.pem b/tests/server3-ecdsa-chain.pem new file mode 100644 index 0000000..03f3373 --- /dev/null +++ b/tests/server3-ecdsa-chain.pem @@ -0,0 +1,26 @@ +subject= CN = LibreSSL Test Server 3 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIJAOVssaaTYoH5MAkGByqGSM49BAEwLjEsMCoGA1UEAwwj +TGlicmVTU0wgVGVzdCBJbnRlcm1lZGlhdGUgQ0EgRUNEU0EwHhcNMjExMjI3MTQ0 +MDQwWhcNMzExMjI1MTQ0MDQwWjAnMSUwIwYDVQQDDBxMaWJyZVNTTCBUZXN0IFNl +cnZlciAzIEVDRFNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0pRqRW+PDenx +cp+5za1pFDdECxXPXZY7LUPoXxens1lPSM2diexVMdLw1kEbVkOZ50s1X32vQnTa +TVpovmwna6NgMF4wHQYDVR0OBBYEFCXbw+Fdv+OWDOU163ujSYbdJZx3MB8GA1Ud +IwQYMBaAFBdWPW/8SlcSOULKAnKBq1AN5MIIMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgeAMAkGByqGSM49BAEDSAAwRQIhAMt01G90LOiCVRIcodKP1nsOg3oY +kX8VHUPk9myD52KZAiBu32mh/fgaWsR/lbo2dyGJQHKkmHNt9Wy8hOQ9eGO91A== +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA ECDSA +issuer= CN = LibreSSL Test Root CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBrDCCAVOgAwIBAgIJAOVssaaTYoH3MAkGByqGSM49BAEwJjEkMCIGA1UEAwwb +TGlicmVTU0wgVGVzdCBSb290IENBIEVDRFNBMB4XDTIxMTIyNzE0NDA0MFoXDTMx +MTIyNTE0NDA0MFowLjEsMCoGA1UEAwwjTGlicmVTU0wgVGVzdCBJbnRlcm1lZGlh +dGUgQ0EgRUNEU0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATWRQbJh4aHPzHq +LOAmosW/o83bTpm3Sj1VxM44StmG7c1nnFM/+gS8rp2bVSgjWZQzRtZqGVGJgzbk +7/M1m3x3o2MwYTAdBgNVHQ4EFgQUF1Y9b/xKVxI5QsoCcoGrUA3kwggwHwYDVR0j +BBgwFoAUtvkat4UdcUEipt6L/PBgEFYH6AwwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwCQYHKoZIzj0EAQNIADBFAiBE4NiOdv/XRN3WWMnkE5QccvC6 +VThoIQRyBf4I97cRPQIhAK18dvwrLuOOfbhWMdkpNCddMkWZHxS7traw/8+s7OUU +-----END CERTIFICATE----- diff --git a/tests/server3-ecdsa.pem b/tests/server3-ecdsa.pem new file mode 100644 index 0000000..98950aa --- /dev/null +++ b/tests/server3-ecdsa.pem @@ -0,0 +1,18 @@ +subject= CN = LibreSSL Test Server 3 ECDSA +issuer= CN = LibreSSL Test Intermediate CA ECDSA +-----BEGIN CERTIFICATE----- +MIIBqjCCAVGgAwIBAgIJAOVssaaTYoH5MAkGByqGSM49BAEwLjEsMCoGA1UEAwwj +TGlicmVTU0wgVGVzdCBJbnRlcm1lZGlhdGUgQ0EgRUNEU0EwHhcNMjExMjI3MTQ0 +MDQwWhcNMzExMjI1MTQ0MDQwWjAnMSUwIwYDVQQDDBxMaWJyZVNTTCBUZXN0IFNl +cnZlciAzIEVDRFNBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0pRqRW+PDenx +cp+5za1pFDdECxXPXZY7LUPoXxens1lPSM2diexVMdLw1kEbVkOZ50s1X32vQnTa +TVpovmwna6NgMF4wHQYDVR0OBBYEFCXbw+Fdv+OWDOU163ujSYbdJZx3MB8GA1Ud +IwQYMBaAFBdWPW/8SlcSOULKAnKBq1AN5MIIMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgeAMAkGByqGSM49BAEDSAAwRQIhAMt01G90LOiCVRIcodKP1nsOg3oY +kX8VHUPk9myD52KZAiBu32mh/fgaWsR/lbo2dyGJQHKkmHNt9Wy8hOQ9eGO91A== +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgTWRMClyUOn11mX5s +hTTIQT+3BeauAjrTvKMy5RryWtyhRANCAATSlGpFb48N6fFyn7nNrWkUN0QLFc9d +ljstQ+hfF6ezWU9IzZ2J7FUx0vDWQRtWQ5nnSzVffa9CdNpNWmi+bCdr +-----END PRIVATE KEY----- diff --git a/tests/server3-rsa-chain.pem b/tests/server3-rsa-chain.pem new file mode 100644 index 0000000..e40c982 --- /dev/null +++ b/tests/server3-rsa-chain.pem @@ -0,0 +1,44 @@ +subject= CN = LibreSSL Test Server 3 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH0MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzdaFw0zMTEyMjUxNDQwMzdaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +U2VydmVyIDMgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqw4 +GSS7/WAR0VYbqFTltj9Cv17m+RuztM1jiJq+MU0Gscbx59NFPt8UFevNsMzWNmAK +qkioEMVJxXzSUDBjXjLesDt/+VTjR46z16fje3MhGmWa8lDt7hpuHwDF80dg3rZa +kVEcgKvd6LODTucgE7l07DzMb8qAdRp1SDXIFECO0wLJewkf2CihmNukTxQhI0d+ +XPZTYe3cyMelj8KpCXCXOVXKnXI+BWnYMHC1Op4S9z90xiVBNgQ+Vmg2K9NFifzT +ZyKIWsERq80rp1s+JmxmzA/vBRlsbj/Ec0h2kF4IavGtHwvAvdvIPV7AG/dIxwlT +VnHZkPDuLK0H396wmwIDAQABo2AwXjAdBgNVHQ4EFgQUSuP+QN+526Pxw/LGBTqP +WJpWGvwwHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAFBJ0mO7dpSN +euxoh2DJghVfqQB4ladEroDZJkJEDuDkY3SjC+WB/lJowBVPC2QkzjTZt/J4B0Om +6irtKUC8jQ7aqMBfESu/s//GEU4kwlvlJN/Z0nLOh1YEeCwbkavFDy/X62iZ9XvJ +gjLVVzaXKWGrgdJedHx9Di04rU9jME5qfpXZI50u8grZccpUuTTqpZBiGjFRda2j +nJhgPBrn9/ityYaOrif8taR+QM6AETvEpJWo+I/iQ7vATmxHuq6y+0Sza5j9wGH/ +begJs9H890AiwO2bbUi1ehNj7NHZHySWNJlzBerwOQv7Zo8j+kHBop82ABsb/Xet +kgn7bdkfKoI= +-----END CERTIFICATE----- +subject= CN = LibreSSL Test Intermediate CA RSA +issuer= CN = LibreSSL Test Root CA RSA +-----BEGIN CERTIFICATE----- +MIIDNjCCAh6gAwIBAgIJAOVssaaTYoHyMA0GCSqGSIb3DQEBCwUAMCQxIjAgBgNV +BAMMGUxpYnJlU1NMIFRlc3QgUm9vdCBDQSBSU0EwHhcNMjExMjI3MTQ0MDM3WhcN +MzExMjI1MTQ0MDM3WjAsMSowKAYDVQQDDCFMaWJyZVNTTCBUZXN0IEludGVybWVk +aWF0ZSBDQSBSU0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD151AI +I+W9MrEP3dO0PEjg6L9E1R6+CG6u0LT3Jobc/rG2RXqKLasEaXoBWYiJoTImVxFT +wtrY+IDDTaEV4/4RGII1fY8Js7v5NpwoEh15jCoJ6/qDjKd4y1s1M48PlWYNNRmv +OBKRIu3Fz7scUa1RSBCp1bZeHbq/V5SzG419nDq2xpyuUrwmfBhDZTH+kUwBNGn8 +XVRFCRJQVP3qEAH02Zai2emSVj13KrhEWMtNyA8fa34GIuV23Q40RKW3jUgGBF+D +5jPNN8EZCj34nvvbjCCBs7cxZvD4F/MzGbatKpNmNOKXKibeg/xCq8B/F1uzHcl3 +IzJuViNtQ3RjQ/1pAgMBAAGjYzBhMB0GA1UdDgQWBBQ2oaFa//6a3ZNBNV0NlN3n +A9jiZjAfBgNVHSMEGDAWgBQ+S/x79Kw0KqURKAHyiOhdj/8V0TAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcok2oSct +BOkm75qA8+4eUilGxTaqFPCqY8fk8MKNRKNNzaqirPaLJW62mZaxRHOn1Bw9uzL3 +jgz2PaTwA7n5GpKs3r5JLk8BdtRyeqMLmqJVJKKuu4GtJLCA8jhQm+XNA1Z324hg +kVeBHLPpLKvQxb+0lmbRBORq/OtMirq2yK8OlF2USrfQx0jmhSvvLpWyA0hhAXRS +gg1ds9aL57dELvk6gR7Unob+J0O2Xq3FRwz2O1k9fF86a0qrWUkxcnAjobC2BczC +7Fe5B194LgrX2U4IIrzwgJ19kmtrb1Qol2okECxomTYsbQY36sBs+LOKxSuiagu6 +ZgJtfcNeVMglYQ== +-----END CERTIFICATE----- diff --git a/tests/server3-rsa.pem b/tests/server3-rsa.pem new file mode 100644 index 0000000..256528a --- /dev/null +++ b/tests/server3-rsa.pem @@ -0,0 +1,50 @@ +subject= CN = LibreSSL Test Server 3 RSA +issuer= CN = LibreSSL Test Intermediate CA RSA +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgIJAOVssaaTYoH0MA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV +BAMMIUxpYnJlU1NMIFRlc3QgSW50ZXJtZWRpYXRlIENBIFJTQTAeFw0yMTEyMjcx +NDQwMzdaFw0zMTEyMjUxNDQwMzdaMCUxIzAhBgNVBAMMGkxpYnJlU1NMIFRlc3Qg +U2VydmVyIDMgUlNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqw4 +GSS7/WAR0VYbqFTltj9Cv17m+RuztM1jiJq+MU0Gscbx59NFPt8UFevNsMzWNmAK +qkioEMVJxXzSUDBjXjLesDt/+VTjR46z16fje3MhGmWa8lDt7hpuHwDF80dg3rZa +kVEcgKvd6LODTucgE7l07DzMb8qAdRp1SDXIFECO0wLJewkf2CihmNukTxQhI0d+ +XPZTYe3cyMelj8KpCXCXOVXKnXI+BWnYMHC1Op4S9z90xiVBNgQ+Vmg2K9NFifzT +ZyKIWsERq80rp1s+JmxmzA/vBRlsbj/Ec0h2kF4IavGtHwvAvdvIPV7AG/dIxwlT +VnHZkPDuLK0H396wmwIDAQABo2AwXjAdBgNVHQ4EFgQUSuP+QN+526Pxw/LGBTqP +WJpWGvwwHwYDVR0jBBgwFoAUNqGhWv/+mt2TQTVdDZTd5wPY4mYwDAYDVR0TAQH/ +BAIwADAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggEBAFBJ0mO7dpSN +euxoh2DJghVfqQB4ladEroDZJkJEDuDkY3SjC+WB/lJowBVPC2QkzjTZt/J4B0Om +6irtKUC8jQ7aqMBfESu/s//GEU4kwlvlJN/Z0nLOh1YEeCwbkavFDy/X62iZ9XvJ +gjLVVzaXKWGrgdJedHx9Di04rU9jME5qfpXZI50u8grZccpUuTTqpZBiGjFRda2j +nJhgPBrn9/ityYaOrif8taR+QM6AETvEpJWo+I/iQ7vATmxHuq6y+0Sza5j9wGH/ +begJs9H890AiwO2bbUi1ehNj7NHZHySWNJlzBerwOQv7Zo8j+kHBop82ABsb/Xet +kgn7bdkfKoI= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDKrDgZJLv9YBHR +VhuoVOW2P0K/Xub5G7O0zWOImr4xTQaxxvHn00U+3xQV682wzNY2YAqqSKgQxUnF +fNJQMGNeMt6wO3/5VONHjrPXp+N7cyEaZZryUO3uGm4fAMXzR2DetlqRURyAq93o +s4NO5yATuXTsPMxvyoB1GnVINcgUQI7TAsl7CR/YKKGY26RPFCEjR35c9lNh7dzI +x6WPwqkJcJc5Vcqdcj4FadgwcLU6nhL3P3TGJUE2BD5WaDYr00WJ/NNnIohawRGr +zSunWz4mbGbMD+8FGWxuP8RzSHaQXghq8a0fC8C928g9XsAb90jHCVNWcdmQ8O4s +rQff3rCbAgMBAAECggEAAoOiaoVvI5SGhA9KZosvElS0kkUuHlb+oraNjotE4r2u +4JO0Ooj/aelAiYkUUyYnXiNQ3o3qL9MSuDV1MnN3OBrvckY6rzAjZabaiklV5Bko +hvhNtMXWPcbsKMxMqFjxVbHza6wS63G2XgWkEl2Bo10Am1Ghw51CfLFoVQ39vmqM +8xKqZBZRwRUNk/2ccNhG5crUOX9+wQJSVjZCTgevjCJVVsFX9NLsHsx7G1wtE580 +AuFb9JEe66QNrtpTbKQP61W8YiRKQHT5uAAL0X9o88d2rpjGAcpJ8214aGH5P1HH +oUjL7mZceYuVeWvAMwLFFmPbPZuj3Ricgo1OIkKyyQKBgQDtNNXod5GzJyHOUrFR +rijyHhS81sOeDOhTbc1Cx8eFNH/svGATAU01HqgFRZpeJPHsAVYwVizfyqp/CESk +EFKTkMqRTat8Pkk+BtAGZD5fEBejl1fwRiBF9bTnk+u6q1WvBsQ0Bngf3v1CYGuq +rvb57AvhkCsEMjWs1YplBLwdVwKBgQDauvNslanbFstrWVBJqxV1iEaWmN1Lr//C +fwCFU8rH8VEvp+JJCICu7sE5Te+1TF/ASEs/bCrsW51YXjH30z3De1oFrjFVjwOU +XFMqcaTCX5Fjxv739LmgGuO2MCrItmveQHYkpTzCl6/p/pI4I1QJN0S5a/FaBNcW +x5tV2Ks4XQKBgHCCiBdsZ1pPbFR9moeAkQFOTU3InB5iRuwTf7F2Kue+oBK8wuEg +0+snMFDX08Flyq3DcIsaxMwdR8NbO5uJ9nDx03MaIQWcUYcvGgp+D6ttaZj5lwdr +a7FjOrxAyCXRUKHlFrkKfH25eey66TabKKAgWv5RMGYcHqNs4ejKVyOfAoGALqUf +tFBWYLqDtujdDljFwsLFCuieiL2HtVqQKd6sp+b2gUs0Ho8JokSYQDg2nlsjMEY6 +hdPzc2Q2Mdoknc0WptFvaTa0nqJZCRKHSc3ibPEkeDq/tPEjhNk3JmsvNI5ygnsM +ttPmGTlv8l6vn/kouq5moYQ7fA78L4dxwOTr3qECgYBNuIf4vQq8WEkt0uSTJXom +UQVZglJu61NVGzR//lyukQB7/HrdEMB+JYJfev0o1GxLx1RV8rTVaeDJkUJjwn/h +qpqiLjJKF328oOuQdP3dH6AavH9r7gUOByOuxXgzZNbhtyNCrStAGOfX2xUxRZyZ +l0+QtrqbPtB4VSfZ0j+imw== +-----END PRIVATE KEY----- diff --git a/tests/servertest.c b/tests/servertest.c new file mode 100644 index 0000000..d572d14 --- /dev/null +++ b/tests/servertest.c @@ -0,0 +1,209 @@ +/* $OpenBSD: servertest.c,v 1.9 2023/07/11 11:52:35 tb Exp $ */ +/* + * Copyright (c) 2015, 2016, 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +const SSL_METHOD *tls_legacy_method(void); + +char *server_ca_file; +char *server_cert_file; +char *server_key_file; + +static unsigned char sslv2_client_hello_tls10[] = { + 0x80, 0x6a, 0x01, 0x03, 0x01, 0x00, 0x51, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x39, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x35, 0x00, 0x00, 0x16, 0x00, + 0x00, 0x13, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x33, + 0x00, 0x00, 0x32, 0x00, 0x00, 0x2f, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x66, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, + 0x00, 0x00, 0x61, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x12, 0x00, 0x00, 0x09, 0x00, 0x00, 0x65, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x60, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x11, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x03, 0xdd, 0xb6, 0x59, 0x26, + 0x46, 0xe6, 0x79, 0x77, 0xf4, 0xec, 0x42, 0x76, + 0xc8, 0x73, 0xad, 0x9c, +}; + +static unsigned char sslv2_client_hello_tls12[] = { + 0x80, 0xcb, 0x01, 0x03, 0x03, 0x00, 0xa2, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0xa5, 0x00, 0x00, + 0xa3, 0x00, 0x00, 0xa1, 0x00, 0x00, 0x9f, 0x00, + 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x69, + 0x00, 0x00, 0x68, 0x00, 0x00, 0x39, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, + 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, + 0x00, 0x00, 0x85, 0x00, 0x00, 0x9d, 0x00, 0x00, + 0x3d, 0x00, 0x00, 0x35, 0x00, 0x00, 0x84, 0x00, + 0x00, 0xa4, 0x00, 0x00, 0xa2, 0x00, 0x00, 0xa0, + 0x00, 0x00, 0x9e, 0x00, 0x00, 0x67, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, + 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x9a, 0x00, 0x00, + 0x99, 0x00, 0x00, 0x98, 0x00, 0x00, 0x97, 0x00, + 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, + 0x00, 0x00, 0x42, 0x00, 0x00, 0x9c, 0x00, 0x00, + 0x3c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x96, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x07, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, + 0x00, 0x0a, 0x00, 0x00, 0xff, 0x1d, 0xfd, 0x90, + 0x03, 0x61, 0x3c, 0x5a, 0x22, 0x83, 0xed, 0x11, + 0x85, 0xf4, 0xea, 0x36, 0x59, 0xd9, 0x1b, 0x27, + 0x22, 0x01, 0x14, 0x07, 0x66, 0xb2, 0x24, 0xf5, + 0x4e, 0x7d, 0x9d, 0x9c, 0x52, +}; + +struct server_hello_test { + const unsigned char *desc; + unsigned char *client_hello; + const size_t client_hello_len; + const SSL_METHOD *(*ssl_method)(void); + const long ssl_clear_options; + const long ssl_set_options; + int accept_fails; +}; + +static struct server_hello_test server_hello_tests[] = { + { + .desc = "TLSv1.0 in SSLv2 record", + .client_hello = sslv2_client_hello_tls10, + .client_hello_len = sizeof(sslv2_client_hello_tls10), + .ssl_method = tls_legacy_method, + .ssl_clear_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, + .ssl_set_options = 0, + .accept_fails = 1, + }, + { + .desc = "TLSv1.2 in SSLv2 record", + .client_hello = sslv2_client_hello_tls12, + .client_hello_len = sizeof(sslv2_client_hello_tls12), + .ssl_method = tls_legacy_method, + .ssl_clear_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, + .ssl_set_options = 0, + .accept_fails = 1, + }, +}; + +#define N_SERVER_HELLO_TESTS \ + (sizeof(server_hello_tests) / sizeof(*server_hello_tests)) + +static int +server_hello_test(int testno, struct server_hello_test *sht) +{ + BIO *rbio = NULL, *wbio = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int ret = 1; + + fprintf(stderr, "Test %d - %s\n", testno, sht->desc); + + if ((rbio = BIO_new_mem_buf(sht->client_hello, + sht->client_hello_len)) == NULL) { + fprintf(stderr, "Failed to setup rbio\n"); + goto failure; + } + if ((wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "Failed to setup wbio\n"); + goto failure; + } + + if ((ssl_ctx = SSL_CTX_new(sht->ssl_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + + if (SSL_CTX_use_certificate_file(ssl_ctx, server_cert_file, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "Failed to load server certificate"); + goto failure; + } + if (SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key_file, + SSL_FILETYPE_PEM) != 1) { + fprintf(stderr, "Failed to load server private key"); + goto failure; + } + + SSL_CTX_set_dh_auto(ssl_ctx, 1); + SSL_CTX_set_ecdh_auto(ssl_ctx, 1); + + SSL_CTX_clear_options(ssl_ctx, sht->ssl_clear_options); + SSL_CTX_set_options(ssl_ctx, sht->ssl_set_options); + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + SSL_set_bio(ssl, rbio, wbio); + + if (SSL_accept(ssl) != 0) { + if (sht->accept_fails) + goto done; + fprintf(stderr, "SSL_accept() returned non-zero\n"); + ERR_print_errors_fp(stderr); + goto failure; + } + + done: + ret = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + BIO_free(rbio); + BIO_free(wbio); + + return (ret); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + if (argc != 4) { + fprintf(stderr, "usage: %s keyfile certfile cafile\n", + argv[0]); + exit(1); + } + + server_key_file = argv[1]; + server_cert_file = argv[2]; + server_ca_file = argv[3]; + + SSL_library_init(); + SSL_load_error_strings(); + + for (i = 0; i < N_SERVER_HELLO_TESTS; i++) + failed |= server_hello_test(i, &server_hello_tests[i]); + + return (failed); +} diff --git a/tests/sha_test.c b/tests/sha_test.c new file mode 100644 index 0000000..82a0c4c --- /dev/null +++ b/tests/sha_test.c @@ -0,0 +1,936 @@ +/* $OpenBSD: sha_test.c,v 1.6 2023/07/19 15:11:42 joshua Exp $ */ +/* + * Copyright (c) 2022, 2023 Joshua Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +struct sha_test { + const int algorithm; + const uint8_t in[128]; + const size_t in_len; + const uint8_t out[EVP_MAX_MD_SIZE]; +}; + +static const struct sha_test sha_tests[] = { + /* SHA-1 */ + { + .algorithm = NID_sha1, + .in = "abc", + .in_len = 3, + .out = { + 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d, + }, + }, + { + .algorithm = NID_sha1, + .in = "", + .in_len = 0, + .out = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, + 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09, + }, + }, + { + .algorithm = NID_sha1, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, + 0xba, 0xae, 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, + 0xe5, 0x46, 0x70, 0xf1, + }, + }, + { + .algorithm = NID_sha1, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b, + 0xf4, 0x19, 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25, + 0x3a, 0x04, 0xa2, 0x59, + }, + }, + + /* SHA-224 */ + { + .algorithm = NID_sha224, + .in = "abc", + .in_len = 3, + .out = { + 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, 0x22, + 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, 0x55, 0xb3, + 0x2a, 0xad, 0xbc, 0xe4, 0xbd, 0xa0, 0xb3, 0xf7, + 0xe3, 0x6c, 0x9d, 0xa7, + }, + }, + { + .algorithm = NID_sha224, + .in = "", + .in_len = 0, + .out = { + 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, + 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, + 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, + 0xc5, 0xb3, 0xe4, 0x2f, + }, + }, + { + .algorithm = NID_sha224, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, 0xcc, + 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, 0x01, 0x50, + 0xb0, 0xc6, 0x45, 0x5c, 0xb4, 0xf5, 0x8b, 0x19, + 0x52, 0x52, 0x25, 0x25, + }, + }, + { + .algorithm = NID_sha224, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0xc9, 0x7c, 0xa9, 0xa5, 0x59, 0x85, 0x0c, 0xe9, + 0x7a, 0x04, 0xa9, 0x6d, 0xef, 0x6d, 0x99, 0xa9, + 0xe0, 0xe0, 0xe2, 0xab, 0x14, 0xe6, 0xb8, 0xdf, + 0x26, 0x5f, 0xc0, 0xb3, + }, + }, + + /* SHA-256 */ + { + .algorithm = NID_sha256, + .in = "abc", + .in_len = 3, + .out = { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad, + }, + }, + { + .algorithm = NID_sha256, + .in = "", + .in_len = 0, + .out = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, + }, + }, + { + .algorithm = NID_sha256, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1, + }, + }, + { + .algorithm = NID_sha256, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0xcf, 0x5b, 0x16, 0xa7, 0x78, 0xaf, 0x83, 0x80, + 0x03, 0x6c, 0xe5, 0x9e, 0x7b, 0x04, 0x92, 0x37, + 0x0b, 0x24, 0x9b, 0x11, 0xe8, 0xf0, 0x7a, 0x51, + 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1, + }, + }, + + /* SHA-384 */ + { + .algorithm = NID_sha384, + .in = "abc", + .in_len = 3, + .out = { + 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7, + }, + }, + { + .algorithm = NID_sha384, + .in = "", + .in_len = 0, + .out = { + 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, + 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, + 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, + 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b, + }, + }, + { + .algorithm = NID_sha384, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x33, 0x91, 0xfd, 0xdd, 0xfc, 0x8d, 0xc7, 0x39, + 0x37, 0x07, 0xa6, 0x5b, 0x1b, 0x47, 0x09, 0x39, + 0x7c, 0xf8, 0xb1, 0xd1, 0x62, 0xaf, 0x05, 0xab, + 0xfe, 0x8f, 0x45, 0x0d, 0xe5, 0xf3, 0x6b, 0xc6, + 0xb0, 0x45, 0x5a, 0x85, 0x20, 0xbc, 0x4e, 0x6f, + 0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b, + }, + }, + { + .algorithm = NID_sha384, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39, + }, + }, + + /* SHA-512 */ + { + .algorithm = NID_sha512, + .in = "abc", + .in_len = 3, + .out = { + 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f, + }, + }, + { + .algorithm = NID_sha512, + .in = "", + .in_len = 0, + .out = { + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, + 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, + 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, + 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, + 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e, + }, + }, + { + .algorithm = NID_sha512, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x20, 0x4a, 0x8f, 0xc6, 0xdd, 0xa8, 0x2f, 0x0a, + 0x0c, 0xed, 0x7b, 0xeb, 0x8e, 0x08, 0xa4, 0x16, + 0x57, 0xc1, 0x6e, 0xf4, 0x68, 0xb2, 0x28, 0xa8, + 0x27, 0x9b, 0xe3, 0x31, 0xa7, 0x03, 0xc3, 0x35, + 0x96, 0xfd, 0x15, 0xc1, 0x3b, 0x1b, 0x07, 0xf9, + 0xaa, 0x1d, 0x3b, 0xea, 0x57, 0x78, 0x9c, 0xa0, + 0x31, 0xad, 0x85, 0xc7, 0xa7, 0x1d, 0xd7, 0x03, + 0x54, 0xec, 0x63, 0x12, 0x38, 0xca, 0x34, 0x45, + }, + }, + { + .algorithm = NID_sha512, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09, + }, + }, + + /* SHA3-224 */ + { + .algorithm = NID_sha3_224, + .in = "abc", + .in_len = 3, + .out = { + 0xe6, 0x42, 0x82, 0x4c, 0x3f, 0x8c, 0xf2, 0x4a, + 0xd0, 0x92, 0x34, 0xee, 0x7d, 0x3c, 0x76, 0x6f, + 0xc9, 0xa3, 0xa5, 0x16, 0x8d, 0x0c, 0x94, 0xad, + 0x73, 0xb4, 0x6f, 0xdf, + }, + }, + { + .algorithm = NID_sha3_224, + .in = "", + .in_len = 0, + .out = { + 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, + 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, + 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, + 0x5b, 0x5a, 0x6b, 0xc7, + }, + }, + { + .algorithm = NID_sha3_224, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x8a, 0x24, 0x10, 0x8b, 0x15, 0x4a, 0xda, 0x21, + 0xc9, 0xfd, 0x55, 0x74, 0x49, 0x44, 0x79, 0xba, + 0x5c, 0x7e, 0x7a, 0xb7, 0x6e, 0xf2, 0x64, 0xea, + 0xd0, 0xfc, 0xce, 0x33, + }, + }, + { + .algorithm = NID_sha3_224, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0x54, 0x3e, 0x68, 0x68, 0xe1, 0x66, 0x6c, 0x1a, + 0x64, 0x36, 0x30, 0xdf, 0x77, 0x36, 0x7a, 0xe5, + 0xa6, 0x2a, 0x85, 0x07, 0x0a, 0x51, 0xc1, 0x4c, + 0xbf, 0x66, 0x5c, 0xbc, + }, + }, + + /* SHA3-256 */ + { + .algorithm = NID_sha3_256, + .in = "abc", + .in_len = 3, + .out = { + 0x3a, 0x98, 0x5d, 0xa7, 0x4f, 0xe2, 0x25, 0xb2, + 0x04, 0x5c, 0x17, 0x2d, 0x6b, 0xd3, 0x90, 0xbd, + 0x85, 0x5f, 0x08, 0x6e, 0x3e, 0x9d, 0x52, 0x5b, + 0x46, 0xbf, 0xe2, 0x45, 0x11, 0x43, 0x15, 0x32, + }, + }, + { + .algorithm = NID_sha3_256, + .in = "", + .in_len = 0, + .out = { + 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, + 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, + 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, + 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a, + }, + }, + { + .algorithm = NID_sha3_256, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x41, 0xc0, 0xdb, 0xa2, 0xa9, 0xd6, 0x24, 0x08, + 0x49, 0x10, 0x03, 0x76, 0xa8, 0x23, 0x5e, 0x2c, + 0x82, 0xe1, 0xb9, 0x99, 0x8a, 0x99, 0x9e, 0x21, + 0xdb, 0x32, 0xdd, 0x97, 0x49, 0x6d, 0x33, 0x76, + }, + }, + { + .algorithm = NID_sha3_256, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0x91, 0x6f, 0x60, 0x61, 0xfe, 0x87, 0x97, 0x41, + 0xca, 0x64, 0x69, 0xb4, 0x39, 0x71, 0xdf, 0xdb, + 0x28, 0xb1, 0xa3, 0x2d, 0xc3, 0x6c, 0xb3, 0x25, + 0x4e, 0x81, 0x2b, 0xe2, 0x7a, 0xad, 0x1d, 0x18, + }, + }, + + /* SHA3-384 */ + { + .algorithm = NID_sha3_384, + .in = "abc", + .in_len = 3, + .out = { + 0xec, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6f, 0xc9, + 0x26, 0x45, 0x9f, 0x58, 0xe2, 0xc6, 0xad, 0x8d, + 0xf9, 0xb4, 0x73, 0xcb, 0x0f, 0xc0, 0x8c, 0x25, + 0x96, 0xda, 0x7c, 0xf0, 0xe4, 0x9b, 0xe4, 0xb2, + 0x98, 0xd8, 0x8c, 0xea, 0x92, 0x7a, 0xc7, 0xf5, + 0x39, 0xf1, 0xed, 0xf2, 0x28, 0x37, 0x6d, 0x25, + }, + }, + { + .algorithm = NID_sha3_384, + .in = "", + .in_len = 0, + .out = { + 0x0c, 0x63, 0xa7, 0x5b, 0x84, 0x5e, 0x4f, 0x7d, + 0x01, 0x10, 0x7d, 0x85, 0x2e, 0x4c, 0x24, 0x85, + 0xc5, 0x1a, 0x50, 0xaa, 0xaa, 0x94, 0xfc, 0x61, + 0x99, 0x5e, 0x71, 0xbb, 0xee, 0x98, 0x3a, 0x2a, + 0xc3, 0x71, 0x38, 0x31, 0x26, 0x4a, 0xdb, 0x47, + 0xfb, 0x6b, 0xd1, 0xe0, 0x58, 0xd5, 0xf0, 0x04, + }, + }, + { + .algorithm = NID_sha3_384, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x99, 0x1c, 0x66, 0x57, 0x55, 0xeb, 0x3a, 0x4b, + 0x6b, 0xbd, 0xfb, 0x75, 0xc7, 0x8a, 0x49, 0x2e, + 0x8c, 0x56, 0xa2, 0x2c, 0x5c, 0x4d, 0x7e, 0x42, + 0x9b, 0xfd, 0xbc, 0x32, 0xb9, 0xd4, 0xad, 0x5a, + 0xa0, 0x4a, 0x1f, 0x07, 0x6e, 0x62, 0xfe, 0xa1, + 0x9e, 0xef, 0x51, 0xac, 0xd0, 0x65, 0x7c, 0x22, + }, + }, + { + .algorithm = NID_sha3_384, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0x79, 0x40, 0x7d, 0x3b, 0x59, 0x16, 0xb5, 0x9c, + 0x3e, 0x30, 0xb0, 0x98, 0x22, 0x97, 0x47, 0x91, + 0xc3, 0x13, 0xfb, 0x9e, 0xcc, 0x84, 0x9e, 0x40, + 0x6f, 0x23, 0x59, 0x2d, 0x04, 0xf6, 0x25, 0xdc, + 0x8c, 0x70, 0x9b, 0x98, 0xb4, 0x3b, 0x38, 0x52, + 0xb3, 0x37, 0x21, 0x61, 0x79, 0xaa, 0x7f, 0xc7, + }, + }, + + /* SHA3-512 */ + { + .algorithm = NID_sha3_512, + .in = "abc", + .in_len = 3, + .out = { + 0xb7, 0x51, 0x85, 0x0b, 0x1a, 0x57, 0x16, 0x8a, + 0x56, 0x93, 0xcd, 0x92, 0x4b, 0x6b, 0x09, 0x6e, + 0x08, 0xf6, 0x21, 0x82, 0x74, 0x44, 0xf7, 0x0d, + 0x88, 0x4f, 0x5d, 0x02, 0x40, 0xd2, 0x71, 0x2e, + 0x10, 0xe1, 0x16, 0xe9, 0x19, 0x2a, 0xf3, 0xc9, + 0x1a, 0x7e, 0xc5, 0x76, 0x47, 0xe3, 0x93, 0x40, + 0x57, 0x34, 0x0b, 0x4c, 0xf4, 0x08, 0xd5, 0xa5, + 0x65, 0x92, 0xf8, 0x27, 0x4e, 0xec, 0x53, 0xf0, + }, + }, + { + .algorithm = NID_sha3_512, + .in = "", + .in_len = 0, + .out = { + 0xa6, 0x9f, 0x73, 0xcc, 0xa2, 0x3a, 0x9a, 0xc5, + 0xc8, 0xb5, 0x67, 0xdc, 0x18, 0x5a, 0x75, 0x6e, + 0x97, 0xc9, 0x82, 0x16, 0x4f, 0xe2, 0x58, 0x59, + 0xe0, 0xd1, 0xdc, 0xc1, 0x47, 0x5c, 0x80, 0xa6, + 0x15, 0xb2, 0x12, 0x3a, 0xf1, 0xf5, 0xf9, 0x4c, + 0x11, 0xe3, 0xe9, 0x40, 0x2c, 0x3a, 0xc5, 0x58, + 0xf5, 0x00, 0x19, 0x9d, 0x95, 0xb6, 0xd3, 0xe3, + 0x01, 0x75, 0x85, 0x86, 0x28, 0x1d, 0xcd, 0x26, + }, + }, + { + .algorithm = NID_sha3_512, + .in = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmno" + "mnopnopq", + .in_len = 56, + .out = { + 0x04, 0xa3, 0x71, 0xe8, 0x4e, 0xcf, 0xb5, 0xb8, + 0xb7, 0x7c, 0xb4, 0x86, 0x10, 0xfc, 0xa8, 0x18, + 0x2d, 0xd4, 0x57, 0xce, 0x6f, 0x32, 0x6a, 0x0f, + 0xd3, 0xd7, 0xec, 0x2f, 0x1e, 0x91, 0x63, 0x6d, + 0xee, 0x69, 0x1f, 0xbe, 0x0c, 0x98, 0x53, 0x02, + 0xba, 0x1b, 0x0d, 0x8d, 0xc7, 0x8c, 0x08, 0x63, + 0x46, 0xb5, 0x33, 0xb4, 0x9c, 0x03, 0x0d, 0x99, + 0xa2, 0x7d, 0xaf, 0x11, 0x39, 0xd6, 0xe7, 0x5e, + }, + }, + { + .algorithm = NID_sha3_512, + .in = + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklm" + "ghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu", + .in_len = 112, + .out = { + 0xaf, 0xeb, 0xb2, 0xef, 0x54, 0x2e, 0x65, 0x79, + 0xc5, 0x0c, 0xad, 0x06, 0xd2, 0xe5, 0x78, 0xf9, + 0xf8, 0xdd, 0x68, 0x81, 0xd7, 0xdc, 0x82, 0x4d, + 0x26, 0x36, 0x0f, 0xee, 0xbf, 0x18, 0xa4, 0xfa, + 0x73, 0xe3, 0x26, 0x11, 0x22, 0x94, 0x8e, 0xfc, + 0xfd, 0x49, 0x2e, 0x74, 0xe8, 0x2e, 0x21, 0x89, + 0xed, 0x0f, 0xb4, 0x40, 0xd1, 0x87, 0xf3, 0x82, + 0x27, 0x0c, 0xb4, 0x55, 0xf2, 0x1d, 0xd1, 0x85, + }, + }, +}; + +struct sha_repetition_test { + const int algorithm; + const uint8_t in; + const size_t in_repetitions; + const uint8_t out[EVP_MAX_MD_SIZE]; +}; + +static const struct sha_repetition_test sha_repetition_tests[] = { + /* SHA-1 */ + { + .algorithm = NID_sha1, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, + 0xf6, 0x1e, 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31, + 0x65, 0x34, 0x01, 0x6f, + }, + }, + + /* SHA-224 */ + { + .algorithm = NID_sha224, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0x20, 0x79, 0x46, 0x55, 0x98, 0x0c, 0x91, 0xd8, + 0xbb, 0xb4, 0xc1, 0xea, 0x97, 0x61, 0x8a, 0x4b, + 0xf0, 0x3f, 0x42, 0x58, 0x19, 0x48, 0xb2, 0xee, + 0x4e, 0xe7, 0xad, 0x67, + }, + }, + + /* SHA-256 */ + { + .algorithm = NID_sha256, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, + 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67, + 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e, + 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0, + }, + }, + + /* SHA-384 */ + { + .algorithm = NID_sha384, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0x9d, 0x0e, 0x18, 0x09, 0x71, 0x64, 0x74, 0xcb, + 0x08, 0x6e, 0x83, 0x4e, 0x31, 0x0a, 0x4a, 0x1c, + 0xed, 0x14, 0x9e, 0x9c, 0x00, 0xf2, 0x48, 0x52, + 0x79, 0x72, 0xce, 0xc5, 0x70, 0x4c, 0x2a, 0x5b, + 0x07, 0xb8, 0xb3, 0xdc, 0x38, 0xec, 0xc4, 0xeb, + 0xae, 0x97, 0xdd, 0xd8, 0x7f, 0x3d, 0x89, 0x85, + }, + }, + + /* SHA-512 */ + { + .algorithm = NID_sha512, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64, + 0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63, + 0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb, + 0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a, + 0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b, + 0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e, + 0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b, + }, + }, + + /* SHA3-224 */ + { + .algorithm = NID_sha3_224, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0xd6, 0x93, 0x35, 0xb9, 0x33, 0x25, 0x19, 0x2e, + 0x51, 0x6a, 0x91, 0x2e, 0x6d, 0x19, 0xa1, 0x5c, + 0xb5, 0x1c, 0x6e, 0xd5, 0xc1, 0x52, 0x43, 0xe7, + 0xa7, 0xfd, 0x65, 0x3c, + }, + }, + + /* SHA3-256 */ + { + .algorithm = NID_sha3_256, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0x5c, 0x88, 0x75, 0xae, 0x47, 0x4a, 0x36, 0x34, + 0xba, 0x4f, 0xd5, 0x5e, 0xc8, 0x5b, 0xff, 0xd6, + 0x61, 0xf3, 0x2a, 0xca, 0x75, 0xc6, 0xd6, 0x99, + 0xd0, 0xcd, 0xcb, 0x6c, 0x11, 0x58, 0x91, 0xc1, + }, + }, + + /* SHA3-384 */ + { + .algorithm = NID_sha3_384, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0xee, 0xe9, 0xe2, 0x4d, 0x78, 0xc1, 0x85, 0x53, + 0x37, 0x98, 0x34, 0x51, 0xdf, 0x97, 0xc8, 0xad, + 0x9e, 0xed, 0xf2, 0x56, 0xc6, 0x33, 0x4f, 0x8e, + 0x94, 0x8d, 0x25, 0x2d, 0x5e, 0x0e, 0x76, 0x84, + 0x7a, 0xa0, 0x77, 0x4d, 0xdb, 0x90, 0xa8, 0x42, + 0x19, 0x0d, 0x2c, 0x55, 0x8b, 0x4b, 0x83, 0x40, + }, + }, + + /* SHA3-512 */ + { + .algorithm = NID_sha3_512, + .in = 'a', + .in_repetitions = 1000000, + .out = { + 0x3c, 0x3a, 0x87, 0x6d, 0xa1, 0x40, 0x34, 0xab, + 0x60, 0x62, 0x7c, 0x07, 0x7b, 0xb9, 0x8f, 0x7e, + 0x12, 0x0a, 0x2a, 0x53, 0x70, 0x21, 0x2d, 0xff, + 0xb3, 0x38, 0x5a, 0x18, 0xd4, 0xf3, 0x88, 0x59, + 0xed, 0x31, 0x1d, 0x0a, 0x9d, 0x51, 0x41, 0xce, + 0x9c, 0xc5, 0xc6, 0x6e, 0xe6, 0x89, 0xb2, 0x66, + 0xa8, 0xaa, 0x18, 0xac, 0xe8, 0x28, 0x2a, 0x0e, + 0x0d, 0xb5, 0x96, 0xc9, 0x0b, 0x0a, 0x7b, 0x87, + }, + }, +}; + +#define N_SHA_TESTS (sizeof(sha_tests) / sizeof(sha_tests[0])) +#define N_SHA_REPETITION_TESTS (sizeof(sha_repetition_tests) / sizeof(sha_repetition_tests[0])) + +typedef unsigned char *(*sha_hash_func)(const unsigned char *, size_t, + unsigned char *); + +static int +sha_hash_from_algorithm(int algorithm, const char **out_label, + sha_hash_func *out_func, const EVP_MD **out_md, size_t *out_len) +{ + const char *label; + sha_hash_func sha_func; + const EVP_MD *md; + size_t len; + + switch (algorithm) { + case NID_sha1: + label = SN_sha1; + sha_func = SHA1; + md = EVP_sha1(); + len = SHA_DIGEST_LENGTH; + break; + case NID_sha224: + label = SN_sha224; + sha_func = SHA224; + md = EVP_sha224(); + len = SHA224_DIGEST_LENGTH; + break; + case NID_sha256: + label = SN_sha256; + sha_func = SHA256; + md = EVP_sha256(); + len = SHA256_DIGEST_LENGTH; + break; + case NID_sha384: + label = SN_sha384; + sha_func = SHA384; + md = EVP_sha384(); + len = SHA384_DIGEST_LENGTH; + break; + case NID_sha512: + label = SN_sha512; + sha_func = SHA512; + md = EVP_sha512(); + len = SHA512_DIGEST_LENGTH; + break; + case NID_sha3_224: + label = SN_sha3_224; + sha_func = NULL; + md = EVP_sha3_224(); + len = 224 / 8; + break; + case NID_sha3_256: + label = SN_sha3_256; + sha_func = NULL; + md = EVP_sha3_256(); + len = 256 / 8; + break; + case NID_sha3_384: + label = SN_sha3_384; + sha_func = NULL; + md = EVP_sha3_384(); + len = 384 / 8; + break; + case NID_sha3_512: + label = SN_sha3_512; + sha_func = NULL; + md = EVP_sha3_512(); + len = 512 / 8; + break; + default: + fprintf(stderr, "FAIL: unknown algorithm (%d)\n", + algorithm); + return 0; + } + + if (out_label != NULL) + *out_label = label; + if (out_func != NULL) + *out_func = sha_func; + if (out_md != NULL) + *out_md = md; + if (out_len != NULL) + *out_len = len; + + return 1; +} + +static int +sha_test(void) +{ + sha_hash_func sha_func; + const struct sha_test *st; + EVP_MD_CTX *hash = NULL; + const EVP_MD *md; + uint8_t out[EVP_MAX_MD_SIZE]; + size_t in_len, out_len; + size_t i; + const char *label; + int failed = 1; + + if ((hash = EVP_MD_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); + goto failed; + } + + for (i = 0; i < N_SHA_TESTS; i++) { + st = &sha_tests[i]; + if (!sha_hash_from_algorithm(st->algorithm, &label, &sha_func, + &md, &out_len)) + goto failed; + + /* Digest */ + if (sha_func != NULL) { + memset(out, 0, sizeof(out)); + sha_func(st->in, st->in_len, out); + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): mismatch\n", + label, i); + goto failed; + } + } + + /* EVP single-shot digest */ + memset(out, 0, sizeof(out)); + if (!EVP_Digest(st->in, st->in_len, out, NULL, md, NULL)) { + fprintf(stderr, "FAIL (%s:%zu): EVP_Digest failed\n", + label, i); + goto failed; + } + + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, + "FAIL (%s:%zu): EVP single-shot mismatch\n", + label, i); + goto failed; + } + + /* EVP digest */ + memset(out, 0, sizeof(out)); + if (!EVP_DigestInit_ex(hash, md, NULL)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestInit_ex failed\n", + label, i); + goto failed; + } + + in_len = st->in_len / 2; + if (!EVP_DigestUpdate(hash, st->in, in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestUpdate first half " + "failed\n", label, i); + goto failed; + } + + if (!EVP_DigestUpdate(hash, st->in + in_len, + st->in_len - in_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestUpdate second half " + "failed\n", label, i); + goto failed; + } + + if (!EVP_DigestFinal_ex(hash, out, NULL)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", + label, i); + goto failed; + } + + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", + label, i); + goto failed; + } + } + + failed = 0; + + failed: + EVP_MD_CTX_free(hash); + return failed; +} + +static int +sha_repetition_test(void) +{ + const struct sha_repetition_test *st; + EVP_MD_CTX *hash = NULL; + const EVP_MD *md; + uint8_t buf[1024]; + uint8_t out[EVP_MAX_MD_SIZE]; + size_t out_len, part_len; + size_t i, j; + const char *label; + int failed = 1; + + if ((hash = EVP_MD_CTX_new()) == NULL) { + fprintf(stderr, "FAIL: EVP_MD_CTX_new() failed\n"); + goto failed; + } + + for (i = 0; i < N_SHA_REPETITION_TESTS; i++) { + st = &sha_repetition_tests[i]; + if (!sha_hash_from_algorithm(st->algorithm, &label, NULL, &md, + &out_len)) + goto failed; + + /* EVP digest */ + if (!EVP_DigestInit_ex(hash, md, NULL)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestInit_ex failed\n", + label, i); + goto failed; + } + + memset(buf, st->in, sizeof(buf)); + + for (j = 0; j < st->in_repetitions;) { + part_len = arc4random_uniform(sizeof(buf)); + if (part_len > st->in_repetitions - j) + part_len = st->in_repetitions - j; + + if (!EVP_DigestUpdate(hash, buf, part_len)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestUpdate failed\n", + label, i); + goto failed; + } + + j += part_len; + } + + if (!EVP_DigestFinal_ex(hash, out, NULL)) { + fprintf(stderr, + "FAIL (%s:%zu): EVP_DigestFinal_ex failed\n", + label, i); + goto failed; + } + + if (memcmp(st->out, out, out_len) != 0) { + fprintf(stderr, "FAIL (%s:%zu): EVP mismatch\n", + label, i); + goto failed; + } + } + + failed = 0; + + failed: + EVP_MD_CTX_free(hash); + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= sha_test(); + failed |= sha_repetition_test(); + + return failed; +} diff --git a/tests/signertest.c b/tests/signertest.c new file mode 100644 index 0000000..f0523d3 --- /dev/null +++ b/tests/signertest.c @@ -0,0 +1,471 @@ +/* $OpenBSD: signertest.c,v 1.6 2023/04/14 12:41:26 tb Exp $ */ +/* + * Copyright (c) 2017, 2018, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "tls_internal.h" + +#ifndef CERTSDIR +#define CERTSDIR "." +#endif + +const char *cert_path = CERTSDIR; +int sign_cb_count; + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static void +load_file(const char *filename, const uint8_t **data, size_t *data_len) +{ + char *filepath; + struct stat sb; + uint8_t *buf; + size_t len; + ssize_t n; + int fd; + + if (asprintf(&filepath, "%s/%s", cert_path, filename) == -1) + err(1, "asprintf"); + if ((fd = open(filepath, O_RDONLY)) == -1) + err(1, "failed to open '%s'", filepath); + if ((fstat(fd, &sb)) == -1) + err(1, "failed to stat '%s'", filepath); + if (sb.st_size < 0) + err(1, "file size invalid for '%s'", filepath); + len = (size_t)sb.st_size; + if ((buf = malloc(len)) == NULL) + err(1, "out of memory"); + n = read(fd, buf, len); + if (n < 0 || (size_t)n != len) + err(1, "failed to read '%s'", filepath); + close(fd); + + *data = buf; + *data_len = len; + + free(filepath); +} + +static int +compare_mem(char *label, const uint8_t *data1, size_t data1_len, + const uint8_t *data2, size_t data2_len) +{ + if (data1_len != data2_len) { + fprintf(stderr, "FAIL: %s length mismatch (%zu != %zu)\n", + label, data1_len, data2_len); + fprintf(stderr, "Got:\n"); + hexdump(data1, data1_len); + fprintf(stderr, "Want:\n"); + hexdump(data2, data2_len); + return -1; + } + if (data1 == data2) { + fprintf(stderr, "FAIL: %s comparing same memory (%p == %p)\n", + label, data1, data2); + return -1; + } + if (memcmp(data1, data2, data1_len) != 0) { + fprintf(stderr, "FAIL: %s data mismatch\n", label); + fprintf(stderr, "Got:\n"); + hexdump(data1, data1_len); + fprintf(stderr, "Want:\n"); + hexdump(data2, data2_len); + return -1; + } + return 0; +} + +const char *server_ecdsa_pubkey_hash = \ + "SHA256:cef2616ece9a57a76d072013b0faad2232511487c67c45bf00fbcecc070e2f5b"; +const char *server_rsa_pubkey_hash = \ + "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9f"; +const char *server_unknown_pubkey_hash = \ + "SHA256:f03c535d374614e7356c0a4e6fd37fe94297b60ed86212adcba40e8e0b07bc9e"; + +const uint8_t test_digest[] = { + 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, 0x20, +}; + +const uint8_t test_rsa_signature[] = { + 0x77, 0xfb, 0xdd, 0x41, 0x45, 0x40, 0x25, 0xd6, + 0x01, 0xe0, 0x59, 0x04, 0x65, 0xae, 0xa1, 0x59, + 0xae, 0xa2, 0x44, 0x08, 0xf7, 0x02, 0x3d, 0xe4, + 0xc6, 0x0d, 0x4d, 0x9a, 0x3a, 0xce, 0x34, 0xbe, + 0x2e, 0xc0, 0xfc, 0xbd, 0x5b, 0x21, 0xe4, 0xbb, + 0xce, 0x02, 0xfd, 0xc3, 0xfc, 0x3d, 0x25, 0xe7, + 0xd1, 0x9a, 0x13, 0x60, 0xcb, 0x07, 0xda, 0x23, + 0xf7, 0xa3, 0xf0, 0xaf, 0x16, 0x1b, 0x28, 0x54, + 0x0a, 0x3c, 0xc1, 0x31, 0x08, 0x0f, 0x2f, 0xce, + 0x6d, 0x09, 0x45, 0x48, 0xee, 0x37, 0xa8, 0xc3, + 0x91, 0xcb, 0xde, 0xad, 0xc6, 0xcf, 0x18, 0x19, + 0xeb, 0xad, 0x08, 0x66, 0x2f, 0xce, 0x1d, 0x07, + 0xe3, 0x03, 0x84, 0x00, 0xca, 0x0f, 0x1d, 0x0f, + 0x0e, 0x6e, 0x54, 0xc1, 0x39, 0x3f, 0x2a, 0x78, + 0xc8, 0xa3, 0x6d, 0x52, 0xb9, 0x26, 0x8e, 0x7e, + 0x7a, 0x18, 0x3c, 0x8a, 0x50, 0xa3, 0xad, 0xab, + 0xd0, 0x03, 0xc5, 0x3e, 0xa5, 0x46, 0x87, 0xb0, + 0x03, 0xde, 0xd9, 0xe5, 0x4d, 0x73, 0x95, 0xcf, + 0xe1, 0x59, 0x8e, 0x2e, 0x50, 0x69, 0xe6, 0x20, + 0xaf, 0x21, 0x4f, 0xe6, 0xc4, 0x86, 0x11, 0x36, + 0x79, 0x68, 0x83, 0xde, 0x0e, 0x81, 0xde, 0x2e, + 0xd0, 0x19, 0x3f, 0x4b, 0xad, 0x3e, 0xbf, 0xdd, + 0x14, 0x4d, 0x66, 0xf3, 0x7f, 0x7d, 0xca, 0xed, + 0x99, 0x62, 0xdc, 0x7c, 0xb2, 0x8b, 0x57, 0xcb, + 0xdf, 0xed, 0x16, 0x13, 0x86, 0xd8, 0xd8, 0xb4, + 0x44, 0x6e, 0xd5, 0x54, 0xbc, 0xdf, 0xe7, 0x34, + 0x10, 0xa4, 0x17, 0x5f, 0xb7, 0xe1, 0x33, 0x2c, + 0xc1, 0x70, 0x5b, 0x87, 0x0d, 0x39, 0xee, 0xe8, + 0xec, 0x18, 0x92, 0xe8, 0x95, 0xa8, 0x93, 0x26, + 0xdf, 0x26, 0x93, 0x96, 0xfd, 0xad, 0x81, 0xb6, + 0xeb, 0x72, 0x9c, 0xd4, 0xcc, 0xf6, 0x9f, 0xb0, + 0xbb, 0xbd, 0xbd, 0x44, 0x1c, 0x99, 0x07, 0x6d, +}; + +static int +do_signer_tests(void) +{ + char *server_rsa_filepath = NULL; + const uint8_t *server_ecdsa = NULL; + size_t server_ecdsa_len; + struct tls_signer *signer = NULL; + uint8_t *signature = NULL; + size_t signature_len; + EC_KEY *ec_key = NULL; + X509 *x509 = NULL; + BIO *bio = NULL; + int failed = 1; + + load_file("server1-ecdsa.pem", &server_ecdsa, &server_ecdsa_len); + + if (asprintf(&server_rsa_filepath, "%s/%s", cert_path, + "server1-rsa.pem") == -1) { + fprintf(stderr, "FAIL: failed to build rsa file path\n"); + goto failure; + } + + /* Load the ECDSA public key - we'll need it later. */ + if ((bio = BIO_new_mem_buf(server_ecdsa, server_ecdsa_len)) == NULL) { + fprintf(stderr, "FAIL: failed to create bio\n"); + goto failure; + } + if ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL)) == NULL) { + fprintf(stderr, "FAIL: failed to load certificate\n"); + goto failure; + } + if ((ec_key = EVP_PKEY_get1_EC_KEY(X509_get0_pubkey(x509))) == NULL) { + fprintf(stderr, "FAIL: failed to get EC public key\n"); + goto failure; + } + + /* Create signer and add key pairs (one ECDSA, one RSA). */ + if ((signer = tls_signer_new()) == NULL) { + fprintf(stderr, "FAIL: failed to create tls signer\n"); + goto failure; + } + if (tls_signer_add_keypair_mem(signer, server_ecdsa, server_ecdsa_len, + server_ecdsa, server_ecdsa_len) == -1) { + fprintf(stderr, "FAIL: failed to add ECDSA keypair to tls " + "signer: %s\n", tls_signer_error(signer)); + goto failure; + } + if (tls_signer_add_keypair_file(signer, server_rsa_filepath, + server_rsa_filepath) == -1) { + fprintf(stderr, "FAIL: failed to add RSA keypair to tls " + "signer: %s\n", tls_signer_error(signer)); + goto failure; + } + + /* Sign with RSA. */ + if (tls_signer_sign(signer, server_rsa_pubkey_hash, test_digest, + sizeof(test_digest), TLS_PADDING_RSA_PKCS1, &signature, + &signature_len) == -1) { + fprintf(stderr, "FAIL: failed to sign with RSA key: %s\n", + tls_signer_error(signer)); + goto failure; + } + if (compare_mem("rsa signature", signature, signature_len, + test_rsa_signature, sizeof(test_rsa_signature)) == -1) + goto failure; + + free(signature); + signature = NULL; + + /* + * Sign with ECDSA - ECDSA signatures are non-deterministic so we cannot + * check against a known value, rather we can only verify the signature. + */ + if (tls_signer_sign(signer, server_ecdsa_pubkey_hash, test_digest, + sizeof(test_digest), TLS_PADDING_NONE, &signature, + &signature_len) == -1) { + fprintf(stderr, "FAIL: failed to sign with ECDSA key: %s\n", + tls_signer_error(signer)); + goto failure; + } + if (ECDSA_verify(0, test_digest, sizeof(test_digest), signature, + signature_len, ec_key) != 1) { + fprintf(stderr, "FAIL: failed to verify ECDSA signature\n"); + goto failure; + } + + free(signature); + signature = NULL; + + /* Attempt to sign with an unknown cert pubkey hash. */ + if (tls_signer_sign(signer, server_unknown_pubkey_hash, test_digest, + sizeof(test_digest), TLS_PADDING_NONE, &signature, + &signature_len) != -1) { + fprintf(stderr, "FAIL: signing succeeded with unknown key\n"); + goto failure; + } + if (strcmp(tls_signer_error(signer), "key not found") != 0) { + fprintf(stderr, "FAIL: got tls signer error '%s', want " + "'key not found'\n", tls_signer_error(signer)); + goto failure; + } + + failed = 0; + + failure: + BIO_free(bio); + EC_KEY_free(ec_key); + X509_free(x509); + tls_signer_free(signer); + free((uint8_t *)server_ecdsa); + free(server_rsa_filepath); + free(signature); + + return failed; +} + +static int +do_tls_handshake(char *name, struct tls *ctx) +{ + int rv; + + rv = tls_handshake(ctx); + if (rv == 0) + return (1); + if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT) + return (0); + + errx(1, "%s handshake failed: %s", name, tls_error(ctx)); +} + +static int +do_client_server_handshake(char *desc, struct tls *client, + struct tls *server_cctx) +{ + int i, client_done, server_done; + + i = client_done = server_done = 0; + do { + if (client_done == 0) + client_done = do_tls_handshake("client", client); + if (server_done == 0) + server_done = do_tls_handshake("server", server_cctx); + } while (i++ < 100 && (client_done == 0 || server_done == 0)); + + if (client_done == 0 || server_done == 0) { + printf("FAIL: %s TLS handshake did not complete\n", desc); + return (1); + } + + return (0); +} + +static int +test_tls_handshake_socket(struct tls *client, struct tls *server) +{ + struct tls *server_cctx; + int failure; + int sv[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC, + sv) == -1) + err(1, "failed to create socketpair"); + + if (tls_accept_socket(server, &server_cctx, sv[0]) == -1) + errx(1, "failed to accept: %s", tls_error(server)); + + if (tls_connect_socket(client, sv[1], "test") == -1) + errx(1, "failed to connect: %s", tls_error(client)); + + failure = do_client_server_handshake("socket", client, server_cctx); + + tls_free(server_cctx); + + close(sv[0]); + close(sv[1]); + + return (failure); +} + +static int +test_signer_tls_sign(void *cb_arg, const char *pubkey_hash, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + struct tls_signer *signer = cb_arg; + + sign_cb_count++; + + return tls_signer_sign(signer, pubkey_hash, input, input_len, + padding_type, out_signature, out_signature_len); +} + +static int +test_signer_tls(char *certfile, char *keyfile, char *cafile) +{ + struct tls_config *client_cfg, *server_cfg; + struct tls_signer *signer; + struct tls *client, *server; + int failure = 0; + + if ((signer = tls_signer_new()) == NULL) + errx(1, "failed to create tls signer"); + if (tls_signer_add_keypair_file(signer, certfile, keyfile)) + errx(1, "failed to add keypair to signer"); + + if ((client = tls_client()) == NULL) + errx(1, "failed to create tls client"); + if ((client_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls client config"); + tls_config_insecure_noverifyname(client_cfg); + if (tls_config_set_ca_file(client_cfg, cafile) == -1) + errx(1, "failed to set ca: %s", tls_config_error(client_cfg)); + + if ((server = tls_server()) == NULL) + errx(1, "failed to create tls server"); + if ((server_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls server config"); + if (tls_config_set_sign_cb(server_cfg, test_signer_tls_sign, + signer) == -1) + errx(1, "failed to set server signer callback: %s", + tls_config_error(server_cfg)); + if (tls_config_set_cert_file(server_cfg, certfile) == -1) + errx(1, "failed to set server certificate: %s", + tls_config_error(server_cfg)); + + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + tls_config_free(client_cfg); + tls_config_free(server_cfg); + + failure |= test_tls_handshake_socket(client, server); + + tls_signer_free(signer); + tls_free(client); + tls_free(server); + + return (failure); +} + +static int +do_signer_tls_tests(void) +{ + char *server_ecdsa_cert = NULL, *server_ecdsa_key = NULL; + char *server_rsa_cert = NULL, *server_rsa_key = NULL; + char *ca_root_ecdsa = NULL, *ca_root_rsa = NULL; + int failure = 0; + + if (asprintf(&ca_root_ecdsa, "%s/%s", cert_path, + "ca-root-ecdsa.pem") == -1) + err(1, "ca ecdsa root"); + if (asprintf(&ca_root_rsa, "%s/%s", cert_path, + "ca-root-rsa.pem") == -1) + err(1, "ca rsa root"); + if (asprintf(&server_ecdsa_cert, "%s/%s", cert_path, + "server1-ecdsa-chain.pem") == -1) + err(1, "server ecdsa chain"); + if (asprintf(&server_ecdsa_key, "%s/%s", cert_path, + "server1-ecdsa.pem") == -1) + err(1, "server ecdsa key"); + if (asprintf(&server_rsa_cert, "%s/%s", cert_path, + "server1-rsa-chain.pem") == -1) + err(1, "server rsa chain"); + if (asprintf(&server_rsa_key, "%s/%s", cert_path, + "server1-rsa.pem") == -1) + err(1, "server rsa key"); + + failure |= test_signer_tls(server_ecdsa_cert, server_ecdsa_key, + ca_root_ecdsa); + failure |= test_signer_tls(server_rsa_cert, server_rsa_key, + ca_root_rsa); + + if (sign_cb_count != 2) { + fprintf(stderr, "FAIL: sign callback was called %d times, " + "want 2\n", sign_cb_count); + failure |= 1; + } + + free(ca_root_ecdsa); + free(ca_root_rsa); + free(server_ecdsa_cert); + free(server_ecdsa_key); + free(server_rsa_cert); + free(server_rsa_key); + + return (failure); +} + +int +main(int argc, char **argv) +{ + int failure = 0; + + if (argc > 2) { + fprintf(stderr, "usage: %s [certpath]\n", argv[0]); + return (1); + } + if (argc == 2) + cert_path = argv[1]; + + failure |= do_signer_tests(); + failure |= do_signer_tls_tests(); + + return (failure); +} diff --git a/tests/sm2crypttest.c b/tests/sm2crypttest.c new file mode 100644 index 0000000..80dcb93 --- /dev/null +++ b/tests/sm2crypttest.c @@ -0,0 +1,191 @@ +/* $OpenBSD: sm2crypttest.c,v 1.2 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2017, 2019 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_NO_SM2 +int main(int argc, char *argv[]) +{ + printf("No SM2 support\n"); + return (0); +} +#else +#include +#include "sm2_local.h" + +static EC_GROUP * +create_EC_group(const char *p_hex, const char *a_hex, const char *b_hex, + const char *x_hex, const char *y_hex, const char *order_hex, + const char *cof_hex) +{ + BIGNUM *p = NULL; + BIGNUM *a = NULL; + BIGNUM *b = NULL; + BIGNUM *g_x = NULL; + BIGNUM *g_y = NULL; + BIGNUM *order = NULL; + BIGNUM *cof = NULL; + EC_POINT *generator = NULL; + EC_GROUP *group = NULL; + + BN_hex2bn(&p, p_hex); + BN_hex2bn(&a, a_hex); + BN_hex2bn(&b, b_hex); + + group = EC_GROUP_new_curve_GFp(p, a, b, NULL); + BN_free(p); + BN_free(a); + BN_free(b); + + if (group == NULL) + return NULL; + + generator = EC_POINT_new(group); + if (generator == NULL) + return NULL; + + BN_hex2bn(&g_x, x_hex); + BN_hex2bn(&g_y, y_hex); + + if (EC_POINT_set_affine_coordinates(group, generator, g_x, g_y, + NULL) == 0) + return NULL; + + BN_free(g_x); + BN_free(g_y); + + BN_hex2bn(&order, order_hex); + BN_hex2bn(&cof, cof_hex); + + if (EC_GROUP_set_generator(group, generator, order, cof) == 0) + return NULL; + + EC_POINT_free(generator); + BN_free(order); + BN_free(cof); + + return group; +} + +static int +test_sm2(const EC_GROUP *group, const EVP_MD *digest, const char *privkey_hex, + const char *message) +{ + const size_t msg_len = strlen(message); + + BIGNUM *priv = NULL; + EC_KEY *key = NULL; + EC_POINT *pt = NULL; + size_t ctext_len = 0; + uint8_t *ctext = NULL; + uint8_t *recovered = NULL; + size_t recovered_len = msg_len; + int rc = 0; + + BN_hex2bn(&priv, privkey_hex); + + key = EC_KEY_new(); + EC_KEY_set_group(key, group); + EC_KEY_set_private_key(key, priv); + + pt = EC_POINT_new(group); + EC_POINT_mul(group, pt, priv, NULL, NULL, NULL); + + EC_KEY_set_public_key(key, pt); + BN_free(priv); + EC_POINT_free(pt); + + if (!SM2_ciphertext_size(key, digest, msg_len, &ctext_len)) + goto done; + ctext = calloc(1, ctext_len); + if (ctext == NULL) + goto done; + + rc = SM2_encrypt(key, digest, (const uint8_t *)message, msg_len, ctext, &ctext_len); + + if (rc == 0) + goto done; + + recovered = calloc(1, msg_len); + if (recovered == NULL) + goto done; + rc = SM2_decrypt(key, digest, ctext, ctext_len, recovered, &recovered_len); + + if (rc == 0) + goto done; + if (recovered_len != msg_len) + goto done; + if (memcmp(recovered, message, msg_len) != 0) + goto done; + + rc = 1; + done: + + free(ctext); + free(recovered); + EC_KEY_free(key); + return rc; +} + +int +main(int argc, char **argv) +{ + int rc; + EC_GROUP *test_group = + create_EC_group + ("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", + "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", + "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", + "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", + "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", + "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", + "1"); + + if (test_group == NULL) + return 1; + + rc = test_sm2(test_group, EVP_sm3(), + "1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0", + "encryption standard"); + + if (rc == 0) + return 1; + + /* Same test as above except using SHA-256 instead of SM3 */ + rc = test_sm2(test_group, EVP_sha256(), + "1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0", + "encryption standard"); + if (rc == 0) + return 1; + + EC_GROUP_free(test_group); + + printf("SUCCESS\n"); + + return 0; +} + +#endif diff --git a/tests/sm2evptest.c b/tests/sm2evptest.c new file mode 100644 index 0000000..9302461 --- /dev/null +++ b/tests/sm2evptest.c @@ -0,0 +1,256 @@ +/* $OpenBSD: sm2evptest.c,v 1.1.1.1 2021/08/18 16:06:56 tb Exp $ */ +/* + * Copyright (c) 2017, 2019 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +#include "tests.h" + +#ifdef OPENSSL_NO_SM2 +int +main(int argc, char *argv[]) +{ + printf("No SM2 support\n"); + return (0); +} +#else +static int +test_EVP_SM2_verify(void) +{ + /* From https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02#appendix-A */ + const char *pubkey = + "-----BEGIN PUBLIC KEY-----\n" + "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEAhULWnkwETxjouSQ1\n" + "v2/33kVyg5FcRVF9ci7biwjx38MwRAQgeHlotPoyw/0kF4Quc7v+/y88hItoMdfg\n" + "7GUiizk35JgEIGPkxtOyOwyEnPhCQUhL/kj2HVmlsWugbm4S0donxSSaBEEEQh3r\n" + "1hti6rZ0ZDTrw8wxXjIiCzut1QvcTE5sFH/t1D0GgFEry7QsB9RzSdIVO3DE5df9\n" + "/L+jbqGoWEG55G4JogIhAIVC1p5MBE8Y6LkkNb9v990pdyBjBIVijVrnTufDLnm3\n" + "AgEBA0IABArkx3mKoPEZRxvuEYJb5GICu3nipYRElel8BP9N8lSKfAJA+I8c1OFj\n" + "Uqc8F7fxbwc1PlOhdtaEqf4Ma7eY6Fc=\n" + "-----END PUBLIC KEY-----\n"; + + const char *input = "message digest"; + const char *user_id = "ALICE123@YAHOO.COM"; + + const uint8_t signature[] = { + 0x30, 0x44, 0x02, 0x20, + 0x40, 0xF1, 0xEC, 0x59, 0xF7, 0x93, 0xD9, 0xF4, 0x9E, 0x09, 0xDC, + 0xEF, 0x49, 0x13, 0x0D, 0x41, 0x94, 0xF7, 0x9F, 0xB1, 0xEE, 0xD2, + 0xCA, 0xA5, 0x5B, 0xAC, 0xDB, 0x49, 0xC4, 0xE7, 0x55, 0xD1, + 0x02, 0x20, + 0x6F, 0xC6, 0xDA, 0xC3, 0x2C, 0x5D, 0x5C, 0xF1, 0x0C, 0x77, 0xDF, + 0xB2, 0x0F, 0x7C, 0x2E, 0xB6, 0x67, 0xA4, 0x57, 0x87, 0x2F, 0xB0, + 0x9E, 0xC5, 0x63, 0x27, 0xA6, 0x7E, 0xC7, 0xDE, 0xEB, 0xE7 + }; + + int rc = 0; + BIO *bufio = NULL; + EVP_PKEY *pkey = NULL; + EVP_MD_CTX *md_ctx_verify = NULL; + EVP_PKEY_CTX *verify_ctx = NULL; + + bufio = BIO_new_mem_buf(pubkey, strlen(pubkey)); + CHECK_GOTO(bufio != NULL); + + pkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL); + CHECK_GOTO(pkey != NULL); + + CHECK_GOTO(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)); + + md_ctx_verify = EVP_MD_CTX_new(); + CHECK_GOTO(md_ctx_verify != NULL); + + CHECK_GOTO(EVP_DigestVerifyInit(md_ctx_verify, &verify_ctx, EVP_sm3(), NULL, pkey)); + + CHECK_GOTO(EVP_PKEY_CTX_set_sm2_uid(verify_ctx, user_id, strlen(user_id)) > 0); + + CHECK_GOTO(EVP_PKEY_CTX_hash_sm2_uid(verify_ctx) > 0); + + CHECK_GOTO(EVP_DigestVerifyUpdate(md_ctx_verify, input, strlen(input))); + + CHECK_GOTO(EVP_DigestVerifyFinal(md_ctx_verify, signature, sizeof(signature))); + + rc = 1; + err: + BIO_free(bufio); + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(md_ctx_verify); + return rc; +} + +static int +test_EVP_SM2(void) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + EVP_PKEY *params = NULL; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY_CTX *sign_ctx = NULL; + EVP_PKEY_CTX *verify_ctx = NULL; + EVP_PKEY_CTX *kctx = NULL; + size_t sig_len = 0; + unsigned char *sig = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_MD_CTX *md_ctx_verify = NULL; + EVP_PKEY_CTX *cctx = NULL; + int useid; + const char *uid_str = "nobody@example.com"; + uint8_t uid_buf[32] = {0}; + size_t uid_len = 0; + + uint8_t ciphertext[128]; + size_t ctext_len = sizeof(ciphertext); + + uint8_t plaintext[8]; + size_t ptext_len = sizeof(plaintext); + + uint8_t kMsg[4] = {1, 2, 3, 4}; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + CHECK_GOTO(pctx != NULL); + + CHECK_GOTO(EVP_PKEY_paramgen_init(pctx) == 1); + + CHECK_GOTO(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2)); + + CHECK_GOTO(EVP_PKEY_paramgen(pctx, ¶ms)); + + kctx = EVP_PKEY_CTX_new(params, NULL); + CHECK_GOTO(kctx != NULL); + + CHECK_GOTO(EVP_PKEY_keygen_init(kctx)); + + CHECK_GOTO(EVP_PKEY_keygen(kctx, &pkey)); + + CHECK_GOTO(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)); + + md_ctx = EVP_MD_CTX_new(); + CHECK_GOTO(md_ctx != NULL); + + md_ctx_verify = EVP_MD_CTX_new(); + CHECK_GOTO(md_ctx_verify != NULL); + + for (useid = 0; useid <= 1; ++useid) { + CHECK_GOTO(EVP_DigestSignInit(md_ctx, &sign_ctx, EVP_sm3(), NULL, pkey)); + + if (useid) { + CHECK_GOTO(EVP_PKEY_CTX_set_sm2_uid(sign_ctx, uid_str, strlen(uid_str)) > 0); + + CHECK_GOTO(EVP_PKEY_CTX_get_sm2_uid_len(sign_ctx, &uid_len) > 0); + + CHECK_GOTO(uid_len == strlen(uid_str)); + + CHECK_GOTO(EVP_PKEY_CTX_get_sm2_uid(sign_ctx, uid_buf) > 0); + + CHECK_GOTO(memcmp(uid_buf, uid_str, uid_len) == 0); + + CHECK_GOTO(EVP_PKEY_CTX_hash_sm2_uid(sign_ctx) > 0); + } + + CHECK_GOTO(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))); + + /* Determine the size of the signature. */ + CHECK_GOTO(EVP_DigestSignFinal(md_ctx, NULL, &sig_len)); + + CHECK_GOTO(sig_len == (size_t) EVP_PKEY_size(pkey)); + + sig = malloc(sig_len); + CHECK_GOTO(sig != NULL); + + CHECK_GOTO(EVP_DigestSignFinal(md_ctx, sig, &sig_len)); + + /* Ensure that the signature round-trips. */ + + CHECK_GOTO(EVP_DigestVerifyInit(md_ctx_verify, &verify_ctx, EVP_sm3(), NULL, pkey)); + + if (useid) { + CHECK_GOTO(EVP_PKEY_CTX_set_sm2_uid(verify_ctx, uid_str, strlen(uid_str)) > 0); + + CHECK_GOTO(EVP_PKEY_CTX_get_sm2_uid_len(verify_ctx, &uid_len) > 0); + + CHECK_GOTO(uid_len == strlen(uid_str)); + + CHECK_GOTO(EVP_PKEY_CTX_get_sm2_uid(verify_ctx, uid_buf) > 0); + + CHECK_GOTO(memcmp(uid_buf, uid_str, uid_len) == 0); + + CHECK_GOTO(EVP_PKEY_CTX_hash_sm2_uid(verify_ctx) > 0); + } + + CHECK_GOTO(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg))); + + CHECK_GOTO(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len)); + + free(sig); + sig = NULL; + } + + /* now check encryption/decryption */ + + cctx = EVP_PKEY_CTX_new(pkey, NULL); + CHECK_GOTO(cctx != NULL); + + CHECK_GOTO(EVP_PKEY_encrypt_init(cctx)); + + CHECK_GOTO(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg))); + + CHECK_GOTO(EVP_PKEY_decrypt_init(cctx)); + + CHECK_GOTO(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len)); + + CHECK_GOTO(ptext_len == sizeof(kMsg)); + + CHECK_GOTO(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0); + + ret = 1; + err: + EVP_PKEY_free(params); + EVP_MD_CTX_free(md_ctx); + EVP_MD_CTX_free(md_ctx_verify); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(cctx); + EVP_PKEY_free(pkey); + free(sig); + return ret; +} + +int +main(int argc, char *argv[]) +{ + if (!test_EVP_SM2()) { + fprintf(stderr, "test_EVP_SM2() failed.\n"); + fflush(stderr); + return 1; + } + if (!test_EVP_SM2_verify()) { + fprintf(stderr, "test_EVP_SM2_verify() failed.\n"); + fflush(stderr); + return 1; + } + + printf("SUCCESS\n"); + + return 0; +} + +#endif diff --git a/tests/sm2sigtest.c b/tests/sm2sigtest.c new file mode 100644 index 0000000..2ded5c4 --- /dev/null +++ b/tests/sm2sigtest.c @@ -0,0 +1,170 @@ +/* $OpenBSD: sm2sigtest.c,v 1.2 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2017, 2019 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef OPENSSL_NO_SM2 +int +main(int argc, char *argv[]) +{ + printf("No SM2 support\n"); + return (0); +} +#else +#include +#include "sm2_local.h" + +static EC_GROUP * +create_EC_group(const char *p_hex, const char *a_hex, const char *b_hex, + const char *x_hex, const char *y_hex, const char *order_hex, + const char *cof_hex) +{ + BIGNUM *p = NULL; + BIGNUM *a = NULL; + BIGNUM *b = NULL; + BIGNUM *g_x = NULL; + BIGNUM *g_y = NULL; + BIGNUM *order = NULL; + BIGNUM *cof = NULL; + EC_POINT *generator = NULL; + EC_GROUP *group = NULL; + + BN_hex2bn(&p, p_hex); + BN_hex2bn(&a, a_hex); + BN_hex2bn(&b, b_hex); + + group = EC_GROUP_new_curve_GFp(p, a, b, NULL); + BN_free(p); + BN_free(a); + BN_free(b); + + if (group == NULL) + return NULL; + + generator = EC_POINT_new(group); + if (generator == NULL) + return NULL; + + BN_hex2bn(&g_x, x_hex); + BN_hex2bn(&g_y, y_hex); + + if (EC_POINT_set_affine_coordinates(group, generator, g_x, g_y, + NULL) == 0) + return NULL; + + BN_free(g_x); + BN_free(g_y); + + BN_hex2bn(&order, order_hex); + BN_hex2bn(&cof, cof_hex); + + if (EC_GROUP_set_generator(group, generator, order, cof) == 0) + return NULL; + + EC_POINT_free(generator); + BN_free(order); + BN_free(cof); + + return group; +} + + +static int +test_sm2(const EC_GROUP *group, const char *userid, const char *privkey_hex, + const char *message) +{ + const size_t msg_len = strlen(message); + int ok = -1; + BIGNUM *priv = NULL; + EC_POINT *pt = NULL; + EC_KEY *key = NULL; + ECDSA_SIG *sig = NULL; + const BIGNUM *sig_r = NULL; + const BIGNUM *sig_s = NULL; + + BN_hex2bn(&priv, privkey_hex); + + key = EC_KEY_new(); + EC_KEY_set_group(key, group); + EC_KEY_set_private_key(key, priv); + + pt = EC_POINT_new(group); + EC_POINT_mul(group, pt, priv, NULL, NULL, NULL); + EC_KEY_set_public_key(key, pt); + + sig = sm2_do_sign(key, EVP_sm3(), userid, strlen(userid), + (const uint8_t *)message, msg_len); + + if (sig == NULL) + return 0; + + ECDSA_SIG_get0(sig, &sig_r, &sig_s); + + ok = sm2_do_verify(key, EVP_sm3(), sig, userid, strlen(userid), + (const uint8_t *)message, msg_len); + + ECDSA_SIG_free(sig); + EC_POINT_free(pt); + EC_KEY_free(key); + BN_free(priv); + + return ok; +} + +int +main(int argc, char **argv) +{ + int rc = 0; + /* From draft-shen-sm2-ecdsa-02 */ + EC_GROUP *test_group = + create_EC_group + ("8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", + "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", + "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", + "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", + "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2", + "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", + "1"); + + if (test_group == NULL) + return 1; + + rc = test_sm2(test_group, "ALICE123@YAHOO.COM", + "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263", + "message digest"); + + EC_GROUP_free(test_group); + + if (rc <= 0) + return 1; + + + printf("SUCCESS\n"); + + return 0; +} + +#endif diff --git a/tests/sm3test.c b/tests/sm3test.c new file mode 100644 index 0000000..f02ce3a --- /dev/null +++ b/tests/sm3test.c @@ -0,0 +1,99 @@ +/* $OpenBSD: sm3test.c,v 1.3 2021/04/06 15:00:19 tb Exp $ */ +/* + * Copyright (c) 2018 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#define SM3_TESTS 3 + +const char *sm3_input[SM3_TESTS] = { + "", + "abc", + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", +}; + +const uint8_t sm3_expected[SM3_TESTS][32] = { + { + 0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f, + 0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f, + 0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74, + 0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b, + }, + { + 0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9, + 0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2, + 0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2, + 0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0, + }, + { + 0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1, + 0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d, + 0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65, + 0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32, + }, +}; + +/* Tweaked version of libssl/key_schedule/key_schedule.c. */ +static void +hexdump(const uint8_t *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02x,%s", buf[i - 1], (i % 8) ? "" : "\n"); + + if (i % 8 != 1) + fprintf(stderr, "\n"); +} + +int +main(int argc, char *argv[]) +{ + EVP_MD_CTX *ctx; + uint8_t digest[32]; + int i; + int numerrors = 0; + + if ((ctx = EVP_MD_CTX_new()) == NULL) + err(1, NULL); + + for (i = 0; i < SM3_TESTS; i++) { + if (!EVP_DigestInit(ctx, EVP_sm3())) + errx(1, "EVP_DigestInit() failed"); + if (!EVP_DigestUpdate(ctx, sm3_input[i], strlen(sm3_input[i]))) + errx(1, "EVP_DigestInit() failed"); + if (!EVP_DigestFinal(ctx, digest, NULL)) + errx(1, "EVP_DigestFinal() failed"); + + if (memcmp(digest, sm3_expected[i], sizeof(digest)) != 0) { + fprintf(stderr, "TEST %d failed\n", i); + fprintf(stderr, "Produced:\n"); + hexdump(digest, sizeof(digest)); + fprintf(stderr, "Expected:\n"); + hexdump(sm3_expected[i], sizeof(sm3_expected[i])); + numerrors++; + } else + fprintf(stderr, "SM3 test %d ok\n", i); + } + + EVP_MD_CTX_free(ctx); + + return (numerrors > 0) ? 1 : 0; +} diff --git a/tests/sm4test.c b/tests/sm4test.c new file mode 100644 index 0000000..1bfdbb6 --- /dev/null +++ b/tests/sm4test.c @@ -0,0 +1,108 @@ +/* $OpenBSD: sm4test.c,v 1.1 2019/03/17 17:48:31 tb Exp $ */ +/* + * Copyright (c) 2017, 2019 Ribose Inc + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +static void +hexdump(FILE *fp, const char *title, const uint8_t *buf, size_t len) +{ + size_t i; + + fprintf(fp, "%s:\n", title); + for (i = 1; i <= len; i++) + fprintf(fp, " 0x%02x,%s", buf[i - 1], (i % 8) ? "" : "\n"); + + if (i % 8 != 1) + fprintf(fp, "\n"); +} + +int +main(int argc, char *argv[]) +{ + int i; + SM4_KEY key; + uint8_t block[SM4_BLOCK_SIZE]; + + static const uint8_t k[SM4_BLOCK_SIZE] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + + static const uint8_t input[SM4_BLOCK_SIZE] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 + }; + + /* + * This test vector comes from Example 1 of GB/T 32907-2016, + * and described in Internet Draft draft-ribose-cfrg-sm4-02. + */ + static const uint8_t expected[SM4_BLOCK_SIZE] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46 + }; + + /* + * This test vector comes from Example 2 from GB/T 32907-2016, + * and described in Internet Draft draft-ribose-cfrg-sm4-02. + * After 1,000,000 iterations. + */ + static const uint8_t expected_iter[SM4_BLOCK_SIZE] = { + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66 + }; + + if (!SM4_set_key(k, &key)) + errx(1, "SM4_set_key() failed"); + + memcpy(block, input, SM4_BLOCK_SIZE); + + SM4_encrypt(block, block, &key); + + if (memcmp(block, expected, SM4_BLOCK_SIZE) != 0) { + fprintf(stderr, "FAIL: Encryption failed\n"); + hexdump(stderr, "Got", block, SM4_BLOCK_SIZE); + hexdump(stderr, "Expected", expected, SM4_BLOCK_SIZE); + return 1; + } + + for (i = 0; i < 999999; i++) + SM4_encrypt(block, block, &key); + + if (memcmp(block, expected_iter, SM4_BLOCK_SIZE) != 0) { + fprintf(stderr, "FAIL: Multi-iteration encryption failed\n"); + hexdump(stderr, "Got", block, SM4_BLOCK_SIZE); + hexdump(stderr, "Expected", expected_iter, SM4_BLOCK_SIZE); + return 1; + } + + for (i = 0; i < 1000000; i++) + SM4_decrypt(block, block, &key); + + if (memcmp(block, input, SM4_BLOCK_SIZE) != 0) { + fprintf(stderr, "FAIL: Decrypted data does not match input\n"); + hexdump(stderr, "Got", block, SM4_BLOCK_SIZE); + hexdump(stderr, "Expected", input, SM4_BLOCK_SIZE); + return 1; + } + + return 0; +} diff --git a/tests/ssl_get_shared_ciphers.c b/tests/ssl_get_shared_ciphers.c new file mode 100644 index 0000000..33efc15 --- /dev/null +++ b/tests/ssl_get_shared_ciphers.c @@ -0,0 +1,482 @@ +/* $OpenBSD: ssl_get_shared_ciphers.c,v 1.11 2022/02/05 18:19:39 tb Exp $ */ +/* + * Copyright (c) 2021 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +struct peer_config { + const char *name; + int server; + uint16_t max_version; + uint16_t min_version; + const char *ciphers; +}; + +struct ssl_shared_ciphers_test_data { + const char *description; + struct peer_config client_config; + struct peer_config server_config; + const char *shared_ciphers; + const char *shared_ciphers_without_aesni; +}; + +char *server_cert; +char *server_key; + +static const struct ssl_shared_ciphers_test_data ssl_shared_ciphers_tests[] = { + { + .description = "TLSv1.3 defaults", + .client_config = { + .name = "client", + .server = 0, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_3_VERSION, + .ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256", + }, + .server_config = { + .name = "server", + .server = 1, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_3_VERSION, + .ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256", + }, + .shared_ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256", + }, + + { + .description = "TLSv1.3, client without ChaCha", + .client_config = { + .name = "client", + .server = 0, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_3_VERSION, + .ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_AES_128_GCM_SHA256", + }, + .server_config = { + .name = "server", + .server = 1, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_3_VERSION, + .ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256", + }, + .shared_ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_AES_128_GCM_SHA256", + }, + + { + .description = "TLSv1.2", + .client_config = { + .name = "client", + .server = 0, + .max_version = TLS1_2_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-ECDSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:" + "ECDHE-ECDSA-AES256-SHA", + }, + .server_config = { + .name = "server", + .server = 1, + .max_version = TLS1_2_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-ECDSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:" + "ECDHE-ECDSA-AES256-SHA", + }, + .shared_ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-ECDSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:" + "ECDHE-ECDSA-AES256-SHA", + }, + + { + .description = "TLSv1.2, server without ECDSA", + .client_config = { + .name = "client", + .server = 0, + .max_version = TLS1_2_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-ECDSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-ECDSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA:" + "ECDHE-ECDSA-AES256-SHA", + }, + .server_config = { + .name = "server", + .server = 1, + .max_version = TLS1_2_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA", + }, + .shared_ciphers = + "ECDHE-RSA-AES256-GCM-SHA384:" + "ECDHE-RSA-AES256-SHA384:" + "ECDHE-RSA-AES256-SHA", + }, + + { + .description = "TLSv1.3 ciphers are prepended", + .client_config = { + .name = "client", + .server = 0, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384", + }, + .server_config = { + .name = "server", + .server = 1, + .max_version = TLS1_3_VERSION, + .min_version = TLS1_2_VERSION, + .ciphers = + "ECDHE-RSA-AES256-GCM-SHA384", + }, + .shared_ciphers = + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_GCM_SHA256:" + "ECDHE-RSA-AES256-GCM-SHA384", + .shared_ciphers_without_aesni = + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_256_GCM_SHA384:" + "TLS_AES_128_GCM_SHA256:" + "ECDHE-RSA-AES256-GCM-SHA384", + }, +}; + +static const size_t N_SHARED_CIPHERS_TESTS = + sizeof(ssl_shared_ciphers_tests) / sizeof(ssl_shared_ciphers_tests[0]); + +static SSL_CTX * +peer_config_to_ssl_ctx(const struct peer_config *config) +{ + SSL_CTX *ctx; + + if ((ctx = SSL_CTX_new(TLS_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new(%s) failed\n", config->name); + goto err; + } + if (!SSL_CTX_set_max_proto_version(ctx, config->max_version)) { + fprintf(stderr, "max_proto_version(%s) failed\n", config->name); + goto err; + } + if (!SSL_CTX_set_min_proto_version(ctx, config->min_version)) { + fprintf(stderr, "min_proto_version(%s) failed\n", config->name); + goto err; + } + if (!SSL_CTX_set_cipher_list(ctx, config->ciphers)) { + fprintf(stderr, "set_cipher_list(%s) failed\n", config->name); + goto err; + } + + if (config->server) { + if (!SSL_CTX_use_certificate_file(ctx, server_cert, + SSL_FILETYPE_PEM)) { + fprintf(stderr, "use_certificate_file(%s) failed\n", + config->name); + goto err; + } + if (!SSL_CTX_use_PrivateKey_file(ctx, server_key, + SSL_FILETYPE_PEM)) { + fprintf(stderr, "use_PrivateKey_file(%s) failed\n", + config->name); + goto err; + } + } + + return ctx; + + err: + SSL_CTX_free(ctx); + return NULL; +} + +/* Connect client and server via a pair of "nonblocking" memory BIOs. */ +static int +connect_peers(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + BIO *client_wbio = NULL, *server_wbio = NULL; + int ret = 0; + + if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "%s: failed to create client BIO\n", + description); + goto err; + } + if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "%s: failed to create server BIO\n", + description); + goto err; + } + if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) { + fprintf(stderr, "%s: failed to set client eof return\n", + description); + goto err; + } + if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) { + fprintf(stderr, "%s: failed to set server eof return\n", + description); + goto err; + } + + /* Avoid double free. SSL_set_bio() takes ownership of the BIOs. */ + BIO_up_ref(client_wbio); + BIO_up_ref(server_wbio); + + SSL_set_bio(client_ssl, server_wbio, client_wbio); + SSL_set_bio(server_ssl, client_wbio, server_wbio); + client_wbio = NULL; + server_wbio = NULL; + + ret = 1; + + err: + BIO_free(client_wbio); + BIO_free(server_wbio); + + return ret; +} + +static int +push_data_to_peer(SSL *ssl, int *ret, int (*func)(SSL *), const char *func_name, + const char *description) +{ + int ssl_err = 0; + + if (*ret == 1) + return 1; + + /* + * Do SSL_connect/SSL_accept/SSL_shutdown once and loop while hitting + * WANT_WRITE. If done or on WANT_READ hand off to peer. + */ + + do { + if ((*ret = func(ssl)) <= 0) + ssl_err = SSL_get_error(ssl, *ret); + } while (*ret <= 0 && ssl_err == SSL_ERROR_WANT_WRITE); + + /* Ignore erroneous error - see SSL_shutdown(3)... */ + if (func == SSL_shutdown && ssl_err == SSL_ERROR_SYSCALL) + return 1; + + if (*ret <= 0 && ssl_err != SSL_ERROR_WANT_READ) { + fprintf(stderr, "%s: %s failed\n", description, func_name); + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} + +/* + * Alternate between loops of SSL_connect() and SSL_accept() as long as only + * WANT_READ and WANT_WRITE situations are encountered. A function is repeated + * until WANT_READ is returned or it succeeds, then it's the other function's + * turn to make progress. Succeeds if SSL_connect() and SSL_accept() return 1. + */ +static int +handshake(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + int loops = 0, client_ret = 0, server_ret = 0; + + while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) { + if (!push_data_to_peer(client_ssl, &client_ret, SSL_connect, + "SSL_connect", description)) + return 0; + + if (!push_data_to_peer(server_ssl, &server_ret, SSL_accept, + "SSL_accept", description)) + return 0; + } + + if (client_ret != 1 || server_ret != 1) { + fprintf(stderr, "%s: failed\n", __func__); + return 0; + } + + return 1; +} + +static int +shutdown_peers(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + int loops = 0, client_ret = 0, server_ret = 0; + + while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) { + if (!push_data_to_peer(client_ssl, &client_ret, SSL_shutdown, + "client shutdown", description)) + return 0; + + if (!push_data_to_peer(server_ssl, &server_ret, SSL_shutdown, + "server shutdown", description)) + return 0; + } + + if (client_ret != 1 || server_ret != 1) { + fprintf(stderr, "%s: failed\n", __func__); + return 0; + } + + return 1; +} + +/* from ssl_ciph.c */ +static inline int +ssl_aes_is_accelerated(void) +{ +#if defined(__i386__) || defined(__x86_64__) + return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0); +#else + return (0); +#endif +} + +static int +check_shared_ciphers(const struct ssl_shared_ciphers_test_data *test, + const char *got) +{ + const char *want = test->shared_ciphers; + int failed; + + if (!ssl_aes_is_accelerated() && + test->shared_ciphers_without_aesni != NULL) + want = test->shared_ciphers_without_aesni; + + failed = strcmp(want, got); + + if (failed) + fprintf(stderr, "%s: want \"%s\", got \"%s\"\n", + test->description, want, got); + + return failed; +} + +static int +test_get_shared_ciphers(const struct ssl_shared_ciphers_test_data *test) +{ + SSL_CTX *client_ctx = NULL, *server_ctx = NULL; + SSL *client_ssl = NULL, *server_ssl = NULL; + char buf[4096]; + int failed = 1; + + if ((client_ctx = peer_config_to_ssl_ctx(&test->client_config)) == NULL) + goto err; + if ((server_ctx = peer_config_to_ssl_ctx(&test->server_config)) == NULL) + goto err; + + if ((client_ssl = SSL_new(client_ctx)) == NULL) { + fprintf(stderr, "%s: failed to create client SSL\n", + test->description); + goto err; + } + if ((server_ssl = SSL_new(server_ctx)) == NULL) { + fprintf(stderr, "%s: failed to create server SSL\n", + test->description); + goto err; + } + + if (!connect_peers(client_ssl, server_ssl, test->description)) + goto err; + + if (!handshake(client_ssl, server_ssl, test->description)) + goto err; + + if (SSL_get_shared_ciphers(server_ssl, buf, sizeof(buf)) == NULL) { + fprintf(stderr, "%s: failed to get shared ciphers\n", + test->description); + goto err; + } + + if (!shutdown_peers(client_ssl, server_ssl, test->description)) + goto err; + + failed = check_shared_ciphers(test, buf); + + err: + SSL_CTX_free(client_ctx); + SSL_CTX_free(server_ctx); + SSL_free(client_ssl); + SSL_free(server_ssl); + + return failed; +} + +int +main(int argc, char **argv) +{ + size_t i; + int failed = 0; + + if (asprintf(&server_cert, "%s/server.pem", CERTSDIR) == -1) { + fprintf(stderr, "asprintf server_cert failed\n"); + failed = 1; + goto err; + } + server_key = server_cert; + + for (i = 0; i < N_SHARED_CIPHERS_TESTS; i++) + failed |= test_get_shared_ciphers(&ssl_shared_ciphers_tests[i]); + + if (failed == 0) + printf("PASS %s\n", __FILE__); + + err: + free(server_cert); + + return failed; +} diff --git a/tests/ssl_methods.c b/tests/ssl_methods.c new file mode 100644 index 0000000..0fc33a4 --- /dev/null +++ b/tests/ssl_methods.c @@ -0,0 +1,267 @@ +/* $OpenBSD: ssl_methods.c,v 1.4 2021/04/04 20:21:43 tb Exp $ */ +/* + * Copyright (c) 2020 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +struct ssl_method_test_data { + const SSL_METHOD *(*method)(void); + const char *name; + int server; + int dtls; +}; + +struct ssl_method_test_data ssl_method_tests[] = { + { + .method = SSLv23_method, + .name = "SSLv23_method", + .server = 1, + .dtls = 0, + }, + { + .method = SSLv23_server_method, + .name = "SSLv23_server_method", + .server = 1, + .dtls = 0, + }, + { + .method = SSLv23_client_method, + .name = "SSLv23_client_method", + .server = 0, + .dtls = 0, + }, + + { + .method = TLSv1_method, + .name = "TLSv1_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_server_method, + .name = "TLSv1_server_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_client_method, + .name = "TLSv1_client_method", + .server = 0, + .dtls = 0, + }, + + { + .method = TLSv1_1_method, + .name = "TLSv1_1_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_1_server_method, + .name = "TLSv1_1_server_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_1_client_method, + .name = "TLSv1_1_client_method", + .server = 0, + .dtls = 0, + }, + + { + .method = TLSv1_2_method, + .name = "TLSv1_2_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_2_server_method, + .name = "TLSv1_2_server_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLSv1_2_client_method, + .name = "TLSv1_2_client_method", + .server = 0, + .dtls = 0, + }, + + { + .method = TLS_method, + .name = "TLS_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLS_server_method, + .name = "TLS_server_method", + .server = 1, + .dtls = 0, + }, + { + .method = TLS_client_method, + .name = "TLS_client_method", + .server = 0, + .dtls = 0, + }, + + { + .method = DTLSv1_method, + .name = "DTLSv1_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLSv1_server_method, + .name = "DTLSv1_server_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLSv1_client_method, + .name = "DTLSv1_client_method", + .server = 0, + .dtls = 1, + }, + + { + .method = DTLSv1_2_method, + .name = "DTLSv1_2_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLSv1_2_server_method, + .name = "DTLSv1_2_server_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLSv1_2_client_method, + .name = "DTLSv1_2_client_method", + .server = 0, + .dtls = 1, + }, + + { + .method = DTLS_method, + .name = "DTLS_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLS_server_method, + .name = "DTLS_server_method", + .server = 1, + .dtls = 1, + }, + { + .method = DTLS_client_method, + .name = "DTLS_client_method", + .server = 0, + .dtls = 1, + }, +}; + +#define N_METHOD_TESTS (sizeof(ssl_method_tests) / sizeof(ssl_method_tests[0])) + +int test_client_or_server_method(struct ssl_method_test_data *); +int test_dtls_method(struct ssl_method_test_data *); + +int +test_client_or_server_method(struct ssl_method_test_data *testcase) +{ + SSL_CTX *ssl_ctx; + SSL *ssl = NULL; + int failed = 1; + + if ((ssl_ctx = SSL_CTX_new(testcase->method())) == NULL) { + fprintf(stderr, "SSL_CTX_new returned NULL\n"); + goto err; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new returned NULL\n"); + goto err; + } + + if (SSL_is_server(ssl) != testcase->server) { + fprintf(stderr, "%s: SSL_is_server: want %d, got %d\n", + testcase->name, testcase->server, SSL_is_server(ssl)); + goto err; + } + + failed = 0; + + err: + SSL_free(ssl); + SSL_CTX_free(ssl_ctx); + + return failed; +} + +int +test_dtls_method(struct ssl_method_test_data *testcase) +{ + SSL_CTX *ssl_ctx; + SSL *ssl = NULL; + int failed = 1; + + if ((ssl_ctx = SSL_CTX_new(testcase->method())) == NULL) { + fprintf(stderr, "SSL_CTX_new returned NULL\n"); + goto err; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new returned NULL\n"); + goto err; + } + + if (SSL_is_dtls(ssl) != testcase->dtls) { + fprintf(stderr, "%s: SSL_is_dtls: want %d, got %d\n", + testcase->name, testcase->dtls, SSL_is_dtls(ssl)); + goto err; + } + + failed = 0; + + err: + SSL_free(ssl); + SSL_CTX_free(ssl_ctx); + + return failed; +} + +int +main(int argc, char **argv) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_METHOD_TESTS; i++) { + failed |= test_client_or_server_method(&ssl_method_tests[i]); + failed |= test_dtls_method(&ssl_method_tests[i]); + } + + if (failed == 0) + printf("PASS %s\n", __FILE__); + + return failed; +} diff --git a/tests/ssl_set_alpn_protos.c b/tests/ssl_set_alpn_protos.c new file mode 100644 index 0000000..87dd4d9 --- /dev/null +++ b/tests/ssl_set_alpn_protos.c @@ -0,0 +1,204 @@ +/* $OpenBSD: ssl_set_alpn_protos.c,v 1.2 2022/07/21 03:59:04 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +struct alpn_test { + const char *description; + const uint8_t protocols[24]; + size_t protocols_len; + int ret; +}; + +static const struct alpn_test alpn_tests[] = { + { + .description = "valid protocol list", + .protocols = { + 6, 's', 'p', 'd', 'y', '/', '1', + 8, 'h', 't', 't', 'p', '/', '1', '.', '1', + }, + .protocols_len = 16, + .ret = 0, + }, + { + .description = "zero length protocol", + .protocols = { + 0, + }, + .protocols_len = 1, + .ret = 1, + }, + { + .description = "zero length protocol at start", + .protocols = { + 0, + 8, 'h', 't', 't', 'p', '/', '1', '.', '1', + 6, 's', 'p', 'd', 'y', '/', '1', + }, + .protocols_len = 17, + .ret = 1, + }, + { + .description = "zero length protocol embedded", + .protocols = { + 8, 'h', 't', 't', 'p', '/', '1', '.', '1', + 0, + 6, 's', 'p', 'd', 'y', '/', '1', + }, + .protocols_len = 17, + .ret = 1, + }, + { + .description = "zero length protocol at end", + .protocols = { + 8, 'h', 't', 't', 'p', '/', '1', '.', '1', + 6, 's', 'p', 'd', 'y', '/', '1', + 0, + }, + .protocols_len = 17, + .ret = 1, + }, + { + .description = "protocol length too short", + .protocols = { + 6, 'h', 't', 't', 'p', '/', '1', '.', '1', + }, + .protocols_len = 9, + .ret = 1, + }, + { + .description = "protocol length too long", + .protocols = { + 8, 's', 'p', 'd', 'y', '/', '1', + }, + .protocols_len = 7, + .ret = 1, + }, +}; + +static const size_t N_ALPN_TESTS = sizeof(alpn_tests) / sizeof(alpn_tests[0]); + +static int +test_ssl_set_alpn_protos(const struct alpn_test *tc) +{ + SSL_CTX *ctx; + SSL *ssl; + int ret; + int failed = 0; + + if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "SSL_CTX_new"); + + ret = SSL_CTX_set_alpn_protos(ctx, tc->protocols, tc->protocols_len); + if (ret != tc->ret) { + warnx("%s: setting on SSL_CTX: want %d, got %d", + tc->description, tc->ret, ret); + failed = 1; + } + + if ((ssl = SSL_new(ctx)) == NULL) + errx(1, "SSL_new"); + + ret = SSL_set_alpn_protos(ssl, tc->protocols, tc->protocols_len); + if (ret != tc->ret) { + warnx("%s: setting on SSL: want %d, got %d", + tc->description, tc->ret, ret); + failed = 1; + } + + SSL_CTX_free(ctx); + SSL_free(ssl); + + return failed; +} + +static int +test_ssl_set_alpn_protos_edge_cases(void) +{ + SSL_CTX *ctx; + SSL *ssl; + const uint8_t valid[] = { + 6, 's', 'p', 'd', 'y', '/', '3', + 8, 'h', 't', 't', 'p', '/', '1', '.', '1', + }; + int failed = 0; + + if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "SSL_CTX_new"); + + if (SSL_CTX_set_alpn_protos(ctx, valid, sizeof(valid)) != 0) { + warnx("setting valid protocols on SSL_CTX failed"); + failed = 1; + } + if (SSL_CTX_set_alpn_protos(ctx, NULL, 0) != 0) { + warnx("setting 'NULL, 0' on SSL_CTX failed"); + failed = 1; + } + if (SSL_CTX_set_alpn_protos(ctx, valid, 0) != 0) { + warnx("setting 'valid, 0' on SSL_CTX failed"); + failed = 1; + } + if (SSL_CTX_set_alpn_protos(ctx, NULL, 43) != 0) { + warnx("setting 'NULL, 43' on SSL_CTX failed"); + failed = 1; + } + + if ((ssl = SSL_new(ctx)) == NULL) + errx(1, "SSL_new"); + + if (SSL_set_alpn_protos(ssl, valid, sizeof(valid)) != 0) { + warnx("setting valid protocols on SSL failed"); + failed = 1; + } + if (SSL_set_alpn_protos(ssl, NULL, 0) != 0) { + warnx("setting 'NULL, 0' on SSL failed"); + failed = 1; + } + if (SSL_set_alpn_protos(ssl, valid, 0) != 0) { + warnx("setting 'valid, 0' on SSL failed"); + failed = 1; + } + if (SSL_set_alpn_protos(ssl, NULL, 43) != 0) { + warnx("setting 'NULL, 43' on SSL failed"); + failed = 1; + } + + SSL_CTX_free(ctx); + SSL_free(ssl); + + return failed; +} + +int +main(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_ALPN_TESTS; i++) + failed |= test_ssl_set_alpn_protos(&alpn_tests[i]); + + failed |= test_ssl_set_alpn_protos_edge_cases(); + + if (!failed) + printf("PASS %s\n", __FILE__); + + return failed; +} diff --git a/tests/ssl_verify_param.c b/tests/ssl_verify_param.c new file mode 100644 index 0000000..cdb52c5 --- /dev/null +++ b/tests/ssl_verify_param.c @@ -0,0 +1,99 @@ +/* $OpenBSD: ssl_verify_param.c,v 1.1 2023/05/24 08:54:59 tb Exp $ */ + +/* + * Copyright (c) 2023 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +unsigned int X509_VERIFY_PARAM_get_hostflags(X509_VERIFY_PARAM *param); + +static int +ssl_verify_param_flags_inherited(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + X509_VERIFY_PARAM *param; + unsigned int defaultflags = 0; + unsigned int newflags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; + unsigned int flags; + int failed = 1; + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) + errx(1, "SSL_CTX_new"); + + if ((param = SSL_CTX_get0_param(ssl_ctx)) == NULL) { + fprintf(stderr, "FAIL: no verify param on ssl_ctx\n"); + goto failure; + } + + if ((flags = X509_VERIFY_PARAM_get_hostflags(param)) != defaultflags) { + fprintf(stderr, "FAIL: SSL_CTX default hostflags, " + "want: %x, got: %x\n", defaultflags, flags); + goto failure; + } + + X509_VERIFY_PARAM_set_hostflags(param, newflags); + + if ((flags = X509_VERIFY_PARAM_get_hostflags(param)) != newflags) { + fprintf(stderr, "FAIL: SSL_CTX new hostflags, " + "want: %x, got: %x\n", newflags, flags); + goto failure; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "SSL_new"); + + if ((param = SSL_get0_param(ssl)) == NULL) { + fprintf(stderr, "FAIL: no verify param on ssl\n"); + goto failure; + } + + if ((flags = X509_VERIFY_PARAM_get_hostflags(param)) != newflags) { + fprintf(stderr, "FAIL: SSL inherited hostflags, " + "want: %x, got: %x\n", newflags, flags); + goto failure; + } + + SSL_set_hostflags(ssl, defaultflags); + + if ((flags = X509_VERIFY_PARAM_get_hostflags(param)) != defaultflags) { + fprintf(stderr, "FAIL: SSL set hostflags, " + "want: %x, got: %x\n", defaultflags, flags); + goto failure; + } + + failed = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= ssl_verify_param_flags_inherited(); + + return failed; +} diff --git a/tests/ssl_versions.c b/tests/ssl_versions.c new file mode 100644 index 0000000..ebfe8d2 --- /dev/null +++ b/tests/ssl_versions.c @@ -0,0 +1,922 @@ +/* $OpenBSD: ssl_versions.c,v 1.20 2023/07/02 17:21:33 beck Exp $ */ +/* + * Copyright (c) 2016, 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" + +struct version_range_test { + const long options; + const uint16_t minver; + const uint16_t maxver; + const uint16_t want_minver; + const uint16_t want_maxver; +}; + +static struct version_range_test version_range_tests[] = { + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1_3, + .minver = TLS1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = SSL_OP_NO_TLSv1_1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_3_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3, + .minver = TLS1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = 0, + .minver = TLS1_2_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = 0, + .minver = TLS1_2_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = 0, + .minver = TLS1_3_VERSION, + .maxver = TLS1_3_VERSION, + .want_minver = TLS1_3_VERSION, + .want_maxver = TLS1_3_VERSION, + }, + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_1_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, + { + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_VERSION, + .want_minver = 0, + .want_maxver = 0, + }, +}; + +#define N_VERSION_RANGE_TESTS \ + (sizeof(version_range_tests) / sizeof(*version_range_tests)) + +static int +test_ssl_enabled_version_range(void) +{ + struct version_range_test *vrt; + uint16_t minver, maxver; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failed = 1; + size_t i; + + fprintf(stderr, "INFO: starting enabled version range tests...\n"); + + if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + + failed = 0; + + for (i = 0; i < N_VERSION_RANGE_TESTS; i++) { + vrt = &version_range_tests[i]; + + SSL_clear_options(ssl, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); + SSL_set_options(ssl, vrt->options); + + minver = maxver = 0xffff; + ssl->min_tls_version = vrt->minver; + ssl->max_tls_version = vrt->maxver; + + if (ssl_enabled_tls_version_range(ssl, &minver, &maxver) != 1) { + if (vrt->want_minver != 0 || vrt->want_maxver != 0) { + fprintf(stderr, "FAIL: test %zu - failed but " + "wanted non-zero versions\n", i); + failed++; + } + continue; + } + if (minver != vrt->want_minver) { + fprintf(stderr, "FAIL: test %zu - got minver %x, " + "want %x\n", i, minver, vrt->want_minver); + failed++; + } + if (maxver != vrt->want_maxver) { + fprintf(stderr, "FAIL: test %zu - got maxver %x, " + "want %x\n", i, maxver, vrt->want_maxver); + failed++; + } + } + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (failed); +} + +struct shared_version_test { + const SSL_METHOD *(*ssl_method)(void); + const long options; + const uint16_t minver; + const uint16_t maxver; + const uint16_t peerver; + const uint16_t want_maxver; +}; + +static struct shared_version_test shared_version_tests[] = { + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = SSL2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = SSL3_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_3_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = 0x7f12, + .want_maxver = TLS1_2_VERSION, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = SSL_OP_NO_TLSv1, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_1_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLSv1_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLSv1_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLSv1_1_method, + .options = 0, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_2_VERSION, + .want_maxver = DTLS1_2_VERSION, + }, + { + .ssl_method = DTLS_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = 0xfefc, /* DTLSv1.3, probably. */ + .want_maxver = DTLS1_2_VERSION, + }, + { + .ssl_method = DTLSv1_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_1_VERSION, + .peerver = DTLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLSv1_2_method, + .options = 0, + .minver = TLS1_2_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_2_VERSION, + .want_maxver = DTLS1_2_VERSION, + }, + { + .ssl_method = DTLSv1_method, + .options = 0, + .minver = TLS1_1_VERSION, + .maxver = TLS1_1_VERSION, + .peerver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .options = SSL_OP_NO_DTLSv1, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .options = SSL_OP_NO_DTLSv1, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_2_VERSION, + .want_maxver = DTLS1_2_VERSION, + }, + { + .ssl_method = DTLS_method, + .options = SSL_OP_NO_DTLSv1_2, + .minver = TLS1_1_VERSION, + .maxver = TLS1_2_VERSION, + .peerver = DTLS1_2_VERSION, + .want_maxver = 0, + }, +}; + +#define N_SHARED_VERSION_TESTS \ + (sizeof(shared_version_tests) / sizeof(*shared_version_tests)) + +static int +test_ssl_max_shared_version(void) +{ + struct shared_version_test *svt; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + uint16_t maxver; + int failed = 0; + size_t i; + + failed = 0; + + fprintf(stderr, "INFO: starting max shared version tests...\n"); + + for (i = 0; i < N_SHARED_VERSION_TESTS; i++) { + svt = &shared_version_tests[i]; + + if ((ssl_ctx = SSL_CTX_new(svt->ssl_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + failed++; + goto err; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + failed++; + goto err; + } + + SSL_clear_options(ssl, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | + SSL_OP_NO_TLSv1_2 | SSL_OP_NO_TLSv1_3); + SSL_set_options(ssl, svt->options); + + maxver = 0; + ssl->min_tls_version = svt->minver; + ssl->max_tls_version = svt->maxver; + + if (!ssl_max_shared_version(ssl, svt->peerver, &maxver)) { + if (svt->want_maxver != 0) { + fprintf(stderr, "FAIL: test %zu - failed but " + "wanted non-zero shared version (peer %x)\n", + i, svt->peerver); + failed++; + } + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + ssl_ctx = NULL; + ssl = NULL; + continue; + } + if (maxver != svt->want_maxver) { + fprintf(stderr, "FAIL: test %zu - got shared " + "version %x, want %x\n", i, maxver, + svt->want_maxver); + failed++; + } + + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + ssl_ctx = NULL; + ssl = NULL; + } + + err: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (failed); +} + +struct min_max_version_test { + const SSL_METHOD *(*ssl_method)(void); + const uint16_t minver; + const uint16_t maxver; + const uint16_t want_minver; + const uint16_t want_maxver; + const int want_min_fail; + const int want_max_fail; +}; + +static struct min_max_version_test min_max_version_tests[] = { + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = 0, + .want_minver = 0, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .minver = TLS1_VERSION, + .maxver = 0, + .want_minver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = TLS1_2_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = TLS1_3_VERSION, + .want_minver = 0, + .want_maxver = TLS1_3_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_VERSION, + .want_maxver = TLS1_2_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = TLS1_1_VERSION, + .maxver = 0, + .want_minver = TLS1_1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .minver = TLS1_2_VERSION, + .maxver = 0, + .want_minver = TLS1_2_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .minver = 0x0300, + .maxver = 0, + .want_minver = TLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = TLS_method, + .minver = 0x0305, + .maxver = 0, + .want_min_fail = 1, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = 0x0305, + .want_minver = 0, + .want_maxver = TLS1_3_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = TLS1_1_VERSION, + .want_minver = 0, + .want_maxver = TLS1_1_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = TLS1_VERSION, + .want_minver = 0, + .want_maxver = TLS1_VERSION, + }, + { + .ssl_method = TLS_method, + .minver = 0, + .maxver = 0x0300, + .want_max_fail = 1, + }, + { + .ssl_method = TLS_method, + .minver = TLS1_2_VERSION, + .maxver = TLS1_1_VERSION, + .want_minver = TLS1_2_VERSION, + .want_maxver = 0, + .want_max_fail = 1, + }, + { + .ssl_method = TLSv1_1_method, + .minver = 0, + .maxver = 0, + .want_minver = 0, + .want_maxver = 0, + }, + { + .ssl_method = TLSv1_1_method, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = TLS1_1_VERSION, + .want_maxver = TLS1_1_VERSION, + }, + { + .ssl_method = TLSv1_1_method, + .minver = TLS1_2_VERSION, + .maxver = 0, + .want_minver = 0, + .want_maxver = 0, + .want_min_fail = 1, + }, + { + .ssl_method = TLSv1_1_method, + .minver = 0, + .maxver = TLS1_VERSION, + .want_minver = 0, + .want_maxver = 0, + .want_max_fail = 1, + }, + { + .ssl_method = DTLS_method, + .minver = 0, + .maxver = 0, + .want_minver = 0, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .minver = 0, + .maxver = DTLS1_VERSION, + .want_minver = 0, + .want_maxver = DTLS1_VERSION, + }, + { + .ssl_method = DTLS_method, + .minver = DTLS1_VERSION, + .maxver = 0, + .want_minver = DTLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLS_method, + .minver = DTLS1_VERSION, + .maxver = DTLS1_2_VERSION, + .want_minver = DTLS1_VERSION, + .want_maxver = DTLS1_2_VERSION, + }, + { + .ssl_method = DTLSv1_method, + .minver = 0, + .maxver = 0, + .want_minver = 0, + .want_maxver = 0, + }, + { + .ssl_method = DTLSv1_method, + .minver = DTLS1_VERSION, + .maxver = 0, + .want_minver = DTLS1_VERSION, + .want_maxver = 0, + }, + { + .ssl_method = DTLSv1_method, + .minver = 0, + .maxver = DTLS1_VERSION, + .want_minver = 0, + .want_maxver = DTLS1_VERSION, + }, + { + .ssl_method = DTLSv1_method, + .minver = 0, + .maxver = DTLS1_2_VERSION, + .want_minver = 0, + .want_maxver = DTLS1_VERSION, + }, + { + .ssl_method = DTLSv1_method, + .minver = TLS1_VERSION, + .maxver = TLS1_2_VERSION, + .want_minver = 0, + .want_maxver = 0, + .want_min_fail = 1, + .want_max_fail = 1, + }, +}; + +#define N_MIN_MAX_VERSION_TESTS \ + (sizeof(min_max_version_tests) / sizeof(*min_max_version_tests)) + +static int +test_ssl_min_max_version(void) +{ + struct min_max_version_test *mmvt; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failed = 0; + size_t i; + + failed = 0; + + fprintf(stderr, "INFO: starting min max version tests...\n"); + + for (i = 0; i < N_MIN_MAX_VERSION_TESTS; i++) { + mmvt = &min_max_version_tests[i]; + + if ((ssl_ctx = SSL_CTX_new(mmvt->ssl_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + return 1; + } + + if (!SSL_CTX_set_min_proto_version(ssl_ctx, mmvt->minver)) { + if (!mmvt->want_min_fail) { + fprintf(stderr, "FAIL: test %zu - failed to set " + "SSL_CTX min version\n", i); + failed++; + } + goto next; + } + if (!SSL_CTX_set_max_proto_version(ssl_ctx, mmvt->maxver)) { + if (!mmvt->want_max_fail) { + fprintf(stderr, "FAIL: test %zu - failed to set " + "SSL_CTX min version\n", i); + failed++; + } + goto next; + } + + if (mmvt->want_min_fail) { + fprintf(stderr, "FAIL: test %zu - successfully set " + "SSL_CTX min version, should have failed\n", i); + failed++; + goto next; + } + if (mmvt->want_max_fail) { + fprintf(stderr, "FAIL: test %zu - successfully set " + "SSL_CTX max version, should have failed\n", i); + failed++; + goto next; + } + + if (SSL_CTX_get_min_proto_version(ssl_ctx) != mmvt->want_minver) { + fprintf(stderr, "FAIL: test %zu - got SSL_CTX min " + "version 0x%x, want 0x%x\n", i, + SSL_CTX_get_min_proto_version(ssl_ctx), mmvt->want_minver); + failed++; + goto next; + } + if (SSL_CTX_get_max_proto_version(ssl_ctx) != mmvt->want_maxver) { + fprintf(stderr, "FAIL: test %zu - got SSL_CTX max " + "version 0x%x, want 0x%x\n", i, + SSL_CTX_get_max_proto_version(ssl_ctx), mmvt->want_maxver); + failed++; + goto next; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + return 1; + } + + if (SSL_get_min_proto_version(ssl) != mmvt->want_minver) { + fprintf(stderr, "FAIL: test %zu - initial SSL min " + "version 0x%x, want 0x%x\n", i, + SSL_get_min_proto_version(ssl), mmvt->want_minver); + failed++; + goto next; + } + if (SSL_get_max_proto_version(ssl) != mmvt->want_maxver) { + fprintf(stderr, "FAIL: test %zu - initial SSL max " + "version 0x%x, want 0x%x\n", i, + SSL_get_max_proto_version(ssl), mmvt->want_maxver); + failed++; + goto next; + } + + if (!SSL_set_min_proto_version(ssl, mmvt->minver)) { + if (mmvt->want_min_fail) { + fprintf(stderr, "FAIL: test %zu - failed to set " + "SSL min version\n", i); + failed++; + } + goto next; + } + if (!SSL_set_max_proto_version(ssl, mmvt->maxver)) { + if (mmvt->want_max_fail) { + fprintf(stderr, "FAIL: test %zu - failed to set " + "SSL min version\n", i); + failed++; + } + goto next; + } + + if (mmvt->want_min_fail) { + fprintf(stderr, "FAIL: test %zu - successfully set SSL " + "min version, should have failed\n", i); + failed++; + goto next; + } + if (mmvt->want_max_fail) { + fprintf(stderr, "FAIL: test %zu - successfully set SSL " + "max version, should have failed\n", i); + failed++; + goto next; + } + + if (SSL_get_min_proto_version(ssl) != mmvt->want_minver) { + fprintf(stderr, "FAIL: test %zu - got SSL min " + "version 0x%x, want 0x%x\n", i, + SSL_get_min_proto_version(ssl), mmvt->want_minver); + failed++; + goto next; + } + if (SSL_get_max_proto_version(ssl) != mmvt->want_maxver) { + fprintf(stderr, "FAIL: test %zu - got SSL max " + "version 0x%x, want 0x%x\n", i, + SSL_get_max_proto_version(ssl), mmvt->want_maxver); + failed++; + goto next; + } + + next: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + ssl_ctx = NULL; + ssl = NULL; + } + + return (failed); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + SSL_library_init(); + + /* XXX - Test ssl_supported_version_range() */ + + failed |= test_ssl_enabled_version_range(); + failed |= test_ssl_max_shared_version(); + failed |= test_ssl_min_max_version(); + + if (failed == 0) + printf("PASS %s\n", __FILE__); + + return (failed); +} diff --git a/tests/ssltest.c b/tests/ssltest.c new file mode 100644 index 0000000..f95ea44 --- /dev/null +++ b/tests/ssltest.c @@ -0,0 +1,1535 @@ +/* $OpenBSD: ssltest.c,v 1.43 2023/08/15 11:20:57 tb Exp $ */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* ==================================================================== + * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. + * ECC cipher suite support in OpenSSL originally developed by + * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. + */ +/* ==================================================================== + * Copyright 2005 Nokia. All rights reserved. + * + * The portions of the attached software ("Contribution") is developed by + * Nokia Corporation and is licensed pursuant to the OpenSSL open source + * license. + * + * The Contribution, originally written by Mika Kousa and Pasi Eronen of + * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites + * support (see RFC 4279) to OpenSSL. + * + * No patent licenses or other rights except those expressly stated in + * the OpenSSL open source license shall be deemed granted or received + * expressly, by implication, estoppel, or otherwise. + * + * No assurances are provided by Nokia that the Contribution does not + * infringe the patent or other intellectual property rights of any third + * party or that the license provides you with all the necessary rights + * to make use of the Contribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN + * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA + * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY + * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR + * OTHERWISE. + */ + +/* XXX - USE_BIOPAIR code needs updating for BIO_n{read,write}{,0} removal. */ +/* #define USE_BIOPAIR */ + +#define _BSD_SOURCE 1 /* Or gethostname won't be declared properly + on Linux and GNU platforms. */ +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_ENGINE +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "ssl_local.h" + +#define TEST_SERVER_CERT "../apps/server.pem" +#define TEST_CLIENT_CERT "../apps/client.pem" + +static int verify_callback(int ok, X509_STORE_CTX *ctx); +static int app_verify_callback(X509_STORE_CTX *ctx, void *arg); + +static DH *get_dh1024(void); +static DH *get_dh1024dsa(void); + +static BIO *bio_err = NULL; +static BIO *bio_stdout = NULL; + +static const char *alpn_client; +static const char *alpn_server; +static const char *alpn_expected; +static unsigned char *alpn_selected; + +/* + * next_protos_parse parses a comma separated list of strings into a string + * in a format suitable for passing to SSL_CTX_set_next_protos_advertised. + * outlen: (output) set to the length of the resulting buffer on success. + * err: (maybe NULL) on failure, an error message line is written to this BIO. + * in: a NUL terminated string like "abc,def,ghi" + * + * returns: a malloced buffer or NULL on failure. + */ +static unsigned char * +next_protos_parse(unsigned short *outlen, const char *in) +{ + size_t i, len, start = 0; + unsigned char *out; + + len = strlen(in); + if (len >= 65535) + return (NULL); + + if ((out = malloc(strlen(in) + 1)) == NULL) + return (NULL); + + for (i = 0; i <= len; ++i) { + if (i == len || in[i] == ',') { + if (i - start > 255) { + free(out); + return (NULL); + } + out[start] = i - start; + start = i + 1; + } else + out[i+1] = in[i]; + } + *outlen = len + 1; + return (out); +} + +static int +cb_server_alpn(SSL *s, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + unsigned char *protos; + unsigned short protos_len; + + if ((protos = next_protos_parse(&protos_len, alpn_server)) == NULL) { + fprintf(stderr, + "failed to parser ALPN server protocol string: %s\n", + alpn_server); + abort(); + } + + if (SSL_select_next_proto((unsigned char **)out, outlen, protos, + protos_len, in, inlen) != OPENSSL_NPN_NEGOTIATED) { + free(protos); + return (SSL_TLSEXT_ERR_NOACK); + } + + /* + * Make a copy of the selected protocol which will be freed in + * verify_alpn. + */ + free(alpn_selected); + if ((alpn_selected = malloc(*outlen)) == NULL) { + fprintf(stderr, "malloc failed\n"); + abort(); + } + memcpy(alpn_selected, *out, *outlen); + *out = alpn_selected; + free(protos); + + return (SSL_TLSEXT_ERR_OK); +} + +static int +verify_alpn(SSL *client, SSL *server) +{ + const unsigned char *client_proto, *server_proto; + unsigned int client_proto_len = 0, server_proto_len = 0; + + SSL_get0_alpn_selected(client, &client_proto, &client_proto_len); + SSL_get0_alpn_selected(server, &server_proto, &server_proto_len); + + free(alpn_selected); + alpn_selected = NULL; + + if (client_proto_len != server_proto_len || (client_proto_len > 0 && + memcmp(client_proto, server_proto, client_proto_len) != 0)) { + BIO_printf(bio_stdout, "ALPN selected protocols differ!\n"); + goto err; + } + + if (client_proto_len > 0 && alpn_expected == NULL) { + BIO_printf(bio_stdout, "ALPN unexpectedly negotiated\n"); + goto err; + } + + if (alpn_expected != NULL && + (client_proto_len != strlen(alpn_expected) || + memcmp(client_proto, alpn_expected, client_proto_len) != 0)) { + BIO_printf(bio_stdout, "ALPN selected protocols not equal to " + "expected protocol: %s\n", alpn_expected); + goto err; + } + + return (0); + +err: + BIO_printf(bio_stdout, "ALPN results: client: '"); + BIO_write(bio_stdout, client_proto, client_proto_len); + BIO_printf(bio_stdout, "', server: '"); + BIO_write(bio_stdout, server_proto, server_proto_len); + BIO_printf(bio_stdout, "'\n"); + BIO_printf(bio_stdout, "ALPN configured: client: '%s', server: '%s'\n", + alpn_client, alpn_server); + + return (-1); +} + +static char *cipher = NULL; +static int verbose = 0; +static int debug = 0; + +int doit_biopair(SSL *s_ssl, SSL *c_ssl, long bytes, clock_t *s_time, + clock_t *c_time); +int doit(SSL *s_ssl, SSL *c_ssl, long bytes); + +static void +sv_usage(void) +{ + fprintf(stderr, "usage: ssltest [args ...]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " -server_auth - check server certificate\n"); + fprintf(stderr, " -client_auth - do client authentication\n"); + fprintf(stderr, " -proxy - allow proxy certificates\n"); + fprintf(stderr, " -proxy_auth - set proxy policy rights\n"); + fprintf(stderr, " -proxy_cond - experssion to test proxy policy rights\n"); + fprintf(stderr, " -v - more output\n"); + fprintf(stderr, " -d - debug output\n"); + fprintf(stderr, " -reuse - use session-id reuse\n"); + fprintf(stderr, " -num - number of connections to perform\n"); + fprintf(stderr, " -bytes - number of bytes to swap between client/server\n"); + fprintf(stderr, " -dhe1024dsa - use 1024 bit key (with 160-bit subprime) for DHE\n"); + fprintf(stderr, " -no_dhe - disable DHE\n"); + fprintf(stderr, " -no_ecdhe - disable ECDHE\n"); + fprintf(stderr, " -dtls1_2 - use DTLSv1.2\n"); + fprintf(stderr, " -tls1 - use TLSv1\n"); + fprintf(stderr, " -tls1_2 - use TLSv1.2\n"); + fprintf(stderr, " -CApath arg - PEM format directory of CA's\n"); + fprintf(stderr, " -CAfile arg - PEM format file of CA's\n"); + fprintf(stderr, " -cert arg - Server certificate file\n"); + fprintf(stderr, " -key arg - Server key file (default: same as -cert)\n"); + fprintf(stderr, " -c_cert arg - Client certificate file\n"); + fprintf(stderr, " -c_key arg - Client key file (default: same as -c_cert)\n"); + fprintf(stderr, " -cipher arg - The cipher list\n"); + fprintf(stderr, " -bio_pair - Use BIO pairs\n"); + fprintf(stderr, " -f - Test even cases that can't work\n"); + fprintf(stderr, " -time - measure processor time used by client and server\n"); + fprintf(stderr, " -named_curve arg - Elliptic curve name to use for ephemeral ECDH keys.\n" \ + " Use \"openssl ecparam -list_curves\" for all names\n" \ + " (default is sect163r2).\n"); + fprintf(stderr, " -alpn_client - have client side offer ALPN\n"); + fprintf(stderr, " -alpn_server - have server side offer ALPN\n"); + fprintf(stderr, " -alpn_expected - the ALPN protocol that should be negotiated\n"); +} + +static void +print_details(SSL *c_ssl, const char *prefix) +{ + const SSL_CIPHER *ciph; + X509 *cert = NULL; + EVP_PKEY *pkey; + + ciph = SSL_get_current_cipher(c_ssl); + BIO_printf(bio_stdout, "%s%s, cipher %s %s", + prefix, SSL_get_version(c_ssl), SSL_CIPHER_get_version(ciph), + SSL_CIPHER_get_name(ciph)); + + if ((cert = SSL_get_peer_certificate(c_ssl)) == NULL) + goto out; + if ((pkey = X509_get0_pubkey(cert)) == NULL) + goto out; + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) { + RSA *rsa; + + if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) + goto out; + + BIO_printf(bio_stdout, ", %d bit RSA", RSA_bits(rsa)); + } else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) { + DSA *dsa; + const BIGNUM *p; + + if ((dsa = EVP_PKEY_get0_DSA(pkey)) == NULL) + goto out; + + DSA_get0_pqg(dsa, &p, NULL, NULL); + + BIO_printf(bio_stdout, ", %d bit DSA", BN_num_bits(p)); + } + + out: + /* + * The SSL API does not allow us to look at temporary RSA/DH keys, + * otherwise we should print their lengths too + */ + BIO_printf(bio_stdout, "\n"); + + X509_free(cert); +} + +int +main(int argc, char *argv[]) +{ + char *CApath = NULL, *CAfile = NULL; + int badop = 0; + int bio_pair = 0; + int force = 0; + int tls1 = 0, tls1_2 = 0, dtls1_2 = 0, ret = 1; + int client_auth = 0; + int server_auth = 0, i; + char *app_verify_arg = "Test Callback Argument"; + char *server_cert = TEST_SERVER_CERT; + char *server_key = NULL; + char *client_cert = TEST_CLIENT_CERT; + char *client_key = NULL; + char *named_curve = NULL; + SSL_CTX *s_ctx = NULL; + SSL_CTX *c_ctx = NULL; + const SSL_METHOD *meth = NULL; + SSL *c_ssl, *s_ssl; + int number = 1, reuse = 0; + int seclevel = 0; + long bytes = 256L; + DH *dh; + int dhe1024dsa = 0; + EC_KEY *ecdh = NULL; + int no_dhe = 0; + int no_ecdhe = 0; + int print_time = 0; + clock_t s_time = 0, c_time = 0; + + verbose = 0; + debug = 0; + cipher = 0; + + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE|BIO_FP_TEXT); + + bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE|BIO_FP_TEXT); + + argc--; + argv++; + + while (argc >= 1) { + if (!strcmp(*argv, "-F")) { + fprintf(stderr, "not compiled with FIPS support, so exiting without running.\n"); + exit(0); + } else if (strcmp(*argv, "-server_auth") == 0) + server_auth = 1; + else if (strcmp(*argv, "-client_auth") == 0) + client_auth = 1; + else if (strcmp(*argv, "-v") == 0) + verbose = 1; + else if (strcmp(*argv, "-d") == 0) + debug = 1; + else if (strcmp(*argv, "-reuse") == 0) + reuse = 1; + else if (strcmp(*argv, "-dhe1024dsa") == 0) { + dhe1024dsa = 1; + } else if (strcmp(*argv, "-no_dhe") == 0) + no_dhe = 1; + else if (strcmp(*argv, "-no_ecdhe") == 0) + no_ecdhe = 1; + else if (strcmp(*argv, "-dtls1_2") == 0) + dtls1_2 = 1; + else if (strcmp(*argv, "-tls1") == 0) + tls1 = 1; + else if (strcmp(*argv, "-tls1_2") == 0) + tls1_2 = 1; + else if (strncmp(*argv, "-num", 4) == 0) { + if (--argc < 1) + goto bad; + number = atoi(*(++argv)); + if (number == 0) + number = 1; + } else if (strncmp(*argv, "-seclevel", 9) == 0) { + if (--argc < 1) + goto bad; + seclevel = atoi(*(++argv)); + } else if (strcmp(*argv, "-bytes") == 0) { + if (--argc < 1) + goto bad; + bytes = atol(*(++argv)); + if (bytes == 0L) + bytes = 1L; + i = strlen(argv[0]); + if (argv[0][i - 1] == 'k') + bytes*=1024L; + if (argv[0][i - 1] == 'm') + bytes*=1024L*1024L; + } else if (strcmp(*argv, "-cert") == 0) { + if (--argc < 1) + goto bad; + server_cert= *(++argv); + } else if (strcmp(*argv, "-s_cert") == 0) { + if (--argc < 1) + goto bad; + server_cert= *(++argv); + } else if (strcmp(*argv, "-key") == 0) { + if (--argc < 1) + goto bad; + server_key= *(++argv); + } else if (strcmp(*argv, "-s_key") == 0) { + if (--argc < 1) + goto bad; + server_key= *(++argv); + } else if (strcmp(*argv, "-c_cert") == 0) { + if (--argc < 1) + goto bad; + client_cert= *(++argv); + } else if (strcmp(*argv, "-c_key") == 0) { + if (--argc < 1) + goto bad; + client_key= *(++argv); + } else if (strcmp(*argv, "-cipher") == 0) { + if (--argc < 1) + goto bad; + cipher= *(++argv); + } else if (strcmp(*argv, "-CApath") == 0) { + if (--argc < 1) + goto bad; + CApath= *(++argv); + } else if (strcmp(*argv, "-CAfile") == 0) { + if (--argc < 1) + goto bad; + CAfile= *(++argv); + } else if (strcmp(*argv, "-bio_pair") == 0) { + bio_pair = 1; + } else if (strcmp(*argv, "-f") == 0) { + force = 1; + } else if (strcmp(*argv, "-time") == 0) { + print_time = 1; + } else if (strcmp(*argv, "-named_curve") == 0) { + if (--argc < 1) + goto bad; + named_curve = *(++argv); + } else if (strcmp(*argv, "-app_verify") == 0) { + ; + } else if (strcmp(*argv, "-alpn_client") == 0) { + if (--argc < 1) + goto bad; + alpn_client = *(++argv); + } else if (strcmp(*argv, "-alpn_server") == 0) { + if (--argc < 1) + goto bad; + alpn_server = *(++argv); + } else if (strcmp(*argv, "-alpn_expected") == 0) { + if (--argc < 1) + goto bad; + alpn_expected = *(++argv); + } else { + fprintf(stderr, "unknown option %s\n", *argv); + badop = 1; + break; + } + argc--; + argv++; + } + if (badop) { +bad: + sv_usage(); + goto end; + } + + if (!dtls1_2 && !tls1 && !tls1_2 && number > 1 && !reuse && !force) { + fprintf(stderr, + "This case cannot work. Use -f to perform " + "the test anyway (and\n-d to see what happens), " + "or add one of -dtls1, -tls1, -tls1_2, -reuse\n" + "to avoid protocol mismatch.\n"); + exit(1); + } + + if (print_time) { + if (!bio_pair) { + fprintf(stderr, "Using BIO pair (-bio_pair)\n"); + bio_pair = 1; + } + if (number < 50 && !force) + fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n"); + } + +/* if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */ + + SSL_library_init(); + SSL_load_error_strings(); + + if (dtls1_2) + meth = DTLSv1_2_method(); + else if (tls1) + meth = TLSv1_method(); + else if (tls1_2) + meth = TLSv1_2_method(); + else + meth = TLS_method(); + + c_ctx = SSL_CTX_new(meth); + s_ctx = SSL_CTX_new(meth); + if ((c_ctx == NULL) || (s_ctx == NULL)) { + ERR_print_errors(bio_err); + goto end; + } + + SSL_CTX_set_security_level(c_ctx, seclevel); + SSL_CTX_set_security_level(s_ctx, seclevel); + + if (cipher != NULL) { + SSL_CTX_set_cipher_list(c_ctx, cipher); + SSL_CTX_set_cipher_list(s_ctx, cipher); + } + + if (!no_dhe) { + if (dhe1024dsa) { + /* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */ + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE); + dh = get_dh1024dsa(); + } else + dh = get_dh1024(); + SSL_CTX_set_tmp_dh(s_ctx, dh); + DH_free(dh); + } + + if (!no_ecdhe) { + int nid; + + if (named_curve != NULL) { + nid = OBJ_sn2nid(named_curve); + if (nid == 0) { + BIO_printf(bio_err, "unknown curve name (%s)\n", named_curve); + goto end; + } + } else + nid = NID_X9_62_prime256v1; + + ecdh = EC_KEY_new_by_curve_name(nid); + if (ecdh == NULL) { + BIO_printf(bio_err, "unable to create curve\n"); + goto end; + } + + SSL_CTX_set_tmp_ecdh(s_ctx, ecdh); + SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_ECDH_USE); + EC_KEY_free(ecdh); + } + + if (!SSL_CTX_use_certificate_chain_file(s_ctx, server_cert)) { + ERR_print_errors(bio_err); + } else if (!SSL_CTX_use_PrivateKey_file(s_ctx, + (server_key ? server_key : server_cert), SSL_FILETYPE_PEM)) { + ERR_print_errors(bio_err); + goto end; + } + + if (client_auth) { + SSL_CTX_use_certificate_chain_file(c_ctx, client_cert); + SSL_CTX_use_PrivateKey_file(c_ctx, + (client_key ? client_key : client_cert), + SSL_FILETYPE_PEM); + } + + if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) || + (!SSL_CTX_set_default_verify_paths(s_ctx)) || + (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) || + (!SSL_CTX_set_default_verify_paths(c_ctx))) { + /* fprintf(stderr,"SSL_load_verify_locations\n"); */ + ERR_print_errors(bio_err); + /* goto end; */ + } + + if (client_auth) { + BIO_printf(bio_err, "client authentication\n"); + SSL_CTX_set_verify(s_ctx, + SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, + verify_callback); + SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, + app_verify_arg); + } + if (server_auth) { + BIO_printf(bio_err, "server authentication\n"); + SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, + verify_callback); + SSL_CTX_set_cert_verify_callback(c_ctx, app_verify_callback, + app_verify_arg); + } + + { + int session_id_context = 0; + SSL_CTX_set_session_id_context(s_ctx, + (void *)&session_id_context, sizeof(session_id_context)); + } + + if (alpn_server != NULL) + SSL_CTX_set_alpn_select_cb(s_ctx, cb_server_alpn, NULL); + + if (alpn_client != NULL) { + unsigned short alpn_len; + unsigned char *alpn = next_protos_parse(&alpn_len, alpn_client); + + if (alpn == NULL) { + BIO_printf(bio_err, "Error parsing -alpn_client argument\n"); + goto end; + } + SSL_CTX_set_alpn_protos(c_ctx, alpn, alpn_len); + free(alpn); + } + + c_ssl = SSL_new(c_ctx); + s_ssl = SSL_new(s_ctx); + + for (i = 0; i < number; i++) { + if (!reuse) + SSL_set_session(c_ssl, NULL); +#ifdef USE_BIOPAIR + if (bio_pair) + ret = doit_biopair(s_ssl, c_ssl, bytes, &s_time, + &c_time); + else +#endif + ret = doit(s_ssl, c_ssl, bytes); + } + + if (!verbose) { + print_details(c_ssl, ""); + } + if ((number > 1) || (bytes > 1L)) + BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n", + number, bytes); + if (print_time) { +#ifdef CLOCKS_PER_SEC + /* "To determine the time in seconds, the value returned + * by the clock function should be divided by the value + * of the macro CLOCKS_PER_SEC." + * -- ISO/IEC 9899 */ + BIO_printf(bio_stdout, + "Approximate total server time: %6.2f s\n" + "Approximate total client time: %6.2f s\n", + (double)s_time/CLOCKS_PER_SEC, + (double)c_time/CLOCKS_PER_SEC); +#else + /* "`CLOCKS_PER_SEC' undeclared (first use this function)" + * -- cc on NeXTstep/OpenStep */ + BIO_printf(bio_stdout, + "Approximate total server time: %6.2f units\n" + "Approximate total client time: %6.2f units\n", + (double)s_time, + (double)c_time); +#endif + } + + SSL_free(s_ssl); + SSL_free(c_ssl); + +end: + SSL_CTX_free(s_ctx); + SSL_CTX_free(c_ctx); + BIO_free(bio_stdout); + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + ERR_remove_thread_state(NULL); + EVP_cleanup(); + CRYPTO_mem_leaks(bio_err); + BIO_free(bio_err); + + exit(ret); + return ret; +} + +#if USE_BIOPAIR +int +doit_biopair(SSL *s_ssl, SSL *c_ssl, long count, clock_t *s_time, + clock_t *c_time) +{ + long cw_num = count, cr_num = count, sw_num = count, sr_num = count; + BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL; + BIO *server = NULL, *server_io = NULL; + BIO *client = NULL, *client_io = NULL; + int ret = 1; + + size_t bufsiz = 256; /* small buffer for testing */ + + if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz)) + goto err; + if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz)) + goto err; + + s_ssl_bio = BIO_new(BIO_f_ssl()); + if (!s_ssl_bio) + goto err; + + c_ssl_bio = BIO_new(BIO_f_ssl()); + if (!c_ssl_bio) + goto err; + + SSL_set_connect_state(c_ssl); + SSL_set_bio(c_ssl, client, client); + (void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE); + + SSL_set_accept_state(s_ssl); + SSL_set_bio(s_ssl, server, server); + (void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE); + + do { + /* c_ssl_bio: SSL filter BIO + * + * client: pseudo-I/O for SSL library + * + * client_io: client's SSL communication; usually to be + * relayed over some I/O facility, but in this + * test program, we're the server, too: + * + * server_io: server's SSL communication + * + * server: pseudo-I/O for SSL library + * + * s_ssl_bio: SSL filter BIO + * + * The client and the server each employ a "BIO pair": + * client + client_io, server + server_io. + * BIO pairs are symmetric. A BIO pair behaves similar + * to a non-blocking socketpair (but both endpoints must + * be handled by the same thread). + * [Here we could connect client and server to the ends + * of a single BIO pair, but then this code would be less + * suitable as an example for BIO pairs in general.] + * + * Useful functions for querying the state of BIO pair endpoints: + * + * BIO_ctrl_pending(bio) number of bytes we can read now + * BIO_ctrl_get_read_request(bio) number of bytes needed to fulfil + * other side's read attempt + * BIO_ctrl_get_write_guarantee(bio) number of bytes we can write now + * + * ..._read_request is never more than ..._write_guarantee; + * it depends on the application which one you should use. + */ + + /* We have non-blocking behaviour throughout this test program, but + * can be sure that there is *some* progress in each iteration; so + * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE + * -- we just try everything in each iteration + */ + + { + /* CLIENT */ + + char cbuf[1024*8]; + int i, r; + clock_t c_clock = clock(); + + memset(cbuf, 0, sizeof(cbuf)); + + if (debug) + if (SSL_in_init(c_ssl)) + printf("client waiting in SSL_connect - %s\n", + SSL_state_string_long(c_ssl)); + + if (cw_num > 0) { + /* Write to server. */ + + if (cw_num > (long)sizeof cbuf) + i = sizeof cbuf; + else + i = (int)cw_num; + r = BIO_write(c_ssl_bio, cbuf, i); + if (r < 0) { + if (!BIO_should_retry(c_ssl_bio)) { + fprintf(stderr, "ERROR in CLIENT\n"); + goto err; + } + /* BIO_should_retry(...) can just be ignored here. + * The library expects us to call BIO_write with + * the same arguments again, and that's what we will + * do in the next iteration. */ + } else if (r == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client wrote %d\n", r); + cw_num -= r; + + } + } + + if (cr_num > 0) { + /* Read from server. */ + + r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf)); + if (r < 0) { + if (!BIO_should_retry(c_ssl_bio)) { + fprintf(stderr, "ERROR in CLIENT\n"); + goto err; + } + /* Again, "BIO_should_retry" can be ignored. */ + } else if (r == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client read %d\n", r); + cr_num -= r; + } + } + + /* c_time and s_time increments will typically be very small + * (depending on machine speed and clock tick intervals), + * but sampling over a large number of connections should + * result in fairly accurate figures. We cannot guarantee + * a lot, however -- if each connection lasts for exactly + * one clock tick, it will be counted only for the client + * or only for the server or even not at all. + */ + *c_time += (clock() - c_clock); + } + + { + /* SERVER */ + + char sbuf[1024*8]; + int i, r; + clock_t s_clock = clock(); + + memset(sbuf, 0, sizeof(sbuf)); + + if (debug) + if (SSL_in_init(s_ssl)) + printf("server waiting in SSL_accept - %s\n", + SSL_state_string_long(s_ssl)); + + if (sw_num > 0) { + /* Write to client. */ + + if (sw_num > (long)sizeof sbuf) + i = sizeof sbuf; + else + i = (int)sw_num; + r = BIO_write(s_ssl_bio, sbuf, i); + if (r < 0) { + if (!BIO_should_retry(s_ssl_bio)) { + fprintf(stderr, "ERROR in SERVER\n"); + goto err; + } + /* Ignore "BIO_should_retry". */ + } else if (r == 0) { + fprintf(stderr, "SSL SERVER STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("server wrote %d\n", r); + sw_num -= r; + + } + } + + if (sr_num > 0) { + /* Read from client. */ + + r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf)); + if (r < 0) { + if (!BIO_should_retry(s_ssl_bio)) { + fprintf(stderr, "ERROR in SERVER\n"); + goto err; + } + /* blah, blah */ + } else if (r == 0) { + fprintf(stderr, "SSL SERVER STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("server read %d\n", r); + sr_num -= r; + } + } + + *s_time += (clock() - s_clock); + } + + { + /* "I/O" BETWEEN CLIENT AND SERVER. */ + + size_t r1, r2; + BIO *io1 = server_io, *io2 = client_io; + /* we use the non-copying interface for io1 + * and the standard BIO_write/BIO_read interface for io2 + */ + + static int prev_progress = 1; + int progress = 0; + + /* io1 to io2 */ + do { + size_t num; + int r; + + r1 = BIO_ctrl_pending(io1); + r2 = BIO_ctrl_get_write_guarantee(io2); + + num = r1; + if (r2 < num) + num = r2; + if (num) { + char *dataptr; + + if (INT_MAX < num) /* yeah, right */ + num = INT_MAX; + + r = BIO_nread(io1, &dataptr, (int)num); + assert(r > 0); + assert(r <= (int)num); + /* possibly r < num (non-contiguous data) */ + num = r; + r = BIO_write(io2, dataptr, (int)num); + if (r != (int)num) /* can't happen */ + { + fprintf(stderr, "ERROR: BIO_write could not write " + "BIO_ctrl_get_write_guarantee() bytes"); + goto err; + } + progress = 1; + + if (debug) + printf((io1 == client_io) ? + "C->S relaying: %d bytes\n" : + "S->C relaying: %d bytes\n", + (int)num); + } + } while (r1 && r2); + + /* io2 to io1 */ + { + size_t num; + int r; + + r1 = BIO_ctrl_pending(io2); + r2 = BIO_ctrl_get_read_request(io1); + /* here we could use ..._get_write_guarantee instead of + * ..._get_read_request, but by using the latter + * we test restartability of the SSL implementation + * more thoroughly */ + num = r1; + if (r2 < num) + num = r2; + if (num) { + char *dataptr; + + if (INT_MAX < num) + num = INT_MAX; + + if (num > 1) + --num; /* test restartability even more thoroughly */ + + r = BIO_nwrite0(io1, &dataptr); + assert(r > 0); + if (r < (int)num) + num = r; + r = BIO_read(io2, dataptr, (int)num); + if (r != (int)num) /* can't happen */ + { + fprintf(stderr, "ERROR: BIO_read could not read " + "BIO_ctrl_pending() bytes"); + goto err; + } + progress = 1; + r = BIO_nwrite(io1, &dataptr, (int)num); + if (r != (int)num) /* can't happen */ + { + fprintf(stderr, "ERROR: BIO_nwrite() did not accept " + "BIO_nwrite0() bytes"); + goto err; + } + + if (debug) + printf((io2 == client_io) ? + "C->S relaying: %d bytes\n" : + "S->C relaying: %d bytes\n", + (int)num); + } + } /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */ + + if (!progress && !prev_progress) { + if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0) { + fprintf(stderr, "ERROR: got stuck\n"); + goto err; + } + } + prev_progress = progress; + } + } while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0); + + if (verbose) + print_details(c_ssl, "DONE via BIO pair: "); + + if (verify_alpn(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; + } + + ret = 0; + +err: + ERR_print_errors(bio_err); + + BIO_free(server); + BIO_free(server_io); + BIO_free(client); + BIO_free(client_io); + BIO_free(s_ssl_bio); + BIO_free(c_ssl_bio); + + return ret; +} +#endif + + +#define W_READ 1 +#define W_WRITE 2 +#define C_DONE 1 +#define S_DONE 2 + +int +doit(SSL *s_ssl, SSL *c_ssl, long count) +{ + char cbuf[1024*8], sbuf[1024*8]; + long cw_num = count, cr_num = count; + long sw_num = count, sr_num = count; + int ret = 1; + BIO *c_to_s = NULL; + BIO *s_to_c = NULL; + BIO *c_bio = NULL; + BIO *s_bio = NULL; + int c_r, c_w, s_r, s_w; + int i, j; + int done = 0; + int c_write, s_write; + int do_server = 0, do_client = 0; + + memset(cbuf, 0, sizeof(cbuf)); + memset(sbuf, 0, sizeof(sbuf)); + + c_to_s = BIO_new(BIO_s_mem()); + s_to_c = BIO_new(BIO_s_mem()); + if ((s_to_c == NULL) || (c_to_s == NULL)) { + ERR_print_errors(bio_err); + goto err; + } + + c_bio = BIO_new(BIO_f_ssl()); + s_bio = BIO_new(BIO_f_ssl()); + if ((c_bio == NULL) || (s_bio == NULL)) { + ERR_print_errors(bio_err); + goto err; + } + + SSL_set_connect_state(c_ssl); + SSL_set_bio(c_ssl, s_to_c, c_to_s); + BIO_set_ssl(c_bio, c_ssl, BIO_NOCLOSE); + + SSL_set_accept_state(s_ssl); + SSL_set_bio(s_ssl, c_to_s, s_to_c); + BIO_set_ssl(s_bio, s_ssl, BIO_NOCLOSE); + + c_r = 0; + s_r = 1; + c_w = 1; + s_w = 0; + c_write = 1, s_write = 0; + + /* We can always do writes */ + for (;;) { + do_server = 0; + do_client = 0; + + i = (int)BIO_pending(s_bio); + if ((i && s_r) || s_w) + do_server = 1; + + i = (int)BIO_pending(c_bio); + if ((i && c_r) || c_w) + do_client = 1; + + if (do_server && debug) { + if (SSL_in_init(s_ssl)) + printf("server waiting in SSL_accept - %s\n", + SSL_state_string_long(s_ssl)); + } + + if (do_client && debug) { + if (SSL_in_init(c_ssl)) + printf("client waiting in SSL_connect - %s\n", + SSL_state_string_long(c_ssl)); + } + + if (!do_client && !do_server) { + fprintf(stdout, "ERROR in STARTUP\n"); + ERR_print_errors(bio_err); + goto err; + } + + if (do_client && !(done & C_DONE)) { + if (c_write) { + j = (cw_num > (long)sizeof(cbuf)) ? + (int)sizeof(cbuf) : (int)cw_num; + i = BIO_write(c_bio, cbuf, j); + if (i < 0) { + c_r = 0; + c_w = 0; + if (BIO_should_retry(c_bio)) { + if (BIO_should_read(c_bio)) + c_r = 1; + if (BIO_should_write(c_bio)) + c_w = 1; + } else { + fprintf(stderr, "ERROR in CLIENT\n"); + ERR_print_errors(bio_err); + goto err; + } + } else if (i == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client wrote %d\n", i); + /* ok */ + s_r = 1; + c_write = 0; + cw_num -= i; + } + } else { + i = BIO_read(c_bio, cbuf, sizeof(cbuf)); + if (i < 0) { + c_r = 0; + c_w = 0; + if (BIO_should_retry(c_bio)) { + if (BIO_should_read(c_bio)) + c_r = 1; + if (BIO_should_write(c_bio)) + c_w = 1; + } else { + fprintf(stderr, "ERROR in CLIENT\n"); + ERR_print_errors(bio_err); + goto err; + } + } else if (i == 0) { + fprintf(stderr, "SSL CLIENT STARTUP FAILED\n"); + goto err; + } else { + if (debug) + printf("client read %d\n", i); + cr_num -= i; + if (sw_num > 0) { + s_write = 1; + s_w = 1; + } + if (cr_num <= 0) { + s_write = 1; + s_w = 1; + done = S_DONE|C_DONE; + } + } + } + } + + if (do_server && !(done & S_DONE)) { + if (!s_write) { + i = BIO_read(s_bio, sbuf, sizeof(cbuf)); + if (i < 0) { + s_r = 0; + s_w = 0; + if (BIO_should_retry(s_bio)) { + if (BIO_should_read(s_bio)) + s_r = 1; + if (BIO_should_write(s_bio)) + s_w = 1; + } else { + fprintf(stderr, "ERROR in SERVER\n"); + ERR_print_errors(bio_err); + goto err; + } + } else if (i == 0) { + ERR_print_errors(bio_err); + fprintf(stderr, "SSL SERVER STARTUP FAILED in SSL_read\n"); + goto err; + } else { + if (debug) + printf("server read %d\n", i); + sr_num -= i; + if (cw_num > 0) { + c_write = 1; + c_w = 1; + } + if (sr_num <= 0) { + s_write = 1; + s_w = 1; + c_write = 0; + } + } + } else { + j = (sw_num > (long)sizeof(sbuf)) ? + (int)sizeof(sbuf) : (int)sw_num; + i = BIO_write(s_bio, sbuf, j); + if (i < 0) { + s_r = 0; + s_w = 0; + if (BIO_should_retry(s_bio)) { + if (BIO_should_read(s_bio)) + s_r = 1; + if (BIO_should_write(s_bio)) + s_w = 1; + } else { + fprintf(stderr, "ERROR in SERVER\n"); + ERR_print_errors(bio_err); + goto err; + } + } else if (i == 0) { + ERR_print_errors(bio_err); + fprintf(stderr, "SSL SERVER STARTUP FAILED in SSL_write\n"); + goto err; + } else { + if (debug) + printf("server wrote %d\n", i); + sw_num -= i; + s_write = 0; + c_r = 1; + if (sw_num <= 0) + done |= S_DONE; + } + } + } + + if ((done & S_DONE) && (done & C_DONE)) + break; + } + + if (verbose) + print_details(c_ssl, "DONE: "); + + if (verify_alpn(c_ssl, s_ssl) < 0) { + ret = 1; + goto err; + } + + ret = 0; +err: + /* We have to set the BIO's to NULL otherwise they will be + * free()ed twice. Once when th s_ssl is SSL_free()ed and + * again when c_ssl is SSL_free()ed. + * This is a hack required because s_ssl and c_ssl are sharing the same + * BIO structure and SSL_set_bio() and SSL_free() automatically + * BIO_free non NULL entries. + * You should not normally do this or be required to do this */ + if (s_ssl != NULL) { + s_ssl->rbio = NULL; + s_ssl->wbio = NULL; + } + if (c_ssl != NULL) { + c_ssl->rbio = NULL; + c_ssl->wbio = NULL; + } + + BIO_free(c_to_s); + BIO_free(s_to_c); + BIO_free_all(c_bio); + BIO_free_all(s_bio); + + return (ret); +} + +static int +verify_callback(int ok, X509_STORE_CTX *ctx) +{ + X509 *xs; + char *s, buf[256]; + int error, error_depth; + + xs = X509_STORE_CTX_get_current_cert(ctx); + s = X509_NAME_oneline(X509_get_subject_name(xs), buf, sizeof buf); + error = X509_STORE_CTX_get_error(ctx); + error_depth = X509_STORE_CTX_get_error_depth(ctx); + if (s != NULL) { + if (ok) + fprintf(stderr, "depth=%d %s\n", error_depth, buf); + else { + fprintf(stderr, "depth=%d error=%d %s\n", error_depth, + error, buf); + } + } + + if (ok == 0) { + fprintf(stderr, "Error string: %s\n", + X509_verify_cert_error_string(error)); + switch (error) { + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + fprintf(stderr, " ... ignored.\n"); + ok = 1; + } + } + + return (ok); +} + +static int +app_verify_callback(X509_STORE_CTX *ctx, void *arg) +{ + X509 *xs; + char *s = NULL, buf[256]; + const char *cb_arg = arg; + + xs = X509_STORE_CTX_get0_cert(ctx); + fprintf(stderr, "In app_verify_callback, allowing cert. "); + fprintf(stderr, "Arg is: %s\n", cb_arg); + fprintf(stderr, "Finished printing do we have a context? 0x%p a cert? 0x%p\n", + (void *)ctx, (void *)xs); + if (xs) + s = X509_NAME_oneline(X509_get_subject_name(xs), buf, 256); + if (s != NULL) { + fprintf(stderr, "cert depth=%d %s\n", + X509_STORE_CTX_get_error_depth(ctx), buf); + } + + return 1; +} + +/* These DH parameters have been generated as follows: + * $ openssl dhparam -C -noout 1024 + * $ openssl dhparam -C -noout -dsaparam 1024 + * (The second function has been renamed to avoid name conflicts.) + */ +static DH * +get_dh1024(void) +{ + static unsigned char dh1024_p[] = { + 0xF8, 0x81, 0x89, 0x7D, 0x14, 0x24, 0xC5, 0xD1, 0xE6, 0xF7, 0xBF, 0x3A, + 0xE4, 0x90, 0xF4, 0xFC, 0x73, 0xFB, 0x34, 0xB5, 0xFA, 0x4C, 0x56, 0xA2, + 0xEA, 0xA7, 0xE9, 0xC0, 0xC0, 0xCE, 0x89, 0xE1, 0xFA, 0x63, 0x3F, 0xB0, + 0x6B, 0x32, 0x66, 0xF1, 0xD1, 0x7B, 0xB0, 0x00, 0x8F, 0xCA, 0x87, 0xC2, + 0xAE, 0x98, 0x89, 0x26, 0x17, 0xC2, 0x05, 0xD2, 0xEC, 0x08, 0xD0, 0x8C, + 0xFF, 0x17, 0x52, 0x8C, 0xC5, 0x07, 0x93, 0x03, 0xB1, 0xF6, 0x2F, 0xB8, + 0x1C, 0x52, 0x47, 0x27, 0x1B, 0xDB, 0xD1, 0x8D, 0x9D, 0x69, 0x1D, 0x52, + 0x4B, 0x32, 0x81, 0xAA, 0x7F, 0x00, 0xC8, 0xDC, 0xE6, 0xD9, 0xCC, 0xC1, + 0x11, 0x2D, 0x37, 0x34, 0x6C, 0xEA, 0x02, 0x97, 0x4B, 0x0E, 0xBB, 0xB1, + 0x71, 0x33, 0x09, 0x15, 0xFD, 0xDD, 0x23, 0x87, 0x07, 0x5E, 0x89, 0xAB, + 0x6B, 0x7C, 0x5F, 0xEC, 0xA6, 0x24, 0xDC, 0x53, + }; + static unsigned char dh1024_g[] = { + 0x02, + }; + DH *dh; + BIGNUM *dh_p = NULL, *dh_g = NULL; + + if ((dh = DH_new()) == NULL) + return NULL; + + dh_p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); + dh_g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); + if (dh_p == NULL || dh_g == NULL) + goto err; + + if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) + goto err; + + return dh; + + err: + BN_free(dh_p); + BN_free(dh_g); + DH_free(dh); + return NULL; +} + +static DH * +get_dh1024dsa(void) +{ + static unsigned char dh1024_p[] = { + 0xC8, 0x00, 0xF7, 0x08, 0x07, 0x89, 0x4D, 0x90, 0x53, 0xF3, 0xD5, 0x00, + 0x21, 0x1B, 0xF7, 0x31, 0xA6, 0xA2, 0xDA, 0x23, 0x9A, 0xC7, 0x87, 0x19, + 0x3B, 0x47, 0xB6, 0x8C, 0x04, 0x6F, 0xFF, 0xC6, 0x9B, 0xB8, 0x65, 0xD2, + 0xC2, 0x5F, 0x31, 0x83, 0x4A, 0xA7, 0x5F, 0x2F, 0x88, 0x38, 0xB6, 0x55, + 0xCF, 0xD9, 0x87, 0x6D, 0x6F, 0x9F, 0xDA, 0xAC, 0xA6, 0x48, 0xAF, 0xFC, + 0x33, 0x84, 0x37, 0x5B, 0x82, 0x4A, 0x31, 0x5D, 0xE7, 0xBD, 0x52, 0x97, + 0xA1, 0x77, 0xBF, 0x10, 0x9E, 0x37, 0xEA, 0x64, 0xFA, 0xCA, 0x28, 0x8D, + 0x9D, 0x3B, 0xD2, 0x6E, 0x09, 0x5C, 0x68, 0xC7, 0x45, 0x90, 0xFD, 0xBB, + 0x70, 0xC9, 0x3A, 0xBB, 0xDF, 0xD4, 0x21, 0x0F, 0xC4, 0x6A, 0x3C, 0xF6, + 0x61, 0xCF, 0x3F, 0xD6, 0x13, 0xF1, 0x5F, 0xBC, 0xCF, 0xBC, 0x26, 0x9E, + 0xBC, 0x0B, 0xBD, 0xAB, 0x5D, 0xC9, 0x54, 0x39, + }; + static unsigned char dh1024_g[] = { + 0x3B, 0x40, 0x86, 0xE7, 0xF3, 0x6C, 0xDE, 0x67, 0x1C, 0xCC, 0x80, 0x05, + 0x5A, 0xDF, 0xFE, 0xBD, 0x20, 0x27, 0x74, 0x6C, 0x24, 0xC9, 0x03, 0xF3, + 0xE1, 0x8D, 0xC3, 0x7D, 0x98, 0x27, 0x40, 0x08, 0xB8, 0x8C, 0x6A, 0xE9, + 0xBB, 0x1A, 0x3A, 0xD6, 0x86, 0x83, 0x5E, 0x72, 0x41, 0xCE, 0x85, 0x3C, + 0xD2, 0xB3, 0xFC, 0x13, 0xCE, 0x37, 0x81, 0x9E, 0x4C, 0x1C, 0x7B, 0x65, + 0xD3, 0xE6, 0xA6, 0x00, 0xF5, 0x5A, 0x95, 0x43, 0x5E, 0x81, 0xCF, 0x60, + 0xA2, 0x23, 0xFC, 0x36, 0xA7, 0x5D, 0x7A, 0x4C, 0x06, 0x91, 0x6E, 0xF6, + 0x57, 0xEE, 0x36, 0xCB, 0x06, 0xEA, 0xF5, 0x3D, 0x95, 0x49, 0xCB, 0xA7, + 0xDD, 0x81, 0xDF, 0x80, 0x09, 0x4A, 0x97, 0x4D, 0xA8, 0x22, 0x72, 0xA1, + 0x7F, 0xC4, 0x70, 0x56, 0x70, 0xE8, 0x20, 0x10, 0x18, 0x8F, 0x2E, 0x60, + 0x07, 0xE7, 0x68, 0x1A, 0x82, 0x5D, 0x32, 0xA2, + }; + DH *dh; + BIGNUM *dh_p = NULL, *dh_g = NULL; + + if ((dh = DH_new()) == NULL) + return NULL; + + dh_p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); + dh_g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); + if (dh_p == NULL || dh_g == NULL) + goto err; + + if (!DH_set0_pqg(dh, dh_p, NULL, dh_g)) + goto err; + + DH_set_length(dh, 160); + + return dh; + + err: + BN_free(dh_p); + BN_free(dh_g); + DH_free(dh); + return NULL; +} diff --git a/tests/string_table.c b/tests/string_table.c new file mode 100644 index 0000000..e80cf0f --- /dev/null +++ b/tests/string_table.c @@ -0,0 +1,128 @@ +/* $OpenBSD: string_table.c,v 1.1 2021/12/11 22:58:48 schwarze Exp $ */ +/* + * Copyright (c) 2021 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +static int errcount; + +static void +report(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vwarnx(fmt, ap); + va_end(ap); + + errcount++; +} + +static void +stable_check(const char *testname, ASN1_STRING_TABLE *have, + ASN1_STRING_TABLE *want, unsigned long want_flags) +{ + if (have == NULL) { + report("%s returned NULL", testname); + return; + } + if (have->nid != want->nid) + report("%s nid %d, expected %d", testname, + have->nid, want->nid); + if (have->minsize != want->minsize) + report("%s minsize %ld, expected %ld", testname, + have->minsize, want->minsize); + if (have->maxsize != want->maxsize) + report("%s maxsize %ld, expected %ld", testname, + have->maxsize, want->maxsize); + if (have->mask != want->mask) + report("%s mask %lu, expected %lu", testname, + have->mask, want->mask); + if (have->flags != want_flags) + report("%s flags %lu, expected %lu", testname, + have->flags, want_flags); +} + +int +main(void) +{ + ASN1_STRING_TABLE orig, mine, *have; + int irc; + + orig.nid = NID_name; + orig.minsize = 1; + orig.maxsize = ub_name; + orig.mask = DIRSTRING_TYPE; + orig.flags = 0; + + mine.nid = NID_name; + mine.minsize = 4; + mine.maxsize = 64; + mine.mask = B_ASN1_PRINTABLESTRING; + mine.flags = STABLE_NO_MASK; + + /* Original entry. */ + + have = ASN1_STRING_TABLE_get(orig.nid); + stable_check("orig", have, &orig, 0); + + /* Copy, but don't really change. */ + + irc = ASN1_STRING_TABLE_add(orig.nid, -1, -1, 0, 0); + if (irc != 1) + report("set noop returned %d, expected 1", irc); + have = ASN1_STRING_TABLE_get(orig.nid); + stable_check("noop", have, &orig, STABLE_FLAGS_MALLOC); + + /* Change entry. */ + + irc = ASN1_STRING_TABLE_add(mine.nid, mine.minsize, mine.maxsize, + mine.mask, mine.flags); + if (irc != 1) + report("set returned %d, expected 1", irc); + have = ASN1_STRING_TABLE_get(mine.nid); + stable_check("set", have, &mine, STABLE_FLAGS_MALLOC | STABLE_NO_MASK); + + /* New entry. */ + + mine.nid = NID_title; + irc = ASN1_STRING_TABLE_add(mine.nid, mine.minsize, mine.maxsize, + mine.mask, mine.flags); + if (irc != 1) + report("new returned %d, expected 1", irc); + have = ASN1_STRING_TABLE_get(mine.nid); + stable_check("new", have, &mine, STABLE_FLAGS_MALLOC | STABLE_NO_MASK); + + /* Back to the initial state. */ + + ASN1_STRING_TABLE_cleanup(); + have = ASN1_STRING_TABLE_get(orig.nid); + stable_check("back", have, &orig, 0); + if (ASN1_STRING_TABLE_get(mine.nid) != NULL) + report("deleted entry is not NULL"); + + switch (errcount) { + case 0: + return 0; + case 1: + errx(1, "one error"); + default: + errx(1, "%d errors", errcount); + } +} diff --git a/tests/tests.h b/tests/tests.h new file mode 100644 index 0000000..2878169 --- /dev/null +++ b/tests/tests.h @@ -0,0 +1,44 @@ +/* $OpenBSD: tests.h,v 1.1 2015/06/27 23:35:52 doug Exp $ */ +/* + * Copyright (c) 2015 Doug Hogan + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef LIBRESSL_REGRESS_TESTS_H__ +#define LIBRESSL_REGRESS_TESTS_H__ 1 + +/* Ugly macros that are useful for regression tests. */ + +#define SKIP(a) do { \ + printf("Skipping test in %s [%s:%d]\n", __func__, __FILE__, \ + __LINE__); \ +} while (0) + +#define CHECK(a) do { \ + if (!(a)) { \ + printf("Error in %s [%s:%d]\n", __func__, __FILE__, \ + __LINE__); \ + return 0; \ + } \ +} while (0) + +#define CHECK_GOTO(a) do { \ + if (!(a)) { \ + printf("Error in %s [%s:%d]\n", __func__, __FILE__, \ + __LINE__); \ + goto err; \ + } \ +} while (0) + +#endif /* LIBRESSL_REGRESS_TESTS_H__ */ diff --git a/tests/testssl b/tests/testssl new file mode 100755 index 0000000..70db175 --- /dev/null +++ b/tests/testssl @@ -0,0 +1,162 @@ +#!/bin/sh + +key="$1" +cert="$2" +CA="-CAfile $3" +ssltest="${4-./ssltest} -key $key -cert $cert -c_key $key -c_cert $cert" +openssl=${5-openssl} +extra="$6" + +$openssl version || exit 1 + +if $openssl x509 -in $cert -text -noout | fgrep 'DSA Public Key' >/dev/null; then + dsa_cert=YES +else + dsa_cert=NO +fi + +############################################################################# + +echo test sslv2/sslv3 +$ssltest $extra || exit 1 + +echo test sslv2/sslv3 with server authentication +$ssltest -server_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with client authentication +$ssltest -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication +$ssltest -server_auth -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 via BIO pair +$ssltest $extra || exit 1 + +if [ $dsa_cert = NO ]; then + echo 'test sslv2/sslv3 w/o (EC)DHE via BIO pair' + $ssltest -bio_pair -no_dhe -no_ecdhe $extra || exit 1 +fi + +echo test sslv2/sslv3 with 1024bit DHE via BIO pair +$ssltest -bio_pair -dhe1024dsa -v $extra || exit 1 + +echo test sslv2/sslv3 with server authentication +$ssltest -bio_pair -server_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with client authentication via BIO pair +$ssltest -bio_pair -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair +$ssltest -bio_pair -server_auth -client_auth $CA $extra || exit 1 + +echo test sslv2/sslv3 with both client and server authentication via BIO pair and app verify +$ssltest -bio_pair -server_auth -client_auth -app_verify $CA $extra || exit 1 + +echo "Testing ciphersuites" +for protocol in SSLv3 TLSv1.2; do + echo "Testing ciphersuites for $protocol" + for cipher in `$openssl ciphers -v "$protocol+aRSA" | + awk "/ $protocol / { print \\$1 }"`; do + echo "Testing $cipher" + $ssltest -cipher $cipher -tls1_2 + if [ $? -ne 0 ] ; then + echo "Failed $cipher" + exit 1 + fi + done +done +for protocol in TLSv1.3; do + echo "Testing ciphersuites for $protocol at security level 2" + for cipher in `$openssl ciphers -v "$protocol" | + awk "/ $protocol / { print \\$1 }"`; do + echo "Testing $cipher" + $ssltest -cipher $cipher -seclevel 2 + if [ $? -ne 0 ] ; then + echo "Failed $cipher" + exit 1 + fi + done +done +for protocol in TLSv1.3; do + echo "Testing ciphersuites for $protocol at security level 3" + for cipher in `$openssl ciphers -v "$protocol" | + awk "/ $protocol / { print \\$1 }"`; do + echo "Testing $cipher" + $ssltest -cipher $cipher -seclevel 3 + if [ $? -eq 0 ] ; then + echo "Failed $cipher should not have succeeded" + exit 1 + fi + done +done + +############################################################################# + +if $openssl no-dh; then + echo skipping anonymous DH tests +else + echo skipping tls1 tests. +fi + +#if $openssl no-rsa; then +# echo skipping RSA tests +#else +# echo 'test tls1 with 1024bit RSA, no (EC)DHE, multiple handshakes' +# ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -no_dhe -no_ecdhe -num 10 -f -time $extra || exit 1 +# +# if $openssl no-dh; then +# echo skipping RSA+DHE tests +# else +# echo test tls1 with 1024bit RSA, 1024bit DHE, multiple handshakes +# ./ssltest -v -bio_pair -tls1 -cert ../apps/server2.pem -dhe1024dsa -num 10 -f -time $extra || exit 1 +# fi +#fi + +# +# DTLS tests +# + +$ssltest -dtls1_2 $extra || exit 1 + +echo test dtlsv1_2 with server authentication +$ssltest -dtls1_2 -server_auth $CA $extra || exit 1 + +echo test dtlsv1_2 with client authentication +$ssltest -dtls1_2 -client_auth $CA $extra || exit 1 + +echo test dtlsv1_2 with both client and server authentication +$ssltest -dtls1_2 -server_auth -client_auth $CA $extra || exit 1 + +echo "Testing DTLS ciphersuites" +for protocol in SSLv3; do + echo "Testing ciphersuites for $protocol" + for cipher in `$openssl ciphers -v "RSA+$protocol" | + awk "/ $protocol / { print \\$1 }" | + grep -v RC4`; do + echo "Testing $cipher" + $ssltest -cipher $cipher -dtls1_2 + if [ $? -ne 0 ] ; then + echo "Failed $cipher" + exit 1 + fi + done +done + +# +# ALPN tests +# +echo "Testing ALPN..." +$ssltest -bio_pair -alpn_client foo -alpn_server bar || exit 1 +$ssltest -bio_pair -alpn_client foo -alpn_server foo \ + -alpn_expected foo || exit 1 +$ssltest -bio_pair -alpn_client foo,bar -alpn_server foo \ + -alpn_expected foo || exit 1 +$ssltest -bio_pair -alpn_client bar,foo -alpn_server foo \ + -alpn_expected foo || exit 1 +$ssltest -bio_pair -alpn_client bar,foo -alpn_server foo,bar \ + -alpn_expected foo || exit 1 +$ssltest -bio_pair -alpn_client bar,foo -alpn_server bar,foo \ + -alpn_expected bar || exit 1 +$ssltest -bio_pair -alpn_client foo,bar -alpn_server bar,foo \ + -alpn_expected bar || exit 1 +$ssltest -bio_pair -alpn_client baz -alpn_server bar,foo || exit 1 diff --git a/tests/timingsafe.c b/tests/timingsafe.c new file mode 100644 index 0000000..f6605f8 --- /dev/null +++ b/tests/timingsafe.c @@ -0,0 +1,68 @@ +/* $OpenBSD: timingsafe.c,v 1.3 2014/06/21 22:57:15 tedu Exp $ */ +/* + * Copyright (c) 2014 Google Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#define ASSERT_EQ(a, b) assert((a) == (b)) + +enum { + N = 8 +}; + +static unsigned char bufone[N], buftwo[N]; + +void +check() +{ + int cmp = memcmp(bufone, buftwo, N); + + /* Check for reflexivity. */ + ASSERT_EQ(0, timingsafe_bcmp(bufone, bufone, N)); + ASSERT_EQ(0, timingsafe_bcmp(buftwo, buftwo, N)); + ASSERT_EQ(0, timingsafe_memcmp(bufone, bufone, N)); + ASSERT_EQ(0, timingsafe_memcmp(buftwo, buftwo, N)); + + /* Check that timingsafe_bcmp returns 0 iff memcmp returns 0. */ + ASSERT_EQ(cmp == 0, timingsafe_bcmp(bufone, buftwo, N) == 0); + + /* Check that timingsafe_memcmp returns cmp... */ + ASSERT_EQ(cmp < 0, timingsafe_memcmp(bufone, buftwo, N) < 0); + + /* ... or -cmp if the argument order is swapped. */ + ASSERT_EQ(-cmp < 0, timingsafe_memcmp(buftwo, bufone, N) < 0); +} + +int +main() +{ + int i, j; + + for (i = 0; i < 10000; i++) { + arc4random_buf(bufone, N); + arc4random_buf(buftwo, N); + + check(); + for (j = 0; j < N; j++) { + buftwo[j] = bufone[j]; + check(); + } + } + + return (0); +} diff --git a/tests/tls_ext_alpn.c b/tests/tls_ext_alpn.c new file mode 100644 index 0000000..d00f3ef --- /dev/null +++ b/tests/tls_ext_alpn.c @@ -0,0 +1,442 @@ +/* $OpenBSD: tls_ext_alpn.c,v 1.9 2022/11/26 16:08:57 tb Exp $ */ +/* + * Copyright (c) 2015 Doug Hogan + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Test TLS extension Application-Layer Protocol Negotiation (RFC 7301). + */ +#include +#include + +#include "ssl_local.h" +#include "ssl_tlsext.h" + +#include "tests.h" + +/* + * In the ProtocolNameList, ProtocolNames must not include empty strings and + * byte strings must not be truncated. + * + * This uses some of the IANA approved protocol names from: + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml + */ + +/* Valid for client and server since it only has one name. */ +static uint8_t proto_single[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0f, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x0b, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x09, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 +}; + +/* Valid for client, but NOT server. Server must have exactly one name. */ +static uint8_t proto_multiple1[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x19, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x15, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x13, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */ + 0x09, /* len */ + 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e +}; + +/* Valid for client, but NOT server. Server must have exactly one name. */ +static uint8_t proto_multiple2[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x1c, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x18, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x16, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'h2' */ + 0x02, /* len */ + 0x68, 0x32, + /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */ + 0x09, /* len */ + 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e +}; + +/* Valid for client, but NOT server. Server must have exactly one name. */ +static uint8_t proto_multiple3[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x20, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x1c, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x1a, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'h2' */ + 0x02, /* len */ + 0x68, 0x32, + /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */ + 0x09, /* len */ + 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e, + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; + +static uint8_t proto_empty[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions. */ + 0x00, 0x00, /* none present. */ +}; + +/* Invalid for both client and server. Length is wrong. */ +static uint8_t proto_invalid_len1[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x04, /* XXX len too large */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len2[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x02, /* XXX len too small */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len3[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x03, /* XXX len too small */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len4[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x06, /* XXX len too large */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len5[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x01, 0x08, /* XXX len too large */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len6[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x05, /* XXX len too small */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len7[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x06, /* XXX len too small */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; +static uint8_t proto_invalid_len8[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0b, /* XXX len too large */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + 0x03, /* len */ + 0x68, 0x32, 0x63 +}; + +/* Invalid for client and server since it is missing data. */ +static uint8_t proto_invalid_missing1[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x06, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x04, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'h2c' */ + /* XXX missing */ +}; +static uint8_t proto_invalid_missing2[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x00, /* XXX missing name list */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ +}; +static uint8_t proto_invalid_missing3[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x02, /* XXX size is sufficient but missing data for name list */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ +}; +static uint8_t proto_invalid_missing4[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x0a, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + /* XXX missing */ +}; +static uint8_t proto_invalid_missing5[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x1c, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x18, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x16, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'h2' */ + 0x02, /* len */ + 0x68, 0x32, + /* XXX missing name */ +}; +static uint8_t proto_invalid_missing6[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x07, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x03, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x01, /* XXX len must be at least 2 */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x00, /* XXX len cannot be 0 */ +}; +static uint8_t proto_invalid_missing7[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x07, /* len */ + /* ExtensionType extension_type */ + 0x00, 0x10, /* ALPN */ + /* opaque extension_data<0..2^16-1> */ + 0x00, 0x03, /* len */ + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x02, /* XXX len is at least 2 but not correct. */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x00, /* XXX len cannot be 0 */ +}; +static uint8_t proto_invalid_missing8[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x00, 0x01, /* len */ + /* ExtensionType extension_type */ + 0x00, /* XXX need a 2 byte type */ +}; +static uint8_t proto_invalid_missing9[] = { + /* Extension extensions<0..2^16-1> -- All TLS extensions */ + 0x0a, /* XXX need a 2 byte len */ +}; + + +#define CHECK_BOTH(c_val, s_val, proto) do { \ + { \ + CBS cbs; \ + int al; \ + \ + CBS_init(&cbs, proto, sizeof(proto)); \ + CHECK(c_val == tlsext_server_parse(s, SSL_TLSEXT_MSG_CH, &cbs, &al)); \ + CBS_init(&cbs, proto, sizeof(proto)); \ + CHECK(s_val == tlsext_client_parse(s, SSL_TLSEXT_MSG_SH, &cbs, &al)); \ + } \ +} while (0) + +static int dummy_alpn_cb(SSL *ssl, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg); + +static int +check_valid_alpn(SSL *s) +{ + const uint8_t str[] = { + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */ + }; + + /* Setup in order to test ALPN. */ + CHECK(! SSL_set_alpn_protos(s, str, 9)); + SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL); + + /* Prerequisites to test these. */ + CHECK(s->alpn_client_proto_list != NULL); + CHECK(s->ctx->alpn_select_cb != NULL); + //CHECK(s->s3->tmp.finish_md_len == 0); + + CHECK_BOTH(1, 1, proto_single); + CHECK_BOTH(1, 1, proto_empty); + + /* Multiple protocol names are only valid for client */ + CHECK_BOTH(1, 0, proto_multiple1); + CHECK_BOTH(1, 0, proto_multiple2); + CHECK_BOTH(1, 0, proto_multiple3); + + return 1; +} + +/* + * Some of the IANA approved IDs from: + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml + */ +static int +check_invalid_alpn(SSL *s) +{ + const uint8_t str[] = { + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* http/1.1 */ + }; + + /* Setup in order to test ALPN. */ + CHECK(! SSL_set_alpn_protos(s, str, 9)); + SSL_CTX_set_alpn_select_cb(s->ctx, dummy_alpn_cb, NULL); + + /* Prerequisites to test these. */ + CHECK(s->alpn_client_proto_list != NULL); + CHECK(s->ctx->alpn_select_cb != NULL); + //CHECK(s->s3->tmp.finish_md_len == 0); + + /* None of these are valid for client or server */ + CHECK_BOTH(0, 0, proto_invalid_len1); + CHECK_BOTH(0, 0, proto_invalid_len2); + CHECK_BOTH(0, 0, proto_invalid_len3); + CHECK_BOTH(0, 0, proto_invalid_len4); + CHECK_BOTH(0, 0, proto_invalid_len5); + CHECK_BOTH(0, 0, proto_invalid_len6); + CHECK_BOTH(0, 0, proto_invalid_len7); + CHECK_BOTH(0, 0, proto_invalid_len8); + CHECK_BOTH(0, 0, proto_invalid_missing1); + CHECK_BOTH(0, 0, proto_invalid_missing2); + CHECK_BOTH(0, 0, proto_invalid_missing3); + CHECK_BOTH(0, 0, proto_invalid_missing4); + CHECK_BOTH(0, 0, proto_invalid_missing5); + CHECK_BOTH(0, 0, proto_invalid_missing6); + CHECK_BOTH(0, 0, proto_invalid_missing7); + CHECK_BOTH(0, 0, proto_invalid_missing8); + CHECK_BOTH(0, 0, proto_invalid_missing9); + + return 1; +} + +int +dummy_alpn_cb(SSL *ssl __attribute__((unused)), const unsigned char **out, + unsigned char *outlen, const unsigned char *in, unsigned int inlen, + void *arg __attribute__((unused))) +{ + *out = in; + *outlen = (unsigned char)inlen; + + return 0; +} + +int +main(void) +{ + SSL_CTX *ctx = NULL; + SSL *s = NULL; + int rv = 1; + + SSL_library_init(); + + CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL); + CHECK_GOTO((s = SSL_new(ctx)) != NULL); + + if (!check_valid_alpn(s)) + goto err; + if (!check_invalid_alpn(s)) + goto err; + + rv = 0; + +err: + SSL_CTX_free(ctx); + SSL_free(s); + + if (!rv) + printf("PASS %s\n", __FILE__); + return rv; +} diff --git a/tests/tls_prf.c b/tests/tls_prf.c new file mode 100644 index 0000000..a22d0e7 --- /dev/null +++ b/tests/tls_prf.c @@ -0,0 +1,251 @@ +/* $OpenBSD: tls_prf.c,v 1.8 2022/11/26 16:08:57 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ssl_local.h" + +int tls1_PRF(SSL *s, const unsigned char *secret, size_t secret_len, + const void *seed1, size_t seed1_len, const void *seed2, size_t seed2_len, + const void *seed3, size_t seed3_len, const void *seed4, size_t seed4_len, + const void *seed5, size_t seed5_len, unsigned char *out, size_t out_len); + +#define TLS_PRF_OUT_LEN 128 + +struct tls_prf_test { + const unsigned char *desc; + const SSL_METHOD *(*ssl_method)(void); + const uint16_t cipher_value; + const unsigned char out[TLS_PRF_OUT_LEN]; +}; + +static struct tls_prf_test tls_prf_tests[] = { + { + .desc = "MD5+SHA1", + .ssl_method = TLSv1_method, + .cipher_value = 0x0033, + .out = { + 0x03, 0xa1, 0xc1, 0x7d, 0x2c, 0xa5, 0x3d, 0xe8, + 0x9d, 0x59, 0x5e, 0x30, 0xf5, 0x71, 0xbb, 0x96, + 0xde, 0x5c, 0x8e, 0xdc, 0x25, 0x8a, 0x7c, 0x05, + 0x9f, 0x7d, 0x35, 0x29, 0x45, 0xae, 0x56, 0xad, + 0x9f, 0x57, 0x15, 0x5c, 0xdb, 0x83, 0x3a, 0xac, + 0x19, 0xa8, 0x2b, 0x40, 0x72, 0x38, 0x1e, 0xed, + 0xf3, 0x25, 0xde, 0x84, 0x84, 0xd8, 0xd1, 0xfc, + 0x31, 0x85, 0x81, 0x12, 0x55, 0x4d, 0x12, 0xb5, + 0xed, 0x78, 0x5e, 0xba, 0xc8, 0xec, 0x8d, 0x28, + 0xa1, 0x21, 0x1e, 0x6e, 0x07, 0xf1, 0xfc, 0xf5, + 0xbf, 0xe4, 0x8e, 0x8e, 0x97, 0x15, 0x93, 0x85, + 0x75, 0xdd, 0x87, 0x09, 0xd0, 0x4e, 0xe5, 0xd5, + 0x9e, 0x1f, 0xd6, 0x1c, 0x3b, 0xe9, 0xad, 0xba, + 0xe0, 0x16, 0x56, 0x62, 0x90, 0xd6, 0x82, 0x84, + 0xec, 0x8a, 0x22, 0xbe, 0xdc, 0x6a, 0x5e, 0x05, + 0x12, 0x44, 0xec, 0x60, 0x61, 0xd1, 0x8a, 0x66, + }, + }, + { + .desc = "GOST94", + .ssl_method = TLSv1_2_method, + .cipher_value = 0x0081, + .out = { + 0xcc, 0xd4, 0x89, 0x5f, 0x52, 0x08, 0x9b, 0xc7, + 0xf9, 0xb5, 0x83, 0x58, 0xe8, 0xc7, 0x71, 0x49, + 0x39, 0x99, 0x1f, 0x14, 0x8f, 0x85, 0xbe, 0x64, + 0xee, 0x40, 0x5c, 0xe7, 0x5f, 0x68, 0xaf, 0xf2, + 0xcd, 0x3a, 0x94, 0x52, 0x33, 0x53, 0x46, 0x7d, + 0xb6, 0xc5, 0xe1, 0xb8, 0xa4, 0x04, 0x69, 0x91, + 0x0a, 0x9c, 0x88, 0x86, 0xd9, 0x60, 0x63, 0xdd, + 0xd8, 0xe7, 0x2e, 0xee, 0xce, 0xe2, 0x20, 0xd8, + 0x9a, 0xfa, 0x9c, 0x63, 0x0c, 0x9c, 0xa1, 0x76, + 0xed, 0x78, 0x9a, 0x84, 0x70, 0xb4, 0xd1, 0x51, + 0x1f, 0xde, 0x44, 0xe8, 0x90, 0x21, 0x3f, 0xeb, + 0x05, 0xf4, 0x77, 0x59, 0xf3, 0xad, 0xdd, 0x34, + 0x3d, 0x3a, 0x7c, 0xd0, 0x59, 0x40, 0xe1, 0x3f, + 0x04, 0x4b, 0x8b, 0xd6, 0x95, 0x46, 0xb4, 0x9e, + 0x4c, 0x2d, 0xf7, 0xee, 0xbd, 0xbc, 0xcb, 0x5c, + 0x3a, 0x36, 0x0c, 0xd0, 0x27, 0xcb, 0x45, 0x06, + }, + }, + { + .desc = "SHA256 (via TLSv1.2)", + .ssl_method = TLSv1_2_method, + .cipher_value = 0x0033, + .out = { + 0x37, 0xa7, 0x06, 0x71, 0x6e, 0x19, 0x19, 0xda, + 0x23, 0x8c, 0xcc, 0xb4, 0x2f, 0x31, 0x64, 0x9d, + 0x05, 0x29, 0x1c, 0x33, 0x7e, 0x09, 0x1b, 0x0c, + 0x0e, 0x23, 0xc1, 0xb0, 0x40, 0xcc, 0x31, 0xf7, + 0x55, 0x66, 0x68, 0xd9, 0xa8, 0xae, 0x74, 0x75, + 0xf3, 0x46, 0xe9, 0x3a, 0x54, 0x9d, 0xe0, 0x8b, + 0x7e, 0x6c, 0x63, 0x1c, 0xfa, 0x2f, 0xfd, 0xc9, + 0xd3, 0xf1, 0xd3, 0xfe, 0x7b, 0x9e, 0x14, 0x95, + 0xb5, 0xd0, 0xad, 0x9b, 0xee, 0x78, 0x8c, 0x83, + 0x18, 0x58, 0x7e, 0xa2, 0x23, 0xc1, 0x8b, 0x62, + 0x94, 0x12, 0xcb, 0xb6, 0x60, 0x69, 0x32, 0xfe, + 0x98, 0x0e, 0x93, 0xb0, 0x8e, 0x5c, 0xfb, 0x6e, + 0xdb, 0x9a, 0xc2, 0x9f, 0x8c, 0x5c, 0x43, 0x19, + 0xeb, 0x4a, 0x52, 0xad, 0x62, 0x2b, 0xdd, 0x9f, + 0xa3, 0x74, 0xa6, 0x96, 0x61, 0x4d, 0x98, 0x40, + 0x63, 0xa6, 0xd4, 0xbb, 0x17, 0x11, 0x75, 0xed, + }, + }, + { + .desc = "SHA384", + .ssl_method = TLSv1_2_method, + .cipher_value = 0x009d, + .out = { + 0x00, 0x93, 0xc3, 0xfd, 0xa7, 0xbb, 0xdc, 0x5b, + 0x13, 0x3a, 0xe6, 0x8b, 0x1b, 0xac, 0xf3, 0xfb, + 0x3c, 0x9a, 0x78, 0xf6, 0x19, 0xf0, 0x13, 0x0f, + 0x0d, 0x01, 0x9d, 0xdf, 0x0a, 0x28, 0x38, 0xce, + 0x1a, 0x9b, 0x43, 0xbe, 0x56, 0x12, 0xa7, 0x16, + 0x58, 0xe1, 0x8a, 0xe4, 0xc5, 0xbb, 0x10, 0x4c, + 0x3a, 0xf3, 0x7f, 0xd3, 0xdb, 0xe4, 0xe0, 0x3d, + 0xcc, 0x83, 0xca, 0xf0, 0xf9, 0x69, 0xcc, 0x70, + 0x83, 0x32, 0xf6, 0xfc, 0x81, 0x80, 0x02, 0xe8, + 0x31, 0x1e, 0x7c, 0x3b, 0x34, 0xf7, 0x34, 0xd1, + 0xcf, 0x2a, 0xc4, 0x36, 0x2f, 0xe9, 0xaa, 0x7f, + 0x6d, 0x1f, 0x5e, 0x0e, 0x39, 0x05, 0x15, 0xe1, + 0xa2, 0x9a, 0x4d, 0x97, 0x8c, 0x62, 0x46, 0xf1, + 0x87, 0x65, 0xd8, 0xe9, 0x14, 0x11, 0xa6, 0x48, + 0xd7, 0x0e, 0x6e, 0x70, 0xad, 0xfb, 0x3f, 0x36, + 0x05, 0x76, 0x4b, 0xe4, 0x28, 0x50, 0x4a, 0xf2, + }, + }, + { + .desc = "STREEBOG256", + .ssl_method = TLSv1_2_method, + .cipher_value = 0xff87, + .out = { + 0x3e, 0x13, 0xb9, 0xeb, 0x85, 0x8c, 0xb4, 0x21, + 0x23, 0x40, 0x9b, 0x73, 0x04, 0x56, 0xe2, 0xff, + 0xce, 0x52, 0x1f, 0x82, 0x7f, 0x17, 0x5b, 0x80, + 0x23, 0x71, 0xca, 0x30, 0xdf, 0xfc, 0xdc, 0x2d, + 0xc0, 0xfc, 0x5d, 0x23, 0x5a, 0x54, 0x7f, 0xae, + 0xf5, 0x7d, 0x52, 0x1e, 0x86, 0x95, 0xe1, 0x2d, + 0x28, 0xe7, 0xbe, 0xd7, 0xd0, 0xbf, 0xa9, 0x96, + 0x13, 0xd0, 0x9c, 0x0c, 0x1c, 0x16, 0x05, 0xbb, + 0x26, 0xd7, 0x30, 0x39, 0xb9, 0x53, 0x28, 0x98, + 0x4f, 0x1b, 0x83, 0xc3, 0xce, 0x1c, 0x7c, 0x34, + 0xa2, 0xc4, 0x7a, 0x54, 0x16, 0xc6, 0xa7, 0x9e, + 0xed, 0x4b, 0x7b, 0x83, 0xa6, 0xae, 0xe2, 0x5b, + 0x96, 0xf5, 0x6c, 0xad, 0x1f, 0xa3, 0x83, 0xb2, + 0x84, 0x32, 0xed, 0xe3, 0x2c, 0xf6, 0xd4, 0x73, + 0x30, 0xef, 0x9d, 0xbe, 0xe7, 0x23, 0x9a, 0xbf, + 0x4d, 0x1c, 0xe7, 0xef, 0x3d, 0xea, 0x46, 0xe2, + }, + }, +}; + +#define N_TLS_PRF_TESTS \ + (sizeof(tls_prf_tests) / sizeof(*tls_prf_tests)) + +#define TLS_PRF_SEED1 "tls prf seed 1" +#define TLS_PRF_SEED2 "tls prf seed 2" +#define TLS_PRF_SEED3 "tls prf seed 3" +#define TLS_PRF_SEED4 "tls prf seed 4" +#define TLS_PRF_SEED5 "tls prf seed 5" +#define TLS_PRF_SECRET "tls prf secretz" + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +do_tls_prf_test(int test_no, struct tls_prf_test *tpt) +{ + unsigned char *out = NULL; + const SSL_CIPHER *cipher; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failure = 1; + int len; + + fprintf(stderr, "Test %d - %s\n", test_no, tpt->desc); + + if ((out = malloc(TLS_PRF_OUT_LEN)) == NULL) + errx(1, "failed to allocate out"); + + if ((ssl_ctx = SSL_CTX_new(tpt->ssl_method())) == NULL) + errx(1, "failed to create SSL context"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL context"); + + if ((cipher = ssl3_get_cipher_by_value(tpt->cipher_value)) == NULL) { + fprintf(stderr, "FAIL: no cipher %hx\n", tpt->cipher_value); + goto failure; + } + + ssl->s3->hs.cipher = cipher; + + for (len = 1; len <= TLS_PRF_OUT_LEN; len++) { + memset(out, 'A', TLS_PRF_OUT_LEN); + + if (tls1_PRF(ssl, TLS_PRF_SECRET, sizeof(TLS_PRF_SECRET), + TLS_PRF_SEED1, sizeof(TLS_PRF_SEED1), TLS_PRF_SEED2, + sizeof(TLS_PRF_SEED2), TLS_PRF_SEED3, sizeof(TLS_PRF_SEED3), + TLS_PRF_SEED4, sizeof(TLS_PRF_SEED4), TLS_PRF_SEED5, + sizeof(TLS_PRF_SEED5), out, len) != 1) { + fprintf(stderr, "FAIL: tls_PRF failed for len %d\n", + len); + goto failure; + } + + if (memcmp(out, tpt->out, len) != 0) { + fprintf(stderr, "FAIL: tls_PRF output differs for " + "len %d\n", len); + fprintf(stderr, "output:\n"); + hexdump(out, TLS_PRF_OUT_LEN); + fprintf(stderr, "test data:\n"); + hexdump(tpt->out, TLS_PRF_OUT_LEN); + fprintf(stderr, "\n"); + goto failure; + } + } + + failure = 0; + + failure: + SSL_free(ssl); + SSL_CTX_free(ssl_ctx); + + free(out); + + return failure; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + SSL_library_init(); + SSL_load_error_strings(); + + for (i = 0; i < N_TLS_PRF_TESTS; i++) + failed |= do_tls_prf_test(i, &tls_prf_tests[i]); + + return failed; +} diff --git a/tests/tlsexttest.c b/tests/tlsexttest.c new file mode 100644 index 0000000..e4da328 --- /dev/null +++ b/tests/tlsexttest.c @@ -0,0 +1,4613 @@ +/* $OpenBSD: tlsexttest.c,v 1.82 2023/07/05 17:30:14 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * Copyright (c) 2017 Doug Hogan + * Copyright (c) 2019 Bob Beck + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include "ssl_local.h" + +#include "bytestring.h" +#include "ssl_tlsext.h" + +struct tls_extension_funcs { + int (*needs)(SSL *s, uint16_t msg_type); + int (*build)(SSL *s, uint16_t msg_type, CBB *cbb); + int (*parse)(SSL *s, uint16_t msg_type, CBS *cbs, int *alert); +}; + +uint16_t tls_extension_type(const struct tls_extension *); +const struct tls_extension *tls_extension_find(uint16_t, size_t *); +const struct tls_extension_funcs *tlsext_funcs(const struct tls_extension *, + int); +int tlsext_linearize_build_order(SSL *); + +static int +tls_extension_funcs(int type, const struct tls_extension_funcs **client_funcs, + const struct tls_extension_funcs **server_funcs) +{ + const struct tls_extension *ext; + size_t idx; + + if ((ext = tls_extension_find(type, &idx)) == NULL) + return 0; + + if ((*client_funcs = tlsext_funcs(ext, 0)) == NULL) + return 0; + + if ((*server_funcs = tlsext_funcs(ext, 1)) == NULL) + return 0; + + return 1; +} + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static void +hexdump2(const uint16_t *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len / 2; i++) + fprintf(stderr, " 0x%04hx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static void +compare_data(const uint8_t *recv, size_t recv_len, const uint8_t *expect, + size_t expect_len) +{ + fprintf(stderr, "received:\n"); + hexdump(recv, recv_len); + + fprintf(stderr, "test data:\n"); + hexdump(expect, expect_len); +} + +static void +compare_data2(const uint16_t *recv, size_t recv_len, const uint16_t *expect, + size_t expect_len) +{ + fprintf(stderr, "received:\n"); + hexdump2(recv, recv_len); + + fprintf(stderr, "test data:\n"); + hexdump2(expect, expect_len); +} + +#define FAIL(msg, ...) \ +do { \ + fprintf(stderr, "[%s:%d] FAIL: ", __FILE__, __LINE__); \ + fprintf(stderr, msg, ##__VA_ARGS__); \ +} while(0) + +/* + * Supported Application-Layer Protocol Negotiation - RFC 7301 + * + * There are already extensive unit tests for this so this just + * tests the state info. + */ + +const uint8_t tlsext_alpn_multiple_protos_val[] = { + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */ + 0x09, /* len */ + 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e +}; + +const uint8_t tlsext_alpn_multiple_protos[] = { + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x13, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, + /* opaque ProtocolName<1..2^8-1> -- 'stun.nat' */ + 0x09, /* len */ + 0x73, 0x74, 0x75, 0x6e, 0x2e, 0x74, 0x75, 0x72, 0x6e +}; + +const uint8_t tlsext_alpn_single_proto_val[] = { + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 +}; + +const uint8_t tlsext_alpn_single_proto_name[] = { + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 /* 'http/1.1' */ +}; + +const uint8_t tlsext_alpn_single_proto[] = { + /* ProtocolName protocol_name_list<2..2^16-1> -- ALPN names */ + 0x00, 0x09, /* len of all names */ + /* opaque ProtocolName<1..2^8-1> -- 'http/1.1' */ + 0x08, /* len */ + 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 +}; + +#define TLSEXT_TYPE_alpn TLSEXT_TYPE_application_layer_protocol_negotiation + +static int +test_tlsext_alpn_client(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + uint8_t *data = NULL; + CBB cbb; + CBS cbs; + int failure, alert; + size_t dlen; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_alpn, &client_funcs, &server_funcs)) + errx(1, "failed to fetch ALPN funcs"); + + /* By default, we don't need this */ + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need ALPN by default\n"); + goto err; + } + + /* + * Prereqs: + * 1) Set s->alpn_client_proto_list + * - Using SSL_set_alpn_protos() + * 2) We have not finished or renegotiated. + * - s->s3->tmp.finish_md_len == 0 + */ + if (SSL_set_alpn_protos(ssl, tlsext_alpn_single_proto_val, + sizeof(tlsext_alpn_single_proto_val)) != 0) { + FAIL("should be able to set ALPN to http/1.1\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ALPN by default\n"); + goto err; + } + + /* Make sure we can build the client with a single proto. */ + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build ALPN\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_alpn_single_proto)) { + FAIL("got client ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_single_proto)); + compare_data(data, dlen, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + goto err; + } + if (memcmp(data, tlsext_alpn_single_proto, dlen) != 0) { + FAIL("client ALPN differs:\n"); + compare_data(data, dlen, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* Make sure we can parse the single proto. */ + + CBS_init(&cbs, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse ALPN\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->alpn_client_proto_list_len != + sizeof(tlsext_alpn_single_proto_val)) { + FAIL("got client ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_single_proto_val)); + compare_data(ssl->alpn_client_proto_list, + ssl->alpn_client_proto_list_len, + tlsext_alpn_single_proto_val, + sizeof(tlsext_alpn_single_proto_val)); + goto err; + } + if (memcmp(ssl->alpn_client_proto_list, + tlsext_alpn_single_proto_val, + sizeof(tlsext_alpn_single_proto_val)) != 0) { + FAIL("client ALPN differs:\n"); + compare_data(data, dlen, tlsext_alpn_single_proto_val, + sizeof(tlsext_alpn_single_proto_val)); + goto err; + } + + /* Make sure we can build the clienthello with multiple entries. */ + + if (SSL_set_alpn_protos(ssl, tlsext_alpn_multiple_protos_val, + sizeof(tlsext_alpn_multiple_protos_val)) != 0) { + FAIL("should be able to set ALPN to http/1.1\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ALPN by now\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build ALPN\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_alpn_multiple_protos)) { + FAIL("got client ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_multiple_protos)); + compare_data(data, dlen, tlsext_alpn_multiple_protos, + sizeof(tlsext_alpn_multiple_protos)); + goto err; + } + if (memcmp(data, tlsext_alpn_multiple_protos, dlen) != 0) { + FAIL("client ALPN differs:\n"); + compare_data(data, dlen, tlsext_alpn_multiple_protos, + sizeof(tlsext_alpn_multiple_protos)); + goto err; + } + + /* Make sure we can parse multiple protos */ + + CBS_init(&cbs, tlsext_alpn_multiple_protos, + sizeof(tlsext_alpn_multiple_protos)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse ALPN\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->alpn_client_proto_list_len != + sizeof(tlsext_alpn_multiple_protos_val)) { + FAIL("got client ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_multiple_protos_val)); + compare_data(ssl->alpn_client_proto_list, + ssl->alpn_client_proto_list_len, + tlsext_alpn_multiple_protos_val, + sizeof(tlsext_alpn_multiple_protos_val)); + goto err; + } + if (memcmp(ssl->alpn_client_proto_list, + tlsext_alpn_multiple_protos_val, + sizeof(tlsext_alpn_multiple_protos_val)) != 0) { + FAIL("client ALPN differs:\n"); + compare_data(data, dlen, tlsext_alpn_multiple_protos_val, + sizeof(tlsext_alpn_multiple_protos_val)); + goto err; + } + + /* Make sure we can remove the list and avoid ALPN */ + + free(ssl->alpn_client_proto_list); + ssl->alpn_client_proto_list = NULL; + ssl->alpn_client_proto_list_len = 0; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ALPN by default\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_alpn_server(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + uint8_t *data = NULL; + CBB cbb; + CBS cbs; + int failure, alert; + size_t dlen; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_alpn, &client_funcs, &server_funcs)) + errx(1, "failed to fetch ALPN funcs"); + + /* By default, ALPN isn't needed. */ + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need ALPN by default\n"); + goto err; + } + + /* + * The server has a single ALPN selection which is set by + * SSL_CTX_set_alpn_select_cb() and calls SSL_select_next_proto(). + * + * This will be a plain name and separate length. + */ + if ((ssl->s3->alpn_selected = malloc(sizeof(tlsext_alpn_single_proto_name))) == NULL) { + errx(1, "failed to malloc"); + } + memcpy(ssl->s3->alpn_selected, tlsext_alpn_single_proto_name, + sizeof(tlsext_alpn_single_proto_name)); + ssl->s3->alpn_selected_len = sizeof(tlsext_alpn_single_proto_name); + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need ALPN after a protocol is selected\n"); + goto err; + } + + /* Make sure we can build a server with one protocol */ + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server should be able to build a response\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_alpn_single_proto)) { + FAIL("got client ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_single_proto)); + compare_data(data, dlen, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + goto err; + } + if (memcmp(data, tlsext_alpn_single_proto, dlen) != 0) { + FAIL("client ALPN differs:\n"); + compare_data(data, dlen, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* Make sure we can parse the single proto. */ + + CBS_init(&cbs, tlsext_alpn_single_proto, + sizeof(tlsext_alpn_single_proto)); + + /* Shouldn't be able to parse without requesting */ + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("Should only parse server if we requested it\n"); + goto err; + } + + /* Should be able to parse once requested. */ + if (SSL_set_alpn_protos(ssl, tlsext_alpn_single_proto_val, + sizeof(tlsext_alpn_single_proto_val)) != 0) { + FAIL("should be able to set ALPN to http/1.1\n"); + goto err; + } + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("Should be able to parse server when we request it\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->alpn_selected_len != + sizeof(tlsext_alpn_single_proto_name)) { + FAIL("got server ALPN with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_alpn_single_proto_name)); + compare_data(ssl->s3->alpn_selected, + ssl->s3->alpn_selected_len, + tlsext_alpn_single_proto_name, + sizeof(tlsext_alpn_single_proto_name)); + goto err; + } + if (memcmp(ssl->s3->alpn_selected, + tlsext_alpn_single_proto_name, + sizeof(tlsext_alpn_single_proto_name)) != 0) { + FAIL("server ALPN differs:\n"); + compare_data(ssl->s3->alpn_selected, + ssl->s3->alpn_selected_len, + tlsext_alpn_single_proto_name, + sizeof(tlsext_alpn_single_proto_name)); + goto err; + } + + /* + * We should NOT be able to build a server with multiple + * protocol names. However, the existing code did not check for this + * case because it is passed in as an encoded value. + */ + + /* Make sure we can remove the list and avoid ALPN */ + + free(ssl->s3->alpn_selected); + ssl->s3->alpn_selected = NULL; + ssl->s3->alpn_selected_len = 0; + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need ALPN by default\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); + +} + +/* + * Supported Elliptic Curves - RFC 4492 section 5.1.1. + * + * This extension is only used by the client. + */ + +static const uint8_t tlsext_supportedgroups_client_default[] = { + 0x00, 0x08, + 0x00, 0x1d, /* X25519 (29) */ + 0x00, 0x17, /* secp256r1 (23) */ + 0x00, 0x18, /* secp384r1 (24) */ + 0x00, 0x19, /* secp521r1 (25) */ +}; + +static const uint16_t tlsext_supportedgroups_client_secp384r1_val[] = { + 0x0018 /* tls1_ec_nid2group_id(NID_secp384r1) */ +}; +static const uint8_t tlsext_supportedgroups_client_secp384r1[] = { + 0x00, 0x02, + 0x00, 0x18 /* secp384r1 (24) */ +}; + +/* Example from RFC 4492 section 5.1.1 */ +static const uint16_t tlsext_supportedgroups_client_nistp192and224_val[] = { + 0x0013, /* tls1_ec_nid2group_id(NID_X9_62_prime192v1) */ + 0x0015 /* tls1_ec_nid2group_id(NID_secp224r1) */ +}; +static const uint8_t tlsext_supportedgroups_client_nistp192and224[] = { + 0x00, 0x04, + 0x00, 0x13, /* secp192r1 aka NIST P-192 */ + 0x00, 0x15 /* secp224r1 aka NIST P-224 */ +}; + +static int +test_tlsext_supportedgroups_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure, alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_supported_groups, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch supported groups funcs"); + + /* + * Default ciphers include EC so we need it by default. + */ + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need Ellipticcurves for default " + "ciphers\n"); + goto err; + } + + /* + * Exclude cipher suites so we can test not including it. + */ + if (!SSL_set_cipher_list(ssl, "TLSv1.2:!ECDHE:!ECDSA")) { + FAIL("client should be able to set cipher list\n"); + goto err; + } + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need Ellipticcurves\n"); + goto err; + } + + /* + * Use libtls default for the rest of the testing + */ + if (!SSL_set_cipher_list(ssl, "TLSv1.2+AEAD+ECDHE")) { + FAIL("client should be able to set cipher list\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need Ellipticcurves\n"); + goto err; + } + + /* + * Test with a session secp384r1. The default is used instead. + */ + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if ((ssl->session->tlsext_supportedgroups = malloc(sizeof(uint16_t))) + == NULL) { + FAIL("client could not malloc\n"); + goto err; + } + if (!tls1_ec_nid2group_id(NID_secp384r1, + &ssl->session->tlsext_supportedgroups[0])) + goto err; + ssl->session->tlsext_supportedgroups_length = 1; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need Ellipticcurves\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build Ellipticcurves\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_supportedgroups_client_default)) { + FAIL("got client Ellipticcurves with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_supportedgroups_client_default)); + compare_data(data, dlen, tlsext_supportedgroups_client_default, + sizeof(tlsext_supportedgroups_client_default)); + goto err; + } + + if (memcmp(data, tlsext_supportedgroups_client_default, dlen) != 0) { + FAIL("client Ellipticcurves differs:\n"); + compare_data(data, dlen, tlsext_supportedgroups_client_default, + sizeof(tlsext_supportedgroups_client_default)); + goto err; + } + + /* + * Test parsing secp384r1 + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + CBS_init(&cbs, tlsext_supportedgroups_client_secp384r1, + sizeof(tlsext_supportedgroups_client_secp384r1)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client Ellipticcurves\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_supportedgroups_length != + sizeof(tlsext_supportedgroups_client_secp384r1_val) / sizeof(uint16_t)) { + FAIL("no tlsext_ellipticcurves from client " + "Ellipticcurves\n"); + goto err; + } + + if (memcmp(ssl->session->tlsext_supportedgroups, + tlsext_supportedgroups_client_secp384r1_val, + sizeof(tlsext_supportedgroups_client_secp384r1_val)) != 0) { + FAIL("client had an incorrect Ellipticcurves " + "entry\n"); + compare_data2(ssl->session->tlsext_supportedgroups, + ssl->session->tlsext_supportedgroups_length * 2, + tlsext_supportedgroups_client_secp384r1_val, + sizeof(tlsext_supportedgroups_client_secp384r1_val)); + goto err; + } + + /* + * Use a custom order. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if ((ssl->tlsext_supportedgroups = malloc(sizeof(uint16_t) * 2)) == NULL) { + FAIL("client could not malloc\n"); + goto err; + } + if (!tls1_ec_nid2group_id(NID_X9_62_prime192v1, + &ssl->tlsext_supportedgroups[0])) + goto err; + if (!tls1_ec_nid2group_id(NID_secp224r1, + &ssl->tlsext_supportedgroups[1])) + goto err; + ssl->tlsext_supportedgroups_length = 2; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need Ellipticcurves\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build Ellipticcurves\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_supportedgroups_client_nistp192and224)) { + FAIL("got client Ellipticcurves with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_supportedgroups_client_nistp192and224)); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_supportedgroups_client_nistp192and224, + sizeof(tlsext_supportedgroups_client_nistp192and224)); + goto err; + } + + if (memcmp(data, tlsext_supportedgroups_client_nistp192and224, dlen) != 0) { + FAIL("client Ellipticcurves differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_supportedgroups_client_nistp192and224, + sizeof(tlsext_supportedgroups_client_nistp192and224)); + goto err; + } + + /* + * Parse non-default curves to session. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + /* Reset back to the default list. */ + free(ssl->tlsext_supportedgroups); + ssl->tlsext_supportedgroups = NULL; + ssl->tlsext_supportedgroups_length = 0; + + CBS_init(&cbs, tlsext_supportedgroups_client_nistp192and224, + sizeof(tlsext_supportedgroups_client_nistp192and224)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client Ellipticcurves\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_supportedgroups_length != + sizeof(tlsext_supportedgroups_client_nistp192and224_val) / sizeof(uint16_t)) { + FAIL("no tlsext_ellipticcurves from client Ellipticcurves\n"); + goto err; + } + + if (memcmp(ssl->session->tlsext_supportedgroups, + tlsext_supportedgroups_client_nistp192and224_val, + sizeof(tlsext_supportedgroups_client_nistp192and224_val)) != 0) { + FAIL("client had an incorrect Ellipticcurves entry\n"); + compare_data2(ssl->session->tlsext_supportedgroups, + ssl->session->tlsext_supportedgroups_length * 2, + tlsext_supportedgroups_client_nistp192and224_val, + sizeof(tlsext_supportedgroups_client_nistp192and224_val)); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + + +/* elliptic_curves is only used by the client so this doesn't test much. */ +static int +test_tlsext_supportedgroups_server(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + + failure = 1; + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_supported_groups, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch supported groups funcs"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need elliptic_curves\n"); + goto err; + } + + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need elliptic_curves\n"); + goto err; + } + + failure = 0; + + err: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return (failure); + +} + +/* + * Supported Point Formats - RFC 4492 section 5.1.2. + * + * Examples are from the RFC. Both client and server have the same build and + * parse but the needs differ. + */ + +static const uint8_t tlsext_ecpf_hello_uncompressed_val[] = { + TLSEXT_ECPOINTFORMAT_uncompressed +}; +static const uint8_t tlsext_ecpf_hello_uncompressed[] = { + 0x01, + 0x00 /* TLSEXT_ECPOINTFORMAT_uncompressed */ +}; + +static const uint8_t tlsext_ecpf_hello_prime[] = { + 0x01, + 0x01 /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime */ +}; + +static const uint8_t tlsext_ecpf_hello_prefer_order_val[] = { + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, + TLSEXT_ECPOINTFORMAT_uncompressed, + TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 +}; +static const uint8_t tlsext_ecpf_hello_prefer_order[] = { + 0x03, + 0x01, /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime */ + 0x00, /* TLSEXT_ECPOINTFORMAT_uncompressed */ + 0x02 /* TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 */ +}; + +static int +test_tlsext_ecpf_client(void) +{ + uint8_t *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure, alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_ec_point_formats, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ecpf funcs"); + + /* + * Default ciphers include EC so we need it by default. + */ + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ECPointFormats for default " + "ciphers\n"); + goto err; + } + + /* + * Exclude EC cipher suites so we can test not including it. + */ + if (!SSL_set_cipher_list(ssl, "ALL:!ECDHE:!ECDH")) { + FAIL("client should be able to set cipher list\n"); + goto err; + } + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need ECPointFormats\n"); + goto err; + } + + /* + * Use libtls default for the rest of the testing + */ + if (!SSL_set_cipher_list(ssl, "TLSv1.2+AEAD+ECDHE")) { + FAIL("client should be able to set cipher list\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ECPointFormats\n"); + goto err; + } + + /* + * The default ECPointFormats should only have uncompressed + */ + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build ECPointFormats\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ecpf_hello_uncompressed)) { + FAIL("got client ECPointFormats with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_ecpf_hello_uncompressed)); + compare_data(data, dlen, tlsext_ecpf_hello_uncompressed, + sizeof(tlsext_ecpf_hello_uncompressed)); + goto err; + } + + if (memcmp(data, tlsext_ecpf_hello_uncompressed, dlen) != 0) { + FAIL("client ECPointFormats differs:\n"); + compare_data(data, dlen, tlsext_ecpf_hello_uncompressed, + sizeof(tlsext_ecpf_hello_uncompressed)); + goto err; + } + + /* + * Make sure we can parse the default. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + CBS_init(&cbs, tlsext_ecpf_hello_uncompressed, + sizeof(tlsext_ecpf_hello_uncompressed)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client ECPointFormats\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_ecpointformatlist_length != + sizeof(tlsext_ecpf_hello_uncompressed_val)) { + FAIL("no tlsext_ecpointformats from client " + "ECPointFormats\n"); + goto err; + } + + if (memcmp(ssl->session->tlsext_ecpointformatlist, + tlsext_ecpf_hello_uncompressed_val, + sizeof(tlsext_ecpf_hello_uncompressed_val)) != 0) { + FAIL("client had an incorrect ECPointFormats entry\n"); + goto err; + } + + /* + * Test with a custom order. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if ((ssl->tlsext_ecpointformatlist = malloc(sizeof(uint8_t) * 3)) == NULL) { + FAIL("client could not malloc\n"); + goto err; + } + ssl->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + ssl->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_uncompressed; + ssl->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + ssl->tlsext_ecpointformatlist_length = 3; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need ECPointFormats with a custom " + "format\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build ECPointFormats\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ecpf_hello_prefer_order)) { + FAIL("got client ECPointFormats with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_ecpf_hello_prefer_order)); + compare_data(data, dlen, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + goto err; + } + + if (memcmp(data, tlsext_ecpf_hello_prefer_order, dlen) != 0) { + FAIL("client ECPointFormats differs:\n"); + compare_data(data, dlen, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + goto err; + } + + /* + * Make sure that we can parse this custom order. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + /* Reset the custom list so we go back to the default uncompressed. */ + free(ssl->tlsext_ecpointformatlist); + ssl->tlsext_ecpointformatlist = NULL; + ssl->tlsext_ecpointformatlist_length = 0; + + CBS_init(&cbs, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client ECPointFormats\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_ecpointformatlist_length != + sizeof(tlsext_ecpf_hello_prefer_order_val)) { + FAIL("no tlsext_ecpointformats from client " + "ECPointFormats\n"); + goto err; + } + + if (memcmp(ssl->session->tlsext_ecpointformatlist, + tlsext_ecpf_hello_prefer_order_val, + sizeof(tlsext_ecpf_hello_prefer_order_val)) != 0) { + FAIL("client had an incorrect ECPointFormats entry\n"); + goto err; + } + + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_ecpf_server(void) +{ + uint8_t *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure, alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_ec_point_formats, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ecpf funcs"); + + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + /* Setup the state so we can call needs. */ + if ((ssl->s3->hs.cipher = + ssl3_get_cipher_by_id(TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305)) + == NULL) { + FAIL("server cannot find cipher\n"); + goto err; + } + if ((ssl->session->tlsext_ecpointformatlist = malloc(sizeof(uint8_t))) + == NULL) { + FAIL("server could not malloc\n"); + goto err; + } + ssl->session->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + ssl->session->tlsext_ecpointformatlist_length = 1; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need ECPointFormats now\n"); + goto err; + } + + /* + * The server will ignore the session list and use either a custom + * list or the default (uncompressed). + */ + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build ECPointFormats\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ecpf_hello_uncompressed)) { + FAIL("got server ECPointFormats with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_ecpf_hello_uncompressed)); + compare_data(data, dlen, tlsext_ecpf_hello_uncompressed, + sizeof(tlsext_ecpf_hello_uncompressed)); + goto err; + } + + if (memcmp(data, tlsext_ecpf_hello_uncompressed, dlen) != 0) { + FAIL("server ECPointFormats differs:\n"); + compare_data(data, dlen, tlsext_ecpf_hello_uncompressed, + sizeof(tlsext_ecpf_hello_uncompressed)); + goto err; + } + + /* + * Cannot parse a non-default list without at least uncompressed. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + CBS_init(&cbs, tlsext_ecpf_hello_prime, + sizeof(tlsext_ecpf_hello_prime)); + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("must include uncompressed in server ECPointFormats\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + /* + * Test with a custom order that replaces the default uncompressed. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + /* Add a session list even though it will be ignored. */ + if ((ssl->session->tlsext_ecpointformatlist = malloc(sizeof(uint8_t))) + == NULL) { + FAIL("server could not malloc\n"); + goto err; + } + ssl->session->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + ssl->session->tlsext_ecpointformatlist_length = 1; + + /* Replace the default list with a custom one. */ + if ((ssl->tlsext_ecpointformatlist = malloc(sizeof(uint8_t) * 3)) == NULL) { + FAIL("server could not malloc\n"); + goto err; + } + ssl->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime; + ssl->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_uncompressed; + ssl->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2; + ssl->tlsext_ecpointformatlist_length = 3; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need ECPointFormats\n"); + goto err; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build ECPointFormats\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ecpf_hello_prefer_order)) { + FAIL("got server ECPointFormats with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_ecpf_hello_prefer_order)); + compare_data(data, dlen, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + goto err; + } + + if (memcmp(data, tlsext_ecpf_hello_prefer_order, dlen) != 0) { + FAIL("server ECPointFormats differs:\n"); + compare_data(data, dlen, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + goto err; + } + + /* + * Should be able to parse the custom list into a session list. + */ + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + /* Reset back to the default (uncompressed) */ + free(ssl->tlsext_ecpointformatlist); + ssl->tlsext_ecpointformatlist = NULL; + ssl->tlsext_ecpointformatlist_length = 0; + + CBS_init(&cbs, tlsext_ecpf_hello_prefer_order, + sizeof(tlsext_ecpf_hello_prefer_order)); + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse server ECPointFormats\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_ecpointformatlist_length != + sizeof(tlsext_ecpf_hello_prefer_order_val)) { + FAIL("no tlsext_ecpointformats from server " + "ECPointFormats\n"); + goto err; + } + + if (memcmp(ssl->session->tlsext_ecpointformatlist, + tlsext_ecpf_hello_prefer_order_val, + sizeof(tlsext_ecpf_hello_prefer_order_val)) != 0) { + FAIL("server had an incorrect ECPointFormats entry\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +/* + * Renegotiation Indication - RFC 5746. + */ + +static const unsigned char tlsext_ri_prev_client[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, +}; + +static const unsigned char tlsext_ri_prev_server[] = { + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, +}; + +static const unsigned char tlsext_ri_client[] = { + 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, +}; + +static const unsigned char tlsext_ri_server[] = { + 0x20, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, +}; + +static int +test_tlsext_ri_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLSv1_2_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_renegotiate, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ri funcs"); + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need RI\n"); + goto err; + } + + if (!SSL_renegotiate(ssl)) { + FAIL("client failed to set renegotiate\n"); + goto err; + } + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need RI\n"); + goto err; + } + + memcpy(ssl->s3->previous_client_finished, tlsext_ri_prev_client, + sizeof(tlsext_ri_prev_client)); + ssl->s3->previous_client_finished_len = sizeof(tlsext_ri_prev_client); + + ssl->s3->renegotiate_seen = 0; + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build RI\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ri_client)) { + FAIL("got client RI with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_ri_client)); + goto err; + } + + if (memcmp(data, tlsext_ri_client, dlen) != 0) { + FAIL("client RI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_ri_client, sizeof(tlsext_ri_client)); + goto err; + } + + CBS_init(&cbs, tlsext_ri_client, sizeof(tlsext_ri_client)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client RI\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->renegotiate_seen != 1) { + FAIL("renegotiate seen not set\n"); + goto err; + } + if (ssl->s3->send_connection_binding != 1) { + FAIL("send connection binding not set\n"); + goto err; + } + + memset(ssl->s3->previous_client_finished, 0, + sizeof(ssl->s3->previous_client_finished)); + + ssl->s3->renegotiate_seen = 0; + + CBS_init(&cbs, tlsext_ri_client, sizeof(tlsext_ri_client)); + if (server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("parsed invalid client RI\n"); + goto err; + } + + if (ssl->s3->renegotiate_seen == 1) { + FAIL("renegotiate seen set\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_ri_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_renegotiate, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ri funcs"); + + ssl->version = TLS1_2_VERSION; + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need RI\n"); + goto err; + } + + ssl->s3->send_connection_binding = 1; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need RI\n"); + goto err; + } + + memcpy(ssl->s3->previous_client_finished, tlsext_ri_prev_client, + sizeof(tlsext_ri_prev_client)); + ssl->s3->previous_client_finished_len = sizeof(tlsext_ri_prev_client); + + memcpy(ssl->s3->previous_server_finished, tlsext_ri_prev_server, + sizeof(tlsext_ri_prev_server)); + ssl->s3->previous_server_finished_len = sizeof(tlsext_ri_prev_server); + + ssl->s3->renegotiate_seen = 0; + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build RI\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_ri_server)) { + FAIL("got server RI with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_ri_server)); + goto err; + } + + if (memcmp(data, tlsext_ri_server, dlen) != 0) { + FAIL("server RI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_ri_server, sizeof(tlsext_ri_server)); + goto err; + } + + CBS_init(&cbs, tlsext_ri_server, sizeof(tlsext_ri_server)); + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse server RI\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->renegotiate_seen != 1) { + FAIL("renegotiate seen not set\n"); + goto err; + } + if (ssl->s3->send_connection_binding != 1) { + FAIL("send connection binding not set\n"); + goto err; + } + + memset(ssl->s3->previous_client_finished, 0, + sizeof(ssl->s3->previous_client_finished)); + memset(ssl->s3->previous_server_finished, 0, + sizeof(ssl->s3->previous_server_finished)); + + ssl->s3->renegotiate_seen = 0; + + CBS_init(&cbs, tlsext_ri_server, sizeof(tlsext_ri_server)); + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("parsed invalid server RI\n"); + goto err; + } + + if (ssl->s3->renegotiate_seen == 1) { + FAIL("renegotiate seen set\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +/* + * Signature Algorithms - RFC 5246 section 7.4.1.4.1. + */ + +static const unsigned char tlsext_sigalgs_client[] = { + 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, + 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, + 0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, +}; + +static int +test_tlsext_sigalgs_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_signature_algorithms, + &client_funcs, &server_funcs)) + errx(1, "failed to fetch sigalgs funcs"); + + ssl->s3->hs.our_max_tls_version = TLS1_1_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need sigalgs\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need sigalgs\n"); + goto done; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build sigalgs\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_sigalgs_client)) { + FAIL("got client sigalgs length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_sigalgs_client)); + goto done; + } + + if (memcmp(data, tlsext_sigalgs_client, dlen) != 0) { + FAIL("client SNI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_sigalgs_client, sizeof(tlsext_sigalgs_client)); + goto done; + } + + CBS_init(&cbs, tlsext_sigalgs_client, sizeof(tlsext_sigalgs_client)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client SNI\n"); + goto done; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +#if 0 +static int +test_tlsext_sigalgs_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_server_name, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch sigalgs funcs"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need sigalgs\n"); + goto done; + } + + if (server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server should not build sigalgs\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + CBS_init(&cbs, tlsext_sigalgs_client, sizeof(tlsext_sigalgs_client)); + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("server should not parse sigalgs\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} +#endif + +/* + * Server Name Indication - RFC 6066 section 3. + */ + +#define TEST_SNI_SERVERNAME "www.libressl.org" + +static const unsigned char tlsext_sni_client[] = { + 0x00, 0x13, 0x00, 0x00, 0x10, 0x77, 0x77, 0x77, + 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x65, 0x73, 0x73, + 0x6c, 0x2e, 0x6f, 0x72, 0x67, +}; + +/* An empty array is an incomplete type and sizeof() is undefined. */ +static const unsigned char tlsext_sni_server[] = { + 0x00, +}; +static size_t tlsext_sni_server_len = 0; + +static int +test_tlsext_sni_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_server_name, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch sni funcs"); + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need SNI\n"); + goto err; + } + + if (!SSL_set_tlsext_host_name(ssl, TEST_SNI_SERVERNAME)) { + FAIL("client failed to set server name\n"); + goto err; + } + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need SNI\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build SNI\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != sizeof(tlsext_sni_client)) { + FAIL("got client SNI with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_sni_client)); + goto err; + } + + if (memcmp(data, tlsext_sni_client, dlen) != 0) { + FAIL("client SNI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_sni_client, sizeof(tlsext_sni_client)); + goto err; + } + + /* + * SSL_set_tlsext_host_name() may be called with a NULL host name to + * disable SNI. + */ + if (!SSL_set_tlsext_host_name(ssl, NULL)) { + FAIL("cannot set host name to NULL"); + goto err; + } + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need SNI\n"); + goto err; + } + + if ((ssl->session = SSL_SESSION_new()) == NULL) { + FAIL("failed to create session"); + goto err; + } + + ssl->hit = 0; + + CBS_init(&cbs, tlsext_sni_client, sizeof(tlsext_sni_client)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client SNI\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_hostname == NULL) { + FAIL("no tlsext_hostname from client SNI\n"); + goto err; + } + + if (strlen(ssl->session->tlsext_hostname) != strlen(TEST_SNI_SERVERNAME) || + strncmp(ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME, + strlen(TEST_SNI_SERVERNAME)) != 0) { + FAIL("got tlsext_hostname `%s', want `%s'\n", + ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME); + goto err; + } + + ssl->hit = 1; + + free(ssl->session->tlsext_hostname); + if ((ssl->session->tlsext_hostname = strdup("notthesame.libressl.org")) == + NULL) { + FAIL("failed to strdup tlsext_hostname"); + goto err; + } + + CBS_init(&cbs, tlsext_sni_client, sizeof(tlsext_sni_client)); + if (server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("parsed client with mismatched SNI\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_sni_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_server_name, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch sni funcs"); + + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need SNI\n"); + goto err; + } + + if (!SSL_set_tlsext_host_name(ssl, TEST_SNI_SERVERNAME)) { + FAIL("client failed to set server name\n"); + goto err; + } + + if ((ssl->session->tlsext_hostname = strdup(TEST_SNI_SERVERNAME)) == + NULL) + errx(1, "failed to strdup tlsext_hostname"); + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need SNI\n"); + goto err; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build SNI\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != tlsext_sni_server_len) { + FAIL("got server SNI with length %zu, " + "want length %zu\n", dlen, tlsext_sni_server_len); + goto err; + } + + if (memcmp(data, tlsext_sni_server, dlen) != 0) { + FAIL("server SNI differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_sni_server, tlsext_sni_server_len); + goto err; + } + + free(ssl->session->tlsext_hostname); + ssl->session->tlsext_hostname = NULL; + + CBS_init(&cbs, tlsext_sni_server, tlsext_sni_server_len); + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse server SNI\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->session->tlsext_hostname == NULL) { + FAIL("no tlsext_hostname after server SNI\n"); + goto err; + } + + if (strlen(ssl->session->tlsext_hostname) != strlen(TEST_SNI_SERVERNAME) || + strncmp(ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME, + strlen(TEST_SNI_SERVERNAME)) != 0) { + FAIL("got tlsext_hostname `%s', want `%s'\n", + ssl->session->tlsext_hostname, TEST_SNI_SERVERNAME); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + + +/* + * QUIC transport parameters extension - RFC 90210 :) + */ + +static const unsigned char tlsext_quic_transport_data[] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, +}; + +static int +test_tlsext_quic_transport_parameters_client(void) +{ + const SSL_QUIC_METHOD quic_method; + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + CBB cbb; + CBS cbs; + int alert; + const uint8_t *out_bytes; + size_t out_bytes_len; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_quic_transport_parameters, + &client_funcs, &server_funcs)) + errx(1, "failed to fetch quic transport parameter funcs"); + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need QUIC\n"); + goto err; + } + + if (!SSL_set_quic_transport_params(ssl, + tlsext_quic_transport_data, sizeof(tlsext_quic_transport_data))) { + FAIL("client failed to set QUIC parametes\n"); + goto err; + } + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need QUIC\n"); + goto err; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need QUIC\n"); + goto err; + } + + ssl->quic_method = &quic_method; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need QUIC\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build QUIC\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != sizeof(tlsext_quic_transport_data)) { + FAIL("got client QUIC with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + if (memcmp(data, tlsext_quic_transport_data, dlen) != 0) { + FAIL("client QUIC differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + CBS_init(&cbs, tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("server_parse of QUIC from server failed\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + SSL_get_peer_quic_transport_params(ssl, &out_bytes, &out_bytes_len); + + if (out_bytes_len != sizeof(tlsext_quic_transport_data)) { + FAIL("server_parse QUIC length differs, got %zu want %zu\n", + out_bytes_len, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + if (memcmp(out_bytes, tlsext_quic_transport_data, + out_bytes_len) != 0) { + FAIL("server_parse QUIC differs from sent:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_quic_transport_parameters_server(void) +{ + const SSL_QUIC_METHOD quic_method; + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + const uint8_t *out_bytes; + size_t out_bytes_len; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_quic_transport_parameters, + &client_funcs, &server_funcs)) + errx(1, "failed to fetch quic transport parameter funcs"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need QUIC\n"); + goto err; + } + + if (!SSL_set_quic_transport_params(ssl, + tlsext_quic_transport_data, sizeof(tlsext_quic_transport_data))) { + FAIL("server failed to set QUIC parametes\n"); + goto err; + } + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_EE)) { + FAIL("server should not need QUIC\n"); + goto err; + } + + ssl->quic_method = &quic_method; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_EE)) { + FAIL("server should need QUIC\n"); + goto err; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_EE, &cbb)) { + FAIL("server failed to build QUIC\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_quic_transport_data)) { + FAIL("got server QUIC with length %zu, want length %zu\n", + dlen, sizeof(tlsext_quic_transport_data)); + goto err; + } + + if (memcmp(data, tlsext_quic_transport_data, dlen) != 0) { + FAIL("saved server QUIC differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + CBS_init(&cbs, tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + + ssl->quic_method = NULL; + + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_EE, &cbs, &alert)) { + FAIL("QUIC parse should have failed!\n"); + goto err; + } + + ssl->quic_method = &quic_method; + + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("client_parse of QUIC from server failed\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + SSL_get_peer_quic_transport_params(ssl, &out_bytes, &out_bytes_len); + + if (out_bytes_len != sizeof(tlsext_quic_transport_data)) { + FAIL("client QUIC length differs, got %zu want %zu\n", + out_bytes_len, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + if (memcmp(out_bytes, tlsext_quic_transport_data, out_bytes_len) != 0) { + FAIL("client QUIC differs from sent:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tlsext_quic_transport_data, + sizeof(tlsext_quic_transport_data)); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static const unsigned char tls_ocsp_client_default[] = { + 0x01, 0x00, 0x00, 0x00, 0x00 +}; + +static int +test_tlsext_ocsp_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_status_request, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ocsp funcs"); + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need TLSEXT_TYPE_status_request\n"); + goto err; + } + SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp); + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need TLSEXT_TYPE_status_request\n"); + goto err; + } + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build SNI\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tls_ocsp_client_default)) { + FAIL("got TLSEXT_TYPE_status_request client with length %zu, " + "want length %zu\n", dlen, + sizeof(tls_ocsp_client_default)); + goto err; + } + if (memcmp(data, tls_ocsp_client_default, dlen) != 0) { + FAIL("TLSEXT_TYPE_status_request client differs:\n"); + fprintf(stderr, "received:\n"); + hexdump(data, dlen); + fprintf(stderr, "test data:\n"); + hexdump(tls_ocsp_client_default, + sizeof(tls_ocsp_client_default)); + goto err; + } + CBS_init(&cbs, tls_ocsp_client_default, + sizeof(tls_ocsp_client_default)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse TLSEXT_TYPE_status_request client\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_ocsp_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure; + CBB cbb; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_status_request, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch ocsp funcs"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need TLSEXT_TYPE_status_request\n"); + goto err; + } + + ssl->tlsext_status_expected = 1; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need TLSEXT_TYPE_status_request\n"); + goto err; + } + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build TLSEXT_TYPE_status_request\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +/* + * Session ticket - RFC 5077 since no known implementations use 4507. + * + * Session tickets can be length 0 (special case) to 2^16-1. + * + * The state is encrypted by the server so it is opaque to the client. + */ +static uint8_t tlsext_sessionticket_hello_min[1]; +static uint8_t tlsext_sessionticket_hello_max[65535]; + +static int +test_tlsext_sessionticket_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + CBB cbb; + size_t dlen; + uint8_t dummy[1234]; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + /* Create fake session tickets with random data. */ + arc4random_buf(tlsext_sessionticket_hello_min, + sizeof(tlsext_sessionticket_hello_min)); + arc4random_buf(tlsext_sessionticket_hello_max, + sizeof(tlsext_sessionticket_hello_max)); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_session_ticket, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch session ticket funcs"); + + /* Should need a ticket by default. */ + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need Sessionticket for default " + "ciphers\n"); + goto err; + } + + /* Test disabling tickets. */ + if ((SSL_set_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) == 0) { + FAIL("Cannot disable tickets in the TLS connection\n"); + goto err; + } + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need SessionTicket if it was disabled\n"); + goto err; + } + + /* Test re-enabling tickets. */ + if ((SSL_clear_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) != 0) { + FAIL("Cannot re-enable tickets in the TLS connection\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need SessionTicket if it was disabled\n"); + goto err; + } + + /* Since we don't have a session, we should build an empty ticket. */ + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("Cannot build a ticket\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("Cannot finish CBB\n"); + goto err; + } + if (dlen != 0) { + FAIL("Expected 0 length but found %zu\n", dlen); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* With a new session (but no ticket), we should still have 0 length */ + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("Should still want a session ticket with a new session\n"); + goto err; + } + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("Cannot build a ticket\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("Cannot finish CBB\n"); + goto err; + } + if (dlen != 0) { + FAIL("Expected 0 length but found %zu\n", dlen); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* With a new session (and ticket), we should use that ticket */ + SSL_SESSION_free(ssl->session); + if ((ssl->session = SSL_SESSION_new()) == NULL) + errx(1, "failed to create session"); + + arc4random_buf(&dummy, sizeof(dummy)); + if ((ssl->session->tlsext_tick = malloc(sizeof(dummy))) == NULL) { + errx(1, "failed to malloc"); + } + memcpy(ssl->session->tlsext_tick, dummy, sizeof(dummy)); + ssl->session->tlsext_ticklen = sizeof(dummy); + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("Should still want a session ticket with a new session\n"); + goto err; + } + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("Cannot build a ticket\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("Cannot finish CBB\n"); + goto err; + } + if (dlen != sizeof(dummy)) { + FAIL("Expected %zu length but found %zu\n", sizeof(dummy), dlen); + goto err; + } + if (memcmp(data, dummy, dlen) != 0) { + FAIL("server SNI differs:\n"); + compare_data(data, dlen, + dummy, sizeof(dummy)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + free(ssl->session->tlsext_tick); + ssl->session->tlsext_tick = NULL; + ssl->session->tlsext_ticklen = 0; + + /* + * Send in NULL to disable session tickets at runtime without going + * through SSL_set_options(). + */ + if (!SSL_set_session_ticket_ext(ssl, NULL, 0)) { + FAIL("Could not set a NULL custom ticket\n"); + goto err; + } + /* Should not need a ticket in this case */ + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("Should not want to use session tickets with a NULL custom\n"); + goto err; + } + + /* + * If you want to remove the tlsext_session_ticket behavior, you have + * to do it manually. + */ + free(ssl->tlsext_session_ticket); + ssl->tlsext_session_ticket = NULL; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("Should need a session ticket again when the custom one is removed\n"); + goto err; + } + + /* Test a custom session ticket (not recommended in practice) */ + if (!SSL_set_session_ticket_ext(ssl, tlsext_sessionticket_hello_max, + sizeof(tlsext_sessionticket_hello_max))) { + FAIL("Should be able to set a custom ticket\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("Should need a session ticket again when the custom one is not empty\n"); + goto err; + } + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("Cannot build a ticket with a max length random payload\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("Cannot finish CBB\n"); + goto err; + } + if (dlen != sizeof(tlsext_sessionticket_hello_max)) { + FAIL("Expected %zu length but found %zu\n", + sizeof(tlsext_sessionticket_hello_max), dlen); + goto err; + } + if (memcmp(data, tlsext_sessionticket_hello_max, + sizeof(tlsext_sessionticket_hello_max)) != 0) { + FAIL("Expected to get what we passed in\n"); + compare_data(data, dlen, + tlsext_sessionticket_hello_max, + sizeof(tlsext_sessionticket_hello_max)); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + + +static int +test_tlsext_sessionticket_server(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + uint8_t *data = NULL; + size_t dlen; + CBB cbb; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_session_ticket, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch session ticket funcs"); + + /* + * By default, should not need a session ticket since the ticket + * is not yet expected. + */ + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need SessionTicket by default\n"); + goto err; + } + + /* Test disabling tickets. */ + if ((SSL_set_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) == 0) { + FAIL("Cannot disable tickets in the TLS connection\n"); + goto err; + } + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need SessionTicket if it was disabled\n"); + goto err; + } + + /* Test re-enabling tickets. */ + if ((SSL_clear_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) != 0) { + FAIL("Cannot re-enable tickets in the TLS connection\n"); + goto err; + } + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need SessionTicket yet\n"); + goto err; + } + + /* Set expected to require it. */ + ssl->tlsext_ticket_expected = 1; + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should now be required for SessionTicket\n"); + goto err; + } + + /* server hello's session ticket should always be 0 length payload. */ + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("Cannot build a ticket with a max length random payload\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("Cannot finish CBB\n"); + goto err; + } + if (dlen != 0) { + FAIL("Expected 0 length but found %zu\n", dlen); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +#ifndef OPENSSL_NO_SRTP +/* + * Supported Secure Real-time Transport Protocol (RFC 5764 section 4.1.1) + */ + +/* Colon separated string values */ +const char *tlsext_srtp_single_profile = "SRTP_AES128_CM_SHA1_80"; +const char *tlsext_srtp_multiple_profiles = "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32"; + +const char *tlsext_srtp_aes128cmsha80 = "SRTP_AES128_CM_SHA1_80"; +const char *tlsext_srtp_aes128cmsha32 = "SRTP_AES128_CM_SHA1_32"; + +const uint8_t tlsext_srtp_single[] = { + /* SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1> */ + 0x00, 0x02, /* len */ + 0x00, 0x01, /* SRTP_AES128_CM_SHA1_80 */ + 0x00 /* opaque srtp_mki<0..255> */ +}; + +const uint8_t tlsext_srtp_multiple[] = { + /* SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1> */ + 0x00, 0x04, /* len */ + 0x00, 0x01, /* SRTP_AES128_CM_SHA1_80 */ + 0x00, 0x02, /* SRTP_AES128_CM_SHA1_32 */ + 0x00 /* opaque srtp_mki<0..255> */ +}; + +const uint8_t tlsext_srtp_multiple_invalid[] = { + /* SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1> */ + 0x00, 0x04, /* len */ + 0x00, 0x08, /* arbitrary value not found in known profiles */ + 0x00, 0x09, /* arbitrary value not found in known profiles */ + 0x00 /* opaque srtp_mki<0..255> */ +}; + +const uint8_t tlsext_srtp_single_invalid[] = { + /* SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1> */ + 0x00, 0x02, /* len */ + 0x00, 0x08, /* arbitrary value not found in known profiles */ + 0x00 /* opaque srtp_mki<0..255> */ +}; + +const uint8_t tlsext_srtp_multiple_one_valid[] = { + /* SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1> */ + 0x00, 0x04, /* len */ + 0x00, 0x08, /* arbitrary value not found in known profiles */ + 0x00, 0x02, /* SRTP_AES128_CM_SHA1_32 */ + 0x00 /* opaque srtp_mki<0..255> */ +}; + +static int +test_tlsext_srtp_client(void) +{ + SRTP_PROTECTION_PROFILE *prof; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + uint8_t *data = NULL; + CBB cbb; + CBS cbs; + int failure, alert; + size_t dlen; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + /* SRTP is for DTLS */ + if ((ssl_ctx = SSL_CTX_new(DTLSv1_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_use_srtp, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch srtp funcs"); + + /* By default, we don't need this */ + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need SRTP by default\n"); + goto err; + } + + if (SSL_set_tlsext_use_srtp(ssl, tlsext_srtp_single_profile) != 0) { + FAIL("should be able to set a single SRTP\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need SRTP\n"); + goto err; + } + + /* Make sure we can build the client with a single profile. */ + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build SRTP\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_srtp_single)) { + FAIL("got client SRTP with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_srtp_single)); + compare_data(data, dlen, tlsext_srtp_single, + sizeof(tlsext_srtp_single)); + goto err; + } + if (memcmp(data, tlsext_srtp_single, dlen) != 0) { + FAIL("client SRTP differs:\n"); + compare_data(data, dlen, tlsext_srtp_single, + sizeof(tlsext_srtp_single)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* Make sure we can parse the single profile. */ + + if (SSL_get_selected_srtp_profile(ssl) != NULL) { + FAIL("SRTP profile should not be set yet\n"); + goto err; + } + + CBS_init(&cbs, tlsext_srtp_single, sizeof(tlsext_srtp_single)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse SRTP\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if ((prof = SSL_get_selected_srtp_profile(ssl)) == NULL) { + FAIL("SRTP profile should be set now\n"); + goto err; + } + if (strcmp(prof->name, tlsext_srtp_aes128cmsha80) != 0) { + FAIL("SRTP profile was not set properly\n"); + goto err; + } + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("should send server extension when profile selected\n"); + goto err; + } + + /* Make sure we can build the clienthello with multiple entries. */ + + if (SSL_set_tlsext_use_srtp(ssl, tlsext_srtp_multiple_profiles) != 0) { + FAIL("should be able to set SRTP to multiple profiles\n"); + goto err; + } + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need SRTP by now\n"); + goto err; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build SRTP\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_srtp_multiple)) { + FAIL("got client SRTP with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_srtp_multiple)); + compare_data(data, dlen, tlsext_srtp_multiple, + sizeof(tlsext_srtp_multiple)); + goto err; + } + if (memcmp(data, tlsext_srtp_multiple, dlen) != 0) { + FAIL("client SRTP differs:\n"); + compare_data(data, dlen, tlsext_srtp_multiple, + sizeof(tlsext_srtp_multiple)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* Make sure we can parse multiple profiles (selects server preferred) */ + + ssl->srtp_profile = NULL; + + CBS_init(&cbs, tlsext_srtp_multiple, + sizeof(tlsext_srtp_multiple)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse SRTP\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if ((prof = SSL_get_selected_srtp_profile(ssl)) == NULL) { + FAIL("SRTP profile should be set now\n"); + goto err; + } + if (strcmp(prof->name, tlsext_srtp_aes128cmsha80) != 0) { + FAIL("SRTP profile was not set properly\n"); + goto err; + } + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("should send server extension when profile selected\n"); + goto err; + } + + /* + * Make sure we can parse the clienthello with multiple entries + * where one is unknown. + */ + ssl->srtp_profile = NULL; + + CBS_init(&cbs, tlsext_srtp_multiple_one_valid, + sizeof(tlsext_srtp_multiple_one_valid)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse SRTP\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if ((prof = SSL_get_selected_srtp_profile(ssl)) == NULL) { + FAIL("SRTP profile should be set now\n"); + goto err; + } + if (strcmp(prof->name, tlsext_srtp_aes128cmsha32) != 0) { + FAIL("SRTP profile was not set properly\n"); + goto err; + } + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("should send server extension when profile selected\n"); + goto err; + } + + /* Make sure we fall back to negotiated when none work. */ + + ssl->srtp_profile = NULL; + + CBS_init(&cbs, tlsext_srtp_multiple_invalid, + sizeof(tlsext_srtp_multiple_invalid)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("should be able to fall back to negotiated\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + /* If we fallback, the server should NOT send the extension. */ + if (SSL_get_selected_srtp_profile(ssl) != NULL) { + FAIL("should not have selected a profile when none found\n"); + goto err; + } + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("should not send server tlsext when no profile found\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_srtp_server(void) +{ + const SRTP_PROTECTION_PROFILE *prof; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + uint8_t *data = NULL; + CBB cbb; + CBS cbs; + int failure, alert; + size_t dlen; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + /* SRTP is for DTLS */ + if ((ssl_ctx = SSL_CTX_new(DTLSv1_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_use_srtp, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch srtp funcs"); + + /* By default, we don't need this */ + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need SRTP by default\n"); + goto err; + } + + if (srtp_find_profile_by_name(tlsext_srtp_aes128cmsha80, &prof, + strlen(tlsext_srtp_aes128cmsha80))) { + FAIL("should be able to find the given profile\n"); + goto err; + } + ssl->srtp_profile = prof; + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need SRTP by now\n"); + goto err; + } + + /* Make sure we can build the server with a single profile. */ + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server failed to build SRTP\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish CBB"); + + if (dlen != sizeof(tlsext_srtp_single)) { + FAIL("got server SRTP with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_srtp_single)); + compare_data(data, dlen, tlsext_srtp_single, + sizeof(tlsext_srtp_single)); + goto err; + } + if (memcmp(data, tlsext_srtp_single, dlen) != 0) { + FAIL("server SRTP differs:\n"); + compare_data(data, dlen, tlsext_srtp_single, + sizeof(tlsext_srtp_single)); + goto err; + } + + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + free(data); + data = NULL; + + /* Make sure we can parse the single profile. */ + ssl->srtp_profile = NULL; + + if (SSL_get_selected_srtp_profile(ssl) != NULL) { + FAIL("SRTP profile should not be set yet\n"); + goto err; + } + + /* Setup the environment as if a client sent a list of profiles. */ + if (SSL_set_tlsext_use_srtp(ssl, tlsext_srtp_multiple_profiles) != 0) { + FAIL("should be able to set multiple profiles in SRTP\n"); + goto err; + } + + CBS_init(&cbs, tlsext_srtp_single, sizeof(tlsext_srtp_single)); + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse SRTP\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if ((prof = SSL_get_selected_srtp_profile(ssl)) == NULL) { + FAIL("SRTP profile should be set now\n"); + goto err; + } + if (strcmp(prof->name, tlsext_srtp_aes128cmsha80) != 0) { + FAIL("SRTP profile was not set properly\n"); + goto err; + } + + /* Make sure we cannot parse multiple profiles */ + ssl->srtp_profile = NULL; + + CBS_init(&cbs, tlsext_srtp_multiple, + sizeof(tlsext_srtp_multiple)); + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("should not find multiple entries from the server\n"); + goto err; + } + + /* Make sure we cannot parse a server with unknown profile */ + ssl->srtp_profile = NULL; + + CBS_init(&cbs, tlsext_srtp_single_invalid, + sizeof(tlsext_srtp_single_invalid)); + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("should not be able to parse this\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} +#endif /* OPENSSL_NO_SRTP */ + +static const unsigned char tlsext_clienthello_default[] = { + 0x00, 0x34, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, + 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, + 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x23, + 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, + 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 0x08, 0x05, + 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, 0x01, + 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, +}; + +/* An empty array is an incomplete type and sizeof() is undefined. */ +static const unsigned char tlsext_clienthello_disabled[] = { + 0x00, +}; +static size_t tlsext_clienthello_disabled_len = 0; + +static int +test_tlsext_clienthello_build(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + size_t dlen; + int failure; + CBB cbb; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) { + FAIL("failed to create SSL_CTX"); + goto err; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + FAIL("failed to create SSL"); + goto err; + } + + if (!tlsext_linearize_build_order(ssl)) { + FAIL("failed to linearize build order"); + goto err; + } + + if (!tls_extension_funcs(TLSEXT_TYPE_supported_versions, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch supported versions funcs"); + + ssl->s3->hs.our_min_tls_version = TLS1_VERSION; + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + + if (!tlsext_client_build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("failed to build clienthello extensions\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != sizeof(tlsext_clienthello_default)) { + FAIL("got clienthello extensions with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_clienthello_default)); + compare_data(data, dlen, tlsext_clienthello_default, + sizeof(tlsext_clienthello_default)); + goto err; + } + if (memcmp(data, tlsext_clienthello_default, dlen) != 0) { + FAIL("clienthello extensions differs:\n"); + compare_data(data, dlen, tlsext_clienthello_default, + sizeof(tlsext_clienthello_default)); + goto err; + } + + free(data); + data = NULL; + CBB_cleanup(&cbb); + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + /* Switch to TLSv1.1, disable EC ciphers and session tickets. */ + ssl->s3->hs.our_max_tls_version = TLS1_1_VERSION; + if (!SSL_set_cipher_list(ssl, "TLSv1.2:!ECDHE:!ECDSA")) { + FAIL("failed to set cipher list\n"); + goto err; + } + if ((SSL_set_options(ssl, SSL_OP_NO_TICKET) & SSL_OP_NO_TICKET) == 0) { + FAIL("failed to disable session tickets\n"); + goto err; + } + + if (!tlsext_client_build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("failed to build clienthello extensions\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != tlsext_clienthello_disabled_len) { + FAIL("got clienthello extensions with length %zu, " + "want length %zu\n", dlen, + tlsext_clienthello_disabled_len); + compare_data(data, dlen, tlsext_clienthello_disabled, + tlsext_clienthello_disabled_len); + goto err; + } + if (memcmp(data, tlsext_clienthello_disabled, dlen) != 0) { + FAIL("clienthello extensions differs:\n"); + compare_data(data, dlen, tlsext_clienthello_disabled, + tlsext_clienthello_disabled_len); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +unsigned char tlsext_serverhello_default[] = { + 0x00, 0x06, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, +}; + +unsigned char tlsext_serverhello_enabled[] = { + 0x00, 0x10, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, + 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23, + 0x00, 0x00, +}; + +static int +test_tlsext_serverhello_build(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + size_t dlen; + int failure; + CBB cbb; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) { + FAIL("failed to create SSL_CTX"); + goto err; + } + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + FAIL("failed to create SSL"); + goto err; + } + if (!tlsext_linearize_build_order(ssl)) { + FAIL("failed to linearize build order"); + goto err; + } + if ((ssl->session = SSL_SESSION_new()) == NULL) { + FAIL("failed to create session"); + goto err; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION; + ssl->s3->hs.cipher = + ssl3_get_cipher_by_id(TLS1_CK_RSA_WITH_AES_128_SHA256); + + if (!tlsext_server_build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("failed to build serverhello extensions\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != sizeof(tlsext_serverhello_default)) { + FAIL("got serverhello extensions with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_serverhello_default)); + compare_data(data, dlen, tlsext_serverhello_default, + sizeof(tlsext_serverhello_default)); + goto err; + } + if (memcmp(data, tlsext_serverhello_default, dlen) != 0) { + FAIL("serverhello extensions differs:\n"); + compare_data(data, dlen, tlsext_serverhello_default, + sizeof(tlsext_serverhello_default)); + goto err; + } + + CBB_cleanup(&cbb); + free(data); + data = NULL; + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + /* Turn a few things on so we get extensions... */ + ssl->s3->send_connection_binding = 1; + ssl->s3->hs.cipher = + ssl3_get_cipher_by_id(TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256); + ssl->tlsext_status_expected = 1; + ssl->tlsext_ticket_expected = 1; + if ((ssl->session->tlsext_ecpointformatlist = malloc(1)) == NULL) { + FAIL("malloc failed"); + goto err; + } + ssl->session->tlsext_ecpointformatlist_length = 1; + ssl->session->tlsext_ecpointformatlist[0] = + TLSEXT_ECPOINTFORMAT_uncompressed; + + if (!tlsext_server_build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("failed to build serverhello extensions\n"); + goto err; + } + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB"); + goto err; + } + + if (dlen != sizeof(tlsext_serverhello_enabled)) { + FAIL("got serverhello extensions with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_serverhello_enabled)); + compare_data(data, dlen, tlsext_serverhello_enabled, + sizeof(tlsext_serverhello_enabled)); + goto err; + } + if (memcmp(data, tlsext_serverhello_enabled, dlen) != 0) { + FAIL("serverhello extensions differs:\n"); + compare_data(data, dlen, tlsext_serverhello_enabled, + sizeof(tlsext_serverhello_enabled)); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +const unsigned char tlsext_versions_client[] = { + 0x08, 0x03, 0x04, 0x03, 0x03, 0x03, + 0x02, 0x03, 0x01, +}; + +const unsigned char tlsext_versions_server[] = { + 0x03, 0x04, +}; + +static int +test_tlsext_versions_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_supported_versions, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch supported versions funcs"); + + ssl->s3->hs.our_max_tls_version = TLS1_1_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need versions\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need versions\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need versions\n"); + goto done; + } + + ssl->s3->hs.our_min_tls_version = TLS1_VERSION; + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client should have built versions\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != sizeof(tlsext_versions_client)) { + FAIL("got versions with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_versions_client)); + goto done; + } + + CBS_init(&cbs, data, dlen); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client versions\n"); + goto done; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_versions_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_supported_versions, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch supported versions funcs"); + + ssl->s3->hs.negotiated_tls_version = TLS1_2_VERSION; + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need versions\n"); + goto done; + } + + ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION; + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need versions\n"); + goto done; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server should have built versions\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != sizeof(tlsext_versions_server)) { + FAIL("got versions with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_versions_server)); + goto done; + } + + CBS_init(&cbs, data, dlen); + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse client versions\n"); + goto done; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +const unsigned char tlsext_keyshare_client[] = { + 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0xba, 0x83, + 0x2e, 0x4a, 0x18, 0xbe, 0x96, 0xd2, 0x71, 0x70, + 0x18, 0x04, 0xf9, 0x9d, 0x76, 0x98, 0xef, 0xe8, + 0x4f, 0x8b, 0x85, 0x41, 0xa4, 0xd9, 0x61, 0x57, + 0xad, 0x5b, 0xa4, 0xe9, 0x8b, 0x6b, +}; + +const unsigned char tlsext_keyshare_server[] = { + 0x00, 0x1d, 0x00, 0x20, 0xe5, 0xe8, 0x5a, 0xb9, + 0x7e, 0x12, 0x62, 0xe3, 0xd8, 0x7f, 0x6e, 0x3c, + 0xec, 0xa6, 0x8b, 0x99, 0x45, 0x77, 0x8e, 0x11, + 0xb3, 0xb9, 0x12, 0xb6, 0xbe, 0x35, 0xca, 0x51, + 0x76, 0x1e, 0xe8, 0x22 +}; + +static int +test_tlsext_keyshare_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_key_share, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch keyshare funcs"); + + if ((ssl->s3->hs.key_share = + tls_key_share_new_nid(NID_X25519)) == NULL) + errx(1, "failed to create key share"); + if (!tls_key_share_generate(ssl->s3->hs.key_share)) + errx(1, "failed to generate key share"); + + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need keyshare\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need keyshare\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client should have built keyshare\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != sizeof(tlsext_keyshare_client)) { + FAIL("got client keyshare with length %zu, " + "want length %zu\n", dlen, (size_t) sizeof(tlsext_keyshare_client)); + goto done; + } + + (ssl)->version = TLS1_3_VERSION; + CBS_init(&cbs, data, dlen); + + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client keyshare\n"); + goto done; + } + + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static const uint8_t bogokey[] = { + 0xe5, 0xe8, 0x5a, 0xb9, 0x7e, 0x12, 0x62, 0xe3, + 0xd8, 0x7f, 0x6e, 0x3c, 0xec, 0xa6, 0x8b, 0x99, + 0x45, 0x77, 0x8e, 0x11, 0xb3, 0xb9, 0x12, 0xb6, + 0xbe, 0x35, 0xca, 0x51, 0x76, 0x1e, 0xe8, 0x22, +}; + +static int +test_tlsext_keyshare_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int decode_error; + int failure; + size_t dlen, idx; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_key_share, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch keyshare funcs"); + + ssl->s3->hs.negotiated_tls_version = TLS1_2_VERSION; + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need keyshare\n"); + goto done; + } + + ssl->s3->hs.negotiated_tls_version = TLS1_3_VERSION; + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("client should not need keyshare\n"); + goto done; + } + + if (tls_extension_find(TLSEXT_TYPE_key_share, &idx) == NULL) { + FAIL("failed to find keyshare extension\n"); + goto done; + } + ssl->s3->hs.extensions_seen |= (1 << idx); + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should need keyshare\n"); + goto done; + } + + if (server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server should not have built a keyshare response\n"); + goto done; + } + + if ((ssl->s3->hs.key_share = + tls_key_share_new_nid(NID_X25519)) == NULL) { + FAIL("failed to create key share"); + goto done; + } + + if (!tls_key_share_generate(ssl->s3->hs.key_share)) { + FAIL("failed to generate key share"); + goto done; + } + + CBS_init(&cbs, bogokey, sizeof(bogokey)); + + if (!tls_key_share_peer_public(ssl->s3->hs.key_share, &cbs, + &decode_error, NULL)) { + FAIL("failed to load peer public key\n"); + goto done; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_SH, &cbb)) { + FAIL("server should be able to build a keyshare response\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != sizeof(tlsext_keyshare_server)) { + FAIL("got server keyshare with length %zu, " + "want length %zu\n", dlen, sizeof(tlsext_keyshare_server)); + goto done; + } + + tls_key_share_free(ssl->s3->hs.key_share); + + if ((ssl->s3->hs.key_share = + tls_key_share_new_nid(NID_X25519)) == NULL) { + FAIL("failed to create key share"); + goto done; + } + if (!tls_key_share_generate(ssl->s3->hs.key_share)) { + FAIL("failed to generate key share"); + goto done; + } + + CBS_init(&cbs, data, dlen); + + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse server keyshare\n"); + goto done; + } + + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + +done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +/* One day I hope to be the only Muppet in this codebase */ +const uint8_t cookie[] = "\n" + " (o)(o) \n" + " m' 'm \n" + " M -****- M \n" + " 'm m' \n" + " m''''''''''m \n" + " M M BB \n"; + +static int +test_tlsext_cookie_client(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_cookie, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch cookie funcs"); + + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need cookie\n"); + goto done; + } + + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need cookie\n"); + goto done; + } + + /* Normally would be set by receiving a server cookie in an HRR */ + ssl->s3->hs.tls13.cookie = strdup(cookie); + ssl->s3->hs.tls13.cookie_len = strlen(cookie); + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need cookie\n"); + goto done; + } + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client should have built a cookie response\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != strlen(cookie) + sizeof(uint16_t)) { + FAIL("got cookie with length %zu, " + "want length %zu\n", dlen, strlen(cookie) + + sizeof(uint16_t)); + goto done; + } + + CBS_init(&cbs, data, dlen); + + /* Checks cookie against what's in the hs.tls13 */ + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse client cookie\n"); + goto done; + } + + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + + done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +static int +test_tlsext_cookie_server(void) +{ + unsigned char *data = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + size_t dlen; + int alert; + CBB cbb; + CBS cbs; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_cookie, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch cookie funcs"); + + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need cookie\n"); + goto done; + } + + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need cookie\n"); + goto done; + } + + /* Normally would be set by server before sending HRR */ + ssl->s3->hs.tls13.cookie = strdup(cookie); + ssl->s3->hs.tls13.cookie_len = strlen(cookie); + + if (!server_funcs->needs(ssl, SSL_TLSEXT_MSG_HRR)) { + FAIL("server should need cookie\n"); + goto done; + } + + if (!server_funcs->build(ssl, SSL_TLSEXT_MSG_HRR, &cbb)) { + FAIL("server should have built a cookie response\n"); + goto done; + } + + if (!CBB_finish(&cbb, &data, &dlen)) { + FAIL("failed to finish CBB\n"); + goto done; + } + + if (dlen != strlen(cookie) + sizeof(uint16_t)) { + FAIL("got cookie with length %zu, " + "want length %zu\n", dlen, strlen(cookie) + + sizeof(uint16_t)); + goto done; + } + + CBS_init(&cbs, data, dlen); + + if (client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("client should not have parsed server cookie\n"); + goto done; + } + + freezero(ssl->s3->hs.tls13.cookie, ssl->s3->hs.tls13.cookie_len); + ssl->s3->hs.tls13.cookie = NULL; + ssl->s3->hs.tls13.cookie_len = 0; + + if (!client_funcs->parse(ssl, SSL_TLSEXT_MSG_SH, &cbs, &alert)) { + FAIL("failed to parse server cookie\n"); + goto done; + } + + if (memcmp(cookie, ssl->s3->hs.tls13.cookie, + ssl->s3->hs.tls13.cookie_len) != 0) { + FAIL("parsed server cookie does not match sent cookie\n"); + goto done; + } + + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto done; + } + + failure = 0; + +done: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return (failure); +} + +const uint8_t tlsext_default_psk_modes[] = { + 0x01, 0x01, +}; + +const uint8_t tlsext_psk_only_mode[] = { + 0x01, 0x00, +}; + +const uint8_t tlsext_psk_both_modes[] = { + 0x02, 0x00, 0x01, +}; + +static int +test_tlsext_psk_modes_client(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + uint8_t *data = NULL; + size_t dlen; + CBB cbb; + CBS cbs; + int alert; + + failure = 1; + + if (!CBB_init(&cbb, 0)) + errx(1, "Failed to create CBB"); + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_psk_kex_modes, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch psk funcs"); + + /* Disabled by default. */ + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need psk kex modes by default\n"); + goto err; + } + + /* + * Prerequisites: use_psk_dhe_ke flag is set and + * our_max_tls_version >= TLSv1.3. + */ + + ssl->s3->hs.tls13.use_psk_dhe_ke = 1; + ssl->s3->hs.our_max_tls_version = TLS1_2_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need psk kex modes with TLSv1.2\n"); + goto err; + } + + ssl->s3->hs.tls13.use_psk_dhe_ke = 0; + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + + if (client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should not need psk kex modes without " + "use_psk_dhe_ke\n"); + goto err; + } + + ssl->s3->hs.tls13.use_psk_dhe_ke = 1; + ssl->s3->hs.our_max_tls_version = TLS1_3_VERSION; + + if (!client_funcs->needs(ssl, SSL_TLSEXT_MSG_CH)) { + FAIL("client should need psk kex modes with TLSv1.3\n"); + goto err; + } + + /* Make sure we can build psk modes with DHE key establishment. */ + + if (!client_funcs->build(ssl, SSL_TLSEXT_MSG_CH, &cbb)) { + FAIL("client failed to build psk kex modes\n"); + goto err; + } + + if (!CBB_finish(&cbb, &data, &dlen)) + errx(1, "failed to finish psk kex CBB"); + + if (dlen != sizeof(tlsext_default_psk_modes)) { + FAIL("got client psk kex modes with length %zu, " + "want length %zu\n", dlen, + sizeof(tlsext_default_psk_modes)); + compare_data(data, dlen, tlsext_default_psk_modes, + sizeof(tlsext_default_psk_modes)); + goto err; + } + if (memcmp(data, tlsext_default_psk_modes, dlen) != 0) { + FAIL("client psk kex modes differ:\n"); + compare_data(data, dlen, tlsext_default_psk_modes, + sizeof(tlsext_default_psk_modes)); + goto err; + } + + CBB_cleanup(&cbb); + free(data); + data = NULL; + + /* + * Make sure we can parse the default psk modes and that use_psk_dhe_ke + * is set after parsing. + */ + + ssl->s3->hs.tls13.use_psk_dhe_ke = 0; + + CBS_init(&cbs, tlsext_default_psk_modes, + sizeof(tlsext_default_psk_modes)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse psk kex modes\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->hs.tls13.use_psk_dhe_ke != 1) { + FAIL("should have set use_psk_dhe_ke\n"); + goto err; + } + + /* + * Make sure we can parse the psk-only mode and that use_psk_dhe_ke + * is still not set after parsing. + */ + + ssl->s3->hs.tls13.use_psk_dhe_ke = 0; + + CBS_init(&cbs, tlsext_psk_only_mode, sizeof(tlsext_psk_only_mode)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse psk kex modes\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->hs.tls13.use_psk_dhe_ke != 0) { + FAIL("should not have set use_psk_dhe_ke\n"); + goto err; + } + + /* + * Make sure we can parse the extension indicating both modes and that + * use_psk_dhe_ke is set after parsing. + */ + + ssl->s3->hs.tls13.use_psk_dhe_ke = 0; + + CBS_init(&cbs, tlsext_psk_both_modes, sizeof(tlsext_psk_both_modes)); + if (!server_funcs->parse(ssl, SSL_TLSEXT_MSG_CH, &cbs, &alert)) { + FAIL("failed to parse psk kex modes\n"); + goto err; + } + if (CBS_len(&cbs) != 0) { + FAIL("extension data remaining\n"); + goto err; + } + + if (ssl->s3->hs.tls13.use_psk_dhe_ke != 1) { + FAIL("should have set use_psk_dhe_ke\n"); + goto err; + } + + failure = 0; + + err: + CBB_cleanup(&cbb); + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + free(data); + + return failure; +} + +static int +test_tlsext_psk_modes_server(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + const struct tls_extension_funcs *client_funcs; + const struct tls_extension_funcs *server_funcs; + int failure; + + failure = 1; + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + if (!tls_extension_funcs(TLSEXT_TYPE_psk_kex_modes, &client_funcs, + &server_funcs)) + errx(1, "failed to fetch psk funcs"); + + if (server_funcs->needs(ssl, SSL_TLSEXT_MSG_SH)) { + FAIL("server should not need psk kex modes\n"); + goto err; + } + + failure = 0; + + err: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return failure; +} + +struct tls_sni_test { + const char *hostname; + int is_ip; + int valid; +}; + +static const struct tls_sni_test tls_sni_tests[] = { + { + .hostname = "openbsd.org", + .valid = 1, + }, + { + .hostname = "op3nbsd.org", + .valid = 1, + }, + { + .hostname = "org", + .valid = 1, + }, + { + .hostname = "3openbsd.com", + .valid = 1, + }, + { + .hostname = "3-0penb-d.c-m", + .valid = 1, + }, + { + .hostname = "a", + .valid = 1, + }, + { + .hostname = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + .valid = 1, + }, + { + .hostname = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + .valid = 1, + }, + { + .hostname = "openbsd.org.", + .valid = 0, + }, + { + .hostname = "openbsd..org", + .valid = 0, + }, + { + .hostname = "openbsd.org-", + .valid = 0, + }, + { + .hostname = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com", + .valid = 0, + }, + { + .hostname = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.a", + .valid = 0, + }, + { + .hostname = "-p3nbsd.org", + .valid = 0, + }, + { + .hostname = "openbs-.org", + .valid = 0, + }, + { + .hostname = "openbsd\n.org", + .valid = 0, + }, + { + .hostname = "open_bsd.org", + .valid = 0, + }, + { + .hostname = "open\178bsd.org", + .valid = 0, + }, + { + .hostname = "open\255bsd.org", + .valid = 0, + }, + { + .hostname = "dead::beef", + .is_ip = 1, + .valid = 0, + }, + { + .hostname = "192.168.0.1", + .is_ip = 1, + .valid = 0, + }, +}; + +#define N_TLS_SNI_TESTS (sizeof(tls_sni_tests) / sizeof(*tls_sni_tests)) + +static int +test_tlsext_is_valid_hostname(const struct tls_sni_test *tst) +{ + int failure; + int is_ip; + CBS cbs; + + failure = 1; + + CBS_init(&cbs, tst->hostname, strlen(tst->hostname)); + if (tlsext_sni_is_valid_hostname(&cbs, &is_ip) != tst->valid) { + if (tst->valid) { + FAIL("Valid hostname '%s' rejected\n", + tst->hostname); + } else { + FAIL("Invalid hostname '%s' accepted\n", + tst->hostname); + } + goto done; + } + if (tst->is_ip != is_ip) { + if (tst->is_ip) { + FAIL("Hostname '%s' is an IP literal but not " + "identified as one\n", tst->hostname); + } else { + FAIL("Hostname '%s' is not an IP literal but is " + "identified as one\n", tst->hostname); + } + goto done; + } + + if (tst->valid) { + CBS_init(&cbs, tst->hostname, + strlen(tst->hostname) + 1); + if (tlsext_sni_is_valid_hostname(&cbs, &is_ip)) { + FAIL("hostname with NUL byte accepted\n"); + goto done; + } + } + + failure = 0; + + done: + + return failure; +} + +static int +test_tlsext_valid_hostnames(void) +{ + const struct tls_sni_test *tst; + int failure = 0; + size_t i; + + for (i = 0; i < N_TLS_SNI_TESTS; i++) { + tst = &tls_sni_tests[i]; + failure |= test_tlsext_is_valid_hostname(tst); + } + + return failure; +} + +#define N_TLSEXT_RANDOMIZATION_TESTS 1000 + +static int +test_tlsext_check_extension_order(SSL *ssl) +{ + const struct tls_extension *ext; + uint16_t type; + size_t alpn_idx, sni_idx; + size_t i; + + if (ssl->tlsext_build_order_len == 0) { + FAIL("Unexpected zero build order length"); + return 1; + } + + ext = ssl->tlsext_build_order[ssl->tlsext_build_order_len - 1]; + if ((type = tls_extension_type(ext)) != TLSEXT_TYPE_psk) { + FAIL("last extension is %u, want %u\n", type, TLSEXT_TYPE_psk); + return 1; + } + + if (ssl->server) + return 0; + + alpn_idx = sni_idx = ssl->tlsext_build_order_len; + for (i = 0; i < ssl->tlsext_build_order_len; i++) { + ext = ssl->tlsext_build_order[i]; + if (tls_extension_type(ext) == TLSEXT_TYPE_alpn) + alpn_idx = i; + if (tls_extension_type(ext) == TLSEXT_TYPE_server_name) + sni_idx = i; + } + + if (alpn_idx == ssl->tlsext_build_order_len) { + FAIL("could not find alpn extension\n"); + return 1; + } + + if (sni_idx == ssl->tlsext_build_order_len) { + FAIL("could not find alpn extension\n"); + return 1; + } + + if (sni_idx >= alpn_idx) { + FAIL("sni does not precede alpn: %zu >= %zu\n", + sni_idx, alpn_idx); + return 1; + } + + return 0; +} + +static int +test_tlsext_randomized_extensions(SSL *ssl) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_TLSEXT_RANDOMIZATION_TESTS; i++) { + if (!tlsext_randomize_build_order(ssl)) + errx(1, "failed to randomize extensions"); + failed |= test_tlsext_check_extension_order(ssl); + } + + return failed; +} + +static int +test_tlsext_extension_order(void) +{ + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int failure; + + failure = 0; + + if ((ssl_ctx = SSL_CTX_new(TLS_client_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + failure |= test_tlsext_randomized_extensions(ssl); + + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + if ((ssl_ctx = SSL_CTX_new(TLS_server_method())) == NULL) + errx(1, "failed to create SSL_CTX"); + if ((ssl = SSL_new(ssl_ctx)) == NULL) + errx(1, "failed to create SSL"); + + failure |= test_tlsext_randomized_extensions(ssl); + + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + return failure; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + SSL_library_init(); + SSL_load_error_strings(); + + failed |= test_tlsext_alpn_client(); + failed |= test_tlsext_alpn_server(); + + failed |= test_tlsext_supportedgroups_client(); + failed |= test_tlsext_supportedgroups_server(); + + failed |= test_tlsext_ecpf_client(); + failed |= test_tlsext_ecpf_server(); + + failed |= test_tlsext_ri_client(); + failed |= test_tlsext_ri_server(); + + failed |= test_tlsext_sigalgs_client(); + + failed |= test_tlsext_sni_client(); + failed |= test_tlsext_sni_server(); + + failed |= test_tlsext_ocsp_client(); + failed |= test_tlsext_ocsp_server(); + + failed |= test_tlsext_sessionticket_client(); + failed |= test_tlsext_sessionticket_server(); + + failed |= test_tlsext_versions_client(); + failed |= test_tlsext_versions_server(); + + failed |= test_tlsext_keyshare_client(); + failed |= test_tlsext_keyshare_server(); + + failed |= test_tlsext_cookie_client(); + failed |= test_tlsext_cookie_server(); + +#ifndef OPENSSL_NO_SRTP + failed |= test_tlsext_srtp_client(); + failed |= test_tlsext_srtp_server(); +#else + fprintf(stderr, "Skipping SRTP tests due to OPENSSL_NO_SRTP\n"); +#endif + + failed |= test_tlsext_psk_modes_client(); + failed |= test_tlsext_psk_modes_server(); + + failed |= test_tlsext_clienthello_build(); + failed |= test_tlsext_serverhello_build(); + + failed |= test_tlsext_valid_hostnames(); + + failed |= test_tlsext_quic_transport_parameters_client(); + failed |= test_tlsext_quic_transport_parameters_server(); + + failed |= test_tlsext_extension_order(); + + return (failed); +} diff --git a/tests/tlslegacytest.c b/tests/tlslegacytest.c new file mode 100644 index 0000000..59429d7 --- /dev/null +++ b/tests/tlslegacytest.c @@ -0,0 +1,625 @@ +/* $OpenBSD: tlslegacytest.c,v 1.7 2022/10/02 16:39:39 jsing Exp $ */ +/* + * Copyright (c) 2015, 2016, 2017, 2020 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +/* openssl.org:443 */ +static uint8_t tls12_server_response[] = { + 0x16, 0x03, 0x03, 0x00, 0x3d, 0x02, 0x00, 0x00, + 0x39, 0x03, 0x03, 0x62, 0x0c, 0x8a, 0x7e, 0x29, + 0x60, 0xcb, 0x08, 0xd1, 0xb4, 0x95, 0x68, 0x76, + 0xea, 0x4e, 0x0c, 0x94, 0xf2, 0x42, 0x3d, 0xd1, + 0x7a, 0xc2, 0xfe, 0x6c, 0xb3, 0xe6, 0x12, 0x8a, + 0x33, 0x02, 0x92, 0x00, 0xc0, 0x30, 0x00, 0x00, + 0x11, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0b, + 0x00, 0x04, 0x03, 0x00, 0x01, 0x02, 0x00, 0x23, + 0x00, 0x00, +}; + +/* + * outlook.office365.com:587 with starttls - this server response includes + * multiple handshake messages contained in a single TLS record. + */ +static uint8_t tls12_server_response_with_cert[] = { + 0x16, 0x03, 0x03, 0x0f, 0x2b, 0x02, 0x00, 0x00, + 0x4d, 0x03, 0x03, 0x5f, 0x7c, 0x69, 0x42, 0xe1, + 0x19, 0xf0, 0x22, 0xfb, 0x71, 0x9a, 0xf1, 0x63, + 0x34, 0xbb, 0x61, 0x46, 0xea, 0x5f, 0x0b, 0x5e, + 0xb1, 0x4e, 0x37, 0x96, 0x67, 0xff, 0x83, 0xea, + 0x0e, 0x16, 0x85, 0x20, 0x3a, 0x1b, 0x00, 0x00, + 0x17, 0xe9, 0xac, 0xca, 0x19, 0x61, 0xaf, 0x70, + 0x28, 0x3b, 0x18, 0xaa, 0x6c, 0xa0, 0x0f, 0x78, + 0xd0, 0x83, 0xfc, 0x5d, 0x78, 0xf9, 0x6d, 0xdb, + 0x16, 0x21, 0x15, 0xa2, 0xc0, 0x30, 0x00, 0x00, + 0x05, 0xff, 0x01, 0x00, 0x01, 0x00, 0x0b, 0x00, + 0x0d, 0x47, 0x00, 0x0d, 0x44, 0x00, 0x08, 0xaf, + 0x30, 0x82, 0x08, 0xab, 0x30, 0x82, 0x07, 0x93, + 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0c, 0x6d, + 0xea, 0x0b, 0xe1, 0x97, 0x27, 0x60, 0xa1, 0x59, + 0xb1, 0x85, 0x60, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x66, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x42, + 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x10, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x6e, + 0x76, 0x2d, 0x73, 0x61, 0x31, 0x3c, 0x30, 0x3a, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x33, 0x47, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, + 0x6e, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x53, + 0x48, 0x41, 0x32, 0x35, 0x36, 0x20, 0x2d, 0x20, + 0x47, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, + 0x30, 0x38, 0x31, 0x33, 0x32, 0x33, 0x31, 0x38, + 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, + 0x38, 0x31, 0x34, 0x32, 0x33, 0x31, 0x38, 0x34, + 0x39, 0x5a, 0x30, 0x6a, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, + 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, + 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, + 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0b, 0x6f, 0x75, 0x74, 0x6c, 0x6f, + 0x6f, 0x6b, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc9, + 0x20, 0x3f, 0x57, 0xb9, 0xf9, 0x71, 0xaa, 0x3c, + 0x6a, 0x0a, 0x5d, 0x3f, 0xc9, 0x8d, 0x99, 0xa5, + 0x50, 0x26, 0x25, 0x4e, 0xdc, 0x69, 0x52, 0xb3, + 0x33, 0x70, 0xe7, 0x72, 0xa2, 0x83, 0x92, 0x54, + 0xd1, 0xd4, 0x86, 0x15, 0xf2, 0xc4, 0x65, 0xf8, + 0xbc, 0xe5, 0xd2, 0x1e, 0x12, 0x25, 0x9e, 0x75, + 0x8e, 0x77, 0xd2, 0x8e, 0x94, 0xca, 0x03, 0x4b, + 0xf4, 0xc8, 0xca, 0xe3, 0xe3, 0x9b, 0x66, 0xa3, + 0xa1, 0x37, 0x74, 0xcc, 0xfe, 0xc4, 0x1e, 0x64, + 0xdc, 0xe3, 0x18, 0xba, 0xc1, 0x7b, 0x39, 0x5b, + 0xb1, 0x47, 0xe9, 0x11, 0x92, 0xef, 0xee, 0xe6, + 0x08, 0xcd, 0x93, 0x7b, 0x09, 0xc7, 0x39, 0xfe, + 0xe5, 0xe2, 0x47, 0x3f, 0x68, 0x78, 0xa4, 0x17, + 0x78, 0x13, 0xcb, 0x12, 0x38, 0x9d, 0x89, 0x2b, + 0x1f, 0x75, 0x9b, 0x87, 0x5d, 0x53, 0xfc, 0xb0, + 0x2a, 0xaf, 0x2d, 0x86, 0x8a, 0x76, 0x3b, 0xce, + 0x5e, 0xae, 0x43, 0x74, 0x68, 0xc3, 0x28, 0xbf, + 0x10, 0x2f, 0xdd, 0xd9, 0x43, 0x4b, 0x2d, 0xa6, + 0xdc, 0x1f, 0x6d, 0x90, 0xd0, 0xce, 0x14, 0x1e, + 0x6c, 0xdc, 0x7b, 0x06, 0xe4, 0x7b, 0xa9, 0x81, + 0x40, 0xed, 0xde, 0x18, 0xb7, 0xdf, 0x53, 0x61, + 0xbc, 0x18, 0x83, 0x11, 0xc7, 0xb4, 0x1b, 0x99, + 0xef, 0x14, 0xe4, 0x63, 0x39, 0xe3, 0x5c, 0x2f, + 0xe7, 0x89, 0x58, 0x5b, 0xda, 0x03, 0x3a, 0x39, + 0x96, 0x8a, 0xca, 0x4f, 0xd8, 0xe3, 0x6c, 0x7f, + 0x6e, 0xd3, 0xe7, 0x30, 0x34, 0x9c, 0xdb, 0x8b, + 0xe8, 0x6a, 0xa6, 0x08, 0x77, 0x1d, 0x63, 0xd6, + 0x57, 0x9d, 0xcd, 0xa7, 0x47, 0x05, 0x39, 0x96, + 0x7b, 0xfd, 0x9a, 0x09, 0x99, 0xef, 0x49, 0xb1, + 0x89, 0x02, 0xbe, 0x4f, 0xb8, 0xef, 0xa0, 0x04, + 0x29, 0x74, 0xfb, 0x9a, 0x7e, 0x9d, 0xa8, 0x10, + 0xfb, 0x7e, 0xb0, 0x6c, 0x60, 0x4f, 0x57, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x05, 0x53, + 0x30, 0x82, 0x05, 0x4f, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, + 0x03, 0x02, 0x05, 0xa0, 0x30, 0x81, 0x9e, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, + 0x01, 0x04, 0x81, 0x91, 0x30, 0x81, 0x8e, 0x30, + 0x4b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x02, 0x86, 0x3f, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x65, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x61, 0x63, 0x65, 0x72, 0x74, + 0x2f, 0x67, 0x73, 0x6f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, + 0x61, 0x6c, 0x73, 0x68, 0x61, 0x32, 0x67, 0x33, + 0x2e, 0x63, 0x72, 0x74, 0x30, 0x3f, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, + 0x86, 0x33, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x32, 0x2e, 0x67, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x73, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x61, 0x6c, 0x73, + 0x68, 0x61, 0x32, 0x67, 0x33, 0x30, 0x56, 0x06, + 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4f, 0x30, 0x4d, + 0x30, 0x41, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, + 0x01, 0xa0, 0x32, 0x01, 0x14, 0x30, 0x34, 0x30, + 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x02, 0x01, 0x16, 0x26, 0x68, 0x74, 0x74, + 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, + 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, + 0x72, 0x79, 0x2f, 0x30, 0x08, 0x06, 0x06, 0x67, + 0x81, 0x0c, 0x01, 0x02, 0x02, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x46, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, + 0x3f, 0x30, 0x3d, 0x30, 0x3b, 0xa0, 0x39, 0xa0, + 0x37, 0x86, 0x35, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x73, 0x6f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x76, 0x61, 0x6c, 0x73, 0x68, + 0x61, 0x32, 0x67, 0x33, 0x2e, 0x63, 0x72, 0x6c, + 0x30, 0x82, 0x02, 0x10, 0x06, 0x03, 0x55, 0x1d, + 0x11, 0x04, 0x82, 0x02, 0x07, 0x30, 0x82, 0x02, + 0x03, 0x82, 0x0b, 0x6f, 0x75, 0x74, 0x6c, 0x6f, + 0x6f, 0x6b, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x16, + 0x2a, 0x2e, 0x63, 0x6c, 0x6f, 0x2e, 0x66, 0x6f, + 0x6f, 0x74, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x64, + 0x6e, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x0d, + 0x2a, 0x2e, 0x68, 0x6f, 0x74, 0x6d, 0x61, 0x69, + 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x16, 0x2a, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x6f, 0x6f, + 0x6b, 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x0a, 0x2a, + 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x82, 0x16, 0x2a, 0x2e, 0x6e, 0x72, 0x62, + 0x2e, 0x66, 0x6f, 0x6f, 0x74, 0x70, 0x72, 0x69, + 0x6e, 0x74, 0x64, 0x6e, 0x73, 0x2e, 0x63, 0x6f, + 0x6d, 0x82, 0x0c, 0x2a, 0x2e, 0x6f, 0x66, 0x66, + 0x69, 0x63, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x82, + 0x0f, 0x2a, 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, + 0x65, 0x33, 0x36, 0x35, 0x2e, 0x63, 0x6f, 0x6d, + 0x82, 0x0d, 0x2a, 0x2e, 0x6f, 0x75, 0x74, 0x6c, + 0x6f, 0x6f, 0x6b, 0x2e, 0x63, 0x6f, 0x6d, 0x82, + 0x17, 0x2a, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x6f, + 0x6f, 0x6b, 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, + 0x65, 0x33, 0x36, 0x35, 0x2e, 0x63, 0x6f, 0x6d, + 0x82, 0x1b, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x6f, 0x75, 0x74, + 0x6c, 0x6f, 0x6f, 0x6b, 0x2e, 0x6c, 0x69, 0x76, + 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x1d, 0x61, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, + 0x74, 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x6f, 0x6f, + 0x6b, 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, + 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x20, 0x61, 0x74, + 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, + 0x2e, 0x6f, 0x75, 0x74, 0x6c, 0x6f, 0x6f, 0x6b, + 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x70, + 0x70, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x16, + 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x6f, 0x66, 0x66, 0x69, + 0x63, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x82, 0x1a, + 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x2d, 0x73, 0x64, 0x66, 0x2e, + 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x2e, 0x6e, + 0x65, 0x74, 0x82, 0x1d, 0x63, 0x63, 0x73, 0x2e, + 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x2e, 0x6d, 0x69, + 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x6f, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x82, 0x21, 0x63, 0x63, 0x73, 0x2d, 0x73, + 0x64, 0x66, 0x2e, 0x6c, 0x6f, 0x67, 0x69, 0x6e, + 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, + 0x66, 0x74, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x0b, 0x68, 0x6f, + 0x74, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x63, 0x6f, + 0x6d, 0x82, 0x16, 0x6d, 0x61, 0x69, 0x6c, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x82, 0x0d, 0x6f, 0x66, 0x66, 0x69, 0x63, + 0x65, 0x33, 0x36, 0x35, 0x2e, 0x63, 0x6f, 0x6d, + 0x82, 0x12, 0x6f, 0x75, 0x74, 0x6c, 0x6f, 0x6f, + 0x6b, 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x82, 0x14, 0x73, 0x75, + 0x62, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x2e, + 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x2e, 0x63, + 0x6f, 0x6d, 0x82, 0x18, 0x73, 0x75, 0x62, 0x73, + 0x74, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x73, 0x64, + 0x66, 0x2e, 0x6f, 0x66, 0x66, 0x69, 0x63, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, + 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x02, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x68, 0x86, 0xb8, 0x7d, 0x7a, 0xd9, 0x6d, 0x49, + 0x6b, 0x87, 0x2f, 0x18, 0x8b, 0x15, 0x34, 0x6c, + 0xd7, 0xb4, 0x7a, 0x0e, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x8a, + 0x7c, 0x73, 0x44, 0x70, 0xa8, 0x4d, 0x83, 0x25, + 0x6f, 0xa6, 0x53, 0xda, 0x42, 0x52, 0x96, 0xc9, + 0x15, 0x71, 0x21, 0x30, 0x82, 0x01, 0x7c, 0x06, + 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, + 0x02, 0x04, 0x02, 0x04, 0x82, 0x01, 0x6c, 0x04, + 0x82, 0x01, 0x68, 0x01, 0x66, 0x00, 0x76, 0x00, + 0x22, 0x45, 0x45, 0x07, 0x59, 0x55, 0x24, 0x56, + 0x96, 0x3f, 0xa1, 0x2f, 0xf1, 0xf7, 0x6d, 0x86, + 0xe0, 0x23, 0x26, 0x63, 0xad, 0xc0, 0x4b, 0x7f, + 0x5d, 0xc6, 0x83, 0x5c, 0x6e, 0xe2, 0x0f, 0x02, + 0x00, 0x00, 0x01, 0x73, 0xea, 0x1e, 0x7d, 0x2f, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x47, 0x30, 0x45, + 0x02, 0x21, 0x00, 0xf4, 0x50, 0x8f, 0xe7, 0x38, + 0xc9, 0x7a, 0xd1, 0xf7, 0xf7, 0x69, 0xc5, 0x05, + 0xea, 0x8e, 0x03, 0x80, 0x2c, 0x87, 0x06, 0x03, + 0xb6, 0x9b, 0xe6, 0xa5, 0x83, 0x2f, 0xb9, 0xaf, + 0x7b, 0xb4, 0xac, 0x02, 0x20, 0x51, 0xa6, 0x8f, + 0xe8, 0xe5, 0x6c, 0xa7, 0xff, 0x16, 0x01, 0x7e, + 0x15, 0x42, 0x11, 0x31, 0xdc, 0xdc, 0xc7, 0x37, + 0x7c, 0x64, 0x2c, 0xac, 0xdd, 0x42, 0xbb, 0x3c, + 0x79, 0x31, 0x74, 0xcc, 0x9d, 0x00, 0x75, 0x00, + 0x29, 0x79, 0xbe, 0xf0, 0x9e, 0x39, 0x39, 0x21, + 0xf0, 0x56, 0x73, 0x9f, 0x63, 0xa5, 0x77, 0xe5, + 0xbe, 0x57, 0x7d, 0x9c, 0x60, 0x0a, 0xf8, 0xf9, + 0x4d, 0x5d, 0x26, 0x5c, 0x25, 0x5d, 0xc7, 0x84, + 0x00, 0x00, 0x01, 0x73, 0xea, 0x1e, 0x7a, 0xa7, + 0x00, 0x00, 0x04, 0x03, 0x00, 0x46, 0x30, 0x44, + 0x02, 0x20, 0x03, 0xf1, 0x19, 0xd7, 0x0f, 0x2f, + 0xc4, 0xa9, 0x84, 0xa0, 0x33, 0xd4, 0x76, 0xa6, + 0xee, 0xf1, 0xae, 0xe0, 0x03, 0xe7, 0xae, 0x98, + 0x43, 0x17, 0xb0, 0x0f, 0xfb, 0x12, 0xbb, 0x13, + 0xda, 0x34, 0x02, 0x20, 0x10, 0xe6, 0xa9, 0x1d, + 0x8b, 0x1c, 0x64, 0xd4, 0xc9, 0xf7, 0xc0, 0x3d, + 0x3c, 0x77, 0x49, 0xb1, 0x08, 0x3d, 0x1d, 0x5e, + 0x34, 0xf9, 0xd9, 0x10, 0x7c, 0x74, 0x6b, 0x18, + 0xc6, 0x5e, 0x6d, 0x07, 0x00, 0x75, 0x00, 0x55, + 0x81, 0xd4, 0xc2, 0x16, 0x90, 0x36, 0x01, 0x4a, + 0xea, 0x0b, 0x9b, 0x57, 0x3c, 0x53, 0xf0, 0xc0, + 0xe4, 0x38, 0x78, 0x70, 0x25, 0x08, 0x17, 0x2f, + 0xa3, 0xaa, 0x1d, 0x07, 0x13, 0xd3, 0x0c, 0x00, + 0x00, 0x01, 0x73, 0xea, 0x1e, 0x7d, 0xae, 0x00, + 0x00, 0x04, 0x03, 0x00, 0x46, 0x30, 0x44, 0x02, + 0x20, 0x26, 0x21, 0x64, 0xdb, 0xa6, 0xe2, 0x3d, + 0x32, 0x7d, 0x9f, 0xa8, 0xae, 0xb7, 0x29, 0xb7, + 0x42, 0x9b, 0x49, 0xaa, 0xf5, 0xa5, 0xc0, 0x12, + 0x01, 0xa1, 0xb6, 0xe7, 0xf2, 0x01, 0xd4, 0x2f, + 0x45, 0x02, 0x20, 0x4e, 0x19, 0xba, 0x47, 0x75, + 0x8b, 0x49, 0xd7, 0x4b, 0xba, 0x04, 0x62, 0xdd, + 0xa2, 0xb7, 0x6b, 0x05, 0xd0, 0x01, 0x1f, 0x7c, + 0x36, 0x17, 0x27, 0x29, 0xb2, 0x17, 0x1c, 0x7f, + 0x10, 0x81, 0x8a, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x26, + 0xf4, 0xa3, 0x77, 0x1d, 0xdc, 0x9e, 0xc4, 0x1a, + 0x88, 0x23, 0x30, 0x8c, 0xe1, 0x14, 0xf9, 0x62, + 0x0e, 0xbf, 0xad, 0x24, 0xc9, 0xab, 0xab, 0xd0, + 0x68, 0x8b, 0xbc, 0xf1, 0xec, 0x1c, 0xd0, 0x96, + 0xad, 0xf9, 0x5f, 0xdd, 0xe0, 0xee, 0xa8, 0xe0, + 0x2c, 0x3a, 0x19, 0xa5, 0x68, 0x0c, 0x6e, 0xfe, + 0xe6, 0x80, 0xce, 0xa3, 0x3b, 0x6c, 0x00, 0x88, + 0x5c, 0xbf, 0x3c, 0xd8, 0x68, 0x08, 0x36, 0xb9, + 0x9e, 0x84, 0x9b, 0x5f, 0x97, 0xfb, 0x77, 0xea, + 0x72, 0xfb, 0x73, 0x47, 0x00, 0xb0, 0xa8, 0x7c, + 0x64, 0x38, 0xf1, 0xcc, 0xc0, 0x29, 0x71, 0x67, + 0x65, 0x76, 0x4c, 0x80, 0x58, 0x97, 0xc8, 0x62, + 0x63, 0x3e, 0xf1, 0x3e, 0xc0, 0x0e, 0x48, 0x5f, + 0x55, 0x21, 0x8f, 0x96, 0x68, 0xbd, 0x41, 0x14, + 0x7a, 0x0b, 0x8c, 0x31, 0x5b, 0x39, 0xac, 0xa3, + 0xa0, 0x99, 0x58, 0x24, 0xfa, 0xd9, 0x19, 0x32, + 0x1c, 0x9f, 0x2d, 0xa9, 0xed, 0xb9, 0x97, 0xa4, + 0x66, 0x30, 0x29, 0xd8, 0x82, 0xa2, 0xf5, 0xfc, + 0x6d, 0x10, 0xf1, 0xac, 0x1d, 0x3f, 0xfb, 0xde, + 0xa1, 0x0e, 0xb6, 0x84, 0x90, 0xd4, 0x55, 0x5c, + 0x21, 0x1b, 0x1f, 0x21, 0x45, 0x92, 0xc5, 0x9a, + 0x47, 0x05, 0x0f, 0xb8, 0x1c, 0x78, 0x6e, 0xb9, + 0x6b, 0xa3, 0xa9, 0x8d, 0xb1, 0x59, 0xff, 0xf4, + 0xe6, 0x71, 0x77, 0x38, 0x12, 0xfe, 0x41, 0x8f, + 0x04, 0x92, 0x08, 0x3f, 0x32, 0x2a, 0x92, 0x5e, + 0x0a, 0x7b, 0x7e, 0x04, 0xee, 0x24, 0x10, 0x39, + 0xf3, 0xac, 0x5e, 0x04, 0x93, 0x91, 0xa2, 0x8f, + 0x90, 0x04, 0x33, 0x5c, 0x5c, 0x94, 0xb3, 0x80, + 0x2b, 0x43, 0xbf, 0xe3, 0x74, 0x64, 0x20, 0xf4, + 0x00, 0xb2, 0x6c, 0x7b, 0xa8, 0x77, 0xfb, 0x74, + 0x35, 0xce, 0xdd, 0xb6, 0x5f, 0x83, 0x18, 0xc4, + 0xe7, 0x31, 0x1a, 0x8d, 0x30, 0x0d, 0xc4, 0x00, + 0x04, 0x8f, 0x30, 0x82, 0x04, 0x8b, 0x30, 0x82, + 0x03, 0x73, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x0e, 0x47, 0x07, 0xb1, 0x01, 0x9a, 0x0c, 0x57, + 0xad, 0x39, 0xb3, 0xe1, 0x7d, 0xa9, 0xf9, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x57, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x10, + 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, 0x69, + 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, 0x61, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x07, 0x52, 0x6f, 0x6f, 0x74, 0x20, + 0x43, 0x41, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x39, 0x30, + 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, + 0x17, 0x0d, 0x32, 0x35, 0x30, 0x39, 0x30, 0x34, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, + 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x42, 0x45, 0x31, 0x19, + 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x10, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x53, + 0x69, 0x67, 0x6e, 0x20, 0x6e, 0x76, 0x2d, 0x73, + 0x61, 0x31, 0x3c, 0x30, 0x3a, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x33, 0x47, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x4f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, + 0x41, 0x20, 0x2d, 0x20, 0x53, 0x48, 0x41, 0x32, + 0x35, 0x36, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, + 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, + 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xc9, 0x86, 0xa2, 0x05, 0x3e, 0xec, 0x77, 0x4d, + 0x79, 0x42, 0x81, 0xf2, 0xc5, 0x46, 0xa9, 0xc2, + 0x9b, 0xf9, 0x57, 0xa9, 0x48, 0xdd, 0x3c, 0x3b, + 0xe2, 0x16, 0x47, 0x83, 0x15, 0x0c, 0x36, 0x88, + 0x61, 0xb3, 0xc8, 0xb9, 0xd5, 0x20, 0x97, 0xb6, + 0xfe, 0x07, 0x30, 0x01, 0x9e, 0x01, 0x3a, 0xf9, + 0x50, 0x87, 0xa0, 0x4f, 0x60, 0xcc, 0x90, 0xf6, + 0xdd, 0x1f, 0xa6, 0xc7, 0x55, 0x00, 0x6c, 0x54, + 0x31, 0x5f, 0x02, 0x9a, 0xf7, 0x7f, 0x07, 0x9a, + 0xd2, 0x22, 0x53, 0x05, 0xcd, 0x9f, 0xc7, 0xbb, + 0x7b, 0x59, 0x3b, 0x8a, 0xb2, 0x93, 0x78, 0x0d, + 0x43, 0x02, 0x92, 0x76, 0xa5, 0x29, 0xf8, 0x7c, + 0x9d, 0x5c, 0x3a, 0xa2, 0xf8, 0x52, 0x72, 0x22, + 0x45, 0x91, 0xfd, 0x90, 0x12, 0x28, 0x4d, 0x75, + 0xe4, 0xdd, 0xaa, 0x79, 0x58, 0x68, 0x6f, 0x2a, + 0x7e, 0x7b, 0xef, 0xd1, 0x9e, 0x7f, 0x52, 0xdc, + 0xcb, 0x1c, 0x48, 0xe2, 0x3e, 0x4d, 0x5c, 0x47, + 0x7a, 0xb4, 0xf1, 0xce, 0xff, 0xd9, 0x60, 0x2b, + 0x77, 0xd1, 0x62, 0x22, 0x2d, 0xa9, 0x5a, 0x06, + 0x16, 0xee, 0x37, 0x6a, 0x51, 0xcf, 0x8e, 0xa5, + 0xd1, 0x6e, 0x70, 0x4a, 0xf0, 0xd8, 0x63, 0x60, + 0x6a, 0x72, 0x55, 0xd7, 0xf1, 0x99, 0x38, 0x86, + 0x44, 0x67, 0x18, 0xe0, 0x71, 0x8e, 0xc1, 0x40, + 0x6d, 0x85, 0xda, 0x4b, 0xdd, 0x31, 0x73, 0xbc, + 0x32, 0xcc, 0x6f, 0x8e, 0x7b, 0xb9, 0x8d, 0x4b, + 0x80, 0xda, 0xb9, 0xc7, 0xc6, 0x24, 0x83, 0x5e, + 0x32, 0xfb, 0x87, 0xe9, 0x8b, 0x61, 0x67, 0xa2, + 0x99, 0x76, 0xdb, 0xa5, 0xaa, 0xb4, 0xe8, 0x6c, + 0x41, 0x9f, 0x5f, 0x2a, 0xb3, 0xd5, 0x7d, 0xd7, + 0x92, 0xc8, 0x27, 0x4b, 0xec, 0x1f, 0xda, 0x05, + 0x6d, 0x88, 0x73, 0x8f, 0x06, 0xb2, 0x38, 0x3d, + 0x03, 0xa2, 0xe1, 0x87, 0x86, 0x3c, 0xc6, 0xa1, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, + 0x44, 0x30, 0x82, 0x01, 0x40, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x03, 0x02, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, + 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x68, 0x86, 0xb8, 0x7d, 0x7a, + 0xd9, 0x6d, 0x49, 0x6b, 0x87, 0x2f, 0x18, 0x8b, + 0x15, 0x34, 0x6c, 0xd7, 0xb4, 0x7a, 0x0e, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x60, 0x7b, 0x66, 0x1a, + 0x45, 0x0d, 0x97, 0xca, 0x89, 0x50, 0x2f, 0x7d, + 0x04, 0xcd, 0x34, 0xa8, 0xff, 0xfc, 0xfd, 0x4b, + 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, 0x30, 0x2f, + 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, + 0x70, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x72, 0x6f, 0x6f, 0x74, 0x72, 0x31, 0x30, + 0x33, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x2c, + 0x30, 0x2a, 0x30, 0x28, 0xa0, 0x26, 0xa0, 0x24, + 0x86, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x6c, 0x6f, + 0x62, 0x61, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x6f, 0x6f, 0x74, + 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x47, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x40, 0x30, 0x3e, 0x30, + 0x3c, 0x06, 0x04, 0x55, 0x1d, 0x20, 0x00, 0x30, + 0x34, 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x26, 0x68, + 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, + 0x77, 0x77, 0x2e, 0x67, 0x6c, 0x6f, 0x62, 0x61, + 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0x9a, 0xb9, 0x82, 0x1c, 0xdd, 0x83, 0x83, + 0x8b, 0x92, 0xc0, 0xc4, 0xed, 0x01, 0xad, 0x84, + 0xfc, 0x4e, 0xee, 0x6d, 0x9c, 0x1d, 0x01, 0xfa, + 0x52, 0x14, 0xdb, 0xd8, 0xc2, 0x10, 0x63, 0x9f, + 0x6b, 0x39, 0x9a, 0xc7, 0x1c, 0x3c, 0xa0, 0xaa, + 0xe3, 0x19, 0x3a, 0xfc, 0x64, 0x46, 0x2a, 0xef, + 0x35, 0x26, 0x03, 0xf6, 0x05, 0x67, 0xfa, 0x6e, + 0x74, 0xe1, 0x46, 0xfb, 0x40, 0xd8, 0x6f, 0xae, + 0x2d, 0x39, 0x21, 0x74, 0x86, 0x9f, 0x00, 0x05, + 0x1a, 0x3f, 0x2f, 0x93, 0x5b, 0xd4, 0xa4, 0x45, + 0xbc, 0x3d, 0x0c, 0x29, 0x17, 0x5a, 0xd3, 0xfb, + 0x68, 0xa6, 0x0f, 0xe0, 0x00, 0x68, 0x79, 0xb0, + 0x4c, 0xb1, 0x45, 0x8b, 0xc8, 0x85, 0x8c, 0x67, + 0x0e, 0x8c, 0x7d, 0x54, 0xf8, 0xb0, 0x75, 0xce, + 0x0a, 0xac, 0x1d, 0xd7, 0x6b, 0x44, 0xac, 0xfe, + 0x1b, 0xd4, 0xa6, 0x98, 0x21, 0x09, 0x3e, 0xa2, + 0x4b, 0x33, 0xba, 0xba, 0x4b, 0x12, 0xa8, 0x6b, + 0x57, 0x27, 0x9d, 0xfa, 0x94, 0x80, 0xb4, 0x68, + 0x4c, 0x77, 0x60, 0xff, 0xd7, 0x29, 0x5a, 0x38, + 0x3d, 0xce, 0x2d, 0x4b, 0x08, 0x56, 0x9f, 0x69, + 0xcb, 0x7b, 0xd8, 0xe2, 0x36, 0xf9, 0x37, 0x69, + 0xc5, 0xce, 0x36, 0x97, 0x1c, 0xba, 0x0d, 0x3f, + 0x15, 0xb3, 0x65, 0xa0, 0xec, 0x74, 0x12, 0xbd, + 0xb3, 0xad, 0xe8, 0xde, 0x9e, 0xa1, 0xec, 0xd3, + 0xbf, 0xa9, 0xe0, 0xa5, 0x91, 0x6d, 0x83, 0x59, + 0x12, 0x56, 0x2f, 0x13, 0xa6, 0x7e, 0x79, 0x73, + 0xa1, 0xa3, 0x89, 0xd5, 0xe1, 0xa5, 0x8c, 0xce, + 0x2d, 0xac, 0x8a, 0xcf, 0x62, 0x16, 0x65, 0xcd, + 0xd9, 0xee, 0xa8, 0xb6, 0x40, 0x08, 0xb5, 0x7c, + 0x50, 0xf9, 0x37, 0x82, 0x7a, 0xa4, 0x0b, 0x34, + 0x66, 0xec, 0xe9, 0x97, 0x57, 0x1f, 0x8a, 0x67, + 0x3e, 0x81, 0xbc, 0x3b, 0x35, 0xd3, 0x2a, 0x48, + 0x0c, 0x0c, 0x00, 0x01, 0x69, 0x03, 0x00, 0x18, + 0x61, 0x04, 0xb7, 0xa9, 0xbd, 0x74, 0x71, 0xd5, + 0x68, 0xbf, 0xd8, 0xa6, 0x84, 0x12, 0xaf, 0x8f, + 0xd4, 0x2c, 0xcf, 0xf9, 0x72, 0x2b, 0x8c, 0x6c, + 0x73, 0xa3, 0x13, 0x74, 0xdb, 0x83, 0x3e, 0xa6, + 0xf4, 0x1b, 0xee, 0xa9, 0x34, 0xe5, 0x65, 0xa7, + 0xaf, 0xef, 0xf2, 0xac, 0xfb, 0x87, 0xb4, 0xdb, + 0x8b, 0x05, 0x4f, 0xe8, 0x25, 0x3d, 0x32, 0x65, + 0xda, 0x47, 0xd8, 0xd2, 0x86, 0xad, 0x9b, 0x37, + 0xbc, 0x45, 0xef, 0xb6, 0x91, 0xa2, 0x71, 0x2f, + 0x13, 0x68, 0xfa, 0xa7, 0x20, 0xe4, 0x8a, 0xa8, + 0x9b, 0xbe, 0xf6, 0x7c, 0xc8, 0x16, 0xd4, 0x50, + 0x9d, 0x63, 0xb3, 0xf4, 0x6e, 0xd3, 0x8f, 0x32, + 0x68, 0x66, 0x04, 0x01, 0x01, 0x00, 0xaa, 0xcb, + 0x90, 0xbd, 0x94, 0x10, 0xab, 0xfc, 0x30, 0x1d, + 0x68, 0x1c, 0xb4, 0x21, 0xcf, 0x73, 0xa5, 0x4b, + 0x20, 0x94, 0xde, 0x66, 0x99, 0x54, 0x3f, 0xba, + 0x40, 0x58, 0x50, 0xe3, 0x64, 0x53, 0x90, 0x9e, + 0xf8, 0x67, 0xcc, 0x85, 0x4a, 0xdc, 0xd8, 0xd7, + 0xc8, 0xb5, 0xe0, 0x92, 0x02, 0x6b, 0xa8, 0x76, + 0x67, 0xc5, 0xae, 0x12, 0x56, 0xff, 0xd1, 0xda, + 0xc0, 0x48, 0x17, 0x99, 0xc9, 0xbe, 0x02, 0xc6, + 0x9e, 0x5c, 0xd9, 0x44, 0x3f, 0x06, 0xbd, 0x98, + 0xe3, 0x4d, 0x46, 0x10, 0xe8, 0x20, 0xed, 0x7b, + 0xcd, 0x73, 0xed, 0x03, 0x6a, 0x4c, 0x49, 0xaf, + 0xbe, 0xa3, 0xe0, 0xab, 0x9a, 0xb8, 0xf8, 0x06, + 0x25, 0x31, 0x8d, 0x32, 0x44, 0xfd, 0xd6, 0xb0, + 0xd4, 0x6c, 0x9a, 0x2a, 0x0f, 0xab, 0xe2, 0x13, + 0x10, 0x6d, 0x41, 0x0b, 0x97, 0x74, 0xa0, 0x04, + 0x16, 0x60, 0xf1, 0x8e, 0x74, 0xf3, 0x91, 0x75, + 0x2b, 0x92, 0x2b, 0xc7, 0x5b, 0x6f, 0x1d, 0x70, + 0xe2, 0xc6, 0x9a, 0x7d, 0x66, 0x55, 0x98, 0x01, + 0x71, 0xb8, 0xdd, 0xf4, 0x70, 0xc9, 0x74, 0x56, + 0xcc, 0xa5, 0x2c, 0x51, 0x70, 0x72, 0xc2, 0x44, + 0xb9, 0x59, 0xc3, 0xc3, 0xf8, 0x29, 0x4e, 0x79, + 0x40, 0x9b, 0x30, 0x35, 0x66, 0xb2, 0xd8, 0x7d, + 0xfe, 0x65, 0x6b, 0xf0, 0x17, 0xa3, 0x13, 0xc7, + 0xc7, 0xc6, 0x48, 0xb2, 0xae, 0x4f, 0x26, 0x0b, + 0x8a, 0x40, 0xaa, 0x06, 0x65, 0x8a, 0x95, 0x00, + 0xc4, 0xc9, 0xfd, 0x69, 0x0a, 0xa9, 0x0a, 0x18, + 0xff, 0x95, 0x40, 0xab, 0x84, 0x75, 0xfe, 0x11, + 0xb1, 0x6f, 0xca, 0x5e, 0xf7, 0xe4, 0x1d, 0x8d, + 0x08, 0x1c, 0xd3, 0x95, 0xf4, 0x9b, 0x17, 0x41, + 0xa8, 0x8f, 0x6e, 0xfa, 0x6c, 0x43, 0x60, 0x39, + 0x0a, 0xa2, 0x7e, 0xdf, 0x3e, 0x74, 0xc2, 0xbf, + 0xaf, 0x96, 0x96, 0xbd, 0x21, 0x4b, 0x0d, 0x00, + 0x00, 0x1a, 0x03, 0x01, 0x02, 0x40, 0x00, 0x12, + 0x04, 0x01, 0x05, 0x01, 0x02, 0x01, 0x04, 0x03, + 0x05, 0x03, 0x02, 0x03, 0x02, 0x02, 0x06, 0x01, + 0x06, 0x03, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, +}; + +struct tlslegacy_client_test { + const unsigned char *desc; + unsigned char *server_response; + const size_t server_response_len; + const SSL_METHOD *(*ssl_method)(void); + int want_state; +}; + +static struct tlslegacy_client_test tlslegacy_client_tests[] = { + { + .desc = "TLSv1.2 legacy fallback", + .server_response = tls12_server_response, + .server_response_len = sizeof(tls12_server_response), + .ssl_method = TLS_client_method, + .want_state = SSL3_ST_CR_CERT_A, + }, + { + .desc = "TLSv1.2 legacy fallback with server cert", + .server_response = tls12_server_response_with_cert, + .server_response_len = sizeof(tls12_server_response_with_cert), + .ssl_method = TLS_client_method, + .want_state = SSL3_ST_CR_KEY_EXCH_B, + }, +}; + +#define N_TLSLEGACY_CLIENT_TESTS \ + (sizeof(tlslegacy_client_tests) / sizeof(*tlslegacy_client_tests)) + +static int +tlslegacy_client_test(int testno, struct tlslegacy_client_test *tct) +{ + BIO *rbio = NULL, *wbio = NULL; + SSL_CTX *ssl_ctx = NULL; + SSL *ssl = NULL; + int ret = 1; + + fprintf(stderr, "Test %d - %s\n", testno, tct->desc); + + if ((rbio = BIO_new_mem_buf(tct->server_response, + tct->server_response_len)) == NULL) { + fprintf(stderr, "Failed to setup rbio\n"); + goto failure; + } + if ((wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "Failed to setup wbio\n"); + goto failure; + } + + if ((ssl_ctx = SSL_CTX_new(tct->ssl_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new() returned NULL\n"); + goto failure; + } + + if ((ssl = SSL_new(ssl_ctx)) == NULL) { + fprintf(stderr, "SSL_new() returned NULL\n"); + goto failure; + } + + BIO_up_ref(rbio); + BIO_up_ref(wbio); + SSL_set_bio(ssl, rbio, wbio); + + if (SSL_connect(ssl) == 1) { + fprintf(stderr, "SSL_connect() succeeded\n"); + goto failure; + } + + if (SSL_state(ssl) != tct->want_state) { + fprintf(stderr, "FAIL: Got SSL state %x, want %x", + SSL_state(ssl), tct->want_state); + goto failure; + } + + ret = 0; + + failure: + SSL_CTX_free(ssl_ctx); + SSL_free(ssl); + + BIO_free(rbio); + BIO_free(wbio); + + return (ret); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_TLSLEGACY_CLIENT_TESTS; i++) + failed |= tlslegacy_client_test(i, &tlslegacy_client_tests[i]); + + return (failed); +} diff --git a/tests/tlstest.c b/tests/tlstest.c new file mode 100644 index 0000000..fb6649e --- /dev/null +++ b/tests/tlstest.c @@ -0,0 +1,555 @@ +/* $OpenBSD: tlstest.c,v 1.15 2022/07/16 07:46:08 tb Exp $ */ +/* + * Copyright (c) 2017 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#define CIRCULAR_BUFFER_SIZE 512 + +unsigned char client_buffer[CIRCULAR_BUFFER_SIZE]; +unsigned char *client_readptr, *client_writeptr; + +unsigned char server_buffer[CIRCULAR_BUFFER_SIZE]; +unsigned char *server_readptr, *server_writeptr; + +char *cafile, *certfile, *keyfile; + +int debug = 0; + +static void +circular_init(void) +{ + client_readptr = client_writeptr = client_buffer; + server_readptr = server_writeptr = server_buffer; +} + +static ssize_t +circular_read(char *name, unsigned char *buf, size_t bufsize, + unsigned char **readptr, unsigned char *writeptr, + unsigned char *outbuf, size_t outlen) +{ + unsigned char *nextptr = *readptr; + size_t n = 0; + + while (n < outlen) { + if (nextptr == writeptr) + break; + *outbuf++ = *nextptr++; + if ((size_t)(nextptr - buf) >= bufsize) + nextptr = buf; + *readptr = nextptr; + n++; + } + + if (debug && n > 0) + fprintf(stderr, "%s buffer: read %zi bytes\n", name, n); + + return (n > 0 ? (ssize_t)n : TLS_WANT_POLLIN); +} + +static ssize_t +circular_write(char *name, unsigned char *buf, size_t bufsize, + unsigned char *readptr, unsigned char **writeptr, + const unsigned char *inbuf, size_t inlen) +{ + unsigned char *nextptr = *writeptr; + unsigned char *prevptr; + size_t n = 0; + + while (n < inlen) { + prevptr = nextptr++; + if ((size_t)(nextptr - buf) >= bufsize) + nextptr = buf; + if (nextptr == readptr) + break; + *prevptr = *inbuf++; + *writeptr = nextptr; + n++; + } + + if (debug && n > 0) + fprintf(stderr, "%s buffer: wrote %zi bytes\n", name, n); + + return (n > 0 ? (ssize_t)n : TLS_WANT_POLLOUT); +} + +static ssize_t +client_read(struct tls *ctx, void *buf, size_t buflen, void *cb_arg) +{ + return circular_read("client", client_buffer, sizeof(client_buffer), + &client_readptr, client_writeptr, buf, buflen); +} + +static ssize_t +client_write(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg) +{ + return circular_write("server", server_buffer, sizeof(server_buffer), + server_readptr, &server_writeptr, buf, buflen); +} + +static ssize_t +server_read(struct tls *ctx, void *buf, size_t buflen, void *cb_arg) +{ + return circular_read("server", server_buffer, sizeof(server_buffer), + &server_readptr, server_writeptr, buf, buflen); +} + +static ssize_t +server_write(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg) +{ + return circular_write("client", client_buffer, sizeof(client_buffer), + client_readptr, &client_writeptr, buf, buflen); +} + +static int +do_tls_handshake(char *name, struct tls *ctx) +{ + int rv; + + rv = tls_handshake(ctx); + if (rv == 0) + return (1); + if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT) + return (0); + + errx(1, "%s handshake failed: %s", name, tls_error(ctx)); +} + +static int +do_tls_close(char *name, struct tls *ctx) +{ + int rv; + + rv = tls_close(ctx); + if (rv == 0) + return (1); + if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT) + return (0); + + errx(1, "%s close failed: %s", name, tls_error(ctx)); +} + +static int +do_client_server_handshake(char *desc, struct tls *client, + struct tls *server_cctx) +{ + int i, client_done, server_done; + + i = client_done = server_done = 0; + do { + if (client_done == 0) + client_done = do_tls_handshake("client", client); + if (server_done == 0) + server_done = do_tls_handshake("server", server_cctx); + } while (i++ < 100 && (client_done == 0 || server_done == 0)); + + if (client_done == 0 || server_done == 0) { + printf("FAIL: %s TLS handshake did not complete\n", desc); + return (1); + } + + return (0); +} + +static int +do_client_server_close(char *desc, struct tls *client, struct tls *server_cctx) +{ + int i, client_done, server_done; + + i = client_done = server_done = 0; + do { + if (client_done == 0) + client_done = do_tls_close("client", client); + if (server_done == 0) + server_done = do_tls_close("server", server_cctx); + } while (i++ < 100 && (client_done == 0 || server_done == 0)); + + if (client_done == 0 || server_done == 0) { + printf("FAIL: %s TLS close did not complete\n", desc); + return (1); + } + + return (0); +} + +static int +do_client_server_test(char *desc, struct tls *client, struct tls *server_cctx) +{ + if (do_client_server_handshake(desc, client, server_cctx) != 0) + return (1); + + printf("INFO: %s TLS handshake completed successfully\n", desc); + + /* XXX - Do some reads and writes... */ + + if (do_client_server_close(desc, client, server_cctx) != 0) + return (1); + + printf("INFO: %s TLS close completed successfully\n", desc); + + return (0); +} + +static int +test_tls_cbs(struct tls *client, struct tls *server) +{ + struct tls *server_cctx; + int failure; + + circular_init(); + + if (tls_accept_cbs(server, &server_cctx, server_read, server_write, + NULL) == -1) + errx(1, "failed to accept: %s", tls_error(server)); + + if (tls_connect_cbs(client, client_read, client_write, NULL, + "test") == -1) + errx(1, "failed to connect: %s", tls_error(client)); + + failure = do_client_server_test("callback", client, server_cctx); + + tls_free(server_cctx); + + return (failure); +} + +static int +test_tls_fds(struct tls *client, struct tls *server) +{ + struct tls *server_cctx; + int cfds[2], sfds[2]; + int failure; + + if (pipe2(cfds, O_NONBLOCK) == -1) + err(1, "failed to create pipe"); + if (pipe2(sfds, O_NONBLOCK) == -1) + err(1, "failed to create pipe"); + + if (tls_accept_fds(server, &server_cctx, sfds[0], cfds[1]) == -1) + errx(1, "failed to accept: %s", tls_error(server)); + + if (tls_connect_fds(client, cfds[0], sfds[1], "test") == -1) + errx(1, "failed to connect: %s", tls_error(client)); + + failure = do_client_server_test("file descriptor", client, server_cctx); + + tls_free(server_cctx); + + close(cfds[0]); + close(cfds[1]); + close(sfds[0]); + close(sfds[1]); + + return (failure); +} + +static int +test_tls_socket(struct tls *client, struct tls *server) +{ + struct tls *server_cctx; + int failure; + int sv[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC, + sv) == -1) + err(1, "failed to create socketpair"); + + if (tls_accept_socket(server, &server_cctx, sv[0]) == -1) + errx(1, "failed to accept: %s", tls_error(server)); + + if (tls_connect_socket(client, sv[1], "test") == -1) + errx(1, "failed to connect: %s", tls_error(client)); + + failure = do_client_server_test("socket", client, server_cctx); + + tls_free(server_cctx); + + close(sv[0]); + close(sv[1]); + + return (failure); +} + +static int +test_tls(char *client_protocols, char *server_protocols, char *ciphers) +{ + struct tls_config *client_cfg, *server_cfg; + struct tls *client, *server; + uint32_t protocols; + int failure = 0; + + if ((client = tls_client()) == NULL) + errx(1, "failed to create tls client"); + if ((client_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls client config"); + tls_config_insecure_noverifyname(client_cfg); + if (tls_config_parse_protocols(&protocols, client_protocols) == -1) + errx(1, "failed to parse protocols: %s", tls_config_error(client_cfg)); + if (tls_config_set_protocols(client_cfg, protocols) == -1) + errx(1, "failed to set protocols: %s", tls_config_error(client_cfg)); + if (tls_config_set_ciphers(client_cfg, ciphers) == -1) + errx(1, "failed to set ciphers: %s", tls_config_error(client_cfg)); + if (tls_config_set_ca_file(client_cfg, cafile) == -1) + errx(1, "failed to set ca: %s", tls_config_error(client_cfg)); + + if ((server = tls_server()) == NULL) + errx(1, "failed to create tls server"); + if ((server_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls server config"); + if (tls_config_parse_protocols(&protocols, server_protocols) == -1) + errx(1, "failed to parse protocols: %s", tls_config_error(server_cfg)); + if (tls_config_set_protocols(server_cfg, protocols) == -1) + errx(1, "failed to set protocols: %s", tls_config_error(server_cfg)); + if (tls_config_set_ciphers(server_cfg, ciphers) == -1) + errx(1, "failed to set ciphers: %s", tls_config_error(server_cfg)); + if (tls_config_set_keypair_file(server_cfg, certfile, keyfile) == -1) + errx(1, "failed to set keypair: %s", + tls_config_error(server_cfg)); + + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + tls_reset(server); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + tls_config_free(client_cfg); + tls_config_free(server_cfg); + + failure |= test_tls_cbs(client, server); + + tls_free(client); + tls_free(server); + + return (failure); +} + +static int +do_tls_tests(void) +{ + struct tls_config *client_cfg, *server_cfg; + struct tls *client, *server; + int failure = 0; + + printf("== TLS tests ==\n"); + + if ((client = tls_client()) == NULL) + errx(1, "failed to create tls client"); + if ((client_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls client config"); + tls_config_insecure_noverifyname(client_cfg); + if (tls_config_set_ca_file(client_cfg, cafile) == -1) + errx(1, "failed to set ca: %s", tls_config_error(client_cfg)); + + if ((server = tls_server()) == NULL) + errx(1, "failed to create tls server"); + if ((server_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls server config"); + if (tls_config_set_keypair_file(server_cfg, certfile, keyfile) == -1) + errx(1, "failed to set keypair: %s", + tls_config_error(server_cfg)); + + tls_reset(client); + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + tls_reset(server); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + failure |= test_tls_cbs(client, server); + + tls_reset(client); + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + tls_reset(server); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + failure |= test_tls_fds(client, server); + + tls_reset(client); + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + tls_reset(server); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + tls_config_free(client_cfg); + tls_config_free(server_cfg); + + failure |= test_tls_socket(client, server); + + tls_free(client); + tls_free(server); + + printf("\n"); + + return (failure); +} + +static int +do_tls_ordering_tests(void) +{ + struct tls *client = NULL, *server = NULL, *server_cctx = NULL; + struct tls_config *client_cfg, *server_cfg; + int failure = 0; + + printf("== TLS ordering tests ==\n"); + + if ((client = tls_client()) == NULL) + errx(1, "failed to create tls client"); + if ((client_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls client config"); + tls_config_insecure_noverifyname(client_cfg); + if (tls_config_set_ca_file(client_cfg, cafile) == -1) + errx(1, "failed to set ca: %s", tls_config_error(client_cfg)); + + if ((server = tls_server()) == NULL) + errx(1, "failed to create tls server"); + if ((server_cfg = tls_config_new()) == NULL) + errx(1, "failed to create tls server config"); + if (tls_config_set_keypair_file(server_cfg, certfile, keyfile) == -1) + errx(1, "failed to set keypair: %s", + tls_config_error(server_cfg)); + + if (tls_configure(client, client_cfg) == -1) + errx(1, "failed to configure client: %s", tls_error(client)); + if (tls_configure(server, server_cfg) == -1) + errx(1, "failed to configure server: %s", tls_error(server)); + + tls_config_free(client_cfg); + tls_config_free(server_cfg); + + if (tls_handshake(client) != -1) { + printf("FAIL: TLS handshake succeeded on unconnnected " + "client context\n"); + failure = 1; + goto done; + } + + circular_init(); + + if (tls_accept_cbs(server, &server_cctx, server_read, server_write, + NULL) == -1) + errx(1, "failed to accept: %s", tls_error(server)); + + if (tls_connect_cbs(client, client_read, client_write, NULL, + "test") == -1) + errx(1, "failed to connect: %s", tls_error(client)); + + if (do_client_server_handshake("ordering", client, server_cctx) != 0) { + failure = 1; + goto done; + } + + if (tls_handshake(client) != -1) { + printf("FAIL: TLS handshake succeeded twice\n"); + failure = 1; + goto done; + } + + if (tls_handshake(server_cctx) != -1) { + printf("FAIL: TLS handshake succeeded twice\n"); + failure = 1; + goto done; + } + + if (do_client_server_close("ordering", client, server_cctx) != 0) { + failure = 1; + goto done; + } + + done: + tls_free(client); + tls_free(server); + tls_free(server_cctx); + + printf("\n"); + + return (failure); +} + +struct test_versions { + char *client; + char *server; +}; + +static struct test_versions tls_test_versions[] = { + {"tlsv1.3", "all"}, + {"tlsv1.2", "all"}, + {"tlsv1.1", "all"}, + {"tlsv1.0", "all"}, + {"all", "tlsv1.3"}, + {"all", "tlsv1.2"}, + {"all", "tlsv1.1"}, + {"all", "tlsv1.0"}, + {"tlsv1.3", "tlsv1.3"}, + {"tlsv1.2", "tlsv1.2"}, + {"tlsv1.1", "tlsv1.1"}, + {"tlsv1.0", "tlsv1.0"}, +}; + +#define N_TLS_VERSION_TESTS \ + (sizeof(tls_test_versions) / sizeof(*tls_test_versions)) + +static int +do_tls_version_tests(void) +{ + struct test_versions *tv; + int failure = 0; + size_t i; + + printf("== TLS version tests ==\n"); + + for (i = 0; i < N_TLS_VERSION_TESTS; i++) { + tv = &tls_test_versions[i]; + printf("INFO: version test %zu - client versions '%s' " + "and server versions '%s'\n", i, tv->client, tv->server); + failure |= test_tls(tv->client, tv->server, "legacy"); + printf("\n"); + } + + return failure; +} + +int +main(int argc, char **argv) +{ + int failure = 0; + + if (argc != 4) { + fprintf(stderr, "usage: %s cafile certfile keyfile\n", + argv[0]); + return (1); + } + + cafile = argv[1]; + certfile = argv[2]; + keyfile = argv[3]; + + failure |= do_tls_tests(); + failure |= do_tls_ordering_tests(); + failure |= do_tls_version_tests(); + + return (failure); +} diff --git a/tests/utf8test.c b/tests/utf8test.c new file mode 100644 index 0000000..26477e8 --- /dev/null +++ b/tests/utf8test.c @@ -0,0 +1,319 @@ +/* $OpenBSD: utf8test.c,v 1.5 2022/11/26 16:08:56 tb Exp $ */ +/* + * Copyright (c) 2014 Philip Guenther + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * A mostly exhaustive test of UTF-8 decoder and encoder + */ + +#include +#include +#include + +#include +#include "asn1_local.h" /* peek into the internals */ + +#define UNCHANGED 0xfedcba98 + +#define ASSERT(x) \ + do { \ + if (!(x)) \ + errx(1, "test failed at line %d: %s", \ + __LINE__, #x); \ + } while (0) + +int +main(void) +{ + unsigned char testbuf[] = "012345"; + const unsigned char zerobuf[sizeof testbuf] = { 0 }; + unsigned long value; + unsigned int i, j, k, l; + int ret; + + /* + * First, verify UTF8_getc() + */ + value = UNCHANGED; + ret = UTF8_getc(testbuf, 0, &value); + ASSERT(ret == 0); + ASSERT(value == UNCHANGED); + + /* check all valid single-byte chars */ + for (i = 0; i < 0x80; i++) { + testbuf[0] = i; + ret = UTF8_getc(testbuf, 1, &value); + ASSERT(ret == 1); + ASSERT(value == i); + + ret = UTF8_getc(testbuf, 2, &value); + ASSERT(ret == 1); + ASSERT(value == i); + } + + /* + * Verify failure on all invalid initial bytes: + * 0x80 - 0xBF following bytes only + * 0xC0 - 0xC1 used to be in non-shortest forms + * 0xF5 - 0xFD used to be initial for 5 and 6 byte sequences + * 0xFE - 0xFF have never been valid in utf-8 + */ + for (i = 0x80; i < 0xC2; i++) { + value = UNCHANGED; + testbuf[0] = i; + ret = UTF8_getc(testbuf, 1, &value); + ASSERT(ret == -2); + ASSERT(value == UNCHANGED); + } + for (i = 0xF5; i < 0x100; i++) { + value = UNCHANGED; + testbuf[0] = i; + ret = UTF8_getc(testbuf, 1, &value); + ASSERT(ret == -2); + ASSERT(value == UNCHANGED); + } + + /* + * Verify handling of all two-byte sequences + */ + for (i = 0xC2; i < 0xE0; i++) { + testbuf[0] = i; + + for (j = 0; j < 0x100; j++) { + testbuf[1] = j; + + value = UNCHANGED; + ret = UTF8_getc(testbuf, 1, &value); + ASSERT(ret == -1); + ASSERT(value == UNCHANGED); + + ret = UTF8_getc(testbuf, 2, &value); + + /* outside range of trailing bytes */ + if (j < 0x80 || j > 0xBF) { + ASSERT(ret == -3); + ASSERT(value == UNCHANGED); + continue; + } + + /* valid */ + ASSERT(ret == 2); + ASSERT((value & 0x3F) == (j & 0x3F)); + ASSERT(value >> 6 == (i & 0x1F)); + } + } + + /* + * Verify handling of all three-byte sequences + */ + for (i = 0xE0; i < 0xF0; i++) { + testbuf[0] = i; + + for (j = 0; j < 0x100; j++) { + testbuf[1] = j; + + for (k = 0; k < 0x100; k++) { + testbuf[2] = k; + + value = UNCHANGED; + ret = UTF8_getc(testbuf, 2, &value); + ASSERT(ret == -1); + ASSERT(value == UNCHANGED); + + ret = UTF8_getc(testbuf, 3, &value); + + /* outside range of trailing bytes */ + if (j < 0x80 || j > 0xBF || + k < 0x80 || k > 0xBF) { + ASSERT(ret == -3); + ASSERT(value == UNCHANGED); + continue; + } + + /* non-shortest form */ + if (i == 0xE0 && j < 0xA0) { + ASSERT(ret == -4); + ASSERT(value == UNCHANGED); + continue; + } + + /* surrogate pair code point */ + if (i == 0xED && j > 0x9F) { + ASSERT(ret == -2); + ASSERT(value == UNCHANGED); + continue; + } + + ASSERT(ret == 3); + ASSERT((value & 0x3F) == (k & 0x3F)); + ASSERT(((value >> 6) & 0x3F) == (j & 0x3F)); + ASSERT(value >> 12 == (i & 0x0F)); + } + } + } + + /* + * Verify handling of all four-byte sequences + */ + for (i = 0xF0; i < 0xF5; i++) { + testbuf[0] = i; + + for (j = 0; j < 0x100; j++) { + testbuf[1] = j; + + for (k = 0; k < 0x100; k++) { + testbuf[2] = k; + + for (l = 0; l < 0x100; l++) { + testbuf[3] = l; + + value = UNCHANGED; + ret = UTF8_getc(testbuf, 3, &value); + ASSERT(ret == -1); + ASSERT(value == UNCHANGED); + + ret = UTF8_getc(testbuf, 4, &value); + + /* outside range of trailing bytes */ + if (j < 0x80 || j > 0xBF || + k < 0x80 || k > 0xBF || + l < 0x80 || l > 0xBF) { + ASSERT(ret == -3); + ASSERT(value == UNCHANGED); + continue; + } + + /* non-shortest form */ + if (i == 0xF0 && j < 0x90) { + ASSERT(ret == -4); + ASSERT(value == UNCHANGED); + continue; + } + + /* beyond end of UCS range */ + if (i == 0xF4 && j > 0x8F) { + ASSERT(ret == -2); + ASSERT(value == UNCHANGED); + continue; + } + + ASSERT(ret == 4); + ASSERT((value & 0x3F) == (l & 0x3F)); + ASSERT(((value >> 6) & 0x3F) == + (k & 0x3F)); + ASSERT(((value >> 12) & 0x3F) == + (j & 0x3F)); + ASSERT(value >> 18 == (i & 0x07)); + } + } + } + } + + + /* + * Next, verify UTF8_putc() + */ + memset(testbuf, 0, sizeof testbuf); + + /* single-byte sequences */ + for (i = 0; i < 0x80; i++) { + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == 1); + + testbuf[0] = 0; + ret = UTF8_putc(testbuf, 0, i); + ASSERT(ret == -1); + ASSERT(memcmp(testbuf, zerobuf, sizeof testbuf) == 0); + + ret = UTF8_putc(testbuf, 1, i); + ASSERT(ret == 1); + ASSERT(testbuf[0] == i); + ASSERT(memcmp(testbuf+1, zerobuf, sizeof(testbuf)-1) == 0); + } + + /* two-byte sequences */ + for (i = 0x80; i < 0x800; i++) { + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == 2); + + testbuf[0] = testbuf[1] = 0; + ret = UTF8_putc(testbuf, 1, i); + ASSERT(ret == -1); + ASSERT(memcmp(testbuf, zerobuf, sizeof testbuf) == 0); + + ret = UTF8_putc(testbuf, 2, i); + ASSERT(ret == 2); + ASSERT(memcmp(testbuf+2, zerobuf, sizeof(testbuf)-2) == 0); + ret = UTF8_getc(testbuf, 2, &value); + ASSERT(ret == 2); + ASSERT(value == i); + } + + /* three-byte sequences */ + for (i = 0x800; i < 0x10000; i++) { + if (i >= 0xD800 && i < 0xE000) { + /* surrogates aren't valid */ + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == -2); + continue; + } + + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == 3); + + testbuf[0] = testbuf[1] = testbuf[2] = 0; + ret = UTF8_putc(testbuf, 2, i); + ASSERT(ret == -1); + ASSERT(memcmp(testbuf, zerobuf, sizeof testbuf) == 0); + + ret = UTF8_putc(testbuf, 3, i); + ASSERT(ret == 3); + ASSERT(memcmp(testbuf+3, zerobuf, sizeof(testbuf)-3) == 0); + ret = UTF8_getc(testbuf, 3, &value); + ASSERT(ret == 3); + ASSERT(value == i); + } + + /* four-byte sequences */ + for (i = 0x10000; i < 0x110000; i++) { + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == 4); + + testbuf[0] = testbuf[1] = testbuf[2] = testbuf[3] = 0; + ret = UTF8_putc(testbuf, 3, i); + ASSERT(ret == -1); + ASSERT(memcmp(testbuf, zerobuf, sizeof testbuf) == 0); + + ret = UTF8_putc(testbuf, 4, i); + ASSERT(ret == 4); + ASSERT(memcmp(testbuf+4, zerobuf, sizeof(testbuf)-4) == 0); + ret = UTF8_getc(testbuf, 4, &value); + ASSERT(ret == 4); + ASSERT(value == i); + } + + /* spot check some larger values to confirm error return */ + for (i = 0x110000; i < 0x110100; i++) { + ret = UTF8_putc(NULL, 0, i); + ASSERT(ret == -2); + } + for (value = (unsigned long)-1; value > (unsigned long)-256; value--) { + ret = UTF8_putc(NULL, 0, value); + ASSERT(ret == -2); + } + + return 0; +} diff --git a/tests/util.c b/tests/util.c new file mode 100644 index 0000000..5190e81 --- /dev/null +++ b/tests/util.c @@ -0,0 +1,145 @@ +/* $OpenBSD: util.c,v 1.3 2018/11/09 06:30:41 bluhm Exp $ */ +/* + * Copyright (c) 2018 Alexander Bluhm + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "util.h" + +void +print_version(void) +{ +#ifdef OPENSSL_VERSION_NUMBER + printf("OPENSSL_VERSION_NUMBER: %#08lx\n", OPENSSL_VERSION_NUMBER); +#endif +#ifdef LIBRESSL_VERSION_NUMBER + printf("LIBRESSL_VERSION_NUMBER: %#08lx\n", LIBRESSL_VERSION_NUMBER); +#endif +#ifdef LIBRESSL_VERSION_TEXT + printf("LIBRESSL_VERSION_TEXT: %s\n", LIBRESSL_VERSION_TEXT); +#endif +#if OPENSSL_VERSION_NUMBER >= 0x1010000f + printf("OpenSSL_version_num: %#08lx\n", OpenSSL_version_num()); + printf("OpenSSL_version OPENSSL_VERSION: %s\n", + OpenSSL_version(OPENSSL_VERSION)); + printf("OpenSSL_version OPENSSL_CFLAGS: %s\n", + OpenSSL_version(OPENSSL_CFLAGS)); + printf("OpenSSL_version OPENSSL_BUILT_ON: %s\n", + OpenSSL_version(OPENSSL_BUILT_ON)); + printf("OpenSSL_version OPENSSL_PLATFORM: %s\n", + OpenSSL_version(OPENSSL_PLATFORM)); + printf("OpenSSL_version OPENSSL_DIR: %s\n", + OpenSSL_version(OPENSSL_DIR)); + printf("OpenSSL_version OPENSSL_ENGINES_DIR: %s\n", + OpenSSL_version(OPENSSL_ENGINES_DIR)); +#endif + printf("SSLeay: %#08lx\n", SSLeay()); + printf("SSLeay_version SSLEAY_VERSION: %s\n", + SSLeay_version(SSLEAY_VERSION)); + printf("SSLeay_version SSLEAY_CFLAGS: %s\n", + SSLeay_version(SSLEAY_CFLAGS)); + printf("SSLeay_version SSLEAY_BUILT_ON: %s\n", + SSLeay_version(SSLEAY_BUILT_ON)); + printf("SSLeay_version SSLEAY_PLATFORM: %s\n", + SSLeay_version(SSLEAY_PLATFORM)); + printf("SSLeay_version SSLEAY_DIR: %s\n", + SSLeay_version(SSLEAY_DIR)); +} + +void +print_ciphers(STACK_OF(SSL_CIPHER) *cstack) +{ + const SSL_CIPHER *cipher; + int i; + + for (i = 0; (cipher = sk_SSL_CIPHER_value(cstack, i)) != NULL; i++) + printf("cipher %s\n", SSL_CIPHER_get_name(cipher)); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); +} + +void +print_sockname(BIO *bio) +{ + struct sockaddr_storage ss; + socklen_t slen; + char host[NI_MAXHOST], port[NI_MAXSERV]; + int fd; + + if (BIO_get_fd(bio, &fd) <= 0) + err_ssl(1, "BIO_get_fd"); + slen = sizeof(ss); + if (getsockname(fd, (struct sockaddr *)&ss, &slen) == -1) + err(1, "getsockname"); + if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host, + sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "getnameinfo"); + printf("sock: %s %s\n", host, port); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); +} + +void +print_peername(BIO *bio) +{ + struct sockaddr_storage ss; + socklen_t slen; + char host[NI_MAXHOST], port[NI_MAXSERV]; + int fd; + + if (BIO_get_fd(bio, &fd) <= 0) + err_ssl(1, "BIO_get_fd"); + slen = sizeof(ss); + if (getpeername(fd, (struct sockaddr *)&ss, &slen) == -1) + err(1, "getpeername"); + if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host, + sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV)) + errx(1, "getnameinfo"); + printf("peer: %s %s\n", host, port); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); +} + +void +err_ssl(int eval, const char *fmt, ...) +{ + va_list ap; + + ERR_print_errors_fp(stderr); + va_start(ap, fmt); + verrx(eval, fmt, ap); + va_end(ap); +} + +int +verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) +{ + printf("verify: %s\n", preverify_ok ? "pass" : "fail"); + if (fflush(stdout) != 0) + err(1, "fflush stdout"); + + return preverify_ok; +} diff --git a/tests/valid_handshakes_terminate.c b/tests/valid_handshakes_terminate.c new file mode 100644 index 0000000..286b860 --- /dev/null +++ b/tests/valid_handshakes_terminate.c @@ -0,0 +1,54 @@ +/* $OpenBSD: valid_handshakes_terminate.c,v 1.4 2022/12/01 13:49:12 tb Exp $ */ +/* + * Copyright (c) 2019 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "tls13_handshake.c" + +int +main(int argc, char *argv[]) +{ + size_t i, j; + int terminates; + int fail = 0; + + for (i = 1; i < handshake_count; i++) { + enum tls13_message_type mt = handshakes[i][0]; + + if (mt == INVALID) + continue; + + terminates = 0; + + for (j = 0; j < TLS13_NUM_MESSAGE_TYPES; j++) { + mt = handshakes[i][j]; + if (state_machine[mt].handshake_complete) { + terminates = 1; + break; + } + } + + if (!terminates) { + fail = 1; + printf("FAIL: handshake_complete never true in " + "handshake %zu\n", i); + } + } + + return fail; +} diff --git a/tests/verify.c b/tests/verify.c new file mode 100644 index 0000000..8784396 --- /dev/null +++ b/tests/verify.c @@ -0,0 +1,373 @@ +/* $OpenBSD: verify.c,v 1.1.1.1 2021/08/30 17:27:45 tb Exp $ */ +/* + * Copyright (c) 2021 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Based on https://github.com/noxxi/libressl-tests */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +struct peer_config { + const char *name; + int server; + const char *cert; + const char *key; + const char *ca_file; +}; + +struct ssl_wildcard_test_data { + const char *description; + struct peer_config client_config; + struct peer_config server_config; + long verify_result; +}; + +static const struct ssl_wildcard_test_data ssl_wildcard_tests[] = { + { + .description = "unusual wildcard cert, no CA given to client", + .client_config = { + .name = "client", + .server = 0, + .cert = NULL, + .ca_file = NULL, + }, + .server_config = { + .name = "server", + .server = 1, + .cert = "server-unusual-wildcard.pem", + .key = "server-unusual-wildcard.pem", + }, + /* OpenSSL returns X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE */ + .verify_result = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + }, + + { + .description = "unusual wildcard cert, CA given to client", + .client_config = { + .name = "client", + .server = 0, + .cert = NULL, + .ca_file = "caR.pem", + }, + .server_config = { + .name = "server", + .server = 1, + .cert = "server-unusual-wildcard.pem", + .key = "server-unusual-wildcard.pem", + }, + .verify_result = X509_V_OK, + }, + + { + .description = "common wildcard cert, no CA given to client", + .client_config = { + .name = "client", + .server = 0, + .cert = NULL, + .ca_file = NULL, + }, + .server_config = { + .name = "server", + .server = 1, + .cert = "server-common-wildcard.pem", + .key = "server-common-wildcard.pem", + }, + /* OpenSSL returns X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE */ + .verify_result = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + }, + + { + .description = "common wildcard cert, CA given to client", + .client_config = { + .name = "client", + .server = 0, + .cert = NULL, + .ca_file = "caR.pem", + }, + .server_config = { + .name = "server", + .server = 1, + .cert = "server-common-wildcard.pem", + .key = "server-common-wildcard.pem", + }, + .verify_result = X509_V_OK, + }, + + { + .description = "server sends all chain certificates", + .client_config = { + .name = "client", + .server = 0, + .cert = NULL, + .ca_file = "caR.pem", + }, + .server_config = { + .name = "server", + .server = 1, + .cert = "server-subca-chainS.pem", + .key = "server-subca-chainS.pem", + .ca_file = "subcaR.pem" + }, + .verify_result = X509_V_OK, + }, +}; + +static const size_t N_SSL_WILDCARD_TESTS = + sizeof(ssl_wildcard_tests) / sizeof(ssl_wildcard_tests[0]); + +static SSL_CTX * +peer_config_to_ssl_ctx(const struct peer_config *config) +{ + SSL_CTX *ctx; + + if ((ctx = SSL_CTX_new(TLS_method())) == NULL) { + fprintf(stderr, "SSL_CTX_new(%s) failed\n", config->name); + goto err; + } + + if (config->server) { + if (!SSL_CTX_use_certificate_file(ctx, config->cert, + SSL_FILETYPE_PEM)) { + fprintf(stderr, "use_certificate_file(%s) failed\n", + config->name); + goto err; + } + if (config->key != NULL && !SSL_CTX_use_PrivateKey_file(ctx, + config->key, SSL_FILETYPE_PEM)) { + fprintf(stderr, "use_PrivateKey_file(%s) failed\n", + config->name); + goto err; + } + } + + if (config->ca_file != NULL) { + if (!SSL_CTX_load_verify_locations(ctx, config->ca_file, NULL)) { + fprintf(stderr, "load_verify_locations(%s) failed\n", + config->name); + goto err; + } + } + + return ctx; + + err: + SSL_CTX_free(ctx); + return NULL; +} + +/* Connect client and server via a pair of "nonblocking" memory BIOs. */ +static int +connect_peers(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + BIO *client_wbio = NULL, *server_wbio = NULL; + int ret = 0; + + if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "%s: failed to create client BIO\n", + description); + goto err; + } + if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) { + fprintf(stderr, "%s: failed to create server BIO\n", + description); + goto err; + } + if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) { + fprintf(stderr, "%s: failed to set client eof return\n", + description); + goto err; + } + if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) { + fprintf(stderr, "%s: failed to set server eof return\n", + description); + goto err; + } + + /* Avoid double free. SSL_set_bio() takes ownership of the BIOs. */ + BIO_up_ref(client_wbio); + BIO_up_ref(server_wbio); + + SSL_set_bio(client_ssl, server_wbio, client_wbio); + SSL_set_bio(server_ssl, client_wbio, server_wbio); + client_wbio = NULL; + server_wbio = NULL; + + ret = 1; + + err: + BIO_free(client_wbio); + BIO_free(server_wbio); + + return ret; +} + +static int +push_data_to_peer(SSL *ssl, int *ret, int (*func)(SSL *), const char *func_name, + const char *description) +{ + int ssl_err = 0; + + if (*ret == 1) + return 1; + + /* + * Do SSL_connect/SSL_accept/SSL_shutdown once and loop while hitting + * WANT_WRITE. If done or on WANT_READ hand off to peer. + */ + + do { + if ((*ret = func(ssl)) <= 0) + ssl_err = SSL_get_error(ssl, *ret); + } while (*ret <= 0 && ssl_err == SSL_ERROR_WANT_WRITE); + + /* Ignore erroneous error - see SSL_shutdown(3)... */ + if (func == SSL_shutdown && ssl_err == SSL_ERROR_SYSCALL) + return 1; + + if (*ret <= 0 && ssl_err != SSL_ERROR_WANT_READ) { + fprintf(stderr, "%s: %s failed\n", description, func_name); + ERR_print_errors_fp(stderr); + return 0; + } + + return 1; +} + +/* + * Alternate between loops of SSL_connect() and SSL_accept() as long as only + * WANT_READ and WANT_WRITE situations are encountered. A function is repeated + * until WANT_READ is returned or it succeeds, then it's the other function's + * turn to make progress. Succeeds if SSL_connect() and SSL_accept() return 1. + */ +static int +handshake(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + int loops = 0, client_ret = 0, server_ret = 0; + + while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) { + if (!push_data_to_peer(client_ssl, &client_ret, SSL_connect, + "SSL_connect", description)) + return 0; + + if (!push_data_to_peer(server_ssl, &server_ret, SSL_accept, + "SSL_accept", description)) + return 0; + } + + if (client_ret != 1 || server_ret != 1) { + fprintf(stderr, "%s: failed\n", __func__); + return 0; + } + + return 1; +} + +static int +shutdown_peers(SSL *client_ssl, SSL *server_ssl, const char *description) +{ + int loops = 0, client_ret = 0, server_ret = 0; + + while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) { + if (!push_data_to_peer(client_ssl, &client_ret, SSL_shutdown, + "client shutdown", description)) + return 0; + + if (!push_data_to_peer(server_ssl, &server_ret, SSL_shutdown, + "server shutdown", description)) + return 0; + } + + if (client_ret != 1 || server_ret != 1) { + fprintf(stderr, "%s: failed\n", __func__); + return 0; + } + + return 1; +} + +static int +test_ssl_wildcards(const struct ssl_wildcard_test_data *test) +{ + SSL_CTX *client_ctx = NULL, *server_ctx = NULL; + SSL *client_ssl = NULL, *server_ssl = NULL; + long verify_result; + int failed = 1; + + if ((client_ctx = peer_config_to_ssl_ctx(&test->client_config)) == NULL) + goto err; + if ((server_ctx = peer_config_to_ssl_ctx(&test->server_config)) == NULL) + goto err; + + if ((client_ssl = SSL_new(client_ctx)) == NULL) { + fprintf(stderr, "%s: failed to create client SSL\n", + test->description); + goto err; + } + if ((server_ssl = SSL_new(server_ctx)) == NULL) { + fprintf(stderr, "%s: failed to create server SSL\n", + test->description); + goto err; + } + + if (!connect_peers(client_ssl, server_ssl, test->description)) + goto err; + + if (!handshake(client_ssl, server_ssl, test->description)) + goto err; + + verify_result = SSL_get_verify_result(client_ssl); + + if (test->verify_result == verify_result) { + failed = 0; + fprintf(stderr, "%s: ok\n", test->description); + } else + fprintf(stderr, "%s: verify_result: want %ld, got %ld\n", + test->description, test->verify_result, verify_result); + + if (!shutdown_peers(client_ssl, server_ssl, test->description)) + goto err; + + err: + SSL_CTX_free(client_ctx); + SSL_CTX_free(server_ctx); + SSL_free(client_ssl); + SSL_free(server_ssl); + + return failed; +} + +int +main(int argc, char **argv) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_SSL_WILDCARD_TESTS; i++) + failed |= test_ssl_wildcards(&ssl_wildcard_tests[i]); + + if (failed == 0) + printf("PASS %s\n", __FILE__); + + return failed; +} diff --git a/tests/verifytest.c b/tests/verifytest.c new file mode 100644 index 0000000..57aa992 --- /dev/null +++ b/tests/verifytest.c @@ -0,0 +1,526 @@ +/* $OpenBSD: verifytest.c,v 1.8 2023/05/28 09:02:01 beck Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +extern int tls_check_name(struct tls *ctx, X509 *cert, const char *name, + int *match); + +struct alt_name { + const char name[128]; + int name_len; + int name_type; +}; + +struct verify_test { + const char common_name[128]; + int common_name_len; + struct alt_name alt_name1; + struct alt_name alt_name2; + struct alt_name alt_name3; + const char name[128]; + int want_return; + int want_match; + int name_type; +}; + +struct verify_test verify_tests[] = { + { + /* CN without SANs - matching. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* Zero length name - non-matching. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .name = "", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - matching. */ + .common_name = "*.openbsd.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* CN without SANs - non-matching. */ + .common_name = "www.openbsdfoundation.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "w*.openbsd.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "www.*.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "www.openbsd.*", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "*", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "*.org", + .common_name_len = -1, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid CN wildcard. */ + .common_name = "*.org", + .common_name_len = -1, + .name = "openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN IPv4 without SANs - matching. */ + .common_name = "1.2.3.4", + .common_name_len = -1, + .name = "1.2.3.4", + .want_return = 0, + .want_match = 1, + }, + { + /* CN IPv4 wildcard without SANS - invalid IP wildcard. */ + .common_name = "*.2.3.4", + .common_name_len = -1, + .name = "1.2.3.4", + .want_return = 0, + .want_match = 0, + }, + { + /* CN IPv6 without SANs - matching. */ + .common_name = "cafe::beef", + .common_name_len = -1, + .name = "cafe::beef", + .want_return = 0, + .want_match = 1, + }, + { + /* CN without SANs - error due to embedded NUL in CN. */ + .common_name = { + 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, + 0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0x00, + 0x6e, 0x61, 0x73, 0x74, 0x79, 0x2e, 0x6f, 0x72, + 0x67, + }, + .common_name_len = 25, + .name = "www.openbsd.org", + .want_return = -1, + .want_match = 0, + }, + { + /* CN wildcard without SANs - invalid non-matching name. */ + .common_name = "*.openbsd.org", + .common_name_len = -1, + .name = ".openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN with SANs - matching on first SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* SANs only - matching on first SAN. */ + .common_name_len = 0, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* SANs only - matching on second SAN. */ + .common_name_len = 0, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "ftp.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* SANs only - non-matching. */ + .common_name_len = 0, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "mail.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN with SANs - matching on second SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "ftp.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* CN with SANs - matching on wildcard second SAN. */ + .common_name = "www.openbsdfoundation.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsdfoundation.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "*.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 1, + }, + { + /* CN with SANs - non-matching invalid wildcard. */ + .common_name = "www.openbsdfoundation.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsdfoundation.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "*.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN with SANs - non-matching IPv4 due to GEN_DNS SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = "1.2.3.4", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "1.2.3.4", + .want_return = 0, + .want_match = 0, + }, + { + /* CN with SANs - matching IPv4 on GEN_IPADD SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = {0x01, 0x02, 0x03, 0x04}, + .name_len = 4, + .name_type = GEN_IPADD, + }, + .name = "1.2.3.4", + .want_return = 0, + .want_match = 1, + }, + { + /* CN with SANs - matching IPv6 on GEN_IPADD SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = { + 0xca, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, + }, + .name_len = 16, + .name_type = GEN_IPADD, + }, + .name = "cafe::beef", + .want_return = 0, + .want_match = 1, + }, + { + /* CN with SANs - error due to embedded NUL in GEN_DNS. */ + .common_name = "www.openbsd.org.nasty.org", + .common_name_len = -1, + .alt_name1 = { + .name = "www.openbsd.org.nasty.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .alt_name2 = { + .name = { + 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, + 0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0x00, + 0x6e, 0x61, 0x73, 0x74, 0x79, 0x2e, 0x6f, 0x72, + 0x67, + }, + .name_len = 25, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = -1, + .want_match = 0, + }, + { + /* CN with SAN - non-matching due to non-matching SAN. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = "ftp.openbsd.org", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = 0, + .want_match = 0, + }, + { + /* CN with SAN - error due to illegal dNSName. */ + .common_name = "www.openbsd.org", + .common_name_len = -1, + .alt_name1 = { + .name = " ", + .name_len = -1, + .name_type = GEN_DNS, + }, + .name = "www.openbsd.org", + .want_return = -1, + .want_match = 0, + }, +}; + +#define N_VERIFY_TESTS \ + (sizeof(verify_tests) / sizeof(*verify_tests)) + +static void +alt_names_add(STACK_OF(GENERAL_NAME) *alt_name_stack, struct alt_name *alt) +{ + ASN1_STRING *alt_name_str; + GENERAL_NAME *alt_name; + + if ((alt_name = GENERAL_NAME_new()) == NULL) + errx(1, "failed to malloc GENERAL_NAME"); + alt_name->type = alt->name_type; + + if ((alt_name_str = ASN1_STRING_new()) == NULL) + errx(1, "failed to malloc alt name"); + if (ASN1_STRING_set(alt_name_str, alt->name, alt->name_len) == 0) + errx(1, "failed to set alt name"); + + switch (alt_name->type) { + case GEN_DNS: + alt_name->d.dNSName = alt_name_str; + break; + case GEN_IPADD: + alt_name->d.iPAddress = alt_name_str; + break; + default: + errx(1, "unknown alt name type (%i)", alt_name->type); + } + + if (sk_GENERAL_NAME_push(alt_name_stack, alt_name) == 0) + errx(1, "failed to push alt_name"); +} + +static void +cert_add_alt_names(X509 *cert, struct verify_test *vt) +{ + STACK_OF(GENERAL_NAME) *alt_name_stack = NULL; + + if (vt->alt_name1.name_type == 0) + return; + + if ((alt_name_stack = sk_GENERAL_NAME_new_null()) == NULL) + errx(1, "failed to malloc sk_GENERAL_NAME"); + + if (vt->alt_name1.name_type != 0) + alt_names_add(alt_name_stack, &vt->alt_name1); + if (vt->alt_name2.name_type != 0) + alt_names_add(alt_name_stack, &vt->alt_name2); + if (vt->alt_name3.name_type != 0) + alt_names_add(alt_name_stack, &vt->alt_name3); + + if (X509_add1_ext_i2d(cert, NID_subject_alt_name, + alt_name_stack, 0, 0) == 0) + errx(1, "failed to set subject alt name"); + + sk_GENERAL_NAME_pop_free(alt_name_stack, GENERAL_NAME_free); +} + +static int +do_verify_test(int test_no, struct verify_test *vt) +{ + struct tls *tls; + X509_NAME *name; + X509 *cert; + int failed = 1; + int match; + + /* Build certificate structure. */ + if ((cert = X509_new()) == NULL) + errx(1, "failed to malloc X509"); + + if (vt->common_name_len != 0) { + if ((name = X509_NAME_new()) == NULL) + errx(1, "failed to malloc X509_NAME"); + if (X509_NAME_add_entry_by_NID(name, NID_commonName, + vt->name_type ? vt->name_type : MBSTRING_ASC, + (unsigned char *)vt->common_name, + vt->common_name_len, -1, 0) == 0) + errx(1, "failed to add name entry"); + if (X509_set_subject_name(cert, name) == 0) + errx(1, "failed to set subject name"); + X509_NAME_free(name); + } + + if ((tls = tls_client()) == NULL) + errx(1, "failed to malloc tls_client"); + + cert_add_alt_names(cert, vt); + + match = 1; + + if (tls_check_name(tls, cert, vt->name, &match) != vt->want_return) { + fprintf(stderr, "FAIL: test %i failed for check name '%s': " + "%s\n", test_no, vt->name, tls_error(tls)); + goto done; + } + if (match != vt->want_match) { + fprintf(stderr, "FAIL: test %i failed to match name '%s'\n", + test_no, vt->name); + goto done; + } + + failed = 0; + + done: + X509_free(cert); + tls_free(tls); + + return (failed); +} + +int +main(int argc, char **argv) +{ + int failed = 0; + size_t i; + + tls_init(); + + for (i = 0; i < N_VERIFY_TESTS; i++) + failed += do_verify_test(i, &verify_tests[i]); + + return (failed); +} diff --git a/tests/wycheproof-primes.c b/tests/wycheproof-primes.c new file mode 100644 index 0000000..57bd7a5 --- /dev/null +++ b/tests/wycheproof-primes.c @@ -0,0 +1,61 @@ +/* $OpenBSD: wycheproof-primes.c,v 1.2 2022/12/01 13:49:12 tb Exp $ */ +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include "primality_testcases.h" + +int +primality_test(struct wycheproof_testcase *test) +{ + BIGNUM *value = NULL; + int ret; + int failed = 1; + + if (!BN_hex2bn(&value, test->value)) + errx(1, "%d: failed to set value \"%s\"", test->id, test->value); + + if ((ret = BN_is_prime_ex(value, BN_prime_checks, NULL, NULL)) < 0) + errx(1, "%d: BN_is_prime_ex errored", test->id); + + if (ret != test->result && !test->acceptable) { + fprintf(stderr, "%d failed, want %d, got %d\n", test->id, + test->result, ret); + goto err; + } + + failed = 0; + err: + BN_free(value); + + return failed; +} + +int +main(void) +{ + size_t i; + int failed = 0; + + for (i = 0; i < N_TESTS; i++) + failed |= primality_test(&testcases[i]); + + return failed; +} diff --git a/tests/x25519test.c b/tests/x25519test.c new file mode 100644 index 0000000..321aac4 --- /dev/null +++ b/tests/x25519test.c @@ -0,0 +1,141 @@ +/* $OpenBSD: x25519test.c,v 1.3 2022/12/01 13:55:22 tb Exp $ */ +/* + * Copyright (c) 2015, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +static int +x25519_test(void) +{ + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + static const uint8_t kScalar1[32] = { + 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, + 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, + 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, + 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4, + }; + static const uint8_t kPoint1[32] = { + 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, + 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, + 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, + 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c, + }; + static const uint8_t kExpected1[32] = { + 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, + 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, + 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, + 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52, + }; + static const uint8_t kScalar2[32] = { + 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, + 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, + 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, + 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d, + }; + static const uint8_t kPoint2[32] = { + 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, + 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, + 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, + 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93, + }; + static const uint8_t kExpected2[32] = { + 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, + 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, + 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, + 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57, + }; + + uint8_t out[32]; + + X25519(out, kScalar1, kPoint1); + if (memcmp(kExpected1, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test one failed.\n"); + return 1; + } + + X25519(out, kScalar2, kPoint2); + if (memcmp(kExpected2, out, sizeof(out)) != 0) { + fprintf(stderr, "X25519 test two failed.\n"); + return 1; + } + + return 0; +} + +static int +x25519_iterated_test(void) +{ + /* Taken from https://tools.ietf.org/html/rfc7748#section-5.2 */ + static const uint8_t kExpected[32] = { + 0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, + 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c, + 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, + 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51, + }; + + uint8_t scalar[32] = {9}, point[32] = {9}, out[32]; + unsigned i; + + for (i = 0; i < 1000; i++) { + X25519(out, scalar, point); + memcpy(point, scalar, sizeof(point)); + memcpy(scalar, out, sizeof(scalar)); + } + + if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) { + fprintf(stderr, "Iterated X25519 test failed\n"); + return 1; + } + + return 0; +} + +static int +x25519_small_order_test(void) +{ + static const uint8_t kSmallOrderPoint[32] = { + 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, + 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, + 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, + 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00, + }; + + uint8_t out[32], private_key[32]; + + memset(private_key, 0x11, sizeof(private_key)); + if (X25519(out, private_key, kSmallOrderPoint)) { + fprintf(stderr, "X25519 returned success with a small-order input.\n"); + return 1; + } + + return 0; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= x25519_test(); + failed |= x25519_iterated_test(); + failed |= x25519_small_order_test(); + + return failed; +} diff --git a/tests/x509_asn1.c b/tests/x509_asn1.c new file mode 100644 index 0000000..c775362 --- /dev/null +++ b/tests/x509_asn1.c @@ -0,0 +1,601 @@ +/* $OpenBSD: x509_asn1.c,v 1.20 2023/06/05 18:32:06 job Exp $ */ +/* + * Copyright (c) 2023 Job Snijders + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This program tests whether the presence of "->enc.modified = 1;" + * in select X509 setter functions properly triggers invalidation of cached + * DER. + */ + +#include +#include +#include + +#include +#include +#include + +static const struct fnnames { + char *name; + void (*fn); +} fnnames[] = { + { "X509_set_version", X509_set_version }, + { "X509_set_serialNumber", X509_set_serialNumber }, + { "X509_set_issuer_name", X509_set_issuer_name }, + { "X509_set_subject_name", X509_set_subject_name }, + { "X509_set_notBefore", X509_set_notBefore }, + { "X509_set_notAfter", X509_set_notAfter }, + { "X509_set_pubkey", X509_set_pubkey }, + { "X509_CRL_set_version", X509_CRL_set_version }, + { "X509_CRL_set_issuer_name", X509_CRL_set_issuer_name }, + { "X509_CRL_set_lastUpdate", X509_CRL_set_lastUpdate }, + { "X509_CRL_set_nextUpdate", X509_CRL_set_nextUpdate }, + { "X509_REQ_add_extensions", X509_REQ_add_extensions }, + { "X509_REQ_add1_attr", X509_REQ_add1_attr }, + { NULL, NULL } +}; + +static void +lookup_and_err(void (*fn)) +{ + int i; + + for (i = 0; fnnames[i].name; i++) { + if (fnnames[i].fn == fn) + errx(1, "%s failed", fnnames[i].name); + } +} + +static void +x509_setup(unsigned char **der, unsigned char **der2, X509 **x, + long dersz, long *der2sz) +{ + const unsigned char *cpder; + + cpder = *der; + if ((*x = d2i_X509(NULL, &cpder, dersz)) == NULL) + errx(1, "d2i_X509"); + if ((*der2sz = i2d_X509(*x, der2)) <= 0) + errx(1, "i2d_X509"); +} + +static void +x509_cleanup(X509 **x, unsigned char **der) +{ + X509_free(*x); + *x = NULL; + free(*der); + *der = NULL; +} + +static void +x509_set_integer(int (*f)(X509 *, ASN1_INTEGER *), X509 **x, int i) +{ + ASN1_INTEGER *ai; + + if ((ai = ASN1_INTEGER_new()) == NULL) + err(1, NULL); + if (!ASN1_INTEGER_set(ai, i)) + errx(1, "ASN1_INTEGER_set"); + if (!f(*x, ai)) + lookup_and_err(f); + + ASN1_INTEGER_free(ai); +} + +static void +x509_set_name(int (*f)(X509 *, X509_NAME *), X509 **x, + const unsigned char *n) +{ + X509_NAME *xn; + + if ((xn = X509_NAME_new()) == NULL) + err(1, NULL); + if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, n, -1, -1, 0)) + errx(1, "X509_NAME_add_entry_by_txt"); + if (!f(*x, xn)) + lookup_and_err(f); + + X509_NAME_free(xn); +} + +static void +x509_set_time(int (*f)(X509 *, const ASN1_TIME *), X509 **x, int t) +{ + ASN1_TIME *at; + + if ((at = X509_gmtime_adj(NULL, t)) == NULL) + errx(1, "X509_gmtime_adj"); + if (!f(*x, at)) + lookup_and_err(f); + + ASN1_TIME_free(at); +} + +static int +x509_compare(char *f, X509 *a, const unsigned char *der, long dersz) +{ + unsigned char *der_test = NULL; + long der_testsz; + int rc = 0; + + if ((der_testsz = i2d_X509(a, &der_test)) <= 0) + errx(1, "i2d_X509"); + + if (dersz == der_testsz) { + if (memcmp(der, der_test, dersz) == 0) { + warnx("%s() stale version of encoding after i2d", f); + rc = 1; + } else + warnx("%s() OK", f); + } else + warnx("%s() OK", f); + + free(der_test); + return rc; +} + +static void +x509_crl_setup(unsigned char **der, unsigned char **der2, X509_CRL **xc, + long dersz, long *der2sz) +{ + const unsigned char *cpder; + + cpder = *der; + if ((*xc = d2i_X509_CRL(NULL, &cpder, dersz)) == NULL) + errx(1, "d2i_X509"); + if ((*der2sz = i2d_X509_CRL(*xc, der2)) <= 0) + errx(1, "i2d_X509"); +} + +static void +x509_crl_cleanup(X509_CRL **xc, unsigned char **der) +{ + X509_CRL_free(*xc); + *xc = NULL; + free(*der); + *der = NULL; +} + +static void +x509_crl_set_name(int (*f)(X509_CRL *, X509_NAME *), X509_CRL **xc, + const unsigned char *n) +{ + X509_NAME *xn; + + if ((xn = X509_NAME_new()) == NULL) + err(1, NULL); + if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, n, -1, -1, 0)) + errx(1, "X509_NAME_add_entry_by_txt"); + if (!f(*xc, xn)) + lookup_and_err(f); + + X509_NAME_free(xn); +} + +static void +x509_crl_set_time(int (*f)(X509_CRL *, const ASN1_TIME *), X509_CRL **xc, int t) +{ + ASN1_TIME *at; + + if ((at = X509_gmtime_adj(NULL, t)) == NULL) + errx(1, "X509_gmtime_adj"); + if (!f(*xc, at)) + lookup_and_err(f); + + ASN1_TIME_free(at); +} + +static int +x509_crl_compare(char *f, X509_CRL *ac, const unsigned char *der, long dersz) +{ + unsigned char *der_test = NULL; + long der_testsz; + int rc = 0; + + if ((der_testsz = i2d_X509_CRL(ac, &der_test)) <= 0) + errx(1, "i2d_X509_CRL"); + + if (dersz == der_testsz) { + if (memcmp(der, der_test, dersz) == 0) { + warnx("%s() stale version of encoding after i2d", f); + rc = 1; + } else + warnx("%s() OK", f); + } else + warnx("%s() OK", f); + + free(der_test); + return rc; +} + +static int +test_x509_setters(void) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + X509 *a, *x; + unsigned char *der = NULL, *der2 = NULL; + long dersz, der2sz; + int failed = 0; + + if ((x = X509_new()) == NULL) + err(1, NULL); + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) + errx(1, "EVP_PKEY_CTX_new_id"); + if (EVP_PKEY_keygen_init(pkey_ctx) != 1) + errx(1, "EVP_PKEY_keygen_init"); + if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0) + errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits"); + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) + errx(1, "EVP_PKEY_keygen"); + if (X509_set_pubkey(x, pkey) != 1) + errx(1, "X509_set_pubkey"); + + x509_set_integer(X509_set_serialNumber, &x, 1); + x509_set_time(X509_set_notBefore, &x, 0); + x509_set_time(X509_set_notAfter, &x, 60); + x509_set_name(X509_set_issuer_name, &x, "NL"); + x509_set_name(X509_set_subject_name, &x, "BE"); + + /* one time creation of the original DER */ + if (!X509_sign(x, pkey, EVP_sha256())) + errx(1, "X509_sign"); + if ((dersz = i2d_X509(x, &der)) <= 0) + errx(1, "i2d_X509"); + + /* test X509_set_version */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + if (!X509_set_version(a, 2)) + errx(1, "X509_set_version"); + failed |= x509_compare("X509_set_version", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_serialNumber */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + x509_set_integer(X509_set_serialNumber, &a, 2); + failed |= x509_compare("X509_set_serialNumber", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_issuer_name */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + x509_set_name(X509_set_issuer_name, &a, "DE"); + failed |= x509_compare("X509_set_issuer_name", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_subject_name */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + x509_set_name(X509_set_subject_name, &a, "FR"); + failed |= x509_compare("X509_set_subject_name", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_notBefore */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + x509_set_time(X509_set_notBefore, &a, 120); + failed |= x509_compare("X509_set_notBefore", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_notAfter */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + x509_set_time(X509_set_notAfter, &a, 180); + failed |= x509_compare("X509_set_notAfter", a, der2, der2sz); + x509_cleanup(&a, &der2); + + /* test X509_set_pubkey */ + x509_setup(&der, &der2, &a, dersz, &der2sz); + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) + errx(1, "EVP_PKEY_keygen"); + if (X509_set_pubkey(a, pkey) != 1) + errx(1, "X509_set_pubkey"); + failed |= x509_compare("X509_set_pubkey", a, der2, der2sz); + x509_cleanup(&a, &der2); + + EVP_PKEY_CTX_free(pkey_ctx); + EVP_PKEY_free(pkey); + X509_free(x); + free(der); + + return failed; +} + +static int +test_x509_crl_setters(void) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + X509_CRL *ac, *xc; + unsigned char *der = NULL, *der2 = NULL; + long dersz, der2sz; + int failed = 0; + + if ((xc = X509_CRL_new()) == NULL) + err(1, NULL); + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) + errx(1, "EVP_PKEY_CTX_new_id"); + if (EVP_PKEY_keygen_init(pkey_ctx) != 1) + errx(1, "EVP_PKEY_keygen_init"); + if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0) + errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits"); + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) + errx(1, "EVP_PKEY_keygen"); + + x509_crl_set_time(X509_CRL_set_lastUpdate, &xc, 0); + x509_crl_set_time(X509_CRL_set_nextUpdate, &xc, 60); + x509_crl_set_name(X509_CRL_set_issuer_name, &xc, "NL"); + + /* one time creation of the original DER */ + if (!X509_CRL_sign(xc, pkey, EVP_sha256())) + errx(1, "X509_CRL_sign"); + if ((dersz = i2d_X509_CRL(xc, &der)) <= 0) + errx(1, "i2d_X509_CRL"); + + /* test X509_CRL_set_version */ + x509_crl_setup(&der, &der2, &ac, dersz, &der2sz); + if (!X509_CRL_set_version(ac, 1)) + errx(1, "X509_CRL_set_version"); + failed |= x509_crl_compare("X509_CRL_set_version", ac, der2, der2sz); + x509_crl_cleanup(&ac, &der2); + + /* test X509_CRL_set_issuer_name */ + x509_crl_setup(&der, &der2, &ac, dersz, &der2sz); + x509_crl_set_name(X509_CRL_set_issuer_name, &ac, "DE"); + failed |= x509_crl_compare("X509_CRL_set_issuer_name", ac, der2, + der2sz); + x509_crl_cleanup(&ac, &der2); + + /* test X509_CRL_set_lastUpdate */ + x509_crl_setup(&der, &der2, &ac, dersz, &der2sz); + x509_crl_set_time(X509_CRL_set_lastUpdate, &ac, 120); + failed |= x509_crl_compare("X509_CRL_set_lastUpdate", ac, der2, der2sz); + x509_crl_cleanup(&ac, &der2); + + /* test X509_CRL_set_nextUpdate */ + x509_crl_setup(&der, &der2, &ac, dersz, &der2sz); + x509_crl_set_time(X509_CRL_set_nextUpdate, &ac, 180); + failed |= x509_crl_compare("X509_CRL_set_nextUpdate", ac, der2, der2sz); + x509_crl_cleanup(&ac, &der2); + + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pkey_ctx); + X509_CRL_free(xc); + free(der); + + return failed; +} + +static void +x509_req_setup(unsigned char **der, unsigned char **der2, X509_REQ **xr, + long dersz, long *der2sz) +{ + const unsigned char *cpder; + + cpder = *der; + if ((*xr = d2i_X509_REQ(NULL, &cpder, dersz)) == NULL) + errx(1, "d2i_X509"); + if ((*der2sz = i2d_X509_REQ(*xr, der2)) <= 0) + errx(1, "i2d_X509"); +} + +static int +x509_req_compare(char *f, X509_REQ *xr, const unsigned char *der, long dersz) +{ + unsigned char *der_test = NULL; + long der_testsz; + int rc = 0; + + if ((der_testsz = i2d_X509_REQ(xr, &der_test)) <= 0) + errx(1, "i2d_X509_REQ"); + + if (dersz == der_testsz) { + if (memcmp(der, der_test, dersz) == 0) { + warnx("%s() stale version of encoding after i2d", f); + rc = 1; + } else + warnx("%s() OK", f); + } else + warnx("%s() OK", f); + + free(der_test); + return rc; +} + +static void +x509_req_cleanup(X509_REQ **xr, unsigned char **der) +{ + X509_REQ_free(*xr); + *xr = NULL; + free(*der); + *der = NULL; +} + +static int +test_x509_req_setters(void) +{ + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *pkey_ctx = NULL; + X509_REQ *ar = NULL, *xr = NULL; + unsigned char *der = NULL, *der2 = NULL; + X509_NAME *xn; + ASN1_OCTET_STRING *aos; + X509_EXTENSION *xe; + STACK_OF(X509_EXTENSION) *exts = NULL; + ASN1_OBJECT *coid; + X509_ATTRIBUTE *xa; + long dersz, der2sz; + int failed = 0; + + if ((xr = X509_REQ_new()) == NULL) + err(1, NULL); + + if (!X509_REQ_set_version(xr, 0)) + errx(1, "X509_REQ_set_version"); + + if ((xn = X509_NAME_new()) == NULL) + err(1, NULL); + if (!X509_NAME_add_entry_by_txt(xn, "C", MBSTRING_ASC, "NL", -1, -1, 0)) + errx(1, "X509_NAME_add_entry_by_txt"); + if (!X509_REQ_set_subject_name(xr, xn)) + errx(1, "X509_REQ_set_subject_name"); + + if ((pkey_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL) + errx(1, "EVP_PKEY_CTX_new_id"); + if (EVP_PKEY_keygen_init(pkey_ctx) != 1) + errx(1, "EVP_PKEY_keygen_init"); + if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_ctx, 2048) <= 0) + errx(1, "EVP_PKEY_CTX_set_rsa_keygen_bits"); + if (EVP_PKEY_keygen(pkey_ctx, &pkey) <= 0) + errx(1, "EVP_PKEY_keygen"); + if (!X509_REQ_set_pubkey(xr, pkey)) + errx(1, "X509_REQ_set_pubkey"); + + if (!X509_REQ_sign(xr, pkey, EVP_sha256())) + errx(1, "X509_REQ_sign"); + if ((dersz = i2d_X509_REQ(xr, &der)) <= 0) + errx(1, "i2d_X509_REQ"); + + /* test X509_REQ_add_extensions */ + x509_req_setup(&der, &der2, &ar, dersz, &der2sz); + if ((aos = ASN1_OCTET_STRING_new()) == NULL) + err(1, NULL); + ASN1_OCTET_STRING_set(aos, (unsigned char *)"DNS: test.nl", + strlen("DNS: test.nl")); + if ((xe = X509_EXTENSION_new()) == NULL) + err(1, NULL); + if (!X509_EXTENSION_create_by_NID(&xe, NID_subject_alt_name, 0, aos)) + errx(1, "X509_EXTENSION_create_by_NID"); + if ((exts = sk_X509_EXTENSION_new_null()) == NULL) + errx(1, "sk_X509_EXTENSION_new_null"); + sk_X509_EXTENSION_push(exts, xe); + if (!X509_REQ_add_extensions(ar, exts)) + errx(1, "X509_REQ_add_extensions"); + failed |= x509_req_compare("X509_REQ_add_extensions", ar, der2, der2sz); + x509_req_cleanup(&ar, &der2); + + /* test X509_REQ_add1_attr */ + x509_req_setup(&der, &der2, &ar, dersz, &der2sz); + if ((coid = OBJ_nid2obj(NID_pkcs7_data)) == NULL) + errx(1, "OBJ_nid2obj"); + if ((xa = X509_ATTRIBUTE_create(NID_pkcs9_contentType, V_ASN1_OBJECT, + coid)) == NULL) + errx(1, "X509_ATTRIBUTE_create"); + if (!X509_REQ_add1_attr(ar, xa)) + errx(1, "X509_REQ_add1_attr"); + failed |= x509_req_compare("X509_REQ_add1_attr", ar, der2, der2sz); + x509_req_cleanup(&ar, &der2); + + ASN1_OBJECT_free(coid); + X509_NAME_free(xn); + ASN1_OCTET_STRING_free(aos); + sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); + X509_ATTRIBUTE_free(xa); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(pkey_ctx); + X509_REQ_free(xr); + free(der); + + return failed; +} + +static const struct testcase { + char *data; + int len; + int len_to_pass; + int encode_type; + int expected_result; + char *expected_string; +} testCases[] = { + /* should work */ + {"fozzie", 6, 80, MBSTRING_ASC, 6, "fozzie"}, + /* should work */ + {"fozzie", 6, -1, MBSTRING_ASC, 6, ""}, + /* should fail, truncation */ + {"muppet", 6, 5, MBSTRING_ASC, -1, ""}, + /* should fail, contains 0 byte */ + {"g\0nzo", 5, 80, MBSTRING_ASC, -1, ""}, + /* should fail, can't encode as utf-8 */ + {"\x30\x00", 2, 80, V_ASN1_SEQUENCE, -1, ""}, +}; + +#define NUM_TEST_CASES (sizeof(testCases) / sizeof(testCases[0])) + +static int +test_x509_name_get(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < NUM_TEST_CASES; i++) { + const struct testcase *test = testCases + i; + X509_NAME_ENTRY *entry = NULL; + X509_NAME *name = NULL; + char textbuf[80]; + int result; + + textbuf[0] = '\0'; + if ((name = X509_NAME_new()) == NULL) + err(1, "X509_NAME_new"); + if ((entry = X509_NAME_ENTRY_new()) == NULL) + err(1, "X509_NAME_ENTRY_new"); + if (!X509_NAME_ENTRY_set_object(entry, + OBJ_nid2obj(NID_commonName))) + err(1, "X509_NAME_ENTRY_set_object"); + if (!X509_NAME_ENTRY_set_data(entry, test->encode_type, + test->data, test->len)) + err(1, "X509_NAME_ENTRY_set_data"); + if (!X509_NAME_add_entry(name, entry, -1, 0)) + err(1, "X509_NAME_add_entry"); + if (test->len_to_pass == -1) + result = X509_NAME_get_text_by_NID(name, NID_commonName, + NULL, 0); + else + result = X509_NAME_get_text_by_NID(name, NID_commonName, + textbuf, test->len_to_pass); + if (result != test->expected_result) { + fprintf(stderr, + "Test %zu X509_GET_text_by_NID returned %d," + "expected %d\n", i, result, test->expected_result); + failed++; + } + if (result != -1 && + strcmp(test->expected_string, textbuf) != 0) { + fprintf(stderr, + "Test %zu, X509_GET_text_by_NID returned bytes do" + "not match \n", i); + failed++; + } + X509_NAME_ENTRY_free(entry); + X509_NAME_free(name); + } + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= test_x509_setters(); + /* failed |= */ test_x509_crl_setters(); + /* failed |= */ test_x509_req_setters(); + failed |= test_x509_name_get(); + + OPENSSL_cleanup(); + + return failed; +} diff --git a/tests/x509_info.c b/tests/x509_info.c new file mode 100644 index 0000000..8e223e2 --- /dev/null +++ b/tests/x509_info.c @@ -0,0 +1,184 @@ +/* $OpenBSD: x509_info.c,v 1.2 2020/09/18 14:41:04 tb Exp $ */ +/* + * Copyright (c) 2020 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +static const char *const bogus_pem = "\ +-----BEGIN BOGUS----- \n\ +-----END BOGUS----- \n\ +"; + +static const char *const cert_pem = "\ +-----BEGIN CERTIFICATE----- \n\ +MIIDpTCCAo2gAwIBAgIJAPYm3GvOr5eTMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV \n\ +BAYTAlVLMRYwFAYDVQQKDA1PcGVuU1NMIEdyb3VwMSIwIAYDVQQLDBlGT1IgVEVT \n\ +VElORyBQVVJQT1NFUyBPTkxZMSUwIwYDVQQDDBxPcGVuU1NMIFRlc3QgSW50ZXJt \n\ +ZWRpYXRlIENBMB4XDTE0MDUyNDE0NDUxMVoXDTI0MDQwMTE0NDUxMVowZDELMAkG \n\ +A1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxIjAgBgNVBAsMGUZPUiBU \n\ +RVNUSU5HIFBVUlBPU0VTIE9OTFkxGTAXBgNVBAMMEFRlc3QgQ2xpZW50IENlcnQw \n\ +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0ranbHRLcLVqN+0BzcZpY \n\ ++yOLqxzDWT1LD9eW1stC4NzXX9/DCtSIVyN7YIHdGLrIPr64IDdXXaMRzgZ2rOKs \n\ +lmHCAiFpO/ja99gGCJRxH0xwQatqAULfJVHeUhs7OEGOZc2nWifjqKvGfNTilP7D \n\ +nwi69ipQFq9oS19FmhwVHk2wg7KZGHI1qDyG04UrfCZMRitvS9+UVhPpIPjuiBi2 \n\ +x3/FZIpL5gXJvvFK6xHY63oq2asyzBATntBgnP4qJFWWcvRx24wF1PnZabxuVoL2 \n\ +bPnQ/KvONDrw3IdqkKhYNTul7jEcu3OlcZIMw+7DiaKJLAzKb/bBF5gm/pwW6As9 \n\ +AgMBAAGjTjBMMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXgMCwGCWCGSAGG \n\ ++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTANBgkqhkiG9w0B \n\ +AQUFAAOCAQEAJzA4KTjkjXGSC4He63yX9Br0DneGBzjAwc1H6f72uqnCs8m7jgkE \n\ +PQJFdTzQUKh97QPUuayZ2gl8XHagg+iWGy60Kw37gQ0+lumCN2sllvifhHU9R03H \n\ +bWtS4kue+yQjMbrzf3zWygMDgwvFOUAIgBpH9qGc+CdNu97INTYd0Mvz51vLlxRn \n\ +sC5aBYCWaZFnw3lWYxf9eVFRy9U+DkYFqX0LpmbDtcKP7AZGE6ZwSzaim+Cnoz1u \n\ +Cgn+QmpFXgJKMFIZ82iSZISn+JkCCGxctZX1lMvai4Wi8Y0HxW9FTFZ6KBNwwE4B \n\ +zjbN/ehBkgLlW/DWfi44DvwUHmuU6QP3cw== \n\ +-----END CERTIFICATE----- \n\ +"; + +int +main(void) +{ + BIO *bp; + STACK_OF(X509_INFO) *skin, *skout; + X509_INFO *info0, *info1; + const char *errdata; + unsigned long errcode; + int errcount, errflags, num; + + errcount = 0; + if ((skin = sk_X509_INFO_new_null()) == NULL) + err(1, "sk_X509_INFO_new_null"); + + /* Test with empty input. */ + + if ((bp = BIO_new_mem_buf("", 0)) == NULL) + err(1, "BIO_new_mem_buf(empty)"); + if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) == NULL) + err(1, "empty input: %s", + ERR_error_string(ERR_get_error(), NULL)); + if (skout != skin) + errx(1, "empty input did not return the same stack"); + skout = NULL; + if ((num = sk_X509_INFO_num(skin)) != 0) + errx(1, "empty input created %d X509_INFO objects", num); + BIO_free(bp); + + /* Test with bogus input. */ + + if ((bp = BIO_new_mem_buf(bogus_pem, strlen(bogus_pem))) == NULL) + err(1, "BIO_new_mem_buf(bogus_pem)"); + if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL) + errx(1, "success with bogus input on first try"); + if ((num = sk_X509_INFO_num(skin)) != 0) + errx(1, "bogus input created %d X509_INFO objects", num); + if (BIO_reset(bp) != 1) + errx(1, "BIO_reset"); + + /* Populate stack and test again with bogus input. */ + + if ((info0 = X509_INFO_new()) == NULL) + err(1, "X509_INFO_new"); + info0->references = 2; /* X509_INFO_up_ref(3) doesn't exist. */ + if (sk_X509_INFO_push(skin, info0) != 1) + err(1, "sk_X509_INFO_push"); + if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL) + errx(1, "success with bogus input on second try"); + if ((num = sk_X509_INFO_num(skin)) != 1) + errx(1, "bogus input changed stack size from 1 to %d", num); + if (sk_X509_INFO_value(skin, 0) != info0) + errx(1, "bogus input changed stack content"); + if (info0->references != 2) { + warnx("bogus input changed ref count from 2 to %d", + info0->references); + info0->references = 2; + errcount++; + } + BIO_free(bp); + + /* Use a real certificate object. */ + + if ((bp = BIO_new_mem_buf(cert_pem, strlen(cert_pem))) == NULL) + err(1, "BIO_new_mem_buf(cert_pem)"); + if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) == NULL) { + errdata = NULL; + errflags = 0; + while ((errcode = ERR_get_error_line_data(NULL, NULL, + &errdata, &errflags)) != 0) + if (errdata != NULL && (errflags & ERR_TXT_STRING)) + warnx("%s --- %s", + ERR_error_string(errcode, NULL), + errdata); + else + warnx("%s", ERR_error_string(errcode, NULL)); + err(1, "real input: parsing failed"); + } + if (skout != skin) + errx(1, "real input did not return the same stack"); + skout = NULL; + if ((num = sk_X509_INFO_num(skin)) != 2) + errx(1, "real input changed stack size from 1 to %d", num); + if (sk_X509_INFO_value(skin, 0) != info0) + errx(1, "real input changed stack content"); + if (info0->references != 2) + errx(1, "real input changed ref count from 2 to %d", + info0->references); + info1 = sk_X509_INFO_pop(skin); + if (info1->x509 == NULL) + errx(1, "real input did not create a certificate"); + X509_INFO_free(info1); + info1 = NULL; + BIO_free(bp); + + /* Two real certificates followed by bogus input. */ + + if ((bp = BIO_new(BIO_s_mem())) == NULL) + err(1, "BIO_new"); + if (BIO_puts(bp, cert_pem) != strlen(cert_pem)) + err(1, "BIO_puts(cert_pem) first copy"); + if (BIO_puts(bp, cert_pem) != strlen(cert_pem)) + err(1, "BIO_puts(cert_pem) second copy"); + if (BIO_puts(bp, bogus_pem) != strlen(bogus_pem)) + err(1, "BIO_puts(bogus_pem)"); + if ((skout = PEM_X509_INFO_read_bio(bp, skin, NULL, NULL)) != NULL) + errx(1, "success with real + bogus input"); + if ((num = sk_X509_INFO_num(skin)) != 1) { + warnx("real + bogus input changed stack size from 1 to %d", + num); + while (sk_X509_INFO_num(skin) > 1) + (void)sk_X509_INFO_pop(skin); + errcount++; + } + if (sk_X509_INFO_value(skin, 0) != info0) + errx(1, "real + bogus input changed stack content"); + if (info0->references != 2) { + warnx("real + bogus input changed ref count from 2 to %d", + info0->references); + errcount++; + } + BIO_free(bp); + info0->references = 1; + X509_INFO_free(info0); + sk_X509_INFO_free(skin); + + if (errcount > 0) + errx(1, "%d errors detected", errcount); + return 0; +} diff --git a/tests/x509attribute.c b/tests/x509attribute.c new file mode 100644 index 0000000..908935c --- /dev/null +++ b/tests/x509attribute.c @@ -0,0 +1,105 @@ +/* $OpenBSD: x509attribute.c,v 1.3 2021/11/01 08:28:31 tb Exp $ */ +/* + * Copyright (c) 2020 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +void fail_head(const char *); +void fail_tail(void); +void fail_str(const char *, const char *); +void fail_int(const char *, int); + +static const char *testname; +static int errcount; + +void +fail_head(const char *stepname) +{ + fprintf(stderr, "failure#%d testname=%s stepname=%s ", + ++errcount, testname, stepname); +} + +void +fail_tail(void) +{ + unsigned long errnum; + + if ((errnum = ERR_get_error())) + fprintf(stderr, "OpenSSL says: %s\n", + ERR_error_string(errnum, NULL)); + if (errno) + fprintf(stderr, "libc says: %s\n", strerror(errno)); +} + +void +fail_str(const char *stepname, const char *result) +{ + fail_head(stepname); + fprintf(stderr, "wrong result=%s\n", result); + fail_tail(); +} + +void +fail_int(const char *stepname, int result) +{ + fail_head(stepname); + fprintf(stderr, "wrong result=%d\n", result); + fail_tail(); +} + +int +main(void) +{ + X509_ATTRIBUTE *attrib; + ASN1_TYPE *any; + ASN1_OBJECT *coid; + int num; + + testname = "preparation"; + if ((coid = OBJ_nid2obj(NID_pkcs7_data)) == NULL) { + fail_str("OBJ_nid2obj", "NULL"); + return 1; + } + + testname = "valid_args"; + if ((attrib = X509_ATTRIBUTE_create(NID_pkcs9_contentType, + V_ASN1_OBJECT, coid)) == NULL) + fail_str("X509_ATTRIBUTE_create", "NULL"); + else if (X509_ATTRIBUTE_get0_object(attrib) == NULL) + fail_str("X509_ATTRIBUTE_get0_object", "NULL"); + else if ((num = X509_ATTRIBUTE_count(attrib)) != 1) + fail_int("X509_ATTRIBUTE_count", num); + else if ((any = X509_ATTRIBUTE_get0_type(attrib, 0)) == NULL) + fail_str("X509_ATTRIBUTE_get0_type", "NULL"); + else if (any->type != V_ASN1_OBJECT) + fail_int("any->type", any->type); + else if (any->value.object != coid) + fail_str("value", "wrong pointer"); + X509_ATTRIBUTE_free(attrib); + + testname = "bad_nid"; + if ((attrib = X509_ATTRIBUTE_create(-1, + V_ASN1_OBJECT, coid)) != NULL) + fail_str("X509_ATTRIBUTE_create", "not NULL"); + X509_ATTRIBUTE_free(attrib); + + return errcount != 0; +} diff --git a/tests/x509name.c b/tests/x509name.c new file mode 100644 index 0000000..9deeeb2 --- /dev/null +++ b/tests/x509name.c @@ -0,0 +1,62 @@ +/* $OpenBSD: x509name.c,v 1.3 2021/10/31 08:27:15 tb Exp $ */ +/* + * Copyright (c) 2018 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +static void debug_print(X509_NAME *); + +static void +debug_print(X509_NAME *name) +{ + int loc; + + for (loc = 0; loc < X509_NAME_entry_count(name); loc++) + printf("%d:", + X509_NAME_ENTRY_set(X509_NAME_get_entry(name, loc))); + putchar(' '); + X509_NAME_print_ex_fp(stdout, name, 0, XN_FLAG_SEP_CPLUS_SPC); + putchar('\n'); +} + +int +main(void) +{ + X509_NAME *name; + + if ((name = X509_NAME_new()) == NULL) + err(1, NULL); + X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, + "BaWue", -1, -1, 0); + X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, + "KIT", -1, -1, 0); + debug_print(name); + + X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, + "Karlsruhe", -1, 1, 0); + debug_print(name); + + X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, + "DE", -1, 0, 1); + debug_print(name); + + X509_NAME_free(name); + + return 0; +} diff --git a/tests/x509req_ext.c b/tests/x509req_ext.c new file mode 100644 index 0000000..b91a413 --- /dev/null +++ b/tests/x509req_ext.c @@ -0,0 +1,161 @@ +/* $OpenBSD: x509req_ext.c,v 1.1 2021/11/03 13:08:57 schwarze Exp $ */ +/* + * Copyright (c) 2020, 2021 Ingo Schwarze + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include +#include + +void fail_head(const char *); +void fail_tail(void); +void fail_str(const char *, const char *); +void fail_int(const char *, int); +void fail_ptr(const char *, const void *); + +static const char *testname; +static int errcount; + +void +fail_head(const char *stepname) +{ + fprintf(stderr, "failure#%d testname=%s stepname=%s ", + ++errcount, testname, stepname); +} + +void +fail_tail(void) +{ + unsigned long errnum; + + if ((errnum = ERR_get_error())) + fprintf(stderr, "OpenSSL says: %s\n", + ERR_error_string(errnum, NULL)); + if (errno) + fprintf(stderr, "libc says: %s\n", strerror(errno)); +} + +void +fail_str(const char *stepname, const char *result) +{ + fail_head(stepname); + fprintf(stderr, "wrong result=%s\n", result); + fail_tail(); +} + +void +fail_int(const char *stepname, int result) +{ + fail_head(stepname); + fprintf(stderr, "wrong result=%d\n", result); + fail_tail(); +} + +void +fail_ptr(const char *stepname, const void *result) +{ + fail_head(stepname); + fprintf(stderr, "wrong result=%p\n", result); + fail_tail(); +} + +int +main(void) +{ + X509_REQ *req; + X509_EXTENSIONS *exts; + X509_ATTRIBUTE *attr; + ASN1_TYPE *aval; + int irc; + + testname = "exts=NULL"; + if ((req = X509_REQ_new()) == NULL) { + fail_str("X509_REQ_new", "NULL"); + return 1; + } + if ((irc = X509_REQ_add_extensions(req, NULL)) != 0) + fail_int("X509_REQ_add_extensions", irc); + if ((irc = X509_REQ_get_attr_count(req)) != 0) + fail_int("X509_REQ_get_attr_count", irc); + if ((attr = X509_REQ_get_attr(req, 0)) != NULL) + fail_ptr("X509_REQ_get_attr", attr); + X509_REQ_free(req); + + testname = "nid=-1"; + if ((req = X509_REQ_new()) == NULL) { + fail_str("X509_REQ_new", "NULL"); + return 1; + } + if ((exts = sk_X509_EXTENSION_new_null()) == NULL) { + fail_str("sk_X509_EXTENSION_new_null", "NULL"); + return 1; + } + if ((irc = X509_REQ_add_extensions_nid(req, exts, -1)) != 0) + fail_int("X509_REQ_add_extensions", irc); + if ((irc = X509_REQ_get_attr_count(req)) != 0) + fail_int("X509_REQ_get_attr_count", irc); + if ((attr = X509_REQ_get_attr(req, 0)) != NULL) + fail_ptr("X509_REQ_get_attr", attr); + X509_REQ_free(req); + + testname = "valid"; + if ((req = X509_REQ_new()) == NULL) { + fail_str("X509_REQ_new", "NULL"); + return 1; + } + if ((irc = X509_REQ_add_extensions(req, exts)) != 1) + fail_int("X509_REQ_add_extensions", irc); + sk_X509_EXTENSION_free(exts); + if ((irc = X509_REQ_get_attr_count(req)) != 1) + fail_int("X509_REQ_get_attr_count", irc); + if ((attr = X509_REQ_get_attr(req, 0)) == NULL) { + fail_str("X509_REQ_get_attr", "NULL"); + goto end_valid; + } + if ((irc = X509_ATTRIBUTE_count(attr)) != 1) + fail_int("X509_ATTRIBUTE_count", irc); + if ((aval = X509_ATTRIBUTE_get0_type(attr, 0)) == NULL) { + fail_str("X509_ATTRIBUTE_get0_type", "NULL"); + goto end_valid; + } + if ((irc = ASN1_TYPE_get(aval)) != V_ASN1_SEQUENCE) + fail_int("ASN1_TYPE_get", irc); + exts = ASN1_item_unpack(aval->value.sequence, &X509_EXTENSIONS_it); + if (exts == NULL) { + fail_str("ASN1_item_unpack", "NULL"); + goto end_valid; + } + if ((irc = sk_X509_EXTENSION_num(exts)) != 0) + fail_int("sk_X509_EXTENSION_num", irc); + sk_X509_EXTENSION_free(exts); + +end_valid: + testname = "getext"; + if ((exts = X509_REQ_get_extensions(req)) == NULL) { + fail_str("X509_REQ_get_extensions", "NULL"); + goto end_getext; + } + if ((irc = sk_X509_EXTENSION_num(exts)) != 0) + fail_int("sk_X509_EXTENSION_num", irc); + sk_X509_EXTENSION_free(exts); + +end_getext: + X509_REQ_free(req); + return errcount != 0; +} diff --git a/tests/xchacha20_poly1305_tests.txt b/tests/xchacha20_poly1305_tests.txt new file mode 100644 index 0000000..d3eb39b --- /dev/null +++ b/tests/xchacha20_poly1305_tests.txt @@ -0,0 +1,366 @@ +# Test vectors generated from libsodium + +KEY: 1f4774fbe6324700d62dd6a104e7b3ca7160cfd958413f2afdb96695475f007e +NONCE: 029174e5102710975a8a4a936075eb3e0f470d436884d250 +IN: +AD: +CT: +TAG: f55cf0949af356f977479f1f187d7291 + +KEY: eb27969c7abf9aff79348e1e77f1fcba7508ceb29a7471961b017aef9ceaf1c2 +NONCE: 990009311eab3459c1bee84b5b860bb5bdf93c7bec8767e2 +IN: e7ec3d4b9f +AD: +CT: 66bd484861 +TAG: 07e31b4dd0f51f0819a0641c86380f32 + +KEY: 4b6d89dbd7d019c0e1683d4c2a497305c778e2089ddb0f383f2c7fa2a5a52153 +NONCE: 97525eb02a8d347fcf38c81b1be5c3ba59406241cf251ba6 +IN: 074db54ef9fbc680b41a +AD: +CT: 1221898afd6f516f770f +TAG: 75e7182e7d715f5a32ee6733fd324539 + +KEY: 766997b1dc6c3c73b1f50e8c28c0fcb90f206258e685aff320f2d4884506c8f4 +NONCE: 30e7a9454892ef304776b6dc3d2c2f767ed97041b331c173 +IN: b8250c93ac6cf28902137b4522cc67 +AD: +CT: e2a13eeff8831a35d9336cb3b5c5d9 +TAG: 62fdf67735cad0172f9b88603b5f3c13 + +KEY: 6585031b5649fcabd9d4971d4ac5646fc7dca22f991dfa7dac39647001004e20 +NONCE: 705ee25d03fec430e24c9c6ccaa633f5b86dd43682778278 +IN: 9a4ca0633886a742e0241f132e8f90794c34dfd4 +AD: +CT: 0a8e6fd4cd1640be77c4c87dde4ae6222c887ed7 +TAG: edc4fbc91dfa07021e74ae0d9d1c98dc + +KEY: dfc6f7c86a10a319ebcb6362997e585f55b67f3434f47dc4039c2d67973e3077 +NONCE: 6097f30fd75229d928454c7d59a2d2c58bfddcb14c16438e +IN: 74c946a7f0733377e852a23087506a28dccef86e101a4359c0 +AD: +CT: 6e8ea0bb4c2f1323841d8e236816c61c3295866b75cefb5c25 +TAG: f16c0e9487ca7de5e7cb2a1b8bb370fc + +KEY: 59b8d488773767c4804d918709cfec6c69a193371145bb94f183899851aaadac +NONCE: ad5bdf8f190ca2d2cc02a75bb62aa22274cb3c98fe2d25f2 +IN: 066b9ed10f16d3dc132b409aae02d8cac209dd9b4fb789c4d34725ab2a1f +AD: +CT: 2bbd4542489006df66ad1462a932524642b139ddcbf86b6b480e9e6d976c +TAG: ca4835419ba029bc57010a8cc8bca80c + +KEY: 8c0cb4633cf8dc6b4b9552d1035f85517cb1ba4c36bcbc43338a8c6c7d15ce20 +NONCE: 8418b9655a0376fadefa3cdf8805815c4f7b56f467a74a95 +IN: 50c205a9c5d4088ba8e59a96fcd837f5170669854547678288199f1078ff2a81f0b19a +AD: +CT: 8b55a12df1a85dd3fb19c34ab047a85849d15a30225bb5360bad1f0a8f5f2bd49f5898 +TAG: bce13201df6e4a7e6d896262e45d969d + +KEY: b45386a75a5772e34bd193e1946f69ebfb90c37ae4581d39c9669d75e4584f50 +NONCE: 9fb763d0926585b5f726af9b8e3babdb331e9aa97f8d99ed +IN: 64df0e341145d9e4a0d090153591a74893bc36cb9dae1e9570d8fee62e907cf004f9d8a360343483 +AD: +CT: 3146d8a5c898edd832ec9d126e93b3a433ec97dc47dce0e1985bda88c88c6aeca46fc7d9a68e30ab +TAG: 44fdb0d69abd8068442cb2ea6df8b2f2 + +KEY: f2efbd358dd353639a162be39a957d27c0175d5ab72aeba4a266aeda434e4a58 +NONCE: 65a6f7ebe48de78beb183b518589a0afacf71b40a949fa59 +IN: f7473947996e6682a3b9c720f03cfaf26bbcdaf76c83342d2ad922435e227a5d1eacbd9bd6ea1727ec19fb0e42 +AD: +CT: 778a0fb701b9d671ccfaf1454e8928158ede9bb4395119356a8133036840c1bcbb8fe5e19922fbbcf8b18596e7 +TAG: 9d195a89fdd29ca271405d3330f996f9 + +KEY: 9dd674fb4a30a7bb85fc78050479ab0e2c3cc9f9f5b8689a7a67413aca304b21 +NONCE: ad9e8fe15940694725f232e88f79cda7c82fe1b8aae58ba4 +IN: 7272bb6609cbd1399a0b89f6ea255165f99330aeb170ac88fccdd8e226df0952407e35718fb5edc9e987faabb271cc69f7e7 +AD: +CT: 846901650cb38974463a18c367676e1579ebdaf3e96b57224e842f5d5f678f3270b9a15f01241795662befb3db0768800e25 +TAG: 900004db3613acbeb33d65d74dd437d7 + +KEY: 280cbe7380a0d8bb4d8dd4476012f2eeb388a37b8b71067969abb99f6a888007 +NONCE: 2e1854617c67002599e6b077a812c326deb22fe29d093cbb +IN: d0901ec3d31ece2832685ff577f383bdff26c31341ea254acee7c5929a5df74fea2aa964524dc680b2f55fbd4fea900e956c304cc4ac3c +AD: +CT: 546370726cc63068d3520d67f4f57f65d03b9ecec21c2a8c7b1133089ad28b07025a7181bddeb4a49f514fac1a44f64ee3af33d778fb98 +TAG: 39084e33e42a1b05f58da65ba487d138 + +KEY: 887564f75afa78f595cdadcea7340d20f5c5a2df169d0ad14b15fe32ce337004 +NONCE: 54c11df13d1f444da80b0964caeb59474b17b23a650a33f5 +IN: f0f008eece79ecb24b715dff8a3456dfe253924b99f98f2f1b18564cced50925fca860d1c2d4785bdf4a964c76c3079efa6b37c4ba2cacc534fb590c +AD: +CT: 32bb077268568d569b39e8ccdeeeb447ef424eaa2ffab565209a19b16a25952f897e5405bb0d67d8c9005d1c0b32687164d17fa4d0f412b80414c025 +TAG: 0bac7c0f8dce12917fbd4ed1738ac0cc + +KEY: 21c6aa88eb1a320d251f71a4b312ca75347040990d869a1dd2a1982c30fda2c7 +NONCE: 7dead2f1a3d9d45a9124a40efe8994300976991a4417ef4d +IN: +AD: e1bf7de4 +CT: +TAG: 341e9d0687006f981bced2f985f953e6 + +KEY: 0c97b9a65ffcd80b8f7c20c3904d0d6dd8809a7f97d7f46d39a12c198a85da5d +NONCE: 1f2c1dbc5f52fc9c8f9ca7695515d01d15904b86f703fba3 +IN: ecaf65b66d +AD: bd8a6f18 +CT: 8d1b2b0e38 +TAG: 27a7c7ac8bda627085414f0f31206a07 + +KEY: 4ab5e3595f39c4379a924e5f8ebcf3279075c08d18daff01d9ddfa40e03faf12 +NONCE: 94e6ddc294f5f1531924ec018823343ebcc220a88ea5ee33 +IN: c91b73abe5316c3effc6 +AD: c576f6ea +CT: abe960fbc64b339c53b1 +TAG: 7ebae48a2ff10117069324f04619ad6f + +KEY: a1e6146c71c2ea22300e9063455f621e15bd5bf1a3762e17f845e1aba5dd5a9c +NONCE: 82ddb6929abff8a9ad03dfb86c0bb3e7c092d45ebfa60a1b +IN: f011f32ccc2955158c117f53cf7b12 +AD: 5d14bc05 +CT: 44592321c665f51e9ffea052df1fea +TAG: d556798b97f9b647729801419424affc + +KEY: 7a1af30362c27fd55b8c24b7fca324d350decee1d1f8fae56b66253a9dd127dd +NONCE: 61201d6247992002e24e1a893180d4f0c19a3ae4cc74bf0c +IN: 5c7150b6a4daa362e62f82f676fdc4c4b558df64 +AD: 00c49210 +CT: 27d9e2730b6809c08efbd4b0d24639c7b67486f3 +TAG: 5889fdee25379960038778e36b2cedb2 + +KEY: 0b3fd9073e545ac44a7967263ead139c9547f7a54f06228fd3c8609fa2620784 +NONCE: 6450e1097d6f9ea76eb42e8e65972d501041c3a58baf8770 +IN: d679ae442b0351e5bff9906b099d45aab4f6aea5306a7a794f +AD: 318d292b +CT: a3f9ee45316d7b0f948a26145ee4fd0552bc6dc25e577e777a +TAG: 0068a401a194b8417ec0e198baa81830 + +KEY: 047c7d378fe80c02ee48df6f679a859253aed534fdcdd87023eb3d2f93fcafe3 +NONCE: ed240b0ff6f8ac585b3ea1ab2dab8080fc2f6401b010c5d0 +IN: 7288afb4e0fa5c58602090a75c10d84b5f5f1c0e03498519afe457251aa7 +AD: e4310302 +CT: 87906b14ca3e32ab01523b31ae0bb74590ce9e1df0811e743a2c7a93415a +TAG: 3a0abeab93792b1ffe768d316da74741 + +KEY: 1ad4e42acc5dfd07eb0a2456e9103cd0e150a36c667eb2f2b73c0d1ac1089ce3 +NONCE: 48efb52387284c5d38b4940c75f0c39a3f81f60bfebb48cb +IN: da7edb5b3193b4484f09efa85fcf85600968ecdc537d3829a469c866ee67b0df677866 +AD: 446be8e3 +CT: b76457ca99e95b6539b12f1d6bdac55a6d5c6469b1ff274459363ec05241f7e6e5d3ce +TAG: 06880ee508ce929da5a81f8b9de0031c + +KEY: 702a554c1b703d4dd69ad51234293ab787a01e15bdb3ce88bf89e18c01a67164 +NONCE: ea535d9c371241b9850b8b4a596b63db79eea60bd2cd9fbb +IN: a97156e9b39d05c00b811552d22088d7ee090a117a7f08adac574820d592021f16207720d49fb5fd +AD: ba5790e3 +CT: 8d0b2b04479c33287096f0c6276a73f6c037edc1a2b28f8d3b2b8e6d4c5f9dc5113309dd3ecb15e6 +TAG: 3cf303305e12924d29c223976699fb73 + +KEY: 1bb7303fefa4d8d344bb9a215901b2314324bf1f3aeb9df5d1c1532c3a55ebf1 +NONCE: a304551e5f0dc98995ddfee6215a9995023a3696debfd302 +IN: 6cf6819ce3e7ed9d4f85f4a5699701dbcaf3161adc210c0b7825ddfd83d6d7c685db62f68b3801ccc8a786066d +AD: 901c5feb +CT: bc5ef09c111f76e54f897e6fce4aee1d25b6ed934f641ed5262d0c5eed45f610a6aea3b58b7771e34256d43a16 +TAG: b83f73f7995ba1b243dbf48ddfeb8e3a + +KEY: 24b294f6cbac10d87158d1c6aca83b337d596132afac7633f69a3b3e58823f11 +NONCE: 805772ff619cc6fcc5ec0e9965435d6f74a2290c055ec754 +IN: 65e8581286868caabcec1a9814db00b805edc660b94ee3babc6ce19a3ca868bd322105484d59b4ce02ced4071bc16642a1f2 +AD: 7ae1c561 +CT: fe1d463b1466e8e411f0b0700f90760472ee5141f3e5afef43fd729f1623dca75cd4d00576765b335f8b2b77b00527599cb3 +TAG: 111d8540fd5ec04b9ba16ed810133026 + +KEY: 38e63e8b6402ac3f6d1641a1e3b74d2074be0fe41129975a3ff62b74ca52af05 +NONCE: 228d671b036710cbdaa72e9bf1d9ed6982b0bb3428a69fd6 +IN: 20a8d18878924d09aac32853c10e73dbd741134b7050ae6999839f2dbc727cb0052b5497c4bbd2a89e716278f15c81b871953614a49693 +AD: e9e6ac73 +CT: 80e0fe8eb26e5df229c6d939c944d440a37aa3cabf76eab5b9a420095513021ea4241ab367f6f44a20817b14631549ae6c96aa963970e1 +TAG: 1e80fbafcc7168e0494fce4cd76d692c + +KEY: 4325dd8406fdb8431a81f1b5db3603995256de36121019724cca2190c87a6e83 +NONCE: dcbf3077b36d5d678d668fd2d0c99284c780b55c4658ea75 +IN: 4f599ad04f79be9add10fdc649b8be53e1062ea5e9c2bed22265dc6fb30d5ab4fd4425b38ff14d8e68013405bec1eff8c9ef3069902e492aac73dcd9 +AD: 6fa0d757 +CT: 7decbdc7043495c59ecc64e720436bb0708b586a46f8745f74391477f5a2520905dfcebc3765a330999013d309dfaa997bf70bab6a0b8f4f2a2a3cdf +TAG: 051ec4ecce208d9be0cd17f434e13be3 + +KEY: 2d3d9ed4bc9eb9668733bafbb73e88be2cd17021c3a23be69b981d9f0df71df1 +NONCE: 84cae69639240c82b58895997511f145e474ebe1b008f391 +IN: +AD: 64db597c26a4c3da +CT: +TAG: 2a22c4a962d46a719014ab7b0ffaf6d3 + +KEY: 09ec4e79a02db53b19b54dd2d3592afc92c74ef57d1e0f51f3726a6631b1b73f +NONCE: 2907ced16e0777fedb1e2de30df11b3fd712af41dd714a4b +IN: b6e50cd4ea +AD: b5488e9b7f339b7b +CT: 0163e75330 +TAG: e29401c6d756adcc516580ae656852aa + +KEY: 9d5ac25a417b8a57b85332979e8a7cbad23617bb27772bbccc2acb0acae7b755 +NONCE: ff152421688dd6af7fef87817b508493a32d97a06fbda4f3 +IN: 92f4b9bc809be77e6a0d +AD: 892b793f7a6e0727 +CT: bcc594f59de8ee8c22c6 +TAG: 1a8275816c0d32a1b6cfd41fa3889558 + +KEY: eccf80c5f744d2ecc932f95ade0d9fe9327e19795023db1846d68d04720a2401 +NONCE: abc050fad8876589633b222d6a0f2e0bf709f73610aa23ee +IN: 45a380e438405314510c166bac6840 +AD: c32c9a1ce6852046 +CT: 9fa452dc9ca04c16ff7bde9925e246 +TAG: 3d5e826162fa78de3fc043af26044a08 + +KEY: b1912d6bc3cff47f0c3beccff85d7cd915b70ab88d0d3a8a59e994e1b0da8ac8 +NONCE: d8756090a42eea14ff25be890e66bfe4949fad498776ea20 +IN: e2f85df2ebcfa6045bd521abfe8af37fc88a0be1 +AD: 4576bb59b78032c8 +CT: 5eb6324aa48e0a4f72f5cb0a4917faf93af4209c +TAG: 774f8077f039588495045fee07950e14 + +KEY: 85162b111c9f3163f57c2cbc311a1e9aeed9dd6136b5784bc9c0b5052f8bffbd +NONCE: 23cdb8b546bb8a5a746b24446f0ab4199f0543d915ff51f1 +IN: dc81000077d5743beef09ac91663885d984212bbccf3dbe6f3 +AD: 3084f3e9c4d0a15f +CT: 692d17ae0b524ec6edc0cf49b69ac90c99bed44691f7ae63b7 +TAG: efe72ff84b3bccb4d83a27ddc574bc21 + +KEY: b05ca358d8ca79f51283d83e2673bfb741c379ba271a773b8dd9c6a108e758d3 +NONCE: 9a53ad79f535c6e9da011463063c896f2ec7645e6e3548fc +IN: 44e793742c774020e7349c996418042dc0dc30ee2bfd2654008c8929a436 +AD: 71ab5948c5e0f4c6 +CT: c5eddb7aeaa175b5f3dab68cf746f2acaf56fc62b29804629e25e2d63879 +TAG: bec3b7a8b8dad22ff3d14d26273294d2 + +KEY: abb5136a01354c765a96e832df58bec3b088bd19dc4d6bd6674f2f02007ebdaa +NONCE: 71267ac9f4fe5caa1d52cd85948a170a778f0141d54dbffe +IN: afb526fe41c4e2a767ce77c4145b9d054268f5f3b279237dec97f8bc46f9d158868b86 +AD: 047baa2b04748b62 +CT: 0032d4c1e65da2266539464c5d3c2b1618454a6af0e7f1e3cfc87845c75f2f4ae8b03f +TAG: b526a95a33f17ab61f2cdfc1e2dd486a + +KEY: bb826ed38008a0d7fb34c0c1a1a1149d2cad16b691d5129cc83f5eff2b3e5748 +NONCE: 4e02fe0915d81e9d5a62e5b3551b9db882e3873c0aaa230d +IN: 20270d291a8d9791b0f5e35a64387bb4237bad61169841d7e1667c994ad49869c7d5580ffa752a2d +AD: db852a275081e29b +CT: d740012efb7e1bb986ce2c535134a45f658b92163c109bdecf1ce5b836879fe9e006a56be1fac8d7 +TAG: 21e931042e7df80695262198a06286c9 + +KEY: 938d2c59f6f3e2e7316726537932372e05e8c1b5577aae0ee870bf712ff001ab +NONCE: fb4d71cf7eb2f70df9759a64c76a36b75203f88bf64f4edb +IN: 8910415d674a93c54c8f5e4aa88e59648d9a0a5039a66837d58ab14f0665a5f6d9af9b839f9033d0fe8bc58f19 +AD: a3fca278a63bf944 +CT: 1905c6987a702980b7f87f1ed2d3ae073abe1401b23434f3db43b5c37c979c2068ce9a92afedcdc218003848ea +TAG: 1bd712f64777381f68be5ccc73f364a3 + +KEY: dd0521842f498d23236692a22db0eb2f0f14fef57577e5fb194503e206b0973d +NONCE: 519e0eee8f86c75c7a364e0905a5d10d82073e11b91083a5 +IN: 61ff13acb99c5a7fd1921ec787c8de23c1a712ff002b08cecc644a78c47341eab78e7680380c93c7d53d5e56ef050d6ff192 +AD: bb5c4e5ae8f7e461 +CT: 9bfdb0fd195fa5d37da3416b3b1e8f67bd2a456eb0317c02aabf9aac9d833a19bda299e6388e7b7119be235761477a34d49e +TAG: 0f0c03b8423583cb8305a74f622fa1f9 + +KEY: 189bd84be3fb02723539b29cf76d41507c8b85b7217777ee1fb8f84a24aa7fee +NONCE: ef1bf39f22ba2edf86853505c24fafdf62c1a067963c63ba +IN: d5f96e240b5dd77b9fb2bf11c154fcbff312a791c3eb0717684e4fd84bf943e788050b47e76c427f42f3e5344b2636091603ba3b1d7a91 +AD: 93368a8e0900c7b6 +CT: c55a8b7f587bee4f97514582c5115582abffd6312914d76c2568be6836f62ba098789ed897c9a7508a5dc214bf8c218664f29941ccdfd6 +TAG: 78f87352dcb1143038c95dc6e7352cfd + +KEY: 23a2dbfcd02d265805169fa86e6927c7d49c9a24d2707884e18955e32dafc542 +NONCE: 305c7851f46f23ea8d832d5ed09d266714fd14f82ba0f69c +IN: 224de94a938d49cad46144e657e548bd86690a1b57b81558095eace59df1c552600dea389aaa609304fbc1eadf2241f2118c8bdf04522e1898efe1d4 +AD: 0075b20502bd29b2 +CT: 8e10c59369bbb0d72958100b05788498f59588795e075b8bce21d92d320206348b04010ced9b8cd3d651e825488915ce4a6e4f1af2f4d2f77b955376 +TAG: c39f0595ae8112dea6ef96df1c12458b + +KEY: 264e3c3f47bdf795cdde57d9a30be5a4da8b18463c0e3e05df28b7bf4e56410b +NONCE: 3ee09b6e205c261bf48ac53a9ba0afa460a5d5c0f2d80be8 +IN: +AD: 8eeec09d8972cb8ab0069554 +CT: +TAG: 245a034d84edab9fa6f0decb6b984766 + +KEY: d8ba98a272b5f91797b04b114311c3b92b7f2e3bb72edb7f78ed311b9f8ea2ad +NONCE: 481de9a06eee76a501e3c2b9d7423d90596193ad9d8a6564 +IN: 9ee1a3134d +AD: 928653701f6d6c8429b08c0d +CT: 459a07898f +TAG: 9188ec8d8e3bd91dcfda48fcc76773f7 + +KEY: ac9afd627a745df682bb003517056f07876eb94d2f8c610c61b6ac0d34ec4ec0 +NONCE: eaae7b8704530db1e8c3dcc968a00604a333c7c27ba51b16 +IN: f7c3f6ee2e9c03394dc8 +AD: 796620b367d5f041821baf69 +CT: d4a69005790cc91d8d34 +TAG: e4c83def113afcf83a1ea8cb204a0eae + +KEY: ea1a07c1fd60a5421f1fb6c43b4318090e290c97aa3bfa037e6fc5ee00fd47d4 +NONCE: 37327805cce92b38a669affbca1de92e068727fcf6fbb09a +IN: 7002ca765b91913ee719e7521ef5ac +AD: 64e7c48fc3041eac0734737f +CT: 9d8857a8c52a9ab3bf44b024b191b6 +TAG: d072c31714a7d0fe1596fd443a96e715 + +KEY: b3beb34fe0229fc8f49b354e941025bde6a788f25017a60e8a49591ed5d7e7da +NONCE: dd0e9fec76de1f6efb022b12164f7e9248b8e8c01d14ac02 +IN: acf360d7529a42be1f132f74745a940da9e823f2 +AD: 1489ca8d852f0a8547dbe8bc +CT: 2e8718372d6e8167213cf112dc41c80377244f5a +TAG: e4f31e8f84b9356999dc60989009e698 + +KEY: 9357cecd10bab8d2e42ed88c0386204827c3b76e9e51150d09fd4e3b4e0e1e6f +NONCE: 81f2106a5379e0ed861cf76b3cf95afb17515478b5cbcae9 +IN: ee51a0f25d091288b5e2b91ad11d491329e48b35a18a3a8685 +AD: b80cb677f4b409cd1537363b +CT: f681f19fa8de1fdea3538001a46f30fa6333b76d6439337e68 +TAG: afad5e6d282d9df6d8119c32237b3e60 + +KEY: 9f868600fbf81e40398b7dfb201fcae35d34bba10908860b0b2bf8b942b4e8fa +NONCE: 2ddcc13c97185614095d437900b8c0a9170e0a4a50e46ba5 +IN: 133fa3ac176fee6df67472752e41c6834f13300c0064ff5b190f903b7ac7 +AD: 0d61321fbee8bb1f3f5cb454 +CT: b93abb311ec0bf018dc300c7d511b42ade72780373186e231820b44f22f0 +TAG: f8bd2f649a337783ff911e37966037bd + +KEY: 05affcdfce0a28539924370db8d80a78b835254778ec41acbff52bfab092fa33 +NONCE: 3edaeb185f7273b1a7cccba54f84c5f7d6583433b49d3694 +IN: 7657581faad266cc1037962a380c8aa5306f88000427d0a05397696b503790ad2643c6 +AD: d7c213e9e6f4a40f3e5b662c +CT: 5eb19080aadc89f2329da4f5c41dc60568651c424c1b05d827f2bfb8dbff42c5a08224 +TAG: 2da20087b5674f0b967d1baa664bbd82 + +KEY: 645ed60ec74ddfe1f02694792db4436c262d20405d8645cd9755d64876219799 +NONCE: d83665b44c1fdf567299f2b8501e9c0e7ae2dda0bb8f2c82 +IN: ceee69d32ad4667a00909964d9611bf34fd98be41ad7f0feaaaff8169060d64cf310c13bcb9394cf +AD: 57379f8f44191ec9cf3b1a07 +CT: 4496a0666f0f895ebce224b448a04502f2ae7b354d868b7c54295bf051162e82c530c767d1ffd2cc +TAG: 1ffc56da4fb961ffdfabe66d82ec8f29 + +KEY: 06624c9a75bb7dbe224a3f23791281f53c40b407a14161a3f82f34924623dc02 +NONCE: e647b8b4739bf542a81d72d695e1cd6ba348fa593987ac47 +IN: 2658763f8d70e8c3303582d66ba3d736ce9d407e9507f6c6627e382d0144da157d73d0aee10ef034083cdd9013 +AD: 75536443a6c2189a57d553bb +CT: 305cab5c2f9a6edccac307d6965febe3c86f2a1e31ac8c74e88924a10c2a29106bce980c803b7886985bba8ec5 +TAG: 8c12bb58c84175b9f601b704d0f8a25c + +KEY: 63aeb46083100bbcc430f4f09bcc34410df9cfd5883d629e4af8645ffabb89c2 +NONCE: b09830874dc549195a5d6da93b9dcc12aa1ec8af201c96bd +IN: 1b3c9050e0a062f5a5cff7bec8706864cf8648142ec5cb1f9867ace384e9b2bba33aab8dc83e83b2d2fac70cd5189f2b5ab5 +AD: 7dcc05b0940198bd5c68cdf1 +CT: d8b22e5d381de08a50b163c00dbbca6c07d61c80199cebd52234c7bd4f7ed0a90d47ef05617cdb8e3f782875ae629c0f0ad6 +TAG: 194077f0e6d415bf7307d171e8484a9c + +KEY: 4826c1bf8b48088fece4008922173c500ff45790f945b1027f36110da4fecc92 +NONCE: 3a78fc7397944d762303b0a75974ac92a60e250bf112600a +IN: d26e3a2b92120ff8056bb992660cc8a2364792589c16a518b8d232b8184aed05ba8d4fd0b2ad2b928cd873e11905a21ffece5f1e63c974 +AD: 904d2cd3e50f7bfb9352f142 +CT: 21f4cf679662fad36f57945fc0c0753c3791261eb58d643278dfe1f14bfb585c5a01370ba96f18dc3f6b6945a2c6997330b24f12f5219a +TAG: 95397c54428f9d069c511b5c82e0151c + +KEY: ec526c03d8a08e8a63751112428a76399c399e8b83d98c9247c73164805ac8fe +NONCE: 2cc1a6ae89c2a091415fa2964b44a0e5da629d40d77b77f1 +IN: 567377f5b6df5442e70bc9a31bc450bd4febfcf89d7ca611353c7e612d8b7e36e859f6365ec7e5e99e9e0e882532666dd7203d06f6e25439ed871237 +AD: 35575b56716868b66cd21e24 +CT: 6b738274fe974438f1f5fca8ef1ee7df664f1e72bc54ccd3fb58c4a3df67ef9a73261df41ffe9c52aeafc8be4f6524baf9efb1558d4a57defec7bee3 +TAG: 92599d4b14a795e8c375ec2a8960b4dc + diff --git a/tls/empty.c b/tls/empty.c new file mode 100644 index 0000000..e69de29 diff --git a/tls/tls.c b/tls/tls.c new file mode 100644 index 0000000..fdb994d --- /dev/null +++ b/tls/tls.c @@ -0,0 +1,931 @@ +/* $OpenBSD: tls.c,v 1.98 2023/07/02 06:37:27 beck Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "tls_internal.h" + +static struct tls_config *tls_config_default; + +static int tls_init_rv = -1; + +static void +tls_do_init(void) +{ + OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_CONFIG, NULL); + + if (BIO_sock_init() != 1) + return; + + if ((tls_config_default = tls_config_new_internal()) == NULL) + return; + + tls_config_default->refcount++; + + tls_init_rv = 0; +} + +int +tls_init(void) +{ + static pthread_once_t once = PTHREAD_ONCE_INIT; + + if (pthread_once(&once, tls_do_init) != 0) + return -1; + + return tls_init_rv; +} + +const char * +tls_error(struct tls *ctx) +{ + return ctx->error.msg; +} + +void +tls_error_clear(struct tls_error *error) +{ + free(error->msg); + error->msg = NULL; + error->num = 0; + error->tls = 0; +} + +static int +tls_error_vset(struct tls_error *error, int errnum, const char *fmt, va_list ap) +{ + char *errmsg = NULL; + int rv = -1; + + tls_error_clear(error); + + error->num = errnum; + error->tls = 1; + + if (vasprintf(&errmsg, fmt, ap) == -1) { + errmsg = NULL; + goto err; + } + + if (errnum == -1) { + error->msg = errmsg; + return (0); + } + + if (asprintf(&error->msg, "%s: %s", errmsg, strerror(errnum)) == -1) { + error->msg = NULL; + goto err; + } + rv = 0; + + err: + free(errmsg); + + return (rv); +} + +int +tls_error_set(struct tls_error *error, const char *fmt, ...) +{ + va_list ap; + int errnum, rv; + + errnum = errno; + + va_start(ap, fmt); + rv = tls_error_vset(error, errnum, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_error_setx(struct tls_error *error, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = tls_error_vset(error, -1, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_config_set_error(struct tls_config *config, const char *fmt, ...) +{ + va_list ap; + int errnum, rv; + + errnum = errno; + + va_start(ap, fmt); + rv = tls_error_vset(&config->error, errnum, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_config_set_errorx(struct tls_config *config, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = tls_error_vset(&config->error, -1, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_set_error(struct tls *ctx, const char *fmt, ...) +{ + va_list ap; + int errnum, rv; + + errnum = errno; + + va_start(ap, fmt); + rv = tls_error_vset(&ctx->error, errnum, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_set_errorx(struct tls *ctx, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = tls_error_vset(&ctx->error, -1, fmt, ap); + va_end(ap); + + return (rv); +} + +int +tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) +{ + va_list ap; + int rv; + + /* Only set an error if a more specific one does not already exist. */ + if (ctx->error.tls != 0) + return (0); + + va_start(ap, fmt); + rv = tls_error_vset(&ctx->error, -1, fmt, ap); + va_end(ap); + + return (rv); +} + +struct tls_sni_ctx * +tls_sni_ctx_new(void) +{ + return (calloc(1, sizeof(struct tls_sni_ctx))); +} + +void +tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx) +{ + if (sni_ctx == NULL) + return; + + SSL_CTX_free(sni_ctx->ssl_ctx); + X509_free(sni_ctx->ssl_cert); + + free(sni_ctx); +} + +struct tls * +tls_new(void) +{ + struct tls *ctx; + + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + return (NULL); + + tls_reset(ctx); + + if (tls_configure(ctx, tls_config_default) == -1) { + free(ctx); + return NULL; + } + + return (ctx); +} + +int +tls_configure(struct tls *ctx, struct tls_config *config) +{ + if (config == NULL) + config = tls_config_default; + + pthread_mutex_lock(&config->mutex); + config->refcount++; + pthread_mutex_unlock(&config->mutex); + + tls_config_free(ctx->config); + + ctx->config = config; + ctx->keypair = config->keypair; + + if ((ctx->flags & TLS_SERVER) != 0) + return (tls_configure_server(ctx)); + + return (0); +} + +int +tls_cert_hash(X509 *cert, char **hash) +{ + char d[EVP_MAX_MD_SIZE], *dhex = NULL; + int dlen, rv = -1; + + free(*hash); + *hash = NULL; + + if (X509_digest(cert, EVP_sha256(), d, &dlen) != 1) + goto err; + + if (tls_hex_string(d, dlen, &dhex, NULL) != 0) + goto err; + + if (asprintf(hash, "SHA256:%s", dhex) == -1) { + *hash = NULL; + goto err; + } + + rv = 0; + err: + free(dhex); + + return (rv); +} + +int +tls_cert_pubkey_hash(X509 *cert, char **hash) +{ + char d[EVP_MAX_MD_SIZE], *dhex = NULL; + int dlen, rv = -1; + + free(*hash); + *hash = NULL; + + if (X509_pubkey_digest(cert, EVP_sha256(), d, &dlen) != 1) + goto err; + + if (tls_hex_string(d, dlen, &dhex, NULL) != 0) + goto err; + + if (asprintf(hash, "SHA256:%s", dhex) == -1) { + *hash = NULL; + goto err; + } + + rv = 0; + + err: + free(dhex); + + return (rv); +} + +static int +tls_keypair_to_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY **pkey) +{ + BIO *bio = NULL; + X509 *x509 = NULL; + char *mem; + size_t len; + int ret = -1; + + *pkey = NULL; + + if (ctx->config->use_fake_private_key) { + mem = keypair->cert_mem; + len = keypair->cert_len; + } else { + mem = keypair->key_mem; + len = keypair->key_len; + } + + if (mem == NULL) + return (0); + + if (len > INT_MAX) { + tls_set_errorx(ctx, ctx->config->use_fake_private_key ? + "cert too long" : "key too long"); + goto err; + } + + if ((bio = BIO_new_mem_buf(mem, len)) == NULL) { + tls_set_errorx(ctx, "failed to create buffer"); + goto err; + } + + if (ctx->config->use_fake_private_key) { + if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to read X509 certificate"); + goto err; + } + if ((*pkey = X509_get_pubkey(x509)) == NULL) { + tls_set_errorx(ctx, "failed to retrieve pubkey"); + goto err; + } + } else { + if ((*pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to read private key"); + goto err; + } + } + + ret = 0; + err: + BIO_free(bio); + X509_free(x509); + return (ret); +} + +static int +tls_keypair_setup_pkey(struct tls *ctx, struct tls_keypair *keypair, EVP_PKEY *pkey) +{ + RSA_METHOD *rsa_method; + EC_KEY_METHOD *ecdsa_method; + RSA *rsa = NULL; + EC_KEY *eckey = NULL; + int ret = -1; + + /* Only install the pubkey hash if fake private keys are used. */ + if (!ctx->config->skip_private_key_check) + return (0); + + if (keypair->pubkey_hash == NULL) { + tls_set_errorx(ctx, "public key hash not set"); + goto err; + } + + switch (EVP_PKEY_id(pkey)) { + case EVP_PKEY_RSA: + if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL || + RSA_set_ex_data(rsa, 0, keypair->pubkey_hash) == 0) { + tls_set_errorx(ctx, "RSA key setup failure"); + goto err; + } + if (ctx->config->sign_cb != NULL) { + rsa_method = tls_signer_rsa_method(); + if (rsa_method == NULL || + RSA_set_ex_data(rsa, 1, ctx->config) == 0 || + RSA_set_method(rsa, rsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup RSA key"); + goto err; + } + } + /* Reset the key to work around caching in OpenSSL 3. */ + if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) { + tls_set_errorx(ctx, "failed to set RSA key"); + goto err; + } + break; + case EVP_PKEY_EC: + if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL || + EC_KEY_set_ex_data(eckey, 0, keypair->pubkey_hash) == 0) { + tls_set_errorx(ctx, "EC key setup failure"); + goto err; + } + if (ctx->config->sign_cb != NULL) { + ecdsa_method = tls_signer_ecdsa_method(); + if (ecdsa_method == NULL || + EC_KEY_set_ex_data(eckey, 1, ctx->config) == 0 || + EC_KEY_set_method(eckey, ecdsa_method) == 0) { + tls_set_errorx(ctx, "failed to setup EC key"); + goto err; + } + } + /* Reset the key to work around caching in OpenSSL 3. */ + if (EVP_PKEY_set1_EC_KEY(pkey, eckey) == 0) { + tls_set_errorx(ctx, "failed to set EC key"); + goto err; + } + break; + default: + tls_set_errorx(ctx, "incorrect key type"); + goto err; + } + + ret = 0; + + err: + RSA_free(rsa); + EC_KEY_free(eckey); + return (ret); +} + +int +tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, + struct tls_keypair *keypair, int required) +{ + EVP_PKEY *pkey = NULL; + + if (!required && + keypair->cert_mem == NULL && + keypair->key_mem == NULL) + return(0); + + if (keypair->cert_mem != NULL) { + if (keypair->cert_len > INT_MAX) { + tls_set_errorx(ctx, "certificate too long"); + goto err; + } + + if (SSL_CTX_use_certificate_chain_mem(ssl_ctx, + keypair->cert_mem, keypair->cert_len) != 1) { + tls_set_errorx(ctx, "failed to load certificate"); + goto err; + } + } + + if (tls_keypair_to_pkey(ctx, keypair, &pkey) == -1) + goto err; + if (pkey != NULL) { + if (tls_keypair_setup_pkey(ctx, keypair, pkey) == -1) + goto err; + if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) { + tls_set_errorx(ctx, "failed to load private key"); + goto err; + } + EVP_PKEY_free(pkey); + pkey = NULL; + } + + if (!ctx->config->skip_private_key_check && + SSL_CTX_check_private_key(ssl_ctx) != 1) { + tls_set_errorx(ctx, "private/public key mismatch"); + goto err; + } + + return (0); + + err: + EVP_PKEY_free(pkey); + + return (-1); +} + +int +tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx) +{ + SSL_CTX_clear_mode(ssl_ctx, SSL_MODE_AUTO_RETRY); + + SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE); + SSL_CTX_set_mode(ssl_ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv3); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); + + SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_2); + SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TLSv1_3); + + if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_2) == 0) + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2); + if ((ctx->config->protocols & TLS_PROTOCOL_TLSv1_3) == 0) + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); + + if (ctx->config->alpn != NULL) { + if (SSL_CTX_set_alpn_protos(ssl_ctx, ctx->config->alpn, + ctx->config->alpn_len) != 0) { + tls_set_errorx(ctx, "failed to set alpn"); + goto err; + } + } + + if (ctx->config->ciphers != NULL) { + if (SSL_CTX_set_cipher_list(ssl_ctx, + ctx->config->ciphers) != 1) { + tls_set_errorx(ctx, "failed to set ciphers"); + goto err; + } + } + + if (ctx->config->verify_time == 0) { + X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(ssl_ctx), + X509_V_FLAG_NO_CHECK_TIME); + } + + /* Disable any form of session caching by default */ + SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_OFF); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET); + + return (0); + + err: + return (-1); +} + +static int +tls_ssl_cert_verify_cb(X509_STORE_CTX *x509_ctx, void *arg) +{ + struct tls *ctx = arg; + int x509_err; + + if (ctx->config->verify_cert == 0) + return (1); + + if ((X509_verify_cert(x509_ctx)) < 0) { + tls_set_errorx(ctx, "X509 verify cert failed"); + return (0); + } + + x509_err = X509_STORE_CTX_get_error(x509_ctx); + if (x509_err == X509_V_OK) + return (1); + + tls_set_errorx(ctx, "certificate verification failed: %s", + X509_verify_cert_error_string(x509_err)); + + return (0); +} + +int +tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify) +{ + size_t ca_len = ctx->config->ca_len; + char *ca_mem = ctx->config->ca_mem; + char *crl_mem = ctx->config->crl_mem; + size_t crl_len = ctx->config->crl_len; + char *ca_free = NULL; + STACK_OF(X509_INFO) *xis = NULL; + X509_STORE *store; + X509_INFO *xi; + BIO *bio = NULL; + int rv = -1; + int i; + + SSL_CTX_set_verify(ssl_ctx, verify, NULL); + SSL_CTX_set_cert_verify_callback(ssl_ctx, tls_ssl_cert_verify_cb, ctx); + + if (ctx->config->verify_depth >= 0) + SSL_CTX_set_verify_depth(ssl_ctx, ctx->config->verify_depth); + + if (ctx->config->verify_cert == 0) + goto done; + + /* If no CA has been specified, attempt to load the default. */ + if (ctx->config->ca_mem == NULL && ctx->config->ca_path == NULL) { + if (tls_config_load_file(&ctx->error, "CA", tls_default_ca_cert_file(), + &ca_mem, &ca_len) != 0) + goto err; + ca_free = ca_mem; + } + + if (ca_mem != NULL) { + if (ca_len > INT_MAX) { + tls_set_errorx(ctx, "ca too long"); + goto err; + } + if (SSL_CTX_load_verify_mem(ssl_ctx, ca_mem, ca_len) != 1) { + tls_set_errorx(ctx, "ssl verify memory setup failure"); + goto err; + } + } else if (SSL_CTX_load_verify_locations(ssl_ctx, NULL, + ctx->config->ca_path) != 1) { + tls_set_errorx(ctx, "ssl verify locations failure"); + goto err; + } + + if (crl_mem != NULL) { + if (crl_len > INT_MAX) { + tls_set_errorx(ctx, "crl too long"); + goto err; + } + if ((bio = BIO_new_mem_buf(crl_mem, crl_len)) == NULL) { + tls_set_errorx(ctx, "failed to create buffer"); + goto err; + } + if ((xis = PEM_X509_INFO_read_bio(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to parse crl"); + goto err; + } + store = SSL_CTX_get_cert_store(ssl_ctx); + for (i = 0; i < sk_X509_INFO_num(xis); i++) { + xi = sk_X509_INFO_value(xis, i); + if (xi->crl == NULL) + continue; + if (!X509_STORE_add_crl(store, xi->crl)) { + tls_set_error(ctx, "failed to add crl"); + goto err; + } + } + X509_STORE_set_flags(store, + X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); + } + + done: + rv = 0; + + err: + sk_X509_INFO_pop_free(xis, X509_INFO_free); + BIO_free(bio); + free(ca_free); + + return (rv); +} + +void +tls_free(struct tls *ctx) +{ + if (ctx == NULL) + return; + + tls_reset(ctx); + + free(ctx); +} + +void +tls_reset(struct tls *ctx) +{ + struct tls_sni_ctx *sni, *nsni; + + tls_config_free(ctx->config); + ctx->config = NULL; + + SSL_CTX_free(ctx->ssl_ctx); + SSL_free(ctx->ssl_conn); + X509_free(ctx->ssl_peer_cert); + + ctx->ssl_conn = NULL; + ctx->ssl_ctx = NULL; + ctx->ssl_peer_cert = NULL; + /* X509 objects in chain are freed with the SSL */ + ctx->ssl_peer_chain = NULL; + + ctx->socket = -1; + ctx->state = 0; + + free(ctx->servername); + ctx->servername = NULL; + + free(ctx->error.msg); + ctx->error.msg = NULL; + ctx->error.num = -1; + + tls_conninfo_free(ctx->conninfo); + ctx->conninfo = NULL; + + tls_ocsp_free(ctx->ocsp); + ctx->ocsp = NULL; + + for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) { + nsni = sni->next; + tls_sni_ctx_free(sni); + } + ctx->sni_ctx = NULL; + + ctx->read_cb = NULL; + ctx->write_cb = NULL; + ctx->cb_arg = NULL; +} + +int +tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix) +{ + const char *errstr = "unknown error"; + unsigned long err; + int ssl_err; + + ssl_err = SSL_get_error(ssl_conn, ssl_ret); + switch (ssl_err) { + case SSL_ERROR_NONE: + case SSL_ERROR_ZERO_RETURN: + return (0); + + case SSL_ERROR_WANT_READ: + return (TLS_WANT_POLLIN); + + case SSL_ERROR_WANT_WRITE: + return (TLS_WANT_POLLOUT); + + case SSL_ERROR_SYSCALL: + if ((err = ERR_peek_error()) != 0) { + errstr = ERR_error_string(err, NULL); + } else if (ssl_ret == 0) { + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) { + ctx->state |= TLS_EOF_NO_CLOSE_NOTIFY; + return (0); + } + errstr = "unexpected EOF"; + } else if (ssl_ret == -1) { + errstr = strerror(errno); + } + tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); + return (-1); + + case SSL_ERROR_SSL: + if ((err = ERR_peek_error()) != 0) { + errstr = ERR_error_string(err, NULL); + } + tls_set_ssl_errorx(ctx, "%s failed: %s", prefix, errstr); + return (-1); + + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + case SSL_ERROR_WANT_X509_LOOKUP: + default: + tls_set_ssl_errorx(ctx, "%s failed (%d)", prefix, ssl_err); + return (-1); + } +} + +int +tls_handshake(struct tls *ctx) +{ + int rv = -1; + + tls_error_clear(&ctx->error); + + if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) { + tls_set_errorx(ctx, "invalid operation for context"); + goto out; + } + + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0) { + tls_set_errorx(ctx, "handshake already completed"); + goto out; + } + + if ((ctx->flags & TLS_CLIENT) != 0) + rv = tls_handshake_client(ctx); + else if ((ctx->flags & TLS_SERVER_CONN) != 0) + rv = tls_handshake_server(ctx); + + if (rv == 0) { + ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); + ctx->ssl_peer_chain = SSL_get_peer_cert_chain(ctx->ssl_conn); + if (tls_conninfo_populate(ctx) == -1) + rv = -1; + if (ctx->ocsp == NULL) + ctx->ocsp = tls_ocsp_setup_from_peer(ctx); + } + out: + /* Prevent callers from performing incorrect error handling */ + errno = 0; + return (rv); +} + +ssize_t +tls_read(struct tls *ctx, void *buf, size_t buflen) +{ + ssize_t rv = -1; + int ssl_ret; + + tls_error_clear(&ctx->error); + + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) { + if ((rv = tls_handshake(ctx)) != 0) + goto out; + } + + if (buflen > INT_MAX) { + tls_set_errorx(ctx, "buflen too long"); + goto out; + } + + ERR_clear_error(); + if ((ssl_ret = SSL_read(ctx->ssl_conn, buf, buflen)) > 0) { + rv = (ssize_t)ssl_ret; + goto out; + } + rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "read"); + + out: + /* Prevent callers from performing incorrect error handling */ + errno = 0; + return (rv); +} + +ssize_t +tls_write(struct tls *ctx, const void *buf, size_t buflen) +{ + ssize_t rv = -1; + int ssl_ret; + + tls_error_clear(&ctx->error); + + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) { + if ((rv = tls_handshake(ctx)) != 0) + goto out; + } + + if (buflen > INT_MAX) { + tls_set_errorx(ctx, "buflen too long"); + goto out; + } + + ERR_clear_error(); + if ((ssl_ret = SSL_write(ctx->ssl_conn, buf, buflen)) > 0) { + rv = (ssize_t)ssl_ret; + goto out; + } + rv = (ssize_t)tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "write"); + + out: + /* Prevent callers from performing incorrect error handling */ + errno = 0; + return (rv); +} + +int +tls_close(struct tls *ctx) +{ + int ssl_ret; + int rv = 0; + + tls_error_clear(&ctx->error); + + if ((ctx->flags & (TLS_CLIENT | TLS_SERVER_CONN)) == 0) { + tls_set_errorx(ctx, "invalid operation for context"); + rv = -1; + goto out; + } + + if (ctx->state & TLS_SSL_NEEDS_SHUTDOWN) { + ERR_clear_error(); + ssl_ret = SSL_shutdown(ctx->ssl_conn); + if (ssl_ret < 0) { + rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, + "shutdown"); + if (rv == TLS_WANT_POLLIN || rv == TLS_WANT_POLLOUT) + goto out; + } + ctx->state &= ~TLS_SSL_NEEDS_SHUTDOWN; + } + + if (ctx->socket != -1) { + if (shutdown(ctx->socket, SHUT_RDWR) != 0) { + if (rv == 0 && + errno != ENOTCONN && errno != ECONNRESET) { + tls_set_error(ctx, "shutdown"); + rv = -1; + } + } + if (close(ctx->socket) != 0) { + if (rv == 0) { + tls_set_error(ctx, "close"); + rv = -1; + } + } + ctx->socket = -1; + } + + if ((ctx->state & TLS_EOF_NO_CLOSE_NOTIFY) != 0) { + tls_set_errorx(ctx, "EOF without close notify"); + rv = -1; + } + + out: + /* Prevent callers from performing incorrect error handling */ + errno = 0; + return (rv); +} diff --git a/tls/tls_bio_cb.c b/tls/tls_bio_cb.c new file mode 100644 index 0000000..8a1edfd --- /dev/null +++ b/tls/tls_bio_cb.c @@ -0,0 +1,171 @@ +/* $OpenBSD: tls_bio_cb.c,v 1.21 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2016 Tobias Pape + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include +#include "tls_internal.h" + +static int bio_cb_write(BIO *bio, const char *buf, int num); +static int bio_cb_read(BIO *bio, char *buf, int size); +static int bio_cb_puts(BIO *bio, const char *str); +static long bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr); + +static BIO_METHOD *bio_cb_method; + +static pthread_mutex_t bio_cb_method_lock = PTHREAD_MUTEX_INITIALIZER; + +static void +bio_cb_method_init(void) +{ + BIO_METHOD *bio_method; + + if (bio_cb_method != NULL) + return; + + bio_method = BIO_meth_new(BIO_TYPE_MEM, "libtls_callbacks"); + if (bio_method == NULL) + return; + + BIO_meth_set_write(bio_method, bio_cb_write); + BIO_meth_set_read(bio_method, bio_cb_read); + BIO_meth_set_puts(bio_method, bio_cb_puts); + BIO_meth_set_ctrl(bio_method, bio_cb_ctrl); + + bio_cb_method = bio_method; +} + +static BIO_METHOD * +bio_s_cb(void) +{ + if (bio_cb_method != NULL) + return (bio_cb_method); + + pthread_mutex_lock(&bio_cb_method_lock); + bio_cb_method_init(); + pthread_mutex_unlock(&bio_cb_method_lock); + + return (bio_cb_method); +} + +static int +bio_cb_puts(BIO *bio, const char *str) +{ + return (bio_cb_write(bio, str, strlen(str))); +} + +static long +bio_cb_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + long ret = 1; + + switch (cmd) { + case BIO_CTRL_GET_CLOSE: + ret = (long)BIO_get_shutdown(bio); + break; + case BIO_CTRL_SET_CLOSE: + BIO_set_shutdown(bio, (int)num); + break; + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: + break; + case BIO_CTRL_INFO: + case BIO_CTRL_GET: + case BIO_CTRL_SET: + default: + ret = BIO_ctrl(BIO_next(bio), cmd, num, ptr); + } + + return (ret); +} + +static int +bio_cb_write(BIO *bio, const char *buf, int num) +{ + struct tls *ctx = BIO_get_data(bio); + int rv; + + BIO_clear_retry_flags(bio); + rv = (ctx->write_cb)(ctx, buf, num, ctx->cb_arg); + if (rv == TLS_WANT_POLLIN) { + BIO_set_retry_read(bio); + rv = -1; + } else if (rv == TLS_WANT_POLLOUT) { + BIO_set_retry_write(bio); + rv = -1; + } + return (rv); +} + +static int +bio_cb_read(BIO *bio, char *buf, int size) +{ + struct tls *ctx = BIO_get_data(bio); + int rv; + + BIO_clear_retry_flags(bio); + rv = (ctx->read_cb)(ctx, buf, size, ctx->cb_arg); + if (rv == TLS_WANT_POLLIN) { + BIO_set_retry_read(bio); + rv = -1; + } else if (rv == TLS_WANT_POLLOUT) { + BIO_set_retry_write(bio); + rv = -1; + } + return (rv); +} + +int +tls_set_cbs(struct tls *ctx, tls_read_cb read_cb, tls_write_cb write_cb, + void *cb_arg) +{ + const BIO_METHOD *bio_cb; + BIO *bio; + int rv = -1; + + if (read_cb == NULL || write_cb == NULL) { + tls_set_errorx(ctx, "no callbacks provided"); + goto err; + } + + ctx->read_cb = read_cb; + ctx->write_cb = write_cb; + ctx->cb_arg = cb_arg; + + if ((bio_cb = bio_s_cb()) == NULL) { + tls_set_errorx(ctx, "failed to create callback method"); + goto err; + } + if ((bio = BIO_new(bio_cb)) == NULL) { + tls_set_errorx(ctx, "failed to create callback i/o"); + goto err; + } + BIO_set_data(bio, ctx); + BIO_set_init(bio, 1); + + SSL_set_bio(ctx->ssl_conn, bio, bio); + + rv = 0; + + err: + return (rv); +} diff --git a/tls/tls_client.c b/tls/tls_client.c new file mode 100644 index 0000000..deb24eb --- /dev/null +++ b/tls/tls_client.c @@ -0,0 +1,485 @@ +/* $OpenBSD: tls_client.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "tls_internal.h" + +struct tls * +tls_client(void) +{ + struct tls *ctx; + + if (tls_init() == -1) + return (NULL); + + if ((ctx = tls_new()) == NULL) + return (NULL); + + ctx->flags |= TLS_CLIENT; + + return (ctx); +} + +int +tls_connect(struct tls *ctx, const char *host, const char *port) +{ + return tls_connect_servername(ctx, host, port, NULL); +} + +int +tls_connect_servername(struct tls *ctx, const char *host, const char *port, + const char *servername) +{ + struct addrinfo hints, *res, *res0; + const char *h = NULL, *p = NULL; + char *hs = NULL, *ps = NULL; + int rv = -1, s = -1, ret; + + if ((ctx->flags & TLS_CLIENT) == 0) { + tls_set_errorx(ctx, "not a client context"); + goto err; + } + + if (host == NULL) { + tls_set_errorx(ctx, "host not specified"); + goto err; + } + + /* If port is NULL, try to extract a port from the specified host. */ + if (port == NULL) { + ret = tls_host_port(host, &hs, &ps); + if (ret == -1) { + tls_set_errorx(ctx, "memory allocation failure"); + goto err; + } + if (ret != 0) { + tls_set_errorx(ctx, "no port provided"); + goto err; + } + } + + h = (hs != NULL) ? hs : host; + p = (ps != NULL) ? ps : port; + + /* + * First check if the host is specified as a numeric IP address, + * either IPv4 or IPv6, before trying to resolve the host. + * The AI_ADDRCONFIG resolver option will not return IPv4 or IPv6 + * records if it is not configured on an interface; not considering + * loopback addresses. Checking the numeric addresses first makes + * sure that connection attempts to numeric addresses and especially + * 127.0.0.1 or ::1 loopback addresses are always possible. + */ + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + + /* try as an IPv4 literal */ + hints.ai_family = AF_INET; + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(h, p, &hints, &res0) != 0) { + /* try again as an IPv6 literal */ + hints.ai_family = AF_INET6; + if (getaddrinfo(h, p, &hints, &res0) != 0) { + /* last try, with name resolution and save the error */ + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG; + if ((s = getaddrinfo(h, p, &hints, &res0)) != 0) { + tls_set_error(ctx, "%s", gai_strerror(s)); + goto err; + } + } + } + + /* It was resolved somehow; now try connecting to what we got */ + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) { + tls_set_error(ctx, "socket"); + continue; + } + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { + tls_set_error(ctx, "connect"); + close(s); + s = -1; + continue; + } + + break; /* Connected. */ + } + freeaddrinfo(res0); + + if (s == -1) + goto err; + + if (servername == NULL) + servername = h; + + if (tls_connect_socket(ctx, s, servername) != 0) { + close(s); + goto err; + } + + ctx->socket = s; + + rv = 0; + + err: + free(hs); + free(ps); + + return (rv); +} + +static int +tls_client_read_session(struct tls *ctx) +{ + int sfd = ctx->config->session_fd; + uint8_t *session = NULL; + size_t session_len = 0; + SSL_SESSION *ss = NULL; + BIO *bio = NULL; + struct stat sb; + ssize_t n; + int rv = -1; + + if (fstat(sfd, &sb) == -1) { + tls_set_error(ctx, "failed to stat session file"); + goto err; + } + if (sb.st_size < 0 || sb.st_size > INT_MAX) { + tls_set_errorx(ctx, "invalid session file size"); + goto err; + } + session_len = (size_t)sb.st_size; + + /* A zero size file means that we do not yet have a valid session. */ + if (session_len == 0) + goto done; + + if ((session = malloc(session_len)) == NULL) + goto err; + + n = pread(sfd, session, session_len, 0); + if (n < 0 || (size_t)n != session_len) { + tls_set_error(ctx, "failed to read session file"); + goto err; + } + if ((bio = BIO_new_mem_buf(session, session_len)) == NULL) + goto err; + if ((ss = PEM_read_bio_SSL_SESSION(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_set_errorx(ctx, "failed to parse session"); + goto err; + } + + if (SSL_set_session(ctx->ssl_conn, ss) != 1) { + tls_set_errorx(ctx, "failed to set session"); + goto err; + } + + done: + rv = 0; + + err: + freezero(session, session_len); + SSL_SESSION_free(ss); + BIO_free(bio); + + return rv; +} + +static int +tls_client_write_session(struct tls *ctx) +{ + int sfd = ctx->config->session_fd; + SSL_SESSION *ss = NULL; + BIO *bio = NULL; + long data_len; + char *data; + off_t offset; + size_t len; + ssize_t n; + int rv = -1; + + if ((ss = SSL_get1_session(ctx->ssl_conn)) == NULL) { + if (ftruncate(sfd, 0) == -1) { + tls_set_error(ctx, "failed to truncate session file"); + goto err; + } + goto done; + } + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto err; + if (PEM_write_bio_SSL_SESSION(bio, ss) == 0) + goto err; + if ((data_len = BIO_get_mem_data(bio, &data)) <= 0) + goto err; + + len = (size_t)data_len; + offset = 0; + + if (ftruncate(sfd, len) == -1) { + tls_set_error(ctx, "failed to truncate session file"); + goto err; + } + while (len > 0) { + if ((n = pwrite(sfd, data + offset, len, offset)) == -1) { + tls_set_error(ctx, "failed to write session file"); + goto err; + } + offset += n; + len -= n; + } + + done: + rv = 0; + + err: + SSL_SESSION_free(ss); + BIO_free_all(bio); + + return (rv); +} + +static int +tls_connect_common(struct tls *ctx, const char *servername) +{ + union tls_addr addrbuf; + size_t servername_len; + int rv = -1; + + if ((ctx->flags & TLS_CLIENT) == 0) { + tls_set_errorx(ctx, "not a client context"); + goto err; + } + + if (servername != NULL) { + if ((ctx->servername = strdup(servername)) == NULL) { + tls_set_errorx(ctx, "out of memory"); + goto err; + } + + /* + * If there's a trailing dot, remove it. While an FQDN includes + * the terminating dot representing the zero-length label of + * the root (RFC 8499, section 2), the SNI explicitly does not + * include it (RFC 6066, section 3). + */ + servername_len = strlen(ctx->servername); + if (servername_len > 0 && + ctx->servername[servername_len - 1] == '.') + ctx->servername[servername_len - 1] = '\0'; + } + + if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) { + tls_set_errorx(ctx, "ssl context failure"); + goto err; + } + + if (tls_configure_ssl(ctx, ctx->ssl_ctx) != 0) + goto err; + + if (tls_configure_ssl_keypair(ctx, ctx->ssl_ctx, + ctx->config->keypair, 0) != 0) + goto err; + + if (ctx->config->verify_name) { + if (ctx->servername == NULL) { + tls_set_errorx(ctx, "server name not specified"); + goto err; + } + } + + if (tls_configure_ssl_verify(ctx, ctx->ssl_ctx, SSL_VERIFY_PEER) == -1) + goto err; + + if (ctx->config->ecdhecurves != NULL) { + if (SSL_CTX_set1_groups(ctx->ssl_ctx, ctx->config->ecdhecurves, + ctx->config->ecdhecurves_len) != 1) { + tls_set_errorx(ctx, "failed to set ecdhe curves"); + goto err; + } + } + + if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) { + tls_set_errorx(ctx, "ssl OCSP verification setup failure"); + goto err; + } + + if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { + tls_set_errorx(ctx, "ssl connection failure"); + goto err; + } + + if (SSL_set_app_data(ctx->ssl_conn, ctx) != 1) { + tls_set_errorx(ctx, "ssl application data failure"); + goto err; + } + + if (ctx->config->session_fd != -1) { + SSL_clear_options(ctx->ssl_conn, SSL_OP_NO_TICKET); + if (tls_client_read_session(ctx) == -1) + goto err; + } + + if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { + tls_set_errorx(ctx, "ssl OCSP extension setup failure"); + goto err; + } + + /* + * RFC 6066 (SNI): Literal IPv4 and IPv6 addresses are not + * permitted in "HostName". + */ + if (ctx->servername != NULL && + inet_pton(AF_INET, ctx->servername, &addrbuf) != 1 && + inet_pton(AF_INET6, ctx->servername, &addrbuf) != 1) { + if (SSL_set_tlsext_host_name(ctx->ssl_conn, + ctx->servername) == 0) { + tls_set_errorx(ctx, "server name indication failure"); + goto err; + } + } + + ctx->state |= TLS_CONNECTED; + rv = 0; + + err: + return (rv); +} + +int +tls_connect_socket(struct tls *ctx, int s, const char *servername) +{ + return tls_connect_fds(ctx, s, s, servername); +} + +int +tls_connect_fds(struct tls *ctx, int fd_read, int fd_write, + const char *servername) +{ + int rv = -1; + + if (fd_read < 0 || fd_write < 0) { + tls_set_errorx(ctx, "invalid file descriptors"); + goto err; + } + + if (tls_connect_common(ctx, servername) != 0) + goto err; + + if (SSL_set_rfd(ctx->ssl_conn, fd_read) != 1 || + SSL_set_wfd(ctx->ssl_conn, fd_write) != 1) { + tls_set_errorx(ctx, "ssl file descriptor failure"); + goto err; + } + + rv = 0; + err: + return (rv); +} + +int +tls_connect_cbs(struct tls *ctx, tls_read_cb read_cb, + tls_write_cb write_cb, void *cb_arg, const char *servername) +{ + int rv = -1; + + if (tls_connect_common(ctx, servername) != 0) + goto err; + + if (tls_set_cbs(ctx, read_cb, write_cb, cb_arg) != 0) + goto err; + + rv = 0; + + err: + return (rv); +} + +int +tls_handshake_client(struct tls *ctx) +{ + X509 *cert = NULL; + int match, ssl_ret; + int rv = -1; + + if ((ctx->flags & TLS_CLIENT) == 0) { + tls_set_errorx(ctx, "not a client context"); + goto err; + } + + if ((ctx->state & TLS_CONNECTED) == 0) { + tls_set_errorx(ctx, "context not connected"); + goto err; + } + + ctx->state |= TLS_SSL_NEEDS_SHUTDOWN; + + ERR_clear_error(); + if ((ssl_ret = SSL_connect(ctx->ssl_conn)) != 1) { + rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); + goto err; + } + + if (ctx->config->verify_name) { + cert = SSL_get_peer_certificate(ctx->ssl_conn); + if (cert == NULL) { + tls_set_errorx(ctx, "no server certificate"); + goto err; + } + if (tls_check_name(ctx, cert, ctx->servername, &match) == -1) + goto err; + if (!match) { + tls_set_errorx(ctx, "name `%s' not present in" + " server certificate", ctx->servername); + goto err; + } + } + + ctx->state |= TLS_HANDSHAKE_COMPLETE; + + if (ctx->config->session_fd != -1) { + if (tls_client_write_session(ctx) == -1) + goto err; + } + + rv = 0; + + err: + X509_free(cert); + + return (rv); +} diff --git a/tls/tls_config.c b/tls/tls_config.c new file mode 100644 index 0000000..5eb5b69 --- /dev/null +++ b/tls/tls_config.c @@ -0,0 +1,930 @@ +/* $OpenBSD: tls_config.c,v 1.67 2023/07/02 06:37:27 beck Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tls_internal.h" + +static const char default_ca_file[] = TLS_DEFAULT_CA_FILE; + +const char * +tls_default_ca_cert_file(void) +{ + return default_ca_file; +} + +int +tls_config_load_file(struct tls_error *error, const char *filetype, + const char *filename, char **buf, size_t *len) +{ + struct stat st; + int fd = -1; + ssize_t n; + + free(*buf); + *buf = NULL; + *len = 0; + + if ((fd = open(filename, O_RDONLY)) == -1) { + tls_error_set(error, "failed to open %s file '%s'", + filetype, filename); + goto err; + } + if (fstat(fd, &st) != 0) { + tls_error_set(error, "failed to stat %s file '%s'", + filetype, filename); + goto err; + } + if (st.st_size < 0) + goto err; + *len = (size_t)st.st_size; + if ((*buf = malloc(*len)) == NULL) { + tls_error_set(error, "failed to allocate buffer for " + "%s file", filetype); + goto err; + } + n = read(fd, *buf, *len); + if (n < 0 || (size_t)n != *len) { + tls_error_set(error, "failed to read %s file '%s'", + filetype, filename); + goto err; + } + close(fd); + return 0; + + err: + if (fd != -1) + close(fd); + freezero(*buf, *len); + *buf = NULL; + *len = 0; + + return -1; +} + +struct tls_config * +tls_config_new_internal(void) +{ + struct tls_config *config; + unsigned char sid[TLS_MAX_SESSION_ID_LENGTH]; + + if ((config = calloc(1, sizeof(*config))) == NULL) + return (NULL); + + if (pthread_mutex_init(&config->mutex, NULL) != 0) + goto err; + + config->refcount = 1; + config->session_fd = -1; + + if ((config->keypair = tls_keypair_new()) == NULL) + goto err; + + /* + * Default configuration. + */ + if (tls_config_set_dheparams(config, "none") != 0) + goto err; + if (tls_config_set_ecdhecurves(config, "default") != 0) + goto err; + if (tls_config_set_ciphers(config, "secure") != 0) + goto err; + + if (tls_config_set_protocols(config, TLS_PROTOCOLS_DEFAULT) != 0) + goto err; + if (tls_config_set_verify_depth(config, 6) != 0) + goto err; + + /* + * Set session ID context to a random value. For the simple case + * of a single process server this is good enough. For multiprocess + * servers the session ID needs to be set by the caller. + */ + arc4random_buf(sid, sizeof(sid)); + if (tls_config_set_session_id(config, sid, sizeof(sid)) != 0) + goto err; + config->ticket_keyrev = arc4random(); + config->ticket_autorekey = 1; + + tls_config_prefer_ciphers_server(config); + + tls_config_verify(config); + + return (config); + + err: + tls_config_free(config); + return (NULL); +} + +struct tls_config * +tls_config_new(void) +{ + if (tls_init() == -1) + return (NULL); + + return tls_config_new_internal(); +} + +void +tls_config_free(struct tls_config *config) +{ + struct tls_keypair *kp, *nkp; + int refcount; + + if (config == NULL) + return; + + pthread_mutex_lock(&config->mutex); + refcount = --config->refcount; + pthread_mutex_unlock(&config->mutex); + + if (refcount > 0) + return; + + for (kp = config->keypair; kp != NULL; kp = nkp) { + nkp = kp->next; + tls_keypair_free(kp); + } + + free(config->error.msg); + + free(config->alpn); + free((char *)config->ca_mem); + free((char *)config->ca_path); + free((char *)config->ciphers); + free((char *)config->crl_mem); + free(config->ecdhecurves); + + pthread_mutex_destroy(&config->mutex); + + free(config); +} + +static void +tls_config_keypair_add(struct tls_config *config, struct tls_keypair *keypair) +{ + struct tls_keypair *kp; + + kp = config->keypair; + while (kp->next != NULL) + kp = kp->next; + + kp->next = keypair; +} + +const char * +tls_config_error(struct tls_config *config) +{ + return config->error.msg; +} + +void +tls_config_clear_keys(struct tls_config *config) +{ + struct tls_keypair *kp; + + for (kp = config->keypair; kp != NULL; kp = kp->next) + tls_keypair_clear_key(kp); +} + +int +tls_config_parse_protocols(uint32_t *protocols, const char *protostr) +{ + uint32_t proto, protos = 0; + char *s, *p, *q; + int negate; + + if (protostr == NULL) { + *protocols = TLS_PROTOCOLS_DEFAULT; + return (0); + } + + if ((s = strdup(protostr)) == NULL) + return (-1); + + q = s; + while ((p = strsep(&q, ",:")) != NULL) { + while (*p == ' ' || *p == '\t') + p++; + + negate = 0; + if (*p == '!') { + negate = 1; + p++; + } + + if (negate && protos == 0) + protos = TLS_PROTOCOLS_ALL; + + proto = 0; + if (strcasecmp(p, "all") == 0 || + strcasecmp(p, "legacy") == 0) + proto = TLS_PROTOCOLS_ALL; + else if (strcasecmp(p, "default") == 0 || + strcasecmp(p, "secure") == 0) + proto = TLS_PROTOCOLS_DEFAULT; + if (strcasecmp(p, "tlsv1") == 0) + proto = TLS_PROTOCOL_TLSv1; + else if (strcasecmp(p, "tlsv1.0") == 0) + proto = TLS_PROTOCOL_TLSv1_2; + else if (strcasecmp(p, "tlsv1.1") == 0) + proto = TLS_PROTOCOL_TLSv1_2; + else if (strcasecmp(p, "tlsv1.2") == 0) + proto = TLS_PROTOCOL_TLSv1_2; + else if (strcasecmp(p, "tlsv1.3") == 0) + proto = TLS_PROTOCOL_TLSv1_3; + + if (proto == 0) { + free(s); + return (-1); + } + + if (negate) + protos &= ~proto; + else + protos |= proto; + } + + *protocols = protos; + + free(s); + + return (0); +} + +static int +tls_config_parse_alpn(struct tls_config *config, const char *alpn, + char **alpn_data, size_t *alpn_len) +{ + size_t buf_len, i, len; + char *buf = NULL; + char *s = NULL; + char *p, *q; + + free(*alpn_data); + *alpn_data = NULL; + *alpn_len = 0; + + if ((buf_len = strlen(alpn) + 1) > 65535) { + tls_config_set_errorx(config, "alpn too large"); + goto err; + } + + if ((buf = malloc(buf_len)) == NULL) { + tls_config_set_errorx(config, "out of memory"); + goto err; + } + + if ((s = strdup(alpn)) == NULL) { + tls_config_set_errorx(config, "out of memory"); + goto err; + } + + i = 0; + q = s; + while ((p = strsep(&q, ",")) != NULL) { + if ((len = strlen(p)) == 0) { + tls_config_set_errorx(config, + "alpn protocol with zero length"); + goto err; + } + if (len > 255) { + tls_config_set_errorx(config, + "alpn protocol too long"); + goto err; + } + buf[i++] = len & 0xff; + memcpy(&buf[i], p, len); + i += len; + } + + free(s); + + *alpn_data = buf; + *alpn_len = buf_len; + + return (0); + + err: + free(buf); + free(s); + + return (-1); +} + +int +tls_config_set_alpn(struct tls_config *config, const char *alpn) +{ + return tls_config_parse_alpn(config, alpn, &config->alpn, + &config->alpn_len); +} + +static int +tls_config_add_keypair_file_internal(struct tls_config *config, + const char *cert_file, const char *key_file, const char *ocsp_file) +{ + struct tls_keypair *keypair; + + if ((keypair = tls_keypair_new()) == NULL) + return (-1); + if (tls_keypair_set_cert_file(keypair, &config->error, cert_file) != 0) + goto err; + if (key_file != NULL && + tls_keypair_set_key_file(keypair, &config->error, key_file) != 0) + goto err; + if (ocsp_file != NULL && + tls_keypair_set_ocsp_staple_file(keypair, &config->error, + ocsp_file) != 0) + goto err; + + tls_config_keypair_add(config, keypair); + + return (0); + + err: + tls_keypair_free(keypair); + return (-1); +} + +static int +tls_config_add_keypair_mem_internal(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len, + const uint8_t *staple, size_t staple_len) +{ + struct tls_keypair *keypair; + + if ((keypair = tls_keypair_new()) == NULL) + return (-1); + if (tls_keypair_set_cert_mem(keypair, &config->error, cert, cert_len) != 0) + goto err; + if (key != NULL && + tls_keypair_set_key_mem(keypair, &config->error, key, key_len) != 0) + goto err; + if (staple != NULL && + tls_keypair_set_ocsp_staple_mem(keypair, &config->error, staple, + staple_len) != 0) + goto err; + + tls_config_keypair_add(config, keypair); + + return (0); + + err: + tls_keypair_free(keypair); + return (-1); +} + +int +tls_config_add_keypair_mem(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len) +{ + return tls_config_add_keypair_mem_internal(config, cert, cert_len, key, + key_len, NULL, 0); +} + +int +tls_config_add_keypair_file(struct tls_config *config, + const char *cert_file, const char *key_file) +{ + return tls_config_add_keypair_file_internal(config, cert_file, + key_file, NULL); +} + +int +tls_config_add_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len, const uint8_t *staple, + size_t staple_len) +{ + return tls_config_add_keypair_mem_internal(config, cert, cert_len, key, + key_len, staple, staple_len); +} + +int +tls_config_add_keypair_ocsp_file(struct tls_config *config, + const char *cert_file, const char *key_file, const char *ocsp_file) +{ + return tls_config_add_keypair_file_internal(config, cert_file, + key_file, ocsp_file); +} + +int +tls_config_set_ca_file(struct tls_config *config, const char *ca_file) +{ + return tls_config_load_file(&config->error, "CA", ca_file, + &config->ca_mem, &config->ca_len); +} + +int +tls_config_set_ca_path(struct tls_config *config, const char *ca_path) +{ + return tls_set_string(&config->ca_path, ca_path); +} + +int +tls_config_set_ca_mem(struct tls_config *config, const uint8_t *ca, size_t len) +{ + return tls_set_mem(&config->ca_mem, &config->ca_len, ca, len); +} + +int +tls_config_set_cert_file(struct tls_config *config, const char *cert_file) +{ + return tls_keypair_set_cert_file(config->keypair, &config->error, + cert_file); +} + +int +tls_config_set_cert_mem(struct tls_config *config, const uint8_t *cert, + size_t len) +{ + return tls_keypair_set_cert_mem(config->keypair, &config->error, + cert, len); +} + +int +tls_config_set_ciphers(struct tls_config *config, const char *ciphers) +{ + SSL_CTX *ssl_ctx = NULL; + + if (ciphers == NULL || + strcasecmp(ciphers, "default") == 0 || + strcasecmp(ciphers, "secure") == 0) + ciphers = TLS_CIPHERS_DEFAULT; + else if (strcasecmp(ciphers, "compat") == 0) + ciphers = TLS_CIPHERS_COMPAT; + else if (strcasecmp(ciphers, "legacy") == 0) + ciphers = TLS_CIPHERS_LEGACY; + else if (strcasecmp(ciphers, "all") == 0 || + strcasecmp(ciphers, "insecure") == 0) + ciphers = TLS_CIPHERS_ALL; + + if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) { + tls_config_set_errorx(config, "out of memory"); + goto err; + } + if (SSL_CTX_set_cipher_list(ssl_ctx, ciphers) != 1) { + tls_config_set_errorx(config, "no ciphers for '%s'", ciphers); + goto err; + } + + SSL_CTX_free(ssl_ctx); + return tls_set_string(&config->ciphers, ciphers); + + err: + SSL_CTX_free(ssl_ctx); + return -1; +} + +int +tls_config_set_crl_file(struct tls_config *config, const char *crl_file) +{ + return tls_config_load_file(&config->error, "CRL", crl_file, + &config->crl_mem, &config->crl_len); +} + +int +tls_config_set_crl_mem(struct tls_config *config, const uint8_t *crl, + size_t len) +{ + return tls_set_mem(&config->crl_mem, &config->crl_len, crl, len); +} + +int +tls_config_set_dheparams(struct tls_config *config, const char *params) +{ + int keylen; + + if (params == NULL || strcasecmp(params, "none") == 0) + keylen = 0; + else if (strcasecmp(params, "auto") == 0) + keylen = -1; + else if (strcasecmp(params, "legacy") == 0) + keylen = 1024; + else { + tls_config_set_errorx(config, "invalid dhe param '%s'", params); + return (-1); + } + + config->dheparams = keylen; + + return (0); +} + +int +tls_config_set_ecdhecurve(struct tls_config *config, const char *curve) +{ + if (curve == NULL || + strcasecmp(curve, "none") == 0 || + strcasecmp(curve, "auto") == 0) { + curve = TLS_ECDHE_CURVES; + } else if (strchr(curve, ',') != NULL || strchr(curve, ':') != NULL) { + tls_config_set_errorx(config, "invalid ecdhe curve '%s'", + curve); + return (-1); + } + + return tls_config_set_ecdhecurves(config, curve); +} + +int +tls_config_set_ecdhecurves(struct tls_config *config, const char *curves) +{ + int *curves_list = NULL, *curves_new; + size_t curves_num = 0; + char *cs = NULL; + char *p, *q; + int rv = -1; + int nid; + + free(config->ecdhecurves); + config->ecdhecurves = NULL; + config->ecdhecurves_len = 0; + + if (curves == NULL || strcasecmp(curves, "default") == 0) + curves = TLS_ECDHE_CURVES; + + if ((cs = strdup(curves)) == NULL) { + tls_config_set_errorx(config, "out of memory"); + goto err; + } + + q = cs; + while ((p = strsep(&q, ",:")) != NULL) { + while (*p == ' ' || *p == '\t') + p++; + + nid = OBJ_sn2nid(p); + if (nid == NID_undef) + nid = OBJ_ln2nid(p); + if (nid == NID_undef) + nid = EC_curve_nist2nid(p); + if (nid == NID_undef) { + tls_config_set_errorx(config, + "invalid ecdhe curve '%s'", p); + goto err; + } + + if ((curves_new = reallocarray(curves_list, curves_num + 1, + sizeof(int))) == NULL) { + tls_config_set_errorx(config, "out of memory"); + goto err; + } + curves_list = curves_new; + curves_list[curves_num] = nid; + curves_num++; + } + + config->ecdhecurves = curves_list; + config->ecdhecurves_len = curves_num; + curves_list = NULL; + + rv = 0; + + err: + free(cs); + free(curves_list); + + return (rv); +} + +int +tls_config_set_key_file(struct tls_config *config, const char *key_file) +{ + return tls_keypair_set_key_file(config->keypair, &config->error, + key_file); +} + +int +tls_config_set_key_mem(struct tls_config *config, const uint8_t *key, + size_t len) +{ + return tls_keypair_set_key_mem(config->keypair, &config->error, + key, len); +} + +static int +tls_config_set_keypair_file_internal(struct tls_config *config, + const char *cert_file, const char *key_file, const char *ocsp_file) +{ + if (tls_config_set_cert_file(config, cert_file) != 0) + return (-1); + if (tls_config_set_key_file(config, key_file) != 0) + return (-1); + if (ocsp_file != NULL && + tls_config_set_ocsp_staple_file(config, ocsp_file) != 0) + return (-1); + + return (0); +} + +static int +tls_config_set_keypair_mem_internal(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len, + const uint8_t *staple, size_t staple_len) +{ + if (tls_config_set_cert_mem(config, cert, cert_len) != 0) + return (-1); + if (tls_config_set_key_mem(config, key, key_len) != 0) + return (-1); + if ((staple != NULL) && + (tls_config_set_ocsp_staple_mem(config, staple, staple_len) != 0)) + return (-1); + + return (0); +} + +int +tls_config_set_keypair_file(struct tls_config *config, + const char *cert_file, const char *key_file) +{ + return tls_config_set_keypair_file_internal(config, cert_file, key_file, + NULL); +} + +int +tls_config_set_keypair_mem(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len) +{ + return tls_config_set_keypair_mem_internal(config, cert, cert_len, + key, key_len, NULL, 0); +} + +int +tls_config_set_keypair_ocsp_file(struct tls_config *config, + const char *cert_file, const char *key_file, const char *ocsp_file) +{ + return tls_config_set_keypair_file_internal(config, cert_file, key_file, + ocsp_file); +} + +int +tls_config_set_keypair_ocsp_mem(struct tls_config *config, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len, + const uint8_t *staple, size_t staple_len) +{ + return tls_config_set_keypair_mem_internal(config, cert, cert_len, + key, key_len, staple, staple_len); +} + + +int +tls_config_set_protocols(struct tls_config *config, uint32_t protocols) +{ + config->protocols = protocols; + + return (0); +} + +int +tls_config_set_session_fd(struct tls_config *config, int session_fd) +{ + struct stat sb; + mode_t mugo; + + if (session_fd == -1) { + config->session_fd = session_fd; + return (0); + } + + if (fstat(session_fd, &sb) == -1) { + tls_config_set_error(config, "failed to stat session file"); + return (-1); + } + if (!S_ISREG(sb.st_mode)) { + tls_config_set_errorx(config, + "session file is not a regular file"); + return (-1); + } + + if (sb.st_uid != getuid()) { + tls_config_set_errorx(config, "session file has incorrect " + "owner (uid %u != %u)", sb.st_uid, getuid()); + return (-1); + } + mugo = sb.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO); + if (mugo != (S_IRUSR|S_IWUSR)) { + tls_config_set_errorx(config, "session file has incorrect " + "permissions (%o != 600)", mugo); + return (-1); + } + + config->session_fd = session_fd; + + return (0); +} + +int +tls_config_set_sign_cb(struct tls_config *config, tls_sign_cb cb, void *cb_arg) +{ + config->use_fake_private_key = 1; + config->skip_private_key_check = 1; + config->sign_cb = cb; + config->sign_cb_arg = cb_arg; + + return (0); +} + +int +tls_config_set_verify_depth(struct tls_config *config, int verify_depth) +{ + config->verify_depth = verify_depth; + + return (0); +} + +void +tls_config_prefer_ciphers_client(struct tls_config *config) +{ + config->ciphers_server = 0; +} + +void +tls_config_prefer_ciphers_server(struct tls_config *config) +{ + config->ciphers_server = 1; +} + +void +tls_config_insecure_noverifycert(struct tls_config *config) +{ + config->verify_cert = 0; +} + +void +tls_config_insecure_noverifyname(struct tls_config *config) +{ + config->verify_name = 0; +} + +void +tls_config_insecure_noverifytime(struct tls_config *config) +{ + config->verify_time = 0; +} + +void +tls_config_verify(struct tls_config *config) +{ + config->verify_cert = 1; + config->verify_name = 1; + config->verify_time = 1; +} + +void +tls_config_ocsp_require_stapling(struct tls_config *config) +{ + config->ocsp_require_stapling = 1; +} + +void +tls_config_verify_client(struct tls_config *config) +{ + config->verify_client = 1; +} + +void +tls_config_verify_client_optional(struct tls_config *config) +{ + config->verify_client = 2; +} + +void +tls_config_skip_private_key_check(struct tls_config *config) +{ + config->skip_private_key_check = 1; +} + +void +tls_config_use_fake_private_key(struct tls_config *config) +{ + config->use_fake_private_key = 1; + config->skip_private_key_check = 1; +} + +int +tls_config_set_ocsp_staple_file(struct tls_config *config, const char *staple_file) +{ + return tls_keypair_set_ocsp_staple_file(config->keypair, &config->error, + staple_file); +} + +int +tls_config_set_ocsp_staple_mem(struct tls_config *config, const uint8_t *staple, + size_t len) +{ + return tls_keypair_set_ocsp_staple_mem(config->keypair, &config->error, + staple, len); +} + +int +tls_config_set_session_id(struct tls_config *config, + const unsigned char *session_id, size_t len) +{ + if (len > TLS_MAX_SESSION_ID_LENGTH) { + tls_config_set_errorx(config, "session ID too large"); + return (-1); + } + memset(config->session_id, 0, sizeof(config->session_id)); + memcpy(config->session_id, session_id, len); + return (0); +} + +int +tls_config_set_session_lifetime(struct tls_config *config, int lifetime) +{ + if (lifetime > TLS_MAX_SESSION_TIMEOUT) { + tls_config_set_errorx(config, "session lifetime too large"); + return (-1); + } + if (lifetime != 0 && lifetime < TLS_MIN_SESSION_TIMEOUT) { + tls_config_set_errorx(config, "session lifetime too small"); + return (-1); + } + + config->session_lifetime = lifetime; + return (0); +} + +int +tls_config_add_ticket_key(struct tls_config *config, uint32_t keyrev, + unsigned char *key, size_t keylen) +{ + struct tls_ticket_key newkey; + int i; + + if (TLS_TICKET_KEY_SIZE != keylen || + sizeof(newkey.aes_key) + sizeof(newkey.hmac_key) > keylen) { + tls_config_set_errorx(config, + "wrong amount of ticket key data"); + return (-1); + } + + keyrev = htonl(keyrev); + memset(&newkey, 0, sizeof(newkey)); + memcpy(newkey.key_name, &keyrev, sizeof(keyrev)); + memcpy(newkey.aes_key, key, sizeof(newkey.aes_key)); + memcpy(newkey.hmac_key, key + sizeof(newkey.aes_key), + sizeof(newkey.hmac_key)); + newkey.time = time(NULL); + + for (i = 0; i < TLS_NUM_TICKETS; i++) { + struct tls_ticket_key *tk = &config->ticket_keys[i]; + if (memcmp(newkey.key_name, tk->key_name, + sizeof(tk->key_name)) != 0) + continue; + + /* allow re-entry of most recent key */ + if (i == 0 && memcmp(newkey.aes_key, tk->aes_key, + sizeof(tk->aes_key)) == 0 && memcmp(newkey.hmac_key, + tk->hmac_key, sizeof(tk->hmac_key)) == 0) + return (0); + tls_config_set_errorx(config, "ticket key already present"); + return (-1); + } + + memmove(&config->ticket_keys[1], &config->ticket_keys[0], + sizeof(config->ticket_keys) - sizeof(config->ticket_keys[0])); + config->ticket_keys[0] = newkey; + + config->ticket_autorekey = 0; + + return (0); +} + +int +tls_config_ticket_autorekey(struct tls_config *config) +{ + unsigned char key[TLS_TICKET_KEY_SIZE]; + int rv; + + arc4random_buf(key, sizeof(key)); + rv = tls_config_add_ticket_key(config, config->ticket_keyrev++, key, + sizeof(key)); + config->ticket_autorekey = 1; + return (rv); +} diff --git a/tls/tls_conninfo.c b/tls/tls_conninfo.c new file mode 100644 index 0000000..b2aadab --- /dev/null +++ b/tls/tls_conninfo.c @@ -0,0 +1,344 @@ +/* $OpenBSD: tls_conninfo.c,v 1.23 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * Copyright (c) 2015 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include + +#include +#include "tls_internal.h" + +int ASN1_time_tm_clamp_notafter(struct tm *tm); + +int +tls_hex_string(const unsigned char *in, size_t inlen, char **out, + size_t *outlen) +{ + static const char hex[] = "0123456789abcdef"; + size_t i, len; + char *p; + + if (outlen != NULL) + *outlen = 0; + + if (inlen >= SIZE_MAX) + return (-1); + if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) + return (-1); + + p = *out; + len = 0; + for (i = 0; i < inlen; i++) { + p[len++] = hex[(in[i] >> 4) & 0x0f]; + p[len++] = hex[in[i] & 0x0f]; + } + p[len++] = 0; + + if (outlen != NULL) + *outlen = len; + + return (0); +} + +static int +tls_get_peer_cert_hash(struct tls *ctx, char **hash) +{ + *hash = NULL; + if (ctx->ssl_peer_cert == NULL) + return (0); + + if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { + tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory"); + *hash = NULL; + return -1; + } + return 0; +} + +static int +tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) +{ + X509_NAME *name = NULL; + + *issuer = NULL; + if (ctx->ssl_peer_cert == NULL) + return (-1); + if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) + return (-1); + *issuer = X509_NAME_oneline(name, 0, 0); + if (*issuer == NULL) + return (-1); + return (0); +} + +static int +tls_get_peer_cert_subject(struct tls *ctx, char **subject) +{ + X509_NAME *name = NULL; + + *subject = NULL; + if (ctx->ssl_peer_cert == NULL) + return (-1); + if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) + return (-1); + *subject = X509_NAME_oneline(name, 0, 0); + if (*subject == NULL) + return (-1); + return (0); +} + +static int +tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, + time_t *notafter) +{ + struct tm before_tm, after_tm; + ASN1_TIME *before, *after; + + if (ctx->ssl_peer_cert == NULL) + return (-1); + + if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL) + goto err; + if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL) + goto err; + if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1) + goto err; + if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1) + goto err; + if (!ASN1_time_tm_clamp_notafter(&after_tm)) + goto err; + if ((*notbefore = timegm(&before_tm)) == -1) + goto err; + if ((*notafter = timegm(&after_tm)) == -1) + goto err; + + return (0); + + err: + return (-1); +} + +static int +tls_get_peer_cert_info(struct tls *ctx) +{ + if (ctx->ssl_peer_cert == NULL) + return (0); + + if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) + goto err; + if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1) + goto err; + if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) + goto err; + if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, + &ctx->conninfo->notafter) == -1) + goto err; + + return (0); + + err: + return (-1); +} + +static int +tls_conninfo_alpn_proto(struct tls *ctx) +{ + const unsigned char *p; + unsigned int len; + + free(ctx->conninfo->alpn); + ctx->conninfo->alpn = NULL; + + SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); + if (len > 0) { + if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) + return (-1); + memcpy(ctx->conninfo->alpn, p, len); + ctx->conninfo->alpn[len] = '\0'; + } + + return (0); +} + +static int +tls_conninfo_cert_pem(struct tls *ctx) +{ + int i, rv = -1; + BIO *membio = NULL; + BUF_MEM *bptr = NULL; + + if (ctx->ssl_peer_cert == NULL) + return 0; + if ((membio = BIO_new(BIO_s_mem()))== NULL) + goto err; + + /* + * We have to write the peer cert out separately, because + * the certificate chain may or may not contain it. + */ + if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) + goto err; + for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { + X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); + if (chaincert != ctx->ssl_peer_cert && + !PEM_write_bio_X509(membio, chaincert)) + goto err; + } + + BIO_get_mem_ptr(membio, &bptr); + free(ctx->conninfo->peer_cert); + ctx->conninfo->peer_cert_len = 0; + if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) + goto err; + ctx->conninfo->peer_cert_len = bptr->length; + memcpy(ctx->conninfo->peer_cert, bptr->data, + ctx->conninfo->peer_cert_len); + + /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ + rv = 0; + err: + BIO_free(membio); + return rv; +} + +static int +tls_conninfo_session(struct tls *ctx) +{ + ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn); + + return 0; +} + +int +tls_conninfo_populate(struct tls *ctx) +{ + const char *tmp; + + tls_conninfo_free(ctx->conninfo); + + if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { + tls_set_errorx(ctx, "out of memory"); + goto err; + } + + if (tls_conninfo_alpn_proto(ctx) == -1) + goto err; + + if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL) + goto err; + if ((ctx->conninfo->cipher = strdup(tmp)) == NULL) + goto err; + ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL); + + if (ctx->servername != NULL) { + if ((ctx->conninfo->servername = + strdup(ctx->servername)) == NULL) + goto err; + } + + if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL) + goto err; + if ((ctx->conninfo->version = strdup(tmp)) == NULL) + goto err; + + if (tls_get_peer_cert_info(ctx) == -1) + goto err; + + if (tls_conninfo_cert_pem(ctx) == -1) + goto err; + + if (tls_conninfo_session(ctx) == -1) + goto err; + + return (0); + + err: + tls_conninfo_free(ctx->conninfo); + ctx->conninfo = NULL; + + return (-1); +} + +void +tls_conninfo_free(struct tls_conninfo *conninfo) +{ + if (conninfo == NULL) + return; + + free(conninfo->alpn); + free(conninfo->cipher); + free(conninfo->servername); + free(conninfo->version); + + free(conninfo->hash); + free(conninfo->issuer); + free(conninfo->subject); + + free(conninfo->peer_cert); + + free(conninfo); +} + +const char * +tls_conn_alpn_selected(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->alpn); +} + +const char * +tls_conn_cipher(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->cipher); +} + +int +tls_conn_cipher_strength(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (0); + return (ctx->conninfo->cipher_strength); +} + +const char * +tls_conn_servername(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->servername); +} + +int +tls_conn_session_resumed(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (0); + return (ctx->conninfo->session_resumed); +} + +const char * +tls_conn_version(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->version); +} diff --git a/tls/tls_internal.h b/tls/tls_internal.h new file mode 100644 index 0000000..5cac881 --- /dev/null +++ b/tls/tls_internal.h @@ -0,0 +1,326 @@ +/* $OpenBSD: tls_internal.h,v 1.83 2023/06/27 18:19:59 tb Exp $ */ +/* + * Copyright (c) 2014 Jeremie Courreges-Anglas + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HEADER_TLS_INTERNAL_H +#define HEADER_TLS_INTERNAL_H + +#include + +#include +#include + +#include + +__BEGIN_HIDDEN_DECLS + +#ifndef TLS_DEFAULT_CA_FILE +#define TLS_DEFAULT_CA_FILE "/etc/ssl/cert.pem" +#endif + +#define TLS_CIPHERS_DEFAULT "TLSv1.3:TLSv1.2+AEAD+ECDHE:TLSv1.2+AEAD+DHE" +#define TLS_CIPHERS_COMPAT "HIGH:!aNULL" +#define TLS_CIPHERS_LEGACY "HIGH:MEDIUM:!aNULL" +#define TLS_CIPHERS_ALL "ALL:!aNULL:!eNULL" + +#define TLS_ECDHE_CURVES "X25519,P-256,P-384" + +union tls_addr { + struct in_addr ip4; + struct in6_addr ip6; +}; + +struct tls_error { + char *msg; + int num; + int tls; +}; + +struct tls_keypair { + struct tls_keypair *next; + + char *cert_mem; + size_t cert_len; + char *key_mem; + size_t key_len; + char *ocsp_staple; + size_t ocsp_staple_len; + char *pubkey_hash; +}; + +#define TLS_MIN_SESSION_TIMEOUT (4) +#define TLS_MAX_SESSION_TIMEOUT (24 * 60 * 60) + +#define TLS_NUM_TICKETS 4 +#define TLS_TICKET_NAME_SIZE 16 +#define TLS_TICKET_AES_SIZE 32 +#define TLS_TICKET_HMAC_SIZE 16 + +struct tls_ticket_key { + /* The key_name must be 16 bytes according to -lssl */ + unsigned char key_name[TLS_TICKET_NAME_SIZE]; + unsigned char aes_key[TLS_TICKET_AES_SIZE]; + unsigned char hmac_key[TLS_TICKET_HMAC_SIZE]; + time_t time; +}; + +typedef int (*tls_sign_cb)(void *_cb_arg, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + +struct tls_config { + struct tls_error error; + + pthread_mutex_t mutex; + int refcount; + + char *alpn; + size_t alpn_len; + const char *ca_path; + char *ca_mem; + size_t ca_len; + const char *ciphers; + int ciphers_server; + char *crl_mem; + size_t crl_len; + int dheparams; + int *ecdhecurves; + size_t ecdhecurves_len; + struct tls_keypair *keypair; + int ocsp_require_stapling; + uint32_t protocols; + unsigned char session_id[TLS_MAX_SESSION_ID_LENGTH]; + int session_fd; + int session_lifetime; + struct tls_ticket_key ticket_keys[TLS_NUM_TICKETS]; + uint32_t ticket_keyrev; + int ticket_autorekey; + int verify_cert; + int verify_client; + int verify_depth; + int verify_name; + int verify_time; + int skip_private_key_check; + int use_fake_private_key; + tls_sign_cb sign_cb; + void *sign_cb_arg; +}; + +struct tls_conninfo { + char *alpn; + char *cipher; + int cipher_strength; + char *servername; + int session_resumed; + char *version; + + char *hash; + char *issuer; + char *subject; + + uint8_t *peer_cert; + size_t peer_cert_len; + + time_t notbefore; + time_t notafter; +}; + +#define TLS_CLIENT (1 << 0) +#define TLS_SERVER (1 << 1) +#define TLS_SERVER_CONN (1 << 2) + +#define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0) +#define TLS_CONNECTED (1 << 1) +#define TLS_HANDSHAKE_COMPLETE (1 << 2) +#define TLS_SSL_NEEDS_SHUTDOWN (1 << 3) + +struct tls_ocsp_result { + const char *result_msg; + int response_status; + int cert_status; + int crl_reason; + time_t this_update; + time_t next_update; + time_t revocation_time; +}; + +struct tls_ocsp { + /* responder location */ + char *ocsp_url; + + /* cert data, this struct does not own these */ + X509 *main_cert; + STACK_OF(X509) *extra_certs; + + struct tls_ocsp_result *ocsp_result; +}; + +struct tls_sni_ctx { + struct tls_sni_ctx *next; + + struct tls_keypair *keypair; + + SSL_CTX *ssl_ctx; + X509 *ssl_cert; +}; + +struct tls { + struct tls_config *config; + struct tls_keypair *keypair; + + struct tls_error error; + + uint32_t flags; + uint32_t state; + + char *servername; + int socket; + + SSL *ssl_conn; + SSL_CTX *ssl_ctx; + + struct tls_sni_ctx *sni_ctx; + + X509 *ssl_peer_cert; + STACK_OF(X509) *ssl_peer_chain; + + struct tls_conninfo *conninfo; + + struct tls_ocsp *ocsp; + + tls_read_cb read_cb; + tls_write_cb write_cb; + void *cb_arg; +}; + +int tls_set_mem(char **_dest, size_t *_destlen, const void *_src, + size_t _srclen); +int tls_set_string(const char **_dest, const char *_src); + +struct tls_keypair *tls_keypair_new(void); +void tls_keypair_clear_key(struct tls_keypair *_keypair); +void tls_keypair_free(struct tls_keypair *_keypair); +int tls_keypair_set_cert_file(struct tls_keypair *_keypair, + struct tls_error *_error, const char *_cert_file); +int tls_keypair_set_cert_mem(struct tls_keypair *_keypair, + struct tls_error *_error, const uint8_t *_cert, size_t _len); +int tls_keypair_set_key_file(struct tls_keypair *_keypair, + struct tls_error *_error, const char *_key_file); +int tls_keypair_set_key_mem(struct tls_keypair *_keypair, + struct tls_error *_error, const uint8_t *_key, size_t _len); +int tls_keypair_set_ocsp_staple_file(struct tls_keypair *_keypair, + struct tls_error *_error, const char *_ocsp_file); +int tls_keypair_set_ocsp_staple_mem(struct tls_keypair *_keypair, + struct tls_error *_error, const uint8_t *_staple, size_t _len); +int tls_keypair_load_cert(struct tls_keypair *_keypair, + struct tls_error *_error, X509 **_cert); + +struct tls_sni_ctx *tls_sni_ctx_new(void); +void tls_sni_ctx_free(struct tls_sni_ctx *sni_ctx); + +struct tls_config *tls_config_new_internal(void); + +struct tls *tls_new(void); +struct tls *tls_server_conn(struct tls *ctx); + +int tls_check_name(struct tls *ctx, X509 *cert, const char *servername, + int *match); +int tls_configure_server(struct tls *ctx); + +int tls_configure_ssl(struct tls *ctx, SSL_CTX *ssl_ctx); +int tls_configure_ssl_keypair(struct tls *ctx, SSL_CTX *ssl_ctx, + struct tls_keypair *keypair, int required); +int tls_configure_ssl_verify(struct tls *ctx, SSL_CTX *ssl_ctx, int verify); + +int tls_handshake_client(struct tls *ctx); +int tls_handshake_server(struct tls *ctx); + +int tls_config_load_file(struct tls_error *error, const char *filetype, + const char *filename, char **buf, size_t *len); +int tls_config_ticket_autorekey(struct tls_config *config); +int tls_host_port(const char *hostport, char **host, char **port); + +int tls_set_cbs(struct tls *ctx, + tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg); + +void tls_error_clear(struct tls_error *error); +int tls_error_set(struct tls_error *error, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_error_setx(struct tls_error *error, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_config_set_error(struct tls_config *cfg, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_config_set_errorx(struct tls_config *cfg, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_set_error(struct tls *ctx, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_set_errorx(struct tls *ctx, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +int tls_set_ssl_errorx(struct tls *ctx, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); + +int tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, + const char *prefix); + +int tls_conninfo_populate(struct tls *ctx); +void tls_conninfo_free(struct tls_conninfo *conninfo); + +int tls_ocsp_verify_cb(SSL *ssl, void *arg); +int tls_ocsp_stapling_cb(SSL *ssl, void *arg); +void tls_ocsp_free(struct tls_ocsp *ctx); +struct tls_ocsp *tls_ocsp_setup_from_peer(struct tls *ctx); +int tls_hex_string(const unsigned char *_in, size_t _inlen, char **_out, + size_t *_outlen); +int tls_cert_hash(X509 *_cert, char **_hash); +int tls_cert_pubkey_hash(X509 *_cert, char **_hash); + +int tls_password_cb(char *_buf, int _size, int _rwflag, void *_u); + +RSA_METHOD *tls_signer_rsa_method(void); +EC_KEY_METHOD *tls_signer_ecdsa_method(void); + +#define TLS_PADDING_NONE 0 +#define TLS_PADDING_RSA_PKCS1 1 + +int tls_config_set_sign_cb(struct tls_config *_config, tls_sign_cb _cb, + void *_cb_arg); + +struct tls_signer* tls_signer_new(void); +void tls_signer_free(struct tls_signer * _signer); +const char *tls_signer_error(struct tls_signer * _signer); +int tls_signer_add_keypair_file(struct tls_signer *_signer, + const char *_cert_file, const char *_key_file); +int tls_signer_add_keypair_mem(struct tls_signer *_signer, const uint8_t *_cert, + size_t _cert_len, const uint8_t *_key, size_t _key_len); +int tls_signer_sign(struct tls_signer *_signer, const char *_pubkey_hash, + const uint8_t *_input, size_t _input_len, int _padding_type, + uint8_t **_out_signature, size_t *_out_signature_len); + +__END_HIDDEN_DECLS + +/* XXX this function is not fully hidden so relayd can use it */ +void tls_config_skip_private_key_check(struct tls_config *config); +void tls_config_use_fake_private_key(struct tls_config *config); + +#endif /* HEADER_TLS_INTERNAL_H */ diff --git a/tls/tls_keypair.c b/tls/tls_keypair.c new file mode 100644 index 0000000..a12d21d --- /dev/null +++ b/tls/tls_keypair.c @@ -0,0 +1,169 @@ +/* $OpenBSD: tls_keypair.c,v 1.8 2021/01/05 17:37:12 jsing Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#include "tls_internal.h" + +struct tls_keypair * +tls_keypair_new(void) +{ + return calloc(1, sizeof(struct tls_keypair)); +} + +static int +tls_keypair_pubkey_hash(struct tls_keypair *keypair, struct tls_error *error) +{ + X509 *cert = NULL; + int rv = -1; + + free(keypair->pubkey_hash); + keypair->pubkey_hash = NULL; + + if (keypair->cert_mem == NULL) { + rv = 0; + goto done; + } + + if (tls_keypair_load_cert(keypair, error, &cert) == -1) + goto err; + if (tls_cert_pubkey_hash(cert, &keypair->pubkey_hash) == -1) + goto err; + + rv = 0; + + err: + X509_free(cert); + done: + return (rv); +} + +void +tls_keypair_clear_key(struct tls_keypair *keypair) +{ + freezero(keypair->key_mem, keypair->key_len); + keypair->key_mem = NULL; + keypair->key_len = 0; +} + +int +tls_keypair_set_cert_file(struct tls_keypair *keypair, struct tls_error *error, + const char *cert_file) +{ + if (tls_config_load_file(error, "certificate", cert_file, + &keypair->cert_mem, &keypair->cert_len) == -1) + return -1; + return tls_keypair_pubkey_hash(keypair, error); +} + +int +tls_keypair_set_cert_mem(struct tls_keypair *keypair, struct tls_error *error, + const uint8_t *cert, size_t len) +{ + if (tls_set_mem(&keypair->cert_mem, &keypair->cert_len, cert, len) == -1) + return -1; + return tls_keypair_pubkey_hash(keypair, error); +} + +int +tls_keypair_set_key_file(struct tls_keypair *keypair, struct tls_error *error, + const char *key_file) +{ + tls_keypair_clear_key(keypair); + return tls_config_load_file(error, "key", key_file, + &keypair->key_mem, &keypair->key_len); +} + +int +tls_keypair_set_key_mem(struct tls_keypair *keypair, struct tls_error *error, + const uint8_t *key, size_t len) +{ + tls_keypair_clear_key(keypair); + return tls_set_mem(&keypair->key_mem, &keypair->key_len, key, len); +} + +int +tls_keypair_set_ocsp_staple_file(struct tls_keypair *keypair, + struct tls_error *error, const char *ocsp_file) +{ + return tls_config_load_file(error, "ocsp", ocsp_file, + &keypair->ocsp_staple, &keypair->ocsp_staple_len); +} + +int +tls_keypair_set_ocsp_staple_mem(struct tls_keypair *keypair, + struct tls_error *error, const uint8_t *staple, size_t len) +{ + return tls_set_mem(&keypair->ocsp_staple, &keypair->ocsp_staple_len, + staple, len); +} + +void +tls_keypair_free(struct tls_keypair *keypair) +{ + if (keypair == NULL) + return; + + tls_keypair_clear_key(keypair); + + free(keypair->cert_mem); + free(keypair->ocsp_staple); + free(keypair->pubkey_hash); + + free(keypair); +} + +int +tls_keypair_load_cert(struct tls_keypair *keypair, struct tls_error *error, + X509 **cert) +{ + char *errstr = "unknown"; + BIO *cert_bio = NULL; + unsigned long ssl_err; + int rv = -1; + + X509_free(*cert); + *cert = NULL; + + if (keypair->cert_mem == NULL) { + tls_error_set(error, "keypair has no certificate"); + goto err; + } + if ((cert_bio = BIO_new_mem_buf(keypair->cert_mem, + keypair->cert_len)) == NULL) { + tls_error_set(error, "failed to create certificate bio"); + goto err; + } + if ((*cert = PEM_read_bio_X509(cert_bio, NULL, tls_password_cb, + NULL)) == NULL) { + if ((ssl_err = ERR_peek_error()) != 0) + errstr = ERR_error_string(ssl_err, NULL); + tls_error_set(error, "failed to load certificate: %s", errstr); + goto err; + } + + rv = 0; + + err: + BIO_free(cert_bio); + + return (rv); +} diff --git a/tls/tls_ocsp.c b/tls/tls_ocsp.c new file mode 100644 index 0000000..acf6935 --- /dev/null +++ b/tls/tls_ocsp.c @@ -0,0 +1,463 @@ +/* $OpenBSD: tls_ocsp.c,v 1.23 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2015 Marko Kreen + * Copyright (c) 2016 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include "tls_internal.h" + +#define MAXAGE_SEC (14*24*60*60) +#define JITTER_SEC (60) + +/* + * State for request. + */ + +static struct tls_ocsp * +tls_ocsp_new(void) +{ + return (calloc(1, sizeof(struct tls_ocsp))); +} + +void +tls_ocsp_free(struct tls_ocsp *ocsp) +{ + if (ocsp == NULL) + return; + + X509_free(ocsp->main_cert); + free(ocsp->ocsp_result); + free(ocsp->ocsp_url); + + free(ocsp); +} + +static int +tls_ocsp_asn1_parse_time(struct tls *ctx, ASN1_GENERALIZEDTIME *gt, time_t *gt_time) +{ + struct tm tm; + + if (gt == NULL) + return -1; + /* RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME */ + if (ASN1_time_parse(gt->data, gt->length, &tm, + V_ASN1_GENERALIZEDTIME) == -1) + return -1; + if ((*gt_time = timegm(&tm)) == -1) + return -1; + return 0; +} + +static int +tls_ocsp_fill_info(struct tls *ctx, int response_status, int cert_status, + int crl_reason, ASN1_GENERALIZEDTIME *revtime, + ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd) +{ + struct tls_ocsp_result *info = NULL; + + free(ctx->ocsp->ocsp_result); + ctx->ocsp->ocsp_result = NULL; + + if ((info = calloc(1, sizeof (struct tls_ocsp_result))) == NULL) { + tls_set_error(ctx, "calloc"); + return -1; + } + info->response_status = response_status; + info->cert_status = cert_status; + info->crl_reason = crl_reason; + if (info->response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + info->result_msg = + OCSP_response_status_str(info->response_status); + } else if (info->cert_status != V_OCSP_CERTSTATUS_REVOKED) { + info->result_msg = OCSP_cert_status_str(info->cert_status); + } else { + info->result_msg = OCSP_crl_reason_str(info->crl_reason); + } + info->revocation_time = info->this_update = info->next_update = -1; + if (revtime != NULL && + tls_ocsp_asn1_parse_time(ctx, revtime, &info->revocation_time) != 0) { + tls_set_error(ctx, + "unable to parse revocation time in OCSP reply"); + goto err; + } + if (thisupd != NULL && + tls_ocsp_asn1_parse_time(ctx, thisupd, &info->this_update) != 0) { + tls_set_error(ctx, + "unable to parse this update time in OCSP reply"); + goto err; + } + if (nextupd != NULL && + tls_ocsp_asn1_parse_time(ctx, nextupd, &info->next_update) != 0) { + tls_set_error(ctx, + "unable to parse next update time in OCSP reply"); + goto err; + } + ctx->ocsp->ocsp_result = info; + return 0; + + err: + free(info); + return -1; +} + +static OCSP_CERTID * +tls_ocsp_get_certid(X509 *main_cert, STACK_OF(X509) *extra_certs, + SSL_CTX *ssl_ctx) +{ + X509_NAME *issuer_name; + X509 *issuer; + X509_STORE_CTX *storectx = NULL; + X509_OBJECT *obj = NULL; + OCSP_CERTID *cid = NULL; + X509_STORE *store; + + if ((issuer_name = X509_get_issuer_name(main_cert)) == NULL) + goto out; + + if (extra_certs != NULL) { + issuer = X509_find_by_subject(extra_certs, issuer_name); + if (issuer != NULL) { + cid = OCSP_cert_to_id(NULL, main_cert, issuer); + goto out; + } + } + + if ((store = SSL_CTX_get_cert_store(ssl_ctx)) == NULL) + goto out; + if ((storectx = X509_STORE_CTX_new()) == NULL) + goto out; + if (X509_STORE_CTX_init(storectx, store, main_cert, extra_certs) != 1) + goto out; + if ((obj = X509_STORE_CTX_get_obj_by_subject(storectx, X509_LU_X509, + issuer_name)) == NULL) + goto out; + + cid = OCSP_cert_to_id(NULL, main_cert, X509_OBJECT_get0_X509(obj)); + + out: + X509_STORE_CTX_free(storectx); + X509_OBJECT_free(obj); + + return cid; +} + +struct tls_ocsp * +tls_ocsp_setup_from_peer(struct tls *ctx) +{ + struct tls_ocsp *ocsp = NULL; + STACK_OF(OPENSSL_STRING) *ocsp_urls = NULL; + + if ((ocsp = tls_ocsp_new()) == NULL) + goto err; + + /* steal state from ctx struct */ + ocsp->main_cert = SSL_get_peer_certificate(ctx->ssl_conn); + ocsp->extra_certs = SSL_get_peer_cert_chain(ctx->ssl_conn); + if (ocsp->main_cert == NULL) { + tls_set_errorx(ctx, "no peer certificate for OCSP"); + goto err; + } + + ocsp_urls = X509_get1_ocsp(ocsp->main_cert); + if (ocsp_urls == NULL) { + tls_set_errorx(ctx, "no OCSP URLs in peer certificate"); + goto err; + } + + ocsp->ocsp_url = strdup(sk_OPENSSL_STRING_value(ocsp_urls, 0)); + if (ocsp->ocsp_url == NULL) { + tls_set_errorx(ctx, "out of memory"); + goto err; + } + + X509_email_free(ocsp_urls); + return ocsp; + + err: + tls_ocsp_free(ocsp); + X509_email_free(ocsp_urls); + return NULL; +} + +static int +tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp) +{ + OCSP_BASICRESP *br = NULL; + ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL; + OCSP_CERTID *cid = NULL; + STACK_OF(X509) *combined = NULL; + int response_status=0, cert_status=0, crl_reason=0; + int ret = -1; + unsigned long flags; + + if ((br = OCSP_response_get1_basic(resp)) == NULL) { + tls_set_errorx(ctx, "cannot load ocsp reply"); + goto err; + } + + /* + * Skip validation of 'extra_certs' as this should be done + * already as part of main handshake. + */ + flags = OCSP_TRUSTOTHER; + + /* now verify */ + if (OCSP_basic_verify(br, ctx->ocsp->extra_certs, + SSL_CTX_get_cert_store(ctx->ssl_ctx), flags) != 1) { + tls_set_errorx(ctx, "ocsp verify failed"); + goto err; + } + + /* signature OK, look inside */ + response_status = OCSP_response_status(resp); + if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { + tls_set_errorx(ctx, "ocsp verify failed: response - %s", + OCSP_response_status_str(response_status)); + goto err; + } + + cid = tls_ocsp_get_certid(ctx->ocsp->main_cert, + ctx->ocsp->extra_certs, ctx->ssl_ctx); + if (cid == NULL) { + tls_set_errorx(ctx, "ocsp verify failed: no issuer cert"); + goto err; + } + + if (OCSP_resp_find_status(br, cid, &cert_status, &crl_reason, + &revtime, &thisupd, &nextupd) != 1) { + tls_set_errorx(ctx, "ocsp verify failed: no result for cert"); + goto err; + } + + if (OCSP_check_validity(thisupd, nextupd, JITTER_SEC, + MAXAGE_SEC) != 1) { + tls_set_errorx(ctx, + "ocsp verify failed: ocsp response not current"); + goto err; + } + + if (tls_ocsp_fill_info(ctx, response_status, cert_status, + crl_reason, revtime, thisupd, nextupd) != 0) + goto err; + + /* finally can look at status */ + if (cert_status != V_OCSP_CERTSTATUS_GOOD && cert_status != + V_OCSP_CERTSTATUS_UNKNOWN) { + tls_set_errorx(ctx, "ocsp verify failed: revoked cert - %s", + OCSP_crl_reason_str(crl_reason)); + goto err; + } + ret = 0; + + err: + sk_X509_free(combined); + OCSP_CERTID_free(cid); + OCSP_BASICRESP_free(br); + return ret; +} + +/* + * Process a raw OCSP response from an OCSP server request. + * OCSP details can then be retrieved with tls_peer_ocsp_* functions. + * returns 0 if certificate ok, -1 otherwise. + */ +static int +tls_ocsp_process_response_internal(struct tls *ctx, const unsigned char *response, + size_t size) +{ + int ret; + OCSP_RESPONSE *resp; + + resp = d2i_OCSP_RESPONSE(NULL, &response, size); + if (resp == NULL) { + tls_ocsp_free(ctx->ocsp); + ctx->ocsp = NULL; + tls_set_error(ctx, "unable to parse OCSP response"); + return -1; + } + ret = tls_ocsp_verify_response(ctx, resp); + OCSP_RESPONSE_free(resp); + return ret; +} + +/* TLS handshake verification callback for stapled requests */ +int +tls_ocsp_verify_cb(SSL *ssl, void *arg) +{ + const unsigned char *raw = NULL; + int size, res = -1; + struct tls *ctx; + + if ((ctx = SSL_get_app_data(ssl)) == NULL) + return -1; + + size = SSL_get_tlsext_status_ocsp_resp(ssl, &raw); + if (size <= 0) { + if (ctx->config->ocsp_require_stapling) { + tls_set_errorx(ctx, "no stapled OCSP response provided"); + return 0; + } + return 1; + } + + tls_ocsp_free(ctx->ocsp); + if ((ctx->ocsp = tls_ocsp_setup_from_peer(ctx)) == NULL) + return 0; + + if (ctx->config->verify_cert == 0 || ctx->config->verify_time == 0) + return 1; + + res = tls_ocsp_process_response_internal(ctx, raw, size); + + return (res == 0) ? 1 : 0; +} + + +/* Staple the OCSP information in ctx->ocsp to the server handshake. */ +int +tls_ocsp_stapling_cb(SSL *ssl, void *arg) +{ + int ret = SSL_TLSEXT_ERR_ALERT_FATAL; + unsigned char *ocsp_staple = NULL; + struct tls *ctx; + + if ((ctx = SSL_get_app_data(ssl)) == NULL) + goto err; + + if (ctx->keypair == NULL || ctx->keypair->ocsp_staple == NULL || + ctx->keypair->ocsp_staple_len == 0) + return SSL_TLSEXT_ERR_NOACK; + + if ((ocsp_staple = malloc(ctx->keypair->ocsp_staple_len)) == NULL) + goto err; + + memcpy(ocsp_staple, ctx->keypair->ocsp_staple, + ctx->keypair->ocsp_staple_len); + + if (SSL_set_tlsext_status_ocsp_resp(ctx->ssl_conn, ocsp_staple, + ctx->keypair->ocsp_staple_len) != 1) + goto err; + + ret = SSL_TLSEXT_ERR_OK; + err: + if (ret != SSL_TLSEXT_ERR_OK) + free(ocsp_staple); + + return ret; +} + +/* + * Public API + */ + +/* Retrieve OCSP URL from peer certificate, if present. */ +const char * +tls_peer_ocsp_url(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return NULL; + return ctx->ocsp->ocsp_url; +} + +const char * +tls_peer_ocsp_result(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return NULL; + if (ctx->ocsp->ocsp_result == NULL) + return NULL; + return ctx->ocsp->ocsp_result->result_msg; +} + +int +tls_peer_ocsp_response_status(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->response_status; +} + +int +tls_peer_ocsp_cert_status(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->cert_status; +} + +int +tls_peer_ocsp_crl_reason(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->crl_reason; +} + +time_t +tls_peer_ocsp_this_update(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->this_update; +} + +time_t +tls_peer_ocsp_next_update(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->next_update; +} + +time_t +tls_peer_ocsp_revocation_time(struct tls *ctx) +{ + if (ctx->ocsp == NULL) + return -1; + if (ctx->ocsp->ocsp_result == NULL) + return -1; + return ctx->ocsp->ocsp_result->revocation_time; +} + +int +tls_ocsp_process_response(struct tls *ctx, const unsigned char *response, + size_t size) +{ + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) == 0) + return -1; + return tls_ocsp_process_response_internal(ctx, response, size); +} diff --git a/tls/tls_peer.c b/tls/tls_peer.c new file mode 100644 index 0000000..ec97a30 --- /dev/null +++ b/tls/tls_peer.c @@ -0,0 +1,99 @@ +/* $OpenBSD: tls_peer.c,v 1.8 2017/04/10 17:11:13 jsing Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * Copyright (c) 2015 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#include "tls_internal.h" + +const char * +tls_peer_cert_hash(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->hash); +} +const char * +tls_peer_cert_issuer(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->issuer); +} + +const char * +tls_peer_cert_subject(struct tls *ctx) +{ + if (ctx->conninfo == NULL) + return (NULL); + return (ctx->conninfo->subject); +} + +int +tls_peer_cert_provided(struct tls *ctx) +{ + return (ctx->ssl_peer_cert != NULL); +} + +int +tls_peer_cert_contains_name(struct tls *ctx, const char *name) +{ + int match; + + if (ctx->ssl_peer_cert == NULL) + return (0); + + if (tls_check_name(ctx, ctx->ssl_peer_cert, name, &match) == -1) + return (0); + + return (match); +} + +time_t +tls_peer_cert_notbefore(struct tls *ctx) +{ + if (ctx->ssl_peer_cert == NULL) + return (-1); + if (ctx->conninfo == NULL) + return (-1); + return (ctx->conninfo->notbefore); +} + +time_t +tls_peer_cert_notafter(struct tls *ctx) +{ + if (ctx->ssl_peer_cert == NULL) + return (-1); + if (ctx->conninfo == NULL) + return (-1); + return (ctx->conninfo->notafter); +} + +const uint8_t * +tls_peer_cert_chain_pem(struct tls *ctx, size_t *size) +{ + if (ctx->ssl_peer_cert == NULL) + return (NULL); + if (ctx->conninfo == NULL) + return (NULL); + *size = ctx->conninfo->peer_cert_len; + return (ctx->conninfo->peer_cert); +} + diff --git a/tls/tls_server.c b/tls/tls_server.c new file mode 100644 index 0000000..5f93c7a --- /dev/null +++ b/tls/tls_server.c @@ -0,0 +1,468 @@ +/* $OpenBSD: tls_server.c,v 1.49 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include + +#include +#include +#include + +#include +#include "tls_internal.h" + +struct tls * +tls_server(void) +{ + struct tls *ctx; + + if (tls_init() == -1) + return (NULL); + + if ((ctx = tls_new()) == NULL) + return (NULL); + + ctx->flags |= TLS_SERVER; + + return (ctx); +} + +struct tls * +tls_server_conn(struct tls *ctx) +{ + struct tls *conn_ctx; + + if ((conn_ctx = tls_new()) == NULL) + return (NULL); + + conn_ctx->flags |= TLS_SERVER_CONN; + + pthread_mutex_lock(&ctx->config->mutex); + ctx->config->refcount++; + pthread_mutex_unlock(&ctx->config->mutex); + + conn_ctx->config = ctx->config; + conn_ctx->keypair = ctx->config->keypair; + + return (conn_ctx); +} + +static int +tls_server_alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, + const unsigned char *in, unsigned int inlen, void *arg) +{ + struct tls *ctx = arg; + + if (SSL_select_next_proto((unsigned char**)out, outlen, + ctx->config->alpn, ctx->config->alpn_len, in, inlen) == + OPENSSL_NPN_NEGOTIATED) + return (SSL_TLSEXT_ERR_OK); + + return (SSL_TLSEXT_ERR_NOACK); +} + +static int +tls_servername_cb(SSL *ssl, int *al, void *arg) +{ + struct tls *ctx = (struct tls *)arg; + struct tls_sni_ctx *sni_ctx; + union tls_addr addrbuf; + struct tls *conn_ctx; + const char *name; + int match; + + if ((conn_ctx = SSL_get_app_data(ssl)) == NULL) + goto err; + + if ((name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) == + NULL) { + /* + * The servername callback gets called even when there is no + * TLS servername extension provided by the client. Sigh! + */ + return (SSL_TLSEXT_ERR_NOACK); + } + + /* + * Per RFC 6066 section 3: ensure that name is not an IP literal. + * + * While we should treat this as an error, a number of clients + * (Python, Ruby and Safari) are not RFC compliant. To avoid handshake + * failures, pretend that we did not receive the extension. + */ + if (inet_pton(AF_INET, name, &addrbuf) == 1 || + inet_pton(AF_INET6, name, &addrbuf) == 1) + return (SSL_TLSEXT_ERR_NOACK); + + free(conn_ctx->servername); + if ((conn_ctx->servername = strdup(name)) == NULL) + goto err; + + /* Find appropriate SSL context for requested servername. */ + for (sni_ctx = ctx->sni_ctx; sni_ctx != NULL; sni_ctx = sni_ctx->next) { + if (tls_check_name(ctx, sni_ctx->ssl_cert, name, + &match) == -1) + goto err; + if (match) { + conn_ctx->keypair = sni_ctx->keypair; + SSL_set_SSL_CTX(conn_ctx->ssl_conn, sni_ctx->ssl_ctx); + return (SSL_TLSEXT_ERR_OK); + } + } + + /* No match, use the existing context/certificate. */ + return (SSL_TLSEXT_ERR_OK); + + err: + /* + * There is no way to tell libssl that an internal failure occurred. + * The only option we have is to return a fatal alert. + */ + *al = SSL_AD_INTERNAL_ERROR; + return (SSL_TLSEXT_ERR_ALERT_FATAL); +} + +static struct tls_ticket_key * +tls_server_ticket_key(struct tls_config *config, unsigned char *keyname) +{ + struct tls_ticket_key *key = NULL; + time_t now; + int i; + + now = time(NULL); + if (config->ticket_autorekey == 1) { + if (now - 3 * (config->session_lifetime / 4) > + config->ticket_keys[0].time) { + if (tls_config_ticket_autorekey(config) == -1) + return (NULL); + } + } + for (i = 0; i < TLS_NUM_TICKETS; i++) { + struct tls_ticket_key *tk = &config->ticket_keys[i]; + if (now - config->session_lifetime > tk->time) + continue; + if (keyname == NULL || timingsafe_memcmp(keyname, + tk->key_name, sizeof(tk->key_name)) == 0) { + key = tk; + break; + } + } + return (key); +} + +static int +tls_server_ticket_cb(SSL *ssl, unsigned char *keyname, unsigned char *iv, + EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int mode) +{ + struct tls_ticket_key *key; + struct tls *tls_ctx; + + if ((tls_ctx = SSL_get_app_data(ssl)) == NULL) + return (-1); + + if (mode == 1) { + /* create new session */ + key = tls_server_ticket_key(tls_ctx->config, NULL); + if (key == NULL) { + tls_set_errorx(tls_ctx, "no valid ticket key found"); + return (-1); + } + + memcpy(keyname, key->key_name, sizeof(key->key_name)); + arc4random_buf(iv, EVP_MAX_IV_LENGTH); + if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + key->aes_key, iv)) { + tls_set_errorx(tls_ctx, "failed to init encrypt"); + return (-1); + } + if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), + EVP_sha256(), NULL)) { + tls_set_errorx(tls_ctx, "failed to init hmac"); + return (-1); + } + return (0); + } else { + /* get key by name */ + key = tls_server_ticket_key(tls_ctx->config, keyname); + if (key == NULL) + return (0); + + if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, + key->aes_key, iv)) { + tls_set_errorx(tls_ctx, "failed to init decrypt"); + return (-1); + } + if (!HMAC_Init_ex(hctx, key->hmac_key, sizeof(key->hmac_key), + EVP_sha256(), NULL)) { + tls_set_errorx(tls_ctx, "failed to init hmac"); + return (-1); + } + + /* time to renew the ticket? is it the primary key? */ + if (key != &tls_ctx->config->ticket_keys[0]) + return (2); + return (1); + } +} + +static int +tls_configure_server_ssl(struct tls *ctx, SSL_CTX **ssl_ctx, + struct tls_keypair *keypair) +{ + SSL_CTX_free(*ssl_ctx); + + if ((*ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) { + tls_set_errorx(ctx, "ssl context failure"); + goto err; + } + + SSL_CTX_set_options(*ssl_ctx, SSL_OP_NO_CLIENT_RENEGOTIATION); + + if (SSL_CTX_set_tlsext_servername_callback(*ssl_ctx, + tls_servername_cb) != 1) { + tls_set_error(ctx, "failed to set servername callback"); + goto err; + } + if (SSL_CTX_set_tlsext_servername_arg(*ssl_ctx, ctx) != 1) { + tls_set_error(ctx, "failed to set servername callback arg"); + goto err; + } + + if (tls_configure_ssl(ctx, *ssl_ctx) != 0) + goto err; + if (tls_configure_ssl_keypair(ctx, *ssl_ctx, keypair, 1) != 0) + goto err; + if (ctx->config->verify_client != 0) { + int verify = SSL_VERIFY_PEER; + if (ctx->config->verify_client == 1) + verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + if (tls_configure_ssl_verify(ctx, *ssl_ctx, verify) == -1) + goto err; + } + + if (ctx->config->alpn != NULL) + SSL_CTX_set_alpn_select_cb(*ssl_ctx, tls_server_alpn_cb, + ctx); + + if (ctx->config->dheparams == -1) + SSL_CTX_set_dh_auto(*ssl_ctx, 1); + else if (ctx->config->dheparams == 1024) + SSL_CTX_set_dh_auto(*ssl_ctx, 2); + + if (ctx->config->ecdhecurves != NULL) { + SSL_CTX_set_ecdh_auto(*ssl_ctx, 1); + if (SSL_CTX_set1_groups(*ssl_ctx, ctx->config->ecdhecurves, + ctx->config->ecdhecurves_len) != 1) { + tls_set_errorx(ctx, "failed to set ecdhe curves"); + goto err; + } + } + + if (ctx->config->ciphers_server == 1) + SSL_CTX_set_options(*ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + + if (SSL_CTX_set_tlsext_status_cb(*ssl_ctx, tls_ocsp_stapling_cb) != 1) { + tls_set_errorx(ctx, "failed to add OCSP stapling callback"); + goto err; + } + + if (ctx->config->session_lifetime > 0) { + /* set the session lifetime and enable tickets */ + SSL_CTX_set_timeout(*ssl_ctx, ctx->config->session_lifetime); + SSL_CTX_clear_options(*ssl_ctx, SSL_OP_NO_TICKET); + if (!SSL_CTX_set_tlsext_ticket_key_cb(*ssl_ctx, + tls_server_ticket_cb)) { + tls_set_error(ctx, + "failed to set the TLS ticket callback"); + goto err; + } + } + + if (SSL_CTX_set_session_id_context(*ssl_ctx, ctx->config->session_id, + sizeof(ctx->config->session_id)) != 1) { + tls_set_error(ctx, "failed to set session id context"); + goto err; + } + + return (0); + + err: + SSL_CTX_free(*ssl_ctx); + *ssl_ctx = NULL; + + return (-1); +} + +static int +tls_configure_server_sni(struct tls *ctx) +{ + struct tls_sni_ctx **sni_ctx; + struct tls_keypair *kp; + + if (ctx->config->keypair->next == NULL) + return (0); + + /* Set up additional SSL contexts for SNI. */ + sni_ctx = &ctx->sni_ctx; + for (kp = ctx->config->keypair->next; kp != NULL; kp = kp->next) { + if ((*sni_ctx = tls_sni_ctx_new()) == NULL) { + tls_set_errorx(ctx, "out of memory"); + goto err; + } + (*sni_ctx)->keypair = kp; + if (tls_configure_server_ssl(ctx, &(*sni_ctx)->ssl_ctx, kp) == -1) + goto err; + if (tls_keypair_load_cert(kp, &ctx->error, + &(*sni_ctx)->ssl_cert) == -1) + goto err; + sni_ctx = &(*sni_ctx)->next; + } + + return (0); + + err: + return (-1); +} + +int +tls_configure_server(struct tls *ctx) +{ + if (tls_configure_server_ssl(ctx, &ctx->ssl_ctx, + ctx->config->keypair) == -1) + goto err; + if (tls_configure_server_sni(ctx) == -1) + goto err; + + return (0); + + err: + return (-1); +} + +static struct tls * +tls_accept_common(struct tls *ctx) +{ + struct tls *conn_ctx = NULL; + + if ((ctx->flags & TLS_SERVER) == 0) { + tls_set_errorx(ctx, "not a server context"); + goto err; + } + + if ((conn_ctx = tls_server_conn(ctx)) == NULL) { + tls_set_errorx(ctx, "connection context failure"); + goto err; + } + + if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { + tls_set_errorx(ctx, "ssl failure"); + goto err; + } + + if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) { + tls_set_errorx(ctx, "ssl application data failure"); + goto err; + } + + return conn_ctx; + + err: + tls_free(conn_ctx); + + return (NULL); +} + +int +tls_accept_socket(struct tls *ctx, struct tls **cctx, int s) +{ + return (tls_accept_fds(ctx, cctx, s, s)); +} + +int +tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write) +{ + struct tls *conn_ctx; + + if ((conn_ctx = tls_accept_common(ctx)) == NULL) + goto err; + + if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 || + SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) { + tls_set_errorx(ctx, "ssl file descriptor failure"); + goto err; + } + + *cctx = conn_ctx; + + return (0); + err: + tls_free(conn_ctx); + *cctx = NULL; + + return (-1); +} + +int +tls_accept_cbs(struct tls *ctx, struct tls **cctx, + tls_read_cb read_cb, tls_write_cb write_cb, void *cb_arg) +{ + struct tls *conn_ctx; + + if ((conn_ctx = tls_accept_common(ctx)) == NULL) + goto err; + + if (tls_set_cbs(conn_ctx, read_cb, write_cb, cb_arg) != 0) + goto err; + + *cctx = conn_ctx; + + return (0); + err: + tls_free(conn_ctx); + *cctx = NULL; + + return (-1); +} + +int +tls_handshake_server(struct tls *ctx) +{ + int ssl_ret; + int rv = -1; + + if ((ctx->flags & TLS_SERVER_CONN) == 0) { + tls_set_errorx(ctx, "not a server connection context"); + goto err; + } + + ctx->state |= TLS_SSL_NEEDS_SHUTDOWN; + + ERR_clear_error(); + if ((ssl_ret = SSL_accept(ctx->ssl_conn)) != 1) { + rv = tls_ssl_error(ctx, ctx->ssl_conn, ssl_ret, "handshake"); + goto err; + } + + ctx->state |= TLS_HANDSHAKE_COMPLETE; + rv = 0; + + err: + return (rv); +} diff --git a/tls/tls_signer.c b/tls/tls_signer.c new file mode 100644 index 0000000..177c9d0 --- /dev/null +++ b/tls/tls_signer.c @@ -0,0 +1,451 @@ +/* $OpenBSD: tls_signer.c,v 1.9 2023/06/18 19:12:58 tb Exp $ */ +/* + * Copyright (c) 2021 Eric Faurot + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include "tls.h" +#include "tls_internal.h" + +struct tls_signer_key { + char *hash; + RSA *rsa; + EC_KEY *ecdsa; + struct tls_signer_key *next; +}; + +struct tls_signer { + struct tls_error error; + struct tls_signer_key *keys; +}; + +static pthread_mutex_t signer_method_lock = PTHREAD_MUTEX_INITIALIZER; + +struct tls_signer * +tls_signer_new(void) +{ + struct tls_signer *signer; + + if ((signer = calloc(1, sizeof(*signer))) == NULL) + return (NULL); + + return (signer); +} + +void +tls_signer_free(struct tls_signer *signer) +{ + struct tls_signer_key *skey; + + if (signer == NULL) + return; + + tls_error_clear(&signer->error); + + while (signer->keys) { + skey = signer->keys; + signer->keys = skey->next; + RSA_free(skey->rsa); + EC_KEY_free(skey->ecdsa); + free(skey->hash); + free(skey); + } + + free(signer); +} + +const char * +tls_signer_error(struct tls_signer *signer) +{ + return (signer->error.msg); +} + +int +tls_signer_add_keypair_mem(struct tls_signer *signer, const uint8_t *cert, + size_t cert_len, const uint8_t *key, size_t key_len) +{ + struct tls_signer_key *skey = NULL; + char *errstr = "unknown"; + int ssl_err; + EVP_PKEY *pkey = NULL; + X509 *x509 = NULL; + BIO *bio = NULL; + char *hash = NULL; + + /* Compute certificate hash */ + if ((bio = BIO_new_mem_buf(cert, cert_len)) == NULL) { + tls_error_setx(&signer->error, + "failed to create certificate bio"); + goto err; + } + if ((x509 = PEM_read_bio_X509(bio, NULL, tls_password_cb, + NULL)) == NULL) { + if ((ssl_err = ERR_peek_error()) != 0) + errstr = ERR_error_string(ssl_err, NULL); + tls_error_setx(&signer->error, "failed to load certificate: %s", + errstr); + goto err; + } + if (tls_cert_pubkey_hash(x509, &hash) == -1) { + tls_error_setx(&signer->error, + "failed to get certificate hash"); + goto err; + } + + X509_free(x509); + x509 = NULL; + BIO_free(bio); + bio = NULL; + + /* Read private key */ + if ((bio = BIO_new_mem_buf(key, key_len)) == NULL) { + tls_error_setx(&signer->error, "failed to create key bio"); + goto err; + } + if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_password_cb, + NULL)) == NULL) { + tls_error_setx(&signer->error, "failed to read private key"); + goto err; + } + + if ((skey = calloc(1, sizeof(*skey))) == NULL) { + tls_error_set(&signer->error, "failed to create key entry"); + goto err; + } + skey->hash = hash; + if ((skey->rsa = EVP_PKEY_get1_RSA(pkey)) == NULL && + (skey->ecdsa = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { + tls_error_setx(&signer->error, "unknown key type"); + goto err; + } + + skey->next = signer->keys; + signer->keys = skey; + EVP_PKEY_free(pkey); + BIO_free(bio); + + return (0); + + err: + EVP_PKEY_free(pkey); + X509_free(x509); + BIO_free(bio); + free(hash); + free(skey); + + return (-1); +} + +int +tls_signer_add_keypair_file(struct tls_signer *signer, const char *cert_file, + const char *key_file) +{ + char *cert = NULL, *key = NULL; + size_t cert_len, key_len; + int rv = -1; + + if (tls_config_load_file(&signer->error, "certificate", cert_file, + &cert, &cert_len) == -1) + goto err; + + if (tls_config_load_file(&signer->error, "key", key_file, &key, + &key_len) == -1) + goto err; + + rv = tls_signer_add_keypair_mem(signer, cert, cert_len, key, key_len); + + err: + free(cert); + free(key); + + return (rv); +} + +static int +tls_sign_rsa(struct tls_signer *signer, struct tls_signer_key *skey, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + int rsa_padding, rsa_size, signature_len; + char *signature = NULL; + + *out_signature = NULL; + *out_signature_len = 0; + + if (padding_type == TLS_PADDING_NONE) { + rsa_padding = RSA_NO_PADDING; + } else if (padding_type == TLS_PADDING_RSA_PKCS1) { + rsa_padding = RSA_PKCS1_PADDING; + } else { + tls_error_setx(&signer->error, "invalid RSA padding type (%d)", + padding_type); + return (-1); + } + + if (input_len > INT_MAX) { + tls_error_setx(&signer->error, "input too large"); + return (-1); + } + if ((rsa_size = RSA_size(skey->rsa)) <= 0) { + tls_error_setx(&signer->error, "invalid RSA size: %d", + rsa_size); + return (-1); + } + if ((signature = calloc(1, rsa_size)) == NULL) { + tls_error_set(&signer->error, "RSA signature"); + return (-1); + } + + if ((signature_len = RSA_private_encrypt((int)input_len, input, + signature, skey->rsa, rsa_padding)) <= 0) { + /* XXX - include further details from libcrypto. */ + tls_error_setx(&signer->error, "RSA signing failed"); + free(signature); + return (-1); + } + + *out_signature = signature; + *out_signature_len = (size_t)signature_len; + + return (0); +} + +static int +tls_sign_ecdsa(struct tls_signer *signer, struct tls_signer_key *skey, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + unsigned char *signature; + int signature_len; + + *out_signature = NULL; + *out_signature_len = 0; + + if (padding_type != TLS_PADDING_NONE) { + tls_error_setx(&signer->error, "invalid ECDSA padding"); + return (-1); + } + + if (input_len > INT_MAX) { + tls_error_setx(&signer->error, "digest too large"); + return (-1); + } + if ((signature_len = ECDSA_size(skey->ecdsa)) <= 0) { + tls_error_setx(&signer->error, "invalid ECDSA size: %d", + signature_len); + return (-1); + } + if ((signature = calloc(1, signature_len)) == NULL) { + tls_error_set(&signer->error, "ECDSA signature"); + return (-1); + } + + if (!ECDSA_sign(0, input, input_len, signature, &signature_len, + skey->ecdsa)) { + /* XXX - include further details from libcrypto. */ + tls_error_setx(&signer->error, "ECDSA signing failed"); + free(signature); + return (-1); + } + + *out_signature = signature; + *out_signature_len = signature_len; + + return (0); +} + +int +tls_signer_sign(struct tls_signer *signer, const char *pubkey_hash, + const uint8_t *input, size_t input_len, int padding_type, + uint8_t **out_signature, size_t *out_signature_len) +{ + struct tls_signer_key *skey; + + *out_signature = NULL; + *out_signature_len = 0; + + for (skey = signer->keys; skey; skey = skey->next) + if (!strcmp(pubkey_hash, skey->hash)) + break; + + if (skey == NULL) { + tls_error_setx(&signer->error, "key not found"); + return (-1); + } + + if (skey->rsa != NULL) + return tls_sign_rsa(signer, skey, input, input_len, + padding_type, out_signature, out_signature_len); + + if (skey->ecdsa != NULL) + return tls_sign_ecdsa(signer, skey, input, input_len, + padding_type, out_signature, out_signature_len); + + tls_error_setx(&signer->error, "unknown key type"); + + return (-1); +} + +static int +tls_rsa_priv_enc(int from_len, const unsigned char *from, unsigned char *to, + RSA *rsa, int rsa_padding) +{ + struct tls_config *config; + uint8_t *signature = NULL; + size_t signature_len = 0; + const char *pubkey_hash; + int padding_type; + + /* + * This function is called via RSA_private_encrypt() and has to conform + * to its calling convention/signature. The caller is required to + * provide a 'to' buffer of at least RSA_size() bytes. + */ + + pubkey_hash = RSA_get_ex_data(rsa, 0); + config = RSA_get_ex_data(rsa, 1); + + if (pubkey_hash == NULL || config == NULL) + goto err; + + if (rsa_padding == RSA_NO_PADDING) { + padding_type = TLS_PADDING_NONE; + } else if (rsa_padding == RSA_PKCS1_PADDING) { + padding_type = TLS_PADDING_RSA_PKCS1; + } else { + goto err; + } + + if (from_len < 0) + goto err; + + if (config->sign_cb(config->sign_cb_arg, pubkey_hash, from, from_len, + padding_type, &signature, &signature_len) == -1) + goto err; + + if (signature_len > INT_MAX || (int)signature_len > RSA_size(rsa)) + goto err; + + memcpy(to, signature, signature_len); + free(signature); + + return ((int)signature_len); + + err: + free(signature); + + return (-1); +} + +RSA_METHOD * +tls_signer_rsa_method(void) +{ + static RSA_METHOD *rsa_method = NULL; + + pthread_mutex_lock(&signer_method_lock); + + if (rsa_method != NULL) + goto out; + + rsa_method = RSA_meth_new("libtls RSA method", 0); + if (rsa_method == NULL) + goto out; + + RSA_meth_set_priv_enc(rsa_method, tls_rsa_priv_enc); + + out: + pthread_mutex_unlock(&signer_method_lock); + + return (rsa_method); +} + +static ECDSA_SIG * +tls_ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + const BIGNUM *rp, EC_KEY *eckey) +{ + struct tls_config *config; + ECDSA_SIG *ecdsa_sig = NULL; + uint8_t *signature = NULL; + size_t signature_len = 0; + const unsigned char *p; + const char *pubkey_hash; + + /* + * This function is called via ECDSA_do_sign_ex() and has to conform + * to its calling convention/signature. + */ + + pubkey_hash = EC_KEY_get_ex_data(eckey, 0); + config = EC_KEY_get_ex_data(eckey, 1); + + if (pubkey_hash == NULL || config == NULL) + goto err; + + if (dgst_len < 0) + goto err; + + if (config->sign_cb(config->sign_cb_arg, pubkey_hash, dgst, dgst_len, + TLS_PADDING_NONE, &signature, &signature_len) == -1) + goto err; + + p = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &p, signature_len)) == NULL) + goto err; + + free(signature); + + return (ecdsa_sig); + + err: + free(signature); + + return (NULL); +} + +EC_KEY_METHOD * +tls_signer_ecdsa_method(void) +{ + static EC_KEY_METHOD *ecdsa_method = NULL; + const EC_KEY_METHOD *default_method; + int (*sign)(int type, const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey); + int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp); + + pthread_mutex_lock(&signer_method_lock); + + if (ecdsa_method != NULL) + goto out; + + default_method = EC_KEY_get_default_method(); + ecdsa_method = EC_KEY_METHOD_new(default_method); + if (ecdsa_method == NULL) + goto out; + + EC_KEY_METHOD_get_sign(default_method, &sign, &sign_setup, NULL); + EC_KEY_METHOD_set_sign(ecdsa_method, sign, sign_setup, + tls_ecdsa_do_sign); + + out: + pthread_mutex_unlock(&signer_method_lock); + + return (ecdsa_method); +} diff --git a/tls/tls_util.c b/tls/tls_util.c new file mode 100644 index 0000000..b276d2c --- /dev/null +++ b/tls/tls_util.c @@ -0,0 +1,226 @@ +/* $OpenBSD: tls_util.c,v 1.16 2023/05/14 07:26:25 op Exp $ */ +/* + * Copyright (c) 2014 Joel Sing + * Copyright (c) 2014 Ted Unangst + * Copyright (c) 2015 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include + +#include "tls.h" +#include "tls_internal.h" + +static void * +memdup(const void *in, size_t len) +{ + void *out; + + if ((out = malloc(len)) == NULL) + return NULL; + memcpy(out, in, len); + return out; +} + +int +tls_set_mem(char **dest, size_t *destlen, const void *src, size_t srclen) +{ + free(*dest); + *dest = NULL; + *destlen = 0; + if (src != NULL) { + if ((*dest = memdup(src, srclen)) == NULL) + return -1; + *destlen = srclen; + } + return 0; +} + +int +tls_set_string(const char **dest, const char *src) +{ + free((char *)*dest); + *dest = NULL; + if (src != NULL) + if ((*dest = strdup(src)) == NULL) + return -1; + return 0; +} + +/* + * Extract the host and port from a colon separated value. For a literal IPv6 + * address the address must be contained with square braces. If a host and + * port are successfully extracted, the function will return 0 and the + * caller is responsible for freeing the host and port. If no port is found + * then the function will return 1, with both host and port being NULL. + * On memory allocation failure -1 will be returned. + */ +int +tls_host_port(const char *hostport, char **host, char **port) +{ + char *h, *p, *s; + int rv = 1; + + *host = NULL; + *port = NULL; + + if ((s = strdup(hostport)) == NULL) + goto err; + + h = p = s; + + /* See if this is an IPv6 literal with square braces. */ + if (p[0] == '[') { + h++; + if ((p = strchr(s, ']')) == NULL) + goto done; + *p++ = '\0'; + } + + /* Find the port separator. */ + if ((p = strchr(p, ':')) == NULL) + goto done; + + /* If there is another separator then we have issues. */ + if (strchr(p + 1, ':') != NULL) + goto done; + + *p++ = '\0'; + + if (asprintf(host, "%s", h) == -1) { + *host = NULL; + goto err; + } + if (asprintf(port, "%s", p) == -1) { + *port = NULL; + goto err; + } + + rv = 0; + goto done; + + err: + free(*host); + *host = NULL; + free(*port); + *port = NULL; + rv = -1; + + done: + free(s); + + return (rv); +} + +int +tls_password_cb(char *buf, int size, int rwflag, void *u) +{ + size_t len; + + if (size < 0) + return (0); + + if (u == NULL) { + memset(buf, 0, size); + return (0); + } + + if ((len = strlcpy(buf, u, size)) >= (size_t)size) + return (0); + + return (len); +} + +uint8_t * +tls_load_file(const char *name, size_t *len, char *password) +{ + FILE *fp; + EVP_PKEY *key = NULL; + BIO *bio = NULL; + char *data; + uint8_t *buf = NULL; + struct stat st; + size_t size = 0; + int fd = -1; + ssize_t n; + + *len = 0; + + if ((fd = open(name, O_RDONLY)) == -1) + return (NULL); + + /* Just load the file into memory without decryption */ + if (password == NULL) { + if (fstat(fd, &st) != 0) + goto err; + if (st.st_size < 0) + goto err; + size = (size_t)st.st_size; + if ((buf = malloc(size)) == NULL) + goto err; + n = read(fd, buf, size); + if (n < 0 || (size_t)n != size) + goto err; + close(fd); + goto done; + } + + /* Or read the (possibly) encrypted key from file */ + if ((fp = fdopen(fd, "r")) == NULL) + goto err; + fd = -1; + + key = PEM_read_PrivateKey(fp, NULL, tls_password_cb, password); + fclose(fp); + if (key == NULL) + goto err; + + /* Write unencrypted key to memory buffer */ + if ((bio = BIO_new(BIO_s_mem())) == NULL) + goto err; + if (!PEM_write_bio_PrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) + goto err; + if ((size = BIO_get_mem_data(bio, &data)) <= 0) + goto err; + if ((buf = malloc(size)) == NULL) + goto err; + memcpy(buf, data, size); + + BIO_free_all(bio); + EVP_PKEY_free(key); + + done: + *len = size; + return (buf); + + err: + if (fd != -1) + close(fd); + freezero(buf, size); + BIO_free_all(bio); + EVP_PKEY_free(key); + + return (NULL); +} + +void +tls_unload_file(uint8_t *buf, size_t len) +{ + freezero(buf, len); +} diff --git a/tls/tls_verify.c b/tls/tls_verify.c new file mode 100644 index 0000000..c588f02 --- /dev/null +++ b/tls/tls_verify.c @@ -0,0 +1,331 @@ +/* $OpenBSD: tls_verify.c,v 1.28 2023/06/01 07:32:25 tb Exp $ */ +/* + * Copyright (c) 2014 Jeremie Courreges-Anglas + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include + +#include + +#include +#include "tls_internal.h" + +static int +tls_match_name(const char *cert_name, const char *name) +{ + const char *cert_domain, *domain, *next_dot; + + if (strcasecmp(cert_name, name) == 0) + return 0; + + /* Wildcard match? */ + if (cert_name[0] == '*') { + /* + * Valid wildcards: + * - "*.domain.tld" + * - "*.sub.domain.tld" + * - etc. + * Reject "*.tld". + * No attempt to prevent the use of eg. "*.co.uk". + */ + cert_domain = &cert_name[1]; + /* Disallow "*" */ + if (cert_domain[0] == '\0') + return -1; + /* Disallow "*foo" */ + if (cert_domain[0] != '.') + return -1; + /* Disallow "*.." */ + if (cert_domain[1] == '.') + return -1; + next_dot = strchr(&cert_domain[1], '.'); + /* Disallow "*.bar" */ + if (next_dot == NULL) + return -1; + /* Disallow "*.bar.." */ + if (next_dot[1] == '.') + return -1; + + domain = strchr(name, '.'); + + /* No wildcard match against a name with no host part. */ + if (name[0] == '.') + return -1; + /* No wildcard match against a name with no domain part. */ + if (domain == NULL || strlen(domain) == 1) + return -1; + + if (strcasecmp(cert_domain, domain) == 0) + return 0; + } + + return -1; +} + +/* + * See RFC 5280 section 4.2.1.6 for SubjectAltName details. + * alt_match is set to 1 if a matching alternate name is found. + * alt_exists is set to 1 if any known alternate name exists in the certificate. + */ +static int +tls_check_subject_altname(struct tls *ctx, X509 *cert, const char *name, + int *alt_match, int *alt_exists) +{ + STACK_OF(GENERAL_NAME) *altname_stack = NULL; + union tls_addr addrbuf; + int addrlen, type; + int count, i; + int critical = 0; + int rv = -1; + + *alt_match = 0; + *alt_exists = 0; + + altname_stack = X509_get_ext_d2i(cert, NID_subject_alt_name, &critical, + NULL); + if (altname_stack == NULL) { + if (critical != -1) { + tls_set_errorx(ctx, "error decoding subjectAltName"); + goto err; + } + goto done; + } + + if (inet_pton(AF_INET, name, &addrbuf) == 1) { + type = GEN_IPADD; + addrlen = 4; + } else if (inet_pton(AF_INET6, name, &addrbuf) == 1) { + type = GEN_IPADD; + addrlen = 16; + } else { + type = GEN_DNS; + addrlen = 0; + } + + count = sk_GENERAL_NAME_num(altname_stack); + for (i = 0; i < count; i++) { + GENERAL_NAME *altname; + + altname = sk_GENERAL_NAME_value(altname_stack, i); + + if (altname->type == GEN_DNS || altname->type == GEN_IPADD) + *alt_exists = 1; + + if (altname->type != type) + continue; + + if (type == GEN_DNS) { + const unsigned char *data; + int format, len; + + format = ASN1_STRING_type(altname->d.dNSName); + if (format == V_ASN1_IA5STRING) { + data = ASN1_STRING_get0_data(altname->d.dNSName); + len = ASN1_STRING_length(altname->d.dNSName); + + if (len < 0 || (size_t)len != strlen(data)) { + tls_set_errorx(ctx, + "error verifying name '%s': " + "NUL byte in subjectAltName, " + "probably a malicious certificate", + name); + goto err; + } + + /* + * Per RFC 5280 section 4.2.1.6: + * " " is a legal domain name, but that + * dNSName must be rejected. + */ + if (strcmp(data, " ") == 0) { + tls_set_errorx(ctx, + "error verifying name '%s': " + "a dNSName of \" \" must not be " + "used", name); + goto err; + } + + if (tls_match_name(data, name) == 0) { + *alt_match = 1; + goto done; + } + } else { +#ifdef DEBUG + fprintf(stdout, "%s: unhandled subjectAltName " + "dNSName encoding (%d)\n", getprogname(), + format); +#endif + } + + } else if (type == GEN_IPADD) { + const unsigned char *data; + int datalen; + + datalen = ASN1_STRING_length(altname->d.iPAddress); + data = ASN1_STRING_get0_data(altname->d.iPAddress); + + if (datalen < 0) { + tls_set_errorx(ctx, + "Unexpected negative length for an " + "IP address: %d", datalen); + goto err; + } + + /* + * Per RFC 5280 section 4.2.1.6: + * IPv4 must use 4 octets and IPv6 must use 16 octets. + */ + if (datalen == addrlen && + memcmp(data, &addrbuf, addrlen) == 0) { + *alt_match = 1; + goto done; + } + } + } + + done: + rv = 0; + + err: + sk_GENERAL_NAME_pop_free(altname_stack, GENERAL_NAME_free); + return rv; +} + +static int +tls_check_common_name(struct tls *ctx, X509 *cert, const char *name, + int *cn_match) +{ + unsigned char *utf8_bytes = NULL; + X509_NAME *subject_name; + char *common_name = NULL; + union tls_addr addrbuf; + int common_name_len; + ASN1_STRING *data; + int lastpos = -1; + int rv = -1; + + *cn_match = 0; + + subject_name = X509_get_subject_name(cert); + if (subject_name == NULL) + goto done; + + lastpos = X509_NAME_get_index_by_NID(subject_name, + NID_commonName, lastpos); + if (lastpos == -1) + goto done; + if (lastpos < 0) + goto err; + if (X509_NAME_get_index_by_NID(subject_name, NID_commonName, lastpos) + != -1) { + /* + * Having multiple CN's is possible, and even happened back in + * the glory days of mullets and Hammer pants. In anything like + * a modern TLS cert, CN is as close to deprecated as it gets, + * and having more than one is bad. We therefore fail if we have + * more than one CN fed to us in the subject, treating the + * certificate as hostile. + */ + tls_set_errorx(ctx, "error verifying name '%s': " + "Certificate subject contains mutiple Common Name fields, " + "probably a malicious or malformed certificate", name); + goto err; + } + + data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject_name, + lastpos)); + /* + * Fail if we cannot encode the CN bytes as UTF-8. + */ + if ((common_name_len = ASN1_STRING_to_UTF8(&utf8_bytes, data)) < 0) { + tls_set_errorx(ctx, "error verifying name '%s': " + "Common Name field cannot be encoded as a UTF-8 string, " + "probably a malicious certificate", name); + goto err; + } + /* + * Fail if the CN is of invalid length. RFC 5280 specifies that a CN + * must be between 1 and 64 bytes long. + */ + if (common_name_len < 1 || common_name_len > 64) { + tls_set_errorx(ctx, "error verifying name '%s': " + "Common Name field has invalid length, " + "probably a malicious certificate", name); + goto err; + } + /* + * Fail if the resulting text contains a NUL byte. + */ + if (memchr(utf8_bytes, 0, common_name_len) != NULL) { + tls_set_errorx(ctx, "error verifying name '%s': " + "NUL byte in Common Name field, " + "probably a malicious certificate", name); + goto err; + } + + common_name = strndup(utf8_bytes, common_name_len); + if (common_name == NULL) { + tls_set_error(ctx, "out of memory"); + goto err; + } + + /* + * We don't want to attempt wildcard matching against IP addresses, + * so perform a simple comparison here. + */ + if (inet_pton(AF_INET, name, &addrbuf) == 1 || + inet_pton(AF_INET6, name, &addrbuf) == 1) { + if (strcmp(common_name, name) == 0) + *cn_match = 1; + goto done; + } + + if (tls_match_name(common_name, name) == 0) + *cn_match = 1; + + done: + rv = 0; + + err: + free(utf8_bytes); + free(common_name); + return rv; +} + +int +tls_check_name(struct tls *ctx, X509 *cert, const char *name, int *match) +{ + int alt_exists; + + *match = 0; + + if (tls_check_subject_altname(ctx, cert, name, match, + &alt_exists) == -1) + return -1; + + /* + * As per RFC 6125 section 6.4.4, if any known alternate name existed + * in the certificate, we do not attempt to match on the CN. + */ + if (*match || alt_exists) + return 0; + + return tls_check_common_name(ctx, cert, name, match); +}